@rdlabo/workers-hono-kit 0.11.2 → 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 +68 -5
- 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 -249
- package/dist/db/database.js +0 -196
- 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 -56
- 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
|
-
}
|