spacetimedb 2.0.4 → 2.2.0

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 (116) hide show
  1. package/LICENSE.txt +2 -2
  2. package/dist/angular/index.cjs +9 -3
  3. package/dist/angular/index.cjs.map +1 -1
  4. package/dist/angular/index.mjs +9 -3
  5. package/dist/angular/index.mjs.map +1 -1
  6. package/dist/browser/angular/index.mjs +9 -3
  7. package/dist/browser/angular/index.mjs.map +1 -1
  8. package/dist/browser/react/index.mjs +62 -7
  9. package/dist/browser/react/index.mjs.map +1 -1
  10. package/dist/browser/svelte/index.mjs +9 -3
  11. package/dist/browser/svelte/index.mjs.map +1 -1
  12. package/dist/browser/vue/index.mjs +9 -3
  13. package/dist/browser/vue/index.mjs.map +1 -1
  14. package/dist/index.browser.mjs +481 -146
  15. package/dist/index.browser.mjs.map +1 -1
  16. package/dist/index.cjs +481 -146
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.mjs +481 -146
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/lib/algebraic_type.d.ts.map +1 -1
  21. package/dist/lib/binary_reader.d.ts +1 -1
  22. package/dist/lib/binary_reader.d.ts.map +1 -1
  23. package/dist/lib/binary_writer.d.ts +2 -1
  24. package/dist/lib/binary_writer.d.ts.map +1 -1
  25. package/dist/lib/filter.d.ts +2 -1
  26. package/dist/lib/filter.d.ts.map +1 -1
  27. package/dist/lib/query.d.ts +10 -5
  28. package/dist/lib/query.d.ts.map +1 -1
  29. package/dist/lib/table.d.ts +12 -1
  30. package/dist/lib/table.d.ts.map +1 -1
  31. package/dist/min/index.browser.mjs +1 -1
  32. package/dist/min/index.browser.mjs.map +1 -1
  33. package/dist/min/react/index.mjs +1 -1
  34. package/dist/min/react/index.mjs.map +1 -1
  35. package/dist/min/sdk/index.browser.mjs +1 -1
  36. package/dist/min/sdk/index.browser.mjs.map +1 -1
  37. package/dist/react/index.cjs +62 -6
  38. package/dist/react/index.cjs.map +1 -1
  39. package/dist/react/index.d.ts +1 -0
  40. package/dist/react/index.d.ts.map +1 -1
  41. package/dist/react/index.mjs +62 -7
  42. package/dist/react/index.mjs.map +1 -1
  43. package/dist/react/useProcedure.d.ts +4 -0
  44. package/dist/react/useProcedure.d.ts.map +1 -0
  45. package/dist/react/useTable.d.ts +2 -0
  46. package/dist/react/useTable.d.ts.map +1 -1
  47. package/dist/sdk/db_connection_builder.d.ts +3 -3
  48. package/dist/sdk/db_connection_builder.d.ts.map +1 -1
  49. package/dist/sdk/db_connection_impl.d.ts +3 -3
  50. package/dist/sdk/db_connection_impl.d.ts.map +1 -1
  51. package/dist/sdk/decompress.d.ts +1 -1
  52. package/dist/sdk/decompress.d.ts.map +1 -1
  53. package/dist/sdk/index.browser.mjs +477 -144
  54. package/dist/sdk/index.browser.mjs.map +1 -1
  55. package/dist/sdk/index.cjs +477 -144
  56. package/dist/sdk/index.cjs.map +1 -1
  57. package/dist/sdk/index.mjs +477 -144
  58. package/dist/sdk/index.mjs.map +1 -1
  59. package/dist/sdk/table_cache.d.ts +1 -0
  60. package/dist/sdk/table_cache.d.ts.map +1 -1
  61. package/dist/sdk/type_utils.d.ts +4 -1
  62. package/dist/sdk/type_utils.d.ts.map +1 -1
  63. package/dist/sdk/websocket_decompress_adapter.d.ts +5 -21
  64. package/dist/sdk/websocket_decompress_adapter.d.ts.map +1 -1
  65. package/dist/sdk/websocket_protocols.d.ts +6 -0
  66. package/dist/sdk/websocket_protocols.d.ts.map +1 -0
  67. package/dist/sdk/websocket_test_adapter.d.ts +14 -18
  68. package/dist/sdk/websocket_test_adapter.d.ts.map +1 -1
  69. package/dist/sdk/websocket_v3_frames.d.ts +9 -0
  70. package/dist/sdk/websocket_v3_frames.d.ts.map +1 -0
  71. package/dist/sdk/ws.d.ts +26 -1
  72. package/dist/sdk/ws.d.ts.map +1 -1
  73. package/dist/server/http_internal.d.ts.map +1 -1
  74. package/dist/server/index.d.ts +2 -1
  75. package/dist/server/index.d.ts.map +1 -1
  76. package/dist/server/index.mjs +76 -15
  77. package/dist/server/index.mjs.map +1 -1
  78. package/dist/server/runtime.d.ts +29 -2
  79. package/dist/server/runtime.d.ts.map +1 -1
  80. package/dist/svelte/index.cjs +9 -3
  81. package/dist/svelte/index.cjs.map +1 -1
  82. package/dist/svelte/index.mjs +9 -3
  83. package/dist/svelte/index.mjs.map +1 -1
  84. package/dist/tanstack/index.cjs +9 -3
  85. package/dist/tanstack/index.cjs.map +1 -1
  86. package/dist/tanstack/index.mjs +9 -3
  87. package/dist/tanstack/index.mjs.map +1 -1
  88. package/dist/vue/index.cjs +9 -3
  89. package/dist/vue/index.cjs.map +1 -1
  90. package/dist/vue/index.mjs +9 -3
  91. package/dist/vue/index.mjs.map +1 -1
  92. package/package.json +2 -2
  93. package/src/lib/algebraic_type.ts +5 -1
  94. package/src/lib/binary_reader.ts +5 -2
  95. package/src/lib/binary_writer.ts +7 -1
  96. package/src/lib/filter.ts +12 -1
  97. package/src/lib/query.ts +60 -19
  98. package/src/lib/table.ts +15 -2
  99. package/src/react/index.ts +1 -0
  100. package/src/react/useProcedure.ts +60 -0
  101. package/src/react/useTable.ts +22 -2
  102. package/src/sdk/db_connection_builder.ts +16 -7
  103. package/src/sdk/db_connection_impl.ts +404 -89
  104. package/src/sdk/decompress.ts +7 -23
  105. package/src/sdk/table_cache.ts +5 -5
  106. package/src/sdk/type_utils.ts +10 -1
  107. package/src/sdk/websocket_decompress_adapter.ts +15 -77
  108. package/src/sdk/websocket_protocols.ts +25 -0
  109. package/src/sdk/websocket_test_adapter.ts +65 -29
  110. package/src/sdk/websocket_v3_frames.ts +126 -0
  111. package/src/sdk/ws.ts +81 -3
  112. package/src/server/http_internal.ts +10 -1
  113. package/src/server/index.ts +2 -1
  114. package/src/server/runtime.ts +39 -1
  115. package/src/server/sys.d.ts +4 -0
  116. package/src/server/view.test-d.ts +4 -0
