Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

199 Commits

Repository files navigation

@async/db

@async/db gives frontend teams a gradual path from mock JSON to production data contracts. Drop JSON files in db/, infer schema metadata, serve REST, GraphQL, and a local data explorer, then move persistence per resource without rewriting frontend data access.

Use it to:

  • Start from editable JSON, JSONC, or CSV data files in db/.
  • Infer schema contracts and generate TypeScript types from data files and schemas.
  • Model resource identity with idField or compound identity.fields, plus log and bytes metadata.
  • Serve local REST routes, GraphQL, and a lightweight data explorer while the backend contract is still forming.
  • Upgrade persistence per resource without rewriting frontend data access.
  • Emit schema metadata for admin, CMS, or form-building screens.

@async/db is not a universal key/value driver layer; storage is one boundary inside the JSON-to-contract workflow.

30-Second Start

pnpm add @async/db
pnpm exec async-db init
pnpm exec async-db serve

Open the local data explorer at http://127.0.0.1:7331/__db and call GET /db/users.json.

No config file is required. init writes a starter JSON file, .gitignore entry for .db/, optional package scripts, and runs the first sync. Prefer a manual one-file start?

mkdir -p db
printf'%s\n''[{"id":"u_1","name":"Ada Lovelace","email":"ada@example.com"}]'> db/users.json
pnpm exec async-db serve

serve syncs on startup and watches db/ for changes.

Deno Quick Start

For a Deno-only local project, use Deno's npm package support and let init write deno.json tasks instead of package scripts:

deno run --allow-read=. --allow-write=. --allow-sys=hostname npm:@async/db init --workflow deno --template data-first
deno task db:serve

After deno.json exists, pass CLI arguments directly through the task, without npm or pnpm -- forwarding:

deno task db init --workflow deno --template data-first
deno task db:sync
deno task db:validate

Minimum Deno permissions are --allow-read=. --allow-write=. --allow-sys=hostname for sync and validation, plus --allow-net=127.0.0.1 for local serve.

File Map

