From 4887baff5f505cf8683e55eb4aec3a263ff36357 Mon Sep 17 00:00:00 2001 From: Daniel Samson Date: Thu, 2 Feb 2023 21:13:08 +0000 Subject: [PATCH 1/4] fix: display custom schematics in help Signed-off-by: Daniel Samson --- actions/generate.action.ts | 6 +++++- bin/nest.ts | 8 +++---- commands/command.loader.ts | 4 ++-- commands/generate.command.ts | 31 ++++++++++++++++++++------- lib/schematics/abstract.collection.ts | 5 ++++- lib/schematics/custom.collection.ts | 29 ++++++++++++++++++++++++- lib/schematics/nest.collection.ts | 2 +- 7 files changed, 67 insertions(+), 18 deletions(-) diff --git a/actions/generate.action.ts b/actions/generate.action.ts index 447436eff..1e024a071 100644 --- a/actions/generate.action.ts +++ b/actions/generate.action.ts @@ -102,7 +102,11 @@ const generateFiles = async (inputs: Input[]) => { specValue, specOptions.passedAsInput, ); - generateFlat = shouldGenerateFlat(configuration, answers.appNames, flatValue); + generateFlat = shouldGenerateFlat( + configuration, + answers.appNames, + flatValue, + ); } } diff --git a/bin/nest.ts b/bin/nest.ts index 7a425f724..eb78617e8 100644 --- a/bin/nest.ts +++ b/bin/nest.ts @@ -7,7 +7,7 @@ import { localBinExists, } from '../lib/utils/local-binaries'; -const bootstrap = () => { +const bootstrap = async () => { const program: CommanderStatic = commander; program .version( @@ -20,11 +20,11 @@ const bootstrap = () => { if (localBinExists()) { const localCommandLoader = loadLocalBinCommandLoader(); - localCommandLoader.load(program); + await localCommandLoader.load(program); } else { - CommandLoader.load(program); + await CommandLoader.load(program); } - commander.parse(process.argv); + commander.parseAsync(process.argv); if (!process.argv.slice(2).length) { program.outputHelp(); diff --git a/commands/command.loader.ts b/commands/command.loader.ts index d73a7d849..ba570a19c 100644 --- a/commands/command.loader.ts +++ b/commands/command.loader.ts @@ -16,13 +16,13 @@ import { InfoCommand } from './info.command'; import { NewCommand } from './new.command'; import { StartCommand } from './start.command'; export class CommandLoader { - public static load(program: CommanderStatic): void { + public static async load(program: CommanderStatic): Promise { new NewCommand(new NewAction()).load(program); new BuildCommand(new BuildAction()).load(program); new StartCommand(new StartAction()).load(program); new InfoCommand(new InfoAction()).load(program); new AddCommand(new AddAction()).load(program); - new GenerateCommand(new GenerateAction()).load(program); + await new GenerateCommand(new GenerateAction()).load(program); this.handleInvalidCommand(program); } diff --git a/commands/generate.command.ts b/commands/generate.command.ts index d4f350849..732a9e0b5 100644 --- a/commands/generate.command.ts +++ b/commands/generate.command.ts @@ -1,16 +1,18 @@ import * as chalk from 'chalk'; import * as Table from 'cli-table3'; import { Command, CommanderStatic } from 'commander'; -import { NestCollection } from '../lib/schematics/nest.collection'; +import { AbstractCollection, CollectionFactory } from '../lib/schematics'; +import { Schematic } from '../lib/schematics/nest.collection'; +import { loadConfiguration } from '../lib/utils/load-configuration'; import { AbstractCommand } from './abstract.command'; import { Input } from './command.input'; export class GenerateCommand extends AbstractCommand { - public load(program: CommanderStatic) { + public async load(program: CommanderStatic): Promise { program .command('generate [name] [path]') .alias('g') - .description(this.buildDescription()) + .description(await this.buildDescription()) .option( '-d, --dry-run', 'Report actions that would be taken without writing out results.', @@ -93,17 +95,18 @@ export class GenerateCommand extends AbstractCommand { ); } - private buildDescription(): string { + private async buildDescription(): Promise { + const collection = await this.getCollection(); return ( 'Generate a Nest element.\n' + ` Schematics available on ${chalk.bold( - '@nestjs/schematics', + collection, )} collection:\n` + - this.buildSchematicsListAsTable() + this.buildSchematicsListAsTable(await this.getSchematics(collection)) ); } - private buildSchematicsListAsTable(): string { + private buildSchematicsListAsTable(schematics: Schematic[]): Promise { const leftMargin = ' '; const tableConfig = { head: ['name', 'alias', 'description'], @@ -118,7 +121,7 @@ export class GenerateCommand extends AbstractCommand { }, }; const table: any = new Table(tableConfig); - for (const schematic of NestCollection.getSchematics()) { + for (const schematic of schematics) { table.push([ chalk.green(schematic.name), chalk.cyan(schematic.alias), @@ -127,4 +130,16 @@ export class GenerateCommand extends AbstractCommand { } return table.toString(); } + + private async getCollection(): Promise { + const configuration = await loadConfiguration(); + return configuration.collection; + } + + private async getSchematics(collection: string): Promise { + const abstractCollection: AbstractCollection = CollectionFactory.create( + collection, + ); + return abstractCollection.getSchematics(); + } } diff --git a/lib/schematics/abstract.collection.ts b/lib/schematics/abstract.collection.ts index ec2c1b94b..88a25a85e 100644 --- a/lib/schematics/abstract.collection.ts +++ b/lib/schematics/abstract.collection.ts @@ -1,7 +1,8 @@ import { AbstractRunner } from '../runners'; +import { Schematic } from './nest.collection'; import { SchematicOption } from './schematic.option'; -export class AbstractCollection { +export abstract class AbstractCollection { constructor(protected collection: string, protected runner: AbstractRunner) {} public async execute( @@ -14,6 +15,8 @@ export class AbstractCollection { await this.runner.run(command); } + public abstract getSchematics(): Schematic[]; + private buildCommandLine(name: string, options: SchematicOption[]): string { return `${this.collection}:${name}${this.buildOptions(options)}`; } diff --git a/lib/schematics/custom.collection.ts b/lib/schematics/custom.collection.ts index 0e8bbc764..9c3a3a087 100644 --- a/lib/schematics/custom.collection.ts +++ b/lib/schematics/custom.collection.ts @@ -1,3 +1,30 @@ +import { description } from 'commander'; +import { readFileSync } from 'fs'; +import { dirname, join } from 'path'; import { AbstractCollection } from './abstract.collection'; +import { Schematic } from './nest.collection'; -export class CustomCollection extends AbstractCollection {} +export interface CollectionSchematic { + factory: string; + schema: string; + aliases: string[]; +} + +export class CustomCollection extends AbstractCollection { + public getSchematics(): Schematic[] { + this.collection; + const collectionPackagePath = dirname(require.resolve(this.collection)); + const collectionPath = join(collectionPackagePath, 'collection.json'); + const collection = JSON.parse(readFileSync(collectionPath).toString()); + const schematics = Object.entries(collection.schematics).map( + ([name, value]) => { + const schematic = value as CollectionSchematic; + const description = schematic.description; + const alias = schematic?.aliases?.length ? schematic.aliases[0] : ''; + return { name, description, alias }; + }, + ); + + return schematics; + } +} diff --git a/lib/schematics/nest.collection.ts b/lib/schematics/nest.collection.ts index 468346028..2d9dc588a 100644 --- a/lib/schematics/nest.collection.ts +++ b/lib/schematics/nest.collection.ts @@ -121,7 +121,7 @@ export class NestCollection extends AbstractCollection { await super.execute(schematic, options); } - public static getSchematics(): Schematic[] { + public getSchematics(): Schematic[] { return NestCollection.schematics.filter( (item) => item.name !== 'angular-app', ); From 6e164a69d582eeabe63030aa333e31f152315532 Mon Sep 17 00:00:00 2001 From: Daniel Samson Date: Thu, 2 Feb 2023 22:21:20 +0000 Subject: [PATCH 2/4] fix: add missing description field --- lib/schematics/custom.collection.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schematics/custom.collection.ts b/lib/schematics/custom.collection.ts index 9c3a3a087..f49dabdde 100644 --- a/lib/schematics/custom.collection.ts +++ b/lib/schematics/custom.collection.ts @@ -5,8 +5,8 @@ import { AbstractCollection } from './abstract.collection'; import { Schematic } from './nest.collection'; export interface CollectionSchematic { - factory: string; schema: string; + description: string; aliases: string[]; } From b71bfea1ebcd45e1ddba2d259603da9db29a4a84 Mon Sep 17 00:00:00 2001 From: Daniel Samson <12231216+daniel-samson@users.noreply.github.com> Date: Fri, 3 Feb 2023 00:22:16 +0000 Subject: [PATCH 3/4] Update lib/schematics/custom.collection.ts Co-authored-by: Micael Levi L. Cavalcante --- lib/schematics/custom.collection.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/schematics/custom.collection.ts b/lib/schematics/custom.collection.ts index f49dabdde..17e3a13f6 100644 --- a/lib/schematics/custom.collection.ts +++ b/lib/schematics/custom.collection.ts @@ -12,7 +12,6 @@ export interface CollectionSchematic { export class CustomCollection extends AbstractCollection { public getSchematics(): Schematic[] { - this.collection; const collectionPackagePath = dirname(require.resolve(this.collection)); const collectionPath = join(collectionPackagePath, 'collection.json'); const collection = JSON.parse(readFileSync(collectionPath).toString()); From 8484742c071b335148d8383e7c5f5f87c3036aa7 Mon Sep 17 00:00:00 2001 From: Daniel Samson <12231216+daniel-samson@users.noreply.github.com> Date: Fri, 3 Feb 2023 00:22:54 +0000 Subject: [PATCH 4/4] Update lib/schematics/custom.collection.ts Co-authored-by: Micael Levi L. Cavalcante --- lib/schematics/custom.collection.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schematics/custom.collection.ts b/lib/schematics/custom.collection.ts index 17e3a13f6..3b345333c 100644 --- a/lib/schematics/custom.collection.ts +++ b/lib/schematics/custom.collection.ts @@ -14,7 +14,7 @@ export class CustomCollection extends AbstractCollection { public getSchematics(): Schematic[] { const collectionPackagePath = dirname(require.resolve(this.collection)); const collectionPath = join(collectionPackagePath, 'collection.json'); - const collection = JSON.parse(readFileSync(collectionPath).toString()); + const collection = JSON.parse(readFileSync(collectionPath, 'utf8')); const schematics = Object.entries(collection.schematics).map( ([name, value]) => { const schematic = value as CollectionSchematic;