@ssolis-ti/mcp-compra-agil 2.4.0 → 2.5.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 +21 -6
- package/dist/api/compra-agil-client.d.ts +29 -0
- package/dist/api/compra-agil-client.d.ts.map +1 -1
- package/dist/api/compra-agil-client.js +35 -0
- package/dist/api/compra-agil-client.js.map +1 -1
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -1
- package/dist/services/monitor.js +11 -1
- package/dist/services/monitor.js.map +1 -1
- package/dist/tools/analizar-precios-mercado.d.ts.map +1 -1
- package/dist/tools/analizar-precios-mercado.js +68 -14
- package/dist/tools/analizar-precios-mercado.js.map +1 -1
- package/dist/tools/auditar-desiertas.d.ts.map +1 -1
- package/dist/tools/auditar-desiertas.js +31 -8
- package/dist/tools/auditar-desiertas.js.map +1 -1
- package/dist/tools/buscar-compras.d.ts.map +1 -1
- package/dist/tools/buscar-compras.js +2 -0
- package/dist/tools/buscar-compras.js.map +1 -1
- package/dist/tools/detalle-compra.d.ts.map +1 -1
- package/dist/tools/detalle-compra.js +2 -0
- package/dist/tools/detalle-compra.js.map +1 -1
- package/dist/tools/detalle-oc.d.ts.map +1 -1
- package/dist/tools/detalle-oc.js +2 -0
- package/dist/tools/detalle-oc.js.map +1 -1
- package/dist/tools/documentos.d.ts.map +1 -1
- package/dist/tools/documentos.js +6 -0
- package/dist/tools/documentos.js.map +1 -1
- package/dist/tools/estadisticas-uso.d.ts.map +1 -1
- package/dist/tools/estadisticas-uso.js +2 -0
- package/dist/tools/estadisticas-uso.js.map +1 -1
- package/dist/tools/generar-borrador.d.ts +1 -1
- package/dist/tools/generar-borrador.d.ts.map +1 -1
- package/dist/tools/generar-borrador.js +35 -18
- package/dist/tools/generar-borrador.js.map +1 -1
- package/dist/tools/generar-informe.d.ts.map +1 -1
- package/dist/tools/generar-informe.js +5 -1
- package/dist/tools/generar-informe.js.map +1 -1
- package/dist/tools/monitorear-cambios.d.ts.map +1 -1
- package/dist/tools/monitorear-cambios.js +2 -0
- package/dist/tools/monitorear-cambios.js.map +1 -1
- package/dist/tools/radar-oportunidades.d.ts +5 -0
- package/dist/tools/radar-oportunidades.d.ts.map +1 -1
- package/dist/tools/radar-oportunidades.js +18 -4
- package/dist/tools/radar-oportunidades.js.map +1 -1
- package/dist/tools/verificar-hora.d.ts +13 -0
- package/dist/tools/verificar-hora.d.ts.map +1 -0
- package/dist/tools/verificar-hora.js +71 -0
- package/dist/tools/verificar-hora.js.map +1 -0
- package/dist/tools/verificar-oc.d.ts.map +1 -1
- package/dist/tools/verificar-oc.js +2 -0
- package/dist/tools/verificar-oc.js.map +1 -1
- package/dist/tools/verificar-ticket.js +1 -1
- package/dist/tools/verificar-ticket.js.map +1 -1
- package/dist/utils/concurrencia.d.ts +63 -0
- package/dist/utils/concurrencia.d.ts.map +1 -0
- package/dist/utils/concurrencia.js +122 -0
- package/dist/utils/concurrencia.js.map +1 -0
- package/dist/utils/error-handler.d.ts.map +1 -1
- package/dist/utils/error-handler.js +8 -0
- package/dist/utils/error-handler.js.map +1 -1
- package/dist/utils/fechas.d.ts +50 -0
- package/dist/utils/fechas.d.ts.map +1 -0
- package/dist/utils/fechas.js +77 -0
- package/dist/utils/fechas.js.map +1 -0
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +13 -2
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/ntp.d.ts +51 -0
- package/dist/utils/ntp.d.ts.map +1 -0
- package/dist/utils/ntp.js +121 -0
- package/dist/utils/ntp.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fechas.js","sourceRoot":"","sources":["../../src/utils/fechas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,wEAAwE;AACxE,MAAM,QAAQ,GAAG,mDAAmD,CAAC;AAErE;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,KAAgC;IAC9D,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;IAEnC,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE,CAAC;QACN,sEAAsE;QACtE,sEAAsE;QACtE,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QAC9B,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,QAAQ,GAAG,CAAC,CAAC;QACnD,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC;IAED,6DAA6D;IAC7D,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1B,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,cAAc,CAAC,KAAgC;IAC7D,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAC5B,qFAAqF;IACrF,uGAAuG;IACvG,wGAAwG,CAAC;AAE3G;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAgC;IAC5D,MAAM,CAAC,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,wEAAwE;IACxE,OAAO,CAAC,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,kBAAkB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAuBH,wBAAgB,YAAY,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,CAE9C;AAsCD,eAAO,MAAM,MAAM;iBACJ,MAAM,SAAS,OAAO;gBACvB,MAAM,SAAS,OAAO;gBACtB,MAAM,SAAS,OAAO;iBACrB,MAAM,SAAS,OAAO;CACpC,CAAC"}
|
package/dist/utils/logger.js
CHANGED
|
@@ -17,6 +17,8 @@ function formatTimestamp() {
|
|
|
17
17
|
return new Date().toISOString();
|
|
18
18
|
}
|
|
19
19
|
let mcpServer = null;
|
|
20
|
+
/** Evita repetir el aviso de fallo de envío en cada línea de log. */
|
|
21
|
+
let falloDeEnvioAvisado = false;
|
|
20
22
|
export function setMcpServer(server) {
|
|
21
23
|
mcpServer = server;
|
|
22
24
|
}
|
|
@@ -37,8 +39,17 @@ function log(level, message, data) {
|
|
|
37
39
|
level,
|
|
38
40
|
logger: 'mcp-compra-agil',
|
|
39
41
|
data: seguro,
|
|
40
|
-
}).catch(() => {
|
|
41
|
-
//
|
|
42
|
+
}).catch((e) => {
|
|
43
|
+
// No se interrumpe el flujo principal por un log que no se pudo enviar,
|
|
44
|
+
// pero tampoco se calla del todo: este `catch` mudo fue lo que ocultó
|
|
45
|
+
// durante meses que la capacidad `logging` no estaba declarada y que
|
|
46
|
+
// NINGUNA notificación llegaba al cliente. Se avisa una sola vez, a
|
|
47
|
+
// stderr, para que el aviso no se convierta en el ruido que denuncia.
|
|
48
|
+
if (!falloDeEnvioAvisado) {
|
|
49
|
+
falloDeEnvioAvisado = true;
|
|
50
|
+
console.error(`[${formatTimestamp()}] [WARN] No se pudieron enviar logs al cliente MCP ` +
|
|
51
|
+
`(se seguirá escribiendo a stderr). Causa: ${redact(String(e))}`);
|
|
52
|
+
}
|
|
42
53
|
});
|
|
43
54
|
}
|
|
44
55
|
}
|
package/dist/utils/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAIrC,MAAM,UAAU,GAA6B;IAC3C,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACT,CAAC;AAEF,MAAM,YAAY,GAAc,OAAO,CAAC,GAAG,CAAC,SAAsB,IAAI,MAAM,CAAC;AAE7E,SAAS,eAAe;IACtB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED,IAAI,SAAS,GAAQ,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAIrC,MAAM,UAAU,GAA6B;IAC3C,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACT,CAAC;AAEF,MAAM,YAAY,GAAc,OAAO,CAAC,GAAG,CAAC,SAAsB,IAAI,MAAM,CAAC;AAE7E,SAAS,eAAe;IACtB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED,IAAI,SAAS,GAAQ,IAAI,CAAC;AAC1B,qEAAqE;AACrE,IAAI,mBAAmB,GAAG,KAAK,CAAC;AAEhC,MAAM,UAAU,YAAY,CAAC,MAAW;IACtC,SAAS,GAAG,MAAM,CAAC;AACrB,CAAC;AAED,SAAS,GAAG,CAAC,KAAe,EAAE,OAAe,EAAE,IAAc;IAC3D,IAAI,UAAU,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO;IAEzD,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,MAAM,KAAK,CAAC,WAAW,EAAE,GAAG,CAAC;IACjE,yEAAyE;IACzE,gDAAgD;IAChD,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;IACrE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAE9B,+BAA+B;IAC/B,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,MAAM,EAAE,CAAC,CAAC;IAErC,6EAA6E;IAC7E,kEAAkE;IAClE,IAAI,SAAS,EAAE,CAAC;QACd,SAAS,CAAC,kBAAkB,CAAC;YAC3B,KAAK;YACL,MAAM,EAAE,iBAAiB;YACzB,IAAI,EAAE,MAAM;SACb,CAAC,CAAC,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE;YACtB,wEAAwE;YACxE,sEAAsE;YACtE,qEAAqE;YACrE,oEAAoE;YACpE,sEAAsE;YACtE,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBACzB,mBAAmB,GAAG,IAAI,CAAC;gBAC3B,OAAO,CAAC,KAAK,CACX,IAAI,eAAe,EAAE,qDAAqD;oBAC1E,6CAA6C,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CACjE,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,KAAK,EAAE,CAAC,GAAW,EAAE,IAAc,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC;IAC/D,IAAI,EAAE,CAAC,GAAW,EAAE,IAAc,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC;IAC7D,IAAI,EAAE,CAAC,GAAW,EAAE,IAAc,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC;IAC7D,KAAK,EAAE,CAAC,GAAW,EAAE,IAAc,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC;CAChE,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consulta la hora oficial de Chile contra el SHOA (Servicio Hidrográfico y
|
|
3
|
+
* Oceanográfico de la Armada), que es el organismo que la fija legalmente.
|
|
4
|
+
*
|
|
5
|
+
* ⚠ QUÉ PROBLEMA RESUELVE Y CUÁL NO: no dice nada sobre cómo interpretar las
|
|
6
|
+
* fechas ambiguas que entrega la API —de eso se encarga `utils/fechas.ts`—.
|
|
7
|
+
* Resuelve algo distinto y anterior: si el reloj de esta máquina está
|
|
8
|
+
* desviado, entonces `horas_restantes` y el puntaje de urgencia del radar
|
|
9
|
+
* están mal aunque la interpretación de la fecha sea perfecta, porque ambos
|
|
10
|
+
* se calculan restando la hora local. Un reloj adelantado media hora hace
|
|
11
|
+
* creer que un plazo está más cerca de lo que está; uno atrasado, lo
|
|
12
|
+
* contrario, y eso sí cuesta una licitación.
|
|
13
|
+
*
|
|
14
|
+
* Implementa lo mínimo de NTP (RFC 5905) sobre `dgram`, sin dependencias. El
|
|
15
|
+
* desfase se calcula con la fórmula del protocolo, que descuenta el viaje de
|
|
16
|
+
* ida y vuelta en vez de atribuirlo todo al reloj:
|
|
17
|
+
*
|
|
18
|
+
* desfase = ((T2 − T1) + (T3 − T4)) / 2
|
|
19
|
+
* demora = (T4 − T1) − (T3 − T2)
|
|
20
|
+
*
|
|
21
|
+
* T1 salida del cliente · T2 llegada al servidor
|
|
22
|
+
* T3 salida del servidor · T4 llegada al cliente
|
|
23
|
+
*/
|
|
24
|
+
/** Servidor oficial de la hora en Chile. */
|
|
25
|
+
export declare const SERVIDOR_NTP_CHILE = "ntp.shoa.cl";
|
|
26
|
+
export interface ResultadoNtp {
|
|
27
|
+
ok: true;
|
|
28
|
+
servidor: string;
|
|
29
|
+
/** Diferencia del reloj local respecto del oficial, en ms. Positivo = local atrasado. */
|
|
30
|
+
desfaseMs: number;
|
|
31
|
+
/** Ida y vuelta de la consulta, en ms. Una demora alta resta precisión al desfase. */
|
|
32
|
+
demoraMs: number;
|
|
33
|
+
horaOficial: string;
|
|
34
|
+
horaLocal: string;
|
|
35
|
+
}
|
|
36
|
+
export interface FalloNtp {
|
|
37
|
+
ok: false;
|
|
38
|
+
servidor: string;
|
|
39
|
+
motivo: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Pregunta la hora al SHOA. Nunca lanza: un fallo de red se devuelve como
|
|
43
|
+
* `{ ok: false }` porque muchas redes corporativas bloquean el UDP 123, y eso
|
|
44
|
+
* no debe impedir que el servidor MCP funcione.
|
|
45
|
+
*/
|
|
46
|
+
export declare function consultarHoraOficial(servidor?: string, timeoutMs?: number): Promise<ResultadoNtp | FalloNtp>;
|
|
47
|
+
/** Umbral a partir del cual el desfase puede alterar una decisión de plazo. */
|
|
48
|
+
export declare const DESFASE_PREOCUPANTE_MS = 60000;
|
|
49
|
+
/** Traduce el desfase a lo que significa para quien va a cotizar. */
|
|
50
|
+
export declare function interpretarDesfase(desfaseMs: number): string;
|
|
51
|
+
//# sourceMappingURL=ntp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ntp.d.ts","sourceRoot":"","sources":["../../src/utils/ntp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,4CAA4C;AAC5C,eAAO,MAAM,kBAAkB,gBAAgB,CAAC;AAKhD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,IAAI,CAAC;IACT,QAAQ,EAAE,MAAM,CAAC;IACjB,yFAAyF;IACzF,SAAS,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,KAAK,CAAC;IACV,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AASD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,GAAE,MAA2B,EACrC,SAAS,SAAO,GACf,OAAO,CAAC,YAAY,GAAG,QAAQ,CAAC,CAmElC;AAED,+EAA+E;AAC/E,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAE7C,qEAAqE;AACrE,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAY5D"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consulta la hora oficial de Chile contra el SHOA (Servicio Hidrográfico y
|
|
3
|
+
* Oceanográfico de la Armada), que es el organismo que la fija legalmente.
|
|
4
|
+
*
|
|
5
|
+
* ⚠ QUÉ PROBLEMA RESUELVE Y CUÁL NO: no dice nada sobre cómo interpretar las
|
|
6
|
+
* fechas ambiguas que entrega la API —de eso se encarga `utils/fechas.ts`—.
|
|
7
|
+
* Resuelve algo distinto y anterior: si el reloj de esta máquina está
|
|
8
|
+
* desviado, entonces `horas_restantes` y el puntaje de urgencia del radar
|
|
9
|
+
* están mal aunque la interpretación de la fecha sea perfecta, porque ambos
|
|
10
|
+
* se calculan restando la hora local. Un reloj adelantado media hora hace
|
|
11
|
+
* creer que un plazo está más cerca de lo que está; uno atrasado, lo
|
|
12
|
+
* contrario, y eso sí cuesta una licitación.
|
|
13
|
+
*
|
|
14
|
+
* Implementa lo mínimo de NTP (RFC 5905) sobre `dgram`, sin dependencias. El
|
|
15
|
+
* desfase se calcula con la fórmula del protocolo, que descuenta el viaje de
|
|
16
|
+
* ida y vuelta en vez de atribuirlo todo al reloj:
|
|
17
|
+
*
|
|
18
|
+
* desfase = ((T2 − T1) + (T3 − T4)) / 2
|
|
19
|
+
* demora = (T4 − T1) − (T3 − T2)
|
|
20
|
+
*
|
|
21
|
+
* T1 salida del cliente · T2 llegada al servidor
|
|
22
|
+
* T3 salida del servidor · T4 llegada al cliente
|
|
23
|
+
*/
|
|
24
|
+
import dgram from 'dgram';
|
|
25
|
+
/** Servidor oficial de la hora en Chile. */
|
|
26
|
+
export const SERVIDOR_NTP_CHILE = 'ntp.shoa.cl';
|
|
27
|
+
/** Segundos entre la época NTP (1900) y la de Unix (1970). */
|
|
28
|
+
const EPOCA_NTP_A_UNIX = 2_208_988_800;
|
|
29
|
+
/** Lee un timestamp NTP de 64 bits (32 de segundos + 32 de fracción) como ms Unix. */
|
|
30
|
+
function leerTimestamp(buf, offset) {
|
|
31
|
+
const segundos = buf.readUInt32BE(offset);
|
|
32
|
+
const fraccion = buf.readUInt32BE(offset + 4);
|
|
33
|
+
return (segundos - EPOCA_NTP_A_UNIX) * 1000 + Math.round((fraccion / 4_294_967_296) * 1000);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Pregunta la hora al SHOA. Nunca lanza: un fallo de red se devuelve como
|
|
37
|
+
* `{ ok: false }` porque muchas redes corporativas bloquean el UDP 123, y eso
|
|
38
|
+
* no debe impedir que el servidor MCP funcione.
|
|
39
|
+
*/
|
|
40
|
+
export function consultarHoraOficial(servidor = SERVIDOR_NTP_CHILE, timeoutMs = 5000) {
|
|
41
|
+
return new Promise((resolve) => {
|
|
42
|
+
const socket = dgram.createSocket('udp4');
|
|
43
|
+
let resuelto = false;
|
|
44
|
+
const terminar = (r) => {
|
|
45
|
+
if (resuelto)
|
|
46
|
+
return;
|
|
47
|
+
resuelto = true;
|
|
48
|
+
try {
|
|
49
|
+
socket.close();
|
|
50
|
+
}
|
|
51
|
+
catch { /* ya cerrado */ }
|
|
52
|
+
resolve(r);
|
|
53
|
+
};
|
|
54
|
+
const temporizador = setTimeout(() => terminar({
|
|
55
|
+
ok: false,
|
|
56
|
+
servidor,
|
|
57
|
+
motivo: `El servidor no respondió en ${timeoutMs} ms. Muchas redes corporativas bloquean el puerto UDP 123, que es el que usa NTP.`,
|
|
58
|
+
}), timeoutMs);
|
|
59
|
+
socket.on('message', (msg) => {
|
|
60
|
+
clearTimeout(temporizador);
|
|
61
|
+
const t4 = Date.now();
|
|
62
|
+
if (msg.length < 48) {
|
|
63
|
+
return terminar({ ok: false, servidor, motivo: 'La respuesta no tiene el tamaño de un paquete NTP.' });
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
const t1 = leerTimestamp(msg, 24); // Originate: el T1 que enviamos, devuelto por el servidor
|
|
67
|
+
const t2 = leerTimestamp(msg, 32); // Receive
|
|
68
|
+
const t3 = leerTimestamp(msg, 40); // Transmit
|
|
69
|
+
const desfaseMs = Math.round(((t2 - t1) + (t3 - t4)) / 2);
|
|
70
|
+
const demoraMs = Math.max(0, Math.round((t4 - t1) - (t3 - t2)));
|
|
71
|
+
terminar({
|
|
72
|
+
ok: true,
|
|
73
|
+
servidor,
|
|
74
|
+
desfaseMs,
|
|
75
|
+
demoraMs,
|
|
76
|
+
horaOficial: new Date(t4 + desfaseMs).toISOString(),
|
|
77
|
+
horaLocal: new Date(t4).toISOString(),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
terminar({ ok: false, servidor, motivo: `No se pudo leer la respuesta: ${String(e)}` });
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
socket.on('error', (e) => {
|
|
85
|
+
clearTimeout(temporizador);
|
|
86
|
+
terminar({ ok: false, servidor, motivo: `Error de red: ${e.message}` });
|
|
87
|
+
});
|
|
88
|
+
// Paquete de consulta: LI=0, VN=4, Mode=3 (cliente). El resto en cero.
|
|
89
|
+
const paquete = Buffer.alloc(48);
|
|
90
|
+
paquete[0] = 0x23;
|
|
91
|
+
// Se escribe T1 en Originate para que el servidor lo devuelva y el cálculo
|
|
92
|
+
// del desfase no dependa del reloj local más de lo imprescindible.
|
|
93
|
+
const t1 = Date.now();
|
|
94
|
+
paquete.writeUInt32BE(Math.floor(t1 / 1000) + EPOCA_NTP_A_UNIX, 40);
|
|
95
|
+
paquete.writeUInt32BE(Math.round(((t1 % 1000) / 1000) * 4_294_967_296), 44);
|
|
96
|
+
socket.send(paquete, 0, 48, 123, servidor, (e) => {
|
|
97
|
+
if (e) {
|
|
98
|
+
clearTimeout(temporizador);
|
|
99
|
+
terminar({ ok: false, servidor, motivo: `No se pudo enviar la consulta: ${e.message}` });
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/** Umbral a partir del cual el desfase puede alterar una decisión de plazo. */
|
|
105
|
+
export const DESFASE_PREOCUPANTE_MS = 60_000;
|
|
106
|
+
/** Traduce el desfase a lo que significa para quien va a cotizar. */
|
|
107
|
+
export function interpretarDesfase(desfaseMs) {
|
|
108
|
+
const abs = Math.abs(desfaseMs);
|
|
109
|
+
if (abs < 1000)
|
|
110
|
+
return 'El reloj de esta máquina está sincronizado con la hora oficial de Chile.';
|
|
111
|
+
if (abs < DESFASE_PREOCUPANTE_MS) {
|
|
112
|
+
return `El reloj está desviado ${(abs / 1000).toFixed(1)} s respecto de la hora oficial. Es una diferencia irrelevante para calcular plazos de cierre.`;
|
|
113
|
+
}
|
|
114
|
+
const minutos = (abs / 60_000).toFixed(1);
|
|
115
|
+
const sentido = desfaseMs > 0 ? 'atrasado' : 'adelantado';
|
|
116
|
+
const consecuencia = desfaseMs > 0
|
|
117
|
+
? 'las horas restantes que informa el radar son MAYORES que las reales, así que un plazo puede vencer antes de lo que parece'
|
|
118
|
+
: 'las horas restantes que informa el radar son MENORES que las reales';
|
|
119
|
+
return `⚠ El reloj de esta máquina está ${sentido} ${minutos} min respecto de la hora oficial de Chile. Como los plazos se calculan restando la hora local, ${consecuencia}. Conviene sincronizar el reloj del sistema antes de fiarse de "horas_restantes".`;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=ntp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ntp.js","sourceRoot":"","sources":["../../src/utils/ntp.ts"],"names":[],"mappings":"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"}
|