@vibeorm/runtime 1.3.0 → 2.0.0-alpha.10

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 (96) hide show
  1. package/README.md +50 -107
  2. package/dist/adapter.d.ts +250 -0
  3. package/dist/adapter.d.ts.map +1 -0
  4. package/dist/bulk-upsert.d.ts +282 -0
  5. package/dist/bulk-upsert.d.ts.map +1 -0
  6. package/dist/client.d.ts +200 -0
  7. package/dist/client.d.ts.map +1 -0
  8. package/dist/codecs.d.ts +170 -0
  9. package/dist/codecs.d.ts.map +1 -0
  10. package/dist/computed.d.ts +43 -0
  11. package/dist/computed.d.ts.map +1 -0
  12. package/dist/db-now.d.ts +41 -0
  13. package/dist/db-now.d.ts.map +1 -0
  14. package/dist/diagnostics/index.d.ts +12 -0
  15. package/dist/diagnostics/index.d.ts.map +1 -0
  16. package/dist/diagnostics/insight.d.ts +63 -0
  17. package/dist/diagnostics/insight.d.ts.map +1 -0
  18. package/dist/diagnostics/plan.d.ts +88 -0
  19. package/dist/diagnostics/plan.d.ts.map +1 -0
  20. package/dist/diagnostics/preview.d.ts +43 -0
  21. package/dist/diagnostics/preview.d.ts.map +1 -0
  22. package/dist/diagnostics/types.d.ts +223 -0
  23. package/dist/diagnostics/types.d.ts.map +1 -0
  24. package/dist/diagnostics/workload.d.ts +32 -0
  25. package/dist/diagnostics/workload.d.ts.map +1 -0
  26. package/dist/extensions.d.ts +102 -0
  27. package/dist/extensions.d.ts.map +1 -0
  28. package/dist/index.d.ts +59 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +13070 -0
  31. package/dist/index.js.map +43 -0
  32. package/dist/keyset-iterator.d.ts +73 -0
  33. package/dist/keyset-iterator.d.ts.map +1 -0
  34. package/dist/keyset.d.ts +121 -0
  35. package/dist/keyset.d.ts.map +1 -0
  36. package/dist/model-meta.d.ts +200 -0
  37. package/dist/model-meta.d.ts.map +1 -0
  38. package/dist/nested-writes.d.ts +67 -0
  39. package/dist/nested-writes.d.ts.map +1 -0
  40. package/dist/policy-operation.d.ts +14 -0
  41. package/dist/policy-operation.d.ts.map +1 -0
  42. package/dist/policy.d.ts +17 -0
  43. package/dist/policy.d.ts.map +1 -0
  44. package/dist/query-builder.d.ts +271 -0
  45. package/dist/query-builder.d.ts.map +1 -0
  46. package/dist/relation-key.d.ts +23 -0
  47. package/dist/relation-key.d.ts.map +1 -0
  48. package/dist/relation-loader.d.ts +46 -0
  49. package/dist/relation-loader.d.ts.map +1 -0
  50. package/dist/relation-plan.d.ts +141 -0
  51. package/dist/relation-plan.d.ts.map +1 -0
  52. package/dist/render-cache.d.ts +48 -0
  53. package/dist/render-cache.d.ts.map +1 -0
  54. package/dist/rls-context.d.ts +14 -0
  55. package/dist/rls-context.d.ts.map +1 -0
  56. package/dist/rls-readiness.d.ts +114 -0
  57. package/dist/rls-readiness.d.ts.map +1 -0
  58. package/dist/scoped.d.ts +104 -0
  59. package/dist/scoped.d.ts.map +1 -0
  60. package/dist/strict-args.d.ts +47 -0
  61. package/dist/strict-args.d.ts.map +1 -0
  62. package/dist/telemetry/collector.d.ts +53 -0
  63. package/dist/telemetry/collector.d.ts.map +1 -0
  64. package/dist/telemetry/config.d.ts +53 -0
  65. package/dist/telemetry/config.d.ts.map +1 -0
  66. package/dist/telemetry/fingerprint.d.ts +38 -0
  67. package/dist/telemetry/fingerprint.d.ts.map +1 -0
  68. package/dist/telemetry/index.d.ts +18 -0
  69. package/dist/telemetry/index.d.ts.map +1 -0
  70. package/dist/telemetry/recorder.d.ts +93 -0
  71. package/dist/telemetry/recorder.d.ts.map +1 -0
  72. package/dist/telemetry/statement.d.ts +53 -0
  73. package/dist/telemetry/statement.d.ts.map +1 -0
  74. package/dist/telemetry/types.d.ts +265 -0
  75. package/dist/telemetry/types.d.ts.map +1 -0
  76. package/dist/validators.d.ts +61 -0
  77. package/dist/validators.d.ts.map +1 -0
  78. package/dist/views.d.ts +97 -0
  79. package/dist/views.d.ts.map +1 -0
  80. package/dist/write-scope.d.ts +14 -0
  81. package/dist/write-scope.d.ts.map +1 -0
  82. package/package.json +33 -26
  83. package/src/adapter.ts +0 -146
  84. package/src/client.ts +0 -2172
  85. package/src/coerce.ts +0 -184
  86. package/src/count-loader.ts +0 -152
  87. package/src/errors.ts +0 -492
  88. package/src/id-generators.ts +0 -151
  89. package/src/index.ts +0 -55
  90. package/src/lateral-join-builder.ts +0 -1053
  91. package/src/query-builder.ts +0 -1832
  92. package/src/relation-loader.ts +0 -534
  93. package/src/retry.ts +0 -183
  94. package/src/types.ts +0 -317
  95. package/src/view.ts +0 -629
  96. package/src/where-builder.ts +0 -772
