@vendure/dashboard 3.3.5-master-202506241144 → 3.3.5-master-202506241446

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,9 +9,77 @@ export type PluginInfo = {
9
9
  pluginPath: string;
10
10
  dashboardEntryPath: string | undefined;
11
11
  };
12
+ /**
13
+ * @description
14
+ * The PathAdapter interface allows customization of how paths are handled
15
+ * when compiling the Vendure config and its imports.
16
+ *
17
+ * This is particularly useful in complex project structures, such as monorepos,
18
+ * where the Vendure config file may not be in the root directory,
19
+ * or when you need to transform TypeScript path mappings.
20
+ */
21
+ export interface PathAdapter {
22
+ /**
23
+ * @description
24
+ * A function to determine the path to the compiled Vendure config file. The default implementation
25
+ * simple joins the output directory with the config file name:
26
+ *
27
+ * ```ts
28
+ * return path.join(outputPath, configFileName)
29
+ * ```
30
+ *
31
+ * However, in some cases with more complex project structures, you may need to
32
+ * provide a custom implementation to ensure the compiled config file is
33
+ * correctly located.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * getCompiledConfigPath: ({ inputRootDir, outputPath, configFileName }) => {
38
+ * const projectName = inputRootDir.split('/libs/')[1].split('/')[0];
39
+ * const pathAfterProject = inputRootDir.split(`/libs/${projectName}`)[1];
40
+ * const compiledConfigFilePath = `${outputPath}/${projectName}${pathAfterProject}`;
41
+ * return path.join(compiledConfigFilePath, configFileName);
42
+ * },
43
+ * ```
44
+ */
45
+ getCompiledConfigPath?: (params: {
46
+ inputRootDir: string;
47
+ outputPath: string;
48
+ configFileName: string;
49
+ }) => string;
50
+ /**
51
+ * If your project makes use of the TypeScript `paths` configuration, the compiler will
52
+ * attempt to use these paths when compiling the Vendure config and its imports.
53
+ *
54
+ * In certain cases, you may need to transform these paths before they are used. For instance,
55
+ * if your project is a monorepo and the paths are defined relative to the root of the monorepo,
56
+ * you may need to adjust them to be relative to the output directory where the compiled files are located.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * transformTsConfigPathMappings: ({ phase, patterns }) => {
61
+ * // "loading" phase is when the compiled Vendure code is being loaded by
62
+ * // the plugin, in order to introspect the configuration of your app.
63
+ * if (phase === 'loading') {
64
+ * return patterns.map((p) =>
65
+ * p.replace('libs/', '').replace(/.ts$/, '.js'),
66
+ * );
67
+ * }
68
+ * return patterns;
69
+ * },
70
+ * ```
71
+ * @param params
72
+ */
73
+ transformTsConfigPathMappings?: (params: {
74
+ phase: 'compiling' | 'loading';
75
+ alias: string;
76
+ patterns: string[];
77
+ }) => string[];
78
+ }
12
79
  export interface ConfigLoaderOptions {
13
80
  vendureConfigPath: string;
14
81
  tempDir: string;
82
+ pathAdapter?: PathAdapter;
15
83
  vendureConfigExport?: string;
16
84
  logger?: Logger;
17
85
  reportCompilationErrors?: boolean;
@@ -42,11 +110,12 @@ type CompileFileOptions = {
42
110
  inputRootDir: string;
43
111
  inputPath: string;
44
112
  outputDir: string;
113
+ transformTsConfigPathMappings: Required<PathAdapter>['transformTsConfigPathMappings'];
45
114
  logger?: Logger;
46
115
  compiledFiles?: Set<string>;
47
116
  isRoot?: boolean;
48
117
  pluginInfo?: PluginInfo[];
49
118
  reportCompilationErrors?: boolean;
50
119
  };
51
- export declare function compileFile({ inputRootDir, inputPath, outputDir, logger, compiledFiles, isRoot, pluginInfo, reportCompilationErrors, }: CompileFileOptions): Promise<PluginInfo[]>;
120
+ export declare function compileFile({ inputRootDir, inputPath, outputDir, transformTsConfigPathMappings, logger, compiledFiles, isRoot, pluginInfo, reportCompilationErrors, }: CompileFileOptions): Promise<PluginInfo[]>;
52
121
  export {};
@@ -15,6 +15,10 @@ const defaultLogger = {
15
15
  /* noop */
16
16
  },
17
17
  };
