From af97525613b1c02d8a9068b1187bbfb3c255d1bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= Date: Thu, 6 Sep 2018 13:18:41 +0200 Subject: [PATCH 1/3] chore: add opencollective statements --- actions/new.action.ts | 167 +++++++++++++++++++++++++++++++++--------- lib/ui/emojis.ts | 2 + package.json | 11 ++- 3 files changed, 145 insertions(+), 35 deletions(-) diff --git a/actions/new.action.ts b/actions/new.action.ts index 79a1d3ebb..7e2490706 100644 --- a/actions/new.action.ts +++ b/actions/new.action.ts @@ -1,12 +1,22 @@ import { dasherize } from '@angular-devkit/core/src/utils/strings'; import chalk from 'chalk'; +import { execSync } from 'child_process'; import * as inquirer from 'inquirer'; import { Answers, PromptModule, Question } from 'inquirer'; import { Input } from '../commands'; -import { AbstractPackageManager, PackageManager, PackageManagerFactory } from '../lib/package-managers'; +import { + AbstractPackageManager, + PackageManager, + PackageManagerFactory, +} from '../lib/package-managers'; import { generateInput, generateSelect } from '../lib/questions/questions'; -import { AbstractCollection, Collection, CollectionFactory, SchematicOption } from '../lib/schematics'; -import { messages } from '../lib/ui'; +import { + AbstractCollection, + Collection, + CollectionFactory, + SchematicOption, +} from '../lib/schematics'; +import { emojis, messages } from '../lib/ui'; import { AbstractAction } from './abstract.action'; export class NewAction extends AbstractAction { @@ -15,16 +25,21 @@ export class NewAction extends AbstractAction { const answers: Answers = await askForMissingInformation(questions); const args: Input[] = replaceInputMissingInformation(inputs, answers); await generateApplicationFiles(inputs, options); - const shouldSkipInstall = options.some((option) => option.name === 'skip-install' && option.value === true); + const shouldSkipInstall = options.some( + (option) => option.name === 'skip-install' && option.value === true, + ); if (!shouldSkipInstall) { await installPackages(inputs, options); } + printCollective(); } } const generateQuestionsForMissingInputs = (inputs: Input[]): Question[] => { return inputs - .map((input) => generateInput(input.name)(input.value)(generateDefaultAnswer(input.name))) + .map((input) => + generateInput(input.name)(input.value)(generateDefaultAnswer(input.name)), + ) .filter((question) => question !== undefined) as Array>; }; @@ -42,7 +57,9 @@ const generateDefaultAnswer = (name: string) => { } }; -const askForMissingInformation = async (questions: Question[]): Promise => { +const askForMissingInformation = async ( + questions: Question[], +): Promise => { console.info(); console.info(messages.PROJECT_INFORMATION_START); console.info(messages.ADDITIONAL_INFORMATION); @@ -55,49 +72,86 @@ const askForMissingInformation = async (questions: Question[]): Promise return answers; }; -const replaceInputMissingInformation = (inputs: Input[], answers: Answers): Input[] => { - return inputs.map((input) => input.value = input.value !== undefined ? input.value : answers[ input.name ]); +const replaceInputMissingInformation = ( + inputs: Input[], + answers: Answers, +): Input[] => { + return inputs.map( + (input) => + (input.value = + input.value !== undefined ? input.value : answers[input.name]), + ); }; const generateApplicationFiles = async (args: Input[], options: Input[]) => { - const collection: AbstractCollection = CollectionFactory.create(Collection.NESTJS); - const schematicOptions: SchematicOption[] = mapSchematicOptions(args.concat(options)); + const collection: AbstractCollection = CollectionFactory.create( + Collection.NESTJS, + ); + const schematicOptions: SchematicOption[] = mapSchematicOptions( + args.concat(options), + ); await collection.execute('application', schematicOptions); await generateConfigurationFile(args, options, collection); console.info(); }; const mapSchematicOptions = (options: Input[]): SchematicOption[] => { - return options.reduce((schematicOptions: SchematicOption[], option: Input) => { - if (option.name !== 'skip-install' && option.value !== 'package-manager') { - schematicOptions.push(new SchematicOption(option.name, option.value)); - } - return schematicOptions; - }, []); + return options.reduce( + (schematicOptions: SchematicOption[], option: Input) => { + if ( + option.name !== 'skip-install' && + option.value !== 'package-manager' + ) { + schematicOptions.push(new SchematicOption(option.name, option.value)); + } + return schematicOptions; + }, + [], + ); }; -const generateConfigurationFile = async (args: Input[], options: Input[], collection: AbstractCollection) => { - const schematicOptions: SchematicOption[] = mapConfigurationSchematicOptions(args.concat(options)); - schematicOptions.push(new SchematicOption('collection', '@nestjs/schematics')); +const generateConfigurationFile = async ( + args: Input[], + options: Input[], + collection: AbstractCollection, +) => { + const schematicOptions: SchematicOption[] = mapConfigurationSchematicOptions( + args.concat(options), + ); + schematicOptions.push( + new SchematicOption('collection', '@nestjs/schematics'), + ); await collection.execute('configuration', schematicOptions); }; -const mapConfigurationSchematicOptions = (inputs: Input[]): SchematicOption[] => { - return inputs.reduce((schematicsOptions: SchematicOption[], option: Input) => { - if (option.name === 'name') { - schematicsOptions.push(new SchematicOption('project', dasherize(option.value as string))); - } - if (option.name === 'language') { - schematicsOptions.push(new SchematicOption(option.name, option.value)); - } - return schematicsOptions; - }, []); +const mapConfigurationSchematicOptions = ( + inputs: Input[], +): SchematicOption[] => { + return inputs.reduce( + (schematicsOptions: SchematicOption[], option: Input) => { + if (option.name === 'name') { + schematicsOptions.push( + new SchematicOption('project', dasherize(option.value as string)), + ); + } + if (option.name === 'language') { + schematicsOptions.push(new SchematicOption(option.name, option.value)); + } + return schematicsOptions; + }, + [], + ); }; const installPackages = async (inputs: Input[], options: Input[]) => { - const installDirectory = dasherize(inputs.find((input) => input.name === 'name')!.value as string); - const dryRunMode = options.find((option) => option.name === 'dry-run')!.value as boolean; - const inputPackageManager: string = options.find((option) => option.name === 'package-manager')!.value as string; + const installDirectory = dasherize(inputs.find( + (input) => input.name === 'name', + )!.value as string); + const dryRunMode = options.find((option) => option.name === 'dry-run')! + .value as boolean; + const inputPackageManager: string = options.find( + (option) => option.name === 'package-manager', + )!.value as string; let packageManager: AbstractPackageManager; if (dryRunMode) { console.info(); @@ -120,13 +174,58 @@ const installPackages = async (inputs: Input[], options: Input[]) => { const selectPackageManager = async (): Promise => { const answers: Answers = await askForPackageManager(); - return PackageManagerFactory.create(answers[ 'package-manager' ]); + return PackageManagerFactory.create(answers['package-manager']); }; const askForPackageManager = async (): Promise => { const questions: Question[] = [ - generateSelect('package-manager')(messages.PACKAGE_MANAGER_QUESTION)([ PackageManager.NPM, PackageManager.YARN ]), + generateSelect('package-manager')(messages.PACKAGE_MANAGER_QUESTION)([ + PackageManager.NPM, + PackageManager.YARN, + ]), ]; const prompt = inquirer.createPromptModule(); return await prompt(questions); }; + +const printCollective = () => { + const dim = print('dim'); + const yellow = print('yellow'); + const emptyLine = print(); + + emptyLine(); + yellow(`Thanks for installing Nest ${emojis.PRAY}`); + dim('Please consider donating to our open collective'); + dim('to help us maintain this package.'); + emptyLine(); + emptyLine(); + print()( + `${chalk.bold(`${emojis.WINE} Donate:`)} ${chalk.underline( + 'https://opencollective.com/nest', + )}`, + ); + emptyLine(); +}; + +const print = (color: string | null = null) => (str = '') => { + const terminalCols = retrieveCols(); + const strLength = str.replace(/\u001b\[[0-9]{2}m/g, '').length; + const leftPaddingLength = Math.floor((terminalCols - strLength) / 2); + const leftPadding = ' '.repeat(Math.max(leftPaddingLength, 0)); + if (color) { + str = (chalk as any)[color](str); + } + console.log(leftPadding, str); +}; + +export const retrieveCols = () => { + const defaultCols = 80; + try { + const terminalCols = execSync('tput cols', { + stdio: ['pipe', 'pipe', 'ignore'], + }); + return parseInt(terminalCols.toString(), 10) || defaultCols; + } catch { + return defaultCols; + } +}; diff --git a/lib/ui/emojis.ts b/lib/ui/emojis.ts index d18cfa1ac..4c4d1d9d2 100644 --- a/lib/ui/emojis.ts +++ b/lib/ui/emojis.ts @@ -16,4 +16,6 @@ export const emojis = { POINT_RIGHT: get('point_right'), ZAP: get('zap'), BOOM: get('boom'), + PRAY: get('pray'), + WINE: get('wine_glass'), }; diff --git a/package.json b/package.json index 2a427da83..c0e5ba4d9 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "lint": "./node_modules/tslint/bin/tslint -p .", "start": "node bin/nest.js", "test": "jest --config test/jest-config.json", - "test:dev": "jest --config test/jest-config.json --watchAll" + "test:dev": "jest --config test/jest-config.json --watchAll", + "postinstall": "opencollective" }, "repository": { "type": "git", @@ -33,6 +34,7 @@ "@angular-devkit/core": "^0.4.9", "@angular-devkit/schematics-cli": "^0.4.9", "@nestjs/schematics": "^5.6.1", + "@nuxtjs/opencollective": "^0.1.0", "@types/jest": "^22.2.3", "chalk": "^2.4.1", "commander": "^2.15.1", @@ -52,5 +54,12 @@ "ts-jest": "^22.4.6", "tslint": "^5.10.0", "typescript": "^2.8.3" + }, + "collective": { + "type": "opencollective", + "url": "https://opencollective.com/nest", + "donation": { + "text": "Become a partner:" + } } } From 3fb32f18de3f2e221fad2d98cf0f1d5960f1bc91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= Date: Sun, 16 Sep 2018 21:35:13 +0200 Subject: [PATCH 2/3] packages: update to latest devtools --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index c0e5ba4d9..00b555d11 100644 --- a/package.json +++ b/package.json @@ -31,9 +31,9 @@ }, "homepage": "https://github.com/nestjs/nest-cli#readme", "dependencies": { - "@angular-devkit/core": "^0.4.9", - "@angular-devkit/schematics-cli": "^0.4.9", - "@nestjs/schematics": "^5.6.1", + "@angular-devkit/core": "^0.8.1", + "@angular-devkit/schematics-cli": "^0.8.1", + "@nestjs/schematics": "^5.7.1", "@nuxtjs/opencollective": "^0.1.0", "@types/jest": "^22.2.3", "chalk": "^2.4.1", From e9bad6ae71526d95caad6a836fba0b64db7149ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= Date: Sun, 16 Sep 2018 21:35:32 +0200 Subject: [PATCH 3/3] bugfix: add error is nil check --- actions/generate.action.ts | 6 +++-- actions/new.action.ts | 17 ++++---------- lib/ui/messages.ts | 48 ++++++++++++++++++++++++-------------- 3 files changed, 39 insertions(+), 32 deletions(-) diff --git a/actions/generate.action.ts b/actions/generate.action.ts index d3578b635..e0977f07e 100644 --- a/actions/generate.action.ts +++ b/actions/generate.action.ts @@ -3,7 +3,7 @@ import { Input } from '../commands'; import { Configuration, ConfigurationLoader } from '../lib/configuration'; import { NestConfigurationLoader } from '../lib/configuration/nest-configuration.loader'; import { FileSystemReader } from '../lib/readers'; -import { AbstractCollection, Collection, CollectionFactory, SchematicOption } from '../lib/schematics'; +import { AbstractCollection, CollectionFactory, SchematicOption } from '../lib/schematics'; import { AbstractAction } from './abstract.action'; export class GenerateAction extends AbstractAction { @@ -24,7 +24,9 @@ const generateFiles = async (inputs: Input[]) => { } await collection.execute(schematicInput.value as string, schematicOptions); } catch (error) { - console.error(chalk.red(error.message)); + if (error && error.message) { + console.error(chalk.red(error.message)); + } } }; diff --git a/actions/new.action.ts b/actions/new.action.ts index 7e2490706..41c05ee2f 100644 --- a/actions/new.action.ts +++ b/actions/new.action.ts @@ -4,18 +4,9 @@ import { execSync } from 'child_process'; import * as inquirer from 'inquirer'; import { Answers, PromptModule, Question } from 'inquirer'; import { Input } from '../commands'; -import { - AbstractPackageManager, - PackageManager, - PackageManagerFactory, -} from '../lib/package-managers'; +import { AbstractPackageManager, PackageManager, PackageManagerFactory } from '../lib/package-managers'; import { generateInput, generateSelect } from '../lib/questions/questions'; -import { - AbstractCollection, - Collection, - CollectionFactory, - SchematicOption, -} from '../lib/schematics'; +import { AbstractCollection, Collection, CollectionFactory, SchematicOption } from '../lib/schematics'; import { emojis, messages } from '../lib/ui'; import { AbstractAction } from './abstract.action'; @@ -164,7 +155,9 @@ const installPackages = async (inputs: Input[], options: Input[]) => { packageManager = PackageManagerFactory.create(inputPackageManager); await packageManager.install(installDirectory); } catch (error) { - console.error(chalk.red(error.message)); + if (error && error.message) { + console.error(chalk.red(error.message)); + } } } else { packageManager = await selectPackageManager(); diff --git a/lib/ui/messages.ts b/lib/ui/messages.ts index 5a301e9a7..60efc2ed4 100644 --- a/lib/ui/messages.ts +++ b/lib/ui/messages.ts @@ -2,25 +2,37 @@ import chalk from 'chalk'; import { emojis } from './emojis'; export const messages = { - PROJECT_INFORMATION_START: `${ emojis.ZAP } Creating your Nest project...`, - ADDITIONAL_INFORMATION: `${ emojis.RAISED_HANDS } We have to collect additional information:`, - PROJECT_INFORMATION_COLLECTED: `${ emojis.BOOM } Thank you for your time!`, + PROJECT_INFORMATION_START: `${emojis.ZAP} Creating your Nest project...`, + ADDITIONAL_INFORMATION: `${ + emojis.RAISED_HANDS + } We have to collect additional information:`, + PROJECT_INFORMATION_COLLECTED: `${emojis.BOOM} Thank you for your time!`, DRY_RUN_MODE: 'Command has been executed in the dry mode, nothing changed!', - RUNNER_EXECUTION_ERROR: - (command: string) => `${ emojis.SCREAM } Failed to execute command: ${ command }`, - PACKAGE_MANAGER_QUESTION: `Which package manager would you ${ emojis.HEART } to use?`, - PACKAGE_MANAGER_INSTALLATION_IN_PROGRESS: - `Take ${ emojis.COFFEE } or ${ emojis.BEER } during the packages installation process and enjoy your time`, - PACKAGE_MANAGER_UPDATE_IN_PROGRESS: - `Take ${ emojis.COFFEE } or ${ emojis.BEER } during the packages update process and enjoy your time`, - PACKAGE_MANAGER_UPGRADE_IN_PROGRESS: - `Take ${ emojis.COFFEE } or ${ emojis.BEER } during the packages upgrade process and enjoy your time`, - PACKAGE_MANAGER_INSTALLATION_SUCCEED: - (name: string) => `${ emojis.ROCKET } Successfully created project ${chalk.green(name)}`, - GET_STARTED_INFORMATION: `${ emojis.POINT_RIGHT } Get started with the following commands:`, + RUNNER_EXECUTION_ERROR: (command: string) => + `Failed to execute command: ${command}`, + PACKAGE_MANAGER_QUESTION: `Which package manager would you ${ + emojis.HEART + } to use?`, + PACKAGE_MANAGER_INSTALLATION_IN_PROGRESS: `Take ${emojis.COFFEE} or ${ + emojis.BEER + } during the packages installation process and enjoy your time`, + PACKAGE_MANAGER_UPDATE_IN_PROGRESS: `Take ${emojis.COFFEE} or ${ + emojis.BEER + } during the packages update process and enjoy your time`, + PACKAGE_MANAGER_UPGRADE_IN_PROGRESS: `Take ${emojis.COFFEE} or ${ + emojis.BEER + } during the packages upgrade process and enjoy your time`, + PACKAGE_MANAGER_INSTALLATION_SUCCEED: (name: string) => + `${emojis.ROCKET} Successfully created project ${chalk.green(name)}`, + GET_STARTED_INFORMATION: `${ + emojis.POINT_RIGHT + } Get started with the following commands:`, CHANGE_DIR_COMMAND: (name: string) => `$ cd ${name}`, START_COMMAND: '$ npm run start', - PACKAGE_MANAGER_INSTALLATION_FAILED: `${ emojis.SCREAM } Packages installation failed, see above`, - NEST_INFORMATION_PACKAGE_MANAGER_FAILED: - `${ emojis.SMIRK } cannot read your project package.json file, are you inside your project directory?`, + PACKAGE_MANAGER_INSTALLATION_FAILED: `${ + emojis.SCREAM + } Packages installation failed, see above`, + NEST_INFORMATION_PACKAGE_MANAGER_FAILED: `${ + emojis.SMIRK + } cannot read your project package.json file, are you inside your project directory?`, };