From 59ddfc46aa38a32ae738e978232a4c548215bf06 Mon Sep 17 00:00:00 2001 From: Jeffrey Dallatezza Date: Fri, 13 Feb 2026 09:13:58 -0800 Subject: [PATCH 1/9] Request table rows when unsubscribing --- crates/bindings-typescript/src/sdk/db_connection_impl.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bindings-typescript/src/sdk/db_connection_impl.ts b/crates/bindings-typescript/src/sdk/db_connection_impl.ts index 96f959f14a8..40e3edc6939 100644 --- a/crates/bindings-typescript/src/sdk/db_connection_impl.ts +++ b/crates/bindings-typescript/src/sdk/db_connection_impl.ts @@ -409,7 +409,7 @@ export class DbConnectionImpl ClientMessage.Unsubscribe({ querySetId: { id: querySetId }, requestId, - flags: UnsubscribeFlags.Default, + flags: UnsubscribeFlags.SendDroppedRows, }) ); } @@ -680,6 +680,7 @@ export class DbConnectionImpl const tableUpdates = result.value.transactionUpdate.querySets.flatMap( qs => this.#querySetUpdateToTableUpdates(qs) ); + // TODO: Fix this context. const event: Event = { tag: 'UnknownTransaction' }; const eventContext = this.#makeEventContext(event); const callbacks = this.#applyTableUpdates(tableUpdates, eventContext); From 57932157cbba8da1c3001751e41c3136dc85474a Mon Sep 17 00:00:00 2001 From: Jeffrey Dallatezza Date: Fri, 13 Feb 2026 10:38:37 -0800 Subject: [PATCH 2/9] Small tweaks for applying transaction updates --- .../src/sdk/db_connection_impl.ts | 53 ++++++++++++++----- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/crates/bindings-typescript/src/sdk/db_connection_impl.ts b/crates/bindings-typescript/src/sdk/db_connection_impl.ts index 40e3edc6939..4d7895ced82 100644 --- a/crates/bindings-typescript/src/sdk/db_connection_impl.ts +++ b/crates/bindings-typescript/src/sdk/db_connection_impl.ts @@ -61,6 +61,7 @@ import type { RowType, UntypedTableDef } from '../lib/table.ts'; import { toCamelCase } from '../lib/util.ts'; import type { ProceduresView } from './procedures.ts'; import type { Values } from '../lib/type_util.ts'; +import type { TransactionUpdate } from './client_api/types.ts'; export { DbConnectionBuilder, @@ -460,6 +461,7 @@ export class DbConnectionImpl return rows; } + // Take a bunch of table updates and ensure that there is at most one update per table. #mergeTableUpdates( updates: CacheTableUpdate[] ): CacheTableUpdate[] { @@ -467,9 +469,9 @@ export class DbConnectionImpl for (const update of updates) { const ops = merged.get(update.tableName); if (ops) { - ops.push(...update.operations); + for (const op of update.operations) ops.push(op); } else { - merged.set(update.tableName, [...update.operations]); + merged.set(update.tableName, update.operations.slice()); } } return Array.from(merged, ([tableName, operations]) => ({ @@ -576,6 +578,31 @@ export class DbConnectionImpl return pendingCallbacks; } + #applyTransactionUpdates( + eventContext: EventContextInterface, + tu: TransactionUpdate + ): PendingCallback[] { + const all_updates: CacheTableUpdate[] = []; + for (const querySetUpdate of tu.querySets) { + const tableUpdates = this.#querySetUpdateToTableUpdates(querySetUpdate); + for (const update of tableUpdates) { + all_updates.push(update); + } + // TODO: When we have per-query storage, we will want to apply the per-query events here. + } + return this.#applyTableUpdates( + this.#mergeTableUpdates(all_updates), + eventContext + ); + const callbacks = this.#applyTableUpdates( + this.#mergeTableUpdates(all_updates), + eventContext + ); + for (const callback of callbacks) { + callback.cb(); + } + } + async #processMessage(data: Uint8Array): Promise { const serverMessage = ServerMessage.deserialize(new BinaryReader(data)); switch (serverMessage.tag) { @@ -663,13 +690,12 @@ export class DbConnectionImpl case 'TransactionUpdate': { const event: Event = { tag: 'UnknownTransaction' }; const eventContext = this.#makeEventContext(event); - for (const querySetUpdate of serverMessage.value.querySets) { - const tableUpdates = - this.#querySetUpdateToTableUpdates(querySetUpdate); - const callbacks = this.#applyTableUpdates(tableUpdates, eventContext); - for (const callback of callbacks) { - callback.cb(); - } + const callbacks = this.#applyTransactionUpdates( + eventContext, + serverMessage.value + ); + for (const callback of callbacks) { + callback.cb(); } break; } @@ -677,13 +703,14 @@ export class DbConnectionImpl const { requestId, result } = serverMessage.value; if (result.tag === 'Ok') { - const tableUpdates = result.value.transactionUpdate.querySets.flatMap( - qs => this.#querySetUpdateToTableUpdates(qs) - ); // TODO: Fix this context. const event: Event = { tag: 'UnknownTransaction' }; const eventContext = this.#makeEventContext(event); - const callbacks = this.#applyTableUpdates(tableUpdates, eventContext); + + const callbacks = this.#applyTransactionUpdates( + eventContext, + result.value.transactionUpdate + ); for (const callback of callbacks) { callback.cb(); } From 692198c63ab5962190a438577eb8b2d9f3e24b95 Mon Sep 17 00:00:00 2001 From: Jeffrey Dallatezza Date: Fri, 13 Feb 2026 10:49:10 -0800 Subject: [PATCH 3/9] Fire reducer callback before row callbacks --- crates/bindings-typescript/src/sdk/db_connection_impl.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/bindings-typescript/src/sdk/db_connection_impl.ts b/crates/bindings-typescript/src/sdk/db_connection_impl.ts index 4d7895ced82..eebc383c8bb 100644 --- a/crates/bindings-typescript/src/sdk/db_connection_impl.ts +++ b/crates/bindings-typescript/src/sdk/db_connection_impl.ts @@ -711,9 +711,13 @@ export class DbConnectionImpl eventContext, result.value.transactionUpdate ); + const cb = this.#reducerCallbacks.get(requestId); + this.#reducerCallbacks.delete(requestId); + cb?.(result); for (const callback of callbacks) { callback.cb(); } + break; } const cb = this.#reducerCallbacks.get(requestId); this.#reducerCallbacks.delete(requestId); From d92b6f4e6a3bd7421978d1647f1d7a2ee00b6531 Mon Sep 17 00:00:00 2001 From: Jeffrey Dallatezza Date: Fri, 13 Feb 2026 13:15:57 -0800 Subject: [PATCH 4/9] make reducer callback ordering match rust and test --- .../src/sdk/db_connection_impl.ts | 4 - .../src/sdk/websocket_test_adapter.ts | 11 ++- .../tests/db_connection.test.ts | 92 ++++++++++++++++++- 3 files changed, 101 insertions(+), 6 deletions(-) diff --git a/crates/bindings-typescript/src/sdk/db_connection_impl.ts b/crates/bindings-typescript/src/sdk/db_connection_impl.ts index eebc383c8bb..4d7895ced82 100644 --- a/crates/bindings-typescript/src/sdk/db_connection_impl.ts +++ b/crates/bindings-typescript/src/sdk/db_connection_impl.ts @@ -711,13 +711,9 @@ export class DbConnectionImpl eventContext, result.value.transactionUpdate ); - const cb = this.#reducerCallbacks.get(requestId); - this.#reducerCallbacks.delete(requestId); - cb?.(result); for (const callback of callbacks) { callback.cb(); } - break; } const cb = this.#reducerCallbacks.get(requestId); this.#reducerCallbacks.delete(requestId); diff --git a/crates/bindings-typescript/src/sdk/websocket_test_adapter.ts b/crates/bindings-typescript/src/sdk/websocket_test_adapter.ts index a63daccbe11..35eb415652c 100644 --- a/crates/bindings-typescript/src/sdk/websocket_test_adapter.ts +++ b/crates/bindings-typescript/src/sdk/websocket_test_adapter.ts @@ -1,5 +1,7 @@ -import { BinaryWriter, type Infer } from '../'; +import { BinaryReader, BinaryWriter, type Infer } from '../'; +import ClientMessageSerde from './client_api/client_message_type'; import ServerMessage from './client_api/server_message_type'; +import type { ClientMessage } from './client_api/types'; class WebsocketTestAdapter { onclose: any; @@ -9,14 +11,21 @@ class WebsocketTestAdapter { onerror: any; messageQueue: any[]; + outgoingMessages: ClientMessage[]; closed: boolean; constructor() { this.messageQueue = []; + this.outgoingMessages = []; this.closed = false; } send(message: any): void { + const parsedMessage = ClientMessageSerde.deserialize( + new BinaryReader(message) + ); + this.outgoingMessages.push(parsedMessage); + // console.ClientMessageSerde.deserialize(message); this.messageQueue.push(message); } diff --git a/crates/bindings-typescript/tests/db_connection.test.ts b/crates/bindings-typescript/tests/db_connection.test.ts index 742b1e4fef2..1cc7781de21 100644 --- a/crates/bindings-typescript/tests/db_connection.test.ts +++ b/crates/bindings-typescript/tests/db_connection.test.ts @@ -1,13 +1,14 @@ import { DbConnection } from '../test-app/src/module_bindings'; import User from '../test-app/src/module_bindings/user_table'; import { beforeEach, describe, expect, test } from 'vitest'; -import { ConnectionId, type Infer } from '../src'; +import { ConnectionId, Timestamp, type Infer } from '../src'; import ServerMessage from '../src/sdk/client_api/server_message_type'; import { Identity } from '../src'; import WebsocketTestAdapter from '../src/sdk/websocket_test_adapter'; import { anIdentity, bobIdentity, + encodePlayer, encodeUser, makeQuerySetUpdate, sallyIdentity, @@ -56,6 +57,38 @@ class Deferred { beforeEach(() => {}); +function getLastCallReducerRequestId(wsAdapter: WebsocketTestAdapter): number { + for (let i = wsAdapter.outgoingMessages.length - 1; i >= 0; i--) { + const message = wsAdapter.outgoingMessages[i]; + if (message.tag === 'CallReducer') { + return message.value.requestId; + } + + console.log('Message: ', JSON.stringify(message)); + } + console.log('Outgoing messages length: ', wsAdapter.outgoingMessages.length); + throw new Error('No CallReducer message found in messageQueue.'); +} + +function makeReducerResult( + requestId: number, + reducerQuerySetUpdate: ReturnType +) { + return ServerMessage.ReducerResult({ + requestId, + timestamp: new Timestamp(0n), + result: { + tag: 'Ok', + value: { + retValue: new Uint8Array(), + transactionUpdate: { + querySets: [reducerQuerySetUpdate], + }, + }, + }, + }); +} + describe('DbConnection', () => { test('call onConnectError callback after websocket connection failed to be established', async () => { const onConnectErrorPromise = new Deferred(); @@ -113,6 +146,63 @@ describe('DbConnection', () => { expect(called).toBeTruthy(); }); + test('fires row callbacks after reducer resolution in ReducerResult', async () => { + const wsAdapter = new WebsocketTestAdapter(); + const onConnectPromise = new Deferred(); + const client = DbConnection.builder() + .withUri('ws://127.0.0.1:1234') + .withDatabaseName('db') + .withWSFn(wsAdapter.createWebSocketFn.bind(wsAdapter) as any) + .onConnect(() => { + onConnectPromise.resolve(); + }) + .build(); + + await client['wsPromise']; + wsAdapter.acceptConnection(); + wsAdapter.sendToClient( + ServerMessage.InitialConnection({ + identity: anIdentity, + token: 'a-token', + connectionId: ConnectionId.random(), + }) + ); + await onConnectPromise.promise; + + let reducerResolved = false; + + const rowCallbackPromise = new Deferred(); + client.db.player.onInsert(() => { + expect(reducerResolved).toBeFalsy(); + rowCallbackPromise.resolve(); + }); + + const reducerPromise = client.reducers.createPlayer({ + name: 'A Player', + location: { x: 1, y: 2 }, + }); + reducerPromise.then(() => { + reducerResolved = true; + }); + // Hack to get the request sent from the client. + await Promise.resolve(); + const requestId = getLastCallReducerRequestId(wsAdapter); + const reducerQuerySetUpdate = makeQuerySetUpdate( + 0, + 'player', + encodePlayer({ + id: 1, + userId: anIdentity, + name: 'A Player', + location: { x: 1, y: 2 }, + }) + ); + wsAdapter.sendToClient(makeReducerResult(requestId, reducerQuerySetUpdate)); + + await rowCallbackPromise.promise; + await reducerPromise; + }); + /* test('it calls onInsert callback when a record is added with a subscription update and then with a transaction update', async () => { const wsAdapter = new WebsocketTestAdapter(); From ff777570f7e79ff681f0683e4e3eb3cd6771c372 Mon Sep 17 00:00:00 2001 From: Jeffrey Dallatezza Date: Mon, 16 Feb 2026 09:01:42 -0800 Subject: [PATCH 5/9] Fix event info --- .../src/sdk/db_connection_impl.ts | 43 +++++++++++++------ .../tests/db_connection.test.ts | 11 ++++- 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/crates/bindings-typescript/src/sdk/db_connection_impl.ts b/crates/bindings-typescript/src/sdk/db_connection_impl.ts index 4d7895ced82..54be1182de8 100644 --- a/crates/bindings-typescript/src/sdk/db_connection_impl.ts +++ b/crates/bindings-typescript/src/sdk/db_connection_impl.ts @@ -155,6 +155,7 @@ export class DbConnectionImpl number, (result: ReducerResultMessage['result']) => void >(); + #reducerCallInfo = new Map(); #procedureCallbacks = new Map(); #rowDeserializers: Record>; #reducerArgsSerializers: Record< @@ -314,7 +315,7 @@ export class DbConnectionImpl const writer = new BinaryWriter(1024); serializeArgs(writer, params); const argsBuffer = writer.getBuffer(); - return this.callReducer(reducerName, argsBuffer); + return this.callReducer(reducerName, argsBuffer, params); }; } @@ -594,13 +595,6 @@ export class DbConnectionImpl this.#mergeTableUpdates(all_updates), eventContext ); - const callbacks = this.#applyTableUpdates( - this.#mergeTableUpdates(all_updates), - eventContext - ); - for (const callback of callbacks) { - callback.cb(); - } } async #processMessage(data: Uint8Array): Promise { @@ -703,9 +697,21 @@ export class DbConnectionImpl const { requestId, result } = serverMessage.value; if (result.tag === 'Ok') { - // TODO: Fix this context. - const event: Event = { tag: 'UnknownTransaction' }; - const eventContext = this.#makeEventContext(event); + const reducerInfo = this.#reducerCallInfo.get(requestId); + const event: Event = reducerInfo + ? { + tag: 'Reducer', + value: { + timestamp: serverMessage.value.timestamp, + outcome: result, + reducer: { + name: reducerInfo.name, + args: reducerInfo.args, + }, + }, + } + : { tag: 'UnknownTransaction' }; + const eventContext = this.#makeEventContext(event as any); const callbacks = this.#applyTransactionUpdates( eventContext, @@ -715,6 +721,7 @@ export class DbConnectionImpl callback.cb(); } } + this.#reducerCallInfo.delete(requestId); const cb = this.#reducerCallbacks.get(requestId); this.#reducerCallbacks.delete(requestId); cb?.(result); @@ -760,7 +767,11 @@ export class DbConnectionImpl * @param reducerName The name of the reducer to call * @param argsSerializer The arguments to pass to the reducer */ - callReducer(reducerName: string, argsBuffer: Uint8Array): Promise { + callReducer( + reducerName: string, + argsBuffer: Uint8Array, + reducerArgs?: object + ): Promise { const { promise, resolve, reject } = Promise.withResolvers(); const requestId = this.#getNextRequestId(); const message = ClientMessage.CallReducer({ @@ -770,6 +781,12 @@ export class DbConnectionImpl flags: 0, }); this.#sendMessage(message); + if (reducerArgs) { + this.#reducerCallInfo.set(requestId, { + name: reducerName, + args: reducerArgs, + }); + } this.#reducerCallbacks.set(requestId, result => { if (result.tag === 'Ok' || result.tag === 'OkEmpty') { resolve(); @@ -795,7 +812,7 @@ export class DbConnectionImpl const writer = new BinaryWriter(1024); this.#reducerArgsSerializers[reducerName].serialize(writer, params); const argsBuffer = writer.getBuffer(); - return this.callReducer(reducerName, argsBuffer); + return this.callReducer(reducerName, argsBuffer, params); } /** diff --git a/crates/bindings-typescript/tests/db_connection.test.ts b/crates/bindings-typescript/tests/db_connection.test.ts index 1cc7781de21..f7a6965063b 100644 --- a/crates/bindings-typescript/tests/db_connection.test.ts +++ b/crates/bindings-typescript/tests/db_connection.test.ts @@ -172,8 +172,16 @@ describe('DbConnection', () => { let reducerResolved = false; const rowCallbackPromise = new Deferred(); - client.db.player.onInsert(() => { + client.db.player.onInsert(ctx => { expect(reducerResolved).toBeFalsy(); + expect(ctx.event.tag).toEqual('Reducer'); + if (ctx.event.tag === 'Reducer') { + expect(ctx.event.value.reducer.name).toEqual('create_player'); + expect(ctx.event.value.reducer.args).toEqual({ + name: 'A Player', + location: { x: 1, y: 2 }, + }); + } rowCallbackPromise.resolve(); }); @@ -201,6 +209,7 @@ describe('DbConnection', () => { await rowCallbackPromise.promise; await reducerPromise; + expect(reducerResolved).toBeTruthy(); }); /* From 9578e41aaf064a1a61b811bd294e78a8c4d2fcc9 Mon Sep 17 00:00:00 2001 From: Jeffrey Dallatezza Date: Mon, 16 Feb 2026 09:37:16 -0800 Subject: [PATCH 6/9] Fix reducer error handling --- .../src/sdk/db_connection_impl.ts | 9 ++- .../tests/db_connection.test.ts | 57 ++++++++++++++++++- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/crates/bindings-typescript/src/sdk/db_connection_impl.ts b/crates/bindings-typescript/src/sdk/db_connection_impl.ts index 54be1182de8..139fcc87daa 100644 --- a/crates/bindings-typescript/src/sdk/db_connection_impl.ts +++ b/crates/bindings-typescript/src/sdk/db_connection_impl.ts @@ -791,7 +791,14 @@ export class DbConnectionImpl if (result.tag === 'Ok' || result.tag === 'OkEmpty') { resolve(); } else { - reject(result.value); + if (result.tag === 'Err') { + /// Interpret the user-returned error as a string. + const reader = new BinaryReader(result.value); + const errorString = reader.readString(); + reject(errorString); + } else { + reject(result.value); + } } }); return promise; diff --git a/crates/bindings-typescript/tests/db_connection.test.ts b/crates/bindings-typescript/tests/db_connection.test.ts index f7a6965063b..4c0d0962417 100644 --- a/crates/bindings-typescript/tests/db_connection.test.ts +++ b/crates/bindings-typescript/tests/db_connection.test.ts @@ -1,7 +1,7 @@ import { DbConnection } from '../test-app/src/module_bindings'; import User from '../test-app/src/module_bindings/user_table'; import { beforeEach, describe, expect, test } from 'vitest'; -import { ConnectionId, Timestamp, type Infer } from '../src'; +import { BinaryWriter, ConnectionId, Timestamp, type Infer } from '../src'; import ServerMessage from '../src/sdk/client_api/server_message_type'; import { Identity } from '../src'; import WebsocketTestAdapter from '../src/sdk/websocket_test_adapter'; @@ -89,6 +89,20 @@ function makeReducerResult( }); } +function makeReducerErrorResult(requestId: number, error: string) { + const errorWriter = new BinaryWriter(64); + errorWriter.writeString(error); + const errorPayload = errorWriter.getBuffer(); + return ServerMessage.ReducerResult({ + requestId, + timestamp: new Timestamp(0n), + result: { + tag: 'Err', + value: errorPayload, + }, + }); +} + describe('DbConnection', () => { test('call onConnectError callback after websocket connection failed to be established', async () => { const onConnectErrorPromise = new Deferred(); @@ -212,6 +226,47 @@ describe('DbConnection', () => { expect(reducerResolved).toBeTruthy(); }); + test('reducer error rejects and does not fire row callbacks', async () => { + const wsAdapter = new WebsocketTestAdapter(); + const onConnectPromise = new Deferred(); + const client = DbConnection.builder() + .withUri('ws://127.0.0.1:1234') + .withDatabaseName('db') + .withWSFn(wsAdapter.createWebSocketFn.bind(wsAdapter) as any) + .onConnect(() => { + onConnectPromise.resolve(); + }) + .build(); + + await client['wsPromise']; + wsAdapter.acceptConnection(); + wsAdapter.sendToClient( + ServerMessage.InitialConnection({ + identity: anIdentity, + token: 'a-token', + connectionId: ConnectionId.random(), + }) + ); + await onConnectPromise.promise; + + let insertCalled = false; + client.db.player.onInsert(() => { + insertCalled = true; + }); + + const reducerPromise = client.reducers.createPlayer({ + name: 'A Player', + location: { x: 1, y: 2 }, + }); + + await Promise.resolve(); + const requestId = getLastCallReducerRequestId(wsAdapter); + wsAdapter.sendToClient(makeReducerErrorResult(requestId, 'test error')); + + await expect(reducerPromise).rejects.toBe('test error'); + expect(insertCalled).toBeFalsy(); + }); + /* test('it calls onInsert callback when a record is added with a subscription update and then with a transaction update', async () => { const wsAdapter = new WebsocketTestAdapter(); From bdfa414ed1bb6ec7af69f95e3bbb9f25fba20866 Mon Sep 17 00:00:00 2001 From: Jeffrey Dallatezza Date: Mon, 16 Feb 2026 10:04:15 -0800 Subject: [PATCH 7/9] Regen some stuff --- .../src/sdk/client_api/index.ts | 2 +- .../test-app/src/module_bindings/index.ts | 20 +++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/crates/bindings-typescript/src/sdk/client_api/index.ts b/crates/bindings-typescript/src/sdk/client_api/index.ts index 673f89b6030..7bc57c79a6b 100644 --- a/crates/bindings-typescript/src/sdk/client_api/index.ts +++ b/crates/bindings-typescript/src/sdk/client_api/index.ts @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.0.0 (commit 901ee64ccec4620a9bbf1090e9cd868040063661). +// This was generated using spacetimedb cli version 2.0.0 (commit 98cb84ff20f3d37dc683c3d3c13ad2cb2bb34fc2). /* eslint-disable */ /* tslint:disable */ diff --git a/crates/bindings-typescript/test-app/src/module_bindings/index.ts b/crates/bindings-typescript/test-app/src/module_bindings/index.ts index 430ed677d7a..a799af68562 100644 --- a/crates/bindings-typescript/test-app/src/module_bindings/index.ts +++ b/crates/bindings-typescript/test-app/src/module_bindings/index.ts @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.0.0 (commit 901ee64ccec4620a9bbf1090e9cd868040063661). +// This was generated using spacetimedb cli version 2.0.0 (commit 98cb84ff20f3d37dc683c3d3c13ad2cb2bb34fc2). /* eslint-disable */ /* tslint:disable */ @@ -50,7 +50,9 @@ const tablesSchema = __schema({ player: __table( { name: 'player', - indexes: [{ name: 'id', algorithm: 'btree', columns: ['id'] }], + indexes: [ + { name: 'player_id_idx_btree', algorithm: 'btree', columns: ['id'] }, + ], constraints: [ { name: 'player_id_key', constraint: 'unique', columns: ['id'] }, ], @@ -60,7 +62,13 @@ const tablesSchema = __schema({ unindexed_player: __table( { name: 'unindexed_player', - indexes: [{ name: 'id', algorithm: 'btree', columns: ['id'] }], + indexes: [ + { + name: 'unindexed_player_id_idx_btree', + algorithm: 'btree', + columns: ['id'], + }, + ], constraints: [ { name: 'unindexed_player_id_key', @@ -75,7 +83,11 @@ const tablesSchema = __schema({ { name: 'user', indexes: [ - { name: 'identity', algorithm: 'btree', columns: ['identity'] }, + { + name: 'user_identity_idx_btree', + algorithm: 'btree', + columns: ['identity'], + }, ], constraints: [ { From bbe99d660f067da8753b250ad5488b312e9022a2 Mon Sep 17 00:00:00 2001 From: Jeffrey Dallatezza Date: Mon, 16 Feb 2026 10:10:43 -0800 Subject: [PATCH 8/9] Fix gen for react-ts --- templates/react-ts/package.json | 2 +- templates/react-ts/src/module_bindings/index.ts | 2 +- templates/react-ts/src/module_bindings/types/reducers.ts | 4 ---- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/templates/react-ts/package.json b/templates/react-ts/package.json index a49c2f23238..bd51ae129ae 100644 --- a/templates/react-ts/package.json +++ b/templates/react-ts/package.json @@ -7,7 +7,7 @@ "dev": "vite", "build": "tsc -b && vite build", "preview": "vite preview", - "generate": "pnpm --dir spacetimedb install --ignore-workspace && cargo run -p gen-bindings -- --out-dir src/module_bindings --project-path spacetimedb && prettier --write src/module_bindings", + "generate": "cargo run -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", "spacetime:generate": "spacetime generate --lang typescript --out-dir src/module_bindings --project-path spacetimedb", "spacetime:publish:local": "spacetime publish --project-path server --server local", "spacetime:publish": "spacetime publish --project-path server --server maincloud" diff --git a/templates/react-ts/src/module_bindings/index.ts b/templates/react-ts/src/module_bindings/index.ts index 8751d04a776..cbc5d6b3eba 100644 --- a/templates/react-ts/src/module_bindings/index.ts +++ b/templates/react-ts/src/module_bindings/index.ts @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.0.0 (commit 901ee64ccec4620a9bbf1090e9cd868040063661). +// This was generated using spacetimedb cli version 2.0.0 (commit 98cb84ff20f3d37dc683c3d3c13ad2cb2bb34fc2). /* eslint-disable */ /* tslint:disable */ diff --git a/templates/react-ts/src/module_bindings/types/reducers.ts b/templates/react-ts/src/module_bindings/types/reducers.ts index 7b434947645..d8ceaeb2709 100644 --- a/templates/react-ts/src/module_bindings/types/reducers.ts +++ b/templates/react-ts/src/module_bindings/types/reducers.ts @@ -7,11 +7,7 @@ import { type Infer as __Infer } from 'spacetimedb'; // Import all reducer arg schemas import AddReducer from '../add_reducer'; -import OnConnectReducer from '../on_connect_reducer'; -import OnDisconnectReducer from '../on_disconnect_reducer'; import SayHelloReducer from '../say_hello_reducer'; export type AddParams = __Infer; -export type OnConnectParams = __Infer; -export type OnDisconnectParams = __Infer; export type SayHelloParams = __Infer; From dac97a0043532a1456a3efb67f11c052ffc1ef93 Mon Sep 17 00:00:00 2001 From: Jeffrey Dallatezza Date: Mon, 16 Feb 2026 10:36:39 -0800 Subject: [PATCH 9/9] Fix generate command for angular-ts --- templates/angular-ts/package.json | 2 +- templates/angular-ts/src/module_bindings/index.ts | 2 +- templates/angular-ts/src/module_bindings/types/reducers.ts | 4 ---- templates/basic-ts/src/module_bindings/index.ts | 2 +- templates/basic-ts/src/module_bindings/types/reducers.ts | 4 ---- templates/chat-react-ts/src/module_bindings/index.ts | 2 +- 6 files changed, 4 insertions(+), 12 deletions(-) diff --git a/templates/angular-ts/package.json b/templates/angular-ts/package.json index 4f8e35ba3b2..2f47cf0e5e4 100644 --- a/templates/angular-ts/package.json +++ b/templates/angular-ts/package.json @@ -6,7 +6,7 @@ "scripts": { "dev": "ng serve", "build": "ng build", - "generate": "pnpm --dir spacetimedb install --ignore-workspace && cargo run -p gen-bindings -- --out-dir src/module_bindings --project-path spacetimedb && prettier --write src/module_bindings", + "generate": "cargo run -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", "spacetime:generate": "spacetime generate --lang typescript --out-dir src/module_bindings --project-path spacetimedb", "spacetime:publish:local": "spacetime publish --project-path spacetimedb --server local", "spacetime:publish": "spacetime publish --project-path spacetimedb --server maincloud" diff --git a/templates/angular-ts/src/module_bindings/index.ts b/templates/angular-ts/src/module_bindings/index.ts index 7b098247c45..cbc5d6b3eba 100644 --- a/templates/angular-ts/src/module_bindings/index.ts +++ b/templates/angular-ts/src/module_bindings/index.ts @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.0.0 (commit 4cf57e2fe6ba480834ee0bb2f6aefa4482550164). +// This was generated using spacetimedb cli version 2.0.0 (commit 98cb84ff20f3d37dc683c3d3c13ad2cb2bb34fc2). /* eslint-disable */ /* tslint:disable */ diff --git a/templates/angular-ts/src/module_bindings/types/reducers.ts b/templates/angular-ts/src/module_bindings/types/reducers.ts index 7b434947645..d8ceaeb2709 100644 --- a/templates/angular-ts/src/module_bindings/types/reducers.ts +++ b/templates/angular-ts/src/module_bindings/types/reducers.ts @@ -7,11 +7,7 @@ import { type Infer as __Infer } from 'spacetimedb'; // Import all reducer arg schemas import AddReducer from '../add_reducer'; -import OnConnectReducer from '../on_connect_reducer'; -import OnDisconnectReducer from '../on_disconnect_reducer'; import SayHelloReducer from '../say_hello_reducer'; export type AddParams = __Infer; -export type OnConnectParams = __Infer; -export type OnDisconnectParams = __Infer; export type SayHelloParams = __Infer; diff --git a/templates/basic-ts/src/module_bindings/index.ts b/templates/basic-ts/src/module_bindings/index.ts index 0ca8d4f8886..0710daad4fc 100644 --- a/templates/basic-ts/src/module_bindings/index.ts +++ b/templates/basic-ts/src/module_bindings/index.ts @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.0.0 (commit 901ee64ccec4620a9bbf1090e9cd868040063661). +// This was generated using spacetimedb cli version 2.0.0 (commit 98cb84ff20f3d37dc683c3d3c13ad2cb2bb34fc2). /* eslint-disable */ /* tslint:disable */ diff --git a/templates/basic-ts/src/module_bindings/types/reducers.ts b/templates/basic-ts/src/module_bindings/types/reducers.ts index 7b434947645..d8ceaeb2709 100644 --- a/templates/basic-ts/src/module_bindings/types/reducers.ts +++ b/templates/basic-ts/src/module_bindings/types/reducers.ts @@ -7,11 +7,7 @@ import { type Infer as __Infer } from 'spacetimedb'; // Import all reducer arg schemas import AddReducer from '../add_reducer'; -import OnConnectReducer from '../on_connect_reducer'; -import OnDisconnectReducer from '../on_disconnect_reducer'; import SayHelloReducer from '../say_hello_reducer'; export type AddParams = __Infer; -export type OnConnectParams = __Infer; -export type OnDisconnectParams = __Infer; export type SayHelloParams = __Infer; diff --git a/templates/chat-react-ts/src/module_bindings/index.ts b/templates/chat-react-ts/src/module_bindings/index.ts index 460ced69795..678713c804a 100644 --- a/templates/chat-react-ts/src/module_bindings/index.ts +++ b/templates/chat-react-ts/src/module_bindings/index.ts @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.0.0 (commit 901ee64ccec4620a9bbf1090e9cd868040063661). +// This was generated using spacetimedb cli version 2.0.0 (commit 98cb84ff20f3d37dc683c3d3c13ad2cb2bb34fc2). /* eslint-disable */ /* tslint:disable */