@angular/build 19.1.0-next.2 → 19.1.0-rc.0

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.
Files changed (43) hide show
  1. package/LICENSE +1 -1
  2. package/builders.json +5 -0
  3. package/index.d.ts +8 -0
  4. package/index.js +24 -0
  5. package/package.json +15 -11
  6. package/private/index.d.ts +8 -0
  7. package/private/index.js +24 -0
  8. package/src/builders/application/build-action.d.ts +1 -0
  9. package/src/builders/application/build-action.js +80 -11
  10. package/src/builders/application/execute-build.js +1 -1
  11. package/src/builders/application/index.d.ts +2 -10
  12. package/src/builders/application/index.js +33 -20
  13. package/src/builders/application/options.d.ts +6 -0
  14. package/src/builders/application/options.js +1 -0
  15. package/src/builders/application/results.d.ts +4 -1
  16. package/src/builders/dev-server/index.d.ts +1 -1
  17. package/src/builders/dev-server/vite-server.d.ts +1 -1
  18. package/src/builders/dev-server/vite-server.js +79 -69
  19. package/src/builders/extract-i18n/index.d.ts +1 -1
  20. package/src/builders/ng-packagr/builder.d.ts +19 -0
  21. package/src/builders/ng-packagr/builder.js +103 -0
  22. package/src/builders/ng-packagr/index.d.ts +12 -0
  23. package/src/builders/ng-packagr/index.js +14 -0
  24. package/src/builders/ng-packagr/schema.d.ts +21 -0
  25. package/src/builders/ng-packagr/schema.js +4 -0
  26. package/src/builders/ng-packagr/schema.json +27 -0
  27. package/src/index.d.ts +2 -1
  28. package/src/index.js +3 -1
  29. package/src/tools/babel/plugins/pure-toplevel-functions.js +14 -3
  30. package/src/tools/esbuild/angular-localize-init-warning-plugin.d.ts +16 -0
  31. package/src/tools/esbuild/angular-localize-init-warning-plugin.js +49 -0
  32. package/src/tools/esbuild/application-code-bundle.js +4 -0
  33. package/src/tools/esbuild/bundler-execution-result.d.ts +9 -3
  34. package/src/tools/esbuild/bundler-execution-result.js +12 -10
  35. package/src/tools/esbuild/javascript-transformer.js +8 -4
  36. package/src/tools/vite/plugins/angular-memory-plugin.js +10 -5
  37. package/src/tools/vite/utils.d.ts +2 -1
  38. package/src/tools/vite/utils.js +2 -1
  39. package/src/utils/bundle-calculator.d.ts +1 -0
  40. package/src/utils/bundle-calculator.js +5 -4
  41. package/src/utils/normalize-cache.js +1 -1
  42. package/src/utils/server-rendering/fetch-patch.js +2 -2
  43. package/tsconfig-build.json +0 -6
@@ -110,6 +110,7 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
110
110
  // This will also replace file-based/inline styles as code if external runtime styles are not enabled.
111
111
  browserOptions.templateUpdates =
112
112
  serverOptions.liveReload && serverOptions.hmr && environment_options_1.useComponentTemplateHmr;
113
+ browserOptions.incrementalResults = true;
113
114
  // Setup the prebundling transformer that will be shared across Vite prebundling requests
114
115
  const prebundleTransformer = new internal_1.JavaScriptTransformer(
115
116
  // Always enable JIT linking to support applications built with and without AOT.
@@ -179,10 +180,17 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
179
180
  : baseHref;
180
181
  }
181
182
  assetFiles.clear();
