@aotter/mantle 0.2.0-alpha.6 → 0.2.0-alpha.8
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 +157 -45
- package/dist/auth/adapter.d.ts +32 -0
- package/dist/auth/adapter.js +285 -0
- package/dist/auth/admin.d.ts +3 -0
- package/dist/auth/admin.js +21 -0
- package/dist/auth/caller.d.ts +86 -0
- package/dist/auth/caller.js +155 -0
- package/dist/auth/hardening.d.ts +24 -0
- package/dist/auth/hardening.js +40 -0
- package/dist/auth/identity.d.ts +121 -0
- package/dist/auth/identity.js +203 -0
- package/dist/auth/oauth.d.ts +63 -0
- package/dist/auth/oauth.js +217 -0
- package/dist/auth/resource-seeds.js +10 -0
- package/dist/auth/routes.d.ts +32 -0
- package/dist/auth/routes.js +225 -0
- package/dist/build/compiler.d.ts +712 -0
- package/dist/build/compiler.js +6896 -0
- package/dist/{spec → build/spec}/domain/model/ManifestGrammar.d.ts +30 -47
- package/dist/{spec → build/spec}/domain/model/RuntimePlan.d.ts +77 -3
- package/dist/{spec → build/spec}/domain/model/SqlIr.d.ts +37 -6
- package/dist/build/spec/domain/model/UserFields.d.ts +20 -0
- package/dist/{spec → build/spec}/domain/service/PlanFingerprint.d.ts +4 -1
- package/dist/{spec → build/spec}/kernel/diagnostic.d.ts +1 -30
- package/dist/bun/assets.d.ts +2 -0
- package/dist/bun/assets.js +24 -0
- package/dist/domain/adminOrder.js +24 -0
- package/dist/domain/columns.js +55 -0
- package/dist/domain/describe/chunk-ZVXBGP7Y.js +424 -0
- package/dist/domain/describe/index.d.ts +58 -0
- package/dist/domain/describe/index.js +115 -0
- package/dist/domain/describe/target-hash.d.ts +8 -0
- package/dist/domain/describe/target-hash.js +12 -0
- package/dist/domain/describe/targets.d.ts +40 -0
- package/dist/domain/entry.js +33 -0
- package/dist/domain/generated-tools.js +19 -0
- package/dist/domain/generation.d.ts +16 -0
- package/dist/domain/generation.js +1 -0
- package/dist/domain/input.js +17 -0
- package/dist/domain/model.js +1 -0
- package/dist/domain/paging.js +230 -0
- package/dist/domain/recipes.js +19 -0
- package/dist/domain/userReferences.js +5 -0
- package/dist/domain/wireScalars.js +47 -0
- package/dist/infrastructure/adminEntries.js +153 -0
- package/dist/infrastructure/adminPaging.js +72 -0
- package/dist/infrastructure/artifacts.js +71 -0
- package/dist/infrastructure/authSchema.js +83 -0
- package/dist/infrastructure/bundle.js +174 -0
- package/dist/infrastructure/cli.js +97 -0
- package/dist/infrastructure/generate.d.ts +12 -0
- package/dist/infrastructure/generate.js +174 -0
- package/dist/infrastructure/generateAuth.d.ts +8 -0
- package/dist/infrastructure/generateAuth.js +23 -0
- package/dist/infrastructure/inputs.js +41 -0
- package/dist/infrastructure/wrangler.js +94 -0
- package/dist/kernel/authorization.d.ts +4 -0
- package/dist/kernel/authorization.js +16 -0
- package/dist/kernel/binds.d.ts +51 -0
- package/dist/kernel/binds.js +45 -0
- package/dist/kernel/caller-identity.d.ts +24 -0
- package/dist/kernel/caller-identity.js +22 -0
- package/dist/kernel/contract-error.d.ts +12 -0
- package/dist/kernel/contract-error.js +14 -0
- package/dist/kernel/contracts.d.ts +139 -0
- package/dist/kernel/contracts.js +92 -0
- package/dist/{spec/domain/service/CloudflareCron.d.ts → kernel/cron.d.ts} +0 -1
- package/dist/{spec/domain/service/CloudflareCron.js → kernel/cron.js} +1 -6
- package/dist/kernel/dialect/common.d.ts +39 -0
- package/dist/kernel/dialect/common.js +6 -0
- package/dist/kernel/dialect/postgres.d.ts +16 -0
- package/dist/kernel/dialect/postgres.js +18 -0
- package/dist/kernel/dialect/sqlite.d.ts +20 -0
- package/dist/kernel/dialect/sqlite.js +34 -0
- package/dist/kernel/drain.d.ts +5 -0
- package/dist/kernel/drain.js +35 -0
- package/dist/kernel/driver/bun-sqlite.d.ts +19 -0
- package/dist/kernel/driver/bun-sqlite.js +77 -0
- package/dist/kernel/driver/d1.d.ts +24 -0
- package/dist/kernel/driver/d1.js +22 -0
- package/dist/kernel/driver/postgres.d.ts +25 -0
- package/dist/kernel/driver/postgres.js +98 -0
- package/dist/kernel/driver/transaction-context.d.ts +10 -0
- package/dist/kernel/driver/transaction-context.js +29 -0
- package/dist/kernel/email.d.ts +28 -0
- package/dist/{auth/emailTemplates.js → kernel/email.js} +13 -2
- package/dist/kernel/host-access.d.ts +10 -0
- package/dist/kernel/host-access.js +65 -0
- package/dist/kernel/host-caller.d.ts +39 -0
- package/dist/kernel/host-caller.js +56 -0
- package/dist/kernel/json-body.d.ts +4 -0
- package/dist/kernel/json-body.js +44 -0
- package/dist/kernel/mcp-apps.d.ts +69 -0
- package/dist/kernel/mcp-apps.js +40 -0
- package/dist/kernel/mcp-call.d.ts +5 -0
- package/dist/kernel/mcp-call.js +25 -0
- package/dist/kernel/mcp-handler.js +371 -0
- package/dist/kernel/mcp.d.ts +106 -0
- package/dist/kernel/mcp.js +49 -0
- package/dist/kernel/media.d.ts +27 -0
- package/dist/kernel/media.js +216 -0
- package/dist/kernel/paging.d.ts +55 -0
- package/dist/kernel/paging.js +95 -0
- package/dist/kernel/publishing.d.ts +4 -0
- package/dist/kernel/publishing.js +16 -0
- package/dist/{cloudflare/r2Media.d.ts → kernel/r2-media.d.ts} +4 -5
- package/dist/kernel/r2-media.js +78 -0
- package/dist/kernel/rest-dispatch.js +38 -0
- package/dist/kernel/rest-router.js +64 -0
- package/dist/kernel/rest.d.ts +58 -0
- package/dist/kernel/rest.js +41 -0
- package/dist/kernel/scalars.d.ts +6 -0
- package/dist/kernel/scalars.js +43 -0
- package/dist/kernel/search.js +5 -0
- package/dist/{core/site.d.ts → kernel/site-types.d.ts} +38 -9
- package/dist/kernel/site-types.js +1 -0
- package/dist/kernel/site.d.ts +39 -0
- package/dist/kernel/site.js +32 -0
- package/dist/kernel/store.d.ts +165 -0
- package/dist/kernel/store.js +257 -0
- package/dist/kernel/surface.d.ts +10 -0
- package/dist/kernel/surface.js +19 -0
- package/dist/kernel/sweep.d.ts +17 -0
- package/dist/kernel/sweep.js +27 -0
- package/dist/kernel/translations.d.ts +1 -0
- package/dist/kernel/translations.js +13 -0
- package/dist/kernel/user-caller.d.ts +31 -0
- package/dist/kernel/user-caller.js +67 -0
- package/dist/kernel/user-field-name.js +3 -0
- package/dist/kernel/user-fields.d.ts +34 -0
- package/dist/kernel/user-fields.js +71 -0
- package/dist/kernel/validation.d.ts +15 -0
- package/dist/kernel/validation.js +54 -0
- package/dist/kernel/web-gateway.js +68 -0
- package/dist/kernel/web-head.js +15 -0
- package/dist/kernel/web-response.js +8 -0
- package/dist/kernel/web.d.ts +77 -0
- package/dist/kernel/web.js +158 -0
- package/dist/kernel/where.js +27 -0
- package/dist/testing/index.d.ts +1 -37
- package/dist/testing/index.js +1 -43
- package/dist/usecase/adminBindings.js +141 -0
- package/dist/usecase/adminClient.js +87 -0
- package/dist/usecase/adminDescriptors.js +107 -0
- package/dist/usecase/generate.js +165 -0
- package/dist/usecase/handlers.js +21 -0
- package/dist/usecase/mcp-media.js +17 -0
- package/dist/usecase/mcp.js +100 -0
- package/dist/usecase/paging.js +71 -0
- package/dist/usecase/publishing.js +63 -0
- package/dist/usecase/refusals.js +27 -0
- package/dist/usecase/rest.js +54 -0
- package/dist/usecase/search.js +7 -0
- package/dist/usecase/site.js +40 -0
- package/dist/usecase/stores.js +62 -0
- package/dist/usecase/tool-version.js +9 -0
- package/dist/usecase/translations.js +78 -0
- package/dist/usecase/ttl.js +20 -0
- package/dist/usecase/validation.js +233 -0
- package/dist/usecase/web.js +23 -0
- package/docs/examples/README.md +31 -16
- package/docs/examples/app-shell/README.md +86 -0
- package/docs/examples/app-shell/package.json +42 -0
- package/docs/examples/app-shell/pnpm-workspace.yaml +8 -0
- package/docs/examples/app-shell/smoke-kit.mjs +154 -0
- package/docs/examples/app-shell/src/auth.ts +57 -0
- package/docs/examples/app-shell/src/handlers.ts +5 -0
- package/docs/examples/app-shell/src/index.ts +4 -0
- package/docs/examples/app-shell/src/routes.ts +13 -0
- package/docs/examples/app-shell/src/schedule.ts +8 -0
- package/docs/examples/app-shell/src/service.ts +70 -0
- package/docs/examples/app-shell/src/sign-in.ts +41 -0
- package/docs/examples/app-shell/src/signup.ts +8 -0
- package/docs/examples/{reference-service → app-shell}/tsconfig.json +6 -2
- package/docs/examples/app-shell/worker-configuration.d.ts +22 -0
- package/docs/examples/app-shell/wrangler.jsonc +62 -0
- package/docs/examples/club-events/README.md +60 -0
- package/docs/examples/club-events/manifests/club-events.yaml +225 -0
- package/docs/examples/club-events/smoke.mjs +121 -0
- package/docs/examples/club-events/src/handlers.ts +25 -0
- package/docs/examples/club-events/src/signup.ts +9 -0
- package/docs/examples/generated-web/README.md +78 -0
- package/docs/examples/generated-web/posts.yaml +38 -0
- package/docs/examples/generated-web/seed.sql +6 -0
- package/docs/examples/generated-web/src/worker.ts +43 -0
- package/docs/examples/generated-web/tsconfig.json +8 -0
- package/docs/examples/generated-web/wrangler.jsonc +8 -0
- package/docs/examples/purchasing/.dev.vars.example +6 -0
- package/docs/examples/purchasing/README.md +90 -0
- package/docs/examples/purchasing/manifests/purchasing.yaml +341 -0
- package/docs/examples/purchasing/seed.sql +4 -0
- package/docs/examples/purchasing/smoke.mjs +177 -0
- package/docs/examples/purchasing/src/admin.tsx +13 -0
- package/docs/examples/purchasing/src/handlers.ts +33 -0
- package/docs/examples/purchasing/src/notify.ts +29 -0
- package/docs/examples/purchasing/src/requests-page.ts +57 -0
- package/docs/examples/purchasing/src/routes.ts +53 -0
- package/docs/examples/purchasing/src/schedule.ts +31 -0
- package/docs/examples/purchasing/src/signup.ts +5 -0
- package/docs/examples/purchasing/src/supplier.ts +32 -0
- package/docs/examples/purchasing/wrangler.jsonc +69 -0
- package/docs/examples/recipes/README.md +58 -0
- package/docs/examples/recipes/manifests/recipes.yaml +75 -0
- package/docs/examples/recipes/smoke.mjs +102 -0
- package/docs/examples/recipes/src/media.ts +13 -0
- package/docs/examples/recipes/src/pages.ts +99 -0
- package/docs/examples/recipes/src/routes.ts +71 -0
- package/docs/examples/recipes/src/site-config.ts +12 -0
- package/docs/examples/recipes/wrangler.jsonc +74 -0
- package/docs/handbook/cloudflare/authentication.md +164 -214
- package/docs/handbook/cloudflare/chatgpt-sites.md +4 -113
- package/docs/handbook/cloudflare/deploy-and-operate.md +38 -103
- package/docs/handbook/cloudflare/media-r2.md +62 -133
- package/docs/handbook/cloudflare/service-entry.md +210 -119
- package/docs/handbook/concepts/authorization.md +10 -123
- package/docs/handbook/concepts/four-atoms.md +9 -92
- package/docs/handbook/concepts/lifecycle-and-locales.md +9 -80
- package/docs/handbook/concepts/mcp-and-agents.md +24 -136
- package/docs/handbook/concepts/procedures-and-triggers.md +5 -162
- package/docs/handbook/concepts/runtime-and-adapters.md +15 -224
- package/docs/handbook/concepts/views.md +10 -109
- package/docs/handbook/examples/hub.md +2 -18
- package/docs/handbook/guides/adapter-guide.md +11 -0
- package/docs/handbook/guides/admin-ui.md +111 -164
- package/docs/handbook/guides/agent-setup.md +32 -27
- package/docs/handbook/guides/email.md +86 -0
- package/docs/handbook/guides/mcp-apps.md +483 -0
- package/docs/handbook/guides/native-admin.md +543 -0
- package/docs/handbook/guides/native-execution.md +132 -0
- package/docs/handbook/guides/oauth.md +161 -0
- package/docs/handbook/guides/postgres-adapters.md +56 -0
- package/docs/handbook/guides/public-pages.md +53 -0
- package/docs/handbook/guides/size-and-startup.md +9 -0
- package/docs/handbook/guides/typed-queries.md +39 -102
- package/docs/handbook/navigation.json +160 -31
- package/docs/handbook/reference/admin-descriptors.md +53 -0
- package/docs/handbook/reference/authorization.md +44 -52
- package/docs/handbook/reference/describe.md +56 -0
- package/docs/handbook/reference/diagnostics.md +15 -79
- package/docs/handbook/reference/features.md +45 -53
- package/docs/handbook/reference/manifest.md +6 -69
- package/docs/handbook/reference/procedure.md +11 -116
- package/docs/handbook/reference/schema.md +85 -185
- package/docs/handbook/reference/site-config.md +5 -65
- package/docs/handbook/reference/surface.md +389 -97
- package/docs/handbook/reference/trigger.md +54 -90
- package/docs/handbook/reference/view.md +32 -160
- package/docs/handbook/releases/index.md +120 -13
- package/docs/handbook/start/overview.md +9 -56
- package/docs/handbook/start/project-and-cli.md +40 -149
- package/docs/handbook/start/quickstart-worker.md +38 -116
- package/docs/skills/develop/SKILL.md +35 -123
- package/docs/skills/develop/mcp-app.md +37 -77
- package/docs/skills/integrate/SKILL.md +42 -84
- package/docs/skills/media-gc/SKILL.md +21 -8
- package/docs/skills/provision/SKILL.md +28 -91
- package/docs/skills/update/SKILL.md +19 -43
- package/docs/source/scripts/postgres-adapter.ts +101 -0
- package/docs/upgrade-0.1-to-0.2.md +25 -9
- package/package.json +97 -112
- package/skills/.keep +0 -0
- package/skills/README.md +67 -0
- package/skills/mantle/SKILL.md +135 -0
- package/skills/mantle/references/local-testing.md +15 -0
- package/skills/mantle/references/web.md +41 -0
- package/skills/mantle/references/website.md +49 -0
- package/dist/admin/consent.d.ts +0 -17
- package/dist/admin/consent.d.ts.map +0 -1
- package/dist/admin/consent.js +0 -17
- package/dist/admin/consent.js.map +0 -1
- package/dist/admin/createAdminSurface.d.ts +0 -25
- package/dist/admin/createAdminSurface.d.ts.map +0 -1
- package/dist/admin/createAdminSurface.js +0 -635
- package/dist/admin/createAdminSurface.js.map +0 -1
- package/dist/admin/design.d.ts +0 -7
- package/dist/admin/design.d.ts.map +0 -1
- package/dist/admin/design.js +0 -18
- package/dist/admin/design.js.map +0 -1
- package/dist/admin/developerConsole.d.ts +0 -267
- package/dist/admin/developerConsole.d.ts.map +0 -1
- package/dist/admin/developerConsole.js +0 -136
- package/dist/admin/developerConsole.js.map +0 -1
- package/dist/admin/extensions.d.ts +0 -290
- package/dist/admin/extensions.d.ts.map +0 -1
- package/dist/admin/extensions.js +0 -532
- package/dist/admin/extensions.js.map +0 -1
- package/dist/admin/identity.d.ts +0 -62
- package/dist/admin/identity.d.ts.map +0 -1
- package/dist/admin/identity.js +0 -7
- package/dist/admin/identity.js.map +0 -1
- package/dist/admin/index.d.ts +0 -7
- package/dist/admin/index.d.ts.map +0 -1
- package/dist/admin/index.js +0 -7
- package/dist/admin/index.js.map +0 -1
- package/dist/admin/procedureFlow.d.ts +0 -38
- package/dist/admin/procedureFlow.d.ts.map +0 -1
- package/dist/admin/procedureFlow.js +0 -188
- package/dist/admin/procedureFlow.js.map +0 -1
- package/dist/auth/ConsoleEmailSender.d.ts +0 -15
- package/dist/auth/ConsoleEmailSender.d.ts.map +0 -1
- package/dist/auth/ConsoleEmailSender.js +0 -19
- package/dist/auth/ConsoleEmailSender.js.map +0 -1
- package/dist/auth/appleClientSecret.d.ts +0 -75
- package/dist/auth/appleClientSecret.d.ts.map +0 -1
- package/dist/auth/appleClientSecret.js +0 -116
- package/dist/auth/appleClientSecret.js.map +0 -1
- package/dist/auth/buildAuth.d.ts +0 -4568
- package/dist/auth/buildAuth.d.ts.map +0 -1
- package/dist/auth/buildAuth.js +0 -312
- package/dist/auth/buildAuth.js.map +0 -1
- package/dist/auth/callerResolver.d.ts +0 -52
- package/dist/auth/callerResolver.d.ts.map +0 -1
- package/dist/auth/callerResolver.js +0 -52
- package/dist/auth/callerResolver.js.map +0 -1
- package/dist/auth/createAuthRoutes.d.ts +0 -22
- package/dist/auth/createAuthRoutes.d.ts.map +0 -1
- package/dist/auth/createAuthRoutes.js +0 -129
- package/dist/auth/createAuthRoutes.js.map +0 -1
- package/dist/auth/createMantleAuth.d.ts +0 -3
- package/dist/auth/createMantleAuth.d.ts.map +0 -1
- package/dist/auth/createMantleAuth.js +0 -504
- package/dist/auth/createMantleAuth.js.map +0 -1
- package/dist/auth/db.d.ts +0 -18
- package/dist/auth/db.d.ts.map +0 -1
- package/dist/auth/db.js +0 -27
- package/dist/auth/db.js.map +0 -1
- package/dist/auth/emailTemplates.d.ts +0 -7
- package/dist/auth/emailTemplates.d.ts.map +0 -1
- package/dist/auth/emailTemplates.js.map +0 -1
- package/dist/auth/index.d.ts +0 -9
- package/dist/auth/index.d.ts.map +0 -1
- package/dist/auth/index.js +0 -7
- package/dist/auth/index.js.map +0 -1
- package/dist/auth/methods.d.ts +0 -717
- package/dist/auth/methods.d.ts.map +0 -1
- package/dist/auth/methods.js +0 -321
- package/dist/auth/methods.js.map +0 -1
- package/dist/auth/oauthTokens.d.ts +0 -24
- package/dist/auth/oauthTokens.d.ts.map +0 -1
- package/dist/auth/oauthTokens.js +0 -146
- package/dist/auth/oauthTokens.js.map +0 -1
- package/dist/auth/setupIncomplete.d.ts +0 -16
- package/dist/auth/setupIncomplete.d.ts.map +0 -1
- package/dist/auth/setupIncomplete.js +0 -50
- package/dist/auth/setupIncomplete.js.map +0 -1
- package/dist/auth/types.d.ts +0 -440
- package/dist/auth/types.d.ts.map +0 -1
- package/dist/auth/types.js +0 -10
- package/dist/auth/types.js.map +0 -1
- package/dist/bun/index.d.ts +0 -21
- package/dist/bun/index.d.ts.map +0 -1
- package/dist/bun/index.js +0 -46
- package/dist/bun/index.js.map +0 -1
- package/dist/cli/emitModule.d.ts +0 -7
- package/dist/cli/emitModule.d.ts.map +0 -1
- package/dist/cli/emitModule.js +0 -127
- package/dist/cli/emitModule.js.map +0 -1
- package/dist/cli/generate.d.ts +0 -8
- package/dist/cli/generate.d.ts.map +0 -1
- package/dist/cli/generate.js +0 -391
- package/dist/cli/generate.js.map +0 -1
- package/dist/cli/main.d.ts +0 -3
- package/dist/cli/main.d.ts.map +0 -1
- package/dist/cli/main.js +0 -21
- package/dist/cli/main.js.map +0 -1
- package/dist/cli/preset.d.ts +0 -18
- package/dist/cli/preset.d.ts.map +0 -1
- package/dist/cli/preset.js +0 -405
- package/dist/cli/preset.js.map +0 -1
- package/dist/cloudflare/index.d.ts +0 -25
- package/dist/cloudflare/index.d.ts.map +0 -1
- package/dist/cloudflare/index.js +0 -16
- package/dist/cloudflare/index.js.map +0 -1
- package/dist/cloudflare/r2Media.d.ts.map +0 -1
- package/dist/cloudflare/r2Media.js +0 -69
- package/dist/cloudflare/r2Media.js.map +0 -1
- package/dist/core/caller.d.ts +0 -35
- package/dist/core/caller.d.ts.map +0 -1
- package/dist/core/caller.js +0 -3
- package/dist/core/caller.js.map +0 -1
- package/dist/core/createMantle.d.ts +0 -22
- package/dist/core/createMantle.d.ts.map +0 -1
- package/dist/core/createMantle.js +0 -117
- package/dist/core/createMantle.js.map +0 -1
- package/dist/core/dialect.d.ts +0 -53
- package/dist/core/dialect.d.ts.map +0 -1
- package/dist/core/dialect.js +0 -7
- package/dist/core/dialect.js.map +0 -1
- package/dist/core/driver.d.ts +0 -24
- package/dist/core/driver.d.ts.map +0 -1
- package/dist/core/driver.js +0 -2
- package/dist/core/driver.js.map +0 -1
- package/dist/core/email.d.ts +0 -17
- package/dist/core/email.d.ts.map +0 -1
- package/dist/core/email.js +0 -2
- package/dist/core/email.js.map +0 -1
- package/dist/core/index.d.ts +0 -16
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js +0 -16
- package/dist/core/index.js.map +0 -1
- package/dist/core/invocation.d.ts +0 -66
- package/dist/core/invocation.d.ts.map +0 -1
- package/dist/core/invocation.js +0 -3
- package/dist/core/invocation.js.map +0 -1
- package/dist/core/observation.d.ts +0 -3
- package/dist/core/observation.d.ts.map +0 -1
- package/dist/core/observation.js +0 -10
- package/dist/core/observation.js.map +0 -1
- package/dist/core/runtime/auth.d.ts +0 -9
- package/dist/core/runtime/auth.d.ts.map +0 -1
- package/dist/core/runtime/auth.js +0 -39
- package/dist/core/runtime/auth.js.map +0 -1
- package/dist/core/runtime/createRuntime.d.ts +0 -23
- package/dist/core/runtime/createRuntime.d.ts.map +0 -1
- package/dist/core/runtime/createRuntime.js +0 -214
- package/dist/core/runtime/createRuntime.js.map +0 -1
- package/dist/core/runtime/verifyPlan.d.ts +0 -34
- package/dist/core/runtime/verifyPlan.d.ts.map +0 -1
- package/dist/core/runtime/verifyPlan.js +0 -301
- package/dist/core/runtime/verifyPlan.js.map +0 -1
- package/dist/core/service.d.ts +0 -45
- package/dist/core/service.d.ts.map +0 -1
- package/dist/core/service.js +0 -2
- package/dist/core/service.js.map +0 -1
- package/dist/core/sessionUser.d.ts +0 -14
- package/dist/core/sessionUser.d.ts.map +0 -1
- package/dist/core/sessionUser.js +0 -4
- package/dist/core/sessionUser.js.map +0 -1
- package/dist/core/site.d.ts.map +0 -1
- package/dist/core/site.js +0 -2
- package/dist/core/site.js.map +0 -1
- package/dist/core/siteConfig.d.ts +0 -5
- package/dist/core/siteConfig.d.ts.map +0 -1
- package/dist/core/siteConfig.js +0 -24
- package/dist/core/siteConfig.js.map +0 -1
- package/dist/core/sql/allowlist.d.ts +0 -67
- package/dist/core/sql/allowlist.d.ts.map +0 -1
- package/dist/core/sql/allowlist.js +0 -737
- package/dist/core/sql/allowlist.js.map +0 -1
- package/dist/core/sql/ast.d.ts +0 -24
- package/dist/core/sql/ast.d.ts.map +0 -1
- package/dist/core/sql/ast.js +0 -32
- package/dist/core/sql/ast.js.map +0 -1
- package/dist/core/sql/compile.d.ts +0 -50
- package/dist/core/sql/compile.d.ts.map +0 -1
- package/dist/core/sql/compile.js +0 -48
- package/dist/core/sql/compile.js.map +0 -1
- package/dist/core/sql/policy.d.ts +0 -123
- package/dist/core/sql/policy.d.ts.map +0 -1
- package/dist/core/sql/policy.js +0 -398
- package/dist/core/sql/policy.js.map +0 -1
- package/dist/core/sql/positions.d.ts +0 -30
- package/dist/core/sql/positions.d.ts.map +0 -1
- package/dist/core/sql/positions.js +0 -22
- package/dist/core/sql/positions.js.map +0 -1
- package/dist/core/sql/run.d.ts +0 -68
- package/dist/core/sql/run.d.ts.map +0 -1
- package/dist/core/sql/run.js +0 -384
- package/dist/core/sql/run.js.map +0 -1
- package/dist/core/store/createStore.d.ts +0 -49
- package/dist/core/store/createStore.d.ts.map +0 -1
- package/dist/core/store/createStore.js +0 -227
- package/dist/core/store/createStore.js.map +0 -1
- package/dist/core/store/cursor.d.ts +0 -4
- package/dist/core/store/cursor.d.ts.map +0 -1
- package/dist/core/store/cursor.js +0 -22
- package/dist/core/store/cursor.js.map +0 -1
- package/dist/core/store/json.d.ts +0 -80
- package/dist/core/store/json.d.ts.map +0 -1
- package/dist/core/store/json.js +0 -342
- package/dist/core/store/json.js.map +0 -1
- package/dist/core/store.d.ts +0 -160
- package/dist/core/store.d.ts.map +0 -1
- package/dist/core/store.js +0 -2
- package/dist/core/store.js.map +0 -1
- package/dist/core/wire.d.ts +0 -20
- package/dist/core/wire.d.ts.map +0 -1
- package/dist/core/wire.js +0 -84
- package/dist/core/wire.js.map +0 -1
- package/dist/core/withCaller.d.ts +0 -24
- package/dist/core/withCaller.d.ts.map +0 -1
- package/dist/core/withCaller.js +0 -35
- package/dist/core/withCaller.js.map +0 -1
- package/dist/d1/adapter.d.ts +0 -12
- package/dist/d1/adapter.d.ts.map +0 -1
- package/dist/d1/adapter.js +0 -23
- package/dist/d1/adapter.js.map +0 -1
- package/dist/d1/codec.d.ts +0 -14
- package/dist/d1/codec.d.ts.map +0 -1
- package/dist/d1/codec.js +0 -136
- package/dist/d1/codec.js.map +0 -1
- package/dist/d1/compile/index.d.ts +0 -9
- package/dist/d1/compile/index.d.ts.map +0 -1
- package/dist/d1/compile/index.js +0 -9
- package/dist/d1/compile/index.js.map +0 -1
- package/dist/d1/dialect.d.ts +0 -4
- package/dist/d1/dialect.d.ts.map +0 -1
- package/dist/d1/dialect.js +0 -13
- package/dist/d1/dialect.js.map +0 -1
- package/dist/d1/executor.d.ts +0 -15
- package/dist/d1/executor.d.ts.map +0 -1
- package/dist/d1/executor.js +0 -96
- package/dist/d1/executor.js.map +0 -1
- package/dist/d1/index.d.ts +0 -6
- package/dist/d1/index.d.ts.map +0 -1
- package/dist/d1/index.js +0 -6
- package/dist/d1/index.js.map +0 -1
- package/dist/d1/lower.d.ts +0 -8
- package/dist/d1/lower.d.ts.map +0 -1
- package/dist/d1/lower.js +0 -167
- package/dist/d1/lower.js.map +0 -1
- package/dist/d1/media.d.ts +0 -5
- package/dist/d1/media.d.ts.map +0 -1
- package/dist/d1/media.js +0 -157
- package/dist/d1/media.js.map +0 -1
- package/dist/d1/migrations.d.ts +0 -12
- package/dist/d1/migrations.d.ts.map +0 -1
- package/dist/d1/migrations.js +0 -111
- package/dist/d1/migrations.js.map +0 -1
- package/dist/d1/print.d.ts +0 -28
- package/dist/d1/print.d.ts.map +0 -1
- package/dist/d1/print.js +0 -54
- package/dist/d1/print.js.map +0 -1
- package/dist/d1/site.d.ts +0 -17
- package/dist/d1/site.d.ts.map +0 -1
- package/dist/d1/site.js +0 -63
- package/dist/d1/site.js.map +0 -1
- package/dist/d1/storage.d.ts +0 -34
- package/dist/d1/storage.d.ts.map +0 -1
- package/dist/d1/storage.js +0 -288
- package/dist/d1/storage.js.map +0 -1
- package/dist/d1/tz.d.ts +0 -21
- package/dist/d1/tz.d.ts.map +0 -1
- package/dist/d1/tz.js +0 -54
- package/dist/d1/tz.js.map +0 -1
- package/dist/d1/validator.d.ts +0 -10
- package/dist/d1/validator.d.ts.map +0 -1
- package/dist/d1/validator.js +0 -33
- package/dist/d1/validator.js.map +0 -1
- package/dist/mcp/apps.d.ts +0 -43
- package/dist/mcp/apps.d.ts.map +0 -1
- package/dist/mcp/apps.js +0 -57
- package/dist/mcp/apps.js.map +0 -1
- package/dist/mcp/catalog.d.ts +0 -55
- package/dist/mcp/catalog.d.ts.map +0 -1
- package/dist/mcp/catalog.js +0 -81
- package/dist/mcp/catalog.js.map +0 -1
- package/dist/mcp/createMcpSurface.d.ts +0 -60
- package/dist/mcp/createMcpSurface.d.ts.map +0 -1
- package/dist/mcp/createMcpSurface.js +0 -182
- package/dist/mcp/createMcpSurface.js.map +0 -1
- package/dist/mcp/index.d.ts +0 -4
- package/dist/mcp/index.d.ts.map +0 -1
- package/dist/mcp/index.js +0 -4
- package/dist/mcp/index.js.map +0 -1
- package/dist/mcp/media.d.ts +0 -9
- package/dist/mcp/media.d.ts.map +0 -1
- package/dist/mcp/media.js +0 -33
- package/dist/mcp/media.js.map +0 -1
- package/dist/postgres/adapter.d.ts +0 -23
- package/dist/postgres/adapter.d.ts.map +0 -1
- package/dist/postgres/adapter.js +0 -50
- package/dist/postgres/adapter.js.map +0 -1
- package/dist/postgres/codec.d.ts +0 -13
- package/dist/postgres/codec.d.ts.map +0 -1
- package/dist/postgres/codec.js +0 -110
- package/dist/postgres/codec.js.map +0 -1
- package/dist/postgres/compile/index.d.ts +0 -9
- package/dist/postgres/compile/index.d.ts.map +0 -1
- package/dist/postgres/compile/index.js +0 -9
- package/dist/postgres/compile/index.js.map +0 -1
- package/dist/postgres/driver.d.ts +0 -109
- package/dist/postgres/driver.d.ts.map +0 -1
- package/dist/postgres/driver.js +0 -186
- package/dist/postgres/driver.js.map +0 -1
- package/dist/postgres/executor.d.ts +0 -28
- package/dist/postgres/executor.d.ts.map +0 -1
- package/dist/postgres/executor.js +0 -96
- package/dist/postgres/executor.js.map +0 -1
- package/dist/postgres/index.d.ts +0 -8
- package/dist/postgres/index.d.ts.map +0 -1
- package/dist/postgres/index.js +0 -8
- package/dist/postgres/index.js.map +0 -1
- package/dist/postgres/lower.d.ts +0 -6
- package/dist/postgres/lower.d.ts.map +0 -1
- package/dist/postgres/lower.js +0 -152
- package/dist/postgres/lower.js.map +0 -1
- package/dist/postgres/print.d.ts +0 -11
- package/dist/postgres/print.d.ts.map +0 -1
- package/dist/postgres/print.js +0 -108
- package/dist/postgres/print.js.map +0 -1
- package/dist/postgres/session.d.ts +0 -9
- package/dist/postgres/session.d.ts.map +0 -1
- package/dist/postgres/session.js +0 -111
- package/dist/postgres/session.js.map +0 -1
- package/dist/postgres/storage.d.ts +0 -32
- package/dist/postgres/storage.d.ts.map +0 -1
- package/dist/postgres/storage.js +0 -283
- package/dist/postgres/storage.js.map +0 -1
- package/dist/postgres/validator.d.ts +0 -13
- package/dist/postgres/validator.d.ts.map +0 -1
- package/dist/postgres/validator.js +0 -53
- package/dist/postgres/validator.js.map +0 -1
- package/dist/spec/domain/index.d.ts +0 -3
- package/dist/spec/domain/index.d.ts.map +0 -1
- package/dist/spec/domain/index.js +0 -3
- package/dist/spec/domain/index.js.map +0 -1
- package/dist/spec/domain/model/ContentState.d.ts +0 -8
- package/dist/spec/domain/model/ContentState.d.ts.map +0 -1
- package/dist/spec/domain/model/ContentState.js +0 -7
- package/dist/spec/domain/model/ContentState.js.map +0 -1
- package/dist/spec/domain/model/Entry.d.ts +0 -29
- package/dist/spec/domain/model/Entry.d.ts.map +0 -1
- package/dist/spec/domain/model/Entry.js +0 -16
- package/dist/spec/domain/model/Entry.js.map +0 -1
- package/dist/spec/domain/model/Locale.d.ts +0 -30
- package/dist/spec/domain/model/Locale.d.ts.map +0 -1
- package/dist/spec/domain/model/Locale.js +0 -33
- package/dist/spec/domain/model/Locale.js.map +0 -1
- package/dist/spec/domain/model/ManifestGrammar.d.ts.map +0 -1
- package/dist/spec/domain/model/ManifestGrammar.js +0 -153
- package/dist/spec/domain/model/ManifestGrammar.js.map +0 -1
- package/dist/spec/domain/model/MediaMimeAccept.d.ts +0 -55
- package/dist/spec/domain/model/MediaMimeAccept.d.ts.map +0 -1
- package/dist/spec/domain/model/MediaMimeAccept.js +0 -90
- package/dist/spec/domain/model/MediaMimeAccept.js.map +0 -1
- package/dist/spec/domain/model/RuntimePlan.d.ts.map +0 -1
- package/dist/spec/domain/model/RuntimePlan.js +0 -4
- package/dist/spec/domain/model/RuntimePlan.js.map +0 -1
- package/dist/spec/domain/model/SiteConfig.d.ts +0 -173
- package/dist/spec/domain/model/SiteConfig.d.ts.map +0 -1
- package/dist/spec/domain/model/SiteConfig.js +0 -13
- package/dist/spec/domain/model/SiteConfig.js.map +0 -1
- package/dist/spec/domain/model/SqlIr.d.ts.map +0 -1
- package/dist/spec/domain/model/SqlIr.js +0 -95
- package/dist/spec/domain/model/SqlIr.js.map +0 -1
- package/dist/spec/domain/model/index.d.ts +0 -14
- package/dist/spec/domain/model/index.d.ts.map +0 -1
- package/dist/spec/domain/model/index.js +0 -14
- package/dist/spec/domain/model/index.js.map +0 -1
- package/dist/spec/domain/service/CloudflareCron.d.ts.map +0 -1
- package/dist/spec/domain/service/CloudflareCron.js.map +0 -1
- package/dist/spec/domain/service/CrossSchemaChecker.d.ts +0 -34
- package/dist/spec/domain/service/CrossSchemaChecker.d.ts.map +0 -1
- package/dist/spec/domain/service/CrossSchemaChecker.js +0 -114
- package/dist/spec/domain/service/CrossSchemaChecker.js.map +0 -1
- package/dist/spec/domain/service/EntryDataValidator.d.ts +0 -56
- package/dist/spec/domain/service/EntryDataValidator.d.ts.map +0 -1
- package/dist/spec/domain/service/EntryDataValidator.js +0 -88
- package/dist/spec/domain/service/EntryDataValidator.js.map +0 -1
- package/dist/spec/domain/service/JsonSchemaToZod.d.ts +0 -29
- package/dist/spec/domain/service/JsonSchemaToZod.d.ts.map +0 -1
- package/dist/spec/domain/service/JsonSchemaToZod.js +0 -156
- package/dist/spec/domain/service/JsonSchemaToZod.js.map +0 -1
- package/dist/spec/domain/service/LifecycleStateMachine.d.ts +0 -75
- package/dist/spec/domain/service/LifecycleStateMachine.d.ts.map +0 -1
- package/dist/spec/domain/service/LifecycleStateMachine.js +0 -76
- package/dist/spec/domain/service/LifecycleStateMachine.js.map +0 -1
- package/dist/spec/domain/service/LocaleCanonicalizer.d.ts +0 -29
- package/dist/spec/domain/service/LocaleCanonicalizer.d.ts.map +0 -1
- package/dist/spec/domain/service/LocaleCanonicalizer.js +0 -96
- package/dist/spec/domain/service/LocaleCanonicalizer.js.map +0 -1
- package/dist/spec/domain/service/ManifestFieldChecks.d.ts +0 -60
- package/dist/spec/domain/service/ManifestFieldChecks.d.ts.map +0 -1
- package/dist/spec/domain/service/ManifestFieldChecks.js +0 -116
- package/dist/spec/domain/service/ManifestFieldChecks.js.map +0 -1
- package/dist/spec/domain/service/ManifestGraphValidator.d.ts +0 -15
- package/dist/spec/domain/service/ManifestGraphValidator.d.ts.map +0 -1
- package/dist/spec/domain/service/ManifestGraphValidator.js +0 -225
- package/dist/spec/domain/service/ManifestGraphValidator.js.map +0 -1
- package/dist/spec/domain/service/ManifestLinker.d.ts +0 -45
- package/dist/spec/domain/service/ManifestLinker.d.ts.map +0 -1
- package/dist/spec/domain/service/ManifestLinker.js +0 -92
- package/dist/spec/domain/service/ManifestLinker.js.map +0 -1
- package/dist/spec/domain/service/ManifestLocaleTrimmer.d.ts +0 -16
- package/dist/spec/domain/service/ManifestLocaleTrimmer.d.ts.map +0 -1
- package/dist/spec/domain/service/ManifestLocaleTrimmer.js +0 -76
- package/dist/spec/domain/service/ManifestLocaleTrimmer.js.map +0 -1
- package/dist/spec/domain/service/ManifestParser.d.ts +0 -49
- package/dist/spec/domain/service/ManifestParser.d.ts.map +0 -1
- package/dist/spec/domain/service/ManifestParser.js +0 -203
- package/dist/spec/domain/service/ManifestParser.js.map +0 -1
- package/dist/spec/domain/service/ManifestPartition.d.ts +0 -9
- package/dist/spec/domain/service/ManifestPartition.d.ts.map +0 -1
- package/dist/spec/domain/service/ManifestPartition.js +0 -19
- package/dist/spec/domain/service/ManifestPartition.js.map +0 -1
- package/dist/spec/domain/service/ManifestPathDiagnoser.d.ts +0 -33
- package/dist/spec/domain/service/ManifestPathDiagnoser.d.ts.map +0 -1
- package/dist/spec/domain/service/ManifestPathDiagnoser.js +0 -43
- package/dist/spec/domain/service/ManifestPathDiagnoser.js.map +0 -1
- package/dist/spec/domain/service/ManifestSourceSpans.d.ts +0 -10
- package/dist/spec/domain/service/ManifestSourceSpans.d.ts.map +0 -1
- package/dist/spec/domain/service/ManifestSourceSpans.js +0 -76
- package/dist/spec/domain/service/ManifestSourceSpans.js.map +0 -1
- package/dist/spec/domain/service/McpToolNaming.d.ts +0 -25
- package/dist/spec/domain/service/McpToolNaming.d.ts.map +0 -1
- package/dist/spec/domain/service/McpToolNaming.js +0 -50
- package/dist/spec/domain/service/McpToolNaming.js.map +0 -1
- package/dist/spec/domain/service/PlanFingerprint.d.ts.map +0 -1
- package/dist/spec/domain/service/PlanFingerprint.js +0 -14
- package/dist/spec/domain/service/PlanFingerprint.js.map +0 -1
- package/dist/spec/domain/service/ProcedureViewSpecChecks.d.ts +0 -4
- package/dist/spec/domain/service/ProcedureViewSpecChecks.d.ts.map +0 -1
- package/dist/spec/domain/service/ProcedureViewSpecChecks.js +0 -211
- package/dist/spec/domain/service/ProcedureViewSpecChecks.js.map +0 -1
- package/dist/spec/domain/service/SchemaAdminUiChecker.d.ts +0 -44
- package/dist/spec/domain/service/SchemaAdminUiChecker.d.ts.map +0 -1
- package/dist/spec/domain/service/SchemaAdminUiChecker.js +0 -333
- package/dist/spec/domain/service/SchemaAdminUiChecker.js.map +0 -1
- package/dist/spec/domain/service/SchemaIndexChecker.d.ts +0 -33
- package/dist/spec/domain/service/SchemaIndexChecker.d.ts.map +0 -1
- package/dist/spec/domain/service/SchemaIndexChecker.js +0 -256
- package/dist/spec/domain/service/SchemaIndexChecker.js.map +0 -1
- package/dist/spec/domain/service/SchemaSearchChecker.d.ts +0 -11
- package/dist/spec/domain/service/SchemaSearchChecker.d.ts.map +0 -1
- package/dist/spec/domain/service/SchemaSearchChecker.js +0 -78
- package/dist/spec/domain/service/SchemaSearchChecker.js.map +0 -1
- package/dist/spec/domain/service/SchemaSpecChecks.d.ts +0 -31
- package/dist/spec/domain/service/SchemaSpecChecks.d.ts.map +0 -1
- package/dist/spec/domain/service/SchemaSpecChecks.js +0 -445
- package/dist/spec/domain/service/SchemaSpecChecks.js.map +0 -1
- package/dist/spec/domain/service/SiteDefaultsValidator.d.ts +0 -39
- package/dist/spec/domain/service/SiteDefaultsValidator.d.ts.map +0 -1
- package/dist/spec/domain/service/SiteDefaultsValidator.js +0 -194
- package/dist/spec/domain/service/SiteDefaultsValidator.js.map +0 -1
- package/dist/spec/domain/service/SqlClassify.d.ts +0 -19
- package/dist/spec/domain/service/SqlClassify.d.ts.map +0 -1
- package/dist/spec/domain/service/SqlClassify.js +0 -42
- package/dist/spec/domain/service/SqlClassify.js.map +0 -1
- package/dist/spec/domain/service/SqlRefusal.d.ts +0 -16
- package/dist/spec/domain/service/SqlRefusal.d.ts.map +0 -1
- package/dist/spec/domain/service/SqlRefusal.js +0 -20
- package/dist/spec/domain/service/SqlRefusal.js.map +0 -1
- package/dist/spec/domain/service/SqlTypes.d.ts +0 -40
- package/dist/spec/domain/service/SqlTypes.d.ts.map +0 -1
- package/dist/spec/domain/service/SqlTypes.js +0 -110
- package/dist/spec/domain/service/SqlTypes.js.map +0 -1
- package/dist/spec/domain/service/StaffRoleHierarchy.d.ts +0 -3
- package/dist/spec/domain/service/StaffRoleHierarchy.d.ts.map +0 -1
- package/dist/spec/domain/service/StaffRoleHierarchy.js +0 -19
- package/dist/spec/domain/service/StaffRoleHierarchy.js.map +0 -1
- package/dist/spec/domain/service/TriggerGraphChecks.d.ts +0 -16
- package/dist/spec/domain/service/TriggerGraphChecks.d.ts.map +0 -1
- package/dist/spec/domain/service/TriggerGraphChecks.js +0 -337
- package/dist/spec/domain/service/TriggerGraphChecks.js.map +0 -1
- package/dist/spec/domain/service/TriggerSpecChecks.d.ts +0 -4
- package/dist/spec/domain/service/TriggerSpecChecks.d.ts.map +0 -1
- package/dist/spec/domain/service/TriggerSpecChecks.js +0 -89
- package/dist/spec/domain/service/TriggerSpecChecks.js.map +0 -1
- package/dist/spec/domain/service/ValidatedAdminUiProjection.d.ts +0 -11
- package/dist/spec/domain/service/ValidatedAdminUiProjection.d.ts.map +0 -1
- package/dist/spec/domain/service/ValidatedAdminUiProjection.js +0 -26
- package/dist/spec/domain/service/ValidatedAdminUiProjection.js.map +0 -1
- package/dist/spec/domain/service/ViewAdminUiChecker.d.ts +0 -14
- package/dist/spec/domain/service/ViewAdminUiChecker.d.ts.map +0 -1
- package/dist/spec/domain/service/ViewAdminUiChecker.js +0 -58
- package/dist/spec/domain/service/ViewAdminUiChecker.js.map +0 -1
- package/dist/spec/domain/service/index.d.ts +0 -24
- package/dist/spec/domain/service/index.d.ts.map +0 -1
- package/dist/spec/domain/service/index.js +0 -24
- package/dist/spec/domain/service/index.js.map +0 -1
- package/dist/spec/index.d.ts +0 -10
- package/dist/spec/index.d.ts.map +0 -1
- package/dist/spec/index.js +0 -12
- package/dist/spec/index.js.map +0 -1
- package/dist/spec/infrastructure/cli/parseArgsError.d.ts +0 -16
- package/dist/spec/infrastructure/cli/parseArgsError.d.ts.map +0 -1
- package/dist/spec/infrastructure/cli/parseArgsError.js +0 -34
- package/dist/spec/infrastructure/cli/parseArgsError.js.map +0 -1
- package/dist/spec/infrastructure/index.d.ts +0 -2
- package/dist/spec/infrastructure/index.d.ts.map +0 -1
- package/dist/spec/infrastructure/index.js +0 -2
- package/dist/spec/infrastructure/index.js.map +0 -1
- package/dist/spec/infrastructure/sql/PgQueryParser.d.ts +0 -18
- package/dist/spec/infrastructure/sql/PgQueryParser.d.ts.map +0 -1
- package/dist/spec/infrastructure/sql/PgQueryParser.js +0 -17
- package/dist/spec/infrastructure/sql/PgQueryParser.js.map +0 -1
- package/dist/spec/infrastructure/sql/compilePlan.d.ts +0 -37
- package/dist/spec/infrastructure/sql/compilePlan.d.ts.map +0 -1
- package/dist/spec/infrastructure/sql/compilePlan.js +0 -287
- package/dist/spec/infrastructure/sql/compilePlan.js.map +0 -1
- package/dist/spec/infrastructure/sql/compileSql.d.ts +0 -35
- package/dist/spec/infrastructure/sql/compileSql.d.ts.map +0 -1
- package/dist/spec/infrastructure/sql/compileSql.js +0 -92
- package/dist/spec/infrastructure/sql/compileSql.js.map +0 -1
- package/dist/spec/infrastructure/sql/frontEnd.d.ts +0 -8
- package/dist/spec/infrastructure/sql/frontEnd.d.ts.map +0 -1
- package/dist/spec/infrastructure/sql/frontEnd.js +0 -100
- package/dist/spec/infrastructure/sql/frontEnd.js.map +0 -1
- package/dist/spec/infrastructure/sql/index.d.ts +0 -4
- package/dist/spec/infrastructure/sql/index.d.ts.map +0 -1
- package/dist/spec/infrastructure/sql/index.js +0 -4
- package/dist/spec/infrastructure/sql/index.js.map +0 -1
- package/dist/spec/kernel/diagnostic.d.ts.map +0 -1
- package/dist/spec/kernel/diagnostic.js +0 -301
- package/dist/spec/kernel/diagnostic.js.map +0 -1
- package/dist/spec/kernel/index.d.ts +0 -8
- package/dist/spec/kernel/index.d.ts.map +0 -1
- package/dist/spec/kernel/index.js +0 -8
- package/dist/spec/kernel/index.js.map +0 -1
- package/dist/spec/usecase/EmitTypes.d.ts +0 -22
- package/dist/spec/usecase/EmitTypes.d.ts.map +0 -1
- package/dist/spec/usecase/EmitTypes.js +0 -182
- package/dist/spec/usecase/EmitTypes.js.map +0 -1
- package/dist/spec/usecase/ValidateManifestsUseCase.d.ts +0 -8
- package/dist/spec/usecase/ValidateManifestsUseCase.d.ts.map +0 -1
- package/dist/spec/usecase/ValidateManifestsUseCase.js +0 -101
- package/dist/spec/usecase/ValidateManifestsUseCase.js.map +0 -1
- package/dist/spec/usecase/dto/ValidateManifestsRequest.d.ts +0 -27
- package/dist/spec/usecase/dto/ValidateManifestsRequest.d.ts.map +0 -1
- package/dist/spec/usecase/dto/ValidateManifestsRequest.js +0 -2
- package/dist/spec/usecase/dto/ValidateManifestsRequest.js.map +0 -1
- package/dist/spec/usecase/dto/ValidateManifestsResponse.d.ts +0 -14
- package/dist/spec/usecase/dto/ValidateManifestsResponse.d.ts.map +0 -1
- package/dist/spec/usecase/dto/ValidateManifestsResponse.js +0 -2
- package/dist/spec/usecase/dto/ValidateManifestsResponse.js.map +0 -1
- package/dist/spec/usecase/dto/index.d.ts +0 -3
- package/dist/spec/usecase/dto/index.d.ts.map +0 -1
- package/dist/spec/usecase/dto/index.js +0 -3
- package/dist/spec/usecase/dto/index.js.map +0 -1
- package/dist/spec/usecase/index.d.ts +0 -10
- package/dist/spec/usecase/index.d.ts.map +0 -1
- package/dist/spec/usecase/index.js +0 -10
- package/dist/spec/usecase/index.js.map +0 -1
- package/dist/testing/cases/before-hook.d.ts +0 -4
- package/dist/testing/cases/before-hook.d.ts.map +0 -1
- package/dist/testing/cases/before-hook.js +0 -71
- package/dist/testing/cases/before-hook.js.map +0 -1
- package/dist/testing/cases/corpus.d.ts +0 -14
- package/dist/testing/cases/corpus.d.ts.map +0 -1
- package/dist/testing/cases/corpus.js +0 -93
- package/dist/testing/cases/corpus.js.map +0 -1
- package/dist/testing/cases/policy.d.ts +0 -87
- package/dist/testing/cases/policy.d.ts.map +0 -1
- package/dist/testing/cases/policy.js +0 -143
- package/dist/testing/cases/policy.js.map +0 -1
- package/dist/testing/cases/printer.d.ts +0 -4
- package/dist/testing/cases/printer.d.ts.map +0 -1
- package/dist/testing/cases/printer.js +0 -34
- package/dist/testing/cases/printer.js.map +0 -1
- package/dist/testing/cases/report-view.d.ts +0 -5
- package/dist/testing/cases/report-view.d.ts.map +0 -1
- package/dist/testing/cases/report-view.js +0 -51
- package/dist/testing/cases/report-view.js.map +0 -1
- package/dist/testing/cases/requisition.d.ts +0 -4
- package/dist/testing/cases/requisition.d.ts.map +0 -1
- package/dist/testing/cases/requisition.js +0 -38
- package/dist/testing/cases/requisition.js.map +0 -1
- package/dist/testing/cases/search-places.d.ts +0 -4
- package/dist/testing/cases/search-places.d.ts.map +0 -1
- package/dist/testing/cases/search-places.js +0 -60
- package/dist/testing/cases/search-places.js.map +0 -1
- package/dist/testing/cases/stock.d.ts +0 -4
- package/dist/testing/cases/stock.d.ts.map +0 -1
- package/dist/testing/cases/stock.js +0 -35
- package/dist/testing/cases/stock.js.map +0 -1
- package/dist/testing/cases/store.d.ts +0 -4
- package/dist/testing/cases/store.d.ts.map +0 -1
- package/dist/testing/cases/store.js +0 -100
- package/dist/testing/cases/store.js.map +0 -1
- package/dist/testing/harness.d.ts +0 -94
- package/dist/testing/harness.d.ts.map +0 -1
- package/dist/testing/harness.js +0 -168
- package/dist/testing/harness.js.map +0 -1
- package/dist/testing/index.d.ts.map +0 -1
- package/dist/testing/index.js.map +0 -1
- package/dist/testing/report.d.ts +0 -15
- package/dist/testing/report.d.ts.map +0 -1
- package/dist/testing/report.js +0 -22
- package/dist/testing/report.js.map +0 -1
- package/dist/web/createRestSurface.d.ts +0 -7
- package/dist/web/createRestSurface.d.ts.map +0 -1
- package/dist/web/createRestSurface.js +0 -41
- package/dist/web/createRestSurface.js.map +0 -1
- package/dist/web/index.d.ts +0 -2
- package/dist/web/index.d.ts.map +0 -1
- package/dist/web/index.js +0 -2
- package/dist/web/index.js.map +0 -1
- package/docs/adr/0001-four-atom-manifest-model.md +0 -440
- package/docs/adr/0002-closed-enums-for-bindings.md +0 -253
- package/docs/adr/0007-ai-as-primary-author.md +0 -473
- package/docs/adr/0008-structured-diagnostic-shape.md +0 -338
- package/docs/adr/0009-consumer-supplied-manifests.md +0 -149
- package/docs/adr/0010-locale-and-translates.md +0 -453
- package/docs/adr/0011-adapter-port-spec.md +0 -281
- package/docs/adr/0012-views-as-public-rest.md +0 -161
- package/docs/adr/0013-agent-provisioned-consumer-projects.md +0 -154
- package/docs/adr/0014-auth-better-auth-and-multi-tenant-mcp.md +0 -939
- package/docs/adr/0016-site-semantic-layer.md +0 -70
- package/docs/adr/0017-media-multi-variant-agent-side-optimization.md +0 -181
- package/docs/adr/0018-core-starters-repository-boundary.md +0 -179
- package/docs/adr/0019-sealed-manifest-runtime-pipeline.md +0 -244
- package/docs/adr/0020-builtin-handler-contracts-and-matched-upsert.md +0 -199
- package/docs/adr/0021-retire-starter-scaffolding.md +0 -30
- package/docs/adr/0022-caller-observed-version-occ.md +0 -212
- package/docs/adr/0023-port-failure-contract.md +0 -69
- package/docs/adr/0024-manifest-native-schema-tables.md +0 -264
- package/docs/adr/0025-reserved-native-columns-and-published-only-public-views.md +0 -105
- package/docs/adr/0026-progressive-generate.md +0 -36
- package/docs/adr/0027-scheduled-procedure-triggers.md +0 -31
- package/docs/adr/0028-schema-ttl-expiry.md +0 -33
- package/docs/adr/0029-mcp-apps-interaction-contracts.md +0 -324
- package/docs/adr/0030-store.md +0 -40
- package/docs/adr/0031-host-cloud-core-contract.md +0 -102
- package/docs/adr/0032-store-centric-core-and-service-contract.md +0 -384
- package/docs/adr/0033-storage-converges-to-the-plan.md +0 -92
- package/docs/adr/0034-store-is-authored-as-sql.md +0 -192
- package/docs/adr/0035-sql-dialects.md +0 -154
- package/docs/adr/0036-host-and-dialect.md +0 -65
- package/docs/adr/0037-postgresql-is-the-reference-dialect.md +0 -125
- package/docs/adr/0038-bun-native-host.md +0 -63
- package/docs/adr/0039-postgresql-is-native.md +0 -130
- package/docs/adr/README.md +0 -98
- package/docs/adr/adr-lite-1376-admin-extensions.md +0 -330
- package/docs/adr/adr-lite-803-request-diagnostics.md +0 -38
- package/docs/adr/adr-lite-808-route-readiness.md +0 -47
- package/docs/adr/adr-lite-809-bounded-public-content.md +0 -71
- package/docs/adr/adr-lite-812-native-parity.md +0 -150
- package/docs/adr/adr-lite-823-home-statistics.md +0 -64
- package/docs/adr/adr-lite-842-mcp-authoring.md +0 -30
- package/docs/adr/adr-lite-845-frontend-client.md +0 -38
- package/docs/adr/adr-lite-861-admin-webmcp.md +0 -48
- package/docs/adr/adr-lite-909-admin-ui-kit.md +0 -37
- package/docs/examples/commerce-inventory.md +0 -498
- package/docs/examples/commerce.md +0 -254
- package/docs/examples/guarded-api.md +0 -238
- package/docs/examples/intake-hooks.md +0 -237
- package/docs/examples/intake.md +0 -127
- package/docs/examples/legal-documents.md +0 -218
- package/docs/examples/procurement.md +0 -226
- package/docs/examples/publication.md +0 -211
- package/docs/examples/reference-service/.mantle/generated/mantle.ts +0 -174
- package/docs/examples/reference-service/.mantle/generated/plan.json +0 -1936
- package/docs/examples/reference-service/README.md +0 -33
- package/docs/examples/reference-service/manifests/catalog.yaml +0 -103
- package/docs/examples/reference-service/manifests/orders.yaml +0 -120
- package/docs/examples/reference-service/mantle.config.json +0 -1
- package/docs/examples/reference-service/package.json +0 -27
- package/docs/examples/reference-service/smoke.mjs +0 -160
- package/docs/examples/reference-service/src/handlers.ts +0 -36
- package/docs/examples/reference-service/src/index.ts +0 -33
- package/docs/examples/reference-service/src/service.ts +0 -78
- package/docs/examples/reference-service/wrangler.jsonc +0 -26
- package/docs/examples/reservation.md +0 -142
- package/docs/handbook/guides/admin-extensions.md +0 -191
- /package/docs/examples/{reference-service → app-shell}/.dev.vars.example +0 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/** Compile boundary checks into each operation; no schema enters the request bundle. */
|
|
2
|
+
import { INPUT_RULE_KEYWORDS, lookupLocalRef as lookup, rootRefChain } from "../build/compiler.js";
|
|
3
|
+
import { literal, q } from "../domain/entry.js";
|
|
4
|
+
import { publishingInput } from "./publishing.js";
|
|
5
|
+
import { equal } from "../kernel/validation.js";
|
|
6
|
+
const pointer = (key) => key.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
7
|
+
const supported = new Set([..."$defs $ref $schema $id type nullable properties required additionalProperties items enum const format pattern minLength maxLength minimum maximum exclusiveMinimum exclusiveMaximum multipleOf minItems maxItems title description default readOnly writeOnly examples deprecated x-mantle-ref x-mcp-hint".split(" "), ...INPUT_RULE_KEYWORDS]);
|
|
8
|
+
const shapes = "see docs/handbook/reference/surface.md";
|
|
9
|
+
// YAML .inf and .nan parse to numbers that JSON writes as null.
|
|
10
|
+
const finite = (value) => typeof value === "number" ? Number.isFinite(value) : !!value && typeof value === "object" ? Object.values(value).every(finite) : true;
|
|
11
|
+
const has = (key) => `Object.hasOwn(object,${q(key)})`;
|
|
12
|
+
const exactly = (value, keys) => !!value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).sort().join(" ") === keys;
|
|
13
|
+
/**
|
|
14
|
+
* An object schema's rules, each failing `when` (JavaScript on `object`) with its sentence at the missing field `key`, or the
|
|
15
|
+
* reason a rule has an unsupported shape.
|
|
16
|
+
*/
|
|
17
|
+
function rules(schema) {
|
|
18
|
+
const declared = (names) => Array.isArray(names) && names.length > 0 && names.every(name => typeof name === "string" && Object.hasOwn(schema.properties ?? {}, name));
|
|
19
|
+
const list = (names) => names.map(name => `'${name}'`).join(" and ");
|
|
20
|
+
const found = [], { dependentRequired: dependent, anyOf, if: condition, then, else: otherwise } = schema;
|
|
21
|
+
if (dependent !== undefined) {
|
|
22
|
+
if (!dependent || typeof dependent !== "object" || Array.isArray(dependent) || !declared(Object.keys(dependent)) || !Object.values(dependent).every(declared))
|
|
23
|
+
return `dependentRequired maps declared properties to lists of declared properties; ${shapes}.`;
|
|
24
|
+
for (const [key, names] of Object.entries(dependent))
|
|
25
|
+
for (const name of names)
|
|
26
|
+
found.push({ when: `${has(key)} && !${has(name)}`, key: name, message: `'${name}' is required when '${key}' is present.` });
|
|
27
|
+
}
|
|
28
|
+
if (anyOf !== undefined) {
|
|
29
|
+
if (!Array.isArray(anyOf) || !anyOf.length || !anyOf.every(branch => exactly(branch, "required") && declared(branch.required)))
|
|
30
|
+
return `anyOf is supported only as branches of exactly { required: [declared properties] }; ${shapes}.`;
|
|
31
|
+
const branches = anyOf.map(branch => branch.required);
|
|
32
|
+
found.push({ when: `!(${branches.map(names => names.map(has).join(" && ")).join(" || ")})`, message: `At least one of ${branches.map(names => names.length > 1 ? `(${list(names)})` : list(names)).join(", ")} is required.` });
|
|
33
|
+
}
|
|
34
|
+
if (condition !== undefined || then !== undefined || otherwise !== undefined) {
|
|
35
|
+
const [key] = exactly(condition, "properties required") ? Object.keys(condition.properties) : [];
|
|
36
|
+
const value = key === undefined ? undefined : condition.properties[key];
|
|
37
|
+
// Without required: [key], an absent key satisfies `if`.
|
|
38
|
+
if (key === undefined || !exactly(condition.properties, key) || !exactly(value, "const") || !(["string", "boolean"].includes(typeof value.const) || Number.isFinite(value.const) || value.const === null) || q(condition.required) !== q([key]) || !declared([key]))
|
|
39
|
+
return `if is supported only as exactly { properties: { <field>: { const: <string, finite number, boolean or null> } }, required: [<field>] }, so an absent field does not satisfy it; ${shapes}.`;
|
|
40
|
+
if (then === undefined && otherwise === undefined || [then, otherwise].some(branch => branch !== undefined && !(exactly(branch, "required") && declared(branch.required))))
|
|
41
|
+
return `then and else are supported only as exactly { required: [declared properties] } after an if; ${shapes}.`;
|
|
42
|
+
const met = `${has(key)} && object[${q(key)}] === ${q(value.const)}`;
|
|
43
|
+
for (const name of then?.required ?? [])
|
|
44
|
+
found.push({ when: `${met} && !${has(name)}`, key: name, message: `'${name}' is required when '${key}' is ${q(value.const)}.` });
|
|
45
|
+
for (const name of otherwise?.required ?? [])
|
|
46
|
+
found.push({ when: `!(${met}) && !${has(name)}`, key: name, message: `'${name}' is required unless '${key}' is ${q(value.const)}.` });
|
|
47
|
+
}
|
|
48
|
+
return found;
|
|
49
|
+
}
|
|
50
|
+
/** Whether an input schema accepts `{}`: a list View is read with no input, so web indexes need this. */
|
|
51
|
+
export function acceptsEmpty(input) {
|
|
52
|
+
if (input === undefined)
|
|
53
|
+
return true;
|
|
54
|
+
// Validation applies a root `$ref`'s target too, so each schema along the chain must accept `{}`; an unresolved or cyclic chain does not.
|
|
55
|
+
// dependentRequired needs a present key; an if needs its field, so `{}` meets only an else. An enum or const must admit `{}`.
|
|
56
|
+
return rootRefChain(input)?.every(schema => !schema.required?.length && schema.anyOf === undefined && !schema.else?.required?.length
|
|
57
|
+
&& (schema.enum === undefined || schema.enum.some(option => equal({}, option))) && (schema.const === undefined || equal({}, schema.const)) && (schema.type === undefined || [schema.type].flat().includes("object"))) ?? false;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* An input schema as an AI tool catalogue advertises it: some model APIs refuse rules (a root `anyOf`, `if`), so each rule leaves
|
|
61
|
+
* the schema and becomes a sentence of the description.
|
|
62
|
+
*/
|
|
63
|
+
export function advertised(input, description) {
|
|
64
|
+
if (!input)
|
|
65
|
+
return { inputSchema: input, description };
|
|
66
|
+
const sentences = [], copy = JSON.parse(q(input));
|
|
67
|
+
const strip = (node, at) => {
|
|
68
|
+
if (!node || typeof node !== "object")
|
|
69
|
+
return;
|
|
70
|
+
const schema = node;
|
|
71
|
+
// An MCP View tool keeps each rule set of its root `$ref` chain as an `allOf` branch over the merged properties.
|
|
72
|
+
const branches = Array.isArray(schema.allOf) ? schema.allOf : [];
|
|
73
|
+
for (const branch of [schema, ...branches.map(branch => ({ ...branch, properties: schema.properties }))]) {
|
|
74
|
+
const found = rules(branch);
|
|
75
|
+
if (typeof found !== "string")
|
|
76
|
+
for (const rule of found)
|
|
77
|
+
sentences.push(at ? `In '${at}': ${rule.message}` : rule.message);
|
|
78
|
+
}
|
|
79
|
+
if (branches.length && branches.every(branch => Object.keys(branch).every(key => INPUT_RULE_KEYWORDS.includes(key))))
|
|
80
|
+
delete schema.allOf;
|
|
81
|
+
for (const keyword of INPUT_RULE_KEYWORDS)
|
|
82
|
+
delete schema[keyword];
|
|
83
|
+
for (const [key, child] of Object.entries((schema.properties ?? {})))
|
|
84
|
+
strip(child, `${at}/${key}`);
|
|
85
|
+
for (const [key, child] of Object.entries((schema.$defs ?? {})))
|
|
86
|
+
strip(child, `#/$defs/${key}`);
|
|
87
|
+
strip(schema.items, `${at}/*`);
|
|
88
|
+
strip(schema.additionalProperties, `${at}/*`);
|
|
89
|
+
};
|
|
90
|
+
strip(copy, "");
|
|
91
|
+
if (!sentences.length)
|
|
92
|
+
return { inputSchema: input, description };
|
|
93
|
+
const text = sentences.join(" ");
|
|
94
|
+
return { inputSchema: copy, description: typeof description === "string" ? `${description} ${text}` : Object.fromEntries(Object.entries(description).map(([locale, value]) => [locale, `${value} ${text}`])) };
|
|
95
|
+
}
|
|
96
|
+
const bounds = [
|
|
97
|
+
["string", "[...value].length", { minLength: "<", maxLength: ">" }],
|
|
98
|
+
["number", "value", { minimum: "<", maximum: ">", exclusiveMinimum: "<=", exclusiveMaximum: ">=" }],
|
|
99
|
+
["array", "value.length", { minItems: "<", maxItems: ">" }],
|
|
100
|
+
];
|
|
101
|
+
const condition = (type) => ({ null: "value === null", array: "Array.isArray(value)", object: 'typeof value === "object" && value !== null && !Array.isArray(value)', integer: 'typeof value === "number" && Number.isSafeInteger(value)', number: 'typeof value === "number" && Number.isFinite(value)' })[type] ?? `typeof value === ${q(type)}`;
|
|
102
|
+
const typeCheck = (types) => `if (!(${types.map(type => `(${condition(type)})`).join(" || ")})) fail(path, ${q(`Expected ${types.join(" or ")}.`)});`;
|
|
103
|
+
export function emitValidation(plan, refuse = (path, message) => { throw Error(`${path}: ${message}`); }) {
|
|
104
|
+
const files = {};
|
|
105
|
+
for (const [kind, operations] of [["views", plan.views], ["procedures", plan.procedures]])
|
|
106
|
+
for (const [name, operation] of Object.entries(operations)) {
|
|
107
|
+
const root = operation.input ?? { type: "object", additionalProperties: false };
|
|
108
|
+
const base = `${kind}/${name}/input`, file = `validation/${kind}/${encodeURIComponent(name)}.ts`;
|
|
109
|
+
const json = q(root);
|
|
110
|
+
if (kind === "procedures" && json === q(publishingInput)) {
|
|
111
|
+
files[file] = `import { transition } from "@aotter/mantle/validation";\nexport const validate = (raw: unknown) => transition(${q(base)}, raw);\n`;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
// Only a local `$ref`, or more than 100 nested objects and arrays, can reach the nesting limit: only then is `depth` passed.
|
|
115
|
+
const recursive = json.includes('"$ref"') || json.split(/[[{]/).length > 101, depth = recursive ? ",depth+1" : "";
|
|
116
|
+
// Identical bodies share one function.
|
|
117
|
+
const nodes = new Map(), bodies = new Map(), functions = [], formats = new Set(), patterns = new Map();
|
|
118
|
+
let equality = false;
|
|
119
|
+
const resolve = (ref) => {
|
|
120
|
+
const found = lookup(root, ref);
|
|
121
|
+
if (!found)
|
|
122
|
+
refuse(base, "Input ref must be a valid local JSON pointer.");
|
|
123
|
+
return found ?? {};
|
|
124
|
+
};
|
|
125
|
+
const emit = (schema) => {
|
|
126
|
+
if (nodes.has(schema))
|
|
127
|
+
return nodes.get(schema);
|
|
128
|
+
const named = `check${nodes.size}`;
|
|
129
|
+
nodes.set(schema, named);
|
|
130
|
+
for (const key of Object.keys(schema))
|
|
131
|
+
if (!supported.has(key))
|
|
132
|
+
refuse(base, `Generated input validation does not support '${key}'.`);
|
|
133
|
+
const lines = recursive ? ['if (depth > 100) fail(path, "Input nesting exceeds 100 levels.");'] : [];
|
|
134
|
+
const check = (invalid, message) => lines.push(`if (${invalid}) fail(path, ${q(message)});`);
|
|
135
|
+
if (schema.nullable)
|
|
136
|
+
lines.push("if (value === null) return;");
|
|
137
|
+
if (schema.$ref !== undefined)
|
|
138
|
+
lines.push(`${emit(resolve(schema.$ref))}(value,path${depth});`);
|
|
139
|
+
const types = [schema.type].flat().filter((type) => !!type);
|
|
140
|
+
for (const type of types)
|
|
141
|
+
if (!"null array object integer number string boolean".split(" ").includes(type))
|
|
142
|
+
refuse(base, `Unsupported input type '${type}'.`);
|
|
143
|
+
if (types.length)
|
|
144
|
+
lines.push(typeCheck(types));
|
|
145
|
+
// After a single type check `fail` (never) has narrowed `value`: that type's guard is implied.
|
|
146
|
+
const only = types.length === 1 ? types[0] : undefined;
|
|
147
|
+
const guard = (type, test = `(${condition(type)})`) => only === type || type === "number" && only === "integer" ? "" : test + " && ";
|
|
148
|
+
if (schema.enum) {
|
|
149
|
+
if (!finite(schema.enum))
|
|
150
|
+
refuse(base, "Input enum numbers must be finite; JSON has no Infinity or NaN.");
|
|
151
|
+
equality = true;
|
|
152
|
+
check(`!${literal(schema.enum)}.some(option=>equal(value,option))`, "Value is not in enum.");
|
|
153
|
+
}
|
|
154
|
+
if (schema.const !== undefined) {
|
|
155
|
+
if (!finite(schema.const))
|
|
156
|
+
refuse(base, "Input const numbers must be finite; JSON has no Infinity or NaN.");
|
|
157
|
+
equality = true;
|
|
158
|
+
check(`!equal(value,${literal(schema.const)})`, "Value violates const.");
|
|
159
|
+
}
|
|
160
|
+
for (const [type, measure, keywords] of bounds)
|
|
161
|
+
for (const [key, operator] of Object.entries(keywords))
|
|
162
|
+
if (schema[key] !== undefined)
|
|
163
|
+
check(`${guard(type)}${measure} ${operator} ${schema[key]}`, `Value violates ${key}.`);
|
|
164
|
+
if (schema.multipleOf !== undefined)
|
|
165
|
+
check(`${guard("number", 'typeof value === "number"')}!(Math.abs(value / ${schema.multipleOf} - Math.round(value / ${schema.multipleOf})) < 1e-9)`, "Number violates multipleOf.");
|
|
166
|
+
if (schema.pattern !== undefined) {
|
|
167
|
+
try {
|
|
168
|
+
new RegExp(schema.pattern);
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
refuse(base, "Input pattern is not a valid regular expression.");
|
|
172
|
+
}
|
|
173
|
+
if (!patterns.has(schema.pattern))
|
|
174
|
+
patterns.set(schema.pattern, `pattern${patterns.size}`);
|
|
175
|
+
check(`${guard("string", 'typeof value === "string"')}!${patterns.get(schema.pattern)}.test(value)`, "String does not match pattern.");
|
|
176
|
+
}
|
|
177
|
+
if (schema.format) {
|
|
178
|
+
if (schema.format === "email")
|
|
179
|
+
check(`${guard("string", 'typeof value === "string"')}!/^[^\\s@]+@[^\\s@]+$/u.test(value)`, "Expected an email with one @, non-empty local and domain parts, and no whitespace.");
|
|
180
|
+
else if (schema.format === "uri")
|
|
181
|
+
lines.push(`${only === "string" ? "" : 'if (typeof value === "string") '}{ let url: URL | undefined; try { url = new URL(value); } catch {} if (url?.protocol !== "http:" && url?.protocol !== "https:") fail(path, "Expected an absolute http or https URL."); }`);
|
|
182
|
+
else if (!["date", "date-time"].includes(schema.format))
|
|
183
|
+
refuse(base, `Generated input validation does not support format '${schema.format}'; ${shapes} for the supported formats.`);
|
|
184
|
+
else {
|
|
185
|
+
const scalar = schema.format === "date" ? "encodeDate" : "encodeTimestamptz";
|
|
186
|
+
formats.add(scalar);
|
|
187
|
+
lines.push(`${only === "string" ? "" : 'if (typeof value === "string") '}try { ${scalar}(value); } catch { fail(path, ${q(`Expected a valid ${schema.format}.`)}); }`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (schema.items)
|
|
191
|
+
lines.push(`${only === "array" ? "" : "if (Array.isArray(value)) "}for (let i=0;i<value.length;i++) ${emit(schema.items)}(value[i],path+"/"+i${depth});`);
|
|
192
|
+
// Several keys that need no JSON-pointer escaping are checked by one loop, in the same order.
|
|
193
|
+
const required = schema.required ?? [], checks = Object.entries(schema.properties ?? {}).map(([key, child]) => [key, emit(child)]);
|
|
194
|
+
const loop = (keys) => keys.length > 1 && keys.every(key => pointer(key) === key);
|
|
195
|
+
const object = loop(required) ? [`for (const key of ${q(required)}) if (!Object.hasOwn(object,key)) fail(path+"/"+key,"Required field is missing.");`] : required.map(key => `if (!Object.hasOwn(object,${q(key)})) fail(path+${q("/" + pointer(key))},"Required field is missing.");`);
|
|
196
|
+
if (loop(checks.map(([key]) => key)))
|
|
197
|
+
object.push(`for (const [key,check] of [${checks.map(([key, fn]) => `[${q(key)},${fn}]`)}] as const) if (Object.hasOwn(object,key)) check(object[key],path+"/"+key${depth});`);
|
|
198
|
+
else
|
|
199
|
+
for (const [key, fn] of checks)
|
|
200
|
+
object.push(`if (Object.hasOwn(object,${q(key)})) ${fn}(object[${q(key)}],path+${q("/" + pointer(key))}${depth});`);
|
|
201
|
+
if (schema.additionalProperties === false || typeof schema.additionalProperties === "object")
|
|
202
|
+
object.push(`for (const key of Object.keys(object)) if (!(${q(Object.keys(schema.properties ?? {}))} as readonly string[]).includes(key)) { const childPath = path+"/"+key.replace(/~/g,"~0").replace(/\\//g,"~1"); ${schema.additionalProperties === false ? 'fail(childPath,"Unknown field.");' : `${emit(schema.additionalProperties)}(object[key],childPath${depth});`} }`);
|
|
203
|
+
const checked = rules(schema);
|
|
204
|
+
if (typeof checked === "string")
|
|
205
|
+
refuse(base, checked);
|
|
206
|
+
else
|
|
207
|
+
for (const rule of checked)
|
|
208
|
+
object.push(`if (${rule.when}) fail(path${rule.key === undefined ? "" : `+${q("/" + pointer(rule.key))}`}, ${q(rule.message)});`);
|
|
209
|
+
if (object.length)
|
|
210
|
+
lines.push(`${only === "object" ? "" : `if (${condition("object")}) `}{ const object = value as Record<string,unknown>;\n${object.join("\n")}\n}`);
|
|
211
|
+
const body = lines.join("\n");
|
|
212
|
+
// Without recursion nothing calls a check before its body is complete, so an identical body's function serves it.
|
|
213
|
+
const fn = recursive ? named : bodies.get(body) ?? named;
|
|
214
|
+
if (fn === named) {
|
|
215
|
+
bodies.set(body, fn);
|
|
216
|
+
functions.push(`function ${fn}(value:unknown,path:string${recursive ? ",depth:number" : ""}):void {\n${body}\n}`);
|
|
217
|
+
}
|
|
218
|
+
nodes.set(schema, fn);
|
|
219
|
+
return fn;
|
|
220
|
+
};
|
|
221
|
+
const validate = emit(root);
|
|
222
|
+
const fields = kind === "views" ? Object.entries(root.properties ?? {}).map(([key, schema]) => {
|
|
223
|
+
const type = [schema.type].flat().find(type => type && type !== "null");
|
|
224
|
+
return type === "boolean" || type === "integer" || type === "number" ? [key, type] : [key];
|
|
225
|
+
}) : undefined;
|
|
226
|
+
const helpers = [...(functions.length ? ["fail"] : []), ...(equality ? ["equal"] : []), ...(fields ? ["query as read"] : [])];
|
|
227
|
+
const code = `${helpers.length ? `import { ${helpers.join(", ")} } from "@aotter/mantle/validation";\n` : ""}${formats.size ? `import { ${[...formats].join(", ")} } from "@aotter/mantle/scalars";\n` : ""}${[...patterns].map(([pattern, name]) => `const ${name} = new RegExp(${q(pattern)});\n`).join("")}${functions.join("\n")}
|
|
228
|
+
export function validate(raw:unknown):Record<string,unknown> { ${validate}(raw,${q(base)}${recursive ? ",0" : ""}); return raw as Record<string,unknown>; }
|
|
229
|
+
${fields ? `export const query = (params:URLSearchParams) => read(params, validate, ${q(`${kind}/${name}`)}, ${q(fields)});\n` : ""}`;
|
|
230
|
+
files[file] = code;
|
|
231
|
+
}
|
|
232
|
+
return files;
|
|
233
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { databaseImport, q } from "../domain/entry.js";
|
|
2
|
+
import { authLines, conversions } from "../domain/input.js";
|
|
3
|
+
import { acceptsEmpty } from "./validation.js";
|
|
4
|
+
export function emitWeb(plan, lowered, target) {
|
|
5
|
+
const views = Object.entries(plan.views).filter(([, v]) => v.surface === "public");
|
|
6
|
+
const table = views.map(([name, v], i) => {
|
|
7
|
+
const binds = lowered.views[name]?.public?.binds ?? [], convert = conversions(v.input?.properties, binds, target);
|
|
8
|
+
const booleans = Object.keys(v.input?.properties ?? {}).filter(field => binds.some(b => b.k === "input" && String(b.name).toLowerCase() === field.toLowerCase() && String(b.type) === "bool"));
|
|
9
|
+
const check = authLines(v.requires, `views/${name}`, binds, !target.endsWith("postgres"));
|
|
10
|
+
return `[${q(name)}, { ${check.length ? `check: (caller) => {${check.join("")}}, ` : ""}${acceptsEmpty(v.input) ? "" : "unlisted: true, "}query: input${i}, page: async (db, caller, input, paging) => (await import("./paged/views/${encodeURIComponent(name)}.js")).default(db, caller, input, paging)${convert ? `, convert: ${convert}` : ""}${booleans.length ? `, booleans: ${q(booleans)}` : ""} }]`;
|
|
11
|
+
});
|
|
12
|
+
return { "web.ts": [
|
|
13
|
+
...(plan.access ? ['import { userBinds } from "@aotter/mantle/user-fields";'] : []),
|
|
14
|
+
...([...Object.values(plan.views)].some(v => v.requires?.auth?.all.length) ? ['import { deny, isAdmin, isUser } from "@aotter/mantle/contracts";'] : []),
|
|
15
|
+
...views.flatMap(([n], i) => [`import { query as input${i} } from "./validation/views/${encodeURIComponent(n)}.js";`, `import type { Row as Row${i} } from "./views/${encodeURIComponent(n)}.js";`]),
|
|
16
|
+
'import { web as site, type Options, type Page } from "@aotter/mantle/web";',
|
|
17
|
+
databaseImport(target),
|
|
18
|
+
`type App = { Rows: {${views.map(([n], i) => `${q(n)}:Row${i}`).join(";")}}; Inputs: {${views.map(([n, v]) => `${q(n)}:${Object.keys(v.input?.properties ?? {}).map(k => q(k)).join(" | ") || "never"}`).join(";")}}; List: ${views.filter(([, v]) => acceptsEmpty(v.input)).map(([n]) => q(n)).join(" | ") || "never"} };`,
|
|
19
|
+
"export function web<const P extends Record<string, Page<App>>, E = unknown>(options: Options<App, Database, P, E>) {",
|
|
20
|
+
` return site<Database, E>(${plan.access ? `{...options, fields: ${q(plan.access.userFields)}, accessTargets: () => import("./access-targets.js").then(m => m.targets)}` : '{...options, accessTargets: () => import("./access-targets.js").then(m => m.targets)}'}, [${table.join(", ")}]);`,
|
|
21
|
+
"}"
|
|
22
|
+
].join("\n") + "\n" };
|
|
23
|
+
}
|
package/docs/examples/README.md
CHANGED
|
@@ -1,20 +1,35 @@
|
|
|
1
|
-
# Examples
|
|
1
|
+
# Examples
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
your project's `manifests/`; none is a template to copy wholesale.
|
|
3
|
+
Start from the **app shell**, then copy the example closest to your app on top of it. Each example shows a few
|
|
4
|
+
capabilities the others do not; combine them for anything else.
|
|
6
5
|
|
|
7
|
-
| Example |
|
|
8
|
-
|
|
9
|
-
| [
|
|
10
|
-
| [
|
|
11
|
-
| [
|
|
12
|
-
| [
|
|
13
|
-
| [
|
|
14
|
-
| [Legal documents and consent](./legal-documents.md) | Immutable revisions, and an acceptance written only for a published revision. | none |
|
|
15
|
-
| [Procurement approvals](./procurement.md) | Members see their own rows through `auth.uid()`; staff review with an optimistic lock. | none |
|
|
16
|
-
| [Commerce catalog and orders](./commerce.md) | A published catalog, guest orders and a locked staff review. | none |
|
|
17
|
-
| [Commerce inventory](./commerce-inventory.md) | Server-side pricing, atomic stock reservation with `checks` and locks, a scheduled expiry and a verified payment callback. | 3 handlers |
|
|
18
|
-
| [Guarded API access](./guarded-api.md) | API keys through a custom `CallerResolver`, scopes and a live entitlement guard. | 2 handlers |
|
|
6
|
+
| Example | Shows |
|
|
7
|
+
|---|---|
|
|
8
|
+
| [App shell](./app-shell/README.md) | Better Auth (email OTP, `admin` + `user`), one Worker fetch, Admin, MCP, REST, local acceptance kit. No business manifests. |
|
|
9
|
+
| [Recipes](./recipes/README.md) | Publishing (draft → publish), translations, visitor pages with SEO, JSON-LD, `llms.txt`, Markdown and hreflang alternates, R2 media. |
|
|
10
|
+
| [Club events](./club-events/README.md) | Members who see and change only their own rows, no duplicates, capacity that never oversells, a handler that checks before writing, a member MCP tool, members-only sign-up. |
|
|
11
|
+
| [Purchasing](./purchasing/README.md) | An internal workflow: guarded status transitions, admin-only approval (Admin and admin MCP), optimistic concurrency, several writes in one transaction, an external API with a signed callback, email and cron. |
|
|
12
|
+
| [Generated website](./generated-web/README.md) | The smallest public site: list and detail pages, REST, `llms.txt`, sitemap, Markdown alternates. |
|
|
19
13
|
|
|
14
|
+
## Combining
|
|
15
|
+
|
|
16
|
+
| You need | Take |
|
|
17
|
+
|---|---|
|
|
18
|
+
| Stock that never oversells (orders, tickets, bookings) | club-events' capacity: a Schema `checks` constraint plus the decrement in the same program |
|
|
19
|
+
| Employees or customers who see only their own records | club-events' `restrict: { <schema>: "author_id = auth.uid()" }` |
|
|
20
|
+
| An approval step, or any state machine | purchasing's guarded `UPDATE ... WHERE requestStatus = ...` Procedures |
|
|
21
|
+
| A third-party API that answers later (webhooks, callbacks) | purchasing's `src/routes.ts`: verify the raw request, then call a Procedure |
|
|
22
|
+
| Public, multilingual, search- and AI-friendly pages | recipes' `src/routes.ts` |
|
|
23
|
+
| Invite-only or members-only sign-up | club-events' `members` allowlist + `src/signup.ts` |
|
|
24
|
+
| Notifications and reminders | purchasing's `EmailSender` call and `src/schedule.ts` |
|
|
25
|
+
|
|
26
|
+
When you copy an example only for one of its patterns, delete what your app does not need. Copying club-events, for
|
|
27
|
+
example, also brings its `members` allowlist and `src/signup.ts` (members-only sign-up); remove both, or restore the
|
|
28
|
+
shell's allow-all `src/signup.ts`, unless sign-up should be invite-only. Purchasing brings its supplier callback
|
|
29
|
+
(`src/routes.ts`, `src/supplier.ts`), email (`src/notify.ts`), cron (`src/schedule.ts` and `triggers.crons`) and its
|
|
30
|
+
`wrangler.jsonc` secrets. `pnpm generate` and `tsc` point at leftovers that reference removed Schemas.
|
|
31
|
+
|
|
32
|
+
Every example uses two roles: `admin` (the admin layer) and `user`.
|
|
33
|
+
|
|
34
|
+
[Reference service](https://github.com/aotter/mantle/tree/v0.2.0-alpha.8/docs/examples/reference-service) is the release smoke test for packed packages, not a starting point. Its source lives in the tagged repository; it is not included in the npm docs.
|
|
20
35
|
Projects on 0.1.x move with [the upgrade guide](../upgrade-0.1-to-0.2.md).
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# App shell
|
|
2
|
+
|
|
3
|
+
The wiring every Mantle Cloudflare app needs, ready to copy: Better Auth (email OTP, admin + user roles),
|
|
4
|
+
one Worker fetch (auth routes → your routes → Admin → MCP → generated REST), the Admin console assets, and a
|
|
5
|
+
local acceptance kit. It has no business manifests: add your own, or copy one of the examples on top of it.
|
|
6
|
+
|
|
7
|
+
## Start an app
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
cp -R node_modules/@aotter/mantle/docs/examples/app-shell/. my-app/ # or from this repository
|
|
11
|
+
cp -R node_modules/@aotter/mantle/docs/examples/club-events/. my-app/ # optional: an example on top
|
|
12
|
+
cd my-app
|
|
13
|
+
# package.json: pin the exact installed Mantle version for @aotter/mantle, -admin and -ui
|
|
14
|
+
pnpm install
|
|
15
|
+
pnpm generate # writes generated/ and lists any `handler: { ref }` to implement in src/handlers.ts
|
|
16
|
+
pnpm types && pnpm check
|
|
17
|
+
cp .dev.vars.example .dev.vars
|
|
18
|
+
pnpm db:init && pnpm db:seed # db:seed only when the example has seed.sql
|
|
19
|
+
pnpm dev # one-time codes print to this log
|
|
20
|
+
pnpm smoke # when the copied example has smoke.mjs
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
npm works too (`npm install`, `npm run …`). `package.json` pins `@better-auth/core` and `@better-auth/utils` even though
|
|
24
|
+
the shell does not import them: they are the exact versions the SDK's Better Auth peers require, and without them a fresh
|
|
25
|
+
install resolves newer ones (npm ERESOLVE, or a second Better Auth type tree under pnpm). Keep every Better Auth package
|
|
26
|
+
on one version.
|
|
27
|
+
|
|
28
|
+
## Files you edit
|
|
29
|
+
|
|
30
|
+
| File | What it is for |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `manifests/*.yaml` | Your Schemas, Views, Procedures and Triggers. `pnpm generate` compiles every file here. |
|
|
33
|
+
| `src/handlers.ts` | Code for each `handler: { ref }` Procedure. The Store it receives is bound to the same caller. |
|
|
34
|
+
| `src/routes.ts` | App-owned routes: visitor pages, SEO files, webhooks and callbacks. |
|
|
35
|
+
| `src/admin.tsx` | Optional, not shipped: the Admin entry (`defineAdmin(admin, { nav, pages, home, components, plugins, mcp })`) `mantle bundle` builds instead of the built-in one. Add it to group the sidebar or replace Admin regions; see docs/handbook/guides/native-admin.md. |
|
|
36
|
+
| `src/sign-in.ts` | Member sign-in page at `/sign-in` (email code, then back to `?return=`) and `signInRedirect(request)` for pages that need a signed-in visitor. Unstyled; delete it if the app has no member pages. |
|
|
37
|
+
| `src/schedule.ts` | Cron work. Add the cron to `wrangler.jsonc` `triggers.crons`. |
|
|
38
|
+
| `src/signup.ts` | `allowSignUp(env, email)`: who may create an account (allow-all by default). `auth.ts` calls it before Better Auth creates a user; `ADMIN_EMAIL` is always allowed. |
|
|
39
|
+
| `src/auth.ts` | Better Auth options. Two roles only: `admin` (the admin layer) and `user`. Replace the console OTP sender before deploying. |
|
|
40
|
+
| `smoke.mjs` | Your acceptance steps on `smoke-kit.mjs` (fresh local D1, OTP sign-in per user, REST/MCP/Admin calls). |
|
|
41
|
+
|
|
42
|
+
`src/service.ts` and `src/index.ts` rarely change. Delete the blocks marked `MCP / OAuth (optional)` in `auth.ts`
|
|
43
|
+
and `service.ts` if the app has no MCP.
|
|
44
|
+
|
|
45
|
+
Search for `AGENT:` to find what an app must fill in.
|
|
46
|
+
|
|
47
|
+
## Local testing notes
|
|
48
|
+
|
|
49
|
+
- Better Auth allows 3 OTP requests per minute per client IP. `smoke-kit.mjs` gives each user its own
|
|
50
|
+
`cf-connecting-ip`; when testing by hand, wait a minute or vary that header.
|
|
51
|
+
- `ADMIN_EMAIL`'s first verified sign-in becomes `admin` while no admin exists. The sign-in response may still show
|
|
52
|
+
the previous role; `/admin/api/me` shows the current one.
|
|
53
|
+
- Admin HTTP routes are listed in `docs/handbook/guides/native-admin.md`.
|
|
54
|
+
|
|
55
|
+
### MCP acceptance
|
|
56
|
+
|
|
57
|
+
Generation declares tools; the app owns whether and where a remote endpoint is mounted.
|
|
58
|
+
In your `smoke.mjs`, reuse the generated static tool names rather than maintaining a second list:
|
|
59
|
+
|
|
60
|
+
```js
|
|
61
|
+
import assert from "node:assert/strict";
|
|
62
|
+
import { assertMcpDiscovery, smoke } from "./smoke-kit.mjs";
|
|
63
|
+
import { developerConsole } from "./generated/admin-descriptors.ts";
|
|
64
|
+
|
|
65
|
+
await smoke(async ({ origin, owner, signIn, mcp }) => {
|
|
66
|
+
const cookie = await signIn(owner);
|
|
67
|
+
const tools = developerConsole.interfaces.callable.filter(tool => tool.surface === "admin");
|
|
68
|
+
await assertMcpDiscovery(`${origin}/mcp/admin`, { tools, headers: { cookie, origin } });
|
|
69
|
+
// Denial is a separate assertion, not successful discovery.
|
|
70
|
+
assert.equal((await mcp("/mcp/admin")).status, 401);
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Node 22.22+ can read this pure static
|
|
75
|
+
TypeScript descriptor directly; no generated request handlers are executed to derive expected names.
|
|
76
|
+
A TypeScript smoke scenario can instead import `tools` from generated `mcp.ts`.
|
|
77
|
+
Explicitly select the permitted subset if the app narrows authorization, and include any app-composed tools.
|
|
78
|
+
The assertion initializes MCP, forwards supplied identity/session headers, reads all tools/list pages,
|
|
79
|
+
and compares exact names without calling business tools. JSON/SSE protocol failures, missing routes,
|
|
80
|
+
unexpected/missing tools and repeated/excessive pagination fail; it never obtains credentials or mounts routes.
|
|
81
|
+
|
|
82
|
+
This local cookie test does not prove OAuth Bearer or an external client's connection. Test those separately
|
|
83
|
+
with supplied credentials and record their results. For each declared interface, the existing handoff/README/test
|
|
84
|
+
report must say verified (command, identity and result), intentionally not exposed, or deferred/unverified with a
|
|
85
|
+
reason. WebMCP-only applications remain valid; an interrupted preview must retain the remote acceptance item
|
|
86
|
+
as deferred rather than silently claiming completion.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mantle-app",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"generate": "mantle generate cloudflare-d1 generated manifests/*.yaml --auth src/auth.ts --entry src/index.ts --admin",
|
|
7
|
+
"types": "wrangler types --include-runtime=false",
|
|
8
|
+
"db:init": "wrangler d1 execute mantle-app --local --file generated/schema.sql",
|
|
9
|
+
"db:seed": "wrangler d1 execute mantle-app --local --file seed.sql",
|
|
10
|
+
"build": "mantle bundle src/index.ts dist",
|
|
11
|
+
"test": "node --test generated/admin-mcp-app.check.mjs",
|
|
12
|
+
"dev": "wrangler dev --local --ip 127.0.0.1 --port 8787",
|
|
13
|
+
"check": "mantle generate cloudflare-d1 generated manifests/*.yaml --auth src/auth.ts --entry src/index.ts --admin --check && wrangler types --include-runtime=false --check && tsc --noEmit",
|
|
14
|
+
"smoke": "node smoke.mjs"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@aotter/mantle": "0.2.0-alpha.8",
|
|
18
|
+
"@aotter/mantle-ui": "0.2.0-alpha.8",
|
|
19
|
+
"@better-auth/cimd": "1.7.7",
|
|
20
|
+
"@better-auth/core": "1.7.7",
|
|
21
|
+
"@better-auth/mcp": "1.7.7",
|
|
22
|
+
"@better-auth/oauth-provider": "1.7.7",
|
|
23
|
+
"@better-auth/utils": "0.4.2",
|
|
24
|
+
"@modelcontextprotocol/ext-apps": "2.0.0",
|
|
25
|
+
"@modelcontextprotocol/server": "2.2.0",
|
|
26
|
+
"better-auth": "1.7.7",
|
|
27
|
+
"@aotter/mantle-admin": "0.2.0-alpha.8",
|
|
28
|
+
"react": "19.3.0",
|
|
29
|
+
"react-dom": "19.3.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@cloudflare/workers-types": "5.20260904.1",
|
|
33
|
+
"@types/node": "^26",
|
|
34
|
+
"@types/react": "^19.3.0",
|
|
35
|
+
"playwright-core": "1.62.1",
|
|
36
|
+
"typescript": "^6.0.3",
|
|
37
|
+
"wrangler": "4.129.0"
|
|
38
|
+
},
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=22.22"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// Local acceptance kit: runs the app under `wrangler dev --local` on a fresh D1 and drives it over HTTP like a browser or agent.
|
|
2
|
+
// Usage in smoke.mjs:
|
|
3
|
+
// import { smoke } from "./smoke-kit.mjs";
|
|
4
|
+
// await smoke(async ({ call, mcp, signIn, owner, step }) => { const admin = await signIn(owner); ... step("..."); });
|
|
5
|
+
// Extra Worker variables: await smoke(scenario, { vars: { SUPPLIER_API_URL: "http://127.0.0.1:9999" } });
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
import { execFile, spawn, spawnSync } from "node:child_process";
|
|
8
|
+
import { existsSync, mkdtempSync, rmSync } from "node:fs";
|
|
9
|
+
import { tmpdir } from "node:os";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { promisify } from "node:util";
|
|
12
|
+
|
|
13
|
+
/** Read-only remote acceptance. Pass generated tools filtered for this surface and the supplied test identity. */
|
|
14
|
+
export async function assertMcpDiscovery(endpoint, { tools, headers = {} }) {
|
|
15
|
+
const expected = tools.map(tool => tool.name).sort();
|
|
16
|
+
assert.equal(new Set(expected).size, expected.length, "expected tools contain duplicate names");
|
|
17
|
+
const requestHeaders = new Headers(headers);
|
|
18
|
+
requestHeaders.set("content-type", "application/json");
|
|
19
|
+
requestHeaders.set("accept", "application/json, text/event-stream");
|
|
20
|
+
let id = 0;
|
|
21
|
+
const rpc = async (method, params, notification = false) => {
|
|
22
|
+
const message = { jsonrpc: "2.0", ...(notification ? {} : { id: ++id }), method, ...(params === undefined ? {} : { params }) };
|
|
23
|
+
const response = await fetch(endpoint, { method: "POST", headers: requestHeaders, redirect: "error", signal: AbortSignal.timeout(10_000), body: JSON.stringify(message) });
|
|
24
|
+
assert.equal(response.status, notification ? 202 : 200, `MCP ${method}: HTTP ${response.status}`);
|
|
25
|
+
if (notification) { await response.body?.cancel(); return; }
|
|
26
|
+
const text = await response.text(), type = response.headers.get("content-type") ?? "";
|
|
27
|
+
let replies;
|
|
28
|
+
if (type.includes("text/event-stream")) {
|
|
29
|
+
replies = text.replace(/\r\n/g, "\n").split("\n\n").map(event => event.split("\n").filter(line => line.startsWith("data:")).map(line => line.slice(5).trimStart()).join("\n")).filter(Boolean).map(data => JSON.parse(data));
|
|
30
|
+
} else {
|
|
31
|
+
assert.ok(type.includes("application/json"), `MCP ${method}: expected JSON or SSE`);
|
|
32
|
+
replies = [JSON.parse(text)];
|
|
33
|
+
}
|
|
34
|
+
const matches = replies.filter(reply => reply?.id === message.id);
|
|
35
|
+
assert.equal(matches.length, 1, `MCP ${method}: expected one response with the request id`);
|
|
36
|
+
const reply = matches[0];
|
|
37
|
+
assert.equal(reply.jsonrpc, "2.0", `MCP ${method}: invalid JSON-RPC version`);
|
|
38
|
+
assert.ok(!Object.hasOwn(reply, "error"), `MCP ${method}: returned a JSON-RPC error`);
|
|
39
|
+
assert.ok(reply.result && typeof reply.result === "object" && !Array.isArray(reply.result), `MCP ${method}: missing result object`);
|
|
40
|
+
const session = response.headers.get("mcp-session-id");
|
|
41
|
+
if (session) requestHeaders.set("mcp-session-id", session);
|
|
42
|
+
return reply.result;
|
|
43
|
+
};
|
|
44
|
+
const initialized = await rpc("initialize", { protocolVersion: "2025-11-25", capabilities: {}, clientInfo: { name: "mantle-smoke", version: "1" } });
|
|
45
|
+
assert.equal(initialized.protocolVersion, "2025-11-25", "MCP initialize: unsupported protocol version");
|
|
46
|
+
assert.ok(initialized.capabilities?.tools && typeof initialized.capabilities.tools === "object" && !Array.isArray(initialized.capabilities.tools), "MCP initialize: no tools capability");
|
|
47
|
+
assert.ok(typeof initialized.serverInfo?.name === "string" && typeof initialized.serverInfo?.version === "string", "MCP initialize: invalid serverInfo");
|
|
48
|
+
requestHeaders.set("mcp-protocol-version", initialized.protocolVersion);
|
|
49
|
+
await rpc("notifications/initialized", undefined, true);
|
|
50
|
+
const names = [], cursors = new Set();
|
|
51
|
+
let cursor;
|
|
52
|
+
do {
|
|
53
|
+
assert.ok(cursors.size < 100, "MCP tools/list: exceeded 100 pages");
|
|
54
|
+
const page = await rpc("tools/list", cursor === undefined ? {} : { cursor });
|
|
55
|
+
assert.ok(Array.isArray(page.tools) && page.tools.every(tool => tool && typeof tool.name === "string" && tool.name.length > 0 && tool.inputSchema && typeof tool.inputSchema === "object" && !Array.isArray(tool.inputSchema) && tool.inputSchema.type === "object"), "MCP tools/list: invalid tools");
|
|
56
|
+
names.push(...page.tools.map(tool => tool.name));
|
|
57
|
+
cursor = page.nextCursor;
|
|
58
|
+
if (cursor !== undefined) {
|
|
59
|
+
assert.ok(typeof cursor === "string" && cursor.length > 0 && !cursors.has(cursor), "MCP tools/list: invalid or repeated cursor");
|
|
60
|
+
cursors.add(cursor);
|
|
61
|
+
}
|
|
62
|
+
} while (cursor !== undefined);
|
|
63
|
+
assert.deepEqual(names.sort(), expected, "MCP tools/list: discovered tools differ from the expected permitted tools");
|
|
64
|
+
return names;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const database = "mantle-app"; // wrangler.jsonc d1_databases[0].database_name
|
|
68
|
+
const env = { ...process.env, WRANGLER_SEND_METRICS: "false" };
|
|
69
|
+
|
|
70
|
+
export async function smoke(scenario, { vars = {} } = {}) {
|
|
71
|
+
const port = 18000 + Math.floor(Math.random() * 1000), origin = `http://127.0.0.1:${port}`, owner = "owner@example.test";
|
|
72
|
+
const state = mkdtempSync(join(tmpdir(), "mantle-smoke-"));
|
|
73
|
+
// Deployment DDL is explicit: nothing at runtime creates tables.
|
|
74
|
+
for (const file of ["generated/schema.sql", ...(existsSync("seed.sql") ? ["seed.sql"] : [])]) {
|
|
75
|
+
const applied = spawnSync("pnpm", ["exec", "wrangler", "d1", "execute", database, "--local", "--persist-to", state, "--file", file], { encoding: "utf8", env });
|
|
76
|
+
assert.equal(applied.status, 0, applied.stdout + applied.stderr);
|
|
77
|
+
}
|
|
78
|
+
const wrangler = spawn("pnpm", ["exec", "wrangler", "dev", "--local", "--ip", "127.0.0.1", "--port", String(port), "--inspector-port", "0", "--persist-to", state, "--test-scheduled",
|
|
79
|
+
"--var", `PUBLIC_ORIGIN:${origin}`, "--var", `ADMIN_EMAIL:${owner}`, "--var", "BETTER_AUTH_SECRET:local-smoke-secret-0123456789abcdef", ...Object.entries(vars).flatMap(([name, value]) => ["--var", `${name}:${value}`])],
|
|
80
|
+
// its own process group: pnpm does not pass a signal on to wrangler and workerd
|
|
81
|
+
{ env: { ...env, CI: "1" }, stdio: ["ignore", "pipe", "pipe"], detached: true });
|
|
82
|
+
let logs = "";
|
|
83
|
+
wrangler.stdout.on("data", chunk => { logs += chunk; });
|
|
84
|
+
wrangler.stderr.on("data", chunk => { logs += chunk; });
|
|
85
|
+
|
|
86
|
+
// Better Auth limits OTP requests to 3 per minute per IP: each signed-in user gets its own client IP.
|
|
87
|
+
const ips = new Map();
|
|
88
|
+
const ipOf = email => ips.get(email) ?? (ips.set(email, `203.0.113.${ips.size + 1}`), ips.get(email));
|
|
89
|
+
/** method, path, { cookie, body, ip, headers } -> { status, body, headers } */
|
|
90
|
+
const call = async (method, path, { cookie, body, ip, headers = {} } = {}) => {
|
|
91
|
+
const response = await fetch(`${origin}${path}`, { method, headers: { "content-type": "application/json", origin, ...(cookie ? { cookie } : {}), ...(ip ? { "cf-connecting-ip": ip } : {}), ...headers },
|
|
92
|
+
...(body === undefined ? {} : { body: typeof body === "string" ? body : JSON.stringify(body) }) });
|
|
93
|
+
const text = await response.text();
|
|
94
|
+
let parsed; try { parsed = text ? JSON.parse(text) : null; } catch { parsed = text; }
|
|
95
|
+
return { status: response.status, body: parsed, headers: response.headers };
|
|
96
|
+
};
|
|
97
|
+
/** MCP tools/list (no name) or tools/call on /mcp or /mcp/admin. */
|
|
98
|
+
const mcp = async (path, cookie, name, args) => {
|
|
99
|
+
const response = await fetch(`${origin}${path}`, { method: "POST", headers: { "content-type": "application/json", origin, accept: "application/json, text/event-stream", ...(cookie ? { cookie } : {}) },
|
|
100
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: name ? "tools/call" : "tools/list", params: name ? { name, arguments: args } : {} }) });
|
|
101
|
+
const text = await response.text(), data = text.split("\n").find(line => line.startsWith("data:"));
|
|
102
|
+
return { status: response.status, body: data ? JSON.parse(data.slice(5)) : text ? JSON.parse(text) : null };
|
|
103
|
+
};
|
|
104
|
+
/** Console email OTP: request a code, read it from the wrangler log, sign in; returns the cookie header. */
|
|
105
|
+
const signIn = async email => {
|
|
106
|
+
const before = logs.length, ip = ipOf(email);
|
|
107
|
+
assert.equal((await call("POST", "/api/auth/email-otp/send-verification-otp", { body: { email, type: "sign-in" }, ip })).status, 200);
|
|
108
|
+
let code;
|
|
109
|
+
for (let i = 0; i < 40 && !code; i++) {
|
|
110
|
+
code = new RegExp(`${email.replace(/[.+]/g, "\\$&")}[\\s\\S]*?one-time code is (\\d{6})`).exec(logs.slice(before))?.[1];
|
|
111
|
+
if (!code) await new Promise(resolve => setTimeout(resolve, 100));
|
|
112
|
+
}
|
|
113
|
+
assert.ok(code, `no one-time code for ${email} in the log`);
|
|
114
|
+
const signed = await call("POST", "/api/auth/sign-in/email-otp", { body: { email, otp: code }, ip });
|
|
115
|
+
assert.equal(signed.status, 200, JSON.stringify(signed.body));
|
|
116
|
+
return signed.headers.getSetCookie().map(c => c.split(";")[0]).join("; ");
|
|
117
|
+
};
|
|
118
|
+
/** Run SQL against the local D1 (inspect state or inject a failure). Async, so the server's sockets stay serviced. */
|
|
119
|
+
const sql = async command => {
|
|
120
|
+
const { stdout } = await promisify(execFile)("pnpm", ["exec", "wrangler", "d1", "execute", database, "--local", "--persist-to", state, "--command", command, "--json"], { encoding: "utf8", env });
|
|
121
|
+
return JSON.parse(stdout)[0].results;
|
|
122
|
+
};
|
|
123
|
+
/** Fire the Worker's scheduled() handler (wrangler dev --test-scheduled). */
|
|
124
|
+
const cron = async expression => (await fetch(`${origin}/cdn-cgi/local/scheduled?cron=${encodeURIComponent(expression)}`)).status;
|
|
125
|
+
/** Wait until the wrangler log (console.log from the Worker, e.g. ConsoleEmailSender) matches. */
|
|
126
|
+
const waitForLog = async pattern => {
|
|
127
|
+
for (let i = 0; i < 40; i++) { if (pattern.test(logs)) return; await new Promise(resolve => setTimeout(resolve, 100)); }
|
|
128
|
+
assert.fail(`no log line matching ${pattern}`);
|
|
129
|
+
};
|
|
130
|
+
const step = name => console.log(`ok - ${name}`);
|
|
131
|
+
try {
|
|
132
|
+
for (let attempt = 0; ; attempt++) {
|
|
133
|
+
if (wrangler.exitCode !== null) throw new Error(`wrangler exited ${wrangler.exitCode}`);
|
|
134
|
+
try { await fetch(`${origin}/api/auth/ok`); break; } catch { /* starting */ }
|
|
135
|
+
if (attempt > 240) throw new Error("the Worker did not start");
|
|
136
|
+
await new Promise(resolve => setTimeout(resolve, 250));
|
|
137
|
+
}
|
|
138
|
+
await scenario({ origin, owner, call, mcp, signIn, sql, cron, waitForLog, step, logs: () => logs });
|
|
139
|
+
console.log("smoke passed");
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.error(logs.slice(-4000));
|
|
142
|
+
throw error;
|
|
143
|
+
} finally {
|
|
144
|
+
const stop = signal => { try { process.kill(-wrangler.pid, signal); } catch { /* already gone */ } };
|
|
145
|
+
stop("SIGTERM");
|
|
146
|
+
await new Promise(resolve => {
|
|
147
|
+
if (wrangler.exitCode !== null) return resolve();
|
|
148
|
+
const timer = setTimeout(() => { stop("SIGKILL"); resolve(); }, 5_000);
|
|
149
|
+
wrangler.once("exit", () => { clearTimeout(timer); resolve(); });
|
|
150
|
+
});
|
|
151
|
+
stop("SIGKILL");
|
|
152
|
+
rmSync(state, { recursive: true, force: true });
|
|
153
|
+
}
|
|
154
|
+
}
|