@nextlyhq/adapter-drizzle 0.0.2-alpha.67 → 0.0.2-alpha.69
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/adapter-BypoOEEN.d.cts +1166 -0
- package/dist/adapter-CSP-Ek-L.d.ts +1166 -0
- package/dist/index-BYb6cDli.d.ts +1168 -0
- package/dist/index-C4HJsfwA.d.cts +1168 -0
- package/dist/index.cjs +2258 -2183
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -10
- package/dist/index.d.ts +5 -10
- package/dist/index.mjs +2257 -2181
- package/dist/index.mjs.map +1 -1
- package/dist/migrations.cjs +345 -146
- package/dist/migrations.cjs.map +1 -1
- package/dist/migrations.d.cts +93 -110
- package/dist/migrations.d.ts +93 -110
- package/dist/migrations.mjs +344 -144
- package/dist/migrations.mjs.map +1 -1
- package/dist/schema/index.cjs +21 -6
- package/dist/schema/index.cjs.map +1 -1
- package/dist/schema/index.d.cts +5 -116
- package/dist/schema/index.d.ts +5 -116
- package/dist/schema/index.mjs +20 -4
- package/dist/schema/index.mjs.map +1 -1
- package/dist/schema-Bkkr3JMC.d.cts +264 -0
- package/dist/schema-Bkkr3JMC.d.ts +264 -0
- package/dist/schema-name.cjs +34 -12
- package/dist/schema-name.cjs.map +1 -1
- package/dist/schema-name.d.cts +3 -15
- package/dist/schema-name.d.ts +3 -15
- package/dist/schema-name.mjs +33 -10
- package/dist/schema-name.mjs.map +1 -1
- package/dist/text-match.cjs +42 -8
- package/dist/text-match.cjs.map +1 -1
- package/dist/text-match.d.cts +4 -16
- package/dist/text-match.d.ts +4 -16
- package/dist/text-match.mjs +41 -6
- package/dist/text-match.mjs.map +1 -1
- package/dist/types/index.cjs +8 -69
- package/dist/types/index.d.cts +3 -225
- package/dist/types/index.d.ts +3 -225
- package/dist/types/index.mjs +1 -64
- package/dist/types-CNyA1oIm.cjs +185 -0
- package/dist/types-CNyA1oIm.cjs.map +1 -0
- package/dist/types-CaF_5jNk.mjs +150 -0
- package/dist/types-CaF_5jNk.mjs.map +1 -0
- package/dist/version-check.cjs +116 -133
- package/dist/version-check.cjs.map +1 -1
- package/dist/version-check.d.cts +46 -47
- package/dist/version-check.d.ts +46 -47
- package/dist/version-check.mjs +115 -131
- package/dist/version-check.mjs.map +1 -1
- package/package.json +12 -16
- package/dist/adapter-bUAaPzjV.d.cts +0 -1143
- package/dist/adapter-iJ5hbUvL.d.ts +0 -1143
- package/dist/core-CVO7WYDj.d.cts +0 -74
- package/dist/core-CVO7WYDj.d.ts +0 -74
- package/dist/error-BrdknH2s.d.cts +0 -122
- package/dist/error-BrdknH2s.d.ts +0 -122
- package/dist/migration-BqHebSwM.d.ts +0 -831
- package/dist/migration-Bu0WLdX4.d.cts +0 -831
- package/dist/schema-BDn8WfSL.d.cts +0 -200
- package/dist/schema-BIQ0YQZ_.d.ts +0 -200
- package/dist/types/index.cjs.map +0 -1
- package/dist/types/index.mjs.map +0 -1
|
@@ -0,0 +1,1166 @@
|
|
|
1
|
+
import { a as DropTableOptions, c as TableDefinition, f as SqlParam, i as CreateTableOptions, m as TableResolver, n as AlterTableOptions, p as SupportedDialect, t as AlterTableOperation } from "./schema-Bkkr3JMC.js";
|
|
2
|
+
import { A as UpdateOptions, C as TransactionContext, D as DeleteOptions, E as CountOptions, F as WhereClause, O as InsertOptions, S as PoolStats, T as TransactionOptions, c as DatabaseError, g as Migration, j as UpsertOptions, k as SelectOptions, l as DatabaseErrorKind, x as DatabaseCapabilities, y as MigrationResult } from "./index-BYb6cDli.js";
|
|
3
|
+
import { AnyRelations, SQL } from "drizzle-orm";
|
|
4
|
+
/**
|
|
5
|
+
* A pooled adapter's Drizzle transactions, each on a connection the adapter
|
|
6
|
+
* checks out and returns itself.
|
|
7
|
+
*
|
|
8
|
+
* Drizzle's own `transaction()` on a pool checks a connection out, but does
|
|
9
|
+
* not return it as carefully as the adapter's `transaction()` does: it sends
|
|
10
|
+
* BEGIN outside its `try`, so a failed BEGIN never gives the connection back;
|
|
11
|
+
* and when its ROLLBACK fails it hands the connection to the pool as if
|
|
12
|
+
* nothing had happened, possibly still inside the transaction, and throws the
|
|
13
|
+
* ROLLBACK's error in place of the work's. Core services open their
|
|
14
|
+
* transactions through that handle, so it gets the same care here: Drizzle
|
|
15
|
+
* runs the transaction on a connection this module owns, and this module
|
|
16
|
+
* decides how the connection goes back.
|
|
17
|
+
*
|
|
18
|
+
* @module pinned-transaction
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Drizzle's database handle, as far as running a transaction goes.
|
|
22
|
+
*
|
|
23
|
+
* The callback takes `unknown` and the options `never`, so every dialect's
|
|
24
|
+
* handle fits, whose callback receives its own transaction type and whose
|
|
25
|
+
* options are its own.
|
|
26
|
+
*/
|
|
27
|
+
interface DrizzleTransactor {
|
|
28
|
+
transaction<T>(work: (tx: unknown) => Promise<T>, config?: never): Promise<T>;
|
|
29
|
+
}
|
|
30
|
+
/** One connection a pooled adapter checked out for one transaction. */
|
|
31
|
+
interface PinnedConnection {
|
|
32
|
+
/** Drizzle bound to this connection alone, with the handle's relations. */
|
|
33
|
+
drizzle: DrizzleTransactor;
|
|
34
|
+
/**
|
|
35
|
+
* Sends ROLLBACK on this connection. Harmless when no transaction is open
|
|
36
|
+
* on it: PostgreSQL answers with a warning, MySQL does nothing.
|
|
37
|
+
*/
|
|
38
|
+
rollback(): Promise<unknown>;
|
|
39
|
+
/**
|
|
40
|
+
* Gives the connection back: to the pool, or, when `dirty`, closed and
|
|
41
|
+
* removed from it, because it may still be inside the transaction.
|
|
42
|
+
*/
|
|
43
|
+
release(dirty: boolean): void;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Interface representing an adapter that can execute CRUD operations with an optional executor.
|
|
47
|
+
*/
|
|
48
|
+
interface TransactionCrudDelegator {
|
|
49
|
+
select<T = unknown>(table: string, options?: SelectOptions, executor?: unknown): Promise<T[]>;
|
|
50
|
+
selectOne<T = unknown>(table: string, options?: SelectOptions, executor?: unknown): Promise<T | null>;
|
|
51
|
+
updateCount(table: string, data: Record<string, unknown>, where: WhereClause, executor?: unknown): Promise<number>;
|
|
52
|
+
delete(table: string, where: WhereClause, options?: DeleteOptions, executor?: unknown): Promise<number>;
|
|
53
|
+
upsert<T = unknown>(table: string, data: Record<string, unknown>, options: UpsertOptions, executor?: unknown): Promise<T>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Transaction context CRUD methods provided by the forwarder.
|
|
57
|
+
*
|
|
58
|
+
* `update` is not among them. The pooled `update` goes through the Drizzle
|
|
59
|
+
* query builder, which writes the columns the runtime model declares; a
|
|
60
|
+
* transaction's update must reach the columns the physical table has, and
|
|
61
|
+
* each adapter binds the base class's `transactionUpdate` beside its
|
|
62
|
+
* transactional `insert`.
|
|
63
|
+
*/
|
|
64
|
+
type TransactionCrudForwarders = Pick<TransactionContext, "select" | "selectOne" | "updateCount" | "delete" | "upsert" | "getDrizzle">;
|
|
65
|
+
declare abstract class DrizzleAdapter {
|
|
66
|
+
/**
|
|
67
|
+
* Database dialect identifier.
|
|
68
|
+
*
|
|
69
|
+
* @remarks
|
|
70
|
+
* Must be set by subclass to identify the database type.
|
|
71
|
+
*/
|
|
72
|
+
abstract readonly dialect: SupportedDialect;
|
|
73
|
+
/**
|
|
74
|
+
* Establish connection to the database.
|
|
75
|
+
*
|
|
76
|
+
* @remarks
|
|
77
|
+
* This method should be idempotent - calling it multiple times
|
|
78
|
+
* should not create multiple connections.
|
|
79
|
+
*
|
|
80
|
+
* @throws {DatabaseError} If connection fails
|
|
81
|
+
*/
|
|
82
|
+
abstract connect(): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Close database connection and release resources.
|
|
85
|
+
*
|
|
86
|
+
* @remarks
|
|
87
|
+
* This method should be idempotent - calling it multiple times
|
|
88
|
+
* should be safe.
|
|
89
|
+
*/
|
|
90
|
+
abstract disconnect(): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Execute a raw SQL query.
|
|
93
|
+
*
|
|
94
|
+
* @param sql - SQL query to execute
|
|
95
|
+
* @param params - Query parameters
|
|
96
|
+
* @returns Array of result rows
|
|
97
|
+
*
|
|
98
|
+
* @throws {DatabaseError} If query execution fails
|
|
99
|
+
*/
|
|
100
|
+
abstract executeQuery<T = unknown>(sql: string, params?: SqlParam[]): Promise<T[]>;
|
|
101
|
+
/**
|
|
102
|
+
* Execute operations within a database transaction.
|
|
103
|
+
*
|
|
104
|
+
* @remarks
|
|
105
|
+
* The transaction is automatically committed on success or rolled back on error.
|
|
106
|
+
* Supports nested transactions via savepoints on databases that support them.
|
|
107
|
+
*
|
|
108
|
+
* Two kinds of error leave this method, and a caller has to be able to tell
|
|
109
|
+
* them apart. An error carrying the Nextly application brand — see
|
|
110
|
+
* `isApplicationError` — arrives exactly as it was thrown, because that is
|
|
111
|
+
* the application refusing the write rather than the database failing to
|
|
112
|
+
* perform it, and rewriting it would discard the code and payload the caller
|
|
113
|
+
* is meant to act on.
|
|
114
|
+
*
|
|
115
|
+
* Everything else arrives as a `DatabaseError` with its kind classified, and
|
|
116
|
+
* that deliberately includes an unbranded error the callback itself threw:
|
|
117
|
+
* the brand is the only thing distinguishing a deliberate refusal from a
|
|
118
|
+
* driver failure that surfaced through callback code, and guessing from the
|
|
119
|
+
* throw site would put raw driver text on the wire under a caller's own
|
|
120
|
+
* error shape.
|
|
121
|
+
*
|
|
122
|
+
* The rollback is the same either way.
|
|
123
|
+
*
|
|
124
|
+
* @param callback - Function to execute within transaction
|
|
125
|
+
* @param options - Transaction options
|
|
126
|
+
* @returns Result from the callback
|
|
127
|
+
*
|
|
128
|
+
* @throws {DatabaseError} If the transaction itself fails, or if the callback
|
|
129
|
+
* threw an error that does not carry the application brand
|
|
130
|
+
* @throws The callback's own error, unchanged, when it carries that brand
|
|
131
|
+
*/
|
|
132
|
+
abstract transaction<T>(callback: (ctx: TransactionContext) => Promise<T>, options?: TransactionOptions): Promise<T>;
|
|
133
|
+
/**
|
|
134
|
+
* Whether a `transaction()` call made from the current async context would
|
|
135
|
+
* join a transaction already open on this adapter, as a savepoint, rather
|
|
136
|
+
* than open one of its own.
|
|
137
|
+
*
|
|
138
|
+
* A caller about to do something no rollback can undo — removing a stored
|
|
139
|
+
* file, say — asks this first: work that joins an enclosing transaction is
|
|
140
|
+
* undone with it, while the effect it performs after its own savepoint
|
|
141
|
+
* releases is not.
|
|
142
|
+
*
|
|
143
|
+
* False here. Concrete rather than abstract so existing adapters keep
|
|
144
|
+
* working unchanged, and false is right for a pooled adapter: a call made
|
|
145
|
+
* inside another transaction's work opens its own transaction on its own
|
|
146
|
+
* connection, which commits independently.
|
|
147
|
+
*
|
|
148
|
+
* @returns True when the call would nest in an open transaction
|
|
149
|
+
*/
|
|
150
|
+
inTransaction(): boolean;
|
|
151
|
+
/**
|
|
152
|
+
* The transaction each async flow is inside, kept per flow rather than per
|
|
153
|
+
* connection: on SQLite every request shares the one connection, and
|
|
154
|
+
* another request's open transaction says nothing about this one.
|
|
155
|
+
*/
|
|
156
|
+
private readonly flowTransactions;
|
|
157
|
+
/** Each pool's reporting views, by method list (`observedPool`). Gone with the pool. */
|
|
158
|
+
private readonly observedPools;
|
|
159
|
+
/**
|
|
160
|
+
* Whether the calling async flow is inside a transaction on this adapter
|
|
161
|
+
* that has not finished: its own, or one it was started from inside.
|
|
162
|
+
*
|
|
163
|
+
* A write that must outlive any rollback — a count of a failed attempt, the
|
|
164
|
+
* spend of a single-use secret — asks this before running in a transaction
|
|
165
|
+
* of its own. Made inside an open transaction on SQLite, it joins that
|
|
166
|
+
* transaction as a savepoint and is undone with it. On PostgreSQL and MySQL
|
|
167
|
+
* it would commit on a connection of its own, so refusing it there too
|
|
168
|
+
* keeps code that passes on one dialect from failing on another. Unlike
|
|
169
|
+
* {@link inTransaction}, which asks whether a call would nest and is always
|
|
170
|
+
* false on a pooled adapter, this answers alike on every dialect, and
|
|
171
|
+
* another flow's open transaction never answers true.
|
|
172
|
+
*
|
|
173
|
+
* Covers transactions opened through {@link transaction} and through the
|
|
174
|
+
* Drizzle handle's own `transaction` on the dialects whose handle takes
|
|
175
|
+
* async work. A dialect that keeps scopes of its own judges from those
|
|
176
|
+
* instead; an adapter that does neither answers false.
|
|
177
|
+
*
|
|
178
|
+
* @experimental
|
|
179
|
+
* @returns True while a transaction the calling flow is inside is open
|
|
180
|
+
*/
|
|
181
|
+
transactionOpenInFlow(): boolean;
|
|
182
|
+
/**
|
|
183
|
+
* Run a whole transaction, from its BEGIN until its COMMIT or ROLLBACK has
|
|
184
|
+
* run, as the calling flow's open transaction, for
|
|
185
|
+
* {@link transactionOpenInFlow}. A dialect's `transaction` runs through
|
|
186
|
+
* this unless it judges the flow from scopes of its own.
|
|
187
|
+
*
|
|
188
|
+
* The transaction counts as open for its work and for anything the work
|
|
189
|
+
* starts, awaited or not, until it has finished. Something the work starts
|
|
190
|
+
* that outlives it then sees it closed, or the one enclosing it still open.
|
|
191
|
+
*
|
|
192
|
+
* @param run - The transaction, BEGIN to COMMIT or ROLLBACK
|
|
193
|
+
* @returns What `run` resolves to
|
|
194
|
+
*/
|
|
195
|
+
protected runInFlowTransaction<T>(run: () => Promise<T>): Promise<T>;
|
|
196
|
+
/**
|
|
197
|
+
* Record that the calling flow's transaction now holds its own connection.
|
|
198
|
+
*
|
|
199
|
+
* A pooled dialect calls this right after checking out the connection a
|
|
200
|
+
* transaction runs on, so {@link notePoolAccess} can tell that checkout,
|
|
201
|
+
* which belongs to the transaction, from any later one, which escapes it.
|
|
202
|
+
*/
|
|
203
|
+
protected markFlowTransactionConnected(): void;
|
|
204
|
+
/**
|
|
205
|
+
* Check out, through `checkout`, the connection the calling flow's
|
|
206
|
+
* transaction runs on. A transaction opened inside another's work takes a
|
|
207
|
+
* second connection, so the checkout is reported first
|
|
208
|
+
* ({@link notePoolAccess}); once it holds its own, the transaction is
|
|
209
|
+
* marked connected, so its later checkouts are told apart from it.
|
|
210
|
+
*
|
|
211
|
+
* @param checkout - Takes a connection from the dialect's pool
|
|
212
|
+
* @returns The connection
|
|
213
|
+
*/
|
|
214
|
+
protected connectFlowTransaction<C>(checkout: () => Promise<C>): Promise<C>;
|
|
215
|
+
/**
|
|
216
|
+
* Called by a pooled dialect before it takes anything from its pool: a
|
|
217
|
+
* query, or a connection checkout.
|
|
218
|
+
*
|
|
219
|
+
* While the calling flow is inside a transaction that already holds its own
|
|
220
|
+
* connection, a pool access runs on another connection: outside the
|
|
221
|
+
* transaction, blind to its uncommitted writes, not undone by its rollback,
|
|
222
|
+
* and able to stall a small pool. Such an access is reported to the
|
|
223
|
+
* observer a test harness installs under
|
|
224
|
+
* `Symbol.for("nextly.transactionEscapeObserver")`, with the stack that
|
|
225
|
+
* names its call site. With no observer installed, which is every
|
|
226
|
+
* production process, this is one property read.
|
|
227
|
+
*
|
|
228
|
+
* @param statement - What the pool call was handed, its SQL passed on so
|
|
229
|
+
* the harness can say which statement escaped; nothing for a checkout
|
|
230
|
+
*/
|
|
231
|
+
protected notePoolAccess(statement?: unknown): void;
|
|
232
|
+
/**
|
|
233
|
+
* `pool`, with {@link notePoolAccess} called before each of `methods`, for
|
|
234
|
+
* handing to code that queries the pool directly, such as Drizzle's handle.
|
|
235
|
+
* Everything else, `instanceof` included, reaches the pool unchanged.
|
|
236
|
+
*
|
|
237
|
+
* One view per pool and method list, made once: every Drizzle handle on the pool is given the
|
|
238
|
+
* same one, so `getDrizzle()` and `getDrizzle(relations)` share a `$client`, as they did when
|
|
239
|
+
* each was handed the pool itself.
|
|
240
|
+
*
|
|
241
|
+
* @param pool - The driver's pool
|
|
242
|
+
* @param methods - The pool methods that take a connection
|
|
243
|
+
* @returns A view of `pool` that reports those calls
|
|
244
|
+
*/
|
|
245
|
+
protected observedPool<P extends object>(pool: P, methods: readonly string[]): P;
|
|
246
|
+
/**
|
|
247
|
+
* Run each of a pool-bound Drizzle handle's transactions on a connection
|
|
248
|
+
* `checkout` hands it, and return that connection as the adapter's own
|
|
249
|
+
* `transaction()` does: closed rather than pooled when no ROLLBACK can be
|
|
250
|
+
* confirmed on it, and never leaked by a failed BEGIN (`pinTransactions`).
|
|
251
|
+
*
|
|
252
|
+
* For PostgreSQL's and MySQL's handles. Apply it before
|
|
253
|
+
* {@link trackFlowTransactions}, which wraps whatever `transaction` the
|
|
254
|
+
* handle has at that point.
|
|
255
|
+
*
|
|
256
|
+
* @param db - A Drizzle handle on this adapter's pool
|
|
257
|
+
* @param checkout - Checks out a connection for one transaction
|
|
258
|
+
* @returns The same handle, its `transaction` replaced
|
|
259
|
+
*/
|
|
260
|
+
protected pinDrizzleTransactions<D extends DrizzleTransactor>(db: D, checkout: () => Promise<PinnedConnection>): D;
|
|
261
|
+
/**
|
|
262
|
+
* Make a Drizzle handle's own `transaction` count for
|
|
263
|
+
* {@link transactionOpenInFlow}, as the adapter's does.
|
|
264
|
+
*
|
|
265
|
+
* Core's services run their transactions through the handle on PostgreSQL
|
|
266
|
+
* and MySQL; without this, a call made inside one would be refused on
|
|
267
|
+
* SQLite, where they go through the adapter, and let through on the
|
|
268
|
+
* others. Not for SQLite's handle: its `transaction` takes only
|
|
269
|
+
* synchronous work, which no async flow can be inside.
|
|
270
|
+
*
|
|
271
|
+
* @param db - A Drizzle handle this adapter created
|
|
272
|
+
* @returns The same handle, its `transaction` tracked
|
|
273
|
+
*/
|
|
274
|
+
protected trackFlowTransactions<D extends DrizzleTransactor>(db: D): D;
|
|
275
|
+
/**
|
|
276
|
+
* Run `effect` once the write made from the current async context has
|
|
277
|
+
* committed: an event, a hook, a cache flush, anything outside the database
|
|
278
|
+
* that must not happen for a change that is rolled back.
|
|
279
|
+
*
|
|
280
|
+
* A caller invokes this after its own transaction has resolved. Where that
|
|
281
|
+
* transaction was nested in an enclosing one, as a savepoint, the change is
|
|
282
|
+
* not durable yet, and an adapter that nests (see {@link inTransaction})
|
|
283
|
+
* holds `effect` until the outermost transaction commits, and drops it when
|
|
284
|
+
* that transaction, or the savepoint it was registered in, rolls back. A
|
|
285
|
+
* held effect runs after the commit, before the outermost `transaction()`
|
|
286
|
+
* call resolves, in registration order; one that then throws or rejects is
|
|
287
|
+
* handed to `onDeferredFailure` rather than failing a transaction that has
|
|
288
|
+
* committed.
|
|
289
|
+
*
|
|
290
|
+
* Here `effect` runs now and the returned promise settles with it, its
|
|
291
|
+
* failure included. Concrete rather than abstract, as `inTransaction` is,
|
|
292
|
+
* and right for a pooled adapter: each transaction has its own connection
|
|
293
|
+
* and has committed by the time its caller continues.
|
|
294
|
+
*
|
|
295
|
+
* @experimental
|
|
296
|
+
* @param effect - What to run once the change is durable
|
|
297
|
+
* @param onDeferredFailure - Receives the error of a held effect that fails
|
|
298
|
+
* @returns Settles once `effect` has run, or once it has been held
|
|
299
|
+
*/
|
|
300
|
+
afterCommit(effect: () => unknown, _onDeferredFailure?: (error: unknown) => void): Promise<void>;
|
|
301
|
+
/**
|
|
302
|
+
* Get database capabilities.
|
|
303
|
+
*
|
|
304
|
+
* @remarks
|
|
305
|
+
* Returns static capability flags for this adapter's dialect.
|
|
306
|
+
* Used by services to conditionally enable features or implement fallbacks.
|
|
307
|
+
*
|
|
308
|
+
* @returns Database capability flags
|
|
309
|
+
*/
|
|
310
|
+
abstract getCapabilities(): DatabaseCapabilities;
|
|
311
|
+
/**
|
|
312
|
+
* The schema this adapter's connections resolve unqualified names in.
|
|
313
|
+
*
|
|
314
|
+
* @remarks
|
|
315
|
+
* Read-only, and optional because only PostgreSQL has a schema namespace:
|
|
316
|
+
* MySQL's "schema" is its database and SQLite has one file. An adapter that
|
|
317
|
+
* sets no `search_path` of its own answers `undefined`, meaning the server's
|
|
318
|
+
* default applies.
|
|
319
|
+
*
|
|
320
|
+
* Exposed so the caller that built its own adapter can be held to the same
|
|
321
|
+
* schema the rest of the application assumes. The value lives in the
|
|
322
|
+
* adapter's config, and a mismatch is not an error anywhere below: every
|
|
323
|
+
* query succeeds, in a namespace nothing else is looking at.
|
|
324
|
+
*
|
|
325
|
+
* @returns The configured schema name, or `undefined` when none is set
|
|
326
|
+
*/
|
|
327
|
+
getConfiguredSchema?(): string | undefined;
|
|
328
|
+
/**
|
|
329
|
+
* Get the raw Drizzle ORM instance for direct queries.
|
|
330
|
+
*
|
|
331
|
+
* @remarks
|
|
332
|
+
* This method provides escape hatch access to the raw Drizzle instance.
|
|
333
|
+
* Use this when you need to run complex queries that the adapter API
|
|
334
|
+
* doesn't support, or for legacy code migration.
|
|
335
|
+
*
|
|
336
|
+
* **Note:** Prefer using adapter methods when possible as they provide:
|
|
337
|
+
* - Database-agnostic API
|
|
338
|
+
* - Consistent error handling
|
|
339
|
+
* - Proper connection pooling
|
|
340
|
+
*
|
|
341
|
+
* @param relations - Optional drizzle v1 relations config (defineRelations
|
|
342
|
+
* output) that enables the typed relational query API on the instance
|
|
343
|
+
* @returns Raw Drizzle ORM database instance
|
|
344
|
+
*
|
|
345
|
+
* @example
|
|
346
|
+
* ```typescript
|
|
347
|
+
* // For legacy code that needs direct Drizzle access
|
|
348
|
+
* const db = adapter.getDrizzle(myRelations); // defineRelations output
|
|
349
|
+
* const result = await db.insert(users).values({ ... }).returning();
|
|
350
|
+
* ```
|
|
351
|
+
*/
|
|
352
|
+
abstract getDrizzle<T = unknown>(relations?: AnyRelations): T;
|
|
353
|
+
/**
|
|
354
|
+
* Table resolver for looking up Drizzle table objects by name.
|
|
355
|
+
* When set, CRUD methods use Drizzle's query API instead of raw SQL.
|
|
356
|
+
* Set via setTableResolver() after boot-time schema loading.
|
|
357
|
+
*/
|
|
358
|
+
protected tableResolver: TableResolver | null;
|
|
359
|
+
/**
|
|
360
|
+
* Set the table resolver for Drizzle query API support.
|
|
361
|
+
* When a resolver is set, CRUD methods (select, insert, update, delete, upsert)
|
|
362
|
+
* will use Drizzle's query API (db.select().from(), etc.) instead of raw SQL
|
|
363
|
+
* string building. Falls back to raw SQL if the resolver doesn't have the table.
|
|
364
|
+
*
|
|
365
|
+
* @param resolver - TableResolver implementation (e.g. SchemaRegistry)
|
|
366
|
+
*/
|
|
367
|
+
setTableResolver(resolver: TableResolver): void;
|
|
368
|
+
/**
|
|
369
|
+
* Get a Drizzle table object by name from the resolver.
|
|
370
|
+
* Returns null if no resolver is set or table is not found.
|
|
371
|
+
*/
|
|
372
|
+
protected getTableObject(tableName: string): unknown;
|
|
373
|
+
/**
|
|
374
|
+
* Run a Drizzle-built statement and return its rows.
|
|
375
|
+
*
|
|
376
|
+
* @remarks
|
|
377
|
+
* The CRUD methods resolve their table through the schema registry and reject
|
|
378
|
+
* any name it does not declare, which leaves no way to read from a table the
|
|
379
|
+
* ORM does not know — one mid-rename, above all — except by assembling SQL and
|
|
380
|
+
* quoting identifiers by hand. This takes Drizzle's `sql` template instead, so
|
|
381
|
+
* the dialect in use decides the quoting and the parameter binding.
|
|
382
|
+
*
|
|
383
|
+
* Concrete rather than abstract so existing adapters keep working unchanged.
|
|
384
|
+
* The three drivers disagree about both the call and the result: node-postgres
|
|
385
|
+
* returns `{ rows }`, mysql2 a `[rows, fields]` tuple, and better-sqlite3 has
|
|
386
|
+
* no `execute` at all and answers `all`. Keeping that here rather than at each
|
|
387
|
+
* call site is the point — a caller reasoning about it would be reasoning
|
|
388
|
+
* about a driver it cannot see.
|
|
389
|
+
*
|
|
390
|
+
* @param statement - Drizzle `sql` template to run
|
|
391
|
+
* @returns Rows the statement produced
|
|
392
|
+
*/
|
|
393
|
+
queryStatement<T = Record<string, unknown>>(statement: SQL): Promise<T[]>;
|
|
394
|
+
/**
|
|
395
|
+
* Map data keys from SQL column names (snake_case) to Drizzle JS property names (camelCase).
|
|
396
|
+
* Drizzle schemas define columns as e.g. `createdAt: timestamp("created_at")` — the JS
|
|
397
|
+
* property is `createdAt` but the SQL column is `created_at`. Services pass snake_case keys
|
|
398
|
+
* because they match the DB column names. This method maps them to the JS names Drizzle expects.
|
|
399
|
+
*/
|
|
400
|
+
protected mapDataToColumnNames(tableObj: unknown, data: Record<string, unknown>): Record<string, unknown>;
|
|
401
|
+
/**
|
|
402
|
+
* Map data keys from Drizzle JS property names to SQL column names for the
|
|
403
|
+
* raw-SQL transaction insert path. The transaction context builds INSERT
|
|
404
|
+
* statements from Object.keys(data) used directly as column identifiers, so a
|
|
405
|
+
* table whose Drizzle property names differ from its SQL column names
|
|
406
|
+
* (camelCase core tables like nextly_versions) needs its keys translated
|
|
407
|
+
* first. For tables whose property names already equal their column names
|
|
408
|
+
* (the dynamic dc_/single_/comp_ tables) every lookup is identity, so
|
|
409
|
+
* existing callers are unaffected.
|
|
410
|
+
*/
|
|
411
|
+
protected mapKeysToSqlColumns(tableObj: unknown, data: Record<string, unknown>): Record<string, unknown>;
|
|
412
|
+
/**
|
|
413
|
+
* Map a list of column identifiers (Drizzle property names) to their SQL
|
|
414
|
+
* column names, for the raw-SQL transaction insert paths that build a
|
|
415
|
+
* RETURNING clause from `options.returning`. Same identity behavior as
|
|
416
|
+
* `mapKeysToSqlColumns`: names that are already SQL columns (the dynamic
|
|
417
|
+
* dc_/single_/comp_ tables) pass through unchanged.
|
|
418
|
+
*/
|
|
419
|
+
protected mapColumnNamesToSql(tableObj: unknown, names: string[]): string[];
|
|
420
|
+
/**
|
|
421
|
+
* Remap a raw-SQL result row's KEYS from SQL column names to Drizzle property
|
|
422
|
+
* names, so the raw-SQL transaction insert paths return the same key casing
|
|
423
|
+
* as the non-transactional (Drizzle) insert. Keys only - values are left
|
|
424
|
+
* untouched, so this does not change how JSON/date columns are decoded. For
|
|
425
|
+
* tables whose property names already equal their SQL columns (the dynamic
|
|
426
|
+
* dc_/single_/comp_ tables) every lookup is identity, so existing callers see
|
|
427
|
+
* no change.
|
|
428
|
+
*/
|
|
429
|
+
protected mapRowKeysToJs<T = unknown>(tableObj: unknown, row: T): T;
|
|
430
|
+
/**
|
|
431
|
+
* Decode a raw-SQL result row's DATE column values the way a Drizzle query
|
|
432
|
+
* would, so a write answers with the same representation a read of the same
|
|
433
|
+
* column gives.
|
|
434
|
+
*
|
|
435
|
+
* A Drizzle query path runs every value through its column definition; a
|
|
436
|
+
* raw-SQL path does not, so a dialect that stores a timestamp as a number
|
|
437
|
+
* answers a write with that number while every read answers a `Date`. Only
|
|
438
|
+
* date columns are touched, and a value that is already a `Date` is left
|
|
439
|
+
* alone, so a driver that decodes on its own is unaffected.
|
|
440
|
+
*
|
|
441
|
+
* Runs after {@link mapRowKeysToJs}: keys are Drizzle property names by then,
|
|
442
|
+
* which is what the table definition is keyed by.
|
|
443
|
+
*/
|
|
444
|
+
protected mapDateValuesFromDriver<T = unknown>(tableObj: unknown, row: T): T;
|
|
445
|
+
/**
|
|
446
|
+
* Encode a row's DATE values the way a Drizzle query would before binding
|
|
447
|
+
* them, so what lands in the column does not depend on the server's timezone.
|
|
448
|
+
*
|
|
449
|
+
* A column declared without a time zone stores a wall clock and records
|
|
450
|
+
* nothing about which zone it belongs to, so both ends have to agree. Drizzle
|
|
451
|
+
* writes UTC and reads UTC. A driver handed a `Date` writes the LOCAL wall
|
|
452
|
+
* clock instead, and the same row then reads back shifted by the offset --
|
|
453
|
+
* on a UTC server the two agree and nothing is visibly wrong, which is why
|
|
454
|
+
* this survives CI.
|
|
455
|
+
*
|
|
456
|
+
* Only date columns are touched. A value that is not a `Date` is left as it
|
|
457
|
+
* is, so a caller that already encoded one is not encoded twice.
|
|
458
|
+
*
|
|
459
|
+
* Keys may be spelled either way at this point, so both the Drizzle property
|
|
460
|
+
* name and the SQL column name resolve.
|
|
461
|
+
*/
|
|
462
|
+
protected mapDateValuesToDriver(tableObj: unknown, data: Record<string, unknown>): Record<string, unknown>;
|
|
463
|
+
/**
|
|
464
|
+
* Bring a row about to be written through a raw-SQL statement into the shape
|
|
465
|
+
* a Drizzle query would have bound: SQL column names for keys, encoded values
|
|
466
|
+
* for date columns.
|
|
467
|
+
*
|
|
468
|
+
* The mirror of {@link mapRowFromRawSql}. The raw-SQL write paths exist
|
|
469
|
+
* because a dialect needs SQL a Drizzle query cannot express, not because
|
|
470
|
+
* their callers want different values in the table.
|
|
471
|
+
*/
|
|
472
|
+
protected mapRowToRawSql(tableObj: unknown, data: Record<string, unknown>): Record<string, unknown>;
|
|
473
|
+
/**
|
|
474
|
+
* Bring a raw-SQL result row into the shape a Drizzle query would have
|
|
475
|
+
* produced: Drizzle property names for keys, decoded values for date columns.
|
|
476
|
+
*
|
|
477
|
+
* The raw-SQL write paths exist because a dialect needs SQL a Drizzle query
|
|
478
|
+
* cannot express, not because their callers want a different row shape, so
|
|
479
|
+
* every one of them ends here.
|
|
480
|
+
*/
|
|
481
|
+
protected mapRowFromRawSql<T = unknown>(tableObj: unknown, row: T, aliases?: ReadonlyArray<{
|
|
482
|
+
alias: string;
|
|
483
|
+
jsName: string;
|
|
484
|
+
}>): T;
|
|
485
|
+
/**
|
|
486
|
+
* The date columns a statement is about to return, and the alias each one's
|
|
487
|
+
* wall clock is spelled out under.
|
|
488
|
+
*
|
|
489
|
+
* A driver turns a timestamp into a `Date` using ITS zone before any of this
|
|
490
|
+
* code runs, and that conversion is lossy: a wall clock inside a
|
|
491
|
+
* daylight-saving gap is a local time that does not exist, so the driver
|
|
492
|
+
* normalizes it and the original is gone. Asking the database for the wall
|
|
493
|
+
* clock as text alongside the row is the only way to read it exactly.
|
|
494
|
+
*
|
|
495
|
+
* `"*"` covers every date column; a projection covers only the ones it asked
|
|
496
|
+
* for, so a caller still gets back what it requested and nothing more.
|
|
497
|
+
*/
|
|
498
|
+
protected dateWallClockAliases(tableObj: unknown, returning: string[] | "*" | undefined): Array<{
|
|
499
|
+
sqlName: string;
|
|
500
|
+
alias: string;
|
|
501
|
+
jsName: string;
|
|
502
|
+
}>;
|
|
503
|
+
/**
|
|
504
|
+
* Replace each date in a row with the wall clock the database spelled out,
|
|
505
|
+
* read as UTC, and drop the aliases that carried it.
|
|
506
|
+
*
|
|
507
|
+
* The statement writes a UTC wall clock, so reading one back as UTC is what
|
|
508
|
+
* makes a write and a later read agree. Whatever the column actually stored
|
|
509
|
+
* is what arrives -- a column keeping only whole seconds reports whole
|
|
510
|
+
* seconds -- because this is the database's own text, not a value
|
|
511
|
+
* reconstructed from the one that was bound.
|
|
512
|
+
*/
|
|
513
|
+
protected applyWallClockAliases<T>(row: T, aliases: ReadonlyArray<{
|
|
514
|
+
alias: string;
|
|
515
|
+
jsName: string;
|
|
516
|
+
}>): T;
|
|
517
|
+
/**
|
|
518
|
+
* Build a Drizzle column projection object (`{ propertyName: column }`) from a
|
|
519
|
+
* requested column list, used by `select` (columns) and `insert` (returning).
|
|
520
|
+
* A requested name resolves against either the Drizzle property name
|
|
521
|
+
* (camelCase) or the SQL column name (snake_case); the projection is keyed by
|
|
522
|
+
* the property name so the row shape matches a full select. Returns undefined
|
|
523
|
+
* for `"*"` or when nothing resolves, so callers fall back to all columns.
|
|
524
|
+
*/
|
|
525
|
+
protected buildColumnProjection(tableObj: unknown, names: string[] | "*" | undefined): Record<string, unknown> | undefined;
|
|
526
|
+
/**
|
|
527
|
+
* The requested column names split into what this table has and what it does not.
|
|
528
|
+
*
|
|
529
|
+
* One resolution, reported both ways, because two callers need different halves
|
|
530
|
+
* of the same answer: a projection drops what it cannot find, while a distinct
|
|
531
|
+
* count has to REFUSE it. Resolving twice would let the two disagree about what
|
|
532
|
+
* "found" means — the SQL-name alias below is exactly the kind of detail a
|
|
533
|
+
* second implementation gets wrong — and the count would then reject a column
|
|
534
|
+
* the projection happily uses.
|
|
535
|
+
*
|
|
536
|
+
* Both spellings resolve: a caller may name the Drizzle property or the SQL
|
|
537
|
+
* column, and either maps to the same projection key.
|
|
538
|
+
*/
|
|
539
|
+
protected resolveColumns(tableObj: unknown, names: readonly string[]): {
|
|
540
|
+
projection: Record<string, unknown>;
|
|
541
|
+
unresolved: string[];
|
|
542
|
+
};
|
|
543
|
+
/**
|
|
544
|
+
* Check if the adapter is currently connected.
|
|
545
|
+
*
|
|
546
|
+
* @remarks
|
|
547
|
+
* Default implementation returns false. Subclasses should override
|
|
548
|
+
* to provide accurate connection status.
|
|
549
|
+
*
|
|
550
|
+
* @returns True if connected, false otherwise
|
|
551
|
+
*/
|
|
552
|
+
isConnected(): boolean;
|
|
553
|
+
/**
|
|
554
|
+
* Get connection pool statistics.
|
|
555
|
+
*
|
|
556
|
+
* @remarks
|
|
557
|
+
* Returns null by default. Subclasses with connection pooling
|
|
558
|
+
* should override to provide pool statistics.
|
|
559
|
+
*
|
|
560
|
+
* @returns Pool statistics or null if not applicable
|
|
561
|
+
*/
|
|
562
|
+
getPoolStats(): PoolStats | null;
|
|
563
|
+
/**
|
|
564
|
+
* Default query timeout in milliseconds.
|
|
565
|
+
*
|
|
566
|
+
* @remarks
|
|
567
|
+
* This value is used by executeWithTimeout() when no explicit timeout
|
|
568
|
+
* is provided. Subclasses should set this from their config.
|
|
569
|
+
*
|
|
570
|
+
* @default 15000 (15 seconds)
|
|
571
|
+
*
|
|
572
|
+
* @protected
|
|
573
|
+
*/
|
|
574
|
+
protected defaultQueryTimeoutMs: number;
|
|
575
|
+
/**
|
|
576
|
+
* Execute an async operation with a timeout.
|
|
577
|
+
*
|
|
578
|
+
* @remarks
|
|
579
|
+
* Wraps an async operation with a timeout that aborts if the operation
|
|
580
|
+
* exceeds the specified duration. Uses Promise.race for clean timeout
|
|
581
|
+
* handling without memory leaks.
|
|
582
|
+
*
|
|
583
|
+
* When the timeout is reached, a DatabaseError with kind 'timeout' is thrown.
|
|
584
|
+
* Note that this does NOT cancel the underlying database query - it only
|
|
585
|
+
* prevents the calling code from waiting indefinitely. For true query
|
|
586
|
+
* cancellation, use database-level statement timeouts (PostgreSQL) or
|
|
587
|
+
* similar mechanisms.
|
|
588
|
+
*
|
|
589
|
+
* @param operation - Async operation to execute
|
|
590
|
+
* @param timeoutMs - Timeout in milliseconds (defaults to defaultQueryTimeoutMs)
|
|
591
|
+
* @returns Result of the operation
|
|
592
|
+
*
|
|
593
|
+
* @throws {DatabaseError} With kind 'timeout' if operation exceeds timeout
|
|
594
|
+
*
|
|
595
|
+
* @example
|
|
596
|
+
* ```typescript
|
|
597
|
+
* // Use default timeout
|
|
598
|
+
* const result = await adapter.executeWithTimeout(
|
|
599
|
+
* () => adapter.select('users', { limit: 1000 })
|
|
600
|
+
* );
|
|
601
|
+
*
|
|
602
|
+
* // Use custom timeout for specific operation
|
|
603
|
+
* const result = await adapter.executeWithTimeout(
|
|
604
|
+
* () => adapter.select('large_table'),
|
|
605
|
+
* 60000 // 60 seconds for large queries
|
|
606
|
+
* );
|
|
607
|
+
* ```
|
|
608
|
+
*
|
|
609
|
+
* @public
|
|
610
|
+
*/
|
|
611
|
+
executeWithTimeout<T>(operation: () => Promise<T>, timeoutMs?: number): Promise<T>;
|
|
612
|
+
/**
|
|
613
|
+
* Set the default query timeout.
|
|
614
|
+
*
|
|
615
|
+
* @remarks
|
|
616
|
+
* This method allows runtime configuration of the default timeout.
|
|
617
|
+
* Subclasses should call this in their constructor or connect() method
|
|
618
|
+
* based on their configuration.
|
|
619
|
+
*
|
|
620
|
+
* @param timeoutMs - Timeout in milliseconds (0 to disable)
|
|
621
|
+
*
|
|
622
|
+
* @protected
|
|
623
|
+
*/
|
|
624
|
+
protected setDefaultQueryTimeout(timeoutMs: number): void;
|
|
625
|
+
/**
|
|
626
|
+
* Get the current default query timeout.
|
|
627
|
+
*
|
|
628
|
+
* @returns Current default timeout in milliseconds
|
|
629
|
+
*
|
|
630
|
+
* @public
|
|
631
|
+
*/
|
|
632
|
+
getDefaultQueryTimeout(): number;
|
|
633
|
+
/**
|
|
634
|
+
* Select multiple records from a table.
|
|
635
|
+
*
|
|
636
|
+
* @remarks
|
|
637
|
+
* Default implementation builds a SELECT query and executes it.
|
|
638
|
+
* Subclasses can override for optimization or dialect-specific features.
|
|
639
|
+
*
|
|
640
|
+
* @param table - Table name
|
|
641
|
+
* @param options - Select options (filtering, sorting, pagination)
|
|
642
|
+
* @returns Array of matching records
|
|
643
|
+
*
|
|
644
|
+
* @throws {DatabaseError} If query fails
|
|
645
|
+
*
|
|
646
|
+
* @example
|
|
647
|
+
* ```typescript
|
|
648
|
+
* const users = await adapter.select('users', {
|
|
649
|
+
* where: { and: [{ column: 'role', op: '=', value: 'admin' }] },
|
|
650
|
+
* orderBy: [{ column: 'created_at', direction: 'desc' }],
|
|
651
|
+
* limit: 10
|
|
652
|
+
* });
|
|
653
|
+
* ```
|
|
654
|
+
*/
|
|
655
|
+
select<T = unknown>(table: string, options?: SelectOptions, executor?: unknown): Promise<T[]>;
|
|
656
|
+
/**
|
|
657
|
+
* Select a single record from a table.
|
|
658
|
+
*
|
|
659
|
+
* @remarks
|
|
660
|
+
* Default implementation uses `select()` with limit 1 and returns first result.
|
|
661
|
+
* Returns null if no matching record is found.
|
|
662
|
+
*
|
|
663
|
+
* @param table - Table name
|
|
664
|
+
* @param options - Select options
|
|
665
|
+
* @returns First matching record or null
|
|
666
|
+
*
|
|
667
|
+
* @throws {DatabaseError} If query fails
|
|
668
|
+
*
|
|
669
|
+
* @example
|
|
670
|
+
* ```typescript
|
|
671
|
+
* const user = await adapter.selectOne('users', {
|
|
672
|
+
* where: { and: [{ column: 'email', op: '=', value: 'user@example.com' }] }
|
|
673
|
+
* });
|
|
674
|
+
* ```
|
|
675
|
+
*/
|
|
676
|
+
/** The registered table object, or a refusal naming what is missing. */
|
|
677
|
+
private requireTableObject;
|
|
678
|
+
/**
|
|
679
|
+
* The columns a distinct count groups by, or `undefined` for a row count.
|
|
680
|
+
*
|
|
681
|
+
* 🔴 EVERY named column must resolve, not merely one of them. A `distinctOn`
|
|
682
|
+
* naming no column this table has would fall through to a row count, and one
|
|
683
|
+
* naming a valid column beside a misspelled or since-removed column would
|
|
684
|
+
* count distinct over a NARROWER key than the caller asked for. Both answer a
|
|
685
|
+
* different question than the one asked, silently; the second is the worse of
|
|
686
|
+
* the two, because a subset key groups more rows together and so UNDERCOUNTS,
|
|
687
|
+
* which reads as a plausible number rather than as a fault. Refused here,
|
|
688
|
+
* where the mistake was made, rather than surfacing as a wrong figure.
|
|
689
|
+
*/
|
|
690
|
+
private countProjection;
|
|
691
|
+
/**
|
|
692
|
+
* `COUNT(*)` over a `SELECT DISTINCT` subquery.
|
|
693
|
+
*
|
|
694
|
+
* Its own function because it is a genuinely different query from the plain
|
|
695
|
+
* count rather than a variation on one, and because building both inline made
|
|
696
|
+
* the public method a chain of decisions the complexity gate objected to
|
|
697
|
+
* before a reader would have.
|
|
698
|
+
*/
|
|
699
|
+
private countDistinctRows;
|
|
700
|
+
/** `COUNT(*)` over the table itself. */
|
|
701
|
+
private countAllRows;
|
|
702
|
+
/**
|
|
703
|
+
* How many rows match, or how many DISTINCT combinations of some columns do.
|
|
704
|
+
*
|
|
705
|
+
* The data layer had no count at all: collection totals go through
|
|
706
|
+
* `countEntries`, an access-controlled path built for collection tables, and
|
|
707
|
+
* nothing could count a system table. A caller wanting one selected the rows
|
|
708
|
+
* and measured the array, which transfers every row to learn a number and
|
|
709
|
+
* cannot be bounded without making the number wrong.
|
|
710
|
+
*
|
|
711
|
+
* 🔴 `distinctOn` compiles to `COUNT(*)` over a `SELECT DISTINCT` SUBQUERY,
|
|
712
|
+
* never to `COUNT(DISTINCT a, b)`. The inline form is not portable and fails
|
|
713
|
+
* in the direction that is hardest to notice -- MySQL accepts it, PostgreSQL
|
|
714
|
+
* needs a row constructor, and SQLite rejects it outright with "wrong number
|
|
715
|
+
* of arguments to function count()" -- so a query written against one engine
|
|
716
|
+
* is a syntax error on another. The subquery is the single form all three
|
|
717
|
+
* accept, and building it here rather than at each call site is what keeps
|
|
718
|
+
* the answer identical per dialect.
|
|
719
|
+
*/
|
|
720
|
+
count(table: string, options?: CountOptions, executor?: unknown): Promise<number>;
|
|
721
|
+
selectOne<T = unknown>(table: string, options?: SelectOptions, executor?: unknown): Promise<T | null>;
|
|
722
|
+
/**
|
|
723
|
+
* Insert a single record into a table.
|
|
724
|
+
*
|
|
725
|
+
* @remarks
|
|
726
|
+
* Default implementation handles databases with and without RETURNING support.
|
|
727
|
+
* For databases without RETURNING (MySQL), performs INSERT followed by SELECT.
|
|
728
|
+
*
|
|
729
|
+
* @param table - Table name
|
|
730
|
+
* @param data - Record data to insert
|
|
731
|
+
* @param options - Insert options
|
|
732
|
+
* @returns Inserted record (with RETURNING columns if specified)
|
|
733
|
+
*
|
|
734
|
+
* @throws {DatabaseError} If insert fails
|
|
735
|
+
*
|
|
736
|
+
* @example
|
|
737
|
+
* ```typescript
|
|
738
|
+
* const user = await adapter.insert('users', {
|
|
739
|
+
* email: 'user@example.com',
|
|
740
|
+
* name: 'John Doe'
|
|
741
|
+
* }, { returning: ['id', 'email', 'created_at'] });
|
|
742
|
+
* ```
|
|
743
|
+
*/
|
|
744
|
+
insert<T = unknown>(table: string, data: Record<string, unknown>, options?: InsertOptions): Promise<T>;
|
|
745
|
+
/**
|
|
746
|
+
* Insert multiple records into a table.
|
|
747
|
+
*
|
|
748
|
+
* @remarks
|
|
749
|
+
* Default implementation performs individual inserts in sequence.
|
|
750
|
+
* Subclasses can override for bulk insert optimization (e.g., COPY in PostgreSQL).
|
|
751
|
+
*
|
|
752
|
+
* @param table - Table name
|
|
753
|
+
* @param data - Array of records to insert
|
|
754
|
+
* @param options - Insert options
|
|
755
|
+
* @returns Inserted records (with RETURNING columns if specified)
|
|
756
|
+
*
|
|
757
|
+
* @throws {DatabaseError} If insert fails
|
|
758
|
+
*
|
|
759
|
+
* @example
|
|
760
|
+
* ```typescript
|
|
761
|
+
* const users = await adapter.insertMany('users', [
|
|
762
|
+
* { email: 'user1@example.com', name: 'User 1' },
|
|
763
|
+
* { email: 'user2@example.com', name: 'User 2' }
|
|
764
|
+
* ], { returning: ['id'] });
|
|
765
|
+
* ```
|
|
766
|
+
*/
|
|
767
|
+
insertMany<T = unknown>(table: string, data: Record<string, unknown>[], options?: InsertOptions): Promise<T[]>;
|
|
768
|
+
/**
|
|
769
|
+
* Update records in a table.
|
|
770
|
+
*
|
|
771
|
+
* @remarks
|
|
772
|
+
* Default implementation builds an UPDATE query with WHERE clause.
|
|
773
|
+
* Returns updated records if RETURNING is supported and requested.
|
|
774
|
+
*
|
|
775
|
+
* @param table - Table name
|
|
776
|
+
* @param data - Data to update
|
|
777
|
+
* @param where - Conditions for records to update
|
|
778
|
+
* @param options - Update options
|
|
779
|
+
* @returns Updated records (with RETURNING columns if specified)
|
|
780
|
+
*
|
|
781
|
+
* @throws {DatabaseError} If update fails
|
|
782
|
+
*
|
|
783
|
+
* @example
|
|
784
|
+
* ```typescript
|
|
785
|
+
* const updated = await adapter.update('users',
|
|
786
|
+
* { status: 'active' },
|
|
787
|
+
* { and: [{ column: 'id', op: '=', value: userId }] },
|
|
788
|
+
* { returning: ['id', 'status', 'updated_at'] }
|
|
789
|
+
* );
|
|
790
|
+
* ```
|
|
791
|
+
*/
|
|
792
|
+
update<T = unknown>(table: string, data: Record<string, unknown>, where: WhereClause, options?: UpdateOptions, executor?: unknown): Promise<T[]>;
|
|
793
|
+
/**
|
|
794
|
+
* Update records in a table and report how many rows the statement affected.
|
|
795
|
+
*
|
|
796
|
+
* The count is the whole return value, mirroring `delete`. `update` cannot answer this: without
|
|
797
|
+
* `returning` it discards the driver's count, and WITH `returning` on a dialect that lacks
|
|
798
|
+
* RETURNING it re-SELECTs using the same WHERE — so a conditional update that just changed a
|
|
799
|
+
* column named in that WHERE reads back zero rows and a write that landed reports as unmatched.
|
|
800
|
+
* Reading the driver's own count has no second query to disagree with the first.
|
|
801
|
+
*
|
|
802
|
+
* 🔴 MySQL reports CHANGED rows, not matched rows: an UPDATE that matches a row but writes values
|
|
803
|
+
* identical to what it holds counts zero. A caller using this as a compare-and-set must therefore
|
|
804
|
+
* include a column the write always moves — a version bump, a timestamp with enough resolution —
|
|
805
|
+
* so that matched implies changed. Postgres (`rowCount`) and SQLite (`changes`) count matched
|
|
806
|
+
* rows and do not need the precaution, which is exactly why it cannot be dropped: the dialect
|
|
807
|
+
* where the distinction exists is the one with no RETURNING to fall back on.
|
|
808
|
+
*/
|
|
809
|
+
updateCount(table: string, data: Record<string, unknown>, where: WhereClause, executor?: unknown): Promise<number>;
|
|
810
|
+
/**
|
|
811
|
+
* Delete records from a table.
|
|
812
|
+
*
|
|
813
|
+
* @remarks
|
|
814
|
+
* Default implementation builds a DELETE query with WHERE clause.
|
|
815
|
+
* Returns the number of deleted records.
|
|
816
|
+
*
|
|
817
|
+
* @param table - Table name
|
|
818
|
+
* @param where - Conditions for records to delete
|
|
819
|
+
* @param options - Delete options
|
|
820
|
+
* @returns Number of deleted records
|
|
821
|
+
*
|
|
822
|
+
* @throws {DatabaseError} If delete fails
|
|
823
|
+
*
|
|
824
|
+
* @example
|
|
825
|
+
* ```typescript
|
|
826
|
+
* const count = await adapter.delete('users', {
|
|
827
|
+
* and: [{ column: 'status', op: '=', value: 'inactive' }]
|
|
828
|
+
* });
|
|
829
|
+
* console.log(`Deleted ${count} users`);
|
|
830
|
+
* ```
|
|
831
|
+
*/
|
|
832
|
+
delete(table: string, where: WhereClause, _options?: DeleteOptions, executor?: unknown): Promise<number>;
|
|
833
|
+
/**
|
|
834
|
+
* Upsert (INSERT or UPDATE) a record.
|
|
835
|
+
*
|
|
836
|
+
* @remarks
|
|
837
|
+
* Default implementation uses dialect-specific ON CONFLICT syntax.
|
|
838
|
+
* PostgreSQL/SQLite: ON CONFLICT ... DO UPDATE
|
|
839
|
+
* MySQL: the MySQL adapter overrides this, resolving the conflict by the
|
|
840
|
+
* conflict columns (see its `upsert`)
|
|
841
|
+
*
|
|
842
|
+
* @param table - Table name
|
|
843
|
+
* @param data - Record data
|
|
844
|
+
* @param options - Upsert options (must specify conflict columns)
|
|
845
|
+
* @returns Upserted record (with RETURNING columns if specified)
|
|
846
|
+
*
|
|
847
|
+
* @throws {DatabaseError} If upsert fails
|
|
848
|
+
*
|
|
849
|
+
* @example
|
|
850
|
+
* ```typescript
|
|
851
|
+
* const user = await adapter.upsert('users', {
|
|
852
|
+
* email: 'user@example.com',
|
|
853
|
+
* name: 'Updated Name'
|
|
854
|
+
* }, {
|
|
855
|
+
* conflictColumns: ['email'],
|
|
856
|
+
* updateColumns: ['name'],
|
|
857
|
+
* returning: ['id', 'email', 'name']
|
|
858
|
+
* });
|
|
859
|
+
* ```
|
|
860
|
+
*/
|
|
861
|
+
upsert<T = unknown>(table: string, data: Record<string, unknown>, options: UpsertOptions, executor?: unknown): Promise<T>;
|
|
862
|
+
/**
|
|
863
|
+
* Run pending migrations.
|
|
864
|
+
*
|
|
865
|
+
* @remarks
|
|
866
|
+
* Default implementation is a placeholder. Subclasses should implement
|
|
867
|
+
* migration tracking and execution logic.
|
|
868
|
+
*
|
|
869
|
+
* @param migrations - Array of migrations to run
|
|
870
|
+
* @returns Migration result with applied and pending migrations
|
|
871
|
+
*
|
|
872
|
+
* @throws {DatabaseError} If migration fails
|
|
873
|
+
*/
|
|
874
|
+
migrate(_migrations: Migration[]): Promise<MigrationResult>;
|
|
875
|
+
/**
|
|
876
|
+
* Rollback the last migration.
|
|
877
|
+
*
|
|
878
|
+
* @remarks
|
|
879
|
+
* Default implementation is a placeholder. Subclasses should implement
|
|
880
|
+
* migration rollback logic.
|
|
881
|
+
*
|
|
882
|
+
* @returns Migration result after rollback
|
|
883
|
+
*
|
|
884
|
+
* @throws {DatabaseError} If rollback fails
|
|
885
|
+
*/
|
|
886
|
+
rollback(): Promise<MigrationResult>;
|
|
887
|
+
/**
|
|
888
|
+
* Get migration status.
|
|
889
|
+
*
|
|
890
|
+
* @remarks
|
|
891
|
+
* Default implementation is a placeholder. Subclasses should implement
|
|
892
|
+
* migration status checking.
|
|
893
|
+
*
|
|
894
|
+
* @returns Current migration status
|
|
895
|
+
*
|
|
896
|
+
* @throws {DatabaseError} If status check fails
|
|
897
|
+
*/
|
|
898
|
+
getMigrationStatus(): Promise<MigrationResult>;
|
|
899
|
+
/**
|
|
900
|
+
* Create a new table.
|
|
901
|
+
*
|
|
902
|
+
* @remarks
|
|
903
|
+
* Default implementation is a placeholder. Subclasses should implement
|
|
904
|
+
* table creation logic.
|
|
905
|
+
*
|
|
906
|
+
* @param definition - Table definition
|
|
907
|
+
* @param options - Creation options
|
|
908
|
+
*
|
|
909
|
+
* @throws {DatabaseError} If table creation fails
|
|
910
|
+
*/
|
|
911
|
+
createTable(definition: TableDefinition, options?: CreateTableOptions): Promise<void>;
|
|
912
|
+
/**
|
|
913
|
+
* Drop a table.
|
|
914
|
+
*
|
|
915
|
+
* @remarks
|
|
916
|
+
* Default implementation is a placeholder. Subclasses should implement
|
|
917
|
+
* table dropping logic.
|
|
918
|
+
*
|
|
919
|
+
* @param tableName - Name of table to drop
|
|
920
|
+
* @param options - Drop options
|
|
921
|
+
*
|
|
922
|
+
* @throws {DatabaseError} If table drop fails
|
|
923
|
+
*/
|
|
924
|
+
dropTable(tableName: string, options?: DropTableOptions): Promise<void>;
|
|
925
|
+
/**
|
|
926
|
+
* Alter an existing table.
|
|
927
|
+
*
|
|
928
|
+
* @remarks
|
|
929
|
+
* Default implementation is a placeholder. Subclasses should implement
|
|
930
|
+
* table alteration logic.
|
|
931
|
+
*
|
|
932
|
+
* @param tableName - Name of table to alter
|
|
933
|
+
* @param operations - Alteration operations
|
|
934
|
+
* @param options - Alter options
|
|
935
|
+
*
|
|
936
|
+
* @throws {DatabaseError} If table alteration fails
|
|
937
|
+
*/
|
|
938
|
+
alterTable(tableName: string, operations: AlterTableOperation[], _options?: AlterTableOptions): Promise<void>;
|
|
939
|
+
/**
|
|
940
|
+
* Check if a table exists in the database.
|
|
941
|
+
*
|
|
942
|
+
* @remarks
|
|
943
|
+
* Uses dialect-specific information schema queries to check table existence.
|
|
944
|
+
* This is useful for development mode auto-sync to determine whether to
|
|
945
|
+
* CREATE or DROP/CREATE tables.
|
|
946
|
+
*
|
|
947
|
+
* @param tableName - Name of table to check
|
|
948
|
+
* @param schema - Optional schema name (defaults to 'public' for PostgreSQL)
|
|
949
|
+
* @returns True if table exists, false otherwise
|
|
950
|
+
*
|
|
951
|
+
* @throws {DatabaseError} If query fails
|
|
952
|
+
*
|
|
953
|
+
* @example
|
|
954
|
+
* ```typescript
|
|
955
|
+
* const exists = await adapter.tableExists('users');
|
|
956
|
+
* if (exists) {
|
|
957
|
+
* await adapter.dropTable('users');
|
|
958
|
+
* }
|
|
959
|
+
* await adapter.createTable(userTableDef);
|
|
960
|
+
* ```
|
|
961
|
+
*/
|
|
962
|
+
tableExists(tableName: string, schema?: string): Promise<boolean>;
|
|
963
|
+
/**
|
|
964
|
+
* Get list of all tables in the database.
|
|
965
|
+
*
|
|
966
|
+
* @remarks
|
|
967
|
+
* Uses dialect-specific information schema queries to list tables.
|
|
968
|
+
* Useful for detecting orphaned tables or validating schema state.
|
|
969
|
+
*
|
|
970
|
+
* @param schema - Optional schema name (defaults to 'public' for PostgreSQL)
|
|
971
|
+
* @returns Array of table names
|
|
972
|
+
*
|
|
973
|
+
* @throws {DatabaseError} If query fails
|
|
974
|
+
*/
|
|
975
|
+
listTables(schema?: string): Promise<string[]>;
|
|
976
|
+
/**
|
|
977
|
+
* Escape a table or column identifier.
|
|
978
|
+
*
|
|
979
|
+
* @remarks
|
|
980
|
+
* Default uses double quotes (SQL standard).
|
|
981
|
+
* MySQL adapter should override to use backticks.
|
|
982
|
+
*
|
|
983
|
+
* @param identifier - Identifier to escape
|
|
984
|
+
* @returns Escaped identifier
|
|
985
|
+
*
|
|
986
|
+
* @protected
|
|
987
|
+
*/
|
|
988
|
+
protected escapeIdentifier(identifier: string): string;
|
|
989
|
+
/**
|
|
990
|
+
* Create a DatabaseError with proper error kind classification.
|
|
991
|
+
*
|
|
992
|
+
* @remarks
|
|
993
|
+
* Protected helper for subclasses to create consistent errors.
|
|
994
|
+
* Subclasses can override to add dialect-specific error classification.
|
|
995
|
+
*
|
|
996
|
+
* @param kind - Error kind
|
|
997
|
+
* @param message - Error message
|
|
998
|
+
* @param cause - Original error
|
|
999
|
+
* @returns DatabaseError instance
|
|
1000
|
+
*
|
|
1001
|
+
* @protected
|
|
1002
|
+
*/
|
|
1003
|
+
protected createDatabaseError(kind: DatabaseErrorKind, message: string, cause?: Error): DatabaseError;
|
|
1004
|
+
/**
|
|
1005
|
+
* Helper to create transaction context CRUD forwarding methods.
|
|
1006
|
+
*
|
|
1007
|
+
* @param txDb - Thunk returning the transaction-bound Drizzle executor
|
|
1008
|
+
* @returns Object providing forwarded CRUD and getDrizzle methods
|
|
1009
|
+
*
|
|
1010
|
+
* @protected
|
|
1011
|
+
*/
|
|
1012
|
+
protected createTransactionForwarders(txDb: () => unknown): TransactionCrudForwarders;
|
|
1013
|
+
/**
|
|
1014
|
+
* The Drizzle handles one transaction hands out; see
|
|
1015
|
+
* `transactionDrizzleHandles`. `build` makes an instance on the
|
|
1016
|
+
* transaction's own connection, with the relations config when given one.
|
|
1017
|
+
*
|
|
1018
|
+
* @protected
|
|
1019
|
+
*/
|
|
1020
|
+
protected transactionDrizzleHandles<TBare>(build: (relations?: AnyRelations) => TBare): {
|
|
1021
|
+
bare: () => TBare;
|
|
1022
|
+
withRelations: <T = unknown>(relations: AnyRelations) => T;
|
|
1023
|
+
};
|
|
1024
|
+
/**
|
|
1025
|
+
* A transaction context's `update`, for each adapter to bind.
|
|
1026
|
+
*
|
|
1027
|
+
* Not forwarded to the pooled `update` the way `select` and `delete` are:
|
|
1028
|
+
* that one goes through the Drizzle query builder, which writes the columns
|
|
1029
|
+
* the runtime MODEL declares, and a transaction's update must reach the
|
|
1030
|
+
* columns the physical TABLE has — the localization transition window
|
|
1031
|
+
* writes a column the model has already moved to a companion table that
|
|
1032
|
+
* does not exist yet. The INSERT half of every transaction context already
|
|
1033
|
+
* builds its own statement for that reason; `update-statement.ts` is the
|
|
1034
|
+
* UPDATE half, spelled once for the three adapters, and this runs it: on
|
|
1035
|
+
* the transaction executor, classified with the operation and table named
|
|
1036
|
+
* as the pooled `update` classifies its failures, and read back through
|
|
1037
|
+
* `select` on the same executor when the caller asked for rows.
|
|
1038
|
+
*
|
|
1039
|
+
* That read is by the rows' IDENTITY where the dialect can report it: on
|
|
1040
|
+
* PostgreSQL and SQLite the statement carries `RETURNING <primary key>`, and
|
|
1041
|
+
* the read-back asks for exactly those rows — so a row another transaction
|
|
1042
|
+
* adds under the same predicate meanwhile is not among them, and an update
|
|
1043
|
+
* whose own write falsifies its predicate still reads its rows back. MySQL
|
|
1044
|
+
* has no RETURNING, so there the read re-runs the predicate, as the pooled
|
|
1045
|
+
* `update` always has on that dialect; a table with no primary key in its
|
|
1046
|
+
* model reads back the same way.
|
|
1047
|
+
*
|
|
1048
|
+
* @param txDb - thunk returning the transaction-bound Drizzle instance
|
|
1049
|
+
* @param run - how this dialect runs a statement on that instance, and the
|
|
1050
|
+
* rows it returns when the statement carries RETURNING: better-sqlite3
|
|
1051
|
+
* answers synchronously, the pooled drivers do not
|
|
1052
|
+
* @param bindUnmodeled - how a value binds when the model declares no
|
|
1053
|
+
* column for it; a declared column binds through its own encoder
|
|
1054
|
+
* @returns the context's `update` method
|
|
1055
|
+
*/
|
|
1056
|
+
protected transactionUpdate(txDb: () => unknown, run: (statement: SQL, returnsRows: boolean) => Promise<Record<string, unknown>[] | undefined> | Record<string, unknown>[] | undefined, bindUnmodeled: (value: unknown) => unknown): TransactionContext["update"];
|
|
1057
|
+
/**
|
|
1058
|
+
* The columns that identify a row of this table, under both spellings: the
|
|
1059
|
+
* SQL name RETURNING reports and the Drizzle property name the query
|
|
1060
|
+
* builder's WHERE is addressed by. Columns flagged primary first; failing
|
|
1061
|
+
* that, the table-level primary key the dialect's table config carries
|
|
1062
|
+
* (`primaryKey({ columns })` leaves each column's flag false), which each
|
|
1063
|
+
* adapter reads through its own dialect. Empty when the model declares
|
|
1064
|
+
* neither, and the read-back falls back to the caller's predicate.
|
|
1065
|
+
*/
|
|
1066
|
+
protected identityColumns(tableObj: Record<string, unknown>): Array<{
|
|
1067
|
+
jsName: string;
|
|
1068
|
+
sqlName: string;
|
|
1069
|
+
}>;
|
|
1070
|
+
/**
|
|
1071
|
+
* How a value binds to a column the model does not declare, on a driver
|
|
1072
|
+
* that binds scalars, dates and binary natively: a structured value goes
|
|
1073
|
+
* as JSON text, since what node-postgres and mysql2 make of a bare object
|
|
1074
|
+
* or array is not JSON. For the adapters to hand `transactionUpdate`.
|
|
1075
|
+
*/
|
|
1076
|
+
protected bindUnmodeledStructuredAsJson(value: unknown): unknown;
|
|
1077
|
+
/**
|
|
1078
|
+
* Refuse an upsert target every dialect would not answer alike: a conflict
|
|
1079
|
+
* column named twice, which SQLite rejects as no constraint's target and
|
|
1080
|
+
* MySQL would accept; and, when nothing is to be updated, a conflict column
|
|
1081
|
+
* left for the database to fill, since the row that stands is then read
|
|
1082
|
+
* back by a value the caller never gave. Shared with the dialects that
|
|
1083
|
+
* override `upsert`, so the refusals are one rule.
|
|
1084
|
+
*/
|
|
1085
|
+
protected assertUpsertTarget(table: string, data: Record<string, unknown>, options: UpsertOptions, keepExisting: boolean): void;
|
|
1086
|
+
/**
|
|
1087
|
+
* The columns of a table-level `primaryKey({ columns })`, as the dialect's
|
|
1088
|
+
* table config reports them. The base class cannot read that config without
|
|
1089
|
+
* naming a dialect, so each adapter answers for its own; a dialect that does
|
|
1090
|
+
* not answer reports none.
|
|
1091
|
+
*/
|
|
1092
|
+
protected compositePrimaryKey(_tableObj: Record<string, unknown>): object[];
|
|
1093
|
+
/** The registered table object, or the error every CRUD method throws without one. */
|
|
1094
|
+
private resolvedTableObject;
|
|
1095
|
+
/**
|
|
1096
|
+
* The statement `transactionUpdate` runs.
|
|
1097
|
+
*
|
|
1098
|
+
* @throws when nothing would be written — every key `undefined`, or none at
|
|
1099
|
+
* all. The query builder refused that too ("No values to set"), and a
|
|
1100
|
+
* patch that names nothing is a caller's mistake rather than a write of
|
|
1101
|
+
* nothing.
|
|
1102
|
+
*/
|
|
1103
|
+
private buildTransactionUpdate;
|
|
1104
|
+
/**
|
|
1105
|
+
* Whether a transaction's `update` reads the rows it changed back: the
|
|
1106
|
+
* caller named columns, or `*`. An empty list, like no option at all, asks
|
|
1107
|
+
* for nothing and `update` answers `[]`, as it always has. The rows come
|
|
1108
|
+
* from a read of the update's own WHERE on its own transaction, so they are
|
|
1109
|
+
* the model's view of the row, decoded as every read is decoded — which is
|
|
1110
|
+
* what the query-builder update returned for them, and why the named list
|
|
1111
|
+
* selects nothing narrower.
|
|
1112
|
+
*/
|
|
1113
|
+
private updateReturnsRows;
|
|
1114
|
+
/**
|
|
1115
|
+
* The driver's own error inside `error`: the first in its `cause` chain that
|
|
1116
|
+
* `isDriverError` recognises, or `error` itself when none does.
|
|
1117
|
+
*
|
|
1118
|
+
* A query that runs through Drizzle fails with Drizzle's `DrizzleQueryError`,
|
|
1119
|
+
* whose message is the SQL statement and which carries no driver code; the
|
|
1120
|
+
* driver's error, the only object that knows what actually went wrong, is
|
|
1121
|
+
* its `cause`. A dialect's {@link classifyError} classifies from what this
|
|
1122
|
+
* returns, so a failure reads the same whether or not Drizzle wrapped it.
|
|
1123
|
+
*
|
|
1124
|
+
* The walk is bounded, because an error chain can be made cyclic and a
|
|
1125
|
+
* classifier that can hang is worse than one that gives up. Falling back to
|
|
1126
|
+
* `error` keeps an error that carries no code anywhere classified as before.
|
|
1127
|
+
*
|
|
1128
|
+
* @param error - The error as it was caught
|
|
1129
|
+
* @param isDriverError - Whether a link in the chain is the driver's error
|
|
1130
|
+
* @returns The driver's error, or `error` when no link is
|
|
1131
|
+
*/
|
|
1132
|
+
protected driverErrorIn<T extends {
|
|
1133
|
+
cause?: unknown;
|
|
1134
|
+
}>(error: unknown, isDriverError: (candidate: T) => boolean): T;
|
|
1135
|
+
/**
|
|
1136
|
+
* Classify an error into a DatabaseError.
|
|
1137
|
+
*
|
|
1138
|
+
* @remarks
|
|
1139
|
+
* Subclasses can override this method to add dialect-specific error code classification.
|
|
1140
|
+
*
|
|
1141
|
+
* @param error - Original error
|
|
1142
|
+
* @param sql - SQL statement that caused the error (optional)
|
|
1143
|
+
* @returns DatabaseError instance
|
|
1144
|
+
*
|
|
1145
|
+
* @protected
|
|
1146
|
+
*/
|
|
1147
|
+
protected classifyError(error: unknown, sql?: string): DatabaseError;
|
|
1148
|
+
/**
|
|
1149
|
+
* Handle query errors and convert to DatabaseError.
|
|
1150
|
+
*
|
|
1151
|
+
* @remarks
|
|
1152
|
+
* Protected helper for consistent error handling across CRUD operations.
|
|
1153
|
+
* Delegates to `classifyError` and attaches operation and table context if not present.
|
|
1154
|
+
* Subclasses override `classifyError` to provide dialect-specific error code classification.
|
|
1155
|
+
*
|
|
1156
|
+
* @param error - Original error
|
|
1157
|
+
* @param operation - Operation that failed
|
|
1158
|
+
* @param table - Table name
|
|
1159
|
+
* @returns DatabaseError instance
|
|
1160
|
+
*
|
|
1161
|
+
* @protected
|
|
1162
|
+
*/
|
|
1163
|
+
protected handleQueryError(error: unknown, operation: string, table: string): DatabaseError;
|
|
1164
|
+
}
|
|
1165
|
+
export { TransactionCrudDelegator as n, TransactionCrudForwarders as r, DrizzleAdapter as t };
|
|
1166
|
+
//# sourceMappingURL=adapter-CSP-Ek-L.d.ts.map
|