Skip to content

Commit f7b2dd7

Browse files
feature: update schematics engine, refactor
1 parent 46f6f3e commit f7b2dd7

35 files changed

+436
-327
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
.idea/
22
.envrc
33
node_modules/
4+
.DS_Store
45

56
# output
67
lib/**/*.js

.npmignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.idea/
22
.gitignore
3+
.prettierrc
34
.travis.yml
45
Makefile
56

.prettierrc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"singleQuote": true,
3+
"trailingComma": "all"
4+
}

actions/info.action.ts

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ import { readFile } from 'fs';
33
import { platform, release } from 'os';
44
import osName = require('os-name');
55
import { join } from 'path';
6-
import { AbstractPackageManager, PackageManagerFactory } from '../lib/package-managers';
6+
import {
7+
AbstractPackageManager,
8+
PackageManagerFactory,
9+
} from '../lib/package-managers';
710
import { BANNER, messages } from '../lib/ui';
811
import { AbstractAction } from './abstract.action';
912

10-
interface PacakgeJsonDependencies {
13+
interface PackageJsonDependencies {
1114
[key: string]: string;
1215
}
1316

@@ -39,61 +42,74 @@ const displayPackageManagerVersion = async () => {
3942
const manager: AbstractPackageManager = await PackageManagerFactory.find();
4043
try {
4144
const version: string = await manager.version();
42-
console.info(`${ manager.name } Version :`, chalk.blue(version));
45+
console.info(`${manager.name} Version :`, chalk.blue(version));
4346
} catch {
44-
console.error(`${ manager.name } Version :`, chalk.red('Unknown'));
47+
console.error(`${manager.name} Version :`, chalk.red('Unknown'));
4548
}
4649
};
4750

4851
const displayNestInformation = async () => {
4952
console.info(chalk.green('[Nest Information]'));
5053
try {
51-
const dependencies: PacakgeJsonDependencies = await readProjectPackageJsonDependencies();
54+
const dependencies: PackageJsonDependencies = await readProjectPackageJsonDependencies();
5255
displayNestVersions(dependencies);
5356
} catch {
5457
console.error(chalk.red(messages.NEST_INFORMATION_PACKAGE_MANAGER_FAILED));
5558
}
5659
};
5760

58-
const readProjectPackageJsonDependencies = async (): Promise<PacakgeJsonDependencies> => {
59-
return new Promise<PacakgeJsonDependencies>((resolve, reject) => {
60-
readFile(join(process.cwd(), 'package.json'), (error: NodeJS.ErrnoException, buffer: Buffer) => {
61-
if (error !== undefined && error !== null) {
62-
reject(error);
63-
} else {
64-
resolve(JSON.parse(buffer.toString()).dependencies);
65-
}
66-
});
61+
const readProjectPackageJsonDependencies = async (): Promise<
62+
PackageJsonDependencies
63+
> => {
64+
return new Promise<PackageJsonDependencies>((resolve, reject) => {
65+
readFile(
66+
join(process.cwd(), 'package.json'),
67+
(error: NodeJS.ErrnoException, buffer: Buffer) => {
68+
if (error !== undefined && error !== null) {
69+
reject(error);
70+
} else {
71+
resolve(JSON.parse(buffer.toString()).dependencies);
72+
}
73+
},
74+
);
6775
});
6876
};
6977

70-
const displayNestVersions = (dependencies: PacakgeJsonDependencies) => {
71-
buildNestVersionsMessage(dependencies)
72-
.forEach((dependency) => console.info(dependency.name, chalk.blue(dependency.value)));
78+
const displayNestVersions = (dependencies: PackageJsonDependencies) => {
79+
buildNestVersionsMessage(dependencies).forEach(dependency =>
80+
console.info(dependency.name, chalk.blue(dependency.value)),
81+
);
7382
};
7483

75-
const buildNestVersionsMessage = (dependencies: PacakgeJsonDependencies): NestDependency[] => {
84+
const buildNestVersionsMessage = (
85+
dependencies: PackageJsonDependencies,
86+
): NestDependency[] => {
7687
const nestDependencies = collectNestDependencies(dependencies);
7788
return format(nestDependencies);
7889
};
7990

80-
const collectNestDependencies = (dependencies: PacakgeJsonDependencies): NestDependency[] => {
91+
const collectNestDependencies = (
92+
dependencies: PackageJsonDependencies,
93+
): NestDependency[] => {
8194
const nestDependencies: NestDependency[] = [];
82-
Object.keys(dependencies).forEach((key) => {
95+
Object.keys(dependencies).forEach(key => {
8396
if (key.indexOf('@nestjs') > -1) {
8497
nestDependencies.push({
85-
name: `${ key.replace(/@nestjs\//, '') } version`,
86-
value: dependencies[ key ],
98+
name: `${key.replace(/@nestjs\//, '')} version`,
99+
value: dependencies[key],
87100
});
88101
}
89102
});
90103
return nestDependencies;
91104
};
92105

93106
const format = (dependencies: NestDependency[]): NestDependency[] => {
94-
const sorted = dependencies.sort((dependencyA, dependencyB) => dependencyB.name.length - dependencyA.name.length);
95-
const length = sorted[ 0 ].name.length;
96-
sorted.forEach((dependency) => {
107+
const sorted = dependencies.sort(
108+
(dependencyA, dependencyB) =>
109+
dependencyB.name.length - dependencyA.name.length,
110+
);
111+
const length = sorted[0].name.length;
112+
sorted.forEach(dependency => {
97113
if (dependency.name.length < length) {
98114
dependency.name = rightPad(dependency.name, length);
99115
}

actions/new.action.ts

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import chalk from 'chalk';
33
import { execSync } from 'child_process';
44
import * as inquirer from 'inquirer';
55
import { Answers, PromptModule, Question } from 'inquirer';
6+
import { join } from 'path';
67
import { Input } from '../commands';
78
import {
89
AbstractPackageManager,
910
PackageManager,
1011
PackageManagerFactory,
1112
} from '../lib/package-managers';
1213
import { generateInput, generateSelect } from '../lib/questions/questions';
14+
import { GitRunner } from '../lib/runners/git.runner';
1315
import {
1416
AbstractCollection,
1517
Collection,
@@ -24,23 +26,42 @@ export class NewAction extends AbstractAction {
2426
const questions: Question[] = generateQuestionsForMissingInputs(inputs);
2527
const answers: Answers = await askForMissingInformation(questions);
2628
const args: Input[] = replaceInputMissingInformation(inputs, answers);
27-
await generateApplicationFiles(inputs, options);
29+
30+
const dryRunOption = options.find(option => option.name === 'dry-run');
31+
const isDryRunEnabled = dryRunOption && dryRunOption.value;
32+
await generateApplicationFiles(
33+
inputs,
34+
options,
35+
isDryRunEnabled as boolean,
36+
).catch(exit);
37+
2838
const shouldSkipInstall = options.some(
29-
(option) => option.name === 'skip-install' && option.value === true,
39+
option => option.name === 'skip-install' && option.value === true,
3040
);
41+
const projectDirectory = dasherize(inputs.find(
42+
input => input.name === 'name',
43+
)!.value as string);
44+
3145
if (!shouldSkipInstall) {
32-
await installPackages(inputs, options);
46+
await installPackages(
47+
options,
48+
isDryRunEnabled as boolean,
49+
projectDirectory,
50+
);
51+
}
52+
if (!isDryRunEnabled) {
53+
await initializeGitRepository(projectDirectory);
54+
printCollective();
3355
}
34-
printCollective();
3556
}
3657
}
3758

3859
const generateQuestionsForMissingInputs = (inputs: Input[]): Question[] => {
3960
return inputs
40-
.map((input) =>
61+
.map(input =>
4162
generateInput(input.name)(input.value)(generateDefaultAnswer(input.name)),
4263
)
43-
.filter((question) => question !== undefined) as Array<Question<Answers>>;
64+
.filter(question => question !== undefined) as Array<Question<Answers>>;
4465
};
4566

4667
const generateDefaultAnswer = (name: string) => {
@@ -64,8 +85,10 @@ const askForMissingInformation = async (
6485
console.info(messages.PROJECT_INFORMATION_START);
6586
console.info(messages.ADDITIONAL_INFORMATION);
6687
console.info();
88+
6789
const prompt: PromptModule = inquirer.createPromptModule();
6890
const answers: Answers = await prompt(questions);
91+
6992
console.info();
7093
console.info(messages.PROJECT_INFORMATION_COLLECTED);
7194
console.info();
@@ -77,13 +100,17 @@ const replaceInputMissingInformation = (
77100
answers: Answers,
78101
): Input[] => {
79102
return inputs.map(
80-
(input) =>
103+
input =>
81104
(input.value =
82105
input.value !== undefined ? input.value : answers[input.name]),
83106
);
84107
};
85108

86-
const generateApplicationFiles = async (args: Input[], options: Input[]) => {
109+
const generateApplicationFiles = async (
110+
args: Input[],
111+
options: Input[],
112+
isDryRunEnabled: boolean,
113+
) => {
87114
const collection: AbstractCollection = CollectionFactory.create(
88115
Collection.NESTJS,
89116
);
@@ -92,9 +119,7 @@ const generateApplicationFiles = async (args: Input[], options: Input[]) => {
92119
);
93120
await collection.execute('application', schematicOptions);
94121

95-
const dryRunOption = options.find((option) => option.name === 'dry-run');
96-
const isDryRunEnabled = dryRunOption && dryRunOption.value;
97-
if (isDryRunEnabled) {
122+
if (!isDryRunEnabled) {
98123
await generateConfigurationFile(args, options, collection);
99124
}
100125
console.info();
@@ -148,15 +173,15 @@ const mapConfigurationSchematicOptions = (
148173
);
149174
};
150175

151-
const installPackages = async (inputs: Input[], options: Input[]) => {
152-
const installDirectory = dasherize(inputs.find(
153-
(input) => input.name === 'name',
154-
)!.value as string);
155-
const dryRunMode = options.find((option) => option.name === 'dry-run')!
156-
.value as boolean;
176+
const installPackages = async (
177+
options: Input[],
178+
dryRunMode: boolean,
179+
installDirectory: string,
180+
) => {
157181
const inputPackageManager: string = options.find(
158-
(option) => option.name === 'package-manager',
182+
option => option.name === 'package-manager',
159183
)!.value as string;
184+
160185
let packageManager: AbstractPackageManager;
161186
if (dryRunMode) {
162187
console.info();
@@ -198,6 +223,13 @@ const askForPackageManager = async (): Promise<Answers> => {
198223
return await prompt(questions);
199224
};
200225

226+
const initializeGitRepository = async (dir: string) => {
227+
const runner = new GitRunner();
228+
await runner.run('init', true, join(process.cwd(), dir)).catch(() => {
229+
console.error(chalk.red(messages.GIT_INITIALIZATION_ERROR));
230+
});
231+
};
232+
201233
const printCollective = () => {
202234
const dim = print('dim');
203235
const yellow = print('yellow');
@@ -239,3 +271,5 @@ export const retrieveCols = () => {
239271
return defaultCols;
240272
}
241273
};
274+
275+
export const exit = () => process.exit(1);

actions/update.action.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ import { AbstractAction } from './abstract.action';
66

77
export class UpdateAction extends AbstractAction {
88
public async handle(inputs: Input[], options: Input[]) {
9-
const force = options.find((option) => option.name === 'force') as Input;
10-
const tag = options.find((option) => option.name === 'tag') as Input;
9+
const force = options.find(option => option.name === 'force') as Input;
10+
const tag = options.find(option => option.name === 'tag') as Input;
1111

1212
if (force.value && tag.value === undefined) {
1313
console.error(chalk.red('You should specify a tag when force update.'));
1414
} else {
15-
const manager = new NestDependencyManager(await PackageManagerFactory.find());
15+
const manager = new NestDependencyManager(
16+
await PackageManagerFactory.find(),
17+
);
1618
await manager.update(force.value as boolean, tag.value as string);
1719
}
1820
}

commands/command.loader.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import chalk from 'chalk';
12
import { CommanderStatic } from 'commander';
23
import { GenerateAction, InfoAction, NewAction } from '../actions';
34
import { AddAction } from '../actions/add.action';
@@ -15,5 +16,15 @@ export class CommandLoader {
1516
new InfoCommand(new InfoAction()).load(program);
1617
new UpdateCommand(new UpdateAction()).load(program);
1718
new AddCommand(new AddAction()).load(program);
19+
20+
this.handleInvalidCommand(program);
21+
}
22+
23+
private static handleInvalidCommand(program: CommanderStatic) {
24+
program.on('command:*', () => {
25+
console.error(chalk.red('Invalid command: %s'), program.args.join(' '));
26+
console.log('See --help for a list of available commands.');
27+
process.exit(1);
28+
});
1829
}
1930
}

commands/new.command.ts

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,34 @@ export class NewCommand extends AbstractCommand {
1515
'Allow to specify package manager to skip package-manager selection.',
1616
)
1717
.option('-l, --language [language]', 'Specify ts or js language to use')
18-
.action(async (name: string, description: string, version: string, author: string, command: Command) => {
19-
const options: Input[] = [];
20-
options.push({ name: 'dry-run', value: !!command.dryRun });
21-
options.push({ name: 'skip-install', value: !!command.skipInstall });
22-
options.push({ name: 'package-manager', value: command.packageManager });
23-
options.push({ name: 'language', value: !!command.language ? command.language : 'ts' });
24-
const inputs: Input[] = [];
25-
inputs.push({ name: 'name', value: name });
26-
inputs.push({ name: 'description', value: description });
27-
inputs.push({ name: 'version', value: version });
28-
inputs.push({ name: 'author', value: author });
29-
await this.action.handle(inputs, options);
30-
});
18+
.action(
19+
async (
20+
name: string,
21+
description: string,
22+
version: string,
23+
author: string,
24+
command: Command,
25+
) => {
26+
const options: Input[] = [];
27+
options.push({ name: 'dry-run', value: !!command.dryRun });
28+
options.push({ name: 'skip-install', value: !!command.skipInstall });
29+
options.push({
30+
name: 'package-manager',
31+
value: command.packageManager,
32+
});
33+
options.push({
34+
name: 'language',
35+
value: !!command.language ? command.language : 'ts',
36+
});
37+
38+
const inputs: Input[] = [];
39+
inputs.push({ name: 'name', value: name });
40+
inputs.push({ name: 'description', value: description });
41+
inputs.push({ name: 'version', value: version });
42+
inputs.push({ name: 'author', value: author });
43+
44+
await this.action.handle(inputs, options);
45+
},
46+
);
3147
}
3248
}

commands/update.command.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ export class UpdateCommand extends AbstractCommand {
99
.alias('u')
1010
.description('Update @nestjs dependencies.')
1111
.option('-f, --force', 'Call for upgrading instead of updating.')
12-
.option('-t, --tag <tag>', 'Call for upgrading to latest | beta | rc | next tag.')
12+
.option(
13+
'-t, --tag <tag>',
14+
'Call for upgrading to latest | beta | rc | next tag.',
15+
)
1316
.action(async (command: Command) => {
1417
const options: Input[] = [];
1518
options.push({ name: 'force', value: !!command.force });

0 commit comments

Comments
 (0)