index.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. /**
  4. * @license
  5. * Copyright Google Inc. All Rights Reserved.
  6. *
  7. * Use of this source code is governed by an MIT-style license that can be
  8. * found in the LICENSE file at https://angular.io/license
  9. */
  10. const core_1 = require("@angular-devkit/core");
  11. const schematics_1 = require("@angular-devkit/schematics");
  12. const json_utils_1 = require("../utility/json-utils");
  13. const parse_name_1 = require("../utility/parse-name");
  14. const paths_1 = require("../utility/paths");
  15. const workspace_1 = require("../utility/workspace");
  16. function addConfig(options, root, tsConfigPath) {
  17. return (host, context) => {
  18. context.logger.debug('updating project configuration.');
  19. // Add worker glob exclusion to tsconfig.app.json.
  20. // Projects pre version 8 should to have tsconfig.app.json inside their application
  21. const isInSrc = core_1.dirname(core_1.normalize(tsConfigPath)).endsWith('src');
  22. const workerGlob = `${isInSrc ? '' : 'src/'}**/*.worker.ts`;
  23. const buffer = host.read(tsConfigPath);
  24. if (buffer) {
  25. const tsCfgAst = core_1.parseJsonAst(buffer.toString(), core_1.JsonParseMode.Loose);
  26. if (tsCfgAst.kind != 'object') {
  27. throw new schematics_1.SchematicsException('Invalid tsconfig. Was expecting an object');
  28. }
  29. const filesAstNode = json_utils_1.findPropertyInAstObject(tsCfgAst, 'exclude');
  30. if (filesAstNode && filesAstNode.kind != 'array') {
  31. throw new schematics_1.SchematicsException('Invalid tsconfig "exclude" property; expected an array.');
  32. }
  33. if (filesAstNode && !filesAstNode.value.includes(workerGlob)) {
  34. const recorder = host.beginUpdate(tsConfigPath);
  35. json_utils_1.appendValueInAstArray(recorder, filesAstNode, workerGlob);
  36. host.commitUpdate(recorder);
  37. }
  38. }
  39. return schematics_1.mergeWith(schematics_1.apply(schematics_1.url('./files/worker-tsconfig'), [
  40. schematics_1.applyTemplates({
  41. ...options,
  42. relativePathToWorkspaceRoot: paths_1.relativePathToWorkspaceRoot(root),
  43. }),
  44. schematics_1.move(root),
  45. ]));
  46. };
  47. }
  48. function addSnippet(options) {
  49. return (host, context) => {
  50. context.logger.debug('Updating appmodule');
  51. if (options.path === undefined) {
  52. return;
  53. }
  54. const fileRegExp = new RegExp(`^${options.name}.*\.ts`);
  55. const siblingModules = host.getDir(options.path).subfiles
  56. // Find all files that start with the same name, are ts files,
  57. // and aren't spec or module files.
  58. .filter(f => fileRegExp.test(f) && !/(module|spec)\.ts$/.test(f))
  59. // Sort alphabetically for consistency.
  60. .sort();
  61. if (siblingModules.length === 0) {
  62. // No module to add in.
  63. return;
  64. }
  65. const siblingModulePath = `${options.path}/${siblingModules[0]}`;
  66. const logMessage = 'console.log(`page got message: ${data}`);';
  67. const workerCreationSnippet = core_1.tags.stripIndent `
  68. if (typeof Worker !== 'undefined') {
  69. // Create a new
  70. const worker = new Worker('./${options.name}.worker', { type: 'module' });
  71. worker.onmessage = ({ data }) => {
  72. ${logMessage}
  73. };
  74. worker.postMessage('hello');
  75. } else {
  76. // Web Workers are not supported in this environment.
  77. // You should add a fallback so that your program still executes correctly.
  78. }
  79. `;
  80. // Append the worker creation snippet.
  81. const originalContent = host.read(siblingModulePath);
  82. host.overwrite(siblingModulePath, originalContent + '\n' + workerCreationSnippet);
  83. return host;
  84. };
  85. }
  86. function default_1(options) {
  87. return async (host) => {
  88. const workspace = await workspace_1.getWorkspace(host);
  89. if (!options.project) {
  90. throw new schematics_1.SchematicsException('Option "project" is required.');
  91. }
  92. if (!options.target) {
  93. throw new schematics_1.SchematicsException('Option "target" is required.');
  94. }
  95. const project = workspace.projects.get(options.project);
  96. if (!project) {
  97. throw new schematics_1.SchematicsException(`Invalid project name (${options.project})`);
  98. }
  99. const projectType = project.extensions['projectType'];
  100. if (projectType !== 'application') {
  101. throw new schematics_1.SchematicsException(`Web Worker requires a project type of "application".`);
  102. }
  103. const projectTarget = project.targets.get(options.target);
  104. if (!projectTarget) {
  105. throw new Error(`Target is not defined for this project.`);
  106. }
  107. const projectTargetOptions = (projectTarget.options || {});
  108. if (options.path === undefined) {
  109. options.path = workspace_1.buildDefaultPath(project);
  110. }
  111. const parsedPath = parse_name_1.parseName(options.path, options.name);
  112. options.name = parsedPath.name;
  113. options.path = parsedPath.path;
  114. const root = project.root || '';
  115. const needWebWorkerConfig = !projectTargetOptions.webWorkerTsConfig;
  116. if (needWebWorkerConfig) {
  117. const workerConfigPath = core_1.join(core_1.normalize(root), 'tsconfig.worker.json');
  118. projectTargetOptions.webWorkerTsConfig = workerConfigPath;
  119. // add worker tsconfig to lint architect target
  120. const lintTarget = project.targets.get('lint');
  121. if (lintTarget) {
  122. const lintOptions = (lintTarget.options || {});
  123. lintOptions.tsConfig = (lintOptions.tsConfig || []).concat(workerConfigPath);
  124. }
  125. }
  126. const templateSource = schematics_1.apply(schematics_1.url('./files/worker'), [
  127. schematics_1.applyTemplates({ ...options, ...core_1.strings }),
  128. schematics_1.move(parsedPath.path),
  129. ]);
  130. return schematics_1.chain([
  131. // Add project configuration.
  132. needWebWorkerConfig ? addConfig(options, root, projectTargetOptions.tsConfig) : schematics_1.noop(),
  133. needWebWorkerConfig ? workspace_1.updateWorkspace(workspace) : schematics_1.noop(),
  134. // Create the worker in a sibling module.
  135. options.snippet ? addSnippet(options) : schematics_1.noop(),
  136. // Add the worker.
  137. schematics_1.mergeWith(templateSource),
  138. ]);
  139. };
  140. }
  141. exports.default = default_1;