@voyantjs/workflows 0.0.0 → 0.6.8

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 (61) hide show
  1. package/dist/auth/index.d.ts +26 -0
  2. package/dist/auth/index.d.ts.map +1 -0
  3. package/dist/auth/index.js +137 -0
  4. package/dist/conditions.d.ts +29 -0
  5. package/dist/conditions.d.ts.map +1 -0
  6. package/dist/conditions.js +5 -0
  7. package/dist/handler/index.d.ts +104 -0
  8. package/dist/handler/index.d.ts.map +1 -0
  9. package/dist/handler/index.js +238 -0
  10. package/dist/index.d.ts +6 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +10 -0
  13. package/dist/protocol/index.d.ts +187 -0
  14. package/dist/protocol/index.d.ts.map +1 -0
  15. package/dist/protocol/index.js +7 -0
  16. package/dist/rate-limit/index.d.ts +40 -0
  17. package/dist/rate-limit/index.d.ts.map +1 -0
  18. package/dist/rate-limit/index.js +139 -0
  19. package/dist/runtime/ctx.d.ts +102 -0
  20. package/dist/runtime/ctx.d.ts.map +1 -0
  21. package/dist/runtime/ctx.js +607 -0
  22. package/dist/runtime/determinism.d.ts +19 -0
  23. package/dist/runtime/determinism.d.ts.map +1 -0
  24. package/dist/runtime/determinism.js +61 -0
  25. package/dist/runtime/errors.d.ts +21 -0
  26. package/dist/runtime/errors.d.ts.map +1 -0
  27. package/dist/runtime/errors.js +45 -0
  28. package/dist/runtime/executor.d.ts +159 -0
  29. package/dist/runtime/executor.d.ts.map +1 -0
  30. package/dist/runtime/executor.js +225 -0
  31. package/dist/runtime/journal.d.ts +55 -0
  32. package/dist/runtime/journal.d.ts.map +1 -0
  33. package/dist/runtime/journal.js +28 -0
  34. package/dist/testing/index.d.ts +117 -0
  35. package/dist/testing/index.d.ts.map +1 -0
  36. package/dist/testing/index.js +595 -0
  37. package/dist/trigger.d.ts +122 -0
  38. package/dist/trigger.d.ts.map +1 -0
  39. package/dist/trigger.js +23 -0
  40. package/dist/types.d.ts +63 -0
  41. package/dist/types.d.ts.map +1 -0
  42. package/dist/types.js +3 -0
  43. package/dist/workflow.d.ts +212 -0
  44. package/dist/workflow.d.ts.map +1 -0
  45. package/dist/workflow.js +46 -0
  46. package/package.json +30 -30
  47. package/src/auth/index.ts +46 -52
  48. package/src/conditions.ts +13 -13
  49. package/src/handler/index.ts +110 -106
  50. package/src/index.ts +7 -7
  51. package/src/protocol/index.ts +137 -71
  52. package/src/rate-limit/index.ts +77 -78
  53. package/src/runtime/ctx.ts +354 -342
  54. package/src/runtime/determinism.ts +27 -27
  55. package/src/runtime/errors.ts +17 -17
  56. package/src/runtime/executor.ts +179 -172
  57. package/src/runtime/journal.ts +25 -25
  58. package/src/testing/index.ts +268 -202
  59. package/src/trigger.ts +64 -71
  60. package/src/types.ts +16 -18
  61. package/src/workflow.ts +154 -152
package/src/workflow.ts CHANGED
@@ -1,46 +1,47 @@
1
1
  // Workflow declaration and the `ctx` object.
2
2
  // Authoritative contract in docs/sdk-surface.md §2–§3.
3
3
 
4
+ import type { Condition } from "./conditions.js"
4
5
  import type {
5
6
  Duration,
6
7
  EnvironmentName,
7
8
  MachineType,
8
- RetryPolicy,
9
9
  RateLimitSpec,
10
+ RetryPolicy,
10
11
  RunStatus,
11
12
  RunTrigger,
12
- } from "./types.js";
13
- import type { Condition } from "./conditions.js";
13
+ } from "./types.js"
14
14
 
15
15
  // ---- Workflow ----
16
16
 
17
17
  export interface WorkflowHandle<TInput = unknown, TOutput = unknown> {
18
- readonly id: string;
18
+ readonly id: string
19
19
  /** Phantom; used only for TypeScript inference of `workflows.trigger(...)`. */
20
- readonly __input?: TInput;
21
- readonly __output?: TOutput;
20
+ readonly __input?: TInput
21
+ readonly __output?: TOutput
22
22
  }
