Skip to content

Type-Safety

TrailBase provides end-to-end type-safety from the database level, through the HTTP APIs, all the way up to the client bindings relying on JSON schemas. It’s worth noting that the JSON schema is derived directly from the database schema as the source of truth meaning that any schema change will be reflected independent of whether they were applied via the admin dashboard, sqlite3 or other means. This also means that you should regenerate your type definitions after changing the schema. We therefore recommend to integrate type generation into your build process or check the generated types in following your database migrations.

Using JSON schema and relying on off-the-shelf code generation tools, allows to keep the client-libraries very thin making it easy to integrate virtually any language in a type-safe fashion. /examples/blog provides a glimpse at using quicktype to generate type-safe TypeScript and Dart APIs.

Type-safety is the main reason why TrailBase APIs require STRICTly typed tables. By default SQLite only has a notion of “type affinity” on inserts and updates, generally allowing any data in any column.

Generating Types from JSON Schemas

The generated JSON schemas depend on two aspects:

  1. The actual database schema mapping columns and column types to fields and data types in a data structure of your target language.
  2. The specific API operation: CREATE, UPDATE, READ.

Expanding on 2., the notion of default values for columns means that data for NOT NULL columns is optional when creating a new record but guaranteed to be present on record read. UPDATEs are point updates of existing records, thus only requiring specific column values to be overridden.

Concretely, looking at /examples/blog, the data structure for inserting a new blog article is less strict than the equivalent for retrieving an existing article:

// Input data type when creating a new article record.
export interface NewArticle {
author: string;
body: string;
created?: number;
id?: string;
image?: FileUpload;
// ...
}
// Result data type when reading an article record.
export interface Article {
author: string;
body: string;
created: number;
id: string;
image?: FileUpload;
// ...
}

Nested JSON Columns

TrailBase also supports generating type-safe bindings for columns containing JSON data and enforcing a specific JSON schema, see here.