@juliantanx/aiusage-widget 1.3.3 → 1.4.0

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.
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * postinstall: produce a better-sqlite3 native binding that matches BOTH the
4
+ * end user's platform/arch AND Electron's ABI, and place it at
5
+ * dist/native/better_sqlite3.node (where main.ts loads it via `nativeBinding`).
6
+ *
7
+ * Why this exists:
8
+ * - Electron embeds its own Node, so a binding compiled for the system Node
9
+ * ABI fails to load inside Electron, and vice versa.
10
+ * - The published package cannot ship a single prebuilt binary, because that
11
+ * binary is locked to the platform/arch of the machine that built it
12
+ * (the CI runner). On any other OS/arch it is unloadable.
13
+ *
14
+ * Strategy: download the prebuilt better-sqlite3 binary for `electron` runtime
15
+ * matching the locally installed Electron version, this platform, and this
16
+ * arch. We run prebuild-install inside a throwaway copy of better-sqlite3's
17
+ * package.json so we never clobber the shared better-sqlite3 build/Release
18
+ * (the CLI package relies on its Node-ABI binding in a pnpm workspace).
19
+ *
20
+ * Best-effort: a failure here (e.g. offline install, or no prebuilt for an
21
+ * exotic platform) prints a warning but does not fail `npm install`; any
22
+ * binary shipped in dist/native remains as a last-resort fallback.
23
+ */
24
+ const { existsSync, mkdirSync, copyFileSync, readFileSync, writeFileSync, rmSync } = require('node:fs')
25
+ const { dirname, join } = require('node:path')
26
+ const { execFileSync } = require('node:child_process')
27
+ const { tmpdir } = require('node:os')
28
+
29
+ const widgetRoot = join(__dirname, '..')
30
+
31
+ function warn(message) {
32
+ console.warn(`[aiusage-widget] ${message}`)
33
+ console.warn('[aiusage-widget] the tray widget may fail to open the usage database until this is resolved.')
34
+ }
35
+
36
+ function resolveElectronVersion() {
37
+ try {
38
+ return require('electron/package.json').version
39
+ } catch {
40
+ return null
41
+ }
42
+ }
43
+
44
+ function main() {
45
+ const electronVersion = resolveElectronVersion()
46
+ if (!electronVersion) {
47
+ warn('could not resolve the installed electron version; skipping native binding setup.')
48
+ return
49
+ }
50
+
51
+ let betterSqlite3Pkg
52
+ try {
53
+ betterSqlite3Pkg = require.resolve('better-sqlite3/package.json')
54
+ } catch {
55
+ warn('could not locate better-sqlite3; skipping native binding setup.')
56
+ return
57
+ }
58
+ const betterSqlite3Dir = dirname(betterSqlite3Pkg)
59
+
60
+ let prebuildInstallBin
61
+ try {
62
+ prebuildInstallBin = require.resolve('prebuild-install/bin.js', { paths: [betterSqlite3Dir] })
63
+ } catch {
64
+ warn('could not locate prebuild-install; skipping native binding setup.')
65
+ return
66
+ }
67
+
68
+ // Run prebuild-install against a disposable copy of better-sqlite3's
69
+ // package.json so the shared install (used by the Node-side CLI) is untouched.
70
+ const stageDir = join(tmpdir(), `aiusage-widget-native-${process.pid}`)
71
+ try {
72
+ mkdirSync(stageDir, { recursive: true })
73
+ writeFileSync(join(stageDir, 'package.json'), readFileSync(betterSqlite3Pkg))
74
+
75
+ execFileSync(
76
+ process.execPath,
77
+ [
78
+ prebuildInstallBin,
79
+ '--runtime=electron',
80
+ `--target=${electronVersion}`,
81
+ `--arch=${process.arch}`,
82
+ `--platform=${process.platform}`,
83
+ ],
84
+ { cwd: stageDir, stdio: 'inherit' },
85
+ )
86
+
87
+ const built = join(stageDir, 'build', 'Release', 'better_sqlite3.node')
88
+ if (!existsSync(built)) {
89
+ warn('prebuild-install completed but produced no binary; skipping native binding setup.')
90
+ return
91
+ }
92
+
93
+ const nativeDir = join(widgetRoot, 'dist', 'native')
94
+ mkdirSync(nativeDir, { recursive: true })
95
+ const target = join(nativeDir, 'better_sqlite3.node')
96
+ copyFileSync(built, target)
97
+
98
+ if (process.platform === 'darwin') {
99
+ // Ad-hoc sign so Gatekeeper / hardened runtime will load the binding.
100
+ try {
101
+ execFileSync('codesign', ['--force', '--sign', '-', target], { stdio: 'inherit' })
102
+ } catch {
103
+ // Non-fatal: unsigned binaries still load in most local setups.
104
+ }
105
+ }
106
+
107
+ console.log(
108
+ `[aiusage-widget] installed better-sqlite3 binding for electron ${electronVersion} (${process.platform}-${process.arch}).`,
109
+ )
110
+ } catch (error) {
111
+ warn(`failed to set up the native binding: ${error && error.message ? error.message : error}`)
112
+ } finally {
113
+ try {
114
+ rmSync(stageDir, { recursive: true, force: true })
115
+ } catch {
116
+ // ignore cleanup failures
117
+ }
118
+ }
119
+ }
120
+
121
+ main()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juliantanx/aiusage-widget",
3
- "version": "1.3.3",
3
+ "version": "1.4.0",
4
4
  "private": false,
5
5
  "description": "System tray widget for aiusage — view AI token usage from your system tray",
6
6
  "keywords": [
@@ -35,7 +35,8 @@
35
35
  "aiusage-widget": "bin/launcher.js"
36
36
  },
37
37
  "dependencies": {
38
- "better-sqlite3": "^12.0.0"
38
+ "better-sqlite3": "^12.0.0",
39
+ "electron": "^33.0.0"
39
40
  },
40
41
  "devDependencies": {
41
42
  "@electron/rebuild": "^3.6.1",
@@ -43,7 +44,6 @@
43
44
  "@types/better-sqlite3": "*",
44
45
  "@types/node": "*",
45
46
  "concurrently": "^8.0.0",
46
- "electron": "^33.0.0",
47
47
  "electron-builder": "^25.0.0",
48
48
  "svelte": "^4.0.0",
49
49
  "typescript": "^5.0.0",
@@ -52,6 +52,7 @@
52
52
  "wait-on": "^7.0.0"
53
53
  },
54
54
  "scripts": {
55
+ "postinstall": "node bin/install-native.js",
55
56
  "rebuild": "pnpm run rebuild:electron",
56
57
  "rebuild:electron": "node -e \"const {rebuild}=require('@electron/rebuild');const v=require('electron/package.json').version;rebuild({buildPath:process.cwd(),electronVersion:v,onlyModules:['better-sqlite3'],force:true}).then(()=>process.exit(0)).catch(e=>{console.error(e);process.exit(1)})\"",
57
58
  "prepare:native": "node bin/prepare-native.js",