ember-cli 4.0.0-beta.4 → 4.1.0

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 (118) hide show
  1. package/.github/workflows/ci.yml +4 -4
  2. package/CHANGELOG.md +28 -17
  3. package/bin/ember +0 -0
  4. package/blueprints/addon/additional-dev-dependencies.json +1 -1
  5. package/blueprints/addon/files/.github/workflows/ci.yml +5 -1
  6. package/blueprints/addon/files/.travis.yml +1 -1
  7. package/blueprints/addon/files/README.md +2 -2
  8. package/blueprints/addon/files/addon-config/ember-try.js +4 -4
  9. package/blueprints/app/files/.github/workflows/ci.yml +4 -0
  10. package/blueprints/app/files/package.json +8 -8
  11. package/blueprints/in-repo-addon/files/__root__/__name__/index.js +0 -0
  12. package/blueprints/in-repo-addon/index.js +0 -0
  13. package/blueprints/lib/index.js +0 -0
  14. package/docs/build/data.json +413 -413
  15. package/lib/models/host-info-cache.js +3 -5
  16. package/lib/models/per-bundle-addon-cache/index.js +2 -3
  17. package/lib/tasks/npm-task.js +1 -1
  18. package/lib/utilities/get-lang-arg.js +45 -45
  19. package/package.json +25 -25
  20. package/.github/ISSUE_TEMPLATE.md +0 -12
  21. package/.github/dependabot.yml +0 -15
  22. package/.github/workflows/coverage.yml +0 -31
  23. package/docs/analytics.md +0 -44
  24. package/docs/architecture.md +0 -316
  25. package/docs/assets/architecture/Ember-CLI architecture.png +0 -0
  26. package/docs/assets/architecture/Ember-CLI architecture.xml +0 -1
  27. package/docs/assets/architecture/README.md +0 -5
  28. package/docs/brocfile-transition.md +0 -46
  29. package/docs/build/api.js +0 -44
  30. package/docs/build/assets/css/external-small.png +0 -0
  31. package/docs/build/assets/css/logo.png +0 -0
  32. package/docs/build/assets/css/main.css +0 -555
  33. package/docs/build/assets/favicon.ico +0 -0
  34. package/docs/build/assets/img/spinner.gif +0 -0
  35. package/docs/build/assets/index.html +0 -10
  36. package/docs/build/assets/js/api-filter.js +0 -56
  37. package/docs/build/assets/js/api-list.js +0 -255
  38. package/docs/build/assets/js/api-search.js +0 -98
  39. package/docs/build/assets/js/apidocs.js +0 -376
  40. package/docs/build/assets/js/yui-prettify.js +0 -17
  41. package/docs/build/assets/vendor/prettify/CHANGES.html +0 -130
  42. package/docs/build/assets/vendor/prettify/COPYING +0 -202
  43. package/docs/build/assets/vendor/prettify/README.html +0 -203
  44. package/docs/build/assets/vendor/prettify/prettify-min.css +0 -1
  45. package/docs/build/assets/vendor/prettify/prettify-min.js +0 -1
  46. package/docs/build/classes/Addon.html +0 -4318
  47. package/docs/build/classes/AmdTransformAddon.html +0 -202
  48. package/docs/build/classes/Blueprint.html +0 -4796
  49. package/docs/build/classes/Builder.html +0 -611
  50. package/docs/build/classes/CLI.html +0 -810
  51. package/docs/build/classes/Command.html +0 -1655
  52. package/docs/build/classes/DefaultPackager.html +0 -202
  53. package/docs/build/classes/EmberAddon.html +0 -2207
  54. package/docs/build/classes/EmberApp.html +0 -2225
  55. package/docs/build/classes/HardwareInfo.html +0 -620
  56. package/docs/build/classes/HistorySupportAddon.html +0 -203
  57. package/docs/build/classes/Instrumentation.html +0 -695
  58. package/docs/build/classes/NodeModulesList.html +0 -460
  59. package/docs/build/classes/NpmTask.html +0 -333
  60. package/docs/build/classes/PackageInfo.html +0 -1390
  61. package/docs/build/classes/PackageInfoCache.html +0 -963
  62. package/docs/build/classes/PerBundleAddonCache {.html +0 -1010
  63. package/docs/build/classes/Project.html +0 -2083
  64. package/docs/build/classes/ServeFilesAddon.html +0 -260
  65. package/docs/build/classes/TestsServerAddon.html +0 -203
  66. package/docs/build/classes/WatcherAddon.html +0 -204
  67. package/docs/build/classes/WindowsSymlinkChecker.html +0 -1505
  68. package/docs/build/files/lib_broccoli_default-packager.js.html +0 -1426
  69. package/docs/build/files/lib_broccoli_ember-addon.js.html +0 -159
  70. package/docs/build/files/lib_broccoli_ember-app.js.html +0 -1913
  71. package/docs/build/files/lib_cli_cli.js.html +0 -417
  72. package/docs/build/files/lib_models_addon-info.js.html +0 -112
  73. package/docs/build/files/lib_models_addon.js.html +0 -1866
  74. package/docs/build/files/lib_models_blueprint.js.html +0 -1678
  75. package/docs/build/files/lib_models_builder.js.html +0 -417
  76. package/docs/build/files/lib_models_command.js.html +0 -804
  77. package/docs/build/files/lib_models_hardware-info.js.html +0 -479
  78. package/docs/build/files/lib_models_host-info-cache.js.html +0 -428
  79. package/docs/build/files/lib_models_installation-checker.js.html +0 -181
  80. package/docs/build/files/lib_models_instantiate-addons.js.html +0 -191
  81. package/docs/build/files/lib_models_instrumentation.js.html +0 -433
  82. package/docs/build/files/lib_models_package-info-cache_index.js.html +0 -793
  83. package/docs/build/files/lib_models_package-info-cache_node-modules-list.js.html +0 -208
  84. package/docs/build/files/lib_models_package-info-cache_package-info.js.html +0 -661
  85. package/docs/build/files/lib_models_per-bundle-addon-cache_addon-proxy.js.html +0 -252
  86. package/docs/build/files/lib_models_per-bundle-addon-cache_index.js.html +0 -485
  87. package/docs/build/files/lib_models_per-bundle-addon-cache_target-instance.js.html +0 -108
  88. package/docs/build/files/lib_models_project.js.html +0 -913
  89. package/docs/build/files/lib_models_task.js.html +0 -117
  90. package/docs/build/files/lib_tasks_build-watch.js.html +0 -157
  91. package/docs/build/files/lib_tasks_npm-task.js.html +0 -463
  92. package/docs/build/files/lib_tasks_serve.js.html +0 -207
  93. package/docs/build/files/lib_tasks_server_middleware_broccoli-serve-files_index.js.html +0 -127
  94. package/docs/build/files/lib_tasks_server_middleware_broccoli-watcher_index.js.html +0 -158
  95. package/docs/build/files/lib_tasks_server_middleware_history-support_index.js.html +0 -181
  96. package/docs/build/files/lib_tasks_server_middleware_tests-server_index.js.html +0 -171
  97. package/docs/build/files/lib_tasks_test-server.js.html +0 -167
  98. package/docs/build/files/lib_tasks_transforms_amd_index.js.html +0 -143
  99. package/docs/build/files/lib_utilities_ember-app-utils.js.html +0 -292
  100. package/docs/build/files/lib_utilities_insert-into-file.js.html +0 -219
  101. package/docs/build/files/lib_utilities_is-lazy-engine.js.html +0 -125
  102. package/docs/build/files/lib_utilities_is-yarn-project.js.html +0 -120
  103. package/docs/build/files/lib_utilities_valid-project-name.js.html +0 -142
  104. package/docs/build/files/lib_utilities_will-interrupt-process.js.html +0 -290
  105. package/docs/build/files/lib_utilities_windows-admin.js.html +0 -230
  106. package/docs/build/index.html +0 -125
  107. package/docs/build/modules/ember-cli.html +0 -152
  108. package/docs/build/modules/is-lazy-engine.html +0 -106
  109. package/docs/build-concurrency.md +0 -15
  110. package/docs/build-pipeline-debugging.md +0 -33
  111. package/docs/code-coverage.md +0 -14
  112. package/docs/error-propagation.md +0 -136
  113. package/docs/experiments.md +0 -53
  114. package/docs/node-support.md +0 -43
  115. package/docs/perf-guide.md +0 -250
  116. package/docs/project_version_preprocessor.js +0 -8
  117. package/docs/sourcemaps.md +0 -60
  118. 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-beta.4-beta-724190cca6
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>