xonecode 0.26.1 → 0.29.0

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.
Files changed (38) hide show
  1. package/apps/web/dist/assets/{EditorDeFichero-BW6i19HW.js → EditorDeFichero-ChyJtiiz.js} +1 -1
  2. package/apps/web/dist/assets/{index-CJycg35E.js → index-CFIrUOmW.js} +84 -84
  3. package/apps/web/dist/assets/{index-DICdq4UC.css → index-IptObD2z.css} +1 -1
  4. package/apps/web/dist/assets/{php-DxWUQTjM.js → php-B91ZcS-9.js} +1 -1
  5. package/apps/web/dist/assets/{ruby-gCKsUWxP.js → ruby-DrxrTSz0.js} +1 -1
  6. package/apps/web/dist/index.html +2 -2
  7. package/dist/agent/dispositivos/hotswap.js +27 -0
  8. package/dist/agent/dispositivos/hotswap.js.map +1 -1
  9. package/dist/agent/dispositivos/lanzamientoEnMaquina.js +33 -1
  10. package/dist/agent/dispositivos/lanzamientoEnMaquina.js.map +1 -1
  11. package/dist/agent/dispositivos/recargaEnAparato.js +190 -0
  12. package/dist/agent/dispositivos/recargaEnAparato.js.map +1 -0
  13. package/dist/agent/grafo/arbolDeProyecto.js +34 -11
  14. package/dist/agent/grafo/arbolDeProyecto.js.map +1 -1
  15. package/dist/agent/grafo/codificacionDelProyecto.js +282 -0
  16. package/dist/agent/grafo/codificacionDelProyecto.js.map +1 -0
  17. package/dist/agent/grafo/proyecto.js +6 -1
  18. package/dist/agent/grafo/proyecto.js.map +1 -1
  19. package/dist/agent/motores/trueforge/sesionTrueforge.js +4 -1
  20. package/dist/agent/motores/trueforge/sesionTrueforge.js.map +1 -1
  21. package/dist/agent/sesiones/baseDeFichero.js +8 -8
  22. package/dist/agent/sesiones/baseDeFichero.js.map +1 -1
  23. package/dist/agent/subagentes/escrituraExterna.js +4 -1
  24. package/dist/agent/subagentes/escrituraExterna.js.map +1 -1
  25. package/dist/agent/turno/turnoReal.js +4 -1
  26. package/dist/agent/turno/turnoReal.js.map +1 -1
  27. package/dist/core/codificacion.js +134 -0
  28. package/dist/core/codificacion.js.map +1 -0
  29. package/dist/core/recargaEnCaliente.js +122 -0
  30. package/dist/core/recargaEnCaliente.js.map +1 -0
  31. package/dist/web/servidor/arranque.js +184 -5
  32. package/dist/web/servidor/arranque.js.map +1 -1
  33. package/dist/web/servidor/transporte.js.map +1 -1
  34. package/package.json +1 -1
  35. package/skills/xone-hotswap/SKILL.md +3 -2
  36. package/skills/xone-hotswap/references/comandos.md +17 -1
  37. package/skills/xone-hotswap/scripts/xone-desplegar-android +62 -24
  38. package/skills/xone-hotswap/scripts/xone-recargar-android +59 -4
