UNPKG

@memory-bank/mcp

Version:

Memory-enabled Co-Pilot (MCP) server for managing project documentation and context

145 lines 6.84 kB
import { Rfc6902JsonPatchAdapter } from '../../../domain/jsonpatch/Rfc6902JsonPatchAdapter.js'; // Use rfc6902 adapter import { DomainError, DomainErrorCodes } from '../../../shared/errors/DomainError.js'; import { JsonDocument } from '../../../domain/entities/JsonDocument.js'; import { DocumentVersionInfo } from '../../../domain/entities/DocumentVersionInfo.js'; import { EventType } from '../../../domain/events/EventType.js'; /** * Use case for partially updating a document using JSON Patch */ export class JsonPatchUseCase { repository; patchService; eventEmitter; /** * Constructor * @param repository JSON document repository * @param eventEmitter Document event emitter * @param patchService JsonPatchService (uses Rfc6902JsonPatchAdapter if omitted) */ constructor(repository, eventEmitter, patchService) { this.repository = repository; this.eventEmitter = eventEmitter; this.patchService = patchService ?? new Rfc6902JsonPatchAdapter(); // Use rfc6902 adapter as default } /** * Apply patch operations to a document * @param path Document path * @param operations Array of patch operations to apply * @param branch Branch name (uses branch memory bank if specified, global otherwise) * @param updateReason Reason for the update (optional) * @returns Updated JSON document * @throws DomainError if document not found, operation invalid, or other errors */ async execute(path, operations, branch, updateReason) { // Get the document const document = await this.getDocument(path, branch); if (!document) { throw new DomainError(DomainErrorCodes.DOCUMENT_NOT_FOUND, `Document not found: ${path}${branch ? ` in branch ${branch}` : ''}`); } // Validate patch operations const isValid = this.patchService.validate(document.content, operations); if (!isValid) { throw new DomainError(DomainErrorCodes.INVALID_JSON_PATCH_OPERATION, 'Invalid JSON patch operation'); } // Apply patch operations const updatedContent = this.patchService.apply(document.content, operations); // Create new document version info const updatedVersionInfo = new DocumentVersionInfo({ version: document.versionInfo.version + 1, lastModified: new Date(), modifiedBy: 'system', updateReason: updateReason || 'Updated via JSON Patch' }); // Create updated document const updatedDocument = JsonDocument.create({ path: document.path, id: document.id, title: document.title, documentType: document.documentType, tags: document.tags, content: updatedContent, branch: document.branch, versionInfo: updatedVersionInfo }); // Save the document const savedDocument = await this.saveDocument(updatedDocument); // Emit update event this.eventEmitter.emit(EventType.DOCUMENT_UPDATED, { path: savedDocument.path, branch: savedDocument.branch, versionInfo: savedDocument.versionInfo }); return savedDocument; } /** * Apply multiple patch operations atomically * @param path Document path * @param operations Array of patch operations to apply * @param branch Branch name (uses branch memory bank if specified, global otherwise) * @param updateReason Reason for the update (optional) * @returns Updated JSON document * @throws DomainError if document not found, operation invalid, or other errors */ async executeBatch(path, operations, branch, updateReason) { // Use the regular execute method (already ensures atomicity) return this.execute(path, operations, branch, updateReason || 'Batch update via JSON Patch'); } /** * Generate patch operations representing the difference between two documents * @param sourcePath Path of the source document * @param targetPath Path of the target document * @param sourceBranch Branch of the source document (optional) * @param targetBranch Branch of the target document (optional) * @returns Array of generated patch operations * @throws DomainError if documents are not found */ async generatePatch(sourcePath, targetPath, sourceBranch, targetBranch) { // Get source document const sourceDocument = await this.getDocument(sourcePath, sourceBranch); if (!sourceDocument) { throw new DomainError(DomainErrorCodes.DOCUMENT_NOT_FOUND, `Source document not found: ${sourcePath}${sourceBranch ? ` in branch ${sourceBranch}` : ''}`); } // Get target document const targetDocument = await this.getDocument(targetPath, targetBranch); if (!targetDocument) { throw new DomainError(DomainErrorCodes.DOCUMENT_NOT_FOUND, `Target document not found: ${targetPath}${targetBranch ? ` in branch ${targetBranch}` : ''}`); } // Generate patch operations return this.patchService.generatePatch(sourceDocument.content, targetDocument.content); } /** * Apply patch operations after verifying test conditions * @param path Document path * @param operations Array including test and update operations * @param branch Branch name (uses branch memory bank if specified, global otherwise) * @param updateReason Reason for the update (optional) * @returns Updated JSON document * @throws DomainError if document not found, test fails, operation invalid, or other errors */ async executeConditional(path, operations, branch, updateReason) { // Use the execute method (patchService's apply method will throw if test fails) return this.execute(path, operations, branch, updateReason || 'Conditional update via JSON Patch'); } /** * Get a document (uses appropriate repository method based on branch presence) * @param path Document path * @param branch Branch name (optional) * @returns JSON document or null if not found */ async getDocument(path, branch) { return branch ? await this.repository.findBranchDocument(path, branch) : await this.repository.findGlobalDocument(path); } /** * Save a document (uses appropriate repository method based on branch presence) * @param document Document to save * @returns Saved document */ async saveDocument(document) { return document.branch ? await this.repository.saveBranchDocument(document) : await this.repository.saveGlobalDocument(document); } } //# sourceMappingURL=JsonPatchUseCase.js.map