@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.
Files changed (56) hide show
  1. package/README.md +73 -37
  2. package/dist/aws/sts.d.ts +2 -2
  3. package/dist/aws/sts.js +4 -4
  4. package/dist/business-time/index.d.ts +68 -122
  5. package/dist/business-time/index.js +55 -222
  6. package/dist/container/middleware.d.ts +1 -2
  7. package/dist/container/middleware.js +1 -1
  8. package/dist/db/index.d.ts +95 -20
  9. package/dist/db/index.js +56 -15
  10. package/dist/db/payment-failed.d.ts +1 -1
  11. package/dist/db/payment-failed.js +1 -1
  12. package/dist/index.d.ts +0 -3
  13. package/dist/index.js +0 -3
  14. package/dist/mysql/index.d.ts +9 -0
  15. package/dist/mysql/index.js +8 -0
  16. package/dist/testing/auth.d.ts +1 -1
  17. package/dist/testing/db.d.ts +19 -106
  18. package/dist/testing/db.js +3 -95
  19. package/dist/testing/fakes.d.ts +15 -97
  20. package/dist/testing/fakes.js +12 -104
  21. package/dist/testing/index.d.ts +8 -3
  22. package/dist/testing/index.js +8 -2
  23. package/docs/api-business-time.md +47 -30
  24. package/docs/api-db.md +48 -29
  25. package/docs/api-offline.md +11 -15
  26. package/docs/api-root.md +64 -58
  27. package/docs/api-testing.md +41 -13
  28. package/docs/api.md +35 -12
  29. package/docs/cli.md +11 -7
  30. package/docs/data-layer.md +68 -5
  31. package/docs/development.md +125 -5
  32. package/docs/http-auth.md +15 -0
  33. package/docs/realtime-offline.md +15 -0
  34. package/docs/role-policies.md +4 -4
  35. package/docs/testing-operations.md +25 -2
  36. package/package.json +24 -18
  37. package/scripts/db-baseline.mjs +3 -68
  38. package/scripts/workspace-package-smoke.mjs +206 -0
  39. package/dist/business-time/types.d.ts +0 -9
  40. package/dist/business-time/types.js +0 -5
  41. package/dist/db/columns.d.ts +0 -38
  42. package/dist/db/columns.js +0 -38
  43. package/dist/db/connection.d.ts +0 -74
  44. package/dist/db/connection.js +0 -67
  45. package/dist/db/database.d.ts +0 -249
  46. package/dist/db/database.js +0 -196
  47. package/dist/db/jst.d.ts +0 -45
  48. package/dist/db/jst.js +0 -47
  49. package/dist/db/migrate.d.ts +0 -51
  50. package/dist/db/migrate.js +0 -109
  51. package/dist/db/orm-config.d.ts +0 -127
  52. package/dist/db/orm-config.js +0 -122
  53. package/dist/db/retry.d.ts +0 -28
  54. package/dist/db/retry.js +0 -56
  55. package/dist/db/write-result.d.ts +0 -39
  56. package/dist/db/write-result.js +0 -34
