@graphql-inspector/patch
Version:
Applies changes output from @graphql-inspect/diff
110 lines (109 loc) • 4.43 kB
JavaScript
import { Kind } from 'graphql';
import { ChangeType } from '@graphql-inspector/core';
import { ChangedCoordinateKindMismatchError, ChangedCoordinateNotFoundError, ChangePathMissingError, DeletedCoordinateNotFound, ValueMismatchError, } from './errors.js';
export function findNamedNode(nodes, name) {
return nodes?.find(value => value.name.value === name);
}
export function deleteNamedNode(nodes, name) {
if (nodes) {
const idx = nodes.findIndex(value => value.name.value === name);
return idx >= 0 ? nodes.toSpliced(idx, 1) : nodes;
}
}
export function parentPath(path) {
const lastDividerIndex = path.lastIndexOf('.');
return lastDividerIndex === -1 ? path : path.substring(0, lastDividerIndex);
}
const isAdditionChange = (change) => {
switch (change.type) {
case ChangeType.DirectiveAdded:
case ChangeType.DirectiveArgumentAdded:
case ChangeType.DirectiveLocationAdded:
case ChangeType.EnumValueAdded:
case ChangeType.EnumValueDeprecationReasonAdded:
case ChangeType.FieldAdded:
case ChangeType.FieldArgumentAdded:
case ChangeType.FieldDeprecationAdded:
case ChangeType.FieldDeprecationReasonAdded:
case ChangeType.FieldDescriptionAdded:
case ChangeType.InputFieldAdded:
case ChangeType.InputFieldDescriptionAdded:
case ChangeType.ObjectTypeInterfaceAdded:
case ChangeType.TypeDescriptionAdded:
case ChangeType.TypeAdded:
case ChangeType.UnionMemberAdded:
case ChangeType.DirectiveUsageArgumentAdded:
case ChangeType.DirectiveUsageArgumentDefinitionAdded:
case ChangeType.DirectiveUsageEnumAdded:
case ChangeType.DirectiveUsageEnumValueAdded:
case ChangeType.DirectiveUsageFieldAdded:
case ChangeType.DirectiveUsageFieldDefinitionAdded:
case ChangeType.DirectiveUsageInputFieldDefinitionAdded:
case ChangeType.DirectiveUsageInputObjectAdded:
case ChangeType.DirectiveUsageInterfaceAdded:
case ChangeType.DirectiveUsageObjectAdded:
case ChangeType.DirectiveUsageScalarAdded:
case ChangeType.DirectiveUsageSchemaAdded:
case ChangeType.DirectiveUsageUnionMemberAdded:
return true;
default:
return false;
}
};
export function debugPrintChange(change, nodeByPath) {
if (isAdditionChange(change)) {
console.debug(`"${change.path}" is being added to the schema.`);
}
else {
const changedNode = (change.path && nodeByPath.get(change.path)) || false;
if (changedNode) {
console.debug(`"${change.path}" has a change: [${change.type}] "${change.message}"`);
}
else {
console.debug(`The "${change.type}" change to "${change.path}" cannot be applied. That coordinate does not exist in the schema.`);
}
}
}
export function assertValueMatch(change, expectedKind, expected, actual, config) {
if (expected !== actual) {
config.onError(new ValueMismatchError(expectedKind, expected, actual), change);
}
}
/**
* Handles verifying the change object has a path, that the node exists in the
* nodeByPath Map, and that the found node is the expected Kind.
*/
export function getChangedNodeOfKind(change, nodeByPath, kind, config) {
if (kind === Kind.DIRECTIVE) {
throw new Error('Directives cannot be found using this method.');
}
if (!change.path) {
config.onError(new ChangePathMissingError(change), change);
return;
}
const existing = nodeByPath.get(change.path);
if (!existing) {
config.onError(new ChangedCoordinateNotFoundError(kind, undefined), change);
return;
}
if (existing.kind !== kind) {
config.onError(new ChangedCoordinateKindMismatchError(kind, existing.kind), change);
}
return existing;
}
export function getDeletedNodeOfKind(change, nodeByPath, kind, config) {
if (!change.path) {
config.onError(new ChangePathMissingError(change), change);
return;
}
const existing = nodeByPath.get(change.path);
if (!existing) {
config.onError(new DeletedCoordinateNotFound(change.path, change.type), change);
return;
}
if (existing.kind !== kind) {
config.onError(new ChangedCoordinateKindMismatchError(kind, existing.kind), change);
return;
}
return existing;
}