index.ts 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. import { createRequire } from 'module'
  2. import { fileURLToPath } from 'url'
  3. import { dirname, join } from 'path'
  4. type ModifiersNapi = {
  5. getModifiers(): string[]
  6. isModifierPressed(modifier: string): boolean
  7. }
  8. let cachedModule: ModifiersNapi | null = null
  9. function loadModule(): ModifiersNapi | null {
  10. if (cachedModule) {
  11. return cachedModule
  12. }
  13. // Only works on macOS
  14. if (process.platform !== 'darwin') {
  15. return null
  16. }
  17. try {
  18. if (process.env.MODIFIERS_NODE_PATH) {
  19. // Bundled mode - use the env var path
  20. // eslint-disable-next-line @typescript-eslint/no-require-imports
  21. cachedModule = require(process.env.MODIFIERS_NODE_PATH) as ModifiersNapi
  22. } else {
  23. // Dev mode - load from vendor directory
  24. const modulePath = join(
  25. dirname(fileURLToPath(import.meta.url)),
  26. '..',
  27. 'modifiers-napi',
  28. `${process.arch}-darwin`,
  29. 'modifiers.node',
  30. )
  31. cachedModule = createRequire(import.meta.url)(modulePath) as ModifiersNapi
  32. }
  33. return cachedModule
  34. } catch {
  35. return null
  36. }
  37. }
  38. export function getModifiers(): string[] {
  39. const mod = loadModule()
  40. if (!mod) {
  41. return []
  42. }
  43. return mod.getModifiers()
  44. }
  45. export function isModifierPressed(modifier: string): boolean {
  46. const mod = loadModule()
  47. if (!mod) {
  48. return false
  49. }
  50. return mod.isModifierPressed(modifier)
  51. }
  52. /**
  53. * Pre-warm the native module by loading it in advance.
  54. * Call this early (e.g., at startup) to avoid delay on first use.
  55. */
  56. export function prewarm(): void {
  57. // Just call loadModule to cache it
  58. loadModule()
  59. }