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
@@ -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;
@@ -1577,7 +1580,7 @@ var FromBuilder = class _FromBuilder {
1577
1580
  }
1578
1581
  [QueryBrand] = true;
1579
1582
  where(predicate) {
1580
- const newCondition = predicate(this.table.cols);
1583
+ const newCondition = normalizePredicateExpr(predicate(this.table.cols));
1581
1584
  const nextWhere = this.whereClause ? this.whereClause.and(newCondition) : newCondition;
1582
1585
  return new _FromBuilder(this.table, nextWhere);
1583
1586
  }
@@ -1754,6 +1757,21 @@ function normalizeValue(val) {
1754
1757
  }
1755
1758
  return literal(val);
1756
1759
  }
1760
+ function normalizePredicateExpr(value) {
1761
+ if (value instanceof BooleanExpr) return value;
1762
+ if (typeof value === "boolean") {
1763
+ return new BooleanExpr({
1764
+ type: "eq",
1765
+ left: literal(value),
1766
+ right: literal(true)
1767
+ });
1768
+ }
1769
+ return new BooleanExpr({
1770
+ type: "eq",
1771
+ left: value,
1772
+ right: literal(true)
1773
+ });
1774
+ }
1757
1775
  var BooleanExpr = class _BooleanExpr {
1758
1776
  constructor(data) {
1759
1777
  this.data = data;
@@ -4315,9 +4333,7 @@ var TableCacheImpl = class {
4315
4333
  this.tableDef = tableDef;
4316
4334
  this.rows = /* @__PURE__ */ new Map();
4317
4335
  this.emitter = new EventEmitter();
4318
- const indexesDef = this.tableDef.indexes || [];
4319
- for (const idx of indexesDef) {
4320
- const idxDef = idx;
4336
+ for (const idxDef of this.tableDef.resolvedIndexes) {
4321
4337
  const index = this.#makeReadonlyIndex(this.tableDef, idxDef);
4322
4338
  this[idxDef.name] = index;
4323
4339
  }
@@ -4874,37 +4890,39 @@ async function resolveWS() {
4874
4890
 
4875
4891
  // src/sdk/websocket_decompress_adapter.ts
4876
4892
  var WebsocketDecompressAdapter = class _WebsocketDecompressAdapter {
4877
- onclose;
4878
- onopen;
4879
- onmessage;
4880
- onerror;
4881
- #ws;
4882
- async #handleOnMessage(msg) {
4883
- const buffer = new Uint8Array(msg.data);
4884
- let decompressed;
4885
- if (buffer[0] === 0) {
4886
- decompressed = buffer.slice(1);
4887
- } else if (buffer[0] === 1) {
4888
- throw new Error(
4889
- "Brotli Compression not supported. Please use gzip or none compression in withCompression method on DbConnection."
4890
- );
4891
- } else if (buffer[0] === 2) {
4892
- decompressed = await decompress(buffer.slice(1), "gzip");
4893
- } else {
4894
- throw new Error(
4895
- "Unexpected Compression Algorithm. Please use `gzip` or `none`"
4896
- );
4897
- }
4898
- this.onmessage?.({ data: decompressed });
4893
+ set onclose(handler) {
4894
+ this.#ws.onclose = handler;
4899
4895
  }
4900
- #handleOnOpen(msg) {
4901
- this.onopen?.(msg);
4896
+ set onopen(handler) {
4897
+ this.#ws.onopen = handler;
4898
+ }
4899
+ set onmessage(handler) {
4900
+ this.#ws.onmessage = async (msg) => {
4901
+ const data = await this.#decompress(new Uint8Array(msg.data));
4902
+ handler({ data });
4903
+ };
4902
4904
  }
4903
- #handleOnError(msg) {
4904
- this.onerror?.(msg);
4905
+ set onerror(handler) {
4906
+ this.#ws.onerror = handler;
4905
4907
  }
4906
- #handleOnClose(msg) {
4907
- this.onclose?.(msg);
4908
+ #ws;
4909
+ async #decompress(buffer) {
4910
+ const tag = buffer[0];
4911
+ const data = buffer.subarray(1);
4912
+ switch (tag) {
4913
+ case 0:
4914
+ return data;
4915
+ case 1:
4916
+ throw new Error(
4917
+ "Brotli Compression not supported. Please use gzip or none compression in withCompression method on DbConnection."
4918
+ );
4919
+ case 2:
4920
+ return await decompress(data, "gzip");
4921
+ default:
4922
+ throw new Error(
4923
+ "Unexpected Compression Algorithm. Please use `gzip` or `none`"
4924
+ );
4925
+ }
4908
4926
  }
4909
4927
  send(msg) {
4910
4928
  this.#ws.send(msg);
@@ -4913,14 +4931,6 @@ var WebsocketDecompressAdapter = class _WebsocketDecompressAdapter {
4913
4931
  this.#ws.close();
4914
4932
  }
4915
4933
  constructor(ws) {
4916
- this.onmessage = void 0;
4917
- this.onopen = void 0;
4918
- this.onmessage = void 0;
4919
- this.onerror = void 0;
4920
- ws.onmessage = this.#handleOnMessage.bind(this);
4921
- ws.onerror = this.#handleOnError.bind(this);
4922
- ws.onclose = this.#handleOnClose.bind(this);
4923
- ws.onopen = this.#handleOnOpen.bind(this);
4924
4934
  ws.binaryType = "arraybuffer";
4925
4935
  this.#ws = ws;
4926
4936
  }
@@ -5557,12 +5567,13 @@ var DbConnectionImpl = class {
5557
5567
  }
5558
5568
  #makeReducers(def) {
5559
5569
  const out = {};
5570
+ const writer = new BinaryWriter(1024);
5560
5571
  for (const reducer of def.reducers) {
5561
5572
  const reducerName = reducer.name;
5562
5573
  const key = reducer.accessorName;
5563
5574
  const { serialize: serializeArgs } = this.#reducerArgsSerializers[reducerName];
5564
5575
  out[key] = (params) => {
5565
- const writer = new BinaryWriter(1024);
5576
+ writer.clear();
5566
5577
  serializeArgs(writer, params);
5567
5578
  const argsBuffer = writer.getBuffer();
5568
5579
  return this.callReducer(reducerName, argsBuffer, params);
@@ -5572,12 +5583,13 @@ var DbConnectionImpl = class {
5572
5583
  }
5573
5584
  #makeProcedures(def) {
5574
5585
  const out = {};
5586
+ const writer = new BinaryWriter(1024);
5575
5587
  for (const procedure of def.procedures) {
5576
5588
  const procedureName = procedure.name;
5577
5589
  const key = procedure.accessorName;
5578
5590
  const { serializeArgs, deserializeReturn } = this.#procedureSerializers[procedureName];
5579
5591
  out[key] = (params) => {
5580
- const writer = new BinaryWriter(1024);
5592
+ writer.clear();
5581
5593
  serializeArgs(writer, params);
5582
5594
  const argsBuffer = writer.getBuffer();
5583
5595
  return this.callProcedure(procedureName, argsBuffer).then((returnBuf) => {
@@ -5732,34 +5744,32 @@ var DbConnectionImpl = class {
5732
5744
  }
5733
5745
  return this.#mergeTableUpdates(updates);
5734
5746
  }
5735
- #sendEncoded(wsResolved, message) {
5736
- stdbLogger(
5737
- "trace",
5738
- () => `Sending message to server: ${stringify(message)}`
5739
- );
5740
- const writer = new BinaryWriter(1024);
5741
- ClientMessage.serialize(writer, message);
5742
- const encoded = writer.getBuffer();
5743
- wsResolved.send(encoded);
5744
- }
5745
5747
  #flushOutboundQueue(wsResolved) {
5746
- if (!this.isActive || this.#outboundQueue.length === 0) {
5747
- return;
5748
- }
5749
5748
  const pending = this.#outboundQueue.splice(0);
5750
5749
  for (const message of pending) {
5751
- this.#sendEncoded(wsResolved, message);
5750
+ wsResolved.send(message);
5752
5751
  }
5753
5752
  }
5753
+ #clientMessageEncoder = new BinaryWriter(1024);
5754
5754
  #sendMessage(message) {
5755
- this.wsPromise.then((wsResolved) => {
5756
- if (!wsResolved || !this.isActive) {
5757
- this.#outboundQueue.push(message);
5758
- return;
5759
- }
5760
- this.#flushOutboundQueue(wsResolved);
5761
- this.#sendEncoded(wsResolved, message);
5762
- });
5755
+ const writer = this.#clientMessageEncoder;
5756
+ writer.clear();
5757
+ ClientMessage.serialize(writer, message);
5758
+ const encoded = writer.getBuffer();
5759
+ if (this.ws && this.isActive) {
5760
+ if (this.#outboundQueue.length) this.#flushOutboundQueue(this.ws);
5761
+ stdbLogger(
5762
+ "trace",
5763
+ () => `Sending message to server: ${stringify(message)}`
5764
+ );
5765
+ this.ws.send(encoded);
5766
+ } else {
5767
+ stdbLogger(
5768
+ "trace",
5769
+ () => `Queuing message to server: ${stringify(message)}`
5770
+ );
5771
+ this.#outboundQueue.push(encoded.slice());
5772
+ }
5763
5773
  }
5764
5774
  #nextEventId() {
5765
5775
  this.#eventId += 1;
@@ -6101,11 +6111,7 @@ var DbConnectionImpl = class {
6101
6111
  * ```
6102
6112
  */
6103
6113
  disconnect() {
6104
- this.wsPromise.then((wsResolved) => {
6105
- if (wsResolved) {
6106
- wsResolved.close();
6107
- }
6108
- });
6114
+ this.wsPromise.then((ws) => ws?.close());
6109
6115
  }
6110
6116
  on(eventName, callback) {
6111
6117
  this.#emitter.on(eventName, callback);
@@ -6135,17 +6141,45 @@ var DbConnectionImpl = class {
6135
6141
 
6136
6142
  // src/lib/schema.ts
6137
6143
  function tablesToSchema(ctx, tables) {
6144
+ const tableDefs = /* @__PURE__ */ Object.create(null);
6145
+ for (const [accName, schema2] of Object.entries(tables)) {
6146
+ tableDefs[accName] = tableToSchema(
6147
+ accName,
6148
+ schema2,
6149
+ schema2.tableDef(ctx, accName)
6150
+ );
6151
+ }
6138
6152
  return {
6139
- tables: Object.fromEntries(
6140
- Object.entries(tables).map(([accName, schema2]) => [
6141
- accName,
6142
- tableToSchema(accName, schema2, schema2.tableDef(ctx, accName))
6143
- ])
6144
- )
6153
+ tables: tableDefs
6145
6154
  };
6146
6155
  }
6147
6156
  function tableToSchema(accName, schema2, tableDef) {
6148
6157
  const getColName = (i) => schema2.rowType.algebraicType.value.elements[i].name;
6158
+ const resolvedIndexes = tableDef.indexes.map(
6159
+ (idx) => {
6160
+ const accessorName = idx.accessorName;
6161
+ if (typeof accessorName !== "string" || accessorName.length === 0) {
6162
+ throw new TypeError(
6163
+ `Index '${idx.sourceName ?? "<unknown>"}' on table '${tableDef.sourceName}' is missing accessor name`
6164
+ );
6165
+ }
6166
+ const columnIds = idx.algorithm.tag === "Direct" ? [idx.algorithm.value] : idx.algorithm.value;
6167
+ const unique = tableDef.constraints.some(
6168
+ (c) => c.data.tag === "Unique" && c.data.value.columns.every((col) => columnIds.includes(col))
6169
+ );
6170
+ const algorithm = {
6171
+ BTree: "btree",
6172
+ Hash: "hash",
6173
+ Direct: "direct"
6174
+ }[idx.algorithm.tag];
6175
+ return {
6176
+ name: accessorName,
6177
+ unique,
6178
+ algorithm,
6179
+ columns: columnIds.map(getColName)
6180
+ };
6181
+ }
6182
+ );
6149
6183
  return {
6150
6184
  // For client,`schama.tableName` will always be there as canonical name.
6151
6185
  // For module, if explicit name is not provided via `name`, accessor name will
@@ -6155,26 +6189,16 @@ function tableToSchema(accName, schema2, tableDef) {
6155
6189
  columns: schema2.rowType.row,
6156
6190
  // typed as T[i]['rowType']['row'] under TablesToSchema<T>
6157
6191
  rowType: schema2.rowSpacetimeType,
6192
+ // Keep declarative indexes in their original shape for type-level consumers.
6193
+ indexes: schema2.idxs,
6158
6194
  constraints: tableDef.constraints.map((c) => ({
6159
6195
  name: c.sourceName,
6160
6196
  constraint: "unique",
6161
6197
  columns: c.data.value.columns.map(getColName)
6162
6198
  })),
6163
- // TODO: horrible horrible horrible. we smuggle this `Array<UntypedIndex>`
6164
- // by casting it to an `Array<IndexOpts>` as `TableToSchema` expects.
6165
- // This is then used in `TableCacheImpl.constructor` and who knows where else.
6166
- // We should stop lying about our types.
6167
- indexes: tableDef.indexes.map((idx) => {
6168
- const columnIds = idx.algorithm.tag === "Direct" ? [idx.algorithm.value] : idx.algorithm.value;
6169
- return {
6170
- name: idx.accessorName,
6171
- unique: tableDef.constraints.some(
6172
- (c) => c.data.value.columns.every((col) => columnIds.includes(col))
6173
- ),
6174
- algorithm: idx.algorithm.tag.toLowerCase(),
6175
- columns: columnIds.map(getColName)
6176
- };
6177
- }),
6199
+ // Expose resolved runtime indexes separately so runtime users don't have to
6200
+ // reinterpret `indexes` with unsafe casts.
6201
+ resolvedIndexes,
6178
6202
  tableDef,
6179
6203
  ...tableDef.isEvent ? { isEvent: true } : {}
6180
6204
  };
@@ -6998,6 +7022,14 @@ function table(opts, row, ..._) {
6998
7022
  }
6999
7023
  }
7000
7024
  for (const indexOpts of userIndexes ?? []) {
7025
+ const accessor = indexOpts.accessor;
7026
+ if (typeof accessor !== "string" || accessor.length === 0) {
7027
+ const tableLabel = name ?? "<unnamed>";
7028
+ const indexLabel = indexOpts.name ?? "<unnamed>";
7029
+ throw new TypeError(
7030
+ `Index '${indexLabel}' on table '${tableLabel}' must define a non-empty 'accessor'`
7031
+ );
7032
+ }
7001
7033
  let algorithm;
7002
7034
  switch (indexOpts.algorithm) {
7003
7035
  case "btree":
@@ -7018,7 +7050,7 @@ function table(opts, row, ..._) {
7018
7050
  }
7019
7051
  indexes.push({
7020
7052
  sourceName: void 0,
7021
- accessorName: indexOpts.accessor,
7053
+ accessorName: accessor,
7022
7054
  algorithm,
7023
7055
  canonicalName: indexOpts.name
7024
7056
  });
@@ -7068,7 +7100,9 @@ function table(opts, row, ..._) {
7068
7100
  isEvent
7069
7101
  };
7070
7102
  },
7071
- idxs: {},
7103
+ // Preserve the declared index options as runtime data so `tableToSchema`
7104
+ // can expose them without type-smuggling.
7105
+ idxs: userIndexes,
7072
7106
  constraints,
7073
7107
  schedule
7074
7108
  };