@glassnote/client 2.4.3 → 2.4.5
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/INSTALACION.md +14 -1
- package/autoupdate.js +4 -2
- package/bin/glassnote.js +46 -11
- package/main.js +5 -0
- package/npmMode.js +114 -0
- package/npmUpdate.js +33 -7
- package/package.json +1 -1
package/INSTALACION.md
CHANGED
|
@@ -86,7 +86,8 @@ se rompe en silencio es la que descarga la gente.
|
|
|
86
86
|
|
|
87
87
|
## Actualizaciones
|
|
88
88
|
|
|
89
|
-
Instalado por npm, el cliente comprueba el registry
|
|
89
|
+
Instalado por npm, el cliente comprueba el registry a los 5 segundos de arrancar y cada
|
|
90
|
+
hora a partir de ahí, y se actualiza solo:
|
|
90
91
|
|
|
91
92
|
- lee `desiredVersion` de los datos de usuario (`lastest` = seguir la última, o una
|
|
92
93
|
versión exacta y clavada); son las mismas claves que usaba el updater de S3, para no
|
|
@@ -95,6 +96,18 @@ Instalado por npm, el cliente comprueba el registry cada 3 horas y se actualiza
|
|
|
95
96
|
abrir. El npm **no** se corre con la app en marcha: en Windows el `electron.exe` en uso
|
|
96
97
|
está bloqueado y npm no podría reemplazarlo.
|
|
97
98
|
|
|
99
|
+
El ayudante corre con un **node de fuera del paquete**, no con el electron de la propia
|
|
100
|
+
app: ese electron vive dentro del árbol que npm va a reemplazar y en Windows lo mantenía
|
|
101
|
+
bloqueado, así que npm fallaba y la actualización no se aplicaba nunca. Se busca, en
|
|
102
|
+
orden: `GLASSNOTE_NODE`, el node anotado en `~/.glassnote/node-path` al instalar, el que
|
|
103
|
+
bajó el instalador a `~/.glassnote/node-v*`, y el del PATH. A npm se lo llama por su
|
|
104
|
+
`npm-cli.js`, no por el shim: en Windows el instalador mete su Node al PATH de esa sola
|
|
105
|
+
sesión de PowerShell, y la app —que la abre el autoarranque— no lo tendría.
|
|
106
|
+
|
|
107
|
+
`glassnote status` dice cuál se va a usar. Si sale `node de update: NO ENCONTRADO`, la
|
|
108
|
+
auto-actualización no puede funcionar en esa máquina: hay que reinstalar el cliente
|
|
109
|
+
(`irm https://glassnote.intermark.ec/install.ps1 | iex`) o instalar Node.
|
|
110
|
+
|
|
98
111
|
Por `npx` no se actualiza nada: la caché es efímera y npx ya baja la última versión cada
|
|
99
112
|
vez. Tampoco se registra el arranque automático — apuntaría a una carpeta que se limpia
|
|
100
113
|
sola.
|
package/autoupdate.js
CHANGED
|
@@ -30,10 +30,12 @@ class AutoUpdate {
|
|
|
30
30
|
this.checkForUpdates();
|
|
31
31
|
}, 5000);
|
|
32
32
|
|
|
33
|
-
// Verificación periódica cada hora
|
|
33
|
+
// Verificación periódica cada hora. Antes decía "cada hora" en el comentario pero
|
|
34
|
+
// la cuenta era 60 * 60 * 3000, o sea 3 horas: un cliente podía tardar toda una
|
|
35
|
+
// tarde en enterarse de una versión nueva.
|
|
34
36
|
this.updateInterval = setInterval(() => {
|
|
35
37
|
this.checkForUpdates();
|
|
36
|
-
}, 60 * 60 *
|
|
38
|
+
}, 60 * 60 * 1000);
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
/**
|
package/bin/glassnote.js
CHANGED
|
@@ -39,6 +39,22 @@ function npmEnv() {
|
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
// npm se invoca por su `npm-cli.js` con el node que lo trae, NO por el shim del PATH.
|
|
43
|
+
// En Windows el instalador puede bajarse un Node a ~/.glassnote y meterlo solo al PATH de
|
|
44
|
+
// la sesión de PowerShell que corrió la instalación: la app la arranca el autoarranque,
|
|
45
|
+
// con otro entorno, y ahí `npm` no existe. La auto-actualización moría en "npm no se
|
|
46
|
+
// reconoce como un comando" y nadie lo veía. Si no hay forma de resolver el npm-cli.js se
|
|
47
|
+
// vuelve al shim de siempre.
|
|
48
|
+
function runNpm(args, opts) {
|
|
49
|
+
const nodeBinary = mode.resolveNodeBinary(process.execPath);
|
|
50
|
+
const npmCli = mode.resolveNpmCli(nodeBinary);
|
|
51
|
+
const base = { stdio: 'inherit', shell: false, env: npmEnv() };
|
|
52
|
+
if (nodeBinary && npmCli) {
|
|
53
|
+
return spawnSync(nodeBinary, [npmCli].concat(args), Object.assign(base, opts || {}));
|
|
54
|
+
}
|
|
55
|
+
return spawnSync(NPM_CMD, args, Object.assign(base, { shell: IS_WIN }, opts || {}));
|
|
56
|
+
}
|
|
57
|
+
|
|
42
58
|
// userData tira de `uuid`, y este CLI corre también donde el árbol de dependencias no
|
|
43
59
|
// está (un tarball recién desempacado, un install a medias). Por eso se carga tarde y
|
|
44
60
|
// tolerando el fallo: si no se puede dejar constancia, el peor caso es que la app
|
|
@@ -406,13 +422,15 @@ function cmdInstall(args) {
|
|
|
406
422
|
// Los scripts de instalación van ACTIVADOS a propósito: el binario de electron se
|
|
407
423
|
// baja en un postinstall. Con --ignore-scripts quedaría instalado y roto.
|
|
408
424
|
step(`npm install -g --prefix ${mode.NPM_PREFIX} (sin root, la primera vez tarda: baja electron)`);
|
|
409
|
-
const res =
|
|
410
|
-
stdio: 'inherit',
|
|
411
|
-
shell: IS_WIN,
|
|
412
|
-
env: npmEnv(),
|
|
413
|
-
});
|
|
425
|
+
const res = runNpm(['install', '-g', '--prefix', mode.NPM_PREFIX, spec]);
|
|
414
426
|
if (res.status !== 0) fail('npm no pudo instalar el paquete (ver el error de arriba).');
|
|
415
427
|
|
|
428
|
+
// Se anota con qué node se instaló: la app lo necesita para auto-actualizarse y no
|
|
429
|
+
// puede contar con que el PATH de la sesión gráfica tenga uno.
|
|
430
|
+
if (mode.rememberNodeBinary(process.execPath)) {
|
|
431
|
+
step(`node para las actualizaciones: ${process.execPath}`);
|
|
432
|
+
}
|
|
433
|
+
|
|
416
434
|
if (!fs.existsSync(mode.INSTALLED_PACKAGE_DIR)) {
|
|
417
435
|
fail(`npm terminó pero no encuentro ${mode.INSTALLED_PACKAGE_DIR}`);
|
|
418
436
|
}
|
|
@@ -487,18 +505,26 @@ function cmdUpdate(args) {
|
|
|
487
505
|
const waitIdx = args.indexOf('--wait');
|
|
488
506
|
const waitMs = waitIdx !== -1 ? parseInt(args[waitIdx + 1], 10) || 0 : 0;
|
|
489
507
|
const relaunch = args.includes('--relaunch');
|
|
490
|
-
|
|
508
|
+
// Sin `--wait`, waitIdx es -1 y waitIdx+1 es 0: el filtro se comía el PRIMER
|
|
509
|
+
// posicional, así que `glassnote update 2.4.3` instalaba latest en vez de 2.4.3.
|
|
510
|
+
const positional = args.filter(
|
|
511
|
+
(a, i) => !a.startsWith('-') && !(waitIdx !== -1 && i === waitIdx + 1)
|
|
512
|
+
);
|
|
491
513
|
const version = positional[0] || 'latest';
|
|
492
514
|
|
|
493
515
|
if (waitMs > 0) sleepSync(waitMs);
|
|
494
516
|
|
|
517
|
+
// El cwd no puede estar dentro de lo que npm va a borrar: en Windows un directorio
|
|
518
|
+
// que es el cwd de un proceso vivo no se puede eliminar, y ese proceso es este.
|
|
519
|
+
try {
|
|
520
|
+
process.chdir(os.tmpdir());
|
|
521
|
+
} catch (error) {
|
|
522
|
+
/* si no se puede, npm igual lo intenta */
|
|
523
|
+
}
|
|
524
|
+
|
|
495
525
|
const spec = toSpec(version);
|
|
496
526
|
log(`glassnote — actualizando a ${spec}`);
|
|
497
|
-
const res =
|
|
498
|
-
stdio: 'inherit',
|
|
499
|
-
shell: IS_WIN,
|
|
500
|
-
env: npmEnv(),
|
|
501
|
-
});
|
|
527
|
+
const res = runNpm(['install', '-g', '--prefix', mode.NPM_PREFIX, spec]);
|
|
502
528
|
if (res.status !== 0) {
|
|
503
529
|
recordarFalloDeUpdate(version, `npm salió con ${res.status}`);
|
|
504
530
|
if (relaunch) {
|
|
@@ -511,6 +537,10 @@ function cmdUpdate(args) {
|
|
|
511
537
|
}
|
|
512
538
|
|
|
513
539
|
olvidarFalloDeUpdate();
|
|
540
|
+
// Igual que en install: si esta actualización la corrió un node de fuera del paquete,
|
|
541
|
+
// se anota para la siguiente. Los clientes instalados antes de que esto existiera no
|
|
542
|
+
// tienen el archivo, y el primer update es su oportunidad de conseguirlo.
|
|
543
|
+
mode.rememberNodeBinary(process.execPath);
|
|
514
544
|
// Se rehace en cada update: quien ya tenia el cliente instalado de antes no paso
|
|
515
545
|
// por el install, y el .app tiene que aparecerle igual (y con la version al dia).
|
|
516
546
|
const appMac = instalarAppMac();
|
|
@@ -617,6 +647,11 @@ function cmdStatus() {
|
|
|
617
647
|
log(` home: ${mode.HOME_DIR}`);
|
|
618
648
|
log(` datos: ${userDataDir()}`);
|
|
619
649
|
log(` autoarranque: ${autoStartOn}`);
|
|
650
|
+
// Sin un node fuera del paquete no hay auto-actualización posible: es lo primero que
|
|
651
|
+
// hay que mirar cuando un cliente se queda clavado en una versión vieja.
|
|
652
|
+
const nodeBinary = mode.resolveNodeBinary(process.execPath);
|
|
653
|
+
log(` node de update: ${nodeBinary || 'NO ENCONTRADO (la auto-actualización va a fallar)'}`);
|
|
654
|
+
log(` npm de update: ${mode.resolveNpmCli(nodeBinary) || `shim del PATH (${NPM_CMD})`}`);
|
|
620
655
|
if (process.platform === 'linux') {
|
|
621
656
|
let sandboxState = 'sin electron';
|
|
622
657
|
try {
|
package/main.js
CHANGED
|
@@ -234,6 +234,11 @@ app.whenReady().then(() => {
|
|
|
234
234
|
windowOptions.height = height;
|
|
235
235
|
// Explicitly set fullscreen to false for macOS
|
|
236
236
|
windowOptions.fullscreen = false;
|
|
237
|
+
// La sombra de la ventana la dibuja macOS alrededor de lo que NO es transparente,
|
|
238
|
+
// asi que en una ventana transparente sin marco la pinta pegada a cada imagen: eso
|
|
239
|
+
// es el borde negro que se ve alrededor de los mensajes. Una capa de overlay no
|
|
240
|
+
// necesita sombra.
|
|
241
|
+
windowOptions.hasShadow = false;
|
|
237
242
|
} else {
|
|
238
243
|
// Windows and other platforms
|
|
239
244
|
windowOptions.width = 400;
|
package/npmMode.js
CHANGED
|
@@ -115,6 +115,116 @@ function sandboxFlags(electronBinary) {
|
|
|
115
115
|
return ['--no-sandbox'];
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
// ── Encontrar un node "de verdad" ──────────────────────────────────────────────────
|
|
119
|
+
//
|
|
120
|
+
// La auto-actualización lanza un ayudante que corre `npm install -g`, y ese ayudante NO
|
|
121
|
+
// puede ser el electron del propio paquete: npm reemplaza justamente ese árbol y en
|
|
122
|
+
// Windows un ejecutable en marcha está BLOQUEADO, así que npm moría con EPERM y la
|
|
123
|
+
// actualización no se aplicaba nunca. (En Linux/macOS borrar un binario en uso sí
|
|
124
|
+
// funciona: por eso el fallo solo se veía en Windows.) Hace falta un node de fuera.
|
|
125
|
+
//
|
|
126
|
+
// Tampoco vale confiar en el PATH para encontrar `npm`: en Windows el instalador puede
|
|
127
|
+
// bajarse un Node a ~/.glassnote y solo lo mete al PATH de ESA sesión de PowerShell. La
|
|
128
|
+
// app la arranca el autoarranque, con otro entorno, y ahí `npm` no existe. Por eso se
|
|
129
|
+
// busca el binario en disco, se recuerda cuál se usó al instalar, y a npm se lo invoca
|
|
130
|
+
// por su npm-cli.js en vez de por el shim.
|
|
131
|
+
const NODE_EXE = process.platform === 'win32' ? 'node.exe' : 'node';
|
|
132
|
+
const NODE_PATH_FILE = path.join(HOME_DIR, 'node-path');
|
|
133
|
+
|
|
134
|
+
function esArchivo(p) {
|
|
135
|
+
try {
|
|
136
|
+
return !!p && fs.statSync(p).isFile();
|
|
137
|
+
} catch (error) {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function usableNode(p) {
|
|
143
|
+
if (!p) return false;
|
|
144
|
+
if (path.basename(p).toLowerCase() !== NODE_EXE) return false;
|
|
145
|
+
if (!esArchivo(p)) return false;
|
|
146
|
+
// Lo que esté dentro del paquete es lo que npm va a reemplazar: no sirve.
|
|
147
|
+
if (isInside(p, INSTALLED_PACKAGE_DIR)) return false;
|
|
148
|
+
if (isInside(p, PACKAGE_ROOT)) return false;
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function readNodePathFile() {
|
|
153
|
+
try {
|
|
154
|
+
return fs.readFileSync(NODE_PATH_FILE, 'utf8').trim() || null;
|
|
155
|
+
} catch (error) {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// El CLI deja constancia del node con el que se instaló: es el único que se sabe seguro
|
|
161
|
+
// que existe en esta máquina, aunque no esté en el PATH de la sesión gráfica.
|
|
162
|
+
function rememberNodeBinary(binary) {
|
|
163
|
+
try {
|
|
164
|
+
if (!usableNode(binary)) return false;
|
|
165
|
+
fs.mkdirSync(HOME_DIR, { recursive: true });
|
|
166
|
+
fs.writeFileSync(NODE_PATH_FILE, realpath(binary), 'utf8');
|
|
167
|
+
return true;
|
|
168
|
+
} catch (error) {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// install.sh e install.ps1 desempacan el tarball oficial en ~/.glassnote/node-vX.Y.Z-...
|
|
174
|
+
function nodesBootstrapeados() {
|
|
175
|
+
const out = [];
|
|
176
|
+
try {
|
|
177
|
+
for (const entry of fs.readdirSync(HOME_DIR)) {
|
|
178
|
+
if (!entry.startsWith('node-v')) continue;
|
|
179
|
+
out.push(path.join(HOME_DIR, entry, NODE_EXE)); // zip de windows
|
|
180
|
+
out.push(path.join(HOME_DIR, entry, 'bin', NODE_EXE)); // tarball unix
|
|
181
|
+
}
|
|
182
|
+
} catch (error) {
|
|
183
|
+
/* ~/.glassnote puede no existir todavía */
|
|
184
|
+
}
|
|
185
|
+
return out;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function nodesEnPath() {
|
|
189
|
+
return String(process.env.PATH || '')
|
|
190
|
+
.split(path.delimiter)
|
|
191
|
+
.filter(Boolean)
|
|
192
|
+
.map((dir) => path.join(dir, NODE_EXE));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// `preferido` es el ejecutable actual: cuando el CLI corre bajo node (npx, el ayudante)
|
|
196
|
+
// ese es el candidato correcto. Cuando corre bajo electron queda descartado solo, por
|
|
197
|
+
// estar dentro del paquete.
|
|
198
|
+
function resolveNodeBinary(preferido) {
|
|
199
|
+
const candidatos = [
|
|
200
|
+
process.env.GLASSNOTE_NODE,
|
|
201
|
+
preferido,
|
|
202
|
+
readNodePathFile(),
|
|
203
|
+
path.join(BIN_DIR, NODE_EXE),
|
|
204
|
+
]
|
|
205
|
+
.concat(nodesBootstrapeados())
|
|
206
|
+
.concat(nodesEnPath());
|
|
207
|
+
for (const candidato of candidatos) {
|
|
208
|
+
if (usableNode(candidato)) return realpath(candidato);
|
|
209
|
+
}
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// npm-cli.js siempre viaja al lado del node que lo trae; el shim del PATH, no.
|
|
214
|
+
function resolveNpmCli(nodeBinary) {
|
|
215
|
+
if (!nodeBinary) return null;
|
|
216
|
+
const dir = path.dirname(nodeBinary);
|
|
217
|
+
const candidatos = [
|
|
218
|
+
path.join(dir, 'node_modules', 'npm', 'bin', 'npm-cli.js'), // zip de windows
|
|
219
|
+
path.join(dir, '..', 'lib', 'node_modules', 'npm', 'bin', 'npm-cli.js'), // tarball unix / node del sistema
|
|
220
|
+
path.join(dir, '..', 'node_modules', 'npm', 'bin', 'npm-cli.js'),
|
|
221
|
+
];
|
|
222
|
+
for (const candidato of candidatos) {
|
|
223
|
+
if (esArchivo(candidato)) return path.normalize(candidato);
|
|
224
|
+
}
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
|
|
118
228
|
const isNpmMode = () => detect() === 'npm-global' || detect() === 'npx';
|
|
119
229
|
const isEphemeral = () => detect() === 'npx';
|
|
120
230
|
const isGlobalInstall = () => detect() === 'npm-global';
|
|
@@ -132,6 +242,10 @@ module.exports = {
|
|
|
132
242
|
sandboxIsSetuidRoot,
|
|
133
243
|
chromeSandboxPath,
|
|
134
244
|
userNamespacesUsable,
|
|
245
|
+
resolveNodeBinary,
|
|
246
|
+
resolveNpmCli,
|
|
247
|
+
rememberNodeBinary,
|
|
248
|
+
NODE_PATH_FILE,
|
|
135
249
|
isNpmMode,
|
|
136
250
|
isEphemeral,
|
|
137
251
|
isGlobalInstall,
|
package/npmUpdate.js
CHANGED
|
@@ -7,8 +7,14 @@
|
|
|
7
7
|
// se está ejecutando está bloqueado y npm no puede reemplazarlo. Se lanza un ayudante
|
|
8
8
|
// desprendido, la app se cierra, el ayudante actualiza y la vuelve a abrir. Igual en las
|
|
9
9
|
// tres plataformas, así no hay una rama por sistema operativo que solo se pruebe en uno.
|
|
10
|
+
//
|
|
11
|
+
// El ayudante corre con un node de FUERA del paquete (npmMode.resolveNodeBinary). Antes
|
|
12
|
+
// se lanzaba con el propio electron en modo node, que vive dentro del árbol que npm va a
|
|
13
|
+
// reemplazar: en Windows eso lo mantenía bloqueado y el update fallaba siempre.
|
|
10
14
|
const https = require('https');
|
|
15
|
+
const http = require('http');
|
|
11
16
|
const fs = require('fs');
|
|
17
|
+
const os = require('os');
|
|
12
18
|
const path = require('path');
|
|
13
19
|
const { spawn } = require('child_process');
|
|
14
20
|
|
|
@@ -18,7 +24,7 @@ const packageJson = require('./package.json');
|
|
|
18
24
|
|
|
19
25
|
const REGISTRY = process.env.GLASSNOTE_REGISTRY || 'https://registry.npmjs.org';
|
|
20
26
|
const CHECK_DELAY_MS = 5000;
|
|
21
|
-
const CHECK_INTERVAL_MS =
|
|
27
|
+
const CHECK_INTERVAL_MS = 60 * 60 * 1000; // cada hora
|
|
22
28
|
|
|
23
29
|
class NpmUpdate {
|
|
24
30
|
constructor() {
|
|
@@ -48,8 +54,12 @@ class NpmUpdate {
|
|
|
48
54
|
}
|
|
49
55
|
|
|
50
56
|
getJson(url) {
|
|
57
|
+
// El módulo va por protocolo: con `https` fijo, un GLASSNOTE_REGISTRY en http
|
|
58
|
+
// —el registry local de scripts/local-registry.js— moría en ERR_INVALID_PROTOCOL
|
|
59
|
+
// y la variable no servía para probar el auto-update.
|
|
60
|
+
const client = String(url).startsWith('http://') ? http : https;
|
|
51
61
|
return new Promise((resolve) => {
|
|
52
|
-
const req =
|
|
62
|
+
const req = client.get(url, { headers: { accept: 'application/json' } }, (res) => {
|
|
53
63
|
if (res.statusCode !== 200) {
|
|
54
64
|
res.resume();
|
|
55
65
|
console.error(`[update] HTTP ${res.statusCode} en ${url}`);
|
|
@@ -130,13 +140,27 @@ class NpmUpdate {
|
|
|
130
140
|
console.log(`[update] ${this.currentVersion} → ${version}: actualizando y reiniciando`);
|
|
131
141
|
|
|
132
142
|
const cli = path.join(npmMode.PACKAGE_ROOT, 'bin', 'glassnote.js');
|
|
133
|
-
|
|
134
|
-
//
|
|
143
|
+
|
|
144
|
+
// Un node de fuera del paquete es lo que hace que esto funcione en Windows: el
|
|
145
|
+
// ayudante no puede tener abierto ninguno de los archivos que npm va a borrar.
|
|
146
|
+
const nodeBinary = npmMode.resolveNodeBinary(process.execPath);
|
|
135
147
|
const env = Object.assign({}, process.env, {
|
|
136
|
-
ELECTRON_RUN_AS_NODE: '1',
|
|
137
148
|
GLASSNOTE_INSTALL_MODE: 'npm-global',
|
|
138
149
|
PATH: `${npmMode.BIN_DIR}${path.delimiter}${process.env.PATH || ''}`,
|
|
139
150
|
});
|
|
151
|
+
if (nodeBinary) {
|
|
152
|
+
delete env.ELECTRON_RUN_AS_NODE;
|
|
153
|
+
console.log(`[update] ayudante: ${nodeBinary}`);
|
|
154
|
+
} else {
|
|
155
|
+
// Último recurso: electron haciendo de node. En Linux/macOS actualiza igual
|
|
156
|
+
// (borrar un binario en uso está permitido); en Windows lo más probable es
|
|
157
|
+
// que npm no pueda y falle. Queda dicho en el log para que se vea por qué.
|
|
158
|
+
env.ELECTRON_RUN_AS_NODE = '1';
|
|
159
|
+
console.error(
|
|
160
|
+
'[update] no encuentro un node fuera del paquete; uso electron como node ' +
|
|
161
|
+
'(en Windows esto suele hacer fallar la actualización)'
|
|
162
|
+
);
|
|
163
|
+
}
|
|
140
164
|
|
|
141
165
|
// El ayudante corre desprendido y su salida no la veía nadie: cuando npm fallaba,
|
|
142
166
|
// el único síntoma era la app reiniciándose sola. Va a un archivo al lado de los
|
|
@@ -150,10 +174,12 @@ class NpmUpdate {
|
|
|
150
174
|
}
|
|
151
175
|
|
|
152
176
|
try {
|
|
177
|
+
// cwd fuera del paquete: en Windows no se puede borrar un directorio que es
|
|
178
|
+
// el cwd de un proceso vivo, y ese proceso sería justamente el actualizador.
|
|
153
179
|
const child = spawn(
|
|
154
|
-
process.execPath,
|
|
180
|
+
nodeBinary || process.execPath,
|
|
155
181
|
[cli, 'update', version, '--relaunch', '--wait', '4000'],
|
|
156
|
-
{ detached: true, stdio: ['ignore', salida, salida], env }
|
|
182
|
+
{ detached: true, stdio: ['ignore', salida, salida], env, cwd: os.tmpdir() }
|
|
157
183
|
);
|
|
158
184
|
child.unref();
|
|
159
185
|
} catch (error) {
|
package/package.json
CHANGED