23
23
 
24
24
  export interface WorkflowConfig<TInput, TOutput> {
25
- id: string;
26
- input?: unknown;
27
- output?: unknown;
28
- description?: string;
29
- schedule?: ScheduleDeclaration | ScheduleDeclaration[];
30
- concurrency?: ConcurrencyPolicy<TInput>;
31
- retry?: RetryPolicy;
32
- timeout?: Duration;
33
- defaultRuntime?: "edge" | "node";
34
- tags?: string[];
35
- run: (input: TInput, ctx: WorkflowContext<TInput>) => Promise<TOutput>;
25
+ id: string
26
+ input?: unknown
27
+ output?: unknown
28
+ description?: string
29
+ schedule?: ScheduleDeclaration | ScheduleDeclaration[]
30
+ concurrency?: ConcurrencyPolicy<TInput>
31
+ retry?: RetryPolicy
32
+ timeout?: Duration
33
+ defaultRuntime?: "edge" | "node"
34
+ tags?: string[]
35
+ run: (input: TInput, ctx: WorkflowContext<TInput>) => Promise<TOutput>
36
36
  }
37
37
 
38
38
  /**
39
39
  * Internal registered form of a workflow. The executor takes this
40
40
  * plus a request and drives the body.
41
41
  */
42
- export interface WorkflowDefinition<TInput = unknown, TOutput = unknown> extends WorkflowHandle<TInput, TOutput> {
43
- readonly config: WorkflowConfig<TInput, TOutput>;
42
+ export interface WorkflowDefinition<TInput = unknown, TOutput = unknown>
43
+ extends WorkflowHandle<TInput, TOutput> {
44
+ readonly config: WorkflowConfig<TInput, TOutput>
44
45
  }
45
46
 
46
47
  export type ScheduleDeclaration = (
@@ -48,18 +49,18 @@ export type ScheduleDeclaration = (
48
49
  | { every: Duration }
49
50
  | { at: string | Date }
50
51
  ) & {
51
- timezone?: string;
52
- input?: unknown | (() => unknown | Promise<unknown>);
53
- enabled?: boolean;
54
- overlap?: "skip" | "queue" | "allow";
55
- environments?: EnvironmentName[];
56
- name?: string;
57
- };
52
+ timezone?: string
53
+ input?: unknown | (() => unknown | Promise<unknown>)
54
+ enabled?: boolean
55
+ overlap?: "skip" | "queue" | "allow"
56
+ environments?: EnvironmentName[]
57
+ name?: string
58
+ }
58
59
 
59
60
  export interface ConcurrencyPolicy<TInput> {
60
- key?: string | ((input: TInput) => string);
61
- limit?: number;
62
- strategy?: "queue" | "cancel-in-progress" | "cancel-newest" | "round-robin";
61
+ key?: string | ((input: TInput) => string)
62
+ limit?: number
63
+ strategy?: "queue" | "cancel-in-progress" | "cancel-newest" | "round-robin"
63
64
  }
64
65
 
65
66
  /**
@@ -69,32 +70,33 @@ export interface ConcurrencyPolicy<TInput> {
69
70
  * manifest from a user bundle at load-time). Module-local `const`
70
71
  * would create a private map per bundle copy.
71
72
  */
72
- const REGISTRY_KEY = "__voyantWorkflowRegistry" as const;
73
+ const REGISTRY_KEY = "__voyantWorkflowRegistry" as const
73
74
  const globalRef = globalThis as unknown as Record<
74
75
  typeof REGISTRY_KEY,
75
76
  Map<string, WorkflowDefinition> | undefined
76
- >;
77
+ >
77
78
  const REGISTRY: Map<string, WorkflowDefinition> =
78
- globalRef[REGISTRY_KEY] ??= new Map<string, WorkflowDefinition>();
79
+ globalRef[REGISTRY_KEY] ?? new Map<string, WorkflowDefinition>()
80
+ globalRef[REGISTRY_KEY] = REGISTRY
79
81
 
80
82
  /** Declare a workflow. See docs/sdk-surface.md §2.1. */
81
83
  export function workflow<TInput = unknown, TOutput = unknown>(
82
84
  config: WorkflowConfig<TInput, TOutput>,
83
85
  ): WorkflowDefinition<TInput, TOutput> {
84
86
  if (REGISTRY.has(config.id)) {
85
- throw new Error(`workflow id "${config.id}" is already registered`);
87
+ throw new Error(`workflow id "${config.id}" is already registered`)
86
88
  }
87
89
  const def: WorkflowDefinition<TInput, TOutput> = {
88
90
  id: config.id,
89
91
  config,
90
- };
91
- REGISTRY.set(config.id, def as WorkflowDefinition);
92
- return def;
92
+ }
93
+ REGISTRY.set(config.id, def as WorkflowDefinition)
94
+ return def
93
95
  }
