update-server-main-file.js 4.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. const ts = require("../../third_party/github.com/Microsoft/TypeScript/lib/typescript");
  4. const ast_utils_1 = require("../../utility/ast-utils");
  5. const json_utils_1 = require("../../utility/json-utils");
  6. const workspace_models_1 = require("../../utility/workspace-models");
  7. const utils_1 = require("./utils");
  8. /**
  9. * Update the `main.server.ts` file by adding exports to `renderModule` and `renderModuleFactory` which are
  10. * now required for Universal and App-Shell for Ivy and `bundleDependencies`.
  11. */
  12. function updateServerMainFile() {
  13. return tree => {
  14. const workspace = utils_1.getWorkspace(tree);
  15. for (const { target } of utils_1.getTargets(workspace, 'server', workspace_models_1.Builders.Server)) {
  16. const options = json_utils_1.findPropertyInAstObject(target, 'options');
  17. if (!options || options.kind !== 'object') {
  18. continue;
  19. }
  20. // find the main server file
  21. const mainFile = json_utils_1.findPropertyInAstObject(options, 'main');
  22. if (!mainFile || typeof mainFile.value !== 'string') {
  23. continue;
  24. }
  25. const mainFilePath = mainFile.value;
  26. const content = tree.read(mainFilePath);
  27. if (!content) {
  28. continue;
  29. }
  30. const source = ts.createSourceFile(mainFilePath, content.toString().replace(/^\uFEFF/, ''), ts.ScriptTarget.Latest, true);
  31. // find exports in main server file
  32. const exportDeclarations = ast_utils_1.findNodes(source, ts.SyntaxKind.ExportDeclaration);
  33. const platformServerExports = exportDeclarations.filter(({ moduleSpecifier }) => (moduleSpecifier && ts.isStringLiteral(moduleSpecifier) && moduleSpecifier.text === '@angular/platform-server'));
  34. let hasRenderModule = false;
  35. let hasRenderModuleFactory = false;
  36. // find exports of renderModule or renderModuleFactory
  37. for (const { exportClause } of platformServerExports) {
  38. if (exportClause && ts.isNamedExports(exportClause)) {
  39. if (!hasRenderModuleFactory) {
  40. hasRenderModuleFactory = exportClause.elements.some(({ name }) => name.text === 'renderModuleFactory');
  41. }
  42. if (!hasRenderModule) {
  43. hasRenderModule = exportClause.elements.some(({ name }) => name.text === 'renderModule');
  44. }
  45. }
  46. }
  47. if (hasRenderModule && hasRenderModuleFactory) {
  48. // We have both required exports
  49. continue;
  50. }
  51. let exportSpecifiers = [];
  52. let updateExisting = false;
  53. // Add missing exports
  54. if (platformServerExports.length) {
  55. const { exportClause } = platformServerExports[0];
  56. if (!exportClause) {
  57. continue;
  58. }
  59. exportSpecifiers = [...exportClause.elements];
  60. updateExisting = true;
  61. }
  62. if (!hasRenderModule) {
  63. exportSpecifiers.push(ts.createExportSpecifier(undefined, ts.createIdentifier('renderModule')));
  64. }
  65. if (!hasRenderModuleFactory) {
  66. exportSpecifiers.push(ts.createExportSpecifier(undefined, ts.createIdentifier('renderModuleFactory')));
  67. }
  68. // Create a TS printer to get the text of the export node
  69. const printer = ts.createPrinter();
  70. const moduleSpecifier = ts.createStringLiteral('@angular/platform-server');
  71. // TypeScript will emit the Node with double quotes.
  72. // In schematics we usually write code with a single quotes
  73. // tslint:disable-next-line: no-any
  74. moduleSpecifier.singleQuote = true;
  75. const newExportDeclarationText = printer.printNode(ts.EmitHint.Unspecified, ts.createExportDeclaration(undefined, undefined, ts.createNamedExports(exportSpecifiers), moduleSpecifier), source);
  76. const recorder = tree.beginUpdate(mainFilePath);
  77. if (updateExisting) {
  78. const start = platformServerExports[0].getStart();
  79. const width = platformServerExports[0].getWidth();
  80. recorder
  81. .remove(start, width)
  82. .insertLeft(start, newExportDeclarationText);
  83. }
  84. else {
  85. recorder.insertLeft(source.getWidth(), '\n' + newExportDeclarationText);
  86. }
  87. tree.commitUpdate(recorder);
  88. }
  89. return tree;
  90. };
  91. }
  92. exports.updateServerMainFile = updateServerMainFile;