Repository: ember-cli/ember-cli
Pull request #10589 (2024-12-22 19:50:50)

[ENHANCEMENT] Deprecate v1 addon `contentFor` types [RFC 1044]
Implements RFC https://github.com/emberjs/rfcs/pull/1044.

ef4: This looks good to me once we can address the conflicts.

Patch:
diff --git a/lib/debug/deprecate.js b/lib/debug/deprecate.js
index f03702800..e6a39cc99 100644
--- a/lib/debug/deprecate.js
+++ b/lib/debug/deprecate.js
@@ -80,9 +80,7 @@ function deprecate(description, condition, options) {
 
   let message = formatMessage(description, options);
 
-  warn(message);
-  warn('');
-  warn(getStackTrace());
+  warn(`${message}\n\n${getStackTrace()}`);
 
   // Return the message for testing purposes.
   // This can be removed once we can register deprecation handlers.
diff --git a/lib/debug/deprecations.js b/lib/debug/deprecations.js
index 3ac2bacad..9bf42e45f 100644
--- a/lib/debug/deprecations.js
+++ b/lib/debug/deprecations.js
@@ -10,6 +10,19 @@ function deprecation(options) {
   };
 }
 
-const DEPRECATIONS = {};
+const DEPRECATIONS = {
+  V1_ADDON_CONTENT_FOR_TYPES: deprecation({
+    for: 'ember-cli',
+    id: 'ember-cli.v1-addon-content-for-types',
+    since: {
+      available: '6.3.0',
+    },
+    until: '7.0.0',
+    url: 'https://deprecations.emberjs.com/id/v1-addon-content-for-types',
+    meta: {
+      types: ['app-prefix', 'app-suffix', 'tests-prefix', 'tests-suffix', 'vendor-prefix', 'vendor-suffix'],
+    },
+  }),
+};
 
 module.exports = DEPRECATIONS;
diff --git a/lib/utilities/ember-app-utils.js b/lib/utilities/ember-app-utils.js
index 19c7eab55..3013a6c94 100644
--- a/lib/utilities/ember-app-utils.js
+++ b/lib/utilities/ember-app-utils.js
@@ -3,6 +3,7 @@
 const fs = require('fs');
 const path = require('path');
 const cleanBaseURL = require('clean-base-url');
+const { deprecate, DEPRECATIONS } = require('../debug');
 
 /**
  * Returns a normalized url given a string.
@@ -124,6 +125,14 @@ document.addEventListener('DOMContentLoaded', function() {
   content = options.addons.reduce((content, addon) => {
     let addonContent = addon.contentFor ? addon.contentFor(type, config, content) : null;
     if (addonContent) {
+      for (const deprecatedType of DEPRECATIONS.V1_ADDON_CONTENT_FOR_TYPES.options.meta.types) {
+        deprecate(
+          `Addon \`${addon.name}\` is using the deprecated \`${deprecatedType}\` type in its \`contentFor\` method. Please see the deprecation guide for the correct path forward.`,
+          type !== deprecatedType,
+          DEPRECATIONS.V1_ADDON_CONTENT_FOR_TYPES.options
+        );
+      }
+
       return content.concat(addonContent);
     }
 


Test patch:
diff --git a/tests/unit/broccoli/default-packager/ember-cli-internal-test.js b/tests/unit/broccoli/default-packager/ember-cli-internal-test.js
index bb8100eac..4c586d52d 100644
--- a/tests/unit/broccoli/default-packager/ember-cli-internal-test.js
+++ b/tests/unit/broccoli/default-packager/ember-cli-internal-test.js
@@ -193,8 +193,8 @@ var runningTests = false;`);
         addons: [
           {
             contentFor(type) {
-              if (type === 'app-prefix') {
-                return 'CUSTOM APP PREFIX CODE';
+              if (type === 'test-support-prefix') {
+                return 'CUSTOM TEST SUPPORT PREFIX CODE';
               }
             },
           },
@@ -231,9 +231,9 @@ var runningTests = false;`);
 
     let emberCliFiles = outputFiles.vendor['ember-cli'];
     let appBootFileContent = emberCliFiles['app-boot.js'].trim();
-    let appPrefixFileContent = emberCliFiles['app-prefix.js'].trim();
+    let testSupportPrefixFileContent = emberCliFiles['test-support-prefix.js'].trim();
 
     expect(appBootFileContent).to.equal('CUSTOM APP BOOT CODE');
-    expect(appPrefixFileContent).to.equal(`'use strict';\n\nCUSTOM APP PREFIX CODE`);
+    expect(testSupportPrefixFileContent).to.equal('CUSTOM TEST SUPPORT PREFIX CODE');
   });
 });
diff --git a/tests/unit/utilities/ember-app-utils-test.js b/tests/unit/utilities/ember-app-utils-test.js
index 1ef275ea3..b011d8175 100644
--- a/tests/unit/utilities/ember-app-utils-test.js
+++ b/tests/unit/utilities/ember-app-utils-test.js
@@ -4,6 +4,7 @@ const fs = require('fs');
 const path = require('path');
 const { expect } = require('chai');
 
+const { DEPRECATIONS } = require('../../../lib/debug');
 const emberAppUtils = require('../../../lib/utilities/ember-app-utils');
 
 const contentFor = emberAppUtils.contentFor;
@@ -233,6 +234,52 @@ document.addEventListener('DOMContentLoaded', function() {
 
         expect(output).to.equal('blammo\nblahzorz');
       });
+
+      for (const deprecatedType of DEPRECATIONS.V1_ADDON_CONTENT_FOR_TYPES.options.meta.types) {
+        it(`shows a deprecation warning when using the deprecated \`${deprecatedType}\` \`contentFor\` type`, function () {
+          if (DEPRECATIONS.V1_ADDON_CONTENT_FOR_TYPES.isRemoved) {
+            this.skip();
+          }
+
+          const consoleWarn = console.warn;
+          const deprecations = [];
+
+          // TODO: This should be updated once we can register deprecation handlers:
+          console.warn = (deprecation) => deprecations.push(deprecation);
+
+          const addons = [
+            {
+              name: 'foo',
+              contentFor(type) {
+                if (type === deprecatedType) {
+                  return `${deprecatedType}-content`;
+                }
+              },
+            },
+            {
+              contentFor(type) {
+                if (type === 'foo') {
+                  return 'foo-content';
+                }
+              },
+            },
+          ];
+
+          const options = { ...defaultOptions, addons };
+
+          let content = '';
+          content += contentFor(config, defaultMatch, deprecatedType, options);
+          content += contentFor(config, defaultMatch, 'foo', options);
+
+          expect(content).to.equal(`${deprecatedType}-contentfoo-content`);
+          expect(deprecations.length).to.equal(1);
+          expect(deprecations[0]).to.include(
+            `Addon \`foo\` is using the deprecated \`${deprecatedType}\` type in its \`contentFor\` method.`
+          );
+
+          console.warn = consoleWarn;
+        });
+      }
     });
   });