Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,6 @@ jobs:

- name: Get pnpm store directory
shell: bash
working-directory: sdks/typescript
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV

Expand Down
24 changes: 8 additions & 16 deletions .github/workflows/typescript-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:

- name: Get pnpm store directory
shell: bash
working-directory: sdks/typescript
working-directory: crates/bindings-typescript
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV

Expand All @@ -38,22 +38,14 @@ jobs:
restore-keys: |
${{ runner.os }}-pnpm-store-

- name: Build module library
- name: Build module library and SDK
working-directory: crates/bindings-typescript
run: pnpm build

- name: Run module library tests
- name: Run module library and SDK tests
working-directory: crates/bindings-typescript
run: pnpm test

- name: Build SDK
working-directory: sdks/typescript
run: pnpm build

- name: Run SDK tests
working-directory: sdks/typescript
run: pnpm test

# - name: Extract SpacetimeDB branch name from file
# id: extract-branch
# run: |
Expand Down Expand Up @@ -104,12 +96,12 @@ jobs:
- name: Generate client bindings
working-directory: modules/quickstart-chat
run: |
spacetime generate --lang typescript --out-dir ../../sdks/typescript/examples/quickstart-chat/src/module_bindings
cd ../../sdks/typescript
pnpm lint --write
spacetime generate --lang typescript --out-dir ../../crates/bindings-typescript/examples/quickstart-chat/src/module_bindings
cd ../../crates/bindings-typescript
pnpm format

- name: Check for changes
working-directory: sdks/typescript
working-directory: crates/bindings-typescript
run: |
# This was copied from SpacetimeDB/tools/check-diff.sh.
# It's required because `spacetime generate` creates lines with the SpacetimeDB commit
Expand Down Expand Up @@ -137,7 +129,7 @@ jobs:
# spacetime logs quickstart-chat

- name: Check that quickstart-chat builds
working-directory: sdks/typescript/examples/quickstart-chat
working-directory: crates/bindings-typescript/examples/quickstart-chat
run: pnpm build

