Skip to content

Commit de64b86

Browse files
committed
fix(@angular/cli): add a flag to let assets outside of outDir
On top of #7778 Fixes #8122
1 parent 8063287 commit de64b86

File tree

4 files changed

+41
-4
lines changed

4 files changed

+41
-4
lines changed

packages/@angular/cli/lib/config/schema.json

+5
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@
7272
"type": "string",
7373
"default": "",
7474
"description": "The output path (relative to the outDir)."
75+
},
76+
"allowOutsideOutDir": {
77+
"type": "boolean",
78+
"description": "Allow assets to be copied outside the outDir.",
79+
"default": false
7580
}
7681
},
7782
"additionalProperties": false

packages/@angular/cli/models/webpack-configs/common.ts

+13-3
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,22 @@ export function getCommonConfig(wco: WebpackConfigOptions) {
9595
asset.output = asset.output || '';
9696
asset.glob = asset.glob || '';
9797

98-
// Prevent asset configurations from writing outside of the output path
98+
// Prevent asset configurations from writing outside of the output path, except if the user
99+
// specify a configuration flag.
100+
// Also prevent writing outside the project path. That is not overridable.
99101
const fullOutputPath = path.resolve(buildOptions.outputPath, asset.output);
100-
if (!fullOutputPath.startsWith(path.resolve(buildOptions.outputPath))) {
101-
const message = 'An asset cannot be written to a location outside of the output path.';
102+
if (!fullOutputPath.startsWith(projectRoot)) {
103+
const message = 'An asset cannot be written to a location outside the project.';
102104
throw new SilentError(message);
103105
}
106+
if (!fullOutputPath.startsWith(path.resolve(buildOptions.outputPath))) {
107+
if (!asset.allowOutsideOutDir) {
108+
const message = 'An asset cannot be written to a location outside of the output path. '
109+
+ 'You can override this message by setting the `allowOutsideOutDir` '
110+
+ 'property on the asset to true in the CLI configuration.';
111+
throw new SilentError(message);
112+
}
113+
}
104114

105115
// Ensure trailing slash.
106116
if (isDirectory(path.resolve(asset.input))) {

packages/@angular/cli/models/webpack-configs/utils.ts

+1
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,5 @@ export interface AssetPattern {
9292
glob: string;
9393
input?: string;
9494
output?: string;
95+
allowOutsideOutDir?: boolean;
9596
}

tests/e2e/tests/build/assets.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,31 @@ export default function () {
3030
.then(() => updateJsonFile('.angular-cli.json', configJson => {
3131
const app = configJson['apps'][0];
3232
app['assets'] = [
33-
{ 'glob': '**/*', 'input': '../node_modules/some-package/', 'output': '../package-folder' }
33+
{ 'glob': '**/*', 'input': '../node_modules/some-package/', 'output': '../temp' }
3434
];
3535
}))
3636
.then(() => expectToFail(() => ng('build')))
37+
38+
// Set an exception for the invalid asset config in .angular-cli.json.
39+
.then(() => updateJsonFile('.angular-cli.json', configJson => {
40+
const app = configJson['apps'][0];
41+
app['assets'] = [
42+
{ 'glob': '**/*', 'input': '../node_modules/some-package/', 'output': '../temp',
43+
'allowOutsideOutDir': true }
44+
];
45+
}))
46+
.then(() => ng('build'))
47+
48+
// This asset should fail even with the exception above.
49+
.then(() => updateJsonFile('.angular-cli.json', configJson => {
50+
const app = configJson['apps'][0];
51+
app['assets'] = [
52+
{ 'glob': '**/*', 'input': '../node_modules/some-package/', 'output': '../../temp',
53+
'allowOutsideOutDir': true }
54+
];
55+
}))
56+
.then(() => expectToFail(() => ng('build')))
57+
3758
// Add asset config in .angular-cli.json.
3859
.then(() => updateJsonFile('.angular-cli.json', configJson => {
3960
const app = configJson['apps'][0];

0 commit comments

Comments
 (0)