app_component.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  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 __importDefault = (this && this.__importDefault) || function (mod) {
  10. return (mod && mod.__esModule) ? mod : { "default": mod };
  11. };
  12. Object.defineProperty(exports, "__esModule", { value: true });
  13. exports.resolveBootstrappedComponentData = resolveBootstrappedComponentData;
  14. const schematics_1 = require("@angular-devkit/schematics");
  15. const typescript_1 = __importDefault(require("../../third_party/github.com/Microsoft/TypeScript/lib/typescript"));
  16. const ast_utils_1 = require("../ast-utils");
  17. const ng_ast_utils_1 = require("../ng-ast-utils");
  18. const util_1 = require("./util");
  19. /**
  20. * Finds the original name and path relative to the `main.ts` of the bootrstrapped app component.
  21. * @param tree File tree in which to look for the component.
  22. * @param mainFilePath Path of the `main` file.
  23. */
  24. function resolveBootstrappedComponentData(tree, mainFilePath) {
  25. // First try to resolve for a standalone app.
  26. try {
  27. const call = (0, util_1.findBootstrapApplicationCall)(tree, mainFilePath);
  28. if (call.arguments.length > 0 && typescript_1.default.isIdentifier(call.arguments[0])) {
  29. const resolved = resolveIdentifier(call.arguments[0]);
  30. if (resolved) {
  31. return {
  32. componentName: resolved.name,
  33. componentImportPathInSameFile: resolved.path,
  34. moduleName: null,
  35. moduleImportPathInSameFile: null,
  36. };
  37. }
  38. }
  39. }
  40. catch (e) {
  41. // `findBootstrapApplicationCall` will throw if it can't find the `bootrstrapApplication` call.
  42. // Catch so we can continue to the fallback logic.
  43. if (!(e instanceof schematics_1.SchematicsException)) {
  44. throw e;
  45. }
  46. }
  47. // Otherwise fall back to resolving an NgModule-based app.
  48. return resolveNgModuleBasedData(tree, mainFilePath);
  49. }
  50. /** Resolves the bootstrap data for a NgModule-based app. */
  51. function resolveNgModuleBasedData(tree, mainFilePath) {
  52. const appModulePath = (0, ng_ast_utils_1.getAppModulePath)(tree, mainFilePath);
  53. const appModuleFile = (0, util_1.getSourceFile)(tree, appModulePath);
  54. const metadataNodes = (0, ast_utils_1.getDecoratorMetadata)(appModuleFile, 'NgModule', '@angular/core');
  55. for (const node of metadataNodes) {
  56. if (!typescript_1.default.isObjectLiteralExpression(node)) {
  57. continue;
  58. }
  59. const bootstrapProp = (0, ast_utils_1.getMetadataField)(node, 'bootstrap').find((prop) => {
  60. return (typescript_1.default.isArrayLiteralExpression(prop.initializer) &&
  61. prop.initializer.elements.length > 0 &&
  62. typescript_1.default.isIdentifier(prop.initializer.elements[0]));
  63. });
  64. const componentIdentifier = (bootstrapProp?.initializer)
  65. .elements[0];
  66. const componentResult = componentIdentifier ? resolveIdentifier(componentIdentifier) : null;
  67. const bootstrapCall = (0, ng_ast_utils_1.findBootstrapModuleCall)(tree, mainFilePath);
  68. if (componentResult &&
  69. bootstrapCall &&
  70. bootstrapCall.arguments.length > 0 &&
  71. typescript_1.default.isIdentifier(bootstrapCall.arguments[0])) {
  72. const moduleResult = resolveIdentifier(bootstrapCall.arguments[0]);
  73. if (moduleResult) {
  74. return {
  75. componentName: componentResult.name,
  76. componentImportPathInSameFile: componentResult.path,
  77. moduleName: moduleResult.name,
  78. moduleImportPathInSameFile: moduleResult.path,
  79. };
  80. }
  81. }
  82. }
  83. return null;
  84. }
  85. /** Resolves an identifier to its original name and path that it was imported from. */
  86. function resolveIdentifier(identifier) {
  87. const sourceFile = identifier.getSourceFile();
  88. // Try to resolve the import path by looking at the top-level named imports of the file.
  89. for (const node of sourceFile.statements) {
  90. if (!typescript_1.default.isImportDeclaration(node) ||
  91. !typescript_1.default.isStringLiteral(node.moduleSpecifier) ||
  92. !node.importClause ||
  93. !node.importClause.namedBindings ||
  94. !typescript_1.default.isNamedImports(node.importClause.namedBindings)) {
  95. continue;
  96. }
  97. for (const element of node.importClause.namedBindings.elements) {
  98. if (element.name.text === identifier.text) {
  99. return {
  100. // Note that we use `propertyName` if available, because it contains
  101. // the real name in the case where the import is aliased.
  102. name: (element.propertyName || element.name).text,
  103. path: node.moduleSpecifier.text,
  104. };
  105. }
  106. }
  107. }
  108. return null;
  109. }