@duraflows/kysely 6.0.0 → 7.0.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/README.md CHANGED
@@ -40,6 +40,7 @@ const runtime = new WorkflowRuntime({
40
40
  ...persistence,
41
41
  clock: { now: () => new Date() },
42
42
  });
43
+ await runtime.initialize(); // surfaces definition/version errors at boot
43
44
  ```
44
45
 
45
46
  ## Sharing a Transaction
@@ -108,7 +109,7 @@ A database type declared as `interface AppDb extends WorkflowDatabase` picks up
108
109
 
109
110
  ## Database Setup
110
111
 
111
- This package uses the same database schema as `@duraflows/pg`. Use the migration generator from `@duraflows/pg` or copy the reference migration:
112
+ This package uses the same database schema as `@duraflows/pg`, including migration `006_definition_version_index.sql` (recommended, not required -- it keeps the 7.0.0 startup executability check and `listDefinitionVersions()` cheap on large tables). Use the migration generator from `@duraflows/pg` or copy the reference migration:
112
113
 
113
114
  ```ts
114
115
  import { generateMigrationSql } from "@duraflows/pg";
@@ -118,6 +119,8 @@ const { up, down } = generateMigrationSql();
118
119
 
119
120
  See the [`@duraflows/pg` README](https://github.com/camcima/duraflows/tree/main/packages/duraflows-pg#database-setup) for full details.
120
121
 
122
+ `KyselyWorkflowInstanceStore` and `KyselyWorkflowDefinitionStore` implement the two store methods (`countInstances()`, `listVersions()`) that back 7.0.0's definition-version pinning and startup executability check. See [Definition versions](https://github.com/camcima/duraflows/blob/main/docs/workflow-definitions.md#definition-versions), and [Upgrading to 7.0.0](https://github.com/camcima/duraflows/blob/main/docs/workflow-definitions.md#upgrading-to-700) before deploying.
123
+
121
124
  ## API
122
125
 
123
126
  ### `kyselyWorkflowProviders(db, options?): WorkflowPersistenceProvider`
@@ -12,6 +12,7 @@ export declare class KyselyWorkflowDefinitionStore implements WorkflowDefinition
12
12
  definitionJson: WorkflowDefinition;
13
13
  }): Promise<StoredWorkflowDefinition>;
14
14
  findByNameAndVersion(workflowName: string, version: number): Promise<StoredWorkflowDefinition | null>;
15
+ listVersions(workflowName: string): Promise<StoredWorkflowDefinition[]>;
15
16
  private mapRow;
16
17
  }
17
18
  //# sourceMappingURL=kysely-definition-store.d.ts.map
@@ -43,6 +43,15 @@ class KyselyWorkflowDefinitionStore {
43
43
  return null;
44
44
  return this.mapRow(row);
45
45
  }
46
+ async listVersions(workflowName) {
47
+ const rows = await this.getExecutor()
48
+ .selectFrom("workflow_definitions")
49
+ .selectAll()
50
+ .where("workflow_name", "=", workflowName)
51
+ .orderBy("version")
52
+ .execute();
53
+ return rows.map((row) => this.mapRow(row));
54
+ }
46
55
  mapRow(row) {
47
56
  return {
48
57
  workflowName: row.workflow_name,
@@ -14,6 +14,11 @@ export declare class KyselyWorkflowInstanceStore implements WorkflowInstanceStor
14
14
  limit: number;
15
15
  workflowName?: string;
16
16
  }): Promise<WorkflowInstance[]>;
17
+ countInstances(options: {
18
+ workflowName: string;
19
+ definitionVersion: number;
20
+ excludeStates: readonly string[];
21
+ }): Promise<number>;
17
22
  private mapRow;
18
23
  }
19
24
  //# sourceMappingURL=kysely-instance-store.d.ts.map
@@ -119,6 +119,19 @@ class KyselyWorkflowInstanceStore {
119
119
  const rows = await query.orderBy("timeout_parked_at").orderBy("uuid").limit(options.limit).execute();
120
120
  return rows.map((row) => this.mapRow(row));
121
121
  }