94
96
 
95
97
  /** Internal: look up a registered workflow by id. */
96
98
  export function getWorkflow(id: string): WorkflowDefinition | undefined {
97
- return REGISTRY.get(id);
99
+ return REGISTRY.get(id)
98
100
  }
99
101
 
100
102
  /**
@@ -103,7 +105,7 @@ export function getWorkflow(id: string): WorkflowDefinition | undefined {
103
105
  * public API — implementation detail of the SDK/CLI pair.
104
106
  */
105
107
  export function __listRegisteredWorkflows(): WorkflowDefinition[] {
106
- return [...REGISTRY.values()];
108
+ return [...REGISTRY.values()]
107
109
  }
108
110
 
109
111
  /**
@@ -113,171 +115,171 @@ export function __listRegisteredWorkflows(): WorkflowDefinition[] {
113
115
  * runs. Not part of the stable public API.
114
116
  */
115
117
  export function __resetRegistry(): void {
116
- REGISTRY.clear();
118
+ REGISTRY.clear()
117
119
  }
118
120
 
119
121
  // ---- Context ----
120
122
 
121
123
  export interface RunContext {
122
- id: string;
123
- number: number;
124
- attempt: number;
125
- triggeredBy: RunTrigger;
126
- tags: readonly string[];
127
- startedAt: number;
124
+ id: string
125
+ number: number
126
+ attempt: number
127
+ triggeredBy: RunTrigger
128
+ tags: readonly string[]
129
+ startedAt: number
128
130
  }
129
131
 
130
132
  export interface EnvironmentContext {
131
- name: EnvironmentName;
133
+ name: EnvironmentName
132
134
  git?: {
133
- commit: string;
134
- branch: string;
135
- pr?: { number: number; url: string };
136
- };
135
+ commit: string
136
+ branch: string
137
+ pr?: { number: number; url: string }
138
+ }
137
139
  }
138
140
 
139
141
  export interface WorkflowContext<_TInput = unknown> {
140
- readonly run: RunContext;
141
- readonly workflow: { id: string; version: string };
142
- readonly environment: EnvironmentContext;
143
- readonly project: { id: string; slug: string };
144
- readonly organization: { id: string; slug: string };
145
- readonly invocationCount: number;
146
- readonly signal: AbortSignal;
147
-
148
- step: StepApi;
149
- sleep: (duration: Duration) => Promise<void>;
150
- waitForEvent: WaitForEventApi;
151
- waitForSignal: WaitForSignalApi;
152
- waitForToken: WaitForTokenApi;
153
- invoke: InvokeApi;
154
- parallel: ParallelApi;
155
- stream: StreamApi;
156
- group: GroupApi;
157
- compensate: () => Promise<never>;
158
- metadata: MetadataApi;
159
-
160
- now: () => number;
161
- random: () => number;
162
- randomUUID: () => string;
163
-
164
- setRetry: (policy: RetryPolicy) => void;
142
+ readonly run: RunContext
143
+ readonly workflow: { id: string; version: string }
144
+ readonly environment: EnvironmentContext
145
+ readonly project: { id: string; slug: string }
146
+ readonly organization: { id: string; slug: string }
147
+ readonly invocationCount: number
148
+ readonly signal: AbortSignal
149
+
150
+ step: StepApi
151
+ sleep: (duration: Duration) => Promise<void>
152
+ waitForEvent: WaitForEventApi
153
+ waitForSignal: WaitForSignalApi
154
+ waitForToken: WaitForTokenApi
155
+ invoke: InvokeApi
156
+ parallel: ParallelApi
157
+ stream: StreamApi
158
+ group: GroupApi
159
+ compensate: () => Promise<never>
160
+ metadata: MetadataApi
161
+
162
+ now: () => number
163
+ random: () => number
164
+ randomUUID: () => string
165
+
166
+ setRetry: (policy: RetryPolicy) => void
165
167
  }
166
168
 
167
169
  // ---- Step ----
168
170
 
