@schematics/angular 17.3.0 → 18.0.0-next.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.
@@ -6,34 +6,13 @@
6
6
  * Use of this source code is governed by an MIT-style license that can be
7
7
  * found in the LICENSE file at https://angular.io/license
8
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 (mod) {
26
- if (mod && mod.__esModule) return mod;
27
- var result = {};
28
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
29
- __setModuleDefault(result, mod);
30
- return result;
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
31
11
  };
32
12
  Object.defineProperty(exports, "__esModule", { value: true });
33
- const core_1 = require("@angular-devkit/core");
34
13
  const schematics_1 = require("@angular-devkit/schematics");
35
- const standalone_1 = require("../private/standalone");
36
- const ts = __importStar(require("../third_party/github.com/Microsoft/TypeScript/lib/typescript"));
14
+ const posix_1 = require("node:path/posix");
15
+ const typescript_1 = __importDefault(require("../third_party/github.com/Microsoft/TypeScript/lib/typescript"));
37
16
  const ast_utils_1 = require("../utility/ast-utils");
38
17
  const change_1 = require("../utility/change");
39
18
  const ng_ast_utils_1 = require("../utility/ng-ast-utils");
@@ -43,18 +22,18 @@ const workspace_models_1 = require("../utility/workspace-models");
43
22
  const APP_SHELL_ROUTE = 'shell';
44
23
  function getSourceFile(host, path) {
45
24
  const content = host.readText(path);
46
- const source = ts.createSourceFile(path, content, ts.ScriptTarget.Latest, true);
25
+ const source = typescript_1.default.createSourceFile(path, content, typescript_1.default.ScriptTarget.Latest, true);
47
26
  return source;
48
27
  }
49
28
  function getServerModulePath(host, sourceRoot, mainPath) {
50
- const mainSource = getSourceFile(host, (0, core_1.join)((0, core_1.normalize)(sourceRoot), mainPath));
29
+ const mainSource = getSourceFile(host, (0, posix_1.join)(sourceRoot, mainPath));
51
30
  const allNodes = (0, ast_utils_1.getSourceNodes)(mainSource);
52
- const expNode = allNodes.find((node) => ts.isExportDeclaration(node));
31
+ const expNode = allNodes.find((node) => typescript_1.default.isExportDeclaration(node));
53
32
  if (!expNode) {
54
33
  return null;
55
34
  }
56
35
  const relativePath = expNode.moduleSpecifier;
57
- const modulePath = (0, core_1.normalize)(`/${sourceRoot}/${relativePath.text}.ts`);
36
+ const modulePath = (0, posix_1.join)(sourceRoot, `${relativePath.text}.ts`);
58
37
  return modulePath;
59
38
  }
