Schemas in Code

Defining schemas in code is a powerful way to manage your data structures which gives a lot of control and benefits such as revisions, reviews and reverts via Git as your data structure scales. This page provides an overview of how to define your schemas in code.

Getting Started

If you haven't yet defined your schemas in code in your project, start by creating the file (in your project's root directory) that will contain the schema definitions for your project:

Bash
mkdir schemas
touch schemas/index.ts

A schema is defined using the Schema.Record generic type from the ronin/schema package. The Schema type also provides other sub-types like Schema.Records and other advanced field types such as Schema.Blob and Schema.RichText.

Here is an example of a basic schema definition:

schemas/index.ts
import { Schema } from 'ronin/schema';
 
type Account = Schema.Record<{
  name: string;
  active: boolean;
  likes: number;
  verifiedAt: Date;
}>;
 
// It's *required* to also define the plural version of the schema
type Accounts = Schema.Records<Account>;
 
declare module 'ronin' {
  interface Schemas {
    account: Account;
    accounts: Accounts;
  }
}

In the example above, we defined a schema named Account with four fields: name, active, likes, and verifiedAt. Each field is defined using a key-value pair where the key is the slug of the field and the value is the type of the field. See all available field types in the Field Types section.

In the Schemas interface, we defined the singular and plural versions of the schema using key-value pairs where the key is the slug of the schema (singular and plural, respectively) and the value is the schema itself. The variable name of the schema will be used as the display name of the schema in the RONIN dashboard.

Once you've defined your schemas, sync them with your remote schemas by running the following command:

Bash
ronin sync

If you'd like to define more advanced field types like Blob or RichText, you can do so by just setting the type of the field to Schema.Blob or Schema.RichText respectively:

schemas/index.ts
type Account = Schema.Record<{
  avatar: Schema.Blob;
  bio: Schema.RichText;
  custom: Schema.JSON;
}>;

Field Types

The following types can be used to define fields in a schema:

Types
stringString field
numberNumber field
booleanBoolean field
DateTimestamp field
Schema.BlobBinary object field
Schema.RichTextRich text field
Schema.JSONJSON field (for storing arbitrary data)

Reference Fields

You can define the relationship of a field to another schema by just using that schema as the field type:

schemas/index.ts
import { Schema } from 'ronin/schema';
 
type User = Schema.Record<{
  name: string;
  email: string;
}>;
 
type Post = Schema.Record<{
  title: string;
  author: User;
}>;
 
type Users = Schema.Records<User>;
type Posts = Schema.Records<Post>;
 
declare module 'ronin' {
  interface Schemas {
    user: User;
    users: Users;
 
    post: Post;
    posts: Posts;
  }
}

In the example above, we defined a schema named User with two fields: name and email. We then defined a schema named Post with two fields: title and author. The author field references the User schema.

Troubleshooting

How to use local schema definitions in other projects

Once you sync your local schema definitions with your remote schemas, your local schema definitions will be available in your types package (i.e. @ronin/YOUR_SPACE_HANDLE) too. See Automatic Types for more information.

How to rename / migrate fields

We currently do not support automatically renaming and migrating fields in code. If you need to rename a field, you should create a new field with the new name and migrate the data manually.

However, this is a feature we are working on and will be available very soon. For updates, keep an eye on our updates page

Plural schema not defined

You must define both the plural and singular versions of the schema in the Schemas interface. The plural version is necessary because it allows you to query records of that schema using the ronin client based on the plural slug you've defined:

TypeScript
import { get } from 'ronin';
 
const accounts = await get.accounts();