@angular/build 19.2.20 → 19.2.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular/build",
3
- "version": "19.2.20",
3
+ "version": "19.2.21",
4
4
  "description": "Official build system for Angular",
5
5
  "keywords": [
6
6
  "Angular CLI",
@@ -23,7 +23,7 @@
23
23
  "builders": "builders.json",
24
24
  "dependencies": {
25
25
  "@ampproject/remapping": "2.3.0",
26
- "@angular-devkit/architect": "0.1902.20",
26
+ "@angular-devkit/architect": "0.1902.21",
27
27
  "@babel/core": "7.26.10",
28
28
  "@babel/helper-annotate-as-pure": "7.25.9",
29
29
  "@babel/helper-split-export-declaration": "7.24.7",
@@ -58,7 +58,7 @@
58
58
  "@angular/localize": "^19.0.0 || ^19.2.0-next.0",
59
59
  "@angular/platform-server": "^19.0.0 || ^19.2.0-next.0",
60
60
  "@angular/service-worker": "^19.0.0 || ^19.2.0-next.0",
61
- "@angular/ssr": "^19.2.20",
61
+ "@angular/ssr": "^19.2.21",
62
62
  "karma": "^6.4.0",
63
63
  "less": "^4.2.0",
64
64
  "ng-packagr": "^19.0.0 || ^19.2.0-next.0",
@@ -60,7 +60,7 @@ const i18n_1 = require("./i18n");
60
60
  const setup_bundling_1 = require("./setup-bundling");
61
61
  // eslint-disable-next-line max-lines-per-function
62
62
  async function executeBuild(options, context, rebuildState) {
63
- const { projectRoot, workspaceRoot, i18nOptions, optimizationOptions, assets, cacheOptions, serverEntryPoint, baseHref, ssrOptions, verbose, colors, jsonLogs, } = options;
63
+ const { projectRoot, workspaceRoot, i18nOptions, optimizationOptions, assets, cacheOptions, serverEntryPoint, baseHref, ssrOptions, verbose, colors, jsonLogs, security, } = options;
64
64
  // TODO: Consider integrating into watch mode. Would require full rebuild on target changes.
65
65
  const browsers = (0, supported_browsers_1.getSupportedBrowsers)(projectRoot, context.logger);
66
66
  // Load active translations if inlining
@@ -216,7 +216,7 @@ async function executeBuild(options, context, rebuildState) {
216
216
  }
217
217
  // Create server app engine manifest
218
218
  if (serverEntryPoint) {
219
- executionResult.addOutputFile(manifest_1.SERVER_APP_ENGINE_MANIFEST_FILENAME, (0, manifest_1.generateAngularServerAppEngineManifest)(i18nOptions, baseHref), bundler_context_1.BuildOutputFileType.ServerRoot);
219
+ executionResult.addOutputFile(manifest_1.SERVER_APP_ENGINE_MANIFEST_FILENAME, (0, manifest_1.generateAngularServerAppEngineManifest)(i18nOptions, security.allowedHosts, baseHref), bundler_context_1.BuildOutputFileType.ServerRoot);
220
220
  }
221
221
  // Perform i18n translation inlining if enabled
222
222
  if (i18nOptions.shouldInline) {
@@ -197,6 +197,7 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
197
197
  externalRuntimeStyles: boolean | undefined;
198
198
  instrumentForCoverage: ((filename: string) => boolean) | undefined;
199
199
  security: {
200
+ allowedHosts: string[];
200
201
  autoCsp: {
201
202
  unsafeEval: boolean;
202
203
  } | undefined;
@@ -236,8 +236,9 @@ async function normalizeOptions(context, projectName, options, extensions) {
236
236
  throw new Error('The "index" option cannot be set to false when enabling "ssr", "prerender" or "app-shell".');
237
237
  }
238
238
  }
239
- const autoCsp = options.security?.autoCsp;
239
+ const { autoCsp, allowedHosts = [] } = options.security ?? {};
240
240
  const security = {
241
+ allowedHosts,
241
242
  autoCsp: autoCsp
242
243
  ? {
243
244
  unsafeEval: autoCsp === true ? false : !!autoCsp.unsafeEval,
@@ -474,6 +474,12 @@ export type ScriptClass = {
474
474
  * Security features to protect against XSS and other common attacks
475
475
  */
476
476
  export type Security = {
477
+ /**
478
+ * A list of hostnames that are allowed to access the server-side application. For more
479
+ * information, see
480
+ * https://angular.dev/best-practices/security#preventing-server-side-request-forgery-ssrf.
481
+ */
482
+ allowedHosts?: string[];
477
483
  /**
478
484
  * Enables automatic generation of a hash-based Strict Content Security Policy
479
485
  * (https://web.dev/articles/strict-csp#choose-hash) based on scripts in index.html. Will
@@ -52,6 +52,14 @@
52
52
  "type": "object",
53
53
  "additionalProperties": false,
54
54
  "properties": {
55
+ "allowedHosts": {
56
+ "description": "A list of hostnames that are allowed to access the server-side application. For more information, see https://angular.dev/best-practices/security#preventing-server-side-request-forgery-ssrf.",
57
+ "type": "array",
58
+ "uniqueItems": true,
59
+ "items": {
60
+ "type": "string"
61
+ }
62
+ },
55
63
  "autoCsp": {
56
64
  "description": "Enables automatic generation of a hash-based Strict Content Security Policy (https://web.dev/articles/strict-csp#choose-hash) based on scripts in index.html. Will default to true once we are out of experimental/preview phases.",
57
65
  "default": false,
@@ -83,7 +83,14 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
83
83
  browserOptions.ssr ||= true;
84
84
  }
85
85
  // Disable auto CSP.
86
+ const allowedHosts = Array.isArray(serverOptions.allowedHosts)
87
+ ? [...serverOptions.allowedHosts]
88
+ : [];
89
+ // Always allow the dev server host
90
+ allowedHosts.push(serverOptions.host);
86
91
  browserOptions.security = {
92
+ allowedHosts,
93
+ // Disable auto CSP.
87
94
  autoCsp: false,
88
95
  };
89
96
  // Disable JSON build stats.
@@ -10,7 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.normalizeCacheOptions = normalizeCacheOptions;
11
11
  const node_path_1 = require("node:path");
12
12
  /** Version placeholder is replaced during the build process with actual package version */
13
- const VERSION = '19.2.20';
13
+ const VERSION = '19.2.21';
14
14
  function hasCacheMetadata(value) {
15
15
  return (!!value &&
16
16
  typeof value === 'object' &&
@@ -19,10 +19,11 @@ export declare const SERVER_APP_ENGINE_MANIFEST_FILENAME = "angular-app-engine-m
19
19
  *
20
20
  * @param i18nOptions - The internationalization options for the application build. This
21
21
  * includes settings for inlining locales and determining the output structure.
22
+ * @param allowedHosts - A list of hosts that are allowed to access the server-side application.
22
23
  * @param baseHref - The base HREF for the application. This is used to set the base URL
23
24
  * for all relative URLs in the application.
24
25
  */
25
- export declare function generateAngularServerAppEngineManifest(i18nOptions: NormalizedApplicationBuildOptions['i18nOptions'], baseHref: string | undefined): string;
26
+ export declare function generateAngularServerAppEngineManifest(i18nOptions: NormalizedApplicationBuildOptions['i18nOptions'], allowedHosts: string[], baseHref: string | undefined): string;
26
27
  /**
27
28
  * Generates the server manifest for the standard Node.js environment.
28
29
  *
@@ -45,10 +45,11 @@ function escapeUnsafeChars(str) {
45
45
  *
46
46
  * @param i18nOptions - The internationalization options for the application build. This
47
47
  * includes settings for inlining locales and determining the output structure.
48
+ * @param allowedHosts - A list of hosts that are allowed to access the server-side application.
48
49
  * @param baseHref - The base HREF for the application. This is used to set the base URL
49
50
  * for all relative URLs in the application.
50
51
  */
51
- function generateAngularServerAppEngineManifest(i18nOptions, baseHref) {
52
+ function generateAngularServerAppEngineManifest(i18nOptions, allowedHosts, baseHref) {
52
53
  const entryPoints = {};
53
54
  const supportedLocales = {};
54
55
  if (i18nOptions.shouldInline && !i18nOptions.flatOutput) {
@@ -71,6 +72,7 @@ function generateAngularServerAppEngineManifest(i18nOptions, baseHref) {
71
72
  const manifestContent = `
72
73
  export default {
73
74
  basePath: '${basePath}',
75
+ allowedHosts: ${JSON.stringify(allowedHosts, undefined, 2)},
74
76
  supportedLocales: ${JSON.stringify(supportedLocales, undefined, 2)},
75
77
  entryPoints: {
76
78
  ${Object.entries(entryPoints)
@@ -124,6 +124,9 @@ async function renderPages(baseHref, sourcemap, serializableRouteTreeNode, maxTh
124
124
  hasSsrEntry: !!outputFilesForWorker['server.mjs'],
125
125
  },
126
126
  execArgv: workerExecArgv,
127
+ env: {
128
+ 'NG_ALLOWED_HOSTS': 'localhost',
129
+ },
127
130
  });
128
131
  try {
129
132
  const renderingPromises = [];
@@ -203,6 +206,9 @@ async function getAllRoutes(workspaceRoot, baseHref, outputFilesForWorker, asset
203
206
  hasSsrEntry: !!outputFilesForWorker['server.mjs'],
204
207
  },
205
208
  execArgv: workerExecArgv,
209
+ env: {
210
+ 'NG_ALLOWED_HOSTS': 'localhost',
211
+ },
206
212
  });
207
213
  try {
208
214
  const { serializedRouteTree, appShellRoute, errors } = await renderWorker.run({});