xonecode 0.21.0 → 0.22.1
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/apps/web/dist/assets/index-5rtynJV_.js +490 -0
- package/apps/web/dist/assets/index-Cq6c6WEF.css +1 -0
- package/apps/web/dist/assets/{php-UkjSyds-.js → php-BTFUgUDo.js} +1 -1
- package/apps/web/dist/assets/{ruby-e801JuzW.js → ruby-BKKiBtJK.js} +1 -1
- package/apps/web/dist/index.html +2 -2
- package/dist/agent/cloudstudio/cloudstudioClient.js +32 -5
- package/dist/agent/cloudstudio/cloudstudioClient.js.map +1 -1
- package/dist/agent/cloudstudio/descarga.js +10 -0
- package/dist/agent/cloudstudio/descarga.js.map +1 -1
- package/dist/agent/cloudstudio/subida.js +31 -6
- package/dist/agent/cloudstudio/subida.js.map +1 -1
- package/dist/agent/cloudstudio/validarTrasDescarga.js +79 -0
- package/dist/agent/cloudstudio/validarTrasDescarga.js.map +1 -0
- package/dist/agent/config/mudanzaEnDisco.js +237 -3
- package/dist/agent/config/mudanzaEnDisco.js.map +1 -1
- package/dist/agent/config/selectorEnMaquina.js +3 -2
- package/dist/agent/config/selectorEnMaquina.js.map +1 -1
- package/dist/agent/config/settingsEnDisco.js +76 -2
- package/dist/agent/config/settingsEnDisco.js.map +1 -1
- package/dist/agent/dispositivos/arranqueDeEmulador.js +27 -3
- package/dist/agent/dispositivos/arranqueDeEmulador.js.map +1 -1
- package/dist/agent/dispositivos/instalacionEnMaquina.js +240 -29
- package/dist/agent/dispositivos/instalacionEnMaquina.js.map +1 -1
- package/dist/agent/dispositivos/lanzamientoEnMaquina.js +12 -17
- package/dist/agent/dispositivos/lanzamientoEnMaquina.js.map +1 -1
- package/dist/cli/main.js +5 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/core/copiaDeAvd.js +111 -0
- package/dist/core/copiaDeAvd.js.map +1 -0
- package/dist/core/mudanzaDeWorkspace.js +105 -15
- package/dist/core/mudanzaDeWorkspace.js.map +1 -1
- package/dist/core/puertosDeAvd.js +64 -0
- package/dist/core/puertosDeAvd.js.map +1 -0
- package/dist/core/selectorDeCarpeta.js +88 -9
- package/dist/core/selectorDeCarpeta.js.map +1 -1
- package/dist/core/settings.js +60 -1
- package/dist/core/settings.js.map +1 -1
- package/dist/core/shellDeAgente.js +11 -0
- package/dist/core/shellDeAgente.js.map +1 -1
- package/dist/core/validacionDeEscritura.js +19 -11
- package/dist/core/validacionDeEscritura.js.map +1 -1
- package/dist/web/servidor/arranque.js +476 -43
- package/dist/web/servidor/arranque.js.map +1 -1
- package/dist/web/servidor/transporte.js.map +1 -1
- package/dist/web/servidor/vestibulo.js +154 -48
- package/dist/web/servidor/vestibulo.js.map +1 -1
- package/package.json +1 -1
- package/skills/xone-hotswap/SKILL.md +26 -10
- package/skills/xone-hotswap/lib/dispositivo.mjs +97 -3
- package/skills/xone-hotswap/references/conexion-y-despliegue.md +27 -15
- package/skills/xone-hotswap/scripts/xone-arrancar-android +9 -2
- package/skills/xone-hotswap/scripts/xone-desplegar-android +12 -6
- package/skills/xone-hotswap/scripts/xone-hotswap +32 -10
- package/skills/xone-hotswap/scripts/xone-reiniciar-android +23 -7
- package/apps/web/dist/assets/index-CFoqpKRk.css +0 -1
- package/apps/web/dist/assets/index-DgvLb2SM.js +0 -486
package/apps/web/dist/index.html
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
<!-- El icono oficial, servido por Vite desde `iconos/`. Es el mismo fichero que la
|
|
8
8
|
marca de la barra superior: dos copias del logo acaban siendo dos logos. -->
|
|
9
9
|
<link rel="icon" type="image/png" href="./iconos/xonecode.png" />
|
|
10
|
-
<script type="module" crossorigin src="./assets/index-
|
|
11
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
10
|
+
<script type="module" crossorigin src="./assets/index-5rtynJV_.js"></script>
|
|
11
|
+
<link rel="stylesheet" crossorigin href="./assets/index-Cq6c6WEF.css">
|
|
12
12
|
</head>
|
|
13
13
|
<!-- Sin el atributo aquí: el oscuro es SOLO del splash (el registro de entorno y
|
|
14
14
|
modelo), no de la consola entera — `App.tsx` lo pone y lo quita él mismo, en el
|
|
@@ -43,6 +43,29 @@ function registro(valor) {
|
|
|
43
43
|
}
|
|
44
44
|
return typeof valor === "object" && valor !== null ? valor : {};
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* El contenido de un fichero tal y como lo manda `studio_get_file`: SERIALIZADO como cadena
|
|
48
|
+
* JSON (medido contra el servidor, en AppDemo y en ActivoMobileDev: `"name=…\nicon=…"`, con
|
|
49
|
+
* las comillas envolventes y los `\n`/`\"` escapados). Escrito tal cual, `app.xml` empezaba
|
|
50
|
+
* por `"` y la app no arrancaba (IXCODE-16); solo pasaba cuando el ZIP fallaba y la descarga
|
|
51
|
+
* bajaba fichero a fichero. El doble `CloudStudioEnMemoria` devuelve el texto en CRUDO, por eso
|
|
52
|
+
* ningún test lo vio.
|
|
53
|
+
*
|
|
54
|
+
* Se decodifica cuando parsea a una CADENA; si no (un servidor que algún día mande el texto en
|
|
55
|
+
* crudo), se devuelve tal cual. El caso que esto no distingue —un servidor en crudo con un
|
|
56
|
+
* fichero que sea literalmente una cadena JSON— no se ha visto nunca: el que hay codifica siempre.
|
|
57
|
+
*/
|
|
58
|
+
function contenidoDeFichero(bruto) {
|
|
59
|
+
if (!bruto.startsWith('"'))
|
|
60
|
+
return bruto;
|
|
61
|
+
try {
|
|
62
|
+
const decodificado = JSON.parse(bruto);
|
|
63
|
+
return typeof decodificado === "string" ? decodificado : bruto;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return bruto;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
46
69
|
/** Cuánto del cuerpo remoto se deja ver en un error de formato: lo justo para reconocerlo. */
|
|
47
70
|
const TOPE_DE_MUESTRA = 120;
|
|
48
71
|
/** Un texto del servidor, acotado: para un mensaje de error, no para volcarlo entero. */
|
|
@@ -174,10 +197,14 @@ esperar = (ms) => new Promise((listo) => setTimeout(listo, ms))) {
|
|
|
174
197
|
return { proyecto: String(r.project ?? ""), rama: String(r.branch ?? "") };
|
|
175
198
|
},
|
|
176
199
|
async descargarZip() {
|
|
177
|
-
const
|
|
178
|
-
const zip =
|
|
179
|
-
if (typeof zip !== "string" || zip === "")
|
|
180
|
-
|
|
200
|
+
const bruto = await conSesion("studio_download_project", { unified: false });
|
|
201
|
+
const zip = registro(bruto).base64Zip;
|
|
202
|
+
if (typeof zip !== "string" || zip === "") {
|
|
203
|
+
// Con la muestra: «no devolvió el ZIP» a secas es lo que quedaba en `sync.json#motivo`
|
|
204
|
+
// y no decía POR QUÉ, que es justo la pista de por qué una copia baja `parcial`.
|
|
205
|
+
const dicho = texto(bruto) || (typeof bruto === "string" ? bruto : JSON.stringify(bruto ?? ""));
|
|
206
|
+
throw new Error(`CloudStudio no devolvió el ZIP del proyecto: «${muestra(dicho)}»`);
|
|
207
|
+
}
|
|
181
208
|
return zip;
|
|
182
209
|
},
|
|
183
210
|
async estructura(directorio) {
|
|
@@ -194,7 +221,7 @@ esperar = (ms) => new Promise((listo) => setTimeout(listo, ms))) {
|
|
|
194
221
|
async leerTexto(ruta) {
|
|
195
222
|
const bruto = await conSesion("studio_get_file", { filePath: ruta });
|
|
196
223
|
const desenvuelto = texto(bruto);
|
|
197
|
-
return desenvuelto !== "" ? desenvuelto : typeof bruto === "string" ? bruto : "";
|
|
224
|
+
return contenidoDeFichero(desenvuelto !== "" ? desenvuelto : typeof bruto === "string" ? bruto : "");
|
|
198
225
|
},
|
|
199
226
|
async escribirTexto(ruta, contenido) {
|
|
200
227
|
await conSesion("studio_edit_file", { filePath: ruta, content: contenido, editMode: "replace" });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudstudioClient.js","sourceRoot":"","sources":["../../../src/agent/cloudstudio/cloudstudioClient.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"cloudstudioClient.js","sourceRoot":"","sources":["../../../src/agent/cloudstudio/cloudstudioClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,7 @@ import { NOMBRE_CARPETA } from "../config/configEnDisco.js";
|
|
|
13
13
|
import { ramaActiva } from "./ramaActiva.js";
|
|
14
14
|
import { destinoSeguro, extraerZipBase64 } from "./zip.js";
|
|
15
15
|
import { enumerarRemoto } from "./manifiesto.js";
|
|
16
|
+
import { validarTrasDescarga } from "./validarTrasDescarga.js";
|
|
16
17
|
/** Bastante para que la espera de red se solape; poco para no parecer un ataque. */
|
|
17
18
|
export const CONCURRENCIA = 6;
|
|
18
19
|
/** Pool acotado. No hay `worker_threads`: esto es espera de red, no CPU. */
|
|
@@ -149,6 +150,14 @@ export async function descargarProyecto(opciones) {
|
|
|
149
150
|
// Misma regla en la vía degradada: si bajó un `.xml` con su `.xne` al lado, fuera.
|
|
150
151
|
descargados = retirarVistasAplanadas(raiz, traidos);
|
|
151
152
|
}
|
|
153
|
+
// Lo bajado se comprueba en el DISCO, por las dos vías: una copia que no se puede leer
|
|
154
|
+
// (IXCODE-16: `app.xml` como cadena JSON, la app en blanco en el aparato) se dice AHORA,
|
|
155
|
+
// con los ficheros, y no cuando el aparato no arranca.
|
|
156
|
+
const ilegibles = validarTrasDescarga(raiz, descargados);
|
|
157
|
+
if (ilegibles.length > 0) {
|
|
158
|
+
informar(`${ilegibles.length} ficheros bajados no se pueden leer, y la app puede no arrancar:\n` +
|
|
159
|
+
ilegibles.map((f) => ` ${f.ruta}: ${f.motivo}\n`).join(""));
|
|
160
|
+
}
|
|
152
161
|
// La rama del estado es la ORIGEN pedida, no una que se vuelva a leer de `contexto()`:
|
|
153
162
|
// es la que se acaba de fijar arriba (o la que ya estaba, si coincidían), así que
|
|
154
163
|
// «lo que se bajó» y «lo que dice `sync.json`» nunca pueden divergir.
|
|
@@ -161,6 +170,7 @@ export async function descargarProyecto(opciones) {
|
|
|
161
170
|
descargados: [...descargados].sort(),
|
|
162
171
|
...(motivo === undefined ? {} : { motivo }),
|
|
163
172
|
...(raizTruncada ? { raizTruncada: true } : {}),
|
|
173
|
+
...(ilegibles.length > 0 ? { ilegibles } : {}),
|
|
164
174
|
};
|
|
165
175
|
const ruta = rutaSyncJson(raiz);
|
|
166
176
|
mkdirSync(dirname(ruta), { recursive: true });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"descarga.js","sourceRoot":"","sources":["../../../src/agent/cloudstudio/descarga.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAG1C,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"descarga.js","sourceRoot":"","sources":["../../../src/agent/cloudstudio/descarga.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,6 +30,7 @@ import { NOMBRE_CARPETA } from "../config/configEnDisco.js";
|
|
|
30
30
|
import { cambiosPendientes, marcarSubido } from "../sesiones/gitSync.js";
|
|
31
31
|
import { rutaSyncJson } from "./descarga.js";
|
|
32
32
|
import { ramaActiva } from "./ramaActiva.js";
|
|
33
|
+
import { validarTrasDescarga } from "./validarTrasDescarga.js";
|
|
33
34
|
export function rutaSyncLog(raiz) {
|
|
34
35
|
return join(raiz, NOMBRE_CARPETA, "cloudstudio", "sync.log");
|
|
35
36
|
}
|
|
@@ -63,24 +64,31 @@ function fuentesXne(raiz) {
|
|
|
63
64
|
*
|
|
64
65
|
* `EstadoDeSync` ya guarda proyecto y rama: se comparan, y si no casan se cae a conjunto
|
|
65
66
|
* vacío —que prohíbe TODO borrado— en vez de a uno inventado. Fail-closed, como el resto.
|
|
67
|
+
*
|
|
68
|
+
* De ahí salen también los `ilegibles` de la bajada, con la MISMA comprobación de identidad: son
|
|
69
|
+
* solo RUTAS que mirar, porque lo que decide es el disco de ahora (ver `subir`).
|
|
66
70
|
*/
|
|
67
|
-
function
|
|
71
|
+
function bajadaDe(raiz, proyecto, rama, informar) {
|
|
72
|
+
const nada = { descargados: new Set(), ilegibles: [] };
|
|
68
73
|
const ruta = rutaSyncJson(raiz);
|
|
69
74
|
if (!existsSync(ruta))
|
|
70
|
-
return
|
|
75
|
+
return nada;
|
|
71
76
|
try {
|
|
72
77
|
const estado = JSON.parse(readFileSync(ruta, "utf8"));
|
|
73
78
|
if (estado.proyecto?.id !== proyecto.id || estado.rama !== rama) {
|
|
74
79
|
informar("el sync.json en disco no es de este proyecto/rama: no se borrará nada en Studio " +
|
|
75
80
|
"hasta que vuelvas a bajar con /sync bajar\n");
|
|
76
|
-
return
|
|
81
|
+
return nada;
|
|
77
82
|
}
|
|
78
|
-
return
|
|
83
|
+
return {
|
|
84
|
+
descargados: new Set(estado.descargados ?? []),
|
|
85
|
+
ilegibles: (estado.ilegibles ?? []).map((f) => f.ruta).filter((r) => typeof r === "string"),
|
|
86
|
+
};
|
|
79
87
|
}
|
|
80
88
|
catch {
|
|
81
89
|
// Sin manifiesto legible no se puede afirmar qué se bajó, y sin eso el candado no
|
|
82
90
|
// existe: mejor un conjunto vacío (que prohíbe TODO borrado) que uno inventado.
|
|
83
|
-
return
|
|
91
|
+
return nada;
|
|
84
92
|
}
|
|
85
93
|
}
|
|
86
94
|
export async function subir(opciones) {
|
|
@@ -92,9 +100,10 @@ export async function subir(opciones) {
|
|
|
92
100
|
if (existsSync(ruta))
|
|
93
101
|
tamanos.set(cambio.ruta, statSync(ruta).size);
|
|
94
102
|
}
|
|
103
|
+
const bajada = bajadaDe(raiz, proyecto, ramaOrigen, informar);
|
|
95
104
|
const { operaciones: plan, omitidas } = planDeSubida({
|
|
96
105
|
cambios,
|
|
97
|
-
descargados:
|
|
106
|
+
descargados: bajada.descargados,
|
|
98
107
|
tamanos,
|
|
99
108
|
fuentesXne: fuentesXne(raiz),
|
|
100
109
|
});
|
|
@@ -139,6 +148,22 @@ export async function subir(opciones) {
|
|
|
139
148
|
registrar();
|
|
140
149
|
return informe;
|
|
141
150
|
}
|
|
151
|
+
// Una copia que no se puede leer NO se sube (IXCODE-16): subir un `app.xml` guardado como
|
|
152
|
+
// cadena JSON lo deja roto TAMBIÉN en Studio, para todo el que lo baje. Se revalida en el
|
|
153
|
+
// DISCO de ahora —lo que se va a escribir más lo que la bajada dejó marcado—, no se cree el
|
|
154
|
+
// `sync.json`: una copia reparada a mano sube sin tener que volver a bajarla. Y antes de la
|
|
155
|
+
// política: no se pide autorizar algo que de todos modos se va a negar.
|
|
156
|
+
const aMirar = [...new Set([...plan.filter((o) => o.tipo === "texto").map((o) => o.ruta), ...bajada.ilegibles])]
|
|
157
|
+
.filter((r) => existsSync(join(raiz, r)));
|
|
158
|
+
const ilegibles = validarTrasDescarga(raiz, aMirar);
|
|
159
|
+
if (ilegibles.length > 0) {
|
|
160
|
+
informar(`subida negada: ${ilegibles.length} ficheros no se pueden leer y romperían el proyecto en Studio. ` +
|
|
161
|
+
"Repáralos (o vuelve a bajar con /sync bajar) y sube de nuevo:\n" +
|
|
162
|
+
ilegibles.map((f) => ` ${f.ruta}: ${f.motivo}\n`).join(""));
|
|
163
|
+
informe.ilegibles = ilegibles;
|
|
164
|
+
registrar(`subida negada: ${ilegibles.length} ficheros ilegibles`);
|
|
165
|
+
return informe;
|
|
166
|
+
}
|
|
142
167
|
// La política decide ANTES de tocar el puerto: ni `abrir` ni `contexto` ni una sola
|
|
143
168
|
// escritura corren sin su autorización. Que no autorice deja el disco, el puerto y la
|
|
144
169
|
// ref exactamente como estaban — sea cual sea la política que haya detrás.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subida.js","sourceRoot":"","sources":["../../../src/agent/cloudstudio/subida.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACrG,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAG1C,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"subida.js","sourceRoot":"","sources":["../../../src/agent/cloudstudio/subida.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Después de bajar, comprobar que lo bajado SE PUEDE LEER (IXCODE-16).
|
|
3
|
+
*
|
|
4
|
+
* La causa de IXCODE-16 era que la vía fichero a fichero escribía el contenido tal y como lo
|
|
5
|
+
* serializa `studio_get_file` (una cadena JSON), y `app.xml` empezaba por `"`: la app se quedaba
|
|
6
|
+
* en blanco en el aparato con «Unexpected token», y nadie lo decía en la descarga. Eso se arregla
|
|
7
|
+
* en `cloudstudioClient.ts#contenidoDeFichero`; esto es la SEGUNDA capa, para que una copia rota
|
|
8
|
+
* se diga al bajarla —venga de donde venga, también del propio Studio— y no cuando el aparato
|
|
9
|
+
* no arranca.
|
|
10
|
+
*
|
|
11
|
+
* Dos reglas, y solo dos, porque son las que no tienen falso positivo medido:
|
|
12
|
+
*
|
|
13
|
+
* - **Ningún fichero de texto es entero una cadena JSON** (`cadenaJsonEnvuelta`). Vale para todas
|
|
14
|
+
* las extensiones: en la copia rota medida lo estaban también `.ini`, `.js`, `.css` y `.txt`.
|
|
15
|
+
* - **`app.xml` y los `.xne` son XML bien formado** (no los demás `.xml`, ver `esXmlDeXone`), con el parser de `xone-linter` —el mismo que
|
|
16
|
+
* lee el proyecto para la navegación, y que respeta la codificación declarada (iso-8859-15)—.
|
|
17
|
+
*
|
|
18
|
+
* Lo que NO se comprueba, a propósito: que `app.ini` sea `clave=valor` línea a línea. El de AppDemo
|
|
19
|
+
* en el servidor trae una línea suelta sin `=` y la app funciona; la regla daría rojo a un proyecto
|
|
20
|
+
* sano.
|
|
21
|
+
*/
|
|
22
|
+
import { readFileSync } from "node:fs";
|
|
23
|
+
// Import PROFUNDO, como en `navegacion/indiceEnDisco.ts`: el barril arrastra un top-level await.
|
|
24
|
+
import { parseXml } from "xone-linter/dist/xml/XmlParser.js";
|
|
25
|
+
import { EXTENSIONES_DE_TEXTO, extensionDe } from "../../core/planDeSubida.js";
|
|
26
|
+
import { cadenaJsonEnvuelta } from "../../core/validacionDeEscritura.js";
|
|
27
|
+
import { destinoSeguro } from "./zip.js";
|
|
28
|
+
/**
|
|
29
|
+
* `app.xml` (en la raíz) y los `.xne`: los que el framework PARSEA al arrancar. Otros `.xml` no:
|
|
30
|
+
* medido sobre las copias de esta máquina, el único falso positivo fue un diccionario
|
|
31
|
+
* (`lang/ca/_cachedictionary.xml`) que excede el límite de entidades del parser y no es de XOne.
|
|
32
|
+
*/
|
|
33
|
+
const esXmlDeXone = (ruta) => /\.xne$/i.test(ruta) || ruta.toLowerCase() === "app.xml";
|
|
34
|
+
/** El motivo por el que `contenido` no vale, o `undefined` si vale. Exportada para el test. */
|
|
35
|
+
export function motivoDeFicheroIlegible(ruta, bytes) {
|
|
36
|
+
const extension = extensionDe(ruta);
|
|
37
|
+
if (!EXTENSIONES_DE_TEXTO.has(extension))
|
|
38
|
+
return undefined;
|
|
39
|
+
// Un `.json` que sea una cadena es JSON VÁLIDO: ahí la regla no dice nada.
|
|
40
|
+
if (extension !== ".json" && cadenaJsonEnvuelta(bytes.toString("utf8")) !== undefined) {
|
|
41
|
+
return "guardado como cadena JSON (empieza por «\"» y lleva el contenido escapado)";
|
|
42
|
+
}
|
|
43
|
+
if (esXmlDeXone(ruta)) {
|
|
44
|
+
try {
|
|
45
|
+
parseXml(bytes);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
// Solo el mensaje del parser: lleva línea y columna, nunca una ruta de la máquina.
|
|
49
|
+
return `XML mal formado: ${error.message}`;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Comprueba en el DISCO los ficheros que la descarga dice haber traído. Lee los BYTES, no el texto
|
|
56
|
+
* que se escribió: es lo que va a leer el aparato. Un fichero que no se puede ni abrir cuenta como
|
|
57
|
+
* ilegible con el `code` de Node (su mensaje lleva la ruta absoluta).
|
|
58
|
+
*/
|
|
59
|
+
export function validarTrasDescarga(raiz, descargados) {
|
|
60
|
+
const ilegibles = [];
|
|
61
|
+
for (const ruta of descargados) {
|
|
62
|
+
if (!EXTENSIONES_DE_TEXTO.has(extensionDe(ruta)))
|
|
63
|
+
continue;
|
|
64
|
+
let bytes;
|
|
65
|
+
try {
|
|
66
|
+
bytes = readFileSync(destinoSeguro(raiz, ruta));
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
ilegibles.push({ ruta, motivo: `no se pudo leer (${error.code ?? "error"})` });
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const motivo = motivoDeFicheroIlegible(ruta, bytes);
|
|
73
|
+
if (motivo !== undefined)
|
|
74
|
+
ilegibles.push({ ruta, motivo });
|
|
75
|
+
}
|
|
76
|
+
// El mismo orden que `descargados` en `sync.json` (por código, no por idioma).
|
|
77
|
+
return ilegibles.sort((a, b) => (a.ruta < b.ruta ? -1 : a.ruta > b.ruta ? 1 : 0));
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=validarTrasDescarga.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validarTrasDescarga.js","sourceRoot":"","sources":["../../../src/agent/cloudstudio/validarTrasDescarga.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,iGAAiG;AACjG,OAAO,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC/E,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAQzC;;;;GAIG;AACH,MAAM,WAAW,GAAG,CAAC,IAAY,EAAW,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC;AAExG,+FAA+F;AAC/F,MAAM,UAAU,uBAAuB,CAAC,IAAY,EAAE,KAAa;IACjE,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3D,2EAA2E;IAC3E,IAAI,SAAS,KAAK,OAAO,IAAI,kBAAkB,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;QACtF,OAAO,4EAA4E,CAAC;IACtF,CAAC;IACD,IAAI,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,IAAI,CAAC;YACH,QAAQ,CAAC,KAAK,CAAC,CAAC;QAClB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,mFAAmF;YACnF,OAAO,oBAAqB,KAAe,CAAC,OAAO,EAAE,CAAC;QACxD,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY,EAAE,WAAqB;IACrE,MAAM,SAAS,GAAsB,EAAE,CAAC;IACxC,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YAAE,SAAS;QAC3D,IAAI,KAAa,CAAC;QAClB,IAAI,CAAC;YACH,KAAK,GAAG,YAAY,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,oBAAqB,KAA+B,CAAC,IAAI,IAAI,OAAO,GAAG,EAAE,CAAC,CAAC;YAC1G,SAAS;QACX,CAAC;QACD,MAAM,MAAM,GAAG,uBAAuB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACpD,IAAI,MAAM,KAAK,SAAS;YAAE,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7D,CAAC;IACD,+EAA+E;IAC/E,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpF,CAAC"}
|
|
@@ -12,10 +12,12 @@
|
|
|
12
12
|
* La decisión de QUÉ se muda es pura y vive en `core/mudanzaDeWorkspace.ts`. Aquí solo está
|
|
13
13
|
* lo que toca disco: mover, reescribir los dos almacenes con raíces absolutas y CONTARLO.
|
|
14
14
|
*/
|
|
15
|
-
import {
|
|
15
|
+
import { randomUUID, createHash } from "node:crypto";
|
|
16
|
+
import { createReadStream, existsSync, mkdirSync, readdirSync, renameSync, rmdirSync, unlinkSync } from "node:fs";
|
|
17
|
+
import { cp, lstat, mkdir, readdir, readlink, rename, rm, statfs, unlink, writeFile } from "node:fs/promises";
|
|
16
18
|
import { homedir } from "node:os";
|
|
17
|
-
import { dirname, join } from "node:path";
|
|
18
|
-
import { mudanzasPendientes, rutaMudada } from "../../core/mudanzaDeWorkspace.js";
|
|
19
|
+
import { dirname, join, relative } from "node:path";
|
|
20
|
+
import { mudanzasPendientes, planDeCambioDeBase, rutaMudada } from "../../core/mudanzaDeWorkspace.js";
|
|
19
21
|
import { remapearRaicesDeTareas } from "../tareas/tareasEnDisco.js";
|
|
20
22
|
import { BASURA_DEL_SO } from "../sesiones/gitSync.js";
|
|
21
23
|
/** Las CARPETAS que cuelgan de una ruta. Un fichero suelto no es un proyecto, y un
|
|
@@ -120,4 +122,236 @@ export function mudarWorkspaceLegado(opciones) {
|
|
|
120
122
|
}
|
|
121
123
|
return { mudadas: hechas.length, chocadas: chocadas.length };
|
|
122
124
|
}
|
|
125
|
+
/** Las carpetas que cuelgan de una ruta: la foto de disco que pide `planDeCambioDeBase`. */
|
|
126
|
+
export function planDeCambioDeBaseEnDisco(opciones) {
|
|
127
|
+
return planDeCambioDeBase({ ...opciones, existe: existsSync, listar: carpetasDe });
|
|
128
|
+
}
|
|
129
|
+
/** Bytes de todo lo que cuelga de `raiz`, sin seguir enlaces. */
|
|
130
|
+
async function tamanyoDe(raiz) {
|
|
131
|
+
const info = await lstat(raiz);
|
|
132
|
+
if (!info.isDirectory())
|
|
133
|
+
return info.isFile() ? info.size : 0;
|
|
134
|
+
let total = 0;
|
|
135
|
+
for (const nombre of await readdir(raiz))
|
|
136
|
+
total += await tamanyoDe(join(raiz, nombre));
|
|
137
|
+
return total;
|
|
138
|
+
}
|
|
139
|
+
/** Lo que ocupa lo que se va a mudar, en megas redondeados hacia arriba: para el aviso. */
|
|
140
|
+
export async function megasDeLasMudanzas(mudanzas) {
|
|
141
|
+
let bytes = 0;
|
|
142
|
+
for (const m of mudanzas)
|
|
143
|
+
bytes += await tamanyoDe(m.desde);
|
|
144
|
+
return Math.ceil(bytes / (1024 * 1024));
|
|
145
|
+
}
|
|
146
|
+
function sha256De(fichero) {
|
|
147
|
+
return new Promise((resolver, rechazar) => {
|
|
148
|
+
const hash = createHash("sha256");
|
|
149
|
+
createReadStream(fichero)
|
|
150
|
+
.on("data", (trozo) => hash.update(trozo))
|
|
151
|
+
.on("error", rechazar)
|
|
152
|
+
.on("end", () => resolver(hash.digest("hex")));
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* La huella de un árbol: por cada entrada, su ruta RELATIVA y lo que es — una carpeta, un
|
|
157
|
+
* enlace con su destino, o un fichero con su tamaño y su SHA-256. Se lee en streaming: un
|
|
158
|
+
* `checkpoint.sqlite` pesa cientos de megas y no tiene por qué caber entero en memoria.
|
|
159
|
+
*/
|
|
160
|
+
async function huellaDe(raiz, dentro = raiz, huella = new Map()) {
|
|
161
|
+
for (const nombre of await readdir(dentro)) {
|
|
162
|
+
const ruta = join(dentro, nombre);
|
|
163
|
+
const clave = relative(raiz, ruta).replace(/\\/g, "/");
|
|
164
|
+
const info = await lstat(ruta);
|
|
165
|
+
if (info.isSymbolicLink())
|
|
166
|
+
huella.set(clave, `enlace:${await readlink(ruta)}`);
|
|
167
|
+
else if (info.isDirectory()) {
|
|
168
|
+
huella.set(clave, "carpeta");
|
|
169
|
+
await huellaDe(raiz, ruta, huella);
|
|
170
|
+
}
|
|
171
|
+
else if (info.isFile())
|
|
172
|
+
huella.set(clave, `fichero:${info.size}:${await sha256De(ruta)}`);
|
|
173
|
+
else
|
|
174
|
+
huella.set(clave, "otro");
|
|
175
|
+
}
|
|
176
|
+
return huella;
|
|
177
|
+
}
|
|
178
|
+
/** Por qué la copia NO es igual al original, o `undefined` si lo es byte a byte. */
|
|
179
|
+
async function diferenciaEntre(original, copia) {
|
|
180
|
+
const [a, b] = await Promise.all([huellaDe(original), huellaDe(copia)]);
|
|
181
|
+
for (const [clave, valor] of a) {
|
|
182
|
+
if (!b.has(clave))
|
|
183
|
+
return `falta «${clave}» en la copia`;
|
|
184
|
+
if (b.get(clave) !== valor)
|
|
185
|
+
return `«${clave}» no es igual en la copia`;
|
|
186
|
+
}
|
|
187
|
+
for (const clave of b.keys())
|
|
188
|
+
if (!a.has(clave))
|
|
189
|
+
return `la copia tiene «${clave}» de más`;
|
|
190
|
+
return undefined;
|
|
191
|
+
}
|
|
192
|
+
/** Margen sobre lo que ocupa lo que se copia: el disco no se llena hasta el último byte. */
|
|
193
|
+
const MARGEN_DE_ESPACIO = 1.1;
|
|
194
|
+
const RESERVA_DE_ESPACIO = 64 * 1024 * 1024;
|
|
195
|
+
/**
|
|
196
|
+
* CAMBIAR EL WORKSPACE MUDANDO lo que hay dentro: copiar, VERIFICAR y solo entonces borrar el
|
|
197
|
+
* origen. La decisión de QUÉ se muda es pura (`core/mudanzaDeWorkspace.ts#planDeCambioDeBase`);
|
|
198
|
+
* aquí está lo que toca disco, en un orden que no deja nada a medias:
|
|
199
|
+
*
|
|
200
|
+
* 1. **comprobar**: el destino se puede escribir y cabe lo que se copia, con margen;
|
|
201
|
+
* 2. **copiar** cada proyecto a una carpeta OCULTA hermana de su destino
|
|
202
|
+
* (`.<proyecto>.llegando-<uuid>`). Se COPIA siempre, también en el mismo disco: un
|
|
203
|
+
* `rename` entre volúmenes da EXDEV, y así el origen sigue intacto hasta el final;
|
|
204
|
+
* 3. **verificar** cada copia contra su original, fichero a fichero con SHA-256 — la igualdad
|
|
205
|
+
* byte a byte es más fuerte que cualquier comprobación de git, y `git fsck` abortaría por
|
|
206
|
+
* defectos que ya traía el origen. Una sola diferencia descarta TODAS las copias;
|
|
207
|
+
* 4. con todo verificado, las ocultas pasan a su nombre, y SOLO ENTONCES se guarda el
|
|
208
|
+
* workspace nuevo y se reescribe `proyecto.raiz` del índice de tareas;
|
|
209
|
+
* 5. **borrar** el origen por lápida (renombrar y luego borrar, el molde de
|
|
210
|
+
* `borrarCopiaDeProyecto`). Si algo lo bloquea, el cambio YA está hecho y se dice como
|
|
211
|
+
* `restos`: deshacerlo con la base nueva escrita sería peor.
|
|
212
|
+
*
|
|
213
|
+
* Hasta el paso 4 la base vieja es la válida y en el destino solo hay carpetas ocultas, que se
|
|
214
|
+
* limpian. Quien llama garantiza que nada escribe en la base mientras tanto
|
|
215
|
+
* (`vestibulo.mudarWorkspace`).
|
|
216
|
+
*/
|
|
217
|
+
export async function mudarBaseDeWorkspace(opciones) {
|
|
218
|
+
const { mudanzas, progreso } = opciones;
|
|
219
|
+
const copiar = opciones.copiar ??
|
|
220
|
+
((desde, hacia) => cp(desde, hacia, { recursive: true, verbatimSymlinks: true, errorOnExist: true, force: false, preserveTimestamps: true }));
|
|
221
|
+
const espacioLibre = opciones.espacioLibre ??
|
|
222
|
+
(async (ruta) => {
|
|
223
|
+
try {
|
|
224
|
+
const s = await statfs(ruta);
|
|
225
|
+
return Number(s.bavail) * Number(s.bsize);
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
const total = mudanzas.length;
|
|
232
|
+
// 1. Comprobar. Un error de Node lleva la ruta absoluta en su mensaje: se dice su `code`.
|
|
233
|
+
progreso?.({ fase: "comprobar" });
|
|
234
|
+
try {
|
|
235
|
+
await mkdir(opciones.hacia, { recursive: true });
|
|
236
|
+
const prueba = join(opciones.hacia, `.xonecode-prueba-${randomUUID()}`);
|
|
237
|
+
await writeFile(prueba, "");
|
|
238
|
+
await unlink(prueba);
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
return { estado: "rechazado", motivo: `no se puede escribir en la carpeta nueva (${codigoDe(error)})` };
|
|
242
|
+
}
|
|
243
|
+
if (total > 0) {
|
|
244
|
+
let ocupa = 0;
|
|
245
|
+
for (const m of mudanzas)
|
|
246
|
+
ocupa += await tamanyoDe(m.desde);
|
|
247
|
+
const libre = await espacioLibre(opciones.hacia);
|
|
248
|
+
if (libre !== undefined && libre < ocupa * MARGEN_DE_ESPACIO + RESERVA_DE_ESPACIO) {
|
|
249
|
+
return {
|
|
250
|
+
estado: "rechazado",
|
|
251
|
+
motivo: `no cabe: hay que copiar ${megas(ocupa)} y en la carpeta nueva quedan ${megas(libre)} libres`,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
// 2 y 3. Copiar y verificar, cada una a su carpeta oculta.
|
|
256
|
+
const ocultas = [];
|
|
257
|
+
const descartar = async () => {
|
|
258
|
+
for (const oculta of ocultas)
|
|
259
|
+
await rm(oculta, { recursive: true, force: true }).catch(() => { });
|
|
260
|
+
};
|
|
261
|
+
for (const [i, m] of mudanzas.entries()) {
|
|
262
|
+
const oculta = join(dirname(m.hacia), `.${m.proyecto}.llegando-${randomUUID()}`);
|
|
263
|
+
try {
|
|
264
|
+
progreso?.({ fase: "copiar", proyecto: m.proyecto, entorno: m.entorno, indice: i + 1, total });
|
|
265
|
+
await mkdir(dirname(m.hacia), { recursive: true });
|
|
266
|
+
ocultas.push(oculta);
|
|
267
|
+
await copiar(m.desde, oculta);
|
|
268
|
+
progreso?.({ fase: "verificar", proyecto: m.proyecto, entorno: m.entorno, indice: i + 1, total });
|
|
269
|
+
const diferencia = await diferenciaEntre(m.desde, oculta);
|
|
270
|
+
if (diferencia !== undefined) {
|
|
271
|
+
await descartar();
|
|
272
|
+
return {
|
|
273
|
+
estado: "rechazado",
|
|
274
|
+
motivo: `la copia de «${m.proyecto}» no salió igual (${diferencia}): no se ha cambiado nada`,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
await descartar();
|
|
280
|
+
return { estado: "rechazado", motivo: `no se pudo copiar «${m.proyecto}» (${codigoDe(error)}): no se ha cambiado nada` };
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
// 4. A su nombre, y entonces el workspace nuevo. Un fallo aquí deshace lo renombrado.
|
|
284
|
+
const puestas = [];
|
|
285
|
+
try {
|
|
286
|
+
for (const [i, m] of mudanzas.entries()) {
|
|
287
|
+
await rename(ocultas[i], m.hacia);
|
|
288
|
+
puestas.push(i);
|
|
289
|
+
}
|
|
290
|
+
opciones.guardarWorkspace(opciones.hacia);
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
// Deshacer es RETIRAR la copia puesta, que se puede: el origen sigue intacto (el paso 5 no
|
|
294
|
+
// ha corrido). Antes se renombraba de vuelta tragándose el error, y si fallaba quedaba una
|
|
295
|
+
// copia entera en la base nueva mientras el resultado decía «no se ha cambiado nada» —y el
|
|
296
|
+
// plan siguiente, al verla, bloqueaba cada reintento con «ya hay una copia de…»—.
|
|
297
|
+
const retirar = opciones.retirar ?? ((copia) => rm(copia, { recursive: true, force: true }));
|
|
298
|
+
const sueltas = [];
|
|
299
|
+
for (const i of puestas) {
|
|
300
|
+
const m = mudanzas[i];
|
|
301
|
+
try {
|
|
302
|
+
await retirar(m.hacia);
|
|
303
|
+
}
|
|
304
|
+
catch {
|
|
305
|
+
sueltas.push(`${m.proyecto} (${m.entorno})`);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
await descartar();
|
|
309
|
+
if (sueltas.length > 0) {
|
|
310
|
+
// Sin rutas: viaja por el cable. El proyecto y el entorno dicen dónde en la carpeta nueva.
|
|
311
|
+
return {
|
|
312
|
+
estado: "rechazado",
|
|
313
|
+
motivo: `no se pudo terminar el cambio (${codigoDe(error)}): el workspace sigue siendo el de antes y tus copias ` +
|
|
314
|
+
`están intactas, pero en la carpeta nueva quedó una copia de ${sueltas.join(", ")} que no se pudo retirar: ` +
|
|
315
|
+
"bórrala a mano antes de volver a intentarlo",
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
return { estado: "rechazado", motivo: `no se pudo terminar el cambio (${codigoDe(error)}): no se ha cambiado nada` };
|
|
319
|
+
}
|
|
320
|
+
const avisos = [];
|
|
321
|
+
try {
|
|
322
|
+
remapearRaicesDeTareas(opciones.casaXonecode, (raiz) => rutaMudada(raiz, mudanzas));
|
|
323
|
+
}
|
|
324
|
+
catch (error) {
|
|
325
|
+
avisos.push(`las copias se mudaron, pero no se pudo actualizar la cola de tareas (${codigoDe(error)})`);
|
|
326
|
+
}
|
|
327
|
+
// 5. Borrar el origen por lápida.
|
|
328
|
+
const restos = [];
|
|
329
|
+
for (const [i, m] of mudanzas.entries()) {
|
|
330
|
+
progreso?.({ fase: "borrar", proyecto: m.proyecto, entorno: m.entorno, indice: i + 1, total });
|
|
331
|
+
const lapida = join(dirname(m.desde), `.${m.proyecto}.borrando-${randomUUID()}`);
|
|
332
|
+
try {
|
|
333
|
+
await (opciones.enterrar ?? rename)(m.desde, lapida);
|
|
334
|
+
}
|
|
335
|
+
catch {
|
|
336
|
+
restos.push(`${m.proyecto} (${m.entorno})`);
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
try {
|
|
340
|
+
await rm(lapida, { recursive: true, force: true });
|
|
341
|
+
}
|
|
342
|
+
catch {
|
|
343
|
+
restos.push(`${m.proyecto} (${m.entorno})`);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
for (const entorno of new Set(mudanzas.map((m) => m.entorno)))
|
|
347
|
+
retirarSiSobra(join(opciones.desde, entorno));
|
|
348
|
+
return { estado: "hecho", mudadas: total, restos, avisos };
|
|
349
|
+
}
|
|
350
|
+
function megas(bytes) {
|
|
351
|
+
return `${Math.ceil(bytes / (1024 * 1024))} MB`;
|
|
352
|
+
}
|
|
353
|
+
function codigoDe(error) {
|
|
354
|
+
const code = error?.code;
|
|
355
|
+
return typeof code === "string" ? code : "error";
|
|
356
|
+
}
|
|
123
357
|
//# sourceMappingURL=mudanzaEnDisco.js.map
|