UNPKG

8.7 kBJavaScriptView Raw
1"use strict";
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4 return new (P || (P = Promise))(function (resolve, reject) {
5 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8 step((generator = generator.apply(thisArg, _arguments || [])).next());
9 });
10};
11Object.defineProperty(exports, "__esModule", { value: true });
12exports.exit = exports.retrieveCols = exports.NewAction = void 0;
13const chalk = require("chalk");
14const child_process_1 = require("child_process");
15const fs = require("fs");
16const inquirer = require("inquirer");
17const path_1 = require("path");
18const defaults_1 = require("../lib/configuration/defaults");
19const package_managers_1 = require("../lib/package-managers");
20const questions_1 = require("../lib/questions/questions");
21const git_runner_1 = require("../lib/runners/git.runner");
22const schematics_1 = require("../lib/schematics");
23const ui_1 = require("../lib/ui");
24const formatting_1 = require("../lib/utils/formatting");
25const abstract_action_1 = require("./abstract.action");
26class NewAction extends abstract_action_1.AbstractAction {
27 handle(inputs, options) {
28 return __awaiter(this, void 0, void 0, function* () {
29 const directoryOption = options.find((option) => option.name === 'directory');
30 const dryRunOption = options.find((option) => option.name === 'dry-run');
31 const isDryRunEnabled = dryRunOption && dryRunOption.value;
32 yield askForMissingInformation(inputs, options);
33 yield generateApplicationFiles(inputs, options).catch(exports.exit);
34 const shouldSkipInstall = options.some((option) => option.name === 'skip-install' && option.value === true);
35 const shouldSkipGit = options.some((option) => option.name === 'skip-git' && option.value === true);
36 const projectDirectory = getProjectDirectory(getApplicationNameInput(inputs), directoryOption);
37 if (!shouldSkipInstall) {
38 yield installPackages(options, isDryRunEnabled, projectDirectory);
39 }
40 if (!isDryRunEnabled) {
41 if (!shouldSkipGit) {
42 yield initializeGitRepository(projectDirectory);
43 yield createGitIgnoreFile(projectDirectory);
44 }
45 printCollective();
46 }
47 process.exit(0);
48 });
49 }
50}
51exports.NewAction = NewAction;
52const getApplicationNameInput = (inputs) => inputs.find((input) => input.name === 'name');
53const getPackageManagerInput = (inputs) => inputs.find((options) => options.name === 'packageManager');
54const getProjectDirectory = (applicationName, directoryOption) => {
55 return ((directoryOption && directoryOption.value) ||
56 (0, formatting_1.normalizeToKebabOrSnakeCase)(applicationName.value));
57};
58const askForMissingInformation = (inputs, options) => __awaiter(void 0, void 0, void 0, function* () {
59 console.info(ui_1.MESSAGES.PROJECT_INFORMATION_START);
60 console.info();
61 const prompt = inquirer.createPromptModule();
62 const nameInput = getApplicationNameInput(inputs);
63 if (!nameInput.value) {
64 const message = 'What name would you like to use for the new project?';
65 const questions = [(0, questions_1.generateInput)('name', message)('nest-app')];
66 const answers = yield prompt(questions);
67 replaceInputMissingInformation(inputs, answers);
68 }
69 const packageManagerInput = getPackageManagerInput(options);
70 if (!packageManagerInput.value) {
71 const answers = yield askForPackageManager();
72 replaceInputMissingInformation(options, answers);
73 }
74});
75const replaceInputMissingInformation = (inputs, answers) => {
76 return inputs.map((input) => (input.value =
77 input.value !== undefined ? input.value : answers[input.name]));
78};
79const generateApplicationFiles = (args, options) => __awaiter(void 0, void 0, void 0, function* () {
80 const collectionName = options.find((option) => option.name === 'collection' && option.value != null).value;
81 const collection = schematics_1.CollectionFactory.create(collectionName || schematics_1.Collection.NESTJS);
82 const schematicOptions = mapSchematicOptions(args.concat(options));
83 yield collection.execute('application', schematicOptions);
84 console.info();
85});
86const mapSchematicOptions = (options) => {
87 return options.reduce((schematicOptions, option) => {
88 if (option.name !== 'skip-install') {
89 schematicOptions.push(new schematics_1.SchematicOption(option.name, option.value));
90 }
91 return schematicOptions;
92 }, []);
93};
94const installPackages = (options, dryRunMode, installDirectory) => __awaiter(void 0, void 0, void 0, function* () {
95 const inputPackageManager = getPackageManagerInput(options).value;
96 let packageManager;
97 if (dryRunMode) {
98 console.info();
99 console.info(chalk.green(ui_1.MESSAGES.DRY_RUN_MODE));
100 console.info();
101 return;
102 }
103 try {
104 packageManager = package_managers_1.PackageManagerFactory.create(inputPackageManager);
105 yield packageManager.install(installDirectory, inputPackageManager);
106 }
107 catch (error) {
108 if (error && error.message) {
109 console.error(chalk.red(error.message));
110 }
111 }
112});
113const askForPackageManager = () => __awaiter(void 0, void 0, void 0, function* () {
114 const questions = [
115 (0, questions_1.generateSelect)('packageManager')(ui_1.MESSAGES.PACKAGE_MANAGER_QUESTION)([
116 package_managers_1.PackageManager.NPM,
117 package_managers_1.PackageManager.YARN,
118 package_managers_1.PackageManager.PNPM,
119 ]),
120 ];
121 const prompt = inquirer.createPromptModule();
122 return yield prompt(questions);
123});
124const initializeGitRepository = (dir) => __awaiter(void 0, void 0, void 0, function* () {
125 const runner = new git_runner_1.GitRunner();
126 yield runner.run('init', true, (0, path_1.join)(process.cwd(), dir)).catch(() => {
127 console.error(chalk.red(ui_1.MESSAGES.GIT_INITIALIZATION_ERROR));
128 });
129});
130/**
131 * Write a file `.gitignore` in the root of the newly created project.
132 * `.gitignore` available in `@nestjs/schematics` cannot be published to
133 * NPM (needs to be investigated).
134 *
135 * @param dir Relative path to the project.
136 * @param content (optional) Content written in the `.gitignore`.
137 *
138 * @return Resolves when succeeds, or rejects with any error from `fn.writeFile`.
139 */
140const createGitIgnoreFile = (dir, content) => {
141 const fileContent = content || defaults_1.defaultGitIgnore;
142 const filePath = (0, path_1.join)(process.cwd(), dir, '.gitignore');
143 if (fileExists(filePath)) {
144 return;
145 }
146 return fs.promises.writeFile(filePath, fileContent);
147};
148const printCollective = () => {
149 const dim = print('dim');
150 const yellow = print('yellow');
151 const emptyLine = print();
152 emptyLine();
153 yellow(`Thanks for installing Nest ${ui_1.EMOJIS.PRAY}`);
154 dim('Please consider donating to our open collective');
155 dim('to help us maintain this package.');
156 emptyLine();
157 emptyLine();
158 print()(`${chalk.bold(`${ui_1.EMOJIS.WINE} Donate:`)} ${chalk.underline('https://opencollective.com/nest')}`);
159 emptyLine();
160};
161const print = (color = null) => (str = '') => {
162 const terminalCols = (0, exports.retrieveCols)();
163 const strLength = str.replace(/\u001b\[[0-9]{2}m/g, '').length;
164 const leftPaddingLength = Math.floor((terminalCols - strLength) / 2);
165 const leftPadding = ' '.repeat(Math.max(leftPaddingLength, 0));
166 if (color) {
167 str = chalk[color](str);
168 }
169 console.log(leftPadding, str);
170};
171const retrieveCols = () => {
172 const defaultCols = 80;
173 try {
174 const terminalCols = (0, child_process_1.execSync)('tput cols', {
175 stdio: ['pipe', 'pipe', 'ignore'],
176 });
177 return parseInt(terminalCols.toString(), 10) || defaultCols;
178 }
179 catch (_a) {
180 return defaultCols;
181 }
182};
183exports.retrieveCols = retrieveCols;
184const fileExists = (path) => {
185 try {
186 fs.accessSync(path);
187 return true;
188 }
189 catch (err) {
190 if (err.code === 'ENOENT') {
191 return false;
192 }
193 throw err;
194 }
195};
196const exit = () => process.exit(1);
197exports.exit = exit;