ember-cli 4.0.0 → 4.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/.github/workflows/ci.yml +4 -4
  2. package/CHANGELOG.md +17 -2
  3. package/blueprints/app/files/package.json +2 -2
  4. package/docs/build/data.json +3 -3
  5. package/lib/models/host-info-cache.js +3 -5
  6. package/lib/models/per-bundle-addon-cache/index.js +2 -3
  7. package/lib/utilities/get-lang-arg.js +45 -45
  8. package/package.json +25 -25
  9. package/.github/ISSUE_TEMPLATE.md +0 -12
  10. package/.github/dependabot.yml +0 -15
  11. package/.github/workflows/coverage.yml +0 -31
  12. package/docs/analytics.md +0 -44
  13. package/docs/architecture.md +0 -316
  14. package/docs/assets/architecture/Ember-CLI architecture.png +0 -0
  15. package/docs/assets/architecture/Ember-CLI architecture.xml +0 -1
  16. package/docs/assets/architecture/README.md +0 -5
  17. package/docs/brocfile-transition.md +0 -46
  18. package/docs/build/api.js +0 -44
  19. package/docs/build/assets/css/external-small.png +0 -0
  20. package/docs/build/assets/css/logo.png +0 -0
  21. package/docs/build/assets/css/main.css +0 -555
  22. package/docs/build/assets/favicon.ico +0 -0
  23. package/docs/build/assets/img/spinner.gif +0 -0
  24. package/docs/build/assets/index.html +0 -10
  25. package/docs/build/assets/js/api-filter.js +0 -56
  26. package/docs/build/assets/js/api-list.js +0 -255
  27. package/docs/build/assets/js/api-search.js +0 -98
  28. package/docs/build/assets/js/apidocs.js +0 -376
  29. package/docs/build/assets/js/yui-prettify.js +0 -17
  30. package/docs/build/assets/vendor/prettify/CHANGES.html +0 -130
  31. package/docs/build/assets/vendor/prettify/COPYING +0 -202
  32. package/docs/build/assets/vendor/prettify/README.html +0 -203
  33. package/docs/build/assets/vendor/prettify/prettify-min.css +0 -1
  34. package/docs/build/assets/vendor/prettify/prettify-min.js +0 -1
  35. package/docs/build/classes/Addon.html +0 -4318
  36. package/docs/build/classes/AmdTransformAddon.html +0 -202
  37. package/docs/build/classes/Blueprint.html +0 -4796
  38. package/docs/build/classes/Builder.html +0 -611
  39. package/docs/build/classes/CLI.html +0 -810
  40. package/docs/build/classes/Command.html +0 -1655
  41. package/docs/build/classes/DefaultPackager.html +0 -202
  42. package/docs/build/classes/EmberAddon.html +0 -2207
  43. package/docs/build/classes/EmberApp.html +0 -2225
  44. package/docs/build/classes/HardwareInfo.html +0 -620
  45. package/docs/build/classes/HistorySupportAddon.html +0 -203
  46. package/docs/build/classes/Instrumentation.html +0 -695
  47. package/docs/build/classes/NodeModulesList.html +0 -460
  48. package/docs/build/classes/NpmTask.html +0 -333
  49. package/docs/build/classes/PackageInfo.html +0 -1390
  50. package/docs/build/classes/PackageInfoCache.html +0 -963
  51. package/docs/build/classes/PerBundleAddonCache {.html +0 -1010
  52. package/docs/build/classes/Project.html +0 -2083
  53. package/docs/build/classes/ServeFilesAddon.html +0 -260
  54. package/docs/build/classes/TestsServerAddon.html +0 -203
  55. package/docs/build/classes/WatcherAddon.html +0 -204
  56. package/docs/build/classes/WindowsSymlinkChecker.html +0 -1505
  57. package/docs/build/files/lib_broccoli_default-packager.js.html +0 -1426
  58. package/docs/build/files/lib_broccoli_ember-addon.js.html +0 -159
  59. package/docs/build/files/lib_broccoli_ember-app.js.html +0 -1913
  60. package/docs/build/files/lib_cli_cli.js.html +0 -417
  61. package/docs/build/files/lib_models_addon-info.js.html +0 -112
  62. package/docs/build/files/lib_models_addon.js.html +0 -1866
  63. package/docs/build/files/lib_models_blueprint.js.html +0 -1678
  64. package/docs/build/files/lib_models_builder.js.html +0 -417
  65. package/docs/build/files/lib_models_command.js.html +0 -804
  66. package/docs/build/files/lib_models_hardware-info.js.html +0 -479
  67. package/docs/build/files/lib_models_host-info-cache.js.html +0 -428
  68. package/docs/build/files/lib_models_installation-checker.js.html +0 -181
  69. package/docs/build/files/lib_models_instantiate-addons.js.html +0 -191
  70. package/docs/build/files/lib_models_instrumentation.js.html +0 -433
  71. package/docs/build/files/lib_models_package-info-cache_index.js.html +0 -793
  72. package/docs/build/files/lib_models_package-info-cache_node-modules-list.js.html +0 -208
  73. package/docs/build/files/lib_models_package-info-cache_package-info.js.html +0 -661
  74. package/docs/build/files/lib_models_per-bundle-addon-cache_addon-proxy.js.html +0 -252
  75. package/docs/build/files/lib_models_per-bundle-addon-cache_index.js.html +0 -485
  76. package/docs/build/files/lib_models_per-bundle-addon-cache_target-instance.js.html +0 -108
  77. package/docs/build/files/lib_models_project.js.html +0 -913
  78. package/docs/build/files/lib_models_task.js.html +0 -117
  79. package/docs/build/files/lib_tasks_build-watch.js.html +0 -157
  80. package/docs/build/files/lib_tasks_npm-task.js.html +0 -463
  81. package/docs/build/files/lib_tasks_serve.js.html +0 -207
  82. package/docs/build/files/lib_tasks_server_middleware_broccoli-serve-files_index.js.html +0 -127
  83. package/docs/build/files/lib_tasks_server_middleware_broccoli-watcher_index.js.html +0 -158
  84. package/docs/build/files/lib_tasks_server_middleware_history-support_index.js.html +0 -181
  85. package/docs/build/files/lib_tasks_server_middleware_tests-server_index.js.html +0 -171
  86. package/docs/build/files/lib_tasks_test-server.js.html +0 -167
  87. package/docs/build/files/lib_tasks_transforms_amd_index.js.html +0 -143
  88. package/docs/build/files/lib_utilities_ember-app-utils.js.html +0 -292
  89. package/docs/build/files/lib_utilities_insert-into-file.js.html +0 -219
  90. package/docs/build/files/lib_utilities_is-lazy-engine.js.html +0 -125
  91. package/docs/build/files/lib_utilities_is-yarn-project.js.html +0 -120
  92. package/docs/build/files/lib_utilities_valid-project-name.js.html +0 -142
  93. package/docs/build/files/lib_utilities_will-interrupt-process.js.html +0 -290
  94. package/docs/build/files/lib_utilities_windows-admin.js.html +0 -230
  95. package/docs/build/index.html +0 -125
  96. package/docs/build/modules/ember-cli.html +0 -152
  97. package/docs/build/modules/is-lazy-engine.html +0 -106
  98. package/docs/build-concurrency.md +0 -15
  99. package/docs/build-pipeline-debugging.md +0 -33
  100. package/docs/code-coverage.md +0 -14
  101. package/docs/error-propagation.md +0 -136
  102. package/docs/experiments.md +0 -53
  103. package/docs/node-support.md +0 -43
  104. package/docs/perf-guide.md +0 -250
  105. package/docs/project_version_preprocessor.js +0 -8
  106. package/docs/sourcemaps.md +0 -60
  107. package/docs/yuidoc.json +0 -13
@@ -1,804 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <title>lib/models/command.js - ember-cli</title>
6
- <link rel="stylesheet" href="../assets/vendor/prettify/prettify-min.css">
7
- <link rel="stylesheet" href="../assets/css/main.css" id="site_styles">
8
- <script src="https://cdnjs.cloudflare.com/ajax/libs/yui/3.18.0/yui/yui-min.js"></script>
9
- </head>
10
- <body class="yui3-skin-sam">
11
-
12
- <div id="doc">
13
- <div class="yui3-g">
14
- <div id="sidebar" class="yui3-u">
15
- <div class="logo">
16
- <a href="../index.html">
17
- <img src="https://ember-cli.com/assets/images/ember-cli-logo-small-dark.png">
18
- </a>
19
- </div>
20
-
21
- <div id="modules" class="sidebox">
22
- <div class="hd">
23
- <h2 class="no-toc">Modules</h2>
24
- </div>
25
- <div class="bd">
26
- <ul>
27
- <li><a href="../modules/ember-cli.html">ember-cli</a>
28
- </li>
29
- <li><a href="../modules/is-lazy-engine.html">is-lazy-engine</a>
30
- </li>
31
- </ul>
32
- </div>
33
- </div>
34
-
35
- <div id="classes" class="sidebox">
36
- <div class="hd">
37
- <h2 class="no-toc">Classes</h2>
38
- </div>
39
- <div class="bd">
40
- <ul>
41
- <li><a href="../classes/Addon.html">Addon</a></li>
42
- <li><a href="../classes/AmdTransformAddon.html">AmdTransformAddon</a></li>
43
- <li><a href="../classes/Blueprint.html">Blueprint</a></li>
44
- <li><a href="../classes/Builder.html">Builder</a></li>
45
- <li><a href="../classes/CLI.html">CLI</a></li>
46
- <li><a href="../classes/Command.html">Command</a></li>
47
- <li><a href="../classes/DefaultPackager.html">DefaultPackager</a></li>
48
- <li><a href="../classes/EmberAddon.html">EmberAddon</a></li>
49
- <li><a href="../classes/EmberApp.html">EmberApp</a></li>
50
- <li><a href="../classes/HardwareInfo.html">HardwareInfo</a></li>
51
- <li><a href="../classes/HistorySupportAddon.html">HistorySupportAddon</a></li>
52
- <li><a href="../classes/Instrumentation.html">Instrumentation</a></li>
53
- <li><a href="../classes/NodeModulesList.html">NodeModulesList</a></li>
54
- <li><a href="../classes/NpmTask.html">NpmTask</a></li>
55
- <li><a href="../classes/PackageInfo.html">PackageInfo</a></li>
56
- <li><a href="../classes/PackageInfoCache.html">PackageInfoCache</a></li>
57
- <li><a href="../classes/PerBundleAddonCache {.html">PerBundleAddonCache {</a></li>
58
- <li><a href="../classes/Project.html">Project</a></li>
59
- <li><a href="../classes/ServeFilesAddon.html">ServeFilesAddon</a></li>
60
- <li><a href="../classes/TestsServerAddon.html">TestsServerAddon</a></li>
61
- <li><a href="../classes/WatcherAddon.html">WatcherAddon</a></li>
62
- <li><a href="../classes/WindowsSymlinkChecker.html">WindowsSymlinkChecker</a></li>
63
- </ul>
64
- </div>
65
- </div>
66
-
67
-
68
-
69
-
70
-
71
- <div class="version-info">
72
- Version: 4.0.0-release-b4cbb1029f
73
- </div>
74
-
75
- </div>
76
-
77
- <div id="main" class="yui3-u">
78
- <div class="content"><div class="title">
79
- <h1 class="file-name">lib/models/command.js</h1>
80
- </div>
81
-
82
- <pre class="code prettyprint linenums">
83
- &#x27;use strict&#x27;;
84
-
85
- const nopt = require(&#x27;nopt&#x27;);
86
- const chalk = require(&#x27;chalk&#x27;);
87
- const path = require(&#x27;path&#x27;);
88
- const isGitRepo = require(&#x27;is-git-url&#x27;);
89
- const camelize = require(&#x27;ember-cli-string-utils&#x27;).camelize;
90
- const getCallerFile = require(&#x27;get-caller-file&#x27;);
91
- const printCommand = require(&#x27;../utilities/print-command&#x27;);
92
- const _ = require(&#x27;ember-cli-lodash-subset&#x27;);
93
- const EOL = require(&#x27;os&#x27;).EOL;
94
- const CoreObject = require(&#x27;core-object&#x27;);
95
- const logger = require(&#x27;heimdalljs-logger&#x27;)(&#x27;ember-cli:command&#x27;);
96
- const WatchDetector = require(&#x27;watch-detector&#x27;);
97
- const SilentError = require(&#x27;silent-error&#x27;);
98
- const execSync = require(&#x27;child_process&#x27;).execSync;
99
- const fs = require(&#x27;fs&#x27;);
100
- const isYarnProject = require(&#x27;../utilities/is-yarn-project&#x27;);
101
-
102
- let cache = {};
103
-
104
- let allowedWorkOptions = {
105
- insideProject: true,
106
- outsideProject: true,
107
- everywhere: true,
108
- };
109
-
110
- path.name = &#x27;Path&#x27;;
111
- // extend nopt to recognize &#x27;gitUrl&#x27; as a type
112
- nopt.typeDefs.gitUrl = {
113
- type: &#x27;gitUrl&#x27;,
114
- validate(data, k, val) {
115
- if (isGitRepo(val)) {
116
- data[k] = val;
117
- return true;
118
- } else {
119
- return false;
120
- }
121
- },
122
- };
123
-
124
- /**
125
- * The base class for all CLI commands.
126
- *
127
- * @module ember-cli
128
- * @class Command
129
- * @constructor
130
- * @extends CoreObject
131
- */
132
- let Command = CoreObject.extend({
133
- /**
134
- * The description of what this command does.
135
- *
136
- * @final
137
- * @property description
138
- * @type String
139
- */
140
- description: null,
141
-
142
- /**
143
- * Does this command work everywhere or just inside or outside of projects.
144
- *
145
- * Possible values:
146
- *
147
- * - &#x60;insideProject&#x60;
148
- * - &#x60;outsideProject&#x60;
149
- * - &#x60;everywhere&#x60;
150
- *
151
- * @final
152
- * @property works
153
- * @type String
154
- * @default &#x60;insideProject&#x60;
155
- */
156
- works: &#x27;insideProject&#x27;,
157
-
158
- _printableProperties: [&#x27;name&#x27;, &#x27;description&#x27;, &#x27;aliases&#x27;, &#x27;works&#x27;, &#x27;availableOptions&#x27;, &#x27;anonymousOptions&#x27;],
159
-
160
- init() {
161
- this._super.apply(this, arguments);
162
-
163
- /**
164
- * @final
165
- * @property isWithinProject
166
- * @type Boolean
167
- */
168
- this.isWithinProject = this.project.isEmberCLIProject();
169
-
170
- /**
171
- * The name of the command.
172
- *
173
- * @final
174
- * @property name
175
- * @type String
176
- * @example &#x60;new&#x60; or &#x60;generate&#x60;
177
- */
178
- this.name = this.name || path.basename(getCallerFile(), &#x27;.js&#x27;);
179
-
180
- logger.info(&#x27;initialize: name: %s, name: %s&#x27;, this.name);
181
-
182
- /**
183
- * An array of aliases for the command
184
- *
185
- * @final
186
- * @property aliases
187
- * @type Array
188
- * @example &#x60;[&#x27;g&#x27;]&#x60; for the &#x60;generate&#x60; command
189
- */
190
- this.aliases = this.aliases || [];
191
-
192
- // Works Property
193
- if (!allowedWorkOptions[this.works]) {
194
- throw new Error(
195
- &#x60;The &quot;${this.name}&quot; command&#x27;s works field has to be either &quot;everywhere&quot;, &quot;insideProject&quot; or &quot;outsideProject&quot;.&#x60;
196
- );
197
- }
198
-
199
- /**
200
- * An array of available options for the command
201
- *
202
- * @final
203
- * @property availableOptions
204
- * @type Array
205
- * @example
206
- * &#x60;&#x60;&#x60;js
207
- * availableOptions: [
208
- * { name: &#x27;dry-run&#x27;, type: Boolean, default: false, aliases: [&#x27;d&#x27;] },
209
- * { name: &#x27;verbose&#x27;, type: Boolean, default: false, aliases: [&#x27;v&#x27;] },
210
- * { name: &#x27;blueprint&#x27;, type: String, default: &#x27;app&#x27;, aliases: [&#x27;b&#x27;] },
211
- * { name: &#x27;skip-npm&#x27;, type: Boolean, default: false, aliases: [&#x27;sn&#x27;] },
212
- * { name: &#x27;skip-bower&#x27;, type: Boolean, default: false, aliases: [&#x27;sb&#x27;] },
213
- * { name: &#x27;skip-git&#x27;, type: Boolean, default: false, aliases: [&#x27;sg&#x27;] },
214
- * { name: &#x27;directory&#x27;, type: String , aliases: [&#x27;dir&#x27;] }
215
- * ],
216
- * &#x60;&#x60;&#x60;
217
- */
218
- this.availableOptions = this.availableOptions || [];
219
-
220
- /**
221
- * An array of anonymous options for the command
222
- *
223
- * @final
224
- * @property anonymousOptions
225
- * @type Array
226
- * @example
227
- * &#x60;&#x60;&#x60;js
228
- * anonymousOptions: [
229
- * &#x27;&lt;blueprint&gt;&#x27;
230
- * ],
231
- * &#x60;&#x60;&#x60;
232
- */
233
- this.anonymousOptions = this.anonymousOptions || [];
234
- },
235
-
236
- /**
237
- Registers options with command. This method provides the ability to extend or override command options.
238
- Expects an object containing anonymousOptions or availableOptions, which it will then merge with
239
- existing availableOptions before building the optionsAliases which are used to define shorthands.
240
-
241
- @method registerOptions
242
- @param {Object} options
243
- */
244
- registerOptions(options) {
245
- let extendedAvailableOptions = (options &amp;&amp; options.availableOptions) || [];
246
- let extendedAnonymousOptions = (options &amp;&amp; options.anonymousOptions) || [];
247
-
248
- this.anonymousOptions = _.union(this.anonymousOptions.slice(0), extendedAnonymousOptions);
249
-
250
- // merge any availableOptions
251
- this.availableOptions = _.union(this.availableOptions.slice(0), extendedAvailableOptions);
252
-
253
- let optionKeys = _.uniq(_.map(this.availableOptions, &#x27;name&#x27;));
254
-
255
- optionKeys.map(this.mergeDuplicateOption.bind(this));
256
-
257
- this.optionsAliases = this.optionsAliases || {};
258
-
259
- this.availableOptions.map(this.validateOption.bind(this));
260
- },
261
-
262
- /**
263
- * Called when command is interrupted from outside, e.g. ctrl+C or process kill
264
- * Can be used to cleanup artifacts produced by command and control process exit code
265
- *
266
- * @method onInterrupt
267
- * @return {Promise|undefined} if rejected promise then result of promise will be used as an exit code
268
- */
269
- onInterrupt() {
270
- if (this._currentTask) {
271
- return this._currentTask.onInterrupt();
272
- } else {
273
- // interrupt all external commands which don&#x27;t use &#x60;runTask()&#x60; with an error
274
-
275
- // eslint-disable-next-line no-process-exit
276
- process.exit(1);
277
- }
278
- },
279
-
280
- _env(/* name */) {
281
- return {
282
- ui: this.ui,
283
- analytics: this.analytics,
284
- project: this.project,
285
- testing: this.testing,
286
- settings: this.settings,
287
- };
288
- },
289
-
290
- /**
291
- * Looks up for the task and runs
292
- * It also keeps the reference for the current active task
293
- * Keeping reference for the current task allows to cleanup task on interruption
294
- *
295
- * @private
296
- * @method runTask
297
- * @throws {Error} when no task found
298
- * @throws {Error} on attempt to run concurrent task
299
- * @param {string} name Task name from the tasks registry. Should be capitalized
300
- * @param {object} options
301
- * @return {Promise} Task run
302
- */
303
- runTask(name, options) {
304
- if (this._currentTask) {
305
- throw new Error(&#x60;Concurrent tasks are not supported&#x60;);
306
- }
307
-
308
- logger.info(&#x60;\&#x60;${this.name}\&#x60; command running \&#x60;${name}\&#x60; task&#x60;);
309
-
310
- let Task = this.tasks[name];
311
- if (!Task) {
312
- throw new Error(&#x60;Unknown task &quot;${name}&quot;&#x60;);
313
- }
314
-
315
- let task = new Task(this._env(name));
316
-
317
- this._currentTask = task;
318
-
319
- return Promise.resolve()
320
- .then(() =&gt; task.run(options))
321
- .catch((error) =&gt; {
322
- logger.info(&#x60;An error occurred running \&#x60;${name}\&#x60; from the \&#x60;${this.name}\&#x60; command.&#x60;, error.stack);
323
-
324
- throw error;
325
- })
326
- .finally(() =&gt; {
327
- delete this._currentTask;
328
- });
329
- },
330
-
331
- /**
332
- Hook for extending a command before it is run in the cli.run command.
333
- Most common use case would be to extend availableOptions.
334
- @method beforeRun
335
- @return {Promise|null}
336
- */
337
- beforeRun() {},
338
-
339
- /**
340
- @method validateAndRun
341
- @return {Promise}
342
- */
343
- validateAndRun(args) {
344
- return new Promise((resolve, reject) =&gt; {
345
- let commandOptions = this.parseArgs(args);
346
- // if the help option was passed, resolve with &#x27;callHelp&#x27; to call help command
347
- if (commandOptions &amp;&amp; (commandOptions.options.help || commandOptions.options.h)) {
348
- logger.info(&#x60;${this.name} called with help option&#x60;);
349
- return resolve(&#x27;callHelp&#x27;);
350
- }
351
-
352
- this.analytics.track({
353
- name: &#x27;ember &#x27;,
354
- message: this.name,
355
- });
356
-
357
- if (commandOptions === null) {
358
- return reject();
359
- }
360
-
361
- if (this.works === &#x27;outsideProject&#x27; &amp;&amp; this.isWithinProject) {
362
- throw new SilentError(&#x60;You cannot use the ${chalk.green(this.name)} command inside an ember-cli project.&#x60;);
363
- }
364
-
365
- if (this.works === &#x27;insideProject&#x27;) {
366
- if (!this.project.hasDependencies()) {
367
- if (!this.isWithinProject &amp;&amp; !this.project.isEmberCLIAddon()) {
368
- throw new SilentError(
369
- &#x60;You have to be inside an ember-cli project to use the ${chalk.green(this.name)} command.&#x60;
370
- );
371
- }
372
-
373
- let installInstuction = &#x27;&#x60;npm install&#x60;&#x27;;
374
- if (isYarnProject(this.project.root)) {
375
- installInstuction = &#x27;&#x60;yarn install&#x60;&#x27;;
376
- }
377
- throw new SilentError(
378
- &#x60;Required packages are missing, run ${installInstuction} from this directory to install them.&#x60;
379
- );
380
- }
381
- }
382
-
383
- let detector = new WatchDetector({
384
- ui: this.ui,
385
- childProcess: { execSync },
386
- fs,
387
- watchmanSupportsPlatform: /^win/.test(process.platform),
388
- cache,
389
- root: this.project.root,
390
- });
391
-
392
- let options = commandOptions.options;
393
-
394
- if (this.hasOption(&#x27;watcher&#x27;)) {
395
- // do stuff to try and provide a good experience when it comes to file watching
396
- let watchPreference = detector.findBestWatcherOption(options);
397
- this.project._watchmanInfo = watchPreference.watchmanInfo;
398
- options.watcher = watchPreference.watcher;
399
- }
400
- resolve(this.run(options, commandOptions.args));
401
- });
402
- },
403
-
404
- /**
405
- Reports if the given command has a command line option by a given name
406
-
407
- @method hasOption
408
- @param {String} name
409
- @return {Boolean}
410
- */
411
- hasOption(name) {
412
- for (let i = 0; i &lt; this.availableOptions.length; i++) {
413
- if (this.availableOptions[i].name === name) {
414
- return true;
415
- }
416
- }
417
- return false;
418
- },
419
-
420
- /**
421
- Merges any options with duplicate keys in the availableOptions array.
422
- Used primarily by registerOptions.
423
- @method mergeDuplicateOption
424
- @param {String} key
425
- @return {Object}
426
- */
427
- mergeDuplicateOption(key) {
428
- let duplicateOptions, mergedOption, mergedAliases;
429
- // get duplicates to merge
430
- duplicateOptions = _.filter(this.availableOptions, { name: key });
431
-
432
- if (duplicateOptions.length &gt; 1) {
433
- // TODO: warn on duplicates and overwriting
434
- mergedAliases = [];
435
-
436
- _.map(duplicateOptions, &#x27;aliases&#x27;).map((alias) =&gt; {
437
- alias.map((a) =&gt; {
438
- mergedAliases.push(a);
439
- });
440
- });
441
-
442
- // merge duplicate options
443
- mergedOption = Object.assign.apply(null, duplicateOptions);
444
-
445
- // replace aliases with unique aliases
446
- mergedOption.aliases = _.uniqBy(mergedAliases, (alias) =&gt; {
447
- if (typeof alias === &#x27;object&#x27;) {
448
- return alias[Object.keys(alias)[0]];
449
- }
450
- return alias;
451
- });
452
-
453
- // remove duplicates from options
454
- this.availableOptions = _.reject(this.availableOptions, { name: key });
455
- this.availableOptions.push(mergedOption);
456
- }
457
- return this.availableOptions;
458
- },
459
-
460
- /**
461
- Normalizes option, filling in implicit values
462
- @method normalizeOption
463
- @param {Object} option
464
- @return {Object}
465
- */
466
- normalizeOption(option) {
467
- option.key = camelize(option.name);
468
- option.required = option.required || false;
469
- return option;
470
- },
471
-
472
- /**
473
- Assigns option
474
- @method assignOption
475
- @param {Object} option
476
- @param {Object} parsedOptions
477
- @param {Object} commandOptions
478
- @return {Boolean}
479
- */
480
- assignOption(option, parsedOptions, commandOptions) {
481
- let isValid = isValidParsedOption(option, parsedOptions[option.name]);
482
- if (isValid) {
483
- if (parsedOptions[option.name] === undefined) {
484
- if (option.default !== undefined) {
485
- commandOptions[option.key] = option.default;
486
- }
487
-
488
- if (this.settings[option.name] !== undefined) {
489
- commandOptions[option.key] = this.settings[option.name];
490
- } else if (this.settings[option.key] !== undefined) {
491
- commandOptions[option.key] = this.settings[option.key];
492
- }
493
- } else {
494
- commandOptions[option.key] = parsedOptions[option.name];
495
- delete parsedOptions[option.name];
496
- }
497
- } else {
498
- this.ui.writeLine(
499
- &#x60;The specified command ${chalk.green(this.name)} requires the option ${chalk.green(option.name)}.&#x60;
500
- );
501
- }
502
- return isValid;
503
- },
504
-
505
- /**
506
- Validates option
507
- @method validateOption
508
- @param {Object} option
509
- @return {Boolean}
510
- */
511
- validateOption(option) {
512
- let parsedAliases;
513
-
514
- if (!option.name || !option.type) {
515
- throw new Error(&#x60;The command &quot;${this.name}&quot; has an option without the required type and name fields.&#x60;);
516
- }
517
-
518
- if (option.name !== option.name.toLowerCase()) {
519
- throw new Error(&#x60;The &quot;${option.name}&quot; option&#x27;s name of the &quot;${this.name}&quot; command contains a capital letter.&#x60;);
520
- }
521
-
522
- this.normalizeOption(option);
523
-
524
- if (option.aliases) {
525
- parsedAliases = option.aliases.map(this.parseAlias.bind(this, option));
526
- return parsedAliases.map(this.assignAlias.bind(this, option)).indexOf(false) === -1;
527
- }
528
- return false;
529
- },
530
-
531
- /**
532
- Parses alias for an option and adds it to optionsAliases
533
- @method parseAlias
534
- @param {Object} option
535
- @param {Object|String} alias
536
- @return {Object}
537
- */
538
- parseAlias(option, alias) {
539
- let aliasType = typeof alias;
540
- let key, value, aliasValue;
541
-
542
- if (isValidAlias(alias, option.type)) {
543
- if (aliasType === &#x27;string&#x27;) {
544
- key = alias;
545
- value = [&#x60;--${option.name}&#x60;];
546
- } else if (aliasType === &#x27;object&#x27;) {
547
- key = Object.keys(alias)[0];
548
- value = [&#x60;--${option.name}&#x60;, alias[key]];
549
- }
550
- } else {
551
- if (Array.isArray(alias)) {
552
- aliasType = &#x27;array&#x27;;
553
- aliasValue = alias.join(&#x27;,&#x27;);
554
- } else {
555
- aliasValue = alias;
556
- try {
557
- aliasValue = JSON.parse(alias);
558
- } catch (e) {
559
- const logger = require(&#x27;heimdalljs-logger&#x27;)(&#x27;ember-cli/models/command&#x27;);
560
- logger.error(e);
561
- }
562
- }
563
- throw new Error(
564
- &#x60;The &quot;${aliasValue}&quot; [type:${aliasType}] alias is not an acceptable value. &#x60; +
565
- &#x60;It must be a string or single key object with a string value (for example, &quot;value&quot; or { &quot;key&quot; : &quot;value&quot; }).&#x60;
566
- );
567
- }
568
-
569
- return {
570
- key,
571
- value,
572
- original: alias,
573
- };
574
- },
575
-
576
- /**
577
- * @method assignAlias
578
- * @param option
579
- * @param alias
580
- * @return {Boolean}
581
- */
582
- assignAlias(option, alias) {
583
- let isValid = this.validateAlias(option, alias);
584
-
585
- if (isValid) {
586
- this.optionsAliases[alias.key] = alias.value;
587
- }
588
- return isValid;
589
- },
590
-
591
- /**
592
- Validates alias value
593
- @method validateAlias
594
- @param {Object} alias
595
- @return {Boolean}
596
- */
597
- validateAlias(option, alias) {
598
- let key = alias.key;
599
- let value = alias.value;
600
-
601
- if (!this.optionsAliases[key]) {
602
- return true;
603
- } else {
604
- if (value[0] !== this.optionsAliases[key][0]) {
605
- throw new SilentError(
606
- &#x60;The &quot;${key}&quot; alias is already in use by the &quot;${this.optionsAliases[key][0]}&quot; option &#x60; +
607
- &#x60;and cannot be used by the &quot;${value[0]}&quot; option. Please use a different alias.&#x60;
608
- );
609
- } else if (value[1] !== this.optionsAliases[key][1]) {
610
- this.ui.writeLine(chalk.yellow(&#x60;The &quot;${key}&quot; alias cannot be overridden. Please use a different alias.&#x60;));
611
- // delete offending alias from options
612
- let index = this.availableOptions.indexOf(option);
613
- let aliasIndex = this.availableOptions[index].aliases.indexOf(alias.original);
614
- if (this.availableOptions[index].aliases[aliasIndex]) {
615
- // first one wins
616
- this.availableOptions[index].aliases = [this.availableOptions[index].aliases[0]];
617
- }
618
- }
619
- return false;
620
- }
621
- },
622
-
623
- /**
624
- Parses command arguments and processes
625
- @method parseArgs
626
- @param {Object} commandArgs
627
- @return {Object|null}
628
- */
629
- parseArgs(commandArgs) {
630
- let knownOpts = {}; // Parse options
631
- let commandOptions = {};
632
- let parsedOptions;
633
-
634
- this.registerOptions();
635
-
636
- let assembleAndValidateOption = function (option) {
637
- return this.assignOption(option, parsedOptions, commandOptions);
638
- };
639
-
640
- let validateParsed = function (key) {
641
- // ignore &#x27;argv&#x27;, &#x27;h&#x27;, and &#x27;help&#x27;
642
- if (!(key in commandOptions) &amp;&amp; key !== &#x27;argv&#x27; &amp;&amp; key !== &#x27;h&#x27; &amp;&amp; key !== &#x27;help&#x27;) {
643
- this.ui.writeLine(
644
- chalk.yellow(
645
- &#x60;The option &#x27;--${key}&#x27; is not registered with the &#x27;${this.name}&#x27; command. &#x60; +
646
- &#x60;Run \&#x60;ember ${this.name} --help\&#x60; for a list of supported options.&#x60;
647
- )
648
- );
649
- }
650
- if (typeof parsedOptions[key] !== &#x27;object&#x27;) {
651
- commandOptions[camelize(key)] = parsedOptions[key];
652
- }
653
- };
654
-
655
- this.availableOptions.forEach((option) =&gt; {
656
- if (typeof option.type !== &#x27;string&#x27;) {
657
- knownOpts[option.name] = option.type;
658
- } else if (option.type === &#x27;Path&#x27;) {
659
- knownOpts[option.name] = path;
660
- } else {
661
- knownOpts[option.name] = String;
662
- }
663
- });
664
-
665
- parsedOptions = nopt(knownOpts, this.optionsAliases, commandArgs, 0);
666
-
667
- if (!this.availableOptions.every(assembleAndValidateOption.bind(this))) {
668
- return null;
669
- }
670
-
671
- Object.keys(parsedOptions).map(validateParsed.bind(this));
672
-
673
- return {
674
- options: _.defaults(commandOptions, this.settings),
675
- args: parsedOptions.argv.remain,
676
- };
677
- },
678
-
679
- /**
680
- * @method run
681
- * @param commandArgs
682
- */
683
- run(commandArgs) {
684
- throw new Error(&#x60;command must implement run${commandArgs.toString()}&#x60;);
685
- },
686
-
687
- _printCommand: printCommand,
688
-
689
- /**
690
- Prints basic help for the command.
691
-
692
- Basic help looks like this:
693
-
694
- ember generate &lt;blueprint&gt; &lt;options...&gt;
695
- Generates new code from blueprints
696
- aliases: g
697
- --dry-run (Default: false)
698
- --verbose (Default: false)
699
-
700
- The default implementation is designed to cover all bases
701
- but may be overridden if necessary.
702
-
703
- @method printBasicHelp
704
- */
705
- printBasicHelp() {
706
- // ember command-name
707
- let output;
708
- if (this.isRoot) {
709
- output = &#x60;Usage: ${this.name}&#x60;;
710
- } else {
711
- output = &#x60;ember ${this.name}&#x60;;
712
- }
713
-
714
- output += this._printCommand();
715
- output += EOL;
716
-
717
- return output;
718
- },
719
-
720
- /**
721
- Prints detailed help for the command.
722
-
723
- The default implementation is no-op and should be overridden
724
- for each command where further help text is required.
725
-
726
- @method printDetailedHelp
727
- */
728
- printDetailedHelp() {},
729
-
730
- /**
731
- * @method getJson
732
- * @param {Object} options
733
- * @return {Object}
734
- */
735
- getJson(options) {
736
- let json = {};
737
-
738
- this.registerOptions(options);
739
- this._printableProperties.forEach((key) =&gt; (json[key] = this[key]));
740
-
741
- if (this.addAdditionalJsonForHelp) {
742
- this.addAdditionalJsonForHelp(json, options);
743
- }
744
-
745
- return json;
746
- },
747
- });
748
-
749
- /*
750
- Validates options parsed by nopt
751
- */
752
- function isValidParsedOption(option, parsedOption) {
753
- // option.name didn&#x27;t parse
754
- if (parsedOption === undefined) {
755
- // no default
756
- if (option.default === undefined) {
757
- if (option.required) {
758
- return false;
759
- }
760
- }
761
- }
762
-
763
- return true;
764
- }
765
-
766
- /*
767
- Validates alias. Must be a string or single key object
768
- */
769
- function isValidAlias(alias, expectedType) {
770
- let type = typeof alias;
771
- let value, valueType;
772
- if (type === &#x27;string&#x27;) {
773
- return true;
774
- } else if (type === &#x27;object&#x27;) {
775
- // no arrays, no multi-key objects
776
- if (!Array.isArray(alias) &amp;&amp; Object.keys(alias).length === 1) {
777
- value = alias[Object.keys(alias)[0]];
778
- valueType = typeof value;
779
- if (!Array.isArray(expectedType)) {
780
- if (valueType === expectedType.name.toLowerCase()) {
781
- return true;
782
- }
783
- } else if (expectedType.indexOf(value) &gt; -1) {
784
- return true;
785
- }
786
- }
787
- }
788
-
789
- return false;
790
- }
791
-
792
- module.exports = Command;
793
-
794
- </pre>
795
-
796
- </div>
797
- </div>
798
- </div>
799
- </div>
800
- <script src="../assets/vendor/prettify/prettify-min.js"></script>
801
- <script>prettyPrint();</script>
802
- <script src="../assets/js/yui-prettify.js"></script>
803
- </body>
804
- </html>