@@ -428,8 +428,8 @@ var BinaryReader = class {
428
428
  this.view = input instanceof DataView ? input : new DataView(input.buffer, input.byteOffset, input.byteLength);
429
429
  this.offset = 0;
430
430
  }
431
- reset(view) {
432
- this.view = view;
431
+ reset(input) {
432
+ this.view = input instanceof DataView ? input : new DataView(input.buffer, input.byteOffset, input.byteLength);
433
433
  this.offset = 0;
434
434
  }
435
435
  get remaining() {
@@ -621,6 +621,11 @@ var BinaryWriter = class {
621
621
  this.view.setUint8(this.offset, value);
622
622
  this.offset += 1;
623
623
  }
624
+ writeBytes(value) {
625
+ this.expandBuffer(value.length);
626
+ new Uint8Array(this.buffer.buffer, this.offset, value.length).set(value);
627
+ this.offset += value.length;
628
+ }
624
629
  writeI8(value) {
625
630
  this.expandBuffer(1);
626
631
  this.view.setInt8(this.offset, value);
@@ -1177,7 +1182,8 @@ writer.offset += ${primitiveSizes[tag]};` : `writer.write${tag}(value.${name});`
1177
1182
  const result = { ${ty.elements.map(getElementInitializer).join(", ")} };
1178
1183
  const view = reader.view;
1179
1184
  ${ty.elements.map(
1180
- ({ name, algebraicType: { tag } }) => tag in primitiveJSName ? `result.${name} = view.get${primitiveJSName[tag]}(reader.offset, ${primitiveSizes[tag] > 1 ? "true" : ""});
1185
+ ({ name, algebraicType: { tag } }) => tag in primitiveJSName ? tag === "Bool" ? `result.${name} = view.getUint8(reader.offset) !== 0;
1186
+ reader.offset += 1;` : `result.${name} = view.get${primitiveJSName[tag]}(reader.offset, ${primitiveSizes[tag] > 1 ? "true" : ""});
1181
1187
  reader.offset += ${primitiveSizes[tag]};` : `result.${name} = reader.read${tag}();`
1182
1188
  ).join("\n")}
1183
1189
  return result;`;
@@ -1673,7 +1679,8 @@ function createRowExpr(tableDef) {
1673
1679
  const column = new ColumnExpression(
1674
1680
  tableDef.sourceName,
1675
1681
  columnName,
1676
- columnBuilder.typeBuilder.algebraicType
1682
+ columnBuilder.typeBuilder.algebraicType,
1683
+ columnBuilder.columnMetadata.name
1677
1684
  );
1678
1685
  row[columnName] = Object.freeze(column);
1679
1686
  }
@@ -1691,14 +1698,18 @@ function renderSelectSqlWithJoins(table2, where, extraClauses = []) {
1691
1698
  }
1692
1699
  var ColumnExpression = class {
1693
1700
  type = "column";
1701
+ // This is the column accessor
1694
1702
  column;
1703
+ // The name of the column in the database.
1704
+ columnName;
1695
1705
  table;
1696
1706
  // phantom: actual runtime value is undefined
1697
1707
  tsValueType;
1698
1708
  spacetimeType;
1699
- constructor(table2, column, spacetimeType) {
1709
+ constructor(table2, column, spacetimeType, columnName) {
1700
1710
  this.table = table2;
1701
1711
  this.column = column;
1712
+ this.columnName = columnName || column;
1702
1713
  this.spacetimeType = spacetimeType;
1703
1714
  }
1704
1715
  eq(x) {
@@ -1775,10 +1786,16 @@ var BooleanExpr = class _BooleanExpr {
1775
1786
  this.data = data;
1776
1787
  }
1777
1788
  and(other) {
1778
- return new _BooleanExpr({ type: "and", clauses: [this.data, other.data] });
1789
+ return new _BooleanExpr({
1790
+ type: "and",
1791
+ clauses: [this.data, other.data]
1792
+ });
1779
1793
  }
1780
1794
  or(other) {
1781
- return new _BooleanExpr({ type: "or", clauses: [this.data, other.data] });
1795
+ return new _BooleanExpr({
1796
+ type: "or",
1797
+ clauses: [this.data, other.data]
1798
+ });
1782
1799
  }
1783
1800
  not() {
1784
1801
  return new _BooleanExpr({ type: "not", clause: this.data });
@@ -1815,7 +1832,7 @@ function valueExprToSql(expr, tableAlias) {
1815
1832
  return literalValueToSql(expr.value);
1816
1833
  }
1817
1834
  const table2 = expr.table;
1818
- return `${quoteIdentifier(table2)}.${quoteIdentifier(expr.column)}`;
1835
+ return `${quoteIdentifier(table2)}.${quoteIdentifier(expr.columnName)}`;
1819
1836
  }
1820
1837
  function literalValueToSql(value) {
1821
1838
  if (value === null || value === void 0) {
@@ -4318,6 +4335,7 @@ var scalarCompare = (x, y) => {
4318
4335
  return x < y ? -1 : 1;
4319
4336
  };
4320
4337
  var TableCacheImpl = class {
4338
+ hasPrimaryKey;
4321
4339
  rows;
4322
4340
  tableDef;
4323
4341
  emitter;
@@ -4331,6 +4349,9 @@ var TableCacheImpl = class {
4331
4349
  this.tableDef = tableDef;
4332
4350
  this.rows = /* @__PURE__ */ new Map();
4333
4351
  this.emitter = new EventEmitter();
4352
+ this.hasPrimaryKey = Object.values(this.tableDef.columns).some(
4353
+ (col) => col.columnMetadata.isPrimaryKey === true
4354
+ );
4334
4355
  for (const idxDef of this.tableDef.resolvedIndexes) {
4335
4356
  const index = this.#makeReadonlyIndex(this.tableDef, idxDef);
4336
4357
  this[idxDef.name] = index;
@@ -4440,10 +4461,7 @@ var TableCacheImpl = class {
4440
4461
  }
4441
4462
  return pendingCallbacks;
4442
4463
  }
4443
- const hasPrimaryKey = Object.values(this.tableDef.columns).some(
4444
- (col) => col.columnMetadata.isPrimaryKey === true
4445
- );
4446
- if (hasPrimaryKey) {
4464
+ if (this.hasPrimaryKey) {
4447
4465
  const insertMap = /* @__PURE__ */ new Map();
4448
4466
  const deleteMap = /* @__PURE__ */ new Map();
4449
4467
  for (const op of operations) {
@@ -4851,27 +4869,17 @@ async function decompress(buffer, type, chunkSize = 128 * 1024) {
4851
4869
  });
4852
4870
  const decompressionStream = new DecompressionStream(type);
4853
4871
  const decompressedStream = readableStream.pipeThrough(decompressionStream);
4854
- const reader = decompressedStream.getReader();
4855
4872
  const chunks = [];
4856
- let totalLength = 0;
4857
- let result;
4858
- while (!(result = await reader.read()).done) {
4859
- chunks.push(result.value);
4860
- totalLength += result.value.length;
4861
- }
4862
- const decompressedArray = new Uint8Array(totalLength);
4863
- let chunkOffset = 0;
4864
- for (const chunk of chunks) {
4865
- decompressedArray.set(chunk, chunkOffset);
4866
- chunkOffset += chunk.length;
4867
- }
4868
- return decompressedArray;
4873
+ for await (const chunk of decompressedStream) {
4874
+ chunks.push(chunk);
4875
+ }
4876
+ return new Blob(chunks).bytes();
4869
4877
  }
4870
4878
 
4871
4879
  // src/sdk/ws.ts
4872
4880
  async function resolveWS() {
4873
- if (typeof globalThis.WebSocket !== "undefined") {
4874
- return globalThis.WebSocket;
4881
+ if (typeof WebSocket !== "undefined") {
4882
+ return WebSocket;
4875
4883
  }
4876
4884
  const dynamicImport = new Function("m", "return import(m)");
4877
4885
  try {
@@ -4885,9 +4893,54 @@ async function resolveWS() {
4885
4893
  throw err;
4886
4894
  }
4887
4895
  }
4896
+ async function openWebSocket({
4897
+ url,
4898
+ nameOrAddress,
4899
+ wsProtocol,
4900
+ authToken,
4901
+ compression,
4902
+ lightMode,
4903
+ confirmedReads
4904
+ }) {
4905
+ const headers = new Headers();
4906
+ const WS = await resolveWS();
4907
+ let temporaryAuthToken;
4908
+ if (authToken) {
4909
+ headers.set("Authorization", `Bearer ${authToken}`);
4910
+ const tokenUrl = new URL("v1/identity/websocket-token", url);
4911
+ tokenUrl.protocol = url.protocol === "wss:" ? "https:" : "http:";
4912
+ const response = await fetch(tokenUrl, { method: "POST", headers });
4913
+ if (response.ok) {
4914
+ const { token } = await response.json();
4915
+ temporaryAuthToken = token;
4916
+ } else {
4917
+ throw new Error(`Failed to verify token: ${response.statusText}`);
4918
+ }
4919
+ }
4920
+ const databaseUrl = new URL(`v1/database/${nameOrAddress}/subscribe`, url);
4921
+ if (temporaryAuthToken) {
4922
+ databaseUrl.searchParams.set("token", temporaryAuthToken);
4923
+ }
4924
+ databaseUrl.searchParams.set(
4925
+ "compression",
4926
+ { gzip: "Gzip", brotli: "Brotli", none: "None" }[compression] ?? "None"
4927
+ );
4928
+ if (lightMode) {
4929
+ databaseUrl.searchParams.set("light", "true");
4930
+ }
4931
+ if (confirmedReads !== void 0) {
4932
+ databaseUrl.searchParams.set("confirmed", confirmedReads.toString());
4933
+ }
4934
+ const ws = new WS(databaseUrl.toString(), wsProtocol);
4935
+ ws.binaryType = "arraybuffer";
4936
+ return ws;
4937
+ }
4888
4938
 
4889
4939
  // src/sdk/websocket_decompress_adapter.ts
4890
4940
  var WebsocketDecompressAdapter = class _WebsocketDecompressAdapter {
4941
+ get protocol() {
4942
+ return this.#ws.protocol;
4943
+ }
4891
4944
  set onclose(handler) {
4892
4945
  this.#ws.onclose = handler;
4893
4946
  }
@@ -4911,9 +4964,7 @@ var WebsocketDecompressAdapter = class _WebsocketDecompressAdapter {
4911
4964
  case 0:
4912
4965
  return data;
4913
4966
  case 1:
4914
- throw new Error(
4915
- "Brotli Compression not supported. Please use gzip or none compression in withCompression method on DbConnection."
4916
- );
4967
+ return await decompress(data, "brotli");
4917
4968
  case 2:
4918
4969
  return await decompress(data, "gzip");
4919
4970
  default:
@@ -4929,51 +4980,10 @@ var WebsocketDecompressAdapter = class _WebsocketDecompressAdapter {
4929
4980
  this.#ws.close();
4930
4981
  }
4931
4982
  constructor(ws) {
4932
- ws.binaryType = "arraybuffer";
4933
4983
  this.#ws = ws;
4934
4984
  }
4935
- static async createWebSocketFn({
4936
- url,
4937
- nameOrAddress,
4938
- wsProtocol,
4939
- authToken,
4940
- compression,
4941
- lightMode,
4942
- confirmedReads
4943
- }) {
4944
- const headers = new Headers();
4945
- const WS = await resolveWS();
4946
- let temporaryAuthToken = void 0;
4947
- if (authToken) {
4948
- headers.set("Authorization", `Bearer ${authToken}`);
4949
- const tokenUrl = new URL("v1/identity/websocket-token", url);
4950
- tokenUrl.protocol = url.protocol === "wss:" ? "https:" : "http:";
4951
- const response = await fetch(tokenUrl, { method: "POST", headers });
4952
- if (response.ok) {
4953
- const { token } = await response.json();
4954
- temporaryAuthToken = token;
4955
- } else {
4956
- return Promise.reject(
4957
- new Error(`Failed to verify token: ${response.statusText}`)
4958
- );
4959
- }
4960
- }
4961
- const databaseUrl = new URL(`v1/database/${nameOrAddress}/subscribe`, url);
4962
- if (temporaryAuthToken) {
4963
- databaseUrl.searchParams.set("token", temporaryAuthToken);
4964
- }
4965
- databaseUrl.searchParams.set(
4966
- "compression",
4967
- compression === "gzip" ? "Gzip" : "None"
4968
- );
4969
- if (lightMode) {
4970
- databaseUrl.searchParams.set("light", "true");
4971
- }
4972
- if (confirmedReads !== void 0) {
4973
- databaseUrl.searchParams.set("confirmed", confirmedReads.toString());
4974
- }
4975
- const ws = new WS(databaseUrl.toString(), wsProtocol);
4976
- return new _WebsocketDecompressAdapter(ws);
4985
+ static async openWebSocket(args) {
4986
+ return new _WebsocketDecompressAdapter(await openWebSocket(args));
4977
4987
  }
4978
4988
  };
4979
4989
 
@@ -4990,7 +5000,7 @@ var DbConnectionBuilder = class {
4990
5000
  constructor(remoteModule, dbConnectionCtor) {
4991
5001
  this.remoteModule = remoteModule;
4992
5002
  this.dbConnectionCtor = dbConnectionCtor;
4993
- this.#createWSFn = WebsocketDecompressAdapter.createWebSocketFn;
5003
+ this.#createWSFn = WebsocketDecompressAdapter.openWebSocket;
4994
5004
  }
4995
5005
  #uri;
4996
5006
  #nameOrAddress;
@@ -5045,6 +5055,16 @@ var DbConnectionBuilder = class {
5045
5055
  * @param compression The compression algorithm to use for the connection.
5046
5056
  */
5047
5057
  withCompression(compression) {
5058
+ if (compression === "brotli") {
5059
+ try {
5060
+ new DecompressionStream("brotli");
5061
+ } catch (e) {
5062
+ throw new TypeError(
5063
+ `Brotli compression is not supported by the runtime. Please choose a different compression method.`,
5064
+ { cause: e }
5065
+ );
5066
+ }
5067
+ }
5048
5068
  this.#compression = compression;
5049
5069
  return this;
5050
5070
  }
@@ -5408,6 +5428,100 @@ var SubscriptionHandleImpl = class {
5408
5428
  return this.#activeState;
5409
5429
  }
5410
5430
  };
5431
+
5432
+ // src/sdk/websocket_protocols.ts
5433
+ var V2_WS_PROTOCOL = "v2.bsatn.spacetimedb";
5434
+ var V3_WS_PROTOCOL = "v3.bsatn.spacetimedb";
5435
+ var PREFERRED_WS_PROTOCOLS = [V3_WS_PROTOCOL, V2_WS_PROTOCOL];
5436
+ function normalizeWsProtocol(protocol) {
5437
+ if (protocol === V3_WS_PROTOCOL) {
5438
+ return V3_WS_PROTOCOL;
5439
+ }
5440
+ if (protocol === "" || protocol === V2_WS_PROTOCOL) {
5441
+ return V2_WS_PROTOCOL;
5442
+ }
5443
+ stdbLogger(
5444
+ "warn",
5445
+ `Unexpected websocket subprotocol "${protocol}", falling back to ${V2_WS_PROTOCOL}.`
5446
+ );
5447
+ return V2_WS_PROTOCOL;
5448
+ }
5449
+
5450
+ // src/sdk/websocket_v3_frames.ts
5451
+ var EMPTY_V3_PAYLOAD_ERR = "v3 websocket payloads must contain at least one message";
5452
+ function ensureMessages(messages) {
5453
+ if (messages.length === 0) {
5454
+ throw new RangeError(EMPTY_V3_PAYLOAD_ERR);
5455
+ }
5456
+ }
5457
+ function ensureMessageCount(messages, messageCount) {
5458
+ ensureMessages(messages);
5459
+ if (messageCount < 1 || messageCount > messages.length) {
5460
+ throw new RangeError(
5461
+ `v3 websocket payload requested ${messageCount} messages from ${messages.length}`
5462
+ );
5463
+ }
5464
+ }
5465
+ function concatenateMessagesV3(writer, messages, messageCount = messages.length) {
5466
+ ensureMessageCount(messages, messageCount);
5467
+ writer.clear();
5468
+ for (let i = 0; i < messageCount; i++) {
5469
+ writer.writeBytes(messages[i]);
5470
+ }
5471
+ return writer.getBuffer();
5472
+ }
5473
+ function countClientMessagesForV3Frame(messages, maxFrameBytes) {
5474
+ ensureMessages(messages);
5475
+ const firstMessage = messages[0];
5476
+ if (firstMessage.length > maxFrameBytes) {
5477
+ return 1;
5478
+ }
5479
+ let count = 1;
5480
+ let frameSize = firstMessage.length;
5481
+ while (count < messages.length) {
5482
+ const nextMessage = messages[count];
5483
+ const nextFrameSize = frameSize + nextMessage.length;
5484
+ if (nextFrameSize > maxFrameBytes) {
5485
+ break;
5486
+ }
5487
+ frameSize = nextFrameSize;
5488
+ count += 1;
5489
+ }
5490
+ return count;
5491
+ }
5492
+ function encodeClientMessagesV3(writer, messages, messageCount = messages.length) {
5493
+ return concatenateMessagesV3(writer, messages, messageCount);
5494
+ }
5495
+ function forEachServerMessageV3(reader, data, visit) {
5496
+ reader.reset(data);
5497
+ if (reader.remaining === 0) {
5498
+ throw new RangeError(EMPTY_V3_PAYLOAD_ERR);
5499
+ }
5500
+ let count = 0;
5501
+ while (reader.remaining > 0) {
5502
+ visit(ServerMessage.deserialize(reader));
5503
+ count += 1;
5504
+ }
5505
+ return count;
5506
+ }
5507
+
5508
+ // src/sdk/db_connection_impl.ts
5509
+ var TEXT_ENCODER = new TextEncoder();
5510
+ function getClientMessageVariantTag(name) {
5511
+ if (ClientMessage.algebraicType.tag !== "Sum") {
5512
+ throw new TypeError("ClientMessage must be a sum type");
5513
+ }
5514
+ const tag = ClientMessage.algebraicType.value.variants.findIndex(
5515
+ (variant) => variant.name === name
5516
+ );
5517
+ if (tag === -1) {
5518
+ throw new RangeError(`Unknown ClientMessage variant: ${name}`);
5519
+ }
5520
+ return tag;
5521
+ }
5522
+ var CLIENT_MESSAGE_CALL_REDUCER_TAG = getClientMessageVariantTag("CallReducer");
5523
+ var CLIENT_MESSAGE_CALL_PROCEDURE_TAG = getClientMessageVariantTag("CallProcedure");
5524
+ var MAX_V3_OUTBOUND_FRAME_BYTES = 256 * 1024;
5411
5525
  var DbConnectionImpl = class {
5412
5526
  /**
5413
5527
  * Whether or not the connection is active.
@@ -5442,22 +5556,35 @@ var DbConnectionImpl = class {
5442
5556
  * The `ConnectionId` of the connection to to the database.
5443
5557
  */
5444
5558
  connectionId = ConnectionId.random();
5559
+ #connectionIdHex = this.connectionId.toHexString();
5445
5560
  // These fields are meant to be strictly private.
5446
5561
  #queryId = 0;
5447
5562
  #requestId = 0;
5448
5563
  #eventId = 0;
5449
5564
  #emitter;
5450
- #messageQueue = Promise.resolve();
5565
+ #inboundQueue = [];
5566
+ #inboundQueueOffset = 0;
5567
+ #isDrainingInboundQueue = false;
5451
5568
  #outboundQueue = [];
5569
+ #isOutboundFlushScheduled = false;
5570
+ #negotiatedWsProtocol = V2_WS_PROTOCOL;
5452
5571
  #subscriptionManager = new SubscriptionManager();
5453
5572
  #remoteModule;
5454
5573
  #reducerCallbacks = /* @__PURE__ */ new Map();
5455
5574
  #reducerCallInfo = /* @__PURE__ */ new Map();
5456
5575
  #procedureCallbacks = /* @__PURE__ */ new Map();
5457
5576
  #rowDeserializers;
5577
+ #rowIdMetadata;
5458
5578
  #reducerArgsSerializers;
5459
5579
  #procedureSerializers;
5580
+ #reducerNameBytes;
5581
+ #procedureNameBytes;
5460
5582
  #sourceNameToTableDef;
5583
+ #messageReader = new BinaryReader(new Uint8Array());
5584
+ #rowListReader = new BinaryReader(new Uint8Array());
5585
+ #clientFrameEncoder = new BinaryWriter(1024);
5586
+ #boundSubscriptionBuilder;
5587
+ #boundDisconnect;
5461
5588
  // These fields are not part of the public API, but in a pinch you
5462
5589
  // could use JavaScript to access them by bypassing TypeScript's
5463
5590
  // private fields.
@@ -5486,22 +5613,35 @@ var DbConnectionImpl = class {
5486
5613
  this.token = token;
5487
5614
  this.#remoteModule = remoteModule;
5488
5615
  this.#emitter = emitter;
5616
+ this.#boundSubscriptionBuilder = this.subscriptionBuilder.bind(this);
5617
+ this.#boundDisconnect = this.disconnect.bind(this);
5489
5618
  this.#rowDeserializers = /* @__PURE__ */ Object.create(null);
5619
+ this.#rowIdMetadata = /* @__PURE__ */ Object.create(null);
5490
5620
  this.#sourceNameToTableDef = /* @__PURE__ */ Object.create(null);
5491
5621
  for (const table2 of Object.values(remoteModule.tables)) {
5492
5622
  this.#rowDeserializers[table2.sourceName] = ProductType.makeDeserializer(
5493
5623
  table2.rowType
5494
5624
  );
5495
5625
  this.#sourceNameToTableDef[table2.sourceName] = table2;
5626
+ const primaryKeyColumn = Object.entries(table2.columns).find(
5627
+ ([, column]) => column.columnMetadata.isPrimaryKey
5628
+ );
5629
+ this.#rowIdMetadata[table2.sourceName] = primaryKeyColumn ? {
5630
+ primaryKeyColName: primaryKeyColumn[0],
5631
+ primaryKeyColType: primaryKeyColumn[1].typeBuilder.algebraicType
5632
+ } : {};
5496
5633
  }
5497
5634
  this.#reducerArgsSerializers = /* @__PURE__ */ Object.create(null);
5635
+ this.#reducerNameBytes = /* @__PURE__ */ Object.create(null);
5498
5636
  for (const reducer of remoteModule.reducers) {
5499
5637
  this.#reducerArgsSerializers[reducer.name] = {
5500
5638
  serialize: ProductType.makeSerializer(reducer.paramsType),
5501
5639
  deserialize: ProductType.makeDeserializer(reducer.paramsType)
5502
5640
  };
5641
+ this.#reducerNameBytes[reducer.name] = TEXT_ENCODER.encode(reducer.name);
5503
5642
  }
5504
5643
  this.#procedureSerializers = /* @__PURE__ */ Object.create(null);
5644
+ this.#procedureNameBytes = /* @__PURE__ */ Object.create(null);
5505
5645
  for (const procedure of remoteModule.procedures) {
5506
5646
  this.#procedureSerializers[procedure.name] = {
5507
5647
  serializeArgs: ProductType.makeSerializer(
@@ -5511,9 +5651,11 @@ var DbConnectionImpl = class {
5511
5651
  procedure.returnType.algebraicType
5512
5652
  )
5513
5653
  };
5654
+ this.#procedureNameBytes[procedure.name] = TEXT_ENCODER.encode(
5655
+ procedure.name
5656
+ );
5514
5657
  }
5515
- const connectionId = this.connectionId.toHexString();
5516
- url.searchParams.set("connection_id", connectionId);
5658
+ url.searchParams.set("connection_id", this.#connectionIdHex);
5517
5659
  this.clientCache = new ClientCache();
5518
5660
  this.db = this.#makeDbView();
5519
5661
  this.reducers = this.#makeReducers(remoteModule);
@@ -5521,7 +5663,7 @@ var DbConnectionImpl = class {
5521
5663
  this.wsPromise = createWSFn({
5522
5664
  url,
5523
5665
  nameOrAddress,
5524
- wsProtocol: "v2.bsatn.spacetimedb",
5666
+ wsProtocol: [...PREFERRED_WS_PROTOCOLS],
5525
5667
  authToken: token,
5526
5668
  compression,
5527
5669
  lightMode,
@@ -5565,16 +5707,22 @@ var DbConnectionImpl = class {
5565
5707
  }
5566
5708
  #makeReducers(def) {
5567
5709
  const out = {};
5568
- const writer = new BinaryWriter(1024);
5569
5710
  for (const reducer of def.reducers) {
5570
5711
  const reducerName = reducer.name;
5712
+ const encodedReducerName = this.#reducerNameBytes[reducerName];
5571
5713
  const key = reducer.accessorName;
5572
5714
  const { serialize: serializeArgs } = this.#reducerArgsSerializers[reducerName];
5573
5715
  out[key] = (params) => {
5716
+ const writer = this.#reducerArgsEncoder;
5574
5717
  writer.clear();
5575
5718
  serializeArgs(writer, params);
5576
5719
  const argsBuffer = writer.getBuffer();
5577
- return this.callReducer(reducerName, argsBuffer, params);
5720
+ return this.#callReducerWithEncodedName(
5721
+ reducerName,
5722
+ encodedReducerName,
5723
+ argsBuffer,
5724
+ params
5725
+ );
5578
5726
  };
5579
5727
  }
5580
5728
  return out;
@@ -5584,13 +5732,18 @@ var DbConnectionImpl = class {
5584
5732
  const writer = new BinaryWriter(1024);
5585
5733
  for (const procedure of def.procedures) {
5586
5734
  const procedureName = procedure.name;
5735
+ const encodedProcedureName = this.#procedureNameBytes[procedureName];
5587
5736
  const key = procedure.accessorName;
5588
5737
  const { serializeArgs, deserializeReturn } = this.#procedureSerializers[procedureName];
5589
5738
  out[key] = (params) => {
5590
5739
  writer.clear();
5591
5740
  serializeArgs(writer, params);
5592
5741
  const argsBuffer = writer.getBuffer();
5593
- return this.callProcedure(procedureName, argsBuffer).then((returnBuf) => {
5742
+ return this.#callProcedureWithEncodedName(
5743
+ procedureName,
5744
+ encodedProcedureName,
5745
+ argsBuffer
5746
+ ).then((returnBuf) => {
5594
5747
  return deserializeReturn(new BinaryReader(returnBuf));
5595
5748
  });
5596
5749
  };
@@ -5602,8 +5755,8 @@ var DbConnectionImpl = class {
5602
5755
  db: this.db,
5603
5756
  reducers: this.reducers,
5604
5757
  isActive: this.isActive,
5605
- subscriptionBuilder: this.subscriptionBuilder.bind(this),
5606
- disconnect: this.disconnect.bind(this),
5758
+ subscriptionBuilder: this.#boundSubscriptionBuilder,
5759
+ disconnect: this.#boundDisconnect,
5607
5760
  event
5608
5761
  };
5609
5762
  }
@@ -5648,21 +5801,16 @@ var DbConnectionImpl = class {
5648
5801
  }
5649
5802
  #parseRowList(type, tableName, rowList) {
5650
5803
  const buffer = rowList.rowsData;
5651
- const reader = new BinaryReader(buffer);
5804
+ const reader = this.#rowListReader;
5805
+ reader.reset(buffer);
5652
5806
  const rows = [];
5653
5807
  const deserializeRow = this.#rowDeserializers[tableName];
5654
- const table2 = this.#sourceNameToTableDef[tableName];
5655
- const columnsArray = Object.entries(table2.columns);
5656
- const primaryKeyColumnEntry = columnsArray.find(
5657
- (col) => col[1].columnMetadata.isPrimaryKey
5658
- );
5808
+ const { primaryKeyColName, primaryKeyColType } = this.#rowIdMetadata[tableName];
5659
5809
  let previousOffset = 0;
5660
5810
  while (reader.remaining > 0) {
5661
5811
  const row = deserializeRow(reader);
5662
5812
  let rowId = void 0;
5663
- if (primaryKeyColumnEntry !== void 0) {
5664
- const primaryKeyColName = primaryKeyColumnEntry[0];
5665
- const primaryKeyColType = primaryKeyColumnEntry[1].typeBuilder.algebraicType;
5813
+ if (primaryKeyColName !== void 0 && primaryKeyColType !== void 0) {
5666
5814
  rowId = AlgebraicType.intoMapKey(
5667
5815
  primaryKeyColType,
5668
5816
  row[primaryKeyColName]
@@ -5743,40 +5891,136 @@ var DbConnectionImpl = class {
5743
5891
  return this.#mergeTableUpdates(updates);
5744
5892
  }
5745
5893
  #flushOutboundQueue(wsResolved) {
5894
+ if (this.#negotiatedWsProtocol === V3_WS_PROTOCOL) {
5895
+ this.#flushOutboundQueueV3(wsResolved);
5896
+ return;
5897
+ }
5898
+ this.#flushOutboundQueueV2(wsResolved);
5899
+ }
5900
+ #flushOutboundQueueV2(wsResolved) {
5746
5901
  const pending = this.#outboundQueue.splice(0);
5747
5902
  for (const message of pending) {
5748
5903
  wsResolved.send(message);
5749
5904
  }
5750
5905
  }
5906
+ #flushOutboundQueueV3(wsResolved) {
5907
+ if (this.#outboundQueue.length === 0) {
5908
+ return;
5909
+ }
5910
+ const batchSize = countClientMessagesForV3Frame(
5911
+ this.#outboundQueue,
5912
+ MAX_V3_OUTBOUND_FRAME_BYTES
5913
+ );
5914
+ wsResolved.send(
5915
+ encodeClientMessagesV3(
5916
+ this.#clientFrameEncoder,
5917
+ this.#outboundQueue,
5918
+ batchSize
5919
+ )
5920
+ );
5921
+ if (batchSize === this.#outboundQueue.length) {
5922
+ this.#outboundQueue.length = 0;
5923
+ return;
5924
+ }
5925
+ this.#outboundQueue.copyWithin(0, batchSize);
5926
+ this.#outboundQueue.length -= batchSize;
5927
+ if (this.#outboundQueue.length > 0) {
5928
+ this.#scheduleDeferredOutboundFlush();
5929
+ }
5930
+ }
5931
+ #scheduleOutboundFlush() {
5932
+ this.#scheduleOutboundFlushWith("microtask");
5933
+ }
5934
+ #scheduleDeferredOutboundFlush() {
5935
+ this.#scheduleOutboundFlushWith("next-task");
5936
+ }
5937
+ #scheduleOutboundFlushWith(schedule) {
5938
+ if (this.#isOutboundFlushScheduled) {
5939
+ return;
5940
+ }
5941
+ this.#isOutboundFlushScheduled = true;
5942
+ const flush = () => {
5943
+ this.#isOutboundFlushScheduled = false;
5944
+ if (this.ws && this.isActive) {
5945
+ this.#flushOutboundQueue(this.ws);
5946
+ }
5947
+ };
5948
+ if (schedule === "next-task") {
5949
+ setTimeout(flush, 0);
5950
+ } else {
5951
+ queueMicrotask(flush);
5952
+ }
5953
+ }
5954
+ #reducerArgsEncoder = new BinaryWriter(1024);
5751
5955
  #clientMessageEncoder = new BinaryWriter(1024);
5956
+ #sendEncodedMessage(encoded, describe) {
5957
+ stdbLogger("trace", describe);
5958
+ if (this.ws && this.isActive) {
5959
+ if (this.#negotiatedWsProtocol === V2_WS_PROTOCOL) {
5960
+ if (this.#outboundQueue.length) this.#flushOutboundQueue(this.ws);
5961
+ this.ws.send(encoded);
5962
+ return;
5963
+ }
5964
+ this.#outboundQueue.push(encoded.slice());
5965
+ this.#scheduleOutboundFlush();
5966
+ } else {
5967
+ this.#outboundQueue.push(encoded.slice());
5968
+ }
5969
+ }
5752
5970
  #sendMessage(message) {
5753
5971
  const writer = this.#clientMessageEncoder;
5754
5972
  writer.clear();
5755
5973
  ClientMessage.serialize(writer, message);
5756
5974
  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
- }
5975
+ const isLive = !!(this.ws && this.isActive);
5976
+ this.#sendEncodedMessage(
5977
+ encoded,
5978
+ () => isLive ? `Sending message to server: ${stringify(message)}` : `Queuing message to server: ${stringify(message)}`
5979
+ );
5980
+ }
5981
+ #sendCallReducerMessage(requestId, reducerNameBytes, argsBuffer) {
5982
+ const writer = this.#clientMessageEncoder;
5983
+ writer.clear();
5984
+ writer.writeByte(CLIENT_MESSAGE_CALL_REDUCER_TAG);
5985
+ writer.writeU32(requestId);
5986
+ writer.writeU8(0);
5987
+ writer.writeUInt8Array(reducerNameBytes);
5988
+ writer.writeUInt8Array(argsBuffer);
5989
+ const encoded = writer.getBuffer();
5990
+ this.#sendEncodedMessage(
5991
+ encoded,
5992
+ () => `Sending reducer call message to server: requestId=${requestId}`
5993
+ );
5994
+ }
5995
+ #sendCallProcedureMessage(requestId, procedureNameBytes, argsBuffer) {
5996
+ const writer = this.#clientMessageEncoder;
5997
+ writer.clear();
5998
+ writer.writeByte(CLIENT_MESSAGE_CALL_PROCEDURE_TAG);
5999
+ writer.writeU32(requestId);
6000
+ writer.writeU8(0);
6001
+ writer.writeUInt8Array(procedureNameBytes);
6002
+ writer.writeUInt8Array(argsBuffer);
6003
+ const encoded = writer.getBuffer();
6004
+ this.#sendEncodedMessage(
6005
+ encoded,
6006
+ () => `Sending procedure call message to server: requestId=${requestId}`
6007
+ );
6008
+ }
6009
+ #setConnectionId(connectionId) {
6010
+ this.connectionId = connectionId;
6011
+ this.#connectionIdHex = connectionId.toHexString();
5771
6012
  }
5772
6013
  #nextEventId() {
5773
6014
  this.#eventId += 1;
5774
- return `${this.connectionId.toHexString()}:${this.#eventId}`;
6015
+ return `${this.#connectionIdHex}:${this.#eventId}`;
5775
6016
  }
5776
6017
  /**
5777
6018
  * Handles WebSocket onOpen event.
5778
6019
  */
5779
6020
  #handleOnOpen() {
6021
+ if (this.ws) {
6022
+ this.#negotiatedWsProtocol = normalizeWsProtocol(this.ws.protocol);
6023
+ }
5780
6024
  this.isActive = true;
5781
6025
  if (this.ws) {
5782
6026
  this.#flushOutboundQueue(this.ws);
@@ -5811,8 +6055,16 @@ var DbConnectionImpl = class {
5811
6055
  eventContext
5812
6056
  );
5813
6057
  }
5814
- async #processMessage(data) {
5815
- const serverMessage = ServerMessage.deserialize(new BinaryReader(data));
6058
+ #dispatchPendingCallbacks(callbacks) {
6059
+ stdbLogger(
6060
+ "trace",
6061
+ () => `Calling ${callbacks.length} triggered row callbacks`
6062
+ );
6063
+ for (const callback of callbacks) {
6064
+ callback.cb();
6065
+ }
6066
+ }
6067
+ #processServerMessage(serverMessage) {
5816
6068
  stdbLogger(
5817
6069
  "trace",
5818
6070
  () => `Processing server message: ${stringify(serverMessage)}`
@@ -5823,7 +6075,7 @@ var DbConnectionImpl = class {
5823
6075
  if (!this.token && serverMessage.value.token) {
5824
6076
  this.token = serverMessage.value.token;
5825
6077
  }
5826
- this.connectionId = serverMessage.value.connectionId;
6078
+ this.#setConnectionId(serverMessage.value.connectionId);
5827
6079
  this.#emitter.emit("connect", this, this.identity, this.token);
5828
6080
  break;
5829
6081
  }
@@ -5849,13 +6101,7 @@ var DbConnectionImpl = class {
5849
6101
  const callbacks = this.#applyTableUpdates(tableUpdates, eventContext);
5850
6102
  const { event: _, ...subscriptionEventContext } = eventContext;
5851
6103
  subscription.emitter.emit("applied", subscriptionEventContext);
5852
- stdbLogger(
5853
- "trace",
5854
- () => `Calling ${callbacks.length} triggered row callbacks`
5855
- );
5856
- for (const callback of callbacks) {
5857
- callback.cb();
5858
- }
6104
+ this.#dispatchPendingCallbacks(callbacks);
5859
6105
  break;
5860
6106
  }
5861
6107
  case "UnsubscribeApplied": {
@@ -5878,13 +6124,7 @@ var DbConnectionImpl = class {
5878
6124
  const { event: _, ...subscriptionEventContext } = eventContext;
5879
6125
  subscription.emitter.emit("end", subscriptionEventContext);
5880
6126
  this.#subscriptionManager.subscriptions.delete(querySetId);
5881
- stdbLogger(
5882
- "trace",
5883
- () => `Calling ${callbacks.length} triggered row callbacks`
5884
- );
5885
- for (const callback of callbacks) {
5886
- callback.cb();
5887
- }
6127
+ this.#dispatchPendingCallbacks(callbacks);
5888
6128
  break;
5889
6129
  }
5890
6130
  case "SubscriptionError": {
@@ -5932,13 +6172,7 @@ var DbConnectionImpl = class {
5932
6172
  eventContext,
5933
6173
  serverMessage.value
5934
6174
  );
5935
- stdbLogger(
5936
- "trace",
5937
- () => `Calling ${callbacks.length} triggered row callbacks`
5938
- );
5939
- for (const callback of callbacks) {
5940
- callback.cb();
5941
- }
6175
+ this.#dispatchPendingCallbacks(callbacks);
5942
6176
  break;
5943
6177
  }
5944
6178
  case "ReducerResult": {
@@ -5966,13 +6200,7 @@ var DbConnectionImpl = class {
5966
6200
  eventContext,
5967
6201
  result.value.transactionUpdate
5968
6202
  );
5969
- stdbLogger(
5970
- "trace",
5971
- () => `Calling ${callbacks.length} triggered row callbacks`
5972
- );
5973
- for (const callback of callbacks) {
5974
- callback.cb();
5975
- }
6203
+ this.#dispatchPendingCallbacks(callbacks);
5976
6204
  }
5977
6205
  this.#reducerCallInfo.delete(requestId);
5978
6206
  const cb = this.#reducerCallbacks.get(requestId);
@@ -5997,14 +6225,55 @@ var DbConnectionImpl = class {
5997
6225
  }
5998
6226
  }
5999
6227
  }
6228
+ #processV2Message(data) {
6229
+ const reader = this.#messageReader;
6230
+ reader.reset(data);
6231
+ this.#processServerMessage(ServerMessage.deserialize(reader));
6232
+ }
6233
+ #processMessage(data) {
6234
+ if (this.#negotiatedWsProtocol !== V3_WS_PROTOCOL) {
6235
+ this.#processV2Message(data);
6236
+ return;
6237
+ }
6238
+ const messageCount = forEachServerMessageV3(
6239
+ this.#messageReader,
6240
+ data,
6241
+ (serverMessage) => {
6242
+ this.#processServerMessage(serverMessage);
6243
+ }
6244
+ );
6245
+ stdbLogger(
6246
+ "trace",
6247
+ () => `Processing server v3 payload with ${messageCount} message(s)`
6248
+ );
6249
+ }
6000
6250
  /**
6001
6251
  * Handles WebSocket onMessage event.
6002
6252
  * @param wsMessage MessageEvent object.
6003
6253
  */
6004
6254
  #handleOnMessage(wsMessage) {
6005
- this.#messageQueue = this.#messageQueue.then(() => {
6006
- return this.#processMessage(wsMessage.data);
6007
- });
6255
+ this.#inboundQueue.push(wsMessage.data);
6256
+ if (this.#isDrainingInboundQueue) {
6257
+ return;
6258
+ }
6259
+ this.#isDrainingInboundQueue = true;
6260
+ try {
6261
+ while (this.#inboundQueueOffset < this.#inboundQueue.length) {
6262
+ const data = this.#inboundQueue[this.#inboundQueueOffset];
6263
+ this.#inboundQueueOffset += 1;
6264
+ if (data) {
6265
+ this.#processMessage(data);
6266
+ }
6267
+ }
6268
+ } finally {
6269
+ if (this.#inboundQueueOffset >= this.#inboundQueue.length) {
6270
+ this.#inboundQueue.length = 0;
6271
+ } else if (this.#inboundQueueOffset > 0) {
6272
+ this.#inboundQueue = this.#inboundQueue.slice(this.#inboundQueueOffset);
6273
+ }
6274
+ this.#inboundQueueOffset = 0;
6275
+ this.#isDrainingInboundQueue = false;
6276
+ }
6008
6277
  }
