@commitspark/graphql-api
Version:
GraphQL API to store and manage structured data with Git
117 lines (108 loc) • 2.94 kB
text/typescript
import { findById, findByTypeId } from '../../../persistence/persistence'
import { GraphQLFieldResolver, isObjectType } from 'graphql'
import { getReferencedEntryIds } from '../../schema-utils/entry-reference-util'
import {
ENTRY_ID_INVALID_CHARACTERS,
EntryData,
EntryDraft,
} from '@commitspark/git-adapter'
import { QueryMutationResolverContext } from '../types'
import { createError, ErrorCode } from '../../errors'
export const mutationCreateResolver: GraphQLFieldResolver<
any,
QueryMutationResolverContext,
any,
Promise<EntryData>
> = async (source, args, context, info) => {
if (!isObjectType(context.type)) {
throw createError(
`Entry of type "${context.type.name}" cannot be created as is not an ObjectType.`,
ErrorCode.INTERNAL_ERROR,
{},
)
}
const idValidationResult = args.id.match(ENTRY_ID_INVALID_CHARACTERS)
if (idValidationResult) {
throw createError(
`Field "id" contains invalid characters "${idValidationResult.join(
', ',
)}".`,
ErrorCode.BAD_USER_INPUT,
{
argumentName: 'id',
argumentValue: args.id,
},
)
}
let existingEntry
try {
existingEntry = await findById(
context.gitAdapter,
context.getCurrentRef(),
args.id,
)
} catch (_) {
/* empty */
}
if (existingEntry) {
throw createError(
`An entry with id "${args.id}" already exists.`,
ErrorCode.BAD_USER_INPUT,
{
argumentName: 'id',
argumentValue: args.id,
},
)
}
const referencedEntryIds = await getReferencedEntryIds(
context.type,
context,
null,
info.returnType,
args.data,
)
const referencedEntryUpdates: EntryDraft[] = []
for (const referencedEntryId of referencedEntryIds) {
const referencedEntry = await findById(
context.gitAdapter,
context.getCurrentRef(),
referencedEntryId,
)
const newReferencedEntryIds: string[] = [
...(referencedEntry.metadata.referencedBy ?? []),
args.id,
].sort()
const newReferencedEntryDraft: EntryDraft = {
...referencedEntry,
metadata: {
...referencedEntry.metadata,
referencedBy: newReferencedEntryIds,
},
deletion: false,
}
referencedEntryUpdates.push(newReferencedEntryDraft)
}
const newEntryDraft: EntryDraft = {
id: args.id,
metadata: {
type: context.type.name,
referencedBy: [],
},
data: args.data,
deletion: false,
}
const commit = await context.gitAdapter.createCommit({
ref: context.branch,
parentSha: context.getCurrentRef(),
entries: [newEntryDraft, ...referencedEntryUpdates],
message: args.commitMessage,
})
context.setCurrentRef(commit.ref)
const newEntry = await findByTypeId(
context.gitAdapter,
context.getCurrentRef(),
context.type.name,
args.id,
)
return { ...newEntry.data, id: newEntry.id }
}