@async/db 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +167 -0
- package/README.md +431 -0
- package/SPEC.md +1429 -0
- package/db.config.example.mjs +128 -0
- package/dist/cli/args.d.ts +8 -0
- package/dist/cli/args.js +16 -0
- package/dist/cli/commands/create.d.ts +3 -0
- package/dist/cli/commands/create.js +13 -0
- package/dist/cli/commands/doctor.d.ts +3 -0
- package/dist/cli/commands/doctor.js +31 -0
- package/dist/cli/commands/generate.d.ts +6 -0
- package/dist/cli/commands/generate.js +24 -0
- package/dist/cli/commands/operations.d.ts +12 -0
- package/dist/cli/commands/operations.js +61 -0
- package/dist/cli/commands/schema.d.ts +11 -0
- package/dist/cli/commands/schema.js +1086 -0
- package/dist/cli/commands/serve.d.ts +9 -0
- package/dist/cli/commands/serve.js +18 -0
- package/dist/cli/commands/sync.d.ts +3 -0
- package/dist/cli/commands/sync.js +11 -0
- package/dist/cli/commands/types.d.ts +7 -0
- package/dist/cli/commands/types.js +37 -0
- package/dist/cli/commands/viewer.d.ts +6 -0
- package/dist/cli/commands/viewer.js +29 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +108 -0
- package/dist/cli/output.d.ts +25 -0
- package/dist/cli/output.js +149 -0
- package/dist/cli/schema-prompt.d.ts +20 -0
- package/dist/cli/schema-prompt.js +66 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +3 -0
- package/dist/client-cache.d.ts +105 -0
- package/dist/client-cache.js +916 -0
- package/dist/client.d.ts +64 -0
- package/dist/client.js +405 -0
- package/dist/config-public.d.ts +1 -0
- package/dist/config-public.js +1 -0
- package/dist/config.d.ts +54 -0
- package/dist/config.js +2 -0
- package/dist/csv.d.ts +1 -0
- package/dist/csv.js +1 -0
- package/dist/db.d.ts +3 -0
- package/dist/db.js +3 -0
- package/dist/doctor.d.ts +1 -0
- package/dist/doctor.js +1 -0
- package/dist/errors.d.ts +1 -0
- package/dist/errors.js +1 -0
- package/dist/features/config/defaults.d.ts +98 -0
- package/dist/features/config/defaults.js +95 -0
- package/dist/features/config/load.d.ts +11 -0
- package/dist/features/config/load.js +265 -0
- package/dist/features/config/public.d.ts +17 -0
- package/dist/features/config/public.js +75 -0
- package/dist/features/doctor/duplicate-ids.d.ts +18 -0
- package/dist/features/doctor/duplicate-ids.js +79 -0
- package/dist/features/doctor/field-consistency.d.ts +17 -0
- package/dist/features/doctor/field-consistency.js +48 -0
- package/dist/features/doctor/index.d.ts +39 -0
- package/dist/features/doctor/index.js +177 -0
- package/dist/features/doctor/relations.d.ts +22 -0
- package/dist/features/doctor/relations.js +90 -0
- package/dist/features/doctor/schema-guidance.d.ts +35 -0
- package/dist/features/doctor/schema-guidance.js +184 -0
- package/dist/features/generate/registry.d.ts +14 -0
- package/dist/features/generate/registry.js +37 -0
- package/dist/features/http/registry.d.ts +46 -0
- package/dist/features/http/registry.js +86 -0
- package/dist/features/operations/index.d.ts +49 -0
- package/dist/features/operations/index.js +199 -0
- package/dist/features/operations/maps.d.ts +1 -0
- package/dist/features/operations/maps.js +10 -0
- package/dist/features/operations/readiness.d.ts +30 -0
- package/dist/features/operations/readiness.js +228 -0
- package/dist/features/operations/runtime.d.ts +57 -0
- package/dist/features/operations/runtime.js +288 -0
- package/dist/features/runtime/collection.d.ts +51 -0
- package/dist/features/runtime/collection.js +198 -0
- package/dist/features/runtime/db.d.ts +152 -0
- package/dist/features/runtime/db.js +824 -0
- package/dist/features/runtime/document.d.ts +43 -0
- package/dist/features/runtime/document.js +111 -0
- package/dist/features/runtime/fanout.d.ts +24 -0
- package/dist/features/runtime/fanout.js +77 -0
- package/dist/features/runtime/json-pointer.d.ts +5 -0
- package/dist/features/runtime/json-pointer.js +49 -0
- package/dist/features/runtime/scope-state.d.ts +44 -0
- package/dist/features/runtime/scope-state.js +185 -0
- package/dist/features/runtime/state.d.ts +1 -0
- package/dist/features/runtime/state.js +1 -0
- package/dist/features/schema/api.d.ts +107 -0
- package/dist/features/schema/api.js +460 -0
- package/dist/features/schema/builders.d.ts +86 -0
- package/dist/features/schema/builders.js +110 -0
- package/dist/features/schema/fields.d.ts +38 -0
- package/dist/features/schema/fields.js +296 -0
- package/dist/features/schema/generated.d.ts +29 -0
- package/dist/features/schema/generated.js +32 -0
- package/dist/features/schema/locator.d.ts +16 -0
- package/dist/features/schema/locator.js +135 -0
- package/dist/features/schema/manifest.d.ts +91 -0
- package/dist/features/schema/manifest.js +384 -0
- package/dist/features/schema/metadata.d.ts +30 -0
- package/dist/features/schema/metadata.js +75 -0
- package/dist/features/schema/project.d.ts +46 -0
- package/dist/features/schema/project.js +442 -0
- package/dist/features/schema/relations.d.ts +38 -0
- package/dist/features/schema/relations.js +109 -0
- package/dist/features/schema/resolvers.d.ts +36 -0
- package/dist/features/schema/resolvers.js +111 -0
- package/dist/features/schema/resource.d.ts +75 -0
- package/dist/features/schema/resource.js +253 -0
- package/dist/features/schema/source-definitions.d.ts +21 -0
- package/dist/features/schema/source-definitions.js +29 -0
- package/dist/features/schema/sources.d.ts +83 -0
- package/dist/features/schema/sources.js +689 -0
- package/dist/features/schema/standard-schema.d.ts +57 -0
- package/dist/features/schema/standard-schema.js +232 -0
- package/dist/features/schema/validation.d.ts +69 -0
- package/dist/features/schema/validation.js +434 -0
- package/dist/features/storage/events.d.ts +12 -0
- package/dist/features/storage/events.js +30 -0
- package/dist/features/storage/json.d.ts +112 -0
- package/dist/features/storage/json.js +239 -0
- package/dist/features/storage/memory.d.ts +30 -0
- package/dist/features/storage/memory.js +44 -0
- package/dist/features/storage/resource-json.d.ts +31 -0
- package/dist/features/storage/resource-json.js +76 -0
- package/dist/features/storage/runtime.d.ts +37 -0
- package/dist/features/storage/runtime.js +184 -0
- package/dist/features/storage/source-metadata.d.ts +20 -0
- package/dist/features/storage/source-metadata.js +25 -0
- package/dist/features/storage/source.d.ts +37 -0
- package/dist/features/storage/source.js +60 -0
- package/dist/features/storage/static.d.ts +29 -0
- package/dist/features/storage/static.js +42 -0
- package/dist/features/sync/defaults.d.ts +21 -0
- package/dist/features/sync/defaults.js +21 -0
- package/dist/features/sync/index.d.ts +35 -0
- package/dist/features/sync/index.js +85 -0
- package/dist/features/sync/mirror-state.d.ts +14 -0
- package/dist/features/sync/mirror-state.js +4 -0
- package/dist/features/sync/runtime-dirs.d.ts +5 -0
- package/dist/features/sync/runtime-dirs.js +9 -0
- package/dist/features/sync/source-writes.d.ts +15 -0
- package/dist/features/sync/source-writes.js +27 -0
- package/dist/features/sync/synthetic-seed.d.ts +26 -0
- package/dist/features/sync/synthetic-seed.js +83 -0
- package/dist/features/viewer/manifest.d.ts +148 -0
- package/dist/features/viewer/manifest.js +165 -0
- package/dist/fs-utils.d.ts +1 -0
- package/dist/fs-utils.js +1 -0
- package/dist/generate/hono/app.d.ts +6 -0
- package/dist/generate/hono/app.js +51 -0
- package/dist/generate/hono/graphql.d.ts +7 -0
- package/dist/generate/hono/graphql.js +53 -0
- package/dist/generate/hono/index.d.ts +55 -0
- package/dist/generate/hono/index.js +140 -0
- package/dist/generate/hono/package.d.ts +6 -0
- package/dist/generate/hono/package.js +44 -0
- package/dist/generate/hono/readme.d.ts +13 -0
- package/dist/generate/hono/readme.js +28 -0
- package/dist/generate/hono/repository.d.ts +1 -0
- package/dist/generate/hono/repository.js +27 -0
- package/dist/generate/hono/rest.d.ts +1 -0
- package/dist/generate/hono/rest.js +38 -0
- package/dist/generate/hono/schema.d.ts +13 -0
- package/dist/generate/hono/schema.js +18 -0
- package/dist/generate/hono/sqlite.d.ts +20 -0
- package/dist/generate/hono/sqlite.js +266 -0
- package/dist/generate/hono/validators.d.ts +1 -0
- package/dist/generate/hono/validators.js +141 -0
- package/dist/generate/hono.d.ts +1 -0
- package/dist/generate/hono.js +1 -0
- package/dist/graphql/execute.d.ts +14 -0
- package/dist/graphql/execute.js +719 -0
- package/dist/graphql/http.d.ts +15 -0
- package/dist/graphql/http.js +29 -0
- package/dist/graphql/index.d.ts +3 -0
- package/dist/graphql/index.js +3 -0
- package/dist/graphql/parser.d.ts +54 -0
- package/dist/graphql/parser.js +433 -0
- package/dist/hono.d.ts +77 -0
- package/dist/hono.js +1 -0
- package/dist/index.d.ts +1065 -0
- package/dist/index.js +14 -0
- package/dist/integrations/hono.d.ts +136 -0
- package/dist/integrations/hono.js +508 -0
- package/dist/integrations/kv.d.ts +69 -0
- package/dist/integrations/kv.js +69 -0
- package/dist/integrations/postgres.d.ts +52 -0
- package/dist/integrations/postgres.js +113 -0
- package/dist/integrations/sqlite.d.ts +112 -0
- package/dist/integrations/sqlite.js +489 -0
- package/dist/integrations/vite.d.ts +45 -0
- package/dist/integrations/vite.js +111 -0
- package/dist/json.d.ts +48 -0
- package/dist/json.js +1 -0
- package/dist/jsonc.d.ts +1 -0
- package/dist/jsonc.js +1 -0
- package/dist/kv.d.ts +24 -0
- package/dist/kv.js +1 -0
- package/dist/mock.d.ts +1 -0
- package/dist/mock.js +1 -0
- package/dist/names.d.ts +1 -0
- package/dist/names.js +1 -0
- package/dist/operations.d.ts +3 -0
- package/dist/operations.js +3 -0
- package/dist/postgres.d.ts +24 -0
- package/dist/postgres.js +1 -0
- package/dist/redis.d.ts +14 -0
- package/dist/redis.js +1 -0
- package/dist/rest/formats.d.ts +80 -0
- package/dist/rest/formats.js +318 -0
- package/dist/rest/handler.d.ts +111 -0
- package/dist/rest/handler.js +833 -0
- package/dist/rest/shape.d.ts +33 -0
- package/dist/rest/shape.js +218 -0
- package/dist/schema-builders.d.ts +1 -0
- package/dist/schema-builders.js +1 -0
- package/dist/schema-manifest.d.ts +1 -0
- package/dist/schema-manifest.js +1 -0
- package/dist/schema.d.ts +193 -0
- package/dist/schema.js +6 -0
- package/dist/server.d.ts +116 -0
- package/dist/server.js +601 -0
- package/dist/shared/csv.d.ts +8 -0
- package/dist/shared/csv.js +149 -0
- package/dist/shared/errors.d.ts +40 -0
- package/dist/shared/errors.js +55 -0
- package/dist/shared/fs-utils.d.ts +4 -0
- package/dist/shared/fs-utils.js +30 -0
- package/dist/shared/jsonc.d.ts +2 -0
- package/dist/shared/jsonc.js +99 -0
- package/dist/shared/mock.d.ts +40 -0
- package/dist/shared/mock.js +83 -0
- package/dist/shared/names.d.ts +28 -0
- package/dist/shared/names.js +127 -0
- package/dist/shared/operations.d.ts +32 -0
- package/dist/shared/operations.js +302 -0
- package/dist/sqlite.d.ts +24 -0
- package/dist/sqlite.js +1 -0
- package/dist/state.d.ts +1 -0
- package/dist/state.js +1 -0
- package/dist/sync.d.ts +1 -0
- package/dist/sync.js +1 -0
- package/dist/tracing.d.ts +95 -0
- package/dist/tracing.js +260 -0
- package/dist/types.d.ts +51 -0
- package/dist/types.js +285 -0
- package/dist/viewer-manifest.d.ts +1 -0
- package/dist/viewer-manifest.js +1 -0
- package/dist/vite.d.ts +59 -0
- package/dist/vite.js +1 -0
- package/dist/web/json-viewer.d.ts +5 -0
- package/dist/web/json-viewer.js +176 -0
- package/dist/web/viewer.d.ts +12 -0
- package/dist/web/viewer.js +1015 -0
- package/docs/README.md +42 -0
- package/docs/architecture.md +112 -0
- package/docs/ci-and-release.md +177 -0
- package/docs/cms-storage-patterns.md +108 -0
- package/docs/concepts.md +141 -0
- package/docs/configuration.md +552 -0
- package/docs/fixtures-and-schemas.md +527 -0
- package/docs/fork-branch-workflows.md +108 -0
- package/docs/generated-files.md +174 -0
- package/docs/getting-started.md +165 -0
- package/docs/integrations.md +206 -0
- package/docs/json-production.md +120 -0
- package/docs/package-api.md +418 -0
- package/docs/prototype-to-production.md +378 -0
- package/docs/server-and-viewer.md +466 -0
- package/docs/store-graduation.md +120 -0
- package/docs/typescript-schema-sources.md +79 -0
- package/examples/advanced/README.md +55 -0
- package/examples/advanced/db/projects.schema.jsonc +44 -0
- package/examples/advanced/db/settings.jsonc +9 -0
- package/examples/advanced/db/users.json +23 -0
- package/examples/advanced/db/users.schema.mjs +31 -0
- package/examples/advanced/db.config.mjs +18 -0
- package/examples/advanced/example.json +5 -0
- package/examples/advanced/src/generated/db.types.d.ts +64 -0
- package/examples/basic/README.md +95 -0
- package/examples/basic/db/operations/get-user.jsonc +8 -0
- package/examples/basic/db/settings.json +7 -0
- package/examples/basic/db/users.schema.jsonc +36 -0
- package/examples/basic/db.config.mjs +68 -0
- package/examples/basic/example.json +5 -0
- package/examples/basic/src/generated/db.types.d.ts +39 -0
- package/examples/cms-json-publish/README.md +21 -0
- package/examples/cms-json-publish/db/navigation.json +7 -0
- package/examples/cms-json-publish/db/pages.json +18 -0
- package/examples/cms-json-publish/example.json +5 -0
- package/examples/cms-json-publish/src/cms.mjs +104 -0
- package/examples/computed-fields/README.md +93 -0
- package/examples/computed-fields/db/orders.schema.mjs +62 -0
- package/examples/computed-fields/db/posts.schema.mjs +59 -0
- package/examples/computed-fields/db/products.schema.mjs +39 -0
- package/examples/computed-fields/db/users.schema.mjs +43 -0
- package/examples/computed-fields/db.config.mjs +15 -0
- package/examples/computed-fields/example.json +5 -0
- package/examples/computed-fields/src/generated/db.types.d.ts +81 -0
- package/examples/content-collections/README.md +91 -0
- package/examples/content-collections/db/authors.json +12 -0
- package/examples/content-collections/db/authors.schema.mjs +20 -0
- package/examples/content-collections/db/blog/draft-roadmap.mdx +12 -0
- package/examples/content-collections/db/blog/index.schema.mjs +61 -0
- package/examples/content-collections/db/blog/launch-notes.mdx +15 -0
- package/examples/content-collections/db/docs/index.schema.mjs +32 -0
- package/examples/content-collections/db/docs/intro.mdx +11 -0
- package/examples/content-collections/db/docs/schema-workflow.mdx +10 -0
- package/examples/content-collections/db/site.schema.jsonc +21 -0
- package/examples/content-collections/db.config.mjs +26 -0
- package/examples/content-collections/example.json +5 -0
- package/examples/content-collections/src/content-preview.mjs +66 -0
- package/examples/content-collections/src/generated/db.types.d.ts +81 -0
- package/examples/csv/README.md +52 -0
- package/examples/csv/db/customers.csv +4 -0
- package/examples/csv/db.config.mjs +13 -0
- package/examples/csv/example.json +5 -0
- package/examples/data-first/README.md +54 -0
- package/examples/data-first/db/posts.json +16 -0
- package/examples/data-first/db/settings.json +8 -0
- package/examples/data-first/db/users.json +14 -0
- package/examples/data-first/db.config.mjs +13 -0
- package/examples/data-first/example.json +5 -0
- package/examples/diagnostics/README.md +55 -0
- package/examples/diagnostics/db/projects.schema.jsonc +27 -0
- package/examples/diagnostics/db/users.json +9 -0
- package/examples/diagnostics/db/users.schema.jsonc +23 -0
- package/examples/diagnostics/db.config.mjs +16 -0
- package/examples/diagnostics/example.json +5 -0
- package/examples/free-plan-upgrade/README.md +22 -0
- package/examples/free-plan-upgrade/db/appSettings.json +4 -0
- package/examples/free-plan-upgrade/db/projects.json +7 -0
- package/examples/free-plan-upgrade/example.json +5 -0
- package/examples/free-plan-upgrade/src/upgrade-tenant-to-paid.mjs +105 -0
- package/examples/hono-auth/README.md +74 -0
- package/examples/hono-auth/db/pages.schema.jsonc +44 -0
- package/examples/hono-auth/db/users.schema.jsonc +42 -0
- package/examples/hono-auth/db.config.mjs +17 -0
- package/examples/hono-auth/example.json +5 -0
- package/examples/hono-auth/package.json +14 -0
- package/examples/hono-auth/src/app.mjs +79 -0
- package/examples/hono-auth/src/server.mjs +13 -0
- package/examples/production-json/README.md +102 -0
- package/examples/production-json/db/appSettings.schema.jsonc +41 -0
- package/examples/production-json/db/featureFlags.schema.jsonc +84 -0
- package/examples/production-json/db/operations/get-control-plane.jsonc +6 -0
- package/examples/production-json/db/operations/get-feature-flag.jsonc +9 -0
- package/examples/production-json/db/operations/list-feature-flags.jsonc +8 -0
- package/examples/production-json/db/operations/read-public-settings.jsonc +8 -0
- package/examples/production-json/db.config.mjs +33 -0
- package/examples/production-json/example.json +5 -0
- package/examples/production-json/src/client-demo.mjs +28 -0
- package/examples/production-json/src/generated/db.types.d.ts +60 -0
- package/examples/relations/README.md +56 -0
- package/examples/relations/db/posts.schema.jsonc +46 -0
- package/examples/relations/db/users.schema.jsonc +34 -0
- package/examples/relations/db.config.mjs +13 -0
- package/examples/relations/example.json +5 -0
- package/examples/rest-client/README.md +54 -0
- package/examples/rest-client/db/settings.json +5 -0
- package/examples/rest-client/db/users.schema.jsonc +42 -0
- package/examples/rest-client/db.config.mjs +13 -0
- package/examples/rest-client/example.json +5 -0
- package/examples/rest-client/src/client-demo.mjs +24 -0
- package/examples/schema-first/README.md +55 -0
- package/examples/schema-first/db/auditEvents.schema.jsonc +24 -0
- package/examples/schema-first/db/settings.schema.jsonc +29 -0
- package/examples/schema-first/db/users.schema.jsonc +36 -0
- package/examples/schema-first/db.config.mjs +15 -0
- package/examples/schema-first/example.json +5 -0
- package/examples/schema-first/src/generated/db.types.d.ts +47 -0
- package/examples/schema-manifest/README.md +50 -0
- package/examples/schema-manifest/db/projects.schema.jsonc +48 -0
- package/examples/schema-manifest/db/users.schema.jsonc +35 -0
- package/examples/schema-manifest/db.config.mjs +41 -0
- package/examples/schema-manifest/example.json +5 -0
- package/examples/schema-manifest/src/generated/db.schema.json +130 -0
- package/examples/schema-manifest/src/generated/db.types.d.ts +50 -0
- package/examples/schema-ui/README.md +103 -0
- package/examples/schema-ui/db/pages.schema.jsonc +53 -0
- package/examples/schema-ui/db/users.schema.jsonc +30 -0
- package/examples/schema-ui/db.config.mjs +55 -0
- package/examples/schema-ui/example.json +5 -0
- package/examples/schema-ui/src/cms-ssr.mjs +276 -0
- package/examples/schema-ui/src/generated/db.schema.json +133 -0
- package/examples/schema-ui/src/generated/db.types.d.ts +46 -0
- package/examples/schema-ui/src/render-admin.mjs +175 -0
- package/examples/schema-ui/src/schema-ui-ssr-handler.mjs +149 -0
- package/examples/schema-ui/src/start-schema-ui-server.mjs +140 -0
- package/examples/standard-schema/README.md +55 -0
- package/examples/standard-schema/db/settings.schema.mjs +22 -0
- package/examples/standard-schema/db/users.schema.mjs +72 -0
- package/examples/standard-schema/example.json +5 -0
- package/package.json +108 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
# Prototype To Production REST Guide
|
|
2
|
+
|
|
3
|
+
@async/db starts with fixture-like local REST routes so a prototype can move
|
|
4
|
+
quickly. When the contract settles, keep the same resource model but move app
|
|
5
|
+
traffic behind an owned API namespace, registered operations, or a generated
|
|
6
|
+
server.
|
|
7
|
+
|
|
8
|
+
## Prototype Defaults
|
|
9
|
+
|
|
10
|
+
Local development is intentionally open by default:
|
|
11
|
+
|
|
12
|
+
```txt
|
|
13
|
+
GET /db/users.json
|
|
14
|
+
GET /db/users/:id.json
|
|
15
|
+
POST /db/users
|
|
16
|
+
PATCH /db/users/:id
|
|
17
|
+
DELETE /db/users/:id
|
|
18
|
+
|
|
19
|
+
GET /__db
|
|
20
|
+
GET /__db/manifest.json
|
|
21
|
+
GET /__db/schema
|
|
22
|
+
POST /__db/batch
|
|
23
|
+
POST /__db/operations/:ref
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Use `/db/*` while the data shape is still changing. It mirrors the `db/`
|
|
27
|
+
fixture folder, works well with `.json` reads, and keeps the browser viewer
|
|
28
|
+
and import tools under `/__db`.
|
|
29
|
+
|
|
30
|
+
This default is local development infrastructure. Do not expose `async-db
|
|
31
|
+
serve` directly to customers as a public database API.
|
|
32
|
+
|
|
33
|
+
The JSON store can still be production-appropriate for small low-write
|
|
34
|
+
resources such as settings, feature flags, content, templates, policy rules,
|
|
35
|
+
and seed data. Treat it as a file-backed store behind your app API, not as a
|
|
36
|
+
public hosted database. Use registered operations, app-owned auth, rate limits,
|
|
37
|
+
and monitoring for production-facing traffic.
|
|
38
|
+
|
|
39
|
+
## Pick A Production Namespace
|
|
40
|
+
|
|
41
|
+
When a prototype turns into app-owned API surface, use an API namespace that
|
|
42
|
+
fits the surrounding app:
|
|
43
|
+
|
|
44
|
+
| Namespace | Use when |
|
|
45
|
+
| --- | --- |
|
|
46
|
+
| `/api/db/{resource}` | The app already has other `/api/*` routes and db routes should be clearly grouped. |
|
|
47
|
+
| `/api/{resource}` | The API is dedicated to db resources and there is no need for an extra `/db` segment. |
|
|
48
|
+
| `/db/{resource}` | Local prototype and test routes. Avoid this as the customer-facing production namespace. |
|
|
49
|
+
|
|
50
|
+
For a production-like local server, move the fixture-style alias and dev-tool
|
|
51
|
+
base together:
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
import { defineConfig } from '@async/db/config';
|
|
55
|
+
|
|
56
|
+
export default defineConfig({
|
|
57
|
+
server: {
|
|
58
|
+
dataPath: '/api/db',
|
|
59
|
+
apiBase: '/api/db',
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
That makes raw app-facing reads look like:
|
|
65
|
+
|
|
66
|
+
```txt
|
|
67
|
+
GET /api/db/users.json
|
|
68
|
+
GET /api/db/users/u_1.json
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
It also moves registered operation execution to:
|
|
72
|
+
|
|
73
|
+
```txt
|
|
74
|
+
POST /api/db/operations/GetUserProfile
|
|
75
|
+
POST /api/db/operations/users.profile.get
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The operation templates themselves still use internal resource paths such as
|
|
79
|
+
`/users/{id}.json`. The public route is the `/operations/:ref` endpoint.
|
|
80
|
+
|
|
81
|
+
## Register Stable Operation Refs
|
|
82
|
+
|
|
83
|
+
Registered operations let app code call a named contract instead of exploring
|
|
84
|
+
raw resource URLs. Any non-path string can be the ref. Use refs that do not
|
|
85
|
+
start with `/` and do not look like `GET /...`, because `client.query()` treats
|
|
86
|
+
those as literal REST templates.
|
|
87
|
+
|
|
88
|
+
Server config:
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
import { defineConfig } from '@async/db/config';
|
|
92
|
+
|
|
93
|
+
export default defineConfig({
|
|
94
|
+
operations: {
|
|
95
|
+
enabled: true,
|
|
96
|
+
registry: {
|
|
97
|
+
GetUserProfile: {
|
|
98
|
+
method: 'GET',
|
|
99
|
+
path: '/users/{id}.json',
|
|
100
|
+
query: {
|
|
101
|
+
select: 'id,name,email',
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
server: {
|
|
107
|
+
apiBase: '/api/db',
|
|
108
|
+
dataPath: '/api/db',
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Client code:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
import { createDbClient } from '@async/db/client';
|
|
117
|
+
|
|
118
|
+
const db = createDbClient({
|
|
119
|
+
baseUrl: 'https://example.com',
|
|
120
|
+
apiBase: '/api/db',
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const user = await db.query('GetUserProfile', { id: 'u_1' });
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The client sends:
|
|
127
|
+
|
|
128
|
+
```txt
|
|
129
|
+
POST /api/db/operations/GetUserProfile
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The server looks up `GetUserProfile`, substitutes variables, and executes the
|
|
133
|
+
registered REST template through normal @async/db shaping and validation.
|
|
134
|
+
|
|
135
|
+
## Use Opaque Refs When You Need Them
|
|
136
|
+
|
|
137
|
+
Readable refs are convenient. Opaque refs are useful when you do not want
|
|
138
|
+
customer-facing client bundles to reveal raw route names, selected fields, or
|
|
139
|
+
query templates.
|
|
140
|
+
|
|
141
|
+
By default, generated refs are derived from the canonical operation contents:
|
|
142
|
+
|
|
143
|
+
```txt
|
|
144
|
+
/users/{id}.json?select=id,name,email
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
and become a stable ref like:
|
|
148
|
+
|
|
149
|
+
```txt
|
|
150
|
+
op_9d66...
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Build a server registry and client-safe refs from operation source files:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
async-db operations build \
|
|
157
|
+
--out ./src/generated/db.operations.json \
|
|
158
|
+
--refs-out ./src/generated/db.operation-refs.json
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Keep `db.operations.json` server-side because it contains full templates. Ship
|
|
162
|
+
only names and callable refs from `db.operation-refs.json` to browser code.
|
|
163
|
+
The client file does not expose paths, query templates, variables, request
|
|
164
|
+
bodies, or the full server registry.
|
|
165
|
+
|
|
166
|
+
Operation names and refs must be unique; the build fails rather than silently
|
|
167
|
+
generating refs that could resolve to a different registry entry.
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
import operationRefs from './generated/db.operation-refs.json' assert { type: 'json' };
|
|
171
|
+
|
|
172
|
+
await db.query(operationRefs.operations.GetUserProfile.ref, { id: 'u_1' });
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
To make the exposed client contract reviewable in CI, print or check the
|
|
176
|
+
deterministic contract:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
async-db operations contract
|
|
180
|
+
async-db operations contract --check
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
`--check` compares the current operation sources with `outputs.operationRefs`
|
|
184
|
+
or an explicit `--out <file>` and fails when exposed names or refs change.
|
|
185
|
+
|
|
186
|
+
By default, `operations.*.ref` is generated with `hashOperation()`. Set an
|
|
187
|
+
explicit `ref` in the operation source when the app wants a readable or
|
|
188
|
+
app-owned callable id:
|
|
189
|
+
|
|
190
|
+
```json
|
|
191
|
+
{
|
|
192
|
+
"name": "GetUserProfile",
|
|
193
|
+
"ref": "users.profile.get",
|
|
194
|
+
"path": "/users/{id}.json",
|
|
195
|
+
"query": {
|
|
196
|
+
"select": "id,name"
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
For opaque production clients, keep generated refs or generate your own refs
|
|
202
|
+
with `hashOperation()`, then accept only refs on the server:
|
|
203
|
+
|
|
204
|
+
```js
|
|
205
|
+
export default defineConfig({
|
|
206
|
+
operations: {
|
|
207
|
+
acceptRefs: 'ref',
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
If an app has its own registry build step or policy, keep generated client refs
|
|
213
|
+
simple and customize server lookup with `operations.resolveRef` or
|
|
214
|
+
`operations.validateRef`. Inline registries can use operation objects or string
|
|
215
|
+
REST templates:
|
|
216
|
+
|
|
217
|
+
```js
|
|
218
|
+
registerDbRoutes(app, db, {
|
|
219
|
+
prefix: '/api/db',
|
|
220
|
+
operations: {
|
|
221
|
+
registry: {
|
|
222
|
+
GetUserProfile: '/users/{id}.json?select=id,name',
|
|
223
|
+
},
|
|
224
|
+
acceptRefs: 'name',
|
|
225
|
+
},
|
|
226
|
+
});
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
If the generated `outputs.operationRegistry` is missing or invalid, operation
|
|
230
|
+
execution fails with `OPERATION_REGISTRY_LOAD_FAILED` so you can rebuild the
|
|
231
|
+
registry or fix the configured path. A loaded registry that simply lacks a ref
|
|
232
|
+
still returns `OPERATION_NOT_FOUND`.
|
|
233
|
+
|
|
234
|
+
Refs are allowlist identifiers, not secrets. They reduce route exploration and
|
|
235
|
+
hide query shape from casual client inspection, but anyone who can call your API
|
|
236
|
+
still needs normal auth, authorization, rate limits, and monitoring.
|
|
237
|
+
|
|
238
|
+
## Operation-Only Exposure
|
|
239
|
+
|
|
240
|
+
`operations.enabled: true` enables registered operation execution without
|
|
241
|
+
closing local REST or viewer routes. Once the app uses registered operation
|
|
242
|
+
refs as its public data contract, opt into operation-only exposure to block raw
|
|
243
|
+
REST exploration:
|
|
244
|
+
|
|
245
|
+
```js
|
|
246
|
+
import { defineConfig } from '@async/db/config';
|
|
247
|
+
|
|
248
|
+
export default defineConfig({
|
|
249
|
+
outputs: {
|
|
250
|
+
operationRegistry: './src/generated/db.operations.json',
|
|
251
|
+
operationRefs: './src/generated/db.operation-refs.json',
|
|
252
|
+
},
|
|
253
|
+
operations: {
|
|
254
|
+
enabled: true,
|
|
255
|
+
acceptRefs: 'ref',
|
|
256
|
+
},
|
|
257
|
+
server: {
|
|
258
|
+
apiBase: '/api/db',
|
|
259
|
+
dataPath: '/api/db',
|
|
260
|
+
expose: {
|
|
261
|
+
rest: 'registered-only',
|
|
262
|
+
graphql: false,
|
|
263
|
+
viewer: 'dev',
|
|
264
|
+
schema: 'dev',
|
|
265
|
+
manifest: 'dev',
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
});
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
`registered-only` is not a general hardening switch. It specifically means only
|
|
272
|
+
registered operations may use the REST data API. With that policy, raw routes
|
|
273
|
+
such as these are rejected:
|
|
274
|
+
|
|
275
|
+
```txt
|
|
276
|
+
GET /api/db/users.json
|
|
277
|
+
POST /api/db/batch
|
|
278
|
+
GET /users
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Registered operations still run:
|
|
282
|
+
|
|
283
|
+
```txt
|
|
284
|
+
POST /api/db/operations/GetUserProfile
|
|
285
|
+
POST /api/db/operations/users.profile.get
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
The built-in server and `async-db doctor` fail early when
|
|
289
|
+
`server.expose.rest: 'registered-only'` is configured without
|
|
290
|
+
`operations.enabled: true` or without a resolvable operation source. Provide
|
|
291
|
+
`outputs.operationRegistry`, `operations.registry`, `operations.resolveRef`, or
|
|
292
|
+
operation files under `operations.sourceDir`; otherwise use
|
|
293
|
+
`server.expose.rest: 'open'` while keeping local REST routes available.
|
|
294
|
+
|
|
295
|
+
Use `server.expose.graphql: false` when the production-facing API is REST-only.
|
|
296
|
+
If you use registered GraphQL operations, keep `graphql.enabled` on and use
|
|
297
|
+
`server.expose.graphql: false` to hide only the direct GraphQL endpoint.
|
|
298
|
+
|
|
299
|
+
## Move To An Owned API Server
|
|
300
|
+
|
|
301
|
+
For app-specific auth, permissions, sessions, logging, and rate limiting, mount
|
|
302
|
+
db behind the framework that owns your production API.
|
|
303
|
+
|
|
304
|
+
With Hono route registration:
|
|
305
|
+
|
|
306
|
+
```ts
|
|
307
|
+
import { registerDbRoutes } from '@async/db/hono';
|
|
308
|
+
|
|
309
|
+
registerDbRoutes(app, db, {
|
|
310
|
+
prefix: '/api/db',
|
|
311
|
+
operations: true,
|
|
312
|
+
lifecycleHooks: {
|
|
313
|
+
beforeRequest({ c }) {
|
|
314
|
+
const session = readSession(c.req.header('authorization'));
|
|
315
|
+
if (!session) return c.json({ error: 'Unauthorized' }, 401);
|
|
316
|
+
c.set('session', session);
|
|
317
|
+
},
|
|
318
|
+
beforeWrite({ c }) {
|
|
319
|
+
if (c.get('session')?.role !== 'admin') {
|
|
320
|
+
return c.json({ error: 'Forbidden' }, 403);
|
|
321
|
+
}
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
});
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
`operations: true` mounts `POST /api/db/operations/:ref` using
|
|
328
|
+
`db.config.operations`. Omit it to use automatic mounting when
|
|
329
|
+
`db.config.operations.enabled` is true, set `operations: false` to keep only
|
|
330
|
+
raw REST routes on that mount, or pass a local operation registry when this
|
|
331
|
+
Hono app owns a custom build step:
|
|
332
|
+
|
|
333
|
+
Hono registered operation routes run `lifecycleHooks.beforeRequest` with
|
|
334
|
+
`method: 'operation'` and the operation `ref`, so shared auth/session checks can
|
|
335
|
+
protect both resource routes and registered operations. Resource write hooks do
|
|
336
|
+
not run for registered operations; enforce operation-specific permissions in the
|
|
337
|
+
app layer or with `operations.validateRef`.
|
|
338
|
+
|
|
339
|
+
```ts
|
|
340
|
+
registerDbRoutes(app, db, {
|
|
341
|
+
prefix: '/api/db',
|
|
342
|
+
operations: {
|
|
343
|
+
registry: generatedOperations.operations,
|
|
344
|
+
acceptRefs: 'ref',
|
|
345
|
+
},
|
|
346
|
+
});
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
Use `/api` instead of `/api/db` when the generated or registered API is only
|
|
350
|
+
for db resources:
|
|
351
|
+
|
|
352
|
+
```ts
|
|
353
|
+
registerDbRoutes(app, db, {
|
|
354
|
+
prefix: '/api',
|
|
355
|
+
});
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
When fixtures and schemas have settled enough for a standalone service, use the
|
|
359
|
+
Hono/SQLite starter:
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
async-db generate hono --api rest --out ./server
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
The generated server is the right direction when the data API needs its own
|
|
366
|
+
repository, deploy process, migrations, and production storage.
|
|
367
|
+
|
|
368
|
+
## Graduation Checklist
|
|
369
|
+
|
|
370
|
+
- Keep `/db/*` for prototype and test traffic.
|
|
371
|
+
- Move app-facing routes to `/api/db/*` or `/api/*`.
|
|
372
|
+
- Register string operation names or refs for stable app contracts.
|
|
373
|
+
- Import generated operation refs and call `.ref`; set explicit refs when app-owned callable ids are clearer.
|
|
374
|
+
- Use `acceptRefs: 'ref'` for opaque public clients, or `acceptRefs: 'name'` for readable internal APIs.
|
|
375
|
+
- Set `server.expose.rest: 'registered-only'` before treating operation refs as the public contract.
|
|
376
|
+
- Add app-owned auth, authorization, rate limits, and observability outside the registered operation registry.
|
|
377
|
+
- Generate a Hono/SQLite API when the endpoint needs production storage and deployment boundaries.
|
|
378
|
+
- Keep low-write control-plane resources in JSON when that is operationally appropriate, but move high-write, transactional, or multi-writer resources to SQLite, Postgres, or another app-owned store.
|