Skip to content

Commit b9db9b6

Browse files
authored
docs: 0.12 public facing docs (#108)
* Push * Add changeset
1 parent 79c278b commit b9db9b6

File tree

6 files changed

+147
-117
lines changed

6 files changed

+147
-117
lines changed

.changeset/orange-dragons-sin.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@clockworklabs/spacetimedb-sdk': patch
3+
---
4+
5+
docs: Public facing docs for 0.12

packages/sdk/README.md

Lines changed: 29 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -12,68 +12,54 @@ The SDK is an NPM package, thus you can use your package manager of choice like
1212
npm install --save @clockworklabs/spacetimedb-sdk
1313
```
1414

15-
You can use the package in the browser, using a bundler like webpack of vite, and in terminal applications
15+
You can use the package in the browser, using a bundler like vite/parcel/rsbuild, in server-side applications like NodeJS, Deno, Bun and in Cloudflare Workers.
1616

17-
> NOTE: For usage in NodeJS 18-21, you need to install the `undici` package as a peer dependency as well: `npm install @clockworklabs/spacetimedb-sdk undici`. Node 22 and later are supported out of the box.
17+
> NOTE: For usage in NodeJS 18-21, you need to install the `undici` package as a peer dependency: `npm install @clockworklabs/spacetimedb-sdk undici`. Node 22 and later are supported out of the box.
1818
1919
### Usage
2020

21-
In order to connect to a database you have to create a new client:
21+
In order to connect to a database you have to generate module bindings for your database.
2222

2323
```ts
24-
import { SpacetimeDBClient } from '@clockworklabs/spacetimedb-sdk';
25-
26-
let client = new SpacetimeDBClient('spacetimedb.com/spacetimedb', '<db-name>');
27-
```
28-
29-
If you would like to connect to the client you can call the below method. This also takes optional parameters to override the host or credentials:
30-
31-
```ts
32-
client.connect();
24+
import { DBConnection } from './module_bindings';
25+
26+
const connection = DBConnection.builder()
27+
.withUri('ws://localhost:3000')
28+
.withModuleName('MODULE_NAME')
29+
.onDisconnect(() => {
30+
console.log('disconnected');
31+
})
32+
.onConnectError(() => {
33+
console.log('client_error');
34+
})
35+
.onConnect((connection, identity, _token) => {
36+
console.log(
37+
'Connected to SpacetimeDB with identity:',
38+
identity.toHexString()
39+
);
40+
41+
connection.subscriptionBuilder().subscribe(['SELECT * FROM player']);
42+
})
43+
.withCredentials([Identity.fromString('IDENTITY'), 'TOKEN'])
44+
.build();
3345
```
3446

3547
If for some reason you need to disconnect the client:
3648

3749
```ts
38-
client.disconnect();
39-
```
40-
41-
This will connect to a database instance without a specified identity. If you want to persist an identity fetched on connection you can register an `onConnect` callback, which will receive a new assigned identity as an argument:
42-
43-
```ts
44-
client.onConnect((identity: string) => {
45-
console.log(identity);
46-
console.log(client.token);
47-
});
48-
```
49-
50-
You may also pass credentials as an optional third argument:
51-
52-
```ts
53-
let credentials = { identity: '<identity>', token: '<token>' };
54-
let client = new SpacetimeDBClient(
55-
'spacetimedb.com/spacetimedb',
56-
'<db-name>',
57-
credentials
58-
);
59-
```
60-
61-
Typically, you will use the SDK with types generated from a backend DB service. For example, given a component named `Player` you can subscribe to player updates by registering the component:
62-
63-
```ts
64-
client.registerComponent(Player, 'Player');
50+
connection.disconnect();
6551
```
6652

67-
Then you will be able to register callbacks on insert and delete events, for example:
53+
Typically, you will use the SDK with types generated from a backend DB service. For example, given a table named `Player` you can subscribe to player updates like this:
6854

6955
```ts
70-
Player.onInsert((newPlayer: Player) => {
71-
console.log(newPlayer);
56+
connection.db.player.onInsert((ctx, player) => {
57+
console.log(player);
7258
});
7359
```
7460

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

7763
```ts
78-
CreatePlayer.call('Nickname');
64+
connection.reducers.createPlayer();
7965
```

packages/sdk/src/db_connection_builder.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { DBConnectionImpl, type ConnectionEvent } from './db_connection_impl';
1+
import { DBConnectionImpl } from './db_connection_impl';
22
import { EventEmitter } from './event_emitter';
33
import type { Identity } from './identity';
44
import { stdbLogger } from './logger';

packages/sdk/src/db_connection_impl.ts

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { Address } from './address.ts';
21
import decompress from 'brotli/decompress';
2+
import { Address } from './address.ts';
33
import {
44
AlgebraicType,
55
ProductType,
@@ -18,43 +18,40 @@ import BinaryReader from './binary_reader.ts';
1818
import BinaryWriter from './binary_writer.ts';
1919
import * as ws from './client_api/index.ts';
2020
import { ClientCache } from './client_cache.ts';
21+
import { DBConnectionBuilder } from './db_connection_builder.ts';
2122
import { SubscriptionBuilder, type DBContext } from './db_context.ts';
23+
import type { Event } from './event.ts';
2224
import { type EventContextInterface } from './event_context.ts';
2325
import { EventEmitter } from './event_emitter.ts';
2426
import type { Identity } from './identity.ts';
25-
import { stdbLogger } from './logger.ts';
2627
import type { IdentityTokenMessage, Message } from './message_types.ts';
2728
import type { ReducerEvent } from './reducer_event.ts';
2829
import type SpacetimeModule from './spacetime_module.ts';
2930
import { TableCache, type Operation, type TableUpdate } from './table_cache.ts';
30-
import { toPascalCase } from './utils.ts';
31+
import { deepEqual, toPascalCase } from './utils.ts';
3132
import { WebsocketDecompressAdapter } from './websocket_decompress_adapter.ts';
3233
import type { WebsocketTestAdapter } from './websocket_test_adapter.ts';
33-
import type { Event } from './event.ts';
34-
import { DBConnectionBuilder } from './db_connection_builder.ts';
35-
import { deepEqual } from './utils.ts';
3634

3735
export {
3836
AlgebraicType,
3937
AlgebraicValue,
38+
BinaryReader,
39+
BinaryWriter,
40+
DBConnectionBuilder,
41+
deepEqual,
4042
ProductType,
4143
ProductTypeElement,
4244
ProductValue,
45+
SubscriptionBuilder,
4346
SumType,
4447
SumTypeVariant,
45-
type ReducerArgsAdapter,
46-
type ValueAdapter,
47-
BinaryReader,
48-
BinaryWriter,
4948
TableCache,
50-
DBConnectionBuilder,
51-
SubscriptionBuilder,
5249
type Event,
53-
deepEqual,
50+
type ReducerArgsAdapter,
51+
type ValueAdapter,
5452
};
5553

56-
export type { DBContext, EventContextInterface };
57-
export type { ReducerEvent };
54+
export type { DBContext, EventContextInterface, ReducerEvent };
5855

5956
export type ConnectionEvent = 'connect' | 'disconnect' | 'connectError';
6057

@@ -105,9 +102,8 @@ export class DBConnectionImpl<DBView = any, Reducers = any>
105102
* @example
106103
*
107104
* ```ts
108-
* var spacetimeDBClient = new SpacetimeDBClient("ws://localhost:3000", "database_name");
109-
*
110-
* spacetimeDBClient.disconnect()
105+
* const connection = DBConnection.builder().build();
106+
* connection.disconnect()
111107
* ```
112108
*/
113109
disconnect(): void {

packages/sdk/src/db_context.ts

Lines changed: 97 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,45 @@ type Result<T = undefined> =
1111
value: Error;
1212
};
1313

14+
/**
15+
* Interface representing a subscription handle for managing queries.
16+
*/
1417
interface SubscriptionHandle {
15-
/// Consumes self and issues an `Unsubscribe` message,
16-
/// removing this query from the client's set of subscribed queries.
17-
/// It is only valid to call this method if `is_active()` is `true`.
18+
/**
19+
* Consumes self and issues an `Unsubscribe` message,
20+
* removing this query from the client's set of subscribed queries.
21+
* It is only valid to call this method if `is_active()` is `true`.
22+
*/
1823
unsubscribe(): Result;
1924

20-
/// `Unsubscribe`s and also registers a callback to run upon success.
21-
/// I.e. when an `UnsubscribeApplied` message is received.
22-
///
23-
/// If `Unsubscribe` returns an error,
24-
/// or if the `on_error` callback(s) are invoked before this subscription would end normally,
25-
/// the `on_end` callback is not invoked.
25+
/**
26+
* Unsubscribes and also registers a callback to run upon success.
27+
* I.e. when an `UnsubscribeApplied` message is received.
28+
*
29+
* If `Unsubscribe` returns an error,
30+
* or if the `on_error` callback(s) are invoked before this subscription would end normally,
31+
* the `on_end` callback is not invoked.
32+
*
33+
* @param onEnd - Callback to run upon successful unsubscribe.
34+
*/
2635
unsubscribeThen(onEnd: () => void): Result;
2736

28-
/// True if this `SubscriptionHandle` has ended,
29-
/// either due to an error or a call to `unsubscribe`.
30-
///
31-
/// This is initially false, and becomes true when either the `on_end` or `on_error` callback is invoked.
32-
/// A subscription which has not yet been applied is not active, but is also not ended.
37+
/**
38+
* True if this `SubscriptionHandle` has ended,
39+
* either due to an error or a call to `unsubscribe`.
40+
*
41+
* This is initially false, and becomes true when either the `on_end` or `on_error` callback is invoked.
42+
* A subscription which has not yet been applied is not active, but is also not ended.
43+
*/
3344
isEnded(): boolean;
3445

35-
/// True if this `SubscriptionHandle` is active, meaning it has been successfully applied
36-
/// and has not since ended, either due to an error or a complete `unsubscribe` request-response pair.
37-
///
38-
/// This corresponds exactly to the interval bounded at the start by the `on_applied` callback
39-
/// and at the end by either the `on_end` or `on_error` callback.
46+
/**
47+
* True if this `SubscriptionHandle` is active, meaning it has been successfully applied
48+
* and has not since ended, either due to an error or a complete `unsubscribe` request-response pair.
49+
*
50+
* This corresponds exactly to the interval bounded at the start by the `on_applied` callback
51+
* and at the end by either the `on_end` or `on_error` callback.
52+
*/
4053
isActive(): boolean;
4154
}
4255

@@ -46,60 +59,90 @@ export class SubscriptionBuilder {
4659

4760
constructor(private db: DBConnectionImpl) {}
4861

49-
/// Registers `callback` to run when this query is successfully added to our subscribed set,
50-
/// I.e. when its `SubscriptionApplied` message is received.
51-
///
52-
/// The database state exposed via the `&EventContext` argument
53-
/// includes all the rows added to the client cache as a result of the new subscription.
54-
///
55-
/// The event in the `&EventContext` argument is `Event::SubscribeApplied`.
56-
///
57-
/// Multiple `on_applied` callbacks for the same query may coexist.
58-
/// No mechanism for un-registering `on_applied` callbacks is exposed.
62+
/**
63+
* Registers `callback` to run when this query is successfully added to our subscribed set,
64+
* I.e. when its `SubscriptionApplied` message is received.
65+
*
66+
* The database state exposed via the `&EventContext` argument
67+
* includes all the rows added to the client cache as a result of the new subscription.
68+
*
69+
* The event in the `&EventContext` argument is `Event::SubscribeApplied`.
70+
*
71+
* Multiple `on_applied` callbacks for the same query may coexist.
72+
* No mechanism for un-registering `on_applied` callbacks is exposed.
73+
*
74+
* @param cb - Callback to run when the subscription is applied.
75+
* @returns The current `SubscriptionBuilder` instance.
76+
*/
5977
onApplied(cb: (ctx: EventContextInterface) => void): SubscriptionBuilder {
6078
this.#onApplied = cb;
6179
return this;
6280
}
6381

64-
/// Registers `callback` to run when this query either:
65-
/// - Fails to be added to our subscribed set.
66-
/// - Is unexpectedly removed from our subscribed set.
67-
///
68-
/// If the subscription had previously started and has been unexpectedly removed,
69-
/// the database state exposed via the `&EventContext` argument contains no rows
70-
/// from any subscriptions removed within the same error event.
71-
/// As proposed, it must therefore contain no rows.
72-
///
73-
/// The event in the `&EventContext` argument is `Event::SubscribeError`,
74-
/// containing a dynamic error object with a human-readable description of the error
75-
/// for diagnostic purposes.
76-
///
77-
/// Multiple `on_error` callbacks for the same query may coexist.
78-
/// No mechanism for un-registering `on_error` callbacks is exposed.
82+
/**
83+
* Registers `callback` to run when this query either:
84+
* - Fails to be added to our subscribed set.
85+
* - Is unexpectedly removed from our subscribed set.
86+
*
87+
* If the subscription had previously started and has been unexpectedly removed,
88+
* the database state exposed via the `&EventContext` argument contains no rows
89+
* from any subscriptions removed within the same error event.
90+
* As proposed, it must therefore contain no rows.
91+
*
92+
* The event in the `&EventContext` argument is `Event::SubscribeError`,
93+
* containing a dynamic error object with a human-readable description of the error
94+
* for diagnostic purposes.
95+
*
96+
* Multiple `on_error` callbacks for the same query may coexist.
97+
* No mechanism for un-registering `on_error` callbacks is exposed.
98+
*
99+
* @param cb - Callback to run when there is an error in subscription.
100+
* @returns The current `SubscriptionBuilder` instance.
101+
*/
79102
onError(cb: (ctx: EventContextInterface) => void): SubscriptionBuilder {
80103
this.#onError = cb;
81104
return this;
82105
}
83106

84-
/// Issues a new `Subscribe` message,
85-
/// adding `query` to the client's set of subscribed queries.
86-
///
87-
/// `query` should be a single SQL `SELECT` statement.
88-
///
89-
/// Installs the above callbacks into the new `SubscriptionHandle`,
90-
/// before issuing the `Subscribe` message, to avoid race conditions.
91-
///
92-
/// Consumes the `SubscriptionBuilder`,
93-
/// because the callbacks are not necessarily `Clone`.
107+
/**
108+
* Issues a new `Subscribe` message,
109+
* adding `query` to the client's set of subscribed queries.
110+
*
111+
* `query` should be a single SQL `SELECT` statement.
112+
*
113+
* Installs the above callbacks into the new `SubscriptionHandle`,
114+
* before issuing the `Subscribe` message, to avoid race conditions.
115+
*
116+
* Consumes the `SubscriptionBuilder`,
117+
* because the callbacks are not necessarily `Clone`.
118+
*
119+
* @param query_sql - The SQL query to subscribe to.
120+
*/
94121
subscribe(query_sql: string[]): void {
95122
this.db['subscribe'](query_sql, this.#onApplied, this.#onError);
96123
}
97124
}
98125

126+
/**
127+
* Interface representing a database context.
128+
*
129+
* @template DBView - Type representing the database view.
130+
* @template Reducers - Type representing the reducers.
131+
*/
99132
export interface DBContext<DBView = any, Reducers = any> {
100133
db: DBView;
101134
reducers: Reducers;
102135
isActive: boolean;
136+
137+
/**
138+
* Disconnects from the database.
139+
*/
103140
disconnect(): void;
141+
142+
/**
143+
* Creates a new `SubscriptionBuilder` for building subscription queries.
144+
*
145+
* @returns A new `SubscriptionBuilder` instance.
146+
*/
104147
subscriptionBuilder(): SubscriptionBuilder;
105148
}

packages/sdk/src/event_context.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ export interface EventContextInterface<
66
Reducers = any,
77
Reducer extends { name: string; args?: any } = { name: string; args?: any },
88
> extends DBContext<DBView, Reducers> {
9-
/// Enum with variants for all possible events.
9+
/** Enum with variants for all possible events. */
1010
event: Event<Reducer>;
1111
}

0 commit comments

Comments
 (0)