6009
6278
  /**
6010
6279
  * Call a reducer on your SpacetimeDB module.
@@ -6013,6 +6282,45 @@ var DbConnectionImpl = class {
6013
6282
  * @param argsSerializer The arguments to pass to the reducer
6014
6283
  */
6015
6284
  callReducer(reducerName, argsBuffer, reducerArgs) {
6285
+ const encodedReducerName = this.#reducerNameBytes[reducerName];
6286
+ if (encodedReducerName) {
6287
+ return this.#callReducerWithEncodedName(
6288
+ reducerName,
6289
+ encodedReducerName,
6290
+ argsBuffer,
6291
+ reducerArgs
6292
+ );
6293
+ }
6294
+ return this.#callReducerGeneric(reducerName, argsBuffer, reducerArgs);
6295
+ }
6296
+ #callReducerWithEncodedName(reducerName, encodedReducerName, argsBuffer, reducerArgs) {
6297
+ const { promise, resolve, reject } = Promise.withResolvers();
6298
+ const requestId = this.#getNextRequestId();
6299
+ this.#sendCallReducerMessage(requestId, encodedReducerName, argsBuffer);
6300
+ if (reducerArgs) {
6301
+ this.#reducerCallInfo.set(requestId, {
6302
+ name: reducerName,
6303
+ args: reducerArgs
6304
+ });
6305
+ }
6306
+ this.#reducerCallbacks.set(requestId, (result) => {
6307
+ if (result.tag === "Ok" || result.tag === "OkEmpty") {
6308
+ resolve();
6309
+ } else {
6310
+ if (result.tag === "Err") {
6311
+ const reader = new BinaryReader(result.value);
6312
+ const errorString = reader.readString();
6313
+ reject(new SenderError(errorString));
6314
+ } else if (result.tag === "InternalError") {
6315
+ reject(new InternalError(result.value));
6316
+ } else {
6317
+ reject(new Error("Unexpected reducer result"));
6318
+ }
6319
+ }
6320
+ });
6321
+ return promise;
6322
+ }
6323
+ #callReducerGeneric(reducerName, argsBuffer, reducerArgs) {
6016
6324
  const { promise, resolve, reject } = Promise.withResolvers();
