@jskit-ai/database-runtime-mysql 0.1.156 → 0.1.158
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/package.json +11 -157
- package/patterns/mysql-application/PATTERN.md +80 -0
- package/patterns/mysql-application/example/.env.example +5 -0
- package/patterns/mysql-application/example/.github/workflows/verify.yml +39 -0
- package/patterns/mysql-application/example/knexfile.js +11 -0
- package/patterns/mysql-application/example/package.json +13 -0
- package/patterns/mysql-application/example/scripts/prepare-database.js +3 -0
- package/src/server/providers/MysqlDatabaseDriverProvider.js +16 -0
- package/test/applicationPattern.test.js +18 -0
- package/test/entrypoints.boundary.test.js +7 -6
- package/test/packageMetadata.test.js +16 -17
- package/test/providerRuntime.test.js +17 -27
- package/src/server/providers/DatabaseRuntimeMysqlServiceProvider.js +0 -21
package/package.json
CHANGED
|
@@ -1,73 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/database-runtime-mysql",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.158",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
7
7
|
},
|
|
8
8
|
"exports": {
|
|
9
9
|
"./client": "./src/client/index.js",
|
|
10
|
-
"./server/providers/
|
|
10
|
+
"./server/providers/MysqlDatabaseDriverProvider": "./src/server/providers/MysqlDatabaseDriverProvider.js",
|
|
11
11
|
"./shared": "./src/shared/index.js",
|
|
12
12
|
"./shared/dialect": "./src/shared/dialect.js"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@jskit-ai/database-runtime": "0.1.
|
|
16
|
-
"@jskit-ai/kernel": "0.1.
|
|
15
|
+
"@jskit-ai/database-runtime": "0.1.160",
|
|
16
|
+
"@jskit-ai/kernel": "0.1.160",
|
|
17
|
+
"mysql2": "^3.11.2"
|
|
17
18
|
},
|
|
18
19
|
"jskit": {
|
|
19
20
|
"kind": "runtime",
|
|
20
|
-
"options": {
|
|
21
|
-
"db-host": {
|
|
22
|
-
"required": false,
|
|
23
|
-
"values": [],
|
|
24
|
-
"defaultValue": "localhost",
|
|
25
|
-
"promptLabel": "Database host",
|
|
26
|
-
"promptHint": "MySQL host (for example 127.0.0.1)"
|
|
27
|
-
},
|
|
28
|
-
"db-port": {
|
|
29
|
-
"required": false,
|
|
30
|
-
"values": [],
|
|
31
|
-
"defaultValue": "3306",
|
|
32
|
-
"promptLabel": "Database port",
|
|
33
|
-
"promptHint": "MySQL port (usually 3306)"
|
|
34
|
-
},
|
|
35
|
-
"db-name": {
|
|
36
|
-
"required": true,
|
|
37
|
-
"values": [],
|
|
38
|
-
"promptLabel": "Database name",
|
|
39
|
-
"promptHint": "Schema/database name to connect to"
|
|
40
|
-
},
|
|
41
|
-
"db-user": {
|
|
42
|
-
"required": true,
|
|
43
|
-
"values": [],
|
|
44
|
-
"promptLabel": "Database user",
|
|
45
|
-
"promptHint": "Database username"
|
|
46
|
-
},
|
|
47
|
-
"db-password": {
|
|
48
|
-
"required": true,
|
|
49
|
-
"values": [],
|
|
50
|
-
"inputType": "password",
|
|
51
|
-
"promptLabel": "Database password",
|
|
52
|
-
"promptHint": "Database password"
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
21
|
"capabilities": {
|
|
56
22
|
"provides": [
|
|
57
|
-
"runtime.database.driver"
|
|
58
|
-
"runtime.database.driver.mysql"
|
|
23
|
+
"runtime.database.driver"
|
|
59
24
|
],
|
|
60
|
-
"requires": [
|
|
61
|
-
"runtime.database"
|
|
62
|
-
]
|
|
25
|
+
"requires": []
|
|
63
26
|
},
|
|
64
27
|
"runtime": {
|
|
65
28
|
"server": {
|
|
66
|
-
"providerEntrypoint": "src/server/providers/DatabaseRuntimeMysqlServiceProvider.js",
|
|
67
29
|
"providers": [
|
|
68
30
|
{
|
|
69
|
-
"entrypoint": "src/server/providers/
|
|
70
|
-
"export": "
|
|
31
|
+
"entrypoint": "src/server/providers/MysqlDatabaseDriverProvider.js",
|
|
32
|
+
"export": "MysqlDatabaseDriverProvider"
|
|
71
33
|
}
|
|
72
34
|
]
|
|
73
35
|
},
|
|
@@ -80,7 +42,7 @@
|
|
|
80
42
|
"surfaces": [
|
|
81
43
|
{
|
|
82
44
|
"subpath": "./server",
|
|
83
|
-
"summary": "
|
|
45
|
+
"summary": "Provides the exclusive runtime.database.driver capability for MySQL."
|
|
84
46
|
},
|
|
85
47
|
{
|
|
86
48
|
"subpath": "./shared",
|
|
@@ -90,116 +52,8 @@
|
|
|
90
52
|
"subpath": "./client",
|
|
91
53
|
"summary": "Exports no runtime API today (reserved client entrypoint)."
|
|
92
54
|
}
|
|
93
|
-
]
|
|
94
|
-
"containerTokens": {
|
|
95
|
-
"server": [
|
|
96
|
-
"runtime.database.driver.mysql"
|
|
97
|
-
],
|
|
98
|
-
"client": []
|
|
99
|
-
}
|
|
55
|
+
]
|
|
100
56
|
}
|
|
101
|
-
},
|
|
102
|
-
"ci": {
|
|
103
|
-
"environment": {
|
|
104
|
-
"DB_CLIENT": "mysql2",
|
|
105
|
-
"DB_HOST": "127.0.0.1",
|
|
106
|
-
"DB_PORT": "33060",
|
|
107
|
-
"DB_NAME": "jskit_ci",
|
|
108
|
-
"DB_USER": "jskit_ci",
|
|
109
|
-
"DB_PASSWORD": "jskit_ci_only_password"
|
|
110
|
-
},
|
|
111
|
-
"services": [
|
|
112
|
-
{
|
|
113
|
-
"id": "mariadb",
|
|
114
|
-
"image": "mariadb:11.4",
|
|
115
|
-
"environment": {
|
|
116
|
-
"MARIADB_DATABASE": "jskit_ci",
|
|
117
|
-
"MARIADB_USER": "jskit_ci",
|
|
118
|
-
"MARIADB_PASSWORD": "jskit_ci_only_password",
|
|
119
|
-
"MARIADB_ROOT_PASSWORD": "jskit_ci_only_root_password"
|
|
120
|
-
},
|
|
121
|
-
"ports": [
|
|
122
|
-
"33060:3306"
|
|
123
|
-
],
|
|
124
|
-
"healthCheck": {
|
|
125
|
-
"command": "healthcheck.sh --connect --innodb_initialized",
|
|
126
|
-
"interval": "10s",
|
|
127
|
-
"timeout": "5s",
|
|
128
|
-
"retries": 10
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
],
|
|
132
|
-
"steps": []
|
|
133
|
-
},
|
|
134
|
-
"mutations": {
|
|
135
|
-
"dependencies": {
|
|
136
|
-
"runtime": {
|
|
137
|
-
"@jskit-ai/database-runtime": "0.1.158",
|
|
138
|
-
"mysql2": "^3.11.2"
|
|
139
|
-
},
|
|
140
|
-
"dev": {}
|
|
141
|
-
},
|
|
142
|
-
"packageJson": {
|
|
143
|
-
"scripts": {}
|
|
144
|
-
},
|
|
145
|
-
"procfile": {},
|
|
146
|
-
"files": [],
|
|
147
|
-
"text": [
|
|
148
|
-
{
|
|
149
|
-
"file": ".env",
|
|
150
|
-
"op": "upsert-env",
|
|
151
|
-
"key": "DB_CLIENT",
|
|
152
|
-
"value": "mysql2",
|
|
153
|
-
"reason": "Configure database client driver for runtime wiring.",
|
|
154
|
-
"category": "runtime-config",
|
|
155
|
-
"id": "database-client-mysql"
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
"file": ".env",
|
|
159
|
-
"op": "upsert-env",
|
|
160
|
-
"key": "DB_HOST",
|
|
161
|
-
"value": "${option:db-host}",
|
|
162
|
-
"reason": "Configure database host.",
|
|
163
|
-
"category": "runtime-config",
|
|
164
|
-
"id": "database-host"
|
|
165
|
-
},
|
|
166
|
-
{
|
|
167
|
-
"file": ".env",
|
|
168
|
-
"op": "upsert-env",
|
|
169
|
-
"key": "DB_PORT",
|
|
170
|
-
"value": "${option:db-port}",
|
|
171
|
-
"reason": "Configure database port.",
|
|
172
|
-
"category": "runtime-config",
|
|
173
|
-
"id": "database-port"
|
|
174
|
-
},
|
|
175
|
-
{
|
|
176
|
-
"file": ".env",
|
|
177
|
-
"op": "upsert-env",
|
|
178
|
-
"key": "DB_NAME",
|
|
179
|
-
"value": "${option:db-name}",
|
|
180
|
-
"reason": "Configure database name.",
|
|
181
|
-
"category": "runtime-config",
|
|
182
|
-
"id": "database-name"
|
|
183
|
-
},
|
|
184
|
-
{
|
|
185
|
-
"file": ".env",
|
|
186
|
-
"op": "upsert-env",
|
|
187
|
-
"key": "DB_USER",
|
|
188
|
-
"value": "${option:db-user}",
|
|
189
|
-
"reason": "Configure database user.",
|
|
190
|
-
"category": "runtime-config",
|
|
191
|
-
"id": "database-user"
|
|
192
|
-
},
|
|
193
|
-
{
|
|
194
|
-
"file": ".env",
|
|
195
|
-
"op": "upsert-env",
|
|
196
|
-
"key": "DB_PASSWORD",
|
|
197
|
-
"value": "${option:db-password}",
|
|
198
|
-
"reason": "Configure database password.",
|
|
199
|
-
"category": "runtime-config",
|
|
200
|
-
"id": "database-password"
|
|
201
|
-
}
|
|
202
|
-
]
|
|
203
57
|
}
|
|
204
58
|
}
|
|
205
59
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: database/mysql-application
|
|
3
|
+
title: MySQL application database
|
|
4
|
+
summary: Configure a JSKIT application for MySQL with a fixed driver, ordinary environment values, and rebuildable Knex migrations.
|
|
5
|
+
keywords: database, knex, mariadb, migrations, mysql, mysql2
|
|
6
|
+
requires: @jskit-ai/database-runtime-mysql
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# MySQL application database
|
|
10
|
+
|
|
11
|
+
## Use when
|
|
12
|
+
|
|
13
|
+
Use this pattern when an application deliberately chooses MySQL or MariaDB.
|
|
14
|
+
Install `@jskit-ai/database-runtime-mysql`; its normal npm dependencies provide
|
|
15
|
+
the database runtime, Knex, and `mysql2` without a package-setup wizard.
|
|
16
|
+
|
|
17
|
+
## Do not use when
|
|
18
|
+
|
|
19
|
+
Do not use this pattern for PostgreSQL, a database-neutral library, or a service
|
|
20
|
+
that does not own its database connection. Do not install both JSKIT drivers
|
|
21
|
+
unless the application genuinely selects between them at runtime.
|
|
22
|
+
|
|
23
|
+
## Product decisions
|
|
24
|
+
|
|
25
|
+
Decide the database name, credentials, host, deployment secret source, backup
|
|
26
|
+
policy, and application migrations. Those are application and environment
|
|
27
|
+
decisions, not framework questions.
|
|
28
|
+
|
|
29
|
+
## Invariants
|
|
30
|
+
|
|
31
|
+
- The application depends directly on the selected JSKIT driver.
|
|
32
|
+
- Credentials stay outside Git.
|
|
33
|
+
- `knexfile.js` fixes `mysql2`; a single-driver application does not require
|
|
34
|
+
`DB_CLIENT`.
|
|
35
|
+
- Schema changes are ordinary immutable migrations.
|
|
36
|
+
- The current package graph, environment, and migrations are authoritative.
|
|
37
|
+
|
|
38
|
+
## Framework APIs
|
|
39
|
+
|
|
40
|
+
Use `createKnexMigrationConfigFromApp()` from
|
|
41
|
+
`@jskit-ai/database-runtime/server/knexMigrationConfig`. The running JSKIT
|
|
42
|
+
application automatically selects the sole installed database driver, while
|
|
43
|
+
Knex discovers package-owned migrations from the installed dependency graph.
|
|
44
|
+
|
|
45
|
+
## Example files
|
|
46
|
+
|
|
47
|
+
`example/package.json` contains the runtime dependency and database scripts.
|
|
48
|
+
`example/knexfile.js` loads an optional local `.env` and fixes the MySQL dialect.
|
|
49
|
+
`example/scripts/prepare-database.js` is the portable migrate-then-seed
|
|
50
|
+
entrypoint for managed sessions and deployments. `example/.env.example` names
|
|
51
|
+
the five connection values without a secret.
|
|
52
|
+
|
|
53
|
+
## Variation points
|
|
54
|
+
|
|
55
|
+
Change scripts, migration location, connection values, and secret injection to
|
|
56
|
+
fit the application. Supply `DATABASE_URL` instead of individual values when
|
|
57
|
+
the environment owns a URL. Add `DB_CLIENT=mysql2` only when a shared external
|
|
58
|
+
tool explicitly needs a dialect selector. When the product needs initial data,
|
|
59
|
+
import one idempotent app-owned seed function in `prepare-database.js` and pass
|
|
60
|
+
it as `seed` to `prepareDatabaseFromApp()`.
|
|
61
|
+
|
|
62
|
+
## Verification
|
|
63
|
+
|
|
64
|
+
- Install dependencies once with `npm install`.
|
|
65
|
+
- Run `npm run db:prepare` against a fresh disposable database.
|
|
66
|
+
- Run `npm run db:migrate:status` and the application verification command.
|
|
67
|
+
- Exercise one transaction and one negative connection case.
|
|
68
|
+
- When a seed exists, run `db:prepare` twice and require the second run to be safe.
|
|
69
|
+
|
|
70
|
+
`example/.github/workflows/verify.yml` is a normal app-owned CI workflow with
|
|
71
|
+
an explicit MariaDB service. Adapt it as source rather than generating it from
|
|
72
|
+
package metadata.
|
|
73
|
+
|
|
74
|
+
## Avoid
|
|
75
|
+
|
|
76
|
+
- framework questionnaires for credentials
|
|
77
|
+
- generated `.env` secrets
|
|
78
|
+
- depending on a live schema as the source contract
|
|
79
|
+
- a second driver installed “just in case”
|
|
80
|
+
- migration receipts, provenance, replay logs, or generator ownership
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: Verify
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
verify:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
services:
|
|
11
|
+
mariadb:
|
|
12
|
+
image: mariadb:11.4
|
|
13
|
+
env:
|
|
14
|
+
MARIADB_DATABASE: app_test
|
|
15
|
+
MARIADB_USER: app_test
|
|
16
|
+
MARIADB_PASSWORD: app_test_password
|
|
17
|
+
MARIADB_ROOT_PASSWORD: root_test_password
|
|
18
|
+
ports:
|
|
19
|
+
- 3306:3306
|
|
20
|
+
options: >-
|
|
21
|
+
--health-cmd="healthcheck.sh --connect --innodb_initialized"
|
|
22
|
+
--health-interval=10s
|
|
23
|
+
--health-timeout=5s
|
|
24
|
+
--health-retries=10
|
|
25
|
+
env:
|
|
26
|
+
DB_HOST: 127.0.0.1
|
|
27
|
+
DB_PORT: 3306
|
|
28
|
+
DB_NAME: app_test
|
|
29
|
+
DB_USER: app_test
|
|
30
|
+
DB_PASSWORD: app_test_password
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v4
|
|
33
|
+
- uses: actions/setup-node@v4
|
|
34
|
+
with:
|
|
35
|
+
node-version-file: .nvmrc
|
|
36
|
+
cache: npm
|
|
37
|
+
- run: npm ci
|
|
38
|
+
- run: npm run db:migrate
|
|
39
|
+
- run: npm run verify
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createKnexMigrationConfigFromApp } from "@jskit-ai/database-runtime/server/knexMigrationConfig";
|
|
2
|
+
|
|
3
|
+
try {
|
|
4
|
+
process.loadEnvFile?.(".env");
|
|
5
|
+
} catch (error) {
|
|
6
|
+
if (error?.code !== "ENOENT") {
|
|
7
|
+
throw error;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default await createKnexMigrationConfigFromApp({ client: "mysql2" });
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"private": true,
|
|
3
|
+
"type": "module",
|
|
4
|
+
"scripts": {
|
|
5
|
+
"db:prepare": "node ./scripts/prepare-database.js",
|
|
6
|
+
"db:migrate": "knex --knexfile ./knexfile.js migrate:latest",
|
|
7
|
+
"db:migrate:rollback": "knex --knexfile ./knexfile.js migrate:rollback",
|
|
8
|
+
"db:migrate:status": "knex --knexfile ./knexfile.js migrate:list"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@jskit-ai/database-runtime-mysql": "0.1.158"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { defineProvider } from "@jskit-ai/kernel/shared/capabilities";
|
|
2
|
+
import * as mysqlDriver from "../../shared/index.js";
|
|
3
|
+
|
|
4
|
+
const MysqlDatabaseDriverProvider = defineProvider({
|
|
5
|
+
id: "runtime.database.driver.mysql",
|
|
6
|
+
provides: {
|
|
7
|
+
driver: "runtime.database.driver"
|
|
8
|
+
},
|
|
9
|
+
setup() {
|
|
10
|
+
return {
|
|
11
|
+
driver: Object.freeze({ ...mysqlDriver })
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export { MysqlDatabaseDriverProvider };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import test from "node:test";
|
|
4
|
+
|
|
5
|
+
const patternUrl = new URL("../patterns/mysql-application/", import.meta.url);
|
|
6
|
+
|
|
7
|
+
test("MySQL application pattern is driver-fixed and questionnaire-free", async () => {
|
|
8
|
+
const [document, manifestSource, knexfile] = await Promise.all([
|
|
9
|
+
readFile(new URL("PATTERN.md", patternUrl), "utf8"),
|
|
10
|
+
readFile(new URL("example/package.json", patternUrl), "utf8"),
|
|
11
|
+
readFile(new URL("example/knexfile.js", patternUrl), "utf8")
|
|
12
|
+
]);
|
|
13
|
+
const manifest = JSON.parse(manifestSource);
|
|
14
|
+
|
|
15
|
+
assert.equal(manifest.dependencies["@jskit-ai/database-runtime-mysql"], "0.1.158");
|
|
16
|
+
assert.match(knexfile, /client: "mysql2"/u);
|
|
17
|
+
assert.doesNotMatch(`${document}\n${knexfile}`, /promptLabel|promptHint|\$\{option:/u);
|
|
18
|
+
});
|
|
@@ -4,15 +4,15 @@ import test from "node:test";
|
|
|
4
4
|
|
|
5
5
|
import * as clientApi from "../src/client/index.js";
|
|
6
6
|
import * as sharedApi from "../src/shared/index.js";
|
|
7
|
-
import {
|
|
7
|
+
import { MysqlDatabaseDriverProvider } from "../src/server/providers/MysqlDatabaseDriverProvider.js";
|
|
8
8
|
|
|
9
9
|
test("package exports include explicit shared and provider entrypoints", async () => {
|
|
10
10
|
const packageJson = JSON.parse(await readFile(new URL("../package.json", import.meta.url), "utf8"));
|
|
11
11
|
const exportsMap = packageJson && typeof packageJson === "object" ? packageJson.exports : {};
|
|
12
12
|
assert.equal(exportsMap["./server"], undefined);
|
|
13
13
|
assert.equal(
|
|
14
|
-
exportsMap["./server/providers/
|
|
15
|
-
"./src/server/providers/
|
|
14
|
+
exportsMap["./server/providers/MysqlDatabaseDriverProvider"],
|
|
15
|
+
"./src/server/providers/MysqlDatabaseDriverProvider.js"
|
|
16
16
|
);
|
|
17
17
|
assert.equal(exportsMap["./shared"], "./src/shared/index.js");
|
|
18
18
|
});
|
|
@@ -21,13 +21,14 @@ test("client entrypoint exports no mysql runtime api", () => {
|
|
|
21
21
|
assert.deepEqual(Object.keys(clientApi), []);
|
|
22
22
|
});
|
|
23
23
|
|
|
24
|
-
test("server provider module exports mysql
|
|
25
|
-
assert.equal(
|
|
24
|
+
test("server provider module exports the declarative mysql driver provider", () => {
|
|
25
|
+
assert.equal(MysqlDatabaseDriverProvider.id, "runtime.database.driver.mysql");
|
|
26
|
+
assert.deepEqual(MysqlDatabaseDriverProvider.provides, { driver: "runtime.database.driver" });
|
|
26
27
|
});
|
|
27
28
|
|
|
28
29
|
test("shared entrypoint exports mysql dialect helpers", () => {
|
|
29
30
|
assert.equal(sharedApi.DIALECT_ID, "mysql2");
|
|
30
31
|
assert.equal(sharedApi.getDialectId(), "mysql2");
|
|
31
32
|
assert.equal(typeof sharedApi.introspectCrudTableSnapshot, "function");
|
|
32
|
-
assert.equal(typeof sharedApi.
|
|
33
|
+
assert.equal(typeof sharedApi.MysqlDatabaseDriverProvider, "undefined");
|
|
33
34
|
});
|
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
2
4
|
import test from "node:test";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
3
6
|
import packageJson from "../package.json" with { type: "json" };
|
|
4
7
|
|
|
5
|
-
const
|
|
6
|
-
import { DIALECT_ID } from "../src/shared/dialect.js";
|
|
8
|
+
const PACKAGE_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
7
9
|
|
|
8
|
-
test("database-runtime-mysql
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
test("database-runtime-mysql owns its driver while CI remains app-owned source", async () => {
|
|
11
|
+
const workflow = await readFile(
|
|
12
|
+
path.join(PACKAGE_ROOT, "patterns/mysql-application/example/.github/workflows/verify.yml"),
|
|
13
|
+
"utf8"
|
|
14
|
+
);
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
assert.equal(
|
|
16
|
-
assert.equal(
|
|
17
|
-
assert.equal(
|
|
18
|
-
assert.
|
|
19
|
-
assert.
|
|
20
|
-
assert.match(
|
|
21
|
-
|
|
22
|
-
const clientMutation = packageMetadata.mutations.text.find((entry) => entry.key === "DB_CLIENT");
|
|
23
|
-
assert.equal(clientMutation.value, DIALECT_ID);
|
|
16
|
+
assert.equal(packageJson.dependencies.mysql2, "^3.11.2");
|
|
17
|
+
assert.equal(Object.hasOwn(packageJson.jskit, "options"), false);
|
|
18
|
+
assert.equal(Object.hasOwn(packageJson.jskit, "mutations"), false);
|
|
19
|
+
assert.equal(Object.hasOwn(packageJson.jskit, "ci"), false);
|
|
20
|
+
assert.match(workflow, /image: mariadb:11\.4/u);
|
|
21
|
+
assert.match(workflow, /npm run db:migrate/u);
|
|
22
|
+
assert.match(workflow, /npm run verify/u);
|
|
24
23
|
});
|
|
@@ -1,33 +1,23 @@
|
|
|
1
|
-
import test from "node:test";
|
|
2
1
|
import assert from "node:assert/strict";
|
|
3
|
-
import
|
|
2
|
+
import test from "node:test";
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
import { createCapabilityRuntime, defineProvider } from "@jskit-ai/kernel/shared/capabilities";
|
|
5
|
+
import { MysqlDatabaseDriverProvider } from "../src/server/providers/MysqlDatabaseDriverProvider.js";
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (!singletons.has(token)) {
|
|
17
|
-
throw new Error(`Token ${String(token)} is not registered.`);
|
|
18
|
-
}
|
|
19
|
-
return singletons.get(token);
|
|
7
|
+
test("MysqlDatabaseDriverProvider provides the exclusive database driver capability", async () => {
|
|
8
|
+
let driver;
|
|
9
|
+
const consumer = defineProvider({
|
|
10
|
+
id: "test.mysql.consumer",
|
|
11
|
+
requires: { databaseDriver: "runtime.database.driver" },
|
|
12
|
+
setup({ databaseDriver }) {
|
|
13
|
+
driver = databaseDriver;
|
|
14
|
+
return {};
|
|
20
15
|
}
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
test("DatabaseRuntimeMysqlServiceProvider registers mysql driver api", () => {
|
|
25
|
-
const app = createSingletonApp();
|
|
26
|
-
const provider = new DatabaseRuntimeMysqlServiceProvider();
|
|
27
|
-
provider.register(app);
|
|
16
|
+
});
|
|
17
|
+
const runtime = createCapabilityRuntime({ providers: [MysqlDatabaseDriverProvider, consumer] });
|
|
28
18
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
assert.equal(
|
|
32
|
-
|
|
19
|
+
await runtime.start();
|
|
20
|
+
assert.equal(driver.DIALECT_ID, "mysql2");
|
|
21
|
+
assert.equal(driver.getDialectId(), "mysql2");
|
|
22
|
+
await runtime.shutdown();
|
|
33
23
|
});
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import * as mysqlDialect from "../../shared/index.js";
|
|
2
|
-
|
|
3
|
-
const MYSQL_DATABASE_DRIVER_API = Object.freeze({
|
|
4
|
-
...mysqlDialect
|
|
5
|
-
});
|
|
6
|
-
|
|
7
|
-
class DatabaseRuntimeMysqlServiceProvider {
|
|
8
|
-
static id = "runtime.database.driver.mysql";
|
|
9
|
-
|
|
10
|
-
register(app) {
|
|
11
|
-
if (!app || typeof app.singleton !== "function") {
|
|
12
|
-
throw new Error("DatabaseRuntimeMysqlServiceProvider requires application singleton().");
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
app.singleton("runtime.database.driver.mysql", () => MYSQL_DATABASE_DRIVER_API);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
boot() {}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export { DatabaseRuntimeMysqlServiceProvider };
|