vite-plugin-config-loader.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import { Plugin } from 'vite';
  2. import { ConfigLoaderOptions, loadVendureConfig, LoadVendureConfigResult } from './utils/config-loader.js';
  3. export interface ConfigLoaderApi {
  4. getVendureConfig(): Promise<LoadVendureConfigResult>;
  5. }
  6. export const configLoaderName = 'vendure:config-loader';
  7. /**
  8. * This Vite plugin loads the VendureConfig from the specified file path, and
  9. * makes it available to other plugins via the `ConfigLoaderApi`.
  10. */
  11. export function configLoaderPlugin(options: ConfigLoaderOptions): Plugin {
  12. let result: LoadVendureConfigResult;
  13. const onConfigLoaded: Array<() => void> = [];
  14. return {
  15. name: configLoaderName,
  16. async buildStart() {
  17. this.info(
  18. `Loading Vendure config. This can take a short while depending on the size of your project...`,
  19. );
  20. try {
  21. const startTime = Date.now();
  22. result = await loadVendureConfig({
  23. pathAdapter: options.pathAdapter,
  24. tempDir: options.tempDir,
  25. vendureConfigPath: options.vendureConfigPath,
  26. vendureConfigExport: options.vendureConfigExport,
  27. logger: {
  28. info: (message: string) => this.info(message),
  29. warn: (message: string) => this.warn(message),
  30. debug: (message: string) => this.debug(message),
  31. },
  32. });
  33. const endTime = Date.now();
  34. const duration = endTime - startTime;
  35. const pluginNames = result.pluginInfo.map(p => p.name).join(', ');
  36. this.info(`Found ${result.pluginInfo.length} plugins: ${pluginNames}`);
  37. this.info(
  38. `Vendure config loaded (using export "${result.exportedSymbolName}") in ${duration}ms`,
  39. );
  40. } catch (e: unknown) {
  41. if (e instanceof Error) {
  42. const message = [
  43. e.message,
  44. `If you are using a monorepo, you may need to provide a custom pathAdapter to resolve the paths correctly.`,
  45. ].join('\n');
  46. this.error(`Error loading Vendure config: ${message}`);
  47. }
  48. }
  49. onConfigLoaded.forEach(fn => fn());
  50. },
  51. api: {
  52. getVendureConfig(): Promise<LoadVendureConfigResult> {
  53. if (result) {
  54. return Promise.resolve(result);
  55. } else {
  56. return new Promise<LoadVendureConfigResult>(resolve => {
  57. onConfigLoaded.push(() => {
  58. resolve(result);
  59. });
  60. });
  61. }
  62. },
  63. } satisfies ConfigLoaderApi,
  64. };
  65. }
  66. /**
  67. * Inter-plugin dependencies implemented following the pattern given here:
  68. * https://rollupjs.org/plugin-development/#direct-plugin-communication
  69. */
  70. export function getConfigLoaderApi(plugins: readonly Plugin[]): ConfigLoaderApi {
  71. const parentPlugin = plugins.find(plugin => plugin.name === configLoaderName);
  72. if (!parentPlugin) {
  73. throw new Error(`This plugin depends on the "${configLoaderName}" plugin.`);
  74. }
  75. return parentPlugin.api as ConfigLoaderApi;
  76. }