ember-cli 5.0.0 → 5.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.
@@ -86,6 +86,7 @@ jobs:
86
86
  - ENABLE_ALL_EXPERIMENTS
87
87
  - EMBROIDER
88
88
  - CLASSIC
89
+ - PNPM
89
90
 
90
91
  steps:
91
92
  - uses: actions/checkout@v3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # ember-cli Changelog
2
2
 
3
+ ## v5.1.0-beta.0
4
+
5
+ #### Blueprint Changes
6
+
7
+ - [`ember new` diff](https://github.com/ember-cli/ember-new-output/compare/v5.0.0...v5.1.0)
8
+ - [`ember addon` diff](https://github.com/ember-cli/ember-addon-output/compare/v5.0.0...v5.1.0)
9
+
10
+ #### Changelog
11
+
12
+ - [#10300](https://github.com/ember-cli/ember-cli/pull/10300) [BUGFIX] Do not try to wire up Testem unless a test framework is detected [@NullVoxPopuli](https://github.com/NullVoxPopuli)
13
+ - [#10256](https://github.com/ember-cli/ember-cli/pull/10256) [ENHANCEMENT] Align `hbs` templates generated by `app` blueprint with Prettier defaults [@jelhan](https://github.com/jelhan)
14
+ - [#10276](https://github.com/ember-cli/ember-cli/pull/10276) [BUGFIX] Widen peer dependency range for ember-source [@jrjohnson](https://github.com/jrjohnson)
15
+ - [#10279](https://github.com/ember-cli/ember-cli/pull/10279) Updated ember-welcome-page to v7.0.2 [@ijlee2](https://github.com/ijlee2)
16
+ - [#10287](https://github.com/ember-cli/ember-cli/pull/10287) Implementation of RFC 907 - pnpm support [@NullVoxPopuli](https://github.com/NullVoxPopuli)
17
+
18
+ Thank you to all who took the time to contribute!
19
+
3
20
  ## v5.0.0
4
21
 
5
22
  #### Blueprint Changes
@@ -18,18 +18,21 @@ jobs:
18
18
  timeout-minutes: 10
19
19
 
20
20
  steps:
21
- - uses: actions/checkout@v3
21
+ - uses: actions/checkout@v3<% if (pnpm) { %>
22
+ - uses: NullVoxPopuli/action-setup-pnpm@v2
23
+ with:
24
+ node-version: 16<% } else { %>
22
25
  - name: Install Node
23
26
  uses: actions/setup-node@v3
24
27
  with:
25
28
  node-version: 16
26
29
  cache: <%= yarn ? 'yarn' : 'npm' %>
27
30
  - name: Install Dependencies
28
- run: <%= yarn ? 'yarn install --frozen-lockfile' : 'npm ci' %>
31
+ run: <%= yarn ? 'yarn install --frozen-lockfile' : 'npm ci' %><% } %>
29
32
  - name: Lint
30
- run: <%= yarn ? 'yarn' : 'npm run' %> lint
33
+ run: <%= pnpm ? 'pnpm' : yarn ? 'yarn' : 'npm run' %> lint
31
34
  - name: Run Tests
32
- run: <%= yarn ? 'yarn' : 'npm run' %> test:ember
35
+ run: <%= pnpm ? 'pnpm' : yarn ? 'yarn' : 'npm run' %> test:ember
33
36
 
34
37
  floating:
35
38
  name: "Floating Dependencies"
@@ -37,15 +40,19 @@ jobs:
37
40
  timeout-minutes: 10
38
41
 
39
42
  steps:
40
- - uses: actions/checkout@v3
43
+ - uses: actions/checkout@v3<% if (pnpm) { %>
44
+ - uses: NullVoxPopuli/action-setup-pnpm@v2
45
+ with:
46
+ node-version: 16
47
+ no-lockfile: true<% } else { %>
41
48
  - uses: actions/setup-node@v3
42
49
  with:
43
50
  node-version: 16
44
51
  cache: <%= yarn ? 'yarn' : 'npm' %>
45
52
  - name: Install Dependencies
46
- run: <%= yarn ? 'yarn install --no-lockfile' : 'npm install --no-shrinkwrap' %>
53
+ run: <%= yarn ? 'yarn install --no-lockfile' : 'npm install --no-shrinkwrap' %><% } %>
47
54
  - name: Run Tests
48
- run: <%= yarn ? 'yarn' : 'npm run' %> test:ember
55
+ run: <%= pnpm ? 'pnpm' : yarn ? 'yarn' : 'npm run' %> test:ember
49
56
 
50
57
  try-scenarios:
51
58
  name: ${{ matrix.try-scenario }}
@@ -66,13 +73,16 @@ jobs:
66
73
  - embroider-optimized
67
74
 
68
75
  steps:
69
- - uses: actions/checkout@v3
76
+ - uses: actions/checkout@v3<% if (pnpm) { %>
77
+ - uses: NullVoxPopuli/action-setup-pnpm@v2
78
+ with:
79
+ node-version: 16<% } else { %>
70
80
  - name: Install Node
71
81
  uses: actions/setup-node@v3
72
82
  with:
73
83
  node-version: 16
74
84
  cache: <%= yarn ? 'yarn' : 'npm' %>
75
85
  - name: Install Dependencies
76
- run: <%= yarn ? 'yarn install --frozen-lockfile' : 'npm ci' %>
86
+ run: <%= yarn ? 'yarn install --frozen-lockfile' : 'npm ci' %><% } %>
77
87
  - name: Run Tests
78
88
  run: ./node_modules/.bin/ember try:one ${{ matrix.try-scenario }}
@@ -4,12 +4,12 @@
4
4
 
5
5
  * `git clone <repository-url>`
6
6
  * `cd <%= addonDirectory %>`
7
- * `<% if (yarn) { %>yarn<% } else { %>npm<% } %> install`
7
+ * `<% if (pnpm) { %>pnpm<% } else if (yarn) { %>yarn<% } else { %>npm<% } %> install`
8
8
 
9
9
  ## Linting
10
10
 
11
- * `<% if (yarn) { %>yarn lint<% } else { %>npm run lint<% } %>`
12
- * `<% if (yarn) { %>yarn lint:fix<% } else { %>npm run lint:fix<% } %>`
11
+ * `<% if (pnpm) { %>pnpm lint<% } else if (yarn) { %>yarn lint<% } else { %>npm run lint<% } %>`
12
+ * `<% if (pnpm) { %>pnpm lint:fix<% } else if (yarn) { %>yarn lint:fix<% } else { %>npm run lint:fix<% } %>`
13
13
 
14
14
  ## Running tests
15
15
 
@@ -5,7 +5,8 @@ const { embroiderSafe, embroiderOptimized } = require('@embroider/test-setup');
5
5
 
6
6
  module.exports = async function () {
7
7
  return {
8
- <% if (yarn) { %>useYarn: true,
8
+ <% if (pnpm) { %>usePnpm: true,
9
+ <% } else if (yarn) { %>useYarn: true,
9
10
  <% } %>scenarios: [
10
11
  {
11
12
  name: 'ember-lts-4.4',
@@ -130,7 +130,7 @@ module.exports = {
130
130
  let addonName = stringUtil.dasherize(addonRawName);
131
131
  let addonNamespace = stringUtil.classify(addonRawName);
132
132
 
133
- let hasOptions = options.welcome || options.yarn || options.ciProvider;
133
+ let hasOptions = options.welcome || options.yarn || options.pnpm || options.ciProvider;
134
134
  let blueprintOptions = '';
135
135
  if (hasOptions) {
136
136
  let indent = `\n `;
@@ -141,6 +141,7 @@ module.exports = {
141
141
  [
142
142
  options.welcome && '"--welcome"',
143
143
  options.yarn && '"--yarn"',
144
+ options.pnpm && '"--pnpm"',
144
145
  options.ciProvider && `"--ci-provider=${options.ciProvider}"`,
145
146
  options.typescript && `"--typescript"`,
146
147
  ]
@@ -159,6 +160,7 @@ module.exports = {
159
160
  emberCLIVersion: require('../../package').version,
160
161
  year: date.getFullYear(),
161
162
  yarn: options.yarn,
163
+ pnpm: options.pnpm,
162
164
  welcome: options.welcome,
163
165
  blueprint: 'addon',
164
166
  blueprintOptions,
@@ -176,6 +178,10 @@ module.exports = {
176
178
 
177
179
  let addonFiles = walkSync(addonFilesPath, { ignore: [ignoredCITemplate] });
178
180
 
181
+ if (!options.pnpm) {
182
+ addonFiles = addonFiles.filter((file) => !file.endsWith('.npmrc'));
183
+ }
184
+
179
185
  return uniq(appFiles.concat(addonFiles));
180
186
  },
181
187
 
@@ -18,16 +18,17 @@ jobs:
18
18
  timeout-minutes: 10
19
19
 
20
20
  steps:
21
- - uses: actions/checkout@v3
21
+ - uses: actions/checkout@v3<% if (pnpm) { %>
22
+ - uses: NullVoxPopuli/action-setup-pnpm@v2<% } else { %>
22
23
  - name: Install Node
23
24
  uses: actions/setup-node@v3
24
25
  with:
25
26
  node-version: 16
26
27
  cache: <%= yarn ? 'yarn' : 'npm' %>
27
28
  - name: Install Dependencies
28
- run: <%= yarn ? 'yarn install --frozen-lockfile' : 'npm ci' %>
29
+ run: <%= yarn ? 'yarn install --frozen-lockfile' : 'npm ci' %><% } %>
29
30
  - name: Lint
30
- run: <%= yarn ? 'yarn' : 'npm run' %> lint
31
+ run: <%= pnpm ? 'pnpm' : yarn ? 'yarn' : 'npm run' %> lint
31
32
 
32
33
  test:
33
34
  name: "Test"
@@ -35,13 +36,14 @@ jobs:
35
36
  timeout-minutes: 10
36
37
 
37
38
  steps:
38
- - uses: actions/checkout@v3
39
+ - uses: actions/checkout@v3<% if (pnpm) { %>
40
+ - uses: NullVoxPopuli/action-setup-pnpm@v2<% } else { %>
39
41
  - name: Install Node
40
42
  uses: actions/setup-node@v3
41
43
  with:
42
44
  node-version: 16
43
45
  cache: <%= yarn ? 'yarn' : 'npm' %>
44
46
  - name: Install Dependencies
45
- run: <%= yarn ? 'yarn install --frozen-lockfile' : 'npm ci' %>
47
+ run: <%= yarn ? 'yarn install --frozen-lockfile' : 'npm ci' %><% } %>
46
48
  - name: Run Tests
47
- run: <%= yarn ? 'yarn' : 'npm' %> test
49
+ run: <%= pnpm ? 'pnpm' : yarn ? 'yarn' : 'npm' %> test
@@ -8,7 +8,8 @@ A short introduction of this app could easily go here.
8
8
  You will need the following things properly installed on your computer.
9
9
 
10
10
  * [Git](https://git-scm.com/)
11
- * [Node.js](https://nodejs.org/)<% if (yarn) { %>
11
+ * [Node.js](https://nodejs.org/)<% if (pnpm) { %>
12
+ * [pnpm](https://pnpm.io/)<% } else if (yarn) { %>
12
13
  * [Yarn](https://yarnpkg.com/)<% } else { %> (with npm)<% } %>
13
14
  * [Ember CLI](https://cli.emberjs.com/release/)
14
15
  * [Google Chrome](https://google.com/chrome/)
@@ -17,7 +18,7 @@ You will need the following things properly installed on your computer.
17
18
 
18
19
  * `git clone <repository-url>` this repository
19
20
  * `cd <%= appDirectory %>`
20
- * `<% if (yarn) { %>yarn<% } else { %>npm<% } %> install`
21
+ * `<% if (pnpm) { %>pnpm<% } else if (yarn) { %>yarn<% } else { %>npm<% } %> install`
21
22
 
22
23
  ## Running / Development
23
24
 
@@ -36,8 +37,8 @@ Make use of the many generators for code, try `ember help generate` for more det
36
37
 
37
38
  ### Linting
38
39
 
39
- * `<% if (yarn) { %>yarn lint<% } else { %>npm run lint<% } %>`
40
- * `<% if (yarn) { %>yarn lint:fix<% } else { %>npm run lint:fix<% } %>`
40
+ * `<% if (pnpm) { %>pnpm lint<% } else if (yarn) { %>yarn lint<% } else { %>npm run lint<% } %>`
41
+ * `<% if (pnpm) { %>pnpm lint:fix<% } else if (yarn) { %>yarn lint:fix<% } else { %>npm run lint:fix<% } %>`
41
42
 
42
43
  ### Building
43
44
 
@@ -1,8 +1,8 @@
1
1
  {{page-title "<%= namespace %>"}}
2
2
 
3
- <% if (welcome) { %>{{!-- The following component displays Ember's default welcome message. --}}
3
+ <% if (welcome) { %>{{! The following component displays Ember's default welcome message. }}
4
4
  <WelcomePage />
5
- {{!-- Feel free to remove this! --}}
5
+ {{! Feel free to remove this! }}
6
6
  <% } else { %><h2 id="title">Welcome to Ember</h2>
7
7
  <% } %>
8
8
  {{outlet}}
@@ -30,51 +30,51 @@
30
30
  "@babel/plugin-proposal-decorators": "^7.22.5",
31
31
  "<% } %>@ember/optional-features": "^2.0.0",
32
32
  "@ember/string": "^3.1.1",
33
- "@ember/test-helpers": "^3.0.3<% if (embroider) { %>",
34
- "@embroider/compat": "^3.0.1",
35
- "@embroider/core": "^3.0.1",
36
- "@embroider/webpack": "^3.0.0<% } %>",
33
+ "@ember/test-helpers": "^3.1.0<% if (embroider) { %>",
34
+ "@embroider/compat": "^3.1.3",
35
+ "@embroider/core": "^3.1.1",
36
+ "@embroider/webpack": "^3.1.1<% } %>",
37
37
  "@glimmer/component": "^1.1.2",
38
38
  "@glimmer/tracking": "^1.1.2<% if (typescript) { %>",
39
- "@typescript-eslint/eslint-plugin": "^5.59.9",
40
- "@typescript-eslint/parser": "^5.59.9<% } %>",
39
+ "@typescript-eslint/eslint-plugin": "^5.60.1",
40
+ "@typescript-eslint/parser": "^5.60.1<% } %>",
41
41
  "broccoli-asset-rev": "^3.0.0",
42
42
  "concurrently": "^8.2.0",
43
43
  "ember-auto-import": "^2.6.3",
44
44
  "ember-cli": "~<%= emberCLIVersion %>",
45
- "ember-cli-app-version": "^6.0.0",
45
+ "ember-cli-app-version": "^6.0.1",
46
46
  "ember-cli-babel": "^7.26.11",
47
47
  "ember-cli-clean-css": "^2.0.0",
48
- "ember-cli-dependency-checker": "^3.3.1",
48
+ "ember-cli-dependency-checker": "^3.3.2",
49
49
  "ember-cli-htmlbars": "^6.2.0",
50
50
  "ember-cli-inject-live-reload": "^2.1.0<% if (!embroider) { %>",
51
51
  "ember-cli-sri": "^2.1.1",
52
52
  "ember-cli-terser": "^4.0.2<% } %>",
53
- "ember-data": "~5.0.0",
53
+ "ember-data": "~5.1.0",
54
54
  "ember-fetch": "^8.1.2",
55
55
  "ember-load-initializers": "^2.1.2",
56
56
  "ember-modifier": "^4.1.0",
57
57
  "ember-page-title": "^7.0.0",
58
58
  "ember-qunit": "^7.0.0",
59
- "ember-resolver": "^10.1.0",
60
- "ember-source": "~5.0.0",
61
- "ember-template-lint": "^5.10.1<% if (welcome) { %>",
59
+ "ember-resolver": "^10.1.1",
60
+ "ember-source": "~5.1.1",
61
+ "ember-template-lint": "^5.11.0<% if (welcome) { %>",
62
62
  "ember-welcome-page": "^7.0.2<% } %>",
63
- "eslint": "^8.42.0",
63
+ "eslint": "^8.43.0",
64
64
  "eslint-config-prettier": "^8.8.0",
65
- "eslint-plugin-ember": "^11.8.0",
66
- "eslint-plugin-n": "^16.0.0",
65
+ "eslint-plugin-ember": "^11.9.0",
66
+ "eslint-plugin-n": "^16.0.1",
67
67
  "eslint-plugin-prettier": "^4.2.1",
68
- "eslint-plugin-qunit": "^7.3.4",
68
+ "eslint-plugin-qunit": "^8.0.0",
69
69
  "loader.js": "^4.7.0",
70
70
  "prettier": "^2.8.8",
71
71
  "qunit": "^2.19.4",
72
72
  "qunit-dom": "^2.0.0",
73
- "stylelint": "^15.7.0",
73
+ "stylelint": "^15.9.0",
74
74
  "stylelint-config-standard": "^33.0.0",
75
75
  "stylelint-prettier": "^3.0.0",
76
76
  "tracked-built-ins": "^3.1.1",
77
- "webpack": "^5.86.0"
77
+ "webpack": "^5.88.1"
78
78
  },
79
79
  "engines": {
80
80
  "node": "16.* || >= 18"
@@ -26,7 +26,7 @@ module.exports = {
26
26
  let namespace = stringUtil.classify(rawName);
27
27
  let embroider = isExperimentEnabled('EMBROIDER') || options.embroider;
28
28
 
29
- let hasOptions = !options.welcome || options.yarn || embroider || options.ciProvider;
29
+ let hasOptions = !options.welcome || options.yarn || options.pnpm || embroider || options.ciProvider;
30
30
  let blueprintOptions = '';
31
31
  if (hasOptions) {
32
32
  let indent = `\n `;
@@ -37,6 +37,7 @@ module.exports = {
37
37
  [
38
38
  !options.welcome && '"--no-welcome"',
39
39
  options.yarn && '"--yarn"',
40
+ options.pnpm && '"--pnpm"',
40
41
  embroider && '"--embroider"',
41
42
  options.ciProvider && `"--ci-provider=${options.ciProvider}"`,
42
43
  options.typescript && `"--typescript"`,
@@ -53,6 +54,7 @@ module.exports = {
53
54
  namespace,
54
55
  emberCLIVersion: require('../../package').version,
55
56
  yarn: options.yarn,
57
+ pnpm: options.pnpm,
56
58
  welcome: options.welcome,
57
59
  blueprint: 'app',
58
60
  blueprintOptions,
@@ -3,7 +3,7 @@
3
3
  "logo": "https://ember-cli.com/assets/images/ember-cli-logo-small-dark.png",
4
4
  "name": "ember-cli",
5
5
  "description": "Command line tool for developing ambitious ember.js apps",
6
- "version": "5.0.0-release-023da4aaef"
6
+ "version": "5.1.0-release-e8820d9d4e"
7
7
  },
8
8
  "files": {
9
9
  "lib/broccoli/default-packager.js": {
@@ -290,6 +290,13 @@
290
290
  "fors": {},
291
291
  "namespaces": {}
292
292
  },
293
+ "lib/utilities/get-package-manager-from-flags.js": {
294
+ "name": "lib/utilities/get-package-manager-from-flags.js",
295
+ "modules": {},
296
+ "classes": {},
297
+ "fors": {},
298
+ "namespaces": {}
299
+ },
293
300
  "lib/utilities/insert-into-file.js": {
294
301
  "name": "lib/utilities/insert-into-file.js",
295
302
  "modules": {},
@@ -306,6 +313,13 @@
306
313
  "fors": {},
307
314
  "namespaces": {}
308
315
  },
316
+ "lib/utilities/is-pnpm-project.js": {
317
+ "name": "lib/utilities/is-pnpm-project.js",
318
+ "modules": {},
319
+ "classes": {},
320
+ "fors": {},
321
+ "namespaces": {}
322
+ },
309
323
  "lib/utilities/is-yarn-project.js": {
310
324
  "name": "lib/utilities/is-yarn-project.js",
311
325
  "modules": {},
@@ -6405,6 +6419,28 @@
6405
6419
  "class": "WindowsSymlinkChecker",
6406
6420
  "module": "ember-cli"
6407
6421
  },
6422
+ {
6423
+ "file": "lib/utilities/get-package-manager-from-flags.js",
6424
+ "line": 3,
6425
+ "description": "Returns the package manager, given an object where folks can *technically*\npass --pnpm --yarn --npm. But using multiple package managers at the\nsame time is not supported (by anything).\n\nThis function defines the priority of package managers, if multiple are present.",
6426
+ "access": "private",
6427
+ "tagname": "",
6428
+ "itemtype": "method",
6429
+ "name": "getPackageManagerFromFlags",
6430
+ "params": [
6431
+ {
6432
+ "name": "}",
6433
+ "description": "options",
6434
+ "type": " pnpm?: boolean; yarn?: boolean; packageManager?: 'pnpm' | 'yarn' | 'npm'"
6435
+ }
6436
+ ],
6437
+ "return": {
6438
+ "description": "",
6439
+ "type": "'pnpm' | 'yarn' | 'npm' | undefined"
6440
+ },
6441
+ "class": "WindowsSymlinkChecker",
6442
+ "module": "ember-cli"
6443
+ },
6408
6444
  {
6409
6445
  "file": "lib/utilities/insert-into-file.js",
6410
6446
  "line": 6,
@@ -6435,6 +6471,28 @@
6435
6471
  "class": "WindowsSymlinkChecker",
6436
6472
  "module": "ember-cli"
6437
6473
  },
6474
+ {
6475
+ "file": "lib/utilities/is-pnpm-project.js",
6476
+ "line": 5,
6477
+ "description": "Returns true if and only if the given directory has a pnpm-lock.yaml file or is a child of a\npnpm workspace root.",
6478
+ "access": "private",
6479
+ "tagname": "",
6480
+ "itemtype": "method",
6481
+ "name": "isPnpmProject",
6482
+ "params": [
6483
+ {
6484
+ "name": "thePath",
6485
+ "description": "",
6486
+ "type": "String"
6487
+ }
6488
+ ],
6489
+ "return": {
6490
+ "description": "",
6491
+ "type": "Promise<boolean>"
6492
+ },
6493
+ "class": "WindowsSymlinkChecker",
6494
+ "module": "is-lazy-engine"
6495
+ },
6438
6496
  {
6439
6497
  "file": "lib/utilities/is-yarn-project.js",
6440
6498
  "line": 6,
@@ -1,6 +1,6 @@
1
1
  runningTests = true;
2
2
 
3
- if (window.Testem) {
3
+ if (typeof Testem !== 'undefined' && (typeof QUnit !== 'undefined' || typeof Mocha !== 'undefined')) {
4
4
  window.Testem.hookIntoTestFramework();
5
5
  }
6
6
 
@@ -14,6 +14,7 @@ module.exports = NewCommand.extend({
14
14
  { name: 'skip-npm', type: Boolean, default: false, aliases: ['sn'] },
15
15
  { name: 'skip-git', type: Boolean, default: false, aliases: ['sg'] },
16
16
  { name: 'yarn', type: Boolean }, // no default means use yarn if the blueprint has a yarn.lock
17
+ { name: 'pnpm', type: Boolean, default: false },
17
18
  { name: 'directory', type: String, aliases: ['dir'] },
18
19
  {
19
20
  name: 'lang',
@@ -9,6 +9,8 @@ const normalizeBlueprint = require('../utilities/normalize-blueprint-option');
9
9
  const mergeBlueprintOptions = require('../utilities/merge-blueprint-options');
10
10
  const isYarnProject = require('../utilities/is-yarn-project');
11
11
  const getLangArg = require('../../lib/utilities/get-lang-arg');
12
+ const { isExperimentEnabled } = require('../experiments');
13
+ const { getPackageManagerFromFlags } = require('../utilities/get-package-manager-from-flags');
12
14
 
13
15
  module.exports = Command.extend({
14
16
  name: 'init',
@@ -28,6 +30,7 @@ module.exports = Command.extend({
28
30
  description: 'Installs and uses {{ember-welcome-page}}. Use --no-welcome to skip it.',
29
31
  },
30
32
  { name: 'yarn', type: Boolean }, // no default means use yarn if the blueprint has a yarn.lock
33
+ { name: 'pnpm', type: Boolean, default: false },
31
34
  { name: 'name', type: String, default: '', aliases: ['n'] },
32
35
  {
33
36
  name: 'lang',
@@ -98,15 +101,13 @@ module.exports = Command.extend({
98
101
 
99
102
  await this.runTask('InstallBlueprint', blueprintOpts);
100
103
 
101
- if (!commandOptions.skipNpm) {
102
- let packageManager =
103
- commandOptions.yarn === true
104
- ? 'yarn'
105
- : // supported for legacy reasons
106
- commandOptions.yarn === false
107
- ? 'npm'
108
- : undefined;
104
+ if (commandOptions.pnpm && !isExperimentEnabled('PNPM')) {
105
+ throw new Error(`--pnpm support is not enabled by default. Please prefix your command with EMBER_CLI_PNPM=true`);
106
+ }
109
107
 
108
+ let packageManager = getPackageManagerFromFlags(commandOptions);
109
+
110
+ if (!commandOptions.skipNpm) {
110
111
  await this.runTask('NpmInstall', {
111
112
  verbose: commandOptions.verbose,
112
113
  packageManager,
@@ -125,8 +126,7 @@ module.exports = Command.extend({
125
126
  this.ui.writeLine('');
126
127
  const command = `cd ${projectName}`;
127
128
  this.ui.writeLine(` ${chalk.gray('$')} ${chalk.cyan(command)}`);
128
- const packageManager = commandOptions.yarn ? 'yarn' : 'npm';
129
- this.ui.writeLine(` ${chalk.gray('$')} ${chalk.cyan(`${packageManager} start`)}`);
129
+ this.ui.writeLine(` ${chalk.gray('$')} ${chalk.cyan(`${packageManager ?? 'npm'} start`)}`);
130
130
  this.ui.writeLine('');
131
131
  this.ui.writeLine('Happy coding!');
132
132
  },
@@ -7,6 +7,7 @@ const SilentError = require('silent-error');
7
7
  const isValidProjectName = require('../utilities/valid-project-name');
8
8
  const normalizeBlueprint = require('../utilities/normalize-blueprint-option');
9
9
  const mergeBlueprintOptions = require('../utilities/merge-blueprint-options');
10
+ const { isExperimentEnabled } = require('../experiments');
10
11
 
11
12
  module.exports = Command.extend({
12
13
  name: 'new',
@@ -26,6 +27,7 @@ module.exports = Command.extend({
26
27
  description: 'Installs and uses {{ember-welcome-page}}. Use --no-welcome to skip it.',
27
28
  },
28
29
  { name: 'yarn', type: Boolean }, // no default means use yarn if the blueprint has a yarn.lock
30
+ { name: 'pnpm', type: Boolean, default: false },
29
31
  { name: 'directory', type: String, aliases: ['dir'] },
30
32
  {
31
33
  name: 'lang',
@@ -74,6 +76,7 @@ module.exports = Command.extend({
74
76
 
75
77
  if (answers.packageManager) {
76
78
  commandOptions.yarn = answers.packageManager === 'yarn';
79
+ commandOptions.pnpm = answers.packageManager === 'pnpm';
77
80
  }
78
81
 
79
82
  if (answers.ciProvider) {
@@ -89,6 +92,10 @@ module.exports = Command.extend({
89
92
  commandOptions.skipGit = true;
90
93
  }
91
94
 
95
+ if (commandOptions.pnpm && !isExperimentEnabled('PNPM')) {
96
+ throw new Error(`--pnpm support is not enabled by default. Please prefix your command with EMBER_CLI_PNPM=true`);
97
+ }
98
+
92
99
  if (projectName === '.') {
93
100
  let blueprintName = commandOptions.blueprint === 'app' ? 'application' : commandOptions.blueprint;
94
101
  message = `Trying to generate an ${blueprintName} structure in this directory? Use \`ember init\` instead.`;
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const chalk = require('chalk');
4
- const availableExperiments = Object.freeze(['EMBROIDER', 'CLASSIC']);
4
+ const availableExperiments = Object.freeze(['EMBROIDER', 'CLASSIC', 'PNPM']);
5
5
 
6
6
  const deprecatedExperiments = Object.freeze([]);
7
7
  const enabledExperiments = Object.freeze([]);
@@ -4,6 +4,7 @@ const Task = require('../models/task');
4
4
  const SilentError = require('silent-error');
5
5
  const { merge } = require('ember-cli-lodash-subset');
6
6
  const getPackageBaseName = require('../utilities/get-package-base-name');
7
+ const { getPackageManagerFromFlags } = require('../utilities/get-package-manager-from-flags');
7
8
 
8
9
  class AddonInstallTask extends Task {
9
10
  constructor(options) {
@@ -35,14 +36,7 @@ class AddonInstallTask extends Task {
35
36
 
36
37
  ui.startProgress(chalk.green('Installing addon package'), chalk.green('.'));
37
38
 
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);
39
+ let packageManager = getPackageManagerFromFlags(commandOptions);
46
40
 
47
41
  return npmInstall
48
42
  .run({
@@ -87,6 +87,10 @@ class InteractiveNewTask extends Task {
87
87
  name: 'NPM',
88
88
  value: 'npm',
89
89
  },
90
+ {
91
+ name: 'pnpm',
92
+ value: 'pnpm',
93
+ },
90
94
  {
91
95
  name: 'Yarn',
92
96
  value: 'yarn',
@@ -0,0 +1,38 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Returns the package manager, given an object where folks can *technically*
5
+ * pass --pnpm --yarn --npm. But using multiple package managers at the
6
+ * same time is not supported (by anything).
7
+ *
8
+ * This function defines the priority of package managers, if multiple are present.
9
+ *
10
+ * @private
11
+ * @method getPackageManagerFromFlags
12
+ * @param {{ pnpm?: boolean; yarn?: boolean; packageManager?: 'pnpm' | 'yarn' | 'npm' }} options
13
+ * @return {'pnpm' | 'yarn' | 'npm' | undefined}
14
+ */
15
+ function getPackageManagerFromFlags(options) {
16
+ let { pnpm, yarn, packageManager } = options;
17
+
18
+ if (packageManager) {
19
+ return packageManager;
20
+ }
21
+
22
+ if (pnpm) {
23
+ return 'pnpm';
24
+ }
25
+
26
+ if (yarn) {
27
+ return 'yarn';
28
+ }
29
+
30
+ // supported for legacy reasons
31
+ if (yarn === false) {
32
+ return 'npm';
33
+ }
34
+
35
+ return undefined;
36
+ }
37
+
38
+ module.exports = { getPackageManagerFromFlags };
@@ -0,0 +1,27 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+
5
+ /**
6
+ * Returns true if and only if the given directory has a pnpm-lock.yaml file or is a child of a
7
+ * pnpm workspace root.
8
+ * @private
9
+ * @method isPnpmProject
10
+ * @param {string} thePath
11
+ * @return {Promise<boolean>}
12
+ */
13
+ async function isPnpmProject(thePath) {
14
+ if (fs.existsSync(`${thePath}/pnpm-lock.yaml`)) {
15
+ return true;
16
+ }
17
+
18
+ const { findWorkspaceDir } = await import('@pnpm/find-workspace-dir');
19
+
20
+ if (await findWorkspaceDir(thePath)) {
21
+ return true;
22
+ }
23
+
24
+ return false;
25
+ }
26
+
27
+ module.exports = isPnpmProject;
@@ -2,6 +2,7 @@
2
2
 
3
3
  const execa = require('../utilities/execa');
4
4
  const isYarnProject = require('../utilities/is-yarn-project');
5
+ const isPnpmProject = require('../utilities/is-pnpm-project');
5
6
  const prependEmoji = require('../utilities/prepend-emoji');
6
7
 
7
8
  async function run(project) {
@@ -21,7 +22,9 @@ async function run(project) {
21
22
 
22
23
  let cwd = process.cwd();
23
24
 
24
- if (isYarnProject(project.root)) {
25
+ if (await isPnpmProject(project.root)) {
26
+ await execa('pnpm', [lintFixScriptName], { cwd });
27
+ } else if (isYarnProject(project.root)) {
25
28
  await execa('yarn', [lintFixScriptName], { cwd });
26
29
  } else {
27
30
  await execa('npm', ['run', lintFixScriptName], { cwd });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember-cli",
3
- "version": "5.0.0",
3
+ "version": "5.1.0",
4
4
  "description": "Command line tool for developing ambitious ember.js apps",
5
5
  "keywords": [
6
6
  "app",
@@ -38,6 +38,7 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "@babel/core": "^7.21.4",
41
+ "@pnpm/find-workspace-dir": "^6.0.1",
41
42
  "broccoli": "^3.5.2",
42
43
  "broccoli-builder": "^0.18.14",
43
44
  "broccoli-concat": "^4.2.5",