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