@voyantjs/workflows 0.28.3 → 0.29.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 (59) hide show
  1. package/dist/driver.d.ts +237 -0
  2. package/dist/driver.d.ts.map +1 -0
  3. package/dist/driver.js +53 -0
  4. package/dist/events/compile.d.ts +34 -0
  5. package/dist/events/compile.d.ts.map +1 -0
  6. package/dist/events/compile.js +204 -0
  7. package/dist/events/index.d.ts +8 -0
  8. package/dist/events/index.d.ts.map +1 -0
  9. package/dist/events/index.js +11 -0
  10. package/dist/events/input-mapper.d.ts +24 -0
  11. package/dist/events/input-mapper.d.ts.map +1 -0
  12. package/dist/events/input-mapper.js +169 -0
  13. package/dist/events/manifest-builder.d.ts +32 -0
  14. package/dist/events/manifest-builder.d.ts.map +1 -0
  15. package/dist/events/manifest-builder.js +66 -0
  16. package/dist/events/payload-hash.d.ts +46 -0
  17. package/dist/events/payload-hash.d.ts.map +1 -0
  18. package/dist/events/payload-hash.js +98 -0
  19. package/dist/events/predicate.d.ts +77 -0
  20. package/dist/events/predicate.d.ts.map +1 -0
  21. package/dist/events/predicate.js +347 -0
  22. package/dist/events/registry.d.ts +37 -0
  23. package/dist/events/registry.d.ts.map +1 -0
  24. package/dist/events/registry.js +47 -0
  25. package/dist/handler/index.d.ts +8 -0
  26. package/dist/handler/index.d.ts.map +1 -1
  27. package/dist/handler/index.js +1 -0
  28. package/dist/http-ingest.d.ts +54 -0
  29. package/dist/http-ingest.d.ts.map +1 -0
  30. package/dist/http-ingest.js +214 -0
  31. package/dist/protocol/index.d.ts +17 -2
  32. package/dist/protocol/index.d.ts.map +1 -1
  33. package/dist/runtime/ctx.d.ts +9 -0
  34. package/dist/runtime/ctx.d.ts.map +1 -1
  35. package/dist/runtime/ctx.js +17 -0
  36. package/dist/runtime/executor.d.ts +7 -0
  37. package/dist/runtime/executor.d.ts.map +1 -1
  38. package/dist/runtime/executor.js +1 -0
  39. package/dist/trigger.d.ts +28 -14
  40. package/dist/trigger.d.ts.map +1 -1
  41. package/dist/trigger.js +4 -4
  42. package/dist/workflow.d.ts +10 -0
  43. package/dist/workflow.d.ts.map +1 -1
  44. package/package.json +14 -2
  45. package/src/driver.ts +277 -0
  46. package/src/events/compile.ts +268 -0
  47. package/src/events/index.ts +42 -0
  48. package/src/events/input-mapper.ts +201 -0
  49. package/src/events/manifest-builder.ts +97 -0
  50. package/src/events/payload-hash.ts +110 -0
  51. package/src/events/predicate.ts +390 -0
  52. package/src/events/registry.ts +88 -0
  53. package/src/handler/index.ts +9 -0
  54. package/src/http-ingest.ts +299 -0
  55. package/src/protocol/index.ts +17 -2
  56. package/src/runtime/ctx.ts +29 -0
  57. package/src/runtime/executor.ts +8 -0
  58. package/src/trigger.ts +31 -15
  59. package/src/workflow.ts +11 -0
