|
| 1 | +import { existsSync } from 'node:fs'; |
1 | 2 | import type { IsPluginEnabled, Plugin, ResolveConfig } from '../../types/config.js';
|
2 |
| -import { type Input, toConfig, toDependency, toEntry, toProductionEntry } from '../../util/input.js'; |
3 |
| -import { join } from '../../util/path.js'; |
| 3 | +import { type Input, toConfig, toDeferResolve, toDependency, toEntry, toProductionEntry } from '../../util/input.js'; |
| 4 | +import { isInternal, join } from '../../util/path.js'; |
4 | 5 | import { hasDependency } from '../../util/plugin.js';
|
5 | 6 | import * as karma from '../karma/helpers.js';
|
6 | 7 | import type {
|
@@ -44,24 +45,37 @@ const resolveConfig: ResolveConfig<AngularCLIWorkspaceConfiguration> = async (co
|
44 | 45 | );
|
45 | 46 | const productionEntriesByOption: EntriesByOption =
|
46 | 47 | entriesByOptionByConfig.get(PRODUCTION_CONFIG_NAME) ?? new Map();
|
47 |
| - const normalizePath = (path: string) => join(cwd, path); |
| 48 | + const isBuildTarget = targetName === BUILD_TARGET_NAME; |
| 49 | + const maybeExternal = (option: string) => option === 'polyfills'; |
| 50 | + const toInput = (specifier: string, opts: { isProduction: boolean; maybeExternal: boolean }): Input => { |
| 51 | + const normalizedPath = join(cwd, specifier); |
| 52 | + // 👇 `isInternal` will report `false` for specifiers not starting with `.` |
| 53 | + // However, relative imports are usually specified in `angular.json` without `.` prefix |
| 54 | + // Hence checking also that file doesn't exist before considering it external |
| 55 | + if (opts.maybeExternal && !isInternal(specifier) && !existsSync(normalizedPath)) { |
| 56 | + return toDeferResolve(specifier); |
| 57 | + } |
| 58 | + return opts.isProduction ? toProductionEntry(normalizedPath) : toEntry(normalizedPath); |
| 59 | + }; |
48 | 60 | for (const [configName, entriesByOption] of entriesByOptionByConfig.entries()) {
|
49 |
| - for (const entries of entriesByOption.values()) { |
| 61 | + for (const [option, entries] of entriesByOption.entries()) { |
50 | 62 | for (const entry of entries) {
|
51 | 63 | inputs.add(
|
52 |
| - targetName === BUILD_TARGET_NAME && configName === PRODUCTION_CONFIG_NAME |
53 |
| - ? toProductionEntry(normalizePath(entry)) |
54 |
| - : toEntry(normalizePath(entry)) |
| 64 | + toInput(entry, { |
| 65 | + isProduction: isBuildTarget && configName === PRODUCTION_CONFIG_NAME, |
| 66 | + maybeExternal: maybeExternal(option), |
| 67 | + }) |
55 | 68 | );
|
56 | 69 | }
|
57 | 70 | }
|
58 | 71 | }
|
59 | 72 | for (const [option, entries] of defaultEntriesByOption.entries()) {
|
60 | 73 | for (const entry of entries) {
|
61 | 74 | inputs.add(
|
62 |
| - targetName === BUILD_TARGET_NAME && !productionEntriesByOption.get(option)?.length |
63 |
| - ? toProductionEntry(normalizePath(entry)) |
64 |
| - : toEntry(normalizePath(entry)) |
| 75 | + toInput(entry, { |
| 76 | + isProduction: isBuildTarget && !productionEntriesByOption.get(option)?.length, |
| 77 | + maybeExternal: maybeExternal(option), |
| 78 | + }) |
65 | 79 | );
|
66 | 80 | }
|
67 | 81 | }
|
@@ -109,6 +123,12 @@ const entriesByOption = (opts: TargetOptions): EntriesByOption =>
|
109 | 123 | typeof scriptStringOrObject === 'string' ? scriptStringOrObject : scriptStringOrObject.input
|
110 | 124 | )
|
111 | 125 | : [],
|
| 126 | + polyfills: |
| 127 | + 'polyfills' in opts && opts.polyfills |
| 128 | + ? Array.isArray(opts.polyfills) |
| 129 | + ? opts.polyfills |
| 130 | + : [opts.polyfills] |
| 131 | + : [], |
112 | 132 | fileReplacements:
|
113 | 133 | 'fileReplacements' in opts && opts.fileReplacements && Array.isArray(opts.fileReplacements)
|
114 | 134 | ? (opts.fileReplacements as FileReplacementsBuildOption).map(fileReplacement =>
|
|
0 commit comments