# - name: Run quickstart-chat tests
Expand Down
4 changes: 4 additions & 0 deletions crates/bindings-typescript/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
src/sdk/client_api/*.ts linguist-generated=true
src/lib/autogen/*.ts linguist-generated=true
test-app/src/module_bindings/*.ts linguist-generated=true
examples/quickstart/client/src/module_bindings/*.ts linguist-generated=true
File renamed without changes.
File renamed without changes.
13 changes: 13 additions & 0 deletions crates/bindings-typescript/DEVELOP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Notes for maintainers

The directory `src/sdk/client_api` is generated from [the SpacetimeDB client-api-messages](https://github.com/clockworklabs/SpacetimeDB/tree/master/crates/client-api-messages).

The directory `src/lib/autogen` is generated from the SpacetimeDB `ModuleDef` definition using the `regen-typescript-moduledef` Rust program.

In order to regenerate both of these bindings, run `pnpm generate`.

Whenever the `client-api-messages` crate or the `ModuleDef` changes, you'll have to manually re-generate the definitions.

## Releases and publishing

In order to release and publish a new version of the package, update the version and run `npm publish`.
118 changes: 118 additions & 0 deletions crates/bindings-typescript/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
## SpacetimeDB Module Library and SDK

### Overview

This repository contains both the SpacetimeDB module library and the TypeScript SDK for SpacetimeDB. The SDK allows you to interact with the database server from a client and applies type information from your SpacetimeDB server module.

### Installation

The SDK is an NPM package, thus you can use your package manager of choice like NPM or Yarn, for example:

```
npm add spacetimedb
```

You can use the package in the browser, using a bundler like vite/parcel/rsbuild, in server-side applications like NodeJS, Deno, Bun, NextJS, Remix, and in Cloudflare Workers.

> NOTE: For usage in NodeJS 18-21, you need to install the `undici` package as a peer dependency: `npm add spacetimedb undici`. Node 22 and later are supported out of the box.

### Usage

In order to connect to a database you have to generate module bindings for your database.

```ts
import { DbConnection } from './module_bindings';

const connection = DbConnection.builder()
.withUri('ws://localhost:3000')
.withModuleName('MODULE_NAME')
.onDisconnect(() => {
console.log('disconnected');
})
.onConnectError(() => {
console.log('client_error');
})
.onConnect((connection, identity, _token) => {
console.log(
'Connected to SpacetimeDB with identity:',
identity.toHexString()
);

connection.subscriptionBuilder().subscribe('SELECT * FROM player');
})
.withToken('TOKEN')
.build();
```

If you need to disconnect the client:

```ts
connection.disconnect();
```

Typically, you will use the SDK with types generated from SpacetimeDB module. For example, given a table named `Player` you can subscribe to player updates like this:

```ts
connection.db.player.onInsert((ctx, player) => {
console.log(player);
});
```

Given a reducer called `CreatePlayer` you can call it using a call method:

```ts
connection.reducers.createPlayer();
```

#### React Usage

This module also include React hooks to subscribe to tables under the `spacetimedb/react` subpath. In order to use SpacetimeDB React hooks in your project, first add a `SpacetimeDBProvider` at the top of your component hierarchy:

```tsx
const connectionBuilder = DbConnection.builder()
.withUri('ws://localhost:3000')
.withModuleName('MODULE_NAME')
.withLightMode(true)
.onDisconnect(() => {
console.log('disconnected');
})
.onConnectError(() => {
console.log('client_error');
})
.onConnect((conn, identity, _token) => {
console.log(
'Connected to SpacetimeDB with identity:',
identity.toHexString()
);

conn.subscriptionBuilder().subscribe('SELECT * FROM player');
})
.withToken('TOKEN');

ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<SpacetimeDBProvider connectionBuilder={connectionBuilder}>
<App />
</SpacetimeDBProvider>
</React.StrictMode>
);
```

One you add a `SpacetimeDBProvider` to your hierarchy, you can use SpacetimeDB React hooks in your render function:

```tsx
function App() {
const conn = useSpacetimeDB<DbConnection>();
const { rows: messages } = useTable<DbConnection, Message>('message');

...
}
```

### Developer notes

To run the tests, do:

```sh
pnpm build && pnpm test
```
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "client",
"name": "@clockworklabs/quickstart-chat",
"private": true,
"version": "0.0.1",
"type": "module",
Expand All @@ -16,7 +16,7 @@
"spacetime:publish": "spacetime publish chat --project-path server --server testnet"
},
"dependencies": {
"@clockworklabs/spacetimedb-sdk": "workspace:*",
"spacetimedb": "workspace:*",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, it, expect } from 'vitest';
import App from './App';
import { SpacetimeDBProvider } from '@clockworklabs/spacetimedb-sdk/react';
import { SpacetimeDBProvider } from 'spacetimedb/react';
import { DbConnection } from './module_bindings';

describe('App Integration Test', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import React, { useState } from 'react';
import './App.css';
import { DbConnection, Message, User } from './module_bindings';
import {
useSpacetimeDB,
useTable,
where,
eq,
} from '@clockworklabs/spacetimedb-sdk/react';
import { Identity, Timestamp } from '@clockworklabs/spacetimedb-sdk';
import { useSpacetimeDB, useTable, where, eq } from 'spacetimedb/react';
import { Identity, Timestamp } from 'spacetimedb';

export type PrettyMessage = {
senderName: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import './index.css';
import App from './App.tsx';
import { Identity } from '@clockworklabs/spacetimedb-sdk';
import { SpacetimeDBProvider } from '@clockworklabs/spacetimedb-sdk/react';
import { Identity } from 'spacetimedb';
import { SpacetimeDBProvider } from 'spacetimedb/react';
import { DbConnection, ErrorContext } from './module_bindings/index.ts';

const onConnect = (conn: DbConnection, identity: Identity, token: string) => {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading