build: adopt moduleResolution: "bundler" (#64125)

This commit updates the TypeScript configuration across the project to use `moduleResolution: "bundler"`. This modernizes our module resolution strategy to align with current TypeScript best practices and bundler behaviors.

The following changes are included:
- Updated `tsconfig.json` files to set `moduleResolution` to `"bundler"`.
- Updated the `rules_angular` bazel dependency to a version compatible with these changes.
- Adjusted related test files and golden files to reflect the new module resolution strategy.

PR Close #64125
This commit is contained in:
Alan Agius 2025-09-29 14:32:10 +00:00 committed by kirjs
parent 377d1a0aea
commit fc643c9044
36 changed files with 70 additions and 60 deletions

View file

@ -18,7 +18,7 @@ bazel_dep(name = "yq.bzl", version = "0.2.0")
bazel_dep(name = "rules_angular")
git_override(
module_name = "rules_angular",
commit = "2c348bf59a38d044f4d389290d597d94c0699607",
commit = "399f782a14ecfd7de7c2736ec7f4f631b6a1b582",
remote = "https://github.com/devversion/rules_angular.git",
)

View file

@ -8,7 +8,7 @@
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"moduleResolution": "bundler",
"importHelpers": true,
"target": "es2022",
"module": "es2020",

View file

@ -14,7 +14,7 @@
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"moduleResolution": "bundler",
"importHelpers": true,
"target": "ES2022",
"module": "ES2022",

View file

@ -17,7 +17,7 @@
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"moduleResolution": "bundler",
"importHelpers": true,
"target": "es2020",
"module": "es2020",

View file

@ -58,7 +58,9 @@ export function getInjectorId() {
return `${injectorId++}`;
}
export function getInjectorMetadata(injector: Injector) {
export function getInjectorMetadata(
injector: Injector,
): ReturnType<NonNullable<ReturnType<typeof ngDebugClient>['ɵgetInjectorMetadata']>> {
return ngDebugClient().ɵgetInjectorMetadata?.(injector) ?? null;
}

View file

@ -10,7 +10,7 @@
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"module": "esnext",
"moduleResolution": "node",
"moduleResolution": "bundler",
"esModuleInterop": true,
"importHelpers": true,
"target": "es2020",

View file

@ -7,12 +7,20 @@
import { AbsoluteFsPath } from '@angular/compiler-cli/private/localize';
import { Element as Element_2 } from '@angular/compiler';
import { Logger } from '@angular/compiler-cli/private/localize';
import { MessageId } from '../../../../../index';
import { NodePath } from '@babel/core';
import { ParseError } from '@angular/compiler';
import { PathManipulation } from '@angular/compiler-cli/private/localize';
import { PluginObj } from '@babel/core';
import { ReadonlyFileSystem } from '@angular/compiler-cli/private/localize';
import { types } from '@babel/core';
import { ɵParsedMessage } from '../../../index';
import { ɵParsedMessage as ɵParsedMessage_2 } from '../../../../index';
import { ɵParsedTranslation } from '../../index';
import { ɵParsedTranslation as ɵParsedTranslation_2 } from '../../../../index';
import { ɵParsedTranslation as ɵParsedTranslation_3 } from '../../../../../index';
import { ɵSourceLocation } from '../../index';
import { ɵSourceMessage } from '../../../../../index';
// @public
export class ArbTranslationParser implements TranslationParser<ArbJsonObject> {
@ -26,14 +34,14 @@ export class ArbTranslationParser implements TranslationParser<ArbJsonObject> {
export class ArbTranslationSerializer implements TranslationSerializer {
constructor(sourceLocale: string, basePath: AbsoluteFsPath, fs: PathManipulation);
// (undocumented)
serialize(messages: ParsedMessage[]): string;
serialize(messages: ɵParsedMessage_2[]): string;
}
// @public
export function buildLocalizeReplacement(messageParts: TemplateStringsArray, substitutions: readonly types.Expression[]): types.Expression;
// @public
export function checkDuplicateMessages(fs: PathManipulation, messages: ParsedMessage[], duplicateMessageHandling: DiagnosticHandlingStrategy, basePath: AbsoluteFsPath): Diagnostics;
export function checkDuplicateMessages(fs: PathManipulation, messages: ɵParsedMessage[], duplicateMessageHandling: DiagnosticHandlingStrategy, basePath: AbsoluteFsPath): Diagnostics;
// @public
export type DiagnosticHandlingStrategy = 'error' | 'warning' | 'ignore';
@ -66,14 +74,14 @@ export function isGlobalIdentifier(identifier: NodePath<types.Identifier>): bool
export class LegacyMessageIdMigrationSerializer implements TranslationSerializer {
constructor(_diagnostics: Diagnostics);
// (undocumented)
serialize(messages: ParsedMessage[]): string;
serialize(messages: ɵParsedMessage_2[]): string;
}
// @public
export function makeEs2015TranslatePlugin(diagnostics: Diagnostics, translations: Record<string, ParsedTranslation>, { missingTranslation, localizeName }?: TranslatePluginOptions, fs?: PathManipulation): PluginObj;
export function makeEs2015TranslatePlugin(diagnostics: Diagnostics, translations: Record<string, ɵParsedTranslation_2>, { missingTranslation, localizeName }?: TranslatePluginOptions, fs?: PathManipulation): PluginObj;
// @public
export function makeEs5TranslatePlugin(diagnostics: Diagnostics, translations: Record<string, ParsedTranslation>, { missingTranslation, localizeName }?: TranslatePluginOptions, fs?: PathManipulation): PluginObj;
export function makeEs5TranslatePlugin(diagnostics: Diagnostics, translations: Record<string, ɵParsedTranslation_2>, { missingTranslation, localizeName }?: TranslatePluginOptions, fs?: PathManipulation): PluginObj;
// @public
export function makeLocalePlugin(locale: string, { localizeName }?: TranslatePluginOptions): PluginObj;
@ -82,7 +90,7 @@ export function makeLocalePlugin(locale: string, { localizeName }?: TranslatePlu
export class MessageExtractor {
constructor(fs: ReadonlyFileSystem, logger: Logger, { basePath, useSourceMaps, localizeName }: ExtractionOptions);
// (undocumented)
extractMessages(filename: string): ParsedMessage[];
extractMessages(filename: string): ɵParsedMessage[];
}
// @public
@ -97,23 +105,23 @@ export class SimpleJsonTranslationParser implements TranslationParser<SimpleJson
export class SimpleJsonTranslationSerializer implements TranslationSerializer {
constructor(sourceLocale: string);
// (undocumented)
serialize(messages: ParsedMessage[]): string;
serialize(messages: ɵParsedMessage_2[]): string;
}
// @public
export function translate(diagnostics: Diagnostics, translations: Record<string, ParsedTranslation>, messageParts: TemplateStringsArray, substitutions: readonly any[], missingTranslation: DiagnosticHandlingStrategy): [TemplateStringsArray, readonly any[]];
export function translate(diagnostics: Diagnostics, translations: Record<string, ɵParsedTranslation>, messageParts: TemplateStringsArray, substitutions: readonly any[], missingTranslation: DiagnosticHandlingStrategy): [TemplateStringsArray, readonly any[]];
// @public
export function unwrapExpressionsFromTemplateLiteral(quasi: NodePath<types.TemplateLiteral>, fs?: PathManipulation): [types.Expression[], (SourceLocation | undefined)[]];
export function unwrapExpressionsFromTemplateLiteral(quasi: NodePath<types.TemplateLiteral>, fs?: PathManipulation): [types.Expression[], (ɵSourceLocation | undefined)[]];
// @public
export function unwrapMessagePartsFromLocalizeCall(call: NodePath<types.CallExpression>, fs?: PathManipulation): [TemplateStringsArray, (SourceLocation | undefined)[]];
export function unwrapMessagePartsFromLocalizeCall(call: NodePath<types.CallExpression>, fs?: PathManipulation): [TemplateStringsArray, (ɵSourceLocation | undefined)[]];
// @public
export function unwrapMessagePartsFromTemplateLiteral(elements: NodePath<types.TemplateElement>[], fs?: PathManipulation): [TemplateStringsArray, (SourceLocation | undefined)[]];
export function unwrapMessagePartsFromTemplateLiteral(elements: NodePath<types.TemplateElement>[], fs?: PathManipulation): [TemplateStringsArray, (ɵSourceLocation | undefined)[]];
// @public
export function unwrapSubstitutionsFromLocalizeCall(call: NodePath<types.CallExpression>, fs?: PathManipulation): [types.Expression[], (SourceLocation | undefined)[]];
export function unwrapSubstitutionsFromLocalizeCall(call: NodePath<types.CallExpression>, fs?: PathManipulation): [types.Expression[], (ɵSourceLocation | undefined)[]];
// @public
export class Xliff1TranslationParser implements TranslationParser<XmlTranslationParserHint> {
@ -127,7 +135,7 @@ export class Xliff1TranslationParser implements TranslationParser<XmlTranslation
export class Xliff1TranslationSerializer implements TranslationSerializer {
constructor(sourceLocale: string, basePath: AbsoluteFsPath, useLegacyIds: boolean, formatOptions?: FormatOptions, fs?: PathManipulation);
// (undocumented)
serialize(messages: ParsedMessage[]): string;
serialize(messages: ɵParsedMessage_2[]): string;
}
// @public
@ -142,14 +150,14 @@ export class Xliff2TranslationParser implements TranslationParser<XmlTranslation
export class Xliff2TranslationSerializer implements TranslationSerializer {
constructor(sourceLocale: string, basePath: AbsoluteFsPath, useLegacyIds: boolean, formatOptions?: FormatOptions, fs?: PathManipulation);
// (undocumented)
serialize(messages: ParsedMessage[]): string;
serialize(messages: ɵParsedMessage_2[]): string;
}
// @public
export class XmbTranslationSerializer implements TranslationSerializer {
constructor(basePath: AbsoluteFsPath, useLegacyIds: boolean, fs?: PathManipulation);
// (undocumented)
serialize(messages: ParsedMessage[]): string;
serialize(messages: ɵParsedMessage_2[]): string;
}
// @public

View file

@ -8,7 +8,7 @@
"declaration": false,
"experimentalDecorators": true,
"module": "es2022",
"moduleResolution": "node",
"moduleResolution": "bundler",
"importHelpers": true,
"target": "es2022",
"typeRoots": ["node_modules/@types"],

View file

@ -8,7 +8,7 @@
"declaration": false,
"experimentalDecorators": true,
"module": "es2022",
"moduleResolution": "node",
"moduleResolution": "bundler",
"importHelpers": true,
"target": "es2022",
"typeRoots": ["node_modules/@types"],

View file

@ -8,7 +8,7 @@
"declaration": false,
"experimentalDecorators": true,
"module": "es2022",
"moduleResolution": "node",
"moduleResolution": "bundler",
"importHelpers": true,
"target": "es2022",
"typeRoots": ["node_modules/@types"],

View file

@ -9,7 +9,7 @@
"declaration": false,
"experimentalDecorators": true,
"module": "es2022",
"moduleResolution": "node",
"moduleResolution": "bundler",
"importHelpers": true,
"target": "es2022",
"typeRoots": ["node_modules/@types"],

View file

@ -8,7 +8,7 @@
"declaration": false,
"experimentalDecorators": true,
"module": "es2022",
"moduleResolution": "node",
"moduleResolution": "bundler",
"importHelpers": true,
"target": "es2022",
"typeRoots": ["node_modules/@types"],

View file

@ -8,7 +8,7 @@
"declaration": false,
"experimentalDecorators": true,
"module": "es2022",
"moduleResolution": "node",
"moduleResolution": "bundler",
"importHelpers": true,
"target": "es2022",
"useDefineForClassFields": false,

View file

@ -8,7 +8,7 @@
"declaration": false,
"experimentalDecorators": true,
"module": "es2022",
"moduleResolution": "node",
"moduleResolution": "bundler",
"importHelpers": true,
"target": "es2022",
"typeRoots": ["node_modules/@types"],

View file

@ -14,7 +14,7 @@
"sourceMap": true,
"declaration": false,
"experimentalDecorators": true,
"moduleResolution": "node",
"moduleResolution": "bundler",
"importHelpers": true,
"target": "es2017",
"module": "es2022",

View file

@ -5,7 +5,7 @@
},
"compilerOptions": {
"module": "es2015",
"moduleResolution": "node",
"moduleResolution": "bundler",
"strictNullChecks": true,
"target": "es2022",
"sourceMap": false,

View file

@ -14,7 +14,7 @@
"esModuleInterop": true,
"declaration": false,
"experimentalDecorators": true,
"moduleResolution": "node",
"moduleResolution": "bundler",
"importHelpers": true,
"target": "ES2022",
"module": "ES2022",

View file

@ -14,7 +14,7 @@
"esModuleInterop": true,
"declaration": false,
"experimentalDecorators": true,
"moduleResolution": "node",
"moduleResolution": "bundler",
"importHelpers": true,
"target": "ES2022",
"module": "ES2022",

View file

@ -8,7 +8,7 @@
"declaration": false,
"experimentalDecorators": true,
"module": "es2022",
"moduleResolution": "node",
"moduleResolution": "bundler",
"importHelpers": true,
"target": "es2022",
"typeRoots": ["node_modules/@types"],

View file

@ -12,7 +12,7 @@
"sourceMap": true,
"declaration": false,
"experimentalDecorators": true,
"moduleResolution": "node",
"moduleResolution": "bundler",
"importHelpers": true,
"target": "es2022",
"module": "es2022",

View file

@ -5,8 +5,8 @@
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"experimentalDecorators": true,
"module": "commonjs",
"moduleResolution": "node",
"module": "es2022",
"moduleResolution": "bundler",
"outDir": "./dist/out-tsc",
"rootDir": ".",
"target": "es2020",

View file

@ -5,8 +5,8 @@
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"experimentalDecorators": true,
"module": "commonjs",
"moduleResolution": "node",
"module": "es2022",
"moduleResolution": "bundler",
"outDir": "./dist/out-tsc",
"rootDir": ".",
"target": "ES2020",

View file

@ -37,7 +37,7 @@ export function makeProgram(
const compilerOptions = {
noLib: true,
experimentalDecorators: true,
moduleResolution: ts.ModuleResolutionKind.Node10,
moduleResolution: ts.ModuleResolutionKind.Bundler,
...options,
};
const compilerHost = new NgtscTestCompilerHost(fs, compilerOptions);

View file

@ -173,7 +173,7 @@ export function angularCoreDtsFiles(): TestFile[] {
const directory = resolveFromRunfiles('_main/packages/core/npm_package');
const dtsFiles = globSync('**/*.d.ts', {cwd: directory});
return (_angularCoreDts = dtsFiles.map((fileName) => ({
return (_angularCoreDts = ['package.json', ...dtsFiles].map((fileName) => ({
name: absoluteFrom(`/node_modules/@angular/core/${fileName}`),
contents: readFileSync(path.join(directory, fileName), 'utf8'),
})));

View file

@ -132,7 +132,7 @@ function getOptions(
target: ts.ScriptTarget.ES2015,
newLine: ts.NewLineKind.LineFeed,
module: ts.ModuleKind.ES2015,
moduleResolution: ts.ModuleResolutionKind.Node10,
moduleResolution: ts.ModuleResolutionKind.Bundler,
typeRoots: ['node_modules/@types'],
...convertedCompilerOptions.options,
enableI18nLegacyMessageIdFormat: false,

View file

@ -97,7 +97,7 @@ export class NgtscTestEnvironment {
"target": "es2015",
"newLine": "lf",
"module": "es2015",
"moduleResolution": "node",
"moduleResolution": "bundler",
"lib": ["es2015", "dom"],
"typeRoots": ["node_modules/@types"]
},

View file

@ -10016,7 +10016,7 @@ runInEachFileSystem((os: string) => {
it('should not error when an undecorated class from a declaration file is provided', () => {
env.write(
'node_modules/@angular/core/testing/index.d.ts',
'node_modules/@angular/core/types/testing.d.ts',
`
export declare class Testability {
}
@ -10041,7 +10041,7 @@ runInEachFileSystem((os: string) => {
it('should not error when an undecorated class without a constructor from a declaration file is provided via useClass', () => {
env.write(
'node_modules/@angular/core/testing/index.d.ts',
'node_modules/@angular/core/types/testing.d.ts',
`
export declare class Testability {
}
@ -10097,7 +10097,7 @@ runInEachFileSystem((os: string) => {
// can be updated.
xit('should error when an undecorated class with a non-trivial constructor in a declaration file is provided via useClass', () => {
env.write(
'node_modules/@angular/core/testing/index.d.ts',
'node_modules/@angular/core/types/testing.d.ts',
`
export declare class NgZone {}
@ -10129,7 +10129,7 @@ runInEachFileSystem((os: string) => {
it('should not error when an class with a factory definition and a non-trivial constructor in a declaration file is provided via useClass', () => {
env.write(
'node_modules/@angular/core/testing/index.d.ts',
'node_modules/@angular/core/types/testing.d.ts',
`
import * as i0 from '@angular/core';

View file

@ -78,7 +78,7 @@ describe('definitions', () => {
);
expect(definitions.length).toEqual(3);
assertTextSpans(definitions, ['transform']);
assertFileNames(definitions, ['index.d.ts']);
assertFileNames(definitions, ['fake_common.d.ts']);
});
it('gets definitions for all inputs when attribute matches more than one', () => {

View file

@ -20,4 +20,4 @@
"strictTemplates": true,
"strictInjectionParameters": true
}
}
}

View file

@ -905,7 +905,7 @@ describe('find references and rename locations', () => {
it('should find references', () => {
const refs = getReferencesAtPosition(file)!;
assertFileNames(refs, ['index.d.ts', 'prefix-pipe.ts', 'app.ts']);
assertFileNames(refs, ['core.d.ts', 'prefix-pipe.ts', 'app.ts']);
assertTextSpans(refs, ['transform', 'prefixPipe']);
});
@ -1830,7 +1830,7 @@ describe('find references and rename locations', () => {
const refs = getReferencesAtPosition(file)!;
expect(refs.length).toBe(7);
assertTextSpans(refs, ['<div *ngFor="let item of items"></div>', 'NgForOf']);
assertFileNames(refs, ['index.d.ts', 'app.ts']);
assertFileNames(refs, ['fake_common.d.ts', 'app.ts']);
});
it('should not support rename if directive is in a dts file', () => {

View file

@ -47,7 +47,7 @@ describe('type definitions', () => {
expect(definitions!.length).toEqual(3);
assertTextSpans(definitions, ['transform']);
assertFileNames(definitions, ['index.d.ts']);
assertFileNames(definitions, ['fake_common.d.ts']);
});
describe('inputs', () => {
@ -80,7 +80,7 @@ describe('type definitions', () => {
expect(definitions!.length).toEqual(1);
assertTextSpans(definitions, ['InputSignal']);
assertFileNames(definitions, ['index.d.ts']);
assertFileNames(definitions, ['core.d.ts']);
});
});
@ -189,7 +189,7 @@ describe('type definitions', () => {
expect(definitions.length).toBe(1);
assertTextSpans(definitions, ['ModelSignal']);
assertFileNames(definitions, ['index.d.ts']);
assertFileNames(definitions, ['core.d.ts']);
});
it('should return the definition for the event side of a two-way binding', () => {
@ -202,7 +202,7 @@ describe('type definitions', () => {
expect(definitions.length).toBe(1);
assertTextSpans(definitions, ['ModelSignal']);
assertFileNames(definitions, ['index.d.ts']);
assertFileNames(definitions, ['core.d.ts']);
});
it('should return the definition of a two-way binding', () => {
@ -215,7 +215,7 @@ describe('type definitions', () => {
expect(definitions.length).toBe(1);
assertTextSpans(definitions, ['ModelSignal']);
assertFileNames(definitions, ['index.d.ts']);
assertFileNames(definitions, ['core.d.ts']);
});
});

View file

@ -45,7 +45,7 @@ function writeTsconfig(
compilerOptions: {
strict: true,
experimentalDecorators: true,
moduleResolution: 'node',
moduleResolution: 'bundler',
target: 'es2015',
rootDir: '.',
lib: ['dom', 'es2015'],

View file

@ -16,7 +16,7 @@
"strict": true,
"strictPropertyInitialization": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"moduleResolution": "bundler",
"module": "esnext",
"target": "es2022",
"lib": ["es2020", "es2022", "dom", "dom.iterable"],

View file

@ -1,6 +1,6 @@
{
"compilerOptions": {
"moduleResolution": "node",
"moduleResolution": "bundler",
"experimentalDecorators": true,
"target": "es2015",
"strict": true,

View file

@ -6,4 +6,4 @@
"dist"
]
},
}
}

View file

@ -12,7 +12,7 @@
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"moduleResolution": "bundler",
"importHelpers": true,
"target": "es2015",
"module": "es2020",