@workflow/core 4.0.1-beta.9 → 4.1.0-beta.51

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 (181) hide show
  1. package/dist/builtins.js +1 -1
  2. package/dist/class-serialization.d.ts +26 -0
  3. package/dist/class-serialization.d.ts.map +1 -0
  4. package/dist/class-serialization.js +66 -0
  5. package/dist/create-hook.js +1 -1
  6. package/dist/define-hook.d.ts +40 -25
  7. package/dist/define-hook.d.ts.map +1 -1
  8. package/dist/define-hook.js +22 -27
  9. package/dist/events-consumer.d.ts.map +1 -1
  10. package/dist/events-consumer.js +5 -1
  11. package/dist/flushable-stream.d.ts +82 -0
  12. package/dist/flushable-stream.d.ts.map +1 -0
  13. package/dist/flushable-stream.js +214 -0
  14. package/dist/global.d.ts +4 -1
  15. package/dist/global.d.ts.map +1 -1
  16. package/dist/global.js +21 -9
  17. package/dist/index.d.ts +2 -2
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +2 -2
  20. package/dist/logger.js +1 -1
  21. package/dist/observability.d.ts +60 -0
  22. package/dist/observability.d.ts.map +1 -1
  23. package/dist/observability.js +265 -32
  24. package/dist/private.d.ts +10 -1
  25. package/dist/private.d.ts.map +1 -1
  26. package/dist/private.js +6 -1
  27. package/dist/runtime/helpers.d.ts +52 -0
  28. package/dist/runtime/helpers.d.ts.map +1 -0
  29. package/dist/runtime/helpers.js +264 -0
  30. package/dist/runtime/resume-hook.d.ts +17 -12
  31. package/dist/runtime/resume-hook.d.ts.map +1 -1
  32. package/dist/runtime/resume-hook.js +79 -64
  33. package/dist/runtime/start.d.ts +14 -0
  34. package/dist/runtime/start.d.ts.map +1 -1
  35. package/dist/runtime/start.js +71 -45
  36. package/dist/runtime/step-handler.d.ts +7 -0
  37. package/dist/runtime/step-handler.d.ts.map +1 -0
  38. package/dist/runtime/step-handler.js +337 -0
  39. package/dist/runtime/suspension-handler.d.ts +25 -0
  40. package/dist/runtime/suspension-handler.d.ts.map +1 -0
  41. package/dist/runtime/suspension-handler.js +182 -0
  42. package/dist/runtime/world.d.ts.map +1 -1
  43. package/dist/runtime/world.js +20 -21
  44. package/dist/runtime.d.ts +3 -7
  45. package/dist/runtime.d.ts.map +1 -1
  46. package/dist/runtime.js +103 -411
  47. package/dist/schemas.d.ts +1 -15
  48. package/dist/schemas.d.ts.map +1 -1
  49. package/dist/schemas.js +2 -15
  50. package/dist/serialization.d.ts +112 -21
  51. package/dist/serialization.d.ts.map +1 -1
  52. package/dist/serialization.js +469 -85
  53. package/dist/sleep.d.ts +10 -0
  54. package/dist/sleep.d.ts.map +1 -1
  55. package/dist/sleep.js +1 -1
  56. package/dist/source-map.d.ts +10 -0
  57. package/dist/source-map.d.ts.map +1 -0
  58. package/dist/source-map.js +56 -0
  59. package/dist/step/context-storage.d.ts +2 -1
  60. package/dist/step/context-storage.d.ts.map +1 -1
  61. package/dist/step/context-storage.js +1 -1
  62. package/dist/step/get-closure-vars.d.ts +9 -0
  63. package/dist/step/get-closure-vars.d.ts.map +1 -0
  64. package/dist/step/get-closure-vars.js +16 -0
  65. package/dist/step/get-step-metadata.js +1 -1
  66. package/dist/step/get-workflow-metadata.js +1 -1
  67. package/dist/step/writable-stream.d.ts +10 -2
  68. package/dist/step/writable-stream.d.ts.map +1 -1
  69. package/dist/step/writable-stream.js +6 -5
  70. package/dist/step.d.ts +1 -1
  71. package/dist/step.d.ts.map +1 -1
  72. package/dist/step.js +93 -47
  73. package/dist/symbols.d.ts +6 -0
  74. package/dist/symbols.d.ts.map +1 -1
  75. package/dist/symbols.js +7 -1
  76. package/dist/telemetry/semantic-conventions.d.ts +66 -38
  77. package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
  78. package/dist/telemetry/semantic-conventions.js +16 -3
  79. package/dist/telemetry.d.ts +8 -4
  80. package/dist/telemetry.d.ts.map +1 -1
  81. package/dist/telemetry.js +39 -6
  82. package/dist/types.js +1 -1
  83. package/dist/util.d.ts +5 -24
  84. package/dist/util.d.ts.map +1 -1
  85. package/dist/util.js +19 -38
  86. package/dist/version.d.ts +2 -0
  87. package/dist/version.d.ts.map +1 -0
  88. package/dist/version.js +3 -0
  89. package/dist/vm/index.js +2 -2
  90. package/dist/vm/uuid.js +1 -1
  91. package/dist/workflow/create-hook.js +1 -1
  92. package/dist/workflow/define-hook.d.ts +3 -3
  93. package/dist/workflow/define-hook.d.ts.map +1 -1
  94. package/dist/workflow/define-hook.js +1 -1
  95. package/dist/workflow/get-workflow-metadata.js +1 -1
  96. package/dist/workflow/hook.d.ts.map +1 -1
  97. package/dist/workflow/hook.js +49 -14
  98. package/dist/workflow/index.d.ts +1 -1
  99. package/dist/workflow/index.d.ts.map +1 -1
  100. package/dist/workflow/index.js +2 -2
  101. package/dist/workflow/sleep.d.ts +1 -1
  102. package/dist/workflow/sleep.d.ts.map +1 -1
  103. package/dist/workflow/sleep.js +26 -39
  104. package/dist/workflow/writable-stream.d.ts +1 -1
  105. package/dist/workflow/writable-stream.d.ts.map +1 -1
  106. package/dist/workflow/writable-stream.js +1 -1
  107. package/dist/workflow.d.ts +1 -1
  108. package/dist/workflow.d.ts.map +1 -1
  109. package/dist/workflow.js +72 -9
  110. package/docs/api-reference/create-hook.mdx +133 -0
  111. package/docs/api-reference/create-webhook.mdx +225 -0
  112. package/docs/api-reference/define-hook.mdx +206 -0
  113. package/docs/api-reference/fatal-error.mdx +37 -0
  114. package/docs/api-reference/fetch.mdx +139 -0
  115. package/docs/api-reference/get-step-metadata.mdx +76 -0
  116. package/docs/api-reference/get-workflow-metadata.mdx +44 -0
  117. package/docs/api-reference/get-writable.mdx +292 -0
  118. package/docs/api-reference/index.mdx +55 -0
  119. package/docs/api-reference/meta.json +3 -0
  120. package/docs/api-reference/retryable-error.mdx +106 -0
  121. package/docs/api-reference/sleep.mdx +59 -0
  122. package/docs/foundations/common-patterns.mdx +253 -0
  123. package/docs/foundations/errors-and-retries.mdx +190 -0
  124. package/docs/foundations/hooks.mdx +455 -0
  125. package/docs/foundations/idempotency.mdx +55 -0
  126. package/docs/foundations/index.mdx +32 -0
  127. package/docs/foundations/meta.json +14 -0
  128. package/docs/foundations/serialization.mdx +157 -0
  129. package/docs/foundations/starting-workflows.mdx +211 -0
  130. package/docs/foundations/streaming.mdx +569 -0
  131. package/docs/foundations/workflows-and-steps.mdx +197 -0
  132. package/docs/how-it-works/code-transform.mdx +334 -0
  133. package/docs/how-it-works/event-sourcing.mdx +254 -0
  134. package/docs/how-it-works/framework-integrations.mdx +437 -0
  135. package/docs/how-it-works/meta.json +10 -0
  136. package/docs/how-it-works/understanding-directives.mdx +611 -0
  137. package/package.json +31 -25
  138. package/dist/builtins.js.map +0 -1
  139. package/dist/create-hook.js.map +0 -1
  140. package/dist/define-hook.js.map +0 -1
  141. package/dist/events-consumer.js.map +0 -1
  142. package/dist/global.js.map +0 -1
  143. package/dist/index.js.map +0 -1
  144. package/dist/logger.js.map +0 -1
  145. package/dist/observability.js.map +0 -1
  146. package/dist/parse-name.d.ts +0 -25
  147. package/dist/parse-name.d.ts.map +0 -1
  148. package/dist/parse-name.js +0 -40
  149. package/dist/parse-name.js.map +0 -1
  150. package/dist/private.js.map +0 -1
  151. package/dist/runtime/resume-hook.js.map +0 -1
  152. package/dist/runtime/start.js.map +0 -1
  153. package/dist/runtime/world.js.map +0 -1
  154. package/dist/runtime.js.map +0 -1
  155. package/dist/schemas.js.map +0 -1
  156. package/dist/serialization.js.map +0 -1
  157. package/dist/sleep.js.map +0 -1
  158. package/dist/step/context-storage.js.map +0 -1
  159. package/dist/step/get-step-metadata.js.map +0 -1
  160. package/dist/step/get-workflow-metadata.js.map +0 -1
  161. package/dist/step/writable-stream.js.map +0 -1
  162. package/dist/step.js.map +0 -1
  163. package/dist/symbols.js.map +0 -1
  164. package/dist/telemetry/semantic-conventions.js.map +0 -1
  165. package/dist/telemetry.js.map +0 -1
  166. package/dist/types.js.map +0 -1
  167. package/dist/util.js.map +0 -1
  168. package/dist/vm/index.js.map +0 -1
  169. package/dist/vm/uuid.js.map +0 -1
  170. package/dist/workflow/create-hook.js.map +0 -1
  171. package/dist/workflow/define-hook.js.map +0 -1
  172. package/dist/workflow/get-workflow-metadata.js.map +0 -1
  173. package/dist/workflow/hook.js.map +0 -1
  174. package/dist/workflow/index.js.map +0 -1
  175. package/dist/workflow/sleep.js.map +0 -1
  176. package/dist/workflow/writable-stream.js.map +0 -1
  177. package/dist/workflow.js.map +0 -1
  178. package/dist/writable-stream.d.ts +0 -23
  179. package/dist/writable-stream.d.ts.map +0 -1
  180. package/dist/writable-stream.js +0 -17
  181. package/dist/writable-stream.js.map +0 -1
