clocktopus 1.1.2 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ import { fileURLToPath } from 'url';
9
9
  import { completeLatestSession, getLatestSession } from './lib/db.js';
10
10
  import { stopJiraTimer } from './lib/jira.js';
11
11
  import { startDashboard } from './dashboard/server.js';
12
+ import { ensureNativeAddons } from './lib/ensure-native-addons.js';
12
13
  const __filename = fileURLToPath(import.meta.url);
13
14
  const __dirname = path.dirname(__filename);
14
15
  const program = new Command();
@@ -290,6 +291,7 @@ program
290
291
  .command('monitor')
291
292
  .description('Start idle monitor as a background daemon.')
292
293
  .action(async () => {
294
+ ensureNativeAddons();
293
295
  const { execSync } = await import('child_process');
294
296
  const bunPath = execSync('which bun', { encoding: 'utf-8' }).trim();
295
297
  const scriptPath = path.join(__dirname, 'index.js');
@@ -0,0 +1,76 @@
1
+ import { execSync } from 'child_process';
2
+ import { createRequire } from 'module';
3
+ import * as path from 'path';
4
+ import * as fs from 'fs';
5
+ const require = createRequire(import.meta.url);
6
+ const NATIVE_MODULES = [
7
+ { name: 'macos-notification-state', addonName: 'notificationstate' },
8
+ { name: 'desktop-idle', addonName: 'desktopIdle' },
9
+ ];
10
+ function hasBuiltAddon(moduleName, addonName) {
11
+ try {
12
+ const modulePath = path.dirname(require.resolve(`${moduleName}/package.json`));
13
+ const nodePath = path.join(modulePath, 'build', 'Release', `${addonName}.node`);
14
+ return fs.existsSync(nodePath);
15
+ }
16
+ catch {
17
+ return false;
18
+ }
19
+ }
20
+ function findNodeGyp() {
21
+ try {
22
+ execSync('node-gyp --version', { stdio: 'ignore' });
23
+ return 'node-gyp';
24
+ }
25
+ catch { }
26
+ try {
27
+ execSync('npx --version', { stdio: 'ignore' });
28
+ return 'npx node-gyp';
29
+ }
30
+ catch { }
31
+ return null;
32
+ }
33
+ function buildModule(moduleName, nodeGypCmd) {
34
+ let modulePath;
35
+ try {
36
+ modulePath = path.dirname(require.resolve(`${moduleName}/package.json`));
37
+ }
38
+ catch {
39
+ return false;
40
+ }
41
+ if (!fs.existsSync(path.join(modulePath, 'binding.gyp')))
42
+ return false;
43
+ try {
44
+ console.log(`Building native addon: ${moduleName}...`);
45
+ execSync(`${nodeGypCmd} rebuild`, { cwd: modulePath, stdio: 'inherit' });
46
+ console.log(`Built ${moduleName} successfully.`);
47
+ return true;
48
+ }
49
+ catch {
50
+ return false;
51
+ }
52
+ }
53
+ export function ensureNativeAddons() {
54
+ if (process.platform !== 'darwin')
55
+ return;
56
+ const missing = NATIVE_MODULES.filter((m) => !hasBuiltAddon(m.name, m.addonName));
57
+ if (missing.length === 0)
58
+ return;
59
+ console.log(`Native addons not built: ${missing.map((m) => m.name).join(', ')}. Attempting to build...`);
60
+ const nodeGypCmd = findNodeGyp();
61
+ if (!nodeGypCmd) {
62
+ console.warn('Warning: node-gyp not found. Native addons could not be built.');
63
+ console.warn(' Install Node.js (includes npx) then restart, or run:');
64
+ console.warn(' bun pm trust clocktopus && bun install -g clocktopus');
65
+ return;
66
+ }
67
+ const failed = [];
68
+ for (const mod of missing) {
69
+ if (!buildModule(mod.name, nodeGypCmd)) {
70
+ failed.push(mod.name);
71
+ }
72
+ }
73
+ if (failed.length > 0) {
74
+ console.warn(`Warning: Failed to build: ${failed.join(', ')}. Monitor features may not work.`);
75
+ }
76
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clocktopus",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {