Typed collections

Base collections

An authenticated administrator can create, inspect, list, change and delete collection metadata through the admin API and dashboard. Application clients then work with the records stored by that schema.

Create in the dashboard

Open Collections, name the collection, and use Add field for every field the schema needs. Each row defines its name, type, required state and uniqueness. Trestle creates the whole collection in one operation. The unfinished draft is kept in the browser while you visit other dashboard sections or reload the page, and is cleared only after successful creation.

Admin API

GET    /admin/v1/collections
POST   /admin/v1/collections
GET    /admin/v1/collections/{name}
PATCH  /admin/v1/collections/{name}
DELETE /admin/v1/collections/{name}

Reads require a live administrator session. Mutations additionally require the current session's X-Trestle-CSRF token and same-origin request.

Read collection metadata with fetch

The administrator cookie is HttpOnly, so browser JavaScript cannot read it. Use credentials: "same-origin" and let the browser attach it. This example belongs in a same-origin administration tool, not in a public application frontend.

async function listCollections() {
  const response = await fetch("/admin/v1/collections", {
    credentials: "same-origin",
    headers: { Accept: "application/json" },
  });

  const body = await response.json();
  if (!response.ok) {
    throw new Error(body.error?.message ?? "Could not load collections");
  }

  return body.items;
}

const collections = await listCollections();
for (const collection of collections) {
  console.log(collection.name, collection.kind);
}

The list response is an object with an items array. Checking response.ok before using it keeps authorization and server errors from being mistaken for valid collection data.

Create a collection with fetch

First read the current administrator session. That response rotates and returns the CSRF token required by the next mutation. Send the token in the header and keep the cookie attached with credentials.

async function createIssuesCollection() {
  const sessionResponse = await fetch("/admin/v1/session", {
    credentials: "same-origin",
    headers: { Accept: "application/json" },
  });
  const session = await sessionResponse.json();

  if (!sessionResponse.ok || !session.authenticated) {
    throw new Error("Administrator sign-in required");
  }

  const response = await fetch("/admin/v1/collections", {
    method: "POST",
    credentials: "same-origin",
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
      "X-Trestle-CSRF": session.csrfToken,
    },
    body: JSON.stringify({
      name: "issues",
      fields: [
        { name: "title", type: "text", required: true, unique: false },
        { name: "priority", type: "number", required: false, unique: false },
      ],
    }),
  });

  const body = await response.json();
  if (!response.ok) {
    throw new Error(body.error?.message ?? "Could not create collection");
  }
  return body;
}

Do not put administrator credentials, cookies or CSRF tokens into application code. Normal web applications should receive an application-user token or use a narrowly scoped service credential from a trusted backend, then call the records API described on the Records page.

Create metadata

{
  "name": "issues",
  "fields": [
    {"name":"title","type":"text","required":true,"unique":false},
    {"name":"priority","type":"number","required":false,"unique":false}
  ]
}

Keys and relations

Every physical collection table has a generated _id TEXT PRIMARY KEY. SQLite foreign-key enforcement is enabled for every connection. Relation fields currently store record IDs as text; target-collection and delete/update policy metadata will be required before Trestle can generate physical foreign-key constraints for them.