@multiplier-labs/stepflow 0.3.4 → 0.3.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 (109) hide show
  1. package/README.md +9 -0
  2. package/dist/{chunk-5XJBAPXF.js → chunk-4IDPWWGS.js} +15 -4
  3. package/dist/chunk-4IDPWWGS.js.map +1 -0
  4. package/dist/{chunk-U3PCVK6O.js → chunk-T6GAZBTQ.js} +70 -38
  5. package/dist/chunk-T6GAZBTQ.js.map +1 -0
  6. package/dist/{chunk-FMPJBK2N.js → chunk-TVSADUYU.js} +3 -5
  7. package/dist/{chunk-FMPJBK2N.js.map → chunk-TVSADUYU.js.map} +1 -1
  8. package/dist/events/index.d.ts +43 -3
  9. package/dist/events/index.js +7 -3
  10. package/dist/{index-Cd0IZ40L.d.ts → index-CdXDv30T.d.ts} +10 -2
  11. package/dist/index.d.ts +5 -4
  12. package/dist/index.js +159 -46
  13. package/dist/index.js.map +1 -1
  14. package/dist/scheduler/index.d.ts +2 -2
  15. package/dist/scheduler/index.js +1 -1
  16. package/dist/storage/index.d.ts +6 -4
  17. package/dist/storage/index.js +1 -1
  18. package/dist/{types-DSEjiLMj.d.ts → types-BfWe5yP6.d.ts} +2 -0
  19. package/package.json +26 -14
  20. package/.codekin/reports/code-review/2026-04-11_code-review-daily.md +0 -146
  21. package/.codekin/reports/code-review/2026-04-13_code-review-daily.md +0 -74
  22. package/.codekin/reports/comments/2026-04-04_comment-assessment.md +0 -179
  23. package/.codekin/reports/comments/2026-04-11_comment-assessment.md +0 -161
  24. package/.codekin/reports/comments/2026-04-14_comment-assessment.md +0 -34
  25. package/.codekin/reports/complexity/2026-04-03_complexity-report.md +0 -152
  26. package/.codekin/reports/complexity/2026-04-11_complexity-report.md +0 -152
  27. package/.codekin/reports/complexity/2026-04-14_complexity-report.md +0 -34
  28. package/.codekin/reports/dependencies/2026-04-04_dependency-health.md +0 -94
  29. package/.codekin/reports/dependencies/2026-04-11_dependency-health.md +0 -93
  30. package/.codekin/reports/docs-audit/2026-04-04_docs-audit.md +0 -10
  31. package/.codekin/reports/docs-audit/2026-04-11_docs-audit.md +0 -138
  32. package/.codekin/reports/docs-audit/2026-04-13_docs-audit.md +0 -121
  33. package/.codekin/reports/security/2026-04-03_security-audit.md +0 -208
  34. package/.codekin/reports/security/2026-04-11_security-audit.md +0 -297
  35. package/.github/CODEOWNERS +0 -15
  36. package/.github/dependabot.yml +0 -23
  37. package/.github/workflows/ci.yml +0 -38
  38. package/.github/workflows/publish.yml +0 -42
  39. package/.github/workflows/security.yml +0 -29
  40. package/CHANGELOG.md +0 -34
  41. package/SECURITY.md +0 -40
  42. package/dist/chunk-5XJBAPXF.js.map +0 -1
  43. package/dist/chunk-U3PCVK6O.js.map +0 -1
  44. package/docs/github-packages-setup.md +0 -97
  45. package/docs/stepflow-api-reference.md +0 -1663
  46. package/src/core/engine/concurrency.ts +0 -229
  47. package/src/core/engine/lifecycle.ts +0 -176
  48. package/src/core/engine.test.ts +0 -1435
  49. package/src/core/engine.ts +0 -598
  50. package/src/core/index.ts +0 -7
  51. package/src/core/orchestrator/persistence.ts +0 -165
  52. package/src/core/orchestrator/plan-resolution.ts +0 -140
  53. package/src/core/orchestrator/state-transitions.ts +0 -109
  54. package/src/core/orchestrator/step-runner.ts +0 -427
  55. package/src/core/orchestrator.ts +0 -252
  56. package/src/core/types.ts +0 -220
  57. package/src/events/index.ts +0 -8
  58. package/src/events/memory.test.ts +0 -107
  59. package/src/events/memory.ts +0 -92
  60. package/src/events/socketio.test.ts +0 -378
  61. package/src/events/socketio.ts +0 -262
  62. package/src/events/types.ts +0 -118
  63. package/src/events/webhook.test.ts +0 -949
  64. package/src/events/webhook.ts +0 -807
  65. package/src/index.ts +0 -270
  66. package/src/planning/evaluate-condition.test.ts +0 -153
  67. package/src/planning/evaluate-condition.ts +0 -105
  68. package/src/planning/index.ts +0 -55
  69. package/src/planning/planner.ts +0 -494
  70. package/src/planning/planning.test.ts +0 -727
  71. package/src/planning/registry.test.ts +0 -398
  72. package/src/planning/registry.ts +0 -283
  73. package/src/planning/types.ts +0 -566
  74. package/src/scheduler/cron.test.ts +0 -479
  75. package/src/scheduler/cron.ts +0 -438
  76. package/src/scheduler/index.ts +0 -8
  77. package/src/scheduler/postgres-persistence.ts +0 -530
  78. package/src/scheduler/sqlite-persistence.test.ts +0 -235
  79. package/src/scheduler/sqlite-persistence.ts +0 -286
  80. package/src/scheduler/types.ts +0 -73
  81. package/src/storage/index.ts +0 -27
  82. package/src/storage/memory.test.ts +0 -349
  83. package/src/storage/memory.ts +0 -227
  84. package/src/storage/postgres-core.ts +0 -550
  85. package/src/storage/postgres-migration.test.ts +0 -69
  86. package/src/storage/postgres-transaction-pagination.test.ts +0 -107
  87. package/src/storage/postgres.ts +0 -835
  88. package/src/storage/sqlite-core.ts +0 -151
  89. package/src/storage/sqlite.test.ts +0 -642
  90. package/src/storage/sqlite.ts +0 -717
  91. package/src/storage/types.ts +0 -343
  92. package/src/utils/errors.test.ts +0 -150
  93. package/src/utils/errors.ts +0 -161
  94. package/src/utils/id.ts +0 -21
  95. package/src/utils/index.ts +0 -10
  96. package/src/utils/logger.test.ts +0 -121
  97. package/src/utils/logger.ts +0 -96
  98. package/src/utils/pinned-fetch.test.ts +0 -84
  99. package/src/utils/pinned-fetch.ts +0 -118
  100. package/src/utils/postgres-deps.ts +0 -79
  101. package/src/utils/retry.test.ts +0 -177
  102. package/src/utils/retry.ts +0 -121
  103. package/src/utils/safe-json.test.ts +0 -166
  104. package/src/utils/safe-json.ts +0 -107
  105. package/src/utils/webhook-signature.test.ts +0 -111
  106. package/src/utils/webhook-signature.ts +0 -74
  107. package/tsconfig.json +0 -21
  108. package/tsup.config.ts +0 -14
  109. package/vitest.config.ts +0 -9
