Skip to content

Commit 820ad16

Browse files
committed
refactor(@ngtools/webpack): support function-based host file replacement
1 parent 8da68e1 commit 820ad16

File tree

2 files changed

+37
-19
lines changed

2 files changed

+37
-19
lines changed

packages/ngtools/webpack/src/angular_compiler_plugin.ts

+27-13
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import { Path, dirname, normalize, resolve, virtualFs } from '@angular-devkit/core';
8+
import { Path, dirname, getSystemPath, normalize, resolve, virtualFs } from '@angular-devkit/core';
99
import { NodeJsSyncHost } from '@angular-devkit/core/node';
1010
import { ChildProcess, ForkOptions, fork } from 'child_process';
1111
import * as fs from 'fs';
@@ -77,7 +77,7 @@ export interface AngularCompilerPluginOptions {
7777
entryModule?: string;
7878
mainPath?: string;
7979
skipCodeGeneration?: boolean;
80-
hostReplacementPaths?: { [path: string]: string };
80+
hostReplacementPaths?: { [path: string]: string } | ((path: string) => string);
8181
forkTypeChecker?: boolean;
8282
// TODO: remove singleFileIncludes for 2.0, this is just to support old projects that did not
8383
// include 'polyfills.ts' in `tsconfig.spec.json'.
@@ -292,11 +292,20 @@ export class AngularCompilerPlugin {
292292

293293
let host: virtualFs.Host<fs.Stats> = options.host || new NodeJsSyncHost();
294294
if (options.hostReplacementPaths) {
295-
const aliasHost = new virtualFs.AliasHost(host);
296-
for (const from in options.hostReplacementPaths) {
297-
aliasHost.aliases.set(normalize(from), normalize(options.hostReplacementPaths[from]));
295+
if (typeof options.hostReplacementPaths == 'function') {
296+
const replacementResolver = options.hostReplacementPaths;
297+
host = new class extends virtualFs.ResolverHost<fs.Stats> {
298+
_resolve(path: Path) {
299+
return normalize(replacementResolver(getSystemPath(path)));
300+
}
301+
}(host);
302+
} else {
303+
const aliasHost = new virtualFs.AliasHost(host);
304+
for (const from in options.hostReplacementPaths) {
305+
aliasHost.aliases.set(normalize(from), normalize(options.hostReplacementPaths[from]));
306+
}
307+
host = aliasHost;
298308
}
299-
host = aliasHost;
300309
}
301310

302311
// Create the webpack compiler host.
@@ -618,14 +627,19 @@ export class AngularCompilerPlugin {
618627
);
619628
compilerWithFileSystems.inputFileSystem = inputDecorator;
620629

621-
let replacements: Map<Path, Path> | undefined;
630+
let replacements: Map<Path, Path> | ((path: Path) => Path) | undefined;
622631
if (this._options.hostReplacementPaths) {
623-
replacements = new Map();
624-
for (const replace in this._options.hostReplacementPaths) {
625-
replacements.set(
626-
normalize(replace),
627-
normalize(this._options.hostReplacementPaths[replace]),
628-
);
632+
if (typeof this._options.hostReplacementPaths === 'function') {
633+
const replacementResolver = this._options.hostReplacementPaths;
634+
replacements = path => normalize(replacementResolver(getSystemPath(path)));
635+
} else {
636+
replacements = new Map();
637+
for (const replace in this._options.hostReplacementPaths) {
638+
replacements.set(
639+
normalize(replace),
640+
normalize(this._options.hostReplacementPaths[replace]),
641+
);
642+
}
629643
}
630644
}
631645

packages/ngtools/webpack/src/virtual_file_system_decorator.ts

+10-6
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import { Path, getSystemPath, normalize } from '@angular-devkit/core';
8+
import { Path, getSystemPath, normalize, strings } from '@angular-devkit/core';
99
import { Stats } from 'fs';
1010
import { WebpackCompilerHost } from './compiler_host';
1111
import { Callback, InputFileSystem, NodeWatchFileSystemInterface } from './webpack';
@@ -108,7 +108,7 @@ export class VirtualFileSystemDecorator implements InputFileSystem {
108108
export class VirtualWatchFileSystemDecorator extends NodeWatchFileSystem {
109109
constructor(
110110
private _virtualInputFileSystem: VirtualFileSystemDecorator,
111-
private _replacements?: Map<Path, Path>,
111+
private _replacements?: Map<Path, Path> | ((path: Path) => Path),
112112
) {
113113
super(_virtualInputFileSystem);
114114
}
@@ -148,11 +148,15 @@ export class VirtualWatchFileSystemDecorator extends NodeWatchFileSystem {
148148
const replacements = this._replacements;
149149

150150
return original.map(file => {
151-
const replacement = replacements.get(normalize(file));
152-
if (replacement) {
153-
return getSystemPath(replacement);
151+
if (typeof replacements === 'function') {
152+
return getSystemPath(replacements(normalize(file)));
154153
} else {
155-
return file;
154+
const replacement = replacements.get(normalize(file));
155+
if (replacement) {
156+
return getSystemPath(replacement);
157+
} else {
158+
return file;
159+
}
156160
}
157161
});
158162
};

0 commit comments

Comments
 (0)