package/README.md CHANGED
@@ -1,141 +1,84 @@
1
1
  # @vibeorm/runtime
2
2
 
3
- Driver-agnostic query engine and client runtime for VibeORM. This package contains the SQL query builder, WHERE clause compiler, relation loading strategies, and client factory. It does **not** include any database driver — use an adapter package to connect to PostgreSQL.
3
+ > Part of **[VibeORM](https://github.com/vibeorm/vibeorm)** — a type-safe TypeScript ORM for Bun and Node. Prisma-schema or TypeScript-DSL input, a canonical schema IR, a generated client, and a dialect-aware SQL layer over PostgreSQL, PGlite, SQLite and MySQL.
4
4
 
5
- ## Installation
5
+ The query engine behind the generated client: it turns delegate calls into SQL statements, loads relations, runs nested writes and moves values across the wire through the codec table. It is its own package because it is driver-agnostic — it talks to databases only through the `DatabaseAdapter` contract, so adapters and the generator can depend on it without depending on each other.
6
6
 
7
7
  ```bash
8
- bun add @vibeorm/runtime
8
+ bun add @vibeorm/runtime@alpha
9
9
  ```
10
10
 
11
- You also need an adapter:
11
+ > **Pre-release.** `2.0.0-alpha.x`, published under the `alpha` dist-tag. `npm i vibeorm` still resolves to the stable v1 line.
12
12
 
13
- ```bash
14
- bun add @vibeorm/adapter-bun # for bun:sql
15
- # or
16
- bun add @vibeorm/adapter-pg pg # for node-postgres
17
- ```
13
+ Most users never install this directly — it ships as a dependency of [`vibeorm`](https://www.npmjs.com/package/vibeorm) and of the generated client. Reach for it when you are writing an adapter or tooling against the runtime.
18
14
 
19
- ## Usage
15
+ ## What it does
20
16
 
21
- This package is consumed by the generated client. You typically don't import from it directly — the generated `index.ts` calls `createClient()` internally.
17
+ `createClient({ schema, adapter, options })` builds a `DynamicClient` from the Schema IR at runtime: model delegates keyed by both camelCase client name and model name (`$models`), plus `$transaction`, `$queryRaw`, `$executeRaw`, `$queryRawUnsafe`, `$executeRawUnsafe`, `$on`, `$connect` and `$disconnect`. The delegates are deliberately broad here (`ClientRow` in, `ClientRow` out); the generated `.d.ts` declares the precise per-model types on top.
22
18
 
23
- ```ts
24
- // The generated client wires everything together:
25
- import { VibeClient } from "./generated/vibeorm/index.ts";
26
-
27
- const db = VibeClient({
28
- relationStrategy: "query",
29
- log: false,
30
- });
31
- ```
19
+ Each `ModelDelegate` implements 16 methods:
32
20
 
33
- ## API
21
+ | Group | Methods |
22
+ |---|---|
23
+ | Read | `findMany` · `findFirst` · `findFirstOrThrow` · `findUnique` · `findUniqueOrThrow` |
24
+ | Create | `create` · `createMany` · `createManyAndReturn` |
25
+ | Update | `update` · `updateMany` · `upsert` |
26
+ | Delete | `delete` · `deleteMany` |
27
+ | Aggregate | `count` · `aggregate` · `groupBy` |
34
28
 
35
- ### `createClient({ options, modelMeta, schemas? })`
29
+ The statement-building pieces are exported too, for tooling that needs SQL without executing it: `buildQuery`, `compileWhere`, `compileSelect`, `compileOrderBy`, `resolveResultShape`, and the runtime metadata builders `buildRuntimeMeta`, `getModelMeta`, `getFieldMeta`.
36
30
 
37
- Creates a VibeORM client instance. Called by generated code — takes model metadata, optional Zod schemas, and client options.
31
+ ## The adapter contract
38
32
 
39
- `countStrategy` can be set globally in client options and overridden per count call:
33
+ `DatabaseAdapter` is frozen. Implement it and any driver works with the whole ORM:
40
34
 
41
35
  ```ts
42
- await db.user.count({
43
- where: { isActive: true },
44
- countStrategy: "subquery",
45
- });
36
+ import type { DatabaseAdapter, QueryResult, TransactionOptions } from "@vibeorm/runtime";
37
+
38
+ const adapter: DatabaseAdapter = {
39
+ dialect: "postgres",
40
+ provider: "postgresql",
41
+ async execute(params: { text: string; values: unknown[] }): Promise<Record<string, unknown>[]> { /* … */ },
42
+ async executeUnsafe(params: { text: string; values?: unknown[] }): Promise<QueryResult> { /* … */ },
43
+ async transaction<T>(fn: (tx: DatabaseAdapter) => Promise<T>, options?: TransactionOptions): Promise<T> { /* … */ },
44
+ async connect(): Promise<void> { /* … */ },
45
+ async disconnect(): Promise<void> { /* … */ },
46
+ formatArrayParam(values: unknown[]): unknown { /* … */ },
47
+ };
46
48
  ```
47
49
 
48
- Per-operation `countStrategy` takes precedence over the client default.
49
-
50
- ### Mutation RETURNING behavior
51
-
52
- `create`, `update`, `delete`, and `upsert` now narrow SQL `RETURNING` columns when `select` is provided, reducing row payload size.
53
-
54
- - Default behavior: full scalar row is returned (same as before)
55
- - With `select`: only selected scalar columns are returned (plus internal keys when needed)
56
- - With `returning: true`: force full scalar `RETURNING` payload even when `select` is present
50
+ - `execute` is the ORM hot path (row-returning, statement-cached by the adapter). `executeUnsafe` is the raw/DDL path and is the only place `affectedRows` surfaces.
51
+ - `transaction` nests: an inner call creates a savepoint. `isolationLevel` and `timeout` are top-level only — a nested call must refuse both with `VIBE_VALIDATION`.
52
+ - Adapters never let raw driver errors escape. Each maps its driver's failures to `VibeError` codes (`VIBE_UNIQUE_VIOLATION`, `VIBE_FK_VIOLATION`, `VIBE_TRANSACTION`, `VIBE_ADAPTER`) through a per-driver table, with the driver error as `cause`.
53
+ - `formatArrayParam` converts a JS array into the driver's preferred scalar-array representation; the ORM path binds arrays through it, the raw path does not.
54
+ - The optional `wire` declaration (`WireFidelity`) tells the runtime what the driver already delivers for non-list scalars, so provably no-op decoders can be skipped.
57
55
 
58
- ### `toSqlExecutor({ adapter })`
56
+ `toSqlExecutor({ adapter })` bridges an adapter to the `SqlExecutor` shape `@vibeorm/migrate` runs on.
59
57
 
60
- Bridges a `DatabaseAdapter` to a `SqlExecutor` for use with the migrate package.
61
-
62
- ### `withRetry(fn, options?)`
63
-
64
- Retry utility with exponential backoff and jitter. Only retries `VibeTransientError` instances (connection failures, deadlocks, serialization conflicts, statement timeouts, pool exhaustion). Deterministic errors (`VibeRequestError`) are never retried.
58
+ ## Relation strategies
65
59
 
66
60
  ```ts
67
- import { withRetry } from "@vibeorm/runtime";
68
-
69
- // Basic — 3 retries, exponential backoff with jitter
70
- const users = await withRetry(() =>
71
- db.user.findMany({ where: { active: true } })
72
- );
73
-
74
- // Custom options
75
- const user = await withRetry(
76
- () => db.user.create({ data: { email: "new@example.com" } }),
77
- { maxRetries: 5, baseDelay: 100, maxDelay: 10000 },
78
- );
79
-
80
- // Retry only specific error codes
81
- const result = await withRetry(
82
- () => db.$transaction(async (tx) => {
83
- /* ... */
84
- }, { isolationLevel: "Serializable" }),
85
- { retryOn: ["SERIALIZATION_FAILURE", "DEADLOCK"] },
86
- );
87
-
88
- // With abort signal
89
- const controller = new AbortController();
90
- const result = await withRetry(
91
- () => db.user.findFirst({ where: { id: 1 } }),
92
- { signal: controller.signal },
93
- );
61
+ const db = createClient({ schema, adapter, options: { relationStrategy: "join" } });
94
62
  ```
95
63
 
96
- **Options (`RetryOptions`):**
97
-
98
- | Option | Default | Description |
99
- |--------|---------|-------------|
100
- | `maxRetries` | `3` | Max retry attempts (total executions = maxRetries + 1) |
101
- | `baseDelay` | `50` | Base delay in ms for exponential backoff |
102
- | `maxDelay` | `5000` | Maximum delay cap in ms |
103
- | `maxJitter` | `50` | Random jitter added per retry to prevent thundering herd |
104
- | `signal` | — | `AbortSignal` to cancel pending retries |
105
- | `retryOn` | — | Filter to retry only specific `VibeTransientErrorCode`s |
106
- | `onRetry` | — | Callback `({ error, attempt, delay }) => void` for logging/metrics |
107
-
108
- Backoff formula: `min(baseDelay * 2^attempt + random(0, maxJitter), maxDelay)`
109
-
110
- ### `VibeValidationError`
64
+ - `"query"` (default): one query per relation, batched with `WHERE ... IN`. Works on every dialect.
65
+ - `"join"`: a single statement using `LEFT JOIN LATERAL` with JSON aggregation. PostgreSQL and PGlite only; other dialects throw `VibeError` with code `VIBE_UNSUPPORTED_CAPABILITY`.
111
66
 
112
- Custom error class thrown when Zod validation fails on input or output data.
67
+ A `relationStrategy` argument on a find overrides the client default. Relation trees are resolved by `resolveRelationSelection` / `resolveRelationLink` and attached by `attachRelations` (query strategy) or `attachLateralRelations` (join strategy).
113
68
 
114
- ### `DatabaseAdapter` interface
69
+ ## Codecs
115
70
 
116
- The contract that adapter packages implement:
71
+ Value encoding and decoding lives in one table per dialect: `POSTGRES_CODECS`, `SQLITE_CODECS`, `MYSQL_CODECS`, indexed by `DIALECT_CODECS` and reachable through `getCodec({ dialect, type })`. Nothing else in the codebase coerces values — scattered coercion is what produced v1's BigInt, enum-array and timestamp bugs.
117
72
 
118
73
  ```ts
119
- type DatabaseAdapter = {
120
- execute(params: { text: string; values: unknown[] }): Promise<Record<string, unknown>[]>;
121
- executeRaw(params: { text: string; values: unknown[] }): Promise<QueryResult>;
122
- transaction<T>(params: { fn: (adapter: DatabaseAdapter) => Promise<T> }): Promise<T>;
123
- connect(): Promise<void>;
124
- disconnect(): Promise<void>;
125
- };
74
+ import { decodeRows, encodeValue, getCodec } from "@vibeorm/runtime";
126
75
  ```
127
76
 
128
- ### Relation Loading Strategies
129
-
130
- | Strategy | Method | Best for |
131
- |----------|--------|----------|
132
- | `"query"` | Parent query + batched `WHERE IN` queries | Deep/nested includes |
133
- | `"join"` | `LEFT JOIN LATERAL` + JSON aggregation | Flat includes, fewer round-trips |
134
-
135
- ### Exported Types
136
-
137
- `DatabaseAdapter`, `QueryResult`, `SqlExecutor`, `VibeClientOptions`, `ModelMeta`, `ModelMetaMap`, `ModelSchemas`, `ValidationSchema`, `QueryProfile`, `RelationProfile`, `ScalarFieldMeta`, `RelationFieldMeta`, `SqlQuery`, `Operation`, `RetryOptions`.
77
+ `encodeValue` runs on every parameter, `decodeValue` / `decodeRow` / `decodeRows` on every row materialization point — including relation children and join-strategy rows, not only top-level parents. `decodeAggregateValue` handles aggregate columns, whose result type differs from the underlying field's.
138
78
 
139
- ## License
79
+ ## Links
140
80
 
141
- [MIT](../../LICENSE)
81
+ - [Documentation](https://github.com/vibeorm/vibeorm/tree/master/docs)
82
+ - [Query API](https://github.com/vibeorm/vibeorm/blob/master/docs/queries.md)
83
+ - [Repository and issues](https://github.com/vibeorm/vibeorm)
84
+ - MIT licensed
@@ -0,0 +1,250 @@
1
+ /**
2
+ * Database adapter contract for VibeORM v2. FROZEN INTERFACE — the runtime is
3
+ * driver-agnostic and talks to databases exclusively through this type;
4
+ * adapter packages (adapter-bun, adapter-pg, adapter-pglite, adapter-sqlite,
5
+ * adapter-mysql) implement it.
6
+ *
7
+ * ERROR CONTRACT: adapters never let raw driver errors escape. Every failure
8
+ * is mapped to a VibeError with a stable code via a per-driver table
9
+ * (unique violation → VIBE_UNIQUE_VIOLATION, FK violation → VIBE_FK_VIOLATION,
10
+ * serialization/deadlock → VIBE_TRANSACTION, connection/other → VIBE_ADAPTER),
11
+ * with the driver error attached as `cause`.
12
+ */
13
+ import type { Dialect, Provider } from "@vibeorm/schema";
14
+ import type { WireFidelity } from "@vibeorm/sql";
15
+ /** Transaction isolation levels (mapped per dialect by the adapter). */
16
+ export type IsolationLevel = "ReadCommitted" | "RepeatableRead" | "Serializable";
17
+ /**
18
+ * What a caller REQUIRES of a transaction deadline (EPIC 6).
19
+ *
20
+ * - `"between-statements"` (the default, deliverable by every adapter): an
21
+ * expired budget refuses the next statement, refuses the `COMMIT`, and rolls
22
+ * back. A statement already in flight is NOT interrupted.
23
+ * - `"cancel-running-statements"`: additionally hands the engine the remaining
24
+ * budget as `statement_timeout`, so the SERVER cancels an over-long
25
+ * statement. Postgres servers only (`adapter-pg`, `adapter-bun`); every other
26
+ * adapter refuses the request with `VIBE_UNSUPPORTED_CAPABILITY` rather than
27
+ * quietly delivering the weaker level.
28
+ */
29
+ export type TransactionDeadlineEnforcement = "between-statements" | "cancel-running-statements";
30
+ /**
31
+ * A TOTAL wall-clock budget for one top-level transaction (EPIC 6) — distinct
32
+ * from {@link TransactionOptions.timeout}, which bounds a single statement.
33
+ *
34
+ * The clock starts immediately before `BEGIN` is sent, so acquiring a
35
+ * connection (bounded separately by the pooled adapters' own acquire timeout)
36
+ * is NOT counted against it.
37
+ *
38
+ * On expiry the adapter refuses the next statement, refuses the commit and
39
+ * rolls back, and every handle of that transaction becomes unusable. Nothing
40
+ * is retried automatically: a callback's external side effects (an SMS, a
41
+ * payment, a queued job) may already have happened. JavaScript cannot forcibly
42
+ * stop a running callback — it can only refuse its later database calls.
43
+ */
44
+ export type TransactionDeadline = {
45
+ /** Whole milliseconds, greater than zero. */
46
+ readonly totalMs: number;
47
+ /** Defaults to `"between-statements"`. */
48
+ readonly enforcement?: TransactionDeadlineEnforcement;
49
+ };
50
+ /**
51
+ * Options for `$transaction` / `adapter.transaction`.
52
+ *
53
+ * `timeout` is milliseconds, enforced database-side where the engine can
54
+ * genuinely cancel a running statement (postgres servers via `SET LOCAL
55
+ * statement_timeout`, mysql's SELECT-only `MAX_EXECUTION_TIME`). Dialect
56
+ * honesty: an adapter whose engine CANNOT enforce it refuses loudly instead
57
+ * of no-opping — sqlite adapters throw `VIBE_VALIDATION` (busy_timeout only
58
+ * bounds lock acquisition), pglite throws `VIBE_UNSUPPORTED_CAPABILITY` (the
59
+ * WASM build accepts statement_timeout but never fires it). Its meaning is
60
+ * UNCHANGED by the deadline work below: it is a PER-STATEMENT bound.
61
+ *
62
+ * `deadline` is the TOTAL budget for the whole transaction — see
63
+ * {@link TransactionDeadline}.
64
+ *
65
+ * Options are TOP-LEVEL only: a nested `transaction()` call (a savepoint)
66
+ * refuses ALL THREE fields with `VIBE_VALIDATION` on every adapter — a
67
+ * savepoint cannot change the isolation level of the transaction it joins,
68
+ * a nested timeout is not enforceable, and a nested deadline would need an
69
+ * independent session setting on a connection it does not own. A nested
70
+ * savepoint instead INHERITS the top-level deadline, by reference.
71
+ */
72
+ export type TransactionOptions = {
73
+ isolationLevel?: IsolationLevel;
74
+ timeout?: number;
75
+ deadline?: TransactionDeadline;
76
+ };
77
+ /**
78
+ * How far an engine's per-statement timeout actually reaches.
79
+ *
80
+ * Tri-state rather than boolean because MySQL's `MAX_EXECUTION_TIME` bounds
81
+ * **SELECT statements only** — INSERT/UPDATE/DELETE run unbounded there, so
82
+ * declaring `true` would be exactly the silent misbehaviour constitution rule 4
83
+ * forbids.
84
+ */
85
+ export type StatementTimeoutSupport = "all-statements" | "select-only" | "unsupported";
86
+ /** The strongest transaction-deadline guarantee an adapter can honestly deliver. */
87
+ export type TransactionDeadlineSupport = "cancel-running-statements" | "between-statements" | "unsupported";
88
+ /**
89
+ * What timing budgets this adapter genuinely enforces (EPIC 6). Read it to
90
+ * decide what to ask for; the adapter refuses anything beyond it rather than
91
+ * degrading silently.
92
+ */
93
+ export type AdapterBudgetSupport = {
94
+ /**
95
+ * The wait for a pooled connection is bounded. False on the single-connection
96
+ * engines (pglite, both sqlite adapters), which have no pool to exhaust.
97
+ */
98
+ readonly acquireTimeout: boolean;
99
+ /** What `TransactionOptions.timeout` reaches on this engine. */
100
+ readonly statementTimeout: StatementTimeoutSupport;
101
+ /** What `TransactionOptions.deadline.enforcement` may ask for on this engine. */
102
+ readonly transactionDeadline: TransactionDeadlineSupport;
103
+ };
104
+ /** Result of an unsafe/raw execution: rows plus affected-row count. */
105
+ export type QueryResult = {
106
+ rows: Record<string, unknown>[];
107
+ affectedRows: number;
108
+ };
109
+ /**
110
+ * The primary interface every database adapter implements. Adapters own
111
+ * connection management, statement caching, transactions (including nested →
112
+ * savepoints), driver-specific parameter formatting and driver-error mapping.
113
+ */
114
+ export type DatabaseAdapter = {
115
+ /** SQL dialect this adapter's database speaks (selects the @vibeorm/sql dialect). */
116
+ readonly dialect: Dialect;
117
+ /** Concrete provider (pglite and postgresql both speak `postgres`). */
118
+ readonly provider: Provider;
119
+ /**
120
+ * What this DRIVER actually delivers for non-list scalar columns on the
121
+ * result path (board #30) — lets the runtime's decode plans skip decoders
122
+ * that are provably no-ops for this driver (e.g. node-postgres already hands
123
+ * `Date` for timestamptz and parsed values for jsonb). OPTIONAL and purely
124
+ * an optimization contract: an adapter that declares nothing gets the full
125
+ * idempotency-guarded decode path. Declare only what the driver verifiably
126
+ * does; transactional adapters must carry the same declaration.
127
+ */
128
+ readonly wire?: WireFidelity;
129
+ /**
130
+ * Execute a parameterized query on the ORM hot path and return rows.
131
+ * The adapter owns prepared-statement caching and ORM-path parameter
132
+ * serialization (e.g. tagged scalar-list params vs JSON values).
133
+ */
134
+ execute(params: {
135
+ text: string;
136
+ values: unknown[];
137
+ }): Promise<Record<string, unknown>[]>;
138
+ /**
139
+ * Execute a raw query (`$queryRaw*`, `$executeRaw*`, DDL). No statement
140
+ * caching; raw-path parameter serialization (arrays pass through to the
141
+ * driver where it supports them — see LEARNINGS: raw vs ORM paths differ).
142
+ *
143
+ * OMITTING `values` changes semantics on the sqlite adapters (board #31):
144
+ * `adapter-sqlite` and `adapter-better-sqlite3` route no-`values` text
145
+ * through the driver's multi-statement script mode (`db.run`/`exec` — the
146
+ * shape @vibeorm/migrate emits for DDL/PRAGMA batches), which CANNOT return
147
+ * rows: a parameterless SELECT yields `rows: []` there, while pg/pglite/
148
+ * mysql/bun return its result set either way. Callers that want rows from a
149
+ * single parameterless statement must pass `values: []` — the client's
150
+ * `$queryRawUnsafe` always does. Rule of thumb: `values` present (even
151
+ * empty) = one prepared statement with rows; `values` absent = script mode,
152
+ * rows not guaranteed.
153
+ */
154
+ executeUnsafe(params: {
155
+ text: string;
156
+ values?: unknown[];
157
+ }): Promise<QueryResult>;
158
+ /**
159
+ * ORM-path execution (same protocol and parameter serialization as
160
+ * {@link DatabaseAdapter.execute}) that ALSO reports the affected-row count.
161
+ *
162
+ * WHY IT EXISTS (F01): bulk mutations need a row count, and `executeUnsafe`
163
+ * used to be the only entry point that surfaces one — but `executeUnsafe` is
164
+ * the RAW path, and a driver is free to implement it with client-side text
165
+ * escaping. mysql2 does (`pool.query`), and client-side escaping cannot know
166
+ * the server's `sql_mode`: under `NO_BACKSLASH_ESCAPES` a hostile string
167
+ * predicate breaks out of its literal. Generated statements must never take
168
+ * that route, so the runtime prefers this entry point and only falls back to
169
+ * `executeUnsafe` for an adapter that does not implement it.
170
+ *
171
+ * OPTIONAL, so the frozen contract stays additive: an adapter whose raw path
172
+ * already binds parameters (pg, pglite, bun, both sqlite adapters) is equally
173
+ * safe without it. An implementation MUST bind — never interpolate, and never
174
+ * fall back to text interpolation when preparation fails.
175
+ */
176
+ executeAffected?(params: {
177
+ text: string;
178
+ values: unknown[];
179
+ }): Promise<QueryResult>;
180
+ /**
181
+ * What timing budgets this adapter actually enforces (EPIC 6).
182
+ *
183
+ * OPTIONAL, so the frozen contract stays additive — exactly like
184
+ * {@link DatabaseAdapter.executeAffected}. An adapter that declares nothing
185
+ * is treated as declaring nothing: callers must not infer support from a
186
+ * provider name. Every adapter in this repository declares it.
187
+ */
188
+ readonly budgets?: AdapterBudgetSupport;
189
+ /**
190
+ * Run `fn` inside a transaction; the callback receives a transactional
191
+ * adapter with this same interface. Nested calls create savepoints. Throwing
192
+ * rolls back (the savepoint or the whole transaction) and rethrows.
193
+ *
194
+ * `options` is honored on TOP-LEVEL calls only. A NESTED call refuses any
195
+ * `isolationLevel` or `timeout` with `VIBE_VALIDATION` (`meta.nested:
196
+ * true`), identically on every adapter: a savepoint cannot change the
197
+ * isolation level of the transaction it joins, and a nested timeout is not
198
+ * enforceable. Silently dropping the option was the pre-#3 behaviour of the
199
+ * pg/pglite/mysql/bun adapters and is forbidden by constitution rule 4.
200
+ */
201
+ transaction<T>(fn: (txAdapter: DatabaseAdapter) => Promise<T>, options?: TransactionOptions): Promise<T>;
202
+ /** Eagerly open/verify connectivity (pool warm-up or first connection). */
203
+ connect(): Promise<void>;
204
+ /**
205
+ * Gracefully close the connections open right now. NOT terminal: every
206
+ * adapter constructs its pool/connection lazily, so a query issued after
207
+ * `disconnect()` transparently opens a NEW connection and succeeds — the
208
+ * documented contract (symmetric with lazy construction, and with Prisma's
209
+ * `$disconnect()`-then-query semantics), not an accident.
210
+ */
211
+ disconnect(): Promise<void>;
212
+ /**
213
+ * Convert a JS array into the driver's preferred representation for a
214
+ * scalar-array parameter (postgres `= ANY($n)`): PG array literal string for
215
+ * drivers that send strings, the raw array for drivers with native support.
216
+ */
217
+ formatArrayParam(values: unknown[]): unknown;
218
+ };
219
+ /** Minimal SQL execution interface used by @vibeorm/migrate. */
220
+ export type SqlExecutor = (params: {
221
+ text: string;
222
+ values?: unknown[];
223
+ }) => Promise<Record<string, unknown>[]>;
224
+ /**
225
+ * Bridge a DatabaseAdapter to the migrate package's SqlExecutor shape.
226
+ *
227
+ * NO SESSION AFFINITY — this bridge pins nothing. Every call goes through
228
+ * `adapter.executeUnsafe`, which a pooled adapter runs on whatever connection
229
+ * the pool hands out. @vibeorm/migrate's executor contract requires the
230
+ * opposite (`packages/migrate/src/types.ts`): its session-scoped statements
231
+ * (`BEGIN`/`COMMIT`, `PRAGMA foreign_keys`, `pg_advisory_lock` / `GET_LOCK`)
232
+ * must all reach ONE session. pglite and sqlite satisfy that by construction;
233
+ * a POOLED adapter (pg, mysql, bun) used for migrate must be constructed with
234
+ * a single-connection pool (`max: 1`; mysql `connectionLimit: 1`), as the
235
+ * `vibeorm` CLI does, or the caller must pin a connection another way —
236
+ * otherwise the advisory lock is taken on one connection while each
237
+ * migration's `BEGIN` runs on another, and a driver that reaps the idle
238
+ * lock-holding connection (node-postgres does, after 10s by default) releases
239
+ * the migration lock mid-run, silently.
240
+ *
241
+ * RE-ENTRANCY HAZARD: `pg_advisory_lock` is re-entrant per SESSION, so two
242
+ * concurrent `applyMigrations` calls sharing one adapter (hence one pool) can
243
+ * both "acquire" it on the same underlying connection and get zero mutual
244
+ * exclusion — separate CLI processes never collide this way, a programmatic
245
+ * caller sharing one adapter can.
246
+ */
247
+ export declare function toSqlExecutor(params: {
248
+ adapter: DatabaseAdapter;
249
+ }): SqlExecutor;
250
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}