169
171
  export interface StepApi {
170
- <T>(id: string, fn: StepFn<T>): Promise<T>;
171
- <T>(id: string, opts: StepOptions<T>, fn: StepFn<T>): Promise<T>;
172
+ <T>(id: string, fn: StepFn<T>): Promise<T>
173
+ <T>(id: string, opts: StepOptions<T>, fn: StepFn<T>): Promise<T>
172
174
  }
173
175
 
174
- export type StepFn<T> = (stepCtx: StepContext) => Promise<T>;
176
+ export type StepFn<T> = (stepCtx: StepContext) => Promise<T>
175
177
 
176
178
  export interface StepContext {
177
- signal: AbortSignal;
178
- attempt: number;
179
- log: (level: "info" | "warn" | "error", msg: string, data?: object) => void;
179
+ signal: AbortSignal
180
+ attempt: number
181
+ log: (level: "info" | "warn" | "error", msg: string, data?: object) => void
180
182
  }
181
183
 
182
184
  export interface StepOptions<T = unknown> {
183
- runtime?: "edge" | "node";
184
- machine?: MachineType;
185
- timeout?: Duration;
186
- retry?: RetryPolicy | { max: 0 };
187
- idempotencyKey?: string;
188
- compensate?: (output: T) => Promise<void>;
189
- rateLimit?: RateLimitSpec;
190
- waitFor?: Condition;
191
- cancelIf?: Condition;
192
- skipIf?: Condition;
185
+ runtime?: "edge" | "node"
186
+ machine?: MachineType
187
+ timeout?: Duration
188
+ retry?: RetryPolicy | { max: 0 }
189
+ idempotencyKey?: string
190
+ compensate?: (output: T) => Promise<void>
191
+ rateLimit?: RateLimitSpec
192
+ waitFor?: Condition
193
+ cancelIf?: Condition
194
+ skipIf?: Condition
193
195
  }
194
196
 
195
197
  // ---- Waits ----
196
198
 
197
199
  export interface Waitable<T> extends PromiseLike<T | null> {
198
- [Symbol.asyncIterator](): AsyncIterableIterator<T>;
199
- close(): void;
200
+ [Symbol.asyncIterator](): AsyncIterableIterator<T>
201
+ close(): void
200
202
  }
201
203
 
202
- export interface WaitForEventApi {
203
- <T = unknown>(eventType: string, opts?: WaitForEventOptions<T>): Waitable<T>;
204
- }
204
+ export type WaitForEventApi = <T = unknown>(
205
+ eventType: string,
206
+ opts?: WaitForEventOptions<T>,
207
+ ) => Waitable<T>
205
208
 
206
209
  export interface WaitForEventOptions<T> {
207
- match?: Partial<T> | ((payload: T) => boolean);
208
- timeout?: Duration;
209
- lookback?: Duration;
210
- bufferSize?: number;
211
- onTimeout?: "null" | "throw";
210
+ match?: Partial<T> | ((payload: T) => boolean)
211
+ timeout?: Duration
212
+ lookback?: Duration
213
+ bufferSize?: number
214
+ onTimeout?: "null" | "throw"
212
215
  }
213
216
 
214
- export interface WaitForSignalApi {
215
- <T = unknown>(name: string, opts?: WaitForSignalOptions<T>): Waitable<T>;
216
- }
217
+ export type WaitForSignalApi = <T = unknown>(
218
+ name: string,
219
+ opts?: WaitForSignalOptions<T>,
220
+ ) => Waitable<T>
217
221
  export interface WaitForSignalOptions<T> extends WaitForEventOptions<T> {}
218
222
 
219
- export interface WaitForTokenApi {
220
- <T = unknown>(opts?: WaitForTokenOptions<T>): Promise<TokenWait<T>>;
221
- }
223
+ export type WaitForTokenApi = <T = unknown>(opts?: WaitForTokenOptions<T>) => Promise<TokenWait<T>>
222
224
  export interface WaitForTokenOptions<_T> {
223
- tokenId?: string;
224
- timeout?: Duration;
225
- onTimeout?: "null" | "throw";
226
- schema?: unknown;
225
+ tokenId?: string
226
+ timeout?: Duration
227
+ onTimeout?: "null" | "throw"
228
+ schema?: unknown
227
229
  }
228
230
  export interface TokenWait<T> {
229
- tokenId: string;
230
- url: string;
231
- wait: () => Promise<T | null>;
231
+ tokenId: string
232
+ url: string
233
+ wait: () => Promise<T | null>
232
234
  }