FilesPurpose
db/*.json, db/*.jsonc, db/*.csvData files
db/*.schema.json, db/*.schema.jsonc, db/*.schema.jsOptional stricter schema contracts
db.schema.jsOptional root schema registry for all resources
.db/state/*Generated writable JSON store state
.db/schema.generated.json, .db/types/index.d.tsGenerated metadata and types

Install

pnpm add @async/db

Add package scripts for the CLI commands you run often:

{
"scripts": {
"db": "async-db",
"db:sync": "async-db sync",
"db:serve": "async-db serve",
"db:types": "async-db types"
}
}

Deno projects can skip package.json and use a generated deno.json instead:

{
"nodeModulesDir": "auto",
"tasks": {
"db": "deno run --allow-read=. --allow-write=. --allow-sys=hostname npm:@async/db@0.15.0",
"db:sync": "deno task db sync",
"db:types": "deno task db types",
"db:validate": "deno task db schema validate",
"db:serve": "deno run --allow-read=. --allow-write=. --allow-sys=hostname --allow-net=127.0.0.1 npm:@async/db@0.15.0 serve"
}
}

The package import name is @async/db. Helpers are available from @async/db/config, @async/db/schema, @async/db/client, and the compatibility JSON engine subpath @async/db/json. The standalone @async/json package owns direct JSON file/folder database usage.

Five-Minute Start

Create a JSON file:

mkdir -p db
cat > db/users.json <<'JSON'[ { "id": "u_1", "name": "Ada Lovelace", "email": "ada@example.com" }]JSON

Sync generated metadata, types, and runtime state:

pnpm run db:sync

Start the local server:

pnpm run db:serve

Open the local data explorer at http://127.0.0.1:7331/__db.

Call the REST API:

curl http://127.0.0.1:7331/db/users.json

Create a local record:

curl -X POST http://127.0.0.1:7331/db/users \
-H 'content-type: application/json' \
-d '{"id":"u_2","name":"Grace Hopper","email":"grace@example.com"}'

Default sync output:

.db/schema.generated.json
.db/types/index.d.ts
.db/state/users.json

Local responses include a small 30-100ms mock delay by default so loading states are visible. It is skipped automatically when NODE_ENV=production. Disable it locally when you want immediate responses:

exportdefault{mock: {delay: false},};

See docs/getting-started.md for the expanded walkthrough, including async-db init --template schema-first and --template source-file.

Defaults

BehaviorDefault
Source data filesRead from ./db
App data routesExposed under /db, such as GET /db/users.json
Runtime writesGo to the JSON store under .db/state
Local server127.0.0.1:7331
RESTEnabled
GraphQL / FalcorDisabled until you opt in
Schema driftWarn on unknown fields

Add Schema When It Pays For It

Data-first JSON files are enough until the shape matters:

pnpm run db -- schema infer users
pnpm run db -- schema infer users --out db/users.schema.jsonc
pnpm run db -- schema validate

Add db/users.schema.json, db/users.schema.jsonc, or db/users.schema.js when you need stricter behavior, defaults, relations, or Standard Schema validators.

See docs/concepts.md and docs/data-files-and-schemas.md.

Common Commands

pnpm run db -- sync
pnpm run db -- types
pnpm run db -- schema validate
pnpm run db -- doctor
pnpm run db -- create users '{"id":"u_2","name":"Grace Hopper","email":"grace@example.com"}'
pnpm run db -- serve
pnpm run db -- init --template data-first
pnpm run db -- init --template schema-first
pnpm run db -- init --template source-file

See docs/package-api.md for CLI and package export details.

Going To Production

The default path stays small on purpose: every resource is born a draft, and async-db promote <resource> moves it to production — pinning the seed, capturing the schema, and turning on write-ahead-log durability (--fsync always|everysec|no). async-db status shows each resource's phase; see docs/shape-is-the-contract.md for the full story. When a resource gets serious, follow the ladder:

TierWhenNext step
0 — JSON filesPrototype with JSON in db/You are here after init or serve
1 — ContractsShape, defaults, and types matterAdd schema files and committed generated types
2 — Hardened APIBrowser or external clients consume dataRegistered operations, server.expose, contracts, doctor --production
3 — Mixed storesJSON is no longer the right persistencePer-resource store graduation to SQLite, Postgres, or custom stores

Production topics:

The built-in JSON store is production-appropriate only for file-suitable resources: app settings, feature flags, content, templates, and other small low-write data with a single writer. Writes are fsync-durable atomic file replaces guarded by a per-resource cross-process lock; durability: 'versioned' keeps undoable per-write history with async-db backup/restore on top; REST supports ETag/If-Match/If-None-Match; and GET /__db/health, server.authorize, per-resource audit trails, and AES-256-GCM encryption at rest cover the operational basics. Keep high-write user data, chat, analytics, ledgers, and compliance-heavy records in SQLite, Postgres, or another app-owned store.

@async/db is not an auth layer, an ORM, or a hosted database service. Put production traffic behind registered operations, app-owned auth, rate limits, and observability.

Examples

Run pnpm run examples to open the grouped examples index, or sync and serve one example directly:

pnpm run db -- sync --cwd ./examples/basic
pnpm run db -- serve --cwd ./examples/basic

Start here

ExampleWhat it shows
examples/data-firstPlain JSON files before schemas exist
examples/deno-basicDeno-only tasks through npm:@async/db
examples/basicShortest schema-backed workflow
examples/schema-firstSchema-only resources and empty seed records
examples/csvCSV inference and mirror refreshes

Core workflows

ExampleWhat it shows
examples/relationsRelation metadata, expand, nested select
examples/rest-clientcreateDbClient, REST batching
examples/diagnosticsFile-specific warnings without breaking valid resources
examples/computed-fieldsComputed field patterns across several models
examples/content-collectionsDocs/blog folders as static content collections
examples/standard-schemaStandard Schema validators with Async DB overlays
examples/schema-manifestCommitted schema metadata for admin/CMS UI
examples/schema-uiManifest-driven SSR admin templates
examples/advancedMixed mode, defaults, nested objects

Production and app patterns

ExampleWhat it shows
examples/production-jsonFeature flags and settings behind registered operations
examples/hono-authOptional Hono auth and write hooks
examples/cms-json-publishApp-owned CMS publish flow over branches
examples/free-plan-upgradeTenant resource graduation from JSON to another store
examples/local-web-appLoopback app state saved directly to db/*.json

Each example README is the runnable authority for that example.

Docs Map

TaskRead
Start a projectdocs/getting-started.md
Understand the product storydocs/shape-is-the-contract.md
Build a docs site / use MDXdocs/docs-and-mdx.md
Understand the modeldocs/concepts.md
Author data files and schemasdocs/data-files-and-schemas.md
Manage generated outputdocs/generated-files.md
Configure @async/dbdocs/configuration.md
Use JSON in production safelydocs/json-production.md
Serve local data and explore it locallydocs/server-and-viewer.md
Graduate REST prototypesdocs/prototype-to-production.md
Use the package API or CLIdocs/package-api.md
Review public API surfaceAPI_SURFACE.md
Integrate with Vite, Hono, or SQLitedocs/integrations.md

For the full product behavior and acceptance model, see SPEC.md.

About

Data-first local database toolkit from JSON fixtures to generated types, local APIs, writable stores, and production persistence.

Topics

Resources

Contributing

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages