@rpcbase/server 0.582.0 → 0.583.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.
@@ -291,6 +291,73 @@ const normalizePagination = (value) => {
291
291
  if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
292
292
  return value;
293
293
  };
294
+ const prepareCursorProjection = (projection, pagination, includeCursors) => {
295
+ if (!projection || !includeCursors) return {
296
+ projection,
297
+ addedPaths: []
298
+ };
299
+ const inclusionProjection = Object.entries(projection).some(([, value]) => value === 1);
300
+ const nextProjection = {
301
+ ...projection
302
+ };
303
+ const addedPaths = [];
304
+ const sortFields = Array.isArray(pagination.sort) ? pagination.sort.map((entry) => entry?.field).filter((field) => typeof field === "string") : [];
305
+ const cursorPaths = Array.from(/* @__PURE__ */ new Set([...sortFields, "_id"]));
306
+ if (!inclusionProjection) {
307
+ for (const path of cursorPaths) {
308
+ const excludedPath = Object.entries(projection).find(([projectedPath, value]) => value === 0 && (projectedPath === path || path.startsWith(`${projectedPath}.`)))?.[0];
309
+ if (!excludedPath) continue;
310
+ if (excludedPath !== path) {
311
+ throw new Error(`Pagination projection cannot exclude cursor path: ${path}`);
312
+ }
313
+ delete nextProjection[path];
314
+ addedPaths.push(path);
315
+ }
316
+ return {
317
+ projection: nextProjection,
318
+ addedPaths
319
+ };
320
+ }
321
+ for (const path of cursorPaths) {
322
+ const isIncluded = path === "_id" ? projection._id !== 0 : Object.entries(projection).some(([projectedPath, value]) => value === 1 && (projectedPath === path || path.startsWith(`${projectedPath}.`)));
323
+ if (isIncluded) continue;
324
+ nextProjection[path] = 1;
325
+ addedPaths.push(path);
326
+ }
327
+ return {
328
+ projection: nextProjection,
329
+ addedPaths
330
+ };
331
+ };
332
+ const stripPath = (target, path) => {
333
+ const parts = path.split(".");
334
+ let current = target;
335
+ for (let index = 0; index < parts.length - 1; index += 1) {
336
+ const part = parts[index];
337
+ const child = current[part];
338
+ if (!child || typeof child !== "object" || Array.isArray(child)) return;
339
+ const cloned = {
340
+ ...child
341
+ };
342
+ current[part] = cloned;
343
+ current = cloned;
344
+ }
345
+ delete current[parts[parts.length - 1]];
346
+ };
347
+ const stripAddedProjectionPaths = (nodes, addedPaths) => {
348
+ if (!addedPaths.length) return nodes;
349
+ return nodes.map((node) => {
350
+ if (!node || typeof node !== "object" || Array.isArray(node)) return node;
351
+ const toObject = node.toObject;
352
+ const raw = typeof toObject === "function" ? toObject.call(node) : node;
353
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return raw;
354
+ const projected = {
355
+ ...raw
356
+ };
357
+ for (const path of addedPaths) stripPath(projected, path);
358
+ return projected;
359
+ });
360
+ };
294
361
  const normalizePopulateSelect = (value) => {
295
362
  if (typeof value === "string") {
296
363
  const normalized = value.trim();
@@ -496,7 +563,9 @@ const runRtsQuery = async ({
496
563
  modelName,
497
564
  query,
498
565
  options,
499
- allowInternalModels = false
566
+ allowInternalModels = false,
567
+ paginationMaxLimit,
568
+ includePaginationCursors = true
500
569
  }) => {
501
570
  const {
502
571
  model,
@@ -523,20 +592,25 @@ const runRtsQuery = async ({
523
592
  dependencyModelNames: /* @__PURE__ */ new Set()
524
593
  });
525
594
  if (options.pagination) {
526
- const paginatedQuery = model.find(finalQuery, projection);
595
+ const cursorProjection = prepareCursorProjection(projection, options.pagination, includePaginationCursors);
596
+ const paginatedQuery = model.find(finalQuery, cursorProjection.projection);
527
597
  if (populate !== void 0) {
528
598
  paginatedQuery.populate(populate);
529
599
  }
530
600
  const paginatedResult = await paginatedQuery.paginate(options.pagination, {
531
601
  cursor: {
532
- signingSecret: getPaginationCursorSigningSecret()
533
- }
602
+ signingSecret: getPaginationCursorSigningSecret(),
603
+ ...paginationMaxLimit !== void 0 ? {
604
+ maxLimit: paginationMaxLimit
605
+ } : {}
606
+ },
607
+ includeCursors: includePaginationCursors
534
608
  });
535
609
  const totalCount = typeof paginatedResult.totalCount === "number" && Number.isFinite(paginatedResult.totalCount) && paginatedResult.totalCount >= 0 ? Math.floor(paginatedResult.totalCount) : void 0;
536
610
  const approximateTotalCount = totalCount === void 0 ? await runApproximateRtsCount(model, finalQuery).catch(() => void 0) : void 0;
537
611
  const resolvedTotalCount = totalCount ?? approximateTotalCount;
538
612
  return {
539
- data: Array.isArray(paginatedResult.nodes) ? paginatedResult.nodes : [],
613
+ data: Array.isArray(paginatedResult.nodes) ? stripAddedProjectionPaths(paginatedResult.nodes, cursorProjection.addedPaths) : [],
540
614
  pageInfo: paginatedResult.pageInfo,
541
615
  ...resolvedTotalCount !== void 0 ? {
542
616
  totalCount: resolvedTotalCount
@@ -623,7 +697,9 @@ const runRtsCount = async ({
623
697
  });
624
698
  return await runApproximateRtsCount(model, finalQuery);
625
699
  };
700
+ const RTS_QUERY_WINDOW_MAX_COUNT = 4096;
626
701
  export {
702
+ RTS_QUERY_WINDOW_MAX_COUNT as R,
627
703
  runRtsQuery as a,
628
704
  buildRtsAbilityFromRequest as b,
629
705
  runRtsCount as c,
@@ -635,4 +711,4 @@ export {
635
711
  resolveRtsRequestTenantId as r,
636
712
  syncAuthenticatedSessionMiddleware as s
637
713
  };
638
- //# sourceMappingURL=queryExecutor-DW7iAdRY.js.map
714
+ //# sourceMappingURL=queryWindow-Cdr7K-S1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryWindow-Cdr7K-S1.js","sources":["../src/getDerivedKey.ts","../src/proxyAuth.ts","../src/syncAuthenticatedSession.ts","../src/rts/queryExecutor.ts","../src/rts/queryWindow.ts"],"sourcesContent":["import assert from \"assert\"\nimport { hkdfSync } from \"crypto\"\n\n\nexport const getDerivedKey = (\n masterKey: string,\n info: string,\n length: number = 32, // Default to 256-bit keys\n salt: string = \"\",\n): string => {\n assert(masterKey?.length >= 32, \"MASTER_KEY must be 32 chars or longer.\")\n\n return Buffer.from(hkdfSync(\n \"sha256\",\n masterKey,\n Buffer.from(salt),\n Buffer.from(info),\n length,\n )).toString(\"hex\")\n}\n","import { createHmac, timingSafeEqual } from \"node:crypto\"\n\n\nexport const AUTHENTICATED_USER_ID_HEADER = \"rb-authenticated-user-id\"\nexport const AUTHENTICATED_TENANT_ID_HEADER = \"rb-authenticated-tenant-id\"\nexport const PROXY_AUTH_TIMESTAMP_HEADER = \"rb-proxy-auth-timestamp\"\nexport const PROXY_AUTH_SIGNATURE_HEADER = \"rb-proxy-auth-signature\"\n\nconst MAX_PROXY_AUTH_AGE_MS = 5 * 60 * 1000\n\ntype HeadersLike = Record<string, string | string[] | undefined>\n\nconst normalizeString = (value: unknown): string | null => {\n if (typeof value !== \"string\") return null\n const normalized = value.trim()\n return normalized || null\n}\n\nconst getHeaderValue = (headers: HeadersLike | undefined, name: string): string | null => {\n const value = headers?.[name]\n if (Array.isArray(value)) return normalizeString(value[0])\n return normalizeString(value)\n}\n\nconst getProxySharedSecret = (): string | null => {\n const secret = process.env.RB_PROXY_SHARED_SECRET?.trim()\n return secret || null\n}\n\nconst timingSafeEqualText = (left: string, right: string): boolean => {\n const leftBuffer = Buffer.from(left)\n const rightBuffer = Buffer.from(right)\n if (leftBuffer.length !== rightBuffer.length) return false\n return timingSafeEqual(leftBuffer, rightBuffer)\n}\n\nexport const buildProxyAuthSignature = ({\n userId,\n tenantId,\n timestamp,\n secret,\n}: {\n userId: string\n tenantId: string\n timestamp: string\n secret: string\n}): string => {\n return createHmac(\"sha256\", secret)\n .update(`${timestamp}:${userId}:${tenantId}`)\n .digest(\"hex\")\n}\n\nexport const getTrustedProxyAuth = (\n headers: HeadersLike | undefined,\n): { userId: string; tenantId: string } | null => {\n const userId = getHeaderValue(headers, AUTHENTICATED_USER_ID_HEADER)\n const tenantId = getHeaderValue(headers, AUTHENTICATED_TENANT_ID_HEADER)\n const timestamp = getHeaderValue(headers, PROXY_AUTH_TIMESTAMP_HEADER)\n const signature = getHeaderValue(headers, PROXY_AUTH_SIGNATURE_HEADER)\n if (!userId || !tenantId || !timestamp || !signature) return null\n\n const parsedTimestamp = Number(timestamp)\n if (!Number.isInteger(parsedTimestamp)) return null\n\n const now = Date.now()\n if (Math.abs(now - parsedTimestamp) > MAX_PROXY_AUTH_AGE_MS) return null\n\n const secret = getProxySharedSecret()\n if (!secret) return null\n\n const expectedSignature = buildProxyAuthSignature({\n userId,\n tenantId,\n timestamp,\n secret,\n })\n\n if (!timingSafeEqualText(signature, expectedSignature)) return null\n\n return { userId, tenantId }\n}\n","import type { RequestHandler } from \"express\"\nimport { models, type LoadModelCtx } from \"@rpcbase/db\"\n\nimport {\n getTrustedProxyAuth,\n} from \"./proxyAuth\"\n\n\ntype SessionUserLike = {\n id?: unknown\n currentTenantId?: unknown\n signedInTenants?: unknown\n tenantRoles?: unknown\n isEntryGateAuthorized?: unknown\n}\n\ntype RequestLike = {\n headers?: Record<string, string | string[] | undefined>\n session?: {\n user?: SessionUserLike\n }\n}\n\ntype LoadedUserDoc = {\n tenants?: unknown\n tenantRoles?: unknown\n}\n\nconst normalizeString = (value: unknown): string | null => {\n if (typeof value !== \"string\") return null\n const normalized = value.trim()\n return normalized || null\n}\n\nconst normalizeStringArray = (value: unknown): string[] => {\n if (!Array.isArray(value)) return []\n return value\n .map((entry) => normalizeString(String(entry)))\n .filter((entry): entry is string => Boolean(entry))\n}\n\nconst normalizeRoles = (value: unknown): string[] => {\n if (!Array.isArray(value)) return []\n return value\n .map((entry) => normalizeString(entry))\n .filter((entry): entry is string => Boolean(entry))\n}\n\nconst normalizeTenantRoles = (value: unknown): Record<string, string[]> | undefined => {\n if (!value || typeof value !== \"object\") return undefined\n\n if (value instanceof Map) {\n const entries = Array.from(value.entries())\n .map(([tenantId, roles]) => {\n const normalizedTenantId = normalizeString(String(tenantId))\n if (!normalizedTenantId) return null\n return [normalizedTenantId, normalizeRoles(roles)] as const\n })\n .filter((entry): entry is readonly [string, string[]] => Boolean(entry))\n return entries.length ? Object.fromEntries(entries) : undefined\n }\n\n const nextRoles = Object.entries(value as Record<string, unknown>)\n .map(([tenantId, roles]) => {\n const normalizedTenantId = normalizeString(tenantId)\n if (!normalizedTenantId) return null\n return [normalizedTenantId, normalizeRoles(roles)] as const\n })\n .filter((entry): entry is readonly [string, string[]] => Boolean(entry))\n\n return nextRoles.length ? Object.fromEntries(nextRoles) : undefined\n}\n\nconst isSessionAuthorizedForTenant = (sessionUser: SessionUserLike | undefined, tenantId: string): boolean => {\n if (!sessionUser) return false\n\n const signedInTenants = normalizeStringArray(sessionUser.signedInTenants)\n if (signedInTenants.length > 0) {\n return signedInTenants.includes(tenantId)\n }\n\n const currentTenantId = normalizeString(sessionUser.currentTenantId)\n return currentTenantId === tenantId\n}\n\nconst loadSessionUser = async (userId: string, tenantId: string): Promise<Record<string, unknown> | null> => {\n const ctx: LoadModelCtx = { req: { session: null } }\n const User = await models.getGlobal(\"RBUser\", ctx)\n const user = await User.findById(userId, { tenants: 1, tenantRoles: 1 }).lean() as LoadedUserDoc | null\n if (!user) return null\n\n const signedInTenants = normalizeStringArray(user.tenants)\n if (!signedInTenants.includes(tenantId)) return null\n\n const tenantRoles = normalizeTenantRoles(user.tenantRoles)\n\n return {\n id: userId,\n currentTenantId: tenantId,\n signedInTenants,\n isEntryGateAuthorized: true,\n ...(tenantRoles ? { tenantRoles } : {}),\n }\n}\n\nexport const syncAuthenticatedSessionFromRequest = async (req: RequestLike): Promise<void> => {\n const proxyAuth = getTrustedProxyAuth(req.headers)\n if (!proxyAuth) return\n\n const { userId, tenantId } = proxyAuth\n\n const session = req.session\n if (!session) return\n\n const sessionUser = session.user\n const sessionUserId = normalizeString(sessionUser?.id)\n\n if (sessionUserId === userId && isSessionAuthorizedForTenant(sessionUser, tenantId)) {\n const currentTenantId = normalizeString(sessionUser?.currentTenantId)\n if (currentTenantId === tenantId) return\n\n const baseUser = sessionUser && typeof sessionUser === \"object\" ? sessionUser as Record<string, unknown> : {}\n session.user = {\n ...baseUser,\n id: userId,\n currentTenantId: tenantId,\n isEntryGateAuthorized: true,\n }\n return\n }\n\n const nextSessionUser = await loadSessionUser(userId, tenantId)\n if (!nextSessionUser) {\n if (session.user) {\n delete session.user\n }\n return\n }\n\n session.user = nextSessionUser as SessionUserLike\n}\n\nexport const syncAuthenticatedSessionMiddleware: RequestHandler = (req, _res, next) => {\n void syncAuthenticatedSessionFromRequest(req).then(() => {\n next()\n }, next)\n}\n","import type { Request } from \"express\"\nimport type { PaginationPageInfo, PaginationSpec } from \"@rpcbase/api\"\nimport { models, type LoadModelCtx } from \"@rpcbase/db\"\nimport { buildAbilityFromSession, getAccessibleByQuery, type AclSubjectType, type AppAbility } from \"@rpcbase/db/acl\"\nimport type { Model } from \"mongoose\"\n\nimport { getDerivedKey } from \"../getDerivedKey\"\n\n\ntype JsonObject = Record<string, unknown>\n\ntype SessionUser = {\n id?: unknown\n currentTenantId?: unknown\n}\n\nexport type RtsPopulateObject = {\n path: string\n model?: string\n select?: string | JsonObject\n match?: JsonObject\n options?: {\n sort?: Record<string, 1 | -1>\n limit?: number\n }\n populate?: RtsPopulateOption\n}\n\nexport type RtsPopulateOption =\n | string\n | RtsPopulateObject\n | Array<string | RtsPopulateObject>\n\nexport type RtsQueryOptions = {\n projection?: JsonObject\n sort?: Record<string, 1 | -1>\n limit?: number\n populate?: RtsPopulateOption\n pagination?: PaginationSpec\n}\n\nexport type RtsQueryResult = {\n data: unknown[]\n pageInfo?: PaginationPageInfo\n totalCount?: number\n}\n\ntype PreparedRtsExecution = {\n model: Model<any>\n finalQuery: JsonObject\n}\n\nconst QUERY_MAX_LIMIT = 4096\nconst INTERNAL_MODEL_NAMES = new Set([\"RBRtsChange\", \"RBRtsCounter\"])\nconst DEFAULT_APPROX_COUNT_SAMPLE_SIZE = 1000\nconst MAX_APPROX_COUNT_SAMPLE_SIZE = 10_000\nconst UNSUPPORTED_APPROX_COUNT_OPERATORS = new Set([\"$text\", \"$near\", \"$nearSphere\", \"$where\"])\nlet paginationCursorSigningSecret: string | null = null\n\nconst getPaginationCursorSigningSecret = (): string => {\n if (paginationCursorSigningSecret) return paginationCursorSigningSecret\n const masterKey = process.env.MASTER_KEY?.trim()\n if (!masterKey) {\n throw new Error(\"MASTER_KEY must be defined to derive pagination cursor signing secret\")\n }\n paginationCursorSigningSecret = getDerivedKey(masterKey, \"pagination_cursor_signing\")\n return paginationCursorSigningSecret\n}\n\nconst normalizeTenantId = (value: unknown): string | null => {\n if (typeof value !== \"string\") return null\n const normalized = value.trim()\n return normalized ? normalized : null\n}\n\nconst getTenantIdFromRequest = (req: Request): string | null => {\n return normalizeTenantId((req.session?.user as SessionUser | undefined)?.currentTenantId)\n}\n\nexport const resolveRtsRequestTenantId = (req: Request): string | null => {\n return getTenantIdFromRequest(req)\n}\n\nexport const resolveRtsRequestUserId = (req: Request): string | null => {\n return normalizeTenantId((req.session?.user as SessionUser | undefined)?.id)\n}\n\nexport const isRtsRequestAuthorized = (req: Request, tenantId: string): boolean => {\n const sessionUser = req.session?.user as SessionUser | undefined\n if (!sessionUser) return false\n\n const currentTenantId = normalizeTenantId(sessionUser.currentTenantId)\n if (!currentTenantId) return false\n return currentTenantId === tenantId\n}\n\nexport const buildRtsAbilityFromRequest = async (\n req: Request,\n tenantId: string,\n): Promise<{ ability: AppAbility; userId: string | null }> => {\n const sessionUserId = normalizeTenantId((req.session?.user as SessionUser | undefined)?.id)\n if (!sessionUserId) {\n const currentTenantId = normalizeTenantId((req.session?.user as SessionUser | undefined)?.currentTenantId)\n if (!currentTenantId || currentTenantId !== tenantId) {\n throw new Error(\"Tenant not authorized for this session\")\n }\n\n return {\n ability: buildAbilityFromSession({ tenantId, session: req.session }),\n userId: null,\n }\n }\n\n const currentTenantId = normalizeTenantId((req.session?.user as SessionUser | undefined)?.currentTenantId)\n if (!currentTenantId || currentTenantId !== tenantId) {\n throw new Error(\"Tenant not authorized for this session\")\n }\n\n return {\n ability: buildAbilityFromSession({ tenantId, session: req.session }),\n userId: sessionUserId,\n }\n}\n\nconst getTenantModel = async (tenantId: string, modelName: string, ability: AppAbility): Promise<Model<any>> => {\n const ctx: LoadModelCtx = {\n req: {\n session: {\n user: {\n currentTenantId: tenantId,\n },\n },\n },\n ability,\n }\n\n return models.get(modelName, ctx)\n}\n\nconst normalizeLimit = (limit?: number): number => {\n if (typeof limit !== \"number\") return QUERY_MAX_LIMIT\n if (!Number.isFinite(limit)) return QUERY_MAX_LIMIT\n return Math.min(QUERY_MAX_LIMIT, Math.abs(limit))\n}\n\nconst normalizeNonNegativeInteger = (value: unknown): number => {\n if (typeof value !== \"number\") return 0\n if (!Number.isFinite(value) || value < 0) return 0\n return Math.floor(value)\n}\n\nconst getApproxCountSampleSize = (): number => {\n const raw = process.env.RB_RTS_APPROX_COUNT_SAMPLE_SIZE?.trim() ?? \"\"\n if (!raw) return DEFAULT_APPROX_COUNT_SAMPLE_SIZE\n\n const parsed = Number(raw)\n if (!Number.isFinite(parsed) || parsed <= 0) return DEFAULT_APPROX_COUNT_SAMPLE_SIZE\n return Math.min(MAX_APPROX_COUNT_SAMPLE_SIZE, Math.floor(parsed))\n}\n\nconst findUnsupportedApproxCountOperator = (value: unknown): string | null => {\n if (!value || typeof value !== \"object\") return null\n\n if (Array.isArray(value)) {\n for (const entry of value) {\n const unsupportedOperator = findUnsupportedApproxCountOperator(entry)\n if (unsupportedOperator) return unsupportedOperator\n }\n return null\n }\n\n for (const [key, nestedValue] of Object.entries(value as Record<string, unknown>)) {\n if (UNSUPPORTED_APPROX_COUNT_OPERATORS.has(key)) {\n return key\n }\n\n const unsupportedOperator = findUnsupportedApproxCountOperator(nestedValue)\n if (unsupportedOperator) return unsupportedOperator\n }\n\n return null\n}\n\nconst castApproxCountQuery = (model: Model<any>, query: JsonObject): JsonObject => {\n const castedQuery = model.find(query).cast(model)\n if (!castedQuery || typeof castedQuery !== \"object\" || Array.isArray(castedQuery)) {\n return query\n }\n\n return castedQuery as JsonObject\n}\n\nconst normalizeString = (value: unknown): string => {\n return typeof value === \"string\" ? value.trim() : \"\"\n}\n\nconst normalizeObject = (value: unknown): JsonObject | undefined => {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined\n return value as JsonObject\n}\n\nconst normalizePagination = (value: unknown): PaginationSpec | undefined => {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined\n return value as PaginationSpec\n}\n\nconst prepareCursorProjection = (\n projection: JsonObject | undefined,\n pagination: PaginationSpec,\n includeCursors: boolean,\n): { projection: JsonObject | undefined; addedPaths: string[] } => {\n if (!projection || !includeCursors) return { projection, addedPaths: [] }\n\n const inclusionProjection = Object.entries(projection).some(([, value]) => value === 1)\n const nextProjection = { ...projection }\n const addedPaths: string[] = []\n const sortFields = Array.isArray(pagination.sort)\n ? pagination.sort\n .map((entry) => entry?.field)\n .filter((field): field is string => typeof field === \"string\")\n : []\n const cursorPaths = Array.from(new Set([...sortFields, \"_id\"]))\n\n if (!inclusionProjection) {\n for (const path of cursorPaths) {\n const excludedPath = Object.entries(projection).find(([projectedPath, value]) =>\n value === 0 && (projectedPath === path || path.startsWith(`${projectedPath}.`)),\n )?.[0]\n if (!excludedPath) continue\n if (excludedPath !== path) {\n throw new Error(`Pagination projection cannot exclude cursor path: ${path}`)\n }\n delete nextProjection[path]\n addedPaths.push(path)\n }\n return { projection: nextProjection, addedPaths }\n }\n\n for (const path of cursorPaths) {\n const isIncluded = path === \"_id\"\n ? projection._id !== 0\n : Object.entries(projection).some(([projectedPath, value]) =>\n value === 1 && (projectedPath === path || path.startsWith(`${projectedPath}.`)),\n )\n if (isIncluded) continue\n nextProjection[path] = 1\n addedPaths.push(path)\n }\n\n return { projection: nextProjection, addedPaths }\n}\n\nconst stripPath = (target: JsonObject, path: string): void => {\n const parts = path.split(\".\")\n let current = target\n\n for (let index = 0; index < parts.length - 1; index += 1) {\n const part = parts[index]!\n const child = current[part]\n if (!child || typeof child !== \"object\" || Array.isArray(child)) return\n const cloned = { ...(child as JsonObject) }\n current[part] = cloned\n current = cloned\n }\n\n delete current[parts[parts.length - 1]!]\n}\n\nconst stripAddedProjectionPaths = (nodes: unknown[], addedPaths: string[]): unknown[] => {\n if (!addedPaths.length) return nodes\n\n return nodes.map((node) => {\n if (!node || typeof node !== \"object\" || Array.isArray(node)) return node\n const toObject = (node as { toObject?: unknown }).toObject\n const raw = typeof toObject === \"function\"\n ? toObject.call(node)\n : node\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return raw\n const projected = { ...(raw as JsonObject) }\n for (const path of addedPaths) stripPath(projected, path)\n return projected\n })\n}\n\nconst normalizePopulateSelect = (value: unknown): string | JsonObject | undefined => {\n if (typeof value === \"string\") {\n const normalized = value.trim()\n return normalized || undefined\n }\n return normalizeObject(value)\n}\n\nconst normalizePopulateOptions = (value: unknown): RtsPopulateObject[\"options\"] | undefined => {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined\n const raw = value as { sort?: unknown; limit?: unknown }\n const normalized: RtsPopulateObject[\"options\"] = {}\n\n if (raw.sort && typeof raw.sort === \"object\" && !Array.isArray(raw.sort)) {\n normalized.sort = raw.sort as Record<string, 1 | -1>\n }\n\n if (typeof raw.limit === \"number\" && Number.isFinite(raw.limit)) {\n normalized.limit = Math.max(0, Math.floor(Math.abs(raw.limit)))\n }\n\n if (!normalized.sort && normalized.limit === undefined) return undefined\n return normalized\n}\n\nconst normalizePopulateObject = (value: unknown): RtsPopulateObject | undefined => {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined\n const raw = value as Record<string, unknown>\n const path = normalizeString(raw.path)\n if (!path) return undefined\n\n const normalized: RtsPopulateObject = { path }\n\n const model = normalizeString(raw.model)\n if (model) normalized.model = model\n\n const select = normalizePopulateSelect(raw.select)\n if (select !== undefined) normalized.select = select\n\n const match = normalizeObject(raw.match)\n if (match) normalized.match = match\n\n const nestedPopulate = normalizeRtsPopulateOption(raw.populate)\n if (nestedPopulate !== undefined) normalized.populate = nestedPopulate\n\n const options = normalizePopulateOptions(raw.options)\n if (options) normalized.options = options\n\n return normalized\n}\n\nconst normalizeRtsPopulateOption = (value: unknown): RtsPopulateOption | undefined => {\n if (typeof value === \"string\") {\n const normalized = value.trim()\n return normalized || undefined\n }\n\n if (Array.isArray(value)) {\n const normalized = value\n .map((entry) => {\n if (typeof entry === \"string\") {\n const path = entry.trim()\n return path || null\n }\n return normalizePopulateObject(entry) ?? null\n })\n .filter((entry): entry is string | RtsPopulateObject => entry !== null)\n\n return normalized.length > 0 ? normalized : undefined\n }\n\n return normalizePopulateObject(value)\n}\n\nconst normalizeModelName = (value: unknown): string | null => {\n if (typeof value !== \"string\") return null\n const normalized = value.trim()\n return normalized || null\n}\n\nconst resolvePopulateRefModelName = (\n model: Model<any>,\n path: string,\n explicitModelName: string | null,\n): string | null => {\n if (explicitModelName) return explicitModelName\n\n const schema = model.schema as any\n const schemaPath = typeof schema.path === \"function\" ? schema.path(path) : null\n const directRef = normalizeModelName(schemaPath?.options?.ref)\n if (directRef) return directRef\n\n const arrayRef = normalizeModelName(schemaPath?.caster?.options?.ref)\n if (arrayRef) return arrayRef\n\n const virtualPath = typeof schema.virtualpath === \"function\" ? schema.virtualpath(path) : null\n const virtualRef = normalizeModelName(virtualPath?.options?.ref)\n if (virtualRef) return virtualRef\n\n return null\n}\n\nconst mergePopulateMatchWithAcl = (\n populateMatch: JsonObject | undefined,\n aclMatch: JsonObject,\n): JsonObject => {\n if (!populateMatch || Object.keys(populateMatch).length === 0) return aclMatch\n return { $and: [populateMatch, aclMatch] }\n}\n\ntype PreparedPopulateObject = {\n path: string\n model?: string\n select?: string | JsonObject\n match?: JsonObject\n options?: {\n sort?: Record<string, 1 | -1>\n limit?: number\n }\n populate?: PreparedPopulateOption\n}\n\ntype PreparedPopulateOption =\n | string\n | PreparedPopulateObject\n | Array<string | PreparedPopulateObject>\n\nconst resolvePopulateSpecForModel = async ({\n tenantId,\n model,\n ability,\n populate,\n allowInternalModels,\n modelCache,\n dependencyModelNames,\n}: {\n tenantId: string\n model: Model<any>\n ability: AppAbility\n populate: RtsPopulateOption | undefined\n allowInternalModels: boolean\n modelCache: Map<string, Model<any>>\n dependencyModelNames: Set<string>\n}): Promise<PreparedPopulateOption | undefined> => {\n if (!populate) return undefined\n\n const getModelCached = async (targetModelName: string): Promise<Model<any>> => {\n const cached = modelCache.get(targetModelName)\n if (cached) return cached\n const loaded = await getTenantModel(tenantId, targetModelName, ability)\n modelCache.set(targetModelName, loaded)\n return loaded\n }\n\n const resolveOne = async (\n entry: string | RtsPopulateObject,\n parentModel: Model<any>,\n ): Promise<string | PreparedPopulateObject | null> => {\n if (typeof entry === \"string\") {\n const path = entry.trim()\n if (!path) return null\n\n const refModelName = resolvePopulateRefModelName(parentModel, path, null)\n if (!refModelName) return path\n if (!allowInternalModels && INTERNAL_MODEL_NAMES.has(refModelName)) {\n throw new Error(\"Model not allowed\")\n }\n if (!ability.can(\"read\", refModelName as AclSubjectType)) {\n throw new Error(\"forbidden\")\n }\n\n dependencyModelNames.add(refModelName)\n\n const aclMatch = getAccessibleByQuery(\n ability,\n \"read\",\n refModelName as Exclude<AclSubjectType, \"all\">,\n )\n return {\n path,\n match: aclMatch as JsonObject,\n }\n }\n\n const path = entry.path.trim()\n if (!path) return null\n\n const explicitModelName = normalizeModelName(entry.model)\n const refModelName = resolvePopulateRefModelName(parentModel, path, explicitModelName)\n let nestedModel = parentModel\n\n const normalizedEntry: PreparedPopulateObject = {\n path,\n }\n\n if (entry.select !== undefined) normalizedEntry.select = entry.select\n if (entry.options !== undefined) normalizedEntry.options = entry.options\n if (explicitModelName) normalizedEntry.model = explicitModelName\n if (entry.match !== undefined) normalizedEntry.match = entry.match\n\n if (refModelName) {\n if (!allowInternalModels && INTERNAL_MODEL_NAMES.has(refModelName)) {\n throw new Error(\"Model not allowed\")\n }\n if (!ability.can(\"read\", refModelName as AclSubjectType)) {\n throw new Error(\"forbidden\")\n }\n\n dependencyModelNames.add(refModelName)\n nestedModel = await getModelCached(refModelName)\n\n const aclMatch = getAccessibleByQuery(\n ability,\n \"read\",\n refModelName as Exclude<AclSubjectType, \"all\">,\n ) as JsonObject\n normalizedEntry.match = mergePopulateMatchWithAcl(\n normalizedEntry.match,\n aclMatch,\n )\n } else if (entry.populate !== undefined) {\n throw new Error(\"Populate path must reference a model when nested populate is used\")\n }\n\n const nestedPopulate = await resolvePopulateSpecForModel({\n tenantId,\n model: nestedModel,\n ability,\n populate: entry.populate,\n allowInternalModels,\n modelCache,\n dependencyModelNames,\n })\n if (nestedPopulate !== undefined) normalizedEntry.populate = nestedPopulate\n\n return normalizedEntry\n }\n\n if (Array.isArray(populate)) {\n const resolved = await Promise.all(populate.map((entry) => resolveOne(entry, model)))\n const filtered = resolved.filter((entry): entry is string | PreparedPopulateObject => entry !== null)\n return filtered.length > 0 ? filtered : undefined\n }\n\n const resolved = await resolveOne(populate, model)\n return resolved ?? undefined\n}\n\nexport const normalizeRtsQueryOptions = (options: RtsQueryOptions | undefined): RtsQueryOptions => {\n if (!options || typeof options !== \"object\") return {}\n const normalized: RtsQueryOptions = {}\n\n if (options.projection && typeof options.projection === \"object\" && !Array.isArray(options.projection)) {\n normalized.projection = options.projection\n }\n\n if (options.sort && typeof options.sort === \"object\" && !Array.isArray(options.sort)) {\n normalized.sort = options.sort\n }\n\n normalized.limit = normalizeLimit(options.limit)\n normalized.populate = normalizeRtsPopulateOption(options.populate)\n normalized.pagination = normalizePagination(options.pagination)\n\n return normalized\n}\n\nexport const resolveRtsQueryDependencyModelNames = async ({\n tenantId,\n ability,\n modelName,\n options,\n allowInternalModels = false,\n}: {\n tenantId: string\n ability: AppAbility\n modelName: string\n options: RtsQueryOptions\n allowInternalModels?: boolean\n}): Promise<string[]> => {\n const model = await getTenantModel(tenantId, modelName, ability)\n const modelCache = new Map<string, Model<any>>()\n modelCache.set(modelName, model)\n\n const dependencyModelNames = new Set<string>()\n await resolvePopulateSpecForModel({\n tenantId,\n model,\n ability,\n populate: options.populate,\n allowInternalModels,\n modelCache,\n dependencyModelNames,\n })\n\n return Array.from(dependencyModelNames)\n}\n\nexport const runRtsQuery = async ({\n tenantId,\n ability,\n modelName,\n query,\n options,\n allowInternalModels = false,\n paginationMaxLimit,\n includePaginationCursors = true,\n}: {\n tenantId: string\n ability: AppAbility\n modelName: string\n query: JsonObject\n options: RtsQueryOptions\n allowInternalModels?: boolean\n paginationMaxLimit?: number\n includePaginationCursors?: boolean\n}): Promise<RtsQueryResult> => {\n const { model, finalQuery } = await prepareRtsExecution({\n tenantId,\n ability,\n modelName,\n query,\n allowInternalModels,\n })\n const projection = options.projection ?? undefined\n const sort = options.sort\n const limit = normalizeLimit(options.limit)\n const modelCache = new Map<string, Model<any>>()\n modelCache.set(modelName, model)\n\n const populate = await resolvePopulateSpecForModel({\n tenantId,\n model,\n ability,\n populate: options.populate,\n allowInternalModels,\n modelCache,\n dependencyModelNames: new Set<string>(),\n })\n\n if (options.pagination) {\n const cursorProjection = prepareCursorProjection(\n projection,\n options.pagination,\n includePaginationCursors,\n )\n const paginatedQuery = model.find(finalQuery, cursorProjection.projection)\n if (populate !== undefined) {\n paginatedQuery.populate(populate as any)\n }\n\n const paginatedResult = await paginatedQuery.paginate(options.pagination, {\n cursor: {\n signingSecret: getPaginationCursorSigningSecret(),\n ...(paginationMaxLimit !== undefined ? { maxLimit: paginationMaxLimit } : {}),\n },\n includeCursors: includePaginationCursors,\n })\n const totalCount = typeof paginatedResult.totalCount === \"number\"\n && Number.isFinite(paginatedResult.totalCount)\n && paginatedResult.totalCount >= 0\n ? Math.floor(paginatedResult.totalCount)\n : undefined\n const approximateTotalCount = totalCount === undefined\n ? await runApproximateRtsCount(model, finalQuery).catch(() => undefined)\n : undefined\n const resolvedTotalCount = totalCount ?? approximateTotalCount\n\n return {\n data: Array.isArray(paginatedResult.nodes)\n ? stripAddedProjectionPaths(paginatedResult.nodes, cursorProjection.addedPaths)\n : [],\n pageInfo: paginatedResult.pageInfo,\n ...(resolvedTotalCount !== undefined ? { totalCount: resolvedTotalCount } : {}),\n }\n }\n\n const queryPromise = model.find(finalQuery, projection)\n if (populate !== undefined) {\n queryPromise.populate(populate as any)\n }\n if (sort && Object.keys(sort).length) {\n queryPromise.sort(sort)\n }\n queryPromise.limit(limit)\n\n const data = await queryPromise\n return { data: Array.isArray(data) ? data : [] }\n}\n\nconst prepareRtsExecution = async ({\n tenantId,\n ability,\n modelName,\n query,\n allowInternalModels = false,\n}: {\n tenantId: string\n ability: AppAbility\n modelName: string\n query: JsonObject\n allowInternalModels?: boolean\n}): Promise<PreparedRtsExecution> => {\n if (!allowInternalModels && INTERNAL_MODEL_NAMES.has(modelName)) {\n throw new Error(\"Model not allowed\")\n }\n\n if (!ability.can(\"read\", modelName as AclSubjectType)) {\n throw new Error(\"forbidden\")\n }\n\n const model = await getTenantModel(tenantId, modelName, ability)\n const accessQuery = getAccessibleByQuery(ability, \"read\", modelName as Exclude<AclSubjectType, \"all\">)\n const finalQuery: JsonObject = { $and: [query, accessQuery] }\n\n return { model, finalQuery }\n}\n\nconst runApproximateRtsCount = async (model: Model<any>, query: JsonObject): Promise<number> => {\n const unsupportedOperator = findUnsupportedApproxCountOperator(query)\n if (unsupportedOperator) {\n throw new Error(`Approximate RTS count does not support ${unsupportedOperator} queries`)\n }\n\n const castedQuery = castApproxCountQuery(model, query)\n const estimatedTotal = normalizeNonNegativeInteger(await model.estimatedDocumentCount())\n if (estimatedTotal === 0) return 0\n\n const sampleSize = Math.min(getApproxCountSampleSize(), estimatedTotal)\n const sampleResult = await model.aggregate([\n { $sample: { size: sampleSize } },\n { $match: castedQuery },\n { $count: \"count\" },\n ]) as Array<{ count?: unknown }>\n const sampleMatches = normalizeNonNegativeInteger(sampleResult[0]?.count)\n\n if (sampleSize >= estimatedTotal) {\n return Math.min(sampleMatches, estimatedTotal)\n }\n\n const estimatedMatches = Math.round((estimatedTotal * sampleMatches) / sampleSize)\n return Math.max(0, Math.min(estimatedTotal, estimatedMatches))\n}\n\nexport const runRtsCount = async ({\n tenantId,\n ability,\n modelName,\n query,\n allowInternalModels = false,\n}: {\n tenantId: string\n ability: AppAbility\n modelName: string\n query: JsonObject\n allowInternalModels?: boolean\n}): Promise<number> => {\n const { model, finalQuery } = await prepareRtsExecution({\n tenantId,\n ability,\n modelName,\n query,\n allowInternalModels,\n })\n\n return await runApproximateRtsCount(model, finalQuery)\n}\n","export const RTS_QUERY_WINDOW_MAX_COUNT = 4096\n"],"names":["getDerivedKey","masterKey","info","length","salt","assert","Buffer","from","hkdfSync","toString","AUTHENTICATED_USER_ID_HEADER","AUTHENTICATED_TENANT_ID_HEADER","PROXY_AUTH_TIMESTAMP_HEADER","PROXY_AUTH_SIGNATURE_HEADER","MAX_PROXY_AUTH_AGE_MS","normalizeString","value","normalized","trim","getHeaderValue","headers","name","Array","isArray","getProxySharedSecret","secret","process","env","RB_PROXY_SHARED_SECRET","timingSafeEqualText","left","right","leftBuffer","rightBuffer","timingSafeEqual","buildProxyAuthSignature","userId","tenantId","timestamp","createHmac","update","digest","getTrustedProxyAuth","signature","parsedTimestamp","Number","isInteger","now","Date","Math","abs","expectedSignature","normalizeStringArray","map","entry","String","filter","Boolean","normalizeRoles","normalizeTenantRoles","undefined","Map","entries","roles","normalizedTenantId","Object","fromEntries","nextRoles","isSessionAuthorizedForTenant","sessionUser","signedInTenants","includes","currentTenantId","loadSessionUser","ctx","req","session","User","models","getGlobal","user","findById","tenants","tenantRoles","lean","id","isEntryGateAuthorized","syncAuthenticatedSessionFromRequest","proxyAuth","sessionUserId","baseUser","nextSessionUser","syncAuthenticatedSessionMiddleware","_res","next","then","QUERY_MAX_LIMIT","INTERNAL_MODEL_NAMES","Set","DEFAULT_APPROX_COUNT_SAMPLE_SIZE","MAX_APPROX_COUNT_SAMPLE_SIZE","UNSUPPORTED_APPROX_COUNT_OPERATORS","paginationCursorSigningSecret","getPaginationCursorSigningSecret","MASTER_KEY","Error","normalizeTenantId","getTenantIdFromRequest","resolveRtsRequestTenantId","isRtsRequestAuthorized","buildRtsAbilityFromRequest","ability","buildAbilityFromSession","getTenantModel","modelName","get","normalizeLimit","limit","isFinite","min","normalizeNonNegativeInteger","floor","getApproxCountSampleSize","raw","RB_RTS_APPROX_COUNT_SAMPLE_SIZE","parsed","findUnsupportedApproxCountOperator","unsupportedOperator","key","nestedValue","has","castApproxCountQuery","model","query","castedQuery","find","cast","normalizeObject","normalizePagination","prepareCursorProjection","projection","pagination","includeCursors","addedPaths","inclusionProjection","some","nextProjection","sortFields","sort","field","cursorPaths","path","excludedPath","projectedPath","startsWith","push","isIncluded","_id","stripPath","target","parts","split","current","index","part","child","cloned","stripAddedProjectionPaths","nodes","node","toObject","call","projected","normalizePopulateSelect","normalizePopulateOptions","max","normalizePopulateObject","select","match","nestedPopulate","normalizeRtsPopulateOption","populate","options","normalizeModelName","resolvePopulateRefModelName","explicitModelName","schema","schemaPath","directRef","ref","arrayRef","caster","virtualPath","virtualpath","virtualRef","mergePopulateMatchWithAcl","populateMatch","aclMatch","keys","$and","resolvePopulateSpecForModel","allowInternalModels","modelCache","dependencyModelNames","getModelCached","targetModelName","cached","loaded","set","resolveOne","parentModel","refModelName","can","add","getAccessibleByQuery","nestedModel","normalizedEntry","resolved","Promise","all","filtered","normalizeRtsQueryOptions","resolveRtsQueryDependencyModelNames","runRtsQuery","paginationMaxLimit","includePaginationCursors","finalQuery","prepareRtsExecution","cursorProjection","paginatedQuery","paginatedResult","paginate","cursor","signingSecret","maxLimit","totalCount","approximateTotalCount","runApproximateRtsCount","catch","resolvedTotalCount","data","pageInfo","queryPromise","accessQuery","estimatedTotal","estimatedDocumentCount","sampleSize","sampleResult","aggregate","$sample","size","$match","$count","sampleMatches","count","estimatedMatches","round","runRtsCount","RTS_QUERY_WINDOW_MAX_COUNT"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rts/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAmB,MAAM,IAAI,UAAU,EAAE,MAAM,WAAW,CAAA;AAGtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAG7C,OAAO,EAAgD,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAG/F,OAAO,EAAiC,KAAK,SAAS,EAAE,MAAM,IAAI,CAAA;AAgElE,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,KAAK,UAAU,GAAG;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,UAAU,CAAA;CACpB,CAAA;AAyBD,KAAK,SAAS,GAAG,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,CAAA;AA+B3D,cAAM,SAAS;IACb,SAAgB,EAAE,EAAE,MAAM,CAAA;IAC1B,SAAgB,QAAQ,EAAE,MAAM,CAAA;IAChC,SAAgB,MAAM,EAAE,MAAM,CAAA;IAE9B,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAW;IAC9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqD;IAC9E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqD;gBAElE,EACjB,EAAE,EACF,EAAE,EACF,IAAI,GACL,EAAE;QACD,EAAE,EAAE,MAAM,CAAA;QACV,EAAE,EAAE,SAAS,CAAA;QACb,IAAI,EAAE,UAAU,CAAA;KACjB;IAOM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI;IAOlE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAO7D,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI;IAI5C,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI;IAO9E,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAOzE,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI;IAIxD,KAAK,IAAI,IAAI;IAQb,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAQ/C,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;CAOnE;AAw2BD,eAAO,MAAM,OAAO,GAAI,4NAQrB;IACD,MAAM,EAAE,UAAU,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,iBAAiB,EAAE,cAAc,CAAA;IACjC,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,yBAAyB,CAAC,EAAE,MAAM,CAAA;IAClC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAC9B,KAAG,IA6IH,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,SAAS,SAAS,KAAG,IAEvD,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAI,wCAAwC,sBAAsB,KAAG,IAalG,CAAA;AAED,eAAO,MAAM,qBAAqB,GAAI,UAAU,MAAM,EAAE,WAAW,MAAM,KAAG,IAE3E,CAAA;AAED,cAAc,UAAU,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rts/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAmB,MAAM,IAAI,UAAU,EAAE,MAAM,WAAW,CAAA;AAGtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAG7C,OAAO,EAAgD,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAG/F,OAAO,EAAiC,KAAK,SAAS,EAAE,MAAM,IAAI,CAAA;AAmElE,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,KAAK,UAAU,GAAG;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,UAAU,CAAA;CACpB,CAAA;AAiCD,KAAK,SAAS,GAAG,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,CAAA;AAqC3D,cAAM,SAAS;IACb,SAAgB,EAAE,EAAE,MAAM,CAAA;IAC1B,SAAgB,QAAQ,EAAE,MAAM,CAAA;IAChC,SAAgB,MAAM,EAAE,MAAM,CAAA;IAE9B,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAW;IAC9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqD;IAC9E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqD;gBAElE,EACjB,EAAE,EACF,EAAE,EACF,IAAI,GACL,EAAE;QACD,EAAE,EAAE,MAAM,CAAA;QACV,EAAE,EAAE,SAAS,CAAA;QACb,IAAI,EAAE,UAAU,CAAA;KACjB;IAOM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI;IAOlE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAO7D,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI;IAI5C,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI;IAO9E,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAOzE,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI;IAIxD,KAAK,IAAI,IAAI;IAQb,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAQ/C,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;CAOnE;AAilCD,eAAO,MAAM,OAAO,GAAI,4NAQrB;IACD,MAAM,EAAE,UAAU,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,iBAAiB,EAAE,cAAc,CAAA;IACjC,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,yBAAyB,CAAC,EAAE,MAAM,CAAA;IAClC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAC9B,KAAG,IAkJH,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,SAAS,SAAS,KAAG,IAEvD,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAI,wCAAwC,sBAAsB,KAAG,IAalG,CAAA;AAED,eAAO,MAAM,qBAAqB,GAAI,UAAU,MAAM,EAAE,WAAW,MAAM,KAAG,IAE3E,CAAA;AAED,cAAc,UAAU,CAAA"}
package/dist/rts/index.js CHANGED
@@ -2,7 +2,7 @@ import { randomUUID } from "node:crypto";
2
2
  import { models } from "@rpcbase/db";
3
3
  import { buildAbilityFromSession } from "@rpcbase/db/acl";
4
4
  import { WebSocketServer } from "ws";
5
- import { d as syncAuthenticatedSessionFromRequest, n as normalizeRtsQueryOptions, e as resolveRtsQueryDependencyModelNames, a as runRtsQuery, c as runRtsCount } from "../queryExecutor-DW7iAdRY.js";
5
+ import { d as syncAuthenticatedSessionFromRequest, n as normalizeRtsQueryOptions, e as resolveRtsQueryDependencyModelNames, R as RTS_QUERY_WINDOW_MAX_COUNT, a as runRtsQuery, c as runRtsCount } from "../queryWindow-Cdr7K-S1.js";
6
6
  const routes = Object.entries({
7
7
  .../* @__PURE__ */ Object.assign({ "./api/changes/handler.ts": () => import("../handler-BqoKvylN.js") })
8
8
  }).reduce((acc, [path, mod]) => {
@@ -31,6 +31,7 @@ let maxPayloadBytes = DEFAULT_MAX_PAYLOAD_BYTES;
31
31
  let maxSubscriptionsPerSocket = DEFAULT_MAX_SUBSCRIPTIONS_PER_SOCKET;
32
32
  let dispatchDebounceMs = DEFAULT_DISPATCH_DEBOUNCE_MS;
33
33
  let allowInternalModels = false;
34
+ const isValidQueryWindowCount = (value) => typeof value === "number" && Number.isInteger(value) && value >= 1 && value <= RTS_QUERY_WINDOW_MAX_COUNT;
34
35
  class RtsSocket {
35
36
  id;
36
37
  tenantId;
@@ -273,6 +274,107 @@ const runAndSendQuery = async ({
273
274
  sendWs(ws, payload);
274
275
  }
275
276
  };
277
+ const getHeadWindowOptions = (options, requestedCount) => {
278
+ if (!options.pagination) return options;
279
+ const pagination = {
280
+ ...options.pagination,
281
+ limit: requestedCount
282
+ };
283
+ delete pagination.cursor;
284
+ delete pagination.direction;
285
+ return {
286
+ ...options,
287
+ pagination
288
+ };
289
+ };
290
+ const runAndSendSubscriptionQuery = async ({
291
+ tenantId,
292
+ targetSocketIds,
293
+ ability,
294
+ modelName,
295
+ queryKey,
296
+ subscription
297
+ }) => {
298
+ if (!subscription.options.pagination) {
299
+ await runAndSendQuery({
300
+ tenantId,
301
+ targetSocketIds,
302
+ ability,
303
+ modelName,
304
+ queryKey,
305
+ query: subscription.query,
306
+ options: subscription.options
307
+ });
308
+ return;
309
+ }
310
+ const groups = /* @__PURE__ */ new Map();
311
+ for (const socketId of targetSocketIds) {
312
+ const state = subscription.windows.get(socketId);
313
+ if (!state) continue;
314
+ state.version += 1;
315
+ const targets = groups.get(state.requestedCount) ?? [];
316
+ targets.push({
317
+ socketId,
318
+ window: {
319
+ requestedCount: state.requestedCount,
320
+ version: state.version
321
+ }
322
+ });
323
+ groups.set(state.requestedCount, targets);
324
+ }
325
+ await Promise.all(Array.from(groups.entries()).map(async ([requestedCount, targets]) => {
326
+ try {
327
+ const result = await runRtsQuery({
328
+ tenantId,
329
+ ability,
330
+ modelName,
331
+ query: subscription.query,
332
+ options: getHeadWindowOptions(subscription.options, requestedCount),
333
+ allowInternalModels,
334
+ paginationMaxLimit: RTS_QUERY_WINDOW_MAX_COUNT,
335
+ includePaginationCursors: false
336
+ });
337
+ for (const target of targets) {
338
+ const current = subscription.windows.get(target.socketId);
339
+ if (!current || current.requestedCount !== target.window.requestedCount || current.version !== target.window.version) {
340
+ continue;
341
+ }
342
+ const ws = sockets.get(target.socketId);
343
+ if (!ws) continue;
344
+ sendWs(ws, {
345
+ type: "query-payload",
346
+ modelName,
347
+ queryKey,
348
+ data: result.data,
349
+ ...result.pageInfo ? {
350
+ pageInfo: result.pageInfo
351
+ } : {},
352
+ ...typeof result.totalCount === "number" ? {
353
+ totalCount: result.totalCount
354
+ } : {},
355
+ window: target.window
356
+ });
357
+ }
358
+ } catch (err) {
359
+ const error = redactErrorMessage(err);
360
+ for (const target of targets) {
361
+ const current = subscription.windows.get(target.socketId);
362
+ if (!current || current.requestedCount !== target.window.requestedCount || current.version !== target.window.version) {
363
+ continue;
364
+ }
365
+ const ws = sockets.get(target.socketId);
366
+ if (!ws) continue;
367
+ sendWs(ws, {
368
+ type: "query-payload",
369
+ modelName,
370
+ queryKey,
371
+ error,
372
+ window: target.window
373
+ });
374
+ }
375
+ }
376
+ }));
377
+ };
276
378
  const runAndSendCount = async ({
277
379
  tenantId,
278
380
  targetSocketIds,
@@ -343,14 +445,13 @@ const dispatchSubscriptionsForModel = async (tenantId, modelName) => {
343
445
  const ability = meta?.ability;
344
446
  if (!ability) continue;
345
447
  try {
346
- await runAndSendQuery({
448
+ await runAndSendSubscriptionQuery({
347
449
  tenantId,
348
450
  targetSocketIds,
349
451
  ability,
350
452
  modelName: ownerModelName,
351
453
  queryKey,
352
- query: sub.query,
353
- options: sub.options
454
+ subscription: sub
354
455
  });
355
456
  } catch (err) {
356
457
  const error = redactErrorMessage(err);
@@ -435,6 +536,21 @@ const ensureChangeStream = async (tenantId, modelName) => {
435
536
  });
436
537
  tenantStreams.set(modelName, stream);
437
538
  };
539
+ const closeUnusedChangeStream = (tenantId, modelName) => {
540
+ if (hasAnySubscriptionsDependingOnModel(tenantId, modelName) || hasAnyCountSubscriptionsForModel(tenantId, modelName)) {
541
+ return;
542
+ }
543
+ const tenantStreams = changeStreams.get(tenantId);
544
+ const stream = tenantStreams?.get(modelName);
545
+ if (!stream) return;
546
+ try {
547
+ stream.close();
548
+ } catch {
549
+ }
550
+ clearDispatchTimer(tenantId, modelName);
551
+ tenantStreams?.delete(modelName);
552
+ if (tenantStreams && tenantStreams.size === 0) changeStreams.delete(tenantId);
553
+ };
438
554
  const addSocketSubscription = ({
439
555
  socketId,
440
556
  tenantId,
@@ -455,12 +571,24 @@ const addSocketSubscription = ({
455
571
  if (existing) {
456
572
  existing.socketIds.add(socketId);
457
573
  existing.dependencyModelNames = Array.from(/* @__PURE__ */ new Set([...existing.dependencyModelNames, ...dependencyModelNames]));
574
+ if (options.pagination) {
575
+ existing.windows.set(socketId, {
576
+ requestedCount: options.pagination.limit,
577
+ version: 0
578
+ });
579
+ } else {
580
+ existing.windows.delete(socketId);
581
+ }
458
582
  } else {
459
583
  modelSubs.set(queryKey, {
460
584
  query,
461
585
  options,
462
586
  dependencyModelNames: Array.from(new Set(dependencyModelNames)),
463
- socketIds: /* @__PURE__ */ new Set([socketId])
587
+ socketIds: /* @__PURE__ */ new Set([socketId]),
588
+ windows: options.pagination ? /* @__PURE__ */ new Map([[socketId, {
589
+ requestedCount: options.pagination.limit,
590
+ version: 0
591
+ }]]) : /* @__PURE__ */ new Map()
464
592
  });
465
593
  }
466
594
  const byModel = socketSubscriptions.get(socketId) ?? /* @__PURE__ */ new Map();
@@ -512,6 +640,7 @@ const removeSocketSubscription = ({
512
640
  const affectedModelNames = /* @__PURE__ */ new Set([modelName, ...sub?.dependencyModelNames ?? []]);
513
641
  if (sub) {
514
642
  sub.socketIds.delete(socketId);
643
+ sub.windows.delete(socketId);
515
644
  if (!sub.socketIds.size) {
516
645
  modelSubs?.delete(queryKey);
517
646
  }
@@ -716,15 +845,56 @@ const handleClientMessage = async ({
716
845
  });
717
846
  return;
718
847
  }
719
- if (!message.query || typeof message.query !== "object") return;
720
848
  const ability = meta.ability;
721
849
  if (!ability.can("read", message.modelName)) {
722
850
  sendAccessError("forbidden");
723
851
  return;
724
852
  }
853
+ if (message.type === "set-query-window") {
854
+ if (!isValidQueryWindowCount(message.requestedCount)) {
855
+ sendWs(ws, {
856
+ type: "query-payload",
857
+ modelName: message.modelName,
858
+ queryKey: message.queryKey,
859
+ error: "Invalid requestedCount"
860
+ });
861
+ return;
862
+ }
863
+ const subscription = subscriptions.get(meta.tenantId)?.get(meta.userId)?.get(message.modelName)?.get(message.queryKey);
864
+ const window = subscription?.windows.get(socketId);
865
+ if (!subscription || !subscription.options.pagination || !window) {
866
+ sendWs(ws, {
867
+ type: "query-payload",
868
+ modelName: message.modelName,
869
+ queryKey: message.queryKey,
870
+ error: "Paginated query subscription not found"
871
+ });
872
+ return;
873
+ }
874
+ window.requestedCount = message.requestedCount;
875
+ await runAndSendSubscriptionQuery({
876
+ tenantId: meta.tenantId,
877
+ targetSocketIds: [socketId],
878
+ ability,
879
+ modelName: message.modelName,
880
+ queryKey: message.queryKey,
881
+ subscription
882
+ });
883
+ return;
884
+ }
885
+ if (!message.query || typeof message.query !== "object") return;
725
886
  if (message.type === "register-query" || message.type === "run-query") {
726
887
  const options = normalizeRtsQueryOptions(message.options);
727
888
  if (message.type === "register-query") {
889
+ if (options.pagination && !isValidQueryWindowCount(options.pagination.limit)) {
890
+ sendWs(ws, {
891
+ type: "query-payload",
892
+ modelName: message.modelName,
893
+ queryKey: message.queryKey,
894
+ error: "Invalid requestedCount"
895
+ });
896
+ return;
897
+ }
728
898
  const existing = socketSubscriptions.get(socketId)?.get(message.modelName)?.has(message.queryKey) ?? false;
729
899
  if (!existing && getSocketSubscriptionCount(socketId) >= maxSubscriptionsPerSocket) {
730
900
  sendWs(ws, {
@@ -756,6 +926,7 @@ const handleClientMessage = async ({
756
926
  return;
757
927
  }
758
928
  }
929
+ if (!sockets.has(socketId)) return;
759
930
  addSocketSubscription({
760
931
  socketId,
761
932
  tenantId: meta.tenantId,
@@ -781,9 +952,36 @@ const handleClientMessage = async ({
781
952
  });
782
953
  return;
783
954
  }
955
+ if (!sockets.has(socketId)) {
956
+ for (const modelName of /* @__PURE__ */ new Set([message.modelName, ...dependencyModelNames])) {
957
+ closeUnusedChangeStream(meta.tenantId, modelName);
958
+ }
959
+ return;
960
+ }
784
961
  if (message.runInitialQuery === false) {
785
962
  return;
786
963
  }
964
+ const subscription = subscriptions.get(meta.tenantId)?.get(meta.userId)?.get(message.modelName)?.get(message.queryKey);
965
+ if (!subscription) return;
966
+ try {
967
+ await runAndSendSubscriptionQuery({
968
+ tenantId: meta.tenantId,
969
+ targetSocketIds: [socketId],
970
+ ability,
971
+ modelName: message.modelName,
972
+ queryKey: message.queryKey,
973
+ subscription
974
+ });
975
+ } catch (err) {
976
+ const error = redactErrorMessage(err);
977
+ sendWs(ws, {
978
+ type: "query-payload",
979
+ modelName: message.modelName,
980
+ queryKey: message.queryKey,
981
+ error
982
+ });
983
+ }
984
+ return;
787
985
  }
788
986
  try {
789
987
  await runAndSendQuery({
@@ -838,6 +1036,10 @@ const handleClientMessage = async ({
838
1036
  });
839
1037
  return;
840
1038
  }
1039
+ if (!sockets.has(socketId)) {
1040
+ closeUnusedChangeStream(meta.tenantId, message.modelName);
1041
+ return;
1042
+ }
841
1043
  if (message.runInitialQuery === false) {
842
1044
  return;
843
1045
  }
@@ -970,6 +1172,7 @@ const initRts = ({
970
1172
  }
971
1173
  }
972
1174
  if (cleanupFns.length) socketCleanup.set(socketId, cleanupFns);
1175
+ let messageQueue = Promise.resolve();
973
1176
  ws.on("message", (raw) => {
974
1177
  let parsed;
975
1178
  try {
@@ -979,12 +1182,12 @@ const initRts = ({
979
1182
  }
980
1183
  if (!parsed || typeof parsed !== "object") return;
981
1184
  const message = parsed;
982
- if (message.type !== "event" && message.type !== "rts-message" && message.type !== "run-query" && message.type !== "register-query" && message.type !== "remove-query" && message.type !== "run-count" && message.type !== "register-count" && message.type !== "remove-count") return;
983
- void handleClientMessage({
1185
+ if (message.type !== "event" && message.type !== "rts-message" && message.type !== "run-query" && message.type !== "register-query" && message.type !== "set-query-window" && message.type !== "remove-query" && message.type !== "run-count" && message.type !== "register-count" && message.type !== "remove-count") return;
1186
+ messageQueue = messageQueue.then(() => handleClientMessage({
984
1187
  socketId,
985
1188
  meta,
986
1189
  message
987
- });
1190
+ })).catch(() => void 0);
988
1191
  });
989
1192
  ws.on("close", () => {
990
1193
  cleanupSocket(socketId);