@gettrace/cli 2.0.7 → 2.0.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gettrace/cli",
3
- "version": "2.0.7",
3
+ "version": "2.0.8",
4
4
  "description": "Trace IDE Bridge for connecting local filesystem to Trace browser extensions.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -34,8 +34,10 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
34
34
 
35
35
  // The extension IDs that are allowed to use this native host.
36
36
  const ALLOWED_EXTENSION_IDS = [
37
- // Development / unpacked extension ID
37
+ // Development / unpacked extension ID (macOS)
38
38
  'jefgjgdcelekglimbmgplkaaabdfpgfm',
39
+ // Development / unpacked extension ID (Windows)
40
+ 'fppbikhdjehmiidhjholkiaeeieoilfb',
39
41
  // Add the published CWS extension ID here when you have it:
40
42
  // 'PRODUCTION_EXTENSION_ID',
41
43
  ];
@@ -49,11 +51,18 @@ if (process.env.TRACE_EXTENSION_IDS) {
49
51
 
50
52
  const HOST_NAME = 'dev.gettrace.host';
51
53
 
52
- // Install native host files into ~/.local/share/trace/native-host/ so that
53
- // Chrome (and other browsers) can always read them. Files on ~/Desktop,
54
- // ~/Documents, ~/Downloads require explicit macOS TCC (Privacy) permission
55
- // which Chrome does not have by default. ~/.local/share/ is always accessible.
56
- const INSTALL_DIR = join(homedir(), '.local', 'share', 'trace', 'native-host');
54
+ // Install native host files into platform-specific directories
55
+ // macOS/Linux: ~/.local/share/trace/native-host/ (no TCC permission issues)
56
+ // Windows: %LOCALAPPDATA%\trace\native-host\ (standard Windows app data location)
57
+ function getInstallDir() {
58
+ if (platform() === 'win32') {
59
+ const localAppData = process.env.LOCALAPPDATA || join(homedir(), 'AppData', 'Local');
60
+ return join(localAppData, 'trace', 'native-host');
61
+ }
62
+ return join(homedir(), '.local', 'share', 'trace', 'native-host');
63
+ }
64
+
65
+ const INSTALL_DIR = getInstallDir();
57
66
  const HOST_ENTRY = join(INSTALL_DIR, 'host-entry');
58
67
  const HOST_CJS_DEST = join(INSTALL_DIR, 'host.cjs');
59
68
 
@@ -96,6 +105,84 @@ function generateHostEntry() {
96
105
  writeFileSync(join(INSTALL_DIR, 'package.json'), readFileSync(pkgSrc), { mode: 0o644 });
97
106
  }
98
107
 
108
+ // On Windows, create a .bat launcher that Chrome can execute
109
+ if (platform() === 'win32') {
110
+ generateWindowsHostEntry(nodePath, tracePath);
111
+ } else {
112
+ generateUnixHostEntry(nodePath, tracePath);
113
+ }
114
+ }
115
+
116
+ function generateWindowsHostEntry(nodePath, tracePath) {
117
+ const HOST_BAT = join(INSTALL_DIR, 'host-entry.bat');
118
+ const HOST_JS = join(INSTALL_DIR, 'host-entry.js');
119
+
120
+ // Create the JavaScript loader file
121
+ const jsContent = [
122
+ `// Auto-generated by @gettrace/cli postinstall — do not edit manually`,
123
+ `// Generated: ${new Date().toISOString()}`,
124
+ `// Node: ${nodePath}`,
125
+ tracePath ? `// Trace: ${tracePath}` : `// Trace: (resolves from PATH)`,
126
+ `'use strict';`,
127
+ ``,
128
+ `// Fix PATH before anything else — Chrome launches with a minimal environment`,
129
+ tracePath
130
+ ? `process.env.PATH = '${dirname(tracePath).replace(/\\/g, '\\\\')};${dirname(nodePath).replace(/\\/g, '\\\\')};' + (process.env.PATH || 'C:\\\\Windows\\\\System32');`
131
+ : `process.env.PATH = '${dirname(nodePath).replace(/\\/g, '\\\\')};;' + (process.env.PATH || 'C:\\\\Windows\\\\System32');`,
132
+ ``,
133
+ ...(() => {
134
+ const monorepoAgent = resolve(
135
+ __dirname, '..', '..', 'packages', 'trace-agent', 'dist', 'node', 'index.js'
136
+ );
137
+ const localCli = resolve(__dirname, '..', 'dist', 'index.js');
138
+ if (existsSync(monorepoAgent) && existsSync(localCli)) {
139
+ return [
140
+ `// Dev mode: use local CLI build instead of the global npm package`,
141
+ `process.env.TRACE_DEV_MODE = '1';`,
142
+ `process.env.TRACE_CLI_PATH = '${localCli.replace(/\\/g, '\\\\')}';`,
143
+ ``,
144
+ ];
145
+ }
146
+ return [];
147
+ })(),
148
+ `// Diagnostic logging — written synchronously so we catch crashes before async`,
149
+ `const fs = require('fs');`,
150
+ `const path = require('path');`,
151
+ `const logPath = path.join('${homedir().replace(/\\/g, '\\\\')}', 'trace-native-host.log');`,
152
+ `function log(msg) {`,
153
+ ` const line = new Date().toISOString() + ' ' + msg + '\\n';`,
154
+ ` try { fs.appendFileSync(logPath, line); } catch(_) {}`,
155
+ `}`,
156
+ ``,
157
+ `log('[host-entry] started, node=' + process.version + ' pid=' + process.pid);`,
158
+ ``,
159
+ `try {`,
160
+ ` require('${HOST_CJS_DEST.replace(/\\/g, '\\\\')}');`,
161
+ ` log('[host-entry] host.cjs loaded OK');`,
162
+ `} catch (err) {`,
163
+ ` log('[host-entry] FATAL: ' + (err.stack || err));`,
164
+ ` process.exit(1);`,
165
+ `}`,
166
+ ].join('\n');
167
+
168
+ writeFileSync(HOST_JS, jsContent, { encoding: 'utf8' });
169
+
170
+ // Create the .bat launcher that Chrome will execute
171
+ const batContent = [
172
+ `@echo off`,
173
+ `REM Auto-generated by @gettrace/cli postinstall`,
174
+ `REM Node: ${nodePath}`,
175
+ `"${nodePath}" "${HOST_JS}" %*`,
176
+ ].join('\r\n');
177
+
178
+ writeFileSync(HOST_BAT, batContent, { encoding: 'utf8' });
179
+
180
+ console.log(`✓ Generated Windows native host: ${HOST_BAT}`);
181
+ console.log(` Node binary: ${nodePath}`);
182
+ if (tracePath) console.log(` Trace binary: ${tracePath}`);
183
+ }
184
+
185
+ function generateUnixHostEntry(nodePath, tracePath) {
99
186
  // Log paths — write to home dir only (always writable by Chrome)
100
187
  const logPath1 = `${homedir()}/trace-native-host.log`;
101
188
 
@@ -112,16 +199,6 @@ function generateHostEntry() {
112
199
  ? `process.env.PATH = '${dirname(tracePath)}:${dirname(nodePath)}:' + (process.env.PATH || '/usr/bin:/bin');`
113
200
  : `process.env.PATH = '${dirname(nodePath)}:/opt/homebrew/bin:/usr/local/bin:' + (process.env.PATH || '/usr/bin:/bin');`,
114
201
  ``,
115
- // Inject dev mode env vars ONLY when running from the trace monorepo
116
- // (the dev workflow). Detect that by the presence of the local agent
117
- // build that dev-mode resolution actually targets:
118
- // <repo>/packages/trace-agent/dist/node/index.js. In a published npm
119
- // install this path does not exist (the package lives under
120
- // node_modules/@gettrace/cli), so production NEVER enables dev mode.
121
- //
122
- // NOTE: do NOT key this off `<pkg>/dist/index.js` — the published CLI
123
- // ships that file too, which previously made every install spuriously
124
- // enable dev mode and fail to locate the agent.
125
202
  ...(() => {
126
203
  const monorepoAgent = resolve(
127
204
  __dirname, '..', '..', 'packages', 'trace-agent', 'dist', 'node', 'index.js'
@@ -179,10 +256,15 @@ function getNativeHostDir() {
179
256
  }
180
257
 
181
258
  function buildManifest() {
259
+ // On Windows, Chrome needs to execute a .bat file; Unix uses the shebang script
260
+ const executablePath = platform() === 'win32'
261
+ ? join(INSTALL_DIR, 'host-entry.bat')
262
+ : HOST_ENTRY;
263
+
182
264
  return JSON.stringify({
183
265
  name: HOST_NAME,
184
266
  description: 'Trace native host — spawns trace dev in the user\'s project directory',
185
- path: HOST_ENTRY, // Points to the generated entry file with hardcoded node path
267
+ path: executablePath,
186
268
  type: 'stdio',
187
269
  allowed_origins: ALLOWED_EXTENSION_IDS.map(id => `chrome-extension://${id}/`),
188
270
  }, null, 2);
@@ -190,15 +272,23 @@ function buildManifest() {
190
272
 
191
273
  function registerOnWindows() {
192
274
  const manifest = buildManifest();
193
- const manifestPath = join(homedir(), 'AppData', 'Local', 'Trace', `${HOST_NAME}.json`);
275
+ // Store manifest in the same directory as the host files for consistency
276
+ const manifestPath = join(INSTALL_DIR, `${HOST_NAME}.json`);
194
277
  mkdirSync(dirname(manifestPath), { recursive: true });
195
278
  writeFileSync(manifestPath, manifest, 'utf8');
279
+ console.log(`✓ Native host manifest: ${manifestPath}`);
280
+
196
281
  const regKey = `HKCU\\Software\\Google\\Chrome\\NativeMessagingHosts\\${HOST_NAME}`;
197
282
  try {
198
- execSync(`reg add "${regKey}" /ve /t REG_SZ /d "${manifestPath}" /f`, { stdio: 'pipe' });
199
- console.log(`✓ Native host registered (Windows registry)`);
283
+ // Use double backslashes for Windows paths in registry
284
+ const manifestPathWin = manifestPath.replace(/\//g, '\\');
285
+ execSync(`reg add "${regKey}" /ve /t REG_SZ /d "${manifestPathWin}" /f`, { stdio: 'pipe' });
286
+ console.log(`✓ Native host registered in Windows registry`);
287
+ console.log(` Registry key: ${regKey}`);
288
+ console.log(` Manifest path: ${manifestPathWin}`);
200
289
  } catch (e) {
201
290
  console.warn('⚠ Could not register native host in Windows registry:', e.message);
291
+ console.warn(' Try running as Administrator or manually import the registry key');
202
292
  }
203
293
  }
204
294