@vibeorm/adapter-pglite 2.1.0 → 2.2.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/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -36
- package/dist/index.js.map +5 -5
- package/dist/queue.d.ts +10 -0
- package/dist/queue.d.ts.map +1 -1
- package/dist/transaction-sql.d.ts +2 -15
- package/dist/transaction-sql.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAEV,eAAe,EAIhB,MAAM,kBAAkB,CAAC;AAa1B,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAA8B,MAAM,sBAAsB,CAAC;AAQpG,yCAAyC;AACzC,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC;IAClC;;;;;;;;OAQG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;CAClC,CAAC;AAsGF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,eAAe,CAuS7E;AAID,OAAO,EACL,2BAA2B,EAC3B,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACtG,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACzF,YAAY,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EACL,mBAAmB,EACnB,8BAA8B,EAC9B,0BAA0B,GAC3B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,0BAA0B,EAC1B,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,8BAA8B,EAC9B,2BAA2B,GAC5B,MAAM,8BAA8B,CAAC;AACtC,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
var __require = import.meta.require;
|
|
3
3
|
|
|
4
4
|
// packages/adapter-pglite/src/index.ts
|
|
5
|
-
import {
|
|
6
|
-
import { VibeError as VibeError4 } from "@vibeorm/schema";
|
|
5
|
+
import { VibeError as VibeError3 } from "@vibeorm/schema";
|
|
7
6
|
import {
|
|
7
|
+
runPinnedSession,
|
|
8
8
|
createSavepointScope,
|
|
9
9
|
runNestedSavepoint,
|
|
10
10
|
runRootScope,
|
|
@@ -142,6 +142,17 @@ function serializeParamsRaw(params) {
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
// packages/adapter-pglite/src/queue.ts
|
|
145
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
146
|
+
var INJECTED_OWNERSHIP = new WeakMap;
|
|
147
|
+
function connectionOwnership(params) {
|
|
148
|
+
const existing = params.database === undefined ? undefined : INJECTED_OWNERSHIP.get(params.database);
|
|
149
|
+
if (existing !== undefined)
|
|
150
|
+
return existing;
|
|
151
|
+
const ownership = { queue: createOperationQueue(), txContext: new AsyncLocalStorage };
|
|
152
|
+
if (params.database !== undefined)
|
|
153
|
+
INJECTED_OWNERSHIP.set(params.database, ownership);
|
|
154
|
+
return ownership;
|
|
155
|
+
}
|
|
145
156
|
function createOperationQueue() {
|
|
146
157
|
let tail = Promise.resolve();
|
|
147
158
|
return {
|
|
@@ -158,7 +169,7 @@ function createOperationQueue() {
|
|
|
158
169
|
}
|
|
159
170
|
|
|
160
171
|
// packages/adapter-pglite/src/transaction-sql.ts
|
|
161
|
-
import {
|
|
172
|
+
import { refuseNestedTransactionOptions } from "@vibeorm/runtime/adapter-kit";
|
|
162
173
|
var ISOLATION_LEVEL_SQL = Object.freeze({
|
|
163
174
|
ReadCommitted: "READ COMMITTED",
|
|
164
175
|
RepeatableRead: "REPEATABLE READ",
|
|
@@ -167,32 +178,6 @@ var ISOLATION_LEVEL_SQL = Object.freeze({
|
|
|
167
178
|
function setIsolationLevelStatement(params) {
|
|
168
179
|
return `SET TRANSACTION ISOLATION LEVEL ${ISOLATION_LEVEL_SQL[params.isolationLevel]}`;
|
|
169
180
|
}
|
|
170
|
-
function refuseNestedTransactionOptions(params) {
|
|
171
|
-
const { options, provider } = params;
|
|
172
|
-
if (options === undefined)
|
|
173
|
-
return;
|
|
174
|
-
const passed = [];
|
|
175
|
-
if (options.isolationLevel !== undefined)
|
|
176
|
-
passed.push("isolationLevel");
|
|
177
|
-
if (options.timeout !== undefined)
|
|
178
|
-
passed.push("timeout");
|
|
179
|
-
if (options.deadline !== undefined)
|
|
180
|
-
passed.push("deadline");
|
|
181
|
-
if (passed.length === 0)
|
|
182
|
-
return;
|
|
183
|
-
const meta = { provider, nested: true };
|
|
184
|
-
if (options.isolationLevel !== undefined)
|
|
185
|
-
meta.isolationLevel = options.isolationLevel;
|
|
186
|
-
if (options.timeout !== undefined)
|
|
187
|
-
meta.timeout = options.timeout;
|
|
188
|
-
if (options.deadline !== undefined)
|
|
189
|
-
meta.deadline = options.deadline;
|
|
190
|
-
throw new VibeError3({
|
|
191
|
-
code: "VIBE_VALIDATION",
|
|
192
|
-
message: `nested transactions run as savepoints and cannot honor ${passed.join(" or ")} \u2014 a savepoint cannot change the isolation level of the transaction it joins, a nested timeout is not enforceable, and a nested deadline would need its own session setting on a connection it does not own (it inherits the top-level one instead); pass options on the top-level $transaction`,
|
|
193
|
-
meta
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
181
|
|
|
197
182
|
// packages/adapter-pglite/src/index.ts
|
|
198
183
|
import { createSavepointCounter, nextSavepointName } from "@vibeorm/runtime/adapter-kit";
|
|
@@ -247,18 +232,17 @@ var BUDGETS = Object.freeze({
|
|
|
247
232
|
});
|
|
248
233
|
function pgliteAdapter(options) {
|
|
249
234
|
if (options?.pglite !== undefined && options.extensions !== undefined) {
|
|
250
|
-
throw new
|
|
235
|
+
throw new VibeError3({
|
|
251
236
|
code: "VIBE_CONFIG",
|
|
252
237
|
message: "pgliteAdapter: `extensions` applies to an instance the adapter CREATES \u2014 a provided `pglite` instance was already constructed with its own extensions; pass one or the other",
|
|
253
238
|
meta: { provider: PROVIDER }
|
|
254
239
|
});
|
|
255
240
|
}
|
|
256
|
-
const queue =
|
|
241
|
+
const { queue, txContext } = connectionOwnership({ database: options?.pglite });
|
|
257
242
|
const ownsInstance = options?.pglite === undefined;
|
|
258
|
-
const txContext = new AsyncLocalStorage;
|
|
259
243
|
function assertNotInsideTransaction() {
|
|
260
244
|
if (txContext.getStore() === true) {
|
|
261
|
-
throw new
|
|
245
|
+
throw new VibeError3({
|
|
262
246
|
code: "VIBE_TRANSACTION",
|
|
263
247
|
message: "root client used inside a transaction callback \u2014 use the tx client the callback receives; the root connection would deadlock behind the open transaction",
|
|
264
248
|
meta: { provider: PROVIDER }
|
|
@@ -348,6 +332,21 @@ function pgliteAdapter(options) {
|
|
|
348
332
|
provider: PROVIDER,
|
|
349
333
|
wire: WIRE,
|
|
350
334
|
budgets: BUDGETS,
|
|
335
|
+
async withSession({ run }) {
|
|
336
|
+
assertNotInsideTransaction();
|
|
337
|
+
return queue.run(async () => {
|
|
338
|
+
const db = await getInstance();
|
|
339
|
+
return txContext.run(true, () => runPinnedSession({
|
|
340
|
+
run,
|
|
341
|
+
execute: async (query) => (await runExecuteUnsafe({ queryable: db, ...query })).rows,
|
|
342
|
+
isLost: () => db.closed,
|
|
343
|
+
release: async () => {
|
|
344
|
+
if (!db.closed)
|
|
345
|
+
await runMapped(() => db.exec("ROLLBACK"));
|
|
346
|
+
}
|
|
347
|
+
}));
|
|
348
|
+
});
|
|
349
|
+
},
|
|
351
350
|
async execute(params) {
|
|
352
351
|
assertNotInsideTransaction();
|
|
353
352
|
return queue.run(async () => runExecute({ queryable: await getInstance(), ...params }));
|
|
@@ -359,7 +358,7 @@ function pgliteAdapter(options) {
|
|
|
359
358
|
async transaction(fn, transactionOptions) {
|
|
360
359
|
assertNotInsideTransaction();
|
|
361
360
|
if (transactionOptions?.timeout !== undefined) {
|
|
362
|
-
throw new
|
|
361
|
+
throw new VibeError3({
|
|
363
362
|
code: "VIBE_UNSUPPORTED_CAPABILITY",
|
|
364
363
|
message: "pglite cannot enforce a transaction timeout: the single-threaded WASM build accepts statement_timeout but never cancels a running statement \u2014 remove the option, or use a postgres server adapter where it is genuinely enforced",
|
|
365
364
|
meta: { provider: PROVIDER, feature: "transactionTimeout", timeout: transactionOptions.timeout }
|
|
@@ -390,7 +389,7 @@ function pgliteAdapter(options) {
|
|
|
390
389
|
budget.close({ outcome: "committed" });
|
|
391
390
|
return result;
|
|
392
391
|
} catch (error) {
|
|
393
|
-
budget.close({ outcome: "rolled-back" });
|
|
392
|
+
budget.close({ outcome: scope.state.poisoned === null ? "rolled-back" : "unknown" });
|
|
394
393
|
if (error instanceof CallbackError)
|
|
395
394
|
throw error.inner;
|
|
396
395
|
throw mapPgliteDriverError({ error });
|
|
@@ -446,4 +445,4 @@ export {
|
|
|
446
445
|
DEFAULT_DEADLINE_CLOCK
|
|
447
446
|
};
|
|
448
447
|
|
|
449
|
-
//# debugId=
|
|
448
|
+
//# debugId=C5F6AEAFCFC17FFF64756E2164756E21
|
package/dist/index.js.map
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts", "../src/errors.ts", "../src/params.ts", "../src/queue.ts", "../src/transaction-sql.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * @vibeorm/adapter-pglite — PGlite (in-process PostgreSQL, WASM) adapter for\n * VibeORM v2.\n *\n * PGlite is a *single* embedded connection, so this adapter serializes every\n * operation through one queue — including whole transactions, which hold the\n * queue until they commit or roll back. That makes concurrent client calls safe\n * without a pool, and makes an in-memory instance an honest postgres target for\n * tests (no Docker).\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { VibeError } from \"@vibeorm/schema\";\nimport type {\n AdapterBudgetSupport,\n DatabaseAdapter,\n QueryResult,\n TransactionOptions,\n WireFidelity,\n} from \"@vibeorm/runtime\";\nimport {\n createSavepointScope,\n runNestedSavepoint,\n runRootScope,\n type SavepointScope,\n scopeTurn,\n startTransactionBudget,\n type TransactionBudget,\n validateTransactionDeadline,\n} from \"@vibeorm/runtime/adapter-kit\";\nimport type { Dialect, Provider } from \"@vibeorm/schema\";\nimport type { Extensions, PGliteInterface, ParserOptions, Transaction } from \"@electric-sql/pglite\";\nimport { mapPgliteDriverError, runMapped } from \"./errors.ts\";\nimport { PgliteArrayParam, serializeParams, serializeParamsRaw } from \"./params.ts\";\nimport { createOperationQueue } from \"./queue.ts\";\nimport { refuseNestedTransactionOptions, setIsolationLevelStatement } from \"./transaction-sql.ts\";\n\n// ─── Options ──────────────────────────────────────────────────────\n\n/** Options for {@link pgliteAdapter}. */\nexport type PgliteAdapterOptions = {\n /**\n * Directory to persist the database in. Omit for a fresh in-memory database —\n * the usual choice for tests. Prefixes PGlite understands (`idb://`,\n * `memory://`) work here too.\n */\n readonly dataDir?: string;\n /**\n * An already-created PGlite instance to run on (sharing one database across\n * adapters, or reusing a warm instance between test files). The adapter never\n * closes an instance it did not create, so `disconnect()` is a no-op then.\n */\n readonly pglite?: PGliteInterface;\n /**\n * PGlite extension bundles to load into the instance the ADAPTER creates —\n * `{ vector }` from `@electric-sql/pglite-pgvector`, `pg_trgm` from\n * `@electric-sql/pglite/contrib/pg_trgm`, … The bundles still come from\n * their own packages; this option removes the need to construct PGlite\n * yourself just to attach them. Mutually exclusive with `pglite` (that\n * instance was already constructed with its extensions) — passing both\n * throws `VIBE_CONFIG`.\n */\n readonly extensions?: Extensions;\n};\n\n// ─── Internals ────────────────────────────────────────────────────\n\n/** Anything that runs SQL: the PGlite instance itself or an open transaction. */\ntype Queryable = Pick<Transaction, \"query\" | \"exec\">;\n\n// ─── UTC zone-less timestamps ─────────────────────────────────────\n\n/** `timestamp without time zone` and its array form. */\nconst TIMESTAMP_OID = 1114;\nconst TIMESTAMP_ARRAY_OID = 1115;\n\n/** PGlite's text output for a zone-less timestamp: `2026-03-08 19:38:08.538`. */\nconst ZONE_LESS_TEXT = /^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}(?:\\.\\d{1,6})?$/;\n\n/**\n * Zone-less timestamp text read as **UTC** — the codec table's\n * `parseDateTimeText` rule (@vibeorm/sql) applied at the driver level, because\n * PGlite hands these columns to the ORM as `Date` objects already\n * (`wire.dateTime: \"native\"` prunes the codec decode). PGlite's own parser is\n * `new Date(text)`, which ECMA-262 reads as host-LOCAL time — while PGlite\n * SERIALIZES a `Date` parameter as UTC (`toISOString()`), so a value did not\n * even round-trip on a non-UTC host. `date` is unaffected (date-only text is\n * UTC midnight under ECMA-262 already). Anything outside the plain form keeps\n * PGlite's parser.\n */\nfunction parseTimestampAsUtc(value: string): unknown {\n if (ZONE_LESS_TEXT.test(value)) {\n const parsed = new Date(`${value.replace(\" \", \"T\").replace(/(\\.\\d{3})\\d+$/, \"$1\")}Z`);\n if (!Number.isNaN(parsed.getTime())) return parsed;\n }\n return new Date(value);\n}\n\nlet utcParsers: ParserOptions | null = null;\n\n/**\n * Per-query parsers (`QueryOptions.parsers`) — never `instance.parsers`, which\n * a caller-supplied instance shares with everyone else. The array parser is\n * PGlite's own (`types.arrayParser`), resolved lazily from the same dynamic\n * import `getInstance` uses, so the WASM module is never loaded just to build\n * this table.\n */\nasync function getUtcParsers(): Promise<ParserOptions> {\n if (utcParsers !== null) return utcParsers;\n const { types } = await import(\"@electric-sql/pglite\");\n utcParsers = {\n [TIMESTAMP_OID]: parseTimestampAsUtc,\n [TIMESTAMP_ARRAY_OID]: (text: string): unknown => types.arrayParser(text, parseTimestampAsUtc, TIMESTAMP_ARRAY_OID),\n };\n return utcParsers;\n}\n\n/**\n * Wrapper that marks an error as \"thrown by the user's transaction callback\",\n * so it can be rethrown untouched instead of being mapped as a driver failure\n * after PGlite has passed it back out of `transaction()`.\n */\nclass CallbackError extends Error {\n readonly inner: unknown;\n\n constructor(inner: unknown) {\n super(\"vibeorm: transaction callback failed\");\n this.name = \"CallbackError\";\n this.inner = inner;\n }\n}\n\nconst DIALECT: Dialect = \"postgres\";\nconst PROVIDER: Provider = \"pglite\";\n\n/**\n * pglite wire (board #30, live-verified on both execute paths): timestamptz →\n * `Date`, json/jsonb → parsed values, int4/float8 → numbers. (int8 arrives as\n * a native `bigint` here — the BigInt codec passes it through; not declared.)\n */\nconst WIRE: WireFidelity = Object.freeze({ dateTime: \"native\", json: \"parsed\", numbers: \"native\" } as const);\n\n/**\n * Timing budgets this adapter genuinely enforces (EPIC 6).\n *\n * - `acquireTimeout: false` — one in-process WASM instance behind a queue.\n * There is no pool to exhaust.\n * - `statementTimeout: \"unsupported\"` — **PGlite ACCEPTING `statement_timeout`\n * is not support.** The single-threaded WASM build reports the setting back\n * via SHOW and never fires it (board #2, live-verified: `pg_sleep(2)` under a\n * 100 ms timeout runs to completion), which is why the `timeout` option is\n * refused outright below.\n * - `transactionDeadline: \"between-statements\"` — the budget is checked before\n * each statement and before the commit, which PGlite CAN honour because those\n * checks happen in JavaScript. It is not cancellation, for the same\n * single-threaded reason, so `\"cancel-running-statements\"` is refused.\n */\nconst BUDGETS: AdapterBudgetSupport = Object.freeze({\n acquireTimeout: false,\n statementTimeout: \"unsupported\",\n transactionDeadline: \"between-statements\",\n} as const);\n\n// ─── Adapter ──────────────────────────────────────────────────────\n\n/**\n * Create a VibeORM adapter backed by PGlite.\n *\n * @example In-memory database (tests)\n * ```ts\n * const adapter = pgliteAdapter();\n * await adapter.executeUnsafe({ text: `CREATE TABLE \"User\" (\"id\" serial primary key)` });\n * ```\n *\n * @example Persistent database, or a shared instance\n * ```ts\n * const adapter = pgliteAdapter({ dataDir: \"./.pglite\" });\n * const shared = pgliteAdapter({ pglite: existingInstance });\n * ```\n *\n * `disconnect()` closes an instance the adapter created; a later call opens a\n * fresh one (lazy reconnect, matching the pool-backed adapters). With no\n * `dataDir` that fresh instance is a new, empty in-memory database.\n *\n * @example Bundled extensions (pgvector) without hand-constructing PGlite\n * ```ts\n * import { vector } from \"@electric-sql/pglite-pgvector\";\n * const adapter = pgliteAdapter({ dataDir: \"./.pglite\", extensions: { vector } });\n * ```\n */\nexport function pgliteAdapter(options?: PgliteAdapterOptions): DatabaseAdapter {\n if (options?.pglite !== undefined && options.extensions !== undefined) {\n throw new VibeError({\n code: \"VIBE_CONFIG\",\n message:\n \"pgliteAdapter: `extensions` applies to an instance the adapter CREATES — a provided `pglite` instance was already constructed with its own extensions; pass one or the other\",\n meta: { provider: PROVIDER },\n });\n }\n const queue = createOperationQueue();\n const ownsInstance = options?.pglite === undefined;\n\n /**\n * Deadlock guard (review F6): PGlite is a single connection, and a whole\n * transaction holds the operation queue — so a ROOT-adapter call issued from\n * inside a `transaction()` callback would queue behind the very transaction\n * it is running in and hang forever. The callback runs inside this context;\n * root entry points refuse instead of deadlocking. The tx-bound adapter\n * bypasses the queue and stays fully usable.\n */\n const txContext = new AsyncLocalStorage<true>();\n\n function assertNotInsideTransaction(): void {\n if (txContext.getStore() === true) {\n throw new VibeError({\n code: \"VIBE_TRANSACTION\",\n message:\n \"root client used inside a transaction callback — use the tx client the callback receives; the root connection would deadlock behind the open transaction\",\n meta: { provider: PROVIDER },\n });\n }\n }\n\n let instance: PGliteInterface | null = options?.pglite ?? null;\n let pending: Promise<PGliteInterface> | null = null;\n\n async function getInstance(): Promise<PGliteInterface> {\n if (instance !== null) return instance;\n if (pending === null) {\n pending = runMapped(async () => {\n const { PGlite } = await import(\"@electric-sql/pglite\");\n const created = new PGlite({\n ...(options?.dataDir === undefined ? {} : { dataDir: options.dataDir }),\n ...(options?.extensions === undefined ? {} : { extensions: options.extensions }),\n });\n await created.waitReady;\n return created;\n });\n }\n try {\n instance = await pending;\n return instance;\n } catch (error) {\n // Let the next caller retry instead of caching the failure forever.\n pending = null;\n throw error;\n }\n }\n\n async function runExecute(params: {\n queryable: Queryable;\n text: string;\n values: unknown[];\n }): Promise<Record<string, unknown>[]> {\n const values = serializeParams({ values: params.values });\n const parsers = utcParsers ?? (await getUtcParsers());\n const result = await runMapped(() =>\n params.queryable.query<Record<string, unknown>>(params.text, values, { parsers }),\n );\n return result.rows;\n }\n\n /**\n * Raw path. Without parameters the statement goes through `exec()` (simple\n * protocol) so multi-statement DDL — what @vibeorm/migrate emits — runs as\n * one call; with parameters it goes through the extended protocol.\n */\n async function runExecuteUnsafe(params: {\n queryable: Queryable;\n text: string;\n values?: unknown[];\n }): Promise<QueryResult> {\n const parsers = utcParsers ?? (await getUtcParsers());\n if (params.values === undefined) {\n const results = await runMapped(() => params.queryable.exec(params.text, { parsers }));\n const last = results.at(-1);\n return { rows: last?.rows ?? [], affectedRows: last?.affectedRows ?? 0 };\n }\n const values = serializeParamsRaw({ values: params.values });\n const result = await runMapped(() =>\n params.queryable.query<Record<string, unknown>>(params.text, values, { parsers }),\n );\n return { rows: result.rows, affectedRows: result.affectedRows ?? 0 };\n }\n\n /**\n * Adapter bound to an open transaction. It never re-enters the queue — the\n * enclosing `transaction()` call already owns the connection — and nested\n * `transaction()` calls become savepoints whose LIFETIMES are serialized by\n * the savepoint gate (F14): overlapping siblings would share one savepoint\n * stack, and the earlier one's rollback would erase the later one's work.\n */\n function createTransactionAdapter(params: {\n tx: Transaction;\n scope: SavepointScope;\n budget: TransactionBudget;\n }): DatabaseAdapter {\n const { tx, scope, budget } = params;\n\n return {\n dialect: DIALECT,\n provider: PROVIDER,\n wire: WIRE,\n budgets: BUDGETS,\n\n async execute(execParams) {\n const turn = scopeTurn({ scope });\n if (turn !== undefined) await turn;\n // After the turn, not before: waiting for a sibling savepoint spends\n // the same budget the statement is about to run against.\n budget.assertUsable({ stage: \"statement\" });\n return runExecute({ queryable: tx, ...execParams });\n },\n\n async executeUnsafe(execParams) {\n const turn = scopeTurn({ scope });\n if (turn !== undefined) await turn;\n budget.assertUsable({ stage: \"statement\" });\n return runExecuteUnsafe({ queryable: tx, ...execParams });\n },\n\n async transaction<T>(\n fn: (txAdapter: DatabaseAdapter) => Promise<T>,\n nestedOptions?: TransactionOptions,\n ): Promise<T> {\n refuseNestedTransactionOptions({ options: nestedOptions, provider: PROVIDER });\n budget.assertUsable({ stage: \"nested\" });\n return runNestedSavepoint({\n scope,\n execute: (statement) => runMapped(() => tx.query(statement)),\n // The child shares the ROOT budget by reference: a savepoint never\n // gets an independent clock or session setting.\n body: (child) => fn(createTransactionAdapter({ tx, scope: child, budget })),\n });\n },\n\n async connect(): Promise<void> {\n // Already connected — this adapter is bound to an open transaction.\n },\n\n async disconnect(): Promise<void> {\n // The database outlives the transaction; closing here would be wrong.\n },\n\n formatArrayParam(values: unknown[]): unknown {\n return new PgliteArrayParam(values);\n },\n };\n }\n\n return {\n dialect: DIALECT,\n provider: PROVIDER,\n wire: WIRE,\n budgets: BUDGETS,\n\n async execute(params) {\n assertNotInsideTransaction();\n // The instance is acquired INSIDE the queue (F15): capturing it first and\n // enqueueing after let a `disconnect()` issued in between overtake this\n // statement and close the instance out from under it.\n return queue.run(async () => runExecute({ queryable: await getInstance(), ...params }));\n },\n\n async executeUnsafe(params) {\n assertNotInsideTransaction();\n return queue.run(async () => runExecuteUnsafe({ queryable: await getInstance(), ...params }));\n },\n\n async transaction<T>(\n fn: (txAdapter: DatabaseAdapter) => Promise<T>,\n transactionOptions?: TransactionOptions,\n ): Promise<T> {\n assertNotInsideTransaction();\n // Dialect honesty (constitution rule 4, board #2): PGlite ACCEPTS\n // `SET LOCAL statement_timeout` and even reports it back via SHOW, but\n // never FIRES it — the single-threaded WASM build has no timer interrupt\n // to cancel a running statement (live-verified: `pg_sleep(2)` under a\n // 100ms timeout runs to completion). A timeout the engine cannot enforce\n // is refused at the earliest knowable moment instead of becoming a\n // silent no-op; the postgres SERVER adapters honor the same option for\n // real (SQLSTATE 57014 → VIBE_TRANSACTION, meta.reason \"timeout\").\n if (transactionOptions?.timeout !== undefined) {\n throw new VibeError({\n code: \"VIBE_UNSUPPORTED_CAPABILITY\",\n message:\n \"pglite cannot enforce a transaction timeout: the single-threaded WASM build accepts statement_timeout but never cancels a running statement — remove the option, or use a postgres server adapter where it is genuinely enforced\",\n meta: { provider: PROVIDER, feature: \"transactionTimeout\", timeout: transactionOptions.timeout },\n });\n }\n // Same earliest-moment rule for the deadline: a budget this engine\n // cannot honour is refused before the transaction is ever opened.\n validateTransactionDeadline({\n options: transactionOptions,\n support: BUDGETS.transactionDeadline,\n provider: PROVIDER,\n });\n const scope = createSavepointScope();\n\n return queue.run(async () => {\n const db = await getInstance();\n // The deadline clock starts here — after the queue turn, immediately\n // before PGlite opens the transaction.\n const budget = startTransactionBudget({ options: transactionOptions, provider: PROVIDER });\n try {\n const result = await db.transaction(async (tx) => {\n if (transactionOptions?.isolationLevel !== undefined) {\n await tx.query(\n setIsolationLevelStatement({ isolationLevel: transactionOptions.isolationLevel }),\n );\n }\n try {\n const value = await txContext.run(true, () =>\n runRootScope({ scope, body: () => fn(createTransactionAdapter({ tx, scope, budget })) }),\n );\n // An expired budget must never commit. PGlite commits when this\n // callback returns, so the refusal has to be thrown from INSIDE\n // it — which makes PGlite roll back, exactly as intended.\n budget.assertUsable({ stage: \"commit\" });\n return value;\n } catch (error) {\n throw new CallbackError(error);\n }\n });\n budget.close({ outcome: \"committed\" });\n return result;\n } catch (error) {\n // PGlite owns this transaction's rollback and performs it in-process\n // before control returns here, so the outcome is known.\n budget.close({ outcome: \"rolled-back\" });\n // The callback's own failure propagates untouched; PGlite has already\n // rolled the transaction back by the time it reaches us.\n if (error instanceof CallbackError) throw error.inner;\n throw mapPgliteDriverError({ error });\n }\n });\n },\n\n async connect(): Promise<void> {\n await getInstance();\n },\n\n /**\n * ONE ordered lifecycle (F15): the reference is cleared and the instance\n * closed INSIDE the queue, so work this adapter already accepted completes\n * on the instance it was accepted against instead of being overtaken by the\n * close. Lazy reconnect is unchanged — a later call creates a fresh\n * instance (with no `dataDir`, a new empty one).\n *\n * Refuses inside a transaction callback for the same reason the other entry\n * points do: the close would queue behind the transaction that is waiting\n * for it. Before this guard that call hung forever.\n */\n async disconnect(): Promise<void> {\n assertNotInsideTransaction();\n if (!ownsInstance) return;\n await queue.run(async () => {\n if (instance === null) {\n pending = null;\n return;\n }\n const closing = instance;\n instance = null;\n pending = null;\n await runMapped(() => closing.close());\n });\n },\n\n formatArrayParam(values: unknown[]): unknown {\n return new PgliteArrayParam(values);\n },\n };\n}\n\n// ─── Re-exports (driver-error table, markers, helpers) ────────────\n\nexport {\n PGLITE_SQLSTATE_ERROR_CODES,\n PGLITE_SQLSTATE_REASONS,\n mapPgliteDriverError,\n pgliteErrorSqlstate,\n} from \"./errors.ts\";\nexport { PgliteArrayParam, serializeParams, serializeParamsRaw, toPgArrayLiteral } from \"./params.ts\";\nexport { createOperationQueue } from \"./queue.ts\";\nexport type { OperationQueue } from \"./queue.ts\";\nexport { createSavepointCounter, nextSavepointName } from \"@vibeorm/runtime/adapter-kit\";\nexport type { SavepointCounter } from \"@vibeorm/runtime/adapter-kit\";\nexport {\n ISOLATION_LEVEL_SQL,\n refuseNestedTransactionOptions,\n setIsolationLevelStatement,\n} from \"./transaction-sql.ts\";\n// ─── EPIC 6: transaction budgets (shared, @vibeorm/runtime/adapter-kit) ───\nexport {\n DEFAULT_DEADLINE_CLOCK,\n engineStatementBudgetMs,\n isTransactionDeadlineError,\n startTransactionBudget,\n transactionClosedError,\n transactionDeadlineError,\n transactionOutcomeUnknownError,\n validateTransactionDeadline,\n} from \"@vibeorm/runtime/adapter-kit\";\nexport type { BudgetStage, DeadlineClock, TransactionBudget, TransactionOutcome } from \"@vibeorm/runtime/adapter-kit\";\n",
|
|
5
|
+
"/**\n * @vibeorm/adapter-pglite — PGlite (in-process PostgreSQL, WASM) adapter for\n * VibeORM v2.\n *\n * PGlite is a *single* embedded connection, so this adapter serializes every\n * operation through one queue — including whole transactions, which hold the\n * queue until they commit or roll back. That makes concurrent client calls safe\n * without a pool, and makes an in-memory instance an honest postgres target for\n * tests (no Docker).\n */\n\nimport { VibeError } from \"@vibeorm/schema\";\nimport type {\n AdapterBudgetSupport,\n DatabaseAdapter,\n QueryResult,\n TransactionOptions,\n WireFidelity,\n} from \"@vibeorm/runtime\";\nimport {\n runPinnedSession,\n createSavepointScope,\n runNestedSavepoint,\n runRootScope,\n type SavepointScope,\n scopeTurn,\n startTransactionBudget,\n type TransactionBudget,\n validateTransactionDeadline,\n} from \"@vibeorm/runtime/adapter-kit\";\nimport type { Dialect, Provider } from \"@vibeorm/schema\";\nimport type { Extensions, PGliteInterface, ParserOptions, Transaction } from \"@electric-sql/pglite\";\nimport { mapPgliteDriverError, runMapped } from \"./errors.ts\";\nimport { PgliteArrayParam, serializeParams, serializeParamsRaw } from \"./params.ts\";\nimport { connectionOwnership } from \"./queue.ts\";\nimport { refuseNestedTransactionOptions, setIsolationLevelStatement } from \"./transaction-sql.ts\";\n\n// ─── Options ──────────────────────────────────────────────────────\n\n/** Options for {@link pgliteAdapter}. */\nexport type PgliteAdapterOptions = {\n /**\n * Directory to persist the database in. Omit for a fresh in-memory database —\n * the usual choice for tests. Prefixes PGlite understands (`idb://`,\n * `memory://`) work here too.\n */\n readonly dataDir?: string;\n /**\n * An already-created PGlite instance to run on (sharing one database across\n * adapters, or reusing a warm instance between test files). The adapter never\n * closes an instance it did not create, so `disconnect()` is a no-op then.\n */\n readonly pglite?: PGliteInterface;\n /**\n * PGlite extension bundles to load into the instance the ADAPTER creates —\n * `{ vector }` from `@electric-sql/pglite-pgvector`, `pg_trgm` from\n * `@electric-sql/pglite/contrib/pg_trgm`, … The bundles still come from\n * their own packages; this option removes the need to construct PGlite\n * yourself just to attach them. Mutually exclusive with `pglite` (that\n * instance was already constructed with its extensions) — passing both\n * throws `VIBE_CONFIG`.\n */\n readonly extensions?: Extensions;\n};\n\n// ─── Internals ────────────────────────────────────────────────────\n\n/** Anything that runs SQL: the PGlite instance itself or an open transaction. */\ntype Queryable = Pick<Transaction, \"query\" | \"exec\">;\n\n// ─── UTC zone-less timestamps ─────────────────────────────────────\n\n/** `timestamp without time zone` and its array form. */\nconst TIMESTAMP_OID = 1114;\nconst TIMESTAMP_ARRAY_OID = 1115;\n\n/** PGlite's text output for a zone-less timestamp: `2026-03-08 19:38:08.538`. */\nconst ZONE_LESS_TEXT = /^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}(?:\\.\\d{1,6})?$/;\n\n/**\n * Zone-less timestamp text read as **UTC** — the codec table's\n * `parseDateTimeText` rule (@vibeorm/sql) applied at the driver level, because\n * PGlite hands these columns to the ORM as `Date` objects already\n * (`wire.dateTime: \"native\"` prunes the codec decode). PGlite's own parser is\n * `new Date(text)`, which ECMA-262 reads as host-LOCAL time — while PGlite\n * SERIALIZES a `Date` parameter as UTC (`toISOString()`), so a value did not\n * even round-trip on a non-UTC host. `date` is unaffected (date-only text is\n * UTC midnight under ECMA-262 already). Anything outside the plain form keeps\n * PGlite's parser.\n */\nfunction parseTimestampAsUtc(value: string): unknown {\n if (ZONE_LESS_TEXT.test(value)) {\n const parsed = new Date(`${value.replace(\" \", \"T\").replace(/(\\.\\d{3})\\d+$/, \"$1\")}Z`);\n if (!Number.isNaN(parsed.getTime())) return parsed;\n }\n return new Date(value);\n}\n\nlet utcParsers: ParserOptions | null = null;\n\n/**\n * Per-query parsers (`QueryOptions.parsers`) — never `instance.parsers`, which\n * a caller-supplied instance shares with everyone else. The array parser is\n * PGlite's own (`types.arrayParser`), resolved lazily from the same dynamic\n * import `getInstance` uses, so the WASM module is never loaded just to build\n * this table.\n */\nasync function getUtcParsers(): Promise<ParserOptions> {\n if (utcParsers !== null) return utcParsers;\n const { types } = await import(\"@electric-sql/pglite\");\n utcParsers = {\n [TIMESTAMP_OID]: parseTimestampAsUtc,\n [TIMESTAMP_ARRAY_OID]: (text: string): unknown => types.arrayParser(text, parseTimestampAsUtc, TIMESTAMP_ARRAY_OID),\n };\n return utcParsers;\n}\n\n/**\n * Wrapper that marks an error as \"thrown by the user's transaction callback\",\n * so it can be rethrown untouched instead of being mapped as a driver failure\n * after PGlite has passed it back out of `transaction()`.\n */\nclass CallbackError extends Error {\n readonly inner: unknown;\n\n constructor(inner: unknown) {\n super(\"vibeorm: transaction callback failed\");\n this.name = \"CallbackError\";\n this.inner = inner;\n }\n}\n\nconst DIALECT: Dialect = \"postgres\";\nconst PROVIDER: Provider = \"pglite\";\n\n/**\n * pglite wire (board #30, live-verified on both execute paths): timestamptz →\n * `Date`, json/jsonb → parsed values, int4/float8 → numbers. (int8 arrives as\n * a native `bigint` here — the BigInt codec passes it through; not declared.)\n */\nconst WIRE: WireFidelity = Object.freeze({ dateTime: \"native\", json: \"parsed\", numbers: \"native\" } as const);\n\n/**\n * Timing budgets this adapter genuinely enforces (EPIC 6).\n *\n * - `acquireTimeout: false` — one in-process WASM instance behind a queue.\n * There is no pool to exhaust.\n * - `statementTimeout: \"unsupported\"` — **PGlite ACCEPTING `statement_timeout`\n * is not support.** The single-threaded WASM build reports the setting back\n * via SHOW and never fires it (board #2, live-verified: `pg_sleep(2)` under a\n * 100 ms timeout runs to completion), which is why the `timeout` option is\n * refused outright below.\n * - `transactionDeadline: \"between-statements\"` — the budget is checked before\n * each statement and before the commit, which PGlite CAN honour because those\n * checks happen in JavaScript. It is not cancellation, for the same\n * single-threaded reason, so `\"cancel-running-statements\"` is refused.\n */\nconst BUDGETS: AdapterBudgetSupport = Object.freeze({\n acquireTimeout: false,\n statementTimeout: \"unsupported\",\n transactionDeadline: \"between-statements\",\n} as const);\n\n// ─── Adapter ──────────────────────────────────────────────────────\n\n/**\n * Create a VibeORM adapter backed by PGlite.\n *\n * @example In-memory database (tests)\n * ```ts\n * const adapter = pgliteAdapter();\n * await adapter.executeUnsafe({ text: `CREATE TABLE \"User\" (\"id\" serial primary key)` });\n * ```\n *\n * @example Persistent database, or a shared instance\n * ```ts\n * const adapter = pgliteAdapter({ dataDir: \"./.pglite\" });\n * const shared = pgliteAdapter({ pglite: existingInstance });\n * ```\n *\n * `disconnect()` closes an instance the adapter created; a later call opens a\n * fresh one (lazy reconnect, matching the pool-backed adapters). With no\n * `dataDir` that fresh instance is a new, empty in-memory database.\n *\n * @example Bundled extensions (pgvector) without hand-constructing PGlite\n * ```ts\n * import { vector } from \"@electric-sql/pglite-pgvector\";\n * const adapter = pgliteAdapter({ dataDir: \"./.pglite\", extensions: { vector } });\n * ```\n */\nexport function pgliteAdapter(options?: PgliteAdapterOptions): DatabaseAdapter {\n if (options?.pglite !== undefined && options.extensions !== undefined) {\n throw new VibeError({\n code: \"VIBE_CONFIG\",\n message:\n \"pgliteAdapter: `extensions` applies to an instance the adapter CREATES — a provided `pglite` instance was already constructed with its own extensions; pass one or the other\",\n meta: { provider: PROVIDER },\n });\n }\n const { queue, txContext } = connectionOwnership({ database: options?.pglite });\n const ownsInstance = options?.pglite === undefined;\n\n /**\n * Deadlock guard (review F6): PGlite is a single connection, and a whole\n * transaction holds the operation queue — so a ROOT-adapter call issued from\n * inside a `transaction()` callback would queue behind the very transaction\n * it is running in and hang forever. The callback runs inside this context;\n * root entry points refuse instead of deadlocking. The tx-bound adapter\n * bypasses the queue and stays fully usable.\n */\n function assertNotInsideTransaction(): void {\n if (txContext.getStore() === true) {\n throw new VibeError({\n code: \"VIBE_TRANSACTION\",\n message:\n \"root client used inside a transaction callback — use the tx client the callback receives; the root connection would deadlock behind the open transaction\",\n meta: { provider: PROVIDER },\n });\n }\n }\n\n let instance: PGliteInterface | null = options?.pglite ?? null;\n let pending: Promise<PGliteInterface> | null = null;\n\n async function getInstance(): Promise<PGliteInterface> {\n if (instance !== null) return instance;\n if (pending === null) {\n pending = runMapped(async () => {\n const { PGlite } = await import(\"@electric-sql/pglite\");\n const created = new PGlite({\n ...(options?.dataDir === undefined ? {} : { dataDir: options.dataDir }),\n ...(options?.extensions === undefined ? {} : { extensions: options.extensions }),\n });\n await created.waitReady;\n return created;\n });\n }\n try {\n instance = await pending;\n return instance;\n } catch (error) {\n // Let the next caller retry instead of caching the failure forever.\n pending = null;\n throw error;\n }\n }\n\n async function runExecute(params: {\n queryable: Queryable;\n text: string;\n values: unknown[];\n }): Promise<Record<string, unknown>[]> {\n const values = serializeParams({ values: params.values });\n const parsers = utcParsers ?? (await getUtcParsers());\n const result = await runMapped(() =>\n params.queryable.query<Record<string, unknown>>(params.text, values, { parsers }),\n );\n return result.rows;\n }\n\n /**\n * Raw path. Without parameters the statement goes through `exec()` (simple\n * protocol) so multi-statement DDL — what @vibeorm/migrate emits — runs as\n * one call; with parameters it goes through the extended protocol.\n */\n async function runExecuteUnsafe(params: {\n queryable: Queryable;\n text: string;\n values?: unknown[];\n }): Promise<QueryResult> {\n const parsers = utcParsers ?? (await getUtcParsers());\n if (params.values === undefined) {\n const results = await runMapped(() => params.queryable.exec(params.text, { parsers }));\n const last = results.at(-1);\n return { rows: last?.rows ?? [], affectedRows: last?.affectedRows ?? 0 };\n }\n const values = serializeParamsRaw({ values: params.values });\n const result = await runMapped(() =>\n params.queryable.query<Record<string, unknown>>(params.text, values, { parsers }),\n );\n return { rows: result.rows, affectedRows: result.affectedRows ?? 0 };\n }\n\n /**\n * Adapter bound to an open transaction. It never re-enters the queue — the\n * enclosing `transaction()` call already owns the connection — and nested\n * `transaction()` calls become savepoints whose LIFETIMES are serialized by\n * the savepoint gate (F14): overlapping siblings would share one savepoint\n * stack, and the earlier one's rollback would erase the later one's work.\n */\n function createTransactionAdapter(params: {\n tx: Transaction;\n scope: SavepointScope;\n budget: TransactionBudget;\n }): DatabaseAdapter {\n const { tx, scope, budget } = params;\n\n return {\n dialect: DIALECT,\n provider: PROVIDER,\n wire: WIRE,\n budgets: BUDGETS,\n\n async execute(execParams) {\n const turn = scopeTurn({ scope });\n if (turn !== undefined) await turn;\n // After the turn, not before: waiting for a sibling savepoint spends\n // the same budget the statement is about to run against.\n budget.assertUsable({ stage: \"statement\" });\n return runExecute({ queryable: tx, ...execParams });\n },\n\n async executeUnsafe(execParams) {\n const turn = scopeTurn({ scope });\n if (turn !== undefined) await turn;\n budget.assertUsable({ stage: \"statement\" });\n return runExecuteUnsafe({ queryable: tx, ...execParams });\n },\n\n async transaction<T>(\n fn: (txAdapter: DatabaseAdapter) => Promise<T>,\n nestedOptions?: TransactionOptions,\n ): Promise<T> {\n refuseNestedTransactionOptions({ options: nestedOptions, provider: PROVIDER });\n budget.assertUsable({ stage: \"nested\" });\n return runNestedSavepoint({\n scope,\n execute: (statement) => runMapped(() => tx.query(statement)),\n // The child shares the ROOT budget by reference: a savepoint never\n // gets an independent clock or session setting.\n body: (child) => fn(createTransactionAdapter({ tx, scope: child, budget })),\n });\n },\n\n async connect(): Promise<void> {\n // Already connected — this adapter is bound to an open transaction.\n },\n\n async disconnect(): Promise<void> {\n // The database outlives the transaction; closing here would be wrong.\n },\n\n formatArrayParam(values: unknown[]): unknown {\n return new PgliteArrayParam(values);\n },\n };\n }\n\n return {\n dialect: DIALECT,\n provider: PROVIDER,\n wire: WIRE,\n budgets: BUDGETS,\n\n async withSession({ run }) {\n assertNotInsideTransaction();\n return queue.run(async () => {\n const db = await getInstance();\n return txContext.run(true, () => runPinnedSession({\n run,\n execute: async (query) => (await runExecuteUnsafe({ queryable: db, ...query })).rows,\n isLost: () => db.closed,\n release: async () => {\n if (!db.closed) await runMapped(() => db.exec(\"ROLLBACK\"));\n },\n }));\n });\n },\n\n async execute(params) {\n assertNotInsideTransaction();\n // The instance is acquired INSIDE the queue (F15): capturing it first and\n // enqueueing after let a `disconnect()` issued in between overtake this\n // statement and close the instance out from under it.\n return queue.run(async () => runExecute({ queryable: await getInstance(), ...params }));\n },\n\n async executeUnsafe(params) {\n assertNotInsideTransaction();\n return queue.run(async () => runExecuteUnsafe({ queryable: await getInstance(), ...params }));\n },\n\n async transaction<T>(\n fn: (txAdapter: DatabaseAdapter) => Promise<T>,\n transactionOptions?: TransactionOptions,\n ): Promise<T> {\n assertNotInsideTransaction();\n // Dialect honesty (constitution rule 4, board #2): PGlite ACCEPTS\n // `SET LOCAL statement_timeout` and even reports it back via SHOW, but\n // never FIRES it — the single-threaded WASM build has no timer interrupt\n // to cancel a running statement (live-verified: `pg_sleep(2)` under a\n // 100ms timeout runs to completion). A timeout the engine cannot enforce\n // is refused at the earliest knowable moment instead of becoming a\n // silent no-op; the postgres SERVER adapters honor the same option for\n // real (SQLSTATE 57014 → VIBE_TRANSACTION, meta.reason \"timeout\").\n if (transactionOptions?.timeout !== undefined) {\n throw new VibeError({\n code: \"VIBE_UNSUPPORTED_CAPABILITY\",\n message:\n \"pglite cannot enforce a transaction timeout: the single-threaded WASM build accepts statement_timeout but never cancels a running statement — remove the option, or use a postgres server adapter where it is genuinely enforced\",\n meta: { provider: PROVIDER, feature: \"transactionTimeout\", timeout: transactionOptions.timeout },\n });\n }\n // Same earliest-moment rule for the deadline: a budget this engine\n // cannot honour is refused before the transaction is ever opened.\n validateTransactionDeadline({\n options: transactionOptions,\n support: BUDGETS.transactionDeadline,\n provider: PROVIDER,\n });\n const scope = createSavepointScope();\n\n return queue.run(async () => {\n const db = await getInstance();\n // The deadline clock starts here — after the queue turn, immediately\n // before PGlite opens the transaction.\n const budget = startTransactionBudget({ options: transactionOptions, provider: PROVIDER });\n try {\n const result = await db.transaction(async (tx) => {\n if (transactionOptions?.isolationLevel !== undefined) {\n await tx.query(\n setIsolationLevelStatement({ isolationLevel: transactionOptions.isolationLevel }),\n );\n }\n try {\n const value = await txContext.run(true, () =>\n runRootScope({ scope, body: () => fn(createTransactionAdapter({ tx, scope, budget })) }),\n );\n // An expired budget must never commit. PGlite commits when this\n // callback returns, so the refusal has to be thrown from INSIDE\n // it — which makes PGlite roll back, exactly as intended.\n budget.assertUsable({ stage: \"commit\" });\n return value;\n } catch (error) {\n throw new CallbackError(error);\n }\n });\n budget.close({ outcome: \"committed\" });\n return result;\n } catch (error) {\n // A successful outer rollback cannot erase uncertainty from a failed\n // nested rollback (the transaction may have ended before cleanup).\n budget.close({ outcome: scope.state.poisoned === null ? \"rolled-back\" : \"unknown\" });\n // Preserve the callback's own failure; the budget retains any\n // uncertainty reported by nested transaction cleanup.\n if (error instanceof CallbackError) throw error.inner;\n throw mapPgliteDriverError({ error });\n }\n });\n },\n\n async connect(): Promise<void> {\n await getInstance();\n },\n\n /**\n * ONE ordered lifecycle (F15): the reference is cleared and the instance\n * closed INSIDE the queue, so work this adapter already accepted completes\n * on the instance it was accepted against instead of being overtaken by the\n * close. Lazy reconnect is unchanged — a later call creates a fresh\n * instance (with no `dataDir`, a new empty one).\n *\n * Refuses inside a transaction callback for the same reason the other entry\n * points do: the close would queue behind the transaction that is waiting\n * for it. Before this guard that call hung forever.\n */\n async disconnect(): Promise<void> {\n assertNotInsideTransaction();\n if (!ownsInstance) return;\n await queue.run(async () => {\n if (instance === null) {\n pending = null;\n return;\n }\n const closing = instance;\n instance = null;\n pending = null;\n await runMapped(() => closing.close());\n });\n },\n\n formatArrayParam(values: unknown[]): unknown {\n return new PgliteArrayParam(values);\n },\n };\n}\n\n// ─── Re-exports (driver-error table, markers, helpers) ────────────\n\nexport {\n PGLITE_SQLSTATE_ERROR_CODES,\n PGLITE_SQLSTATE_REASONS,\n mapPgliteDriverError,\n pgliteErrorSqlstate,\n} from \"./errors.ts\";\nexport { PgliteArrayParam, serializeParams, serializeParamsRaw, toPgArrayLiteral } from \"./params.ts\";\nexport { createOperationQueue } from \"./queue.ts\";\nexport type { OperationQueue } from \"./queue.ts\";\nexport { createSavepointCounter, nextSavepointName } from \"@vibeorm/runtime/adapter-kit\";\nexport type { SavepointCounter } from \"@vibeorm/runtime/adapter-kit\";\nexport {\n ISOLATION_LEVEL_SQL,\n refuseNestedTransactionOptions,\n setIsolationLevelStatement,\n} from \"./transaction-sql.ts\";\n// ─── EPIC 6: transaction budgets (shared, @vibeorm/runtime/adapter-kit) ───\nexport {\n DEFAULT_DEADLINE_CLOCK,\n engineStatementBudgetMs,\n isTransactionDeadlineError,\n startTransactionBudget,\n transactionClosedError,\n transactionDeadlineError,\n transactionOutcomeUnknownError,\n validateTransactionDeadline,\n} from \"@vibeorm/runtime/adapter-kit\";\nexport type { BudgetStage, DeadlineClock, TransactionBudget, TransactionOutcome } from \"@vibeorm/runtime/adapter-kit\";\n",
|
|
6
6
|
"/**\n * Driver-error mapping for PGlite.\n *\n * PGlite runs the real PostgreSQL error protocol in-process, so its errors\n * carry the same SQLSTATE (`code`) plus `constraint` / `table` / `column` as a\n * server would. Constitution rule 5: only `VibeError` escapes the adapter.\n */\n\nimport { VibeError, type VibeErrorCode } from \"@vibeorm/schema\";\n\n// ─── SQLSTATE table ───────────────────────────────────────────────\n\n/**\n * PostgreSQL SQLSTATE → stable VibeError code. Frozen and mirrored by tests;\n * anything absent from this table maps to `VIBE_ADAPTER`.\n */\nexport const PGLITE_SQLSTATE_ERROR_CODES: Readonly<Record<string, VibeErrorCode>> = Object.freeze({\n /** exclusion_violation */\n \"23P01\": \"VIBE_EXCLUSION_VIOLATION\",\n /** unique_violation */\n \"23505\": \"VIBE_UNIQUE_VIOLATION\",\n /** foreign_key_violation */\n \"23503\": \"VIBE_FK_VIOLATION\",\n /** restrict_violation — PostgreSQL 18+ ON DELETE/UPDATE RESTRICT */\n \"23001\": \"VIBE_FK_VIOLATION\",\n /** not_null_violation */\n \"23502\": \"VIBE_VALIDATION\",\n /** check_violation */\n \"23514\": \"VIBE_VALIDATION\",\n /**\n * invalid_text_representation — a value the server cannot parse into the\n * column's type (out-of-range enum value, `\"abc\"` for an integer). Bad input,\n * so the same code sqlite reports for its enum CHECK violation.\n */\n \"22P02\": \"VIBE_VALIDATION\",\n /**\n * insufficient_privilege — a denied table/column privilege, and the SQLSTATE a\n * native row-level-security policy raises when its WITH CHECK refuses a write.\n * Callers identify it by this code, never by message text.\n */\n \"42501\": \"VIBE_PERMISSION_DENIED\",\n /** serialization_failure */\n \"40001\": \"VIBE_TRANSACTION\",\n /**\n * lock_not_available. PGlite has ONE session, so nothing can contend with the\n * caller — the mapping exists for parity with the server adapters (identical\n * PostgreSQL SQLSTATEs), not because this engine is expected to raise it.\n */\n \"55P03\": \"VIBE_LOCK_NOT_AVAILABLE\",\n /** deadlock_detected */\n \"40P01\": \"VIBE_TRANSACTION\",\n /** query_canceled — statement_timeout fired */\n \"57014\": \"VIBE_TRANSACTION\",\n});\n\n/** SQLSTATEs that additionally explain themselves through `meta.reason`. */\nexport const PGLITE_SQLSTATE_REASONS: Readonly<Record<string, string>> = Object.freeze({\n \"23P01\": \"exclusion-violation\",\n \"57014\": \"timeout\",\n \"55P03\": \"lock-not-available\",\n \"40P01\": \"deadlock\",\n \"40001\": \"serialization-failure\",\n});\n\n// ─── Reading driver errors ────────────────────────────────────────\n\n/** A PostgreSQL SQLSTATE is exactly five digits/uppercase letters (e.g. `40P01`). */\nconst SQLSTATE_PATTERN = /^[0-9A-Z]{5}$/;\n\nfunction readStringField(params: { source: Record<string, unknown>; key: string }): string | undefined {\n const value = params.source[params.key];\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\n/**\n * Extract the SQLSTATE from a PGlite error. Failures raised by PGlite itself\n * (closed database, WASM init) carry no SQLSTATE and yield `undefined`.\n */\nexport function pgliteErrorSqlstate(params: { error: unknown }): string | undefined {\n const { error } = params;\n if (error === null || typeof error !== \"object\") return undefined;\n const code = readStringField({ source: error as Record<string, unknown>, key: \"code\" });\n return code !== undefined && SQLSTATE_PATTERN.test(code) ? code : undefined;\n}\n\n// ─── Mapping ──────────────────────────────────────────────────────\n\n/**\n * Map any error thrown by PGlite onto a `VibeError`.\n *\n * A `VibeError` passes through unchanged, so an error raised deeper inside the\n * ORM (or by a nested adapter call) is never re-wrapped.\n */\nexport function mapPgliteDriverError(params: { error: unknown }): VibeError {\n const { error } = params;\n if (error instanceof VibeError) return error;\n\n const source: Record<string, unknown> =\n error !== null && typeof error === \"object\" ? (error as Record<string, unknown>) : {};\n const sqlstate = pgliteErrorSqlstate({ error });\n const code: VibeErrorCode =\n (sqlstate === undefined ? undefined : PGLITE_SQLSTATE_ERROR_CODES[sqlstate]) ?? \"VIBE_ADAPTER\";\n\n const meta: Record<string, unknown> = {};\n if (sqlstate !== undefined) meta.sqlstate = sqlstate;\n const constraint = readStringField({ source, key: \"constraint\" });\n if (constraint !== undefined) meta.constraint = constraint;\n const table = readStringField({ source, key: \"table\" });\n if (table !== undefined) meta.table = table;\n const column = readStringField({ source, key: \"column\" });\n if (column !== undefined) meta.column = column;\n const reason = sqlstate === undefined ? undefined : PGLITE_SQLSTATE_REASONS[sqlstate];\n if (reason !== undefined) meta.reason = reason;\n\n const message =\n readStringField({ source, key: \"message\" }) ??\n (typeof error === \"string\" ? error : \"unknown pglite driver error\");\n\n return new VibeError({ code, message, meta, cause: error });\n}\n\n/** Run a driver call, mapping anything it throws onto a `VibeError`. */\nexport async function runMapped<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n throw mapPgliteDriverError({ error });\n }\n}\n",
|
|
7
7
|
"/**\n * Parameter serialization for PGlite.\n *\n * PGlite takes JS arrays natively for the array types it knows, but it picks a\n * parameter serializer from the BACKEND-INFERRED type OID and falls back to\n * `String(value)` for anything else — so a scalar list bound against a column\n * of a custom type (a native `enum`, i.e. every `Role[]` / `role IN (…)` query)\n * reached the server as `ADMIN,MODERATOR` and was rejected with `malformed\n * array literal`. ORM-path scalar lists are therefore rendered as PostgreSQL\n * array literals here, exactly like the bun:sql adapter does\n * (`@vibeorm/adapter-bun`'s `toPgArrayLiteral`); the server then coerces the\n * literal to whichever array type the statement needs (`text[]`, `int[]`,\n * `timestamptz[]`, `\"Role\"[]`).\n *\n * The ORM path and the raw path still split the same way (LEARNINGS.md): the\n * ORM path cannot tell a `jsonb` value that happens to be an array from a\n * scalar-list parameter, so it JSON-stringifies plain arrays and only treats\n * values tagged with {@link PgliteArrayParam} as scalar lists; the raw path\n * passes plain JS arrays straight through to the driver.\n */\n\nimport { VibeError } from \"@vibeorm/schema\";\n\n// ─── Scalar-list marker ───────────────────────────────────────────\n\n/**\n * Opaque token returned by `pgliteAdapter().formatArrayParam` marking a value\n * as a PostgreSQL array parameter (rather than a JSON value that happens to be\n * an array). The wrapped array is rendered as an array literal on the way out.\n */\nexport class PgliteArrayParam {\n /** The untouched scalar-list values. */\n readonly values: unknown[];\n\n constructor(values: unknown[]) {\n this.values = values;\n }\n}\n\n// ─── PostgreSQL array literals ────────────────────────────────────\n\n/** Quote and escape one array element: `\"` and `\\` are the special characters. */\nfunction quoteElement(value: string): string {\n return `\"${value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n}\n\n/**\n * Render a JS array as a PostgreSQL array literal string — the same element\n * rules as `@vibeorm/adapter-bun`'s `toPgArrayLiteral` (kept per-adapter: an\n * array literal is driver transport, not SQL text):\n * - `null` / `undefined` → unquoted `NULL`\n * - `number` / `bigint` / `boolean` → unquoted primitive\n * - `Date` → quoted ISO-8601 (PostgreSQL cannot parse `String(date)`)\n * - `string` → quoted, with `\"` and `\\` escaped (commas, braces and quotes\n * inside an element are safe)\n * - any other object, **including a nested array** → quoted `JSON.stringify`,\n * which is what a `Json[]` scalar list needs\n * - binary (`Uint8Array` / `ArrayBuffer`) → unsupported, throws\n *\n * @throws VibeError `VIBE_VALIDATION` for binary elements.\n */\nexport function toPgArrayLiteral(values: readonly unknown[]): string {\n const elements = values.map((value) => {\n if (value === null || value === undefined) return \"NULL\";\n if (typeof value === \"number\" || typeof value === \"bigint\" || typeof value === \"boolean\") {\n return String(value);\n }\n if (value instanceof Date) return quoteElement(value.toISOString());\n if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) {\n throw new VibeError({\n code: \"VIBE_VALIDATION\",\n message: \"binary values are not supported inside a postgres array literal\",\n meta: { driver: \"pglite\" },\n });\n }\n if (typeof value === \"string\") return quoteElement(value);\n if (typeof value === \"object\") return quoteElement(JSON.stringify(value));\n return quoteElement(String(value));\n });\n return `{${elements.join(\",\")}}`;\n}\n\n// ─── Serialization ────────────────────────────────────────────────\n\n/** True for values PGlite must receive verbatim (dates, binary, primitives, null). */\nfunction isDriverNativeValue(value: unknown): boolean {\n return (\n value === null ||\n value === undefined ||\n typeof value !== \"object\" ||\n value instanceof Date ||\n ArrayBuffer.isView(value) ||\n value instanceof ArrayBuffer\n );\n}\n\n/**\n * ORM hot path: render scalar-list markers as array literals, JSON-stringify\n * plain objects **and** plain arrays (they can only be `json`/`jsonb` values at\n * this point).\n */\nexport function serializeParams(params: { values: readonly unknown[] }): unknown[] {\n return params.values.map((value) => {\n if (value instanceof PgliteArrayParam) return toPgArrayLiteral(value.values);\n if (isDriverNativeValue(value)) return value;\n return JSON.stringify(value);\n });\n}\n\n/**\n * Raw path (`$queryRaw*` / `$executeRaw*` / DDL): identical to\n * {@link serializeParams} except that plain JS arrays pass straight through, so\n * `db.$queryRawUnsafe('… WHERE \"id\" = ANY($1)', [1, 2, 3])` matches rows.\n */\nexport function serializeParamsRaw(params: { values: readonly unknown[] }): unknown[] {\n return params.values.map((value) => {\n if (value instanceof PgliteArrayParam) return toPgArrayLiteral(value.values);\n if (Array.isArray(value)) return value;\n if (isDriverNativeValue(value)) return value;\n return JSON.stringify(value);\n });\n}\n",
|
|
8
|
-
"/**\n * Operation queue for PGlite.\n *\n * PGlite is a single embedded PostgreSQL connection: two overlapping\n * operations would interleave on the same wire, and an interleaved statement\n * inside a transaction would silently join that transaction. Every adapter\n * entry point therefore runs through one serial chain — including whole\n * `transaction()` calls, which occupy the chain until they commit or roll back.\n */\n\n/** A serial chain: jobs run one at a time, in the order they were queued. */\nexport type OperationQueue = {\n /** Queue `job`, resolving with its result once every earlier job has settled. */\n run<T>(job: () => Promise<T>): Promise<T>;\n};\n\n/** Create an empty operation queue. */\nexport function createOperationQueue(): OperationQueue {\n let tail: Promise<unknown> = Promise.resolve();\n\n return {\n run<T>(job: () => Promise<T>): Promise<T> {\n // Run after the previous job settles, whether it resolved or rejected.\n const result = tail.then(job, job);\n // Keep the chain alive: a rejected job must not reject every later job.\n tail = result.then(\n () => undefined,\n () => undefined,\n );\n return result;\n },\n };\n}\n",
|
|
9
|
-
"/**\n * Transaction-control SQL text (postgres dialect, PGlite flavour).\n *\n * PGlite issues its own `BEGIN` inside `pglite.transaction(cb)`, so isolation\n * is set with `SET TRANSACTION …` as the first statement of the callback rather\n * than as a `BEGIN` clause.\n */\n\nimport type { IsolationLevel
|
|
8
|
+
"/**\n * Operation queue for PGlite.\n *\n * PGlite is a single embedded PostgreSQL connection: two overlapping\n * operations would interleave on the same wire, and an interleaved statement\n * inside a transaction would silently join that transaction. Every adapter\n * entry point therefore runs through one serial chain — including whole\n * `transaction()` calls, which occupy the chain until they commit or roll back.\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\n/** Connection-wide exclusion shared by wrappers of an injected instance. */\nexport type ConnectionOwnership = {\n readonly queue: OperationQueue;\n readonly txContext: AsyncLocalStorage<true>;\n};\n\nconst INJECTED_OWNERSHIP: WeakMap<object, ConnectionOwnership> = new WeakMap();\n\n/** Reuse the same operation queue for the same caller-owned PGlite instance. */\nexport function connectionOwnership(params: { database?: object }): ConnectionOwnership {\n const existing = params.database === undefined ? undefined : INJECTED_OWNERSHIP.get(params.database);\n if (existing !== undefined) return existing;\n const ownership = { queue: createOperationQueue(), txContext: new AsyncLocalStorage<true>() };\n if (params.database !== undefined) INJECTED_OWNERSHIP.set(params.database, ownership);\n return ownership;\n}\n\n/** A serial chain: jobs run one at a time, in the order they were queued. */\nexport type OperationQueue = {\n /** Queue `job`, resolving with its result once every earlier job has settled. */\n run<T>(job: () => Promise<T>): Promise<T>;\n};\n\n/** Create an empty operation queue. */\nexport function createOperationQueue(): OperationQueue {\n let tail: Promise<unknown> = Promise.resolve();\n\n return {\n run<T>(job: () => Promise<T>): Promise<T> {\n // Run after the previous job settles, whether it resolved or rejected.\n const result = tail.then(job, job);\n // Keep the chain alive: a rejected job must not reject every later job.\n tail = result.then(\n () => undefined,\n () => undefined,\n );\n return result;\n },\n };\n}\n",
|
|
9
|
+
"/**\n * Transaction-control SQL text (postgres dialect, PGlite flavour).\n *\n * PGlite issues its own `BEGIN` inside `pglite.transaction(cb)`, so isolation\n * is set with `SET TRANSACTION …` as the first statement of the callback rather\n * than as a `BEGIN` clause.\n */\n\nimport type { IsolationLevel } from \"@vibeorm/runtime\";\n\n/** VibeORM isolation level → PostgreSQL isolation level keyword. */\nexport const ISOLATION_LEVEL_SQL: Readonly<Record<IsolationLevel, string>> = Object.freeze({\n ReadCommitted: \"READ COMMITTED\",\n RepeatableRead: \"REPEATABLE READ\",\n Serializable: \"SERIALIZABLE\",\n});\n\n/**\n * `SET TRANSACTION ISOLATION LEVEL <level>` — valid only as the first statement\n * of an open transaction, which is where the adapter issues it.\n */\nexport function setIsolationLevelStatement(params: { isolationLevel: IsolationLevel }): string {\n return `SET TRANSACTION ISOLATION LEVEL ${ISOLATION_LEVEL_SQL[params.isolationLevel]}`;\n}\n\n// NOTE (board #2): this module deliberately has NO statementTimeoutStatement.\n// PGlite accepts `SET LOCAL statement_timeout` and reports it back via SHOW,\n// but the single-threaded WASM build never fires it (live-verified:\n// `pg_sleep(2)` under a 100ms timeout runs to completion) — so the adapter\n// refuses the `timeout` option outright with VIBE_UNSUPPORTED_CAPABILITY\n// instead of rendering SQL that silently does nothing.\n\n// ─── Nested transaction options (the cross-adapter contract) ──────\n\n// ONE copy, shared by every adapter through the runtime's adapter-kit;\n// re-exported here so this adapter's public surface is unchanged.\nexport { refuseNestedTransactionOptions } from \"@vibeorm/runtime/adapter-kit\";\n"
|
|
10
10
|
],
|
|
11
|
-
"mappings": ";;;;AAWA
|
|
12
|
-
"debugId": "
|
|
11
|
+
"mappings": "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",
|
|
12
|
+
"debugId": "C5F6AEAFCFC17FFF64756E2164756E21",
|
|
13
13
|
"names": []
|
|
14
14
|
}
|
package/dist/queue.d.ts
CHANGED
|
@@ -7,6 +7,16 @@
|
|
|
7
7
|
* entry point therefore runs through one serial chain — including whole
|
|
8
8
|
* `transaction()` calls, which occupy the chain until they commit or roll back.
|
|
9
9
|
*/
|
|
10
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
11
|
+
/** Connection-wide exclusion shared by wrappers of an injected instance. */
|
|
12
|
+
export type ConnectionOwnership = {
|
|
13
|
+
readonly queue: OperationQueue;
|
|
14
|
+
readonly txContext: AsyncLocalStorage<true>;
|
|
15
|
+
};
|
|
16
|
+
/** Reuse the same operation queue for the same caller-owned PGlite instance. */
|
|
17
|
+
export declare function connectionOwnership(params: {
|
|
18
|
+
database?: object;
|
|
19
|
+
}): ConnectionOwnership;
|
|
10
20
|
/** A serial chain: jobs run one at a time, in the order they were queued. */
|
|
11
21
|
export type OperationQueue = {
|
|
12
22
|
/** Queue `job`, resolving with its result once every earlier job has settled. */
|
package/dist/queue.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,6EAA6E;AAC7E,MAAM,MAAM,cAAc,GAAG;IAC3B,iFAAiF;IACjF,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC3C,CAAC;AAEF,uCAAuC;AACvC,wBAAgB,oBAAoB,IAAI,cAAc,CAerD"}
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,4EAA4E;AAC5E,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC;CAC7C,CAAC;AAIF,gFAAgF;AAChF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,mBAAmB,CAMtF;AAED,6EAA6E;AAC7E,MAAM,MAAM,cAAc,GAAG;IAC3B,iFAAiF;IACjF,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC3C,CAAC;AAEF,uCAAuC;AACvC,wBAAgB,oBAAoB,IAAI,cAAc,CAerD"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* is set with `SET TRANSACTION …` as the first statement of the callback rather
|
|
6
6
|
* than as a `BEGIN` clause.
|
|
7
7
|
*/
|
|
8
|
-
import type { IsolationLevel
|
|
8
|
+
import type { IsolationLevel } from "@vibeorm/runtime";
|
|
9
9
|
/** VibeORM isolation level → PostgreSQL isolation level keyword. */
|
|
10
10
|
export declare const ISOLATION_LEVEL_SQL: Readonly<Record<IsolationLevel, string>>;
|
|
11
11
|
/**
|
|
@@ -15,18 +15,5 @@ export declare const ISOLATION_LEVEL_SQL: Readonly<Record<IsolationLevel, string
|
|
|
15
15
|
export declare function setIsolationLevelStatement(params: {
|
|
16
16
|
isolationLevel: IsolationLevel;
|
|
17
17
|
}): string;
|
|
18
|
-
|
|
19
|
-
* Refuse options on a NESTED `transaction()` call — the same contract on every
|
|
20
|
-
* adapter (see the `DatabaseAdapter.transaction` JSDoc in @vibeorm/runtime):
|
|
21
|
-
* a nested transaction is a SAVEPOINT, and a savepoint can neither change the
|
|
22
|
-
* isolation level of the transaction it joins nor enforce its own timeout.
|
|
23
|
-
* Silently dropping the option (the pre-#3 behaviour) hid exactly that.
|
|
24
|
-
*
|
|
25
|
-
* @throws VibeError `VIBE_VALIDATION` when `isolationLevel` or `timeout` is
|
|
26
|
-
* present (an `undefined` or empty options object is accepted).
|
|
27
|
-
*/
|
|
28
|
-
export declare function refuseNestedTransactionOptions(params: {
|
|
29
|
-
options?: TransactionOptions;
|
|
30
|
-
provider: string;
|
|
31
|
-
}): void;
|
|
18
|
+
export { refuseNestedTransactionOptions } from "@vibeorm/runtime/adapter-kit";
|
|
32
19
|
//# sourceMappingURL=transaction-sql.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction-sql.d.ts","sourceRoot":"","sources":["../src/transaction-sql.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"transaction-sql.d.ts","sourceRoot":"","sources":["../src/transaction-sql.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,oEAAoE;AACpE,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAIvE,CAAC;AAEH;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE;IAAE,cAAc,EAAE,cAAc,CAAA;CAAE,GAAG,MAAM,CAE7F;AAaD,OAAO,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeorm/adapter-pglite",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "PGlite (in-process Postgres) adapter for VibeORM v2",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"orm",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@electric-sql/pglite": "^0.3.0 || ^0.4.0 || ^0.5.0",
|
|
47
|
-
"@vibeorm/runtime": "2.
|
|
48
|
-
"@vibeorm/schema": "2.
|
|
47
|
+
"@vibeorm/runtime": "2.3.0",
|
|
48
|
+
"@vibeorm/schema": "2.2.0"
|
|
49
49
|
},
|
|
50
50
|
"publishConfig": {
|
|
51
51
|
"access": "public"
|