60
39
  function getComponentTemplateInfo(host, componentPath) {
@@ -72,8 +51,8 @@ function getComponentTemplate(host, compPath, tmplInfo) {
72
51
  }
73
52
  else if (tmplInfo.templateUrlProp) {
74
53
  const templateUrl = tmplInfo.templateUrlProp.initializer.text;
75
- const dir = (0, core_1.dirname)((0, core_1.normalize)(compPath));
76
- const templatePath = (0, core_1.join)(dir, templateUrl);
54
+ const dir = (0, posix_1.dirname)(compPath);
55
+ const templatePath = (0, posix_1.join)(dir, templateUrl);
77
56
  try {
78
57
  template = host.readText(templatePath);
79
58
  }
@@ -82,16 +61,15 @@ function getComponentTemplate(host, compPath, tmplInfo) {
82
61
  return template;
83
62
  }
84
63
  function getBootstrapComponentPath(host, mainPath) {
85
- const mainSource = getSourceFile(host, mainPath);
86
- const bootstrapAppCall = (0, standalone_1.findBootstrapApplicationCall)(mainSource);
87
64
  let bootstrappingFilePath;
88
65
  let bootstrappingSource;
89
66
  let componentName;
90
- if (bootstrapAppCall) {
67
+ if ((0, ng_ast_utils_1.isStandaloneApp)(host, mainPath)) {
91
68
  // Standalone Application
92
- componentName = bootstrapAppCall.arguments[0].getText();
69
+ const bootstrapCall = (0, util_1.findBootstrapApplicationCall)(host, mainPath);
70
+ componentName = bootstrapCall.arguments[0].getText();
93
71
  bootstrappingFilePath = mainPath;
94
- bootstrappingSource = mainSource;
72
+ bootstrappingSource = getSourceFile(host, mainPath);
95
73
  }
96
74
  else {
97
75
  // NgModule Application
@@ -105,15 +83,15 @@ function getBootstrapComponentPath(host, mainPath) {
105
83
  bootstrappingFilePath = modulePath;
106
84
  }
107
85
  const componentRelativeFilePath = (0, ast_utils_1.getSourceNodes)(bootstrappingSource)
108
- .filter(ts.isImportDeclaration)
86
+ .filter(typescript_1.default.isImportDeclaration)
109
87
  .filter((imp) => {
110
- return (0, ast_utils_1.findNode)(imp, ts.SyntaxKind.Identifier, componentName);
88
+ return (0, ast_utils_1.findNode)(imp, typescript_1.default.SyntaxKind.Identifier, componentName);
111
89
  })
112
90
  .map((imp) => {
113
91
  const pathStringLiteral = imp.moduleSpecifier;
114
92
  return pathStringLiteral.text;
115
93
  })[0];
116
- return (0, core_1.join)((0, core_1.dirname)((0, core_1.normalize)(bootstrappingFilePath)), componentRelativeFilePath + '.ts');
94
+ return (0, posix_1.join)((0, posix_1.dirname)(bootstrappingFilePath), componentRelativeFilePath + '.ts');
117
95
  }
118
96
  // end helper functions.
119
97
  function validateProject(mainPath) {
@@ -193,12 +171,12 @@ function addRouterModule(mainPath) {
193
171
  }
194
172
  function getMetadataProperty(metadata, propertyName) {
195
173
  const properties = metadata.properties;
196
- const property = properties.filter(ts.isPropertyAssignment).filter((prop) => {
174
+ const property = properties.filter(typescript_1.default.isPropertyAssignment).filter((prop) => {
197
175
  const name = prop.name;
198
176
  switch (name.kind) {
199
- case ts.SyntaxKind.Identifier:
177
+ case typescript_1.default.SyntaxKind.Identifier:
200
178
  return name.getText() === propertyName;
201
- case ts.SyntaxKind.StringLiteral:
179
+ case typescript_1.default.SyntaxKind.StringLiteral:
202
180
  return name.text === propertyName;
203
181
  }
204
182
  return false;
@@ -225,7 +203,7 @@ function addServerRoutes(options) {
225
203
  (0, change_1.applyToUpdateRecorder)(recorder, [routesChange]);
226
204
  }
227
205
  const imports = (0, ast_utils_1.getSourceNodes)(moduleSource)
228
- .filter((node) => node.kind === ts.SyntaxKind.ImportDeclaration)
206
+ .filter((node) => node.kind === typescript_1.default.SyntaxKind.ImportDeclaration)
229
207
  .sort((a, b) => a.getStart() - b.getStart());
230
208
  const insertPosition = imports[imports.length - 1].getEnd();
231
209
  const routeText = `\n\nconst routes: Routes = [ { path: '${APP_SHELL_ROUTE}', component: AppShellComponent }];`;
@@ -254,7 +232,7 @@ function addStandaloneServerRoute(options) {
254
232
  if (!project) {
255
233
  throw new schematics_1.SchematicsException(`Project name "${options.project}" doesn't not exist.`);
256
234
  }
257
- const configFilePath = (0, core_1.join)((0, core_1.normalize)(project.sourceRoot ?? 'src'), 'app/app.config.server.ts');
235
+ const configFilePath = (0, posix_1.join)(project.sourceRoot ?? 'src', 'app/app.config.server.ts');
258
236
  if (!host.exists(configFilePath)) {
259
237
  throw new schematics_1.SchematicsException(`Cannot find "${configFilePath}".`);
260
238
  }
@@ -268,28 +246,28 @@ function addStandaloneServerRoute(options) {
268
246
  }
269
247
  }
270
248
  configSourceFile = getSourceFile(host, configFilePath);
271
- const providersLiteral = (0, ast_utils_1.findNodes)(configSourceFile, ts.isPropertyAssignment).find((n) => ts.isArrayLiteralExpression(n.initializer) && n.name.getText() === 'providers')?.initializer;
249
+ const providersLiteral = (0, ast_utils_1.findNodes)(configSourceFile, typescript_1.default.isPropertyAssignment).find((n) => typescript_1.default.isArrayLiteralExpression(n.initializer) && n.name.getText() === 'providers')?.initializer;
272
250
  if (!providersLiteral) {
273
251
  throw new schematics_1.SchematicsException(`Cannot find the "providers" configuration in "${configFilePath}".`);
274
252
  }
275
253
  // Add route to providers literal.
276
- const newProvidersLiteral = ts.factory.updateArrayLiteralExpression(providersLiteral, [
254
+ const newProvidersLiteral = typescript_1.default.factory.updateArrayLiteralExpression(providersLiteral, [
277
255
  ...providersLiteral.elements,
278
- ts.factory.createObjectLiteralExpression([
279
- ts.factory.createPropertyAssignment('provide', ts.factory.createIdentifier('ROUTES')),
280
- ts.factory.createPropertyAssignment('multi', ts.factory.createIdentifier('true')),
281
- ts.factory.createPropertyAssignment('useValue', ts.factory.createArrayLiteralExpression([
282
- ts.factory.createObjectLiteralExpression([
283
- ts.factory.createPropertyAssignment('path', ts.factory.createIdentifier(`'${APP_SHELL_ROUTE}'`)),
284
- ts.factory.createPropertyAssignment('component', ts.factory.createIdentifier('AppShellComponent')),
256
+ typescript_1.default.factory.createObjectLiteralExpression([
257
+ typescript_1.default.factory.createPropertyAssignment('provide', typescript_1.default.factory.createIdentifier('ROUTES')),
258
+ typescript_1.default.factory.createPropertyAssignment('multi', typescript_1.default.factory.createIdentifier('true')),
259
+ typescript_1.default.factory.createPropertyAssignment('useValue', typescript_1.default.factory.createArrayLiteralExpression([
260
+ typescript_1.default.factory.createObjectLiteralExpression([
261
+ typescript_1.default.factory.createPropertyAssignment('path', typescript_1.default.factory.createIdentifier(`'${APP_SHELL_ROUTE}'`)),
262
+ typescript_1.default.factory.createPropertyAssignment('component', typescript_1.default.factory.createIdentifier('AppShellComponent')),
285
263
  ], true),
286
264
  ], true)),
287
265
  ], true),
288
266
  ]);
289
267
  const recorder = host.beginUpdate(configFilePath);
290
268
  recorder.remove(providersLiteral.getStart(), providersLiteral.getWidth());
291
- const printer = ts.createPrinter();
292
- recorder.insertRight(providersLiteral.getStart(), printer.printNode(ts.EmitHint.Unspecified, newProvidersLiteral, configSourceFile));
269
+ const printer = typescript_1.default.createPrinter();
270
+ recorder.insertRight(providersLiteral.getStart(), printer.printNode(typescript_1.default.EmitHint.Unspecified, newProvidersLiteral, configSourceFile));
293
271
  // Add AppShellComponent import
294
272
  const appShellImportChange = (0, ast_utils_1.insertImport)(configSourceFile, configFilePath, 'AppShellComponent', './app-shell/app-shell.component');
295
273
  (0, change_1.applyToUpdateRecorder)(recorder, [appShellImportChange]);
@@ -59,18 +59,21 @@
59
59
  "message": "Which stylesheet format would you like to use?",
60
60
  "type": "list",
61
61
  "items": [
62
- { "value": "css", "label": "CSS" },
62
+ {
63
+ "value": "css",
64
+ "label": "CSS [ https://developer.mozilla.org/docs/Web/CSS ]"
65
+ },
63
66
  {
64
67
  "value": "scss",
65
- "label": "SCSS [ https://sass-lang.com/documentation/syntax#scss ]"
68
+ "label": "Sass (SCSS) [ https://sass-lang.com/documentation/syntax#scss ]"
66
69
  },
67
70
  {
68
71
  "value": "sass",
69
- "label": "Sass [ https://sass-lang.com/documentation/syntax#the-indented-syntax ]"
72
+ "label": "Sass (Indented) [ https://sass-lang.com/documentation/syntax#the-indented-syntax ]"
70
73
  },
71
74
  {
72
75
  "value": "less",
73
- "label": "Less [ http://lesscss.org ]"
76
+ "label": "Less [ http://lesscss.org ]"
74
77
  }
75
78
  ]
76
79
  },
@@ -1,6 +1,5 @@
1
1
  import { Injectable } from '@angular/core';
2
2
  import { <%= routerImports %> } from '@angular/router';
3
- import { Observable } from 'rxjs';
4
3
 
5
4
  @Injectable({
6
5
  providedIn: 'root'
@@ -8,24 +7,24 @@ import { Observable } from 'rxjs';
8
7
  export class <%= classify(name) %>Guard implements <%= implementations %> {
9
8
  <% if (implements.includes('CanActivate')) { %>canActivate(
10
9
  route: ActivatedRouteSnapshot,
11
- state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
10
+ state: RouterStateSnapshot): MaybeAsync<GuardResult> {
12
11
  return true;
13
12
  }
14
13
  <% } %><% if (implements.includes('CanActivateChild')) { %>canActivateChild(
15
14
  childRoute: ActivatedRouteSnapshot,
16
- state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
15
+ state: RouterStateSnapshot): MaybeAsync<GuardResult> {
17
16
  return true;
18
17
  }
19
18
  <% } %><% if (implements.includes('CanDeactivate')) { %>canDeactivate(
20
19
  component: unknown,
21
20
  currentRoute: ActivatedRouteSnapshot,
22
21
  currentState: RouterStateSnapshot,
23
- nextState?: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
22
+ nextState?: RouterStateSnapshot): MaybeAsync<GuardResult> {
24
23
  return true;
25
24
  }
26
25
  <% } %><% if (implements.includes('CanMatch')) { %>canMatch(
27
26
  route: Route,
28
- segments: UrlSegment[]): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
27
+ segments: UrlSegment[]): MaybeAsync<GuardResult> {
29
28
  return true;
30
29
  }<% } %>
31
30
  }
package/guard/index.js CHANGED
@@ -26,7 +26,7 @@ function default_1(options) {
26
26
  .map((implement) => (implement === 'CanDeactivate' ? 'CanDeactivate<unknown>' : implement))
27
27
  .join(', ');
28
28
  const commonRouterNameImports = ['ActivatedRouteSnapshot', 'RouterStateSnapshot'];
29
- const routerNamedImports = [...options.implements, 'UrlTree'];
29
+ const routerNamedImports = [...options.implements, 'MaybeAsync', 'GuardResult'];
30
30
  if (options.implements.includes(schema_1.Implement.CanMatch)) {
31
31
  routerNamedImports.push('Route', 'UrlSegment');
32
32
  if (options.implements.length > 1) {
package/library/index.js CHANGED
@@ -7,9 +7,9 @@
7
7
  * found in the LICENSE file at https://angular.io/license
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- const core_1 = require("@angular-devkit/core");
11
10
  const schematics_1 = require("@angular-devkit/schematics");
12
11
  const tasks_1 = require("@angular-devkit/schematics/tasks");
12
+ const posix_1 = require("node:path/posix");
13
13
  const dependencies_1 = require("../utility/dependencies");
14
14
  const json_file_1 = require("../utility/json-file");
15
15
  const latest_versions_1 = require("../utility/latest-versions");
@@ -110,8 +110,8 @@ function default_1(options) {
110
110
  folderName = schematics_1.strings.dasherize(folderName);
111
111
  }
112
112
  const libDir = options.projectRoot !== undefined
113
- ? (0, core_1.normalize)(options.projectRoot)
114
- : (0, core_1.join)((0, core_1.normalize)(newProjectRoot), folderName);
113
+ ? (0, posix_1.join)(options.projectRoot)
114
+ : (0, posix_1.join)(newProjectRoot, folderName);
115
115
  const distRoot = `dist/${folderName}`;
116
116
  const sourceDir = `${libDir}/src/lib`;
117
117
  const templateSource = (0, schematics_1.apply)((0, schematics_1.url)('./files'), [
@@ -7,8 +7,8 @@
7
7
  * found in the LICENSE file at https://angular.io/license
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- const core_1 = require("@angular-devkit/core");
11
10
  const schematics_1 = require("@angular-devkit/schematics");
11
+ const posix_1 = require("node:path/posix");
12
12
  const utility_1 = require("../../utility");
13
13
  const dependencies_1 = require("../../utility/dependencies");
14
14
  const latest_versions_1 = require("../../utility/latest-versions");
@@ -80,7 +80,7 @@ function default_1() {
80
80
  // Check if file is importing tokens
81
81
  if (content.includes('@nguniversal/express-engine/tokens')) {
82
82
  hasExpressTokens ||= true;
83
- let tokensFileRelativePath = (0, core_1.relative)((0, core_1.dirname)((0, core_1.normalize)(path)), (0, core_1.normalize)(tokensFilePath));
83
+ let tokensFileRelativePath = (0, posix_1.relative)((0, posix_1.dirname)(path), tokensFilePath);
84
84
  if (tokensFileRelativePath.charAt(0) !== '.') {
85
85
  tokensFileRelativePath = './' + tokensFileRelativePath;
86
86
  }
package/module/index.js CHANGED
@@ -30,8 +30,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
30
30
  return result;
31
31
  };
32
32
  Object.defineProperty(exports, "__esModule", { value: true });
33
- const core_1 = require("@angular-devkit/core");
34
33
  const schematics_1 = require("@angular-devkit/schematics");
34
+ const posix_1 = require("node:path/posix");
35
35
  const ts = __importStar(require("../third_party/github.com/Microsoft/TypeScript/lib/typescript"));
36
36
  const ast_utils_1 = require("../utility/ast-utils");
37
37
  const change_1 = require("../utility/change");
@@ -41,10 +41,7 @@ const validation_1 = require("../utility/validation");
41
41
  const workspace_1 = require("../utility/workspace");
42
42
  const schema_1 = require("./schema");
43
43
  function buildRelativeModulePath(options, modulePath) {
44
- const importModulePath = (0, core_1.normalize)(`/${options.path}/` +
45
- (options.flat ? '' : schematics_1.strings.dasherize(options.name) + '/') +
46
- schematics_1.strings.dasherize(options.name) +
47
- '.module');
44
+ const importModulePath = (0, posix_1.join)(options.path ?? '', options.flat ? '' : schematics_1.strings.dasherize(options.name), schematics_1.strings.dasherize(options.name) + '.module');
48
45
  return (0, find_module_1.buildRelativePath)(modulePath, importModulePath);
49
46
  }
50
47
  function addImportToNgModule(options) {
@@ -94,7 +91,7 @@ function getRoutingModulePath(host, modulePath) {
94
91
  const routingModulePath = modulePath.endsWith(find_module_1.ROUTING_MODULE_EXT)
95
92
  ? modulePath
96
93
  : modulePath.replace(find_module_1.MODULE_EXT, find_module_1.ROUTING_MODULE_EXT);
97
- return host.exists(routingModulePath) ? (0, core_1.normalize)(routingModulePath) : undefined;
94
+ return host.exists(routingModulePath) ? routingModulePath : undefined;
98
95
  }
99
96
  function buildRoute(options, modulePath) {
100
97
  const relativeModulePath = buildRelativeModulePath(options, modulePath);
package/ng-new/index.js CHANGED
@@ -53,9 +53,6 @@ function default_1(options) {
53
53
  workingDirectory: options.directory,
54
54
  packageManager: options.packageManager,
55
55
  }));
56
- if (options.linkCli) {
57
- packageTask = context.addTask(new tasks_1.NodePackageLinkTask('@angular/cli', options.directory), [packageTask]);
58
- }
59
56
  }
60
57
  if (!options.skipGit) {
61
58
  const commit = typeof options.commit == 'object' ? options.commit : options.commit ? {} : false;
@@ -26,10 +26,6 @@ export interface Schema {
26
26
  * is created and referenced in the component TypeScript file.
27
27
  */
28
28
  inlineTemplate?: boolean;
29
- /**
30
- * Link the CLI to the global version (internal development only).
31
- */
32
- linkCli?: boolean;
33
29
  /**
34
30
  * Create a workspace without any testing frameworks. (Use for learning purposes only.)
35
31
  */
@@ -24,12 +24,6 @@
24
24
  "type": "boolean",
25
25
  "default": false
26
26
  },
27
- "linkCli": {
28
- "description": "Link the CLI to the global version (internal development only).",
29
- "type": "boolean",
30
- "default": false,
31
- "visible": false
32
- },
33
27
  "skipGit": {
34
28
  "description": "Do not initialize a git repository.",
35
29
  "type": "boolean",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schematics/angular",
3
- "version": "17.3.0",
3
+ "version": "18.0.0-next.0",
4
4
  "description": "Schematics specific to Angular",
5
5
  "homepage": "https://github.com/angular/angular-cli",
6
6
  "keywords": [
@@ -18,13 +18,12 @@
18
18
  "./utility": "./utility/index.js",
19
19
  "./utility/*": "./utility/*.js",
20
20
  "./migrations/migration-collection.json": "./migrations/migration-collection.json",
21
- "./*": "./*.js",
22
- "./private/components": "./private/components.js"
21
+ "./*": "./*.js"
23
22
  },
24
23
  "schematics": "./collection.json",
25
24
  "dependencies": {
26
- "@angular-devkit/core": "17.3.0",
27
- "@angular-devkit/schematics": "17.3.0",
25
+ "@angular-devkit/core": "18.0.0-next.0",
26
+ "@angular-devkit/schematics": "18.0.0-next.0",
28
27
  "jsonc-parser": "3.2.1"
29
28
  },
30
29
  "repository": {
@@ -32,7 +31,7 @@
32
31
  "url": "https://github.com/angular/angular-cli.git"
33
32
  },
34
33
  "engines": {
35
- "node": "^18.13.0 || >=20.9.0",
34
+ "node": "^18.19.1 || >=20.11.1",
36
35
  "npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
37
36
  "yarn": ">= 1.13.0"
38
37
  },
@@ -32,7 +32,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
32
32
  Object.defineProperty(exports, "__esModule", { value: true });
33
33
  const core_1 = require("@angular-devkit/core");
34
34
  const schematics_1 = require("@angular-devkit/schematics");
35
- const standalone_1 = require("../private/standalone");
36
35
  const ts = __importStar(require("../third_party/github.com/Microsoft/TypeScript/lib/typescript"));
37
36
  const utility_1 = require("../utility");
38
37
  const ast_utils_1 = require("../utility/ast-utils");
@@ -41,6 +40,8 @@ const dependencies_1 = require("../utility/dependencies");
41
40
  const ng_ast_utils_1 = require("../utility/ng-ast-utils");
42
41
  const paths_1 = require("../utility/paths");
43
42
  const project_targets_1 = require("../utility/project-targets");
43
+ const app_config_1 = require("../utility/standalone/app_config");
44
+ const util_1 = require("../utility/standalone/util");
44
45
  const workspace_models_1 = require("../utility/workspace-models");
45
46
  function addDependencies() {
46
47
  return (host) => {
@@ -77,17 +78,15 @@ function updateAppModule(mainPath) {
77
78
  return host;
78
79
  };
79
80
  }
80
- function addProvideServiceWorker(mainPath) {
81
+ function addProvideServiceWorker(projectName, mainPath) {
81
82
  return (host) => {
82
- const updatedFilePath = (0, standalone_1.addFunctionalProvidersToStandaloneBootstrap)(host, mainPath, 'provideServiceWorker', '@angular/service-worker', [
83
- ts.factory.createStringLiteral('ngsw-worker.js', true),
84
- ts.factory.createObjectLiteralExpression([
85
- ts.factory.createPropertyAssignment(ts.factory.createIdentifier('enabled'), ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.ExclamationToken, ts.factory.createCallExpression(ts.factory.createIdentifier('isDevMode'), undefined, []))),
86
- ts.factory.createPropertyAssignment(ts.factory.createIdentifier('registrationStrategy'), ts.factory.createStringLiteral('registerWhenStable:30000', true)),
87
- ], true),
88
- ]);
89
- addImport(host, updatedFilePath, 'isDevMode', '@angular/core');
90
- return host;
83
+ const bootstrapCall = (0, util_1.findBootstrapApplicationCall)(host, mainPath);
84
+ const appConfig = (0, app_config_1.findAppConfig)(bootstrapCall, host, mainPath)?.filePath || mainPath;
85
+ addImport(host, appConfig, 'isDevMode', '@angular/core');
86
+ return (0, utility_1.addRootProvider)(projectName, ({ code, external }) => code `${external('provideServiceWorker', '@angular/service-worker')}('ngsw-worker.js', {
87
+ enabled: !isDevMode(),
88
+ registrationStrategy: 'registerWhenStable:30000'
89
+ })`);
91
90
  };
92
91
  }
93
92
  function getTsSourceFile(host, path) {
@@ -141,7 +140,7 @@ function default_1(options) {
141
140
  (0, schematics_1.move)(project.root),
142
141
  ])),
143
142
  (0, ng_ast_utils_1.isStandaloneApp)(host, browserEntryPoint)
144
- ? addProvideServiceWorker(browserEntryPoint)
143
+ ? addProvideServiceWorker(options.project, browserEntryPoint)
145
144
  : updateAppModule(browserEntryPoint),
146
145
  ]);
147
146
  };
@@ -15,7 +15,7 @@
15
15
  "karma-jasmine-html-reporter": "~2.1.0",
16
16
  "karma-jasmine": "~5.1.0",
17
17
  "karma": "~6.4.0",
18
- "ng-packagr": "^17.3.0",
18
+ "ng-packagr": "^18.0.0-next.0",
19
19
  "protractor": "~7.0.0",
20
20
  "rxjs": "~7.8.0",
21
21
  "tslib": "^2.3.0",
@@ -13,7 +13,7 @@ exports.latestVersions = {
13
13
  // but ts_library doesn't support JSON inputs.
14
14
  ...require('./latest-versions/package.json')['dependencies'],
15
15
  // As Angular CLI works with same minor versions of Angular Framework, a tilde match for the current
16
- Angular: '^17.3.0',
17
- DevkitBuildAngular: '^17.3.0',
18
- AngularSSR: '^17.3.0',
16
+ Angular: '^18.0.0-next.0',
17
+ DevkitBuildAngular: '^18.0.0-next.0',
18
+ AngularSSR: '^18.0.0-next.0',
19
19
  };
@@ -31,12 +31,11 @@ var __importStar = (this && this.__importStar) || function (mod) {
31
31
  };
32
32
  Object.defineProperty(exports, "__esModule", { value: true });
33
33
  exports.isStandaloneApp = exports.getAppModulePath = exports.findBootstrapModuleCall = void 0;
34
- const core_1 = require("@angular-devkit/core");
35
34
  const schematics_1 = require("@angular-devkit/schematics");
36
- const path_1 = require("path");
37
- const standalone_1 = require("../private/standalone");
35
+ const posix_1 = require("node:path/posix");
38
36
  const ts = __importStar(require("../third_party/github.com/Microsoft/TypeScript/lib/typescript"));
39
37
  const ast_utils_1 = require("../utility/ast-utils");
38
+ const util_1 = require("./standalone/util");
40
39
  function findBootstrapModuleCall(host, mainPath) {
41
40
  const mainText = host.readText(mainPath);
42
41
  const source = ts.createSourceFile(mainPath, mainText, ts.ScriptTarget.Latest, true);
@@ -83,14 +82,21 @@ function findBootstrapModulePath(host, mainPath) {
83
82
  }
84
83
  function getAppModulePath(host, mainPath) {
85
84
  const moduleRelativePath = findBootstrapModulePath(host, mainPath);
86
- const mainDir = (0, path_1.dirname)(mainPath);
87
- const modulePath = (0, core_1.normalize)(`/${mainDir}/${moduleRelativePath}.ts`);
85
+ const mainDir = (0, posix_1.dirname)(mainPath);
86
+ const modulePath = (0, posix_1.join)(mainDir, `${moduleRelativePath}.ts`);
88
87
  return modulePath;
89
88
  }
90
89
  exports.getAppModulePath = getAppModulePath;
91
90
  function isStandaloneApp(host, mainPath) {
92
- const source = ts.createSourceFile(mainPath, host.readText(mainPath), ts.ScriptTarget.Latest, true);
93
- const bootstrapCall = (0, standalone_1.findBootstrapApplicationCall)(source);
94
- return bootstrapCall !== null;
91
+ try {
92
+ (0, util_1.findBootstrapApplicationCall)(host, mainPath);
93
+ return true;
94
+ }
95
+ catch (error) {
96
+ if (error instanceof schematics_1.SchematicsException) {
97
+ return false;
98
+ }
99
+ throw error;
100
+ }
95
101
  }
96
102
  exports.isStandaloneApp = isStandaloneApp;
package/utility/paths.js CHANGED
@@ -8,14 +8,11 @@
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.relativePathToWorkspaceRoot = void 0;
11
- const core_1 = require("@angular-devkit/core");
11
+ const posix_1 = require("node:path/posix");
12
12
  function relativePathToWorkspaceRoot(projectRoot) {
13
- const normalizedPath = (0, core_1.split)((0, core_1.normalize)(projectRoot || ''));
14
- if (normalizedPath.length === 0 || !normalizedPath[0]) {
13
+ if (!projectRoot) {
15
14
  return '.';
16
15
  }
17
- else {
18
- return normalizedPath.map(() => '..').join('/');
19
- }
16
+ return (0, posix_1.relative)((0, posix_1.join)('/', projectRoot), '/') || '.';
20
17
  }
21
18
  exports.relativePathToWorkspaceRoot = relativePathToWorkspaceRoot;
@@ -3,7 +3,6 @@
3
3
  "compileOnSave": false,
4
4
  "compilerOptions": {
5
5
  "outDir": "./dist/out-tsc",<% if (strict) { %>
6
- "forceConsistentCasingInFileNames": true,
7
6
  "strict": true,
8
7
  "noImplicitOverride": true,
9
8
  "noPropertyAccessFromIndexSignature": true,
@@ -14,7 +13,7 @@
14
13
  "sourceMap": true,
15
14
  "declaration": false,
16
15
  "experimentalDecorators": true,
17
- "moduleResolution": "node",
16
+ "moduleResolution": "bundler",
18
17
  "importHelpers": true,
19
18
  "target": "ES2022",
20
19
  "module": "ES2022",
@@ -1,8 +0,0 @@
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.io/license
7
- */
8
- export { addModuleImportToStandaloneBootstrap, addFunctionalProvidersToStandaloneBootstrap, callsProvidersFunction, findBootstrapApplicationCall, importsProvidersFrom, } from './standalone';
@@ -1,16 +0,0 @@
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.io/license
8
- */
9
- Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.importsProvidersFrom = exports.findBootstrapApplicationCall = exports.callsProvidersFunction = exports.addFunctionalProvidersToStandaloneBootstrap = exports.addModuleImportToStandaloneBootstrap = void 0;
11
- var standalone_1 = require("./standalone");
12
- Object.defineProperty(exports, "addModuleImportToStandaloneBootstrap", { enumerable: true, get: function () { return standalone_1.addModuleImportToStandaloneBootstrap; } });
13
- Object.defineProperty(exports, "addFunctionalProvidersToStandaloneBootstrap", { enumerable: true, get: function () { return standalone_1.addFunctionalProvidersToStandaloneBootstrap; } });
14
- Object.defineProperty(exports, "callsProvidersFunction", { enumerable: true, get: function () { return standalone_1.callsProvidersFunction; } });
15
- Object.defineProperty(exports, "findBootstrapApplicationCall", { enumerable: true, get: function () { return standalone_1.findBootstrapApplicationCall; } });
16
- Object.defineProperty(exports, "importsProvidersFrom", { enumerable: true, get: function () { return standalone_1.importsProvidersFrom; } });
@@ -1,55 +0,0 @@
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.io/license
7
- */
8
- import { Tree } from '@angular-devkit/schematics';
9
- import ts from '../third_party/github.com/Microsoft/TypeScript/lib/typescript';
10
- /**
11
- * Checks whether the providers from a module are being imported in a `bootstrapApplication` call.
12
- * @param tree File tree of the project.
13
- * @param filePath Path of the file in which to check.
14
- * @param className Class name of the module to search for.
15
- * @deprecated Private utility that will be removed. Use `addRootImport` or `addRootProvider` from
16
- * `@schematics/angular/utility` instead.
17
- */
18
- export declare function importsProvidersFrom(tree: Tree, filePath: string, className: string): boolean;
19
- /**
20
- * Checks whether a providers function is being called in a `bootstrapApplication` call.
21
- * @param tree File tree of the project.
22
- * @param filePath Path of the file in which to check.
23
- * @param functionName Name of the function to search for.
24
- * @deprecated Private utility that will be removed. Use `addRootImport` or `addRootProvider` from
25
- * `@schematics/angular/utility` instead.
26
- */
27
- export declare function callsProvidersFunction(tree: Tree, filePath: string, functionName: string): boolean;
28
- /**
29
- * Adds an `importProvidersFrom` call to the `bootstrapApplication` call.
30
- * @param tree File tree of the project.
31
- * @param filePath Path to the file that should be updated.
32
- * @param moduleName Name of the module that should be imported.
33
- * @param modulePath Path from which to import the module.
34
- * @deprecated Private utility that will be removed. Use `addRootImport` or `addRootProvider` from
35
- * `@schematics/angular/utility` instead.
36
- */
37
- export declare function addModuleImportToStandaloneBootstrap(tree: Tree, filePath: string, moduleName: string, modulePath: string): void;
38
- /**
39
- * Adds a providers function call to the `bootstrapApplication` call.
40
- * @param tree File tree of the project.
41
- * @param filePath Path to the file that should be updated.
42
- * @param functionName Name of the function that should be called.
43
- * @param importPath Path from which to import the function.
44
- * @param args Arguments to use when calling the function.
45
- * @return The file path that the provider was added to.
46
- * @deprecated Private utility that will be removed. Use `addRootImport` or `addRootProvider` from
47
- * `@schematics/angular/utility` instead.
48
- */
49
- export declare function addFunctionalProvidersToStandaloneBootstrap(tree: Tree, filePath: string, functionName: string, importPath: string, args?: ts.Expression[]): string;
50
- /**
51
- * Finds the call to `bootstrapApplication` within a file.
52
- * @deprecated Private utility that will be removed. Use `addRootImport` or `addRootProvider` from
53
- * `@schematics/angular/utility` instead.
54
- */
55
- export declare function findBootstrapApplicationCall(sourceFile: ts.SourceFile): ts.CallExpression | null;
@@ -1,393 +0,0 @@
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.io/license
8
- */
9
- var __importDefault = (this && this.__importDefault) || function (mod) {
10
- return (mod && mod.__esModule) ? mod : { "default": mod };
11
- };
12
- Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.findBootstrapApplicationCall = exports.addFunctionalProvidersToStandaloneBootstrap = exports.addModuleImportToStandaloneBootstrap = exports.callsProvidersFunction = exports.importsProvidersFrom = void 0;
14
- const schematics_1 = require("@angular-devkit/schematics");
15
- const path_1 = require("path");
16
- const typescript_1 = __importDefault(require("../third_party/github.com/Microsoft/TypeScript/lib/typescript"));
17
- const ast_utils_1 = require("../utility/ast-utils");
18
- const change_1 = require("../utility/change");
19
- /**
20
- * Checks whether the providers from a module are being imported in a `bootstrapApplication` call.
21
- * @param tree File tree of the project.
22
- * @param filePath Path of the file in which to check.
23
- * @param className Class name of the module to search for.
24
- * @deprecated Private utility that will be removed. Use `addRootImport` or `addRootProvider` from
25
- * `@schematics/angular/utility` instead.
26
- */
27
- function importsProvidersFrom(tree, filePath, className) {
28
- const sourceFile = createSourceFile(tree, filePath);
29
- const bootstrapCall = findBootstrapApplicationCall(sourceFile);
30
- const appConfig = bootstrapCall ? findAppConfig(bootstrapCall, tree, filePath) : null;
31
- const importProvidersFromCall = appConfig ? findImportProvidersFromCall(appConfig.node) : null;
32
- return !!importProvidersFromCall?.arguments.some((arg) => typescript_1.default.isIdentifier(arg) && arg.text === className);
33
- }
34
- exports.importsProvidersFrom = importsProvidersFrom;
35
- /**
36
- * Checks whether a providers function is being called in a `bootstrapApplication` call.
37
- * @param tree File tree of the project.
38
- * @param filePath Path of the file in which to check.
39
- * @param functionName Name of the function to search for.
40
- * @deprecated Private utility that will be removed. Use `addRootImport` or `addRootProvider` from
41
- * `@schematics/angular/utility` instead.
42
- */
43
- function callsProvidersFunction(tree, filePath, functionName) {
44
- const sourceFile = createSourceFile(tree, filePath);
45
- const bootstrapCall = findBootstrapApplicationCall(sourceFile);
46
- const appConfig = bootstrapCall ? findAppConfig(bootstrapCall, tree, filePath) : null;
47
- const providersLiteral = appConfig ? findProvidersLiteral(appConfig.node) : null;
48
- return !!providersLiteral?.elements.some((el) => typescript_1.default.isCallExpression(el) &&
49
- typescript_1.default.isIdentifier(el.expression) &&
50
- el.expression.text === functionName);
51
- }
52
- exports.callsProvidersFunction = callsProvidersFunction;
53
- /**
54
- * Adds an `importProvidersFrom` call to the `bootstrapApplication` call.
55
- * @param tree File tree of the project.
56
- * @param filePath Path to the file that should be updated.
57
- * @param moduleName Name of the module that should be imported.
58
- * @param modulePath Path from which to import the module.
59
- * @deprecated Private utility that will be removed. Use `addRootImport` or `addRootProvider` from
60
- * `@schematics/angular/utility` instead.
61
- */
62
- function addModuleImportToStandaloneBootstrap(tree, filePath, moduleName, modulePath) {
63
- const sourceFile = createSourceFile(tree, filePath);
64
- const bootstrapCall = findBootstrapApplicationCall(sourceFile);
65
- const addImports = (file, recorder) => {
66
- const sourceText = file.getText();
67
- [
68
- (0, ast_utils_1.insertImport)(file, sourceText, moduleName, modulePath),
69
- (0, ast_utils_1.insertImport)(file, sourceText, 'importProvidersFrom', '@angular/core'),
70
- ].forEach((change) => {
71
- if (change instanceof change_1.InsertChange) {
72
- recorder.insertLeft(change.pos, change.toAdd);
73
- }
74
- });
75
- };
76
- if (!bootstrapCall) {
77
- throw new schematics_1.SchematicsException(`Could not find bootstrapApplication call in ${filePath}`);
78
- }
79
- const importProvidersCall = typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier('importProvidersFrom'), [], [typescript_1.default.factory.createIdentifier(moduleName)]);
80
- // If there's only one argument, we have to create a new object literal.
81
- if (bootstrapCall.arguments.length === 1) {
82
- const recorder = tree.beginUpdate(filePath);
83
- addNewAppConfigToCall(bootstrapCall, importProvidersCall, recorder);
84
- addImports(sourceFile, recorder);
85
- tree.commitUpdate(recorder);
86
- return;
87
- }
88
- // If the config is a `mergeApplicationProviders` call, add another config to it.
89
- if (isMergeAppConfigCall(bootstrapCall.arguments[1])) {
90
- const recorder = tree.beginUpdate(filePath);
91
- addNewAppConfigToCall(bootstrapCall.arguments[1], importProvidersCall, recorder);
92
- addImports(sourceFile, recorder);
93
- tree.commitUpdate(recorder);
94
- return;
95
- }
96
- // Otherwise attempt to merge into the current config.
97
- const appConfig = findAppConfig(bootstrapCall, tree, filePath);
98
- if (!appConfig) {
99
- throw new schematics_1.SchematicsException(`Could not statically analyze config in bootstrapApplication call in ${filePath}`);
100
- }
101
- const { filePath: configFilePath, node: config } = appConfig;
102
- const recorder = tree.beginUpdate(configFilePath);
103
- const importCall = findImportProvidersFromCall(config);
104
- addImports(config.getSourceFile(), recorder);
105
- if (importCall) {
106
- // If there's an `importProvidersFrom` call already, add the module to it.
107
- recorder.insertRight(importCall.arguments[importCall.arguments.length - 1].getEnd(), `, ${moduleName}`);
108
- }
109
- else {
110
- const providersLiteral = findProvidersLiteral(config);
111
- if (providersLiteral) {
112
- // If there's a `providers` array, add the import to it.
113
- addElementToArray(providersLiteral, importProvidersCall, recorder);
114
- }
115
- else {
116
- // Otherwise add a `providers` array to the existing object literal.
117
- addProvidersToObjectLiteral(config, importProvidersCall, recorder);
118
- }
119
- }
120
- tree.commitUpdate(recorder);
121
- }
122
- exports.addModuleImportToStandaloneBootstrap = addModuleImportToStandaloneBootstrap;
123
- /**
124
- * Adds a providers function call to the `bootstrapApplication` call.
125
- * @param tree File tree of the project.
126
- * @param filePath Path to the file that should be updated.
127
- * @param functionName Name of the function that should be called.
128
- * @param importPath Path from which to import the function.
129
- * @param args Arguments to use when calling the function.
130
- * @return The file path that the provider was added to.
131
- * @deprecated Private utility that will be removed. Use `addRootImport` or `addRootProvider` from
132
- * `@schematics/angular/utility` instead.
133
- */
134
- function addFunctionalProvidersToStandaloneBootstrap(tree, filePath, functionName, importPath, args = []) {
135
- const sourceFile = createSourceFile(tree, filePath);
136
- const bootstrapCall = findBootstrapApplicationCall(sourceFile);
137
- const addImports = (file, recorder) => {
138
- const change = (0, ast_utils_1.insertImport)(file, file.getText(), functionName, importPath);
139
- if (change instanceof change_1.InsertChange) {
140
- recorder.insertLeft(change.pos, change.toAdd);
141
- }
142
- };
143
- if (!bootstrapCall) {
144
- throw new schematics_1.SchematicsException(`Could not find bootstrapApplication call in ${filePath}`);
145
- }
146
- const providersCall = typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier(functionName), undefined, args);
147
- // If there's only one argument, we have to create a new object literal.
148
- if (bootstrapCall.arguments.length === 1) {
149
- const recorder = tree.beginUpdate(filePath);
150
- addNewAppConfigToCall(bootstrapCall, providersCall, recorder);
151
- addImports(sourceFile, recorder);
152
- tree.commitUpdate(recorder);
153
- return filePath;
154
- }
155
- // If the config is a `mergeApplicationProviders` call, add another config to it.
156
- if (isMergeAppConfigCall(bootstrapCall.arguments[1])) {
157
- const recorder = tree.beginUpdate(filePath);
158
- addNewAppConfigToCall(bootstrapCall.arguments[1], providersCall, recorder);
159
- addImports(sourceFile, recorder);
160
- tree.commitUpdate(recorder);
161
- return filePath;
162
- }
163
- // Otherwise attempt to merge into the current config.
164
- const appConfig = findAppConfig(bootstrapCall, tree, filePath);
165
- if (!appConfig) {
166
- throw new schematics_1.SchematicsException(`Could not statically analyze config in bootstrapApplication call in ${filePath}`);
167
- }
168
- const { filePath: configFilePath, node: config } = appConfig;
169
- const recorder = tree.beginUpdate(configFilePath);
170
- const providersLiteral = findProvidersLiteral(config);
171
- addImports(config.getSourceFile(), recorder);
172
- if (providersLiteral) {
173
- // If there's a `providers` array, add the import to it.
174
- addElementToArray(providersLiteral, providersCall, recorder);
175
- }
176
- else {
177
- // Otherwise add a `providers` array to the existing object literal.
178
- addProvidersToObjectLiteral(config, providersCall, recorder);
179
- }
180
- tree.commitUpdate(recorder);
181
- return configFilePath;
182
- }
183
- exports.addFunctionalProvidersToStandaloneBootstrap = addFunctionalProvidersToStandaloneBootstrap;
184
- /**
185
- * Finds the call to `bootstrapApplication` within a file.
186
- * @deprecated Private utility that will be removed. Use `addRootImport` or `addRootProvider` from
187
- * `@schematics/angular/utility` instead.
188
- */
189
- function findBootstrapApplicationCall(sourceFile) {
190
- const localName = findImportLocalName(sourceFile, 'bootstrapApplication', '@angular/platform-browser');
191
- if (!localName) {
192
- return null;
193
- }
194
- let result = null;
195
- sourceFile.forEachChild(function walk(node) {
196
- if (typescript_1.default.isCallExpression(node) &&
197
- typescript_1.default.isIdentifier(node.expression) &&
198
- node.expression.text === localName) {
199
- result = node;
200
- }
201
- if (!result) {
202
- node.forEachChild(walk);
203
- }
204
- });
205
- return result;
206
- }
207
- exports.findBootstrapApplicationCall = findBootstrapApplicationCall;
208
- /** Find a call to `importProvidersFrom` within an application config. */
209
- function findImportProvidersFromCall(config) {
210
- const importProvidersName = findImportLocalName(config.getSourceFile(), 'importProvidersFrom', '@angular/core');
211
- const providersLiteral = findProvidersLiteral(config);
212
- if (providersLiteral && importProvidersName) {
213
- for (const element of providersLiteral.elements) {
214
- // Look for an array element that calls the `importProvidersFrom` function.
215
- if (typescript_1.default.isCallExpression(element) &&
216
- typescript_1.default.isIdentifier(element.expression) &&
217
- element.expression.text === importProvidersName) {
218
- return element;
219
- }
220
- }
221
- }
222
- return null;
223
- }
224
- /** Finds the `providers` array literal within an application config. */
225
- function findProvidersLiteral(config) {
226
- for (const prop of config.properties) {
227
- if (typescript_1.default.isPropertyAssignment(prop) &&
228
- typescript_1.default.isIdentifier(prop.name) &&
229
- prop.name.text === 'providers' &&
230
- typescript_1.default.isArrayLiteralExpression(prop.initializer)) {
231
- return prop.initializer;
232
- }
233
- }
234
- return null;
235
- }
236
- /**
237
- * Resolves the node that defines the app config from a bootstrap call.
238
- * @param bootstrapCall Call for which to resolve the config.
239
- * @param tree File tree of the project.
240
- * @param filePath File path of the bootstrap call.
241
- */
242
- function findAppConfig(bootstrapCall, tree, filePath) {
243
- if (bootstrapCall.arguments.length > 1) {
244
- const config = bootstrapCall.arguments[1];
245
- if (typescript_1.default.isObjectLiteralExpression(config)) {
246
- return { filePath, node: config };
247
- }
248
- if (typescript_1.default.isIdentifier(config)) {
249
- return resolveAppConfigFromIdentifier(config, tree, filePath);
250
- }
251
- }
252
- return null;
253
- }
254
- /**
255
- * Resolves the app config from an identifier referring to it.
256
- * @param identifier Identifier referring to the app config.
257
- * @param tree File tree of the project.
258
- * @param bootstapFilePath Path of the bootstrap call.
259
- */
260
- function resolveAppConfigFromIdentifier(identifier, tree, bootstapFilePath) {
261
- const sourceFile = identifier.getSourceFile();
262
- for (const node of sourceFile.statements) {
263
- // Only look at relative imports. This will break if the app uses a path
264
- // mapping to refer to the import, but in order to resolve those, we would
265
- // need knowledge about the entire program.
266
- if (!typescript_1.default.isImportDeclaration(node) ||
267
- !node.importClause?.namedBindings ||
268
- !typescript_1.default.isNamedImports(node.importClause.namedBindings) ||
269
- !typescript_1.default.isStringLiteralLike(node.moduleSpecifier) ||
270
- !node.moduleSpecifier.text.startsWith('.')) {
271
- continue;
272
- }
273
- for (const specifier of node.importClause.namedBindings.elements) {
274
- if (specifier.name.text !== identifier.text) {
275
- continue;
276
- }
277
- // Look for a variable with the imported name in the file. Note that ideally we would use
278
- // the type checker to resolve this, but we can't because these utilities are set up to
279
- // operate on individual files, not the entire program.
280
- const filePath = (0, path_1.join)((0, path_1.dirname)(bootstapFilePath), node.moduleSpecifier.text + '.ts');
281
- const importedSourceFile = createSourceFile(tree, filePath);
282
- const resolvedVariable = findAppConfigFromVariableName(importedSourceFile, (specifier.propertyName || specifier.name).text);
283
- if (resolvedVariable) {
284
- return { filePath, node: resolvedVariable };
285
- }
286
- }
287
- }
288
- const variableInSameFile = findAppConfigFromVariableName(sourceFile, identifier.text);
289
- return variableInSameFile ? { filePath: bootstapFilePath, node: variableInSameFile } : null;
290
- }
291
- /**
292
- * Finds an app config within the top-level variables of a file.
293
- * @param sourceFile File in which to search for the config.
294
- * @param variableName Name of the variable containing the config.
295
- */
296
- function findAppConfigFromVariableName(sourceFile, variableName) {
297
- for (const node of sourceFile.statements) {
298
- if (typescript_1.default.isVariableStatement(node)) {
299
- for (const decl of node.declarationList.declarations) {
300
- if (typescript_1.default.isIdentifier(decl.name) &&
301
- decl.name.text === variableName &&
302
- decl.initializer &&
303
- typescript_1.default.isObjectLiteralExpression(decl.initializer)) {
304
- return decl.initializer;
305
- }
306
- }
307
- }
308
- }
309
- return null;
310
- }
311
- /**
312
- * Finds the local name of an imported symbol. Could be the symbol name itself or its alias.
313
- * @param sourceFile File within which to search for the import.
314
- * @param name Actual name of the import, not its local alias.
315
- * @param moduleName Name of the module from which the symbol is imported.
316
- */
317
- function findImportLocalName(sourceFile, name, moduleName) {
318
- for (const node of sourceFile.statements) {
319
- // Only look for top-level imports.
320
- if (!typescript_1.default.isImportDeclaration(node) ||
321
- !typescript_1.default.isStringLiteral(node.moduleSpecifier) ||
322
- node.moduleSpecifier.text !== moduleName) {
323
- continue;
324
- }
325
- // Filter out imports that don't have the right shape.
326
- if (!node.importClause ||
327
- !node.importClause.namedBindings ||
328
- !typescript_1.default.isNamedImports(node.importClause.namedBindings)) {
329
- continue;
330
- }
331
- // Look through the elements of the declaration for the specific import.
332
- for (const element of node.importClause.namedBindings.elements) {
333
- if ((element.propertyName || element.name).text === name) {
334
- // The local name is always in `name`.
335
- return element.name.text;
336
- }
337
- }
338
- }
339
- return null;
340
- }
341
- /** Creates a source file from a file path within a project. */
342
- function createSourceFile(tree, filePath) {
343
- return typescript_1.default.createSourceFile(filePath, tree.readText(filePath), typescript_1.default.ScriptTarget.Latest, true);
344
- }
345
- /**
346
- * Creates a new app config object literal and adds it to a call expression as an argument.
347
- * @param call Call to which to add the config.
348
- * @param expression Expression that should inserted into the new config.
349
- * @param recorder Recorder to which to log the change.
350
- */
351
- function addNewAppConfigToCall(call, expression, recorder) {
352
- const newCall = typescript_1.default.factory.updateCallExpression(call, call.expression, call.typeArguments, [
353
- ...call.arguments,
354
- typescript_1.default.factory.createObjectLiteralExpression([
355
- typescript_1.default.factory.createPropertyAssignment('providers', typescript_1.default.factory.createArrayLiteralExpression([expression])),
356
- ], true),
357
- ]);
358
- recorder.remove(call.getStart(), call.getWidth());
359
- recorder.insertRight(call.getStart(), typescript_1.default.createPrinter().printNode(typescript_1.default.EmitHint.Unspecified, newCall, call.getSourceFile()));
360
- }
361
- /**
362
- * Adds an element to an array literal expression.
363
- * @param node Array to which to add the element.
364
- * @param element Element to be added.
365
- * @param recorder Recorder to which to log the change.
366
- */
367
- function addElementToArray(node, element, recorder) {
368
- const newLiteral = typescript_1.default.factory.updateArrayLiteralExpression(node, [...node.elements, element]);
369
- recorder.remove(node.getStart(), node.getWidth());
370
- recorder.insertRight(node.getStart(), typescript_1.default.createPrinter().printNode(typescript_1.default.EmitHint.Unspecified, newLiteral, node.getSourceFile()));
371
- }
372
- /**
373
- * Adds a `providers` property to an object literal.
374
- * @param node Literal to which to add the `providers`.
375
- * @param expression Provider that should be part of the generated `providers` array.
376
- * @param recorder Recorder to which to log the change.
377
- */
378
- function addProvidersToObjectLiteral(node, expression, recorder) {
379
- const newOptionsLiteral = typescript_1.default.factory.updateObjectLiteralExpression(node, [
380
- ...node.properties,
381
- typescript_1.default.factory.createPropertyAssignment('providers', typescript_1.default.factory.createArrayLiteralExpression([expression])),
382
- ]);
383
- recorder.remove(node.getStart(), node.getWidth());
384
- recorder.insertRight(node.getStart(), typescript_1.default.createPrinter().printNode(typescript_1.default.EmitHint.Unspecified, newOptionsLiteral, node.getSourceFile()));
385
- }
386
- /** Checks whether a node is a call to `mergeApplicationConfig`. */
387
- function isMergeAppConfigCall(node) {
388
- if (!typescript_1.default.isCallExpression(node)) {
389
- return false;
390
- }
391
- const localName = findImportLocalName(node.getSourceFile(), 'mergeApplicationConfig', '@angular/core');
392
- return !!localName && typescript_1.default.isIdentifier(node.expression) && node.expression.text === localName;
393
- }