@voyantjs/workflows-orchestrator-cloudflare 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 (44) hide show
  1. package/README.md +23 -11
  2. package/dist/cloudflare-edge-driver.d.ts +49 -0
  3. package/dist/cloudflare-edge-driver.d.ts.map +1 -0
  4. package/dist/cloudflare-edge-driver.js +317 -0
  5. package/dist/dispatchers.d.ts +87 -0
  6. package/dist/dispatchers.d.ts.map +1 -0
  7. package/dist/dispatchers.js +83 -0
  8. package/dist/do-store.d.ts.map +1 -1
  9. package/dist/do-store.js +12 -0
  10. package/dist/durable-object.d.ts +13 -6
  11. package/dist/durable-object.d.ts.map +1 -1
  12. package/dist/durable-object.js +13 -4
  13. package/dist/event-handler.d.ts +23 -0
  14. package/dist/event-handler.d.ts.map +1 -0
  15. package/dist/event-handler.js +241 -0
  16. package/dist/index.d.ts +3 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +14 -6
  19. package/dist/manifest-handler.d.ts +16 -0
  20. package/dist/manifest-handler.d.ts.map +1 -0
  21. package/dist/manifest-handler.js +92 -0
  22. package/dist/manifest-kv-store.d.ts +59 -0
  23. package/dist/manifest-kv-store.d.ts.map +1 -0
  24. package/dist/manifest-kv-store.js +134 -0
  25. package/dist/types.d.ts +7 -15
  26. package/dist/types.d.ts.map +1 -1
  27. package/dist/worker.d.ts +19 -0
  28. package/dist/worker.d.ts.map +1 -1
  29. package/dist/worker.js +41 -0
  30. package/package.json +3 -3
  31. package/src/cloudflare-edge-driver.ts +435 -0
  32. package/src/dispatchers.ts +162 -0
  33. package/src/do-store.ts +13 -0
  34. package/src/durable-object.ts +30 -9
  35. package/src/event-handler.ts +302 -0
  36. package/src/index.ts +32 -8
  37. package/src/manifest-handler.ts +113 -0
  38. package/src/manifest-kv-store.ts +186 -0
  39. package/src/types.ts +7 -19
  40. package/src/worker.ts +64 -0
  41. package/dist/dispatch-handler.d.ts +0 -20
  42. package/dist/dispatch-handler.d.ts.map +0 -1
  43. package/dist/dispatch-handler.js +0 -31
  44. package/src/dispatch-handler.ts +0 -51
