openworkflow 0.4.1 → 0.6.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 +43 -345
- package/dist/backend-test/backend.testsuite.d.ts +20 -0
- package/dist/backend-test/backend.testsuite.d.ts.map +1 -0
- package/dist/{core → backend-test}/backend.testsuite.js +191 -59
- package/dist/backend-test/index.d.ts +2 -0
- package/dist/backend-test/index.d.ts.map +1 -0
- package/dist/backend-test/index.js +1 -0
- package/dist/{core/backend.d.ts → backend.d.ts} +7 -5
- package/dist/backend.d.ts.map +1 -0
- package/dist/{core/backend.js → backend.js} +0 -1
- package/dist/backend.testsuite.d.ts +20 -0
- package/dist/backend.testsuite.d.ts.map +1 -0
- package/dist/{core/backend-test-suite.js → backend.testsuite.js} +301 -171
- package/dist/bin/openworkflow.d.ts +3 -0
- package/dist/bin/openworkflow.d.ts.map +1 -0
- package/dist/bin/openworkflow.js +43 -0
- package/dist/chaos.test.d.ts +2 -0
- package/dist/chaos.test.d.ts.map +1 -0
- package/dist/chaos.test.js +88 -0
- package/dist/client.d.ts +141 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/{sdk/sdk.js → client.js} +43 -71
- package/dist/client.test.d.ts +2 -0
- package/dist/client.test.d.ts.map +1 -0
- package/dist/{sdk/sdk.test.js → client.test.js} +130 -14
- package/dist/core/duration.d.ts +4 -2
- package/dist/core/duration.d.ts.map +1 -1
- package/dist/core/duration.js +3 -2
- package/dist/core/duration.test.js +0 -1
- package/dist/core/error.d.ts +14 -0
- package/dist/core/error.d.ts.map +1 -0
- package/dist/core/error.js +17 -0
- package/dist/core/error.test.d.ts +2 -0
- package/dist/core/error.test.d.ts.map +1 -0
- package/dist/core/error.test.js +60 -0
- package/dist/core/json.js +0 -1
- package/dist/core/result.d.ts +14 -4
- package/dist/core/result.d.ts.map +1 -1
- package/dist/core/result.js +10 -1
- package/dist/core/result.test.js +2 -2
- package/dist/core/retry.d.ts +0 -9
- package/dist/core/retry.d.ts.map +1 -1
- package/dist/core/retry.js +0 -15
- package/dist/core/schema.js +0 -1
- package/dist/core/step.d.ts +1 -32
- package/dist/core/step.d.ts.map +1 -1
- package/dist/core/step.js +0 -36
- package/dist/core/step.test.js +1 -75
- package/dist/core/workflow.d.ts +2 -47
- package/dist/core/workflow.d.ts.map +1 -1
- package/dist/core/workflow.js +0 -45
- package/dist/core/workflow.test.js +1 -104
- package/dist/driver.d.ts +116 -0
- package/dist/driver.d.ts.map +1 -0
- package/dist/driver.js +1 -0
- package/dist/{execution/execution.d.ts → execution.d.ts} +4 -26
- package/dist/execution.d.ts.map +1 -0
- package/dist/{execution/execution.js → execution.js} +4 -5
- package/dist/execution.test.d.ts.map +1 -0
- package/dist/{execution/execution.test.js → execution.test.js} +4 -5
- package/dist/factory.d.ts +74 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/factory.js +72 -0
- package/dist/index.d.ts +6 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -5
- package/dist/internal.d.ts +7 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +2 -0
- package/dist/node-sqlite/backend.d.ts +52 -0
- package/dist/node-sqlite/backend.d.ts.map +1 -0
- package/dist/node-sqlite/backend.js +673 -0
- package/dist/node-sqlite/index.d.ts +11 -0
- package/dist/node-sqlite/index.d.ts.map +1 -0
- package/dist/node-sqlite/index.js +7 -0
- package/dist/node-sqlite/sqlite.d.ts +60 -0
- package/dist/node-sqlite/sqlite.d.ts.map +1 -0
- package/dist/{backend-sqlite → node-sqlite}/sqlite.js +20 -3
- package/dist/postgres/backend.d.ts +44 -0
- package/dist/postgres/backend.d.ts.map +1 -0
- package/dist/postgres/backend.js +534 -0
- package/dist/postgres/backend.test.d.ts +2 -0
- package/dist/postgres/backend.test.d.ts.map +1 -0
- package/dist/postgres/backend.test.js +19 -0
- package/dist/postgres/driver.d.ts +81 -0
- package/dist/postgres/driver.d.ts.map +1 -0
- package/dist/postgres/driver.js +63 -0
- package/dist/postgres/index.d.ts +11 -0
- package/dist/postgres/index.d.ts.map +1 -0
- package/dist/postgres/index.js +7 -0
- package/dist/postgres/internal.d.ts +2 -0
- package/dist/postgres/internal.d.ts.map +1 -0
- package/dist/postgres/internal.js +1 -0
- package/dist/postgres/postgres.d.ts +42 -0
- package/dist/postgres/postgres.d.ts.map +1 -0
- package/dist/postgres/postgres.js +233 -0
- package/dist/postgres/postgres.test.d.ts +2 -0
- package/dist/postgres/postgres.test.d.ts.map +1 -0
- package/dist/postgres/postgres.test.js +45 -0
- package/dist/postgres/scripts/db-migrate.d.ts +2 -0
- package/dist/postgres/scripts/db-migrate.d.ts.map +1 -0
- package/dist/postgres/scripts/db-migrate.js +4 -0
- package/dist/postgres/scripts/db-reset.d.ts +2 -0
- package/dist/postgres/scripts/db-reset.d.ts.map +1 -0
- package/dist/postgres/scripts/db-reset.js +5 -0
- package/dist/postgres/scripts/squawk.d.ts +2 -0
- package/dist/postgres/scripts/squawk.d.ts.map +1 -0
- package/dist/postgres/scripts/squawk.js +16 -0
- package/dist/postgres/vitest.global-setup.d.ts +3 -0
- package/dist/postgres/vitest.global-setup.d.ts.map +1 -0
- package/dist/postgres/vitest.global-setup.js +7 -0
- package/dist/postgres.d.ts +2 -0
- package/dist/postgres.d.ts.map +1 -0
- package/dist/postgres.js +1 -0
- package/dist/registry.d.ts +27 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +48 -0
- package/dist/registry.test.d.ts +2 -0
- package/dist/registry.test.d.ts.map +1 -0
- package/dist/registry.test.js +109 -0
- package/dist/{backend-sqlite → sqlite}/backend.d.ts +8 -4
- package/dist/sqlite/backend.d.ts.map +1 -0
- package/dist/{backend-sqlite → sqlite}/backend.js +35 -9
- package/dist/sqlite/backend.test.d.ts +2 -0
- package/dist/sqlite/backend.test.d.ts.map +1 -0
- package/dist/sqlite/backend.test.js +50 -0
- package/dist/sqlite/driver.d.ts +79 -0
- package/dist/sqlite/driver.d.ts.map +1 -0
- package/dist/sqlite/driver.js +62 -0
- package/dist/sqlite/index.d.ts +13 -0
- package/dist/sqlite/index.d.ts.map +1 -0
- package/dist/sqlite/index.js +11 -0
- package/dist/sqlite/internal.d.ts +2 -0
- package/dist/sqlite/internal.d.ts.map +1 -0
- package/dist/sqlite/internal.js +1 -0
- package/dist/{backend-sqlite → sqlite}/sqlite.d.ts +18 -2
- package/dist/sqlite/sqlite.d.ts.map +1 -0
- package/dist/sqlite/sqlite.js +246 -0
- package/dist/sqlite/sqlite.test.d.ts +2 -0
- package/dist/sqlite/sqlite.test.d.ts.map +1 -0
- package/dist/sqlite/sqlite.test.js +171 -0
- package/dist/sqlite.d.ts +2 -0
- package/dist/sqlite.d.ts.map +1 -0
- package/dist/sqlite.js +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/{worker/worker.d.ts → worker.d.ts} +11 -4
- package/dist/worker.d.ts.map +1 -0
- package/dist/{worker/worker.js → worker.js} +20 -11
- package/dist/{worker/worker.test.d.ts.map → worker.test.d.ts.map} +1 -1
- package/dist/{worker/worker.test.js → worker.test.js} +136 -22
- package/dist/workflow.d.ts +60 -0
- package/dist/workflow.d.ts.map +1 -0
- package/dist/workflow.js +48 -0
- package/dist/workflow.test.d.ts +2 -0
- package/dist/workflow.test.d.ts.map +1 -0
- package/dist/workflow.test.js +84 -0
- package/package.json +28 -4
- package/dist/backend-sqlite/backend.d.ts.map +0 -1
- package/dist/backend-sqlite/backend.js.map +0 -1
- package/dist/backend-sqlite/index.d.ts +0 -2
- package/dist/backend-sqlite/index.d.ts.map +0 -1
- package/dist/backend-sqlite/index.js +0 -2
- package/dist/backend-sqlite/index.js.map +0 -1
- package/dist/backend-sqlite/sqlite.d.ts.map +0 -1
- package/dist/backend-sqlite/sqlite.js.map +0 -1
- package/dist/config/config.d.ts +0 -102
- package/dist/config/config.d.ts.map +0 -1
- package/dist/config/config.js +0 -29
- package/dist/config/config.js.map +0 -1
- package/dist/config/index.d.ts +0 -3
- package/dist/config/index.d.ts.map +0 -1
- package/dist/config/index.js +0 -2
- package/dist/config/index.js.map +0 -1
- package/dist/config.d.ts +0 -28
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -41
- package/dist/config.js.map +0 -1
- package/dist/core/backend-test-suite.d.ts +0 -22
- package/dist/core/backend-test-suite.d.ts.map +0 -1
- package/dist/core/backend-test-suite.js.map +0 -1
- package/dist/core/backend.d.ts.map +0 -1
- package/dist/core/backend.js.map +0 -1
- package/dist/core/backend.testsuite.d.ts +0 -21
- package/dist/core/backend.testsuite.d.ts.map +0 -1
- package/dist/core/backend.testsuite.js.map +0 -1
- package/dist/core/duration.js.map +0 -1
- package/dist/core/duration.test.js.map +0 -1
- package/dist/core/json.js.map +0 -1
- package/dist/core/result.js.map +0 -1
- package/dist/core/result.test.js.map +0 -1
- package/dist/core/retry.js.map +0 -1
- package/dist/core/retry.test.d.ts +0 -2
- package/dist/core/retry.test.d.ts.map +0 -1
- package/dist/core/retry.test.js +0 -36
- package/dist/core/retry.test.js.map +0 -1
- package/dist/core/schema.js.map +0 -1
- package/dist/core/step.js.map +0 -1
- package/dist/core/step.test.js.map +0 -1
- package/dist/core/workflow.js.map +0 -1
- package/dist/core/workflow.test.js.map +0 -1
- package/dist/execution/execution.d.ts.map +0 -1
- package/dist/execution/execution.js.map +0 -1
- package/dist/execution/execution.test.d.ts.map +0 -1
- package/dist/execution/execution.test.js.map +0 -1
- package/dist/global.d.ts +0 -62
- package/dist/global.d.ts.map +0 -1
- package/dist/global.js +0 -78
- package/dist/global.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/sdk/sdk.d.ts +0 -182
- package/dist/sdk/sdk.d.ts.map +0 -1
- package/dist/sdk/sdk.js.map +0 -1
- package/dist/sdk/sdk.test.d.ts +0 -2
- package/dist/sdk/sdk.test.d.ts.map +0 -1
- package/dist/sdk/sdk.test.js.map +0 -1
- package/dist/worker/worker.d.ts.map +0 -1
- package/dist/worker/worker.js.map +0 -1
- package/dist/worker/worker.test.js.map +0 -1
- /package/dist/{execution/execution.test.d.ts → execution.test.d.ts} +0 -0
- /package/dist/{worker/worker.test.d.ts → worker.test.d.ts} +0 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { WorkflowRegistry } from "./registry.js";
|
|
2
|
+
import { defineWorkflow } from "./workflow.js";
|
|
3
|
+
import { describe, expect, test } from "vitest";
|
|
4
|
+
describe("WorkflowRegistry", () => {
|
|
5
|
+
describe("register", () => {
|
|
6
|
+
test("registers a workflow without version", () => {
|
|
7
|
+
const registry = new WorkflowRegistry();
|
|
8
|
+
const workflow = createMockWorkflow("my-workflow");
|
|
9
|
+
registry.register(workflow);
|
|
10
|
+
expect(registry.get("my-workflow", null)).toBe(workflow);
|
|
11
|
+
});
|
|
12
|
+
test("registers a workflow with version", () => {
|
|
13
|
+
const registry = new WorkflowRegistry();
|
|
14
|
+
const workflow = createMockWorkflow("my-workflow", "v1");
|
|
15
|
+
registry.register(workflow);
|
|
16
|
+
expect(registry.get("my-workflow", "v1")).toBe(workflow);
|
|
17
|
+
});
|
|
18
|
+
test("registers multiple versions of the same workflow", () => {
|
|
19
|
+
const registry = new WorkflowRegistry();
|
|
20
|
+
const v1 = createMockWorkflow("my-workflow", "v1");
|
|
21
|
+
const v2 = createMockWorkflow("my-workflow", "v2");
|
|
22
|
+
registry.register(v1);
|
|
23
|
+
registry.register(v2);
|
|
24
|
+
expect(registry.get("my-workflow", "v1")).toBe(v1);
|
|
25
|
+
expect(registry.get("my-workflow", "v2")).toBe(v2);
|
|
26
|
+
});
|
|
27
|
+
test("registers different workflows with same version", () => {
|
|
28
|
+
const registry = new WorkflowRegistry();
|
|
29
|
+
const workflow1 = createMockWorkflow("workflow-a", "v1");
|
|
30
|
+
const workflow2 = createMockWorkflow("workflow-b", "v1");
|
|
31
|
+
registry.register(workflow1);
|
|
32
|
+
registry.register(workflow2);
|
|
33
|
+
expect(registry.get("workflow-a", "v1")).toBe(workflow1);
|
|
34
|
+
expect(registry.get("workflow-b", "v1")).toBe(workflow2);
|
|
35
|
+
});
|
|
36
|
+
test("throws when registering duplicate unversioned workflow", () => {
|
|
37
|
+
const registry = new WorkflowRegistry();
|
|
38
|
+
registry.register(createMockWorkflow("my-workflow"));
|
|
39
|
+
expect(() => {
|
|
40
|
+
registry.register(createMockWorkflow("my-workflow"));
|
|
41
|
+
}).toThrow('Workflow "my-workflow" is already registered');
|
|
42
|
+
});
|
|
43
|
+
test("throws when registering duplicate versioned workflow", () => {
|
|
44
|
+
const registry = new WorkflowRegistry();
|
|
45
|
+
registry.register(createMockWorkflow("my-workflow", "v1"));
|
|
46
|
+
expect(() => {
|
|
47
|
+
registry.register(createMockWorkflow("my-workflow", "v1"));
|
|
48
|
+
}).toThrow('Workflow "my-workflow" (version: v1) is already registered');
|
|
49
|
+
});
|
|
50
|
+
test("allows same name with different versions", () => {
|
|
51
|
+
const registry = new WorkflowRegistry();
|
|
52
|
+
const versioned = createMockWorkflow("my-workflow", "v1");
|
|
53
|
+
const unversioned = createMockWorkflow("my-workflow");
|
|
54
|
+
registry.register(versioned);
|
|
55
|
+
registry.register(unversioned);
|
|
56
|
+
expect(registry.get("my-workflow", "v1")).toBe(versioned);
|
|
57
|
+
expect(registry.get("my-workflow", null)).toBe(unversioned);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
describe("get", () => {
|
|
61
|
+
test("returns undefined for non-existent workflow", () => {
|
|
62
|
+
const registry = new WorkflowRegistry();
|
|
63
|
+
expect(registry.get("non-existent", null)).toBeUndefined();
|
|
64
|
+
});
|
|
65
|
+
test("returns undefined for wrong version", () => {
|
|
66
|
+
const registry = new WorkflowRegistry();
|
|
67
|
+
registry.register(createMockWorkflow("my-workflow", "v1"));
|
|
68
|
+
expect(registry.get("my-workflow", "v2")).toBeUndefined();
|
|
69
|
+
expect(registry.get("my-workflow", null)).toBeUndefined();
|
|
70
|
+
});
|
|
71
|
+
test("returns undefined for versioned lookup on unversioned workflow", () => {
|
|
72
|
+
const registry = new WorkflowRegistry();
|
|
73
|
+
registry.register(createMockWorkflow("my-workflow"));
|
|
74
|
+
expect(registry.get("my-workflow", "v1")).toBeUndefined();
|
|
75
|
+
});
|
|
76
|
+
test("returns the registered workflow", () => {
|
|
77
|
+
const registry = new WorkflowRegistry();
|
|
78
|
+
const workflow = createMockWorkflow("my-workflow");
|
|
79
|
+
registry.register(workflow);
|
|
80
|
+
expect(registry.get("my-workflow", null)).toBe(workflow);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
describe("getAll", () => {
|
|
84
|
+
test("returns all registered workflows", () => {
|
|
85
|
+
const registry = new WorkflowRegistry();
|
|
86
|
+
const a = createMockWorkflow("workflow-a");
|
|
87
|
+
const b = createMockWorkflow("workflow-b", "v1");
|
|
88
|
+
const c = createMockWorkflow("workflow-a", "v2");
|
|
89
|
+
registry.register(a);
|
|
90
|
+
registry.register(b);
|
|
91
|
+
registry.register(c);
|
|
92
|
+
const all = registry.getAll();
|
|
93
|
+
expect(all).toHaveLength(3);
|
|
94
|
+
expect(all).toEqual(expect.arrayContaining([a, b, c]));
|
|
95
|
+
});
|
|
96
|
+
test("returns empty array when none registered", () => {
|
|
97
|
+
const registry = new WorkflowRegistry();
|
|
98
|
+
expect(registry.getAll()).toEqual([]);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
function createMockWorkflow(name, version) {
|
|
103
|
+
return defineWorkflow({
|
|
104
|
+
name,
|
|
105
|
+
...(version && { version }),
|
|
106
|
+
}, async () => {
|
|
107
|
+
// no-op
|
|
108
|
+
});
|
|
109
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Backend, CancelWorkflowRunParams, ClaimWorkflowRunParams, CreateStepAttemptParams, CreateWorkflowRunParams, GetStepAttemptParams, GetWorkflowRunParams, ExtendWorkflowRunLeaseParams, ListStepAttemptsParams, ListWorkflowRunsParams, PaginatedResponse, FailStepAttemptParams, CompleteStepAttemptParams, FailWorkflowRunParams, CompleteWorkflowRunParams, SleepWorkflowRunParams
|
|
2
|
-
|
|
1
|
+
import { Backend, CancelWorkflowRunParams, ClaimWorkflowRunParams, CreateStepAttemptParams, CreateWorkflowRunParams, GetStepAttemptParams, GetWorkflowRunParams, ExtendWorkflowRunLeaseParams, ListStepAttemptsParams, ListWorkflowRunsParams, PaginatedResponse, FailStepAttemptParams, CompleteStepAttemptParams, FailWorkflowRunParams, CompleteWorkflowRunParams, SleepWorkflowRunParams } from "../backend.js";
|
|
2
|
+
import { StepAttempt } from "../core/step.js";
|
|
3
|
+
import { WorkflowRun } from "../core/workflow.js";
|
|
3
4
|
interface BackendSqliteOptions {
|
|
4
5
|
namespaceId?: string;
|
|
5
6
|
runMigrations?: boolean;
|
|
@@ -15,9 +16,12 @@ export declare class BackendSqlite implements Backend {
|
|
|
15
16
|
* Create and initialize a new BackendSqlite instance. This will
|
|
16
17
|
* automatically run migrations on startup unless `runMigrations` is set to
|
|
17
18
|
* false.
|
|
19
|
+
* @param path - Database path
|
|
20
|
+
* @param options - Backend options
|
|
21
|
+
* @returns A connected backend instance
|
|
18
22
|
*/
|
|
19
|
-
static connect(path
|
|
20
|
-
stop(): void
|
|
23
|
+
static connect(path: string, options?: BackendSqliteOptions): BackendSqlite;
|
|
24
|
+
stop(): Promise<void>;
|
|
21
25
|
createWorkflowRun(params: CreateWorkflowRunParams): Promise<WorkflowRun>;
|
|
22
26
|
getWorkflowRun(params: GetWorkflowRunParams): Promise<WorkflowRun | null>;
|
|
23
27
|
claimWorkflowRun(params: ClaimWorkflowRunParams): Promise<WorkflowRun | null>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../sqlite/backend.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,OAAO,EACP,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,EACpB,oBAAoB,EACpB,4BAA4B,EAC5B,sBAAsB,EACtB,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,yBAAyB,EACzB,sBAAsB,EACvB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAgBlD,UAAU,oBAAoB;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,qBAAa,aAAc,YAAW,OAAO;IAC3C,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO;IAKP;;;;;;;OAOG;IACH,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,aAAa;IAiBrE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,iBAAiB,CACrB,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,WAAW,CAAC;IAgDvB,cAAc,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAenE,gBAAgB,CACpB,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IA0FxB,sBAAsB,CAC1B,MAAM,EAAE,4BAA4B,GACnC,OAAO,CAAC,WAAW,CAAC;IAmCjB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,WAAW,CAAC;IAoCtE,mBAAmB,CACvB,MAAM,EAAE,yBAAyB,GAChC,OAAO,CAAC,WAAW,CAAC;IAyCjB,eAAe,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,WAAW,CAAC;IA+DpE,iBAAiB,CACrB,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,WAAW,CAAC;IAuDvB,gBAAgB,CACd,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAgE1C,gBAAgB,CACd,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAmE1C,OAAO,CAAC,wBAAwB;IAyC1B,iBAAiB,CACrB,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,WAAW,CAAC;IAwCvB,cAAc,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAenE,mBAAmB,CACvB,MAAM,EAAE,yBAAyB,GAChC,OAAO,CAAC,WAAW,CAAC;IA0DjB,eAAe,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,WAAW,CAAC;CAyD3E"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { DEFAULT_NAMESPACE_ID, } from "../backend.js";
|
|
2
|
+
import { DEFAULT_RETRY_POLICY } from "../core/retry.js";
|
|
3
|
+
import { newDatabase, migrate, generateUUID, now, addMilliseconds, toJSON, fromJSON, toISO, fromISO, } from "./sqlite.js";
|
|
4
|
+
const DEFAULT_PAGINATION_PAGE_SIZE = 100;
|
|
4
5
|
/**
|
|
5
6
|
* Manages a connection to a SQLite database for workflow operations.
|
|
6
7
|
*/
|
|
@@ -15,8 +16,11 @@ export class BackendSqlite {
|
|
|
15
16
|
* Create and initialize a new BackendSqlite instance. This will
|
|
16
17
|
* automatically run migrations on startup unless `runMigrations` is set to
|
|
17
18
|
* false.
|
|
19
|
+
* @param path - Database path
|
|
20
|
+
* @param options - Backend options
|
|
21
|
+
* @returns A connected backend instance
|
|
18
22
|
*/
|
|
19
|
-
static connect(path
|
|
23
|
+
static connect(path, options) {
|
|
20
24
|
const { namespaceId, runMigrations } = {
|
|
21
25
|
namespaceId: DEFAULT_NAMESPACE_ID,
|
|
22
26
|
runMigrations: true,
|
|
@@ -28,7 +32,8 @@ export class BackendSqlite {
|
|
|
28
32
|
}
|
|
29
33
|
return new BackendSqlite(db, namespaceId);
|
|
30
34
|
}
|
|
31
|
-
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
36
|
+
async stop() {
|
|
32
37
|
this.db.close();
|
|
33
38
|
}
|
|
34
39
|
async createWorkflowRun(params) {
|
|
@@ -305,12 +310,12 @@ export class BackendSqlite {
|
|
|
305
310
|
cursor = decodeCursor(before);
|
|
306
311
|
}
|
|
307
312
|
const order = before
|
|
308
|
-
? `ORDER BY "created_at"
|
|
309
|
-
: `ORDER BY "created_at"
|
|
313
|
+
? `ORDER BY "created_at" ASC, "id" ASC`
|
|
314
|
+
: `ORDER BY "created_at" DESC, "id" DESC`;
|
|
310
315
|
let query;
|
|
311
316
|
let queryParams;
|
|
312
317
|
if (cursor) {
|
|
313
|
-
const op = after ? "
|
|
318
|
+
const op = after ? "<" : ">";
|
|
314
319
|
query = `
|
|
315
320
|
SELECT *
|
|
316
321
|
FROM "workflow_runs"
|
|
@@ -551,6 +556,12 @@ export class BackendSqlite {
|
|
|
551
556
|
}
|
|
552
557
|
}
|
|
553
558
|
// Conversion functions
|
|
559
|
+
/**
|
|
560
|
+
* Convert a database row to a WorkflowRun.
|
|
561
|
+
* @param row - Workflow run row
|
|
562
|
+
* @returns Workflow run
|
|
563
|
+
* @throws {Error} If required fields are missing
|
|
564
|
+
*/
|
|
554
565
|
function rowToWorkflowRun(row) {
|
|
555
566
|
const createdAt = fromISO(row.created_at);
|
|
556
567
|
const updatedAt = fromISO(row.updated_at);
|
|
@@ -585,6 +596,12 @@ function rowToWorkflowRun(row) {
|
|
|
585
596
|
updatedAt,
|
|
586
597
|
};
|
|
587
598
|
}
|
|
599
|
+
/**
|
|
600
|
+
* Convert a database row to a StepAttempt.
|
|
601
|
+
* @param row - Step attempt row
|
|
602
|
+
* @returns Step attempt
|
|
603
|
+
* @throws {Error} If required fields are missing
|
|
604
|
+
*/
|
|
588
605
|
function rowToStepAttempt(row) {
|
|
589
606
|
const createdAt = fromISO(row.created_at);
|
|
590
607
|
const updatedAt = fromISO(row.updated_at);
|
|
@@ -614,9 +631,19 @@ function rowToStepAttempt(row) {
|
|
|
614
631
|
updatedAt,
|
|
615
632
|
};
|
|
616
633
|
}
|
|
634
|
+
/**
|
|
635
|
+
* Encode a pagination cursor to a string.
|
|
636
|
+
* @param item - Cursor data
|
|
637
|
+
* @returns Encoded cursor
|
|
638
|
+
*/
|
|
617
639
|
function encodeCursor(item) {
|
|
618
640
|
return Buffer.from(JSON.stringify({ createdAt: item.createdAt, id: item.id })).toString("base64");
|
|
619
641
|
}
|
|
642
|
+
/**
|
|
643
|
+
* Decode a pagination cursor from a string.
|
|
644
|
+
* @param cursor - Encoded cursor
|
|
645
|
+
* @returns Cursor data
|
|
646
|
+
*/
|
|
620
647
|
function decodeCursor(cursor) {
|
|
621
648
|
const decoded = Buffer.from(cursor, "base64").toString("utf8");
|
|
622
649
|
const parsed = JSON.parse(decoded);
|
|
@@ -625,4 +652,3 @@ function decodeCursor(cursor) {
|
|
|
625
652
|
id: parsed.id,
|
|
626
653
|
};
|
|
627
654
|
}
|
|
628
|
-
//# sourceMappingURL=backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.test.d.ts","sourceRoot":"","sources":["../../sqlite/backend.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { testBackend } from "../internal.js";
|
|
2
|
+
import { BackendSqlite } from "./backend.js";
|
|
3
|
+
import assert from "node:assert";
|
|
4
|
+
import { randomUUID } from "node:crypto";
|
|
5
|
+
import { unlinkSync, existsSync } from "node:fs";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { test, describe, afterAll } from "vitest";
|
|
9
|
+
test("it is a test file (workaround for sonarjs/no-empty-test-file linter)", () => {
|
|
10
|
+
assert.ok(true);
|
|
11
|
+
});
|
|
12
|
+
describe("BackendSqlite (in-memory)", () => {
|
|
13
|
+
testBackend({
|
|
14
|
+
setup: () => {
|
|
15
|
+
return Promise.resolve(BackendSqlite.connect(":memory:", {
|
|
16
|
+
namespaceId: randomUUID(),
|
|
17
|
+
}));
|
|
18
|
+
},
|
|
19
|
+
teardown: async (backend) => {
|
|
20
|
+
await backend.stop();
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
describe("BackendSqlite (file-based)", () => {
|
|
25
|
+
const testDbPath = path.join(tmpdir(), `openworkflow-test-${randomUUID()}.db`);
|
|
26
|
+
afterAll(() => {
|
|
27
|
+
const walPath = `${testDbPath}-wal`;
|
|
28
|
+
const shmPath = `${testDbPath}-shm`;
|
|
29
|
+
// clean up the test database, WAL, and SHM files if they exist
|
|
30
|
+
if (existsSync(testDbPath)) {
|
|
31
|
+
unlinkSync(testDbPath);
|
|
32
|
+
}
|
|
33
|
+
if (existsSync(walPath)) {
|
|
34
|
+
unlinkSync(walPath);
|
|
35
|
+
}
|
|
36
|
+
if (existsSync(shmPath)) {
|
|
37
|
+
unlinkSync(shmPath);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
testBackend({
|
|
41
|
+
setup: () => {
|
|
42
|
+
return Promise.resolve(BackendSqlite.connect(testDbPath, {
|
|
43
|
+
namespaceId: randomUUID(),
|
|
44
|
+
}));
|
|
45
|
+
},
|
|
46
|
+
teardown: async (backend) => {
|
|
47
|
+
await backend.stop();
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite driver for OpenWorkflow using the Drizzle-style API.
|
|
3
|
+
*
|
|
4
|
+
* This module provides a `sqlite()` function that creates a driver
|
|
5
|
+
* for connecting to SQLite databases.
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { openworkflow } from 'openworkflow';
|
|
9
|
+
* import { sqlite } from 'openworkflow/sqlite';
|
|
10
|
+
*
|
|
11
|
+
* // In-memory database (great for testing)
|
|
12
|
+
* const ow = await openworkflow(sqlite(':memory:'));
|
|
13
|
+
*
|
|
14
|
+
* // File-based database
|
|
15
|
+
* const ow = await openworkflow(sqlite('./data/workflow.db'));
|
|
16
|
+
*
|
|
17
|
+
* // With configuration options
|
|
18
|
+
* const ow = await openworkflow(sqlite({
|
|
19
|
+
* path: './data/workflow.db',
|
|
20
|
+
* namespace: 'my-app',
|
|
21
|
+
* runMigrations: true,
|
|
22
|
+
* }));
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
import type { Backend, Driver, DriverConfig } from "openworkflow/internal";
|
|
26
|
+
/**
|
|
27
|
+
* SQLite-specific driver configuration.
|
|
28
|
+
*/
|
|
29
|
+
export interface SqliteDriverConfig extends DriverConfig {
|
|
30
|
+
/**
|
|
31
|
+
* Path to the SQLite database file.
|
|
32
|
+
* Use ':memory:' for an in-memory database.
|
|
33
|
+
*/
|
|
34
|
+
path?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Existing SQLite database instance.
|
|
37
|
+
* If provided, the driver will use this database instead of creating a new one.
|
|
38
|
+
*/
|
|
39
|
+
database?: SqliteDatabase;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Interface for SQLite database instance.
|
|
43
|
+
* This matches the node:sqlite DatabaseSync interface.
|
|
44
|
+
*/
|
|
45
|
+
export interface SqliteDatabase {
|
|
46
|
+
close(): void;
|
|
47
|
+
exec(sql: string): void;
|
|
48
|
+
prepare(sql: string): any;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* SQLite driver instance.
|
|
52
|
+
*/
|
|
53
|
+
export interface SqliteDriver extends Driver {
|
|
54
|
+
readonly dialect: "sqlite";
|
|
55
|
+
readonly $client: SqliteDatabase | undefined;
|
|
56
|
+
createBackend(): Backend;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Creates a SQLite driver for OpenWorkflow.
|
|
60
|
+
*
|
|
61
|
+
* This function follows the Drizzle ORM pattern and supports multiple
|
|
62
|
+
* calling conventions:
|
|
63
|
+
* @param config - Database path or configuration object
|
|
64
|
+
* @returns A SqliteDriver instance
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* // With database path
|
|
68
|
+
* sqlite('./data/workflow.db')
|
|
69
|
+
* sqlite(':memory:')
|
|
70
|
+
*
|
|
71
|
+
* // With config object
|
|
72
|
+
* sqlite({
|
|
73
|
+
* path: './data/workflow.db',
|
|
74
|
+
* namespace: 'my-app',
|
|
75
|
+
* })
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export declare function sqlite(config: string | SqliteDriverConfig): SqliteDriver;
|
|
79
|
+
//# sourceMappingURL=driver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../sqlite/driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE3E;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,YAAY;IACtD;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,YAAa,SAAQ,MAAM;IAC1C,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,CAAC;IAC7C,aAAa,IAAI,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,GAAG,YAAY,CAqExE"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a SQLite driver for OpenWorkflow.
|
|
3
|
+
*
|
|
4
|
+
* This function follows the Drizzle ORM pattern and supports multiple
|
|
5
|
+
* calling conventions:
|
|
6
|
+
* @param config - Database path or configuration object
|
|
7
|
+
* @returns A SqliteDriver instance
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* // With database path
|
|
11
|
+
* sqlite('./data/workflow.db')
|
|
12
|
+
* sqlite(':memory:')
|
|
13
|
+
*
|
|
14
|
+
* // With config object
|
|
15
|
+
* sqlite({
|
|
16
|
+
* path: './data/workflow.db',
|
|
17
|
+
* namespace: 'my-app',
|
|
18
|
+
* })
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export function sqlite(config) {
|
|
22
|
+
// Normalize config
|
|
23
|
+
const normalizedConfig = typeof config === "string" ? { path: config } : config;
|
|
24
|
+
// Store the database reference (will be set on createBackend)
|
|
25
|
+
let databaseRef = normalizedConfig.database;
|
|
26
|
+
return {
|
|
27
|
+
dialect: "sqlite",
|
|
28
|
+
get $client() {
|
|
29
|
+
return databaseRef;
|
|
30
|
+
},
|
|
31
|
+
createBackend() {
|
|
32
|
+
// Dynamically import BackendSqlite to avoid requiring the sqlite
|
|
33
|
+
// package as a direct dependency of the openworkflow package
|
|
34
|
+
// Note: We use require here because sqlite is synchronous
|
|
35
|
+
// Determine the database path
|
|
36
|
+
const databasePath = normalizedConfig.path;
|
|
37
|
+
if (!databasePath && !normalizedConfig.database) {
|
|
38
|
+
throw new Error("SQLite driver requires either a database path or an existing database. " +
|
|
39
|
+
"Provide `path` or `database` in the config.");
|
|
40
|
+
}
|
|
41
|
+
// If we have an existing database, we need to handle it differently
|
|
42
|
+
if (!databasePath) {
|
|
43
|
+
throw new Error("Using an existing SQLite database is not yet supported. " +
|
|
44
|
+
"Please provide a database path via the `path` option.");
|
|
45
|
+
}
|
|
46
|
+
// Import and create the backend synchronously
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
48
|
+
const { BackendSqlite } = require("@openworkflow/backend-sqlite");
|
|
49
|
+
const options = {
|
|
50
|
+
runMigrations: normalizedConfig.runMigrations ?? true,
|
|
51
|
+
};
|
|
52
|
+
if (normalizedConfig.namespace) {
|
|
53
|
+
options.namespaceId = normalizedConfig.namespace;
|
|
54
|
+
}
|
|
55
|
+
const backend = BackendSqlite.connect(databasePath, options);
|
|
56
|
+
// Store database reference for $client getter
|
|
57
|
+
// Note: BackendSqlite doesn't expose the database, so this remains undefined
|
|
58
|
+
databaseRef = undefined;
|
|
59
|
+
return backend;
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite driver for OpenWorkflow.
|
|
3
|
+
* @example
|
|
4
|
+
* ```ts
|
|
5
|
+
* import { openworkflow } from 'openworkflow';
|
|
6
|
+
* import { sqlite } from 'openworkflow/sqlite';
|
|
7
|
+
*
|
|
8
|
+
* const ow = await openworkflow(sqlite(':memory:'));
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export { sqlite } from "./driver.js";
|
|
12
|
+
export type { SqliteDriver, SqliteDriverConfig, SqliteDatabase, } from "./driver.js";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../sqlite/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EACV,YAAY,EACZ,kBAAkB,EAClB,cAAc,GACf,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite driver for OpenWorkflow.
|
|
3
|
+
* @example
|
|
4
|
+
* ```ts
|
|
5
|
+
* import { openworkflow } from 'openworkflow';
|
|
6
|
+
* import { sqlite } from 'openworkflow/sqlite';
|
|
7
|
+
*
|
|
8
|
+
* const ow = await openworkflow(sqlite(':memory:'));
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export { sqlite } from "./driver.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../sqlite/internal.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./sqlite.js";
|
|
@@ -1,45 +1,61 @@
|
|
|
1
1
|
import { DatabaseSync } from "node:sqlite";
|
|
2
2
|
export type Database = DatabaseSync;
|
|
3
|
-
export declare const DEFAULT_DATABASE_PATH = ":memory:";
|
|
4
3
|
/**
|
|
5
4
|
* newDatabase creates a new SQLite database connection.
|
|
5
|
+
* @param path - Database file path (or ":memory:") for testing
|
|
6
|
+
* @returns SQLite database connection
|
|
6
7
|
*/
|
|
7
|
-
export declare function newDatabase(path
|
|
8
|
+
export declare function newDatabase(path: string): Database;
|
|
8
9
|
/**
|
|
9
10
|
* migrations returns the list of migration SQL statements.
|
|
11
|
+
* @returns Migration SQL statements
|
|
10
12
|
*/
|
|
11
13
|
export declare function migrations(): string[];
|
|
12
14
|
/**
|
|
13
15
|
* migrate applies pending migrations to the database. Does nothing if the
|
|
14
16
|
* database is already up to date.
|
|
17
|
+
* @param db - SQLite database
|
|
15
18
|
*/
|
|
16
19
|
export declare function migrate(db: Database): void;
|
|
17
20
|
/**
|
|
18
21
|
* Helper to generate UUIDs (SQLite doesn't have built-in UUID generation)
|
|
22
|
+
* @returns A UUID string
|
|
19
23
|
*/
|
|
20
24
|
export declare function generateUUID(): string;
|
|
21
25
|
/**
|
|
22
26
|
* Helper to get current timestamp in ISO8601 format
|
|
27
|
+
* @returns ISO8601 timestamp string
|
|
23
28
|
*/
|
|
24
29
|
export declare function now(): string;
|
|
25
30
|
/**
|
|
26
31
|
* Helper to add milliseconds to a date and return ISO8601 string
|
|
32
|
+
* @param date - ISO8601 date string
|
|
33
|
+
* @param ms - Milliseconds to add
|
|
34
|
+
* @returns Updated ISO8601 date string
|
|
27
35
|
*/
|
|
28
36
|
export declare function addMilliseconds(date: string, ms: number): string;
|
|
29
37
|
/**
|
|
30
38
|
* Helper to serialize JSON for SQLite storage
|
|
39
|
+
* @param value - Value to serialize
|
|
40
|
+
* @returns JSON string or null
|
|
31
41
|
*/
|
|
32
42
|
export declare function toJSON(value: unknown): string | null;
|
|
33
43
|
/**
|
|
34
44
|
* Helper to deserialize JSON from SQLite storage
|
|
45
|
+
* @param value - JSON string or null
|
|
46
|
+
* @returns Parsed value
|
|
35
47
|
*/
|
|
36
48
|
export declare function fromJSON(value: string | null): unknown;
|
|
37
49
|
/**
|
|
38
50
|
* Helper to convert Date to ISO8601 string for SQLite
|
|
51
|
+
* @param date - Date or null
|
|
52
|
+
* @returns ISO8601 date string or null
|
|
39
53
|
*/
|
|
40
54
|
export declare function toISO(date: Date | null): string | null;
|
|
41
55
|
/**
|
|
42
56
|
* Helper to convert ISO8601 string from SQLite to Date
|
|
57
|
+
* @param dateStr - ISO8601 date string or null
|
|
58
|
+
* @returns Date or null
|
|
43
59
|
*/
|
|
44
60
|
export declare function fromISO(dateStr: string | null): Date | null;
|
|
45
61
|
//# sourceMappingURL=sqlite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../sqlite/sqlite.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,MAAM,QAAQ,GAAG,YAAY,CAAC;AAEpC;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAQlD;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,EAAE,CA2IrC;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CAQ1C;AAyBD;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;;GAGG;AACH,wBAAgB,GAAG,IAAI,MAAM,CAE5B;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAIhE;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAE3D"}
|