spacetimedb 2.0.3 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +2 -2
- package/dist/angular/index.cjs +3 -0
- package/dist/angular/index.cjs.map +1 -1
- package/dist/angular/index.mjs +3 -0
- package/dist/angular/index.mjs.map +1 -1
- package/dist/browser/angular/index.mjs +3 -0
- package/dist/browser/angular/index.mjs.map +1 -1
- package/dist/browser/react/index.mjs +3 -0
- package/dist/browser/react/index.mjs.map +1 -1
- package/dist/browser/svelte/index.mjs +3 -0
- package/dist/browser/svelte/index.mjs.map +1 -1
- package/dist/browser/vue/index.mjs +3 -0
- package/dist/browser/vue/index.mjs.map +1 -1
- package/dist/index.browser.mjs +126 -92
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.cjs +126 -92
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +126 -92
- package/dist/index.mjs.map +1 -1
- package/dist/lib/binary_writer.d.ts +1 -0
- package/dist/lib/binary_writer.d.ts.map +1 -1
- package/dist/lib/indexes.d.ts +1 -1
- package/dist/lib/indexes.d.ts.map +1 -1
- package/dist/lib/query.d.ts +4 -2
- package/dist/lib/query.d.ts.map +1 -1
- package/dist/lib/schema.d.ts +2 -0
- package/dist/lib/schema.d.ts.map +1 -1
- package/dist/lib/table.d.ts +19 -1
- package/dist/lib/table.d.ts.map +1 -1
- package/dist/min/index.browser.mjs +1 -1
- package/dist/min/index.browser.mjs.map +1 -1
- package/dist/min/react/index.mjs +1 -1
- package/dist/min/react/index.mjs.map +1 -1
- package/dist/min/sdk/index.browser.mjs +1 -1
- package/dist/min/sdk/index.browser.mjs.map +1 -1
- package/dist/react/index.cjs +3 -0
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.mjs +3 -0
- package/dist/react/index.mjs.map +1 -1
- package/dist/sdk/db_connection_impl.d.ts.map +1 -1
- package/dist/sdk/index.browser.mjs +126 -92
- package/dist/sdk/index.browser.mjs.map +1 -1
- package/dist/sdk/index.cjs +126 -92
- package/dist/sdk/index.cjs.map +1 -1
- package/dist/sdk/index.mjs +126 -92
- package/dist/sdk/index.mjs.map +1 -1
- package/dist/sdk/table_cache.d.ts.map +1 -1
- package/dist/sdk/websocket_decompress_adapter.d.ts +17 -7
- package/dist/sdk/websocket_decompress_adapter.d.ts.map +1 -1
- package/dist/sdk/websocket_test_adapter.d.ts +3 -2
- package/dist/sdk/websocket_test_adapter.d.ts.map +1 -1
- package/dist/server/index.mjs +65 -21
- package/dist/server/index.mjs.map +1 -1
- package/dist/svelte/index.cjs +3 -0
- package/dist/svelte/index.cjs.map +1 -1
- package/dist/svelte/index.mjs +3 -0
- package/dist/svelte/index.mjs.map +1 -1
- package/dist/tanstack/SpacetimeDBQueryClient.d.ts +1 -0
- package/dist/tanstack/SpacetimeDBQueryClient.d.ts.map +1 -1
- package/dist/tanstack/index.cjs +24 -0
- package/dist/tanstack/index.cjs.map +1 -1
- package/dist/tanstack/index.mjs +24 -0
- package/dist/tanstack/index.mjs.map +1 -1
- package/dist/vue/index.cjs +3 -0
- package/dist/vue/index.cjs.map +1 -1
- package/dist/vue/index.mjs +3 -0
- package/dist/vue/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/lib/binary_writer.ts +4 -0
- package/src/lib/indexes.ts +1 -1
- package/src/lib/query.ts +30 -6
- package/src/lib/schema.ts +66 -24
- package/src/lib/table.ts +41 -9
- package/src/sdk/db_connection_impl.ts +38 -43
- package/src/sdk/table_cache.ts +14 -11
- package/src/sdk/websocket_decompress_adapter.ts +42 -45
- package/src/sdk/websocket_test_adapter.ts +3 -2
- package/src/server/runtime.ts +7 -3
- package/src/server/schema.test-d.ts +37 -0
- package/src/server/view.test-d.ts +2 -0
- package/src/tanstack/SpacetimeDBQueryClient.ts +24 -0
package/dist/index.cjs
CHANGED
|
@@ -583,6 +583,9 @@ var BinaryWriter = class {
|
|
|
583
583
|
constructor(init) {
|
|
584
584
|
this.buffer = typeof init === "number" ? new ResizableBuffer(init) : init;
|
|
585
585
|
}
|
|
586
|
+
clear() {
|
|
587
|
+
this.offset = 0;
|
|
588
|
+
}
|
|
586
589
|
reset(buffer) {
|
|
587
590
|
this.buffer = buffer;
|
|
588
591
|
this.offset = 0;
|
|
@@ -1630,7 +1633,7 @@ var FromBuilder = class _FromBuilder {
|
|
|
1630
1633
|
}
|
|
1631
1634
|
[QueryBrand] = true;
|
|
1632
1635
|
where(predicate) {
|
|
1633
|
-
const newCondition = predicate(this.table.cols);
|
|
1636
|
+
const newCondition = normalizePredicateExpr(predicate(this.table.cols));
|
|
1634
1637
|
const nextWhere = this.whereClause ? this.whereClause.and(newCondition) : newCondition;
|
|
1635
1638
|
return new _FromBuilder(this.table, nextWhere);
|
|
1636
1639
|
}
|
|
@@ -1807,6 +1810,21 @@ function normalizeValue(val) {
|
|
|
1807
1810
|
}
|
|
1808
1811
|
return literal(val);
|
|
1809
1812
|
}
|
|
1813
|
+
function normalizePredicateExpr(value) {
|
|
1814
|
+
if (value instanceof BooleanExpr) return value;
|
|
1815
|
+
if (typeof value === "boolean") {
|
|
1816
|
+
return new BooleanExpr({
|
|
1817
|
+
type: "eq",
|
|
1818
|
+
left: literal(value),
|
|
1819
|
+
right: literal(true)
|
|
1820
|
+
});
|
|
1821
|
+
}
|
|
1822
|
+
return new BooleanExpr({
|
|
1823
|
+
type: "eq",
|
|
1824
|
+
left: value,
|
|
1825
|
+
right: literal(true)
|
|
1826
|
+
});
|
|
1827
|
+
}
|
|
1810
1828
|
var BooleanExpr = class _BooleanExpr {
|
|
1811
1829
|
constructor(data) {
|
|
1812
1830
|
this.data = data;
|
|
@@ -4448,9 +4466,7 @@ var TableCacheImpl = class {
|
|
|
4448
4466
|
this.tableDef = tableDef;
|
|
4449
4467
|
this.rows = /* @__PURE__ */ new Map();
|
|
4450
4468
|
this.emitter = new EventEmitter();
|
|
4451
|
-
const
|
|
4452
|
-
for (const idx of indexesDef) {
|
|
4453
|
-
const idxDef = idx;
|
|
4469
|
+
for (const idxDef of this.tableDef.resolvedIndexes) {
|
|
4454
4470
|
const index = this.#makeReadonlyIndex(this.tableDef, idxDef);
|
|
4455
4471
|
this[idxDef.name] = index;
|
|
4456
4472
|
}
|
|
@@ -5007,37 +5023,39 @@ async function resolveWS() {
|
|
|
5007
5023
|
|
|
5008
5024
|
// src/sdk/websocket_decompress_adapter.ts
|
|
5009
5025
|
var WebsocketDecompressAdapter = class _WebsocketDecompressAdapter {
|
|
5010
|
-
onclose
|
|
5011
|
-
|
|
5012
|
-
onmessage;
|
|
5013
|
-
onerror;
|
|
5014
|
-
#ws;
|
|
5015
|
-
async #handleOnMessage(msg) {
|
|
5016
|
-
const buffer = new Uint8Array(msg.data);
|
|
5017
|
-
let decompressed;
|
|
5018
|
-
if (buffer[0] === 0) {
|
|
5019
|
-
decompressed = buffer.slice(1);
|
|
5020
|
-
} else if (buffer[0] === 1) {
|
|
5021
|
-
throw new Error(
|
|
5022
|
-
"Brotli Compression not supported. Please use gzip or none compression in withCompression method on DbConnection."
|
|
5023
|
-
);
|
|
5024
|
-
} else if (buffer[0] === 2) {
|
|
5025
|
-
decompressed = await decompress(buffer.slice(1), "gzip");
|
|
5026
|
-
} else {
|
|
5027
|
-
throw new Error(
|
|
5028
|
-
"Unexpected Compression Algorithm. Please use `gzip` or `none`"
|
|
5029
|
-
);
|
|
5030
|
-
}
|
|
5031
|
-
this.onmessage?.({ data: decompressed });
|
|
5026
|
+
set onclose(handler) {
|
|
5027
|
+
this.#ws.onclose = handler;
|
|
5032
5028
|
}
|
|
5033
|
-
|
|
5034
|
-
this.onopen
|
|
5029
|
+
set onopen(handler) {
|
|
5030
|
+
this.#ws.onopen = handler;
|
|
5035
5031
|
}
|
|
5036
|
-
|
|
5037
|
-
this.
|
|
5032
|
+
set onmessage(handler) {
|
|
5033
|
+
this.#ws.onmessage = async (msg) => {
|
|
5034
|
+
const data = await this.#decompress(new Uint8Array(msg.data));
|
|
5035
|
+
handler({ data });
|
|
5036
|
+
};
|
|
5038
5037
|
}
|
|
5039
|
-
|
|
5040
|
-
this.
|
|
5038
|
+
set onerror(handler) {
|
|
5039
|
+
this.#ws.onerror = handler;
|
|
5040
|
+
}
|
|
5041
|
+
#ws;
|
|
5042
|
+
async #decompress(buffer) {
|
|
5043
|
+
const tag = buffer[0];
|
|
5044
|
+
const data = buffer.subarray(1);
|
|
5045
|
+
switch (tag) {
|
|
5046
|
+
case 0:
|
|
5047
|
+
return data;
|
|
5048
|
+
case 1:
|
|
5049
|
+
throw new Error(
|
|
5050
|
+
"Brotli Compression not supported. Please use gzip or none compression in withCompression method on DbConnection."
|
|
5051
|
+
);
|
|
5052
|
+
case 2:
|
|
5053
|
+
return await decompress(data, "gzip");
|
|
5054
|
+
default:
|
|
5055
|
+
throw new Error(
|
|
5056
|
+
"Unexpected Compression Algorithm. Please use `gzip` or `none`"
|
|
5057
|
+
);
|
|
5058
|
+
}
|
|
5041
5059
|
}
|
|
5042
5060
|
send(msg) {
|
|
5043
5061
|
this.#ws.send(msg);
|
|
@@ -5046,14 +5064,6 @@ var WebsocketDecompressAdapter = class _WebsocketDecompressAdapter {
|
|
|
5046
5064
|
this.#ws.close();
|
|
5047
5065
|
}
|
|
5048
5066
|
constructor(ws) {
|
|
5049
|
-
this.onmessage = void 0;
|
|
5050
|
-
this.onopen = void 0;
|
|
5051
|
-
this.onmessage = void 0;
|
|
5052
|
-
this.onerror = void 0;
|
|
5053
|
-
ws.onmessage = this.#handleOnMessage.bind(this);
|
|
5054
|
-
ws.onerror = this.#handleOnError.bind(this);
|
|
5055
|
-
ws.onclose = this.#handleOnClose.bind(this);
|
|
5056
|
-
ws.onopen = this.#handleOnOpen.bind(this);
|
|
5057
5067
|
ws.binaryType = "arraybuffer";
|
|
5058
5068
|
this.#ws = ws;
|
|
5059
5069
|
}
|
|
@@ -5690,12 +5700,13 @@ var DbConnectionImpl = class {
|
|
|
5690
5700
|
}
|
|
5691
5701
|
#makeReducers(def) {
|
|
5692
5702
|
const out = {};
|
|
5703
|
+
const writer = new BinaryWriter(1024);
|
|
5693
5704
|
for (const reducer of def.reducers) {
|
|
5694
5705
|
const reducerName = reducer.name;
|
|
5695
5706
|
const key = reducer.accessorName;
|
|
5696
5707
|
const { serialize: serializeArgs } = this.#reducerArgsSerializers[reducerName];
|
|
5697
5708
|
out[key] = (params) => {
|
|
5698
|
-
|
|
5709
|
+
writer.clear();
|
|
5699
5710
|
serializeArgs(writer, params);
|
|
5700
5711
|
const argsBuffer = writer.getBuffer();
|
|
5701
5712
|
return this.callReducer(reducerName, argsBuffer, params);
|
|
@@ -5705,12 +5716,13 @@ var DbConnectionImpl = class {
|
|
|
5705
5716
|
}
|
|
5706
5717
|
#makeProcedures(def) {
|
|
5707
5718
|
const out = {};
|
|
5719
|
+
const writer = new BinaryWriter(1024);
|
|
5708
5720
|
for (const procedure of def.procedures) {
|
|
5709
5721
|
const procedureName = procedure.name;
|
|
5710
5722
|
const key = procedure.accessorName;
|
|
5711
5723
|
const { serializeArgs, deserializeReturn } = this.#procedureSerializers[procedureName];
|
|
5712
5724
|
out[key] = (params) => {
|
|
5713
|
-
|
|
5725
|
+
writer.clear();
|
|
5714
5726
|
serializeArgs(writer, params);
|
|
5715
5727
|
const argsBuffer = writer.getBuffer();
|
|
5716
5728
|
return this.callProcedure(procedureName, argsBuffer).then((returnBuf) => {
|
|
@@ -5865,34 +5877,32 @@ var DbConnectionImpl = class {
|
|
|
5865
5877
|
}
|
|
5866
5878
|
return this.#mergeTableUpdates(updates);
|
|
5867
5879
|
}
|
|
5868
|
-
#sendEncoded(wsResolved, message) {
|
|
5869
|
-
stdbLogger(
|
|
5870
|
-
"trace",
|
|
5871
|
-
() => `Sending message to server: ${stringify(message)}`
|
|
5872
|
-
);
|
|
5873
|
-
const writer = new BinaryWriter(1024);
|
|
5874
|
-
ClientMessage.serialize(writer, message);
|
|
5875
|
-
const encoded = writer.getBuffer();
|
|
5876
|
-
wsResolved.send(encoded);
|
|
5877
|
-
}
|
|
5878
5880
|
#flushOutboundQueue(wsResolved) {
|
|
5879
|
-
if (!this.isActive || this.#outboundQueue.length === 0) {
|
|
5880
|
-
return;
|
|
5881
|
-
}
|
|
5882
5881
|
const pending = this.#outboundQueue.splice(0);
|
|
5883
5882
|
for (const message of pending) {
|
|
5884
|
-
|
|
5883
|
+
wsResolved.send(message);
|
|
5885
5884
|
}
|
|
5886
5885
|
}
|
|
5886
|
+
#clientMessageEncoder = new BinaryWriter(1024);
|
|
5887
5887
|
#sendMessage(message) {
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
this.#flushOutboundQueue(
|
|
5894
|
-
|
|
5895
|
-
|
|
5888
|
+
const writer = this.#clientMessageEncoder;
|
|
5889
|
+
writer.clear();
|
|
5890
|
+
ClientMessage.serialize(writer, message);
|
|
5891
|
+
const encoded = writer.getBuffer();
|
|
5892
|
+
if (this.ws && this.isActive) {
|
|
5893
|
+
if (this.#outboundQueue.length) this.#flushOutboundQueue(this.ws);
|
|
5894
|
+
stdbLogger(
|
|
5895
|
+
"trace",
|
|
5896
|
+
() => `Sending message to server: ${stringify(message)}`
|
|
5897
|
+
);
|
|
5898
|
+
this.ws.send(encoded);
|
|
5899
|
+
} else {
|
|
5900
|
+
stdbLogger(
|
|
5901
|
+
"trace",
|
|
5902
|
+
() => `Queuing message to server: ${stringify(message)}`
|
|
5903
|
+
);
|
|
5904
|
+
this.#outboundQueue.push(encoded.slice());
|
|
5905
|
+
}
|
|
5896
5906
|
}
|
|
5897
5907
|
#nextEventId() {
|
|
5898
5908
|
this.#eventId += 1;
|
|
@@ -6234,11 +6244,7 @@ var DbConnectionImpl = class {
|
|
|
6234
6244
|
* ```
|
|
6235
6245
|
*/
|
|
6236
6246
|
disconnect() {
|
|
6237
|
-
this.wsPromise.then((
|
|
6238
|
-
if (wsResolved) {
|
|
6239
|
-
wsResolved.close();
|
|
6240
|
-
}
|
|
6241
|
-
});
|
|
6247
|
+
this.wsPromise.then((ws) => ws?.close());
|
|
6242
6248
|
}
|
|
6243
6249
|
on(eventName, callback) {
|
|
6244
6250
|
this.#emitter.on(eventName, callback);
|
|
@@ -6268,17 +6274,45 @@ var DbConnectionImpl = class {
|
|
|
6268
6274
|
|
|
6269
6275
|
// src/lib/schema.ts
|
|
6270
6276
|
function tablesToSchema(ctx, tables) {
|
|
6277
|
+
const tableDefs = /* @__PURE__ */ Object.create(null);
|
|
6278
|
+
for (const [accName, schema2] of Object.entries(tables)) {
|
|
6279
|
+
tableDefs[accName] = tableToSchema(
|
|
6280
|
+
accName,
|
|
6281
|
+
schema2,
|
|
6282
|
+
schema2.tableDef(ctx, accName)
|
|
6283
|
+
);
|
|
6284
|
+
}
|
|
6271
6285
|
return {
|
|
6272
|
-
tables:
|
|
6273
|
-
Object.entries(tables).map(([accName, schema2]) => [
|
|
6274
|
-
accName,
|
|
6275
|
-
tableToSchema(accName, schema2, schema2.tableDef(ctx, accName))
|
|
6276
|
-
])
|
|
6277
|
-
)
|
|
6286
|
+
tables: tableDefs
|
|
6278
6287
|
};
|
|
6279
6288
|
}
|
|
6280
6289
|
function tableToSchema(accName, schema2, tableDef) {
|
|
6281
6290
|
const getColName = (i) => schema2.rowType.algebraicType.value.elements[i].name;
|
|
6291
|
+
const resolvedIndexes = tableDef.indexes.map(
|
|
6292
|
+
(idx) => {
|
|
6293
|
+
const accessorName = idx.accessorName;
|
|
6294
|
+
if (typeof accessorName !== "string" || accessorName.length === 0) {
|
|
6295
|
+
throw new TypeError(
|
|
6296
|
+
`Index '${idx.sourceName ?? "<unknown>"}' on table '${tableDef.sourceName}' is missing accessor name`
|
|
6297
|
+
);
|
|
6298
|
+
}
|
|
6299
|
+
const columnIds = idx.algorithm.tag === "Direct" ? [idx.algorithm.value] : idx.algorithm.value;
|
|
6300
|
+
const unique = tableDef.constraints.some(
|
|
6301
|
+
(c) => c.data.tag === "Unique" && c.data.value.columns.every((col) => columnIds.includes(col))
|
|
6302
|
+
);
|
|
6303
|
+
const algorithm = {
|
|
6304
|
+
BTree: "btree",
|
|
6305
|
+
Hash: "hash",
|
|
6306
|
+
Direct: "direct"
|
|
6307
|
+
}[idx.algorithm.tag];
|
|
6308
|
+
return {
|
|
6309
|
+
name: accessorName,
|
|
6310
|
+
unique,
|
|
6311
|
+
algorithm,
|
|
6312
|
+
columns: columnIds.map(getColName)
|
|
6313
|
+
};
|
|
6314
|
+
}
|
|
6315
|
+
);
|
|
6282
6316
|
return {
|
|
6283
6317
|
// For client,`schama.tableName` will always be there as canonical name.
|
|
6284
6318
|
// For module, if explicit name is not provided via `name`, accessor name will
|
|
@@ -6288,26 +6322,16 @@ function tableToSchema(accName, schema2, tableDef) {
|
|
|
6288
6322
|
columns: schema2.rowType.row,
|
|
6289
6323
|
// typed as T[i]['rowType']['row'] under TablesToSchema<T>
|
|
6290
6324
|
rowType: schema2.rowSpacetimeType,
|
|
6325
|
+
// Keep declarative indexes in their original shape for type-level consumers.
|
|
6326
|
+
indexes: schema2.idxs,
|
|
6291
6327
|
constraints: tableDef.constraints.map((c) => ({
|
|
6292
6328
|
name: c.sourceName,
|
|
6293
6329
|
constraint: "unique",
|
|
6294
6330
|
columns: c.data.value.columns.map(getColName)
|
|
6295
6331
|
})),
|
|
6296
|
-
//
|
|
6297
|
-
//
|
|
6298
|
-
|
|
6299
|
-
// We should stop lying about our types.
|
|
6300
|
-
indexes: tableDef.indexes.map((idx) => {
|
|
6301
|
-
const columnIds = idx.algorithm.tag === "Direct" ? [idx.algorithm.value] : idx.algorithm.value;
|
|
6302
|
-
return {
|
|
6303
|
-
name: idx.accessorName,
|
|
6304
|
-
unique: tableDef.constraints.some(
|
|
6305
|
-
(c) => c.data.value.columns.every((col) => columnIds.includes(col))
|
|
6306
|
-
),
|
|
6307
|
-
algorithm: idx.algorithm.tag.toLowerCase(),
|
|
6308
|
-
columns: columnIds.map(getColName)
|
|
6309
|
-
};
|
|
6310
|
-
}),
|
|
6332
|
+
// Expose resolved runtime indexes separately so runtime users don't have to
|
|
6333
|
+
// reinterpret `indexes` with unsafe casts.
|
|
6334
|
+
resolvedIndexes,
|
|
6311
6335
|
tableDef,
|
|
6312
6336
|
...tableDef.isEvent ? { isEvent: true } : {}
|
|
6313
6337
|
};
|
|
@@ -7131,6 +7155,14 @@ function table(opts, row, ..._) {
|
|
|
7131
7155
|
}
|
|
7132
7156
|
}
|
|
7133
7157
|
for (const indexOpts of userIndexes ?? []) {
|
|
7158
|
+
const accessor = indexOpts.accessor;
|
|
7159
|
+
if (typeof accessor !== "string" || accessor.length === 0) {
|
|
7160
|
+
const tableLabel = name ?? "<unnamed>";
|
|
7161
|
+
const indexLabel = indexOpts.name ?? "<unnamed>";
|
|
7162
|
+
throw new TypeError(
|
|
7163
|
+
`Index '${indexLabel}' on table '${tableLabel}' must define a non-empty 'accessor'`
|
|
7164
|
+
);
|
|
7165
|
+
}
|
|
7134
7166
|
let algorithm;
|
|
7135
7167
|
switch (indexOpts.algorithm) {
|
|
7136
7168
|
case "btree":
|
|
@@ -7151,7 +7183,7 @@ function table(opts, row, ..._) {
|
|
|
7151
7183
|
}
|
|
7152
7184
|
indexes.push({
|
|
7153
7185
|
sourceName: void 0,
|
|
7154
|
-
accessorName:
|
|
7186
|
+
accessorName: accessor,
|
|
7155
7187
|
algorithm,
|
|
7156
7188
|
canonicalName: indexOpts.name
|
|
7157
7189
|
});
|
|
@@ -7201,7 +7233,9 @@ function table(opts, row, ..._) {
|
|
|
7201
7233
|
isEvent
|
|
7202
7234
|
};
|
|
7203
7235
|
},
|
|
7204
|
-
|
|
7236
|
+
// Preserve the declared index options as runtime data so `tableToSchema`
|
|
7237
|
+
// can expose them without type-smuggling.
|
|
7238
|
+
idxs: userIndexes,
|
|
7205
7239
|
constraints,
|
|
7206
7240
|
schedule
|
|
7207
7241
|
};
|