@angular/build 19.1.0-next.1 → 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 +18 -12
  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 +36 -3
  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 +103 -76
  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 +6 -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 +20 -4
  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/environment-options.js +1 -1
  42. package/src/utils/normalize-cache.js +1 -1
  43. package/src/utils/server-rendering/fetch-patch.js +2 -2
@@ -103,14 +103,14 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
103
103
  // https://nodejs.org/api/process.html#processsetsourcemapsenabledval
104
104
  process.setSourceMapsEnabled(true);
105
105
  }
106
- // Enable to support component style hot reloading (`NG_HMR_CSTYLES=0` can be used to disable selectively)
106
+ // Enable to support link-based component style hot reloading (`NG_HMR_CSTYLES=0` can be used to disable selectively)
107
107
  browserOptions.externalRuntimeStyles =
108
108
  serverOptions.liveReload && serverOptions.hmr && environment_options_1.useComponentStyleHmr;
109
- // Enable to support component template hot replacement (`NG_HMR_TEMPLATE=1` can be used to enable)
110
- browserOptions.templateUpdates = !!serverOptions.liveReload && environment_options_1.useComponentTemplateHmr;
111
- if (browserOptions.templateUpdates) {
112
- context.logger.warn('Experimental support for component template hot replacement has been enabled via the "NG_HMR_TEMPLATE" environment variable.');
113
- }
109
+ // Enable to support component template hot replacement (`NG_HMR_TEMPLATE=0` can be used to disable selectively)
110
+ // This will also replace file-based/inline styles as code if external runtime styles are not enabled.
111
+ browserOptions.templateUpdates =
112
+ serverOptions.liveReload && serverOptions.hmr && environment_options_1.useComponentTemplateHmr;
113
+ browserOptions.incrementalResults = true;
114
114
  // Setup the prebundling transformer that will be shared across Vite prebundling requests
115
115
  const prebundleTransformer = new internal_1.JavaScriptTransformer(
116
116
  // Always enable JIT linking to support applications built with and without AOT.
@@ -180,23 +180,49 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
180
180
  : baseHref;
181
181
  }
182
182
  assetFiles.clear();
183
- 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;
184
187
  if (file.origin === 'disk') {
185
188
  assetFiles.set('/' + normalizePath(outputPath), normalizePath(file.inputPath));
189
+ continue;
186
190
  }
191
+ updateResultRecord(outputPath, file, normalizePath, htmlIndexPath, generatedFiles, componentStyles,
192
+ // The initial build will not yet have a server setup
193
+ !server);
194
+ }
195
+ // Invalidate SSR module graph to ensure that only new rebuild is used and not stale component updates
196
+ if (server && browserOptions.ssr && templateUpdates.size > 0) {
197
+ server.moduleGraph.invalidateAll();
187
198
  }
188
199
  // Clear stale template updates on code rebuilds
189
200
  templateUpdates.clear();
190
- // Analyze result files for changes
191
- analyzeResultFiles(normalizePath, htmlIndexPath, result.files, generatedFiles, componentStyles);
192
201
  break;
193
202
  case results_1.ResultKind.Incremental:
194
203
  (0, node_assert_1.default)(server, 'Builder must provide an initial full build before incremental results.');
195
- // 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
+ }
196
215
  break;
197
216
  case results_1.ResultKind.ComponentUpdate:
198
217
  (0, node_assert_1.default)(serverOptions.hmr, 'Component updates are only supported with HMR enabled.');
199
218
  (0, node_assert_1.default)(server, 'Builder must provide an initial full build before component update results.');
219
+ // Invalidate SSR module graph to ensure that new component updates are used
220
+ // TODO: Use fine-grained invalidation of only the component update modules
221
+ if (browserOptions.ssr) {
222
+ server.moduleGraph.invalidateAll();
223
+ const { ɵresetCompiledComponents } = (await server.ssrLoadModule('/main.server.mjs'));
224
+ ɵresetCompiledComponents();
225
+ }
200
226
  for (const componentUpdate of result.updates) {
201
227
  if (componentUpdate.type === 'template') {
202
228
  templateUpdates.set(componentUpdate.id, componentUpdate.content);
@@ -276,7 +302,7 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
276
302
  });
277
303
  }
278
304
  // Setup server and start listening
279
- 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);
280
306
  server = await createServer(serverConfiguration);
281
307
  await server.listen();
282
308
  const urls = server.resolvedUrls;
