@mandujs/core 0.53.2 → 0.54.0
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 +654 -654
- package/package.json +2 -2
- package/src/a11y/__tests__/run-audit.test.ts +333 -333
- package/src/a11y/fix-hints.ts +76 -76
- package/src/a11y/index.ts +18 -18
- package/src/a11y/run-audit.ts +394 -394
- package/src/a11y/types.ts +125 -125
- package/src/auth/__tests__/login.test.ts +1 -1
- package/src/auth/__tests__/password.test.ts +122 -122
- package/src/auth/__tests__/tokens.test.ts +274 -274
- package/src/auth/__tests__/verification.test.ts +274 -274
- package/src/auth/index.ts +76 -76
- package/src/auth/login.ts +225 -225
- package/src/auth/password.ts +120 -120
- package/src/auth/reset.ts +243 -243
- package/src/auth/tokens.ts +612 -612
- package/src/auth/verification.ts +253 -253
- package/src/brain/__tests__/redactor.test.ts +94 -94
- package/src/brain/adapters/__tests__/_helpers.ts +83 -83
- package/src/brain/adapters/__tests__/anthropic-oauth.test.ts +196 -196
- package/src/brain/adapters/__tests__/chatgpt-auth.test.ts +193 -193
- package/src/brain/adapters/__tests__/openai-oauth.test.ts +209 -209
- package/src/brain/adapters/__tests__/resolver.test.ts +143 -143
- package/src/brain/adapters/anthropic-oauth.ts +1 -1
- package/src/brain/adapters/chatgpt-auth.ts +300 -300
- package/src/brain/adapters/index.ts +319 -319
- package/src/brain/adapters/oauth-flow.ts +439 -439
- package/src/brain/consent.ts +240 -240
- package/src/brain/credentials.ts +396 -396
- package/src/bundler/__tests__/build-runner.ts +113 -113
- package/src/bundler/__tests__/dev-reliability.test.ts +619 -619
- package/src/bundler/__tests__/extended-watch.test.ts +711 -711
- package/src/bundler/__tests__/fast-refresh.test.ts +10 -10
- package/src/bundler/__tests__/hdr.test.ts +353 -353
- package/src/bundler/__tests__/hmr-client.test.ts +532 -532
- package/src/bundler/__tests__/manifest-schema.test.ts +266 -266
- package/src/bundler/__tests__/prod-smoke.test.ts +138 -138
- package/src/bundler/__tests__/reverse-import-graph.test.ts +519 -519
- package/src/bundler/__tests__/slot-dispatch.test.ts +573 -573
- package/src/bundler/__tests__/url-cap-and-slot-regex.test.ts +286 -286
- package/src/bundler/__tests__/vendor-cache.test.ts +455 -455
- package/src/bundler/budget.ts +404 -404
- package/src/bundler/build.test.ts +179 -179
- package/src/bundler/build.ts +55 -55
- package/src/bundler/dev.ts +42 -42
- package/src/bundler/manifest-schema.ts +301 -301
- package/src/bundler/plugins/__tests__/block-generated-imports.test.ts +263 -263
- package/src/bundler/plugins/__tests__/react-compiler-config.test.ts +83 -83
- package/src/bundler/plugins/__tests__/react-compiler-lint.test.ts +110 -110
- package/src/bundler/plugins/block-generated-imports.ts +155 -155
- package/src/bundler/plugins/index.ts +83 -83
- package/src/bundler/plugins/react-compiler-config.ts +108 -108
- package/src/bundler/plugins/react-compiler-lint.ts +253 -253
- package/src/bundler/plugins/react-compiler.ts +162 -162
- package/src/bundler/reverse-import-graph.ts +339 -339
- package/src/bundler/safe-build.test.ts +201 -201
- package/src/bundler/safe-build.ts +103 -103
- package/src/bundler/scenario-matrix.ts +229 -229
- package/src/bundler/types.ts +10 -10
- package/src/bundler/vendor-cache-types.ts +130 -130
- package/src/bundler/vendor-cache.ts +526 -526
- package/src/change/snapshot.ts +18 -18
- package/src/client/Form.tsx +105 -105
- package/src/client/Link.tsx +9 -9
- package/src/client/__tests__/use-sse.test.ts +153 -153
- package/src/client/globals.ts +1 -1
- package/src/client/hooks.ts +362 -362
- package/src/client/hydrate.ts +340 -340
- package/src/client/prefetch-helper.ts +55 -55
- package/src/client/router.ts +11 -11
- package/src/client/runtime.ts +47 -47
- package/src/client/serialize.ts +404 -404
- package/src/client/use-fetch.ts +6 -6
- package/src/client/use-head.ts +197 -197
- package/src/client/use-sse.ts +378 -378
- package/src/client/window-state.ts +101 -101
- package/src/components/Image.tsx +162 -162
- package/src/config/validate.ts +3 -3
- package/src/config/watcher.ts +311 -311
- package/src/constants.ts +40 -40
- package/src/content/collection.ts +8 -8
- package/src/content/content-layer.ts +7 -7
- package/src/content/data-store.ts +245 -245
- package/src/content/frontmatter.ts +189 -189
- package/src/content/loader-context.ts +171 -171
- package/src/content/loaders/api.ts +216 -216
- package/src/content/loaders/file.ts +172 -172
- package/src/content/loaders/glob.ts +253 -253
- package/src/content/loaders/index.ts +34 -34
- package/src/content/loaders/types.ts +137 -137
- package/src/content/meta-store.ts +209 -209
- package/src/content/prebuild.test.ts +571 -571
- package/src/content/prebuild.ts +636 -636
- package/src/content/schema.ts +20 -20
- package/src/content/sidebar.ts +630 -630
- package/src/content/slug.ts +110 -110
- package/src/content/types.ts +282 -282
- package/src/content/watcher.ts +135 -135
- package/src/contract/client-safe.test.ts +42 -42
- package/src/contract/client-safe.ts +114 -114
- package/src/contract/define.ts +11 -11
- package/src/contract/index.ts +1 -1
- package/src/contract/normalize.test.ts +276 -276
- package/src/contract/normalize.ts +410 -410
- package/src/contract/registry.test.ts +206 -206
- package/src/contract/route-helpers.ts +1 -1
- package/src/contract/rpc.ts +443 -443
- package/src/contract/schema.ts +48 -48
- package/src/contract/types.ts +58 -58
- package/src/db/__tests__/db.test.ts +482 -482
- package/src/db/index.ts +138 -138
- package/src/db/migrations/history-table.ts +345 -345
- package/src/db/migrations/index.ts +3 -3
- package/src/db/migrations/lock.ts +324 -324
- package/src/db/migrations/runner.ts +650 -650
- package/src/deploy/cache.ts +140 -140
- package/src/deploy/compile/vercel.ts +344 -344
- package/src/deploy/index.ts +87 -87
- package/src/deploy/inference/brain.ts +268 -268
- package/src/deploy/inference/context.ts +182 -182
- package/src/deploy/inference/filling-extract.ts +245 -245
- package/src/deploy/inference/heuristic.ts +182 -182
- package/src/deploy/intent.ts +173 -173
- package/src/deploy/plan.ts +178 -178
- package/src/design/__tests__/agents-link.test.ts +109 -109
- package/src/design/__tests__/extract-patch-diff.test.ts +265 -265
- package/src/design/__tests__/lint.test.ts +110 -110
- package/src/design/__tests__/parser.test.ts +195 -195
- package/src/design/__tests__/tailwind-theme.test.ts +229 -229
- package/src/design/agents-link.ts +165 -165
- package/src/design/diff.ts +138 -138
- package/src/design/extract.ts +285 -285
- package/src/design/index.ts +102 -102
- package/src/design/lint.ts +209 -209
- package/src/design/parser.ts +555 -555
- package/src/design/patch.ts +241 -241
- package/src/design/scaffold.ts +147 -147
- package/src/design/tailwind-theme.ts +441 -441
- package/src/design/types.ts +210 -210
- package/src/desktop/__tests__/webview-fallback.test.ts +254 -254
- package/src/desktop/__tests__/window.test.ts +248 -248
- package/src/desktop/__tests__/worker.test.ts +266 -266
- package/src/desktop/index.ts +43 -43
- package/src/desktop/types.ts +158 -158
- package/src/desktop/worker.ts +180 -180
- package/src/dev-error-overlay/__tests__/overlay-injector.test.ts +241 -241
- package/src/dev-error-overlay/index.ts +30 -30
- package/src/dev-error-overlay/overlay-injector.ts +243 -243
- package/src/dev-error-overlay/overlay-styles.ts +52 -52
- package/src/dev-error-overlay/types.ts +66 -66
- package/src/devtools/ai/context-builder.ts +375 -375
- package/src/devtools/ai/index.ts +25 -25
- package/src/devtools/ai/mcp-connector.ts +25 -25
- package/src/devtools/client/catchers/error-catcher.ts +344 -344
- package/src/devtools/client/catchers/index.ts +18 -18
- package/src/devtools/client/components/index.ts +39 -39
- package/src/devtools/client/components/mandu-character.tsx +331 -331
- package/src/devtools/client/components/overlay.tsx +368 -368
- package/src/devtools/client/components/panel/errors-panel.tsx +259 -259
- package/src/devtools/client/components/panel/guard-panel.tsx +30 -30
- package/src/devtools/client/components/panel/islands-panel.tsx +320 -320
- package/src/devtools/client/components/panel/network-panel.tsx +291 -291
- package/src/devtools/client/components/panel/panel-container.tsx +500 -500
- package/src/devtools/client/components/panel/preview-panel.tsx +46 -46
- package/src/devtools/client/filters/context-filters.ts +282 -282
- package/src/devtools/client/filters/index.ts +16 -16
- package/src/devtools/client/index.ts +63 -63
- package/src/devtools/client/persistence.ts +335 -335
- package/src/devtools/hook/create-hook.ts +207 -207
- package/src/devtools/hook/index.ts +13 -13
- package/src/devtools/index.ts +439 -439
- package/src/devtools/init.ts +265 -265
- package/src/devtools/protocol.ts +237 -237
- package/src/devtools/server/index.ts +17 -17
- package/src/devtools/server/source-context.ts +450 -450
- package/src/devtools/types.ts +35 -35
- package/src/devtools/worker/index.ts +25 -25
- package/src/devtools/worker/redaction-worker.ts +233 -233
- package/src/devtools/worker/worker-manager.ts +410 -410
- package/src/diagnose/__tests__/checks.test.ts +451 -380
- package/src/diagnose/checks.ts +832 -720
- package/src/diagnose/index.ts +17 -16
- package/src/diagnose/run.ts +93 -91
- package/src/diagnose/types.ts +53 -53
- package/src/email/__tests__/email.test.ts +355 -355
- package/src/email/index.ts +282 -282
- package/src/email/smtp.ts +64 -64
- package/src/error/domains.ts +265 -265
- package/src/error/result.ts +60 -60
- package/src/error/types.ts +6 -6
- package/src/errors/extractor.ts +409 -409
- package/src/errors/index.ts +19 -19
- package/src/filling/__tests__/session-sqlite.test.ts +454 -454
- package/src/filling/auth.ts +308 -308
- package/src/filling/cookie-codec.ts +299 -299
- package/src/filling/deps.ts +265 -265
- package/src/filling/session-sqlite.ts +617 -617
- package/src/filling/sse.ts +5 -5
- package/src/filling/ws.ts +78 -78
- package/src/generator/index.ts +3 -3
- package/src/guard/__tests__/design-inline-class.test.ts +219 -219
- package/src/guard/__tests__/tsgolint-bridge.test.ts +347 -347
- package/src/guard/analyzer.ts +360 -360
- package/src/guard/auto-correct.ts +1 -1
- package/src/guard/contract-guard.ts +9 -9
- package/src/guard/define-rule.ts +243 -243
- package/src/guard/design-inline-class.ts +393 -393
- package/src/guard/file-type.test.ts +24 -24
- package/src/guard/graph.ts +1 -1
- package/src/guard/healing.ts +36 -36
- package/src/guard/presets/atomic.ts +70 -70
- package/src/guard/presets/clean.ts +77 -77
- package/src/guard/presets/fsd.ts +79 -79
- package/src/guard/presets/hexagonal.ts +68 -68
- package/src/guard/reporter.ts +442 -442
- package/src/guard/rule-presets.ts +379 -379
- package/src/guard/semantic-slots.ts +1 -1
- package/src/guard/suggestions.ts +358 -358
- package/src/guard/tsgolint-bridge.ts +512 -512
- package/src/guard/types.ts +348 -348
- package/src/guard/watcher.ts +405 -405
- package/src/i18n/define.ts +126 -126
- package/src/i18n/index.ts +52 -52
- package/src/i18n/message-registry.ts +173 -173
- package/src/i18n/types.ts +112 -112
- package/src/id/index.ts +105 -105
- package/src/index.ts +2 -2
- package/src/kitchen/api/agent-devtools-api.ts +779 -544
- package/src/kitchen/api/errors-grouping.ts +126 -0
- package/src/kitchen/kitchen-handler.ts +192 -63
- package/src/kitchen/kitchen-ui.ts +842 -464
- package/src/logging/index.ts +22 -22
- package/src/logging/transports.ts +365 -365
- package/src/middleware/bridge.ts +147 -147
- package/src/middleware/compose.ts +134 -134
- package/src/middleware/compress.ts +62 -62
- package/src/middleware/cors.ts +47 -47
- package/src/middleware/csrf.ts +328 -328
- package/src/middleware/define.ts +132 -132
- package/src/middleware/jwt.ts +134 -134
- package/src/middleware/logger.ts +58 -58
- package/src/middleware/oauth/__tests__/oauth.test.ts +1 -1
- package/src/middleware/oauth/index.ts +505 -505
- package/src/middleware/oauth/providers.ts +115 -115
- package/src/middleware/rate-limit/index.ts +522 -522
- package/src/middleware/rate-limit/sqlite-store.ts +382 -382
- package/src/middleware/scheduler-cron.ts +96 -96
- package/src/middleware/secure/__tests__/secure.test.ts +360 -360
- package/src/middleware/secure/csp.ts +193 -193
- package/src/middleware/session.ts +174 -174
- package/src/middleware/timeout.ts +55 -55
- package/src/observability/logger-adapter.ts +36 -36
- package/src/observability/sqlite-store.ts +254 -254
- package/src/openapi/generator.ts +1 -1
- package/src/openapi/openapi.test.ts +43 -43
- package/src/perf/__tests__/user-marks.test.ts +354 -354
- package/src/perf/index.ts +133 -133
- package/src/plugins/__tests__/lifecycle-integration.test.ts +272 -272
- package/src/plugins/__tests__/runner.test.ts +409 -409
- package/src/plugins/define.ts +124 -124
- package/src/plugins/examples/dep-check-plugin.ts +80 -80
- package/src/plugins/examples/prerender-cache-plugin.ts +111 -111
- package/src/plugins/examples/sitemap-plugin.ts +65 -65
- package/src/plugins/runner.ts +361 -361
- package/src/plugins/types.ts +368 -368
- package/src/report/index.ts +1 -1
- package/src/resource/__tests__/generator.test.ts +32 -32
- package/src/resource/ddl/__tests__/diff.test.ts +639 -639
- package/src/resource/ddl/__tests__/emit.test.ts +823 -823
- package/src/resource/ddl/__tests__/snapshot.test.ts +499 -499
- package/src/resource/ddl/emit.ts +559 -559
- package/src/resource/ddl/persistence-types.ts +218 -218
- package/src/resource/ddl/type-map.ts +223 -223
- package/src/resource/ddl/types.ts +232 -232
- package/src/resource/generator-repo.ts +630 -630
- package/src/resource/schema.ts +1 -1
- package/src/router/fs-patterns.test.ts +96 -96
- package/src/router/fs-routes.ts +6 -6
- package/src/routes/index.ts +74 -74
- package/src/routes/metadata-routes.ts +427 -427
- package/src/routes/types.ts +341 -341
- package/src/runtime/__tests__/error-boundary-redaction.test.ts +141 -141
- package/src/runtime/__tests__/hdr-client.test.ts +223 -223
- package/src/runtime/__tests__/http-errors.test.ts +117 -117
- package/src/runtime/__tests__/not-found.test.ts +152 -152
- package/src/runtime/adapter.ts +47 -47
- package/src/runtime/boundary.tsx +252 -252
- package/src/runtime/cache.ts +494 -494
- package/src/runtime/compose.ts +222 -222
- package/src/runtime/fast-refresh-runtime.ts +322 -322
- package/src/runtime/handler.ts +65 -65
- package/src/runtime/handlers.ts +300 -300
- package/src/runtime/http-errors.ts +113 -113
- package/src/runtime/image-handler.ts +1 -1
- package/src/runtime/lifecycle.ts +381 -381
- package/src/runtime/logger.test.ts +345 -345
- package/src/runtime/middleware.ts +264 -264
- package/src/runtime/not-found.ts +93 -93
- package/src/runtime/openapi-endpoint.ts +236 -236
- package/src/runtime/ppr.ts +74 -74
- package/src/runtime/registry.ts +171 -171
- package/src/runtime/router.ts +105 -105
- package/src/runtime/server.ts +67 -67
- package/src/runtime/shims.ts +48 -48
- package/src/runtime/ssr.ts +24 -31
- package/src/runtime/streaming-ssr.ts +32 -37
- package/src/runtime/trace.ts +144 -144
- package/src/scheduler/validate.ts +169 -169
- package/src/seo/index.ts +219 -219
- package/src/seo/integration/ssr.ts +306 -306
- package/src/seo/render/basic.ts +435 -435
- package/src/seo/render/index.ts +143 -143
- package/src/seo/render/jsonld.ts +539 -539
- package/src/seo/render/opengraph.ts +197 -197
- package/src/seo/render/robots.ts +116 -116
- package/src/seo/render/sitemap.ts +137 -137
- package/src/seo/render/twitter.ts +127 -127
- package/src/seo/resolve/opengraph.ts +143 -143
- package/src/seo/resolve/robots.ts +73 -73
- package/src/seo/resolve/title.ts +94 -94
- package/src/seo/resolve/twitter.ts +73 -73
- package/src/seo/resolve/url.ts +104 -104
- package/src/seo/routes/index.ts +290 -290
- package/src/seo/types.ts +588 -588
- package/src/slot/validator.ts +39 -39
- package/src/storage/s3/__tests__/s3.test.ts +479 -479
- package/src/storage/s3/index.ts +412 -412
- package/src/testing/__tests__/assertions.test.ts +632 -632
- package/src/testing/__tests__/reporter.test.ts +454 -454
- package/src/testing/assertions.ts +986 -986
- package/src/testing/db.ts +157 -157
- package/src/testing/mocks.ts +203 -203
- package/src/testing/session.ts +190 -190
- package/src/types/branded.ts +56 -56
- package/src/types/index.ts +1 -1
- package/src/utils/safe-io.ts +188 -188
- package/src/utils/string-safe.ts +298 -298
- package/src/watcher/watcher.ts +18 -18
package/src/testing/db.ts
CHANGED
|
@@ -1,157 +1,157 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @mandujs/core/testing/db
|
|
3
|
-
*
|
|
4
|
-
* In-memory / file-backed SQLite fixture for integration tests.
|
|
5
|
-
*
|
|
6
|
-
* Wraps `@mandujs/core/db` so callers do not have to learn Bun.SQL's URL
|
|
7
|
-
* conventions just to stand up a throwaway database. The default is
|
|
8
|
-
* `sqlite::memory:` — fully isolated, survives exactly one test, zero
|
|
9
|
-
* filesystem footprint.
|
|
10
|
-
*
|
|
11
|
-
* ```ts
|
|
12
|
-
* import { createTestDb } from "@mandujs/core/testing";
|
|
13
|
-
*
|
|
14
|
-
* const db = await createTestDb({
|
|
15
|
-
* schema: `
|
|
16
|
-
* CREATE TABLE users (id TEXT PRIMARY KEY, email TEXT NOT NULL);
|
|
17
|
-
* CREATE INDEX users_email ON users(email);
|
|
18
|
-
* `,
|
|
19
|
-
* });
|
|
20
|
-
* afterEach(async () => await db.close());
|
|
21
|
-
*
|
|
22
|
-
* await db.db`INSERT INTO users (id, email) VALUES (${"u1"}, ${"a@b.c"})`;
|
|
23
|
-
* const rows = await db.db<{ id: string; email: string }>`SELECT * FROM users`;
|
|
24
|
-
* expect(rows).toHaveLength(1);
|
|
25
|
-
* ```
|
|
26
|
-
*
|
|
27
|
-
* ## Design
|
|
28
|
-
*
|
|
29
|
-
* - **Isolation first**: each call to `createTestDb()` returns a fresh
|
|
30
|
-
* `Db` handle. SQLite in-memory dbs are scoped to the connection, so
|
|
31
|
-
* there is no cross-fixture leakage.
|
|
32
|
-
* - **DDL delivered as plain SQL**: callers pass schema as a string (or an
|
|
33
|
-
* array of statements). No dependency on the resource migration runner —
|
|
34
|
-
* that's a Phase 12.3 concern.
|
|
35
|
-
* - **Transaction helper**: `transaction(fn)` is just a re-export of the
|
|
36
|
-
* underlying `Db.transaction` — convenient to avoid threading `db.db.*`.
|
|
37
|
-
* - **Async-dispose**: `using db = await createTestDb(...)` works via
|
|
38
|
-
* `Symbol.asyncDispose` (ES2023 Explicit Resource Management). Pair with
|
|
39
|
-
* Bun.test's per-test cleanup for maximum terseness.
|
|
40
|
-
*
|
|
41
|
-
* ## SQLite caveats
|
|
42
|
-
*
|
|
43
|
-
* Bun.SQL's SQLite adapter requires non-null columns to be typed.
|
|
44
|
-
* Tests that want rich schemas should use `TEXT`, `INTEGER`, `REAL`,
|
|
45
|
-
* `BLOB`. Higher-level typed schemas come with the Phase 12.3 resource
|
|
46
|
-
* migration fixture.
|
|
47
|
-
*
|
|
48
|
-
* @module testing/db
|
|
49
|
-
*/
|
|
50
|
-
|
|
51
|
-
import { createDb, type Db } from "../db/index";
|
|
52
|
-
|
|
53
|
-
/** Options for {@link createTestDb}. */
|
|
54
|
-
export interface CreateTestDbOptions {
|
|
55
|
-
/**
|
|
56
|
-
* Connection URL. Default: `"sqlite::memory:"`.
|
|
57
|
-
*
|
|
58
|
-
* Any `sqlite:` URL is accepted — `sqlite:./fixture.db` for a file-backed
|
|
59
|
-
* fixture that survives across fixture instances, for example. Non-sqlite
|
|
60
|
-
* providers are accepted but not recommended for unit tests (you lose
|
|
61
|
-
* isolation across fixtures).
|
|
62
|
-
*/
|
|
63
|
-
url?: string;
|
|
64
|
-
/**
|
|
65
|
-
* DDL to apply on open. Accepts a multi-statement SQL string or an array
|
|
66
|
-
* of pre-split statements. Statements are run sequentially — if any
|
|
67
|
-
* fails, subsequent ones are skipped and the error re-throws.
|
|
68
|
-
*/
|
|
69
|
-
schema?: string | string[];
|
|
70
|
-
/** Optional seed block to run after `schema` — convenient for row-level setup. */
|
|
71
|
-
seed?: (db: Db) => Promise<void> | void;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/** Handle returned by {@link createTestDb}. */
|
|
75
|
-
export interface TestDb {
|
|
76
|
-
/** The underlying Db handle — use as a tagged-template query function. */
|
|
77
|
-
readonly db: Db;
|
|
78
|
-
/** Re-export of `db.transaction`. */
|
|
79
|
-
transaction: Db["transaction"];
|
|
80
|
-
/**
|
|
81
|
-
* Apply additional DDL after the fixture has been created. Useful when the
|
|
82
|
-
* schema depends on per-test parameters (e.g., random suffixes to avoid
|
|
83
|
-
* SQLite's reserved-words).
|
|
84
|
-
*/
|
|
85
|
-
apply(ddl: string | string[]): Promise<void>;
|
|
86
|
-
/** Idempotent cleanup — safe to call multiple times. */
|
|
87
|
-
close(): Promise<void>;
|
|
88
|
-
/** `using db = await createTestDb(...)` support. */
|
|
89
|
-
[Symbol.asyncDispose](): Promise<void>;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/** Split a multi-statement SQL string into individual statements. */
|
|
93
|
-
function splitSql(source: string): string[] {
|
|
94
|
-
// Naïve splitter: works for vanilla DDL without embedded `;` inside quoted
|
|
95
|
-
// strings — the realistic shape of test fixtures. A full lexer lives in
|
|
96
|
-
// `db/migrations/runner.ts`; we intentionally do not re-use it here to
|
|
97
|
-
// avoid coupling the testing fixture to migration-runner internals.
|
|
98
|
-
return source
|
|
99
|
-
.split(";")
|
|
100
|
-
.map((s) => s.trim())
|
|
101
|
-
.filter((s) => s.length > 0);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
async function applyDdl(db: Db, ddl: string | string[]): Promise<void> {
|
|
105
|
-
const statements = Array.isArray(ddl) ? ddl : splitSql(ddl);
|
|
106
|
-
for (const stmt of statements) {
|
|
107
|
-
// Bun.SQL's tagged-template form does not support raw DDL composition —
|
|
108
|
-
// but a 1-argument template with no placeholders is safe. The value
|
|
109
|
-
// inside `strings.raw[0]` is the literal SQL, never an interpolated value.
|
|
110
|
-
const raw = stmt.trim();
|
|
111
|
-
if (raw.length === 0) continue;
|
|
112
|
-
const strings = Object.assign([raw], { raw: [raw] }) as TemplateStringsArray;
|
|
113
|
-
await db(strings);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Boot a fixture-scoped database handle.
|
|
119
|
-
*
|
|
120
|
-
* The default URL (`sqlite::memory:`) creates a per-connection in-memory
|
|
121
|
-
* database — ideal for per-test isolation.
|
|
122
|
-
*
|
|
123
|
-
* @throws if `url` is non-empty but Bun.SQL rejects it on the first query.
|
|
124
|
-
* Validation is lazy — construction never throws on unreachable targets.
|
|
125
|
-
*/
|
|
126
|
-
export async function createTestDb(
|
|
127
|
-
options: CreateTestDbOptions = {},
|
|
128
|
-
): Promise<TestDb> {
|
|
129
|
-
const url = options.url ?? "sqlite::memory:";
|
|
130
|
-
const db = createDb({ url });
|
|
131
|
-
|
|
132
|
-
if (options.schema !== undefined) {
|
|
133
|
-
await applyDdl(db, options.schema);
|
|
134
|
-
}
|
|
135
|
-
if (options.seed) {
|
|
136
|
-
await options.seed(db);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
let closed = false;
|
|
140
|
-
const close = async (): Promise<void> => {
|
|
141
|
-
if (closed) return;
|
|
142
|
-
closed = true;
|
|
143
|
-
await db.close();
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
return {
|
|
147
|
-
db,
|
|
148
|
-
transaction: db.transaction.bind(db),
|
|
149
|
-
async apply(ddl) {
|
|
150
|
-
await applyDdl(db, ddl);
|
|
151
|
-
},
|
|
152
|
-
close,
|
|
153
|
-
async [Symbol.asyncDispose]() {
|
|
154
|
-
await close();
|
|
155
|
-
},
|
|
156
|
-
};
|
|
157
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @mandujs/core/testing/db
|
|
3
|
+
*
|
|
4
|
+
* In-memory / file-backed SQLite fixture for integration tests.
|
|
5
|
+
*
|
|
6
|
+
* Wraps `@mandujs/core/db` so callers do not have to learn Bun.SQL's URL
|
|
7
|
+
* conventions just to stand up a throwaway database. The default is
|
|
8
|
+
* `sqlite::memory:` — fully isolated, survives exactly one test, zero
|
|
9
|
+
* filesystem footprint.
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { createTestDb } from "@mandujs/core/testing";
|
|
13
|
+
*
|
|
14
|
+
* const db = await createTestDb({
|
|
15
|
+
* schema: `
|
|
16
|
+
* CREATE TABLE users (id TEXT PRIMARY KEY, email TEXT NOT NULL);
|
|
17
|
+
* CREATE INDEX users_email ON users(email);
|
|
18
|
+
* `,
|
|
19
|
+
* });
|
|
20
|
+
* afterEach(async () => await db.close());
|
|
21
|
+
*
|
|
22
|
+
* await db.db`INSERT INTO users (id, email) VALUES (${"u1"}, ${"a@b.c"})`;
|
|
23
|
+
* const rows = await db.db<{ id: string; email: string }>`SELECT * FROM users`;
|
|
24
|
+
* expect(rows).toHaveLength(1);
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* ## Design
|
|
28
|
+
*
|
|
29
|
+
* - **Isolation first**: each call to `createTestDb()` returns a fresh
|
|
30
|
+
* `Db` handle. SQLite in-memory dbs are scoped to the connection, so
|
|
31
|
+
* there is no cross-fixture leakage.
|
|
32
|
+
* - **DDL delivered as plain SQL**: callers pass schema as a string (or an
|
|
33
|
+
* array of statements). No dependency on the resource migration runner —
|
|
34
|
+
* that's a Phase 12.3 concern.
|
|
35
|
+
* - **Transaction helper**: `transaction(fn)` is just a re-export of the
|
|
36
|
+
* underlying `Db.transaction` — convenient to avoid threading `db.db.*`.
|
|
37
|
+
* - **Async-dispose**: `using db = await createTestDb(...)` works via
|
|
38
|
+
* `Symbol.asyncDispose` (ES2023 Explicit Resource Management). Pair with
|
|
39
|
+
* Bun.test's per-test cleanup for maximum terseness.
|
|
40
|
+
*
|
|
41
|
+
* ## SQLite caveats
|
|
42
|
+
*
|
|
43
|
+
* Bun.SQL's SQLite adapter requires non-null columns to be typed.
|
|
44
|
+
* Tests that want rich schemas should use `TEXT`, `INTEGER`, `REAL`,
|
|
45
|
+
* `BLOB`. Higher-level typed schemas come with the Phase 12.3 resource
|
|
46
|
+
* migration fixture.
|
|
47
|
+
*
|
|
48
|
+
* @module testing/db
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
import { createDb, type Db } from "../db/index";
|
|
52
|
+
|
|
53
|
+
/** Options for {@link createTestDb}. */
|
|
54
|
+
export interface CreateTestDbOptions {
|
|
55
|
+
/**
|
|
56
|
+
* Connection URL. Default: `"sqlite::memory:"`.
|
|
57
|
+
*
|
|
58
|
+
* Any `sqlite:` URL is accepted — `sqlite:./fixture.db` for a file-backed
|
|
59
|
+
* fixture that survives across fixture instances, for example. Non-sqlite
|
|
60
|
+
* providers are accepted but not recommended for unit tests (you lose
|
|
61
|
+
* isolation across fixtures).
|
|
62
|
+
*/
|
|
63
|
+
url?: string;
|
|
64
|
+
/**
|
|
65
|
+
* DDL to apply on open. Accepts a multi-statement SQL string or an array
|
|
66
|
+
* of pre-split statements. Statements are run sequentially — if any
|
|
67
|
+
* fails, subsequent ones are skipped and the error re-throws.
|
|
68
|
+
*/
|
|
69
|
+
schema?: string | string[];
|
|
70
|
+
/** Optional seed block to run after `schema` — convenient for row-level setup. */
|
|
71
|
+
seed?: (db: Db) => Promise<void> | void;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Handle returned by {@link createTestDb}. */
|
|
75
|
+
export interface TestDb {
|
|
76
|
+
/** The underlying Db handle — use as a tagged-template query function. */
|
|
77
|
+
readonly db: Db;
|
|
78
|
+
/** Re-export of `db.transaction`. */
|
|
79
|
+
transaction: Db["transaction"];
|
|
80
|
+
/**
|
|
81
|
+
* Apply additional DDL after the fixture has been created. Useful when the
|
|
82
|
+
* schema depends on per-test parameters (e.g., random suffixes to avoid
|
|
83
|
+
* SQLite's reserved-words).
|
|
84
|
+
*/
|
|
85
|
+
apply(ddl: string | string[]): Promise<void>;
|
|
86
|
+
/** Idempotent cleanup — safe to call multiple times. */
|
|
87
|
+
close(): Promise<void>;
|
|
88
|
+
/** `using db = await createTestDb(...)` support. */
|
|
89
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Split a multi-statement SQL string into individual statements. */
|
|
93
|
+
function splitSql(source: string): string[] {
|
|
94
|
+
// Naïve splitter: works for vanilla DDL without embedded `;` inside quoted
|
|
95
|
+
// strings — the realistic shape of test fixtures. A full lexer lives in
|
|
96
|
+
// `db/migrations/runner.ts`; we intentionally do not re-use it here to
|
|
97
|
+
// avoid coupling the testing fixture to migration-runner internals.
|
|
98
|
+
return source
|
|
99
|
+
.split(";")
|
|
100
|
+
.map((s) => s.trim())
|
|
101
|
+
.filter((s) => s.length > 0);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function applyDdl(db: Db, ddl: string | string[]): Promise<void> {
|
|
105
|
+
const statements = Array.isArray(ddl) ? ddl : splitSql(ddl);
|
|
106
|
+
for (const stmt of statements) {
|
|
107
|
+
// Bun.SQL's tagged-template form does not support raw DDL composition —
|
|
108
|
+
// but a 1-argument template with no placeholders is safe. The value
|
|
109
|
+
// inside `strings.raw[0]` is the literal SQL, never an interpolated value.
|
|
110
|
+
const raw = stmt.trim();
|
|
111
|
+
if (raw.length === 0) continue;
|
|
112
|
+
const strings = Object.assign([raw], { raw: [raw] }) as TemplateStringsArray;
|
|
113
|
+
await db(strings);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Boot a fixture-scoped database handle.
|
|
119
|
+
*
|
|
120
|
+
* The default URL (`sqlite::memory:`) creates a per-connection in-memory
|
|
121
|
+
* database — ideal for per-test isolation.
|
|
122
|
+
*
|
|
123
|
+
* @throws if `url` is non-empty but Bun.SQL rejects it on the first query.
|
|
124
|
+
* Validation is lazy — construction never throws on unreachable targets.
|
|
125
|
+
*/
|
|
126
|
+
export async function createTestDb(
|
|
127
|
+
options: CreateTestDbOptions = {},
|
|
128
|
+
): Promise<TestDb> {
|
|
129
|
+
const url = options.url ?? "sqlite::memory:";
|
|
130
|
+
const db = createDb({ url });
|
|
131
|
+
|
|
132
|
+
if (options.schema !== undefined) {
|
|
133
|
+
await applyDdl(db, options.schema);
|
|
134
|
+
}
|
|
135
|
+
if (options.seed) {
|
|
136
|
+
await options.seed(db);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
let closed = false;
|
|
140
|
+
const close = async (): Promise<void> => {
|
|
141
|
+
if (closed) return;
|
|
142
|
+
closed = true;
|
|
143
|
+
await db.close();
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
db,
|
|
148
|
+
transaction: db.transaction.bind(db),
|
|
149
|
+
async apply(ddl) {
|
|
150
|
+
await applyDdl(db, ddl);
|
|
151
|
+
},
|
|
152
|
+
close,
|
|
153
|
+
async [Symbol.asyncDispose]() {
|
|
154
|
+
await close();
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
}
|