@saiforceone/dirt-cli
Version:
Official CLI Utility for the D.I.R.T stack
253 lines (226 loc) • 8.05 kB
text/typescript
import chalk from 'chalk';
import type { Answers, QuestionCollection } from 'inquirer';
import inquirer from 'inquirer';
import ora from 'ora';
import ConsoleLogger from './utils/ConsoleLogger.js';
import { preScaffold } from './preScaffold.js';
import { postScaffold } from './postScaffold.js';
import { validateProjectName } from './utils/validateProjectName.js';
import { setupGitRepo } from './setupGitRepo.js';
import { setupPrettier } from './setupPrettier.js';
import { scaffoldChecks } from './scaffoldChecks.js';
import LogType = DIRTStackCLI.LogType;
import ScaffoldOptions = DIRTStackCLI.ScaffoldOptions;
import ScaffoldOutput = DIRTStackCLI.ScaffoldOutput;
import { setupVercelDeployment } from './utils/deploymentSetupUtils.js';
const { scaffoldDjango } = await import('./scaffoldDjango.js');
const { scaffoldFrontend } = await import('./scaffoldFrontend.js');
/**
* @description Prompt the user when setting up a new DIRT Stack project
*/
async function cliPrompts(): Promise<Answers> {
const prompts: QuestionCollection = [
{
message: 'What should we call this project?',
name: 'projectName',
type: 'input',
validate: function (input: string) {
return validateProjectName(input) ? true : 'Not a valid project name';
},
},
{
choices: ['react', 'vue'],
message: 'Select a frontend framework / library',
name: 'frontend',
type: 'list',
},
{
choices: ['None', 'sqlite', 'mysql', 'postgresql'],
message: 'Select a database',
name: 'databaseOption',
type: 'list',
default: 'None',
},
{
default: false,
message: 'Would you like to use StorybookJS?',
name: 'withStorybook',
type: 'confirm',
},
{
default: false,
message: 'Would you like to install Prettier?',
name: 'installPrettier',
type: 'confirm',
},
{
default: false,
message: 'Would you like to have git initialized?',
name: 'initializeGit',
type: 'confirm',
},
{
choices: ['Vercel', 'None'],
message: 'What deployment option would you like to use?',
name: 'deploymentOption',
type: 'list',
},
{
default: false,
message: 'Show verbose logs?',
name: 'verboseLogs',
type: 'confirm',
},
];
return inquirer.prompt(prompts);
}
/**
* @description Helper function that handles if we should show quiet or noisy logs
* @param {LogType} logType
* @param {ScaffoldOptions} options
* @returns {*|(function(): Promise<*>)}
*/
function scaffoldFuncs(logType: LogType, options: ScaffoldOptions) {
const funcs = {
noisyLogs: async function () {
const djangoResult = await scaffoldDjango(options);
ConsoleLogger.printMessage(`Django setup status: ${djangoResult.result}`);
if (!djangoResult.success) {
process.exit(1);
}
// Scaffold the Frontend application
const frontendResult: ScaffoldOutput = await scaffoldFrontend(options);
ConsoleLogger.printMessage(
`${options.frontend} frontend Status: ${frontendResult.result}`
);
if (!frontendResult.success) {
process.exit(1);
}
// Prettier
if (options['installPrettier']) {
ConsoleLogger.printMessage('Installing prettier...');
const prettierResult = await setupPrettier(process.cwd());
ConsoleLogger.printMessage(
prettierResult.success
? 'Done'
: `Failed to install Prettier with error: ${prettierResult.error}. You might want to try installing it manually`,
prettierResult.success ? 'success' : 'warning'
);
}
if (options['initializeGit']) {
ConsoleLogger.printMessage('Initializing git...');
const gitResult: ScaffoldOutput = await setupGitRepo();
ConsoleLogger.printMessage(
gitResult.success
? 'Done'
: 'Failed to initialize git. You might want to try running the command yourself',
gitResult.success ? 'success' : 'warning'
);
}
if (options['deploymentOption'] === 'Vercel') {
ConsoleLogger.printMessage(
`Setting up deployment option for ${options['deploymentOption']}`
);
const deploymentSetupResult = await setupVercelDeployment({
projectName: options.projectName,
destination: process.cwd(),
});
ConsoleLogger.printOutput(deploymentSetupResult);
}
},
quietLogs: async function () {
const djangoSpinner = ora('Setting up Django...');
const frontendSpinner = ora(
`Setting up Frontend (${chalk.green(options['frontend'])})...`
);
const prettierSpinner = ora('Setting up prettier in your project...');
const gitSpinner = ora('Setting up git in your project...');
const deploymentOptSpinner = ora(
`Setting up deployment options for ${chalk.green(
options['deploymentOption']
)}...`
);
try {
djangoSpinner.start();
const djangoResult = await scaffoldDjango(options);
djangoResult.success
? djangoSpinner.succeed()
: djangoSpinner.fail('Failed to setup Django. See below.');
if (!djangoResult.success) {
console.log(`${chalk.red(`Error: ${djangoResult.error}`)}`);
process.exit(1);
}
frontendSpinner.start();
const frontendResult: ScaffoldOutput = await scaffoldFrontend(options);
frontendResult.success
? frontendSpinner.succeed()
: frontendSpinner.fail('Failed to setup Frontend. See below.');
if (!frontendResult.success) {
console.log(`
${chalk.red(`Error: ${frontendResult.error}`)}
`);
process.exit(1);
}
if (options['installPrettier']) {
prettierSpinner.start();
const prettierResult = await setupPrettier(process.cwd());
prettierResult.success
? prettierSpinner.succeed()
: prettierSpinner.warn(prettierResult.error);
}
if (options['initializeGit']) {
gitSpinner.start();
const gitResult: ScaffoldOutput = await setupGitRepo();
gitResult.success
? gitSpinner.succeed()
: gitSpinner.warn(gitResult.error);
}
if (options['deploymentOption'] === 'Vercel') {
deploymentOptSpinner.start();
const deploymentSetupResult = await setupVercelDeployment({
projectName: options.projectName,
destination: process.cwd(),
});
deploymentSetupResult.success
? deploymentOptSpinner.succeed()
: deploymentOptSpinner.warn(deploymentSetupResult.result);
}
} catch (e) {
console.log(`
${chalk.red(
`Failed to scaffold project with error: ${(e as Error).message}`
)}
`);
process.exit(1);
}
},
};
return funcs[logType] ? funcs[logType] : funcs['quietLogs'];
}
/**
* @description entry point for the application / util. Scaffolding of the different parts of
* a D.I.R.T Stack application happens here
* @returns {Promise<void>}
*/
export async function cli() {
// print welcome message
preScaffold();
// process prompts
const options = await cliPrompts();
// environment checks
scaffoldChecks(options as ScaffoldOptions);
// print welcome
console.log(
`${chalk.green.italic('\nSetting up your D.I.R.T Stack application...')}`
);
// Scaffolds the Django (core) application and sets up base structure
const logType = options['verboseLogs'] ? 'noisyLogs' : 'quietLogs';
console.log(`Setting up project with log mode: ${chalk.blue(
options['verboseLogs'] ? 'Verbose' : 'Quiet'
)}
`);
// Call scaffold functions based on log type selection
await scaffoldFuncs(logType, options as ScaffoldOptions)();
// print post scaffold message
postScaffold(options as ScaffoldOptions);
}