Skip to content

Define a Schema

This guide will walk you though defining a basic StatelyDB Schema. Schema is how you define all the different data models you’ll store in the database - their structure, data types, and key paths. First you’ll get your development environment set up, then you’ll define and publish a schema.

Prerequisites

  • Make sure you’ve followed all the steps in Getting Started. You will need to download the StatelyDB CLI, which is needed for working with schema definitions, and you should have a Store and an empty Schema created for you.
  • You will need to install NodeJS because our Schema language is based on TypeScript.

Create your schema

Stately schemas are TypeScript code that’s checked in to your code repository alongside your service code. You write your schema in TypeScript even if you’ll be using a Go, Ruby, or Python client. You describe all of your data types in code, and then use the Stately CLI to publish changes to it. Each StatelyDB Store has an associated schema, and multiple stores can share the same schema.

In your code repository, use the StatelyDB CLI to initialize a new schema package (it can be any directory name you want but we’ll call it schema here):

stately schema init ./schema

This will create a directory containing a new NodeJS package:

schema/.gitignore
schema/package.json
schema/README.md
schema/schema.ts
schema/tsconfig.json

Next we’ll need to install the NPM dependencies:

cd ./schema
npm install # or whatever your favorite JavaScript package manager is

The schema.ts file is where you will write your schema, using helper methods imported from the @stately-cloud/schema package. We recommend opening the schema directory in VSCode since it has built-in support for TypeScript.

Add an Item Type

Item Types are the top-level documents in your database - you can have many different item types in a Store, and each item type can be manipulated our Data APIs. Many applications have some sort of “user” model, so let’s start with that:

import {
itemType,
string,
timestampSeconds,
uint,
uuid,
} from "@stately-cloud/schema";
// A sort of unrelated type used for some simpler examples.
export const User = itemType("User", {
keyPath: "/user-:id",
fields: {
id: {
type: uuid,
initialValue: "uuid",
fieldNum: 1,
},
displayName: {
type: string,
fieldNum: 2,
},
email: {
type: string,
fieldNum: 3,
},
lastLoginDate: {
type: timestampSeconds,
fieldNum: 4,
},
numLogins: {
type: uint,
fieldNum: 5,
},
},
});

There are a few things going on here:

  1. First, we import a bunch of schema helpers from the @stately-cloud/schema package. VSCode can help you automatically add these imports.
  2. We declare a new Item Type to describe a User. The item type must be exported from the JavaScript module so it is visible to the schema tools.
  3. The User item type has a key path of /user-:id. This is like a “primary key” in other databases - it’s the path you’ll use to access a specific user. An individual User might have a key path like /user-p05olqcFSfC6zOqEojxT9g.
  4. Lastly there are the actual fields of the item. Each field has a name, a type, and a unique field number. The field number is used to efficiently store the data without having to store the field name every time.
    • There are a few different data types in use - basic types like string, uint (unsigned integer), and more complex types like uuid and timestampSeconds. These are provided as part of @stately-cloud/schema, but you can also make custom types with the type(...) helper function.
    • The id field has an initialValue—this means that StatelyDB will pick a new UUID whenever you create a new User.

This is just scratching the surface of what you can express with schema. See Defining Item Types for more things to try.

Generating Language-Specific Code

You can now generate the typed client code for one of our supported programming languages. Generating the SDK can be done in one of two ways: preview or release. Preview mode generates the SDK based on your local changes, which is useful for rapidly iterating and integrating the generated code without having to put new schema versions. Release mode generates everything that preview mode does plus a customized client that speaks the specific version you generate it with. Release mode requires that you have published the schema version to Stately Cloud, so it can be nice to start with preview mode, then switch to release mode when you’re ready to integrate the client into your application.

Generating an SDK in --preview mode is done via the StatelyDB CLI with the command:

stately schema generate --language go --preview ./schema/schema.ts ./pkg/schema

If you look in the lib directory, you’ll now see some files that export objects for all of your item types. You can iterate on your schema and generate a preview as many times as you wish. Once you’re satisfied you can publish the schema to Stately Cloud.

Publishing your schema

Once you have written out your schema definition, you need to publish the schema into your Stately Cloud account. First, find the Schema ID of the schema you want to update (it’s in the Console and in the output of stately whoami), then using the StatelyDB CLI:

stately schema put --schema-id <your schema ID> --message "First version" path/to/schema.ts

In order for your Store to use this schema, the schema needs to be “bound” to the store. This only needs to happen once per store, and a single schema can be bound to multiple stores. Using the CLI:

stately schema bind --schema-id <your schema ID> --store-id <your store ID>

Generating Language-Specific Code for release

When you’re ready wire up the stately client in your application, you can generate the SDK in release mode. This will generate an SDK similar to --preview but with a customized client based on the schema ID and version that you have published to Stately Cloud.

stately schema generate --language go --schema-id <your schema ID> --version <schema version> lib