Skip to content

JavaScript (TypeScript)

Our API Reference has generic examples in every supported language, and we strive to make the experience of each SDK very similar. However, there are some things specific to the JavaScript SDK that we want to call out here.

NodeJS Only

The JavaScript SDK is meant for NodeJS backend applications, and cannot run in a browser.

ES Modules

The generated code uses ES Modules, with import paths that include the .js file extension. You may need to configure your tools to recognize this code as ESM.

Creating Item Objects

The generated code binds a client to the types in your schema, so it can validate that you’re always passing the right types in. There are TypeScript types available for all of the item, object, and enum types you defined in your schema. However, you need to use the create method to correctly initialize new objects of a particular type:

const movie = client.create("Movie", {
title: "Starship Troopers 2",
year: 2004n,
genre: "Sci-Fi",
duration: 7880n,
rating: "R",
});

This is necessary because create stamps some additional information in a $typeName property, which is then used by the client to properly serialize and deserialize items. Note that the type name argument to create is also based on your schema and will only allow the item type names you’ve defined.

Checking an Item’s Type

Since JavaScript doesn’t have types at runtime, and Stately generated objects aren’t classes, we need a special function to check the type of an item:

// out here, item is type AnyItem
if (client.isType(item, "Movie")) {
// Within this branch the item is Movie
console.log("Movie:", item.title);
} else if (client.isType(item, "Character")) {
// Within this branch the item is Character
console.log("Character:", item.name);
}

Key Path Helper

The keyPath tagged string literal function can be used to generate key paths while correctly formatting IDs (especially UUIDs):

import { keyPath } from "@stately-cloud/client";
//...
const kp = keyPath`/movie-${movieId}/actor-${actorId}`;

Protobuf

The objects generated from your schema use the @bufbuild/protobuf-es library to serialize and deserialize. You’ll need to make sure your code has a dependency on @bufbuild/protobuf-es, and you may find the types and helpers in that library useful for working with Stately objects.

BigInts

JavaScript has very limited support for numbers compared to other languages. The number type in JavaScript is always a 64-bit floating-point number, which means it can’t hold all the values of a 64-bit integer. However, 64-bit integers are used frequently in Stately schema. These get translated in generated code to BigInt which can represent 64-bit integers. These are unfortunately not that easy to work with - literals must be suffixed with n (e.g. 1234n), and common functions like JSON.stringify blow up when encountering BigInts.

For now, you can use our int32 and uint32 types in fields to force some numbers to a range that will fit in number, or just manually deal with the BigInts.

UUIDs

UUIDs are represented as 16-element Uint8Arrays. You can use the uuid package to convert between these and the more common string form.

Async Iterables

The List APIs return Async Iterables, which allow you to handle results as they stream back from the server. You can use the for await...of syntax to handle them:

for await (const item of client.beginList(prefix)) {
// handle an item...
}

Unwanted Imports

VSCode may try to import the constants you export from your schema files, instead of the generated files. Set the preference typescript.preferences.autoImportSpecifierExcludeRegexes to exclude your schema directory:

.vscode/settings.json
{
"typescript.preferences.autoImportSpecifierExcludeRegexes": [
"\/schema\/"
]
}