nextdevkit
Version:
A Comprehensive CLI Toolkit for Next.js Development
105 lines (104 loc) • 4.13 kB
JavaScript
import chalk from 'chalk';
import { spawn } from 'child_process';
import fs from 'fs-extra';
import path from 'path';
import ts from 'typescript';
import files from '../files.js';
import { __dirname } from '../utils/constants/package.constant.js';
import getAliasValue from '../utils/getAliasValue.js';
import getDestinationPaths from '../utils/getDestinationPaths.js';
import getPackageManager from '../utils/getPackageManager.js';
import { handleError, handleSuccess } from '../utils/handleMessages.js';
import isTypeScriptProject from '../utils/isTypescriptProject.js';
import loadNextdevkitConfig from '../utils/loadNextdevkitConfig.js';
const addFile = async (fileName) => {
if (!fileName) {
console.log(chalk.red('Please specify the name of the file to add.'));
console.log(chalk.yellow('Usage: npx nextdevkit@latest add <name>'));
return;
}
const currentDirectory = process.cwd();
const config = await loadNextdevkitConfig(currentDirectory);
if (!config) {
handleError('Failed to load configuration file.', {
message: 'Ensure the configuration file exists or can be created.',
exit: true
});
return;
}
const isTs = isTypeScriptProject(currentDirectory);
const fileConfig = files.find((f) => f.command.toLowerCase() === fileName.toLowerCase());
if (!fileConfig) {
console.log(chalk.red(`File name '${fileName}' not found.`));
console.log(`\nUse ${chalk.cyan('npx nextdevkit@latest list')} to list all available utility and hook files.\n`);
return;
}
try {
const aliasValue = await getAliasValue(currentDirectory, isTs);
const { destFolderPath, destFilePath } = getDestinationPaths(currentDirectory, config.aliases, fileConfig, aliasValue, fileName, isTs);
await fs.ensureDir(destFolderPath);
const srcFilePath = path.join(__dirname, '../../files', fileConfig.destinationFolder, `${fileConfig.name}.ts`);
if (isTs) {
await fs.copy(srcFilePath, destFilePath);
}
else {
await transpileToJs(srcFilePath, destFilePath, fileConfig.name);
}
if (fileConfig.dependencies || fileConfig.devDependencies) {
await installDependencies(fileConfig.dependencies || [], false);
await installDependencies(fileConfig.devDependencies || [], true);
}
handleSuccess(`File '${fileName}' added successfully.`);
}
catch (error) {
handleError(error, {
message: `Failed to add file '${fileName}'. Please check the input and try again.`,
verbose: true
});
}
};
const transpileToJs = async (srcFilePath, destFilePath, fileName) => {
const sourceCode = await fs.readFile(srcFilePath, 'utf8');
const transpileOptions = {
compilerOptions: {
module: ts.ModuleKind.ESNext,
target: ts.ScriptTarget.ESNext,
sourceMap: false,
declaration: false
},
fileName: `${fileName}.ts`
};
const result = ts.transpileModule(sourceCode, transpileOptions);
await fs.writeFile(destFilePath, result.outputText, 'utf8');
};
const installDependencies = async (packages, isDev) => {
if (packages.length === 0)
return;
const currentDirectory = process.cwd();
const packageManager = await getPackageManager();
const command = packageManager;
const args = [
packageManager === 'npm' ? 'install' : 'add',
...packages,
isDev ?
packageManager === 'npm' ?
'--save-dev'
: '-D'
: ''
].filter(Boolean);
await new Promise((resolve, reject) => {
const child = spawn(command, args, {
cwd: currentDirectory,
stdio: 'inherit'
});
child.on('close', (code) => {
if (code === 0) {
resolve();
}
else {
reject(new Error(`Failed to install ${isDev ? 'devDependencies' : 'dependencies'}`));
}
});
});
};
export default addFile;