@glassnote/client 2.4.8 → 2.4.10

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/autoStart.js CHANGED
@@ -220,35 +220,6 @@ class AutoStart {
220
220
  }
221
221
  }
222
222
 
223
- // Remove existing plist if it exists
224
- if (fs.existsSync(plistPath)) {
225
- try {
226
- // Use spawn instead of execSync to avoid blocking
227
- const unloadProcess = spawn('launchctl', ['unload', plistPath], {
228
- stdio: 'ignore',
229
- timeout: 5000 // 5 second timeout
230
- });
231
-
232
- unloadProcess.on('error', (error) => {
233
- });
234
-
235
- unloadProcess.on('exit', (code) => {
236
- if (code !== 0) {
237
- console.warn('launchctl unload exited with code:', code, '(may not be loaded)');
238
- }
239
- });
240
- } catch (error) {
241
- console.error('Could not unload existing plist:', error.message);
242
- }
243
-
244
- // Remove the plist file regardless of launchctl status
245
- try {
246
- fs.unlinkSync(plistPath);
247
- } catch (error) {
248
- console.error('Could not remove plist file:', error.message);
249
- }
250
- }
251
-
252
223
  const plistContent = `<?xml version="1.0" encoding="UTF-8"?>
253
224
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
254
225
  <plist version="1.0">
@@ -273,29 +244,30 @@ ${launchArgs.map((a) => ` <string>${a}</string>`).join('\n')}
273
244
  fs.mkdirSync(plistDir, { recursive: true });
274
245
  }
275
246
 
276
- fs.writeFileSync(plistPath, plistContent);
277
-
278
- // Load the launch agent asynchronously
247
+ // El plist NO se borra ni se recarga si ya dice lo mismo, y NUNCA se hace
248
+ // `launchctl unload`.
249
+ //
250
+ // Esto lo llama el main en CADA arranque. En macOS, cuando el que arranca es el
251
+ // propio LaunchAgent (o sea: al iniciar sesión, que es el caso normal), la app era
252
+ // el job de launchd: el `launchctl unload` de aquí abajo mataba el job, y con él a
253
+ // la app que lo estaba ejecutando. Medido: el cliente se abría al login y se moría
254
+ // a los ~3 segundos, antes incluso del primer chequeo de actualización, que es a
255
+ // los 5. Encima el agente quedaba descargado, así que ni `launchctl list` lo veía.
256
+ //
257
+ // Tampoco se hace `load` cuando el contenido cambia: `RunAtLoad` arrancaría OTRA
258
+ // instancia encima de esta —la app no tiene lock de instancia única— y el archivo
259
+ // nuevo lo lee launchd solo en el próximo login, que es justo cuando tiene que
260
+ // valer. Escribirlo es todo lo que hace falta.
261
+ let actual = null;
279
262
  try {
280
- const loadProcess = spawn('launchctl', ['load', plistPath], {
281
- stdio: 'ignore',
282
- timeout: 5000 // 5 second timeout
283
- });
284
-
285
- loadProcess.on('error', (error) => {
286
- console.error('Error spawning launchctl load:', error.message);
287
- });
288
-
289
- loadProcess.on('exit', (code) => {
290
- if (code !== 0) {
291
- console.warn('launchctl load exited with code:', code);
292
- } else {
293
- console.warn('macOS auto-start configured:', plistPath);
294
- }
295
- });
263
+ actual = fs.readFileSync(plistPath, 'utf8');
296
264
  } catch (error) {
297
- console.error('Error loading launch agent:', error.message);
265
+ actual = null; // no existía
298
266
  }
267
+ if (actual === plistContent) return true;
268
+
269
+ fs.writeFileSync(plistPath, plistContent);
270
+ console.log('macOS auto-start configured:', plistPath);
299
271
 
300
272
  return true;
301
273
  } catch (error) {
package/bin/glassnote.js CHANGED
@@ -52,14 +52,26 @@ function npmEnv() {
52
52
  // con otro entorno, y ahí `npm` no existe. La auto-actualización moría en "npm no se
53
53
  // reconoce como un comando" y nadie lo veía. Si no hay forma de resolver el npm-cli.js se
54
54
  // vuelve al shim de siempre.
55
- function runNpm(args, opts) {
55
+ // Separado de runNpm a propósito: decidir CÓMO se llama a npm es una función pura, y por
56
+ // eso se puede comprobar en cualquier sistema (scripts/test-update.js lo hace). Ejecutarlo
57
+ // no. La regresión que hay que impedir es volver a `shell: true` con un array de
58
+ // argumentos: Node no entrecomilla en ese caso y en Windows la ruta del prefix se parte en
59
+ // el primer espacio —`C:\Users\Santiago Andrade\...`—, con lo que npm intenta un
60
+ // mkdir de 'C:\Users\Santiago' y la instalación entera falla con EPERM.
61
+ function npmInvocation(args) {
56
62
  const nodeBinary = mode.resolveNodeBinary(process.execPath);
57
63
  const npmCli = mode.resolveNpmCli(nodeBinary);
58
- const base = { stdio: 'inherit', shell: false, env: npmEnv() };
59
64
  if (nodeBinary && npmCli) {
60
- return spawnSync(nodeBinary, [npmCli].concat(args), Object.assign(base, opts || {}));
65
+ return { file: nodeBinary, args: [npmCli].concat(args), shell: false, viaNode: true };
61
66
  }
62
- return spawnSync(NPM_CMD, args, Object.assign(base, { shell: IS_WIN }, opts || {}));
67
+ // Sin npm-cli.js localizable no queda más que el shim del PATH. Sigue sin shell:
68
+ // spawnSync con un array ya entrecomilla por su cuenta cuando no hay shell de por medio.
69
+ return { file: NPM_CMD, args, shell: false, viaNode: false };
70
+ }
71
+
72
+ function runNpm(args, opts) {
73
+ const { file, args: argv, shell } = npmInvocation(args);
74
+ return spawnSync(file, argv, Object.assign({ stdio: 'inherit', shell, env: npmEnv() }, opts || {}));
63
75
  }
64
76
 
65
77
  // userData tira de `uuid`, y este CLI corre también donde el árbol de dependencias no
@@ -772,4 +784,10 @@ function main() {
772
784
  }
773
785
  }
774
786
 
775
- process.exit(main());
787
+ // Requerido desde un test, el archivo NO debe correr nada: solo expone las piezas que
788
+ // se comprueban. Como CLI se comporta igual que siempre.
789
+ if (require.main === module) {
790
+ process.exit(main());
791
+ } else {
792
+ module.exports = { npmInvocation, npmEnv, toSpec };
793
+ }