UNPKG

@al76/tools-and-spec-workflow-mcp

Version:

MCP server for spec-driven development workflow with real-time web dashboard

97 lines 3.6 kB
import { join, normalize, sep, resolve } from 'path'; import { access, stat, mkdir } from 'fs/promises'; import { constants } from 'fs'; export class PathUtils { static getWorkflowRoot(projectPath) { return normalize(join(projectPath, '.spec-workflow')); } static getSpecPath(projectPath, specName) { return normalize(join(projectPath, '.spec-workflow', 'specs', specName)); } static getArchiveSpecPath(projectPath, specName) { return normalize(join(projectPath, '.spec-workflow', 'archive', 'specs', specName)); } static getArchiveSpecsPath(projectPath) { return normalize(join(projectPath, '.spec-workflow', 'archive', 'specs')); } static getSteeringPath(projectPath) { return normalize(join(projectPath, '.spec-workflow', 'steering')); } static getTemplatesPath(projectPath) { return normalize(join(projectPath, '.spec-workflow', 'templates')); } static getAgentsPath(projectPath) { return normalize(join(projectPath, '.spec-workflow', 'agents')); } static getCommandsPath(projectPath) { return normalize(join(projectPath, '.spec-workflow', 'commands')); } static getApprovalsPath(projectPath) { return normalize(join(projectPath, '.spec-workflow', 'approvals')); } static getSpecApprovalPath(projectPath, specName) { return normalize(join(projectPath, '.spec-workflow', 'approvals', specName)); } // Ensure paths work across Windows, macOS, Linux static toPlatformPath(path) { return path.split('/').join(sep); } static toUnixPath(path) { return path.split(sep).join('/'); } // Get relative path from project root static getRelativePath(projectPath, fullPath) { const normalizedProject = normalize(projectPath); const normalizedFull = normalize(fullPath); if (normalizedFull.startsWith(normalizedProject)) { return normalizedFull.slice(normalizedProject.length + 1); } return normalizedFull; } } export async function validateProjectPath(projectPath) { try { // Resolve to absolute path const absolutePath = resolve(projectPath); // Check if path exists await access(absolutePath, constants.F_OK); // Ensure it's a directory const stats = await stat(absolutePath); if (!stats.isDirectory()) { throw new Error(`Project path is not a directory: ${absolutePath}`); } return absolutePath; } catch (error) { if (error.code === 'ENOENT') { throw new Error(`Project path does not exist: ${projectPath}`); } throw error; } } export async function ensureDirectoryExists(dirPath) { try { await access(dirPath, constants.F_OK); } catch { await mkdir(dirPath, { recursive: true }); } } export async function ensureWorkflowDirectory(projectPath) { const workflowRoot = PathUtils.getWorkflowRoot(projectPath); // Create all necessary subdirectories (approvals created on-demand) const directories = [ workflowRoot, PathUtils.getSpecPath(projectPath, ''), PathUtils.getArchiveSpecsPath(projectPath), PathUtils.getSteeringPath(projectPath), PathUtils.getTemplatesPath(projectPath), PathUtils.getAgentsPath(projectPath), PathUtils.getCommandsPath(projectPath) ]; for (const dir of directories) { await ensureDirectoryExists(dir); } return workflowRoot; } //# sourceMappingURL=path-utils.js.map