{"version":3,"file":"joins.cjs","sources":["../../../../src/query/compiler/joins.ts"],"sourcesContent":["import { filter, join as joinOperator, map, tap } from '@tanstack/db-ivm'\nimport {\n  CollectionInputNotFoundError,\n  InvalidJoinCondition,\n  InvalidJoinConditionLeftSourceError,\n  InvalidJoinConditionRightSourceError,\n  InvalidJoinConditionSameSourceError,\n  InvalidJoinConditionSourceMismatchError,\n  JoinCollectionNotFoundError,\n  SubscriptionNotFoundError,\n  UnsupportedJoinSourceTypeError,\n  UnsupportedJoinTypeError,\n} from '../../errors.js'\nimport { normalizeValue } from '../../utils/comparison.js'\nimport { ensureIndexForField } from '../../indexes/auto-index.js'\nimport { PropRef } from '../ir.js'\nimport { inArray } from '../builder/functions.js'\nimport { compileExpression } from './evaluators.js'\nimport { getLazyLoadTargets } from './lazy-targets.js'\nimport type { CompileQueryFn } from './index.js'\nimport type { OrderByOptimizationInfo } from './order-by.js'\nimport type {\n  BasicExpression,\n  CollectionRef,\n  JoinClause,\n  QueryIR,\n  QueryRef,\n} from '../ir.js'\nimport type { IStreamBuilder, JoinType } from '@tanstack/db-ivm'\nimport type { Collection } from '../../collection/index.js'\nimport type {\n  KeyedStream,\n  NamespacedAndKeyedStream,\n  NamespacedRow,\n} from '../../types.js'\nimport type { QueryCache, QueryMapping, WindowOptions } from './types.js'\nimport type { CollectionSubscription } from '../../collection/subscription.js'\n\n/** Function type for loading specific keys into a lazy collection */\nexport type LoadKeysFn = (key: Set<string | number>) => void\n\n/** Callbacks for managing lazy-loaded collections in optimized joins */\nexport type LazyCollectionCallbacks = {\n  loadKeys: LoadKeysFn\n  loadInitialState: () => void\n}\n\n/**\n * Processes all join clauses, applying lazy loading optimizations and maintaining\n * alias tracking for per-alias subscriptions (enables self-joins).\n */\nexport function processJoins(\n  pipeline: NamespacedAndKeyedStream,\n  joinClauses: Array<JoinClause>,\n  sources: Record<string, KeyedStream>,\n  mainCollectionId: string,\n  mainSource: string,\n  allInputs: Record<string, KeyedStream>,\n  cache: QueryCache,\n  queryMapping: QueryMapping,\n  collections: Record<string, Collection>,\n  subscriptions: Record<string, CollectionSubscription>,\n  callbacks: Record<string, LazyCollectionCallbacks>,\n  lazySources: Set<string>,\n  optimizableOrderByCollections: Record<string, OrderByOptimizationInfo>,\n  setWindowFn: (windowFn: (options: WindowOptions) => void) => void,\n  rawQuery: QueryIR,\n  onCompileSubquery: CompileQueryFn,\n  aliasToCollectionId: Record<string, string>,\n  aliasRemapping: Record<string, string>,\n  sourceWhereClauses: Map<string, BasicExpression<boolean>>,\n): NamespacedAndKeyedStream {\n  let resultPipeline = pipeline\n\n  for (const joinClause of joinClauses) {\n    resultPipeline = processJoin(\n      resultPipeline,\n      joinClause,\n      sources,\n      mainCollectionId,\n      mainSource,\n      allInputs,\n      cache,\n      queryMapping,\n      collections,\n      subscriptions,\n      callbacks,\n      lazySources,\n      optimizableOrderByCollections,\n      setWindowFn,\n      rawQuery,\n      onCompileSubquery,\n      aliasToCollectionId,\n      aliasRemapping,\n      sourceWhereClauses,\n    )\n  }\n\n  return resultPipeline\n}\n\n/**\n * Processes a single join clause with lazy loading optimization.\n * For LEFT/RIGHT/INNER joins, marks one side as \"lazy\" (loads on-demand based on join keys).\n */\nfunction processJoin(\n  pipeline: NamespacedAndKeyedStream,\n  joinClause: JoinClause,\n  sources: Record<string, KeyedStream>,\n  mainCollectionId: string,\n  mainSource: string,\n  allInputs: Record<string, KeyedStream>,\n  cache: QueryCache,\n  queryMapping: QueryMapping,\n  collections: Record<string, Collection>,\n  subscriptions: Record<string, CollectionSubscription>,\n  callbacks: Record<string, LazyCollectionCallbacks>,\n  lazySources: Set<string>,\n  optimizableOrderByCollections: Record<string, OrderByOptimizationInfo>,\n  setWindowFn: (windowFn: (options: WindowOptions) => void) => void,\n  rawQuery: QueryIR,\n  onCompileSubquery: CompileQueryFn,\n  aliasToCollectionId: Record<string, string>,\n  aliasRemapping: Record<string, string>,\n  sourceWhereClauses: Map<string, BasicExpression<boolean>>,\n): NamespacedAndKeyedStream {\n  const isCollectionRef = joinClause.from.type === `collectionRef`\n\n  // Get the joined source alias and input stream\n  const {\n    alias: joinedSource,\n    input: joinedInput,\n    collectionId: joinedCollectionId,\n  } = processJoinSource(\n    joinClause.from,\n    allInputs,\n    collections,\n    subscriptions,\n    callbacks,\n    lazySources,\n    optimizableOrderByCollections,\n    setWindowFn,\n    cache,\n    queryMapping,\n    onCompileSubquery,\n    aliasToCollectionId,\n    aliasRemapping,\n    sourceWhereClauses,\n  )\n\n  // Add the joined source to the sources map\n  sources[joinedSource] = joinedInput\n  if (isCollectionRef) {\n    // Only direct collection references form new alias bindings. Subquery\n    // aliases reuse the mapping returned from the recursive compilation above.\n    aliasToCollectionId[joinedSource] = joinedCollectionId\n  }\n\n  const mainCollection = collections[mainCollectionId]\n  const joinedCollection = collections[joinedCollectionId]\n\n  if (!mainCollection) {\n    throw new JoinCollectionNotFoundError(mainCollectionId)\n  }\n\n  if (!joinedCollection) {\n    throw new JoinCollectionNotFoundError(joinedCollectionId)\n  }\n\n  const { activeSource, lazySource } = getActiveAndLazySources(\n    joinClause.type,\n    mainCollection,\n    joinedCollection,\n  )\n\n  // Analyze which source each expression refers to and swap if necessary\n  const availableSources = Object.keys(sources)\n  const { mainExpr, joinedExpr } = analyzeJoinExpressions(\n    joinClause.left,\n    joinClause.right,\n    availableSources,\n    joinedSource,\n    rawQuery.from.type === `unionAll`,\n  )\n\n  // Pre-compile the join expressions\n  const compiledMainExpr = compileExpression(mainExpr)\n  const compiledJoinedExpr = compileExpression(joinedExpr)\n\n  // Prepare the main pipeline for joining\n  let mainPipeline = pipeline.pipe(\n    map(([currentKey, namespacedRow]) => {\n      // Extract the join key from the main source expression\n      const mainKey = normalizeValue(compiledMainExpr(namespacedRow))\n\n      // Return [joinKey, [originalKey, namespacedRow]]\n      return [mainKey, [currentKey, namespacedRow]] as [\n        unknown,\n        [string, typeof namespacedRow],\n      ]\n    }),\n  )\n\n  // Prepare the joined pipeline\n  let joinedPipeline = joinedInput.pipe(\n    map(([currentKey, row]) => {\n      // Wrap the row in a namespaced structure\n      const namespacedRow: NamespacedRow = { [joinedSource]: row }\n\n      // Extract the join key from the joined source expression\n      const joinedKey = normalizeValue(compiledJoinedExpr(namespacedRow))\n\n      // Return [joinKey, [originalKey, namespacedRow]]\n      return [joinedKey, [currentKey, namespacedRow]] as [\n        unknown,\n        [string, typeof namespacedRow],\n      ]\n    }),\n  )\n\n  // Apply the join operation\n  if (![`inner`, `left`, `right`, `full`].includes(joinClause.type)) {\n    throw new UnsupportedJoinTypeError(joinClause.type)\n  }\n\n  if (activeSource) {\n    // If the lazy collection comes from a subquery that has a limit and/or an offset clause\n    // then we need to deoptimize the join because we don't know which rows are in the result set\n    // since we simply lookup matching keys in the index but the index contains all rows\n    // (not just the ones that pass the limit and offset clauses)\n    const lazyFrom = activeSource === `main` ? joinClause.from : rawQuery.from\n    const limitedSubquery =\n      lazyFrom.type === `queryRef` &&\n      (lazyFrom.query.limit || lazyFrom.query.offset)\n    const resultUnionLazySide = lazyFrom.type === `unionAll`\n\n    const lazySourceJoinExpr = activeSource === `main` ? joinedExpr : mainExpr\n    const lazyAlias = activeSource === `main` ? joinedSource : mainSource\n    const lazyTargets = resultUnionLazySide\n      ? []\n      : getLazyLoadTargets(\n          rawQuery,\n          lazyFrom,\n          lazyAlias,\n          lazySourceJoinExpr,\n          lazySource,\n          aliasRemapping,\n        )\n\n    if (!limitedSubquery && lazyTargets.length > 0) {\n      // This join can be optimized by having the active collection\n      // dynamically load keys into the lazy collection\n      // based on the value of the joinKey and by looking up\n      // matching rows in the index of the lazy collection\n\n      // Mark the lazy source aliases as lazy\n      // this Set is passed by the liveQueryCollection to the compiler\n      // such that the liveQueryCollection can check it after compilation\n      // to know which source aliases should load data lazily (not initially)\n      for (const target of lazyTargets) {\n        lazySources.add(target.alias)\n      }\n\n      const activePipeline =\n        activeSource === `main` ? mainPipeline : joinedPipeline\n\n      for (const target of lazyTargets) {\n        const fieldName = target.path[0]\n        if (fieldName) {\n          ensureIndexForField(fieldName, target.path, target.collection)\n        }\n      }\n\n      // Set up lazy loading: intercept active side's stream and dynamically load\n      // matching rows from lazy side based on join keys.\n      const activePipelineWithLoading: IStreamBuilder<\n        [key: unknown, [originalKey: string, namespacedRow: NamespacedRow]]\n      > = activePipeline.pipe(\n        tap((data) => {\n          // Deduplicate and filter null keys before requesting snapshot\n          const joinKeys = [\n            ...new Set(\n              data\n                .getInner()\n                .map(([[joinKey]]) => joinKey)\n                .filter((key) => key != null),\n            ),\n          ]\n\n          if (joinKeys.length === 0) {\n            return\n          }\n\n          for (const target of lazyTargets) {\n            const lazySourceSubscription = subscriptions[target.alias]\n\n            if (!lazySourceSubscription) {\n              throw new SubscriptionNotFoundError(\n                target.alias,\n                lazyAlias,\n                target.collection.id,\n                Object.keys(subscriptions),\n              )\n            }\n\n            if (lazySourceSubscription.hasLoadedInitialState()) {\n              // Entire state was already loaded because we deoptimized the join\n              continue\n            }\n\n            const lazyJoinRef = new PropRef(target.path)\n            const loaded = lazySourceSubscription.requestSnapshot({\n              where: inArray(lazyJoinRef, joinKeys),\n              optimizedOnly: true,\n            })\n\n            if (!loaded) {\n              // Snapshot wasn't sent because it could not be loaded from the indexes\n              const collectionId = target.collection.id\n              const fieldPath = target.path.join(`.`)\n              console.warn(\n                `[TanStack DB]${collectionId ? ` [${collectionId}]` : ``} Join requires an index on \"${fieldPath}\" for efficient loading. ` +\n                  `Falling back to loading all data. ` +\n                  `Consider creating an index on the collection with collection.createIndex((row) => row.${fieldPath}) ` +\n                  `or enable auto-indexing with autoIndex: 'eager' and a defaultIndexType.`,\n              )\n              lazySourceSubscription.requestSnapshot()\n            }\n          }\n        }),\n      )\n\n      if (activeSource === `main`) {\n        mainPipeline = activePipelineWithLoading\n      } else {\n        joinedPipeline = activePipelineWithLoading\n      }\n    }\n  }\n\n  return mainPipeline.pipe(\n    joinOperator(joinedPipeline, joinClause.type as JoinType),\n    processJoinResults(joinClause.type),\n  )\n}\n\n/**\n * Analyzes join expressions to determine which refers to which source\n * and returns them in the correct order (available source expression first, joined source expression second)\n */\nfunction analyzeJoinExpressions(\n  left: BasicExpression,\n  right: BasicExpression,\n  allAvailableSourceAliases: Array<string>,\n  joinedSource: string,\n  allowResultFields: boolean = false,\n): { mainExpr: BasicExpression; joinedExpr: BasicExpression } {\n  // Filter out the joined source alias from the available source aliases\n  const availableSources = allAvailableSourceAliases.filter(\n    (alias) => alias !== joinedSource,\n  )\n\n  const leftSourceAliases = getSourceAliasesFromExpression(left)\n  const rightSourceAliases = getSourceAliasesFromExpression(right)\n  const leftReferencesJoined = leftSourceAliases.has(joinedSource)\n  const rightReferencesJoined = rightSourceAliases.has(joinedSource)\n  const leftAvailableAliases = [...leftSourceAliases].filter(\n    (alias) =>\n      availableSources.includes(alias) ||\n      (allowResultFields && alias !== joinedSource),\n  )\n  const rightAvailableAliases = [...rightSourceAliases].filter(\n    (alias) =>\n      availableSources.includes(alias) ||\n      (allowResultFields && alias !== joinedSource),\n  )\n\n  // If left expression refers to an available source and right refers to joined source, keep as is\n  if (\n    leftAvailableAliases.length > 0 &&\n    !leftReferencesJoined &&\n    rightReferencesJoined &&\n    rightAvailableAliases.length === 0\n  ) {\n    return { mainExpr: left, joinedExpr: right }\n  }\n\n  // If left expression refers to joined source and right refers to an available source, swap them\n  if (\n    leftReferencesJoined &&\n    leftAvailableAliases.length === 0 &&\n    rightAvailableAliases.length > 0 &&\n    !rightReferencesJoined\n  ) {\n    return { mainExpr: right, joinedExpr: left }\n  }\n\n  // If one expression doesn't refer to any source, this is an invalid join\n  if (leftSourceAliases.size === 0 || rightSourceAliases.size === 0) {\n    throw new InvalidJoinConditionSourceMismatchError()\n  }\n\n  // If both expressions refer to the same alias, this is an invalid join\n  if (\n    leftSourceAliases.size === 1 &&\n    rightSourceAliases.size === 1 &&\n    [...leftSourceAliases][0] === [...rightSourceAliases][0]\n  ) {\n    throw new InvalidJoinConditionSameSourceError([...leftSourceAliases][0]!)\n  }\n\n  // Left side must refer to an available source\n  // This cannot happen with the query builder as there is no way to build a ref\n  // to an unavailable source, but just in case, but could happen with the IR\n  if (leftAvailableAliases.length === 0) {\n    throw new InvalidJoinConditionLeftSourceError([...leftSourceAliases][0]!)\n  }\n\n  // Right side must refer to the joined source\n  if (!rightReferencesJoined) {\n    throw new InvalidJoinConditionRightSourceError(joinedSource)\n  }\n\n  // This should not be reachable given the logic above, but just in case\n  throw new InvalidJoinCondition()\n}\n\n/**\n * Extracts the source alias from a join expression\n */\nfunction getSourceAliasesFromExpression(expr: BasicExpression): Set<string> {\n  switch (expr.type) {\n    case `ref`:\n      // PropRef path has the source alias as the first element\n      return new Set(expr.path[0] ? [expr.path[0]] : [])\n    case `func`: {\n      // For function expressions, we need to check if all arguments refer to the same source\n      const sourceAliases = new Set<string>()\n      for (const arg of expr.args) {\n        for (const alias of getSourceAliasesFromExpression(arg)) {\n          sourceAliases.add(alias)\n        }\n      }\n      return sourceAliases\n    }\n    default:\n      // Values (type='val') don't reference any source\n      return new Set()\n  }\n}\n\n/**\n * Processes the join source (collection or sub-query)\n */\nfunction processJoinSource(\n  from: CollectionRef | QueryRef,\n  allInputs: Record<string, KeyedStream>,\n  collections: Record<string, Collection>,\n  subscriptions: Record<string, CollectionSubscription>,\n  callbacks: Record<string, LazyCollectionCallbacks>,\n  lazySources: Set<string>,\n  optimizableOrderByCollections: Record<string, OrderByOptimizationInfo>,\n  setWindowFn: (windowFn: (options: WindowOptions) => void) => void,\n  cache: QueryCache,\n  queryMapping: QueryMapping,\n  onCompileSubquery: CompileQueryFn,\n  aliasToCollectionId: Record<string, string>,\n  aliasRemapping: Record<string, string>,\n  sourceWhereClauses: Map<string, BasicExpression<boolean>>,\n): { alias: string; input: KeyedStream; collectionId: string } {\n  switch (from.type) {\n    case `collectionRef`: {\n      const input = allInputs[from.alias]\n      if (!input) {\n        throw new CollectionInputNotFoundError(\n          from.alias,\n          from.collection.id,\n          Object.keys(allInputs),\n        )\n      }\n      aliasToCollectionId[from.alias] = from.collection.id\n      return { alias: from.alias, input, collectionId: from.collection.id }\n    }\n    case `queryRef`: {\n      // Find the original query for caching purposes\n      const originalQuery = queryMapping.get(from.query) || from.query\n\n      // Recursively compile the sub-query with cache\n      const subQueryResult = onCompileSubquery(\n        originalQuery,\n        allInputs,\n        collections,\n        subscriptions,\n        callbacks,\n        lazySources,\n        optimizableOrderByCollections,\n        setWindowFn,\n        cache,\n        queryMapping,\n      )\n\n      // Pull up alias mappings from subquery to parent scope.\n      // This includes both the innermost alias-to-collection mappings AND\n      // any existing remappings from nested subquery levels.\n      Object.assign(aliasToCollectionId, subQueryResult.aliasToCollectionId)\n      Object.assign(aliasRemapping, subQueryResult.aliasRemapping)\n\n      // Pull up source WHERE clauses from subquery to parent scope.\n      // This enables loadSubset to receive the correct where clauses for subquery collections.\n      //\n      // IMPORTANT: Skip pull-up for optimizer-created subqueries. These are detected when:\n      // 1. The outer alias (from.alias) matches the inner alias (from.query.from.alias)\n      // 2. The subquery was found in queryMapping (it's a user-defined subquery, not optimizer-created)\n      //\n      // For optimizer-created subqueries, the parent already has the sourceWhereClauses\n      // extracted from the original raw query, so pulling up would be redundant.\n      const isUserDefinedSubquery = queryMapping.has(from.query)\n      const fromInnerAlias = getFirstFromAlias(from.query)\n      const isOptimizerCreated =\n        !isUserDefinedSubquery &&\n        fromInnerAlias !== undefined &&\n        from.alias === fromInnerAlias\n\n      if (!isOptimizerCreated) {\n        for (const [alias, whereClause] of subQueryResult.sourceWhereClauses) {\n          sourceWhereClauses.set(alias, whereClause)\n        }\n      }\n\n      // Create a flattened remapping from outer alias to innermost alias.\n      // For nested subqueries, this ensures one-hop lookups (not recursive chains).\n      //\n      // Example with 3-level nesting:\n      //   Inner:  .from({ user: usersCollection })\n      //   Middle: .from({ activeUser: innerSubquery })     → creates: activeUser → user\n      //   Outer:  .join({ author: middleSubquery }, ...)   → creates: author → user (not author → activeUser)\n      //\n      // We search through the PULLED-UP aliasToCollectionId (which contains the\n      // innermost 'user' alias), so we always map directly to the deepest level.\n      // This means aliasRemapping[lazyAlias] is always a single lookup, never recursive.\n      const innerAlias = Object.keys(subQueryResult.aliasToCollectionId).find(\n        (alias) =>\n          subQueryResult.aliasToCollectionId[alias] ===\n          subQueryResult.collectionId,\n      )\n      if (innerAlias && innerAlias !== from.alias) {\n        aliasRemapping[from.alias] = innerAlias\n      }\n\n      // Extract the pipeline from the compilation result\n      const subQueryInput = subQueryResult.pipeline\n\n      // Subqueries may return [key, [value, orderByIndex]] (with ORDER BY) or [key, value] (without ORDER BY)\n      // We need to extract just the value for use in parent queries\n      const extractedInput = subQueryInput.pipe(\n        map((data: any) => {\n          const [key, [value, _orderByIndex]] = data\n          return [key, value] as [unknown, any]\n        }),\n      )\n\n      return {\n        alias: from.alias,\n        input: extractedInput as KeyedStream,\n        collectionId: subQueryResult.collectionId,\n      }\n    }\n    default:\n      throw new UnsupportedJoinSourceTypeError((from as any).type)\n  }\n}\n\nfunction getFirstFromAlias(query: QueryIR): string | undefined {\n  if (query.from.type === `unionFrom`) {\n    return query.from.sources[0]?.alias\n  }\n\n  if (query.from.type === `unionAll`) {\n    return undefined\n  }\n\n  return query.from.alias\n}\n\n/**\n * Processes the results of a join operation\n */\nfunction processJoinResults(joinType: string) {\n  return function (\n    pipeline: IStreamBuilder<\n      [\n        key: string,\n        [\n          [string, NamespacedRow] | undefined,\n          [string, NamespacedRow] | undefined,\n        ],\n      ]\n    >,\n  ): NamespacedAndKeyedStream {\n    return pipeline.pipe(\n      // Process the join result and handle nulls\n      filter((result) => {\n        const [_key, [main, joined]] = result\n        const mainNamespacedRow = main?.[1]\n        const joinedNamespacedRow = joined?.[1]\n\n        // Handle different join types\n        if (joinType === `inner`) {\n          return !!(mainNamespacedRow && joinedNamespacedRow)\n        }\n\n        if (joinType === `left`) {\n          return !!mainNamespacedRow\n        }\n\n        if (joinType === `right`) {\n          return !!joinedNamespacedRow\n        }\n\n        // For full joins, always include\n        return true\n      }),\n      map((result) => {\n        const [_key, [main, joined]] = result\n        const mainKey = main?.[0]\n        const mainNamespacedRow = main?.[1]\n        const joinedKey = joined?.[0]\n        const joinedNamespacedRow = joined?.[1]\n\n        // Merge the namespaced rows\n        const mergedNamespacedRow: NamespacedRow = {}\n\n        // Add main row data if it exists\n        if (mainNamespacedRow) {\n          Object.assign(mergedNamespacedRow, mainNamespacedRow)\n        }\n\n        // Add joined row data if it exists\n        if (joinedNamespacedRow) {\n          Object.assign(mergedNamespacedRow, joinedNamespacedRow)\n        }\n\n        // We create a composite key that combines the main and joined keys\n        const resultKey = `[${mainKey},${joinedKey}]`\n\n        return [resultKey, mergedNamespacedRow] as [string, NamespacedRow]\n      }),\n    )\n  }\n}\n\n/**\n * Returns the active and lazy collections for a join clause.\n * The active collection is the one that we need to fully iterate over\n * and it can be the main source (i.e. left collection) or the joined source (i.e. right collection).\n * The lazy collection is the one that we should join-in lazily based on matches in the active collection.\n * @param joinClause - The join clause to analyze\n * @param leftCollection - The left collection\n * @param rightCollection - The right collection\n * @returns The active and lazy collections. They are undefined if we need to loop over both collections (i.e. both are active)\n */\nfunction getActiveAndLazySources(\n  joinType: JoinClause[`type`],\n  leftCollection: Collection,\n  rightCollection: Collection,\n):\n  | { activeSource: `main` | `joined`; lazySource: Collection }\n  | { activeSource: undefined; lazySource: undefined } {\n  // Self-joins can now be optimized since we track lazy loading by source alias\n  // rather than collection ID. Each alias has its own subscription and lazy state.\n\n  switch (joinType) {\n    case `left`:\n      return { activeSource: `main`, lazySource: rightCollection }\n    case `right`:\n      return { activeSource: `joined`, lazySource: leftCollection }\n    case `inner`:\n      // The smallest collection should be the active collection\n      // and the biggest collection should be lazy\n      return leftCollection.size < rightCollection.size\n        ? { activeSource: `main`, lazySource: rightCollection }\n        : { activeSource: `joined`, lazySource: leftCollection }\n    default:\n      return { activeSource: undefined, lazySource: undefined }\n  }\n}\n"],"names":["JoinCollectionNotFoundError","compileExpression","map","normalizeValue","UnsupportedJoinTypeError","lazyTargets","getLazyLoadTargets","ensureIndexForField","tap","SubscriptionNotFoundError","PropRef","inArray","joinOperator","InvalidJoinConditionSourceMismatchError","InvalidJoinConditionSameSourceError","InvalidJoinConditionLeftSourceError","InvalidJoinConditionRightSourceError","InvalidJoinCondition","CollectionInputNotFoundError","UnsupportedJoinSourceTypeError","filter"],"mappings":"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"}