compile.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import { AdminUiExtension } from '@vendure/common/lib/shared-types';
  2. import { exec, spawn } from 'child_process';
  3. import * as fs from 'fs-extra';
  4. import * as path from 'path';
  5. const EXTENSIONS_DIR = path.join(__dirname, '../src/app/extensions');
  6. const EXTENSIONS_MODULES_DIR = 'modules';
  7. const originalExtensionsModuleFile = path.join(EXTENSIONS_DIR, 'extensions.module.ts');
  8. const tempExtensionsModuleFile = path.join(EXTENSIONS_DIR, 'extensions.module.ts.temp');
  9. /**
  10. * Builds the admin-ui app using the Angular CLI `ng build --prod` command.
  11. */
  12. export function compileAdminUiApp(outputPath: string, extensions: Array<Required<AdminUiExtension>>) {
  13. const cwd = path.join(__dirname, '..');
  14. const relativeOutputPath = path.relative(cwd, outputPath);
  15. return new Promise((resolve, reject) => {
  16. deleteExistingExtensionModules();
  17. copyExtensionModules(extensions);
  18. createExtensionsModule(extensions);
  19. const buildProcess = spawn('yarn', ['build:in-plugin', `--outputPath=${relativeOutputPath}`], {
  20. cwd,
  21. shell: true,
  22. stdio: 'inherit',
  23. });
  24. buildProcess.on('close', code => {
  25. if (code === 0) {
  26. resolve();
  27. } else {
  28. reject(code);
  29. }
  30. });
  31. buildProcess.on('error', err => {
  32. reject(err);
  33. });
  34. }).finally(() => {
  35. restoreOriginalExtensionsModule();
  36. });
  37. }
  38. function deleteExistingExtensionModules() {
  39. fs.removeSync(path.join(EXTENSIONS_DIR, EXTENSIONS_MODULES_DIR));
  40. }
  41. function copyExtensionModules(extensions: Array<Required<AdminUiExtension>>) {
  42. for (const extension of extensions) {
  43. const dirName = path.basename(path.dirname(extension.ngModulePath));
  44. const dest = path.join(EXTENSIONS_DIR, EXTENSIONS_MODULES_DIR, extension.id);
  45. fs.copySync(extension.ngModulePath, dest);
  46. }
  47. }
  48. function createExtensionsModule(extensions: Array<Required<AdminUiExtension>>) {
  49. const removeTsExtension = (filename: string): string => filename.replace(/\.ts$/, '');
  50. const importPath = (e: Required<AdminUiExtension>): string =>
  51. `./${EXTENSIONS_MODULES_DIR}/${e.id}/${removeTsExtension(e.ngModuleFileName)}`;
  52. fs.renameSync(originalExtensionsModuleFile, tempExtensionsModuleFile);
  53. const source = generateExtensionModuleTsSource(
  54. extensions.map(e => ({ className: e.ngModuleName, path: importPath(e) })),
  55. );
  56. fs.writeFileSync(path.join(EXTENSIONS_DIR, 'extensions.module.ts'), source, 'utf-8');
  57. }
  58. function restoreOriginalExtensionsModule() {
  59. fs.renameSync(originalExtensionsModuleFile, path.join(EXTENSIONS_DIR, 'extensions.module.ts.generated'));
  60. fs.renameSync(tempExtensionsModuleFile, originalExtensionsModuleFile);
  61. }
  62. function generateExtensionModuleTsSource(modules: Array<{ className: string; path: string }>): string {
  63. return `/** This file is generated by the build() function. Do not edit. */
  64. import { CommonModule } from '@angular/common';
  65. import { NgModule } from '@angular/core';
  66. ${modules.map(e => `import { ${e.className} } from '${e.path}';`).join('\n')}
  67. @NgModule({
  68. imports: [
  69. CommonModule,
  70. ${modules.map(e => e.className + ',').join('\n')}
  71. ],
  72. })
  73. export class ExtensionsModule {}
  74. `;
  75. }