@nx/angular 19.8.0-canary.20240917-5b34ea5 → 19.8.0-canary.20240918-eb61254

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/angular",
3
- "version": "19.8.0-canary.20240917-5b34ea5",
3
+ "version": "19.8.0-canary.20240918-eb61254",
4
4
  "private": false,
5
5
  "description": "The Nx Plugin for Angular contains executors, generators, and utilities for managing Angular applications and libraries within an Nx workspace. It provides: \n\n- Integration with libraries such as Storybook, Jest, ESLint, Tailwind CSS, Playwright and Cypress. \n\n- Generators to help scaffold code quickly (like: Micro Frontends, Libraries, both internal to your codebase and publishable to npm) \n\n- Single Component Application Modules (SCAMs) \n\n- NgRx helpers. \n\n- Utilities for automatic workspace refactoring.",
6
6
  "repository": {
@@ -22,6 +22,7 @@
22
22
  "./executors.json": "./executors.json",
23
23
  "./generators": "./generators.js",
24
24
  "./executors": "./executors.js",
25
+ "./plugin": "./plugin.js",
25
26
  "./tailwind": "./tailwind.js",
26
27
  "./module-federation": "./module-federation/index.js",
27
28
  "./src/utils": "./src/utils/index.js",
@@ -79,14 +80,14 @@
79
80
  "webpack-merge": "^5.8.0",
80
81
  "webpack": "^5.88.0",
81
82
  "@module-federation/enhanced": "~0.6.0",
82
- "@nx/devkit": "19.8.0-canary.20240917-5b34ea5",
83
- "@nx/js": "19.8.0-canary.20240917-5b34ea5",
84
- "@nx/eslint": "19.8.0-canary.20240917-5b34ea5",
85
- "@nx/webpack": "19.8.0-canary.20240917-5b34ea5",
86
- "@nx/web": "19.8.0-canary.20240917-5b34ea5",
87
- "@nx/workspace": "19.8.0-canary.20240917-5b34ea5",
83
+ "@nx/devkit": "19.8.0-canary.20240918-eb61254",
84
+ "@nx/js": "19.8.0-canary.20240918-eb61254",
85
+ "@nx/eslint": "19.8.0-canary.20240918-eb61254",
86
+ "@nx/webpack": "19.8.0-canary.20240918-eb61254",
87
+ "@nx/web": "19.8.0-canary.20240918-eb61254",
88
+ "@nx/workspace": "19.8.0-canary.20240918-eb61254",
88
89
  "piscina": "^4.4.0",
89
- "@nrwl/angular": "19.8.0-canary.20240917-5b34ea5"
90
+ "@nrwl/angular": "19.8.0-canary.20240918-eb61254"
90
91
  },
