create-mcp-i-app
Version:
Bootstrap MCP applications with identity features (temporary - use create-mcpi-app after Oct 7)
103 lines • 3.73 kB
JavaScript
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