122
+ async countInstances(options) {
123
+ let query = this.getExecutor()
124
+ .selectFrom("workflow_instances")
125
+ .select((eb) => eb.fn.countAll().as("count"))
126
+ .where("workflow_name", "=", options.workflowName)
127
+ .where("definition_version", "=", options.definitionVersion);
128
+ // Kysely rejects `not in ()`; an empty list excludes nothing anyway.
129
+ if (options.excludeStates.length > 0) {
130
+ query = query.where("current_state", "not in", [...options.excludeStates]);
131
+ }
132
+ const row = await query.executeTakeFirst();
133
+ return Number(row?.count ?? 0);
134
+ }
122
135
  mapRow(row) {
123
136
  return {
124
137
  uuid: row.uuid,
@@ -12,6 +12,7 @@ export declare class KyselyWorkflowDefinitionStore implements WorkflowDefinition
12
12
  definitionJson: WorkflowDefinition;
13
13
  }): Promise<StoredWorkflowDefinition>;
14
14
  findByNameAndVersion(workflowName: string, version: number): Promise<StoredWorkflowDefinition | null>;
15
+ listVersions(workflowName: string): Promise<StoredWorkflowDefinition[]>;
15
16
  private mapRow;
16
17
  }
17
18
  //# sourceMappingURL=kysely-definition-store.d.ts.map
@@ -40,6 +40,15 @@ export class KyselyWorkflowDefinitionStore {
40
40
  return null;
41
41
  return this.mapRow(row);
42
42
  }
43
+ async listVersions(workflowName) {
44
+ const rows = await this.getExecutor()
45
+ .selectFrom("workflow_definitions")
46
+ .selectAll()
47
+ .where("workflow_name", "=", workflowName)
48
+ .orderBy("version")
49
+ .execute();
50
+ return rows.map((row) => this.mapRow(row));
51
+ }
43
52
  mapRow(row) {
44
53
  return {
45
54
  workflowName: row.workflow_name,
@@ -14,6 +14,11 @@ export declare class KyselyWorkflowInstanceStore implements WorkflowInstanceStor
14
14
  limit: number;
15
15
  workflowName?: string;
16
16
  }): Promise<WorkflowInstance[]>;
17
+ countInstances(options: {
18
+ workflowName: string;
19
+ definitionVersion: number;
20
+ excludeStates: readonly string[];
21
+ }): Promise<number>;
17
22
  private mapRow;
18
23
  }
19
24
  //# sourceMappingURL=kysely-instance-store.d.ts.map
@@ -116,6 +116,19 @@ export class KyselyWorkflowInstanceStore {
116
116
  const rows = await query.orderBy("timeout_parked_at").orderBy("uuid").limit(options.limit).execute();
117
117
  return rows.map((row) => this.mapRow(row));
118
118
  }
119
+ async countInstances(options) {
120
+ let query = this.getExecutor()
121
+ .selectFrom("workflow_instances")
122
+ .select((eb) => eb.fn.countAll().as("count"))
123
+ .where("workflow_name", "=", options.workflowName)
124
+ .where("definition_version", "=", options.definitionVersion);
125
+ // Kysely rejects `not in ()`; an empty list excludes nothing anyway.
126
+ if (options.excludeStates.length > 0) {
127
+ query = query.where("current_state", "not in", [...options.excludeStates]);
128
+ }
129
+ const row = await query.executeTakeFirst();
130
+ return Number(row?.count ?? 0);
131
+ }
119
132
  mapRow(row) {
120
133
  return {
121
134
  uuid: row.uuid,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duraflows/kysely",
3
- "version": "6.0.0",
3
+ "version": "7.0.0",
4
4
  "description": "PostgreSQL persistence adapter for duraflows using `kysely`. Integrates with kysely's type-safe query builder and AsyncLocalStorage-based transaction context.",
5
5
  "keywords": [
6
6
  "duraflows",
@@ -51,15 +51,15 @@
51
51
  "access": "public"
52
52
  },
53
53
  "peerDependencies": {
54
- "@duraflows/core": "^6.0.0",
54
+ "@duraflows/core": "^7.0.0",
55
55
  "kysely": "^0.29.6"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@types/pg": "^8.23.1",
59
59
  "kysely": "^0.29.6",
60
60
  "pg": "^8.23.0",
61
- "@duraflows/core": "6.0.0",
62
- "@duraflows/pg": "6.0.0"
61
+ "@duraflows/core": "7.0.0",
62
+ "@duraflows/pg": "7.0.0"
63
63
  },
64
64
  "scripts": {
65
65
  "build": "tsc --build"