233
235
 
234
236
  // ---- Invoke / parallel ----
235
237
 
236
- export interface InvokeApi {
237
- <TIn, TOut>(
238
- workflow: WorkflowHandle<TIn, TOut>,
239
- input: TIn,
240
- opts?: InvokeOptions,
241
- ): Promise<TOut>;
242
- }
238
+ export type InvokeApi = <TIn, TOut>(
239
+ workflow: WorkflowHandle<TIn, TOut>,
240
+ input: TIn,
241
+ opts?: InvokeOptions,
242
+ ) => Promise<TOut>
243
243
 
244
244
  export interface InvokeOptions {
245
- idempotencyKey?: string;
246
- tags?: string[];
247
- lockToVersion?: string;
248
- detach?: boolean;
245
+ idempotencyKey?: string
246
+ tags?: string[]
247
+ lockToVersion?: string
248
+ /**
249
+ * Fire-and-forget child run. The child is still triggered and
250
+ * persisted, but the parent does not wait for its output or error.
251
+ * The awaited result resolves to `undefined`; callers should not use
252
+ * detached invokes for control flow.
253
+ */
254
+ detach?: boolean
249
255
  }
250
256
 
251
- export interface ParallelApi {
252
- <T, R>(
253
- items: readonly T[],
254
- fn: (item: T, index: number) => Promise<R>,
255
- opts?: ParallelOptions,
256
- ): Promise<R[]>;
257
- }
257
+ export type ParallelApi = <T, R>(
258
+ items: readonly T[],
259
+ fn: (item: T, index: number) => Promise<R>,
260
+ opts?: ParallelOptions,
261
+ ) => Promise<R[]>
258
262
 
259
263
  export interface ParallelOptions {
260
- concurrency?: number;
261
- settle?: boolean;
264
+ concurrency?: number
265
+ settle?: boolean
262
266
  }
263
267
 
264
268
  // ---- Streams ----
265
269
 
266
270
  export interface StreamApi {
267
- text(streamId: string, source: AsyncIterable<string>): Promise<void>;
268
- json<T>(streamId: string, source: AsyncIterable<T>): Promise<void>;
269
- bytes(streamId: string, source: AsyncIterable<Uint8Array>): Promise<void>;
270
- <T>(streamId: string, fn: () => AsyncGenerator<T>): Promise<void>;
271
+ text(streamId: string, source: AsyncIterable<string>): Promise<void>
272
+ json<T>(streamId: string, source: AsyncIterable<T>): Promise<void>
273
+ bytes(streamId: string, source: AsyncIterable<Uint8Array>): Promise<void>
274
+ <T>(streamId: string, fn: () => AsyncGenerator<T>): Promise<void>
271
275
  }
272
276
 
273
277
  // ---- Groups (scoped compensation) ----
274
278
 
275
- export interface GroupApi {
276
- <T>(name: string, fn: (scope: GroupScope) => Promise<T>): Promise<T>;
277
- }
279
+ export type GroupApi = <T>(name: string, fn: (scope: GroupScope) => Promise<T>) => Promise<T>
278
280
  export interface GroupScope {
279
- step: StepApi;
280
- compensate: () => Promise<never>;
281
+ step: StepApi
282
+ compensate: () => Promise<never>
281
283
  }
282
284
 
283
285
  // ---- Metadata ----
@@ -288,19 +290,19 @@ export type MetadataValue =
288
290
  | boolean
289
291
  | null
290
292
  | MetadataValue[]
291
- | { [key: string]: MetadataValue };
293
+ | { [key: string]: MetadataValue }
292
294
 
293
295
  export interface MetadataMutatorSubset {
294
- set(key: string, value: MetadataValue): void;
295
- increment(key: string, by?: number): void;
296
- append<T>(key: string, value: T): void;
297
- remove(key: string): void;
296
+ set(key: string, value: MetadataValue): void
297
+ increment(key: string, by?: number): void
298
+ append<T>(key: string, value: T): void
299
+ remove(key: string): void
298
300
  }
299
301
 
300
302
  export interface MetadataApi extends MetadataMutatorSubset {
301
- flush(): Promise<void>;
302
- parent?: MetadataMutatorSubset;
303
- root?: MetadataMutatorSubset;
303
+ flush(): Promise<void>
304
+ parent?: MetadataMutatorSubset
305
+ root?: MetadataMutatorSubset
304
306
  }
305
307
 
306
- export type { RunStatus };
308
+ export type { RunStatus }