@workflow/core 4.0.1-beta.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.
- package/LICENSE.md +21 -0
- package/README.md +3 -0
- package/dist/builtins.d.ts +4 -0
- package/dist/builtins.d.ts.map +1 -0
- package/dist/builtins.js +13 -0
- package/dist/builtins.js.map +1 -0
- package/dist/create-hook.d.ts +123 -0
- package/dist/create-hook.d.ts.map +1 -0
- package/dist/create-hook.js +32 -0
- package/dist/create-hook.js.map +1 -0
- package/dist/define-hook.d.ts +53 -0
- package/dist/define-hook.d.ts.map +1 -0
- package/dist/define-hook.js +59 -0
- package/dist/define-hook.js.map +1 -0
- package/dist/events-consumer.d.ts +35 -0
- package/dist/events-consumer.d.ts.map +1 -0
- package/dist/events-consumer.js +72 -0
- package/dist/events-consumer.js.map +1 -0
- package/dist/global.d.ts +29 -0
- package/dist/global.d.ts.map +1 -0
- package/dist/global.js +50 -0
- package/dist/global.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +31 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +32 -0
- package/dist/logger.js.map +1 -0
- package/dist/observability.d.ts +24 -0
- package/dist/observability.d.ts.map +1 -0
- package/dist/observability.js +126 -0
- package/dist/observability.js.map +1 -0
- package/dist/parse-name.d.ts +25 -0
- package/dist/parse-name.d.ts.map +1 -0
- package/dist/parse-name.js +40 -0
- package/dist/parse-name.js.map +1 -0
- package/dist/private.d.ts +26 -0
- package/dist/private.d.ts.map +1 -0
- package/dist/private.js +17 -0
- package/dist/private.js.map +1 -0
- package/dist/runtime/resume-hook.d.ts +71 -0
- package/dist/runtime/resume-hook.d.ts.map +1 -0
- package/dist/runtime/resume-hook.js +180 -0
- package/dist/runtime/resume-hook.js.map +1 -0
- package/dist/runtime/start.d.ts +28 -0
- package/dist/runtime/start.d.ts.map +1 -0
- package/dist/runtime/start.js +57 -0
- package/dist/runtime/start.js.map +1 -0
- package/dist/runtime/world.d.ts +24 -0
- package/dist/runtime/world.d.ts.map +1 -0
- package/dist/runtime/world.js +84 -0
- package/dist/runtime/world.js.map +1 -0
- package/dist/runtime.d.ts +121 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +554 -0
- package/dist/runtime.js.map +1 -0
- package/dist/schemas.d.ts +29 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +15 -0
- package/dist/schemas.js.map +1 -0
- package/dist/serialization.d.ts +188 -0
- package/dist/serialization.d.ts.map +1 -0
- package/dist/serialization.js +725 -0
- package/dist/serialization.js.map +1 -0
- package/dist/step/context-storage.d.ts +8 -0
- package/dist/step/context-storage.d.ts.map +1 -0
- package/dist/step/context-storage.js +3 -0
- package/dist/step/context-storage.js.map +1 -0
- package/dist/step/get-step-metadata.d.ts +38 -0
- package/dist/step/get-step-metadata.d.ts.map +1 -0
- package/dist/step/get-step-metadata.js +14 -0
- package/dist/step/get-step-metadata.js.map +1 -0
- package/dist/step/get-workflow-metadata.d.ts +7 -0
- package/dist/step/get-workflow-metadata.d.ts.map +1 -0
- package/dist/step/get-workflow-metadata.js +12 -0
- package/dist/step/get-workflow-metadata.js.map +1 -0
- package/dist/step.d.ts +4 -0
- package/dist/step.d.ts.map +1 -0
- package/dist/step.js +92 -0
- package/dist/step.js.map +1 -0
- package/dist/symbols.d.ts +9 -0
- package/dist/symbols.d.ts.map +1 -0
- package/dist/symbols.js +9 -0
- package/dist/symbols.js.map +1 -0
- package/dist/telemetry/semantic-conventions.d.ts +175 -0
- package/dist/telemetry/semantic-conventions.d.ts.map +1 -0
- package/dist/telemetry/semantic-conventions.js +121 -0
- package/dist/telemetry/semantic-conventions.js.map +1 -0
- package/dist/telemetry.d.ts +24 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +121 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +39 -0
- package/dist/types.js.map +1 -0
- package/dist/util.d.ts +43 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +76 -0
- package/dist/util.js.map +1 -0
- package/dist/vm/index.d.ts +17 -0
- package/dist/vm/index.d.ts.map +1 -0
- package/dist/vm/index.js +93 -0
- package/dist/vm/index.js.map +1 -0
- package/dist/vm/uuid.d.ts +10 -0
- package/dist/vm/uuid.d.ts.map +1 -0
- package/dist/vm/uuid.js +30 -0
- package/dist/vm/uuid.js.map +1 -0
- package/dist/workflow/create-hook.d.ts +7 -0
- package/dist/workflow/create-hook.d.ts.map +1 -0
- package/dist/workflow/create-hook.js +22 -0
- package/dist/workflow/create-hook.js.map +1 -0
- package/dist/workflow/define-hook.d.ts +10 -0
- package/dist/workflow/define-hook.d.ts.map +1 -0
- package/dist/workflow/define-hook.js +15 -0
- package/dist/workflow/define-hook.js.map +1 -0
- package/dist/workflow/get-workflow-metadata.d.ts +17 -0
- package/dist/workflow/get-workflow-metadata.d.ts.map +1 -0
- package/dist/workflow/get-workflow-metadata.js +11 -0
- package/dist/workflow/get-workflow-metadata.js.map +1 -0
- package/dist/workflow/hook.d.ts +4 -0
- package/dist/workflow/hook.d.ts.map +1 -0
- package/dist/workflow/hook.js +101 -0
- package/dist/workflow/hook.js.map +1 -0
- package/dist/workflow/index.d.ts +10 -0
- package/dist/workflow/index.d.ts.map +1 -0
- package/dist/workflow/index.js +14 -0
- package/dist/workflow/index.js.map +1 -0
- package/dist/workflow/writable-stream.d.ts +3 -0
- package/dist/workflow/writable-stream.d.ts.map +1 -0
- package/dist/workflow/writable-stream.js +12 -0
- package/dist/workflow/writable-stream.js.map +1 -0
- package/dist/workflow.d.ts +3 -0
- package/dist/workflow.d.ts.map +1 -0
- package/dist/workflow.js +454 -0
- package/dist/workflow.js.map +1 -0
- package/dist/writable-stream.d.ts +22 -0
- package/dist/writable-stream.d.ts.map +1 -0
- package/dist/writable-stream.js +16 -0
- package/dist/writable-stream.js.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/workflow/hook.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAI3D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAIjE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,2BAA2B,IAChC,CAAC,GAAG,GAAG,EAAE,UAAS,WAAgB,KAAG,IAAI,CAAC,CAAC,CAAC,CAiI5E"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { EventConsumerResult } from '../events-consumer.js';
|
|
2
|
+
import { WorkflowSuspension } from '../global.js';
|
|
3
|
+
import { webhookLogger } from '../logger.js';
|
|
4
|
+
import { hydrateStepReturnValue } from '../serialization.js';
|
|
5
|
+
import { withResolvers } from '../util.js';
|
|
6
|
+
export function createCreateHook(ctx) {
|
|
7
|
+
return function createHookImpl(options = {}) {
|
|
8
|
+
// Generate hook ID and token
|
|
9
|
+
const correlationId = `hook_${ctx.generateUlid()}`;
|
|
10
|
+
const token = options.token ?? ctx.generateNanoid();
|
|
11
|
+
// Add hook creation to invocations queue
|
|
12
|
+
ctx.invocationsQueue.push({
|
|
13
|
+
type: 'hook',
|
|
14
|
+
correlationId,
|
|
15
|
+
token,
|
|
16
|
+
metadata: options.metadata,
|
|
17
|
+
});
|
|
18
|
+
// Queue of hook events that have been received but not yet processed
|
|
19
|
+
const payloadsQueue = [];
|
|
20
|
+
// Queue of promises that resolve to the next hook payload
|
|
21
|
+
const promises = [];
|
|
22
|
+
let eventLogEmpty = false;
|
|
23
|
+
webhookLogger.debug('Hook consumer setup', { correlationId, token });
|
|
24
|
+
ctx.eventsConsumer.subscribe((event) => {
|
|
25
|
+
// If there are no events and there are promises waiting,
|
|
26
|
+
// it means the hook has been awaited, but an incoming payload has not yet been received.
|
|
27
|
+
// In this case, the workflow should be suspended until the hook is resumed.
|
|
28
|
+
if (!event) {
|
|
29
|
+
eventLogEmpty = true;
|
|
30
|
+
if (promises.length > 0) {
|
|
31
|
+
setTimeout(() => {
|
|
32
|
+
ctx.onWorkflowError(new WorkflowSuspension(ctx.invocationsQueue, ctx.globalThis));
|
|
33
|
+
}, 0);
|
|
34
|
+
return EventConsumerResult.Finished;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Check for hook_created event to remove this hook from the queue if it was already created
|
|
38
|
+
if (event?.eventType === 'hook_created' &&
|
|
39
|
+
event.correlationId === correlationId) {
|
|
40
|
+
// Remove this hook from the invocations queue if it exists
|
|
41
|
+
const index = ctx.invocationsQueue.findIndex((item) => item.type === 'hook' && item.correlationId === correlationId);
|
|
42
|
+
if (index !== -1) {
|
|
43
|
+
ctx.invocationsQueue.splice(index, 1);
|
|
44
|
+
}
|
|
45
|
+
return EventConsumerResult.Consumed;
|
|
46
|
+
}
|
|
47
|
+
if (event?.eventType === 'hook_received' &&
|
|
48
|
+
event.correlationId === correlationId) {
|
|
49
|
+
if (promises.length > 0) {
|
|
50
|
+
const next = promises.shift();
|
|
51
|
+
if (next) {
|
|
52
|
+
// Reconstruct the payload from the event data
|
|
53
|
+
const payload = hydrateStepReturnValue(event.eventData.payload, ctx.globalThis);
|
|
54
|
+
next.resolve(payload);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
payloadsQueue.push(event);
|
|
59
|
+
}
|
|
60
|
+
return EventConsumerResult.Consumed;
|
|
61
|
+
}
|
|
62
|
+
return EventConsumerResult.NotConsumed;
|
|
63
|
+
});
|
|
64
|
+
// Helper function to create a new promise that waits for the next hook payload
|
|
65
|
+
function createHookPromise() {
|
|
66
|
+
const resolvers = withResolvers();
|
|
67
|
+
if (payloadsQueue.length > 0) {
|
|
68
|
+
const nextPayload = payloadsQueue.shift();
|
|
69
|
+
if (nextPayload) {
|
|
70
|
+
const payload = hydrateStepReturnValue(nextPayload.eventData.payload, ctx.globalThis);
|
|
71
|
+
resolvers.resolve(payload);
|
|
72
|
+
return resolvers.promise;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (eventLogEmpty) {
|
|
76
|
+
// If the event log is already empty then we know the hook will not be resolved.
|
|
77
|
+
// Treat this case as a "step not run" scenario and suspend the workflow.
|
|
78
|
+
setTimeout(() => {
|
|
79
|
+
ctx.onWorkflowError(new WorkflowSuspension(ctx.invocationsQueue, ctx.globalThis));
|
|
80
|
+
}, 0);
|
|
81
|
+
}
|
|
82
|
+
promises.push(resolvers);
|
|
83
|
+
return resolvers.promise;
|
|
84
|
+
}
|
|
85
|
+
const hook = {
|
|
86
|
+
token,
|
|
87
|
+
// biome-ignore lint/suspicious/noThenProperty: Intentionally thenable
|
|
88
|
+
then(onfulfilled, onrejected) {
|
|
89
|
+
return createHookPromise().then(onfulfilled, onrejected);
|
|
90
|
+
},
|
|
91
|
+
// Support `for await (const payload of hook) { … }` syntax
|
|
92
|
+
async *[Symbol.asyncIterator]() {
|
|
93
|
+
while (true) {
|
|
94
|
+
yield await this;
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
return hook;
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook.js","sourceRoot":"","sources":["../../src/workflow/hook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { StepMetadata } from '../step/get-step-metadata.js';
|
|
2
|
+
export { FatalError, RetryableError, type RetryableErrorOptions, } from '@workflow/errors';
|
|
3
|
+
export type { Hook, HookOptions } from '../create-hook.js';
|
|
4
|
+
export { createHook, createWebhook } from './create-hook.js';
|
|
5
|
+
export { defineHook } from './define-hook.js';
|
|
6
|
+
export { getWorkflowMetadata } from './get-workflow-metadata.js';
|
|
7
|
+
export { getWritable } from './writable-stream.js';
|
|
8
|
+
export declare function getStepMetadata(): StepMetadata;
|
|
9
|
+
export declare function resumeHook(): void;
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/workflow/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEjE,OAAO,EACL,UAAU,EACV,cAAc,EACd,KAAK,qBAAqB,GAC3B,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAInD,wBAAgB,eAAe,IAAI,YAAY,CAI9C;AACD,wBAAgB,UAAU,SAIzB"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { FatalError, RetryableError, } from '@workflow/errors';
|
|
2
|
+
export { createHook, createWebhook } from './create-hook.js';
|
|
3
|
+
export { defineHook } from './define-hook.js';
|
|
4
|
+
export { getWorkflowMetadata } from './get-workflow-metadata.js';
|
|
5
|
+
export { getWritable } from './writable-stream.js';
|
|
6
|
+
// workflows can't use these functions, but we still need to provide
|
|
7
|
+
// the export so bundling doesn't fail when step and workflow are in same file
|
|
8
|
+
export function getStepMetadata() {
|
|
9
|
+
throw new Error('`getStepMetadata()` can only be called inside a step function');
|
|
10
|
+
}
|
|
11
|
+
export function resumeHook() {
|
|
12
|
+
throw new Error('`resumeHook()` can only be called from outside a workflow function');
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/workflow/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,UAAU,EACV,cAAc,GAEf,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,oEAAoE;AACpE,8EAA8E;AAC9E,MAAM,UAAU,eAAe;IAC7B,MAAM,IAAI,KAAK,CACb,+DAA+D,CAChE,CAAC;AACJ,CAAC;AACD,MAAM,UAAU,UAAU;IACxB,MAAM,IAAI,KAAK,CACb,oEAAoE,CACrE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writable-stream.d.ts","sourceRoot":"","sources":["../../src/workflow/writable-stream.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AAE3E,wBAAgB,WAAW,CAAC,CAAC,GAAG,GAAG,EACjC,OAAO,GAAE,6BAAkC,GAC1C,cAAc,CAAC,CAAC,CAAC,CASnB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { STREAM_NAME_SYMBOL, WORKFLOW_GET_STREAM_ID } from '../symbols.js';
|
|
2
|
+
export function getWritable(options = {}) {
|
|
3
|
+
const { namespace } = options;
|
|
4
|
+
const name = globalThis[WORKFLOW_GET_STREAM_ID](namespace);
|
|
5
|
+
return Object.create(globalThis.WritableStream.prototype, {
|
|
6
|
+
[STREAM_NAME_SYMBOL]: {
|
|
7
|
+
value: name,
|
|
8
|
+
writable: false,
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=writable-stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writable-stream.js","sourceRoot":"","sources":["../../src/workflow/writable-stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAG3E,MAAM,UAAU,WAAW,CACzB,UAAyC,EAAE;IAE3C,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAC9B,MAAM,IAAI,GAAI,UAAkB,CAAC,sBAAsB,CAAC,CAAC,SAAS,CAAC,CAAC;IACpE,OAAO,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,SAAS,EAAE;QACxD,CAAC,kBAAkB,CAAC,EAAE;YACpB,KAAK,EAAE,IAAI;YACX,QAAQ,EAAE,KAAK;SAChB;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../src/workflow.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAyB1D,wBAAsB,WAAW,CAC/B,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,KAAK,EAAE,GACd,OAAO,CAAC,OAAO,CAAC,CAuhBlB"}
|
package/dist/workflow.js
ADDED
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
import { runInContext } from 'node:vm';
|
|
2
|
+
import { ERROR_SLUGS } from '@workflow/errors';
|
|
3
|
+
import * as nanoid from 'nanoid';
|
|
4
|
+
import { monotonicFactory } from 'ulid';
|
|
5
|
+
import { EventConsumerResult, EventsConsumer } from './events-consumer.js';
|
|
6
|
+
import { ENOTSUP } from './global.js';
|
|
7
|
+
import { dehydrateWorkflowReturnValue, hydrateWorkflowArguments, } from './serialization.js';
|
|
8
|
+
import { createUseStep } from './step.js';
|
|
9
|
+
import { BODY_INIT_SYMBOL, WORKFLOW_CREATE_HOOK, WORKFLOW_GET_STREAM_ID, WORKFLOW_USE_STEP, } from './symbols.js';
|
|
10
|
+
import * as Attribute from './telemetry/semantic-conventions.js';
|
|
11
|
+
import { trace } from './telemetry.js';
|
|
12
|
+
import { getWorkflowRunStreamId, withResolvers } from './util.js';
|
|
13
|
+
import { createContext } from './vm/index.js';
|
|
14
|
+
import { WORKFLOW_CONTEXT_SYMBOL } from './workflow/get-workflow-metadata.js';
|
|
15
|
+
import { createCreateHook } from './workflow/hook.js';
|
|
16
|
+
export async function runWorkflow(workflowCode, workflowRun, events) {
|
|
17
|
+
return trace(`WORKFLOW.run ${workflowRun.workflowName}`, async (span) => {
|
|
18
|
+
span?.setAttributes({
|
|
19
|
+
...Attribute.WorkflowName(workflowRun.workflowName),
|
|
20
|
+
...Attribute.WorkflowRunId(workflowRun.runId),
|
|
21
|
+
...Attribute.WorkflowRunStatus(workflowRun.status),
|
|
22
|
+
...Attribute.WorkflowEventsCount(events.length),
|
|
23
|
+
});
|
|
24
|
+
const startedAt = workflowRun.startedAt;
|
|
25
|
+
if (!startedAt) {
|
|
26
|
+
throw new Error(`Workflow run "${workflowRun.runId}" has no "startedAt" timestamp (should not happen)`);
|
|
27
|
+
}
|
|
28
|
+
const { context, globalThis: vmGlobalThis, updateTimestamp, } = createContext({
|
|
29
|
+
seed: workflowRun.runId,
|
|
30
|
+
fixedTimestamp: +startedAt,
|
|
31
|
+
});
|
|
32
|
+
const workflowDiscontinuation = withResolvers();
|
|
33
|
+
const ulid = monotonicFactory(() => vmGlobalThis.Math.random());
|
|
34
|
+
const generateNanoid = nanoid.customRandom(nanoid.urlAlphabet, 21, (size) => new Uint8Array(size).map(() => 256 * vmGlobalThis.Math.random()));
|
|
35
|
+
const workflowContext = {
|
|
36
|
+
globalThis: vmGlobalThis,
|
|
37
|
+
onWorkflowError: workflowDiscontinuation.reject,
|
|
38
|
+
eventsConsumer: new EventsConsumer(events),
|
|
39
|
+
generateUlid: () => ulid(+startedAt),
|
|
40
|
+
generateNanoid,
|
|
41
|
+
invocationsQueue: [],
|
|
42
|
+
};
|
|
43
|
+
// Subscribe to the events log to update the timestamp in the vm context
|
|
44
|
+
workflowContext.eventsConsumer.subscribe((event) => {
|
|
45
|
+
const createdAt = event?.createdAt;
|
|
46
|
+
if (createdAt) {
|
|
47
|
+
updateTimestamp(+createdAt);
|
|
48
|
+
}
|
|
49
|
+
// Never consume events - this is only a passive subscriber
|
|
50
|
+
return EventConsumerResult.NotConsumed;
|
|
51
|
+
});
|
|
52
|
+
const useStep = createUseStep(workflowContext);
|
|
53
|
+
const createHook = createCreateHook(workflowContext);
|
|
54
|
+
// @ts-expect-error - `@types/node` says symbol is not valid, but it does work
|
|
55
|
+
vmGlobalThis[WORKFLOW_USE_STEP] = useStep;
|
|
56
|
+
// @ts-expect-error - `@types/node` says symbol is not valid, but it does work
|
|
57
|
+
vmGlobalThis[WORKFLOW_CREATE_HOOK] = createHook;
|
|
58
|
+
// @ts-expect-error - `@types/node` says symbol is not valid, but it does work
|
|
59
|
+
vmGlobalThis[WORKFLOW_GET_STREAM_ID] = (namespace) => getWorkflowRunStreamId(workflowRun.runId, namespace);
|
|
60
|
+
// TODO: there should be a getUrl method on the world interface itself. This
|
|
61
|
+
// solution only works for vercel + embedded worlds.
|
|
62
|
+
const url = process.env.VERCEL_URL
|
|
63
|
+
? `https://${process.env.VERCEL_URL}`
|
|
64
|
+
: `http://localhost:${process.env.PORT || 3000}`;
|
|
65
|
+
// For the workflow VM, we store the context in a symbol on the `globalThis` object
|
|
66
|
+
const ctx = {
|
|
67
|
+
workflowRunId: workflowRun.runId,
|
|
68
|
+
workflowStartedAt: new vmGlobalThis.Date(+startedAt),
|
|
69
|
+
url,
|
|
70
|
+
};
|
|
71
|
+
// @ts-expect-error - `@types/node` says symbol is not valid, but it does work
|
|
72
|
+
vmGlobalThis[WORKFLOW_CONTEXT_SYMBOL] = ctx;
|
|
73
|
+
// NOTE: Will have a config override to use the custom fetch step.
|
|
74
|
+
// For now `fetch` must be explicitly imported from `workflow`.
|
|
75
|
+
vmGlobalThis.fetch = () => {
|
|
76
|
+
throw new vmGlobalThis.Error(`Global "fetch" is unavailable in workflow functions. Use the "fetch" step function from "workflow" to make HTTP requests.\n\nLearn more: https://useworkflow.dev/err/${ERROR_SLUGS.FETCH_IN_WORKFLOW_FUNCTION}`);
|
|
77
|
+
};
|
|
78
|
+
// `Request` and `Response` are special built-in classes that invoke steps
|
|
79
|
+
// for the `json()`, `text()` and `arrayBuffer()` instance methods
|
|
80
|
+
class Request {
|
|
81
|
+
cache;
|
|
82
|
+
credentials;
|
|
83
|
+
destination;
|
|
84
|
+
headers;
|
|
85
|
+
integrity;
|
|
86
|
+
method;
|
|
87
|
+
mode;
|
|
88
|
+
redirect;
|
|
89
|
+
referrer;
|
|
90
|
+
referrerPolicy;
|
|
91
|
+
url;
|
|
92
|
+
keepalive;
|
|
93
|
+
signal;
|
|
94
|
+
duplex;
|
|
95
|
+
body;
|
|
96
|
+
constructor(input, init) {
|
|
97
|
+
// Handle URL input
|
|
98
|
+
if (typeof input === 'string' || input instanceof vmGlobalThis.URL) {
|
|
99
|
+
const urlString = String(input);
|
|
100
|
+
// Validate URL format
|
|
101
|
+
try {
|
|
102
|
+
new vmGlobalThis.URL(urlString);
|
|
103
|
+
this.url = urlString;
|
|
104
|
+
}
|
|
105
|
+
catch (cause) {
|
|
106
|
+
throw new TypeError(`Failed to parse URL from ${urlString}`, {
|
|
107
|
+
cause,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Input is a Request object - clone its properties
|
|
113
|
+
this.url = input.url;
|
|
114
|
+
if (!init) {
|
|
115
|
+
this.method = input.method;
|
|
116
|
+
this.headers = new vmGlobalThis.Headers(input.headers);
|
|
117
|
+
this.body = input.body;
|
|
118
|
+
this.mode = input.mode;
|
|
119
|
+
this.credentials = input.credentials;
|
|
120
|
+
this.cache = input.cache;
|
|
121
|
+
this.redirect = input.redirect;
|
|
122
|
+
this.referrer = input.referrer;
|
|
123
|
+
this.referrerPolicy = input.referrerPolicy;
|
|
124
|
+
this.integrity = input.integrity;
|
|
125
|
+
this.keepalive = input.keepalive;
|
|
126
|
+
this.signal = input.signal;
|
|
127
|
+
this.duplex = input.duplex;
|
|
128
|
+
this.destination = input.destination;
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
// If init is provided, merge: use source properties, then override with init
|
|
132
|
+
// Copy all properties from the source Request first
|
|
133
|
+
this.method = input.method;
|
|
134
|
+
this.headers = new vmGlobalThis.Headers(input.headers);
|
|
135
|
+
this.body = input.body;
|
|
136
|
+
this.mode = input.mode;
|
|
137
|
+
this.credentials = input.credentials;
|
|
138
|
+
this.cache = input.cache;
|
|
139
|
+
this.redirect = input.redirect;
|
|
140
|
+
this.referrer = input.referrer;
|
|
141
|
+
this.referrerPolicy = input.referrerPolicy;
|
|
142
|
+
this.integrity = input.integrity;
|
|
143
|
+
this.keepalive = input.keepalive;
|
|
144
|
+
this.signal = input.signal;
|
|
145
|
+
this.duplex = input.duplex;
|
|
146
|
+
this.destination = input.destination;
|
|
147
|
+
}
|
|
148
|
+
// Override with init options if provided
|
|
149
|
+
// Set method
|
|
150
|
+
if (init?.method) {
|
|
151
|
+
this.method = init.method.toUpperCase();
|
|
152
|
+
}
|
|
153
|
+
else if (typeof this.method !== 'string') {
|
|
154
|
+
// Fallback to default for string input case
|
|
155
|
+
this.method = 'GET';
|
|
156
|
+
}
|
|
157
|
+
// Set headers
|
|
158
|
+
if (init?.headers) {
|
|
159
|
+
this.headers = new vmGlobalThis.Headers(init.headers);
|
|
160
|
+
}
|
|
161
|
+
else if (typeof input === 'string' ||
|
|
162
|
+
input instanceof vmGlobalThis.URL) {
|
|
163
|
+
// For string/URL input, create empty headers
|
|
164
|
+
this.headers = new vmGlobalThis.Headers();
|
|
165
|
+
}
|
|
166
|
+
// Set other properties with init values or defaults
|
|
167
|
+
if (init?.mode !== undefined) {
|
|
168
|
+
this.mode = init.mode;
|
|
169
|
+
}
|
|
170
|
+
else if (typeof this.mode !== 'string') {
|
|
171
|
+
this.mode = 'cors';
|
|
172
|
+
}
|
|
173
|
+
if (init?.credentials !== undefined) {
|
|
174
|
+
this.credentials = init.credentials;
|
|
175
|
+
}
|
|
176
|
+
else if (typeof this.credentials !== 'string') {
|
|
177
|
+
this.credentials = 'same-origin';
|
|
178
|
+
}
|
|
179
|
+
if (init?.cache !== undefined) {
|
|
180
|
+
this.cache = init.cache;
|
|
181
|
+
}
|
|
182
|
+
else if (typeof this.cache !== 'string') {
|
|
183
|
+
this.cache = 'default';
|
|
184
|
+
}
|
|
185
|
+
if (init?.redirect !== undefined) {
|
|
186
|
+
this.redirect = init.redirect;
|
|
187
|
+
}
|
|
188
|
+
else if (typeof this.redirect !== 'string') {
|
|
189
|
+
this.redirect = 'follow';
|
|
190
|
+
}
|
|
191
|
+
if (init?.referrer !== undefined) {
|
|
192
|
+
this.referrer = init.referrer;
|
|
193
|
+
}
|
|
194
|
+
else if (typeof this.referrer !== 'string') {
|
|
195
|
+
this.referrer = 'about:client';
|
|
196
|
+
}
|
|
197
|
+
if (init?.referrerPolicy !== undefined) {
|
|
198
|
+
this.referrerPolicy = init.referrerPolicy;
|
|
199
|
+
}
|
|
200
|
+
else if (typeof this.referrerPolicy !== 'string') {
|
|
201
|
+
this.referrerPolicy = '';
|
|
202
|
+
}
|
|
203
|
+
if (init?.integrity !== undefined) {
|
|
204
|
+
this.integrity = init.integrity;
|
|
205
|
+
}
|
|
206
|
+
else if (typeof this.integrity !== 'string') {
|
|
207
|
+
this.integrity = '';
|
|
208
|
+
}
|
|
209
|
+
if (init?.keepalive !== undefined) {
|
|
210
|
+
this.keepalive = init.keepalive;
|
|
211
|
+
}
|
|
212
|
+
else if (typeof this.keepalive !== 'boolean') {
|
|
213
|
+
this.keepalive = false;
|
|
214
|
+
}
|
|
215
|
+
if (init?.signal !== undefined) {
|
|
216
|
+
// @ts-expect-error - AbortSignal stub
|
|
217
|
+
this.signal = init.signal;
|
|
218
|
+
}
|
|
219
|
+
else if (!this.signal) {
|
|
220
|
+
// @ts-expect-error - AbortSignal stub
|
|
221
|
+
this.signal = { aborted: false };
|
|
222
|
+
}
|
|
223
|
+
if (!this.duplex) {
|
|
224
|
+
this.duplex = 'half';
|
|
225
|
+
}
|
|
226
|
+
if (!this.destination) {
|
|
227
|
+
this.destination = 'document';
|
|
228
|
+
}
|
|
229
|
+
const body = init?.body;
|
|
230
|
+
// Validate that GET/HEAD methods don't have a body
|
|
231
|
+
if (body !== null &&
|
|
232
|
+
body !== undefined &&
|
|
233
|
+
(this.method === 'GET' || this.method === 'HEAD')) {
|
|
234
|
+
throw new TypeError(`Request with GET/HEAD method cannot have body.`);
|
|
235
|
+
}
|
|
236
|
+
// Store the original BodyInit for serialization
|
|
237
|
+
if (body !== null && body !== undefined) {
|
|
238
|
+
// Create a "fake" ReadableStream that stores the original body
|
|
239
|
+
// This avoids doing async work during workflow replay
|
|
240
|
+
this.body = Object.create(vmGlobalThis.ReadableStream.prototype, {
|
|
241
|
+
[BODY_INIT_SYMBOL]: {
|
|
242
|
+
value: body,
|
|
243
|
+
writable: false,
|
|
244
|
+
},
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
this.body = null;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
clone() {
|
|
252
|
+
ENOTSUP();
|
|
253
|
+
}
|
|
254
|
+
get bodyUsed() {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
// TODO: implement these
|
|
258
|
+
blob;
|
|
259
|
+
formData;
|
|
260
|
+
async arrayBuffer() {
|
|
261
|
+
return resArrayBuffer(this);
|
|
262
|
+
}
|
|
263
|
+
async bytes() {
|
|
264
|
+
return new Uint8Array(await resArrayBuffer(this));
|
|
265
|
+
}
|
|
266
|
+
async json() {
|
|
267
|
+
return resJson(this);
|
|
268
|
+
}
|
|
269
|
+
async text() {
|
|
270
|
+
return resText(this);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
vmGlobalThis.Request = Request;
|
|
274
|
+
const resJson = useStep('__builtin_response_json');
|
|
275
|
+
const resText = useStep('__builtin_response_text');
|
|
276
|
+
const resArrayBuffer = useStep('__builtin_response_array_buffer');
|
|
277
|
+
class Response {
|
|
278
|
+
type;
|
|
279
|
+
url;
|
|
280
|
+
status;
|
|
281
|
+
statusText;
|
|
282
|
+
body;
|
|
283
|
+
headers;
|
|
284
|
+
redirected;
|
|
285
|
+
constructor(body, init) {
|
|
286
|
+
this.status = init?.status ?? 200;
|
|
287
|
+
this.statusText = init?.statusText ?? '';
|
|
288
|
+
this.headers = new vmGlobalThis.Headers(init?.headers);
|
|
289
|
+
this.type = 'default';
|
|
290
|
+
this.url = '';
|
|
291
|
+
this.redirected = false;
|
|
292
|
+
// Validate that null-body status codes don't have a body
|
|
293
|
+
// Per HTTP spec: 204 (No Content), 205 (Reset Content), and 304 (Not Modified)
|
|
294
|
+
if (body !== null &&
|
|
295
|
+
body !== undefined &&
|
|
296
|
+
(this.status === 204 || this.status === 205 || this.status === 304)) {
|
|
297
|
+
throw new TypeError(`Response constructor: Invalid response status code ${this.status}`);
|
|
298
|
+
}
|
|
299
|
+
// Store the original BodyInit for serialization
|
|
300
|
+
if (body !== null && body !== undefined) {
|
|
301
|
+
// Create a "fake" ReadableStream that stores the original body
|
|
302
|
+
// This avoids doing async work during workflow replay
|
|
303
|
+
this.body = Object.create(vmGlobalThis.ReadableStream.prototype, {
|
|
304
|
+
[BODY_INIT_SYMBOL]: {
|
|
305
|
+
value: body,
|
|
306
|
+
writable: false,
|
|
307
|
+
},
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
this.body = null;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
// TODO: implement these
|
|
315
|
+
clone;
|
|
316
|
+
blob;
|
|
317
|
+
formData;
|
|
318
|
+
get ok() {
|
|
319
|
+
return this.status >= 200 && this.status < 300;
|
|
320
|
+
}
|
|
321
|
+
get bodyUsed() {
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
async arrayBuffer() {
|
|
325
|
+
return resArrayBuffer(this);
|
|
326
|
+
}
|
|
327
|
+
async bytes() {
|
|
328
|
+
return new Uint8Array(await resArrayBuffer(this));
|
|
329
|
+
}
|
|
330
|
+
async json() {
|
|
331
|
+
return resJson(this);
|
|
332
|
+
}
|
|
333
|
+
static json(data, init) {
|
|
334
|
+
const body = JSON.stringify(data);
|
|
335
|
+
const headers = new vmGlobalThis.Headers(init?.headers);
|
|
336
|
+
if (!headers.has('content-type')) {
|
|
337
|
+
headers.set('content-type', 'application/json');
|
|
338
|
+
}
|
|
339
|
+
return new Response(body, { ...init, headers });
|
|
340
|
+
}
|
|
341
|
+
async text() {
|
|
342
|
+
return resText(this);
|
|
343
|
+
}
|
|
344
|
+
static error() {
|
|
345
|
+
ENOTSUP();
|
|
346
|
+
}
|
|
347
|
+
static redirect(url, status = 302) {
|
|
348
|
+
// Validate status code - only specific redirect codes are allowed
|
|
349
|
+
if (![301, 302, 303, 307, 308].includes(status)) {
|
|
350
|
+
throw new RangeError(`Invalid redirect status code: ${status}. Must be one of: 301, 302, 303, 307, 308`);
|
|
351
|
+
}
|
|
352
|
+
// Create response with Location header
|
|
353
|
+
const headers = new vmGlobalThis.Headers();
|
|
354
|
+
headers.set('Location', String(url));
|
|
355
|
+
const response = Object.create(Response.prototype);
|
|
356
|
+
response.status = status;
|
|
357
|
+
response.statusText = '';
|
|
358
|
+
response.headers = headers;
|
|
359
|
+
response.body = null;
|
|
360
|
+
response.type = 'default';
|
|
361
|
+
response.url = '';
|
|
362
|
+
response.redirected = false;
|
|
363
|
+
return response;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
vmGlobalThis.Response = Response;
|
|
367
|
+
class ReadableStream {
|
|
368
|
+
constructor() {
|
|
369
|
+
ENOTSUP();
|
|
370
|
+
}
|
|
371
|
+
get locked() {
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
cancel() {
|
|
375
|
+
ENOTSUP();
|
|
376
|
+
}
|
|
377
|
+
getReader() {
|
|
378
|
+
ENOTSUP();
|
|
379
|
+
}
|
|
380
|
+
pipeThrough() {
|
|
381
|
+
ENOTSUP();
|
|
382
|
+
}
|
|
383
|
+
pipeTo() {
|
|
384
|
+
ENOTSUP();
|
|
385
|
+
}
|
|
386
|
+
tee() {
|
|
387
|
+
ENOTSUP();
|
|
388
|
+
}
|
|
389
|
+
values() {
|
|
390
|
+
ENOTSUP();
|
|
391
|
+
}
|
|
392
|
+
static from() {
|
|
393
|
+
ENOTSUP();
|
|
394
|
+
}
|
|
395
|
+
[Symbol.asyncIterator]() {
|
|
396
|
+
ENOTSUP();
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
vmGlobalThis.ReadableStream = ReadableStream;
|
|
400
|
+
class WritableStream {
|
|
401
|
+
constructor() {
|
|
402
|
+
ENOTSUP();
|
|
403
|
+
}
|
|
404
|
+
get locked() {
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
abort() {
|
|
408
|
+
ENOTSUP();
|
|
409
|
+
}
|
|
410
|
+
close() {
|
|
411
|
+
ENOTSUP();
|
|
412
|
+
}
|
|
413
|
+
getWriter() {
|
|
414
|
+
ENOTSUP();
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
vmGlobalThis.WritableStream = WritableStream;
|
|
418
|
+
class TransformStream {
|
|
419
|
+
readable;
|
|
420
|
+
writable;
|
|
421
|
+
constructor() {
|
|
422
|
+
ENOTSUP();
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
vmGlobalThis.TransformStream = TransformStream;
|
|
426
|
+
// Eventually we'll probably want to provide our own `console` object,
|
|
427
|
+
// but for now we'll just expose the global one.
|
|
428
|
+
vmGlobalThis.console = globalThis.console;
|
|
429
|
+
// HACK: propagate symbol needed for AI gateway usage
|
|
430
|
+
const SYMBOL_FOR_REQ_CONTEXT = Symbol.for('@vercel/request-context');
|
|
431
|
+
// @ts-expect-error - `@types/node` says symbol is not valid, but it does work
|
|
432
|
+
vmGlobalThis[SYMBOL_FOR_REQ_CONTEXT] = globalThis[SYMBOL_FOR_REQ_CONTEXT];
|
|
433
|
+
// Get a reference to the user-defined workflow function
|
|
434
|
+
const workflowFn = runInContext(`${workflowCode}; globalThis.__private_workflows?.get(${JSON.stringify(workflowRun.workflowName)})`, context);
|
|
435
|
+
if (typeof workflowFn !== 'function') {
|
|
436
|
+
throw new ReferenceError(`Workflow ${JSON.stringify(workflowRun.workflowName)} must be a function, but got "${typeof workflowFn}" instead`);
|
|
437
|
+
}
|
|
438
|
+
const args = hydrateWorkflowArguments(workflowRun.input, vmGlobalThis);
|
|
439
|
+
span?.setAttributes({
|
|
440
|
+
...Attribute.WorkflowArgumentsCount(args.length),
|
|
441
|
+
});
|
|
442
|
+
// Invoke user workflow
|
|
443
|
+
const result = await Promise.race([
|
|
444
|
+
workflowFn(...args),
|
|
445
|
+
workflowDiscontinuation.promise,
|
|
446
|
+
]);
|
|
447
|
+
const dehydrated = dehydrateWorkflowReturnValue(result, vmGlobalThis);
|
|
448
|
+
span?.setAttributes({
|
|
449
|
+
...Attribute.WorkflowResultType(typeof result),
|
|
450
|
+
});
|
|
451
|
+
return dehydrated;
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
//# sourceMappingURL=workflow.js.map
|