@vite-hub/workflow 0.0.3 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +187 -56
  3. package/dist/{_app-DgwN4ulW.d.ts → app-BojnC_yf.d.ts} +1 -4
  4. package/dist/{app-BZpq2cwC.js → app-CzPoP84f.js} +2 -1
  5. package/dist/client-DsGM3M4U.js +389 -0
  6. package/dist/cloudflare-env-BNrYo29x.js +113 -0
  7. package/dist/cloudflare-nF4abPd4.js +59 -0
  8. package/dist/cloudflare-shared-CaxrMD1A.d.ts +1 -0
  9. package/dist/{cloudflare-vite-B0zel2Do.js → cloudflare-vite-B3IabBsv.js} +18 -10
  10. package/dist/{config-BDqB6I4E.js → config-IJMb0eeZ.js} +39 -25
  11. package/dist/error-diagnostics-A_8Kp-48.js +116 -0
  12. package/dist/error-diagnostics-pwNFvAHP.js +67 -0
  13. package/dist/index.d.ts +24 -20
  14. package/dist/index.js +25 -334
  15. package/dist/inspect-B72iFyj-.js +70 -0
  16. package/dist/operations-B_rYG71W.js +230 -0
  17. package/dist/operations-tNUdj3G4.d.ts +212 -0
  18. package/dist/operations.d.ts +37 -0
  19. package/dist/operations.js +887 -0
  20. package/dist/out-CsaJxg8m.js +21755 -0
  21. package/dist/{provider-operation-CWIV4k42.js → provider-operation-CW2cYfVy.js} +13 -10
  22. package/dist/rolldown-runtime-CMFfr-1z.js +26 -0
  23. package/dist/runtime/cloudflare-runner.d.ts +8 -14
  24. package/dist/runtime/cloudflare-runner.js +77 -14
  25. package/dist/runtime/cloudflare-shared.d.ts +1 -0
  26. package/dist/runtime/cloudflare-shared.js +1 -1
  27. package/dist/runtime/cloudflare-vite.d.ts +8 -9
  28. package/dist/runtime/cloudflare-vite.js +2 -2
  29. package/dist/runtime/execute.d.ts +8 -7
  30. package/dist/runtime/execute.js +28 -5
  31. package/dist/runtime/openworkflow-worker.d.ts +6 -8
  32. package/dist/runtime/openworkflow-worker.js +43 -6
  33. package/dist/runtime/openworkflow.d.ts +8 -10
  34. package/dist/runtime/openworkflow.js +50 -32
  35. package/dist/runtime/state.d.ts +20 -21
  36. package/dist/runtime/state.js +90 -20
  37. package/dist/runtime/vercel-vite.d.ts +10 -11
  38. package/dist/runtime/vercel-vite.js +11 -8
  39. package/dist/runtime-type-DBCvIh5x.js +7 -0
  40. package/dist/{types-BUlYBZwH.d.ts → types-D82WmfZa.d.ts} +35 -18
  41. package/dist/{vercel-D2_J5D_Y.js → vercel-D-ZNtB_u.js} +59 -26
  42. package/dist/vite.d.ts +365 -6
  43. package/dist/vite.js +4667 -910
  44. package/package.json +78 -28
  45. package/dist/cloudflare-Cds1VIWa.js +0 -42
  46. package/dist/cloudflare-env-mFp2Uj6Z.js +0 -53
  47. package/dist/cloudflare-shared-BVVgDSdq.d.ts +0 -1
@@ -1,9 +1,9 @@
1
- import { h as WorkflowDefinitionRegistry, l as ResolvedWorkflowOptions, p as WorkflowDefinition } from "../types-BUlYBZwH.js";
2
-
1
+ import { h as WorkflowDefinitionRegistry, l as ResolvedWorkflowOptions, p as WorkflowDefinition } from "../types-D82WmfZa.js";
3
2
  //#region src/runtime/state.d.ts
