Skip to content

Commit

Permalink
Merge pull request #180 from nestjs/opencollective
Browse files Browse the repository at this point in the history
release(patch): 5.4.1 bugfixes & opencollective statements
  • Loading branch information
kamilmysliwiec authored Sep 17, 2018
2 parents 6f008f0 + 8b9b818 commit ff0cff2
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 57 deletions.
6 changes: 4 additions & 2 deletions actions/generate.action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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));
}
}
};

Expand Down
158 changes: 125 additions & 33 deletions actions/new.action.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
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 { generateInput, generateSelect } from '../lib/questions/questions';
import { AbstractCollection, Collection, CollectionFactory, SchematicOption } from '../lib/schematics';
import { messages } from '../lib/ui';
import { emojis, messages } from '../lib/ui';
import { AbstractAction } from './abstract.action';

export class NewAction extends AbstractAction {
Expand All @@ -15,16 +16,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<Question<Answers>>;
};

Expand All @@ -42,7 +48,9 @@ const generateDefaultAnswer = (name: string) => {
}
};

const askForMissingInformation = async (questions: Question[]): Promise<Answers> => {
const askForMissingInformation = async (
questions: Question[],
): Promise<Answers> => {
console.info();
console.info(messages.PROJECT_INFORMATION_START);
console.info(messages.ADDITIONAL_INFORMATION);
Expand All @@ -55,49 +63,86 @@ const askForMissingInformation = async (questions: Question[]): Promise<Answers>
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();
Expand All @@ -110,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();
Expand All @@ -120,13 +167,58 @@ const installPackages = async (inputs: Input[], options: Input[]) => {

const selectPackageManager = async (): Promise<AbstractPackageManager> => {
const answers: Answers = await askForPackageManager();
return PackageManagerFactory.create(answers[ 'package-manager' ]);
return PackageManagerFactory.create(answers['package-manager']);
};

const askForPackageManager = async (): Promise<Answers> => {
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;
}
};
2 changes: 2 additions & 0 deletions lib/ui/emojis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
};
48 changes: 30 additions & 18 deletions lib/ui/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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?`,
};
17 changes: 13 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -30,9 +31,10 @@
},
"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",
"commander": "^2.15.1",
Expand All @@ -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:"
}
}
}

0 comments on commit ff0cff2

Please sign in to comment.