okmodel 0.0.0 → 0.1.1

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.
Files changed (147) hide show
  1. package/README.md +246 -1
  2. package/dist/adapters/capabilities.d.ts +62 -0
  3. package/dist/adapters/error.d.ts +91 -0
  4. package/dist/adapters/failure.d.ts +39 -0
  5. package/dist/adapters/pg/batch.d.ts +36 -0
  6. package/dist/adapters/pg/call.d.ts +59 -0
  7. package/dist/adapters/pg/pglite.d.ts +21 -0
  8. package/dist/adapters/pg/postgres-extra.d.ts +43 -0
  9. package/dist/adapters/pg/postgresjs.d.ts +95 -0
  10. package/dist/adapters/pg/result.d.ts +30 -0
  11. package/dist/contracts/catalog/build.d.ts +18 -0
  12. package/dist/contracts/catalog/document.d.ts +79 -0
  13. package/dist/contracts/catalog/enum.d.ts +35 -0
  14. package/dist/contracts/catalog/identifier.d.ts +71 -0
  15. package/dist/contracts/catalog/identity.d.ts +98 -0
  16. package/dist/contracts/catalog/index.d.ts +11 -0
  17. package/dist/contracts/catalog/json.d.ts +17 -0
  18. package/dist/contracts/catalog/object.d.ts +142 -0
  19. package/dist/contracts/catalog/order.d.ts +43 -0
  20. package/dist/contracts/catalog/rewrite.d.ts +18 -0
  21. package/dist/contracts/catalog/types.d.ts +292 -0
  22. package/dist/contracts/catalog/words.d.ts +13 -0
  23. package/dist/contracts/connection.d.ts +33 -0
  24. package/dist/contracts/driver.d.ts +163 -0
  25. package/dist/contracts/error.d.ts +298 -0
  26. package/dist/contracts/index.d.ts +11 -0
  27. package/dist/contracts/index.js +16 -0
  28. package/dist/contracts/internal.d.ts +15 -0
  29. package/dist/contracts/internal.js +68 -0
  30. package/dist/contracts/nearest.d.ts +15 -0
  31. package/dist/contracts/rows.d.ts +84 -0
  32. package/dist/contracts/sha256.d.ts +14 -0
  33. package/dist/contracts/utf8.d.ts +33 -0
  34. package/dist/dialects/pg/array-literal.d.ts +25 -0
  35. package/dist/dialects/pg/bool.d.ts +46 -0
  36. package/dist/dialects/pg/column.d.ts +386 -0
  37. package/dist/dialects/pg/compile.d.ts +81 -0
  38. package/dist/dialects/pg/custom.d.ts +21 -0
  39. package/dist/dialects/pg/ddl.d.ts +70 -0
  40. package/dist/dialects/pg/decimal.d.ts +62 -0
  41. package/dist/dialects/pg/declarations.d.ts +34 -0
  42. package/dist/dialects/pg/emit.d.ts +18 -0
  43. package/dist/dialects/pg/enum.d.ts +30 -0
  44. package/dist/dialects/pg/errors.d.ts +30 -0
  45. package/dist/dialects/pg/finite.d.ts +15 -0
  46. package/dist/dialects/pg/geometry.d.ts +55 -0
  47. package/dist/dialects/pg/index.d.ts +45 -0
  48. package/dist/dialects/pg/index.js +1821 -0
  49. package/dist/dialects/pg/integer.d.ts +96 -0
  50. package/dist/dialects/pg/introspect.d.ts +43 -0
  51. package/dist/dialects/pg/json.d.ts +43 -0
  52. package/dist/dialects/pg/keys.d.ts +32 -0
  53. package/dist/dialects/pg/misuse.d.ts +31 -0
  54. package/dist/dialects/pg/model.d.ts +71 -0
  55. package/dist/dialects/pg/namespace.d.ts +63 -0
  56. package/dist/dialects/pg/network.d.ts +28 -0
  57. package/dist/dialects/pg/operators.d.ts +71 -0
  58. package/dist/dialects/pg/ops/between.d.ts +10 -0
  59. package/dist/dialects/pg/ops/contains.d.ts +8 -0
  60. package/dist/dialects/pg/ops/endsWith.d.ts +8 -0
  61. package/dist/dialects/pg/ops/eq.d.ts +9 -0
  62. package/dist/dialects/pg/ops/every.d.ts +9 -0
  63. package/dist/dialects/pg/ops/gt.d.ts +9 -0
  64. package/dist/dialects/pg/ops/gte.d.ts +9 -0
  65. package/dist/dialects/pg/ops/has.d.ts +9 -0
  66. package/dist/dialects/pg/ops/ilike.d.ts +8 -0
  67. package/dist/dialects/pg/ops/inList.d.ts +9 -0
  68. package/dist/dialects/pg/ops/inc.d.ts +13 -0
  69. package/dist/dialects/pg/ops/like.d.ts +8 -0
  70. package/dist/dialects/pg/ops/lt.d.ts +9 -0
  71. package/dist/dialects/pg/ops/lte.d.ts +9 -0
  72. package/dist/dialects/pg/ops/none.d.ts +9 -0
  73. package/dist/dialects/pg/ops/not.d.ts +9 -0
  74. package/dist/dialects/pg/ops/notIn.d.ts +9 -0
  75. package/dist/dialects/pg/ops/or.d.ts +9 -0
  76. package/dist/dialects/pg/ops/startsWith.d.ts +8 -0
  77. package/dist/dialects/pg/quote.d.ts +24 -0
  78. package/dist/dialects/pg/range.d.ts +50 -0
  79. package/dist/dialects/pg/relations.d.ts +45 -0
  80. package/dist/dialects/pg/schema.d.ts +77 -0
  81. package/dist/dialects/pg/search.d.ts +23 -0
  82. package/dist/dialects/pg/table.d.ts +201 -0
  83. package/dist/dialects/pg/temporal.d.ts +211 -0
  84. package/dist/dialects/pg/text.d.ts +44 -0
  85. package/dist/dialects/pg/time.d.ts +46 -0
  86. package/dist/okm.js +2 -0
  87. package/dist/okmodel.js +2 -0
  88. package/dist/runtime/client.d.ts +47 -0
  89. package/dist/runtime/conflict.d.ts +38 -0
  90. package/dist/runtime/drift-detail.d.ts +32 -0
  91. package/dist/runtime/drift.d.ts +29 -0
  92. package/dist/runtime/include.d.ts +15 -0
  93. package/dist/runtime/pg/pglite.d.ts +25 -0
  94. package/dist/runtime/pg/pglite.js +48 -0
  95. package/dist/runtime/pg/postgresjs.d.ts +29 -0
  96. package/dist/runtime/pg/postgresjs.js +62 -0
  97. package/dist/runtime/plan.d.ts +167 -0
  98. package/dist/runtime/tx.d.ts +29 -0
  99. package/dist/runtime/types.d.ts +385 -0
  100. package/dist/runtime/write.d.ts +48 -0
  101. package/dist/shared/05w44d8g.js +1524 -0
  102. package/dist/shared/523ft3e8.js +171 -0
  103. package/dist/shared/8b04d28c.js +14 -0
  104. package/dist/shared/cn0n68ft.js +16 -0
  105. package/dist/shared/dkn3y60a.js +374 -0
  106. package/dist/shared/dynq16vb.js +81 -0
  107. package/dist/shared/fgqgsb5z.js +281 -0
  108. package/dist/shared/g5fhqmwe.js +188 -0
  109. package/dist/shared/gk7cs7sp.js +566 -0
  110. package/dist/shared/hadrfb9h.js +398 -0
  111. package/dist/shared/hd293j9g.js +98 -0
  112. package/dist/shared/j5cn2963.js +701 -0
  113. package/dist/shared/jjb7yht9.js +37 -0
  114. package/dist/shared/kprcwaha.js +30 -0
  115. package/dist/shared/m3ypagh5.js +347 -0
  116. package/dist/shared/mkjmqjv4.js +456 -0
  117. package/dist/shared/mtkwv8wx.js +18 -0
  118. package/dist/shared/ngk8gj61.js +40 -0
  119. package/dist/shared/p0cbr3g2.js +79 -0
  120. package/dist/shared/qk3hxfja.js +83 -0
  121. package/dist/shared/rgs0st28.js +1066 -0
  122. package/dist/shared/w8samvk1.js +18 -0
  123. package/dist/shared/x5x59srr.js +566 -0
  124. package/dist/shared/xqbhg6cn.js +119 -0
  125. package/dist/shared/xy79j5hq.js +177 -0
  126. package/dist/shared/y9m15dfv.js +888 -0
  127. package/dist/shared/ycwz42az.js +412 -0
  128. package/dist/shared/yd1kzwn2.js +148 -0
  129. package/dist/shared/zhc5vmgf.js +257 -0
  130. package/dist/tooling/cli.d.ts +1 -0
  131. package/dist/tooling/cli.js +193 -0
  132. package/dist/tooling/errors/registry.d.ts +33 -0
  133. package/dist/tooling/migrate/apply.d.ts +86 -0
  134. package/dist/tooling/migrate/commands.d.ts +21 -0
  135. package/dist/tooling/migrate/config.d.ts +48 -0
  136. package/dist/tooling/migrate/dev.d.ts +16 -0
  137. package/dist/tooling/migrate/equal.d.ts +15 -0
  138. package/dist/tooling/migrate/files.d.ts +19 -0
  139. package/dist/tooling/migrate/index.d.ts +7 -0
  140. package/dist/tooling/migrate/index.js +7 -0
  141. package/dist/tooling/migrate/plan.d.ts +76 -0
  142. package/dist/tooling/migrate/policy.d.ts +78 -0
  143. package/dist/tooling/migrate/project.d.ts +69 -0
  144. package/dist/tooling/migrate/status.d.ts +74 -0
  145. package/dist/tooling/migrate/values.d.ts +29 -0
  146. package/package.json +109 -7
  147. package/dist/index.js +0 -0
