@vibeorm/adapter-mysql 2.3.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +8 -5
- package/dist/config.d.ts +2 -2
- package/dist/errors.d.ts +14 -0
- package/dist/index.d.ts +41 -11
- package/dist/index.js +223 -87
- package/dist/index.js.map +6 -6
- package/dist/transaction-sql.d.ts +27 -0
- package/package.json +6 -4
- package/dist/acquire.d.ts.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/placeholders.d.ts.map +0 -1
- package/dist/results.d.ts.map +0 -1
- package/dist/transaction-sql.d.ts.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 VibeORM contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -16,7 +16,10 @@ bun add @vibeorm/adapter-mysql
|
|
|
16
16
|
import { VibeClient } from "./generated/vibeorm/index.js";
|
|
17
17
|
import { mysqlAdapter } from "@vibeorm/adapter-mysql";
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
// The adapter reads no environment variable: pass the address you mean.
|
|
20
|
+
const url = process.env.MYSQL_URL;
|
|
21
|
+
if (!url) throw new Error("MYSQL_URL is not set");
|
|
22
|
+
const db = VibeClient({ adapter: mysqlAdapter({ url }) });
|
|
20
23
|
|
|
21
24
|
const users = await db.user.findMany({ where: { email: { contains: "@example.com" } }, take: 10 });
|
|
22
25
|
|
|
@@ -25,13 +28,13 @@ await db.$disconnect();
|
|
|
25
28
|
|
|
26
29
|
## Options
|
|
27
30
|
|
|
28
|
-
`mysqlAdapter(options
|
|
31
|
+
`mysqlAdapter(options: MysqlAdapterOptions)` — one of `url`, `host` or `pool` is required. Without any, the factory throws `VIBE_CONFIG` (`meta.reason: "missing-address"`) before any pool or connection exists. The adapter never reads `MYSQL_URL`.
|
|
29
32
|
|
|
30
33
|
| Option | Type | Default | Meaning |
|
|
31
34
|
|---|---|---|---|
|
|
32
|
-
| `url` | `string` |
|
|
33
|
-
| `host` / `port` / `user` / `password` / `database` | `string` / `number` | — | Discrete connection fields. When both are given, these win over the parsed `url`. |
|
|
34
|
-
| `pool` | `MysqlPoolLike` | — | An existing mysql2 promise pool. The adapter never ends a pool it did not create
|
|
35
|
+
| `url` | `string` | — | Connection URL, `mysql://user:pw@host:3306/db`. Give a host: mysql2 connects a URL without one (`mysql:///db`) to its built-in `localhost`. |
|
|
36
|
+
| `host` / `port` / `user` / `password` / `database` | `string` / `number` | — | Discrete connection fields; `host` is the address. `database` may be omitted for a server-level connection. When both are given, these win over the parsed `url`. |
|
|
37
|
+
| `pool` | `MysqlPoolLike` | — | An existing mysql2 promise pool. The adapter never ends a pool it did not create; `disconnect()` then only ends the adapter (later calls refuse with `VIBE_ADAPTER_CLOSED`). Configuring it to the codec contract is on you. |
|
|
35
38
|
| `connectionLimit` | `number` | mysql2's `10` | Maximum pooled connections. Ignored when `pool` is given. |
|
|
36
39
|
| `timezone` | `string` | `"Z"` | mysql2 timezone. `DATETIME(3)` carries no zone, so `"Z"` makes outgoing `Date`s serialize as UTC and incoming text parse as UTC. mysql2's own default (`"local"`) would shift values by the process offset. |
|
|
37
40
|
| `charset` | `string` | mysql2's `utf8mb4_general_ci` | Connection charset/collation. |
|
package/dist/config.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { MysqlAdapterSettings, MysqlPoolConfig } from "./index.ts";
|
|
2
2
|
/** The mysql2 typeCast surface used for JSON; other scalars keep the driver decoder. */
|
|
3
3
|
export type MysqlTypeCast = (field: {
|
|
4
4
|
readonly type: string;
|
|
@@ -7,6 +7,6 @@ export type MysqlTypeCast = (field: {
|
|
|
7
7
|
}, next: () => unknown) => unknown;
|
|
8
8
|
/** Parse once, overlay explicit options, then pin the wire and statement contracts. */
|
|
9
9
|
export declare function mysqlPoolConfig(params: {
|
|
10
|
-
options?:
|
|
10
|
+
options?: MysqlAdapterSettings;
|
|
11
11
|
}): MysqlPoolConfig;
|
|
12
12
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/errors.d.ts
CHANGED
|
@@ -23,6 +23,20 @@ import { VibeError, type VibeErrorCode } from "@vibeorm/schema";
|
|
|
23
23
|
export declare const MYSQL_ERRNO_ERROR_CODES: Readonly<Record<number, VibeErrorCode>>;
|
|
24
24
|
/** Errnos that additionally explain themselves through `meta.reason`. */
|
|
25
25
|
export declare const MYSQL_ERRNO_REASONS: Readonly<Record<number, string>>;
|
|
26
|
+
/**
|
|
27
|
+
* Errnos the MySQL 8.4 server error reference documents as "the WHOLE
|
|
28
|
+
* transaction was rolled back". A COMMIT the server answers with one of these
|
|
29
|
+
* did not commit. Every other COMMIT error proves nothing and stays `unknown`:
|
|
30
|
+
* 1205 ER_LOCK_WAIT_TIMEOUT rolls back only the statement by default ("not the entire
|
|
31
|
+
* transaction"), and 1180 ER_ERROR_DURING_COMMIT / 3100 ER_RUN_HOOK_ERROR say
|
|
32
|
+
* nothing about a rollback. Frozen and mirrored by tests.
|
|
33
|
+
*
|
|
34
|
+
* - 1213 ER_LOCK_DEADLOCK: "a transaction encounters a deadlock and is
|
|
35
|
+
* automatically rolled back".
|
|
36
|
+
* - 3101 ER_TRANSACTION_ROLLBACK_DURING_COMMIT: "a transaction failed the group
|
|
37
|
+
* certification process […] and was thus rolled back".
|
|
38
|
+
*/
|
|
39
|
+
export declare const MYSQL_ROLLED_BACK_ERRNOS: readonly number[];
|
|
26
40
|
/**
|
|
27
41
|
* Extract the numeric MySQL errno from a mysql2 error. Client-side failures
|
|
28
42
|
* (`ECONNREFUSED`, `PROTOCOL_CONNECTION_LOST`, …) have no numeric errno and
|
package/dist/index.d.ts
CHANGED
|
@@ -31,6 +31,14 @@ export type MysqlConnectionLike = {
|
|
|
31
31
|
ping(): Promise<void>;
|
|
32
32
|
release(): void;
|
|
33
33
|
destroy(): void;
|
|
34
|
+
/**
|
|
35
|
+
* mysql2's connection events. Optional, so injected doubles without them
|
|
36
|
+
* stay valid. A transaction listens for `error` and `end`: once either fired,
|
|
37
|
+
* mysql2 refuses every later command on that connection locally, so a
|
|
38
|
+
* COMMIT after it never leaves the client (EPIC T).
|
|
39
|
+
*/
|
|
40
|
+
on?(event: "error" | "end", listener: (error?: unknown) => void): unknown;
|
|
41
|
+
removeListener?(event: "error" | "end", listener: (error?: unknown) => void): unknown;
|
|
34
42
|
};
|
|
35
43
|
/** The parts of a mysql2 promise `Pool` this adapter uses. */
|
|
36
44
|
export type MysqlPoolLike = {
|
|
@@ -82,14 +90,16 @@ export type MysqlPoolConfig = {
|
|
|
82
90
|
readonly multipleStatements: boolean;
|
|
83
91
|
};
|
|
84
92
|
/**
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* both; when both are given the discrete fields win — the adapter parses the
|
|
88
|
-
* URL once before overlaying explicit config), or hand it a pool you already own.
|
|
93
|
+
* Every {@link mysqlAdapter} option. {@link MysqlAdapterOptions} adds the rule
|
|
94
|
+
* that one of `url`, `host` and `pool` is present.
|
|
89
95
|
*/
|
|
90
|
-
export type
|
|
91
|
-
/**
|
|
96
|
+
export type MysqlAdapterSettings = {
|
|
97
|
+
/**
|
|
98
|
+
* MySQL connection URL (`mysql://user:pw@host:3306/db`). The adapter never
|
|
99
|
+
* reads `MYSQL_URL` (or any other environment variable) itself.
|
|
100
|
+
*/
|
|
92
101
|
readonly url?: string;
|
|
102
|
+
/** Server host, the address of the discrete-field form. `database` may be omitted for a server-level connection. */
|
|
93
103
|
readonly host?: string;
|
|
94
104
|
readonly port?: number;
|
|
95
105
|
readonly user?: string;
|
|
@@ -97,8 +107,9 @@ export type MysqlAdapterOptions = {
|
|
|
97
107
|
readonly database?: string;
|
|
98
108
|
/**
|
|
99
109
|
* An existing mysql2 promise pool to use instead of creating one. The
|
|
100
|
-
* adapter never ends a pool it did not create
|
|
101
|
-
*
|
|
110
|
+
* adapter never ends a pool it did not create: `disconnect()` only ends this
|
|
111
|
+
* adapter (and rolls back and releases its own raw session); the pool stays
|
|
112
|
+
* usable. The pool MUST be configured to the codec contract
|
|
102
113
|
* ({@link MysqlPoolConfig}) — the adapter cannot verify it.
|
|
103
114
|
*/
|
|
104
115
|
readonly pool?: MysqlPoolLike;
|
|
@@ -148,12 +159,31 @@ export type MysqlAdapterOptions = {
|
|
|
148
159
|
*/
|
|
149
160
|
readonly createPool?: (config: MysqlPoolConfig) => MysqlPoolLike;
|
|
150
161
|
};
|
|
162
|
+
/**
|
|
163
|
+
* Options for {@link mysqlAdapter}: an explicit address is required. Point it
|
|
164
|
+
* at a connection URL **or** at discrete `host`/`port`/`user`/`password`/
|
|
165
|
+
* `database` fields (mysql2 accepts both; when both are given the discrete
|
|
166
|
+
* fields win — the adapter parses the URL once before overlaying explicit
|
|
167
|
+
* config), or hand it a pool you already own. Without any of the three, the
|
|
168
|
+
* factory throws `VIBE_CONFIG` before any pool or connection exists.
|
|
169
|
+
*/
|
|
170
|
+
export type MysqlAdapterOptions = MysqlAdapterSettings & ({
|
|
171
|
+
readonly url: string;
|
|
172
|
+
} | {
|
|
173
|
+
readonly host: string;
|
|
174
|
+
} | {
|
|
175
|
+
readonly pool: MysqlPoolLike;
|
|
176
|
+
});
|
|
151
177
|
/**
|
|
152
178
|
* Create a VibeORM adapter backed by mysql2.
|
|
153
179
|
*
|
|
180
|
+
* Requires an explicit address (`url`, `host` or `pool`); see
|
|
181
|
+
* {@link MysqlAdapterOptions}. Construction opens nothing — the pool is
|
|
182
|
+
* created on first use.
|
|
183
|
+
*
|
|
154
184
|
* @example
|
|
155
185
|
* ```ts
|
|
156
|
-
* const adapter = mysqlAdapter({ url:
|
|
186
|
+
* const adapter = mysqlAdapter({ url: "mysql://app:secret@db.internal:3306/app", connectionLimit: 20 });
|
|
157
187
|
* await adapter.connect();
|
|
158
188
|
* const rows = await adapter.execute({ text: "SELECT * FROM `User` WHERE `id` = ?", values: [1] });
|
|
159
189
|
* ```
|
|
@@ -174,10 +204,10 @@ export type MysqlAdapterOptions = {
|
|
|
174
204
|
* string, DateTime is a `Date` (mysql2 serializes it per `timezone`), BigInt
|
|
175
205
|
* is a string. The adapter forwards values verbatim — no second conversion.
|
|
176
206
|
*/
|
|
177
|
-
export declare function mysqlAdapter(options
|
|
207
|
+
export declare function mysqlAdapter(options: MysqlAdapterOptions): DatabaseAdapter;
|
|
178
208
|
export { DEFAULT_ACQUIRE_TIMERS, MYSQL_DEFAULT_CONNECTION_LIMIT, acquireTimeoutError, acquireWithTimeout, } from "./acquire.ts";
|
|
179
209
|
export type { AcquireSource, AcquireTimers, ReleasableConnection, TimerHandle } from "./acquire.ts";
|
|
180
|
-
export { MYSQL_ERRNO_ERROR_CODES, MYSQL_ERRNO_REASONS, mapMysqlDriverError, mysqlErrorErrno, runMapped, } from "./errors.ts";
|
|
210
|
+
export { MYSQL_ERRNO_ERROR_CODES, MYSQL_ERRNO_REASONS, MYSQL_ROLLED_BACK_ERRNOS, mapMysqlDriverError, mysqlErrorErrno, runMapped, } from "./errors.ts";
|
|
181
211
|
export { isResultSetHeader, normalizeDriverResult } from "./results.ts";
|
|
182
212
|
export { createSavepointCounter, nextSavepointName } from "@vibeorm/runtime/adapter-kit";
|
|
183
213
|
export type { SavepointCounter } from "@vibeorm/runtime/adapter-kit";
|
package/dist/index.js
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/adapter-mysql/src/index.ts
|
|
3
3
|
import {
|
|
4
|
+
createAdapterLifecycleGate,
|
|
4
5
|
runPinnedSession,
|
|
6
|
+
runShutdownCleanup,
|
|
7
|
+
transactionLifecycleRefusal,
|
|
5
8
|
observeRowChanges,
|
|
6
9
|
readRowChanges,
|
|
7
10
|
statementRowChanges,
|
|
11
|
+
closeFailedTransactionBudget,
|
|
8
12
|
createSavepointScope,
|
|
9
|
-
isTransactionDeadlineError,
|
|
10
13
|
isSavepointRollbackFailedError,
|
|
11
14
|
runNestedSavepoint,
|
|
12
15
|
runRootScope,
|
|
13
16
|
scopeTurn,
|
|
17
|
+
settleFailedTransaction,
|
|
14
18
|
startTransactionBudget,
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
validateTransactionDeadline,
|
|
20
|
+
readOnlyRequested
|
|
17
21
|
} from "@vibeorm/runtime/adapter-kit";
|
|
18
22
|
import { internalError, VibeError as VibeError6 } from "@vibeorm/schema";
|
|
19
23
|
import { createPool as mysql2CreatePool } from "mysql2/promise";
|
|
@@ -78,7 +82,7 @@ var typeCast = (field, next) => {
|
|
|
78
82
|
};
|
|
79
83
|
function mysqlPoolConfig(params) {
|
|
80
84
|
const options = params.options;
|
|
81
|
-
const url = options?.url
|
|
85
|
+
const url = options?.url;
|
|
82
86
|
let parsed;
|
|
83
87
|
try {
|
|
84
88
|
parsed = url === undefined ? {} : connectionConfig.parseUrl(url);
|
|
@@ -139,16 +143,21 @@ var MYSQL_ERRNO_ERROR_CODES = Object.freeze({
|
|
|
139
143
|
1292: "VIBE_VALIDATION",
|
|
140
144
|
3819: "VIBE_VALIDATION",
|
|
141
145
|
1213: "VIBE_TRANSACTION",
|
|
146
|
+
3101: "VIBE_TRANSACTION",
|
|
142
147
|
1205: "VIBE_LOCK_NOT_AVAILABLE",
|
|
143
148
|
3572: "VIBE_LOCK_NOT_AVAILABLE",
|
|
144
|
-
3024: "VIBE_TRANSACTION"
|
|
149
|
+
3024: "VIBE_TRANSACTION",
|
|
150
|
+
1792: "VIBE_TRANSACTION"
|
|
145
151
|
});
|
|
146
152
|
var MYSQL_ERRNO_REASONS = Object.freeze({
|
|
147
153
|
1213: "deadlock",
|
|
154
|
+
3101: "serialization-failure",
|
|
148
155
|
1205: "lock-not-available",
|
|
149
156
|
3572: "lock-not-available",
|
|
150
|
-
3024: "timeout"
|
|
157
|
+
3024: "timeout",
|
|
158
|
+
1792: "read-only-transaction"
|
|
151
159
|
});
|
|
160
|
+
var MYSQL_ROLLED_BACK_ERRNOS = Object.freeze([1213, 3101]);
|
|
152
161
|
function readStringField(params) {
|
|
153
162
|
const value = params.source[params.key];
|
|
154
163
|
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
@@ -371,6 +380,17 @@ function maxExecutionTimeStatement(params) {
|
|
|
371
380
|
}
|
|
372
381
|
return `SET SESSION MAX_EXECUTION_TIME = ${timeout}`;
|
|
373
382
|
}
|
|
383
|
+
var ISOLATION_LEVEL_VALUE = Object.freeze({
|
|
384
|
+
ReadCommitted: "READ-COMMITTED",
|
|
385
|
+
RepeatableRead: "REPEATABLE-READ",
|
|
386
|
+
Serializable: "SERIALIZABLE"
|
|
387
|
+
});
|
|
388
|
+
function sessionOptionsStatement(params) {
|
|
389
|
+
const timeoutText = maxExecutionTimeStatement({ timeout: params.timeout });
|
|
390
|
+
const ms = timeoutText.slice(timeoutText.lastIndexOf(" ") + 1);
|
|
391
|
+
return `SET @@SESSION.max_execution_time = ${ms}, @@transaction_isolation = '${ISOLATION_LEVEL_VALUE[params.isolationLevel]}'`;
|
|
392
|
+
}
|
|
393
|
+
var START_TRANSACTION_READ_ONLY_SQL = "START TRANSACTION READ ONLY";
|
|
374
394
|
var RESET_MAX_EXECUTION_TIME_SQL = "SET SESSION MAX_EXECUTION_TIME = DEFAULT";
|
|
375
395
|
var RAW_OPEN_PATTERN = /^\s*(?:begin|start\s+transaction)\b[^;]*;?\s*$/i;
|
|
376
396
|
var RAW_CLOSE_PATTERN = /^\s*(?:commit|rollback)(?:\s+work)?\s*;?\s*$/i;
|
|
@@ -387,20 +407,22 @@ import { createSavepointCounter, nextSavepointName } from "@vibeorm/runtime/adap
|
|
|
387
407
|
import {
|
|
388
408
|
DEFAULT_DEADLINE_CLOCK,
|
|
389
409
|
engineStatementBudgetMs,
|
|
390
|
-
isTransactionDeadlineError
|
|
410
|
+
isTransactionDeadlineError,
|
|
391
411
|
startTransactionBudget as startTransactionBudget2,
|
|
392
412
|
transactionClosedError,
|
|
393
413
|
transactionDeadlineError,
|
|
394
|
-
transactionOutcomeUnknownError
|
|
414
|
+
transactionOutcomeUnknownError,
|
|
395
415
|
validateTransactionDeadline as validateTransactionDeadline2
|
|
396
416
|
} from "@vibeorm/runtime/adapter-kit";
|
|
397
417
|
var DIALECT = "mysql";
|
|
398
418
|
var PROVIDER = "mysql";
|
|
399
419
|
var WIRE = Object.freeze({ dateTime: "native", json: "parsed", numbers: "native" });
|
|
420
|
+
var ROUND_TRIPS = "network";
|
|
400
421
|
var BUDGETS = Object.freeze({
|
|
401
422
|
acquireTimeout: true,
|
|
402
423
|
statementTimeout: "select-only",
|
|
403
|
-
transactionDeadline: "between-statements"
|
|
424
|
+
transactionDeadline: "between-statements",
|
|
425
|
+
accessModes: Object.freeze(["readOnly"])
|
|
404
426
|
});
|
|
405
427
|
function defaultCreatePool(config) {
|
|
406
428
|
return mysql2CreatePool(config);
|
|
@@ -413,33 +435,59 @@ function finalizationOutcomeUnknown(params) {
|
|
|
413
435
|
cause: params.cause
|
|
414
436
|
});
|
|
415
437
|
}
|
|
438
|
+
function connectionLostBeforeCommit(params) {
|
|
439
|
+
return new VibeError6({
|
|
440
|
+
code: "VIBE_ADAPTER",
|
|
441
|
+
message: "the MySQL connection was lost before COMMIT, so COMMIT was never sent and the transaction did not commit. The connection was discarded.",
|
|
442
|
+
meta: { provider: PROVIDER, reason: "connection-lost", stage: "commit" },
|
|
443
|
+
...params.cause === undefined ? {} : { cause: params.cause }
|
|
444
|
+
});
|
|
445
|
+
}
|
|
416
446
|
function throwOnArrayParam(values) {
|
|
417
447
|
throw internalError({
|
|
418
448
|
message: "formatArrayParam called on the mysql adapter \u2014 the mysql dialect expands scalar-list parameters into IN (?, ?, \u2026) placeholders, so the runtime should have expanded this array before binding",
|
|
419
449
|
meta: { length: values.length }
|
|
420
450
|
});
|
|
421
451
|
}
|
|
452
|
+
function isGiven(value) {
|
|
453
|
+
return typeof value === "string" && value.trim() !== "";
|
|
454
|
+
}
|
|
455
|
+
function takeAddress(params) {
|
|
456
|
+
const options = params.options;
|
|
457
|
+
if (options?.pool !== undefined && options.pool !== null)
|
|
458
|
+
return { pool: options.pool };
|
|
459
|
+
if (options !== undefined && (isGiven(options.url) || isGiven(options.host)))
|
|
460
|
+
return { options: { ...options } };
|
|
461
|
+
throw new VibeError6({
|
|
462
|
+
code: "VIBE_CONFIG",
|
|
463
|
+
message: "mysqlAdapter needs an explicit address: pass `url`, a `host` (with port/user/password/database as needed) " + "or an existing `pool`. The adapter does not read MYSQL_URL or DATABASE_URL.",
|
|
464
|
+
meta: { adapter: "mysql", reason: "missing-address" }
|
|
465
|
+
});
|
|
466
|
+
}
|
|
422
467
|
function mysqlAdapter(options) {
|
|
468
|
+
const address = takeAddress({ options });
|
|
423
469
|
let pool = null;
|
|
424
470
|
let ownsPool = false;
|
|
425
471
|
let rawSession = null;
|
|
426
472
|
const acquireTimeoutMs = options?.acquireTimeout;
|
|
427
|
-
const poolSize =
|
|
428
|
-
function getPool() {
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
pool
|
|
433
|
-
|
|
473
|
+
const poolSize = "pool" in address ? undefined : address.options.connectionLimit ?? MYSQL_DEFAULT_CONNECTION_LIMIT;
|
|
474
|
+
async function getPool() {
|
|
475
|
+
return runMapped(async () => {
|
|
476
|
+
if (pool !== null)
|
|
477
|
+
return pool;
|
|
478
|
+
if ("pool" in address) {
|
|
479
|
+
pool = address.pool;
|
|
480
|
+
ownsPool = false;
|
|
481
|
+
return pool;
|
|
482
|
+
}
|
|
483
|
+
const config = mysqlPoolConfig({ options: address.options });
|
|
484
|
+
pool = (address.options.createPool ?? defaultCreatePool)(config);
|
|
485
|
+
ownsPool = true;
|
|
434
486
|
return pool;
|
|
435
|
-
}
|
|
436
|
-
const config = mysqlPoolConfig({ options });
|
|
437
|
-
pool = (options?.createPool ?? defaultCreatePool)(config);
|
|
438
|
-
ownsPool = true;
|
|
439
|
-
return pool;
|
|
487
|
+
});
|
|
440
488
|
}
|
|
441
489
|
async function acquireConnection() {
|
|
442
|
-
const active = getPool();
|
|
490
|
+
const active = pool ?? await getPool();
|
|
443
491
|
if (acquireTimeoutMs === undefined) {
|
|
444
492
|
return runMapped(() => active.getConnection());
|
|
445
493
|
}
|
|
@@ -488,7 +536,7 @@ function mysqlAdapter(options) {
|
|
|
488
536
|
scope.state.poisoned = new VibeError6({
|
|
489
537
|
code: mapped.code,
|
|
490
538
|
message: mapped.message,
|
|
491
|
-
meta: { ...mapped.meta, outcome: "
|
|
539
|
+
meta: { ...mapped.meta, outcome: "not-committed" },
|
|
492
540
|
cause: mapped
|
|
493
541
|
});
|
|
494
542
|
}
|
|
@@ -501,6 +549,7 @@ function mysqlAdapter(options) {
|
|
|
501
549
|
provider: PROVIDER,
|
|
502
550
|
wire: WIRE,
|
|
503
551
|
budgets: BUDGETS,
|
|
552
|
+
roundTrips: ROUND_TRIPS,
|
|
504
553
|
rowChanges: () => {
|
|
505
554
|
budget.assertUsable({ stage: "statement" });
|
|
506
555
|
return readRowChanges({ scope });
|
|
@@ -538,18 +587,45 @@ function mysqlAdapter(options) {
|
|
|
538
587
|
body: (child) => fn(createConnectionAdapter({ conn, scope: child, budget }))
|
|
539
588
|
}).catch(invalidate);
|
|
540
589
|
},
|
|
541
|
-
async connect() {
|
|
542
|
-
|
|
590
|
+
async connect() {
|
|
591
|
+
budget.assertUsable({ stage: "statement" });
|
|
592
|
+
throw transactionLifecycleRefusal({ method: "connect" });
|
|
593
|
+
},
|
|
594
|
+
async disconnect() {
|
|
595
|
+
budget.assertUsable({ stage: "statement" });
|
|
596
|
+
throw transactionLifecycleRefusal({ method: "disconnect" });
|
|
597
|
+
},
|
|
543
598
|
formatArrayParam(values) {
|
|
544
599
|
return throwOnArrayParam(values);
|
|
545
600
|
}
|
|
546
601
|
};
|
|
547
602
|
}
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
603
|
+
function closeOwnedResources() {
|
|
604
|
+
return runShutdownCleanup({
|
|
605
|
+
steps: [
|
|
606
|
+
async () => {
|
|
607
|
+
if (rawSession === null)
|
|
608
|
+
return;
|
|
609
|
+
const session = rawSession;
|
|
610
|
+
rawSession = null;
|
|
611
|
+
await runMapped(() => session.query("ROLLBACK")).then(() => {
|
|
612
|
+
session.release();
|
|
613
|
+
}, (error) => {
|
|
614
|
+
session.destroy();
|
|
615
|
+
throw error;
|
|
616
|
+
});
|
|
617
|
+
},
|
|
618
|
+
async () => {
|
|
619
|
+
if (pool === null || !ownsPool)
|
|
620
|
+
return;
|
|
621
|
+
const closing = pool;
|
|
622
|
+
await runMapped(() => closing.end());
|
|
623
|
+
}
|
|
624
|
+
]
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
const lifecycle = createAdapterLifecycleGate({ driver: "mysql", cleanup: closeOwnedResources });
|
|
628
|
+
const root = {
|
|
553
629
|
async withSession({ run }) {
|
|
554
630
|
const conn = await acquireConnection();
|
|
555
631
|
return runPinnedSession({
|
|
@@ -563,7 +639,7 @@ function mysqlAdapter(options) {
|
|
|
563
639
|
},
|
|
564
640
|
async execute(params) {
|
|
565
641
|
if (acquireTimeoutMs === undefined) {
|
|
566
|
-
return runExecute({ queryable: getPool(), ...params });
|
|
642
|
+
return runExecute({ queryable: pool ?? await getPool(), ...params });
|
|
567
643
|
}
|
|
568
644
|
const conn = await acquireConnection();
|
|
569
645
|
try {
|
|
@@ -574,7 +650,7 @@ function mysqlAdapter(options) {
|
|
|
574
650
|
},
|
|
575
651
|
async executeAffected(params) {
|
|
576
652
|
if (acquireTimeoutMs === undefined) {
|
|
577
|
-
return runExecuteAffected({ queryable: getPool(), ...params });
|
|
653
|
+
return runExecuteAffected({ queryable: pool ?? await getPool(), ...params });
|
|
578
654
|
}
|
|
579
655
|
const conn = await acquireConnection();
|
|
580
656
|
try {
|
|
@@ -583,9 +659,6 @@ function mysqlAdapter(options) {
|
|
|
583
659
|
conn.release();
|
|
584
660
|
}
|
|
585
661
|
},
|
|
586
|
-
async executeRawBound(params) {
|
|
587
|
-
return this.executeUnsafe(params);
|
|
588
|
-
},
|
|
589
662
|
async executeUnsafe(params) {
|
|
590
663
|
const control = classifyRawTransactionControl({ text: params.text });
|
|
591
664
|
if (rawSession !== null) {
|
|
@@ -615,7 +688,7 @@ function mysqlAdapter(options) {
|
|
|
615
688
|
}
|
|
616
689
|
}
|
|
617
690
|
if (acquireTimeoutMs === undefined) {
|
|
618
|
-
return runExecuteUnsafe({ queryable: getPool(), ...params });
|
|
691
|
+
return runExecuteUnsafe({ queryable: pool ?? await getPool(), ...params });
|
|
619
692
|
}
|
|
620
693
|
const conn = await acquireConnection();
|
|
621
694
|
try {
|
|
@@ -631,21 +704,64 @@ function mysqlAdapter(options) {
|
|
|
631
704
|
support: BUDGETS.transactionDeadline,
|
|
632
705
|
provider: PROVIDER
|
|
633
706
|
});
|
|
707
|
+
const readOnly = readOnlyRequested({ options: transactionOptions, provider: PROVIDER });
|
|
708
|
+
const isolationLevel = transactionOptions?.isolationLevel;
|
|
709
|
+
const combinedText = transactionOptions?.timeout === undefined || isolationLevel === undefined ? undefined : sessionOptionsStatement({ timeout: transactionOptions.timeout, isolationLevel });
|
|
634
710
|
const conn = await acquireConnection();
|
|
635
711
|
let rollbackFailed = false;
|
|
636
712
|
const budget = startTransactionBudget({ options: transactionOptions, provider: PROVIDER });
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
713
|
+
const commit = { progress: "not-sent" };
|
|
714
|
+
const lost = { seen: false };
|
|
715
|
+
const onLost = (cause) => {
|
|
716
|
+
if (lost.seen)
|
|
717
|
+
return;
|
|
718
|
+
lost.seen = true;
|
|
719
|
+
lost.cause = cause;
|
|
720
|
+
};
|
|
721
|
+
conn.on?.("error", onLost);
|
|
722
|
+
conn.on?.("end", onLost);
|
|
723
|
+
let released;
|
|
724
|
+
const releaseConnection = async () => {
|
|
725
|
+
if (released !== undefined)
|
|
726
|
+
return released;
|
|
727
|
+
conn.removeListener?.("error", onLost);
|
|
728
|
+
conn.removeListener?.("end", onLost);
|
|
729
|
+
let poisoned = rollbackFailed || lost.seen;
|
|
730
|
+
if (timeoutText !== undefined && !poisoned) {
|
|
731
|
+
try {
|
|
732
|
+
await conn.query(RESET_MAX_EXECUTION_TIME_SQL);
|
|
733
|
+
} catch {
|
|
734
|
+
poisoned = true;
|
|
735
|
+
}
|
|
640
736
|
}
|
|
641
|
-
|
|
642
|
-
if (
|
|
643
|
-
|
|
644
|
-
|
|
737
|
+
released = poisoned ? "discarded" : "returned";
|
|
738
|
+
if (poisoned) {
|
|
739
|
+
conn.destroy();
|
|
740
|
+
} else {
|
|
741
|
+
conn.release();
|
|
645
742
|
}
|
|
646
|
-
|
|
647
|
-
|
|
743
|
+
return released;
|
|
744
|
+
};
|
|
745
|
+
const scope = createSavepointScope();
|
|
746
|
+
let opened = false;
|
|
747
|
+
try {
|
|
648
748
|
try {
|
|
749
|
+
if (combinedText !== undefined) {
|
|
750
|
+
await runMapped(() => conn.query(combinedText));
|
|
751
|
+
} else {
|
|
752
|
+
if (timeoutText !== undefined) {
|
|
753
|
+
await runMapped(() => conn.query(timeoutText));
|
|
754
|
+
}
|
|
755
|
+
if (isolationLevel !== undefined) {
|
|
756
|
+
const isolationText = setIsolationLevelStatement({ isolationLevel });
|
|
757
|
+
await runMapped(() => conn.query(isolationText));
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
if (readOnly)
|
|
761
|
+
await runMapped(() => conn.query(START_TRANSACTION_READ_ONLY_SQL));
|
|
762
|
+
else
|
|
763
|
+
await runMapped(() => conn.beginTransaction());
|
|
764
|
+
opened = true;
|
|
649
765
|
const result = await runRootScope({
|
|
650
766
|
scope,
|
|
651
767
|
body: () => fn(createConnectionAdapter({ conn, scope, budget }))
|
|
@@ -654,7 +770,16 @@ function mysqlAdapter(options) {
|
|
|
654
770
|
if (turn !== undefined)
|
|
655
771
|
await turn;
|
|
656
772
|
budget.assertUsable({ stage: "commit" });
|
|
773
|
+
if (lost.seen)
|
|
774
|
+
throw connectionLostBeforeCommit({ cause: lost.cause });
|
|
775
|
+
commit.progress = "sent";
|
|
657
776
|
await runMapped(() => conn.commit()).catch((cause) => {
|
|
777
|
+
const errno = cause instanceof VibeError6 ? cause.meta.errno : undefined;
|
|
778
|
+
if (typeof errno === "number" && MYSQL_ROLLED_BACK_ERRNOS.includes(errno)) {
|
|
779
|
+
commit.progress = "answered";
|
|
780
|
+
throw cause;
|
|
781
|
+
}
|
|
782
|
+
commit.progress = "unanswered";
|
|
658
783
|
budget.close({ outcome: "unknown" });
|
|
659
784
|
rollbackFailed = true;
|
|
660
785
|
throw finalizationOutcomeUnknown({ cause, stage: "commit" });
|
|
@@ -662,40 +787,33 @@ function mysqlAdapter(options) {
|
|
|
662
787
|
budget.close({ outcome: "committed" });
|
|
663
788
|
return result;
|
|
664
789
|
} catch (error) {
|
|
665
|
-
if (isSavepointRollbackFailedError(error) ||
|
|
790
|
+
if (isSavepointRollbackFailedError(error) || commit.progress === "unanswered") {
|
|
666
791
|
budget.close({ outcome: "unknown" });
|
|
667
792
|
rollbackFailed = true;
|
|
668
793
|
}
|
|
794
|
+
let rollback = "not-needed";
|
|
669
795
|
try {
|
|
670
|
-
|
|
671
|
-
|
|
796
|
+
if (opened) {
|
|
797
|
+
await conn.rollback();
|
|
798
|
+
rollback = "acknowledged";
|
|
799
|
+
}
|
|
672
800
|
} catch {
|
|
673
801
|
rollbackFailed = true;
|
|
674
|
-
|
|
675
|
-
if (budget.totalMs !== null && isTransactionDeadlineError(error)) {
|
|
676
|
-
throw transactionOutcomeUnknownError({
|
|
677
|
-
provider: PROVIDER,
|
|
678
|
-
totalMs: budget.totalMs,
|
|
679
|
-
cause: error
|
|
680
|
-
});
|
|
681
|
-
}
|
|
802
|
+
rollback = "failed";
|
|
682
803
|
}
|
|
683
|
-
|
|
804
|
+
closeFailedTransactionBudget({ error, budget, scope, commit: commit.progress });
|
|
805
|
+
throw settleFailedTransaction({
|
|
806
|
+
error,
|
|
807
|
+
provider: PROVIDER,
|
|
808
|
+
budget,
|
|
809
|
+
scope,
|
|
810
|
+
commit: commit.progress,
|
|
811
|
+
rollback,
|
|
812
|
+
connection: await releaseConnection()
|
|
813
|
+
});
|
|
684
814
|
}
|
|
685
815
|
} finally {
|
|
686
|
-
|
|
687
|
-
if (timeoutText !== undefined && !poisoned) {
|
|
688
|
-
try {
|
|
689
|
-
await conn.query(RESET_MAX_EXECUTION_TIME_SQL);
|
|
690
|
-
} catch {
|
|
691
|
-
poisoned = true;
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
if (poisoned) {
|
|
695
|
-
conn.destroy();
|
|
696
|
-
} else {
|
|
697
|
-
conn.release();
|
|
698
|
-
}
|
|
816
|
+
await releaseConnection();
|
|
699
817
|
}
|
|
700
818
|
},
|
|
701
819
|
async connect() {
|
|
@@ -705,21 +823,38 @@ function mysqlAdapter(options) {
|
|
|
705
823
|
} finally {
|
|
706
824
|
conn.release();
|
|
707
825
|
}
|
|
826
|
+
}
|
|
827
|
+
};
|
|
828
|
+
return {
|
|
829
|
+
dialect: DIALECT,
|
|
830
|
+
provider: PROVIDER,
|
|
831
|
+
wire: WIRE,
|
|
832
|
+
budgets: BUDGETS,
|
|
833
|
+
roundTrips: ROUND_TRIPS,
|
|
834
|
+
transactionOutcome: "reported",
|
|
835
|
+
withSession({ run }) {
|
|
836
|
+
return lifecycle.admit({ run: () => root.withSession({ run: (executor) => lifecycle.inCallback({ run: () => run(executor) }) }) });
|
|
708
837
|
},
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
}
|
|
838
|
+
execute(params) {
|
|
839
|
+
return lifecycle.admit({ run: () => root.execute(params) });
|
|
840
|
+
},
|
|
841
|
+
executeAffected(params) {
|
|
842
|
+
return lifecycle.admit({ run: () => root.executeAffected(params) });
|
|
843
|
+
},
|
|
844
|
+
executeRawBound(params) {
|
|
845
|
+
return lifecycle.admit({ run: () => root.executeUnsafe(params) });
|
|
846
|
+
},
|
|
847
|
+
executeUnsafe(params) {
|
|
848
|
+
return lifecycle.admit({ run: () => root.executeUnsafe(params) });
|
|
849
|
+
},
|
|
850
|
+
transaction(fn, transactionOptions) {
|
|
851
|
+
return lifecycle.admit({ run: () => root.transaction((txAdapter) => lifecycle.inCallback({ run: () => fn(txAdapter) }), transactionOptions) });
|
|
852
|
+
},
|
|
853
|
+
connect() {
|
|
854
|
+
return lifecycle.admit({ run: () => root.connect() });
|
|
855
|
+
},
|
|
856
|
+
disconnect() {
|
|
857
|
+
return lifecycle.disconnect();
|
|
723
858
|
},
|
|
724
859
|
formatArrayParam(values) {
|
|
725
860
|
return throwOnArrayParam(values);
|
|
@@ -733,6 +868,7 @@ export {
|
|
|
733
868
|
MYSQL_DEFAULT_CONNECTION_LIMIT,
|
|
734
869
|
MYSQL_ERRNO_ERROR_CODES,
|
|
735
870
|
MYSQL_ERRNO_REASONS,
|
|
871
|
+
MYSQL_ROLLED_BACK_ERRNOS,
|
|
736
872
|
RESET_MAX_EXECUTION_TIME_SQL,
|
|
737
873
|
acquireTimeoutError,
|
|
738
874
|
acquireWithTimeout,
|
|
@@ -740,7 +876,7 @@ export {
|
|
|
740
876
|
createSavepointCounter,
|
|
741
877
|
engineStatementBudgetMs,
|
|
742
878
|
isResultSetHeader,
|
|
743
|
-
|
|
879
|
+
isTransactionDeadlineError,
|
|
744
880
|
mapMysqlDriverError,
|
|
745
881
|
maxExecutionTimeStatement,
|
|
746
882
|
mysqlAdapter,
|
|
@@ -753,8 +889,8 @@ export {
|
|
|
753
889
|
startTransactionBudget2 as startTransactionBudget,
|
|
754
890
|
transactionClosedError,
|
|
755
891
|
transactionDeadlineError,
|
|
756
|
-
|
|
892
|
+
transactionOutcomeUnknownError,
|
|
757
893
|
validateTransactionDeadline2 as validateTransactionDeadline
|
|
758
894
|
};
|
|
759
895
|
|
|
760
|
-
//# debugId=
|
|
896
|
+
//# debugId=FADF8CA995993FB064756E2164756E21
|
package/dist/index.js.map
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts", "../src/acquire.ts", "../src/config.ts", "../src/errors.ts", "../src/placeholders.ts", "../src/results.ts", "../src/transaction-sql.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * @vibeorm/adapter-mysql — mysql2 adapter for VibeORM v2.\n *\n * Runs on Bun and Node over `mysql2/promise`. Owns pooling, transactions\n * (nested → savepoints on the same pinned connection) and driver-error\n * mapping. Only `VibeError` ever escapes.\n *\n * SAME-CONNECTION GUARANTEE (board #7): `transaction()` checks ONE connection\n * out of the pool and every operation on the callback's adapter — `execute`,\n * `executeUnsafe`, nested `transaction` — runs on that same connection until\n * commit/rollback. That pinning is what makes `LAST_INSERT_ID()` sound: the\n * runtime wraps DB-assigned-key creates in `adapter.transaction` and issues\n * `SELECT LAST_INSERT_ID() AS id` via `executeUnsafe`, and LAST_INSERT_ID() is\n * per-connection state in MySQL — on any other connection it would answer for\n * someone else's INSERT.\n *\n * Driver configuration is pinned to the runtime's MYSQL_CODECS contract\n * (packages/runtime/src/codecs.ts) — see {@link MysqlPoolConfig}.\n */\n\nimport type {\n AdapterBudgetSupport,\n DatabaseAdapter,\n QueryResult,\n RowChangeCount,\n StatementEffect,\n TransactionOptions,\n WireFidelity,\n} from \"@vibeorm/runtime\";\nimport {\n runPinnedSession,\n observeRowChanges,\n readRowChanges,\n statementRowChanges,\n createSavepointScope,\n isTransactionDeadlineError,\n isSavepointRollbackFailedError,\n runNestedSavepoint,\n runRootScope,\n type SavepointScope,\n scopeTurn,\n startTransactionBudget,\n type TransactionBudget,\n transactionOutcomeUnknownError,\n validateTransactionDeadline,\n} from \"@vibeorm/runtime/adapter-kit\";\nimport type { Dialect, Provider } from \"@vibeorm/schema\";\nimport { internalError, VibeError } from \"@vibeorm/schema\";\nimport { createPool as mysql2CreatePool } from \"mysql2/promise\";\nimport { MYSQL_DEFAULT_CONNECTION_LIMIT, acquireWithTimeout } from \"./acquire.ts\";\nimport { mysqlPoolConfig, type MysqlTypeCast } from \"./config.ts\";\nimport { mapMysqlDriverError, runMapped } from \"./errors.ts\";\nimport { bindRowCountParams } from \"./placeholders.ts\";\nimport { isResultSetHeader, normalizeDriverResult } from \"./results.ts\";\nimport {\n RESET_MAX_EXECUTION_TIME_SQL,\n classifyRawTransactionControl,\n maxExecutionTimeStatement,\n refuseNestedTransactionOptions,\n setIsolationLevelStatement,\n} from \"./transaction-sql.ts\";\n\n// ─── Minimal mysql2 surface ───────────────────────────────────────\n\n/** The parts of a mysql2 `PoolConnection` this adapter uses. */\nexport type MysqlConnectionLike = {\n /** Binary protocol — prepared statements, cached per connection by mysql2. */\n execute(text: string, values?: unknown[]): Promise<[unknown, unknown]>;\n /** Text protocol — raw path and transaction-control statements. */\n query(text: string, values?: unknown[]): Promise<[unknown, unknown]>;\n beginTransaction(): Promise<void>;\n commit(): Promise<void>;\n rollback(): Promise<void>;\n ping(): Promise<void>;\n release(): void;\n destroy(): void;\n};\n\n/** The parts of a mysql2 promise `Pool` this adapter uses. */\nexport type MysqlPoolLike = {\n execute(text: string, values?: unknown[]): Promise<[unknown, unknown]>;\n query(text: string, values?: unknown[]): Promise<[unknown, unknown]>;\n getConnection(): Promise<MysqlConnectionLike>;\n end(): Promise<void>;\n};\n\n/** Anything that can run a statement: the pool itself or a pinned connection. */\ntype Queryable = Pick<MysqlConnectionLike, \"execute\" | \"query\">;\n\n// ─── Pool config ──────────────────────────────────────────────────\n\n/**\n * The exact configuration this adapter hands to `mysql2.createPool`. The\n * literal-typed fields are pinned to the runtime's MYSQL_CODECS contract and\n * are not user-overridable:\n *\n * - `decimalNumbers: false` — DECIMAL comes back as a string; the Decimal\n * codec keeps it a string (no float rounding) and trims the fixed-scale\n * padding MySQL reports (`DECIMAL(65, 30)` → `\"42.420…00\"` → `\"42.42\"`).\n * - `supportBigNumbers: true` + `bigNumberStrings: true` — BIGINT (and\n * DECIMAL) always come back as strings, never a precision-lossy JS number;\n * the BigInt codec decodes strings exactly.\n * - `dateStrings: false` — DATETIME comes back as a JS `Date`; the DateTime\n * codec passes `Date` through in both directions.\n * - `jsonStrings: false` + JSON-specific `typeCast` — parsed JSON with ordinary\n * JSON.parse number semantics, independent of BIGINT string decoding.\n * - `namedPlaceholders: false` — the mysql dialect renders positional `?`.\n * - `multipleStatements` defaults to false: the ORM never batches, and\n * @vibeorm/migrate's mysql runner applies DDL per-statement anyway (DDL\n * auto-commits, so per-statement progress tracking needs it).\n */\nexport type MysqlPoolConfig = {\n readonly uri?: string;\n readonly host?: string;\n readonly port?: number;\n readonly user?: string;\n readonly password?: string;\n readonly database?: string;\n readonly connectionLimit?: number;\n readonly charset?: string;\n readonly timezone: string;\n readonly decimalNumbers: false;\n readonly supportBigNumbers: true;\n readonly bigNumberStrings: true;\n readonly dateStrings: false;\n readonly jsonStrings: false;\n readonly namedPlaceholders: false;\n readonly rowsAsArray: false;\n readonly nestTables: undefined;\n readonly typeCast: MysqlTypeCast;\n readonly flags: string[];\n readonly multipleStatements: boolean;\n};\n\n// ─── Options ──────────────────────────────────────────────────────\n\n/**\n * Options for {@link mysqlAdapter}. Point it at a connection URL **or** at\n * discrete `host`/`port`/`user`/`password`/`database` fields (mysql2 accepts\n * both; when both are given the discrete fields win — the adapter parses the\n * URL once before overlaying explicit config), or hand it a pool you already own.\n */\nexport type MysqlAdapterOptions = {\n /** MySQL connection URL (`mysql://user:pw@host:3306/db`). Defaults to `process.env.MYSQL_URL`. */\n readonly url?: string;\n readonly host?: string;\n readonly port?: number;\n readonly user?: string;\n readonly password?: string;\n readonly database?: string;\n /**\n * An existing mysql2 promise pool to use instead of creating one. The\n * adapter never ends a pool it did not create, so `disconnect()` is a no-op\n * in this mode. The pool MUST be configured to the codec contract\n * ({@link MysqlPoolConfig}) — the adapter cannot verify it.\n */\n readonly pool?: MysqlPoolLike;\n /** Maximum pooled connections (mysql2 default 10). Ignored when `pool` is given. */\n readonly connectionLimit?: number;\n /**\n * mysql2 `timezone`, default `\"Z\"`: the codec table stores DateTime as UTC\n * in `DATETIME(3)` columns, and DATETIME has no zone of its own — with\n * `\"Z\"` mysql2 serializes outgoing `Date`s as UTC and parses incoming\n * DATETIME text as UTC, so the instant round-trips regardless of the server\n * or process time zone. mysql2's own default (`\"local\"`) would silently\n * shift values by the process offset.\n */\n readonly timezone?: string;\n /** Connection charset/collation (mysql2 default `utf8mb4_general_ci`). */\n readonly charset?: string;\n /**\n * Milliseconds to wait for a pool connection before refusing with a\n * `VibeError` (`VIBE_ADAPTER`, `meta.reason: \"acquire-timeout\"`).\n *\n * **Unset (the default) keeps mysql2's own behaviour**: the pool is created\n * with `waitForConnections: true` and no time bound, so a caller whose\n * connections are all busy QUEUES until one frees. Setting this bounds EVERY\n * pool checkout the adapter makes — the caller gets a coded refusal instead\n * of an unbounded wait.\n *\n * Adapter-owned: mysql2 has no acquire timeout at all (its pool knobs are\n * `waitForConnections` and `queueLimit`, which bounds queue DEPTH, not time),\n * so this value is never passed to `mysql2.createPool`.\n *\n * **Not mysql2's `connectTimeout`**, which is the deadline for establishing a\n * NEW connection rather than for waiting on a busy pool. The equivalent\n * option on `@vibeorm/adapter-pg` is `connectionTimeout`; the name differs\n * here precisely because mysql2 already uses that word for something else.\n */\n readonly acquireTimeout?: number;\n /**\n * Allow multiple statements per `executeUnsafe` call (default false). Leave\n * it off: the ORM never batches, @vibeorm/migrate applies DDL per statement,\n * and enabling it widens the SQL-injection blast radius of raw queries.\n */\n readonly multipleStatements?: boolean;\n /**\n * Pool factory — a test seam. Defaults to `mysql2/promise`'s `createPool`;\n * tests inject a recording fake here to assert the exact config the adapter\n * builds. Ignored when `pool` is given.\n */\n readonly createPool?: (config: MysqlPoolConfig) => MysqlPoolLike;\n};\n\n// ─── Adapter ──────────────────────────────────────────────────────\n\nconst DIALECT: Dialect = \"mysql\";\nconst PROVIDER: Provider = \"mysql\";\n\n/**\n * mysql2 wire (board #30, live-verified on both execute paths, 8.4):\n * datetime(3) → `Date` (under the adapter's pinned `timezone: \"Z\"`), JSON →\n * parsed values, int/double → numbers. (BIGINT arrives as a string and\n * TINYINT(1) as 0/1 — BigInt/Boolean decoding stays.)\n */\nconst WIRE: WireFidelity = Object.freeze({ dateTime: \"native\", json: \"parsed\", numbers: \"native\" } as const);\n\n/**\n * Timing budgets this adapter genuinely enforces (EPIC 6).\n *\n * - `acquireTimeout: true` — {@link MysqlAdapterOptions.acquireTimeout} bounds\n * the checkout wait (mysql2 itself has none; ./acquire.ts explains why).\n * Declared as a capability; it is OFF until the option is set.\n * - `statementTimeout: \"select-only\"` — **MySQL's `MAX_EXECUTION_TIME` bounds\n * SELECT statements only.** INSERT/UPDATE/DELETE/DDL run unbounded, so this\n * is NOT general write cancellation and is not declared as one.\n * - `transactionDeadline: \"between-statements\"` — the budget is honoured before\n * each statement and at the commit. `\"cancel-running-statements\"` is REFUSED:\n * an in-flight write cannot be stopped through this connection, and killing\n * it from a second pooled connection would risk cancelling a session that had\n * already moved on.\n */\nconst BUDGETS: AdapterBudgetSupport = Object.freeze({\n acquireTimeout: true,\n statementTimeout: \"select-only\",\n transactionDeadline: \"between-statements\",\n} as const);\n\nfunction defaultCreatePool(config: MysqlPoolConfig): MysqlPoolLike {\n // Single cast seam: mysql2's Pool satisfies MysqlPoolLike structurally, but\n // its generic overloads don't reduce to our plain signatures.\n return mysql2CreatePool(config as Parameters<typeof mysql2CreatePool>[0]) as unknown as MysqlPoolLike;\n}\n\n/** A failed finalization reply cannot establish whether the transaction committed. */\nfunction finalizationOutcomeUnknown(params: { cause: unknown; stage: \"commit\" | \"raw-close\" }): VibeError {\n return new VibeError({\n code: \"VIBE_TRANSACTION\",\n message: \"MySQL transaction finalization failed; its outcome is unknown. The connection was discarded. Inspect the data before retrying.\",\n meta: { provider: PROVIDER, reason: \"transaction-outcome-unknown\", outcome: \"unknown\", stage: params.stage },\n cause: params.cause,\n });\n}\n\n/** Scalar-array params must never reach this adapter — the dialect expands IN. */\nfunction throwOnArrayParam(values: unknown[]): never {\n throw internalError({\n message:\n \"formatArrayParam called on the mysql adapter — the mysql dialect expands scalar-list parameters into IN (?, ?, …) placeholders, so the runtime should have expanded this array before binding\",\n meta: { length: values.length },\n });\n}\n\n/**\n * Create a VibeORM adapter backed by mysql2.\n *\n * @example\n * ```ts\n * const adapter = mysqlAdapter({ url: process.env.MYSQL_URL, connectionLimit: 20 });\n * await adapter.connect();\n * const rows = await adapter.execute({ text: \"SELECT * FROM `User` WHERE `id` = ?\", values: [1] });\n * ```\n *\n * @example Discrete fields, or reusing a pool you already own\n * ```ts\n * const adapter = mysqlAdapter({ host: \"127.0.0.1\", port: 3306, user: \"app\", password: \"pw\", database: \"app\" });\n * const shared = mysqlAdapter({ pool: existingPool });\n * ```\n *\n * ORM path (`execute`) uses mysql2's binary protocol (`pool.execute`), which\n * prepares statements and caches them per connection keyed by statement text\n * (mysql2's `maxPreparedStatements` LRU, default 16000). Raw path\n * (`executeUnsafe`) uses the text protocol (`pool.query`) when parameterless;\n * nonempty values always use prepared binding, with the same raw-session pin.\n *\n * Parameters arrive PRE-ENCODED by the runtime codec table: Json is already a\n * string, DateTime is a `Date` (mysql2 serializes it per `timezone`), BigInt\n * is a string. The adapter forwards values verbatim — no second conversion.\n */\nexport function mysqlAdapter(options?: MysqlAdapterOptions): DatabaseAdapter {\n let pool: MysqlPoolLike | null = null;\n let ownsPool = false;\n\n /**\n * The pinned connection of an OPEN raw transaction — session affinity for\n * the raw path. A raw `BEGIN` … `COMMIT` sequence over `executeUnsafe` is\n * sound only when every statement in between rides the SAME pooled\n * connection, so a pure `BEGIN` checks one out, raw statements ride it, and\n * the matching `COMMIT`/`ROLLBACK` releases it (same semantics as the pg and\n * bun adapters). The ORM path (`execute`) and `transaction()` stay on the\n * pool. Concurrent raw transactions on one adapter are unsupported.\n */\n let rawSession: MysqlConnectionLike | null = null;\n\n const acquireTimeoutMs = options?.acquireTimeout;\n\n /**\n * Effective pool size for the refusal message. Unknown — and reported as\n * such — when the caller supplied the pool, since `connectionLimit` is\n * ignored in that mode.\n */\n const poolSize: number | undefined =\n options?.pool === undefined ? (options?.connectionLimit ?? MYSQL_DEFAULT_CONNECTION_LIMIT) : undefined;\n\n function getPool(): MysqlPoolLike {\n if (pool !== null) return pool;\n\n if (options?.pool !== undefined) {\n pool = options.pool;\n ownsPool = false;\n return pool;\n }\n\n const config = mysqlPoolConfig({ options });\n pool = (options?.createPool ?? defaultCreatePool)(config);\n ownsPool = true;\n return pool;\n }\n\n /**\n * The ONE place a connection is checked out. Without `acquireTimeout` this is\n * mysql2's own unbounded checkout, byte for byte; with it, the wait is\n * bounded and a caller that cannot be served refuses instead of queueing.\n * `runMapped` maps driver failures — the timeout error is already a\n * `VibeError` and passes through untouched (errors.ts:121).\n */\n async function acquireConnection(): Promise<MysqlConnectionLike> {\n const active = getPool();\n if (acquireTimeoutMs === undefined) {\n return runMapped(() => active.getConnection());\n }\n return runMapped(() => acquireWithTimeout({ pool: active, timeoutMs: acquireTimeoutMs, poolSize }));\n }\n\n /** A failed raw script can retain earlier statements without returning their headers. */\n function observeUnclassifiedDispatch(params: { scope?: SavepointScope; effect?: StatementEffect }): void {\n if (params.scope !== undefined && params.effect !== \"read\" && params.effect !== \"write\") {\n observeRowChanges({ scope: params.scope, count: \"unknown\" });\n }\n }\n\n function observeResult(params: { scope?: SavepointScope; effect?: StatementEffect; result: unknown }): void {\n if (params.scope === undefined) return;\n const count = isResultSetHeader({ value: params.result }) ? (params.result as { affectedRows: number }).affectedRows : undefined;\n observeRowChanges({ scope: params.scope, count: statementRowChanges({ effect: params.effect, count }) });\n }\n\n async function runExecute(params: {\n queryable: Queryable;\n text: string;\n values: unknown[];\n scope?: SavepointScope;\n effect?: StatementEffect;\n }): Promise<Record<string, unknown>[]> {\n observeUnclassifiedDispatch(params);\n const [result, fields] = await runMapped(() => params.queryable.execute(params.text, params.values));\n observeResult({ scope: params.scope, effect: params.effect, result });\n return normalizeDriverResult({ result, fields }).rows;\n }\n\n /**\n * The ORM's affected-row path (F01). Same PREPARED protocol as `execute()` —\n * mysql2 sends the statement and its parameters separately — but keeping the\n * OK-packet's `affectedRows` instead of dropping it.\n *\n * Never `query()`: that is the TEXT protocol, which interpolates values into\n * the SQL client-side. mysql2 cannot know the server's `sql_mode`, so under\n * `NO_BACKSLASH_ESCAPES` its `\\'` is not an escape and a hostile string\n * predicate breaks out of its literal — a `deleteMany` deleted rows a bound\n * read did not match. There is deliberately NO fallback from a failed\n * preparation to interpolation: an unpreparable statement fails loudly.\n *\n * RAW STATEMENTS RIDE THIS PATH TOO, so `bindRowCountParams` first rewrites\n * integers sitting in a `LIMIT` / `OFFSET` position into their decimal text:\n * mysql2's prepared protocol types a JS number in a way the server refuses\n * there (errno 1210), and only user-written raw SQL can produce that shape —\n * the ORM inlines its limits as literal text. Nothing else is touched.\n */\n async function runExecuteAffected(params: {\n queryable: Queryable;\n text: string;\n values: unknown[];\n scope?: SavepointScope;\n effect?: StatementEffect;\n }): Promise<QueryResult> {\n const values = bindRowCountParams({ text: params.text, values: params.values });\n observeUnclassifiedDispatch(params);\n const [result, fields] = await runMapped(() => params.queryable.execute(params.text, values));\n observeResult({ scope: params.scope, effect: params.effect, result });\n return normalizeDriverResult({ result, fields });\n }\n\n async function runExecuteUnsafe(params: {\n queryable: Queryable;\n text: string;\n values?: unknown[];\n scope?: SavepointScope;\n effect?: StatementEffect;\n }): Promise<QueryResult> {\n if (params.values !== undefined && params.values.length > 0) {\n return runExecuteAffected({ ...params, values: params.values });\n }\n observeUnclassifiedDispatch(params);\n const [result, fields] = await runMapped(() => params.queryable.query(params.text, params.values));\n observeResult({ scope: params.scope, effect: params.effect, result });\n return normalizeDriverResult({ result, fields });\n }\n\n /**\n * Adapter bound to the ONE pinned connection of an open transaction — the\n * same-connection guarantee. Nested `transaction()` calls open savepoints on\n * that connection, and their LIFETIMES are serialized by the savepoint gate\n * (F14): overlapping siblings share one savepoint stack, so the earlier\n * one's rollback would erase the later one's already released work.\n */\n function createConnectionAdapter(params: {\n conn: MysqlConnectionLike;\n scope: SavepointScope;\n budget: TransactionBudget;\n }): DatabaseAdapter {\n const { conn, scope, budget } = params;\n\n function invalidate(error: unknown): never {\n // Driver calls already map errors. A nested callback's own error must\n // retain its identity rather than being relabelled as a driver failure.\n if (!(error instanceof VibeError)) throw error;\n const mapped = error;\n if (mapped.meta.errno === 1213) {\n // InnoDB has rolled back the whole transaction, not just this statement.\n // Keep this terminal for every handle even when the callback catches it.\n scope.state.poisoned = new VibeError({\n code: mapped.code, message: mapped.message,\n meta: { ...mapped.meta, outcome: \"rolled-back\" }, cause: mapped,\n });\n }\n if (isSavepointRollbackFailedError(mapped)) budget.close({ outcome: \"unknown\" });\n throw mapped;\n }\n\n return {\n dialect: DIALECT,\n provider: PROVIDER,\n wire: WIRE,\n budgets: BUDGETS,\n rowChanges: (): RowChangeCount => { budget.assertUsable({ stage: \"statement\" }); return readRowChanges({ scope }); },\n\n async execute(execParams) {\n const turn = scopeTurn({ scope });\n if (turn !== undefined) await turn;\n // After the turn, not before: waiting for a sibling savepoint spends\n // the same budget the statement is about to run against.\n budget.assertUsable({ stage: \"statement\" });\n return runExecute({ queryable: conn, scope, ...execParams }).catch(invalidate);\n },\n\n async executeRawBound(execParams) {\n return this.executeUnsafe(execParams);\n },\n\n async executeUnsafe(execParams) {\n const turn = scopeTurn({ scope });\n if (turn !== undefined) await turn;\n budget.assertUsable({ stage: \"statement\" });\n return runExecuteUnsafe({ queryable: conn, scope, ...execParams }).catch(invalidate);\n },\n\n async executeAffected(execParams) {\n const turn = scopeTurn({ scope });\n if (turn !== undefined) await turn;\n budget.assertUsable({ stage: \"statement\" });\n return runExecuteAffected({ queryable: conn, scope, ...execParams }).catch(invalidate);\n },\n\n async transaction<T>(\n fn: (txAdapter: DatabaseAdapter) => Promise<T>,\n nestedOptions?: TransactionOptions,\n ): Promise<T> {\n refuseNestedTransactionOptions({ options: nestedOptions, provider: PROVIDER });\n budget.assertUsable({ stage: \"nested\" });\n return runNestedSavepoint({\n scope,\n execute: (statement) => runMapped(() => conn.query(statement)).catch(invalidate),\n // The child shares the ROOT budget by reference: a savepoint never\n // gets an independent clock or session setting.\n body: (child) => fn(createConnectionAdapter({ conn, scope: child, budget })),\n }).catch(invalidate);\n },\n\n async connect(): Promise<void> {\n // Already connected — this adapter is bound to a pinned connection.\n },\n\n async disconnect(): Promise<void> {\n // The pool owns the connection lifecycle; releasing happens at the\n // top-level transaction boundary.\n },\n\n formatArrayParam(values: unknown[]): unknown {\n return throwOnArrayParam(values);\n },\n };\n }\n\n return {\n dialect: DIALECT,\n provider: PROVIDER,\n wire: WIRE,\n budgets: BUDGETS,\n\n async withSession({ run }) {\n const conn = await acquireConnection();\n return runPinnedSession({\n run,\n execute: async (query) => (await runExecuteUnsafe({ queryable: conn, ...query })).rows,\n isLost: (error) => error instanceof VibeError && (\n typeof error.meta.errno !== \"number\" || [2006, 2013, 2055, 4031].includes(error.meta.errno)\n ),\n // Discard session settings and any open transaction, even on success.\n release: async () => { conn.destroy(); },\n });\n },\n\n async execute(params) {\n // Default path: mysql2's `pool.execute` does its own implicit checkout.\n // With `acquireTimeout` set that checkout has to be visible to be\n // bounded, so the statement is routed over an explicit connection\n // instead (mysql2 caches prepared statements per connection either way).\n if (acquireTimeoutMs === undefined) {\n return runExecute({ queryable: getPool(), ...params });\n }\n const conn = await acquireConnection();\n try {\n return await runExecute({ queryable: conn, ...params });\n } finally {\n conn.release();\n }\n },\n\n async executeAffected(params) {\n // Same checkout rules as `execute()` above: implicit with mysql2's own\n // pool, explicit (and therefore boundable) when `acquireTimeout` is set.\n if (acquireTimeoutMs === undefined) {\n return runExecuteAffected({ queryable: getPool(), ...params });\n }\n const conn = await acquireConnection();\n try {\n return await runExecuteAffected({ queryable: conn, ...params });\n } finally {\n conn.release();\n }\n },\n\n async executeRawBound(params) {\n return this.executeUnsafe(params);\n },\n\n async executeUnsafe(params) {\n const control = classifyRawTransactionControl({ text: params.text });\n if (rawSession !== null) {\n if (control === \"close\") {\n const session = rawSession;\n rawSession = null;\n try {\n const result = await runExecuteUnsafe({ queryable: session, ...params });\n session.release();\n return result;\n } catch (cause) {\n session.destroy();\n throw finalizationOutcomeUnknown({ cause, stage: \"raw-close\" });\n }\n }\n return runExecuteUnsafe({ queryable: rawSession, ...params });\n }\n if (control === \"open\") {\n const conn = await acquireConnection();\n try {\n const result = await runExecuteUnsafe({ queryable: conn, ...params });\n rawSession = conn;\n return result;\n } catch (error) {\n conn.release();\n throw error;\n }\n }\n // Default path: mysql2's `pool.query` checks a connection out\n // implicitly. Same reroute as `execute()` above, for the same reason —\n // a checkout has to be visible to be bounded, so with `acquireTimeout`\n // set the raw statement runs on an explicit connection too.\n if (acquireTimeoutMs === undefined) {\n return runExecuteUnsafe({ queryable: getPool(), ...params });\n }\n const conn = await acquireConnection();\n try {\n return await runExecuteUnsafe({ queryable: conn, ...params });\n } finally {\n conn.release();\n }\n },\n\n async transaction<T>(\n fn: (txAdapter: DatabaseAdapter) => Promise<T>,\n transactionOptions?: TransactionOptions,\n ): Promise<T> {\n // Validate the timeout before taking a connection, so a bad option fails\n // fast instead of wasting a checkout.\n const timeoutText =\n transactionOptions?.timeout === undefined\n ? undefined\n : maxExecutionTimeStatement({ timeout: transactionOptions.timeout });\n // Same rule for the deadline: an unsupportable budget is refused before a\n // connection is taken, so it never costs a checkout.\n validateTransactionDeadline({\n options: transactionOptions,\n support: BUDGETS.transactionDeadline,\n provider: PROVIDER,\n });\n\n const conn = await acquireConnection();\n /** Set when the session state can no longer be asserted (see below). */\n let rollbackFailed = false;\n // The deadline clock starts with the connection already in hand:\n // acquisition has its own budget (`acquireTimeout`) and is not charged here.\n const budget = startTransactionBudget({ options: transactionOptions, provider: PROVIDER });\n try {\n // Session-scoped SELECT bound — see transaction-sql.ts for the loud\n // \"SELECT statements only\" caveat. Reset in finally below.\n if (timeoutText !== undefined) {\n await runMapped(() => conn.query(timeoutText));\n }\n // Applies to the NEXT transaction in the session → must precede begin.\n const isolationLevel = transactionOptions?.isolationLevel;\n if (isolationLevel !== undefined) {\n const isolationText = setIsolationLevelStatement({ isolationLevel });\n await runMapped(() => conn.query(isolationText));\n }\n await runMapped(() => conn.beginTransaction());\n const scope = createSavepointScope();\n try {\n const result = await runRootScope({\n scope,\n body: () => fn(createConnectionAdapter({ conn, scope, budget })),\n });\n // The callback may have caught a driver error that invalidated the\n // whole transaction. Check the shared scope as well as the deadline.\n const turn = scopeTurn({ scope });\n if (turn !== undefined) await turn;\n budget.assertUsable({ stage: \"commit\" });\n await runMapped(() => conn.commit()).catch((cause: unknown) => {\n // A later successful ROLLBACK does not disprove a committed write\n // whose acknowledgement was lost. Close unknown before cleanup.\n budget.close({ outcome: \"unknown\" });\n rollbackFailed = true;\n throw finalizationOutcomeUnknown({ cause, stage: \"commit\" });\n });\n budget.close({ outcome: \"committed\" });\n return result;\n } catch (error) {\n if (isSavepointRollbackFailedError(error) || budget.outcome === \"unknown\") {\n budget.close({ outcome: \"unknown\" });\n rollbackFailed = true;\n }\n // Best effort: never mask the original failure with a rollback failure.\n try {\n await conn.rollback();\n budget.close({ outcome: \"rolled-back\" });\n } catch {\n // The rollback that should have cleaned up failed: the commit state\n // is genuinely unknown and the connection is destroyed below rather\n // than pooled while it may still be inside a transaction.\n rollbackFailed = true;\n budget.close({ outcome: \"unknown\" });\n if (budget.totalMs !== null && isTransactionDeadlineError(error)) {\n throw transactionOutcomeUnknownError({\n provider: PROVIDER,\n totalMs: budget.totalMs,\n cause: error,\n });\n }\n }\n throw error;\n }\n } finally {\n let poisoned = rollbackFailed;\n if (timeoutText !== undefined && !poisoned) {\n try {\n await conn.query(RESET_MAX_EXECUTION_TIME_SQL);\n } catch {\n poisoned = true;\n }\n }\n // A connection whose session default could not be restored — or whose\n // rollback failed, so it may still be inside a transaction — must never\n // return to the pool.\n if (poisoned) {\n conn.destroy();\n } else {\n conn.release();\n }\n }\n },\n\n async connect(): Promise<void> {\n const conn = await acquireConnection();\n try {\n await runMapped(() => conn.ping());\n } finally {\n conn.release();\n }\n },\n\n async disconnect(): Promise<void> {\n if (rawSession !== null) {\n // An abandoned raw transaction must not leak an in-transaction\n // connection; roll it back best-effort before the pool ends.\n const session = rawSession;\n rawSession = null;\n try {\n await session.query(\"ROLLBACK\");\n } catch {\n /* the pool is closing; the session is going away regardless */\n }\n session.release();\n }\n if (pool !== null && ownsPool) {\n const closing = pool;\n pool = null;\n await runMapped(() => closing.end());\n }\n },\n\n formatArrayParam(values: unknown[]): unknown {\n return throwOnArrayParam(values);\n },\n };\n}\n\n// ─── Re-exports (driver-error table, helpers) ─────────────────────\n\nexport {\n DEFAULT_ACQUIRE_TIMERS,\n MYSQL_DEFAULT_CONNECTION_LIMIT,\n acquireTimeoutError,\n acquireWithTimeout,\n} from \"./acquire.ts\";\nexport type { AcquireSource, AcquireTimers, ReleasableConnection, TimerHandle } from \"./acquire.ts\";\nexport {\n MYSQL_ERRNO_ERROR_CODES,\n MYSQL_ERRNO_REASONS,\n mapMysqlDriverError,\n mysqlErrorErrno,\n runMapped,\n} from \"./errors.ts\";\nexport { isResultSetHeader, normalizeDriverResult } from \"./results.ts\";\nexport { createSavepointCounter, nextSavepointName } from \"@vibeorm/runtime/adapter-kit\";\nexport type { SavepointCounter } from \"@vibeorm/runtime/adapter-kit\";\nexport {\n ISOLATION_LEVEL_SQL,\n RESET_MAX_EXECUTION_TIME_SQL,\n classifyRawTransactionControl,\n maxExecutionTimeStatement,\n refuseNestedTransactionOptions,\n setIsolationLevelStatement,\n} from \"./transaction-sql.ts\";\nexport type { RawTransactionControl } from \"./transaction-sql.ts\";\n// ─── EPIC 6: transaction budgets (shared, @vibeorm/runtime/adapter-kit) ───\nexport {\n DEFAULT_DEADLINE_CLOCK,\n engineStatementBudgetMs,\n isTransactionDeadlineError,\n startTransactionBudget,\n transactionClosedError,\n transactionDeadlineError,\n transactionOutcomeUnknownError,\n validateTransactionDeadline,\n} from \"@vibeorm/runtime/adapter-kit\";\nexport type { BudgetStage, DeadlineClock, TransactionBudget, TransactionOutcome } from \"@vibeorm/runtime/adapter-kit\";\n",
|
|
5
|
+
"/**\n * @vibeorm/adapter-mysql — mysql2 adapter for VibeORM v2.\n *\n * Runs on Bun and Node over `mysql2/promise`. Owns pooling, transactions\n * (nested → savepoints on the same pinned connection) and driver-error\n * mapping. Only `VibeError` ever escapes.\n *\n * SAME-CONNECTION GUARANTEE (board #7): `transaction()` checks ONE connection\n * out of the pool and every operation on the callback's adapter — `execute`,\n * `executeUnsafe`, nested `transaction` — runs on that same connection until\n * commit/rollback. That pinning is what makes `LAST_INSERT_ID()` sound: the\n * runtime wraps DB-assigned-key creates in `adapter.transaction` and issues\n * `SELECT LAST_INSERT_ID() AS id` via `executeUnsafe`, and LAST_INSERT_ID() is\n * per-connection state in MySQL — on any other connection it would answer for\n * someone else's INSERT.\n *\n * Driver configuration is pinned to the runtime's MYSQL_CODECS contract\n * (packages/runtime/src/codecs.ts) — see {@link MysqlPoolConfig}.\n */\n\nimport type {\n AdapterBudgetSupport,\n DatabaseAdapter,\n QueryResult,\n RowChangeCount,\n StatementEffect,\n TransactionOptions,\n WireFidelity,\n} from \"@vibeorm/runtime\";\nimport {\n createAdapterLifecycleGate,\n runPinnedSession,\n runShutdownCleanup,\n transactionLifecycleRefusal,\n observeRowChanges,\n readRowChanges,\n statementRowChanges,\n closeFailedTransactionBudget,\n type CommitProgress,\n type ConnectionOutcome,\n createSavepointScope,\n isSavepointRollbackFailedError,\n type RollbackOutcome,\n runNestedSavepoint,\n runRootScope,\n type SavepointScope,\n scopeTurn,\n settleFailedTransaction,\n startTransactionBudget,\n type TransactionBudget,\n validateTransactionDeadline,\n readOnlyRequested,\n} from \"@vibeorm/runtime/adapter-kit\";\nimport type { Dialect, Provider } from \"@vibeorm/schema\";\nimport { internalError, VibeError } from \"@vibeorm/schema\";\nimport { createPool as mysql2CreatePool } from \"mysql2/promise\";\nimport { MYSQL_DEFAULT_CONNECTION_LIMIT, acquireWithTimeout } from \"./acquire.ts\";\nimport { mysqlPoolConfig, type MysqlTypeCast } from \"./config.ts\";\nimport { MYSQL_ROLLED_BACK_ERRNOS, mapMysqlDriverError, runMapped } from \"./errors.ts\";\nimport { bindRowCountParams } from \"./placeholders.ts\";\nimport { isResultSetHeader, normalizeDriverResult } from \"./results.ts\";\nimport {\n RESET_MAX_EXECUTION_TIME_SQL,\n START_TRANSACTION_READ_ONLY_SQL,\n classifyRawTransactionControl,\n maxExecutionTimeStatement,\n refuseNestedTransactionOptions,\n sessionOptionsStatement,\n setIsolationLevelStatement,\n} from \"./transaction-sql.ts\";\n\n// ─── Minimal mysql2 surface ───────────────────────────────────────\n\n/** The parts of a mysql2 `PoolConnection` this adapter uses. */\nexport type MysqlConnectionLike = {\n /** Binary protocol — prepared statements, cached per connection by mysql2. */\n execute(text: string, values?: unknown[]): Promise<[unknown, unknown]>;\n /** Text protocol — raw path and transaction-control statements. */\n query(text: string, values?: unknown[]): Promise<[unknown, unknown]>;\n beginTransaction(): Promise<void>;\n commit(): Promise<void>;\n rollback(): Promise<void>;\n ping(): Promise<void>;\n release(): void;\n destroy(): void;\n /**\n * mysql2's connection events. Optional, so injected doubles without them\n * stay valid. A transaction listens for `error` and `end`: once either fired,\n * mysql2 refuses every later command on that connection locally, so a\n * COMMIT after it never leaves the client (EPIC T).\n */\n on?(event: \"error\" | \"end\", listener: (error?: unknown) => void): unknown;\n removeListener?(event: \"error\" | \"end\", listener: (error?: unknown) => void): unknown;\n};\n\n/** The parts of a mysql2 promise `Pool` this adapter uses. */\nexport type MysqlPoolLike = {\n execute(text: string, values?: unknown[]): Promise<[unknown, unknown]>;\n query(text: string, values?: unknown[]): Promise<[unknown, unknown]>;\n getConnection(): Promise<MysqlConnectionLike>;\n end(): Promise<void>;\n};\n\n/** Anything that can run a statement: the pool itself or a pinned connection. */\ntype Queryable = Pick<MysqlConnectionLike, \"execute\" | \"query\">;\n\n// ─── Pool config ──────────────────────────────────────────────────\n\n/**\n * The exact configuration this adapter hands to `mysql2.createPool`. The\n * literal-typed fields are pinned to the runtime's MYSQL_CODECS contract and\n * are not user-overridable:\n *\n * - `decimalNumbers: false` — DECIMAL comes back as a string; the Decimal\n * codec keeps it a string (no float rounding) and trims the fixed-scale\n * padding MySQL reports (`DECIMAL(65, 30)` → `\"42.420…00\"` → `\"42.42\"`).\n * - `supportBigNumbers: true` + `bigNumberStrings: true` — BIGINT (and\n * DECIMAL) always come back as strings, never a precision-lossy JS number;\n * the BigInt codec decodes strings exactly.\n * - `dateStrings: false` — DATETIME comes back as a JS `Date`; the DateTime\n * codec passes `Date` through in both directions.\n * - `jsonStrings: false` + JSON-specific `typeCast` — parsed JSON with ordinary\n * JSON.parse number semantics, independent of BIGINT string decoding.\n * - `namedPlaceholders: false` — the mysql dialect renders positional `?`.\n * - `multipleStatements` defaults to false: the ORM never batches, and\n * @vibeorm/migrate's mysql runner applies DDL per-statement anyway (DDL\n * auto-commits, so per-statement progress tracking needs it).\n */\nexport type MysqlPoolConfig = {\n readonly uri?: string;\n readonly host?: string;\n readonly port?: number;\n readonly user?: string;\n readonly password?: string;\n readonly database?: string;\n readonly connectionLimit?: number;\n readonly charset?: string;\n readonly timezone: string;\n readonly decimalNumbers: false;\n readonly supportBigNumbers: true;\n readonly bigNumberStrings: true;\n readonly dateStrings: false;\n readonly jsonStrings: false;\n readonly namedPlaceholders: false;\n readonly rowsAsArray: false;\n readonly nestTables: undefined;\n readonly typeCast: MysqlTypeCast;\n readonly flags: string[];\n readonly multipleStatements: boolean;\n};\n\n// ─── Options ──────────────────────────────────────────────────────\n\n/**\n * Every {@link mysqlAdapter} option. {@link MysqlAdapterOptions} adds the rule\n * that one of `url`, `host` and `pool` is present.\n */\nexport type MysqlAdapterSettings = {\n /**\n * MySQL connection URL (`mysql://user:pw@host:3306/db`). The adapter never\n * reads `MYSQL_URL` (or any other environment variable) itself.\n */\n readonly url?: string;\n /** Server host, the address of the discrete-field form. `database` may be omitted for a server-level connection. */\n readonly host?: string;\n readonly port?: number;\n readonly user?: string;\n readonly password?: string;\n readonly database?: string;\n /**\n * An existing mysql2 promise pool to use instead of creating one. The\n * adapter never ends a pool it did not create: `disconnect()` only ends this\n * adapter (and rolls back and releases its own raw session); the pool stays\n * usable. The pool MUST be configured to the codec contract\n * ({@link MysqlPoolConfig}) — the adapter cannot verify it.\n */\n readonly pool?: MysqlPoolLike;\n /** Maximum pooled connections (mysql2 default 10). Ignored when `pool` is given. */\n readonly connectionLimit?: number;\n /**\n * mysql2 `timezone`, default `\"Z\"`: the codec table stores DateTime as UTC\n * in `DATETIME(3)` columns, and DATETIME has no zone of its own — with\n * `\"Z\"` mysql2 serializes outgoing `Date`s as UTC and parses incoming\n * DATETIME text as UTC, so the instant round-trips regardless of the server\n * or process time zone. mysql2's own default (`\"local\"`) would silently\n * shift values by the process offset.\n */\n readonly timezone?: string;\n /** Connection charset/collation (mysql2 default `utf8mb4_general_ci`). */\n readonly charset?: string;\n /**\n * Milliseconds to wait for a pool connection before refusing with a\n * `VibeError` (`VIBE_ADAPTER`, `meta.reason: \"acquire-timeout\"`).\n *\n * **Unset (the default) keeps mysql2's own behaviour**: the pool is created\n * with `waitForConnections: true` and no time bound, so a caller whose\n * connections are all busy QUEUES until one frees. Setting this bounds EVERY\n * pool checkout the adapter makes — the caller gets a coded refusal instead\n * of an unbounded wait.\n *\n * Adapter-owned: mysql2 has no acquire timeout at all (its pool knobs are\n * `waitForConnections` and `queueLimit`, which bounds queue DEPTH, not time),\n * so this value is never passed to `mysql2.createPool`.\n *\n * **Not mysql2's `connectTimeout`**, which is the deadline for establishing a\n * NEW connection rather than for waiting on a busy pool. The equivalent\n * option on `@vibeorm/adapter-pg` is `connectionTimeout`; the name differs\n * here precisely because mysql2 already uses that word for something else.\n */\n readonly acquireTimeout?: number;\n /**\n * Allow multiple statements per `executeUnsafe` call (default false). Leave\n * it off: the ORM never batches, @vibeorm/migrate applies DDL per statement,\n * and enabling it widens the SQL-injection blast radius of raw queries.\n */\n readonly multipleStatements?: boolean;\n /**\n * Pool factory — a test seam. Defaults to `mysql2/promise`'s `createPool`;\n * tests inject a recording fake here to assert the exact config the adapter\n * builds. Ignored when `pool` is given.\n */\n readonly createPool?: (config: MysqlPoolConfig) => MysqlPoolLike;\n};\n\n/**\n * Options for {@link mysqlAdapter}: an explicit address is required. Point it\n * at a connection URL **or** at discrete `host`/`port`/`user`/`password`/\n * `database` fields (mysql2 accepts both; when both are given the discrete\n * fields win — the adapter parses the URL once before overlaying explicit\n * config), or hand it a pool you already own. Without any of the three, the\n * factory throws `VIBE_CONFIG` before any pool or connection exists.\n */\nexport type MysqlAdapterOptions = MysqlAdapterSettings &\n ({ readonly url: string } | { readonly host: string } | { readonly pool: MysqlPoolLike });\n\n// ─── Adapter ──────────────────────────────────────────────────────\n\nconst DIALECT: Dialect = \"mysql\";\nconst PROVIDER: Provider = \"mysql\";\n\n/**\n * mysql2 wire (board #30, live-verified on both execute paths, 8.4):\n * datetime(3) → `Date` (under the adapter's pinned `timezone: \"Z\"`), JSON →\n * parsed values, int/double → numbers. (BIGINT arrives as a string and\n * TINYINT(1) as 0/1 — BigInt/Boolean decoding stays.)\n */\nconst WIRE: WireFidelity = Object.freeze({ dateTime: \"native\", json: \"parsed\", numbers: \"native\" } as const);\n\n/**\n * A MySQL server: every round trip crosses a network (a local socket\n * included). The transaction facades carry the same declaration.\n */\nconst ROUND_TRIPS: NonNullable<DatabaseAdapter[\"roundTrips\"]> = \"network\";\n\n/**\n * Timing budgets this adapter genuinely enforces (EPIC 6).\n *\n * - `acquireTimeout: true` — {@link MysqlAdapterOptions.acquireTimeout} bounds\n * the checkout wait (mysql2 itself has none; ./acquire.ts explains why).\n * Declared as a capability; it is OFF until the option is set.\n * - `statementTimeout: \"select-only\"` — **MySQL's `MAX_EXECUTION_TIME` bounds\n * SELECT statements only.** INSERT/UPDATE/DELETE/DDL run unbounded, so this\n * is NOT general write cancellation and is not declared as one.\n * - `transactionDeadline: \"between-statements\"` — the budget is honoured before\n * each statement and at the commit. `\"cancel-running-statements\"` is REFUSED:\n * an in-flight write cannot be stopped through this connection, and killing\n * it from a second pooled connection would risk cancelling a session that had\n * already moved on.\n */\nconst BUDGETS: AdapterBudgetSupport = Object.freeze({\n acquireTimeout: true,\n statementTimeout: \"select-only\",\n transactionDeadline: \"between-statements\",\n accessModes: Object.freeze([\"readOnly\"] as const),\n} as const);\n\nfunction defaultCreatePool(config: MysqlPoolConfig): MysqlPoolLike {\n // Single cast seam: mysql2's Pool satisfies MysqlPoolLike structurally, but\n // its generic overloads don't reduce to our plain signatures.\n return mysql2CreatePool(config as Parameters<typeof mysql2CreatePool>[0]) as unknown as MysqlPoolLike;\n}\n\n/** A failed finalization reply cannot establish whether the transaction committed. */\nfunction finalizationOutcomeUnknown(params: { cause: unknown; stage: \"commit\" | \"raw-close\" }): VibeError {\n return new VibeError({\n code: \"VIBE_TRANSACTION\",\n message: \"MySQL transaction finalization failed; its outcome is unknown. The connection was discarded. Inspect the data before retrying.\",\n meta: { provider: PROVIDER, reason: \"transaction-outcome-unknown\", outcome: \"unknown\", stage: params.stage },\n cause: params.cause,\n });\n}\n\n/**\n * The connection died before COMMIT (mysql2 reported `error` or `end`), so\n * COMMIT was never sent and the transaction did not commit (EPIC T).\n */\nfunction connectionLostBeforeCommit(params: { cause: unknown }): VibeError {\n return new VibeError({\n code: \"VIBE_ADAPTER\",\n message: \"the MySQL connection was lost before COMMIT, so COMMIT was never sent and the transaction did not commit. The connection was discarded.\",\n meta: { provider: PROVIDER, reason: \"connection-lost\", stage: \"commit\" },\n ...(params.cause === undefined ? {} : { cause: params.cause }),\n });\n}\n\n/** Scalar-array params must never reach this adapter — the dialect expands IN. */\nfunction throwOnArrayParam(values: unknown[]): never {\n throw internalError({\n message:\n \"formatArrayParam called on the mysql adapter — the mysql dialect expands scalar-list parameters into IN (?, ?, …) placeholders, so the runtime should have expanded this array before binding\",\n meta: { length: values.length },\n });\n}\n\n/** A non-empty text after trimming; the value itself is used untrimmed. */\nfunction isGiven(value: unknown): value is string {\n return typeof value === \"string\" && value.trim() !== \"\";\n}\n\n/**\n * The address this adapter will use, taken once at construction: an injected\n * pool (it wins, as documented), or a snapshot of the options carrying a `url`\n * or a `host`. The URL itself is still parsed on first use, as before; nothing\n * re-reads the caller's object or the environment later.\n *\n * @throws VibeError `VIBE_CONFIG` (`meta.reason: \"missing-address\"`) when\n * none of `pool`, `url` and `host` is present. The message never echoes a value.\n */\nfunction takeAddress(params: { options: MysqlAdapterOptions | undefined }): { pool: MysqlPoolLike } | { options: MysqlAdapterSettings } {\n const options: MysqlAdapterSettings | undefined = params.options;\n if (options?.pool !== undefined && options.pool !== null) return { pool: options.pool };\n if (options !== undefined && (isGiven(options.url) || isGiven(options.host))) return { options: { ...options } };\n throw new VibeError({\n code: \"VIBE_CONFIG\",\n message:\n \"mysqlAdapter needs an explicit address: pass `url`, a `host` (with port/user/password/database as needed) \" +\n \"or an existing `pool`. The adapter does not read MYSQL_URL or DATABASE_URL.\",\n meta: { adapter: \"mysql\", reason: \"missing-address\" },\n });\n}\n\n/**\n * Create a VibeORM adapter backed by mysql2.\n *\n * Requires an explicit address (`url`, `host` or `pool`); see\n * {@link MysqlAdapterOptions}. Construction opens nothing — the pool is\n * created on first use.\n *\n * @example\n * ```ts\n * const adapter = mysqlAdapter({ url: \"mysql://app:secret@db.internal:3306/app\", connectionLimit: 20 });\n * await adapter.connect();\n * const rows = await adapter.execute({ text: \"SELECT * FROM `User` WHERE `id` = ?\", values: [1] });\n * ```\n *\n * @example Discrete fields, or reusing a pool you already own\n * ```ts\n * const adapter = mysqlAdapter({ host: \"127.0.0.1\", port: 3306, user: \"app\", password: \"pw\", database: \"app\" });\n * const shared = mysqlAdapter({ pool: existingPool });\n * ```\n *\n * ORM path (`execute`) uses mysql2's binary protocol (`pool.execute`), which\n * prepares statements and caches them per connection keyed by statement text\n * (mysql2's `maxPreparedStatements` LRU, default 16000). Raw path\n * (`executeUnsafe`) uses the text protocol (`pool.query`) when parameterless;\n * nonempty values always use prepared binding, with the same raw-session pin.\n *\n * Parameters arrive PRE-ENCODED by the runtime codec table: Json is already a\n * string, DateTime is a `Date` (mysql2 serializes it per `timezone`), BigInt\n * is a string. The adapter forwards values verbatim — no second conversion.\n */\nexport function mysqlAdapter(options: MysqlAdapterOptions): DatabaseAdapter {\n const address = takeAddress({ options });\n let pool: MysqlPoolLike | null = null;\n let ownsPool = false;\n\n /**\n * The pinned connection of an OPEN raw transaction — session affinity for\n * the raw path. A raw `BEGIN` … `COMMIT` sequence over `executeUnsafe` is\n * sound only when every statement in between rides the SAME pooled\n * connection, so a pure `BEGIN` checks one out, raw statements ride it, and\n * the matching `COMMIT`/`ROLLBACK` releases it (same semantics as the pg and\n * bun adapters). The ORM path (`execute`) and `transaction()` stay on the\n * pool. Concurrent raw transactions on one adapter are unsupported.\n */\n let rawSession: MysqlConnectionLike | null = null;\n\n const acquireTimeoutMs = options?.acquireTimeout;\n\n /**\n * Effective pool size for the refusal message. Unknown — and reported as\n * such — when the caller supplied the pool, since `connectionLimit` is\n * ignored in that mode.\n */\n const poolSize: number | undefined =\n \"pool\" in address ? undefined : (address.options.connectionLimit ?? MYSQL_DEFAULT_CONNECTION_LIMIT);\n\n async function getPool(): Promise<MysqlPoolLike> {\n return runMapped(async () => {\n if (pool !== null) return pool;\n\n if (\"pool\" in address) {\n pool = address.pool;\n ownsPool = false;\n return pool;\n }\n\n const config = mysqlPoolConfig({ options: address.options });\n pool = (address.options.createPool ?? defaultCreatePool)(config);\n ownsPool = true;\n return pool;\n });\n }\n\n /**\n * The ONE place a connection is checked out. Without `acquireTimeout` this is\n * mysql2's own unbounded checkout, byte for byte; with it, the wait is\n * bounded and a caller that cannot be served refuses instead of queueing.\n * `runMapped` maps driver failures — the timeout error is already a\n * `VibeError` and passes through untouched (errors.ts:121).\n */\n async function acquireConnection(): Promise<MysqlConnectionLike> {\n const active = pool ?? await getPool();\n if (acquireTimeoutMs === undefined) {\n return runMapped(() => active.getConnection());\n }\n return runMapped(() => acquireWithTimeout({ pool: active, timeoutMs: acquireTimeoutMs, poolSize }));\n }\n\n /** A failed raw script can retain earlier statements without returning their headers. */\n function observeUnclassifiedDispatch(params: { scope?: SavepointScope; effect?: StatementEffect }): void {\n if (params.scope !== undefined && params.effect !== \"read\" && params.effect !== \"write\") {\n observeRowChanges({ scope: params.scope, count: \"unknown\" });\n }\n }\n\n function observeResult(params: { scope?: SavepointScope; effect?: StatementEffect; result: unknown }): void {\n if (params.scope === undefined) return;\n const count = isResultSetHeader({ value: params.result }) ? (params.result as { affectedRows: number }).affectedRows : undefined;\n observeRowChanges({ scope: params.scope, count: statementRowChanges({ effect: params.effect, count }) });\n }\n\n async function runExecute(params: {\n queryable: Queryable;\n text: string;\n values: unknown[];\n scope?: SavepointScope;\n effect?: StatementEffect;\n }): Promise<Record<string, unknown>[]> {\n observeUnclassifiedDispatch(params);\n const [result, fields] = await runMapped(() => params.queryable.execute(params.text, params.values));\n observeResult({ scope: params.scope, effect: params.effect, result });\n return normalizeDriverResult({ result, fields }).rows;\n }\n\n /**\n * The ORM's affected-row path (F01). Same PREPARED protocol as `execute()` —\n * mysql2 sends the statement and its parameters separately — but keeping the\n * OK-packet's `affectedRows` instead of dropping it.\n *\n * Never `query()`: that is the TEXT protocol, which interpolates values into\n * the SQL client-side. mysql2 cannot know the server's `sql_mode`, so under\n * `NO_BACKSLASH_ESCAPES` its `\\'` is not an escape and a hostile string\n * predicate breaks out of its literal — a `deleteMany` deleted rows a bound\n * read did not match. There is deliberately NO fallback from a failed\n * preparation to interpolation: an unpreparable statement fails loudly.\n *\n * RAW STATEMENTS RIDE THIS PATH TOO, so `bindRowCountParams` first rewrites\n * integers sitting in a `LIMIT` / `OFFSET` position into their decimal text:\n * mysql2's prepared protocol types a JS number in a way the server refuses\n * there (errno 1210), and only user-written raw SQL can produce that shape —\n * the ORM inlines its limits as literal text. Nothing else is touched.\n */\n async function runExecuteAffected(params: {\n queryable: Queryable;\n text: string;\n values: unknown[];\n scope?: SavepointScope;\n effect?: StatementEffect;\n }): Promise<QueryResult> {\n const values = bindRowCountParams({ text: params.text, values: params.values });\n observeUnclassifiedDispatch(params);\n const [result, fields] = await runMapped(() => params.queryable.execute(params.text, values));\n observeResult({ scope: params.scope, effect: params.effect, result });\n return normalizeDriverResult({ result, fields });\n }\n\n async function runExecuteUnsafe(params: {\n queryable: Queryable;\n text: string;\n values?: unknown[];\n scope?: SavepointScope;\n effect?: StatementEffect;\n }): Promise<QueryResult> {\n if (params.values !== undefined && params.values.length > 0) {\n return runExecuteAffected({ ...params, values: params.values });\n }\n observeUnclassifiedDispatch(params);\n const [result, fields] = await runMapped(() => params.queryable.query(params.text, params.values));\n observeResult({ scope: params.scope, effect: params.effect, result });\n return normalizeDriverResult({ result, fields });\n }\n\n /**\n * Adapter bound to the ONE pinned connection of an open transaction — the\n * same-connection guarantee. Nested `transaction()` calls open savepoints on\n * that connection, and their LIFETIMES are serialized by the savepoint gate\n * (F14): overlapping siblings share one savepoint stack, so the earlier\n * one's rollback would erase the later one's already released work.\n */\n function createConnectionAdapter(params: {\n conn: MysqlConnectionLike;\n scope: SavepointScope;\n budget: TransactionBudget;\n }): DatabaseAdapter {\n const { conn, scope, budget } = params;\n\n function invalidate(error: unknown): never {\n // Driver calls already map errors. A nested callback's own error must\n // retain its identity rather than being relabelled as a driver failure.\n if (!(error instanceof VibeError)) throw error;\n const mapped = error;\n if (mapped.meta.errno === 1213) {\n // InnoDB has rolled back the whole transaction, not just this statement.\n // Keep this terminal for every handle even when the callback catches it.\n scope.state.poisoned = new VibeError({\n code: mapped.code, message: mapped.message,\n meta: { ...mapped.meta, outcome: \"not-committed\" }, cause: mapped,\n });\n }\n if (isSavepointRollbackFailedError(mapped)) budget.close({ outcome: \"unknown\" });\n throw mapped;\n }\n\n return {\n dialect: DIALECT,\n provider: PROVIDER,\n wire: WIRE,\n budgets: BUDGETS,\n roundTrips: ROUND_TRIPS,\n rowChanges: (): RowChangeCount => { budget.assertUsable({ stage: \"statement\" }); return readRowChanges({ scope }); },\n\n async execute(execParams) {\n const turn = scopeTurn({ scope });\n if (turn !== undefined) await turn;\n // After the turn, not before: waiting for a sibling savepoint spends\n // the same budget the statement is about to run against.\n budget.assertUsable({ stage: \"statement\" });\n return runExecute({ queryable: conn, scope, ...execParams }).catch(invalidate);\n },\n\n async executeRawBound(execParams) {\n return this.executeUnsafe(execParams);\n },\n\n async executeUnsafe(execParams) {\n const turn = scopeTurn({ scope });\n if (turn !== undefined) await turn;\n budget.assertUsable({ stage: \"statement\" });\n return runExecuteUnsafe({ queryable: conn, scope, ...execParams }).catch(invalidate);\n },\n\n async executeAffected(execParams) {\n const turn = scopeTurn({ scope });\n if (turn !== undefined) await turn;\n budget.assertUsable({ stage: \"statement\" });\n return runExecuteAffected({ queryable: conn, scope, ...execParams }).catch(invalidate);\n },\n\n async transaction<T>(\n fn: (txAdapter: DatabaseAdapter) => Promise<T>,\n nestedOptions?: TransactionOptions,\n ): Promise<T> {\n refuseNestedTransactionOptions({ options: nestedOptions, provider: PROVIDER });\n budget.assertUsable({ stage: \"nested\" });\n return runNestedSavepoint({\n scope,\n execute: (statement) => runMapped(() => conn.query(statement)).catch(invalidate),\n // The child shares the ROOT budget by reference: a savepoint never\n // gets an independent clock or session setting.\n body: (child) => fn(createConnectionAdapter({ conn, scope: child, budget })),\n }).catch(invalidate);\n },\n\n // The open transaction owns this connection: neither call may act on it.\n // An expired handle keeps its own refusal (the budget check comes first).\n async connect(): Promise<void> {\n budget.assertUsable({ stage: \"statement\" });\n throw transactionLifecycleRefusal({ method: \"connect\" });\n },\n\n async disconnect(): Promise<void> {\n budget.assertUsable({ stage: \"statement\" });\n throw transactionLifecycleRefusal({ method: \"disconnect\" });\n },\n\n formatArrayParam(values: unknown[]): unknown {\n return throwOnArrayParam(values);\n },\n };\n }\n\n /**\n * Final cleanup, run ONCE by the lifecycle gate after every admitted\n * operation settled — so a raw BEGIN that was still pending at the\n * `disconnect()` call has published its session by now. Rolls back and\n * releases an abandoned raw session (destroyed when the rollback failed),\n * then ends the pool the adapter created. An injected pool is never ended.\n */\n function closeOwnedResources(): Promise<void> {\n return runShutdownCleanup({\n steps: [\n async (): Promise<void> => {\n if (rawSession === null) return;\n const session = rawSession;\n rawSession = null;\n // An abandoned raw checkout is reusable only after a successful rollback.\n await runMapped(() => session.query(\"ROLLBACK\")).then(\n () => { session.release(); },\n (error: unknown) => { session.destroy(); throw error; },\n );\n },\n async (): Promise<void> => {\n if (pool === null || !ownsPool) return;\n const closing = pool;\n await runMapped(() => closing.end());\n },\n ],\n });\n }\n\n const lifecycle = createAdapterLifecycleGate({ driver: \"mysql\", cleanup: closeOwnedResources });\n\n /** The root operations; the adapter below admits each one through {@link lifecycle}. */\n const root: Pick<Required<DatabaseAdapter>, \"withSession\" | \"execute\" | \"executeAffected\" | \"executeUnsafe\" | \"transaction\" | \"connect\"> = {\n async withSession({ run }) {\n const conn = await acquireConnection();\n return runPinnedSession({\n run,\n execute: async (query) => (await runExecuteUnsafe({ queryable: conn, ...query })).rows,\n isLost: (error) => error instanceof VibeError && (\n typeof error.meta.errno !== \"number\" || [2006, 2013, 2055, 4031].includes(error.meta.errno)\n ),\n // Discard session settings and any open transaction, even on success.\n release: async () => { conn.destroy(); },\n });\n },\n\n async execute(params) {\n // Default path: mysql2's `pool.execute` does its own implicit checkout.\n // With `acquireTimeout` set that checkout has to be visible to be\n // bounded, so the statement is routed over an explicit connection\n // instead (mysql2 caches prepared statements per connection either way).\n if (acquireTimeoutMs === undefined) {\n return runExecute({ queryable: pool ?? await getPool(), ...params });\n }\n const conn = await acquireConnection();\n try {\n return await runExecute({ queryable: conn, ...params });\n } finally {\n conn.release();\n }\n },\n\n async executeAffected(params) {\n // Same checkout rules as `execute()` above: implicit with mysql2's own\n // pool, explicit (and therefore boundable) when `acquireTimeout` is set.\n if (acquireTimeoutMs === undefined) {\n return runExecuteAffected({ queryable: pool ?? await getPool(), ...params });\n }\n const conn = await acquireConnection();\n try {\n return await runExecuteAffected({ queryable: conn, ...params });\n } finally {\n conn.release();\n }\n },\n\n async executeUnsafe(params) {\n const control = classifyRawTransactionControl({ text: params.text });\n if (rawSession !== null) {\n if (control === \"close\") {\n const session = rawSession;\n rawSession = null;\n try {\n const result = await runExecuteUnsafe({ queryable: session, ...params });\n session.release();\n return result;\n } catch (cause) {\n session.destroy();\n throw finalizationOutcomeUnknown({ cause, stage: \"raw-close\" });\n }\n }\n return runExecuteUnsafe({ queryable: rawSession, ...params });\n }\n if (control === \"open\") {\n const conn = await acquireConnection();\n try {\n const result = await runExecuteUnsafe({ queryable: conn, ...params });\n rawSession = conn;\n return result;\n } catch (error) {\n conn.release();\n throw error;\n }\n }\n // Default path: mysql2's `pool.query` checks a connection out\n // implicitly. Same reroute as `execute()` above, for the same reason —\n // a checkout has to be visible to be bounded, so with `acquireTimeout`\n // set the raw statement runs on an explicit connection too.\n if (acquireTimeoutMs === undefined) {\n return runExecuteUnsafe({ queryable: pool ?? await getPool(), ...params });\n }\n const conn = await acquireConnection();\n try {\n return await runExecuteUnsafe({ queryable: conn, ...params });\n } finally {\n conn.release();\n }\n },\n\n async transaction<T>(\n fn: (txAdapter: DatabaseAdapter) => Promise<T>,\n transactionOptions?: TransactionOptions,\n ): Promise<T> {\n // Validate the timeout before taking a connection, so a bad option fails\n // fast instead of wasting a checkout.\n const timeoutText =\n transactionOptions?.timeout === undefined\n ? undefined\n : maxExecutionTimeStatement({ timeout: transactionOptions.timeout });\n // Same rule for the deadline: an unsupportable budget is refused before a\n // connection is taken, so it never costs a checkout.\n validateTransactionDeadline({\n options: transactionOptions,\n support: BUDGETS.transactionDeadline,\n provider: PROVIDER,\n });\n const readOnly = readOnlyRequested({ options: transactionOptions, provider: PROVIDER });\n const isolationLevel = transactionOptions?.isolationLevel;\n // Round-trip EPIC 3 (A-06a): both options in ONE SET (see transaction-sql.ts).\n const combinedText =\n transactionOptions?.timeout === undefined || isolationLevel === undefined\n ? undefined\n : sessionOptionsStatement({ timeout: transactionOptions.timeout, isolationLevel });\n\n const conn = await acquireConnection();\n /** Set when the session state can no longer be asserted (see below). */\n let rollbackFailed = false;\n // The deadline clock starts with the connection already in hand:\n // acquisition has its own budget (`acquireTimeout`) and is not charged here.\n const budget = startTransactionBudget({ options: transactionOptions, provider: PROVIDER });\n /**\n * How far COMMIT got — the only input of the commit outcome (EPIC T). A\n * holder, because the COMMIT failure handler moves it out of sight of\n * the compiler's narrowing.\n */\n const commit: { progress: CommitProgress } = { progress: \"not-sent\" };\n /**\n * The connection died while this transaction held it: mysql2 reported\n * `error` or `end` (EPIC T review, finding 1). A holder, because the\n * listener sets it out of sight of the compiler's narrowing.\n */\n const lost: { cause?: unknown; seen: boolean } = { seen: false };\n const onLost = (cause?: unknown): void => {\n if (lost.seen) return;\n lost.seen = true;\n lost.cause = cause;\n };\n conn.on?.(\"error\", onLost);\n conn.on?.(\"end\", onLost);\n /** Where the connection went, once `releaseConnection` has run. */\n let released: ConnectionOutcome | undefined;\n /**\n * Restore the session default and hand the connection back — or destroy\n * it. Runs ONCE: from the failure path, so the outcome report can say\n * where the connection went, or from `finally`.\n */\n const releaseConnection = async (): Promise<ConnectionOutcome> => {\n if (released !== undefined) return released;\n conn.removeListener?.(\"error\", onLost);\n conn.removeListener?.(\"end\", onLost);\n let poisoned = rollbackFailed || lost.seen;\n if (timeoutText !== undefined && !poisoned) {\n try {\n await conn.query(RESET_MAX_EXECUTION_TIME_SQL);\n } catch {\n poisoned = true;\n }\n }\n // A connection whose session default could not be restored — or whose\n // rollback failed, so it may still be inside a transaction — must never\n // return to the pool.\n released = poisoned ? \"discarded\" : \"returned\";\n if (poisoned) {\n conn.destroy();\n } else {\n conn.release();\n }\n return released;\n };\n const scope = createSavepointScope();\n /** Whether the opening (START TRANSACTION) succeeded: before it, there is nothing to roll back. */\n let opened = false;\n try {\n try {\n // Session-scoped SELECT bound — see transaction-sql.ts for the loud\n // \"SELECT statements only\" caveat. Reset when the connection leaves.\n if (combinedText !== undefined) {\n await runMapped(() => conn.query(combinedText));\n } else {\n if (timeoutText !== undefined) {\n await runMapped(() => conn.query(timeoutText));\n }\n // Applies to the NEXT transaction in the session → must precede begin.\n if (isolationLevel !== undefined) {\n const isolationText = setIsolationLevelStatement({ isolationLevel });\n await runMapped(() => conn.query(isolationText));\n }\n }\n if (readOnly) await runMapped(() => conn.query(START_TRANSACTION_READ_ONLY_SQL));\n else await runMapped(() => conn.beginTransaction());\n opened = true;\n const result = await runRootScope({\n scope,\n body: () => fn(createConnectionAdapter({ conn, scope, budget })),\n });\n // The callback may have caught a driver error that invalidated the\n // whole transaction. Check the shared scope as well as the deadline.\n const turn = scopeTurn({ scope });\n if (turn !== undefined) await turn;\n budget.assertUsable({ stage: \"commit\" });\n // mysql2 refuses every command on a connection whose death it has\n // seen, without writing it: COMMIT would never leave the client.\n if (lost.seen) throw connectionLostBeforeCommit({ cause: lost.cause });\n commit.progress = \"sent\";\n await runMapped(() => conn.commit()).catch((cause: unknown) => {\n // An errno MySQL documents as \"the transaction was rolled back\"\n // (errors.ts): the server answered, nothing committed, and the\n // connection is healthy. The server error is thrown as it is.\n const errno = cause instanceof VibeError ? cause.meta.errno : undefined;\n if (typeof errno === \"number\" && MYSQL_ROLLED_BACK_ERRNOS.includes(errno)) {\n commit.progress = \"answered\";\n throw cause;\n }\n // A later successful ROLLBACK does not disprove a committed write\n // whose acknowledgement was lost, and any other MySQL COMMIT error\n // does not prove a rollback either: it is unanswered here.\n // Close unknown before cleanup.\n commit.progress = \"unanswered\";\n budget.close({ outcome: \"unknown\" });\n rollbackFailed = true;\n throw finalizationOutcomeUnknown({ cause, stage: \"commit\" });\n });\n budget.close({ outcome: \"committed\" });\n return result;\n } catch (error) {\n if (isSavepointRollbackFailedError(error) || commit.progress === \"unanswered\") {\n budget.close({ outcome: \"unknown\" });\n rollbackFailed = true;\n }\n // Best effort: never mask the original failure with a rollback failure.\n // A failed opening left nothing to undo: no ROLLBACK is sent then.\n let rollback: RollbackOutcome = \"not-needed\";\n try {\n if (opened) {\n await conn.rollback();\n rollback = \"acknowledged\";\n }\n } catch {\n // The rollback that should have cleaned up failed: the connection is\n // destroyed rather than pooled while it may still be inside a\n // transaction. The commit outcome does not change: it follows from\n // how far COMMIT got, and the server ends an open transaction when\n // the connection closes.\n rollbackFailed = true;\n rollback = \"failed\";\n }\n // Close the budget BEFORE the connection leaves (the session reset\n // below is a round trip, and `release()` hands it to the next caller):\n // a late statement on this transaction's handle must already be\n // refused by then (EPIC T review, finding 2).\n closeFailedTransactionBudget({ error, budget, scope, commit: commit.progress });\n // EPIC T: the same error, with the facts recorded beside it.\n throw settleFailedTransaction({\n error,\n provider: PROVIDER,\n budget,\n scope,\n commit: commit.progress,\n rollback,\n connection: await releaseConnection(),\n });\n }\n } finally {\n await releaseConnection();\n }\n },\n\n async connect(): Promise<void> {\n const conn = await acquireConnection();\n try {\n await runMapped(() => conn.ping());\n } finally {\n conn.release();\n }\n },\n };\n\n return {\n dialect: DIALECT,\n provider: PROVIDER,\n wire: WIRE,\n budgets: BUDGETS,\n roundTrips: ROUND_TRIPS,\n transactionOutcome: \"reported\",\n\n withSession({ run }) {\n return lifecycle.admit({ run: () => root.withSession({ run: (executor) => lifecycle.inCallback({ run: () => run(executor) }) }) });\n },\n\n execute(params) {\n return lifecycle.admit({ run: () => root.execute(params) });\n },\n\n executeAffected(params) {\n return lifecycle.admit({ run: () => root.executeAffected(params) });\n },\n\n executeRawBound(params) {\n return lifecycle.admit({ run: () => root.executeUnsafe(params) });\n },\n\n executeUnsafe(params) {\n return lifecycle.admit({ run: () => root.executeUnsafe(params) });\n },\n\n transaction<T>(\n fn: (txAdapter: DatabaseAdapter) => Promise<T>,\n transactionOptions?: TransactionOptions,\n ): Promise<T> {\n return lifecycle.admit({ run: () => root.transaction((txAdapter) => lifecycle.inCallback({ run: () => fn(txAdapter) }), transactionOptions) });\n },\n\n connect(): Promise<void> {\n return lifecycle.admit({ run: () => root.connect() });\n },\n\n /**\n * Terminal (EPIC A2): refuses new work at once, waits for admitted work —\n * whole transaction and session callbacks included — then closes what the\n * adapter owns, once. Repeated calls share that completion. A new adapter\n * is the only way to connect again.\n */\n disconnect(): Promise<void> {\n return lifecycle.disconnect();\n },\n\n formatArrayParam(values: unknown[]): unknown {\n return throwOnArrayParam(values);\n },\n };\n}\n\n// ─── Re-exports (driver-error table, helpers) ─────────────────────\n\nexport {\n DEFAULT_ACQUIRE_TIMERS,\n MYSQL_DEFAULT_CONNECTION_LIMIT,\n acquireTimeoutError,\n acquireWithTimeout,\n} from \"./acquire.ts\";\nexport type { AcquireSource, AcquireTimers, ReleasableConnection, TimerHandle } from \"./acquire.ts\";\nexport {\n MYSQL_ERRNO_ERROR_CODES,\n MYSQL_ERRNO_REASONS,\n MYSQL_ROLLED_BACK_ERRNOS,\n mapMysqlDriverError,\n mysqlErrorErrno,\n runMapped,\n} from \"./errors.ts\";\nexport { isResultSetHeader, normalizeDriverResult } from \"./results.ts\";\nexport { createSavepointCounter, nextSavepointName } from \"@vibeorm/runtime/adapter-kit\";\nexport type { SavepointCounter } from \"@vibeorm/runtime/adapter-kit\";\nexport {\n ISOLATION_LEVEL_SQL,\n RESET_MAX_EXECUTION_TIME_SQL,\n classifyRawTransactionControl,\n maxExecutionTimeStatement,\n refuseNestedTransactionOptions,\n setIsolationLevelStatement,\n} from \"./transaction-sql.ts\";\nexport type { RawTransactionControl } from \"./transaction-sql.ts\";\n// ─── EPIC 6: transaction budgets (shared, @vibeorm/runtime/adapter-kit) ───\nexport {\n DEFAULT_DEADLINE_CLOCK,\n engineStatementBudgetMs,\n isTransactionDeadlineError,\n startTransactionBudget,\n transactionClosedError,\n transactionDeadlineError,\n transactionOutcomeUnknownError,\n validateTransactionDeadline,\n} from \"@vibeorm/runtime/adapter-kit\";\nexport type { BudgetStage, DeadlineClock, TransactionBudget, TransactionOutcome } from \"@vibeorm/runtime/adapter-kit\";\n",
|
|
6
6
|
"/**\n * Bounded pool acquisition — the adapter's own acquire timeout.\n *\n * mysql2 has NO acquire timeout of its own (verified against mysql2 3.23.3:\n * neither `acquireTimeout` nor `acquire_timeout` exists anywhere in its\n * sources). Its pool backpressure knobs are `waitForConnections`\n * (`node_modules/mysql2/lib/pool_config.js:11-14`, default `true`) and\n * `queueLimit` (`:24-26`, default `0` = unlimited), which bounds queue DEPTH,\n * not TIME; `connectTimeout` is the TCP deadline for establishing a NEW\n * connection, not for waiting on a busy pool. So an exhausted pool queues the\n * caller forever unless something above the driver bounds the wait — which is\n * what this module does.\n *\n * The trap this module exists to get right: when the deadline wins the race,\n * the driver's `getConnection()` promise is STILL PENDING and will later hand\n * back a real connection nobody holds. Dropping it would turn \"waits too long\"\n * into \"the pool is dead forever\", so the losing promise is always released.\n */\n\nimport { VibeError } from \"@vibeorm/schema\";\n\n// ─── Seams ────────────────────────────────────────────────────────\n\n/** Timer handle, as the ambient `setTimeout` returns it. */\nexport type TimerHandle = ReturnType<typeof setTimeout>;\n\n/**\n * Timer seam — a test injects a counting pair to prove the deadline timer is\n * cleared exactly once, rather than asserting on wall-clock luck.\n */\nexport type AcquireTimers = {\n readonly set: (fn: () => void, ms: number) => TimerHandle;\n readonly clear: (handle: TimerHandle) => void;\n};\n\n/** The ambient timers, used whenever no seam is injected. */\nexport const DEFAULT_ACQUIRE_TIMERS: AcquireTimers = Object.freeze({\n set: (fn: () => void, ms: number): TimerHandle => setTimeout(fn, ms),\n clear: (handle: TimerHandle): void => clearTimeout(handle),\n});\n\n/** The one connection capability the late-release path needs. */\nexport type ReleasableConnection = {\n release(): void;\n};\n\n/** The one pool capability bounded acquisition needs. */\nexport type AcquireSource<TConnection extends ReleasableConnection> = {\n getConnection(): Promise<TConnection>;\n};\n\n// ─── Error ────────────────────────────────────────────────────────\n\n/** mysql2's own pool default when `connectionLimit` is unset (`lib/pool_config.js:15-17`). */\nexport const MYSQL_DEFAULT_CONNECTION_LIMIT: number = 10;\n\n/**\n * The refusal a bounded acquisition raises. `VIBE_ADAPTER` for parity with\n * `@vibeorm/adapter-pg`, whose `connectionTimeout` surfaces the same way, and\n * `meta.reason: \"acquire-timeout\"` so a caller can tell an exhausted pool from\n * any other adapter failure without reading message text.\n */\nexport function acquireTimeoutError(params: { timeoutMs: number; poolSize?: number }): VibeError {\n const { timeoutMs, poolSize } = params;\n const size =\n poolSize === undefined\n ? \"pool size unknown — the pool was supplied by the caller\"\n : `connectionLimit ${poolSize}`;\n return new VibeError({\n code: \"VIBE_ADAPTER\",\n message:\n `timed out after ${timeoutMs} ms waiting for a mysql pool connection — every pooled connection ` +\n `is busy (${size}). Raise \\`connectionLimit\\`, shorten the work holding a connection, or raise ` +\n \"the adapter's `acquireTimeout` option.\",\n meta: {\n reason: \"acquire-timeout\",\n timeoutMs,\n ...(poolSize === undefined ? {} : { connectionLimit: poolSize }),\n },\n });\n}\n\n// ─── Bounded acquisition ──────────────────────────────────────────\n\n/**\n * Check a connection out of `pool`, refusing with {@link acquireTimeoutError}\n * when it takes longer than `timeoutMs`.\n *\n * Two invariants make this safe:\n *\n * 1. **The lost acquire is released.** When the deadline wins, the pending\n * `getConnection()` is not abandoned: a handler released it as soon as it\n * lands, so a `connectionLimit: 1` pool keeps working after a timeout\n * instead of being permanently starved of its only connection.\n * 2. **The deadline timer never outlives the call.** It is cleared in a\n * `finally`, so a successful acquire leaves nothing pending that could keep\n * the event loop (or a test runner) alive.\n */\nexport async function acquireWithTimeout<TConnection extends ReleasableConnection>(params: {\n pool: AcquireSource<TConnection>;\n timeoutMs: number;\n /** Effective pool size, named in the refusal; omit when the pool is the caller's. */\n poolSize?: number;\n timers?: AcquireTimers;\n}): Promise<TConnection> {\n const { pool, timeoutMs, poolSize } = params;\n const timers = params.timers ?? DEFAULT_ACQUIRE_TIMERS;\n\n const pending = pool.getConnection();\n let timedOut = false;\n let handle: TimerHandle | undefined;\n\n const deadline = new Promise<never>((_resolve, reject) => {\n handle = timers.set(() => {\n timedOut = true;\n reject(acquireTimeoutError({ timeoutMs, poolSize }));\n }, timeoutMs);\n });\n\n // Trap: the loser of the race still settles. A connection that arrives after\n // the refusal belongs to nobody, so it goes straight back to the pool; a\n // rejection is already the race's business and is swallowed here so it can\n // never surface as an unhandled rejection.\n void pending\n .then(\n (connection) => {\n if (timedOut) connection.release();\n },\n () => undefined,\n )\n .catch(() => undefined);\n\n try {\n return await Promise.race([pending, deadline]);\n } finally {\n if (handle !== undefined) timers.clear(handle);\n }\n}\n",
|
|
7
|
-
"import * as mysql2 from \"mysql2\";\nimport { VibeError } from \"@vibeorm/schema\";\nimport type {
|
|
8
|
-
"/**\n * Driver-error mapping for mysql2.\n *\n * Constitution rule 5: a raw driver error never escapes an adapter. Every\n * failure becomes a `VibeError` with a stable code, the driver error attached\n * as `cause`, and the MySQL errno / symbolic code / SQLSTATE / server message\n * in `meta`.\n *\n * mysql2 errors carry `errno` (the numeric MySQL server error, e.g. 1062),\n * `code` (the symbolic name, `ER_DUP_ENTRY`, or a client-side string like\n * `ECONNREFUSED` / `PROTOCOL_CONNECTION_LOST`), `sqlState` and `sqlMessage`.\n * The table is keyed by `errno` because it is the stable server-side identity;\n * client-side failures have no errno and fall through to `VIBE_ADAPTER`.\n */\n\nimport { VibeError, type VibeErrorCode } from \"@vibeorm/schema\";\n\n// ─── Errno table ──────────────────────────────────────────────────\n\n/**\n * MySQL server errno → stable VibeError code. Frozen and mirrored by tests;\n * anything absent from this table maps to `VIBE_ADAPTER` — including access\n * failures (1044 `ER_DBACCESS_DENIED_ERROR`, 1045 `ER_ACCESS_DENIED_ERROR`)\n * and every client-side connection error (`ECONNREFUSED`,\n * `PROTOCOL_CONNECTION_LOST`, `ETIMEDOUT`), which carry no errno at all.\n */\nexport const MYSQL_ERRNO_ERROR_CODES: Readonly<Record<number, VibeErrorCode>> = Object.freeze({\n /** ER_DUP_ENTRY */\n 1062: \"VIBE_UNIQUE_VIOLATION\",\n /** ER_DUP_ENTRY_WITH_KEY_NAME */\n 1586: \"VIBE_UNIQUE_VIOLATION\",\n /** ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO */\n 1761: \"VIBE_UNIQUE_VIOLATION\",\n /** ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO */\n 1762: \"VIBE_UNIQUE_VIOLATION\",\n /** ER_NO_REFERENCED_ROW */\n 1216: \"VIBE_FK_VIOLATION\",\n /** ER_ROW_IS_REFERENCED */\n 1217: \"VIBE_FK_VIOLATION\",\n /** ER_ROW_IS_REFERENCED_2 */\n 1451: \"VIBE_FK_VIOLATION\",\n /** ER_NO_REFERENCED_ROW_2 */\n 1452: \"VIBE_FK_VIOLATION\",\n /** ER_BAD_NULL_ERROR — NOT NULL column set to NULL */\n 1048: \"VIBE_VALIDATION\",\n /** ER_WARN_DATA_OUT_OF_RANGE — value out of column range */\n 1264: \"VIBE_VALIDATION\",\n /** ER_NO_DEFAULT_FOR_FIELD — column without default omitted */\n 1364: \"VIBE_VALIDATION\",\n /** ER_DATA_TOO_LONG */\n 1406: \"VIBE_VALIDATION\",\n /**\n * WARN_DATA_TRUNCATED — despite the WARN_ name, strict mode raises it as a\n * hard error: an out-of-range ENUM value or a truncated numeric string\n * (live-verified on 8.4: `role = \"SUPERUSER\"` and `n = \"12abc\"` → 1265).\n * The same bad input is a CHECK violation on sqlite and SQLSTATE 22P02 on\n * postgres — all VIBE_VALIDATION (board #9).\n */\n 1265: \"VIBE_VALIDATION\",\n /**\n * ER_TRUNCATED_WRONG_VALUE_FOR_FIELD — a wrong-TYPED value for the column\n * (live-verified on 8.4: `\"abc\"` into INT, `\"12.x9\"` into DECIMAL → 1366).\n */\n 1366: \"VIBE_VALIDATION\",\n /**\n * ER_TRUNCATED_WRONG_VALUE — an unparseable literal, e.g. a bad datetime\n * (live-verified on 8.4: `\"not-a-date\"` into DATETIME(3) → 1292,\n * SQLSTATE 22007).\n */\n 1292: \"VIBE_VALIDATION\",\n /** ER_CHECK_CONSTRAINT_VIOLATED */\n 3819: \"VIBE_VALIDATION\",\n /** ER_LOCK_DEADLOCK */\n 1213: \"VIBE_TRANSACTION\",\n /**\n * ER_LOCK_WAIT_TIMEOUT — `innodb_lock_wait_timeout` expired while waiting for\n * a row lock. This is MySQL's spelling of PostgreSQL's `lock_timeout` case,\n * which is SQLSTATE 55P03 there, so it carries the same VibeORM code: a\n * caller asking \"was the row locked?\" must branch identically on both\n * engines. (Before EPIC 5 it was VIBE_TRANSACTION with reason \"timeout\",\n * which read the same as a STATEMENT timeout — a different failure.)\n */\n 1205: \"VIBE_LOCK_NOT_AVAILABLE\",\n /**\n * ER_LOCK_NOWAIT — \"Statement aborted because lock(s) could not be acquired\n * immediately and NOWAIT is set\" (verified on mysql 26.7.0, SQLSTATE HY000).\n */\n 3572: \"VIBE_LOCK_NOT_AVAILABLE\",\n /** ER_QUERY_TIMEOUT — max_execution_time exceeded, statement interrupted */\n 3024: \"VIBE_TRANSACTION\",\n});\n\n/** Errnos that additionally explain themselves through `meta.reason`. */\nexport const MYSQL_ERRNO_REASONS: Readonly<Record<number, string>> = Object.freeze({\n /** ER_LOCK_DEADLOCK */\n 1213: \"deadlock\",\n /** ER_LOCK_WAIT_TIMEOUT — the wait for a row lock ran out. */\n 1205: \"lock-not-available\",\n /** ER_LOCK_NOWAIT — the row was locked and the caller asked not to wait. */\n 3572: \"lock-not-available\",\n /** ER_QUERY_TIMEOUT */\n 3024: \"timeout\",\n});\n\n// ─── Reading driver errors ────────────────────────────────────────\n\nfunction readStringField(params: { source: Record<string, unknown>; key: string }): string | undefined {\n const value = params.source[params.key];\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\n/**\n * Extract the numeric MySQL errno from a mysql2 error. Client-side failures\n * (`ECONNREFUSED`, `PROTOCOL_CONNECTION_LOST`, …) have no numeric errno and\n * yield `undefined`.\n */\nexport function mysqlErrorErrno(params: { error: unknown }): number | undefined {\n const { error } = params;\n if (error === null || typeof error !== \"object\") return undefined;\n const errno = (error as Record<string, unknown>).errno;\n return typeof errno === \"number\" && Number.isInteger(errno) ? errno : undefined;\n}\n\n// ─── Mapping ──────────────────────────────────────────────────────\n\n/**\n * Map any error thrown by mysql2 onto a `VibeError`.\n *\n * A `VibeError` passes through unchanged, so an error raised deeper inside the\n * ORM (or by a nested adapter call) is never re-wrapped, and a user callback's\n * error is rethrown identically.\n */\nexport function mapMysqlDriverError(params: { error: unknown }): VibeError {\n const { error } = params;\n if (error instanceof VibeError) return error;\n\n const source: Record<string, unknown> =\n error !== null && typeof error === \"object\" ? (error as Record<string, unknown>) : {};\n const errno = mysqlErrorErrno({ error });\n const code: VibeErrorCode =\n (errno === undefined ? undefined : MYSQL_ERRNO_ERROR_CODES[errno]) ?? \"VIBE_ADAPTER\";\n\n const meta: Record<string, unknown> = {};\n if (errno !== undefined) meta.errno = errno;\n const symbolicCode = readStringField({ source, key: \"code\" });\n if (symbolicCode !== undefined) meta.code = symbolicCode;\n const sqlState = readStringField({ source, key: \"sqlState\" });\n if (sqlState !== undefined) meta.sqlState = sqlState;\n const sqlMessage = readStringField({ source, key: \"sqlMessage\" });\n if (sqlMessage !== undefined) meta.sqlMessage = sqlMessage.trim();\n const reason = errno === undefined ? undefined : MYSQL_ERRNO_REASONS[errno];\n if (reason !== undefined) meta.reason = reason;\n\n const message =\n readStringField({ source, key: \"message\" }) ??\n (sqlMessage !== undefined ? sqlMessage.trim() : undefined) ??\n (typeof error === \"string\" ? error : \"unknown mysql driver error\");\n\n return new VibeError({ code, message, meta, cause: error });\n}\n\n/** Run a driver call, mapping anything it throws onto a `VibeError`. */\nexport async function runMapped<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n throw mapMysqlDriverError({ error });\n }\n}\n",
|
|
7
|
+
"import * as mysql2 from \"mysql2\";\nimport { VibeError } from \"@vibeorm/schema\";\nimport type { MysqlAdapterSettings, MysqlPoolConfig } from \"./index.ts\";\n\n/** mysql2's runtime export has static methods but its declarations only expose an interface. */\nconst connectionConfig: { parseUrl(url: string): Record<string, unknown> } =\n (mysql2 as unknown as { ConnectionConfig: { parseUrl(url: string): Record<string, unknown> } }).ConnectionConfig;\n\n/** The mysql2 typeCast surface used for JSON; other scalars keep the driver decoder. */\nexport type MysqlTypeCast = (field: {\n readonly type: string;\n readonly extendedFormat?: string;\n string(encoding?: string): string | null;\n}, next: () => unknown) => unknown;\n\n/** Retain JSON.parse number semantics independently of mysql2's BIGINT configuration. */\nconst typeCast: MysqlTypeCast = (field, next): unknown => {\n if (field.type !== \"JSON\" && field.extendedFormat !== \"json\") return next();\n const text = field.string(\"utf8\");\n return text === null ? null : JSON.parse(text);\n};\n\n/** Parse once, overlay explicit options, then pin the wire and statement contracts. */\nexport function mysqlPoolConfig(params: { options?: MysqlAdapterSettings }): MysqlPoolConfig {\n const options = params.options;\n // Only the caller's own address: never MYSQL_URL or any other environment value.\n const url = options?.url;\n let parsed: Record<string, unknown>;\n try {\n parsed = url === undefined ? {} : connectionConfig.parseUrl(url);\n } catch (cause) {\n throw new VibeError({ code: \"VIBE_CONFIG\", message: \"Invalid MySQL connection URL\", cause });\n }\n // Never let a URL query parameter re-enter mysql2's falsy-value URI merge.\n delete parsed.uri;\n const explicit = {\n host: options?.host, port: options?.port, user: options?.user,\n password: options?.password, database: options?.database,\n connectionLimit: options?.connectionLimit, charset: options?.charset,\n };\n for (const [key, value] of Object.entries(explicit)) {\n if (value !== undefined) parsed[key] = value;\n }\n if (options?.password !== undefined) delete parsed.password1;\n // Preserve transport flags, but the driver may not disable matched-row counts\n // or enable multi-statements behind the explicit adapter opt-in.\n const flags = (Array.isArray(parsed.flags) ? parsed.flags : String(parsed.flags ?? \"\").split(/\\s*,+\\s*/))\n .map((flag: unknown) => String(flag).toUpperCase())\n .filter((flag: string) => ![\"-FOUND_ROWS\", \"MULTI_STATEMENTS\", \"-MULTI_STATEMENTS\"].includes(flag));\n return {\n ...parsed,\n timezone: options?.timezone ?? \"Z\",\n decimalNumbers: false,\n supportBigNumbers: true,\n bigNumberStrings: true,\n dateStrings: false,\n jsonStrings: false,\n namedPlaceholders: false,\n rowsAsArray: false,\n nestTables: undefined,\n typeCast,\n flags,\n multipleStatements: options?.multipleStatements ?? false,\n };\n}\n",
|
|
8
|
+
"/**\n * Driver-error mapping for mysql2.\n *\n * Constitution rule 5: a raw driver error never escapes an adapter. Every\n * failure becomes a `VibeError` with a stable code, the driver error attached\n * as `cause`, and the MySQL errno / symbolic code / SQLSTATE / server message\n * in `meta`.\n *\n * mysql2 errors carry `errno` (the numeric MySQL server error, e.g. 1062),\n * `code` (the symbolic name, `ER_DUP_ENTRY`, or a client-side string like\n * `ECONNREFUSED` / `PROTOCOL_CONNECTION_LOST`), `sqlState` and `sqlMessage`.\n * The table is keyed by `errno` because it is the stable server-side identity;\n * client-side failures have no errno and fall through to `VIBE_ADAPTER`.\n */\n\nimport { VibeError, type VibeErrorCode } from \"@vibeorm/schema\";\n\n// ─── Errno table ──────────────────────────────────────────────────\n\n/**\n * MySQL server errno → stable VibeError code. Frozen and mirrored by tests;\n * anything absent from this table maps to `VIBE_ADAPTER` — including access\n * failures (1044 `ER_DBACCESS_DENIED_ERROR`, 1045 `ER_ACCESS_DENIED_ERROR`)\n * and every client-side connection error (`ECONNREFUSED`,\n * `PROTOCOL_CONNECTION_LOST`, `ETIMEDOUT`), which carry no errno at all.\n */\nexport const MYSQL_ERRNO_ERROR_CODES: Readonly<Record<number, VibeErrorCode>> = Object.freeze({\n /** ER_DUP_ENTRY */\n 1062: \"VIBE_UNIQUE_VIOLATION\",\n /** ER_DUP_ENTRY_WITH_KEY_NAME */\n 1586: \"VIBE_UNIQUE_VIOLATION\",\n /** ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO */\n 1761: \"VIBE_UNIQUE_VIOLATION\",\n /** ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO */\n 1762: \"VIBE_UNIQUE_VIOLATION\",\n /** ER_NO_REFERENCED_ROW */\n 1216: \"VIBE_FK_VIOLATION\",\n /** ER_ROW_IS_REFERENCED */\n 1217: \"VIBE_FK_VIOLATION\",\n /** ER_ROW_IS_REFERENCED_2 */\n 1451: \"VIBE_FK_VIOLATION\",\n /** ER_NO_REFERENCED_ROW_2 */\n 1452: \"VIBE_FK_VIOLATION\",\n /** ER_BAD_NULL_ERROR — NOT NULL column set to NULL */\n 1048: \"VIBE_VALIDATION\",\n /** ER_WARN_DATA_OUT_OF_RANGE — value out of column range */\n 1264: \"VIBE_VALIDATION\",\n /** ER_NO_DEFAULT_FOR_FIELD — column without default omitted */\n 1364: \"VIBE_VALIDATION\",\n /** ER_DATA_TOO_LONG */\n 1406: \"VIBE_VALIDATION\",\n /**\n * WARN_DATA_TRUNCATED — despite the WARN_ name, strict mode raises it as a\n * hard error: an out-of-range ENUM value or a truncated numeric string\n * (live-verified on 8.4: `role = \"SUPERUSER\"` and `n = \"12abc\"` → 1265).\n * The same bad input is a CHECK violation on sqlite and SQLSTATE 22P02 on\n * postgres — all VIBE_VALIDATION (board #9).\n */\n 1265: \"VIBE_VALIDATION\",\n /**\n * ER_TRUNCATED_WRONG_VALUE_FOR_FIELD — a wrong-TYPED value for the column\n * (live-verified on 8.4: `\"abc\"` into INT, `\"12.x9\"` into DECIMAL → 1366).\n */\n 1366: \"VIBE_VALIDATION\",\n /**\n * ER_TRUNCATED_WRONG_VALUE — an unparseable literal, e.g. a bad datetime\n * (live-verified on 8.4: `\"not-a-date\"` into DATETIME(3) → 1292,\n * SQLSTATE 22007).\n */\n 1292: \"VIBE_VALIDATION\",\n /** ER_CHECK_CONSTRAINT_VIOLATED */\n 3819: \"VIBE_VALIDATION\",\n /** ER_LOCK_DEADLOCK */\n 1213: \"VIBE_TRANSACTION\",\n /**\n * ER_TRANSACTION_ROLLBACK_DURING_COMMIT (SQLSTATE 40000) — \"Plugin instructed\n * the server to rollback the current transaction\": with Group Replication,\n * the transaction failed certification at COMMIT and was rolled back.\n */\n 3101: \"VIBE_TRANSACTION\",\n /**\n * ER_LOCK_WAIT_TIMEOUT — `innodb_lock_wait_timeout` expired while waiting for\n * a row lock. This is MySQL's spelling of PostgreSQL's `lock_timeout` case,\n * which is SQLSTATE 55P03 there, so it carries the same VibeORM code: a\n * caller asking \"was the row locked?\" must branch identically on both\n * engines. (Before EPIC 5 it was VIBE_TRANSACTION with reason \"timeout\",\n * which read the same as a STATEMENT timeout — a different failure.)\n */\n 1205: \"VIBE_LOCK_NOT_AVAILABLE\",\n /**\n * ER_LOCK_NOWAIT — \"Statement aborted because lock(s) could not be acquired\n * immediately and NOWAIT is set\" (verified on mysql 26.7.0, SQLSTATE HY000).\n */\n 3572: \"VIBE_LOCK_NOT_AVAILABLE\",\n /** ER_QUERY_TIMEOUT — max_execution_time exceeded, statement interrupted */\n 3024: \"VIBE_TRANSACTION\",\n /**\n * ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION — a write inside a `START\n * TRANSACTION READ ONLY` transaction (`accessMode: \"readOnly\"`). Same code\n * and reason as PostgreSQL's SQLSTATE 25006.\n */\n 1792: \"VIBE_TRANSACTION\",\n});\n\n/** Errnos that additionally explain themselves through `meta.reason`. */\nexport const MYSQL_ERRNO_REASONS: Readonly<Record<number, string>> = Object.freeze({\n /** ER_LOCK_DEADLOCK */\n 1213: \"deadlock\",\n /**\n * ER_TRANSACTION_ROLLBACK_DURING_COMMIT — Group Replication certification\n * found a conflicting write and rolled the transaction back at COMMIT: the\n * same retryable situation PostgreSQL reports as 40001 at COMMIT, so the same\n * reason word (docs/queries.md lists the retryable reasons).\n */\n 3101: \"serialization-failure\",\n /** ER_LOCK_WAIT_TIMEOUT — the wait for a row lock ran out. */\n 1205: \"lock-not-available\",\n /** ER_LOCK_NOWAIT — the row was locked and the caller asked not to wait. */\n 3572: \"lock-not-available\",\n /** ER_QUERY_TIMEOUT */\n 3024: \"timeout\",\n /** ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION */\n 1792: \"read-only-transaction\",\n});\n\n/**\n * Errnos the MySQL 8.4 server error reference documents as \"the WHOLE\n * transaction was rolled back\". A COMMIT the server answers with one of these\n * did not commit. Every other COMMIT error proves nothing and stays `unknown`:\n * 1205 ER_LOCK_WAIT_TIMEOUT rolls back only the statement by default (\"not the entire\n * transaction\"), and 1180 ER_ERROR_DURING_COMMIT / 3100 ER_RUN_HOOK_ERROR say\n * nothing about a rollback. Frozen and mirrored by tests.\n *\n * - 1213 ER_LOCK_DEADLOCK: \"a transaction encounters a deadlock and is\n * automatically rolled back\".\n * - 3101 ER_TRANSACTION_ROLLBACK_DURING_COMMIT: \"a transaction failed the group\n * certification process […] and was thus rolled back\".\n */\nexport const MYSQL_ROLLED_BACK_ERRNOS: readonly number[] = Object.freeze([1213, 3101]);\n\n// ─── Reading driver errors ────────────────────────────────────────\n\nfunction readStringField(params: { source: Record<string, unknown>; key: string }): string | undefined {\n const value = params.source[params.key];\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\n/**\n * Extract the numeric MySQL errno from a mysql2 error. Client-side failures\n * (`ECONNREFUSED`, `PROTOCOL_CONNECTION_LOST`, …) have no numeric errno and\n * yield `undefined`.\n */\nexport function mysqlErrorErrno(params: { error: unknown }): number | undefined {\n const { error } = params;\n if (error === null || typeof error !== \"object\") return undefined;\n const errno = (error as Record<string, unknown>).errno;\n return typeof errno === \"number\" && Number.isInteger(errno) ? errno : undefined;\n}\n\n// ─── Mapping ──────────────────────────────────────────────────────\n\n/**\n * Map any error thrown by mysql2 onto a `VibeError`.\n *\n * A `VibeError` passes through unchanged, so an error raised deeper inside the\n * ORM (or by a nested adapter call) is never re-wrapped, and a user callback's\n * error is rethrown identically.\n */\nexport function mapMysqlDriverError(params: { error: unknown }): VibeError {\n const { error } = params;\n if (error instanceof VibeError) return error;\n\n const source: Record<string, unknown> =\n error !== null && typeof error === \"object\" ? (error as Record<string, unknown>) : {};\n const errno = mysqlErrorErrno({ error });\n const code: VibeErrorCode =\n (errno === undefined ? undefined : MYSQL_ERRNO_ERROR_CODES[errno]) ?? \"VIBE_ADAPTER\";\n\n const meta: Record<string, unknown> = {};\n if (errno !== undefined) meta.errno = errno;\n const symbolicCode = readStringField({ source, key: \"code\" });\n if (symbolicCode !== undefined) meta.code = symbolicCode;\n const sqlState = readStringField({ source, key: \"sqlState\" });\n if (sqlState !== undefined) meta.sqlState = sqlState;\n const sqlMessage = readStringField({ source, key: \"sqlMessage\" });\n if (sqlMessage !== undefined) meta.sqlMessage = sqlMessage.trim();\n const reason = errno === undefined ? undefined : MYSQL_ERRNO_REASONS[errno];\n if (reason !== undefined) meta.reason = reason;\n\n const message =\n readStringField({ source, key: \"message\" }) ??\n (sqlMessage !== undefined ? sqlMessage.trim() : undefined) ??\n (typeof error === \"string\" ? error : \"unknown mysql driver error\");\n\n return new VibeError({ code, message, meta, cause: error });\n}\n\n/** Run a driver call, mapping anything it throws onto a `VibeError`. */\nexport async function runMapped<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n throw mapMysqlDriverError({ error });\n }\n}\n",
|
|
9
9
|
"/**\n * Raw-path `?` placeholder analysis for mysql2's PREPARED protocol.\n *\n * WHY THIS EXISTS. F01 moved raw calls that carry parameters off mysql2's text\n * protocol (which interpolates values client-side and cannot know the server's\n * `sql_mode`) onto its prepared protocol. The prepared protocol types a JS\n * **number** in a way the server refuses in a ROW-COUNT position:\n *\n * execute(\"SELECT 1 LIMIT ?\", [2]) → errno 1210 ER_WRONG_ARGUMENTS\n * execute(\"SELECT 1 LIMIT ?\", [\"2\"]) → OK\n * execute(\"SELECT ? AS a\", [2]) → OK\n *\n * so the ONE narrow repair is: bind a row-count placeholder's integer as its\n * decimal TEXT, and leave every other binding byte-for-byte as it was.\n * Stringifying an integer at a `LIMIT`/`OFFSET` position is lossless — MySQL\n * parses it back to the same unsigned integer — while stringifying anywhere\n * else would change the wire type of ordinary comparisons.\n *\n * The ORM never emits `LIMIT ?` (the renderer inlines its limits as literal\n * text), so this only ever fires for user-written `$queryRaw` /\n * `$queryRawUnsafe` / `$executeRaw*`.\n *\n * SCANNING IS CONSERVATIVE. Finding row-count placeholders means finding the\n * REAL `?` tokens first, so the scanner skips string literals, backtick-quoted\n * identifiers and all three MySQL comment forms. Two self-checks keep a\n * mis-scan from ever mis-binding: the placeholder count must match the\n * parameter count, and only placeholders in a row-count position are touched.\n * When either check fails the values pass through EXACTLY as they do today.\n *\n * Known scanner limits, all of which fail into that pass-through:\n * - `NO_BACKSLASH_ESCAPES`: a backslash is treated as an escape here, so under\n * that mode a literal ending in `\\` can be mis-measured. The count check then\n * disagrees and nothing is transformed.\n * - `/*! … *\\/` executable comments are skipped like ordinary comments, so a\n * placeholder inside one is not counted — again a count mismatch.\n */\n\nimport { VibeError } from \"@vibeorm/schema\";\n\n/** Where the real `?` placeholders are, and which of them are row counts. */\nexport type ScannedPlaceholders = {\n /** How many real placeholders the statement has. */\n readonly count: number;\n /** 0-based ordinals of the placeholders governed by `LIMIT` / `OFFSET`. */\n readonly rowCountPositions: ReadonlySet<number>;\n};\n\n/** Cheap pre-filter: no row-count clause is possible without one of these words. */\nconst ROW_COUNT_HINT = /\\b(?:limit|offset)\\b/i;\n\nfunction isIdentChar(char: string | undefined): boolean {\n return char !== undefined && /[A-Za-z0-9_$]/.test(char);\n}\n\n/**\n * Index just past a quoted run starting at `start` — `'…'`, `\"…\"` or\n * `` `…` ``. A doubled quote continues the run (MySQL's own escape) and a\n * backslash escapes the next character (MySQL's default mode).\n */\nfunction skipQuoted(text: string, start: number, quote: string): number {\n let index = start + 1;\n while (index < text.length) {\n const char = text[index];\n if (char === \"\\\\\") {\n index += 2;\n continue;\n }\n if (char === quote) {\n if (text[index + 1] === quote) {\n index += 2;\n continue;\n }\n return index + 1;\n }\n index += 1;\n }\n return text.length; // unterminated — the driver reports it, not this scanner\n}\n\n/** Index just past a line comment (`-- ` or `#`). */\nfunction skipLineComment(text: string, start: number): number {\n const newline = text.indexOf(\"\\n\", start);\n return newline === -1 ? text.length : newline + 1;\n}\n\n/** Index just past a block comment. MySQL does not nest them. */\nfunction skipBlockComment(text: string, start: number): number {\n const close = text.indexOf(\"*/\", start + 2);\n return close === -1 ? text.length : close + 2;\n}\n\n/**\n * Scan a statement for its real `?` placeholders, marking the ones a `LIMIT` or\n * `OFFSET` keyword governs.\n *\n * The row-count context opens on the word `LIMIT` or `OFFSET` and survives only\n * whitespace, comments, commas, integer literals and further placeholders —\n * exactly the tokens MySQL's `LIMIT {[offset,] count | count OFFSET offset}`\n * grammar allows. Any other word or symbol closes it, so `?` anywhere else is\n * left alone.\n */\nexport function scanPlaceholders(params: { text: string }): ScannedPlaceholders {\n const { text } = params;\n const rowCountPositions = new Set<number>();\n let count = 0;\n let inRowCount = false;\n let index = 0;\n\n while (index < text.length) {\n const char = text[index] as string;\n\n if (char === \"'\" || char === '\"' || char === \"`\") {\n index = skipQuoted(text, index, char);\n inRowCount = false;\n continue;\n }\n // `--` is a comment only when whitespace follows it (MySQL, unlike others).\n if (char === \"-\" && text[index + 1] === \"-\" && (text[index + 2] === undefined || /\\s/.test(text[index + 2] as string))) {\n index = skipLineComment(text, index);\n continue;\n }\n if (char === \"#\") {\n index = skipLineComment(text, index);\n continue;\n }\n if (char === \"/\" && text[index + 1] === \"*\") {\n index = skipBlockComment(text, index);\n continue;\n }\n if (char === \"?\") {\n if (inRowCount) rowCountPositions.add(count);\n count += 1;\n index += 1;\n continue;\n }\n // Whitespace and commas carry the context across `LIMIT ?, ?`.\n if (/\\s/.test(char) || char === \",\") {\n index += 1;\n continue;\n }\n // An integer literal is a legal row count — the context survives it.\n if (/[0-9]/.test(char)) {\n while (index < text.length && /[0-9]/.test(text[index] as string)) index += 1;\n continue;\n }\n if (/[A-Za-z_$]/.test(char)) {\n const start = index;\n while (isIdentChar(text[index])) index += 1;\n const word = text.slice(start, index).toUpperCase();\n inRowCount = word === \"LIMIT\" || word === \"OFFSET\";\n continue;\n }\n inRowCount = false;\n index += 1;\n }\n\n return { count, rowCountPositions };\n}\n\n/**\n * A row count as mysql2's prepared protocol will accept it: the integer's\n * decimal text.\n *\n * A number that is not a non-negative safe integer is REFUSED with a typed\n * error rather than rounded or guessed — `LIMIT 1.5` has no meaning, and a\n * value past `Number.MAX_SAFE_INTEGER` has already lost digits before this\n * function can see it. A `bigint` of any size converts losslessly, so it is\n * accepted whenever it is non-negative. Every other type (strings, `null`,\n * `undefined`) passes through untouched: mysql2 already sends those verbatim,\n * and MySQL's own error names anything it dislikes.\n */\nfunction toRowCount(params: { value: unknown; ordinal: number; text: string }): unknown {\n const { value, ordinal, text } = params;\n const refuse = (reason: string): never => {\n throw new VibeError({\n code: \"VIBE_VALIDATION\",\n message:\n `parameter $${ordinal} sits in a LIMIT/OFFSET position and ${reason} — ` +\n \"a row count must be a non-negative integer\",\n meta: { placeholder: ordinal, value: String(value), text },\n });\n };\n if (typeof value === \"number\") {\n if (!Number.isSafeInteger(value)) return refuse(\"is not a safe integer\");\n if (value < 0) return refuse(\"is negative\");\n return String(value);\n }\n if (typeof value === \"bigint\") {\n if (value < 0n) return refuse(\"is negative\");\n return value.toString();\n }\n return value;\n}\n\n/**\n * The parameter list to hand mysql2's prepared protocol: identical to the one\n * passed in, except that integers in a `LIMIT` / `OFFSET` position become their\n * decimal text.\n *\n * Returns the SAME array when nothing needs changing, so the ORM's own\n * affected-row path — which never emits a row-count placeholder — pays only a\n * word test.\n */\nexport function bindRowCountParams(params: { text: string; values: unknown[] }): unknown[] {\n const { text, values } = params;\n if (values.length === 0) return values;\n if (!values.some((value) => typeof value === \"number\" || typeof value === \"bigint\")) return values;\n if (!ROW_COUNT_HINT.test(text)) return values;\n\n const scanned = scanPlaceholders({ text });\n // Self-check: an unparsed shape must never shift a binding.\n if (scanned.rowCountPositions.size === 0 || scanned.count !== values.length) return values;\n\n return values.map((value, index) =>\n scanned.rowCountPositions.has(index) ? toRowCount({ value, ordinal: index + 1, text }) : value,\n );\n}\n",
|
|
10
10
|
"/**\n * Result normalization for mysql2.\n *\n * mysql2 resolves `execute()` / `query()` with a `[result, fields]` tuple where\n * `result` is one of:\n * - `RowDataPacket[]` — a SELECT's rows (plain objects; `rowsAsArray` is off);\n * - `ResultSetHeader` — an INSERT / UPDATE / DELETE / DDL OK-packet carrying\n * `affectedRows` and `insertId`;\n * - an array of the above — only when `multipleStatements` is enabled, one\n * entry per statement.\n *\n * The adapter's contract: `execute` returns rows (a header normalizes to `[]`);\n * `executeUnsafe` returns `{ rows, affectedRows }` (a SELECT has\n * `affectedRows: 0`, a mutation has `rows: []`). With `multipleStatements`\n * enabled the LAST statement's result wins, mirroring adapter-pglite's `exec`.\n */\n\nimport type { QueryResult } from \"@vibeorm/runtime\";\n\n// ─── Header detection ─────────────────────────────────────────────\n\n/**\n * True when a driver result value is shaped like mysql2's `ResultSetHeader`\n * (an OK-packet). This shape check is only sound at a driver-result boundary,\n * never for members of a SELECT's row array; those can have any column names.\n */\nexport function isResultSetHeader(params: { value: unknown }): boolean {\n const { value } = params;\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) return false;\n const source = value as Record<string, unknown>;\n return typeof source.affectedRows === \"number\" && typeof source.serverStatus === \"number\";\n}\n\n// ─── Normalization ────────────────────────────────────────────────\n\n/** One result set (never a multi-statement array) → the adapter contract. */\nfunction normalizeSingle(value: unknown): QueryResult {\n if (Array.isArray(value)) {\n return { rows: value as Record<string, unknown>[], affectedRows: 0 };\n }\n if (isResultSetHeader({ value })) {\n const header = value as { affectedRows: number; insertId?: unknown };\n const insertId = header.insertId;\n // mysql2 uses zero for OK packets without an auto-generated identity.\n // Keep that sentinel absent so callers retain their last-id fallback.\n const hasIdentity = (typeof insertId === \"number\" && Number.isSafeInteger(insertId) && insertId !== 0) ||\n (typeof insertId === \"string\" && /^-?\\d+$/.test(insertId) && !/^-?0+$/.test(insertId));\n return { rows: [], affectedRows: header.affectedRows, ...(hasIdentity ? { insertId: insertId as number | string } : {}) };\n }\n return { rows: [], affectedRows: 0 };\n}\n\n/**\n * Normalize mysql2's result and field metadata. Multi-statement arrays collapse\n * to their LAST statement's result; field metadata distinguishes headers from\n * legal SELECT rows with header-like aliases.\n */\nexport function normalizeDriverResult(params: { result: unknown; fields?: unknown }): QueryResult {\n const { result, fields } = params;\n if (Array.isArray(result)) {\n // mysql2 supplies a parallel fields array for multiple results: each entry\n // is a field list for a SELECT, or undefined for an OK packet. A single\n // SELECT has a flat field list, regardless of its user-chosen column names.\n const multiple = Array.isArray(fields)\n ? fields.some((field: unknown) => field === undefined || Array.isArray(field))\n : result.some((value: unknown) => Array.isArray(value));\n if (multiple) return normalizeSingle(result.at(-1));\n // A plain result set: row objects (or an empty SELECT).\n return { rows: result as Record<string, unknown>[], affectedRows: 0 };\n }\n return normalizeSingle(result);\n}\n",
|
|
11
|
-
"/**\n * Transaction-control SQL text (mysql dialect).\n *\n * Kept apart from the adapter so the mapping from `TransactionOptions` to SQL\n * is unit-testable without a server, and so the timeout value is validated\n * before it is ever interpolated into a statement.\n *\n * MySQL specifics:\n * - `SET TRANSACTION ISOLATION LEVEL <level>` applies to the NEXT transaction\n * started in the session, so the adapter issues it BEFORE\n * `conn.beginTransaction()` — never inside the open transaction.\n * - MySQL has no general per-transaction statement timeout.\n * `MAX_EXECUTION_TIME` is the closest tool and it bounds **SELECT statements\n * only** — see {@link maxExecutionTimeStatement}.\n */\n\nimport type { IsolationLevel, TransactionOptions } from \"@vibeorm/runtime\";\nimport { VibeError } from \"@vibeorm/schema\";\n\n/** VibeORM isolation level → MySQL isolation level keyword. */\nexport const ISOLATION_LEVEL_SQL: Readonly<Record<IsolationLevel, string>> = Object.freeze({\n ReadCommitted: \"READ COMMITTED\",\n RepeatableRead: \"REPEATABLE READ\",\n Serializable: \"SERIALIZABLE\",\n});\n\n/**\n * `SET TRANSACTION ISOLATION LEVEL <level>` — scoped to the next transaction\n * in the session, which is why the adapter sends it before\n * `conn.beginTransaction()` on the pinned connection.\n *\n * Observability trap (verified live on MySQL 8.4): the one-shot value IS\n * applied to the next transaction — `performance_schema.\n * events_transactions_current` reports the requested level — but\n * `@@transaction_isolation` NEVER reflects it; that variable keeps answering\n * the session value both before and inside the transaction. Tests must assert\n * the level's behavior (e.g. SERIALIZABLE turning plain SELECTs into locking\n * reads), not the variable — see tests/live.test.ts.\n */\nexport function setIsolationLevelStatement(params: { isolationLevel: IsolationLevel }): string {\n return `SET TRANSACTION ISOLATION LEVEL ${ISOLATION_LEVEL_SQL[params.isolationLevel]}`;\n}\n\n/**\n * `SET SESSION MAX_EXECUTION_TIME = <ms>` — the closest MySQL gets to a\n * transaction timeout, and the semantics differ LOUDLY from postgres:\n *\n * **`MAX_EXECUTION_TIME` bounds SELECT statements only.** INSERT / UPDATE /\n * DELETE / DDL inside the transaction run unbounded; MySQL simply has no\n * per-statement timeout for mutations. An over-long SELECT is interrupted with\n * errno 3024 (`ER_QUERY_TIMEOUT`), mapped to `VIBE_TRANSACTION` with\n * `meta.reason = \"timeout\"`. The setting is session-scoped (not\n * transaction-scoped), so the adapter resets it to DEFAULT in `finally` before\n * the connection returns to the pool.\n *\n * One more caveat (verified live on MySQL 8.4): `SELECT SLEEP(n)` cannot\n * observe the bound — an interrupted `SLEEP()` swallows the kill and returns\n * `1` with NO error, so the statement comes back \"successfully\" at ~timeout.\n * Only a SELECT doing real work is cancelled with errno 3024.\n *\n * @throws VibeError `VIBE_VALIDATION` when the timeout is not a non-negative\n * integer — the value is interpolated into SQL, so it is never trusted blindly.\n */\nexport function maxExecutionTimeStatement(params: { timeout: number }): string {\n const { timeout } = params;\n if (!Number.isInteger(timeout) || timeout < 0) {\n throw new VibeError({\n code: \"VIBE_VALIDATION\",\n message: `transaction timeout must be a non-negative integer of milliseconds, received ${String(timeout)}`,\n meta: { timeout },\n });\n }\n return `SET SESSION MAX_EXECUTION_TIME = ${timeout}`;\n}\n\n/**\n * Restores the session default after a transaction that set a timeout. Issued\n * in `finally`; if it fails the adapter destroys the connection instead of\n * releasing it, so a poisoned session never returns to the pool.\n */\nexport const RESET_MAX_EXECUTION_TIME_SQL: string = \"SET SESSION MAX_EXECUTION_TIME = DEFAULT\";\n\n// ─── Raw transaction control (session affinity) ─────────────────\n\n/** How a raw statement steers the adapter's session-affine raw transaction. */\nexport type RawTransactionControl = \"open\" | \"close\" | null;\n\nconst RAW_OPEN_PATTERN: RegExp = /^\\s*(?:begin|start\\s+transaction)\\b[^;]*;?\\s*$/i;\nconst RAW_CLOSE_PATTERN: RegExp = /^\\s*(?:commit|rollback)(?:\\s+work)?\\s*;?\\s*$/i;\n\n/**\n * Classify a raw statement as transaction control. A raw `BEGIN` … `COMMIT`\n * sequence over `executeUnsafe` is sound only when every statement in between\n * rides the SAME pooled connection, so the adapter pins one connection for\n * the whole raw transaction (\"open\" checks out, \"close\" releases). MySQL DDL\n * auto-commits, so @vibeorm/migrate never wraps here — this exists for raw\n * user sequences and keeps the three pool adapters' semantics identical.\n *\n * Deliberately strict: only PURE single-statement control text matches.\n * Compound scripts, `ROLLBACK TO SAVEPOINT` and `COMMIT AND CHAIN` (which\n * keeps a transaction open) never engage the pinning.\n */\nexport function classifyRawTransactionControl(params: { text: string }): RawTransactionControl {\n if (RAW_OPEN_PATTERN.test(params.text)) return \"open\";\n if (RAW_CLOSE_PATTERN.test(params.text)) return \"close\";\n return null;\n}\n\n// ─── Nested transaction options (the cross-adapter contract) ──────\n\n// ONE copy, shared by every adapter through the runtime's adapter-kit;\n// re-exported here so this adapter's public surface is unchanged.\nexport { refuseNestedTransactionOptions } from \"@vibeorm/runtime/adapter-kit\";\n"
|
|
11
|
+
"/**\n * Transaction-control SQL text (mysql dialect).\n *\n * Kept apart from the adapter so the mapping from `TransactionOptions` to SQL\n * is unit-testable without a server, and so the timeout value is validated\n * before it is ever interpolated into a statement.\n *\n * MySQL specifics:\n * - `SET TRANSACTION ISOLATION LEVEL <level>` applies to the NEXT transaction\n * started in the session, so the adapter issues it BEFORE\n * `conn.beginTransaction()` — never inside the open transaction.\n * - MySQL has no general per-transaction statement timeout.\n * `MAX_EXECUTION_TIME` is the closest tool and it bounds **SELECT statements\n * only** — see {@link maxExecutionTimeStatement}.\n */\n\nimport type { IsolationLevel, TransactionOptions } from \"@vibeorm/runtime\";\nimport { VibeError } from \"@vibeorm/schema\";\n\n/** VibeORM isolation level → MySQL isolation level keyword. */\nexport const ISOLATION_LEVEL_SQL: Readonly<Record<IsolationLevel, string>> = Object.freeze({\n ReadCommitted: \"READ COMMITTED\",\n RepeatableRead: \"REPEATABLE READ\",\n Serializable: \"SERIALIZABLE\",\n});\n\n/**\n * `SET TRANSACTION ISOLATION LEVEL <level>` — scoped to the next transaction\n * in the session, which is why the adapter sends it before\n * `conn.beginTransaction()` on the pinned connection.\n *\n * Observability trap (verified live on MySQL 8.4): the one-shot value IS\n * applied to the next transaction — `performance_schema.\n * events_transactions_current` reports the requested level — but\n * `@@transaction_isolation` NEVER reflects it; that variable keeps answering\n * the session value both before and inside the transaction. Tests must assert\n * the level's behavior (e.g. SERIALIZABLE turning plain SELECTs into locking\n * reads), not the variable — see tests/live.test.ts.\n */\nexport function setIsolationLevelStatement(params: { isolationLevel: IsolationLevel }): string {\n return `SET TRANSACTION ISOLATION LEVEL ${ISOLATION_LEVEL_SQL[params.isolationLevel]}`;\n}\n\n/**\n * `SET SESSION MAX_EXECUTION_TIME = <ms>` — the closest MySQL gets to a\n * transaction timeout, and the semantics differ LOUDLY from postgres:\n *\n * **`MAX_EXECUTION_TIME` bounds SELECT statements only.** INSERT / UPDATE /\n * DELETE / DDL inside the transaction run unbounded; MySQL simply has no\n * per-statement timeout for mutations. An over-long SELECT is interrupted with\n * errno 3024 (`ER_QUERY_TIMEOUT`), mapped to `VIBE_TRANSACTION` with\n * `meta.reason = \"timeout\"`. The setting is session-scoped (not\n * transaction-scoped), so the adapter resets it to DEFAULT in `finally` before\n * the connection returns to the pool.\n *\n * One more caveat (verified live on MySQL 8.4): `SELECT SLEEP(n)` cannot\n * observe the bound — an interrupted `SLEEP()` swallows the kill and returns\n * `1` with NO error, so the statement comes back \"successfully\" at ~timeout.\n * Only a SELECT doing real work is cancelled with errno 3024.\n *\n * @throws VibeError `VIBE_VALIDATION` when the timeout is not a non-negative\n * integer — the value is interpolated into SQL, so it is never trusted blindly.\n */\nexport function maxExecutionTimeStatement(params: { timeout: number }): string {\n const { timeout } = params;\n if (!Number.isInteger(timeout) || timeout < 0) {\n throw new VibeError({\n code: \"VIBE_VALIDATION\",\n message: `transaction timeout must be a non-negative integer of milliseconds, received ${String(timeout)}`,\n meta: { timeout },\n });\n }\n return `SET SESSION MAX_EXECUTION_TIME = ${timeout}`;\n}\n\n/** VibeORM isolation level → the value spelling of MySQL's `transaction_isolation` variable. */\nconst ISOLATION_LEVEL_VALUE: Readonly<Record<IsolationLevel, string>> = Object.freeze({\n ReadCommitted: \"READ-COMMITTED\",\n RepeatableRead: \"REPEATABLE-READ\",\n Serializable: \"SERIALIZABLE\",\n});\n\n/**\n * Round-trip EPIC 3 (A-06a): the timeout AND the isolation level in ONE `SET`\n * — `SET @@SESSION.max_execution_time = N, @@transaction_isolation = '…'` —\n * one wait instead of two. Used only when both options are set.\n *\n * Scope is unchanged: `@@SESSION.max_execution_time` is the same session\n * variable {@link maxExecutionTimeStatement} sets (reset after the transaction\n * as before), and `@@transaction_isolation` WITHOUT a scope modifier applies to\n * the NEXT transaction only — exactly the scope of `SET TRANSACTION ISOLATION\n * LEVEL` (MySQL manual, \"SET TRANSACTION Statement\", scope table; verified\n * live in the round-trip inventory A-06 through\n * `performance_schema.events_transactions_current`).\n *\n * @throws VibeError `VIBE_VALIDATION` for an invalid timeout (same check and\n * message as {@link maxExecutionTimeStatement}).\n */\nexport function sessionOptionsStatement(params: { timeout: number; isolationLevel: IsolationLevel }): string {\n const timeoutText = maxExecutionTimeStatement({ timeout: params.timeout });\n const ms = timeoutText.slice(timeoutText.lastIndexOf(\" \") + 1);\n return `SET @@SESSION.max_execution_time = ${ms}, @@transaction_isolation = '${ISOLATION_LEVEL_VALUE[params.isolationLevel]}'`;\n}\n\n/**\n * `START TRANSACTION READ ONLY` — `accessMode: \"readOnly\"` (Q4). Replaces the\n * driver's `beginTransaction()` (`START TRANSACTION`) only when asked; a write\n * inside raises errno 1792, mapped to `VIBE_TRANSACTION` with\n * `meta.reason = \"read-only-transaction\"`.\n */\nexport const START_TRANSACTION_READ_ONLY_SQL: string = \"START TRANSACTION READ ONLY\";\n\n/**\n * Restores the session default after a transaction that set a timeout. Issued\n * in `finally`; if it fails the adapter destroys the connection instead of\n * releasing it, so a poisoned session never returns to the pool.\n */\nexport const RESET_MAX_EXECUTION_TIME_SQL: string = \"SET SESSION MAX_EXECUTION_TIME = DEFAULT\";\n\n// ─── Raw transaction control (session affinity) ─────────────────\n\n/** How a raw statement steers the adapter's session-affine raw transaction. */\nexport type RawTransactionControl = \"open\" | \"close\" | null;\n\nconst RAW_OPEN_PATTERN: RegExp = /^\\s*(?:begin|start\\s+transaction)\\b[^;]*;?\\s*$/i;\nconst RAW_CLOSE_PATTERN: RegExp = /^\\s*(?:commit|rollback)(?:\\s+work)?\\s*;?\\s*$/i;\n\n/**\n * Classify a raw statement as transaction control. A raw `BEGIN` … `COMMIT`\n * sequence over `executeUnsafe` is sound only when every statement in between\n * rides the SAME pooled connection, so the adapter pins one connection for\n * the whole raw transaction (\"open\" checks out, \"close\" releases). MySQL DDL\n * auto-commits, so @vibeorm/migrate never wraps here — this exists for raw\n * user sequences and keeps the three pool adapters' semantics identical.\n *\n * Deliberately strict: only PURE single-statement control text matches.\n * Compound scripts, `ROLLBACK TO SAVEPOINT` and `COMMIT AND CHAIN` (which\n * keeps a transaction open) never engage the pinning.\n */\nexport function classifyRawTransactionControl(params: { text: string }): RawTransactionControl {\n if (RAW_OPEN_PATTERN.test(params.text)) return \"open\";\n if (RAW_CLOSE_PATTERN.test(params.text)) return \"close\";\n return null;\n}\n\n// ─── Nested transaction options (the cross-adapter contract) ──────\n\n// ONE copy, shared by every adapter through the runtime's adapter-kit;\n// re-exported here so this adapter's public surface is unchanged.\nexport { refuseNestedTransactionOptions } from \"@vibeorm/runtime/adapter-kit\";\n"
|
|
12
12
|
],
|
|
13
|
-
"mappings": "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",
|
|
14
|
-
"debugId": "
|
|
13
|
+
"mappings": "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",
|
|
14
|
+
"debugId": "FADF8CA995993FB064756E2164756E21",
|
|
15
15
|
"names": []
|
|
16
16
|
}
|
|
@@ -55,6 +55,33 @@ export declare function setIsolationLevelStatement(params: {
|
|
|
55
55
|
export declare function maxExecutionTimeStatement(params: {
|
|
56
56
|
timeout: number;
|
|
57
57
|
}): string;
|
|
58
|
+
/**
|
|
59
|
+
* Round-trip EPIC 3 (A-06a): the timeout AND the isolation level in ONE `SET`
|
|
60
|
+
* — `SET @@SESSION.max_execution_time = N, @@transaction_isolation = '…'` —
|
|
61
|
+
* one wait instead of two. Used only when both options are set.
|
|
62
|
+
*
|
|
63
|
+
* Scope is unchanged: `@@SESSION.max_execution_time` is the same session
|
|
64
|
+
* variable {@link maxExecutionTimeStatement} sets (reset after the transaction
|
|
65
|
+
* as before), and `@@transaction_isolation` WITHOUT a scope modifier applies to
|
|
66
|
+
* the NEXT transaction only — exactly the scope of `SET TRANSACTION ISOLATION
|
|
67
|
+
* LEVEL` (MySQL manual, "SET TRANSACTION Statement", scope table; verified
|
|
68
|
+
* live in the round-trip inventory A-06 through
|
|
69
|
+
* `performance_schema.events_transactions_current`).
|
|
70
|
+
*
|
|
71
|
+
* @throws VibeError `VIBE_VALIDATION` for an invalid timeout (same check and
|
|
72
|
+
* message as {@link maxExecutionTimeStatement}).
|
|
73
|
+
*/
|
|
74
|
+
export declare function sessionOptionsStatement(params: {
|
|
75
|
+
timeout: number;
|
|
76
|
+
isolationLevel: IsolationLevel;
|
|
77
|
+
}): string;
|
|
78
|
+
/**
|
|
79
|
+
* `START TRANSACTION READ ONLY` — `accessMode: "readOnly"` (Q4). Replaces the
|
|
80
|
+
* driver's `beginTransaction()` (`START TRANSACTION`) only when asked; a write
|
|
81
|
+
* inside raises errno 1792, mapped to `VIBE_TRANSACTION` with
|
|
82
|
+
* `meta.reason = "read-only-transaction"`.
|
|
83
|
+
*/
|
|
84
|
+
export declare const START_TRANSACTION_READ_ONLY_SQL: string;
|
|
58
85
|
/**
|
|
59
86
|
* Restores the session default after a transaction that set a timeout. Issued
|
|
60
87
|
* in `finally`; if it fails the adapter destroys the connection instead of
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeorm/adapter-mysql",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "mysql2 adapter for VibeORM v2",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"orm",
|
|
@@ -35,15 +35,17 @@
|
|
|
35
35
|
},
|
|
36
36
|
"files": [
|
|
37
37
|
"dist",
|
|
38
|
-
"
|
|
38
|
+
"!dist/**/*.d.ts.map",
|
|
39
|
+
"README.md",
|
|
40
|
+
"LICENSE"
|
|
39
41
|
],
|
|
40
42
|
"engines": {
|
|
41
43
|
"node": ">=18",
|
|
42
44
|
"bun": ">=1.2.0"
|
|
43
45
|
},
|
|
44
46
|
"dependencies": {
|
|
45
|
-
"@vibeorm/runtime": "
|
|
46
|
-
"@vibeorm/schema": "
|
|
47
|
+
"@vibeorm/runtime": "3.0.0",
|
|
48
|
+
"@vibeorm/schema": "3.0.0",
|
|
47
49
|
"mysql2": "^3.15.0"
|
|
48
50
|
},
|
|
49
51
|
"publishConfig": {
|
package/dist/acquire.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"acquire.d.ts","sourceRoot":"","sources":["../src/acquire.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,4DAA4D;AAC5D,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAExD;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,WAAW,CAAC;IAC1D,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAC;CAC/C,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,sBAAsB,EAAE,aAGnC,CAAC;AAEH,iEAAiE;AACjE,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,IAAI,IAAI,CAAC;CACjB,CAAC;AAEF,yDAAyD;AACzD,MAAM,MAAM,aAAa,CAAC,WAAW,SAAS,oBAAoB,IAAI;IACpE,aAAa,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC;CACvC,CAAC;AAIF,8FAA8F;AAC9F,eAAO,MAAM,8BAA8B,EAAE,MAAW,CAAC;AAEzD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAkB/F;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CAAC,WAAW,SAAS,oBAAoB,EAAE,MAAM,EAAE;IACzF,IAAI,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB,GAAG,OAAO,CAAC,WAAW,CAAC,CAiCvB"}
|
package/dist/config.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAMvE,wFAAwF;AACxF,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CAC1C,EAAE,IAAI,EAAE,MAAM,OAAO,KAAK,OAAO,CAAC;AASnC,uFAAuF;AACvF,wBAAgB,eAAe,CAAC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,mBAAmB,CAAA;CAAE,GAAG,eAAe,CAwC1F"}
|
package/dist/errors.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIhE;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAgE1E,CAAC;AAEH,yEAAyE;AACzE,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAS/D,CAAC;AASH;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,GAAG,SAAS,CAK9E;AAID;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,CA2BzE;AAED,wEAAwE;AACxE,wBAAsB,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAMnE"}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"placeholders.d.ts","sourceRoot":"","sources":["../src/placeholders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAIH,6EAA6E;AAC7E,MAAM,MAAM,mBAAmB,GAAG;IAChC,oDAAoD;IACpD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,2EAA2E;IAC3E,QAAQ,CAAC,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACjD,CAAC;AA8CF;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,mBAAmB,CAwD9E;AAqCD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAA;CAAE,GAAG,OAAO,EAAE,CAazF"}
|
package/dist/results.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"results.d.ts","sourceRoot":"","sources":["../src/results.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAIpD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAKrE;AAqBD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,WAAW,CAchG"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"transaction-sql.d.ts","sourceRoot":"","sources":["../src/transaction-sql.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAsB,MAAM,kBAAkB,CAAC;AAG3E,+DAA+D;AAC/D,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAIvE,CAAC;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE;IAAE,cAAc,EAAE,cAAc,CAAA;CAAE,GAAG,MAAM,CAE7F;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAU7E;AAED;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,EAAE,MAAmD,CAAC;AAI/F,+EAA+E;AAC/E,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAK5D;;;;;;;;;;;GAWG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,qBAAqB,CAI7F;AAMD,OAAO,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC"}
|