utils.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /* tslint:disable:no-console */
  2. import chalk from 'chalk';
  3. import { execSync } from 'child_process';
  4. import { createHash } from 'crypto';
  5. import * as fs from 'fs-extra';
  6. import * as path from 'path';
  7. import { STATIC_ASSETS_OUTPUT_DIR } from './constants';
  8. import {
  9. AdminUiExtension,
  10. Extension,
  11. GlobalStylesExtension,
  12. StaticAssetDefinition,
  13. StaticAssetExtension,
  14. TranslationExtension,
  15. } from './types';
  16. export const logger = {
  17. log: (message: string) => console.log(chalk.green(message)),
  18. error: (message: string) => console.log(chalk.red(message)),
  19. };
  20. /**
  21. * Checks for the global yarn binary and returns true if found.
  22. */
  23. export function shouldUseYarn(): boolean {
  24. try {
  25. execSync('yarnpkg --version', { stdio: 'ignore' });
  26. return true;
  27. } catch (e) {
  28. return false;
  29. }
  30. }
  31. /**
  32. * Returns the string path of a static asset
  33. */
  34. export function getStaticAssetPath(staticAssetDef: StaticAssetDefinition): string {
  35. return typeof staticAssetDef === 'string' ? staticAssetDef : staticAssetDef.path;
  36. }
  37. /**
  38. * Copy the @vendure/ui-devkit files to the static assets dir.
  39. */
  40. export function copyUiDevkit(outputPath: string) {
  41. const devkitDir = path.join(outputPath, STATIC_ASSETS_OUTPUT_DIR, 'devkit');
  42. fs.ensureDirSync(devkitDir);
  43. fs.copySync(require.resolve('@vendure/ui-devkit'), path.join(devkitDir, 'ui-devkit.js'));
  44. }
  45. /**
  46. * Copies over any files defined by the extensions' `staticAssets` array to the shared
  47. * static assets directory. When the app is built by the ng cli, this assets directory is
  48. * the copied over to the final static assets location (i.e. http://domain/admin/assets/)
  49. */
  50. export async function copyStaticAsset(outputPath: string, staticAssetDef: StaticAssetDefinition) {
  51. const staticAssetPath = getStaticAssetPath(staticAssetDef);
  52. let assetOutputPath: string;
  53. const assetBasename = path.basename(staticAssetPath);
  54. assetOutputPath = path.join(outputPath, STATIC_ASSETS_OUTPUT_DIR, assetBasename);
  55. fs.copySync(staticAssetPath, assetOutputPath);
  56. if (typeof staticAssetDef !== 'string') {
  57. // The asset is being renamed
  58. const newName = path.join(path.dirname(assetOutputPath), staticAssetDef.rename);
  59. try {
  60. // We use copy, remove rather than rename due to problems with the
  61. // EPERM error in Windows.
  62. await fs.copy(assetOutputPath, newName);
  63. await fs.remove(assetOutputPath);
  64. } catch (e) {
  65. logger.log(e);
  66. }
  67. }
  68. }
  69. /**
  70. * Ensures each extension has an ID and a value for the optional properties.
  71. * If not defined by the user, a deterministic ID is generated
  72. * from a hash of the extension config.
  73. */
  74. export function normalizeExtensions(extensions?: AdminUiExtension[]): Array<Required<AdminUiExtension>> {
  75. return (extensions || []).map(e => {
  76. let id = e.id;
  77. if (!id) {
  78. const hash = createHash('sha256');
  79. hash.update(JSON.stringify(e));
  80. id = hash.digest('hex');
  81. }
  82. return { staticAssets: [], translations: {}, globalStyles: [], ...e, id };
  83. });
  84. }
  85. export function isAdminUiExtension(input: Extension): input is AdminUiExtension {
  86. return input.hasOwnProperty('extensionPath');
  87. }
  88. export function isTranslationExtension(input: Extension): input is TranslationExtension {
  89. return input.hasOwnProperty('translations');
  90. }
  91. export function isStaticAssetExtension(input: Extension): input is StaticAssetExtension {
  92. return input.hasOwnProperty('staticAssets');
  93. }
  94. export function isGlobalStylesExtension(input: Extension): input is GlobalStylesExtension {
  95. return input.hasOwnProperty('globalStyles');
  96. }