@multiplier-labs/stepflow 0.3.4 → 0.3.6

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 (99) hide show
  1. package/README.md +9 -0
  2. package/dist/{chunk-U3PCVK6O.js → chunk-D5HW7VEG.js} +4 -2
  3. package/dist/chunk-D5HW7VEG.js.map +1 -0
  4. package/dist/{chunk-5XJBAPXF.js → chunk-JUPZEBR3.js} +3 -1
  5. package/dist/{chunk-5XJBAPXF.js.map → chunk-JUPZEBR3.js.map} +1 -1
  6. package/dist/events/index.d.ts +2 -0
  7. package/dist/events/index.js +1 -1
  8. package/dist/index.js +2 -2
  9. package/dist/storage/index.js +1 -1
  10. package/package.json +23 -12
  11. package/.codekin/reports/code-review/2026-04-11_code-review-daily.md +0 -146
  12. package/.codekin/reports/code-review/2026-04-13_code-review-daily.md +0 -74
  13. package/.codekin/reports/comments/2026-04-04_comment-assessment.md +0 -179
  14. package/.codekin/reports/comments/2026-04-11_comment-assessment.md +0 -161
  15. package/.codekin/reports/comments/2026-04-14_comment-assessment.md +0 -34
  16. package/.codekin/reports/complexity/2026-04-03_complexity-report.md +0 -152
  17. package/.codekin/reports/complexity/2026-04-11_complexity-report.md +0 -152
  18. package/.codekin/reports/complexity/2026-04-14_complexity-report.md +0 -34
  19. package/.codekin/reports/dependencies/2026-04-04_dependency-health.md +0 -94
  20. package/.codekin/reports/dependencies/2026-04-11_dependency-health.md +0 -93
  21. package/.codekin/reports/docs-audit/2026-04-04_docs-audit.md +0 -10
  22. package/.codekin/reports/docs-audit/2026-04-11_docs-audit.md +0 -138
  23. package/.codekin/reports/docs-audit/2026-04-13_docs-audit.md +0 -121
  24. package/.codekin/reports/security/2026-04-03_security-audit.md +0 -208
  25. package/.codekin/reports/security/2026-04-11_security-audit.md +0 -297
  26. package/.github/CODEOWNERS +0 -15
  27. package/.github/dependabot.yml +0 -23
  28. package/.github/workflows/ci.yml +0 -38
  29. package/.github/workflows/publish.yml +0 -42
  30. package/.github/workflows/security.yml +0 -29
  31. package/CHANGELOG.md +0 -34
  32. package/SECURITY.md +0 -40
  33. package/dist/chunk-U3PCVK6O.js.map +0 -1
  34. package/docs/github-packages-setup.md +0 -97
  35. package/docs/stepflow-api-reference.md +0 -1663
  36. package/src/core/engine/concurrency.ts +0 -229
  37. package/src/core/engine/lifecycle.ts +0 -176
  38. package/src/core/engine.test.ts +0 -1435
  39. package/src/core/engine.ts +0 -598
  40. package/src/core/index.ts +0 -7
  41. package/src/core/orchestrator/persistence.ts +0 -165
  42. package/src/core/orchestrator/plan-resolution.ts +0 -140
  43. package/src/core/orchestrator/state-transitions.ts +0 -109
  44. package/src/core/orchestrator/step-runner.ts +0 -427
  45. package/src/core/orchestrator.ts +0 -252
  46. package/src/core/types.ts +0 -220
  47. package/src/events/index.ts +0 -8
  48. package/src/events/memory.test.ts +0 -107
  49. package/src/events/memory.ts +0 -92
  50. package/src/events/socketio.test.ts +0 -378
  51. package/src/events/socketio.ts +0 -262
  52. package/src/events/types.ts +0 -118
  53. package/src/events/webhook.test.ts +0 -949
  54. package/src/events/webhook.ts +0 -807
  55. package/src/index.ts +0 -270
  56. package/src/planning/evaluate-condition.test.ts +0 -153
  57. package/src/planning/evaluate-condition.ts +0 -105
  58. package/src/planning/index.ts +0 -55
  59. package/src/planning/planner.ts +0 -494
  60. package/src/planning/planning.test.ts +0 -727
  61. package/src/planning/registry.test.ts +0 -398
  62. package/src/planning/registry.ts +0 -283
  63. package/src/planning/types.ts +0 -566
  64. package/src/scheduler/cron.test.ts +0 -479
  65. package/src/scheduler/cron.ts +0 -438
  66. package/src/scheduler/index.ts +0 -8
  67. package/src/scheduler/postgres-persistence.ts +0 -530
  68. package/src/scheduler/sqlite-persistence.test.ts +0 -235
  69. package/src/scheduler/sqlite-persistence.ts +0 -286
  70. package/src/scheduler/types.ts +0 -73
  71. package/src/storage/index.ts +0 -27
  72. package/src/storage/memory.test.ts +0 -349
  73. package/src/storage/memory.ts +0 -227
  74. package/src/storage/postgres-core.ts +0 -550
  75. package/src/storage/postgres-migration.test.ts +0 -69
  76. package/src/storage/postgres-transaction-pagination.test.ts +0 -107
  77. package/src/storage/postgres.ts +0 -835
  78. package/src/storage/sqlite-core.ts +0 -151
  79. package/src/storage/sqlite.test.ts +0 -642
  80. package/src/storage/sqlite.ts +0 -717
  81. package/src/storage/types.ts +0 -343
  82. package/src/utils/errors.test.ts +0 -150
  83. package/src/utils/errors.ts +0 -161
  84. package/src/utils/id.ts +0 -21
  85. package/src/utils/index.ts +0 -10
  86. package/src/utils/logger.test.ts +0 -121
  87. package/src/utils/logger.ts +0 -96
  88. package/src/utils/pinned-fetch.test.ts +0 -84
  89. package/src/utils/pinned-fetch.ts +0 -118
  90. package/src/utils/postgres-deps.ts +0 -79
  91. package/src/utils/retry.test.ts +0 -177
  92. package/src/utils/retry.ts +0 -121
  93. package/src/utils/safe-json.test.ts +0 -166
  94. package/src/utils/safe-json.ts +0 -107
  95. package/src/utils/webhook-signature.test.ts +0 -111
  96. package/src/utils/webhook-signature.ts +0 -74
  97. package/tsconfig.json +0 -21
  98. package/tsup.config.ts +0 -14
  99. package/vitest.config.ts +0 -9