4
- interface WorkflowRunState<TResult = unknown> {
3
+ export interface WorkflowRunState<TResult = unknown> {
5
4
  error?: unknown;
6
5
  expiresAt?: number;
6
+ payload?: unknown;
7
7
  promise: Promise<{
8
8
  result?: TResult;
9
9
  status: "completed" | "failed";
@@ -12,24 +12,23 @@ interface WorkflowRunState<TResult = unknown> {
12
12
  result?: TResult;
13
13
  status: "running" | "completed" | "failed";
14
14
  }
15
- declare function setWorkflowRuntimeConfig(config: false | ResolvedWorkflowOptions | undefined): void;
16
- declare function getWorkflowRuntimeConfig(): false | ResolvedWorkflowOptions | undefined;
17
- declare function setWorkflowRuntimeRegistry(registry: WorkflowDefinitionRegistry | undefined): void;
18
- declare function getWorkflowRuntimeRegistry(): WorkflowDefinitionRegistry | undefined;
19
- declare function getInlineWorkflowDefinitions(): ReadonlyMap<string, WorkflowDefinition>;
20
- declare function takeInlineWorkflowDefinition(name: string): WorkflowDefinition | undefined;
21
- declare function takeInlineWorkflowDefinitionForModule(name: string, loaded: unknown): WorkflowDefinition | undefined;
22
- declare function registerInlineWorkflowDefinition(name: string, definition: WorkflowDefinition): void;
23
- declare function enterWorkflowRuntimeEvent(event: unknown): void;
24
- declare function getWorkflowRuntimeEvent(): unknown;
25
- declare function runWithWorkflowRuntimeEvent<T>(event: unknown, run: () => T | Promise<T>): Promise<T>;
26
- declare function loadWorkflowDefinition(name: string): Promise<WorkflowDefinition | undefined>;
27
- declare function setWorkflowRun<TResult = unknown>(name: string, id: string, promise: Promise<{
15
+ export declare function setWorkflowRuntimeConfig(config: false | ResolvedWorkflowOptions | undefined): void;
16
+ export declare function getWorkflowRuntimeConfig(): false | ResolvedWorkflowOptions | undefined;
17
+ export declare function setWorkflowRuntimeRegistry(registry: WorkflowDefinitionRegistry | undefined): void;
18
+ export declare function getWorkflowRuntimeRegistry(): WorkflowDefinitionRegistry | undefined;
19
+ export declare function getInlineWorkflowDefinitions(): ReadonlyMap<string, WorkflowDefinition>;
20
+ export declare function takeInlineWorkflowDefinition(name: string): WorkflowDefinition | undefined;
21
+ export declare function takeInlineWorkflowDefinitionForModule(name: string, loaded: unknown): WorkflowDefinition | undefined;
22
+ export declare function registerInlineWorkflowDefinition(name: string, definition: WorkflowDefinition): void;
23
+ export declare function enterWorkflowRuntimeEvent(event: unknown): void;
24
+ export declare function getWorkflowRuntimeEvent(): unknown;
25
+ export declare function runWithWorkflowRuntimeEvent<T>(event: unknown, run: () => T | Promise<T>): Promise<T>;
26
+ export declare function loadWorkflowDefinition(name: string): Promise<WorkflowDefinition | undefined>;
27
+ export declare function setWorkflowRun<TResult = unknown>(name: string, id: string, promise: Promise<{
28
28
  result?: TResult;
29
29
  status: "completed" | "failed";
30
30
  error?: unknown;
31
- }>): WorkflowRunState<TResult>;
32
- declare function getWorkflowRunState(name: string, id: string): WorkflowRunState | undefined;
33
- declare function resetWorkflowRuntime(): void;
34
- //#endregion
35
- export { WorkflowRunState, enterWorkflowRuntimeEvent, getInlineWorkflowDefinitions, getWorkflowRunState, getWorkflowRuntimeConfig, getWorkflowRuntimeEvent, getWorkflowRuntimeRegistry, loadWorkflowDefinition, registerInlineWorkflowDefinition, resetWorkflowRuntime, runWithWorkflowRuntimeEvent, setWorkflowRun, setWorkflowRuntimeConfig, setWorkflowRuntimeRegistry, takeInlineWorkflowDefinition, takeInlineWorkflowDefinitionForModule };
31
+ }>, payload?: unknown, retainInFlight?: boolean): WorkflowRunState<TResult>;
32
+ export declare function getWorkflowRunState(name: string, id: string): WorkflowRunState | undefined;
33
+ export declare function resetWorkflowRuntime(): void;
34
+ //#endregion
@@ -1,23 +1,34 @@
1
+ import { t as workflowErrorDiagnostics } from "../error-diagnostics-pwNFvAHP.js";
1
2
  import { AsyncLocalStorage } from "node:async_hooks";
2
3
  //#region src/runtime/state.ts
3
4
  const RUNS_LIMIT = 1024;
4
- const RUNS_TTL_MS = 300 * 1e3;
5
+ const RUNS_TTL_MS = 3e5;
5
6
  let runtimeConfig;
6
7
  let runtimeRegistry;
7
8
  const inlineRegistry = /* @__PURE__ */ new Map();
8
9
  const loadingRegistryEntries = /* @__PURE__ */ new Map();
9
10
  const loadedRegistryEntries = /* @__PURE__ */ new Map();
11
+ let runtimeRegistryGeneration = 0;
10
12
  let fallbackEvent;
11
13
  const eventStorage = new AsyncLocalStorage();
12
14
  const loadingRegistryStorage = new AsyncLocalStorage();
13
15
  const loadingInlineRegistryStorage = new AsyncLocalStorage();
16
+ const loadingGenerationStorage = new AsyncLocalStorage();
14
17
  const runs = /* @__PURE__ */ new Map();
18
+ const inFlightRuns = /* @__PURE__ */ new Map();
19
+ const fallbackRunKeys = /* @__PURE__ */ new Set();
20
+ let collectedRuns;
21
+ const completedRuns = /* @__PURE__ */ new Map();
22
+ function isWeakReference(reference) {
23
+ return reference !== null && "deref" in reference;
24
+ }
15
25
  function getRunKey(name, id) {
16
- return `${name}\0${id}`;
26
+ return JSON.stringify([name, id]);
17
27
  }
18
28
  function pruneWorkflowRuns() {
19
29
  const now = Date.now();
20
- for (const [key, run] of runs) if (run.expiresAt && run.expiresAt <= now) runs.delete(key);
30
+ for (const [key, run] of completedRuns) if (run.expiresAt && run.expiresAt <= now) completedRuns.delete(key);
31
+ while (completedRuns.size > RUNS_LIMIT) completedRuns.delete(completedRuns.keys().next().value);
21
32
  }
22
33
  function setWorkflowRuntimeConfig(config) {
23
34
  runtimeConfig = config;
@@ -26,6 +37,8 @@ function getWorkflowRuntimeConfig() {
26
37
  return runtimeConfig;
27
38
  }
28
39
  function setWorkflowRuntimeRegistry(registry) {
40
+ if (runtimeRegistry !== registry) loadingRegistryEntries.clear();
41
+ runtimeRegistryGeneration++;
29
42
  runtimeRegistry = registry;
30
43
  loadedRegistryEntries.clear();
31
44
  }
@@ -42,7 +55,12 @@ function takeInlineWorkflowDefinition(name) {
42
55
  return definition;
43
56
  }
44
57
  function isWorkflowHandle(value) {
45
- return typeof value === "object" && value !== null && typeof value.name === "string" && typeof value.defer === "function" && typeof value.getRun === "function" && typeof value.run === "function";
58
+ if (typeof value !== "object" || value === null) return false;
59
+ const candidate = value;
60
+ if (typeof candidate.name !== "string") return false;
61
+ if (typeof candidate.defer !== "function") return false;
62
+ if (typeof candidate.getRun !== "function") return false;
63
+ return typeof candidate.run === "function";
46
64
  }
47
65
  function findExportedInlineWorkflowDefinition(name, loaded, definitions) {
48
66
  const namedDefinition = definitions.get(name);
@@ -83,13 +101,14 @@ function consumeInlineWorkflowDefinition(name, expected) {
83
101
  return definition;
84
102
  }
85
103
  function registerInlineWorkflowDefinition(name, definition) {
86
- if (!name || typeof name !== "string") throw new TypeError("`createWorkflow()` requires a workflow name.");
104
+ if (!name || typeof name !== "string") throw workflowErrorDiagnostics.WORKFLOW_R0023({ message: "`createWorkflow()` requires a workflow name." });
87
105
  const loadingDefinitions = loadingInlineRegistryStorage.getStore();
106
+ const loadingGeneration = loadingGenerationStorage.getStore();
88
107
  const existing = inlineRegistry.get(name);
89
108
  if (existing && existing !== definition) {
90
- if (!loadingDefinitions) throw new Error(`Duplicate workflow name "${name}" from inline definitions.`);
109
+ if (!loadingDefinitions) throw workflowErrorDiagnostics.WORKFLOW_R0024({ message: `Duplicate workflow name "${name}" from inline definitions.` });
91
110
  }
92
- inlineRegistry.set(name, definition);
111
+ if (loadingGeneration === void 0 || loadingGeneration === runtimeRegistryGeneration) inlineRegistry.set(name, definition);
93
112
  loadingDefinitions?.set(name, definition);
94
113
  }
95
114
  function enterWorkflowRuntimeEvent(event) {
@@ -105,11 +124,12 @@ async function runWithWorkflowRuntimeEvent(event, run) {
105
124
  return await eventStorage.run(event, run);
106
125
  }
107
126
  async function loadWorkflowDefinition(name) {
127
+ const generation = runtimeRegistryGeneration;
108
128
  const inlineDefinition = inlineRegistry.get(name);
109
- const entry = runtimeRegistry?.[name];
129
+ const entry = runtimeRegistry && Object.hasOwn(runtimeRegistry, name) ? runtimeRegistry[name] : void 0;
110
130
  if (entry && loadedRegistryEntries.has(name)) return loadedRegistryEntries.get(name);
111
131
  if (inlineDefinition) {
112
- if (entry) throw new Error(`Duplicate workflow name "${name}" from inline and discovered definitions.`);
132
+ if (entry) throw workflowErrorDiagnostics.WORKFLOW_R0025({ message: `Duplicate workflow name "${name}" from inline and discovered definitions.` });
113
133
  return inlineDefinition;
114
134
  }
115
135
  if (!entry) return;
@@ -120,9 +140,15 @@ async function loadWorkflowDefinition(name) {
120
140
  nextActiveLoads.add(name);
121
141
  const loadingEntry = Promise.resolve().then(() => loadingRegistryStorage.run(nextActiveLoads, async () => {
122
142
  const loadingInlineDefinitions = /* @__PURE__ */ new Map();
123
- const loaded = await loadingInlineRegistryStorage.run(loadingInlineDefinitions, entry);
143
+ let loaded;
144
+ try {
145
+ loaded = await loadingGenerationStorage.run(generation, () => loadingInlineRegistryStorage.run(loadingInlineDefinitions, entry));
146
+ } catch (error) {
147
+ for (const [definitionName, definition] of loadingInlineDefinitions) if (inlineRegistry.get(definitionName) === definition) inlineRegistry.delete(definitionName);
148
+ throw error;
149
+ }
124
150
  if (!loaded || typeof loaded !== "object") return;
125
- const registeredInlineDefinition = loadingInlineDefinitions.get(name) ?? consumeInlineWorkflowDefinition(name);
151
+ const registeredInlineDefinition = loadingInlineDefinitions.get(name) ?? (generation === runtimeRegistryGeneration ? consumeInlineWorkflowDefinition(name) : void 0);
126
152
  if (registeredInlineDefinition) {
127
153
  consumeInlineWorkflowDefinition(name, registeredInlineDefinition);
128
154
  return registeredInlineDefinition;
@@ -137,43 +163,87 @@ async function loadWorkflowDefinition(name) {
137
163
  loadingRegistryEntries.set(name, loadingEntry);
138
164
  try {
139
165
  const loaded = await loadingEntry;
140
- loadedRegistryEntries.set(name, loaded);
166
+ if (generation === runtimeRegistryGeneration && loadingRegistryEntries.get(name) === loadingEntry) loadedRegistryEntries.set(name, loaded);
141
167
  return loaded;
142
168
  } finally {
143
- loadingRegistryEntries.delete(name);
169
+ if (loadingRegistryEntries.get(name) === loadingEntry) loadingRegistryEntries.delete(name);
144
170
  }
145
171
  }
146
- function setWorkflowRun(name, id, promise) {
172
+ function setWorkflowRun(name, id, promise, payload, retainInFlight = false) {
147
173
  pruneWorkflowRuns();
148
- if (runs.size >= RUNS_LIMIT) {
149
- const oldest = runs.keys().next().value;
150
- if (oldest !== void 0) runs.delete(oldest);
151
- }
174
+ const key = getRunKey(name, id);
175
+ const canUseWeakReferences = globalThis.WeakRef !== void 0 && globalThis.FinalizationRegistry !== void 0;
176
+ if (canUseWeakReferences) collectedRuns ??= new FinalizationRegistry(({ key, reference }) => {
177
+ if (runs.get(key) === reference) runs.delete(key);
178
+ });
179
+ const previous = runs.get(key);
180
+ if (previous && canUseWeakReferences) collectedRuns?.unregister(previous);
181
+ fallbackRunKeys.delete(key);
182
+ completedRuns.delete(key);
152
183
  const state = {
184
+ payload,
153
185
  promise: promise.then((resolved) => {
154
186
  state.status = resolved.status;
155
187
  state.result = resolved.result;
156
188
  state.error = resolved.error;
157
189
  state.expiresAt = Date.now() + RUNS_TTL_MS;
190
+ if (inFlightRuns.get(key) === state) inFlightRuns.delete(key);
191
+ const active = runs.get(key);
192
+ if ((active && isWeakReference(active) ? active.deref() : active) === state) {
193
+ runs.delete(key);
194
+ fallbackRunKeys.delete(key);
195
+ if (isWeakReference(reference)) collectedRuns?.unregister(reference);
196
+ completedRuns.set(key, state);
197
+ pruneWorkflowRuns();
198
+ }
158
199
  return resolved;
159
200
  }),
160
201
  status: "running"
161
202
  };
162
- runs.set(getRunKey(name, id), state);
203
+ const reference = canUseWeakReferences ? new WeakRef(state) : state;
204
+ runs.set(key, reference);
205
+ if (retainInFlight) inFlightRuns.set(key, state);
206
+ if (isWeakReference(reference)) collectedRuns?.register(state, {
207
+ key,
208
+ reference
209
+ }, reference);
210
+ else {
211
+ fallbackRunKeys.add(key);
212
+ while (fallbackRunKeys.size > RUNS_LIMIT) {
213
+ const oldest = fallbackRunKeys.values().next().value;
214
+ fallbackRunKeys.delete(oldest);
215
+ runs.delete(oldest);
216
+ inFlightRuns.delete(oldest);
217
+ }
218
+ }
163
219
  return state;
164
220
  }
165
221
  function getWorkflowRunState(name, id) {
166
222
  pruneWorkflowRuns();
167
- return runs.get(getRunKey(name, id));
223
+ const key = getRunKey(name, id);
224
+ const inFlight = inFlightRuns.get(key);
225
+ if (inFlight) return inFlight;
226
+ const reference = runs.get(key);
227
+ const state = reference && isWeakReference(reference) ? reference.deref() : reference;
228
+ if (reference && !state) {
229
+ runs.delete(key);
230
+ if (isWeakReference(reference)) collectedRuns?.unregister(reference);
231
+ }
232
+ return state ?? completedRuns.get(key);
168
233
  }
169
234
  function resetWorkflowRuntime() {
235
+ runtimeRegistryGeneration++;
170
236
  runtimeConfig = void 0;
171
237
  runtimeRegistry = void 0;
172
238
  inlineRegistry.clear();
173
239
  loadingRegistryEntries.clear();
174
240
  loadedRegistryEntries.clear();
175
241
  fallbackEvent = void 0;
242
+ for (const reference of runs.values()) if (isWeakReference(reference)) collectedRuns?.unregister(reference);
176
243
  runs.clear();
244
+ inFlightRuns.clear();
245
+ fallbackRunKeys.clear();
246
+ completedRuns.clear();
177
247
  }
178
248
  //#endregion
179
249
  export { enterWorkflowRuntimeEvent, getInlineWorkflowDefinitions, getWorkflowRunState, getWorkflowRuntimeConfig, getWorkflowRuntimeEvent, getWorkflowRuntimeRegistry, loadWorkflowDefinition, registerInlineWorkflowDefinition, resetWorkflowRuntime, runWithWorkflowRuntimeEvent, setWorkflowRun, setWorkflowRuntimeConfig, setWorkflowRuntimeRegistry, takeInlineWorkflowDefinition, takeInlineWorkflowDefinitionForModule };
@@ -1,7 +1,6 @@
1
- import { h as WorkflowDefinitionRegistry, l as ResolvedWorkflowOptions } from "../types-BUlYBZwH.js";
2
- import { t as WorkflowApp } from "../_app-DgwN4ulW.js";
1
+ import { h as WorkflowDefinitionRegistry, l as ResolvedWorkflowOptions } from "../types-D82WmfZa.js";
2
+ import { t as VitehubApp } from "../app-BojnC_yf.js";
3
3
  import { IncomingMessage, ServerResponse } from "node:http";
4
-
5
4
  //#region src/runtime/vercel.d.ts
6
5
  interface VercelRun {
7
6
  cancel: () => Promise<void>;
@@ -40,7 +39,7 @@ interface VercelWorkflowRuntimeModule {
40
39
  getWorld: () => Promise<{
41
40
  steps: {
42
41
  list: (options: unknown) => Promise<{
43
- cursor?: string;
42
+ cursor?: string | null;
44
43
  data: unknown[];
45
44
  hasMore: boolean;
46
45
  }>;
@@ -48,22 +47,22 @@ interface VercelWorkflowRuntimeModule {
48
47
  }> | {
49
48
  steps: {
50
49
  list: (options: unknown) => Promise<{
51
- cursor?: string;
50
+ cursor?: string | null;
52
51
  data: unknown[];
53
52
  hasMore: boolean;
54
53
  }>;
55
54
  };
56
55
  };
57
56
  }
58
- declare function setVercelWorkflowRuntimeModules(api: VercelWorkflowApiModule, runtime: VercelWorkflowRuntimeModule): void;
57
+ export declare function setVercelWorkflowRuntimeModules(api: VercelWorkflowApiModule, runtime: VercelWorkflowRuntimeModule): void;
59
58
  //#endregion
60
59
  //#region src/runtime/vercel-vite.d.ts
60
+ export declare function runWithVercelWorkflowRuntimeEvent<T>(req: unknown, res: unknown, run: () => T | Promise<T>): Promise<T>;
61
61
  interface WorkflowVercelServerOptions {
62
- app?: WorkflowApp;
62
+ app?: VitehubApp;
63
63
  registry?: WorkflowDefinitionRegistry;
64
64
  workflow?: false | ResolvedWorkflowOptions;
65
65
  }
66
- type WorkflowVercelServer = (req: IncomingMessage, res: ServerResponse) => unknown;
67
- declare function createWorkflowVercelServer(options?: WorkflowVercelServerOptions): WorkflowVercelServer;
68
- //#endregion
69
- export { WorkflowVercelServer, createWorkflowVercelServer, setVercelWorkflowRuntimeModules };
66
+ export type WorkflowVercelServer = (req: IncomingMessage, res: ServerResponse) => unknown;
67
+ export declare function createWorkflowVercelServer(options?: WorkflowVercelServerOptions): WorkflowVercelServer;
68
+ //#endregion
@@ -1,6 +1,6 @@
1
1
  import { runWithWorkflowRuntimeEvent, setWorkflowRuntimeConfig, setWorkflowRuntimeRegistry } from "./state.js";
2
- import { i as setVercelWorkflowRuntimeModules } from "../vercel-D2_J5D_Y.js";
3
- import { t as resolveAppFetch } from "../app-BZpq2cwC.js";
2
+ import { i as setVercelWorkflowRuntimeModules } from "../vercel-D-ZNtB_u.js";
3
+ import { t as resolveAppFetch } from "../app-CzPoP84f.js";
4
4
  import { waitUntil } from "@vercel/functions";
5
5
  import { H3 } from "h3";
6
6
  //#region ../internal/src/runtime/vercel-hosted.ts
@@ -30,6 +30,13 @@ function createVercelHostedServer(adapter) {
30
30
  }
31
31
  //#endregion
32
32
  //#region src/runtime/vercel-vite.ts
33
+ async function runWithVercelWorkflowRuntimeEvent(req, res, run) {
34
+ return await runWithWorkflowRuntimeEvent({
35
+ req,
36
+ res,
37
+ waitUntil
38
+ }, run);
39
+ }
33
40
  function createWorkflowVercelServer(options = {}) {
34
41
  return createVercelHostedServer({
35
42
  app: options.app,
@@ -37,13 +44,9 @@ function createWorkflowVercelServer(options = {}) {
37
44
  onRequest({ handle, req, res }) {
38
45
  setWorkflowRuntimeConfig(options.workflow);
39
46
  setWorkflowRuntimeRegistry(options.registry);
40
- return runWithWorkflowRuntimeEvent({
41
- req,
42
- res,
43
- waitUntil
44
- }, handle);
47
+ return runWithVercelWorkflowRuntimeEvent(req, res, handle);
45
48
  }
46
49
  });
47
50
  }
48
51
  //#endregion
49
- export { createWorkflowVercelServer, setVercelWorkflowRuntimeModules };
52
+ export { createWorkflowVercelServer, runWithVercelWorkflowRuntimeEvent, setVercelWorkflowRuntimeModules };
@@ -0,0 +1,7 @@
1
+ import { hasRuntimeType } from "@vite-hub/runtime/internal/runtime-type";
2
+ //#region src/internal/runtime-type.ts
3
+ function isRuntimeRecord(value) {
4
+ return value !== null && hasRuntimeType(value, "object") && !Array.isArray(value);
5
+ }
6
+ //#endregion
7
+ export { isRuntimeRecord as n, hasRuntimeType as t };
@@ -1,10 +1,10 @@
1
1
  //#region src/types.d.ts
2
2
  type WorkflowProvider = "cloudflare" | "openworkflow" | "vercel";
3
3
  interface CloudflareWorkflowBinding<TPayload = unknown> {
4
- create: (options?: {
5
- id?: string;
4
+ createBatch: (batch: Array<{
5
+ id: string;
6
6
  params?: TPayload;
7
- }) => Promise<CloudflareWorkflowInstance>;
7
+ }>) => Promise<CloudflareWorkflowInstance[]>;
8
8
  get: (id: string) => Promise<CloudflareWorkflowInstance>;
9
9
  }
10
10
  interface CloudflareWorkflowInstance {
@@ -46,14 +46,12 @@ interface OpenWorkflowWorkerOptions {
46
46
  concurrency?: number;
47
47
  }
48
48
  interface OpenWorkflowProviderOptions extends WorkflowSharedOptions {
49
- database?: string;
50
49
  postgres?: OpenWorkflowPostgresOptions;
51
50
  provider: "openworkflow";
52
51
  sqlite?: OpenWorkflowSqliteOptions;
53
52
  worker?: OpenWorkflowWorkerOptions;
54
53
  }
55
54
  interface InferredWorkflowProviderOptions extends WorkflowSharedOptions {
56
- database?: string;
57
55
  postgres?: OpenWorkflowPostgresOptions;
58
56
  provider?: undefined;
59
57
  sqlite?: OpenWorkflowSqliteOptions;
@@ -98,15 +96,20 @@ interface WorkflowStepOptions {
98
96
  type WorkflowStepFunction<TInput = unknown, TResult = unknown> = (input: TInput) => TResult | Promise<TResult>;
99
97
  interface WorkflowProviderStep {
100
98
  do?: <TResult>(name: string, options: WorkflowStepOptions, run: () => TResult | Promise<TResult>) => Promise<TResult>;
99
+ sleep?: (name: string, duration: string) => Promise<void>;
101
100
  }
102
- type WorkflowStepRunner<TSteps extends Record<string, WorkflowStepFunction> = Record<string, WorkflowStepFunction>> = { [TName in keyof TSteps]: TSteps[TName] };
103
- interface WorkflowExecutionContext<TPayload = unknown> {
101
+ type WorkflowStepRunner<TSteps extends Record<string, WorkflowStepFunction> = Record<string, WorkflowStepFunction>> = { [TName in keyof TSteps]: TSteps[TName]; };
102
+ /** Run data that a provider gives to ViteHub before ViteHub adds the step runner. */
103
+ interface WorkflowProviderContext<TPayload = unknown> {
104
104
  id?: string;
105
105
  name: string;
106
106
  payload: TPayload;
107
107
  provider: WorkflowProvider;
108
108
  step?: WorkflowProviderStep;
109
- steps?: WorkflowStepRunner;
109
+ }
110
+ interface WorkflowExecutionContext<TPayload = unknown> extends WorkflowProviderContext<TPayload> {
111
+ /** Step functions from the numbered files in the Workflow folder. Empty when the Workflow has no step files. */
112
+ steps: WorkflowStepRunner;
110
113
  }
111
114
  type WorkflowHandler<TPayload = unknown, TResult = unknown> = (context: WorkflowExecutionContext<TPayload>) => TResult | Promise<TResult>;
112
115
  type WorkflowRunIdValue = boolean | null | number | string | undefined | {
@@ -119,22 +122,28 @@ interface WorkflowCreateOptions<TPayload = unknown, TResult = unknown> {
119
122
  payload?: TPayload;
120
123
  }) => Promise<WorkflowRunIdValue> | WorkflowRunIdValue;
121
124
  name?: string;
125
+ rootStep?: boolean;
122
126
  }
123
127
  interface WorkflowDefinitionOptions<TPayload = unknown, TResult = unknown> {
124
128
  id?: string;
125
- native?: WorkflowHandler<TPayload, TResult>;
129
+ /** Vercel native entry. Vercel calls it with the provider context only, so it gets no step runner. */
130
+ native?: (context: WorkflowProviderContext<TPayload>) => TResult | Promise<TResult>;
126
131
  rootStep?: boolean;
127
132
  }
128
133
  interface WorkflowDefinition<TPayload = unknown, TResult = unknown> {
134
+ /** @internal Identifies provider-generated Agent invocation recovery definitions. */
135
+ internalAgentInvocationRecovery?: true;
129
136
  handler: WorkflowHandler<TPayload, TResult>;
130
137
  options?: WorkflowDefinitionOptions<TPayload, TResult>;
131
138
  }
139
+ /** Omission is valid only when the handler accepts undefined. */
140
+ type WorkflowStartArguments<TPayload> = undefined extends TPayload ? [payload?: TPayload, options?: WorkflowStartOptions] : [payload: TPayload, options?: WorkflowStartOptions];
132
141
  interface WorkflowHandle<TPayload = unknown, TResult = unknown> {
133
- cancel: (id: string) => Promise<WorkflowRun<TPayload, TResult>>;
134
- defer: (payload?: TPayload, options?: WorkflowStartOptions) => Promise<WorkflowRun<TPayload>>;
135
- getRun: (id: string) => Promise<WorkflowRun<TPayload, TResult>>;
142
+ cancel: (id: string) => Promise<WorkflowRun<unknown, unknown>>;
143
+ defer: (...args: WorkflowStartArguments<TPayload>) => Promise<WorkflowRun<TPayload>>;
144
+ getRun: (id: string) => Promise<WorkflowRun<unknown, unknown>>;
136
145
  name: string;
137
- run: (payload?: TPayload, options?: WorkflowStartOptions) => Promise<WorkflowRun<TPayload, TResult>>;
146
+ run: (...args: WorkflowStartArguments<TPayload>) => Promise<WorkflowRun<TPayload, TResult>>;
138
147
  }
139
148
  interface WorkflowStartOptions {
140
149
  id?: string;
@@ -146,18 +155,26 @@ interface WorkflowSignalResult {
146
155
  id: string;
147
156
  provider: WorkflowProvider;
148
157
  }
158
+ /**
159
+ * Maps Workflow names to module loaders. The registry does not know each
160
+ * payload type, so it uses `never` as the payload. A definition with any
161
+ * payload type fits without a cast.
162
+ */
149
163
  interface WorkflowDefinitionRegistry {
150
- [name: string]: () => Promise<{
151
- default?: WorkflowDefinition;
164
+ [name: string]: (() => Promise<{
165
+ default?: WorkflowDefinition<never>;
152
166
  [exportName: string]: unknown;
153
- } | WorkflowDefinition>;
167
+ } | WorkflowDefinition<never>>) & {
168
+ /** @internal Identifies provider-generated Agent invocation recovery definitions without evaluating their modules. */
169
+ internalAgentInvocationRecovery?: true;
170
+ };
154
171
  }
155
172
  interface DiscoveredWorkflowDefinition {
156
173
  agentIdentity?: string;
157
174
  handler: string;
158
175
  name: string;
159
- source?: "agent-workflow" | "inline" | "server-workflows" | "vite-suffix";
176
+ source?: "agent-workflow" | "agent-workflow-recovery" | "inline" | "server-workflows" | "vite-suffix";
160
177
  steps?: string[];
161
178
  }
162
179
  //#endregion
163
- export { WorkflowStepFunction as A, WorkflowProviderStep as C, WorkflowSharedOptions as D, WorkflowRunStep as E, WorkflowStepRunner as M, WorkflowSignalResult as O, WorkflowProviderOptions as S, WorkflowRunStatus as T, WorkflowHandle as _, InferredWorkflowProviderOptions as a, WorkflowModuleProviderOptions as b, OpenWorkflowWorkerOptions as c, WorkflowCreateOptions as d, WorkflowDeferOptions as f, WorkflowExecutionContext as g, WorkflowDefinitionRegistry as h, DiscoveredWorkflowDefinition as i, WorkflowStepOptions as j, WorkflowStartOptions as k, ResolvedWorkflowOptions as l, WorkflowDefinitionOptions as m, CloudflareWorkflowInstance as n, OpenWorkflowPostgresOptions as o, WorkflowDefinition as p, CloudflareWorkflowProviderOptions as r, OpenWorkflowProviderOptions as s, CloudflareWorkflowBinding as t, VercelWorkflowProviderOptions as u, WorkflowHandler as v, WorkflowRun as w, WorkflowProvider as x, WorkflowModuleOptions as y };
180
+ export { WorkflowStartOptions as A, WorkflowProviderOptions as C, WorkflowRunStep as D, WorkflowRunStatus as E, WorkflowStepOptions as M, WorkflowStepRunner as N, WorkflowSharedOptions as O, WorkflowProviderContext as S, WorkflowRun as T, WorkflowHandle as _, InferredWorkflowProviderOptions as a, WorkflowModuleProviderOptions as b, OpenWorkflowWorkerOptions as c, WorkflowCreateOptions as d, WorkflowDeferOptions as f, WorkflowExecutionContext as g, WorkflowDefinitionRegistry as h, DiscoveredWorkflowDefinition as i, WorkflowStepFunction as j, WorkflowSignalResult as k, ResolvedWorkflowOptions as l, WorkflowDefinitionOptions as m, CloudflareWorkflowInstance as n, OpenWorkflowPostgresOptions as o, WorkflowDefinition as p, CloudflareWorkflowProviderOptions as r, OpenWorkflowProviderOptions as s, CloudflareWorkflowBinding as t, VercelWorkflowProviderOptions as u, WorkflowHandler as v, WorkflowProviderStep as w, WorkflowProvider as x, WorkflowModuleOptions as y };
@@ -1,4 +1,6 @@
1
- import { i as createWorkflowError, n as runWorkflowProviderOperation, r as safeWorkflowName, t as isWorkflowBoundaryError } from "./provider-operation-CWIV4k42.js";
1
+ import { t as workflowErrorDiagnostics } from "./error-diagnostics-pwNFvAHP.js";
2
+ import { t as hasRuntimeType } from "./runtime-type-DBCvIh5x.js";
3
+ import { a as createWorkflowError, i as safeWorkflowName, n as isWorkflowBoundaryError, r as runWorkflowProviderOperation } from "./provider-operation-CW2cYfVy.js";
2
4
  //#region src/runtime/vercel.ts
3
5
  async function loadVercelWorkflowRuntime() {
4
6
  const importVercelWorkflow = new Function("specifier", "return import(specifier)");
@@ -12,9 +14,10 @@ function createVercelWorkflowRuntime(api, runtime) {
12
14
  getRun,
13
15
  async listSteps(id) {
14
16
  const steps = [];
17
+ const cursors = /* @__PURE__ */ new Set();
15
18
  let cursor;
16
19
  do {
17
- const page = await (await getWorld()).steps.list({
20
+ const page = normalizeStepPage(await (await getWorld()).steps.list({
18
21
  pagination: {
19
22
  cursor,
20
23
  limit: 1e3,
@@ -22,9 +25,12 @@ function createVercelWorkflowRuntime(api, runtime) {
22
25
  },
23
26
  resolveData: "none",
24
27
  runId: id
25
- });
28
+ }));
26
29
  steps.push(...page.data);
27
- cursor = page.hasMore && page.cursor ? page.cursor : void 0;
30
+ if (!page.hasMore) break;
31
+ if (!hasRuntimeType(page.cursor, "string") || !page.cursor || cursors.has(page.cursor)) throw invalidVercelResult("step pagination cursor");
32
+ cursors.add(page.cursor);
33
+ cursor = page.cursor;
28
34
  } while (cursor);
29
35
  return steps;
30
36
  },
@@ -56,35 +62,55 @@ const statusMap = {
56
62
  running: "running"
57
63
  };
58
64
  function invalidVercelResult(field) {
59
- return /* @__PURE__ */ new TypeError(`Vercel Workflow provider returned an invalid ${field}.`);
65
+ return workflowErrorDiagnostics.WORKFLOW_R0026({ message: `Vercel Workflow provider returned an invalid ${field}.` });
66
+ }
67
+ function normalizeStepPage(page) {
68
+ if (!hasRuntimeType(page, "object") || page === null || Array.isArray(page)) throw invalidVercelResult("step page");
69
+ const { cursor, data, hasMore } = page;
70
+ if (!Array.isArray(data)) throw invalidVercelResult("step page data");
71
+ if (!hasRuntimeType(hasMore, "boolean")) throw invalidVercelResult("step page hasMore flag");
72
+ if (cursor !== void 0 && cursor !== null && !hasRuntimeType(cursor, "string")) throw invalidVercelResult("step page cursor");
73
+ return {
74
+ ...cursor === void 0 || cursor === null ? {} : { cursor },
75
+ data,
76
+ hasMore
77
+ };
60
78
  }
61
79
  function normalizeStatus(status) {
62
- if (typeof status !== "string") throw invalidVercelResult("status");
63
- return statusMap[status.toLowerCase()] || "unknown";
80
+ if (!hasRuntimeType(status, "string")) throw invalidVercelResult("status");
81
+ const normalized = status.toLowerCase();
82
+ return Object.hasOwn(statusMap, normalized) ? statusMap[normalized] : "unknown";
64
83
  }
65
84
  function normalizeRunId(id) {
66
- if (typeof id !== "string" || !id) throw invalidVercelResult("run ID");
85
+ if (!hasRuntimeType(id, "string") || !id) throw invalidVercelResult("run ID");
67
86
  return id;
68
87
  }
69
88
  function normalizeDate(value, field) {
70
89
  if (value === void 0) return void 0;
71
- if (!(value instanceof Date) || !Number.isFinite(value.getTime())) throw invalidVercelResult(field);
72
- return value;
90
+ let timestamp;
91
+ try {
92
+ timestamp = Date.prototype.getTime.call(value);
93
+ } catch {
94
+ throw invalidVercelResult(field);
95
+ }
96
+ if (!Number.isFinite(timestamp)) throw invalidVercelResult(field);
97
+ return new Date(timestamp);
73
98
  }
74
99
  function normalizeStepError(error) {
75
100
  if (error === void 0 || error === null) return void 0;
76
101
  if (error instanceof Error) return { message: error.message };
77
- if (typeof error === "string") try {
102
+ if (hasRuntimeType(error, "string")) try {
78
103
  return normalizeStepError(JSON.parse(error)) || { message: error };
79
104
  } catch {
80
105
  return { message: error };
81
106
  }
82
- if (typeof error === "object") {
107
+ if (hasRuntimeType(error, "object") && error) {
83
108
  const value = error;
84
- if (typeof value.message === "string") return {
85
- ...typeof value.code === "string" ? { code: value.code } : {},
86
- message: value.message
87
- };
109
+ if (hasRuntimeType(value.message, "string")) {
110
+ const normalized = { message: value.message };
111
+ if (hasRuntimeType(value.code, "string")) normalized.code = value.code;
112
+ return normalized;
113
+ }
88
114
  if (value.error !== void 0) return normalizeStepError(value.error);
89
115
  }
90
116
  return { message: "Workflow step failed." };
@@ -92,11 +118,11 @@ function normalizeStepError(error) {
92
118
  function normalizeSteps(steps) {
93
119
  if (!Array.isArray(steps)) throw invalidVercelResult("step list");
94
120
  return steps.map((step) => {
95
- if (typeof step !== "object" || step === null) throw invalidVercelResult("step");
121
+ if (!hasRuntimeType(step, "object") || step === null) throw invalidVercelResult("step");
96
122
  const value = step;
97
- if (typeof value.attempt !== "number" || !Number.isFinite(value.attempt)) throw invalidVercelResult("step attempt");
98
- if (typeof value.stepId !== "string" || !value.stepId) throw invalidVercelResult("step ID");
99
- if (typeof value.stepName !== "string" || !value.stepName) throw invalidVercelResult("step name");
123
+ if (!hasRuntimeType(value.attempt, "number") || !Number.isFinite(value.attempt)) throw invalidVercelResult("step attempt");
124
+ if (!hasRuntimeType(value.stepId, "string") || !value.stepId) throw invalidVercelResult("step ID");
125
+ if (!hasRuntimeType(value.stepName, "string") || !value.stepName) throw invalidVercelResult("step name");
100
126
  return {
101
127
  attempt: value.attempt,
102
128
  completedAt: normalizeDate(value.completedAt, "step completion date"),
@@ -110,10 +136,10 @@ function normalizeSteps(steps) {
110
136
  }
111
137
  async function readRunIdentity(run) {
112
138
  const exists = await run.exists;
113
- if (typeof exists !== "boolean") throw invalidVercelResult("existence state");
139
+ if (!hasRuntimeType(exists, "boolean")) throw invalidVercelResult("existence state");
114
140
  if (!exists) return { exists };
115
141
  const workflowName = await run.workflowName;
116
- if (typeof workflowName !== "string") throw invalidVercelResult("workflow name");
142
+ if (!hasRuntimeType(workflowName, "string")) throw invalidVercelResult("workflow name");
117
143
  return {
118
144
  exists,
119
145
  workflowName
@@ -167,7 +193,7 @@ async function inspectVercelWorkflowRun(name, definition, id, payload) {
167
193
  steps
168
194
  };
169
195
  }
170
- async function startVercelWorkflow(name, definition, payload) {
196
+ async function startVercelWorkflow(name, definition, payload, observeSettlement, onDispatch) {
171
197
  const native = definition.options?.native;
172
198
  if (!native) throw createWorkflowError({
173
199
  code: "WORKFLOW_NATIVE_ENTRY_REQUIRED",
@@ -182,10 +208,17 @@ async function startVercelWorkflow(name, definition, payload) {
182
208
  provider: "vercel"
183
209
  };
184
210
  const runtime = await getVercelWorkflowRuntime();
211
+ onDispatch?.();
212
+ const { id, run } = await runWorkflowProviderOperation("vercel", "start", async () => {
213
+ const run = await runtime.start(native, [context]);
214
+ return {
215
+ id: normalizeRunId(run.runId),
216
+ run
217
+ };
218
+ });
219
+ observeSettlement?.(Promise.resolve(run.returnValue).then(() => void 0, () => void 0));
185
220
  return {
186
- id: await runWorkflowProviderOperation("vercel", "start", async () => {
187
- return normalizeRunId((await runtime.start(native, [context])).runId);
188
- }),
221
+ id,
189
222
  metadata: { workflow: name },
190
223
  payload,
191
224
  provider: "vercel",