UNPKG

@aws-amplify/datastore

Version:

AppSyncLocal support for aws-amplify

1 lines 14.4 kB
{"version":3,"file":"relationship.mjs","sources":["../../../src/storage/relationship.ts"],"sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport { isFieldAssociation } from '../types';\n/**\n * Defines a relationship from a LOCAL model.field to a REMOTE model.field and helps\n * navigate the relationship, providing a simplified peek at the relationship details\n * pertinent to setting FK's and constructing join conditions.\n *\n * Because I mean, relationships are tough.\n *\n */\nexport class ModelRelationship {\n /**\n * @param modelDefinition The \"local\" model.\n * @param field The \"local\" model field.\n */\n constructor(model, field) {\n if (!isFieldAssociation(model.schema, field)) {\n throw new Error(`${model.schema.name}.${field} is not a relationship.`);\n }\n this.localModel = model;\n this._field = field;\n }\n /**\n * Returns a ModelRelationship for the the given model and field if the pair\n * indicates a relationship to another model. Else, returns `null`.\n *\n * @param model The model the relationship field exists in.\n * @param field The field that may relates the local model to the remote model.\n */\n static from(model, field) {\n if (isFieldAssociation(model.schema, field)) {\n return new this(model, field);\n }\n else {\n return null;\n }\n }\n /**\n * Enumerates all valid `ModelRelationship`'s on the given model.\n *\n * @param model The model definition to enumerate relationships of.\n */\n static allFrom(model) {\n const relationships = [];\n for (const field of Object.keys(model.schema.fields)) {\n const relationship = ModelRelationship.from(model, field);\n relationship && relationships.push(relationship);\n }\n return relationships;\n }\n get localDefinition() {\n return this.localModel.schema;\n }\n /**\n * The virtual/computed field on the local model that should contain\n * the related model.\n */\n get field() {\n return this._field;\n }\n /**\n * The constructor that can be used to query DataStore or create instance for\n * the local model.\n */\n get localConstructor() {\n return this.localModel.builder;\n }\n /**\n * The name/type of the relationship the local model has with the remote model\n * via the defined local model field.\n */\n get type() {\n return this.localAssocation.connectionType;\n }\n /**\n * Raw details about the local FK as-is from the local model's field definition in\n * the schema. This field requires interpretation.\n *\n * @see localJoinFields\n * @see localAssociatedWith\n */\n get localAssocation() {\n return this.localDefinition.fields[this.field].association;\n }\n /**\n * The field names on the local model that can be used to query or queried to match\n * with instances of the remote model.\n *\n * Fields are returned in-order to match the order of `this.remoteKeyFields`.\n */\n get localJoinFields() {\n /**\n * This is relatively straightforward, actually.\n *\n * If we have explicitly stated targetNames, codegen is telling us authoritatively\n * to use those fields for this relationship. The local model \"points to\" fields\n * in the remote one.\n *\n * In other cases, the remote model points to this one's\n */\n if (this.localAssocation.targetName) {\n // This case is theoretically unnecessary going forward.\n return [this.localAssocation.targetName];\n }\n else if (this.localAssocation.targetNames) {\n return this.localAssocation.targetNames;\n }\n else {\n return this.localPKFields;\n }\n }\n /**\n * The field names on the local model that uniquely identify it.\n *\n * These fields may or may not be relevant to the join fields.\n */\n get localPKFields() {\n return this.localModel.pkField;\n }\n get remoteDefinition() {\n return this.remoteModelType.modelConstructor?.schema;\n }\n get remoteModelType() {\n return this.localDefinition.fields[this.field].type;\n }\n /**\n * Constructor that can be used to query DataStore or create instances for\n * the remote model.\n */\n get remoteModelConstructor() {\n return this.remoteModelType.modelConstructor.builder;\n }\n /**\n * The field names on the remote model that uniquely identify it.\n *\n * These fields may or may not be relevant to the join fields.\n */\n get remotePKFields() {\n return this.remoteModelType.modelConstructor?.pkField || ['id'];\n }\n /**\n * The `associatedWith` fields from the local perspective.\n *\n * When present, these fields indicate which fields on the remote model to use\n * when looking for a remote association and/or determining the final remote\n * key fields.\n */\n get localAssociatedWith() {\n if (this.localAssocation.connectionType === 'HAS_MANY' ||\n this.localAssocation.connectionType === 'HAS_ONE') {\n // This de-arraying is theoretically unnecessary going forward.\n return Array.isArray(this.localAssocation.associatedWith)\n ? this.localAssocation.associatedWith\n : [this.localAssocation.associatedWith];\n }\n else {\n return undefined;\n }\n }\n /**\n * The `remote` model's associated field's `assocation` metadata, if\n * present.\n *\n * This is used when determining if the remote model's associated field\n * specifies which FK fields to use. If this value is `undefined`, the\n * name of the remote field (`this.localAssociatedWith`) *is* the remote\n * key field.\n */\n get explicitRemoteAssociation() {\n if (this.localAssociatedWith) {\n if (this.localAssociatedWith.length === 1) {\n return this.remoteDefinition.fields[this.localAssociatedWith[0]]\n ?.association;\n }\n else {\n return undefined;\n }\n }\n }\n /**\n * The field names on the remote model that can used to query or queried to match\n * with instances of the local model.\n *\n * Fields are returned in-order to match the order of `this.localKeyFields`.\n */\n get remoteJoinFields() {\n /**\n * If the local relationship explicitly names \"associated with\" fields, we\n * need to see if this points direction to a reciprocating assocation. If it\n * does, the remote assocation indicates what fields to use.\n */\n if (this.explicitRemoteAssociation?.targetName) {\n // This case is theoretically unnecessary going forward.\n return [this.explicitRemoteAssociation.targetName];\n }\n else if (this.explicitRemoteAssociation?.targetNames) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain\n return this.explicitRemoteAssociation?.targetNames;\n }\n else if (this.localAssociatedWith) {\n return this.localAssociatedWith;\n }\n else {\n return this.remotePKFields;\n }\n }\n /**\n * Whether this relationship everything necessary to get, set, and query from\n * the perspective of the local model provided at instantiation.\n */\n get isComplete() {\n return this.localJoinFields.length > 0 && this.remoteJoinFields.length > 0;\n }\n /**\n * Creates an FK mapper object with respect to the given related instance.\n *\n * E.g., if the local FK fields are `[parentId, parentName]` and point to\n * `[customId, name]` on the remote model, `createLocalFKObject(remote)`\n * will return:\n *\n * ```\n * {\n * \tparentId: remote.customId,\n * \tparentName: remote.name\n * }\n * ```\n *\n * @param remote The remote related instance.\n */\n createLocalFKObject(remote) {\n const fk = {};\n for (let i = 0; i < this.localJoinFields.length; i++) {\n fk[this.localJoinFields[i]] = remote[this.remoteJoinFields[i]];\n }\n return fk;\n }\n /**\n * Creates an query mapper object to help fetch the remote instance(s) or\n * `null` if any of the necessary local fields are `null` or `undefined`.\n *\n * E.g., if the local FK fields are `[parentId, parentName]` and point to\n * `[customId, name]` on the remote model, `createLocalFKObject(remote)`\n * will return:\n *\n * ```\n * {\n * \tcustomId: local.parentId\n * \tname: local.parentName\n * }\n * ```\n *\n * If the local fields are not populated, returns\n *\n * @param local The local instance.\n */\n createRemoteQueryObject(local) {\n const query = {};\n for (let i = 0; i < this.remoteJoinFields.length; i++) {\n const localValue = local[this.localJoinFields[i]];\n if (localValue === null || localValue === undefined)\n return null;\n query[this.remoteJoinFields[i]] = local[this.localJoinFields[i]];\n }\n return query;\n }\n}\n"],"names":[],"mappings":"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"}