Repository: ember-cli/ember-cli
Pull request #10536 (2024-10-25 19:55:35)

[ENHANCEMENT] Make deprecations throw when the `until` for `ember-cli` has passed
Throw deprecations if the until of ember-cli has passed


For - https://rfcs.emberjs.com/id/0830-evolving-embers-major-version-process

kategengler: This is in-progress version of https://github.com/emberjs/ember.js/pull/20669 for ember-cli

Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index facc2da90..a1ff9b4bf 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -112,3 +112,15 @@ jobs:
       - run: pnpm test:all
         env:
           'EMBER_CLI_${{ matrix.feature-flag }}': true
+
+  deprecations-broken-test:
+    name: Deprecations "broken"
+    runs-on: ubuntu-latest
+    needs: [basic-tests, linting]
+    steps:
+      - uses: actions/checkout@v4
+      - uses: ./.github/actions/setup-environment
+      - name: Run Tests with Deprecations as Errors
+        env:
+          OVERRIDE_DEPRECATION_VERSION: '22.0.0'
+        run: pnpm test:all
diff --git a/blueprints/addon/files/tsconfig.json b/blueprints/addon/files/tsconfig.json
index 7b83c0d8b..cf5217e56 100644
--- a/blueprints/addon/files/tsconfig.json
+++ b/blueprints/addon/files/tsconfig.json
@@ -1,5 +1,8 @@
 {
   "extends": "@tsconfig/ember/tsconfig.json",
+  "glint": {
+    "environment": ["ember-loose", "ember-template-imports"]
+  },
   "compilerOptions": {
     // The combination of `baseUrl` with `paths` allows Ember's classic package
     // layout, which is not resolvable with the Node resolution algorithm, to
diff --git a/blueprints/addon/index.js b/blueprints/addon/index.js
index ac2ed3678..23899dbf0 100644
--- a/blueprints/addon/index.js
+++ b/blueprints/addon/index.js
@@ -68,6 +68,9 @@ module.exports = {
     contents.dependencies['ember-cli-htmlbars'] = contents.devDependencies['ember-cli-htmlbars'];
     delete contents.devDependencies['ember-cli-htmlbars'];
 
+    contents.dependencies['ember-template-imports'] = contents.devDependencies['ember-template-imports'];
+    delete contents.devDependencies['ember-template-imports'];
+
     // 95% of addons don't need ember-data or ember-fetch, make them opt-in instead
     let deps = Object.keys(contents.devDependencies);
     for (let depName of deps) {
diff --git a/blueprints/app/files/.prettierrc.js b/blueprints/app/files/.prettierrc.js
index 8d067814c..7c49e9dee 100644
--- a/blueprints/app/files/.prettierrc.js
+++ b/blueprints/app/files/.prettierrc.js
@@ -4,7 +4,7 @@ module.exports = {
   plugins: ['prettier-plugin-ember-template-tag'],
   overrides: [
     {
-      files: '*.{js,ts,mjs,mts,cjs,cts}',
+      files: '*.{js,gjs,ts,gts,mjs,mts,cjs,cts}',
       options: {
         singleQuote: true,
       },
diff --git a/blueprints/app/files/_js_eslint.config.mjs b/blueprints/app/files/_js_eslint.config.mjs
index e05042fd2..b895cc463 100644
--- a/blueprints/app/files/_js_eslint.config.mjs
+++ b/blueprints/app/files/_js_eslint.config.mjs
@@ -1,15 +1,25 @@
+/**
+ * Debugging:
+ *   https://eslint.org/docs/latest/use/configure/debug
+ *  ----------------------------------------------------
+ *
+ *   Print a file's calculated configuration
+ *
+ *     npx eslint --print-config path/to/file.js
+ *
+ *   Inspecting the config
+ *
+ *     npx eslint --inspect-config
+ *
+ */
 import globals from 'globals';
 import js from '@eslint/js';
 
-import ember from 'eslint-plugin-ember';
-import emberRecommended from 'eslint-plugin-ember/configs/recommended';
-import gjsRecommended from 'eslint-plugin-ember/configs/recommended-gjs';
-
+import ember from 'eslint-plugin-ember/recommended';
 import prettier from 'eslint-plugin-prettier/recommended';
 import qunit from 'eslint-plugin-qunit';
 import n from 'eslint-plugin-n';
 
-import emberParser from 'ember-eslint-parser';
 import babelParser from '@babel/eslint-parser';
 
 const esmParserOptions = {
@@ -26,8 +36,19 @@ const esmParserOptions = {
 export default [
   js.configs.recommended,
   prettier,
+  ember.configs.base,
+  ember.configs.gjs,
+  /**
+   * Ignores must be in their own object
+   * https://eslint.org/docs/latest/use/configure/ignore
+   */
   {
     ignores: ['dist/', 'node_modules/', 'coverage/', '!**/.*'],
+  },
+  /**
+   * https://eslint.org/docs/latest/use/configure/configuration-files#configuring-linter-options
+   */
+  {
     linterOptions: {
       reportUnusedDisableDirectives: 'error',
     },
@@ -36,35 +57,16 @@ export default [
     files: ['**/*.js'],
     languageOptions: {
       parser: babelParser,
-      parserOptions: esmParserOptions,
-      globals: {
-        ...globals.browser,
-      },
-    },
-    plugins: {
-      ember,
-    },
-    rules: {
-      ...emberRecommended.rules,
-      ...gjsRecommended.rules,
     },
   },
   {
-    files: ['**/*.gjs'],
+    files: ['**/*.{js,gjs}'],
     languageOptions: {
-      parser: emberParser,
       parserOptions: esmParserOptions,
       globals: {
         ...globals.browser,
       },
     },
-    plugins: {
-      ember,
-    },
-    rules: {
-      ...emberRecommended.rules,
-      ...gjsRecommended.rules,
-    },
   },
   {
     files: ['tests/**/*-test.{js,gjs}'],
@@ -102,7 +104,7 @@ export default [
    * ESM node files
    */
   {
-    files: ['*.mjs'],
+    files: ['**/*.mjs'],
     plugins: {
       n,
     },
diff --git a/blueprints/app/files/_ts_eslint.config.mjs b/blueprints/app/files/_ts_eslint.config.mjs
index 8acc12d10..c84c3aebe 100644
--- a/blueprints/app/files/_ts_eslint.config.mjs
+++ b/blueprints/app/files/_ts_eslint.config.mjs
@@ -1,18 +1,28 @@
+/**
+ * Debugging:
+ *   https://eslint.org/docs/latest/use/configure/debug
+ *  ----------------------------------------------------
+ *
+ *   Print a file's calculated configuration
+ *
+ *     npx eslint --print-config path/to/file.js
+ *
+ *   Inspecting the config
+ *
+ *     npx eslint --inspect-config
+ *
+ */
 import globals from 'globals';
 import js from '@eslint/js';
 
 import ts from 'typescript-eslint';
 
-import ember from 'eslint-plugin-ember';
-import emberRecommended from 'eslint-plugin-ember/configs/recommended';
-import gjsRecommended from 'eslint-plugin-ember/configs/recommended-gjs';
-import gtsRecommended from 'eslint-plugin-ember/configs/recommended-gts';
+import ember from 'eslint-plugin-ember/recommended';
 
 import prettier from 'eslint-plugin-prettier/recommended';
 import qunit from 'eslint-plugin-qunit';
 import n from 'eslint-plugin-n';
 
-import emberParser from 'ember-eslint-parser';
 import babelParser from '@babel/eslint-parser';
 
 const parserOptions = {
@@ -39,62 +49,57 @@ const parserOptions = {
 
 export default ts.config(
   js.configs.recommended,
+  ember.configs.base,
+  ember.configs.gjs,
+  ember.configs.gts,
   prettier,
+  /**
+   * Ignores must be in their own object
+   * https://eslint.org/docs/latest/use/configure/ignore
+   */
   {
-    files: ['**/*.js'],
-    languageOptions: {
-      parser: babelParser,
-      parserOptions: parserOptions.esm.js,
-      globals: {
-        ...globals.browser,
-      },
-    },
-    plugins: {
-      ember,
-    },
-    rules: {
-      ...emberRecommended.rules,
+    ignores: ['dist/', 'node_modules/', 'coverage/', '!**/.*'],
+  },
+  /**
+   * https://eslint.org/docs/latest/use/configure/configuration-files#configuring-linter-options
+   */
+  {
+    linterOptions: {
+      reportUnusedDisableDirectives: 'error',
     },
   },
   {
-    files: ['**/*.ts'],
-    plugins: { ember },
+    files: ['**/*.js'],
     languageOptions: {
-      parserOptions: parserOptions.esm.ts,
+      parser: babelParser,
     },
-    extends: [...ts.configs.strictTypeChecked, ...emberRecommended],
   },
   {
-    files: ['**/*.gjs'],
+    files: ['**/*.{js,gjs}'],
     languageOptions: {
-      parser: emberParser,
       parserOptions: parserOptions.esm.js,
       globals: {
         ...globals.browser,
       },
     },
-    plugins: {
-      ember,
-    },
-    rules: {
-      ...emberRecommended.rules,
-      ...gjsRecommended.rules,
+  },
+  {
+    files: ['**/*.ts'],
+    languageOptions: {
+      parserOptions: parserOptions.esm.ts,
     },
+    extends: [ember.configs.base, ...ts.configs.recommendedTypeChecked],
   },
   {
     files: ['**/*.gts'],
-    plugins: { ember },
     languageOptions: {
+      parser: ember.parser,
       parserOptions: parserOptions.esm.ts,
     },
-    extends: [
-      ...ts.configs.strictTypeChecked,
-      ...emberRecommended,
-      ...gtsRecommended,
-    ],
+    extends: [...ts.configs.recommendedTypeChecked, ember.configs.gts],
   },
   {
-    files: ['tests/**/*-test.{js,gjs}'],
+    files: ['tests/**/*-test.{js,gjs,ts,gts}'],
     plugins: {
       qunit,
     },
@@ -129,7 +134,7 @@ export default ts.config(
    * ESM node files
    */
   {
-    files: ['*.mjs'],
+    files: ['**/*.mjs'],
     plugins: {
       n,
     },
@@ -143,13 +148,4 @@ export default ts.config(
       },
     },
   },
-  /**
-   * Settings
-   */
-  {
-    ignores: ['dist/', 'node_modules/', 'coverage/', '!**/.*'],
-    linterOptions: {
-      reportUnusedDisableDirectives: 'error',
-    },
-  }
 );
diff --git a/blueprints/app/files/package.json b/blueprints/app/files/package.json
index 662becb84..d2cbef770 100644
--- a/blueprints/app/files/package.json
+++ b/blueprints/app/files/package.json
@@ -49,6 +49,7 @@
     "@glimmer/component": "^1.1.2",
     "@glimmer/tracking": "^1.1.2<% if (typescript) { %>",
     "@glint/environment-ember-loose": "^1.4.0",
+    "@glint/environment-ember-template-imports": "^1.4.0",
     "@glint/template": "^1.4.0",
     "@tsconfig/ember": "^3.0.8",
     "@types/eslint__js": "^8.42.3",
@@ -77,6 +78,7 @@
     "ember-qunit": "^8.1.0",
     "ember-resolver": "^13.0.2",
     "ember-source": "~6.0.0-beta.1",
+    "ember-template-imports": "^4.1.3",
     "ember-template-lint": "^6.0.0<% if (welcome) { %>",
     "ember-welcome-page": "^7.0.2<% } %>",
     "eslint": "^9.12.0",
diff --git a/blueprints/app/files/tsconfig.json b/blueprints/app/files/tsconfig.json
index 9387ba942..d987b0f5a 100644
--- a/blueprints/app/files/tsconfig.json
+++ b/blueprints/app/files/tsconfig.json
@@ -1,5 +1,8 @@
 {
   "extends": "@tsconfig/ember/tsconfig.json",
+  "glint": {
+    "environment": ["ember-loose", "ember-template-imports"]
+  },
   "compilerOptions": {
     // The combination of `baseUrl` with `paths` allows Ember's classic package
     // layout, which is not resolvable with the Node resolution algorithm, to
diff --git a/lib/broccoli/ember-app.js b/lib/broccoli/ember-app.js
index dae062e80..1e5c41384 100644
--- a/lib/broccoli/ember-app.js
+++ b/lib/broccoli/ember-app.js
@@ -9,7 +9,7 @@ const p = require('ember-cli-preprocess-registry/preprocessors');
 const chalk = require('chalk');
 const resolve = require('resolve');
 
-const { assert, deprecate } = require('../debug');
+const { assert, deprecate, DEPRECATIONS } = require('../debug');
 const Project = require('../models/project');
 
 const concat = require('broccoli-concat');
@@ -226,15 +226,7 @@ class EmberApp {
     deprecate(
       'Using the `outputPaths` build option is deprecated, as output paths will no longer be predetermined under Embroider.',
       typeof options.outputPaths === 'undefined',
-      {
-        for: 'ember-cli',
-        id: 'ember-cli.outputPaths-build-option',
-        since: {
-          available: '5.3.0',
-          enabled: '5.3.0',
-        },
-        until: '6.0.0',
-      }
+      DEPRECATIONS.DEPRECATE_OUTPUT_PATHS.options
     );
 
     let resolvePathFor = (defaultPath, specified) => {
diff --git a/lib/commands/init.js b/lib/commands/init.js
index 29ffdd73e..1e48720af 100644
--- a/lib/commands/init.js
+++ b/lib/commands/init.js
@@ -9,7 +9,7 @@ const normalizeBlueprint = require('../utilities/normalize-blueprint-option');
 const mergeBlueprintOptions = require('../utilities/merge-blueprint-options');
 const { isPnpmProject, isYarnProject } = require('../utilities/package-managers');
 const getLangArg = require('../../lib/utilities/get-lang-arg');
-const { deprecate } = require('../debug');
+const { deprecate, DEPRECATIONS } = require('../debug');
 
 module.exports = Command.extend({
   name: 'init',
@@ -126,16 +126,7 @@ module.exports = Command.extend({
       deprecate(
         'Support for generating a Travis CI config file is deprecated.\nYou can keep using Travis CI, or you could also consider switching to GitHub Actions instead.',
         false,
-        {
-          for: 'ember-cli',
-          id: 'travis-ci-support',
-          since: {
-            available: '5.5.0',
-            enabled: '5.5.0',
-          },
-          until: '6.0.0',
-          url: 'https://deprecations.emberjs.com/id/travis-ci-support',
-        }
+        DEPRECATIONS.DEPRECATE_TRAVIS_CI_SUPPORT.options
       );
     }
 
diff --git a/lib/debug/deprecate.js b/lib/debug/deprecate.js
index 4342c39ce..f03702800 100644
--- a/lib/debug/deprecate.js
+++ b/lib/debug/deprecate.js
@@ -3,6 +3,7 @@
 const chalk = require('chalk');
 const semver = require('semver');
 const assert = require('./assert');
+const emberCLIVersion = require('../../package').version;
 
 /**
  * Display a deprecation message.
@@ -71,6 +72,12 @@ function deprecate(description, condition, options) {
     return;
   }
 
+  if (options.for === 'ember-cli' && isDeprecationRemoved(options.until)) {
+    throw new Error(
+      `The API deprecated by ${options.id} was removed in ember-cli ${options.until}. The message was: ${description}. Please see ${options.url} for more details.`
+    );
+  }
+
   let message = formatMessage(description, options);
 
   warn(message);
@@ -117,4 +124,12 @@ function warn(message) {
   console.warn(chalk.yellow(message));
 }
 
+function isDeprecationRemoved(until) {
+  const currentEmberCLIVersion = parseFloat(process.env.OVERRIDE_DEPRECATION_VERSION ?? emberCLIVersion);
+
+  let significantUntil = until.replace(/(\.0+)/g, '');
+  return currentEmberCLIVersion >= parseFloat(significantUntil);
+}
+
 module.exports = deprecate;
+module.exports._isDeprecationRemoved = isDeprecationRemoved;
diff --git a/lib/debug/deprecations.js b/lib/debug/deprecations.js
new file mode 100644
index 000000000..9c99db35e
--- /dev/null
+++ b/lib/debug/deprecations.js
@@ -0,0 +1,34 @@
+'use strict';
+
+const { _isDeprecationRemoved } = require('./deprecate');
+
+function deprecation(options) {
+  return {
+    options,
+    isRemoved: _isDeprecationRemoved(options.until),
+  };
+}
+
+const DEPRECATIONS = {
+  DEPRECATE_OUTPUT_PATHS: deprecation({
+    for: 'ember-cli',
+    id: 'ember-cli.outputPaths-build-option',
+    since: {
+      available: '5.3.0',
+      enabled: '5.3.0',
+    },
+    until: '6.0.0',
+  }),
+  DEPRECATE_TRAVIS_CI_SUPPORT: deprecation({
+    for: 'ember-cli',
+    id: 'travis-ci-support',
+    since: {
+      available: '5.5.0',
+      enabled: '5.5.0',
+    },
+    until: '6.0.0',
+    url: 'https://deprecations.emberjs.com/id/travis-ci-support',
+  }),
+};
+
+module.exports = DEPRECATIONS;
diff --git a/lib/debug/index.js b/lib/debug/index.js
index 10b336ceb..d8b272011 100644
--- a/lib/debug/index.js
+++ b/lib/debug/index.js
@@ -3,4 +3,5 @@
 module.exports = {
   assert: require('./assert'),
   deprecate: require('./deprecate'),
+  DEPRECATIONS: require('./deprecations'),
 };
diff --git a/package.json b/package.json
index 16e627c21..08833e4c4 100644
--- a/package.json
+++ b/package.json
@@ -38,7 +38,7 @@
     "test:slow": "node --unhandled-rejections=strict tests/runner slow"
   },
   "dependencies": {
-    "@pnpm/find-workspace-dir": "^6.0.2",
+    "@pnpm/find-workspace-dir": "^7.0.2",
     "broccoli": "^3.5.2",
     "broccoli-builder": "^0.18.14",
     "broccoli-concat": "^4.2.5",
@@ -55,7 +55,7 @@
     "calculate-cache-key-for-tree": "^2.0.0",
     "capture-exit": "^2.0.0",
     "chalk": "^4.1.2",
-    "ci-info": "^3.8.0",
+    "ci-info": "^4.0.0",
     "clean-base-url": "^1.0.0",
     "compression": "^1.7.4",
     "configstore": "^5.0.1",
@@ -72,7 +72,7 @@
     "ensure-posix-path": "^1.1.1",
     "execa": "^5.1.1",
     "exit": "^0.1.2",
-    "express": "^4.18.1",
+    "express": "^4.21.1",
     "filesize": "^10.0.8",
     "find-up": "^5.0.0",
     "find-yarn-workspace-root": "^2.0.0",
@@ -98,7 +98,7 @@
     "minimatch": "^7.4.3",
     "morgan": "^1.10.0",
     "nopt": "^3.0.6",
-    "npm-package-arg": "^10.1.0",
+    "npm-package-arg": "^12.0.0",
     "os-locale": "^5.0.0",
     "p-defer": "^3.0.0",
     "portfinder": "^1.0.32",
@@ -115,7 +115,7 @@
     "sort-package-json": "^1.57.0",
     "symlink-or-copy": "^1.3.1",
     "temp": "0.9.4",
-    "testem": "^3.15.1",
+    "testem": "^3.15.2",
     "tiny-lr": "^2.0.0",
     "tree-sync": "^2.1.0",
     "walk-sync": "^3.0.0",
@@ -143,7 +143,7 @@
     "jsdom": "^21.1.1",
     "latest-version": "^5.1.0",
     "mocha": "^10.0.0",
-    "nock": "^13.3.0",
+    "nock": "^13.5.5",
     "nyc": "^15.1.0",
     "prettier": "2.8.7",
     "release-it": "^15.10.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2f67793aa..d73d4f9e5 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -9,8 +9,8 @@ importers:
   .:
     dependencies:
       '@pnpm/find-workspace-dir':
-        specifier: ^6.0.2
-        version: 6.0.3
+        specifier: ^7.0.2
+        version: 7.0.2
       babel-remove-types:
         specifier: ^1.0.0
         version: 1.0.0
@@ -63,8 +63,8 @@ importers:
         specifier: ^4.1.2
         version: 4.1.2
       ci-info:
-        specifier: ^3.8.0
-        version: 3.9.0
+        specifier: ^4.0.0
+        version: 4.0.0
       clean-base-url:
         specifier: ^1.0.0
         version: 1.0.0
@@ -114,8 +114,8 @@ importers:
         specifier: ^0.1.2
         version: 0.1.2
       express:
-        specifier: ^4.18.1
-        version: 4.19.2
+        specifier: ^4.21.1
+        version: 4.21.1
       filesize:
         specifier: ^10.0.8
         version: 10.1.4
@@ -192,8 +192,8 @@ importers:
         specifier: ^3.0.6
         version: 3.0.6
       npm-package-arg:
-        specifier: ^10.1.0
-        version: 10.1.0
+        specifier: ^12.0.0
+        version: 12.0.0
       os-locale:
         specifier: ^5.0.0
         version: 5.0.0
@@ -240,8 +240,8 @@ importers:
         specifier: 0.9.4
         version: 0.9.4
       testem:
-        specifier: ^3.15.1
-        version: 3.15.1(bufferutil@4.0.8)(handlebars@4.7.8)(underscore@1.13.7)(utf-8-validate@6.0.4)
+        specifier: ^3.15.2
+        version: 3.15.2(bufferutil@4.0.8)(handlebars@4.7.8)(underscore@1.13.7)(utf-8-validate@6.0.4)
       tiny-lr:
         specifier: ^2.0.0
         version: 2.0.0
@@ -319,8 +319,8 @@ importers:
         specifier: ^10.0.0
         version: 10.6.0
       nock:
-        specifier: ^13.3.0
-        version: 13.5.4
+        specifier: ^13.5.5
+        version: 13.5.5
       nyc:
         specifier: ^15.1.0
         version: 15.1.0
@@ -648,17 +648,17 @@ packages:
     resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==}
     engines: {node: '>=12.22.0'}
 
-  '@pnpm/constants@7.1.1':
-    resolution: {integrity: sha512-31pZqMtjwV+Vaq7MaPrT1EoDFSYwye3dp6BiHIGRJmVThCQwySRKM7hCvqqI94epNkqFAAYoWrNynWoRYosGdw==}
-    engines: {node: '>=16.14'}
+  '@pnpm/constants@9.0.0':
+    resolution: {integrity: sha512-cyZ12A7j1BzeQ9nr5HBdlSLxN1VWnCG/1xjdgDUL/WDlgmVa3k6TI2CktTHjR5w/rWbKudpIaMAmJJk9w+cTRQ==}
+    engines: {node: '>=18.12'}
 
-  '@pnpm/error@5.0.3':
-    resolution: {integrity: sha512-ONJU5cUeoeJSy50qOYsMZQHTA/9QKmGgh1ATfEpCLgtbdwqUiwD9MxHNeXUYYI/pocBCz6r1ZCFqiQvO+8SUKA==}
-    engines: {node: '>=16.14'}
+  '@pnpm/error@6.0.2':
+    resolution: {integrity: sha512-3/wWJYjUyO9ToLaZpBASYIBg87C4DBZ8yfzrt0cSCTbRFDBUNdH0dzwfVKEqhR7A9tpRMyeoRIzPUVxWc+U+RQ==}
+    engines: {node: '>=18.12'}
 
-  '@pnpm/find-workspace-dir@6.0.3':
-    resolution: {integrity: sha512-0iJnNkS4T8lJE4ldOhRERgER1o59iHA1nMlvpUI5lxNC9SUruH6peRUOlP4/rNcDg+UQ9u0rt5loYOnWKCojtw==}
-    engines: {node: '>=16.14'}
+  '@pnpm/find-workspace-dir@7.0.2':
+    resolution: {integrity: sha512-BAcRbWXNBeA9ur+d/ccO2dvxogHr6+6qtiM1AgXzJ6gSfNqJRb6tzgRDgIJGouve9s2P6Qsqr4TbFOltEKuLJg==}
+    engines: {node: '>=18.12'}
 
   '@pnpm/network.ca-file@1.0.2':
     resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==}
@@ -1067,8 +1067,8 @@ packages:
   bluebird@3.7.2:
     resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
 
-  body-parser@1.20.2:
-    resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==}
+  body-parser@1.20.3:
+    resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==}
     engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
 
   body@5.1.0:
@@ -1364,6 +1364,10 @@ packages:
     resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
     engines: {node: '>=8'}
 
+  ci-info@4.0.0:
+    resolution: {integrity: sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==}
+    engines: {node: '>=8'}
+
   class-utils@0.3.6:
     resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==}
     engines: {node: '>=0.10.0'}
@@ -1694,8 +1698,8 @@ packages:
     resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==}
     engines: {node: '>= 0.6'}
 
-  cookie@0.6.0:
-    resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
+  cookie@0.7.1:
+    resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==}
     engines: {node: '>= 0.6'}
 
   cookiejar@2.1.4:
@@ -2012,6 +2016,10 @@ packages:
     resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
     engines: {node: '>= 0.8'}
 
+  encodeurl@2.0.0:
+    resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
+    engines: {node: '>= 0.8'}
+
   end-of-stream@1.4.4:
     resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==}
 
@@ -2188,6 +2196,7 @@ packages:
   eslint@8.57.0:
     resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options.
     hasBin: true
 
   esm@3.2.25:
@@ -2280,8 +2289,8 @@ packages:
     resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==}
     engines: {node: '>=0.10.0'}
 
-  express@4.19.2:
-    resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==}
+  express@4.21.1:
+    resolution: {integrity: sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==}
     engines: {node: '>= 0.10.0'}
 
   ext@1.7.0:
@@ -2375,8 +2384,8 @@ packages:
     resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==}
     engines: {node: '>= 0.8'}
 
-  finalhandler@1.2.0:
-    resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==}
+  finalhandler@1.3.1:
+    resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==}
     engines: {node: '>= 0.8'}
 
   find-cache-dir@3.3.2:
@@ -2802,9 +2811,9 @@ packages:
     resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==}
     engines: {node: '>=0.10.0'}
 
-  hosted-git-info@6.1.1:
-    resolution: {integrity: sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==}
-    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+  hosted-git-info@8.0.0:
+    resolution: {integrity: sha512-4nw3vOVR+vHUOT8+U4giwe2tcGv+R3pwwRidUe67DoMBTjhrfr6rZYJVVwdkBE+Um050SG+X9tf0Jo4fOpn01w==}
+    engines: {node: ^18.17.0 || >=20.5.0}
 
   html-encoding-sniffer@3.0.0:
     resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==}
@@ -3497,6 +3506,9 @@ packages:
     resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==}
     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
 
+  lru-cache@10.4.3:
+    resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
+
   lru-cache@5.1.1:
     resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
 
@@ -3576,8 +3588,8 @@ packages:
   memory-streams@0.1.3:
     resolution: {integrity: sha512-qVQ/CjkMyMInPaaRMrwWNDvf6boRZXaT/DbQeMYcCWuXPEBf1v8qChOc9OlEVQp2uOvRXa1Qu30fLmKhY6NipA==}
 
-  merge-descriptors@1.0.1:
-    resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==}
+  merge-descriptors@1.0.3:
+    resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==}
 
   merge-stream@2.0.0:
     resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
@@ -3745,8 +3757,8 @@ packages:
   nice-try@1.0.5:
     resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==}
 
-  nock@13.5.4:
-    resolution: {integrity: sha512-yAyTfdeNJGGBFxWdzSKCBYxs5FxLbCg5X5Q4ets974hcQzG1+qCxvIyOo4j2Ry6MUlhWVMX4OoYDefAIIwupjw==}
+  nock@13.5.5:
+    resolution: {integrity: sha512-XKYnqUrCwXC8DGG1xX4YH5yNIrlh9c065uaMZZHUoeUUINTOyt+x/G+ezYk0Ft6ExSREVIs+qBJDK503viTfFA==}
     engines: {node: '>= 10.13'}
 
   node-domexception@1.0.0:
@@ -3808,9 +3820,9 @@ packages:
     resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==}
     engines: {node: '>=14.16'}
 
-  npm-package-arg@10.1.0:
-    resolution: {integrity: sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==}
-    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+  npm-package-arg@12.0.0:
+    resolution: {integrity: sha512-ZTE0hbwSdTNL+Stx2zxSqdu2KZfNDcrtrLdIk7XGnQFYBWYDho/ORvXtn5XEePcL3tFpGjHCV3X3xrtDh7eZ+A==}
+    engines: {node: ^18.17.0 || >=20.5.0}
 
   npm-run-path@2.0.2:
     resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==}
@@ -4070,8 +4082,8 @@ packages:
     resolution: {integrity: sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==}
     engines: {node: '>=0.10.0'}
 
-  path-to-regexp@0.1.7:
-    resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==}
+  path-to-regexp@0.1.10:
+    resolution: {integrity: sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==}
 
   path-type@4.0.0:
     resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
@@ -4131,9 +4143,9 @@ packages:
     resolution: {integrity: sha512-is0ctgGdPJ5951KulgfzvHGwJtZ5ck8l042vRkV6jrkpBzTmb/lueTqguWHy2JfVA+RY6gFVlaZgUS0j7S/dsw==}
     engines: {node: '>= 0.9.0'}
 
-  proc-log@3.0.0:
-    resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==}
-    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+  proc-log@5.0.0:
+    resolution: {integrity: sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==}
+    engines: {node: ^18.17.0 || >=20.5.0}
 
   process-on-spawn@1.0.0:
     resolution: {integrity: sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==}
@@ -4196,14 +4208,14 @@ packages:
   qs@1.0.2:
     resolution: {integrity: sha512-tHuOP9TN/1VmDM/ylApGK1QF3PSIP8I6bHDEfoKNQeViREQ/sfu1bAUrA1hoDun8p8Tpm7jcsz47g+3PiGoYdg==}
 
-  qs@6.11.0:
-    resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==}
-    engines: {node: '>=0.6'}
-
   qs@6.12.3:
     resolution: {integrity: sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ==}
     engines: {node: '>=0.6'}
 
+  qs@6.13.0:
+    resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==}
+    engines: {node: '>=0.6'}
+
   querystringify@2.2.0:
     resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
 
@@ -4506,15 +4518,15 @@ packages:
     engines: {node: '>=10'}
     hasBin: true
 
-  send@0.18.0:
-    resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==}
+  send@0.19.0:
+    resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==}
     engines: {node: '>= 0.8.0'}
 
   serialize-javascript@6.0.2:
     resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==}
 
-  serve-static@1.15.0:
-    resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==}
+  serve-static@1.16.2:
+    resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==}
     engines: {node: '>= 0.8.0'}
 
   set-blocking@2.0.0:
@@ -4828,8 +4840,8 @@ packages:
     resolution: {integrity: sha512-790e9vJKdfddWNOaxW1/V9FcMk48cPEl3eJSj2i8Hh1fX89qArEJ6cp3DBnaECpGXc3xKJVWbc1jeNlWYWgiMg==}
     engines: {node: '>= 16'}
 
-  testem@3.15.1:
-    resolution: {integrity: sha512-532OJy6VVsnDFEGZBdWVywvceNWdjdxJruC6qCDzLH586+eh1duWk5ju6QSRqQdP6gZB7zNiUJU9dSQdHPzFuA==}
+  testem@3.15.2:
+    resolution: {integrity: sha512-mRzqZktqTCWi/rUP/RQOKXvMtuvY3lxuzBVb1xGXPnRNGMEj/1DaLGn6X447yOsz6SlWxSsZfcNuiE7fT1MOKg==}
     engines: {node: '>= 7.*'}
     hasBin: true
 
@@ -5115,9 +5127,9 @@ packages:
     resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
     hasBin: true
 
-  validate-npm-package-name@5.0.1:
-    resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==}
-    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+  validate-npm-package-name@6.0.0:
+    resolution: {integrity: sha512-d7KLgL1LD3U3fgnvWEY1cQXoO/q6EQ1BSz48Sa149V/5zVTAbgmZIpyI8TRi6U9/JNyeYLlTKsEMPtLC27RFUg==}
+    engines: {node: ^18.17.0 || >=20.5.0}
 
   vary@1.1.2:
     resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
@@ -5756,15 +5768,15 @@ snapshots:
 
   '@pnpm/config.env-replace@1.1.0': {}
 
-  '@pnpm/constants@7.1.1': {}
+  '@pnpm/constants@9.0.0': {}
 
-  '@pnpm/error@5.0.3':
+  '@pnpm/error@6.0.2':
     dependencies:
-      '@pnpm/constants': 7.1.1
+      '@pnpm/constants': 9.0.0
 
-  '@pnpm/find-workspace-dir@6.0.3':
+  '@pnpm/find-workspace-dir@7.0.2':
     dependencies:
-      '@pnpm/error': 5.0.3
+      '@pnpm/error': 6.0.2
       find-up: 5.0.0
 
   '@pnpm/network.ca-file@1.0.2':
@@ -5806,7 +5818,7 @@ snapshots:
 
   '@types/connect@3.4.38':
     dependencies:
-      '@types/node': 20.14.11
+      '@types/node': 20.14.12
 
   '@types/cookie@0.4.1': {}
 
@@ -5889,7 +5901,7 @@ snapshots:
   '@types/send@0.17.4':
     dependencies:
       '@types/mime': 1.3.5
-      '@types/node': 20.14.11
+      '@types/node': 20.14.12
 
   '@types/serve-static@1.15.7':
     dependencies:
@@ -6181,7 +6193,7 @@ snapshots:
 
   bluebird@3.7.2: {}
 
-  body-parser@1.20.2:
+  body-parser@1.20.3:
     dependencies:
       bytes: 3.1.2
       content-type: 1.0.5
@@ -6191,7 +6203,7 @@ snapshots:
       http-errors: 2.0.0
       iconv-lite: 0.4.24
       on-finished: 2.4.1
-      qs: 6.11.0
+      qs: 6.13.0
       raw-body: 2.5.2
       type-is: 1.6.18
       unpipe: 1.0.0
@@ -6728,6 +6740,8 @@ snapshots:
 
   ci-info@3.9.0: {}
 
+  ci-info@4.0.0: {}
+
   class-utils@0.3.6:
     dependencies:
       arr-union: 3.1.0
@@ -6907,7 +6921,7 @@ snapshots:
 
   cookie@0.4.2: {}
 
-  cookie@0.6.0: {}
+  cookie@0.7.1: {}
 
   cookiejar@2.1.4: {}
 
@@ -7213,6 +7227,8 @@ snapshots:
 
   encodeurl@1.0.2: {}
 
+  encodeurl@2.0.0: {}
+
   end-of-stream@1.4.4:
     dependencies:
       once: 1.4.0
@@ -7605,34 +7621,34 @@ snapshots:
     dependencies:
       homedir-polyfill: 1.0.3
 
-  express@4.19.2:
+  express@4.21.1:
     dependencies:
       accepts: 1.3.8
       array-flatten: 1.1.1
-      body-parser: 1.20.2
+      body-parser: 1.20.3
       content-disposition: 0.5.4
       content-type: 1.0.5
-      cookie: 0.6.0
+      cookie: 0.7.1
       cookie-signature: 1.0.6
       debug: 2.6.9
       depd: 2.0.0
-      encodeurl: 1.0.2
+      encodeurl: 2.0.0
       escape-html: 1.0.3
       etag: 1.8.1
-      finalhandler: 1.2.0
+      finalhandler: 1.3.1
       fresh: 0.5.2
       http-errors: 2.0.0
-      merge-descriptors: 1.0.1
+      merge-descriptors: 1.0.3
       methods: 1.1.2
       on-finished: 2.4.1
       parseurl: 1.3.3
-      path-to-regexp: 0.1.7
+      path-to-regexp: 0.1.10
       proxy-addr: 2.0.7
-      qs: 6.11.0
+      qs: 6.13.0
       range-parser: 1.2.1
       safe-buffer: 5.2.1
-      send: 0.18.0
-      serve-static: 1.15.0
+      send: 0.19.0
+      serve-static: 1.16.2
       setprototypeof: 1.2.0
       statuses: 2.0.1
       type-is: 1.6.18
@@ -7764,10 +7780,10 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  finalhandler@1.2.0:
+  finalhandler@1.3.1:
     dependencies:
       debug: 2.6.9
-      encodeurl: 1.0.2
+      encodeurl: 2.0.0
       escape-html: 1.0.3
       on-finished: 2.4.1
       parseurl: 1.3.3
@@ -8340,9 +8356,9 @@ snapshots:
     dependencies:
       parse-passwd: 1.0.0
 
-  hosted-git-info@6.1.1:
+  hosted-git-info@8.0.0:
     dependencies:
-      lru-cache: 7.18.3
+      lru-cache: 10.4.3
 
   html-encoding-sniffer@3.0.0:
     dependencies:
@@ -9056,6 +9072,8 @@ snapshots:
 
   lowercase-keys@3.0.0: {}
 
+  lru-cache@10.4.3: {}
+
   lru-cache@5.1.1:
     dependencies:
       yallist: 3.1.1
@@ -9147,7 +9165,7 @@ snapshots:
     dependencies:
       readable-stream: 1.0.34
 
-  merge-descriptors@1.0.1: {}
+  merge-descriptors@1.0.3: {}
 
   merge-stream@2.0.0: {}
 
@@ -9323,7 +9341,7 @@ snapshots:
 
   nice-try@1.0.5: {}
 
-  nock@13.5.4:
+  nock@13.5.5:
     dependencies:
       debug: 4.3.5(supports-color@8.1.1)
       json-stringify-safe: 5.0.1
@@ -9378,12 +9396,12 @@ snapshots:
 
   normalize-url@8.0.1: {}
 
-  npm-package-arg@10.1.0:
+  npm-package-arg@12.0.0:
     dependencies:
-      hosted-git-info: 6.1.1
-      proc-log: 3.0.0
+      hosted-git-info: 8.0.0
+      proc-log: 5.0.0
       semver: 7.6.3
-      validate-npm-package-name: 5.0.1
+      validate-npm-package-name: 6.0.0
 
   npm-run-path@2.0.2:
     dependencies:
@@ -9694,7 +9712,7 @@ snapshots:
     dependencies:
       path-root-regex: 0.1.2
 
-  path-to-regexp@0.1.7: {}
+  path-to-regexp@0.1.10: {}
 
   path-type@4.0.0: {}
 
@@ -9739,7 +9757,7 @@ snapshots:
 
   printf@0.6.1: {}
 
-  proc-log@3.0.0: {}
+  proc-log@5.0.0: {}
 
   process-on-spawn@1.0.0:
     dependencies:
@@ -9811,11 +9829,11 @@ snapshots:
 
   qs@1.0.2: {}
 
-  qs@6.11.0:
+  qs@6.12.3:
     dependencies:
       side-channel: 1.0.6
 
-  qs@6.12.3:
+  qs@6.13.0:
     dependencies:
       side-channel: 1.0.6
 
@@ -10159,7 +10177,7 @@ snapshots:
 
   semver@7.6.3: {}
 
-  send@0.18.0:
+  send@0.19.0:
     dependencies:
       debug: 2.6.9
       depd: 2.0.0
@@ -10181,12 +10199,12 @@ snapshots:
     dependencies:
       randombytes: 2.1.0
 
-  serve-static@1.15.0:
+  serve-static@1.16.2:
     dependencies:
-      encodeurl: 1.0.2
+      encodeurl: 2.0.0
       escape-html: 1.0.3
       parseurl: 1.3.3
-      send: 0.18.0
+      send: 0.19.0
     transitivePeerDependencies:
       - supports-color
 
@@ -10560,7 +10578,7 @@ snapshots:
       stringify-object-es5: 2.5.0
       theredoc: 1.0.0
 
-  testem@3.15.1(bufferutil@4.0.8)(handlebars@4.7.8)(underscore@1.13.7)(utf-8-validate@6.0.4):
+  testem@3.15.2(bufferutil@4.0.8)(handlebars@4.7.8)(underscore@1.13.7)(utf-8-validate@6.0.4):
     dependencies:
       '@xmldom/xmldom': 0.8.10
       backbone: 1.6.0
@@ -10570,7 +10588,7 @@ snapshots:
       compression: 1.7.4
       consolidate: 0.16.0(handlebars@4.7.8)(lodash@4.17.21)(mustache@4.2.0)(underscore@1.13.7)
       execa: 1.0.0
-      express: 4.19.2
+      express: 4.21.1
       fireworm: 0.7.2
       glob: 7.2.3
       http-proxy: 1.18.1
@@ -10938,7 +10956,7 @@ snapshots:
 
   uuid@8.3.2: {}
 
-  validate-npm-package-name@5.0.1: {}
+  validate-npm-package-name@6.0.0: {}
 
   vary@1.1.2: {}
 
@@ -11207,7 +11225,7 @@ snapshots:
 
   yuidocjs@0.10.2:
     dependencies:
-      express: 4.19.2
+      express: 4.21.1
       graceful-fs: 4.2.11
       markdown-it: 4.4.0
       mdn-links: 0.1.0


Test patch:
diff --git a/tests/acceptance/brocfile-smoke-test-slow.js b/tests/acceptance/brocfile-smoke-test-slow.js
index c87536c37..ad04130a5 100644
--- a/tests/acceptance/brocfile-smoke-test-slow.js
+++ b/tests/acceptance/brocfile-smoke-test-slow.js
@@ -15,6 +15,7 @@ let cleanupRun = acceptance.cleanupRun;
 
 const { expect } = require('chai');
 const { dir, file } = require('chai-files');
+const { DEPRECATIONS } = require('../../lib/debug');
 
 let appName = 'some-cool-app';
 let appRoot;
@@ -417,6 +418,10 @@ describe('Acceptance: brocfile-smoke-test', function () {
   // custom outputPaths are deprecated under embroider
   if (!isExperimentEnabled('EMBROIDER')) {
     it('multiple paths can be CSS preprocessed', async function () {
+      if (DEPRECATIONS.DEPRECATE_OUTPUT_PATHS.isRemoved) {
+        this.skip();
+      }
+
       await copyFixtureFiles('brocfile-tests/multiple-sass-files');
 
       let packageJsonPath = path.join(appRoot, 'package.json');
diff --git a/tests/acceptance/init-test.js b/tests/acceptance/init-test.js
index c34aadd4f..b7135193d 100644
--- a/tests/acceptance/init-test.js
+++ b/tests/acceptance/init-test.js
@@ -17,6 +17,7 @@ const lintFix = require('../../lib/utilities/lint-fix');
 
 const { expect } = require('chai');
 const { dir, file } = require('chai-files');
+const { DEPRECATIONS } = require('../../lib/debug');
 
 let defaultIgnoredFiles = Blueprint.ignoredFiles;
 
@@ -196,6 +197,10 @@ describe('Acceptance: ember init', function () {
   });
 
   it('configurable CI option', async function () {
+    if (DEPRECATIONS.DEPRECATE_TRAVIS_CI_SUPPORT.isRemoved) {
+      this.skip();
+    }
+
     await ember(['init', '--ci-provider=travis', '--skip-npm']);
 
     let fixturePath = 'app/npm-travis';
diff --git a/tests/acceptance/new-test.js b/tests/acceptance/new-test.js
index 2f722e0ae..d54aedf83 100644
--- a/tests/acceptance/new-test.js
+++ b/tests/acceptance/new-test.js
@@ -17,6 +17,7 @@ const { isExperimentEnabled } = require('../../lib/experiments');
 const { expect } = require('chai');
 const { dir, file } = require('chai-files');
 const assertVersionLock = require('../helpers/assert-version-lock');
+const { DEPRECATIONS } = require('../../lib/debug');
 
 let tmpDir = './tmp/new-test';
 
@@ -632,6 +633,10 @@ describe('Acceptance: ember new', function () {
     });
 
     it('configurable CI option', async function () {
+      if (DEPRECATIONS.DEPRECATE_TRAVIS_CI_SUPPORT.isRemoved) {
+        this.skip();
+      }
+
       await ember(['new', 'foo', '--ci-provider=travis', '--skip-npm', '--skip-git']);
 
       let fixturePath = 'app/npm-travis';
@@ -648,6 +653,9 @@ describe('Acceptance: ember new', function () {
     });
 
     it('configurable CI option with yarn', async function () {
+      if (DEPRECATIONS.DEPRECATE_TRAVIS_CI_SUPPORT.isRemoved) {
+        this.skip();
+      }
       await ember(['new', 'foo', '--ci-provider=travis', '--skip-npm', '--skip-git', '--yarn']);
 
       let fixturePath = 'app/yarn-travis';
@@ -663,6 +671,10 @@ describe('Acceptance: ember new', function () {
     });
 
     it('addon configurable CI option', async function () {
+      if (DEPRECATIONS.DEPRECATE_TRAVIS_CI_SUPPORT.isRemoved) {
+        this.skip();
+      }
+
       await ember(['addon', 'foo', '--ci-provider=travis', '--skip-npm', '--skip-git']);
 
       let namespace = 'addon';
diff --git a/tests/fixtures/addon/defaults-travis/package.json b/tests/fixtures/addon/defaults-travis/package.json
index 96792112e..115fc7a30 100644
--- a/tests/fixtures/addon/defaults-travis/package.json
+++ b/tests/fixtures/addon/defaults-travis/package.json
@@ -29,7 +29,8 @@
   },
   "dependencies": {
     "ember-cli-babel": "^7.26.6",
-    "ember-cli-htmlbars": "^5.7.1"
+    "ember-cli-htmlbars": "^5.7.1",
+    "ember-template-imports": "^4.1.3"
   },
   "devDependencies": {
     "@babel/eslint-parser": "^7.19.1",
diff --git a/tests/fixtures/addon/defaults/package.json b/tests/fixtures/addon/defaults/package.json
index 11daa2d3d..9561ab7c8 100644
--- a/tests/fixtures/addon/defaults/package.json
+++ b/tests/fixtures/addon/defaults/package.json
@@ -30,7 +30,8 @@
   "dependencies": {
     "@babel/core": "^7.25.2",
     "ember-cli-babel": "^8.2.0",
-    "ember-cli-htmlbars": "^6.3.0"
+    "ember-cli-htmlbars": "^6.3.0",
+    "ember-template-imports": "^4.1.3"
   },
   "devDependencies": {
     "@babel/eslint-parser": "^7.25.1",
diff --git a/tests/fixtures/addon/eslint.config.mjs b/tests/fixtures/addon/eslint.config.mjs
index e05042fd2..b895cc463 100644
--- a/tests/fixtures/addon/eslint.config.mjs
+++ b/tests/fixtures/addon/eslint.config.mjs
@@ -1,15 +1,25 @@
+/**
+ * Debugging:
+ *   https://eslint.org/docs/latest/use/configure/debug
+ *  ----------------------------------------------------
+ *
+ *   Print a file's calculated configuration
+ *
+ *     npx eslint --print-config path/to/file.js
+ *
+ *   Inspecting the config
+ *
+ *     npx eslint --inspect-config
+ *
+ */
 import globals from 'globals';
 import js from '@eslint/js';
 
-import ember from 'eslint-plugin-ember';
-import emberRecommended from 'eslint-plugin-ember/configs/recommended';
-import gjsRecommended from 'eslint-plugin-ember/configs/recommended-gjs';
-
+import ember from 'eslint-plugin-ember/recommended';
 import prettier from 'eslint-plugin-prettier/recommended';
 import qunit from 'eslint-plugin-qunit';
 import n from 'eslint-plugin-n';
 
-import emberParser from 'ember-eslint-parser';
 import babelParser from '@babel/eslint-parser';
 
 const esmParserOptions = {
@@ -26,8 +36,19 @@ const esmParserOptions = {
 export default [
   js.configs.recommended,
   prettier,
+  ember.configs.base,
+  ember.configs.gjs,
+  /**
+   * Ignores must be in their own object
+   * https://eslint.org/docs/latest/use/configure/ignore
+   */
   {
     ignores: ['dist/', 'node_modules/', 'coverage/', '!**/.*'],
+  },
+  /**
+   * https://eslint.org/docs/latest/use/configure/configuration-files#configuring-linter-options
+   */
+  {
     linterOptions: {
       reportUnusedDisableDirectives: 'error',
     },
@@ -36,35 +57,16 @@ export default [
     files: ['**/*.js'],
     languageOptions: {
       parser: babelParser,
-      parserOptions: esmParserOptions,
-      globals: {
-        ...globals.browser,
-      },
-    },
-    plugins: {
-      ember,
-    },
-    rules: {
-      ...emberRecommended.rules,
-      ...gjsRecommended.rules,
     },
   },
   {
-    files: ['**/*.gjs'],
+    files: ['**/*.{js,gjs}'],
     languageOptions: {
-      parser: emberParser,
       parserOptions: esmParserOptions,
       globals: {
         ...globals.browser,
       },
     },
-    plugins: {
-      ember,
-    },
-    rules: {
-      ...emberRecommended.rules,
-      ...gjsRecommended.rules,
-    },
   },
   {
     files: ['tests/**/*-test.{js,gjs}'],
@@ -102,7 +104,7 @@ export default [
    * ESM node files
    */
   {
-    files: ['*.mjs'],
+    files: ['**/*.mjs'],
     plugins: {
       n,
     },
diff --git a/tests/fixtures/addon/pnpm/package.json b/tests/fixtures/addon/pnpm/package.json
index 2a5f228e2..7982139f1 100644
--- a/tests/fixtures/addon/pnpm/package.json
+++ b/tests/fixtures/addon/pnpm/package.json
@@ -30,7 +30,8 @@
   "dependencies": {
     "@babel/core": "^7.25.2",
     "ember-cli-babel": "^8.2.0",
-    "ember-cli-htmlbars": "^6.3.0"
+    "ember-cli-htmlbars": "^6.3.0",
+    "ember-template-imports": "^4.1.3"
   },
   "devDependencies": {
     "@babel/eslint-parser": "^7.25.1",
diff --git a/tests/fixtures/addon/typescript/eslint.config.mjs b/tests/fixtures/addon/typescript/eslint.config.mjs
index 8acc12d10..c84c3aebe 100644
--- a/tests/fixtures/addon/typescript/eslint.config.mjs
+++ b/tests/fixtures/addon/typescript/eslint.config.mjs
@@ -1,18 +1,28 @@
+/**
+ * Debugging:
+ *   https://eslint.org/docs/latest/use/configure/debug
+ *  ----------------------------------------------------
+ *
+ *   Print a file's calculated configuration
+ *
+ *     npx eslint --print-config path/to/file.js
+ *
+ *   Inspecting the config
+ *
+ *     npx eslint --inspect-config
+ *
+ */
 import globals from 'globals';
 import js from '@eslint/js';
 
 import ts from 'typescript-eslint';
 
-import ember from 'eslint-plugin-ember';
-import emberRecommended from 'eslint-plugin-ember/configs/recommended';
-import gjsRecommended from 'eslint-plugin-ember/configs/recommended-gjs';
-import gtsRecommended from 'eslint-plugin-ember/configs/recommended-gts';
+import ember from 'eslint-plugin-ember/recommended';
 
 import prettier from 'eslint-plugin-prettier/recommended';
 import qunit from 'eslint-plugin-qunit';
 import n from 'eslint-plugin-n';
 
-import emberParser from 'ember-eslint-parser';
 import babelParser from '@babel/eslint-parser';
 
 const parserOptions = {
@@ -39,62 +49,57 @@ const parserOptions = {
 
 export default ts.config(
   js.configs.recommended,
+  ember.configs.base,
+  ember.configs.gjs,
+  ember.configs.gts,
   prettier,
+  /**
+   * Ignores must be in their own object
+   * https://eslint.org/docs/latest/use/configure/ignore
+   */
   {
-    files: ['**/*.js'],
-    languageOptions: {
-      parser: babelParser,
-      parserOptions: parserOptions.esm.js,
-      globals: {
-        ...globals.browser,
-      },
-    },
-    plugins: {
-      ember,
-    },
-    rules: {
-      ...emberRecommended.rules,
+    ignores: ['dist/', 'node_modules/', 'coverage/', '!**/.*'],
+  },
+  /**
+   * https://eslint.org/docs/latest/use/configure/configuration-files#configuring-linter-options
+   */
+  {
+    linterOptions: {
+      reportUnusedDisableDirectives: 'error',
     },
   },
   {
-    files: ['**/*.ts'],
-    plugins: { ember },
+    files: ['**/*.js'],
     languageOptions: {
-      parserOptions: parserOptions.esm.ts,
+      parser: babelParser,
     },
-    extends: [...ts.configs.strictTypeChecked, ...emberRecommended],
   },
   {
-    files: ['**/*.gjs'],
+    files: ['**/*.{js,gjs}'],
     languageOptions: {
-      parser: emberParser,
       parserOptions: parserOptions.esm.js,
       globals: {
         ...globals.browser,
       },
     },
-    plugins: {
-      ember,
-    },
-    rules: {
-      ...emberRecommended.rules,
-      ...gjsRecommended.rules,
+  },
+  {
+    files: ['**/*.ts'],
+    languageOptions: {
+      parserOptions: parserOptions.esm.ts,
     },
+    extends: [ember.configs.base, ...ts.configs.recommendedTypeChecked],
   },
   {
     files: ['**/*.gts'],
-    plugins: { ember },
     languageOptions: {
+      parser: ember.parser,
       parserOptions: parserOptions.esm.ts,
     },
-    extends: [
-      ...ts.configs.strictTypeChecked,
-      ...emberRecommended,
-      ...gtsRecommended,
-    ],
+    extends: [...ts.configs.recommendedTypeChecked, ember.configs.gts],
   },
   {
-    files: ['tests/**/*-test.{js,gjs}'],
+    files: ['tests/**/*-test.{js,gjs,ts,gts}'],
     plugins: {
       qunit,
     },
@@ -129,7 +134,7 @@ export default ts.config(
    * ESM node files
    */
   {
-    files: ['*.mjs'],
+    files: ['**/*.mjs'],
     plugins: {
       n,
     },
@@ -143,13 +148,4 @@ export default ts.config(
       },
     },
   },
-  /**
-   * Settings
-   */
-  {
-    ignores: ['dist/', 'node_modules/', 'coverage/', '!**/.*'],
-    linterOptions: {
-      reportUnusedDisableDirectives: 'error',
-    },
-  }
 );
diff --git a/tests/fixtures/addon/typescript/package.json b/tests/fixtures/addon/typescript/package.json
index e03ccef87..3de0dbdb4 100644
--- a/tests/fixtures/addon/typescript/package.json
+++ b/tests/fixtures/addon/typescript/package.json
@@ -48,7 +48,8 @@
   "dependencies": {
     "@babel/core": "^7.25.2",
     "ember-cli-babel": "^8.2.0",
-    "ember-cli-htmlbars": "^6.3.0"
+    "ember-cli-htmlbars": "^6.3.0",
+    "ember-template-imports": "^4.1.3"
   },
   "devDependencies": {
     "@ember/optional-features": "^2.1.0",
@@ -58,6 +59,7 @@
     "@glimmer/component": "^1.1.2",
     "@glimmer/tracking": "^1.1.2",
     "@glint/environment-ember-loose": "^1.4.0",
+    "@glint/environment-ember-template-imports": "^1.4.0",
     "@glint/template": "^1.4.0",
     "@tsconfig/ember": "^3.0.8",
     "@types/eslint__js": "^8.42.3",
diff --git a/tests/fixtures/addon/typescript/tsconfig.json b/tests/fixtures/addon/typescript/tsconfig.json
index b4455bf29..80b7f1c5c 100644
--- a/tests/fixtures/addon/typescript/tsconfig.json
+++ b/tests/fixtures/addon/typescript/tsconfig.json
@@ -1,5 +1,8 @@
 {
   "extends": "@tsconfig/ember/tsconfig.json",
+  "glint": {
+    "environment": ["ember-loose", "ember-template-imports"]
+  },
   "compilerOptions": {
     // The combination of `baseUrl` with `paths` allows Ember's classic package
     // layout, which is not resolvable with the Node resolution algorithm, to
diff --git a/tests/fixtures/addon/yarn/package.json b/tests/fixtures/addon/yarn/package.json
index 52c43e3ce..8c270df1a 100644
--- a/tests/fixtures/addon/yarn/package.json
+++ b/tests/fixtures/addon/yarn/package.json
@@ -30,7 +30,8 @@
   "dependencies": {
     "@babel/core": "^7.25.2",
     "ember-cli-babel": "^8.2.0",
-    "ember-cli-htmlbars": "^6.3.0"
+    "ember-cli-htmlbars": "^6.3.0",
+    "ember-template-imports": "^4.1.3"
   },
   "devDependencies": {
     "@babel/eslint-parser": "^7.25.1",
diff --git a/tests/fixtures/app/defaults/package.json b/tests/fixtures/app/defaults/package.json
index c0d37a627..12e835e98 100644
--- a/tests/fixtures/app/defaults/package.json
+++ b/tests/fixtures/app/defaults/package.json
@@ -54,6 +54,7 @@
     "ember-qunit": "^8.1.0",
     "ember-resolver": "^13.0.2",
     "ember-source": "~6.0.0-beta.1",
+    "ember-template-imports": "^4.1.3",
     "ember-template-lint": "^6.0.0",
     "ember-welcome-page": "^7.0.2",
     "eslint": "^9.12.0",
diff --git a/tests/fixtures/app/embroider-no-welcome/package.json b/tests/fixtures/app/embroider-no-welcome/package.json
index 598553aac..669d2d9ce 100644
--- a/tests/fixtures/app/embroider-no-welcome/package.json
+++ b/tests/fixtures/app/embroider-no-welcome/package.json
@@ -55,6 +55,7 @@
     "ember-qunit": "^8.1.0",
     "ember-resolver": "^13.0.2",
     "ember-source": "~6.0.0-beta.1",
+    "ember-template-imports": "^4.1.3",
     "ember-template-lint": "^6.0.0",
     "eslint": "^9.12.0",
     "eslint-config-prettier": "^9.1.0",
diff --git a/tests/fixtures/app/embroider-pnpm/package.json b/tests/fixtures/app/embroider-pnpm/package.json
index b9cf3f4aa..2376033fa 100644
--- a/tests/fixtures/app/embroider-pnpm/package.json
+++ b/tests/fixtures/app/embroider-pnpm/package.json
@@ -55,6 +55,7 @@
     "ember-qunit": "^8.1.0",
     "ember-resolver": "^13.0.2",
     "ember-source": "~6.0.0-beta.1",
+    "ember-template-imports": "^4.1.3",
     "ember-template-lint": "^6.0.0",
     "ember-welcome-page": "^7.0.2",
     "eslint": "^9.12.0",
diff --git a/tests/fixtures/app/embroider-yarn/package.json b/tests/fixtures/app/embroider-yarn/package.json
index b9da16d79..246adbf73 100644
--- a/tests/fixtures/app/embroider-yarn/package.json
+++ b/tests/fixtures/app/embroider-yarn/package.json
@@ -55,6 +55,7 @@
     "ember-qunit": "^8.1.0",
     "ember-resolver": "^13.0.2",
     "ember-source": "~6.0.0-beta.1",
+    "ember-template-imports": "^4.1.3",
     "ember-template-lint": "^6.0.0",
     "ember-welcome-page": "^7.0.2",
     "eslint": "^9.12.0",
diff --git a/tests/fixtures/app/embroider/package.json b/tests/fixtures/app/embroider/package.json
index 484ce0bdd..3ea359fcf 100644
--- a/tests/fixtures/app/embroider/package.json
+++ b/tests/fixtures/app/embroider/package.json
@@ -55,6 +55,7 @@
     "ember-qunit": "^8.1.0",
     "ember-resolver": "^13.0.2",
     "ember-source": "~6.0.0-beta.1",
+    "ember-template-imports": "^4.1.3",
     "ember-template-lint": "^6.0.0",
     "ember-welcome-page": "^7.0.2",
     "eslint": "^9.12.0",
diff --git a/tests/fixtures/app/eslint.config.mjs b/tests/fixtures/app/eslint.config.mjs
index e05042fd2..b895cc463 100644
--- a/tests/fixtures/app/eslint.config.mjs
+++ b/tests/fixtures/app/eslint.config.mjs
@@ -1,15 +1,25 @@
+/**
+ * Debugging:
+ *   https://eslint.org/docs/latest/use/configure/debug
+ *  ----------------------------------------------------
+ *
+ *   Print a file's calculated configuration
+ *
+ *     npx eslint --print-config path/to/file.js
+ *
+ *   Inspecting the config
+ *
+ *     npx eslint --inspect-config
+ *
+ */
 import globals from 'globals';
 import js from '@eslint/js';
 
-import ember from 'eslint-plugin-ember';
-import emberRecommended from 'eslint-plugin-ember/configs/recommended';
-import gjsRecommended from 'eslint-plugin-ember/configs/recommended-gjs';
-
+import ember from 'eslint-plugin-ember/recommended';
 import prettier from 'eslint-plugin-prettier/recommended';
 import qunit from 'eslint-plugin-qunit';
 import n from 'eslint-plugin-n';
 
-import emberParser from 'ember-eslint-parser';
 import babelParser from '@babel/eslint-parser';
 
 const esmParserOptions = {
@@ -26,8 +36,19 @@ const esmParserOptions = {
 export default [
   js.configs.recommended,
   prettier,
+  ember.configs.base,
+  ember.configs.gjs,
+  /**
+   * Ignores must be in their own object
+   * https://eslint.org/docs/latest/use/configure/ignore
+   */
   {
     ignores: ['dist/', 'node_modules/', 'coverage/', '!**/.*'],
+  },
+  /**
+   * https://eslint.org/docs/latest/use/configure/configuration-files#configuring-linter-options
+   */
+  {
     linterOptions: {
       reportUnusedDisableDirectives: 'error',
     },
@@ -36,35 +57,16 @@ export default [
     files: ['**/*.js'],
     languageOptions: {
       parser: babelParser,
-      parserOptions: esmParserOptions,
-      globals: {
-        ...globals.browser,
-      },
-    },
-    plugins: {
-      ember,
-    },
-    rules: {
-      ...emberRecommended.rules,
-      ...gjsRecommended.rules,
     },
   },
   {
-    files: ['**/*.gjs'],
+    files: ['**/*.{js,gjs}'],
     languageOptions: {
-      parser: emberParser,
       parserOptions: esmParserOptions,
       globals: {
         ...globals.browser,
       },
     },
-    plugins: {
-      ember,
-    },
-    rules: {
-      ...emberRecommended.rules,
-      ...gjsRecommended.rules,
-    },
   },
   {
     files: ['tests/**/*-test.{js,gjs}'],
@@ -102,7 +104,7 @@ export default [
    * ESM node files
    */
   {
-    files: ['*.mjs'],
+    files: ['**/*.mjs'],
     plugins: {
       n,
     },
diff --git a/tests/fixtures/app/nested-project/actual-project/package.json b/tests/fixtures/app/nested-project/actual-project/package.json
index fc9c0c55f..8888a4738 100644
--- a/tests/fixtures/app/nested-project/actual-project/package.json
+++ b/tests/fixtures/app/nested-project/actual-project/package.json
@@ -50,6 +50,7 @@
     "ember-qunit": "^5.1.4",
     "ember-resolver": "^8.0.2",
     "ember-source": "~3.27.0-beta.3",
+    "ember-template-imports": "^4.1.3",
     "ember-template-lint": "^4.0.0",
     "ember-welcome-page": "^5.0.0",
     "eslint": "^8.32.0",
diff --git a/tests/fixtures/app/npm-travis/package.json b/tests/fixtures/app/npm-travis/package.json
index 707efc4c1..60c74579d 100644
--- a/tests/fixtures/app/npm-travis/package.json
+++ b/tests/fixtures/app/npm-travis/package.json
@@ -51,6 +51,7 @@
     "ember-qunit": "^5.1.4",
     "ember-resolver": "^8.0.2",
     "ember-source": "~3.27.2",
+    "ember-template-imports": "^4.1.3",
     "ember-template-lint": "^4.0.0",
     "eslint": "^8.32.0",
     "eslint-config-prettier": "^8.3.0",
diff --git a/tests/fixtures/app/npm/package.json b/tests/fixtures/app/npm/package.json
index cef155adc..7ca380206 100644
--- a/tests/fixtures/app/npm/package.json
+++ b/tests/fixtures/app/npm/package.json
@@ -54,6 +54,7 @@
     "ember-qunit": "^8.1.0",
     "ember-resolver": "^13.0.2",
     "ember-source": "~6.0.0-beta.1",
+    "ember-template-imports": "^4.1.3",
     "ember-template-lint": "^6.0.0",
     "eslint": "^9.12.0",
     "eslint-config-prettier": "^9.1.0",
diff --git a/tests/fixtures/app/pnpm/package.json b/tests/fixtures/app/pnpm/package.json
index dfbba1912..135ca11ba 100644
--- a/tests/fixtures/app/pnpm/package.json
+++ b/tests/fixtures/app/pnpm/package.json
@@ -54,6 +54,7 @@
     "ember-qunit": "^8.1.0",
     "ember-resolver": "^13.0.2",
     "ember-source": "~6.0.0-beta.1",
+    "ember-template-imports": "^4.1.3",
     "ember-template-lint": "^6.0.0",
     "ember-welcome-page": "^7.0.2",
     "eslint": "^9.12.0",
diff --git a/tests/fixtures/app/typescript-embroider/eslint.config.mjs b/tests/fixtures/app/typescript-embroider/eslint.config.mjs
index 8acc12d10..c84c3aebe 100644
--- a/tests/fixtures/app/typescript-embroider/eslint.config.mjs
+++ b/tests/fixtures/app/typescript-embroider/eslint.config.mjs
@@ -1,18 +1,28 @@
+/**
+ * Debugging:
+ *   https://eslint.org/docs/latest/use/configure/debug
+ *  ----------------------------------------------------
+ *
+ *   Print a file's calculated configuration
+ *
+ *     npx eslint --print-config path/to/file.js
+ *
+ *   Inspecting the config
+ *
+ *     npx eslint --inspect-config
+ *
+ */
 import globals from 'globals';
 import js from '@eslint/js';
 
 import ts from 'typescript-eslint';
 
-import ember from 'eslint-plugin-ember';
-import emberRecommended from 'eslint-plugin-ember/configs/recommended';
-import gjsRecommended from 'eslint-plugin-ember/configs/recommended-gjs';
-import gtsRecommended from 'eslint-plugin-ember/configs/recommended-gts';
+import ember from 'eslint-plugin-ember/recommended';
 
 import prettier from 'eslint-plugin-prettier/recommended';
 import qunit from 'eslint-plugin-qunit';
 import n from 'eslint-plugin-n';
 
-import emberParser from 'ember-eslint-parser';
 import babelParser from '@babel/eslint-parser';
 
 const parserOptions = {
@@ -39,62 +49,57 @@ const parserOptions = {
 
 export default ts.config(
   js.configs.recommended,
+  ember.configs.base,
+  ember.configs.gjs,
+  ember.configs.gts,
   prettier,
+  /**
+   * Ignores must be in their own object
+   * https://eslint.org/docs/latest/use/configure/ignore
+   */
   {
-    files: ['**/*.js'],
-    languageOptions: {
-      parser: babelParser,
-      parserOptions: parserOptions.esm.js,
-      globals: {
-        ...globals.browser,
-      },
-    },
-    plugins: {
-      ember,
-    },
-    rules: {
-      ...emberRecommended.rules,
+    ignores: ['dist/', 'node_modules/', 'coverage/', '!**/.*'],
+  },
+  /**
+   * https://eslint.org/docs/latest/use/configure/configuration-files#configuring-linter-options
+   */
+  {
+    linterOptions: {
+      reportUnusedDisableDirectives: 'error',
     },
   },
   {
-    files: ['**/*.ts'],
-    plugins: { ember },
+    files: ['**/*.js'],
     languageOptions: {
-      parserOptions: parserOptions.esm.ts,
+      parser: babelParser,
     },
-    extends: [...ts.configs.strictTypeChecked, ...emberRecommended],
   },
   {
-    files: ['**/*.gjs'],
+    files: ['**/*.{js,gjs}'],
     languageOptions: {
-      parser: emberParser,
       parserOptions: parserOptions.esm.js,
       globals: {
         ...globals.browser,
       },
     },
-    plugins: {
-      ember,
-    },
-    rules: {
-      ...emberRecommended.rules,
-      ...gjsRecommended.rules,
+  },
+  {
+    files: ['**/*.ts'],
+    languageOptions: {
+      parserOptions: parserOptions.esm.ts,
     },
+    extends: [ember.configs.base, ...ts.configs.recommendedTypeChecked],
   },
   {
     files: ['**/*.gts'],
-    plugins: { ember },
     languageOptions: {
+      parser: ember.parser,
       parserOptions: parserOptions.esm.ts,
     },
-    extends: [
-      ...ts.configs.strictTypeChecked,
-      ...emberRecommended,
-      ...gtsRecommended,
-    ],
+    extends: [...ts.configs.recommendedTypeChecked, ember.configs.gts],
   },
   {
-    files: ['tests/**/*-test.{js,gjs}'],
+    files: ['tests/**/*-test.{js,gjs,ts,gts}'],
     plugins: {
       qunit,
     },
@@ -129,7 +134,7 @@ export default ts.config(
    * ESM node files
    */
   {
-    files: ['*.mjs'],
+    files: ['**/*.mjs'],
     plugins: {
       n,
     },
@@ -143,13 +148,4 @@ export default ts.config(
       },
     },
   },
-  /**
-   * Settings
-   */
-  {
-    ignores: ['dist/', 'node_modules/', 'coverage/', '!**/.*'],
-    linterOptions: {
-      reportUnusedDisableDirectives: 'error',
-    },
-  }
 );
diff --git a/tests/fixtures/app/typescript-embroider/package.json b/tests/fixtures/app/typescript-embroider/package.json
index e490e09af..6b7d7c97f 100644
--- a/tests/fixtures/app/typescript-embroider/package.json
+++ b/tests/fixtures/app/typescript-embroider/package.json
@@ -47,6 +47,7 @@
     "@glimmer/component": "^1.1.2",
     "@glimmer/tracking": "^1.1.2",
     "@glint/environment-ember-loose": "^1.4.0",
+    "@glint/environment-ember-template-imports": "^1.4.0",
     "@glint/template": "^1.4.0",
     "@tsconfig/ember": "^3.0.8",
     "@types/eslint__js": "^8.42.3",
@@ -73,6 +74,7 @@
     "ember-qunit": "^8.1.0",
     "ember-resolver": "^13.0.2",
     "ember-source": "~6.0.0-beta.1",
+    "ember-template-imports": "^4.1.3",
     "ember-template-lint": "^6.0.0",
     "ember-welcome-page": "^7.0.2",
     "eslint": "^9.12.0",
diff --git a/tests/fixtures/app/typescript-embroider/tsconfig.json b/tests/fixtures/app/typescript-embroider/tsconfig.json
index e61dd08cc..4a5785db1 100644
--- a/tests/fixtures/app/typescript-embroider/tsconfig.json
+++ b/tests/fixtures/app/typescript-embroider/tsconfig.json
@@ -1,5 +1,8 @@
 {
   "extends": "@tsconfig/ember/tsconfig.json",
+  "glint": {
+    "environment": ["ember-loose", "ember-template-imports"]
+  },
   "compilerOptions": {
     // The combination of `baseUrl` with `paths` allows Ember's classic package
     // layout, which is not resolvable with the Node resolution algorithm, to
diff --git a/tests/fixtures/app/typescript/eslint.config.mjs b/tests/fixtures/app/typescript/eslint.config.mjs
index 8acc12d10..c84c3aebe 100644
--- a/tests/fixtures/app/typescript/eslint.config.mjs
+++ b/tests/fixtures/app/typescript/eslint.config.mjs
@@ -1,18 +1,28 @@
+/**
+ * Debugging:
+ *   https://eslint.org/docs/latest/use/configure/debug
+ *  ----------------------------------------------------
+ *
+ *   Print a file's calculated configuration
+ *
+ *     npx eslint --print-config path/to/file.js
+ *
+ *   Inspecting the config
+ *
+ *     npx eslint --inspect-config
+ *
+ */
 import globals from 'globals';
 import js from '@eslint/js';
 
 import ts from 'typescript-eslint';
 
-import ember from 'eslint-plugin-ember';
-import emberRecommended from 'eslint-plugin-ember/configs/recommended';
-import gjsRecommended from 'eslint-plugin-ember/configs/recommended-gjs';
-import gtsRecommended from 'eslint-plugin-ember/configs/recommended-gts';
+import ember from 'eslint-plugin-ember/recommended';
 
 import prettier from 'eslint-plugin-prettier/recommended';
 import qunit from 'eslint-plugin-qunit';
 import n from 'eslint-plugin-n';
 
-import emberParser from 'ember-eslint-parser';
 import babelParser from '@babel/eslint-parser';
 
 const parserOptions = {
@@ -39,62 +49,57 @@ const parserOptions = {
 
 export default ts.config(
   js.configs.recommended,
+  ember.configs.base,
+  ember.configs.gjs,
+  ember.configs.gts,
   prettier,
+  /**
+   * Ignores must be in their own object
+   * https://eslint.org/docs/latest/use/configure/ignore
+   */
   {
-    files: ['**/*.js'],
-    languageOptions: {
-      parser: babelParser,
-      parserOptions: parserOptions.esm.js,
-      globals: {
-        ...globals.browser,
-      },
-    },
-    plugins: {
-      ember,
-    },
-    rules: {
-      ...emberRecommended.rules,
+    ignores: ['dist/', 'node_modules/', 'coverage/', '!**/.*'],
+  },
+  /**
+   * https://eslint.org/docs/latest/use/configure/configuration-files#configuring-linter-options
+   */
+  {
+    linterOptions: {
+      reportUnusedDisableDirectives: 'error',
     },
   },
   {
-    files: ['**/*.ts'],
-    plugins: { ember },
+    files: ['**/*.js'],
     languageOptions: {
-      parserOptions: parserOptions.esm.ts,
+      parser: babelParser,
     },
-    extends: [...ts.configs.strictTypeChecked, ...emberRecommended],
   },
   {
-    files: ['**/*.gjs'],
+    files: ['**/*.{js,gjs}'],
     languageOptions: {
-      parser: emberParser,
       parserOptions: parserOptions.esm.js,
       globals: {
         ...globals.browser,
       },
     },
-    plugins: {
-      ember,
-    },
-    rules: {
-      ...emberRecommended.rules,
-      ...gjsRecommended.rules,
+  },
+  {
+    files: ['**/*.ts'],
+    languageOptions: {
+      parserOptions: parserOptions.esm.ts,
     },
+    extends: [ember.configs.base, ...ts.configs.recommendedTypeChecked],
   },
   {
     files: ['**/*.gts'],
-    plugins: { ember },
     languageOptions: {
+      parser: ember.parser,
       parserOptions: parserOptions.esm.ts,
     },
-    extends: [
-      ...ts.configs.strictTypeChecked,
-      ...emberRecommended,
-      ...gtsRecommended,
-    ],
+    extends: [...ts.configs.recommendedTypeChecked, ember.configs.gts],
   },
   {
-    files: ['tests/**/*-test.{js,gjs}'],
+    files: ['tests/**/*-test.{js,gjs,ts,gts}'],
     plugins: {
       qunit,
     },
@@ -129,7 +134,7 @@ export default ts.config(
    * ESM node files
    */
   {
-    files: ['*.mjs'],
+    files: ['**/*.mjs'],
     plugins: {
       n,
     },
@@ -143,13 +148,4 @@ export default ts.config(
       },
     },
   },
-  /**
-   * Settings
-   */
-  {
-    ignores: ['dist/', 'node_modules/', 'coverage/', '!**/.*'],
-    linterOptions: {
-      reportUnusedDisableDirectives: 'error',
-    },
-  }
 );
diff --git a/tests/fixtures/app/typescript/package.json b/tests/fixtures/app/typescript/package.json
index edefa5a55..46ae133db 100644
--- a/tests/fixtures/app/typescript/package.json
+++ b/tests/fixtures/app/typescript/package.json
@@ -44,6 +44,7 @@
     "@glimmer/component": "^1.1.2",
     "@glimmer/tracking": "^1.1.2",
     "@glint/environment-ember-loose": "^1.4.0",
+    "@glint/environment-ember-template-imports": "^1.4.0",
     "@glint/template": "^1.4.0",
     "@tsconfig/ember": "^3.0.8",
     "@types/eslint__js": "^8.42.3",
@@ -72,6 +73,7 @@
     "ember-qunit": "^8.1.0",
     "ember-resolver": "^13.0.2",
     "ember-source": "~6.0.0-beta.1",
+    "ember-template-imports": "^4.1.3",
     "ember-template-lint": "^6.0.0",
     "ember-welcome-page": "^7.0.2",
     "eslint": "^9.12.0",
diff --git a/tests/fixtures/app/typescript/tsconfig.json b/tests/fixtures/app/typescript/tsconfig.json
index e61dd08cc..4a5785db1 100644
--- a/tests/fixtures/app/typescript/tsconfig.json
+++ b/tests/fixtures/app/typescript/tsconfig.json
@@ -1,5 +1,8 @@
 {
   "extends": "@tsconfig/ember/tsconfig.json",
+  "glint": {
+    "environment": ["ember-loose", "ember-template-imports"]
+  },
   "compilerOptions": {
     // The combination of `baseUrl` with `paths` allows Ember's classic package
     // layout, which is not resolvable with the Node resolution algorithm, to
diff --git a/tests/fixtures/app/with-blueprint-override-lint-fail/eslint.config.mjs b/tests/fixtures/app/with-blueprint-override-lint-fail/eslint.config.mjs
index e05042fd2..b895cc463 100644
--- a/tests/fixtures/app/with-blueprint-override-lint-fail/eslint.config.mjs
+++ b/tests/fixtures/app/with-blueprint-override-lint-fail/eslint.config.mjs
@@ -1,15 +1,25 @@
+/**
+ * Debugging:
+ *   https://eslint.org/docs/latest/use/configure/debug
+ *  ----------------------------------------------------
+ *
+ *   Print a file's calculated configuration
+ *
+ *     npx eslint --print-config path/to/file.js
+ *
+ *   Inspecting the config
+ *
+ *     npx eslint --inspect-config
+ *
+ */
 import globals from 'globals';
 import js from '@eslint/js';
 
-import ember from 'eslint-plugin-ember';
-import emberRecommended from 'eslint-plugin-ember/configs/recommended';
-import gjsRecommended from 'eslint-plugin-ember/configs/recommended-gjs';
-
+import ember from 'eslint-plugin-ember/recommended';
 import prettier from 'eslint-plugin-prettier/recommended';
 import qunit from 'eslint-plugin-qunit';
 import n from 'eslint-plugin-n';
 
-import emberParser from 'ember-eslint-parser';
 import babelParser from '@babel/eslint-parser';
 
 const esmParserOptions = {
@@ -26,8 +36,19 @@ const esmParserOptions = {
 export default [
   js.configs.recommended,
   prettier,
+  ember.configs.base,
+  ember.configs.gjs,
+  /**
+   * Ignores must be in their own object
+   * https://eslint.org/docs/latest/use/configure/ignore
+   */
   {
     ignores: ['dist/', 'node_modules/', 'coverage/', '!**/.*'],
+  },
+  /**
+   * https://eslint.org/docs/latest/use/configure/configuration-files#configuring-linter-options
+   */
+  {
     linterOptions: {
       reportUnusedDisableDirectives: 'error',
     },
@@ -36,35 +57,16 @@ export default [
     files: ['**/*.js'],
     languageOptions: {
       parser: babelParser,
-      parserOptions: esmParserOptions,
-      globals: {
-        ...globals.browser,
-      },
-    },
-    plugins: {
-      ember,
-    },
-    rules: {
-      ...emberRecommended.rules,
-      ...gjsRecommended.rules,
     },
   },
   {
-    files: ['**/*.gjs'],
+    files: ['**/*.{js,gjs}'],
     languageOptions: {
-      parser: emberParser,
       parserOptions: esmParserOptions,
       globals: {
         ...globals.browser,
       },
     },
-    plugins: {
-      ember,
-    },
-    rules: {
-      ...emberRecommended.rules,
-      ...gjsRecommended.rules,
-    },
   },
   {
     files: ['tests/**/*-test.{js,gjs}'],
@@ -102,7 +104,7 @@ export default [
    * ESM node files
    */
   {
-    files: ['*.mjs'],
+    files: ['**/*.mjs'],
     plugins: {
       n,
     },
diff --git a/tests/fixtures/app/with-blueprint-override-lint-fail/package.json b/tests/fixtures/app/with-blueprint-override-lint-fail/package.json
index a41be1db3..02e618cf7 100644
--- a/tests/fixtures/app/with-blueprint-override-lint-fail/package.json
+++ b/tests/fixtures/app/with-blueprint-override-lint-fail/package.json
@@ -50,6 +50,7 @@
     "ember-qunit": "^5.1.2",
     "ember-resolver": "^8.0.2",
     "ember-source": "~3.26.0-beta.2",
+    "ember-template-imports": "^4.1.3",
     "ember-template-lint": "^4.0.0",
     "ember-welcome-page": "^5.0.0",
     "eslint": "^8.32.0",
diff --git a/tests/fixtures/app/yarn-travis/package.json b/tests/fixtures/app/yarn-travis/package.json
index a93470a2d..4db25ca7a 100644
--- a/tests/fixtures/app/yarn-travis/package.json
+++ b/tests/fixtures/app/yarn-travis/package.json
@@ -51,6 +51,7 @@
     "ember-qunit": "^5.1.4",
     "ember-resolver": "^8.0.2",
     "ember-source": "~3.27.2",
+    "ember-template-imports": "^4.1.3",
     "ember-template-lint": "^4.0.0",
     "ember-welcome-page": "^4.0.0",
     "eslint": "^8.32.0",
diff --git a/tests/fixtures/app/yarn/package.json b/tests/fixtures/app/yarn/package.json
index f2e26cbcb..89a745f84 100644
--- a/tests/fixtures/app/yarn/package.json
+++ b/tests/fixtures/app/yarn/package.json
@@ -54,6 +54,7 @@
     "ember-qunit": "^8.1.0",
     "ember-resolver": "^13.0.2",
     "ember-source": "~6.0.0-beta.1",
+    "ember-template-imports": "^4.1.3",
     "ember-template-lint": "^6.0.0",
     "ember-welcome-page": "^7.0.2",
     "eslint": "^9.12.0",
diff --git a/tests/unit/debug/deprecate-test.js b/tests/unit/debug/deprecate-test.js
index 56f14188e..7de75c3b0 100644
--- a/tests/unit/debug/deprecate-test.js
+++ b/tests/unit/debug/deprecate-test.js
@@ -182,4 +182,56 @@ ID     foo
 UNTIL  5.0.0
 URL    https://example.com`);
   });
+
+  it('throws an deprecation if the current ember-cli version is greater than the until version of deprecation', function () {
+    expect(() => {
+      deprecate('The `foo` method is deprecated', false, {
+        for: 'ember-cli',
+        id: 'ember-cli.foo-method',
+        since: {
+          available: '4.1.0',
+          enabled: '4.2.0',
+        },
+        until: '3.0.0', // This should be less than the current emberCLIVersion to trigger the error
+        url: 'https://example.com',
+      });
+    }).to.throw(
+      'The API deprecated by ember-cli.foo-method was removed in ember-cli 3.0.0. The message was: The `foo` method is deprecated. Please see https://example.com for more details.'
+    );
+  });
+
+  it('throws an deprecation if the pre-release ember-cli version is greater than the until version of deprecation', function () {
+    const OVERRIDE_VERSION = process.env.OVERRIDE_DEPRECATION_VERSION;
+    process.env.OVERRIDE_DEPRECATION_VERSION = '9.0.0-beta.1';
+    expect(() => {
+      deprecate('The `bar` method is deprecated', false, {
+        for: 'ember-cli',
+        id: 'ember-cli.bar-method',
+        since: {
+          available: '4.1.0',
+          enabled: '4.2.0',
+        },
+        until: '9.0.0', // This should be less than the current emberCLIVersion to trigger the error
+        url: 'https://example.com',
+      });
+    }).to.throw(
+      'The API deprecated by ember-cli.bar-method was removed in ember-cli 9.0.0. The message was: The `bar` method is deprecated. Please see https://example.com for more details.'
+    );
+    process.env.OVERRIDE_DEPRECATION_VERSION = OVERRIDE_VERSION;
+  });
+
+  it('does not throw a deprecation if "for" is not "ember-cli"', function () {
+    expect(() => {
+      deprecate('The `foo` method is deprecated.', false, {
+        for: 'ember-source',
+        id: 'not-ember-cli.foo-method',
+        since: {
+          available: '4.1.0',
+          enabled: '4.2.0',
+        },
+        until: '3.0.0',
+        url: 'https://example.com',
+      });
+    }).to.not.throw();
+  });
 });