@rdlabo/workers-mysql 0.1.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.
@@ -0,0 +1,28 @@
1
+ ---
2
+ title: Migration
3
+ ---
4
+
5
+ # Migration
6
+
7
+ The database utilities are standalone from kit `0.12.0`. Install `@rdlabo/workers-mysql` directly;
8
+ keep `@rdlabo/workers-hono-kit` only if using its Hono integration. `mysql2` is included, while
9
+ `drizzle-orm` remains an optional peer for `/drizzle` and `/testing`. TypeScript consumers need
10
+ the Node declarations described in the [README](../README.md).
11
+
12
+ | Previous import | New import |
13
+ | -------------------------------------- | ---------------------------------- |
14
+ | Kit root `createContainerRuntime` | `@rdlabo/workers-hono-kit/mysql` |
15
+ | Kit root `retryWhenDeadlock` | `@rdlabo/workers-mysql` |
16
+ | Kit `/db` runtime and JST wire helpers | `@rdlabo/workers-mysql` |
17
+ | Kit `/db` column/configuration helpers | `@rdlabo/workers-mysql/drizzle` |
18
+ | Kit `/db` baseline helpers | `@rdlabo/workers-mysql/migrations` |
19
+ | Kit `/testing` database helpers | `@rdlabo/workers-mysql/testing` |
20
+
21
+ The old `/db` and DB-related `/testing` paths remain available as maintained compatibility
22
+ re-exports with `@deprecated` notices; there is no planned removal. Do not import the legacy
23
+ aggregate `/db` in new Worker code: use the dedicated runtime entry points to keep Node-only
24
+ migration code out of the Worker bundle. Rename `honoDrizzleConfig` to `workersDrizzleConfig` when
25
+ updating configuration.
26
+
27
+ No Hono dependency is required by this database package. The fixed-JST storage contract also
28
+ remains separate from configurable business timezones; see [Drizzle and dates](./drizzle.md).
@@ -0,0 +1,72 @@
1
+ ---
2
+ title: Runtime
3
+ ---
4
+
5
+ # Runtime
6
+
7
+ Enable `nodejs_compat` in your Worker and install the dependencies described in the
8
+ [README](../README.md). `mysql2` is included; the package does not depend on Hono.
9
+ The application supplies its Hyperdrive bindings, schema, and ORM factory.
10
+
11
+ ## Invocation lifetime
12
+
13
+ Create `createHyperdriveDatabase` inside each invocation, not in module-global state. Connections
14
+ open lazily and are reused by that database instance. The runtime cleans up invocation connections;
15
+ its compatibility `dispose()` method is a no-op.
16
+
17
+ This complete Worker example uses one Hyperdrive binding for both roles. Applications with a
18
+ replica can supply a separate binding for `replicaHyperdrive`:
19
+
20
+ ```ts
21
+ import { createHyperdriveDatabase, type HyperdriveLike } from '@rdlabo/workers-mysql';
22
+ import { DRIZZLE_ORM_OPTIONS } from '@rdlabo/workers-mysql/drizzle';
23
+ import { drizzle } from 'drizzle-orm/mysql2';
24
+
25
+ interface Env {
26
+ DB: HyperdriveLike;
27
+ }
28
+
29
+ export default {
30
+ async fetch(_request: Request, env: Env): Promise<Response> {
31
+ const db = createHyperdriveDatabase({
32
+ primaryHyperdrive: env.DB,
33
+ replicaHyperdrive: env.DB,
34
+ createOrm: (connection) => drizzle(connection, DRIZZLE_ORM_OPTIONS),
35
+ });
36
+ const rows = await db.query<Array<{ value: number }>>('SELECT ? AS value', [1]);
37
+ return Response.json(rows);
38
+ },
39
+ };
40
+ ```
41
+
42
+ ## Read and write paths
43
+
44
+ | Operation | Destination | Result type parameter |
45
+ | --------------------------- | --------------------------- | --------------------------------- |
46
+ | `read<Row>(sql, params?)` | Replica | One row; returns `Row[]` |
47
+ | `query<Rows>(sql, params?)` | Primary SELECT | Whole result, for example `Row[]` |
48
+ | `readTransaction(fn)` | Primary consistent snapshot | Callback result |
49
+ | `write(fn)` | Primary ORM | Awaited callback result |
50
+ | `transaction(fn)` | Primary transaction | Awaited callback result |
51
+
52
+ Use `query` for reads that cannot tolerate replica lag. Query caching, if enabled on a Hyperdrive
53
+ binding, is a separate configuration concern. Use parameter placeholders, not interpolated SQL.
54
+
55
+ `readTransaction` passes `{ orm, query }` on one read-only snapshot. Its calls are serialized on a
56
+ dedicated connection; do not call it recursively inside its callback.
57
+
58
+ ## Retry boundaries
59
+
60
+ Database operations retry deadlocks. Return/await the write builder or promise from callbacks.
61
+ The whole transaction callback can run again: keep email, payments, and other external side effects
62
+ outside it. Do not add another `retryWhenDeadlock` wrapper around an already-retrying operation.
63
+
64
+ Hyperdrive SELECTs and read-only transactions can additionally repeat once on a fresh connection
65
+ after a fatal connection error. Writes and write transactions are not replayed for connection loss:
66
+ the outcome may be unknown. Handle application idempotency before retrying such a request.
67
+
68
+ `createMysqlDatabase({ orm, replica })` and `databaseFrom(orm, replica)` wrap existing handles;
69
+ their caller owns connection cleanup. They expose `Database`, not the extra Hyperdrive primary-read
70
+ methods. For Hono containers, use `@rdlabo/workers-hono-kit/mysql` (kit `0.12.0` or later).
71
+
72
+ See [Drizzle and dates](./drizzle.md) for connection defaults and [API](./api.md) for exports.
@@ -0,0 +1,51 @@
1
+ ---
2
+ title: Migrations and testing
3
+ ---
4
+
5
+ # Migrations and testing
6
+
7
+ These helpers are for Node.js tooling, not Worker request bundles. Import them from their dedicated
8
+ entry points. The consumer owns migrations, credentials, test fixtures, and database provisioning.
9
+
10
+ ## Drizzle configuration
11
+
12
+ `workersDrizzleConfig` from `/drizzle` builds a MySQL Drizzle Kit configuration with snake-case
13
+ casing. Supply your `database`, `schema`, and `out` paths explicitly.
14
+ `workersDrizzleConfig` automatically reads `DB_SECRET`: when set, its connection details override
15
+ even explicitly supplied `database`, host, port, user, and password options, as well as `DB_*`
16
+ environment variables. Before running migrations, verify the secret's target; specifying a local
17
+ `database` option alone does not restrict the connection to that database.
18
+ `resolveDbSecret()` reads `DB_SECRET` JSON (`host`, `username`, `password`, `dbname`, optional
19
+ `port`). It returns `undefined` if unset and throws for invalid input rather than silently falling
20
+ back. Never commit or log database secrets.
21
+
22
+ ## Existing-database baseline
23
+
24
+ `baselineMigrations({ db, migrationsFolder })` from `/migrations` records the first migration as
25
+ applied **without executing its schema SQL**. It does not verify that the existing schema matches
26
+ that SQL. Compare them, back up the target, and confirm credentials before invoking it.
27
+
28
+ For a fresh database, run the normal Drizzle migrator, not baseline. Baseline refuses an empty
29
+ database or unexpected migration history and is a no-op if the baseline marker already exists.
30
+
31
+ The installed CLI is `workers-mysql-db-baseline --migrations ./drizzle`. It uses `DB_SECRET` or
32
+ `DB_HOST`, `DB_PORT`, `DB_USER`, `DB_PASSWORD`, and `DB_NAME`. This command writes migration
33
+ metadata; it is not a dry run. `/baseline-cli` exports `runBaselineCli` for tooling integrations.
34
+
35
+ ## Local tests
36
+
37
+ `createTestDb({ dbName, migrationsFolder, connection })` from `/testing` returns fixture helpers.
38
+ Use an isolated disposable database and explicit local connection settings:
39
+
40
+ - `resetSchema()` **drops and recreates the database**, then applies migrations.
41
+ - `truncateAll(pool)` deletes table contents, excluding migration bookkeeping.
42
+ - `seed(pool, table, row)` inserts a fixture.
43
+ - `createTestPool()` creates a pool; close it with `pool.end()` after testing.
44
+ - `mysqlReachable()` probes connectivity, not schema correctness.
45
+
46
+ Never point these helpers at shared or production data. Distinct test runs should use distinct
47
+ database names. `createPoolDatabase({ pool, orm })` uses one pool for reads/writes and closes it
48
+ on `dispose()`. `createNoopDatabase()` returns empty reads and throws on unexpected writes or
49
+ transactions; it is a stub, not an acceptance test against MySQL.
50
+
51
+ See [API](./api.md) for the available types.
package/package.json ADDED
@@ -0,0 +1,92 @@
1
+ {
2
+ "name": "@rdlabo/workers-mysql",
3
+ "version": "0.1.0-beta.pr48.sha371f5792ce8a",
4
+ "private": false,
5
+ "publishConfig": {
6
+ "access": "public",
7
+ "registry": "https://registry.npmjs.org/"
8
+ },
9
+ "type": "module",
10
+ "description": "MySQL and Hyperdrive utilities for Cloudflare Workers",
11
+ "license": "MIT",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/rdlabo-dev/workers-hono-kit.git",
15
+ "directory": "packages/mysql"
16
+ },
17
+ "bugs": {
18
+ "url": "https://github.com/rdlabo-dev/workers-hono-kit/issues"
19
+ },
20
+ "homepage": "https://github.com/rdlabo-dev/workers-hono-kit/tree/main/packages/mysql#readme",
21
+ "files": [
22
+ "dist",
23
+ "bin",
24
+ "docs"
25
+ ],
26
+ "bin": {
27
+ "workers-mysql-db-baseline": "./bin/db-baseline.mjs"
28
+ },
29
+ "exports": {
30
+ ".": {
31
+ "types": "./dist/index.d.ts",
32
+ "import": "./dist/index.js",
33
+ "default": "./dist/index.js"
34
+ },
35
+ "./drizzle": {
36
+ "types": "./dist/drizzle.d.ts",
37
+ "import": "./dist/drizzle.js",
38
+ "default": "./dist/drizzle.js"
39
+ },
40
+ "./migrations": {
41
+ "types": "./dist/migrations.d.ts",
42
+ "import": "./dist/migrations.js",
43
+ "default": "./dist/migrations.js"
44
+ },
45
+ "./baseline-cli": {
46
+ "types": "./dist/baseline-cli.d.ts",
47
+ "import": "./dist/baseline-cli.js",
48
+ "default": "./dist/baseline-cli.js"
49
+ },
50
+ "./testing": {
51
+ "types": "./dist/testing/index.d.ts",
52
+ "import": "./dist/testing/index.js",
53
+ "default": "./dist/testing/index.js"
54
+ }
55
+ },
56
+ "scripts": {
57
+ "build": "tsc -p tsconfig.build.json",
58
+ "typecheck": "tsc --noEmit",
59
+ "test": "vitest run",
60
+ "test:package": "node scripts/package-smoke.mjs",
61
+ "lint": "eslint \"src/**/*.ts\"",
62
+ "lint:fix": "eslint \"src/**/*.ts\" --fix",
63
+ "format": "prettier --write .",
64
+ "format:check": "prettier --check .",
65
+ "prepack": "npm run build"
66
+ },
67
+ "engines": {
68
+ "node": ">=20.0.0"
69
+ },
70
+ "dependencies": {
71
+ "mysql2": "^3.24.3"
72
+ },
73
+ "peerDependencies": {
74
+ "@types/node": ">=20.19.43",
75
+ "drizzle-orm": "^0.45.2"
76
+ },
77
+ "peerDependenciesMeta": {
78
+ "drizzle-orm": {
79
+ "optional": true
80
+ }
81
+ },
82
+ "devDependencies": {
83
+ "@hono/eslint-config": "^2.1.0",
84
+ "@rdlabo/workers-timezone": "0.1.0-beta.pr48.sha371f5792ce8a",
85
+ "drizzle-orm": "^0.45.2",
86
+ "eslint": "^9.39.4",
87
+ "prettier": "^3.8.4",
88
+ "typescript": "~5.6.2",
89
+ "typescript-eslint": "^8.61.1",
90
+ "vitest": "^2.1.0"
91
+ }
92
+ }