@kya-os/create-mcp-i-app
Version:
Bootstrap MCP applications with identity features (temporary - use @kya-os/create-mcpi-app after Oct 7)
106 lines • 3.46 kB
JavaScript
import fs from "fs-extra";
import path from "path";
/**
* Validate project name meets requirements
*/
export function validateProjectName(name) {
const issues = [];
// Check if name is empty
if (!name || name.trim().length === 0) {
issues.push("Project name cannot be empty");
return { valid: false, issues };
}
const trimmedName = name.trim();
// Check length
if (trimmedName.length < 1) {
issues.push("Project name must be at least 1 character long");
}
if (trimmedName.length > 214) {
issues.push("Project name must be less than 214 characters");
}
// Check for invalid characters (npm package name rules)
if (!/^[a-z0-9@._/-]+$/.test(trimmedName)) {
issues.push("Project name can only contain lowercase letters, numbers, and the characters @._/-");
}
// Check if it starts with . or _
if (trimmedName.startsWith(".") || trimmedName.startsWith("_")) {
issues.push("Project name cannot start with . or _");
}
// Check for reserved names
const reservedNames = [
"node_modules",
"favicon.ico",
"package.json",
"package-lock.json",
"yarn.lock",
"pnpm-lock.yaml",
".git",
".gitignore",
".env",
"readme",
"readme.md",
"readme.txt",
"license",
"license.md",
"license.txt",
"changelog",
"changelog.md",
"changelog.txt",
];
if (reservedNames.includes(trimmedName.toLowerCase())) {
issues.push(`"${trimmedName}" is a reserved name and cannot be used as a project name`);
}
// Check for scoped package format
if (trimmedName.startsWith("@")) {
const parts = trimmedName.split("/");
if (parts.length !== 2) {
issues.push("Scoped package names must be in the format @scope/name");
}
else if (parts[1].length === 0) {
issues.push("Scoped package name cannot have empty package name");
}
}
return {
valid: issues.length === 0,
issues,
};
}
/**
* Check if directory is available for project creation
*/
export function validateDirectoryAvailability(projectPath) {
const issues = [];
try {
// Check if path exists
if (fs.existsSync(projectPath)) {
const stats = fs.statSync(projectPath);
if (!stats.isDirectory()) {
issues.push(`Path exists but is not a directory: ${projectPath}`);
}
else {
// Check if directory is empty
const files = fs.readdirSync(projectPath);
const nonHiddenFiles = files.filter((file) => !file.startsWith("."));
if (nonHiddenFiles.length > 0) {
issues.push(`Directory is not empty: ${projectPath}`);
}
}
}
// Check if parent directory is writable
const parentDir = path.dirname(projectPath);
try {
fs.accessSync(parentDir, fs.constants.W_OK);
}
catch {
issues.push(`Parent directory is not writable: ${parentDir}`);
}
}
catch (error) {
issues.push(`Error checking directory: ${error instanceof Error ? error.message : String(error)}`);
}
return {
valid: issues.length === 0,
issues,
};
}
//# sourceMappingURL=validate-project-name.js.map