@tanstack/db
Version:
A reactive client store for building super fast apps on sync
1 lines • 29.3 kB
Source Map (JSON)
{"version":3,"file":"functions.cjs","sources":["../../../../src/query/builder/functions.ts"],"sourcesContent":["import { Aggregate, Func } from '../ir'\nimport { isRefProxy, toExpression } from './ref-proxy.js'\nimport type { BasicExpression } from '../ir'\nimport type { RefProxy } from './ref-proxy.js'\nimport type { SingleResult } from '../../types.js'\nimport type {\n Context,\n GetRawResult,\n RefLeaf,\n StringifiableScalar,\n} from './types.js'\nimport type { QueryBuilder } from './index.js'\n\ntype StringRef =\n | RefLeaf<string>\n | RefLeaf<string | null>\n | RefLeaf<string | undefined>\ntype StringRefProxy =\n | RefProxy<string>\n | RefProxy<string | null>\n | RefProxy<string | undefined>\ntype StringBasicExpression =\n | BasicExpression<string>\n | BasicExpression<string | null>\n | BasicExpression<string | undefined>\ntype StringLike =\n | StringRef\n | StringRefProxy\n | StringBasicExpression\n | string\n | null\n | undefined\n\ntype ComparisonOperand<T> =\n | RefProxy<T>\n | RefLeaf<T>\n | T\n | BasicExpression<T>\n | undefined\n | null\ntype ComparisonOperandPrimitive<T extends string | number | boolean> =\n | T\n | BasicExpression<T>\n | undefined\n | null\n\n// Helper type for values that can be lowered to expressions.\ntype ExpressionLike =\n | Aggregate\n | BasicExpression\n | RefProxy<any>\n | RefLeaf<any>\n | string\n | number\n | boolean\n | bigint\n | Date\n | null\n | undefined\n | Array<unknown>\n\ntype CaseWhenValue =\n | ExpressionLike\n | QueryBuilder<any>\n | ToArrayWrapper<any>\n | ConcatToArrayWrapper<any>\n | Record<string, any>\n\ntype ExtractCaseWhenValue<T> =\n T extends CaseWhenWrapper<infer TResult> ? TResult : T\n\ntype CaseWhenResult<\n TValues extends Array<CaseWhenValue>,\n THasDefault extends boolean,\n> = TValues[number] extends ExpressionLike\n ? BasicExpression<\n ExtractType<TValues[number]> | (THasDefault extends true ? never : null)\n >\n : CaseWhenWrapper<\n | ExtractCaseWhenValue<TValues[number]>\n | (THasDefault extends true ? never : undefined)\n >\n\n// Helper type to extract the underlying type from various expression types\ntype ExtractType<T> =\n T extends RefProxy<infer U>\n ? U\n : T extends RefLeaf<infer U>\n ? U\n : T extends BasicExpression<infer U>\n ? U\n : T\n\n// Helper type to determine aggregate return type based on input nullability\ntype AggregateReturnType<T> =\n ExtractType<T> extends infer U\n ? U extends number | undefined | null | Date | bigint | string\n ? Aggregate<U>\n : Aggregate<number | undefined | null | Date | bigint | string>\n : Aggregate<number | undefined | null | Date | bigint | string>\n\n// Helper type to determine string function return type based on input nullability\ntype StringFunctionReturnType<T> =\n ExtractType<T> extends infer U\n ? U extends string | undefined | null\n ? BasicExpression<U>\n : BasicExpression<string | undefined | null>\n : BasicExpression<string | undefined | null>\n\n// Helper type to determine numeric function return type based on input nullability\n// This handles string, array, and number inputs for functions like length()\ntype NumericFunctionReturnType<T> =\n ExtractType<T> extends infer U\n ? U extends string | Array<any> | undefined | null | number\n ? BasicExpression<MapToNumber<U>>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n\n// Transform string/array types to number while preserving nullability\ntype MapToNumber<T> = T extends string | Array<any>\n ? number\n : T extends undefined\n ? undefined\n : T extends null\n ? null\n : T\n\n// Helper type for binary numeric operations (combines nullability of both operands)\ntype BinaryNumericReturnType<T1, T2> =\n ExtractType<T1> extends infer U1\n ? ExtractType<T2> extends infer U2\n ? U1 extends number\n ? U2 extends number\n ? BasicExpression<number>\n : U2 extends number | undefined\n ? BasicExpression<number | undefined>\n : U2 extends number | null\n ? BasicExpression<number | null>\n : BasicExpression<number | undefined | null>\n : U1 extends number | undefined\n ? U2 extends number\n ? BasicExpression<number | undefined>\n : U2 extends number | undefined\n ? BasicExpression<number | undefined>\n : BasicExpression<number | undefined | null>\n : U1 extends number | null\n ? U2 extends number\n ? BasicExpression<number | null>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n\n// Operators\n\nexport function eq<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>,\n): BasicExpression<boolean>\nexport function eq<T extends string | number | boolean>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>,\n): BasicExpression<boolean>\nexport function eq<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function eq(left: any, right: any): BasicExpression<boolean> {\n return new Func(`eq`, [toExpression(left), toExpression(right)])\n}\n\nexport function gt<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>,\n): BasicExpression<boolean>\nexport function gt<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>,\n): BasicExpression<boolean>\nexport function gt<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function gt(left: any, right: any): BasicExpression<boolean> {\n return new Func(`gt`, [toExpression(left), toExpression(right)])\n}\n\nexport function gte<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>,\n): BasicExpression<boolean>\nexport function gte<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>,\n): BasicExpression<boolean>\nexport function gte<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function gte(left: any, right: any): BasicExpression<boolean> {\n return new Func(`gte`, [toExpression(left), toExpression(right)])\n}\n\nexport function lt<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>,\n): BasicExpression<boolean>\nexport function lt<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>,\n): BasicExpression<boolean>\nexport function lt<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function lt(left: any, right: any): BasicExpression<boolean> {\n return new Func(`lt`, [toExpression(left), toExpression(right)])\n}\n\nexport function lte<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>,\n): BasicExpression<boolean>\nexport function lte<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>,\n): BasicExpression<boolean>\nexport function lte<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function lte(left: any, right: any): BasicExpression<boolean> {\n return new Func(`lte`, [toExpression(left), toExpression(right)])\n}\n\n// Overloads for and() - support 2 or more arguments\nexport function and(\n left: ExpressionLike,\n right: ExpressionLike,\n): BasicExpression<boolean>\nexport function and(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean>\nexport function and(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean> {\n const allArgs = [left, right, ...rest]\n return new Func(\n `and`,\n allArgs.map((arg) => toExpression(arg)),\n )\n}\n\n// Overloads for or() - support 2 or more arguments\nexport function or(\n left: ExpressionLike,\n right: ExpressionLike,\n): BasicExpression<boolean>\nexport function or(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean>\nexport function or(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean> {\n const allArgs = [left, right, ...rest]\n return new Func(\n `or`,\n allArgs.map((arg) => toExpression(arg)),\n )\n}\n\nexport function not(value: ExpressionLike): BasicExpression<boolean> {\n return new Func(`not`, [toExpression(value)])\n}\n\n// Null/undefined checking functions\nexport function isUndefined(value: ExpressionLike): BasicExpression<boolean> {\n return new Func(`isUndefined`, [toExpression(value)])\n}\n\nexport function isNull(value: ExpressionLike): BasicExpression<boolean> {\n return new Func(`isNull`, [toExpression(value)])\n}\n\nexport function inArray(\n value: ExpressionLike,\n array: ExpressionLike,\n): BasicExpression<boolean> {\n return new Func(`in`, [toExpression(value), toExpression(array)])\n}\n\nexport function like(\n left: StringLike,\n right: StringLike,\n): BasicExpression<boolean>\nexport function like(left: any, right: any): BasicExpression<boolean> {\n return new Func(`like`, [toExpression(left), toExpression(right)])\n}\n\nexport function ilike(\n left: StringLike,\n right: StringLike,\n): BasicExpression<boolean> {\n return new Func(`ilike`, [toExpression(left), toExpression(right)])\n}\n\n// Functions\n\nexport function upper<T extends ExpressionLike>(\n arg: T,\n): StringFunctionReturnType<T> {\n return new Func(`upper`, [toExpression(arg)]) as StringFunctionReturnType<T>\n}\n\nexport function lower<T extends ExpressionLike>(\n arg: T,\n): StringFunctionReturnType<T> {\n return new Func(`lower`, [toExpression(arg)]) as StringFunctionReturnType<T>\n}\n\nexport function length<T extends ExpressionLike>(\n arg: T,\n): NumericFunctionReturnType<T> {\n return new Func(`length`, [toExpression(arg)]) as NumericFunctionReturnType<T>\n}\n\nexport function concat<T extends StringifiableScalar>(\n arg: ToArrayWrapper<T>,\n): ConcatToArrayWrapper<T>\nexport function concat(...args: Array<ExpressionLike>): BasicExpression<string>\nexport function concat(\n ...args: Array<ExpressionLike | ToArrayWrapper<any>>\n): BasicExpression<string> | ConcatToArrayWrapper<any> {\n const toArrayArg = args.find(\n (arg): arg is ToArrayWrapper<any> => arg instanceof ToArrayWrapper,\n )\n\n if (toArrayArg) {\n if (args.length !== 1) {\n throw new Error(\n `concat(toArray(...)) currently supports only a single toArray(...) argument`,\n )\n }\n return new ConcatToArrayWrapper(toArrayArg.query)\n }\n\n return new Func(\n `concat`,\n args.map((arg) => toExpression(arg)),\n )\n}\n\n// Helper type for coalesce: extracts non-nullish value types from all args\ntype CoalesceArgTypes<T extends Array<ExpressionLike>> = {\n [K in keyof T]: NonNullable<ExtractType<T[K]>>\n}[number]\n\n// Whether any arg in the tuple is statically guaranteed non-null (i.e., does not include null | undefined)\ntype HasGuaranteedNonNull<T extends Array<ExpressionLike>> = {\n [K in keyof T]: null extends ExtractType<T[K]>\n ? false\n : undefined extends ExtractType<T[K]>\n ? false\n : true\n}[number] extends false\n ? false\n : true\n\n// coalesce() return type: union of all non-null arg types; null included unless a guaranteed non-null arg exists\ntype CoalesceReturnType<T extends Array<ExpressionLike>> =\n HasGuaranteedNonNull<T> extends true\n ? BasicExpression<CoalesceArgTypes<T>>\n : BasicExpression<CoalesceArgTypes<T> | null>\n\nexport function coalesce<T extends [ExpressionLike, ...Array<ExpressionLike>]>(\n ...args: T\n): CoalesceReturnType<T> {\n return new Func(\n `coalesce`,\n args.map((arg) => toExpression(arg)),\n ) as CoalesceReturnType<T>\n}\n\n/**\n * Returns the value for the first matching condition, similar to SQL\n * `CASE WHEN`.\n *\n * Arguments are evaluated as condition/value pairs followed by an optional\n * default value. Scalar branch values return a query expression and can be used\n * in expression contexts like `select`, `where`, `orderBy`, `groupBy`,\n * `having`, and equality join operands. If no scalar branch matches and no\n * default is provided, the result is `null`.\n *\n * When a branch value is a projection object, `caseWhen` becomes a select-only\n * projection value. Projection branches can include nested fields, ref spreads,\n * and includes. If no projection branch matches and no default is provided, the\n * result is `undefined`.\n *\n * @example\n * ```ts\n * caseWhen(gt(user.age, 18), `adult`, `minor`)\n * ```\n *\n * @example\n * ```ts\n * caseWhen(\n * gt(user.age, 65),\n * `senior`,\n * gt(user.age, 18),\n * `adult`,\n * `minor`,\n * )\n * ```\n *\n * @example\n * ```ts\n * caseWhen(gt(user.age, 18), {\n * ...user,\n * posts: q\n * .from({ post: postsCollection })\n * .where(({ post }) => eq(post.userId, user.id)),\n * })\n * ```\n */\nexport function caseWhen<C1 extends ExpressionLike, V1 extends CaseWhenValue>(\n condition1: C1,\n value1: V1,\n): CaseWhenResult<[V1], false>\nexport function caseWhen<\n C1 extends ExpressionLike,\n V1 extends CaseWhenValue,\n D extends CaseWhenValue,\n>(condition1: C1, value1: V1, defaultValue: D): CaseWhenResult<[V1, D], true>\nexport function caseWhen<\n C1 extends ExpressionLike,\n V1 extends CaseWhenValue,\n C2 extends ExpressionLike,\n V2 extends CaseWhenValue,\n>(\n condition1: C1,\n value1: V1,\n condition2: C2,\n value2: V2,\n): CaseWhenResult<[V1, V2], false>\nexport function caseWhen<\n C1 extends ExpressionLike,\n V1 extends CaseWhenValue,\n C2 extends ExpressionLike,\n V2 extends CaseWhenValue,\n D extends CaseWhenValue,\n>(\n condition1: C1,\n value1: V1,\n condition2: C2,\n value2: V2,\n defaultValue: D,\n): CaseWhenResult<[V1, V2, D], true>\nexport function caseWhen<\n C1 extends ExpressionLike,\n V1 extends CaseWhenValue,\n C2 extends ExpressionLike,\n V2 extends CaseWhenValue,\n C3 extends ExpressionLike,\n V3 extends CaseWhenValue,\n>(\n condition1: C1,\n value1: V1,\n condition2: C2,\n value2: V2,\n condition3: C3,\n value3: V3,\n): CaseWhenResult<[V1, V2, V3], false>\nexport function caseWhen<\n C1 extends ExpressionLike,\n V1 extends CaseWhenValue,\n C2 extends ExpressionLike,\n V2 extends CaseWhenValue,\n C3 extends ExpressionLike,\n V3 extends CaseWhenValue,\n D extends CaseWhenValue,\n>(\n condition1: C1,\n value1: V1,\n condition2: C2,\n value2: V2,\n condition3: C3,\n value3: V3,\n defaultValue: D,\n): CaseWhenResult<[V1, V2, V3, D], true>\nexport function caseWhen<\n C1 extends ExpressionLike,\n V1 extends CaseWhenValue,\n C2 extends ExpressionLike,\n V2 extends CaseWhenValue,\n C3 extends ExpressionLike,\n V3 extends CaseWhenValue,\n C4 extends ExpressionLike,\n V4 extends CaseWhenValue,\n>(\n condition1: C1,\n value1: V1,\n condition2: C2,\n value2: V2,\n condition3: C3,\n value3: V3,\n condition4: C4,\n value4: V4,\n): CaseWhenResult<[V1, V2, V3, V4], false>\nexport function caseWhen<\n C1 extends ExpressionLike,\n V1 extends CaseWhenValue,\n C2 extends ExpressionLike,\n V2 extends CaseWhenValue,\n C3 extends ExpressionLike,\n V3 extends CaseWhenValue,\n C4 extends ExpressionLike,\n V4 extends CaseWhenValue,\n D extends CaseWhenValue,\n>(\n condition1: C1,\n value1: V1,\n condition2: C2,\n value2: V2,\n condition3: C3,\n value3: V3,\n condition4: C4,\n value4: V4,\n defaultValue: D,\n): CaseWhenResult<[V1, V2, V3, V4, D], true>\nexport function caseWhen<\n C1 extends ExpressionLike,\n V1 extends CaseWhenValue,\n C2 extends ExpressionLike,\n V2 extends CaseWhenValue,\n C3 extends ExpressionLike,\n V3 extends CaseWhenValue,\n C4 extends ExpressionLike,\n V4 extends CaseWhenValue,\n C5 extends ExpressionLike,\n V5 extends CaseWhenValue,\n>(\n condition1: C1,\n value1: V1,\n condition2: C2,\n value2: V2,\n condition3: C3,\n value3: V3,\n condition4: C4,\n value4: V4,\n condition5: C5,\n value5: V5,\n): CaseWhenResult<[V1, V2, V3, V4, V5], false>\nexport function caseWhen<\n C1 extends ExpressionLike,\n V1 extends CaseWhenValue,\n C2 extends ExpressionLike,\n V2 extends CaseWhenValue,\n C3 extends ExpressionLike,\n V3 extends CaseWhenValue,\n C4 extends ExpressionLike,\n V4 extends CaseWhenValue,\n C5 extends ExpressionLike,\n V5 extends CaseWhenValue,\n D extends CaseWhenValue,\n>(\n condition1: C1,\n value1: V1,\n condition2: C2,\n value2: V2,\n condition3: C3,\n value3: V3,\n condition4: C4,\n value4: V4,\n condition5: C5,\n value5: V5,\n defaultValue: D,\n): CaseWhenResult<[V1, V2, V3, V4, V5, D], true>\nexport function caseWhen<\n C1 extends ExpressionLike,\n V1 extends CaseWhenValue,\n C2 extends ExpressionLike,\n V2 extends CaseWhenValue,\n C3 extends ExpressionLike,\n V3 extends CaseWhenValue,\n C4 extends ExpressionLike,\n V4 extends CaseWhenValue,\n C5 extends ExpressionLike,\n V5 extends CaseWhenValue,\n>(\n condition1: C1,\n value1: V1,\n condition2: C2,\n value2: V2,\n condition3: C3,\n value3: V3,\n condition4: C4,\n value4: V4,\n condition5: C5,\n value5: V5,\n condition6: ExpressionLike,\n value6: CaseWhenValue,\n ...rest: Array<CaseWhenValue>\n): any\nexport function caseWhen(...args: Array<CaseWhenValue>): any {\n if (args.length < 2) {\n throw new Error(`caseWhen() requires at least two arguments`)\n }\n\n const pairCount = Math.floor(args.length / 2)\n for (let i = 0; i < pairCount; i++) {\n const condition = args[i * 2]\n if (!isConditionValue(condition)) {\n throw new Error(`caseWhen() conditions must be expression-like values`)\n }\n }\n\n if (caseWhenHasOnlyExpressionValues(args)) {\n return new Func(\n `caseWhen`,\n args.map((arg) => toExpression(arg)),\n )\n }\n\n return new CaseWhenWrapper(args)\n}\n\nexport function add<T1 extends ExpressionLike, T2 extends ExpressionLike>(\n left: T1,\n right: T2,\n): BinaryNumericReturnType<T1, T2> {\n return new Func(`add`, [\n toExpression(left),\n toExpression(right),\n ]) as BinaryNumericReturnType<T1, T2>\n}\n\n// Aggregates\n\nexport function count(arg: ExpressionLike): Aggregate<number> {\n return new Aggregate(`count`, [toExpression(arg)])\n}\n\nexport function avg<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`avg`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\nexport function sum<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`sum`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\nexport function min<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`min`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\nexport function max<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`max`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\n/**\n * List of comparison function names that can be used with indexes\n */\nexport const comparisonFunctions = [\n `eq`,\n `gt`,\n `gte`,\n `lt`,\n `lte`,\n `in`,\n `like`,\n `ilike`,\n] as const\n\n/**\n * All supported operator names in TanStack DB expressions\n */\nexport const operators = [\n // Comparison operators\n `eq`,\n `gt`,\n `gte`,\n `lt`,\n `lte`,\n `in`,\n `like`,\n `ilike`,\n // Logical operators\n `and`,\n `or`,\n `not`,\n // Null checking\n `isNull`,\n `isUndefined`,\n // String functions\n `upper`,\n `lower`,\n `length`,\n `concat`,\n // Numeric functions\n `add`,\n // Utility functions\n `coalesce`,\n `caseWhen`,\n // Aggregate functions\n `count`,\n `avg`,\n `sum`,\n `min`,\n `max`,\n] as const\n\nexport type OperatorName = (typeof operators)[number]\n\nexport class ToArrayWrapper<_T = unknown> {\n readonly __brand = `ToArrayWrapper` as const\n declare readonly _type: `toArray`\n declare readonly _result: _T\n constructor(public readonly query: QueryBuilder<any>) {}\n}\n\nexport class ConcatToArrayWrapper<_T = unknown> {\n readonly __brand = `ConcatToArrayWrapper` as const\n declare readonly _type: `concatToArray`\n declare readonly _result: _T\n constructor(public readonly query: QueryBuilder<any>) {}\n}\n\nexport class CaseWhenWrapper<_T = any> {\n readonly __brand = `CaseWhenWrapper` as const\n declare readonly _type: `caseWhen`\n readonly _result?: _T\n constructor(public readonly args: Array<CaseWhenValue>) {}\n}\n\nexport class MaterializeWrapper<\n _T = unknown,\n _IsSingle extends boolean = boolean,\n> {\n readonly __brand = `MaterializeWrapper` as const\n declare readonly _type: `materialize`\n declare readonly _result: _T\n declare readonly _isSingle: _IsSingle\n constructor(public readonly query: QueryBuilder<any>) {}\n}\n\nexport function toArray<TContext extends Context>(\n query: QueryBuilder<TContext>,\n): ToArrayWrapper<GetRawResult<TContext>> {\n return new ToArrayWrapper(query)\n}\n\nfunction caseWhenHasOnlyExpressionValues(args: Array<CaseWhenValue>): boolean {\n const valueIndexes = getCaseWhenValueIndexes(args.length)\n return valueIndexes.every((index) => isExpressionValue(args[index]))\n}\n\nfunction getCaseWhenValueIndexes(argCount: number): Array<number> {\n const valueIndexes: Array<number> = []\n const hasDefaultValue = argCount % 2 === 1\n const pairCount = Math.floor(argCount / 2)\n\n for (let i = 0; i < pairCount; i++) {\n valueIndexes.push(i * 2 + 1)\n }\n\n if (hasDefaultValue) {\n valueIndexes.push(argCount - 1)\n }\n\n return valueIndexes\n}\n\nfunction isExpressionValue(value: CaseWhenValue | undefined): boolean {\n if (isRefProxy(value)) return true\n if (value instanceof Aggregate || value instanceof Func) return true\n if (value == null) return true\n if (\n typeof value === `string` ||\n typeof value === `number` ||\n typeof value === `boolean` ||\n typeof value === `bigint`\n ) {\n return true\n }\n if (value instanceof Date || Array.isArray(value)) return true\n if (typeof value === `object`) {\n const candidate = value as {\n type?: unknown\n args?: unknown\n name?: unknown\n path?: unknown\n value?: unknown\n }\n\n if (\n (candidate.type === `agg` || candidate.type === `func`) &&\n typeof candidate.name === `string` &&\n Array.isArray(candidate.args)\n ) {\n return true\n }\n if (candidate.type === `ref` && Array.isArray(candidate.path)) return true\n if (candidate.type === `val` && `value` in candidate) return true\n }\n return false\n}\n\nfunction isConditionValue(value: CaseWhenValue | undefined): boolean {\n return isExpressionValue(value) && !Array.isArray(value)\n}\n\n/**\n * Materialize an includes subquery into a plain value on the parent row.\n *\n * - For multi-row subqueries, the parent receives an `Array<T>` snapshot\n * (equivalent to `toArray()`).\n * - For `findOne()` subqueries, the parent receives a single `T | undefined`\n * value — `undefined` when no child matches.\n *\n * The snapshot updates reactively: parent rows re-emit when the underlying\n * children change.\n *\n * @example\n * ```ts\n * // Multi-row: produces Array<Issue> on each project\n * select(({ p }) => ({\n * ...p,\n * issues: materialize(\n * q.from({ i: issues }).where(({ i }) => eq(i.projectId, p.id)),\n * ),\n * }))\n *\n * // Singleton: produces Author | undefined on each post\n * select(({ p }) => ({\n * ...p,\n * author: materialize(\n * q.from({ a: authors }).where(({ a }) => eq(a.id, p.authorId)).findOne(),\n * ),\n * }))\n * ```\n */\nexport function materialize<TContext extends Context>(\n query: QueryBuilder<TContext>,\n): MaterializeWrapper<\n GetRawResult<TContext>,\n TContext extends SingleResult ? true : false\n> {\n return new MaterializeWrapper(query)\n}\n"],"names":["Func","toExpression","Aggregate","isRefProxy"],"mappings":"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"}