Forráskód Böngészése

fix(dashboard): Introduce experimental support for ESM projects

Relates to #3727, relates to #3533
Michael Bromley 2 hónapja
szülő
commit
3881d46f8f

+ 27 - 0
packages/dashboard/vite/tests/esm.spec.ts

@@ -0,0 +1,27 @@
+import { rm } from 'node:fs/promises';
+import { join } from 'node:path';
+import { describe, expect, it } from 'vitest';
+
+import { compile } from '../utils/compiler.js';
+import { debugLogger, noopLogger } from '../utils/logger.js';
+
+describe('handling esm projects', () => {
+    it('should compile esm project', { timeout: 60_000 }, async () => {
+        const tempDir = join(__dirname, './__temp/esm');
+        await rm(tempDir, { recursive: true, force: true });
+        const result = await compile({
+            outputPath: tempDir,
+            vendureConfigPath: join(__dirname, 'fixtures-esm', 'vendure-config.ts'),
+            logger: process.env.LOG ? debugLogger : noopLogger,
+            module: 'esm',
+        });
+
+        expect(result.pluginInfo).toHaveLength(1);
+        expect(result.pluginInfo[0].name).toBe('MyPlugin');
+        expect(result.pluginInfo[0].dashboardEntryPath).toBe('./dashboard/index.tsx');
+        expect(result.pluginInfo[0].sourcePluginPath).toBe(
+            join(__dirname, 'fixtures-esm', 'my-plugin', 'src', 'my.plugin.ts'),
+        );
+        expect(result.pluginInfo[0].pluginPath).toBe(join(tempDir, 'my-plugin', 'src', 'my.plugin.js'));
+    });
+});

+ 21 - 0
packages/dashboard/vite/tests/fixtures-esm/my-plugin/src/my.plugin.ts

@@ -0,0 +1,21 @@
+import { PluginCommonModule, VendurePlugin } from '@vendure/core';
+import { dirname, join } from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+/**
+ * Provider method to simulate __dirname variable.
+ */
+export const getDirname = (url: string, ...subDir: string[]) => {
+    return join(dirname(fileURLToPath(url)), ...subDir);
+};
+
+@VendurePlugin({
+    imports: [PluginCommonModule],
+    providers: [],
+    dashboard: './dashboard/index.tsx',
+})
+export class MyPlugin {
+    static options = {
+        projectDir: getDirname(import.meta.url, '../templates'),
+    };
+}

+ 6 - 0
packages/dashboard/vite/tests/fixtures-esm/package.json

@@ -0,0 +1,6 @@
+{
+    "type": "module",
+    "name": "esm",
+    "version": "0.0.1",
+    "main": "index.ts"
+}

+ 21 - 0
packages/dashboard/vite/tests/fixtures-esm/vendure-config.ts

@@ -0,0 +1,21 @@
+import { VendureConfig } from '@vendure/core';
+
+import { MyPlugin } from './my-plugin/src/my.plugin.js';
+
+const somePath = import.meta.url;
+
+export const config: VendureConfig = {
+    apiOptions: {
+        port: 3000,
+    },
+    authOptions: {
+        tokenMethod: 'bearer',
+    },
+    dbConnectionOptions: {
+        type: 'postgres',
+    },
+    paymentOptions: {
+        paymentMethodHandlers: [],
+    },
+    plugins: [MyPlugin],
+};

+ 6 - 2
packages/dashboard/vite/utils/compiler.ts

@@ -28,6 +28,7 @@ export interface CompilerOptions {
     pathAdapter?: PathAdapter;
     logger?: Logger;
     pluginPackageScanner?: PackageScannerConfig;
+    module?: 'commonjs' | 'esm';
 }
 
 export interface CompileResult {
@@ -57,6 +58,7 @@ export async function compile(options: CompilerOptions): Promise<CompileResult>
         outputPath,
         logger,
         transformTsConfigPathMappings,
+        module: options.module ?? 'commonjs',
     });
     logger.info(`TypeScript compilation completed in ${Date.now() - compileStart}ms`);
 
@@ -86,7 +88,7 @@ export async function compile(options: CompilerOptions): Promise<CompileResult>
     // Create package.json with type commonjs
     await fs.writeFile(
         path.join(outputPath, 'package.json'),
-        JSON.stringify({ type: 'commonjs', private: true }, null, 2),
+        JSON.stringify({ type: options.module === 'esm' ? 'module' : 'commonjs', private: true }, null, 2),
     );
 
     // Find the exported config symbol
@@ -137,11 +139,13 @@ async function compileTypeScript({
     outputPath,
     logger,
     transformTsConfigPathMappings,
+    module,
 }: {
     inputPath: string;
     outputPath: string;
     logger: Logger;
     transformTsConfigPathMappings: Required<PathAdapter>['transformTsConfigPathMappings'];
+    module: 'commonjs' | 'esm';
 }): Promise<void> {
     await fs.ensureDir(outputPath);
 
@@ -155,7 +159,7 @@ async function compileTypeScript({
 
     const compilerOptions: ts.CompilerOptions = {
         target: ts.ScriptTarget.ES2020,
-        module: ts.ModuleKind.CommonJS,
+        module: module === 'esm' ? ts.ModuleKind.ESNext : ts.ModuleKind.CommonJS,
         moduleResolution: ts.ModuleResolutionKind.Node10, // More explicit CJS resolution
         experimentalDecorators: true,
         emitDecoratorMetadata: true,

+ 13 - 0
packages/dashboard/vite/vite-plugin-vendure-dashboard.ts

@@ -93,6 +93,18 @@ export type VitePluginVendureDashboardOptions = {
      * the location based on the location of the `@vendure/core` package.
      */
     pluginPackageScanner?: PackageScannerConfig;
+    /**
+     * @description
+     * Allows you to specify the module system to use when compiling and loading your Vendure config.
+     * By default, the compiler will use CommonJS, but you can set it to `esm` if you are using
+     * ES Modules in your Vendure project.
+     *
+     * **Status** Developer preview. If you are using ESM please try this out and provide us with feedback!
+     *
+     * @since 3.5.1
+     * @default 'commonjs'
+     */
+    module?: 'commonjs' | 'esm';
     /**
      * @description
      * Allows you to selectively disable individual plugins.
@@ -204,6 +216,7 @@ export function vendureDashboardPlugin(options: VitePluginVendureDashboardOption
                     outputPath: tempDir,
                     pathAdapter: options.pathAdapter,
                     pluginPackageScanner: options.pluginPackageScanner,
+                    module: options.module,
                 }),
         },
         {