Skip to content

Commit 97371c4

Browse files
committed
[TS] Fix useTable casing issues
1 parent e5f1558 commit 97371c4

15 files changed

Lines changed: 602 additions & 156 deletions

File tree

crates/bindings-typescript/examples/basic-react/src/module_bindings/index.ts

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/bindings-typescript/examples/empty/src/module_bindings/index.ts

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/bindings-typescript/examples/quickstart-chat/src/module_bindings/index.ts

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/bindings-typescript/src/lib/schema.ts

Lines changed: 56 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import {
3636
} from './algebraic_type';
3737
import type RawScopedTypeNameV9 from './autogen/raw_scoped_type_name_v_9_type';
3838
import type { CamelCase } from './type_util';
39-
import type { TableSchema } from './table_schema';
39+
import type { UntypedTableSchema } from './table_schema';
4040
import { toCamelCase } from './util';
4141
import {
4242
defineView,
@@ -45,8 +45,7 @@ import {
4545
type ViewOpts,
4646
type ViewReturnTypeBuilder,
4747
} from './views';
48-
import RawIndexDefV9 from './autogen/raw_index_def_v_9_type';
49-
import type { IndexOpts } from './indexes';
48+
import type { UntypedIndex } from './indexes';
5049
import { procedure, type ProcedureFn } from './procedures';
5150

5251
export type TableNamesOf<S extends UntypedSchemaDef> =
@@ -71,76 +70,63 @@ export function getRegisteredSchema(): UntypedSchemaDef {
7170
/**
7271
* Helper type to convert an array of TableSchema into a schema definition
7372
*/
74-
type TablesToSchema<T extends readonly TableSchema<any, any, any>[]> = {
73+
type TablesToSchema<T extends readonly UntypedTableSchema[]> = {
7574
tables: {
76-
/** @type {UntypedTableDef} */
77-
readonly [i in keyof T]: {
78-
name: T[i]['tableName'];
79-
accessorName: CamelCase<T[i]['tableName']>;
80-
columns: T[i]['rowType']['row'];
81-
rowType: T[i]['rowSpacetimeType'];
82-
indexes: T[i]['idxs'];
83-
constraints: T[i]['constraints'];
84-
};
75+
readonly [i in keyof T]: TableToSchema<T[i]>;
8576
};
8677
};
8778

88-
export function tablesToSchema<
89-
const T extends readonly TableSchema<any, any, readonly any[]>[],
90-
>(tables: T): TablesToSchema<T> {
91-
const result = {
92-
tables: tables.map(schema => {
93-
const colNameList: string[] = [];
94-
schema.rowType.algebraicType.value.elements.forEach(elem => {
95-
colNameList.push(elem.name);
96-
});
79+
interface TableToSchema<T extends UntypedTableSchema> extends UntypedTableDef {
80+
name: T['tableName'];
81+
accessorName: CamelCase<T['tableName']>;
82+
columns: T['rowType']['row'];
83+
rowType: T['rowSpacetimeType'];
84+
indexes: T['idxs'];
85+
constraints: T['constraints'];
86+
}
87+
88+
export function tablesToSchema<const T extends readonly UntypedTableSchema[]>(
89+
tables: T
90+
): TablesToSchema<T> {
91+
return { tables: tables.map(tableToSchema) as TablesToSchema<T>['tables'] };
92+
}
9793

94+
function tableToSchema<T extends UntypedTableSchema>(
95+
schema: T
96+
): TableToSchema<T> {
97+
const getColName = (i: number) =>
98+
schema.rowType.algebraicType.value.elements[i].name;
99+
100+
type AllowedCol = keyof T['rowType']['row'] & string;
101+
return {
102+
name: schema.tableName,
103+
accessorName: toCamelCase(schema.tableName as T['tableName']),
104+
columns: schema.rowType.row, // typed as T[i]['rowType']['row'] under TablesToSchema<T>
105+
rowType: schema.rowSpacetimeType,
106+
constraints: schema.tableDef.constraints.map(c => ({
107+
name: c.name,
108+
constraint: 'unique',
109+
columns: c.data.value.columns.map(getColName) as [string],
110+
})),
111+
// TODO: horrible horrible horrible. we smuggle this `Array<UntypedIndex>`
112+
// by casting it to an `Array<IndexOpts>` as `TableToSchema` expects.
113+
// This is then used in `TableCacheImpl.constructor` and who knows where else.
114+
// We should stop lying about our types.
115+
indexes: schema.tableDef.indexes.map((idx): UntypedIndex<AllowedCol> => {
116+
const columnIds =
117+
idx.algorithm.tag === 'Direct'
118+
? [idx.algorithm.value]
119+
: idx.algorithm.value;
98120
return {
99-
name: schema.tableName,
100-
accessorName: toCamelCase(schema.tableName),
101-
columns: schema.rowType.row, // typed as T[i]['rowType']['row'] under TablesToSchema<T>
102-
rowType: schema.rowSpacetimeType,
103-
constraints: [
104-
...schema.tableDef.constraints.map(c => ({
105-
name: c.name,
106-
constraint: 'unique' as const,
107-
columns: Array.from(c.data.value.columns.map(i => colNameList[i])),
108-
})),
109-
],
110-
// UntypedTableDef expects mutable array; idxs are readonly, spread to copy.
111-
indexes: [
112-
...schema.idxs.map(
113-
(idx: Infer<typeof RawIndexDefV9>): IndexOpts<any> => {
114-
const columnIds =
115-
idx.algorithm.tag === 'Direct'
116-
? [idx.algorithm.value]
117-
: idx.algorithm.value;
118-
const columns = columnIds.map(i => colNameList[i]);
119-
return {
120-
name: idx.accessorName,
121-
unique: schema.tableDef.constraints.some(c =>
122-
c.data.value.columns.every(col => columnIds.includes(col))
123-
),
124-
algorithm: idx.algorithm.tag.toLowerCase() as 'btree',
125-
columns,
126-
} as IndexOpts<any>;
127-
}
128-
),
129-
],
130-
} as const;
131-
}) as {
132-
// preserve tuple indices so the return type matches `[i in keyof T]`
133-
readonly [I in keyof T]: {
134-
name: T[I]['tableName'];
135-
accessorName: CamelCase<T[I]['tableName']>;
136-
columns: T[I]['rowType']['row'];
137-
rowType: T[I]['rowSpacetimeType'];
138-
indexes: T[I]['idxs'];
139-
constraints: T[I]['constraints'];
121+
name: idx.accessorName!,
122+
unique: schema.tableDef.constraints.some(c =>
123+
c.data.value.columns.every(col => columnIds.includes(col))
124+
),
125+
algorithm: idx.algorithm.tag.toLowerCase() as 'btree',
126+
columns: columnIds.map(getColName),
140127
};
141-
},
142-
} satisfies TablesToSchema<T>;
143-
return result;
128+
}) as T['idxs'],
129+
};
144130
}
145131

146132
/**
@@ -333,7 +319,7 @@ class Schema<S extends UntypedSchemaDef> {
333319
constructor(
334320
tables: Infer<typeof RawTableDefV9>[],
335321
typespace: Infer<typeof Typespace>,
336-
handles: readonly TableSchema<any, any, any>[]
322+
handles: readonly UntypedTableSchema[]
337323
) {
338324
this.tablesDef = { tables };
339325
this.typespace = typespace;
@@ -597,7 +583,7 @@ export type InferSchema<SchemaDef extends Schema<any>> =
597583
* );
598584
* ```
599585
*/
600-
export function schema<const H extends readonly TableSchema<any, any, any>[]>(
586+
export function schema<const H extends readonly UntypedTableSchema[]>(
601587
...handles: H
602588
): Schema<TablesToSchema<H>>;
603589

@@ -606,7 +592,7 @@ export function schema<const H extends readonly TableSchema<any, any, any>[]>(
606592
* @param handles - Array of table handles created by table() function
607593
* @returns ColumnBuilder representing the complete database schema
608594
*/
609-
export function schema<const H extends readonly TableSchema<any, any, any>[]>(
595+
export function schema<const H extends readonly UntypedTableSchema[]>(
610596
handles: H
611597
): Schema<TablesToSchema<H>>;
612598

@@ -622,7 +608,7 @@ export function schema<const H extends readonly TableSchema<any, any, any>[]>(
622608
* );
623609
* ```
624610
*/
625-
export function schema<const H extends readonly TableSchema<any, any, any>[]>(
611+
export function schema<const H extends readonly UntypedTableSchema[]>(
626612
...args: [H] | H
627613
): Schema<TablesToSchema<H>> {
628614
const handles = (

crates/bindings-typescript/src/lib/table.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ export function table<Row extends RowObj, const Opts extends TableOpts<Row>>(
376376
tableName: name,
377377
rowSpacetimeType: productType,
378378
tableDef,
379-
idxs: indexes as OptsIndices<Opts>,
379+
idxs: {} as OptsIndices<Opts>,
380380
constraints: constraints as OptsConstraints<Opts>,
381381
};
382382
}

crates/bindings-typescript/src/lib/table_schema.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,9 @@ export type TableSchema<
4545
columns: [any];
4646
}[];
4747
};
48+
49+
export type UntypedTableSchema = TableSchema<
50+
string,
51+
Record<string, ColumnBuilder<any, any, any>>,
52+
readonly IndexOpts<string>[]
53+
>;

0 commit comments

Comments
 (0)