qdd-framework 2.10.0-rc.2 → 2.10.0-rc.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/bin/qdd.js +44 -17
- package/install.js +121 -9
- package/package.json +1 -1
package/bin/qdd.js
CHANGED
|
@@ -2,26 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
const { spawnSync } = require('child_process');
|
|
4
4
|
const path = require('path');
|
|
5
|
-
const
|
|
5
|
+
const fs = require('fs');
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
// rutaDelBinario: en Windows, qdd.exe vive fuera del paquete, en la carpeta de su versión (install.js, FND-142). Una
|
|
8
|
+
// instalación anterior a ese cambio, o sin LOCALAPPDATA, lo tiene dentro del paquete.
|
|
9
|
+
function rutaDelBinario({ platform, env, dir, version, existe }) {
|
|
10
|
+
const nombre = platform === 'win32' ? 'qdd.exe' : 'qdd';
|
|
11
|
+
const enElPaquete = path.join(dir, nombre);
|
|
12
|
+
if (platform !== 'win32' || !env.LOCALAPPDATA || !version) {
|
|
13
|
+
return enElPaquete;
|
|
14
|
+
}
|
|
15
|
+
const porVersion = path.join(env.LOCALAPPDATA, 'qdd', 'bin', version, nombre);
|
|
16
|
+
return existe(porVersion) ? porVersion : enElPaquete;
|
|
17
|
+
}
|
|
13
18
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
function versionDelPaquete() {
|
|
20
|
+
try {
|
|
21
|
+
return require('../package.json').version;
|
|
22
|
+
} catch (_) {
|
|
23
|
+
return '';
|
|
24
|
+
}
|
|
19
25
|
}
|
|
20
26
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
process.
|
|
27
|
+
function main() {
|
|
28
|
+
const binaryPath = rutaDelBinario({ platform: process.platform, env: process.env, dir: __dirname, version: versionDelPaquete(), existe: fs.existsSync });
|
|
29
|
+
|
|
30
|
+
const result = spawnSync(binaryPath, process.argv.slice(2), {
|
|
31
|
+
stdio: 'inherit'
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Sin binario, lo más probable es que npm esté reinstalando qdd: 75 es «todavía no» para los pedidos del panel (FND-135).
|
|
35
|
+
if (result.error && result.error.code === 'ENOENT') {
|
|
36
|
+
console.error('[QDD] qdd se está actualizando: inténtalo de nuevo en un momento.');
|
|
37
|
+
console.error('[QDD] Si sigue así, reinstala el paquete con: npm install -g qdd-framework');
|
|
38
|
+
process.exit(75);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (result.error) {
|
|
42
|
+
console.error(`[QDD] No se pudo ejecutar el binario nativo ${binaryPath}: ${result.error.message}`);
|
|
43
|
+
console.error('[QDD] Reinstala el paquete con: npm install -g qdd-framework');
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
process.exit(result.status === null ? 1 : result.status);
|
|
25
48
|
}
|
|
26
49
|
|
|
27
|
-
|
|
50
|
+
module.exports = { rutaDelBinario };
|
|
51
|
+
|
|
52
|
+
if (require.main === module) {
|
|
53
|
+
main();
|
|
54
|
+
}
|
package/install.js
CHANGED
|
@@ -69,6 +69,9 @@ function main() {
|
|
|
69
69
|
const binaryName = `qdd${binaryExt}`;
|
|
70
70
|
const binDir = path.join(__dirname, 'bin');
|
|
71
71
|
|
|
72
|
+
const carpeta = carpetaDeVersiones({ os, env: process.env });
|
|
73
|
+
const destino = destinoDelBinario({ carpeta, version: pkg.version, binDir, binaryName });
|
|
74
|
+
|
|
72
75
|
if (!fs.existsSync(binDir)) {
|
|
73
76
|
fs.mkdirSync(binDir, { recursive: true });
|
|
74
77
|
}
|
|
@@ -82,11 +85,32 @@ function main() {
|
|
|
82
85
|
process.exit(0);
|
|
83
86
|
}
|
|
84
87
|
|
|
85
|
-
|
|
88
|
+
// Reinstalar la misma versión: su binario puede estar corriendo y no hace falta tocarlo.
|
|
89
|
+
if (carpeta && respondeBinario(destino)) {
|
|
90
|
+
console.log(`[QDD] La versión ${pkg.version} ya está en ${destino}.`);
|
|
91
|
+
terminarInstalacion({ bin: destino, carpeta });
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (process.env.QDD_INSTALL_BINARIO) {
|
|
96
|
+
instalarBinarioIndicado({ origen: process.env.QDD_INSTALL_BINARIO, destino, carpeta });
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
descargarDesdeRelease({ os, arch, ext, binaryName, binDir, destino, carpeta });
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// QDD_INSTALL_BINARIO instala ese binario en vez de descargarlo: es como el CI prueba el paquete antes de publicarlo.
|
|
104
|
+
function instalarBinarioIndicado({ origen, destino, carpeta }) {
|
|
105
|
+
try {
|
|
106
|
+
terminarInstalacion({ bin: instalarCopia(origen, destino), carpeta });
|
|
107
|
+
} catch (err) {
|
|
108
|
+
fallar(`no se pudo instalar ${origen}: ${err.message}`);
|
|
109
|
+
}
|
|
86
110
|
}
|
|
87
111
|
|
|
88
112
|
// 2. Descarga desde GitHub Releases
|
|
89
|
-
function descargarDesdeRelease({ os, arch, ext, binaryName, binDir }) {
|
|
113
|
+
function descargarDesdeRelease({ os, arch, ext, binaryName, binDir, destino, carpeta }) {
|
|
90
114
|
const url = `https://github.com/${REPO}/releases/download/${VERSION}/qdd_${os}_${arch}.${ext}`;
|
|
91
115
|
const downloadDest = path.join(__dirname, `qdd-download.${ext}`);
|
|
92
116
|
|
|
@@ -121,9 +145,9 @@ function descargarDesdeRelease({ os, arch, ext, binaryName, binDir }) {
|
|
|
121
145
|
function extractBinary() {
|
|
122
146
|
console.log('[QDD] Extrayendo...');
|
|
123
147
|
try {
|
|
124
|
-
const bin = instalarDescarga({ os, paquete: downloadDest, carpeta: __dirname, binaryName, binDir, env: process.env });
|
|
148
|
+
const bin = instalarDescarga({ os, paquete: downloadDest, carpeta: __dirname, binaryName, binDir, env: process.env, destino });
|
|
125
149
|
console.log('[QDD] ¡Instalación nativa completada exitosamente!');
|
|
126
|
-
|
|
150
|
+
terminarInstalacion({ bin, carpeta });
|
|
127
151
|
} catch (err) {
|
|
128
152
|
fallar(`no se pudo instalar el binario: ${err.message}`);
|
|
129
153
|
}
|
|
@@ -140,8 +164,96 @@ function comandoExtraer(os, paquete, destino, env) {
|
|
|
140
164
|
return { programa: 'tar', args: ['-xzf', paquete, '-C', destino] };
|
|
141
165
|
}
|
|
142
166
|
|
|
143
|
-
//
|
|
144
|
-
|
|
167
|
+
// En Windows, npm no puede reemplazar un qdd.exe en uso, y siempre hay uno: el panel y los pedidos corren desde él (issue
|
|
168
|
+
// #107, FND-142). Por eso ahí el binario vive fuera del paquete, en %LOCALAPPDATA%\qdd\bin\<versión>\qdd.exe: lo que
|
|
169
|
+
// corre se queda con su versión y npm no se topa con nada. bin\actual.txt dice cuál es la instalada: lo que corre lo
|
|
170
|
+
// mira para saber que tiene que cerrarse. Linux y macOS pueden reemplazar un binario en uso: siguen con él en el paquete.
|
|
171
|
+
function carpetaDeVersiones({ os, env }) {
|
|
172
|
+
if (os !== 'windows' || !env.LOCALAPPDATA) {
|
|
173
|
+
return '';
|
|
174
|
+
}
|
|
175
|
+
return path.join(env.LOCALAPPDATA, 'qdd', 'bin');
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function destinoDelBinario({ carpeta, version, binDir, binaryName }) {
|
|
179
|
+
if (!carpeta) {
|
|
180
|
+
return path.join(binDir, binaryName);
|
|
181
|
+
}
|
|
182
|
+
return path.join(carpeta, version, binaryName);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function respondeBinario(ruta) {
|
|
186
|
+
try {
|
|
187
|
+
execFileSync(ruta, ['--version'], { stdio: 'pipe', timeout: TOPE_VERSION_MS });
|
|
188
|
+
return true;
|
|
189
|
+
} catch (_) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// moverBinario copia si el destino está en otro volumen: el prefijo de npm y %LOCALAPPDATA% pueden estarlo.
|
|
195
|
+
function moverBinario(origen, destino, renombrar = fs.renameSync) {
|
|
196
|
+
try {
|
|
197
|
+
renombrar(origen, destino);
|
|
198
|
+
return;
|
|
199
|
+
} catch (err) {
|
|
200
|
+
if (err.code !== 'EXDEV') {
|
|
201
|
+
throw err;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
copiarBinario(origen, destino);
|
|
205
|
+
fs.rmSync(origen, { force: true });
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// copiarBinario nunca deja un binario a medias con el nombre final.
|
|
209
|
+
function copiarBinario(origen, destino) {
|
|
210
|
+
const temporal = destino + '.nuevo';
|
|
211
|
+
fs.copyFileSync(origen, temporal);
|
|
212
|
+
fs.renameSync(temporal, destino);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function instalarCopia(origen, destino) {
|
|
216
|
+
execFileSync(origen, ['--version'], { stdio: 'pipe', timeout: TOPE_VERSION_MS });
|
|
217
|
+
fs.mkdirSync(path.dirname(destino), { recursive: true });
|
|
218
|
+
copiarBinario(origen, destino);
|
|
219
|
+
return destino;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// registrarVersion avisa a lo que corre que hay otra versión y borra las viejas: quedan esta y la anterior. Lo que no se
|
|
223
|
+
// puede borrar sigue corriendo: se borrará en otra actualización.
|
|
224
|
+
function registrarVersion({ carpeta, version, borrar = fs.rmSync }) {
|
|
225
|
+
const puntero = path.join(carpeta, 'actual.txt');
|
|
226
|
+
const anterior = esArchivo(puntero) ? fs.readFileSync(puntero, 'utf8').trim() : '';
|
|
227
|
+
if (anterior !== version) {
|
|
228
|
+
fs.writeFileSync(puntero, version);
|
|
229
|
+
}
|
|
230
|
+
for (const nombre of fs.readdirSync(carpeta)) {
|
|
231
|
+
if (!/^\d+\.\d+\.\d+/.test(nombre) || nombre === version || nombre === anterior) {
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
try {
|
|
235
|
+
borrar(path.join(carpeta, nombre), { recursive: true, force: true });
|
|
236
|
+
} catch (_) {
|
|
237
|
+
console.log(`[QDD] La versión ${nombre} sigue en uso: se borrará más adelante.`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// terminarInstalacion: primero el panel, y al final el puntero, porque lo que corre se cierra apenas cambia.
|
|
243
|
+
function terminarInstalacion({ bin, carpeta }) {
|
|
244
|
+
actualizarConsola(bin);
|
|
245
|
+
if (!carpeta) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
try {
|
|
249
|
+
registrarVersion({ carpeta, version: pkg.version });
|
|
250
|
+
} catch (err) {
|
|
251
|
+
console.error('[QDD] No se pudo registrar la versión instalada:', err.message);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// instalarDescarga deja el binario en su destino solo si responde; si algo falla, lanza el error y el binario anterior sigue ahí.
|
|
256
|
+
function instalarDescarga({ os, paquete, carpeta, binaryName, binDir, env, destino = path.join(binDir, binaryName) }) {
|
|
145
257
|
const { programa, args } = comandoExtraer(os, paquete, carpeta, env);
|
|
146
258
|
execFileSync(programa, args, { stdio: 'pipe' });
|
|
147
259
|
const extraido = path.join(carpeta, binaryName);
|
|
@@ -150,8 +262,8 @@ function instalarDescarga({ os, paquete, carpeta, binaryName, binDir, env }) {
|
|
|
150
262
|
}
|
|
151
263
|
fs.chmodSync(extraido, 0o755);
|
|
152
264
|
execFileSync(extraido, ['--version'], { stdio: 'pipe', timeout: TOPE_VERSION_MS });
|
|
153
|
-
|
|
154
|
-
|
|
265
|
+
fs.mkdirSync(path.dirname(destino), { recursive: true });
|
|
266
|
+
moverBinario(extraido, destino);
|
|
155
267
|
fs.rmSync(paquete, { force: true });
|
|
156
268
|
return destino;
|
|
157
269
|
}
|
|
@@ -178,7 +290,7 @@ function actualizarConsola(bin) {
|
|
|
178
290
|
}
|
|
179
291
|
}
|
|
180
292
|
|
|
181
|
-
module.exports = { esArchivo, estaDentroDeNodeModules, resolverBinarioLocal, comandoExtraer, instalarDescarga, codigoDeFalla };
|
|
293
|
+
module.exports = { esArchivo, estaDentroDeNodeModules, resolverBinarioLocal, comandoExtraer, instalarDescarga, codigoDeFalla, carpetaDeVersiones, destinoDelBinario, respondeBinario, moverBinario, instalarCopia, registrarVersion };
|
|
182
294
|
|
|
183
295
|
if (require.main === module) {
|
|
184
296
|
main();
|