* Recursively save/update all nested related o2m items
( data: Partial<Item>, parent: PrimaryKey, opts?: MutationOptions, )
| 763 | * Recursively save/update all nested related o2m items |
| 764 | */ |
| 765 | async processO2M( |
| 766 | data: Partial<Item>, |
| 767 | parent: PrimaryKey, |
| 768 | opts?: MutationOptions, |
| 769 | ): Promise<PayloadServiceProcessRelationResult> { |
| 770 | const revisions: PrimaryKey[] = []; |
| 771 | let userIntegrityCheckFlags = UserIntegrityCheckFlag.None; |
| 772 | |
| 773 | const nestedActionEvents: ActionEventParams[] = []; |
| 774 | |
| 775 | const relations = this.schema.relations.filter((relation) => { |
| 776 | return relation.related_collection === this.collection; |
| 777 | }); |
| 778 | |
| 779 | const payload = cloneDeep(data); |
| 780 | |
| 781 | // Only process related records that are actually in the payload |
| 782 | const relationsToProcess = relations.filter((relation) => { |
| 783 | if (!relation.meta?.one_field) return false; |
| 784 | return relation.meta.one_field in payload; |
| 785 | }); |
| 786 | |
| 787 | const nestedUpdateSchema = Joi.object({ |
| 788 | create: Joi.array().items(Joi.object().unknown()), |
| 789 | update: Joi.array().items(Joi.object().unknown()), |
| 790 | delete: Joi.array().items(Joi.string(), Joi.number()), |
| 791 | }); |
| 792 | |
| 793 | for (const relation of relationsToProcess) { |
| 794 | if (!relation.meta) continue; |
| 795 | |
| 796 | const currentPrimaryKeyField = this.schema.collections[relation.related_collection!]!.primary; |
| 797 | const relatedPrimaryKeyField = this.schema.collections[relation.collection]!.primary; |
| 798 | |
| 799 | const { getService } = await import('../utils/get-service.js'); |
| 800 | |
| 801 | const service = getService(relation.collection, { |
| 802 | accountability: this.accountability, |
| 803 | knex: this.knex, |
| 804 | schema: this.schema, |
| 805 | nested: [...this.nested, relation.meta!.one_field!], |
| 806 | }); |
| 807 | |
| 808 | const recordsToUpsert: Partial<Item>[] = []; |
| 809 | const savedPrimaryKeys: PrimaryKey[] = []; |
| 810 | |
| 811 | // Nested array of individual items |
| 812 | const field = payload[relation.meta!.one_field!]; |
| 813 | |
| 814 | if (!field || Array.isArray(field)) { |
| 815 | const updates = field || []; // treat falsey values as removing all children |
| 816 | |
| 817 | for (let i = 0; i < updates.length; i++) { |
| 818 | const currentId = parent || payload[currentPrimaryKeyField]; |
| 819 | const relatedRecord = updates[i]; |
| 820 | |
| 821 | const relatedId = |
| 822 | typeof relatedRecord === 'string' || typeof relatedRecord === 'number' |
no test coverage detected