Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(wip): support new options #37

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7,304 changes: 7,303 additions & 1 deletion package-lock.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion packages/@guidesmiths/cuckoojs-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,18 @@
"dependencies": {
"@angular-devkit/schematics-cli": "^14.2.3",
"@guidesmiths/cuckoojs-schematics": "^0.0.1",
"@nestjs/cli": "^9.1.5",
"@nestjs/schematics": "^9.0.3",
"@types/jasmine": "~4.3.0",
"@types/node": "^18.7.18",
"commander": "^9.4.0",
"loading-cli": "^1.1.0"
"loading-cli": "^1.1.0",
"inquirer": "^8.2.5"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To remove

},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.38.0",
"@typescript-eslint/parser": "^5.38.0",
"@types/inquirer": "^9.0.3",
"eslint": "^8.23.1",
"eslint-config-xo": "^0.42.0",
"eslint-config-xo-typescript": "^0.53.0",
Expand Down
40 changes: 25 additions & 15 deletions packages/@guidesmiths/cuckoojs-cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,27 @@
import {Command} from 'commander';
import {version} from '../package.json';
import {NewCommand, GenerateCommand} from './commands';
import {removeDashes} from './lib/utils/formatArgs';

const init = (): void => {
const cuckoo = new Command('cuckoo');

cuckoo
.version(
version,
'-v, --version',
'Output the current version.',
);
const originalArgs = process.argv;

cuckoo
.helpOption('-h, --help', 'Output usage information.')
.showHelpAfterError()
.usage('<command> [options]');

cuckoo
.command('new <name>')
.command('new')
.argument('[name]', 'Name of your Nest App')
.argument('[options...]', 'List of options. Please, refer to Nest documentation for the available options: https://docs.nestjs.com/cli/usages#nest-new')
.alias('n')
.description('Generate Nest application with basic tooling.')
.action(async (name: string, _options: any) => {
await new NewCommand(name).execute();
.hook('preAction', (_, actionCommand) => {
const commandArgs = originalArgs.slice(3);
const isOption = (a: string) => /^--|^-/.test(a);
actionCommand.processedArgs[0] = commandArgs.find(a => !isOption(a));
actionCommand.processedArgs[1] = commandArgs.filter(a => isOption(a));
})
.action(async (name: string, options: string[]) => {
await new NewCommand(name, options).execute();
});

cuckoo
Expand All @@ -35,7 +34,18 @@ const init = (): void => {
});

cuckoo
.parse(process.argv);
.version(
version,
'-v, --version',
'Output the current version.',
);

cuckoo
.helpOption('-h, --help', 'Output usage information.')
.showHelpAfterError();

cuckoo
.parse(removeDashes(process.argv));
};

init();
160 changes: 93 additions & 67 deletions packages/@guidesmiths/cuckoojs-cli/src/commands/new.command.ts
Original file line number Diff line number Diff line change
@@ -1,88 +1,114 @@
import {SchematicRunner} from '../lib/runners/schematic.runner';
import {GitRunner} from '../lib/runners/git.runner';
import type {PackageEntry, ScriptEntry} from '../lib/runners/npm.runner';
import {NpmRunner} from '../lib/runners/npm.runner';
import {messages} from '../lib/ui/ui';
import * as fs from 'fs';
import {join} from 'path';
import {BashRunnerHusky} from '../lib/runners/bash.runner.husky';

import {AbstractCommand} from './abstract.command';
import Printer from '../lib/printer/printer';
// import {SchematicRunner} from '../lib/runners/schematic.runner';
// import {GitRunner} from '../lib/runners/git.runner';
// import type {PackageEntry, ScriptEntry} from '../lib/runners/npm.runner';
// import {NpmRunner} from '../lib/runners/npm.runner';
// import {BashRunnerHusky} from '../lib/runners/bash.runner.husky';
import {NestJsRunner} from '../lib/runners/nestjs.runner';

// import Printer from '../lib/printer/printer';
// import {promptInput, promptSelect} from '../lib/inquirer/inquirer';
import {messages} from '../lib/ui/ui';

export class NewCommand extends AbstractCommand {
private readonly schematicRunner: SchematicRunner = new SchematicRunner();
private readonly gitRunner: GitRunner = new GitRunner();
private readonly npmRunner: NpmRunner = new NpmRunner();
private readonly bashRunnerHusky: BashRunnerHusky = new BashRunnerHusky();

private readonly initialPackages: PackageEntry[] = [
{name: 'husky', version: '^8.0.1', section: 'devDependencies'},
];

private readonly initialScripts: ScriptEntry[] = [
{name: 'prepare', value: 'husky install'},
{name: 'postinstall', value: 'npx @guidesmiths/license-checker --outputFileName license-report --failOn /GPL/'},
];
// private readonly schematicRunner: SchematicRunner = new SchematicRunner();
// private readonly gitRunner: GitRunner = new GitRunner();
// private readonly npmRunner: NpmRunner = new NpmRunner();
// private readonly bashRunnerHusky: BashRunnerHusky = new BashRunnerHusky();
private readonly nestJsRunner: NestJsRunner = new NestJsRunner();

// private readonly initialPackages: PackageEntry[] = [
// {name: 'husky', version: '^8.0.1', section: 'devDependencies'},
// ];
//
// private readonly initialScripts: ScriptEntry[] = [
// {name: 'prepare', value: 'husky install'},
// {name: 'postinstall', value: 'npx @guidesmiths/license-checker --outputFileName license-report --failOn /GPL/'},
// ];

constructor(
private readonly name: string,
private readonly options: string[],
) {
super();
}

public async execute() {
const printer = new Printer({total: 8, step: 1});
// const printer = new Printer({total: 8, step: 1});
this.printSuccess(messages.banner);

if (this.checkFileExists()) {
this.printError(`Error generating new project: Folder ${this.name} already exists`);
NewCommand.endProcess(1);
}

try {
this.checkFileExists();

printer.startStep('Generating NestJS application scaffolding');
await this.schematicRunner.generateNestApplication(this.name);
printer.endStep();

printer.startStep('Initializing Git repository');
await this.gitRunner.init(this.name);
await this.gitRunner.createBranch({folderName: this.name});
printer.endStep();

printer.startStep('Adding additional packages');
await this.npmRunner.addPackages(this.name, this.initialPackages);
printer.endStep();

printer.startStep('Adding additional npm scripts');
await this.npmRunner.addScripts(this.name, this.initialScripts);
printer.endStep();

printer.startStep('Adding commitlint config file');
await this.schematicRunner.addCommitlint(this.name);
printer.endStep();

printer.startStep('Adding .gitignore file');
await this.schematicRunner.addGitignoreFile(this.name);
printer.endStep();

printer.startStep('Installing dependencies');
await this.npmRunner.install(this.name);
printer.endStep();

printer.startStep('Creating husky files');
await this.bashRunnerHusky.runHuskyCommit(this.name);
printer.endStep();

this.printSuccess(`\n 🐦 Your CuckooJS nest "${this.name}" is generated and ready to use 🐦`);
// await this.retrieveMissingArguments();

// printer.startStep('Generating NestJS application scaffolding');
await this.nestJsRunner.generateNestApplication(this.name, this.options);
// printer.endStep();

// printer.startStep('Initializing Git repository');
// await this.gitRunner.init(this.name);
// await this.gitRunner.createBranch({folderName: this.name});
// printer.endStep();
//
// printer.startStep('Adding additional packages');
// await this.npmRunner.addPackages(this.name, this.initialPackages);
// printer.endStep();
//
// printer.startStep('Adding additional npm scripts');
// await this.npmRunner.addScripts(this.name, this.initialScripts);
// printer.endStep();
//
// printer.startStep('Adding commitlint config file');
// await this.schematicRunner.addCommitlint(this.name);
// printer.endStep();
//
// printer.startStep('Adding .gitignore file');
// await this.schematicRunner.addGitignoreFile(this.name);
// printer.endStep();
//
// printer.startStep('Installing dependencies');
// await this.npmRunner.install(this.name);
// printer.endStep();
//
// printer.startStep('Creating husky files');
// await this.bashRunnerHusky.runHuskyCommit(this.name);
// printer.endStep();

this.printSuccess('\n 🐦 Your CuckooJS NestJS app is generated and ready to use 🐦');
} catch (error: unknown) {
printer.load.fail(`Error generating new project: ${(error as Error).message}`);
// printer.load.fail(`Error generating new project: ${(error as Error).message}`);
this.removeFolder();
NewCommand.endProcess(1);
}
}

// private async retrieveMissingArguments() {
// let {name} = this;
// if (!this.name) {
// ({name} = await promptInput({name: 'name', message: 'What is the name of your application?', defaultAnswer: 'cuckoo-app'}));
// console.log(name);
// if (this.checkFileExists()) {
// this.printError(`Error generating new project: Folder ${this.name} already exists`);
// NewCommand.endProcess(1);
// }
// }
//
// const packageManagerOption = this.options.find(option => option.includes('--package-manager'));
// let selectedPackageManager = packageManagerOption?.split('=')?.[1];
// if (!packageManagerOption || !selectedPackageManager || ['npm', 'yarn', 'pnpm'].includes(selectedPackageManager)) {
// ({packageManager: selectedPackageManager} = await promptSelect({
// name: 'packageManager',
// message: 'What package manager you would like to use',
// choices: ['npm', 'yarn', 'pnpm'],
// defaultAnswer: 'npm',
// }));
// }
//
// return {name, packageManager: selectedPackageManager};
// }

private removeFolder() {
try {
fs.rmdirSync(join(process.cwd(), this.name), {recursive: true});
Expand All @@ -91,8 +117,8 @@ export class NewCommand extends AbstractCommand {
}
}

private checkFileExists() {
const path = join(process.cwd(), this.name);
return fs.existsSync(path);
}
// private checkFileExists() {
// const path = join(process.cwd(), this.name);
// return fs.existsSync(path);
// }
}
13 changes: 13 additions & 0 deletions packages/@guidesmiths/cuckoojs-cli/src/lib/inquirer/inquirer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import * as inquirer from 'inquirer';

export async function promptInput({
name, message, defaultAnswer,
}: {name: string; message: string; defaultAnswer: string}): Promise<inquirer.Answers> {
return inquirer.createPromptModule()([{type: 'input', name, message, default: defaultAnswer}]);
}

export async function promptSelect({
name, message, choices, defaultAnswer,
}: {name: string; message: string; choices: string[]; defaultAnswer: string}): Promise<inquirer.Answers> {
return inquirer.createPromptModule({})([{type: 'select', name, message, choices, default: defaultAnswer}]);
}
Comment on lines +1 to +13
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To remove

Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class GenericRunner {
const options: SpawnOptions = {
cwd,
stdio,
shell: true,
shell: false,
};

return new Promise((resolve, reject) => {
Expand All @@ -31,8 +31,7 @@ export class GenericRunner {
);

child.on('error', error => {
console.log('eeeee', error);
reject(new Error(`Child process filed with error: ${error.message}`));
reject(new Error(`Child process failed with error: ${error.message}`));
});

child.on('close', code => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {GenericRunner} from './generic.runner';

export class NestJsRunner extends GenericRunner {
private static getNestJsCliPath(): string {
return require.resolve(
'@nestjs/cli/bin/nest.js',
{paths: module.paths},
);
}

// private static formatNewOptions(options: string[]): string {
// const formattedOptions = options.filter(Boolean).join(' ');
// if (options.includes('--skip-install')) {
// return formattedOptions;
// }
//
// return `${formattedOptions} --skip-install`;
// }
//
Comment on lines +11 to +19
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To remove

constructor() {
super('node');
}

public async generateNestApplication(name: string, options: string[]) {
const args = ['new', name, ...options].filter(Boolean);
console.log(args);
await super.run({command: NestJsRunner.getNestJsCliPath(), args, stdio: 'inherit'});
}
}
30 changes: 30 additions & 0 deletions packages/@guidesmiths/cuckoojs-cli/src/lib/utils/formatArgs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
function removeDashesFrom(args: string[], initialIndex: number): string[] {
return args.map((arg, index) => {
if (index < initialIndex) {
return arg;
}

return arg.replace(/^--|^-/, '');
});
}

export function removeDashes(args: string[]): string[] {
const command = args[2];
const parsingStrategies: Record<string, () => string[]> = {
new() {
return removeDashesFrom(args, 2);
},
generate() {
return removeDashesFrom(args, 5);
},
default() {
return args;
},
};

return (parsingStrategies[command] || parsingStrategies.default)();
}

export function addDashes(args: string[]): string[] {
return args.map(arg => `--${arg}`);
}
Comment on lines +28 to +30
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To remove