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/index.browser.mjs
CHANGED
|
@@ -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(
|
|
432
|
-
this.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);
|
|
@@ -4465,6 +4470,7 @@ var scalarCompare = (x, y) => {
|
|
|
4465
4470
|
return x < y ? -1 : 1;
|
|
4466
4471
|
};
|
|
4467
4472
|
var TableCacheImpl = class {
|
|
4473
|
+
hasPrimaryKey;
|
|
4468
4474
|
rows;
|
|
4469
4475
|
tableDef;
|
|
4470
4476
|
emitter;
|
|
@@ -4478,6 +4484,9 @@ var TableCacheImpl = class {
|
|
|
4478
4484
|
this.tableDef = tableDef;
|
|
4479
4485
|
this.rows = /* @__PURE__ */ new Map();
|
|
4480
4486
|
this.emitter = new EventEmitter();
|
|
4487
|
+
this.hasPrimaryKey = Object.values(this.tableDef.columns).some(
|
|
4488
|
+
(col) => col.columnMetadata.isPrimaryKey === true
|
|
4489
|
+
);
|
|
4481
4490
|
for (const idxDef of this.tableDef.resolvedIndexes) {
|
|
4482
4491
|
const index = this.#makeReadonlyIndex(this.tableDef, idxDef);
|
|
4483
4492
|
this[idxDef.name] = index;
|
|
@@ -4587,10 +4596,7 @@ var TableCacheImpl = class {
|
|
|
4587
4596
|
}
|
|
4588
4597
|
return pendingCallbacks;
|
|
4589
4598
|
}
|
|
4590
|
-
|
|
4591
|
-
(col) => col.columnMetadata.isPrimaryKey === true
|
|
4592
|
-
);
|
|
4593
|
-
if (hasPrimaryKey) {
|
|
4599
|
+
if (this.hasPrimaryKey) {
|
|
4594
4600
|
const insertMap = /* @__PURE__ */ new Map();
|
|
4595
4601
|
const deleteMap = /* @__PURE__ */ new Map();
|
|
4596
4602
|
for (const op of operations) {
|
|
@@ -4998,27 +5004,17 @@ async function decompress(buffer, type, chunkSize = 128 * 1024) {
|
|
|
4998
5004
|
});
|
|
4999
5005
|
const decompressionStream = new DecompressionStream(type);
|
|
5000
5006
|
const decompressedStream = readableStream.pipeThrough(decompressionStream);
|
|
5001
|
-
const reader = decompressedStream.getReader();
|
|
5002
5007
|
const chunks = [];
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
totalLength += result.value.length;
|
|
5008
|
-
}
|
|
5009
|
-
const decompressedArray = new Uint8Array(totalLength);
|
|
5010
|
-
let chunkOffset = 0;
|
|
5011
|
-
for (const chunk of chunks) {
|
|
5012
|
-
decompressedArray.set(chunk, chunkOffset);
|
|
5013
|
-
chunkOffset += chunk.length;
|
|
5014
|
-
}
|
|
5015
|
-
return decompressedArray;
|
|
5008
|
+
for await (const chunk of decompressedStream) {
|
|
5009
|
+
chunks.push(chunk);
|
|
5010
|
+
}
|
|
5011
|
+
return new Blob(chunks).bytes();
|
|
5016
5012
|
}
|
|
5017
5013
|
|
|
5018
5014
|
// src/sdk/ws.ts
|
|
5019
5015
|
async function resolveWS() {
|
|
5020
|
-
if (typeof
|
|
5021
|
-
return
|
|
5016
|
+
if (typeof WebSocket !== "undefined") {
|
|
5017
|
+
return WebSocket;
|
|
5022
5018
|
}
|
|
5023
5019
|
const dynamicImport = new Function("m", "return import(m)");
|
|
5024
5020
|
try {
|
|
@@ -5032,9 +5028,54 @@ async function resolveWS() {
|
|
|
5032
5028
|
throw err;
|
|
5033
5029
|
}
|
|
5034
5030
|
}
|
|
5031
|
+
async function openWebSocket({
|
|
5032
|
+
url,
|
|
5033
|
+
nameOrAddress,
|
|
5034
|
+
wsProtocol,
|
|
5035
|
+
authToken,
|
|
5036
|
+
compression,
|
|
5037
|
+
lightMode,
|
|
5038
|
+
confirmedReads
|
|
5039
|
+
}) {
|
|
5040
|
+
const headers = new Headers();
|
|
5041
|
+
const WS = await resolveWS();
|
|
5042
|
+
let temporaryAuthToken;
|
|
5043
|
+
if (authToken) {
|
|
5044
|
+
headers.set("Authorization", `Bearer ${authToken}`);
|
|
5045
|
+
const tokenUrl = new URL("v1/identity/websocket-token", url);
|
|
5046
|
+
tokenUrl.protocol = url.protocol === "wss:" ? "https:" : "http:";
|
|
5047
|
+
const response = await fetch(tokenUrl, { method: "POST", headers });
|
|
5048
|
+
if (response.ok) {
|
|
5049
|
+
const { token } = await response.json();
|
|
5050
|
+
temporaryAuthToken = token;
|
|
5051
|
+
} else {
|
|
5052
|
+
throw new Error(`Failed to verify token: ${response.statusText}`);
|
|
5053
|
+
}
|
|
5054
|
+
}
|
|
5055
|
+
const databaseUrl = new URL(`v1/database/${nameOrAddress}/subscribe`, url);
|
|
5056
|
+
if (temporaryAuthToken) {
|
|
5057
|
+
databaseUrl.searchParams.set("token", temporaryAuthToken);
|
|
5058
|
+
}
|
|
5059
|
+
databaseUrl.searchParams.set(
|
|
5060
|
+
"compression",
|
|
5061
|
+
{ gzip: "Gzip", brotli: "Brotli", none: "None" }[compression] ?? "None"
|
|
5062
|
+
);
|
|
5063
|
+
if (lightMode) {
|
|
5064
|
+
databaseUrl.searchParams.set("light", "true");
|
|
5065
|
+
}
|
|
5066
|
+
if (confirmedReads !== void 0) {
|
|
5067
|
+
databaseUrl.searchParams.set("confirmed", confirmedReads.toString());
|
|
5068
|
+
}
|
|
5069
|
+
const ws = new WS(databaseUrl.toString(), wsProtocol);
|
|
5070
|
+
ws.binaryType = "arraybuffer";
|
|
5071
|
+
return ws;
|
|
5072
|
+
}
|
|
5035
5073
|
|
|
5036
5074
|
// src/sdk/websocket_decompress_adapter.ts
|
|
5037
5075
|
var WebsocketDecompressAdapter = class _WebsocketDecompressAdapter {
|
|
5076
|
+
get protocol() {
|
|
5077
|
+
return this.#ws.protocol;
|
|
5078
|
+
}
|
|
5038
5079
|
set onclose(handler) {
|
|
5039
5080
|
this.#ws.onclose = handler;
|
|
5040
5081
|
}
|
|
@@ -5058,9 +5099,7 @@ var WebsocketDecompressAdapter = class _WebsocketDecompressAdapter {
|
|
|
5058
5099
|
case 0:
|
|
5059
5100
|
return data;
|
|
5060
5101
|
case 1:
|
|
5061
|
-
|
|
5062
|
-
"Brotli Compression not supported. Please use gzip or none compression in withCompression method on DbConnection."
|
|
5063
|
-
);
|
|
5102
|
+
return await decompress(data, "brotli");
|
|
5064
5103
|
case 2:
|
|
5065
5104
|
return await decompress(data, "gzip");
|
|
5066
5105
|
default:
|
|
@@ -5076,51 +5115,10 @@ var WebsocketDecompressAdapter = class _WebsocketDecompressAdapter {
|
|
|
5076
5115
|
this.#ws.close();
|
|
5077
5116
|
}
|
|
5078
5117
|
constructor(ws) {
|
|
5079
|
-
ws.binaryType = "arraybuffer";
|
|
5080
5118
|
this.#ws = ws;
|
|
5081
5119
|
}
|
|
5082
|
-
static async
|
|
5083
|
-
|
|
5084
|
-
nameOrAddress,
|
|
5085
|
-
wsProtocol,
|
|
5086
|
-
authToken,
|
|
5087
|
-
compression,
|
|
5088
|
-
lightMode,
|
|
5089
|
-
confirmedReads
|
|
5090
|
-
}) {
|
|
5091
|
-
const headers = new Headers();
|
|
5092
|
-
const WS = await resolveWS();
|
|
5093
|
-
let temporaryAuthToken = void 0;
|
|
5094
|
-
if (authToken) {
|
|
5095
|
-
headers.set("Authorization", `Bearer ${authToken}`);
|
|
5096
|
-
const tokenUrl = new URL("v1/identity/websocket-token", url);
|
|
5097
|
-
tokenUrl.protocol = url.protocol === "wss:" ? "https:" : "http:";
|
|
5098
|
-
const response = await fetch(tokenUrl, { method: "POST", headers });
|
|
5099
|
-
if (response.ok) {
|
|
5100
|
-
const { token } = await response.json();
|
|
5101
|
-
temporaryAuthToken = token;
|
|
5102
|
-
} else {
|
|
5103
|
-
return Promise.reject(
|
|
5104
|
-
new Error(`Failed to verify token: ${response.statusText}`)
|
|
5105
|
-
);
|
|
5106
|
-
}
|
|
5107
|
-
}
|
|
5108
|
-
const databaseUrl = new URL(`v1/database/${nameOrAddress}/subscribe`, url);
|
|
5109
|
-
if (temporaryAuthToken) {
|
|
5110
|
-
databaseUrl.searchParams.set("token", temporaryAuthToken);
|
|
5111
|
-
}
|
|
5112
|
-
databaseUrl.searchParams.set(
|
|
5113
|
-
"compression",
|
|
5114
|
-
compression === "gzip" ? "Gzip" : "None"
|
|
5115
|
-
);
|
|
5116
|
-
if (lightMode) {
|
|
5117
|
-
databaseUrl.searchParams.set("light", "true");
|
|
5118
|
-
}
|
|
5119
|
-
if (confirmedReads !== void 0) {
|
|
5120
|
-
databaseUrl.searchParams.set("confirmed", confirmedReads.toString());
|
|
5121
|
-
}
|
|
5122
|
-
const ws = new WS(databaseUrl.toString(), wsProtocol);
|
|
5123
|
-
return new _WebsocketDecompressAdapter(ws);
|
|
5120
|
+
static async openWebSocket(args) {
|
|
5121
|
+
return new _WebsocketDecompressAdapter(await openWebSocket(args));
|
|
5124
5122
|
}
|
|
5125
5123
|
};
|
|
5126
5124
|
|
|
@@ -5137,7 +5135,7 @@ var DbConnectionBuilder = class {
|
|
|
5137
5135
|
constructor(remoteModule, dbConnectionCtor) {
|
|
5138
5136
|
this.remoteModule = remoteModule;
|
|
5139
5137
|
this.dbConnectionCtor = dbConnectionCtor;
|
|
5140
|
-
this.#createWSFn = WebsocketDecompressAdapter.
|
|
5138
|
+
this.#createWSFn = WebsocketDecompressAdapter.openWebSocket;
|
|
5141
5139
|
}
|
|
5142
5140
|
#uri;
|
|
5143
5141
|
#nameOrAddress;
|
|
@@ -5192,6 +5190,16 @@ var DbConnectionBuilder = class {
|
|
|
5192
5190
|
* @param compression The compression algorithm to use for the connection.
|
|
5193
5191
|
*/
|
|
5194
5192
|
withCompression(compression) {
|
|
5193
|
+
if (compression === "brotli") {
|
|
5194
|
+
try {
|
|
5195
|
+
new DecompressionStream("brotli");
|
|
5196
|
+
} catch (e) {
|
|
5197
|
+
throw new TypeError(
|
|
5198
|
+
`Brotli compression is not supported by the runtime. Please choose a different compression method.`,
|
|
5199
|
+
{ cause: e }
|
|
5200
|
+
);
|
|
5201
|
+
}
|
|
5202
|
+
}
|
|
5195
5203
|
this.#compression = compression;
|
|
5196
5204
|
return this;
|
|
5197
5205
|
}
|
|
@@ -5555,6 +5563,100 @@ var SubscriptionHandleImpl = class {
|
|
|
5555
5563
|
return this.#activeState;
|
|
5556
5564
|
}
|
|
5557
5565
|
};
|
|
5566
|
+
|
|
5567
|
+
// src/sdk/websocket_protocols.ts
|
|
5568
|
+
var V2_WS_PROTOCOL = "v2.bsatn.spacetimedb";
|
|
5569
|
+
var V3_WS_PROTOCOL = "v3.bsatn.spacetimedb";
|
|
5570
|
+
var PREFERRED_WS_PROTOCOLS = [V3_WS_PROTOCOL, V2_WS_PROTOCOL];
|
|
5571
|
+
function normalizeWsProtocol(protocol) {
|
|
5572
|
+
if (protocol === V3_WS_PROTOCOL) {
|
|
5573
|
+
return V3_WS_PROTOCOL;
|
|
5574
|
+
}
|
|
5575
|
+
if (protocol === "" || protocol === V2_WS_PROTOCOL) {
|
|
5576
|
+
return V2_WS_PROTOCOL;
|
|
5577
|
+
}
|
|
5578
|
+
stdbLogger(
|
|
5579
|
+
"warn",
|
|
5580
|
+
`Unexpected websocket subprotocol "${protocol}", falling back to ${V2_WS_PROTOCOL}.`
|
|
5581
|
+
);
|
|
5582
|
+
return V2_WS_PROTOCOL;
|
|
5583
|
+
}
|
|
5584
|
+
|
|
5585
|
+
// src/sdk/websocket_v3_frames.ts
|
|
5586
|
+
var EMPTY_V3_PAYLOAD_ERR = "v3 websocket payloads must contain at least one message";
|
|
5587
|
+
function ensureMessages(messages) {
|
|
5588
|
+
if (messages.length === 0) {
|
|
5589
|
+
throw new RangeError(EMPTY_V3_PAYLOAD_ERR);
|
|
5590
|
+
}
|
|
5591
|
+
}
|
|
5592
|
+
function ensureMessageCount(messages, messageCount) {
|
|
5593
|
+
ensureMessages(messages);
|
|
5594
|
+
if (messageCount < 1 || messageCount > messages.length) {
|
|
5595
|
+
throw new RangeError(
|
|
5596
|
+
`v3 websocket payload requested ${messageCount} messages from ${messages.length}`
|
|
5597
|
+
);
|
|
5598
|
+
}
|
|
5599
|
+
}
|
|
5600
|
+
function concatenateMessagesV3(writer, messages, messageCount = messages.length) {
|
|
5601
|
+
ensureMessageCount(messages, messageCount);
|
|
5602
|
+
writer.clear();
|
|
5603
|
+
for (let i = 0; i < messageCount; i++) {
|
|
5604
|
+
writer.writeBytes(messages[i]);
|
|
5605
|
+
}
|
|
5606
|
+
return writer.getBuffer();
|
|
5607
|
+
}
|
|
5608
|
+
function countClientMessagesForV3Frame(messages, maxFrameBytes) {
|
|
5609
|
+
ensureMessages(messages);
|
|
5610
|
+
const firstMessage = messages[0];
|
|
5611
|
+
if (firstMessage.length > maxFrameBytes) {
|
|
5612
|
+
return 1;
|
|
5613
|
+
}
|
|
5614
|
+
let count = 1;
|
|
5615
|
+
let frameSize = firstMessage.length;
|
|
5616
|
+
while (count < messages.length) {
|
|
5617
|
+
const nextMessage = messages[count];
|
|
5618
|
+
const nextFrameSize = frameSize + nextMessage.length;
|
|
5619
|
+
if (nextFrameSize > maxFrameBytes) {
|
|
5620
|
+
break;
|
|
5621
|
+
}
|
|
5622
|
+
frameSize = nextFrameSize;
|
|
5623
|
+
count += 1;
|
|
5624
|
+
}
|
|
5625
|
+
return count;
|
|
5626
|
+
}
|
|
5627
|
+
function encodeClientMessagesV3(writer, messages, messageCount = messages.length) {
|
|
5628
|
+
return concatenateMessagesV3(writer, messages, messageCount);
|
|
5629
|
+
}
|
|
5630
|
+
function forEachServerMessageV3(reader, data, visit) {
|
|
5631
|
+
reader.reset(data);
|
|
5632
|
+
if (reader.remaining === 0) {
|
|
5633
|
+
throw new RangeError(EMPTY_V3_PAYLOAD_ERR);
|
|
5634
|
+
}
|
|
5635
|
+
let count = 0;
|
|
5636
|
+
while (reader.remaining > 0) {
|
|
5637
|
+
visit(ServerMessage.deserialize(reader));
|
|
5638
|
+
count += 1;
|
|
5639
|
+
}
|
|
5640
|
+
return count;
|
|
5641
|
+
}
|
|
5642
|
+
|
|
5643
|
+
// src/sdk/db_connection_impl.ts
|
|
5644
|
+
var TEXT_ENCODER = new TextEncoder();
|
|
5645
|
+
function getClientMessageVariantTag(name) {
|
|
5646
|
+
if (ClientMessage.algebraicType.tag !== "Sum") {
|
|
5647
|
+
throw new TypeError("ClientMessage must be a sum type");
|
|
5648
|
+
}
|
|
5649
|
+
const tag = ClientMessage.algebraicType.value.variants.findIndex(
|
|
5650
|
+
(variant) => variant.name === name
|
|
5651
|
+
);
|
|
5652
|
+
if (tag === -1) {
|
|
5653
|
+
throw new RangeError(`Unknown ClientMessage variant: ${name}`);
|
|
5654
|
+
}
|
|
5655
|
+
return tag;
|
|
5656
|
+
}
|
|
5657
|
+
var CLIENT_MESSAGE_CALL_REDUCER_TAG = getClientMessageVariantTag("CallReducer");
|
|
5658
|
+
var CLIENT_MESSAGE_CALL_PROCEDURE_TAG = getClientMessageVariantTag("CallProcedure");
|
|
5659
|
+
var MAX_V3_OUTBOUND_FRAME_BYTES = 256 * 1024;
|
|
5558
5660
|
var DbConnectionImpl = class {
|
|
5559
5661
|
/**
|
|
5560
5662
|
* Whether or not the connection is active.
|
|
@@ -5589,22 +5691,35 @@ var DbConnectionImpl = class {
|
|
|
5589
5691
|
* The `ConnectionId` of the connection to to the database.
|
|
5590
5692
|
*/
|
|
5591
5693
|
connectionId = ConnectionId.random();
|
|
5694
|
+
#connectionIdHex = this.connectionId.toHexString();
|
|
5592
5695
|
// These fields are meant to be strictly private.
|
|
5593
5696
|
#queryId = 0;
|
|
5594
5697
|
#requestId = 0;
|
|
5595
5698
|
#eventId = 0;
|
|
5596
5699
|
#emitter;
|
|
5597
|
-
#
|
|
5700
|
+
#inboundQueue = [];
|
|
5701
|
+
#inboundQueueOffset = 0;
|
|
5702
|
+
#isDrainingInboundQueue = false;
|
|
5598
5703
|
#outboundQueue = [];
|
|
5704
|
+
#isOutboundFlushScheduled = false;
|
|
5705
|
+
#negotiatedWsProtocol = V2_WS_PROTOCOL;
|
|
5599
5706
|
#subscriptionManager = new SubscriptionManager();
|
|
5600
5707
|
#remoteModule;
|
|
5601
5708
|
#reducerCallbacks = /* @__PURE__ */ new Map();
|
|
5602
5709
|
#reducerCallInfo = /* @__PURE__ */ new Map();
|
|
5603
5710
|
#procedureCallbacks = /* @__PURE__ */ new Map();
|
|
5604
5711
|
#rowDeserializers;
|
|
5712
|
+
#rowIdMetadata;
|
|
5605
5713
|
#reducerArgsSerializers;
|
|
5606
5714
|
#procedureSerializers;
|
|
5715
|
+
#reducerNameBytes;
|
|
5716
|
+
#procedureNameBytes;
|
|
5607
5717
|
#sourceNameToTableDef;
|
|
5718
|
+
#messageReader = new BinaryReader(new Uint8Array());
|
|
5719
|
+
#rowListReader = new BinaryReader(new Uint8Array());
|
|
5720
|
+
#clientFrameEncoder = new BinaryWriter(1024);
|
|
5721
|
+
#boundSubscriptionBuilder;
|
|
5722
|
+
#boundDisconnect;
|
|
5608
5723
|
// These fields are not part of the public API, but in a pinch you
|
|
5609
5724
|
// could use JavaScript to access them by bypassing TypeScript's
|
|
5610
5725
|
// private fields.
|
|
@@ -5633,22 +5748,35 @@ var DbConnectionImpl = class {
|
|
|
5633
5748
|
this.token = token;
|
|
5634
5749
|
this.#remoteModule = remoteModule;
|
|
5635
5750
|
this.#emitter = emitter;
|
|
5751
|
+
this.#boundSubscriptionBuilder = this.subscriptionBuilder.bind(this);
|
|
5752
|
+
this.#boundDisconnect = this.disconnect.bind(this);
|
|
5636
5753
|
this.#rowDeserializers = /* @__PURE__ */ Object.create(null);
|
|
5754
|
+
this.#rowIdMetadata = /* @__PURE__ */ Object.create(null);
|
|
5637
5755
|
this.#sourceNameToTableDef = /* @__PURE__ */ Object.create(null);
|
|
5638
5756
|
for (const table2 of Object.values(remoteModule.tables)) {
|
|
5639
5757
|
this.#rowDeserializers[table2.sourceName] = ProductType.makeDeserializer(
|
|
5640
5758
|
table2.rowType
|
|
5641
5759
|
);
|
|
5642
5760
|
this.#sourceNameToTableDef[table2.sourceName] = table2;
|
|
5761
|
+
const primaryKeyColumn = Object.entries(table2.columns).find(
|
|
5762
|
+
([, column]) => column.columnMetadata.isPrimaryKey
|
|
5763
|
+
);
|
|
5764
|
+
this.#rowIdMetadata[table2.sourceName] = primaryKeyColumn ? {
|
|
5765
|
+
primaryKeyColName: primaryKeyColumn[0],
|
|
5766
|
+
primaryKeyColType: primaryKeyColumn[1].typeBuilder.algebraicType
|
|
5767
|
+
} : {};
|
|
5643
5768
|
}
|
|
5644
5769
|
this.#reducerArgsSerializers = /* @__PURE__ */ Object.create(null);
|
|
5770
|
+
this.#reducerNameBytes = /* @__PURE__ */ Object.create(null);
|
|
5645
5771
|
for (const reducer of remoteModule.reducers) {
|
|
5646
5772
|
this.#reducerArgsSerializers[reducer.name] = {
|
|
5647
5773
|
serialize: ProductType.makeSerializer(reducer.paramsType),
|
|
5648
5774
|
deserialize: ProductType.makeDeserializer(reducer.paramsType)
|
|
5649
5775
|
};
|
|
5776
|
+
this.#reducerNameBytes[reducer.name] = TEXT_ENCODER.encode(reducer.name);
|
|
5650
5777
|
}
|
|
5651
5778
|
this.#procedureSerializers = /* @__PURE__ */ Object.create(null);
|
|
5779
|
+
this.#procedureNameBytes = /* @__PURE__ */ Object.create(null);
|
|
5652
5780
|
for (const procedure of remoteModule.procedures) {
|
|
5653
5781
|
this.#procedureSerializers[procedure.name] = {
|
|
5654
5782
|
serializeArgs: ProductType.makeSerializer(
|
|
@@ -5658,9 +5786,11 @@ var DbConnectionImpl = class {
|
|
|
5658
5786
|
procedure.returnType.algebraicType
|
|
5659
5787
|
)
|
|
5660
5788
|
};
|
|
5789
|
+
this.#procedureNameBytes[procedure.name] = TEXT_ENCODER.encode(
|
|
5790
|
+
procedure.name
|
|
5791
|
+
);
|
|
5661
5792
|
}
|
|
5662
|
-
|
|
5663
|
-
url.searchParams.set("connection_id", connectionId);
|
|
5793
|
+
url.searchParams.set("connection_id", this.#connectionIdHex);
|
|
5664
5794
|
this.clientCache = new ClientCache();
|
|
5665
5795
|
this.db = this.#makeDbView();
|
|
5666
5796
|
this.reducers = this.#makeReducers(remoteModule);
|
|
@@ -5668,7 +5798,7 @@ var DbConnectionImpl = class {
|
|
|
5668
5798
|
this.wsPromise = createWSFn({
|
|
5669
5799
|
url,
|
|
5670
5800
|
nameOrAddress,
|
|
5671
|
-
wsProtocol:
|
|
5801
|
+
wsProtocol: [...PREFERRED_WS_PROTOCOLS],
|
|
5672
5802
|
authToken: token,
|
|
5673
5803
|
compression,
|
|
5674
5804
|
lightMode,
|
|
@@ -5712,16 +5842,22 @@ var DbConnectionImpl = class {
|
|
|
5712
5842
|
}
|
|
5713
5843
|
#makeReducers(def) {
|
|
5714
5844
|
const out = {};
|
|
5715
|
-
const writer = new BinaryWriter(1024);
|
|
5716
5845
|
for (const reducer of def.reducers) {
|
|
5717
5846
|
const reducerName = reducer.name;
|
|
5847
|
+
const encodedReducerName = this.#reducerNameBytes[reducerName];
|
|
5718
5848
|
const key = reducer.accessorName;
|
|
5719
5849
|
const { serialize: serializeArgs } = this.#reducerArgsSerializers[reducerName];
|
|
5720
5850
|
out[key] = (params) => {
|
|
5851
|
+
const writer = this.#reducerArgsEncoder;
|
|
5721
5852
|
writer.clear();
|
|
5722
5853
|
serializeArgs(writer, params);
|
|
5723
5854
|
const argsBuffer = writer.getBuffer();
|
|
5724
|
-
return this
|
|
5855
|
+
return this.#callReducerWithEncodedName(
|
|
5856
|
+
reducerName,
|
|
5857
|
+
encodedReducerName,
|
|
5858
|
+
argsBuffer,
|
|
5859
|
+
params
|
|
5860
|
+
);
|
|
5725
5861
|
};
|
|
5726
5862
|
}
|
|
5727
5863
|
return out;
|
|
@@ -5731,13 +5867,18 @@ var DbConnectionImpl = class {
|
|
|
5731
5867
|
const writer = new BinaryWriter(1024);
|
|
5732
5868
|
for (const procedure of def.procedures) {
|
|
5733
5869
|
const procedureName = procedure.name;
|
|
5870
|
+
const encodedProcedureName = this.#procedureNameBytes[procedureName];
|
|
5734
5871
|
const key = procedure.accessorName;
|
|
5735
5872
|
const { serializeArgs, deserializeReturn } = this.#procedureSerializers[procedureName];
|
|
5736
5873
|
out[key] = (params) => {
|
|
5737
5874
|
writer.clear();
|
|
5738
5875
|
serializeArgs(writer, params);
|
|
5739
5876
|
const argsBuffer = writer.getBuffer();
|
|
5740
|
-
return this
|
|
5877
|
+
return this.#callProcedureWithEncodedName(
|
|
5878
|
+
procedureName,
|
|
5879
|
+
encodedProcedureName,
|
|
5880
|
+
argsBuffer
|
|
5881
|
+
).then((returnBuf) => {
|
|
5741
5882
|
return deserializeReturn(new BinaryReader(returnBuf));
|
|
5742
5883
|
});
|
|
5743
5884
|
};
|
|
@@ -5749,8 +5890,8 @@ var DbConnectionImpl = class {
|
|
|
5749
5890
|
db: this.db,
|
|
5750
5891
|
reducers: this.reducers,
|
|
5751
5892
|
isActive: this.isActive,
|
|
5752
|
-
subscriptionBuilder: this
|
|
5753
|
-
disconnect: this
|
|
5893
|
+
subscriptionBuilder: this.#boundSubscriptionBuilder,
|
|
5894
|
+
disconnect: this.#boundDisconnect,
|
|
5754
5895
|
event
|
|
5755
5896
|
};
|
|
5756
5897
|
}
|
|
@@ -5795,21 +5936,16 @@ var DbConnectionImpl = class {
|
|
|
5795
5936
|
}
|
|
5796
5937
|
#parseRowList(type, tableName, rowList) {
|
|
5797
5938
|
const buffer = rowList.rowsData;
|
|
5798
|
-
const reader =
|
|
5939
|
+
const reader = this.#rowListReader;
|
|
5940
|
+
reader.reset(buffer);
|
|
5799
5941
|
const rows = [];
|
|
5800
5942
|
const deserializeRow = this.#rowDeserializers[tableName];
|
|
5801
|
-
const
|
|
5802
|
-
const columnsArray = Object.entries(table2.columns);
|
|
5803
|
-
const primaryKeyColumnEntry = columnsArray.find(
|
|
5804
|
-
(col) => col[1].columnMetadata.isPrimaryKey
|
|
5805
|
-
);
|
|
5943
|
+
const { primaryKeyColName, primaryKeyColType } = this.#rowIdMetadata[tableName];
|
|
5806
5944
|
let previousOffset = 0;
|
|
5807
5945
|
while (reader.remaining > 0) {
|
|
5808
5946
|
const row = deserializeRow(reader);
|
|
5809
5947
|
let rowId = void 0;
|
|
5810
|
-
if (
|
|
5811
|
-
const primaryKeyColName = primaryKeyColumnEntry[0];
|
|
5812
|
-
const primaryKeyColType = primaryKeyColumnEntry[1].typeBuilder.algebraicType;
|
|
5948
|
+
if (primaryKeyColName !== void 0 && primaryKeyColType !== void 0) {
|
|
5813
5949
|
rowId = AlgebraicType.intoMapKey(
|
|
5814
5950
|
primaryKeyColType,
|
|
5815
5951
|
row[primaryKeyColName]
|
|
@@ -5890,40 +6026,136 @@ var DbConnectionImpl = class {
|
|
|
5890
6026
|
return this.#mergeTableUpdates(updates);
|
|
5891
6027
|
}
|
|
5892
6028
|
#flushOutboundQueue(wsResolved) {
|
|
6029
|
+
if (this.#negotiatedWsProtocol === V3_WS_PROTOCOL) {
|
|
6030
|
+
this.#flushOutboundQueueV3(wsResolved);
|
|
6031
|
+
return;
|
|
6032
|
+
}
|
|
6033
|
+
this.#flushOutboundQueueV2(wsResolved);
|
|
6034
|
+
}
|
|
6035
|
+
#flushOutboundQueueV2(wsResolved) {
|
|
5893
6036
|
const pending = this.#outboundQueue.splice(0);
|
|
5894
6037
|
for (const message of pending) {
|
|
5895
6038
|
wsResolved.send(message);
|
|
5896
6039
|
}
|
|
5897
6040
|
}
|
|
6041
|
+
#flushOutboundQueueV3(wsResolved) {
|
|
6042
|
+
if (this.#outboundQueue.length === 0) {
|
|
6043
|
+
return;
|
|
6044
|
+
}
|
|
6045
|
+
const batchSize = countClientMessagesForV3Frame(
|
|
6046
|
+
this.#outboundQueue,
|
|
6047
|
+
MAX_V3_OUTBOUND_FRAME_BYTES
|
|
6048
|
+
);
|
|
6049
|
+
wsResolved.send(
|
|
6050
|
+
encodeClientMessagesV3(
|
|
6051
|
+
this.#clientFrameEncoder,
|
|
6052
|
+
this.#outboundQueue,
|
|
6053
|
+
batchSize
|
|
6054
|
+
)
|
|
6055
|
+
);
|
|
6056
|
+
if (batchSize === this.#outboundQueue.length) {
|
|
6057
|
+
this.#outboundQueue.length = 0;
|
|
6058
|
+
return;
|
|
6059
|
+
}
|
|
6060
|
+
this.#outboundQueue.copyWithin(0, batchSize);
|
|
6061
|
+
this.#outboundQueue.length -= batchSize;
|
|
6062
|
+
if (this.#outboundQueue.length > 0) {
|
|
6063
|
+
this.#scheduleDeferredOutboundFlush();
|
|
6064
|
+
}
|
|
6065
|
+
}
|
|
6066
|
+
#scheduleOutboundFlush() {
|
|
6067
|
+
this.#scheduleOutboundFlushWith("microtask");
|
|
6068
|
+
}
|
|
6069
|
+
#scheduleDeferredOutboundFlush() {
|
|
6070
|
+
this.#scheduleOutboundFlushWith("next-task");
|
|
6071
|
+
}
|
|
6072
|
+
#scheduleOutboundFlushWith(schedule) {
|
|
6073
|
+
if (this.#isOutboundFlushScheduled) {
|
|
6074
|
+
return;
|
|
6075
|
+
}
|
|
6076
|
+
this.#isOutboundFlushScheduled = true;
|
|
6077
|
+
const flush = () => {
|
|
6078
|
+
this.#isOutboundFlushScheduled = false;
|
|
6079
|
+
if (this.ws && this.isActive) {
|
|
6080
|
+
this.#flushOutboundQueue(this.ws);
|
|
6081
|
+
}
|
|
6082
|
+
};
|
|
6083
|
+
if (schedule === "next-task") {
|
|
6084
|
+
setTimeout(flush, 0);
|
|
6085
|
+
} else {
|
|
6086
|
+
queueMicrotask(flush);
|
|
6087
|
+
}
|
|
6088
|
+
}
|
|
6089
|
+
#reducerArgsEncoder = new BinaryWriter(1024);
|
|
5898
6090
|
#clientMessageEncoder = new BinaryWriter(1024);
|
|
6091
|
+
#sendEncodedMessage(encoded, describe) {
|
|
6092
|
+
stdbLogger("trace", describe);
|
|
6093
|
+
if (this.ws && this.isActive) {
|
|
6094
|
+
if (this.#negotiatedWsProtocol === V2_WS_PROTOCOL) {
|
|
6095
|
+
if (this.#outboundQueue.length) this.#flushOutboundQueue(this.ws);
|
|
6096
|
+
this.ws.send(encoded);
|
|
6097
|
+
return;
|
|
6098
|
+
}
|
|
6099
|
+
this.#outboundQueue.push(encoded.slice());
|
|
6100
|
+
this.#scheduleOutboundFlush();
|
|
6101
|
+
} else {
|
|
6102
|
+
this.#outboundQueue.push(encoded.slice());
|
|
6103
|
+
}
|
|
6104
|
+
}
|
|
5899
6105
|
#sendMessage(message) {
|
|
5900
6106
|
const writer = this.#clientMessageEncoder;
|
|
5901
6107
|
writer.clear();
|
|
5902
6108
|
ClientMessage.serialize(writer, message);
|
|
5903
6109
|
const encoded = writer.getBuffer();
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
6110
|
+
const isLive = !!(this.ws && this.isActive);
|
|
6111
|
+
this.#sendEncodedMessage(
|
|
6112
|
+
encoded,
|
|
6113
|
+
() => isLive ? `Sending message to server: ${stringify(message)}` : `Queuing message to server: ${stringify(message)}`
|
|
6114
|
+
);
|
|
6115
|
+
}
|
|
6116
|
+
#sendCallReducerMessage(requestId, reducerNameBytes, argsBuffer) {
|
|
6117
|
+
const writer = this.#clientMessageEncoder;
|
|
6118
|
+
writer.clear();
|
|
6119
|
+
writer.writeByte(CLIENT_MESSAGE_CALL_REDUCER_TAG);
|
|
6120
|
+
writer.writeU32(requestId);
|
|
6121
|
+
writer.writeU8(0);
|
|
6122
|
+
writer.writeUInt8Array(reducerNameBytes);
|
|
6123
|
+
writer.writeUInt8Array(argsBuffer);
|
|
6124
|
+
const encoded = writer.getBuffer();
|
|
6125
|
+
this.#sendEncodedMessage(
|
|
6126
|
+
encoded,
|
|
6127
|
+
() => `Sending reducer call message to server: requestId=${requestId}`
|
|
6128
|
+
);
|
|
6129
|
+
}
|
|
6130
|
+
#sendCallProcedureMessage(requestId, procedureNameBytes, argsBuffer) {
|
|
6131
|
+
const writer = this.#clientMessageEncoder;
|
|
6132
|
+
writer.clear();
|
|
6133
|
+
writer.writeByte(CLIENT_MESSAGE_CALL_PROCEDURE_TAG);
|
|
6134
|
+
writer.writeU32(requestId);
|
|
6135
|
+
writer.writeU8(0);
|
|
6136
|
+
writer.writeUInt8Array(procedureNameBytes);
|
|
6137
|
+
writer.writeUInt8Array(argsBuffer);
|
|
6138
|
+
const encoded = writer.getBuffer();
|
|
6139
|
+
this.#sendEncodedMessage(
|
|
6140
|
+
encoded,
|
|
6141
|
+
() => `Sending procedure call message to server: requestId=${requestId}`
|
|
6142
|
+
);
|
|
6143
|
+
}
|
|
6144
|
+
#setConnectionId(connectionId) {
|
|
6145
|
+
this.connectionId = connectionId;
|
|
6146
|
+
this.#connectionIdHex = connectionId.toHexString();
|
|
5918
6147
|
}
|
|
5919
6148
|
#nextEventId() {
|
|
5920
6149
|
this.#eventId += 1;
|
|
5921
|
-
return `${this
|
|
6150
|
+
return `${this.#connectionIdHex}:${this.#eventId}`;
|
|
5922
6151
|
}
|
|
5923
6152
|
/**
|
|
5924
6153
|
* Handles WebSocket onOpen event.
|
|
5925
6154
|
*/
|
|
5926
6155
|
#handleOnOpen() {
|
|
6156
|
+
if (this.ws) {
|
|
6157
|
+
this.#negotiatedWsProtocol = normalizeWsProtocol(this.ws.protocol);
|
|
6158
|
+
}
|
|
5927
6159
|
this.isActive = true;
|
|
5928
6160
|
if (this.ws) {
|
|
5929
6161
|
this.#flushOutboundQueue(this.ws);
|
|
@@ -5958,8 +6190,16 @@ var DbConnectionImpl = class {
|
|
|
5958
6190
|
eventContext
|
|
5959
6191
|
);
|
|
5960
6192
|
}
|
|
5961
|
-
|
|
5962
|
-
|
|
6193
|
+
#dispatchPendingCallbacks(callbacks) {
|
|
6194
|
+
stdbLogger(
|
|
6195
|
+
"trace",
|
|
6196
|
+
() => `Calling ${callbacks.length} triggered row callbacks`
|
|
6197
|
+
);
|
|
6198
|
+
for (const callback of callbacks) {
|
|
6199
|
+
callback.cb();
|
|
6200
|
+
}
|
|
6201
|
+
}
|
|
6202
|
+
#processServerMessage(serverMessage) {
|
|
5963
6203
|
stdbLogger(
|
|
5964
6204
|
"trace",
|
|
5965
6205
|
() => `Processing server message: ${stringify(serverMessage)}`
|
|
@@ -5970,7 +6210,7 @@ var DbConnectionImpl = class {
|
|
|
5970
6210
|
if (!this.token && serverMessage.value.token) {
|
|
5971
6211
|
this.token = serverMessage.value.token;
|
|
5972
6212
|
}
|
|
5973
|
-
this
|
|
6213
|
+
this.#setConnectionId(serverMessage.value.connectionId);
|
|
5974
6214
|
this.#emitter.emit("connect", this, this.identity, this.token);
|
|
5975
6215
|
break;
|
|
5976
6216
|
}
|
|
@@ -5996,13 +6236,7 @@ var DbConnectionImpl = class {
|
|
|
5996
6236
|
const callbacks = this.#applyTableUpdates(tableUpdates, eventContext);
|
|
5997
6237
|
const { event: _, ...subscriptionEventContext } = eventContext;
|
|
5998
6238
|
subscription.emitter.emit("applied", subscriptionEventContext);
|
|
5999
|
-
|
|
6000
|
-
"trace",
|
|
6001
|
-
() => `Calling ${callbacks.length} triggered row callbacks`
|
|
6002
|
-
);
|
|
6003
|
-
for (const callback of callbacks) {
|
|
6004
|
-
callback.cb();
|
|
6005
|
-
}
|
|
6239
|
+
this.#dispatchPendingCallbacks(callbacks);
|
|
6006
6240
|
break;
|
|
6007
6241
|
}
|
|
6008
6242
|
case "UnsubscribeApplied": {
|
|
@@ -6025,13 +6259,7 @@ var DbConnectionImpl = class {
|
|
|
6025
6259
|
const { event: _, ...subscriptionEventContext } = eventContext;
|
|
6026
6260
|
subscription.emitter.emit("end", subscriptionEventContext);
|
|
6027
6261
|
this.#subscriptionManager.subscriptions.delete(querySetId);
|
|
6028
|
-
|
|
6029
|
-
"trace",
|
|
6030
|
-
() => `Calling ${callbacks.length} triggered row callbacks`
|
|
6031
|
-
);
|
|
6032
|
-
for (const callback of callbacks) {
|
|
6033
|
-
callback.cb();
|
|
6034
|
-
}
|
|
6262
|
+
this.#dispatchPendingCallbacks(callbacks);
|
|
6035
6263
|
break;
|
|
6036
6264
|
}
|
|
6037
6265
|
case "SubscriptionError": {
|
|
@@ -6079,13 +6307,7 @@ var DbConnectionImpl = class {
|
|
|
6079
6307
|
eventContext,
|
|
6080
6308
|
serverMessage.value
|
|
6081
6309
|
);
|
|
6082
|
-
|
|
6083
|
-
"trace",
|
|
6084
|
-
() => `Calling ${callbacks.length} triggered row callbacks`
|
|
6085
|
-
);
|
|
6086
|
-
for (const callback of callbacks) {
|
|
6087
|
-
callback.cb();
|
|
6088
|
-
}
|
|
6310
|
+
this.#dispatchPendingCallbacks(callbacks);
|
|
6089
6311
|
break;
|
|
6090
6312
|
}
|
|
6091
6313
|
case "ReducerResult": {
|
|
@@ -6113,13 +6335,7 @@ var DbConnectionImpl = class {
|
|
|
6113
6335
|
eventContext,
|
|
6114
6336
|
result.value.transactionUpdate
|
|
6115
6337
|
);
|
|
6116
|
-
|
|
6117
|
-
"trace",
|
|
6118
|
-
() => `Calling ${callbacks.length} triggered row callbacks`
|
|
6119
|
-
);
|
|
6120
|
-
for (const callback of callbacks) {
|
|
6121
|
-
callback.cb();
|
|
6122
|
-
}
|
|
6338
|
+
this.#dispatchPendingCallbacks(callbacks);
|
|
6123
6339
|
}
|
|
6124
6340
|
this.#reducerCallInfo.delete(requestId);
|
|
6125
6341
|
const cb = this.#reducerCallbacks.get(requestId);
|
|
@@ -6144,14 +6360,55 @@ var DbConnectionImpl = class {
|
|
|
6144
6360
|
}
|
|
6145
6361
|
}
|
|
6146
6362
|
}
|
|
6363
|
+
#processV2Message(data) {
|
|
6364
|
+
const reader = this.#messageReader;
|
|
6365
|
+
reader.reset(data);
|
|
6366
|
+
this.#processServerMessage(ServerMessage.deserialize(reader));
|
|
6367
|
+
}
|
|
6368
|
+
#processMessage(data) {
|
|
6369
|
+
if (this.#negotiatedWsProtocol !== V3_WS_PROTOCOL) {
|
|
6370
|
+
this.#processV2Message(data);
|
|
6371
|
+
return;
|
|
6372
|
+
}
|
|
6373
|
+
const messageCount = forEachServerMessageV3(
|
|
6374
|
+
this.#messageReader,
|
|
6375
|
+
data,
|
|
6376
|
+
(serverMessage) => {
|
|
6377
|
+
this.#processServerMessage(serverMessage);
|
|
6378
|
+
}
|
|
6379
|
+
);
|
|
6380
|
+
stdbLogger(
|
|
6381
|
+
"trace",
|
|
6382
|
+
() => `Processing server v3 payload with ${messageCount} message(s)`
|
|
6383
|
+
);
|
|
6384
|
+
}
|
|
6147
6385
|
/**
|
|
6148
6386
|
* Handles WebSocket onMessage event.
|
|
6149
6387
|
* @param wsMessage MessageEvent object.
|
|
6150
6388
|
*/
|
|
6151
6389
|
#handleOnMessage(wsMessage) {
|
|
6152
|
-
this.#
|
|
6153
|
-
|
|
6154
|
-
|
|
6390
|
+
this.#inboundQueue.push(wsMessage.data);
|
|
6391
|
+
if (this.#isDrainingInboundQueue) {
|
|
6392
|
+
return;
|
|
6393
|
+
}
|
|
6394
|
+
this.#isDrainingInboundQueue = true;
|
|
6395
|
+
try {
|
|
6396
|
+
while (this.#inboundQueueOffset < this.#inboundQueue.length) {
|
|
6397
|
+
const data = this.#inboundQueue[this.#inboundQueueOffset];
|
|
6398
|
+
this.#inboundQueueOffset += 1;
|
|
6399
|
+
if (data) {
|
|
6400
|
+
this.#processMessage(data);
|
|
6401
|
+
}
|
|
6402
|
+
}
|
|
6403
|
+
} finally {
|
|
6404
|
+
if (this.#inboundQueueOffset >= this.#inboundQueue.length) {
|
|
6405
|
+
this.#inboundQueue.length = 0;
|
|
6406
|
+
} else if (this.#inboundQueueOffset > 0) {
|
|
6407
|
+
this.#inboundQueue = this.#inboundQueue.slice(this.#inboundQueueOffset);
|
|
6408
|
+
}
|
|
6409
|
+
this.#inboundQueueOffset = 0;
|
|
6410
|
+
this.#isDrainingInboundQueue = false;
|
|
6411
|
+
}
|
|
6155
6412
|
}
|
|
6156
6413
|
/**
|
|
6157
6414
|
* Call a reducer on your SpacetimeDB module.
|
|
@@ -6160,6 +6417,45 @@ var DbConnectionImpl = class {
|
|
|
6160
6417
|
* @param argsSerializer The arguments to pass to the reducer
|
|
6161
6418
|
*/
|
|
6162
6419
|
callReducer(reducerName, argsBuffer, reducerArgs) {
|
|
6420
|
+
const encodedReducerName = this.#reducerNameBytes[reducerName];
|
|
6421
|
+
if (encodedReducerName) {
|
|
6422
|
+
return this.#callReducerWithEncodedName(
|
|
6423
|
+
reducerName,
|
|
6424
|
+
encodedReducerName,
|
|
6425
|
+
argsBuffer,
|
|
6426
|
+
reducerArgs
|
|
6427
|
+
);
|
|
6428
|
+
}
|
|
6429
|
+
return this.#callReducerGeneric(reducerName, argsBuffer, reducerArgs);
|
|
6430
|
+
}
|
|
6431
|
+
#callReducerWithEncodedName(reducerName, encodedReducerName, argsBuffer, reducerArgs) {
|
|
6432
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
6433
|
+
const requestId = this.#getNextRequestId();
|
|
6434
|
+
this.#sendCallReducerMessage(requestId, encodedReducerName, argsBuffer);
|
|
6435
|
+
if (reducerArgs) {
|
|
6436
|
+
this.#reducerCallInfo.set(requestId, {
|
|
6437
|
+
name: reducerName,
|
|
6438
|
+
args: reducerArgs
|
|
6439
|
+
});
|
|
6440
|
+
}
|
|
6441
|
+
this.#reducerCallbacks.set(requestId, (result) => {
|
|
6442
|
+
if (result.tag === "Ok" || result.tag === "OkEmpty") {
|
|
6443
|
+
resolve();
|
|
6444
|
+
} else {
|
|
6445
|
+
if (result.tag === "Err") {
|
|
6446
|
+
const reader = new BinaryReader(result.value);
|
|
6447
|
+
const errorString = reader.readString();
|
|
6448
|
+
reject(new SenderError(errorString));
|
|
6449
|
+
} else if (result.tag === "InternalError") {
|
|
6450
|
+
reject(new InternalError(result.value));
|
|
6451
|
+
} else {
|
|
6452
|
+
reject(new Error("Unexpected reducer result"));
|
|
6453
|
+
}
|
|
6454
|
+
}
|
|
6455
|
+
});
|
|
6456
|
+
return promise;
|
|
6457
|
+
}
|
|
6458
|
+
#callReducerGeneric(reducerName, argsBuffer, reducerArgs) {
|
|
6163
6459
|
const { promise, resolve, reject } = Promise.withResolvers();
|
|
6164
6460
|
const requestId = this.#getNextRequestId();
|
|
6165
6461
|
const message = ClientMessage.CallReducer({
|
|
@@ -6199,7 +6495,8 @@ var DbConnectionImpl = class {
|
|
|
6199
6495
|
* @param params The arguments to pass to the reducer
|
|
6200
6496
|
*/
|
|
6201
6497
|
callReducerWithParams(reducerName, _paramsType, params) {
|
|
6202
|
-
const writer =
|
|
6498
|
+
const writer = this.#reducerArgsEncoder;
|
|
6499
|
+
writer.clear();
|
|
6203
6500
|
this.#reducerArgsSerializers[reducerName].serialize(writer, params);
|
|
6204
6501
|
const argsBuffer = writer.getBuffer();
|
|
6205
6502
|
return this.callReducer(reducerName, argsBuffer, params);
|
|
@@ -6211,6 +6508,30 @@ var DbConnectionImpl = class {
|
|
|
6211
6508
|
* @param argsBuffer The arguments to pass to the reducer
|
|
6212
6509
|
*/
|
|
6213
6510
|
callProcedure(procedureName, argsBuffer) {
|
|
6511
|
+
const encodedProcedureName = this.#procedureNameBytes[procedureName];
|
|
6512
|
+
if (encodedProcedureName) {
|
|
6513
|
+
return this.#callProcedureWithEncodedName(
|
|
6514
|
+
procedureName,
|
|
6515
|
+
encodedProcedureName,
|
|
6516
|
+
argsBuffer
|
|
6517
|
+
);
|
|
6518
|
+
}
|
|
6519
|
+
return this.#callProcedureGeneric(procedureName, argsBuffer);
|
|
6520
|
+
}
|
|
6521
|
+
#callProcedureWithEncodedName(procedureName, encodedProcedureName, argsBuffer) {
|
|
6522
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
6523
|
+
const requestId = this.#getNextRequestId();
|
|
6524
|
+
this.#sendCallProcedureMessage(requestId, encodedProcedureName, argsBuffer);
|
|
6525
|
+
this.#procedureCallbacks.set(requestId, (result) => {
|
|
6526
|
+
if (result.tag === "Ok") {
|
|
6527
|
+
resolve(result.value);
|
|
6528
|
+
} else {
|
|
6529
|
+
reject(result.value);
|
|
6530
|
+
}
|
|
6531
|
+
});
|
|
6532
|
+
return promise;
|
|
6533
|
+
}
|
|
6534
|
+
#callProcedureGeneric(procedureName, argsBuffer) {
|
|
6214
6535
|
const { promise, resolve, reject } = Promise.withResolvers();
|
|
6215
6536
|
const requestId = this.#getNextRequestId();
|
|
6216
6537
|
const message = ClientMessage.CallProcedure({
|
|
@@ -7151,7 +7472,7 @@ function table(opts, row, ..._) {
|
|
|
7151
7472
|
increment: 1n
|
|
7152
7473
|
});
|
|
7153
7474
|
}
|
|
7154
|
-
if (meta
|
|
7475
|
+
if (Object.prototype.hasOwnProperty.call(meta, "defaultValue")) {
|
|
7155
7476
|
const writer = new BinaryWriter(16);
|
|
7156
7477
|
builder.serialize(writer, meta.defaultValue);
|
|
7157
7478
|
defaultValues.push({
|