@@ -315,11 +341,12 @@ async function handleUpdate(normalizePath, generatedFiles, server, serverOptions
315
341
  const updatedFiles = [];
316
342
  let destroyAngularServerAppCalled = false;
317
343
  // Invalidate any updated files
318
- for (const [file, { updated, type }] of generatedFiles) {
319
- if (!updated) {
344
+ for (const [file, record] of generatedFiles) {
345
+ if (!record.updated) {
320
346
  continue;
321
347
  }
322
- if (type === internal_1.BuildOutputFileType.ServerApplication && !destroyAngularServerAppCalled) {
348
+ record.updated = false;
349
+ if (record.type === internal_1.BuildOutputFileType.ServerApplication && !destroyAngularServerAppCalled) {
323
350
  // Clear the server app cache
324
351
  // This must be done before module invalidation.
325
352
  const { ɵdestroyAngularServerApp } = (await server.ssrLoadModule('/main.server.mjs'));
@@ -392,79 +419,71 @@ async function handleUpdate(normalizePath, generatedFiles, server, serverOptions
392
419
  logger.info('Page reload sent to client(s).');
393
420
  }
394
421
  }
395
- function analyzeResultFiles(normalizePath, htmlIndexPath, resultFiles, generatedFiles, componentStyles) {
396
- const seen = new Set(['/index.html']);
397
- for (const [outputPath, file] of Object.entries(resultFiles)) {
398
- if (file.origin === 'disk') {
399
- continue;
400
- }
401
- let filePath;
402
- if (outputPath === htmlIndexPath) {
403
- // Convert custom index output path to standard index path for dev-server usage.
404
- // This mimics the Webpack dev-server behavior.
405
- filePath = '/index.html';
406
- }
407
- else {
408
- filePath = '/' + normalizePath(outputPath);
409
- }
410
- seen.add(filePath);
411
- const servable = file.type === internal_1.BuildOutputFileType.Browser || file.type === internal_1.BuildOutputFileType.Media;
412
- // Skip analysis of sourcemaps
413
- if (filePath.endsWith('.map')) {
414
- generatedFiles.set(filePath, {
415
- contents: file.contents,
416
- servable,
417
- size: file.contents.byteLength,
418
- hash: file.hash,
419
- type: file.type,
420
- updated: false,
421
- });
422
- continue;
423
- }
424
- const existingRecord = generatedFiles.get(filePath);
425
- if (existingRecord &&
426
- existingRecord.size === file.contents.byteLength &&
427
- existingRecord.hash === file.hash) {
428
- // Same file
429
- existingRecord.updated = false;
430
- continue;
431
- }
432
- // 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')) {
433
438
  generatedFiles.set(filePath, {
434
439
  contents: file.contents,
440
+ servable,
435
441
  size: file.contents.byteLength,
436
442
  hash: file.hash,
437
- updated: true,
438
443
  type: file.type,
439
- servable,
444
+ updated: false,
440
445
  });
441
- // Record any external component styles
442
- if (filePath.endsWith('.css') && /^\/[a-f0-9]{64}\.css$/.test(filePath)) {
443
- const componentStyle = componentStyles.get(filePath);
444
- if (componentStyle) {
445
- componentStyle.rawContent = file.contents;
446
- }
447
- else {
448
- componentStyles.set(filePath, {
449
- rawContent: file.contents,
450
- });
451
- }
452
- }
446
+ return;
453
447
  }
454
- // Clear stale output files
455
- for (const file of generatedFiles.keys()) {
456
- if (!seen.has(file)) {
457
- generatedFiles.delete(file);
458
- 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
+ });
459
468
  }
460
469
  }
461
470
  }
462
- 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) {
463
472
  const proxy = await (0, utils_2.loadProxyConfiguration)(serverOptions.workspaceRoot, serverOptions.proxyConfig);
464
473
  // dynamically import Vite for ESM compatibility
465
474
  const { normalizePath } = await (0, load_esm_1.loadEsmModule)('vite');
466
475
  // Path will not exist on disk and only used to provide separate path for Vite requests
467
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
+ }
468
487
  const cacheDir = (0, node_path_1.join)(serverOptions.cacheOptions.path, serverOptions.buildTarget.project, 'vite');
469
488
  const configuration = {
470
489
  configFile: false,
@@ -495,7 +514,7 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
495
514
  },
496
515
  server: {
497
516
  warmup: {
498
- ssrFiles: ['./main.server.mjs', './server.mjs'],
517
+ ssrFiles,
499
518
  },
500
519
  port: serverOptions.port,
501
520
  strictPort: true,
@@ -504,7 +523,14 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
504
523
  headers: serverOptions.headers,
505
524
  // Disable the websocket if live reload is disabled (false/undefined are the only valid values)
506
525
  ws: serverOptions.liveReload === false && serverOptions.hmr === false ? false : undefined,
507
- proxy,
526
+ // When server-side rendering (SSR) is enabled togather with SSL and Express is being used,
527
+ // we must configure Vite to use HTTP/1.1.
528
+ // This is necessary because Express does not support HTTP/2.
529
+ // We achieve this by defining an empty proxy.
530
+ // See: https://github.com/vitejs/vite/blob/c4b532cc900bf988073583511f57bd581755d5e3/packages/vite/src/node/http.ts#L106
531
+ proxy: serverOptions.ssl && ssrMode === plugins_1.ServerSsrMode.ExternalSsrMiddleware
532
+ ? (proxy ?? {})
533
+ : proxy,
508
534
  cors: {
509
535
  // Allow preflight requests to be proxied.
510
536
  preflightContinue: true,
@@ -540,6 +566,7 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
540
566
  target,
541
567
  loader: prebundleLoaderExtensions,
542
568
  thirdPartySourcemaps,
569
+ define,
543
570
  }),
544
571
  },
545
572
  plugins: [
@@ -577,12 +604,13 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
577
604
  zoneless,
578
605
  loader: prebundleLoaderExtensions,
579
606
  thirdPartySourcemaps,
607
+ define,
580
608
  }),
581
609
  };
582
610
  if (serverOptions.ssl) {
583
611
  if (serverOptions.sslCert && serverOptions.sslKey) {
612
+ configuration.server ??= {};
584
613
  // server configuration is defined above
585
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
586
614
  configuration.server.https = {
587
615
  cert: await (0, promises_1.readFile)(serverOptions.sslCert),
588
616
  key: await (0, promises_1.readFile)(serverOptions.sslKey),
@@ -590,7 +618,6 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
590
618
  }
591
619
  else {
592
620
  const { default: basicSslPlugin } = await Promise.resolve().then(() => __importStar(require('@vitejs/plugin-basic-ssl')));
593
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
594
621
  configuration.plugins ??= [];
595
622
  configuration.plugins.push(basicSslPlugin());
596
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
+ }