6017
6325
  const requestId = this.#getNextRequestId();
6018
6326
  const message = ClientMessage.CallReducer({
@@ -6052,7 +6360,8 @@ var DbConnectionImpl = class {
6052
6360
  * @param params The arguments to pass to the reducer
6053
6361
  */
6054
6362
  callReducerWithParams(reducerName, _paramsType, params) {
6055
- const writer = new BinaryWriter(1024);
6363
+ const writer = this.#reducerArgsEncoder;
6364
+ writer.clear();
6056
6365
  this.#reducerArgsSerializers[reducerName].serialize(writer, params);
6057
6366
  const argsBuffer = writer.getBuffer();
6058
6367
  return this.callReducer(reducerName, argsBuffer, params);
@@ -6064,6 +6373,30 @@ var DbConnectionImpl = class {
6064
6373
  * @param argsBuffer The arguments to pass to the reducer
6065
6374
  */
6066
6375
  callProcedure(procedureName, argsBuffer) {
6376
+ const encodedProcedureName = this.#procedureNameBytes[procedureName];
6377
+ if (encodedProcedureName) {
6378
+ return this.#callProcedureWithEncodedName(
6379
+ procedureName,
6380
+ encodedProcedureName,
6381
+ argsBuffer
6382
+ );
6383
+ }
6384
+ return this.#callProcedureGeneric(procedureName, argsBuffer);
6385
+ }
6386
+ #callProcedureWithEncodedName(procedureName, encodedProcedureName, argsBuffer) {
6387
+ const { promise, resolve, reject } = Promise.withResolvers();
6388
+ const requestId = this.#getNextRequestId();
6389
+ this.#sendCallProcedureMessage(requestId, encodedProcedureName, argsBuffer);
6390
+ this.#procedureCallbacks.set(requestId, (result) => {
6391
+ if (result.tag === "Ok") {
6392
+ resolve(result.value);
6393
+ } else {
6394
+ reject(result.value);
6395
+ }
6396
+ });
6397
+ return promise;
6398
+ }
6399
+ #callProcedureGeneric(procedureName, argsBuffer) {
6067
6400
  const { promise, resolve, reject } = Promise.withResolvers();
6068
6401
  const requestId = this.#getNextRequestId();
6069
6402
  const message = ClientMessage.CallProcedure({
@@ -7004,7 +7337,7 @@ function table(opts, row, ..._) {
7004
7337
  increment: 1n
7005
7338
  });
7006
7339
  }
7007
- if (meta.defaultValue) {
7340
+ if (Object.prototype.hasOwnProperty.call(meta, "defaultValue")) {
7008
7341
  const writer = new BinaryWriter(16);
7009
7342
  builder.serialize(writer, meta.defaultValue);
7010
7343
  defaultValues.push({