1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.runCommand = void 0;
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 | const core_1 = require("@angular-devkit/core");
|
12 | const fs_1 = require("fs");
|
13 | const path_1 = require("path");
|
14 | const json_schema_1 = require("../utilities/json-schema");
|
15 | const analytics_1 = require("./analytics");
|
16 | const command_1 = require("./command");
|
17 | const parser = require("./parser");
|
18 |
|
19 | const standardCommands = {
|
20 | 'add': '../commands/add.json',
|
21 | 'analytics': '../commands/analytics.json',
|
22 | 'build': '../commands/build.json',
|
23 | 'deploy': '../commands/deploy.json',
|
24 | 'config': '../commands/config.json',
|
25 | 'doc': '../commands/doc.json',
|
26 | 'e2e': '../commands/e2e.json',
|
27 | 'make-this-awesome': '../commands/easter-egg.json',
|
28 | 'generate': '../commands/generate.json',
|
29 | 'help': '../commands/help.json',
|
30 | 'lint': '../commands/lint.json',
|
31 | 'new': '../commands/new.json',
|
32 | 'run': '../commands/run.json',
|
33 | 'serve': '../commands/serve.json',
|
34 | 'test': '../commands/test.json',
|
35 | 'update': '../commands/update.json',
|
36 | 'version': '../commands/version.json',
|
37 | 'xi18n': '../commands/xi18n.json',
|
38 | };
|
39 |
|
40 |
|
41 |
|
42 |
|
43 | async function _createAnalytics(workspace, skipPrompt = false) {
|
44 | let config = await analytics_1.getGlobalAnalytics();
|
45 |
|
46 | if (workspace && config) {
|
47 | const skipAnalytics = skipPrompt ||
|
48 | (process.env['NG_CLI_ANALYTICS'] &&
|
49 | (process.env['NG_CLI_ANALYTICS'].toLowerCase() === 'false' ||
|
50 | process.env['NG_CLI_ANALYTICS'] === '0'));
|
51 |
|
52 |
|
53 |
|
54 | if (!skipAnalytics && !(await analytics_1.hasWorkspaceAnalyticsConfiguration())) {
|
55 | await analytics_1.promptProjectAnalytics();
|
56 | }
|
57 | config = await analytics_1.getWorkspaceAnalytics();
|
58 | }
|
59 | const maybeSharedAnalytics = await analytics_1.getSharedAnalytics();
|
60 | if (config && maybeSharedAnalytics) {
|
61 | return new core_1.analytics.MultiAnalytics([config, maybeSharedAnalytics]);
|
62 | }
|
63 | else if (config) {
|
64 | return config;
|
65 | }
|
66 | else if (maybeSharedAnalytics) {
|
67 | return maybeSharedAnalytics;
|
68 | }
|
69 | else {
|
70 | return new core_1.analytics.NoopAnalytics();
|
71 | }
|
72 | }
|
73 | async function loadCommandDescription(name, path, registry) {
|
74 | const schemaPath = path_1.resolve(__dirname, path);
|
75 | const schemaContent = fs_1.readFileSync(schemaPath, 'utf-8');
|
76 | const schema = core_1.json.parseJson(schemaContent, core_1.JsonParseMode.Loose, { path: schemaPath });
|
77 | if (!core_1.isJsonObject(schema)) {
|
78 | throw new Error('Invalid command JSON loaded from ' + JSON.stringify(schemaPath));
|
79 | }
|
80 | return json_schema_1.parseJsonSchemaToCommandDescription(name, schemaPath, registry, schema);
|
81 | }
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 |
|
89 |
|
90 | async function runCommand(args, logger, workspace, commands = standardCommands, options = {}) {
|
91 |
|
92 | const registry = new core_1.schema.CoreSchemaRegistry([]);
|
93 | registry.registerUriHandler((uri) => {
|
94 | if (uri.startsWith('ng-cli://')) {
|
95 | const content = fs_1.readFileSync(path_1.join(__dirname, '..', uri.substr('ng-cli://'.length)), 'utf-8');
|
96 | return Promise.resolve(JSON.parse(content));
|
97 | }
|
98 | else {
|
99 | return null;
|
100 | }
|
101 | });
|
102 | let commandName = undefined;
|
103 | for (let i = 0; i < args.length; i++) {
|
104 | const arg = args[i];
|
105 | if (!arg.startsWith('-')) {
|
106 | commandName = arg;
|
107 | args.splice(i, 1);
|
108 | break;
|
109 | }
|
110 | }
|
111 | let description = null;
|
112 |
|
113 | if (!commandName) {
|
114 | if (args.length === 1 && args[0] === '--version') {
|
115 | commandName = 'version';
|
116 | }
|
117 | else {
|
118 | commandName = 'help';
|
119 | }
|
120 | if (!(commandName in commands)) {
|
121 | logger.error(core_1.tags.stripIndent `
|
122 | The "${commandName}" command seems to be disabled.
|
123 | This is an issue with the CLI itself. If you see this comment, please report it and
|
124 | provide your repository.
|
125 | `);
|
126 | return 1;
|
127 | }
|
128 | }
|
129 | if (commandName in commands) {
|
130 | description = await loadCommandDescription(commandName, commands[commandName], registry);
|
131 | }
|
132 | else {
|
133 | const commandNames = Object.keys(commands);
|
134 |
|
135 | if (commandName.length === 1) {
|
136 | commandNames.sort((a, b) => {
|
137 | const aMatch = a[0] === commandName;
|
138 | const bMatch = b[0] === commandName;
|
139 | if (aMatch && !bMatch) {
|
140 | return -1;
|
141 | }
|
142 | else if (!aMatch && bMatch) {
|
143 | return 1;
|
144 | }
|
145 | else {
|
146 | return 0;
|
147 | }
|
148 | });
|
149 | }
|
150 | for (const name of commandNames) {
|
151 | const aliasDesc = await loadCommandDescription(name, commands[name], registry);
|
152 | const aliases = aliasDesc.aliases;
|
153 | if (aliases && aliases.some(alias => alias === commandName)) {
|
154 | commandName = name;
|
155 | description = aliasDesc;
|
156 | break;
|
157 | }
|
158 | }
|
159 | }
|
160 | if (!description) {
|
161 | const commandsDistance = {};
|
162 | const name = commandName;
|
163 | const allCommands = Object.keys(commands).sort((a, b) => {
|
164 | if (!(a in commandsDistance)) {
|
165 | commandsDistance[a] = core_1.strings.levenshtein(a, name);
|
166 | }
|
167 | if (!(b in commandsDistance)) {
|
168 | commandsDistance[b] = core_1.strings.levenshtein(b, name);
|
169 | }
|
170 | return commandsDistance[a] - commandsDistance[b];
|
171 | });
|
172 | logger.error(core_1.tags.stripIndent `
|
173 | The specified command ("${commandName}") is invalid. For a list of available options,
|
174 | run "ng help".
|
175 |
|
176 | Did you mean "${allCommands[0]}"?
|
177 | `);
|
178 | return 1;
|
179 | }
|
180 | try {
|
181 | const parsedOptions = parser.parseArguments(args, description.options, logger);
|
182 | command_1.Command.setCommandMap(async () => {
|
183 | const map = {};
|
184 | for (const [name, path] of Object.entries(commands)) {
|
185 | map[name] = await loadCommandDescription(name, path, registry);
|
186 | }
|
187 | return map;
|
188 | });
|
189 | const analytics = options.analytics ||
|
190 | (await _createAnalytics(!!workspace.configFile, description.name === 'update'));
|
191 | const context = { workspace, analytics };
|
192 | const command = new description.impl(context, description, logger);
|
193 |
|
194 | let analyticsFlushPromise = Promise.resolve();
|
195 | setInterval(() => {
|
196 | analyticsFlushPromise = analyticsFlushPromise.then(() => analytics.flush());
|
197 | }, 1000);
|
198 | const result = await command.validateAndRun(parsedOptions);
|
199 |
|
200 | await analyticsFlushPromise.then(() => analytics.flush());
|
201 | return result;
|
202 | }
|
203 | catch (e) {
|
204 | if (e instanceof parser.ParseArgumentException) {
|
205 | logger.fatal('Cannot parse arguments. See below for the reasons.');
|
206 | logger.fatal(' ' + e.comments.join('\n '));
|
207 | return 1;
|
208 | }
|
209 | else {
|
210 | throw e;
|
211 | }
|
212 | }
|
213 | }
|
214 | exports.runCommand = runCommand;
|