@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.
- package/README.md +60 -1
- package/dist/_app-BVWpnNHo.d.ts +11 -0
- package/dist/app-BE3EYOWn.js +10 -0
- package/dist/cloudflare-CeHVSHoN.js +42 -0
- package/dist/cloudflare-env-BVUMOgFK.d.ts +21 -0
- package/dist/cloudflare-env-g0Rf3ClH.js +49 -0
- package/dist/cloudflare-shared-BIeY2kak.d.ts +1 -0
- package/dist/cloudflare-vite-DcM5YVTP.js +40 -0
- package/dist/config-DkgsQuXz.js +92 -0
- package/dist/index.d.ts +65 -0
- package/dist/index.js +369 -0
- package/dist/module-UYEnVfxy.js +1546 -0
- package/dist/nitro.d.ts +19 -0
- package/dist/nitro.js +2 -0
- package/dist/openworkflow-amN7IkGO.d.ts +24 -0
- package/dist/runtime/cloudflare-runner.d.ts +27 -0
- package/dist/runtime/cloudflare-runner.js +23 -0
- package/dist/runtime/cloudflare-shared.d.ts +2 -0
- package/dist/runtime/cloudflare-shared.js +2 -0
- package/dist/runtime/cloudflare-vite.d.ts +17 -0
- package/dist/runtime/cloudflare-vite.js +2 -0
- package/dist/runtime/execute.d.ts +11 -0
- package/dist/runtime/execute.js +25 -0
- package/dist/runtime/nitro-plugin.d.ts +6 -0
- package/dist/runtime/nitro-plugin.js +14 -0
- package/dist/runtime/openworkflow-worker.d.ts +18 -0
- package/dist/runtime/openworkflow-worker.js +55 -0
- package/dist/runtime/openworkflow.d.ts +2 -0
- package/dist/runtime/openworkflow.js +143 -0
- package/dist/runtime/state.d.ts +35 -0
- package/dist/runtime/state.js +179 -0
- package/dist/runtime/vercel-vite.d.ts +14 -0
- package/dist/runtime/vercel-vite.js +48 -0
- package/dist/types-ThDitg7Z.d.ts +121 -0
- package/dist/vite.d.ts +16 -0
- package/dist/vite.js +503 -0
- 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 };
|