@@ -1,343 +0,0 @@
1
- /**
2
- * Storage interface types for the workflow engine.
3
- * Implement StorageAdapter to use your preferred database.
4
- */
5
-
6
- import type { WorkflowKind, RunStatus, StepStatus, WorkflowError } from '../core/types';
7
-
8
- // ============================================================================
9
- // Extended Status Types (New)
10
- // ============================================================================
11
-
12
- /**
13
- * Extended status of a workflow run.
14
- * Adds 'pending' and 'timeout' to the core statuses.
15
- */
16
- export type ExtendedRunStatus =
17
- | 'pending'
18
- | 'queued'
19
- | 'running'
20
- | 'succeeded'
21
- | 'failed'
22
- | 'canceled'
23
- | 'timeout';
24
-
25
- /**
26
- * Extended status of a workflow step.
27
- * Uses 'completed' instead of 'succeeded' for consistency.
28
- */
29
- export type ExtendedStepStatus =
30
- | 'pending'
31
- | 'running'
32
- | 'completed'
33
- | 'failed'
34
- | 'skipped'
35
- | 'canceled';
36
-
37
- // ============================================================================
38
- // Legacy Record Types (Backward Compatible)
39
- // ============================================================================
40
-
41
- /**
42
- * Stored representation of a workflow run.
43
- */
44
- export interface WorkflowRunRecord {
45
- id: string;
46
- kind: string;
47
- status: RunStatus;
48
- parentRunId?: string;
49
- input: Record<string, unknown>;
50
- context: Record<string, unknown>;
51
- completedSteps?: string[];
52
- output?: Record<string, unknown>;
53
- error?: { code: string; message: string };
54
- metadata?: Record<string, unknown>;
55
- priority?: number;
56
- timeoutMs?: number;
57
- createdAt: Date;
58
- startedAt?: Date;
59
- finishedAt?: Date;
60
- }
61
-
62
- /**
63
- * Stored representation of a workflow step execution.
64
- */
65
- export interface WorkflowRunStepRecord {
66
- id: string;
67
- runId: string;
68
- stepKey: string;
69
- stepName: string;
70
- status: StepStatus;
71
- attempt: number;
72
- result?: unknown;
73
- error?: WorkflowError;
74
- startedAt?: Date;
75
- finishedAt?: Date;
76
- }
77
-
78
- /**
79
- * Stored workflow event.
80
- */
81
- export interface WorkflowEventRecord {
82
- id: string;
83
- runId: string;
84
- stepKey?: string;
85
- eventType: string;
86
- level: 'info' | 'warn' | 'error';
87
- payload?: unknown;
88
- timestamp: Date;
89
- }
90
-
91
- // ============================================================================
92
- // New Extended Record Types
93
- // ============================================================================
94
-
95
- /**
96
- * Extended workflow run record with additional fields.
97
- * Used by new WorkflowStorage implementations.
98
- */
99
- export interface ExtendedWorkflowRunRecord {
100
- id: string;
101
- kind: string;
102
- status: ExtendedRunStatus;
103
- input: Record<string, unknown>;
104
- context: Record<string, unknown>;
105
- output?: Record<string, unknown>;
106
- error?: { code: string; message: string };
107
- metadata?: Record<string, unknown>;
108
- priority: number;
109
- timeoutMs?: number;
110
- createdAt: Date;
111
- startedAt?: Date;
112
- finishedAt?: Date;
113
- }
114
-
115
- /**
116
- * Step result representation.
117
- */
118
- export interface StepResult {
119
- id: string;
120
- runId: string;
121
- stepName: string;
122
- status: ExtendedStepStatus;
123
- output?: Record<string, unknown>;
124
- error?: Record<string, unknown>;
125
- attempt: number;
126
- startedAt?: Date;
127
- completedAt?: Date;
128
- }
129
-
130
- /**
131
- * Step record for workflow steps.
132
- */
133
- export interface StepRecord {
134
- stepKey: string;
135
- stepName: string;
136
- status: ExtendedStepStatus;
137
- result?: Record<string, unknown>;
138
- error?: Record<string, unknown>;
139
- attempt: number;
140
- startedAt?: Date;
141
- finishedAt?: Date;
142
- }
143
-
144
- // ============================================================================
145
- // Input Types (New)
146
- // ============================================================================
147
-
148
- /**
149
- * Input for creating a new workflow run.
150
- */
151
- export interface CreateRunInput {
152
- id?: string;
153
- kind: string;
154
- status: ExtendedRunStatus;
155
- parentRunId?: string;
156
- input: Record<string, unknown>;
157
- context?: Record<string, unknown>; // Optional with default {}
158
- metadata?: Record<string, unknown>;
159
- priority?: number;
160
- timeoutMs?: number;
161
- }
162
-
163
- /**
164
- * Input for updating a workflow run.
165
- */
166
- export interface UpdateRunInput {
167
- status?: ExtendedRunStatus;
168
- context?: Record<string, unknown>;
169
- output?: Record<string, unknown>;
170
- error?: { code: string; message: string };
171
- startedAt?: Date;
172
- finishedAt?: Date;
173
- }
174
-
175
- // ============================================================================
176
- // Query Options
177
- // ============================================================================
178
-
179
- /**
180
- * Options for listing runs.
181
- */
182
- export interface ListRunsOptions {
183
- kind?: WorkflowKind;
184
- status?: RunStatus | RunStatus[];
185
- parentRunId?: string;
186
- limit?: number;
187
- offset?: number;
188
- orderBy?: 'createdAt' | 'startedAt' | 'finishedAt';
189
- orderDirection?: 'asc' | 'desc';
190
- }
191
-
192
- /**
193
- * Extended options for listing runs.
194
- */
195
- export interface ExtendedListRunsOptions {
196
- kind?: string;
197
- status?: ExtendedRunStatus | ExtendedRunStatus[];
198
- limit?: number;
199
- offset?: number;
200
- orderBy?: 'createdAt' | 'startedAt' | 'finishedAt';
201
- orderDir?: 'asc' | 'desc';
202
- }
203
-
204
- /**
205
- * Options for listing events.
206
- */
207
- export interface ListEventsOptions {
208
- stepKey?: string;
209
- level?: 'info' | 'warn' | 'error';
210
- limit?: number;
211
- offset?: number;
212
- }
213
-
214
- /**
215
- * Paginated result wrapper.
216
- */
217
- export interface PaginatedResult<T> {
218
- items: T[];
219
- total: number;
220
- limit?: number;
221
- offset?: number;
222
- }
223
-
224
- // ============================================================================
225
- // WorkflowStorage Interface (New)
226
- // ============================================================================
227
-
228
- /**
229
- * New storage interface for workflow persistence.
230
- * Implement this interface for new implementations.
231
- */
232
- export interface WorkflowStorage {
233
- // Run operations
234
- createRun(run: CreateRunInput): Promise<ExtendedWorkflowRunRecord>;
235
- getRun(id: string): Promise<ExtendedWorkflowRunRecord | null>;
236
- updateRun(id: string, updates: UpdateRunInput): Promise<void>;
237
- listRuns(options?: ExtendedListRunsOptions): Promise<PaginatedResult<ExtendedWorkflowRunRecord>>;
238
- deleteRun(id: string): Promise<void>;
239
-
240
- // Atomic dequeue for concurrency control
241
- dequeueRun(workflowKinds: string[]): Promise<ExtendedWorkflowRunRecord | null>;
242
-
243
- // Stale workflow cleanup
244
- cleanupStaleRuns(defaultTimeoutMs?: number): Promise<number>;
245
- markRunsAsFailed(runIds: string[], reason: string): Promise<void>;
246
-
247
- // Step operations
248
- getStepResult(runId: string, stepName: string): Promise<StepResult | undefined>;
249
- getStepResults(runId: string): Promise<StepResult[]>;
250
- getStepsForRun(runId: string): Promise<StepRecord[]>;
251
- saveStepResult(result: Omit<StepResult, 'id'> & { id?: string }): Promise<void>;
252
-
253
- // Lifecycle
254
- initialize(): Promise<void>;
255
- close(): Promise<void>;
256
- }
257
-
258
- // ============================================================================
259
- // Legacy Storage Adapter Interface
260
- // ============================================================================
261
-
262
- /**
263
- * Abstract storage adapter interface.
264
- * Implement this interface to use your preferred database.
265
- */
266
- export interface StorageAdapter {
267
- // Run operations
268
- createRun(run: Omit<WorkflowRunRecord, 'id' | 'createdAt'>): Promise<WorkflowRunRecord>;
269
- getRun(runId: string): Promise<WorkflowRunRecord | null>;
270
- updateRun(runId: string, updates: Partial<WorkflowRunRecord>): Promise<void>;
271
- listRuns(options?: ListRunsOptions): Promise<PaginatedResult<WorkflowRunRecord>>;
272
-
273
- // Step operations
274
- createStep(step: Omit<WorkflowRunStepRecord, 'id'>): Promise<WorkflowRunStepRecord>;
275
- getStep(stepId: string): Promise<WorkflowRunStepRecord | null>;
276
- updateStep(stepId: string, updates: Partial<WorkflowRunStepRecord>): Promise<void>;
277
- getStepsForRun(runId: string): Promise<WorkflowRunStepRecord[]>;
278
-
279
- // Event operations
280
- saveEvent(event: Omit<WorkflowEventRecord, 'id'>): Promise<void>;
281
- getEventsForRun(runId: string, options?: ListEventsOptions): Promise<WorkflowEventRecord[]>;
282
-
283
- /**
284
- * Optional transaction support.
285
- * @deprecated Transaction support is deprecated and will be removed in a future release.
286
- */
287
- transaction?<T>(fn: (tx: StorageAdapter) => Promise<T>): Promise<T>;
288
-
289
- // Optional: Cleanup
290
- deleteOldRuns?(olderThan: Date): Promise<number>;
291
-
292
- // Optional: Lifecycle (required for adapters that need async setup, e.g. PostgreSQL)
293
- initialize?(): Promise<void>;
294
- close?(): void | Promise<void>;
295
- }
296
-
297
- // ============================================================================
298
- // Database Schema Types
299
- // ============================================================================
300
-
301
- /**
302
- * Database table schema for workflow runs.
303
- * Note: When used with Kysely, wrap auto-generated fields with Generated<T>.
304
- */
305
- export interface StepflowRunsTable {
306
- id: string;
307
- kind: string;
308
- status: ExtendedRunStatus;
309
- input: Record<string, unknown>;
310
- context: Record<string, unknown>;
311
- output: Record<string, unknown> | null;
312
- error: { code: string; message: string } | null;
313
- metadata: Record<string, unknown> | null;
314
- priority: number;
315
- timeout_ms: number | null;
316
- created_at: Date;
317
- started_at: Date | null;
318
- finished_at: Date | null;
319
- }
320
-
321
- /**
322
- * Database table schema for step results.
323
- * Note: When used with Kysely, wrap auto-generated fields with Generated<T>.
324
- */
325
- export interface StepflowStepResultsTable {
326
- id: string;
327
- run_id: string;
328
- step_name: string;
329
- status: ExtendedStepStatus;
330
- output: Record<string, unknown> | null;
331
- error: Record<string, unknown> | null;
332
- attempt: number;
333
- started_at: Date | null;
334
- completed_at: Date | null;
335
- }
336
-
337
- /**
338
- * Combined database schema for Stepflow.
339
- */
340
- export interface StepflowDatabase {
341
- 'stepflow.runs': StepflowRunsTable;
342
- 'stepflow.step_results': StepflowStepResultsTable;
343
- }
@@ -1,150 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import {
3
- WorkflowEngineError,
4
- WorkflowNotFoundError,
5
- WorkflowAlreadyRegisteredError,
6
- RunNotFoundError,
7
- StepError,
8
- StepTimeoutError,
9
- WorkflowCanceledError,
10
- WorkflowTimeoutError,
11
- } from './errors';
12
-
13
- describe('WorkflowEngineError', () => {
14
- it('should store code, message, and details', () => {
15
- const err = new WorkflowEngineError('TEST_CODE', 'test message', { key: 'val' });
16
-
17
- expect(err.code).toBe('TEST_CODE');
18
- expect(err.message).toBe('test message');
19
- expect(err.details).toEqual({ key: 'val' });
20
- expect(err.name).toBe('WorkflowEngineError');
21
- expect(err).toBeInstanceOf(Error);
22
- });
23
-
24
- it('should convert to record', () => {
25
- const err = new WorkflowEngineError('CODE', 'msg', { x: 1 });
26
- const record = err.toRecord();
27
-
28
- expect(record.code).toBe('CODE');
29
- expect(record.message).toBe('msg');
30
- expect(record.details).toEqual({ x: 1 });
31
- expect(record.stack).toBeUndefined();
32
- });
33
-
34
- describe('fromError', () => {
35
- it('should convert WorkflowEngineError to record', () => {
36
- const err = new WorkflowEngineError('MY_CODE', 'my msg');
37
- const record = WorkflowEngineError.fromError(err);
38
-
39
- expect(record.code).toBe('MY_CODE');
40
- expect(record.message).toBe('my msg');
41
- });
42
-
43
- it('should convert regular Error to record with default code', () => {
44
- const err = new Error('regular error');
45
- const record = WorkflowEngineError.fromError(err);
46
-
47
- expect(record.code).toBe('UNKNOWN_ERROR');
48
- expect(record.message).toBe('regular error');
49
- expect(record.stack).toBeUndefined();
50
- });
51
-
52
- it('should convert regular Error with custom code', () => {
53
- const err = new Error('oops');
54
- const record = WorkflowEngineError.fromError(err, 'CUSTOM_CODE');
55
-
56
- expect(record.code).toBe('CUSTOM_CODE');
57
- });
58
-
59
- it('should convert non-Error value to record', () => {
60
- const record = WorkflowEngineError.fromError('string error');
61
-
62
- expect(record.code).toBe('UNKNOWN_ERROR');
63
- expect(record.message).toBe('string error');
64
- expect(record.stack).toBeUndefined();
65
- });
66
-
67
- it('should convert number to record', () => {
68
- const record = WorkflowEngineError.fromError(42);
69
-
70
- expect(record.message).toBe('42');
71
- });
72
- });
73
- });
74
-
75
- describe('WorkflowNotFoundError', () => {
76
- it('should have correct code and message', () => {
77
- const err = new WorkflowNotFoundError('my.workflow');
78
-
79
- expect(err.code).toBe('WORKFLOW_NOT_FOUND');
80
- expect(err.message).toBe('Workflow "my.workflow" is not registered');
81
- expect(err.name).toBe('WorkflowNotFoundError');
82
- expect(err.details).toEqual({ kind: 'my.workflow' });
83
- });
84
- });
85
-
86
- describe('WorkflowAlreadyRegisteredError', () => {
87
- it('should have correct code and message', () => {
88
- const err = new WorkflowAlreadyRegisteredError('dup.workflow');
89
-
90
- expect(err.code).toBe('WORKFLOW_ALREADY_REGISTERED');
91
- expect(err.message).toContain('dup.workflow');
92
- expect(err.name).toBe('WorkflowAlreadyRegisteredError');
93
- });
94
- });
95
-
96
- describe('RunNotFoundError', () => {
97
- it('should have correct code and message', () => {
98
- const err = new RunNotFoundError('run-123');
99
-
100
- expect(err.code).toBe('RUN_NOT_FOUND');
101
- expect(err.message).toContain('run-123');
102
- expect(err.name).toBe('RunNotFoundError');
103
- });
104
- });
105
-
106
- describe('StepError', () => {
107
- it('should store step key, attempt, and cause', () => {
108
- const cause = new Error('root cause');
109
- const err = new StepError('step1', 'step failed', 3, cause);
110
-
111
- expect(err.code).toBe('STEP_ERROR');
112
- expect(err.stepKey).toBe('step1');
113
- expect(err.attempt).toBe(3);
114
- expect(err.cause).toBe(cause);
115
- expect(err.name).toBe('StepError');
116
- });
117
- });
118
-
119
- describe('StepTimeoutError', () => {
120
- it('should store step key and timeout', () => {
121
- const err = new StepTimeoutError('slow_step', 5000);
122
-
123
- expect(err.code).toBe('STEP_TIMEOUT');
124
- expect(err.stepKey).toBe('slow_step');
125
- expect(err.timeoutMs).toBe(5000);
126
- expect(err.message).toContain('5000ms');
127
- expect(err.name).toBe('StepTimeoutError');
128
- });
129
- });
130
-
131
- describe('WorkflowCanceledError', () => {
132
- it('should have correct code and message', () => {
133
- const err = new WorkflowCanceledError('run-456');
134
-
135
- expect(err.code).toBe('WORKFLOW_CANCELED');
136
- expect(err.message).toContain('run-456');
137
- expect(err.name).toBe('WorkflowCanceledError');
138
- });
139
- });
140
-
141
- describe('WorkflowTimeoutError', () => {
142
- it('should store timeout value', () => {
143
- const err = new WorkflowTimeoutError('run-789', 30000);
144
-
145
- expect(err.code).toBe('WORKFLOW_TIMEOUT');
146
- expect(err.timeoutMs).toBe(30000);
147
- expect(err.message).toContain('30000ms');
148
- expect(err.name).toBe('WorkflowTimeoutError');
149
- });
150
- });
@@ -1,161 +0,0 @@
1
- /**
2
- * Custom error classes for the workflow engine.
3
- */
4
-
5
- import type { WorkflowError } from '../core/types';
6
-
7
- /**
8
- * Base error class for workflow-related errors.
9
- */
10
- export class WorkflowEngineError extends Error {
11
- readonly code: string;
12
- readonly details?: Record<string, unknown>;
13
-
14
- constructor(code: string, message: string, details?: Record<string, unknown>) {
15
- super(message);
16
- this.name = 'WorkflowEngineError';
17
- this.code = code;
18
- this.details = details;
19
- }
20
-
21
- /**
22
- * Convert to a WorkflowError record for storage.
23
- */
24
- toRecord(): WorkflowError {
25
- return {
26
- code: this.code,
27
- message: this.message,
28
- details: this.details,
29
- };
30
- }
31
-
32
- /**
33
- * Create a WorkflowError record from any error.
34
- */
35
- static fromError(error: unknown, defaultCode = 'UNKNOWN_ERROR'): WorkflowError {
36
- if (error instanceof WorkflowEngineError) {
37
- return error.toRecord();
38
- }
39
-
40
- if (error instanceof Error) {
41
- return {
42
- code: defaultCode,
43
- message: error.message,
44
- };
45
- }
46
-
47
- return {
48
- code: defaultCode,
49
- message: String(error),
50
- };
51
- }
52
- }
53
-
54
- /**
55
- * Error thrown when a workflow is not found in the registry.
56
- */
57
- export class WorkflowNotFoundError extends WorkflowEngineError {
58
- constructor(kind: string) {
59
- super('WORKFLOW_NOT_FOUND', `Workflow "${kind}" is not registered`, { kind });
60
- this.name = 'WorkflowNotFoundError';
61
- }
62
- }
63
-
64
- /**
65
- * Error thrown when a workflow is already registered.
66
- */
67
- export class WorkflowAlreadyRegisteredError extends WorkflowEngineError {
68
- constructor(kind: string) {
69
- super('WORKFLOW_ALREADY_REGISTERED', `Workflow "${kind}" is already registered`, { kind });
70
- this.name = 'WorkflowAlreadyRegisteredError';
71
- }
72
- }
73
-
74
- /**
75
- * Error thrown when a run is not found.
76
- */
77
- export class RunNotFoundError extends WorkflowEngineError {
78
- constructor(runId: string) {
79
- super('RUN_NOT_FOUND', `Run "${runId}" not found`, { runId });
80
- this.name = 'RunNotFoundError';
81
- }
82
- }
83
-
84
- /**
85
- * Error thrown when a step fails.
86
- */
87
- export class StepError extends WorkflowEngineError {
88
- readonly stepKey: string;
89
- readonly attempt: number;
90
- readonly cause?: Error;
91
-
92
- constructor(stepKey: string, message: string, attempt: number, cause?: Error) {
93
- super('STEP_ERROR', message, { stepKey, attempt });
94
- this.name = 'StepError';
95
- this.stepKey = stepKey;
96
- this.attempt = attempt;
97
- this.cause = cause;
98
- }
99
- }
100
-
101
- /**
102
- * Error thrown when a step times out.
103
- */
104
- export class StepTimeoutError extends WorkflowEngineError {
105
- readonly stepKey: string;
106
- readonly timeoutMs: number;
107
-
108
- constructor(stepKey: string, timeoutMs: number) {
109
- super('STEP_TIMEOUT', `Step "${stepKey}" timed out after ${timeoutMs}ms`, {
110
- stepKey,
111
- timeoutMs,
112
- });
113
- this.name = 'StepTimeoutError';
114
- this.stepKey = stepKey;
115
- this.timeoutMs = timeoutMs;
116
- }
117
- }
118
-
119
- /**
120
- * Error thrown when a workflow is canceled.
121
- */
122
- export class WorkflowCanceledError extends WorkflowEngineError {
123
- constructor(runId: string) {
124
- super('WORKFLOW_CANCELED', `Workflow run "${runId}" was canceled`, { runId });
125
- this.name = 'WorkflowCanceledError';
126
- }
127
- }
128
-
129
- /**
130
- * Error thrown when waitForRun times out polling for a terminal status.
131
- */
132
- export class WaitForRunTimeoutError extends WorkflowEngineError {
133
- readonly runId: string;
134
- readonly timeoutMs: number;
135
-
136
- constructor(runId: string, timeoutMs: number) {
137
- super('WAIT_FOR_RUN_TIMEOUT', `Timeout waiting for run ${runId} after ${timeoutMs}ms`, {
138
- runId,
139
- timeoutMs,
140
- });
141
- this.name = 'WaitForRunTimeoutError';
142
- this.runId = runId;
143
- this.timeoutMs = timeoutMs;
144
- }
145
- }
146
-
147
- /**
148
- * Error thrown when a workflow times out.
149
- */
150
- export class WorkflowTimeoutError extends WorkflowEngineError {
151
- readonly timeoutMs: number;
152
-
153
- constructor(runId: string, timeoutMs: number) {
154
- super('WORKFLOW_TIMEOUT', `Workflow run "${runId}" timed out after ${timeoutMs}ms`, {
155
- runId,
156
- timeoutMs,
157
- });
158
- this.name = 'WorkflowTimeoutError';
159
- this.timeoutMs = timeoutMs;
160
- }
161
- }
package/src/utils/id.ts DELETED
@@ -1,21 +0,0 @@
1
- /**
2
- * ID generation utilities for the workflow engine.
3
- */
4
-
5
- import { randomBytes } from 'node:crypto';
6
-
7
- /**
8
- * Generate a unique ID for database records.
9
- * Uses a ULID-like format: base36 timestamp + random suffix.
10
- * This provides:
11
- * - Rough time-ordering (useful for debugging)
12
- * - High collision resistance
13
- * - URL-safe characters
14
- *
15
- * @returns A unique identifier string (approx 16 characters)
16
- */
17
- export function generateId(): string {
18
- const timestamp = Date.now().toString(36);
19
- const randomPart = randomBytes(6).toString('base64url');
20
- return `${timestamp}${randomPart}`;
21
- }
@@ -1,10 +0,0 @@
1
- /**
2
- * Utilities module exports.
3
- */
4
-
5
- export * from './id';
6
- export * from './errors';
7
- export * from './logger';
8
- export * from './retry';
9
- export * from './safe-json';
10
- export * from './webhook-signature';