91
92
  "peerDependencies": {
92
93
  "@angular-devkit/build-angular": ">= 16.0.0 < 19.0.0",
package/plugin.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { createNodesV2 } from './src/plugins/plugin';
package/plugin.js ADDED
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createNodesV2 = void 0;
4
+ var plugin_1 = require("./src/plugins/plugin");
5
+ Object.defineProperty(exports, "createNodesV2", { enumerable: true, get: function () { return plugin_1.createNodesV2; } });
@@ -2,10 +2,22 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.angularInitGenerator = angularInitGenerator;
4
4
  const devkit_1 = require("@nx/devkit");
5
+ const add_plugin_1 = require("@nx/devkit/src/utils/add-plugin");
5
6
  const version_utils_1 = require("../utils/version-utils");
7
+ const plugin_1 = require("../../plugins/plugin");
6
8
  async function angularInitGenerator(tree, options) {
7
9
  ignoreAngularCacheDirectory(tree);
8
10
  const installTask = installAngularDevkitCoreIfMissing(tree, options);
11
+ // For Angular inference plugin, we only want it during import since our
12
+ // generators do not use `angular.json`, and `nx init` should split
13
+ // `angular.json` into multiple `project.json` files -- as this is preferred
14
+ // by most folks we've talked to.
15
+ options.addPlugin ??= process.env.NX_RUNNING_NX_IMPORT === 'true';
16
+ if (options.addPlugin) {
17
+ await (0, add_plugin_1.addPlugin)(tree, await (0, devkit_1.createProjectGraphAsync)(), '@nx/angular/plugin', plugin_1.createNodesV2, {
18
+ targetNamePrefix: ['', 'angular:', 'angular-'],
19
+ }, options.updatePackageScripts);
20
+ }
9
21
  if (!options.skipFormat) {
10
22
  await (0, devkit_1.formatFiles)(tree);
11
23
  }
@@ -3,4 +3,7 @@ export interface Schema {
3
3
  skipInstall?: boolean;
4
4
  skipPackageJson?: boolean;
5
5
  keepExistingVersions?: boolean;
6
+ /* internal */
7
+ addPlugin?: boolean;
8
+ updatePackageScripts?: boolean;
6
9
  }
@@ -6,12 +6,14 @@ function addMfEnvToTargetDefaultInputs(tree) {
6
6
  const nxJson = (0, devkit_1.readNxJson)(tree);
7
7
  const webpackExecutor = '@nx/angular:webpack-browser';
8
8
  const mfEnvVar = 'NX_MF_DEV_REMOTES';
9
+ const inputs = [
10
+ ...(nxJson.namedInputs && 'production' in nxJson.namedInputs
11
+ ? ['production', '^production']
12
+ : ['default', '^default']),
13
+ ];
9
14
  nxJson.targetDefaults ??= {};
10
15
  nxJson.targetDefaults[webpackExecutor] ??= {};
11
- nxJson.targetDefaults[webpackExecutor].inputs ??= [
12
- 'production',
13
- '^production',
14
- ];
16
+ nxJson.targetDefaults[webpackExecutor].inputs ??= inputs;
15
17
  nxJson.targetDefaults[webpackExecutor].dependsOn ??= ['^build'];
16
18
  let mfEnvVarExists = false;
17
19
  for (const input of nxJson.targetDefaults[webpackExecutor].inputs) {
@@ -20,12 +20,18 @@ async function default_1(tree) {
20
20
  }
21
21
  const nxJson = (0, devkit_1.readNxJson)(tree);
22
22
  const nxMFDevRemotesEnvVar = 'NX_MF_DEV_REMOTES';
23
+ const inputs = [
24
+ ...(nxJson.namedInputs && 'production' in nxJson.namedInputs
25
+ ? ['production', '^production']
26
+ : ['default', '^default']),
27
+ { env: nxMFDevRemotesEnvVar },
28
+ ];
23
29
  if (!nxJson.targetDefaults ||
24
30
  !nxJson.targetDefaults?.['@nx/angular:webpack-browser']) {
25
31
  nxJson.targetDefaults ??= {};
26
32
  nxJson.targetDefaults['@nx/angular:webpack-browser'] = {
27
33
  cache: true,
28
- inputs: ['production', '^production', { env: nxMFDevRemotesEnvVar }],
34
+ inputs,
29
35
  dependsOn: ['^build'],
30
36
  };
31
37
  }
@@ -0,0 +1,19 @@
1
+ import { type CreateNodesV2 } from '@nx/devkit';
2
+ export interface AngularPluginOptions {
3
+ targetNamePrefix?: string;
4
+ }
5
+ type AngularTargetConfiguration = {
6
+ builder: string;
7
+ options?: Record<string, any>;
8
+ configurations?: Record<string, any>;
9
+ defaultConfiguration?: string;
10
+ };
11
+ export type AngularProjectConfiguration = {
12
+ projectType: 'application' | 'library';
13
+ root: string;
14
+ sourceRoot?: string;
15
+ architect?: Record<string, AngularTargetConfiguration>;
16
+ targets?: Record<string, AngularTargetConfiguration>;
17
+ };
18
+ export declare const createNodesV2: CreateNodesV2<AngularPluginOptions>;
19
+ export {};
@@ -0,0 +1,418 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createNodesV2 = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const devkit_1 = require("@nx/devkit");
6
+ const calculate_hash_for_create_nodes_1 = require("@nx/devkit/src/utils/calculate-hash-for-create-nodes");
7
+ const get_named_inputs_1 = require("@nx/devkit/src/utils/get-named-inputs");
8
+ const js_1 = require("@nx/js");
9
+ const node_fs_1 = require("node:fs");
10
+ const node_path_1 = require("node:path");
11
+ const posix = tslib_1.__importStar(require("node:path/posix"));
12
+ const devkit_internals_1 = require("nx/src/devkit-internals");
13
+ const cache_directory_1 = require("nx/src/utils/cache-directory");
14
+ const knownExecutors = {
15
+ appShell: new Set(['@angular-devkit/build-angular:app-shell']),
16
+ build: new Set([
17
+ '@angular-devkit/build-angular:application',
18
+ '@angular/build:application',
19
+ '@angular-devkit/build-angular:browser-esbuild',
20
+ '@angular-devkit/build-angular:browser',
21
+ '@angular-devkit/build-angular:ng-packagr',
22
+ ]),
23
+ devServer: new Set(['@angular-devkit/build-angular:dev-server']),
24
+ extractI18n: new Set(['@angular-devkit/build-angular:extract-i18n']),
25
+ prerender: new Set([
26
+ '@angular-devkit/build-angular:prerender',
27
+ '@nguniversal/builders:prerender',
28
+ ]),
29
+ server: new Set(['@angular-devkit/build-angular:server']),
30
+ serveSsr: new Set([
31
+ '@angular-devkit/build-angular:ssr-dev-server',
32
+ '@nguniversal/builders:ssr-dev-server',
33
+ ]),
34
+ test: new Set(['@angular-devkit/build-angular:karma']),
35
+ };
36
+ const pmc = (0, devkit_1.getPackageManagerCommand)();
37
+ function readProjectsCache(cachePath) {
38
+ return (0, node_fs_1.existsSync)(cachePath) ? (0, devkit_1.readJsonFile)(cachePath) : {};
39
+ }
40
+ function writeProjectsToCache(cachePath, results) {
41
+ (0, devkit_1.writeJsonFile)(cachePath, results);
42
+ }
43
+ exports.createNodesV2 = [
44
+ '**/angular.json',
45
+ async (configFiles, options, context) => {
46
+ const optionsHash = (0, devkit_internals_1.hashObject)(options);
47
+ const cachePath = (0, node_path_1.join)(cache_directory_1.workspaceDataDirectory, `angular-${optionsHash}.hash`);
48
+ const projectsCache = readProjectsCache(cachePath);
49
+ try {
50
+ return await (0, devkit_1.createNodesFromFiles)((configFile, options, context) => createNodesInternal(configFile, options, context, projectsCache), configFiles, options, context);
51
+ }
52
+ finally {
53
+ writeProjectsToCache(cachePath, projectsCache);
54
+ }
55
+ },
56
+ ];
57
+ async function createNodesInternal(configFilePath, options, context, projectsCache) {
58
+ const angularWorkspaceRoot = (0, node_path_1.dirname)(configFilePath);
59
+ // Do not create a project if package.json isn't there
60
+ const siblingFiles = (0, node_fs_1.readdirSync)((0, node_path_1.join)(context.workspaceRoot, angularWorkspaceRoot));
61
+ if (!siblingFiles.includes('package.json')) {
62
+ return {};
63
+ }
64
+ const hash = await (0, calculate_hash_for_create_nodes_1.calculateHashForCreateNodes)(angularWorkspaceRoot, options, context, [(0, js_1.getLockFileName)((0, devkit_1.detectPackageManager)(context.workspaceRoot))]);
65
+ projectsCache[hash] ??= await buildAngularProjects(configFilePath, options, angularWorkspaceRoot, context);
66
+ return { projects: projectsCache[hash] };
67
+ }
68
+ async function buildAngularProjects(configFilePath, options, angularWorkspaceRoot, context) {
69
+ const projects = {};
70
+ const absoluteConfigFilePath = (0, node_path_1.join)(context.workspaceRoot, configFilePath);
71
+ const angularJson = (0, devkit_1.readJsonFile)(absoluteConfigFilePath);
72
+ const appShellTargets = [];
73
+ const prerenderTargets = [];
74
+ for (const [projectName, project] of Object.entries(angularJson.projects ?? {})) {
75
+ const targets = {};
76
+ const projectTargets = getAngularJsonProjectTargets(project);
77
+ if (!projectTargets) {
78
+ continue;
79
+ }
80
+ const namedInputs = (0, get_named_inputs_1.getNamedInputs)(project.root, context);
81
+ for (const [angularTargetName, angularTarget] of Object.entries(projectTargets)) {
82
+ const nxTargetName = options?.targetNamePrefix
83
+ ? `${options.targetNamePrefix}${angularTargetName}`
84
+ : angularTargetName;
85
+ const externalDependencies = ['@angular/cli'];
86
+ targets[nxTargetName] = {
87
+ command:
88
+ // For targets that are also Angular CLI commands, infer the simplified form.
89
+ // Otherwise, use `ng run` to support non-command targets so that they will run.
90
+ angularTargetName === 'build' ||
91
+ angularTargetName === 'deploy' ||
92
+ angularTargetName === 'extract-i18n' ||
93
+ angularTargetName === 'e2e' ||
94
+ angularTargetName === 'lint' ||
95
+ angularTargetName === 'serve' ||
96
+ angularTargetName === 'test'
97
+ ? `ng ${angularTargetName}`
98
+ : `ng run ${projectName}:${angularTargetName}`,
99
+ options: { cwd: angularWorkspaceRoot },
100
+ metadata: {
101
+ technologies: ['angular'],
102
+ description: `Run the "${angularTargetName}" target for "${projectName}".`,
103
+ help: {
104
+ command: `${pmc.exec} ng run ${projectName}:${angularTargetName} --help`,
105
+ example: {},
106
+ },
107
+ },
108
+ };
109
+ if (knownExecutors.appShell.has(angularTarget.builder)) {
110
+ appShellTargets.push({ target: nxTargetName, project: projectName });
111
+ }
112
+ else if (knownExecutors.build.has(angularTarget.builder)) {
113
+ await updateBuildTarget(nxTargetName, targets[nxTargetName], angularTarget, context, angularWorkspaceRoot, project.root, namedInputs);
114
+ }
115
+ else if (knownExecutors.devServer.has(angularTarget.builder)) {
116
+ targets[nxTargetName].metadata.help.example.options = { port: 4201 };
117
+ }
118
+ else if (knownExecutors.extractI18n.has(angularTarget.builder)) {
119
+ targets[nxTargetName].metadata.help.example.options = {
120
+ format: 'json',
121
+ };
122
+ }
123
+ else if (knownExecutors.test.has(angularTarget.builder)) {
124
+ updateTestTarget(targets[nxTargetName], angularTarget, context, angularWorkspaceRoot, project.root, namedInputs, externalDependencies);
125
+ }
126
+ else if (knownExecutors.server.has(angularTarget.builder)) {
127
+ updateServerTarget(targets[nxTargetName], angularTarget, context, angularWorkspaceRoot, project.root, namedInputs);
128
+ }
129
+ else if (knownExecutors.serveSsr.has(angularTarget.builder)) {
130
+ targets[nxTargetName].metadata.help.example.options = { port: 4201 };
131
+ }
132
+ else if (knownExecutors.prerender.has(angularTarget.builder)) {
133
+ prerenderTargets.push({ target: nxTargetName, project: projectName });
134
+ }
135
+ if (targets[nxTargetName].inputs?.length) {
136
+ targets[nxTargetName].inputs.push({ externalDependencies });
137
+ }
138
+ if (angularTarget.configurations) {
139
+ for (const configurationName of Object.keys(angularTarget.configurations)) {
140
+ targets[nxTargetName].configurations = {
141
+ ...targets[nxTargetName].configurations,
142
+ [configurationName]: {
143
+ command: `ng run ${projectName}:${angularTargetName}:${configurationName}`,
144
+ },
145
+ };
146
+ }
147
+ }
148
+ if (angularTarget.defaultConfiguration) {
149
+ targets[nxTargetName].defaultConfiguration =
150
+ angularTarget.defaultConfiguration;
151
+ }
152
+ }
153
+ projects[projectName] = {
154
+ projectType: project.projectType,
155
+ root: posix.join(angularWorkspaceRoot, project.root),
156
+ sourceRoot: project.sourceRoot
157
+ ? posix.join(angularWorkspaceRoot, project.sourceRoot)
158
+ : undefined,
159
+ targets,
160
+ };
161
+ }
162
+ for (const { project, target } of appShellTargets) {
163
+ updateAppShellTarget(project, target, projects, angularJson, angularWorkspaceRoot, context);
164
+ }
165
+ for (const { project, target } of prerenderTargets) {
166
+ updatePrerenderTarget(project, target, projects, angularJson);
167
+ }
168
+ return Object.entries(projects).reduce((acc, [projectName, project]) => {
169
+ acc[project.root] = {
170
+ projectType: project.projectType,
171
+ sourceRoot: project.sourceRoot,
172
+ targets: project.targets,
173
+ };
174
+ return acc;
175
+ }, {});
176
+ }
177
+ function updateAppShellTarget(projectName, targetName, projects, angularJson, angularWorkspaceRoot, context) {
178
+ // it must exist since we collected it when processing it
179
+ const target = projects[projectName].targets[targetName];
180
+ target.metadata.help.example.options = { route: '/some/route' };
181
+ const { inputs, outputs } = getBrowserAndServerTargetInputsAndOutputs(projectName, targetName, projects, angularJson);
182
+ const outputIndexPath = getAngularJsonProjectTargets(angularJson.projects[projectName])[targetName].options?.outputIndexPath;
183
+ if (outputIndexPath) {
184
+ const fullOutputIndexPath = (0, node_path_1.join)(context.workspaceRoot, angularWorkspaceRoot, outputIndexPath);
185
+ outputs.push(getOutput(fullOutputIndexPath, context.workspaceRoot, angularWorkspaceRoot, angularJson.projects[projectName].root));
186
+ }
187
+ if (!outputs.length) {
188
+ // no outputs were identified for the build or server target, so we don't
189
+ // set any Nx cache options
190
+ return;
191
+ }
192
+ target.cache = true;
193
+ target.inputs = inputs;
194
+ target.outputs = outputs;
195
+ }
196
+ async function updateBuildTarget(targetName, target, angularTarget, context, angularWorkspaceRoot, projectRoot, namedInputs) {
197
+ target.dependsOn = [`^${targetName}`];
198
+ if (angularTarget.options?.outputPath) {
199
+ const fullOutputPath = (0, node_path_1.join)(context.workspaceRoot, angularWorkspaceRoot, angularTarget.options.outputPath);
200
+ target.outputs = [
201
+ getOutput(fullOutputPath, context.workspaceRoot, angularWorkspaceRoot, projectRoot),
202
+ ];
203
+ }
204
+ else if (angularTarget.builder === '@angular-devkit/build-angular:ng-packagr') {
205
+ const outputs = await getNgPackagrOutputs(angularTarget, angularWorkspaceRoot, projectRoot, context);
206
+ if (outputs.length) {
207
+ target.outputs = outputs;
208
+ }
209
+ }
210
+ if (target.outputs?.length) {
211
+ // make it cacheable if we were able to identify outputs
212
+ target.cache = true;
213
+ target.inputs =
214
+ 'production' in namedInputs
215
+ ? ['production', '^production']
216
+ : ['default', '^default'];
217
+ }
218
+ if (angularTarget.builder === '@angular-devkit/build-angular:ng-packagr') {
219
+ target.metadata.help.example.options = { watch: true };
220
+ }
221
+ else {
222
+ target.metadata.help.example.options = { localize: true };
223
+ }
224
+ }
225
+ function updateTestTarget(target, angularTarget, context, angularWorkspaceRoot, projectRoot, namedInputs, externalDependencies) {
226
+ target.cache = true;
227
+ target.inputs =
228
+ 'production' in namedInputs
229
+ ? ['default', '^production']
230
+ : ['default', '^default'];
231
+ target.outputs = getKarmaTargetOutputs(angularTarget, angularWorkspaceRoot, projectRoot, context);
232
+ externalDependencies.push('karma');
233
+ target.metadata.help.example.options = { codeCoverage: true };
234
+ }
235
+ function updateServerTarget(target, angularTarget, context, angularWorkspaceRoot, projectRoot, namedInputs) {
236
+ target.metadata.help.example.options = { localize: true };
237
+ if (!angularTarget.options?.outputPath) {
238
+ // only make it cacheable if we were able to identify outputs
239
+ return;
240
+ }
241
+ target.cache = true;
242
+ target.inputs =
243
+ 'production' in namedInputs
244
+ ? ['production', '^production']
245
+ : ['default', '^default'];
246
+ const fullOutputPath = (0, node_path_1.join)(context.workspaceRoot, angularWorkspaceRoot, angularTarget.options.outputPath);
247
+ target.outputs = [
248
+ getOutput(fullOutputPath, context.workspaceRoot, angularWorkspaceRoot, projectRoot),
249
+ ];
250
+ }
251
+ function updatePrerenderTarget(projectName, targetName, projects, angularJson) {
252
+ // it must exist since we collected it when processing it
253
+ const target = projects[projectName].targets[targetName];
254
+ target.metadata.help.example.options =
255
+ getAngularJsonProjectTargets(angularJson.projects[projectName])[targetName]
256
+ .builder === '@angular-devkit/build-angular:prerender'
257
+ ? { discoverRoutes: false }
258
+ : { guessRoutes: false };
259
+ const { inputs, outputs } = getBrowserAndServerTargetInputsAndOutputs(projectName, targetName, projects, angularJson);
260
+ if (!outputs.length) {
261
+ // no outputs were identified for the build or server target, so we don't
262
+ // set any Nx cache options
263
+ return;
264
+ }
265
+ target.cache = true;
266
+ target.inputs = inputs;
267
+ target.outputs = outputs;
268
+ }
269
+ async function getNgPackagrOutputs(target, angularWorkspaceRoot, projectRoot, context) {
270
+ let ngPackageJsonPath = (0, node_path_1.join)(context.workspaceRoot, angularWorkspaceRoot, target.options.project);
271
+ const readConfig = async (configPath) => {
272
+ if (!(0, node_fs_1.existsSync)(configPath)) {
273
+ return undefined;
274
+ }
275
+ try {
276
+ if (configPath.endsWith('.js')) {
277
+ const result = await import(configPath);
278
+ return result['default'] ?? result;
279
+ }
280
+ return (0, devkit_1.readJsonFile)(configPath);
281
+ }
282
+ catch { }
283
+ return undefined;
284
+ };
285
+ let ngPackageJson;
286
+ let basePath;
287
+ if ((0, node_fs_1.statSync)(ngPackageJsonPath).isDirectory()) {
288
+ basePath = ngPackageJsonPath;
289
+ ngPackageJson = await readConfig((0, node_path_1.join)(ngPackageJsonPath, 'ng-package.json'));
290
+ if (!ngPackageJson) {
291
+ ngPackageJson = await readConfig((0, node_path_1.join)(ngPackageJsonPath, 'ng-package.js'));
292
+ }
293
+ }
294
+ else {
295
+ basePath = (0, node_path_1.dirname)(ngPackageJsonPath);
296
+ ngPackageJson = await readConfig(ngPackageJsonPath);
297
+ }
298
+ if (!ngPackageJson) {
299
+ return [];
300
+ }
301
+ const destination = ngPackageJson.dest
302
+ ? (0, node_path_1.join)(basePath, ngPackageJson.dest)
303
+ : (0, node_path_1.join)(basePath, 'dist');
304
+ return [
305
+ getOutput(destination, context.workspaceRoot, angularWorkspaceRoot, projectRoot),
306
+ ];
307
+ }
308
+ function getKarmaTargetOutputs(target, angularWorkspaceRoot, projectRoot, context) {
309
+ const defaultOutput = posix.join('{workspaceRoot}', angularWorkspaceRoot, 'coverage/{projectName}');
310
+ if (!target.options?.karmaConfig) {
311
+ return [defaultOutput];
312
+ }
313
+ try {
314
+ const { parseConfig } = require('karma/lib/config');
315
+ const karmaConfigPath = (0, node_path_1.join)(context.workspaceRoot, angularWorkspaceRoot, projectRoot, target.options.karmaConfig);
316
+ const config = parseConfig(karmaConfigPath);
317
+ if (config.coverageReporter.dir) {
318
+ return [
319
+ getOutput(config.coverageReporter.dir, context.workspaceRoot, angularWorkspaceRoot, projectRoot),
320
+ ];
321
+ }
322
+ }
323
+ catch {
324
+ // we silently ignore any error here and fall back to the default output
325
+ }
326
+ return [defaultOutput];
327
+ }
328
+ function getBrowserAndServerTargetInputsAndOutputs(projectName, targetName, projects, angularJson) {
329
+ const { browserTarget, serverTarget } = extractBrowserAndServerTargets(angularJson, projectName, targetName);
330
+ if (!browserTarget || !serverTarget) {
331
+ // if any of these are missing, the target is invalid so we return empty values
332
+ return { inputs: [], outputs: [] };
333
+ }
334
+ const browserTargetInputs = projects[browserTarget.project]?.targets?.[browserTarget.target]?.inputs ??
335
+ [];
336
+ const serverTargetInputs = projects[serverTarget.project]?.targets?.[serverTarget.target]?.inputs ??
337
+ [];
338
+ const browserTargetOutputs = projects[browserTarget.project]?.targets?.[browserTarget.target]?.outputs ??
339
+ [];
340
+ const serverTargetOutputs = projects[serverTarget.project]?.targets?.[serverTarget.target]?.outputs ??
341
+ [];
342
+ return {
343
+ inputs: mergeInputs(...browserTargetInputs, ...serverTargetInputs),
344
+ outputs: Array.from(new Set([...browserTargetOutputs, ...serverTargetOutputs])),
345
+ };
346
+ }
347
+ function extractBrowserAndServerTargets(angularJson, projectName, targetName) {
348
+ let browserTarget;
349
+ let serverTarget;
350
+ try {
351
+ const targets = getAngularJsonProjectTargets(angularJson.projects[projectName]);
352
+ const target = targets[targetName];
353
+ let browserTargetSpecifier = target.options?.browserTarget;
354
+ if (!browserTargetSpecifier) {
355
+ const configuration = Object.values(target.configurations ?? {}).find((config) => !!config.browserTarget);
356
+ browserTargetSpecifier = configuration?.browserTarget;
357
+ }
358
+ if (browserTargetSpecifier) {
359
+ browserTarget = targetFromTargetString(browserTargetSpecifier, projectName, targetName);
360
+ }
361
+ let serverTargetSpecifier = target.options?.serverTarget;
362
+ if (!serverTargetSpecifier) {
363
+ serverTargetSpecifier = Object.values(target.configurations ?? {}).find((config) => !!config.serverTarget)?.serverTarget;
364
+ }
365
+ if (serverTargetSpecifier) {
366
+ serverTarget = targetFromTargetString(serverTargetSpecifier, projectName, targetName);
367
+ }
368
+ }
369
+ catch { }
370
+ return { browserTarget: browserTarget, serverTarget };
371
+ }
372
+ function mergeInputs(...inputs) {
373
+ const stringInputs = new Set();
374
+ const externalDependencies = new Set();
375
+ for (const input of inputs) {
376
+ if (typeof input === 'string') {
377
+ stringInputs.add(input);
378
+ }
379
+ else if ('externalDependencies' in input) {
380
+ // we only infer external dependencies, so we don't need to handle the other input definitions
381
+ for (const externalDependency of input.externalDependencies) {
382
+ externalDependencies.add(externalDependency);
383
+ }
384
+ }
385
+ }
386
+ return [
387
+ ...stringInputs,
388
+ ...(externalDependencies.size
389
+ ? [{ externalDependencies: Array.from(externalDependencies) }]
390
+ : []),
391
+ ];
392
+ }
393
+ // angular support abbreviated target specifiers, this is adapter from:
394
+ // https://github.com/angular/angular-cli/blob/7d9ce246a33c60ec96eb4bf99520f5475716a910/packages/angular_devkit/architect/src/api.ts#L336
395
+ function targetFromTargetString(specifier, abbreviatedProjectName, abbreviatedTargetName) {
396
+ const tuple = specifier.split(':', 3);
397
+ if (tuple.length < 2) {
398
+ // invalid target, ignore
399
+ return undefined;
400
+ }
401
+ // we only care about project and target
402
+ return {
403
+ project: tuple[0] || abbreviatedProjectName || '',
404
+ target: tuple[1] || abbreviatedTargetName || '',
405
+ };
406
+ }
407
+ function getOutput(path, workspaceRoot, angularWorkspaceRoot, projectRoot) {
408
+ const relativePath = (0, node_path_1.relative)((0, node_path_1.join)(workspaceRoot, angularWorkspaceRoot, projectRoot), path);
409
+ if (relativePath.startsWith('..')) {
410
+ return posix.join('{workspaceRoot}', (0, node_path_1.join)(angularWorkspaceRoot, projectRoot, relativePath));
411
+ }
412
+ else {
413
+ return posix.join('{projectRoot}', relativePath);
414
+ }
415
+ }
416
+ function getAngularJsonProjectTargets(project) {
417
+ return project.architect ?? project.targets;
418
+ }