@aws-amplify/datastore
Version:
AppSyncLocal support for aws-amplify
1 lines • 53.9 kB
Source Map (JSON)
{"version":3,"file":"next.mjs","sources":["../../../src/predicates/next.ts"],"sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport { PredicateInternalsKey, } from '../types';\nimport { ModelRelationship } from '../storage/relationship';\nimport { asyncEvery, asyncSome } from '../util';\nimport { ModelPredicateCreator as FlatModelPredicateCreator, comparisonKeys, } from './index';\nconst ops = [...comparisonKeys];\n/**\n * A map from keys (exposed to customers) to the internal predicate data\n * structures invoking code should not muck with.\n */\nconst predicateInternalsMap = new Map();\n/**\n * Creates a link between a key (and generates a key if needed) and an internal\n * `GroupCondition`, which allows us to return a key object instead of the gory\n * conditions details to customers/invoking code.\n *\n * @param condition The internal condition to keep hidden.\n * @param key The object DataStore will use to find the internal condition.\n * If no key is given, an empty one is created.\n */\nconst registerPredicateInternals = (condition, key) => {\n const finalKey = key || new PredicateInternalsKey();\n predicateInternalsMap.set(finalKey, condition);\n return finalKey;\n};\n/**\n * Takes a key object from `registerPredicateInternals()` to fetch an internal\n * `GroupCondition` object, which can then be used to query storage or\n * test/match objects.\n *\n * This indirection exists to hide `GroupCondition` from public interfaces, since\n * `GroupCondition` contains extra methods and properties that public callers\n * should not use.\n *\n * @param key A key object previously returned by `registerPredicateInternals()`\n */\nexport const internals = (key) => {\n if (!predicateInternalsMap.has(key)) {\n throw new Error(\"Invalid predicate. Terminate your predicate with a valid condition (e.g., `p => p.field.eq('value')`) or pass `Predicates.ALL`.\");\n }\n return predicateInternalsMap.get(key);\n};\n/**\n * Maps operators to negated operators.\n * Used to facilitate propagation of negation down a tree of conditions.\n */\nconst negations = {\n and: 'or',\n or: 'and',\n not: 'and',\n eq: 'ne',\n ne: 'eq',\n gt: 'le',\n ge: 'lt',\n lt: 'ge',\n le: 'gt',\n contains: 'notContains',\n notContains: 'contains',\n in: 'notIn',\n notIn: 'in',\n};\n/**\n * A condition that can operate against a single \"primitive\" field of a model or item.\n * @member field The field of *some record* to test against.\n * @member operator The equality or comparison operator to use.\n * @member operands The operands for the equality/comparison check.\n */\nexport class FieldCondition {\n constructor(field, operator, operands) {\n this.field = field;\n this.operator = operator;\n this.operands = operands;\n this.validate();\n }\n /**\n * Creates a copy of self.\n * @param extract Not used. Present only to fulfill the `UntypedCondition` interface.\n * @returns A new, identitical `FieldCondition`.\n */\n copy() {\n return [\n new FieldCondition(this.field, this.operator, [...this.operands]),\n undefined,\n ];\n }\n /**\n * Produces a tree structure similar to a graphql condition. The returned\n * structure is \"dumb\" and is intended for another query/condition\n * generation mechanism to interpret, such as the cloud or storage query\n * builders.\n *\n * E.g.,\n *\n * ```json\n * {\n * \t\"name\": {\n * \t\t\"eq\": \"robert\"\n * \t}\n * }\n * ```\n */\n toAST() {\n return {\n [this.field]: {\n [this.operator]: this.operator === 'between'\n ? [this.operands[0], this.operands[1]]\n : this.operands[0],\n },\n };\n }\n /**\n * Produces a new condition (`FieldCondition` or `GroupCondition`) that\n * matches the opposite of this condition.\n *\n * Intended to be used when applying De Morgan's Law, which can be done to\n * produce more efficient queries against the storage layer if a negation\n * appears in the query tree.\n *\n * For example:\n *\n * 1. `name.eq('robert')` becomes `name.ne('robert')`\n * 2. `price.between(100, 200)` becomes `m => m.or(m => [m.price.lt(100), m.price.gt(200)])`\n *\n * @param model The model meta to use when construction a new `GroupCondition`\n * for cases where the negation requires multiple `FieldCondition`'s.\n */\n negated(model) {\n if (this.operator === 'between') {\n return new GroupCondition(model, undefined, undefined, 'or', [\n new FieldCondition(this.field, 'lt', [this.operands[0]]),\n new FieldCondition(this.field, 'gt', [this.operands[1]]),\n ]);\n }\n else if (this.operator === 'beginsWith') {\n // beginsWith negation doesn't have a good, safe optimation right now.\n // just re-wrap it in negation. The adapter will have to scan-and-filter,\n // as is likely optimal for negated beginsWith conditions *anyway*.\n return new GroupCondition(model, undefined, undefined, 'not', [\n new FieldCondition(this.field, 'beginsWith', [this.operands[0]]),\n ]);\n }\n else {\n return new FieldCondition(this.field, negations[this.operator], this.operands);\n }\n }\n /**\n * Not implemented. Not needed. GroupCondition instead consumes FieldConditions and\n * transforms them into legacy predicates. (*For now.*)\n * @param storage N/A. If ever implemented, the storage adapter to query.\n * @returns N/A. If ever implemented, return items from `storage` that match.\n */\n async fetch() {\n // eslint-disable-next-line prefer-promise-reject-errors\n return Promise.reject('No implementation needed [yet].');\n }\n /**\n * Determins whether a given item matches the expressed condition.\n * @param item The item to test.\n * @returns `Promise<boolean>`, `true` if matches; `false` otherwise.\n */\n async matches(item) {\n const v = item[this.field];\n const operations = {\n eq: () => v === this.operands[0],\n ne: () => v !== this.operands[0],\n gt: () => v > this.operands[0],\n ge: () => v >= this.operands[0],\n lt: () => v < this.operands[0],\n le: () => v <= this.operands[0],\n contains: () => v?.indexOf(this.operands[0]) > -1,\n notContains: () => (!v ? true : v.indexOf(this.operands[0]) === -1),\n beginsWith: () => v?.startsWith(this.operands[0]),\n between: () => v >= this.operands[0] && v <= this.operands[1],\n in: () => {\n const values = this.operands[0];\n return Array.isArray(values) && values.includes(v);\n },\n notIn: () => {\n const values = this.operands[0];\n return Array.isArray(values) && !values.includes(v);\n },\n };\n const operation = operations[this.operator];\n if (operation) {\n const result = operation();\n return result;\n }\n else {\n throw new Error(`Invalid operator given: ${this.operator}`);\n }\n }\n /**\n * Checks `this.operands` for compatibility with `this.operator`.\n */\n validate() {\n /**\n * Creates a validator that checks for a particular `operands` count.\n * Throws an exception if the `count` disagrees with `operands.length`.\n * @param count The number of `operands` expected.\n */\n const argumentCount = count => {\n const argsClause = count === 1 ? 'argument is' : 'arguments are';\n return () => {\n if (this.operands.length !== count) {\n return `Exactly ${count} ${argsClause} required.`;\n }\n };\n };\n // NOTE: validations should return a message on failure.\n // hence, they should be \"joined\" together with logical OR's\n // as seen in the `between:` entry.\n const validations = {\n eq: argumentCount(1),\n ne: argumentCount(1),\n gt: argumentCount(1),\n ge: argumentCount(1),\n lt: argumentCount(1),\n le: argumentCount(1),\n contains: argumentCount(1),\n notContains: argumentCount(1),\n beginsWith: argumentCount(1),\n between: () => argumentCount(2)() ||\n (this.operands[0] > this.operands[1]\n ? 'The first argument must be less than or equal to the second argument.'\n : null),\n in: () => {\n const countError = argumentCount(1)();\n if (countError)\n return countError;\n const values = this.operands[0];\n if (!Array.isArray(values)) {\n return 'The argument must be an array.';\n }\n return null;\n },\n notIn: () => {\n const countError = argumentCount(1)();\n if (countError)\n return countError;\n const values = this.operands[0];\n if (!Array.isArray(values)) {\n return 'The argument must be an array.';\n }\n return null;\n },\n };\n const validate = validations[this.operator];\n if (validate) {\n const e = validate();\n if (typeof e === 'string')\n throw new Error(`Incorrect usage of \\`${this.operator}()\\`: ${e}`);\n }\n else {\n throw new Error(`Non-existent operator: \\`${this.operator}()\\``);\n }\n }\n}\n/**\n * Small utility function to generate a monotonically increasing ID.\n * Used by GroupCondition to help keep track of which group is doing what,\n * when, and where during troubleshooting.\n */\nconst getGroupId = (() => {\n let seed = 1;\n return () => `group_${seed++}`;\n})();\n/**\n * A set of sub-conditions to operate against a model, optionally scoped to\n * a specific field, combined with the given operator (one of `and`, `or`, or `not`).\n * @member groupId Used to distinguish between GroupCondition instances for\n * debugging and troublehsooting.\n * @member model A metadata object that tells GroupCondition what to query and how.\n * @member field The field on the model that the sub-conditions apply to.\n * @member operator How to group child conditions together.\n * @member operands The child conditions.\n */\nexport class GroupCondition {\n constructor(\n /**\n * The `ModelMeta` of the model to query and/or filter against.\n * Expected to contain:\n *\n * ```js\n * {\n * \tbuilder: ModelConstructor,\n * \tschema: SchemaModel,\n * \tpkField: string[]\n * }\n * ```\n */\n model, \n /**\n * If populated, this group specifices a condition on a relationship.\n *\n * If `field` does *not* point to a related model, that's an error. It\n * could indicate that the `GroupCondition` was instantiated with bad\n * data, or that the model metadata is incorrect.\n */\n field, \n /**\n * If a `field` is given, whether the relationship is a `HAS_ONE`,\n * 'HAS_MANY`, or `BELONGS_TO`.\n *\n * TODO: Remove this and replace with derivation using\n * `ModelRelationship.from(this.model, this.field).relationship`;\n */\n relationshipType, \n /**\n *\n */\n operator, \n /**\n *\n */\n operands, \n /**\n * Whether this GroupCondition is the result of an optimize call.\n *\n * This is used to guard against infinitely fetch -> optimize -> fetch\n * recursion.\n */\n isOptimized = false) {\n this.model = model;\n this.field = field;\n this.relationshipType = relationshipType;\n this.operator = operator;\n this.operands = operands;\n this.isOptimized = isOptimized;\n // `groupId` was used for development/debugging.\n // Should we leave this in for future troubleshooting?\n this.groupId = getGroupId();\n }\n /**\n * Returns a copy of a GroupCondition, which also returns the copy of a\n * given reference node to \"extract\".\n * @param extract A node of interest. Its copy will *also* be returned if the node exists.\n * @returns [The full copy, the copy of `extract` | undefined]\n */\n copy(extract) {\n const copied = new GroupCondition(this.model, this.field, this.relationshipType, this.operator, []);\n let extractedCopy = extract === this ? copied : undefined;\n this.operands.forEach(o => {\n const [operandCopy, extractedFromOperand] = o.copy(extract);\n copied.operands.push(operandCopy);\n extractedCopy = extractedCopy || extractedFromOperand;\n });\n return [copied, extractedCopy];\n }\n /**\n * Creates a new `GroupCondition` that contains only the local field conditions,\n * omitting related model conditions. That resulting `GroupCondition` can be\n * used to produce predicates that are compatible with the storage adapters and\n * Cloud storage.\n *\n * @param negate Whether the condition tree should be negated according\n * to De Morgan's law.\n */\n withFieldConditionsOnly(negate) {\n const negateChildren = negate !== (this.operator === 'not');\n return new GroupCondition(this.model, undefined, undefined, (negate ? negations[this.operator] : this.operator), this.operands\n .filter(o => o instanceof FieldCondition)\n .map(o => negateChildren ? o.negated(this.model) : o));\n }\n /**\n * Returns a version of the predicate tree with unnecessary logical groups\n * condensed and merged together. This is intended to create a dense tree\n * with leaf nodes (`FieldCondition`'s) aggregated under as few group conditions\n * as possible for the most efficient fetching possible -- it allows `fetch()`.\n *\n * E.g. a grouping like this:\n *\n * ```yaml\n * and:\n * \tand:\n * \t\tid:\n * \t\t\teq: \"abc\"\n * \tand:\n * \t\tname:\n * \t\t\teq: \"xyz\"\n * ```\n *\n * Will become this:\n *\n * ```yaml\n * and:\n * \tid:\n * \t\teq: \"abc\"\n * \tname:\n * \t\teq: \"xyz\"\n * ```\n *\n * This allows `fetch()` to pass both the `id` and `name` conditions to the adapter\n * together, which can then decide what index to use based on both fields together.\n *\n * @param preserveNode Whether to preserve the current node and to explicitly not eliminate\n * it during optimization. Used internally to preserve the root node and children of\n * `not` groups. `not` groups will always have a single child, so there's nothing to\n * optimize below a `not` (for now), and it makes the query logic simpler later.\n */\n optimized(preserveNode = true) {\n const operands = this.operands.map(o => o instanceof GroupCondition ? o.optimized(this.operator === 'not') : o);\n // we're only collapsing and/or groups that contains a single child for now,\n // because they're much more common and much more trivial to collapse. basically,\n // an `and`/`or` that contains a single child doesn't require the layer of\n // logical grouping.\n if (!preserveNode &&\n ['and', 'or'].includes(this.operator) &&\n !this.field &&\n operands.length === 1) {\n const operand = operands[0];\n if (operand instanceof FieldCondition) {\n // between conditions should NOT be passed up the chain. if they\n // need to be *negated* later, it is important that they be properly\n // contained in an AND group. when de morgan's law is applied, the\n // conditions are reversed and the AND group flips to an OR. this\n // doesn't work right if the a `between` doesn't live in an AND group.\n if (operand.operator !== 'between') {\n return operand;\n }\n }\n else {\n return operand;\n }\n }\n return new GroupCondition(this.model, this.field, this.relationshipType, this.operator, operands, true);\n }\n /**\n * Fetches matching records from a given storage adapter using legacy predicates (for now).\n * @param storage The storage adapter this predicate will query against.\n * @param breadcrumb For debugging/troubleshooting. A list of the `groupId`'s this\n * GroupdCondition.fetch is nested within.\n * @param negate Whether to match on the `NOT` of `this`.\n * @returns An `Promise` of `any[]` from `storage` matching the child conditions.\n */\n async fetch(storage, breadcrumb = [], negate = false) {\n if (!this.isOptimized) {\n return this.optimized().fetch(storage);\n }\n const resultGroups = [];\n const operator = (negate ? negations[this.operator] : this.operator);\n const negateChildren = negate !== (this.operator === 'not');\n /**\n * Conditions that must be branched out and used to generate a base, \"candidate\"\n * result set.\n *\n * If `field` is populated, these groups select *related* records, and the base,\n * candidate results are selected to match those.\n */\n const groups = this.operands.filter(op => op instanceof GroupCondition);\n /**\n * Simple conditions that must match the target model of `this`.\n */\n const conditions = this.operands.filter(op => op instanceof FieldCondition);\n for (const g of groups) {\n const relatives = await g.fetch(storage, [...breadcrumb, this.groupId], negateChildren);\n // no relatives -> no need to attempt to perform a \"join\" query for\n // candidate results:\n //\n // select a.* from a,b where b.id in EMPTY_SET ==> EMPTY_SET\n //\n // Additionally, the entire (sub)-query can be short-circuited if\n // the operator is `AND`. Illustrated in SQL:\n //\n // select a.* from a where\n // id in [a,b,c]\n // AND <\n // id in EMTPY_SET <<< Look!\n // AND <\n // id in [x,y,z]\n //\n // YIELDS: EMPTY_SET // <-- Easy peasy. Lemon squeezy.\n //\n if (relatives.length === 0) {\n // aggressively short-circuit as soon as we know the group condition will fail\n if (operator === 'and') {\n return [];\n }\n // less aggressive short-circuit if we know the relatives will produce no\n // candidate results; but aren't sure yet how this affects the group condition.\n resultGroups.push([]);\n continue;\n }\n if (g.field) {\n // `relatives` are actual relatives. We'll skim them for FK query values.\n // Use the relatives to add candidate result sets (`resultGroups`)\n const relationship = ModelRelationship.from(this.model, g.field);\n if (relationship) {\n const allJoinConditions = [];\n for (const relative of relatives) {\n const relativeConditions = [];\n for (let i = 0; i < relationship.localJoinFields.length; i++) {\n relativeConditions.push({\n [relationship.localJoinFields[i]]: {\n eq: relative[relationship.remoteJoinFields[i]],\n },\n });\n }\n allJoinConditions.push({ and: relativeConditions });\n }\n const predicate = FlatModelPredicateCreator.createFromAST(this.model.schema, {\n or: allJoinConditions,\n });\n resultGroups.push(await storage.query(this.model.builder, predicate));\n }\n else {\n throw new Error('Missing field metadata.');\n }\n }\n else {\n // relatives are not actually relatives. they're candidate results.\n resultGroups.push(relatives);\n }\n }\n // if conditions is empty at this point, child predicates found no matches.\n // i.e., we can stop looking and return empty.\n if (conditions.length > 0) {\n const predicate = this.withFieldConditionsOnly(negateChildren).toStoragePredicate();\n resultGroups.push(await storage.query(this.model.builder, predicate));\n }\n else if (conditions.length === 0 && resultGroups.length === 0) {\n resultGroups.push(await storage.query(this.model.builder));\n }\n // PK might be a single field, like `id`, or it might be several fields.\n // so, we'll need to extract the list of PK fields from an object\n // and stringify the list for easy comparison / merging.\n const getPKValue = item => JSON.stringify(this.model.pkField.map(name => item[name]));\n // will be used for intersecting or unioning results\n let resultIndex;\n if (operator === 'and') {\n if (resultGroups.length === 0) {\n return [];\n }\n // for each group, we intersect, removing items from the result index\n // that aren't present in each subsequent group.\n for (const group of resultGroups) {\n if (resultIndex === undefined) {\n resultIndex = new Map(group.map(item => [getPKValue(item), item]));\n }\n else {\n const intersectWith = new Map(group.map(item => [getPKValue(item), item]));\n for (const k of resultIndex.keys()) {\n if (!intersectWith.has(k)) {\n resultIndex.delete(k);\n }\n }\n }\n }\n }\n else if (operator === 'or' || operator === 'not') {\n // it's OK to handle NOT here, because NOT must always only negate\n // a single child predicate. NOT logic will have been distributed down\n // to the leaf conditions already.\n resultIndex = new Map();\n // just merge the groups, performing DISTINCT-ification by ID.\n for (const group of resultGroups) {\n for (const item of group) {\n resultIndex.set(getPKValue(item), item);\n }\n }\n }\n return Array.from(resultIndex?.values() || []);\n }\n /**\n * Determines whether a single item matches the conditions of `this`.\n * When checking the target `item`'s properties, each property will be `await`'d\n * to ensure lazy-loading is respected where applicable.\n * @param item The item to match against.\n * @param ignoreFieldName Tells `match()` that the field name has already been dereferenced.\n * (Used for iterating over children on HAS_MANY checks.)\n * @returns A boolean (promise): `true` if matched, `false` otherwise.\n */\n async matches(item, ignoreFieldName = false) {\n const itemToCheck = this.field && !ignoreFieldName ? await item[this.field] : item;\n // if there is no item to check, we can stop recursing immediately.\n // a condition cannot match against an item that does not exist. this\n // can occur when `item.field` is optional in the schema.\n if (!itemToCheck) {\n return false;\n }\n if (this.relationshipType === 'HAS_MANY' &&\n typeof itemToCheck[Symbol.asyncIterator] === 'function') {\n for await (const singleItem of itemToCheck) {\n if (await this.matches(singleItem, true)) {\n return true;\n }\n }\n return false;\n }\n if (this.operator === 'or') {\n return asyncSome(this.operands, c => c.matches(itemToCheck));\n }\n else if (this.operator === 'and') {\n return asyncEvery(this.operands, c => c.matches(itemToCheck));\n }\n else if (this.operator === 'not') {\n if (this.operands.length !== 1) {\n throw new Error('Invalid arguments! `not()` accepts exactly one predicate expression.');\n }\n return !(await this.operands[0].matches(itemToCheck));\n }\n else {\n throw new Error('Invalid group operator!');\n }\n }\n /**\n * Tranfsorm to a AppSync GraphQL compatible AST.\n * (Does not support filtering in nested types.)\n */\n toAST() {\n if (this.field)\n throw new Error('Nested type conditions are not supported!');\n return {\n [this.operator]: this.operands.map(operand => operand.toAST()),\n };\n }\n /**\n * Turn this predicate group into something a storage adapter\n * understands how to use.\n */\n toStoragePredicate() {\n return FlatModelPredicateCreator.createFromAST(this.model.schema, this.toAST());\n }\n /**\n * A JSON representation that's good for debugging.\n */\n toJSON() {\n return {\n ...this,\n model: this.model.schema.name,\n };\n }\n}\n/**\n * Creates a \"seed\" predicate that can be used to build an executable condition.\n * This is used in `query()`, for example, to seed customer- E.g.,\n *\n * ```\n * const p = predicateFor({builder: modelConstructor, schema: modelSchema, pkField: string[]});\n * p.and(child => [\n * child.field.eq('whatever'),\n * child.childModel.childField.eq('whatever else'),\n * child.childModel.or(child => [\n * child.otherField.contains('x'),\n * child.otherField.contains('y'),\n * child.otherField.contains('z'),\n * ])\n * ])\n * ```\n *\n * `predicateFor()` returns objecst with recursive getters. To facilitate this,\n * a `query` and `tail` can be provided to \"accumulate\" nested conditions.\n *\n * @param ModelType The ModelMeta used to build child properties.\n * @param field Scopes the query branch to a field.\n * @param query A base query to build on. Omit to start a new query.\n * @param tail The point in an existing `query` to attach new conditions to.\n * @returns A ModelPredicate (builder) that customers can create queries with.\n * (As shown in function description.)\n */\nexport function recursivePredicateFor(ModelType, allowRecursion = true, field, query, tail) {\n // to be used if we don't have a base query or tail to build onto\n const starter = new GroupCondition(ModelType, field, undefined, 'and', []);\n const baseCondition = query && tail ? query : starter;\n const tailCondition = query && tail ? tail : starter;\n // our eventual return object, which can be built upon.\n // next steps will be to add or(), and(), not(), and field.op() methods.\n const link = {};\n // so it can be looked up later with in the internals when processing conditions.\n registerPredicateInternals(baseCondition, link);\n const copyLink = () => {\n const [copiedQuery, newTail] = baseCondition.copy(tailCondition);\n const newLink = recursivePredicateFor(ModelType, allowRecursion, undefined, copiedQuery, newTail);\n return { query: copiedQuery, newTail, newLink };\n };\n // Adds .or() and .and() methods to the link.\n // TODO: If revisiting this code, consider writing a Proxy instead.\n ['and', 'or'].forEach(op => {\n link[op] = (builder) => {\n // or() and and() will return a copy of the original link\n // to head off mutability concerns.\n const { query: copiedLinkQuery, newTail } = copyLink();\n const childConditions = builder(recursivePredicateFor(ModelType, allowRecursion));\n if (!Array.isArray(childConditions)) {\n throw new Error(`Invalid predicate. \\`${op}\\` groups must return an array of child conditions.`);\n }\n // the customer will supply a child predicate, which apply to the `model.field`\n // of the tail GroupCondition.\n newTail?.operands.push(new GroupCondition(ModelType, field, undefined, op, childConditions.map(c => internals(c))));\n // FinalPredicate\n return registerPredicateInternals(copiedLinkQuery);\n };\n });\n // TODO: If revisiting this code, consider proxy.\n link.not = (builder) => {\n // not() will return a copy of the original link\n // to head off mutability concerns.\n const { query: copiedLinkQuery, newTail } = copyLink();\n // unlike and() and or(), the customer will supply a \"singular\" child predicate.\n // the difference being: not() does not accept an array of predicate-like objects.\n // it negates only a *single* predicate subtree.\n newTail?.operands.push(new GroupCondition(ModelType, field, undefined, 'not', [\n internals(builder(recursivePredicateFor(ModelType, allowRecursion))),\n ]));\n // A `FinalModelPredicate`.\n // Return a thing that can no longer be extended, but instead used to `async filter(items)`\n // or query storage: `.__query.fetch(storage)`.\n return registerPredicateInternals(copiedLinkQuery);\n };\n // For each field on the model schema, we want to add a getter\n // that creates the appropriate new `link` in the query chain.\n // TODO: If revisiting, consider a proxy.\n for (const fieldName in ModelType.schema.allFields) {\n Object.defineProperty(link, fieldName, {\n enumerable: true,\n get: () => {\n const def = ModelType.schema.allFields[fieldName];\n if (!def.association) {\n // we're looking at a value field. we need to return a\n // \"field matcher object\", which contains all of the comparison\n // functions ('eq', 'ne', 'gt', etc.), scoped to operate\n // against the target field (fieldName).\n return ops.reduce((fieldMatcher, operator) => {\n return {\n ...fieldMatcher,\n // each operator on the fieldMatcher objcect is a function.\n // when the customer calls the function, it returns a new link\n // in the chain -- for now -- this is the \"leaf\" link that\n // cannot be further extended.\n [operator]: (...operands) => {\n // build off a fresh copy of the existing `link`, just in case\n // the same link is being used elsewhere by the customer.\n const { query: copiedLinkQuery, newTail } = copyLink();\n // normalize operands. if any of the values are `undefiend`, use\n // `null` instead, because that's what will be stored cross-platform.\n const normalizedOperands = operands.map(o => o === undefined ? null : o);\n // add the given condition to the link's TAIL node.\n // remember: the base link might go N nodes deep! e.g.,\n newTail?.operands.push(new FieldCondition(fieldName, operator, normalizedOperands));\n // A `FinalModelPredicate`.\n // Return a thing that can no longer be extended, but instead used to `async filter(items)`\n // or query storage: `.__query.fetch(storage)`.\n return registerPredicateInternals(copiedLinkQuery);\n },\n };\n }, {});\n }\n else {\n if (!allowRecursion) {\n throw new Error('Predication on releated models is not supported in this context.');\n }\n else if (def.association.connectionType === 'BELONGS_TO' ||\n def.association.connectionType === 'HAS_ONE' ||\n def.association.connectionType === 'HAS_MANY') {\n // the use has just typed '.someRelatedModel'. we need to given them\n // back a predicate chain.\n const relatedMeta = def.type.modelConstructor;\n if (!relatedMeta) {\n throw new Error('Related model metadata is missing. This is a bug! Please report it.');\n }\n // `Model.reletedModelField` returns a copy of the original link,\n // and will contains copies of internal GroupConditions\n // to head off mutability concerns.\n const [newquery, oldtail] = baseCondition.copy(tailCondition);\n const newtail = new GroupCondition(relatedMeta, fieldName, def.association.connectionType, 'and', []);\n // `oldtail` here refers to the *copy* of the old tail.\n // so, it's safe to modify at this point. and we need to modify\n // it to push the *new* tail onto the end of it.\n oldtail.operands.push(newtail);\n const newlink = recursivePredicateFor(relatedMeta, allowRecursion, undefined, newquery, newtail);\n return newlink;\n }\n else {\n throw new Error(\"Related model definition doesn't have a typedef. This is a bug! Please report it.\");\n }\n }\n },\n });\n }\n return link;\n}\nexport function predicateFor(ModelType) {\n // the cast here is just a cheap way to reduce the surface area from\n // the recursive type.\n return recursivePredicateFor(ModelType, false);\n}\n"],"names":["FlatModelPredicateCreator"],"mappings":"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