@fitzzero/quickdraw-core 5.1.1 → 5.1.3
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/README.md +1308 -219
- package/dist/{admin-DKwkIh5i.d.ts → admin-CS7JB_UH.d.ts} +2 -2
- package/dist/{adminSchemas-2DUA_hZ8.d.ts → adminSchemas-29cGgrg5.d.ts} +6 -4
- package/dist/{auth-BhWqdyb-.d.ts → auth-DtdYjrZ9.d.ts} +51 -21
- package/dist/{caller-CXTFswBO.d.ts → caller-BTwGl7vm.d.ts} +296 -33
- package/dist/chunk-2FDSKLBO.js +82 -0
- package/dist/chunk-2FDSKLBO.js.map +1 -0
- package/dist/{chunk-RT6OILOI.js → chunk-4D2DOGAW.js} +2 -14
- package/dist/chunk-4D2DOGAW.js.map +1 -0
- package/dist/{chunk-OECZPRPW.js → chunk-64I6MYBC.js} +162 -775
- package/dist/chunk-64I6MYBC.js.map +1 -0
- package/dist/chunk-7473HK24.js +17 -0
- package/dist/chunk-7473HK24.js.map +1 -0
- package/dist/chunk-7Y5ROPXL.js +33 -0
- package/dist/chunk-7Y5ROPXL.js.map +1 -0
- package/dist/chunk-A2RBQD66.js +7 -0
- package/dist/chunk-A2RBQD66.js.map +1 -0
- package/dist/chunk-AK23XSWD.js +16 -0
- package/dist/chunk-AK23XSWD.js.map +1 -0
- package/dist/chunk-ASAMUGHG.js +651 -0
- package/dist/chunk-ASAMUGHG.js.map +1 -0
- package/dist/{chunk-B2P7AZ25.js → chunk-CYE4UBOB.js} +6 -4
- package/dist/chunk-CYE4UBOB.js.map +1 -0
- package/dist/chunk-DKE6QO26.js +136 -0
- package/dist/chunk-DKE6QO26.js.map +1 -0
- package/dist/chunk-DNP65TD5.js +832 -0
- package/dist/chunk-DNP65TD5.js.map +1 -0
- package/dist/{chunk-H23KEFBA.js → chunk-DUBU3BB3.js} +30 -1
- package/dist/chunk-DUBU3BB3.js.map +1 -0
- package/dist/chunk-GYLWEJHW.js +19 -0
- package/dist/chunk-GYLWEJHW.js.map +1 -0
- package/dist/{chunk-SHEGLZEP.js → chunk-I3JCFS7H.js} +34 -13
- package/dist/chunk-I3JCFS7H.js.map +1 -0
- package/dist/{chunk-X5CWPX7H.js → chunk-IIQ3WMJK.js} +13 -2
- package/dist/chunk-IIQ3WMJK.js.map +1 -0
- package/dist/{chunk-RZTP4IEW.js → chunk-JVTONQFI.js} +6339 -4226
- package/dist/chunk-JVTONQFI.js.map +1 -0
- package/dist/{chunk-QEKVYG5F.js → chunk-KKQANRLG.js} +2 -2
- package/dist/chunk-KKQANRLG.js.map +1 -0
- package/dist/{chunk-CDKG4TFA.js → chunk-MPQAT55F.js} +38 -205
- package/dist/chunk-MPQAT55F.js.map +1 -0
- package/dist/chunk-NO4M6PO5.js +101 -0
- package/dist/chunk-NO4M6PO5.js.map +1 -0
- package/dist/{chunk-TBMKJ26R.js → chunk-NW6U45HX.js} +3 -1
- package/dist/chunk-NW6U45HX.js.map +1 -0
- package/dist/chunk-NX2V6SIL.js +202 -0
- package/dist/chunk-NX2V6SIL.js.map +1 -0
- package/dist/{chunk-ZIVPHYRG.js → chunk-NZHA4TZD.js} +72 -175
- package/dist/chunk-NZHA4TZD.js.map +1 -0
- package/dist/{chunk-2PWMUVC7.js → chunk-OCZJ4EYV.js} +518 -27
- package/dist/chunk-OCZJ4EYV.js.map +1 -0
- package/dist/{chunk-REX5YPHX.js → chunk-PHCURHC7.js} +76 -21
- package/dist/chunk-PHCURHC7.js.map +1 -0
- package/dist/{chunk-4YO5H5ON.js → chunk-Q4OGQM5I.js} +4 -10
- package/dist/chunk-Q4OGQM5I.js.map +1 -0
- package/dist/chunk-QSU47XEX.js +13 -0
- package/dist/chunk-QSU47XEX.js.map +1 -0
- package/dist/{chunk-DD4SKCNO.js → chunk-RZXJTDH5.js} +13 -2
- package/dist/chunk-RZXJTDH5.js.map +1 -0
- package/dist/{chunk-Z2LZ7IZ7.js → chunk-SN3OZVEQ.js} +5 -31
- package/dist/chunk-SN3OZVEQ.js.map +1 -0
- package/dist/{chunk-4DIQHASK.js → chunk-SQ5VUG77.js} +28 -8
- package/dist/chunk-SQ5VUG77.js.map +1 -0
- package/dist/chunk-STH5DLQP.js +1192 -0
- package/dist/chunk-STH5DLQP.js.map +1 -0
- package/dist/{chunk-QCHKWIRS.js → chunk-VZFJTKIW.js} +13 -13
- package/dist/{chunk-QCHKWIRS.js.map → chunk-VZFJTKIW.js.map} +1 -1
- package/dist/{chunk-VSQBHPWH.js → chunk-X4ZU4QH5.js} +54 -22
- package/dist/chunk-X4ZU4QH5.js.map +1 -0
- package/dist/chunk-XD7SRDUY.js +188 -0
- package/dist/chunk-XD7SRDUY.js.map +1 -0
- package/dist/chunk-XH2IZVLT.js +62 -0
- package/dist/chunk-XH2IZVLT.js.map +1 -0
- package/dist/chunk-Z7I6SONO.js +825 -0
- package/dist/chunk-Z7I6SONO.js.map +1 -0
- package/dist/cli/quickdraw-docs.js +132 -112
- package/dist/cli/quickdraw-docs.js.map +1 -1
- package/dist/client/core.d.ts +387 -0
- package/dist/client/core.js +109 -0
- package/dist/client/index.d.ts +52 -203
- package/dist/client/index.js +59 -218
- package/dist/client/index.js.map +1 -1
- package/dist/{clientTypes-Bc-G8n-U.d.ts → clientTypes-CUUNJwWs.d.ts} +3 -3
- package/dist/{connection-Cr1BU07W.d.ts → connection-2EeQ_Et0.d.ts} +22 -11
- package/dist/{createServer-CP9eDHZZ.d.ts → createServer-Bx5HOcYK.d.ts} +67 -17
- package/dist/{createTestApp-UKVGEmOf.d.ts → createTestApp-DAMANT79.d.ts} +46 -13
- package/dist/{envelope-Cp3YcVxC.d.ts → envelope-BMBaxppV.d.ts} +216 -10
- package/dist/{http-Djj2Inuu.d.ts → http-YzLAar3w.d.ts} +76 -60
- package/dist/index.d.ts +8 -7
- package/dist/index.js +82 -25
- package/dist/index.js.map +1 -1
- package/dist/{infer-Teo1xpsd.d.ts → infer-Br62cnyW.d.ts} +82 -11
- package/dist/logger-Yz93KzdV.d.ts +30 -0
- package/dist/{metrics-BdBu5o8G.d.ts → metrics-CTVpw0gu.d.ts} +2 -2
- package/dist/origins-kvpxnVcW.d.ts +8 -0
- package/dist/parser.js +2 -1
- package/dist/prisma/index.d.ts +14 -7
- package/dist/prisma/index.js +279 -70
- package/dist/prisma/index.js.map +1 -1
- package/dist/{rateLimit-ZMIZJUZF.js → rateLimit-5RKBFLUR.js} +2 -2
- package/dist/rateLimit-5RKBFLUR.js.map +1 -0
- package/dist/remote-N7OUAGOW.js +15 -0
- package/dist/remote-N7OUAGOW.js.map +1 -0
- package/dist/server/auth/index.d.ts +82 -33
- package/dist/server/auth/index.js +277 -270
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/express/index.d.ts +9 -2
- package/dist/server/express/index.js +1 -1
- package/dist/server/index.d.ts +268 -84
- package/dist/server/index.js +664 -418
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp/index.d.ts +89 -27
- package/dist/server/mcp/index.js +281 -62
- package/dist/server/mcp/index.js.map +1 -1
- package/dist/server/otel.d.ts +3 -3
- package/dist/{sharing-DVa8W-yR.d.ts → sharing-BrsmlDv_.d.ts} +3 -3
- package/dist/testing/client.d.ts +14 -14
- package/dist/testing/client.js +19 -10
- package/dist/testing/client.js.map +1 -1
- package/dist/testing/index.d.ts +50 -13
- package/dist/testing/index.js +113 -21
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/mock.d.ts +5 -5
- package/dist/testing/mock.js +17 -9
- package/dist/tracked-BR5b2O-U.d.ts +43 -0
- package/dist/{types-Cu0vmx7c.d.ts → types-CLRCQGnO.d.ts} +4 -3
- package/dist/types-tMagHbjy.d.ts +151 -0
- package/dist/utils/index.d.ts +16 -4
- package/dist/utils/index.js +6 -3
- package/package.json +5 -1
- package/dist/chunk-2PWMUVC7.js.map +0 -1
- package/dist/chunk-4DIQHASK.js.map +0 -1
- package/dist/chunk-4YO5H5ON.js.map +0 -1
- package/dist/chunk-B2P7AZ25.js.map +0 -1
- package/dist/chunk-CDKG4TFA.js.map +0 -1
- package/dist/chunk-DD4SKCNO.js.map +0 -1
- package/dist/chunk-H23KEFBA.js.map +0 -1
- package/dist/chunk-OECZPRPW.js.map +0 -1
- package/dist/chunk-QEKVYG5F.js.map +0 -1
- package/dist/chunk-REX5YPHX.js.map +0 -1
- package/dist/chunk-RT6OILOI.js.map +0 -1
- package/dist/chunk-RZTP4IEW.js.map +0 -1
- package/dist/chunk-SHEGLZEP.js.map +0 -1
- package/dist/chunk-TBMKJ26R.js.map +0 -1
- package/dist/chunk-VSQBHPWH.js.map +0 -1
- package/dist/chunk-X5CWPX7H.js.map +0 -1
- package/dist/chunk-YSWH776Y.js +0 -13
- package/dist/chunk-YSWH776Y.js.map +0 -1
- package/dist/chunk-Z2LZ7IZ7.js.map +0 -1
- package/dist/chunk-ZIVPHYRG.js.map +0 -1
- package/dist/logger-BY28acW-.d.ts +0 -16
- /package/dist/{rateLimit-ZMIZJUZF.js.map → client/core.js.map} +0 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isTimeLimit,
|
|
3
|
+
mayConnect,
|
|
4
|
+
notifyEach,
|
|
5
|
+
retryAfterOf
|
|
6
|
+
} from "./chunk-STH5DLQP.js";
|
|
7
|
+
import {
|
|
8
|
+
CLIENT_EVENTS,
|
|
9
|
+
reservedRoomPrefix,
|
|
10
|
+
socketIdShaped
|
|
11
|
+
} from "./chunk-X4ZU4QH5.js";
|
|
12
|
+
import {
|
|
13
|
+
QuickdrawError,
|
|
14
|
+
fromWire
|
|
15
|
+
} from "./chunk-Q4OGQM5I.js";
|
|
16
|
+
import {
|
|
17
|
+
isRecord
|
|
18
|
+
} from "./chunk-QSU47XEX.js";
|
|
19
|
+
|
|
20
|
+
// src/client/call.ts
|
|
21
|
+
var UNSENT_TIMEOUT = "operation has timed out";
|
|
22
|
+
function isNotModified(result) {
|
|
23
|
+
return result.nm === true;
|
|
24
|
+
}
|
|
25
|
+
function cancelledError() {
|
|
26
|
+
return new QuickdrawError("CANCELLED", "The call was cancelled");
|
|
27
|
+
}
|
|
28
|
+
function internalError(message) {
|
|
29
|
+
return new QuickdrawError("INTERNAL", message);
|
|
30
|
+
}
|
|
31
|
+
var lostInFlight = /* @__PURE__ */ new WeakSet();
|
|
32
|
+
function isUnknownOutcome(error) {
|
|
33
|
+
return error instanceof QuickdrawError && (error.code === "TIMEOUT" || lostInFlight.has(error));
|
|
34
|
+
}
|
|
35
|
+
function lostError() {
|
|
36
|
+
const error = internalError("No answer: the connection to the server is down");
|
|
37
|
+
lostInFlight.add(error);
|
|
38
|
+
return error;
|
|
39
|
+
}
|
|
40
|
+
function refusedBeforeSending(connection, kind, signal) {
|
|
41
|
+
if (signal?.aborted === true) {
|
|
42
|
+
return cancelledError();
|
|
43
|
+
}
|
|
44
|
+
if (!connection.socket.connected && !mayConnect(connection)) {
|
|
45
|
+
return internalError("Not connected to the server");
|
|
46
|
+
}
|
|
47
|
+
const remaining = connection.backoffRemaining(kind);
|
|
48
|
+
if (remaining > 0) {
|
|
49
|
+
return new QuickdrawError(
|
|
50
|
+
"RATE_LIMITED",
|
|
51
|
+
`Waiting before more ${kind} calls: the server answered RATE_LIMITED`,
|
|
52
|
+
{ retryAfterMs: Math.ceil(remaining) }
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
return void 0;
|
|
56
|
+
}
|
|
57
|
+
function envelopeOf(id, request) {
|
|
58
|
+
return {
|
|
59
|
+
id,
|
|
60
|
+
s: request.service,
|
|
61
|
+
m: request.method,
|
|
62
|
+
...request.input === void 0 ? {} : { i: request.input },
|
|
63
|
+
...request.v === void 0 ? {} : { v: request.v }
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function readReply(connection, kind, reply) {
|
|
67
|
+
if (isRecord(reply) && reply.ok === true) {
|
|
68
|
+
const versioned = typeof reply.v === "string" || typeof reply.v === "number";
|
|
69
|
+
if (reply.nm === true && !versioned) {
|
|
70
|
+
return internalError("The server answered not modified without a version");
|
|
71
|
+
}
|
|
72
|
+
return reply;
|
|
73
|
+
}
|
|
74
|
+
if (isRecord(reply) && reply.ok === false) {
|
|
75
|
+
const error = fromWire(reply.e);
|
|
76
|
+
if (error.code === "RATE_LIMITED") {
|
|
77
|
+
connection.reportRateLimited(kind, retryAfterOf(error));
|
|
78
|
+
}
|
|
79
|
+
return error;
|
|
80
|
+
}
|
|
81
|
+
return internalError("The server's reply is not a call reply");
|
|
82
|
+
}
|
|
83
|
+
function isQueuedCall(data, id) {
|
|
84
|
+
return Array.isArray(data) && data[0] === CLIENT_EVENTS.call && isRecord(data[1]) && data[1].id === id;
|
|
85
|
+
}
|
|
86
|
+
function cancelCall(socket, id) {
|
|
87
|
+
const queued = socket.sendBuffer.findIndex((packet) => isQueuedCall(packet.data, id));
|
|
88
|
+
if (queued >= 0) {
|
|
89
|
+
socket.sendBuffer.splice(queued, 1);
|
|
90
|
+
} else if (socket.connected) {
|
|
91
|
+
socket.emit(CLIENT_EVENTS.cancel, { id });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function call(connection, request) {
|
|
95
|
+
const kind = request.kind ?? "query";
|
|
96
|
+
const { signal } = request;
|
|
97
|
+
const refused = refusedBeforeSending(connection, kind, signal);
|
|
98
|
+
if (refused !== void 0) {
|
|
99
|
+
return Promise.reject(refused);
|
|
100
|
+
}
|
|
101
|
+
const { socket } = connection;
|
|
102
|
+
const timeoutMs = request.timeoutMs ?? connection.timeoutMs;
|
|
103
|
+
if (!isTimeLimit(timeoutMs)) {
|
|
104
|
+
return Promise.reject(
|
|
105
|
+
new TypeError(
|
|
106
|
+
"call: timeoutMs must be a number of milliseconds, above 0 and at most 2^31 - 1"
|
|
107
|
+
)
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
const id = connection.nextCallId();
|
|
111
|
+
return new Promise((resolve, reject) => {
|
|
112
|
+
let settled = false;
|
|
113
|
+
const settle = (outcome) => {
|
|
114
|
+
if (settled) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
settled = true;
|
|
118
|
+
signal?.removeEventListener("abort", onAbort);
|
|
119
|
+
if (outcome instanceof QuickdrawError) {
|
|
120
|
+
reject(outcome);
|
|
121
|
+
} else {
|
|
122
|
+
notifyEach([request.onReply], (onReply) => {
|
|
123
|
+
onReply?.(outcome);
|
|
124
|
+
});
|
|
125
|
+
resolve(outcome);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
function onAbort() {
|
|
129
|
+
cancelCall(socket, id);
|
|
130
|
+
settle(cancelledError());
|
|
131
|
+
}
|
|
132
|
+
socket.timeout(timeoutMs).emit(CLIENT_EVENTS.call, envelopeOf(id, request), (error, reply) => {
|
|
133
|
+
if (error === null) {
|
|
134
|
+
settle(readReply(connection, kind, reply));
|
|
135
|
+
} else if (error instanceof QuickdrawError) {
|
|
136
|
+
settle(error);
|
|
137
|
+
} else if (socket.connected) {
|
|
138
|
+
settle(new QuickdrawError("TIMEOUT", `No answer within ${timeoutMs} ms`));
|
|
139
|
+
} else if (error.message === UNSENT_TIMEOUT) {
|
|
140
|
+
settle(internalError("No answer: the connection to the server is down"));
|
|
141
|
+
} else {
|
|
142
|
+
settle(lostError());
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
async function callData(connection, request) {
|
|
149
|
+
const result = await call(connection, request);
|
|
150
|
+
if (isNotModified(result)) {
|
|
151
|
+
throw internalError("The server answered not modified to a call that sent no version");
|
|
152
|
+
}
|
|
153
|
+
return result.d;
|
|
154
|
+
}
|
|
155
|
+
function shouldRetry(failureCount, error) {
|
|
156
|
+
return failureCount < 1 && (!(error instanceof QuickdrawError) || error.code === "INTERNAL");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// src/client/host/rooms.ts
|
|
160
|
+
function appRoom(value) {
|
|
161
|
+
return typeof value === "string" && value !== "" && reservedRoomPrefix(value) === void 0 && !socketIdShaped(value) ? value : void 0;
|
|
162
|
+
}
|
|
163
|
+
function computed(room, value) {
|
|
164
|
+
try {
|
|
165
|
+
return appRoom(room(value));
|
|
166
|
+
} catch {
|
|
167
|
+
return void 0;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function channelRoomOf(def, payload, rooms) {
|
|
171
|
+
const room = def.requires?.room;
|
|
172
|
+
if (typeof room === "string") {
|
|
173
|
+
return room;
|
|
174
|
+
}
|
|
175
|
+
if (typeof room === "function") {
|
|
176
|
+
return computed(room, payload);
|
|
177
|
+
}
|
|
178
|
+
if (typeof room === "object") {
|
|
179
|
+
for (const known of rooms) {
|
|
180
|
+
if (known.startsWith(room.prefix)) {
|
|
181
|
+
return known;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return void 0;
|
|
186
|
+
}
|
|
187
|
+
function streamRoomOf(def, scope) {
|
|
188
|
+
const access = typeof def.access === "object" ? def.access : void 0;
|
|
189
|
+
const room = access?.room;
|
|
190
|
+
return typeof room === "function" ? computed(room, scope) : void 0;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export {
|
|
194
|
+
isNotModified,
|
|
195
|
+
isUnknownOutcome,
|
|
196
|
+
call,
|
|
197
|
+
callData,
|
|
198
|
+
shouldRetry,
|
|
199
|
+
channelRoomOf,
|
|
200
|
+
streamRoomOf
|
|
201
|
+
};
|
|
202
|
+
//# sourceMappingURL=chunk-NX2V6SIL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client/call.ts","../src/client/host/rooms.ts"],"sourcesContent":["// One method call over a client connection (RFC 0003 sections 8.2, 9 and\n// 11.2): a `qd:call` envelope with a fresh id, answered through Socket.IO's\n// acknowledgement. 4.1 sent one event per method and resolved the\n// `{ success, data }` reply (4.1 `src/client/useServiceQuery.ts:94-121`).\n//\n// - A failed call rejects with the `QuickdrawError` the reply carries.\n// `RATE_LIMITED` also starts the connection's backoff for the call's kind,\n// and while it lasts a call of that kind fails at once, without being\n// sent, so a client that is being limited stops spending the budget.\n// - Aborting the signal rejects with `CANCELLED` and sends `qd:cancel`; a\n// call still waiting in Socket.IO's send buffer is dropped instead, so it\n// never reaches the server.\n// - No answer within the time limit rejects with `TIMEOUT`. It is never\n// retried here: the server may still be running the call.\n// - A connection that drops before the answer, or is not open at all,\n// rejects with `INTERNAL`. A call made while the socket reconnects, or\n// while the connection waits to connect again after the server could not\n// authenticate it (`mayConnect`), waits in Socket.IO's send buffer, within\n// its time limit; new credentials meanwhile fail it with `CANCELLED`\n// instead of sending it as them (`connection.ts`).\n// - A `TIMEOUT`, and the `INTERNAL` of a call whose connection dropped after\n// it was sent, leave its outcome unknown: the server may have run it, and\n// may still be running it. `isUnknownOutcome` tells them from refusals, so\n// an optimistic addition waits for its scope's next load instead of being\n// refused (`optimisticCall.ts`).\n// - A reply `{ ok: true, nm: true, v }` resolves as it is: the version the\n// caller sent is current, and the caller keeps its copy.\n//\n// React-free: the hooks call through here, and so can any other client.\n\nimport type { MethodKind } from \"../contract/methods\";\nimport { CLIENT_EVENTS } from \"../contract/names\";\nimport type {\n CallEnvelope,\n CallId,\n CallNotModified,\n CallSuccess,\n Version,\n} from \"../protocol/envelope\";\nimport { QuickdrawError, fromWire } from \"../protocol/errors\";\nimport { isRecord } from \"../protocol/guards\";\nimport { retryAfterOf } from \"./backoff\";\nimport {\n isTimeLimit,\n mayConnect,\n type QuickdrawConnection,\n type QuickdrawSocket,\n} from \"./connection\";\nimport { notifyEach } from \"./watch\";\n\n/**\n * What Socket.IO's client fails an acknowledgement with when its time limit\n * passes; with the socket down, the packet was still in its send buffer,\n * which drops it. Any other failure while the socket is down (it says \"socket\n * has been disconnected\") came after the packet was sent.\n */\nconst UNSENT_TIMEOUT = \"operation has timed out\";\n\n/** One call, as {@link call} takes it. */\nexport interface CallRequest {\n /** The service's name on the wire: the contract's `name`. */\n readonly service: string;\n readonly method: string;\n /** The input; left out of the envelope when `undefined`. */\n readonly input?: unknown;\n /** The method's kind, which picks the backoff a `RATE_LIMITED` answer starts. Default `\"query\"`. */\n readonly kind?: MethodKind;\n /** Aborting it cancels the call. */\n readonly signal?: AbortSignal;\n /** How long to wait for the answer. Default: the connection's `timeoutMs`. */\n readonly timeoutMs?: number;\n /** The version of the result the caller holds; the server answers \"not modified\" while it is current. */\n readonly v?: Version;\n /**\n * Called with the result the moment the reply arrives, before any frame\n * the server sent after it is handled; the returned promise settles only\n * after more microtasks, and a client on Node can handle several frames in\n * between. What must follow reply order goes here: an optimistic layer\n * ends at the first newer frame after its call's reply.\n */\n readonly onReply?: (result: CallResult) => void;\n}\n\n/** What a call resolves with: the data, or \"not modified\" when the `v` it sent is current. */\nexport type CallResult<Output = unknown> = CallSuccess<Output> | CallNotModified;\n\n/** True when the server answered that the caller's version is current. */\nexport function isNotModified(result: CallResult): result is CallNotModified {\n return result.nm === true;\n}\n\n/** The error a cancelled call rejects with. */\nfunction cancelledError(): QuickdrawError {\n return new QuickdrawError(\"CANCELLED\", \"The call was cancelled\");\n}\n\nfunction internalError(message: string): QuickdrawError {\n return new QuickdrawError(\"INTERNAL\", message);\n}\n\n/** The errors of calls whose connection dropped after they were sent: their outcome is unknown. */\nconst lostInFlight = new WeakSet<QuickdrawError>();\n\n/**\n * True when `error` leaves a call's outcome unknown: a `TIMEOUT` (the\n * server may still be running it, or ran it and the answer was lost), or the\n * `INTERNAL` of a call whose connection dropped after it was sent. The write\n * may have been made: before sending it again, make sure the call is\n * idempotent (a create that carries an id the client made, which the server\n * keeps, fails `CONFLICT` the second time instead of writing a second row).\n * False for a refusal, and for a call that was never sent.\n *\n * @example\n * onError: (error) => setStatus(isUnknownOutcome(error) ? \"checking\" : \"failed\")\n */\nexport function isUnknownOutcome(error: unknown): boolean {\n return error instanceof QuickdrawError && (error.code === \"TIMEOUT\" || lostInFlight.has(error));\n}\n\n/** The error of a call whose connection dropped after it was sent. */\nfunction lostError(): QuickdrawError {\n const error = internalError(\"No answer: the connection to the server is down\");\n lostInFlight.add(error);\n return error;\n}\n\n/** Why a call fails before it is sent, if it does. */\nfunction refusedBeforeSending(\n connection: QuickdrawConnection,\n kind: MethodKind,\n signal: AbortSignal | undefined,\n): QuickdrawError | undefined {\n if (signal?.aborted === true) {\n return cancelledError();\n }\n if (!connection.socket.connected && !mayConnect(connection)) {\n return internalError(\"Not connected to the server\");\n }\n const remaining = connection.backoffRemaining(kind);\n if (remaining > 0) {\n return new QuickdrawError(\n \"RATE_LIMITED\",\n `Waiting before more ${kind} calls: the server answered RATE_LIMITED`,\n { retryAfterMs: Math.ceil(remaining) },\n );\n }\n return undefined;\n}\n\nfunction envelopeOf(id: CallId, request: CallRequest): CallEnvelope {\n return {\n id,\n s: request.service,\n m: request.method,\n ...(request.input === undefined ? {} : { i: request.input }),\n ...(request.v === undefined ? {} : { v: request.v }),\n };\n}\n\n/** The result or error a reply stands for; `RATE_LIMITED` starts the kind's backoff. */\nfunction readReply(\n connection: QuickdrawConnection,\n kind: MethodKind,\n reply: unknown,\n): CallResult | QuickdrawError {\n if (isRecord(reply) && reply.ok === true) {\n const versioned = typeof reply.v === \"string\" || typeof reply.v === \"number\";\n if (reply.nm === true && !versioned) {\n return internalError(\"The server answered not modified without a version\");\n }\n return reply as unknown as CallResult;\n }\n if (isRecord(reply) && reply.ok === false) {\n const error = fromWire(reply.e);\n if (error.code === \"RATE_LIMITED\") {\n connection.reportRateLimited(kind, retryAfterOf(error));\n }\n return error;\n }\n return internalError(\"The server's reply is not a call reply\");\n}\n\n/** True when a send-buffer packet is the `qd:call` frame of call `id`. */\nfunction isQueuedCall(data: unknown, id: CallId): boolean {\n return (\n Array.isArray(data) && data[0] === CLIENT_EVENTS.call && isRecord(data[1]) && data[1].id === id\n );\n}\n\n/** Drops the call from Socket.IO's send buffer, or else asks the server to cancel it. */\nfunction cancelCall(socket: QuickdrawSocket, id: CallId): void {\n const queued = socket.sendBuffer.findIndex((packet) => isQueuedCall(packet.data, id));\n if (queued >= 0) {\n socket.sendBuffer.splice(queued, 1);\n } else if (socket.connected) {\n socket.emit(CLIENT_EVENTS.cancel, { id });\n }\n}\n\n/**\n * Calls `request.method` of `request.service` over `connection`. Resolves\n * with `{ ok: true, d, v? }`, or `{ ok: true, nm: true, v }` when the `v` it\n * sent is current; rejects with a `QuickdrawError` (see the top of this file\n * for which code when).\n *\n * @example\n * const reply = await call(connection, { service: \"taskService\", method: \"get\", input: { id } });\n * const task = isNotModified(reply) ? cached : reply.d;\n */\nexport function call<Output = unknown>(\n connection: QuickdrawConnection,\n request: CallRequest,\n): Promise<CallResult<Output>> {\n const kind = request.kind ?? \"query\";\n const { signal } = request;\n const refused = refusedBeforeSending(connection, kind, signal);\n if (refused !== undefined) {\n return Promise.reject(refused);\n }\n const { socket } = connection;\n const timeoutMs = request.timeoutMs ?? connection.timeoutMs;\n if (!isTimeLimit(timeoutMs)) {\n return Promise.reject(\n new TypeError(\n \"call: timeoutMs must be a number of milliseconds, above 0 and at most 2^31 - 1\",\n ),\n );\n }\n const id = connection.nextCallId();\n return new Promise<CallResult<Output>>((resolve, reject) => {\n let settled = false;\n const settle = (outcome: CallResult | QuickdrawError): void => {\n if (settled) {\n return;\n }\n settled = true;\n signal?.removeEventListener(\"abort\", onAbort);\n if (outcome instanceof QuickdrawError) {\n reject(outcome);\n } else {\n notifyEach([request.onReply], (onReply) => {\n onReply?.(outcome);\n });\n resolve(outcome as CallResult<Output>);\n }\n };\n function onAbort(): void {\n cancelCall(socket, id);\n settle(cancelledError());\n }\n socket\n .timeout(timeoutMs)\n .emit(CLIENT_EVENTS.call, envelopeOf(id, request), (error: Error | null, reply: unknown) => {\n if (error === null) {\n settle(readReply(connection, kind, reply));\n } else if (error instanceof QuickdrawError) {\n // Failed by the connection before it was sent (new credentials).\n settle(error);\n } else if (socket.connected) {\n settle(new QuickdrawError(\"TIMEOUT\", `No answer within ${timeoutMs} ms`));\n } else if (error.message === UNSENT_TIMEOUT) {\n // Still in the send buffer when its time ran out: Socket.IO drops it unsent.\n settle(internalError(\"No answer: the connection to the server is down\"));\n } else {\n // Sent, then the connection dropped: Socket.IO fails the acknowledgements it waits for.\n settle(lostError());\n }\n });\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\n/**\n * Calls a method and resolves with its data. For a caller that sends no\n * version, which is never answered \"not modified\".\n */\nexport async function callData<Output = unknown>(\n connection: QuickdrawConnection,\n request: Omit<CallRequest, \"v\">,\n): Promise<Output> {\n const result = await call<Output>(connection, request);\n if (isNotModified(result)) {\n throw internalError(\"The server answered not modified to a call that sent no version\");\n }\n return result.d;\n}\n\n/**\n * The default `retry` of query hooks: one more attempt after an `INTERNAL`\n * error, which includes a dropped connection, or an error that is not a\n * `QuickdrawError`; none for any other code. A `TIMEOUT` is not retried,\n * because the server may still be running the call, and `RATE_LIMITED`\n * waits for the backoff instead.\n */\nexport function shouldRetry(failureCount: number, error: unknown): boolean {\n return failureCount < 1 && (!(error instanceof QuickdrawError) || error.code === \"INTERNAL\");\n}\n","// The app room a host-served member names (host mode, RFC 0003 section\n// 12.5), read from the contract as the server reads it: a channel's\n// `requires: { room }` (a name, a function of the payload, or `{ prefix }`)\n// and a stream's `access: { room: (scope) => room }`. A computed name that\n// is not a string, is empty, is the framework's (`qd:`, `user:`) or has the\n// shape of a socket id names no room. The peer side asks which host to send\n// to; the host side checks that a message or a subscribe is for its room.\n//\n// React-free.\n\nimport { reservedRoomPrefix, socketIdShaped } from \"../../contract/names\";\nimport type { ChannelDef, StreamDef } from \"../../contract/realtime\";\n\n/** `value`, when it can name an app room. */\nfunction appRoom(value: unknown): string | undefined {\n return typeof value === \"string\" &&\n value !== \"\" &&\n reservedRoomPrefix(value) === undefined &&\n !socketIdShaped(value)\n ? value\n : undefined;\n}\n\n/** Calls a room function of the contract; one that throws names no room. */\nfunction computed(room: unknown, value: unknown): string | undefined {\n try {\n return appRoom((room as (input: unknown) => unknown)(value));\n } catch {\n return undefined;\n }\n}\n\n/**\n * The room a host-served channel's message is for: its requirement's name,\n * the one it computes from `payload`, or for `{ prefix }` the first of\n * `rooms` (the rooms whose host is known) that starts with it.\n */\nexport function channelRoomOf(\n def: ChannelDef,\n payload: unknown,\n rooms: Iterable<string>,\n): string | undefined {\n const room = def.requires?.room;\n if (typeof room === \"string\") {\n return room;\n }\n if (typeof room === \"function\") {\n return computed(room, payload);\n }\n if (typeof room === \"object\") {\n for (const known of rooms) {\n if (known.startsWith(room.prefix)) {\n return known;\n }\n }\n }\n return undefined;\n}\n\n/** The room whose host serves a host-served stream's feed of `scope`. */\nexport function streamRoomOf(def: StreamDef, scope: string): string | undefined {\n const access = typeof def.access === \"object\" ? def.access : undefined;\n const room = access?.room;\n return typeof room === \"function\" ? computed(room, scope) : undefined;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -10,23 +10,18 @@ import {
|
|
|
10
10
|
createBinding,
|
|
11
11
|
createInvalidationCoordinator,
|
|
12
12
|
createMutationTrace,
|
|
13
|
-
createQuickdrawConnection,
|
|
14
13
|
entityScopes,
|
|
15
14
|
entryQuery,
|
|
16
15
|
feedKey,
|
|
17
16
|
invalidateWith,
|
|
18
|
-
isTimeLimit,
|
|
19
17
|
isWatchedQuery,
|
|
20
18
|
liveDataOf,
|
|
21
19
|
loopGuardOf,
|
|
22
20
|
newItem,
|
|
23
|
-
notifyEach,
|
|
24
21
|
overlaysOf,
|
|
25
22
|
reconnectJitter,
|
|
26
23
|
refetchOnAccessChanges,
|
|
27
24
|
registerQuery,
|
|
28
|
-
reloadOncePerSession,
|
|
29
|
-
retryAfterOf,
|
|
30
25
|
searchCall,
|
|
31
26
|
searchTargetOf,
|
|
32
27
|
serverStateOf,
|
|
@@ -43,167 +38,45 @@ import {
|
|
|
43
38
|
useQuickdrawContext,
|
|
44
39
|
userOf,
|
|
45
40
|
viewPredicate
|
|
46
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-64I6MYBC.js";
|
|
47
42
|
import {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
43
|
+
call,
|
|
44
|
+
callData,
|
|
45
|
+
channelRoomOf,
|
|
46
|
+
isNotModified,
|
|
47
|
+
isUnknownOutcome,
|
|
48
|
+
shouldRetry,
|
|
49
|
+
streamRoomOf
|
|
50
|
+
} from "./chunk-NX2V6SIL.js";
|
|
52
51
|
import {
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
createQuickdrawConnection,
|
|
53
|
+
hostLinksOf,
|
|
54
|
+
hostsOf,
|
|
55
|
+
mayConnect,
|
|
56
|
+
reloadOncePerSession
|
|
57
|
+
} from "./chunk-STH5DLQP.js";
|
|
55
58
|
import {
|
|
56
59
|
buildCaller,
|
|
57
60
|
collectionKey,
|
|
58
61
|
entityKey,
|
|
59
62
|
methodKey,
|
|
60
63
|
methodKeyPrefix
|
|
61
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-IIQ3WMJK.js";
|
|
65
|
+
import {
|
|
66
|
+
CLIENT_EVENTS,
|
|
67
|
+
SERVICE_TOPIC,
|
|
68
|
+
collectionTopic
|
|
69
|
+
} from "./chunk-X4ZU4QH5.js";
|
|
70
|
+
import {
|
|
71
|
+
isHostServed,
|
|
72
|
+
isScopedStream
|
|
73
|
+
} from "./chunk-GYLWEJHW.js";
|
|
74
|
+
import {
|
|
75
|
+
QuickdrawError
|
|
76
|
+
} from "./chunk-Q4OGQM5I.js";
|
|
62
77
|
import {
|
|
63
|
-
QuickdrawError,
|
|
64
|
-
fromWire,
|
|
65
78
|
isRecord
|
|
66
|
-
} from "./chunk-
|
|
67
|
-
|
|
68
|
-
// src/client/call.ts
|
|
69
|
-
var UNSENT_TIMEOUT = "operation has timed out";
|
|
70
|
-
function isNotModified(result) {
|
|
71
|
-
return result.nm === true;
|
|
72
|
-
}
|
|
73
|
-
function cancelledError() {
|
|
74
|
-
return new QuickdrawError("CANCELLED", "The call was cancelled");
|
|
75
|
-
}
|
|
76
|
-
function internalError(message) {
|
|
77
|
-
return new QuickdrawError("INTERNAL", message);
|
|
78
|
-
}
|
|
79
|
-
var lostInFlight = /* @__PURE__ */ new WeakSet();
|
|
80
|
-
function isUnknownOutcome(error) {
|
|
81
|
-
return error instanceof QuickdrawError && (error.code === "TIMEOUT" || lostInFlight.has(error));
|
|
82
|
-
}
|
|
83
|
-
function lostError() {
|
|
84
|
-
const error = internalError("No answer: the connection to the server is down");
|
|
85
|
-
lostInFlight.add(error);
|
|
86
|
-
return error;
|
|
87
|
-
}
|
|
88
|
-
function refusedBeforeSending(connection, kind, signal) {
|
|
89
|
-
if (signal?.aborted === true) {
|
|
90
|
-
return cancelledError();
|
|
91
|
-
}
|
|
92
|
-
const { socket } = connection;
|
|
93
|
-
if (!socket.connected && !socket.active) {
|
|
94
|
-
return internalError("Not connected to the server");
|
|
95
|
-
}
|
|
96
|
-
const remaining = connection.backoffRemaining(kind);
|
|
97
|
-
if (remaining > 0) {
|
|
98
|
-
return new QuickdrawError(
|
|
99
|
-
"RATE_LIMITED",
|
|
100
|
-
`Waiting before more ${kind} calls: the server answered RATE_LIMITED`,
|
|
101
|
-
{ retryAfterMs: Math.ceil(remaining) }
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
return void 0;
|
|
105
|
-
}
|
|
106
|
-
function envelopeOf(id, request) {
|
|
107
|
-
return {
|
|
108
|
-
id,
|
|
109
|
-
s: request.service,
|
|
110
|
-
m: request.method,
|
|
111
|
-
...request.input === void 0 ? {} : { i: request.input },
|
|
112
|
-
...request.v === void 0 ? {} : { v: request.v }
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
function readReply(connection, kind, reply) {
|
|
116
|
-
if (isRecord(reply) && reply.ok === true) {
|
|
117
|
-
const versioned = typeof reply.v === "string" || typeof reply.v === "number";
|
|
118
|
-
if (reply.nm === true && !versioned) {
|
|
119
|
-
return internalError("The server answered not modified without a version");
|
|
120
|
-
}
|
|
121
|
-
return reply;
|
|
122
|
-
}
|
|
123
|
-
if (isRecord(reply) && reply.ok === false) {
|
|
124
|
-
const error = fromWire(reply.e);
|
|
125
|
-
if (error.code === "RATE_LIMITED") {
|
|
126
|
-
connection.reportRateLimited(kind, retryAfterOf(error));
|
|
127
|
-
}
|
|
128
|
-
return error;
|
|
129
|
-
}
|
|
130
|
-
return internalError("The server's reply is not a call reply");
|
|
131
|
-
}
|
|
132
|
-
function isQueuedCall(data, id) {
|
|
133
|
-
return Array.isArray(data) && data[0] === CLIENT_EVENTS.call && isRecord(data[1]) && data[1].id === id;
|
|
134
|
-
}
|
|
135
|
-
function cancelCall(socket, id) {
|
|
136
|
-
const queued = socket.sendBuffer.findIndex((packet) => isQueuedCall(packet.data, id));
|
|
137
|
-
if (queued >= 0) {
|
|
138
|
-
socket.sendBuffer.splice(queued, 1);
|
|
139
|
-
} else if (socket.connected) {
|
|
140
|
-
socket.emit(CLIENT_EVENTS.cancel, { id });
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
function call(connection, request) {
|
|
144
|
-
const kind = request.kind ?? "query";
|
|
145
|
-
const { signal } = request;
|
|
146
|
-
const refused = refusedBeforeSending(connection, kind, signal);
|
|
147
|
-
if (refused !== void 0) {
|
|
148
|
-
return Promise.reject(refused);
|
|
149
|
-
}
|
|
150
|
-
const { socket } = connection;
|
|
151
|
-
const timeoutMs = request.timeoutMs ?? connection.timeoutMs;
|
|
152
|
-
if (!isTimeLimit(timeoutMs)) {
|
|
153
|
-
return Promise.reject(
|
|
154
|
-
new TypeError(
|
|
155
|
-
"call: timeoutMs must be a number of milliseconds, above 0 and at most 2^31 - 1"
|
|
156
|
-
)
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
const id = connection.nextCallId();
|
|
160
|
-
return new Promise((resolve, reject) => {
|
|
161
|
-
let settled = false;
|
|
162
|
-
const settle = (outcome) => {
|
|
163
|
-
if (settled) {
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
settled = true;
|
|
167
|
-
signal?.removeEventListener("abort", onAbort);
|
|
168
|
-
if (outcome instanceof QuickdrawError) {
|
|
169
|
-
reject(outcome);
|
|
170
|
-
} else {
|
|
171
|
-
notifyEach([request.onReply], (onReply) => {
|
|
172
|
-
onReply?.(outcome);
|
|
173
|
-
});
|
|
174
|
-
resolve(outcome);
|
|
175
|
-
}
|
|
176
|
-
};
|
|
177
|
-
function onAbort() {
|
|
178
|
-
cancelCall(socket, id);
|
|
179
|
-
settle(cancelledError());
|
|
180
|
-
}
|
|
181
|
-
socket.timeout(timeoutMs).emit(CLIENT_EVENTS.call, envelopeOf(id, request), (error, reply) => {
|
|
182
|
-
if (error === null) {
|
|
183
|
-
settle(readReply(connection, kind, reply));
|
|
184
|
-
} else if (error instanceof QuickdrawError) {
|
|
185
|
-
settle(error);
|
|
186
|
-
} else if (socket.connected) {
|
|
187
|
-
settle(new QuickdrawError("TIMEOUT", `No answer within ${timeoutMs} ms`));
|
|
188
|
-
} else if (error.message === UNSENT_TIMEOUT) {
|
|
189
|
-
settle(internalError("No answer: the connection to the server is down"));
|
|
190
|
-
} else {
|
|
191
|
-
settle(lostError());
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
async function callData(connection, request) {
|
|
198
|
-
const result = await call(connection, request);
|
|
199
|
-
if (isNotModified(result)) {
|
|
200
|
-
throw internalError("The server answered not modified to a call that sent no version");
|
|
201
|
-
}
|
|
202
|
-
return result.d;
|
|
203
|
-
}
|
|
204
|
-
function shouldRetry(failureCount, error) {
|
|
205
|
-
return failureCount < 1 && (!(error instanceof QuickdrawError) || error.code === "INTERNAL");
|
|
206
|
-
}
|
|
79
|
+
} from "./chunk-QSU47XEX.js";
|
|
207
80
|
|
|
208
81
|
// src/client/live/useSearch.ts
|
|
209
82
|
import { useQuery as useQuery2 } from "@tanstack/react-query";
|
|
@@ -310,7 +183,7 @@ async function fetchVersioned(connection, queryClient, query, signal) {
|
|
|
310
183
|
return fetchFresh(connection, query, signal);
|
|
311
184
|
}
|
|
312
185
|
async function helloKnown(connection, signal) {
|
|
313
|
-
const ready = () => connection.getState().hello !== null || !connection
|
|
186
|
+
const ready = () => connection.getState().hello !== null || !mayConnect(connection) || signal?.aborted === true;
|
|
314
187
|
if (ready()) {
|
|
315
188
|
return;
|
|
316
189
|
}
|
|
@@ -356,7 +229,9 @@ async function fetchMethodQuery(connection, queryClient, query, signal) {
|
|
|
356
229
|
}
|
|
357
230
|
|
|
358
231
|
// src/client/queryHooks.ts
|
|
359
|
-
import {
|
|
232
|
+
import {
|
|
233
|
+
hashKey
|
|
234
|
+
} from "@tanstack/react-query";
|
|
360
235
|
import { useEffect, useMemo, useRef, useSyncExternalStore } from "react";
|
|
361
236
|
function watchedModelsOf(target) {
|
|
362
237
|
const { watch } = target;
|
|
@@ -465,6 +340,19 @@ function useOverlaySelect(queryClient, target, select) {
|
|
|
465
340
|
};
|
|
466
341
|
}, [shape, view, select]);
|
|
467
342
|
}
|
|
343
|
+
function placeholderFromCache(queryClient, placeholderData) {
|
|
344
|
+
if (typeof placeholderData !== "function") {
|
|
345
|
+
return placeholderData;
|
|
346
|
+
}
|
|
347
|
+
const asked = placeholderData;
|
|
348
|
+
const fromCache = (previousData, previousQuery) => previousQuery === void 0 || queryClient.getQueryCache().get(previousQuery.queryHash) === previousQuery ? asked(previousData, previousQuery) : void 0;
|
|
349
|
+
return fromCache;
|
|
350
|
+
}
|
|
351
|
+
function placeholderOption(queryClient, queryKey, options) {
|
|
352
|
+
const keyDefaults = queryClient.getQueryDefaults(queryKey);
|
|
353
|
+
const given = "placeholderData" in options ? options.placeholderData : Object.hasOwn(keyDefaults, "placeholderData") ? keyDefaults.placeholderData : queryClient.getDefaultOptions().queries?.placeholderData;
|
|
354
|
+
return placeholderFromCache(queryClient, given);
|
|
355
|
+
}
|
|
468
356
|
function hiddenResult(result) {
|
|
469
357
|
return {
|
|
470
358
|
...result,
|
|
@@ -725,6 +613,7 @@ function useMethodQuery(target, input, options = {}) {
|
|
|
725
613
|
enabled: live ? enabled ?? true : false,
|
|
726
614
|
retry: retry ?? shouldRetry,
|
|
727
615
|
structuralSharing: shareKeepingVersion(structuralSharing),
|
|
616
|
+
placeholderData: placeholderOption(queryClient, queryKey, options),
|
|
728
617
|
...shown2 === void 0 ? {} : { select: shown2 }
|
|
729
618
|
});
|
|
730
619
|
return awaiting ? hiddenResult(result) : result;
|
|
@@ -939,17 +828,25 @@ function clientAdminNamespace(contract, methods) {
|
|
|
939
828
|
|
|
940
829
|
// src/client/live/useChannel.ts
|
|
941
830
|
import { useCallback, useMemo as useMemo4 } from "react";
|
|
942
|
-
function useChannel(service, channel) {
|
|
831
|
+
function useChannel(service, channel, def) {
|
|
943
832
|
const { connection } = useQuickdrawContext(`${service}.${channel}.useChannel`);
|
|
944
833
|
const state = useConnectionState(connection);
|
|
945
834
|
const send = useCallback(
|
|
946
835
|
(payload) => {
|
|
947
836
|
const { socket } = connection;
|
|
948
|
-
if (socket.connected) {
|
|
949
|
-
|
|
837
|
+
if (!socket.connected) {
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
if (def !== void 0 && isHostServed(def)) {
|
|
841
|
+
const room = channelRoomOf(def, payload, hostsOf(connection).rooms.keys());
|
|
842
|
+
if (room !== void 0) {
|
|
843
|
+
hostLinksOf(connection).send(room, service, channel, payload);
|
|
844
|
+
}
|
|
845
|
+
return;
|
|
950
846
|
}
|
|
847
|
+
socket.volatile.emit(CLIENT_EVENTS.channel, [service, channel, payload]);
|
|
951
848
|
},
|
|
952
|
-
[connection, service, channel]
|
|
849
|
+
[connection, service, channel, def]
|
|
953
850
|
);
|
|
954
851
|
const isReady = state.status === "connected" && state.hello !== null;
|
|
955
852
|
return useMemo4(() => ({ send, isReady }), [send, isReady]);
|
|
@@ -1016,13 +913,16 @@ function streamMember(target) {
|
|
|
1016
913
|
}
|
|
1017
914
|
function realtimeMembers(contract) {
|
|
1018
915
|
const service = contract.name;
|
|
1019
|
-
const streams = Object.entries(contract.streams).map(([stream, def]) =>
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
916
|
+
const streams = Object.entries(contract.streams).map(([stream, def]) => {
|
|
917
|
+
const host = isHostServed(def) ? { host: (scope) => streamRoomOf(def, scope) } : {};
|
|
918
|
+
return [
|
|
919
|
+
stream,
|
|
920
|
+
streamMember(Object.freeze({ service, stream, scoped: isScopedStream(def), ...host }))
|
|
921
|
+
];
|
|
922
|
+
});
|
|
923
|
+
const channels = Object.entries(contract.channels).map(([channel, def]) => [
|
|
1024
924
|
channel,
|
|
1025
|
-
Object.freeze({ useChannel: () => useChannel(service, channel) })
|
|
925
|
+
Object.freeze({ useChannel: () => useChannel(service, channel, def) })
|
|
1026
926
|
]);
|
|
1027
927
|
const events = Object.keys(contract.events).map((event) => [
|
|
1028
928
|
event,
|
|
@@ -1244,9 +1144,11 @@ function searchMember(target, definition, contract) {
|
|
|
1244
1144
|
var RESERVED_KEYS = ["invalidate"];
|
|
1245
1145
|
function queryMember(binding, target, extra) {
|
|
1246
1146
|
const key = (input) => methodKey(target.service, target.method, input);
|
|
1147
|
+
const defaults = target.queryDefaults;
|
|
1247
1148
|
const member = Object.freeze({
|
|
1248
1149
|
...extra,
|
|
1249
|
-
|
|
1150
|
+
// The caller's options over the method's defaults (the admin kit's reads of rows: `staleTime: 0`).
|
|
1151
|
+
useQuery: (input, options) => useMethodQuery(target, input, defaults === void 0 ? options : { ...defaults, ...options }),
|
|
1250
1152
|
call: async (input, options) => await callData(connectionOf(binding, target, "call"), {
|
|
1251
1153
|
...target,
|
|
1252
1154
|
input,
|
|
@@ -1399,15 +1301,10 @@ function useQuickdraw() {
|
|
|
1399
1301
|
}
|
|
1400
1302
|
|
|
1401
1303
|
export {
|
|
1402
|
-
isNotModified,
|
|
1403
|
-
isUnknownOutcome,
|
|
1404
|
-
call,
|
|
1405
|
-
callData,
|
|
1406
|
-
shouldRetry,
|
|
1407
1304
|
useLiveData,
|
|
1408
1305
|
SEARCH_DEBOUNCE_MS,
|
|
1409
1306
|
createQuickdrawClient,
|
|
1410
1307
|
QuickdrawProvider,
|
|
1411
1308
|
useQuickdraw
|
|
1412
1309
|
};
|
|
1413
|
-
//# sourceMappingURL=chunk-
|
|
1310
|
+
//# sourceMappingURL=chunk-NZHA4TZD.js.map
|