@@ -0,0 +1,134 @@
1
+ // KV-backed manifest store for the Cloudflare orchestrator.
2
+ //
3
+ // Mirrors the Mode 2 ManifestStore contract from
4
+ // `@voyantjs/workflows-orchestrator-node`'s `createPostgresManifestStore`,
5
+ // just against KV instead of Postgres. Both are consumed by their
6
+ // respective driver factories — the orchestrator's `WorkflowDriver`
7
+ // shape is identical.
8
+ //
9
+ // Layout in KV:
10
+ //
11
+ // manifest:<environment>:<versionId> → JSON-serialized manifest
12
+ // manifest:<environment>:current → versionId of the active manifest
13
+ //
14
+ // Idempotent: same `(environment, versionId)` overwrite is fine.
15
+ // Latest N versions retained via `pruneToVersions(env, n)`. KV is
16
+ // eventually consistent (~60s globally), which is acceptable for the
17
+ // manifest read path (manifests change at deploy boundaries, not per
18
+ // event).
19
+ // ---- Public factory ----
20
+ /**
21
+ * Build a KV-backed `CfManifestStore`. Stateless — every call hits KV.
22
+ */
23
+ export function createKvManifestStore(opts) {
24
+ const kv = opts.kv;
25
+ return {
26
+ async registerManifest(envelope) {
27
+ const versionKey = manifestVersionKey(envelope.environment, envelope.versionId);
28
+ const currentKey = manifestCurrentKey(envelope.environment);
29
+ // Idempotent overwrite — same body produces the same byte content
30
+ // because manifests are content-addressed (versionId derives from
31
+ // a sha256 of the canonicalized manifest in the SDK).
32
+ await kv.put(versionKey, JSON.stringify(envelope.manifest));
33
+ await kv.put(currentKey, envelope.versionId);
34
+ return { versionId: envelope.versionId };
35
+ },
36
+ async getCurrent(environment) {
37
+ const currentKey = manifestCurrentKey(environment);
38
+ const versionId = await kv.get(currentKey);
39
+ if (!versionId)
40
+ return null;
41
+ const versionKey = manifestVersionKey(environment, versionId);
42
+ const raw = await kv.get(versionKey);
43
+ if (!raw)
44
+ return null;
45
+ let parsed;
46
+ try {
47
+ parsed = JSON.parse(raw);
48
+ }
49
+ catch {
50
+ return null;
51
+ }
52
+ return {
53
+ environment,
54
+ versionId,
55
+ manifest: parsed,
56
+ };
57
+ },
58
+ async pruneToVersions(environment, keep) {
59
+ if (keep < 1) {
60
+ throw new Error(`pruneToVersions: keep must be >= 1, got ${keep}`);
61
+ }
62
+ // List every version key for this environment; sort so we can drop
63
+ // older entries. Lexicographic sort is fine because the SDK's
64
+ // versionId is a hex string of the same length, and KV's natural
65
+ // order is also lexicographic. For deterministic semantics we
66
+ // additionally fetch the `current` pointer and always keep that.
67
+ const prefix = `manifest:${environment}:`;
68
+ const list = await kv.list({ prefix, limit: 1000 });
69
+ const versionKeys = list.keys.map((k) => k.name).filter((name) => !name.endsWith(":current"));
70
+ // Sort newest-first (lexicographic descending).
71
+ versionKeys.sort((a, b) => (a < b ? 1 : a > b ? -1 : 0));
72
+ const currentVersion = await kv.get(manifestCurrentKey(environment));
73
+ const currentKey = currentVersion
74
+ ? manifestVersionKey(environment, currentVersion)
75
+ : undefined;
76
+ const keepers = new Set();
77
+ if (currentKey)
78
+ keepers.add(currentKey);
79
+ for (const k of versionKeys) {
80
+ if (keepers.size >= keep)
81
+ break;
82
+ keepers.add(k);
83
+ }
84
+ let deleted = 0;
85
+ for (const k of versionKeys) {
86
+ if (keepers.has(k))
87
+ continue;
88
+ await kv.delete(k);
89
+ deleted++;
90
+ }
91
+ return { deleted };
92
+ },
93
+ };
94
+ }
95
+ // ---- Key helpers ----
96
+ function manifestVersionKey(environment, versionId) {
97
+ return `manifest:${environment}:${versionId}`;
98
+ }
99
+ function manifestCurrentKey(environment) {
100
+ return `manifest:${environment}:current`;
101
+ }
102
+ // ---- In-memory KV fake (test-only) ----
103
+ /**
104
+ * Tiny in-memory implementation of `KvNamespaceLike` for tests + the CF
105
+ * compliance suite run that doesn't go through wrangler. Mirrors the
106
+ * subset of CF KV semantics we use (list returns matching prefix in
107
+ * lexicographic order; get returns null for missing keys).
108
+ */
109
+ export function createInMemoryKv() {
110
+ const map = new Map();
111
+ return {
112
+ async get(key) {
113
+ return map.has(key) ? map.get(key) : null;
114
+ },
115
+ async put(key, value) {
116
+ map.set(key, value);
117
+ },
118
+ async delete(key) {
119
+ map.delete(key);
120
+ },
121
+ async list(opts) {
122
+ const prefix = opts?.prefix ?? "";
123
+ const limit = opts?.limit ?? 1000;
124
+ const matching = [...map.keys()]
125
+ .filter((k) => k.startsWith(prefix))
126
+ .sort()
127
+ .slice(0, limit);
128
+ return {
129
+ keys: matching.map((name) => ({ name })),
130
+ list_complete: true,
131
+ };
132
+ },
133
+ };
134
+ }
package/dist/types.d.ts CHANGED
@@ -24,16 +24,6 @@ export interface DurableObjectStorageLike {
24
24
  /** Cancel any pending alarm. */
25
25
  deleteAlarm?(): Promise<void>;
26
26
  }
