Skip to content

Defining Item Types

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 write your schema using helper methods imported from the @stately-cloud/schema package. We recommend opening your schema directory in VSCode since it has built-in support for TypeScript.

Make sure to follow the Define a Schema to get set up with the tools and configuration to build schemas. This document is a reference for how the schema builder API works, and what options you have for defining schema.

Declaring Types

Your schema will consist of as many different type declarations as you want. Each of these is constructed through one of the type builders in the @stately-cloud/schema package, such as itemType, objectType, enumType, or type. These declarations must be exported so the Stately CLI can read them. Since your schema is defined using regular TypeScript, you can use variables, shared constants, functions, even loops (please be reasonable). This also means you can break up your schema into multiple files and import them all together. The only thing to keep in mind is that the CLI will load a single file to find all your exported types, so you should have a top level schema.ts or index.ts that re-exports everything you’ve declared. For example, if you’ve made a user.ts, address.ts, and orders.ts that each have some types in them, you could have an index.ts that looks like:

index.ts
1
export * from './user.js';
2
export * from './address.js';
3
export * from './orders.js';

Notice that the file extensions are .js, not .ts. That’s because TypeScript gets translated to JavaScript before being run. It’s weird, we know!

Here’s an example type declaration (the ”…” is a lot of omitted code):

1
export const User = itemType("User", { ... });

The type builder function itemType is configuring a new type. The name for the new type is the first argument to the itemType function. We also assign to a variable const User - the name of that variable doesn’t actually matter, but it’s a good idea to make it the same as the name of the type you’re declaring, because you can pass around these variables and it’d be confusing if they had a different name. Lastly we export the variable so the type will show up in our schema.

There’s an alternate way to declare types, using a function (not an arrow function):

1
export function User() {
2
return itemType("User", { ... });
3
}

This has the same result, but there’s one big advantage - types declared as functions are resolved lazily, which means you can use a type before it’s declared. This is very helpful when making circular data structures—imagine a User has an Address but the Address also has a list of Users, which one needs to be declared first? If you declare at least one of them as a function, it doesn’t matter.

Item Types

Each Item in your Store belongs to an Item Type which defines its shape and how it is stored. Item Types are declared using the itemType function:

1
export const User = itemType("User", {
2
keyPath: ["/user-:id"],
3
fields: {
4
id: {
5
type: uuid,
6
initialValue: "uuid",
7
fieldNum: 1,
8
},
9
// more fields...
10
},
11
});

Each Item Type has the following required properties:

  1. A name, which is the first argument to the itemType function. Item Type names must be unique within the schema, and by convention are CamelCase.
  2. At least one keyPath which provides an address to store the Item at.
  3. fields that define all the fields of the item type. This is an object where each property is the name of a field, and the value configures that field. Field names are by convention camelCase.

Along with some optional properties:

  1. ttl (Time To Live) - A way to define how long an Item should exist before being automatically delted from the store.
  2. indexes - A list of group-local indexes that allow for different ways to list items in the same Group.
  3. reservedFieldNums - The field numbers for fields that have been removed. These numbers are reserved so they don’t get reused.

Documenting Schema

Right now, documentation in your schema doesn’t get copied into your generated code or shown in the web console. We plan to make documentation survive the generation process in the future!