package/src/core/types.ts DELETED
@@ -1,220 +0,0 @@
1
- /**
2
- * Core types for the workflow engine.
3
- * These are the foundational interfaces used throughout the system.
4
- */
5
-
6
- // ============================================================================
7
- // Basic Types
8
- // ============================================================================
9
-
10
- /**
11
- * Unique identifier for a workflow type.
12
- * Used to register and look up workflow definitions.
13
- */
14
- export type WorkflowKind = string;
15
-
16
- /**
17
- * Status of a workflow run.
18
- */
19
- export type RunStatus = 'queued' | 'running' | 'succeeded' | 'failed' | 'canceled';
20
-
21
- /**
22
- * Status of a workflow step.
23
- */
24
- export type StepStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'skipped' | 'canceled';
25
-
26
- /**
27
- * Error handling strategy for a step.
28
- * - 'fail': Stop the workflow immediately
29
- * - 'retry': Retry the step up to maxRetries times
30
- * - 'skip': Mark as skipped and continue to next step
31
- */
32
- export type StepErrorStrategy = 'fail' | 'retry' | 'skip';
33
-
34
- // ============================================================================
35
- // Error Types
36
- // ============================================================================
37
-
38
- /**
39
- * Structured error information stored with runs and steps.
40
- */
41
- export interface WorkflowError {
42
- code: string;
43
- message: string;
44
- stack?: string;
45
- details?: Record<string, unknown>;
46
- }
47
-
48
- /**
49
- * Result of a completed workflow run.
50
- */
51
- export interface RunResult {
52
- status: 'succeeded' | 'failed' | 'canceled';
53
- results: Record<string, unknown>;
54
- error?: WorkflowError;
55
- duration: number;
56
- }
57
-
58
- // ============================================================================
59
- // Logger Interface
60
- // ============================================================================
61
-
62
- /**
63
- * Minimal logger interface that consumers can implement.
64
- * Compatible with console, pino, winston, etc.
65
- */
66
- export interface Logger {
67
- debug(message: string, ...args: unknown[]): void;
68
- info(message: string, ...args: unknown[]): void;
69
- warn(message: string, ...args: unknown[]): void;
70
- error(message: string, ...args: unknown[]): void;
71
- }
72
-
73
- // ============================================================================
74
- // Spawn Child Options
75
- // ============================================================================
76
-
77
- /**
78
- * Options for spawning a child workflow from within a step handler.
79
- */
80
- export interface SpawnChildOptions {
81
- kind: WorkflowKind;
82
- input?: Record<string, unknown>;
83
- metadata?: Record<string, unknown>;
84
- }
85
-
86
- // ============================================================================
87
- // Workflow Context
88
- // ============================================================================
89
-
90
- /**
91
- * Runtime context passed to each step handler.
92
- * Contains all information a step needs to execute and interact with the engine.
93
- */
94
- export interface WorkflowContext<TInput = Record<string, unknown>> {
95
- /** Unique run identifier */
96
- runId: string;
97
-
98
- /** Current step identifier (for granular tracking, e.g., token usage) */
99
- stepId: string;
100
-
101
- /** Workflow type */
102
- kind: WorkflowKind;
103
-
104
- /** Input parameters passed when starting the run */
105
- input: TInput;
106
-
107
- /** Accumulated results from previous steps (keyed by step key) */
108
- results: Record<string, unknown>;
109
-
110
- /** Optional metadata (topicId, userId, etc.) */
111
- metadata: Record<string, unknown>;
112
-
113
- /** Current step key (set during execution) */
114
- currentStep?: string;
115
-
116
- /** Logger instance scoped to this run */
117
- logger: Logger;
118
-
119
- /** Abort signal for cancellation */
120
- signal: AbortSignal;
121
-
122
- /** Helper to spawn child workflows */
123
- spawnChild: (options: SpawnChildOptions) => Promise<string>;
124
-
125
- /** Helper to emit custom events */
126
- emit: (eventType: string, payload?: unknown) => void;
127
- }
128
-
129
- // ============================================================================
130
- // Workflow Step
131
- // ============================================================================
132
-
133
- /**
134
- * Definition of a single workflow step.
135
- * Steps are executed sequentially within a workflow.
136
- */
137
- export interface WorkflowStep<TInput = Record<string, unknown>> {
138
- /** Unique step identifier within the workflow */
139
- key: string;
140
-
141
- /** Human-readable step name */
142
- name: string;
143
-
144
- /** Async function that performs the step's work */
145
- handler: (ctx: WorkflowContext<TInput>) => Promise<unknown>;
146
-
147
- /** What to do when the step fails (default: 'fail') */
148
- onError?: StepErrorStrategy;
149
-
150
- /** Maximum retry attempts when onError is 'retry' @default 3 */
151
- maxRetries?: number;
152
-
153
- /** Delay between retries in ms @default 1000 */
154
- retryDelay?: number;
155
-
156
- /** Exponential backoff multiplier @default 2 */
157
- retryBackoff?: number;
158
-
159
- /** Timeout for this step in ms (optional) */
160
- timeout?: number;
161
-
162
- /** Condition to skip this step */
163
- skipIf?: (ctx: WorkflowContext<TInput>) => boolean | Promise<boolean>;
164
- }
165
-
166
- // ============================================================================
167
- // Workflow Hooks
168
- // ============================================================================
169
-
170
- /**
171
- * Lifecycle hooks for workflows.
172
- * Allow custom logic at key points in the workflow execution.
173
- */
174
- export interface WorkflowHooks<TInput = Record<string, unknown>> {
175
- /** Called before workflow starts */
176
- beforeRun?: (ctx: WorkflowContext<TInput>) => Promise<void>;
177
-
178
- /** Called after workflow completes (success or failure) */
179
- afterRun?: (ctx: WorkflowContext<TInput>, result: RunResult) => Promise<void>;
180
-
181
- /** Called before each step */
182
- beforeStep?: (ctx: WorkflowContext<TInput>, step: WorkflowStep<TInput>) => Promise<void>;
183
-
184
- /** Called after each step (success only) */
185
- afterStep?: (ctx: WorkflowContext<TInput>, step: WorkflowStep<TInput>, result: unknown) => Promise<void>;
186
-
187
- /** Called when a step fails */
188
- onStepError?: (ctx: WorkflowContext<TInput>, step: WorkflowStep<TInput>, error: Error) => Promise<void>;
189
- }
190
-
191
- // ============================================================================
192
- // Workflow Definition
193
- // ============================================================================
194
-
195
- /**
196
- * Complete workflow definition.
197
- * Registered with the engine to enable starting runs of this type.
198
- */
199
- export interface WorkflowDefinition<TInput = Record<string, unknown>> {
200
- /** Unique workflow type identifier */
201
- kind: WorkflowKind;
202
-
203
- /** Human-readable workflow name */
204
- name: string;
205
-
206
- /** Optional description */
207
- description?: string;
208
-
209
- /** Ordered list of steps to execute */
210
- steps: WorkflowStep<TInput>[];
211
-
212
- /** Default error strategy for all steps (default: 'fail') */
213
- defaultOnError?: StepErrorStrategy;
214
-
215
- /** Global timeout for the entire workflow in ms */
216
- timeout?: number;
217
-
218
- /** Hooks for workflow lifecycle */
219
- hooks?: WorkflowHooks<TInput>;
220
- }
@@ -1,8 +0,0 @@
1
- /**
2
- * Events module exports.
3
- */
4
-
5
- export * from './types';
6
- export * from './memory';
7
- export * from './socketio';
8
- export * from './webhook';
@@ -1,107 +0,0 @@
1
- import { describe, it, expect, beforeEach, vi } from 'vitest';
2
- import { MemoryEventTransport } from './memory';
3
- import type { WorkflowEvent, WorkflowEventType } from './types';
4
-
5
- function createTestEvent(overrides: Partial<WorkflowEvent> = {}): WorkflowEvent {
6
- return {
7
- eventType: 'run.started',
8
- runId: 'run-123',
9
- kind: 'test.workflow',
10
- timestamp: new Date('2024-01-01T12:00:00Z'),
11
- ...overrides,
12
- };
13
- }
14
-
15
- describe('MemoryEventTransport', () => {
16
- let transport: MemoryEventTransport;
17
-
18
- beforeEach(() => {
19
- transport = new MemoryEventTransport();
20
- });
21
-
22
- describe('subscribeToType', () => {
23
- it('should call callback when event of matching type is emitted', () => {
24
- const callback = vi.fn();
25
- transport.subscribeToType('run.completed', callback);
26
-
27
- const event = createTestEvent({ eventType: 'run.completed' });
28
- transport.emit(event);
29
-
30
- expect(callback).toHaveBeenCalledWith(event);
31
- });
32
-
33
- it('should not call callback for events of a different type', () => {
34
- const callback = vi.fn();
35
- transport.subscribeToType('run.completed', callback);
36
-
37
- transport.emit(createTestEvent({ eventType: 'run.started' }));
38
-
39
- expect(callback).not.toHaveBeenCalled();
40
- });
41
-
42
- it('should unsubscribe when calling the returned function', () => {
43
- const callback = vi.fn();
44
- const unsubscribe = transport.subscribeToType('run.completed', callback);
45
-
46
- // Emit once before unsubscribe
47
- transport.emit(createTestEvent({ eventType: 'run.completed' }));
48
- expect(callback).toHaveBeenCalledTimes(1);
49
-
50
- unsubscribe();
51
-
52
- // Emit again after unsubscribe
53
- transport.emit(createTestEvent({ eventType: 'run.completed' }));
54
- expect(callback).toHaveBeenCalledTimes(1);
55
- });
56
-
57
- it('should support multiple type subscriptions independently', () => {
58
- const completedCb = vi.fn();
59
- const failedCb = vi.fn();
60
- transport.subscribeToType('run.completed', completedCb);
61
- transport.subscribeToType('run.failed', failedCb);
62
-
63
- transport.emit(createTestEvent({ eventType: 'run.completed' }));
64
-
65
- expect(completedCb).toHaveBeenCalledTimes(1);
66
- expect(failedCb).not.toHaveBeenCalled();
67
- });
68
- });
69
-
70
- describe('getListenerCount', () => {
71
- it('should return 0 when no listeners are registered', () => {
72
- expect(transport.getListenerCount()).toBe(0);
73
- });
74
-
75
- it('should return global listener count when called without channel', () => {
76
- transport.subscribeAll(vi.fn());
77
- transport.subscribeAll(vi.fn());
78
-
79
- expect(transport.getListenerCount()).toBe(2);
80
- });
81
-
82
- it('should return channel-specific listener count when called with channel', () => {
83
- transport.subscribe('run-1', vi.fn());
84
- transport.subscribe('run-1', vi.fn());
85
- transport.subscribe('run-2', vi.fn());
86
-
87
- expect(transport.getListenerCount('run:run-1')).toBe(2);
88
- expect(transport.getListenerCount('run:run-2')).toBe(1);
89
- });
90
-
91
- it('should update count after subscribe and unsubscribe', () => {
92
- const unsub = transport.subscribeAll(vi.fn());
93
- expect(transport.getListenerCount()).toBe(1);
94
-
95
- unsub();
96
- expect(transport.getListenerCount()).toBe(0);
97
- });
98
-
99
- it('should return count for type-based channels', () => {
100
- transport.subscribeToType('step.completed', vi.fn());
101
- transport.subscribeToType('step.completed', vi.fn());
102
-
103
- expect(transport.getListenerCount('type:step.completed')).toBe(2);
104
- expect(transport.getListenerCount('type:step.failed')).toBe(0);
105
- });
106
- });
107
- });
@@ -1,92 +0,0 @@
1
- /**
2
- * In-memory event transport using Node.js EventEmitter.
3
- * Default transport for development and single-process deployments.
4
- *
5
- * NOTE: This adapter is intended for development and testing only. It stores
6
- * all state in-process with no persistence or multi-process safety guarantees.
7
- */
8
-
9
- import { EventEmitter } from 'events';
10
- import type {
11
- EventTransport,
12
- WorkflowEvent,
13
- WorkflowEventType,
14
- EventCallback,
15
- Unsubscribe,
16
- } from './types';
17
-
18
- /**
19
- * In-memory event transport implementation using EventEmitter.
20
- * Events are emitted to subscribers in the same process.
21
- */
22
- export class MemoryEventTransport implements EventTransport {
23
- private emitter = new EventEmitter();
24
-
25
- constructor() {
26
- // Increase max listeners to avoid warnings in workflows with many steps
27
- this.emitter.setMaxListeners(100);
28
- }
29
-
30
- /**
31
- * Emit an event to all subscribers.
32
- */
33
- emit(event: WorkflowEvent): void {
34
- // Emit to global subscribers
35
- this.emitter.emit('event', event);
36
-
37
- // Emit to run-specific subscribers
38
- this.emitter.emit(`run:${event.runId}`, event);
39
-
40
- // Emit to event-type subscribers
41
- this.emitter.emit(`type:${event.eventType}`, event);
42
- }
43
-
44
- /**
45
- * Subscribe to events for a specific run.
46
- */
47
- subscribe(runId: string, callback: EventCallback): Unsubscribe {
48
- const channel = `run:${runId}`;
49
- this.emitter.on(channel, callback);
50
- return () => {
51
- this.emitter.off(channel, callback);
52
- };
53
- }
54
-
55
- /**
56
- * Subscribe to all events.
57
- */
58
- subscribeAll(callback: EventCallback): Unsubscribe {
59
- this.emitter.on('event', callback);
60
- return () => {
61
- this.emitter.off('event', callback);
62
- };
63
- }
64
-
65
- /**
66
- * Subscribe to events of a specific type.
67
- */
68
- subscribeToType(eventType: WorkflowEventType, callback: EventCallback): Unsubscribe {
69
- const channel = `type:${eventType}`;
70
- this.emitter.on(channel, callback);
71
- return () => {
72
- this.emitter.off(channel, callback);
73
- };
74
- }
75
-
76
- /**
77
- * Close the transport and remove all listeners.
78
- */
79
- close(): void {
80
- this.emitter.removeAllListeners();
81
- }
82
-
83
- /**
84
- * Get the number of listeners for a channel (for testing).
85
- */
86
- getListenerCount(channel?: string): number {
87
- if (channel) {
88
- return this.emitter.listenerCount(channel);
89
- }
90
- return this.emitter.listenerCount('event');
91
- }
92
- }