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