From 0bd00bf1b8e85dc9cace1dbc1774ab5187f3c13a Mon Sep 17 00:00:00 2001 From: "kistz (Kilian Strunz)" Date: Wed, 20 May 2026 00:21:01 +0200 Subject: [PATCH 1/6] allow to use Uuid as literal value --- crates/bindings-typescript/src/lib/query.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bindings-typescript/src/lib/query.ts b/crates/bindings-typescript/src/lib/query.ts index 37743ccd0be..2a0b908e03b 100644 --- a/crates/bindings-typescript/src/lib/query.ts +++ b/crates/bindings-typescript/src/lib/query.ts @@ -12,6 +12,7 @@ import type { } from './type_builders'; import type { Values } from './type_util'; import type { Bool as SatsBool } from './algebraic_type_variants'; +import type { Uuid } from './uuid'; /** * Helper to get the set of table names. @@ -623,6 +624,7 @@ type LiteralValue = | bigint | boolean | Identity + | Uuid | Timestamp | ConnectionId; From 6fc7791a03b24f072a2c79fbc9577fffc3997da9 Mon Sep 17 00:00:00 2001 From: "kistz (Kilian Strunz)" Date: Wed, 20 May 2026 19:38:48 +0200 Subject: [PATCH 2/6] fix mistake in the actual exec path --- crates/bindings-typescript/src/lib/query.ts | 104 ++++++++++---------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/crates/bindings-typescript/src/lib/query.ts b/crates/bindings-typescript/src/lib/query.ts index 2a0b908e03b..6d16d363a69 100644 --- a/crates/bindings-typescript/src/lib/query.ts +++ b/crates/bindings-typescript/src/lib/query.ts @@ -12,7 +12,7 @@ import type { } from './type_builders'; import type { Values } from './type_util'; import type { Bool as SatsBool } from './algebraic_type_variants'; -import type { Uuid } from './uuid'; +import { Uuid } from './uuid'; /** * Helper to get the set of table names. @@ -102,8 +102,7 @@ type SemijoinBuilder = RowTypedQuery< }>; class SemijoinImpl - implements SemijoinBuilder, TableTypedQuery -{ + implements SemijoinBuilder, TableTypedQuery { readonly [QueryBrand] = true; readonly type = 'semijoin' as const; constructor( @@ -160,13 +159,12 @@ class SemijoinImpl } class FromBuilder - implements From, TableTypedQuery -{ + implements From, TableTypedQuery { readonly [QueryBrand] = true; constructor( readonly table: TableRef, readonly whereClause?: BooleanExpr - ) {} + ) { } where( predicate: (row: RowExpr) => PredicateExpr @@ -242,8 +240,7 @@ export type TableRef = Readonly<{ }>; class TableRefImpl - implements TableRef, From -{ + implements TableRef, From { readonly [QueryBrand] = true; readonly type = 'table' as const; sourceName: string; @@ -399,8 +396,8 @@ type RowType = { any, any > - ? T - : never; + ? T + : never; }; // TODO: Consider making a smaller version of these types that doesn't expose the internals. @@ -412,8 +409,8 @@ export type ColumnExpr< type ColumnSpacetimeType> = Col extends ColumnExpr - ? InferSpacetimeTypeOfColumn - : never; + ? InferSpacetimeTypeOfColumn + : never; // TODO: This checks that they match, but we also need to make sure that they are comparable types, // since you can use product types at all. @@ -425,10 +422,10 @@ type ColumnSameSpacetime< ColumnSpacetimeType, ] ? [ColumnSpacetimeType] extends [ - InferSpacetimeTypeOfColumn, - ] - ? OtherCol - : never + InferSpacetimeTypeOfColumn, + ] + ? OtherCol + : never : never; // Helper to get the table back from a column. @@ -563,8 +560,8 @@ type InferSpacetimeTypeOfColumn< any, infer U > - ? U - : never; + ? U + : never; type ColumnNames = keyof RowType & string; @@ -572,16 +569,16 @@ type ColumnNames = keyof RowType & // For composite indexes, we only consider it as an index over the first column in the index. type FirstIndexColumn> = IndexColumns extends readonly [infer Head extends string, ...infer _Rest] - ? Head - : never; + ? Head + : never; // Columns that are indexed by something in the indexes: [...] part. type ExplicitIndexedColumns = TableDef['indexes'][number] extends infer I - ? I extends IndexOpts> - ? FirstIndexColumn & ColumnNames - : never - : never; + ? I extends IndexOpts> + ? FirstIndexColumn & ColumnNames + : never + : never; // Columns with an index defined on the column definition. type MetadataIndexedColumns = { @@ -589,8 +586,8 @@ type MetadataIndexedColumns = { K, TableDef['columns'][K]['columnMetadata'] > extends never - ? never - : K; + ? never + : K; }[ColumnNames]; export type IndexedColumnNames = @@ -614,8 +611,8 @@ export type RowExpr = Readonly<{ */ export type ColumnExprForValue = { [C in ColumnNames
]: InferSpacetimeTypeOfColumn extends Value - ? ColumnExpr - : never; + ? ColumnExpr + : never; }[ColumnNames
]; type LiteralValue = @@ -690,30 +687,30 @@ type EqExpr
= BooleanExpr
; type BooleanExprData
= ( | { - type: 'eq' | 'ne' | 'gt' | 'lt' | 'gte' | 'lte'; - left: ValueExpr; - right: ValueExpr; - } + type: 'eq' | 'ne' | 'gt' | 'lt' | 'gte' | 'lte'; + left: ValueExpr; + right: ValueExpr; + } | { - type: 'and'; - clauses: readonly [ - BooleanExprData
, - BooleanExprData
, - ...BooleanExprData
[], - ]; - } + type: 'and'; + clauses: readonly [ + BooleanExprData
, + BooleanExprData
, + ...BooleanExprData
[], + ]; + } | { - type: 'or'; - clauses: readonly [ - BooleanExprData
, - BooleanExprData
, - ...BooleanExprData
[], - ]; - } + type: 'or'; + clauses: readonly [ + BooleanExprData
, + BooleanExprData
, + ...BooleanExprData
[], + ]; + } | { - type: 'not'; - clause: BooleanExprData
; - } + type: 'not'; + clause: BooleanExprData
; + } ) & { _tableType?: Table; }; @@ -727,12 +724,12 @@ type RequireSameAndOrTable< Actual extends TypedTableDef, > = [Expected] extends [Actual] ? [Actual] extends [Expected] - ? unknown - : AndOrMixedTableScopeError + ? unknown + : AndOrMixedTableScopeError : AndOrMixedTableScopeError; export class BooleanExpr
{ - constructor(readonly data: BooleanExprData
) {} + constructor(readonly data: BooleanExprData
) { } and( other: BooleanExpr & RequireSameAndOrTable @@ -860,6 +857,9 @@ function literalValueToSql(value: unknown): string { if (value instanceof Timestamp) { return `'${value.toISOString()}'`; } + if (value instanceof Uuid) { + return value.toString(); + } switch (typeof value) { case 'number': case 'bigint': From de08c2224e178d9dbeaa6b215ae658cbf619b5e9 Mon Sep 17 00:00:00 2001 From: "kistz (Kilian Strunz)" Date: Wed, 20 May 2026 19:39:45 +0200 Subject: [PATCH 3/6] =?UTF-8?q?ugh=20forgot=20to=20format=20=F0=9F=98=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/bindings-typescript/src/lib/query.ts | 99 +++++++++++---------- 1 file changed, 51 insertions(+), 48 deletions(-) diff --git a/crates/bindings-typescript/src/lib/query.ts b/crates/bindings-typescript/src/lib/query.ts index 6d16d363a69..266531b8448 100644 --- a/crates/bindings-typescript/src/lib/query.ts +++ b/crates/bindings-typescript/src/lib/query.ts @@ -102,7 +102,8 @@ type SemijoinBuilder = RowTypedQuery< }>; class SemijoinImpl - implements SemijoinBuilder, TableTypedQuery { + implements SemijoinBuilder, TableTypedQuery +{ readonly [QueryBrand] = true; readonly type = 'semijoin' as const; constructor( @@ -159,12 +160,13 @@ class SemijoinImpl } class FromBuilder - implements From, TableTypedQuery { + implements From, TableTypedQuery +{ readonly [QueryBrand] = true; constructor( readonly table: TableRef, readonly whereClause?: BooleanExpr - ) { } + ) {} where( predicate: (row: RowExpr) => PredicateExpr @@ -240,7 +242,8 @@ export type TableRef = Readonly<{ }>; class TableRefImpl - implements TableRef, From { + implements TableRef, From +{ readonly [QueryBrand] = true; readonly type = 'table' as const; sourceName: string; @@ -396,8 +399,8 @@ type RowType = { any, any > - ? T - : never; + ? T + : never; }; // TODO: Consider making a smaller version of these types that doesn't expose the internals. @@ -409,8 +412,8 @@ export type ColumnExpr< type ColumnSpacetimeType> = Col extends ColumnExpr - ? InferSpacetimeTypeOfColumn - : never; + ? InferSpacetimeTypeOfColumn + : never; // TODO: This checks that they match, but we also need to make sure that they are comparable types, // since you can use product types at all. @@ -422,10 +425,10 @@ type ColumnSameSpacetime< ColumnSpacetimeType, ] ? [ColumnSpacetimeType] extends [ - InferSpacetimeTypeOfColumn, - ] - ? OtherCol - : never + InferSpacetimeTypeOfColumn, + ] + ? OtherCol + : never : never; // Helper to get the table back from a column. @@ -560,8 +563,8 @@ type InferSpacetimeTypeOfColumn< any, infer U > - ? U - : never; + ? U + : never; type ColumnNames = keyof RowType & string; @@ -569,16 +572,16 @@ type ColumnNames = keyof RowType & // For composite indexes, we only consider it as an index over the first column in the index. type FirstIndexColumn> = IndexColumns extends readonly [infer Head extends string, ...infer _Rest] - ? Head - : never; + ? Head + : never; // Columns that are indexed by something in the indexes: [...] part. type ExplicitIndexedColumns = TableDef['indexes'][number] extends infer I - ? I extends IndexOpts> - ? FirstIndexColumn & ColumnNames - : never - : never; + ? I extends IndexOpts> + ? FirstIndexColumn & ColumnNames + : never + : never; // Columns with an index defined on the column definition. type MetadataIndexedColumns = { @@ -586,8 +589,8 @@ type MetadataIndexedColumns = { K, TableDef['columns'][K]['columnMetadata'] > extends never - ? never - : K; + ? never + : K; }[ColumnNames]; export type IndexedColumnNames = @@ -611,8 +614,8 @@ export type RowExpr = Readonly<{ */ export type ColumnExprForValue
= { [C in ColumnNames
]: InferSpacetimeTypeOfColumn extends Value - ? ColumnExpr - : never; + ? ColumnExpr + : never; }[ColumnNames
]; type LiteralValue = @@ -687,30 +690,30 @@ type EqExpr
= BooleanExpr
; type BooleanExprData
= ( | { - type: 'eq' | 'ne' | 'gt' | 'lt' | 'gte' | 'lte'; - left: ValueExpr; - right: ValueExpr; - } + type: 'eq' | 'ne' | 'gt' | 'lt' | 'gte' | 'lte'; + left: ValueExpr; + right: ValueExpr; + } | { - type: 'and'; - clauses: readonly [ - BooleanExprData
, - BooleanExprData
, - ...BooleanExprData
[], - ]; - } + type: 'and'; + clauses: readonly [ + BooleanExprData
, + BooleanExprData
, + ...BooleanExprData
[], + ]; + } | { - type: 'or'; - clauses: readonly [ - BooleanExprData
, - BooleanExprData
, - ...BooleanExprData
[], - ]; - } + type: 'or'; + clauses: readonly [ + BooleanExprData
, + BooleanExprData
, + ...BooleanExprData
[], + ]; + } | { - type: 'not'; - clause: BooleanExprData
; - } + type: 'not'; + clause: BooleanExprData
; + } ) & { _tableType?: Table; }; @@ -724,12 +727,12 @@ type RequireSameAndOrTable< Actual extends TypedTableDef, > = [Expected] extends [Actual] ? [Actual] extends [Expected] - ? unknown - : AndOrMixedTableScopeError + ? unknown + : AndOrMixedTableScopeError : AndOrMixedTableScopeError; export class BooleanExpr
{ - constructor(readonly data: BooleanExprData
) { } + constructor(readonly data: BooleanExprData
) {} and( other: BooleanExpr & RequireSameAndOrTable From 66a1235703163ab145d5a1540028a607f20ab5d9 Mon Sep 17 00:00:00 2001 From: "kistz (Kilian Strunz)" Date: Thu, 18 Jun 2026 12:25:36 +0200 Subject: [PATCH 4/6] format literal as hex --- crates/bindings-typescript/src/lib/query.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bindings-typescript/src/lib/query.ts b/crates/bindings-typescript/src/lib/query.ts index 266531b8448..28f057e7ba7 100644 --- a/crates/bindings-typescript/src/lib/query.ts +++ b/crates/bindings-typescript/src/lib/query.ts @@ -13,6 +13,7 @@ import type { import type { Values } from './type_util'; import type { Bool as SatsBool } from './algebraic_type_variants'; import { Uuid } from './uuid'; +import { u128ToHexString } from './util'; /** * Helper to get the set of table names. @@ -861,7 +862,7 @@ function literalValueToSql(value: unknown): string { return `'${value.toISOString()}'`; } if (value instanceof Uuid) { - return value.toString(); + return u128ToHexString(value.__uuid__); } switch (typeof value) { case 'number': From 9e384a9a1e86db2370202fbeccf3b7056f98bb26 Mon Sep 17 00:00:00 2001 From: joshua-spacetime Date: Thu, 18 Jun 2026 11:58:16 -0700 Subject: [PATCH 5/6] Format UUID query literals as SQL hex --- crates/bindings-typescript/src/lib/query.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bindings-typescript/src/lib/query.ts b/crates/bindings-typescript/src/lib/query.ts index 28f057e7ba7..a826d11c34b 100644 --- a/crates/bindings-typescript/src/lib/query.ts +++ b/crates/bindings-typescript/src/lib/query.ts @@ -862,7 +862,7 @@ function literalValueToSql(value: unknown): string { return `'${value.toISOString()}'`; } if (value instanceof Uuid) { - return u128ToHexString(value.__uuid__); + return `0x${u128ToHexString(value.asBigInt())}`; } switch (typeof value) { case 'number': From 940fd2080b2422da25979651e7495abc50c1f681 Mon Sep 17 00:00:00 2001 From: joshua-spacetime Date: Thu, 18 Jun 2026 12:08:35 -0700 Subject: [PATCH 6/6] Add UUID hex string formatting --- crates/bindings-typescript/src/lib/query.ts | 10 +++++----- crates/bindings-typescript/src/lib/uuid.ts | 9 +++++++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/crates/bindings-typescript/src/lib/query.ts b/crates/bindings-typescript/src/lib/query.ts index a826d11c34b..fda31f68f45 100644 --- a/crates/bindings-typescript/src/lib/query.ts +++ b/crates/bindings-typescript/src/lib/query.ts @@ -13,7 +13,6 @@ import type { import type { Values } from './type_util'; import type { Bool as SatsBool } from './algebraic_type_variants'; import { Uuid } from './uuid'; -import { u128ToHexString } from './util'; /** * Helper to get the set of table names. @@ -854,16 +853,17 @@ function literalValueToSql(value: unknown): string { if (value === null || value === undefined) { return 'NULL'; } - if (value instanceof Identity || value instanceof ConnectionId) { + if ( + value instanceof Identity || + value instanceof ConnectionId || + value instanceof Uuid + ) { // We use this hex string syntax. return `0x${value.toHexString()}`; } if (value instanceof Timestamp) { return `'${value.toISOString()}'`; } - if (value instanceof Uuid) { - return `0x${u128ToHexString(value.asBigInt())}`; - } switch (typeof value) { case 'number': case 'bigint': diff --git a/crates/bindings-typescript/src/lib/uuid.ts b/crates/bindings-typescript/src/lib/uuid.ts index 2216e1e9499..097424c8da3 100644 --- a/crates/bindings-typescript/src/lib/uuid.ts +++ b/crates/bindings-typescript/src/lib/uuid.ts @@ -1,5 +1,6 @@ import { Timestamp } from './timestamp'; import { AlgebraicType } from './algebraic_type.ts'; +import { u128ToHexString } from './util'; export type UuidAlgebraicType = { tag: 'Product'; @@ -226,10 +227,14 @@ export class Uuid { return new Uuid(v); } + /** Convert to hex string without a 0x prefix. */ + toHexString(): string { + return u128ToHexString(this.asBigInt()); + } + /** Convert to string (hyphenated form). */ toString(): string { - const bytes = Uuid.bigIntToBytes(this.__uuid__); - const hex = [...bytes].map(b => b.toString(16).padStart(2, '0')).join(''); + const hex = this.toHexString(); // Format as 8-4-4-4-12 return (