@vendure/dashboard 3.4.1-master-202508030248 → 3.4.1-master-202508050244

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.
Files changed (44) hide show
  1. package/dist/vite/utils/schema-generator.js +17 -12
  2. package/package.json +154 -155
  3. package/vite/constants.ts +0 -280
  4. package/vite/index.ts +0 -1
  5. package/vite/tests/barrel-exports.spec.ts +0 -30
  6. package/vite/tests/fixtures-barrel-exports/my-plugin/index.ts +0 -1
  7. package/vite/tests/fixtures-barrel-exports/my-plugin/src/my.plugin.ts +0 -8
  8. package/vite/tests/fixtures-barrel-exports/package.json +0 -6
  9. package/vite/tests/fixtures-barrel-exports/vendure-config.ts +0 -19
  10. package/vite/tests/fixtures-npm-plugin/fake_node_modules/test-plugin/index.js +0 -20
  11. package/vite/tests/fixtures-npm-plugin/fake_node_modules/test-plugin/package.json +0 -8
  12. package/vite/tests/fixtures-npm-plugin/package.json +0 -6
  13. package/vite/tests/fixtures-npm-plugin/vendure-config.ts +0 -18
  14. package/vite/tests/fixtures-path-alias/js-aliased/index.ts +0 -1
  15. package/vite/tests/fixtures-path-alias/js-aliased/src/js-aliased.plugin.ts +0 -8
  16. package/vite/tests/fixtures-path-alias/package.json +0 -6
  17. package/vite/tests/fixtures-path-alias/star-aliased/index.ts +0 -1
  18. package/vite/tests/fixtures-path-alias/star-aliased/src/star-aliased.plugin.ts +0 -8
  19. package/vite/tests/fixtures-path-alias/ts-aliased/index.ts +0 -1
  20. package/vite/tests/fixtures-path-alias/ts-aliased/src/ts-aliased.plugin.ts +0 -8
  21. package/vite/tests/fixtures-path-alias/vendure-config.ts +0 -20
  22. package/vite/tests/npm-plugin.spec.ts +0 -46
  23. package/vite/tests/path-alias.spec.ts +0 -61
  24. package/vite/tests/tsconfig.json +0 -21
  25. package/vite/types.ts +0 -44
  26. package/vite/utils/ast-utils.spec.ts +0 -49
  27. package/vite/utils/ast-utils.ts +0 -33
  28. package/vite/utils/compiler.ts +0 -244
  29. package/vite/utils/config-loader.ts +0 -0
  30. package/vite/utils/logger.ts +0 -43
  31. package/vite/utils/plugin-discovery.ts +0 -494
  32. package/vite/utils/schema-generator.ts +0 -45
  33. package/vite/utils/tsconfig-utils.ts +0 -79
  34. package/vite/utils/ui-config.ts +0 -52
  35. package/vite/vite-plugin-admin-api-schema.ts +0 -131
  36. package/vite/vite-plugin-config-loader.ts +0 -84
  37. package/vite/vite-plugin-config.ts +0 -70
  38. package/vite/vite-plugin-dashboard-metadata.ts +0 -73
  39. package/vite/vite-plugin-gql-tada.ts +0 -62
  40. package/vite/vite-plugin-tailwind-source.ts +0 -81
  41. package/vite/vite-plugin-theme.ts +0 -195
  42. package/vite/vite-plugin-transform-index.ts +0 -40
  43. package/vite/vite-plugin-ui-config.ts +0 -163
  44. package/vite/vite-plugin-vendure-dashboard.ts +0 -174
