From a616d5db1571fa90f7734fd3b16e7af03103757d Mon Sep 17 00:00:00 2001 From: Ian Clanton-Thuon Date: Sun, 13 Sep 2026 17:28:09 -0400 Subject: [PATCH 01/16] [eslint-config] Separate type-aware rules and add without-type-information helper Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- ...-type-aware-rules_2026-09-13-04-00-00.json | 9 +++ eslint/eslint-config/flat/profile/_common.js | 67 +++++++++++-------- .../flat/without-type-information.js | 48 +++++++++++++ 3 files changed, 96 insertions(+), 28 deletions(-) create mode 100644 common/changes/@rushstack/eslint-config/eslint-config-type-aware-rules_2026-09-13-04-00-00.json create mode 100644 eslint/eslint-config/flat/without-type-information.js diff --git a/common/changes/@rushstack/eslint-config/eslint-config-type-aware-rules_2026-09-13-04-00-00.json b/common/changes/@rushstack/eslint-config/eslint-config-type-aware-rules_2026-09-13-04-00-00.json new file mode 100644 index 00000000000..3a31b8f141f --- /dev/null +++ b/common/changes/@rushstack/eslint-config/eslint-config-type-aware-rules_2026-09-13-04-00-00.json @@ -0,0 +1,9 @@ +{ + "changes": [ + { + "packageName": "@rushstack/eslint-config", + "comment": "Group the profile's type-aware rules into an exported `typeAwareRules` set and add a `flat/without-type-information` helper for linting files that are not part of the TypeScript program with only the non-type-aware rules.", + "type": "minor" + } + ] +} diff --git a/eslint/eslint-config/flat/profile/_common.js b/eslint/eslint-config/flat/profile/_common.js index 4513f97c146..8c5dc8341c5 100644 --- a/eslint/eslint-config/flat/profile/_common.js +++ b/eslint/eslint-config/flat/profile/_common.js @@ -183,6 +183,41 @@ const commonNamingConventionSelectors = [ } ]; +// These are the only rules in this profile that require type information (i.e. the TypeScript program). +// They are grouped separately so that TypeScript files which are NOT part of the project's TypeScript program +// (for example config files or tests that are not included by tsconfig.json) can be linted with only the +// non-type-aware rules. See the "without-type-information" helper (flat/without-type-information.js), which +// disables these rules and type-aware parsing for a given set of files. +const typeAwareRules = { + // NOTE: This new rule replaces several deprecated rules from @typescript-eslint/eslint-plugin@2.3.3: + // + // - @typescript-eslint/camelcase + // - @typescript-eslint/class-name-casing + // - @typescript-eslint/interface-name-prefix + // - @typescript-eslint/member-naming + // + // Docs: https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/naming-convention.md + '@typescript-eslint/naming-convention': [ + 'warn', + ...expandNamingConventionSelectors(commonNamingConventionSelectors) + ], + + // RATIONALE: The #1 rule of promises is that every promise chain must be terminated by a catch() + // handler. Thus wherever a Promise arises, the code must either append a catch handler, + // or else return the object to a caller (who assumes this responsibility). Unterminated + // promise chains are a serious issue. Besides causing errors to be silently ignored, + // they can also cause a NodeJS process to terminate unexpectedly. + '@typescript-eslint/no-floating-promises': [ + 'error', + { + checkThenables: true + } + ], + + // RATIONALE: Catches a common coding mistake. + '@typescript-eslint/no-for-in-array': 'error' +}; + const commonConfig = [ // Manually authored .d.ts files are generally used to describe external APIs that are not expected // to follow our coding conventions. Linting those files tends to produce a lot of spurious suppressions, @@ -291,18 +326,9 @@ const commonConfig = [ } ], - // NOTE: This new rule replaces several deprecated rules from @typescript-eslint/eslint-plugin@2.3.3: - // - // - @typescript-eslint/camelcase - // - @typescript-eslint/class-name-casing - // - @typescript-eslint/interface-name-prefix - // - @typescript-eslint/member-naming - // - // Docs: https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/naming-convention.md - '@typescript-eslint/naming-convention': [ - 'warn', - ...expandNamingConventionSelectors(commonNamingConventionSelectors) - ], + // Type-aware rules (require the TypeScript program) are grouped in typeAwareRules so that files outside + // the TypeScript program can be linted with only the non-type-aware rules. + ...typeAwareRules, // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json '@typescript-eslint/no-array-constructor': 'warn', @@ -315,21 +341,6 @@ const commonConfig = [ // may be more appropriate such as "unknown", "{}", or "Record". '@typescript-eslint/no-explicit-any': 'warn', - // RATIONALE: The #1 rule of promises is that every promise chain must be terminated by a catch() - // handler. Thus wherever a Promise arises, the code must either append a catch handler, - // or else return the object to a caller (who assumes this responsibility). Unterminated - // promise chains are a serious issue. Besides causing errors to be silently ignored, - // they can also cause a NodeJS process to terminate unexpectedly. - '@typescript-eslint/no-floating-promises': [ - 'error', - { - checkThenables: true - } - ], - - // RATIONALE: Catches a common coding mistake. - '@typescript-eslint/no-for-in-array': 'error', - // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json '@typescript-eslint/no-misused-new': 'error', @@ -774,4 +785,4 @@ const commonConfig = [ } ]; -module.exports = { commonNamingConventionSelectors, commonConfig }; +module.exports = { commonNamingConventionSelectors, commonConfig, typeAwareRules }; diff --git a/eslint/eslint-config/flat/without-type-information.js b/eslint/eslint-config/flat/without-type-information.js new file mode 100644 index 00000000000..2fde93f4c73 --- /dev/null +++ b/eslint/eslint-config/flat/without-type-information.js @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +// The profile's type-aware rules, turned off. Keep this in sync with the typeAwareRules group in +// ./profile/_common.js. +const disabledTypeAwareRules = { + '@typescript-eslint/naming-convention': 'off', + '@typescript-eslint/no-floating-promises': 'off', + '@typescript-eslint/no-for-in-array': 'off' +}; + +// Returns ESLint flat-config objects that lint the specified files WITHOUT type information: type-aware parsing +// is disabled and the profile's type-aware rules are turned off, leaving only the non-type-aware rules in effect. +// +// Use this for TypeScript files that are selected by your ESLint configuration but are NOT part of the project's +// TypeScript program -- for example configuration files or tests that are not included by tsconfig.json. Without +// this, typescript-eslint reports a fatal parsing error because it cannot associate those files with the project, +// and any type-aware rule would be unable to run. +// +// IMPORTANT: These config objects must be included in your ESLint configuration AFTER the profile, so that they +// override the profile's type-aware parser options and rules for the specified files. +// +// Example (eslint.config.js): +// +// const { withoutTypeInformation } = require('@rushstack/eslint-config/flat/without-type-information'); +// +// module.exports = [ +// ...nodeTrustedToolProfile, +// ...withoutTypeInformation({ files: ['tests/**/*.ts', 'playwright.config.ts'] }) +// ]; +function withoutTypeInformation({ files }) { + return [ + { + files, + languageOptions: { + parserOptions: { + // Disable type-aware parsing so that files outside the TypeScript program do not fail to resolve + // against it. + project: false, + projectService: false + } + }, + rules: disabledTypeAwareRules + } + ]; +} + +module.exports = { withoutTypeInformation }; From fe6a846fbb87b113b6bb4b6036629f57e582fd35 Mon Sep 17 00:00:00 2001 From: Ian Clanton-Thuon Date: Sun, 13 Sep 2026 18:09:21 -0400 Subject: [PATCH 02/16] [eslint-config] Convert the package to TypeScript Author the ESLint configuration modules in TypeScript under src/ and build them with Heft (decoupled-local-node-rig) to lib-commonjs. Preserve the existing subpath entry points (e.g. @rushstack/eslint-config/flat/profile/node-trusted-tool) via a package.json "exports" map, and keep CommonJS output using `export =` so that existing require()-based consumers are unaffected. The compiled configuration output is verified to be runtime-identical to the previous JavaScript sources. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- eslint/eslint-config/.npmignore | 24 ---------- eslint/eslint-config/config/rig.json | 7 +++ eslint/eslint-config/config/typescript.json | 9 ++++ eslint/eslint-config/eslint.config.js | 20 ++++++++ eslint/eslint-config/package.json | 26 +++++++++- .../flat/mixins/friendly-locals.ts} | 15 ++++-- .../flat/mixins/packlets.ts} | 14 ++++-- .../react.js => src/flat/mixins/react.ts} | 7 ++- .../tsdoc.js => src/flat/mixins/tsdoc.ts} | 7 ++- .../flat/patch/eslint-bulk-suppressions.ts} | 2 +- .../flat/profile/_common.ts} | 48 ++++++++++++------- .../flat/profile/_macros.ts} | 34 +++++++++---- .../flat/profile/node-trusted-tool.ts} | 8 +++- .../node.js => src/flat/profile/node.ts} | 9 ++-- .../flat/profile/web-app.ts} | 8 +++- .../flat/without-type-information.ts} | 12 +++-- .../eslint-config/{index.js => src/index.ts} | 2 + .../mixins/friendly-locals.ts} | 6 ++- .../packlets.js => src/mixins/packlets.ts} | 6 ++- .../{mixins/react.js => src/mixins/react.ts} | 6 ++- .../{mixins/tsdoc.js => src/mixins/tsdoc.ts} | 6 ++- .../src/module-declarations.d.ts | 5 ++ .../patch-eslint6.ts} | 2 + .../patch/custom-config-package-names.ts} | 2 +- .../patch/eslint-bulk-suppressions.ts} | 2 +- .../patch/modern-module-resolution.ts} | 2 +- .../_common.js => src/profile/_common.ts} | 20 +++++--- .../_macros.js => src/profile/_macros.ts} | 32 +++++++++---- .../profile/node-trusted-tool.ts} | 8 ++-- .../profile/node.js => src/profile/node.ts} | 7 ++- .../web-app.js => src/profile/web-app.ts} | 8 ++-- .../eslint-config/{react.js => src/react.ts} | 2 + eslint/eslint-config/tsconfig.json | 7 +++ 33 files changed, 269 insertions(+), 104 deletions(-) create mode 100644 eslint/eslint-config/config/rig.json create mode 100644 eslint/eslint-config/config/typescript.json create mode 100644 eslint/eslint-config/eslint.config.js rename eslint/eslint-config/{flat/mixins/friendly-locals.js => src/flat/mixins/friendly-locals.ts} (88%) rename eslint/eslint-config/{flat/mixins/packlets.js => src/flat/mixins/packlets.ts} (64%) rename eslint/eslint-config/{flat/mixins/react.js => src/flat/mixins/react.ts} (94%) rename eslint/eslint-config/{flat/mixins/tsdoc.js => src/flat/mixins/tsdoc.ts} (78%) rename eslint/eslint-config/{flat/patch/eslint-bulk-suppressions.js => src/flat/patch/eslint-bulk-suppressions.ts} (71%) rename eslint/eslint-config/{flat/profile/_common.js => src/flat/profile/_common.ts} (96%) rename eslint/eslint-config/{flat/profile/_macros.js => src/flat/profile/_macros.ts} (71%) rename eslint/eslint-config/{flat/profile/node-trusted-tool.js => src/flat/profile/node-trusted-tool.ts} (88%) rename eslint/eslint-config/{profile/node.js => src/flat/profile/node.ts} (74%) rename eslint/eslint-config/{flat/profile/web-app.js => src/flat/profile/web-app.ts} (73%) rename eslint/eslint-config/{flat/without-type-information.js => src/flat/without-type-information.ts} (86%) rename eslint/eslint-config/{index.js => src/index.ts} (97%) rename eslint/eslint-config/{mixins/friendly-locals.js => src/mixins/friendly-locals.ts} (97%) rename eslint/eslint-config/{mixins/packlets.js => src/mixins/packlets.ts} (87%) rename eslint/eslint-config/{mixins/react.js => src/mixins/react.ts} (96%) rename eslint/eslint-config/{mixins/tsdoc.js => src/mixins/tsdoc.ts} (86%) create mode 100644 eslint/eslint-config/src/module-declarations.d.ts rename eslint/eslint-config/{patch-eslint6.js => src/patch-eslint6.ts} (97%) rename eslint/eslint-config/{patch/custom-config-package-names.js => src/patch/custom-config-package-names.ts} (70%) rename eslint/eslint-config/{patch/modern-module-resolution.js => src/patch/eslint-bulk-suppressions.ts} (71%) rename eslint/eslint-config/{patch/eslint-bulk-suppressions.js => src/patch/modern-module-resolution.ts} (71%) rename eslint/eslint-config/{profile/_common.js => src/profile/_common.ts} (98%) rename eslint/eslint-config/{profile/_macros.js => src/profile/_macros.ts} (71%) rename eslint/eslint-config/{profile/node-trusted-tool.js => src/profile/node-trusted-tool.ts} (83%) rename eslint/eslint-config/{flat/profile/node.js => src/profile/node.ts} (74%) rename eslint/eslint-config/{profile/web-app.js => src/profile/web-app.ts} (73%) rename eslint/eslint-config/{react.js => src/react.ts} (97%) create mode 100644 eslint/eslint-config/tsconfig.json diff --git a/eslint/eslint-config/.npmignore b/eslint/eslint-config/.npmignore index 31e20769649..ec65d0fb23c 100644 --- a/eslint/eslint-config/.npmignore +++ b/eslint/eslint-config/.npmignore @@ -35,28 +35,4 @@ # DO NOT MODIFY ABOVE THIS LINE! Add any project-specific overrides below. # --------------------------------------------------------------------------- -!/*.js -!/*.[cm]js -!/*.d.ts -!/*.d.[cm]ts - -!flat/**/*.js -!flat/**/*.[cm]js -!flat/**/*.d.ts -!flat/**/*.d.[cm]ts - -!mixins/*.js -!mixins/*.[cm]js -!mixins/*.d.ts -!mixins/*.d.[cm]ts - -!patch/*.js -!patch/*.[cm]js -!patch/*.d.ts -!patch/*.d.[cm]ts - -!profile/*.js -!profile/*.[cm]js -!profile/*.d.ts -!profile/*.d.[cm]ts diff --git a/eslint/eslint-config/config/rig.json b/eslint/eslint-config/config/rig.json new file mode 100644 index 00000000000..cc98dea43dd --- /dev/null +++ b/eslint/eslint-config/config/rig.json @@ -0,0 +1,7 @@ +{ + // The "rig.json" file directs tools to look for their config files in an external package. + // Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package + "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", + + "rigPackageName": "decoupled-local-node-rig" +} diff --git a/eslint/eslint-config/config/typescript.json b/eslint/eslint-config/config/typescript.json new file mode 100644 index 00000000000..9bcead41dfc --- /dev/null +++ b/eslint/eslint-config/config/typescript.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/heft/v0/typescript.schema.json", + + "extends": "decoupled-local-node-rig/profiles/default/config/typescript.json", + + // These ESLint configuration modules are consumed via CommonJS require(), so only emit CommonJS (which also + // works for ESM consumers via Node.js interop). Overrides the rig's additional ESM module kind. + "additionalModuleKindsToEmit": [] +} diff --git a/eslint/eslint-config/eslint.config.js b/eslint/eslint-config/eslint.config.js new file mode 100644 index 00000000000..f83aea7d1b7 --- /dev/null +++ b/eslint/eslint-config/eslint.config.js @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +const nodeTrustedToolProfile = require('decoupled-local-node-rig/profiles/default/includes/eslint/flat/profile/node-trusted-tool'); +const friendlyLocalsMixin = require('decoupled-local-node-rig/profiles/default/includes/eslint/flat/mixins/friendly-locals'); +const tsdocMixin = require('decoupled-local-node-rig/profiles/default/includes/eslint/flat/mixins/tsdoc'); + +module.exports = [ + ...nodeTrustedToolProfile, + ...friendlyLocalsMixin, + ...tsdocMixin, + { + files: ['**/*.ts', '**/*.tsx'], + languageOptions: { + parserOptions: { + tsconfigRootDir: __dirname + } + } + } +]; diff --git a/eslint/eslint-config/package.json b/eslint/eslint-config/package.json index 4623afe2aca..4c70cd7e047 100644 --- a/eslint/eslint-config/package.json +++ b/eslint/eslint-config/package.json @@ -12,9 +12,29 @@ "node": ">=20.9.0" }, "homepage": "https://rushstack.io", + "main": "./lib-commonjs/index.js", + "types": "./lib-dts/index.d.ts", + "exports": { + ".": { + "types": "./lib-dts/index.d.ts", + "default": "./lib-commonjs/index.js" + }, + "./*": { + "types": "./lib-dts/*.d.ts", + "default": "./lib-commonjs/*.js" + }, + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "*": [ + "lib-dts/*" + ] + } + }, "scripts": { - "build": "", - "_phase:build": "", + "build": "heft build --clean", + "_phase:build": "heft run --only build -- --clean", "_phase:pack": "rush-pnpm pack" }, "keywords": [ @@ -44,6 +64,8 @@ "eslint-plugin-tsdoc": "~0.5.1" }, "devDependencies": { + "@rushstack/heft": "1.2.25", + "decoupled-local-node-rig": "workspace:*", "eslint": "~9.37.0", "typescript": "~5.8.2" }, diff --git a/eslint/eslint-config/flat/mixins/friendly-locals.js b/eslint/eslint-config/src/flat/mixins/friendly-locals.ts similarity index 88% rename from eslint/eslint-config/flat/mixins/friendly-locals.js rename to eslint/eslint-config/src/flat/mixins/friendly-locals.ts index e63e96783ca..84be3ff5f26 100644 --- a/eslint/eslint-config/flat/mixins/friendly-locals.js +++ b/eslint/eslint-config/src/flat/mixins/friendly-locals.ts @@ -22,13 +22,18 @@ // // IMPORTANT: Mixins must be included in your ESLint configuration AFTER the profile -const typescriptEslintPlugin = require('@typescript-eslint/eslint-plugin'); +import type { ESLint, Linter } from 'eslint'; +import typescriptEslintPlugin = require('@typescript-eslint/eslint-plugin'); -module.exports = [ +function toEslintPlugin(plugin: object): ESLint.Plugin { + return plugin; +} + +const config: Linter.Config[] = [ { files: ['**/*.ts', '**/*.tsx'], plugins: { - '@typescript-eslint': typescriptEslintPlugin + '@typescript-eslint': toEslintPlugin(typescriptEslintPlugin) }, rules: { '@rushstack/typedef-var': 'off', // <--- disabled by the mixin @@ -69,7 +74,7 @@ module.exports = [ '**/test/**/*.tsx' ], plugins: { - '@typescript-eslint': typescriptEslintPlugin + '@typescript-eslint': toEslintPlugin(typescriptEslintPlugin) }, rules: { '@typescript-eslint/typedef': [ @@ -88,3 +93,5 @@ module.exports = [ } } ]; + +export = config; diff --git a/eslint/eslint-config/flat/mixins/packlets.js b/eslint/eslint-config/src/flat/mixins/packlets.ts similarity index 64% rename from eslint/eslint-config/flat/mixins/packlets.js rename to eslint/eslint-config/src/flat/mixins/packlets.ts index 0c1f22487dd..bc53988db83 100644 --- a/eslint/eslint-config/flat/mixins/packlets.js +++ b/eslint/eslint-config/src/flat/mixins/packlets.ts @@ -7,15 +7,23 @@ // // IMPORTANT: Mixins must be included in your ESLint configuration AFTER the profile -const rushstackPackletsEslintPlugin = require('@rushstack/eslint-plugin-packlets'); +import type { ESLint, Linter } from 'eslint'; -module.exports = { +import rushstackPackletsEslintPlugin = require('@rushstack/eslint-plugin-packlets'); + +function toEslintPlugin(plugin: object): ESLint.Plugin { + return plugin; +} + +const config: Linter.Config = { files: ['**/*.ts', '**/*.tsx'], plugins: { - '@rushstack/packlets': rushstackPackletsEslintPlugin + '@rushstack/packlets': toEslintPlugin(rushstackPackletsEslintPlugin) }, rules: { '@rushstack/packlets/mechanics': 'warn', '@rushstack/packlets/circular-deps': 'warn' } }; + +export = config; diff --git a/eslint/eslint-config/flat/mixins/react.js b/eslint/eslint-config/src/flat/mixins/react.ts similarity index 94% rename from eslint/eslint-config/flat/mixins/react.js rename to eslint/eslint-config/src/flat/mixins/react.ts index 8ee798c1e0b..72764ff6c9b 100644 --- a/eslint/eslint-config/flat/mixins/react.js +++ b/eslint/eslint-config/src/flat/mixins/react.ts @@ -6,9 +6,10 @@ // // IMPORTANT: Mixins must be included in your ESLint configuration AFTER the profile -const reactEslintPlugin = require('eslint-plugin-react'); +import type { Linter } from 'eslint'; +import reactEslintPlugin = require('eslint-plugin-react'); -module.exports = [ +const config: Linter.Config[] = [ { files: ['**/*.ts', '**/*.tsx'], plugins: { @@ -75,3 +76,5 @@ module.exports = [ } } ]; + +export = config; diff --git a/eslint/eslint-config/flat/mixins/tsdoc.js b/eslint/eslint-config/src/flat/mixins/tsdoc.ts similarity index 78% rename from eslint/eslint-config/flat/mixins/tsdoc.js rename to eslint/eslint-config/src/flat/mixins/tsdoc.ts index 2b1009259bf..9307f0f7c3a 100644 --- a/eslint/eslint-config/flat/mixins/tsdoc.js +++ b/eslint/eslint-config/src/flat/mixins/tsdoc.ts @@ -6,9 +6,10 @@ // // IMPORTANT: Mixins must be included in your ESLint configuration AFTER the profile -const tsdocEslintPlugin = require('eslint-plugin-tsdoc'); +import type { Linter } from 'eslint'; +import tsdocEslintPlugin = require('eslint-plugin-tsdoc'); -module.exports = [ +const config: Linter.Config[] = [ { files: ['**/*.ts', '**/*.tsx'], plugins: { @@ -19,3 +20,5 @@ module.exports = [ } } ]; + +export = config; diff --git a/eslint/eslint-config/flat/patch/eslint-bulk-suppressions.js b/eslint/eslint-config/src/flat/patch/eslint-bulk-suppressions.ts similarity index 71% rename from eslint/eslint-config/flat/patch/eslint-bulk-suppressions.js rename to eslint/eslint-config/src/flat/patch/eslint-bulk-suppressions.ts index 12c37b253da..448a68224e6 100644 --- a/eslint/eslint-config/flat/patch/eslint-bulk-suppressions.js +++ b/eslint/eslint-config/src/flat/patch/eslint-bulk-suppressions.ts @@ -1,4 +1,4 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. -require('@rushstack/eslint-patch/eslint-bulk-suppressions'); +import '@rushstack/eslint-patch/eslint-bulk-suppressions'; diff --git a/eslint/eslint-config/flat/profile/_common.js b/eslint/eslint-config/src/flat/profile/_common.ts similarity index 96% rename from eslint/eslint-config/flat/profile/_common.js rename to eslint/eslint-config/src/flat/profile/_common.ts index 8c5dc8341c5..d8cd9889128 100644 --- a/eslint/eslint-config/flat/profile/_common.js +++ b/eslint/eslint-config/src/flat/profile/_common.ts @@ -20,15 +20,29 @@ // - An issue that catches code that is likely to malfunction (e.g. unterminated promise chain) // - An obsolete language feature that nobody should be using for any good reason -const { globalIgnores } = require('eslint/config'); -const promiseEslintPlugin = require('eslint-plugin-promise'); -const typescriptEslintPlugin = require('@typescript-eslint/eslint-plugin'); -const typescriptEslintParser = require('@typescript-eslint/parser'); -const rushstackEslintPlugin = require('@rushstack/eslint-plugin'); -const rushstackSecurityEslintPlugin = require('@rushstack/eslint-plugin-security'); -const { expandNamingConventionSelectors } = require('./_macros'); - -const commonNamingConventionSelectors = [ +import type { ESLint, Linter } from 'eslint'; +import { globalIgnores } from 'eslint/config'; +import promiseEslintPlugin = require('eslint-plugin-promise'); +import typescriptEslintPlugin = require('@typescript-eslint/eslint-plugin'); +import typescriptEslintParser = require('@typescript-eslint/parser'); + +import rushstackEslintPlugin = require('@rushstack/eslint-plugin'); +import rushstackSecurityEslintPlugin = require('@rushstack/eslint-plugin-security'); + +import { expandNamingConventionSelectors } from './_macros'; + +interface INamingConventionSelectorMacroBlock { + selectors: string[]; + enforceLeadingUnderscoreWhenPrivate?: boolean; + modifiers?: string[]; + [optionName: string]: unknown; +} + +function toEslintPlugin(plugin: object): ESLint.Plugin { + return plugin; +} + +const commonNamingConventionSelectors: INamingConventionSelectorMacroBlock[] = [ { // We should be stricter about 'enumMember', but it often functions legitimately as an ad hoc namespace. selectors: ['variable', 'enumMember', 'function'], @@ -188,7 +202,7 @@ const commonNamingConventionSelectors = [ // (for example config files or tests that are not included by tsconfig.json) can be linted with only the // non-type-aware rules. See the "without-type-information" helper (flat/without-type-information.js), which // disables these rules and type-aware parsing for a given set of files. -const typeAwareRules = { +const typeAwareRules: Linter.RulesRecord = { // NOTE: This new rule replaces several deprecated rules from @typescript-eslint/eslint-plugin@2.3.3: // // - @typescript-eslint/camelcase @@ -218,11 +232,11 @@ const typeAwareRules = { '@typescript-eslint/no-for-in-array': 'error' }; -const commonConfig = [ +const commonConfig: Linter.Config[] = [ // Manually authored .d.ts files are generally used to describe external APIs that are not expected // to follow our coding conventions. Linting those files tends to produce a lot of spurious suppressions, // so we simply ignore them. - globalIgnores(['**/*.d.ts']), + globalIgnores(['**/*.d.ts']) as Linter.Config, { files: ['**/*.ts', '**/*.tsx'], @@ -242,10 +256,10 @@ const commonConfig = [ } }, plugins: { - '@rushstack': rushstackEslintPlugin, - '@rushstack/security': rushstackSecurityEslintPlugin, - '@typescript-eslint': typescriptEslintPlugin, - promise: promiseEslintPlugin + '@rushstack': toEslintPlugin(rushstackEslintPlugin), + '@rushstack/security': toEslintPlugin(rushstackSecurityEslintPlugin), + '@typescript-eslint': toEslintPlugin(typescriptEslintPlugin), + promise: toEslintPlugin(promiseEslintPlugin) }, rules: { // ==================================================================== @@ -785,4 +799,4 @@ const commonConfig = [ } ]; -module.exports = { commonNamingConventionSelectors, commonConfig, typeAwareRules }; +export { commonNamingConventionSelectors, commonConfig, typeAwareRules }; diff --git a/eslint/eslint-config/flat/profile/_macros.js b/eslint/eslint-config/src/flat/profile/_macros.ts similarity index 71% rename from eslint/eslint-config/flat/profile/_macros.js rename to eslint/eslint-config/src/flat/profile/_macros.ts index 4d95857abc1..6579dd48b4b 100644 --- a/eslint/eslint-config/flat/profile/_macros.js +++ b/eslint/eslint-config/src/flat/profile/_macros.ts @@ -60,31 +60,47 @@ // }, // . . . // ] -function expandNamingConventionSelectors(inputBlocks) { - const firstPassBlocks = []; +interface INamingConventionSelectorMacroBlock { + selectors: string[]; + enforceLeadingUnderscoreWhenPrivate?: boolean; + modifiers?: string[]; + [optionName: string]: unknown; +} + +interface INamingConventionSelectorBlock { + selector: string; + selectors?: string[]; + enforceLeadingUnderscoreWhenPrivate?: boolean; + modifiers?: string[]; + [optionName: string]: unknown; +} + +function expandNamingConventionSelectors( + inputBlocks: INamingConventionSelectorMacroBlock[] +): INamingConventionSelectorBlock[] { + const firstPassBlocks: INamingConventionSelectorBlock[] = []; // Expand "selectors" --> "selector" for (const block of inputBlocks) { for (const selector of block.selectors) { - const expandedBlock = { ...block }; + const expandedBlock: INamingConventionSelectorBlock = { ...block, selector: selector }; delete expandedBlock.selectors; - expandedBlock.selector = selector; firstPassBlocks.push(expandedBlock); } } // Expand "enforceLeadingUnderscoreWhenPrivate" --> "leadingUnderscore" - const secondPassBlocks = []; + const secondPassBlocks: INamingConventionSelectorBlock[] = []; for (const block of firstPassBlocks) { if (block.enforceLeadingUnderscoreWhenPrivate) { - const expandedBlock1 = { + const expandedBlock1: INamingConventionSelectorBlock = { ...block, leadingUnderscore: 'allow' }; delete expandedBlock1.enforceLeadingUnderscoreWhenPrivate; secondPassBlocks.push(expandedBlock1); - const expandedBlock2 = { + const expandedBlock2: INamingConventionSelectorBlock = { ...block, modifiers: [...(block.modifiers ?? []), 'private'], leadingUnderscore: 'require' @@ -99,6 +115,4 @@ function expandNamingConventionSelectors(inputBlocks) { return secondPassBlocks; } -module.exports = { - expandNamingConventionSelectors: expandNamingConventionSelectors -}; +export { expandNamingConventionSelectors }; diff --git a/eslint/eslint-config/flat/profile/node-trusted-tool.js b/eslint/eslint-config/src/flat/profile/node-trusted-tool.ts similarity index 88% rename from eslint/eslint-config/flat/profile/node-trusted-tool.js rename to eslint/eslint-config/src/flat/profile/node-trusted-tool.ts index a6a05c4b061..bd2ec43a56a 100644 --- a/eslint/eslint-config/flat/profile/node-trusted-tool.js +++ b/eslint/eslint-config/src/flat/profile/node-trusted-tool.ts @@ -12,9 +12,11 @@ // DO NOT use this profile for a library project that might also be loaded by a Node.js service; // use "@rushstack/eslint-config/profiles/node" instead. -const { commonConfig } = require('./_common'); +import type { Linter } from 'eslint'; -module.exports = [ +import { commonConfig } from './_common'; + +const config: Linter.Config[] = [ ...commonConfig, { files: ['**/*.ts', '**/*.tsx'], @@ -24,3 +26,5 @@ module.exports = [ } } ]; + +export = config; diff --git a/eslint/eslint-config/profile/node.js b/eslint/eslint-config/src/flat/profile/node.ts similarity index 74% rename from eslint/eslint-config/profile/node.js rename to eslint/eslint-config/src/flat/profile/node.ts index df3b0dc79fa..2d52b407930 100644 --- a/eslint/eslint-config/profile/node.js +++ b/eslint/eslint-config/src/flat/profile/node.ts @@ -5,7 +5,10 @@ // It enables security rules that assume the service could receive malicious inputs from an // untrusted user. If that is not the case, consider using the "node-trusted-tool" profile instead. -const { buildRules } = require('./_common'); +import type { Linter } from 'eslint'; -const rules = buildRules('node'); -module.exports = rules; +import { commonConfig } from './_common'; + +const config: Linter.Config[] = [...commonConfig]; + +export = config; diff --git a/eslint/eslint-config/flat/profile/web-app.js b/eslint/eslint-config/src/flat/profile/web-app.ts similarity index 73% rename from eslint/eslint-config/flat/profile/web-app.js rename to eslint/eslint-config/src/flat/profile/web-app.ts index 8d254fdd8d9..784e5c4e34a 100644 --- a/eslint/eslint-config/flat/profile/web-app.js +++ b/eslint/eslint-config/src/flat/profile/web-app.ts @@ -7,6 +7,10 @@ // Also use this profile if you are creating a library that can be consumed by both Node.js // and web applications. -const { commonConfig } = require('./_common'); +import type { Linter } from 'eslint'; -module.exports = [...commonConfig]; +import { commonConfig } from './_common'; + +const config: Linter.Config[] = [...commonConfig]; + +export = config; diff --git a/eslint/eslint-config/flat/without-type-information.js b/eslint/eslint-config/src/flat/without-type-information.ts similarity index 86% rename from eslint/eslint-config/flat/without-type-information.js rename to eslint/eslint-config/src/flat/without-type-information.ts index 2fde93f4c73..eb00f1ceb97 100644 --- a/eslint/eslint-config/flat/without-type-information.js +++ b/eslint/eslint-config/src/flat/without-type-information.ts @@ -1,9 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. +import type { Linter } from 'eslint'; + // The profile's type-aware rules, turned off. Keep this in sync with the typeAwareRules group in // ./profile/_common.js. -const disabledTypeAwareRules = { +const disabledTypeAwareRules: Linter.RulesRecord = { '@typescript-eslint/naming-convention': 'off', '@typescript-eslint/no-floating-promises': 'off', '@typescript-eslint/no-for-in-array': 'off' @@ -28,7 +30,11 @@ const disabledTypeAwareRules = { // ...nodeTrustedToolProfile, // ...withoutTypeInformation({ files: ['tests/**/*.ts', 'playwright.config.ts'] }) // ]; -function withoutTypeInformation({ files }) { +interface IWithoutTypeInformationOptions { + files: string[]; +} + +function withoutTypeInformation({ files }: IWithoutTypeInformationOptions): Linter.Config[] { return [ { files, @@ -45,4 +51,4 @@ function withoutTypeInformation({ files }) { ]; } -module.exports = { withoutTypeInformation }; +export { withoutTypeInformation }; diff --git a/eslint/eslint-config/index.js b/eslint/eslint-config/src/index.ts similarity index 97% rename from eslint/eslint-config/index.js rename to eslint/eslint-config/src/index.ts index b8eedd9c41f..b86fb87e387 100644 --- a/eslint/eslint-config/index.js +++ b/eslint/eslint-config/src/index.ts @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. +export {}; + throw new Error( 'The index.js entry point has been removed. Please update your ESLint configuration to import one of the' + ' profile paths such as "@rushstack/eslint-config/profile/web-app" or "@rushstack/eslint-config/profile/node.' + diff --git a/eslint/eslint-config/mixins/friendly-locals.js b/eslint/eslint-config/src/mixins/friendly-locals.ts similarity index 97% rename from eslint/eslint-config/mixins/friendly-locals.js rename to eslint/eslint-config/src/mixins/friendly-locals.ts index 35b1dcd686f..672c1fa56ce 100644 --- a/eslint/eslint-config/mixins/friendly-locals.js +++ b/eslint/eslint-config/src/mixins/friendly-locals.ts @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. +import type { Linter } from 'eslint'; + // For the first 5 years of Rush, our lint rules required explicit types for most declarations // such as function parameters, function return values, and exported variables. Although more verbose, // declaring types (instead of relying on type inference) encourages engineers to create interfaces @@ -21,7 +23,7 @@ // It will restore the requirement that local variables should have explicit type declarations. // // IMPORTANT: Your .eslintrc.js "extends" field must load mixins AFTER the profile. -module.exports = { +const config: Linter.LegacyConfig = { overrides: [ { files: ['*.ts', '*.tsx'], @@ -83,3 +85,5 @@ module.exports = { } ] }; + +export = config; diff --git a/eslint/eslint-config/mixins/packlets.js b/eslint/eslint-config/src/mixins/packlets.ts similarity index 87% rename from eslint/eslint-config/mixins/packlets.js rename to eslint/eslint-config/src/mixins/packlets.ts index 9c6b791e546..46ac8b3a73f 100644 --- a/eslint/eslint-config/mixins/packlets.js +++ b/eslint/eslint-config/src/mixins/packlets.ts @@ -1,10 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. +import type { Linter } from 'eslint'; + // This mixin implements the "packlet" formalism for organizing source files. // For more information, see the documentation here: // https://www.npmjs.com/package/@rushstack/eslint-plugin-packlets -module.exports = { +const config: Linter.LegacyConfig = { plugins: ['@rushstack/eslint-plugin-packlets'], overrides: [ @@ -19,3 +21,5 @@ module.exports = { } ] }; + +export = config; diff --git a/eslint/eslint-config/mixins/react.js b/eslint/eslint-config/src/mixins/react.ts similarity index 96% rename from eslint/eslint-config/mixins/react.js rename to eslint/eslint-config/src/mixins/react.ts index 00e06aa0074..d8e615057b4 100644 --- a/eslint/eslint-config/mixins/react.js +++ b/eslint/eslint-config/src/mixins/react.ts @@ -1,9 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. +import type { Linter } from 'eslint'; + // This mixin applies some additional checks for projects using the React library. For more information, // please see the README.md for "@rushstack/eslint-config". -module.exports = { +const config: Linter.LegacyConfig = { // Plugin documentation: https://www.npmjs.com/package/eslint-plugin-react plugins: ['eslint-plugin-react'], @@ -75,3 +77,5 @@ module.exports = { } ] }; + +export = config; diff --git a/eslint/eslint-config/mixins/tsdoc.js b/eslint/eslint-config/src/mixins/tsdoc.ts similarity index 86% rename from eslint/eslint-config/mixins/tsdoc.js rename to eslint/eslint-config/src/mixins/tsdoc.ts index 5e07fc79e28..07168bbfca3 100644 --- a/eslint/eslint-config/mixins/tsdoc.js +++ b/eslint/eslint-config/src/mixins/tsdoc.ts @@ -1,9 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. +import type { Linter } from 'eslint'; + // This mixin validates code comments to ensure that they follow the TSDoc standard. For more // information please see the README.md for @rushstack/eslint-config. -module.exports = { +const config: Linter.LegacyConfig = { // The plugin documentation is here: https://www.npmjs.com/package/eslint-plugin-tsdoc plugins: ['eslint-plugin-tsdoc'], @@ -18,3 +20,5 @@ module.exports = { } ] }; + +export = config; diff --git a/eslint/eslint-config/src/module-declarations.d.ts b/eslint/eslint-config/src/module-declarations.d.ts new file mode 100644 index 00000000000..fb7c6a59711 --- /dev/null +++ b/eslint/eslint-config/src/module-declarations.d.ts @@ -0,0 +1,5 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +declare module 'eslint-plugin-promise'; +declare module 'eslint-plugin-react'; diff --git a/eslint/eslint-config/patch-eslint6.js b/eslint/eslint-config/src/patch-eslint6.ts similarity index 97% rename from eslint/eslint-config/patch-eslint6.js rename to eslint/eslint-config/src/patch-eslint6.ts index 336494cb3b9..cc49f1a6fd2 100644 --- a/eslint/eslint-config/patch-eslint6.js +++ b/eslint/eslint-config/src/patch-eslint6.ts @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. +export {}; + throw new Error( 'The patch-eslint6.js script has been rewritten to support both ESLint 6.x and 7.x.' + ' Please update your ESLint configuration to use this path instead:\n\n' + diff --git a/eslint/eslint-config/patch/custom-config-package-names.js b/eslint/eslint-config/src/patch/custom-config-package-names.ts similarity index 70% rename from eslint/eslint-config/patch/custom-config-package-names.js rename to eslint/eslint-config/src/patch/custom-config-package-names.ts index 20341195020..858b48be393 100644 --- a/eslint/eslint-config/patch/custom-config-package-names.js +++ b/eslint/eslint-config/src/patch/custom-config-package-names.ts @@ -1,4 +1,4 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. -require('@rushstack/eslint-patch/custom-config-package-names'); +import '@rushstack/eslint-patch/custom-config-package-names'; diff --git a/eslint/eslint-config/patch/modern-module-resolution.js b/eslint/eslint-config/src/patch/eslint-bulk-suppressions.ts similarity index 71% rename from eslint/eslint-config/patch/modern-module-resolution.js rename to eslint/eslint-config/src/patch/eslint-bulk-suppressions.ts index d4ba8827123..448a68224e6 100644 --- a/eslint/eslint-config/patch/modern-module-resolution.js +++ b/eslint/eslint-config/src/patch/eslint-bulk-suppressions.ts @@ -1,4 +1,4 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. -require('@rushstack/eslint-patch/modern-module-resolution'); +import '@rushstack/eslint-patch/eslint-bulk-suppressions'; diff --git a/eslint/eslint-config/patch/eslint-bulk-suppressions.js b/eslint/eslint-config/src/patch/modern-module-resolution.ts similarity index 71% rename from eslint/eslint-config/patch/eslint-bulk-suppressions.js rename to eslint/eslint-config/src/patch/modern-module-resolution.ts index 12c37b253da..8ccac47ea6b 100644 --- a/eslint/eslint-config/patch/eslint-bulk-suppressions.js +++ b/eslint/eslint-config/src/patch/modern-module-resolution.ts @@ -1,4 +1,4 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. -require('@rushstack/eslint-patch/eslint-bulk-suppressions'); +import '@rushstack/eslint-patch/modern-module-resolution'; diff --git a/eslint/eslint-config/profile/_common.js b/eslint/eslint-config/src/profile/_common.ts similarity index 98% rename from eslint/eslint-config/profile/_common.js rename to eslint/eslint-config/src/profile/_common.ts index 584628cd15f..f8ed284de81 100644 --- a/eslint/eslint-config/profile/_common.js +++ b/eslint/eslint-config/src/profile/_common.ts @@ -1,9 +1,18 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. -const macros = require('./_macros'); +import type { Linter } from 'eslint'; -const namingConventionRuleOptions = [ +import { expandNamingConventionSelectors } from './_macros'; + +interface INamingConventionSelectorMacroBlock { + selectors: string[]; + enforceLeadingUnderscoreWhenPrivate?: boolean; + modifiers?: string[]; + [optionName: string]: unknown; +} + +const namingConventionRuleOptions: INamingConventionSelectorMacroBlock[] = [ { // We should be stricter about 'enumMember', but it often functions legitimately as an ad hoc namespace. selectors: ['variable', 'enumMember', 'function'], @@ -177,7 +186,7 @@ const namingConventionRuleOptions = [ // - An issue that catches code that is likely to malfunction (e.g. unterminated promise chain) // - An obsolete language feature that nobody should be using for any good reason -function buildRules(profile) { +function buildRules(profile: 'node' | 'node-trusted-tool' | 'web-app'): Linter.LegacyConfig { return { // After an .eslintrc.js file is loaded, ESLint will normally continue visiting all parent folders // to look for other .eslintrc.js files, and also consult a personal file ~/.eslintrc.js. If any files @@ -318,7 +327,7 @@ function buildRules(profile) { // Docs: https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/naming-convention.md '@typescript-eslint/naming-convention': [ 'warn', - ...macros.expandNamingConventionSelectors(namingConventionRuleOptions) + ...expandNamingConventionSelectors(namingConventionRuleOptions) ], // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json @@ -800,5 +809,4 @@ function buildRules(profile) { }; } -exports.buildRules = buildRules; -exports.namingConventionRuleOptions = namingConventionRuleOptions; +export { buildRules, namingConventionRuleOptions }; diff --git a/eslint/eslint-config/profile/_macros.js b/eslint/eslint-config/src/profile/_macros.ts similarity index 71% rename from eslint/eslint-config/profile/_macros.js rename to eslint/eslint-config/src/profile/_macros.ts index 87c8487b314..6579dd48b4b 100644 --- a/eslint/eslint-config/profile/_macros.js +++ b/eslint/eslint-config/src/profile/_macros.ts @@ -60,31 +60,47 @@ // }, // . . . // ] -function expandNamingConventionSelectors(inputBlocks) { - const firstPassBlocks = []; +interface INamingConventionSelectorMacroBlock { + selectors: string[]; + enforceLeadingUnderscoreWhenPrivate?: boolean; + modifiers?: string[]; + [optionName: string]: unknown; +} + +interface INamingConventionSelectorBlock { + selector: string; + selectors?: string[]; + enforceLeadingUnderscoreWhenPrivate?: boolean; + modifiers?: string[]; + [optionName: string]: unknown; +} + +function expandNamingConventionSelectors( + inputBlocks: INamingConventionSelectorMacroBlock[] +): INamingConventionSelectorBlock[] { + const firstPassBlocks: INamingConventionSelectorBlock[] = []; // Expand "selectors" --> "selector" for (const block of inputBlocks) { for (const selector of block.selectors) { - const expandedBlock = { ...block }; + const expandedBlock: INamingConventionSelectorBlock = { ...block, selector: selector }; delete expandedBlock.selectors; - expandedBlock.selector = selector; firstPassBlocks.push(expandedBlock); } } // Expand "enforceLeadingUnderscoreWhenPrivate" --> "leadingUnderscore" - const secondPassBlocks = []; + const secondPassBlocks: INamingConventionSelectorBlock[] = []; for (const block of firstPassBlocks) { if (block.enforceLeadingUnderscoreWhenPrivate) { - const expandedBlock1 = { + const expandedBlock1: INamingConventionSelectorBlock = { ...block, leadingUnderscore: 'allow' }; delete expandedBlock1.enforceLeadingUnderscoreWhenPrivate; secondPassBlocks.push(expandedBlock1); - const expandedBlock2 = { + const expandedBlock2: INamingConventionSelectorBlock = { ...block, modifiers: [...(block.modifiers ?? []), 'private'], leadingUnderscore: 'require' @@ -99,4 +115,4 @@ function expandNamingConventionSelectors(inputBlocks) { return secondPassBlocks; } -exports.expandNamingConventionSelectors = expandNamingConventionSelectors; +export { expandNamingConventionSelectors }; diff --git a/eslint/eslint-config/profile/node-trusted-tool.js b/eslint/eslint-config/src/profile/node-trusted-tool.ts similarity index 83% rename from eslint/eslint-config/profile/node-trusted-tool.js rename to eslint/eslint-config/src/profile/node-trusted-tool.ts index f185f532b70..f6b7d4ca271 100644 --- a/eslint/eslint-config/profile/node-trusted-tool.js +++ b/eslint/eslint-config/src/profile/node-trusted-tool.ts @@ -12,7 +12,9 @@ // DO NOT use this profile for a library project that might also be loaded by a Node.js service; // use "@rushstack/eslint-config/profiles/node" instead. -const { buildRules } = require('./_common'); +import type { Linter } from 'eslint'; -const rules = buildRules('node-trusted-tool'); -module.exports = rules; +import { buildRules } from './_common'; + +const rules: Linter.LegacyConfig = buildRules('node-trusted-tool'); +export = rules; diff --git a/eslint/eslint-config/flat/profile/node.js b/eslint/eslint-config/src/profile/node.ts similarity index 74% rename from eslint/eslint-config/flat/profile/node.js rename to eslint/eslint-config/src/profile/node.ts index e18325a793a..7fd6eb072e5 100644 --- a/eslint/eslint-config/flat/profile/node.js +++ b/eslint/eslint-config/src/profile/node.ts @@ -5,6 +5,9 @@ // It enables security rules that assume the service could receive malicious inputs from an // untrusted user. If that is not the case, consider using the "node-trusted-tool" profile instead. -const { commonConfig } = require('./_common'); +import type { Linter } from 'eslint'; -module.exports = [...commonConfig]; +import { buildRules } from './_common'; + +const rules: Linter.LegacyConfig = buildRules('node'); +export = rules; diff --git a/eslint/eslint-config/profile/web-app.js b/eslint/eslint-config/src/profile/web-app.ts similarity index 73% rename from eslint/eslint-config/profile/web-app.js rename to eslint/eslint-config/src/profile/web-app.ts index 916b888ec6e..a0d35c13edd 100644 --- a/eslint/eslint-config/profile/web-app.js +++ b/eslint/eslint-config/src/profile/web-app.ts @@ -7,7 +7,9 @@ // Also use this profile if you are creating a library that can be consumed by both Node.js // and web applications. -const { buildRules } = require('./_common'); +import type { Linter } from 'eslint'; -const rules = buildRules('web-app'); -module.exports = rules; +import { buildRules } from './_common'; + +const rules: Linter.LegacyConfig = buildRules('web-app'); +export = rules; diff --git a/eslint/eslint-config/react.js b/eslint/eslint-config/src/react.ts similarity index 97% rename from eslint/eslint-config/react.js rename to eslint/eslint-config/src/react.ts index 14516d2ff32..f4b4e005289 100644 --- a/eslint/eslint-config/react.js +++ b/eslint/eslint-config/src/react.ts @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. +export {}; + throw new Error( 'The react.js entry point has moved. Please update your ESLint configuration to reference' + ' "@rushstack/eslint-config/mixins/react" instead.' + diff --git a/eslint/eslint-config/tsconfig.json b/eslint/eslint-config/tsconfig.json new file mode 100644 index 00000000000..e98df1ad324 --- /dev/null +++ b/eslint/eslint-config/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "./node_modules/decoupled-local-node-rig/profiles/default/tsconfig-base.json", + + "compilerOptions": { + "module": "Node16" + } +} From 7ce8b2c831ff150bfcf6b16198dced2e5a7394b7 Mon Sep 17 00:00:00 2001 From: Ian Clanton-Thuon Date: Sun, 13 Sep 2026 18:21:18 -0400 Subject: [PATCH 03/16] [eslint-config] Link disabledTypeAwareRules to typeAwareRules via the type system Use `satisfies Linter.RulesRecord` on typeAwareRules so its literal rule names are preserved in the inferred type, and type disabledTypeAwareRules as `Record`. Adding a type-aware rule now becomes a compile error until it is also disabled in without-type-information. Also add the change file for the TypeScript conversion. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../eslint-config-typescript_2026-09-13-04-30-00.json | 9 +++++++++ eslint/eslint-config/src/flat/profile/_common.ts | 8 ++++++-- eslint/eslint-config/src/flat/profile/_macros.ts | 2 +- .../eslint-config/src/flat/without-type-information.ts | 9 ++++++--- 4 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 common/changes/@rushstack/eslint-config/eslint-config-typescript_2026-09-13-04-30-00.json diff --git a/common/changes/@rushstack/eslint-config/eslint-config-typescript_2026-09-13-04-30-00.json b/common/changes/@rushstack/eslint-config/eslint-config-typescript_2026-09-13-04-30-00.json new file mode 100644 index 00000000000..ae50701f89d --- /dev/null +++ b/common/changes/@rushstack/eslint-config/eslint-config-typescript_2026-09-13-04-30-00.json @@ -0,0 +1,9 @@ +{ + "changes": [ + { + "packageName": "@rushstack/eslint-config", + "comment": "Author the package in TypeScript (built to CommonJS via Heft). The existing subpath entry points are preserved via a package.json \"exports\" map and the compiled configuration is runtime-identical to the previous JavaScript.", + "type": "patch" + } + ] +} diff --git a/eslint/eslint-config/src/flat/profile/_common.ts b/eslint/eslint-config/src/flat/profile/_common.ts index d8cd9889128..03ab7185402 100644 --- a/eslint/eslint-config/src/flat/profile/_common.ts +++ b/eslint/eslint-config/src/flat/profile/_common.ts @@ -202,7 +202,11 @@ const commonNamingConventionSelectors: INamingConventionSelectorMacroBlock[] = [ // (for example config files or tests that are not included by tsconfig.json) can be linted with only the // non-type-aware rules. See the "without-type-information" helper (flat/without-type-information.js), which // disables these rules and type-aware parsing for a given set of files. -const typeAwareRules: Linter.RulesRecord = { +// +// Use `satisfies` (rather than a type annotation) so that the literal rule names are preserved in the inferred +// type, which lets "./without-type-information" derive `keyof typeof typeAwareRules`. +// eslint-disable-next-line @typescript-eslint/typedef +const typeAwareRules = { // NOTE: This new rule replaces several deprecated rules from @typescript-eslint/eslint-plugin@2.3.3: // // - @typescript-eslint/camelcase @@ -230,7 +234,7 @@ const typeAwareRules: Linter.RulesRecord = { // RATIONALE: Catches a common coding mistake. '@typescript-eslint/no-for-in-array': 'error' -}; +} as const satisfies Linter.RulesRecord; const commonConfig: Linter.Config[] = [ // Manually authored .d.ts files are generally used to describe external APIs that are not expected diff --git a/eslint/eslint-config/src/flat/profile/_macros.ts b/eslint/eslint-config/src/flat/profile/_macros.ts index 6579dd48b4b..492ea0e27d3 100644 --- a/eslint/eslint-config/src/flat/profile/_macros.ts +++ b/eslint/eslint-config/src/flat/profile/_macros.ts @@ -67,7 +67,7 @@ interface INamingConventionSelectorMacroBlock { [optionName: string]: unknown; } -interface INamingConventionSelectorBlock { +export interface INamingConventionSelectorBlock { selector: string; selectors?: string[]; enforceLeadingUnderscoreWhenPrivate?: boolean; diff --git a/eslint/eslint-config/src/flat/without-type-information.ts b/eslint/eslint-config/src/flat/without-type-information.ts index eb00f1ceb97..0853f3f107d 100644 --- a/eslint/eslint-config/src/flat/without-type-information.ts +++ b/eslint/eslint-config/src/flat/without-type-information.ts @@ -3,9 +3,12 @@ import type { Linter } from 'eslint'; -// The profile's type-aware rules, turned off. Keep this in sync with the typeAwareRules group in -// ./profile/_common.js. -const disabledTypeAwareRules: Linter.RulesRecord = { +import type { typeAwareRules } from './profile/_common'; + +// The profile's type-aware rules, turned off. Typing this as `Record` keeps +// it in sync with the typeAwareRules group in ./profile/_common: adding a type-aware rule there becomes a compile +// error until it is disabled here as well. +const disabledTypeAwareRules: Record = { '@typescript-eslint/naming-convention': 'off', '@typescript-eslint/no-floating-promises': 'off', '@typescript-eslint/no-for-in-array': 'off' From 4e6dc57a6fb85843d2bcf396e85ce50b97c7e46f Mon Sep 17 00:00:00 2001 From: Ian Clanton-Thuon Date: Sun, 13 Sep 2026 18:29:28 -0400 Subject: [PATCH 04/16] [eslint-config] Use ES import syntax and `as const satisfies` for the rule group Replace the remaining `import x = require(...)` forms with ES `import` statements (esModuleInterop is enabled), and use `as const satisfies Linter.RulesRecord` for the typeAwareRules group. The compiled configuration remains runtime-identical. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../eslint-config/src/flat/mixins/friendly-locals.ts | 2 +- eslint/eslint-config/src/flat/mixins/packlets.ts | 2 +- eslint/eslint-config/src/flat/mixins/react.ts | 2 +- eslint/eslint-config/src/flat/mixins/tsdoc.ts | 2 +- eslint/eslint-config/src/flat/profile/_common.ts | 10 +++++----- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/eslint/eslint-config/src/flat/mixins/friendly-locals.ts b/eslint/eslint-config/src/flat/mixins/friendly-locals.ts index 84be3ff5f26..bf473c195af 100644 --- a/eslint/eslint-config/src/flat/mixins/friendly-locals.ts +++ b/eslint/eslint-config/src/flat/mixins/friendly-locals.ts @@ -23,7 +23,7 @@ // IMPORTANT: Mixins must be included in your ESLint configuration AFTER the profile import type { ESLint, Linter } from 'eslint'; -import typescriptEslintPlugin = require('@typescript-eslint/eslint-plugin'); +import typescriptEslintPlugin from '@typescript-eslint/eslint-plugin'; function toEslintPlugin(plugin: object): ESLint.Plugin { return plugin; diff --git a/eslint/eslint-config/src/flat/mixins/packlets.ts b/eslint/eslint-config/src/flat/mixins/packlets.ts index bc53988db83..686e556844c 100644 --- a/eslint/eslint-config/src/flat/mixins/packlets.ts +++ b/eslint/eslint-config/src/flat/mixins/packlets.ts @@ -9,7 +9,7 @@ import type { ESLint, Linter } from 'eslint'; -import rushstackPackletsEslintPlugin = require('@rushstack/eslint-plugin-packlets'); +import rushstackPackletsEslintPlugin from '@rushstack/eslint-plugin-packlets'; function toEslintPlugin(plugin: object): ESLint.Plugin { return plugin; diff --git a/eslint/eslint-config/src/flat/mixins/react.ts b/eslint/eslint-config/src/flat/mixins/react.ts index 72764ff6c9b..155896c1790 100644 --- a/eslint/eslint-config/src/flat/mixins/react.ts +++ b/eslint/eslint-config/src/flat/mixins/react.ts @@ -7,7 +7,7 @@ // IMPORTANT: Mixins must be included in your ESLint configuration AFTER the profile import type { Linter } from 'eslint'; -import reactEslintPlugin = require('eslint-plugin-react'); +import reactEslintPlugin from 'eslint-plugin-react'; const config: Linter.Config[] = [ { diff --git a/eslint/eslint-config/src/flat/mixins/tsdoc.ts b/eslint/eslint-config/src/flat/mixins/tsdoc.ts index 9307f0f7c3a..096fd2e053d 100644 --- a/eslint/eslint-config/src/flat/mixins/tsdoc.ts +++ b/eslint/eslint-config/src/flat/mixins/tsdoc.ts @@ -7,7 +7,7 @@ // IMPORTANT: Mixins must be included in your ESLint configuration AFTER the profile import type { Linter } from 'eslint'; -import tsdocEslintPlugin = require('eslint-plugin-tsdoc'); +import tsdocEslintPlugin from 'eslint-plugin-tsdoc'; const config: Linter.Config[] = [ { diff --git a/eslint/eslint-config/src/flat/profile/_common.ts b/eslint/eslint-config/src/flat/profile/_common.ts index 03ab7185402..8039a5ffec8 100644 --- a/eslint/eslint-config/src/flat/profile/_common.ts +++ b/eslint/eslint-config/src/flat/profile/_common.ts @@ -22,12 +22,12 @@ import type { ESLint, Linter } from 'eslint'; import { globalIgnores } from 'eslint/config'; -import promiseEslintPlugin = require('eslint-plugin-promise'); -import typescriptEslintPlugin = require('@typescript-eslint/eslint-plugin'); -import typescriptEslintParser = require('@typescript-eslint/parser'); +import promiseEslintPlugin from 'eslint-plugin-promise'; +import typescriptEslintPlugin from '@typescript-eslint/eslint-plugin'; +import typescriptEslintParser from '@typescript-eslint/parser'; -import rushstackEslintPlugin = require('@rushstack/eslint-plugin'); -import rushstackSecurityEslintPlugin = require('@rushstack/eslint-plugin-security'); +import rushstackEslintPlugin from '@rushstack/eslint-plugin'; +import rushstackSecurityEslintPlugin from '@rushstack/eslint-plugin-security'; import { expandNamingConventionSelectors } from './_macros'; From f8d0d4f544838e733c05012671737fce5777f97a Mon Sep 17 00:00:00 2001 From: Ian Clanton-Thuon Date: Mon, 14 Sep 2026 11:53:55 -0400 Subject: [PATCH 05/16] [eslint-config] Export the @rushstack plugins as ESLint.Plugin to drop the coercion helper typescript-eslint's `RuleModule` type is intentionally not structurally assignable to ESLint's `RuleDefinition`, so a plugin object authored with typescript-eslint's types cannot be assigned to an `ESLint.Plugin` without a widening cast. Move that cast to each @rushstack plugin's export (`@rushstack/eslint-plugin`, `-security`, `-packlets`) so their public type is `ESLint.Plugin`, and drop the `toEslintPlugin` helper from the config. Only the genuinely third-party @typescript-eslint plugin now needs a localized cast. The casts widen through `object` (never `unknown`), and the compiled configuration remains runtime-identical. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- ...int-config-typescript_2026-09-14-04-00-00.json | 9 +++++++++ ...int-config-typescript_2026-09-14-04-00-00.json | 9 +++++++++ ...int-config-typescript_2026-09-14-04-00-00.json | 9 +++++++++ .../src/flat/mixins/friendly-locals.ts | 11 ++++++----- eslint/eslint-config/src/flat/mixins/packlets.ts | 8 ++------ eslint/eslint-config/src/flat/profile/_common.ts | 15 +++++++-------- eslint/eslint-plugin-packlets/src/index.ts | 7 ++++++- eslint/eslint-plugin-security/src/index.ts | 7 ++++++- eslint/eslint-plugin/src/index.ts | 7 ++++++- 9 files changed, 60 insertions(+), 22 deletions(-) create mode 100644 common/changes/@rushstack/eslint-plugin-packlets/eslint-config-typescript_2026-09-14-04-00-00.json create mode 100644 common/changes/@rushstack/eslint-plugin-security/eslint-config-typescript_2026-09-14-04-00-00.json create mode 100644 common/changes/@rushstack/eslint-plugin/eslint-config-typescript_2026-09-14-04-00-00.json diff --git a/common/changes/@rushstack/eslint-plugin-packlets/eslint-config-typescript_2026-09-14-04-00-00.json b/common/changes/@rushstack/eslint-plugin-packlets/eslint-config-typescript_2026-09-14-04-00-00.json new file mode 100644 index 00000000000..188b364da5d --- /dev/null +++ b/common/changes/@rushstack/eslint-plugin-packlets/eslint-config-typescript_2026-09-14-04-00-00.json @@ -0,0 +1,9 @@ +{ + "changes": [ + { + "packageName": "@rushstack/eslint-plugin-packlets", + "comment": "Type the plugin's default export as `ESLint.Plugin` so that it can be referenced in ESLint flat-config `plugins` maps without a cast. This is a type-only change; the runtime export is unchanged.", + "type": "patch" + } + ] +} diff --git a/common/changes/@rushstack/eslint-plugin-security/eslint-config-typescript_2026-09-14-04-00-00.json b/common/changes/@rushstack/eslint-plugin-security/eslint-config-typescript_2026-09-14-04-00-00.json new file mode 100644 index 00000000000..79793b0a962 --- /dev/null +++ b/common/changes/@rushstack/eslint-plugin-security/eslint-config-typescript_2026-09-14-04-00-00.json @@ -0,0 +1,9 @@ +{ + "changes": [ + { + "packageName": "@rushstack/eslint-plugin-security", + "comment": "Type the plugin's default export as `ESLint.Plugin` so that it can be referenced in ESLint flat-config `plugins` maps without a cast. This is a type-only change; the runtime export is unchanged.", + "type": "patch" + } + ] +} diff --git a/common/changes/@rushstack/eslint-plugin/eslint-config-typescript_2026-09-14-04-00-00.json b/common/changes/@rushstack/eslint-plugin/eslint-config-typescript_2026-09-14-04-00-00.json new file mode 100644 index 00000000000..791e582f809 --- /dev/null +++ b/common/changes/@rushstack/eslint-plugin/eslint-config-typescript_2026-09-14-04-00-00.json @@ -0,0 +1,9 @@ +{ + "changes": [ + { + "packageName": "@rushstack/eslint-plugin", + "comment": "Type the plugin's default export as `ESLint.Plugin` so that it can be referenced in ESLint flat-config `plugins` maps without a cast. This is a type-only change; the runtime export is unchanged.", + "type": "patch" + } + ] +} diff --git a/eslint/eslint-config/src/flat/mixins/friendly-locals.ts b/eslint/eslint-config/src/flat/mixins/friendly-locals.ts index bf473c195af..86357f149b2 100644 --- a/eslint/eslint-config/src/flat/mixins/friendly-locals.ts +++ b/eslint/eslint-config/src/flat/mixins/friendly-locals.ts @@ -25,15 +25,16 @@ import type { ESLint, Linter } from 'eslint'; import typescriptEslintPlugin from '@typescript-eslint/eslint-plugin'; -function toEslintPlugin(plugin: object): ESLint.Plugin { - return plugin; -} +// The third-party @typescript-eslint plugin does not present itself as an `ESLint.Plugin` (its typescript-eslint +// `RuleModule` types are intentionally not assignable to ESLint's `RuleDefinition`), so widen it through +// `object` to reference it in a flat-config `plugins` map. +const typescriptEslintPluginAsEslintPlugin: ESLint.Plugin = typescriptEslintPlugin as object as ESLint.Plugin; const config: Linter.Config[] = [ { files: ['**/*.ts', '**/*.tsx'], plugins: { - '@typescript-eslint': toEslintPlugin(typescriptEslintPlugin) + '@typescript-eslint': typescriptEslintPluginAsEslintPlugin }, rules: { '@rushstack/typedef-var': 'off', // <--- disabled by the mixin @@ -74,7 +75,7 @@ const config: Linter.Config[] = [ '**/test/**/*.tsx' ], plugins: { - '@typescript-eslint': toEslintPlugin(typescriptEslintPlugin) + '@typescript-eslint': typescriptEslintPluginAsEslintPlugin }, rules: { '@typescript-eslint/typedef': [ diff --git a/eslint/eslint-config/src/flat/mixins/packlets.ts b/eslint/eslint-config/src/flat/mixins/packlets.ts index 686e556844c..57f811d32de 100644 --- a/eslint/eslint-config/src/flat/mixins/packlets.ts +++ b/eslint/eslint-config/src/flat/mixins/packlets.ts @@ -7,18 +7,14 @@ // // IMPORTANT: Mixins must be included in your ESLint configuration AFTER the profile -import type { ESLint, Linter } from 'eslint'; +import type { Linter } from 'eslint'; import rushstackPackletsEslintPlugin from '@rushstack/eslint-plugin-packlets'; -function toEslintPlugin(plugin: object): ESLint.Plugin { - return plugin; -} - const config: Linter.Config = { files: ['**/*.ts', '**/*.tsx'], plugins: { - '@rushstack/packlets': toEslintPlugin(rushstackPackletsEslintPlugin) + '@rushstack/packlets': rushstackPackletsEslintPlugin }, rules: { '@rushstack/packlets/mechanics': 'warn', diff --git a/eslint/eslint-config/src/flat/profile/_common.ts b/eslint/eslint-config/src/flat/profile/_common.ts index 8039a5ffec8..33996a54a5e 100644 --- a/eslint/eslint-config/src/flat/profile/_common.ts +++ b/eslint/eslint-config/src/flat/profile/_common.ts @@ -38,10 +38,6 @@ interface INamingConventionSelectorMacroBlock { [optionName: string]: unknown; } -function toEslintPlugin(plugin: object): ESLint.Plugin { - return plugin; -} - const commonNamingConventionSelectors: INamingConventionSelectorMacroBlock[] = [ { // We should be stricter about 'enumMember', but it often functions legitimately as an ad hoc namespace. @@ -260,10 +256,13 @@ const commonConfig: Linter.Config[] = [ } }, plugins: { - '@rushstack': toEslintPlugin(rushstackEslintPlugin), - '@rushstack/security': toEslintPlugin(rushstackSecurityEslintPlugin), - '@typescript-eslint': toEslintPlugin(typescriptEslintPlugin), - promise: toEslintPlugin(promiseEslintPlugin) + '@rushstack': rushstackEslintPlugin, + '@rushstack/security': rushstackSecurityEslintPlugin, + // Unlike the @rushstack plugins, the third-party @typescript-eslint plugin does not present itself as an + // `ESLint.Plugin` (its typescript-eslint `RuleModule` types are intentionally not assignable to ESLint's + // `RuleDefinition`), so widen it through `object` here. + '@typescript-eslint': typescriptEslintPlugin as object as ESLint.Plugin, + promise: promiseEslintPlugin }, rules: { // ==================================================================== diff --git a/eslint/eslint-plugin-packlets/src/index.ts b/eslint/eslint-plugin-packlets/src/index.ts index 7958fa842df..a3ee2d1bdb6 100644 --- a/eslint/eslint-plugin-packlets/src/index.ts +++ b/eslint/eslint-plugin-packlets/src/index.ts @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. +import type { ESLint } from 'eslint'; import type { TSESLint } from '@typescript-eslint/utils'; import { mechanics } from './mechanics'; @@ -32,4 +33,8 @@ const plugin: IPlugin = { } }; -export = plugin; +// The rule modules are authored with typescript-eslint's types, whose `RuleModule` is intentionally not +// structurally assignable to ESLint's `RuleDefinition`. Widen through `object` (rather than `unknown`) to +// present the plugin as an `ESLint.Plugin` so that consumers (such as flat-config `plugins` maps) can +// reference it without a cast of their own. +export = plugin as object as ESLint.Plugin; diff --git a/eslint/eslint-plugin-security/src/index.ts b/eslint/eslint-plugin-security/src/index.ts index 8e2d433001c..8a2d41f2d46 100644 --- a/eslint/eslint-plugin-security/src/index.ts +++ b/eslint/eslint-plugin-security/src/index.ts @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. +import type { ESLint } from 'eslint'; import type { TSESLint } from '@typescript-eslint/utils'; import { noUnsafeRegExp } from './no-unsafe-regexp'; @@ -16,4 +17,8 @@ const plugin: IPlugin = { } }; -export = plugin; +// The rule modules are authored with typescript-eslint's types, whose `RuleModule` is intentionally not +// structurally assignable to ESLint's `RuleDefinition`. Widen through `object` (rather than `unknown`) to +// present the plugin as an `ESLint.Plugin` so that consumers (such as flat-config `plugins` maps) can +// reference it without a cast of their own. +export = plugin as object as ESLint.Plugin; diff --git a/eslint/eslint-plugin/src/index.ts b/eslint/eslint-plugin/src/index.ts index 61f0c64f23e..8ae431a3003 100644 --- a/eslint/eslint-plugin/src/index.ts +++ b/eslint/eslint-plugin/src/index.ts @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. +import type { ESLint } from 'eslint'; import type { TSESLint } from '@typescript-eslint/utils'; import { hoistJestMock } from './hoist-jest-mock'; @@ -56,4 +57,8 @@ const plugin: IPlugin = { } }; -export = plugin; +// The rule modules are authored with typescript-eslint's types, whose `RuleModule` is intentionally not +// structurally assignable to ESLint's `RuleDefinition`. Widen through `object` (rather than `unknown`) to +// present the plugin as an `ESLint.Plugin` so that consumers (such as flat-config `plugins` maps) can +// reference it without a cast of their own. +export = plugin as object as ESLint.Plugin; From 10d969c178b5a5bc00e14ec97ede97ad317b5d9a Mon Sep 17 00:00:00 2001 From: Ian Clanton-Thuon Date: Mon, 14 Sep 2026 12:24:39 -0400 Subject: [PATCH 06/16] fixup! [eslint-config] Convert the package to TypeScript --- rush.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rush.json b/rush.json index 985396fe793..5f6bc73d8fd 100644 --- a/rush.json +++ b/rush.json @@ -812,7 +812,8 @@ "packageName": "@rushstack/eslint-config", "projectFolder": "eslint/eslint-config", "reviewCategory": "libraries", - "shouldPublish": true + "shouldPublish": true, + "decoupledLocalDependencies": ["@rushstack/heft"] }, { "packageName": "local-eslint-config", From 712ad04bc1d4f6227ee59ebe76b15cb7314fb734 Mon Sep 17 00:00:00 2001 From: Ian Clanton-Thuon Date: Mon, 14 Sep 2026 12:45:20 -0400 Subject: [PATCH 07/16] Clean up types. --- .../src/flat/mixins/friendly-locals.ts | 3 ++- eslint/eslint-config/src/flat/profile/_macros.ts | 13 +++++++------ .../src/flat/without-type-information.ts | 3 ++- eslint/eslint-plugin/src/index.ts | 3 +-- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/eslint/eslint-config/src/flat/mixins/friendly-locals.ts b/eslint/eslint-config/src/flat/mixins/friendly-locals.ts index 86357f149b2..f22e7f9f53f 100644 --- a/eslint/eslint-config/src/flat/mixins/friendly-locals.ts +++ b/eslint/eslint-config/src/flat/mixins/friendly-locals.ts @@ -28,7 +28,8 @@ import typescriptEslintPlugin from '@typescript-eslint/eslint-plugin'; // The third-party @typescript-eslint plugin does not present itself as an `ESLint.Plugin` (its typescript-eslint // `RuleModule` types are intentionally not assignable to ESLint's `RuleDefinition`), so widen it through // `object` to reference it in a flat-config `plugins` map. -const typescriptEslintPluginAsEslintPlugin: ESLint.Plugin = typescriptEslintPlugin as object as ESLint.Plugin; +const typescriptEslintPluginAsEslintPlugin: ESLint.Plugin = + typescriptEslintPlugin as unknown as ESLint.Plugin; const config: Linter.Config[] = [ { diff --git a/eslint/eslint-config/src/flat/profile/_macros.ts b/eslint/eslint-config/src/flat/profile/_macros.ts index 492ea0e27d3..bb23daf68a9 100644 --- a/eslint/eslint-config/src/flat/profile/_macros.ts +++ b/eslint/eslint-config/src/flat/profile/_macros.ts @@ -60,19 +60,20 @@ // }, // . . . // ] -interface INamingConventionSelectorMacroBlock { - selectors: string[]; + +interface INamingConventionSelectorBlockBase { enforceLeadingUnderscoreWhenPrivate?: boolean; modifiers?: string[]; [optionName: string]: unknown; } -export interface INamingConventionSelectorBlock { +interface INamingConventionSelectorMacroBlock extends INamingConventionSelectorBlockBase { + selectors: string[]; +} + +export interface INamingConventionSelectorBlock extends INamingConventionSelectorBlockBase { selector: string; selectors?: string[]; - enforceLeadingUnderscoreWhenPrivate?: boolean; - modifiers?: string[]; - [optionName: string]: unknown; } function expandNamingConventionSelectors( diff --git a/eslint/eslint-config/src/flat/without-type-information.ts b/eslint/eslint-config/src/flat/without-type-information.ts index 0853f3f107d..3d0089ac47e 100644 --- a/eslint/eslint-config/src/flat/without-type-information.ts +++ b/eslint/eslint-config/src/flat/without-type-information.ts @@ -37,7 +37,8 @@ interface IWithoutTypeInformationOptions { files: string[]; } -function withoutTypeInformation({ files }: IWithoutTypeInformationOptions): Linter.Config[] { +function withoutTypeInformation(options: IWithoutTypeInformationOptions): Linter.Config[] { + const { files } = options; return [ { files, diff --git a/eslint/eslint-plugin/src/index.ts b/eslint/eslint-plugin/src/index.ts index 8ae431a3003..0e81fb1963c 100644 --- a/eslint/eslint-plugin/src/index.ts +++ b/eslint/eslint-plugin/src/index.ts @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. -import type { ESLint } from 'eslint'; import type { TSESLint } from '@typescript-eslint/utils'; import { hoistJestMock } from './hoist-jest-mock'; @@ -61,4 +60,4 @@ const plugin: IPlugin = { // structurally assignable to ESLint's `RuleDefinition`. Widen through `object` (rather than `unknown`) to // present the plugin as an `ESLint.Plugin` so that consumers (such as flat-config `plugins` maps) can // reference it without a cast of their own. -export = plugin as object as ESLint.Plugin; +export = plugin as unknown as IPlugin; From 056729604a4c48280c4948b592f2d9db2983be89 Mon Sep 17 00:00:00 2001 From: Ian Clanton-Thuon Date: Mon, 14 Sep 2026 12:52:59 -0400 Subject: [PATCH 08/16] Rush update. --- .../build-tests-subspace/repo-state.json | 2 +- .../config/subspaces/default/pnpm-lock.yaml | 46 +++++++++++-------- .../config/subspaces/default/repo-state.json | 2 +- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/common/config/subspaces/build-tests-subspace/repo-state.json b/common/config/subspaces/build-tests-subspace/repo-state.json index a8b0af670ab..6e6e59dee0b 100644 --- a/common/config/subspaces/build-tests-subspace/repo-state.json +++ b/common/config/subspaces/build-tests-subspace/repo-state.json @@ -2,5 +2,5 @@ { "pnpmShrinkwrapHash": "50a1f3c8d2270f840d49426b54c028e26de05189", "preferredVersionsHash": "550b4cee0bef4e97db6c6aad726df5149d20e7d9", - "packageJsonInjectedDependenciesHash": "af9e972a5d86601391889a0ff0ae8349679a6a10" + "packageJsonInjectedDependenciesHash": "d7c7e7ed81eabefe053347ab6e27d121c3d0c2db" } diff --git a/common/config/subspaces/default/pnpm-lock.yaml b/common/config/subspaces/default/pnpm-lock.yaml index a9c01ddb734..d13faefc471 100644 --- a/common/config/subspaces/default/pnpm-lock.yaml +++ b/common/config/subspaces/default/pnpm-lock.yaml @@ -2990,6 +2990,12 @@ importers: specifier: ~0.5.1 version: 0.5.2(eslint@9.37.0)(typescript@5.8.2) devDependencies: + '@rushstack/heft': + specifier: 1.2.25 + version: 1.2.25(@types/node@22.9.3) + decoupled-local-node-rig: + specifier: workspace:* + version: link:../../rigs/decoupled-local-node-rig eslint: specifier: ~9.37.0 version: 9.37.0 @@ -4743,7 +4749,7 @@ importers: version: 1.2.25(@types/node@20.17.19) '@rushstack/heft-node-rig': specifier: 2.11.48 - version: 2.11.48(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/node@20.17.19)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.0))(jest-environment-jsdom@30.3.0) + version: 2.11.48(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/node@20.17.19)(esbuild-register@3.6.0(esbuild@0.28.0))(jest-environment-jsdom@30.3.0) '@types/jest': specifier: 30.0.0 version: 30.0.0 @@ -8870,7 +8876,7 @@ packages: '@pnpm/logger': ^5.0.0 '@pnpm/lockfile-types@5.1.5': - resolution: {integrity: sha1-FLhcl23c90dPWmopNRy1eZWdDsg=, tarball: https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@pnpm/lockfile-types/-/lockfile-types-5.1.5.tgz} + resolution: {integrity: sha1-FLhcl23c90dPWmopNRy1eZWdDsg=, tarball: https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@pnpm/lockfile-types/-/lockfile-types-5.1.5.tgz} engines: {node: '>=16.14'} '@pnpm/lockfile.fs@1001.1.32': @@ -12380,7 +12386,7 @@ packages: hasBin: true cross-spawn@6.0.6: - resolution: {integrity: sha1-MNDvoHEt2361p24ehyG/+vprXVc=, tarball: https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/cross-spawn/-/cross-spawn-6.0.6.tgz} + resolution: {integrity: sha1-MNDvoHEt2361p24ehyG/+vprXVc=, tarball: https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/cross-spawn/-/cross-spawn-6.0.6.tgz} engines: {node: '>=4.8'} cross-spawn@7.0.6: @@ -13444,7 +13450,7 @@ packages: engines: {node: '>=6'} execa@5.1.1: - resolution: {integrity: sha1-+ArZy/Qpj3vR1MlVXCHpN0HEEd0=, tarball: https://ms-feed-17.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/execa/-/execa-5.1.1.tgz} + resolution: {integrity: sha1-+ArZy/Qpj3vR1MlVXCHpN0HEEd0=, tarball: https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/execa/-/execa-5.1.1.tgz} engines: {node: '>=10'} exit-x@0.2.2: @@ -13914,15 +13920,15 @@ packages: engines: {node: '>= 0.4'} get-stream@4.1.0: - resolution: {integrity: sha1-wbJVV189wh1Zv8ec09K0axw6VLU=, tarball: https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/get-stream/-/get-stream-4.1.0.tgz} + resolution: {integrity: sha1-wbJVV189wh1Zv8ec09K0axw6VLU=, tarball: https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/get-stream/-/get-stream-4.1.0.tgz} engines: {node: '>=6'} get-stream@5.2.0: - resolution: {integrity: sha1-SWaheV7lrOZecGxLe+txJX1uItM=, tarball: https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/get-stream/-/get-stream-5.2.0.tgz} + resolution: {integrity: sha1-SWaheV7lrOZecGxLe+txJX1uItM=, tarball: https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/get-stream/-/get-stream-5.2.0.tgz} engines: {node: '>=8'} get-stream@6.0.1: - resolution: {integrity: sha1-omLY7vZ6ztV8KFKtYWdSakPL97c=, tarball: https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/get-stream/-/get-stream-6.0.1.tgz} + resolution: {integrity: sha1-omLY7vZ6ztV8KFKtYWdSakPL97c=, tarball: https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/get-stream/-/get-stream-6.0.1.tgz} engines: {node: '>=10'} get-symbol-description@1.1.0: @@ -14292,7 +14298,7 @@ packages: engines: {node: '>= 14'} human-signals@2.1.0: - resolution: {integrity: sha1-3JH8ukLk0G5Kuu0zs+ejwC9RTqA=, tarball: https://ms-feed-17.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/human-signals/-/human-signals-2.1.0.tgz} + resolution: {integrity: sha1-3JH8ukLk0G5Kuu0zs+ejwC9RTqA=, tarball: https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/human-signals/-/human-signals-2.1.0.tgz} engines: {node: '>=10.17.0'} humanize-ms@1.2.1: @@ -14689,11 +14695,11 @@ packages: engines: {node: '>= 0.4'} is-stream@1.1.0: - resolution: {integrity: sha1-EtSj3U5o4Lec6428hBc66A2RykQ=, tarball: https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/is-stream/-/is-stream-1.1.0.tgz} + resolution: {integrity: sha1-EtSj3U5o4Lec6428hBc66A2RykQ=, tarball: https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/is-stream/-/is-stream-1.1.0.tgz} engines: {node: '>=0.10.0'} is-stream@2.0.1: - resolution: {integrity: sha1-+sHj1TuXrVqdCunO8jifWBClwHc=, tarball: https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/is-stream/-/is-stream-2.0.1.tgz} + resolution: {integrity: sha1-+sHj1TuXrVqdCunO8jifWBClwHc=, tarball: https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/is-stream/-/is-stream-2.0.1.tgz} engines: {node: '>=8'} is-string@1.1.1: @@ -14766,7 +14772,7 @@ packages: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} isexe@2.0.0: - resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=, tarball: https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/isexe/-/isexe-2.0.0.tgz} + resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=, tarball: https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/isexe/-/isexe-2.0.0.tgz} isobject@2.1.0: resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} @@ -15662,7 +15668,7 @@ packages: hasBin: true mimic-fn@2.1.0: - resolution: {integrity: sha1-ftLCzMyvhNP/y3pptXcR/CCDQBs=, tarball: https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/mimic-fn/-/mimic-fn-2.1.0.tgz} + resolution: {integrity: sha1-ftLCzMyvhNP/y3pptXcR/CCDQBs=, tarball: https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/mimic-fn/-/mimic-fn-2.1.0.tgz} engines: {node: '>=6'} mimic-fn@3.1.0: @@ -15969,7 +15975,7 @@ packages: engines: {node: '>=4'} npm-run-path@4.0.1: - resolution: {integrity: sha1-t+zR5e1T2o43pV4cImnguX7XSOo=, tarball: https://ms-feed-17.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/npm-run-path/-/npm-run-path-4.0.1.tgz} + resolution: {integrity: sha1-t+zR5e1T2o43pV4cImnguX7XSOo=, tarball: https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/npm-run-path/-/npm-run-path-4.0.1.tgz} engines: {node: '>=8'} npmlog@4.1.2: @@ -16080,7 +16086,7 @@ packages: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} onetime@5.1.2: - resolution: {integrity: sha1-0Oluu1awdHbfHdnEgG5SN5hcpF4=, tarball: https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/onetime/-/onetime-5.1.2.tgz} + resolution: {integrity: sha1-0Oluu1awdHbfHdnEgG5SN5hcpF4=, tarball: https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/onetime/-/onetime-5.1.2.tgz} engines: {node: '>=6'} open@10.2.0: @@ -16299,7 +16305,7 @@ packages: engines: {node: '>=0.10.0'} path-key@2.0.1: - resolution: {integrity: sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=, tarball: https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/path-key/-/path-key-2.0.1.tgz} + resolution: {integrity: sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=, tarball: https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/path-key/-/path-key-2.0.1.tgz} engines: {node: '>=4'} path-key@3.1.1: @@ -17765,10 +17771,10 @@ packages: engines: {node: '>= 0.4'} signal-exit@3.0.7: - resolution: {integrity: sha1-qaF2f4r4QVURTqq9c/mSc8j1mtk=, tarball: https://ms-feed-17.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/signal-exit/-/signal-exit-3.0.7.tgz} + resolution: {integrity: sha1-qaF2f4r4QVURTqq9c/mSc8j1mtk=, tarball: https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/signal-exit/-/signal-exit-3.0.7.tgz} signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + resolution: {integrity: sha1-lSGIwcvVRgcOLdIND0HArgUwywQ=, tarball: https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/signal-exit/-/signal-exit-4.1.0.tgz} engines: {node: '>=14'} simple-concat@1.0.1: @@ -24857,7 +24863,7 @@ snapshots: transitivePeerDependencies: - '@types/node' - '@rushstack/heft-jest-plugin@2.0.15(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/jest@30.0.0)(@types/node@20.17.19)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.0))(jest-environment-jsdom@30.3.0)(jest-environment-node@30.3.0)': + '@rushstack/heft-jest-plugin@2.0.15(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/jest@30.0.0)(@types/node@20.17.19)(esbuild-register@3.6.0(esbuild@0.28.0))(jest-environment-jsdom@30.3.0)(jest-environment-node@30.3.0)': dependencies: '@jest/core': 30.3.0(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.0)) '@jest/reporters': 30.3.0 @@ -24890,13 +24896,13 @@ snapshots: transitivePeerDependencies: - '@types/node' - '@rushstack/heft-node-rig@2.11.48(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/node@20.17.19)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.0))(jest-environment-jsdom@30.3.0)': + '@rushstack/heft-node-rig@2.11.48(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/node@20.17.19)(esbuild-register@3.6.0(esbuild@0.28.0))(jest-environment-jsdom@30.3.0)': dependencies: '@microsoft/api-extractor': 7.59.0(@types/node@20.17.19) '@rushstack/eslint-config': 4.6.5(eslint@9.37.0)(typescript@5.8.2) '@rushstack/heft': 1.2.25(@types/node@20.17.19) '@rushstack/heft-api-extractor-plugin': 1.3.25(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/node@20.17.19) - '@rushstack/heft-jest-plugin': 2.0.15(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/jest@30.0.0)(@types/node@20.17.19)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.0))(jest-environment-jsdom@30.3.0)(jest-environment-node@30.3.0) + '@rushstack/heft-jest-plugin': 2.0.15(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/jest@30.0.0)(@types/node@20.17.19)(esbuild-register@3.6.0(esbuild@0.28.0))(jest-environment-jsdom@30.3.0)(jest-environment-node@30.3.0) '@rushstack/heft-lint-plugin': 1.2.25(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/node@20.17.19) '@rushstack/heft-typescript-plugin': 1.3.20(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/node@20.17.19) '@types/jest': 30.0.0 diff --git a/common/config/subspaces/default/repo-state.json b/common/config/subspaces/default/repo-state.json index 298e1a8a29e..612c6c457f7 100644 --- a/common/config/subspaces/default/repo-state.json +++ b/common/config/subspaces/default/repo-state.json @@ -1,5 +1,5 @@ // DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush. { - "pnpmShrinkwrapHash": "f9acc34af9572dd5baa4246a14a8b0482730a5be", + "pnpmShrinkwrapHash": "a6e9851a3eab8b986764f21034c02cd77e61c4c7", "preferredVersionsHash": "029c99bd6e65c5e1f25e2848340509811ff9753c" } From fa4b86031c3be6a1317b69d2aa03bad4570fd8ba Mon Sep 17 00:00:00 2001 From: Ian Clanton-Thuon Date: Mon, 14 Sep 2026 12:57:06 -0400 Subject: [PATCH 09/16] fixup! Clean up types. --- eslint/eslint-plugin/src/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/eslint/eslint-plugin/src/index.ts b/eslint/eslint-plugin/src/index.ts index 0e81fb1963c..7787b59a5d0 100644 --- a/eslint/eslint-plugin/src/index.ts +++ b/eslint/eslint-plugin/src/index.ts @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. +import type { ESLint } from 'eslint'; import type { TSESLint } from '@typescript-eslint/utils'; import { hoistJestMock } from './hoist-jest-mock'; @@ -60,4 +61,4 @@ const plugin: IPlugin = { // structurally assignable to ESLint's `RuleDefinition`. Widen through `object` (rather than `unknown`) to // present the plugin as an `ESLint.Plugin` so that consumers (such as flat-config `plugins` maps) can // reference it without a cast of their own. -export = plugin as unknown as IPlugin; +export = plugin as unknown as ESLint.Plugin; From 7f7f6648a7d61543b98d87affdb92508b568628e Mon Sep 17 00:00:00 2001 From: Ian Clanton-Thuon Date: Mon, 14 Sep 2026 14:10:12 -0400 Subject: [PATCH 10/16] Rush change. --- .../eslint-config-typescript_2026-09-13-04-30-00.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/changes/@rushstack/eslint-config/eslint-config-typescript_2026-09-13-04-30-00.json b/common/changes/@rushstack/eslint-config/eslint-config-typescript_2026-09-13-04-30-00.json index ae50701f89d..3bd5463b84e 100644 --- a/common/changes/@rushstack/eslint-config/eslint-config-typescript_2026-09-13-04-30-00.json +++ b/common/changes/@rushstack/eslint-config/eslint-config-typescript_2026-09-13-04-30-00.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@rushstack/eslint-config", - "comment": "Author the package in TypeScript (built to CommonJS via Heft). The existing subpath entry points are preserved via a package.json \"exports\" map and the compiled configuration is runtime-identical to the previous JavaScript.", + "comment": "Author the package in TypeScript (built to CommonJS via Heft). The existing subpath entry points are preserved via a `package.json` `\"exports\"` map and the compiled configuration is runtime-identical to the previous JavaScript.", "type": "patch" } ] From d5c92252e8edbbdd424f4d0ddafc30a2baa8a3b5 Mon Sep 17 00:00:00 2001 From: Ian Clanton-Thuon Date: Mon, 14 Sep 2026 14:25:08 -0400 Subject: [PATCH 11/16] [eslint-config] Document the "module": "Node16" override in tsconfig.json Explain that the override is needed so that TypeScript uses Node16 module resolution (which honors dependencies' "exports" maps) instead of the legacy "node" resolution implied by the rig's "module": "commonjs", while still emitting CommonJS output. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- eslint/eslint-config/tsconfig.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/eslint/eslint-config/tsconfig.json b/eslint/eslint-config/tsconfig.json index e98df1ad324..438ea9bfddf 100644 --- a/eslint/eslint-config/tsconfig.json +++ b/eslint/eslint-config/tsconfig.json @@ -2,6 +2,12 @@ "extends": "./node_modules/decoupled-local-node-rig/profiles/default/tsconfig-base.json", "compilerOptions": { + // The rig's base config uses "module": "commonjs", which implies the legacy "node" module resolution. + // That resolution mode ignores the "exports" maps in dependencies' package.json files, so imports that are + // only reachable through an "exports" subpath (for example `eslint/config`, which provides `globalIgnores`, + // and various `@typescript-eslint/*` entry points) fail to resolve. "Node16" switches to Node16 module + // resolution, which honors "exports" maps. It still emits CommonJS here because this package's package.json + // has no "type": "module", so the require()-compatible output is preserved. "module": "Node16" } } From 53209c0582847ed0af1330f7267228b9b0e97624 Mon Sep 17 00:00:00 2001 From: Ian Clanton-Thuon Date: Mon, 14 Sep 2026 14:25:44 -0400 Subject: [PATCH 12/16] Fix an issue with a missing eslint peer dependency --- common/config/rush/pnpm-config.json | 11 +++ .../build-tests-subspace/pnpm-lock.yaml | 22 ++++-- .../build-tests-subspace/repo-state.json | 2 +- .../config/subspaces/default/pnpm-lock.yaml | 77 ++++++++++++------- .../config/subspaces/default/repo-state.json | 2 +- 5 files changed, 80 insertions(+), 34 deletions(-) diff --git a/common/config/rush/pnpm-config.json b/common/config/rush/pnpm-config.json index 95be7286441..80adb237ddf 100644 --- a/common/config/rush/pnpm-config.json +++ b/common/config/rush/pnpm-config.json @@ -476,6 +476,17 @@ } }, + "eslint-plugin-tsdoc": { + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + } + }, + "peerDependencies": { + "@types/eslint": "*" + } + }, + "query-ast": { "dependencies": { "lodash": "~4.17.15" diff --git a/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml b/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml index 928ffa7350d..ab8ba01d526 100644 --- a/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml +++ b/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml @@ -11,7 +11,7 @@ overrides: loader-utils@^2.0.0: 2.0.4 fast-xml-parser@^5.3.3: 5.3.5 -packageExtensionsChecksum: sha256-8fXYR9X9qRA57SZJJSADz6C9KMP6QQYYut4DHyehah0= +packageExtensionsChecksum: sha256-X4+Xs9WDTMcR0G6ffHhXVwXZEtOoa0Fy3JeVU0aTaUM= pnpmfileChecksum: sha256-E1T7OJ3DLTjpDqf4RdJzK9VDtAxgm4gDEQCLYdHD8nI= @@ -114,7 +114,7 @@ importers: devDependencies: '@rushstack/eslint-config': specifier: file:../../eslint/eslint-config - version: file:../../../eslint/eslint-config(eslint@9.25.1)(typescript@4.9.5) + version: file:../../../eslint/eslint-config(@types/eslint@9.6.1)(eslint@9.25.1)(typescript@4.9.5) '@rushstack/heft': specifier: file:../../apps/heft version: file:../../../apps/heft(@types/node@20.17.19) @@ -1970,6 +1970,11 @@ packages: eslint-plugin-tsdoc@0.5.2: resolution: {integrity: sha512-BlvqjWZdBJDIPO/YU3zcPCF23CvjYT3gyu63yo6b609NNV3D1b6zceAREy2xnweuBoDpZcLNuPyAUq9cvx6bbQ==} + peerDependencies: + '@types/eslint': '*' + peerDependenciesMeta: + '@types/eslint': + optional: true eslint-scope@5.1.1: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} @@ -4707,7 +4712,7 @@ snapshots: transitivePeerDependencies: - '@types/node' - '@rushstack/eslint-config@file:../../../eslint/eslint-config(eslint@9.25.1)(typescript@4.9.5)': + '@rushstack/eslint-config@file:../../../eslint/eslint-config(@types/eslint@9.6.1)(eslint@9.25.1)(typescript@4.9.5)': dependencies: '@rushstack/eslint-patch': file:../../../eslint/eslint-patch '@rushstack/eslint-plugin': file:../../../eslint/eslint-plugin(eslint@9.25.1)(typescript@4.9.5) @@ -4720,9 +4725,10 @@ snapshots: eslint: 9.25.1 eslint-plugin-promise: 7.2.1(eslint@9.25.1) eslint-plugin-react: 7.37.5(eslint@9.25.1) - eslint-plugin-tsdoc: 0.5.2(eslint@9.25.1)(typescript@4.9.5) + eslint-plugin-tsdoc: 0.5.2(@types/eslint@9.6.1)(eslint@9.25.1)(typescript@4.9.5) typescript: 4.9.5 transitivePeerDependencies: + - '@types/eslint' - supports-color '@rushstack/eslint-config@file:../../../eslint/eslint-config(eslint@9.37.0)(typescript@5.8.3)': @@ -4741,6 +4747,7 @@ snapshots: eslint-plugin-tsdoc: 0.5.2(eslint@9.37.0)(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: + - '@types/eslint' - supports-color '@rushstack/eslint-patch@file:../../../eslint/eslint-patch': {} @@ -4862,6 +4869,7 @@ snapshots: jest-environment-node: 30.3.0 typescript: 5.8.3 transitivePeerDependencies: + - '@types/eslint' - '@types/node' - babel-plugin-macros - esbuild-register @@ -6208,11 +6216,13 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 - eslint-plugin-tsdoc@0.5.2(eslint@9.25.1)(typescript@4.9.5): + eslint-plugin-tsdoc@0.5.2(@types/eslint@9.6.1)(eslint@9.25.1)(typescript@4.9.5): dependencies: '@microsoft/tsdoc': 0.16.0 '@microsoft/tsdoc-config': 0.18.1 '@typescript-eslint/utils': 8.56.1(eslint@9.25.1)(typescript@4.9.5) + optionalDependencies: + '@types/eslint': 9.6.1 transitivePeerDependencies: - eslint - supports-color @@ -7233,6 +7243,7 @@ snapshots: eslint-plugin-react-hooks: 5.2.0(eslint@9.37.0) typescript: 5.8.3 transitivePeerDependencies: + - '@types/eslint' - supports-color local-node-rig@file:../../../rigs/local-node-rig: @@ -7248,6 +7259,7 @@ snapshots: local-eslint-config: file:../../../eslint/local-eslint-config(eslint@9.37.0)(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: + - '@types/eslint' - babel-plugin-macros - esbuild-register - jest-environment-jsdom diff --git a/common/config/subspaces/build-tests-subspace/repo-state.json b/common/config/subspaces/build-tests-subspace/repo-state.json index 6e6e59dee0b..ac48106a5d6 100644 --- a/common/config/subspaces/build-tests-subspace/repo-state.json +++ b/common/config/subspaces/build-tests-subspace/repo-state.json @@ -1,6 +1,6 @@ // DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush. { - "pnpmShrinkwrapHash": "50a1f3c8d2270f840d49426b54c028e26de05189", + "pnpmShrinkwrapHash": "3e33ae7aa8eb62c26699395f42638456c7713bd4", "preferredVersionsHash": "550b4cee0bef4e97db6c6aad726df5149d20e7d9", "packageJsonInjectedDependenciesHash": "d7c7e7ed81eabefe053347ab6e27d121c3d0c2db" } diff --git a/common/config/subspaces/default/pnpm-lock.yaml b/common/config/subspaces/default/pnpm-lock.yaml index d13faefc471..3f9f262089d 100644 --- a/common/config/subspaces/default/pnpm-lock.yaml +++ b/common/config/subspaces/default/pnpm-lock.yaml @@ -11,7 +11,7 @@ overrides: loader-utils@^2.0.0: 2.0.4 fast-xml-parser@^5.3.3: 5.3.5 -packageExtensionsChecksum: sha256-8fXYR9X9qRA57SZJJSADz6C9KMP6QQYYut4DHyehah0= +packageExtensionsChecksum: sha256-X4+Xs9WDTMcR0G6ffHhXVwXZEtOoa0Fy3JeVU0aTaUM= pnpmfileChecksum: sha256-E1T7OJ3DLTjpDqf4RdJzK9VDtAxgm4gDEQCLYdHD8nI= @@ -1437,7 +1437,7 @@ importers: devDependencies: '@rushstack/eslint-config': specifier: 3.7.1 - version: 3.7.1(eslint@7.11.0)(typescript@5.8.2) + version: 3.7.1(@types/eslint@9.6.1)(eslint@7.11.0)(typescript@5.8.2) '@rushstack/heft': specifier: workspace:* version: link:../../apps/heft @@ -1461,7 +1461,7 @@ importers: devDependencies: '@rushstack/eslint-config': specifier: 3.7.1 - version: 3.7.1(eslint@7.7.0)(typescript@5.8.2) + version: 3.7.1(@types/eslint@9.6.1)(eslint@7.7.0)(typescript@5.8.2) '@rushstack/heft': specifier: workspace:* version: link:../../apps/heft @@ -1485,7 +1485,7 @@ importers: devDependencies: '@rushstack/eslint-config': specifier: 3.7.1 - version: 3.7.1(eslint@7.30.0)(typescript@5.8.2) + version: 3.7.1(@types/eslint@9.6.1)(eslint@7.30.0)(typescript@5.8.2) '@rushstack/heft': specifier: workspace:* version: link:../../apps/heft @@ -1614,7 +1614,7 @@ importers: version: link:../../eslint/eslint-bulk '@rushstack/eslint-config': specifier: 3.7.1 - version: 3.7.1(eslint@8.57.1)(typescript@5.8.2) + version: 3.7.1(@types/eslint@9.6.1)(eslint@8.57.1)(typescript@5.8.2) '@rushstack/eslint-patch': specifier: workspace:* version: link:../../eslint/eslint-patch @@ -2360,7 +2360,7 @@ importers: version: link:../../apps/api-extractor '@rushstack/eslint-config': specifier: 4.6.5 - version: 4.6.5(eslint@8.57.1)(typescript@4.9.5) + version: 4.6.5(@types/eslint@9.6.1)(eslint@8.57.1)(typescript@4.9.5) '@rushstack/eslint-patch': specifier: workspace:* version: link:../../eslint/eslint-patch @@ -2988,7 +2988,7 @@ importers: version: 7.37.5(eslint@9.37.0) eslint-plugin-tsdoc: specifier: ~0.5.1 - version: 0.5.2(eslint@9.37.0)(typescript@5.8.2) + version: 0.5.2(@types/eslint@9.6.1)(eslint@9.37.0)(typescript@5.8.2) devDependencies: '@rushstack/heft': specifier: 1.2.25 @@ -4737,7 +4737,7 @@ importers: version: 7.59.0(@types/node@20.17.19) '@rushstack/eslint-config': specifier: 4.6.5 - version: 4.6.5(eslint@9.37.0)(typescript@5.8.2) + version: 4.6.5(@types/eslint@9.6.1)(eslint@9.37.0)(typescript@5.8.2) '@rushstack/eslint-patch': specifier: 1.16.1 version: 1.16.1 @@ -4749,7 +4749,7 @@ importers: version: 1.2.25(@types/node@20.17.19) '@rushstack/heft-node-rig': specifier: 2.11.48 - version: 2.11.48(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/node@20.17.19)(esbuild-register@3.6.0(esbuild@0.28.0))(jest-environment-jsdom@30.3.0) + version: 2.11.48(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/eslint@9.6.1)(@types/node@20.17.19)(esbuild-register@3.6.0(esbuild@0.28.0))(jest-environment-jsdom@30.3.0) '@types/jest': specifier: 30.0.0 version: 30.0.0 @@ -13266,9 +13266,19 @@ packages: eslint-plugin-tsdoc@0.3.0: resolution: {integrity: sha512-0MuFdBrrJVBjT/gyhkP2BqpD0np1NxNLfQ38xXDlSs/KVVpKI2A6vN7jx2Rve/CyUsvOsMGwp9KKrinv7q9g3A==} + peerDependencies: + '@types/eslint': '*' + peerDependenciesMeta: + '@types/eslint': + optional: true eslint-plugin-tsdoc@0.5.2: resolution: {integrity: sha512-BlvqjWZdBJDIPO/YU3zcPCF23CvjYT3gyu63yo6b609NNV3D1b6zceAREy2xnweuBoDpZcLNuPyAUq9cvx6bbQ==} + peerDependencies: + '@types/eslint': '*' + peerDependenciesMeta: + '@types/eslint': + optional: true eslint-scope@4.0.3: resolution: {integrity: sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==} @@ -15616,7 +15626,7 @@ packages: engines: {node: '>=18'} merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + resolution: {integrity: sha1-UoI2KaFN0AyXcPtq1H3GMQ8sH2A=, tarball: https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/merge-stream/-/merge-stream-2.0.0.tgz} merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} @@ -24563,7 +24573,7 @@ snapshots: '@rtsao/scc@1.1.0': {} - '@rushstack/eslint-config@3.7.1(eslint@7.11.0)(typescript@5.8.2)': + '@rushstack/eslint-config@3.7.1(@types/eslint@9.6.1)(eslint@7.11.0)(typescript@5.8.2)': dependencies: '@rushstack/eslint-patch': 1.10.4 '@rushstack/eslint-plugin': 0.15.2(eslint@7.11.0)(typescript@5.8.2) @@ -24576,12 +24586,13 @@ snapshots: eslint: 7.11.0 eslint-plugin-promise: 6.1.1(eslint@7.11.0) eslint-plugin-react: 7.33.2(eslint@7.11.0) - eslint-plugin-tsdoc: 0.3.0 + eslint-plugin-tsdoc: 0.3.0(@types/eslint@9.6.1) typescript: 5.8.2 transitivePeerDependencies: + - '@types/eslint' - supports-color - '@rushstack/eslint-config@3.7.1(eslint@7.30.0)(typescript@5.8.2)': + '@rushstack/eslint-config@3.7.1(@types/eslint@9.6.1)(eslint@7.30.0)(typescript@5.8.2)': dependencies: '@rushstack/eslint-patch': 1.10.4 '@rushstack/eslint-plugin': 0.15.2(eslint@7.30.0)(typescript@5.8.2) @@ -24594,12 +24605,13 @@ snapshots: eslint: 7.30.0 eslint-plugin-promise: 6.1.1(eslint@7.30.0) eslint-plugin-react: 7.33.2(eslint@7.30.0) - eslint-plugin-tsdoc: 0.3.0 + eslint-plugin-tsdoc: 0.3.0(@types/eslint@9.6.1) typescript: 5.8.2 transitivePeerDependencies: + - '@types/eslint' - supports-color - '@rushstack/eslint-config@3.7.1(eslint@7.7.0)(typescript@5.8.2)': + '@rushstack/eslint-config@3.7.1(@types/eslint@9.6.1)(eslint@7.7.0)(typescript@5.8.2)': dependencies: '@rushstack/eslint-patch': 1.10.4 '@rushstack/eslint-plugin': 0.15.2(eslint@7.7.0)(typescript@5.8.2) @@ -24612,12 +24624,13 @@ snapshots: eslint: 7.7.0 eslint-plugin-promise: 6.1.1(eslint@7.7.0) eslint-plugin-react: 7.33.2(eslint@7.7.0) - eslint-plugin-tsdoc: 0.3.0 + eslint-plugin-tsdoc: 0.3.0(@types/eslint@9.6.1) typescript: 5.8.2 transitivePeerDependencies: + - '@types/eslint' - supports-color - '@rushstack/eslint-config@3.7.1(eslint@8.57.1)(typescript@5.8.2)': + '@rushstack/eslint-config@3.7.1(@types/eslint@9.6.1)(eslint@8.57.1)(typescript@5.8.2)': dependencies: '@rushstack/eslint-patch': 1.10.4 '@rushstack/eslint-plugin': 0.15.2(eslint@8.57.1)(typescript@5.8.2) @@ -24630,12 +24643,13 @@ snapshots: eslint: 8.57.1 eslint-plugin-promise: 6.1.1(eslint@8.57.1) eslint-plugin-react: 7.33.2(eslint@8.57.1) - eslint-plugin-tsdoc: 0.3.0 + eslint-plugin-tsdoc: 0.3.0(@types/eslint@9.6.1) typescript: 5.8.2 transitivePeerDependencies: + - '@types/eslint' - supports-color - '@rushstack/eslint-config@4.6.5(eslint@8.57.1)(typescript@4.9.5)': + '@rushstack/eslint-config@4.6.5(@types/eslint@9.6.1)(eslint@8.57.1)(typescript@4.9.5)': dependencies: '@rushstack/eslint-patch': 1.16.1 '@rushstack/eslint-plugin': 0.23.3(eslint@8.57.1)(typescript@4.9.5) @@ -24648,12 +24662,13 @@ snapshots: eslint: 8.57.1 eslint-plugin-promise: 7.2.1(eslint@8.57.1) eslint-plugin-react: 7.37.5(eslint@8.57.1) - eslint-plugin-tsdoc: 0.5.2(eslint@8.57.1)(typescript@4.9.5) + eslint-plugin-tsdoc: 0.5.2(@types/eslint@9.6.1)(eslint@8.57.1)(typescript@4.9.5) typescript: 4.9.5 transitivePeerDependencies: + - '@types/eslint' - supports-color - '@rushstack/eslint-config@4.6.5(eslint@9.37.0)(typescript@5.8.2)': + '@rushstack/eslint-config@4.6.5(@types/eslint@9.6.1)(eslint@9.37.0)(typescript@5.8.2)': dependencies: '@rushstack/eslint-patch': 1.16.1 '@rushstack/eslint-plugin': 0.23.3(eslint@9.37.0)(typescript@5.8.2) @@ -24666,9 +24681,10 @@ snapshots: eslint: 9.37.0 eslint-plugin-promise: 7.2.1(eslint@9.37.0) eslint-plugin-react: 7.37.5(eslint@9.37.0) - eslint-plugin-tsdoc: 0.5.2(eslint@9.37.0)(typescript@5.8.2) + eslint-plugin-tsdoc: 0.5.2(@types/eslint@9.6.1)(eslint@9.37.0)(typescript@5.8.2) typescript: 5.8.2 transitivePeerDependencies: + - '@types/eslint' - supports-color '@rushstack/eslint-patch@1.10.4': {} @@ -24896,10 +24912,10 @@ snapshots: transitivePeerDependencies: - '@types/node' - '@rushstack/heft-node-rig@2.11.48(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/node@20.17.19)(esbuild-register@3.6.0(esbuild@0.28.0))(jest-environment-jsdom@30.3.0)': + '@rushstack/heft-node-rig@2.11.48(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/eslint@9.6.1)(@types/node@20.17.19)(esbuild-register@3.6.0(esbuild@0.28.0))(jest-environment-jsdom@30.3.0)': dependencies: '@microsoft/api-extractor': 7.59.0(@types/node@20.17.19) - '@rushstack/eslint-config': 4.6.5(eslint@9.37.0)(typescript@5.8.2) + '@rushstack/eslint-config': 4.6.5(@types/eslint@9.6.1)(eslint@9.37.0)(typescript@5.8.2) '@rushstack/heft': 1.2.25(@types/node@20.17.19) '@rushstack/heft-api-extractor-plugin': 1.3.25(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/node@20.17.19) '@rushstack/heft-jest-plugin': 2.0.15(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/jest@30.0.0)(@types/node@20.17.19)(esbuild-register@3.6.0(esbuild@0.28.0))(jest-environment-jsdom@30.3.0)(jest-environment-node@30.3.0) @@ -24910,6 +24926,7 @@ snapshots: jest-environment-node: 30.3.0 typescript: 5.8.2 transitivePeerDependencies: + - '@types/eslint' - '@types/node' - babel-plugin-macros - esbuild-register @@ -30805,26 +30822,32 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 - eslint-plugin-tsdoc@0.3.0: + eslint-plugin-tsdoc@0.3.0(@types/eslint@9.6.1): dependencies: '@microsoft/tsdoc': 0.15.0 '@microsoft/tsdoc-config': 0.17.0 + optionalDependencies: + '@types/eslint': 9.6.1 - eslint-plugin-tsdoc@0.5.2(eslint@8.57.1)(typescript@4.9.5): + eslint-plugin-tsdoc@0.5.2(@types/eslint@9.6.1)(eslint@8.57.1)(typescript@4.9.5): dependencies: '@microsoft/tsdoc': 0.16.0 '@microsoft/tsdoc-config': 0.18.1 '@typescript-eslint/utils': 8.56.1(eslint@8.57.1)(typescript@4.9.5) + optionalDependencies: + '@types/eslint': 9.6.1 transitivePeerDependencies: - eslint - supports-color - typescript - eslint-plugin-tsdoc@0.5.2(eslint@9.37.0)(typescript@5.8.2): + eslint-plugin-tsdoc@0.5.2(@types/eslint@9.6.1)(eslint@9.37.0)(typescript@5.8.2): dependencies: '@microsoft/tsdoc': 0.16.0 '@microsoft/tsdoc-config': 0.18.1 '@typescript-eslint/utils': 8.56.1(eslint@9.37.0)(typescript@5.8.2) + optionalDependencies: + '@types/eslint': 9.6.1 transitivePeerDependencies: - eslint - supports-color diff --git a/common/config/subspaces/default/repo-state.json b/common/config/subspaces/default/repo-state.json index 612c6c457f7..83a2197fee6 100644 --- a/common/config/subspaces/default/repo-state.json +++ b/common/config/subspaces/default/repo-state.json @@ -1,5 +1,5 @@ // DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush. { - "pnpmShrinkwrapHash": "a6e9851a3eab8b986764f21034c02cd77e61c4c7", + "pnpmShrinkwrapHash": "5b3efbbf0dd84ee956069134cd298660bcefa479", "preferredVersionsHash": "029c99bd6e65c5e1f25e2848340509811ff9753c" } From 6b13230e375fac8f0b89b70873e106ec4388c8f9 Mon Sep 17 00:00:00 2001 From: Ian Clanton-Thuon Date: Mon, 14 Sep 2026 14:08:53 -0400 Subject: [PATCH 13/16] Use nodenext instead. --- eslint/eslint-config/tsconfig.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eslint/eslint-config/tsconfig.json b/eslint/eslint-config/tsconfig.json index 438ea9bfddf..d10a9d761a1 100644 --- a/eslint/eslint-config/tsconfig.json +++ b/eslint/eslint-config/tsconfig.json @@ -5,9 +5,9 @@ // The rig's base config uses "module": "commonjs", which implies the legacy "node" module resolution. // That resolution mode ignores the "exports" maps in dependencies' package.json files, so imports that are // only reachable through an "exports" subpath (for example `eslint/config`, which provides `globalIgnores`, - // and various `@typescript-eslint/*` entry points) fail to resolve. "Node16" switches to Node16 module + // and various `@typescript-eslint/*` entry points) fail to resolve. "nodenext" switches to Node16 module // resolution, which honors "exports" maps. It still emits CommonJS here because this package's package.json // has no "type": "module", so the require()-compatible output is preserved. - "module": "Node16" + "module": "nodenext" } } From d293a24b988b4859ecb4135aef5b7730b370a3fe Mon Sep 17 00:00:00 2001 From: Ian Clanton-Thuon Date: Mon, 14 Sep 2026 14:41:52 -0400 Subject: [PATCH 14/16] fixup! Fix an issue with a missing eslint peer dependency --- common/config/rush/pnpm-config.json | 4 +- .../build-tests-subspace/pnpm-lock.yaml | 25 ++--- .../build-tests-subspace/repo-state.json | 2 +- .../config/subspaces/default/pnpm-lock.yaml | 96 +++++++++++-------- .../config/subspaces/default/repo-state.json | 2 +- 5 files changed, 68 insertions(+), 61 deletions(-) diff --git a/common/config/rush/pnpm-config.json b/common/config/rush/pnpm-config.json index 80adb237ddf..2c1f6a9b597 100644 --- a/common/config/rush/pnpm-config.json +++ b/common/config/rush/pnpm-config.json @@ -478,12 +478,12 @@ "eslint-plugin-tsdoc": { "peerDependenciesMeta": { - "@types/eslint": { + "eslint": { "optional": true } }, "peerDependencies": { - "@types/eslint": "*" + "eslint": "*" } }, diff --git a/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml b/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml index ab8ba01d526..1b399279287 100644 --- a/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml +++ b/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml @@ -11,7 +11,7 @@ overrides: loader-utils@^2.0.0: 2.0.4 fast-xml-parser@^5.3.3: 5.3.5 -packageExtensionsChecksum: sha256-X4+Xs9WDTMcR0G6ffHhXVwXZEtOoa0Fy3JeVU0aTaUM= +packageExtensionsChecksum: sha256-oUDDH9n0S+YRKY1TEmsTuFsNCNlmI4mpaLdAtVDhjgY= pnpmfileChecksum: sha256-E1T7OJ3DLTjpDqf4RdJzK9VDtAxgm4gDEQCLYdHD8nI= @@ -114,7 +114,7 @@ importers: devDependencies: '@rushstack/eslint-config': specifier: file:../../eslint/eslint-config - version: file:../../../eslint/eslint-config(@types/eslint@9.6.1)(eslint@9.25.1)(typescript@4.9.5) + version: file:../../../eslint/eslint-config(eslint@9.25.1)(typescript@4.9.5) '@rushstack/heft': specifier: file:../../apps/heft version: file:../../../apps/heft(@types/node@20.17.19) @@ -1971,9 +1971,9 @@ packages: eslint-plugin-tsdoc@0.5.2: resolution: {integrity: sha512-BlvqjWZdBJDIPO/YU3zcPCF23CvjYT3gyu63yo6b609NNV3D1b6zceAREy2xnweuBoDpZcLNuPyAUq9cvx6bbQ==} peerDependencies: - '@types/eslint': '*' + eslint: '*' peerDependenciesMeta: - '@types/eslint': + eslint: optional: true eslint-scope@5.1.1: @@ -4712,7 +4712,7 @@ snapshots: transitivePeerDependencies: - '@types/node' - '@rushstack/eslint-config@file:../../../eslint/eslint-config(@types/eslint@9.6.1)(eslint@9.25.1)(typescript@4.9.5)': + '@rushstack/eslint-config@file:../../../eslint/eslint-config(eslint@9.25.1)(typescript@4.9.5)': dependencies: '@rushstack/eslint-patch': file:../../../eslint/eslint-patch '@rushstack/eslint-plugin': file:../../../eslint/eslint-plugin(eslint@9.25.1)(typescript@4.9.5) @@ -4725,10 +4725,9 @@ snapshots: eslint: 9.25.1 eslint-plugin-promise: 7.2.1(eslint@9.25.1) eslint-plugin-react: 7.37.5(eslint@9.25.1) - eslint-plugin-tsdoc: 0.5.2(@types/eslint@9.6.1)(eslint@9.25.1)(typescript@4.9.5) + eslint-plugin-tsdoc: 0.5.2(eslint@9.25.1)(typescript@4.9.5) typescript: 4.9.5 transitivePeerDependencies: - - '@types/eslint' - supports-color '@rushstack/eslint-config@file:../../../eslint/eslint-config(eslint@9.37.0)(typescript@5.8.3)': @@ -4747,7 +4746,6 @@ snapshots: eslint-plugin-tsdoc: 0.5.2(eslint@9.37.0)(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: - - '@types/eslint' - supports-color '@rushstack/eslint-patch@file:../../../eslint/eslint-patch': {} @@ -4869,7 +4867,6 @@ snapshots: jest-environment-node: 30.3.0 typescript: 5.8.3 transitivePeerDependencies: - - '@types/eslint' - '@types/node' - babel-plugin-macros - esbuild-register @@ -6216,15 +6213,14 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 - eslint-plugin-tsdoc@0.5.2(@types/eslint@9.6.1)(eslint@9.25.1)(typescript@4.9.5): + eslint-plugin-tsdoc@0.5.2(eslint@9.25.1)(typescript@4.9.5): dependencies: '@microsoft/tsdoc': 0.16.0 '@microsoft/tsdoc-config': 0.18.1 '@typescript-eslint/utils': 8.56.1(eslint@9.25.1)(typescript@4.9.5) optionalDependencies: - '@types/eslint': 9.6.1 + eslint: 9.25.1 transitivePeerDependencies: - - eslint - supports-color - typescript @@ -6233,8 +6229,9 @@ snapshots: '@microsoft/tsdoc': 0.16.0 '@microsoft/tsdoc-config': 0.18.1 '@typescript-eslint/utils': 8.56.1(eslint@9.37.0)(typescript@5.8.3) + optionalDependencies: + eslint: 9.37.0 transitivePeerDependencies: - - eslint - supports-color - typescript @@ -7243,7 +7240,6 @@ snapshots: eslint-plugin-react-hooks: 5.2.0(eslint@9.37.0) typescript: 5.8.3 transitivePeerDependencies: - - '@types/eslint' - supports-color local-node-rig@file:../../../rigs/local-node-rig: @@ -7259,7 +7255,6 @@ snapshots: local-eslint-config: file:../../../eslint/local-eslint-config(eslint@9.37.0)(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: - - '@types/eslint' - babel-plugin-macros - esbuild-register - jest-environment-jsdom diff --git a/common/config/subspaces/build-tests-subspace/repo-state.json b/common/config/subspaces/build-tests-subspace/repo-state.json index ac48106a5d6..30a9f67ff2c 100644 --- a/common/config/subspaces/build-tests-subspace/repo-state.json +++ b/common/config/subspaces/build-tests-subspace/repo-state.json @@ -1,6 +1,6 @@ // DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush. { - "pnpmShrinkwrapHash": "3e33ae7aa8eb62c26699395f42638456c7713bd4", + "pnpmShrinkwrapHash": "a677ee686d23fba9fabdb7e97011613afc372b04", "preferredVersionsHash": "550b4cee0bef4e97db6c6aad726df5149d20e7d9", "packageJsonInjectedDependenciesHash": "d7c7e7ed81eabefe053347ab6e27d121c3d0c2db" } diff --git a/common/config/subspaces/default/pnpm-lock.yaml b/common/config/subspaces/default/pnpm-lock.yaml index 3f9f262089d..90ba1a908ca 100644 --- a/common/config/subspaces/default/pnpm-lock.yaml +++ b/common/config/subspaces/default/pnpm-lock.yaml @@ -11,7 +11,7 @@ overrides: loader-utils@^2.0.0: 2.0.4 fast-xml-parser@^5.3.3: 5.3.5 -packageExtensionsChecksum: sha256-X4+Xs9WDTMcR0G6ffHhXVwXZEtOoa0Fy3JeVU0aTaUM= +packageExtensionsChecksum: sha256-oUDDH9n0S+YRKY1TEmsTuFsNCNlmI4mpaLdAtVDhjgY= pnpmfileChecksum: sha256-E1T7OJ3DLTjpDqf4RdJzK9VDtAxgm4gDEQCLYdHD8nI= @@ -1437,7 +1437,7 @@ importers: devDependencies: '@rushstack/eslint-config': specifier: 3.7.1 - version: 3.7.1(@types/eslint@9.6.1)(eslint@7.11.0)(typescript@5.8.2) + version: 3.7.1(eslint@7.11.0)(typescript@5.8.2) '@rushstack/heft': specifier: workspace:* version: link:../../apps/heft @@ -1461,7 +1461,7 @@ importers: devDependencies: '@rushstack/eslint-config': specifier: 3.7.1 - version: 3.7.1(@types/eslint@9.6.1)(eslint@7.7.0)(typescript@5.8.2) + version: 3.7.1(eslint@7.7.0)(typescript@5.8.2) '@rushstack/heft': specifier: workspace:* version: link:../../apps/heft @@ -1485,7 +1485,7 @@ importers: devDependencies: '@rushstack/eslint-config': specifier: 3.7.1 - version: 3.7.1(@types/eslint@9.6.1)(eslint@7.30.0)(typescript@5.8.2) + version: 3.7.1(eslint@7.30.0)(typescript@5.8.2) '@rushstack/heft': specifier: workspace:* version: link:../../apps/heft @@ -1614,7 +1614,7 @@ importers: version: link:../../eslint/eslint-bulk '@rushstack/eslint-config': specifier: 3.7.1 - version: 3.7.1(@types/eslint@9.6.1)(eslint@8.57.1)(typescript@5.8.2) + version: 3.7.1(eslint@8.57.1)(typescript@5.8.2) '@rushstack/eslint-patch': specifier: workspace:* version: link:../../eslint/eslint-patch @@ -2360,7 +2360,7 @@ importers: version: link:../../apps/api-extractor '@rushstack/eslint-config': specifier: 4.6.5 - version: 4.6.5(@types/eslint@9.6.1)(eslint@8.57.1)(typescript@4.9.5) + version: 4.6.5(eslint@8.57.1)(typescript@4.9.5) '@rushstack/eslint-patch': specifier: workspace:* version: link:../../eslint/eslint-patch @@ -2988,7 +2988,7 @@ importers: version: 7.37.5(eslint@9.37.0) eslint-plugin-tsdoc: specifier: ~0.5.1 - version: 0.5.2(@types/eslint@9.6.1)(eslint@9.37.0)(typescript@5.8.2) + version: 0.5.2(eslint@9.37.0)(typescript@5.8.2) devDependencies: '@rushstack/heft': specifier: 1.2.25 @@ -4737,7 +4737,7 @@ importers: version: 7.59.0(@types/node@20.17.19) '@rushstack/eslint-config': specifier: 4.6.5 - version: 4.6.5(@types/eslint@9.6.1)(eslint@9.37.0)(typescript@5.8.2) + version: 4.6.5(eslint@9.37.0)(typescript@5.8.2) '@rushstack/eslint-patch': specifier: 1.16.1 version: 1.16.1 @@ -4749,7 +4749,7 @@ importers: version: 1.2.25(@types/node@20.17.19) '@rushstack/heft-node-rig': specifier: 2.11.48 - version: 2.11.48(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/eslint@9.6.1)(@types/node@20.17.19)(esbuild-register@3.6.0(esbuild@0.28.0))(jest-environment-jsdom@30.3.0) + version: 2.11.48(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/node@20.17.19)(esbuild-register@3.6.0(esbuild@0.28.0))(jest-environment-jsdom@30.3.0) '@types/jest': specifier: 30.0.0 version: 30.0.0 @@ -13267,17 +13267,17 @@ packages: eslint-plugin-tsdoc@0.3.0: resolution: {integrity: sha512-0MuFdBrrJVBjT/gyhkP2BqpD0np1NxNLfQ38xXDlSs/KVVpKI2A6vN7jx2Rve/CyUsvOsMGwp9KKrinv7q9g3A==} peerDependencies: - '@types/eslint': '*' + eslint: '*' peerDependenciesMeta: - '@types/eslint': + eslint: optional: true eslint-plugin-tsdoc@0.5.2: resolution: {integrity: sha512-BlvqjWZdBJDIPO/YU3zcPCF23CvjYT3gyu63yo6b609NNV3D1b6zceAREy2xnweuBoDpZcLNuPyAUq9cvx6bbQ==} peerDependencies: - '@types/eslint': '*' + eslint: '*' peerDependenciesMeta: - '@types/eslint': + eslint: optional: true eslint-scope@4.0.3: @@ -24573,7 +24573,7 @@ snapshots: '@rtsao/scc@1.1.0': {} - '@rushstack/eslint-config@3.7.1(@types/eslint@9.6.1)(eslint@7.11.0)(typescript@5.8.2)': + '@rushstack/eslint-config@3.7.1(eslint@7.11.0)(typescript@5.8.2)': dependencies: '@rushstack/eslint-patch': 1.10.4 '@rushstack/eslint-plugin': 0.15.2(eslint@7.11.0)(typescript@5.8.2) @@ -24586,13 +24586,12 @@ snapshots: eslint: 7.11.0 eslint-plugin-promise: 6.1.1(eslint@7.11.0) eslint-plugin-react: 7.33.2(eslint@7.11.0) - eslint-plugin-tsdoc: 0.3.0(@types/eslint@9.6.1) + eslint-plugin-tsdoc: 0.3.0(eslint@7.11.0) typescript: 5.8.2 transitivePeerDependencies: - - '@types/eslint' - supports-color - '@rushstack/eslint-config@3.7.1(@types/eslint@9.6.1)(eslint@7.30.0)(typescript@5.8.2)': + '@rushstack/eslint-config@3.7.1(eslint@7.30.0)(typescript@5.8.2)': dependencies: '@rushstack/eslint-patch': 1.10.4 '@rushstack/eslint-plugin': 0.15.2(eslint@7.30.0)(typescript@5.8.2) @@ -24605,13 +24604,12 @@ snapshots: eslint: 7.30.0 eslint-plugin-promise: 6.1.1(eslint@7.30.0) eslint-plugin-react: 7.33.2(eslint@7.30.0) - eslint-plugin-tsdoc: 0.3.0(@types/eslint@9.6.1) + eslint-plugin-tsdoc: 0.3.0(eslint@7.30.0) typescript: 5.8.2 transitivePeerDependencies: - - '@types/eslint' - supports-color - '@rushstack/eslint-config@3.7.1(@types/eslint@9.6.1)(eslint@7.7.0)(typescript@5.8.2)': + '@rushstack/eslint-config@3.7.1(eslint@7.7.0)(typescript@5.8.2)': dependencies: '@rushstack/eslint-patch': 1.10.4 '@rushstack/eslint-plugin': 0.15.2(eslint@7.7.0)(typescript@5.8.2) @@ -24624,13 +24622,12 @@ snapshots: eslint: 7.7.0 eslint-plugin-promise: 6.1.1(eslint@7.7.0) eslint-plugin-react: 7.33.2(eslint@7.7.0) - eslint-plugin-tsdoc: 0.3.0(@types/eslint@9.6.1) + eslint-plugin-tsdoc: 0.3.0(eslint@7.7.0) typescript: 5.8.2 transitivePeerDependencies: - - '@types/eslint' - supports-color - '@rushstack/eslint-config@3.7.1(@types/eslint@9.6.1)(eslint@8.57.1)(typescript@5.8.2)': + '@rushstack/eslint-config@3.7.1(eslint@8.57.1)(typescript@5.8.2)': dependencies: '@rushstack/eslint-patch': 1.10.4 '@rushstack/eslint-plugin': 0.15.2(eslint@8.57.1)(typescript@5.8.2) @@ -24643,13 +24640,12 @@ snapshots: eslint: 8.57.1 eslint-plugin-promise: 6.1.1(eslint@8.57.1) eslint-plugin-react: 7.33.2(eslint@8.57.1) - eslint-plugin-tsdoc: 0.3.0(@types/eslint@9.6.1) + eslint-plugin-tsdoc: 0.3.0(eslint@8.57.1) typescript: 5.8.2 transitivePeerDependencies: - - '@types/eslint' - supports-color - '@rushstack/eslint-config@4.6.5(@types/eslint@9.6.1)(eslint@8.57.1)(typescript@4.9.5)': + '@rushstack/eslint-config@4.6.5(eslint@8.57.1)(typescript@4.9.5)': dependencies: '@rushstack/eslint-patch': 1.16.1 '@rushstack/eslint-plugin': 0.23.3(eslint@8.57.1)(typescript@4.9.5) @@ -24662,13 +24658,12 @@ snapshots: eslint: 8.57.1 eslint-plugin-promise: 7.2.1(eslint@8.57.1) eslint-plugin-react: 7.37.5(eslint@8.57.1) - eslint-plugin-tsdoc: 0.5.2(@types/eslint@9.6.1)(eslint@8.57.1)(typescript@4.9.5) + eslint-plugin-tsdoc: 0.5.2(eslint@8.57.1)(typescript@4.9.5) typescript: 4.9.5 transitivePeerDependencies: - - '@types/eslint' - supports-color - '@rushstack/eslint-config@4.6.5(@types/eslint@9.6.1)(eslint@9.37.0)(typescript@5.8.2)': + '@rushstack/eslint-config@4.6.5(eslint@9.37.0)(typescript@5.8.2)': dependencies: '@rushstack/eslint-patch': 1.16.1 '@rushstack/eslint-plugin': 0.23.3(eslint@9.37.0)(typescript@5.8.2) @@ -24681,10 +24676,9 @@ snapshots: eslint: 9.37.0 eslint-plugin-promise: 7.2.1(eslint@9.37.0) eslint-plugin-react: 7.37.5(eslint@9.37.0) - eslint-plugin-tsdoc: 0.5.2(@types/eslint@9.6.1)(eslint@9.37.0)(typescript@5.8.2) + eslint-plugin-tsdoc: 0.5.2(eslint@9.37.0)(typescript@5.8.2) typescript: 5.8.2 transitivePeerDependencies: - - '@types/eslint' - supports-color '@rushstack/eslint-patch@1.10.4': {} @@ -24912,10 +24906,10 @@ snapshots: transitivePeerDependencies: - '@types/node' - '@rushstack/heft-node-rig@2.11.48(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/eslint@9.6.1)(@types/node@20.17.19)(esbuild-register@3.6.0(esbuild@0.28.0))(jest-environment-jsdom@30.3.0)': + '@rushstack/heft-node-rig@2.11.48(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/node@20.17.19)(esbuild-register@3.6.0(esbuild@0.28.0))(jest-environment-jsdom@30.3.0)': dependencies: '@microsoft/api-extractor': 7.59.0(@types/node@20.17.19) - '@rushstack/eslint-config': 4.6.5(@types/eslint@9.6.1)(eslint@9.37.0)(typescript@5.8.2) + '@rushstack/eslint-config': 4.6.5(eslint@9.37.0)(typescript@5.8.2) '@rushstack/heft': 1.2.25(@types/node@20.17.19) '@rushstack/heft-api-extractor-plugin': 1.3.25(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/node@20.17.19) '@rushstack/heft-jest-plugin': 2.0.15(@rushstack/heft@1.2.25(@types/node@20.17.19))(@types/jest@30.0.0)(@types/node@20.17.19)(esbuild-register@3.6.0(esbuild@0.28.0))(jest-environment-jsdom@30.3.0)(jest-environment-node@30.3.0) @@ -24926,7 +24920,6 @@ snapshots: jest-environment-node: 30.3.0 typescript: 5.8.2 transitivePeerDependencies: - - '@types/eslint' - '@types/node' - babel-plugin-macros - esbuild-register @@ -30822,34 +30815,53 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 - eslint-plugin-tsdoc@0.3.0(@types/eslint@9.6.1): + eslint-plugin-tsdoc@0.3.0(eslint@7.11.0): dependencies: '@microsoft/tsdoc': 0.15.0 '@microsoft/tsdoc-config': 0.17.0 optionalDependencies: - '@types/eslint': 9.6.1 + eslint: 7.11.0 + + eslint-plugin-tsdoc@0.3.0(eslint@7.30.0): + dependencies: + '@microsoft/tsdoc': 0.15.0 + '@microsoft/tsdoc-config': 0.17.0 + optionalDependencies: + eslint: 7.30.0 + + eslint-plugin-tsdoc@0.3.0(eslint@7.7.0): + dependencies: + '@microsoft/tsdoc': 0.15.0 + '@microsoft/tsdoc-config': 0.17.0 + optionalDependencies: + eslint: 7.7.0 + + eslint-plugin-tsdoc@0.3.0(eslint@8.57.1): + dependencies: + '@microsoft/tsdoc': 0.15.0 + '@microsoft/tsdoc-config': 0.17.0 + optionalDependencies: + eslint: 8.57.1 - eslint-plugin-tsdoc@0.5.2(@types/eslint@9.6.1)(eslint@8.57.1)(typescript@4.9.5): + eslint-plugin-tsdoc@0.5.2(eslint@8.57.1)(typescript@4.9.5): dependencies: '@microsoft/tsdoc': 0.16.0 '@microsoft/tsdoc-config': 0.18.1 '@typescript-eslint/utils': 8.56.1(eslint@8.57.1)(typescript@4.9.5) optionalDependencies: - '@types/eslint': 9.6.1 + eslint: 8.57.1 transitivePeerDependencies: - - eslint - supports-color - typescript - eslint-plugin-tsdoc@0.5.2(@types/eslint@9.6.1)(eslint@9.37.0)(typescript@5.8.2): + eslint-plugin-tsdoc@0.5.2(eslint@9.37.0)(typescript@5.8.2): dependencies: '@microsoft/tsdoc': 0.16.0 '@microsoft/tsdoc-config': 0.18.1 '@typescript-eslint/utils': 8.56.1(eslint@9.37.0)(typescript@5.8.2) optionalDependencies: - '@types/eslint': 9.6.1 + eslint: 9.37.0 transitivePeerDependencies: - - eslint - supports-color - typescript diff --git a/common/config/subspaces/default/repo-state.json b/common/config/subspaces/default/repo-state.json index 83a2197fee6..fe731d80391 100644 --- a/common/config/subspaces/default/repo-state.json +++ b/common/config/subspaces/default/repo-state.json @@ -1,5 +1,5 @@ // DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush. { - "pnpmShrinkwrapHash": "5b3efbbf0dd84ee956069134cd298660bcefa479", + "pnpmShrinkwrapHash": "231e6e537030dbc8e5f90637485903a017fc41cd", "preferredVersionsHash": "029c99bd6e65c5e1f25e2848340509811ff9753c" } From 8daeca6687bc7a1e040604bf6a752532cd4c4f47 Mon Sep 17 00:00:00 2001 From: Ian Clanton-Thuon Date: Mon, 14 Sep 2026 16:01:26 -0400 Subject: [PATCH 15/16] Rush update. --- common/config/subspaces/default/pnpm-lock.yaml | 2 +- common/config/subspaces/default/repo-state.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/config/subspaces/default/pnpm-lock.yaml b/common/config/subspaces/default/pnpm-lock.yaml index 90ba1a908ca..8c8146a1138 100644 --- a/common/config/subspaces/default/pnpm-lock.yaml +++ b/common/config/subspaces/default/pnpm-lock.yaml @@ -15626,7 +15626,7 @@ packages: engines: {node: '>=18'} merge-stream@2.0.0: - resolution: {integrity: sha1-UoI2KaFN0AyXcPtq1H3GMQ8sH2A=, tarball: https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/merge-stream/-/merge-stream-2.0.0.tgz} + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} diff --git a/common/config/subspaces/default/repo-state.json b/common/config/subspaces/default/repo-state.json index fe731d80391..44f44f58b5c 100644 --- a/common/config/subspaces/default/repo-state.json +++ b/common/config/subspaces/default/repo-state.json @@ -1,5 +1,5 @@ // DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush. { - "pnpmShrinkwrapHash": "231e6e537030dbc8e5f90637485903a017fc41cd", + "pnpmShrinkwrapHash": "02dd9ec20215ff4da03645a5df79e9dc3d83b735", "preferredVersionsHash": "029c99bd6e65c5e1f25e2848340509811ff9753c" } From 3a37a8fe6bcfadc3d8096ca8554bcb6891d4fe33 Mon Sep 17 00:00:00 2001 From: Ian Clanton-Thuon Date: Mon, 14 Sep 2026 16:33:49 -0400 Subject: [PATCH 16/16] [eslint-config] Fix the TypeScript parser import so ESLint parses TypeScript `@typescript-eslint/parser` marks its CommonJS export with `__esModule` but exposes the parser API on `module.exports` with no `default` export, so a default `import` resolved to `undefined` at runtime. ESLint then silently fell back to its built-in parser and failed to parse TypeScript ("Unexpected token ...") across every consumer of the shared config. Use a namespace import to bind the module export. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- eslint/eslint-config/src/flat/profile/_common.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/eslint/eslint-config/src/flat/profile/_common.ts b/eslint/eslint-config/src/flat/profile/_common.ts index 33996a54a5e..ae4812001b8 100644 --- a/eslint/eslint-config/src/flat/profile/_common.ts +++ b/eslint/eslint-config/src/flat/profile/_common.ts @@ -24,7 +24,11 @@ import type { ESLint, Linter } from 'eslint'; import { globalIgnores } from 'eslint/config'; import promiseEslintPlugin from 'eslint-plugin-promise'; import typescriptEslintPlugin from '@typescript-eslint/eslint-plugin'; -import typescriptEslintParser from '@typescript-eslint/parser'; +// `@typescript-eslint/parser` marks its CommonJS export with `__esModule` but exposes the parser API +// (`parseForESLint`) directly on `module.exports` with no `default` export. A default `import` would therefore +// resolve to `undefined` at runtime (ESLint would silently fall back to its built-in parser and fail to parse +// TypeScript), so use a namespace import to bind the module export itself. +import * as typescriptEslintParser from '@typescript-eslint/parser'; import rushstackEslintPlugin from '@rushstack/eslint-plugin'; import rushstackSecurityEslintPlugin from '@rushstack/eslint-plugin-security';