xonecode 0.1.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 (187) hide show
  1. package/README.md +167 -0
  2. package/dist/agent/authEnDisco.js +56 -0
  3. package/dist/agent/authEnDisco.js.map +1 -0
  4. package/dist/agent/configEnDisco.js +109 -0
  5. package/dist/agent/configEnDisco.js.map +1 -0
  6. package/dist/agent/crearProyecto.js +34 -0
  7. package/dist/agent/crearProyecto.js.map +1 -0
  8. package/dist/agent/entorno.js +124 -0
  9. package/dist/agent/entorno.js.map +1 -0
  10. package/dist/agent/guionizado.js +53 -0
  11. package/dist/agent/guionizado.js.map +1 -0
  12. package/dist/agent/instantanea.js +129 -0
  13. package/dist/agent/instantanea.js.map +1 -0
  14. package/dist/agent/interrupts.js +83 -0
  15. package/dist/agent/interrupts.js.map +1 -0
  16. package/dist/agent/mensajes.js +24 -0
  17. package/dist/agent/mensajes.js.map +1 -0
  18. package/dist/agent/modelos.js +42 -0
  19. package/dist/agent/modelos.js.map +1 -0
  20. package/dist/agent/normalizar.js +20 -0
  21. package/dist/agent/normalizar.js.map +1 -0
  22. package/dist/agent/perfiles.js +103 -0
  23. package/dist/agent/perfiles.js.map +1 -0
  24. package/dist/agent/proyecto.js +107 -0
  25. package/dist/agent/proyecto.js.map +1 -0
  26. package/dist/agent/puente.js +142 -0
  27. package/dist/agent/puente.js.map +1 -0
  28. package/dist/agent/resumenDeTool.js +48 -0
  29. package/dist/agent/resumenDeTool.js.map +1 -0
  30. package/dist/agent/skills.js +65 -0
  31. package/dist/agent/skills.js.map +1 -0
  32. package/dist/agent/textoDeTool.js +113 -0
  33. package/dist/agent/textoDeTool.js.map +1 -0
  34. package/dist/agent/turnoReal.js +173 -0
  35. package/dist/agent/turnoReal.js.map +1 -0
  36. package/dist/agent/verificador.js +65 -0
  37. package/dist/agent/verificador.js.map +1 -0
  38. package/dist/agent/xoneAgent.js +106 -0
  39. package/dist/agent/xoneAgent.js.map +1 -0
  40. package/dist/bin.js +9 -0
  41. package/dist/bin.js.map +1 -0
  42. package/dist/cli/aprobar.js +82 -0
  43. package/dist/cli/aprobar.js.map +1 -0
  44. package/dist/cli/config.js +133 -0
  45. package/dist/cli/config.js.map +1 -0
  46. package/dist/cli/consola.js +346 -0
  47. package/dist/cli/consola.js.map +1 -0
  48. package/dist/cli/describe.js +53 -0
  49. package/dist/cli/describe.js.map +1 -0
  50. package/dist/cli/doctor.js +45 -0
  51. package/dist/cli/doctor.js.map +1 -0
  52. package/dist/cli/main.js +520 -0
  53. package/dist/cli/main.js.map +1 -0
  54. package/dist/cli/markdown.js +90 -0
  55. package/dist/cli/markdown.js.map +1 -0
  56. package/dist/cli/run.js +164 -0
  57. package/dist/cli/run.js.map +1 -0
  58. package/dist/cli/spinner.js +89 -0
  59. package/dist/cli/spinner.js.map +1 -0
  60. package/dist/cli/stdio.js +193 -0
  61. package/dist/cli/stdio.js.map +1 -0
  62. package/dist/cli/tema.js +40 -0
  63. package/dist/cli/tema.js.map +1 -0
  64. package/dist/cli/verify.js +62 -0
  65. package/dist/cli/verify.js.map +1 -0
  66. package/dist/core/bitacora.js +30 -0
  67. package/dist/core/bitacora.js.map +1 -0
  68. package/dist/core/config.js +236 -0
  69. package/dist/core/config.js.map +1 -0
  70. package/dist/core/contextos.js +56 -0
  71. package/dist/core/contextos.js.map +1 -0
  72. package/dist/core/deps.js +51 -0
  73. package/dist/core/deps.js.map +1 -0
  74. package/dist/core/diff.js +79 -0
  75. package/dist/core/diff.js.map +1 -0
  76. package/dist/core/esqueleto.js +366 -0
  77. package/dist/core/esqueleto.js.map +1 -0
  78. package/dist/core/events.js +2 -0
  79. package/dist/core/events.js.map +1 -0
  80. package/dist/core/modelos.js +85 -0
  81. package/dist/core/modelos.js.map +1 -0
  82. package/dist/core/notify.js +106 -0
  83. package/dist/core/notify.js.map +1 -0
  84. package/dist/core/ports.js +114 -0
  85. package/dist/core/ports.js.map +1 -0
  86. package/dist/core/turno.js +127 -0
  87. package/dist/core/turno.js.map +1 -0
  88. package/dist/vendor/hitl.js +103 -0
  89. package/dist/vendor/hitl.js.map +1 -0
  90. package/dist/vendor/skillLoaders/catalog.js +74 -0
  91. package/dist/vendor/skillLoaders/catalog.js.map +1 -0
  92. package/dist/vendor/tokenTracking.js +58 -0
  93. package/dist/vendor/tokenTracking.js.map +1 -0
  94. package/package.json +41 -0
  95. package/skills/xone-debugging/SKILL.md +52 -0
  96. package/skills/xone-debugging/references/faq.md +561 -0
  97. package/skills/xone-debugging/references/troubleshooting-y-glosario.md +429 -0
  98. package/skills/xone-development/SKILL.md +105 -0
  99. package/skills/xone-development/references/anti-patrones.md +94 -0
  100. package/skills/xone-development/references/css/atributos-por-categoria.md +509 -0
  101. package/skills/xone-development/references/css/buenas-practicas-y-parser.md +419 -0
  102. package/skills/xone-development/references/css/dinamicos-cascada-y-componentes.md +550 -0
  103. package/skills/xone-development/references/css/patrones-material-y-temas.md +1140 -0
  104. package/skills/xone-development/references/css/propiedades-y-herencia.md +885 -0
  105. package/skills/xone-development/references/css/selectores-unidades-colores.md +840 -0
  106. package/skills/xone-development/references/datos/appdata-referencia-ampliada.md +457 -0
  107. package/skills/xone-development/references/datos/appdata.md +611 -0
  108. package/skills/xone-development/references/datos/http-sqlmanager-y-crypto.md +720 -0
  109. package/skills/xone-development/references/datos/http.md +366 -0
  110. package/skills/xone-development/references/datos/oauth2-y-replica.md +156 -0
  111. package/skills/xone-development/references/device/biometria-imagedrawing-y-otros.md +544 -0
  112. package/skills/xone-development/references/device/objetos-de-dispositivo.md +583 -0
  113. package/skills/xone-development/references/device/systemsettings-referencia-ampliada.md +396 -0
  114. package/skills/xone-development/references/device/systemsettings-y-permisos.md +342 -0
  115. package/skills/xone-development/references/fundamentos/conceptos-clave.md +695 -0
  116. package/skills/xone-development/references/fundamentos/configuracion-app-xml-ini-mappings.md +668 -0
  117. package/skills/xone-development/references/fundamentos/errores-comunes.md +312 -0
  118. package/skills/xone-development/references/fundamentos/navegacion-convenciones-y-primer-proyecto.md +576 -0
  119. package/skills/xone-development/references/fundamentos/plataforma-y-anatomia-de-proyecto.md +387 -0
  120. package/skills/xone-development/references/indice-completo.md +77 -0
  121. package/skills/xone-development/references/javascript/coleccion-error-y-usuario.md +260 -0
  122. package/skills/xone-development/references/javascript/debugging-y-best-practices.md +245 -0
  123. package/skills/xone-development/references/javascript/metodos-de-los-controles.md +556 -0
  124. package/skills/xone-development/references/javascript/metodos-nativos-de-la-vista.md +114 -0
  125. package/skills/xone-development/references/javascript/motor-js-y-contexto-de-ejecucion.md +319 -0
  126. package/skills/xone-development/references/javascript/objeto-ai-llm-en-dispositivo.md +358 -0
  127. package/skills/xone-development/references/javascript/objetos-creables-a-m.md +527 -0
  128. package/skills/xone-development/references/javascript/objetos-creables-n-z.md +385 -0
  129. package/skills/xone-development/references/javascript/patrones-criticos-seguridad-y-rendimiento.md +595 -0
  130. package/skills/xone-development/references/javascript/patrones-de-navegacion-datos-y-codigo.md +751 -0
  131. package/skills/xone-development/references/javascript/patrones-de-ui-voz-integracion-y-seguridad.md +701 -0
  132. package/skills/xone-development/references/javascript/plantillas-y-funciones-utilitarias.md +647 -0
  133. package/skills/xone-development/references/javascript/self-y-dataobject.md +449 -0
  134. package/skills/xone-development/references/javascript/singletons-globales.md +361 -0
  135. package/skills/xone-development/references/javascript/ui-catalogo-de-metodos.md +464 -0
  136. package/skills/xone-development/references/javascript/ui-gps-camara-y-multimedia.md +506 -0
  137. package/skills/xone-development/references/javascript/ui-navegacion-mensajes-y-vista.md +422 -0
  138. package/skills/xone-development/references/resumen-js-datos-dispositivo.md +80 -0
  139. package/skills/xone-development/references/resumen-xml-y-css.md +74 -0
  140. package/skills/xone-development/references/tipos-de-prop.md +28 -0
  141. package/skills/xone-development/references/xml-ui/asfilter-visibilidad-eventos-y-macros.md +576 -0
  142. package/skills/xone-development/references/xml-ui/atributos-coll-group-frame.md +235 -0
  143. package/skills/xone-development/references/xml-ui/atributos-method-macro-script-event-app.md +244 -0
  144. package/skills/xone-development/references/xml-ui/atributos-prop.md +439 -0
  145. package/skills/xone-development/references/xml-ui/contents-y-macros.md +392 -0
  146. package/skills/xone-development/references/xml-ui/errores-comunes-xml.md +245 -0
  147. package/skills/xone-development/references/xml-ui/estructura-y-nodo-coll.md +326 -0
  148. package/skills/xone-development/references/xml-ui/eventos-ciclo-de-vida-e-interaccion.md +704 -0
  149. package/skills/xone-development/references/xml-ui/eventos-sistema-login-y-personalizados.md +944 -0
  150. package/skills/xone-development/references/xml-ui/layouts-herencia-y-buenas-practicas.md +618 -0
  151. package/skills/xone-development/references/xml-ui/mapas.md +685 -0
  152. package/skills/xone-development/references/xml-ui/mappings-y-colecciones-separadas.md +148 -0
  153. package/skills/xone-development/references/xml-ui/nodos-group-y-frame.md +666 -0
  154. package/skills/xone-development/references/xml-ui/patrones-de-pantalla.md +643 -0
  155. package/skills/xone-development/references/xml-ui/prop-atributos-y-condiciones.md +298 -0
  156. package/skills/xone-development/references/xml-ui/prop-tipos-basicos.md +493 -0
  157. package/skills/xone-development/references/xml-ui/prop-tipos-combos-y-controles.md +664 -0
  158. package/skills/xone-development/references/xml-ui/prop-tipos-listas-y-mapas.md +412 -0
  159. package/skills/xone-plan-builder/SKILL.md +183 -0
  160. package/skills/xone-plan-builder/agents/openai.yaml +5 -0
  161. package/skills/xone-plan-builder/references/TASKS-FORMAT.md +132 -0
  162. package/skills/xone-project-generator/SKILL.md +111 -0
  163. package/skills/xone-project-generator/references/canonical-sizes.md +292 -0
  164. package/skills/xone-project-generator/references/colecciones-base.md +16 -0
  165. package/skills/xone-project-generator/references/convenciones-de-nombres.md +16 -0
  166. package/skills/xone-project-generator/references/ejemplos-por-sector-y-prohibiciones.md +140 -0
  167. package/skills/xone-project-generator/references/fase-3-estilos-css.md +597 -0
  168. package/skills/xone-project-generator/references/fase-6-colecciones.md +762 -0
  169. package/skills/xone-project-generator/references/fase-7-asfilter-e-integraciones.md +142 -0
  170. package/skills/xone-project-generator/references/fase-7-entidades-y-estructura-de-pantalla.md +494 -0
  171. package/skills/xone-project-generator/references/fase-7-plantilla-consola.md +477 -0
  172. package/skills/xone-project-generator/references/fase-7-plantillas-de-pantalla.md +302 -0
  173. package/skills/xone-project-generator/references/fase-7-viewmodes-graficos-y-listas.md +681 -0
  174. package/skills/xone-project-generator/references/fase-7-viewmodes-mapa-y-calendario.md +479 -0
  175. package/skills/xone-project-generator/references/fases-0-2-analisis-y-modelo-de-datos.md +350 -0
  176. package/skills/xone-project-generator/references/fases-10-12-readmes-y-validacion.md +194 -0
  177. package/skills/xone-project-generator/references/fases-4-5-estructura-y-configuracion.md +587 -0
  178. package/skills/xone-project-generator/references/fases-8-9-eventos-y-javascript.md +861 -0
  179. package/skills/xone-project-generator/references/flujo-de-generacion.md +67 -0
  180. package/skills/xone-project-generator/references/plantillas-estandar.md +98 -0
  181. package/skills/xone-project-generator/references/tamanos-canonicos.md +49 -0
  182. package/skills/xone-review/SKILL.md +189 -0
  183. package/skills/xone-spec-builder/SKILL.md +235 -0
  184. package/skills/xone-spec-builder/agents/openai.yaml +5 -0
  185. package/skills/xone-spec-builder/references/ADR-FORMAT.md +55 -0
  186. package/skills/xone-spec-builder/references/CONTEXT-FORMAT.md +42 -0
  187. package/skills/xone-spec-builder/references/PLAN-FORMAT.md +120 -0
