@async/db

serve

Use REST as the local app contract. Keep dev tools on their own route base.

The server starts from fixture-backed resources, exposes readable REST routes, supports local writes, and keeps viewer, schema, manifest, import, batch, log, GraphQL, and operation routes explicit. File-like suffixes such as .json and .md choose response formats for the same shaped data.

/db/*

App-facing REST alias for fixture-like reads and writes.

/__db/*

Viewer, schema, manifest, import, batch, logs, events, and scoped REST.

/graphql

Optional GraphQL route for local queries and mutations.

endpoint map

Route families

Defaults shown for 127.0.0.1:7331.

GET /__db

Built-in viewer shell.

GET /__db/schema

Normalized schema metadata.

GET /__db/manifest[.json|.html|.md]

Viewer/API manifest in negotiated or explicit format.

GET /__db/events

Live event stream for viewer refreshes.

GET /__db/log

Runtime log and request trace output.

POST /__db/import

CSV import endpoint used by the viewer.

POST /__db/batch

Sequential REST batch execution.

/__db/rest/*

Scoped REST when the app data alias is disabled or not desired.

/db/*

App-facing REST alias controlled by server.dataPath.

POST /graphql

GraphQL subset endpoint.

POST /__db/operations/:ref

Allowlisted registered operation execution.

collections

Resource CRUD endpoints

GET/db/users.jsonList the collection.
GET/db/users/u_1.jsonRead one record by id.
POST/db/usersCreate a record with a JSON body.
PATCH/db/users/u_1Merge fields into an existing record.
DELETE/db/users/u_1Delete one record.

documents

Singleton endpoints

GET/db/settings.jsonRead the document.
GET/db/settings.mdRender the same data as Markdown.
GET/db/settings.htmlRender a browser-readable view.
PUT/db/settingsReplace the document.
PATCH/db/settingsMerge fields into the document.

formats

What a suffix means on a REST route

It selects an output format

Adding .json, .md, .html, or a registered custom extension to a GET route renders the same resource after REST shaping. It does not fetch a different source file.

Query shaping happens first

select, expand, offset, and limit run before the renderer. /db/users.md?select=id,name is Markdown for the selected fields.

Extensionless reads negotiate

GET /db/users uses the configured default or a registered Accept media type. Unsupported Accept values fall back to the default format.

Writes stay extensionless

Use POST /db/users, PATCH /db/users/u_1, PUT /db/settings, and PATCH /db/settings for JSON request bodies. Suffixes are for read rendering.

Source file extensions and REST response extensions are separate. Built-in source readers load db/*.json, db/*.jsonc, and db/*.csv. Built-in response formats are .json, .html, and .md. Add source formats through sources.readers; add REST response formats through rest.formats.

curl

REST examples

curl http://127.0.0.1:7331/db/users.json
curl 'http://127.0.0.1:7331/db/users.json?select=id,name&offset=0&limit=20'
curl 'http://127.0.0.1:7331/db/users.json?id=u_1&select=id,name'
curl http://127.0.0.1:7331/db/users/u_1.json
curl http://127.0.0.1:7331/db/users/u_1.md
curl http://127.0.0.1:7331/db/settings.html

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"}'

curl -X PATCH http://127.0.0.1:7331/db/users/u_2 \
  -H 'content-type: application/json' \
  -d '{"name":"Rear Admiral Grace Hopper"}'

curl -X DELETE http://127.0.0.1:7331/db/users/u_2

batch + scoped rest

Same contract, different base

curl http://127.0.0.1:7331/__db/rest/users.json

curl -X POST http://127.0.0.1:7331/__db/batch \
  -H 'content-type: application/json' \
  -d '[
    { "method": "GET", "path": "/db/users.json" },
    {
      "method": "PATCH",
      "path": "/db/settings",
      "body": { "theme": "dark" }
    }
  ]'

curl -X POST http://127.0.0.1:7331/__db/operations/users.get \
  -H 'content-type: application/json' \
  -d '{"params":{"id":"u_1"}}'

custom extensions

Add output formats in config

A custom format adds routes like /db/users.yaml and media negotiation for extensionless routes. Use object syntax when the format also needs manifest support.

import { defineConfig } from '@async/db/config';

export default defineConfig({
  rest: {
    formats: {
      default: 'json',
      yaml: {
        mediaTypes: ['application/yaml', 'text/yaml'],
        contentType: 'application/yaml; charset=utf-8',
        render({ data }) {
          return stringifyYaml(data);
        },
        renderManifest({ data }) {
          return stringifyYaml(data);
        },
      },
    },
  },
});

custom sources

Add input formats separately

If a project wants to load fixtures from a new file type, register a source reader. That changes how Async DB discovers input files; it does not automatically add a matching REST suffix.

import { defineConfig } from '@async/db/config';

export default defineConfig({
  sources: {
    readers: [
      {
        name: 'ndjson-data',
        match({ file }) {
          return file.endsWith('.ndjson');
        },
        async read({ basename, readText }) {
          const text = await readText();
          return {
            kind: 'data',
            resourceName: basename,
            format: 'ndjson',
            data: text
              .trim()
              .split('\\n')
              .filter(Boolean)
              .map((line) => JSON.parse(line)),
          };
        },
      },
    ],
  },
});
Example: db/users.ndjson can become the users resource, while GET /db/users.md still means “render users as Markdown.”

configuration

Move and lock down routes deliberately

export default defineConfig({
  server: {
    apiBase: '/__db',
    dataPath: '/db',
    host: '127.0.0.1',
    port: 7331,
  },
});
export default defineConfig({
  server: {
    expose: {
      rest: 'registered-only',
      graphql: false,
      viewer: 'dev',
      schema: 'dev',
      manifest: 'dev',
    },
  },
});

Set server.dataPath: false when an app should not receive the /db alias. The same REST resources remain available under /__db/rest for local tools, and standalone serve keeps root convenience routes for development.