@vite-hub/workflow 0.0.0 → 0.0.1

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 (37) hide show
  1. package/README.md +60 -1
  2. package/dist/_app-BVWpnNHo.d.ts +11 -0
  3. package/dist/app-BE3EYOWn.js +10 -0
  4. package/dist/cloudflare-CeHVSHoN.js +42 -0
  5. package/dist/cloudflare-env-BVUMOgFK.d.ts +21 -0
  6. package/dist/cloudflare-env-g0Rf3ClH.js +49 -0
  7. package/dist/cloudflare-shared-BIeY2kak.d.ts +1 -0
  8. package/dist/cloudflare-vite-DcM5YVTP.js +40 -0
  9. package/dist/config-DkgsQuXz.js +92 -0
  10. package/dist/index.d.ts +65 -0
  11. package/dist/index.js +369 -0
  12. package/dist/module-UYEnVfxy.js +1546 -0
  13. package/dist/nitro.d.ts +19 -0
  14. package/dist/nitro.js +2 -0
  15. package/dist/openworkflow-amN7IkGO.d.ts +24 -0
  16. package/dist/runtime/cloudflare-runner.d.ts +27 -0
  17. package/dist/runtime/cloudflare-runner.js +23 -0
  18. package/dist/runtime/cloudflare-shared.d.ts +2 -0
  19. package/dist/runtime/cloudflare-shared.js +2 -0
  20. package/dist/runtime/cloudflare-vite.d.ts +17 -0
  21. package/dist/runtime/cloudflare-vite.js +2 -0
  22. package/dist/runtime/execute.d.ts +11 -0
  23. package/dist/runtime/execute.js +25 -0
  24. package/dist/runtime/nitro-plugin.d.ts +6 -0
  25. package/dist/runtime/nitro-plugin.js +14 -0
  26. package/dist/runtime/openworkflow-worker.d.ts +18 -0
  27. package/dist/runtime/openworkflow-worker.js +55 -0
  28. package/dist/runtime/openworkflow.d.ts +2 -0
  29. package/dist/runtime/openworkflow.js +143 -0
  30. package/dist/runtime/state.d.ts +35 -0
  31. package/dist/runtime/state.js +179 -0
  32. package/dist/runtime/vercel-vite.d.ts +14 -0
  33. package/dist/runtime/vercel-vite.js +48 -0
  34. package/dist/types-ThDitg7Z.d.ts +121 -0
  35. package/dist/vite.d.ts +16 -0
  36. package/dist/vite.js +503 -0
  37. package/package.json +93 -5
package/dist/index.js ADDED
@@ -0,0 +1,369 @@
1
+ import { t as normalizeWorkflowOptions } from "./config-DkgsQuXz.js";
2
+ import { a as encodeNameHex, i as getCloudflareWorkflowName, n as getCloudflareWorkflowBindingName, r as getCloudflareWorkflowClassName } from "./cloudflare-CeHVSHoN.js";
3
+ import { n as getCloudflareEnv, r as resolveWaitUntil } from "./cloudflare-env-g0Rf3ClH.js";
4
+ import { runWorkflowHandler } from "./runtime/execute.js";
5
+ import { getOpenWorkflowRun, runOpenWorkflow } from "./runtime/openworkflow.js";
6
+ import { getWorkflowRunState, getWorkflowRuntimeConfig, getWorkflowRuntimeEvent, loadWorkflowDefinition, registerInlineWorkflowDefinition, runWithWorkflowRuntimeEvent, setWorkflowRun } from "./runtime/state.js";
7
+ import { t as createWorkflowCloudflareWorker } from "./cloudflare-vite-DcM5YVTP.js";
8
+ import { createOpenWorkflowWorker, startOpenWorkflowWorker } from "./runtime/openworkflow-worker.js";
9
+ //#region src/definition.ts
10
+ function defineWorkflow(handler, options) {
11
+ if (typeof handler !== "function") throw new TypeError("`defineWorkflow()` requires a workflow handler.");
12
+ if (typeof options !== "undefined" && (!options || typeof options !== "object" || Array.isArray(options))) throw new TypeError("`defineWorkflow()` options must be a plain object.");
13
+ return {
14
+ handler,
15
+ options
16
+ };
17
+ }
18
+ //#endregion
19
+ //#region src/errors.ts
20
+ var WorkflowError = class extends Error {
21
+ code;
22
+ details;
23
+ httpStatus;
24
+ provider;
25
+ constructor(message, options = {}) {
26
+ super(message);
27
+ this.name = "WorkflowError";
28
+ this.cause = options.cause;
29
+ this.code = options.code;
30
+ this.details = options.details;
31
+ this.httpStatus = options.httpStatus;
32
+ this.provider = options.provider;
33
+ }
34
+ };
35
+ //#endregion
36
+ //#region src/integrations/vercel.ts
37
+ function getVercelWorkflowName(name) {
38
+ return `workflow--${encodeNameHex(name)}`;
39
+ }
40
+ //#endregion
41
+ //#region ../internal/src/runtime/random.ts
42
+ function randomId(prefix) {
43
+ const body = `${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
44
+ return prefix ? `${prefix}_${body}` : body;
45
+ }
46
+ //#endregion
47
+ //#region src/runtime/vercel-state.ts
48
+ const RUNS_TTL_SECONDS = 300;
49
+ function readEnv(name) {
50
+ const value = globalThis.process?.env?.[name];
51
+ return value && value.trim() ? value : void 0;
52
+ }
53
+ function getUpstashConfig() {
54
+ const url = readEnv("KV_REST_API_URL") || readEnv("UPSTASH_REDIS_REST_URL");
55
+ const token = readEnv("KV_REST_API_TOKEN") || readEnv("UPSTASH_REDIS_REST_TOKEN");
56
+ return url && token ? {
57
+ token,
58
+ url
59
+ } : void 0;
60
+ }
61
+ function getRunKey(name, id) {
62
+ return `vitehub:workflow:runs:${encodeURIComponent(name)}:${encodeURIComponent(id)}`;
63
+ }
64
+ async function command(body) {
65
+ const config = getUpstashConfig();
66
+ if (!config || typeof fetch !== "function") return;
67
+ try {
68
+ const response = await fetch(config.url, {
69
+ body: JSON.stringify(body),
70
+ headers: {
71
+ authorization: `Bearer ${config.token}`,
72
+ "content-type": "application/json"
73
+ },
74
+ method: "POST"
75
+ });
76
+ if (!response.ok) return;
77
+ return (await response.json()).result;
78
+ } catch {
79
+ return;
80
+ }
81
+ }
82
+ async function setVercelWorkflowRunState(name, id, run) {
83
+ const value = JSON.stringify(run);
84
+ await command([
85
+ "SET",
86
+ getRunKey(name, id),
87
+ value,
88
+ "EX",
89
+ RUNS_TTL_SECONDS
90
+ ]);
91
+ }
92
+ async function getVercelWorkflowRunState(name, id) {
93
+ const value = await command(["GET", getRunKey(name, id)]);
94
+ if (!value) return;
95
+ try {
96
+ const parsed = JSON.parse(value);
97
+ return parsed && typeof parsed.status === "string" ? parsed : void 0;
98
+ } catch {
99
+ return;
100
+ }
101
+ }
102
+ //#endregion
103
+ //#region src/runtime/adapters.ts
104
+ function resolveCloudflareBinding(event, binding, name) {
105
+ const bindingName = binding || getCloudflareWorkflowBindingName(name);
106
+ return getCloudflareEnv(event)?.[bindingName];
107
+ }
108
+ const cloudflareStatusMap = {
109
+ complete: "completed",
110
+ completed: "completed",
111
+ errored: "failed",
112
+ failed: "failed",
113
+ queued: "queued",
114
+ running: "running",
115
+ success: "completed",
116
+ terminated: "failed"
117
+ };
118
+ function normalizeCloudflareStatus(status) {
119
+ const value = typeof status === "object" && status ? status.status : status;
120
+ return cloudflareStatusMap[String(value || "").toLowerCase()] || "unknown";
121
+ }
122
+ function createCloudflareAdapter(config) {
123
+ return {
124
+ async get({ event, id, name }) {
125
+ const binding = resolveCloudflareBinding(event, config.binding, name);
126
+ if (binding) {
127
+ const metadata = await (await binding.get(id)).status();
128
+ return {
129
+ id,
130
+ metadata,
131
+ provider: "cloudflare",
132
+ status: normalizeCloudflareStatus(metadata)
133
+ };
134
+ }
135
+ return await inlineAdapter(config).get({
136
+ event,
137
+ id,
138
+ name
139
+ });
140
+ },
141
+ async run({ definition, event, id, name, options, payload }) {
142
+ const binding = resolveCloudflareBinding(event, config.binding, name);
143
+ if (binding) {
144
+ const start = binding.create({
145
+ id,
146
+ params: payload
147
+ });
148
+ const waitUntil = options.deferred ? resolveWaitUntil(event) : void 0;
149
+ if (waitUntil) waitUntil(start);
150
+ const instance = await start;
151
+ return {
152
+ id: instance.id,
153
+ metadata: await instance.status(),
154
+ payload,
155
+ provider: "cloudflare",
156
+ status: "queued"
157
+ };
158
+ }
159
+ return await inlineAdapter(config).run({
160
+ definition,
161
+ event,
162
+ id,
163
+ name,
164
+ options,
165
+ payload
166
+ });
167
+ }
168
+ };
169
+ }
170
+ function createOpenWorkflowAdapter(config) {
171
+ return {
172
+ get: async ({ id, name }) => await getOpenWorkflowRun(config, name, id),
173
+ run: async ({ definition, name, options, payload }) => await runOpenWorkflow(config, name, payload, definition, options)
174
+ };
175
+ }
176
+ function inlineAdapter(config) {
177
+ return {
178
+ async get({ id, name }) {
179
+ const run = getWorkflowRunState(name, id);
180
+ if (run) {
181
+ if (run.status === "running") return {
182
+ id,
183
+ provider: config.provider,
184
+ status: "running"
185
+ };
186
+ return {
187
+ id,
188
+ metadata: run.error,
189
+ provider: config.provider,
190
+ result: run.result,
191
+ status: run.status
192
+ };
193
+ }
194
+ if (config.provider === "vercel") {
195
+ const persisted = await getVercelWorkflowRunState(name, id);
196
+ if (persisted) return {
197
+ id,
198
+ metadata: persisted.error,
199
+ provider: "vercel",
200
+ result: persisted.result,
201
+ status: persisted.status
202
+ };
203
+ }
204
+ return {
205
+ id,
206
+ provider: config.provider,
207
+ status: "unknown"
208
+ };
209
+ },
210
+ async run({ definition, event, id, name, payload }) {
211
+ const runState = setWorkflowRun(name, id, Promise.resolve().then(() => runWorkflowHandler({
212
+ id,
213
+ name,
214
+ payload,
215
+ provider: config.provider
216
+ }, definition)).then((result) => ({
217
+ result,
218
+ status: "completed"
219
+ })).catch((error) => ({
220
+ error,
221
+ status: "failed"
222
+ })));
223
+ const persistStarted = config.provider === "vercel" ? setVercelWorkflowRunState(name, id, { status: "running" }).catch(() => {}) : Promise.resolve();
224
+ const persistFinished = config.provider === "vercel" ? runState.promise.then((result) => setVercelWorkflowRunState(name, id, result)).catch(() => {}) : Promise.resolve();
225
+ const waitUntil = resolveWaitUntil(event);
226
+ if (waitUntil) waitUntil(Promise.all([runState.promise, persistFinished]));
227
+ await persistStarted;
228
+ return {
229
+ id,
230
+ metadata: config.provider === "vercel" ? { workflow: getVercelWorkflowName(name) } : void 0,
231
+ payload,
232
+ provider: config.provider,
233
+ status: "queued"
234
+ };
235
+ }
236
+ };
237
+ }
238
+ function getWorkflowRuntimeAdapter(config) {
239
+ if (config.provider === "cloudflare") return createCloudflareAdapter(config);
240
+ if (config.provider === "openworkflow") return createOpenWorkflowAdapter(config);
241
+ return inlineAdapter(config);
242
+ }
243
+ //#endregion
244
+ //#region src/runtime/client.ts
245
+ function getActiveWorkflowConfig() {
246
+ const config = getWorkflowRuntimeConfig();
247
+ if (config === false) return false;
248
+ return config || normalizeWorkflowOptions(void 0, { hosting: "vercel" });
249
+ }
250
+ async function loadRequiredWorkflowDefinition(name) {
251
+ const definition = await loadWorkflowDefinition(name);
252
+ if (!definition) throw new WorkflowError(`Unknown workflow definition: ${name}`, {
253
+ code: "WORKFLOW_DEFINITION_NOT_FOUND",
254
+ details: { name },
255
+ httpStatus: 404
256
+ });
257
+ return definition;
258
+ }
259
+ function normalizeWorkflowRunIdValue(value) {
260
+ if (value === void 0) return null;
261
+ if (value === null || typeof value !== "object") return value;
262
+ if (Array.isArray(value)) return value.map((item) => normalizeWorkflowRunIdValue(item));
263
+ const record = value;
264
+ return Object.fromEntries(Object.keys(record).filter((key) => record[key] !== void 0).sort().map((key) => [key, normalizeWorkflowRunIdValue(record[key])]));
265
+ }
266
+ async function sha256Hex(value) {
267
+ const data = new TextEncoder().encode(value);
268
+ const digest = await crypto.subtle.digest("SHA-256", data);
269
+ return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
270
+ }
271
+ async function createStableWorkflowRunId(name, value) {
272
+ const hash = await sha256Hex(`${name}:${JSON.stringify(normalizeWorkflowRunIdValue(value))}`);
273
+ return `${name.replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "") || "workflow"}-${hash.slice(0, 32)}`;
274
+ }
275
+ async function resolveWorkflowStartOptions(name, payload, createOptions, startOptions) {
276
+ if (startOptions.id || !createOptions?.id) return startOptions;
277
+ return {
278
+ ...startOptions,
279
+ id: await createStableWorkflowRunId(name, await createOptions.id({
280
+ name,
281
+ payload
282
+ }))
283
+ };
284
+ }
285
+ function createWorkflow(nameOrOptions, handlerOrOptions, options) {
286
+ if (typeof nameOrOptions === "object" && nameOrOptions !== null) {
287
+ const createOptions = nameOrOptions;
288
+ const { handler, name } = createOptions;
289
+ if (!name || typeof name !== "string") throw new TypeError("`createWorkflow()` requires a workflow name.");
290
+ if (typeof handler !== "function") throw new TypeError("`createWorkflow()` requires a workflow handler.");
291
+ registerInlineWorkflowDefinition(name, { handler });
292
+ return {
293
+ name,
294
+ defer: async (payload, options = {}) => deferWorkflow(name, payload, await resolveWorkflowStartOptions(name, payload, createOptions, options)),
295
+ getRun: (id) => getWorkflowRun(name, id),
296
+ run: async (payload, options = {}) => runWorkflow(name, payload, await resolveWorkflowStartOptions(name, payload, createOptions, options))
297
+ };
298
+ }
299
+ const name = nameOrOptions;
300
+ if (!name || typeof name !== "string") throw new TypeError("`createWorkflow()` requires a workflow name.");
301
+ const handler = typeof handlerOrOptions === "function" ? handlerOrOptions : typeof handlerOrOptions === "object" && handlerOrOptions !== null ? handlerOrOptions.handler : void 0;
302
+ const createOptions = typeof handlerOrOptions === "function" ? options : handlerOrOptions;
303
+ if (handler !== void 0) {
304
+ if (typeof handler !== "function") throw new TypeError("`createWorkflow()` requires a workflow handler.");
305
+ registerInlineWorkflowDefinition(name, { handler });
306
+ } else if (handlerOrOptions !== void 0 && (typeof handlerOrOptions !== "object" || handlerOrOptions === null)) throw new TypeError("`createWorkflow()` options must be an object.");
307
+ return {
308
+ name,
309
+ defer: async (payload, options = {}) => deferWorkflow(name, payload, await resolveWorkflowStartOptions(name, payload, createOptions, options)),
310
+ getRun: (id) => getWorkflowRun(name, id),
311
+ run: async (payload, options = {}) => runWorkflow(name, payload, await resolveWorkflowStartOptions(name, payload, createOptions, options))
312
+ };
313
+ }
314
+ async function runWorkflow(name, payload, options = {}) {
315
+ const config = getActiveWorkflowConfig();
316
+ if (config === false) throw new WorkflowError("Workflow is disabled.", {
317
+ code: "WORKFLOW_DISABLED",
318
+ httpStatus: 400
319
+ });
320
+ const id = options.id || randomId("wrun");
321
+ const definition = await loadRequiredWorkflowDefinition(name);
322
+ return await getWorkflowRuntimeAdapter(config).run({
323
+ definition,
324
+ event: getWorkflowRuntimeEvent(),
325
+ id,
326
+ name,
327
+ options,
328
+ payload
329
+ });
330
+ }
331
+ async function getWorkflowRun(name, id) {
332
+ const config = getActiveWorkflowConfig();
333
+ if (config === false) throw new WorkflowError("Workflow is disabled.", {
334
+ code: "WORKFLOW_DISABLED",
335
+ httpStatus: 400
336
+ });
337
+ return await getWorkflowRuntimeAdapter(config).get({
338
+ event: getWorkflowRuntimeEvent(),
339
+ id,
340
+ name
341
+ });
342
+ }
343
+ function deferWorkflow(name, payload, options = {}) {
344
+ return runWithWorkflowRuntimeEvent(getWorkflowRuntimeEvent(), () => runWorkflow(name, payload, {
345
+ ...options,
346
+ deferred: true
347
+ }));
348
+ }
349
+ //#endregion
350
+ //#region src/runtime/payload.ts
351
+ async function readRequestPayload(request) {
352
+ if ((request.headers.get("content-type") || "").includes("application/json")) return await request.json();
353
+ return await request.text();
354
+ }
355
+ async function validatePayload(payload, schema) {
356
+ if (typeof schema === "function") return await schema(payload);
357
+ if ("safeParse" in schema && typeof schema.safeParse === "function") {
358
+ const result = schema.safeParse(payload);
359
+ if (!result.success) throw result.error || /* @__PURE__ */ new TypeError("Invalid workflow payload.");
360
+ return result.data;
361
+ }
362
+ if ("parse" in schema && typeof schema.parse === "function") return schema.parse(payload);
363
+ throw new TypeError("Invalid workflow payload schema.");
364
+ }
365
+ async function readValidatedPayload(request, schema) {
366
+ return await validatePayload(await readRequestPayload(request), schema);
367
+ }
368
+ //#endregion
369
+ export { WorkflowError, createOpenWorkflowWorker, createWorkflow, createWorkflowCloudflareWorker, deferWorkflow, defineWorkflow, getCloudflareWorkflowBindingName, getCloudflareWorkflowClassName, getCloudflareWorkflowName, getVercelWorkflowName, getWorkflowRun, normalizeWorkflowOptions, readRequestPayload, readValidatedPayload, runWorkflow, startOpenWorkflowWorker, validatePayload };