@@ -1,15 +1,16 @@
1
+ import { withResolvers } from '@workflow/utils';
1
2
  import { EventConsumerResult } from '../events-consumer.js';
2
3
  import { WorkflowSuspension } from '../global.js';
3
4
  import { webhookLogger } from '../logger.js';
4
5
  import { hydrateStepReturnValue } from '../serialization.js';
5
- import { withResolvers } from '../util.js';
6
+ import { ERROR_SLUGS, WorkflowRuntimeError } from '@workflow/errors';
6
7
  export function createCreateHook(ctx) {
7
8
  return function createHookImpl(options = {}) {
8
9
  // Generate hook ID and token
9
10
  const correlationId = `hook_${ctx.generateUlid()}`;
10
11
  const token = options.token ?? ctx.generateNanoid();
11
- // Add hook creation to invocations queue
12
- ctx.invocationsQueue.push({
12
+ // Add hook creation to invocations queue (using Map for O(1) operations)
13
+ ctx.invocationsQueue.set(correlationId, {
13
14
  type: 'hook',
14
15
  correlationId,
15
16
  token,
@@ -20,6 +21,9 @@ export function createCreateHook(ctx) {
20
21
  // Queue of promises that resolve to the next hook payload
21
22
  const promises = [];
22
23
  let eventLogEmpty = false;
24
+ // Track if we have a conflict so we can reject future awaits
25
+ let hasConflict = false;
26
+ let conflictErrorRef = null;
23
27
  webhookLogger.debug('Hook consumer setup', { correlationId, token });
24
28
  ctx.eventsConsumer.subscribe((event) => {
25
29
  // If there are no events and there are promises waiting,
@@ -31,21 +35,37 @@ export function createCreateHook(ctx) {
31
35
  setTimeout(() => {
32
36
  ctx.onWorkflowError(new WorkflowSuspension(ctx.invocationsQueue, ctx.globalThis));
33
37
  }, 0);
34
- return EventConsumerResult.Finished;
35
38
  }
39
+ return EventConsumerResult.NotConsumed;
40
+ }
41
+ if (event.correlationId !== correlationId) {
42
+ // We're not interested in this event - the correlationId belongs to a different entity
43
+ return EventConsumerResult.NotConsumed;
36
44
  }
37
45
  // 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);
46
+ if (event.eventType === 'hook_created') {
47
+ // Remove this hook from the invocations queue (O(1) delete using Map)
48
+ ctx.invocationsQueue.delete(correlationId);
49
+ return EventConsumerResult.Consumed;
50
+ }
51
+ // Handle hook_conflict event - another workflow is using this token
52
+ if (event.eventType === 'hook_conflict') {
53
+ // Remove this hook from the invocations queue
54
+ ctx.invocationsQueue.delete(correlationId);
55
+ // Store the conflict event so we can reject any awaited promises
56
+ const conflictEvent = event;
57
+ const conflictError = new WorkflowRuntimeError(`Hook token "${conflictEvent.eventData.token}" is already in use by another workflow`, { slug: ERROR_SLUGS.HOOK_CONFLICT });
58
+ // Reject any pending promises
59
+ for (const resolver of promises) {
60
+ resolver.reject(conflictError);
44
61
  }
62
+ promises.length = 0;
63
+ // Mark that we have a conflict so future awaits also reject
64
+ hasConflict = true;
65
+ conflictErrorRef = conflictError;
45
66
  return EventConsumerResult.Consumed;
46
67
  }
47
- if (event?.eventType === 'hook_received' &&
48
- event.correlationId === correlationId) {
68
+ if (event.eventType === 'hook_received') {
49
69
  if (promises.length > 0) {
50
70
  const next = promises.shift();
51
71
  if (next) {
@@ -59,11 +79,26 @@ export function createCreateHook(ctx) {
59
79
  }
60
80
  return EventConsumerResult.Consumed;
61
81
  }
62
- return EventConsumerResult.NotConsumed;
82
+ if (event.eventType === 'hook_disposed') {
83
+ // If a hook is explicitly disposed, we're done processing any more
84
+ // events for it
85
+ return EventConsumerResult.Finished;
86
+ }
87
+ // An unexpected event type has been received, this event log looks corrupted. Let's fail immediately.
88
+ setTimeout(() => {
89
+ ctx.onWorkflowError(new WorkflowRuntimeError(`Unexpected event type for hook ${correlationId} (token: ${token}) "${event.eventType}"`));
90
+ }, 0);
91
+ return EventConsumerResult.Finished;
63
92
  });
64
93
  // Helper function to create a new promise that waits for the next hook payload
65
94
  function createHookPromise() {
66
95
  const resolvers = withResolvers();
96
+ // If we have a conflict, reject immediately
97
+ // This handles the iterator case where each await should reject
98
+ if (hasConflict && conflictErrorRef) {
99
+ resolvers.reject(conflictErrorRef);
100
+ return resolvers.promise;
101
+ }
67
102
  if (payloadsQueue.length > 0) {
68
103
  const nextPayload = payloadsQueue.shift();
69
104
  if (nextPayload) {
@@ -98,4 +133,4 @@ export function createCreateHook(ctx) {
98
133
  return hook;
99
134
  };
100
135
  }
101
- //# sourceMappingURL=hook.js.map
136
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG9vay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy93b3JrZmxvdy9ob29rLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBNkIsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFHM0UsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDNUQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ2xELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFN0MsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDN0QsT0FBTyxFQUFFLFdBQVcsRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRXJFLE1BQU0sVUFBVSxnQkFBZ0IsQ0FBQyxHQUFnQztJQUMvRCxPQUFPLFNBQVMsY0FBYyxDQUFVLFVBQXVCLEVBQUU7UUFDL0QsNkJBQTZCO1FBQzdCLE1BQU0sYUFBYSxHQUFHLFFBQVEsR0FBRyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUM7UUFDbkQsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLEtBQUssSUFBSSxHQUFHLENBQUMsY0FBYyxFQUFFLENBQUM7UUFFcEQseUVBQXlFO1FBQ3pFLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFO1lBQ3RDLElBQUksRUFBRSxNQUFNO1lBQ1osYUFBYTtZQUNiLEtBQUs7WUFDTCxRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVE7U0FDM0IsQ0FBQyxDQUFDO1FBRUgscUVBQXFFO1FBQ3JFLE1BQU0sYUFBYSxHQUF3QixFQUFFLENBQUM7UUFFOUMsMERBQTBEO1FBQzFELE1BQU0sUUFBUSxHQUE4QixFQUFFLENBQUM7UUFFL0MsSUFBSSxhQUFhLEdBQUcsS0FBSyxDQUFDO1FBRTFCLDZEQUE2RDtRQUM3RCxJQUFJLFdBQVcsR0FBRyxLQUFLLENBQUM7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
@@ -1,10 +1,10 @@
1
1
  import type { StepMetadata } from '../step/get-step-metadata.js';
2
2
  export { FatalError, RetryableError, type RetryableErrorOptions, } from '@workflow/errors';
3
3
  export type { Hook, HookOptions } from '../create-hook.js';
4
+ export { sleep } from '../sleep.js';
4
5
  export { createHook, createWebhook } from './create-hook.js';
5
6
  export { defineHook } from './define-hook.js';
6
7
  export { getWorkflowMetadata } from './get-workflow-metadata.js';
7
- export { sleep } from '../sleep.js';
8
8
  export { getWritable } from './writable-stream.js';
9
9
  export declare function getStepMetadata(): StepMetadata;
10
10
  export declare function resumeHook(): void;
@@ -1 +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,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAInD,wBAAgB,eAAe,IAAI,YAAY,CAI9C;AACD,wBAAgB,UAAU,SAIzB"}
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,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,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"}
@@ -1,8 +1,8 @@
1
1
  export { FatalError, RetryableError, } from '@workflow/errors';
2
+ export { sleep } from '../sleep.js';
2
3
  export { createHook, createWebhook } from './create-hook.js';
3
4
  export { defineHook } from './define-hook.js';
4
5
  export { getWorkflowMetadata } from './get-workflow-metadata.js';
5
- export { sleep } from '../sleep.js';
6
6
  export { getWritable } from './writable-stream.js';
7
7
  // workflows can't use these functions, but we still need to provide
8
8
  // the export so bundling doesn't fail when step and workflow are in same file
@@ -12,4 +12,4 @@ export function getStepMetadata() {
12
12
  export function resumeHook() {
13
13
  throw new Error('`resumeHook()` can only be called from outside a workflow function');
14
14
  }
15
- //# sourceMappingURL=index.js.map
15
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvd29ya2Zsb3cvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUNMLFVBQVUsRUFDVixjQUFjLEdBRWYsTUFBTSxrQkFBa0IsQ0FBQztBQUUxQixPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxVQUFVLEVBQUUsYUFBYSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDN0QsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUVuRCxvRUFBb0U7QUFDcEUsOEVBQThFO0FBQzlFLE1BQU0sVUFBVSxlQUFlO0lBQzdCLE1BQU0sSUFBSSxLQUFLLENBQ2IsK0RBQStELENBQ2hFLENBQUM7QUFDSixDQUFDO0FBQ0QsTUFBTSxVQUFVLFVBQVU7SUFDeEIsTUFBTSxJQUFJLEtBQUssQ0FDYixvRUFBb0UsQ0FDckUsQ0FBQztBQUNKLENBQUMifQ==
@@ -1,4 +1,4 @@
1
1
  import type { StringValue } from 'ms';
2
2
  import type { WorkflowOrchestratorContext } from '../private.js';
3
- export declare function createSleep(ctx: WorkflowOrchestratorContext): (param: StringValue | Date) => Promise<void>;
3
+ export declare function createSleep(ctx: WorkflowOrchestratorContext): (param: StringValue | Date | number) => Promise<void>;
4
4
  //# sourceMappingURL=sleep.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sleep.d.ts","sourceRoot":"","sources":["../../src/workflow/sleep.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AAItC,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAGjE,wBAAgB,WAAW,CAAC,GAAG,EAAE,2BAA2B,IAC1B,OAAO,WAAW,GAAG,IAAI,KAAG,OAAO,CAAC,IAAI,CAAC,CA0F1E"}
1
+ {"version":3,"file":"sleep.d.ts","sourceRoot":"","sources":["../../src/workflow/sleep.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AAGtC,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAGjE,wBAAgB,WAAW,CAAC,GAAG,EAAE,2BAA2B,IAExD,OAAO,WAAW,GAAG,IAAI,GAAG,MAAM,KACjC,OAAO,CAAC,IAAI,CAAC,CAqEjB"}
@@ -1,37 +1,20 @@
1
- import ms from 'ms';
1
+ import { parseDurationToDate, withResolvers } from '@workflow/utils';
2
2
  import { EventConsumerResult } from '../events-consumer.js';
3
3
  import { WorkflowSuspension } from '../global.js';
4
- import { withResolvers } from '../util.js';
4
+ import { WorkflowRuntimeError } from '@workflow/errors';
5
5
  export function createSleep(ctx) {
6
6
  return async function sleepImpl(param) {
7
7
  const { promise, resolve } = withResolvers();
8
8
  const correlationId = `wait_${ctx.generateUlid()}`;
9
9
  // Calculate the resume time
10
- let resumeAt;
11
- if (typeof param === 'string') {
12
- const durationMs = ms(param);
13
- if (typeof durationMs !== 'number' || durationMs < 0) {
14
- throw new Error(`Invalid sleep duration: "${param}". Expected a valid duration string like "1s", "1m", "1h", etc.`);
15
- }
16
- resumeAt = new Date(Date.now() + durationMs);
17
- }
18
- else if (param instanceof Date ||
19
- (param &&
20
- typeof param === 'object' &&
21
- typeof param.getTime === 'function')) {
22
- // Handle both Date instances and date-like objects (from deserialization)
23
- const dateParam = param instanceof Date ? param : new Date(param.getTime());
24
- resumeAt = dateParam;
25
- }
26
- else {
27
- throw new Error(`Invalid sleep parameter. Expected a duration string or Date object.`);
28
- }
29
- // Add wait to invocations queue
30
- ctx.invocationsQueue.push({
10
+ const resumeAt = parseDurationToDate(param);
11
+ // Add wait to invocations queue (using Map for O(1) operations)
12
+ const waitItem = {
31
13
  type: 'wait',
32
14
  correlationId,
33
15
  resumeAt,
34
- });
16
+ };
17
+ ctx.invocationsQueue.set(correlationId, waitItem);
35
18
  ctx.eventsConsumer.subscribe((event) => {
36
19
  // If there are no events and we're waiting for wait_completed,
37
20
  // suspend the workflow until the wait fires
@@ -41,34 +24,38 @@ export function createSleep(ctx) {
41
24
  }, 0);
42
25
  return EventConsumerResult.NotConsumed;
43
26
  }
27
+ if (event.correlationId !== correlationId) {
28
+ // We're not interested in this event - the correlationId belongs to a different entity
29
+ return EventConsumerResult.NotConsumed;
30
+ }
44
31
  // Check for wait_created event to mark this wait as having the event created
45
- if (event?.eventType === 'wait_created' &&
46
- event.correlationId === correlationId) {
32
+ if (event.eventType === 'wait_created') {
47
33
  // Mark this wait as having the created event, but keep it in the queue
48
- const waitItem = ctx.invocationsQueue.find((item) => item.type === 'wait' && item.correlationId === correlationId);
49
- if (waitItem) {
50
- waitItem.hasCreatedEvent = true;
51
- waitItem.resumeAt = event.eventData.resumeAt;
34
+ // O(1) lookup using Map
35
+ const queueItem = ctx.invocationsQueue.get(correlationId);
36
+ if (queueItem && queueItem.type === 'wait') {
37
+ queueItem.hasCreatedEvent = true;
38
+ queueItem.resumeAt = event.eventData.resumeAt;
52
39
  }
53
40
  return EventConsumerResult.Consumed;
54
41
  }
55
42
  // Check for wait_completed event
56
- if (event?.eventType === 'wait_completed' &&
57
- event.correlationId === correlationId) {
58
- // Remove this wait from the invocations queue
59
- const index = ctx.invocationsQueue.findIndex((item) => item.type === 'wait' && item.correlationId === correlationId);
60
- if (index !== -1) {
61
- ctx.invocationsQueue.splice(index, 1);
62
- }
43
+ if (event.eventType === 'wait_completed') {
44
+ // Remove this wait from the invocations queue (O(1) delete using Map)
45
+ ctx.invocationsQueue.delete(correlationId);
63
46
  // Wait has elapsed, resolve the sleep
64
47
  setTimeout(() => {
65
48
  resolve();
66
49
  }, 0);
67
50
  return EventConsumerResult.Finished;
68
51
  }
69
- return EventConsumerResult.NotConsumed;
52
+ // An unexpected event type has been received, this event log looks corrupted. Let's fail immediately.
53
+ setTimeout(() => {
54
+ ctx.onWorkflowError(new WorkflowRuntimeError(`Unexpected event type for wait ${correlationId} "${event.eventType}"`));
55
+ }, 0);
56
+ return EventConsumerResult.Finished;
70
57
  });
71
58
  return promise;
72
59
  };
73
60
  }
74
- //# sourceMappingURL=sleep.js.map
61
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2xlZXAuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvd29ya2Zsb3cvc2xlZXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLG1CQUFtQixFQUFFLGFBQWEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRXJFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzVELE9BQU8sRUFBZ0Msa0JBQWtCLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFaEYsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFeEQsTUFBTSxVQUFVLFdBQVcsQ0FBQyxHQUFnQztJQUMxRCxPQUFPLEtBQUssVUFBVSxTQUFTLENBQzdCLEtBQWtDO1FBRWxDLE1BQU0sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLEdBQUcsYUFBYSxFQUFRLENBQUM7UUFDbkQsTUFBTSxhQUFhLEdBQUcsUUFBUSxHQUFHLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQztRQUVuRCw0QkFBNEI7UUFDNUIsTUFBTSxRQUFRLEdBQUcsbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFNUMsZ0VBQWdFO1FBQ2hFLE1BQU0sUUFBUSxHQUE0QjtZQUN4QyxJQUFJLEVBQUUsTUFBTTtZQUNaLGFBQWE7WUFDYixRQUFRO1NBQ1QsQ0FBQztRQUNGLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBRWxELEdBQUcsQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7WUFDckMsK0RBQStEO1lBQy9ELDRDQUE0QztZQUM1QyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ1gsVUFBVSxDQUFDLEdBQUcsRUFBRTtvQkFDZCxHQUFHLENBQUMsZUFBZSxDQUNqQixJQUFJLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxHQUFHLENBQUMsVUFBVSxDQUFDLENBQzdELENBQUM7Z0JBQ0osQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO2dCQUNOLE9BQU8sbUJBQW1CLENBQUMsV0FBVyxDQUFDO1lBQ3pDLENBQUM7WUFFRCxJQUFJLEtBQUssQ0FBQyxhQUFhLEtBQUssYUFBYSxFQUFFLENBQUM7Z0JBQzFDLHVGQUF1RjtnQkFDdkYsT0FBTyxtQkFBbUIsQ0FBQyxXQUFXLENBQUM7WUFDekMsQ0FBQztZQUVELDZFQUE2RTtZQUM3RSxJQUFJLEtBQUssQ0FBQyxTQUFTLEtBQUssY0FBYyxFQUFFLENBQUM7Z0JBQ3ZDLHVFQUF1RTtnQkFDdkUsd0JBQXdCO2dCQUN4QixNQUFNLFNBQVMsR0FBRyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxDQUFDO2dCQUMxRCxJQUFJLFNBQVMsSUFBSSxTQUFTLENBQUMsSUFBSSxLQUFLLE1BQU0sRUFBRSxDQUFDO29CQUMzQyxTQUFTLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQztvQkFDakMsU0FBUyxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQztnQkFDaEQsQ0FBQztnQkFDRCxPQUFPLG1CQUFtQixDQUFDLFFBQVEsQ0FBQztZQUN0QyxDQUFDO1lBRUQsaUNBQWlDO1lBQ2pDLElBQUksS0FBSyxDQUFDLFNBQVMsS0FBSyxnQkFBZ0IsRUFBRSxDQUFDO2dCQUN6QyxzRUFBc0U7Z0JBQ3RFLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUM7Z0JBRTNDLHNDQUFzQztnQkFDdEMsVUFBVSxDQUFDLEdBQUcsRUFBRTtvQkFDZCxPQUFPLEVBQUUsQ0FBQztnQkFDWixDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQ04sT0FBTyxtQkFBbUIsQ0FBQyxRQUFRLENBQUM7WUFDdEMsQ0FBQztZQUVELHNHQUFzRztZQUN0RyxVQUFVLENBQUMsR0FBRyxFQUFFO2dCQUNkLEdBQUcsQ0FBQyxlQUFlLENBQ2pCLElBQUksb0JBQW9CLENBQ3RCLGtDQUFrQyxhQUFhLEtBQUssS0FBSyxDQUFDLFNBQVMsR0FBRyxDQUN2RSxDQUNGLENBQUM7WUFDSixDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDTixPQUFPLG1CQUFtQixDQUFDLFFBQVEsQ0FBQztRQUN0QyxDQUFDLENBQUMsQ0FBQztRQUVILE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENBQUMsQ0FBQztBQUNKLENBQUMifQ==
@@ -1,3 +1,3 @@
1
- import type { WorkflowWritableStreamOptions } from '../writable-stream.js';
1
+ import type { WorkflowWritableStreamOptions } from '../step/writable-stream.js';
2
2
  export declare function getWritable<W = any>(options?: WorkflowWritableStreamOptions): WritableStream<W>;
3
3
  //# sourceMappingURL=writable-stream.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"writable-stream.d.ts","sourceRoot":"","sources":["../../src/workflow/writable-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAC;AAGhF,wBAAgB,WAAW,CAAC,CAAC,GAAG,GAAG,EACjC,OAAO,GAAE,6BAAkC,GAC1C,cAAc,CAAC,CAAC,CAAC,CASnB"}
@@ -9,4 +9,4 @@ export function getWritable(options = {}) {
9
9
  },
10
10
  });
11
11
  }
12
- //# sourceMappingURL=writable-stream.js.map
12
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JpdGFibGUtc3RyZWFtLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3dvcmtmbG93L3dyaXRhYmxlLXN0cmVhbS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFM0UsTUFBTSxVQUFVLFdBQVcsQ0FDekIsVUFBeUMsRUFBRTtJQUUzQyxNQUFNLEVBQUUsU0FBUyxFQUFFLEdBQUcsT0FBTyxDQUFDO0lBQzlCLE1BQU0sSUFBSSxHQUFJLFVBQWtCLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNwRSxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLGNBQWMsQ0FBQyxTQUFTLEVBQUU7UUFDeEQsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFO1lBQ3BCLEtBQUssRUFBRSxJQUFJO1lBQ1gsUUFBUSxFQUFFLEtBQUs7U0FDaEI7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDIn0=
@@ -1,3 +1,3 @@
1
1
  import type { Event, WorkflowRun } from '@workflow/world';
2
- export declare function runWorkflow(workflowCode: string, workflowRun: WorkflowRun, events: Event[]): Promise<unknown>;
2
+ export declare function runWorkflow(workflowCode: string, workflowRun: WorkflowRun, events: Event[]): Promise<Uint8Array | unknown>;
3
3
  //# sourceMappingURL=workflow.d.ts.map
@@ -1 +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;AA2B1D,wBAAsB,WAAW,CAC/B,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,KAAK,EAAE,GACd,OAAO,CAAC,OAAO,CAAC,CA2hBlB"}
1
+ {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../src/workflow.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AA4B1D,wBAAsB,WAAW,CAC/B,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,KAAK,EAAE,GACd,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,CAimB/B"}
package/dist/workflow.js CHANGED
@@ -1,15 +1,18 @@
1
1
  import { runInContext } from 'node:vm';
2
- import { ERROR_SLUGS } from '@workflow/errors';
2
+ import { ERROR_SLUGS, WorkflowRuntimeError } from '@workflow/errors';
3
+ import { withResolvers } from '@workflow/utils';
4
+ import { getPort } from '@workflow/utils/get-port';
5
+ import { parseWorkflowName } from '@workflow/utils/parse-name';
3
6
  import * as nanoid from 'nanoid';
4
7
  import { monotonicFactory } from 'ulid';
5
8
  import { EventConsumerResult, EventsConsumer } from './events-consumer.js';
6
9
  import { ENOTSUP } from './global.js';
7
10
  import { dehydrateWorkflowReturnValue, hydrateWorkflowArguments, } from './serialization.js';
8
11
  import { createUseStep } from './step.js';
9
- import { BODY_INIT_SYMBOL, WORKFLOW_CREATE_HOOK, WORKFLOW_GET_STREAM_ID, WORKFLOW_SLEEP, WORKFLOW_USE_STEP, } from './symbols.js';
12
+ import { BODY_INIT_SYMBOL, STABLE_ULID, WORKFLOW_CREATE_HOOK, WORKFLOW_GET_STREAM_ID, WORKFLOW_SLEEP, WORKFLOW_USE_STEP, } from './symbols.js';
10
13
  import * as Attribute from './telemetry/semantic-conventions.js';
11
14
  import { trace } from './telemetry.js';
12
- import { getWorkflowRunStreamId, withResolvers } from './util.js';
15
+ import { getWorkflowRunStreamId } from './util.js';
13
16
  import { createContext } from './vm/index.js';
14
17
  import { WORKFLOW_CONTEXT_SYMBOL } from './workflow/get-workflow-metadata.js';
15
18
  import { createCreateHook } from './workflow/hook.js';
@@ -26,6 +29,9 @@ export async function runWorkflow(workflowCode, workflowRun, events) {
26
29
  if (!startedAt) {
27
30
  throw new Error(`Workflow run "${workflowRun.runId}" has no "startedAt" timestamp (should not happen)`);
28
31
  }
32
+ // Get the port before creating VM context to avoid async operations
33
+ // affecting the deterministic timestamp
34
+ const port = await getPort();
29
35
  const { context, globalThis: vmGlobalThis, updateTimestamp, } = createContext({
30
36
  seed: workflowRun.runId,
31
37
  fixedTimestamp: +startedAt,
@@ -39,7 +45,7 @@ export async function runWorkflow(workflowCode, workflowRun, events) {
39
45
  eventsConsumer: new EventsConsumer(events),
40
46
  generateUlid: () => ulid(+startedAt),
41
47
  generateNanoid,
42
- invocationsQueue: [],
48
+ invocationsQueue: new Map(),
43
49
  };
44
50
  // Subscribe to the events log to update the timestamp in the vm context
45
51
  workflowContext.eventsConsumer.subscribe((event) => {
@@ -50,6 +56,23 @@ export async function runWorkflow(workflowCode, workflowRun, events) {
50
56
  // Never consume events - this is only a passive subscriber
51
57
  return EventConsumerResult.NotConsumed;
52
58
  });
59
+ // Consume run lifecycle events - these are structural events that don't
60
+ // need special handling in the workflow, but must be consumed to advance
61
+ // past them in the event log
62
+ workflowContext.eventsConsumer.subscribe((event) => {
63
+ if (!event) {
64
+ return EventConsumerResult.NotConsumed;
65
+ }
66
+ // Consume run_created - every run has exactly one
67
+ if (event.eventType === 'run_created') {
68
+ return EventConsumerResult.Consumed;
69
+ }
70
+ // Consume run_started - every run has exactly one
71
+ if (event.eventType === 'run_started') {
72
+ return EventConsumerResult.Consumed;
73
+ }
74
+ return EventConsumerResult.NotConsumed;
75
+ });
53
76
  const useStep = createUseStep(workflowContext);
54
77
  const createHook = createCreateHook(workflowContext);
55
78
  const sleep = createSleep(workflowContext);
@@ -62,10 +85,10 @@ export async function runWorkflow(workflowCode, workflowRun, events) {
62
85
  // @ts-expect-error - `@types/node` says symbol is not valid, but it does work
63
86
  vmGlobalThis[WORKFLOW_GET_STREAM_ID] = (namespace) => getWorkflowRunStreamId(workflowRun.runId, namespace);
64
87
  // TODO: there should be a getUrl method on the world interface itself. This
65
- // solution only works for vercel + embedded worlds.
88
+ // solution only works for vercel + local worlds.
66
89
  const url = process.env.VERCEL_URL
67
90
  ? `https://${process.env.VERCEL_URL}`
68
- : `http://localhost:${process.env.PORT || 3000}`;
91
+ : `http://localhost:${port ?? 3000}`;
69
92
  // For the workflow VM, we store the context in a symbol on the `globalThis` object
70
93
  const ctx = {
71
94
  workflowRunId: workflowRun.runId,
@@ -74,11 +97,47 @@ export async function runWorkflow(workflowCode, workflowRun, events) {
74
97
  };
75
98
  // @ts-expect-error - `@types/node` says symbol is not valid, but it does work
76
99
  vmGlobalThis[WORKFLOW_CONTEXT_SYMBOL] = ctx;
100
+ // @ts-expect-error - `@types/node` says symbol is not valid, but it does work
101
+ vmGlobalThis[STABLE_ULID] = ulid;
77
102
  // NOTE: Will have a config override to use the custom fetch step.
78
103
  // For now `fetch` must be explicitly imported from `workflow`.
79
104
  vmGlobalThis.fetch = () => {
80
105
  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}`);
81
106
  };
107
+ // Override timeout/interval functions to throw helpful errors
108
+ // These are not supported in workflow functions because they rely on
109
+ // asynchronous scheduling which breaks deterministic replay
110
+ const timeoutErrorMessage = 'Timeout functions like "setTimeout" and "setInterval" are not supported in workflow functions. Use the "sleep" function from "workflow" for time-based delays.';
111
+ vmGlobalThis.setTimeout = () => {
112
+ throw new WorkflowRuntimeError(timeoutErrorMessage, {
113
+ slug: ERROR_SLUGS.TIMEOUT_FUNCTIONS_IN_WORKFLOW,
114
+ });
115
+ };
116
+ vmGlobalThis.setInterval = () => {
117
+ throw new WorkflowRuntimeError(timeoutErrorMessage, {
118
+ slug: ERROR_SLUGS.TIMEOUT_FUNCTIONS_IN_WORKFLOW,
119
+ });
120
+ };
121
+ vmGlobalThis.clearTimeout = () => {
122
+ throw new WorkflowRuntimeError(timeoutErrorMessage, {
123
+ slug: ERROR_SLUGS.TIMEOUT_FUNCTIONS_IN_WORKFLOW,
124
+ });
125
+ };
126
+ vmGlobalThis.clearInterval = () => {
127
+ throw new WorkflowRuntimeError(timeoutErrorMessage, {
128
+ slug: ERROR_SLUGS.TIMEOUT_FUNCTIONS_IN_WORKFLOW,
129
+ });
130
+ };
131
+ vmGlobalThis.setImmediate = () => {
132
+ throw new WorkflowRuntimeError(timeoutErrorMessage, {
133
+ slug: ERROR_SLUGS.TIMEOUT_FUNCTIONS_IN_WORKFLOW,
134
+ });
135
+ };
136
+ vmGlobalThis.clearImmediate = () => {
137
+ throw new WorkflowRuntimeError(timeoutErrorMessage, {
138
+ slug: ERROR_SLUGS.TIMEOUT_FUNCTIONS_IN_WORKFLOW,
139
+ });
140
+ };
82
141
  // `Request` and `Response` are special built-in classes that invoke steps
83
142
  // for the `json()`, `text()` and `arrayBuffer()` instance methods
84
143
  class Request {
@@ -435,8 +494,12 @@ export async function runWorkflow(workflowCode, workflowRun, events) {
435
494
  const SYMBOL_FOR_REQ_CONTEXT = Symbol.for('@vercel/request-context');
436
495
  // @ts-expect-error - `@types/node` says symbol is not valid, but it does work
437
496
  vmGlobalThis[SYMBOL_FOR_REQ_CONTEXT] = globalThis[SYMBOL_FOR_REQ_CONTEXT];
438
- // Get a reference to the user-defined workflow function
439
- const workflowFn = runInContext(`${workflowCode}; globalThis.__private_workflows?.get(${JSON.stringify(workflowRun.workflowName)})`, context);
497
+ // Get a reference to the user-defined workflow function.
498
+ // The filename parameter ensures stack traces show a meaningful name
499
+ // (e.g., "example/workflows/99_e2e.ts") instead of "evalmachine.<anonymous>".
500
+ const parsedName = parseWorkflowName(workflowRun.workflowName);
501
+ const filename = parsedName?.path || workflowRun.workflowName;
502
+ const workflowFn = runInContext(`${workflowCode}; globalThis.__private_workflows?.get(${JSON.stringify(workflowRun.workflowName)})`, context, { filename });
440
503
  if (typeof workflowFn !== 'function') {
441
504
  throw new ReferenceError(`Workflow ${JSON.stringify(workflowRun.workflowName)} must be a function, but got "${typeof workflowFn}" instead`);
442
505
  }
@@ -456,4 +519,4 @@ export async function runWorkflow(workflowCode, workflowRun, events) {
456
519
  return dehydrated;
457
520
  });
458
521
  }
459
- //# sourceMappingURL=workflow.js.map
522
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29ya2Zsb3cuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvd29ya2Zsb3cudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUN2QyxPQUFPLEVBQUUsV0FBVyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDckUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2hELE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUUvRCxPQUFPLEtBQUssTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUNqQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDeEMsT0FBTyxFQUFFLG1CQUFtQixFQUFFLGNBQWMsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzNFLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFdEMsT0FBTyxFQUNMLDRCQUE0QixFQUM1Qix3QkFBd0IsR0FDekIsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzFDLE9BQU8sRUFDTCxnQkFBZ0IsRUFDaEIsV0FBVyxFQUNYLG9CQUFvQixFQUNwQixzQkFBc0IsRUFDdEIsY0FBYyxFQUNkLGlCQUFpQixHQUNsQixNQUFNLGNBQWMsQ0FBQztBQUN0QixPQUFPLEtBQUssU0FBUyxNQUFNLHFDQUFxQyxDQUFDO0FBQ2pFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN2QyxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDbkQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUU5QyxPQUFPLEVBQUUsdUJBQXVCLEVB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
@@ -0,0 +1,133 @@
1
+ ---
2
+ title: createHook
3
+ ---
4
+
5
+ Creates a low-level hook primitive that can be used to resume a workflow run with arbitrary payloads.
6
+
7
+ Hooks allow external systems to send data to a paused workflow without the HTTP-specific constraints of webhooks. They're identified by a token and can receive any serializable payload.
8
+
9
+ ```ts lineNumbers
10
+ import { createHook } from "workflow"
11
+
12
+ export async function hookWorkflow() {
13
+ "use workflow";
14
+ const hook = createHook(); // [!code highlight]
15
+ const result = await hook; // Suspends the workflow until the hook is resumed
16
+ }
17
+ ```
18
+
19
+ ## API Signature
20
+
21
+ ### Parameters
22
+
23
+ <TSDoc
24
+ definition={`
25
+ import { createHook } from "workflow";
26
+ export default createHook;`
27
+ }
28
+ showSections={['parameters']}
29
+ />
30
+
31
+ #### HookOptions
32
+
33
+ <TSDoc
34
+ definition={`
35
+ import type { HookOptions } from "workflow";
36
+ export default HookOptions;`
37
+ }
38
+ />
39
+
40
+ ### Returns
41
+
42
+ <TSDoc
43
+ definition={`
44
+ import { createHook } from "workflow";
45
+ export default createHook;`}
46
+ showSections={['returns']}
47
+ />
48
+
49
+ #### Hook
50
+
51
+ <TSDoc
52
+ definition={`
53
+ import type { Hook } from "workflow";
54
+ export default Hook;`}
55
+ />
56
+
57
+ The returned `Hook` object also implements `AsyncIterable<T>`, which allows you to iterate over incoming payloads using `for await...of` syntax.
58
+
59
+ ## Examples
60
+
61
+ ### Basic Usage
62
+
63
+ When creating a hook, you can specify a payload type to be used for automatic type safety.
64
+
65
+ ```typescript lineNumbers
66
+ import { createHook } from "workflow"
67
+
68
+ export async function approvalWorkflow() {
69
+ "use workflow";
70
+
71
+ const hook = createHook<{ approved: boolean; comment: string }>(); // [!code highlight]
72
+ console.log("Send approval to token:", hook.token);
73
+
74
+ const result = await hook;
75
+
76
+ if (result.approved) {
77
+ console.log("Approved with comment:", result.comment);
78
+ }
79
+ }
80
+ ```
81
+
82
+ ### Customizing Tokens
83
+
84
+ Tokens are used to identify a specific hook. You can customize the token to be more specific to a use case.
85
+
86
+ ```typescript lineNumbers
87
+ import { createHook } from "workflow";
88
+
89
+ export async function slackBotWorkflow(channelId: string) {
90
+ "use workflow";
91
+
92
+ // Token constructed from channel ID
93
+ const hook = createHook<SlackMessage>({ // [!code highlight]
94
+ token: `slack_webhook:${channelId}`, // [!code highlight]
95
+ }); // [!code highlight]
96
+
97
+ for await (const message of hook) {
98
+ if (message.text === "/stop") {
99
+ break;
100
+ }
101
+ await processMessage(message);
102
+ }
103
+ }
104
+ ```
105
+
106
+ ### Waiting for Multiple Payloads
107
+
108
+ You can also wait for multiple payloads by using the `for await...of` syntax.
109
+
110
+ ```typescript lineNumbers
111
+ import { createHook } from "workflow"
112
+
113
+ export async function collectHookWorkflow() {
114
+ "use workflow";
115
+
116
+ const hook = createHook<{ message: string; done?: boolean }>();
117
+
118
+ const payloads = [];
119
+ for await (const payload of hook) { // [!code highlight]
120
+ payloads.push(payload);
121
+
122
+ if (payload.done) break;
123
+ }
124
+
125
+ return payloads;
126
+ }
127
+ ```
128
+
129
+ ## Related Functions
130
+
131
+ - [`defineHook()`](/docs/api-reference/workflow/define-hook) - Type-safe hook helper
132
+ - [`resumeHook()`](/docs/api-reference/workflow-api/resume-hook) - Resume a hook with a payload
133
+ - [`createWebhook()`](/docs/api-reference/workflow/create-webhook) - Higher-level HTTP webhook abstraction