@@ -1 +1 @@
1
- {"version":3,"file":"transporte.js","sourceRoot":"","sources":["../../../src/web/servidor/transporte.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"transporte.js","sourceRoot":"","sources":["../../../src/web/servidor/transporte.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xonecode",
3
- "version": "0.26.1",
3
+ "version": "0.29.0",
4
4
  "description": "Consola CLI y harness de agente para desarrollar aplicaciones XOne",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -107,7 +107,8 @@ xone-desplegar-android --app MiApp --serie emulator-5554
107
107
  # «cambié un botón / una función / un color»: NO despliegues entero. Compara el proyecto con el
108
108
  # aparato, sube SOLO lo que difiere y lo aplica por la vía más barata (1-2 s si es una colección):
109
109
  # colección (.xne) → recarga en caliente JavaScript (.js) → recarga del include
110
- # CSS, app.xml, app.ini, mappings → relanza la app (unos 6 s)
110
+ # CSS (.css) → recarga en caliente (loadCssFile; en frameworks viejos, por runScript)
111
+ # app.xml, app.ini, mappings → relanza la app (unos 6 s)
111
112
  # Necesita la app YA desplegada. Lo que no sabe aplicar (iconos, bd) lo dice y manda a desplegar.
112
113
  xone-recargar-android
113
114
  xone-recargar-android MenuPrincipal.xne functions.js # solo esos, sin comparar
@@ -246,7 +247,7 @@ Detalle de despliegue, relanzado y endpoints de fichero: [conexión y despliegue
246
247
  | Tocar (`click`, `tap`, `doubleTap`, `longPress`, `openSelector`, `fill`, `clear`, `scroll`, `pressKey`) | sí | **sí**, con desviaciones (abajo) |
247
248
  | Ciclo de app (`launchApplication`, `exitApplication`, `directdownload`) | sí | `launchApplication` y `directdownload` sí; `exitApplication` no |
248
249
  | Atributos y colecciones (`setAttribute`, `deleteAttribute`, `loadCollection`) | sí | sí |
249
- | CSS, `replaceProperty`, `refresh`, `relayout`, `loadIncludeFile` | sí | **no** |
250
+ | CSS (`setCssAttribute`, `loadCssFile`/`unloadCssFile`), `replaceProperty`, `refresh`, `relayout`, `loadIncludeFile` | sí | **no** |
250
251
  | Ficheros (`/file_upload`, `/file_download`, `uploadFile`, `getFileChecksum`) | sí | **no** (`listappfiles` sí) |
251
252
  | Scripts y SQL (`runScript`, `runSql`, `getDatabaseTableNames`, `queryDatabaseTable`) | sí | **no** |
252
253
  | Logs (`getLog`, `*DeviceLogging`, `setLog*`) | sí | **no** |
@@ -81,6 +81,7 @@ por los dos canales.
81
81
  | `deleteAttribute` | sí | sí | **solo WS** |
82
82
  | `replaceProperty` | sí | — | — |
83
83
  | `setCssAttribute` / `deleteCssAttribute` | sí | — | — |
84
+ | `loadCssFile` / `unloadCssFile` (desde 5.0.5.7dev) | sí | — | — |
84
85
  | `refresh` / `relayout` | sí | — | — |
85
86
  | `status` / `state` | sí | sí | **solo WS** |
86
87
  | `uploadFile` | sí | — | — |
@@ -542,7 +543,8 @@ Carga o recarga una colección XML en caliente. **Entrada:** `xmlNode` (XML en *
542
543
  |---|---|---|
543
544
  | Colección `.xne` | `loadCollection` con el fichero entero en Base64 y `encoding=UTF-8` | Se repinta en ~2 s, **solo en memoria**: al relanzar la app vuelve la versión de disco. Para que persista, subir también el fichero con `uploadFile`. |
544
545
  | JavaScript | `uploadFile` y luego `loadIncludeFile` con `compile=true` | Se aplica al instante. Solo subirlo, o `loadCollection`, **no** lo recarga. |
545
- | CSS | `uploadFile` y luego `launchApplication` | Se aplica al relanzar. `setCssAttribute`, `relayout`, `refresh` y `loadCollection` contestan `result:true` y el color **no cambia**; `loadIncludeFile` no admite css (`Unknown script language css`). |
546
+ | CSS (5.0.5.7dev en adelante) | `uploadFile` y luego `loadCssFile` con `fileName` | Se aplica al instante (medido: ~50 ms), **sin relanzar ni `refresh`**: sustituye la hoja en su sitio de la cascada y relayouta. |
547
+ | CSS (antes de 5.0.5.7dev, donde `loadCssFile` es `Unknown command`) | `uploadFile`, `runScript` con `appData.unloadCssFile(n); appData.loadCssFile(n, enc); return "ok";` y luego `refresh` | Se aplica sin relanzar. **Sin el `refresh` no se ve**: el cambio entra en el siguiente pintado. `setCssAttribute`, `relayout`, `refresh` y `loadCollection` solos contestan `result:true` y el color **no cambia**; `loadIncludeFile` no admite css (`Unknown script language css`). |
546
548
 
547
549
  `uploadFile`: `destinationPath` cuelga del directorio de datos del framework, no del de la app.
548
550
  La app vive en `app_<nombre en minúsculas>/`, así que hay que dar `app_holamundo/functions.js`; con
@@ -567,6 +569,20 @@ relayout o refresh según el atributo. **(iOS)** también es legado: solo WebSoc
567
569
  ### `setCssAttribute` / `deleteCssAttribute` — solo Android
568
570
  `fileName`, `className`, `attributeName` (+ `attributeValue` en el set).
569
571
 
572
+ ### `loadCssFile` / `unloadCssFile` — solo Android, desde 5.0.5.7dev
573
+ `loadCssFile`: `fileName` (sí), `encoding` (no, `UTF-8`), `conditions` (no, vacío = siempre),
574
+ `strictMode` (no, `false`). Carga una hoja que **ya está en el dispositivo** (súbela antes con
575
+ `uploadFile`), como un `<style>` del `<app>`, y relayouta las ventanas visibles. Si ya estaba cargada
576
+ con las mismas `conditions`, la **sustituye** en su sitio: así se aplica una hoja recién subida, sin
577
+ `unloadCssFile` antes. `unloadCssFile`: `fileName` (sí); quita la hoja y relayouta; una que no está
578
+ cargada responde éxito.
579
+
580
+ **Medido (5.0.5.7dev, emulador):** `uploadFile` + `loadCssFile fileName=default-colors.css` cambia el
581
+ color de un botón en ~50 ms, sin relanzar. Un nombre que no existe: `result:false` con
582
+ `FileNotFoundException`. Sin app cargada contestan `App is not running` en `status`. En 5.0.5.5dev el
583
+ comando no existe (`Unknown command: loadCssFile`): ahí, las funciones de XOne por `runScript` + `refresh`
584
+ (tabla de arriba).
585
+
570
586
  ### `refresh` / `relayout` — solo Android
571
587
  En iOS las ramas existen en el dispatcher pero están **vacías**: no hacen nada.
572
588
 
@@ -359,6 +359,68 @@ function exigirAparato() {
359
359
  const cuerpo = crearZip(process.cwd(), [".xonecode", ".git"]);
360
360
  console.log(` ${(cuerpo.length / 1024).toFixed(0)} KB`);
361
361
 
362
+ const cliente = join(import.meta.dirname, "xone-hotswap");
363
+ /**
364
+ * **En `clave=valor`, que es lo único que el cliente entiende.**
365
+ *
366
+ * Esto mandaba `JSON.stringify(comando)` y se rompió ENTERO el día que el cliente dejó de
367
+ * aceptar JSON: el objeto se metía como NOMBRE del comando, el aparato contestaba
368
+ * `Unknown command: {…}` y el despliegue no lanzaba nada. Lanzar la app, pedir el árbol y
369
+ * capturar —las tres cosas que hace este paso— pasaban por aquí, así que se cayeron las
370
+ * tres a la vez, y en silencio: el script reintenta diez veces y acaba diciendo que el
371
+ * canal no levantó, que manda a mirar el puerto y el paquete en vez de al cliente.
372
+ *
373
+ * La conversión es la misma que hace el cliente al revés: cada campo que no es `command`
374
+ * sale como `clave=valor`, y un objeto o un array se serializan porque el tipado del
375
+ * cliente los reconoce por la forma.
376
+ */
377
+ const mandar = (comando) => {
378
+ const { command, ...resto } = comando;
379
+ const pares = Object.entries(resto).map(([k, v]) =>
380
+ `${k}=${typeof v === "object" && v !== null ? JSON.stringify(v) : String(v)}`,
381
+ );
382
+ // El hijo habla por el MISMO puerto que el túnel de arriba, aunque venga de `--puerto`.
383
+ return execFileSync(NODE, [cliente, command, ...pares], { encoding: "utf8", env: { ...process.env, HOTSWAP_URL: process.env.HOTSWAP_URL ?? `wss://127.0.0.1:${PUERTO}/hotswap` } }).trim();
384
+ };
385
+ const esperar = (segundos) => dormir(segundos);
386
+
387
+ /**
388
+ * **El servidor del framework, ANTES de subir: la subida va por él.** Medido en el emulador: con el
389
+ * framework parado (`am force-stop`) la subida moría con un error de TLS, porque el túnel acepta y no
390
+ * hay nadie detrás; el reinicio del paso 4 —lo único que lo arrancaba— llega DESPUÉS. Se pregunta una
391
+ * vez (`getAllElements` contesta «App is not running» con el framework vivo y sin app, y el cliente
392
+ * sale con error si no hay servidor); si no contesta, se arranca su pantalla y se espera a que conteste.
393
+ * Es la misma regla que Ejecutar (`lanzamientoEnMaquina.ts`).
394
+ */
395
+ const contesta = () => {
396
+ try {
397
+ // Con su stderr CALLADO: aquí que falle es la respuesta, no un error, y la línea del cliente
398
+ // («no se pudo hablar con el aparato») haría creer que el despliegue va mal.
399
+ execFileSync(NODE, [cliente, "getAllElements", "format=xone"], {
400
+ encoding: "utf8",
401
+ stdio: ["ignore", "pipe", "ignore"],
402
+ env: { ...process.env, HOTSWAP_URL: process.env.HOTSWAP_URL ?? `wss://127.0.0.1:${PUERTO}/hotswap` },
403
+ });
404
+ return true;
405
+ } catch {
406
+ return false;
407
+ }
408
+ };
409
+ if (!contesta()) {
410
+ console.log(" el servidor del framework no contesta: se arranca su pantalla");
411
+ adb("shell", "am", "start", "-n", ACTIVIDAD);
412
+ let arranco = false;
413
+ for (let intento = 1; intento <= 60 && !arranco; intento++) {
414
+ esperar(1);
415
+ arranco = contesta();
416
+ }
417
+ if (!arranco) {
418
+ console.error(`el servidor del framework no arrancó en 60 s. Comprueba que ${PAQUETE} está instalado.`);
419
+ process.exit(1);
420
+ }
421
+ console.log(" el servidor del framework ya contesta");
422
+ }
423
+
362
424
  console.log(`3/5 subiendo a ${app}`);
363
425
  const url = `https://127.0.0.1:${PUERTO}/file_upload?file=debug_app_update.zip&appName=${encodeURIComponent(app)}`;
364
426
  const respuesta = await fetch(url, {
@@ -385,30 +447,6 @@ function exigirAparato() {
385
447
  adb("shell", "am", "start", "-n", ACTIVIDAD);
386
448
 
387
449
  console.log("5/5 esperando al canal, lanzando y comprobando que está VIVA");
388
- const cliente = join(import.meta.dirname, "xone-hotswap");
389
- /**
390
- * **En `clave=valor`, que es lo único que el cliente entiende.**
391
- *
392
- * Esto mandaba `JSON.stringify(comando)` y se rompió ENTERO el día que el cliente dejó de
393
- * aceptar JSON: el objeto se metía como NOMBRE del comando, el aparato contestaba
394
- * `Unknown command: {…}` y el despliegue no lanzaba nada. Lanzar la app, pedir el árbol y
395
- * capturar —las tres cosas que hace este paso— pasaban por aquí, así que se cayeron las
396
- * tres a la vez, y en silencio: el script reintenta diez veces y acaba diciendo que el
397
- * canal no levantó, que manda a mirar el puerto y el paquete en vez de al cliente.
398
- *
399
- * La conversión es la misma que hace el cliente al revés: cada campo que no es `command`
400
- * sale como `clave=valor`, y un objeto o un array se serializan porque el tipado del
401
- * cliente los reconoce por la forma.
402
- */
403
- const mandar = (comando) => {
404
- const { command, ...resto } = comando;
405
- const pares = Object.entries(resto).map(([k, v]) =>
406
- `${k}=${typeof v === "object" && v !== null ? JSON.stringify(v) : String(v)}`,
407
- );
408
- // El hijo habla por el MISMO puerto que el túnel de arriba, aunque venga de `--puerto`.
409
- return execFileSync(NODE, [cliente, command, ...pares], { encoding: "utf8", env: { ...process.env, HOTSWAP_URL: process.env.HOTSWAP_URL ?? `wss://127.0.0.1:${PUERTO}/hotswap` } }).trim();
410
- };
411
- const esperar = (segundos) => dormir(segundos);
412
450
 
413
451
  /**
414
452
  * **El canal no está en pie justo después del reinicio**, y esto se descubrió corriéndolo:
@@ -13,9 +13,13 @@
13
13
  * devuelve a la versión anterior.
14
14
  * JavaScript (.js) → `loadIncludeFile` con compile=true. Subir el fichero NO basta,
15
15
  * y `loadCollection` tampoco lo recarga.
16
- * CSS, .ini, app.xml, mappings → relanzar la app (`launchApplication`). Medido: `setCssAttribute`,
17
- * `relayout`, `refresh` y `loadCollection` contestan `result:true`
18
- * y el color NO cambia; `loadIncludeFile` no admite css.
16
+ * CSS (.css) → el comando `loadCssFile` (framework 5.0.5.7dev en adelante): la
17
+ * sustituye y relayouta solo. En uno anterior, que contesta
18
+ * `Unknown command`, `runScript` con `appData.unloadCssFile` +
19
+ * `appData.loadCssFile` y un `refresh`. Medidos los dos: el color
20
+ * cambia SIN relanzar. Lo que no sirve, también medido:
21
+ * `setCssAttribute`, `relayout`, `refresh` o `loadCollection` solos.
22
+ * .ini, app.xml, mappings → relanzar la app (`launchApplication`): solo se leen al cargarla.
19
23
  *
20
24
  * **`result:true` es «aceptado», no «aplicado».** Lo que dice si funcionó es el árbol de
21
25
  * controles, y por eso el script lo pide al acabar. Un atributo que XOne no conoce tampoco da
@@ -202,10 +206,33 @@ if (cambiados.length === 0) {
202
206
  function clase(rel) {
203
207
  const ext = extname(rel).toLowerCase();
204
208
  if (ext === ".js") return "js";
209
+ if (ext === ".css") return "css";
205
210
  if (ext === ".xne") return /<coll[\s>]/.test(readFileSync(rel, "latin1")) ? "coleccion" : "relanzar";
206
211
  return "relanzar";
207
212
  }
208
213
 
214
+ /**
215
+ * Lo que se le da a `loadCollection`: el MISMO XML en UTF-8 y con el prólogo diciendo UTF-8.
216
+ * MEDIDO (5.0.5.5dev): con los bytes de un `.xne` en ISO-8859-15, cada tilde salía doble («Año»).
217
+ * La misma regla que `core/recargaEnCaliente.ts#xmlParaCargarEnMemoria`. Solo para memoria: a disco
218
+ * va el fichero tal cual, que es lo que el framework lee al relanzar.
219
+ */
220
+ function xmlEnUtf8(bytes) {
221
+ let texto;
222
+ try {
223
+ texto = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
224
+ } catch {
225
+ const cabeza = bytes.subarray(0, 256).toString("latin1");
226
+ const tabla = /encoding\s*=\s*["'][^"']*(8859-15|latin-?9)/i.test(cabeza) ? "iso-8859-15" : "windows-1252";
227
+ texto = new TextDecoder(tabla).decode(bytes);
228
+ }
229
+ texto = texto.replace(/^\uFEFF/, "").replace(
230
+ /^(\s*<\?xml[^?]*?encoding\s*=\s*)(["'])[^"']*\2/i,
231
+ (_t, antes, comilla) => `${antes}${comilla}UTF-8${comilla}`,
232
+ );
233
+ return Buffer.from(texto, "utf8");
234
+ }
235
+
209
236
  // 1. Subir a disco (siempre): lo que solo está en memoria se pierde al relanzar.
210
237
  const subidos = [];
211
238
  for (const rel of cambiados) {
@@ -226,6 +253,7 @@ for (const rel of cambiados) {
226
253
  const clases = new Map(subidos.map((f) => [f, clase(f)]));
227
254
  const hayQueRelanzar = [...clases.values()].includes("relanzar");
228
255
  const fallos = [];
256
+ let necesitaRefresh = false;
229
257
 
230
258
  if (hayQueRelanzar) {
231
259
  const r = mandar("launchApplication", { appName: app });
@@ -238,15 +266,42 @@ if (hayQueRelanzar) {
238
266
  } else {
239
267
  for (const [f, c] of clases) {
240
268
  if (c === "coleccion") {
241
- const r = mandar("loadCollection", { xmlNode: readFileSync(f).toString("base64"), encoding: "UTF-8" });
269
+ const r = mandar("loadCollection", { xmlNode: xmlEnUtf8(readFileSync(f)).toString("base64"), encoding: "UTF-8" });
242
270
  if (r.result !== true) fallos.push(`${f}: loadCollection ${r.exceptionMessage ?? r.status ?? "sin motivo"}`);
243
271
  else console.log(` ${f} → colección recargada en caliente`);
272
+ } else if (c === "css") {
273
+ // La codificación de SUS bytes: `loadCssFile` asume UTF-8 si no se le dice.
274
+ let tabla = "UTF-8";
275
+ try {
276
+ new TextDecoder("utf-8", { fatal: true }).decode(readFileSync(f));
277
+ } catch {
278
+ tabla = "windows-1252";
279
+ }
280
+ const nativo = mandar("loadCssFile", { fileName: f, encoding: tabla });
281
+ if (nativo.result === true) {
282
+ console.log(` ${f} → estilos recargados en caliente`);
283
+ } else if (/Unknown command/i.test(String(nativo.exceptionMessage ?? nativo.status ?? ""))) {
284
+ // Framework anterior a 5.0.5.7dev: las mismas funciones de XOne, por `runScript`, y un
285
+ // `refresh` (abajo) para que se pinte.
286
+ const script = `appData.unloadCssFile(${JSON.stringify(f)}); appData.loadCssFile(${JSON.stringify(f)}, ${JSON.stringify(tabla)}); return "ok";`;
287
+ const r = mandar("runScript", { scriptLanguage: "javascript", scriptText: Buffer.from(script, "utf8").toString("base64") });
288
+ if (r.result !== true) fallos.push(`${f}: loadCssFile ${r.exceptionMessage ?? r.status ?? "sin motivo"}`);
289
+ else {
290
+ necesitaRefresh = true;
291
+ console.log(` ${f} → estilos recargados en caliente (por runScript)`);
292
+ }
293
+ } else {
294
+ fallos.push(`${f}: loadCssFile ${nativo.exceptionMessage ?? nativo.status ?? "sin motivo"}`);
295
+ }
244
296
  } else {
245
297
  const r = mandar("loadIncludeFile", { file: f, language: "javascript", encoding: "UTF-8", compile: true });
246
298
  if (r.result !== true) fallos.push(`${f}: loadIncludeFile ${r.exceptionMessage ?? r.status ?? "sin motivo"}`);
247
299
  else console.log(` ${f} → JavaScript recargado`);
248
300
  }
249
301
  }
302
+ // Por `runScript` los estilos se ven en el SIGUIENTE pintado: sin este `refresh`, no cambia nada
303
+ // (medido). El comando `loadCssFile` relayouta él solo.
304
+ if (necesitaRefresh) mandar("refresh");
250
305
  dormir(1);
251
306
  }
252
307