Field types
Every field builder of locosdk/schema, its options, its TypeScript type, its SQLite column and its MCP input type.
Fields are declared in schema.ts with builders from locosdk/schema. The options are PocketBase's field JSON under PocketBase's own names, minus id, name and type. How a schema fits together: Schema as code.
Types at a glance#
| builder | TypeScript | SQLite column | MCP input |
|---|---|---|---|
text() | string | TEXT DEFAULT '' NOT NULL | string |
email(), url(), editor() | string | TEXT DEFAULT '' NOT NULL | string |
number() | number | NUMERIC DEFAULT 0 NOT NULL | number, integer when onlyInt, min and max kept |
bool() | boolean | BOOLEAN DEFAULT FALSE NOT NULL | boolean |
date() | string | TEXT DEFAULT '' NOT NULL | string YYYY-MM-DD HH:MM:SS.sssZ |
autodate() | string | TEXT DEFAULT '' NOT NULL | never an input |
select(values) | one of values, or '' unless required | TEXT DEFAULT '' NOT NULL | an enum of the values |
select(values, { maxSelect: n }), n > 1 | an array of the values | JSON DEFAULT '[]' NOT NULL | an array of the enum |
relation(target) | string, a record id | TEXT DEFAULT '' NOT NULL | a record id of the target |
relation(target, { maxSelect: n }), n > 1 | string[] | JSON DEFAULT '[]' NOT NULL | an array of ids |
file() | string, the stored name | TEXT DEFAULT '' NOT NULL | never an input: files go through the UI |
file({ maxSelect: n }), n > 1 | string[] | JSON DEFAULT '[]' NOT NULL | never an input |
json<T>() | T | null | JSON DEFAULT NULL | any |
password() | string, never output | TEXT DEFAULT '' NOT NULL | only password and passwordConfirm on an auth create |
The id column is TEXT PRIMARY KEY DEFAULT ('r'||lower(hex(randomblob(7)))) NOT NULL. Columns are sorted by name when a table is made. Dates are UTC text, '' when empty.
Options every field takes#
| option | what |
|---|---|
required | a value must be set. On a select it also drops '' from the type |
hidden | never in a response to anyone but a superuser, never in an MCP input, never readable in a client filter |
presentable | the field names a record: in relation pickers and in the journal's label |
help | a description: the schema form's hint and the MCP tool's field description |
Per type#
| builder | options |
|---|---|
text | min, max (characters), pattern (a regular expression), autogeneratePattern, primaryKey |
email, url | exceptDomains, onlyDomains |
editor | maxSize, convertURLs |
number | min, max, onlyInt |
date | min, max |
autodate | onCreate, onUpdate (the builder's default is { onCreate: true }) |
select(values) | maxSelect |
relation(target) | maxSelect, minSelect, cascadeDelete |
file | maxSelect, maxSize (bytes, 5 MB when unset), mimeTypes, protected, thumbs |
json<T> | maxSize |
password | min, max, pattern, cost (bcrypt, 0 means 10) |
geoPoint has no builder. A raw { type: 'geoPoint' } spec works, and the filter reaches geo.lon and geo.lat.
Relations#
- The target is a collection NAME.
defineSchemaresolves it to the collection id and throws on an unknown name. cascadeDelete: true: deleting the target removes its id from this field, and deletes this record when the field ends empty.required: truewithout a cascade: deleting the target is refused when it leaves this field empty.- Otherwise the target's id is removed from the field. All of it happens in one transaction.
Indexes#
indexes is a list of raw CREATE INDEX statements, PocketBase's way. A partial unique index works:
indexes: ["CREATE UNIQUE INDEX idx_clients_code ON clients (code) WHERE code != ''"],
A unique index violation answers validation_not_unique on its fields. Dropping an index from a table with rows is refused at boot: a migration does it.
System fields#
base and auth add id, created and updated. auth adds email, emailVisibility, verified, password and tokenKey, and unique indexes on email and tokenKey. Declaring one of these names in fields overrides its options. autodates picks which autodates a collection keeps.
Validation codes#
A refused value answers 400 with data.<field>: { code, message }, PocketBase's codes: validation_required, validation_min_text_constraint, validation_max_text_constraint, validation_invalid_format, validation_not_unique, validation_values_mismatch, validation_invalid_old_password and the others of PocketBase's field validators.