Fast implementation of JSON-Patch (RFC-6902) with duplex capabilities for applying, generating, and observing JSON document changes
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Comprehensive validation utilities for ensuring JSON Patch operations and sequences are correctly formatted and can be safely applied to target documents.
Validates an array of JSON Patch operations, optionally against a target document.
/**
* Validates a sequence of operations. If document parameter is provided,
* the sequence is additionally validated against the object document.
* @param sequence Array of operations to validate
* @param document Optional document to validate operations against
* @param externalValidator Optional custom validator function
* @returns JsonPatchError if validation fails, undefined if valid
*/
function validate<T>(
sequence: ReadonlyArray<Operation>,
document?: T,
externalValidator?: Validator<T>
): JsonPatchError | undefined;Usage Examples:
import { validate } from "fast-json-patch";
// Basic structure validation
const patch = [
{ op: "add", path: "/name", value: "Alice" },
{ op: "remove", path: "/age" }
];
const error = validate(patch);
if (error) {
console.error("Invalid patch:", error.message);
} else {
console.log("Patch is valid");
}
// Validate against target document
const document = { name: "John", age: 30 };
const patchWithError = [
{ op: "remove", path: "/nonexistent" } // This path doesn't exist
];
const docError = validate(patchWithError, document);
if (docError) {
console.error("Cannot apply patch:", docError.name); // "OPERATION_PATH_UNRESOLVABLE"
}
// Using custom validator
const customValidator = (op, index, doc, path) => {
if (op.op === "add" && typeof op.value === "string" && op.value.length > 100) {
throw new Error("String values cannot exceed 100 characters");
}
};
const longStringPatch = [
{ op: "add", path: "/description", value: "a".repeat(150) }
];
const customError = validate(longStringPatch, document, customValidator);Validates a single JSON Patch operation, with detailed error reporting.
/**
* Validates a single operation. Called from validate. Throws JsonPatchError in case of an error.
* @param operation Operation object to validate
* @param index Index of operation in the sequence
* @param document Optional object where the operation is supposed to be applied
* @param existingPathFragment Optional existing path fragment for context
*/
function validator(
operation: Operation,
index: number,
document?: any,
existingPathFragment?: string
): void;Usage Examples:
import { validator } from "fast-json-patch";
try {
// Validate operation structure
validator({ op: "add", path: "/name", value: "Alice" }, 0);
console.log("Operation is valid");
// This will throw an error
validator({ op: "invalid", path: "/name" }, 0);
} catch (error) {
console.error("Validation failed:", error.message);
console.error("Error code:", error.name); // "OPERATION_OP_INVALID"
}
// Validate against document context
const doc = { users: ["Alice"] };
try {
validator(
{ op: "add", path: "/users/5", value: "Bob" },
0,
doc,
"/users"
);
} catch (error) {
console.error("Invalid array index:", error.name); // "OPERATION_VALUE_OUT_OF_BOUNDS"
}Custom validator function interface for extending validation logic:
interface Validator<T> {
/**
* Custom validation function
* @param operation The operation being validated
* @param index The operation's index in the sequence
* @param document The target document
* @param existingPathFragment The existing path fragment for context
*/
(
operation: Operation,
index: number,
document: T,
existingPathFragment: string
): void;
}Comprehensive error class for JSON Patch validation failures:
class JsonPatchError extends Error {
constructor(
message: string,
name: JsonPatchErrorName,
index?: number,
operation?: any,
tree?: any
);
/** Descriptive error name */
name: JsonPatchErrorName;
/** Index of the failing operation */
index?: number;
/** The operation that caused the error */
operation?: any;
/** The document being operated on */
tree?: any;
}All possible validation error types:
type JsonPatchErrorName =
| 'SEQUENCE_NOT_AN_ARRAY' // Patch sequence must be an array
| 'OPERATION_NOT_AN_OBJECT' // Operation must be an object
| 'OPERATION_OP_INVALID' // Invalid operation type
| 'OPERATION_PATH_INVALID' // Invalid path format
| 'OPERATION_FROM_REQUIRED' // Missing 'from' property for move/copy
| 'OPERATION_VALUE_REQUIRED' // Missing 'value' property for add/replace/test
| 'OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED' // Value cannot contain undefined
| 'OPERATION_PATH_CANNOT_ADD' // Cannot add at the specified path
| 'OPERATION_PATH_UNRESOLVABLE' // Path does not exist in document
| 'OPERATION_FROM_UNRESOLVABLE' // From path does not exist in document
| 'OPERATION_PATH_ILLEGAL_ARRAY_INDEX' // Invalid array index format
| 'OPERATION_VALUE_OUT_OF_BOUNDS' // Array index out of bounds
| 'TEST_OPERATION_FAILED'; // Test operation comparison failedAdd Operations:
value propertyundefinedRemove Operations:
Replace Operations:
value propertyundefinedMove Operations:
from property (string)path and from must be valid pathsfrom path must exist in the target documentCopy Operations:
from property (string)from path must exist in the target documentTest Operations:
value propertyTEST_OPERATION_FAILED if values don't matchWhen validating against a document:
__proto__ and constructor.prototypeExtend validation with custom logic:
import { validate, Validator } from "fast-json-patch";
const businessValidator: Validator<any> = (operation, index, document, path) => {
// Business logic validation
if (operation.op === "add" && operation.path.startsWith("/admin/")) {
throw new Error("Admin modifications not allowed");
}
// Type-specific validation
if (operation.op === "replace" && operation.path === "/email") {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(operation.value)) {
throw new Error("Invalid email format");
}
}
};
// Use with validation
const error = validate(patch, document, businessValidator);This validation system ensures patch operations are safe, correctly formatted, and can be successfully applied to target documents while providing detailed error information for debugging.