UNPKG

@commitspark/graphql-api

Version:

GraphQL API to store and manage structured data with Git

120 lines (110 loc) 3.35 kB
import { findById, findByTypeId } from '../../../persistence/persistence' import { getReferencedEntryIds } from '../../schema-utils/entry-reference-util' import { GraphQLFieldResolver, isObjectType } from 'graphql' import { EntryData, EntryDraft } from '@commitspark/git-adapter' import { QueryMutationResolverContext } from '../types' import { createError, ErrorCode } from '../../errors' function mergeData( existingEntryData: EntryData, updateData: EntryData, ): EntryData { return { ...existingEntryData, ...updateData, } } export const mutationUpdateResolver: GraphQLFieldResolver< any, QueryMutationResolverContext, any, Promise<EntryData> > = async (source, args, context, info) => { if (!isObjectType(context.type)) { throw createError( `Type "${context.type.name}" cannot be mutated as is not an ObjectType.`, ErrorCode.INTERNAL_ERROR, {}, ) } const existingEntry = await findByTypeId( context.gitAdapter, context.getCurrentRef(), context.type.name, args.id, ) const existingReferencedEntryIds = await getReferencedEntryIds( context.type, context, null, info.returnType, existingEntry.data, ) const mergedData = mergeData(existingEntry.data ?? null, args.data) const updatedReferencedEntryIds = await getReferencedEntryIds( context.type, context, null, info.returnType, mergedData, ) const noLongerReferencedIds = existingReferencedEntryIds.filter( (entryId) => !updatedReferencedEntryIds.includes(entryId), ) const newlyReferencedIds = updatedReferencedEntryIds.filter( (entryId) => !existingReferencedEntryIds.includes(entryId), ) const referencedEntryUpdates: EntryDraft[] = [] for (const noLongerReferencedEntryId of noLongerReferencedIds) { const noLongerReferencedEntry = await findById( context.gitAdapter, context.getCurrentRef(), noLongerReferencedEntryId, ) referencedEntryUpdates.push({ ...noLongerReferencedEntry, metadata: { ...noLongerReferencedEntry.metadata, referencedBy: noLongerReferencedEntry.metadata.referencedBy?.filter( (entryId) => entryId !== args.id, ), }, deletion: false, }) } for (const newlyReferencedEntryId of newlyReferencedIds) { const newlyReferencedEntry = await findById( context.gitAdapter, context.getCurrentRef(), newlyReferencedEntryId, ) const updatedReferenceList: string[] = newlyReferencedEntry.metadata.referencedBy ?? [] updatedReferenceList.push(args.id) updatedReferenceList.sort() referencedEntryUpdates.push({ ...newlyReferencedEntry, metadata: { ...newlyReferencedEntry.metadata, referencedBy: updatedReferenceList, }, deletion: false, }) } const commit = await context.gitAdapter.createCommit({ ref: context.branch, parentSha: context.getCurrentRef(), entries: [ { ...existingEntry, data: mergedData, deletion: false }, ...referencedEntryUpdates, ], message: args.commitMessage, }) context.setCurrentRef(commit.ref) const updatedEntry = await findByTypeId( context.gitAdapter, context.getCurrentRef(), context.type.name, args.id, ) return { ...updatedEntry.data, id: updatedEntry.id } }