@memory-bank/mcp
Version:
Memory-enabled Co-Pilot (MCP) server for managing project documentation and context
145 lines • 5.01 kB
JavaScript
import { DomainError, DomainErrorCodes } from '../../shared/errors/DomainError.js';
import { JsonPath } from './JsonPath.js';
/**
* Class encapsulating a JSON Patch operation
* Implementation of JSON Patch operations compliant with RFC 6902
*/
export class JsonPatchOperation {
_op;
_path;
_value;
_from;
/**
* Constructor - Do not use directly, use the static factory method instead
*/
constructor(op, path, value, from) {
this._op = op;
this._path = path;
this._value = value;
this._from = from;
}
/**
* Create a patch operation object
* @param op Operation type
* @param path Target path
* @param value Value to set (required for add/replace/test)
* @param from Source path (required for move/copy)
* @returns New JsonPatchOperation instance
* @throws DomainError if operation type is invalid or required parameters are missing
*/
static create(op, path, value, from) {
// Validate operation type
const validOps = ['add', 'remove', 'replace', 'move', 'copy', 'test'];
if (!validOps.includes(op)) {
throw new DomainError(DomainErrorCodes.INVALID_JSON_PATCH_OPERATION, `Invalid operation type: '${op}'`);
}
// Validate and parse path
if (path === undefined || path === null) { // path の存在チェックを追加
throw new DomainError(DomainErrorCodes.INVALID_JSON_PATCH_OPERATION, `Operation of type '${op}' requires 'path'`);
}
const jsonPath = JsonPath.parse(path);
// Parse 'from' if specified
const jsonFrom = from ? JsonPath.parse(from) : undefined;
// Operation type specific validation
// add, replace, test require value
if (['add', 'replace', 'test'].includes(op) && value === undefined) {
throw new DomainError(DomainErrorCodes.INVALID_JSON_PATCH_OPERATION, `Operation of type '${op}' requires 'value'`);
}
// move, copy require from
if (['move', 'copy'].includes(op) && !from) {
throw new DomainError(DomainErrorCodes.INVALID_JSON_PATCH_OPERATION, `Operation of type '${op}' requires 'from'`);
}
// 操作タイプに応じて不要な引数をクリア
let finalValue = value;
let finalFrom = jsonFrom;
if (op === 'remove') {
finalValue = undefined;
finalFrom = undefined;
}
else if (['add', 'replace', 'test'].includes(op)) {
finalFrom = undefined;
}
else if (['move', 'copy'].includes(op)) {
finalValue = undefined;
}
// Create instance with potentially cleared arguments
return new JsonPatchOperation(op, jsonPath, finalValue, finalFrom);
}
/**
* Create a patch operation object from a JSON representation
* @param json JSON string or already parsed object
* @returns New JsonPatchOperation instance
*/
static fromJSON(json) {
const obj = typeof json === 'string' ? JSON.parse(json) : json;
return JsonPatchOperation.create(obj.op, obj.path, obj.value, obj.from);
}
/**
* Get the operation type
*/
get op() {
return this._op;
}
/**
* Get the target path
*/
get path() {
return this._path;
}
/**
* Get the value
*/
get value() {
return this._value;
}
/**
* Get the source path
*/
get from() {
return this._from;
}
/**
* Validate the operation's validity
* @throws DomainError if the operation is invalid
*/
validate() {
// For 'move', cannot move to a descendant of the source path
if (this._op === 'move' && this._from && this._path.toString().startsWith(this._from.toString() + '/')) {
throw new DomainError(DomainErrorCodes.INVALID_JSON_PATCH_OPERATION, 'Cannot move to a path that is a child of the source path');
}
}
/**
* Convert to JSON representation
* @returns JSON-serializable object
*/
toJSON() {
const result = {
op: this._op,
path: this._path.toString(),
};
if (this._value !== undefined) {
result.value = this._value;
}
if (this._from) {
result.from = this._from.toString();
}
return result;
}
/**
* Convert to rfc6902 format operation object
* @returns rfc6902 compatible object
*/
toRfc6902Operation() {
// toJSON() already returns an object that is compatible with rfc6902 Operation
return this.toJSON();
}
/**
* @deprecated Use toRfc6902Operation instead
* Legacy adapter method - kept for compatibility with existing code
*/
toFastJsonPatchOperation() {
// Just delegates to toJSON for backward compatibility
return this.toJSON();
}
}
//# sourceMappingURL=JsonPatchOperation.js.map