@@ -0,0 +1,347 @@
1
+ // Predicate DSL — the structured `where` filter on EventFilterDeclaration.
2
+ //
3
+ // Closed grammar of 12 operators, evaluated against the standard
4
+ // EventEnvelope shape (`data`, `metadata`, `name`, `emittedAt`). No `eval`,
5
+ // no Function constructor, no callback-via-network — everything is data.
6
+ //
7
+ // Authoring shape (from a module's source):
8
+ //
9
+ // trigger.on("promotion.changed", {
10
+ // target: bulkReindexProducts,
11
+ // where: { eq: [{ path: "data.affected.kind" }, { lit: "all" }] },
12
+ // input: { ... },
13
+ // })
14
+ //
15
+ // Architecture: docs/architecture/workflows-runtime-architecture.md §13.1.
16
+ // ---- Public API ----
17
+ /**
18
+ * Evaluate a predicate against an event envelope. Returns `true` / `false`.
19
+ * Path resolution against missing keys yields `undefined`, which makes
20
+ * comparison ops `false` (not throw). The evaluator never throws on data
21
+ * mismatches — registration-time linting catches structural errors via
22
+ * {@link validatePredicate}.
23
+ *
24
+ * Throws `PredicateEvalError` only on unexpected shape errors (the predicate
25
+ * itself was constructed wrong, e.g. malformed operator). Drivers catch
26
+ * this and surface it as `IngestMatch.status === "skipped"` with reason
27
+ * `"where_eval_error"`.
28
+ */
29
+ export function evaluatePredicate(expr, envelope) {
30
+ if ("eq" in expr) {
31
+ return strictEquals(resolveSide(expr.eq[0], envelope), resolveSide(expr.eq[1], envelope));
32
+ }
33
+ if ("neq" in expr) {
34
+ return !strictEquals(resolveSide(expr.neq[0], envelope), resolveSide(expr.neq[1], envelope));
35
+ }
36
+ if ("in" in expr) {
37
+ const lhs = resolveSide(expr.in[0], envelope);
38
+ const rhs = expr.in[1].map((item) => resolveSide(item, envelope));
39
+ return rhs.some((candidate) => strictEquals(lhs, candidate));
40
+ }
41
+ if ("gt" in expr)
42
+ return compareTwo(expr.gt, envelope, ">");
43
+ if ("gte" in expr)
44
+ return compareTwo(expr.gte, envelope, ">=");
45
+ if ("lt" in expr)
46
+ return compareTwo(expr.lt, envelope, "<");
47
+ if ("lte" in expr)
48
+ return compareTwo(expr.lte, envelope, "<=");
49
+ if ("exists" in expr) {
50
+ return resolveSide(expr.exists, envelope) !== undefined;
51
+ }
52
+ if ("not" in expr)
53
+ return !evaluatePredicate(expr.not, envelope);
54
+ if ("and" in expr) {
55
+ if (!Array.isArray(expr.and)) {
56
+ throw new PredicateEvalError("`and` clause must be an array of predicates");
57
+ }
58
+ return expr.and.every((sub) => evaluatePredicate(sub, envelope));
59
+ }
60
+ if ("or" in expr) {
61
+ if (!Array.isArray(expr.or)) {
62
+ throw new PredicateEvalError("`or` clause must be an array of predicates");
63
+ }
64
+ return expr.or.some((sub) => evaluatePredicate(sub, envelope));
65
+ }
66
+ throw new PredicateEvalError(`unknown predicate operator: ${stringify(expr)}`);
67
+ }
68
+ /**
69
+ * Resolve a path string against an envelope. Public so consumers (input
70
+ * mapper, manifest builder) can share the same path semantics without
71
+ * re-implementing them.
72
+ *
73
+ * Path syntax: dot-separated; `[N]` for array index; missing intermediate
74
+ * keys produce `undefined`. Roots: `data`, `metadata`, `name`, `emittedAt`.
75
+ *
76
+ * Returns `undefined` on any shape mismatch — that's how runtime evaluation
77
+ * stays no-throw.
78
+ */
79
+ export function resolvePath(path, envelope) {
80
+ const segments = parsePath(path);
81
+ if (segments.length === 0)
82
+ return undefined;
83
+ const [root, ...rest] = segments;
84
+ let value;
85
+ switch (root) {
86
+ case "name":
87
+ value = envelope.name;
88
+ break;
89
+ case "emittedAt":
90
+ value = envelope.emittedAt;
91
+ break;
92
+ case "data":
93
+ value = envelope.data;
94
+ break;
95
+ case "metadata":
96
+ value = envelope.metadata;
97
+ break;
98
+ default:
99
+ // Unknown roots evaluate to undefined at runtime. Registration-time
100
+ // linter surfaces this as a structural error so callers see it earlier.
101
+ return undefined;
102
+ }
103
+ for (const segment of rest) {
104
+ if (value === undefined || value === null)
105
+ return undefined;
106
+ if (typeof segment === "number") {
107
+ if (!Array.isArray(value))
108
+ return undefined;
109
+ value = value[segment];
110
+ }
111
+ else {
112
+ if (typeof value !== "object")
113
+ return undefined;
114
+ value = value[segment];
115
+ }
116
+ }
117
+ return value;
118
+ }
119
+ /**
120
+ * Static structural check on a `PredicateExpr`. Catches path roots that
121
+ * aren't `data`/`metadata`/`name`/`emittedAt`, type mismatches on
122
+ * comparison operators (number vs string lhs/rhs), and malformed grammars.
123
+ * Surfaced at `trigger.on()` registration so authoring errors fail fast.
124
+ */
125
+ export function validatePredicate(expr) {
126
+ const errors = [];
127
+ walk(expr, errors, []);
128
+ return { ok: errors.length === 0, errors };
129
+ }
130
+ function walk(expr, errors, path) {
131
+ if (typeof expr !== "object" || expr === null) {
132
+ errors.push(`${pathLabel(path)}: predicate must be an object, got ${typeof expr}`);
133
+ return;
134
+ }
135
+ const keys = Object.keys(expr);
136
+ if (keys.length !== 1) {
137
+ errors.push(`${pathLabel(path)}: a predicate object must have exactly one operator key, got ${keys.length} (${keys.join(", ")})`);
138
+ return;
139
+ }
140
+ const op = keys[0];
141
+ switch (op) {
142
+ case "eq":
143
+ case "neq":
144
+ case "gt":
145
+ case "gte":
146
+ case "lt":
147
+ case "lte": {
148
+ const raw = expr[op];
149
+ if (!Array.isArray(raw) || raw.length !== 2) {
150
+ errors.push(`${pathLabel([...path, op])}: expected [lhs, rhs] tuple`);
151
+ return;
152
+ }
153
+ const sides = raw;
154
+ validateSide(sides[0], errors, [...path, op, "0"]);
155
+ validateSide(sides[1], errors, [...path, op, "1"]);
156
+ // Type-sanity for ordered comparisons: both literals must be the same numeric/string flavor.
157
+ if (op !== "eq" && op !== "neq") {
158
+ const lhsLit = sideLitType(sides[0]);
159
+ const rhsLit = sideLitType(sides[1]);
160
+ if (lhsLit !== "unknown" &&
161
+ rhsLit !== "unknown" &&
162
+ lhsLit !== rhsLit &&
163
+ (lhsLit === "number" || lhsLit === "string")) {
164
+ errors.push(`${pathLabel([...path, op])}: ordered comparison sides must agree on type (got ${lhsLit} vs ${rhsLit})`);
165
+ }
166
+ }
167
+ return;
168
+ }
169
+ case "in": {
170
+ const tuple = expr.in;
171
+ if (!Array.isArray(tuple) || tuple.length !== 2) {
172
+ errors.push(`${pathLabel([...path, "in"])}: expected [lhs, rhs[]] tuple`);
173
+ return;
174
+ }
175
+ validateSide(tuple[0], errors, [...path, "in", "0"]);
176
+ if (!Array.isArray(tuple[1])) {
177
+ errors.push(`${pathLabel([...path, "in", "1"])}: rhs must be an array of paths/literals`);
178
+ return;
179
+ }
180
+ for (let i = 0; i < tuple[1].length; i++) {
181
+ const s = tuple[1][i];
182
+ validateSide(s, errors, [...path, "in", "1", String(i)]);
183
+ }
184
+ return;
185
+ }
186
+ case "exists":
187
+ validateSide(expr.exists, errors, [...path, "exists"]);
188
+ return;
189
+ case "not":
190
+ walk(expr.not, errors, [...path, "not"]);
191
+ return;
192
+ case "and":
193
+ case "or": {
194
+ const raw = expr[op];
195
+ if (!Array.isArray(raw)) {
196
+ errors.push(`${pathLabel([...path, op])}: ${op} must be an array of predicates`);
197
+ return;
198
+ }
199
+ const arr = raw;
200
+ for (let i = 0; i < arr.length; i++) {
201
+ const sub = arr[i];
202
+ walk(sub, errors, [...path, op, String(i)]);
203
+ }
204
+ return;
205
+ }
206
+ default:
207
+ errors.push(`${pathLabel(path)}: unknown predicate operator "${String(op)}"`);
208
+ }
209
+ }
210
+ function validateSide(side, errors, path) {
211
+ if (typeof side !== "object" || side === null) {
212
+ errors.push(`${pathLabel(path)}: expected { path } or { lit }, got ${typeof side}`);
213
+ return;
214
+ }
215
+ if ("path" in side) {
216
+ if (typeof side.path !== "string" || side.path.length === 0) {
217
+ errors.push(`${pathLabel(path)}: "path" must be a non-empty string`);
218
+ return;
219
+ }
220
+ const root = parsePath(side.path)[0];
221
+ if (root !== "data" && root !== "metadata" && root !== "name" && root !== "emittedAt") {
222
+ errors.push(`${pathLabel(path)}: path root "${String(root)}" is not one of data | metadata | name | emittedAt`);
223
+ }
224
+ return;
225
+ }
226
+ if ("lit" in side) {
227
+ const t = typeof side.lit;
228
+ if (t !== "string" && t !== "number" && t !== "boolean" && side.lit !== null) {
229
+ errors.push(`${pathLabel(path)}: lit must be string | number | boolean | null`);
230
+ }
231
+ return;
232
+ }
233
+ errors.push(`${pathLabel(path)}: must specify "path" or "lit"`);
234
+ }
235
+ // ---- Internal helpers ----
236
+ class PredicateEvalError extends Error {
237
+ constructor(message) {
238
+ super(message);
239
+ this.name = "PredicateEvalError";
240
+ }
241
+ }
242
+ function resolveSide(side, envelope) {
243
+ if ("lit" in side)
244
+ return side.lit;
245
+ if ("path" in side)
246
+ return resolvePath(side.path, envelope);
247
+ return undefined;
248
+ }
249
+ function strictEquals(a, b) {
250
+ if (a === undefined || b === undefined)
251
+ return false;
252
+ if (a === null && b === null)
253
+ return true;
254
+ if (a === null || b === null)
255
+ return false;
256
+ if (typeof a !== typeof b)
257
+ return false;
258
+ if (typeof a === "object") {
259
+ // Strict equality only for primitives + null. Object equality is not
260
+ // supported in v1; users who need it project specific paths to compare.
261
+ return false;
262
+ }
263
+ return a === b;
264
+ }
265
+ function compareTwo(sides, envelope, op) {
266
+ const lhs = resolveSide(sides[0], envelope);
267
+ const rhs = resolveSide(sides[1], envelope);
268
+ if (lhs === undefined || rhs === undefined)
269
+ return false;
270
+ if (typeof lhs !== typeof rhs)
271
+ return false;
272
+ if (typeof lhs !== "number" && typeof lhs !== "string")
273
+ return false;
274
+ switch (op) {
275
+ case ">":
276
+ return lhs > rhs;
277
+ case ">=":
278
+ return lhs >= rhs;
279
+ case "<":
280
+ return lhs < rhs;
281
+ case "<=":
282
+ return lhs <= rhs;
283
+ }
284
+ }
285
+ function sideLitType(side) {
286
+ if ("lit" in side) {
287
+ if (side.lit === null)
288
+ return "null";
289
+ const t = typeof side.lit;
290
+ if (t === "number" || t === "string" || t === "boolean")
291
+ return t;
292
+ }
293
+ return "unknown";
294
+ }
295
+ /**
296
+ * Parse a dot-and-bracket path into segments. `data.items[0].id` becomes
297
+ * `["data", "items", 0, "id"]`. Numeric segments inside `[N]` are returned
298
+ * as numbers; everything else as strings. Malformed input yields `[]`.
299
+ */
300
+ function parsePath(path) {
301
+ if (typeof path !== "string" || path.length === 0)
302
+ return [];
303
+ const segments = [];
304
+ let i = 0;
305
+ let buf = "";
306
+ const flushBuf = () => {
307
+ if (buf.length > 0) {
308
+ segments.push(buf);
309
+ buf = "";
310
+ }
311
+ };
312
+ while (i < path.length) {
313
+ const c = path[i];
314
+ if (c === ".") {
315
+ flushBuf();
316
+ i++;
317
+ continue;
318
+ }
319
+ if (c === "[") {
320
+ flushBuf();
321
+ const end = path.indexOf("]", i);
322
+ if (end === -1)
323
+ return [];
324
+ const idx = Number(path.slice(i + 1, end));
325
+ if (!Number.isInteger(idx) || idx < 0)
326
+ return [];
327
+ segments.push(idx);
328
+ i = end + 1;
329
+ continue;
330
+ }
331
+ buf += c;
332
+ i++;
333
+ }
334
+ flushBuf();
335
+ return segments;
336
+ }
337
+ function pathLabel(path) {
338
+ return path.length === 0 ? "(root)" : path.join(".");
339
+ }
340
+ function stringify(value) {
341
+ try {
342
+ return JSON.stringify(value);
343
+ }
344
+ catch {
345
+ return String(value);
346
+ }
347
+ }
@@ -0,0 +1,37 @@
1
+ import type { EventFilterManifestEntry } from "../protocol/index.js";
2
+ import type { EventFilterDeclaration } from "../trigger.js";
3
+ /**
4
+ * Internal/runtime form of a registered event filter. Carries:
5
+ * - The serializable manifest entry (sent to drivers, persisted in
6
+ * manifest stores, evaluated by the event router).
7
+ * - A debug-only structural copy of the original declaration. Not
8
+ * serialized; used by the dashboard / dev mode for human-readable
9
+ * filter inspection.
10
+ *
11
+ * Concrete `WorkflowDefinition` from `workflow.ts` satisfies the structural
12
+ * `target` shape via TypeScript compat.
13
+ */
14
+ export interface EventFilterRuntimeEntry {
15
+ readonly id: string;
16
+ readonly eventType: string;
17
+ readonly manifest: EventFilterManifestEntry;
18
+ /** Debug-only — non-serializable. */
19
+ readonly declaration: EventFilterDeclaration<unknown>;
20
+ /** Workflow id this filter targets, for quick lookup. */
21
+ readonly targetWorkflowId: string;
22
+ }
23
+ interface EventFilterRegistry {
24
+ add(entry: EventFilterRuntimeEntry): void;
25
+ list(): EventFilterRuntimeEntry[];
26
+ /** Reset to empty. Test-only — production code never calls this. */
27
+ reset(): void;
28
+ }
29
+ /** Process-local event-filter registry. Singleton per realm. */
30
+ export declare function getEventFilterRegistry(): EventFilterRegistry;
31
+ /**
32
+ * Internal: clear every registered filter. Used by tests that import the
33
+ * SDK and need a clean slate between cases. Not part of the public API.
34
+ */
35
+ export declare function __resetEventFilterRegistry(): void;
36
+ export {};
37
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/events/registry.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAA;AACpE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAI3D;;;;;;;;;;GAUG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,QAAQ,EAAE,wBAAwB,CAAA;IAC3C,qCAAqC;IACrC,QAAQ,CAAC,WAAW,EAAE,sBAAsB,CAAC,OAAO,CAAC,CAAA;IACrD,yDAAyD;IACzD,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;CAClC;AAED,UAAU,mBAAmB;IAC3B,GAAG,CAAC,KAAK,EAAE,uBAAuB,GAAG,IAAI,CAAA;IACzC,IAAI,IAAI,uBAAuB,EAAE,CAAA;IACjC,oEAAoE;IACpE,KAAK,IAAI,IAAI,CAAA;CACd;AAgCD,gEAAgE;AAChE,wBAAgB,sBAAsB,IAAI,mBAAmB,CAE5D;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD"}
@@ -0,0 +1,47 @@
1
+ // Process-local registry for event-filter runtime entries.
2
+ //
3
+ // `trigger.on(eventName, filter)` adds an entry here at module-load time.
4
+ // `createApp()` (PR4) walks `getEventFilterRegistry().list()` to build a
5
+ // manifest, hand it to the configured driver, and install the EventBus
6
+ // forwarder.
7
+ //
8
+ // Backed by `globalThis` so bundles that inline their own copy of
9
+ // `@voyantjs/workflows` still share the registry with the loader's copy
10
+ // — same pattern `getWorkflow()` uses for the workflow registry.
11
+ //
12
+ // Architecture: docs/architecture/workflows-runtime-architecture.md §12.
13
+ const REGISTRY_KEY = "__voyantEventFilterRegistry";
14
+ const globalRef = globalThis;
15
+ const REGISTRY = globalRef[REGISTRY_KEY] ?? new Map();
16
+ globalRef[REGISTRY_KEY] = REGISTRY;
17
+ const registry = {
18
+ add(entry) {
19
+ if (REGISTRY.has(entry.id)) {
20
+ // Same id implies same canonicalized declaration. HMR re-imports
21
+ // and re-evaluations of the same module file land here; replace
22
+ // (overwrite is harmless since the entry is content-addressed).
23
+ // For genuine duplicates from different declarations, the canonical
24
+ // hash would differ, so different ids would result.
25
+ REGISTRY.set(entry.id, entry);
26
+ return;
27
+ }
28
+ REGISTRY.set(entry.id, entry);
29
+ },
30
+ list() {
31
+ return [...REGISTRY.values()];
32
+ },
33
+ reset() {
34
+ REGISTRY.clear();
35
+ },
36
+ };
37
+ /** Process-local event-filter registry. Singleton per realm. */
38
+ export function getEventFilterRegistry() {
39
+ return registry;
40
+ }
41
+ /**
42
+ * Internal: clear every registered filter. Used by tests that import the
43
+ * SDK and need a clean slate between cases. Not part of the public API.
44
+ */
45
+ export function __resetEventFilterRegistry() {
46
+ registry.reset();
47
+ }
@@ -40,6 +40,14 @@ export interface StepHandlerDeps {
40
40
  * the target runtime; the executor only cares that a runner exists.
41
41
  */
42
42
  nodeStepRunner?: StepRunner;
43
+ /**
44
+ * Read-only service resolver, surfaced to step bodies as `ctx.services`.
45
+ * The framework's `createApp()` wires this from its `ModuleContainer`;
46
+ * raw orchestrator harnesses (tests, ad-hoc scripts) typically leave
47
+ * it unset, in which case `ctx.services.resolve(...)` throws with a
48
+ * clear message. See architecture doc §11.
49
+ */
50
+ services?: import("../driver.js").ServiceResolver;
43
51
  }