@@ -1,249 +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
- * Read-only transactions are serialized on a separately cached primary connection so their
110
- * snapshot boundaries cannot mix with ordinary primary operations or with each other. Do not call
111
- * `readTransaction()` recursively from its own callback.
112
- *
113
- * @typeParam TDrizzle - the consumer's Drizzle ORM type.
114
- * @typeParam TTx - the transaction-handle type, inferred from `TDrizzle` by default.
115
- */
116
- export interface HyperdriveDatabase<TDrizzle, TTx = TxOf<TDrizzle>> extends DisposableDatabase<TDrizzle, TTx> {
117
- /**
118
- * Run a raw SQL SELECT against the primary database.
119
- *
120
- * @typeParam T - the complete rows result type (for example, `User[]`).
121
- * @param sql - the SQL text, with `?` placeholders for `params`.
122
- * @param params - optional positional parameters.
123
- * @returns the rows returned by the query, typed as `T`.
124
- */
125
- query<T = unknown>(sql: string, params?: unknown[]): Promise<T>;
126
- /**
127
- * Run a repeatable-read, consistent snapshot on the primary database.
128
- *
129
- * @remarks
130
- * The callback is repeated at most once on a fresh connection after a fatal connection error.
131
- * This is safe only because the transaction is declared read-only. Use {@link transaction} for
132
- * writes; write transactions are never repeated after connection loss. Calls are serialized on
133
- * one dedicated connection, so recursive `readTransaction()` calls are not supported.
134
- */
135
- readTransaction<T>(fn: (reader: ReadTransaction<TTx>) => Promise<T>): Promise<T>;
136
- }
137
- /** Primary read-only transaction handles that share one consistent snapshot. */
138
- export interface ReadTransaction<TTx> {
139
- /**
140
- * The consumer's Drizzle transaction handle.
141
- *
142
- * @remarks
143
- * Drizzle's type does not distinguish read-only transactions. MySQL enforces read-only mode at
144
- * runtime; applications may expose a narrower SELECT-only facade when they need compile-time
145
- * enforcement.
146
- */
147
- orm: TTx;
148
- /** Run raw SQL on the same primary connection and snapshot. */
149
- query: <T = unknown>(sql: string, params?: unknown[]) => Promise<T>;
150
- }
151
- /**
152
- * Options for {@link createMysqlDatabase}.
153
- *
154
- * @typeParam TDrizzle - the consumer's Drizzle ORM type.
155
- */
156
- export interface CreateMysqlDatabaseOptions<TDrizzle> {
157
- /**
158
- * The Drizzle ORM used for writes, created by the consumer with its own `drizzle-orm`
159
- * (e.g. `drizzle(primary, { schema, ... })`).
160
- */
161
- orm: TDrizzle;
162
- /** The connection used for reads (raw SQL). */
163
- replica: QueryRunner;
164
- }
165
- /**
166
- * Assemble a {@link Database} from an already-connected ORM and replica.
167
- *
168
- * @remarks
169
- * The caller (typically the worker entry point) owns creating the connections and the ORM, and is
170
- * responsible for closing the connections; this variant does not manage their lifecycle.
171
- *
172
- * @typeParam TDrizzle - the consumer's Drizzle ORM type.
173
- * @param options - the write ORM and the read connection.
174
- * @returns a {@link Database} backed by the supplied ORM and replica.
175
- * @example
176
- * ```ts
177
- * const db = createMysqlDatabase({
178
- * orm: drizzle(primary, { schema, ...DRIZZLE_ORM_OPTIONS }),
179
- * replica,
180
- * });
181
- * const rows = await db.read<User>('SELECT * FROM users WHERE id = ?', [id]);
182
- * ```
183
- */
184
- export declare function createMysqlDatabase<TDrizzle>(options: CreateMysqlDatabaseOptions<TDrizzle>): Database<TDrizzle>;
185
- /**
186
- * Options for {@link createHyperdriveDatabase}.
187
- *
188
- * @typeParam TDrizzle - the consumer's Drizzle ORM type.
189
- */
190
- export interface CreateHyperdriveDatabaseOptions<TDrizzle> {
191
- /** The Hyperdrive binding for the primary (write) connection. */
192
- primaryHyperdrive: HyperdriveLike;
193
- /** The Hyperdrive binding for the replica (read) connection. */
194
- replicaHyperdrive: HyperdriveLike;
195
- /**
196
- * Factory that builds the write ORM from the primary connection, using the consumer's
197
- * `drizzle-orm`.
198
- */
199
- createOrm: (primary: Connection) => TDrizzle;
200
- /**
201
- * Extra options forwarded to mysql2 `createConnection`, merged on top of the defaults applied by
202
- * {@link hyperdriveConnectionOptions} (`disableEval: true`, `decimalNumbers: true`, and
203
- * `timezone: '+09:00'`). Pass a field here to override any of those defaults.
204
- */
205
- connectionOptions?: Record<string, unknown>;
206
- }
207
- /**
208
- * Create a {@link HyperdriveDatabase} that lazily opens its connections from Hyperdrive bindings.
209
- *
210
- * @remarks
211
- * Construct one per request. Connections and the ORM are created on first use and reused for the
212
- * lifetime of the instance. `read()` uses the replica, while `query()` provides an explicit
213
- * primary SELECT path. Workers automatically cleans up connections at the end of the invocation,
214
- * so callers do not need to close them manually. Either SELECT path is repeated once on a fresh
215
- * connection after a fatal mysql2 connection error. Writes and transactions are never repeated
216
- * for connection errors because their commit state can be ambiguous.
217
- *
218
- * @typeParam TDrizzle - the consumer's Drizzle ORM type.
219
- * @param options - the primary/replica Hyperdrive bindings, the ORM factory, and connection options.
220
- * @returns a {@link HyperdriveDatabase} whose compatibility `dispose()` method is a no-op; Workers
221
- * cleans up its invocation-scoped connections automatically.
222
- * @example
223
- * ```ts
224
- * const db = createHyperdriveDatabase({
225
- * primaryHyperdrive: env.PRIMARY,
226
- * replicaHyperdrive: env.REPLICA,
227
- * createOrm: (primary) => drizzle(primary, { schema, ...DRIZZLE_ORM_OPTIONS }),
228
- * });
229
- * await db.write((dz) => dz.insert(users).values(user));
230
- * ```
231
- */
232
- export declare function createHyperdriveDatabase<TDrizzle>(options: CreateHyperdriveDatabaseOptions<TDrizzle>): HyperdriveDatabase<TDrizzle>;
233
- /**
234
- * Internal helper that assembles a {@link Database} from an ORM and a replica connection.
235
- *
236
- * @typeParam TDrizzle - the consumer's Drizzle ORM type.
237
- * @param orm - the Drizzle ORM used for writes and transactions.
238
- * @param replica - the connection used for reads.
239
- * @returns a {@link Database} wiring reads to `replica` and writes to `orm`, both with deadlock retry.
240
- * @internal
241
- */
242
- export declare function databaseFrom<TDrizzle>(orm: TDrizzle, replica: QueryRunner): Database<TDrizzle>;
243
- /**
244
- * Re-export of the mysql2 `Connection` and `Pool` types.
245
- *
246
- * @remarks
247
- * Both are structurally assignable to the kit's {@link QueryRunner}.
248
- */
249
- export type { Connection, Pool };
@@ -1,196 +0,0 @@
1
- import { createConnection } from 'mysql2/promise';
2
- import { hyperdriveConnectionOptions } from './connection.js';
3
- import { retryWhenDeadlock } from './retry.js';
4
- /**
5
- * Assemble a {@link Database} from an already-connected ORM and replica.
6
- *
7
- * @remarks
8
- * The caller (typically the worker entry point) owns creating the connections and the ORM, and is
9
- * responsible for closing the connections; this variant does not manage their lifecycle.
10
- *
11
- * @typeParam TDrizzle - the consumer's Drizzle ORM type.
12
- * @param options - the write ORM and the read connection.
13
- * @returns a {@link Database} backed by the supplied ORM and replica.
14
- * @example
15
- * ```ts
16
- * const db = createMysqlDatabase({
17
- * orm: drizzle(primary, { schema, ...DRIZZLE_ORM_OPTIONS }),
18
- * replica,
19
- * });
20
- * const rows = await db.read<User>('SELECT * FROM users WHERE id = ?', [id]);
21
- * ```
22
- */
23
- export function createMysqlDatabase(options) {
24
- return databaseFrom(options.orm, options.replica);
25
- }
26
- /**
27
- * Create a {@link HyperdriveDatabase} that lazily opens its connections from Hyperdrive bindings.
28
- *
29
- * @remarks
30
- * Construct one per request. Connections and the ORM are created on first use and reused for the
31
- * lifetime of the instance. `read()` uses the replica, while `query()` provides an explicit
32
- * primary SELECT path. Workers automatically cleans up connections at the end of the invocation,
33
- * so callers do not need to close them manually. Either SELECT path is repeated once on a fresh
34
- * connection after a fatal mysql2 connection error. Writes and transactions are never repeated
35
- * for connection errors because their commit state can be ambiguous.
36
- *
37
- * @typeParam TDrizzle - the consumer's Drizzle ORM type.
38
- * @param options - the primary/replica Hyperdrive bindings, the ORM factory, and connection options.
39
- * @returns a {@link HyperdriveDatabase} whose compatibility `dispose()` method is a no-op; Workers
40
- * cleans up its invocation-scoped connections automatically.
41
- * @example
42
- * ```ts
43
- * const db = createHyperdriveDatabase({
44
- * primaryHyperdrive: env.PRIMARY,
45
- * replicaHyperdrive: env.REPLICA,
46
- * createOrm: (primary) => drizzle(primary, { schema, ...DRIZZLE_ORM_OPTIONS }),
47
- * });
48
- * await db.write((dz) => dz.insert(users).values(user));
49
- * ```
50
- */
51
- export function createHyperdriveDatabase(options) {
52
- const { primaryHyperdrive, replicaHyperdrive, createOrm, connectionOptions } = options;
53
- let primaryConn;
54
- let replicaConn;
55
- let readTransactionConn;
56
- let orm;
57
- let readTransactionOrm;
58
- let readTransactionTail;
59
- const primary = () => (primaryConn ??= connect(primaryHyperdrive, connectionOptions));
60
- const replica = () => (replicaConn ??= connect(replicaHyperdrive, connectionOptions));
61
- const readTransactionConnection = () => (readTransactionConn ??= connect(primaryHyperdrive, connectionOptions));
62
- const ormFor = async () => (orm ??= createOrm(await primary()));
63
- const readFrom = (connection, sql, params) => retryWhenDeadlock(async () => {
64
- const [rows] = (await (await connection).query(sql, params));
65
- return rows;
66
- });
67
- const readWithRecovery = async (connectionFor, reset, sql, params) => {
68
- const connection = connectionFor();
69
- const outcome = await readFrom(connection, sql, params).then((rows) => ({ ok: true, rows }), (error) => ({ ok: false, error }));
70
- if (outcome.ok) {
71
- return outcome.rows;
72
- }
73
- if (!isFatalConnectionError(outcome.error)) {
74
- throw outcome.error;
75
- }
76
- reset(connection);
77
- return readFrom(connectionFor(), sql, params);
78
- };
79
- const resetPrimary = (failedConnection) => {
80
- if (primaryConn === failedConnection) {
81
- primaryConn = undefined;
82
- orm = undefined;
83
- }
84
- };
85
- const resetReadTransaction = (failedConnection) => {
86
- if (readTransactionConn === failedConnection) {
87
- readTransactionConn = undefined;
88
- readTransactionOrm = undefined;
89
- }
90
- };
91
- const withReadTransactionLock = (fn) => {
92
- const result = readTransactionTail ? readTransactionTail.then(fn, fn) : fn();
93
- readTransactionTail = result.then(() => undefined, () => undefined);
94
- return result;
95
- };
96
- const runReadTransaction = async (connection, fn) => {
97
- const conn = await connection;
98
- const dz = (readTransactionOrm ??= createOrm(conn));
99
- return retryWhenDeadlock(async () => {
100
- await conn.query('SET TRANSACTION READ ONLY');
101
- return dz.transaction((tx) => fn({
102
- orm: tx,
103
- query: async (sql, params = []) => {
104
- const [rows] = (await conn.query(sql, params));
105
- return rows;
106
- },
107
- }), { isolationLevel: 'repeatable read', withConsistentSnapshot: true });
108
- });
109
- };
110
- return {
111
- read(sql, params = []) {
112
- return readWithRecovery(replica, (failedConnection) => {
113
- if (replicaConn === failedConnection) {
114
- replicaConn = undefined;
115
- }
116
- }, sql, params);
117
- },
118
- query(sql, params = []) {
119
- return readWithRecovery(primary, resetPrimary, sql, params);
120
- },
121
- async readTransaction(fn) {
122
- return withReadTransactionLock(async () => {
123
- const connection = readTransactionConnection();
124
- const outcome = await runReadTransaction(connection, fn).then((value) => ({ ok: true, value }), (error) => ({ ok: false, error }));
125
- if (outcome.ok) {
126
- return outcome.value;
127
- }
128
- if (!isFatalConnectionError(outcome.error)) {
129
- throw outcome.error;
130
- }
131
- resetReadTransaction(connection);
132
- return runReadTransaction(readTransactionConnection(), fn);
133
- });
134
- },
135
- async write(fn) {
136
- const dz = await ormFor();
137
- return retryWhenDeadlock(() => fn(dz));
138
- },
139
- async transaction(fn) {
140
- const dz = (await ormFor());
141
- return retryWhenDeadlock(() => dz.transaction(fn));
142
- },
143
- /** @deprecated Workers cleans up invocation-scoped connections automatically. */
144
- async dispose() {
145
- return;
146
- },
147
- };
148
- }
149
- /**
150
- * Internal helper that assembles a {@link Database} from an ORM and a replica connection.
151
- *
152
- * @typeParam TDrizzle - the consumer's Drizzle ORM type.
153
- * @param orm - the Drizzle ORM used for writes and transactions.
154
- * @param replica - the connection used for reads.
155
- * @returns a {@link Database} wiring reads to `replica` and writes to `orm`, both with deadlock retry.
156
- * @internal
157
- */
158
- export function databaseFrom(orm, replica) {
159
- const drizzleLike = orm;
160
- return {
161
- read(sql, params = []) {
162
- return retryWhenDeadlock(async () => {
163
- const [rows] = (await replica.query(sql, params));
164
- return rows;
165
- });
166
- },
167
- write(fn) {
168
- return retryWhenDeadlock(() => fn(orm));
169
- },
170
- transaction(fn) {
171
- return retryWhenDeadlock(() => drizzleLike.transaction(fn));
172
- },
173
- };
174
- }
175
- function connect(hyperdrive, extra) {
176
- return createConnection(hyperdriveConnectionOptions(hyperdrive, extra));
177
- }
178
- function isFatalConnectionError(error) {
179
- let current = error;
180
- const seen = new Set();
181
- while (typeof current === 'object' && current !== null && !seen.has(current)) {
182
- seen.add(current);
183
- const value = current;
184
- if (value.fatal === true ||
185
- value.code === 'PROTOCOL_CONNECTION_LOST' ||
186
- value.code === 'ECONNRESET' ||
187
- value.code === 'EPIPE' ||
188
- (typeof value.message === 'string' &&
189
- (value.message.includes('Connection lost:') ||
190
- value.message.includes("Can't add new command when connection is in closed state")))) {
191
- return true;
192
- }
193
- current = value.cause;
194
- }
195
- return false;
196
- }
package/dist/db/jst.d.ts DELETED
@@ -1,45 +0,0 @@
1
- /**
2
- * JST wire conversion and DATE-column normalization for MySQL / Drizzle.
3
- *
4
- * @remarks
5
- * Business-time semantics are consolidated in {@link ../business-time/index.js | business-time}. This
6
- * module only owns the MySQL connection default, the DATE column's `toDriver`, and the column
7
- * `customType` params.
8
- */
9
- import type { BusinessDate } from '../business-time/index.js';
10
- /** Default mysql2 connection `timezone` (for the existing JST DB deployment). */
11
- export declare const MYSQL_TIMEZONE = "+09:00";
12
- /**
13
- * Normalize a client input to `YYYY-MM-DD` (a JST business calendar date) for a MySQL `DATE` column.
14
- * Accepts ISO 8601 / `YYYY-MM-DD` / empty strings. A `YYYY-MM-DD` value is passed through without
15
- * constructing a `Date`.
16
- *
17
- * @param value - the string or nullish input to normalize.
18
- * @returns the business date as `YYYY-MM-DD`, or `null` when the input cannot be resolved.
19
- */
20
- export declare function toJstDate(value: string | null | undefined): BusinessDate | null;
21
- /**
22
- * Build the params for a `customType` backing a MySQL `timestamp` column with `Date` pass-through.
23
- *
24
- * @param fsp - optional fractional-seconds precision; when provided, emits `timestamp(fsp)`.
25
- */
26
- export declare const jstTimestampParams: (fsp?: number) => {
27
- dataType: () => string;
28
- };
29
- /**
30
- * Build the params for a `customType` backing a MySQL `datetime` column with `Date` pass-through.
31
- *
32
- * @param fsp - optional fractional-seconds precision; when provided, emits `datetime(fsp)`.
33
- */
34
- export declare const jstDatetimeParams: (fsp?: number) => {
35
- dataType: () => string;
36
- };
37
- /**
38
- * Build the params for a `customType` backing a MySQL `date` column with JST normalization.
39
- *
40
- * @returns params with `toDriver` running {@link toJstDate}.
41
- */
42
- export declare const jstDateParams: () => {
43
- dataType: () => string;
44
- toDriver: (value: string | null) => string | null;
45
- };
package/dist/db/jst.js DELETED
@@ -1,47 +0,0 @@
1
- /**
2
- * JST wire conversion and DATE-column normalization for MySQL / Drizzle.
3
- *
4
- * @remarks
5
- * Business-time semantics are consolidated in {@link ../business-time/index.js | business-time}. This
6
- * module only owns the MySQL connection default, the DATE column's `toDriver`, and the column
7
- * `customType` params.
8
- */
9
- import { normalizeBusinessDate } from '../business-time/index.js';
10
- /** Default mysql2 connection `timezone` (for the existing JST DB deployment). */
11
- export const MYSQL_TIMEZONE = '+09:00';
12
- /**
13
- * Normalize a client input to `YYYY-MM-DD` (a JST business calendar date) for a MySQL `DATE` column.
14
- * Accepts ISO 8601 / `YYYY-MM-DD` / empty strings. A `YYYY-MM-DD` value is passed through without
15
- * constructing a `Date`.
16
- *
17
- * @param value - the string or nullish input to normalize.
18
- * @returns the business date as `YYYY-MM-DD`, or `null` when the input cannot be resolved.
19
- */
20
- export function toJstDate(value) {
21
- return normalizeBusinessDate(value ?? null);
22
- }
23
- /**
24
- * Build the params for a `customType` backing a MySQL `timestamp` column with `Date` pass-through.
25
- *
26
- * @param fsp - optional fractional-seconds precision; when provided, emits `timestamp(fsp)`.
27
- */
28
- export const jstTimestampParams = (fsp) => ({
29
- dataType: () => (fsp != null ? `timestamp(${fsp})` : 'timestamp'),
30
- });
31
- /**
32
- * Build the params for a `customType` backing a MySQL `datetime` column with `Date` pass-through.
33
- *
34
- * @param fsp - optional fractional-seconds precision; when provided, emits `datetime(fsp)`.
35
- */
36
- export const jstDatetimeParams = (fsp) => ({
37
- dataType: () => (fsp != null ? `datetime(${fsp})` : 'datetime'),
38
- });
39
- /**
40
- * Build the params for a `customType` backing a MySQL `date` column with JST normalization.
41
- *
42
- * @returns params with `toDriver` running {@link toJstDate}.
43
- */
44
- export const jstDateParams = () => ({
45
- dataType: () => 'date',
46
- toDriver: (value) => toJstDate(value),
47
- });
@@ -1,51 +0,0 @@
1
- import type { QueryRunner } from './database.js';
2
- /** Identifying info for the baseline (i.e. first) migration. */
3
- export interface BaselineEntry {
4
- /** The migration tag (e.g. `0000_melted_weapon_omega`). */
5
- tag: string;
6
- /** The `when` from `_journal.json` (= drizzle's `created_at` / `folderMillis`). */
7
- when: number;
8
- /** The sha256 of the raw `<tag>.sql` contents (the same algorithm as drizzle). */
9
- hash: string;
10
- }
11
- /**
12
- * Read the baseline (first) entry from `migrationsFolder` (drizzle's `out`, e.g. `./drizzle`).
13
- *
14
- * @param migrationsFolder - the folder containing `meta/_journal.json` and `<tag>.sql`.
15
- * @returns the baseline entry (tag/when/hash).
16
- * @throws Error when the journal is missing, the entries are empty, or `<tag>.sql` is missing.
17
- */
18
- export declare function readBaselineEntry(migrationsFolder: string): BaselineEntry;
19
- /** Options for {@link baselineMigrations}. */
20
- export interface BaselineMigrationsOptions {
21
- /** A QueryRunner for raw SQL (a mysql2 `Connection`/`Pool` is assignable). Must already be connected to the target DB. */
22
- db: QueryRunner;
23
- /** Drizzle's `out` folder (defaults to `./drizzle`). */
24
- migrationsFolder?: string;
25
- }
26
- /** The result of {@link baselineMigrations}. */
27
- export type BaselineResult = {
28
- status: 'inserted';
29
- tag: string;
30
- when: number;
31
- hash: string;
32
- } | {
33
- status: 'already-baselined';
34
- tag: string;
35
- when: number;
36
- };
37
- /**
38
- * Record the baseline (0000) as "applied" on an existing DB. Idempotent, with safety guards.
39
- *
40
- * @remarks
41
- * Guards:
42
- * - If a baseline marker (`created_at = when`) already exists → **no-op** (`already-baselined`).
43
- * - If there is no marker but `__drizzle_migrations` has other rows → **abort** (unexpected state).
44
- * - If the target DB has no base tables (an empty DB) → **abort** (skipping 0000 on an empty DB would
45
- * never create the tables; use `db:migrate` for a fresh DB).
46
- *
47
- * @param options - the connection and migrations folder; see {@link BaselineMigrationsOptions}.
48
- * @returns whether a marker was inserted or the DB was already baselined.
49
- * @throws Error when one of the guards above trips.
50
- */
51
- export declare function baselineMigrations(options: BaselineMigrationsOptions): Promise<BaselineResult>;