@rpcbase/server 0.636.0 → 0.638.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/dist/{handler-C34TFH28.js → handler-Dy_L6_-U.js} +36 -8
- package/dist/handler-Dy_L6_-U.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/proxyAuth.d.ts +4 -1
- package/dist/proxyAuth.d.ts.map +1 -1
- package/dist/{queryWindow-NCe5vJHt.js → queryWindow-RHVy3D0L.js} +51 -35
- package/dist/queryWindow-RHVy3D0L.js.map +1 -0
- package/dist/rts/index.d.ts +3 -1
- package/dist/rts/index.d.ts.map +1 -1
- package/dist/rts/index.js +87 -10
- package/dist/rts/index.js.map +1 -1
- package/dist/rts/origin.d.ts +3 -0
- package/dist/rts/origin.d.ts.map +1 -0
- package/dist/syncAuthenticatedSession.d.ts +2 -0
- package/dist/syncAuthenticatedSession.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/uploads/api/files/handlers/getFile.d.ts.map +1 -1
- package/dist/uploads/fileContentHeaders.d.ts +2 -0
- package/dist/uploads/fileContentHeaders.d.ts.map +1 -0
- package/dist/uploads.js +1 -1
- package/package.json +1 -1
- package/dist/handler-C34TFH28.js.map +0 -1
- package/dist/queryWindow-NCe5vJHt.js.map +0 -1
package/dist/rts/index.js
CHANGED
|
@@ -1,8 +1,27 @@
|
|
|
1
|
-
import { a as resolveRtsQueryDependencyModelNames, c as runRtsQuery, i as normalizeRtsQueryOptions, l as
|
|
1
|
+
import { a as resolveRtsQueryDependencyModelNames, c as runRtsQuery, f as getTrustedProxyAuth, i as normalizeRtsQueryOptions, l as revalidateAuthenticatedSession, s as runRtsCount, t as RTS_QUERY_WINDOW_MAX_COUNT, u as syncAuthenticatedSessionFromRequest } from "../queryWindow-RHVy3D0L.js";
|
|
2
2
|
import { models } from "@rpcbase/db";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
import { buildAbilityFromSession } from "@rpcbase/db/acl";
|
|
5
5
|
import { WebSocketServer } from "ws";
|
|
6
|
+
//#region src/rts/origin.ts
|
|
7
|
+
var isRtsOriginAllowed = (req, allowedOrigins = []) => {
|
|
8
|
+
const origin = req.headers.origin;
|
|
9
|
+
if (origin === void 0) return true;
|
|
10
|
+
try {
|
|
11
|
+
const parsed = new URL(origin);
|
|
12
|
+
if (!["http:", "https:"].includes(parsed.protocol) || parsed.origin !== origin) return false;
|
|
13
|
+
if (allowedOrigins.includes(origin)) return true;
|
|
14
|
+
const trustedProxy = getTrustedProxyAuth(req.headers);
|
|
15
|
+
const forwardedHost = trustedProxy && req.headers["x-forwarded-host"];
|
|
16
|
+
const forwardedProto = trustedProxy && req.headers["x-forwarded-proto"];
|
|
17
|
+
const host = typeof forwardedHost === "string" ? forwardedHost : req.headers.host;
|
|
18
|
+
const protocol = typeof forwardedProto === "string" ? forwardedProto === "wss" ? "https:" : forwardedProto === "ws" ? "http:" : `${forwardedProto}:` : "encrypted" in req.socket && req.socket.encrypted ? "https:" : "http:";
|
|
19
|
+
return origin === new URL(`${protocol}//${host}`).origin;
|
|
20
|
+
} catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
//#endregion
|
|
6
25
|
//#region src/rts/routes.ts
|
|
7
26
|
var routes = Object.entries({ .../* #__PURE__ */ Object.assign({ "./api/changes/handler.ts": () => import("../handler-BL-Je36s.js") }) }).reduce((acc, [path, mod]) => {
|
|
8
27
|
acc[path.replace("./api/", "@rpcbase/server/rts/api/")] = mod;
|
|
@@ -19,6 +38,7 @@ var initializedServers = /* @__PURE__ */ new WeakSet();
|
|
|
19
38
|
var customHandlers = [];
|
|
20
39
|
var sockets = /* @__PURE__ */ new Map();
|
|
21
40
|
var socketMeta = /* @__PURE__ */ new Map();
|
|
41
|
+
var socketValidators = /* @__PURE__ */ new WeakMap();
|
|
22
42
|
var socketWrappers = /* @__PURE__ */ new Map();
|
|
23
43
|
var socketCleanup = /* @__PURE__ */ new Map();
|
|
24
44
|
var socketSubscriptions = /* @__PURE__ */ new Map();
|
|
@@ -109,7 +129,11 @@ var rawToText = (raw) => {
|
|
|
109
129
|
var safeJsonParse = (raw) => JSON.parse(rawToText(raw));
|
|
110
130
|
var sendWs = (ws, message) => {
|
|
111
131
|
if (ws.readyState !== 1) return;
|
|
112
|
-
|
|
132
|
+
const validate = socketValidators.get(ws);
|
|
133
|
+
if (!validate) return;
|
|
134
|
+
validate().then((valid) => {
|
|
135
|
+
if (valid && ws.readyState === 1) ws.send(JSON.stringify(message));
|
|
136
|
+
}).catch(() => ws.close(1011, "Session validation failed"));
|
|
113
137
|
};
|
|
114
138
|
var ensureSocketErrorHandler = (socket, context) => {
|
|
115
139
|
if (socket.listenerCount("error") > 0) return;
|
|
@@ -185,13 +209,42 @@ var parseUpgradeMeta = async ({ req, url, sessionMiddleware, postSyncSessionMidd
|
|
|
185
209
|
if (!sessionUserId) throw new Error("Not signed in (missing session.user.id)");
|
|
186
210
|
const tenantId = sessionUser?.currentTenantId?.trim();
|
|
187
211
|
if (!tenantId) throw new Error("Missing current tenant in session");
|
|
212
|
+
const ability = buildAbilityFromSession({
|
|
213
|
+
tenantId,
|
|
214
|
+
session: upgradeReq.session
|
|
215
|
+
});
|
|
216
|
+
const authVersion = sessionUser?.authVersion ?? 0;
|
|
217
|
+
const rules = JSON.stringify(ability.rules);
|
|
218
|
+
if (upgradeReq.session?.save) await new Promise((resolve, reject) => {
|
|
219
|
+
upgradeReq.session.save((err) => err ? reject(err) : resolve());
|
|
220
|
+
});
|
|
221
|
+
let validation;
|
|
222
|
+
const validate = () => {
|
|
223
|
+
if (validation) return validation;
|
|
224
|
+
validation = (async () => {
|
|
225
|
+
if (upgradeReq.session?.reload) await new Promise((resolve, reject) => {
|
|
226
|
+
upgradeReq.session.reload((err) => err ? reject(err) : resolve());
|
|
227
|
+
});
|
|
228
|
+
const expires = upgradeReq.session?.cookie?.expires;
|
|
229
|
+
if (expires && new Date(expires).getTime() <= Date.now()) return false;
|
|
230
|
+
await revalidateAuthenticatedSession(upgradeReq);
|
|
231
|
+
if (!upgradeReq.session?.user?.id) return false;
|
|
232
|
+
if (postSyncSessionMiddleware) await runSessionMiddleware(postSyncSessionMiddleware, upgradeReq);
|
|
233
|
+
const currentUser = upgradeReq.session?.user;
|
|
234
|
+
return currentUser?.id === sessionUserId && currentUser.currentTenantId === tenantId && (currentUser.authVersion ?? 0) === authVersion && JSON.stringify(buildAbilityFromSession({
|
|
235
|
+
tenantId,
|
|
236
|
+
session: upgradeReq.session
|
|
237
|
+
}).rules) === rules;
|
|
238
|
+
})().catch(() => false).finally(() => {
|
|
239
|
+
validation = void 0;
|
|
240
|
+
});
|
|
241
|
+
return validation;
|
|
242
|
+
};
|
|
188
243
|
return {
|
|
189
244
|
tenantId,
|
|
190
245
|
userId: sessionUserId,
|
|
191
|
-
ability
|
|
192
|
-
|
|
193
|
-
session: upgradeReq.session
|
|
194
|
-
})
|
|
246
|
+
ability,
|
|
247
|
+
validate
|
|
195
248
|
};
|
|
196
249
|
};
|
|
197
250
|
var getTenantModel = async (tenantId, modelName) => {
|
|
@@ -359,12 +412,20 @@ var hasAnyCountSubscriptionsForModel = (tenantId, modelName) => {
|
|
|
359
412
|
for (const userSubs of tenantSubs.values()) if (userSubs.get(modelName)?.size) return true;
|
|
360
413
|
return false;
|
|
361
414
|
};
|
|
415
|
+
var getValidatedSocketIds = async (socketIds) => {
|
|
416
|
+
const ids = Array.from(socketIds);
|
|
417
|
+
const valid = await Promise.all(ids.map((id) => {
|
|
418
|
+
const ws = sockets.get(id);
|
|
419
|
+
return ws ? socketValidators.get(ws)?.() : false;
|
|
420
|
+
}));
|
|
421
|
+
return ids.filter((_, index) => valid[index]);
|
|
422
|
+
};
|
|
362
423
|
var dispatchSubscriptionsForModel = async (tenantId, modelName) => {
|
|
363
424
|
const tenantSubs = subscriptions.get(tenantId);
|
|
364
425
|
if (!tenantSubs || !tenantSubs.size) return;
|
|
365
426
|
for (const userSubs of tenantSubs.values()) for (const [ownerModelName, modelSubs] of userSubs.entries()) for (const [queryKey, sub] of modelSubs.entries()) {
|
|
366
427
|
if (!subscriptionDependsOnModel(modelName, ownerModelName, sub)) continue;
|
|
367
|
-
const targetSocketIds =
|
|
428
|
+
const targetSocketIds = await getValidatedSocketIds(sub.socketIds);
|
|
368
429
|
if (!targetSocketIds.length) continue;
|
|
369
430
|
const socketId = targetSocketIds[0];
|
|
370
431
|
const ability = socketMeta.get(socketId)?.ability;
|
|
@@ -400,7 +461,7 @@ var dispatchCountSubscriptionsForModel = async (tenantId, modelName) => {
|
|
|
400
461
|
const modelSubs = userSubs.get(modelName);
|
|
401
462
|
if (!modelSubs) continue;
|
|
402
463
|
for (const [queryKey, sub] of modelSubs.entries()) {
|
|
403
|
-
const targetSocketIds =
|
|
464
|
+
const targetSocketIds = await getValidatedSocketIds(sub.socketIds);
|
|
404
465
|
if (!targetSocketIds.length) continue;
|
|
405
466
|
const socketId = targetSocketIds[0];
|
|
406
467
|
const ability = socketMeta.get(socketId)?.ability;
|
|
@@ -624,6 +685,7 @@ var cleanupSocket = (socketId) => {
|
|
|
624
685
|
var handleClientMessage = async ({ socketId, meta, message }) => {
|
|
625
686
|
const ws = sockets.get(socketId);
|
|
626
687
|
if (!ws) return;
|
|
688
|
+
if (!await socketValidators.get(ws)?.()) return;
|
|
627
689
|
if (message.type === "event") {
|
|
628
690
|
socketWrappers.get(socketId)?.dispatch(message.event, message.payload);
|
|
629
691
|
return;
|
|
@@ -884,7 +946,7 @@ var handleClientMessage = async ({ socketId, meta, message }) => {
|
|
|
884
946
|
}
|
|
885
947
|
}
|
|
886
948
|
};
|
|
887
|
-
var initRts = ({ server, path = "/rts", sessionMiddleware, postSyncSessionMiddleware, maxPayloadBytes: maxPayloadBytesArg, maxSubscriptionsPerSocket: maxSubscriptionsPerSocketArg, dispatchDebounceMs: dispatchDebounceMsArg, allowInternalModels: allowInternalModelsArg }) => {
|
|
949
|
+
var initRts = ({ server, path = "/rts", sessionMiddleware, postSyncSessionMiddleware, maxPayloadBytes: maxPayloadBytesArg, maxSubscriptionsPerSocket: maxSubscriptionsPerSocketArg, dispatchDebounceMs: dispatchDebounceMsArg, allowInternalModels: allowInternalModelsArg, allowedOrigins = (process.env.RB_RTS_ALLOWED_ORIGINS ?? "").split(",").map((value) => value.trim()).filter(Boolean) }) => {
|
|
888
950
|
if (initializedServers.has(server)) return;
|
|
889
951
|
initializedServers.add(server);
|
|
890
952
|
if (typeof maxPayloadBytesArg === "number" && Number.isFinite(maxPayloadBytesArg) && maxPayloadBytesArg > 0) maxPayloadBytes = Math.floor(maxPayloadBytesArg);
|
|
@@ -910,6 +972,10 @@ var initRts = ({ server, path = "/rts", sessionMiddleware, postSyncSessionMiddle
|
|
|
910
972
|
return;
|
|
911
973
|
}
|
|
912
974
|
if (url.pathname !== path) return;
|
|
975
|
+
if (!isRtsOriginAllowed(req, allowedOrigins)) {
|
|
976
|
+
socket.end("HTTP/1.1 403 Forbidden\r\nConnection: close\r\n\r\n");
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
913
979
|
(async () => {
|
|
914
980
|
try {
|
|
915
981
|
const meta = await parseUpgradeMeta({
|
|
@@ -962,13 +1028,24 @@ var initRts = ({ server, path = "/rts", sessionMiddleware, postSyncSessionMiddle
|
|
|
962
1028
|
const socketId = randomUUID();
|
|
963
1029
|
sockets.set(socketId, ws);
|
|
964
1030
|
socketMeta.set(socketId, meta);
|
|
1031
|
+
const validate = async () => {
|
|
1032
|
+
if (ws.readyState !== 1) return false;
|
|
1033
|
+
const valid = await meta.validate();
|
|
1034
|
+
if (!valid) ws.close(1008, "Session expired or permissions changed");
|
|
1035
|
+
return valid;
|
|
1036
|
+
};
|
|
1037
|
+
socketValidators.set(ws, validate);
|
|
965
1038
|
const wrapper = new RtsSocket({
|
|
966
1039
|
id: socketId,
|
|
967
1040
|
ws,
|
|
968
1041
|
meta
|
|
969
1042
|
});
|
|
970
1043
|
socketWrappers.set(socketId, wrapper);
|
|
971
|
-
const
|
|
1044
|
+
const validationTimer = setInterval(() => {
|
|
1045
|
+
validate();
|
|
1046
|
+
}, 3e4);
|
|
1047
|
+
validationTimer.unref();
|
|
1048
|
+
const cleanupFns = [() => clearInterval(validationTimer)];
|
|
972
1049
|
for (const handler of customHandlers) try {
|
|
973
1050
|
const cleanup = handler(wrapper);
|
|
974
1051
|
if (typeof cleanup === "function") cleanupFns.push(cleanup);
|
package/dist/rts/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/rts/routes.ts","../../src/rts/index.ts"],"sourcesContent":["export const routes = Object.entries({\n ...import.meta.glob(\"./api/**/handler.ts\"),\n}).reduce<Record<string, unknown>>((acc, [path, mod]) => {\n acc[path.replace(\"./api/\", \"@rpcbase/server/rts/api/\")] = mod\n return acc\n}, {})\n\n","import { randomUUID } from \"node:crypto\"\nimport type { IncomingMessage, Server as HttpServer } from \"node:http\"\nimport type { Socket } from \"node:net\"\n\nimport type { RequestHandler } from \"express\"\nimport type { PaginationPageInfo } from \"@rpcbase/api\"\nimport { models, type LoadModelCtx } from \"@rpcbase/db\"\nimport { buildAbilityFromSession, type AclSubjectType, type AppAbility } from \"@rpcbase/db/acl\"\nimport type { ChangeStream } from \"mongodb\"\nimport type { Model } from \"mongoose\"\nimport { WebSocketServer, type RawData, type WebSocket } from \"ws\"\n\nimport {\n normalizeRtsQueryOptions,\n resolveRtsQueryDependencyModelNames,\n runRtsCount,\n runRtsQuery,\n type RtsQueryOptions as QueryOptions,\n} from \"./queryExecutor\"\nimport { RTS_QUERY_WINDOW_MAX_COUNT } from \"./queryWindow\"\nimport { syncAuthenticatedSessionFromRequest } from \"../syncAuthenticatedSession\"\n\n\ntype JsonObject = Record<string, unknown>\n\ntype CountOptions = {\n key?: string\n}\n\ntype ClientMessage =\n | { type: \"run-query\"; modelName: string; queryKey: string; query: JsonObject; options?: QueryOptions }\n | {\n type: \"register-query\"\n modelName: string\n queryKey: string\n query: JsonObject\n options?: QueryOptions\n runInitialQuery?: boolean\n }\n | { type: \"set-query-window\"; modelName: string; queryKey: string; requestedCount: number }\n | { type: \"remove-query\"; modelName: string; queryKey: string }\n | { type: \"run-count\"; modelName: string; queryKey: string; query: JsonObject; options?: CountOptions }\n | {\n type: \"register-count\"\n modelName: string\n queryKey: string\n query: JsonObject\n options?: CountOptions\n runInitialQuery?: boolean\n }\n | { type: \"remove-count\"; modelName: string; queryKey: string }\n | { type: \"event\"; event: string; payload?: unknown }\n | { type: \"rts-message\"; channel: string; payload?: unknown }\n\ntype ServerMessage =\n | {\n type: \"query-payload\"\n modelName: string\n queryKey: string\n data?: unknown\n error?: string\n txnId?: string\n pageInfo?: PaginationPageInfo\n totalCount?: number\n window?: QueryWindowPayload\n }\n | {\n type: \"count-payload\"\n modelName: string\n queryKey: string\n count?: number\n error?: string\n txnId?: string\n }\n | { type: \"event\"; event: string; payload?: unknown }\n | { type: \"rts-message\"; channel: string; payload?: unknown }\n\nexport type PublishRtsMessageInput = {\n tenantId: string\n userId?: string\n channel: string\n payload?: unknown\n}\n\ntype SocketMeta = {\n tenantId: string\n userId: string\n ability: AppAbility\n}\n\ntype SessionUser = {\n id?: string\n currentTenantId?: string\n}\n\ntype UpgradeRequest = IncomingMessage & {\n session?: {\n user?: SessionUser\n }\n}\n\ntype Subscription = {\n query: JsonObject\n options: QueryOptions\n dependencyModelNames: string[]\n socketIds: Set<string>\n windows: Map<string, QueryWindowState>\n}\n\ntype QueryWindowPayload = {\n requestedCount: number\n version: number\n}\n\ntype QueryWindowState = QueryWindowPayload\n\ntype CountSubscription = {\n query: JsonObject\n socketIds: Set<string>\n}\n\ntype HandlerFn = (socket: RtsSocket) => void | (() => void)\n\nconst QUERY_KEY_MAX_LEN = 4096\n\nconst INTERNAL_MODEL_NAMES = new Set([\"RBRtsChange\", \"RBRtsCounter\"])\n\nconst DEFAULT_MAX_PAYLOAD_BYTES = 1024 * 1024\nconst DEFAULT_MAX_SUBSCRIPTIONS_PER_SOCKET = 256\nconst DEFAULT_DISPATCH_DEBOUNCE_MS = 25\n\nconst initializedServers = new WeakSet<HttpServer>()\nconst customHandlers: HandlerFn[] = []\n\nconst sockets = new Map<string, WebSocket>()\nconst socketMeta = new Map<string, SocketMeta>()\nconst socketWrappers = new Map<string, RtsSocket>()\nconst socketCleanup = new Map<string, Array<() => void>>()\n\nconst socketSubscriptions = new Map<string, Map<string, Set<string>>>()\nconst socketCountSubscriptions = new Map<string, Map<string, Set<string>>>()\nconst subscriptions = new Map<string, Map<string, Map<string, Map<string, Subscription>>>>()\nconst countSubscriptions = new Map<string, Map<string, Map<string, Map<string, CountSubscription>>>>()\nconst changeStreams = new Map<string, Map<string, ChangeStream>>()\nconst dispatchTimers = new Map<string, ReturnType<typeof setTimeout>>()\nconst upgradeMeta = new WeakMap<IncomingMessage, SocketMeta>()\n\nlet maxPayloadBytes = DEFAULT_MAX_PAYLOAD_BYTES\nlet maxSubscriptionsPerSocket = DEFAULT_MAX_SUBSCRIPTIONS_PER_SOCKET\nlet dispatchDebounceMs = DEFAULT_DISPATCH_DEBOUNCE_MS\nlet allowInternalModels = false\n\nconst isValidQueryWindowCount = (value: unknown): value is number =>\n typeof value === \"number\"\n && Number.isInteger(value)\n && value >= 1\n && value <= RTS_QUERY_WINDOW_MAX_COUNT\n\nclass RtsSocket {\n public readonly id: string\n public readonly tenantId: string\n public readonly userId: string\n\n private readonly ws: WebSocket\n private readonly handlers = new Map<string, Set<(payload: unknown) => void>>()\n private readonly messageHandlers = new Map<string, Set<(payload: unknown) => void>>()\n\n public constructor({\n id,\n ws,\n meta,\n }: {\n id: string\n ws: WebSocket\n meta: SocketMeta\n }) {\n this.id = id\n this.ws = ws\n this.tenantId = meta.tenantId\n this.userId = meta.userId\n }\n\n public on(event: string, handler: (payload: unknown) => void): () => void {\n const set = this.handlers.get(event) ?? new Set()\n set.add(handler)\n this.handlers.set(event, set)\n return () => this.off(event, handler)\n }\n\n public off(event: string, handler: (payload: unknown) => void): void {\n const set = this.handlers.get(event)\n if (!set) return\n set.delete(handler)\n if (!set.size) this.handlers.delete(event)\n }\n\n public emit(event: string, payload?: unknown): void {\n sendWs(this.ws, { type: \"event\", event, payload })\n }\n\n public onRtsMessage(channel: string, handler: (payload: unknown) => void): () => void {\n const set = this.messageHandlers.get(channel) ?? new Set()\n set.add(handler)\n this.messageHandlers.set(channel, set)\n return () => this.offRtsMessage(channel, handler)\n }\n\n public offRtsMessage(channel: string, handler: (payload: unknown) => void): void {\n const set = this.messageHandlers.get(channel)\n if (!set) return\n set.delete(handler)\n if (!set.size) this.messageHandlers.delete(channel)\n }\n\n public emitRtsMessage(channel: string, payload?: unknown): void {\n sendWs(this.ws, { type: \"rts-message\", channel, payload })\n }\n\n public close(): void {\n try {\n this.ws.close()\n } catch {\n // ignore\n }\n }\n\n public dispatch(event: string, payload: unknown): void {\n const set = this.handlers.get(event)\n if (!set) return\n for (const handler of set) {\n handler(payload)\n }\n }\n\n public dispatchRtsMessage(channel: string, payload: unknown): void {\n const set = this.messageHandlers.get(channel)\n if (!set) return\n for (const handler of set) {\n handler(payload)\n }\n }\n}\n\nconst rawToText = (raw: RawData): string => {\n if (typeof raw === \"string\") return raw\n if (raw instanceof ArrayBuffer) return Buffer.from(raw).toString()\n if (Array.isArray(raw)) return Buffer.concat(raw).toString()\n return raw.toString()\n}\n\nconst safeJsonParse = (raw: RawData): unknown => JSON.parse(rawToText(raw))\n\nconst sendWs = (ws: WebSocket, message: ServerMessage): void => {\n if (ws.readyState !== 1) return\n ws.send(JSON.stringify(message))\n}\n\nconst ensureSocketErrorHandler = (socket: Socket, context?: () => Record<string, unknown>): void => {\n if (socket.listenerCount(\"error\") > 0) return\n\n socket.on(\"error\", (err: unknown) => {\n const message = err instanceof Error ? err.message : String(err)\n const name = err instanceof Error ? err.name : typeof err\n const stack = err instanceof Error ? err.stack : undefined\n const code = err && typeof err === \"object\" && \"code\" in err ? (err as any).code : undefined\n\n if (code === \"ECONNRESET\" || (code == null && message.includes(\"ECONNRESET\"))) return\n\n console.warn(\"[rb/rts] socket error\", {\n name,\n code,\n message,\n stack,\n remoteAddress: socket.remoteAddress,\n remotePort: socket.remotePort,\n localAddress: socket.localAddress,\n localPort: socket.localPort,\n ...context?.(),\n })\n })\n}\n\nconst redactErrorMessage = (err: unknown): string => {\n const raw = err instanceof Error ? err.message : \"Unknown error\"\n const trimmedModelList = raw.replace(/\\.\\s+Available models:[\\s\\S]*$/, \"\")\n const maxLen = 256\n if (trimmedModelList.length <= maxLen) return trimmedModelList\n return trimmedModelList.slice(0, maxLen)\n}\n\nconst unauthorized = (socket: Socket, message = \"Unauthorized\"): void => {\n ensureSocketErrorHandler(socket)\n try {\n socket.write(\"HTTP/1.1 401 Unauthorized\\r\\n\\r\\n\")\n socket.write(`Error: ${message}\\r\\n`)\n socket.end()\n } catch {\n socket.destroy()\n }\n}\n\nconst badRequest = (socket: Socket, message = \"Bad Request\"): void => {\n ensureSocketErrorHandler(socket)\n try {\n socket.write(\"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\")\n socket.write(`Error: ${message}\\r\\n`)\n socket.end()\n } catch {\n socket.destroy()\n }\n}\n\nconst runSessionMiddleware = async (sessionMiddleware: RequestHandler, req: UpgradeRequest): Promise<void> => {\n type MiddlewareReq = Parameters<RequestHandler>[0]\n type MiddlewareRes = Parameters<RequestHandler>[1]\n type MiddlewareNext = Parameters<RequestHandler>[2]\n\n await new Promise<void>((resolve, reject) => {\n const next: MiddlewareNext = (err) => {\n if (err) reject(err)\n else resolve()\n }\n\n sessionMiddleware(req as unknown as MiddlewareReq, {} as unknown as MiddlewareRes, next)\n })\n}\n\nconst parseUpgradeMeta = async ({\n req,\n url,\n sessionMiddleware,\n postSyncSessionMiddleware,\n}: {\n req: IncomingMessage\n url: URL\n sessionMiddleware: RequestHandler\n postSyncSessionMiddleware?: RequestHandler\n}): Promise<SocketMeta> => {\n const upgradeReq = req as UpgradeRequest\n try {\n await runSessionMiddleware(sessionMiddleware, upgradeReq)\n } catch {\n throw new Error(\"Failed to load session for RTS\")\n }\n\n await syncAuthenticatedSessionFromRequest(upgradeReq as never)\n\n if (postSyncSessionMiddleware) {\n try {\n await runSessionMiddleware(postSyncSessionMiddleware, upgradeReq)\n } catch {\n throw new Error(\"RTS session authorization failed\")\n }\n }\n\n const sessionUser = upgradeReq.session?.user\n const sessionUserId = sessionUser?.id?.trim()\n if (!sessionUserId) {\n throw new Error(\"Not signed in (missing session.user.id)\")\n }\n\n const tenantId = sessionUser?.currentTenantId?.trim()\n if (!tenantId) {\n throw new Error(\"Missing current tenant in session\")\n }\n\n const ability = buildAbilityFromSession({ tenantId, session: upgradeReq.session })\n return { tenantId, userId: sessionUserId, ability }\n}\n\nconst getTenantModel = async (tenantId: string, modelName: string): Promise<Model<any>> => {\n const ctx: LoadModelCtx = {\n req: {\n session: {\n user: {\n currentTenantId: tenantId,\n },\n },\n },\n }\n\n return models.getUnsafe(modelName, ctx)\n}\n\nconst makeDispatchKey = (tenantId: string, modelName: string): string => `${tenantId}:${modelName}`\n\nconst clearDispatchTimer = (tenantId: string, modelName: string): void => {\n const key = makeDispatchKey(tenantId, modelName)\n const timer = dispatchTimers.get(key)\n if (!timer) return\n clearTimeout(timer)\n dispatchTimers.delete(key)\n}\n\nconst scheduleDispatchSubscriptionsForModel = (tenantId: string, modelName: string): void => {\n const key = makeDispatchKey(tenantId, modelName)\n if (dispatchTimers.has(key)) return\n\n const delay = Math.max(0, Math.min(1000, Math.floor(dispatchDebounceMs)))\n dispatchTimers.set(key, setTimeout(() => {\n dispatchTimers.delete(key)\n void Promise.all([\n dispatchSubscriptionsForModel(tenantId, modelName),\n dispatchCountSubscriptionsForModel(tenantId, modelName),\n ]).catch(() => {})\n }, delay))\n}\n\nconst runAndSendQuery = async ({\n tenantId,\n targetSocketIds,\n ability,\n modelName,\n queryKey,\n query,\n options,\n}: {\n tenantId: string\n targetSocketIds: string[]\n ability: AppAbility\n modelName: string\n queryKey: string\n query: JsonObject\n options: QueryOptions\n}): Promise<void> => {\n const result = await runRtsQuery({\n tenantId,\n ability,\n modelName,\n query,\n options,\n allowInternalModels,\n })\n const payload: ServerMessage = {\n type: \"query-payload\",\n modelName,\n queryKey,\n data: result.data,\n ...(result.pageInfo ? { pageInfo: result.pageInfo } : {}),\n ...(typeof result.totalCount === \"number\" ? { totalCount: result.totalCount } : {}),\n }\n\n for (const socketId of targetSocketIds) {\n const ws = sockets.get(socketId)\n if (!ws) continue\n sendWs(ws, payload)\n }\n}\n\nconst getHeadWindowOptions = (options: QueryOptions, requestedCount: number): QueryOptions => {\n if (!options.pagination) return options\n\n const pagination = { ...options.pagination, limit: requestedCount }\n delete pagination.cursor\n delete pagination.direction\n\n return {\n ...options,\n pagination,\n }\n}\n\nconst runAndSendSubscriptionQuery = async ({\n tenantId,\n targetSocketIds,\n ability,\n modelName,\n queryKey,\n subscription,\n}: {\n tenantId: string\n targetSocketIds: string[]\n ability: AppAbility\n modelName: string\n queryKey: string\n subscription: Subscription\n}): Promise<void> => {\n if (!subscription.options.pagination) {\n await runAndSendQuery({\n tenantId,\n targetSocketIds,\n ability,\n modelName,\n queryKey,\n query: subscription.query,\n options: subscription.options,\n })\n return\n }\n\n const groups = new Map<number, Array<{ socketId: string; window: QueryWindowPayload }>>()\n for (const socketId of targetSocketIds) {\n const state = subscription.windows.get(socketId)\n if (!state) continue\n\n state.version += 1\n const targets = groups.get(state.requestedCount) ?? []\n targets.push({\n socketId,\n window: {\n requestedCount: state.requestedCount,\n version: state.version,\n },\n })\n groups.set(state.requestedCount, targets)\n }\n\n await Promise.all(Array.from(groups.entries()).map(async ([requestedCount, targets]) => {\n try {\n const result = await runRtsQuery({\n tenantId,\n ability,\n modelName,\n query: subscription.query,\n options: getHeadWindowOptions(subscription.options, requestedCount),\n allowInternalModels,\n paginationMaxLimit: RTS_QUERY_WINDOW_MAX_COUNT,\n includePaginationCursors: false,\n })\n\n for (const target of targets) {\n const current = subscription.windows.get(target.socketId)\n if (\n !current\n || current.requestedCount !== target.window.requestedCount\n || current.version !== target.window.version\n ) {\n continue\n }\n\n const ws = sockets.get(target.socketId)\n if (!ws) continue\n sendWs(ws, {\n type: \"query-payload\",\n modelName,\n queryKey,\n data: result.data,\n ...(result.pageInfo ? { pageInfo: result.pageInfo } : {}),\n ...(typeof result.totalCount === \"number\" ? { totalCount: result.totalCount } : {}),\n window: target.window,\n })\n }\n } catch (err) {\n const error = redactErrorMessage(err)\n for (const target of targets) {\n const current = subscription.windows.get(target.socketId)\n if (\n !current\n || current.requestedCount !== target.window.requestedCount\n || current.version !== target.window.version\n ) {\n continue\n }\n\n const ws = sockets.get(target.socketId)\n if (!ws) continue\n sendWs(ws, {\n type: \"query-payload\",\n modelName,\n queryKey,\n error,\n window: target.window,\n })\n }\n }\n }))\n}\n\nconst runAndSendCount = async ({\n tenantId,\n targetSocketIds,\n ability,\n modelName,\n queryKey,\n query,\n}: {\n tenantId: string\n targetSocketIds: string[]\n ability: AppAbility\n modelName: string\n queryKey: string\n query: JsonObject\n}): Promise<void> => {\n const count = await runRtsCount({\n tenantId,\n ability,\n modelName,\n query,\n allowInternalModels,\n })\n const payload: ServerMessage = {\n type: \"count-payload\",\n modelName,\n queryKey,\n count,\n }\n\n for (const socketId of targetSocketIds) {\n const ws = sockets.get(socketId)\n if (!ws) continue\n sendWs(ws, payload)\n }\n}\n\nconst subscriptionDependsOnModel = (\n changedModelName: string,\n ownerModelName: string,\n subscription: Subscription,\n): boolean => {\n if (ownerModelName === changedModelName) return true\n return subscription.dependencyModelNames.includes(changedModelName)\n}\n\nconst hasAnySubscriptionsDependingOnModel = (\n tenantId: string,\n modelName: string,\n): boolean => {\n const tenantSubs = subscriptions.get(tenantId)\n if (!tenantSubs) return false\n\n for (const userSubs of tenantSubs.values()) {\n for (const [ownerModelName, modelSubs] of userSubs.entries()) {\n for (const subscription of modelSubs.values()) {\n if (subscriptionDependsOnModel(modelName, ownerModelName, subscription)) {\n return true\n }\n }\n }\n }\n\n return false\n}\n\nconst hasAnyCountSubscriptionsForModel = (\n tenantId: string,\n modelName: string,\n): boolean => {\n const tenantSubs = countSubscriptions.get(tenantId)\n if (!tenantSubs) return false\n\n for (const userSubs of tenantSubs.values()) {\n const modelSubs = userSubs.get(modelName)\n if (modelSubs?.size) {\n return true\n }\n }\n\n return false\n}\n\nconst dispatchSubscriptionsForModel = async (tenantId: string, modelName: string): Promise<void> => {\n const tenantSubs = subscriptions.get(tenantId)\n if (!tenantSubs || !tenantSubs.size) return\n\n for (const userSubs of tenantSubs.values()) {\n for (const [ownerModelName, modelSubs] of userSubs.entries()) {\n for (const [queryKey, sub] of modelSubs.entries()) {\n if (!subscriptionDependsOnModel(modelName, ownerModelName, sub)) continue\n\n const targetSocketIds = Array.from(sub.socketIds)\n if (!targetSocketIds.length) continue\n\n const socketId = targetSocketIds[0]\n const meta = socketMeta.get(socketId)\n const ability = meta?.ability\n if (!ability) continue\n\n try {\n await runAndSendSubscriptionQuery({\n tenantId,\n targetSocketIds,\n ability,\n modelName: ownerModelName,\n queryKey,\n subscription: sub,\n })\n } catch (err) {\n const error = redactErrorMessage(err)\n const payload: ServerMessage = { type: \"query-payload\", modelName: ownerModelName, queryKey, error }\n for (const socketId of targetSocketIds) {\n const ws = sockets.get(socketId)\n if (!ws) continue\n sendWs(ws, payload)\n }\n }\n }\n }\n }\n}\n\nconst dispatchCountSubscriptionsForModel = async (tenantId: string, modelName: string): Promise<void> => {\n const tenantSubs = countSubscriptions.get(tenantId)\n if (!tenantSubs || !tenantSubs.size) return\n\n for (const userSubs of tenantSubs.values()) {\n const modelSubs = userSubs.get(modelName)\n if (!modelSubs) continue\n\n for (const [queryKey, sub] of modelSubs.entries()) {\n const targetSocketIds = Array.from(sub.socketIds)\n if (!targetSocketIds.length) continue\n\n const socketId = targetSocketIds[0]\n const meta = socketMeta.get(socketId)\n const ability = meta?.ability\n if (!ability) continue\n\n try {\n await runAndSendCount({\n tenantId,\n targetSocketIds,\n ability,\n modelName,\n queryKey,\n query: sub.query,\n })\n } catch (err) {\n const error = redactErrorMessage(err)\n const payload: ServerMessage = { type: \"count-payload\", modelName, queryKey, error }\n for (const targetSocketId of targetSocketIds) {\n const ws = sockets.get(targetSocketId)\n if (!ws) continue\n sendWs(ws, payload)\n }\n }\n }\n }\n}\n\nconst ensureChangeStream = async (tenantId: string, modelName: string): Promise<void> => {\n const tenantStreams = changeStreams.get(tenantId) ?? new Map()\n changeStreams.set(tenantId, tenantStreams)\n if (tenantStreams.has(modelName)) return\n\n const model = await getTenantModel(tenantId, modelName)\n\n const stream = model.watch([], {\n fullDocument: \"updateLookup\",\n })\n\n stream.on(\"change\", () => {\n scheduleDispatchSubscriptionsForModel(tenantId, modelName)\n })\n\n stream.on(\"close\", () => {\n clearDispatchTimer(tenantId, modelName)\n const map = changeStreams.get(tenantId)\n map?.delete(modelName)\n if (map && map.size === 0) changeStreams.delete(tenantId)\n })\n\n stream.on(\"error\", () => {\n try {\n clearDispatchTimer(tenantId, modelName)\n stream.close()\n } catch {\n // ignore\n }\n })\n\n tenantStreams.set(modelName, stream)\n}\n\nconst closeUnusedChangeStream = (tenantId: string, modelName: string): void => {\n if (hasAnySubscriptionsDependingOnModel(tenantId, modelName) || hasAnyCountSubscriptionsForModel(tenantId, modelName)) {\n return\n }\n\n const tenantStreams = changeStreams.get(tenantId)\n const stream = tenantStreams?.get(modelName)\n if (!stream) return\n try {\n stream.close()\n } catch {\n // ignore\n }\n clearDispatchTimer(tenantId, modelName)\n tenantStreams?.delete(modelName)\n if (tenantStreams && tenantStreams.size === 0) changeStreams.delete(tenantId)\n}\n\nconst addSocketSubscription = ({\n socketId,\n tenantId,\n userId,\n modelName,\n queryKey,\n query,\n options,\n dependencyModelNames,\n}: {\n socketId: string\n tenantId: string\n userId: string\n modelName: string\n queryKey: string\n query: JsonObject\n options: QueryOptions\n dependencyModelNames: string[]\n}): void => {\n const tenantSubs = subscriptions.get(tenantId) ?? new Map<string, Map<string, Map<string, Subscription>>>()\n subscriptions.set(tenantId, tenantSubs)\n\n const userSubs = tenantSubs.get(userId) ?? new Map<string, Map<string, Subscription>>()\n tenantSubs.set(userId, userSubs)\n\n const modelSubs = userSubs.get(modelName) ?? new Map<string, Subscription>()\n userSubs.set(modelName, modelSubs)\n\n const existing = modelSubs.get(queryKey)\n if (existing) {\n existing.socketIds.add(socketId)\n existing.dependencyModelNames = Array.from(new Set([...existing.dependencyModelNames, ...dependencyModelNames]))\n if (options.pagination) {\n existing.windows.set(socketId, {\n requestedCount: options.pagination.limit,\n version: 0,\n })\n } else {\n existing.windows.delete(socketId)\n }\n } else {\n modelSubs.set(queryKey, {\n query,\n options,\n dependencyModelNames: Array.from(new Set(dependencyModelNames)),\n socketIds: new Set([socketId]),\n windows: options.pagination\n ? new Map([[socketId, { requestedCount: options.pagination.limit, version: 0 }]])\n : new Map(),\n })\n }\n\n const byModel = socketSubscriptions.get(socketId) ?? new Map()\n socketSubscriptions.set(socketId, byModel)\n\n const querySet = byModel.get(modelName) ?? new Set()\n byModel.set(modelName, querySet)\n querySet.add(queryKey)\n}\n\nconst addSocketCountSubscription = ({\n socketId,\n tenantId,\n userId,\n modelName,\n queryKey,\n query,\n}: {\n socketId: string\n tenantId: string\n userId: string\n modelName: string\n queryKey: string\n query: JsonObject\n}): void => {\n const tenantSubs = countSubscriptions.get(tenantId) ?? new Map<string, Map<string, Map<string, CountSubscription>>>()\n countSubscriptions.set(tenantId, tenantSubs)\n\n const userSubs = tenantSubs.get(userId) ?? new Map<string, Map<string, CountSubscription>>()\n tenantSubs.set(userId, userSubs)\n\n const modelSubs = userSubs.get(modelName) ?? new Map<string, CountSubscription>()\n userSubs.set(modelName, modelSubs)\n\n const existing = modelSubs.get(queryKey)\n if (existing) {\n existing.socketIds.add(socketId)\n } else {\n modelSubs.set(queryKey, {\n query,\n socketIds: new Set([socketId]),\n })\n }\n\n const byModel = socketCountSubscriptions.get(socketId) ?? new Map()\n socketCountSubscriptions.set(socketId, byModel)\n\n const querySet = byModel.get(modelName) ?? new Set()\n byModel.set(modelName, querySet)\n querySet.add(queryKey)\n}\n\nconst removeSocketSubscription = ({\n socketId,\n tenantId,\n userId,\n modelName,\n queryKey,\n}: {\n socketId: string\n tenantId: string\n userId: string\n modelName: string\n queryKey: string\n}): void => {\n const tenantSubs = subscriptions.get(tenantId)\n const userSubs = tenantSubs?.get(userId)\n const modelSubs = userSubs?.get(modelName)\n const sub = modelSubs?.get(queryKey)\n const affectedModelNames = new Set<string>([modelName, ...(sub?.dependencyModelNames ?? [])])\n if (sub) {\n sub.socketIds.delete(socketId)\n sub.windows.delete(socketId)\n if (!sub.socketIds.size) {\n modelSubs?.delete(queryKey)\n }\n }\n\n const byModel = socketSubscriptions.get(socketId)\n const set = byModel?.get(modelName)\n if (set) {\n set.delete(queryKey)\n if (!set.size) {\n byModel?.delete(modelName)\n }\n }\n\n if (modelSubs && modelSubs.size === 0) {\n userSubs?.delete(modelName)\n }\n\n if (userSubs && userSubs.size === 0) {\n tenantSubs?.delete(userId)\n }\n\n for (const affectedModelName of affectedModelNames) {\n if (\n hasAnySubscriptionsDependingOnModel(tenantId, affectedModelName)\n || hasAnyCountSubscriptionsForModel(tenantId, affectedModelName)\n ) {\n continue\n }\n\n const tenantStreams = changeStreams.get(tenantId)\n const stream = tenantStreams?.get(affectedModelName)\n if (stream) {\n try {\n stream.close()\n } catch {\n // ignore\n }\n clearDispatchTimer(tenantId, affectedModelName)\n tenantStreams?.delete(affectedModelName)\n if (tenantStreams && tenantStreams.size === 0) changeStreams.delete(tenantId)\n }\n }\n\n if (tenantSubs && tenantSubs.size === 0) subscriptions.delete(tenantId)\n if (byModel && byModel.size === 0) socketSubscriptions.delete(socketId)\n}\n\nconst removeSocketCountSubscription = ({\n socketId,\n tenantId,\n userId,\n modelName,\n queryKey,\n}: {\n socketId: string\n tenantId: string\n userId: string\n modelName: string\n queryKey: string\n}): void => {\n const tenantSubs = countSubscriptions.get(tenantId)\n const userSubs = tenantSubs?.get(userId)\n const modelSubs = userSubs?.get(modelName)\n const sub = modelSubs?.get(queryKey)\n if (sub) {\n sub.socketIds.delete(socketId)\n if (!sub.socketIds.size) {\n modelSubs?.delete(queryKey)\n }\n }\n\n const byModel = socketCountSubscriptions.get(socketId)\n const set = byModel?.get(modelName)\n if (set) {\n set.delete(queryKey)\n if (!set.size) {\n byModel?.delete(modelName)\n }\n }\n\n if (modelSubs && modelSubs.size === 0) {\n userSubs?.delete(modelName)\n }\n\n if (userSubs && userSubs.size === 0) {\n tenantSubs?.delete(userId)\n }\n\n if (!hasAnySubscriptionsDependingOnModel(tenantId, modelName) && !hasAnyCountSubscriptionsForModel(tenantId, modelName)) {\n const tenantStreams = changeStreams.get(tenantId)\n const stream = tenantStreams?.get(modelName)\n if (stream) {\n try {\n stream.close()\n } catch {\n // ignore\n }\n clearDispatchTimer(tenantId, modelName)\n tenantStreams?.delete(modelName)\n if (tenantStreams && tenantStreams.size === 0) changeStreams.delete(tenantId)\n }\n }\n\n if (tenantSubs && tenantSubs.size === 0) countSubscriptions.delete(tenantId)\n if (byModel && byModel.size === 0) socketCountSubscriptions.delete(socketId)\n}\n\nconst getSocketSubscriptionCount = (socketId: string): number => {\n let count = 0\n const querySubscriptionsByModel = socketSubscriptions.get(socketId)\n if (querySubscriptionsByModel) {\n for (const set of querySubscriptionsByModel.values()) count += set.size\n }\n\n const countSubscriptionsByModel = socketCountSubscriptions.get(socketId)\n if (countSubscriptionsByModel) {\n for (const set of countSubscriptionsByModel.values()) count += set.size\n }\n\n return count\n}\n\nconst cleanupSocket = (socketId: string): void => {\n const meta = socketMeta.get(socketId)\n if (meta) {\n const byModel = socketSubscriptions.get(socketId)\n if (byModel) {\n for (const [modelName, keys] of byModel.entries()) {\n for (const queryKey of keys.values()) {\n removeSocketSubscription({\n socketId,\n tenantId: meta.tenantId,\n userId: meta.userId,\n modelName,\n queryKey,\n })\n }\n }\n }\n\n const countByModel = socketCountSubscriptions.get(socketId)\n if (countByModel) {\n for (const [modelName, keys] of countByModel.entries()) {\n for (const queryKey of keys.values()) {\n removeSocketCountSubscription({\n socketId,\n tenantId: meta.tenantId,\n userId: meta.userId,\n modelName,\n queryKey,\n })\n }\n }\n }\n }\n\n socketSubscriptions.delete(socketId)\n socketCountSubscriptions.delete(socketId)\n\n const cleanupFns = socketCleanup.get(socketId) ?? []\n socketCleanup.delete(socketId)\n for (const fn of cleanupFns) {\n try {\n fn()\n } catch {\n // ignore\n }\n }\n\n sockets.delete(socketId)\n socketMeta.delete(socketId)\n socketWrappers.delete(socketId)\n}\n\nconst handleClientMessage = async ({\n socketId,\n meta,\n message,\n}: {\n socketId: string\n meta: SocketMeta\n message: ClientMessage\n}): Promise<void> => {\n const ws = sockets.get(socketId)\n if (!ws) return\n\n if (message.type === \"event\") {\n const wrapper = socketWrappers.get(socketId)\n wrapper?.dispatch(message.event, message.payload)\n return\n }\n\n if (message.type === \"rts-message\") {\n const wrapper = socketWrappers.get(socketId)\n wrapper?.dispatchRtsMessage(message.channel, message.payload)\n return\n }\n\n const isCountMessage =\n message.type === \"run-count\"\n || message.type === \"register-count\"\n || message.type === \"remove-count\"\n const sendAccessError = (error: string) => {\n if (isCountMessage) {\n sendWs(ws, { type: \"count-payload\", modelName: message.modelName ?? \"\", queryKey: message.queryKey ?? \"\", error })\n return\n }\n\n sendWs(ws, { type: \"query-payload\", modelName: message.modelName ?? \"\", queryKey: message.queryKey ?? \"\", error })\n }\n\n if (!message.modelName || typeof message.modelName !== \"string\") return\n if (!allowInternalModels && INTERNAL_MODEL_NAMES.has(message.modelName)) {\n sendAccessError(\"Model not allowed\")\n return\n }\n if (!message.queryKey || typeof message.queryKey !== \"string\") return\n if (message.queryKey.length > QUERY_KEY_MAX_LEN) return\n\n if (message.type === \"remove-query\") {\n removeSocketSubscription({\n socketId,\n tenantId: meta.tenantId,\n userId: meta.userId,\n modelName: message.modelName,\n queryKey: message.queryKey,\n })\n return\n }\n\n if (message.type === \"remove-count\") {\n removeSocketCountSubscription({\n socketId,\n tenantId: meta.tenantId,\n userId: meta.userId,\n modelName: message.modelName,\n queryKey: message.queryKey,\n })\n return\n }\n\n const ability = meta.ability\n\n if (!ability.can(\"read\", message.modelName as AclSubjectType)) {\n sendAccessError(\"forbidden\")\n return\n }\n\n if (message.type === \"set-query-window\") {\n if (!isValidQueryWindowCount(message.requestedCount)) {\n sendWs(ws, {\n type: \"query-payload\",\n modelName: message.modelName,\n queryKey: message.queryKey,\n error: \"Invalid requestedCount\",\n })\n return\n }\n\n const subscription = subscriptions\n .get(meta.tenantId)\n ?.get(meta.userId)\n ?.get(message.modelName)\n ?.get(message.queryKey)\n const window = subscription?.windows.get(socketId)\n if (!subscription || !subscription.options.pagination || !window) {\n sendWs(ws, {\n type: \"query-payload\",\n modelName: message.modelName,\n queryKey: message.queryKey,\n error: \"Paginated query subscription not found\",\n })\n return\n }\n\n window.requestedCount = message.requestedCount\n await runAndSendSubscriptionQuery({\n tenantId: meta.tenantId,\n targetSocketIds: [socketId],\n ability,\n modelName: message.modelName,\n queryKey: message.queryKey,\n subscription,\n })\n return\n }\n\n if (!message.query || typeof message.query !== \"object\") return\n\n if (message.type === \"register-query\" || message.type === \"run-query\") {\n const options = normalizeRtsQueryOptions(message.options)\n if (message.type === \"register-query\") {\n if (options.pagination && !isValidQueryWindowCount(options.pagination.limit)) {\n sendWs(ws, {\n type: \"query-payload\",\n modelName: message.modelName,\n queryKey: message.queryKey,\n error: \"Invalid requestedCount\",\n })\n return\n }\n\n const existing = socketSubscriptions.get(socketId)?.get(message.modelName)?.has(message.queryKey) ?? false\n if (!existing && getSocketSubscriptionCount(socketId) >= maxSubscriptionsPerSocket) {\n sendWs(ws, { type: \"query-payload\", modelName: message.modelName, queryKey: message.queryKey, error: \"Too many subscriptions\" })\n return\n }\n\n let dependencyModelNames: string[] = []\n if (options.populate !== undefined) {\n try {\n dependencyModelNames = await resolveRtsQueryDependencyModelNames({\n tenantId: meta.tenantId,\n ability,\n modelName: message.modelName,\n options,\n allowInternalModels,\n })\n } catch (err) {\n const error = redactErrorMessage(err)\n sendWs(ws, { type: \"query-payload\", modelName: message.modelName, queryKey: message.queryKey, error })\n return\n }\n }\n\n if (!sockets.has(socketId)) return\n\n addSocketSubscription({\n socketId,\n tenantId: meta.tenantId,\n userId: meta.userId,\n modelName: message.modelName,\n queryKey: message.queryKey,\n query: message.query,\n options,\n dependencyModelNames,\n })\n\n try {\n const modelNamesToWatch = new Set<string>([message.modelName, ...dependencyModelNames])\n for (const modelName of modelNamesToWatch) {\n await ensureChangeStream(meta.tenantId, modelName)\n }\n } catch (err) {\n const error = redactErrorMessage(err)\n sendWs(ws, { type: \"query-payload\", modelName: message.modelName, queryKey: message.queryKey, error })\n return\n }\n\n if (!sockets.has(socketId)) {\n for (const modelName of new Set<string>([message.modelName, ...dependencyModelNames])) {\n closeUnusedChangeStream(meta.tenantId, modelName)\n }\n return\n }\n\n if (message.runInitialQuery === false) {\n return\n }\n\n const subscription = subscriptions\n .get(meta.tenantId)\n ?.get(meta.userId)\n ?.get(message.modelName)\n ?.get(message.queryKey)\n if (!subscription) return\n\n try {\n await runAndSendSubscriptionQuery({\n tenantId: meta.tenantId,\n targetSocketIds: [socketId],\n ability,\n modelName: message.modelName,\n queryKey: message.queryKey,\n subscription,\n })\n } catch (err) {\n const error = redactErrorMessage(err)\n sendWs(ws, { type: \"query-payload\", modelName: message.modelName, queryKey: message.queryKey, error })\n }\n return\n }\n\n try {\n await runAndSendQuery({\n tenantId: meta.tenantId,\n targetSocketIds: [socketId],\n ability,\n modelName: message.modelName,\n queryKey: message.queryKey,\n query: message.query,\n options,\n })\n } catch (err) {\n const error = redactErrorMessage(err)\n sendWs(ws, { type: \"query-payload\", modelName: message.modelName, queryKey: message.queryKey, error })\n }\n return\n }\n\n if (message.type === \"register-count\" || message.type === \"run-count\") {\n if (message.type === \"register-count\") {\n const existing = socketCountSubscriptions.get(socketId)?.get(message.modelName)?.has(message.queryKey) ?? false\n if (!existing && getSocketSubscriptionCount(socketId) >= maxSubscriptionsPerSocket) {\n sendWs(ws, { type: \"count-payload\", modelName: message.modelName, queryKey: message.queryKey, error: \"Too many subscriptions\" })\n return\n }\n\n addSocketCountSubscription({\n socketId,\n tenantId: meta.tenantId,\n userId: meta.userId,\n modelName: message.modelName,\n queryKey: message.queryKey,\n query: message.query,\n })\n\n try {\n await ensureChangeStream(meta.tenantId, message.modelName)\n } catch (err) {\n const error = redactErrorMessage(err)\n sendWs(ws, { type: \"count-payload\", modelName: message.modelName, queryKey: message.queryKey, error })\n return\n }\n\n if (!sockets.has(socketId)) {\n closeUnusedChangeStream(meta.tenantId, message.modelName)\n return\n }\n\n if (message.runInitialQuery === false) {\n return\n }\n }\n\n try {\n await runAndSendCount({\n tenantId: meta.tenantId,\n targetSocketIds: [socketId],\n ability,\n modelName: message.modelName,\n queryKey: message.queryKey,\n query: message.query,\n })\n } catch (err) {\n const error = redactErrorMessage(err)\n sendWs(ws, { type: \"count-payload\", modelName: message.modelName, queryKey: message.queryKey, error })\n }\n }\n}\n\nexport const initRts = ({\n server,\n path = \"/rts\",\n sessionMiddleware,\n postSyncSessionMiddleware,\n maxPayloadBytes: maxPayloadBytesArg,\n maxSubscriptionsPerSocket: maxSubscriptionsPerSocketArg,\n dispatchDebounceMs: dispatchDebounceMsArg,\n allowInternalModels: allowInternalModelsArg,\n}: {\n server: HttpServer\n path?: string\n sessionMiddleware: RequestHandler\n postSyncSessionMiddleware?: RequestHandler\n maxPayloadBytes?: number\n maxSubscriptionsPerSocket?: number\n dispatchDebounceMs?: number\n allowInternalModels?: boolean\n}): void => {\n if (initializedServers.has(server)) return\n initializedServers.add(server)\n\n if (typeof maxPayloadBytesArg === \"number\" && Number.isFinite(maxPayloadBytesArg) && maxPayloadBytesArg > 0) {\n maxPayloadBytes = Math.floor(maxPayloadBytesArg)\n }\n\n if (\n typeof maxSubscriptionsPerSocketArg === \"number\"\n && Number.isFinite(maxSubscriptionsPerSocketArg)\n && maxSubscriptionsPerSocketArg > 0\n ) {\n maxSubscriptionsPerSocket = Math.floor(maxSubscriptionsPerSocketArg)\n }\n\n if (typeof dispatchDebounceMsArg === \"number\" && Number.isFinite(dispatchDebounceMsArg) && dispatchDebounceMsArg >= 0) {\n dispatchDebounceMs = Math.floor(dispatchDebounceMsArg)\n }\n\n allowInternalModels = Boolean(allowInternalModelsArg)\n\n const wss = new WebSocketServer({ noServer: true, maxPayload: maxPayloadBytes })\n\n server.on(\"upgrade\", (req: IncomingMessage, socket: Socket, head: Buffer) => {\n ensureSocketErrorHandler(socket, () => ({\n upgradeHost: req.headers.host ?? \"\",\n upgradeUrl: req.url ?? \"\",\n userAgent: typeof req.headers[\"user-agent\"] === \"string\" ? req.headers[\"user-agent\"] : \"\",\n }))\n upgradeMeta.delete(req)\n\n let url: URL\n try {\n url = new URL(req.url ?? \"\", `http://${req.headers.host ?? \"localhost\"}`)\n } catch {\n badRequest(socket, \"Invalid URL\")\n return\n }\n\n if (url.pathname !== path) return\n\n void (async() => {\n try {\n const meta = await parseUpgradeMeta({\n req,\n url,\n sessionMiddleware,\n postSyncSessionMiddleware,\n })\n upgradeMeta.set(req, meta)\n\n wss.handleUpgrade(req, socket, head, (ws: WebSocket) => {\n wss.emit(\"connection\", ws, req)\n })\n } catch (err) {\n const message = err instanceof Error ? err.message : \"RTS upgrade failed\"\n const upgradeReq = req as UpgradeRequest\n const sessionUser = upgradeReq.session?.user\n const sessionUserId = typeof sessionUser?.id === \"string\" ? sessionUser.id.trim() : \"\"\n const sessionTenantId = typeof sessionUser?.currentTenantId === \"string\" ? sessionUser.currentTenantId.trim() : \"\"\n const authenticatedUserIdHeader = req.headers[\"rb-authenticated-user-id\"]\n const authenticatedTenantIdHeader = req.headers[\"rb-authenticated-tenant-id\"]\n console.warn(\"[rb/rts] upgrade rejected\", {\n reason: message,\n host: req.headers.host ?? \"\",\n url: req.url ?? \"\",\n hasSessionUserId: Boolean(sessionUserId),\n hasCurrentTenantId: Boolean(sessionTenantId),\n hasAuthenticatedUserIdHeader: Boolean(Array.isArray(authenticatedUserIdHeader) ? authenticatedUserIdHeader[0] : authenticatedUserIdHeader),\n hasAuthenticatedTenantIdHeader: Boolean(Array.isArray(authenticatedTenantIdHeader) ? authenticatedTenantIdHeader[0] : authenticatedTenantIdHeader),\n userAgent: typeof req.headers[\"user-agent\"] === \"string\" ? req.headers[\"user-agent\"] : \"\",\n })\n if (message === \"Missing current tenant in session\") {\n badRequest(socket, message)\n return\n }\n unauthorized(socket, message)\n return\n }\n })().catch(() => {\n badRequest(socket, \"RTS upgrade failed\")\n })\n })\n\n wss.on(\"connection\", (ws: WebSocket, req: IncomingMessage) => {\n const meta = upgradeMeta.get(req)\n upgradeMeta.delete(req)\n if (!meta) {\n try {\n ws.close()\n } catch {\n // ignore\n }\n return\n }\n\n const socketId = randomUUID()\n sockets.set(socketId, ws)\n socketMeta.set(socketId, meta)\n\n const wrapper = new RtsSocket({ id: socketId, ws, meta })\n socketWrappers.set(socketId, wrapper)\n\n const cleanupFns: Array<() => void> = []\n for (const handler of customHandlers) {\n try {\n const cleanup = handler(wrapper)\n if (typeof cleanup === \"function\") cleanupFns.push(cleanup)\n } catch {\n // ignore\n }\n }\n if (cleanupFns.length) socketCleanup.set(socketId, cleanupFns)\n\n let messageQueue = Promise.resolve()\n\n ws.on(\"message\", (raw: RawData) => {\n let parsed: unknown\n try {\n parsed = safeJsonParse(raw)\n } catch {\n return\n }\n\n if (!parsed || typeof parsed !== \"object\") return\n const message = parsed as { type?: unknown }\n if (\n message.type !== \"event\"\n && message.type !== \"rts-message\"\n && message.type !== \"run-query\"\n && message.type !== \"register-query\"\n && message.type !== \"set-query-window\"\n && message.type !== \"remove-query\"\n && message.type !== \"run-count\"\n && message.type !== \"register-count\"\n && message.type !== \"remove-count\"\n ) return\n messageQueue = messageQueue\n .then(() => handleClientMessage({ socketId, meta, message: message as ClientMessage }))\n .catch(() => undefined)\n })\n\n ws.on(\"close\", () => {\n cleanupSocket(socketId)\n })\n\n ws.on(\"error\", () => {\n cleanupSocket(socketId)\n })\n })\n}\n\nexport const registerRtsHandler = (handler: HandlerFn): void => {\n customHandlers.push(handler)\n}\n\nexport const publishRtsMessage = ({ tenantId, userId, channel, payload }: PublishRtsMessageInput): void => {\n const normalizedTenantId = tenantId.trim()\n const normalizedUserId = userId?.trim()\n const normalizedChannel = channel.trim()\n if (!normalizedTenantId || !normalizedChannel) return\n\n for (const [socketId, meta] of socketMeta.entries()) {\n if (meta.tenantId !== normalizedTenantId) continue\n if (normalizedUserId && meta.userId !== normalizedUserId) continue\n const ws = sockets.get(socketId)\n if (!ws) continue\n sendWs(ws, { type: \"rts-message\", channel: normalizedChannel, payload })\n }\n}\n\nexport const notifyRtsModelChanged = (tenantId: string, modelName: string): void => {\n scheduleDispatchSubscriptionsForModel(tenantId, modelName)\n}\n\nexport * from \"./routes\"\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/rts/origin.ts","../../src/rts/routes.ts","../../src/rts/index.ts"],"sourcesContent":["import type { IncomingMessage } from \"node:http\"\n\nimport { getTrustedProxyAuth } from \"../proxyAuth\"\n\n\nexport const isRtsOriginAllowed = (req: IncomingMessage, allowedOrigins: string[] = []): boolean => {\n const origin = req.headers.origin\n if (origin === undefined) return true\n try {\n const parsed = new URL(origin)\n if (![\"http:\", \"https:\"].includes(parsed.protocol) || parsed.origin !== origin) return false\n if (allowedOrigins.includes(origin)) return true\n const trustedProxy = getTrustedProxyAuth(req.headers)\n const forwardedHost = trustedProxy && req.headers[\"x-forwarded-host\"]\n const forwardedProto = trustedProxy && req.headers[\"x-forwarded-proto\"]\n const host = typeof forwardedHost === \"string\" ? forwardedHost : req.headers.host\n const protocol = typeof forwardedProto === \"string\"\n ? forwardedProto === \"wss\" ? \"https:\" : forwardedProto === \"ws\" ? \"http:\" : `${forwardedProto}:`\n : \"encrypted\" in req.socket && req.socket.encrypted ? \"https:\" : \"http:\"\n return origin === new URL(`${protocol}//${host}`).origin\n } catch {\n return false\n }\n}\n","export const routes = Object.entries({\n ...import.meta.glob(\"./api/**/handler.ts\"),\n}).reduce<Record<string, unknown>>((acc, [path, mod]) => {\n acc[path.replace(\"./api/\", \"@rpcbase/server/rts/api/\")] = mod\n return acc\n}, {})\n\n","import { randomUUID } from \"node:crypto\"\nimport type { IncomingMessage, Server as HttpServer } from \"node:http\"\nimport type { Socket } from \"node:net\"\n\nimport type { RequestHandler } from \"express\"\nimport type { PaginationPageInfo } from \"@rpcbase/api\"\nimport { models, type LoadModelCtx } from \"@rpcbase/db\"\nimport { buildAbilityFromSession, type AclSubjectType, type AppAbility } from \"@rpcbase/db/acl\"\nimport type { ChangeStream } from \"mongodb\"\nimport type { Model } from \"mongoose\"\nimport { WebSocketServer, type RawData, type WebSocket } from \"ws\"\n\nimport {\n normalizeRtsQueryOptions,\n resolveRtsQueryDependencyModelNames,\n runRtsCount,\n runRtsQuery,\n type RtsQueryOptions as QueryOptions,\n} from \"./queryExecutor\"\nimport { RTS_QUERY_WINDOW_MAX_COUNT } from \"./queryWindow\"\nimport { revalidateAuthenticatedSession, syncAuthenticatedSessionFromRequest } from \"../syncAuthenticatedSession\"\nimport { isRtsOriginAllowed } from \"./origin\"\n\n\ntype JsonObject = Record<string, unknown>\n\ntype CountOptions = {\n key?: string\n}\n\ntype ClientMessage =\n | { type: \"run-query\"; modelName: string; queryKey: string; query: JsonObject; options?: QueryOptions }\n | {\n type: \"register-query\"\n modelName: string\n queryKey: string\n query: JsonObject\n options?: QueryOptions\n runInitialQuery?: boolean\n }\n | { type: \"set-query-window\"; modelName: string; queryKey: string; requestedCount: number }\n | { type: \"remove-query\"; modelName: string; queryKey: string }\n | { type: \"run-count\"; modelName: string; queryKey: string; query: JsonObject; options?: CountOptions }\n | {\n type: \"register-count\"\n modelName: string\n queryKey: string\n query: JsonObject\n options?: CountOptions\n runInitialQuery?: boolean\n }\n | { type: \"remove-count\"; modelName: string; queryKey: string }\n | { type: \"event\"; event: string; payload?: unknown }\n | { type: \"rts-message\"; channel: string; payload?: unknown }\n\ntype ServerMessage =\n | {\n type: \"query-payload\"\n modelName: string\n queryKey: string\n data?: unknown\n error?: string\n txnId?: string\n pageInfo?: PaginationPageInfo\n totalCount?: number\n window?: QueryWindowPayload\n }\n | {\n type: \"count-payload\"\n modelName: string\n queryKey: string\n count?: number\n error?: string\n txnId?: string\n }\n | { type: \"event\"; event: string; payload?: unknown }\n | { type: \"rts-message\"; channel: string; payload?: unknown }\n\nexport type PublishRtsMessageInput = {\n tenantId: string\n userId?: string\n channel: string\n payload?: unknown\n}\n\ntype SocketMeta = {\n tenantId: string\n userId: string\n ability: AppAbility\n validate: () => Promise<boolean>\n}\n\ntype SessionUser = {\n id?: string\n currentTenantId?: string\n authVersion?: number\n}\n\ntype UpgradeRequest = IncomingMessage & {\n session?: {\n user?: SessionUser\n cookie?: { expires?: Date | string | null }\n reload?: (callback: (err?: unknown) => void) => unknown\n save?: (callback: (err?: unknown) => void) => unknown\n }\n}\n\ntype Subscription = {\n query: JsonObject\n options: QueryOptions\n dependencyModelNames: string[]\n socketIds: Set<string>\n windows: Map<string, QueryWindowState>\n}\n\ntype QueryWindowPayload = {\n requestedCount: number\n version: number\n}\n\ntype QueryWindowState = QueryWindowPayload\n\ntype CountSubscription = {\n query: JsonObject\n socketIds: Set<string>\n}\n\ntype HandlerFn = (socket: RtsSocket) => void | (() => void)\n\nconst QUERY_KEY_MAX_LEN = 4096\n\nconst INTERNAL_MODEL_NAMES = new Set([\"RBRtsChange\", \"RBRtsCounter\"])\n\nconst DEFAULT_MAX_PAYLOAD_BYTES = 1024 * 1024\nconst DEFAULT_MAX_SUBSCRIPTIONS_PER_SOCKET = 256\nconst DEFAULT_DISPATCH_DEBOUNCE_MS = 25\n\nconst initializedServers = new WeakSet<HttpServer>()\nconst customHandlers: HandlerFn[] = []\n\nconst sockets = new Map<string, WebSocket>()\nconst socketMeta = new Map<string, SocketMeta>()\nconst socketValidators = new WeakMap<WebSocket, () => Promise<boolean>>()\nconst socketWrappers = new Map<string, RtsSocket>()\nconst socketCleanup = new Map<string, Array<() => void>>()\n\nconst socketSubscriptions = new Map<string, Map<string, Set<string>>>()\nconst socketCountSubscriptions = new Map<string, Map<string, Set<string>>>()\nconst subscriptions = new Map<string, Map<string, Map<string, Map<string, Subscription>>>>()\nconst countSubscriptions = new Map<string, Map<string, Map<string, Map<string, CountSubscription>>>>()\nconst changeStreams = new Map<string, Map<string, ChangeStream>>()\nconst dispatchTimers = new Map<string, ReturnType<typeof setTimeout>>()\nconst upgradeMeta = new WeakMap<IncomingMessage, SocketMeta>()\n\nlet maxPayloadBytes = DEFAULT_MAX_PAYLOAD_BYTES\nlet maxSubscriptionsPerSocket = DEFAULT_MAX_SUBSCRIPTIONS_PER_SOCKET\nlet dispatchDebounceMs = DEFAULT_DISPATCH_DEBOUNCE_MS\nlet allowInternalModels = false\n\nconst isValidQueryWindowCount = (value: unknown): value is number =>\n typeof value === \"number\"\n && Number.isInteger(value)\n && value >= 1\n && value <= RTS_QUERY_WINDOW_MAX_COUNT\n\nclass RtsSocket {\n public readonly id: string\n public readonly tenantId: string\n public readonly userId: string\n\n private readonly ws: WebSocket\n private readonly handlers = new Map<string, Set<(payload: unknown) => void>>()\n private readonly messageHandlers = new Map<string, Set<(payload: unknown) => void>>()\n\n public constructor({\n id,\n ws,\n meta,\n }: {\n id: string\n ws: WebSocket\n meta: SocketMeta\n }) {\n this.id = id\n this.ws = ws\n this.tenantId = meta.tenantId\n this.userId = meta.userId\n }\n\n public on(event: string, handler: (payload: unknown) => void): () => void {\n const set = this.handlers.get(event) ?? new Set()\n set.add(handler)\n this.handlers.set(event, set)\n return () => this.off(event, handler)\n }\n\n public off(event: string, handler: (payload: unknown) => void): void {\n const set = this.handlers.get(event)\n if (!set) return\n set.delete(handler)\n if (!set.size) this.handlers.delete(event)\n }\n\n public emit(event: string, payload?: unknown): void {\n sendWs(this.ws, { type: \"event\", event, payload })\n }\n\n public onRtsMessage(channel: string, handler: (payload: unknown) => void): () => void {\n const set = this.messageHandlers.get(channel) ?? new Set()\n set.add(handler)\n this.messageHandlers.set(channel, set)\n return () => this.offRtsMessage(channel, handler)\n }\n\n public offRtsMessage(channel: string, handler: (payload: unknown) => void): void {\n const set = this.messageHandlers.get(channel)\n if (!set) return\n set.delete(handler)\n if (!set.size) this.messageHandlers.delete(channel)\n }\n\n public emitRtsMessage(channel: string, payload?: unknown): void {\n sendWs(this.ws, { type: \"rts-message\", channel, payload })\n }\n\n public close(): void {\n try {\n this.ws.close()\n } catch {\n // ignore\n }\n }\n\n public dispatch(event: string, payload: unknown): void {\n const set = this.handlers.get(event)\n if (!set) return\n for (const handler of set) {\n handler(payload)\n }\n }\n\n public dispatchRtsMessage(channel: string, payload: unknown): void {\n const set = this.messageHandlers.get(channel)\n if (!set) return\n for (const handler of set) {\n handler(payload)\n }\n }\n}\n\nconst rawToText = (raw: RawData): string => {\n if (typeof raw === \"string\") return raw\n if (raw instanceof ArrayBuffer) return Buffer.from(raw).toString()\n if (Array.isArray(raw)) return Buffer.concat(raw).toString()\n return raw.toString()\n}\n\nconst safeJsonParse = (raw: RawData): unknown => JSON.parse(rawToText(raw))\n\nconst sendWs = (ws: WebSocket, message: ServerMessage): void => {\n if (ws.readyState !== 1) return\n const validate = socketValidators.get(ws)\n if (!validate) return\n void validate().then((valid) => {\n if (valid && ws.readyState === 1) ws.send(JSON.stringify(message))\n }).catch(() => ws.close(1011, \"Session validation failed\"))\n}\n\nconst ensureSocketErrorHandler = (socket: Socket, context?: () => Record<string, unknown>): void => {\n if (socket.listenerCount(\"error\") > 0) return\n\n socket.on(\"error\", (err: unknown) => {\n const message = err instanceof Error ? err.message : String(err)\n const name = err instanceof Error ? err.name : typeof err\n const stack = err instanceof Error ? err.stack : undefined\n const code = err && typeof err === \"object\" && \"code\" in err ? (err as any).code : undefined\n\n if (code === \"ECONNRESET\" || (code == null && message.includes(\"ECONNRESET\"))) return\n\n console.warn(\"[rb/rts] socket error\", {\n name,\n code,\n message,\n stack,\n remoteAddress: socket.remoteAddress,\n remotePort: socket.remotePort,\n localAddress: socket.localAddress,\n localPort: socket.localPort,\n ...context?.(),\n })\n })\n}\n\nconst redactErrorMessage = (err: unknown): string => {\n const raw = err instanceof Error ? err.message : \"Unknown error\"\n const trimmedModelList = raw.replace(/\\.\\s+Available models:[\\s\\S]*$/, \"\")\n const maxLen = 256\n if (trimmedModelList.length <= maxLen) return trimmedModelList\n return trimmedModelList.slice(0, maxLen)\n}\n\nconst unauthorized = (socket: Socket, message = \"Unauthorized\"): void => {\n ensureSocketErrorHandler(socket)\n try {\n socket.write(\"HTTP/1.1 401 Unauthorized\\r\\n\\r\\n\")\n socket.write(`Error: ${message}\\r\\n`)\n socket.end()\n } catch {\n socket.destroy()\n }\n}\n\nconst badRequest = (socket: Socket, message = \"Bad Request\"): void => {\n ensureSocketErrorHandler(socket)\n try {\n socket.write(\"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\")\n socket.write(`Error: ${message}\\r\\n`)\n socket.end()\n } catch {\n socket.destroy()\n }\n}\n\nconst runSessionMiddleware = async (sessionMiddleware: RequestHandler, req: UpgradeRequest): Promise<void> => {\n type MiddlewareReq = Parameters<RequestHandler>[0]\n type MiddlewareRes = Parameters<RequestHandler>[1]\n type MiddlewareNext = Parameters<RequestHandler>[2]\n\n await new Promise<void>((resolve, reject) => {\n const next: MiddlewareNext = (err) => {\n if (err) reject(err)\n else resolve()\n }\n\n sessionMiddleware(req as unknown as MiddlewareReq, {} as unknown as MiddlewareRes, next)\n })\n}\n\nconst parseUpgradeMeta = async ({\n req,\n url,\n sessionMiddleware,\n postSyncSessionMiddleware,\n}: {\n req: IncomingMessage\n url: URL\n sessionMiddleware: RequestHandler\n postSyncSessionMiddleware?: RequestHandler\n}): Promise<SocketMeta> => {\n const upgradeReq = req as UpgradeRequest\n try {\n await runSessionMiddleware(sessionMiddleware, upgradeReq)\n } catch {\n throw new Error(\"Failed to load session for RTS\")\n }\n\n await syncAuthenticatedSessionFromRequest(upgradeReq as never)\n\n if (postSyncSessionMiddleware) {\n try {\n await runSessionMiddleware(postSyncSessionMiddleware, upgradeReq)\n } catch {\n throw new Error(\"RTS session authorization failed\")\n }\n }\n\n const sessionUser = upgradeReq.session?.user\n const sessionUserId = sessionUser?.id?.trim()\n if (!sessionUserId) {\n throw new Error(\"Not signed in (missing session.user.id)\")\n }\n\n const tenantId = sessionUser?.currentTenantId?.trim()\n if (!tenantId) {\n throw new Error(\"Missing current tenant in session\")\n }\n\n const ability = buildAbilityFromSession({ tenantId, session: upgradeReq.session })\n const authVersion = sessionUser?.authVersion ?? 0\n const rules = JSON.stringify(ability.rules)\n if (upgradeReq.session?.save) {\n await new Promise<void>((resolve, reject) => {\n upgradeReq.session!.save!((err) => err ? reject(err) : resolve())\n })\n }\n let validation: Promise<boolean> | undefined\n const validate = (): Promise<boolean> => {\n if (validation) return validation\n validation = (async () => {\n if (upgradeReq.session?.reload) {\n await new Promise<void>((resolve, reject) => {\n upgradeReq.session!.reload!((err) => err ? reject(err) : resolve())\n })\n }\n const expires = upgradeReq.session?.cookie?.expires\n if (expires && new Date(expires).getTime() <= Date.now()) return false\n await revalidateAuthenticatedSession(upgradeReq)\n if (!upgradeReq.session?.user?.id) return false\n if (postSyncSessionMiddleware) await runSessionMiddleware(postSyncSessionMiddleware, upgradeReq)\n const currentUser = upgradeReq.session?.user\n return currentUser?.id === sessionUserId\n && currentUser.currentTenantId === tenantId\n && (currentUser.authVersion ?? 0) === authVersion\n && JSON.stringify(buildAbilityFromSession({ tenantId, session: upgradeReq.session }).rules) === rules\n })().catch(() => false).finally(() => { validation = undefined })\n return validation\n }\n return { tenantId, userId: sessionUserId, ability, validate }\n}\n\nconst getTenantModel = async (tenantId: string, modelName: string): Promise<Model<any>> => {\n const ctx: LoadModelCtx = {\n req: {\n session: {\n user: {\n currentTenantId: tenantId,\n },\n },\n },\n }\n\n return models.getUnsafe(modelName, ctx)\n}\n\nconst makeDispatchKey = (tenantId: string, modelName: string): string => `${tenantId}:${modelName}`\n\nconst clearDispatchTimer = (tenantId: string, modelName: string): void => {\n const key = makeDispatchKey(tenantId, modelName)\n const timer = dispatchTimers.get(key)\n if (!timer) return\n clearTimeout(timer)\n dispatchTimers.delete(key)\n}\n\nconst scheduleDispatchSubscriptionsForModel = (tenantId: string, modelName: string): void => {\n const key = makeDispatchKey(tenantId, modelName)\n if (dispatchTimers.has(key)) return\n\n const delay = Math.max(0, Math.min(1000, Math.floor(dispatchDebounceMs)))\n dispatchTimers.set(key, setTimeout(() => {\n dispatchTimers.delete(key)\n void Promise.all([\n dispatchSubscriptionsForModel(tenantId, modelName),\n dispatchCountSubscriptionsForModel(tenantId, modelName),\n ]).catch(() => {})\n }, delay))\n}\n\nconst runAndSendQuery = async ({\n tenantId,\n targetSocketIds,\n ability,\n modelName,\n queryKey,\n query,\n options,\n}: {\n tenantId: string\n targetSocketIds: string[]\n ability: AppAbility\n modelName: string\n queryKey: string\n query: JsonObject\n options: QueryOptions\n}): Promise<void> => {\n const result = await runRtsQuery({\n tenantId,\n ability,\n modelName,\n query,\n options,\n allowInternalModels,\n })\n const payload: ServerMessage = {\n type: \"query-payload\",\n modelName,\n queryKey,\n data: result.data,\n ...(result.pageInfo ? { pageInfo: result.pageInfo } : {}),\n ...(typeof result.totalCount === \"number\" ? { totalCount: result.totalCount } : {}),\n }\n\n for (const socketId of targetSocketIds) {\n const ws = sockets.get(socketId)\n if (!ws) continue\n sendWs(ws, payload)\n }\n}\n\nconst getHeadWindowOptions = (options: QueryOptions, requestedCount: number): QueryOptions => {\n if (!options.pagination) return options\n\n const pagination = { ...options.pagination, limit: requestedCount }\n delete pagination.cursor\n delete pagination.direction\n\n return {\n ...options,\n pagination,\n }\n}\n\nconst runAndSendSubscriptionQuery = async ({\n tenantId,\n targetSocketIds,\n ability,\n modelName,\n queryKey,\n subscription,\n}: {\n tenantId: string\n targetSocketIds: string[]\n ability: AppAbility\n modelName: string\n queryKey: string\n subscription: Subscription\n}): Promise<void> => {\n if (!subscription.options.pagination) {\n await runAndSendQuery({\n tenantId,\n targetSocketIds,\n ability,\n modelName,\n queryKey,\n query: subscription.query,\n options: subscription.options,\n })\n return\n }\n\n const groups = new Map<number, Array<{ socketId: string; window: QueryWindowPayload }>>()\n for (const socketId of targetSocketIds) {\n const state = subscription.windows.get(socketId)\n if (!state) continue\n\n state.version += 1\n const targets = groups.get(state.requestedCount) ?? []\n targets.push({\n socketId,\n window: {\n requestedCount: state.requestedCount,\n version: state.version,\n },\n })\n groups.set(state.requestedCount, targets)\n }\n\n await Promise.all(Array.from(groups.entries()).map(async ([requestedCount, targets]) => {\n try {\n const result = await runRtsQuery({\n tenantId,\n ability,\n modelName,\n query: subscription.query,\n options: getHeadWindowOptions(subscription.options, requestedCount),\n allowInternalModels,\n paginationMaxLimit: RTS_QUERY_WINDOW_MAX_COUNT,\n includePaginationCursors: false,\n })\n\n for (const target of targets) {\n const current = subscription.windows.get(target.socketId)\n if (\n !current\n || current.requestedCount !== target.window.requestedCount\n || current.version !== target.window.version\n ) {\n continue\n }\n\n const ws = sockets.get(target.socketId)\n if (!ws) continue\n sendWs(ws, {\n type: \"query-payload\",\n modelName,\n queryKey,\n data: result.data,\n ...(result.pageInfo ? { pageInfo: result.pageInfo } : {}),\n ...(typeof result.totalCount === \"number\" ? { totalCount: result.totalCount } : {}),\n window: target.window,\n })\n }\n } catch (err) {\n const error = redactErrorMessage(err)\n for (const target of targets) {\n const current = subscription.windows.get(target.socketId)\n if (\n !current\n || current.requestedCount !== target.window.requestedCount\n || current.version !== target.window.version\n ) {\n continue\n }\n\n const ws = sockets.get(target.socketId)\n if (!ws) continue\n sendWs(ws, {\n type: \"query-payload\",\n modelName,\n queryKey,\n error,\n window: target.window,\n })\n }\n }\n }))\n}\n\nconst runAndSendCount = async ({\n tenantId,\n targetSocketIds,\n ability,\n modelName,\n queryKey,\n query,\n}: {\n tenantId: string\n targetSocketIds: string[]\n ability: AppAbility\n modelName: string\n queryKey: string\n query: JsonObject\n}): Promise<void> => {\n const count = await runRtsCount({\n tenantId,\n ability,\n modelName,\n query,\n allowInternalModels,\n })\n const payload: ServerMessage = {\n type: \"count-payload\",\n modelName,\n queryKey,\n count,\n }\n\n for (const socketId of targetSocketIds) {\n const ws = sockets.get(socketId)\n if (!ws) continue\n sendWs(ws, payload)\n }\n}\n\nconst subscriptionDependsOnModel = (\n changedModelName: string,\n ownerModelName: string,\n subscription: Subscription,\n): boolean => {\n if (ownerModelName === changedModelName) return true\n return subscription.dependencyModelNames.includes(changedModelName)\n}\n\nconst hasAnySubscriptionsDependingOnModel = (\n tenantId: string,\n modelName: string,\n): boolean => {\n const tenantSubs = subscriptions.get(tenantId)\n if (!tenantSubs) return false\n\n for (const userSubs of tenantSubs.values()) {\n for (const [ownerModelName, modelSubs] of userSubs.entries()) {\n for (const subscription of modelSubs.values()) {\n if (subscriptionDependsOnModel(modelName, ownerModelName, subscription)) {\n return true\n }\n }\n }\n }\n\n return false\n}\n\nconst hasAnyCountSubscriptionsForModel = (\n tenantId: string,\n modelName: string,\n): boolean => {\n const tenantSubs = countSubscriptions.get(tenantId)\n if (!tenantSubs) return false\n\n for (const userSubs of tenantSubs.values()) {\n const modelSubs = userSubs.get(modelName)\n if (modelSubs?.size) {\n return true\n }\n }\n\n return false\n}\n\nconst getValidatedSocketIds = async (socketIds: Set<string>): Promise<string[]> => {\n const ids = Array.from(socketIds)\n const valid = await Promise.all(ids.map((id) => {\n const ws = sockets.get(id)\n return ws ? socketValidators.get(ws)?.() : false\n }))\n return ids.filter((_, index) => valid[index])\n}\n\nconst dispatchSubscriptionsForModel = async (tenantId: string, modelName: string): Promise<void> => {\n const tenantSubs = subscriptions.get(tenantId)\n if (!tenantSubs || !tenantSubs.size) return\n\n for (const userSubs of tenantSubs.values()) {\n for (const [ownerModelName, modelSubs] of userSubs.entries()) {\n for (const [queryKey, sub] of modelSubs.entries()) {\n if (!subscriptionDependsOnModel(modelName, ownerModelName, sub)) continue\n\n const targetSocketIds = await getValidatedSocketIds(sub.socketIds)\n if (!targetSocketIds.length) continue\n\n const socketId = targetSocketIds[0]\n const meta = socketMeta.get(socketId)\n const ability = meta?.ability\n if (!ability) continue\n\n try {\n await runAndSendSubscriptionQuery({\n tenantId,\n targetSocketIds,\n ability,\n modelName: ownerModelName,\n queryKey,\n subscription: sub,\n })\n } catch (err) {\n const error = redactErrorMessage(err)\n const payload: ServerMessage = { type: \"query-payload\", modelName: ownerModelName, queryKey, error }\n for (const socketId of targetSocketIds) {\n const ws = sockets.get(socketId)\n if (!ws) continue\n sendWs(ws, payload)\n }\n }\n }\n }\n }\n}\n\nconst dispatchCountSubscriptionsForModel = async (tenantId: string, modelName: string): Promise<void> => {\n const tenantSubs = countSubscriptions.get(tenantId)\n if (!tenantSubs || !tenantSubs.size) return\n\n for (const userSubs of tenantSubs.values()) {\n const modelSubs = userSubs.get(modelName)\n if (!modelSubs) continue\n\n for (const [queryKey, sub] of modelSubs.entries()) {\n const targetSocketIds = await getValidatedSocketIds(sub.socketIds)\n if (!targetSocketIds.length) continue\n\n const socketId = targetSocketIds[0]\n const meta = socketMeta.get(socketId)\n const ability = meta?.ability\n if (!ability) continue\n\n try {\n await runAndSendCount({\n tenantId,\n targetSocketIds,\n ability,\n modelName,\n queryKey,\n query: sub.query,\n })\n } catch (err) {\n const error = redactErrorMessage(err)\n const payload: ServerMessage = { type: \"count-payload\", modelName, queryKey, error }\n for (const targetSocketId of targetSocketIds) {\n const ws = sockets.get(targetSocketId)\n if (!ws) continue\n sendWs(ws, payload)\n }\n }\n }\n }\n}\n\nconst ensureChangeStream = async (tenantId: string, modelName: string): Promise<void> => {\n const tenantStreams = changeStreams.get(tenantId) ?? new Map()\n changeStreams.set(tenantId, tenantStreams)\n if (tenantStreams.has(modelName)) return\n\n const model = await getTenantModel(tenantId, modelName)\n\n const stream = model.watch([], {\n fullDocument: \"updateLookup\",\n })\n\n stream.on(\"change\", () => {\n scheduleDispatchSubscriptionsForModel(tenantId, modelName)\n })\n\n stream.on(\"close\", () => {\n clearDispatchTimer(tenantId, modelName)\n const map = changeStreams.get(tenantId)\n map?.delete(modelName)\n if (map && map.size === 0) changeStreams.delete(tenantId)\n })\n\n stream.on(\"error\", () => {\n try {\n clearDispatchTimer(tenantId, modelName)\n stream.close()\n } catch {\n // ignore\n }\n })\n\n tenantStreams.set(modelName, stream)\n}\n\nconst closeUnusedChangeStream = (tenantId: string, modelName: string): void => {\n if (hasAnySubscriptionsDependingOnModel(tenantId, modelName) || hasAnyCountSubscriptionsForModel(tenantId, modelName)) {\n return\n }\n\n const tenantStreams = changeStreams.get(tenantId)\n const stream = tenantStreams?.get(modelName)\n if (!stream) return\n try {\n stream.close()\n } catch {\n // ignore\n }\n clearDispatchTimer(tenantId, modelName)\n tenantStreams?.delete(modelName)\n if (tenantStreams && tenantStreams.size === 0) changeStreams.delete(tenantId)\n}\n\nconst addSocketSubscription = ({\n socketId,\n tenantId,\n userId,\n modelName,\n queryKey,\n query,\n options,\n dependencyModelNames,\n}: {\n socketId: string\n tenantId: string\n userId: string\n modelName: string\n queryKey: string\n query: JsonObject\n options: QueryOptions\n dependencyModelNames: string[]\n}): void => {\n const tenantSubs = subscriptions.get(tenantId) ?? new Map<string, Map<string, Map<string, Subscription>>>()\n subscriptions.set(tenantId, tenantSubs)\n\n const userSubs = tenantSubs.get(userId) ?? new Map<string, Map<string, Subscription>>()\n tenantSubs.set(userId, userSubs)\n\n const modelSubs = userSubs.get(modelName) ?? new Map<string, Subscription>()\n userSubs.set(modelName, modelSubs)\n\n const existing = modelSubs.get(queryKey)\n if (existing) {\n existing.socketIds.add(socketId)\n existing.dependencyModelNames = Array.from(new Set([...existing.dependencyModelNames, ...dependencyModelNames]))\n if (options.pagination) {\n existing.windows.set(socketId, {\n requestedCount: options.pagination.limit,\n version: 0,\n })\n } else {\n existing.windows.delete(socketId)\n }\n } else {\n modelSubs.set(queryKey, {\n query,\n options,\n dependencyModelNames: Array.from(new Set(dependencyModelNames)),\n socketIds: new Set([socketId]),\n windows: options.pagination\n ? new Map([[socketId, { requestedCount: options.pagination.limit, version: 0 }]])\n : new Map(),\n })\n }\n\n const byModel = socketSubscriptions.get(socketId) ?? new Map()\n socketSubscriptions.set(socketId, byModel)\n\n const querySet = byModel.get(modelName) ?? new Set()\n byModel.set(modelName, querySet)\n querySet.add(queryKey)\n}\n\nconst addSocketCountSubscription = ({\n socketId,\n tenantId,\n userId,\n modelName,\n queryKey,\n query,\n}: {\n socketId: string\n tenantId: string\n userId: string\n modelName: string\n queryKey: string\n query: JsonObject\n}): void => {\n const tenantSubs = countSubscriptions.get(tenantId) ?? new Map<string, Map<string, Map<string, CountSubscription>>>()\n countSubscriptions.set(tenantId, tenantSubs)\n\n const userSubs = tenantSubs.get(userId) ?? new Map<string, Map<string, CountSubscription>>()\n tenantSubs.set(userId, userSubs)\n\n const modelSubs = userSubs.get(modelName) ?? new Map<string, CountSubscription>()\n userSubs.set(modelName, modelSubs)\n\n const existing = modelSubs.get(queryKey)\n if (existing) {\n existing.socketIds.add(socketId)\n } else {\n modelSubs.set(queryKey, {\n query,\n socketIds: new Set([socketId]),\n })\n }\n\n const byModel = socketCountSubscriptions.get(socketId) ?? new Map()\n socketCountSubscriptions.set(socketId, byModel)\n\n const querySet = byModel.get(modelName) ?? new Set()\n byModel.set(modelName, querySet)\n querySet.add(queryKey)\n}\n\nconst removeSocketSubscription = ({\n socketId,\n tenantId,\n userId,\n modelName,\n queryKey,\n}: {\n socketId: string\n tenantId: string\n userId: string\n modelName: string\n queryKey: string\n}): void => {\n const tenantSubs = subscriptions.get(tenantId)\n const userSubs = tenantSubs?.get(userId)\n const modelSubs = userSubs?.get(modelName)\n const sub = modelSubs?.get(queryKey)\n const affectedModelNames = new Set<string>([modelName, ...(sub?.dependencyModelNames ?? [])])\n if (sub) {\n sub.socketIds.delete(socketId)\n sub.windows.delete(socketId)\n if (!sub.socketIds.size) {\n modelSubs?.delete(queryKey)\n }\n }\n\n const byModel = socketSubscriptions.get(socketId)\n const set = byModel?.get(modelName)\n if (set) {\n set.delete(queryKey)\n if (!set.size) {\n byModel?.delete(modelName)\n }\n }\n\n if (modelSubs && modelSubs.size === 0) {\n userSubs?.delete(modelName)\n }\n\n if (userSubs && userSubs.size === 0) {\n tenantSubs?.delete(userId)\n }\n\n for (const affectedModelName of affectedModelNames) {\n if (\n hasAnySubscriptionsDependingOnModel(tenantId, affectedModelName)\n || hasAnyCountSubscriptionsForModel(tenantId, affectedModelName)\n ) {\n continue\n }\n\n const tenantStreams = changeStreams.get(tenantId)\n const stream = tenantStreams?.get(affectedModelName)\n if (stream) {\n try {\n stream.close()\n } catch {\n // ignore\n }\n clearDispatchTimer(tenantId, affectedModelName)\n tenantStreams?.delete(affectedModelName)\n if (tenantStreams && tenantStreams.size === 0) changeStreams.delete(tenantId)\n }\n }\n\n if (tenantSubs && tenantSubs.size === 0) subscriptions.delete(tenantId)\n if (byModel && byModel.size === 0) socketSubscriptions.delete(socketId)\n}\n\nconst removeSocketCountSubscription = ({\n socketId,\n tenantId,\n userId,\n modelName,\n queryKey,\n}: {\n socketId: string\n tenantId: string\n userId: string\n modelName: string\n queryKey: string\n}): void => {\n const tenantSubs = countSubscriptions.get(tenantId)\n const userSubs = tenantSubs?.get(userId)\n const modelSubs = userSubs?.get(modelName)\n const sub = modelSubs?.get(queryKey)\n if (sub) {\n sub.socketIds.delete(socketId)\n if (!sub.socketIds.size) {\n modelSubs?.delete(queryKey)\n }\n }\n\n const byModel = socketCountSubscriptions.get(socketId)\n const set = byModel?.get(modelName)\n if (set) {\n set.delete(queryKey)\n if (!set.size) {\n byModel?.delete(modelName)\n }\n }\n\n if (modelSubs && modelSubs.size === 0) {\n userSubs?.delete(modelName)\n }\n\n if (userSubs && userSubs.size === 0) {\n tenantSubs?.delete(userId)\n }\n\n if (!hasAnySubscriptionsDependingOnModel(tenantId, modelName) && !hasAnyCountSubscriptionsForModel(tenantId, modelName)) {\n const tenantStreams = changeStreams.get(tenantId)\n const stream = tenantStreams?.get(modelName)\n if (stream) {\n try {\n stream.close()\n } catch {\n // ignore\n }\n clearDispatchTimer(tenantId, modelName)\n tenantStreams?.delete(modelName)\n if (tenantStreams && tenantStreams.size === 0) changeStreams.delete(tenantId)\n }\n }\n\n if (tenantSubs && tenantSubs.size === 0) countSubscriptions.delete(tenantId)\n if (byModel && byModel.size === 0) socketCountSubscriptions.delete(socketId)\n}\n\nconst getSocketSubscriptionCount = (socketId: string): number => {\n let count = 0\n const querySubscriptionsByModel = socketSubscriptions.get(socketId)\n if (querySubscriptionsByModel) {\n for (const set of querySubscriptionsByModel.values()) count += set.size\n }\n\n const countSubscriptionsByModel = socketCountSubscriptions.get(socketId)\n if (countSubscriptionsByModel) {\n for (const set of countSubscriptionsByModel.values()) count += set.size\n }\n\n return count\n}\n\nconst cleanupSocket = (socketId: string): void => {\n const meta = socketMeta.get(socketId)\n if (meta) {\n const byModel = socketSubscriptions.get(socketId)\n if (byModel) {\n for (const [modelName, keys] of byModel.entries()) {\n for (const queryKey of keys.values()) {\n removeSocketSubscription({\n socketId,\n tenantId: meta.tenantId,\n userId: meta.userId,\n modelName,\n queryKey,\n })\n }\n }\n }\n\n const countByModel = socketCountSubscriptions.get(socketId)\n if (countByModel) {\n for (const [modelName, keys] of countByModel.entries()) {\n for (const queryKey of keys.values()) {\n removeSocketCountSubscription({\n socketId,\n tenantId: meta.tenantId,\n userId: meta.userId,\n modelName,\n queryKey,\n })\n }\n }\n }\n }\n\n socketSubscriptions.delete(socketId)\n socketCountSubscriptions.delete(socketId)\n\n const cleanupFns = socketCleanup.get(socketId) ?? []\n socketCleanup.delete(socketId)\n for (const fn of cleanupFns) {\n try {\n fn()\n } catch {\n // ignore\n }\n }\n\n sockets.delete(socketId)\n socketMeta.delete(socketId)\n socketWrappers.delete(socketId)\n}\n\nconst handleClientMessage = async ({\n socketId,\n meta,\n message,\n}: {\n socketId: string\n meta: SocketMeta\n message: ClientMessage\n}): Promise<void> => {\n const ws = sockets.get(socketId)\n if (!ws) return\n if (!await socketValidators.get(ws)?.()) return\n\n if (message.type === \"event\") {\n const wrapper = socketWrappers.get(socketId)\n wrapper?.dispatch(message.event, message.payload)\n return\n }\n\n if (message.type === \"rts-message\") {\n const wrapper = socketWrappers.get(socketId)\n wrapper?.dispatchRtsMessage(message.channel, message.payload)\n return\n }\n\n const isCountMessage =\n message.type === \"run-count\"\n || message.type === \"register-count\"\n || message.type === \"remove-count\"\n const sendAccessError = (error: string) => {\n if (isCountMessage) {\n sendWs(ws, { type: \"count-payload\", modelName: message.modelName ?? \"\", queryKey: message.queryKey ?? \"\", error })\n return\n }\n\n sendWs(ws, { type: \"query-payload\", modelName: message.modelName ?? \"\", queryKey: message.queryKey ?? \"\", error })\n }\n\n if (!message.modelName || typeof message.modelName !== \"string\") return\n if (!allowInternalModels && INTERNAL_MODEL_NAMES.has(message.modelName)) {\n sendAccessError(\"Model not allowed\")\n return\n }\n if (!message.queryKey || typeof message.queryKey !== \"string\") return\n if (message.queryKey.length > QUERY_KEY_MAX_LEN) return\n\n if (message.type === \"remove-query\") {\n removeSocketSubscription({\n socketId,\n tenantId: meta.tenantId,\n userId: meta.userId,\n modelName: message.modelName,\n queryKey: message.queryKey,\n })\n return\n }\n\n if (message.type === \"remove-count\") {\n removeSocketCountSubscription({\n socketId,\n tenantId: meta.tenantId,\n userId: meta.userId,\n modelName: message.modelName,\n queryKey: message.queryKey,\n })\n return\n }\n\n const ability = meta.ability\n\n if (!ability.can(\"read\", message.modelName as AclSubjectType)) {\n sendAccessError(\"forbidden\")\n return\n }\n\n if (message.type === \"set-query-window\") {\n if (!isValidQueryWindowCount(message.requestedCount)) {\n sendWs(ws, {\n type: \"query-payload\",\n modelName: message.modelName,\n queryKey: message.queryKey,\n error: \"Invalid requestedCount\",\n })\n return\n }\n\n const subscription = subscriptions\n .get(meta.tenantId)\n ?.get(meta.userId)\n ?.get(message.modelName)\n ?.get(message.queryKey)\n const window = subscription?.windows.get(socketId)\n if (!subscription || !subscription.options.pagination || !window) {\n sendWs(ws, {\n type: \"query-payload\",\n modelName: message.modelName,\n queryKey: message.queryKey,\n error: \"Paginated query subscription not found\",\n })\n return\n }\n\n window.requestedCount = message.requestedCount\n await runAndSendSubscriptionQuery({\n tenantId: meta.tenantId,\n targetSocketIds: [socketId],\n ability,\n modelName: message.modelName,\n queryKey: message.queryKey,\n subscription,\n })\n return\n }\n\n if (!message.query || typeof message.query !== \"object\") return\n\n if (message.type === \"register-query\" || message.type === \"run-query\") {\n const options = normalizeRtsQueryOptions(message.options)\n if (message.type === \"register-query\") {\n if (options.pagination && !isValidQueryWindowCount(options.pagination.limit)) {\n sendWs(ws, {\n type: \"query-payload\",\n modelName: message.modelName,\n queryKey: message.queryKey,\n error: \"Invalid requestedCount\",\n })\n return\n }\n\n const existing = socketSubscriptions.get(socketId)?.get(message.modelName)?.has(message.queryKey) ?? false\n if (!existing && getSocketSubscriptionCount(socketId) >= maxSubscriptionsPerSocket) {\n sendWs(ws, { type: \"query-payload\", modelName: message.modelName, queryKey: message.queryKey, error: \"Too many subscriptions\" })\n return\n }\n\n let dependencyModelNames: string[] = []\n if (options.populate !== undefined) {\n try {\n dependencyModelNames = await resolveRtsQueryDependencyModelNames({\n tenantId: meta.tenantId,\n ability,\n modelName: message.modelName,\n options,\n allowInternalModels,\n })\n } catch (err) {\n const error = redactErrorMessage(err)\n sendWs(ws, { type: \"query-payload\", modelName: message.modelName, queryKey: message.queryKey, error })\n return\n }\n }\n\n if (!sockets.has(socketId)) return\n\n addSocketSubscription({\n socketId,\n tenantId: meta.tenantId,\n userId: meta.userId,\n modelName: message.modelName,\n queryKey: message.queryKey,\n query: message.query,\n options,\n dependencyModelNames,\n })\n\n try {\n const modelNamesToWatch = new Set<string>([message.modelName, ...dependencyModelNames])\n for (const modelName of modelNamesToWatch) {\n await ensureChangeStream(meta.tenantId, modelName)\n }\n } catch (err) {\n const error = redactErrorMessage(err)\n sendWs(ws, { type: \"query-payload\", modelName: message.modelName, queryKey: message.queryKey, error })\n return\n }\n\n if (!sockets.has(socketId)) {\n for (const modelName of new Set<string>([message.modelName, ...dependencyModelNames])) {\n closeUnusedChangeStream(meta.tenantId, modelName)\n }\n return\n }\n\n if (message.runInitialQuery === false) {\n return\n }\n\n const subscription = subscriptions\n .get(meta.tenantId)\n ?.get(meta.userId)\n ?.get(message.modelName)\n ?.get(message.queryKey)\n if (!subscription) return\n\n try {\n await runAndSendSubscriptionQuery({\n tenantId: meta.tenantId,\n targetSocketIds: [socketId],\n ability,\n modelName: message.modelName,\n queryKey: message.queryKey,\n subscription,\n })\n } catch (err) {\n const error = redactErrorMessage(err)\n sendWs(ws, { type: \"query-payload\", modelName: message.modelName, queryKey: message.queryKey, error })\n }\n return\n }\n\n try {\n await runAndSendQuery({\n tenantId: meta.tenantId,\n targetSocketIds: [socketId],\n ability,\n modelName: message.modelName,\n queryKey: message.queryKey,\n query: message.query,\n options,\n })\n } catch (err) {\n const error = redactErrorMessage(err)\n sendWs(ws, { type: \"query-payload\", modelName: message.modelName, queryKey: message.queryKey, error })\n }\n return\n }\n\n if (message.type === \"register-count\" || message.type === \"run-count\") {\n if (message.type === \"register-count\") {\n const existing = socketCountSubscriptions.get(socketId)?.get(message.modelName)?.has(message.queryKey) ?? false\n if (!existing && getSocketSubscriptionCount(socketId) >= maxSubscriptionsPerSocket) {\n sendWs(ws, { type: \"count-payload\", modelName: message.modelName, queryKey: message.queryKey, error: \"Too many subscriptions\" })\n return\n }\n\n addSocketCountSubscription({\n socketId,\n tenantId: meta.tenantId,\n userId: meta.userId,\n modelName: message.modelName,\n queryKey: message.queryKey,\n query: message.query,\n })\n\n try {\n await ensureChangeStream(meta.tenantId, message.modelName)\n } catch (err) {\n const error = redactErrorMessage(err)\n sendWs(ws, { type: \"count-payload\", modelName: message.modelName, queryKey: message.queryKey, error })\n return\n }\n\n if (!sockets.has(socketId)) {\n closeUnusedChangeStream(meta.tenantId, message.modelName)\n return\n }\n\n if (message.runInitialQuery === false) {\n return\n }\n }\n\n try {\n await runAndSendCount({\n tenantId: meta.tenantId,\n targetSocketIds: [socketId],\n ability,\n modelName: message.modelName,\n queryKey: message.queryKey,\n query: message.query,\n })\n } catch (err) {\n const error = redactErrorMessage(err)\n sendWs(ws, { type: \"count-payload\", modelName: message.modelName, queryKey: message.queryKey, error })\n }\n }\n}\n\nexport const initRts = ({\n server,\n path = \"/rts\",\n sessionMiddleware,\n postSyncSessionMiddleware,\n maxPayloadBytes: maxPayloadBytesArg,\n maxSubscriptionsPerSocket: maxSubscriptionsPerSocketArg,\n dispatchDebounceMs: dispatchDebounceMsArg,\n allowInternalModels: allowInternalModelsArg,\n allowedOrigins = (process.env.RB_RTS_ALLOWED_ORIGINS ?? \"\").split(\",\").map((value) => value.trim()).filter(Boolean),\n}: {\n server: HttpServer\n path?: string\n sessionMiddleware: RequestHandler\n postSyncSessionMiddleware?: RequestHandler\n maxPayloadBytes?: number\n maxSubscriptionsPerSocket?: number\n dispatchDebounceMs?: number\n allowInternalModels?: boolean\n allowedOrigins?: string[]\n}): void => {\n if (initializedServers.has(server)) return\n initializedServers.add(server)\n\n if (typeof maxPayloadBytesArg === \"number\" && Number.isFinite(maxPayloadBytesArg) && maxPayloadBytesArg > 0) {\n maxPayloadBytes = Math.floor(maxPayloadBytesArg)\n }\n\n if (\n typeof maxSubscriptionsPerSocketArg === \"number\"\n && Number.isFinite(maxSubscriptionsPerSocketArg)\n && maxSubscriptionsPerSocketArg > 0\n ) {\n maxSubscriptionsPerSocket = Math.floor(maxSubscriptionsPerSocketArg)\n }\n\n if (typeof dispatchDebounceMsArg === \"number\" && Number.isFinite(dispatchDebounceMsArg) && dispatchDebounceMsArg >= 0) {\n dispatchDebounceMs = Math.floor(dispatchDebounceMsArg)\n }\n\n allowInternalModels = Boolean(allowInternalModelsArg)\n\n const wss = new WebSocketServer({ noServer: true, maxPayload: maxPayloadBytes })\n\n server.on(\"upgrade\", (req: IncomingMessage, socket: Socket, head: Buffer) => {\n ensureSocketErrorHandler(socket, () => ({\n upgradeHost: req.headers.host ?? \"\",\n upgradeUrl: req.url ?? \"\",\n userAgent: typeof req.headers[\"user-agent\"] === \"string\" ? req.headers[\"user-agent\"] : \"\",\n }))\n upgradeMeta.delete(req)\n\n let url: URL\n try {\n url = new URL(req.url ?? \"\", `http://${req.headers.host ?? \"localhost\"}`)\n } catch {\n badRequest(socket, \"Invalid URL\")\n return\n }\n\n if (url.pathname !== path) return\n if (!isRtsOriginAllowed(req, allowedOrigins)) {\n socket.end(\"HTTP/1.1 403 Forbidden\\r\\nConnection: close\\r\\n\\r\\n\")\n return\n }\n\n void (async() => {\n try {\n const meta = await parseUpgradeMeta({\n req,\n url,\n sessionMiddleware,\n postSyncSessionMiddleware,\n })\n upgradeMeta.set(req, meta)\n\n wss.handleUpgrade(req, socket, head, (ws: WebSocket) => {\n wss.emit(\"connection\", ws, req)\n })\n } catch (err) {\n const message = err instanceof Error ? err.message : \"RTS upgrade failed\"\n const upgradeReq = req as UpgradeRequest\n const sessionUser = upgradeReq.session?.user\n const sessionUserId = typeof sessionUser?.id === \"string\" ? sessionUser.id.trim() : \"\"\n const sessionTenantId = typeof sessionUser?.currentTenantId === \"string\" ? sessionUser.currentTenantId.trim() : \"\"\n const authenticatedUserIdHeader = req.headers[\"rb-authenticated-user-id\"]\n const authenticatedTenantIdHeader = req.headers[\"rb-authenticated-tenant-id\"]\n console.warn(\"[rb/rts] upgrade rejected\", {\n reason: message,\n host: req.headers.host ?? \"\",\n url: req.url ?? \"\",\n hasSessionUserId: Boolean(sessionUserId),\n hasCurrentTenantId: Boolean(sessionTenantId),\n hasAuthenticatedUserIdHeader: Boolean(Array.isArray(authenticatedUserIdHeader) ? authenticatedUserIdHeader[0] : authenticatedUserIdHeader),\n hasAuthenticatedTenantIdHeader: Boolean(Array.isArray(authenticatedTenantIdHeader) ? authenticatedTenantIdHeader[0] : authenticatedTenantIdHeader),\n userAgent: typeof req.headers[\"user-agent\"] === \"string\" ? req.headers[\"user-agent\"] : \"\",\n })\n if (message === \"Missing current tenant in session\") {\n badRequest(socket, message)\n return\n }\n unauthorized(socket, message)\n return\n }\n })().catch(() => {\n badRequest(socket, \"RTS upgrade failed\")\n })\n })\n\n wss.on(\"connection\", (ws: WebSocket, req: IncomingMessage) => {\n const meta = upgradeMeta.get(req)\n upgradeMeta.delete(req)\n if (!meta) {\n try {\n ws.close()\n } catch {\n // ignore\n }\n return\n }\n\n const socketId = randomUUID()\n sockets.set(socketId, ws)\n socketMeta.set(socketId, meta)\n const validate = async (): Promise<boolean> => {\n if (ws.readyState !== 1) return false\n const valid = await meta.validate()\n if (!valid) ws.close(1008, \"Session expired or permissions changed\")\n return valid\n }\n socketValidators.set(ws, validate)\n\n const wrapper = new RtsSocket({ id: socketId, ws, meta })\n socketWrappers.set(socketId, wrapper)\n\n const validationTimer = setInterval(() => { void validate() }, 30_000)\n validationTimer.unref()\n const cleanupFns: Array<() => void> = [() => clearInterval(validationTimer)]\n for (const handler of customHandlers) {\n try {\n const cleanup = handler(wrapper)\n if (typeof cleanup === \"function\") cleanupFns.push(cleanup)\n } catch {\n // ignore\n }\n }\n if (cleanupFns.length) socketCleanup.set(socketId, cleanupFns)\n\n let messageQueue = Promise.resolve()\n\n ws.on(\"message\", (raw: RawData) => {\n let parsed: unknown\n try {\n parsed = safeJsonParse(raw)\n } catch {\n return\n }\n\n if (!parsed || typeof parsed !== \"object\") return\n const message = parsed as { type?: unknown }\n if (\n message.type !== \"event\"\n && message.type !== \"rts-message\"\n && message.type !== \"run-query\"\n && message.type !== \"register-query\"\n && message.type !== \"set-query-window\"\n && message.type !== \"remove-query\"\n && message.type !== \"run-count\"\n && message.type !== \"register-count\"\n && message.type !== \"remove-count\"\n ) return\n messageQueue = messageQueue\n .then(() => handleClientMessage({ socketId, meta, message: message as ClientMessage }))\n .catch(() => undefined)\n })\n\n ws.on(\"close\", () => {\n cleanupSocket(socketId)\n })\n\n ws.on(\"error\", () => {\n cleanupSocket(socketId)\n })\n })\n}\n\nexport const registerRtsHandler = (handler: HandlerFn): void => {\n customHandlers.push(handler)\n}\n\nexport const publishRtsMessage = ({ tenantId, userId, channel, payload }: PublishRtsMessageInput): void => {\n const normalizedTenantId = tenantId.trim()\n const normalizedUserId = userId?.trim()\n const normalizedChannel = channel.trim()\n if (!normalizedTenantId || !normalizedChannel) return\n\n for (const [socketId, meta] of socketMeta.entries()) {\n if (meta.tenantId !== normalizedTenantId) continue\n if (normalizedUserId && meta.userId !== normalizedUserId) continue\n const ws = sockets.get(socketId)\n if (!ws) continue\n sendWs(ws, { type: \"rts-message\", channel: normalizedChannel, payload })\n }\n}\n\nexport const notifyRtsModelChanged = (tenantId: string, modelName: string): void => {\n scheduleDispatchSubscriptionsForModel(tenantId, modelName)\n}\n\nexport * from \"./routes\"\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"origin.d.ts","sourceRoot":"","sources":["../../src/rts/origin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAKhD,eAAO,MAAM,kBAAkB,GAAI,KAAK,eAAe,EAAE,iBAAgB,MAAM,EAAO,KAAG,OAkBxF,CAAA"}
|
|
@@ -5,6 +5,7 @@ type SessionUserLike = {
|
|
|
5
5
|
signedInTenants?: unknown;
|
|
6
6
|
tenantRoles?: unknown;
|
|
7
7
|
isEntryGateAuthorized?: unknown;
|
|
8
|
+
authVersion?: unknown;
|
|
8
9
|
};
|
|
9
10
|
type RequestLike = {
|
|
10
11
|
headers?: Record<string, string | string[] | undefined>;
|
|
@@ -12,6 +13,7 @@ type RequestLike = {
|
|
|
12
13
|
user?: SessionUserLike;
|
|
13
14
|
};
|
|
14
15
|
};
|
|
16
|
+
export declare const revalidateAuthenticatedSession: (req: RequestLike) => Promise<void>;
|
|
15
17
|
export declare const syncAuthenticatedSessionFromRequest: (req: RequestLike) => Promise<void>;
|
|
16
18
|
export declare const syncAuthenticatedSessionMiddleware: RequestHandler;
|
|
17
19
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncAuthenticatedSession.d.ts","sourceRoot":"","sources":["../src/syncAuthenticatedSession.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAQ7C,KAAK,eAAe,GAAG;IACrB,EAAE,CAAC,EAAE,OAAO,CAAA;IACZ,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,qBAAqB,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"syncAuthenticatedSession.d.ts","sourceRoot":"","sources":["../src/syncAuthenticatedSession.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAQ7C,KAAK,eAAe,GAAG;IACrB,EAAE,CAAC,EAAE,OAAO,CAAA;IACZ,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,CAAA;AAED,KAAK,WAAW,GAAG;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAA;IACvD,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,eAAe,CAAA;KACvB,CAAA;CACF,CAAA;AA6ED,eAAO,MAAM,8BAA8B,GAAU,KAAK,WAAW,KAAG,OAAO,CAAC,IAAI,CAYnF,CAAA;AAED,eAAO,MAAM,mCAAmC,GAAU,KAAK,WAAW,KAAG,OAAO,CAAC,IAAI,CAexF,CAAA;AAED,eAAO,MAAM,kCAAkC,EAAE,cAIhD,CAAA"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getFile.d.ts","sourceRoot":"","sources":["../../../../../src/uploads/api/files/handlers/getFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"getFile.d.ts","sourceRoot":"","sources":["../../../../../src/uploads/api/files/handlers/getFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAMzC,OAAO,EAML,KAAK,WAAW,EACjB,MAAM,2BAA2B,CAAA;AAuElC,eAAO,MAAM,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,CAwHzF,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileContentHeaders.d.ts","sourceRoot":"","sources":["../../src/uploads/fileContentHeaders.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,qBAAqB,GAAI,UAAU,MAAM,EAAE,UAAU,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAW/F,CAAA"}
|
package/dist/uploads.js
CHANGED
|
@@ -2,7 +2,7 @@ import { a as getUploadProcessors, c as registerUploadProcessor, d as unregister
|
|
|
2
2
|
//#region src/uploads/routes.ts
|
|
3
3
|
var routes = Object.entries({ .../* #__PURE__ */ Object.assign({
|
|
4
4
|
"./api/file-uploads/handler.ts": () => import("./handler-BkGfOJ1l.js"),
|
|
5
|
-
"./api/files/handler.ts": () => import("./handler-
|
|
5
|
+
"./api/files/handler.ts": () => import("./handler-Dy_L6_-U.js")
|
|
6
6
|
}) }).reduce((acc, [path, mod]) => {
|
|
7
7
|
acc[path.replace("./api/", "@rpcbase/server/uploads/api/")] = mod;
|
|
8
8
|
return acc;
|