@drej/postgres 0.1.2

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/CHANGELOG.md ADDED
@@ -0,0 +1,41 @@
1
+ # @drej/postgres
2
+
3
+ ## 0.1.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [4c0ad93]
8
+ - Updated dependencies [b04f8eb]
9
+ - Updated dependencies [a971b7b]
10
+ - Updated dependencies [ce173be]
11
+ - Updated dependencies [86c2dde]
12
+ - Updated dependencies [82094ae]
13
+ - @drej/core@0.2.0
14
+
15
+ ## 0.1.1
16
+
17
+ ### Patch Changes
18
+
19
+ - 0ea4c33: Rename npm scope from `@drej/*` to `@drej/*` and add TSDoc to all public API surfaces.
20
+
21
+ - All workspace packages now published under `@drej/*` (e.g. `@drej/sqlite`, `@drej/postgres`)
22
+ - `DrejClient`, `WorkflowBuilder`, `SandboxStepBuilder`, `IStorageAdapter`, `LedgerEvent`, `SandboxOpts` and all their members now have hover documentation visible in VS Code
23
+
24
+ - Updated dependencies [0ea4c33]
25
+ - @drej/core@0.1.1
26
+
27
+ ## 0.1.0
28
+
29
+ ### Minor Changes
30
+
31
+ - 82e77fd: Introduce pluggable storage adapter system.
32
+
33
+ - `ILedger` renamed to `IStorageAdapter` with optional `connect()` and `close()` lifecycle methods
34
+ - `DrejClientOptions.adapter` accepts any `IStorageAdapter` implementation; `DrejClient` exposes matching `connect()` and `close()` methods
35
+ - New `@drej/postgres` package: `PostgresAdapter` backed by a user-supplied Postgres connection string; owns its schema and runs migrations on `connect()`
36
+
37
+ ### Patch Changes
38
+
39
+ - Updated dependencies [82e77fd]
40
+ - Updated dependencies [5d77498]
41
+ - @drej/core@0.1.0
package/package.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "@drej/postgres",
3
+ "version": "0.1.2",
4
+ "publishConfig": { "access": "public" },
5
+ "main": "./src/index.ts",
6
+ "dependencies": {
7
+ "postgres": "^3.4.5",
8
+ "@drej/core": "workspace:*"
9
+ },
10
+ "devDependencies": {
11
+ "bun-types": "latest",
12
+ "typescript": "latest"
13
+ }
14
+ }
package/src/adapter.ts ADDED
@@ -0,0 +1,87 @@
1
+ import postgres from "postgres";
2
+ import type { IStorageAdapter, LedgerEntry, LedgerEvent } from "@drej/core";
3
+ import { MIGRATION_SQL } from "./migrations";
4
+
5
+ type Row = {
6
+ run_id: string;
7
+ wf_name: string;
8
+ step_idx: number;
9
+ branch: number | null;
10
+ event: string;
11
+ payload: unknown;
12
+ error: string | null;
13
+ ts: string;
14
+ };
15
+
16
+ function rowToEntry(row: Row): LedgerEntry {
17
+ return {
18
+ runId: row.run_id,
19
+ workflowName: row.wf_name,
20
+ stepIndex: row.step_idx,
21
+ branch: row.branch ?? undefined,
22
+ event: row.event as LedgerEvent,
23
+ payload: row.payload ?? undefined,
24
+ error: row.error ?? undefined,
25
+ ts: Number(row.ts),
26
+ };
27
+ }
28
+
29
+ export class PostgresAdapter implements IStorageAdapter {
30
+ private readonly sql: ReturnType<typeof postgres>;
31
+
32
+ constructor(connectionString: string) {
33
+ this.sql = postgres(connectionString);
34
+ }
35
+
36
+ async connect(): Promise<void> {
37
+ await this.sql.unsafe(MIGRATION_SQL);
38
+ }
39
+
40
+ async close(): Promise<void> {
41
+ await this.sql.end();
42
+ }
43
+
44
+ async append(entry: LedgerEntry): Promise<void> {
45
+ await this.sql`
46
+ INSERT INTO drej_events (run_id, wf_name, step_idx, branch, event, payload, error, ts)
47
+ VALUES (
48
+ ${entry.runId},
49
+ ${entry.workflowName},
50
+ ${entry.stepIndex},
51
+ ${entry.branch ?? null},
52
+ ${entry.event},
53
+ ${entry.payload !== undefined ? JSON.stringify(entry.payload) : null},
54
+ ${entry.error ?? null},
55
+ ${entry.ts}
56
+ )
57
+ `;
58
+ }
59
+
60
+ async readAll(workflowName: string, runId: string): Promise<LedgerEntry[]> {
61
+ const rows = await this.sql<Row[]>`
62
+ SELECT run_id, wf_name, step_idx, branch, event, payload, error, ts
63
+ FROM drej_events
64
+ WHERE wf_name = ${workflowName} AND run_id = ${runId}
65
+ ORDER BY ts ASC
66
+ `;
67
+ return rows.map(rowToEntry);
68
+ }
69
+
70
+ async lastCheckpoint(workflowName: string, runId: string): Promise<LedgerEntry | null> {
71
+ const rows = await this.sql<Row[]>`
72
+ SELECT run_id, wf_name, step_idx, branch, event, payload, error, ts
73
+ FROM drej_events
74
+ WHERE wf_name = ${workflowName} AND run_id = ${runId} AND event = 'checkpoint'
75
+ ORDER BY ts DESC
76
+ LIMIT 1
77
+ `;
78
+ return rows.length ? rowToEntry(rows[0]) : null;
79
+ }
80
+
81
+ async listRuns(workflowName: string): Promise<string[]> {
82
+ const rows = await this.sql<{ run_id: string }[]>`
83
+ SELECT DISTINCT run_id FROM drej_events WHERE wf_name = ${workflowName}
84
+ `;
85
+ return rows.map((r) => r.run_id);
86
+ }
87
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export { PostgresAdapter } from "./adapter";
@@ -0,0 +1,16 @@
1
+ export const MIGRATION_SQL = `
2
+ CREATE TABLE IF NOT EXISTS drej_events (
3
+ id BIGSERIAL PRIMARY KEY,
4
+ run_id TEXT NOT NULL,
5
+ wf_name TEXT NOT NULL,
6
+ step_idx INTEGER NOT NULL,
7
+ branch INTEGER,
8
+ event TEXT NOT NULL,
9
+ payload JSONB,
10
+ error TEXT,
11
+ ts BIGINT NOT NULL
12
+ );
13
+
14
+ CREATE INDEX IF NOT EXISTS drej_events_run_id ON drej_events(run_id);
15
+ CREATE INDEX IF NOT EXISTS drej_events_wf_name ON drej_events(wf_name);
16
+ `;
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "noEmit": true,
8
+ "skipLibCheck": true,
9
+ "allowImportingTsExtensions": true,
10
+ "types": ["bun-types"]
11
+ },
12
+ "include": ["src"]
13
+ }