4.4 The data service: schema-validated JSON records

data is a JSON record store. Like file, it implements the store pattern (3.3), so the verbs and listings are the familiar contract — but its containers are datasets and its children are JSON records, optionally validated against a schema.

Mounting it

{ "path": "/data", "service": "data",
  "config": { "access": { "read": "all", "write": "A" },
              "enforceSchema": true } }

enforceSchema is optional (default off). With it on, writes — and the results of PATCHes — are validated against the dataset's schema.

The standard server's default data backend is durable and file-backed under dataRoot. Use store.adapter: "builtin:mem" only when you deliberately want ephemeral data; 4.7 covers backend selection and per-mount isolation.

Datasets and records

  • The mount root lists datasets, each shown as a container ("dir": true).
  • GET /<dataset>/ lists the record keys in that dataset, plus a fixed child .schema.json when a schema is installed.
  • GET /<dataset>/<key> returns one record.
curl.exe -X PUT http://127.0.0.1:3100/data/people/ada `
  -H "Content-Type: application/json" --data '{ "name": "Ada", "role": "pioneer" }'
curl.exe http://127.0.0.1:3100/data/people/        # → keys in "people"
curl.exe http://127.0.0.1:3100/data/people/ada     # → the record + ETag

Record ETags are content hashes, so an unchanged record keeps its ETag and conditional GETs (4.2) work without extra bookkeeping.

What data adds beyond the store contract

The data service declares the schema, patch, echo, and confirm-delete facets:

Request Behavior
GET /<dataset>/<key> Record; when a schema exists, Content-Type: application/json; schema="…/.schema.json" and a Link: …; rel="describedby"
PATCH /<dataset>/<key> RFC 7386 JSON merge patch; the merged result is re-validated and returned (patch facet)
GET / PUT /<dataset>/.schema.json Read or install the dataset schema (4.5)
POST /<dataset>/<key> Upsert and return the stored representation (echo facet)
DELETE /<dataset>/?confirm=<dataset> Dataset delete always requires the confirm token

What it deliberately can't do

A store cannot filter by field — listings page, they don't query. To select records by content you use a query mount (Part 6) or a pipeline (Part 7) over the data store. This keeps the store simple and pushes querying to a surface designed for it.

The next section goes deep on schemas, validation errors, and merge PATCH.


Previous: 4.3 Static-site & SPA hosting · Manual home · Next: 4.5 Schemas, validation, merge PATCH →