UNPKG

@memory-bank/mcp

Version:

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

132 lines 5.84 kB
import { BranchInfo } from '../../domain/entities/BranchInfo.js'; import { ApplicationErrors } from '../../shared/errors/ApplicationError.js'; import { DomainError } from '../../shared/errors/DomainError.js'; import { logger } from '../../shared/utils/logger.js'; /** * Helper service that selects the appropriate repository based on scope and branch name. * Also handles branch name auto-detection in project mode. */ export class DocumentRepositorySelector { branchRepository; globalRepository; gitService; configProvider; componentLogger = logger.withContext({ component: 'DocumentRepositorySelector' }); /** * Constructor * @param branchRepository Branch memory bank repository * @param globalRepository Global memory bank repository * @param gitService Git service for branch detection * @param configProvider Configuration provider */ constructor(branchRepository, globalRepository, gitService, configProvider) { this.branchRepository = branchRepository; this.globalRepository = globalRepository; this.gitService = gitService; this.configProvider = configProvider; } /** * Get the appropriate repository based on scope and branch name * @param scope 'branch' or 'global' * @param branchName Optional branch name (will be auto-detected in project mode if not provided) * @returns Promise resolving to repository and branch info (if applicable) * @throws ApplicationError if scope is invalid or branch name cannot be determined */ async getRepository(scope, branchName) { this.componentLogger.debug(`Getting repository for scope: ${scope}`, { branchName }); if (scope === 'global') { return { repository: this.createGlobalRepositoryAdapter(), }; } else if (scope === 'branch') { const resolvedBranchName = await this.resolveBranchName(branchName); const branchInfo = BranchInfo.create(resolvedBranchName); // Check if branch exists const exists = await this.branchRepository.exists(branchInfo.safeName); if (!exists) { this.componentLogger.info(`Branch '${branchInfo.safeName}' does not exist. Will be initialized when used.`); } return { repository: this.createBranchRepositoryAdapter(branchInfo), branchInfo, }; } else { throw ApplicationErrors.invalidInput(`Invalid scope: ${scope}. Must be 'branch' or 'global'.`); } } /** * Create an adapter that implements IDocumentRepository for branch repository * @param branchInfo Branch information * @returns IDocumentRepository adapter */ createBranchRepositoryAdapter(branchInfo) { return { getDocument: async (path) => { return this.branchRepository.getDocument(branchInfo, path); }, saveDocument: async (document) => { await this.branchRepository.saveDocument(branchInfo, document); }, exists: async (identifier) => { return this.branchRepository.exists(identifier); }, initialize: async () => { await this.branchRepository.initialize(branchInfo); }, }; } /** * Create an adapter that implements IDocumentRepository for global repository * @returns IDocumentRepository adapter */ createGlobalRepositoryAdapter() { return { getDocument: async (path) => { return this.globalRepository.getDocument(path); }, saveDocument: async (document) => { await this.globalRepository.saveDocument(document); }, exists: async () => { return true; // Global repository always exists }, initialize: async () => { await this.globalRepository.initialize(); }, }; } /** * Resolve branch name, auto-detecting from Git in project mode if not provided * @param branchName Optional branch name * @returns Promise resolving to branch name * @throws ApplicationError if branch name cannot be determined */ async resolveBranchName(branchName) { // Check for empty string if (branchName === '') { this.componentLogger.warn('Empty branch name provided.'); throw new DomainError('DOMAIN_ERROR.INVALID_BRANCH_NAME', 'Branch name cannot be empty'); } if (branchName) { return branchName; } const config = this.configProvider.getConfig(); if (config.isProjectMode) { try { this.componentLogger.info('Branch name not provided in project mode, attempting to detect from Git...'); const currentBranch = await this.gitService.getCurrentBranchName(); this.componentLogger.info(`Current branch name automatically detected: ${currentBranch}`); return currentBranch; } catch (error) { this.componentLogger.error('Failed to get current branch name', { error }); throw ApplicationErrors.invalidInput('Branch name is required but could not be automatically determined. Please provide it explicitly or ensure you are in a Git repository.', { cause: error instanceof Error ? error : undefined }); } } this.componentLogger.warn('Branch name omitted outside of project mode.'); throw ApplicationErrors.invalidInput('Branch name is required when not running in project mode.'); } } //# sourceMappingURL=DocumentRepositorySelector.js.map