182
- for (const [outputPath, file] of Object.entries(result.files)) {
183
+ componentStyles.clear();
184
+ generatedFiles.clear();
185
+ for (const entry of Object.entries(result.files)) {
186
+ const [outputPath, file] = entry;
183
187
  if (file.origin === 'disk') {
184
188
  assetFiles.set('/' + normalizePath(outputPath), normalizePath(file.inputPath));
189
+ continue;
185
190
  }
191
+ updateResultRecord(outputPath, file, normalizePath, htmlIndexPath, generatedFiles, componentStyles,
192
+ // The initial build will not yet have a server setup
193
+ !server);
186
194
  }
187
195
  // Invalidate SSR module graph to ensure that only new rebuild is used and not stale component updates
188
196
  if (server && browserOptions.ssr && templateUpdates.size > 0) {
@@ -190,12 +198,20 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
190
198
  }
191
199
  // Clear stale template updates on code rebuilds
192
200
  templateUpdates.clear();
193
- // Analyze result files for changes
194
- analyzeResultFiles(normalizePath, htmlIndexPath, result.files, generatedFiles, componentStyles);
195
201
  break;
196
202
  case results_1.ResultKind.Incremental:
197
203
  (0, node_assert_1.default)(server, 'Builder must provide an initial full build before incremental results.');
198
- // TODO: Implement support -- application builder currently does not use
204
+ for (const removed of result.removed) {
205
+ const filePath = '/' + normalizePath(removed.path);
206
+ generatedFiles.delete(filePath);
207
+ assetFiles.delete(filePath);
208
+ }
209
+ for (const modified of result.modified) {
210
+ updateResultRecord(modified, result.files[modified], normalizePath, htmlIndexPath, generatedFiles, componentStyles);
211
+ }
212
+ for (const added of result.added) {
213
+ updateResultRecord(added, result.files[added], normalizePath, htmlIndexPath, generatedFiles, componentStyles);
214
+ }
199
215
  break;
200
216
  case results_1.ResultKind.ComponentUpdate:
201
217
  (0, node_assert_1.default)(serverOptions.hmr, 'Component updates are only supported with HMR enabled.');
@@ -286,7 +302,7 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
286
302
  });
287
303
  }
288
304
  // Setup server and start listening
289
- const serverConfiguration = await setupServer(serverOptions, generatedFiles, assetFiles, browserOptions.preserveSymlinks, externalMetadata, ssrMode, prebundleTransformer, target, (0, internal_1.isZonelessApp)(polyfills), componentStyles, templateUpdates, browserOptions.loader, extensions?.middleware, transformers?.indexHtml, thirdPartySourcemaps);
305
+ const serverConfiguration = await setupServer(serverOptions, generatedFiles, assetFiles, browserOptions.preserveSymlinks, externalMetadata, ssrMode, prebundleTransformer, target, (0, internal_1.isZonelessApp)(polyfills), componentStyles, templateUpdates, browserOptions.loader, browserOptions.define, extensions?.middleware, transformers?.indexHtml, thirdPartySourcemaps);
290
306
  server = await createServer(serverConfiguration);
291
307
  await server.listen();
292
308
  const urls = server.resolvedUrls;
