Collections

Status: Implemented (Milestone 3)

Collections are dynamic database tables defined in JSON. Bakend persists the schema, generates SQLite tables, and validates record data.

Defining a Collection

Place one definition per file in collections/ next to bakend.json:

{
  "name": "posts",
  "fields": [
    { "name": "title", "type": "string", "required": true },
    { "name": "content", "type": "text" }
  ]
}

Files are loaded alphabetically on bak start. If a collection already exists with the same definition, it is skipped.

Relations: the target collection must be defined first. Name files so dependencies load first (e.g. users.json before posts.json).

Programmatic API

const meta = collections.create({
  name: "posts",
  fields: [
    { name: "title", type: "string", required: true },
    { name: "content", type: "text" },
  ],
});

Available on StartResult.collections after bak start.

Field Types

TypeDescription
stringShort text
textLong text
integerWhole number
floatDecimal number
booleantrue or false
datetimeISO-8601 string
jsonJSON object or array
relationReference to another collection (requires collection property)
fileFile id from storage upload API (validated against _files)

System Fields

Every collection automatically includes:

  • id — generated as rec_<uuid>
  • createdAt
  • updatedAt

You do not define these in your schema.

Validation Rules

RuleApplies toDescription
requiredAll typesField must be present and non-empty on create
minstring, text, integer, floatMinimum length or value
maxstring, text, integer, floatMaximum length or value
regexstring, textMust match pattern
uniqueAll except jsonValue must be unique in the collection

Validate record data before insert/update:

const result = collections.validateRecord("posts", { title: "Hello" }, "create");
if (!result.valid) {
  console.log(result.errors);
}

Naming Rules

  • Collection and field names: ^[a-z][a-z0-9_]*$
  • Cannot start with _
  • Cannot use reserved names (_bakend_meta, _collections, id, createdAt, updatedAt)

Field names are stored as snake_case columns in SQLite (e.g. authorIdauthor_id).

Events

Creating a collection emits system.collection.created on the Event Bus.

Record CRUD emits {collection}.created, {collection}.updated, and {collection}.deleted.

REST API

Every collection exposes CRUD endpoints automatically:

curl -X POST http://localhost:8080/api/posts \
  -H 'Content-Type: application/json' \
  -d '{"title":"Hello"}'

curl http://localhost:8080/api/posts

See REST API for the full specification.

Programmatic access is also available via StartResult.recordStore after bak start.

Schema sync

Sync collections/*.json with the database:

bak migrate status
bak migrate apply
bak migrate export

See RFC-0012 Migration Engine.

What Is Not Available Yet

FeatureStatus
Filtering, sorting, paginationPlanned
Collection permissionsImplemented — see Authentication
File upload for file fieldsImplemented — see Storage