@multiplier-labs/stepflow 0.3.1 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.codekin/reports/code-review/2026-04-11_code-review-daily.md +146 -0
- package/.codekin/reports/code-review/2026-04-13_code-review-daily.md +74 -0
- package/.codekin/reports/comments/2026-04-04_comment-assessment.md +179 -0
- package/.codekin/reports/comments/2026-04-11_comment-assessment.md +161 -0
- package/.codekin/reports/comments/2026-04-14_comment-assessment.md +34 -0
- package/.codekin/reports/complexity/2026-04-03_complexity-report.md +152 -0
- package/.codekin/reports/complexity/2026-04-11_complexity-report.md +152 -0
- package/.codekin/reports/complexity/2026-04-14_complexity-report.md +34 -0
- package/.codekin/reports/dependencies/2026-04-04_dependency-health.md +94 -0
- package/.codekin/reports/dependencies/2026-04-11_dependency-health.md +93 -0
- package/.codekin/reports/docs-audit/2026-04-04_docs-audit.md +10 -0
- package/.codekin/reports/docs-audit/2026-04-11_docs-audit.md +138 -0
- package/.codekin/reports/docs-audit/2026-04-13_docs-audit.md +121 -0
- package/.codekin/reports/security/2026-04-03_security-audit.md +208 -0
- package/.codekin/reports/security/2026-04-11_security-audit.md +297 -0
- package/.github/CODEOWNERS +15 -0
- package/.github/dependabot.yml +23 -0
- package/.github/workflows/ci.yml +38 -0
- package/.github/workflows/publish.yml +17 -5
- package/.github/workflows/security.yml +29 -0
- package/CHANGELOG.md +34 -0
- package/README.md +24 -0
- package/SECURITY.md +40 -0
- package/dist/{chunk-FQCT3I2A.js → chunk-5XJBAPXF.js} +527 -551
- package/dist/chunk-5XJBAPXF.js.map +1 -0
- package/dist/{chunk-U5QGN3RT.js → chunk-FMPJBK2N.js} +67 -55
- package/dist/chunk-FMPJBK2N.js.map +1 -0
- package/dist/{chunk-GXY66V7Q.js → chunk-JPXPB7U5.js} +52 -2
- package/dist/chunk-JPXPB7U5.js.map +1 -0
- package/dist/{chunk-XCF4PLN7.js → chunk-U3PCVK6O.js} +276 -61
- package/dist/chunk-U3PCVK6O.js.map +1 -0
- package/dist/events/index.d.ts +60 -7
- package/dist/events/index.js +1 -1
- package/dist/{index-CPfGsmrp.d.ts → index-Cd0IZ40L.d.ts} +56 -17
- package/dist/index.d.ts +15 -23
- package/dist/index.js +784 -547
- package/dist/index.js.map +1 -1
- package/dist/scheduler/index.d.ts +4 -4
- package/dist/scheduler/index.js +2 -2
- package/dist/storage/index.d.ts +322 -56
- package/dist/storage/index.js +4 -2
- package/dist/{types-BlwFEGzj.d.ts → types-DSEjiLMj.d.ts} +16 -15
- package/dist/{types-DzkEqnQJ.d.ts → types-DZUdWmCc.d.ts} +2 -2
- package/dist/{types-BVShq7zT.d.ts → types-K5Gjk3H_.d.ts} +4 -4
- package/docs/stepflow-api-reference.md +5 -4
- package/package.json +12 -8
- package/src/core/engine/concurrency.ts +229 -0
- package/src/core/engine/lifecycle.ts +176 -0
- package/src/core/engine.test.ts +536 -522
- package/src/core/engine.ts +116 -235
- package/src/core/index.ts +3 -3
- package/src/core/orchestrator/persistence.ts +165 -0
- package/src/core/orchestrator/plan-resolution.ts +140 -0
- package/src/core/orchestrator/state-transitions.ts +109 -0
- package/src/core/orchestrator/step-runner.ts +427 -0
- package/src/core/orchestrator.ts +57 -395
- package/src/core/types.ts +7 -29
- package/src/events/index.ts +4 -4
- package/src/events/memory.test.ts +39 -41
- package/src/events/memory.ts +7 -10
- package/src/events/socketio.test.ts +112 -162
- package/src/events/socketio.ts +20 -27
- package/src/events/types.ts +16 -19
- package/src/events/webhook.test.ts +489 -235
- package/src/events/webhook.ts +355 -139
- package/src/index.ts +19 -19
- package/src/planning/evaluate-condition.test.ts +153 -0
- package/src/planning/evaluate-condition.ts +105 -0
- package/src/planning/index.ts +6 -3
- package/src/planning/planner.ts +45 -152
- package/src/planning/planning.test.ts +303 -366
- package/src/planning/registry.test.ts +204 -251
- package/src/planning/registry.ts +20 -106
- package/src/planning/types.ts +23 -27
- package/src/scheduler/cron.test.ts +149 -150
- package/src/scheduler/cron.ts +58 -69
- package/src/scheduler/index.ts +4 -14
- package/src/scheduler/postgres-persistence.ts +89 -105
- package/src/scheduler/sqlite-persistence.test.ts +96 -96
- package/src/scheduler/sqlite-persistence.ts +40 -22
- package/src/scheduler/types.ts +4 -9
- package/src/storage/index.ts +5 -5
- package/src/storage/memory.test.ts +133 -183
- package/src/storage/memory.ts +21 -42
- package/src/storage/postgres-core.ts +550 -0
- package/src/storage/postgres-migration.test.ts +69 -0
- package/src/storage/postgres-transaction-pagination.test.ts +107 -0
- package/src/storage/postgres.ts +222 -937
- package/src/storage/sqlite-core.ts +151 -0
- package/src/storage/sqlite.test.ts +330 -281
- package/src/storage/sqlite.ts +225 -170
- package/src/storage/types.ts +33 -58
- package/src/utils/errors.test.ts +78 -80
- package/src/utils/errors.ts +27 -57
- package/src/utils/id.ts +3 -3
- package/src/utils/index.ts +6 -4
- package/src/utils/logger.test.ts +52 -58
- package/src/utils/logger.ts +4 -4
- package/src/utils/pinned-fetch.test.ts +84 -0
- package/src/utils/pinned-fetch.ts +118 -0
- package/src/utils/postgres-deps.ts +20 -4
- package/src/utils/retry.test.ts +47 -67
- package/src/utils/retry.ts +9 -9
- package/src/utils/safe-json.test.ts +166 -0
- package/src/utils/safe-json.ts +107 -0
- package/src/utils/webhook-signature.test.ts +111 -0
- package/src/utils/webhook-signature.ts +74 -0
- package/dist/chunk-FQCT3I2A.js.map +0 -1
- package/dist/chunk-GXY66V7Q.js.map +0 -1
- package/dist/chunk-U5QGN3RT.js.map +0 -1
- package/dist/chunk-XCF4PLN7.js.map +0 -1
- package/src/scheduler/postgres-persistence.test.ts +0 -906
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared core for the SQLite storage adapter.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the structure introduced for Postgres in `postgres-core.ts` (PR #50)
|
|
5
|
+
* so all storage adapters expose row mappers and types in the same shape.
|
|
6
|
+
*
|
|
7
|
+
* The SQLite case is simpler than Postgres: there is only one adapter class
|
|
8
|
+
* (`SQLiteStorageAdapter`), with no transaction-scoped twin. So this module
|
|
9
|
+
* carries only the *pure* portion of the postgres-core split:
|
|
10
|
+
*
|
|
11
|
+
* - SQLite row type interfaces for the three core tables
|
|
12
|
+
* (`workflow_runs`, `workflow_run_steps`, `workflow_events`).
|
|
13
|
+
* - Pure row mappers (`mapRunRow`, `mapStepRow`, `mapEventRow`) that take
|
|
14
|
+
* a `MapperContext = { component, logger }` and route every JSON-column
|
|
15
|
+
* parse through the shared `safeParseField` / `safeParseOptionalField`
|
|
16
|
+
* helpers. Corruption is reported via the configured logger with safe
|
|
17
|
+
* metadata only — the raw value is never logged (audit M2 / L3, PR #52).
|
|
18
|
+
*
|
|
19
|
+
* No abstract base class is needed: the adapter class binds the prepared
|
|
20
|
+
* statements + better-sqlite3 connection in one place and would gain nothing
|
|
21
|
+
* from inheritance. The mappers and row types are extracted purely so they
|
|
22
|
+
* are reusable, testable, and consistent with `postgres-core.ts`.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import {
|
|
26
|
+
safeParseField as sharedSafeParseField,
|
|
27
|
+
safeParseOptionalField as sharedSafeParseOptionalField,
|
|
28
|
+
type MapperContext,
|
|
29
|
+
type SafeJsonParseContext,
|
|
30
|
+
} from '../utils/safe-json';
|
|
31
|
+
import type {
|
|
32
|
+
WorkflowRunRecord,
|
|
33
|
+
WorkflowRunStepRecord,
|
|
34
|
+
WorkflowEventRecord,
|
|
35
|
+
} from './types';
|
|
36
|
+
import type { RunStatus, StepStatus, WorkflowError } from '../core/types';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Re-export the shared `MapperContext` so callers can `import { MapperContext }`
|
|
40
|
+
* from either storage core module.
|
|
41
|
+
*/
|
|
42
|
+
export type { MapperContext };
|
|
43
|
+
|
|
44
|
+
// ============================================================================
|
|
45
|
+
// SQLite row types
|
|
46
|
+
// ============================================================================
|
|
47
|
+
//
|
|
48
|
+
// SQLite stores everything as text/integer/real, so timestamps come back as
|
|
49
|
+
// ISO-8601 strings (the adapter writes them via `Date.prototype.toISOString`)
|
|
50
|
+
// and JSON columns come back as the original `JSON.stringify` output. The
|
|
51
|
+
// mappers below convert each row back to the public record shape.
|
|
52
|
+
|
|
53
|
+
/** Row shape for the `workflow_runs` table. */
|
|
54
|
+
export interface SQLiteRunRow {
|
|
55
|
+
id: string;
|
|
56
|
+
kind: string;
|
|
57
|
+
status: string;
|
|
58
|
+
parent_run_id: string | null;
|
|
59
|
+
input_json: string;
|
|
60
|
+
metadata_json: string;
|
|
61
|
+
context_json: string;
|
|
62
|
+
completed_steps_json: string | null;
|
|
63
|
+
error_json: string | null;
|
|
64
|
+
created_at: string;
|
|
65
|
+
started_at: string | null;
|
|
66
|
+
finished_at: string | null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Row shape for the `workflow_run_steps` table. */
|
|
70
|
+
export interface SQLiteStepRow {
|
|
71
|
+
id: string;
|
|
72
|
+
run_id: string;
|
|
73
|
+
step_key: string;
|
|
74
|
+
step_name: string;
|
|
75
|
+
status: string;
|
|
76
|
+
attempt: number;
|
|
77
|
+
result_json: string | null;
|
|
78
|
+
error_json: string | null;
|
|
79
|
+
started_at: string | null;
|
|
80
|
+
finished_at: string | null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Row shape for the `workflow_events` table. */
|
|
84
|
+
export interface SQLiteEventRow {
|
|
85
|
+
id: string;
|
|
86
|
+
run_id: string;
|
|
87
|
+
step_key: string | null;
|
|
88
|
+
event_type: string;
|
|
89
|
+
level: string;
|
|
90
|
+
payload_json: string | null;
|
|
91
|
+
timestamp: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ============================================================================
|
|
95
|
+
// Row mappers (pure)
|
|
96
|
+
// ============================================================================
|
|
97
|
+
//
|
|
98
|
+
// Adapters supply a `MapperContext` ({ component, logger }); each helper
|
|
99
|
+
// extends it with the row id and column being parsed so a structured log
|
|
100
|
+
// emitted on corruption identifies the bad row. The raw value is never
|
|
101
|
+
// logged — see `src/utils/safe-json.ts`.
|
|
102
|
+
|
|
103
|
+
/** Map a `workflow_runs` row to the public `WorkflowRunRecord` shape. */
|
|
104
|
+
export function mapRunRow(row: SQLiteRunRow, ctx: MapperContext): WorkflowRunRecord {
|
|
105
|
+
const fieldCtx = (column: string): SafeJsonParseContext => ({ ...ctx, rowId: row.id, column });
|
|
106
|
+
return {
|
|
107
|
+
id: row.id,
|
|
108
|
+
kind: row.kind,
|
|
109
|
+
status: row.status as RunStatus,
|
|
110
|
+
parentRunId: row.parent_run_id ?? undefined,
|
|
111
|
+
input: sharedSafeParseField(row.input_json, {}, fieldCtx('input_json')) as Record<string, unknown>,
|
|
112
|
+
metadata: sharedSafeParseField(row.metadata_json, {}, fieldCtx('metadata_json')) as Record<string, unknown>,
|
|
113
|
+
context: sharedSafeParseField(row.context_json, {}, fieldCtx('context_json')) as Record<string, unknown>,
|
|
114
|
+
completedSteps: sharedSafeParseOptionalField(row.completed_steps_json, fieldCtx('completed_steps_json')) as string[] | undefined,
|
|
115
|
+
error: sharedSafeParseOptionalField(row.error_json, fieldCtx('error_json')) as WorkflowError | undefined,
|
|
116
|
+
createdAt: new Date(row.created_at),
|
|
117
|
+
startedAt: row.started_at ? new Date(row.started_at) : undefined,
|
|
118
|
+
finishedAt: row.finished_at ? new Date(row.finished_at) : undefined,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Map a `workflow_run_steps` row to the public `WorkflowRunStepRecord` shape. */
|
|
123
|
+
export function mapStepRow(row: SQLiteStepRow, ctx: MapperContext): WorkflowRunStepRecord {
|
|
124
|
+
const fieldCtx = (column: string): SafeJsonParseContext => ({ ...ctx, rowId: row.id, column });
|
|
125
|
+
return {
|
|
126
|
+
id: row.id,
|
|
127
|
+
runId: row.run_id,
|
|
128
|
+
stepKey: row.step_key,
|
|
129
|
+
stepName: row.step_name,
|
|
130
|
+
status: row.status as StepStatus,
|
|
131
|
+
attempt: row.attempt,
|
|
132
|
+
result: sharedSafeParseOptionalField(row.result_json, fieldCtx('result_json')),
|
|
133
|
+
error: sharedSafeParseOptionalField(row.error_json, fieldCtx('error_json')) as WorkflowError | undefined,
|
|
134
|
+
startedAt: row.started_at ? new Date(row.started_at) : undefined,
|
|
135
|
+
finishedAt: row.finished_at ? new Date(row.finished_at) : undefined,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Map a `workflow_events` row to the public `WorkflowEventRecord` shape. */
|
|
140
|
+
export function mapEventRow(row: SQLiteEventRow, ctx: MapperContext): WorkflowEventRecord {
|
|
141
|
+
const fieldCtx: SafeJsonParseContext = { ...ctx, rowId: row.id, column: 'payload_json' };
|
|
142
|
+
return {
|
|
143
|
+
id: row.id,
|
|
144
|
+
runId: row.run_id,
|
|
145
|
+
stepKey: row.step_key ?? undefined,
|
|
146
|
+
eventType: row.event_type,
|
|
147
|
+
level: row.level as 'info' | 'warn' | 'error',
|
|
148
|
+
payload: sharedSafeParseOptionalField(row.payload_json, fieldCtx),
|
|
149
|
+
timestamp: new Date(row.timestamp),
|
|
150
|
+
};
|
|
151
|
+
}
|