Repository: ember-cli/ember-cli
Pull request #9707 (2021-12-07 20:47:57)

[RFC 772] Deprecate Bower support
Implements [RFC 772](https://github.com/emberjs/rfcs/pull/772).

~~I _think_ this is ready for review, but marking it as draft as the RFC is still in FCP.~~

I know the current deprecation utility doesn't support the third argument, but this way the details are already present.

bertdeblock: @rwjblue Do you know if the failure is related to this PR or can we just try and re-run CI?
rwjblue: Now that the other PR is landed, would you mind rebasing?
bertdeblock: @rwjblue Should be good to go.

Patch:
diff --git a/lib/broccoli/default-packager.js b/lib/broccoli/default-packager.js
index 3d38e26d5..0acefdc3f 100644
--- a/lib/broccoli/default-packager.js
+++ b/lib/broccoli/default-packager.js
@@ -12,6 +12,7 @@ const ConfigReplace = require('broccoli-config-replace');
 const emberAppUtils = require('../utilities/ember-app-utils');
 const funnelReducer = require('broccoli-funnel-reducer');
 const addonProcessTree = require('../utilities/addon-process-tree');
+const { deprecate } = require('../debug');
 
 const preprocessCss = p.preprocessCss;
 const preprocessJs = p.preprocessJs;
@@ -628,9 +629,21 @@ module.exports = class DefaultPackager {
    * @param {String} bowerDirectory Custom path to bower components
    */
   packageBower(tree, bowerDirectory) {
+    let destDir = bowerDirectory || DEFAULT_BOWER_PATH;
+
+    deprecate(`Building Bower packages has been deprecated. You have Bower packages in \`${destDir}\`.`, false, {
+      for: 'ember-cli',
+      id: 'ember-cli.building-bower-packages',
+      since: {
+        available: '4.2.0',
+        enabled: '4.2.0',
+      },
+      until: '5.0.0',
+    });
+
     if (this._cachedBower === null) {
       this._cachedBower = new Funnel(tree, {
-        destDir: bowerDirectory || DEFAULT_BOWER_PATH,
+        destDir,
         annotation: 'Packaged Bower',
       });
     }
diff --git a/lib/broccoli/ember-app.js b/lib/broccoli/ember-app.js
index e5d562226..67f7cb070 100644
--- a/lib/broccoli/ember-app.js
+++ b/lib/broccoli/ember-app.js
@@ -108,7 +108,7 @@ class EmberApp {
 
     this.registry = options.registry || p.defaultRegistry(this);
 
-    this.bowerDirectory = this.project.bowerDirectory;
+    this.bowerDirectory = this.project._bowerDirectory;
 
     this._initTestsAndHinting(options);
     this._initOptions(options);
@@ -438,7 +438,7 @@ class EmberApp {
     @method _initVendorFiles
   */
   _initVendorFiles() {
-    let bowerDeps = this.project.bowerDependencies();
+    let bowerDeps = this.project._bowerDependencies();
     let ember = this.project.findAddonByName('ember-source');
     let addonEmberCliShims = this.project.findAddonByName('ember-cli-shims');
     let bowerEmberCliShims = bowerDeps['ember-cli-shims'];
diff --git a/lib/models/blueprint.js b/lib/models/blueprint.js
index a08d5a588..55e8a67ab 100644
--- a/lib/models/blueprint.js
+++ b/lib/models/blueprint.js
@@ -24,6 +24,7 @@ const bowEpParser = require('bower-endpoint-parser');
 const logger = require('heimdalljs-logger')('ember-cli:blueprint');
 const normalizeEntityName = require('ember-cli-normalize-entity-name');
 const isAddon = require('../utilities/is-addon');
+const { deprecate } = require('../debug');
 
 const initialIgnoredFiles = ['.DS_Store'];
 
@@ -1017,10 +1018,29 @@ let Blueprint = CoreObject.extend({
     ```
   */
   addBowerPackageToProject(localPackageName, target, installOptions) {
+    deprecate(
+      [
+        `(Blueprint: \`${this.name}\`) \`addBowerPackageToProject\` has been deprecated.`,
+        'If the package is also available on the npm registry, please use `addPackageToProject` instead.',
+        'If not, please install the Bower package manually by running:',
+        `\`bower install ${localPackageName} --save\``,
+      ].join('\n'),
+      false,
+      {
+        for: 'ember-cli',
+        id: 'ember-cli.blueprint.add-bower-package-to-project',
+        since: {
+          available: '4.2.0',
+          enabled: '4.2.0',
+        },
+        until: '5.0.0',
+      }
+    );
+
     let lpn = localPackageName;
     let tar = target;
     let packageObject = bowEpParser.json2decomposed(lpn, tar);
-    return this.addBowerPackagesToProject([packageObject], installOptions);
+    return this.addBowerPackagesToProject([packageObject], installOptions, true);
   },
 
   /**
@@ -1039,7 +1059,7 @@ let Blueprint = CoreObject.extend({
     @param {Object} installOptions
     @return {Promise}
   */
-  addBowerPackagesToProject(packages, installOptions) {
+  addBowerPackagesToProject(packages, installOptions, _deprecationCondition = false) {
     let task = this.taskFor('bower-install');
     let installText = packages.length > 1 ? 'install bower packages' : 'install bower package';
     let packageNames = [];
@@ -1051,6 +1071,25 @@ let Blueprint = CoreObject.extend({
       })
       .map(bowEpParser.compose);
 
+    deprecate(
+      [
+        `(Blueprint: \`${this.name}\`) \`addBowerPackagesToProject\` has been deprecated.`,
+        'If the packages are also available on the npm registry, please use `addPackagesToProject` instead.',
+        'If not, please install the Bower packages manually by running:',
+        `\`bower install ${packageNames.join(' ')} --save\``,
+      ].join('\n'),
+      _deprecationCondition,
+      {
+        for: 'ember-cli',
+        id: 'ember-cli.blueprint.add-bower-packages-to-project',
+        since: {
+          available: '4.2.0',
+          enabled: '4.2.0',
+        },
+        until: '5.0.0',
+      }
+    );
+
     this._writeStatusToUI(chalk.green, installText, packageNames.join(', '));
 
     return task.run({
diff --git a/lib/models/installation-checker.js b/lib/models/installation-checker.js
index a236608b9..737858471 100644
--- a/lib/models/installation-checker.js
+++ b/lib/models/installation-checker.js
@@ -48,7 +48,7 @@ class InstallationChecker {
   }
 
   bowerDependenciesNotPresent() {
-    return !fs.existsSync(this.project.bowerDirectory);
+    return !fs.existsSync(this.project._bowerDirectory);
   }
 
   hasNpmDeps() {
diff --git a/lib/models/project.js b/lib/models/project.js
index d1c53a11f..a4b7f47b0 100644
--- a/lib/models/project.js
+++ b/lib/models/project.js
@@ -18,6 +18,7 @@ const PackageInfoCache = require('./package-info-cache');
 const PerBundleAddonCache = require('./per-bundle-addon-cache');
 const instantiateAddons = require('./instantiate-addons');
 const HostInfoCache = require('./host-info-cache');
+const { deprecate } = require('../debug');
 
 let processCwd = process.cwd();
 
@@ -117,15 +118,36 @@ class Project {
 
     if (fs.existsSync(bowerrcPath)) {
       try {
-        this.bowerDirectory = fs.readJsonSync(bowerrcPath).directory;
+        this._bowerDirectory = fs.readJsonSync(bowerrcPath).directory;
       } catch (exception) {
         logger.info('failed to parse bowerc: %s', exception);
-        this.bowerDirectory = null;
+        this._bowerDirectory = null;
       }
     }
 
-    this.bowerDirectory = this.bowerDirectory || 'bower_components';
-    logger.info('bowerDirectory: %s', this.bowerDirectory);
+    this._bowerDirectory = this._bowerDirectory || 'bower_components';
+    logger.info('bowerDirectory: %s', this._bowerDirectory);
+  }
+
+  get bowerDirectory() {
+    deprecate(
+      [
+        '`bowerDirectory` has been deprecated.',
+        "If you still need access to the project's Bower directory, you will have to manually resolve the project's `.bowerrc` file, and read the `directory` property instead.",
+      ].join('\n'),
+      false,
+      {
+        for: 'ember-cli',
+        id: 'ember-cli.project.bower-directory',
+        since: {
+          available: '4.2.0',
+          enabled: '4.2.0',
+        },
+        until: '5.0.0',
+      }
+    );
+
+    return this._bowerDirectory;
   }
 
   // Checks whether the project's npm dependencies are
@@ -387,6 +409,27 @@ class Project {
     @return {Object}       Bower dependencies
    */
   bowerDependencies(bower) {
+    deprecate(
+      [
+        '`bowerDependencies` has been deprecated.',
+        "If you still need access to the project's Bower dependencies, you will have to manually resolve the project's `bower.json` file instead.",
+      ].join('\n'),
+      false,
+      {
+        for: 'ember-cli',
+        id: 'ember-cli.project.bower-dependencies',
+        since: {
+          available: '4.2.0',
+          enabled: '4.2.0',
+        },
+        until: '5.0.0',
+      }
+    );
+
+    return this._bowerDependencies(bower);
+  }
+
+  _bowerDependencies(bower) {
     if (!bower) {
       let bowerPath = path.join(this.root, 'bower.json');
       bower = fs.existsSync(bowerPath) ? require(bowerPath) : {};


Test patch:
diff --git a/tests/unit/broccoli/ember-app-test.js b/tests/unit/broccoli/ember-app-test.js
index 493f176a7..19dead0f0 100644
--- a/tests/unit/broccoli/ember-app-test.js
+++ b/tests/unit/broccoli/ember-app-test.js
@@ -825,7 +825,7 @@ describe('EmberApp', function () {
       });
 
       it('keeps ember-resolver.js in vendorFiles when npm ember-resolver is not installed, but is present in bower.json', function () {
-        project.bowerDependencies = function () {
+        project._bowerDependencies = function () {
           return { ember: {}, 'ember-resolver': {} };
         };
         let app = new EmberApp({
@@ -841,7 +841,7 @@ describe('EmberApp', function () {
       });
 
       it('removes ember-resolver.js from vendorFiles when not in bower.json and npm ember-resolver not installed', function () {
-        project.bowerDependencies = function () {
+        project._bowerDependencies = function () {
           return { ember: {} };
         };
         let app = new EmberApp({