18
+ const defaultPathAdapter = {
19
+ getCompiledConfigPath: ({ outputPath, configFileName }) => path.join(outputPath, configFileName),
20
+ transformTsConfigPathMappings: ({ patterns }) => patterns,
21
+ };
18
22
  /**
19
23
  * @description
20
24
  * This function compiles the given Vendure config file and any imported relative files (i.e.
@@ -32,7 +36,10 @@ const defaultLogger = {
32
36
  * to handle the compiled JavaScript output.
33
37
  */
34
38
  export async function loadVendureConfig(options) {
35
- const { vendureConfigPath, vendureConfigExport, tempDir } = options;
39
+ var _a, _b;
40
+ const { vendureConfigPath, vendureConfigExport, tempDir, pathAdapter } = options;
41
+ const getCompiledConfigPath = (_a = pathAdapter === null || pathAdapter === void 0 ? void 0 : pathAdapter.getCompiledConfigPath) !== null && _a !== void 0 ? _a : defaultPathAdapter.getCompiledConfigPath;
42
+ const transformTsConfigPathMappings = (_b = pathAdapter === null || pathAdapter === void 0 ? void 0 : pathAdapter.transformTsConfigPathMappings) !== null && _b !== void 0 ? _b : defaultPathAdapter.transformTsConfigPathMappings;
36
43
  const logger = options.logger || defaultLogger;
37
44
  const outputPath = tempDir;
38
45
  const configFileName = path.basename(vendureConfigPath);
@@ -43,8 +50,13 @@ export async function loadVendureConfig(options) {
43
50
  inputPath: vendureConfigPath,
44
51
  outputDir: outputPath,
45
52
  logger,
53
+ transformTsConfigPathMappings,
46
54
  });
47
- const compiledConfigFilePath = pathToFileURL(path.join(outputPath, configFileName)).href.replace(/.ts$/, '.js');
55
+ const compiledConfigFilePath = pathToFileURL(getCompiledConfigPath({
56
+ inputRootDir,
57
+ outputPath,
58
+ configFileName,
59
+ })).href.replace(/.ts$/, '.js');
48
60
  // create package.json with type commonjs and save it to the output dir
49
61
  await fs.writeFile(path.join(outputPath, 'package.json'), JSON.stringify({ type: 'commonjs' }, null, 2));
50
62
  // We need to figure out the symbol exported by the config file by
@@ -56,7 +68,7 @@ export async function loadVendureConfig(options) {
56
68
  throw new Error(`Could not find a variable exported as VendureConfig. Please specify the name of the exported variable using the "vendureConfigExport" option.`);
57
69
  }
58
70
  // Register path aliases from tsconfig before importing
