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