@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,174 @@
|
|
|
1
|
+
# Generated Files
|
|
2
|
+
|
|
3
|
+
@async/db writes generated output during `sync`, `serve`, package API startup, and some smoke commands. Know which files are runtime state and which files are intentionally committed.
|
|
4
|
+
|
|
5
|
+
## Default Generated Output
|
|
6
|
+
|
|
7
|
+
Default sync output:
|
|
8
|
+
|
|
9
|
+
```txt
|
|
10
|
+
.db/schema.generated.json
|
|
11
|
+
.db/types/index.d.ts
|
|
12
|
+
.db/state/*.json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
`.db/` is normally uncommitted. It contains generated schema metadata, generated TypeScript types, source metadata, and writable runtime store state.
|
|
16
|
+
|
|
17
|
+
## Runtime State
|
|
18
|
+
|
|
19
|
+
With the default JSON store:
|
|
20
|
+
|
|
21
|
+
```txt
|
|
22
|
+
db/users.json source fixture
|
|
23
|
+
.db/state/users.json writable runtime JSON store
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
REST writes, GraphQL mutations, package API writes, and viewer operations write to runtime state. Changed source fixtures refresh state based on source hashes; unchanged source fixtures preserve runtime edits.
|
|
27
|
+
|
|
28
|
+
## Generated Ids
|
|
29
|
+
|
|
30
|
+
Collections need ids. If a JSON, JSONC, or CSV collection fixture omits `id`, @async/db adds counter ids in the selected runtime store.
|
|
31
|
+
|
|
32
|
+
Source fixtures stay unchanged by default. For resources bound to the `sourceFile` store, @async/db may write generated ids back to plain `.json` collection fixtures when configured intentionally.
|
|
33
|
+
|
|
34
|
+
## Generated Types
|
|
35
|
+
|
|
36
|
+
Default generated TypeScript output:
|
|
37
|
+
|
|
38
|
+
```txt
|
|
39
|
+
.db/types/index.d.ts
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Use `outputs.committedTypes` when TypeScript imports should work before anyone runs sync:
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
import { defineConfig } from '@async/db/config';
|
|
46
|
+
|
|
47
|
+
export default defineConfig({
|
|
48
|
+
outputs: {
|
|
49
|
+
committedTypes: './src/generated/db.types.d.ts',
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Field descriptions become TypeScript JSDoc:
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
export type User = {
|
|
58
|
+
/** Stable user id. */
|
|
59
|
+
id: string;
|
|
60
|
+
|
|
61
|
+
/** Email address used for local sign-in. */
|
|
62
|
+
email: string;
|
|
63
|
+
};
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Selected examples intentionally commit generated type output:
|
|
67
|
+
|
|
68
|
+
```txt
|
|
69
|
+
examples/advanced/src/generated/db.types.d.ts
|
|
70
|
+
examples/basic/src/generated/db.types.d.ts
|
|
71
|
+
examples/computed-fields/src/generated/db.types.d.ts
|
|
72
|
+
examples/content-collections/src/generated/db.types.d.ts
|
|
73
|
+
examples/production-json/src/generated/db.types.d.ts
|
|
74
|
+
examples/schema-first/src/generated/db.types.d.ts
|
|
75
|
+
examples/schema-manifest/src/generated/db.types.d.ts
|
|
76
|
+
examples/schema-ui/src/generated/db.types.d.ts
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Schema Manifest Output
|
|
80
|
+
|
|
81
|
+
Use `outputs.schemaManifest` when a local admin, CMS, or form-building UI needs runtime schema metadata:
|
|
82
|
+
|
|
83
|
+
```js
|
|
84
|
+
import { defineConfig } from '@async/db/config';
|
|
85
|
+
|
|
86
|
+
export default defineConfig({
|
|
87
|
+
outputs: {
|
|
88
|
+
schemaManifest: './src/generated/db.schema.json',
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
`async-db sync` writes the manifest when `outputs.schemaManifest` is set. You can also generate it directly:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
npm run db -- schema manifest --out ./src/generated/db.schema.json
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The manifest includes normalized resource and field metadata such as `type`, `required`, `nullable`, `default`, `values`, nested `fields`, array `items`, relations, and generated UI defaults. The manifest file is metadata output only. Schema field defaults still drive configured runtime behavior such as create-time defaults and safe additive store hydration.
|
|
100
|
+
|
|
101
|
+
The manifests at [examples/schema-manifest/src/generated/db.schema.json](../examples/schema-manifest/src/generated/db.schema.json) and [examples/schema-ui/src/generated/db.schema.json](../examples/schema-ui/src/generated/db.schema.json) are intentionally committed.
|
|
102
|
+
|
|
103
|
+
## Viewer Manifest Output
|
|
104
|
+
|
|
105
|
+
Use `outputs.viewerManifest` when a custom data viewer needs the same JSON metadata used by the built-in viewer:
|
|
106
|
+
|
|
107
|
+
```js
|
|
108
|
+
import { defineConfig } from '@async/db/config';
|
|
109
|
+
|
|
110
|
+
export default defineConfig({
|
|
111
|
+
outputs: {
|
|
112
|
+
viewerManifest: './src/generated/db.viewer.json',
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`async-db sync` writes the viewer manifest when `outputs.viewerManifest` is set. You can also generate it directly:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
npm run db -- viewer manifest --out ./src/generated/db.viewer.json
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The viewer manifest includes field metadata, UI hints, relation hints, diagnostics, capabilities, configured viewer links, and API links such as `/__db/manifest`, `/__db/manifest.json`, `/__db/manifest.html`, `/__db/manifest.md`, `/__db/batch`, `/graphql`, and scoped REST resource routes under `/__db/rest`. It does not include seed records, source paths, source hashes, runtime state paths, or GraphQL SDL. Fetch actual records from REST or GraphQL.
|
|
124
|
+
|
|
125
|
+
## Operation Registry And Client Contract
|
|
126
|
+
|
|
127
|
+
Use `outputs.operationRegistry` for the full server-side operation registry and
|
|
128
|
+
`outputs.operationRefs` for the client-safe refs file:
|
|
129
|
+
|
|
130
|
+
```js
|
|
131
|
+
import { defineConfig } from '@async/db/config';
|
|
132
|
+
|
|
133
|
+
export default defineConfig({
|
|
134
|
+
outputs: {
|
|
135
|
+
operationRegistry: './src/generated/db.operations.json',
|
|
136
|
+
operationRefs: './src/generated/db.operation-refs.json',
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Build both files with:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
npm run db -- operations build
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
`db.operations.json` contains full templates and should stay server-side.
|
|
148
|
+
`db.operation-refs.json` is the browser-facing surface: it exposes operation
|
|
149
|
+
names and callable refs only, not paths, query templates, variables, request
|
|
150
|
+
bodies, or server registry internals.
|
|
151
|
+
|
|
152
|
+
For CI, use the deterministic contract view:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
npm run db -- operations contract --check
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The check compares the current generated client contract with
|
|
159
|
+
`outputs.operationRefs` by default. It ignores volatile `generatedAt` values and
|
|
160
|
+
fails only when exposed operation names or refs change.
|
|
161
|
+
|
|
162
|
+
## Cleanup Rules
|
|
163
|
+
|
|
164
|
+
- Do not commit `.db/` unless a task explicitly asks for generated runtime state.
|
|
165
|
+
- Do commit configured `outputs.committedTypes` output when an app needs stable imports in a fresh checkout.
|
|
166
|
+
- Do commit configured `outputs.schemaManifest` output when an app needs stable schema metadata at runtime.
|
|
167
|
+
- Do commit configured `outputs.viewerManifest` output when a custom viewer needs stable metadata and route links at runtime.
|
|
168
|
+
- Do commit configured `outputs.operationRefs` output when app or CI code imports approved registered operation refs.
|
|
169
|
+
- Smoke commands against examples may create `examples/*/.db/`; remove that generated runtime output before finalizing.
|
|
170
|
+
|
|
171
|
+
## Related Examples
|
|
172
|
+
|
|
173
|
+
- [Basic](../examples/basic/README.md)
|
|
174
|
+
- [Schema Manifest](../examples/schema-manifest/README.md)
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# Getting Started
|
|
2
|
+
|
|
3
|
+
This guide takes a project from one fixture file to a local API, viewer, generated schema metadata, and generated TypeScript types.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
Install @async/db from npm:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @async/db
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Add package scripts for the CLI commands you want to run often:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"scripts": {
|
|
18
|
+
"db": "async-db",
|
|
19
|
+
"db:sync": "async-db sync",
|
|
20
|
+
"db:serve": "async-db serve",
|
|
21
|
+
"db:types": "async-db types"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
If you need an unreleased fix, pin a reviewed GitHub commit or release tag instead of the moving default branch:
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@async/db": "github:async-framework/async-db#<reviewed-commit-sha-or-tag>"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The scripts use the local `node_modules/.bin/async-db` binary, so each project controls its own @async/db version.
|
|
37
|
+
|
|
38
|
+
## Create A Fixture
|
|
39
|
+
|
|
40
|
+
@async/db uses `./db` by default:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
mkdir -p db
|
|
44
|
+
cat > db/users.json <<'JSON'
|
|
45
|
+
[
|
|
46
|
+
{
|
|
47
|
+
"id": "u_1",
|
|
48
|
+
"name": "Ada Lovelace",
|
|
49
|
+
"email": "ada@example.com"
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
JSON
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Sync
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm run db:sync
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Sync reads fixtures and writes generated runtime output:
|
|
62
|
+
|
|
63
|
+
```txt
|
|
64
|
+
.db/schema.generated.json
|
|
65
|
+
.db/types/index.d.ts
|
|
66
|
+
.db/state/users.json
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
By default, app writes update the generated JSON store under `.db/state`. Source fixtures stay unchanged.
|
|
70
|
+
|
|
71
|
+
## Serve
|
|
72
|
+
|
|
73
|
+
In terminal 1:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npm run db:serve
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Open the viewer:
|
|
80
|
+
|
|
81
|
+
```txt
|
|
82
|
+
http://127.0.0.1:7331/__db
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
In terminal 2, call the REST API:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
curl http://127.0.0.1:7331/db/users.json
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
You can also read one record through the fixture-shaped URL:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
curl 'http://127.0.0.1:7331/db/users.json?id=u_1'
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Create another record:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
curl -X POST http://127.0.0.1:7331/db/users \
|
|
101
|
+
-H 'content-type: application/json' \
|
|
102
|
+
-d '{"id":"u_2","name":"Grace Hopper","email":"grace@example.com"}'
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The new record is written to `.db/state/users.json`, not `db/users.json`.
|
|
106
|
+
|
|
107
|
+
## Add A Schema
|
|
108
|
+
|
|
109
|
+
Add schema when the contract matters: required fields, defaults, descriptions, enums, uniqueness, relations, or stricter validation.
|
|
110
|
+
|
|
111
|
+
Create `db/users.schema.json`:
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"kind": "collection",
|
|
116
|
+
"idField": "id",
|
|
117
|
+
"fields": {
|
|
118
|
+
"id": { "type": "string", "required": true },
|
|
119
|
+
"name": { "type": "string", "required": true },
|
|
120
|
+
"email": {
|
|
121
|
+
"type": "string",
|
|
122
|
+
"required": true,
|
|
123
|
+
"unique": true,
|
|
124
|
+
"description": "Email address used for local sign-in."
|
|
125
|
+
},
|
|
126
|
+
"role": {
|
|
127
|
+
"type": "enum",
|
|
128
|
+
"values": ["admin", "user"],
|
|
129
|
+
"default": "user"
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Validate:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
npm run db -- schema validate
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
When `db/users.schema.json` and `db/users.json` both exist, the schema defines the contract and the data file provides seed records.
|
|
142
|
+
|
|
143
|
+
## Run A Repo Example
|
|
144
|
+
|
|
145
|
+
From this repository root:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
npm run db -- sync --cwd ./examples/basic
|
|
149
|
+
npm run db -- serve --cwd ./examples/basic
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Open:
|
|
153
|
+
|
|
154
|
+
```txt
|
|
155
|
+
http://127.0.0.1:7331/__db
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The example README has the exact files and requests for that workflow: [examples/basic](../examples/basic/README.md).
|
|
159
|
+
|
|
160
|
+
## Next Steps
|
|
161
|
+
|
|
162
|
+
- Use [Concepts](./concepts.md) to understand data-first, schema-first, mixed resources, runtime stores, and source writebacks.
|
|
163
|
+
- Use [Fixtures And Schemas](./fixtures-and-schemas.md) to author richer fixtures and schemas.
|
|
164
|
+
- Use [Server And Viewer](./server-and-viewer.md) for REST, GraphQL, viewer, and watch behavior.
|
|
165
|
+
- Use [Generated Files](./generated-files.md) before committing generated output.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# Integrations
|
|
2
|
+
|
|
3
|
+
@async/db keeps integrations optional. The core package remains dependency-light; apps opt into Vite, Hono, SQLite, or generated starter code when they need those paths.
|
|
4
|
+
|
|
5
|
+
## Vite Dev Server Plugin
|
|
6
|
+
|
|
7
|
+
Vite apps can mount @async/db into the existing dev server instead of running `async-db serve` on a second port:
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
import { defineConfig } from 'vite';
|
|
11
|
+
import { dbPlugin } from '@async/db/vite';
|
|
12
|
+
|
|
13
|
+
export default defineConfig({
|
|
14
|
+
plugins: [
|
|
15
|
+
dbPlugin(),
|
|
16
|
+
],
|
|
17
|
+
});
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The plugin is dev-only (`apply: 'serve'`). It does not run during `vite build`, and it does not add a mandatory Vite dependency to @async/db.
|
|
21
|
+
|
|
22
|
+
By default, app data routes use `/db`, while dev-tool routes stay scoped under `/__db`:
|
|
23
|
+
|
|
24
|
+
```txt
|
|
25
|
+
GET /db/users.json
|
|
26
|
+
GET /__db
|
|
27
|
+
GET /__db/schema
|
|
28
|
+
POST /__db/batch
|
|
29
|
+
POST /__db/graphql
|
|
30
|
+
GET /__db/rest/users
|
|
31
|
+
GET /__db/rest/users/u_1
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Use the virtual browser client from app code:
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import db from 'virtual:db/client';
|
|
38
|
+
|
|
39
|
+
const users = await db.rest.get('/users');
|
|
40
|
+
const selected = await db.rest.get('/users?select=id,name');
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Plugin options include `cwd`, `dbDir`, `outputs`, legacy `stateDir`, `apiBase`, `dataPath`, `restBasePath`, `graphqlPath`, `rootRoutes`, `clientVirtualModule`, `clientImport`, and `clientCache`.
|
|
44
|
+
The plugin uses `apiBase` first, then `server.apiBase`, then `/__db` for scoped dev routes.
|
|
45
|
+
Use `server.dataPath: false` to disable the `/db` app-facing data route alias.
|
|
46
|
+
|
|
47
|
+
Set `clientCache: true` to opt the virtual browser client into the default
|
|
48
|
+
memory cache during Vite dev. Object form supports serializable cache policy
|
|
49
|
+
options:
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
dbPlugin({
|
|
53
|
+
clientCache: {
|
|
54
|
+
enabled: true,
|
|
55
|
+
readPolicy: 'cache-and-network',
|
|
56
|
+
writePolicy: 'merge-and-invalidate',
|
|
57
|
+
eventPolicy: 'refetch',
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Use `createDbClient()` directly when you need an explicit browser storage
|
|
63
|
+
adapter such as `createIndexedDbCacheStorage(...)`.
|
|
64
|
+
|
|
65
|
+
Add `trace` to the plugin options to override `db.config.mjs` for Vite dev
|
|
66
|
+
requests:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
dbPlugin({
|
|
70
|
+
trace: {
|
|
71
|
+
enabled: true,
|
|
72
|
+
slowMs: 100,
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Set `rootRoutes: true` only when you intentionally want Vite dev to also answer unscoped routes like `/users`. Standalone `async-db serve` keeps those root REST routes by default.
|
|
78
|
+
|
|
79
|
+
The plugin watches fixture sources, not generated runtime output. @async/db also skips rewriting generated and state files when their content is unchanged, so normal `sync` or `openDb()` calls should not trigger Vite reloads by changing mtimes alone.
|
|
80
|
+
|
|
81
|
+
If an app commits generated files under frontend source, Vite may still reload when those files genuinely change. Ignore only generated files that the browser does not need to hot reload.
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
export default defineConfig({
|
|
85
|
+
server: {
|
|
86
|
+
watch: {
|
|
87
|
+
ignored: [
|
|
88
|
+
'../.db/**',
|
|
89
|
+
// Only include committed generated files here when browser code
|
|
90
|
+
// does not import them at runtime.
|
|
91
|
+
'src/generated/db.schema.json',
|
|
92
|
+
'src/generated/db.types.d.ts',
|
|
93
|
+
],
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Hono Route Registration
|
|
100
|
+
|
|
101
|
+
Apps that own a Hono instance can register @async/db REST routes and wrap them with lifecycle hooks.
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
import { registerDbRoutes } from '@async/db/hono';
|
|
105
|
+
|
|
106
|
+
registerDbRoutes(app, db, {
|
|
107
|
+
prefix: '/api',
|
|
108
|
+
operations: true,
|
|
109
|
+
trace: true,
|
|
110
|
+
resources: ['pages', 'charts'],
|
|
111
|
+
lifecycleHooks: {
|
|
112
|
+
beforeRequest({ c }) {
|
|
113
|
+
const session = readSession(c.req.header('authorization'));
|
|
114
|
+
if (!session) return c.json({ error: 'Unauthorized' }, 401);
|
|
115
|
+
c.set('session', session);
|
|
116
|
+
},
|
|
117
|
+
beforeWrite({ c, body }) {
|
|
118
|
+
if (c.get('session')?.role !== 'admin') {
|
|
119
|
+
return c.json({ error: 'Forbidden' }, 403);
|
|
120
|
+
}
|
|
121
|
+
if (body) body.updatedAt = new Date().toISOString();
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
hooks: {
|
|
125
|
+
beforeCreate({ body }) {
|
|
126
|
+
body.createdAt ??= body.updatedAt;
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Resource hook order is deterministic:
|
|
133
|
+
|
|
134
|
+
1. `beforeRequest`
|
|
135
|
+
2. `beforeWrite` for `create`, `patch`, `put`, or `delete`
|
|
136
|
+
3. matching global method hook
|
|
137
|
+
4. matching resource method hook
|
|
138
|
+
5. @async/db operation
|
|
139
|
+
|
|
140
|
+
Any hook can return a Hono response to short-circuit the request. Write hooks can mutate `body` before @async/db validates and writes it.
|
|
141
|
+
Registered operation routes run `lifecycleHooks.beforeRequest` before operation
|
|
142
|
+
execution with `method: 'operation'` and the operation `ref`. They do not run
|
|
143
|
+
resource write or resource method hooks.
|
|
144
|
+
When tracing is enabled, hook phases and short-circuit responses are included in
|
|
145
|
+
the request trace event without recording request or response bodies.
|
|
146
|
+
|
|
147
|
+
Registered operations mount at `POST {prefix}/operations/:ref` when
|
|
148
|
+
`db.config.operations.enabled` is true. Set `operations: false` for a REST-only
|
|
149
|
+
mount, `operations: true` to explicitly use global config, or pass a local
|
|
150
|
+
registry/resolver when a Hono app owns a custom build step:
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
registerDbRoutes(app, db, {
|
|
154
|
+
prefix: '/api/db',
|
|
155
|
+
operations: {
|
|
156
|
+
registry: generatedOperations.operations,
|
|
157
|
+
acceptRefs: 'ref',
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
See [examples/hono-auth](../examples/hono-auth/README.md) for a runnable Hono app with bearer-token auth.
|
|
163
|
+
|
|
164
|
+
For guidance on moving local `/db/*` prototype routes to `/api/db/*` or
|
|
165
|
+
`/api/*` production namespaces, registered operation refs, and locked-down
|
|
166
|
+
route exposure, see the
|
|
167
|
+
[Prototype To Production REST Guide](./prototype-to-production.md).
|
|
168
|
+
|
|
169
|
+
## Hono And SQLite Starter Generation
|
|
170
|
+
|
|
171
|
+
When fixtures and schemas have settled enough to graduate toward a real database API, generate a Hono starter:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
async-db generate hono
|
|
175
|
+
async-db generate hono --api rest,graphql --out ./server
|
|
176
|
+
async-db generate hono --api none --app module
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The default output is `./db-api` with REST routes, a portable repository interface, a `node:sqlite` adapter, validators, and an initial SQL migration.
|
|
180
|
+
|
|
181
|
+
Generated standalone apps are TypeScript-first and target Node.js `>=22.13` because SQLite output uses `node:sqlite`.
|
|
182
|
+
|
|
183
|
+
The main package stays dependency-light. Generated apps declare their own `hono`, `@hono/node-server`, `typescript`, and `tsx` dependencies.
|
|
184
|
+
|
|
185
|
+
Generation fails on schema errors and, by default, on schema warnings so production starter code only uses declared schema fields. Pass `--allow-warnings` only when you intentionally want to generate with warning diagnostics.
|
|
186
|
+
|
|
187
|
+
## Optional Runtime Hono/SQLite
|
|
188
|
+
|
|
189
|
+
Apps can also use optional runtime exports directly:
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
import { Hono } from 'hono';
|
|
193
|
+
import { createDbHonoApp } from '@async/db/hono';
|
|
194
|
+
|
|
195
|
+
const app = new Hono();
|
|
196
|
+
app.route('/api', await createDbHonoApp({
|
|
197
|
+
dbDir: './db',
|
|
198
|
+
storage: {
|
|
199
|
+
kind: 'sqlite',
|
|
200
|
+
file: './data/app.sqlite',
|
|
201
|
+
},
|
|
202
|
+
api: ['rest'],
|
|
203
|
+
}));
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
These integrations are opt-in. They should not make `hono`, `@hono/node-server`, or SQLite libraries mandatory dependencies of the core package.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Production JSON Database
|
|
2
|
+
|
|
3
|
+
`@async/db/json` is the first-party file database surface for @async/db. It is for resources that should stay simple, reviewable, and file-backed while the app talks to the same @async/db API layer it would use for SQLite, Postgres, or a custom store.
|
|
4
|
+
|
|
5
|
+
The product split is:
|
|
6
|
+
|
|
7
|
+
- `@async/db` owns the app-facing data layer: schemas, generated types, clients, REST/GraphQL metadata, registered operations, and store switching.
|
|
8
|
+
- `@async/db/json` owns the simple JSON file database surface: JSON store capability metadata and safe JSON state-file helpers.
|
|
9
|
+
|
|
10
|
+
JSON controls the app. Databases record the app.
|
|
11
|
+
|
|
12
|
+
## Good Production Fits
|
|
13
|
+
|
|
14
|
+
Use the JSON store for small low-write resources that are naturally files:
|
|
15
|
+
|
|
16
|
+
- app settings
|
|
17
|
+
- feature flags and rollout rules
|
|
18
|
+
- navigation, labels, and UI configuration
|
|
19
|
+
- CMS/content records, docs metadata, and templates
|
|
20
|
+
- prompt templates and model/provider defaults
|
|
21
|
+
- plan, pricing, and entitlement definitions
|
|
22
|
+
- policy rules and permission maps
|
|
23
|
+
- seed data, demo data, fixtures, mocks, and test baselines
|
|
24
|
+
|
|
25
|
+
These are control-plane resources. They are valuable in production when they stay easy to review, snapshot, diff, and promote between environments.
|
|
26
|
+
|
|
27
|
+
See [examples/production-json](../examples/production-json/README.md) for a runnable feature flags and app settings example that keeps JSON as the store while browser traffic uses registered operation refs.
|
|
28
|
+
|
|
29
|
+
## Hard Limits
|
|
30
|
+
|
|
31
|
+
Do not use the JSON store as the primary production store for:
|
|
32
|
+
|
|
33
|
+
- chat messages, activity feeds, analytics events, or logs
|
|
34
|
+
- payments, ledgers, balances, inventory counters, or booking availability
|
|
35
|
+
- high-write user data or large searchable datasets
|
|
36
|
+
- data written by multiple app instances at the same time
|
|
37
|
+
- multi-region writes or cross-process transactional workflows
|
|
38
|
+
- compliance-heavy records that require database-level audit, retention, or access controls
|
|
39
|
+
|
|
40
|
+
The default JSON store writes complete resource files under `.db/state`. Writes are atomic at the file/resource level and queued in-process, but that is not the same as a database transaction, cross-process lock, query planner, or replicated storage system.
|
|
41
|
+
|
|
42
|
+
Treat 1,000 collection records as a review point. `async-db doctor` already warns when a JSON-backed collection has more than 1,000 seed records without index metadata. For fast-changing or query-heavy collections, graduate the resource before users depend on it.
|
|
43
|
+
|
|
44
|
+
If a JSON state file is corrupt or only partially recoverable, `@async/db/json` reports `JSON_STATE_INVALID` with the file path and parser message. Restore that file from a known-good snapshot, delete it only when rehydrating from seed data is safe, or fix the JSON syntax before restarting the app.
|
|
45
|
+
|
|
46
|
+
## Production API Boundary
|
|
47
|
+
|
|
48
|
+
Do not expose local `async-db serve` as an unauthenticated public database API.
|
|
49
|
+
|
|
50
|
+
For production-facing traffic:
|
|
51
|
+
|
|
52
|
+
1. Move app routes to `/api/db/*` or `/api/*`.
|
|
53
|
+
2. Register stable operations for browser-facing reads and writes.
|
|
54
|
+
3. Generate client-safe operation refs.
|
|
55
|
+
4. Use `server.expose.rest: 'registered-only'` when raw REST should be blocked.
|
|
56
|
+
5. Add app-owned auth, authorization, rate limits, and monitoring around the mounted API.
|
|
57
|
+
|
|
58
|
+
The browser should call the data contract, not the JSON files. With the built-in operation system, that means calling generated operation refs:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
const flags = await db.query(operationRefs.operations.ListFeatureFlags.ref);
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The operation template can read JSON today and later point at a SQLite, Postgres, Redis, or custom-backed resource while the client call stays the same. App-owned servers can also wrap the operation route with auth, rate limits, policy checks, and flag evaluation before returning a client-safe result.
|
|
65
|
+
|
|
66
|
+
## Public JSON Helpers
|
|
67
|
+
|
|
68
|
+
Use `@async/db/json` when app or tooling code needs to inspect the built-in JSON database surface directly:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import {
|
|
72
|
+
jsonStoreCapabilities,
|
|
73
|
+
jsonStatePathForResource,
|
|
74
|
+
readJsonState,
|
|
75
|
+
writeJsonState,
|
|
76
|
+
} from '@async/db/json';
|
|
77
|
+
|
|
78
|
+
if (jsonStoreCapabilities.production === 'small-local') {
|
|
79
|
+
const file = jsonStatePathForResource({ stateDir: './.db' }, 'settings');
|
|
80
|
+
const settings = await readJsonState(file, {});
|
|
81
|
+
await writeJsonState(file, settings);
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Most app code should still use `openDb()`, `createDbClient()`, and registered operations. The JSON helpers are for tooling, diagnostics, migrations, exports, and advanced local workflows.
|
|
86
|
+
|
|
87
|
+
## Mixed Stores
|
|
88
|
+
|
|
89
|
+
Keep JSON for control-plane resources and graduate data-plane resources independently:
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
export default {
|
|
93
|
+
stores: {
|
|
94
|
+
default: 'json',
|
|
95
|
+
appDb: postgresStore({ client }),
|
|
96
|
+
},
|
|
97
|
+
resources: {
|
|
98
|
+
featureFlags: { store: 'json' },
|
|
99
|
+
settings: { store: 'json' },
|
|
100
|
+
activityEvents: { store: 'appDb' },
|
|
101
|
+
orders: { store: 'appDb' },
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The app-facing contract stays in @async/db. Frontend code calls the same generated types, REST resources, or registered operation refs while each resource chooses the storage boundary that fits its write rate and operational risk.
|
|
107
|
+
|
|
108
|
+
For the full resource-by-resource migration path, see [Resource Graduation And Mixed Stores](./store-graduation.md).
|
|
109
|
+
|
|
110
|
+
## Readiness Checklist
|
|
111
|
+
|
|
112
|
+
- Run `async-db doctor --production` before treating JSON-backed resources as production data. Use `async-db check --strict --production` when warnings should fail CI.
|
|
113
|
+
- Use explicit schemas for production JSON resources.
|
|
114
|
+
- Prefer `schema.unknownFields: 'error'` when drift should fail.
|
|
115
|
+
- Keep JSON-backed writes low-volume and single-writer.
|
|
116
|
+
- Snapshot or back up `.db/state` before deployments and migrations.
|
|
117
|
+
- Practice recovery for `JSON_STATE_INVALID` by restoring a known-good state snapshot.
|
|
118
|
+
- Keep browser traffic behind registered operations when exposing production APIs.
|
|
119
|
+
- Return evaluated feature flags or policy decisions to the browser, not sensitive rule internals.
|
|
120
|
+
- Move a resource to SQLite, Postgres, or a custom store when write rate, size, query needs, or concurrency exceed file-backed JSON limits.
|