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.
- package/README.md +167 -0
- package/dist/agent/authEnDisco.js +56 -0
- package/dist/agent/authEnDisco.js.map +1 -0
- package/dist/agent/configEnDisco.js +109 -0
- package/dist/agent/configEnDisco.js.map +1 -0
- package/dist/agent/crearProyecto.js +34 -0
- package/dist/agent/crearProyecto.js.map +1 -0
- package/dist/agent/entorno.js +124 -0
- package/dist/agent/entorno.js.map +1 -0
- package/dist/agent/guionizado.js +53 -0
- package/dist/agent/guionizado.js.map +1 -0
- package/dist/agent/instantanea.js +129 -0
- package/dist/agent/instantanea.js.map +1 -0
- package/dist/agent/interrupts.js +83 -0
- package/dist/agent/interrupts.js.map +1 -0
- package/dist/agent/mensajes.js +24 -0
- package/dist/agent/mensajes.js.map +1 -0
- package/dist/agent/modelos.js +42 -0
- package/dist/agent/modelos.js.map +1 -0
- package/dist/agent/normalizar.js +20 -0
- package/dist/agent/normalizar.js.map +1 -0
- package/dist/agent/perfiles.js +103 -0
- package/dist/agent/perfiles.js.map +1 -0
- package/dist/agent/proyecto.js +107 -0
- package/dist/agent/proyecto.js.map +1 -0
- package/dist/agent/puente.js +142 -0
- package/dist/agent/puente.js.map +1 -0
- package/dist/agent/resumenDeTool.js +48 -0
- package/dist/agent/resumenDeTool.js.map +1 -0
- package/dist/agent/skills.js +65 -0
- package/dist/agent/skills.js.map +1 -0
- package/dist/agent/textoDeTool.js +113 -0
- package/dist/agent/textoDeTool.js.map +1 -0
- package/dist/agent/turnoReal.js +173 -0
- package/dist/agent/turnoReal.js.map +1 -0
- package/dist/agent/verificador.js +65 -0
- package/dist/agent/verificador.js.map +1 -0
- package/dist/agent/xoneAgent.js +106 -0
- package/dist/agent/xoneAgent.js.map +1 -0
- package/dist/bin.js +9 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli/aprobar.js +82 -0
- package/dist/cli/aprobar.js.map +1 -0
- package/dist/cli/config.js +133 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/consola.js +346 -0
- package/dist/cli/consola.js.map +1 -0
- package/dist/cli/describe.js +53 -0
- package/dist/cli/describe.js.map +1 -0
- package/dist/cli/doctor.js +45 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/main.js +520 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/markdown.js +90 -0
- package/dist/cli/markdown.js.map +1 -0
- package/dist/cli/run.js +164 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/spinner.js +89 -0
- package/dist/cli/spinner.js.map +1 -0
- package/dist/cli/stdio.js +193 -0
- package/dist/cli/stdio.js.map +1 -0
- package/dist/cli/tema.js +40 -0
- package/dist/cli/tema.js.map +1 -0
- package/dist/cli/verify.js +62 -0
- package/dist/cli/verify.js.map +1 -0
- package/dist/core/bitacora.js +30 -0
- package/dist/core/bitacora.js.map +1 -0
- package/dist/core/config.js +236 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/contextos.js +56 -0
- package/dist/core/contextos.js.map +1 -0
- package/dist/core/deps.js +51 -0
- package/dist/core/deps.js.map +1 -0
- package/dist/core/diff.js +79 -0
- package/dist/core/diff.js.map +1 -0
- package/dist/core/esqueleto.js +366 -0
- package/dist/core/esqueleto.js.map +1 -0
- package/dist/core/events.js +2 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/modelos.js +85 -0
- package/dist/core/modelos.js.map +1 -0
- package/dist/core/notify.js +106 -0
- package/dist/core/notify.js.map +1 -0
- package/dist/core/ports.js +114 -0
- package/dist/core/ports.js.map +1 -0
- package/dist/core/turno.js +127 -0
- package/dist/core/turno.js.map +1 -0
- package/dist/vendor/hitl.js +103 -0
- package/dist/vendor/hitl.js.map +1 -0
- package/dist/vendor/skillLoaders/catalog.js +74 -0
- package/dist/vendor/skillLoaders/catalog.js.map +1 -0
- package/dist/vendor/tokenTracking.js +58 -0
- package/dist/vendor/tokenTracking.js.map +1 -0
- package/package.json +41 -0
- package/skills/xone-debugging/SKILL.md +52 -0
- package/skills/xone-debugging/references/faq.md +561 -0
- package/skills/xone-debugging/references/troubleshooting-y-glosario.md +429 -0
- package/skills/xone-development/SKILL.md +105 -0
- package/skills/xone-development/references/anti-patrones.md +94 -0
- package/skills/xone-development/references/css/atributos-por-categoria.md +509 -0
- package/skills/xone-development/references/css/buenas-practicas-y-parser.md +419 -0
- package/skills/xone-development/references/css/dinamicos-cascada-y-componentes.md +550 -0
- package/skills/xone-development/references/css/patrones-material-y-temas.md +1140 -0
- package/skills/xone-development/references/css/propiedades-y-herencia.md +885 -0
- package/skills/xone-development/references/css/selectores-unidades-colores.md +840 -0
- package/skills/xone-development/references/datos/appdata-referencia-ampliada.md +457 -0
- package/skills/xone-development/references/datos/appdata.md +611 -0
- package/skills/xone-development/references/datos/http-sqlmanager-y-crypto.md +720 -0
- package/skills/xone-development/references/datos/http.md +366 -0
- package/skills/xone-development/references/datos/oauth2-y-replica.md +156 -0
- package/skills/xone-development/references/device/biometria-imagedrawing-y-otros.md +544 -0
- package/skills/xone-development/references/device/objetos-de-dispositivo.md +583 -0
- package/skills/xone-development/references/device/systemsettings-referencia-ampliada.md +396 -0
- package/skills/xone-development/references/device/systemsettings-y-permisos.md +342 -0
- package/skills/xone-development/references/fundamentos/conceptos-clave.md +695 -0
- package/skills/xone-development/references/fundamentos/configuracion-app-xml-ini-mappings.md +668 -0
- package/skills/xone-development/references/fundamentos/errores-comunes.md +312 -0
- package/skills/xone-development/references/fundamentos/navegacion-convenciones-y-primer-proyecto.md +576 -0
- package/skills/xone-development/references/fundamentos/plataforma-y-anatomia-de-proyecto.md +387 -0
- package/skills/xone-development/references/indice-completo.md +77 -0
- package/skills/xone-development/references/javascript/coleccion-error-y-usuario.md +260 -0
- package/skills/xone-development/references/javascript/debugging-y-best-practices.md +245 -0
- package/skills/xone-development/references/javascript/metodos-de-los-controles.md +556 -0
- package/skills/xone-development/references/javascript/metodos-nativos-de-la-vista.md +114 -0
- package/skills/xone-development/references/javascript/motor-js-y-contexto-de-ejecucion.md +319 -0
- package/skills/xone-development/references/javascript/objeto-ai-llm-en-dispositivo.md +358 -0
- package/skills/xone-development/references/javascript/objetos-creables-a-m.md +527 -0
- package/skills/xone-development/references/javascript/objetos-creables-n-z.md +385 -0
- package/skills/xone-development/references/javascript/patrones-criticos-seguridad-y-rendimiento.md +595 -0
- package/skills/xone-development/references/javascript/patrones-de-navegacion-datos-y-codigo.md +751 -0
- package/skills/xone-development/references/javascript/patrones-de-ui-voz-integracion-y-seguridad.md +701 -0
- package/skills/xone-development/references/javascript/plantillas-y-funciones-utilitarias.md +647 -0
- package/skills/xone-development/references/javascript/self-y-dataobject.md +449 -0
- package/skills/xone-development/references/javascript/singletons-globales.md +361 -0
- package/skills/xone-development/references/javascript/ui-catalogo-de-metodos.md +464 -0
- package/skills/xone-development/references/javascript/ui-gps-camara-y-multimedia.md +506 -0
- package/skills/xone-development/references/javascript/ui-navegacion-mensajes-y-vista.md +422 -0
- package/skills/xone-development/references/resumen-js-datos-dispositivo.md +80 -0
- package/skills/xone-development/references/resumen-xml-y-css.md +74 -0
- package/skills/xone-development/references/tipos-de-prop.md +28 -0
- package/skills/xone-development/references/xml-ui/asfilter-visibilidad-eventos-y-macros.md +576 -0
- package/skills/xone-development/references/xml-ui/atributos-coll-group-frame.md +235 -0
- package/skills/xone-development/references/xml-ui/atributos-method-macro-script-event-app.md +244 -0
- package/skills/xone-development/references/xml-ui/atributos-prop.md +439 -0
- package/skills/xone-development/references/xml-ui/contents-y-macros.md +392 -0
- package/skills/xone-development/references/xml-ui/errores-comunes-xml.md +245 -0
- package/skills/xone-development/references/xml-ui/estructura-y-nodo-coll.md +326 -0
- package/skills/xone-development/references/xml-ui/eventos-ciclo-de-vida-e-interaccion.md +704 -0
- package/skills/xone-development/references/xml-ui/eventos-sistema-login-y-personalizados.md +944 -0
- package/skills/xone-development/references/xml-ui/layouts-herencia-y-buenas-practicas.md +618 -0
- package/skills/xone-development/references/xml-ui/mapas.md +685 -0
- package/skills/xone-development/references/xml-ui/mappings-y-colecciones-separadas.md +148 -0
- package/skills/xone-development/references/xml-ui/nodos-group-y-frame.md +666 -0
- package/skills/xone-development/references/xml-ui/patrones-de-pantalla.md +643 -0
- package/skills/xone-development/references/xml-ui/prop-atributos-y-condiciones.md +298 -0
- package/skills/xone-development/references/xml-ui/prop-tipos-basicos.md +493 -0
- package/skills/xone-development/references/xml-ui/prop-tipos-combos-y-controles.md +664 -0
- package/skills/xone-development/references/xml-ui/prop-tipos-listas-y-mapas.md +412 -0
- package/skills/xone-plan-builder/SKILL.md +183 -0
- package/skills/xone-plan-builder/agents/openai.yaml +5 -0
- package/skills/xone-plan-builder/references/TASKS-FORMAT.md +132 -0
- package/skills/xone-project-generator/SKILL.md +111 -0
- package/skills/xone-project-generator/references/canonical-sizes.md +292 -0
- package/skills/xone-project-generator/references/colecciones-base.md +16 -0
- package/skills/xone-project-generator/references/convenciones-de-nombres.md +16 -0
- package/skills/xone-project-generator/references/ejemplos-por-sector-y-prohibiciones.md +140 -0
- package/skills/xone-project-generator/references/fase-3-estilos-css.md +597 -0
- package/skills/xone-project-generator/references/fase-6-colecciones.md +762 -0
- package/skills/xone-project-generator/references/fase-7-asfilter-e-integraciones.md +142 -0
- package/skills/xone-project-generator/references/fase-7-entidades-y-estructura-de-pantalla.md +494 -0
- package/skills/xone-project-generator/references/fase-7-plantilla-consola.md +477 -0
- package/skills/xone-project-generator/references/fase-7-plantillas-de-pantalla.md +302 -0
- package/skills/xone-project-generator/references/fase-7-viewmodes-graficos-y-listas.md +681 -0
- package/skills/xone-project-generator/references/fase-7-viewmodes-mapa-y-calendario.md +479 -0
- package/skills/xone-project-generator/references/fases-0-2-analisis-y-modelo-de-datos.md +350 -0
- package/skills/xone-project-generator/references/fases-10-12-readmes-y-validacion.md +194 -0
- package/skills/xone-project-generator/references/fases-4-5-estructura-y-configuracion.md +587 -0
- package/skills/xone-project-generator/references/fases-8-9-eventos-y-javascript.md +861 -0
- package/skills/xone-project-generator/references/flujo-de-generacion.md +67 -0
- package/skills/xone-project-generator/references/plantillas-estandar.md +98 -0
- package/skills/xone-project-generator/references/tamanos-canonicos.md +49 -0
- package/skills/xone-review/SKILL.md +189 -0
- package/skills/xone-spec-builder/SKILL.md +235 -0
- package/skills/xone-spec-builder/agents/openai.yaml +5 -0
- package/skills/xone-spec-builder/references/ADR-FORMAT.md +55 -0
- package/skills/xone-spec-builder/references/CONTEXT-FORMAT.md +42 -0
- 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
|
+
|