@rdlabo/workers-hono-kit 0.11.1 → 0.12.0-beta.pr48.sha371f5792ce8a
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/README.md +73 -37
- package/dist/aws/sts.d.ts +2 -2
- package/dist/aws/sts.js +4 -4
- package/dist/business-time/index.d.ts +68 -122
- package/dist/business-time/index.js +55 -222
- package/dist/container/middleware.d.ts +1 -2
- package/dist/container/middleware.js +1 -1
- package/dist/db/index.d.ts +95 -20
- package/dist/db/index.js +56 -15
- package/dist/db/payment-failed.d.ts +1 -1
- package/dist/db/payment-failed.js +1 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.js +0 -3
- package/dist/mysql/index.d.ts +9 -0
- package/dist/mysql/index.js +8 -0
- package/dist/testing/auth.d.ts +1 -1
- package/dist/testing/db.d.ts +19 -106
- package/dist/testing/db.js +3 -95
- package/dist/testing/fakes.d.ts +15 -97
- package/dist/testing/fakes.js +12 -104
- package/dist/testing/index.d.ts +8 -3
- package/dist/testing/index.js +8 -2
- package/docs/api-business-time.md +47 -30
- package/docs/api-db.md +48 -29
- package/docs/api-offline.md +11 -15
- package/docs/api-root.md +64 -58
- package/docs/api-testing.md +41 -13
- package/docs/api.md +35 -12
- package/docs/cli.md +11 -7
- package/docs/data-layer.md +78 -6
- package/docs/development.md +125 -5
- package/docs/http-auth.md +15 -0
- package/docs/realtime-offline.md +15 -0
- package/docs/role-policies.md +4 -4
- package/docs/testing-operations.md +25 -2
- package/package.json +24 -18
- package/scripts/db-baseline.mjs +3 -68
- package/scripts/workspace-package-smoke.mjs +206 -0
- package/dist/business-time/types.d.ts +0 -9
- package/dist/business-time/types.js +0 -5
- package/dist/db/columns.d.ts +0 -38
- package/dist/db/columns.js +0 -38
- package/dist/db/connection.d.ts +0 -74
- package/dist/db/connection.js +0 -67
- package/dist/db/database.d.ts +0 -222
- package/dist/db/database.js +0 -146
- package/dist/db/jst.d.ts +0 -45
- package/dist/db/jst.js +0 -47
- package/dist/db/migrate.d.ts +0 -51
- package/dist/db/migrate.js +0 -109
- package/dist/db/orm-config.d.ts +0 -127
- package/dist/db/orm-config.js +0 -122
- package/dist/db/retry.d.ts +0 -28
- package/dist/db/retry.js +0 -44
- package/dist/db/write-result.d.ts +0 -39
- package/dist/db/write-result.js +0 -34
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { join, resolve } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
const root = resolve(fileURLToPath(new URL('../../..', import.meta.url)));
|
|
8
|
+
const temporaryDirectory = mkdtempSync(join(tmpdir(), 'workers-workspace-smoke-'));
|
|
9
|
+
const commandEnvironment = {
|
|
10
|
+
...process.env,
|
|
11
|
+
npm_config_cache: join(temporaryDirectory, 'npm-cache'),
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
function pack(workspace) {
|
|
15
|
+
const args = ['pack', '--json', '--pack-destination', temporaryDirectory, '--workspace', workspace];
|
|
16
|
+
const result = JSON.parse(
|
|
17
|
+
execFileSync('npm', args, {
|
|
18
|
+
cwd: root,
|
|
19
|
+
encoding: 'utf8',
|
|
20
|
+
env: commandEnvironment,
|
|
21
|
+
}),
|
|
22
|
+
);
|
|
23
|
+
return join(temporaryDirectory, result[0].filename);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const timezoneTarball = pack('@rdlabo/workers-timezone');
|
|
28
|
+
const mysqlTarball = pack('@rdlabo/workers-mysql');
|
|
29
|
+
const kitTarball = pack('@rdlabo/workers-hono-kit');
|
|
30
|
+
const rootConsumer = join(temporaryDirectory, 'root-consumer');
|
|
31
|
+
mkdirSync(rootConsumer);
|
|
32
|
+
writeFileSync(join(rootConsumer, 'package.json'), '{"private":true,"type":"module"}\n');
|
|
33
|
+
execFileSync('npm', ['install', '--ignore-scripts', kitTarball, 'ai-gateway-provider@^3.1.0'], {
|
|
34
|
+
cwd: rootConsumer,
|
|
35
|
+
stdio: 'inherit',
|
|
36
|
+
env: commandEnvironment,
|
|
37
|
+
});
|
|
38
|
+
if (existsSync(join(rootConsumer, 'node_modules', '@rdlabo', 'workers-timezone'))) {
|
|
39
|
+
throw new Error('The optional timezone peer was installed for a root consumer');
|
|
40
|
+
}
|
|
41
|
+
if (existsSync(join(rootConsumer, 'node_modules', 'drizzle-orm'))) {
|
|
42
|
+
throw new Error('The optional drizzle peer was installed for a root consumer');
|
|
43
|
+
}
|
|
44
|
+
if (existsSync(join(rootConsumer, 'node_modules', '@rdlabo', 'workers-mysql'))) {
|
|
45
|
+
throw new Error('The optional MySQL package was installed for a root consumer');
|
|
46
|
+
}
|
|
47
|
+
if (existsSync(join(rootConsumer, 'node_modules', 'mysql2'))) {
|
|
48
|
+
throw new Error('mysql2 was installed for a root consumer');
|
|
49
|
+
}
|
|
50
|
+
writeFileSync(
|
|
51
|
+
join(rootConsumer, 'smoke.mjs'),
|
|
52
|
+
`import * as kit from "@rdlabo/workers-hono-kit";
|
|
53
|
+
const { HttpStatus } = kit;
|
|
54
|
+
if (HttpStatus.OK !== 200) process.exit(1);
|
|
55
|
+
if ("createContainerRuntime" in kit) process.exit(1);
|
|
56
|
+
if ("retryWhenDeadlock" in kit) process.exit(1);
|
|
57
|
+
// The legacy testing barrel intentionally requires the optional MySQL package.
|
|
58
|
+
const { rejects } = await import("node:assert/strict");
|
|
59
|
+
await rejects(import("@rdlabo/workers-hono-kit/testing"), (error) =>
|
|
60
|
+
error.code === "ERR_MODULE_NOT_FOUND" && error.message.includes("@rdlabo/workers-mysql"));
|
|
61
|
+
`,
|
|
62
|
+
);
|
|
63
|
+
writeFileSync(
|
|
64
|
+
join(rootConsumer, 'smoke.ts'),
|
|
65
|
+
`import { HttpStatus } from "@rdlabo/workers-hono-kit";
|
|
66
|
+
const ok: number = HttpStatus.OK;
|
|
67
|
+
void ok;
|
|
68
|
+
`,
|
|
69
|
+
);
|
|
70
|
+
writeFileSync(
|
|
71
|
+
join(rootConsumer, 'tsconfig.json'),
|
|
72
|
+
'{"compilerOptions":{"strict":true,"module":"ESNext","moduleResolution":"Bundler","target":"ES2022","noEmit":true,"skipLibCheck":true},"include":["smoke.ts"]}\n',
|
|
73
|
+
);
|
|
74
|
+
execFileSync('node', ['smoke.mjs'], { cwd: rootConsumer, stdio: 'inherit' });
|
|
75
|
+
execFileSync(join(root, 'node_modules', '.bin', 'tsc'), ['-p', 'tsconfig.json'], {
|
|
76
|
+
cwd: rootConsumer,
|
|
77
|
+
stdio: 'inherit',
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const timezoneConsumer = join(temporaryDirectory, 'timezone-consumer');
|
|
81
|
+
mkdirSync(timezoneConsumer);
|
|
82
|
+
writeFileSync(join(timezoneConsumer, 'package.json'), '{"private":true,"type":"module"}\n');
|
|
83
|
+
execFileSync('npm', ['install', '--ignore-scripts', timezoneTarball, kitTarball, 'ai-gateway-provider@^3.1.0'], {
|
|
84
|
+
cwd: timezoneConsumer,
|
|
85
|
+
stdio: 'inherit',
|
|
86
|
+
env: commandEnvironment,
|
|
87
|
+
});
|
|
88
|
+
writeFileSync(
|
|
89
|
+
join(timezoneConsumer, 'smoke.mjs'),
|
|
90
|
+
`import { initializeTimezone, toLocalDateTime } from "@rdlabo/workers-timezone";
|
|
91
|
+
import { getTimezoneConfig, toBusinessDateTime } from "@rdlabo/workers-hono-kit/business-time";
|
|
92
|
+
initializeTimezone({ timeZone: "America/New_York" });
|
|
93
|
+
const instant = new Date("2026-07-01T13:00:00Z");
|
|
94
|
+
if (toLocalDateTime(instant) !== "2026-07-01 09:00:00") process.exit(1);
|
|
95
|
+
if (toBusinessDateTime(instant) !== "2026-07-01 09:00:00") process.exit(1);
|
|
96
|
+
if (getTimezoneConfig().timeZone !== "America/New_York") process.exit(1);
|
|
97
|
+
`,
|
|
98
|
+
);
|
|
99
|
+
writeFileSync(
|
|
100
|
+
join(timezoneConsumer, 'smoke.ts'),
|
|
101
|
+
`import { type TimeZone } from "@rdlabo/workers-timezone";
|
|
102
|
+
import { type BusinessTimeZone } from "@rdlabo/workers-hono-kit/business-time";
|
|
103
|
+
const current: TimeZone = "Europe/London";
|
|
104
|
+
const legacy: BusinessTimeZone = current;
|
|
105
|
+
void legacy;
|
|
106
|
+
`,
|
|
107
|
+
);
|
|
108
|
+
writeFileSync(
|
|
109
|
+
join(timezoneConsumer, 'tsconfig.json'),
|
|
110
|
+
'{"compilerOptions":{"strict":true,"module":"ESNext","moduleResolution":"Bundler","target":"ES2022","noEmit":true,"skipLibCheck":true},"include":["smoke.ts"]}\n',
|
|
111
|
+
);
|
|
112
|
+
execFileSync('node', ['smoke.mjs'], { cwd: timezoneConsumer, stdio: 'inherit' });
|
|
113
|
+
execFileSync(join(root, 'node_modules', '.bin', 'tsc'), ['-p', 'tsconfig.json'], {
|
|
114
|
+
cwd: timezoneConsumer,
|
|
115
|
+
stdio: 'inherit',
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const mysqlCoreConsumer = join(temporaryDirectory, 'mysql-core-consumer');
|
|
119
|
+
mkdirSync(mysqlCoreConsumer);
|
|
120
|
+
writeFileSync(join(mysqlCoreConsumer, 'package.json'), '{"private":true,"type":"module"}\n');
|
|
121
|
+
execFileSync('npm', ['install', '--ignore-scripts', mysqlTarball, '@types/node@20.19.43'], {
|
|
122
|
+
cwd: mysqlCoreConsumer,
|
|
123
|
+
stdio: 'inherit',
|
|
124
|
+
env: commandEnvironment,
|
|
125
|
+
});
|
|
126
|
+
if (existsSync(join(mysqlCoreConsumer, 'node_modules', 'drizzle-orm'))) {
|
|
127
|
+
throw new Error('The optional drizzle peer was installed for a MySQL core consumer');
|
|
128
|
+
}
|
|
129
|
+
writeFileSync(
|
|
130
|
+
join(mysqlCoreConsumer, 'smoke.mjs'),
|
|
131
|
+
`import { MYSQL_TIMEZONE, toJstDate } from "@rdlabo/workers-mysql";
|
|
132
|
+
if (MYSQL_TIMEZONE !== "+09:00") process.exit(1);
|
|
133
|
+
if (toJstDate("1950-07-01T14:30:00Z") !== "1950-07-01") process.exit(1);
|
|
134
|
+
`,
|
|
135
|
+
);
|
|
136
|
+
execFileSync('node', ['smoke.mjs'], { cwd: mysqlCoreConsumer, stdio: 'inherit' });
|
|
137
|
+
writeFileSync(
|
|
138
|
+
join(mysqlCoreConsumer, 'smoke.ts'),
|
|
139
|
+
'import { type Database, MYSQL_TIMEZONE } from "@rdlabo/workers-mysql";\ndeclare const db: Database<unknown>;\nvoid db; void MYSQL_TIMEZONE;\n',
|
|
140
|
+
);
|
|
141
|
+
writeFileSync(
|
|
142
|
+
join(mysqlCoreConsumer, 'tsconfig.json'),
|
|
143
|
+
'{"compilerOptions":{"strict":true,"module":"ESNext","moduleResolution":"Bundler","target":"ES2022","noEmit":true,"skipLibCheck":false},"include":["smoke.ts"]}\n',
|
|
144
|
+
);
|
|
145
|
+
execFileSync(join(root, 'node_modules', '.bin', 'tsc'), ['-p', 'tsconfig.json'], {
|
|
146
|
+
cwd: mysqlCoreConsumer,
|
|
147
|
+
stdio: 'inherit',
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const databaseConsumer = join(temporaryDirectory, 'database-consumer');
|
|
151
|
+
mkdirSync(databaseConsumer);
|
|
152
|
+
writeFileSync(join(databaseConsumer, 'package.json'), '{"private":true,"type":"module"}\n');
|
|
153
|
+
execFileSync(
|
|
154
|
+
'npm',
|
|
155
|
+
['install', '--ignore-scripts', mysqlTarball, kitTarball, 'drizzle-orm@^0.45.2', 'ai-gateway-provider@^3.1.0'],
|
|
156
|
+
{
|
|
157
|
+
cwd: databaseConsumer,
|
|
158
|
+
stdio: 'inherit',
|
|
159
|
+
env: commandEnvironment,
|
|
160
|
+
},
|
|
161
|
+
);
|
|
162
|
+
if (existsSync(join(databaseConsumer, 'node_modules', '@rdlabo', 'workers-timezone'))) {
|
|
163
|
+
throw new Error('The optional timezone peer was installed for a database-only consumer');
|
|
164
|
+
}
|
|
165
|
+
writeFileSync(
|
|
166
|
+
join(databaseConsumer, 'smoke.mjs'),
|
|
167
|
+
`import { MYSQL_TIMEZONE, toJstDate } from "@rdlabo/workers-mysql";
|
|
168
|
+
import { workersDrizzleConfig } from "@rdlabo/workers-mysql/drizzle";
|
|
169
|
+
import { MYSQL_TIMEZONE as legacyTimezone, toJstDate as legacyToJstDate } from "@rdlabo/workers-hono-kit/db";
|
|
170
|
+
import { createContainerRuntime } from "@rdlabo/workers-hono-kit/mysql";
|
|
171
|
+
import { FakeFirebaseVerifier, fakeKv } from "@rdlabo/workers-hono-kit/testing";
|
|
172
|
+
if (typeof FakeFirebaseVerifier !== "function" || typeof fakeKv !== "function") process.exit(1);
|
|
173
|
+
if (MYSQL_TIMEZONE !== "+09:00") process.exit(1);
|
|
174
|
+
if (legacyTimezone !== MYSQL_TIMEZONE) process.exit(1);
|
|
175
|
+
if (legacyToJstDate !== toJstDate) process.exit(1);
|
|
176
|
+
if (toJstDate("1950-07-01T14:30:00Z") !== "1950-07-01") process.exit(1);
|
|
177
|
+
if (workersDrizzleConfig({ database: "app" }).casing !== "snake_case") process.exit(1);
|
|
178
|
+
if (typeof createContainerRuntime !== "function") process.exit(1);
|
|
179
|
+
`,
|
|
180
|
+
);
|
|
181
|
+
writeFileSync(
|
|
182
|
+
join(databaseConsumer, 'smoke.ts'),
|
|
183
|
+
`import { MYSQL_TIMEZONE, toJstDate } from "@rdlabo/workers-mysql";
|
|
184
|
+
import { workersDrizzleConfig } from "@rdlabo/workers-mysql/drizzle";
|
|
185
|
+
import { createContainerRuntime } from "@rdlabo/workers-hono-kit/mysql";
|
|
186
|
+
const timezone: string = MYSQL_TIMEZONE;
|
|
187
|
+
const date: string | null = toJstDate("2026-07-01T00:00:00Z");
|
|
188
|
+
const config = workersDrizzleConfig({ database: "app" });
|
|
189
|
+
void timezone;
|
|
190
|
+
void date;
|
|
191
|
+
void config;
|
|
192
|
+
void createContainerRuntime;
|
|
193
|
+
`,
|
|
194
|
+
);
|
|
195
|
+
writeFileSync(
|
|
196
|
+
join(databaseConsumer, 'tsconfig.json'),
|
|
197
|
+
'{"compilerOptions":{"strict":true,"module":"ESNext","moduleResolution":"Bundler","target":"ES2022","noEmit":true,"skipLibCheck":true},"include":["smoke.ts"]}\n',
|
|
198
|
+
);
|
|
199
|
+
execFileSync('node', ['smoke.mjs'], { cwd: databaseConsumer, stdio: 'inherit' });
|
|
200
|
+
execFileSync(join(root, 'node_modules', '.bin', 'tsc'), ['-p', 'tsconfig.json'], {
|
|
201
|
+
cwd: databaseConsumer,
|
|
202
|
+
stdio: 'inherit',
|
|
203
|
+
});
|
|
204
|
+
} finally {
|
|
205
|
+
rmSync(temporaryDirectory, { recursive: true, force: true });
|
|
206
|
+
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/** A JST business calendar date `YYYY-MM-DD` (a calendar day, not an instant). */
|
|
2
|
-
export type BusinessDate = string;
|
|
3
|
-
/** A JST business date-time `YYYY-MM-DD HH:mm:ss` (a wall-clock value, MySQL `DATETIME`-compatible). */
|
|
4
|
-
export type BusinessDateTime = string;
|
|
5
|
-
/** JST business timezone constant. Workers run in UTC instants; business time is made explicit here. */
|
|
6
|
-
export declare const BUSINESS_TIMEZONE: {
|
|
7
|
-
readonly iana: "Asia/Tokyo";
|
|
8
|
-
readonly offsetMinutes: 540;
|
|
9
|
-
};
|
package/dist/db/columns.d.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SQL expression for `ON UPDATE CURRENT_TIMESTAMP` (the MySQL session clock).
|
|
3
|
-
* customType columns have no `.onUpdateNow()`, so pair this with `.$onUpdateFn(() => jstOnUpdateNow(fsp))`.
|
|
4
|
-
*
|
|
5
|
-
* @param fsp - optional fractional-seconds precision; when provided, emits `CURRENT_TIMESTAMP(fsp)`.
|
|
6
|
-
*/
|
|
7
|
-
export declare const jstOnUpdateNow: (fsp?: number) => import("drizzle-orm").SQL<unknown>;
|
|
8
|
-
/** MySQL `timestamp` — pass-through. A `Date` is formatted as JST by mysql2 via the connection `timezone:'+09:00'`. */
|
|
9
|
-
export declare const jstTimestamp: (name: string, opts?: {
|
|
10
|
-
fsp?: number;
|
|
11
|
-
}) => import("drizzle-orm/mysql-core").MySqlCustomColumnBuilder<{
|
|
12
|
-
name: string;
|
|
13
|
-
dataType: "custom";
|
|
14
|
-
columnType: "MySqlCustomColumn";
|
|
15
|
-
data: string | Date;
|
|
16
|
-
driverParam: string | Date;
|
|
17
|
-
enumValues: undefined;
|
|
18
|
-
}>;
|
|
19
|
-
/** MySQL `datetime` — same pass-through policy as {@link jstTimestamp}. */
|
|
20
|
-
export declare const jstDatetime: (name: string, opts?: {
|
|
21
|
-
fsp?: number;
|
|
22
|
-
}) => import("drizzle-orm/mysql-core").MySqlCustomColumnBuilder<{
|
|
23
|
-
name: string;
|
|
24
|
-
dataType: "custom";
|
|
25
|
-
columnType: "MySqlCustomColumn";
|
|
26
|
-
data: string | Date;
|
|
27
|
-
driverParam: string | Date;
|
|
28
|
-
enumValues: undefined;
|
|
29
|
-
}>;
|
|
30
|
-
/** MySQL `date` — on INSERT/UPDATE, normalizes ISO / empty strings to `YYYY-MM-DD` (via `toDriver`). */
|
|
31
|
-
export declare const jstDate: (name: string) => import("drizzle-orm/mysql-core").MySqlCustomColumnBuilder<{
|
|
32
|
-
name: string;
|
|
33
|
-
dataType: "custom";
|
|
34
|
-
columnType: "MySqlCustomColumn";
|
|
35
|
-
data: string | null;
|
|
36
|
-
driverParam: string | null;
|
|
37
|
-
enumValues: undefined;
|
|
38
|
-
}>;
|
package/dist/db/columns.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared Drizzle column helpers. Removes the need for a thin `custom-types.ts` / `columns.ts` wrapper
|
|
3
|
-
* in each repo.
|
|
4
|
-
*
|
|
5
|
-
* @remarks
|
|
6
|
-
* `drizzle-orm` is a **peer** (the consumer resolves a single copy); the kit does not bundle it. The
|
|
7
|
-
* return types are the `customType` inference as-is (`MySqlCustomColumnBuilder<…>`) with no `any`, so
|
|
8
|
-
* the column's semantic type (`string | Date`, etc.) propagates to the consumer table's `$inferSelect`.
|
|
9
|
-
*
|
|
10
|
-
* **Precondition (a single drizzle copy)**: Drizzle's `SQL` is a **nominal** type carrying a private
|
|
11
|
-
* field `shouldInlineParams`, so if the kit and the consumer resolve different copies of drizzle,
|
|
12
|
-
* `jstTimestamp(…).default(sql\`…\`)` fails with `TS2345: separate declarations of a private property
|
|
13
|
-
* 'shouldInlineParams'`. The fleet references the kit via a `file:` link, which tends to nest a second
|
|
14
|
-
* copy of drizzle under the kit. Pin `drizzle-orm` to the consumer's **own single copy** with tsconfig
|
|
15
|
-
* `paths` (see the "Drizzle column helpers" section of the README). The published package (a single
|
|
16
|
-
* copy) is already unified.
|
|
17
|
-
*
|
|
18
|
-
* **DEFAULT / ON UPDATE CURRENT_TIMESTAMP** is a server-side default (an INSERT / UPDATE that omits the
|
|
19
|
-
* column). The connection's `timezone:'+09:00'` ({@link hyperdriveConnectionOptions}) only applies when
|
|
20
|
-
* the **app binds a `Date`**. Do not conflate the two (see the `datetime-wire` / `drizzle-smoke` JST
|
|
21
|
-
* tests).
|
|
22
|
-
*/
|
|
23
|
-
import { sql } from 'drizzle-orm';
|
|
24
|
-
import { customType } from 'drizzle-orm/mysql-core';
|
|
25
|
-
import { jstDateParams, jstDatetimeParams, jstTimestampParams } from './jst.js';
|
|
26
|
-
/**
|
|
27
|
-
* SQL expression for `ON UPDATE CURRENT_TIMESTAMP` (the MySQL session clock).
|
|
28
|
-
* customType columns have no `.onUpdateNow()`, so pair this with `.$onUpdateFn(() => jstOnUpdateNow(fsp))`.
|
|
29
|
-
*
|
|
30
|
-
* @param fsp - optional fractional-seconds precision; when provided, emits `CURRENT_TIMESTAMP(fsp)`.
|
|
31
|
-
*/
|
|
32
|
-
export const jstOnUpdateNow = (fsp) => fsp != null ? sql `(CURRENT_TIMESTAMP(${sql.raw(String(fsp))}))` : sql `(CURRENT_TIMESTAMP)`;
|
|
33
|
-
/** MySQL `timestamp` — pass-through. A `Date` is formatted as JST by mysql2 via the connection `timezone:'+09:00'`. */
|
|
34
|
-
export const jstTimestamp = (name, opts) => customType(jstTimestampParams(opts?.fsp))(name);
|
|
35
|
-
/** MySQL `datetime` — same pass-through policy as {@link jstTimestamp}. */
|
|
36
|
-
export const jstDatetime = (name, opts) => customType(jstDatetimeParams(opts?.fsp))(name);
|
|
37
|
-
/** MySQL `date` — on INSERT/UPDATE, normalizes ISO / empty strings to `YYYY-MM-DD` (via `toDriver`). */
|
|
38
|
-
export const jstDate = (name) => customType(jstDateParams())(name);
|
package/dist/db/connection.d.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import type { Connection } from 'mysql2/promise';
|
|
2
|
-
import type { ExecutionContextLike } from '../http/execution-context.js';
|
|
3
|
-
export type { ExecutionContextLike } from '../http/execution-context.js';
|
|
4
|
-
/**
|
|
5
|
-
* Minimal structural shape of a Cloudflare Hyperdrive binding.
|
|
6
|
-
*
|
|
7
|
-
* @remarks
|
|
8
|
-
* Declared structurally to avoid a dependency on `@cloudflare/workers-types`; any object with these
|
|
9
|
-
* connection fields satisfies it.
|
|
10
|
-
*/
|
|
11
|
-
export interface HyperdriveLike {
|
|
12
|
-
/** Database host to connect to. */
|
|
13
|
-
host: string;
|
|
14
|
-
/** Database user. */
|
|
15
|
-
user: string;
|
|
16
|
-
/** Database password. */
|
|
17
|
-
password: string;
|
|
18
|
-
/** Database name. */
|
|
19
|
-
database: string;
|
|
20
|
-
/** Database port. */
|
|
21
|
-
port: number;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Build mysql2 `createConnection` options from a Hyperdrive binding, applying the kit's defaults.
|
|
25
|
-
*
|
|
26
|
-
* @remarks
|
|
27
|
-
* Three defaults are applied and can each be overridden via `extra`:
|
|
28
|
-
*
|
|
29
|
-
* - `disableEval: true` — `eval` is unavailable in the Workers runtime, so the driver's eval-based
|
|
30
|
-
* fast paths must be disabled.
|
|
31
|
-
* - `decimalNumbers: true` — return `DECIMAL`/`NEWDECIMAL` columns as JS `number` rather than
|
|
32
|
-
* strings, so raw-SQL reads and Drizzle's inferred types align on a single numeric domain type.
|
|
33
|
-
* This assumes no column's precision exceeds the JS safe-integer range.
|
|
34
|
-
* - `timezone: '+09:00'` — interpret and serialize JavaScript `Date` values as JST. This is a
|
|
35
|
-
* mysql2 client-side conversion option; it does not issue `SET time_zone` or change the MySQL
|
|
36
|
-
* session timezone. Non-JST deployments can override it via `extra: { timezone: '...' }`.
|
|
37
|
-
*
|
|
38
|
-
* @param hyperdrive - the Hyperdrive binding to derive connection fields from.
|
|
39
|
-
* @param extra - additional mysql2 options merged last, overriding the defaults above.
|
|
40
|
-
* @returns a plain options object to pass to mysql2 `createConnection`.
|
|
41
|
-
*/
|
|
42
|
-
export declare function hyperdriveConnectionOptions(hyperdrive: HyperdriveLike, extra?: Record<string, unknown>): Record<string, unknown>;
|
|
43
|
-
/**
|
|
44
|
-
* Open primary and replica connections in parallel and run `fn` with them.
|
|
45
|
-
*
|
|
46
|
-
* Cloudflare Workers automatically cleans up connections created during an invocation. Calling
|
|
47
|
-
* `Connection.end()` is unnecessary and can race work registered with `waitUntil`. The `ctx`
|
|
48
|
-
* parameter remains for API compatibility and is intentionally not used for connection teardown.
|
|
49
|
-
*
|
|
50
|
-
* @typeParam T - resolved value produced by `fn`.
|
|
51
|
-
* @param hyperdrives - the primary and replica Hyperdrive bindings to connect to.
|
|
52
|
-
* @param ctx - the request execution context, retained for API compatibility.
|
|
53
|
-
* @param fn - callback invoked with the open `primary` and `replica` connections.
|
|
54
|
-
* @param connectionOptions - extra mysql2 options forwarded to {@link hyperdriveConnectionOptions}.
|
|
55
|
-
* @returns the value resolved by `fn`.
|
|
56
|
-
* @example
|
|
57
|
-
* ```ts
|
|
58
|
-
* const data = await withMysqlConnections(
|
|
59
|
-
* { primary: env.PRIMARY, replica: env.REPLICA },
|
|
60
|
-
* ctx,
|
|
61
|
-
* async ({ primary, replica }) => {
|
|
62
|
-
* const [rows] = await replica.query('SELECT 1');
|
|
63
|
-
* return rows;
|
|
64
|
-
* },
|
|
65
|
-
* );
|
|
66
|
-
* ```
|
|
67
|
-
*/
|
|
68
|
-
export declare function withMysqlConnections<T>(hyperdrives: {
|
|
69
|
-
primary: HyperdriveLike;
|
|
70
|
-
replica: HyperdriveLike;
|
|
71
|
-
}, ctx: ExecutionContextLike, fn: (connections: {
|
|
72
|
-
primary: Connection;
|
|
73
|
-
replica: Connection;
|
|
74
|
-
}) => Promise<T>, connectionOptions?: Record<string, unknown>): Promise<T>;
|
package/dist/db/connection.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { createConnection } from 'mysql2/promise';
|
|
2
|
-
import { MYSQL_TIMEZONE } from './jst.js';
|
|
3
|
-
/**
|
|
4
|
-
* Build mysql2 `createConnection` options from a Hyperdrive binding, applying the kit's defaults.
|
|
5
|
-
*
|
|
6
|
-
* @remarks
|
|
7
|
-
* Three defaults are applied and can each be overridden via `extra`:
|
|
8
|
-
*
|
|
9
|
-
* - `disableEval: true` — `eval` is unavailable in the Workers runtime, so the driver's eval-based
|
|
10
|
-
* fast paths must be disabled.
|
|
11
|
-
* - `decimalNumbers: true` — return `DECIMAL`/`NEWDECIMAL` columns as JS `number` rather than
|
|
12
|
-
* strings, so raw-SQL reads and Drizzle's inferred types align on a single numeric domain type.
|
|
13
|
-
* This assumes no column's precision exceeds the JS safe-integer range.
|
|
14
|
-
* - `timezone: '+09:00'` — interpret and serialize JavaScript `Date` values as JST. This is a
|
|
15
|
-
* mysql2 client-side conversion option; it does not issue `SET time_zone` or change the MySQL
|
|
16
|
-
* session timezone. Non-JST deployments can override it via `extra: { timezone: '...' }`.
|
|
17
|
-
*
|
|
18
|
-
* @param hyperdrive - the Hyperdrive binding to derive connection fields from.
|
|
19
|
-
* @param extra - additional mysql2 options merged last, overriding the defaults above.
|
|
20
|
-
* @returns a plain options object to pass to mysql2 `createConnection`.
|
|
21
|
-
*/
|
|
22
|
-
export function hyperdriveConnectionOptions(hyperdrive, extra) {
|
|
23
|
-
return {
|
|
24
|
-
host: hyperdrive.host,
|
|
25
|
-
user: hyperdrive.user,
|
|
26
|
-
password: hyperdrive.password,
|
|
27
|
-
database: hyperdrive.database,
|
|
28
|
-
port: hyperdrive.port,
|
|
29
|
-
disableEval: true,
|
|
30
|
-
decimalNumbers: true,
|
|
31
|
-
timezone: MYSQL_TIMEZONE,
|
|
32
|
-
...extra,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Open primary and replica connections in parallel and run `fn` with them.
|
|
37
|
-
*
|
|
38
|
-
* Cloudflare Workers automatically cleans up connections created during an invocation. Calling
|
|
39
|
-
* `Connection.end()` is unnecessary and can race work registered with `waitUntil`. The `ctx`
|
|
40
|
-
* parameter remains for API compatibility and is intentionally not used for connection teardown.
|
|
41
|
-
*
|
|
42
|
-
* @typeParam T - resolved value produced by `fn`.
|
|
43
|
-
* @param hyperdrives - the primary and replica Hyperdrive bindings to connect to.
|
|
44
|
-
* @param ctx - the request execution context, retained for API compatibility.
|
|
45
|
-
* @param fn - callback invoked with the open `primary` and `replica` connections.
|
|
46
|
-
* @param connectionOptions - extra mysql2 options forwarded to {@link hyperdriveConnectionOptions}.
|
|
47
|
-
* @returns the value resolved by `fn`.
|
|
48
|
-
* @example
|
|
49
|
-
* ```ts
|
|
50
|
-
* const data = await withMysqlConnections(
|
|
51
|
-
* { primary: env.PRIMARY, replica: env.REPLICA },
|
|
52
|
-
* ctx,
|
|
53
|
-
* async ({ primary, replica }) => {
|
|
54
|
-
* const [rows] = await replica.query('SELECT 1');
|
|
55
|
-
* return rows;
|
|
56
|
-
* },
|
|
57
|
-
* );
|
|
58
|
-
* ```
|
|
59
|
-
*/
|
|
60
|
-
export async function withMysqlConnections(hyperdrives, ctx, fn, connectionOptions) {
|
|
61
|
-
void ctx;
|
|
62
|
-
const [primary, replica] = await Promise.all([
|
|
63
|
-
createConnection(hyperdriveConnectionOptions(hyperdrives.primary, connectionOptions)),
|
|
64
|
-
createConnection(hyperdriveConnectionOptions(hyperdrives.replica, connectionOptions)),
|
|
65
|
-
]);
|
|
66
|
-
return fn({ primary, replica });
|
|
67
|
-
}
|
package/dist/db/database.d.ts
DELETED
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
import type { Connection, Pool } from 'mysql2/promise';
|
|
2
|
-
import type { HyperdriveLike } from './connection.js';
|
|
3
|
-
/**
|
|
4
|
-
* Dual-connection data layer that separates reads from writes.
|
|
5
|
-
*
|
|
6
|
-
* @remarks
|
|
7
|
-
* The two sides of the database are deliberately handled differently:
|
|
8
|
-
*
|
|
9
|
-
* - Reads go to the **replica** as raw SQL (`QueryRunner.query`) by default, returning plain rows.
|
|
10
|
-
* Hyperdrive-backed databases also expose `query()` for freshness-sensitive primary SELECTs.
|
|
11
|
-
* - Writes and transactions go to the **primary** through the Drizzle ORM for type safety, but only
|
|
12
|
-
* via `write(fn)` / `transaction(fn)` — the raw query builder is never exposed. The builder is
|
|
13
|
-
* awaited inside those methods, which removes a foot-gun: a Drizzle builder is a lazy thenable, so
|
|
14
|
-
* a bare `return builder` would silently become a no-op.
|
|
15
|
-
*
|
|
16
|
-
* Both sides retry on `ER_LOCK_DEADLOCK`.
|
|
17
|
-
*
|
|
18
|
-
* The kit deliberately avoids depending on the type identity of `drizzle-orm`: the consumer creates
|
|
19
|
-
* the ORM instance with its own copy of `drizzle-orm` and passes it in, and {@link Database} is
|
|
20
|
-
* generic over that ORM type (`TDrizzle`). This keeps the ORM's `MySqlTable`/`SQL` brands from
|
|
21
|
-
* clashing even when the kit and the consumer resolve separate copies of `drizzle-orm`.
|
|
22
|
-
*/
|
|
23
|
-
/**
|
|
24
|
-
* Minimal connection interface used for reads.
|
|
25
|
-
*
|
|
26
|
-
* @remarks
|
|
27
|
-
* A mysql2 `Connection` or `Pool` satisfies this structurally.
|
|
28
|
-
*/
|
|
29
|
-
export interface QueryRunner {
|
|
30
|
-
/**
|
|
31
|
-
* Run a parameterized SQL query.
|
|
32
|
-
*
|
|
33
|
-
* @param sql - the SQL text, with `?` placeholders for `params`.
|
|
34
|
-
* @param params - optional positional parameters.
|
|
35
|
-
* @returns the driver's raw result (typically `[rows, fields]`).
|
|
36
|
-
*/
|
|
37
|
-
query(sql: string, params?: unknown[]): Promise<unknown>;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Extract the transaction-handle type that a Drizzle instance passes to its `.transaction(cb)`
|
|
41
|
-
* callback.
|
|
42
|
-
*
|
|
43
|
-
* @typeParam TDrizzle - the consumer's Drizzle ORM type.
|
|
44
|
-
*/
|
|
45
|
-
export type TxOf<TDrizzle> = TDrizzle extends {
|
|
46
|
-
transaction(cb: (tx: infer Tx) => Promise<unknown>): Promise<unknown>;
|
|
47
|
-
} ? Tx : unknown;
|
|
48
|
-
/**
|
|
49
|
-
* The read/write surface of the data layer.
|
|
50
|
-
*
|
|
51
|
-
* @typeParam TDrizzle - the consumer's Drizzle ORM type used for writes and transactions.
|
|
52
|
-
* @typeParam TTx - the transaction-handle type, inferred from `TDrizzle` by default.
|
|
53
|
-
*/
|
|
54
|
-
export interface Database<TDrizzle, TTx = TxOf<TDrizzle>> {
|
|
55
|
-
/**
|
|
56
|
-
* Run a raw SQL read against the replica. Hyperdrive-backed databases retry deadlocks and repeat
|
|
57
|
-
* the SELECT once on a fresh connection after mysql2 reports a fatal connection error.
|
|
58
|
-
*
|
|
59
|
-
* @typeParam T - the row shape.
|
|
60
|
-
* @param sql - the SQL text, with `?` placeholders for `params`.
|
|
61
|
-
* @param params - optional positional parameters.
|
|
62
|
-
* @returns the rows returned by the query.
|
|
63
|
-
*/
|
|
64
|
-
read<T>(sql: string, params?: unknown[]): Promise<T[]>;
|
|
65
|
-
/**
|
|
66
|
-
* Run a single INSERT/UPDATE/DELETE against the primary, awaited with deadlock retry.
|
|
67
|
-
*
|
|
68
|
-
* @typeParam T - the value resolved by `fn`.
|
|
69
|
-
* @param fn - callback that receives the Drizzle ORM and returns the awaited write.
|
|
70
|
-
* @returns the value resolved by `fn`.
|
|
71
|
-
*/
|
|
72
|
-
write<T>(fn: (dz: TDrizzle) => Promise<T>): Promise<T>;
|
|
73
|
-
/**
|
|
74
|
-
* Run multiple writes inside a single transaction; the whole transaction is retried on deadlock.
|
|
75
|
-
*
|
|
76
|
-
* @typeParam T - the value resolved by `fn`.
|
|
77
|
-
* @param fn - callback that receives the transaction handle and returns the awaited work.
|
|
78
|
-
* @returns the value resolved by `fn`.
|
|
79
|
-
*/
|
|
80
|
-
transaction<T>(fn: (tx: TTx) => Promise<T>): Promise<T>;
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* A {@link Database} that opens its own connections.
|
|
84
|
-
*
|
|
85
|
-
* @remarks
|
|
86
|
-
* Used by variants that open connections internally. Lifecycle behavior depends on the backing
|
|
87
|
-
* implementation: pool-backed databases close their pool, while Hyperdrive-backed databases leave
|
|
88
|
-
* invocation-scoped connection cleanup to the Workers runtime.
|
|
89
|
-
*
|
|
90
|
-
* @typeParam TDrizzle - the consumer's Drizzle ORM type.
|
|
91
|
-
* @typeParam TTx - the transaction-handle type, inferred from `TDrizzle` by default.
|
|
92
|
-
*/
|
|
93
|
-
export interface DisposableDatabase<TDrizzle, TTx = TxOf<TDrizzle>> extends Database<TDrizzle, TTx> {
|
|
94
|
-
/**
|
|
95
|
-
* Release resources owned by the implementation. Hyperdrive-backed databases keep this method as
|
|
96
|
-
* a compatibility no-op; pool-backed databases use it to close their pool.
|
|
97
|
-
*
|
|
98
|
-
* @returns a promise that resolves after implementation-specific cleanup.
|
|
99
|
-
*/
|
|
100
|
-
dispose(): Promise<void>;
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* A Hyperdrive-backed database with an explicit primary query path.
|
|
104
|
-
*
|
|
105
|
-
* @remarks
|
|
106
|
-
* Use `query()` only for SELECTs that require read-after-write consistency or cannot use the
|
|
107
|
-
* configured replica. Fatal connection errors recreate the primary connection and repeat the
|
|
108
|
-
* SELECT at most once. Writes and transactions are never repeated for connection errors.
|
|
109
|
-
*
|
|
110
|
-
* @typeParam TDrizzle - the consumer's Drizzle ORM type.
|
|
111
|
-
* @typeParam TTx - the transaction-handle type, inferred from `TDrizzle` by default.
|
|
112
|
-
*/
|
|
113
|
-
export interface HyperdriveDatabase<TDrizzle, TTx = TxOf<TDrizzle>> extends DisposableDatabase<TDrizzle, TTx> {
|
|
114
|
-
/**
|
|
115
|
-
* Run a raw SQL SELECT against the primary database.
|
|
116
|
-
*
|
|
117
|
-
* @typeParam T - the complete rows result type (for example, `User[]`).
|
|
118
|
-
* @param sql - the SQL text, with `?` placeholders for `params`.
|
|
119
|
-
* @param params - optional positional parameters.
|
|
120
|
-
* @returns the rows returned by the query, typed as `T`.
|
|
121
|
-
*/
|
|
122
|
-
query<T = unknown>(sql: string, params?: unknown[]): Promise<T>;
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Options for {@link createMysqlDatabase}.
|
|
126
|
-
*
|
|
127
|
-
* @typeParam TDrizzle - the consumer's Drizzle ORM type.
|
|
128
|
-
*/
|
|
129
|
-
export interface CreateMysqlDatabaseOptions<TDrizzle> {
|
|
130
|
-
/**
|
|
131
|
-
* The Drizzle ORM used for writes, created by the consumer with its own `drizzle-orm`
|
|
132
|
-
* (e.g. `drizzle(primary, { schema, ... })`).
|
|
133
|
-
*/
|
|
134
|
-
orm: TDrizzle;
|
|
135
|
-
/** The connection used for reads (raw SQL). */
|
|
136
|
-
replica: QueryRunner;
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Assemble a {@link Database} from an already-connected ORM and replica.
|
|
140
|
-
*
|
|
141
|
-
* @remarks
|
|
142
|
-
* The caller (typically the worker entry point) owns creating the connections and the ORM, and is
|
|
143
|
-
* responsible for closing the connections; this variant does not manage their lifecycle.
|
|
144
|
-
*
|
|
145
|
-
* @typeParam TDrizzle - the consumer's Drizzle ORM type.
|
|
146
|
-
* @param options - the write ORM and the read connection.
|
|
147
|
-
* @returns a {@link Database} backed by the supplied ORM and replica.
|
|
148
|
-
* @example
|
|
149
|
-
* ```ts
|
|
150
|
-
* const db = createMysqlDatabase({
|
|
151
|
-
* orm: drizzle(primary, { schema, ...DRIZZLE_ORM_OPTIONS }),
|
|
152
|
-
* replica,
|
|
153
|
-
* });
|
|
154
|
-
* const rows = await db.read<User>('SELECT * FROM users WHERE id = ?', [id]);
|
|
155
|
-
* ```
|
|
156
|
-
*/
|
|
157
|
-
export declare function createMysqlDatabase<TDrizzle>(options: CreateMysqlDatabaseOptions<TDrizzle>): Database<TDrizzle>;
|
|
158
|
-
/**
|
|
159
|
-
* Options for {@link createHyperdriveDatabase}.
|
|
160
|
-
*
|
|
161
|
-
* @typeParam TDrizzle - the consumer's Drizzle ORM type.
|
|
162
|
-
*/
|
|
163
|
-
export interface CreateHyperdriveDatabaseOptions<TDrizzle> {
|
|
164
|
-
/** The Hyperdrive binding for the primary (write) connection. */
|
|
165
|
-
primaryHyperdrive: HyperdriveLike;
|
|
166
|
-
/** The Hyperdrive binding for the replica (read) connection. */
|
|
167
|
-
replicaHyperdrive: HyperdriveLike;
|
|
168
|
-
/**
|
|
169
|
-
* Factory that builds the write ORM from the primary connection, using the consumer's
|
|
170
|
-
* `drizzle-orm`.
|
|
171
|
-
*/
|
|
172
|
-
createOrm: (primary: Connection) => TDrizzle;
|
|
173
|
-
/**
|
|
174
|
-
* Extra options forwarded to mysql2 `createConnection`, merged on top of the defaults applied by
|
|
175
|
-
* {@link hyperdriveConnectionOptions} (`disableEval: true`, `decimalNumbers: true`, and
|
|
176
|
-
* `timezone: '+09:00'`). Pass a field here to override any of those defaults.
|
|
177
|
-
*/
|
|
178
|
-
connectionOptions?: Record<string, unknown>;
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Create a {@link HyperdriveDatabase} that lazily opens its connections from Hyperdrive bindings.
|
|
182
|
-
*
|
|
183
|
-
* @remarks
|
|
184
|
-
* Construct one per request. Connections and the ORM are created on first use and reused for the
|
|
185
|
-
* lifetime of the instance. `read()` uses the replica, while `query()` provides an explicit
|
|
186
|
-
* primary SELECT path. Workers automatically cleans up connections at the end of the invocation,
|
|
187
|
-
* so callers do not need to close them manually. Either SELECT path is repeated once on a fresh
|
|
188
|
-
* connection after a fatal mysql2 connection error. Writes and transactions are never repeated
|
|
189
|
-
* for connection errors because their commit state can be ambiguous.
|
|
190
|
-
*
|
|
191
|
-
* @typeParam TDrizzle - the consumer's Drizzle ORM type.
|
|
192
|
-
* @param options - the primary/replica Hyperdrive bindings, the ORM factory, and connection options.
|
|
193
|
-
* @returns a {@link HyperdriveDatabase} whose compatibility `dispose()` method is a no-op; Workers
|
|
194
|
-
* cleans up its invocation-scoped connections automatically.
|
|
195
|
-
* @example
|
|
196
|
-
* ```ts
|
|
197
|
-
* const db = createHyperdriveDatabase({
|
|
198
|
-
* primaryHyperdrive: env.PRIMARY,
|
|
199
|
-
* replicaHyperdrive: env.REPLICA,
|
|
200
|
-
* createOrm: (primary) => drizzle(primary, { schema, ...DRIZZLE_ORM_OPTIONS }),
|
|
201
|
-
* });
|
|
202
|
-
* await db.write((dz) => dz.insert(users).values(user));
|
|
203
|
-
* ```
|
|
204
|
-
*/
|
|
205
|
-
export declare function createHyperdriveDatabase<TDrizzle>(options: CreateHyperdriveDatabaseOptions<TDrizzle>): HyperdriveDatabase<TDrizzle>;
|
|
206
|
-
/**
|
|
207
|
-
* Internal helper that assembles a {@link Database} from an ORM and a replica connection.
|
|
208
|
-
*
|
|
209
|
-
* @typeParam TDrizzle - the consumer's Drizzle ORM type.
|
|
210
|
-
* @param orm - the Drizzle ORM used for writes and transactions.
|
|
211
|
-
* @param replica - the connection used for reads.
|
|
212
|
-
* @returns a {@link Database} wiring reads to `replica` and writes to `orm`, both with deadlock retry.
|
|
213
|
-
* @internal
|
|
214
|
-
*/
|
|
215
|
-
export declare function databaseFrom<TDrizzle>(orm: TDrizzle, replica: QueryRunner): Database<TDrizzle>;
|
|
216
|
-
/**
|
|
217
|
-
* Re-export of the mysql2 `Connection` and `Pool` types.
|
|
218
|
-
*
|
|
219
|
-
* @remarks
|
|
220
|
-
* Both are structurally assignable to the kit's {@link QueryRunner}.
|
|
221
|
-
*/
|
|
222
|
-
export type { Connection, Pool };
|