@hostwebhook/platform-contracts 0.1.0 → 0.3.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 +64 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/operadores.d.ts +60 -0
- package/dist/operadores.js +123 -0
- package/dist/servicios/almacenes-vectoriales.d.ts +105 -0
- package/dist/servicios/almacenes-vectoriales.js +26 -0
- package/dist/servicios/aprobaciones-pendientes.d.ts +207 -0
- package/dist/servicios/aprobaciones-pendientes.js +51 -0
- package/dist/servicios/avisos-en-vivo.d.ts +106 -0
- package/dist/servicios/avisos-en-vivo.js +60 -0
- package/dist/servicios/canal-de-stream.d.ts +78 -0
- package/dist/servicios/canal-de-stream.js +5 -0
- package/dist/servicios/conversaciones-del-chat.d.ts +139 -0
- package/dist/servicios/conversaciones-del-chat.js +51 -0
- package/dist/servicios/corridas-programadas.d.ts +29 -0
- package/dist/servicios/corridas-programadas.js +5 -0
- package/dist/servicios/credencial/permiso-sobre-credencial.d.ts +61 -0
- package/dist/servicios/credencial/permiso-sobre-credencial.js +42 -0
- package/dist/servicios/credenciales-del-gateway.d.ts +722 -0
- package/dist/servicios/credenciales-del-gateway.js +114 -0
- package/dist/servicios/cuentas-de-atlassian.d.ts +22 -0
- package/dist/servicios/cuentas-de-atlassian.js +5 -0
- package/dist/servicios/descarga-de-drive.d.ts +74 -0
- package/dist/servicios/descarga-de-drive.js +41 -0
- package/dist/servicios/ejecucion-de-ia.d.ts +81 -0
- package/dist/servicios/ejecucion-de-ia.js +39 -0
- package/dist/servicios/enlaces-de-flujo.d.ts +59 -0
- package/dist/servicios/enlaces-de-flujo.js +27 -0
- package/dist/servicios/ficheros-del-gateway.d.ts +210 -0
- package/dist/servicios/ficheros-del-gateway.js +8 -0
- package/dist/servicios/formas-compartidas.d.ts +57 -0
- package/dist/servicios/formas-compartidas.js +22 -0
- package/dist/servicios/historial-de-corridas.d.ts +75 -0
- package/dist/servicios/historial-de-corridas.js +7 -0
- package/dist/servicios/index.d.ts +57 -0
- package/dist/servicios/index.js +44 -0
- package/dist/servicios/limites-del-plan.d.ts +82 -0
- package/dist/servicios/limites-del-plan.js +41 -0
- package/dist/servicios/motor-de-ejecucion.d.ts +197 -0
- package/dist/servicios/motor-de-ejecucion.js +11 -0
- package/dist/servicios/plantillas-de-origen.d.ts +25 -0
- package/dist/servicios/plantillas-de-origen.js +5 -0
- package/dist/servicios/posts-sociales.d.ts +69 -0
- package/dist/servicios/posts-sociales.js +23 -0
- package/dist/servicios/registro-de-entregas.d.ts +93 -0
- package/dist/servicios/registro-de-entregas.js +46 -0
- package/dist/servicios/registro-de-eventos.d.ts +135 -0
- package/dist/servicios/registro-de-eventos.js +62 -0
- package/dist/servicios/restauracion-de-nodos.d.ts +53 -0
- package/dist/servicios/restauracion-de-nodos.js +4 -0
- package/dist/servicios/salud-del-webhook.d.ts +26 -0
- package/dist/servicios/salud-del-webhook.js +6 -0
- package/dist/servicios/secretos-de-firma.d.ts +26 -0
- package/dist/servicios/secretos-de-firma.js +5 -0
- package/dist/servicios/telemetria.d.ts +114 -0
- package/dist/servicios/telemetria.js +60 -0
- package/dist/servicios/trazas-de-llm.d.ts +79 -0
- package/dist/servicios/trazas-de-llm.js +23 -0
- package/dist/servicios/tuneles.d.ts +106 -0
- package/dist/servicios/tuneles.js +87 -0
- package/dist/servicios/workspace/acceso-al-recurso.d.ts +39 -0
- package/dist/servicios/workspace/acceso-al-recurso.js +5 -0
- package/dist/servicios/zona-horaria-del-usuario.d.ts +40 -0
- package/dist/servicios/zona-horaria-del-usuario.js +7 -0
- package/package.json +9 -3
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ALMACEN_DE_OBJETOS = exports.REGISTRO_DE_FICHEROS = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* ⚠️ Cadenas y no `Symbol`, igual que el resto de tokens de la Fase 2.
|
|
6
|
+
*/
|
|
7
|
+
exports.REGISTRO_DE_FICHEROS = 'REGISTRO_DE_FICHEROS';
|
|
8
|
+
exports.ALMACEN_DE_OBJETOS = 'ALMACEN_DE_OBJETOS';
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Las formas que varios contratos de esta carpeta necesitan, y que antes
|
|
3
|
+
* vivían fuera de ella.
|
|
4
|
+
*
|
|
5
|
+
* ## Por qué están aquí y no donde estaban
|
|
6
|
+
*
|
|
7
|
+
* Al sacar los contratos del monolito, tres de ellos apuntaban a tipos que se
|
|
8
|
+
* quedaban en la api o en el SDK. Un contrato que describe una frontera no
|
|
9
|
+
* puede depender de un lado de esa frontera: si `RegistroDeFicheros` habla de
|
|
10
|
+
* un `FileRef`, entonces `FileRef` **es parte del contrato**, no un detalle
|
|
11
|
+
* del gateway.
|
|
12
|
+
*
|
|
13
|
+
* Los tres eran `import type`, así que no había ciclo en tiempo de ejecución —
|
|
14
|
+
* pero sí en el de compilación, y sobre todo una mentira sobre quién define
|
|
15
|
+
* qué.
|
|
16
|
+
*
|
|
17
|
+
* ⚠️ Los originales pasan a re-exportar desde aquí. Copiarlos habría dejado dos
|
|
18
|
+
* definiciones que un día se escriben distinto, que es exactamente lo que este
|
|
19
|
+
* paquete existe para impedir.
|
|
20
|
+
*/
|
|
21
|
+
/** Un fichero ya registrado: lo que un nodo recibe para poder leerlo. */
|
|
22
|
+
export interface FileRef {
|
|
23
|
+
id: string;
|
|
24
|
+
key: string;
|
|
25
|
+
originalName: string;
|
|
26
|
+
mimeType: string;
|
|
27
|
+
size: number;
|
|
28
|
+
downloadUrl: string;
|
|
29
|
+
}
|
|
30
|
+
export type ChunkingStrategy = 'recursive' | 'fixed' | 'semantic';
|
|
31
|
+
/**
|
|
32
|
+
* `skipped` es un estado de primera y no un `failed` descafeinado: un paso que
|
|
33
|
+
* no llegó a correr porque el anterior falló no es lo mismo que uno que sí
|
|
34
|
+
* corrió y salió mal, y la pantalla necesita distinguirlos para enseñar dónde
|
|
35
|
+
* se cortó el flujo.
|
|
36
|
+
*/
|
|
37
|
+
export type RunStepStatus = 'success' | 'failed' | 'skipped';
|
|
38
|
+
export interface PasoEjecutado {
|
|
39
|
+
organizationId: string;
|
|
40
|
+
correlationId: string;
|
|
41
|
+
nodeId: string;
|
|
42
|
+
nodeName?: string;
|
|
43
|
+
nodeType?: string;
|
|
44
|
+
status: RunStepStatus;
|
|
45
|
+
startedAt: Date;
|
|
46
|
+
durationMs: number;
|
|
47
|
+
error?: string;
|
|
48
|
+
/** El origen de la corrida, para poder abrirla en la primera fila. */
|
|
49
|
+
sourceId?: string;
|
|
50
|
+
sourceName?: string;
|
|
51
|
+
workspaceId?: string;
|
|
52
|
+
entrada?: unknown;
|
|
53
|
+
salida?: unknown;
|
|
54
|
+
metadata?: Record<string, unknown>;
|
|
55
|
+
/** Cómo se disparó la corrida. Ausente = producción. */
|
|
56
|
+
modo?: 'pipeline';
|
|
57
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Las formas que varios contratos de esta carpeta necesitan, y que antes
|
|
4
|
+
* vivían fuera de ella.
|
|
5
|
+
*
|
|
6
|
+
* ## Por qué están aquí y no donde estaban
|
|
7
|
+
*
|
|
8
|
+
* Al sacar los contratos del monolito, tres de ellos apuntaban a tipos que se
|
|
9
|
+
* quedaban en la api o en el SDK. Un contrato que describe una frontera no
|
|
10
|
+
* puede depender de un lado de esa frontera: si `RegistroDeFicheros` habla de
|
|
11
|
+
* un `FileRef`, entonces `FileRef` **es parte del contrato**, no un detalle
|
|
12
|
+
* del gateway.
|
|
13
|
+
*
|
|
14
|
+
* Los tres eran `import type`, así que no había ciclo en tiempo de ejecución —
|
|
15
|
+
* pero sí en el de compilación, y sobre todo una mentira sobre quién define
|
|
16
|
+
* qué.
|
|
17
|
+
*
|
|
18
|
+
* ⚠️ Los originales pasan a re-exportar desde aquí. Copiarlos habría dejado dos
|
|
19
|
+
* definiciones que un día se escriben distinto, que es exactamente lo que este
|
|
20
|
+
* paquete existe para impedir.
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { PasoEjecutado as PasoDelSdk } from './formas-compartidas';
|
|
2
|
+
/**
|
|
3
|
+
* Lo que un nodo apunta en el historial de corridas. Dos cosas.
|
|
4
|
+
*
|
|
5
|
+
* ## Por qué
|
|
6
|
+
*
|
|
7
|
+
* Costura de la Fase 2. `nodes/` y `common/` importaban `history-runs/` así:
|
|
8
|
+
*
|
|
9
|
+
* 6 `HistoryRecorderService` el grabador
|
|
10
|
+
* 3 `paso-de-origen` un ayudante PURO, que se muda con ellos
|
|
11
|
+
* 5 `history-runs.module` cableado, desaparece con la mudanza
|
|
12
|
+
*
|
|
13
|
+
* `HistoryRecorderService` arrastra cuatro colecciones —`runs`, `run_steps`,
|
|
14
|
+
* `run_payloads`, `flow_versions`—, **su propia conexión de Mongo** a otra
|
|
15
|
+
* base, el almacén de payloads que se van a R2 y el sellado de versiones del
|
|
16
|
+
* flujo contra el lienzo. El historial es del gateway: es lo que la pantalla
|
|
17
|
+
* lee. El nodo sólo tiene que decir qué hizo.
|
|
18
|
+
*
|
|
19
|
+
* ## Dos métodos, y ya estaban medio declarados
|
|
20
|
+
*
|
|
21
|
+
* El SDK ya tiene `RegistradorDeHistorial` con `registrarPaso`, porque el
|
|
22
|
+
* ciclo de vida lo necesitaba y no podía depender de la api. Le falta
|
|
23
|
+
* `cerrar`, que es lo que usa quien ARRANCA una corrida y sabe cuándo acaba.
|
|
24
|
+
*
|
|
25
|
+
* Así que este contrato no inventa: reusa `PasoEjecutado` del SDK y le añade
|
|
26
|
+
* el único campo que la api tiene de más.
|
|
27
|
+
*
|
|
28
|
+
* ⚠️ Las dos definiciones habían divergido — la del SDK tiene `metadata` y le
|
|
29
|
+
* falta `esOrigen`; la de la api al revés. `extends` deja de multiplicar
|
|
30
|
+
* copias: los campos compartidos se declaran en un sitio.
|
|
31
|
+
*
|
|
32
|
+
* ## Cómo viaja
|
|
33
|
+
*
|
|
34
|
+
* ⚠️ Los dos métodos devuelven `void` y **no esperan ni lanzan**: por dentro
|
|
35
|
+
* hacen `void this.encolar(...).catch(...)`. Eso es deliberado y hay que
|
|
36
|
+
* conservarlo. Un nodo no puede fallar porque no se haya podido escribir una
|
|
37
|
+
* fila de historial, y menos aún quedarse esperando a que se escriba —
|
|
38
|
+
* `registrarPaso` corre en el camino caliente de CADA paso del pipeline.
|
|
39
|
+
*
|
|
40
|
+
* ⚠️ Y el orden importa: el grabador encola por `correlationId` para que los
|
|
41
|
+
* pasos de una corrida se escriban en orden y `cerrar` llegue el último. Una
|
|
42
|
+
* implementación por red que mandara los mensajes en paralelo cerraría
|
|
43
|
+
* corridas antes de tiempo, y el veredicto saldría mal.
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
* Un paso ejecutado.
|
|
47
|
+
*
|
|
48
|
+
* ⚠️ Extiende el del SDK en vez de copiarlo. `esOrigen` es lo único que la api
|
|
49
|
+
* necesita de más: marca el nodo que ARRANCÓ la corrida, que cuenta en
|
|
50
|
+
* `steps` pero no en el denominador del veredicto. Sin él, una corrida de una
|
|
51
|
+
* sola acción fallida se lee `partial` en vez de `failed`.
|
|
52
|
+
*/
|
|
53
|
+
export interface PasoEjecutado extends PasoDelSdk {
|
|
54
|
+
esOrigen?: boolean;
|
|
55
|
+
}
|
|
56
|
+
/** Quien anota lo que pasa en una corrida. */
|
|
57
|
+
export interface GrabadorDeHistorial {
|
|
58
|
+
/**
|
|
59
|
+
* ⚠️ `void`, no espera y no lanza. Corre en el camino caliente de cada
|
|
60
|
+
* paso: ver la nota de arriba.
|
|
61
|
+
*/
|
|
62
|
+
registrarPaso(paso: PasoEjecutado): void;
|
|
63
|
+
/**
|
|
64
|
+
* La corrida terminó.
|
|
65
|
+
*
|
|
66
|
+
* ⚠️ Tiene que llegar DESPUÉS de los pasos de esa misma `correlationId`. El
|
|
67
|
+
* grabador lo garantiza encolando por corrida; quien lo implemente por red
|
|
68
|
+
* tiene que garantizarlo también.
|
|
69
|
+
*/
|
|
70
|
+
cerrar(correlationId: string): void;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* ⚠️ Cadena y no `Symbol`, igual que el resto de tokens de la Fase 2.
|
|
74
|
+
*/
|
|
75
|
+
export declare const HISTORIAL_DE_CORRIDAS = "HISTORIAL_DE_CORRIDAS";
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Los contratos entre servicios: lo que el gateway y hw-nodes se piden.
|
|
3
|
+
*
|
|
4
|
+
* Cada fichero es **un token de cadena + la interfaz que ese token promete**.
|
|
5
|
+
* Nada de implementación: quien sirve el contrato vive en un servicio y quien
|
|
6
|
+
* lo consume en el otro, y este paquete es lo único que los dos comparten.
|
|
7
|
+
*
|
|
8
|
+
* ## Por qué aquí y no en `@hostwebhook/node-sdk`
|
|
9
|
+
*
|
|
10
|
+
* El SDK está **publicado para autores de nodos**: es ciclo de vida,
|
|
11
|
+
* reintentos, filtros e iteración. Estos veintiocho son fontanería interna
|
|
12
|
+
* entre dos servicios nuestros —`TUNELES_DE_LA_ORGANIZACION`,
|
|
13
|
+
* `SECRETOS_DE_FIRMA`, `REGISTRO_DE_ENTREGAS`—, y meterlos ahí los habría
|
|
14
|
+
* convertido en API pública: cada cambio pasaría a ser una pregunta de
|
|
15
|
+
* compatibilidad hacia fuera.
|
|
16
|
+
*
|
|
17
|
+
* ## ⚠️ Lo que NO entra aquí
|
|
18
|
+
*
|
|
19
|
+
* Lo mismo que dice el `index.ts` de arriba, y con un caso que se comprobó al
|
|
20
|
+
* mudarlos: `limites-del-plan` entra porque es la PREGUNTA («¿cuáles son los
|
|
21
|
+
* topes de esta organización?»), no los topes. Los valores —`PLAN_LIMITS`, los
|
|
22
|
+
* precios, los ids de Stripe— se quedan en el gateway, donde se pueden cambiar
|
|
23
|
+
* sin publicar un paquete.
|
|
24
|
+
*
|
|
25
|
+
* Y `credenciales-del-gateway` entra porque describe la forma de la pregunta,
|
|
26
|
+
* que está diseñada justo para que los secretos NO crucen a lo bruto. Ningún
|
|
27
|
+
* secreto vive aquí.
|
|
28
|
+
*/
|
|
29
|
+
export type { FileRef, ChunkingStrategy, RunStepStatus, PasoEjecutado as PasoEjecutadoDelSdk, } from './formas-compartidas';
|
|
30
|
+
export * from './almacenes-vectoriales';
|
|
31
|
+
export * from './aprobaciones-pendientes';
|
|
32
|
+
export * from './avisos-en-vivo';
|
|
33
|
+
export * from './canal-de-stream';
|
|
34
|
+
export * from './conversaciones-del-chat';
|
|
35
|
+
export * from './corridas-programadas';
|
|
36
|
+
export * from './credencial/permiso-sobre-credencial';
|
|
37
|
+
export * from './credenciales-del-gateway';
|
|
38
|
+
export * from './cuentas-de-atlassian';
|
|
39
|
+
export * from './descarga-de-drive';
|
|
40
|
+
export * from './ejecucion-de-ia';
|
|
41
|
+
export * from './enlaces-de-flujo';
|
|
42
|
+
export * from './ficheros-del-gateway';
|
|
43
|
+
export * from './historial-de-corridas';
|
|
44
|
+
export * from './limites-del-plan';
|
|
45
|
+
export * from './motor-de-ejecucion';
|
|
46
|
+
export * from './plantillas-de-origen';
|
|
47
|
+
export * from './posts-sociales';
|
|
48
|
+
export * from './registro-de-entregas';
|
|
49
|
+
export * from './registro-de-eventos';
|
|
50
|
+
export * from './restauracion-de-nodos';
|
|
51
|
+
export * from './salud-del-webhook';
|
|
52
|
+
export * from './secretos-de-firma';
|
|
53
|
+
export * from './telemetria';
|
|
54
|
+
export * from './trazas-de-llm';
|
|
55
|
+
export * from './tuneles';
|
|
56
|
+
export * from './workspace/acceso-al-recurso';
|
|
57
|
+
export * from './zona-horaria-del-usuario';
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./almacenes-vectoriales"), exports);
|
|
18
|
+
__exportStar(require("./aprobaciones-pendientes"), exports);
|
|
19
|
+
__exportStar(require("./avisos-en-vivo"), exports);
|
|
20
|
+
__exportStar(require("./canal-de-stream"), exports);
|
|
21
|
+
__exportStar(require("./conversaciones-del-chat"), exports);
|
|
22
|
+
__exportStar(require("./corridas-programadas"), exports);
|
|
23
|
+
__exportStar(require("./credencial/permiso-sobre-credencial"), exports);
|
|
24
|
+
__exportStar(require("./credenciales-del-gateway"), exports);
|
|
25
|
+
__exportStar(require("./cuentas-de-atlassian"), exports);
|
|
26
|
+
__exportStar(require("./descarga-de-drive"), exports);
|
|
27
|
+
__exportStar(require("./ejecucion-de-ia"), exports);
|
|
28
|
+
__exportStar(require("./enlaces-de-flujo"), exports);
|
|
29
|
+
__exportStar(require("./ficheros-del-gateway"), exports);
|
|
30
|
+
__exportStar(require("./historial-de-corridas"), exports);
|
|
31
|
+
__exportStar(require("./limites-del-plan"), exports);
|
|
32
|
+
__exportStar(require("./motor-de-ejecucion"), exports);
|
|
33
|
+
__exportStar(require("./plantillas-de-origen"), exports);
|
|
34
|
+
__exportStar(require("./posts-sociales"), exports);
|
|
35
|
+
__exportStar(require("./registro-de-entregas"), exports);
|
|
36
|
+
__exportStar(require("./registro-de-eventos"), exports);
|
|
37
|
+
__exportStar(require("./restauracion-de-nodos"), exports);
|
|
38
|
+
__exportStar(require("./salud-del-webhook"), exports);
|
|
39
|
+
__exportStar(require("./secretos-de-firma"), exports);
|
|
40
|
+
__exportStar(require("./telemetria"), exports);
|
|
41
|
+
__exportStar(require("./trazas-de-llm"), exports);
|
|
42
|
+
__exportStar(require("./tuneles"), exports);
|
|
43
|
+
__exportStar(require("./workspace/acceso-al-recurso"), exports);
|
|
44
|
+
__exportStar(require("./zona-horaria-del-usuario"), exports);
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Los topes del plan que un nodo necesita saber. Nada más.
|
|
3
|
+
*
|
|
4
|
+
* ## Por qué
|
|
5
|
+
*
|
|
6
|
+
* Costura de la Fase 2. `src/nodes/` importaba `plans/` 64 veces, y ese
|
|
7
|
+
* número engaña como engañaban los otros:
|
|
8
|
+
*
|
|
9
|
+
* 48 `PlansModule` cableado de DI, desaparece con la mudanza
|
|
10
|
+
* 13 `PlansService` de los que TODOS llaman UN método
|
|
11
|
+
* 3 helpers sueltos `managedStorageUsage`, `enMegas`, `registerManagedStore`
|
|
12
|
+
*
|
|
13
|
+
* Los trece llaman `getOrgPlanLimits` y ninguno llama nada más. `PlansService`
|
|
14
|
+
* arrastra 13 ficheros del gateway —`plan.constants`, la entidad de usuario,
|
|
15
|
+
* la de organización— y con eso esos trece servicios de nodo no se pueden
|
|
16
|
+
* mudar a `hw-nodes`.
|
|
17
|
+
*
|
|
18
|
+
* ## Lo que lee cada uno, medido
|
|
19
|
+
*
|
|
20
|
+
* Del resultado se desestructura `{ limits, tier }`, y de `limits` se leen
|
|
21
|
+
* SEIS campos. Son los que están abajo. No se copia la forma entera de
|
|
22
|
+
* `PLAN_LIMITS` —que tiene muchos más— por la misma doctrina que el resto de
|
|
23
|
+
* contratos de esta fase: la superficie USADA, no la entidad completa.
|
|
24
|
+
*
|
|
25
|
+
* ⚠️ Y aquí el compilador es el verificador. Si me dejé un campo fuera, el
|
|
26
|
+
* sitio que lo lee no compila — no hace falta creerse la medición.
|
|
27
|
+
*
|
|
28
|
+
* ## Cuando esto cruce una red
|
|
29
|
+
*
|
|
30
|
+
* Bien: son números y una cadena. A diferencia de la costura del motor —que
|
|
31
|
+
* pasaba documentos de Mongoose vivos— y de la de Drive —donde `auth` es un
|
|
32
|
+
* objeto con métodos—, esto viaja tal cual.
|
|
33
|
+
*/
|
|
34
|
+
/** Los topes que un nodo consulta antes de aceptar una configuración. */
|
|
35
|
+
export interface TopesDelPlan {
|
|
36
|
+
/** Reintentos máximos de una entrega. */
|
|
37
|
+
maxRetries: number;
|
|
38
|
+
/** Segundos entre reintentos. */
|
|
39
|
+
maxRetryDelaySeconds: number;
|
|
40
|
+
/**
|
|
41
|
+
* El TECHO del backoff, que no es lo mismo que el de arriba.
|
|
42
|
+
*
|
|
43
|
+
* ⚠️ Octavo campo, y otra vez lo encontró el COMPILADOR y no mi medición.
|
|
44
|
+
* Se parecen tanto en el nombre que es fácil dar uno por el otro: uno es el
|
|
45
|
+
* hueco entre reintentos y éste el límite al que el backoff deja de crecer.
|
|
46
|
+
* Confundirlos hace que una organización reintente con el calendario de
|
|
47
|
+
* otra, y nada lo dice.
|
|
48
|
+
*/
|
|
49
|
+
maxRetryDelayCapSeconds: number;
|
|
50
|
+
/** Techo del nodo de espera. */
|
|
51
|
+
maxDelaySeconds: number;
|
|
52
|
+
/** Minutos que puede esperar una aprobación. */
|
|
53
|
+
maxApprovalTimeoutMinutes: number;
|
|
54
|
+
/** Minutos que puede esperar un merge a sus ramas. */
|
|
55
|
+
maxMergeTimeoutMinutes: number;
|
|
56
|
+
/** Cada cuánto, como mínimo, puede dispararse un cron. */
|
|
57
|
+
minCronIntervalMinutes: number;
|
|
58
|
+
/**
|
|
59
|
+
* Cuántas veces puede pasar una corrida por el mismo nodo.
|
|
60
|
+
*
|
|
61
|
+
* ⚠️ Éste se me escapó al medir y lo encontró el COMPILADOR: se lee con
|
|
62
|
+
* encadenado opcional (`?.limits?.maxNodeCycles`) y mi barrido exigía un
|
|
63
|
+
* punto literal. Es la cuarta forma del mismo error esta tanda —dar por
|
|
64
|
+
* hecho que el código se escribe como uno lo busca— y por eso el contrato
|
|
65
|
+
* se escribe primero y se deja que tsc lo corrija, en vez de fiarse de la
|
|
66
|
+
* medición.
|
|
67
|
+
*/
|
|
68
|
+
maxNodeCycles: number;
|
|
69
|
+
}
|
|
70
|
+
export interface LimitesDeLaOrganizacion {
|
|
71
|
+
limits: TopesDelPlan;
|
|
72
|
+
/** El plan contratado. Se usa para el mensaje de error, no para decidir. */
|
|
73
|
+
tier: string;
|
|
74
|
+
}
|
|
75
|
+
export interface LimitesDelPlan {
|
|
76
|
+
getOrgPlanLimits(orgId: string): Promise<LimitesDeLaOrganizacion>;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* ⚠️ Cadena y no `Symbol`, igual que los otros tokens de la Fase 2: un
|
|
80
|
+
* `Symbol` no sobrevive a una frontera de módulo duplicada.
|
|
81
|
+
*/
|
|
82
|
+
export declare const LIMITES_DEL_PLAN = "LIMITES_DEL_PLAN";
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Los topes del plan que un nodo necesita saber. Nada más.
|
|
4
|
+
*
|
|
5
|
+
* ## Por qué
|
|
6
|
+
*
|
|
7
|
+
* Costura de la Fase 2. `src/nodes/` importaba `plans/` 64 veces, y ese
|
|
8
|
+
* número engaña como engañaban los otros:
|
|
9
|
+
*
|
|
10
|
+
* 48 `PlansModule` cableado de DI, desaparece con la mudanza
|
|
11
|
+
* 13 `PlansService` de los que TODOS llaman UN método
|
|
12
|
+
* 3 helpers sueltos `managedStorageUsage`, `enMegas`, `registerManagedStore`
|
|
13
|
+
*
|
|
14
|
+
* Los trece llaman `getOrgPlanLimits` y ninguno llama nada más. `PlansService`
|
|
15
|
+
* arrastra 13 ficheros del gateway —`plan.constants`, la entidad de usuario,
|
|
16
|
+
* la de organización— y con eso esos trece servicios de nodo no se pueden
|
|
17
|
+
* mudar a `hw-nodes`.
|
|
18
|
+
*
|
|
19
|
+
* ## Lo que lee cada uno, medido
|
|
20
|
+
*
|
|
21
|
+
* Del resultado se desestructura `{ limits, tier }`, y de `limits` se leen
|
|
22
|
+
* SEIS campos. Son los que están abajo. No se copia la forma entera de
|
|
23
|
+
* `PLAN_LIMITS` —que tiene muchos más— por la misma doctrina que el resto de
|
|
24
|
+
* contratos de esta fase: la superficie USADA, no la entidad completa.
|
|
25
|
+
*
|
|
26
|
+
* ⚠️ Y aquí el compilador es el verificador. Si me dejé un campo fuera, el
|
|
27
|
+
* sitio que lo lee no compila — no hace falta creerse la medición.
|
|
28
|
+
*
|
|
29
|
+
* ## Cuando esto cruce una red
|
|
30
|
+
*
|
|
31
|
+
* Bien: son números y una cadena. A diferencia de la costura del motor —que
|
|
32
|
+
* pasaba documentos de Mongoose vivos— y de la de Drive —donde `auth` es un
|
|
33
|
+
* objeto con métodos—, esto viaja tal cual.
|
|
34
|
+
*/
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.LIMITES_DEL_PLAN = void 0;
|
|
37
|
+
/**
|
|
38
|
+
* ⚠️ Cadena y no `Symbol`, igual que los otros tokens de la Fase 2: un
|
|
39
|
+
* `Symbol` no sobrevive a una frontera de módulo duplicada.
|
|
40
|
+
*/
|
|
41
|
+
exports.LIMITES_DEL_PLAN = 'LIMITES_DEL_PLAN';
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import type { Types } from 'mongoose';
|
|
2
|
+
/**
|
|
3
|
+
* Lo que un nodo le pide al motor de ejecución. Nada más.
|
|
4
|
+
*
|
|
5
|
+
* ## Por qué existe
|
|
6
|
+
*
|
|
7
|
+
* Es la costura de la Fase 2. Para que `src/nodes/` pueda salir a `hw-nodes`
|
|
8
|
+
* —un servicio aparte— no puede importar `EventPipelineService` ni
|
|
9
|
+
* `PipelineRunService`: son el motor, y el motor se queda en el gateway.
|
|
10
|
+
*
|
|
11
|
+
* Medido antes de escribir esto: son **14 imports en 12 ficheros**, y todo lo
|
|
12
|
+
* que se llama son **seis métodos**. Nada más. Cinco familias de nodo
|
|
13
|
+
* —approval, merge, scheduled-workflows, triggers y ai— y ninguna otra.
|
|
14
|
+
*
|
|
15
|
+
* ⚠️ El barrido que lo midió tuvo que admitir SALTOS DE LÍNEA: en
|
|
16
|
+
* `ai-nodes.service` la llamada está partida
|
|
17
|
+
* (`void this.eventPipelineService` y `.dispatchFromOriginEntity(` debajo),
|
|
18
|
+
* y una regex de una línea se dejó ese método fuera. Una interfaz a la que
|
|
19
|
+
* le falta un método es una interfaz que no sirve.
|
|
20
|
+
*
|
|
21
|
+
* ## Por qué está aquí y no en el SDK
|
|
22
|
+
*
|
|
23
|
+
* Porque todavía no hay un segundo consumidor. El propio plan lo dice para
|
|
24
|
+
* los paquetes: extraer antes de que alguien lo pida es cómo se acaba con
|
|
25
|
+
* código publicado que nadie usa. Cuando `hw-nodes` exista de verdad, este
|
|
26
|
+
* fichero se muda entero y los `import type` de abajo se convierten en las
|
|
27
|
+
* formas planas que viajen por la red.
|
|
28
|
+
*
|
|
29
|
+
* Lo que SÍ cambia hoy es lo que importa: `nodes/` deja de conocer al motor.
|
|
30
|
+
* Los tipos entran por `import type` —que se borra al compilar— y el único
|
|
31
|
+
* vínculo en ejecución es el token, que es una cadena.
|
|
32
|
+
*
|
|
33
|
+
* ## ⚠️ Lo que esta interfaz NO arregla
|
|
34
|
+
*
|
|
35
|
+
* Por aquí cruzan **documentos de Mongoose vivos**, no datos planos:
|
|
36
|
+
* `PendingApprovalDocument`, `WebhookDocument`, `PipelineContext`. El plan
|
|
37
|
+
* dice que `hw-nodes` será «sin estado: el runner le manda entidad, payload
|
|
38
|
+
* y credencial», y eso hoy no es cierto en esta costura. Aplanarlo es
|
|
39
|
+
* trabajo aparte y hay que hacerlo ANTES de que esto cruce una red — un
|
|
40
|
+
* documento de Mongoose no sobrevive a un `JSON.stringify` con sus métodos.
|
|
41
|
+
*
|
|
42
|
+
* Se declaran como formas mínimas y no como las entidades enteras, que es la
|
|
43
|
+
* misma doctrina de `contratos.ts` en el SDK: la superficie USADA, no el
|
|
44
|
+
* documento completo. Así el día que esto se serialice, lo que hay que
|
|
45
|
+
* aplanar está escrito aquí y no hay que ir a buscarlo.
|
|
46
|
+
*/
|
|
47
|
+
/**
|
|
48
|
+
* Medido, no adivinado: cada forma de aquí es lo que el motor LEE de ese
|
|
49
|
+
* parámetro y nada más. `webhook` son dos campos, no un documento.
|
|
50
|
+
*
|
|
51
|
+
* ## Por qué son formas y no `unknown`
|
|
52
|
+
*
|
|
53
|
+
* La primera versión los dejó opacos, y opaco no sirve para el destino: el
|
|
54
|
+
* día que esto cruce una red hay que saber QUÉ serializar. Escrito aquí, la
|
|
55
|
+
* lista de lo que hay que empaquetar está donde se necesita.
|
|
56
|
+
*
|
|
57
|
+
* ⚠️ Y NO llevan `[k: string]: unknown`. Un índice de cadena hace la forma
|
|
58
|
+
* MÁS estricta, no menos —un documento de Mongoose no lo tiene— y rechazaría
|
|
59
|
+
* justo lo que hoy se le pasa. Sin él, el tipado estructural acepta el
|
|
60
|
+
* documento vivo Y el objeto plano, que es exactamente lo que hace falta
|
|
61
|
+
* durante la transición.
|
|
62
|
+
*
|
|
63
|
+
* ## Cómo se comprobó que se puede aplanar
|
|
64
|
+
*
|
|
65
|
+
* Se midió qué hace el motor con cada uno: **sólo lecturas de propiedad**,
|
|
66
|
+
* ninguna llamada a método de Mongoose. Y de las siete funciones que reciben
|
|
67
|
+
* uno entero, seis tampoco los tocan. La única que sí —`gateApproval`, con
|
|
68
|
+
* `event.toJSON()`— se arregló para aceptar los dos.
|
|
69
|
+
*/
|
|
70
|
+
/** Lo que el motor lee de un evento. */
|
|
71
|
+
export interface EventoDeCorrida {
|
|
72
|
+
id: unknown;
|
|
73
|
+
correlationId?: unknown;
|
|
74
|
+
eventType?: unknown;
|
|
75
|
+
headers?: unknown;
|
|
76
|
+
sourceIp?: unknown;
|
|
77
|
+
webhookId?: unknown;
|
|
78
|
+
}
|
|
79
|
+
/** Y de un webhook: dos campos. */
|
|
80
|
+
export interface WebhookDeCorrida {
|
|
81
|
+
id: unknown;
|
|
82
|
+
name?: unknown;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* El contexto de la corrida.
|
|
86
|
+
*
|
|
87
|
+
* ⚠️ `nodeVisitCounts` va como OBJETO y no como `Map`, y ése era el segundo
|
|
88
|
+
* bloqueo del aplanado: un `Map` se convierte en `{}` al serializar, y aquí
|
|
89
|
+
* además se MUTA al otro lado —`ctx.nodeVisitCounts.set(...)`—, así que por
|
|
90
|
+
* una red el contador de ciclos dejaría de contar en silencio. Y fallar en la
|
|
91
|
+
* detección de ciclos es un bucle infinito, no un aviso.
|
|
92
|
+
*
|
|
93
|
+
* No hay que inventar nada: el motor YA hace esta conversión para cruzar la
|
|
94
|
+
* cola de BullMQ —`Object.fromEntries` al salir, `new Map(Object.entries(…))`
|
|
95
|
+
* al entrar, ver `delivery.processor`— porque un job es JSON. La costura usa
|
|
96
|
+
* la misma forma serializada, y el motor convierte en su borde.
|
|
97
|
+
*/
|
|
98
|
+
export interface ContextoDeCorrida {
|
|
99
|
+
orgId: string;
|
|
100
|
+
backoffCapMs?: number;
|
|
101
|
+
maxNodeCycles?: number;
|
|
102
|
+
nodeVisitCounts?: Record<string, number>;
|
|
103
|
+
}
|
|
104
|
+
/** Una espera pendiente, de lo que el motor le lee. */
|
|
105
|
+
export interface EsperaPendiente {
|
|
106
|
+
id?: unknown;
|
|
107
|
+
eventId?: unknown;
|
|
108
|
+
eventHeaders?: unknown;
|
|
109
|
+
organizationId?: unknown;
|
|
110
|
+
payload?: unknown;
|
|
111
|
+
pipelineContext?: unknown;
|
|
112
|
+
webhookId?: unknown;
|
|
113
|
+
}
|
|
114
|
+
/** Un nodo de aprobación. */
|
|
115
|
+
export interface NodoDeAprobacion {
|
|
116
|
+
_id: unknown;
|
|
117
|
+
name?: unknown;
|
|
118
|
+
outputNodes?: unknown;
|
|
119
|
+
rejectionOutputNodes?: unknown;
|
|
120
|
+
}
|
|
121
|
+
/** El estado acumulado de un merge. */
|
|
122
|
+
export interface EstadoDeMerge {
|
|
123
|
+
correlationId?: unknown;
|
|
124
|
+
expectedCount?: unknown;
|
|
125
|
+
organizationId?: unknown;
|
|
126
|
+
receivedBranches?: unknown;
|
|
127
|
+
}
|
|
128
|
+
/** Un nodo de merge. */
|
|
129
|
+
export interface NodoDeMerge {
|
|
130
|
+
_id: unknown;
|
|
131
|
+
name?: unknown;
|
|
132
|
+
}
|
|
133
|
+
/** Un paso ejecutado, tal como lo devuelve `resumeFromApproval`. */
|
|
134
|
+
export type PasoDeCorrida = unknown;
|
|
135
|
+
/**
|
|
136
|
+
* Los seis métodos, agrupados por lo que hacen.
|
|
137
|
+
*
|
|
138
|
+
* Se separan en dos interfaces porque hoy las implementan DOS servicios
|
|
139
|
+
* distintos —`EventPipelineService` y `PipelineRunService`— y juntarlas
|
|
140
|
+
* obligaría a un adaptador que no aporta nada.
|
|
141
|
+
*/
|
|
142
|
+
export interface DespachoDelMotor {
|
|
143
|
+
/** Sigue el flujo hacia los nodos de salida de un webhook. */
|
|
144
|
+
dispatchOutputNodes(outputNodes: Array<{
|
|
145
|
+
nodeType: string;
|
|
146
|
+
nodeId: Types.ObjectId;
|
|
147
|
+
}>, payload: Record<string, unknown>, event: EventoDeCorrida, webhook: WebhookDeCorrida, ctx: ContextoDeCorrida, depth: number): Promise<void>;
|
|
148
|
+
/**
|
|
149
|
+
* Arranca una corrida desde un nodo cualquiera, sin webhook de por medio.
|
|
150
|
+
* Lo usa el nodo de IA cuando lo dispara un chat: `executeForEvent` se
|
|
151
|
+
* salta el paso de aguas abajo del ciclo de vida, así que hay que
|
|
152
|
+
* empujarlo a mano.
|
|
153
|
+
*/
|
|
154
|
+
dispatchFromOriginEntity(params: {
|
|
155
|
+
originType: string;
|
|
156
|
+
originEntity: unknown;
|
|
157
|
+
payload: Record<string, unknown>;
|
|
158
|
+
orgId: string;
|
|
159
|
+
[k: string]: unknown;
|
|
160
|
+
}): Promise<unknown>;
|
|
161
|
+
/** Reanuda tras un visto bueno o un rechazo. */
|
|
162
|
+
resumeAfterApproval(pending: EsperaPendiente, approvalNode: NodoDeAprobacion, action: 'approve' | 'reject'): Promise<void>;
|
|
163
|
+
/** Reanuda tras una respuesta de «envía y espera». */
|
|
164
|
+
resumeAfterSendAndWait(pending: EsperaPendiente, decision: {
|
|
165
|
+
approved: boolean;
|
|
166
|
+
decidedAt: Date;
|
|
167
|
+
decidedBy?: string;
|
|
168
|
+
ipAddress?: string;
|
|
169
|
+
comment?: string;
|
|
170
|
+
[k: string]: unknown;
|
|
171
|
+
}): Promise<void>;
|
|
172
|
+
/** Reanuda cuando a un merge se le acaba el tiempo de espera. */
|
|
173
|
+
resumeAfterMergeTimeout(mergeState: EstadoDeMerge, mergeNode: NodoDeMerge): Promise<void>;
|
|
174
|
+
}
|
|
175
|
+
/** El otro servicio: la corrida de prueba desde el panel. */
|
|
176
|
+
export interface CorridaDelMotor {
|
|
177
|
+
/**
|
|
178
|
+
* Arrancar una corrida desde un nodo de origen.
|
|
179
|
+
*
|
|
180
|
+
* ⚠️ Es «lanza y olvida»: el llamante genera el `executionId`, lo devuelve al
|
|
181
|
+
* panel de inmediato y el progreso viaja por socket. La promesa que sale de
|
|
182
|
+
* aquí NO se espera — esperarla dejaría al navegador colgado el tiempo que
|
|
183
|
+
* dure el flujo entero.
|
|
184
|
+
*/
|
|
185
|
+
ejecutar(startNodeType: string, startNodeId: string, payload: Record<string, unknown> | undefined, orgId: string, userId: string, executionId: string): Promise<unknown>;
|
|
186
|
+
resumeFromApproval(approvalNode: NodoDeAprobacion, payload: Record<string, unknown>, action: 'approve' | 'reject', orgId: string): Promise<{
|
|
187
|
+
executionId: string;
|
|
188
|
+
steps: PasoDeCorrida[];
|
|
189
|
+
}>;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* ⚠️ Son cadenas y no `Symbol` a propósito: un `Symbol` no sobrevive a un
|
|
193
|
+
* `JSON.stringify` ni a una frontera de módulo duplicada, y esto está
|
|
194
|
+
* pensado para acabar cruzando una.
|
|
195
|
+
*/
|
|
196
|
+
export declare const DESPACHO_DEL_MOTOR = "DESPACHO_DEL_MOTOR";
|
|
197
|
+
export declare const CORRIDA_DEL_MOTOR = "CORRIDA_DEL_MOTOR";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CORRIDA_DEL_MOTOR = exports.DESPACHO_DEL_MOTOR = void 0;
|
|
4
|
+
/* ── Los tokens ──────────────────────────────────────────────────── */
|
|
5
|
+
/**
|
|
6
|
+
* ⚠️ Son cadenas y no `Symbol` a propósito: un `Symbol` no sobrevive a un
|
|
7
|
+
* `JSON.stringify` ni a una frontera de módulo duplicada, y esto está
|
|
8
|
+
* pensado para acabar cruzando una.
|
|
9
|
+
*/
|
|
10
|
+
exports.DESPACHO_DEL_MOTOR = 'DESPACHO_DEL_MOTOR';
|
|
11
|
+
exports.CORRIDA_DEL_MOTOR = 'CORRIDA_DEL_MOTOR';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Las plantillas de payload de un servicio de trigger.
|
|
3
|
+
*
|
|
4
|
+
* ## Por qué es un contrato y no un import
|
|
5
|
+
*
|
|
6
|
+
* El registro son **23 ficheros y 5.800 líneas** de plantillas —una por
|
|
7
|
+
* servicio, y varias miran su config: `changeType` en Calendar, `eventTrigger`
|
|
8
|
+
* en Gmail, `enabledEvents` en Sheets—. Viven con el trigger, que es uno de los
|
|
9
|
+
* cinco nodos de origen que se quedan en el gateway.
|
|
10
|
+
*
|
|
11
|
+
* `start-node-sample.ts` las necesita para el paso 3 de «con qué payload
|
|
12
|
+
* arranca una corrida», y ese fichero viaja con el motor. Demasiado para
|
|
13
|
+
* mudarlo, y demasiado poco para copiarlo: de tener dos copias de una plantilla
|
|
14
|
+
* salió que un trigger de Google Calendar arrancara con
|
|
15
|
+
* `{ event: "new_email" }`.
|
|
16
|
+
*
|
|
17
|
+
* ⚠️ Y NO se escriben a mano en ningún lado: pasan por el MISMO formateador que
|
|
18
|
+
* la entrega real, así que no pueden desfasarse de lo que se despacha. Una copia
|
|
19
|
+
* sí se desfasa.
|
|
20
|
+
*/
|
|
21
|
+
export type PlantillasDeOrigen = (service: string | null | undefined, serviceConfig: Record<string, unknown> | undefined) => Array<{
|
|
22
|
+
payload: Record<string, unknown>;
|
|
23
|
+
}>;
|
|
24
|
+
/** ⚠️ Cadena y no `Symbol`. */
|
|
25
|
+
export declare const PLANTILLAS_DE_ORIGEN = "PLANTILLAS_DE_ORIGEN";
|