Ulabase

Your data

Schemas

Refuse a document that does not match: write a JSON Schema once, bind it to a collection, and every write from every client is validated on the server.

A schema says what a document must look like: which fields, of which type, which are required, which values are allowed. Bind one to a collection and every POST, PUT and PATCH is checked on the server before it is stored, whoever sends it. Your app can still validate forms to give a better error message, but the data stays clean without it.

Schemas are JSON Schema draft-07, stored in the schemas collection and managed under Schemas.

The Schemas page: each schema with its type

Write a schema

Click Create schema, choose an _id and paste the schema. This one validates a product:

{
  "_id": "product",
  "title": "Product",
  "description": "A product of the catalog",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "name":     { "type": "string", "minLength": 1 },
    "price":    { "type": "number", "minimum": 0 },
    "category": { "type": "string", "enum": ["electronics", "clothing", "food"] },
    "inStock":  { "type": "boolean" }
  },
  "required": ["name", "price", "category"]
}

The _id is how you will refer to it. title and description show in the list. The rest is JSON Schema; these are the keywords you will use most:

Keyword What it does

type

string, number, integer, boolean, object, array, null.

properties and required

The fields, and which of them must be present.

enum

The only values allowed.

minimum, maximum, minLength, maxLength, pattern

Ranges, lengths, and a regular expression for strings.

items

The schema of each element of an array.

additionalProperties: false

Refuse fields that are not in properties.

if, then, else

A rule that depends on another field.

Setup BSON Types adds a schema that describes MongoDB’s own types, so yours can declare a date field as {"$ref": "bson#/date"}. Or declare a date field inline as {"type": "object", "properties": {"$date": {"type": "number"}}}: inside a schema $date is written $date, and a document sends the date as {"$date": <epoch millis>}, which is also what a permission’s @now stores.

The editor checks the JSON as you type. The full vocabulary is in the JSON Schema draft-07 specification.

Bind it to a collection

A schema does nothing until a collection uses it. On the Collections page, click the gear of the collection, choose the schema under Schema, and click Save.

One schema can serve several collections. Editing it affects all of them, for writes from then on: documents already stored are not checked again.

What your app sees

A document that does not match is refused with 400 Bad Request and a body that says why:

{
  "http status code": 400,
  "message": "Document validation failed",
  "exception": { "message": "required key [customerId] not found" }
}

Show that message to the user, or map it to your form. A PATCH is validated on the document as it would be after the change, so a partial update cannot leave a document invalid.

From a script

Operation API

List

GET /schemas

Create

POST /schemas with the schema as the body

Update

PUT /schemas/<id> with the whole schema: a schema is never patched

Delete

DELETE /schemas/<id>

Bind to a collection

PATCH /<collection> with { "jsonSchema": { "schemaId": "<id>" } }

Deleting a schema does not unbind it: a collection that still references it refuses every write until you bind another or remove the reference. With ulabase, schemas and their bindings are part of the setup file.