@brandboostinggmbh/observable-workflows 0.17.6 → 0.18.0

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/dist/index.d.ts CHANGED
@@ -6,7 +6,6 @@ declare function createStepContext(context: StepContextOptions): Promise<{
6
6
  metadata?: Record<string, any>;
7
7
  }, callback: (ctx: StepCtx) => Promise<RESULT>): Promise<RESULT>;
8
8
  }>;
9
-
10
9
  //#endregion
11
10
  //#region src/observableWorkflows/migrations.d.ts
12
11
 
@@ -16,7 +15,8 @@ declare function createStepContext(context: StepContextOptions): Promise<{
16
15
  *
17
16
  * @param db - D1Database instance
18
17
  */
19
- declare function ensureTables(db: D1Database): Promise<void>; //#endregion
18
+ declare function ensureTables(db: D1Database): Promise<void>;
19
+ //#endregion
20
20
  //#region src/observableWorkflows/helperFunctions.d.ts
21
21
  declare function finalizeWorkflowRecord(options: InternalWorkflowContextOptions, {
22
22
  workflowStatus,
@@ -171,7 +171,6 @@ declare function upsertWorkflowProperty<T extends keyof ValueTypeMap>({
171
171
  value: ValueTypeMap[T];
172
172
  tenantId: string;
173
173
  }): Promise<boolean>;
174
-
175
174
  //#endregion
176
175
  //#region src/observableWorkflows/types.d.ts
177
176
  type StepContextOptions = {
@@ -438,7 +437,6 @@ type WorkflowCallParams<I> = {
438
437
  /** Optional trigger identifier for workflow correlation */
439
438
  triggerId?: string | null;
440
439
  };
441
-
442
440
  //#endregion
443
441
  //#region src/observableWorkflows/createLogAccessor.d.ts
444
442
  declare const createLogAccessor: (context: {
@@ -489,7 +487,6 @@ declare const createLogAccessor: (context: {
489
487
  failedWorkflowCount: number;
490
488
  }[]>;
491
489
  };
492
-
493
490
  //#endregion
494
491
  //#region src/observableWorkflows/createQueueWorkflowContext.d.ts
495
492
  declare function createQueueWorkflowContext(options: QueueWorkflowContextOptions): {
@@ -502,11 +499,9 @@ declare function createQueueWorkflowContext(options: QueueWorkflowContextOptions
502
499
  workflowResolver
503
500
  }: HandleWorkflowQueueMessageParams) => Promise<void>;
504
501
  };
505
-
506
502
  //#endregion
507
503
  //#region src/observableWorkflows/createWorkflowContext.d.ts
508
504
  declare function createWorkflowContext(options: WorkflowContextOptions): WorkflowContextInstance;
509
-
510
505
  //#endregion
511
506
  //#region src/observableWorkflows/defaultImplementations.d.ts
512
507
  declare const defaultSerializer: {
@@ -517,7 +512,6 @@ declare const defaultSerializer: {
517
512
  deserialize: (text: string, reviver?: (this: any, key: string, value: any) => any) => any;
518
513
  };
519
514
  declare const defaultIdFactory: () => string;
520
-
521
515
  //#endregion
522
516
  //#region src/observableWorkflows/defineWorkflow.d.ts
523
517
  declare function defineWorkflow<I extends {} | null>(workflow: {
@@ -525,7 +519,6 @@ declare function defineWorkflow<I extends {} | null>(workflow: {
525
519
  metadata?: Record<string, any>;
526
520
  }, callback: (input: I, ctx: WorkflowContext) => Promise<any>): WorkflowFunction<I>;
527
521
  declare function defineWorkflow<I extends {} | null>(workflowType: string, callback: (input: I, ctx: WorkflowContext) => Promise<any>): WorkflowFunction<I>;
528
-
529
522
  //#endregion
530
523
  //#region src/observableWorkflows/r2ExternalBlobStorage.d.ts
531
524
  /**
@@ -561,7 +554,6 @@ type R2ExternalBlobStorageOptions = {
561
554
  * ```
562
555
  */
563
556
  declare function createR2ExternalBlobStorage(options: R2ExternalBlobStorageOptions): ExternalBlobStorage;
564
-
565
557
  //#endregion
566
558
  //#region src/observableWorkflows/createCleanupManager.d.ts
567
559
  type DeleteConfig = {
@@ -618,6 +610,5 @@ declare const createCleanupManager: (context: {
618
610
  deletedOrphanedLogs: number;
619
611
  }>;
620
612
  };
621
-
622
613
  //#endregion
623
614
  export { ConsoleWrapper, DateRangeFilter, ExternalBlobStorage, HandleWorkflowQueueMessageParams, InternalWorkflowContextOptions, Log, PossibleValueTypeNames, PossibleValueTypes, PropertyFilter, QueueWorkflowContextOptions, R2ExternalBlobStorageOptions, Serializer, Step, StepContextOptions, StepCtx, StepWorkflowStatus, StringFilter, ValueTypeMap, WorkflowContext, WorkflowContextInstance, WorkflowContextOptions, WorkflowEnqueueBatchItem, WorkflowFilter, WorkflowFunction, WorkflowProperty, WorkflowPropertyDefinition, WorkflowQueueMessage, WorkflowRun, createCleanupManager, createLogAccessor, createQueueWorkflowContext, createR2ExternalBlobStorage, createStepContext, createWorkflowContext, defaultIdFactory, defaultSerializer, defineWorkflow, deserializeWithExternalStorage, ensureTables, finalizeWorkflowRecord, insertStepRecordFull, insertWorkflowRecord, pushLogToDB, serializeWithExternalStorage, tryDeserializeObj, updateWorkflowName, upsertWorkflowProperty, workflowTableRowToWorkflowRun };
package/dist/index.js CHANGED
@@ -51,9 +51,7 @@ async function migrateWorkflowTableV1ToV2(db) {
51
51
  const hasInputRef = workflowTableInfo.sql.includes("inputRef");
52
52
  const inputHasNotNull = workflowTableInfo.sql.includes("input TEXT NOT NULL");
53
53
  if (!hasInputRef || inputHasNotNull) await db.batch([
54
- db.prepare(
55
- /* sql */
56
- `CREATE TABLE WorkflowTable_new (
54
+ db.prepare(`CREATE TABLE WorkflowTable_new (
57
55
  instanceId TEXT NOT NULL,
58
56
  workflowType TEXT NOT NULL,
59
57
  workflowName TEXT NOT NULL,
@@ -66,16 +64,12 @@ async function migrateWorkflowTableV1ToV2(db) {
66
64
  endTime INTEGER,
67
65
  parentInstanceId TEXT,
68
66
  PRIMARY KEY (instanceId)
69
- )`
70
- ),
71
- db.prepare(
72
- /* sql */
73
- `INSERT INTO WorkflowTable_new
67
+ )`),
68
+ db.prepare(`INSERT INTO WorkflowTable_new
74
69
  SELECT instanceId, workflowType, workflowName, workflowMetadata,
75
70
  CASE WHEN input = '' THEN NULL ELSE input END as input,
76
71
  NULL as inputRef, tenantId, workflowStatus, startTime, endTime, parentInstanceId
77
- FROM WorkflowTable`
78
- ),
72
+ FROM WorkflowTable`),
79
73
  db.prepare(`DROP TABLE WorkflowTable`),
80
74
  db.prepare(`ALTER TABLE WorkflowTable_new RENAME TO WorkflowTable`)
81
75
  ]);
@@ -88,9 +82,7 @@ async function migrateWorkflowTableV2V3ToV4(db) {
88
82
  const workflowTableInfo = await db.prepare(`SELECT sql FROM sqlite_master WHERE type='table' AND name='WorkflowTable'`).first();
89
83
  const hasTriggerId = workflowTableInfo.sql.includes("triggerId");
90
84
  if (!hasTriggerId) await db.batch([
91
- db.prepare(
92
- /* sql */
93
- `CREATE TABLE WorkflowTable_new (
85
+ db.prepare(`CREATE TABLE WorkflowTable_new (
94
86
  instanceId TEXT NOT NULL,
95
87
  workflowType TEXT NOT NULL,
96
88
  workflowName TEXT NOT NULL,
@@ -105,16 +97,12 @@ async function migrateWorkflowTableV2V3ToV4(db) {
105
97
  triggerId TEXT,
106
98
  PRIMARY KEY (instanceId),
107
99
  UNIQUE (triggerId)
108
- )`
109
- ),
110
- db.prepare(
111
- /* sql */
112
- `INSERT INTO WorkflowTable_new
100
+ )`),
101
+ db.prepare(`INSERT INTO WorkflowTable_new
113
102
  SELECT instanceId, workflowType, workflowName, workflowMetadata,
114
103
  input, inputRef, tenantId, workflowStatus, startTime, endTime, parentInstanceId,
115
104
  NULL as triggerId
116
- FROM WorkflowTable`
117
- ),
105
+ FROM WorkflowTable`),
118
106
  db.prepare(`DROP TABLE WorkflowTable`),
119
107
  db.prepare(`ALTER TABLE WorkflowTable_new RENAME TO WorkflowTable`)
120
108
  ]);
@@ -124,9 +112,7 @@ async function migrateWorkflowTableV2V3ToV4(db) {
124
112
  */
125
113
  async function migrateWorkflowTable(db, currentVersion) {
126
114
  if (currentVersion === "missing") {
127
- await db.prepare(
128
- /* sql */
129
- `CREATE TABLE WorkflowTable (
115
+ await db.prepare(`CREATE TABLE WorkflowTable (
130
116
  instanceId TEXT NOT NULL,
131
117
  workflowType TEXT NOT NULL,
132
118
  workflowName TEXT NOT NULL,
@@ -141,8 +127,7 @@ async function migrateWorkflowTable(db, currentVersion) {
141
127
  triggerId TEXT,
142
128
  PRIMARY KEY (instanceId),
143
129
  UNIQUE (triggerId)
144
- )`
145
- ).run();
130
+ )`).run();
146
131
  return;
147
132
  }
148
133
  if (currentVersion === "v1") {
@@ -160,9 +145,7 @@ async function migrateWorkflowTable(db, currentVersion) {
160
145
  */
161
146
  async function migrateStepTable(db, currentVersion) {
162
147
  if (currentVersion === "missing") {
163
- await db.prepare(
164
- /* sql */
165
- `CREATE TABLE StepTable (
148
+ await db.prepare(`CREATE TABLE StepTable (
166
149
  instanceId TEXT NOT NULL,
167
150
  stepName TEXT NOT NULL,
168
151
  stepStatus TEXT NOT NULL,
@@ -176,8 +159,7 @@ async function migrateStepTable(db, currentVersion) {
176
159
  tenantId TEXT NOT NULL,
177
160
  PRIMARY KEY (instanceId, stepName),
178
161
  FOREIGN KEY (instanceId) REFERENCES WorkflowTable(instanceId) ON DELETE CASCADE
179
- )`
180
- ).run();
162
+ )`).run();
181
163
  return;
182
164
  }
183
165
  if (currentVersion === "v1") {
@@ -193,9 +175,7 @@ async function migrateStepTable(db, currentVersion) {
193
175
  */
194
176
  async function migrateLogTable(db, currentVersion) {
195
177
  if (currentVersion === "missing") {
196
- await db.prepare(
197
- /* sql */
198
- `CREATE TABLE LogTable (
178
+ await db.prepare(`CREATE TABLE LogTable (
199
179
  instanceId TEXT NOT NULL,
200
180
  stepName TEXT,
201
181
  log TEXT NOT NULL,
@@ -205,8 +185,7 @@ async function migrateLogTable(db, currentVersion) {
205
185
  tenantId TEXT NOT NULL,
206
186
  FOREIGN KEY (instanceId, stepName) REFERENCES StepTable(instanceId, stepName) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
207
187
  FOREIGN KEY (instanceId) REFERENCES WorkflowTable(instanceId) ON DELETE CASCADE
208
- )`
209
- ).run();
188
+ )`).run();
210
189
  return;
211
190
  }
212
191
  }
@@ -215,9 +194,7 @@ async function migrateLogTable(db, currentVersion) {
215
194
  */
216
195
  async function migrateWorkflowPropertiesTable(db, currentVersion) {
217
196
  if (currentVersion === "missing") {
218
- await db.prepare(
219
- /* sql */
220
- `CREATE TABLE WorkflowProperties (
197
+ await db.prepare(`CREATE TABLE WorkflowProperties (
221
198
  instanceId TEXT NOT NULL,
222
199
  key TEXT NOT NULL,
223
200
  value TEXT NOT NULL,
@@ -226,8 +203,7 @@ async function migrateWorkflowPropertiesTable(db, currentVersion) {
226
203
  PRIMARY KEY (instanceId, key),
227
204
  FOREIGN KEY (instanceId) REFERENCES WorkflowTable(instanceId)
228
205
  ON DELETE CASCADE
229
- )`
230
- ).run();
206
+ )`).run();
231
207
  return;
232
208
  }
233
209
  }
@@ -235,21 +211,73 @@ async function migrateWorkflowPropertiesTable(db, currentVersion) {
235
211
  * Create necessary indexes
236
212
  */
237
213
  async function createIndexes(db) {
238
- await db.prepare(`CREATE INDEX IF NOT EXISTS idx_workflows_parent_instance_id ON WorkflowTable (parentInstanceId)`).run();
239
- await db.prepare(`CREATE INDEX IF NOT EXISTS idx_workflows_trigger_id ON WorkflowTable (triggerId)`).run();
240
- await db.prepare(`CREATE INDEX IF NOT EXISTS idx_workflows_start_time ON WorkflowTable (startTime)`).run();
241
- await db.prepare(`CREATE INDEX IF NOT EXISTS idx_workflows_tenant_id ON WorkflowTable (tenantId)`).run();
242
- await db.prepare(`CREATE INDEX IF NOT EXISTS idx_workflows_tenant_starttime ON WorkflowTable (tenantId, startTime DESC)`).run();
243
- await db.prepare(`CREATE INDEX IF NOT EXISTS idx_workflows_instance_id ON WorkflowTable (instanceId)`).run();
244
- await db.prepare(`CREATE INDEX IF NOT EXISTS idx_workflows_status ON WorkflowTable (workflowStatus)`).run();
245
- await db.prepare(`CREATE INDEX IF NOT EXISTS idx_steps_instance_id ON StepTable (instanceId)`).run();
246
- await db.prepare(`CREATE INDEX IF NOT EXISTS idx_steps_tenant_id ON StepTable (tenantId)`).run();
247
- await db.prepare(`CREATE INDEX IF NOT EXISTS idx_steps_start_time ON StepTable (startTime)`).run();
248
- await db.prepare(`CREATE INDEX IF NOT EXISTS idx_steps_instance_starttime ON StepTable (instanceId, startTime)`).run();
249
- await db.prepare(`CREATE INDEX IF NOT EXISTS idx_logs_instance_id ON LogTable (instanceId)`).run();
250
- await db.prepare(`CREATE INDEX IF NOT EXISTS idx_logs_tenant_id ON LogTable (tenantId)`).run();
251
- await db.prepare(`CREATE INDEX IF NOT EXISTS idx_workflow_properties_tenant_id ON WorkflowProperties (tenantId)`).run();
252
- await db.prepare(`CREATE INDEX IF NOT EXISTS idx_workflow_properties_tenant_key ON WorkflowProperties (tenantId, key, valueType)`).run();
214
+ const existingIndexes = await db.prepare(`SELECT name FROM sqlite_master WHERE type='index' AND name LIKE 'idx_%'`).all();
215
+ const existingIndexNames = new Set(existingIndexes.results?.map((row) => row.name) || []);
216
+ const indexes = [
217
+ {
218
+ name: "idx_workflows_parent_instance_id",
219
+ sql: `CREATE INDEX idx_workflows_parent_instance_id ON WorkflowTable (parentInstanceId)`
220
+ },
221
+ {
222
+ name: "idx_workflows_trigger_id",
223
+ sql: `CREATE INDEX idx_workflows_trigger_id ON WorkflowTable (triggerId)`
224
+ },
225
+ {
226
+ name: "idx_workflows_start_time",
227
+ sql: `CREATE INDEX idx_workflows_start_time ON WorkflowTable (startTime)`
228
+ },
229
+ {
230
+ name: "idx_workflows_tenant_id",
231
+ sql: `CREATE INDEX idx_workflows_tenant_id ON WorkflowTable (tenantId)`
232
+ },
233
+ {
234
+ name: "idx_workflows_tenant_starttime",
235
+ sql: `CREATE INDEX idx_workflows_tenant_starttime ON WorkflowTable (tenantId, startTime DESC)`
236
+ },
237
+ {
238
+ name: "idx_workflows_instance_id",
239
+ sql: `CREATE INDEX idx_workflows_instance_id ON WorkflowTable (instanceId)`
240
+ },
241
+ {
242
+ name: "idx_workflows_status",
243
+ sql: `CREATE INDEX idx_workflows_status ON WorkflowTable (workflowStatus)`
244
+ },
245
+ {
246
+ name: "idx_steps_instance_id",
247
+ sql: `CREATE INDEX idx_steps_instance_id ON StepTable (instanceId)`
248
+ },
249
+ {
250
+ name: "idx_steps_tenant_id",
251
+ sql: `CREATE INDEX idx_steps_tenant_id ON StepTable (tenantId)`
252
+ },
253
+ {
254
+ name: "idx_steps_start_time",
255
+ sql: `CREATE INDEX idx_steps_start_time ON StepTable (startTime)`
256
+ },
257
+ {
258
+ name: "idx_steps_instance_starttime",
259
+ sql: `CREATE INDEX idx_steps_instance_starttime ON StepTable (instanceId, startTime)`
260
+ },
261
+ {
262
+ name: "idx_logs_instance_id",
263
+ sql: `CREATE INDEX idx_logs_instance_id ON LogTable (instanceId)`
264
+ },
265
+ {
266
+ name: "idx_logs_tenant_id",
267
+ sql: `CREATE INDEX idx_logs_tenant_id ON LogTable (tenantId)`
268
+ },
269
+ {
270
+ name: "idx_workflow_properties_tenant_id",
271
+ sql: `CREATE INDEX idx_workflow_properties_tenant_id ON WorkflowProperties (tenantId)`
272
+ },
273
+ {
274
+ name: "idx_workflow_properties_tenant_key",
275
+ sql: `CREATE INDEX idx_workflow_properties_tenant_key ON WorkflowProperties (tenantId, key, valueType)`
276
+ }
277
+ ];
278
+ const preparedStatements = [];
279
+ for (const index of indexes) if (!existingIndexNames.has(index.name)) preparedStatements.push(db.prepare(index.sql));
280
+ if (preparedStatements.length > 0) await db.batch(preparedStatements);
253
281
  }
254
282
  /**
255
283
  * Main migration function that ensures all tables exist and are up-to-date.
@@ -270,35 +298,23 @@ async function ensureTables(db) {
270
298
  //#endregion
271
299
  //#region src/observableWorkflows/helperFunctions.ts
272
300
  function finalizeWorkflowRecord(options, { workflowStatus, endTime, instanceId }) {
273
- return options.D1.prepare(
274
- /* sql */
275
- `UPDATE WorkflowTable
301
+ return options.D1.prepare(`UPDATE WorkflowTable
276
302
  SET workflowStatus = ?, endTime = ?
277
- WHERE instanceId = ?`
278
- ).bind(workflowStatus, endTime, instanceId).run();
303
+ WHERE instanceId = ?`).bind(workflowStatus, endTime, instanceId).run();
279
304
  }
280
305
  async function insertWorkflowRecord(options, { instanceId, workflowType, workflowName, workflowMetadata, input, workflowStatus, startTime, endTime, parentInstanceId, tenantId, triggerId }) {
281
306
  const { data: inputData, externalRef: inputRef } = await serializeWithExternalStorage(input, options.serializer, options.externalBlobStorage);
282
- return options.D1.prepare(
283
- /* sql */
284
- `INSERT INTO WorkflowTable
307
+ return options.D1.prepare(`INSERT INTO WorkflowTable
285
308
  (instanceId, workflowType, workflowName, workflowMetadata, input, inputRef, tenantId, workflowStatus, startTime, endTime, parentInstanceId, triggerId)
286
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
287
- ).bind(instanceId, workflowType, workflowName, options.serializer.serialize(workflowMetadata), inputData, inputRef, tenantId, workflowStatus, startTime, endTime ?? null, parentInstanceId ?? null, triggerId ?? null).run();
309
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).bind(instanceId, workflowType, workflowName, options.serializer.serialize(workflowMetadata), inputData, inputRef, tenantId, workflowStatus, startTime, endTime ?? null, parentInstanceId ?? null, triggerId ?? null).run();
288
310
  }
289
311
  function insertStepRecordFull(context, { instanceId, name, status, metadata, startTime, endTime, result, error, resultRef, errorRef }) {
290
- return context.D1.prepare(
291
- /* sql */
292
- `INSERT INTO StepTable
312
+ return context.D1.prepare(`INSERT INTO StepTable
293
313
  (instanceId, stepName, stepStatus, stepMetadata, startTime, endTime, result, error, resultRef, errorRef, tenantId)
294
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
295
- ).bind(instanceId, name, status, metadata, startTime, endTime, result, error, resultRef ?? null, errorRef ?? null, context.tenantId).run();
314
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).bind(instanceId, name, status, metadata, startTime, endTime, result, error, resultRef ?? null, errorRef ?? null, context.tenantId).run();
296
315
  }
297
316
  async function getStepRecord(context, stepName, instanceId) {
298
- const existingStep = await context.D1.prepare(
299
- /* sql */
300
- `SELECT * FROM StepTable WHERE instanceId = ? AND stepName = ? AND tenantId = ?`
301
- ).bind(instanceId, stepName, context.tenantId).first();
317
+ const existingStep = await context.D1.prepare(`SELECT * FROM StepTable WHERE instanceId = ? AND stepName = ? AND tenantId = ?`).bind(instanceId, stepName, context.tenantId).first();
302
318
  const row = existingStep;
303
319
  if (row) {
304
320
  const result = await deserializeWithExternalStorage(row.result, row.resultRef, context.serializer, context.externalBlobStorage);
@@ -372,12 +388,9 @@ function truncateLogMessage(message) {
372
388
  }
373
389
  function pushLogToDB(options, { instanceId, stepName, message, timestamp, type, logOrder, tenantId }) {
374
390
  const truncatedMessage = truncateLogMessage(message);
375
- return options.D1.prepare(
376
- /* sql */
377
- `INSERT INTO LogTable
391
+ return options.D1.prepare(`INSERT INTO LogTable
378
392
  (instanceId, stepName, log, timestamp, type, logOrder, tenantId)
379
- VALUES (?, ?, ?, ?, ?, ?, ?)`
380
- ).bind(instanceId, stepName, truncatedMessage, timestamp, type, logOrder, tenantId).run();
393
+ VALUES (?, ?, ?, ?, ?, ?, ?)`).bind(instanceId, stepName, truncatedMessage, timestamp, type, logOrder, tenantId).run();
381
394
  }
382
395
  var LogBatcher = class {
383
396
  batch = [];
@@ -412,12 +425,9 @@ var LogBatcher = class {
412
425
  if (this.batch.length === 0) return;
413
426
  const logsToFlush = this.batch.splice(0);
414
427
  try {
415
- const statements = logsToFlush.map((entry) => this.options.D1.prepare(
416
- /* sql */
417
- `INSERT INTO LogTable
428
+ const statements = logsToFlush.map((entry) => this.options.D1.prepare(`INSERT INTO LogTable
418
429
  (instanceId, stepName, log, timestamp, type, logOrder, tenantId)
419
- VALUES (?, ?, ?, ?, ?, ?, ?)`
420
- ).bind(entry.instanceId, entry.stepName, entry.message, entry.timestamp, entry.type, entry.logOrder, entry.tenantId));
430
+ VALUES (?, ?, ?, ?, ?, ?, ?)`).bind(entry.instanceId, entry.stepName, entry.message, entry.timestamp, entry.type, entry.logOrder, entry.tenantId));
421
431
  await this.options.D1.batch(statements);
422
432
  } catch (error) {
423
433
  console.error("Batch log insert failed, falling back to individual inserts:", error);
@@ -543,22 +553,16 @@ async function workflowTableRowToWorkflowRun({ row, serializer, externalBlobStor
543
553
  };
544
554
  }
545
555
  async function updateWorkflowName(context, instanceId, newWorkflowName) {
546
- return await context.D1.prepare(
547
- /* sql */
548
- `UPDATE WorkflowTable
556
+ return await context.D1.prepare(`UPDATE WorkflowTable
549
557
  SET workflowName = ?
550
- WHERE instanceId = ?`
551
- ).bind(newWorkflowName, instanceId).run();
558
+ WHERE instanceId = ?`).bind(newWorkflowName, instanceId).run();
552
559
  }
553
560
  async function upsertWorkflowProperty({ context, instanceId, key, value, tenantId }) {
554
561
  const valueType = typeof value;
555
562
  const serializedValue = valueType === "object" ? JSON.stringify(value) : String(value);
556
- const res = await context.D1.prepare(
557
- /* sql */
558
- `INSERT OR REPLACE INTO WorkflowProperties
563
+ const res = await context.D1.prepare(`INSERT OR REPLACE INTO WorkflowProperties
559
564
  (instanceId, key, value, valueType, tenantId)
560
- VALUES (?, ?, ?, ?, ?)`
561
- ).bind(instanceId, key, serializedValue, valueType, tenantId).run();
565
+ VALUES (?, ?, ?, ?, ?)`).bind(instanceId, key, serializedValue, valueType, tenantId).run();
562
566
  if (res.error) {
563
567
  console.error("Error inserting workflow property:", res.error);
564
568
  return false;
@@ -779,15 +783,12 @@ const createLogAccessor = (context) => {
779
783
  })));
780
784
  if (options?.populateProperties && workflows.length > 0) {
781
785
  const instanceIds = workflows.map((w) => w.instanceId);
782
- const BATCH_SIZE = 100;
786
+ const BATCH_SIZE = 80;
783
787
  const propertiesByInstanceId = new Map();
784
788
  for (let i = 0; i < instanceIds.length; i += BATCH_SIZE) {
785
789
  const batchIds = instanceIds.slice(i, i + BATCH_SIZE);
786
790
  const placeholders = batchIds.map(() => "?").join(", ");
787
- const propertiesResult = await context.D1.prepare(
788
- /* sql */
789
- `SELECT * FROM WorkflowProperties WHERE instanceId IN (${placeholders}) AND tenantId = ?`
790
- ).bind(...batchIds, context.tenantId).all();
791
+ const propertiesResult = await context.D1.prepare(`SELECT * FROM WorkflowProperties WHERE instanceId IN (${placeholders}) AND tenantId = ?`).bind(...batchIds, context.tenantId).all();
791
792
  if (propertiesResult.results) for (const row of propertiesResult.results) {
792
793
  const property = {
793
794
  key: row.key,
@@ -806,10 +807,7 @@ const createLogAccessor = (context) => {
806
807
  return [];
807
808
  };
808
809
  const getWorkflowByParentId = async (parentInstanceId) => {
809
- const result = await context.D1.prepare(
810
- /* sql */
811
- `SELECT * FROM WorkflowTable WHERE parentInstanceId = ? AND tenantId = ?`
812
- ).bind(parentInstanceId, context.tenantId).all();
810
+ const result = await context.D1.prepare(`SELECT * FROM WorkflowTable WHERE parentInstanceId = ? AND tenantId = ?`).bind(parentInstanceId, context.tenantId).all();
813
811
  if (result.results) {
814
812
  const workflows = await Promise.all(result.results.map((row) => workflowTableRowToWorkflowRun({
815
813
  row,
@@ -821,10 +819,7 @@ const createLogAccessor = (context) => {
821
819
  return null;
822
820
  };
823
821
  const getWorkflowByTriggerId = async (triggerId) => {
824
- const result = await context.D1.prepare(
825
- /* sql */
826
- `SELECT * FROM WorkflowTable WHERE triggerId = ? AND tenantId = ?`
827
- ).bind(triggerId, context.tenantId).first();
822
+ const result = await context.D1.prepare(`SELECT * FROM WorkflowTable WHERE triggerId = ? AND tenantId = ?`).bind(triggerId, context.tenantId).first();
828
823
  if (result) {
829
824
  const workflow = await workflowTableRowToWorkflowRun({
830
825
  row: result,
@@ -836,18 +831,12 @@ const createLogAccessor = (context) => {
836
831
  return null;
837
832
  };
838
833
  const getWorkflowTypesByTenantId = async (tenantId) => {
839
- const result = await context.D1.prepare(
840
- /* sql */
841
- `SELECT DISTINCT workflowType FROM WorkflowTable WHERE tenantId = ?`
842
- ).bind(tenantId).all();
834
+ const result = await context.D1.prepare(`SELECT DISTINCT workflowType FROM WorkflowTable WHERE tenantId = ?`).bind(tenantId).all();
843
835
  if (!result.results) return [];
844
836
  return result.results.map((row) => row.workflowType);
845
837
  };
846
838
  const getWorkflowProperties = async (instanceId) => {
847
- const result = await context.D1.prepare(
848
- /* sql */
849
- `SELECT * FROM WorkflowProperties WHERE instanceId = ?`
850
- ).bind(instanceId).all();
839
+ const result = await context.D1.prepare(`SELECT * FROM WorkflowProperties WHERE instanceId = ?`).bind(instanceId).all();
851
840
  if (!result.results) return [];
852
841
  return result.results.map((row) => ({
853
842
  key: row.key,
@@ -857,10 +846,7 @@ const createLogAccessor = (context) => {
857
846
  };
858
847
  /** This function gets the basic data of a workflow, without populating any of it's complex fields */
859
848
  const getWorkflowShallow = async (instanceId) => {
860
- const result = await context.D1.prepare(
861
- /* sql */
862
- `SELECT * FROM WorkflowTable WHERE instanceId = ? AND tenantId = ?`
863
- ).bind(instanceId, context.tenantId).first();
849
+ const result = await context.D1.prepare(`SELECT * FROM WorkflowTable WHERE instanceId = ? AND tenantId = ?`).bind(instanceId, context.tenantId).first();
864
850
  if (!result) return null;
865
851
  const workflow = await workflowTableRowToWorkflowRun({
866
852
  row: result,
@@ -883,10 +869,7 @@ const createLogAccessor = (context) => {
883
869
  retryWorkflow.isRetryOf = workflow;
884
870
  });
885
871
  workflow.isRetryOf = parentWorkflow;
886
- const allLogs = await context.D1.prepare(
887
- /* sql */
888
- `SELECT * FROM LogTable WHERE instanceId = ? ORDER BY timestamp ASC, logOrder ASC`
889
- ).bind(instanceId).all();
872
+ const allLogs = await context.D1.prepare(`SELECT * FROM LogTable WHERE instanceId = ? ORDER BY timestamp ASC, logOrder ASC`).bind(instanceId).all();
890
873
  const logs = allLogs.results?.map((logRow) => ({
891
874
  instanceId: logRow.instanceId,
892
875
  stepName: logRow.stepName,
@@ -904,10 +887,7 @@ const createLogAccessor = (context) => {
904
887
  return workflow;
905
888
  };
906
889
  const getStep = async (instanceId, stepName) => {
907
- const result = await context.D1.prepare(
908
- /* sql */
909
- `SELECT * FROM StepTable WHERE instanceId = ? AND stepName = ? AND tenantId = ?`
910
- ).bind(instanceId, stepName, context.tenantId).all();
890
+ const result = await context.D1.prepare(`SELECT * FROM StepTable WHERE instanceId = ? AND stepName = ? AND tenantId = ?`).bind(instanceId, stepName, context.tenantId).all();
911
891
  if (!result.results || result.results.length === 0) return null;
912
892
  const row = result.results[0];
913
893
  if (!row) return null;
@@ -924,10 +904,7 @@ const createLogAccessor = (context) => {
924
904
  error: deserializedError,
925
905
  logs: []
926
906
  };
927
- const logResult = await context.D1.prepare(
928
- /* sql */
929
- `SELECT * FROM LogTable WHERE instanceId = ? AND stepName = ? ORDER BY logOrder ASC`
930
- ).bind(instanceId, stepName).all();
907
+ const logResult = await context.D1.prepare(`SELECT * FROM LogTable WHERE instanceId = ? AND stepName = ? ORDER BY logOrder ASC`).bind(instanceId, stepName).all();
931
908
  if (logResult.results) step.logs = logResult.results.map((logRow) => ({
932
909
  instanceId: logRow.instanceId,
933
910
  stepName: logRow.stepName,
@@ -938,13 +915,10 @@ const createLogAccessor = (context) => {
938
915
  return step;
939
916
  };
940
917
  const getPropertiesKeys = async (instanceId) => {
941
- const result = await context.D1.prepare(
942
- /* sql */
943
- `
918
+ const result = await context.D1.prepare(`
944
919
  SELECT DISTINCT key, valueType FROM WorkflowProperties
945
920
  WHERE tenantId = ? AND (? IS NULL OR instanceId = ?)
946
- `
947
- ).bind(context.tenantId, instanceId ?? null, instanceId ?? null).all();
921
+ `).bind(context.tenantId, instanceId ?? null, instanceId ?? null).all();
948
922
  console.log(`debug getPropertiesKeys: ${JSON.stringify(result)}`);
949
923
  if (!result.results) return [];
950
924
  return result.results.map((row) => ({
@@ -967,9 +941,7 @@ const createLogAccessor = (context) => {
967
941
  bindings.push(toTime);
968
942
  }
969
943
  const whereClause = whereConditions.length > 0 ? `WHERE ${whereConditions.join(" AND ")}` : "";
970
- const result = await context.D1.prepare(
971
- /* sql */
972
- `
944
+ const result = await context.D1.prepare(`
973
945
  SELECT
974
946
  workflowType,
975
947
  COUNT(*) as workflowCount,
@@ -1012,8 +984,7 @@ const createLogAccessor = (context) => {
1012
984
  ${whereClause}
1013
985
  GROUP BY workflowType
1014
986
  ORDER BY workflowCount DESC
1015
- `
1016
- ).bind(...bindings).all();
987
+ `).bind(...bindings).all();
1017
988
  if (!result.results) return [];
1018
989
  return result.results.map((row) => ({
1019
990
  workflowType: row.workflowType,
@@ -1191,12 +1162,9 @@ async function createStepContext(context) {
1191
1162
  const stepStatus$1 = "completed";
1192
1163
  const { data: resultData, externalRef: resultRef } = await serializeWithExternalStorage(result, context.serializer, context.externalBlobStorage);
1193
1164
  const stepError$1 = null;
1194
- await context.D1.prepare(
1195
- /* sql */
1196
- `UPDATE StepTable
1165
+ await context.D1.prepare(`UPDATE StepTable
1197
1166
  SET stepStatus = ?, endTime = ?, result = ?, error = ?, resultRef = ?, errorRef = ?
1198
- WHERE instanceId = ? AND stepName = ?`
1199
- ).bind(stepStatus$1, endTime, resultData, stepError$1, resultRef, null, instanceId, stepName).run();
1167
+ WHERE instanceId = ? AND stepName = ?`).bind(stepStatus$1, endTime, resultData, stepError$1, resultRef, null, instanceId, stepName).run();
1200
1168
  await logBatcher.destroy();
1201
1169
  return result;
1202
1170
  } catch (error) {
@@ -1204,12 +1172,9 @@ async function createStepContext(context) {
1204
1172
  const stepStatus$1 = "failed";
1205
1173
  const stepResult$1 = null;
1206
1174
  const { data: errorData, externalRef: errorRef } = await serializeWithExternalStorage(error, context.serializer, context.externalBlobStorage);
1207
- await context.D1.prepare(
1208
- /* sql */
1209
- `UPDATE StepTable
1175
+ await context.D1.prepare(`UPDATE StepTable
1210
1176
  SET stepStatus = ?, endTime = ?, result = ?, error = ?, resultRef = ?, errorRef = ?
1211
- WHERE instanceId = ? AND stepName = ?`
1212
- ).bind(stepStatus$1, endTime, stepResult$1, errorData, null, errorRef, instanceId, stepName).run();
1177
+ WHERE instanceId = ? AND stepName = ?`).bind(stepStatus$1, endTime, stepResult$1, errorData, null, errorRef, instanceId, stepName).run();
1213
1178
  await logBatcher.destroy();
1214
1179
  throw error;
1215
1180
  }
@@ -1337,10 +1302,7 @@ function createWorkflowContext(options) {
1337
1302
  await ensureTables(options.D1);
1338
1303
  ensuredTables = true;
1339
1304
  }
1340
- const oldRun = await options.D1.prepare(
1341
- /* sql */
1342
- `SELECT input, workflowName, tenantId, inputRef FROM WorkflowTable WHERE instanceId = ? `
1343
- ).bind(retryInstanceId).first();
1305
+ const oldRun = await options.D1.prepare(`SELECT input, workflowName, tenantId, inputRef FROM WorkflowTable WHERE instanceId = ? `).bind(retryInstanceId).first();
1344
1306
  const oldWorkflowName = oldRun?.workflowName;
1345
1307
  const tenantId = oldRun?.tenantId;
1346
1308
  if (!tenantId) throw new Error(`No tenantId found for instanceId ${retryInstanceId}`);
@@ -1462,9 +1424,7 @@ const createCleanupManager = (context) => {
1462
1424
  const getAffectedWorkflows = async (config, limit) => {
1463
1425
  const { statuses, statusPlaceholders } = buildStatusesAndPlaceholders(config);
1464
1426
  if (statuses.length === 0) return [];
1465
- const result = await context.D1.prepare(
1466
- /* sql */
1467
- `
1427
+ const result = await context.D1.prepare(`
1468
1428
  SELECT instanceId, inputRef
1469
1429
  FROM WorkflowTable
1470
1430
  WHERE tenantId = ?
@@ -1472,16 +1432,13 @@ const createCleanupManager = (context) => {
1472
1432
  AND workflowStatus IN (${statusPlaceholders})
1473
1433
  ORDER BY instanceId
1474
1434
  LIMIT ?
1475
- `
1476
- ).bind(context.tenantId, config.deleteWorkflowsOlderThanDays, ...statuses, limit).all();
1435
+ `).bind(context.tenantId, config.deleteWorkflowsOlderThanDays, ...statuses, limit).all();
1477
1436
  return result.results;
1478
1437
  };
1479
1438
  const getAffectedSteps = async (config, limit) => {
1480
1439
  const { statuses, statusPlaceholders } = buildStatusesAndPlaceholders(config);
1481
1440
  if (statuses.length === 0) return [];
1482
- const result = await context.D1.prepare(
1483
- /* sql */
1484
- `
1441
+ const result = await context.D1.prepare(`
1485
1442
  SELECT s.instanceId, s.stepName, s.stepStatus, s.errorRef, s.resultRef
1486
1443
  FROM StepTable s
1487
1444
  WHERE s.instanceId IN (
@@ -1494,8 +1451,7 @@ const createCleanupManager = (context) => {
1494
1451
  LIMIT ?
1495
1452
  )
1496
1453
  ORDER BY s.instanceId, s.stepName
1497
- `
1498
- ).bind(context.tenantId, config.deleteWorkflowsOlderThanDays, ...statuses, limit).all();
1454
+ `).bind(context.tenantId, config.deleteWorkflowsOlderThanDays, ...statuses, limit).all();
1499
1455
  return result.results;
1500
1456
  };
1501
1457
  const collectExternalStorageKeys = (workflows, steps) => {
@@ -1553,13 +1509,10 @@ const createCleanupManager = (context) => {
1553
1509
  for (let i = 0; i < deletedWorkflows.length; i += 100) {
1554
1510
  const batch = deletedWorkflows.slice(i, i + 100);
1555
1511
  const workflowIds = batch.map(() => "?").join(", ");
1556
- const result = await context.D1.prepare(
1557
- /* sql */
1558
- `
1512
+ const result = await context.D1.prepare(`
1559
1513
  DELETE FROM WorkflowTable
1560
1514
  WHERE instanceId IN (${workflowIds})
1561
- `
1562
- ).bind(...batch.map((w) => w.instanceId)).run();
1515
+ `).bind(...batch.map((w) => w.instanceId)).run();
1563
1516
  totalDeletedCount += result.meta.changes || 0;
1564
1517
  }
1565
1518
  return {
@@ -1576,9 +1529,7 @@ const createCleanupManager = (context) => {
1576
1529
  };
1577
1530
  const cleanupOrphanedSteps = async (config, limit) => {
1578
1531
  await context.D1.prepare(`PRAGMA foreign_keys = ON`).run();
1579
- const orphanedSteps = await context.D1.prepare(
1580
- /* sql */
1581
- `
1532
+ const orphanedSteps = await context.D1.prepare(`
1582
1533
  SELECT s.instanceId, s.stepName, s.errorRef, s.resultRef
1583
1534
  FROM StepTable s
1584
1535
  WHERE s.tenantId = ?
@@ -1588,8 +1539,7 @@ const createCleanupManager = (context) => {
1588
1539
  )
1589
1540
  ORDER BY s.instanceId, s.stepName
1590
1541
  LIMIT ?
1591
- `
1592
- ).bind(context.tenantId, context.tenantId, limit).all();
1542
+ `).bind(context.tenantId, context.tenantId, limit).all();
1593
1543
  const orphanedStepResults = orphanedSteps.results;
1594
1544
  let deletedExternalStorageKeysCount = 0;
1595
1545
  if (config.deleteRefsFromExternalStorage && context.externalBlobStorage && orphanedStepResults.length > 0) {
@@ -1605,14 +1555,11 @@ const createCleanupManager = (context) => {
1605
1555
  for (let i = 0; i < orphanedStepResults.length; i += 99) {
1606
1556
  const batch = orphanedStepResults.slice(i, i + 99);
1607
1557
  const instanceIds = batch.map(() => "?").join(", ");
1608
- const deletedStepsResult = await context.D1.prepare(
1609
- /* sql */
1610
- `
1558
+ const deletedStepsResult = await context.D1.prepare(`
1611
1559
  DELETE FROM StepTable
1612
1560
  WHERE tenantId = ?
1613
1561
  AND instanceId IN (${instanceIds})
1614
- `
1615
- ).bind(context.tenantId, ...batch.map((s) => s.instanceId)).run();
1562
+ `).bind(context.tenantId, ...batch.map((s) => s.instanceId)).run();
1616
1563
  totalDeletedSteps += deletedStepsResult.meta.changes || 0;
1617
1564
  }
1618
1565
  return {
@@ -1629,9 +1576,7 @@ const createCleanupManager = (context) => {
1629
1576
  };
1630
1577
  const cleanupOrphanedLogs = async (limit) => {
1631
1578
  await context.D1.prepare(`PRAGMA foreign_keys = ON`).run();
1632
- const deletedLogsResult = await context.D1.prepare(
1633
- /* sql */
1634
- `
1579
+ const deletedLogsResult = await context.D1.prepare(`
1635
1580
  DELETE FROM LogTable
1636
1581
  WHERE tenantId = ?
1637
1582
  AND (
@@ -1646,8 +1591,7 @@ const createCleanupManager = (context) => {
1646
1591
  ))
1647
1592
  )
1648
1593
  LIMIT ?
1649
- `
1650
- ).bind(context.tenantId, context.tenantId, context.tenantId, limit).run();
1594
+ `).bind(context.tenantId, context.tenantId, context.tenantId, limit).run();
1651
1595
  return { deletedOrphanedLogs: deletedLogsResult.meta.changes || 0 };
1652
1596
  };
1653
1597
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brandboostinggmbh/observable-workflows",
3
- "version": "0.17.6",
3
+ "version": "0.18.0",
4
4
  "description": "My awesome typescript library",
5
5
  "type": "module",
6
6
  "license": "MIT",