From 6eb0a6e79696ceab80a1884824973357f1154221 Mon Sep 17 00:00:00 2001 From: Alessandro Asoni Date: Tue, 21 Oct 2025 15:47:32 +0200 Subject: [PATCH 1/6] Code generate filter function for non-unique indexes --- crates/codegen/src/typescript.rs | 91 +++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 30 deletions(-) diff --git a/crates/codegen/src/typescript.rs b/crates/codegen/src/typescript.rs index e8c793be5b8..0f59d0e79ff 100644 --- a/crates/codegen/src/typescript.rs +++ b/crates/codegen/src/typescript.rs @@ -1,6 +1,5 @@ use crate::util::{ - is_reducer_invokable, iter_reducers, iter_tables, iter_types, iter_unique_cols, - print_auto_generated_version_comment, + is_reducer_invokable, iter_indexes, iter_reducers, iter_tables, iter_types, print_auto_generated_version_comment, }; use crate::{indent_scope, OutputFile}; @@ -13,7 +12,10 @@ use std::ops::Deref; use convert_case::{Case, Casing}; use spacetimedb_lib::sats::layout::PrimitiveType; use spacetimedb_lib::sats::AlgebraicTypeRef; -use spacetimedb_schema::def::{ModuleDef, ReducerDef, ScopedTypeName, TableDef, TypeDef}; +use spacetimedb_primitives::ColId; +use spacetimedb_schema::def::{ + BTreeAlgorithm, IndexAlgorithm, ModuleDef, ReducerDef, ScopedTypeName, TableDef, TypeDef, +}; use spacetimedb_schema::identifier::Identifier; use spacetimedb_schema::schema::{Schema, TableSchema}; use spacetimedb_schema::type_for_generate::{AlgebraicTypeDef, AlgebraicTypeUse, ProductTypeDef}; @@ -190,45 +192,76 @@ export class {table_handle} implements __TableHandle = match &index_def.algorithm { + IndexAlgorithm::BTree(BTreeAlgorithm { columns }) => { + let get_name_and_type = |col_pos: ColId| { + let (field_name, field_type) = &product_type.elements[col_pos.idx()]; + let name_pascal = field_name.deref().to_case(Case::Camel); + (name_pascal, field_type) + }; + is_unique = schema.is_unique(columns); + columns.iter().map(get_name_and_type).collect() + } + IndexAlgorithm::Direct(_) => { + eprintln!("Direct indexes are not implemented"); + continue; + } + _ => todo!(), + }; + let function_name = if is_unique { "find" } else { "filter" }; writeln!( out, "/** - * Access to the `{unique_field_name}` unique index on the table `{table_name}`, - * which allows point queries on the field of the same name - * via the [`{unique_constraint}.find`] method. - * - * Users are encouraged not to explicitly reference this type, - * but to directly chain method calls, - * like `ctx.db.{accessor_method}.{unique_field_name}().find(...)`. - * - * Get a handle on the `{unique_field_name}` unique index on the table `{table_name}`. + * Access to the `{index_field_name}` index on the table `{table_name}`, + * with `ctx.db.{accessor_method}.{index_field_name}.{function_name}(...)`. */" ); - writeln!(out, "{unique_field_name} = {{"); + writeln!(out, "{index_field_name} = {{"); out.with_indent(|out| { writeln!( out, - "// Find the subscribed row whose `{unique_field_name}` column value is equal to `col_val`," - ); - writeln!(out, "// if such a row is present in the client cache."); - writeln!( - out, - "find: (col_val: {unique_field_type}): {row_type} | undefined => {{" + "// Find the subscribed row matching the lookup value if present in the client cache." ); + write!(out, "{function_name}: (col_vals: "); + + // if the index has multiple columns the input to `filter` is a tuple + let mut row_values = String::new(); + if index_fields.len() > 1 { + write!(out, "["); + row_values.push('['); + } + for (i, (name, column_type)) in index_fields.iter().enumerate() { + write_type(module, out, column_type, None, None).unwrap(); + row_values.push_str(format!("row.{name}").as_str()); + if i < index_fields.len() - 1 { + write!(out, ","); + row_values.push(','); + } + } + if index_fields.len() > 1 { + write!(out, "]"); + row_values.push(']'); + } + writeln!(out, "): {row_type} | undefined => {{"); out.with_indent(|out| { writeln!(out, "for (let row of this.tableCache.iter()) {{"); out.with_indent(|out| { - writeln!(out, "if (__deepEqual(row.{unique_field_name}, col_val)) {{"); + writeln!(out, "if (__deepEqual({row_values}, col_vals)) {{"); out.with_indent(|out| { writeln!(out, "return row;"); }); @@ -241,8 +274,6 @@ export class {table_handle} implements __TableHandle Date: Tue, 21 Oct 2025 20:11:57 +0200 Subject: [PATCH 2/6] Fix some syntax --- crates/codegen/src/typescript.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/crates/codegen/src/typescript.rs b/crates/codegen/src/typescript.rs index 0f59d0e79ff..273da361ad1 100644 --- a/crates/codegen/src/typescript.rs +++ b/crates/codegen/src/typescript.rs @@ -257,17 +257,31 @@ export class {table_handle} implements __TableHandle {{"); + if is_unique { + writeln!(out, "): {row_type} | undefined => {{"); + } else { + writeln!(out, "): {row_type}[] => {{"); + } out.with_indent(|out| { + if !is_unique { + writeln!(out, "const result: {row_type}[] = [];"); + } writeln!(out, "for (let row of this.tableCache.iter()) {{"); out.with_indent(|out| { writeln!(out, "if (__deepEqual({row_values}, col_vals)) {{"); out.with_indent(|out| { - writeln!(out, "return row;"); + if is_unique { + writeln!(out, "return row;"); + } else { + writeln!(out, "result.push(row);"); + } }); writeln!(out, "}}"); }); writeln!(out, "}}"); + if !is_unique { + writeln!(out, "return result"); + } }); writeln!(out, "}},"); }); From 9fb76ffefa45dc7d590a5432d9f24b9aeb0e0bf8 Mon Sep 17 00:00:00 2001 From: Alessandro Asoni Date: Tue, 21 Oct 2025 20:36:16 +0200 Subject: [PATCH 3/6] Add missing semicolon --- crates/codegen/src/typescript.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/codegen/src/typescript.rs b/crates/codegen/src/typescript.rs index 273da361ad1..e844f65c268 100644 --- a/crates/codegen/src/typescript.rs +++ b/crates/codegen/src/typescript.rs @@ -280,7 +280,7 @@ export class {table_handle} implements __TableHandle Date: Mon, 27 Oct 2025 12:10:43 -0700 Subject: [PATCH 4/6] Regen typescript and update snapshot --- .../src/module_bindings/index.ts | 2 +- .../src/module_bindings/user_table.ts | 20 +- .../raw_misc_module_export_v_9_type.ts | 32 +- .../raw_misc_module_export_v_9_variants.ts | 8 + .../src/sdk/client_api/index.ts | 4 +- .../test-app/src/module_bindings/index.ts | 4 +- .../src/module_bindings/player_table.ts | 20 +- .../src/module_bindings/user_table.ts | 20 +- .../codegen__codegen_typescript.snap | 282 ++++++++---------- 9 files changed, 187 insertions(+), 205 deletions(-) diff --git a/crates/bindings-typescript/examples/quickstart-chat/src/module_bindings/index.ts b/crates/bindings-typescript/examples/quickstart-chat/src/module_bindings/index.ts index f30b1c1253b..fe1c6cd4e81 100644 --- a/crates/bindings-typescript/examples/quickstart-chat/src/module_bindings/index.ts +++ b/crates/bindings-typescript/examples/quickstart-chat/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 1.5.0 (commit 5bfc84351742a6a8dc717b6c0011946f2d1b632d). +// This was generated using spacetimedb cli version 1.6.0 (commit 2b2599073d5dff2b25c0c84b8ac96cb43653ba43). /* eslint-disable */ /* tslint:disable */ diff --git a/crates/bindings-typescript/examples/quickstart-chat/src/module_bindings/user_table.ts b/crates/bindings-typescript/examples/quickstart-chat/src/module_bindings/user_table.ts index 85687a99eff..e0ad21a6ebd 100644 --- a/crates/bindings-typescript/examples/quickstart-chat/src/module_bindings/user_table.ts +++ b/crates/bindings-typescript/examples/quickstart-chat/src/module_bindings/user_table.ts @@ -64,29 +64,21 @@ export class UserTableHandle iter(): Iterable { return this.tableCache.iter(); } + /** - * Access to the `identity` unique index on the table `user`, - * which allows point queries on the field of the same name - * via the [`UserIdentityUnique.find`] method. - * - * Users are encouraged not to explicitly reference this type, - * but to directly chain method calls, - * like `ctx.db.user.identity().find(...)`. - * - * Get a handle on the `identity` unique index on the table `user`. + * Access to the `identity` index on the table `user`, + * with `ctx.db.user.identity.find(...)`. */ identity = { - // Find the subscribed row whose `identity` column value is equal to `col_val`, - // if such a row is present in the client cache. - find: (col_val: __Identity): User | undefined => { + // Find the subscribed row matching the lookup value if present in the client cache. + find: (col_vals: __Identity): User | undefined => { for (let row of this.tableCache.iter()) { - if (__deepEqual(row.identity, col_val)) { + if (__deepEqual(row.identity, col_vals)) { return row; } } }, }; - onInsert = (cb: (ctx: EventContext, row: User) => void) => { return this.tableCache.onInsert(cb); }; diff --git a/crates/bindings-typescript/src/lib/autogen/raw_misc_module_export_v_9_type.ts b/crates/bindings-typescript/src/lib/autogen/raw_misc_module_export_v_9_type.ts index f8a0566672b..e10a92d8844 100644 --- a/crates/bindings-typescript/src/lib/autogen/raw_misc_module_export_v_9_type.ts +++ b/crates/bindings-typescript/src/lib/autogen/raw_misc_module_export_v_9_type.ts @@ -19,12 +19,20 @@ import { import { RawColumnDefaultValueV9 } from './raw_column_default_value_v_9_type'; // Mark import as potentially unused declare type __keep_RawColumnDefaultValueV9 = RawColumnDefaultValueV9; +import { RawProcedureDefV9 } from './raw_procedure_def_v_9_type'; +// Mark import as potentially unused +declare type __keep_RawProcedureDefV9 = RawProcedureDefV9; +import { RawViewDefV9 } from './raw_view_def_v_9_type'; +// Mark import as potentially unused +declare type __keep_RawViewDefV9 = RawViewDefV9; import * as RawMiscModuleExportV9Variants from './raw_misc_module_export_v_9_variants'; // The tagged union or sum type for the algebraic type `RawMiscModuleExportV9`. export type RawMiscModuleExportV9 = - RawMiscModuleExportV9Variants.ColumnDefaultValue; + | RawMiscModuleExportV9Variants.ColumnDefaultValue + | RawMiscModuleExportV9Variants.Procedure + | RawMiscModuleExportV9Variants.View; let _cached_RawMiscModuleExportV9_type_value: __AlgebraicTypeType | null = null; @@ -42,6 +50,13 @@ export const RawMiscModuleExportV9 = { tag: 'ColumnDefaultValue', value, }), + Procedure: ( + value: RawProcedureDefV9 + ): RawMiscModuleExportV9Variants.Procedure => ({ tag: 'Procedure', value }), + View: (value: RawViewDefV9): RawMiscModuleExportV9Variants.View => ({ + tag: 'View', + value, + }), getTypeScriptAlgebraicType(): __AlgebraicTypeType { if (_cached_RawMiscModuleExportV9_type_value) @@ -49,10 +64,17 @@ export const RawMiscModuleExportV9 = { _cached_RawMiscModuleExportV9_type_value = __AlgebraicTypeValue.Sum({ variants: [], }); - _cached_RawMiscModuleExportV9_type_value.value.variants.push({ - name: 'ColumnDefaultValue', - algebraicType: RawColumnDefaultValueV9.getTypeScriptAlgebraicType(), - }); + _cached_RawMiscModuleExportV9_type_value.value.variants.push( + { + name: 'ColumnDefaultValue', + algebraicType: RawColumnDefaultValueV9.getTypeScriptAlgebraicType(), + }, + { + name: 'Procedure', + algebraicType: RawProcedureDefV9.getTypeScriptAlgebraicType(), + }, + { name: 'View', algebraicType: RawViewDefV9.getTypeScriptAlgebraicType() } + ); return _cached_RawMiscModuleExportV9_type_value; }, diff --git a/crates/bindings-typescript/src/lib/autogen/raw_misc_module_export_v_9_variants.ts b/crates/bindings-typescript/src/lib/autogen/raw_misc_module_export_v_9_variants.ts index e65385fac01..a100dd6dc1c 100644 --- a/crates/bindings-typescript/src/lib/autogen/raw_misc_module_export_v_9_variants.ts +++ b/crates/bindings-typescript/src/lib/autogen/raw_misc_module_export_v_9_variants.ts @@ -19,8 +19,16 @@ import { import { RawColumnDefaultValueV9 as RawColumnDefaultValueV9Type } from './raw_column_default_value_v_9_type'; // Mark import as potentially unused declare type __keep_RawColumnDefaultValueV9Type = RawColumnDefaultValueV9Type; +import { RawProcedureDefV9 as RawProcedureDefV9Type } from './raw_procedure_def_v_9_type'; +// Mark import as potentially unused +declare type __keep_RawProcedureDefV9Type = RawProcedureDefV9Type; +import { RawViewDefV9 as RawViewDefV9Type } from './raw_view_def_v_9_type'; +// Mark import as potentially unused +declare type __keep_RawViewDefV9Type = RawViewDefV9Type; export type ColumnDefaultValue = { tag: 'ColumnDefaultValue'; value: RawColumnDefaultValueV9Type; }; +export type Procedure = { tag: 'Procedure'; value: RawProcedureDefV9Type }; +export type View = { tag: 'View'; value: RawViewDefV9Type }; diff --git a/crates/bindings-typescript/src/sdk/client_api/index.ts b/crates/bindings-typescript/src/sdk/client_api/index.ts index 5e3cc809133..eb3add4399f 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 ../../index cli version 1.5.0 (commit 5bfc84351742a6a8dc717b6c0011946f2d1b632d). +// This was generated using ../../index cli version 1.6.0 (commit 2b2599073d5dff2b25c0c84b8ac96cb43653ba43). /* eslint-disable */ /* tslint:disable */ @@ -102,7 +102,7 @@ const REMOTE_MODULE = { tables: {}, reducers: {}, versionInfo: { - cliVersion: '1.5.0', + cliVersion: '1.6.0', }, // Constructors which are used by the DbConnectionImpl to // extract type information from the generated RemoteModule. 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 104b8f6c14c..86420b1f272 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 ../../../src/index cli version 1.5.0 (commit 5bfc84351742a6a8dc717b6c0011946f2d1b632d). +// This was generated using ../../../src/index cli version 1.6.0 (commit 2b2599073d5dff2b25c0c84b8ac96cb43653ba43). /* eslint-disable */ /* tslint:disable */ @@ -88,7 +88,7 @@ const REMOTE_MODULE = { }, }, versionInfo: { - cliVersion: '1.5.0', + cliVersion: '1.6.0', }, // Constructors which are used by the DbConnectionImpl to // extract type information from the generated RemoteModule. diff --git a/crates/bindings-typescript/test-app/src/module_bindings/player_table.ts b/crates/bindings-typescript/test-app/src/module_bindings/player_table.ts index 63a846fa7f6..2e51c6ac891 100644 --- a/crates/bindings-typescript/test-app/src/module_bindings/player_table.ts +++ b/crates/bindings-typescript/test-app/src/module_bindings/player_table.ts @@ -68,29 +68,21 @@ export class PlayerTableHandle iter(): Iterable { return this.tableCache.iter(); } + /** - * Access to the `ownerId` unique index on the table `player`, - * which allows point queries on the field of the same name - * via the [`PlayerOwnerIdUnique.find`] method. - * - * Users are encouraged not to explicitly reference this type, - * but to directly chain method calls, - * like `ctx.db.player.ownerId().find(...)`. - * - * Get a handle on the `ownerId` unique index on the table `player`. + * Access to the `ownerId` index on the table `player`, + * with `ctx.db.player.ownerId.find(...)`. */ ownerId = { - // Find the subscribed row whose `ownerId` column value is equal to `col_val`, - // if such a row is present in the client cache. - find: (col_val: string): Player | undefined => { + // Find the subscribed row matching the lookup value if present in the client cache. + find: (col_vals: string): Player | undefined => { for (let row of this.tableCache.iter()) { - if (__deepEqual(row.ownerId, col_val)) { + if (__deepEqual(row.ownerId, col_vals)) { return row; } } }, }; - onInsert = (cb: (ctx: EventContext, row: Player) => void) => { return this.tableCache.onInsert(cb); }; diff --git a/crates/bindings-typescript/test-app/src/module_bindings/user_table.ts b/crates/bindings-typescript/test-app/src/module_bindings/user_table.ts index 21275ac19c1..a72ec6b63c6 100644 --- a/crates/bindings-typescript/test-app/src/module_bindings/user_table.ts +++ b/crates/bindings-typescript/test-app/src/module_bindings/user_table.ts @@ -64,29 +64,21 @@ export class UserTableHandle iter(): Iterable { return this.tableCache.iter(); } + /** - * Access to the `identity` unique index on the table `user`, - * which allows point queries on the field of the same name - * via the [`UserIdentityUnique.find`] method. - * - * Users are encouraged not to explicitly reference this type, - * but to directly chain method calls, - * like `ctx.db.user.identity().find(...)`. - * - * Get a handle on the `identity` unique index on the table `user`. + * Access to the `identity` index on the table `user`, + * with `ctx.db.user.identity.find(...)`. */ identity = { - // Find the subscribed row whose `identity` column value is equal to `col_val`, - // if such a row is present in the client cache. - find: (col_val: __Identity): User | undefined => { + // Find the subscribed row matching the lookup value if present in the client cache. + find: (col_vals: __Identity): User | undefined => { for (let row of this.tableCache.iter()) { - if (__deepEqual(row.identity, col_val)) { + if (__deepEqual(row.identity, col_vals)) { return row; } } }, }; - onInsert = (cb: (ctx: EventContext, row: User) => void) => { return this.tableCache.onInsert(cb); }; diff --git a/crates/codegen/tests/snapshots/codegen__codegen_typescript.snap b/crates/codegen/tests/snapshots/codegen__codegen_typescript.snap index ee6178b0c03..acf37403bdc 100644 --- a/crates/codegen/tests/snapshots/codegen__codegen_typescript.snap +++ b/crates/codegen/tests/snapshots/codegen__codegen_typescript.snap @@ -1639,73 +1639,49 @@ export class LoggedOutPlayerTableHandle implements __T iter(): Iterable { return this.tableCache.iter(); } + /** - * Access to the `identity` unique index on the table `logged_out_player`, - * which allows point queries on the field of the same name - * via the [`LoggedOutPlayerIdentityUnique.find`] method. - * - * Users are encouraged not to explicitly reference this type, - * but to directly chain method calls, - * like `ctx.db.loggedOutPlayer.identity().find(...)`. - * - * Get a handle on the `identity` unique index on the table `logged_out_player`. + * Access to the `identity` index on the table `logged_out_player`, + * with `ctx.db.loggedOutPlayer.identity.find(...)`. */ identity = { - // Find the subscribed row whose `identity` column value is equal to `col_val`, - // if such a row is present in the client cache. - find: (col_val: __Identity): Player | undefined => { + // Find the subscribed row matching the lookup value if present in the client cache. + find: (col_vals: __Identity): Player | undefined => { for (let row of this.tableCache.iter()) { - if (__deepEqual(row.identity, col_val)) { + if (__deepEqual(row.identity, col_vals)) { return row; } } }, }; /** - * Access to the `playerId` unique index on the table `logged_out_player`, - * which allows point queries on the field of the same name - * via the [`LoggedOutPlayerPlayerIdUnique.find`] method. - * - * Users are encouraged not to explicitly reference this type, - * but to directly chain method calls, - * like `ctx.db.loggedOutPlayer.playerId().find(...)`. - * - * Get a handle on the `playerId` unique index on the table `logged_out_player`. + * Access to the `name` index on the table `logged_out_player`, + * with `ctx.db.loggedOutPlayer.name.find(...)`. */ - playerId = { - // Find the subscribed row whose `playerId` column value is equal to `col_val`, - // if such a row is present in the client cache. - find: (col_val: bigint): Player | undefined => { + name = { + // Find the subscribed row matching the lookup value if present in the client cache. + find: (col_vals: string): Player | undefined => { for (let row of this.tableCache.iter()) { - if (__deepEqual(row.playerId, col_val)) { + if (__deepEqual(row.name, col_vals)) { return row; } } }, }; /** - * Access to the `name` unique index on the table `logged_out_player`, - * which allows point queries on the field of the same name - * via the [`LoggedOutPlayerNameUnique.find`] method. - * - * Users are encouraged not to explicitly reference this type, - * but to directly chain method calls, - * like `ctx.db.loggedOutPlayer.name().find(...)`. - * - * Get a handle on the `name` unique index on the table `logged_out_player`. + * Access to the `playerId` index on the table `logged_out_player`, + * with `ctx.db.loggedOutPlayer.playerId.find(...)`. */ - name = { - // Find the subscribed row whose `name` column value is equal to `col_val`, - // if such a row is present in the client cache. - find: (col_val: string): Player | undefined => { + playerId = { + // Find the subscribed row matching the lookup value if present in the client cache. + find: (col_vals: bigint): Player | undefined => { for (let row of this.tableCache.iter()) { - if (__deepEqual(row.name, col_val)) { + if (__deepEqual(row.playerId, col_vals)) { return row; } } }, }; - onInsert = (cb: (ctx: EventContext, row: Player) => void) => { return this.tableCache.onInsert(cb); } @@ -2011,29 +1987,37 @@ export class PersonTableHandle implements __TableHandl iter(): Iterable { return this.tableCache.iter(); } + /** - * Access to the `id` unique index on the table `person`, - * which allows point queries on the field of the same name - * via the [`PersonIdUnique.find`] method. - * - * Users are encouraged not to explicitly reference this type, - * but to directly chain method calls, - * like `ctx.db.person.id().find(...)`. - * - * Get a handle on the `id` unique index on the table `person`. + * Access to the `age` index on the table `person`, + * with `ctx.db.person.age.filter(...)`. + */ + age = { + // Find the subscribed row matching the lookup value if present in the client cache. + filter: (col_vals: number): Person[] => { + const result: Person[] = []; + for (let row of this.tableCache.iter()) { + if (__deepEqual(row.age, col_vals)) { + result.push(row); + } + } + return result; + }, + }; + /** + * Access to the `id` index on the table `person`, + * with `ctx.db.person.id.find(...)`. */ id = { - // Find the subscribed row whose `id` column value is equal to `col_val`, - // if such a row is present in the client cache. - find: (col_val: number): Person | undefined => { + // Find the subscribed row matching the lookup value if present in the client cache. + find: (col_vals: number): Person | undefined => { for (let row of this.tableCache.iter()) { - if (__deepEqual(row.id, col_val)) { + if (__deepEqual(row.id, col_vals)) { return row; } } }, }; - onInsert = (cb: (ctx: EventContext, row: Person) => void) => { return this.tableCache.onInsert(cb); } @@ -2190,51 +2174,35 @@ export class PkMultiIdentityTableHandle implements __T iter(): Iterable { return this.tableCache.iter(); } + /** - * Access to the `id` unique index on the table `pk_multi_identity`, - * which allows point queries on the field of the same name - * via the [`PkMultiIdentityIdUnique.find`] method. - * - * Users are encouraged not to explicitly reference this type, - * but to directly chain method calls, - * like `ctx.db.pkMultiIdentity.id().find(...)`. - * - * Get a handle on the `id` unique index on the table `pk_multi_identity`. + * Access to the `id` index on the table `pk_multi_identity`, + * with `ctx.db.pkMultiIdentity.id.find(...)`. */ id = { - // Find the subscribed row whose `id` column value is equal to `col_val`, - // if such a row is present in the client cache. - find: (col_val: number): PkMultiIdentity | undefined => { + // Find the subscribed row matching the lookup value if present in the client cache. + find: (col_vals: number): PkMultiIdentity | undefined => { for (let row of this.tableCache.iter()) { - if (__deepEqual(row.id, col_val)) { + if (__deepEqual(row.id, col_vals)) { return row; } } }, }; /** - * Access to the `other` unique index on the table `pk_multi_identity`, - * which allows point queries on the field of the same name - * via the [`PkMultiIdentityOtherUnique.find`] method. - * - * Users are encouraged not to explicitly reference this type, - * but to directly chain method calls, - * like `ctx.db.pkMultiIdentity.other().find(...)`. - * - * Get a handle on the `other` unique index on the table `pk_multi_identity`. + * Access to the `other` index on the table `pk_multi_identity`, + * with `ctx.db.pkMultiIdentity.other.find(...)`. */ other = { - // Find the subscribed row whose `other` column value is equal to `col_val`, - // if such a row is present in the client cache. - find: (col_val: number): PkMultiIdentity | undefined => { + // Find the subscribed row matching the lookup value if present in the client cache. + find: (col_vals: number): PkMultiIdentity | undefined => { for (let row of this.tableCache.iter()) { - if (__deepEqual(row.other, col_val)) { + if (__deepEqual(row.other, col_vals)) { return row; } } }, }; - onInsert = (cb: (ctx: EventContext, row: PkMultiIdentity) => void) => { return this.tableCache.onInsert(cb); } @@ -2389,73 +2357,49 @@ export class PlayerTableHandle implements __TableHandl iter(): Iterable { return this.tableCache.iter(); } + /** - * Access to the `identity` unique index on the table `player`, - * which allows point queries on the field of the same name - * via the [`PlayerIdentityUnique.find`] method. - * - * Users are encouraged not to explicitly reference this type, - * but to directly chain method calls, - * like `ctx.db.player.identity().find(...)`. - * - * Get a handle on the `identity` unique index on the table `player`. + * Access to the `identity` index on the table `player`, + * with `ctx.db.player.identity.find(...)`. */ identity = { - // Find the subscribed row whose `identity` column value is equal to `col_val`, - // if such a row is present in the client cache. - find: (col_val: __Identity): Player | undefined => { + // Find the subscribed row matching the lookup value if present in the client cache. + find: (col_vals: __Identity): Player | undefined => { for (let row of this.tableCache.iter()) { - if (__deepEqual(row.identity, col_val)) { + if (__deepEqual(row.identity, col_vals)) { return row; } } }, }; /** - * Access to the `playerId` unique index on the table `player`, - * which allows point queries on the field of the same name - * via the [`PlayerPlayerIdUnique.find`] method. - * - * Users are encouraged not to explicitly reference this type, - * but to directly chain method calls, - * like `ctx.db.player.playerId().find(...)`. - * - * Get a handle on the `playerId` unique index on the table `player`. + * Access to the `name` index on the table `player`, + * with `ctx.db.player.name.find(...)`. */ - playerId = { - // Find the subscribed row whose `playerId` column value is equal to `col_val`, - // if such a row is present in the client cache. - find: (col_val: bigint): Player | undefined => { + name = { + // Find the subscribed row matching the lookup value if present in the client cache. + find: (col_vals: string): Player | undefined => { for (let row of this.tableCache.iter()) { - if (__deepEqual(row.playerId, col_val)) { + if (__deepEqual(row.name, col_vals)) { return row; } } }, }; /** - * Access to the `name` unique index on the table `player`, - * which allows point queries on the field of the same name - * via the [`PlayerNameUnique.find`] method. - * - * Users are encouraged not to explicitly reference this type, - * but to directly chain method calls, - * like `ctx.db.player.name().find(...)`. - * - * Get a handle on the `name` unique index on the table `player`. + * Access to the `playerId` index on the table `player`, + * with `ctx.db.player.playerId.find(...)`. */ - name = { - // Find the subscribed row whose `name` column value is equal to `col_val`, - // if such a row is present in the client cache. - find: (col_val: string): Player | undefined => { + playerId = { + // Find the subscribed row matching the lookup value if present in the client cache. + find: (col_vals: bigint): Player | undefined => { for (let row of this.tableCache.iter()) { - if (__deepEqual(row.name, col_val)) { + if (__deepEqual(row.playerId, col_vals)) { return row; } } }, }; - onInsert = (cb: (ctx: EventContext, row: Player) => void) => { return this.tableCache.onInsert(cb); } @@ -2682,6 +2626,22 @@ export class PointsTableHandle implements __TableHandl return this.tableCache.iter(); } + /** + * Access to the `multiColumnIndex` index on the table `points`, + * with `ctx.db.points.multiColumnIndex.filter(...)`. + */ + multiColumnIndex = { + // Find the subscribed row matching the lookup value if present in the client cache. + filter: (col_vals: [bigint,bigint]): Point[] => { + const result: Point[] = []; + for (let row of this.tableCache.iter()) { + if (__deepEqual([row.x,row.y], col_vals)) { + result.push(row); + } + } + return result; + }, + }; onInsert = (cb: (ctx: EventContext, row: Point) => void) => { return this.tableCache.onInsert(cb); } @@ -2967,29 +2927,21 @@ export class RepeatingTestArgTableHandle implements __ iter(): Iterable { return this.tableCache.iter(); } + /** - * Access to the `scheduledId` unique index on the table `repeating_test_arg`, - * which allows point queries on the field of the same name - * via the [`RepeatingTestArgScheduledIdUnique.find`] method. - * - * Users are encouraged not to explicitly reference this type, - * but to directly chain method calls, - * like `ctx.db.repeatingTestArg.scheduledId().find(...)`. - * - * Get a handle on the `scheduledId` unique index on the table `repeating_test_arg`. + * Access to the `scheduledId` index on the table `repeating_test_arg`, + * with `ctx.db.repeatingTestArg.scheduledId.find(...)`. */ scheduledId = { - // Find the subscribed row whose `scheduledId` column value is equal to `col_val`, - // if such a row is present in the client cache. - find: (col_val: bigint): RepeatingTestArg | undefined => { + // Find the subscribed row matching the lookup value if present in the client cache. + find: (col_vals: bigint): RepeatingTestArg | undefined => { for (let row of this.tableCache.iter()) { - if (__deepEqual(row.scheduledId, col_val)) { + if (__deepEqual(row.scheduledId, col_vals)) { return row; } } }, }; - onInsert = (cb: (ctx: EventContext, row: RepeatingTestArg) => void) => { return this.tableCache.onInsert(cb); } @@ -3280,6 +3232,22 @@ export class TestATableHandle implements __TableHandle return this.tableCache.iter(); } + /** + * Access to the `foo` index on the table `test_a`, + * with `ctx.db.testA.foo.filter(...)`. + */ + foo = { + // Find the subscribed row matching the lookup value if present in the client cache. + filter: (col_vals: number): TestA[] => { + const result: TestA[] = []; + for (let row of this.tableCache.iter()) { + if (__deepEqual(row.x, col_vals)) { + result.push(row); + } + } + return result; + }, + }; onInsert = (cb: (ctx: EventContext, row: TestA) => void) => { return this.tableCache.onInsert(cb); } @@ -3711,29 +3679,37 @@ export class TestETableHandle implements __TableHandle iter(): Iterable { return this.tableCache.iter(); } + /** - * Access to the `id` unique index on the table `test_e`, - * which allows point queries on the field of the same name - * via the [`TestEIdUnique.find`] method. - * - * Users are encouraged not to explicitly reference this type, - * but to directly chain method calls, - * like `ctx.db.testE.id().find(...)`. - * - * Get a handle on the `id` unique index on the table `test_e`. + * Access to the `id` index on the table `test_e`, + * with `ctx.db.testE.id.find(...)`. */ id = { - // Find the subscribed row whose `id` column value is equal to `col_val`, - // if such a row is present in the client cache. - find: (col_val: bigint): TestE | undefined => { + // Find the subscribed row matching the lookup value if present in the client cache. + find: (col_vals: bigint): TestE | undefined => { for (let row of this.tableCache.iter()) { - if (__deepEqual(row.id, col_val)) { + if (__deepEqual(row.id, col_vals)) { return row; } } }, }; - + /** + * Access to the `name` index on the table `test_e`, + * with `ctx.db.testE.name.filter(...)`. + */ + name = { + // Find the subscribed row matching the lookup value if present in the client cache. + filter: (col_vals: string): TestE[] => { + const result: TestE[] = []; + for (let row of this.tableCache.iter()) { + if (__deepEqual(row.name, col_vals)) { + result.push(row); + } + } + return result; + }, + }; onInsert = (cb: (ctx: EventContext, row: TestE) => void) => { return this.tableCache.onInsert(cb); } From 8f69b90aef6e932485cf4fe42fcb7746a75142fd Mon Sep 17 00:00:00 2001 From: Jeffrey Dallatezza Date: Mon, 27 Oct 2025 14:18:11 -0700 Subject: [PATCH 5/6] Remove println --- crates/codegen/src/typescript.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/codegen/src/typescript.rs b/crates/codegen/src/typescript.rs index e844f65c268..f7b40381c00 100644 --- a/crates/codegen/src/typescript.rs +++ b/crates/codegen/src/typescript.rs @@ -217,7 +217,7 @@ export class {table_handle} implements __TableHandle { - eprintln!("Direct indexes are not implemented"); + // Direct indexes are not implemented yet. continue; } _ => todo!(), From 3bf9d3af8a42c8d939977d9402c17622191b0a99 Mon Sep 17 00:00:00 2001 From: Jeffrey Dallatezza Date: Tue, 28 Oct 2025 10:06:00 -0700 Subject: [PATCH 6/6] Add the new generated files --- .../lib/autogen/raw_procedure_def_v_9_type.ts | 77 ++++++++++++++++++ .../src/lib/autogen/raw_view_def_v_9_type.ts | 80 +++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 crates/bindings-typescript/src/lib/autogen/raw_procedure_def_v_9_type.ts create mode 100644 crates/bindings-typescript/src/lib/autogen/raw_view_def_v_9_type.ts diff --git a/crates/bindings-typescript/src/lib/autogen/raw_procedure_def_v_9_type.ts b/crates/bindings-typescript/src/lib/autogen/raw_procedure_def_v_9_type.ts new file mode 100644 index 00000000000..8c422c869be --- /dev/null +++ b/crates/bindings-typescript/src/lib/autogen/raw_procedure_def_v_9_type.ts @@ -0,0 +1,77 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +/* eslint-disable */ +/* tslint:disable */ +import { + AlgebraicType as __AlgebraicTypeValue, + BinaryReader as __BinaryReader, + BinaryWriter as __BinaryWriter, + ConnectionId as __ConnectionId, + Identity as __Identity, + TimeDuration as __TimeDuration, + Timestamp as __Timestamp, + deepEqual as __deepEqual, + type AlgebraicType as __AlgebraicTypeType, + type AlgebraicTypeVariants as __AlgebraicTypeVariants, + type TableHandle as __TableHandle, +} from '../../index'; +import { AlgebraicType } from './algebraic_type_type'; +// Mark import as potentially unused +declare type __keep_AlgebraicType = AlgebraicType; +import { ProductType } from './product_type_type'; +// Mark import as potentially unused +declare type __keep_ProductType = ProductType; + +export type RawProcedureDefV9 = { + name: string; + params: ProductType; + returnType: AlgebraicType; +}; +let _cached_RawProcedureDefV9_type_value: __AlgebraicTypeType | null = null; + +/** + * An object for generated helper functions. + */ +export const RawProcedureDefV9 = { + /** + * A function which returns this type represented as an AlgebraicType. + * This function is derived from the AlgebraicType used to generate this type. + */ + getTypeScriptAlgebraicType(): __AlgebraicTypeType { + if (_cached_RawProcedureDefV9_type_value) + return _cached_RawProcedureDefV9_type_value; + _cached_RawProcedureDefV9_type_value = __AlgebraicTypeValue.Product({ + elements: [], + }); + _cached_RawProcedureDefV9_type_value.value.elements.push( + { name: 'name', algebraicType: __AlgebraicTypeValue.String }, + { + name: 'params', + algebraicType: ProductType.getTypeScriptAlgebraicType(), + }, + { + name: 'returnType', + algebraicType: AlgebraicType.getTypeScriptAlgebraicType(), + } + ); + return _cached_RawProcedureDefV9_type_value; + }, + + serialize(writer: __BinaryWriter, value: RawProcedureDefV9): void { + __AlgebraicTypeValue.serializeValue( + writer, + RawProcedureDefV9.getTypeScriptAlgebraicType(), + value + ); + }, + + deserialize(reader: __BinaryReader): RawProcedureDefV9 { + return __AlgebraicTypeValue.deserializeValue( + reader, + RawProcedureDefV9.getTypeScriptAlgebraicType() + ); + }, +}; + +export default RawProcedureDefV9; diff --git a/crates/bindings-typescript/src/lib/autogen/raw_view_def_v_9_type.ts b/crates/bindings-typescript/src/lib/autogen/raw_view_def_v_9_type.ts new file mode 100644 index 00000000000..d2386eb4301 --- /dev/null +++ b/crates/bindings-typescript/src/lib/autogen/raw_view_def_v_9_type.ts @@ -0,0 +1,80 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +/* eslint-disable */ +/* tslint:disable */ +import { + AlgebraicType as __AlgebraicTypeValue, + BinaryReader as __BinaryReader, + BinaryWriter as __BinaryWriter, + ConnectionId as __ConnectionId, + Identity as __Identity, + TimeDuration as __TimeDuration, + Timestamp as __Timestamp, + deepEqual as __deepEqual, + type AlgebraicType as __AlgebraicTypeType, + type AlgebraicTypeVariants as __AlgebraicTypeVariants, + type TableHandle as __TableHandle, +} from '../../index'; +import { AlgebraicType } from './algebraic_type_type'; +// Mark import as potentially unused +declare type __keep_AlgebraicType = AlgebraicType; +import { ProductType } from './product_type_type'; +// Mark import as potentially unused +declare type __keep_ProductType = ProductType; + +export type RawViewDefV9 = { + name: string; + isPublic: boolean; + isAnonymous: boolean; + params: ProductType; + returnType: AlgebraicType; +}; +let _cached_RawViewDefV9_type_value: __AlgebraicTypeType | null = null; + +/** + * An object for generated helper functions. + */ +export const RawViewDefV9 = { + /** + * A function which returns this type represented as an AlgebraicType. + * This function is derived from the AlgebraicType used to generate this type. + */ + getTypeScriptAlgebraicType(): __AlgebraicTypeType { + if (_cached_RawViewDefV9_type_value) return _cached_RawViewDefV9_type_value; + _cached_RawViewDefV9_type_value = __AlgebraicTypeValue.Product({ + elements: [], + }); + _cached_RawViewDefV9_type_value.value.elements.push( + { name: 'name', algebraicType: __AlgebraicTypeValue.String }, + { name: 'isPublic', algebraicType: __AlgebraicTypeValue.Bool }, + { name: 'isAnonymous', algebraicType: __AlgebraicTypeValue.Bool }, + { + name: 'params', + algebraicType: ProductType.getTypeScriptAlgebraicType(), + }, + { + name: 'returnType', + algebraicType: AlgebraicType.getTypeScriptAlgebraicType(), + } + ); + return _cached_RawViewDefV9_type_value; + }, + + serialize(writer: __BinaryWriter, value: RawViewDefV9): void { + __AlgebraicTypeValue.serializeValue( + writer, + RawViewDefV9.getTypeScriptAlgebraicType(), + value + ); + }, + + deserialize(reader: __BinaryReader): RawViewDefV9 { + return __AlgebraicTypeValue.deserializeValue( + reader, + RawViewDefV9.getTypeScriptAlgebraicType() + ); + }, +}; + +export default RawViewDefV9;