package/README.md CHANGED
@@ -1 +1,246 @@
1
- okmodel — work in progress
1
+ # OKModel
2
+
3
+ okmodel is a catalog-first TypeScript ORM, PostgreSQL first. Other SQL databases are the direction. Version 0.1 supports PostgreSQL only. The schema is the single source. Migrations and queries come from it.
4
+
5
+ Version 0.1.1. Apache-2.0.
6
+
7
+ ## Contents
8
+
9
+ - [Install](#install)
10
+ - [Quickstart](#quickstart)
11
+ - [Configure](#configure)
12
+ - [Schema](#schema)
13
+ - [Push](#push)
14
+ - [Reviewed migrations](#reviewed-migrations)
15
+ - [One client](#one-client)
16
+ - [Insert](#insert)
17
+ - [Find](#find)
18
+ - [Errors](#errors)
19
+ - [Close](#close)
20
+ - [Commands](#commands)
21
+ - [Roadmap](#roadmap)
22
+ - [Size](#size)
23
+ - [Docs](#docs)
24
+
25
+ ## Install
26
+
27
+ Install okmodel and the postgres.js driver.
28
+
29
+ ```sh
30
+ bun add okmodel postgres
31
+ ```
32
+
33
+ PGlite is the in-process driver.
34
+
35
+ ```sh
36
+ bun add okmodel @electric-sql/pglite
37
+ ```
38
+
39
+ okmodel has no runtime dependencies. The driver is a peer.
40
+
41
+ ## Quickstart
42
+
43
+ `DATABASE_URL` is a direct Postgres URL, not a pooler. The client, insert, find, and error blocks are one script, `run.ts`. `script.ts` is the `await using` form. The last block calls `db.close()`.
44
+
45
+ ### Configure
46
+
47
+ Point the CLI at the schema and at that URL.
48
+
49
+ `okmodel.config.ts`:
50
+
51
+ ```ts
52
+ import { defineConfig } from "okmodel/migrate";
53
+
54
+ const url = process.env.DATABASE_URL;
55
+ if (url === undefined || url.length === 0) {
56
+ throw new Error("DATABASE_URL is not set");
57
+ }
58
+
59
+ export default defineConfig({
60
+ schema: "./schema.ts",
61
+ database: url,
62
+ });
63
+ ```
64
+
65
+ ### Schema
66
+
67
+ `t.identity()` is the primary key. An insert omits the id, and the row that comes back carries it. Identity ids come back as strings by default. `t.identity({ as: "number" })` returns numbers. Push and reviewed migrations are two ways to do the same job: pick one per database.
68
+
69
+ Tested on PostgreSQL 15 to 18.
70
+
71
+ `schema.ts`:
72
+
73
+ ```ts
74
+ import { one, schema, table, t } from "okmodel/pg";
75
+
76
+ const authors = table("authors", {
77
+ id: t.identity(),
78
+ name: t.text().unique(),
79
+ });
80
+
81
+ const notes = table(
82
+ "notes",
83
+ {
84
+ id: t.identity(),
85
+ title: t.text(),
86
+ authorId: t.bigint().references("authors", { columns: ["id"] }),
87
+ },
88
+ { relations: { author: one("authors") } },
89
+ );
90
+
91
+ const tables = [authors, notes];
92
+
93
+ export default schema({ tables });
94
+ ```
95
+
96
+ ### Push
97
+
98
+ Create the tables with push, which is allowed because this target is not protected.
99
+
100
+ ```sh
101
+ bunx okm push
102
+ ```
103
+
104
+ A protected target refuses push. Production settings are in the [production checklist](https://github.com/omqkhafi/okmodel/blob/main/docs/production.md).
105
+
106
+ ### Reviewed migrations
107
+
108
+ Generate writes a SQL file and `.okm`, and apply runs that file later so you can read the migration first.
109
+
110
+ ```sh
111
+ bunx okm generate init
112
+ bunx okm migrate apply
113
+ ```
114
+
115
+ ### One client
116
+
117
+ This module is cached, so the process has one client.
118
+
119
+ `db.ts`:
120
+
121
+ ```ts
122
+ import { connect } from "okmodel/pg/postgresjs";
123
+
124
+ import schema from "./schema.ts";
125
+
126
+ const url = process.env.DATABASE_URL;
127
+ if (url === undefined || url.length === 0) throw new Error("DATABASE_URL is not set");
128
+
129
+ export const db = connect(url, { schema });
130
+ ```
131
+
132
+ ### Insert
133
+
134
+ Insert an author, then a note that points at the author's id.
135
+
136
+ ```ts
137
+ import { db } from "./db.ts";
138
+
139
+ const author = await db.authors.insert({ name: "Ada" });
140
+ const note = await db.notes.insert({
141
+ title: "hello",
142
+ authorId: author.id,
143
+ });
144
+ if (author.name !== "Ada" || note.title !== "hello" || author.id.length === 0) {
145
+ throw new Error("insert did not return the row");
146
+ }
147
+ ```
148
+
149
+ ### Find
150
+
151
+ Load that note and its author by the id the insert returned.
152
+
153
+ ```ts
154
+ const found = await db.notes.find({
155
+ where: { id: note.id },
156
+ limit: 5,
157
+ include: { author: true },
158
+ });
159
+ const row = found[0];
160
+ if (row?.title !== "hello" || row.author?.name !== "Ada") {
161
+ throw new Error("find did not return the note and its author");
162
+ }
163
+ ```
164
+
165
+ ### Errors
166
+
167
+ `safe` returns the `OkmError` instead of throwing when the author name is already used.
168
+
169
+ ```ts
170
+ import { OkmError, safe } from "okmodel";
171
+
172
+ const duplicate = await safe(db.authors.insert({ name: "Ada" }));
173
+ if (duplicate.ok || !(duplicate.error instanceof OkmError) || duplicate.error.kind !== "unique") {
174
+ throw new Error("expected an OkmError of kind unique");
175
+ }
176
+ ```
177
+
178
+ ### Close
179
+
180
+ A script exits when its queries finish. It does not need `close()` for that. `await using` closes the pool at the end of the block. `db.close()` is that call on a line you choose. A server keeps the client and its connections. A pool opened with `ssl` still waits out the driver's 30 second idle timer.
181
+
182
+ `script.ts`:
183
+
184
+ ```ts
185
+ import { connect } from "okmodel/pg/postgresjs";
186
+
187
+ import schema from "./schema.ts";
188
+
189
+ const url = process.env.DATABASE_URL;
190
+ if (url === undefined || url.length === 0) throw new Error("DATABASE_URL is not set");
191
+
192
+ await using db = connect(url, { schema });
193
+ const author = await db.authors.insert({ name: "Lin" });
194
+ if (author.name !== "Lin" || author.id.length === 0) {
195
+ throw new Error("insert did not return the row");
196
+ }
197
+ ```
198
+
199
+ ```ts
200
+ await db.close();
201
+ ```
202
+
203
+ ## Commands
204
+
205
+ | Command | What it does |
206
+ | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
207
+ | `okm build` | Validates the schema and writes `.okm/` (catalog, hash, emitted row types). `okm generate` writes those files too. |
208
+ | `okm check` | Reports a stale `renamedFrom` and a table file the schema does not import. |
209
+ | `okm generate [name]` | Writes a SQL migration and `.okm/`. The name defaults to `migration`. Prints `no changes` when the schema matches. |
210
+ | `okm dev` | Uses a target named `dev`, or creates a PGlite database in `.okm/dev-db`. It does not apply migrations or write the catalog. |
211
+ | `okm push` | Applies the schema directly. Refused when the target is protected. |
212
+ | `okm migrate plan <name>` | Prints the plan and its class. The name is required. |
213
+ | `okm migrate apply` | Replays migration files on the database. |
214
+ | `okm migrate status` | Prints version, catalog hash, and state for each target. |
215
+ | `okm --version` | Prints the package version. |
216
+
217
+ `okmodel` and `okm` are the same command.
218
+
219
+ ## Roadmap
220
+
221
+ - [x] 0.1 — Schema, queries, and migrations on PostgreSQL, with postgres.js and PGlite.
222
+ - [ ] 0.2 — Hidden and sensitive fields, validation, traits, tenancy, archive and restore, richer relations, presets, transactions, and operators for JSON, arrays, ranges, and search.
223
+ - [ ] 0.3 — Extensions, domains, functions, triggers, views, roles, and grants.
224
+ - [ ] 0.4 — Safer migration plans, backfill, drift checks, provisioning, reference data, and a testing package.
225
+ - [ ] 0.5 — A primary with replicas, read routing, and a reference app.
226
+
227
+ `okmodel/internal` has no stability promise. Names on that subpath can change or disappear in any release.
228
+
229
+ Each limit, with the version that lifts it, is in [known limits](https://github.com/omqkhafi/okmodel/blob/main/docs/known-limits.md).
230
+
231
+ ## Size
232
+
233
+ Measured on this release.
234
+
235
+ | | Minified | Gzip | Cold import |
236
+ | --------------------------------- | -------: | -----: | ----------: |
237
+ | Runtime entry | 5,525 | 2,042 | 1.758 ms |
238
+ | App startup (10 tables, one find) | 77,537 | 25,625 | 9.922 ms |
239
+
240
+ The rest of the measurements are in [size](https://github.com/omqkhafi/okmodel/blob/main/docs/size.md).
241
+
242
+ ## Docs
243
+
244
+ - [Quickstart](https://github.com/omqkhafi/okmodel/blob/main/docs/quickstart.md)
245
+ - [Production checklist](https://github.com/omqkhafi/okmodel/blob/main/docs/production.md)
246
+ - [Known limits](https://github.com/omqkhafi/okmodel/blob/main/docs/known-limits.md)
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Driver capability registry.
3
+ *
4
+ * The flags are data (spec §4). A helper reads them. Spec section 21 has no
5
+ * OKM11xx for a driver that lacks a flag: OKM1110 is the engine-version gate,
6
+ * and OKM1801 is a dialect mismatch. This module does not invent a code and
7
+ * does not throw for a missing flag.
8
+ */
9
+ import type { DriverCapabilities } from "../contracts/driver.js";
10
+ /** Capability names a caller can read. */
11
+ export declare const CAPABILITY_NAMES: readonly ["transactions", "stream", "listen", "cancel", "prepared", "describe"];
12
+ /** One name in {@link DriverCapabilities}. */
13
+ export type CapabilityName = (typeof CAPABILITY_NAMES)[number];
14
+ /**
15
+ * postgres.js execution flags.
16
+ *
17
+ * Interactive transactions, streaming, listen, cancel, and describe.
18
+ * Statements use the unnamed extended protocol so a plain execute is one
19
+ * round trip. Named prepares are a later opt-in.
20
+ */
21
+ export declare const POSTGRESJS_CAPABILITIES: {
22
+ readonly transactions: "interactive";
23
+ readonly stream: true;
24
+ readonly listen: true;
25
+ readonly cancel: true;
26
+ readonly prepared: "unnamed";
27
+ readonly describe: true;
28
+ };
29
+ /**
30
+ * PGlite execution flags.
31
+ *
32
+ * A pool of one with interactive transactions, listen, and describe.
33
+ * `cancel` is false: an in-flight statement cannot be aborted, and
34
+ * `statement_timeout` is not enforced.
35
+ */
36
+ export declare const PGLITE_CAPABILITIES: {
37
+ readonly transactions: "interactive";
38
+ readonly stream: false;
39
+ readonly listen: true;
40
+ readonly cancel: false;
41
+ readonly prepared: "unnamed";
42
+ readonly describe: true;
43
+ };
44
+ /**
45
+ * Reads one capability flag.
46
+ *
47
+ * @param flags - Declared capabilities
48
+ * @param name - Flag name
49
+ * @returns The flag value
50
+ */
51
+ export declare function readCapability<Name extends CapabilityName>(flags: DriverCapabilities, name: Name): DriverCapabilities[Name];
52
+ /**
53
+ * Reports whether a boolean capability is set.
54
+ *
55
+ * `transactions` and `prepared` are not boolean. Use {@link readCapability}
56
+ * for those.
57
+ *
58
+ * @param flags - Declared capabilities
59
+ * @param name - `stream`, `listen`, `cancel`, or `describe`
60
+ * @returns The flag
61
+ */
62
+ export declare function hasCapability(flags: DriverCapabilities, name: "stream" | "listen" | "cancel" | "describe"): boolean;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Errors an adapter throws.
3
+ *
4
+ * Database failures stay {@link DriverError}. The Postgres dialect maps that
5
+ * to {@link OkmError}. Acquire exhaustion is OKM1846 on {@link OkmError}:
6
+ * that code is the pool's own deadline (spec §15.2), not a SQLSTATE.
7
+ */
8
+ import { OkmError } from "../contracts/error.js";
9
+ import type { DriverErrorFields, DriverFailureKind } from "../contracts/driver.js";
10
+ /**
11
+ * A driver failure normalised to the contract fields.
12
+ *
13
+ * `batchIndex` is `null` except on a failed batch statement, where it is that
14
+ * statement's index. A commit failure (a deferred constraint) stays `null`.
15
+ */
16
+ export declare class DriverError extends Error {
17
+ /** SQLSTATE, when the server sent one. */
18
+ readonly sqlstate: string | undefined;
19
+ /** Constraint name, when the server sent one. */
20
+ readonly constraint: string | undefined;
21
+ /** Table name, when the server sent one. */
22
+ readonly table: string | undefined;
23
+ /** Column name, when the server sent one. */
24
+ readonly column: string | undefined;
25
+ /** Server detail line. */
26
+ readonly detail: string | undefined;
27
+ /** Driver or server error underneath. */
28
+ readonly cause: unknown;
29
+ /** Statement index inside a batch, or `null` when this is not that case. */
30
+ readonly batchIndex: number | null;
31
+ /** `timeout` or `cancelled`. Absent on a database error. */
32
+ readonly kind: DriverFailureKind | undefined;
33
+ /**
34
+ * @param message - Error text
35
+ * @param fields - Normalised fields
36
+ */
37
+ constructor(message: string, fields?: DriverErrorFields);
38
+ /**
39
+ * Same error with a batch index.
40
+ *
41
+ * @param batchIndex - Statement index, or `null` at commit
42
+ * @returns A new error when the index differs
43
+ */
44
+ at(batchIndex: number | null): DriverError;
45
+ }
46
+ /**
47
+ * An abort from the caller's `signal` (D124).
48
+ *
49
+ * @param cause - Underlying error, when one exists
50
+ * @returns Kind `cancelled`
51
+ */
52
+ export declare function cancelled(cause?: unknown): DriverError;
53
+ /**
54
+ * A statement, transaction, or batch deadline (D124).
55
+ *
56
+ * @param cause - Underlying error, when one exists
57
+ * @returns Kind `timeout`
58
+ */
59
+ export declare function timedOut(cause?: unknown): DriverError;
60
+ /**
61
+ * A commit was sent and its result never arrived (OKM1401 once mapped).
62
+ *
63
+ * @param cause - Underlying error, when one exists
64
+ * @returns Kind `outcome_unknown`, batch index `null`
65
+ */
66
+ export declare function outcomeUnknown(cause?: unknown): DriverError;
67
+ /**
68
+ * The pool did not hand out a connection within `timeouts.acquire`.
69
+ *
70
+ * @returns OKM1846, kind `timeout`
71
+ */
72
+ export declare function acquireTimeout(): OkmError;
73
+ /**
74
+ * Reads a string field from an unknown error object.
75
+ *
76
+ * @param error - Caught value
77
+ * @param key - Field name
78
+ * @returns The string, or `undefined`
79
+ */
80
+ export declare function errorField(error: unknown, key: string): string | undefined;
81
+ /**
82
+ * Maps a driver exception into {@link DriverError}.
83
+ *
84
+ * {@link OkmError} and {@link DriverError} pass through. A batch index on an
85
+ * existing {@link DriverError} is applied with {@link DriverError.at}.
86
+ *
87
+ * @param error - Caught value
88
+ * @param batchIndex - Statement index, or `null` at commit
89
+ * @returns A normalised error
90
+ */
91
+ export declare function mapDriverError(error: unknown, batchIndex?: number | null): unknown;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Driver-error constructors, loaded on the first failure.
3
+ *
4
+ * A successful `execute` does not import {@link import("./error.js")}.
5
+ */
6
+ type ErrorModule = typeof import("./error.js");
7
+ /**
8
+ * Loads driver-error constructors once.
9
+ *
10
+ * @returns The error module
11
+ */
12
+ export declare function driverErrors(): Promise<ErrorModule>;
13
+ /**
14
+ * Rejects with a closed-pool {@link import("./error.js").DriverError}.
15
+ *
16
+ * @param message - Error text
17
+ * @returns A rejected promise
18
+ */
19
+ export declare function rejectClosed(message?: string): Promise<never>;
20
+ /**
21
+ * Rejects with kind `cancelled`.
22
+ *
23
+ * @returns A rejected promise
24
+ */
25
+ export declare function rejectCancelled(): Promise<never>;
26
+ /**
27
+ * Rejects with kind `timeout`.
28
+ *
29
+ * @returns A rejected promise
30
+ */
31
+ export declare function rejectTimedOut(): Promise<never>;
32
+ /**
33
+ * Maps a caught driver exception.
34
+ *
35
+ * @param error - Caught value
36
+ * @returns A normalised error
37
+ */
38
+ export declare function mapFailure(error: unknown): Promise<unknown>;
39
+ export {};
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Atomic batch for an interactive connection.
3
+ *
4
+ * Statements run one at a time. A failure rolls the unit back. Inside an open
5
+ * transaction the unit is a savepoint and the outer transaction stays open
6
+ * (D124). A timeout stays kind `timeout`. An abort stays kind `cancelled`.
7
+ */
8
+ import type { ExecuteResult, Statement, WireValue } from "../../contracts/driver.js";
9
+ import type { Watch } from "./call.js";
10
+ /** A connection that can run the batch protocol. */
11
+ export type BatchSession = {
12
+ /** This driver can abort an in-flight statement. */
13
+ readonly canCancel: boolean;
14
+ /**
15
+ * Runs one statement.
16
+ *
17
+ * @param text - SQL
18
+ * @param params - Wire parameters
19
+ * @param watch - Shared deadline for the batch, when there is one
20
+ * @returns The statement result
21
+ */
22
+ query(text: string, params: readonly WireValue[] | undefined, watch: Watch | undefined): Promise<ExecuteResult>;
23
+ /** Reports whether a transaction is open on this connection. */
24
+ inTransaction(): boolean;
25
+ /** Forgets a transaction after a rollback that did not complete. */
26
+ abandon(): void;
27
+ };
28
+ /**
29
+ * Runs statements as one atomic unit.
30
+ *
31
+ * @param session - Connection to use
32
+ * @param statements - Statements in order
33
+ * @param watch - Deadline for the whole batch
34
+ * @returns One result per statement
35
+ */
36
+ export declare function runAtomicBatch(session: BatchSession, statements: readonly Statement[], watch: Watch | undefined): Promise<readonly ExecuteResult[]>;
@@ -0,0 +1,59 @@
1
+ /**
2
+ * One deadline for a call.
3
+ *
4
+ * Created only when the caller passed `signal` or `timeout`. A plain execute
5
+ * does not allocate one.
6
+ */
7
+ import type { DriverFailureKind, ExecuteOptions } from "../../contracts/driver.js";
8
+ /** A signal plus the reason it aborted. */
9
+ export type Watch = {
10
+ /** Aborts on the caller's signal or on the deadline. */
11
+ readonly signal: AbortSignal;
12
+ /** Stops the timer and drops the caller's listener. */
13
+ finish(): void;
14
+ /**
15
+ * Why {@link signal} aborted.
16
+ *
17
+ * `undefined` until it aborts.
18
+ */
19
+ reason(): DriverFailureKind | undefined;
20
+ };
21
+ /**
22
+ * Reports whether `options` carries a signal or a timeout.
23
+ *
24
+ * @param options - Per-call options
25
+ * @returns True when a {@link Watch} is required
26
+ */
27
+ export declare function needsWatch(options: ExecuteOptions | undefined): boolean;
28
+ /**
29
+ * Next transaction depth after one statement.
30
+ *
31
+ * Only a whole command matches, so `ROLLBACK TO SAVEPOINT` stays inside the
32
+ * transaction. Kept here so a read does not load the batch runner.
33
+ *
34
+ * @param depth - Depth before the statement
35
+ * @param text - Statement text
36
+ * @returns Depth after a successful statement
37
+ */
38
+ export declare function nextTransactionDepth(depth: number, text: string): number;
39
+ /**
40
+ * Opens a watch for one call.
41
+ *
42
+ * The caller has already rejected a pre-aborted signal and a non-positive
43
+ * timeout.
44
+ *
45
+ * @param options - Options that include a signal or a timeout
46
+ * @returns The watch. The caller must {@link Watch.finish} it
47
+ */
48
+ export declare function openWatch(options: ExecuteOptions): Watch;
49
+ /**
50
+ * Runs `fn` with a watch when the caller set a signal or a timeout.
51
+ *
52
+ * A plain call passes `undefined` and returns `fn`'s promise unchanged.
53
+ *
54
+ * @param closed - The pool has been closed
55
+ * @param options - Per-call options
56
+ * @param fn - Work that receives the watch
57
+ * @returns Whatever `fn` returns
58
+ */
59
+ export declare function runCall<T>(closed: boolean, options: ExecuteOptions | undefined, fn: (watch: Watch | undefined) => Promise<T>): Promise<T>;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * PGlite adapter (`okmodel/pg/pglite`).
3
+ *
4
+ * One database is a pool of one. `cancel` is false: a statement already
5
+ * running cannot be aborted. `@electric-sql/pglite` is a peer of this entry.
6
+ */
7
+ import type { DriverPool, DriverPoolConfig } from "../../contracts/driver.js";
8
+ export { hasCapability, PGLITE_CAPABILITIES as capabilities, readCapability, } from "../capabilities.js";
9
+ export { DriverError } from "../error.js";
10
+ /** Options for {@link open}. The pool size is always one. */
11
+ export type PgliteConfig = DriverPoolConfig & {
12
+ /** Data directory. `memory://` when omitted. */
13
+ readonly dataDir?: string;
14
+ };
15
+ /**
16
+ * Opens a PGlite pool of one.
17
+ *
18
+ * @param config - Data directory and acquire timeout. `max` is ignored
19
+ * @returns The pool
20
+ */
21
+ export declare function open(config?: PgliteConfig): Promise<DriverPool>;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Pool operations a read does not use: checkout, describe, and stream.
3
+ *
4
+ * Loaded on the first reserve, batch, describe, or stream.
5
+ */
6
+ import type { Sql } from "postgres";
7
+ import type { DescribeResult, DriverConnection, WireValue } from "../../contracts/driver.js";
8
+ import { type Canceller, type Counters, type NoticeBuffer } from "./postgresjs.js";
9
+ /** State `open` shares with a checkout. */
10
+ export type HeldPool = {
11
+ readonly sql: Sql;
12
+ readonly acquireMs: number | undefined;
13
+ readonly counters: Counters;
14
+ readonly isClosed: () => boolean;
15
+ readonly notices: NoticeBuffer;
16
+ readonly named: boolean;
17
+ readonly poolInflight: Set<Canceller>;
18
+ };
19
+ /**
20
+ * Checks out one connection and clears it on release.
21
+ *
22
+ * @param pool - The open pool
23
+ * @returns A connection the caller must release
24
+ */
25
+ export declare function checkout(pool: HeldPool): Promise<DriverConnection>;
26
+ /**
27
+ * Describes a statement.
28
+ *
29
+ * @param sql - Pool client
30
+ * @param text - SQL
31
+ * @param params - Wire parameters
32
+ * @returns Column names and the parameter count
33
+ */
34
+ export declare function describe(sql: Sql, text: string, params?: readonly WireValue[]): Promise<DescribeResult>;
35
+ /**
36
+ * Yields cursor chunks.
37
+ *
38
+ * @param sql - Pool client
39
+ * @param text - SQL
40
+ * @param params - Wire parameters
41
+ * @returns Chunks of wire rows
42
+ */
43
+ export declare function stream(sql: Sql, text: string, params?: readonly WireValue[]): AsyncIterable<readonly (readonly WireValue[])[]>;