@rpcbase/server 0.636.0 → 0.637.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/rts/index.js CHANGED
@@ -1,8 +1,27 @@
1
- import { a as resolveRtsQueryDependencyModelNames, c as runRtsQuery, i as normalizeRtsQueryOptions, l as syncAuthenticatedSessionFromRequest, s as runRtsCount, t as RTS_QUERY_WINDOW_MAX_COUNT } from "../queryWindow-NCe5vJHt.js";
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
- ws.send(JSON.stringify(message));
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: buildAbilityFromSession({
192
- tenantId,
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 = Array.from(sub.socketIds);
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 = Array.from(sub.socketIds);
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 cleanupFns = [];
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);
@@ -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,3 @@
1
+ import { IncomingMessage } from 'node:http';
2
+ export declare const isRtsOriginAllowed: (req: IncomingMessage, allowedOrigins?: string[]) => boolean;
3
+ //# sourceMappingURL=origin.d.ts.map
@@ -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;CAChC,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;AAoFD,eAAO,MAAM,mCAAmC,GAAU,KAAK,WAAW,KAAG,OAAO,CAAC,IAAI,CAmCxF,CAAA;AAED,eAAO,MAAM,kCAAkC,EAAE,cAIhD,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"}
@@ -2,5 +2,6 @@ export type SessionUser = {
2
2
  id: string;
3
3
  currentTenantId: string;
4
4
  signedInTenants: string[];
5
+ authVersion?: number;
5
6
  };
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -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;CAC3B,CAAA"}
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;AAKzC,OAAO,EAML,KAAK,WAAW,EACjB,MAAM,2BAA2B,CAAA;AAyElC,eAAO,MAAM,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,CA+HzF,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,2 @@
1
+ export declare const getFileContentHeaders: (mimeType: string, filename: string) => Record<string, string>;
2
+ //# sourceMappingURL=fileContentHeaders.d.ts.map
@@ -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-C34TFH28.js")
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpcbase/server",
3
- "version": "0.636.0",
3
+ "version": "0.637.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"