mern-project-cli
Version:
A developer-friendly CLI tool that streamlines MERN stack development by automating project setup, database configuration, and boilerplate generation by implementing MVC Architecture. Create production-ready MongoDB, Express, React, and Node.js applicatio
153 lines (137 loc) • 3.96 kB
JavaScript
import fs from 'fs-extra';
import path from 'path';
import { execSync } from 'child_process';
import detectProjectType from '../utils/detectProjectType.js';
const getESLintConfig = (projectType) => {
const baseConfig = {
env: {
es2021: true,
browser: !['node'].includes(projectType),
node: ['node', 'typescript'].includes(projectType),
},
extends: ['eslint:recommended', 'plugin:prettier/recommended'],
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
rules: {
'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
'prettier/prettier': [
'error',
{
singleQuote: true,
trailingComma: 'es5',
printWidth: 80,
tabWidth: 2,
},
],
},
};
const configs = {
react: {
...baseConfig,
extends: [
...baseConfig.extends,
'plugin:react/recommended',
'plugin:react-hooks/recommended',
],
plugins: ['react', 'react-hooks'],
settings: {
react: { version: 'detect' },
},
},
vue: {
...baseConfig,
extends: [...baseConfig.extends, 'plugin:vue/vue3-recommended'],
plugins: ['vue'],
},
typescript: {
...baseConfig,
extends: [...baseConfig.extends, 'plugin:@typescript-eslint/recommended'],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
},
node: {
...baseConfig,
extends: [...baseConfig.extends, 'plugin:node/recommended'],
plugins: ['node'],
rules: {
...baseConfig.rules,
'no-process-env': 'warn',
},
},
};
return configs[projectType] || baseConfig;
};
const getDependencies = (projectType) => {
const baseDeps = [
'eslint',
'prettier',
'eslint-config-prettier',
'eslint-plugin-prettier',
];
const projectDeps = {
react: ['eslint-plugin-react', 'eslint-plugin-react-hooks'],
vue: ['eslint-plugin-vue'],
typescript: [
'@typescript-eslint/parser',
'@typescript-eslint/eslint-plugin',
],
node: ['eslint-plugin-node'],
};
return [...baseDeps, ...(projectDeps[projectType] || [])];
};
const setupESLint = async (dirPath) => {
try {
const projectType = detectProjectType(dirPath);
console.log(`Setting up ESLint for ${projectType} project...`);
// Write ESLint config
await fs.writeJSON(
path.join(dirPath, '.eslintrc.json'),
getESLintConfig(projectType),
{ spaces: 2 }
);
// Write Prettier config
await fs.writeJSON(
path.join(dirPath, '.prettierrc'),
{
singleQuote: true,
trailingComma: 'es5',
printWidth: 80,
tabWidth: 2,
},
{ spaces: 2 }
);
// Update package.json
const packageJsonPath = path.join(dirPath, 'package.json');
const packageJson = fs.existsSync(packageJsonPath)
? await fs.readJSON(packageJsonPath)
: { scripts: {} };
packageJson.scripts = {
...packageJson.scripts,
lint: 'eslint . --ext .js,.jsx,.ts,.tsx,.vue',
'lint:fix': 'eslint . --ext .js,.jsx,.ts,.tsx,.vue --fix',
format: 'prettier --write "**/*.{js,jsx,ts,tsx,vue,json,css,scss,md}"',
};
await fs.writeJSON(packageJsonPath, packageJson, { spaces: 2 });
// Install dependencies
const dependencies = getDependencies(projectType);
execSync(`npm install ${dependencies.join(' ')} --save-dev`, {
stdio: 'inherit',
cwd: dirPath,
});
console.log('ESLint setup complete!');
return true;
} catch (error) {
console.error(`Setup failed: ${error.message}`);
return false;
}
};
export default function addESLintCommand(program) {
program
.command('add-eslint [directory]')
.description('Initialize ESLint and Prettier in the specified directory')
.action(async (directory = '.') => {
await setupESLint(path.resolve(directory));
});
}