@tanstack/db
Version:
A reactive client store for building super fast apps on sync
1 lines • 45.6 kB
Source Map (JSON)
{"version":3,"file":"ir-stable-identity.cjs","sources":["../../../src/query/ir-stable-identity.ts"],"sourcesContent":["import { normalizeValue } from '../utils/comparison.js'\nimport { isRefProxy, toExpression } from './builder/ref-proxy.js'\nimport { getQueryIR } from './builder/index.js'\nimport { getRuntimeReferenceIdentity } from './runtime-reference-identity.js'\nimport type {\n Aggregate,\n BasicExpression,\n ConditionalSelect,\n From,\n Having,\n IncludesSubquery,\n JoinClause,\n OrderByClause,\n QueryIR,\n Select,\n Where,\n} from './ir.js'\nimport type { InitialQueryBuilder, QueryBuilder } from './builder/index.js'\nimport type { LoadSubsetOptions } from '../types.js'\n\ntype StableIdentityValue =\n | null\n | boolean\n | number\n | string\n | Array<StableIdentityValue>\n | { [key: string]: StableIdentityValue }\n\ntype ValueIdentityContext =\n | `exact-output`\n | `equality-operand`\n | `ordering-operand`\n\ntype AliasScope = {\n bindings: ReadonlyMap<string, number>\n hasUnqualifiedOutput: boolean\n parent: AliasScope | undefined\n}\n\ndeclare const queryIdentityBrand: unique symbol\ndeclare const demandKeyBrand: unique symbol\n\n/** Semantic identity for a query plan, independent of its runtime owners. */\nexport type QueryIdentity = string & {\n readonly [queryIdentityBrand]: true\n}\n\n/** Exact identity for one loadSubset demand, including its requested window. */\nexport type DemandKey = string & {\n readonly [demandKeyBrand]: true\n}\n\nexport class UnhashableQueryIRError extends Error {\n constructor(\n public readonly path: string,\n public readonly reason: string,\n ) {\n super(`Query IR is not stably hashable at ${path}: ${reason}`)\n this.name = `UnhashableQueryIRError`\n }\n}\n\nexport function getStableQueryIRHash(query: QueryIR): string {\n return getQueryIdentity(query)\n}\n\nexport function getStableQueryBuilderHash(\n query: InitialQueryBuilder | QueryBuilder<any>,\n): string {\n return getStableQueryIRHash(getQueryIR(query))\n}\n\nexport function getStableValueHash(value: unknown, path = `value`): string {\n return JSON.stringify(canonicalizeRuntimeValue(value, path, new WeakSet()))\n}\n\n/**\n * Returns the semantic identity of a structured query.\n *\n * Logical conjunctions and disjunctions are associative, commutative, and\n * idempotent. Equality operands are commutative, while reversed inequalities\n * are normalized by inverting their operator. Order-sensitive clauses and\n * function arguments retain their original order.\n */\nexport function getQueryIdentity(query: QueryIR): QueryIdentity {\n return JSON.stringify(canonicalizeQueryIR(query)) as QueryIdentity\n}\n\n/** Returns the semantic identity of one structured expression. */\nexport function getStableExpressionHash(expression: BasicExpression): string {\n return JSON.stringify(\n canonicalizeExpression(\n expression,\n `expression`,\n new WeakSet(),\n `exact-output`,\n ),\n )\n}\n\n/**\n * Returns the exact semantic identity of a loadSubset request.\n *\n * Abort signals and subscriptions are owners of a request, not part of the\n * requested data, and therefore do not affect the key. A demand generation\n * scopes one asynchronous attempt rather than the data it requests. Code that\n * rejects stale work compares this key alongside its generation; query-db uses\n * the key alone so equivalent data demands can reuse one cache entry across\n * generations.\n */\nexport function getLoadSubsetDemandKey(\n options: LoadSubsetOptions,\n): DemandKey | undefined {\n if (\n options.where === undefined &&\n !options.orderBy?.length &&\n options.limit === undefined &&\n (options.offset === undefined || options.offset === 0) &&\n options.cursor === undefined\n ) {\n // Query-db uses its base query key for the one unconstrained demand. An\n // owner-only option must not create another cache entry for the same data.\n return undefined\n }\n\n const seen = new WeakSet<object>()\n const result: Record<string, StableIdentityValue> = {\n type: `loadSubsetDemand`,\n query: canonicalizeLoadSubsetQuery(options, `loadSubset`, seen),\n }\n\n if (options.limit !== undefined) {\n result.limit = canonicalizeRuntimeValue(\n options.limit,\n `loadSubset.limit`,\n seen,\n )\n }\n\n if (options.offset !== undefined && options.offset !== 0) {\n result.offset = canonicalizeRuntimeValue(\n options.offset,\n `loadSubset.offset`,\n seen,\n )\n }\n\n if (options.cursor !== undefined) {\n const cursor: Record<string, StableIdentityValue> = {\n whereFrom: canonicalizeExpression(\n options.cursor.whereFrom,\n `loadSubset.cursor.whereFrom`,\n seen,\n `exact-output`,\n ),\n whereCurrent: canonicalizeExpression(\n options.cursor.whereCurrent,\n `loadSubset.cursor.whereCurrent`,\n seen,\n `exact-output`,\n ),\n }\n if (options.cursor.lastKey !== undefined) {\n cursor.lastKey = canonicalizeRuntimeValue(\n options.cursor.lastKey,\n `loadSubset.cursor.lastKey`,\n seen,\n )\n }\n result.cursor = cursor\n }\n\n return JSON.stringify(result) as DemandKey\n}\n\nexport function canonicalizeQueryIR(query: QueryIR): StableIdentityValue {\n return canonicalizeQuery(query, `query`, new WeakSet<object>())\n}\n\nfunction createAliasScope(\n query: QueryIR,\n parent: AliasScope | undefined,\n): AliasScope {\n const bindings = new Map<string, number>()\n\n const bindSource = (source: From): void => {\n if (source.type === `unionFrom`) {\n source.sources.forEach(bindSource)\n return\n }\n if (source.type === `unionAll`) return\n if (!bindings.has(source.alias)) {\n bindings.set(source.alias, bindings.size)\n }\n }\n\n bindSource(query.from)\n query.join?.forEach(({ from }) => bindSource(from))\n return {\n bindings,\n hasUnqualifiedOutput: query.from.type === `unionAll`,\n parent,\n }\n}\n\nfunction resolveAliasBinding(\n scope: AliasScope | undefined,\n alias: string,\n): readonly [number, number] | undefined {\n let current = scope\n let parentDistance = 0\n while (current) {\n const binding = current.bindings.get(alias)\n if (binding !== undefined) return [parentDistance, binding]\n // A result-level union has no source alias. Every downstream ref starts at\n // an output field, including nested paths such as profile.id, so it must\n // not fall through and bind that field name to an enclosing query alias.\n if (current.hasUnqualifiedOutput) return undefined\n current = current.parent\n parentDistance++\n }\n return undefined\n}\n\nfunction canonicalizeQuery(\n query: QueryIR,\n path: string,\n seen: WeakSet<object>,\n parentScope?: AliasScope,\n): StableIdentityValue {\n return canonicalizeQueryInScope(\n query,\n path,\n seen,\n createAliasScope(query, parentScope),\n )\n}\n\nfunction canonicalizeQueryInScope(\n query: QueryIR,\n path: string,\n seen: WeakSet<object>,\n scope: AliasScope,\n): StableIdentityValue {\n if (query.fnSelect) {\n throw new UnhashableQueryIRError(`${path}.fnSelect`, `function select`)\n }\n\n if (query.fnWhere?.length) {\n throw new UnhashableQueryIRError(`${path}.fnWhere`, `function where`)\n }\n\n if (query.fnHaving?.length) {\n throw new UnhashableQueryIRError(`${path}.fnHaving`, `function having`)\n }\n\n const result: Record<string, StableIdentityValue> = {\n type: `query`,\n from: canonicalizeSource(query.from, `${path}.from`, seen, scope),\n }\n\n if (query.select) {\n result.select = canonicalizeSelect(\n query.select,\n `${path}.select`,\n seen,\n scope,\n )\n }\n\n if (\n !query.select &&\n (query.from.type === `unionFrom` ||\n query.join !== undefined ||\n query.groupBy !== undefined)\n ) {\n // Without an explicit projection, these query shapes return a namespaced\n // row. Its alias keys are public output and therefore part of identity.\n result.implicitOutput = {\n type: `namespaced`,\n aliases: Array.from(scope.bindings.keys()),\n }\n }\n\n if (query.join) {\n result.join = query.join.map((join, index) =>\n canonicalizeJoin(join, `${path}.join[${index}]`, seen, scope),\n )\n }\n\n if (query.where) {\n result.where = canonicalizeImplicitConjunction(\n query.where,\n `${path}.where`,\n seen,\n scope,\n )\n }\n\n if (query.groupBy) {\n result.groupBy = query.groupBy.map((expression, index) =>\n canonicalizeExpression(\n expression,\n `${path}.groupBy[${index}]`,\n seen,\n `exact-output`,\n scope,\n ),\n )\n }\n\n if (query.having) {\n result.having = canonicalizeImplicitConjunction(\n query.having,\n `${path}.having`,\n seen,\n scope,\n )\n }\n\n if (query.orderBy) {\n result.orderBy = query.orderBy.map((orderBy, index) =>\n canonicalizeOrderBy(\n orderBy,\n `${path}.orderBy[${index}]`,\n seen,\n `ordering-operand`,\n scope,\n ),\n )\n }\n\n if (query.limit !== undefined) {\n result.limit = canonicalizeRuntimeValue(query.limit, `${path}.limit`, seen)\n }\n\n if (query.offset !== undefined && query.offset !== 0) {\n result.offset = canonicalizeRuntimeValue(\n query.offset,\n `${path}.offset`,\n seen,\n )\n }\n\n if (query.distinct) {\n result.distinct = true\n }\n\n if (query.singleResult) {\n result.singleResult = true\n }\n\n return result\n}\n\nfunction canonicalizeImplicitConjunction(\n clauses: ReadonlyArray<Where | Having>,\n path: string,\n seen: WeakSet<object>,\n scope: AliasScope,\n): Array<StableIdentityValue> {\n const canonical = clauses.map((clause, index) =>\n canonicalizeWhere(clause, `${path}[${index}]`, seen, scope),\n )\n canonical.sort(compareStableIdentityValues)\n\n return canonical.filter(\n (clause, index) =>\n index === 0 ||\n compareStableIdentityValues(clause, canonical[index - 1]!) !== 0,\n )\n}\n\nfunction canonicalizeLoadSubsetQuery(\n options: LoadSubsetOptions,\n path: string,\n seen: WeakSet<object>,\n): StableIdentityValue {\n const result: Record<string, StableIdentityValue> = {\n type: `loadSubsetQuery`,\n }\n\n if (options.where !== undefined) {\n result.where = canonicalizeExpression(\n options.where,\n `${path}.where`,\n seen,\n `exact-output`,\n )\n }\n\n if (options.orderBy?.length) {\n result.orderBy = options.orderBy.map((orderBy, index) =>\n canonicalizeOrderBy(\n orderBy,\n `${path}.orderBy[${index}]`,\n seen,\n `ordering-operand`,\n ),\n )\n }\n\n return result\n}\n\nfunction canonicalizeJoin(\n join: JoinClause,\n path: string,\n seen: WeakSet<object>,\n scope: AliasScope,\n): StableIdentityValue {\n return {\n type: join.type,\n from: canonicalizeSource(join.from, `${path}.from`, seen, scope),\n left: canonicalizeExpression(\n join.left,\n `${path}.left`,\n seen,\n `equality-operand`,\n scope,\n ),\n right: canonicalizeExpression(\n join.right,\n `${path}.right`,\n seen,\n `equality-operand`,\n scope,\n ),\n }\n}\n\nfunction canonicalizeSource(\n source: From,\n path: string,\n seen: WeakSet<object>,\n scope: AliasScope,\n): StableIdentityValue {\n if (source.type === `collectionRef`) {\n return {\n type: `collectionRef`,\n collectionId: canonicalizeRuntimeValue(\n source.collection.id,\n `${path}.collection.id`,\n seen,\n ),\n }\n }\n\n if (source.type === `unionFrom`) {\n return {\n type: `unionFrom`,\n sources: source.sources.map((unionSource, index) =>\n canonicalizeSource(\n unionSource,\n `${path}.sources[${index}]`,\n seen,\n scope,\n ),\n ),\n }\n }\n\n if (source.type === `unionAll`) {\n return {\n type: `unionAll`,\n queries: source.queries.map((query, index) =>\n // Branches are peers that may capture the union query's outer scope;\n // they are not children of the union result row itself.\n canonicalizeQuery(\n query,\n `${path}.queries[${index}]`,\n seen,\n scope.parent,\n ),\n ),\n }\n }\n\n return {\n type: `queryRef`,\n query: canonicalizeQuery(source.query, `${path}.query`, seen, scope),\n }\n}\n\nfunction canonicalizeSelect(\n select: Select,\n path: string,\n seen: WeakSet<object>,\n scope?: AliasScope,\n): StableIdentityValue {\n return {\n type: `select`,\n fields: Object.keys(select)\n .sort()\n .map((key) => [\n key,\n canonicalizeSelectValue(select[key]!, `${path}.${key}`, seen, scope),\n ]),\n }\n}\n\nfunction canonicalizeSelectValue(\n value: unknown,\n path: string,\n seen: WeakSet<object>,\n scope?: AliasScope,\n): StableIdentityValue {\n if (isRefProxy(value)) {\n return canonicalizeExpression(\n toExpression(value),\n path,\n seen,\n `exact-output`,\n scope,\n )\n }\n\n if (isExpression(value)) {\n return canonicalizeExpression(value, path, seen, `exact-output`, scope)\n }\n\n if (isPlainObject(value)) {\n return canonicalizeSelect(value as Select, path, seen, scope)\n }\n\n return canonicalizeExactOutputRuntimeValue(value, path, seen)\n}\n\nfunction canonicalizeWhere(\n where: Where | Having,\n path: string,\n seen: WeakSet<object>,\n scope?: AliasScope,\n): StableIdentityValue {\n if (isWhereObject(where)) {\n const result: Record<string, StableIdentityValue> = {\n type: `where`,\n expression: canonicalizeExpression(\n where.expression,\n `${path}.expression`,\n seen,\n `exact-output`,\n scope,\n ),\n }\n\n if (where.residual === true) {\n result.residual = true\n }\n\n return result\n }\n\n return canonicalizeExpression(where, path, seen, `exact-output`, scope)\n}\n\nfunction canonicalizeOrderBy(\n orderBy: OrderByClause,\n path: string,\n seen: WeakSet<object>,\n valueContext: ValueIdentityContext = `exact-output`,\n scope?: AliasScope,\n): StableIdentityValue {\n return {\n expression: canonicalizeExpression(\n orderBy.expression,\n `${path}.expression`,\n seen,\n valueContext,\n scope,\n ),\n compareOptions: canonicalizeRuntimeValue(\n orderBy.compareOptions,\n `${path}.compareOptions`,\n seen,\n ),\n }\n}\n\nfunction canonicalizeExpression(\n expression:\n | BasicExpression\n | Aggregate\n | IncludesSubquery\n | ConditionalSelect,\n path: string,\n seen: WeakSet<object>,\n valueContext: ValueIdentityContext = `exact-output`,\n scope?: AliasScope,\n): StableIdentityValue {\n if (expression.type === `ref`) {\n const binding = resolveAliasBinding(scope, expression.path[0] ?? ``)\n return {\n type: `ref`,\n path:\n binding === undefined\n ? expression.path.map((segment, index) =>\n canonicalizeRuntimeValue(segment, `${path}.path[${index}]`, seen),\n )\n : [\n [`binding`, ...binding],\n ...expression.path\n .slice(1)\n .map((segment, index) =>\n canonicalizeRuntimeValue(\n segment,\n `${path}.path[${index + 1}]`,\n seen,\n ),\n ),\n ],\n }\n }\n\n if (expression.type === `val`) {\n return {\n type: `val`,\n value:\n valueContext === `equality-operand`\n ? canonicalizeEqualityRuntimeValue(\n expression.value,\n `${path}.value`,\n seen,\n scope,\n )\n : valueContext === `ordering-operand`\n ? canonicalizeOrderingRuntimeValue(\n expression.value,\n `${path}.value`,\n seen,\n )\n : canonicalizeExactOutputRuntimeValue(\n expression.value,\n `${path}.value`,\n seen,\n ),\n }\n }\n\n if (expression.type === `func`) {\n if (\n expression.name === `in` &&\n expression.args.length === 2 &&\n expression.args[1]?.type === `val` &&\n Array.isArray(expression.args[1].value)\n ) {\n const candidates = expression.args[1].value.map((value, index) =>\n canonicalizeEqualityRuntimeValue(\n value,\n `${path}.args[1].value[${index}]`,\n seen,\n scope,\n ),\n )\n return canonicalizeFunction(expression.name, [\n canonicalizeExpression(\n expression.args[0]!,\n `${path}.args[0]`,\n seen,\n `equality-operand`,\n scope,\n ),\n {\n type: `val`,\n // IN tests membership. Candidate order and duplicates do not change\n // its result, but each candidate keeps its own equality semantics.\n value: [`set`, sortUniqueStableIdentityValues(candidates)],\n },\n ])\n }\n\n const operandContext: ValueIdentityContext =\n expression.name === `eq`\n ? `equality-operand`\n : expression.name === `gt` ||\n expression.name === `gte` ||\n expression.name === `lt` ||\n expression.name === `lte`\n ? `ordering-operand`\n : `exact-output`\n const args = expression.args.map((arg, index) =>\n canonicalizeExpression(\n arg,\n `${path}.args[${index}]`,\n seen,\n operandContext,\n scope,\n ),\n )\n return canonicalizeFunction(expression.name, args)\n }\n\n if (expression.type === `agg`) {\n return {\n type: `agg`,\n name: expression.name,\n args: expression.args.map((arg, index) =>\n canonicalizeExpression(\n arg,\n `${path}.args[${index}]`,\n seen,\n `exact-output`,\n scope,\n ),\n ),\n }\n }\n\n if (expression.type === `conditionalSelect`) {\n const result: Record<string, StableIdentityValue> = {\n type: `conditionalSelect`,\n branches: expression.branches.map((branch, index) => ({\n condition: canonicalizeExpression(\n branch.condition,\n `${path}.branches[${index}].condition`,\n seen,\n `exact-output`,\n scope,\n ),\n value: canonicalizeSelectValue(\n branch.value,\n `${path}.branches[${index}].value`,\n seen,\n scope,\n ),\n })),\n }\n\n if (expression.defaultValue !== undefined) {\n result.defaultValue = canonicalizeSelectValue(\n expression.defaultValue,\n `${path}.defaultValue`,\n seen,\n scope,\n )\n }\n\n return result\n }\n\n const childScope = createAliasScope(expression.query, scope)\n const result: Record<string, StableIdentityValue> = {\n type: `includesSubquery`,\n query: canonicalizeQueryInScope(\n expression.query,\n `${path}.query`,\n seen,\n childScope,\n ),\n correlationField: canonicalizeExpression(\n expression.correlationField,\n `${path}.correlationField`,\n seen,\n `equality-operand`,\n scope,\n ),\n childCorrelationField: canonicalizeExpression(\n expression.childCorrelationField,\n `${path}.childCorrelationField`,\n seen,\n `equality-operand`,\n childScope,\n ),\n fieldName: expression.fieldName,\n materialization: expression.materialization,\n }\n\n if (expression.parentFilters) {\n result.parentFilters = expression.parentFilters.map((where, index) =>\n canonicalizeWhere(where, `${path}.parentFilters[${index}]`, seen, scope),\n )\n }\n\n if (expression.parentProjection) {\n result.parentProjection = expression.parentProjection.map(\n (projection, index) =>\n canonicalizeExpression(\n projection,\n `${path}.parentProjection[${index}]`,\n seen,\n `exact-output`,\n scope,\n ),\n )\n }\n\n if (expression.scalarField !== undefined) {\n result.scalarField = expression.scalarField\n }\n\n return result\n}\n\nfunction canonicalizeFunction(\n name: string,\n args: Array<StableIdentityValue>,\n): StableIdentityValue {\n if ((name === `and` || name === `or`) && args.length > 0) {\n const flattened = args.flatMap((arg) =>\n isCanonicalFunction(arg, name) ? arg.args : [arg],\n )\n const unique = sortUniqueStableIdentityValues(flattened)\n\n // The evaluator gives `and` and `or` boolean results even when their sole\n // operand returns another truthy or falsy value. Keep that coercion in the\n // identity because expression result types are erased at runtime.\n return { type: `func`, name, args: unique }\n }\n\n if (name === `eq` && args.length === 2) {\n args.sort(compareStableIdentityValues)\n return { type: `func`, name, args }\n }\n\n if (\n (name === `gt` || name === `gte` || name === `lt` || name === `lte`) &&\n args.length === 2 &&\n compareStableIdentityValues(args[0]!, args[1]!) > 0\n ) {\n return {\n type: `func`,\n name: invertComparison(name),\n args: [args[1]!, args[0]!],\n }\n }\n\n return { type: `func`, name, args }\n}\n\nfunction sortUniqueStableIdentityValues(\n values: Array<StableIdentityValue>,\n): Array<StableIdentityValue> {\n const keyedValues = values.map((value) => ({\n key: JSON.stringify(value),\n value,\n }))\n keyedValues.sort((a, b) => (a.key < b.key ? -1 : a.key > b.key ? 1 : 0))\n return keyedValues\n .filter(\n (entry, index) =>\n index === 0 || entry.key !== keyedValues[index - 1]!.key,\n )\n .map((entry) => entry.value)\n}\n\nfunction isCanonicalFunction(\n value: StableIdentityValue,\n name: string,\n): value is {\n type: string\n name: string\n args: Array<StableIdentityValue>\n} {\n return (\n value !== null &&\n typeof value === `object` &&\n !Array.isArray(value) &&\n value.type === `func` &&\n value.name === name &&\n Array.isArray(value.args)\n )\n}\n\nfunction invertComparison(\n name: `gt` | `gte` | `lt` | `lte`,\n): `gt` | `gte` | `lt` | `lte` {\n switch (name) {\n case `gt`:\n return `lt`\n case `gte`:\n return `lte`\n case `lt`:\n return `gt`\n case `lte`:\n return `gte`\n }\n}\n\nfunction canonicalizeRuntimeValue(\n value: unknown,\n path: string,\n seen: WeakSet<object>,\n): StableIdentityValue {\n if (value === null) return [`null`]\n\n if (typeof value === `string`) {\n return [`string`, value]\n }\n\n if (typeof value === `boolean`) {\n return [`boolean`, value]\n }\n\n if (typeof value === `number`) {\n if (Number.isNaN(value)) {\n return [`number`, `NaN`]\n }\n\n if (value === Infinity) {\n return [`number`, `Infinity`]\n }\n\n if (value === -Infinity) {\n return [`number`, `-Infinity`]\n }\n\n if (Object.is(value, -0)) {\n return [`number`, `-0`]\n }\n\n return [`number`, value]\n }\n\n if (typeof value === `undefined`) {\n return [`undefined`]\n }\n\n if (typeof value === `bigint`) {\n return [`bigint`, value.toString()]\n }\n\n if (typeof value === `function`) {\n throw new UnhashableQueryIRError(path, `function value`)\n }\n\n if (typeof value === `symbol`) {\n throw new UnhashableQueryIRError(path, `symbol value`)\n }\n\n if (isRefProxy(value)) {\n return canonicalizeExpression(toExpression(value), path, seen)\n }\n\n if (Array.isArray(value)) {\n return withCircularGuard(value, path, seen, () => [\n `array`,\n value.map((item, index) =>\n canonicalizeRuntimeValue(item, `${path}[${index}]`, seen),\n ),\n ])\n }\n\n if (value instanceof Date) {\n const timestamp = value.getTime()\n if (Number.isNaN(timestamp)) {\n throw new UnhashableQueryIRError(path, `invalid Date`)\n }\n\n return [`Date`, value.toISOString()]\n }\n\n if (value instanceof ArrayBuffer) {\n return [`binary`, `ArrayBuffer`, Array.from(new Uint8Array(value))]\n }\n\n if (ArrayBuffer.isView(value)) {\n return [\n `binary`,\n value.constructor.name,\n Array.from(\n new Uint8Array(value.buffer, value.byteOffset, value.byteLength),\n ),\n ]\n }\n\n if (value instanceof Map) {\n return withCircularGuard(value, path, seen, () => {\n const entries = Array.from(\n value.entries(),\n ([key, entryValue], index) => [\n canonicalizeRuntimeValue(key, `${path}.key[${index}]`, seen),\n canonicalizeRuntimeValue(entryValue, `${path}.value[${index}]`, seen),\n ],\n )\n entries.sort(compareStableIdentityValues)\n return [`Map`, entries]\n })\n }\n\n if (value instanceof Set) {\n return withCircularGuard(value, path, seen, () => {\n const entries = Array.from(value, (entry, index) =>\n canonicalizeRuntimeValue(entry, `${path}[${index}]`, seen),\n )\n entries.sort(compareStableIdentityValues)\n return [`Set`, entries]\n })\n }\n\n if (isPlainObject(value)) {\n return canonicalizeObject(value, path, seen)\n }\n\n throw new UnhashableQueryIRError(path, `non-plain object value`)\n}\n\nfunction canonicalizeExactOutputRuntimeValue(\n value: unknown,\n path: string,\n seen: WeakSet<object>,\n): StableIdentityValue {\n if (typeof value === `object` && value !== null) {\n return getRuntimeReferenceIdentity(value)\n }\n\n return canonicalizeRuntimeValue(value, path, seen)\n}\n\nfunction canonicalizeEqualityRuntimeValue(\n value: unknown,\n path: string,\n seen: WeakSet<object>,\n scope?: AliasScope,\n): StableIdentityValue {\n if (isRefProxy(value)) {\n return canonicalizeExpression(\n toExpression(value),\n path,\n seen,\n `equality-operand`,\n scope,\n )\n }\n\n if (typeof value === `number` && Object.is(value, -0)) {\n return canonicalizeRuntimeValue(0, path, seen)\n }\n\n // Equality compares Uint8Array and Buffer values by content, independent of\n // their concrete constructor and size.\n const isUint8Array =\n (typeof Buffer !== `undefined` && value instanceof Buffer) ||\n value instanceof Uint8Array\n if (isUint8Array) {\n return [`binary`, `Uint8Array`, Array.from(value as Uint8Array)]\n }\n\n const normalized = normalizeValue(value)\n if (normalized !== value) {\n return canonicalizeRuntimeValue(normalized, path, seen)\n }\n\n if (typeof value === `object` && value !== null) {\n return getRuntimeReferenceIdentity(value)\n }\n\n return canonicalizeRuntimeValue(value, path, seen)\n}\n\nfunction canonicalizeOrderingRuntimeValue(\n value: unknown,\n path: string,\n seen: WeakSet<object>,\n): StableIdentityValue {\n if (typeof value === `number` && Object.is(value, -0)) {\n return canonicalizeRuntimeValue(0, path, seen)\n }\n\n if (value instanceof Date && Number.isNaN(value.getTime())) {\n return canonicalizeRuntimeValue(Number.NaN, path, seen)\n }\n\n const normalized = normalizeValue(value)\n if (normalized !== value && !(value instanceof Uint8Array)) {\n return canonicalizeRuntimeValue(normalized, path, seen)\n }\n\n try {\n return canonicalizeRuntimeValue(value, path, seen)\n } catch (error) {\n if (\n error instanceof UnhashableQueryIRError &&\n typeof value === `object` &&\n value !== null\n ) {\n return getRuntimeReferenceIdentity(value)\n }\n throw error\n }\n}\n\nfunction compareStableIdentityValues(\n left: StableIdentityValue,\n right: StableIdentityValue,\n): number {\n const serializedLeft = JSON.stringify(left)\n const serializedRight = JSON.stringify(right)\n return serializedLeft < serializedRight\n ? -1\n : serializedLeft > serializedRight\n ? 1\n : 0\n}\n\nfunction canonicalizeObject(\n value: Record<string, unknown>,\n path: string,\n seen: WeakSet<object>,\n): StableIdentityValue {\n return withCircularGuard(value, path, seen, () => [\n `object`,\n Object.keys(value)\n .sort()\n .map((key) => [\n key,\n canonicalizeRuntimeValue(value[key], `${path}.${key}`, seen),\n ]),\n ])\n}\n\nfunction withCircularGuard<T>(\n value: object,\n path: string,\n seen: WeakSet<object>,\n callback: () => T,\n): T {\n if (seen.has(value)) {\n throw new UnhashableQueryIRError(path, `circular value`)\n }\n\n seen.add(value)\n try {\n return callback()\n } finally {\n seen.delete(value)\n }\n}\n\nfunction isWhereObject(\n where: Where | Having,\n): where is { expression: BasicExpression<boolean>; residual?: boolean } {\n return `expression` in where\n}\n\nfunction isExpression(\n value: unknown,\n): value is BasicExpression | Aggregate | IncludesSubquery {\n if (value === null || typeof value !== `object`) {\n return false\n }\n\n const expressionType = (value as { type?: unknown }).type\n return (\n expressionType === `agg` ||\n expressionType === `conditionalSelect` ||\n expressionType === `func` ||\n expressionType === `ref` ||\n expressionType === `val` ||\n expressionType === `includesSubquery`\n )\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== `object`) return false\n\n const prototype = Object.getPrototypeOf(value)\n return prototype === Object.prototype || prototype === null\n}\n"],"names":["getQueryIR","index","isRefProxy","toExpression","result","getRuntimeReferenceIdentity","normalizeValue"],"mappings":"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"}