@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
|
@@ -1,232 +1,232 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Phase 4c shared types — DDL / diff / migration runtime.
|
|
3
|
-
*
|
|
4
|
-
* This file is the CONTRACT between Agents A (DDL emit), B (diff engine),
|
|
5
|
-
* C (migration runtime), and downstream D (generator) / E (CLI) / F (QA).
|
|
6
|
-
* Do NOT add logic here — pure types only. Logic belongs next to each
|
|
7
|
-
* agent's module.
|
|
8
|
-
*
|
|
9
|
-
* Source of truth for:
|
|
10
|
-
* - SqlProvider, DdlFieldType, DdlDefault, DdlFieldDef, DdlIndex, DdlResource
|
|
11
|
-
* - Snapshot (serialized state of the schema at a point in time)
|
|
12
|
-
* - Change (discriminated union the diff engine emits)
|
|
13
|
-
* - PendingMigration / AppliedMigration (runtime plan + history records)
|
|
14
|
-
* - LockStrategy (per-dialect apply serialization)
|
|
15
|
-
*
|
|
16
|
-
* References:
|
|
17
|
-
* docs/bun/phase-4c-team-plan.md — team plan + I/O contracts
|
|
18
|
-
* docs/rfcs/0001-db-resource-layer.md — design decisions incl. Appendix D
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
// ========== Provider + field types ==========
|
|
22
|
-
|
|
23
|
-
/** Supported SQL providers. Drizzle/Atlas/sqldef all share this same set. */
|
|
24
|
-
export type SqlProvider = "postgres" | "mysql" | "sqlite";
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* DDL-relevant subset of Mandu's existing `FieldType`. v1 supports:
|
|
28
|
-
* string/number/boolean/date/uuid/email/url/json/array/object.
|
|
29
|
-
*
|
|
30
|
-
* `array` and `object` are persisted as JSON columns (JSONB on Postgres,
|
|
31
|
-
* JSON on MySQL, TEXT on SQLite). Users who need typed JSON fields should
|
|
32
|
-
* define a Zod schema in the contract layer; the DB only stores the blob.
|
|
33
|
-
*/
|
|
34
|
-
export type DdlFieldType =
|
|
35
|
-
| "string"
|
|
36
|
-
| "number"
|
|
37
|
-
| "boolean"
|
|
38
|
-
| "date"
|
|
39
|
-
| "uuid"
|
|
40
|
-
| "email"
|
|
41
|
-
| "url"
|
|
42
|
-
| "json"
|
|
43
|
-
| "array"
|
|
44
|
-
| "object";
|
|
45
|
-
|
|
46
|
-
/** How a DEFAULT clause is represented. */
|
|
47
|
-
export type DdlDefault =
|
|
48
|
-
| { kind: "now" } // CURRENT_TIMESTAMP / NOW() — dialect-mapped
|
|
49
|
-
| { kind: "null" }
|
|
50
|
-
| { kind: "literal"; value: string | number | boolean }
|
|
51
|
-
| { kind: "sql"; expr: string }; // raw expression — caller responsible for portability
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* DDL-level field definition. Normalized form derived from
|
|
55
|
-
* ResourceField + ResourceDefinition.persistence.fieldOverrides at
|
|
56
|
-
* snapshot creation time (see `snapshotFromResources`).
|
|
57
|
-
*/
|
|
58
|
-
export interface DdlFieldDef {
|
|
59
|
-
/** Column name in the DB. Derived from Mandu's field key (e.g. `passwordHash` → `password_hash` when `snake_case: true`). */
|
|
60
|
-
name: string;
|
|
61
|
-
/** Abstract Mandu field type. Maps to dialect-specific SQL type via the type map. */
|
|
62
|
-
type: DdlFieldType;
|
|
63
|
-
/** Whether NULL is allowed. Default: false (derived from `ResourceField.required === false`). */
|
|
64
|
-
nullable: boolean;
|
|
65
|
-
/** Primary key flag. Exactly one field per resource should have this set (composite keys are v2+). */
|
|
66
|
-
primary: boolean;
|
|
67
|
-
/** Unique constraint — emits `UNIQUE` on the column (standalone, not composite). */
|
|
68
|
-
unique: boolean;
|
|
69
|
-
/** Whether this field participates in a single-column index (non-unique). */
|
|
70
|
-
indexed: boolean;
|
|
71
|
-
/** DEFAULT clause. */
|
|
72
|
-
default?: DdlDefault;
|
|
73
|
-
/**
|
|
74
|
-
* For `string` type — VARCHAR length hint. Ignored by SQLite (TEXT is
|
|
75
|
-
* unbounded). Postgres prefers TEXT when undefined; MySQL emits
|
|
76
|
-
* VARCHAR(255) default when undefined.
|
|
77
|
-
*/
|
|
78
|
-
maxLength?: number;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/** Multi-column index definition (composite). Single-column indexes live on `DdlFieldDef.indexed`. */
|
|
82
|
-
export interface DdlIndex {
|
|
83
|
-
name: string; // must be unique within the resource
|
|
84
|
-
fields: string[]; // field names (in order)
|
|
85
|
-
unique: boolean;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* DDL-level resource — what actually reaches the emit / diff engines.
|
|
90
|
-
* Produced by `snapshotFromResources` from `ParsedResource[]`. Contains
|
|
91
|
-
* only the information the DB layer cares about.
|
|
92
|
-
*/
|
|
93
|
-
export interface DdlResource {
|
|
94
|
-
/** Table name in the DB. Usually `pluralize(resourceName)` or explicit override. */
|
|
95
|
-
name: string;
|
|
96
|
-
fields: DdlFieldDef[]; // order-preserving; affects emit order
|
|
97
|
-
indexes: DdlIndex[]; // multi-column indexes only; single-column live on fields
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// ========== Snapshots ==========
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* The full schema state at a point in time. Serialized to JSON and stored
|
|
104
|
-
* at `.mandu/schema/applied.json` after each successful apply.
|
|
105
|
-
* The diff engine compares an old snapshot (or null for first run) to a
|
|
106
|
-
* next snapshot computed from the current resource files.
|
|
107
|
-
*/
|
|
108
|
-
export interface Snapshot {
|
|
109
|
-
/** Format version of this snapshot file. Bump on breaking schema changes. */
|
|
110
|
-
version: 1;
|
|
111
|
-
/** Which provider this snapshot was built for. Diffing across providers is an error. */
|
|
112
|
-
provider: SqlProvider;
|
|
113
|
-
/** Resources in deterministic order (sorted by name). */
|
|
114
|
-
resources: DdlResource[];
|
|
115
|
-
/** When this snapshot was computed. For provenance only — not used by diff. */
|
|
116
|
-
generatedAt: string; // ISO 8601
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// ========== Changes ==========
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Discriminated union emitted by the diff engine. Every `Change` is one
|
|
123
|
-
* "atomic" DDL operation. Emit order is deterministic so the generated
|
|
124
|
-
* migration SQL is stable across runs.
|
|
125
|
-
*
|
|
126
|
-
* Rename is NOT auto-detected — the diff engine always emits drop + add.
|
|
127
|
-
* The CLI layer (Agent E) asks the user whether consecutive drop+add are
|
|
128
|
-
* a rename and rewrites the Change list accordingly before SQL emit.
|
|
129
|
-
*/
|
|
130
|
-
export type Change =
|
|
131
|
-
| { kind: "create-table"; resource: DdlResource }
|
|
132
|
-
| { kind: "drop-table"; resourceName: string }
|
|
133
|
-
| { kind: "add-column"; resourceName: string; field: DdlFieldDef }
|
|
134
|
-
| { kind: "drop-column"; resourceName: string; fieldName: string }
|
|
135
|
-
| {
|
|
136
|
-
kind: "alter-column-type";
|
|
137
|
-
resourceName: string;
|
|
138
|
-
fieldName: string;
|
|
139
|
-
fromType: DdlFieldType;
|
|
140
|
-
toType: DdlFieldType;
|
|
141
|
-
/** v1 emits a stub comment. User edits the migration manually. */
|
|
142
|
-
stub: true;
|
|
143
|
-
}
|
|
144
|
-
| { kind: "alter-column-nullable"; resourceName: string; fieldName: string; nullable: boolean }
|
|
145
|
-
| { kind: "alter-column-default"; resourceName: string; fieldName: string; default?: DdlDefault }
|
|
146
|
-
| { kind: "add-index"; resourceName: string; index: DdlIndex }
|
|
147
|
-
| { kind: "drop-index"; resourceName: string; indexName: string }
|
|
148
|
-
| {
|
|
149
|
-
kind: "rename-table";
|
|
150
|
-
oldName: string;
|
|
151
|
-
newName: string;
|
|
152
|
-
/** Emitted only after CLI user confirmation. Diff engine never emits directly. */
|
|
153
|
-
origin: "user-confirmed";
|
|
154
|
-
}
|
|
155
|
-
| {
|
|
156
|
-
kind: "rename-column";
|
|
157
|
-
resourceName: string;
|
|
158
|
-
oldName: string;
|
|
159
|
-
newName: string;
|
|
160
|
-
origin: "user-confirmed";
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
// ========== Migration runtime ==========
|
|
164
|
-
|
|
165
|
-
/** A migration file that exists in the migrations directory but has not yet been applied. */
|
|
166
|
-
export interface PendingMigration {
|
|
167
|
-
/** Zero-padded 4-digit sequence, e.g. "0001". Must sort lexicographically. */
|
|
168
|
-
version: string;
|
|
169
|
-
/** Filename relative to the migrations dir, e.g. "0001_create_users.sql". */
|
|
170
|
-
filename: string;
|
|
171
|
-
/** Full SQL text of the migration. */
|
|
172
|
-
sql: string;
|
|
173
|
-
/** SHA-256 of `sql` with `\r\n` normalized to `\n` — used by `__mandu_migrations` for tamper detection. */
|
|
174
|
-
checksum: string;
|
|
175
|
-
/** Filesystem mtime of the migration file. */
|
|
176
|
-
createdAt: Date;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/** A migration that has been applied — read from the `__mandu_migrations` history table. */
|
|
180
|
-
export interface AppliedMigration {
|
|
181
|
-
version: string;
|
|
182
|
-
filename: string;
|
|
183
|
-
checksum: string;
|
|
184
|
-
appliedAt: Date;
|
|
185
|
-
executionMs: number;
|
|
186
|
-
success: boolean;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/** Snapshot of the migration history at call time. */
|
|
190
|
-
export interface MigrationStatus {
|
|
191
|
-
applied: AppliedMigration[];
|
|
192
|
-
pending: PendingMigration[];
|
|
193
|
-
/** Migrations that exist in history but whose checksum no longer matches the file. */
|
|
194
|
-
tampered: Array<{ version: string; filename: string; storedChecksum: string; currentChecksum: string }>;
|
|
195
|
-
/** Migration files on disk that have no history row and don't match pending (shouldn't happen but guards against dir corruption). */
|
|
196
|
-
orphaned: Array<{ filename: string }>;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// ========== Lock strategy (per-dialect apply serialization) ==========
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Single-process apply serialization. Multi-instance coordination is out of
|
|
203
|
-
* scope for v1 (RFC §8 non-goals).
|
|
204
|
-
*
|
|
205
|
-
* Defaults per provider (Agent C implements):
|
|
206
|
-
* - postgres → "pg_advisory_lock" (`pg_advisory_lock(bigint)` + `pg_advisory_unlock`)
|
|
207
|
-
* - mysql → "mysql_get_lock" (`GET_LOCK('mandu-migrations', 60)` + `RELEASE_LOCK`)
|
|
208
|
-
* - sqlite → "sqlite_immediate" (`BEGIN IMMEDIATE` for the apply transaction)
|
|
209
|
-
*/
|
|
210
|
-
export type LockStrategy = "pg_advisory_lock" | "mysql_get_lock" | "sqlite_immediate" | "none";
|
|
211
|
-
|
|
212
|
-
// ========== Scope fences — what v1 does NOT cover ==========
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* v1 scope (enforced by Agent A/B — they should NOT handle these):
|
|
216
|
-
* - Foreign keys
|
|
217
|
-
* - CHECK constraints
|
|
218
|
-
* - ENUM types (custom Postgres ENUMs, MySQL ENUM columns)
|
|
219
|
-
* - Computed / GENERATED columns
|
|
220
|
-
* - Partitioning
|
|
221
|
-
* - Triggers, views, stored procedures
|
|
222
|
-
* - Alter column type (stub only — user edits manually)
|
|
223
|
-
* - Rename auto-detection (always drop+add unless CLI prompts user)
|
|
224
|
-
* - Multi-column primary key (composite)
|
|
225
|
-
* - Rollback / DOWN migrations
|
|
226
|
-
* - Repeatable migrations (Flyway `R__` style)
|
|
227
|
-
*
|
|
228
|
-
* Anything outside this list is intentionally out of scope for Phase 4c
|
|
229
|
-
* v1. Expansion lands in 4c.1 / 4c.2 patches after 4c merge.
|
|
230
|
-
*/
|
|
231
|
-
export type Phase4cScopeMarker = typeof _PHASE_4C_V1_SCOPE;
|
|
232
|
-
const _PHASE_4C_V1_SCOPE = Symbol.for("@mandujs/core/resource/ddl/phase-4c-v1");
|
|
1
|
+
/**
|
|
2
|
+
* Phase 4c shared types — DDL / diff / migration runtime.
|
|
3
|
+
*
|
|
4
|
+
* This file is the CONTRACT between Agents A (DDL emit), B (diff engine),
|
|
5
|
+
* C (migration runtime), and downstream D (generator) / E (CLI) / F (QA).
|
|
6
|
+
* Do NOT add logic here — pure types only. Logic belongs next to each
|
|
7
|
+
* agent's module.
|
|
8
|
+
*
|
|
9
|
+
* Source of truth for:
|
|
10
|
+
* - SqlProvider, DdlFieldType, DdlDefault, DdlFieldDef, DdlIndex, DdlResource
|
|
11
|
+
* - Snapshot (serialized state of the schema at a point in time)
|
|
12
|
+
* - Change (discriminated union the diff engine emits)
|
|
13
|
+
* - PendingMigration / AppliedMigration (runtime plan + history records)
|
|
14
|
+
* - LockStrategy (per-dialect apply serialization)
|
|
15
|
+
*
|
|
16
|
+
* References:
|
|
17
|
+
* docs/bun/phase-4c-team-plan.md — team plan + I/O contracts
|
|
18
|
+
* docs/rfcs/0001-db-resource-layer.md — design decisions incl. Appendix D
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
// ========== Provider + field types ==========
|
|
22
|
+
|
|
23
|
+
/** Supported SQL providers. Drizzle/Atlas/sqldef all share this same set. */
|
|
24
|
+
export type SqlProvider = "postgres" | "mysql" | "sqlite";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* DDL-relevant subset of Mandu's existing `FieldType`. v1 supports:
|
|
28
|
+
* string/number/boolean/date/uuid/email/url/json/array/object.
|
|
29
|
+
*
|
|
30
|
+
* `array` and `object` are persisted as JSON columns (JSONB on Postgres,
|
|
31
|
+
* JSON on MySQL, TEXT on SQLite). Users who need typed JSON fields should
|
|
32
|
+
* define a Zod schema in the contract layer; the DB only stores the blob.
|
|
33
|
+
*/
|
|
34
|
+
export type DdlFieldType =
|
|
35
|
+
| "string"
|
|
36
|
+
| "number"
|
|
37
|
+
| "boolean"
|
|
38
|
+
| "date"
|
|
39
|
+
| "uuid"
|
|
40
|
+
| "email"
|
|
41
|
+
| "url"
|
|
42
|
+
| "json"
|
|
43
|
+
| "array"
|
|
44
|
+
| "object";
|
|
45
|
+
|
|
46
|
+
/** How a DEFAULT clause is represented. */
|
|
47
|
+
export type DdlDefault =
|
|
48
|
+
| { kind: "now" } // CURRENT_TIMESTAMP / NOW() — dialect-mapped
|
|
49
|
+
| { kind: "null" }
|
|
50
|
+
| { kind: "literal"; value: string | number | boolean }
|
|
51
|
+
| { kind: "sql"; expr: string }; // raw expression — caller responsible for portability
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* DDL-level field definition. Normalized form derived from
|
|
55
|
+
* ResourceField + ResourceDefinition.persistence.fieldOverrides at
|
|
56
|
+
* snapshot creation time (see `snapshotFromResources`).
|
|
57
|
+
*/
|
|
58
|
+
export interface DdlFieldDef {
|
|
59
|
+
/** Column name in the DB. Derived from Mandu's field key (e.g. `passwordHash` → `password_hash` when `snake_case: true`). */
|
|
60
|
+
name: string;
|
|
61
|
+
/** Abstract Mandu field type. Maps to dialect-specific SQL type via the type map. */
|
|
62
|
+
type: DdlFieldType;
|
|
63
|
+
/** Whether NULL is allowed. Default: false (derived from `ResourceField.required === false`). */
|
|
64
|
+
nullable: boolean;
|
|
65
|
+
/** Primary key flag. Exactly one field per resource should have this set (composite keys are v2+). */
|
|
66
|
+
primary: boolean;
|
|
67
|
+
/** Unique constraint — emits `UNIQUE` on the column (standalone, not composite). */
|
|
68
|
+
unique: boolean;
|
|
69
|
+
/** Whether this field participates in a single-column index (non-unique). */
|
|
70
|
+
indexed: boolean;
|
|
71
|
+
/** DEFAULT clause. */
|
|
72
|
+
default?: DdlDefault;
|
|
73
|
+
/**
|
|
74
|
+
* For `string` type — VARCHAR length hint. Ignored by SQLite (TEXT is
|
|
75
|
+
* unbounded). Postgres prefers TEXT when undefined; MySQL emits
|
|
76
|
+
* VARCHAR(255) default when undefined.
|
|
77
|
+
*/
|
|
78
|
+
maxLength?: number;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Multi-column index definition (composite). Single-column indexes live on `DdlFieldDef.indexed`. */
|
|
82
|
+
export interface DdlIndex {
|
|
83
|
+
name: string; // must be unique within the resource
|
|
84
|
+
fields: string[]; // field names (in order)
|
|
85
|
+
unique: boolean;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* DDL-level resource — what actually reaches the emit / diff engines.
|
|
90
|
+
* Produced by `snapshotFromResources` from `ParsedResource[]`. Contains
|
|
91
|
+
* only the information the DB layer cares about.
|
|
92
|
+
*/
|
|
93
|
+
export interface DdlResource {
|
|
94
|
+
/** Table name in the DB. Usually `pluralize(resourceName)` or explicit override. */
|
|
95
|
+
name: string;
|
|
96
|
+
fields: DdlFieldDef[]; // order-preserving; affects emit order
|
|
97
|
+
indexes: DdlIndex[]; // multi-column indexes only; single-column live on fields
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ========== Snapshots ==========
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* The full schema state at a point in time. Serialized to JSON and stored
|
|
104
|
+
* at `.mandu/schema/applied.json` after each successful apply.
|
|
105
|
+
* The diff engine compares an old snapshot (or null for first run) to a
|
|
106
|
+
* next snapshot computed from the current resource files.
|
|
107
|
+
*/
|
|
108
|
+
export interface Snapshot {
|
|
109
|
+
/** Format version of this snapshot file. Bump on breaking schema changes. */
|
|
110
|
+
version: 1;
|
|
111
|
+
/** Which provider this snapshot was built for. Diffing across providers is an error. */
|
|
112
|
+
provider: SqlProvider;
|
|
113
|
+
/** Resources in deterministic order (sorted by name). */
|
|
114
|
+
resources: DdlResource[];
|
|
115
|
+
/** When this snapshot was computed. For provenance only — not used by diff. */
|
|
116
|
+
generatedAt: string; // ISO 8601
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ========== Changes ==========
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Discriminated union emitted by the diff engine. Every `Change` is one
|
|
123
|
+
* "atomic" DDL operation. Emit order is deterministic so the generated
|
|
124
|
+
* migration SQL is stable across runs.
|
|
125
|
+
*
|
|
126
|
+
* Rename is NOT auto-detected — the diff engine always emits drop + add.
|
|
127
|
+
* The CLI layer (Agent E) asks the user whether consecutive drop+add are
|
|
128
|
+
* a rename and rewrites the Change list accordingly before SQL emit.
|
|
129
|
+
*/
|
|
130
|
+
export type Change =
|
|
131
|
+
| { kind: "create-table"; resource: DdlResource }
|
|
132
|
+
| { kind: "drop-table"; resourceName: string }
|
|
133
|
+
| { kind: "add-column"; resourceName: string; field: DdlFieldDef }
|
|
134
|
+
| { kind: "drop-column"; resourceName: string; fieldName: string }
|
|
135
|
+
| {
|
|
136
|
+
kind: "alter-column-type";
|
|
137
|
+
resourceName: string;
|
|
138
|
+
fieldName: string;
|
|
139
|
+
fromType: DdlFieldType;
|
|
140
|
+
toType: DdlFieldType;
|
|
141
|
+
/** v1 emits a stub comment. User edits the migration manually. */
|
|
142
|
+
stub: true;
|
|
143
|
+
}
|
|
144
|
+
| { kind: "alter-column-nullable"; resourceName: string; fieldName: string; nullable: boolean }
|
|
145
|
+
| { kind: "alter-column-default"; resourceName: string; fieldName: string; default?: DdlDefault }
|
|
146
|
+
| { kind: "add-index"; resourceName: string; index: DdlIndex }
|
|
147
|
+
| { kind: "drop-index"; resourceName: string; indexName: string }
|
|
148
|
+
| {
|
|
149
|
+
kind: "rename-table";
|
|
150
|
+
oldName: string;
|
|
151
|
+
newName: string;
|
|
152
|
+
/** Emitted only after CLI user confirmation. Diff engine never emits directly. */
|
|
153
|
+
origin: "user-confirmed";
|
|
154
|
+
}
|
|
155
|
+
| {
|
|
156
|
+
kind: "rename-column";
|
|
157
|
+
resourceName: string;
|
|
158
|
+
oldName: string;
|
|
159
|
+
newName: string;
|
|
160
|
+
origin: "user-confirmed";
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// ========== Migration runtime ==========
|
|
164
|
+
|
|
165
|
+
/** A migration file that exists in the migrations directory but has not yet been applied. */
|
|
166
|
+
export interface PendingMigration {
|
|
167
|
+
/** Zero-padded 4-digit sequence, e.g. "0001". Must sort lexicographically. */
|
|
168
|
+
version: string;
|
|
169
|
+
/** Filename relative to the migrations dir, e.g. "0001_create_users.sql". */
|
|
170
|
+
filename: string;
|
|
171
|
+
/** Full SQL text of the migration. */
|
|
172
|
+
sql: string;
|
|
173
|
+
/** SHA-256 of `sql` with `\r\n` normalized to `\n` — used by `__mandu_migrations` for tamper detection. */
|
|
174
|
+
checksum: string;
|
|
175
|
+
/** Filesystem mtime of the migration file. */
|
|
176
|
+
createdAt: Date;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** A migration that has been applied — read from the `__mandu_migrations` history table. */
|
|
180
|
+
export interface AppliedMigration {
|
|
181
|
+
version: string;
|
|
182
|
+
filename: string;
|
|
183
|
+
checksum: string;
|
|
184
|
+
appliedAt: Date;
|
|
185
|
+
executionMs: number;
|
|
186
|
+
success: boolean;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** Snapshot of the migration history at call time. */
|
|
190
|
+
export interface MigrationStatus {
|
|
191
|
+
applied: AppliedMigration[];
|
|
192
|
+
pending: PendingMigration[];
|
|
193
|
+
/** Migrations that exist in history but whose checksum no longer matches the file. */
|
|
194
|
+
tampered: Array<{ version: string; filename: string; storedChecksum: string; currentChecksum: string }>;
|
|
195
|
+
/** Migration files on disk that have no history row and don't match pending (shouldn't happen but guards against dir corruption). */
|
|
196
|
+
orphaned: Array<{ filename: string }>;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// ========== Lock strategy (per-dialect apply serialization) ==========
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Single-process apply serialization. Multi-instance coordination is out of
|
|
203
|
+
* scope for v1 (RFC §8 non-goals).
|
|
204
|
+
*
|
|
205
|
+
* Defaults per provider (Agent C implements):
|
|
206
|
+
* - postgres → "pg_advisory_lock" (`pg_advisory_lock(bigint)` + `pg_advisory_unlock`)
|
|
207
|
+
* - mysql → "mysql_get_lock" (`GET_LOCK('mandu-migrations', 60)` + `RELEASE_LOCK`)
|
|
208
|
+
* - sqlite → "sqlite_immediate" (`BEGIN IMMEDIATE` for the apply transaction)
|
|
209
|
+
*/
|
|
210
|
+
export type LockStrategy = "pg_advisory_lock" | "mysql_get_lock" | "sqlite_immediate" | "none";
|
|
211
|
+
|
|
212
|
+
// ========== Scope fences — what v1 does NOT cover ==========
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* v1 scope (enforced by Agent A/B — they should NOT handle these):
|
|
216
|
+
* - Foreign keys
|
|
217
|
+
* - CHECK constraints
|
|
218
|
+
* - ENUM types (custom Postgres ENUMs, MySQL ENUM columns)
|
|
219
|
+
* - Computed / GENERATED columns
|
|
220
|
+
* - Partitioning
|
|
221
|
+
* - Triggers, views, stored procedures
|
|
222
|
+
* - Alter column type (stub only — user edits manually)
|
|
223
|
+
* - Rename auto-detection (always drop+add unless CLI prompts user)
|
|
224
|
+
* - Multi-column primary key (composite)
|
|
225
|
+
* - Rollback / DOWN migrations
|
|
226
|
+
* - Repeatable migrations (Flyway `R__` style)
|
|
227
|
+
*
|
|
228
|
+
* Anything outside this list is intentionally out of scope for Phase 4c
|
|
229
|
+
* v1. Expansion lands in 4c.1 / 4c.2 patches after 4c merge.
|
|
230
|
+
*/
|
|
231
|
+
export type Phase4cScopeMarker = typeof _PHASE_4C_V1_SCOPE;
|
|
232
|
+
const _PHASE_4C_V1_SCOPE = Symbol.for("@mandujs/core/resource/ddl/phase-4c-v1");
|