@@ -1,494 +0,0 @@
1
- import { parse } from 'acorn';
2
- import { simple as walkSimple } from 'acorn-walk';
3
- import glob from 'fast-glob';
4
- import fs from 'fs-extra';
5
- import { open } from 'fs/promises';
6
- import path from 'path';
7
- import * as ts from 'typescript';
8
- import { fileURLToPath } from 'url';
9
-
10
- import { Logger, PluginInfo, TransformTsConfigPathMappingsFn } from '../types.js';
11
-
12
- import { PackageScannerConfig } from './compiler.js';
13
- import { findTsConfigPaths, TsConfigPathsConfig } from './tsconfig-utils.js';
14
-
15
- export async function discoverPlugins({
16
- vendureConfigPath,
17
- transformTsConfigPathMappings,
18
- logger,
19
- outputPath,
20
- pluginPackageScanner,
21
- }: {
22
- vendureConfigPath: string;
23
- transformTsConfigPathMappings: TransformTsConfigPathMappingsFn;
24
- logger: Logger;
25
- outputPath: string;
26
- pluginPackageScanner?: PackageScannerConfig;
27
- }): Promise<PluginInfo[]> {
28
- const plugins: PluginInfo[] = [];
29
-
30
- // Analyze source files to find local plugins and package imports
31
- const { localPluginLocations, packageImports } = await analyzeSourceFiles(
32
- vendureConfigPath,
33
- pluginPackageScanner?.nodeModulesRoot ?? guessNodeModulesRoot(vendureConfigPath, logger),
34
- logger,
35
- transformTsConfigPathMappings,
36
- );
37
- logger.debug(
38
- `[discoverPlugins] Found ${localPluginLocations.size} local plugins: ${JSON.stringify([...localPluginLocations.entries()], null, 2)}`,
39
- );
40
- logger.debug(
41
- `[discoverPlugins] Found ${packageImports.length} package imports: ${JSON.stringify(packageImports, null, 2)}`,
42
- );
43
-
44
- const filePaths = await findVendurePluginFiles({
45
- logger,
46
- nodeModulesRoot: pluginPackageScanner?.nodeModulesRoot,
47
- packageGlobs: packageImports.map(pkg => pkg + '/**/*.js'),
48
- outputPath,
49
- vendureConfigPath,
50
- });
51
-
52
- for (const filePath of filePaths) {
53
- const content = await fs.readFile(filePath, 'utf-8');
54
- logger.debug(`[discoverPlugins] Checking file ${filePath}`);
55
-
56
- // First check if this file imports from @vendure/core
57
- if (!content.includes('@vendure/core')) {
58
- continue;
59
- }
60
-
61
- try {
62
- const ast = parse(content, {
63
- ecmaVersion: 'latest',
64
- sourceType: 'module',
65
- });
66
-
67
- let hasVendurePlugin = false;
68
- let pluginName: string | undefined;
69
- let dashboardPath: string | undefined;
70
-
71
- // Walk the AST to find the plugin class and its decorator
72
- walkSimple(ast, {
73
- CallExpression(node: any) {
74
- // Look for __decorate calls
75
- const calleeName = node.callee.name;
76
- const nodeArgs = node.arguments;
77
- const isDecoratorWithArgs = calleeName === '__decorate' && nodeArgs.length >= 2;
78
-
79
- if (isDecoratorWithArgs) {
80
- // Check the decorators array (first argument)
81
- const decorators = nodeArgs[0];
82
- if (decorators.type === 'ArrayExpression') {
83
- for (const decorator of decorators.elements) {
84
- const props = getDecoratorObjectProps(decorator);
85
- for (const prop of props) {
86
- const isDashboardProd =
87
- prop.key.name === 'dashboard' && prop.value.type === 'Literal';
88
- if (isDashboardProd) {
89
- dashboardPath = prop.value.value;
90
- hasVendurePlugin = true;
91
- }
92
- }
93
- }
94
- }
95
- // Get the plugin class name (second argument)
96
- const targetClass = nodeArgs[1];
97
- if (targetClass.type === 'Identifier') {
98
- pluginName = targetClass.name;
99
- }
100
- }
101
- },
102
- });
103
-
104
- if (hasVendurePlugin && pluginName && dashboardPath) {
105
- logger.debug(`[discoverPlugins] Found plugin "${pluginName}" in file: ${filePath}`);
106
- // Keep the dashboard path relative to the plugin file
107
- const resolvedDashboardPath = dashboardPath.startsWith('.')
108
- ? dashboardPath // Keep the relative path as-is
109
- : './' + path.relative(path.dirname(filePath), dashboardPath); // Make absolute path relative
110
-
111
- // Check if this is a local plugin we found earlier
112
- const sourcePluginPath = localPluginLocations.get(pluginName);
113
-
114
- plugins.push({
115
- name: pluginName,
116
- pluginPath: filePath,
117
- dashboardEntryPath: resolvedDashboardPath,
118
- ...(sourcePluginPath && { sourcePluginPath }),
119
- });
120
- }
121
- } catch (e) {
122
- logger.error(`Failed to parse ${filePath}: ${e instanceof Error ? e.message : String(e)}`);
123
- }
124
- }
125
-
126
- return plugins;
127
- }
128
-
129
- function getDecoratorObjectProps(decorator: any): any[] {
130
- if (
131
- decorator.type === 'CallExpression' &&
132
- decorator.arguments.length === 1 &&
133
- decorator.arguments[0].type === 'ObjectExpression'
134
- ) {
135
- // Look for the dashboard property in the decorator config
136
- return decorator.arguments[0].properties ?? [];
137
- }
138
- return [];
139
- }
140
-
141
- async function isSymlinkedLocalPackage(
142
- packageName: string,
143
- nodeModulesRoot: string,
144
- ): Promise<string | undefined> {
145
- try {
146
- const packagePath = path.join(nodeModulesRoot, packageName);
147
- const stats = await fs.lstat(packagePath);
148
- if (stats.isSymbolicLink()) {
149
- // Get the real path that the symlink points to
150
- const realPath = await fs.realpath(packagePath);
151
- // If the real path is within the project directory (i.e. not in some other node_modules),
152
- // then it's a local package
153
- if (!realPath.includes('node_modules')) {
154
- return realPath;
155
- }
156
- }
157
- } catch (e) {
158
- // Package doesn't exist or other error - not a local package
159
- return undefined;
160
- }
161
- return undefined;
162
- }
163
-
164
- /**
165
- * Analyzes TypeScript source files starting from the config file to discover:
166
- * 1. Local Vendure plugins
167
- * 2. All non-local package imports that could contain plugins
168
- */
169
- export async function analyzeSourceFiles(
170
- vendureConfigPath: string,
171
- nodeModulesRoot: string,
172
- logger: Logger,
173
- transformTsConfigPathMappings: TransformTsConfigPathMappingsFn,
174
- ): Promise<{
175
- localPluginLocations: Map<string, string>;
176
- packageImports: string[];
177
- }> {
178
- const localPluginLocations = new Map<string, string>();
179
- const visitedFiles = new Set<string>();
180
- const packageImportsSet = new Set<string>();
181
-
182
- // Get tsconfig paths for resolving aliases
183
- const tsConfigInfo = await findTsConfigPaths(
184
- vendureConfigPath,
185
- logger,
186
- 'compiling',
187
- transformTsConfigPathMappings,
188
- );
189
-
190
- async function processFile(filePath: string) {
191
- if (visitedFiles.has(filePath)) {
192
- return;
193
- }
194
- visitedFiles.add(filePath);
195
-
196
- try {
197
- // First check if this is a directory
198
- const stat = await fs.stat(filePath);
199
- if (stat.isDirectory()) {
200
- // If it's a directory, try to find the plugin file
201
- const indexFilePath = path.join(filePath, 'index.ts');
202
- if (await fs.pathExists(indexFilePath)) {
203
- await processFile(indexFilePath);
204
- }
205
- return;
206
- }
207
-
208
- const content = await fs.readFile(filePath, 'utf-8');
209
- const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
210
-
211
- // Track imports to follow
212
- const importsToFollow: string[] = [];
213
-
214
- async function visit(node: ts.Node) {
215
- // Look for VendurePlugin decorator
216
- const vendurePluginClassName = getVendurePluginClassName(node);
217
- if (vendurePluginClassName) {
218
- localPluginLocations.set(vendurePluginClassName, filePath);
219
- logger.debug(`Found plugin "${vendurePluginClassName}" at ${filePath}`);
220
- }
221
-
222
- // Handle both imports and exports
223
- const isImportOrExport = ts.isImportDeclaration(node) || ts.isExportDeclaration(node);
224
- if (isImportOrExport) {
225
- const moduleSpecifier = node.moduleSpecifier;
226
- if (moduleSpecifier && ts.isStringLiteral(moduleSpecifier)) {
227
- const importPath = moduleSpecifier.text;
228
-
229
- // Track non-local imports (packages)
230
- const npmPackageName = getNpmPackageNameFromImport(importPath);
231
- if (npmPackageName) {
232
- // Check if this is actually a symlinked local package
233
- const localPackagePath = await isSymlinkedLocalPackage(
234
- npmPackageName,
235
- nodeModulesRoot,
236
- );
237
- if (localPackagePath) {
238
- // If it is local, follow it like a local import
239
- importsToFollow.push(localPackagePath);
240
- logger.debug(
241
- `Found symlinked local package "${npmPackageName}" at ${localPackagePath}`,
242
- );
243
- } else {
244
- packageImportsSet.add(npmPackageName);
245
- }
246
- }
247
- // Handle path aliases and local imports
248
- const pathAliasImports = getPotentialPathAliasImportPaths(importPath, tsConfigInfo);
249
- if (pathAliasImports.length) {
250
- importsToFollow.push(...pathAliasImports);
251
- }
252
- // Also handle local imports
253
- if (importPath.startsWith('.')) {
254
- const resolvedPath = path.resolve(path.dirname(filePath), importPath);
255
- importsToFollow.push(resolvedPath);
256
- }
257
- }
258
- }
259
-
260
- // Visit children
261
- const promises: Array<Promise<void>> = [];
262
- ts.forEachChild(node, child => {
263
- promises.push(visit(child));
264
- });
265
- await Promise.all(promises);
266
- }
267
-
268
- await visit(sourceFile);
269
-
270
- // Follow imports
271
- for (const importPath of importsToFollow) {
272
- // Try all possible file paths
273
- const possiblePaths = [
274
- importPath + '.ts',
275
- importPath + '.js',
276
- path.join(importPath, 'index.ts'),
277
- path.join(importPath, 'index.js'),
278
- importPath,
279
- ];
280
- if (importPath.endsWith('.js')) {
281
- possiblePaths.push(importPath.replace(/.js$/, '.ts'));
282
- }
283
- // Try each possible path
284
- let found = false;
285
- for (const possiblePath of possiblePaths) {
286
- const possiblePathExists = await fs.pathExists(possiblePath);
287
- if (possiblePathExists) {
288
- await processFile(possiblePath);
289
- found = true;
290
- break;
291
- }
292
- }
293
-
294
- // If none of the file paths worked, try the raw import path
295
- // (it might be a directory)
296
- const tryRawPath = !found && (await fs.pathExists(importPath));
297
- if (tryRawPath) {
298
- await processFile(importPath);
299
- }
300
- }
301
- } catch (e) {
302
- const message = e instanceof Error ? e.message : String(e);
303
- logger.error(`Failed to process ${filePath}: ${message}`);
304
- }
305
- }
306
-
307
- await processFile(vendureConfigPath);
308
- return {
309
- localPluginLocations,
310
- packageImports: Array.from(packageImportsSet),
311
- };
312
- }
313
-
314
- /**
315
- * If this is a class declaration that is decorated with the `VendurePlugin` decorator,
316
- * we want to return that class name, as we have found a local Vendure plugin.
317
- */
318
- function getVendurePluginClassName(node: ts.Node): string | undefined {
319
- if (ts.isClassDeclaration(node)) {
320
- const decorators = ts.canHaveDecorators(node) ? ts.getDecorators(node) : undefined;
321
- if (decorators?.length) {
322
- for (const decorator of decorators) {
323
- const decoratorName = getDecoratorName(decorator);
324
- if (decoratorName === 'VendurePlugin') {
325
- const className = node.name?.text;
326
- if (className) {
327
- return className;
328
- }
329
- }
330
- }
331
- }
332
- }
333
- }
334
-
335
- function getNpmPackageNameFromImport(importPath: string): string | undefined {
336
- if (!importPath.startsWith('.') && !importPath.startsWith('/')) {
337
- // Get the root package name (e.g. '@scope/package/subpath' -> '@scope/package')
338
- const packageName = importPath.startsWith('@')
339
- ? importPath.split('/').slice(0, 2).join('/')
340
- : importPath.split('/')[0];
341
- return packageName;
342
- }
343
- }
344
-
345
- function getPotentialPathAliasImportPaths(importPath: string, tsConfigInfo?: TsConfigPathsConfig) {
346
- const importsToFollow: string[] = [];
347
- if (!tsConfigInfo) {
348
- return importsToFollow;
349
- }
350
- for (const [alias, patterns] of Object.entries(tsConfigInfo.paths)) {
351
- const aliasPattern = alias.replace(/\*$/, '');
352
- if (importPath.startsWith(aliasPattern)) {
353
- const relativePart = importPath.slice(aliasPattern.length);
354
- // Try each pattern
355
- for (const pattern of patterns) {
356
- const resolvedPattern = pattern.replace(/\*$/, '');
357
- const resolvedPath = path.resolve(tsConfigInfo.baseUrl, resolvedPattern, relativePart);
358
- importsToFollow.push(resolvedPath);
359
- }
360
- }
361
- }
362
- return importsToFollow;
363
- }
364
-
365
- function getDecoratorName(decorator: ts.Decorator): string | undefined {
366
- if (ts.isCallExpression(decorator.expression)) {
367
- const expression = decorator.expression.expression;
368
- // Handle both direct usage and imported usage
369
- if (ts.isIdentifier(expression)) {
370
- return expression.text;
371
- }
372
- // Handle property access like `Decorators.VendurePlugin`
373
- if (ts.isPropertyAccessExpression(expression)) {
374
- return expression.name.text;
375
- }
376
- }
377
- return undefined;
378
- }
379
-
380
- interface FindPluginFilesOptions {
381
- outputPath: string;
382
- vendureConfigPath: string;
383
- logger: Logger;
384
- packageGlobs: string[];
385
- nodeModulesRoot?: string;
386
- }
387
-
388
- export async function findVendurePluginFiles({
389
- outputPath,
390
- vendureConfigPath,
391
- logger,
392
- nodeModulesRoot: providedNodeModulesRoot,
393
- packageGlobs,
394
- }: FindPluginFilesOptions): Promise<string[]> {
395
- let nodeModulesRoot = providedNodeModulesRoot;
396
- const readStart = Date.now();
397
- if (!nodeModulesRoot) {
398
- nodeModulesRoot = guessNodeModulesRoot(vendureConfigPath, logger);
399
- }
400
-
401
- const patterns = [
402
- // Local compiled plugins in temp dir
403
- path.join(outputPath, '**/*.js'),
404
- // Node modules patterns
405
- ...packageGlobs.map(pattern => path.join(nodeModulesRoot, pattern)),
406
- ].map(p => p.replace(/\\/g, '/'));
407
-
408
- logger.debug(`Finding Vendure plugins using patterns: ${patterns.join('\n')}`);
409
-
410
- const globStart = Date.now();
411
- const files = await glob(patterns, {
412
- ignore: [
413
- // Standard test & doc files
414
- '**/node_modules/**/node_modules/**',
415
- '**/*.spec.js',
416
- '**/*.test.js',
417
- ],
418
- onlyFiles: true,
419
- absolute: true,
420
- followSymbolicLinks: false,
421
- stats: false,
422
- });
423
- logger.debug(`Glob found ${files.length} files in ${Date.now() - globStart}ms`);
424
-
425
- // Read files in larger parallel batches
426
- const batchSize = 100; // Increased batch size
427
- const potentialPluginFiles: string[] = [];
428
-
429
- for (let i = 0; i < files.length; i += batchSize) {
430
- const batch = files.slice(i, i + batchSize);
431
- const results = await Promise.all(
432
- batch.map(async file => {
433
- try {
434
- // Try reading just first 3000 bytes first - most imports are at the top
435
- const fileHandle = await open(file, 'r');
436
- try {
437
- const buffer = Buffer.alloc(3000);
438
- const { bytesRead } = await fileHandle.read(buffer, 0, 3000, 0);
439
- let content = buffer.toString('utf8', 0, bytesRead);
440
-
441
- // Quick check for common indicators
442
- if (content.includes('@vendure/core')) {
443
- return file;
444
- }
445
-
446
- // If we find a promising indicator but no definitive match,
447
- // read more of the file
448
- if (content.includes('@vendure') || content.includes('VendurePlugin')) {
449
- const largerBuffer = Buffer.alloc(5000);
450
- const { bytesRead: moreBytes } = await fileHandle.read(largerBuffer, 0, 5000, 0);
451
- content = largerBuffer.toString('utf8', 0, moreBytes);
452
- if (content.includes('@vendure/core')) {
453
- return file;
454
- }
455
- }
456
- } finally {
457
- await fileHandle.close();
458
- }
459
- } catch (e: any) {
460
- logger.warn(`Failed to read file ${file}: ${e instanceof Error ? e.message : String(e)}`);
461
- }
462
- return null;
463
- }),
464
- );
465
-
466
- const validResults = results.filter((f): f is string => f !== null);
467
- potentialPluginFiles.push(...validResults);
468
- }
469
-
470
- logger.info(
471
- `Found ${potentialPluginFiles.length} potential plugin files in ${Date.now() - readStart}ms ` +
472
- `(scanned ${files.length} files)`,
473
- );
474
-
475
- return potentialPluginFiles;
476
- }
477
-
478
- function guessNodeModulesRoot(vendureConfigPath: string, logger: Logger): string {
479
- let nodeModulesRoot: string;
480
- // If the node_modules root path has not been explicitly
481
- // specified, we will try to guess it by resolving the
482
- // `@vendure/core` package.
483
- try {
484
- const coreUrl = import.meta.resolve('@vendure/core');
485
- logger.debug(`Found core URL: ${coreUrl}`);
486
- const corePath = fileURLToPath(coreUrl);
487
- logger.debug(`Found core path: ${corePath}`);
488
- nodeModulesRoot = path.join(path.dirname(corePath), '..', '..', '..');
489
- } catch (e) {
490
- logger.warn(`Failed to resolve @vendure/core: ${e instanceof Error ? e.message : String(e)}`);
491
- nodeModulesRoot = path.dirname(vendureConfigPath);
492
- }
493
- return nodeModulesRoot;
494
- }
@@ -1,45 +0,0 @@
1
- import { GraphQLTypesLoader } from '@nestjs/graphql';
2
- import {
3
- getConfig,
4
- getFinalVendureSchema,
5
- resetConfig,
6
- runPluginConfigurations,
7
- setConfig,
8
- VENDURE_ADMIN_API_TYPE_PATHS,
9
- VendureConfig,
10
- } from '@vendure/core';
11
- import { buildSchema, GraphQLSchema } from 'graphql';
12
-
13
- let schemaPromise: Promise<GraphQLSchema> | undefined;
14
-
15
- /**
16
- * @description
17
- * This function generates a GraphQL schema from the Vendure config.
18
- * It is used to generate the schema for the dashboard.
19
- */
20
- export async function generateSchema({
21
- vendureConfig,
22
- }: {
23
- vendureConfig: VendureConfig;
24
- }): Promise<GraphQLSchema> {
25
- if (!schemaPromise) {
26
- /* eslint-disable-next-line @typescript-eslint/no-misused-promises */
27
- schemaPromise = new Promise(async (resolve, reject) => {
28
- resetConfig();
29
- await setConfig(vendureConfig ?? {});
30
-
31
- const runtimeConfig = await runPluginConfigurations(getConfig() as any);
32
- const typesLoader = new GraphQLTypesLoader();
33
- const finalSchema = await getFinalVendureSchema({
34
- config: runtimeConfig,
35
- typePaths: VENDURE_ADMIN_API_TYPE_PATHS,
36
- typesLoader,
37
- apiType: 'admin',
38
- output: 'sdl',
39
- });
40
- const safeSchema = buildSchema(finalSchema);
41
- resolve(safeSchema);
42
- });
43
- }
44
- return schemaPromise;
45
- }
@@ -1,79 +0,0 @@
1
- import fs from 'fs-extra';
2
- import path from 'path';
3
- import { CompilerOptions } from 'typescript';
4
-
5
- import { Logger, TransformTsConfigPathMappingsFn } from '../types.js';
6
-
7
- export interface TsConfigPathsConfig {
8
- baseUrl: string;
9
- paths: Record<string, string[]>;
10
- }
11
-
12
- /**
13
- * Finds and parses tsconfig files in the given directory and its parent directories.
14
- */
15
- export async function findTsConfigPaths(
16
- configPath: string,
17
- logger: Logger,
18
- phase: 'compiling' | 'loading',
19
- transformTsConfigPathMappings: TransformTsConfigPathMappingsFn,
20
- ): Promise<TsConfigPathsConfig | undefined> {
21
- let currentDir = path.dirname(configPath);
22
-
23
- while (currentDir !== path.parse(currentDir).root) {
24
- try {
25
- const files = await fs.readdir(currentDir);
26
- const tsConfigFiles = files.filter(file => /^tsconfig(\..*)?\.json$/.test(file));
27
-
28
- for (const fileName of tsConfigFiles) {
29
- const tsConfigFilePath = path.join(currentDir, fileName);
30
- try {
31
- const { paths, baseUrl } = await getCompilerOptionsFromFile(tsConfigFilePath);
32
- if (paths) {
33
- const tsConfigBaseUrl = path.resolve(currentDir, baseUrl || '.');
34
- const pathMappings = getTransformedPathMappings(
35
- paths,
36
- phase,
37
- transformTsConfigPathMappings,
38
- );
39
- return { baseUrl: tsConfigBaseUrl, paths: pathMappings };
40
- }
41
- } catch (e) {
42
- logger.warn(
43
- `Could not read or parse tsconfig file ${tsConfigFilePath}: ${e instanceof Error ? e.message : String(e)}`,
44
- );
45
- }
46
- }
47
- } catch (e) {
48
- logger.warn(
49
- `Could not read directory ${currentDir}: ${e instanceof Error ? e.message : String(e)}`,
50
- );
51
- }
52
- currentDir = path.dirname(currentDir);
53
- }
54
- return undefined;
55
- }
56
-
57
- async function getCompilerOptionsFromFile(tsConfigFilePath: string): Promise<CompilerOptions> {
58
- const tsConfigContent = await fs.readFile(tsConfigFilePath, 'utf-8');
59
- const tsConfig = JSON.parse(tsConfigContent);
60
- return tsConfig.compilerOptions || {};
61
- }
62
-
63
- function getTransformedPathMappings(
64
- paths: Required<CompilerOptions>['paths'],
65
- phase: 'compiling' | 'loading',
66
- transformTsConfigPathMappings: TransformTsConfigPathMappingsFn,
67
- ) {
68
- const pathMappings: Record<string, string[]> = {};
69
-
70
- for (const [alias, patterns] of Object.entries(paths)) {
71
- const normalizedPatterns = patterns.map(pattern => pattern.replace(/\\/g, '/'));
72
- pathMappings[alias] = transformTsConfigPathMappings({
73
- phase,
74
- alias,
75
- patterns: normalizedPatterns,
76
- });
77
- }
78
- return pathMappings;
79
- }
@@ -1,52 +0,0 @@
1
- import {
2
- ADMIN_API_PATH,
3
- DEFAULT_AUTH_TOKEN_HEADER_KEY,
4
- DEFAULT_CHANNEL_TOKEN_KEY,
5
- } from '@vendure/common/lib/shared-constants';
6
- import { VendureConfig } from '@vendure/core';
7
-
8
- import {
9
- defaultAvailableLanguages,
10
- defaultAvailableLocales,
11
- defaultLanguage,
12
- defaultLocale,
13
- } from '../constants.js';
14
- import { ResolvedUiConfig, UiConfigPluginOptions } from '../vite-plugin-ui-config.js';
15
-
16
- export function getUiConfig(config: VendureConfig, pluginOptions: UiConfigPluginOptions): ResolvedUiConfig {
17
- const { authOptions, apiOptions } = config;
18
-
19
- // Merge API configuration with defaults
20
- const api = {
21
- adminApiPath: pluginOptions.api?.adminApiPath ?? apiOptions.adminApiPath ?? ADMIN_API_PATH,
22
- host: pluginOptions.api?.host ?? 'auto',
23
- port: pluginOptions.api?.port ?? 'auto',
24
- tokenMethod:
25
- pluginOptions.api?.tokenMethod ?? (authOptions.tokenMethod === 'bearer' ? 'bearer' : 'cookie'),
26
- authTokenHeaderKey:
27
- pluginOptions.api?.authTokenHeaderKey ??
28
- authOptions.authTokenHeaderKey ??
29
- DEFAULT_AUTH_TOKEN_HEADER_KEY,
30
- channelTokenKey:
31
- pluginOptions.api?.channelTokenKey ?? apiOptions.channelTokenKey ?? DEFAULT_CHANNEL_TOKEN_KEY,
32
- };
33
-
34
- // Merge i18n configuration with defaults
35
- const i18n = {
36
- defaultLanguage: pluginOptions.i18n?.defaultLanguage ?? defaultLanguage,
37
- defaultLocale: pluginOptions.i18n?.defaultLocale ?? defaultLocale,
38
- availableLanguages:
39
- pluginOptions.i18n?.availableLanguages && pluginOptions.i18n.availableLanguages.length > 0
40
- ? pluginOptions.i18n.availableLanguages
41
- : defaultAvailableLanguages,
42
- availableLocales:
43
- pluginOptions.i18n?.availableLocales && pluginOptions.i18n.availableLocales.length > 0
44
- ? pluginOptions.i18n.availableLocales
45
- : defaultAvailableLocales,
46
- };
47
-
48
- return {
49
- api,
50
- i18n,
51
- };
52
- }