ember-cli 3.28.3 → 4.0.0-beta.3
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.
- package/.github/workflows/ci.yml +5 -1
- package/CHANGELOG.md +75 -0
- package/README.md +1 -1
- package/blueprints/addon/additional-dev-dependencies.json +2 -2
- package/blueprints/addon/files/.github/workflows/ci.yml +73 -0
- package/blueprints/addon/files/.travis.yml +1 -1
- package/blueprints/addon/files/npmignore +4 -0
- package/blueprints/addon/index.js +14 -5
- package/blueprints/app/files/.eslintignore +3 -0
- package/blueprints/app/files/.eslintrc.js +1 -1
- package/blueprints/app/files/.github/workflows/ci.yml +41 -0
- package/blueprints/app/files/.prettierignore +4 -0
- package/blueprints/app/files/config/targets.js +0 -15
- package/blueprints/app/files/gitignore +3 -0
- package/blueprints/app/files/package.json +20 -21
- package/blueprints/app/index.js +23 -2
- package/docs/build/classes/Addon.html +1 -1
- package/docs/build/classes/AmdTransformAddon.html +1 -1
- package/docs/build/classes/Blueprint.html +1 -1
- package/docs/build/classes/Builder.html +1 -1
- package/docs/build/classes/CLI.html +1 -1
- package/docs/build/classes/Command.html +1 -1
- package/docs/build/classes/DefaultPackager.html +1 -1
- package/docs/build/classes/EmberAddon.html +39 -39
- package/docs/build/classes/EmberApp.html +39 -39
- package/docs/build/classes/HardwareInfo.html +1 -1
- package/docs/build/classes/HistorySupportAddon.html +1 -1
- package/docs/build/classes/Instrumentation.html +1 -1
- package/docs/build/classes/NodeModulesList.html +1 -1
- package/docs/build/classes/NpmTask.html +4 -4
- package/docs/build/classes/PackageInfo.html +1 -1
- package/docs/build/classes/PackageInfoCache.html +1 -1
- package/docs/build/classes/PerBundleAddonCache {.html +1 -1
- package/docs/build/classes/Project.html +1 -1
- package/docs/build/classes/ServeFilesAddon.html +1 -1
- package/docs/build/classes/TestsServerAddon.html +1 -1
- package/docs/build/classes/WatcherAddon.html +1 -1
- package/docs/build/classes/WindowsSymlinkChecker.html +1 -1
- package/docs/build/data.json +36 -36
- package/docs/build/files/lib_broccoli_default-packager.js.html +1 -1
- package/docs/build/files/lib_broccoli_ember-addon.js.html +1 -1
- package/docs/build/files/lib_broccoli_ember-app.js.html +63 -21
- package/docs/build/files/lib_cli_cli.js.html +1 -1
- package/docs/build/files/lib_models_addon-info.js.html +1 -1
- package/docs/build/files/lib_models_addon.js.html +1 -1
- package/docs/build/files/lib_models_blueprint.js.html +5 -5
- package/docs/build/files/lib_models_builder.js.html +1 -1
- package/docs/build/files/lib_models_command.js.html +1 -1
- package/docs/build/files/lib_models_hardware-info.js.html +1 -1
- package/docs/build/files/lib_models_host-info-cache.js.html +1 -1
- package/docs/build/files/lib_models_installation-checker.js.html +1 -1
- package/docs/build/files/lib_models_instantiate-addons.js.html +1 -1
- package/docs/build/files/lib_models_instrumentation.js.html +1 -1
- package/docs/build/files/lib_models_package-info-cache_index.js.html +1 -1
- package/docs/build/files/lib_models_package-info-cache_node-modules-list.js.html +1 -1
- package/docs/build/files/lib_models_package-info-cache_package-info.js.html +1 -1
- package/docs/build/files/lib_models_per-bundle-addon-cache_addon-proxy.js.html +1 -1
- package/docs/build/files/lib_models_per-bundle-addon-cache_index.js.html +1 -1
- package/docs/build/files/lib_models_per-bundle-addon-cache_target-instance.js.html +1 -1
- package/docs/build/files/lib_models_project.js.html +1 -1
- package/docs/build/files/lib_models_task.js.html +1 -1
- package/docs/build/files/lib_tasks_build-watch.js.html +1 -1
- package/docs/build/files/lib_tasks_npm-task.js.html +134 -46
- package/docs/build/files/lib_tasks_serve.js.html +1 -1
- package/docs/build/files/lib_tasks_server_middleware_broccoli-serve-files_index.js.html +1 -1
- package/docs/build/files/lib_tasks_server_middleware_broccoli-watcher_index.js.html +1 -1
- package/docs/build/files/lib_tasks_server_middleware_history-support_index.js.html +1 -1
- package/docs/build/files/lib_tasks_server_middleware_tests-server_index.js.html +1 -1
- package/docs/build/files/lib_tasks_test-server.js.html +1 -1
- package/docs/build/files/lib_tasks_transforms_amd_index.js.html +1 -1
- package/docs/build/files/lib_utilities_ember-app-utils.js.html +1 -1
- package/docs/build/files/lib_utilities_insert-into-file.js.html +1 -1
- package/docs/build/files/lib_utilities_is-lazy-engine.js.html +1 -1
- package/docs/build/files/lib_utilities_is-yarn-project.js.html +1 -1
- package/docs/build/files/lib_utilities_valid-project-name.js.html +1 -1
- package/docs/build/files/lib_utilities_will-interrupt-process.js.html +1 -1
- package/docs/build/files/lib_utilities_windows-admin.js.html +1 -1
- package/docs/build/index.html +2 -2
- package/docs/build/modules/ember-cli.html +2 -2
- package/docs/build/modules/is-lazy-engine.html +1 -1
- package/docs/perf-guide.md +2 -0
- package/lib/broccoli/ember-app.js +62 -20
- package/lib/commands/addon.js +6 -0
- package/lib/commands/init.js +18 -2
- package/lib/commands/install.js +9 -1
- package/lib/commands/new.js +6 -0
- package/lib/models/blueprint.js +4 -4
- package/lib/tasks/addon-install.js +10 -1
- package/lib/tasks/install-blueprint.js +1 -0
- package/lib/tasks/npm-install.js +2 -2
- package/lib/tasks/npm-task.js +133 -45
- package/lib/tasks/npm-uninstall.js +2 -2
- package/package.json +2 -2
- package/tests/helpers/dist-checker.js +21 -1
- package/tests/helpers/ember.js +2 -2
|
@@ -84,7 +84,7 @@ class EmberApp {
|
|
|
84
84
|
- trees, defaults to `{}`
|
|
85
85
|
- jshintrc, defaults to `{}`
|
|
86
86
|
- vendorFiles, defaults to `{}`
|
|
87
|
-
- addons, defaults to `{
|
|
87
|
+
- addons, defaults to `{ exclude: [], include: [] }`
|
|
88
88
|
|
|
89
89
|
@class EmberApp
|
|
90
90
|
@constructor
|
|
@@ -170,10 +170,12 @@ class EmberApp {
|
|
|
170
170
|
this._cachedAddonBundles = {};
|
|
171
171
|
|
|
172
172
|
if (this.project.perBundleAddonCache && this.project.perBundleAddonCache.numProxies > 0) {
|
|
173
|
-
if (this.options.addons.
|
|
173
|
+
if (this.options.addons.include && this.options.addons.include.length) {
|
|
174
|
+
let optionKey = this.options.addons.hasWhitelist ? 'whitelist' : 'include';
|
|
175
|
+
|
|
174
176
|
throw new Error(
|
|
175
177
|
[
|
|
176
|
-
|
|
178
|
+
`[ember-cli] addon bundle caching is disabled for apps that specify an addon "${optionKey}"`,
|
|
177
179
|
'',
|
|
178
180
|
'All addons using bundle caching:',
|
|
179
181
|
...this.project.perBundleAddonCache.getPathsToAddonsOptedIn(),
|
|
@@ -181,10 +183,12 @@ class EmberApp {
|
|
|
181
183
|
);
|
|
182
184
|
}
|
|
183
185
|
|
|
184
|
-
if (this.options.addons.
|
|
186
|
+
if (this.options.addons.exclude && this.options.addons.exclude.length) {
|
|
187
|
+
let optionKey = this.options.addons.hasBlacklist ? 'blacklist' : 'exclude';
|
|
188
|
+
|
|
185
189
|
throw new Error(
|
|
186
190
|
[
|
|
187
|
-
|
|
191
|
+
`[ember-cli] addon bundle caching is disabled for apps that specify an addon "${optionKey}"`,
|
|
188
192
|
'',
|
|
189
193
|
'All addons using bundle caching:',
|
|
190
194
|
...this.project.perBundleAddonCache.getPathsToAddonsOptedIn(),
|
|
@@ -366,6 +370,40 @@ class EmberApp {
|
|
|
366
370
|
|
|
367
371
|
this.options = defaultsDeep(options, detectedDefaultOptions, DEFAULT_CONFIG);
|
|
368
372
|
|
|
373
|
+
if (this.options.addons.blacklist) {
|
|
374
|
+
if (this.options.addons.exclude) {
|
|
375
|
+
throw new Error('Specifying both "blacklist" and "exclude" is not supported. Please use only one.');
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
this.options.addons.hasBlacklist = true;
|
|
379
|
+
this.options.addons.exclude = this.options.addons.blacklist;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
Object.defineProperty(this.options.addons, 'blacklist', {
|
|
383
|
+
get() {
|
|
384
|
+
console.log(chalk.yellow('Please use "exclude" instead of "blacklist".'));
|
|
385
|
+
|
|
386
|
+
return this.exclude;
|
|
387
|
+
},
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
if (this.options.addons.whitelist) {
|
|
391
|
+
if (this.options.addons.include) {
|
|
392
|
+
throw new Error('Specifying both "whitelist" and "include" is not supported. Please use only one.');
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
this.options.addons.hasWhitelist = true;
|
|
396
|
+
this.options.addons.include = this.options.addons.whitelist;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
Object.defineProperty(this.options.addons, 'whitelist', {
|
|
400
|
+
get() {
|
|
401
|
+
console.log(chalk.yellow('Please use "include" instead of "whitelist".'));
|
|
402
|
+
|
|
403
|
+
return this.include;
|
|
404
|
+
},
|
|
405
|
+
});
|
|
406
|
+
|
|
369
407
|
// For now we must disable Babel sourcemaps due to unforeseen
|
|
370
408
|
// performance regressions.
|
|
371
409
|
if (!('sourceMaps' in this.options.babel)) {
|
|
@@ -555,24 +593,24 @@ class EmberApp {
|
|
|
555
593
|
|
|
556
594
|
/**
|
|
557
595
|
@private
|
|
558
|
-
@method
|
|
596
|
+
@method _addonDisabledByExclude
|
|
559
597
|
@param {Addon} addon
|
|
560
598
|
@return {Boolean}
|
|
561
599
|
*/
|
|
562
|
-
|
|
563
|
-
let
|
|
564
|
-
return !!
|
|
600
|
+
_addonDisabledByExclude(addon) {
|
|
601
|
+
let exclude = this.options.addons.exclude;
|
|
602
|
+
return !!exclude && exclude.indexOf(addon.name) !== -1;
|
|
565
603
|
}
|
|
566
604
|
|
|
567
605
|
/**
|
|
568
606
|
@private
|
|
569
|
-
@method
|
|
607
|
+
@method _addonDisabledByInclude
|
|
570
608
|
@param {Addon} addon
|
|
571
609
|
@return {Boolean}
|
|
572
610
|
*/
|
|
573
|
-
|
|
574
|
-
let
|
|
575
|
-
return !!
|
|
611
|
+
_addonDisabledByInclude(addon) {
|
|
612
|
+
let include = this.options.addons.include;
|
|
613
|
+
return !!include && include.indexOf(addon.name) === -1;
|
|
576
614
|
}
|
|
577
615
|
|
|
578
616
|
/**
|
|
@@ -616,7 +654,7 @@ class EmberApp {
|
|
|
616
654
|
return false;
|
|
617
655
|
}
|
|
618
656
|
|
|
619
|
-
return !this.
|
|
657
|
+
return !this._addonDisabledByExclude(addon) && !this._addonDisabledByInclude(addon);
|
|
620
658
|
}
|
|
621
659
|
|
|
622
660
|
/**
|
|
@@ -628,18 +666,22 @@ class EmberApp {
|
|
|
628
666
|
_notifyAddonIncluded() {
|
|
629
667
|
let addonNames = this.project.addons.map((addon) => addon.name);
|
|
630
668
|
|
|
631
|
-
if (this.options.addons.
|
|
632
|
-
this.options.addons.blacklist
|
|
669
|
+
if (this.options.addons.exclude) {
|
|
670
|
+
let optionKey = this.options.addons.hasBlacklist ? 'blacklist' : 'exclude';
|
|
671
|
+
|
|
672
|
+
this.options.addons.exclude.forEach((addonName) => {
|
|
633
673
|
if (addonNames.indexOf(addonName) === -1) {
|
|
634
|
-
throw new Error(`Addon "${addonName}" defined in
|
|
674
|
+
throw new Error(`Addon "${addonName}" defined in "${optionKey}" is not found`);
|
|
635
675
|
}
|
|
636
676
|
});
|
|
637
677
|
}
|
|
638
678
|
|
|
639
|
-
if (this.options.addons.
|
|
640
|
-
this.options.addons.whitelist
|
|
679
|
+
if (this.options.addons.include) {
|
|
680
|
+
let optionKey = this.options.addons.hasWhitelist ? 'whitelist' : 'include';
|
|
681
|
+
|
|
682
|
+
this.options.addons.include.forEach((addonName) => {
|
|
641
683
|
if (addonNames.indexOf(addonName) === -1) {
|
|
642
|
-
throw new Error(`Addon "${addonName}" defined in
|
|
684
|
+
throw new Error(`Addon "${addonName}" defined in "${optionKey}" is not found`);
|
|
643
685
|
}
|
|
644
686
|
});
|
|
645
687
|
}
|
package/lib/commands/addon.js
CHANGED
|
@@ -20,6 +20,12 @@ module.exports = NewCommand.extend({
|
|
|
20
20
|
type: String,
|
|
21
21
|
description: "Sets the base human language of the addon's own test application via index.html",
|
|
22
22
|
},
|
|
23
|
+
{
|
|
24
|
+
name: 'ci-provider',
|
|
25
|
+
type: ['travis', 'github'],
|
|
26
|
+
default: 'github',
|
|
27
|
+
description: 'Installs the default CI blueprint. Either Travis or Github Actions is supported.',
|
|
28
|
+
},
|
|
23
29
|
],
|
|
24
30
|
|
|
25
31
|
anonymousOptions: ['<addon-name>'],
|
package/lib/commands/init.js
CHANGED
|
@@ -37,6 +37,12 @@ module.exports = Command.extend({
|
|
|
37
37
|
description: 'Sets the base human language of the application via index.html',
|
|
38
38
|
},
|
|
39
39
|
{ name: 'embroider', type: Boolean, default: false, description: 'Enables the build system to use Embroider' },
|
|
40
|
+
{
|
|
41
|
+
name: 'ci-provider',
|
|
42
|
+
type: ['travis', 'github'],
|
|
43
|
+
default: 'github',
|
|
44
|
+
description: 'Installs the default CI blueprint. Either Travis or Github Actions is supported.',
|
|
45
|
+
},
|
|
40
46
|
],
|
|
41
47
|
|
|
42
48
|
anonymousOptions: ['<glob-pattern>'],
|
|
@@ -59,6 +65,7 @@ module.exports = Command.extend({
|
|
|
59
65
|
|
|
60
66
|
let project = this.project;
|
|
61
67
|
let packageName = (commandOptions.name !== '.' && commandOptions.name) || project.name();
|
|
68
|
+
let ciProvider = commandOptions.ciProvider;
|
|
62
69
|
|
|
63
70
|
if (!packageName) {
|
|
64
71
|
let message =
|
|
@@ -75,7 +82,7 @@ module.exports = Command.extend({
|
|
|
75
82
|
|
|
76
83
|
let blueprintOpts = clone(commandOptions);
|
|
77
84
|
|
|
78
|
-
if (blueprintOpts.yarn === undefined) {
|
|
85
|
+
if (blueprintOpts.yarn === undefined && project.isEmberCLIProject()) {
|
|
79
86
|
blueprintOpts.yarn = isYarnProject(project.root);
|
|
80
87
|
}
|
|
81
88
|
|
|
@@ -84,6 +91,7 @@ module.exports = Command.extend({
|
|
|
84
91
|
targetFiles: rawArgs || '',
|
|
85
92
|
rawArgs: rawArgs.toString(),
|
|
86
93
|
blueprint: normalizeBlueprint(blueprintOpts.blueprint || this._defaultBlueprint()),
|
|
94
|
+
ciProvider,
|
|
87
95
|
});
|
|
88
96
|
|
|
89
97
|
if (!isValidProjectName(packageName)) {
|
|
@@ -93,9 +101,17 @@ module.exports = Command.extend({
|
|
|
93
101
|
await this.runTask('InstallBlueprint', blueprintOpts);
|
|
94
102
|
|
|
95
103
|
if (!commandOptions.skipNpm) {
|
|
104
|
+
let packageManager =
|
|
105
|
+
commandOptions.yarn === true
|
|
106
|
+
? 'yarn'
|
|
107
|
+
: // supported for legacy reasons
|
|
108
|
+
commandOptions.yarn === false
|
|
109
|
+
? 'npm'
|
|
110
|
+
: undefined;
|
|
111
|
+
|
|
96
112
|
await this.runTask('NpmInstall', {
|
|
97
113
|
verbose: commandOptions.verbose,
|
|
98
|
-
|
|
114
|
+
packageManager,
|
|
99
115
|
});
|
|
100
116
|
}
|
|
101
117
|
|
package/lib/commands/install.js
CHANGED
|
@@ -13,7 +13,15 @@ module.exports = Command.extend({
|
|
|
13
13
|
{ name: 'save', type: Boolean, default: false, aliases: ['S'] },
|
|
14
14
|
{ name: 'save-dev', type: Boolean, default: true, aliases: ['D'] },
|
|
15
15
|
{ name: 'save-exact', type: Boolean, default: false, aliases: ['E', 'exact'] },
|
|
16
|
-
{
|
|
16
|
+
{
|
|
17
|
+
name: 'package-manager',
|
|
18
|
+
type: ['npm', 'pnpm', 'yarn'],
|
|
19
|
+
description:
|
|
20
|
+
'Use this option to force the usage of a specific package manager. ' +
|
|
21
|
+
'By default, ember-cli will try to detect the right package manager ' +
|
|
22
|
+
'from any lockfiles that exist in your project.',
|
|
23
|
+
aliases: [{ yarn: 'yarn' }, { pnpm: 'pnpm' }],
|
|
24
|
+
},
|
|
17
25
|
],
|
|
18
26
|
|
|
19
27
|
anonymousOptions: ['<addon-name>'],
|
package/lib/commands/new.js
CHANGED
|
@@ -35,6 +35,12 @@ module.exports = Command.extend({
|
|
|
35
35
|
description: 'Sets the base human language of the application via index.html',
|
|
36
36
|
},
|
|
37
37
|
{ name: 'embroider', type: Boolean, default: false, description: 'Enables the build system to use Embroider' },
|
|
38
|
+
{
|
|
39
|
+
name: 'ci-provider',
|
|
40
|
+
type: ['travis', 'github'],
|
|
41
|
+
default: 'github',
|
|
42
|
+
description: 'Installs the default CI blueprint. Either Travis or Github Actions is supported.',
|
|
43
|
+
},
|
|
38
44
|
],
|
|
39
45
|
|
|
40
46
|
anonymousOptions: ['<app-name>'],
|
package/lib/models/blueprint.js
CHANGED
|
@@ -446,7 +446,7 @@ let Blueprint = CoreObject.extend({
|
|
|
446
446
|
this.project = options.project;
|
|
447
447
|
this.pod = options.pod;
|
|
448
448
|
this.options = options;
|
|
449
|
-
this.hasPathToken = hasPathToken(this.files());
|
|
449
|
+
this.hasPathToken = hasPathToken(this.files(this.options));
|
|
450
450
|
|
|
451
451
|
ui.writeLine(`installing ${this.name}`);
|
|
452
452
|
|
|
@@ -476,7 +476,7 @@ let Blueprint = CoreObject.extend({
|
|
|
476
476
|
this.project = options.project;
|
|
477
477
|
this.pod = options.pod;
|
|
478
478
|
this.options = options;
|
|
479
|
-
this.hasPathToken = hasPathToken(this.files());
|
|
479
|
+
this.hasPathToken = hasPathToken(this.files(this.options));
|
|
480
480
|
|
|
481
481
|
ui.writeLine(`uninstalling ${this.name}`);
|
|
482
482
|
|
|
@@ -717,7 +717,7 @@ let Blueprint = CoreObject.extend({
|
|
|
717
717
|
@return {Array} files
|
|
718
718
|
*/
|
|
719
719
|
_getFilesForInstall(targetFiles) {
|
|
720
|
-
let files = this.files();
|
|
720
|
+
let files = this.files(this.options);
|
|
721
721
|
|
|
722
722
|
// if we've defined targetFiles, get file info on ones that match
|
|
723
723
|
return (targetFiles && targetFiles.length > 0 && _.intersection(files, targetFiles)) || files;
|
|
@@ -765,7 +765,7 @@ let Blueprint = CoreObject.extend({
|
|
|
765
765
|
@param {Object} templateVariables
|
|
766
766
|
*/
|
|
767
767
|
processFilesForUninstall(intoDir, templateVariables) {
|
|
768
|
-
let fileInfos = this._getFileInfos(this.files(), intoDir, templateVariables);
|
|
768
|
+
let fileInfos = this._getFileInfos(this.files(this.options), intoDir, templateVariables);
|
|
769
769
|
|
|
770
770
|
this._ignoreUpdateFiles();
|
|
771
771
|
|
|
@@ -35,13 +35,22 @@ class AddonInstallTask extends Task {
|
|
|
35
35
|
|
|
36
36
|
ui.startProgress(chalk.green('Installing addon package'), chalk.green('.'));
|
|
37
37
|
|
|
38
|
+
let packageManager =
|
|
39
|
+
commandOptions.packageManager ||
|
|
40
|
+
(commandOptions.yarn === true
|
|
41
|
+
? 'yarn'
|
|
42
|
+
: // supported for legacy reasons
|
|
43
|
+
commandOptions.yarn === false
|
|
44
|
+
? 'npm'
|
|
45
|
+
: undefined);
|
|
46
|
+
|
|
38
47
|
return npmInstall
|
|
39
48
|
.run({
|
|
40
49
|
packages: packageNames,
|
|
41
50
|
save: commandOptions.save,
|
|
42
51
|
'save-dev': !commandOptions.save,
|
|
43
52
|
'save-exact': commandOptions.saveExact,
|
|
44
|
-
|
|
53
|
+
packageManager,
|
|
45
54
|
})
|
|
46
55
|
.then(() => this.project.reloadAddons())
|
|
47
56
|
.then(() => this.installBlueprint(blueprintInstall, packageNames, blueprintOptions))
|
package/lib/tasks/npm-install.js
CHANGED
|
@@ -25,11 +25,11 @@ class NpmInstallTask extends NpmTask {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
formatStartMessage(packages) {
|
|
28
|
-
return `${this.
|
|
28
|
+
return `${this.packageManagerOutputName}: Installing ${formatPackageList(packages)} ...`;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
formatCompleteMessage(packages) {
|
|
32
|
-
return `${this.
|
|
32
|
+
return `${this.packageManagerOutputName}: Installed ${formatPackageList(packages)}`;
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
package/lib/tasks/npm-task.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
const chalk = require('chalk');
|
|
6
6
|
const execa = require('../utilities/execa');
|
|
7
|
+
const findUp = require('find-up');
|
|
7
8
|
const semver = require('semver');
|
|
8
9
|
const SilentError = require('silent-error');
|
|
9
10
|
const isYarnProject = require('../utilities/is-yarn-project');
|
|
@@ -28,6 +29,10 @@ class NpmTask extends Task {
|
|
|
28
29
|
this.versionConstraints = '3 || 4 || 5 || 6';
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
get packageManagerOutputName() {
|
|
33
|
+
return this.packageManager.name;
|
|
34
|
+
}
|
|
35
|
+
|
|
31
36
|
npm(args) {
|
|
32
37
|
logger.info('npm: %j', args);
|
|
33
38
|
return execa('npm', args, { preferLocal: false });
|
|
@@ -38,10 +43,19 @@ class NpmTask extends Task {
|
|
|
38
43
|
return execa('yarn', args, { preferLocal: false });
|
|
39
44
|
}
|
|
40
45
|
|
|
46
|
+
pnpm(args) {
|
|
47
|
+
logger.info('pnpm: %j', args);
|
|
48
|
+
return execa('pnpm', args, { preferLocal: false });
|
|
49
|
+
}
|
|
50
|
+
|
|
41
51
|
hasYarnLock() {
|
|
42
52
|
return isYarnProject(this.project.root);
|
|
43
53
|
}
|
|
44
54
|
|
|
55
|
+
async hasPNPMLock() {
|
|
56
|
+
return Boolean(await findUp('pnpm-lock.yaml', { cwd: this.project.root }));
|
|
57
|
+
}
|
|
58
|
+
|
|
45
59
|
async checkYarn() {
|
|
46
60
|
try {
|
|
47
61
|
let result = await this.yarn(['--version']);
|
|
@@ -54,9 +68,7 @@ class NpmTask extends Task {
|
|
|
54
68
|
logger.info('yarn --version: %s', version);
|
|
55
69
|
}
|
|
56
70
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return { yarnVersion: version };
|
|
71
|
+
return { name: 'yarn', version };
|
|
60
72
|
} catch (error) {
|
|
61
73
|
logger.error('yarn --version failed: %s', error);
|
|
62
74
|
|
|
@@ -71,6 +83,28 @@ class NpmTask extends Task {
|
|
|
71
83
|
}
|
|
72
84
|
}
|
|
73
85
|
|
|
86
|
+
async checkPNPM() {
|
|
87
|
+
try {
|
|
88
|
+
let result = await this.pnpm(['--version']);
|
|
89
|
+
let version = result.stdout;
|
|
90
|
+
|
|
91
|
+
logger.info('pnpm --version: %s', version);
|
|
92
|
+
|
|
93
|
+
return { name: 'pnpm', version };
|
|
94
|
+
} catch (error) {
|
|
95
|
+
logger.error('pnpm --version failed: %s', error);
|
|
96
|
+
|
|
97
|
+
if (error.code === 'ENOENT') {
|
|
98
|
+
throw new SilentError(
|
|
99
|
+
'Ember CLI is now using pnpm, but was not able to find it.\n' +
|
|
100
|
+
'Please install pnpm using the instructions at https://pnpm.io/installation'
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
74
108
|
async checkNpmVersion() {
|
|
75
109
|
try {
|
|
76
110
|
let result = await this.npm(['--version']);
|
|
@@ -95,7 +129,7 @@ class NpmTask extends Task {
|
|
|
95
129
|
);
|
|
96
130
|
}
|
|
97
131
|
|
|
98
|
-
return {
|
|
132
|
+
return { name: 'npm', version };
|
|
99
133
|
} catch (error) {
|
|
100
134
|
logger.error('npm --version failed: %s', error);
|
|
101
135
|
|
|
@@ -124,37 +158,55 @@ class NpmTask extends Task {
|
|
|
124
158
|
* @method findPackageManager
|
|
125
159
|
* @return {Promise}
|
|
126
160
|
*/
|
|
127
|
-
async findPackageManager() {
|
|
128
|
-
if (
|
|
161
|
+
async findPackageManager(packageManager = null) {
|
|
162
|
+
if (packageManager === 'yarn') {
|
|
129
163
|
logger.info('yarn requested -> trying yarn');
|
|
130
164
|
return this.checkYarn();
|
|
131
165
|
}
|
|
132
166
|
|
|
133
|
-
if (
|
|
167
|
+
if (packageManager === 'npm') {
|
|
134
168
|
logger.info('npm requested -> using npm');
|
|
135
169
|
return this.checkNpmVersion();
|
|
136
170
|
}
|
|
137
171
|
|
|
138
|
-
if (
|
|
139
|
-
logger.info('
|
|
140
|
-
return this.
|
|
172
|
+
if (packageManager === 'pnpm') {
|
|
173
|
+
logger.info('pnpm requested -> using pnpm');
|
|
174
|
+
return this.checkPNPM();
|
|
141
175
|
}
|
|
142
176
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
177
|
+
if (this.hasYarnLock()) {
|
|
178
|
+
logger.info('yarn.lock found -> trying yarn');
|
|
179
|
+
try {
|
|
180
|
+
const yarnResult = await this.checkYarn();
|
|
181
|
+
logger.info('yarn found -> using yarn');
|
|
182
|
+
return yarnResult;
|
|
183
|
+
} catch (_err) {
|
|
184
|
+
logger.info('yarn not found');
|
|
185
|
+
}
|
|
186
|
+
} else {
|
|
187
|
+
logger.info('yarn.lock not found');
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (this.hasPNPMLock()) {
|
|
191
|
+
logger.info('pnpm-lock.yaml found -> trying pnpm');
|
|
192
|
+
try {
|
|
193
|
+
let result = await this.checkPNPM();
|
|
194
|
+
logger.info('pnpm found -> using pnpm');
|
|
195
|
+
return result;
|
|
196
|
+
} catch (_err) {
|
|
197
|
+
logger.info('pnpm not found');
|
|
198
|
+
}
|
|
199
|
+
} else {
|
|
200
|
+
logger.info('pnpm-lock.yaml not found');
|
|
151
201
|
}
|
|
202
|
+
|
|
203
|
+
logger.info('using npm');
|
|
204
|
+
return this.checkNpmVersion();
|
|
152
205
|
}
|
|
153
206
|
|
|
154
207
|
async run(options) {
|
|
155
|
-
this.
|
|
208
|
+
this.packageManager = await this.findPackageManager(options.packageManager);
|
|
156
209
|
|
|
157
|
-
let result = await this.findPackageManager();
|
|
158
210
|
let ui = this.ui;
|
|
159
211
|
let startMessage = this.formatStartMessage(options.packages);
|
|
160
212
|
let completeMessage = this.formatCompleteMessage(options.packages);
|
|
@@ -165,31 +217,37 @@ class NpmTask extends Task {
|
|
|
165
217
|
ui.writeLine(prependEmoji('🚧', 'Installing packages... This might take a couple of minutes.'));
|
|
166
218
|
ui.startProgress(chalk.green(startMessage));
|
|
167
219
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
220
|
+
try {
|
|
221
|
+
if (this.packageManager.name === 'yarn') {
|
|
222
|
+
let args = this.toYarnArgs(this.command, options);
|
|
223
|
+
await this.yarn(args);
|
|
224
|
+
} else if (this.packageManager.name === 'pnpm') {
|
|
225
|
+
let args = this.toPNPMArgs(this.command, options);
|
|
226
|
+
await this.pnpm(args);
|
|
227
|
+
} else {
|
|
228
|
+
let args = this.toNpmArgs(this.command, options);
|
|
229
|
+
await this.npm(args);
|
|
230
|
+
|
|
231
|
+
// as of 2018-10-09 npm 5 and 6 _break_ the hierarchy of `node_modules`
|
|
232
|
+
// after a `npm install foo` (deletes files/folders other than
|
|
233
|
+
// what was directly installed) in some circumstances, see:
|
|
234
|
+
//
|
|
235
|
+
// * https://github.com/npm/npm/issues/16853
|
|
236
|
+
// * https://github.com/npm/npm/issues/17379
|
|
237
|
+
//
|
|
238
|
+
// this ensures that we run a full `npm install` **after** any `npm
|
|
239
|
+
// install foo` runs to ensure that we have a fully functional
|
|
240
|
+
// node_modules hierarchy
|
|
241
|
+
let npmVersion = this.packageManager.version;
|
|
242
|
+
if (npmVersion && semver.lt(npmVersion, '5.7.1')) {
|
|
243
|
+
await this.npm(['install']);
|
|
244
|
+
}
|
|
189
245
|
}
|
|
246
|
+
} finally {
|
|
247
|
+
ui.stopProgress();
|
|
190
248
|
}
|
|
191
249
|
|
|
192
|
-
|
|
250
|
+
ui.writeLine(chalk.green(completeMessage));
|
|
193
251
|
}
|
|
194
252
|
|
|
195
253
|
toNpmArgs(command, options) {
|
|
@@ -212,9 +270,9 @@ class NpmTask extends Task {
|
|
|
212
270
|
}
|
|
213
271
|
|
|
214
272
|
if (options.verbose) {
|
|
215
|
-
args.push('--loglevel verbose');
|
|
273
|
+
args.push('--loglevel', 'verbose');
|
|
216
274
|
} else {
|
|
217
|
-
args.push('--loglevel error');
|
|
275
|
+
args.push('--loglevel', 'error');
|
|
218
276
|
}
|
|
219
277
|
|
|
220
278
|
if (options.packages) {
|
|
@@ -262,13 +320,43 @@ class NpmTask extends Task {
|
|
|
262
320
|
// Yarn v2 defaults to non-interactive
|
|
263
321
|
// with an optional -i flag
|
|
264
322
|
|
|
265
|
-
if (semver.lt(this.
|
|
323
|
+
if (semver.lt(this.packageManager.version, '2.0.0')) {
|
|
266
324
|
args.push('--non-interactive');
|
|
267
325
|
}
|
|
268
326
|
|
|
269
327
|
return args;
|
|
270
328
|
}
|
|
271
329
|
|
|
330
|
+
toPNPMArgs(command, options) {
|
|
331
|
+
let args = [];
|
|
332
|
+
|
|
333
|
+
if (command === 'install') {
|
|
334
|
+
if (options.save) {
|
|
335
|
+
args.push('add');
|
|
336
|
+
} else if (options['save-dev']) {
|
|
337
|
+
args.push('add', '--save-dev');
|
|
338
|
+
} else if (options.packages) {
|
|
339
|
+
throw new Error(`npm command "${command} ${options.packages.join(' ')}" can not be translated to pnpm command`);
|
|
340
|
+
} else {
|
|
341
|
+
args.push('install');
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (options['save-exact']) {
|
|
345
|
+
args.push('--save-exact');
|
|
346
|
+
}
|
|
347
|
+
} else if (command === 'uninstall') {
|
|
348
|
+
args.push('remove');
|
|
349
|
+
} else {
|
|
350
|
+
throw new Error(`npm command "${command}" can not be translated to pnpm command`);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if (options.packages) {
|
|
354
|
+
args = args.concat(options.packages);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return args;
|
|
358
|
+
}
|
|
359
|
+
|
|
272
360
|
formatStartMessage(/* packages */) {
|
|
273
361
|
return '';
|
|
274
362
|
}
|
|
@@ -12,11 +12,11 @@ class NpmUninstallTask extends NpmTask {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
formatStartMessage(packages) {
|
|
15
|
-
return `${this.
|
|
15
|
+
return `${this.packageManagerOutputName}: Uninstalling ${formatPackageList(packages)} ...`;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
formatCompleteMessage(packages) {
|
|
19
|
-
return `${this.
|
|
19
|
+
return `${this.packageManagerOutputName}: Uninstalled ${formatPackageList(packages)}`;
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ember-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0-beta.3",
|
|
4
4
|
"description": "Command line tool for developing ambitious ember.js apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"app",
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
"tree-sync": "^2.1.0",
|
|
126
126
|
"uuid": "^8.3.2",
|
|
127
127
|
"walk-sync": "^2.2.0",
|
|
128
|
-
"watch-detector": "^1.0.
|
|
128
|
+
"watch-detector": "^1.0.1",
|
|
129
129
|
"workerpool": "^6.1.4",
|
|
130
130
|
"yam": "^1.0.0"
|
|
131
131
|
},
|