44
52
  /** The HTTP request body the orchestrator sends. */
45
53
  export interface WorkflowStepRequest {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/handler/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/handler/index.ts"],"names":[],"mappings":"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"}
@@ -114,6 +114,7 @@ async function runStepInner(raw, deps, opts = {}) {
114
114
  stepRunner,
115
115
  nodeStepRunner: deps.nodeStepRunner,
116
116
  rateLimiter: deps.rateLimiter,
117
+ services: deps.services,
117
118
  now,
118
119
  abortSignal: opts.signal,
119
120
  onStreamChunk: opts.onStreamChunk,
@@ -0,0 +1,54 @@
1
+ import type { WorkflowDriver } from "./driver.js";
2
+ /**
3
+ * Minimum interface a Hono-shaped app exposes that we use. `app.post(...)`
4
+ * and `app.get(...)` register handlers; the handler signature mirrors
5
+ * Hono's `Context`-style callback for portability — we only read the
6
+ * request body and request params via the framework's response helpers.
7
+ */
8
+ export interface HttpAppLike {
9
+ post(path: string, handler: HttpHandler): unknown;
10
+ get(path: string, handler: HttpHandler): unknown;
11
+ }
12
+ /**
13
+ * Minimum context shape we read off Hono. Restricted to body parsing,
14
+ * route params, and JSON response helpers.
15
+ */
16
+ export interface HttpContextLike {
17
+ req: {
18
+ json(): Promise<unknown>;
19
+ param(name: string): string | undefined;
20
+ header(name: string): string | undefined;
21
+ raw: Request;
22
+ };
23
+ json(body: unknown, status?: number): Response;
24
+ text(body: string, status?: number): Response;
25
+ status(code: number): unknown;
26
+ }
27
+ export type HttpHandler = (ctx: HttpContextLike) => Promise<Response> | Response;
28
+ export interface MountHttpIngestAdapterOptions {
29
+ /**
30
+ * Driver the adapter forwards into. Typically the same instance
31
+ * `createApp({ workflows: { driver } })` constructed.
32
+ */
33
+ driver: WorkflowDriver;
34
+ /** Mount path. Defaults to `"/api/workflows"`. */
35
+ basePath?: string;
36
+ /**
37
+ * Optional auth check. Receives the original `Request` and returns
38
+ * `void` on success / throws on failure. Reuse
39
+ * `createBearerVerifier(...)` from `@voyantjs/workflows/auth` for the
40
+ * canonical bearer-token shape.
41
+ */
42
+ verifyRequest?: (req: Request) => void | Promise<void>;
43
+ }
44
+ /**
45
+ * Mount the adapter onto a Hono-shaped app. Registers:
46
+ *
47
+ * POST {basePath}/events → driver.ingestEvent
48
+ * POST {basePath}/manifests → driver.registerManifest
49
+ * GET {basePath}/manifests/:env → driver.getManifest
50
+ *
51
+ * Returns the mounted base path so callers can log it.
52
+ */
53
+ export declare function mountHttpIngestAdapter(app: HttpAppLike, opts: MountHttpIngestAdapterOptions): string;
54
+ //# sourceMappingURL=http-ingest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-ingest.d.ts","sourceRoot":"","sources":["../src/http-ingest.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAmB,cAAc,EAAE,MAAM,aAAa,CAAA;AAOlE;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAA;IACjD,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAA;CACjD;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE;QACH,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;QACxB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;QACvC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;QACxC,GAAG,EAAE,OAAO,CAAA;KACb,CAAA;IACD,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAA;IAC9C,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAA;IAC7C,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAC9B;AAED,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAA;AAEhF,MAAM,WAAW,6BAA6B;IAC5C;;;OAGG;IACH,MAAM,EAAE,cAAc,CAAA;IACtB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACvD;AAID;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,6BAA6B,GAClC,MAAM,CAyFR"}