@@ -325,11 +341,12 @@ async function handleUpdate(normalizePath, generatedFiles, server, serverOptions
325
341
  const updatedFiles = [];
326
342
  let destroyAngularServerAppCalled = false;
327
343
  // Invalidate any updated files
328
- for (const [file, { updated, type }] of generatedFiles) {
329
- if (!updated) {
344
+ for (const [file, record] of generatedFiles) {
345
+ if (!record.updated) {
330
346
  continue;
331
347
  }
332
- if (type === internal_1.BuildOutputFileType.ServerApplication && !destroyAngularServerAppCalled) {
348
+ record.updated = false;
349
+ if (record.type === internal_1.BuildOutputFileType.ServerApplication && !destroyAngularServerAppCalled) {
333
350
  // Clear the server app cache
334
351
  // This must be done before module invalidation.
335
352
  const { ɵdestroyAngularServerApp } = (await server.ssrLoadModule('/main.server.mjs'));
@@ -402,79 +419,71 @@ async function handleUpdate(normalizePath, generatedFiles, server, serverOptions
402
419
  logger.info('Page reload sent to client(s).');
403
420
  }
404
421
  }
405
- function analyzeResultFiles(normalizePath, htmlIndexPath, resultFiles, generatedFiles, componentStyles) {
406
- const seen = new Set(['/index.html']);
407
- for (const [outputPath, file] of Object.entries(resultFiles)) {
408
- if (file.origin === 'disk') {
409
- continue;
410
- }
411
- let filePath;
412
- if (outputPath === htmlIndexPath) {
413
- // Convert custom index output path to standard index path for dev-server usage.
414
- // This mimics the Webpack dev-server behavior.
415
- filePath = '/index.html';
416
- }
417
- else {
418
- filePath = '/' + normalizePath(outputPath);
419
- }
420
- seen.add(filePath);
421
- const servable = file.type === internal_1.BuildOutputFileType.Browser || file.type === internal_1.BuildOutputFileType.Media;
422
- // Skip analysis of sourcemaps
423
- if (filePath.endsWith('.map')) {
424
- generatedFiles.set(filePath, {
425
- contents: file.contents,
426
- servable,
427
- size: file.contents.byteLength,
428
- hash: file.hash,
429
- type: file.type,
430
- updated: false,
431
- });
432
- continue;
433
- }
434
- const existingRecord = generatedFiles.get(filePath);
435
- if (existingRecord &&
436
- existingRecord.size === file.contents.byteLength &&
437
- existingRecord.hash === file.hash) {
438
- // Same file
439
- existingRecord.updated = false;
440
- continue;
441
- }
442
- // New or updated file
422
+ function updateResultRecord(outputPath, file, normalizePath, htmlIndexPath, generatedFiles, componentStyles, initial = false) {
423
+ if (file.origin === 'disk') {
424
+ return;
425
+ }
426
+ let filePath;
427
+ if (outputPath === htmlIndexPath) {
428
+ // Convert custom index output path to standard index path for dev-server usage.
429
+ // This mimics the Webpack dev-server behavior.
430
+ filePath = '/index.html';
431
+ }
432
+ else {
433
+ filePath = '/' + normalizePath(outputPath);
434
+ }
435
+ const servable = file.type === internal_1.BuildOutputFileType.Browser || file.type === internal_1.BuildOutputFileType.Media;
436
+ // Skip analysis of sourcemaps
437
+ if (filePath.endsWith('.map')) {
443
438
  generatedFiles.set(filePath, {
444
439
  contents: file.contents,
440
+ servable,
445
441
  size: file.contents.byteLength,
446
442
  hash: file.hash,
447
- updated: true,
448
443
  type: file.type,
449
- servable,
444
+ updated: false,
450
445
  });
451
- // Record any external component styles
452
- if (filePath.endsWith('.css') && /^\/[a-f0-9]{64}\.css$/.test(filePath)) {
453
- const componentStyle = componentStyles.get(filePath);
454
- if (componentStyle) {
455
- componentStyle.rawContent = file.contents;
456
- }
457
- else {
458
- componentStyles.set(filePath, {
459
- rawContent: file.contents,
460
- });
461
- }
462
- }
446
+ return;
463
447
  }
464
- // Clear stale output files
465
- for (const file of generatedFiles.keys()) {
466
- if (!seen.has(file)) {
467
- generatedFiles.delete(file);
468
- componentStyles.delete(file);
448
+ // New or updated file
449
+ generatedFiles.set(filePath, {
450
+ contents: file.contents,
451
+ size: file.contents.byteLength,
452
+ hash: file.hash,
453
+ // Consider the files updated except on the initial build result
454
+ updated: !initial,
455
+ type: file.type,
456
+ servable,
457
+ });
458
+ // Record any external component styles
459
+ if (filePath.endsWith('.css') && /^\/[a-f0-9]{64}\.css$/.test(filePath)) {
460
+ const componentStyle = componentStyles.get(filePath);
461
+ if (componentStyle) {
462
+ componentStyle.rawContent = file.contents;
463
+ }
464
+ else {
465
+ componentStyles.set(filePath, {
466
+ rawContent: file.contents,
467
+ });
469
468
  }
470
469
  }
471
470
  }
472
- async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks, externalMetadata, ssrMode, prebundleTransformer, target, zoneless, componentStyles, templateUpdates, prebundleLoaderExtensions, extensionMiddleware, indexHtmlTransformer, thirdPartySourcemaps = false) {
471
+ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks, externalMetadata, ssrMode, prebundleTransformer, target, zoneless, componentStyles, templateUpdates, prebundleLoaderExtensions, define, extensionMiddleware, indexHtmlTransformer, thirdPartySourcemaps = false) {
473
472
  const proxy = await (0, utils_2.loadProxyConfiguration)(serverOptions.workspaceRoot, serverOptions.proxyConfig);
474
473
  // dynamically import Vite for ESM compatibility
475
474
  const { normalizePath } = await (0, load_esm_1.loadEsmModule)('vite');
476
475
  // Path will not exist on disk and only used to provide separate path for Vite requests
477
476
  const virtualProjectRoot = normalizePath((0, node_path_1.join)(serverOptions.workspaceRoot, `.angular/vite-root`, serverOptions.buildTarget.project));
477
+ // Files used for SSR warmup.
478
+ let ssrFiles;
479
+ switch (ssrMode) {
480
+ case plugins_1.ServerSsrMode.InternalSsrMiddleware:
481
+ ssrFiles = ['./main.server.mjs'];
482
+ break;
483
+ case plugins_1.ServerSsrMode.ExternalSsrMiddleware:
484
+ ssrFiles = ['./main.server.mjs', './server.mjs'];
485
+ break;
486
+ }
478
487
  const cacheDir = (0, node_path_1.join)(serverOptions.cacheOptions.path, serverOptions.buildTarget.project, 'vite');
479
488
  const configuration = {
480
489
  configFile: false,
@@ -505,7 +514,7 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
505
514
  },
506
515
  server: {
507
516
  warmup: {
508
- ssrFiles: ['./main.server.mjs', './server.mjs'],
517
+ ssrFiles,
509
518
  },
510
519
  port: serverOptions.port,
511
520
  strictPort: true,
@@ -557,6 +566,7 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
557
566
  target,
558
567
  loader: prebundleLoaderExtensions,
559
568
  thirdPartySourcemaps,
569
+ define,
560
570
  }),
561
571
  },
562
572
  plugins: [
@@ -594,12 +604,13 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
594
604
  zoneless,
595
605
  loader: prebundleLoaderExtensions,
596
606
  thirdPartySourcemaps,
607
+ define,
597
608
  }),
598
609
  };
599
610
  if (serverOptions.ssl) {
600
611
  if (serverOptions.sslCert && serverOptions.sslKey) {
612
+ configuration.server ??= {};
601
613
  // server configuration is defined above
602
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
603
614
  configuration.server.https = {
604
615
  cert: await (0, promises_1.readFile)(serverOptions.sslCert),
605
616
  key: await (0, promises_1.readFile)(serverOptions.sslKey),
@@ -607,7 +618,6 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
607
618
  }
608
619
  else {
609
620
  const { default: basicSslPlugin } = await Promise.resolve().then(() => __importStar(require('@vitejs/plugin-basic-ssl')));
610
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
611
621
  configuration.plugins ??= [];
612
622
  configuration.plugins.push(basicSslPlugin());
613
623
  }
@@ -8,5 +8,5 @@
8
8
  import { execute } from './builder';
9
9
  import type { Schema as ExtractI18nBuilderOptions } from './schema';
10
10
  export { ExtractI18nBuilderOptions, execute };
11
- declare const _default: import("../../../../../angular_devkit/architect/src/internal").Builder<ExtractI18nBuilderOptions & import("../../../../../angular_devkit/core/src").JsonObject>;
11
+ declare const _default: import("../../../../../angular_devkit/architect/src/internal").Builder<ExtractI18nBuilderOptions & import("../../../../../angular_devkit/core").JsonObject>;
12
12
  export default _default;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.dev/license
7
+ */
8
+ import type { BuilderContext, BuilderOutput } from '@angular-devkit/architect';
9
+ import type { Schema as NgPackagrBuilderOptions } from './schema';
10
+ /**
11
+ * A Builder that executes the `ng-packagr` tool to build an Angular library.
12
+ *
13
+ * @param options The builder options as defined by the JSON schema.
14
+ * @param context A BuilderContext instance.
15
+ * @returns A BuilderOutput object.
16
+ *
17
+ * @experimental Direct usage of this function is considered experimental.
18
+ */
19
+ export declare function execute(options: NgPackagrBuilderOptions, context: BuilderContext): AsyncIterableIterator<BuilderOutput>;
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright Google LLC All Rights Reserved.
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://angular.dev/license
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.execute = execute;
44
+ const node_path_1 = require("node:path");
45
+ const error_1 = require("../../utils/error");
46
+ const normalize_cache_1 = require("../../utils/normalize-cache");
47
+ const purge_cache_1 = require("../../utils/purge-cache");
48
+ /**
49
+ * A Builder that executes the `ng-packagr` tool to build an Angular library.
50
+ *
51
+ * @param options The builder options as defined by the JSON schema.
52
+ * @param context A BuilderContext instance.
53
+ * @returns A BuilderOutput object.
54
+ *
55
+ * @experimental Direct usage of this function is considered experimental.
56
+ */
57
+ async function* execute(options, context) {
58
+ // Purge old build disk cache.
59
+ await (0, purge_cache_1.purgeStaleBuildCache)(context);
60
+ const root = context.workspaceRoot;
61
+ let packager;
62
+ try {
63
+ packager = (await Promise.resolve().then(() => __importStar(require('ng-packagr')))).ngPackagr();
64
+ }
65
+ catch (error) {
66
+ (0, error_1.assertIsError)(error);
67
+ if (error.code === 'MODULE_NOT_FOUND') {
68
+ return {
69
+ success: false,
70
+ error: 'The "ng-packagr" package was not found. To correct this error, ensure this package is installed in the project.',
71
+ };
72
+ }
73
+ throw error;
74
+ }
75
+ packager.forProject((0, node_path_1.resolve)(root, options.project));
76
+ if (options.tsConfig) {
77
+ packager.withTsConfig((0, node_path_1.resolve)(root, options.tsConfig));
78
+ }
79
+ const projectName = context.target?.project;
80
+ if (!projectName) {
81
+ throw new Error('The builder requires a target.');
82
+ }
83
+ const metadata = await context.getProjectMetadata(projectName);
84
+ const { enabled: cacheEnabled, path: cacheDirectory } = (0, normalize_cache_1.normalizeCacheOptions)(metadata, context.workspaceRoot);
85
+ const ngPackagrOptions = {
86
+ cacheEnabled,
87
+ poll: options.poll,
88
+ cacheDirectory: (0, node_path_1.join)(cacheDirectory, 'ng-packagr'),
89
+ };
90
+ try {
91
+ if (options.watch) {
92
+ await packager.watch(ngPackagrOptions).toPromise();
93
+ }
94
+ else {
95
+ await packager.build(ngPackagrOptions);
96
+ }
97
+ yield { success: true };
98
+ }
99
+ catch (error) {
100
+ (0, error_1.assertIsError)(error);
101
+ yield { success: false, error: error.message };
102
+ }
103
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.dev/license
7
+ */
8
+ import { execute } from './builder';
9
+ import type { Schema as NgPackagrBuilderOptions } from './schema';
10
+ export { type NgPackagrBuilderOptions, execute };
11
+ declare const _default: import("../../../../../angular_devkit/architect/src/internal").Builder<NgPackagrBuilderOptions & import("../../../../../angular_devkit/core").JsonObject>;
12
+ export default _default;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright Google LLC All Rights Reserved.
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://angular.dev/license
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.execute = void 0;
11
+ const architect_1 = require("@angular-devkit/architect");
12
+ const builder_1 = require("./builder");
13
+ Object.defineProperty(exports, "execute", { enumerable: true, get: function () { return builder_1.execute; } });
14
+ exports.default = (0, architect_1.createBuilder)(builder_1.execute);
@@ -0,0 +1,21 @@
1
+ /**
2
+ * ng-packagr target options for Build Architect. Use to build library projects.
3
+ */
4
+ export interface Schema {
5
+ /**
6
+ * Enable and define the file watching poll time period in milliseconds.
7
+ */
8
+ poll?: number;
9
+ /**
10
+ * The file path for the ng-packagr configuration file, relative to the current workspace.
11
+ */
12
+ project: string;
13
+ /**
14
+ * The full path for the TypeScript configuration file, relative to the current workspace.
15
+ */
16
+ tsConfig?: string;
17
+ /**
18
+ * Run build when files change.
19
+ */
20
+ watch?: boolean;
21
+ }
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ // THIS FILE IS AUTOMATICALLY GENERATED. TO UPDATE THIS FILE YOU NEED TO CHANGE THE
3
+ // CORRESPONDING JSON SCHEMA FILE, THEN RUN devkit-admin build (or bazel build ...).
4
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema",
3
+ "title": "ng-packagr Target",
4
+ "description": "ng-packagr target options for Build Architect. Use to build library projects.",
5
+ "type": "object",
6
+ "properties": {
7
+ "project": {
8
+ "type": "string",
9
+ "description": "The file path for the ng-packagr configuration file, relative to the current workspace."
10
+ },
11
+ "tsConfig": {
12
+ "type": "string",
13
+ "description": "The full path for the TypeScript configuration file, relative to the current workspace."
14
+ },
15
+ "watch": {
16
+ "type": "boolean",
17
+ "description": "Run build when files change.",
18
+ "default": false
19
+ },
20
+ "poll": {
21
+ "type": "number",
22
+ "description": "Enable and define the file watching poll time period in milliseconds."
23
+ }
24
+ },
25
+ "additionalProperties": false,
26
+ "required": ["project"]
27
+ }
package/src/index.d.ts CHANGED
@@ -5,9 +5,10 @@
5
5
  * Use of this source code is governed by an MIT-style license that can be
6
6
  * found in the LICENSE file at https://angular.dev/license
7
7
  */
8
- export { buildApplication, type ApplicationBuilderOptions, type ApplicationBuilderOutput, } from './builders/application';
8
+ export { buildApplication, type ApplicationBuilderOptions } from './builders/application';
9
9
  export type { ApplicationBuilderExtensions } from './builders/application/options';
10
10
  export { type BuildOutputFile, BuildOutputFileType } from './tools/esbuild/bundler-context';
11
11
  export type { BuildOutputAsset } from './tools/esbuild/bundler-execution-result';
12
12
  export { executeDevServerBuilder, type DevServerBuilderOptions, type DevServerBuilderOutput, } from './builders/dev-server';
13
13
  export { execute as executeExtractI18nBuilder, type ExtractI18nBuilderOptions, } from './builders/extract-i18n';
14
+ export { execute as executeNgPackagrBuilder, type NgPackagrBuilderOptions, } from './builders/ng-packagr';
package/src/index.js CHANGED
@@ -7,7 +7,7 @@
7
7
  * found in the LICENSE file at https://angular.dev/license
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.executeExtractI18nBuilder = exports.executeDevServerBuilder = exports.BuildOutputFileType = exports.buildApplication = void 0;
10
+ exports.executeNgPackagrBuilder = exports.executeExtractI18nBuilder = exports.executeDevServerBuilder = exports.BuildOutputFileType = exports.buildApplication = void 0;
11
11
  var application_1 = require("./builders/application");
12
12
  Object.defineProperty(exports, "buildApplication", { enumerable: true, get: function () { return application_1.buildApplication; } });
13
13
  var bundler_context_1 = require("./tools/esbuild/bundler-context");
@@ -16,3 +16,5 @@ var dev_server_1 = require("./builders/dev-server");
16
16
  Object.defineProperty(exports, "executeDevServerBuilder", { enumerable: true, get: function () { return dev_server_1.executeDevServerBuilder; } });
17
17
  var extract_i18n_1 = require("./builders/extract-i18n");
18
18
  Object.defineProperty(exports, "executeExtractI18nBuilder", { enumerable: true, get: function () { return extract_i18n_1.execute; } });
19
+ var ng_packagr_1 = require("./builders/ng-packagr");
20
+ Object.defineProperty(exports, "executeNgPackagrBuilder", { enumerable: true, get: function () { return ng_packagr_1.execute; } });
@@ -64,6 +64,16 @@ function isTslibHelperName(name) {
64
64
  }
65
65
  return tslibHelpers.has(originalName);
66
66
  }
67
+ const babelHelpers = new Set(['_defineProperty']);
68
+ /**
69
+ * Determinates whether an identifier name matches one of the Babel helper function names.
70
+ *
71
+ * @param name The identifier name to check.
72
+ * @returns True, if the name matches a Babel helper name; otherwise, false.
73
+ */
74
+ function isBabelHelperName(name) {
75
+ return babelHelpers.has(name);
76
+ }
67
77
  /**
68
78
  * A babel plugin factory function for adding the PURE annotation to top-level new and call expressions.
69
79
  *
@@ -82,9 +92,10 @@ function default_1() {
82
92
  path.node.arguments.length !== 0) {
83
93
  return;
84
94
  }
85
- // Do not annotate TypeScript helpers emitted by the TypeScript compiler.
86
- // TypeScript helpers are intended to cause side effects.
87
- if (callee.isIdentifier() && isTslibHelperName(callee.node.name)) {
95
+ // Do not annotate TypeScript helpers emitted by the TypeScript compiler or Babel helpers.
96
+ // They are intended to cause side effects.
97
+ if (callee.isIdentifier() &&
98
+ (isTslibHelperName(callee.node.name) || isBabelHelperName(callee.node.name))) {
88
99
  return;
89
100
  }
90
101
  (0, helper_annotate_as_pure_1.default)(path);
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.dev/license
7
+ */
8
+ import type { Plugin } from 'esbuild';
9
+ /**
10
+ * This plugin addresses an issue where '@angular/localize/init' is directly imported,
11
+ * potentially resulting in undefined behavior. By detecting such imports, the plugin
12
+ * issues a warning and suggests including '@angular/localize/init' as a polyfill.
13
+ *
14
+ * @returns An esbuild plugin.
15
+ */
16
+ export declare function createAngularLocalizeInitWarningPlugin(): Plugin;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright Google LLC All Rights Reserved.
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://angular.dev/license
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.createAngularLocalizeInitWarningPlugin = createAngularLocalizeInitWarningPlugin;
11
+ const NG_LOCALIZE_RESOLUTION = Symbol('NG_LOCALIZE_RESOLUTION');
12
+ /**
13
+ * This plugin addresses an issue where '@angular/localize/init' is directly imported,
14
+ * potentially resulting in undefined behavior. By detecting such imports, the plugin
15
+ * issues a warning and suggests including '@angular/localize/init' as a polyfill.
16
+ *
17
+ * @returns An esbuild plugin.
18
+ */
19
+ function createAngularLocalizeInitWarningPlugin() {
20
+ return {
21
+ name: 'angular-localize-init-warning',
22
+ setup(build) {
23
+ build.onResolve({ filter: /^@angular\/localize\/init/ }, async (args) => {
24
+ if (args.pluginData?.[NG_LOCALIZE_RESOLUTION]) {
25
+ return null;
26
+ }
27
+ const { importer, kind, resolveDir, namespace, pluginData = {} } = args;
28
+ pluginData[NG_LOCALIZE_RESOLUTION] = true;
29
+ const result = await build.resolve(args.path, {
30
+ importer,
31
+ kind,
32
+ namespace,
33
+ pluginData,
34
+ resolveDir,
35
+ });
36
+ return {
37
+ ...result,
38
+ warnings: [
39
+ ...result.warnings,
40
+ {
41
+ text: `Direct import of '@angular/localize/init' detected. This may lead to undefined behavior.`,
42
+ notes: [{ text: `Include '@angular/localize/init' as a polyfill instead.` }],
43
+ },
44
+ ],
45
+ };
46
+ });
47
+ },
48
+ };
49
+ }
@@ -22,6 +22,7 @@ const schema_1 = require("../../builders/application/schema");
22
22
  const environment_options_1 = require("../../utils/environment-options");
23
23
  const manifest_1 = require("../../utils/server-rendering/manifest");
24
24
  const compiler_plugin_1 = require("./angular/compiler-plugin");
25
+ const angular_localize_init_warning_plugin_1 = require("./angular-localize-init-warning-plugin");
25
26
  const compiler_plugin_options_1 = require("./compiler-plugin-options");
26
27
  const external_packages_plugin_1 = require("./external-packages-plugin");
27
28
  const i18n_locale_plugin_1 = require("./i18n-locale-plugin");
@@ -53,6 +54,7 @@ function createBrowserCodeBundleOptions(options, target, sourceFileCache, styles
53
54
  (0, loader_import_attribute_plugin_1.createLoaderImportAttributePlugin)(),
54
55
  (0, wasm_plugin_1.createWasmPlugin)({ allowAsync: zoneless, cache: loadCache }),
55
56
  (0, sourcemap_ignorelist_plugin_1.createSourcemapIgnorelistPlugin)(),
57
+ (0, angular_localize_init_warning_plugin_1.createAngularLocalizeInitWarningPlugin)(),
56
58
  (0, compiler_plugin_1.createCompilerPlugin)(
57
59
  // JS/TS options
58
60
  pluginOptions,
@@ -196,6 +198,7 @@ function createServerMainCodeBundleOptions(options, target, sourceFileCache, sty
196
198
  plugins: [
197
199
  (0, wasm_plugin_1.createWasmPlugin)({ allowAsync: zoneless, cache: loadResultCache }),
198
200
  (0, sourcemap_ignorelist_plugin_1.createSourcemapIgnorelistPlugin)(),
201
+ (0, angular_localize_init_warning_plugin_1.createAngularLocalizeInitWarningPlugin)(),
199
202
  (0, compiler_plugin_1.createCompilerPlugin)(
200
203
  // JS/TS options
201
204
  { ...pluginOptions, noopTypeScriptCompilation: true },
@@ -299,6 +302,7 @@ function createSsrEntryCodeBundleOptions(options, target, sourceFileCache, style
299
302
  supported: (0, utils_1.getFeatureSupport)(target, true),
300
303
  plugins: [
301
304
  (0, sourcemap_ignorelist_plugin_1.createSourcemapIgnorelistPlugin)(),
305
+ (0, angular_localize_init_warning_plugin_1.createAngularLocalizeInitWarningPlugin)(),
302
306
  (0, compiler_plugin_1.createCompilerPlugin)(
303
307
  // JS/TS options
304
308
  { ...pluginOptions, noopTypeScriptCompilation: true },
@@ -22,7 +22,10 @@ export interface RebuildState {
22
22
  componentStyleBundler: ComponentStylesheetBundler;
23
23
  codeBundleCache?: SourceFileCache;
24
24
  fileChanges: ChangedFiles;
25
- previousOutputHashes: Map<string, string>;
25
+ previousOutputInfo: Map<string, {
26
+ hash: string;
27
+ type: BuildOutputFileType;
28
+ }>;
26
29
  templateUpdates?: Map<string, string>;
27
30
  }
28
31
  export interface ExternalResultMetadata {
@@ -81,8 +84,11 @@ export declare class ExecutionResult {
81
84
  errors: (PartialMessage | Message)[];
82
85
  externalMetadata: ExternalResultMetadata | undefined;
83
86
  };
84
- get watchFiles(): string[];
87
+ get watchFiles(): Readonly<string[]>;
85
88
  createRebuildState(fileChanges: ChangedFiles): RebuildState;
86
- findChangedFiles(previousOutputHashes: Map<string, string>): Set<string>;
89
+ findChangedFiles(previousOutputHashes: Map<string, {
90
+ hash: string;
91
+ type: BuildOutputFileType;
92
+ }>): Set<string>;
87
93
  dispose(): Promise<void>;
88
94
  }