59
- const tsConfigInfo = await findTsConfigPaths(vendureConfigPath, logger);
71
+ const tsConfigInfo = await findTsConfigPaths(vendureConfigPath, logger, 'loading', transformTsConfigPathMappings);
60
72
  if (tsConfigInfo) {
61
73
  tsConfigPaths.register({
62
74
  baseUrl: outputPath,
@@ -73,7 +85,7 @@ export async function loadVendureConfig(options) {
73
85
  * Finds and parses tsconfig files in the given directory and its parent directories.
74
86
  * Returns the paths configuration if found.
75
87
  */
76
- async function findTsConfigPaths(configPath, logger) {
88
+ async function findTsConfigPaths(configPath, logger, phase, transformTsConfigPathMappings) {
77
89
  const configDir = path.dirname(configPath);
78
90
  let currentDir = configDir;
79
91
  while (currentDir !== path.parse(currentDir).root) {
@@ -94,9 +106,14 @@ async function findTsConfigPaths(configPath, logger) {
94
106
  const paths = {};
95
107
  for (const [alias, patterns] of Object.entries(compilerOptions.paths)) {
96
108
  // Store paths as defined in tsconfig, they will be relative to baseUrl
97
- paths[alias] = patterns.map(pattern =>
109
+ const normalizedPatterns = patterns.map(pattern =>
98
110
  // Normalize slashes for consistency, keep relative
99
111
  pattern.replace(/\\/g, '/'));
112
+ paths[alias] = transformTsConfigPathMappings({
113
+ phase,
114
+ alias,
115
+ patterns: normalizedPatterns,
116
+ });
100
117
  }
101
118
  logger.debug(`Found tsconfig paths in ${tsConfigPath}: ${JSON.stringify({
102
119
  baseUrl: tsConfigBaseUrl,
@@ -119,7 +136,7 @@ async function findTsConfigPaths(configPath, logger) {
119
136
  logger.debug(`No tsconfig paths found traversing up from ${configDir}`);
120
137
  return undefined;
121
138
  }
122
- export async function compileFile({ inputRootDir, inputPath, outputDir, logger = defaultLogger, compiledFiles = new Set(), isRoot = true, pluginInfo = [], reportCompilationErrors = false, }) {
139
+ export async function compileFile({ inputRootDir, inputPath, outputDir, transformTsConfigPathMappings, logger = defaultLogger, compiledFiles = new Set(), isRoot = true, pluginInfo = [], reportCompilationErrors = false, }) {
123
140
  const absoluteInputPath = path.resolve(inputPath);
124
141
  if (compiledFiles.has(absoluteInputPath)) {
125
142
  return pluginInfo;
@@ -134,7 +151,7 @@ export async function compileFile({ inputRootDir, inputPath, outputDir, logger =
134
151
  const importPaths = new Set();
135
152
  let tsConfigInfo;
136
153
  if (isRoot) {
137
- tsConfigInfo = await findTsConfigPaths(absoluteInputPath, logger);
154
+ tsConfigInfo = await findTsConfigPaths(absoluteInputPath, logger, 'compiling', transformTsConfigPathMappings);
138
155
  if (tsConfigInfo) {
139
156
  logger === null || logger === void 0 ? void 0 : logger.debug(`Using TypeScript configuration: ${JSON.stringify(tsConfigInfo, null, 2)}`);
140
157
  }
@@ -263,6 +280,7 @@ export async function compileFile({ inputRootDir, inputPath, outputDir, logger =
263
280
  inputPath: importPath,
264
281
  outputDir,
265
282
  logger,
283
+ transformTsConfigPathMappings,
266
284
  compiledFiles,
267
285
  isRoot: false,
268
286
  pluginInfo,
@@ -14,6 +14,7 @@ export function configLoaderPlugin(options) {
14
14
  try {
15
15
  const startTime = Date.now();
16
16
  result = await loadVendureConfig({
17
+ pathAdapter: options.pathAdapter,
17
18
  tempDir: options.tempDir,
18
19
  vendureConfigPath: options.vendureConfigPath,
19
20
  vendureConfigExport: options.vendureConfigExport,
@@ -31,7 +32,11 @@ export function configLoaderPlugin(options) {
31
32
  }
32
33
  catch (e) {
33
34
  if (e instanceof Error) {
34
- this.error(`Error loading Vendure config: ${e.message}`);
35
+ const message = [
36
+ e.message,
37
+ `If you are using a monorepo, you may need to provide a custom pathAdapter to resolve the paths correctly.`,
38
+ ].join('\n');
39
+ this.error(`Error loading Vendure config: ${message}`);
35
40
  }
36
41
  }
37
42
  onConfigLoaded.forEach(fn => fn());
@@ -1,4 +1,5 @@
1
1
  import { PluginOption } from 'vite';
2
+ import { PathAdapter } from './utils/config-loader.js';
2
3
  import { ThemeVariablesPluginOptions } from './vite-plugin-theme.js';
3
4
  import { UiConfigPluginOptions } from './vite-plugin-ui-config.js';
4
5
  /**
@@ -11,6 +12,46 @@ export type VitePluginVendureDashboardOptions = {
11
12
  * The path to the Vendure server configuration file.
12
13
  */
13
14
  vendureConfigPath: string | URL;
15
+ /**
16
+ * @description
17
+ * The {@link PathAdapter} allows you to customize the resolution of paths
18
+ * in the compiled Vendure source code which is used as part of the
19
+ * introspection step of building the dashboard.
20
+ *
21
+ * It enables support for more complex repository structures, such as
22
+ * monorepos, where the Vendure server configuration file may not
23
+ * be located in the root directory of the project.
24
+ *
25
+ * If you get compilation errors like "Error loading Vendure config: Cannot find module",
26
+ * you probably need to provide a custom `pathAdapter` to resolve the paths correctly.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * vendureDashboardPlugin({
31
+ * tempCompilationDir: join(__dirname, './__vendure-dashboard-temp'),
32
+ * pathAdapter: {
33
+ * getCompiledConfigPath: ({ inputRootDir, outputPath, configFileName }) => {
34
+ * const projectName = inputRootDir.split('/libs/')[1].split('/')[0];
35
+ * const pathAfterProject = inputRootDir.split(`/libs/${projectName}`)[1];
36
+ * const compiledConfigFilePath = `${outputPath}/${projectName}${pathAfterProject}`;
37
+ * return path.join(compiledConfigFilePath, configFileName);
38
+ * },
39
+ * transformTsConfigPathMappings: ({ phase, patterns }) => {
40
+ * // "loading" phase is when the compiled Vendure code is being loaded by
41
+ * // the plugin, in order to introspect the configuration of your app.
42
+ * if (phase === 'loading') {
43
+ * return patterns.map((p) =>
44
+ * p.replace('libs/', '').replace(/.ts$/, '.js'),
45
+ * );
46
+ * }
47
+ * return patterns;
48
+ * },
49
+ * },
50
+ * // ...
51
+ * }),
52
+ * ```
53
+ */
54
+ pathAdapter?: PathAdapter;
14
55
  /**
15
56
  * @description
16
57
  * The name of the exported variable from the Vendure server configuration file.
@@ -47,6 +47,7 @@ export function vendureDashboardPlugin(options) {
47
47
  vendureConfigPath: normalizedVendureConfigPath,
48
48
  tempDir,
49
49
  reportCompilationErrors: options.reportCompilationErrors,
50
+ pathAdapter: options.pathAdapter,
50
51
  }),
51
52
  viteConfigPlugin({ packageRoot }),
52
53
  adminApiSchemaPlugin(),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vendure/dashboard",
3
3
  "private": false,
4
- "version": "3.3.5-master-202506241144",
4
+ "version": "3.3.5-master-202506241446",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "type": "git",
@@ -86,8 +86,8 @@
86
86
  "@types/react-dom": "^19.0.4",
87
87
  "@types/react-grid-layout": "^1.3.5",
88
88
  "@uidotdev/usehooks": "^2.4.1",
89
- "@vendure/common": "^3.3.5-master-202506241144",
90
- "@vendure/core": "^3.3.5-master-202506241144",
89
+ "@vendure/common": "^3.3.5-master-202506241446",
90
+ "@vendure/core": "^3.3.5-master-202506241446",
91
91
  "@vitejs/plugin-react": "^4.3.4",
92
92
  "awesome-graphql-client": "^2.1.0",
93
93
  "class-variance-authority": "^0.7.1",
@@ -130,5 +130,5 @@
130
130
  "lightningcss-linux-arm64-musl": "^1.29.3",
131
131
  "lightningcss-linux-x64-musl": "^1.29.1"
132
132
  },
133
- "gitHead": "6998254d4bfdad0e2d963ac242777aae4d18a46d"
133
+ "gitHead": "87c4cecdb30f3c14ca2935ab3c573ddfcaa826e9"
134
134
  }
@@ -150,7 +150,6 @@ export interface DashboardExtension {
150
150
  * given components and optionally also add a nav menu item.
151
151
  */
152
152
  widgets?: DashboardWidgetDefinition[];
153
-
154
153
  /**
155
154
  * @description
156
155
  * Allows you to define custom form components for custom fields in the dashboard.
@@ -31,9 +31,83 @@ const defaultLogger: Logger = {
31
31
  },
32
32
  };
33
33
 
34
+ /**
35
+ * @description
36
+ * The PathAdapter interface allows customization of how paths are handled
37
+ * when compiling the Vendure config and its imports.
38
+ *
39
+ * This is particularly useful in complex project structures, such as monorepos,
40
+ * where the Vendure config file may not be in the root directory,
41
+ * or when you need to transform TypeScript path mappings.
42
+ */
43
+ export interface PathAdapter {
44
+ /**
45
+ * @description
46
+ * A function to determine the path to the compiled Vendure config file. The default implementation
47
+ * simple joins the output directory with the config file name:
48
+ *
49
+ * ```ts
50
+ * return path.join(outputPath, configFileName)
51
+ * ```
52
+ *
53
+ * However, in some cases with more complex project structures, you may need to
54
+ * provide a custom implementation to ensure the compiled config file is
55
+ * correctly located.
56
+ *
57
+ * @example
58
+ * ```ts
59
+ * getCompiledConfigPath: ({ inputRootDir, outputPath, configFileName }) => {
60
+ * const projectName = inputRootDir.split('/libs/')[1].split('/')[0];
61
+ * const pathAfterProject = inputRootDir.split(`/libs/${projectName}`)[1];
62
+ * const compiledConfigFilePath = `${outputPath}/${projectName}${pathAfterProject}`;
63
+ * return path.join(compiledConfigFilePath, configFileName);
64
+ * },
65
+ * ```
66
+ */
67
+ getCompiledConfigPath?: (params: {
68
+ inputRootDir: string;
69
+ outputPath: string;
70
+ configFileName: string;
71
+ }) => string;
72
+ /**
73
+ * If your project makes use of the TypeScript `paths` configuration, the compiler will
74
+ * attempt to use these paths when compiling the Vendure config and its imports.
75
+ *
76
+ * In certain cases, you may need to transform these paths before they are used. For instance,
77
+ * if your project is a monorepo and the paths are defined relative to the root of the monorepo,
78
+ * you may need to adjust them to be relative to the output directory where the compiled files are located.
79
+ *
80
+ * @example
81
+ * ```ts
82
+ * transformTsConfigPathMappings: ({ phase, patterns }) => {
83
+ * // "loading" phase is when the compiled Vendure code is being loaded by
84
+ * // the plugin, in order to introspect the configuration of your app.
85
+ * if (phase === 'loading') {
86
+ * return patterns.map((p) =>
87
+ * p.replace('libs/', '').replace(/.ts$/, '.js'),
88
+ * );
89
+ * }
90
+ * return patterns;
91
+ * },
92
+ * ```
93
+ * @param params
94
+ */
95
+ transformTsConfigPathMappings?: (params: {
96
+ phase: 'compiling' | 'loading';
97
+ alias: string;
98
+ patterns: string[];
99
+ }) => string[];
100
+ }
101
+
102
+ const defaultPathAdapter: Required<PathAdapter> = {
103
+ getCompiledConfigPath: ({ outputPath, configFileName }) => path.join(outputPath, configFileName),
104
+ transformTsConfigPathMappings: ({ patterns }) => patterns,
105
+ };
106
+
34
107
  export interface ConfigLoaderOptions {
35
108
  vendureConfigPath: string;
36
109
  tempDir: string;
110
+ pathAdapter?: PathAdapter;
37
111
  vendureConfigExport?: string;
38
112
  logger?: Logger;
39
113
  reportCompilationErrors?: boolean;
@@ -62,7 +136,11 @@ export interface LoadVendureConfigResult {
62
136
  * to handle the compiled JavaScript output.
63
137
  */
64
138
  export async function loadVendureConfig(options: ConfigLoaderOptions): Promise<LoadVendureConfigResult> {
65
- const { vendureConfigPath, vendureConfigExport, tempDir } = options;
139
+ const { vendureConfigPath, vendureConfigExport, tempDir, pathAdapter } = options;
140
+ const getCompiledConfigPath =
141
+ pathAdapter?.getCompiledConfigPath ?? defaultPathAdapter.getCompiledConfigPath;
142
+ const transformTsConfigPathMappings =
143
+ pathAdapter?.transformTsConfigPathMappings ?? defaultPathAdapter.transformTsConfigPathMappings;
66
144
  const logger = options.logger || defaultLogger;
67
145
  const outputPath = tempDir;
68
146
  const configFileName = path.basename(vendureConfigPath);
@@ -73,11 +151,15 @@ export async function loadVendureConfig(options: ConfigLoaderOptions): Promise<L
73
151
  inputPath: vendureConfigPath,
74
152
  outputDir: outputPath,
75
153
  logger,
154
+ transformTsConfigPathMappings,
76
155
  });
77
- const compiledConfigFilePath = pathToFileURL(path.join(outputPath, configFileName)).href.replace(
78
- /.ts$/,
79
- '.js',
80
- );
156
+ const compiledConfigFilePath = pathToFileURL(
157
+ getCompiledConfigPath({
158
+ inputRootDir,
159
+ outputPath,
160
+ configFileName,
161
+ }),
162
+ ).href.replace(/.ts$/, '.js');
81
163
  // create package.json with type commonjs and save it to the output dir
82
164
  await fs.writeFile(path.join(outputPath, 'package.json'), JSON.stringify({ type: 'commonjs' }, null, 2));
83
165
 
@@ -98,7 +180,12 @@ export async function loadVendureConfig(options: ConfigLoaderOptions): Promise<L
98
180
  }
99
181
 
100
182
  // Register path aliases from tsconfig before importing
101
- const tsConfigInfo = await findTsConfigPaths(vendureConfigPath, logger);
183
+ const tsConfigInfo = await findTsConfigPaths(
184
+ vendureConfigPath,
185
+ logger,
186
+ 'loading',
187
+ transformTsConfigPathMappings,
188
+ );
102
189
  if (tsConfigInfo) {
103
190
  tsConfigPaths.register({
104
191
  baseUrl: outputPath,
@@ -122,6 +209,8 @@ export async function loadVendureConfig(options: ConfigLoaderOptions): Promise<L
122
209
  async function findTsConfigPaths(
123
210
  configPath: string,
124
211
  logger: Logger,
212
+ phase: 'compiling' | 'loading',
213
+ transformTsConfigPathMappings: Required<PathAdapter>['transformTsConfigPathMappings'],
125
214
  ): Promise<{ baseUrl: string; paths: Record<string, string[]> } | undefined> {
126
215
  const configDir = path.dirname(configPath);
127
216
  let currentDir = configDir;
@@ -147,10 +236,15 @@ async function findTsConfigPaths(
147
236
 
148
237
  for (const [alias, patterns] of Object.entries(compilerOptions.paths)) {
149
238
  // Store paths as defined in tsconfig, they will be relative to baseUrl
150
- paths[alias] = (patterns as string[]).map(pattern =>
239
+ const normalizedPatterns = (patterns as string[]).map(pattern =>
151
240
  // Normalize slashes for consistency, keep relative
152
241
  pattern.replace(/\\/g, '/'),
153
242
  );
243
+ paths[alias] = transformTsConfigPathMappings({
244
+ phase,
245
+ alias,
246
+ patterns: normalizedPatterns,
247
+ });
154
248
  }
155
249
  logger.debug(
156
250
  `Found tsconfig paths in ${tsConfigPath}: ${JSON.stringify(
@@ -184,6 +278,7 @@ type CompileFileOptions = {
184
278
  inputRootDir: string;
185
279
  inputPath: string;
186
280
  outputDir: string;
281
+ transformTsConfigPathMappings: Required<PathAdapter>['transformTsConfigPathMappings'];
187
282
  logger?: Logger;
188
283
  compiledFiles?: Set<string>;
189
284
  isRoot?: boolean;
@@ -195,6 +290,7 @@ export async function compileFile({
195
290
  inputRootDir,
196
291
  inputPath,
197
292
  outputDir,
293
+ transformTsConfigPathMappings,
198
294
  logger = defaultLogger,
199
295
  compiledFiles = new Set<string>(),
200
296
  isRoot = true,
@@ -220,7 +316,12 @@ export async function compileFile({
220
316
  let tsConfigInfo: { baseUrl: string; paths: Record<string, string[]> } | undefined;
221
317
 
222
318
  if (isRoot) {
223
- tsConfigInfo = await findTsConfigPaths(absoluteInputPath, logger);
319
+ tsConfigInfo = await findTsConfigPaths(
320
+ absoluteInputPath,
321
+ logger,
322
+ 'compiling',
323
+ transformTsConfigPathMappings,
324
+ );
224
325
  if (tsConfigInfo) {
225
326
  logger?.debug(`Using TypeScript configuration: ${JSON.stringify(tsConfigInfo, null, 2)}`);
226
327
  }
@@ -355,6 +456,7 @@ export async function compileFile({
355
456
  inputPath: importPath,
356
457
  outputDir,
357
458
  logger,
459
+ transformTsConfigPathMappings,
358
460
  compiledFiles,
359
461
  isRoot: false,
360
462
  pluginInfo,
@@ -24,6 +24,7 @@ export function configLoaderPlugin(options: ConfigLoaderOptions): Plugin {
24
24
  try {
25
25
  const startTime = Date.now();
26
26
  result = await loadVendureConfig({
27
+ pathAdapter: options.pathAdapter,
27
28
  tempDir: options.tempDir,
28
29
  vendureConfigPath: options.vendureConfigPath,
29
30
  vendureConfigExport: options.vendureConfigExport,
@@ -42,7 +43,11 @@ export function configLoaderPlugin(options: ConfigLoaderOptions): Plugin {
42
43
  );
43
44
  } catch (e: unknown) {
44
45
  if (e instanceof Error) {
45
- this.error(`Error loading Vendure config: ${e.message}`);
46
+ const message = [
47
+ e.message,
48
+ `If you are using a monorepo, you may need to provide a custom pathAdapter to resolve the paths correctly.`,
49
+ ].join('\n');
50
+ this.error(`Error loading Vendure config: ${message}`);
46
51
  }
47
52
  }
48
53
  onConfigLoaded.forEach(fn => fn());
@@ -4,6 +4,7 @@ import react from '@vitejs/plugin-react';
4
4
  import path from 'path';
5
5
  import { PluginOption } from 'vite';
6
6
 
7
+ import { PathAdapter } from './utils/config-loader.js';
7
8
  import { adminApiSchemaPlugin } from './vite-plugin-admin-api-schema.js';
8
9
  import { configLoaderPlugin } from './vite-plugin-config-loader.js';
9
10
  import { viteConfigPlugin } from './vite-plugin-config.js';
@@ -23,6 +24,46 @@ export type VitePluginVendureDashboardOptions = {
23
24
  * The path to the Vendure server configuration file.
24
25
  */
25
26
  vendureConfigPath: string | URL;
27
+ /**
28
+ * @description
29
+ * The {@link PathAdapter} allows you to customize the resolution of paths
30
+ * in the compiled Vendure source code which is used as part of the
31
+ * introspection step of building the dashboard.
32
+ *
33
+ * It enables support for more complex repository structures, such as
34
+ * monorepos, where the Vendure server configuration file may not
35
+ * be located in the root directory of the project.
36
+ *
37
+ * If you get compilation errors like "Error loading Vendure config: Cannot find module",
38
+ * you probably need to provide a custom `pathAdapter` to resolve the paths correctly.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * vendureDashboardPlugin({
43
+ * tempCompilationDir: join(__dirname, './__vendure-dashboard-temp'),
44
+ * pathAdapter: {
45
+ * getCompiledConfigPath: ({ inputRootDir, outputPath, configFileName }) => {
46
+ * const projectName = inputRootDir.split('/libs/')[1].split('/')[0];
47
+ * const pathAfterProject = inputRootDir.split(`/libs/${projectName}`)[1];
48
+ * const compiledConfigFilePath = `${outputPath}/${projectName}${pathAfterProject}`;
49
+ * return path.join(compiledConfigFilePath, configFileName);
50
+ * },
51
+ * transformTsConfigPathMappings: ({ phase, patterns }) => {
52
+ * // "loading" phase is when the compiled Vendure code is being loaded by
53
+ * // the plugin, in order to introspect the configuration of your app.
54
+ * if (phase === 'loading') {
55
+ * return patterns.map((p) =>
56
+ * p.replace('libs/', '').replace(/.ts$/, '.js'),
57
+ * );
58
+ * }
59
+ * return patterns;
60
+ * },
61
+ * },
62
+ * // ...
63
+ * }),
64
+ * ```
65
+ */
66
+ pathAdapter?: PathAdapter;
26
67
  /**
27
68
  * @description
28
69
  * The name of the exported variable from the Vendure server configuration file.
@@ -85,6 +126,7 @@ export function vendureDashboardPlugin(options: VitePluginVendureDashboardOption
85
126
  vendureConfigPath: normalizedVendureConfigPath,
86
127
  tempDir,
87
128
  reportCompilationErrors: options.reportCompilationErrors,
129
+ pathAdapter: options.pathAdapter,
88
130
  }),
89
131
  viteConfigPlugin({ packageRoot }),
90
132
  adminApiSchemaPlugin(),