compile.ts 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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 compileUiExtensions(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(
  20. 'yarn',
  21. [
  22. 'build',
  23. /*'--prod=true', */
  24. `--outputPath=${relativeOutputPath}`,
  25. ],
  26. {
  27. cwd,
  28. shell: true,
  29. stdio: 'inherit',
  30. },
  31. );
  32. buildProcess.on('close', code => {
  33. if (code === 0) {
  34. resolve();
  35. } else {
  36. reject(code);
  37. }
  38. });
  39. buildProcess.on('error', err => {
  40. reject(err);
  41. });
  42. }).finally(() => {
  43. restoreOriginalExtensionsModule();
  44. });
  45. }
  46. function deleteExistingExtensionModules() {
  47. fs.removeSync(path.join(EXTENSIONS_DIR, EXTENSIONS_MODULES_DIR));
  48. }
  49. function copyExtensionModules(extensions: Array<Required<AdminUiExtension>>) {
  50. for (const extension of extensions) {
  51. const dirName = path.basename(path.dirname(extension.ngModulePath));
  52. const dest = path.join(EXTENSIONS_DIR, EXTENSIONS_MODULES_DIR, extension.id);
  53. fs.copySync(extension.ngModulePath, dest);
  54. }
  55. }
  56. function createExtensionsModule(extensions: Array<Required<AdminUiExtension>>) {
  57. const removeTsExtension = (filename: string): string => filename.replace(/\.ts$/, '');
  58. const importPath = (e: Required<AdminUiExtension>): string =>
  59. `./${EXTENSIONS_MODULES_DIR}/${e.id}/${removeTsExtension(e.ngModuleFileName)}`;
  60. fs.renameSync(originalExtensionsModuleFile, tempExtensionsModuleFile);
  61. const source = generateExtensionModuleTsSource(
  62. extensions.map(e => ({ className: e.ngModuleName, path: importPath(e) })),
  63. );
  64. fs.writeFileSync(path.join(EXTENSIONS_DIR, 'extensions.module.ts'), source, 'utf-8');
  65. }
  66. function restoreOriginalExtensionsModule() {
  67. fs.renameSync(originalExtensionsModuleFile, path.join(EXTENSIONS_DIR, 'extensions.module.ts.generated'));
  68. fs.renameSync(tempExtensionsModuleFile, originalExtensionsModuleFile);
  69. }
  70. function generateExtensionModuleTsSource(modules: Array<{ className: string; path: string }>): string {
  71. return `/** This file is generated by the build() function. Do not edit. */
  72. import { CommonModule } from '@angular/common';
  73. import { NgModule } from '@angular/core';
  74. ${modules.map(e => `import { ${e.className} } from '${e.path}';`).join('\n')}
  75. @NgModule({
  76. imports: [
  77. CommonModule,
  78. ${modules.map(e => e.className + ',').join('\n')}
  79. ],
  80. })
  81. export class ExtensionsModule {}
  82. `;
  83. }