UNPKG

create-mcp-i-app

Version:

Bootstrap MCP applications with identity features (temporary - use create-mcpi-app after Oct 7)

103 lines 3.73 kB
import fs from "fs-extra"; import path from "path"; import chalk from "chalk"; /** * Validate that the generated project structure meets requirements */ export function validateProjectStructure(projectPath, identityEnabled) { const issues = []; // Check package.json scripts const packageJsonPath = path.join(projectPath, "package.json"); if (fs.existsSync(packageJsonPath)) { const packageJson = fs.readJsonSync(packageJsonPath); const scripts = packageJson.scripts || {}; const scriptCount = Object.keys(scripts).length; if (identityEnabled) { // Should have exactly 8 scripts for identity-enabled projects if (scriptCount !== 8) { issues.push(`Expected exactly 8 scripts for identity project, found ${scriptCount}`); } const requiredScripts = [ "dev", "build", "start", "init", "register", "keys:rotate", "identity:clean", "status", ]; for (const script of requiredScripts) { if (!scripts[script]) { issues.push(`Missing required script: ${script}`); } } } else { // Should have exactly 3 scripts for vanilla XMCP projects if (scriptCount !== 3) { issues.push(`Expected exactly 3 scripts for vanilla project, found ${scriptCount}`); } const requiredScripts = ["dev", "build", "start"]; for (const script of requiredScripts) { if (!scripts[script]) { issues.push(`Missing required script: ${script}`); } } } } else { issues.push("package.json not found"); } // Check required files exist (based on actual XMCP upstream structure) const requiredFiles = [ "src/tools/greet.ts", // XMCP creates greet.ts, not hello.ts ".gitignore", "xmcp.config.ts", ]; for (const file of requiredFiles) { if (!fs.existsSync(path.join(projectPath, file))) { issues.push(`Missing required file: ${file}`); } } // Check .gitignore includes .mcpi/ for identity projects if (identityEnabled) { const gitignorePath = path.join(projectPath, ".gitignore"); if (fs.existsSync(gitignorePath)) { const gitignoreContent = fs.readFileSync(gitignorePath, "utf8"); if (!gitignoreContent.includes(".mcp-i/") && !gitignoreContent.includes(".mcpi/")) { issues.push(".gitignore should include .mcp-i/ directory"); } } } return { valid: issues.length === 0, issues, }; } /** * Ensure lockfile is written and not mutated post-generation */ export function ensureLockfile(projectPath, packageManager) { const lockfiles = { npm: "package-lock.json", yarn: "yarn.lock", pnpm: "pnpm-lock.yaml", }; const lockfileName = lockfiles[packageManager]; if (!lockfileName) { console.warn(chalk.yellow(`Unknown package manager: ${packageManager}`)); return; } const lockfilePath = path.join(projectPath, lockfileName); // The lockfile should be created during npm install // We just validate it exists after installation if (fs.existsSync(lockfilePath)) { console.log(chalk.green(`✅ Lockfile created: ${lockfileName}`)); } else { console.warn(chalk.yellow(`⚠️ Lockfile not found: ${lockfileName}`)); } } //# sourceMappingURL=validate-project-structure.js.map