@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.
- package/dist/plugin/utils/config-loader.d.ts +70 -1
- package/dist/plugin/utils/config-loader.js +25 -7
- package/dist/plugin/vite-plugin-config-loader.js +6 -1
- package/dist/plugin/vite-plugin-vendure-dashboard.d.ts +41 -0
- package/dist/plugin/vite-plugin-vendure-dashboard.js +1 -0
- package/package.json +4 -4
- package/src/lib/framework/extension-api/extension-api-types.ts +0 -1
- package/vite/utils/config-loader.ts +110 -8
- package/vite/vite-plugin-config-loader.ts +6 -1
- package/vite/vite-plugin-vendure-dashboard.ts +42 -0
|
@@ -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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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-
|
|
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-
|
|
90
|
-
"@vendure/core": "^3.3.5-master-
|
|
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": "
|
|
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(
|
|
78
|
-
|
|
79
|
-
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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(),
|