diff --git a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRelationsOptimisticEffect.ts b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRelationsOptimisticEffect.ts index 8b8777d7ce..0ca181b676 100644 --- a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRelationsOptimisticEffect.ts +++ b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRelationsOptimisticEffect.ts @@ -392,6 +392,7 @@ const extractTargetRecordsFromRelation = ( ): RecordGqlNode[] => { // TODO investigate on the root cause of array injection here, should never occurs // Cache might be corrupted somewhere due to ObjectRecord and RecordGqlNode inclusion + if (!isDefined(value) || isArray(value)) { return []; } diff --git a/packages/twenty-front/src/modules/object-record/cache/utils/getFieldMetadataMorphRelationFromGqlField.ts b/packages/twenty-front/src/modules/object-record/cache/utils/getMorphRelationFromFieldMetadataAndGqlField.ts similarity index 69% rename from packages/twenty-front/src/modules/object-record/cache/utils/getFieldMetadataMorphRelationFromGqlField.ts rename to packages/twenty-front/src/modules/object-record/cache/utils/getMorphRelationFromFieldMetadataAndGqlField.ts index 580c4af21e..2eadff760b 100644 --- a/packages/twenty-front/src/modules/object-record/cache/utils/getFieldMetadataMorphRelationFromGqlField.ts +++ b/packages/twenty-front/src/modules/object-record/cache/utils/getMorphRelationFromFieldMetadataAndGqlField.ts @@ -1,10 +1,9 @@ import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; -import { getFieldMetadataItemById } from '@/object-metadata/utils/getFieldMetadataItemById'; import { type FieldMorphRelationMetadata } from '@/object-record/record-field/ui/types/FieldMetadata'; import { computeMorphRelationFieldName } from 'twenty-shared/utils'; -export const getFieldMetadataMorphRelationFromGqlField = ({ +export const getMorphRelationFromFieldMetadataAndGqlField = ({ objectMetadataItems, fieldMetadata, gqlField, @@ -50,25 +49,10 @@ export const getFieldMetadataMorphRelationFromGqlField = ({ return { morphRelation: gqlFieldMorphRelation.morphRelation, - sourceFieldMetadata: getFieldMetadataItemById({ - fieldMetadataId: - gqlFieldMorphRelation.morphRelation.sourceFieldMetadata.id, - objectMetadataItems, - }), - targetFieldMetadata: getFieldMetadataItemById({ - fieldMetadataId: - gqlFieldMorphRelation.morphRelation?.targetFieldMetadata.id, - objectMetadataItems, - }), targetObjectMetadata: objectMetadataItems.find( (objectMetadataItem) => objectMetadataItem.id === - gqlFieldMorphRelation.morphRelation?.targetObjectMetadata.id, - ), - sourceObjectMetadata: objectMetadataItems.find( - (objectMetadataItem) => - objectMetadataItem.id === - gqlFieldMorphRelation.morphRelation?.sourceObjectMetadata.id, + gqlFieldMorphRelation.morphRelation.targetObjectMetadata.id, ), }; }; diff --git a/packages/twenty-front/src/modules/object-record/cache/utils/getRecordNodeFromRecord.ts b/packages/twenty-front/src/modules/object-record/cache/utils/getRecordNodeFromRecord.ts index 0a3a9969ac..00d590ddc4 100644 --- a/packages/twenty-front/src/modules/object-record/cache/utils/getRecordNodeFromRecord.ts +++ b/packages/twenty-front/src/modules/object-record/cache/utils/getRecordNodeFromRecord.ts @@ -1,7 +1,9 @@ import { isNull, isUndefined } from '@sniptt/guards'; import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; +import { computePossibleMorphGqlFieldForFieldName } from '@/object-record/cache/utils/computePossibleMorphGqlFieldForFieldName'; import { getFieldMetadataFromGqlField } from '@/object-record/cache/utils/getFieldMetadataFromGqlField'; +import { getMorphRelationFromFieldMetadataAndGqlField } from '@/object-record/cache/utils/getMorphRelationFromFieldMetadataAndGqlField'; import { getNodeTypename } from '@/object-record/cache/utils/getNodeTypename'; import { getObjectTypename } from '@/object-record/cache/utils/getObjectTypename'; import { getRecordConnectionFromRecords } from '@/object-record/cache/utils/getRecordConnectionFromRecords'; @@ -44,14 +46,14 @@ export const getRecordNodeFromRecord = ({ const nestedRecord = Object.fromEntries( Object.entries(record) - .map(([fieldName, value]) => { - if (isDefined(recordGqlFields) && !recordGqlFields[fieldName]) { + .map(([gqlField, value]) => { + if (isDefined(recordGqlFields) && !recordGqlFields[gqlField]) { return undefined; } const field = getFieldMetadataFromGqlField({ objectMetadataItem, - gqlField: fieldName, + gqlField: gqlField, }); if (isUndefined(field)) { @@ -73,16 +75,56 @@ export const getRecordNodeFromRecord = ({ } return [ - fieldName, + gqlField, getRecordConnectionFromRecords({ objectMetadataItems, objectMetadataItem: oneToManyObjectMetadataItem, records: value as ObjectRecord[], recordGqlFields: - recordGqlFields?.[fieldName] === true || - isUndefined(recordGqlFields?.[fieldName]) + recordGqlFields?.[gqlField] === true || + isUndefined(recordGqlFields?.[gqlField]) ? undefined - : recordGqlFields?.[fieldName], + : recordGqlFields?.[gqlField], + withPageInfo: false, + isRootLevel: false, + computeReferences, + }), + ]; + } + + if ( + field.type === FieldMetadataType.MORPH_RELATION && + field.settings?.relationType === RelationType.ONE_TO_MANY + ) { + if (field.morphRelations?.length === 0) { + return undefined; + } + + const morphRelation = getMorphRelationFromFieldMetadataAndGqlField({ + objectMetadataItems, + fieldMetadata: { morphRelations: field.morphRelations ?? [] }, + gqlField: gqlField, + }); + + if (isUndefined(morphRelation?.targetObjectMetadata?.nameSingular)) { + return undefined; + } + + if (!morphRelation?.targetObjectMetadata?.nameSingular) { + return undefined; + } + + return [ + gqlField, + getRecordConnectionFromRecords({ + objectMetadataItems, + objectMetadataItem: morphRelation?.targetObjectMetadata, + records: value as ObjectRecord[], + recordGqlFields: + recordGqlFields?.[gqlField] === true || + isUndefined(recordGqlFields?.[gqlField]) + ? undefined + : recordGqlFields?.[gqlField], withPageInfo: false, isRootLevel: false, computeReferences, @@ -92,10 +134,9 @@ export const getRecordNodeFromRecord = ({ switch (field.type) { case FieldMetadataType.RELATION: { - const isJoinColumn = field.settings?.joinColumnName === fieldName; - + const isJoinColumn = field.settings?.joinColumnName === gqlField; if (isJoinColumn) { - return [fieldName, value]; + return [gqlField, value]; } if ( @@ -105,7 +146,7 @@ export const getRecordNodeFromRecord = ({ } if (isNull(value)) { - return [fieldName, null]; + return [gqlField, null]; } if (isUndefined(value?.id)) { @@ -118,7 +159,7 @@ export const getRecordNodeFromRecord = ({ if (computeReferences) { return [ - fieldName, + gqlField, { __ref: `${typeName}:${value.id}`, }, @@ -126,7 +167,64 @@ export const getRecordNodeFromRecord = ({ } return [ - fieldName, + gqlField, + { + __typename: typeName, + ...value, + }, + ]; + } + case FieldMetadataType.MORPH_RELATION: { + const possibleMorphRelationsJoinColumnNames = + computePossibleMorphGqlFieldForFieldName({ + fieldMetadata: { + morphRelations: field.morphRelations ?? [], + fieldName: field.name, + }, + }).map( + (possibleMorphRelationName) => `${possibleMorphRelationName}Id`, + ); + + const isJoinColumn = + possibleMorphRelationsJoinColumnNames.includes(gqlField); + if (isJoinColumn) { + return [gqlField, value]; + } + + if (field.morphRelations?.length === 0) { + return undefined; + } + + const morphRelation = getMorphRelationFromFieldMetadataAndGqlField({ + objectMetadataItems, + fieldMetadata: { morphRelations: field.morphRelations ?? [] }, + gqlField: gqlField, + }); + + if ( + isUndefined(morphRelation?.targetObjectMetadata?.nameSingular) + ) { + return undefined; + } + + const typeName = getObjectTypename( + morphRelation?.targetObjectMetadata?.nameSingular, + ); + + if (isNull(value)) { + return [gqlField, null]; + } + + if (isUndefined(value?.id)) { + return undefined; + } + + if (computeReferences) { + return [gqlField, { __ref: `${typeName}:${value.id}` }]; + } + + return [ + gqlField, { __typename: typeName, ...value, @@ -138,7 +236,7 @@ export const getRecordNodeFromRecord = ({ case FieldMetadataType.FULL_NAME: case FieldMetadataType.CURRENCY: { return [ - fieldName, + gqlField, { ...value, __typename: pascalCase(field.type), @@ -146,7 +244,7 @@ export const getRecordNodeFromRecord = ({ ]; } default: { - return [fieldName, value]; + return [gqlField, value]; } } }) diff --git a/packages/twenty-front/src/modules/object-record/hooks/useUpdateOneRecordV2.ts b/packages/twenty-front/src/modules/object-record/hooks/useUpdateOneRecordV2.ts index a001e27b5f..c49981b105 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useUpdateOneRecordV2.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useUpdateOneRecordV2.ts @@ -5,6 +5,7 @@ import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadat import { generateUpdateOneRecordMutation } from '@/object-metadata/utils/generateUpdateOneRecordMutation'; import { getObjectTypename } from '@/object-record/cache/utils/getObjectTypename'; import { getRecordFromCache } from '@/object-record/cache/utils/getRecordFromCache'; +import { getRecordFromRecordNode } from '@/object-record/cache/utils/getRecordFromRecordNode'; import { getRecordNodeFromRecord } from '@/object-record/cache/utils/getRecordNodeFromRecord'; import { updateRecordFromCache } from '@/object-record/cache/utils/updateRecordFromCache'; import { type RecordGqlFields } from '@/object-record/graphql/record-gql-fields/types/RecordGqlFields'; @@ -171,6 +172,11 @@ export const useUpdateOneRecordV2 = () => { const record = data?.[mutationResponseField]; if (!isDefined(record)) return; + const recordToUpsert = getRecordFromRecordNode({ + recordNode: record, + }); + upsertRecordsInStore([recordToUpsert]); + triggerUpdateRecordOptimisticEffect({ cache, objectMetadataItem, diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/hooks/usePersistField.ts b/packages/twenty-front/src/modules/object-record/record-field/ui/hooks/usePersistField.ts index 7bb3dfbb41..440c2cc24d 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/ui/hooks/usePersistField.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/ui/hooks/usePersistField.ts @@ -26,16 +26,11 @@ import { isFieldSelect } from '@/object-record/record-field/ui/types/guards/isFi import { isFieldSelectValue } from '@/object-record/record-field/ui/types/guards/isFieldSelectValue'; import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector'; -import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient'; import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById'; -import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems'; -import { getRecordFromCache } from '@/object-record/cache/utils/getRecordFromCache'; import { getRecordFromRecordNode } from '@/object-record/cache/utils/getRecordFromRecordNode'; -import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions'; import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { isFieldArray } from '@/object-record/record-field/ui/types/guards/isFieldArray'; import { isFieldArrayValue } from '@/object-record/record-field/ui/types/guards/isFieldArrayValue'; -import { isFieldMorphRelation } from '@/object-record/record-field/ui/types/guards/isFieldMorphRelation'; import { isFieldMorphRelationManyToOne } from '@/object-record/record-field/ui/types/guards/isFieldMorphRelationManyToOne'; import { isFieldRelationManyToOne } from '@/object-record/record-field/ui/types/guards/isFieldRelationManyToOne'; import { isFieldRelationManyToOneValue } from '@/object-record/record-field/ui/types/guards/isFieldRelationManyToOneValue'; @@ -45,7 +40,6 @@ import { isFieldRichTextValue } from '@/object-record/record-field/ui/types/guar import { isFieldRichTextV2Value } from '@/object-record/record-field/ui/types/guards/isFieldRichTextValueV2'; import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore'; import { getForeignKeyNameFromRelationFieldName } from '@/object-record/utils/getForeignKeyNameFromRelationFieldName'; -import { computeMorphRelationFieldName, isDefined } from 'twenty-shared/utils'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; import { isFieldBoolean } from '../types/guards/isFieldBoolean'; import { isFieldBooleanValue } from '../types/guards/isFieldBooleanValue'; @@ -65,18 +59,15 @@ export const usePersistField = ({ }: { objectMetadataItemId: string; }) => { - const apolloCoreClient = useApolloCoreClient(); const { objectMetadataItem } = useObjectMetadataItemById({ objectId: objectMetadataItemId, }); - const { objectMetadataItems } = useObjectMetadataItems(); const { updateOneRecord } = useUpdateOneRecord({ objectNameSingular: objectMetadataItem?.nameSingular ?? '', }); const { upsertRecordsInStore } = useUpsertRecordsInStore(); - const { objectPermissionsByObjectMetadataId } = useObjectPermissions(); const persistField = useRecoilCallback( ({ set, snapshot }) => @@ -222,68 +213,6 @@ export const usePersistField = ({ return; } - if (fieldIsMorphRelationManyToOne) { - if (isFieldMorphRelation(fieldDefinition)) { - // TODO: this is hack, we should refactor the SingleRecordPicker to pass the updated object - const objectNameSingulars = - fieldDefinition.metadata.morphRelations.map( - (morphRelation) => - morphRelation.targetObjectMetadata.nameSingular, - ); - - if (!isDefined(valueToPersist?.id)) { - // Handle detach - return; - } - - for (const objectNameSingular of objectNameSingulars) { - const candidateObjectMetadataItem = objectMetadataItems.find( - (objectMetadataItem) => - objectMetadataItem.nameSingular === objectNameSingular, - ); - - if (!isDefined(candidateObjectMetadataItem)) { - throw new Error( - `Object metadata item not found for ${objectNameSingular}`, - ); - } - - const cachedRecord = getRecordFromCache({ - cache: apolloCoreClient.cache, - objectMetadataItem: candidateObjectMetadataItem, - objectMetadataItems, - recordId: valueToPersist.id, - objectPermissionsByObjectMetadataId, - }); - - if (!isDefined(cachedRecord)) { - continue; - } - - const computedFieldName = computeMorphRelationFieldName({ - fieldName, - relationType: fieldDefinition.metadata.relationType, - targetObjectMetadataNameSingular: objectNameSingular, - targetObjectMetadataNamePlural: - candidateObjectMetadataItem.namePlural, - }); - - const newRecord = await updateOneRecord?.({ - idToUpdate: recordId, - updateOneRecordInput: { - [`${computedFieldName}Id`]: valueToPersist.id, - }, - }); - upsertRecordsInStore([ - getRecordFromRecordNode({ - recordNode: newRecord, - }), - ]); - return; - } - } - } - if (isDeeplyEqual(valueToPersist, currentValue)) { return; } @@ -308,13 +237,7 @@ export const usePersistField = ({ ); } }, - [ - apolloCoreClient.cache, - objectMetadataItems, - objectPermissionsByObjectMetadataId, - updateOneRecord, - upsertRecordsInStore, - ], + [updateOneRecord, upsertRecordsInStore], ); return persistField; diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/input/hooks/useMorphPersistManyToOne.ts b/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/input/hooks/useMorphPersistManyToOne.ts index 61c35d923c..139d91a6f6 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/input/hooks/useMorphPersistManyToOne.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/input/hooks/useMorphPersistManyToOne.ts @@ -5,7 +5,8 @@ import { type FieldMetadata } from '@/object-record/record-field/ui/types/FieldM import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector'; import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems'; -import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; + +import { useUpdateOneRecordV2 } from '@/object-record/hooks/useUpdateOneRecordV2'; import { assertFieldMetadata } from '@/object-record/record-field/ui/types/guards/assertFieldMetadata'; import { isFieldMorphRelation } from '@/object-record/record-field/ui/types/guards/isFieldMorphRelation'; import { type ObjectRecord } from '@/object-record/types/ObjectRecord'; @@ -21,12 +22,10 @@ export const useMorphPersistManyToOne = ({ }: MorphPersistManyToOneProps) => { const { objectMetadataItems } = useObjectMetadataItems(); - const { updateOneRecord } = useUpdateOneRecord({ - objectNameSingular: objectMetadataNameSingular, - }); + const { updateOneRecord } = useUpdateOneRecordV2(); const persistMorphManyToOne = useRecoilCallback( - ({ set, snapshot }) => + ({ snapshot }) => async ({ recordId, fieldDefinition, @@ -84,22 +83,35 @@ export const useMorphPersistManyToOne = ({ return; } + const allNullRecordInput: Record = + fieldDefinition.metadata.morphRelations.reduce( + (acc, morphRelation) => { + const computedFieldName = computeMorphRelationFieldName({ + fieldName, + relationType: fieldDefinition.metadata.relationType, + targetObjectMetadataNameSingular: + morphRelation.targetObjectMetadata.nameSingular, + targetObjectMetadataNamePlural: + morphRelation.targetObjectMetadata.namePlural, + }); + acc[`${computedFieldName}Id`] = null; + return acc; + }, + {} as Record, + ); + updateOneRecord?.({ + objectNameSingular: objectMetadataNameSingular, idToUpdate: recordId, updateOneRecordInput: { + ...allNullRecordInput, [`${computedFieldName}Id`]: valueToPersist, }, }); - set( - recordStoreFamilySelector({ - recordId, - fieldName: computedFieldName, - }), - valueToPersist, - ); + return; }, - [updateOneRecord, objectMetadataItems], + [updateOneRecord, objectMetadataItems, objectMetadataNameSingular], ); return { persistMorphManyToOne }; diff --git a/packages/twenty-front/src/modules/object-record/utils/computeOptimisticRecordFromInput.ts b/packages/twenty-front/src/modules/object-record/utils/computeOptimisticRecordFromInput.ts index 4a53eb20d8..e27c4ce0a8 100644 --- a/packages/twenty-front/src/modules/object-record/utils/computeOptimisticRecordFromInput.ts +++ b/packages/twenty-front/src/modules/object-record/utils/computeOptimisticRecordFromInput.ts @@ -3,7 +3,7 @@ import { isNull, isUndefined } from '@sniptt/guards'; import { type CurrentWorkspaceMember } from '@/auth/states/currentWorkspaceMemberState'; import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { getFieldMetadataFromGqlField } from '@/object-record/cache/utils/getFieldMetadataFromGqlField'; -import { getFieldMetadataMorphRelationFromGqlField } from '@/object-record/cache/utils/getFieldMetadataMorphRelationFromGqlField'; +import { getMorphRelationFromFieldMetadataAndGqlField } from '@/object-record/cache/utils/getMorphRelationFromFieldMetadataAndGqlField'; import { getRecordFromCache, type GetRecordFromCacheArgs, @@ -146,19 +146,19 @@ export const computeOptimisticRecordFromInput = ({ ); } - const relationFieldIdName = getForeignKeyNameFromRelationFieldName( + const relationGqlFieldWithId = getForeignKeyNameFromRelationFieldName( fieldMetadataItem.name, ); const recordInputFieldIdValue: string | null | undefined = - recordInput[relationFieldIdName]; + recordInput[relationGqlFieldWithId]; if (isUndefined(recordInputFieldIdValue)) { continue; } if (isNull(recordInputFieldIdValue)) { - optimisticRecord[relationFieldIdName] = null; + optimisticRecord[relationGqlFieldWithId] = null; optimisticRecord[fieldMetadataItem.name] = null; continue; } @@ -182,7 +182,7 @@ export const computeOptimisticRecordFromInput = ({ objectPermissionsByObjectMetadataId, }); - optimisticRecord[relationFieldIdName] = recordInputFieldIdValue; + optimisticRecord[relationGqlFieldWithId] = recordInputFieldIdValue; if (!isDefined(cachedRecord) || Object.keys(cachedRecord).length <= 0) { continue; @@ -208,7 +208,7 @@ export const computeOptimisticRecordFromInput = ({ ); } - const relationFieldIdNames = fieldMetadataItem.morphRelations?.map( + const relationGqlFields = fieldMetadataItem.morphRelations?.map( (morphRelation) => { return computeMorphRelationFieldName({ fieldName: fieldMetadataItem.name, @@ -221,39 +221,25 @@ export const computeOptimisticRecordFromInput = ({ }, ); - const relationFieldName = relationFieldIdNames?.find( - (relationFieldIdName) => recordInput[`${relationFieldIdName}Id`], + const relationGqlField = relationGqlFields?.find( + (relationGqlField) => recordInput[`${relationGqlField}Id`], ); - const relationFieldIdName = `${relationFieldName}Id`; + const relationGqlFieldWithId = `${relationGqlField}Id`; - if (isUndefined(relationFieldName)) { + if (isUndefined(relationGqlField)) { continue; } const recordInputFieldIdValue: string | null | undefined = - recordInput[relationFieldIdName]; + recordInput[relationGqlFieldWithId]; if (isUndefined(recordInputFieldIdValue)) { continue; } - const relationIdFieldMetadataItem = getFieldMetadataFromGqlField({ - objectMetadataItem, - gqlField: relationFieldName, - }); - - if ( - !isDefined(relationIdFieldMetadataItem) && - !isDefined(fieldMetadataItem.settings?.joinColumnName) - ) { - throw new Error( - 'Should never occur, encountered unknown relationId within relations definitions', - ); - } - if (isNull(recordInputFieldIdValue)) { - optimisticRecord[relationFieldName] = null; + optimisticRecord[relationGqlField] = null; optimisticRecord[fieldMetadataItem.name] = null; continue; } @@ -265,10 +251,10 @@ export const computeOptimisticRecordFromInput = ({ } const fieldMetadataMorphRelation = - getFieldMetadataMorphRelationFromGqlField({ + getMorphRelationFromFieldMetadataAndGqlField({ objectMetadataItems, fieldMetadata: { morphRelations: fieldMetadataItem.morphRelations }, - gqlField: relationFieldName, + gqlField: relationGqlField, }); if (!isDefined(fieldMetadataMorphRelation?.targetObjectMetadata)) { @@ -285,13 +271,13 @@ export const computeOptimisticRecordFromInput = ({ objectPermissionsByObjectMetadataId, }); - optimisticRecord[relationFieldIdName] = recordInputFieldIdValue; + optimisticRecord[relationGqlFieldWithId] = recordInputFieldIdValue; if (!isDefined(cachedRecord) || Object.keys(cachedRecord).length <= 0) { continue; } - optimisticRecord[relationFieldName] = cachedRecord; + optimisticRecord[relationGqlField] = cachedRecord; } }