The SpacetimeDB Typescript client SDK
The SpacetimeDB client SDK for TypeScript contains all the tools you need to build clients for SpacetimeDB modules using Typescript, either in the browser or with NodeJS.
Note
You need a database created before use the client, so make sure to follow the Rust or C# Module Quickstart guides if need one.
Install the SDK
First, create a new client project, and add the following to your tsconfig.json file:
{
"compilerOptions": {
//You can use any target higher than this one
//https://www.typescriptlang.org/tsconfig#target
"target": "es2015"
}
}
Then add the SpacetimeDB SDK to your dependencies:
cd client
npm install @clockworklabs/spacetimedb-sdk
You should have this folder layout starting from the root of your project:
quickstart-chat
├── client
│ ├── node_modules
│ ├── public
│ └── src
└── server
└── src
Tip for utilities/scripts
If want to create a quick script to test your module bindings from the command line, you can use https://www.npmjs.com/package/tsx to execute TypeScript files.
Then you create a script.ts file and add the imports, code and execute with:
npx tsx src/script.ts
Generate module bindings
Each SpacetimeDB client depends on some bindings specific to your module. Create a module_bindings directory in your project's src directory and generate the Typescript interface files using the Spacetime CLI. From your project directory, run:
mkdir -p client/src/module_bindings
spacetime generate --lang typescript \
--out-dir client/src/module_bindings \
--project-path server
And now you will get the files for the reducers & tables:
quickstart-chat
├── client
│ ├── node_modules
│ ├── public
│ └── src
| └── module_bindings
| ├── add_reducer.ts
| ├── person.ts
| └── say_hello_reducer.ts
└── server
└── src
Import the module_bindings in your client's main file:
import { SpacetimeDBClient, Identity } from '@clockworklabs/spacetimedb-sdk';
import Person from './module_bindings/person';
import AddReducer from './module_bindings/add_reducer';
import SayHelloReducer from './module_bindings/say_hello_reducer';
console.log(Person, AddReducer, SayHelloReducer);
Note
There is a known issue where if you do not use every type in your file, it will not pull them into the published build. To fix this, we are using console.log to force them to get pulled in.
API at a glance
Classes
Class | Description |
---|---|
SpacetimeDBClient | The database client connection to a SpacetimeDB server. |
Identity | The user's public identity. |
Address | An opaque identifier for differentiating connections by the same Identity. |
{Table} | {Table} is a placeholder for each of the generated tables. |
{Reducer} | {Reducer} is a placeholder for each of the generated reducers. |
Class SpacetimeDBClient
The database client connection to a SpacetimeDB server.
Defined in spacetimedb-sdk.spacetimedb:
Constructors | Description |
---|---|
SpacetimeDBClient.constructor | Creates a new SpacetimeDBClient database client. |
Properties | |
SpacetimeDBClient.identity | The user's public identity. |
SpacetimeDBClient.live | Whether the client is connected. |
SpacetimeDBClient.token | The user's private authentication token. |
Methods | |
SpacetimeDBClient.connect | Connect to a SpacetimeDB module. |
SpacetimeDBClient.disconnect | Close the current connection. |
SpacetimeDBClient.subscribe | Subscribe to a set of queries. |
Events | |
SpacetimeDBClient.onConnect | Register a callback to be invoked upon authentication with the database. |
SpacetimeDBClient.onError | Register a callback to be invoked upon a error. |
Constructors
SpacetimeDBClient constructor
Creates a new SpacetimeDBClient database client and set the initial parameters.
new SpacetimeDBClient(host: string, name_or_address: string, auth_token?: string, protocol?: "binary" | "json")
Parameters
Name | Type | Description |
---|---|---|
host | string | The host of the SpacetimeDB server. |
name_or_address | string | The name or address of the SpacetimeDB module. |
auth_token? | string | The credentials to use to connect to authenticate with SpacetimeDB. |
protocol? | "binary" | "json" | Define how encode the messages: "binary" | "json". Binary is more efficient and compact, but JSON provides human-readable debug information. |
Example
const host = 'ws://localhost:3000';
const name_or_address = 'database_name';
const auth_token = undefined;
const protocol = 'binary';
var spacetimeDBClient = new SpacetimeDBClient(
host,
name_or_address,
auth_token,
protocol
);
Class methods
SpacetimeDBClient.registerReducers
Registers reducer classes for use with a SpacetimeDBClient
registerReducers(...reducerClasses: ReducerClass[])
Parameters
Name | Type | Description |
---|---|---|
reducerClasses | ReducerClass | A list of classes to register |
Example
import SayHelloReducer from './types/say_hello_reducer';
import AddReducer from './types/add_reducer';
SpacetimeDBClient.registerReducers(SayHelloReducer, AddReducer);
SpacetimeDBClient.registerTables
Registers table classes for use with a SpacetimeDBClient
registerTables(...reducerClasses: TableClass[])
Parameters
Name | Type | Description |
---|---|---|
tableClasses | TableClass | A list of classes to register |
Example
import User from './types/user';
import Player from './types/player';
SpacetimeDBClient.registerTables(User, Player);
Properties
SpacetimeDBClient identity
The user's public Identity.
identity: Identity | undefined
SpacetimeDBClient live
Whether the client is connected.
live: boolean;
SpacetimeDBClient token
The user's private authentication token.
token: string | undefined
Parameters
Name | Type | Description |
---|---|---|
reducerName | string | The name of the reducer to call |
serializer | Serializer | - |
SpacetimeDBClient connect
Connect to The SpacetimeDB Websocket For Your Module. By default, this will use a secure websocket connection. The parameters are optional, and if not provided, will use the values provided on construction of the client.
connect(host: string?, name_or_address: string?, auth_token: string?): Promise<void>
Parameters
Name | Type | Description |
---|---|---|
host? | string | The hostname of the SpacetimeDB server. Defaults to the value passed to the constructor. |
name_or_address? | string | The name or address of the SpacetimeDB module. Defaults to the value passed to the constructor. |
auth_token? | string | The credentials to use to authenticate with SpacetimeDB. Defaults to the value passed to the constructor. |
Returns
Promise<void>
Example
const host = 'ws://localhost:3000';
const name_or_address = 'database_name';
const auth_token = undefined;
var spacetimeDBClient = new SpacetimeDBClient(
host,
name_or_address,
auth_token
);
// Connect with the initial parameters
spacetimeDBClient.connect();
//Set the `auth_token`
spacetimeDBClient.connect(undefined, undefined, NEW_TOKEN);
SpacetimeDBClient disconnect
Close the current connection.
disconnect(): void
Example
var spacetimeDBClient = new SpacetimeDBClient(
'ws://localhost:3000',
'database_name'
);
spacetimeDBClient.disconnect();
SpacetimeDBClient subscribe
Subscribe to a set of queries, to be notified when rows which match those queries are altered.
A new call to subscribe will remove all previous subscriptions and replace them with the new queries. If any rows matched the previous subscribed queries but do not match the new queries, those rows will be removed from the client cache, and {Table}.on_delete callbacks will be invoked for them.
subscribe(queryOrQueries: string | string[]): void
Parameters
Name | Type | Description |
---|---|---|
queryOrQueries | string | string[] | A SQL query or list of queries |
Example
spacetimeDBClient.subscribe(['SELECT * FROM User', 'SELECT * FROM Message']);
Events
SpacetimeDBClient onConnect
Register a callback to be invoked upon authentication with the database.
onConnect(callback: (token: string, identity: Identity) => void): void
The callback will be invoked with the public user Identity, private authentication token and connection Address provided by the database. If credentials were supplied to connect, those passed to the callback will be equivalent to the ones used to connect. If the initial connection was anonymous, a new set of credentials will be generated by the database to identify this user.
The credentials passed to the callback can be saved and used to authenticate the same user in future connections.
Parameters
Name | Type |
---|---|
callback | (token: string, identity: Identity, address: Address) => void |
Example
spacetimeDBClient.onConnect((token, identity, address) => {
console.log('Connected to SpacetimeDB');
console.log('Token', token);
console.log('Identity', identity);
console.log('Address', address);
});
SpacetimeDBClient onError
Register a callback to be invoked upon an error.
onError(callback: (...args: any[]) => void): void
Parameters
Name | Type |
---|---|
callback | (...args: any[]) => void |
Example
spacetimeDBClient.onError((...args: any[]) => {
console.error('ERROR', args);
});
Class Identity
A unique public identifier for a user of a database.
Defined in spacetimedb-sdk.identity:
Constructors | Description |
---|---|
Identity.constructor | Creates a new Identity. |
Methods | |
Identity.isEqual | Compare two identities for equality. |
Identity.toHexString | Print the identity as a hexadecimal string. |
Static methods | |
Identity.fromString | Parse an Identity from a hexadecimal string. |
Constructors
Identity constructor
new Identity(data: Uint8Array)
Parameters
Name | Type |
---|---|
data | Uint8Array |
Methods
Identity isEqual
Compare two identities for equality.
isEqual(other: Identity): boolean
Parameters
Name | Type |
---|---|
other | Identity |
Returns
boolean
Identity toHexString
Print an Identity as a hexadecimal string.
toHexString(): string
Returns
string
Identity fromString
Static method; parse an Identity from a hexadecimal string.
Identity.fromString(str: string): Identity
Parameters
Name | Type |
---|---|
str | string |
Returns
Class Address
An opaque identifier for a client connection to a database, intended to differentiate between connections from the same Identity.
Defined in spacetimedb-sdk.address:
Constructors | Description |
---|---|
Address.constructor | Creates a new Address. |
Methods | |
Address.isEqual | Compare two identities for equality. |
Address.toHexString | Print the address as a hexadecimal string. |
Static methods | |
Address.fromString | Parse an Address from a hexadecimal string. |
Constructors
Address constructor
new Address(data: Uint8Array)
Parameters
Name | Type |
---|---|
data | Uint8Array |
Methods
Address isEqual
Compare two addresses for equality.
isEqual(other: Address): boolean
Parameters
Name | Type |
---|---|
other | Address |
Returns
boolean
Address toHexString
Print an Address as a hexadecimal string.
toHexString(): string
Returns
string
Address fromString
Static method; parse an Address from a hexadecimal string.
Address.fromString(str: string): Address
Parameters
Name | Type |
---|---|
str | string |
Returns
Class {Table}
For each table defined by a module, spacetime generate generates a class in the module_bindings folder whose name is that table's name converted to PascalCase.
The generated class has a field for each of the table's columns, whose names are the column names converted to snake_case.
Properties | Description |
---|---|
Table.name | The name of the class. |
Table.tableName | The name of the table in the database. |
Methods | |
Table.isEqual | Method to compare two identities. |
Table.all | Return all the subscribed rows in the table. |
Table.filterBy{COLUMN} | Autogenerated; return subscribed rows with a given value in a particular column. {COLUMN} is a placeholder for a column name. |
Table.findBy{COLUMN} | Autogenerated; return a subscribed row with a given value in a particular unique column. {COLUMN} is a placeholder for a column name. |
Events | |
Table.onInsert | Register an onInsert callback for when a subscribed row is newly inserted into the database. |
Table.removeOnInsert | Unregister a previously-registered onInsert callback. |
Table.onUpdate | Register an onUpdate callback for when an existing row is modified. |
Table.removeOnUpdate | Unregister a previously-registered onUpdate callback. |
Table.onDelete | Register an onDelete callback for when a subscribed row is removed from the database. |
Table.removeOnDelete | Unregister a previously-registered onDelete callback. |
Properties
{Table} name
• name: string
The name of the Class.
{Table} tableName
The name of the table in the database.
▪ Static tableName: string = "Person"
Methods
{Table} all
Return all the subscribed rows in the table.
{Table}.all(): {Table}[]
Returns
{Table}[]
Example
var spacetimeDBClient = new SpacetimeDBClient(
'ws://localhost:3000',
'database_name'
);
spacetimeDBClient.onConnect((token, identity, address) => {
spacetimeDBClient.subscribe(['SELECT * FROM Person']);
setTimeout(() => {
console.log(Person.all()); // Prints all the `Person` rows in the database.
}, 5000);
});
{Table} count
Return the number of subscribed rows in the table, or 0 if there is no active connection.
{Table}.count(): number
Returns
number
Example
var spacetimeDBClient = new SpacetimeDBClient(
'ws://localhost:3000',
'database_name'
);
spacetimeDBClient.onConnect((token, identity, address) => {
spacetimeDBClient.subscribe(['SELECT * FROM Person']);
setTimeout(() => {
console.log(Person.count());
}, 5000);
});
{Table} filterBy{COLUMN}
For each column of a table, spacetime generate generates a static method on the Class to filter subscribed rows where that column matches a requested value.
These methods are named filterBy{COLUMN}, where {COLUMN} is the column name converted to camelCase.
{Table}.filterBy{COLUMN}(value): Iterable<{Table}>
Parameters
Name | Type |
---|---|
value | The type of the {COLUMN}. |
Returns
Iterable<{Table}>
Example
var spacetimeDBClient = new SpacetimeDBClient(
'ws://localhost:3000',
'database_name'
);
spacetimeDBClient.onConnect((token, identity, address) => {
spacetimeDBClient.subscribe(['SELECT * FROM Person']);
setTimeout(() => {
console.log(...Person.filterByName('John')); // prints all the `Person` rows named John.
}, 5000);
});
{Table} findBy{COLUMN}
For each unique column of a table, spacetime generate generates a static method on the Class to find the subscribed row where that column matches a requested value.
These methods are named findBy{COLUMN}, where {COLUMN} is the column name converted to camelCase.
{Table}.findBy{COLUMN}(value): {Table} | undefined
Parameters
Name | Type |
---|---|
value | The type of the {COLUMN}. |
Returns
{Table} | undefined
Example
var spacetimeDBClient = new SpacetimeDBClient(
'ws://localhost:3000',
'database_name'
);
spacetimeDBClient.onConnect((token, identity, address) => {
spacetimeDBClient.subscribe(['SELECT * FROM Person']);
setTimeout(() => {
console.log(Person.findById(0)); // prints a `Person` row with id 0.
}, 5000);
});
{Table} fromValue
Deserialize an AlgebraicType into this {Table}.
{Table}.fromValue(value: AlgebraicValue): {Table}
Parameters
Name | Type |
---|---|
value | AlgebraicValue |
Returns
{Table}
{Table} getAlgebraicType
Serialize this into an AlgebraicType.
Example
{Table}.getAlgebraicType(): AlgebraicType
Returns
AlgebraicType
{Table} onInsert
Register an onInsert callback for when a subscribed row is newly inserted into the database.
{Table}.onInsert(callback: (value: {Table}, reducerEvent: ReducerEvent | undefined) => void): void
Parameters
Name | Type | Description |
---|---|---|
callback | (value: {Table}, reducerEvent: undefined | ReducerEvent) => void | Callback to run whenever a subscribed row is inserted. |
Example
var spacetimeDBClient = new SpacetimeDBClient(
'ws://localhost:3000',
'database_name'
);
spacetimeDBClient.onConnect((token, identity, address) => {
spacetimeDBClient.subscribe(['SELECT * FROM Person']);
});
Person.onInsert((person, reducerEvent) => {
if (reducerEvent) {
console.log('New person inserted by reducer', reducerEvent, person);
} else {
console.log('New person received during subscription update', person);
}
});
{Table} removeOnInsert
Unregister a previously-registered onInsert callback.
{Table}.removeOnInsert(callback: (value: Person, reducerEvent: ReducerEvent | undefined) => void): void
Parameters
Name | Type |
---|---|
callback | (value: {Table}, reducerEvent: undefined | ReducerEvent) => void |
{Table} onUpdate
Register an onUpdate callback to run when an existing row is modified by primary key.
{Table}.onUpdate(callback: (oldValue: {Table}, newValue: {Table}, reducerEvent: ReducerEvent | undefined) => void): void
onUpdate callbacks are only meaningful for tables with a column declared as a primary key. Tables without primary keys will never fire onUpdate callbacks.
Parameters
Name | Type | Description |
---|---|---|
callback | (oldValue: {Table}, newValue: {Table}, reducerEvent: undefined | ReducerEvent) => void | Callback to run whenever a subscribed row is updated. |
Example
var spacetimeDBClient = new SpacetimeDBClient(
'ws://localhost:3000',
'database_name'
);
spacetimeDBClient.onConnect((token, identity, address) => {
spacetimeDBClient.subscribe(['SELECT * FROM Person']);
});
Person.onUpdate((oldPerson, newPerson, reducerEvent) => {
console.log('Person updated by reducer', reducerEvent, oldPerson, newPerson);
});
{Table} removeOnUpdate
Unregister a previously-registered onUpdate callback.
{Table}.removeOnUpdate(callback: (oldValue: {Table}, newValue: {Table}, reducerEvent: ReducerEvent | undefined) => void): void
Parameters
Name | Type |
---|---|
callback | (oldValue: {Table}, newValue: {Table}, reducerEvent: undefined | ReducerEvent) => void |
{Table} onDelete
Register an onDelete callback for when a subscribed row is removed from the database.
{Table}.onDelete(callback: (value: {Table}, reducerEvent: ReducerEvent | undefined) => void): void
Parameters
Name | Type | Description |
---|---|---|
callback | (value: {Table}, reducerEvent: undefined | ReducerEvent) => void | Callback to run whenever a subscribed row is removed. |
Example
var spacetimeDBClient = new SpacetimeDBClient(
'ws://localhost:3000',
'database_name'
);
spacetimeDBClient.onConnect((token, identity, address) => {
spacetimeDBClient.subscribe(['SELECT * FROM Person']);
});
Person.onDelete((person, reducerEvent) => {
if (reducerEvent) {
console.log('Person deleted by reducer', reducerEvent, person);
} else {
console.log(
'Person no longer subscribed during subscription update',
person
);
}
});
{Table} removeOnDelete
Unregister a previously-registered onDelete callback.
{Table}.removeOnDelete(callback: (value: {Table}, reducerEvent: ReducerEvent | undefined) => void): void
Parameters
Name | Type |
---|---|
callback | (value: {Table}, reducerEvent: undefined | ReducerEvent) => void |
Class {Reducer}
spacetime generate defines an {Reducer} class in the module_bindings folder for each reducer defined by a module.
The class's name will be the reducer's name converted to PascalCase.
Static methods | Description |
---|---|
Reducer.call | Executes the reducer. |
Events | |
Reducer.on | Register a callback to run each time the reducer is invoked. |
Static methods
{Reducer} call
Executes the reducer.
{Reducer}.call(): void
Example
SayHelloReducer.call();
Events
{Reducer} on
Register a callback to run each time the reducer is invoked.
{Reducer}.on(callback: (reducerEvent: ReducerEvent, ...reducerArgs: any[]) => void): void
Clients will only be notified of reducer runs if either of two criteria is met:
- The reducer inserted, deleted or updated at least one row to which the client is subscribed.
- The reducer invocation was requested by this client, and the run failed.
Parameters
Name | Type |
---|---|
callback | (reducerEvent: ReducerEvent, ...reducerArgs: any[]) => void) |
Example
SayHelloReducer.on((reducerEvent, ...reducerArgs) => {
console.log('SayHelloReducer called', reducerEvent, reducerArgs);
});