{"version":3,"file":"lazy-targets.cjs","sources":["../../../../src/query/compiler/lazy-targets.ts"],"sourcesContent":["import { PropRef, followRef } from '../ir.js'\nimport type {\n  BasicExpression,\n  CollectionRef,\n  From,\n  QueryIR,\n  QueryRef,\n} from '../ir.js'\nimport type { Collection } from '../../collection/index.js'\n\nexport type LazyLoadTarget = {\n  alias: string\n  collection: Collection\n  path: Array<string>\n}\n\nexport function getLazyLoadTargets(\n  rawQuery: QueryIR,\n  lazyFrom: From,\n  lazyAlias: string,\n  lazySourceExpr: BasicExpression,\n  lazySource: Collection | undefined,\n  aliasRemapping: Record<string, string>,\n): Array<LazyLoadTarget> {\n  if (lazyFrom.type === `unionFrom`) {\n    return getTargetsFromExpression(rawQuery, lazySourceExpr)\n  }\n\n  if (lazyFrom.type === `queryRef` && containsUnionFrom(lazyFrom.query.from)) {\n    const targets = getTargetsFromQueryRef(\n      lazyFrom.query,\n      lazyAlias,\n      lazySourceExpr,\n    )\n    return dedupeLazyLoadTargets(targets)\n  }\n\n  if (!lazySource) {\n    return []\n  }\n\n  const lazySourceRef = toPropRef(lazySourceExpr)\n  if (!lazySourceRef) {\n    return []\n  }\n\n  const followRefResult = followRef(rawQuery, lazySourceRef, lazySource)\n  if (!followRefResult) {\n    return []\n  }\n\n  return [\n    {\n      alias: aliasRemapping[lazyAlias] || lazyAlias,\n      collection: followRefResult.collection,\n      path: followRefResult.path,\n    },\n  ]\n}\n\nexport function containsUnionFrom(from: From): boolean {\n  if (from.type === `unionFrom`) {\n    return true\n  }\n  if (from.type === `queryRef`) {\n    return containsUnionFrom(from.query.from)\n  }\n  if (from.type === `unionAll`) {\n    return from.queries.some((query) => containsUnionFrom(query.from))\n  }\n  return false\n}\n\nfunction getTargetsFromQueryRef(\n  query: QueryIR,\n  outerAlias: string,\n  expr: unknown,\n): Array<LazyLoadTarget> {\n  if (!expr || typeof expr !== `object` || !(`type` in expr)) {\n    return []\n  }\n\n  const expression = expr as BasicExpression\n  if (expression.type === `func` && expression.name === `coalesce`) {\n    return dedupeLazyLoadTargets(\n      expression.args.flatMap((arg) =>\n        getTargetsFromQueryRef(query, outerAlias, arg),\n      ),\n    )\n  }\n\n  const ref = toPropRef(expression)\n  if (!ref || ref.path[0] !== outerAlias) {\n    return []\n  }\n\n  return getTargetsFromPropRef(query, new PropRef(ref.path.slice(1)))\n}\n\nfunction getTargetsFromExpression(\n  query: QueryIR,\n  expr: unknown,\n): Array<LazyLoadTarget> {\n  if (!expr || typeof expr !== `object` || !(`type` in expr)) {\n    return []\n  }\n\n  const expression = expr as BasicExpression\n  if (expression.type === `ref`) {\n    return getTargetsFromPropRef(query, expression)\n  }\n\n  if (expression.type === `func` && expression.name === `coalesce`) {\n    return dedupeLazyLoadTargets(\n      expression.args.flatMap((arg) => getTargetsFromExpression(query, arg)),\n    )\n  }\n\n  return []\n}\n\nfunction getTargetsFromPropRef(\n  query: QueryIR,\n  ref: PropRef,\n): Array<LazyLoadTarget> {\n  if (ref.path.length === 0) {\n    return []\n  }\n\n  if (ref.path.length === 1) {\n    const field = ref.path[0]!\n    const selectedField = query.select?.[field]\n    if (selectedField) {\n      return getTargetsFromExpression(query, selectedField)\n    }\n    return []\n  }\n\n  const [alias, ...path] = ref.path\n  const source = getSourceFromAlias(query, alias!)\n  if (!source) {\n    return []\n  }\n\n  if (source.type === `collectionRef`) {\n    return [{ alias: source.alias, collection: source.collection, path }]\n  }\n\n  if (source.query.limit || source.query.offset) {\n    return []\n  }\n\n  return getTargetsFromQueryRef(source.query, source.alias, ref)\n}\n\nfunction getSourceFromAlias(\n  query: QueryIR,\n  alias: string,\n): CollectionRef | QueryRef | undefined {\n  if (query.join) {\n    for (const join of query.join) {\n      if (join.from.alias === alias) {\n        return join.from\n      }\n    }\n  }\n\n  const from = query.from\n  const sources =\n    from.type === `unionFrom`\n      ? from.sources\n      : from.type === `unionAll`\n        ? []\n        : [from]\n  return sources.find((source) => source.alias === alias)\n}\n\nfunction dedupeLazyLoadTargets(\n  targets: Array<LazyLoadTarget>,\n): Array<LazyLoadTarget> {\n  const seen = new Set<string>()\n  const deduped: Array<LazyLoadTarget> = []\n  for (const target of targets) {\n    const key = `${target.alias}:${target.path.join(`.`)}`\n    if (!seen.has(key)) {\n      seen.add(key)\n      deduped.push(target)\n    }\n  }\n  return deduped\n}\n\nfunction toPropRef(expr: unknown): PropRef | undefined {\n  if (expr instanceof PropRef) {\n    return expr\n  }\n  if (\n    expr &&\n    typeof expr === `object` &&\n    `type` in expr &&\n    (expr as { type?: string }).type === `ref` &&\n    Array.isArray((expr as { path?: unknown }).path)\n  ) {\n    return new PropRef((expr as unknown as { path: Array<string> }).path)\n  }\n  return undefined\n}\n"],"names":["followRef","PropRef"],"mappings":"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"}