@effectstream/db 0.100.14 → 0.100.16

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 ADDED
@@ -0,0 +1,108 @@
1
+ # @effectstream/db
2
+
3
+ The PostgreSQL (and PgLite) layer for EffectStream. Wraps `pg` with a
4
+ connection pool, ships every pgtyped-generated SQL query the runtime
5
+ needs, owns the snapshot loop, and provides a mutex needed for safe
6
+ single-threaded PgLite access.
7
+
8
+ - Pooled Postgres client plus every pgtyped query the runtime needs.
9
+ - Snapshot loop (`runSnapshotLoop`) and `acquireDBMutex` / `releaseDBMutex` for PgLite.
10
+ - Subpath scripts for in-memory PgLite, migrations, and version checks.
11
+ - `getConnection()` is the dominant entry point, ~31 call sites across the repo.
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ bun add @effectstream/db
17
+ # or
18
+ npm install @effectstream/db
19
+ ```
20
+
21
+ ## Standalone usage
22
+
23
+ You can drop `@effectstream/db` into any Node service that needs a
24
+ pooled Postgres client plus EffectStream's pgtyped queries. The most
25
+ common things you'd reach for:
26
+
27
+ ```typescript
28
+ import {
29
+ getConnection,
30
+ getBlockHeights,
31
+ getLatestProcessedBlockHeight,
32
+ } from "@effectstream/db";
33
+
34
+ const pool = getConnection({
35
+ host: process.env.PGHOST,
36
+ user: process.env.PGUSER,
37
+ password: process.env.PGPASSWORD,
38
+ database: process.env.PGDATABASE,
39
+ });
40
+
41
+ const client = await pool.connect();
42
+ try {
43
+ const heights = await getBlockHeights.run({ limit: 5 }, client);
44
+ console.log(heights);
45
+ } finally {
46
+ client.release();
47
+ }
48
+ ```
49
+
50
+ For PgLite (in-memory) the package ships `./start-pglite`,
51
+ `./apply-migrations`, `./db-wait`, `./pgtyped-update`, `./version` as
52
+ small executable subpaths — used directly by the orchestrator.
53
+
54
+ > **PgLite caveat:** PgLite is single-writer. Wrap PgLite-bound code in
55
+ > `acquireDBMutex(name)` / `releaseDBMutex(name)` so concurrent generators
56
+ > don't trample each other.
57
+
58
+ ## Inside EffectStream
59
+
60
+ `@effectstream/db` is the canonical access path. The runtime gets a
61
+ pooled client through `getConnection()`, every state-transition function
62
+ yields against pgtyped queries exported here, and the snapshot loop
63
+ (`runSnapshotLoop`) emits versioned `pg_dump` artifacts so a fresh node
64
+ can rejoin without re-syncing from genesis.
65
+
66
+ ## Key exports
67
+
68
+ Connection management (heavily used):
69
+
70
+ - `getConnection(creds?)`: pooled `Pool` singleton. Dominant entry point (~31 call sites across the repo).
71
+ - `acquireDBMutex(name, priority?)` and `releaseDBMutex(name)` coordinate PgLite access; ~7 call sites each.
72
+ - `waitUntilFree()` — companion to the mutex.
73
+ - `getPersistentConnection(creds)` returns a non-pooled `Client` for long-lived listeners.
74
+
75
+ Queries (pgtyped-generated, shipped under one umbrella):
76
+
77
+ - Block bookkeeping: `getBlockHeights`, `getBlockByHash`, `blockHeightDone`, `saveLastBlock`, `getLatestProcessedBlockHeight`.
78
+ - Achievements: `getAchievementProgress`, `setAchievementProgress`.
79
+ - Re-exports of `*.queries.ts` for statistics, nonces, rollup inputs, accounts, events, sync protocol pages, primitives, system, tables.
80
+
81
+ Snapshots:
82
+
83
+ - `runSnapshotLoop` — periodic `pg_dump` of synced state.
84
+ - `createSnapshot`: single-shot snapshot helper.
85
+ - `SnapshotConfig`, `SnapshotRetentionConfig`: config types.
86
+
87
+ Dynamic table / event helpers:
88
+
89
+ - `createDynamicTables` registers tables a primitive wants to own.
90
+ - `createIndexesForEvents` creates pgtyped indexes for app events; `registerEventTypes` records each event's topic/name in the database.
91
+
92
+ Subpath entry points (executable scripts):
93
+
94
+ - `@effectstream/db/start-pglite`: boot a PgLite instance.
95
+ - `@effectstream/db/apply-migrations` — apply SQL migrations against the active DB.
96
+ - `@effectstream/db/db-wait`: block until the DB accepts a connection.
97
+ - `@effectstream/db/pgtyped-update`: regenerate pgtyped types.
98
+ - `@effectstream/db/version` — print schema version.
99
+
100
+ ## Examples
101
+
102
+ - Real connection round-trip: [`src/pg-connection.test.ts`](./src/pg-connection.test.ts).
103
+ - Runnable: [`test/examples.test.ts`](./test/examples.test.ts).
104
+
105
+ ## Links
106
+
107
+ - Docs: https://effectstream.github.io/docs/packages/node/db
108
+ - Source: https://github.com/effectstream/effectstream/tree/main/packages/node-sdk/db
@@ -104,12 +104,15 @@ export function* getLastBlockHeight(
104
104
  dbConn: Client,
105
105
  ): Operation<number> {
106
106
  yield* acquireDBMutex("get-last-block-height");
107
- const v = versionInfo.is_empty
108
- ? 0
109
- : (yield* until(getLatestProcessedBlockHeight.run(undefined, dbConn)))[0]
110
- .block_height;
111
- releaseDBMutex("get-last-block-height");
112
- return v;
107
+ try {
108
+ if (versionInfo.is_empty) return 0;
109
+ const rows = yield* until(
110
+ getLatestProcessedBlockHeight.run(undefined, dbConn),
111
+ );
112
+ return rows[0]?.block_height ?? 0;
113
+ } finally {
114
+ releaseDBMutex("get-last-block-height");
115
+ }
113
116
  }
114
117
 
115
118
  export function* getVersionInfo(dbConn: Client): Operation<VersionInfo> {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effectstream/db",
3
- "version": "0.100.14",
3
+ "version": "0.100.16",
4
4
  "license": "MIT",
5
5
  "homepage": "https://effectstream.github.io/docs/",
6
6
  "repository": {
@@ -21,11 +21,11 @@
21
21
  "./version": "./migrations/system-version.ts"
22
22
  },
23
23
  "dependencies": {
24
- "@effectstream/coroutine": "0.100.14",
25
- "@effectstream/log": "0.100.14",
26
- "@effectstream/runtime": "0.100.14",
27
- "@effectstream/sync": "0.100.14",
28
- "@effectstream/utils": "0.100.14",
24
+ "@effectstream/coroutine": "0.100.16",
25
+ "@effectstream/log": "0.100.16",
26
+ "@effectstream/runtime": "0.100.16",
27
+ "@effectstream/sync": "0.100.16",
28
+ "@effectstream/utils": "0.100.16",
29
29
  "@electric-sql/pglite": "^0.3.14",
30
30
  "@pgtyped/runtime": "2.4.2",
31
31
  "@pgtyped/parser": "2.4.2",
@@ -0,0 +1,27 @@
1
+ // Examples for the README — verify the public surface resolves without
2
+ // touching an actual Postgres or PgLite instance.
3
+
4
+ import { test, expect } from "bun:test";
5
+ import * as db from "../src/mod.ts";
6
+
7
+ test("README: connection helpers are exported", () => {
8
+ expect(typeof db.getConnection).toBe("function");
9
+ expect(typeof db.getPersistentConnection).toBe("function");
10
+ });
11
+
12
+ test("README: PgLite mutex helpers are exported", () => {
13
+ expect(typeof db.acquireDBMutex).toBe("function");
14
+ expect(typeof db.releaseDBMutex).toBe("function");
15
+ expect(typeof db.waitUntilFree).toBe("function");
16
+ });
17
+
18
+ test("README: snapshot helpers are exported", () => {
19
+ expect(typeof db.createSnapshot).toBe("function");
20
+ expect(typeof db.runSnapshotLoop).toBe("function");
21
+ });
22
+
23
+ test("README: pgtyped query objects are exported", () => {
24
+ expect(db.getBlockHeights).toBeDefined();
25
+ expect(db.getBlockByHash).toBeDefined();
26
+ expect(db.getLatestProcessedBlockHeight).toBeDefined();
27
+ });