Skip to main content

Protocol Schema

The full JSON schema of a protocol file, with every key explained.

Top level

{
"<database-alias>": {
"database": "<actual-db-name>",
"entities": {
"<entity-alias>": { ... }
}
}
}
KeyTypeRequiredPurpose
<database-alias>objectyesTop-level key. The name you'll use in queries.
databasestringyesActual database name in storage
entitiesobjectyesMap of entity-alias → entity definition

Entity

{
"table": "<actual-table-name>",
"fields": { "<query-name>": "<column-name>", ... },
"relations": { "<relation-name>": { ... }, ... },
"context": { "<context-name>": "<onql-fragment>", ... }
}
KeyTypeRequiredPurpose
tablestringyesActual table name
fieldsobjectyesColumn mapping
relationsobjectnoFK relationships
contextobjectnoAuto-scoping rules

Relation

{
"type": "oto | otm | mto | mtm",
"entity": "<target-entity>",
"prototable": "<target-entity>",
"fkfield": "<fk-spec>",
"through": "<junction-table>"
}
KeyTypeRequiredPurpose
typeenumyesOne of oto, otm, mto, mtm
entitystringyesTarget entity alias
prototablestringyesTarget entity alias (same as entity in 99% of cases)
fkfieldstringyesForeign key spec
throughstringonly mtmJunction table

fkfield format

TypeFormat
oto, mtolocal_col:remote_col
otmlocal_col:remote_col
mtmlocal:through_local:through_remote:remote

Context

{
"<context-name>": "<onql-query-fragment>"
}

The fragment is a regular ONQL query (without a projection) that returns the rows visible to that context. Use $1, $2, ... for parameters.

Example — full file

{
"blog": {
"database": "blog",
"entities": {
"posts": {
"table": "posts",
"fields": { "id": "id", "title": "title", "body": "body", "author_id": "author_id" },
"relations": {
"author": { "type": "mto", "entity": "users", "prototable": "users", "fkfield": "author_id:id" }
},
"context": {
"public": "blog.posts[published_at != null]",
"admin": "blog.posts"
}
},
"users": {
"table": "users",
"fields": { "id": "id", "name": "name", "email": "email" }
}
}
}
}