@multiplier-labs/stepflow 0.3.1 → 0.3.3
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/comments/2026-04-04_comment-assessment.md +179 -0
- package/.codekin/reports/complexity/2026-04-03_complexity-report.md +152 -0
- package/.codekin/reports/dependencies/2026-04-04_dependency-health.md +94 -0
- package/.codekin/reports/docs-audit/2026-04-04_docs-audit.md +10 -0
- package/.codekin/reports/security/2026-04-03_security-audit.md +208 -0
- package/.github/CODEOWNERS +15 -0
- package/.github/dependabot.yml +23 -0
- package/.github/workflows/ci.yml +38 -0
- package/.github/workflows/publish.yml +11 -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-4VOKMGP6.js} +23 -42
- package/dist/chunk-4VOKMGP6.js.map +1 -0
- package/dist/{chunk-XCF4PLN7.js → chunk-GYPNJBDP.js} +12 -16
- package/dist/chunk-GYPNJBDP.js.map +1 -0
- package/dist/{chunk-U5QGN3RT.js → chunk-KHTUWLVZ.js} +14 -47
- package/dist/chunk-KHTUWLVZ.js.map +1 -0
- package/dist/{chunk-GXY66V7Q.js → chunk-ML35PIHX.js} +1 -1
- package/dist/chunk-ML35PIHX.js.map +1 -0
- package/dist/events/index.d.ts +4 -4
- package/dist/events/index.js +1 -1
- package/dist/{index-CPfGsmrp.d.ts → index-Dzr437iW.d.ts} +6 -6
- package/dist/index.d.ts +14 -12
- package/dist/index.js +40 -82
- 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 +13 -13
- package/dist/storage/index.js +2 -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 +2 -3
- package/package.json +7 -6
- package/src/core/engine.test.ts +466 -522
- package/src/core/engine.ts +42 -67
- package/src/core/index.ts +3 -3
- package/src/core/orchestrator.ts +64 -83
- 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 +197 -235
- package/src/events/webhook.ts +44 -71
- package/src/index.ts +19 -19
- package/src/planning/index.ts +6 -3
- package/src/planning/planner.ts +66 -91
- package/src/planning/planning.test.ts +303 -366
- package/src/planning/registry.test.ts +204 -251
- package/src/planning/registry.ts +39 -43
- package/src/planning/types.ts +23 -27
- package/src/scheduler/cron.test.ts +141 -150
- package/src/scheduler/cron.ts +32 -67
- package/src/scheduler/index.ts +4 -14
- package/src/scheduler/postgres-persistence.ts +71 -99
- package/src/scheduler/sqlite-persistence.test.ts +96 -96
- package/src/scheduler/sqlite-persistence.ts +12 -19
- 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.ts +197 -393
- package/src/storage/sqlite.test.ts +154 -281
- package/src/storage/sqlite.ts +50 -85
- 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 +4 -4
- package/src/utils/logger.test.ts +52 -58
- package/src/utils/logger.ts +4 -4
- package/src/utils/postgres-deps.ts +4 -4
- package/src/utils/retry.test.ts +47 -67
- package/src/utils/retry.ts +9 -9
- 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
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from
|
|
2
|
-
import Database from
|
|
3
|
-
import { SQLiteSchedulePersistence } from
|
|
4
|
-
import type { WorkflowSchedule } from
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import Database from 'better-sqlite3';
|
|
3
|
+
import { SQLiteSchedulePersistence } from './sqlite-persistence';
|
|
4
|
+
import type { WorkflowSchedule } from './types';
|
|
5
5
|
|
|
6
|
-
describe(
|
|
6
|
+
describe('SQLiteSchedulePersistence', () => {
|
|
7
7
|
let db: Database.Database;
|
|
8
8
|
let persistence: SQLiteSchedulePersistence;
|
|
9
9
|
|
|
10
10
|
beforeEach(() => {
|
|
11
11
|
// Use in-memory database for testing
|
|
12
|
-
db = new Database(
|
|
12
|
+
db = new Database(':memory:');
|
|
13
13
|
persistence = new SQLiteSchedulePersistence({ db });
|
|
14
14
|
});
|
|
15
15
|
|
|
@@ -17,35 +17,35 @@ describe("SQLiteSchedulePersistence", () => {
|
|
|
17
17
|
db.close();
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
-
describe(
|
|
21
|
-
it(
|
|
20
|
+
describe('saveSchedule', () => {
|
|
21
|
+
it('should save a cron schedule', async () => {
|
|
22
22
|
const schedule: WorkflowSchedule = {
|
|
23
|
-
id:
|
|
24
|
-
workflowKind:
|
|
25
|
-
triggerType:
|
|
26
|
-
cronExpression:
|
|
27
|
-
timezone:
|
|
23
|
+
id: 'test-1',
|
|
24
|
+
workflowKind: 'test.workflow',
|
|
25
|
+
triggerType: 'cron',
|
|
26
|
+
cronExpression: '0 * * * *',
|
|
27
|
+
timezone: 'UTC',
|
|
28
28
|
enabled: true,
|
|
29
|
-
input: { foo:
|
|
30
|
-
metadata: { user:
|
|
29
|
+
input: { foo: 'bar' },
|
|
30
|
+
metadata: { user: 'test' },
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
await persistence.saveSchedule(schedule);
|
|
34
34
|
|
|
35
35
|
const loaded = await persistence.loadSchedules();
|
|
36
36
|
expect(loaded).toHaveLength(1);
|
|
37
|
-
expect(loaded[0].id).toBe(
|
|
38
|
-
expect(loaded[0].cronExpression).toBe(
|
|
39
|
-
expect(loaded[0].input).toEqual({ foo:
|
|
37
|
+
expect(loaded[0].id).toBe('test-1');
|
|
38
|
+
expect(loaded[0].cronExpression).toBe('0 * * * *');
|
|
39
|
+
expect(loaded[0].input).toEqual({ foo: 'bar' });
|
|
40
40
|
});
|
|
41
41
|
|
|
42
|
-
it(
|
|
42
|
+
it('should save a workflow completion trigger', async () => {
|
|
43
43
|
const schedule: WorkflowSchedule = {
|
|
44
|
-
id:
|
|
45
|
-
workflowKind:
|
|
46
|
-
triggerType:
|
|
47
|
-
triggerOnWorkflowKind:
|
|
48
|
-
triggerOnStatus: [
|
|
44
|
+
id: 'test-2',
|
|
45
|
+
workflowKind: 'notification.send',
|
|
46
|
+
triggerType: 'workflow_completed',
|
|
47
|
+
triggerOnWorkflowKind: 'order.process',
|
|
48
|
+
triggerOnStatus: ['succeeded', 'failed'],
|
|
49
49
|
enabled: true,
|
|
50
50
|
};
|
|
51
51
|
|
|
@@ -53,23 +53,23 @@ describe("SQLiteSchedulePersistence", () => {
|
|
|
53
53
|
|
|
54
54
|
const loaded = await persistence.loadSchedules();
|
|
55
55
|
expect(loaded).toHaveLength(1);
|
|
56
|
-
expect(loaded[0].triggerType).toBe(
|
|
57
|
-
expect(loaded[0].triggerOnWorkflowKind).toBe(
|
|
58
|
-
expect(loaded[0].triggerOnStatus).toEqual([
|
|
56
|
+
expect(loaded[0].triggerType).toBe('workflow_completed');
|
|
57
|
+
expect(loaded[0].triggerOnWorkflowKind).toBe('order.process');
|
|
58
|
+
expect(loaded[0].triggerOnStatus).toEqual(['succeeded', 'failed']);
|
|
59
59
|
});
|
|
60
60
|
|
|
61
|
-
it(
|
|
62
|
-
const lastRunAt = new Date(
|
|
63
|
-
const nextRunAt = new Date(
|
|
61
|
+
it('should save schedule with dates', async () => {
|
|
62
|
+
const lastRunAt = new Date('2024-01-01T12:00:00Z');
|
|
63
|
+
const nextRunAt = new Date('2024-01-01T13:00:00Z');
|
|
64
64
|
|
|
65
65
|
const schedule: WorkflowSchedule = {
|
|
66
|
-
id:
|
|
67
|
-
workflowKind:
|
|
68
|
-
triggerType:
|
|
69
|
-
cronExpression:
|
|
66
|
+
id: 'test-3',
|
|
67
|
+
workflowKind: 'test.workflow',
|
|
68
|
+
triggerType: 'cron',
|
|
69
|
+
cronExpression: '0 * * * *',
|
|
70
70
|
enabled: true,
|
|
71
71
|
lastRunAt,
|
|
72
|
-
lastRunId:
|
|
72
|
+
lastRunId: 'run-123',
|
|
73
73
|
nextRunAt,
|
|
74
74
|
};
|
|
75
75
|
|
|
@@ -77,30 +77,30 @@ describe("SQLiteSchedulePersistence", () => {
|
|
|
77
77
|
|
|
78
78
|
const loaded = await persistence.loadSchedules();
|
|
79
79
|
expect(loaded[0].lastRunAt).toEqual(lastRunAt);
|
|
80
|
-
expect(loaded[0].lastRunId).toBe(
|
|
80
|
+
expect(loaded[0].lastRunId).toBe('run-123');
|
|
81
81
|
expect(loaded[0].nextRunAt).toEqual(nextRunAt);
|
|
82
82
|
});
|
|
83
83
|
});
|
|
84
84
|
|
|
85
|
-
describe(
|
|
86
|
-
it(
|
|
85
|
+
describe('loadSchedules', () => {
|
|
86
|
+
it('should return empty array when no schedules', async () => {
|
|
87
87
|
const schedules = await persistence.loadSchedules();
|
|
88
88
|
expect(schedules).toHaveLength(0);
|
|
89
89
|
});
|
|
90
90
|
|
|
91
|
-
it(
|
|
91
|
+
it('should load multiple schedules', async () => {
|
|
92
92
|
await persistence.saveSchedule({
|
|
93
|
-
id:
|
|
94
|
-
workflowKind:
|
|
95
|
-
triggerType:
|
|
96
|
-
cronExpression:
|
|
93
|
+
id: 'schedule-1',
|
|
94
|
+
workflowKind: 'workflow.a',
|
|
95
|
+
triggerType: 'cron',
|
|
96
|
+
cronExpression: '0 * * * *',
|
|
97
97
|
enabled: true,
|
|
98
98
|
});
|
|
99
99
|
|
|
100
100
|
await persistence.saveSchedule({
|
|
101
|
-
id:
|
|
102
|
-
workflowKind:
|
|
103
|
-
triggerType:
|
|
101
|
+
id: 'schedule-2',
|
|
102
|
+
workflowKind: 'workflow.b',
|
|
103
|
+
triggerType: 'manual',
|
|
104
104
|
enabled: false,
|
|
105
105
|
});
|
|
106
106
|
|
|
@@ -109,102 +109,102 @@ describe("SQLiteSchedulePersistence", () => {
|
|
|
109
109
|
});
|
|
110
110
|
});
|
|
111
111
|
|
|
112
|
-
describe(
|
|
113
|
-
it(
|
|
112
|
+
describe('updateSchedule', () => {
|
|
113
|
+
it('should update enabled status', async () => {
|
|
114
114
|
await persistence.saveSchedule({
|
|
115
|
-
id:
|
|
116
|
-
workflowKind:
|
|
117
|
-
triggerType:
|
|
118
|
-
cronExpression:
|
|
115
|
+
id: 'update-1',
|
|
116
|
+
workflowKind: 'test.workflow',
|
|
117
|
+
triggerType: 'cron',
|
|
118
|
+
cronExpression: '0 * * * *',
|
|
119
119
|
enabled: true,
|
|
120
120
|
});
|
|
121
121
|
|
|
122
|
-
await persistence.updateSchedule(
|
|
122
|
+
await persistence.updateSchedule('update-1', { enabled: false });
|
|
123
123
|
|
|
124
124
|
const loaded = await persistence.loadSchedules();
|
|
125
125
|
expect(loaded[0].enabled).toBe(false);
|
|
126
126
|
});
|
|
127
127
|
|
|
128
|
-
it(
|
|
128
|
+
it('should update cron expression', async () => {
|
|
129
129
|
await persistence.saveSchedule({
|
|
130
|
-
id:
|
|
131
|
-
workflowKind:
|
|
132
|
-
triggerType:
|
|
133
|
-
cronExpression:
|
|
130
|
+
id: 'update-2',
|
|
131
|
+
workflowKind: 'test.workflow',
|
|
132
|
+
triggerType: 'cron',
|
|
133
|
+
cronExpression: '0 * * * *',
|
|
134
134
|
enabled: true,
|
|
135
135
|
});
|
|
136
136
|
|
|
137
|
-
await persistence.updateSchedule(
|
|
138
|
-
cronExpression:
|
|
137
|
+
await persistence.updateSchedule('update-2', {
|
|
138
|
+
cronExpression: '30 * * * *',
|
|
139
139
|
});
|
|
140
140
|
|
|
141
141
|
const loaded = await persistence.loadSchedules();
|
|
142
|
-
expect(loaded[0].cronExpression).toBe(
|
|
142
|
+
expect(loaded[0].cronExpression).toBe('30 * * * *');
|
|
143
143
|
});
|
|
144
144
|
|
|
145
|
-
it(
|
|
145
|
+
it('should update lastRunAt and lastRunId', async () => {
|
|
146
146
|
await persistence.saveSchedule({
|
|
147
|
-
id:
|
|
148
|
-
workflowKind:
|
|
149
|
-
triggerType:
|
|
150
|
-
cronExpression:
|
|
147
|
+
id: 'update-3',
|
|
148
|
+
workflowKind: 'test.workflow',
|
|
149
|
+
triggerType: 'cron',
|
|
150
|
+
cronExpression: '0 * * * *',
|
|
151
151
|
enabled: true,
|
|
152
152
|
});
|
|
153
153
|
|
|
154
154
|
const now = new Date();
|
|
155
|
-
await persistence.updateSchedule(
|
|
155
|
+
await persistence.updateSchedule('update-3', {
|
|
156
156
|
lastRunAt: now,
|
|
157
|
-
lastRunId:
|
|
157
|
+
lastRunId: 'run-456',
|
|
158
158
|
});
|
|
159
159
|
|
|
160
160
|
const loaded = await persistence.loadSchedules();
|
|
161
161
|
expect(loaded[0].lastRunAt).toEqual(now);
|
|
162
|
-
expect(loaded[0].lastRunId).toBe(
|
|
162
|
+
expect(loaded[0].lastRunId).toBe('run-456');
|
|
163
163
|
});
|
|
164
164
|
|
|
165
|
-
it(
|
|
165
|
+
it('should throw for non-existent schedule', async () => {
|
|
166
166
|
await expect(
|
|
167
|
-
persistence.updateSchedule(
|
|
168
|
-
).rejects.toThrow(
|
|
167
|
+
persistence.updateSchedule('nonexistent', { enabled: false })
|
|
168
|
+
).rejects.toThrow('Schedule not found');
|
|
169
169
|
});
|
|
170
170
|
});
|
|
171
171
|
|
|
172
|
-
describe(
|
|
173
|
-
it(
|
|
172
|
+
describe('deleteSchedule', () => {
|
|
173
|
+
it('should delete a schedule', async () => {
|
|
174
174
|
await persistence.saveSchedule({
|
|
175
|
-
id:
|
|
176
|
-
workflowKind:
|
|
177
|
-
triggerType:
|
|
178
|
-
cronExpression:
|
|
175
|
+
id: 'delete-1',
|
|
176
|
+
workflowKind: 'test.workflow',
|
|
177
|
+
triggerType: 'cron',
|
|
178
|
+
cronExpression: '0 * * * *',
|
|
179
179
|
enabled: true,
|
|
180
180
|
});
|
|
181
181
|
|
|
182
|
-
await persistence.deleteSchedule(
|
|
182
|
+
await persistence.deleteSchedule('delete-1');
|
|
183
183
|
|
|
184
184
|
const loaded = await persistence.loadSchedules();
|
|
185
185
|
expect(loaded).toHaveLength(0);
|
|
186
186
|
});
|
|
187
187
|
|
|
188
|
-
it(
|
|
188
|
+
it('should handle deleting non-existent schedule gracefully', async () => {
|
|
189
189
|
// This should not throw
|
|
190
|
-
await persistence.deleteSchedule(
|
|
190
|
+
await persistence.deleteSchedule('nonexistent');
|
|
191
191
|
});
|
|
192
192
|
});
|
|
193
193
|
|
|
194
|
-
describe(
|
|
195
|
-
it(
|
|
194
|
+
describe('data integrity', () => {
|
|
195
|
+
it('should preserve all fields through save/load cycle', async () => {
|
|
196
196
|
const schedule: WorkflowSchedule = {
|
|
197
|
-
id:
|
|
198
|
-
workflowKind:
|
|
199
|
-
triggerType:
|
|
200
|
-
triggerOnWorkflowKind:
|
|
201
|
-
triggerOnStatus: [
|
|
197
|
+
id: 'integrity-1',
|
|
198
|
+
workflowKind: 'complex.workflow',
|
|
199
|
+
triggerType: 'workflow_completed',
|
|
200
|
+
triggerOnWorkflowKind: 'parent.workflow',
|
|
201
|
+
triggerOnStatus: ['succeeded'],
|
|
202
202
|
input: { nested: { value: 123 } },
|
|
203
|
-
metadata: { tags: [
|
|
203
|
+
metadata: { tags: ['a', 'b'] },
|
|
204
204
|
enabled: true,
|
|
205
|
-
lastRunAt: new Date(
|
|
206
|
-
lastRunId:
|
|
207
|
-
nextRunAt: new Date(
|
|
205
|
+
lastRunAt: new Date('2024-06-15T10:30:00Z'),
|
|
206
|
+
lastRunId: 'run-789',
|
|
207
|
+
nextRunAt: new Date('2024-06-15T11:00:00Z'),
|
|
208
208
|
};
|
|
209
209
|
|
|
210
210
|
await persistence.saveSchedule(schedule);
|
|
@@ -213,11 +213,11 @@ describe("SQLiteSchedulePersistence", () => {
|
|
|
213
213
|
expect(loaded[0]).toEqual(schedule);
|
|
214
214
|
});
|
|
215
215
|
|
|
216
|
-
it(
|
|
216
|
+
it('should handle null/undefined values correctly', async () => {
|
|
217
217
|
const schedule: WorkflowSchedule = {
|
|
218
|
-
id:
|
|
219
|
-
workflowKind:
|
|
220
|
-
triggerType:
|
|
218
|
+
id: 'nullable-1',
|
|
219
|
+
workflowKind: 'test.workflow',
|
|
220
|
+
triggerType: 'manual',
|
|
221
221
|
enabled: false,
|
|
222
222
|
// All other optional fields are undefined
|
|
223
223
|
};
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* Stores workflow schedules in a SQLite database table.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { Database, Statement } from
|
|
8
|
-
import type { WorkflowSchedule } from
|
|
9
|
-
import type { SchedulePersistence } from
|
|
10
|
-
import { generateId } from
|
|
7
|
+
import type { Database, Statement } from 'better-sqlite3';
|
|
8
|
+
import type { WorkflowSchedule } from './types';
|
|
9
|
+
import type { SchedulePersistence } from './cron';
|
|
10
|
+
import { generateId } from '../utils/id';
|
|
11
11
|
|
|
12
12
|
// ============================================================================
|
|
13
13
|
// Configuration Types
|
|
@@ -57,7 +57,7 @@ export class SQLiteSchedulePersistence implements SchedulePersistence {
|
|
|
57
57
|
|
|
58
58
|
constructor(config: SQLiteSchedulePersistenceConfig) {
|
|
59
59
|
this.db = config.db;
|
|
60
|
-
this.tableName = config.tableName ??
|
|
60
|
+
this.tableName = config.tableName ?? 'workflow_schedules';
|
|
61
61
|
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(this.tableName)) {
|
|
62
62
|
throw new Error(`Invalid table name: ${this.tableName}`);
|
|
63
63
|
}
|
|
@@ -159,7 +159,7 @@ export class SQLiteSchedulePersistence implements SchedulePersistence {
|
|
|
159
159
|
|
|
160
160
|
async loadSchedules(): Promise<WorkflowSchedule[]> {
|
|
161
161
|
const rows = this.stmts!.getAll.all() as ScheduleRow[];
|
|
162
|
-
return rows.map(
|
|
162
|
+
return rows.map(row => this.rowToSchedule(row));
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
async saveSchedule(schedule: WorkflowSchedule): Promise<void> {
|
|
@@ -170,26 +170,19 @@ export class SQLiteSchedulePersistence implements SchedulePersistence {
|
|
|
170
170
|
schedule.cronExpression ?? null,
|
|
171
171
|
schedule.timezone ?? null,
|
|
172
172
|
schedule.triggerOnWorkflowKind ?? null,
|
|
173
|
-
schedule.triggerOnStatus
|
|
174
|
-
? JSON.stringify(schedule.triggerOnStatus)
|
|
175
|
-
: null,
|
|
173
|
+
schedule.triggerOnStatus ? JSON.stringify(schedule.triggerOnStatus) : null,
|
|
176
174
|
schedule.input ? JSON.stringify(schedule.input) : null,
|
|
177
175
|
schedule.metadata ? JSON.stringify(schedule.metadata) : null,
|
|
178
176
|
schedule.enabled ? 1 : 0,
|
|
179
177
|
schedule.lastRunAt?.toISOString() ?? null,
|
|
180
178
|
schedule.lastRunId ?? null,
|
|
181
|
-
schedule.nextRunAt?.toISOString() ?? null
|
|
179
|
+
schedule.nextRunAt?.toISOString() ?? null
|
|
182
180
|
);
|
|
183
181
|
}
|
|
184
182
|
|
|
185
|
-
async updateSchedule(
|
|
186
|
-
scheduleId: string,
|
|
187
|
-
updates: Partial<WorkflowSchedule>,
|
|
188
|
-
): Promise<void> {
|
|
183
|
+
async updateSchedule(scheduleId: string, updates: Partial<WorkflowSchedule>): Promise<void> {
|
|
189
184
|
// Get existing schedule to merge with updates
|
|
190
|
-
const existing = this.stmts!.getById.get(scheduleId) as
|
|
191
|
-
| ScheduleRow
|
|
192
|
-
| undefined;
|
|
185
|
+
const existing = this.stmts!.getById.get(scheduleId) as ScheduleRow | undefined;
|
|
193
186
|
if (!existing) {
|
|
194
187
|
throw new Error(`Schedule not found: ${scheduleId}`);
|
|
195
188
|
}
|
|
@@ -212,7 +205,7 @@ export class SQLiteSchedulePersistence implements SchedulePersistence {
|
|
|
212
205
|
merged.lastRunAt?.toISOString() ?? null,
|
|
213
206
|
merged.lastRunId ?? null,
|
|
214
207
|
merged.nextRunAt?.toISOString() ?? null,
|
|
215
|
-
scheduleId
|
|
208
|
+
scheduleId
|
|
216
209
|
);
|
|
217
210
|
}
|
|
218
211
|
|
|
@@ -228,7 +221,7 @@ export class SQLiteSchedulePersistence implements SchedulePersistence {
|
|
|
228
221
|
return {
|
|
229
222
|
id: row.id,
|
|
230
223
|
workflowKind: row.workflow_kind,
|
|
231
|
-
triggerType: row.trigger_type as WorkflowSchedule[
|
|
224
|
+
triggerType: row.trigger_type as WorkflowSchedule['triggerType'],
|
|
232
225
|
cronExpression: row.cron_expression ?? undefined,
|
|
233
226
|
timezone: row.timezone ?? undefined,
|
|
234
227
|
triggerOnWorkflowKind: row.trigger_on_workflow_kind ?? undefined,
|
package/src/scheduler/types.ts
CHANGED
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
* and {@link PostgresSchedulePersistence}.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type { WorkflowKind, RunStatus } from
|
|
8
|
+
import type { WorkflowKind, RunStatus } from '../core/types';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Schedule trigger types.
|
|
12
12
|
*/
|
|
13
|
-
export type TriggerType =
|
|
13
|
+
export type TriggerType = 'cron' | 'workflow_completed' | 'manual';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Schedule definition.
|
|
@@ -57,18 +57,13 @@ export interface Scheduler {
|
|
|
57
57
|
stop(): Promise<void>;
|
|
58
58
|
|
|
59
59
|
/** Add a schedule */
|
|
60
|
-
addSchedule(
|
|
61
|
-
schedule: Omit<WorkflowSchedule, "id">,
|
|
62
|
-
): Promise<WorkflowSchedule>;
|
|
60
|
+
addSchedule(schedule: Omit<WorkflowSchedule, 'id'>): Promise<WorkflowSchedule>;
|
|
63
61
|
|
|
64
62
|
/** Remove a schedule */
|
|
65
63
|
removeSchedule(scheduleId: string): Promise<void>;
|
|
66
64
|
|
|
67
65
|
/** Update a schedule */
|
|
68
|
-
updateSchedule(
|
|
69
|
-
scheduleId: string,
|
|
70
|
-
updates: Partial<WorkflowSchedule>,
|
|
71
|
-
): Promise<void>;
|
|
66
|
+
updateSchedule(scheduleId: string, updates: Partial<WorkflowSchedule>): Promise<void>;
|
|
72
67
|
|
|
73
68
|
/** Get all schedules */
|
|
74
69
|
getSchedules(): Promise<WorkflowSchedule[]>;
|
package/src/storage/index.ts
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* Storage module exports.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
export * from
|
|
6
|
-
export * from
|
|
7
|
-
export * from
|
|
8
|
-
export * from
|
|
5
|
+
export * from './types';
|
|
6
|
+
export * from './memory';
|
|
7
|
+
export * from './sqlite';
|
|
8
|
+
export * from './postgres';
|
|
9
9
|
|
|
10
10
|
// Re-export specific types for convenience
|
|
11
11
|
export type {
|
|
@@ -24,4 +24,4 @@ export type {
|
|
|
24
24
|
StepflowRunsTable,
|
|
25
25
|
StepflowStepResultsTable,
|
|
26
26
|
StepflowDatabase,
|
|
27
|
-
} from
|
|
27
|
+
} from './types';
|