27
- /**
28
- * Subset of a Workers-for-Platforms dispatch namespace. `get(name)`
29
- * returns a binding whose `fetch` delivers to the tenant Worker
30
- * registered under that name.
31
- */
32
- export interface DispatchNamespaceLike {
33
- get(name: string, args?: Record<string, unknown>): {
34
- fetch(request: Request): Promise<Response>;
35
- };
36
- }
37
27
  /** Args the Worker passes when routing to a run DO. */
38
28
  export interface RunOperation {
39
29
  op: "trigger" | "resume" | "cancel" | "get";
@@ -52,8 +42,12 @@ export interface TriggerPayload {
52
42
  tenantId: string;
53
43
  projectId: string;
54
44
  organizationId: string;
55
- /** Dispatch-namespace name to forward step requests to. */
56
- tenantScript: string;
45
+ /**
46
+ * Adapter-specific tenant identifier. Opaque to the OSS runtime —
47
+ * surfaces on `StepDispatcherContext` so custom dispatchers can
48
+ * use it as a routing key.
49
+ */
50
+ tenantScript?: string;
57
51
  };
58
52
  environment?: "production" | "preview" | "development";
59
53
  tags?: string[];
@@ -67,10 +61,8 @@ export interface CancelPayload {
67
61
  * The Worker runtime env the adapter expects. Callers provide their
68
62
  * own wrangler config; this interface documents what we read.
69
63
  */
70
- export interface AdapterEnv<DONamespace = unknown, DispatchNS = DispatchNamespaceLike> {
64
+ export interface AdapterEnv<DONamespace = unknown> {
71
65
  /** Durable Object namespace holding one DO per run. Typed loosely to avoid a CF types dep. */
72
66
  WORKFLOW_RUN_DO: DONamespace;
73
- /** Dispatch namespace containing tenant Workers. */
74
- DISPATCHER: DispatchNS;
75
67
  }
76
68
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AAE1E;;;;;;;;;GASG;AACH,MAAM,WAAW,wBAAwB;IACvC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAA;IAC3C,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACrC,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAA;IAC/E,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACnC,4DAA4D;IAC5D,QAAQ,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACxC,gCAAgC;IAChC,WAAW,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAC9B;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,GAAG,CACD,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B;QACD,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;KAC3C,CAAA;CACF;AAED,uDAAuD;AACvD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,KAAK,CAAA;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,uCAAuC;AACvC,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,kBAAkB,CAAA;CAC9B;AAED,uBAAuB;AACvB,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,eAAe,EAAE,MAAM,CAAA;IACvB,KAAK,EAAE,OAAO,CAAA;IACd,UAAU,EAAE;QACV,QAAQ,EAAE,MAAM,CAAA;QAChB,SAAS,EAAE,MAAM,CAAA;QACjB,cAAc,EAAE,MAAM,CAAA;QACtB,2DAA2D;QAC3D,YAAY,EAAE,MAAM,CAAA;KACrB,CAAA;IACD,WAAW,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,aAAa,CAAA;IACtD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,sBAAsB;AACtB,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU,CAAC,WAAW,GAAG,OAAO,EAAE,UAAU,GAAG,qBAAqB;IACnF,8FAA8F;IAC9F,eAAe,EAAE,WAAW,CAAA;IAC5B,oDAAoD;IACpD,UAAU,EAAE,UAAU,CAAA;CACvB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AAE1E;;;;;;;;;GASG;AACH,MAAM,WAAW,wBAAwB;IACvC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAA;IAC3C,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACrC,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAA;IAC/E,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACnC,4DAA4D;IAC5D,QAAQ,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACxC,gCAAgC;IAChC,WAAW,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAC9B;AAED,uDAAuD;AACvD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,KAAK,CAAA;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,uCAAuC;AACvC,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,kBAAkB,CAAA;CAC9B;AAED,uBAAuB;AACvB,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,eAAe,EAAE,MAAM,CAAA;IACvB,KAAK,EAAE,OAAO,CAAA;IACd,UAAU,EAAE;QACV,QAAQ,EAAE,MAAM,CAAA;QAChB,SAAS,EAAE,MAAM,CAAA;QACjB,cAAc,EAAE,MAAM,CAAA;QACtB;;;;WAIG;QACH,YAAY,CAAC,EAAE,MAAM,CAAA;KACtB,CAAA;IACD,WAAW,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,aAAa,CAAA;IACtD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,sBAAsB;AACtB,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU,CAAC,WAAW,GAAG,OAAO;IAC/C,8FAA8F;IAC9F,eAAe,EAAE,WAAW,CAAA;CAC7B"}
package/dist/worker.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { CfManifestStore } from "./manifest-kv-store.js";
1
2
  /**
2
3
  * Minimal shape of a DO namespace. `idFromName` returns an opaque id;
3
4
  * `get(id)` returns a stub with `fetch` (matching the CF DO API).
@@ -22,6 +23,24 @@ export interface WorkerFetchDeps<Id = unknown> {
22
23
  idGenerator?: () => string;
23
24
  /** Injectable clock for id generation. */
24
25
  now?: () => number;
26
+ /**
27
+ * Optional KV-backed manifest store. When set, the worker also serves
28
+ * `/api/manifests` and `/api/events`. When unset, those routes 404 —
29
+ * useful for orchestrators that only expose the run surface.
30
+ */
31
+ manifestStore?: CfManifestStore;
32
+ /**
33
+ * Tenant metadata stamped on event-triggered runs. Defaults to
34
+ * `{ tenantId: "default", projectId: "default", organizationId: "default" }`.
35
+ * Voyant Cloud's wrapper layer overrides this with per-org values via
36
+ * the request-routing layer.
37
+ */
38
+ tenantMeta?: {
39
+ tenantId: string;
40
+ projectId: string;
41
+ organizationId: string;
42
+ tenantScript?: string;
43
+ };
25
44
  }
26
45
  export declare function handleWorkerRequest<Id>(req: Request, deps: WorkerFetchDeps<Id>): Promise<Response>;
27
46
  //# sourceMappingURL=worker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAeA;;;;GAIG;AACH,MAAM,WAAW,0BAA0B,CAAC,EAAE,GAAG,OAAO;IACtD,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,EAAE,CAAA;IAC5B,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG;QAAE,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAA;CACxD;AAED,MAAM,WAAW,eAAe,CAAC,EAAE,GAAG,OAAO;IAC3C,KAAK,EAAE,0BAA0B,CAAC,EAAE,CAAC,CAAA;IACrC;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtD,uBAAuB;IACvB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/E,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,MAAM,CAAA;IAC1B,0CAA0C;IAC1C,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB;AAED,wBAAsB,mBAAmB,CAAC,EAAE,EAC1C,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,eAAe,CAAC,EAAE,CAAC,GACxB,OAAO,CAAC,QAAQ,CAAC,CA6EnB"}
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAE7D;;;;GAIG;AACH,MAAM,WAAW,0BAA0B,CAAC,EAAE,GAAG,OAAO;IACtD,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,EAAE,CAAA;IAC5B,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG;QAAE,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAA;CACxD;AAED,MAAM,WAAW,eAAe,CAAC,EAAE,GAAG,OAAO;IAC3C,KAAK,EAAE,0BAA0B,CAAC,EAAE,CAAC,CAAA;IACrC;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtD,uBAAuB;IACvB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/E,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,MAAM,CAAA;IAC1B,0CAA0C;IAC1C,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;IAClB;;;;OAIG;IACH,aAAa,CAAC,EAAE,eAAe,CAAA;IAC/B;;;;;OAKG;IACH,UAAU,CAAC,EAAE;QACX,QAAQ,EAAE,MAAM,CAAA;QAChB,SAAS,EAAE,MAAM,CAAA;QACjB,cAAc,EAAE,MAAM,CAAA;QACtB,YAAY,CAAC,EAAE,MAAM,CAAA;KACtB,CAAA;CACF;AAED,wBAAsB,mBAAmB,CAAC,EAAE,EAC1C,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,eAAe,CAAC,EAAE,CAAC,GACxB,OAAO,CAAC,QAAQ,CAAC,CAuHnB"}
package/dist/worker.js CHANGED
@@ -10,6 +10,8 @@
10
10
  // POST /api/runs/:id/events → inject an EVENT waitpoint
11
11
  // POST /api/runs/:id/tokens/:token → inject a MANUAL (token) waitpoint
12
12
  // POST /api/runs/:id/cancel → cancel a run
13
+ import { handleIngestEvent } from "./event-handler.js";
14
+ import { handleGetManifest, handleRegisterManifest } from "./manifest-handler.js";
13
15
  export async function handleWorkerRequest(req, deps) {
14
16
  const url = new URL(req.url);
15
17
  if (req.method === "OPTIONS") {
@@ -28,6 +30,45 @@ export async function handleWorkerRequest(req, deps) {
28
30
  message: err instanceof Error ? err.message : String(err),
29
31
  });
30
32
  }
33
+ // POST /api/manifests — register a manifest for an environment.
34
+ if (req.method === "POST" && url.pathname === "/api/manifests") {
35
+ if (!deps.manifestStore) {
36
+ return json(404, { error: "manifests_not_configured" });
37
+ }
38
+ return handleRegisterManifest(req, {
39
+ manifestStore: deps.manifestStore,
40
+ logger: deps.logger,
41
+ });
42
+ }
43
+ // GET /api/manifests/:env — read the current manifest.
44
+ if (req.method === "GET") {
45
+ const manifestMatch = url.pathname.match(/^\/api\/manifests\/([^/]+)$/);
46
+ if (manifestMatch) {
47
+ if (!deps.manifestStore) {
48
+ return json(404, { error: "manifests_not_configured" });
49
+ }
50
+ const env = decodeURIComponent(manifestMatch[1] ?? "");
51
+ return handleGetManifest(env, {
52
+ manifestStore: deps.manifestStore,
53
+ logger: deps.logger,
54
+ });
55
+ }
56
+ }
57
+ // POST /api/events — synchronous event ingest. Loads the manifest,
58
+ // routes filters, forwards each match to the run-DO trigger flow.
59
+ if (req.method === "POST" && url.pathname === "/api/events") {
60
+ if (!deps.manifestStore) {
61
+ return json(404, { error: "events_not_configured" });
62
+ }
63
+ return handleIngestEvent(req, {
64
+ manifestStore: deps.manifestStore,
65
+ runDO: deps.runDO,
66
+ idGenerator: deps.idGenerator,
67
+ now: deps.now,
68
+ tenantMeta: deps.tenantMeta,
69
+ logger: deps.logger,
70
+ });
71
+ }
31
72
  // POST /api/runs — trigger a new run.
32
73
  if (req.method === "POST" && url.pathname === "/api/runs") {
33
74
  let payload;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voyantjs/workflows-orchestrator-cloudflare",
3
- "version": "0.28.3",
3
+ "version": "0.29.0",
4
4
  "description": "Cloudflare Worker + Durable Object adapter for @voyantjs/workflows-orchestrator. Dispatches workflow-step requests to tenant Workers via a Workers-for-Platforms dispatch namespace.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -26,8 +26,8 @@
26
26
  "NOTICE"
27
27
  ],
28
28
  "dependencies": {
29
- "@voyantjs/workflows-orchestrator": "0.28.3",
30
- "@voyantjs/workflows": "0.28.3"
29
+ "@voyantjs/workflows-orchestrator": "0.29.0",
30
+ "@voyantjs/workflows": "0.29.0"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@cloudflare/vitest-pool-workers": "^0.15.1",