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.
Files changed (81) hide show
  1. package/LICENSE.txt +2 -2
  2. package/dist/angular/index.cjs +3 -0
  3. package/dist/angular/index.cjs.map +1 -1
  4. package/dist/angular/index.mjs +3 -0
  5. package/dist/angular/index.mjs.map +1 -1
  6. package/dist/browser/angular/index.mjs +3 -0
  7. package/dist/browser/angular/index.mjs.map +1 -1
  8. package/dist/browser/react/index.mjs +3 -0
  9. package/dist/browser/react/index.mjs.map +1 -1
  10. package/dist/browser/svelte/index.mjs +3 -0
  11. package/dist/browser/svelte/index.mjs.map +1 -1
  12. package/dist/browser/vue/index.mjs +3 -0
  13. package/dist/browser/vue/index.mjs.map +1 -1
  14. package/dist/index.browser.mjs +126 -92
  15. package/dist/index.browser.mjs.map +1 -1
  16. package/dist/index.cjs +126 -92
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.mjs +126 -92
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/lib/binary_writer.d.ts +1 -0
  21. package/dist/lib/binary_writer.d.ts.map +1 -1
  22. package/dist/lib/indexes.d.ts +1 -1
  23. package/dist/lib/indexes.d.ts.map +1 -1
  24. package/dist/lib/query.d.ts +4 -2
  25. package/dist/lib/query.d.ts.map +1 -1
  26. package/dist/lib/schema.d.ts +2 -0
  27. package/dist/lib/schema.d.ts.map +1 -1
  28. package/dist/lib/table.d.ts +19 -1
  29. package/dist/lib/table.d.ts.map +1 -1
  30. package/dist/min/index.browser.mjs +1 -1
  31. package/dist/min/index.browser.mjs.map +1 -1
  32. package/dist/min/react/index.mjs +1 -1
  33. package/dist/min/react/index.mjs.map +1 -1
  34. package/dist/min/sdk/index.browser.mjs +1 -1
  35. package/dist/min/sdk/index.browser.mjs.map +1 -1
  36. package/dist/react/index.cjs +3 -0
  37. package/dist/react/index.cjs.map +1 -1
  38. package/dist/react/index.mjs +3 -0
  39. package/dist/react/index.mjs.map +1 -1
  40. package/dist/sdk/db_connection_impl.d.ts.map +1 -1
  41. package/dist/sdk/index.browser.mjs +126 -92
  42. package/dist/sdk/index.browser.mjs.map +1 -1
  43. package/dist/sdk/index.cjs +126 -92
  44. package/dist/sdk/index.cjs.map +1 -1
  45. package/dist/sdk/index.mjs +126 -92
  46. package/dist/sdk/index.mjs.map +1 -1
  47. package/dist/sdk/table_cache.d.ts.map +1 -1
  48. package/dist/sdk/websocket_decompress_adapter.d.ts +17 -7
  49. package/dist/sdk/websocket_decompress_adapter.d.ts.map +1 -1
  50. package/dist/sdk/websocket_test_adapter.d.ts +3 -2
  51. package/dist/sdk/websocket_test_adapter.d.ts.map +1 -1
  52. package/dist/server/index.mjs +65 -21
  53. package/dist/server/index.mjs.map +1 -1
  54. package/dist/svelte/index.cjs +3 -0
  55. package/dist/svelte/index.cjs.map +1 -1
  56. package/dist/svelte/index.mjs +3 -0
  57. package/dist/svelte/index.mjs.map +1 -1
  58. package/dist/tanstack/SpacetimeDBQueryClient.d.ts +1 -0
  59. package/dist/tanstack/SpacetimeDBQueryClient.d.ts.map +1 -1
  60. package/dist/tanstack/index.cjs +24 -0
  61. package/dist/tanstack/index.cjs.map +1 -1
  62. package/dist/tanstack/index.mjs +24 -0
  63. package/dist/tanstack/index.mjs.map +1 -1
  64. package/dist/vue/index.cjs +3 -0
  65. package/dist/vue/index.cjs.map +1 -1
  66. package/dist/vue/index.mjs +3 -0
  67. package/dist/vue/index.mjs.map +1 -1
  68. package/package.json +1 -1
  69. package/src/lib/binary_writer.ts +4 -0
  70. package/src/lib/indexes.ts +1 -1
  71. package/src/lib/query.ts +30 -6
  72. package/src/lib/schema.ts +66 -24
  73. package/src/lib/table.ts +41 -9
  74. package/src/sdk/db_connection_impl.ts +38 -43
  75. package/src/sdk/table_cache.ts +14 -11
  76. package/src/sdk/websocket_decompress_adapter.ts +42 -45
  77. package/src/sdk/websocket_test_adapter.ts +3 -2
  78. package/src/server/runtime.ts +7 -3
  79. package/src/server/schema.test-d.ts +37 -0
  80. package/src/server/view.test-d.ts +2 -0
  81. 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 indexesDef = this.tableDef.indexes || [];
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
- onopen;
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
- #handleOnOpen(msg) {
5034
- this.onopen?.(msg);
5029
+ set onopen(handler) {
5030
+ this.#ws.onopen = handler;
5035
5031
  }
5036
- #handleOnError(msg) {
5037
- this.onerror?.(msg);
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
- #handleOnClose(msg) {
5040
- this.onclose?.(msg);
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
- const writer = new BinaryWriter(1024);
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
- const writer = new BinaryWriter(1024);
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
- this.#sendEncoded(wsResolved, message);
5883
+ wsResolved.send(message);
5885
5884
  }
5886
5885
  }
5886
+ #clientMessageEncoder = new BinaryWriter(1024);
5887
5887
  #sendMessage(message) {
5888
- this.wsPromise.then((wsResolved) => {
5889
- if (!wsResolved || !this.isActive) {
5890
- this.#outboundQueue.push(message);
5891
- return;
5892
- }
5893
- this.#flushOutboundQueue(wsResolved);
5894
- this.#sendEncoded(wsResolved, message);
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((wsResolved) => {
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: Object.fromEntries(
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
- // TODO: horrible horrible horrible. we smuggle this `Array<UntypedIndex>`
6297
- // by casting it to an `Array<IndexOpts>` as `TableToSchema` expects.
6298
- // This is then used in `TableCacheImpl.constructor` and who knows where else.
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: indexOpts.accessor,
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
- idxs: {},
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
  };