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,366 @@
1
+ # XOne — $http: peticiones, futures, TLS y WebSocket
2
+
3
+ > Fuente: `xone/v2/xone-help-docs/topics/03c-js-appdata-http.md` §5. Referencia de la skill; el índice está en [../../SKILL.md](../../SKILL.md).
4
+
5
+ Contenido: §5 $http: GET, POST, PUT, DELETE, PATCH, descarga de fichero, futures y llamadas en paralelo, seguridad SSL/TLS (mutual TLS, pinning, allowedRootCas), proxy y WebSocket
6
+
7
+ ---
8
+
9
+ ## 5. Objeto Global `$http` - Peticiones HTTP
10
+
11
+ `$http` es el cliente HTTP de XOne. Todos los métodos devuelven un `Future` que permite lanzar peticiones en paralelo. Los callbacks son opcionales.
12
+
13
+ ### 5.1 Estructura del objeto request
14
+
15
+ ```javascript
16
+ let request = {
17
+ headers: {
18
+ "Content-Type" : "application/json",
19
+ "Authorization": "Bearer " + token,
20
+ "Accept-Encoding": "br" // Para Brotli
21
+ },
22
+ parameters: {
23
+ connectTimeout : 120000, // ms espera conexión
24
+ readTimeout : 120000, // ms espera respuesta
25
+ allowUnsafeCertificates: false, // true = acepta certs autofirmados (solo dev)
26
+ allowedRootCas : ["mi_ca.crt"], // CA propia en carpeta de la app
27
+ enablePinning : true, // Certificate pinning
28
+ },
29
+ // En GET: se añaden como ?clave=valor en la URL
30
+ // En POST/PUT/PATCH/DELETE: van como body JSON
31
+ // Puede ser objeto JS o string (para XML, etc.)
32
+ data: { campo1: "valor1", campo2: "valor2" },
33
+ // Certificado de cliente (mutual TLS)
34
+ privateKey : authenticationKey, // Obtenido con KeyStore
35
+ certificateChain: certificateChain, // Obtenido con KeyStore
36
+ // Volcar cadena de certificacion del servidor (solo depuracion)
37
+ dumpCertificateChainPath: "/sdcard/Download/"
38
+ };
39
+ ```
40
+
41
+ #### Caché de disco para offline (`cacheData`)
42
+
43
+ Opt-in por petición: guarda en disco la última respuesta exitosa y, si una petición posterior **falla por error de conexión o por un 5xx del servidor**, sirve esa respuesta cacheada de forma transparente para que la app siga funcionando offline. Los 4xx se tratan como respuesta real y van por el flujo de error normal. Aplica a `get`, `post`, `put`, `delete`, `patch` y `request`.
44
+
45
+ ```javascript
46
+ $http.post("https://api.ejemplo.com/datos", {
47
+ data : { id: 1 },
48
+ cacheData : true, // activa la caché de disco para esta petición
49
+ cacheTTL : 3600, // opcional: segundos de validez (sin él o <=0 = no caduca)
50
+ cacheSetting: { // opcional: ajustes finos de la clave de caché
51
+ // Campos del body (rutas con punto) que se excluyen de la clave para que dos
52
+ // llamadas que solo difieren en ellos compartan entrada. Si se pasa, REEMPLAZA
53
+ // por completo a los defaults ["transacid", "data.headers"].
54
+ ignoreBodyFields: ["transacid", "data.headers", "miCampoVolatil"]
55
+ }
56
+ },
57
+ function(sData, headers, statusCode, fromCache, fromCacheDate) {
58
+ // fromCache === true -> sData viene de la caché offline
59
+ // fromCacheDate -> Date de la última respuesta exitosa (solo si fromCache es true)
60
+ if (fromCache) {
61
+ ui.showToast("Mostrando datos offline de " + fromCacheDate);
62
+ }
63
+ let json = JSON.parse(sData);
64
+ },
65
+ function(nError, sErrorDesc) {
66
+ // Solo se llama si NO hay entrada válida en caché
67
+ }
68
+ );
69
+ ```
70
+
71
+ Notas:
72
+ - El callback de éxito recibe dos parámetros extra al final, `fromCache` (booleano) y `fromCacheDate` (Date). En un éxito de red normal `fromCache` es `false` y `fromCacheDate` viene `undefined`. Los callbacks que no los declaran los ignoran sin problema.
73
+ - Solo se cachean respuestas de datos (JSON/texto). Las descargas de fichero no se cachean.
74
+ - Sin `cacheData`, el comportamiento es exactamente el de siempre: no se escribe ni se lee nada.
75
+
76
+ ### 5.2 GET
77
+
78
+ ```javascript
79
+ let miObjeto = self; // Guardar contexto ANTES del callback asincrono
80
+
81
+ $http.get("https://api.ejemplo.com/datos", {
82
+ parameters: { connectTimeout: 120000, readTimeout: 120000 },
83
+ data: { pagina: 1, limite: 50 } // Se añaden como query string
84
+ },
85
+ function(sData, responseHeaders, nHttpStatusCode) {
86
+ let json = JSON.parse(sData);
87
+ miObjeto.MAP_RESULTADO = json.total;
88
+ ui.refreshValue("MAP_RESULTADO");
89
+ },
90
+ function(nError, sErrorDesc) {
91
+ ui.showToast("Error " + nError + ": " + sErrorDesc);
92
+ }
93
+ );
94
+
95
+ // GET con lectura de cabeceras de respuesta
96
+ $http.get("https://api.ejemplo.com", request,
97
+ function(sData, responseHeaders) {
98
+ let contentType = responseHeaders["Content-Type"];
99
+ let fecha = new Date(responseHeaders.Date).getDate();
100
+ },
101
+ function(nError, sErrorDesc) {}
102
+ );
103
+ ```
104
+
105
+ ### 5.3 POST
106
+
107
+ ```javascript
108
+ // POST con body JSON
109
+ ui.showWaitDialog("Enviando...");
110
+ $http.post("https://api.ejemplo.com/usuarios", {
111
+ headers : { "Content-Type": "application/json" },
112
+ parameters: { connectTimeout: 120000, readTimeout: 120000 },
113
+ data : { nombre: "Juan", activo: true }
114
+ },
115
+ function(sData, headers, nHttpStatusCode) {
116
+ let resultado = JSON.parse(sData);
117
+ ui.hideWaitDialog();
118
+ ui.showToast("Creado con ID: " + resultado.id);
119
+ },
120
+ function(nError, sErrorDesc) {
121
+ ui.hideWaitDialog();
122
+ ui.showToast("Error: " + sErrorDesc);
123
+ }
124
+ );
125
+
126
+ // POST con body XML (data como string)
127
+ $http.post("https://api.ejemplo.com/xml", {
128
+ headers: { "Content-Type": "application/xml" },
129
+ data : "<nota><de>Juan</de><para>Pedro</para></nota>"
130
+ },
131
+ function(sData) {},
132
+ function(nError, sErrorDesc) {}
133
+ );
134
+ ```
135
+
136
+ ### 5.4 PUT / DELETE / PATCH
137
+
138
+ ```javascript
139
+ let request = {
140
+ headers : { "Content-Type": "application/json" },
141
+ parameters: { connectTimeout: 120000, readTimeout: 120000 },
142
+ data : { campo: "valor" }
143
+ };
144
+
145
+ $http.put("https://api.ejemplo.com/recurso/1", request, successCb, errorCb);
146
+ $http.delete("https://api.ejemplo.com/recurso/1", request, successCb, errorCb);
147
+ $http.patch("https://api.ejemplo.com/recurso/1", request, successCb, errorCb);
148
+ ```
149
+
150
+ ### 5.5 Descarga de fichero
151
+
152
+ ```javascript
153
+ $http.download("https://ejemplo.com/documento.pdf", {},
154
+ function(sPath, headers, nHttpStatusCode) {
155
+ // sPath: ruta local donde se guardo el fichero descargado
156
+ ui.openFile(sPath);
157
+ },
158
+ function(nError, sMessage) {
159
+ ui.showToast("Error en descarga: " + sMessage);
160
+ }
161
+ );
162
+ ```
163
+
164
+ ### 5.6 Futures — llamadas en paralelo
165
+
166
+ Un `Future` es el objeto que devuelve cualquier método `$http`. Permite lanzar varias llamadas a la vez y recoger los resultados cuando todas terminen.
167
+
168
+ - **`future.getResult()`** — devuelve el cuerpo como **string**
169
+ - **`future.get()`** — devuelve el cuerpo **parseado a objeto JS** si es posible. **Preferible**
170
+ - **`future.cancel()`** — cancela la peticion
171
+
172
+ ```javascript
173
+ // Lanzar tres peticiones en paralelo
174
+ let future1 = $http.get("https://api.ejemplo.com/datos1", { data: { id: 1 } });
175
+ let future2 = $http.get("https://api.ejemplo.com/datos2", { data: { id: 2 } });
176
+ let future3 = $http.get("https://api.ejemplo.com/datos3", { data: { id: 3 } });
177
+
178
+ // getResult() bloquea hasta que cada peticion termina
179
+ let sValor1 = future1.getResult(); // string
180
+ let oValor2 = future2.get(); // objeto JS parseado (preferible)
181
+ let oValor3 = future3.get();
182
+
183
+ // Futures con callbacks (se ejecutan al terminar) y recogida posterior
184
+ let f1 = $http.get(url1, {},
185
+ function(sData) { ui.showToast("OK #1"); },
186
+ function(nErr, sDesc) { ui.showToast("Error #1"); }
187
+ );
188
+ let f2 = $http.get(url2, {},
189
+ function(sData) { ui.showToast("OK #2"); },
190
+ function(nErr, sDesc) { ui.showToast("Error #2"); }
191
+ );
192
+ // Esperar a que ambas terminen
193
+ let r1 = f1.getResult();
194
+ let r2 = f2.getResult();
195
+ ```
196
+
197
+ ### 5.7 Cancelar request
198
+
199
+ ```javascript
200
+ let future = $http.post("https://api.ejemplo.com/lenta", {},
201
+ function(sData) {},
202
+ function(nError, sErrorDesc) { /* se llama con error de cancelacion */ }
203
+ );
204
+ future.cancel();
205
+
206
+ // Patron: cancelar peticion anterior antes de lanzar nueva
207
+ var requestActual = null;
208
+ function buscarEnAPI(termino) {
209
+ if (requestActual) requestActual.cancel();
210
+ requestActual = $http.get(url + "?q=" + termino, {},
211
+ function(sData) { requestActual = null; procesarResultados(sData); },
212
+ function(nError, sDesc) { requestActual = null; }
213
+ );
214
+ }
215
+ ```
216
+
217
+ ### 5.8 Seguridad SSL/TLS
218
+
219
+ ```javascript
220
+ // Certificados autofirmados — SOLO desarrollo, nunca produccion
221
+ let request = {
222
+ parameters: { allowUnsafeCertificates: true, connectTimeout: 120000, readTimeout: 120000 }
223
+ };
224
+
225
+ // CA propia con certificate pinning
226
+ // El fichero .crt debe estar en la carpeta de la app
227
+ let request = {
228
+ parameters: {
229
+ allowedRootCas: ["mi_ca_root.crt"],
230
+ enablePinning : true,
231
+ connectTimeout: 120000, readTimeout: 120000
232
+ }
233
+ };
234
+
235
+ // Mutual TLS con certificado de cliente
236
+ // Soporta: pkcs12 (recomendado), bks, jks
237
+ ui.showWaitDialog("Conectando...");
238
+ try {
239
+ let keyStore = new KeyStore();
240
+ keyStore.open({ file: "cert_cliente.p12", type: "pkcs12", password: "" });
241
+ let request = {
242
+ headers : { "Content-Type": "application/json" },
243
+ parameters : { connectTimeout: 120000, readTimeout: 120000 },
244
+ data : { campo: "valor" },
245
+ privateKey : keyStore.getKey("alias"),
246
+ certificateChain: keyStore.getCertificateChain("alias")
247
+ };
248
+ $http.post("https://servidor-mutual-tls.com", request,
249
+ function(sData) { ui.hideWaitDialog(); },
250
+ function(nCode, sError) { ui.hideWaitDialog(); }
251
+ );
252
+ } catch(ex) {
253
+ ui.hideWaitDialog();
254
+ throw ex;
255
+ }
256
+
257
+ // Volcar cadena de certificacion para depuracion
258
+ $http.get("https://servidor.com", {
259
+ parameters: { connectTimeout: 120000, readTimeout: 120000 },
260
+ dumpCertificateChainPath: "/sdcard/Download/"
261
+ }, function(sData) {
262
+ ui.showToast("Certificados guardados en /sdcard/Download/");
263
+ }, function(nError, sErrorDesc) {});
264
+ ```
265
+
266
+ ### 5.9 Proxy
267
+
268
+ Configura un proxy global para toda la app, incluyendo XOneLive y el replicador.
269
+
270
+ ```javascript
271
+ // Establecer proxy
272
+ $http.setProxy({
273
+ host: "192.168.1.100",
274
+ port: 8080,
275
+ type: "http" // "http" o "socks"
276
+ // enabledHosts: ["api.ejemplo.com"]
277
+ // skipHosts : ["interno.ejemplo.com"]
278
+ });
279
+
280
+ // Eliminar proxy
281
+ $http.setProxy(null);
282
+ ```
283
+
284
+ ### 5.10 Cleartext HTTP
285
+
286
+ Por defecto Android solo permite HTTPS. Para saber si HTTP sin cifrar esta permitido:
287
+
288
+ ```javascript
289
+ let bPermitido = systemSettings.isClearTextTrafficAllowed();
290
+ ```
291
+
292
+ ### 5.11 WebSocket
293
+
294
+ ```javascript
295
+ let ws;
296
+ let dataObject = self; // Guardar referencia ANTES de los callbacks
297
+
298
+ function conectarWebSocket() {
299
+ let opciones = {
300
+ url : "wss://servidor.ejemplo.com/canal",
301
+ // protocol: "mi_protocolo",
302
+ // certificate: "servidor.crt",
303
+ // verifyWithSystemTrustManagers: true,
304
+ onOpen: function() {
305
+ ui.showToast("Conectado");
306
+ ws.send(JSON.stringify({ command: "login", user: "usuario" }));
307
+ },
308
+ onMessage: function(sData) {
309
+ dataObject.MAP_CHAT = dataObject.MAP_CHAT + sData + "\n";
310
+ ui.refreshValue("MAP_CHAT");
311
+ },
312
+ onError: function(error) {
313
+ ui.showToast("Error: " + error.message);
314
+ ws = null;
315
+ },
316
+ onClose: function() {
317
+ ui.showToast("Conexión cerrada");
318
+ ws = null;
319
+ }
320
+ };
321
+ if (ws) { ws.close(); ws = null; }
322
+ ws = new WebSocket(opciones);
323
+ }
324
+
325
+ function enviarMensaje(sTexto) {
326
+ if (!ws) throw "Conecte el WebSocket primero";
327
+ ws.send(JSON.stringify(sTexto));
328
+ }
329
+
330
+ function cerrarWebSocket() {
331
+ if (ws) { ws.close(); ws = null; }
332
+ }
333
+ ```
334
+
335
+ > **Nota**: Guardar `self` en una variable local (`dataObject`) antes de los callbacks. Dentro de `onMessage` y `onOpen`, `self` puede no estar disponible.
336
+
337
+ ### 5.12 loadFromJson / toJson
338
+
339
+ ```javascript
340
+ // Cargar datos en un OBJETO individual desde string JSON
341
+ let obj = new Productos();
342
+ obj.loadFromJson('{"ID": 1, "NOMBRE": "Tornillo", "PRECIO": 0.15}');
343
+
344
+ // Cargar datos en una COLECCION desde array JSON
345
+ let coll = appData.getCollection("Productos");
346
+ coll.loadFromJson('[{"ID": 1, "NOMBRE": "Tornillo"}, {"ID": 2, "NOMBRE": "Tuerca"}]');
347
+ let nTotal = coll.getCount(); // 2
348
+
349
+ // Serializar coleccion a array JS nativo
350
+ let jsArray = coll.toJson();
351
+ let sJson = JSON.stringify(jsArray, null, 4);
352
+
353
+ // Serializar objeto individual
354
+ let jsObj = obj.toJson();
355
+ let sObjJs = obj.toJsonString();
356
+
357
+ // Caso de uso tipico: recibir de API y cargar en coleccion
358
+ $http.get("https://api.ejemplo.com/productos", {},
359
+ function(sData) {
360
+ let coll = appData.getCollection("Productos");
361
+ coll.loadFromJson(sData);
362
+ },
363
+ function(nError, sErrorDesc) {}
364
+ );
365
+ ```
366
+
@@ -0,0 +1,156 @@
1
+ # XOne — OAuth2 y réplica
2
+
3
+ > Fuente: `xone/v2/xone-help-docs/topics/03c-js-appdata-http.md` §6–§7. Referencia de la skill; el índice está en [../../SKILL.md](../../SKILL.md).
4
+
5
+ Contenido: §6 OAuth2: autenticación completa · §7 objeto replica: sincronización
6
+
7
+ ---
8
+
9
+ ## 6. OAuth2 - Autenticación OAuth
10
+
11
+ ### 6.1 Autenticación OAuth2
12
+
13
+ ```javascript
14
+ function doAuthLogin() {
15
+ let strAuthorityUrl = "https://auth.miservidor.com/identity";
16
+ let strClientID = "mi_client_id";
17
+ let strClientSecret = "mi_client_secret";
18
+ let strPersistenceKey = "oauth_key";
19
+ let strRedirectUri = "com.miapp.oauth:/callback";
20
+
21
+ new OAuth2().withOptions({
22
+ authority : strAuthorityUrl,
23
+ clientID : strClientID,
24
+ clientSecret : strClientSecret,
25
+ scope : "openid profile",
26
+ responseType : "code id_token",
27
+ persistenceKey: strPersistenceKey,
28
+ redirectUri : strRedirectUri
29
+ }).authenticate({
30
+ onSuccess: function(result) {
31
+ console.log("OAuth2 login exitoso");
32
+ console.log(result);
33
+ appData.setGlobalMacro("##OAUTH_TOKEN##", result.access_token);
34
+ },
35
+ onError: function(err) {
36
+ console.log("OAuth2 error: " + err);
37
+ ui.showToast("Error de autenticación");
38
+ }
39
+ });
40
+ }
41
+ ```
42
+
43
+ ### 6.2 OAuth2 Logout
44
+
45
+ ```javascript
46
+ function doAuthLogout() {
47
+ new OAuth2().withOptions({
48
+ authority : "https://auth.miservidor.com/identity",
49
+ clientID : "mi_client_id",
50
+ clientSecret : "mi_client_secret",
51
+ scope : "openid profile",
52
+ persistenceKey: "oauth_key",
53
+ responseType : "code id_token",
54
+ redirectUri : "com.miapp.oauth:/callback"
55
+ }).logout();
56
+ }
57
+ ```
58
+
59
+ ### 6.3 Configuración Completa
60
+
61
+ | Parámetro | Tipo | Descripción |
62
+ |-----------|------|-------------|
63
+ | `authority` | String | URL del servidor de autorización |
64
+ | `clientID` | String | ID del cliente OAuth2 |
65
+ | `clientSecret` | String | Secreto del cliente |
66
+ | `scope` | String | Ambitos solicitados ("openid profile") |
67
+ | `responseType` | String | Tipo de respuesta ("code id_token") |
68
+ | `persistenceKey` | String | Clave para persistir la sesión |
69
+ | `redirectUri` | String | URI de redirección (esquema de URL de la app) |
70
+
71
+ ---
72
+
73
+ ## 7. Objeto `replica` - Sincronización
74
+
75
+ El objeto global `replica` gestiona la replicación/sincronización de datos y ficheros entre el dispositivo y el servidor central. También permite imponer restricciones de replica (p.ej. solo wifi) y consultar el estado.
76
+
77
+ **Catálogo completo de métodos:**
78
+
79
+ | Método | Descripción |
80
+ | --- | --- |
81
+ | **start** | Iniciar el servicio de réplica. |
82
+ | **stop** | Detener la réplica. |
83
+ | **processReplicatorQueue** | Procesar cola pendiente del replicador. Acepta tres formas de argumento (NO un callback): el `LiveSecureProvisioningResponse` recibido en el evento `live`, un `string` con el nombre de la app (resuelve `gestion.db` automáticamente), o un `{databasePath, appName, taskId}`. Devuelve `boolean` (true = cola vacía / éxito). |
84
+ | **getLog** | Obtener log de la réplica. |
85
+ | **getDatabaseId** | Obtener ID de la base de datos. |
86
+ | **getHostname** | Obtener nombre de host del servidor. |
87
+ | **getLicense** | Obtener licencia. |
88
+ | **getMid** | Obtener MID (identificador del dispositivo). |
89
+ | **getRecordsPend** | Obtener registros pendientes de enviar. |
90
+ | **getRecordsRX** | Obtener registros RX (recibidos en la sesión actual). |
91
+ | **getRecordsTX** | Obtener registros TX (enviados en la sesión actual). |
92
+ | **getTotalRecordsRX** | Total registros RX desde el inicio. |
93
+ | **getTotalRecordsTX** | Total registros TX desde el inicio. |
94
+ | **setRestriction** | Ajustar una restricción de réplica (p.ej. solo wifi). |
95
+ | **clearRestrictions** | Quitar las restricciones actuales. |
96
+ | **clearAllRestrictions** | Quitar todas las restricciones. |
97
+
98
+ ### 7.1 replica.processReplicatorQueue(arg)
99
+
100
+ El argumento NO es un callback. Es uno de:
101
+ - el objeto `LiveSecureProvisioningResponse` recibido en el evento `live` (forma típica);
102
+ - un `string` con el nombre de la app (resuelve internamente `gestion.db`);
103
+ - un objeto `{databasePath, appName, taskId}` con los tres datos manuales.
104
+
105
+ Devuelve `boolean` sincronamente. NO recibe función de progreso (cualquier callback se ignora silenciosamente).
106
+
107
+ ```javascript
108
+ // Forma típica: usar el objeto recibido en el evento live
109
+ function sincronizar(liveResponse) {
110
+ let bResult = replica.processReplicatorQueue(liveResponse);
111
+ if (bResult) {
112
+ ui.showToast("Sincronización completada");
113
+ } else {
114
+ ui.showToast("Error en sincronización");
115
+ }
116
+ }
117
+
118
+ // Forma alternativa: solo nombre de app
119
+ let bResult = replica.processReplicatorQueue("MiApp");
120
+
121
+ replica.start();
122
+
123
+ if (appData.isReplicating()) {
124
+ ui.showToast("Sincronización en curso...");
125
+ }
126
+ ```
127
+
128
+ ### 7.2 Flujo de Replica con sys-message
129
+
130
+ ```javascript
131
+ // Funcion llamada por el evento sys-message de la coleccion Empresas
132
+ function sysMessage(codigo, message) {
133
+ switch(codigo) {
134
+ case 1000:
135
+ // Actualización descargándose
136
+ break;
137
+ case 1001:
138
+ // Actualización aplicada
139
+ break;
140
+ case 1002:
141
+ // Todas las actualizaciones aplicadas
142
+ break;
143
+ case 1003:
144
+ // Provisionamiento seguro: replicar y cerrar
145
+ ui.msgBox("Se va a actualizar la BD. Se replicaran datos y cerrara la app.", "Mensaje", 0);
146
+ let bResult = replica.processReplicatorQueue(message); // 'message' es el liveResponse del sys-message
147
+ if (bResult) {
148
+ appData.exit();
149
+ } else {
150
+ ui.showToast("Error al procesar cola de salida. Reintente.");
151
+ }
152
+ break;
153
+ }
154
+ }
155
+ ```
156
+