node-systray icon indicating copy to clipboard operation
node-systray copied to clipboard

TypeError: SysTray is not a constructor

Open trymeouteh opened this issue 1 year ago • 1 comments

When I run the simple example from the README I get the following error...

const systray = new SysTray({
                ^

TypeError: SysTray is not a constructor

Node.js v22.12.0

The script

import SysTray from 'systray2';
import os from 'os'

const item = {
  title: 'Show Exit Button',
  tooltip: 'This menu item will toggle the display of the exit button.',
  // The "checked" property will create a check mark on the side of this menu item.
  // To dynamically update the display of the check mark, use the "sendAction" method, as shown below.
  // Note that "checked" is implemented by plain text in linux
  checked: false,
  enabled: true,
}

const itemExit = {
  title: 'Exit',
  tooltip: 'bb',
  checked: false,
  enabled: true,
}

// Simple menu example
const systray = new SysTray({
  menu: {
    // you should use .png icon on macOS/Linux, and .ico format on Windows
    icon: os.platform() === 'win32' ? './logo_s.ico' : './logo_s.png',
    // a template icon is a transparency mask that will appear to be dark in light mode and light in dark mode
    isTemplateIcon: os.platform() === 'darwin',
    title: '标题',
    tooltip: 'Tips',
    items: [
      item,
      itemExit
    ]
  },
  debug: false,
  copyDir: false // copy go tray binary to an outside directory, useful for packing tool like pkg.
})

// The actual handling of the click events.
// This is obviously important if you want your MenuItems to react to mouse clicks.
systray.onClick(action => {
  if (action.item.title === "Exit") {
    systray.kill(false)
  } else {
    console.log("menu item clicked!")
  }
})

// Systray.ready is a promise which resolves when the tray is ready.
systray.ready().then(() => {
  console.log('systray started!')
}).catch(err => {
  console.log('systray failed to start: ' + err.message)
})

My package.json

{
	"type": "module",
	"dependencies": {
		"systray2": "^2.1.4"
	}
}

trymeouteh avatar Feb 26 '25 02:02 trymeouteh

Hey! I ran into the exact same issue with systray2 and Node.js v22.

TL;DR: The constructor is nested deeper than expected due to ESM/CommonJS export wrapping.

Solution:

  import * as SysTray from 'systray2';
  const Constructor = SysTray.default.default; // Yes, double .default!
  const systray = new Constructor({ /* your config */ });

Why: The library exports are wrapped like this:

  • SysTray.default.default = actual constructor function
  • SysTray.default = wrapper object
  • SysTray = ESM wrapper

Tested on Node.js v22 and it works perfectly.

Hope this helps! 🎉

Nouuu avatar Aug 08 '25 13:08 Nouuu