nextdevkit
Version:
A Comprehensive CLI Toolkit for Next.js Development
56 lines (55 loc) • 2.47 kB
JavaScript
import { execSync } from 'child_process';
import fs from 'fs-extra';
import inquirer from 'inquirer';
import path from 'path';
import getPackageManager from '../utils/getPackageManager.js';
import getProjectCreateCommand from '../utils/getProjectCreateCommand.js';
import { handleError } from '../utils/handleMessages.js';
const createCommand = async (projectName) => {
try {
if (!projectName) {
const answers = await inquirer.prompt([
{
type: 'input',
name: 'projectName',
message: 'Enter a name for your project:',
validate: (input) => {
if (!input.trim()) {
return 'Project name cannot be empty.';
}
if (!isValidProjectName(input)) {
return ('Invalid project name. ' +
'The name can only contain letters, numbers, hyphens (-), and underscores (_), ' +
'and it cannot start or end with a hyphen or underscore.');
}
return true;
}
}
]);
projectName = answers.projectName;
}
const packageManager = await getPackageManager();
const createCommand = getProjectCreateCommand(packageManager, projectName);
execSync(createCommand, { stdio: 'inherit' });
const projectPath = path.resolve(process.cwd(), projectName);
process.chdir(projectPath);
await createProjectStructure(projectPath);
}
catch (error) {
handleError(error);
}
};
const isValidProjectName = (name) => {
const regex = /^(?![_-])[a-zA-Z0-9_-]+(?<![_-])$/;
return regex.test(name);
};
const createProjectStructure = async (projectPath) => {
const srcPath = path.join(projectPath, 'src');
const directories = (await fs.pathExists(srcPath)) ?
['src/components', 'src/hooks', 'src/lib', 'src/context', 'src/utils']
: ['components', 'hooks', 'lib', 'context', 'utils'];
const files = [{ filePath: '.env', content: 'NODE_ENV=development\n' }];
await Promise.all(directories.map((dir) => fs.ensureDir(path.join(projectPath, dir))));
await Promise.all(files.map(({ filePath, content }) => fs.outputFile(path.join(projectPath, filePath), content)));
};
export default createCommand;