spacetimedb 2.1.0 → 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.
- package/LICENSE.txt +2 -2
- package/dist/angular/index.cjs +7 -2
- package/dist/angular/index.cjs.map +1 -1
- package/dist/angular/index.mjs +7 -2
- package/dist/angular/index.mjs.map +1 -1
- package/dist/browser/angular/index.mjs +7 -2
- package/dist/browser/angular/index.mjs.map +1 -1
- package/dist/browser/react/index.mjs +57 -6
- package/dist/browser/react/index.mjs.map +1 -1
- package/dist/browser/svelte/index.mjs +7 -2
- package/dist/browser/svelte/index.mjs.map +1 -1
- package/dist/browser/vue/index.mjs +7 -2
- package/dist/browser/vue/index.mjs.map +1 -1
- package/dist/index.browser.mjs +459 -138
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.cjs +459 -138
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +459 -138
- package/dist/index.mjs.map +1 -1
- package/dist/lib/binary_reader.d.ts +1 -1
- package/dist/lib/binary_reader.d.ts.map +1 -1
- package/dist/lib/binary_writer.d.ts +2 -1
- package/dist/lib/binary_writer.d.ts.map +1 -1
- package/dist/lib/filter.d.ts +2 -1
- package/dist/lib/filter.d.ts.map +1 -1
- package/dist/lib/table.d.ts +6 -0
- package/dist/lib/table.d.ts.map +1 -1
- package/dist/min/index.browser.mjs +1 -1
- package/dist/min/index.browser.mjs.map +1 -1
- package/dist/min/react/index.mjs +1 -1
- package/dist/min/react/index.mjs.map +1 -1
- package/dist/min/sdk/index.browser.mjs +1 -1
- package/dist/min/sdk/index.browser.mjs.map +1 -1
- package/dist/react/index.cjs +57 -5
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.mjs +57 -6
- package/dist/react/index.mjs.map +1 -1
- package/dist/react/useProcedure.d.ts +4 -0
- package/dist/react/useProcedure.d.ts.map +1 -0
- package/dist/react/useTable.d.ts +2 -0
- package/dist/react/useTable.d.ts.map +1 -1
- package/dist/sdk/db_connection_builder.d.ts +3 -3
- package/dist/sdk/db_connection_builder.d.ts.map +1 -1
- package/dist/sdk/db_connection_impl.d.ts +3 -3
- package/dist/sdk/db_connection_impl.d.ts.map +1 -1
- package/dist/sdk/decompress.d.ts +1 -1
- package/dist/sdk/decompress.d.ts.map +1 -1
- package/dist/sdk/index.browser.mjs +459 -138
- package/dist/sdk/index.browser.mjs.map +1 -1
- package/dist/sdk/index.cjs +459 -138
- package/dist/sdk/index.cjs.map +1 -1
- package/dist/sdk/index.mjs +459 -138
- package/dist/sdk/index.mjs.map +1 -1
- package/dist/sdk/table_cache.d.ts +1 -0
- package/dist/sdk/table_cache.d.ts.map +1 -1
- package/dist/sdk/type_utils.d.ts +4 -1
- package/dist/sdk/type_utils.d.ts.map +1 -1
- package/dist/sdk/websocket_decompress_adapter.d.ts +5 -21
- package/dist/sdk/websocket_decompress_adapter.d.ts.map +1 -1
- package/dist/sdk/websocket_protocols.d.ts +6 -0
- package/dist/sdk/websocket_protocols.d.ts.map +1 -0
- package/dist/sdk/websocket_test_adapter.d.ts +14 -18
- package/dist/sdk/websocket_test_adapter.d.ts.map +1 -1
- package/dist/sdk/websocket_v3_frames.d.ts +9 -0
- package/dist/sdk/websocket_v3_frames.d.ts.map +1 -0
- package/dist/sdk/ws.d.ts +26 -1
- package/dist/sdk/ws.d.ts.map +1 -1
- package/dist/server/http_internal.d.ts.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.mjs +53 -6
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/runtime.d.ts +29 -2
- package/dist/server/runtime.d.ts.map +1 -1
- package/dist/svelte/index.cjs +7 -2
- package/dist/svelte/index.cjs.map +1 -1
- package/dist/svelte/index.mjs +7 -2
- package/dist/svelte/index.mjs.map +1 -1
- package/dist/tanstack/index.cjs +7 -2
- package/dist/tanstack/index.cjs.map +1 -1
- package/dist/tanstack/index.mjs +7 -2
- package/dist/tanstack/index.mjs.map +1 -1
- package/dist/vue/index.cjs +7 -2
- package/dist/vue/index.cjs.map +1 -1
- package/dist/vue/index.mjs +7 -2
- package/dist/vue/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/lib/binary_reader.ts +5 -2
- package/src/lib/binary_writer.ts +7 -1
- package/src/lib/filter.ts +12 -1
- package/src/lib/table.ts +9 -1
- package/src/react/index.ts +1 -0
- package/src/react/useProcedure.ts +60 -0
- package/src/react/useTable.ts +17 -2
- package/src/sdk/db_connection_builder.ts +16 -7
- package/src/sdk/db_connection_impl.ts +404 -89
- package/src/sdk/decompress.ts +7 -23
- package/src/sdk/table_cache.ts +5 -5
- package/src/sdk/type_utils.ts +10 -1
- package/src/sdk/websocket_decompress_adapter.ts +15 -77
- package/src/sdk/websocket_protocols.ts +25 -0
- package/src/sdk/websocket_test_adapter.ts +65 -29
- package/src/sdk/websocket_v3_frames.ts +126 -0
- package/src/sdk/ws.ts +81 -3
- package/src/server/http_internal.ts +10 -1
- package/src/server/index.ts +1 -1
- package/src/server/runtime.ts +39 -1
- package/src/server/sys.d.ts +4 -0
package/dist/sdk/index.cjs
CHANGED
|
@@ -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(
|
|
434
|
-
this.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);
|
|
@@ -4332,6 +4337,7 @@ var scalarCompare = (x, y) => {
|
|
|
4332
4337
|
return x < y ? -1 : 1;
|
|
4333
4338
|
};
|
|
4334
4339
|
var TableCacheImpl = class {
|
|
4340
|
+
hasPrimaryKey;
|
|
4335
4341
|
rows;
|
|
4336
4342
|
tableDef;
|
|
4337
4343
|
emitter;
|
|
@@ -4345,6 +4351,9 @@ var TableCacheImpl = class {
|
|
|
4345
4351
|
this.tableDef = tableDef;
|
|
4346
4352
|
this.rows = /* @__PURE__ */ new Map();
|
|
4347
4353
|
this.emitter = new EventEmitter();
|
|
4354
|
+
this.hasPrimaryKey = Object.values(this.tableDef.columns).some(
|
|
4355
|
+
(col) => col.columnMetadata.isPrimaryKey === true
|
|
4356
|
+
);
|
|
4348
4357
|
for (const idxDef of this.tableDef.resolvedIndexes) {
|
|
4349
4358
|
const index = this.#makeReadonlyIndex(this.tableDef, idxDef);
|
|
4350
4359
|
this[idxDef.name] = index;
|
|
@@ -4454,10 +4463,7 @@ var TableCacheImpl = class {
|
|
|
4454
4463
|
}
|
|
4455
4464
|
return pendingCallbacks;
|
|
4456
4465
|
}
|
|
4457
|
-
|
|
4458
|
-
(col) => col.columnMetadata.isPrimaryKey === true
|
|
4459
|
-
);
|
|
4460
|
-
if (hasPrimaryKey) {
|
|
4466
|
+
if (this.hasPrimaryKey) {
|
|
4461
4467
|
const insertMap = /* @__PURE__ */ new Map();
|
|
4462
4468
|
const deleteMap = /* @__PURE__ */ new Map();
|
|
4463
4469
|
for (const op of operations) {
|
|
@@ -4865,27 +4871,17 @@ async function decompress(buffer, type, chunkSize = 128 * 1024) {
|
|
|
4865
4871
|
});
|
|
4866
4872
|
const decompressionStream = new DecompressionStream(type);
|
|
4867
4873
|
const decompressedStream = readableStream.pipeThrough(decompressionStream);
|
|
4868
|
-
const reader = decompressedStream.getReader();
|
|
4869
4874
|
const chunks = [];
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
totalLength += result.value.length;
|
|
4875
|
-
}
|
|
4876
|
-
const decompressedArray = new Uint8Array(totalLength);
|
|
4877
|
-
let chunkOffset = 0;
|
|
4878
|
-
for (const chunk of chunks) {
|
|
4879
|
-
decompressedArray.set(chunk, chunkOffset);
|
|
4880
|
-
chunkOffset += chunk.length;
|
|
4881
|
-
}
|
|
4882
|
-
return decompressedArray;
|
|
4875
|
+
for await (const chunk of decompressedStream) {
|
|
4876
|
+
chunks.push(chunk);
|
|
4877
|
+
}
|
|
4878
|
+
return new Blob(chunks).bytes();
|
|
4883
4879
|
}
|
|
4884
4880
|
|
|
4885
4881
|
// src/sdk/ws.ts
|
|
4886
4882
|
async function resolveWS() {
|
|
4887
|
-
if (typeof
|
|
4888
|
-
return
|
|
4883
|
+
if (typeof WebSocket !== "undefined") {
|
|
4884
|
+
return WebSocket;
|
|
4889
4885
|
}
|
|
4890
4886
|
const dynamicImport = new Function("m", "return import(m)");
|
|
4891
4887
|
try {
|
|
@@ -4899,9 +4895,54 @@ async function resolveWS() {
|
|
|
4899
4895
|
throw err;
|
|
4900
4896
|
}
|
|
4901
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
|
+
}
|
|
4902
4940
|
|
|
4903
4941
|
// src/sdk/websocket_decompress_adapter.ts
|
|
4904
4942
|
var WebsocketDecompressAdapter = class _WebsocketDecompressAdapter {
|
|
4943
|
+
get protocol() {
|
|
4944
|
+
return this.#ws.protocol;
|
|
4945
|
+
}
|
|
4905
4946
|
set onclose(handler) {
|
|
4906
4947
|
this.#ws.onclose = handler;
|
|
4907
4948
|
}
|
|
@@ -4925,9 +4966,7 @@ var WebsocketDecompressAdapter = class _WebsocketDecompressAdapter {
|
|
|
4925
4966
|
case 0:
|
|
4926
4967
|
return data;
|
|
4927
4968
|
case 1:
|
|
4928
|
-
|
|
4929
|
-
"Brotli Compression not supported. Please use gzip or none compression in withCompression method on DbConnection."
|
|
4930
|
-
);
|
|
4969
|
+
return await decompress(data, "brotli");
|
|
4931
4970
|
case 2:
|
|
4932
4971
|
return await decompress(data, "gzip");
|
|
4933
4972
|
default:
|
|
@@ -4943,51 +4982,10 @@ var WebsocketDecompressAdapter = class _WebsocketDecompressAdapter {
|
|
|
4943
4982
|
this.#ws.close();
|
|
4944
4983
|
}
|
|
4945
4984
|
constructor(ws) {
|
|
4946
|
-
ws.binaryType = "arraybuffer";
|
|
4947
4985
|
this.#ws = ws;
|
|
4948
4986
|
}
|
|
4949
|
-
static async
|
|
4950
|
-
|
|
4951
|
-
nameOrAddress,
|
|
4952
|
-
wsProtocol,
|
|
4953
|
-
authToken,
|
|
4954
|
-
compression,
|
|
4955
|
-
lightMode,
|
|
4956
|
-
confirmedReads
|
|
4957
|
-
}) {
|
|
4958
|
-
const headers = new Headers();
|
|
4959
|
-
const WS = await resolveWS();
|
|
4960
|
-
let temporaryAuthToken = void 0;
|
|
4961
|
-
if (authToken) {
|
|
4962
|
-
headers.set("Authorization", `Bearer ${authToken}`);
|
|
4963
|
-
const tokenUrl = new URL("v1/identity/websocket-token", url);
|
|
4964
|
-
tokenUrl.protocol = url.protocol === "wss:" ? "https:" : "http:";
|
|
4965
|
-
const response = await fetch(tokenUrl, { method: "POST", headers });
|
|
4966
|
-
if (response.ok) {
|
|
4967
|
-
const { token } = await response.json();
|
|
4968
|
-
temporaryAuthToken = token;
|
|
4969
|
-
} else {
|
|
4970
|
-
return Promise.reject(
|
|
4971
|
-
new Error(`Failed to verify token: ${response.statusText}`)
|
|
4972
|
-
);
|
|
4973
|
-
}
|
|
4974
|
-
}
|
|
4975
|
-
const databaseUrl = new URL(`v1/database/${nameOrAddress}/subscribe`, url);
|
|
4976
|
-
if (temporaryAuthToken) {
|
|
4977
|
-
databaseUrl.searchParams.set("token", temporaryAuthToken);
|
|
4978
|
-
}
|
|
4979
|
-
databaseUrl.searchParams.set(
|
|
4980
|
-
"compression",
|
|
4981
|
-
compression === "gzip" ? "Gzip" : "None"
|
|
4982
|
-
);
|
|
4983
|
-
if (lightMode) {
|
|
4984
|
-
databaseUrl.searchParams.set("light", "true");
|
|
4985
|
-
}
|
|
4986
|
-
if (confirmedReads !== void 0) {
|
|
4987
|
-
databaseUrl.searchParams.set("confirmed", confirmedReads.toString());
|
|
4988
|
-
}
|
|
4989
|
-
const ws = new WS(databaseUrl.toString(), wsProtocol);
|
|
4990
|
-
return new _WebsocketDecompressAdapter(ws);
|
|
4987
|
+
static async openWebSocket(args) {
|
|
4988
|
+
return new _WebsocketDecompressAdapter(await openWebSocket(args));
|
|
4991
4989
|
}
|
|
4992
4990
|
};
|
|
4993
4991
|
|
|
@@ -5004,7 +5002,7 @@ var DbConnectionBuilder = class {
|
|
|
5004
5002
|
constructor(remoteModule, dbConnectionCtor) {
|
|
5005
5003
|
this.remoteModule = remoteModule;
|
|
5006
5004
|
this.dbConnectionCtor = dbConnectionCtor;
|
|
5007
|
-
this.#createWSFn = WebsocketDecompressAdapter.
|
|
5005
|
+
this.#createWSFn = WebsocketDecompressAdapter.openWebSocket;
|
|
5008
5006
|
}
|
|
5009
5007
|
#uri;
|
|
5010
5008
|
#nameOrAddress;
|
|
@@ -5059,6 +5057,16 @@ var DbConnectionBuilder = class {
|
|
|
5059
5057
|
* @param compression The compression algorithm to use for the connection.
|
|
5060
5058
|
*/
|
|
5061
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
|
+
}
|
|
5062
5070
|
this.#compression = compression;
|
|
5063
5071
|
return this;
|
|
5064
5072
|
}
|
|
@@ -5422,6 +5430,100 @@ var SubscriptionHandleImpl = class {
|
|
|
5422
5430
|
return this.#activeState;
|
|
5423
5431
|
}
|
|
5424
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;
|
|
5425
5527
|
var DbConnectionImpl = class {
|
|
5426
5528
|
/**
|
|
5427
5529
|
* Whether or not the connection is active.
|
|
@@ -5456,22 +5558,35 @@ var DbConnectionImpl = class {
|
|
|
5456
5558
|
* The `ConnectionId` of the connection to to the database.
|
|
5457
5559
|
*/
|
|
5458
5560
|
connectionId = ConnectionId.random();
|
|
5561
|
+
#connectionIdHex = this.connectionId.toHexString();
|
|
5459
5562
|
// These fields are meant to be strictly private.
|
|
5460
5563
|
#queryId = 0;
|
|
5461
5564
|
#requestId = 0;
|
|
5462
5565
|
#eventId = 0;
|
|
5463
5566
|
#emitter;
|
|
5464
|
-
#
|
|
5567
|
+
#inboundQueue = [];
|
|
5568
|
+
#inboundQueueOffset = 0;
|
|
5569
|
+
#isDrainingInboundQueue = false;
|
|
5465
5570
|
#outboundQueue = [];
|
|
5571
|
+
#isOutboundFlushScheduled = false;
|
|
5572
|
+
#negotiatedWsProtocol = V2_WS_PROTOCOL;
|
|
5466
5573
|
#subscriptionManager = new SubscriptionManager();
|
|
5467
5574
|
#remoteModule;
|
|
5468
5575
|
#reducerCallbacks = /* @__PURE__ */ new Map();
|
|
5469
5576
|
#reducerCallInfo = /* @__PURE__ */ new Map();
|
|
5470
5577
|
#procedureCallbacks = /* @__PURE__ */ new Map();
|
|
5471
5578
|
#rowDeserializers;
|
|
5579
|
+
#rowIdMetadata;
|
|
5472
5580
|
#reducerArgsSerializers;
|
|
5473
5581
|
#procedureSerializers;
|
|
5582
|
+
#reducerNameBytes;
|
|
5583
|
+
#procedureNameBytes;
|
|
5474
5584
|
#sourceNameToTableDef;
|
|
5585
|
+
#messageReader = new BinaryReader(new Uint8Array());
|
|
5586
|
+
#rowListReader = new BinaryReader(new Uint8Array());
|
|
5587
|
+
#clientFrameEncoder = new BinaryWriter(1024);
|
|
5588
|
+
#boundSubscriptionBuilder;
|
|
5589
|
+
#boundDisconnect;
|
|
5475
5590
|
// These fields are not part of the public API, but in a pinch you
|
|
5476
5591
|
// could use JavaScript to access them by bypassing TypeScript's
|
|
5477
5592
|
// private fields.
|
|
@@ -5500,22 +5615,35 @@ var DbConnectionImpl = class {
|
|
|
5500
5615
|
this.token = token;
|
|
5501
5616
|
this.#remoteModule = remoteModule;
|
|
5502
5617
|
this.#emitter = emitter;
|
|
5618
|
+
this.#boundSubscriptionBuilder = this.subscriptionBuilder.bind(this);
|
|
5619
|
+
this.#boundDisconnect = this.disconnect.bind(this);
|
|
5503
5620
|
this.#rowDeserializers = /* @__PURE__ */ Object.create(null);
|
|
5621
|
+
this.#rowIdMetadata = /* @__PURE__ */ Object.create(null);
|
|
5504
5622
|
this.#sourceNameToTableDef = /* @__PURE__ */ Object.create(null);
|
|
5505
5623
|
for (const table2 of Object.values(remoteModule.tables)) {
|
|
5506
5624
|
this.#rowDeserializers[table2.sourceName] = ProductType.makeDeserializer(
|
|
5507
5625
|
table2.rowType
|
|
5508
5626
|
);
|
|
5509
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
|
+
} : {};
|
|
5510
5635
|
}
|
|
5511
5636
|
this.#reducerArgsSerializers = /* @__PURE__ */ Object.create(null);
|
|
5637
|
+
this.#reducerNameBytes = /* @__PURE__ */ Object.create(null);
|
|
5512
5638
|
for (const reducer of remoteModule.reducers) {
|
|
5513
5639
|
this.#reducerArgsSerializers[reducer.name] = {
|
|
5514
5640
|
serialize: ProductType.makeSerializer(reducer.paramsType),
|
|
5515
5641
|
deserialize: ProductType.makeDeserializer(reducer.paramsType)
|
|
5516
5642
|
};
|
|
5643
|
+
this.#reducerNameBytes[reducer.name] = TEXT_ENCODER.encode(reducer.name);
|
|
5517
5644
|
}
|
|
5518
5645
|
this.#procedureSerializers = /* @__PURE__ */ Object.create(null);
|
|
5646
|
+
this.#procedureNameBytes = /* @__PURE__ */ Object.create(null);
|
|
5519
5647
|
for (const procedure of remoteModule.procedures) {
|
|
5520
5648
|
this.#procedureSerializers[procedure.name] = {
|
|
5521
5649
|
serializeArgs: ProductType.makeSerializer(
|
|
@@ -5525,9 +5653,11 @@ var DbConnectionImpl = class {
|
|
|
5525
5653
|
procedure.returnType.algebraicType
|
|
5526
5654
|
)
|
|
5527
5655
|
};
|
|
5656
|
+
this.#procedureNameBytes[procedure.name] = TEXT_ENCODER.encode(
|
|
5657
|
+
procedure.name
|
|
5658
|
+
);
|
|
5528
5659
|
}
|
|
5529
|
-
|
|
5530
|
-
url.searchParams.set("connection_id", connectionId);
|
|
5660
|
+
url.searchParams.set("connection_id", this.#connectionIdHex);
|
|
5531
5661
|
this.clientCache = new ClientCache();
|
|
5532
5662
|
this.db = this.#makeDbView();
|
|
5533
5663
|
this.reducers = this.#makeReducers(remoteModule);
|
|
@@ -5535,7 +5665,7 @@ var DbConnectionImpl = class {
|
|
|
5535
5665
|
this.wsPromise = createWSFn({
|
|
5536
5666
|
url,
|
|
5537
5667
|
nameOrAddress,
|
|
5538
|
-
wsProtocol:
|
|
5668
|
+
wsProtocol: [...PREFERRED_WS_PROTOCOLS],
|
|
5539
5669
|
authToken: token,
|
|
5540
5670
|
compression,
|
|
5541
5671
|
lightMode,
|
|
@@ -5579,16 +5709,22 @@ var DbConnectionImpl = class {
|
|
|
5579
5709
|
}
|
|
5580
5710
|
#makeReducers(def) {
|
|
5581
5711
|
const out = {};
|
|
5582
|
-
const writer = new BinaryWriter(1024);
|
|
5583
5712
|
for (const reducer of def.reducers) {
|
|
5584
5713
|
const reducerName = reducer.name;
|
|
5714
|
+
const encodedReducerName = this.#reducerNameBytes[reducerName];
|
|
5585
5715
|
const key = reducer.accessorName;
|
|
5586
5716
|
const { serialize: serializeArgs } = this.#reducerArgsSerializers[reducerName];
|
|
5587
5717
|
out[key] = (params) => {
|
|
5718
|
+
const writer = this.#reducerArgsEncoder;
|
|
5588
5719
|
writer.clear();
|
|
5589
5720
|
serializeArgs(writer, params);
|
|
5590
5721
|
const argsBuffer = writer.getBuffer();
|
|
5591
|
-
return this
|
|
5722
|
+
return this.#callReducerWithEncodedName(
|
|
5723
|
+
reducerName,
|
|
5724
|
+
encodedReducerName,
|
|
5725
|
+
argsBuffer,
|
|
5726
|
+
params
|
|
5727
|
+
);
|
|
5592
5728
|
};
|
|
5593
5729
|
}
|
|
5594
5730
|
return out;
|
|
@@ -5598,13 +5734,18 @@ var DbConnectionImpl = class {
|
|
|
5598
5734
|
const writer = new BinaryWriter(1024);
|
|
5599
5735
|
for (const procedure of def.procedures) {
|
|
5600
5736
|
const procedureName = procedure.name;
|
|
5737
|
+
const encodedProcedureName = this.#procedureNameBytes[procedureName];
|
|
5601
5738
|
const key = procedure.accessorName;
|
|
5602
5739
|
const { serializeArgs, deserializeReturn } = this.#procedureSerializers[procedureName];
|
|
5603
5740
|
out[key] = (params) => {
|
|
5604
5741
|
writer.clear();
|
|
5605
5742
|
serializeArgs(writer, params);
|
|
5606
5743
|
const argsBuffer = writer.getBuffer();
|
|
5607
|
-
return this
|
|
5744
|
+
return this.#callProcedureWithEncodedName(
|
|
5745
|
+
procedureName,
|
|
5746
|
+
encodedProcedureName,
|
|
5747
|
+
argsBuffer
|
|
5748
|
+
).then((returnBuf) => {
|
|
5608
5749
|
return deserializeReturn(new BinaryReader(returnBuf));
|
|
5609
5750
|
});
|
|
5610
5751
|
};
|
|
@@ -5616,8 +5757,8 @@ var DbConnectionImpl = class {
|
|
|
5616
5757
|
db: this.db,
|
|
5617
5758
|
reducers: this.reducers,
|
|
5618
5759
|
isActive: this.isActive,
|
|
5619
|
-
subscriptionBuilder: this
|
|
5620
|
-
disconnect: this
|
|
5760
|
+
subscriptionBuilder: this.#boundSubscriptionBuilder,
|
|
5761
|
+
disconnect: this.#boundDisconnect,
|
|
5621
5762
|
event
|
|
5622
5763
|
};
|
|
5623
5764
|
}
|
|
@@ -5662,21 +5803,16 @@ var DbConnectionImpl = class {
|
|
|
5662
5803
|
}
|
|
5663
5804
|
#parseRowList(type, tableName, rowList) {
|
|
5664
5805
|
const buffer = rowList.rowsData;
|
|
5665
|
-
const reader =
|
|
5806
|
+
const reader = this.#rowListReader;
|
|
5807
|
+
reader.reset(buffer);
|
|
5666
5808
|
const rows = [];
|
|
5667
5809
|
const deserializeRow = this.#rowDeserializers[tableName];
|
|
5668
|
-
const
|
|
5669
|
-
const columnsArray = Object.entries(table2.columns);
|
|
5670
|
-
const primaryKeyColumnEntry = columnsArray.find(
|
|
5671
|
-
(col) => col[1].columnMetadata.isPrimaryKey
|
|
5672
|
-
);
|
|
5810
|
+
const { primaryKeyColName, primaryKeyColType } = this.#rowIdMetadata[tableName];
|
|
5673
5811
|
let previousOffset = 0;
|
|
5674
5812
|
while (reader.remaining > 0) {
|
|
5675
5813
|
const row = deserializeRow(reader);
|
|
5676
5814
|
let rowId = void 0;
|
|
5677
|
-
if (
|
|
5678
|
-
const primaryKeyColName = primaryKeyColumnEntry[0];
|
|
5679
|
-
const primaryKeyColType = primaryKeyColumnEntry[1].typeBuilder.algebraicType;
|
|
5815
|
+
if (primaryKeyColName !== void 0 && primaryKeyColType !== void 0) {
|
|
5680
5816
|
rowId = AlgebraicType.intoMapKey(
|
|
5681
5817
|
primaryKeyColType,
|
|
5682
5818
|
row[primaryKeyColName]
|
|
@@ -5757,40 +5893,136 @@ var DbConnectionImpl = class {
|
|
|
5757
5893
|
return this.#mergeTableUpdates(updates);
|
|
5758
5894
|
}
|
|
5759
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) {
|
|
5760
5903
|
const pending = this.#outboundQueue.splice(0);
|
|
5761
5904
|
for (const message of pending) {
|
|
5762
5905
|
wsResolved.send(message);
|
|
5763
5906
|
}
|
|
5764
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);
|
|
5765
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
|
+
}
|
|
5766
5972
|
#sendMessage(message) {
|
|
5767
5973
|
const writer = this.#clientMessageEncoder;
|
|
5768
5974
|
writer.clear();
|
|
5769
5975
|
ClientMessage.serialize(writer, message);
|
|
5770
5976
|
const encoded = writer.getBuffer();
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
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();
|
|
5785
6014
|
}
|
|
5786
6015
|
#nextEventId() {
|
|
5787
6016
|
this.#eventId += 1;
|
|
5788
|
-
return `${this
|
|
6017
|
+
return `${this.#connectionIdHex}:${this.#eventId}`;
|
|
5789
6018
|
}
|
|
5790
6019
|
/**
|
|
5791
6020
|
* Handles WebSocket onOpen event.
|
|
5792
6021
|
*/
|
|
5793
6022
|
#handleOnOpen() {
|
|
6023
|
+
if (this.ws) {
|
|
6024
|
+
this.#negotiatedWsProtocol = normalizeWsProtocol(this.ws.protocol);
|
|
6025
|
+
}
|
|
5794
6026
|
this.isActive = true;
|
|
5795
6027
|
if (this.ws) {
|
|
5796
6028
|
this.#flushOutboundQueue(this.ws);
|
|
@@ -5825,8 +6057,16 @@ var DbConnectionImpl = class {
|
|
|
5825
6057
|
eventContext
|
|
5826
6058
|
);
|
|
5827
6059
|
}
|
|
5828
|
-
|
|
5829
|
-
|
|
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) {
|
|
5830
6070
|
stdbLogger(
|
|
5831
6071
|
"trace",
|
|
5832
6072
|
() => `Processing server message: ${stringify(serverMessage)}`
|
|
@@ -5837,7 +6077,7 @@ var DbConnectionImpl = class {
|
|
|
5837
6077
|
if (!this.token && serverMessage.value.token) {
|
|
5838
6078
|
this.token = serverMessage.value.token;
|
|
5839
6079
|
}
|
|
5840
|
-
this
|
|
6080
|
+
this.#setConnectionId(serverMessage.value.connectionId);
|
|
5841
6081
|
this.#emitter.emit("connect", this, this.identity, this.token);
|
|
5842
6082
|
break;
|
|
5843
6083
|
}
|
|
@@ -5863,13 +6103,7 @@ var DbConnectionImpl = class {
|
|
|
5863
6103
|
const callbacks = this.#applyTableUpdates(tableUpdates, eventContext);
|
|
5864
6104
|
const { event: _, ...subscriptionEventContext } = eventContext;
|
|
5865
6105
|
subscription.emitter.emit("applied", subscriptionEventContext);
|
|
5866
|
-
|
|
5867
|
-
"trace",
|
|
5868
|
-
() => `Calling ${callbacks.length} triggered row callbacks`
|
|
5869
|
-
);
|
|
5870
|
-
for (const callback of callbacks) {
|
|
5871
|
-
callback.cb();
|
|
5872
|
-
}
|
|
6106
|
+
this.#dispatchPendingCallbacks(callbacks);
|
|
5873
6107
|
break;
|
|
5874
6108
|
}
|
|
5875
6109
|
case "UnsubscribeApplied": {
|
|
@@ -5892,13 +6126,7 @@ var DbConnectionImpl = class {
|
|
|
5892
6126
|
const { event: _, ...subscriptionEventContext } = eventContext;
|
|
5893
6127
|
subscription.emitter.emit("end", subscriptionEventContext);
|
|
5894
6128
|
this.#subscriptionManager.subscriptions.delete(querySetId);
|
|
5895
|
-
|
|
5896
|
-
"trace",
|
|
5897
|
-
() => `Calling ${callbacks.length} triggered row callbacks`
|
|
5898
|
-
);
|
|
5899
|
-
for (const callback of callbacks) {
|
|
5900
|
-
callback.cb();
|
|
5901
|
-
}
|
|
6129
|
+
this.#dispatchPendingCallbacks(callbacks);
|
|
5902
6130
|
break;
|
|
5903
6131
|
}
|
|
5904
6132
|
case "SubscriptionError": {
|
|
@@ -5946,13 +6174,7 @@ var DbConnectionImpl = class {
|
|
|
5946
6174
|
eventContext,
|
|
5947
6175
|
serverMessage.value
|
|
5948
6176
|
);
|
|
5949
|
-
|
|
5950
|
-
"trace",
|
|
5951
|
-
() => `Calling ${callbacks.length} triggered row callbacks`
|
|
5952
|
-
);
|
|
5953
|
-
for (const callback of callbacks) {
|
|
5954
|
-
callback.cb();
|
|
5955
|
-
}
|
|
6177
|
+
this.#dispatchPendingCallbacks(callbacks);
|
|
5956
6178
|
break;
|
|
5957
6179
|
}
|
|
5958
6180
|
case "ReducerResult": {
|
|
@@ -5980,13 +6202,7 @@ var DbConnectionImpl = class {
|
|
|
5980
6202
|
eventContext,
|
|
5981
6203
|
result.value.transactionUpdate
|
|
5982
6204
|
);
|
|
5983
|
-
|
|
5984
|
-
"trace",
|
|
5985
|
-
() => `Calling ${callbacks.length} triggered row callbacks`
|
|
5986
|
-
);
|
|
5987
|
-
for (const callback of callbacks) {
|
|
5988
|
-
callback.cb();
|
|
5989
|
-
}
|
|
6205
|
+
this.#dispatchPendingCallbacks(callbacks);
|
|
5990
6206
|
}
|
|
5991
6207
|
this.#reducerCallInfo.delete(requestId);
|
|
5992
6208
|
const cb = this.#reducerCallbacks.get(requestId);
|
|
@@ -6011,14 +6227,55 @@ var DbConnectionImpl = class {
|
|
|
6011
6227
|
}
|
|
6012
6228
|
}
|
|
6013
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
|
+
}
|
|
6014
6252
|
/**
|
|
6015
6253
|
* Handles WebSocket onMessage event.
|
|
6016
6254
|
* @param wsMessage MessageEvent object.
|
|
6017
6255
|
*/
|
|
6018
6256
|
#handleOnMessage(wsMessage) {
|
|
6019
|
-
this.#
|
|
6020
|
-
|
|
6021
|
-
|
|
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
|
+
}
|
|
6022
6279
|
}
|
|
6023
6280
|
/**
|
|
6024
6281
|
* Call a reducer on your SpacetimeDB module.
|
|
@@ -6027,6 +6284,45 @@ var DbConnectionImpl = class {
|
|
|
6027
6284
|
* @param argsSerializer The arguments to pass to the reducer
|
|
6028
6285
|
*/
|
|
6029
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) {
|
|
6030
6326
|
const { promise, resolve, reject } = Promise.withResolvers();
|
|
6031
6327
|
const requestId = this.#getNextRequestId();
|
|
6032
6328
|
const message = ClientMessage.CallReducer({
|
|
@@ -6066,7 +6362,8 @@ var DbConnectionImpl = class {
|
|
|
6066
6362
|
* @param params The arguments to pass to the reducer
|
|
6067
6363
|
*/
|
|
6068
6364
|
callReducerWithParams(reducerName, _paramsType, params) {
|
|
6069
|
-
const writer =
|
|
6365
|
+
const writer = this.#reducerArgsEncoder;
|
|
6366
|
+
writer.clear();
|
|
6070
6367
|
this.#reducerArgsSerializers[reducerName].serialize(writer, params);
|
|
6071
6368
|
const argsBuffer = writer.getBuffer();
|
|
6072
6369
|
return this.callReducer(reducerName, argsBuffer, params);
|
|
@@ -6078,6 +6375,30 @@ var DbConnectionImpl = class {
|
|
|
6078
6375
|
* @param argsBuffer The arguments to pass to the reducer
|
|
6079
6376
|
*/
|
|
6080
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) {
|
|
6081
6402
|
const { promise, resolve, reject } = Promise.withResolvers();
|
|
6082
6403
|
const requestId = this.#getNextRequestId();
|
|
6083
6404
|
const message = ClientMessage.CallProcedure({
|
|
@@ -7018,7 +7339,7 @@ function table(opts, row, ..._) {
|
|
|
7018
7339
|
increment: 1n
|
|
7019
7340
|
});
|
|
7020
7341
|
}
|
|
7021
|
-
if (meta
|
|
7342
|
+
if (Object.prototype.hasOwnProperty.call(meta, "defaultValue")) {
|
|
7022
7343
|
const writer = new BinaryWriter(16);
|
|
7023
7344
|
builder.serialize(writer, meta.defaultValue);
|
|
7024
7345
|
defaultValues.push({
|