UNPKG

@graphql-inspector/patch

Version:

Applies changes output from @graphql-inspect/diff

218 lines (217 loc) 9.95 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ChangePathMissingError = exports.ChangedCoordinateKindMismatchError = exports.DeletedCoordinateNotFound = exports.ChangedCoordinateNotFoundError = exports.DeletedAttributeNotFoundError = exports.AddedAttributeAlreadyExistsError = exports.DeletedAncestorCoordinateNotFoundError = exports.ChangedAncestorCoordinateNotFoundError = exports.AddedAttributeCoordinateNotFoundError = exports.AddedCoordinateAlreadyExistsError = exports.ValueMismatchError = exports.NoopError = exports.looseErrorHandler = exports.defaultErrorHandler = exports.strictErrorHandler = void 0; const utils_js_1 = require("./utils.js"); /** * The strictest of the standard error handlers. This checks if the error is a "No-op", * meaning if the change wouldn't impact the schema at all, and ignores the error * only in this one case. Otherwise, the error is raised. */ const strictErrorHandler = (err, _change) => { if (err instanceof NoopError) { console.debug(`[IGNORED] ${err.message}`); } else { throw err; } }; exports.strictErrorHandler = strictErrorHandler; /** * A convenient, semi-strict error handler. This ignores "no-op" errors -- if * the change wouldn't impact the patched schema at all. And it ignores * value mismatches, which are when the change notices that the value captured in * the change doesn't match the value in the patched schema. * * For example, if the change indicates the default value WAS "foo" before being * changed, but the patch is applied to a schema where the default value is "bar". * This is useful to avoid overwriting changes unknowingly that may have occurred * from other sources. */ const defaultErrorHandler = (err, change) => { if (err instanceof NoopError) { console.debug(`[IGNORED] ${err.message}`); } else if (err instanceof ValueMismatchError) { console.debug(`Ignoring old value mismatch at "${change.path}".`); } else { throw err; } }; exports.defaultErrorHandler = defaultErrorHandler; /** * The least strict error handler. This will only log errors and will never * raise an error. This is potentially useful for getting a patched schema * rendered, and then handling the conflict/error in a separate step. E.g. * if creating a merge conflict resolution UI. */ const looseErrorHandler = (err, change) => { if (err instanceof NoopError) { console.debug(`[IGNORED] ${err.message}`); } else if (err instanceof ValueMismatchError) { console.debug(`Ignoring old value mismatch at "${change.path}".`); } else { console.warn(err.message); } }; exports.looseErrorHandler = looseErrorHandler; /** * When the change does not actually modify the resulting schema, then it is * considered a "no-op". This error can safely be ignored. */ class NoopError extends Error { constructor(message) { super(`The change resulted in a no op. ${message}`); this.noop = true; } } exports.NoopError = NoopError; class ValueMismatchError extends Error { constructor(kind, expected, actual) { super(`The existing value did not match what was expected. Expected the "${kind}" to be "${String(expected)}" but found "${String(actual)}".`); this.mismatch = true; } } exports.ValueMismatchError = ValueMismatchError; /** * If the requested change would not modify the schema because that change is effectively * already applied. * * If the added coordinate exists but the kind does not match what's expected, then use * ChangedCoordinateKindMismatchError instead. */ class AddedCoordinateAlreadyExistsError extends NoopError { constructor(path, changeType) { const subpath = path.substring(path.lastIndexOf('.') + 1); const parent = (0, utils_js_1.parentPath)(path); const printedParent = parent === subpath ? 'schema' : `"${parent}"`; super(`Cannot apply "${changeType}" to add "${subpath}" to ${printedParent} because that schema coordinate already exists.`); this.path = path; this.changeType = changeType; } } exports.AddedCoordinateAlreadyExistsError = AddedCoordinateAlreadyExistsError; class AddedAttributeCoordinateNotFoundError extends Error { constructor(path, changeType, /** * The value of what is being changed at the path. E.g. if the description is being changed, then this should * be the description string. */ changeValue) { const subpath = path.substring(path.lastIndexOf('.')); super(`Cannot apply addition "${changeType}" (${changeValue}) to "${subpath}", because "${path}" does not exist.`); this.path = path; this.changeType = changeType; this.changeValue = changeValue; } } exports.AddedAttributeCoordinateNotFoundError = AddedAttributeCoordinateNotFoundError; /** * If trying to manipulate a node at a path, but that path no longer exists. E.g. change a description of * a type, but that type was previously deleted. */ class ChangedAncestorCoordinateNotFoundError extends Error { constructor(path, changeType, /** * The value of what is being changed at the path. E.g. if the description is being changed, then this should * be the description string. */ changeValue) { const subpath = path.substring(path.lastIndexOf('.')); super(`Cannot apply change "${changeType}" (${typeof changeValue === 'string' ? `"${changeValue}"` : changeValue}) to "${subpath}", because the "${(0, utils_js_1.parentPath)(path)}" does not exist.`); this.path = path; this.changeType = changeType; this.changeValue = changeValue; } } exports.ChangedAncestorCoordinateNotFoundError = ChangedAncestorCoordinateNotFoundError; /** * If trying to remove a node but that node no longer exists. E.g. remove a directive from * a type, but that type does not exist. */ class DeletedAncestorCoordinateNotFoundError extends NoopError { constructor(path, changeType, /** * The value of what is being changed at the path. E.g. if the description is being changed, then this should * be the description string. */ expectedValue) { const subpath = path.substring(path.lastIndexOf('.')); super(`Cannot apply "${changeType}" to remove ${typeof expectedValue === 'string' ? `"${expectedValue}"` : expectedValue} from "${subpath}", because "${(0, utils_js_1.parentPath)(path)}" does not exist.`); this.path = path; this.changeType = changeType; this.expectedValue = expectedValue; } } exports.DeletedAncestorCoordinateNotFoundError = DeletedAncestorCoordinateNotFoundError; /** * If adding an attribute to a node, but that attribute already exists. * E.g. adding an interface but that interface is already applied to the type. */ class AddedAttributeAlreadyExistsError extends NoopError { constructor(path, changeType, /** The property's path on the node. E.g. defaultValue */ attribute, expectedValue) { const subpath = path.substring(path.lastIndexOf('.')); super(`Cannot apply "${changeType}" to add ${typeof expectedValue === 'string' ? `"${expectedValue}"` : expectedValue} to "${subpath}.${attribute}", because it already exists`); this.path = path; this.changeType = changeType; this.attribute = attribute; this.expectedValue = expectedValue; } } exports.AddedAttributeAlreadyExistsError = AddedAttributeAlreadyExistsError; /** * If deleting an attribute from a node, but that attribute does not exist. * E.g. deleting an interface but that interface is not applied to the type. */ class DeletedAttributeNotFoundError extends NoopError { constructor(path, changeType, /** The property's path on the node. E.g. defaultValue */ attribute, expectedValue) { const subpath = path.substring(path.lastIndexOf('.')); super(`Cannot apply "${changeType}" to remove ${typeof expectedValue === 'string' ? `"${expectedValue}"` : expectedValue} from ${subpath}'s "${attribute}", because "${attribute}" does not exist at "${path}".`); this.path = path; this.changeType = changeType; this.attribute = attribute; this.expectedValue = expectedValue; } } exports.DeletedAttributeNotFoundError = DeletedAttributeNotFoundError; class ChangedCoordinateNotFoundError extends Error { constructor(expectedKind, expectedNameOrValue) { super(`The "${expectedKind}" ${expectedNameOrValue ? `"${expectedNameOrValue}" ` : ''}does not exist.`); } } exports.ChangedCoordinateNotFoundError = ChangedCoordinateNotFoundError; class DeletedCoordinateNotFound extends NoopError { constructor(path, changeType) { const subpath = path.substring(path.lastIndexOf('.')); const parent = (0, utils_js_1.parentPath)(path); const printedParent = parent === subpath ? 'schema' : `"${parent}"`; super(`Cannot apply "${changeType}" on "${printedParent}", because "${subpath}" does not exist.`); this.path = path; this.changeType = changeType; } } exports.DeletedCoordinateNotFound = DeletedCoordinateNotFound; class ChangedCoordinateKindMismatchError extends Error { constructor(expectedKind, receivedKind) { super(`Expected type to have be a "${expectedKind}", but found a "${receivedKind}".`); this.expectedKind = expectedKind; this.receivedKind = receivedKind; } } exports.ChangedCoordinateKindMismatchError = ChangedCoordinateKindMismatchError; /** * This should not happen unless there's an issue with the diff creation. */ class ChangePathMissingError extends Error { constructor(change) { super(`The change "${change.type}" at "${change.path}" is missing a "path" value. Cannot apply.`); this.change = change; } } exports.ChangePathMissingError = ChangePathMissingError;