@@ -0,0 +1,457 @@
1
+ # XOne — appData: referencia ampliada
2
+
3
+ > Fuente: `xone/v2/xone-project-generator/references/xone-javascript-patterns-c-appdata-http.md` §2.2. Referencia de la skill; el índice está en [../../SKILL.md](../../SKILL.md).
4
+
5
+ Contenido: segunda redacción del corpus para appData, con ejemplos adicionales
6
+
7
+ ---
8
+
9
+ ### 2.2 Objeto `appData`
10
+
11
+ El objeto `appData` gestiona datos, configuración y estado de la aplicación.
12
+
13
+ #### 2.2.1 Colecciones
14
+
15
+ **Crear objetos — patrón preferido (constructor `new`):** toda colección de la aplicación está disponible como constructor global. Acepta un parámetro opcional con los valores iniciales (cada propiedad se asigna igual que `obj.PROP = valor`, disparando sus `onchange`):
16
+
17
+ ```javascript
18
+ // Crear un objeto nuevo con valores iniciales
19
+ let obj = new Clientes({ NOMBRE: "ACME", ACTIVO: 1 });
20
+
21
+ // El parámetro es opcional
22
+ let obj2 = new Clientes();
23
+
24
+ // Crear, añadir a la colección y guardar
25
+ let coll = appData.getCollection("Clientes");
26
+ let obj3 = new Clientes({ NOMBRE: "Nuevo registro" });
27
+ coll.addItem(obj3);
28
+ obj3.save();
29
+ ```
30
+
31
+ Cuándo NO aplica el constructor:
32
+
33
+ - **Contents anidados**: para crear líneas de un content usa `self.Contents("Lineas").createObject()` — crear desde el content establece el vínculo con el objeto padre; el constructor crea sobre la colección global y no vincula.
34
+ - **Nombre de colección dinámico**: si el nombre llega en una variable, usa el patrón legacy `appData.getCollection(nombre).createObject()`.
35
+
36
+ El constructor solo crea objetos. No existen métodos estáticos tipo ORM (`Usuarios.find(...)`, `Usuarios.create(...)`, `Usuarios.findById(...)`); las consultas se hacen con `appData.getCollection("Usuarios").findObject(...)` y demás métodos de la colección.
37
+
38
+ ```javascript
39
+ // Obtener una coleccion por nombre
40
+ let coll = appData.getCollection("NombreColeccion");
41
+
42
+ // Cargar todos los registros de la coleccion
43
+ coll.loadAll();
44
+
45
+ // Obtener cantidad de registros cargados
46
+ let nCount = coll.getCount();
47
+
48
+ // Obtener objeto por indice (base 0)
49
+ let obj = coll.get(0);
50
+
51
+ // Buscar un objeto con filtro SQL-like
52
+ let obj = coll.findObject("LOGIN = 'admin'");
53
+ let obj = coll.findObject("ID = 5 AND ACTIVO = 1");
54
+
55
+ // Buscar objeto por campo y valor
56
+ let obj = coll.getItem("MAP_CAMPO", valor);
57
+
58
+ // Crear un nuevo objeto en la coleccion (constructor preferido)
59
+ let newObj = new NombreColeccion({ MAP_NOMBRE: "Nuevo registro" });
60
+ coll.addItem(newObj);
61
+ newObj.save();
62
+
63
+ // Clonar coleccion (copia en memoria)
64
+ let collClone = coll.createClone();
65
+
66
+ // Aplicar filtro y recargar
67
+ coll.setFilter("ACTIVO = 1 AND TIPO = 'A'");
68
+ coll.clear();
69
+ coll.loadAll();
70
+
71
+ // Ordenar registros
72
+ coll.doSort("FECHA DESC");
73
+
74
+ // Borrar todos los registros de la BD
75
+ coll.browseDeleteAll();
76
+
77
+ // Guardar todos los registros modificados
78
+ coll.saveAll();
79
+ ```
80
+
81
+ #### 2.2.2 Autenticación
82
+
83
+ ```javascript
84
+ // Login
85
+ appData.login({
86
+ userName : "usuario",
87
+ password : "contraseña",
88
+ entryPoint : "MenuPrincipal",
89
+ onLoginSuccessful : function() {
90
+ ui.showToast("Bienvenido!");
91
+ },
92
+ onLoginFailed : function() {
93
+ ui.showToast("Credenciales incorrectas");
94
+ }
95
+ });
96
+
97
+ // Logout
98
+ appData.logout();
99
+
100
+ // Salir de la aplicación
101
+ appData.exit();
102
+ ```
103
+
104
+ #### 2.2.3 Rutas y Configuración
105
+
106
+ ```javascript
107
+ // Obtener ruta base de la aplicación
108
+ let sAppPath = appData.getAppPath();
109
+
110
+ // Obtener ruta de la carpeta files/
111
+ let sFilesPath = appData.getFilesPath();
112
+
113
+ // Obtener macro global del sistema
114
+ let sDeviceOs = appData.getGlobalMacro("##DEVICE_OS##");
115
+ let sVersion = appData.getGlobalMacro("##VERSION##");
116
+ let sFrameVersion = appData.getGlobalMacro("##FRAME_VERSION##");
117
+
118
+ // Obtener/Establecer macros personalizadas
119
+ let valor = appData.getGlobalMacro("##MI_MACRO##");
120
+ appData.setGlobalMacro("##MI_MACRO##", "mi_valor");
121
+
122
+ // Escribir mensaje de debug
123
+ appData.writeConsoleString("Debug: valor = " + valor);
124
+
125
+ // Limpiar errores acumulados
126
+ appData.error().clear();
127
+ ```
128
+
129
+ #### 2.2.4 Empresa Actual y Variables Globales de Sesión
130
+
131
+ ```javascript
132
+ // Obtener la empresa actual del usuario logueado
133
+ var empresa = appData.getCurrentEnterprise();
134
+
135
+ // Almacenar variables globales de sesion (persisten durante la sesion)
136
+ appData.getCurrentEnterprise().setVariable("LATITUD", latitud);
137
+ appData.getCurrentEnterprise().setVariable("LONGITUD", longitud);
138
+ appData.getCurrentEnterprise().setVariable("MODO_DARK", true);
139
+
140
+ // Recuperar variables globales de sesion
141
+ var lat = appData.getCurrentEnterprise().getVariable("LATITUD");
142
+ var lng = appData.getCurrentEnterprise().getVariable("LONGITUD");
143
+ var debug = appData.getCurrentEnterprise().getVariable("Debug");
144
+ ```
145
+
146
+ #### 2.2.5 Formateo y Utilidades Numéricas
147
+
148
+ ```javascript
149
+ // Convertir cualquier valor (fecha, número, booleano, …) a string siguiendo
150
+ // las reglas de XOne (formato de fecha de la empresa, decimales, etc.).
151
+ // Segundo parámetro opcional: flags numéricos.
152
+ var sqlStr = appData.variantToString(valor);
153
+ var sFecha = appData.variantToString(new Date());
154
+
155
+ // Redondeo seguro (importante para evitar errores de precision con decimales/euros)
156
+ var precio = appData.safeRound(vPendiente, 2);
157
+ var total = appData.safeRound(cantidad * precioUnitario, 2);
158
+ ```
159
+
160
+ #### 2.2.6 Cifrado y Descifrado (métodos de appData)
161
+
162
+ ```javascript
163
+ // Cifrar una cadena de texto
164
+ var cifrado = appData.encryptString("texto sensible");
165
+
166
+ // Descifrar una cadena previamente cifrada
167
+ var descifrado = appData.decryptString(cifrado);
168
+
169
+ // Variantes con flags opcionales
170
+ var cifrado2 = appData.encrypt("texto", "flags_opcionales");
171
+ var descifrado2 = appData.decrypt(cifrado2, "flags_opcionales");
172
+ ```
173
+
174
+ #### 2.2.7 Objeto error() - Control de Errores del Framework
175
+
176
+ El manejo de errores del framework se realiza a traves de `appData.error()`. Es fundamental verificar errores después de operaciones críticas.
177
+
178
+ ```javascript
179
+ // Verificar si hubo error
180
+ if (appData.error().getNumber() != 0) {
181
+ // Obtener descripción del error
182
+ var desc = appData.error().getDescription();
183
+
184
+ // Obtener SQL que fallo (si aplica)
185
+ var sql = appData.error().getFailedSql();
186
+
187
+ ui.msgBox("Error: " + desc, "ERROR", 0);
188
+ if (sql) {
189
+ ui.msgBox("SQL fallida: " + sql, "SQL", 0);
190
+ }
191
+
192
+ // Limpiar el error (importante: siempre limpiar después de manejar)
193
+ appData.error().clear();
194
+ }
195
+
196
+ // Patron completo: verificar error después de operación
197
+ var coll = appData.getCollection("ArticulosBuscar");
198
+ var filtroOriginal = coll.getFilter();
199
+ coll.setFilter("CODARTICULO=" + codigoArticulo);
200
+ coll.startBrowse();
201
+
202
+ if (appData.error().getNumber() != 0) {
203
+ ui.msgBox("Error: " + appData.error().getDescription(), "ERROR", 0);
204
+ appData.error().clear();
205
+ } else {
206
+ // Procesar resultados normalmente
207
+ var item = coll.getCurrentItem();
208
+ }
209
+
210
+ coll.setFilter(filtroOriginal);
211
+ coll.endBrowse();
212
+ ```
213
+
214
+ #### 2.2.8 Consola de Depuracion
215
+
216
+ ```javascript
217
+ // Escribir en la consola de depuracion
218
+ appData.writeConsoleString("App_log_xone->Mensaje de depuracion");
219
+ appData.writeConsoleString("Debug: valor = " + JSON.stringify(datos));
220
+
221
+ // Patron de depuracion condicional con variables de empresa
222
+ function ShowMessageDebug(mode, stmsg) {
223
+ if (appData.getCurrentEnterprise().getVariable("Debug") === true) {
224
+ if (mode === "msgbox")
225
+ ui.msgBox(stmsg, "App_log_xone!", 0);
226
+ else if (mode === "showtoast")
227
+ ui.showToast("App_log_xone->" + stmsg);
228
+ else if (mode === "consola")
229
+ appData.writeConsoleString("App_log_xone->" + stmsg);
230
+ }
231
+ }
232
+ ```
233
+
234
+ #### 2.2.9 Ejecución SQL Directa
235
+
236
+ **Firma:** `appData.executeSql(sql)`
237
+
238
+ - **Parámetros:** exactamente **1** — string SQL (no soporta placeholders `?` ni varargs; para parametrizar usar `SqlManager.doRawQuery()`).
239
+ - **Sustitución de macros:** sí, automática. Las macros del framework (`##USERID##`, `##NOW##`, etc.) se sustituyen en el SQL antes de ejecutarlo.
240
+ - **No usar para leer escalares**: para `SELECT` no devuelve el valor — devuelve un cursor inutilizable desde JS. Para leer datos usar `SqlManager.doRawQuery()` + cursor.
241
+ - **Uso recomendado:** sentencias de modificación (`UPDATE`/`INSERT`/`DELETE`) sobre la BBDD local, especialmente útil cuando hay cursores abiertos sobre la misma tabla y `CurrentItem` no puede modificarse desde la coll.
242
+ - **Seguridad:** **NUNCA concatenar input de usuario sin validar** (riesgo de SQL injection). Para consultas con parámetros usar `SqlManager.doRawQuery("... WHERE X=?", valor)`.
243
+
244
+ ```javascript
245
+ // === UPDATE/DELETE: uso típico de executeSql ===
246
+ // IDUSUARIO viene de self (entero validado); concatenación segura
247
+ appData.executeSql("UPDATE Gen_Rutas SET VISITADO=0 WHERE IDUSUARIO=" + self.IDUSUARIO);
248
+
249
+ // === SELECT: NO usar executeSql para leer escalares ===
250
+ // Esto NO devuelve el número de filas (devuelve un cursor inutilizable desde JS)
251
+ // var resultado = appData.executeSql("SELECT COUNT(*) FROM Gen_Clientes WHERE ACTIVO=1"); // MAL
252
+
253
+ // Forma correcta para leer datos: SqlManager + cursor
254
+ let sqlManager = new SqlManager();
255
+ try {
256
+ sqlManager.openDatabase({ databasePath: "gestion.db", useExistingConnection: true });
257
+ let cursor = sqlManager.doRawQuery("SELECT COUNT(*) AS N FROM Gen_Clientes WHERE ACTIVO=?", 1);
258
+ try {
259
+ cursor.moveToFirst();
260
+ var resultado = cursor.getInteger("N");
261
+ } finally {
262
+ cursor.close();
263
+ }
264
+ } finally {
265
+ sqlManager.close();
266
+ }
267
+ ```
268
+
269
+ #### 2.2.10 Control de Replicación
270
+
271
+ ```javascript
272
+ // Desactivar replicacion para operaciones de mantenimiento
273
+ appData.setIsReplicating(false);
274
+ // ... operaciones de mantenimiento que no deben sincronizarse
275
+ appData.setIsReplicating(true);
276
+
277
+ // Verificar estado de replicacion
278
+ var replicando = appData.isReplicating();
279
+ ```
280
+
281
+ #### 2.2.10b Otros métodos de appData
282
+
283
+ ```javascript
284
+ // === Conexiones ===
285
+ var conn = appData.getConnection("REMOTA"); // conexión por nombre
286
+ var s = appData.getConnString(); // string de la conexión principal
287
+
288
+ // === Diagnóstico ===
289
+ var nColls = appData.getCollectionCount(); // total de colecciones registradas
290
+ var conds = appData.getVisualConditions(); // string con las condiciones visuales activas
291
+ ```
292
+
293
+ #### 2.2.11 Objeto `replica`
294
+
295
+ Además del control desde `appData`, existe un objeto global `replica` con más control: iniciar/detener el servicio, procesar la cola manualmente, consultar métricas en tiempo real y fijar restricciones.
296
+
297
+ **Catálogo completo de métodos:**
298
+
299
+ | Método | Descripción |
300
+ | --- | --- |
301
+ | **start** | Iniciar el servicio de réplica. |
302
+ | **stop** | Detener la réplica. |
303
+ | **processReplicatorQueue(arg)** | Procesar cola pendiente. El argumento NO es un callback: acepta el `LiveSecureProvisioningResponse` del evento `live`, un `string` con el nombre de la app, o un `{databasePath, appName, taskId}`. Devuelve `boolean`. |
304
+ | **getLog** | Obtener log de la réplica. |
305
+ | **getDatabaseId** | ID de la base de datos. |
306
+ | **getHostname** | Nombre de host del servidor. |
307
+ | **getLicense** | Licencia. |
308
+ | **getMid** | MID (identificador del dispositivo). |
309
+ | **getRecordsPend** | Registros pendientes por enviar. |
310
+ | **getRecordsRX** / **getRecordsTX** | Registros recibidos/enviados en la sesión actual. |
311
+ | **getTotalRecordsRX** / **getTotalRecordsTX** | Totales desde el inicio. |
312
+ | **setRestriction** | Ajustar una restricción de réplica (p.ej. solo wifi). |
313
+ | **clearRestrictions** | Quitar restricciones actuales. |
314
+ | **clearAllRestrictions** | Quitar todas las restricciones. |
315
+
316
+ ```javascript
317
+ // Forzar replica manual y reportar metricas al terminar.
318
+ // El argumento es el liveResponse recibido en el evento live, o el nombre de la app.
319
+ function forzarReplica(liveResponse) {
320
+ ui.showWaitDialog("Sincronizando...");
321
+ let ok = replica.processReplicatorQueue(liveResponse);
322
+ ui.hideWaitDialog();
323
+
324
+ if (ok) {
325
+ ui.msgBox(
326
+ "Sincronización OK\n" +
327
+ "TX: " + replica.getRecordsTX() + " / " + replica.getTotalRecordsTX() + "\n" +
328
+ "RX: " + replica.getRecordsRX() + " / " + replica.getTotalRecordsRX() + "\n" +
329
+ "Pendientes: " + replica.getRecordsPend(),
330
+ "Replica", 0
331
+ );
332
+ } else {
333
+ ui.showToast("Error en la replica");
334
+ }
335
+ }
336
+ ```
337
+
338
+ #### 2.2.12 Carga dinámica de scripts (`loadIncludeFile`) y declaración preferida
339
+
340
+ > **Regla general:** declara los scripts en el nodo `<app>` siempre que puedas. Reserva `loadIncludeFile()` para casos especiales que **realmente** necesiten cargar el fichero en runtime (carga condicional según usuario/empresa, scripts descargados dinámicamente, parches en caliente, etc.).
341
+
342
+ **Forma preferida — declarar en el nodo `<app>` (estática):**
343
+
344
+ ```xml
345
+ <app default-language="javascript" ...>
346
+ <!-- functions.js se carga automáticamente, no hace falta declararlo -->
347
+
348
+ <!-- Forma <include>: encoding por defecto ISO-8859-1 -->
349
+ <include file="scripts/utils.js" />
350
+ <include url="scripts/api.js" encoding="UTF-8" />
351
+
352
+ <!-- Forma <script> (alias estilo HTML): encoding por defecto UTF-8 -->
353
+ <script src="scripts/auth.js" />
354
+ </app>
355
+ ```
356
+
357
+ Atributos comunes a `<include>` y `<script>`:
358
+
359
+ | Atributo | Alias | Obligatorio | Default | Descripción |
360
+ |---|---|---|---|---|
361
+ | `file` | `url`, `src` | sí | — | Ruta del fichero |
362
+ | `language` | — | no | `default-language` del `<app>` | `"javascript"` o `"vbscript"` |
363
+ | `encoding` | `charset` | no | `ISO-8859-1` en `<include>` · `UTF-8` en `<script>` | Codificación del fichero |
364
+ | `delay-compilation` | — | no | `false` | Difiere la compilación hasta el primer uso |
365
+ | `compile` | — | no | `true` | Si `false`, registra el fichero pero no lo compila |
366
+
367
+ **Forma dinámica — `appData.loadIncludeFile()` (solo casos especiales):**
368
+
369
+ ```javascript
370
+ appData.loadIncludeFile(fileName [, scriptLanguage] [, encoding] [, delayCompilation] [, compile]);
371
+ ```
372
+
373
+ | # | Nombre | Obligatorio | Valor por defecto | Descripción |
374
+ |---|---|---|---|---|
375
+ | 1 | `fileName` | sí | — | Ruta del fichero igual que en el nodo XML `<include>` |
376
+ | 2 | `scriptLanguage` | no | `default-language` del nodo `<app>` | `"javascript"` o `"vbscript"` |
377
+ | 3 | `encoding` | no | `"ISO-8859-1"` | Codificación del fichero. **Atención: el default NO es UTF-8** |
378
+ | 4 | `delayCompilation` | no | `false` | Si `true`, difiere la compilación hasta el primer uso |
379
+ | 5 | `compile` | no | `true` | Si `false`, registra el fichero pero no lo compila |
380
+
381
+ ```javascript
382
+ // Carga simple (asume default-language=javascript y encoding ISO-8859-1)
383
+ appData.loadIncludeFile("scripts/miModulo.js");
384
+
385
+ // Recomendado si el script tiene tildes/ñ guardadas como UTF-8
386
+ appData.loadIncludeFile("scripts/miModulo.js", "javascript", "UTF-8");
387
+ ```
388
+
389
+ **Advertencia sobre el encoding:** el valor por defecto es `ISO-8859-1`, no UTF-8. Si tu script contiene caracteres no-ASCII (tildes, ñ, símbolos) y está guardado como UTF-8, **se romperán** salvo que pases `"UTF-8"` explícitamente como tercer parámetro.
390
+
391
+ Llamadas posteriores al mismo fichero **no recompilan**: el motor reutiliza el bytecode ya cargado.
392
+
393
+ #### 2.2.13 Carga dinámica de CSS (`loadCssFile` / `unloadCssFile`) y declaración preferida
394
+
395
+ > **Regla general:** declara las hojas de estilo en el nodo `<app>` siempre que puedas. Reserva `loadCssFile()` / `unloadCssFile()` para casos especiales (cambio de tema por usuario, modo oscuro/claro en runtime, A/B testing visual, etc.).
396
+
397
+ **Forma preferida — declarar en el nodo `<app>` (estática):**
398
+
399
+ ```xml
400
+ <app ...>
401
+ <style url="estilos.css" />
402
+ <style url="temas/oscuro.css" encoding="UTF-8" conditions="##DEVICE_OS##='android'" strict-mode="true" />
403
+ </app>
404
+ ```
405
+
406
+ Atributos del nodo `<style>`:
407
+
408
+ | Atributo | Obligatorio | Default | Descripción |
409
+ |---|---|---|---|
410
+ | `url` | sí | — | Ruta del fichero CSS |
411
+ | `encoding` | no | (depende del fichero) | Codificación del fichero |
412
+ | `conditions` | no | (sin condición) | Condición de carga evaluada al iniciar (p. ej. macros globales) |
413
+ | `strict-mode` | no | `false` | Si `true`, exige CSS bien formado (avisa de errores como falta de `;`). En modo estricto hay que escapar `:` en valores: `title:Hola\:Mundo;` |
414
+
415
+ **Forma dinámica — `appData.loadCssFile()` / `appData.unloadCssFile()` (solo casos especiales):**
416
+
417
+ ```javascript
418
+ // Forma 1: argumentos posicionales
419
+ appData.loadCssFile(name [, encoding] [, conditions] [, strictMode]);
420
+
421
+ // Forma 2: objeto literal
422
+ appData.loadCssFile({ name: "...", encoding: "...", conditions: "...", strictMode: false });
423
+
424
+ // Descarga (un único argumento)
425
+ appData.unloadCssFile(name);
426
+ ```
427
+
428
+ Parámetros de `loadCssFile`:
429
+
430
+ | # / clave | Obligatorio | Valor por defecto | Descripción |
431
+ |---|---|---|---|
432
+ | `name` | sí | — | Ruta del fichero CSS |
433
+ | `encoding` | no | `"UTF-8"` | Codificación del fichero (¡distinto de `loadIncludeFile`!) |
434
+ | `conditions` | no | (sin condición) | Condición de carga |
435
+ | `strictMode` | no | `false` | Modo estricto de parseo |
436
+
437
+ ```javascript
438
+ // Ejemplo: cambio de tema en runtime
439
+ function aplicarTemaOscuro() {
440
+ appData.unloadCssFile("temas/claro.css");
441
+ appData.loadCssFile("temas/oscuro.css", "UTF-8");
442
+ // El framework limpia caches de propiedades y refresca la cascada
443
+ }
444
+ ```
445
+
446
+ `loadCssFile()` y `unloadCssFile()` invalidan automáticamente los caches internos de propiedades visuales (`ClearCollPropValueCaches()`), por lo que los cambios se reflejan en los siguientes renders sin reiniciar la app.
447
+
448
+ **Diferencia de encoding por defecto:**
449
+
450
+ | Método | Default encoding |
451
+ |---|---|
452
+ | `appData.loadCssFile()` | `"UTF-8"` |
453
+ | `appData.loadIncludeFile()` | `"ISO-8859-1"` |
454
+ | `<style>` en `<app>` | depende del fichero |
455
+ | `<include>` en `<app>` | `"ISO-8859-1"` |
456
+ | `<script>` en `<app>` | `"UTF-8"` |
457
+