@vendure/dashboard 3.6.0-minor-202511061555 → 3.6.0-minor-202512161454

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 (152) hide show
  1. package/dist/plugin/constants.js +2 -2
  2. package/dist/vite/constants.js +1 -0
  3. package/dist/vite/utils/compiler.d.ts +1 -0
  4. package/dist/vite/utils/compiler.js +5 -4
  5. package/dist/vite/utils/get-dashboard-paths.d.ts +5 -0
  6. package/dist/vite/utils/get-dashboard-paths.js +20 -0
  7. package/dist/vite/vite-plugin-dashboard-metadata.js +2 -1
  8. package/dist/vite/vite-plugin-tailwind-source.js +2 -15
  9. package/dist/vite/vite-plugin-translations.d.ts +10 -1
  10. package/dist/vite/vite-plugin-translations.js +156 -45
  11. package/dist/vite/vite-plugin-vendure-dashboard.d.ts +12 -0
  12. package/dist/vite/vite-plugin-vendure-dashboard.js +1 -0
  13. package/lingui.config.js +1 -0
  14. package/package.json +7 -7
  15. package/src/app/routeTree.gen.ts +1221 -0
  16. package/src/app/routes/_authenticated/_administrators/administrators.tsx +9 -12
  17. package/src/app/routes/_authenticated/_administrators/administrators_.$id.tsx +9 -12
  18. package/src/app/routes/_authenticated/_assets/assets_.$id.tsx +6 -9
  19. package/src/app/routes/_authenticated/_channels/channels.tsx +9 -12
  20. package/src/app/routes/_authenticated/_channels/channels_.$id.tsx +9 -12
  21. package/src/app/routes/_authenticated/_collections/collections.tsx +9 -12
  22. package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +9 -12
  23. package/src/app/routes/_authenticated/_countries/countries.tsx +9 -12
  24. package/src/app/routes/_authenticated/_countries/countries_.$id.tsx +9 -12
  25. package/src/app/routes/_authenticated/_customer-groups/customer-groups.tsx +9 -12
  26. package/src/app/routes/_authenticated/_customer-groups/customer-groups_.$id.tsx +9 -12
  27. package/src/app/routes/_authenticated/_customers/components/customer-history/index.ts +0 -1
  28. package/src/app/routes/_authenticated/_customers/customers.tsx +9 -12
  29. package/src/app/routes/_authenticated/_customers/customers_.$id.tsx +9 -12
  30. package/src/app/routes/_authenticated/_facets/facets.tsx +9 -12
  31. package/src/app/routes/_authenticated/_facets/facets_.$facetId.values_.$id.tsx +9 -12
  32. package/src/app/routes/_authenticated/_facets/facets_.$id.tsx +9 -12
  33. package/src/app/routes/_authenticated/_global-settings/global-settings.tsx +10 -13
  34. package/src/app/routes/_authenticated/_orders/components/add-surcharge-form.tsx +139 -0
  35. package/src/app/routes/_authenticated/_orders/components/edit-order-table.tsx +3 -0
  36. package/src/app/routes/_authenticated/_orders/components/fulfill-order-dialog.tsx +3 -1
  37. package/src/app/routes/_authenticated/_orders/components/order-address.tsx +3 -3
  38. package/src/app/routes/_authenticated/_orders/components/order-detail-shared.tsx +41 -41
  39. package/src/app/routes/_authenticated/_orders/components/order-history/order-history-utils.tsx +1 -1
  40. package/src/app/routes/_authenticated/_orders/components/order-modification-summary.tsx +49 -11
  41. package/src/app/routes/_authenticated/_orders/components/order-table.tsx +4 -1
  42. package/src/app/routes/_authenticated/_orders/components/use-transition-order-to-state.tsx +2 -3
  43. package/src/app/routes/_authenticated/_orders/orders.tsx +3 -3
  44. package/src/app/routes/_authenticated/_orders/orders_.$id_.modify.tsx +12 -3
  45. package/src/app/routes/_authenticated/_orders/orders_.draft.$id.tsx +27 -30
  46. package/src/app/routes/_authenticated/_orders/utils/use-modify-order.ts +23 -0
  47. package/src/app/routes/_authenticated/_payment-methods/payment-methods.tsx +9 -12
  48. package/src/app/routes/_authenticated/_payment-methods/payment-methods_.$id.tsx +9 -12
  49. package/src/app/routes/_authenticated/_product-variants/components/add-currency-dropdown.tsx +3 -3
  50. package/src/app/routes/_authenticated/_product-variants/components/add-stock-location-dropdown.tsx +2 -2
  51. package/src/app/routes/_authenticated/_product-variants/product-variants.graphql.ts +1 -0
  52. package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +10 -12
  53. package/src/app/routes/_authenticated/_products/products.graphql.ts +1 -0
  54. package/src/app/routes/_authenticated/_products/products.tsx +15 -18
  55. package/src/app/routes/_authenticated/_products/products_.$id.tsx +9 -12
  56. package/src/app/routes/_authenticated/_products/products_.$productId.option-groups.$id.tsx +9 -12
  57. package/src/app/routes/_authenticated/_products/products_.$productId.option-groups.$productOptionGroupId.options_.$id.tsx +9 -12
  58. package/src/app/routes/_authenticated/_profile/profile.tsx +3 -3
  59. package/src/app/routes/_authenticated/_promotions/promotions.tsx +9 -12
  60. package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +9 -12
  61. package/src/app/routes/_authenticated/_roles/roles.tsx +9 -12
  62. package/src/app/routes/_authenticated/_roles/roles_.$id.tsx +9 -12
  63. package/src/app/routes/_authenticated/_sellers/sellers.tsx +9 -12
  64. package/src/app/routes/_authenticated/_sellers/sellers_.$id.tsx +9 -12
  65. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.tsx +11 -12
  66. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +19 -20
  67. package/src/app/routes/_authenticated/_stock-locations/stock-locations.tsx +9 -12
  68. package/src/app/routes/_authenticated/_stock-locations/stock-locations_.$id.tsx +9 -12
  69. package/src/app/routes/_authenticated/_system/healthchecks.tsx +2 -3
  70. package/src/app/routes/_authenticated/_system/job-queue.tsx +3 -3
  71. package/src/app/routes/_authenticated/_tax-categories/tax-categories.tsx +9 -12
  72. package/src/app/routes/_authenticated/_tax-categories/tax-categories_.$id.tsx +9 -12
  73. package/src/app/routes/_authenticated/_tax-rates/tax-rates.tsx +9 -12
  74. package/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx +9 -12
  75. package/src/app/routes/_authenticated/_zones/components/zone-bulk-actions.tsx +49 -1
  76. package/src/app/routes/_authenticated/_zones/components/zone-countries-table.tsx +34 -16
  77. package/src/app/routes/_authenticated/_zones/zones.tsx +9 -12
  78. package/src/app/routes/_authenticated/_zones/zones_.$id.tsx +9 -12
  79. package/src/app/routes/_authenticated/index.tsx +5 -3
  80. package/src/i18n/locales/bg.po +3436 -0
  81. package/src/lib/components/data-input/datetime-input.tsx +1 -1
  82. package/src/lib/components/data-input/default-relation-input.tsx +1 -1
  83. package/src/lib/components/data-input/relation-selector.tsx +1 -1
  84. package/src/lib/components/data-input/string-list-input.tsx +188 -26
  85. package/src/lib/components/data-input/struct-form-input.tsx +175 -174
  86. package/src/lib/components/data-table/column-header-wrapper.tsx +1 -1
  87. package/src/lib/components/data-table/data-table-filter-badge.tsx +2 -2
  88. package/src/lib/components/data-table/data-table.tsx +1 -1
  89. package/src/lib/components/data-table/use-generated-columns.tsx +1 -1
  90. package/src/lib/components/layout/channel-switcher.tsx +6 -2
  91. package/src/lib/components/layout/content-language-selector.tsx +6 -7
  92. package/src/lib/components/layout/dev-mode-indicator.tsx +7 -3
  93. package/src/lib/components/layout/language-dialog.tsx +26 -13
  94. package/src/lib/components/layout/manage-languages-dialog.tsx +10 -29
  95. package/src/lib/components/layout/nav-item-wrapper.tsx +1 -1
  96. package/src/lib/components/shared/asset/asset-gallery.tsx +8 -3
  97. package/src/lib/components/shared/configurable-operation-multi-selector.tsx +14 -16
  98. package/src/lib/components/shared/custom-fields-form.tsx +14 -9
  99. package/src/lib/components/shared/language-selector.tsx +14 -6
  100. package/src/lib/components/shared/multi-select.tsx +1 -1
  101. package/src/lib/components/shared/navigation-confirmation.tsx +1 -1
  102. package/src/lib/components/shared/table-cell/order-table-cell-components.tsx +4 -4
  103. package/src/lib/components/ui/carousel.tsx +2 -2
  104. package/src/lib/components/ui/chart.tsx +1 -1
  105. package/src/lib/components/ui/context-menu.tsx +1 -1
  106. package/src/lib/components/ui/drawer.tsx +1 -1
  107. package/src/lib/components/ui/grid-layout.tsx +1 -1
  108. package/src/lib/components/ui/input-group.tsx +1 -0
  109. package/src/lib/components/ui/input-otp.tsx +1 -1
  110. package/src/lib/components/ui/menubar.tsx +1 -1
  111. package/src/lib/components/ui/navigation-menu.tsx +1 -1
  112. package/src/lib/components/ui/progress.tsx +1 -1
  113. package/src/lib/components/ui/radio-group.tsx +1 -1
  114. package/src/lib/components/ui/resizable.tsx +1 -1
  115. package/src/lib/components/ui/select.tsx +1 -1
  116. package/src/lib/components/ui/slider.tsx +1 -1
  117. package/src/lib/components/ui/toggle-group.tsx +2 -2
  118. package/src/lib/components/ui/toggle.tsx +1 -1
  119. package/src/lib/framework/component-registry/component-registry.tsx +2 -6
  120. package/src/lib/framework/document-introspection/add-custom-fields.spec.ts +907 -1
  121. package/src/lib/framework/document-introspection/add-custom-fields.ts +248 -119
  122. package/src/lib/framework/extension-api/display-component-extensions.tsx +4 -3
  123. package/src/lib/framework/extension-api/logic/detail-forms.ts +0 -13
  124. package/src/lib/framework/extension-api/logic/navigation.ts +1 -1
  125. package/src/lib/framework/extension-api/types/data-table.ts +4 -2
  126. package/src/lib/framework/extension-api/types/layout.ts +34 -1
  127. package/src/lib/framework/extension-api/types/navigation.ts +7 -2
  128. package/src/lib/framework/form-engine/use-generated-form.tsx +7 -1
  129. package/src/lib/framework/history-entry/history-entry.tsx +1 -1
  130. package/src/lib/framework/layout-engine/action-bar-item-wrapper.tsx +185 -0
  131. package/src/lib/framework/layout-engine/dev-mode-button.tsx +15 -13
  132. package/src/lib/framework/layout-engine/location-wrapper.tsx +3 -1
  133. package/src/lib/framework/layout-engine/page-layout.spec.tsx +138 -0
  134. package/src/lib/framework/layout-engine/page-layout.tsx +294 -69
  135. package/src/lib/framework/nav-menu/nav-menu-extensions.ts +1 -1
  136. package/src/lib/framework/page/detail-page-route-loader.tsx +1 -1
  137. package/src/lib/framework/page/page-api.ts +1 -1
  138. package/src/lib/framework/page/use-detail-page.ts +4 -2
  139. package/src/lib/framework/page/use-extended-router.tsx +20 -16
  140. package/src/lib/framework/registry/registry-types.ts +2 -1
  141. package/src/lib/graphql/api.ts +3 -8
  142. package/src/lib/graphql/graphql-env.d.ts +29 -10
  143. package/src/lib/hooks/use-permissions.ts +3 -3
  144. package/src/lib/hooks/use-sorted-languages.ts +41 -0
  145. package/src/lib/index.ts +1 -0
  146. package/src/lib/lib/load-i18n-messages.ts +4 -1
  147. package/src/lib/providers/channel-provider.tsx +11 -7
  148. package/src/lib/utils/config-utils.ts +19 -0
  149. package/src/lib/virtual.d.ts +3 -0
  150. package/LICENSE.md +0 -42
  151. package/src/app/routes/_authenticated/_facets/components/edit-facet-value.tsx +0 -129
  152. /package/src/{app/routes/_authenticated/_global-settings → lib}/utils/global-languages.ts +0 -0
@@ -7,6 +7,6 @@ exports.DEFAULT_APP_PATH = (0, path_1.join)(__dirname, 'dist');
7
7
  exports.loggerCtx = 'DashboardPlugin';
8
8
  exports.defaultLanguage = 'en';
9
9
  exports.defaultLocale = undefined;
10
- exports.defaultAvailableLanguages = ['en', 'de', 'es', 'cs', 'zh_Hans', 'pt_BR', 'pt_PT', 'zh_Hant'];
11
- exports.defaultAvailableLocales = ['en-US', 'de-DE', 'es-ES', 'zh-CN', 'zh-TW', 'pt-BR', 'pt-PT'];
10
+ exports.defaultAvailableLanguages = ['en', 'de', 'es', 'cs', 'zh_Hans', 'pt_BR', 'pt_PT', 'zh_Hant', 'bg'];
11
+ exports.defaultAvailableLocales = ['en-US', 'de-DE', 'es-ES', 'zh-CN', 'zh-TW', 'pt-BR', 'pt-PT', 'bg_BG'];
12
12
  exports.manageDashboardGlobalViews = new core_1.RwPermissionDefinition('DashboardGlobalViews');
@@ -23,6 +23,7 @@ export const defaultAvailableLanguages = [
23
23
  LanguageCode.sv,
24
24
  LanguageCode.nb,
25
25
  LanguageCode.tr,
26
+ LanguageCode.bg,
26
27
  ];
27
28
  export const defaultAvailableLocales = [
28
29
  'AF',
@@ -9,6 +9,7 @@ export interface CompilerOptions {
9
9
  pathAdapter?: PathAdapter;
10
10
  logger?: Logger;
11
11
  pluginPackageScanner?: PackageScannerConfig;
12
+ module?: 'commonjs' | 'esm';
12
13
  }
13
14
  export interface CompileResult {
14
15
  vendureConfig: VendureConfig;
@@ -16,7 +16,7 @@ const defaultPathAdapter = {
16
16
  * and in node_modules.
17
17
  */
18
18
  export async function compile(options) {
19
- var _a, _b;
19
+ var _a, _b, _c;
20
20
  const { vendureConfigPath, outputPath, pathAdapter, logger = noopLogger, pluginPackageScanner } = options;
21
21
  const getCompiledConfigPath = (_a = pathAdapter === null || pathAdapter === void 0 ? void 0 : pathAdapter.getCompiledConfigPath) !== null && _a !== void 0 ? _a : defaultPathAdapter.getCompiledConfigPath;
22
22
  const transformTsConfigPathMappings = (_b = pathAdapter === null || pathAdapter === void 0 ? void 0 : pathAdapter.transformTsConfigPathMappings) !== null && _b !== void 0 ? _b : defaultPathAdapter.transformTsConfigPathMappings;
@@ -29,6 +29,7 @@ export async function compile(options) {
29
29
  outputPath,
30
30
  logger,
31
31
  transformTsConfigPathMappings,
32
+ module: (_c = options.module) !== null && _c !== void 0 ? _c : 'commonjs',
32
33
  });
33
34
  logger.info(`TypeScript compilation completed in ${Date.now() - compileStart}ms`);
34
35
  // 2. Discover plugins
@@ -49,7 +50,7 @@ export async function compile(options) {
49
50
  configFileName,
50
51
  })).href.replace(/.ts$/, '.js');
51
52
  // Create package.json with type commonjs
52
- await fs.writeFile(path.join(outputPath, 'package.json'), JSON.stringify({ type: 'commonjs', private: true }, null, 2));
53
+ await fs.writeFile(path.join(outputPath, 'package.json'), JSON.stringify({ type: options.module === 'esm' ? 'module' : 'commonjs', private: true }, null, 2));
53
54
  // Find the exported config symbol
54
55
  const sourceFile = ts.createSourceFile(vendureConfigPath, await fs.readFile(vendureConfigPath, 'utf-8'), ts.ScriptTarget.Latest, true);
55
56
  const exportedSymbolName = findConfigExport(sourceFile);
@@ -80,14 +81,14 @@ export async function compile(options) {
80
81
  /**
81
82
  * Compiles TypeScript files to JavaScript
82
83
  */
83
- async function compileTypeScript({ inputPath, outputPath, logger, transformTsConfigPathMappings, }) {
84
+ async function compileTypeScript({ inputPath, outputPath, logger, transformTsConfigPathMappings, module, }) {
84
85
  var _a;
85
86
  await fs.ensureDir(outputPath);
86
87
  // Find tsconfig paths first
87
88
  const tsConfigInfo = await findTsConfigPaths(inputPath, logger, 'compiling', transformTsConfigPathMappings);
88
89
  const compilerOptions = {
89
90
  target: ts.ScriptTarget.ES2020,
90
- module: ts.ModuleKind.CommonJS,
91
+ module: module === 'esm' ? ts.ModuleKind.ESNext : ts.ModuleKind.CommonJS,
91
92
  moduleResolution: ts.ModuleResolutionKind.Node10, // More explicit CJS resolution
92
93
  experimentalDecorators: true,
93
94
  emitDecoratorMetadata: true,
@@ -0,0 +1,5 @@
1
+ import { PluginInfo } from '../types.js';
2
+ /**
3
+ * Returns an array of the paths to plugins, based on the info provided by the ConfigLoaderApi.
4
+ */
5
+ export declare function getDashboardPaths(pluginInfo: PluginInfo[]): string[];
@@ -0,0 +1,20 @@
1
+ import path from 'path';
2
+ /**
3
+ * Returns an array of the paths to plugins, based on the info provided by the ConfigLoaderApi.
4
+ */
5
+ export function getDashboardPaths(pluginInfo) {
6
+ var _a;
7
+ return ((_a = pluginInfo === null || pluginInfo === void 0 ? void 0 : pluginInfo.flatMap(({ dashboardEntryPath, sourcePluginPath, pluginPath }) => {
8
+ if (!dashboardEntryPath) {
9
+ return [];
10
+ }
11
+ const sourcePaths = [];
12
+ if (sourcePluginPath) {
13
+ sourcePaths.push(path.join(path.dirname(sourcePluginPath), path.dirname(dashboardEntryPath)));
14
+ }
15
+ if (pluginPath) {
16
+ sourcePaths.push(path.join(path.dirname(pluginPath), path.dirname(dashboardEntryPath)));
17
+ }
18
+ return sourcePaths;
19
+ }).filter(x => x != null)) !== null && _a !== void 0 ? _a : []);
20
+ }
@@ -1,4 +1,5 @@
1
1
  import path from 'path';
2
+ import { pathToFileURL } from 'node:url';
2
3
  import { getConfigLoaderApi } from './vite-plugin-config-loader.js';
3
4
  const virtualModuleId = 'virtual:dashboard-extensions';
4
5
  const resolvedVirtualModuleId = `\0${virtualModuleId}`;
@@ -50,7 +51,7 @@ export function dashboardMetadataPlugin() {
50
51
  export async function runDashboardExtensions() {
51
52
  ${pluginsWithExtensions
52
53
  .map(extension => {
53
- return `await import(\`${extension}\`);`;
54
+ return `await import(\`${pathToFileURL(extension)}\`);`;
54
55
  })
55
56
  .join('\n')}
56
57
  }`;
@@ -1,4 +1,4 @@
1
- import path from 'path';
1
+ import { getDashboardPaths } from './utils/get-dashboard-paths.js';
2
2
  import { getConfigLoaderApi } from './vite-plugin-config-loader.js';
3
3
  /**
4
4
  * This Vite plugin transforms the `app/styles.css` file to include a `@source` directive
@@ -16,25 +16,12 @@ export function dashboardTailwindSourcePlugin() {
16
16
  configLoaderApi = getConfigLoaderApi(plugins);
17
17
  },
18
18
  async transform(src, id) {
19
- var _a;
20
19
  if (/app\/styles.css$/.test(id)) {
21
20
  if (!loadVendureConfigResult) {
22
21
  loadVendureConfigResult = await configLoaderApi.getVendureConfig();
23
22
  }
24
23
  const { pluginInfo } = loadVendureConfigResult;
25
- const dashboardExtensionDirs = (_a = pluginInfo === null || pluginInfo === void 0 ? void 0 : pluginInfo.flatMap(({ dashboardEntryPath, sourcePluginPath, pluginPath }) => {
26
- if (!dashboardEntryPath) {
27
- return [];
28
- }
29
- const sourcePaths = [];
30
- if (sourcePluginPath) {
31
- sourcePaths.push(path.join(path.dirname(sourcePluginPath), path.dirname(dashboardEntryPath)));
32
- }
33
- if (pluginPath) {
34
- sourcePaths.push(path.join(path.dirname(pluginPath), path.dirname(dashboardEntryPath)));
35
- }
36
- return sourcePaths;
37
- }).filter(x => x != null)) !== null && _a !== void 0 ? _a : [];
24
+ const dashboardExtensionDirs = getDashboardPaths(pluginInfo);
38
25
  const sources = dashboardExtensionDirs
39
26
  .map(extension => {
40
27
  return `@source '${extension}';`;
@@ -16,7 +16,16 @@ export interface TranslationsPluginOptions {
16
16
  }
17
17
  /**
18
18
  * @description
19
- * This Vite plugin compiles
19
+ * This Vite plugin compiles the source .po files into JS bundles that can be loaded statically.
20
+ *
21
+ * It handles 2 modes: dev and build.
22
+ *
23
+ * - The dev case is handled in the `load` function using Vite virtual
24
+ * modules to compile and return translations from plugins _only_, which then get merged with the built-in
25
+ * translations in the `loadI18nMessages` function
26
+ * - The build case loads both built-in and plugin translations, merges them, and outputs the compiled
27
+ * files as .js files that can be statically consumed by the built app.
28
+ *
20
29
  * @param options
21
30
  */
22
31
  export declare function translationsPlugin(options: TranslationsPluginOptions): Plugin;
@@ -1,62 +1,82 @@
1
1
  import { createCompilationErrorMessage, createCompiledCatalog, getCatalogForFile, getCatalogs, } from '@lingui/cli/api';
2
2
  import { getConfig } from '@lingui/conf';
3
+ import glob from 'fast-glob';
3
4
  import * as fs from 'fs';
4
5
  import * as path from 'path';
6
+ import { getDashboardPaths } from './utils/get-dashboard-paths.js';
7
+ import { getConfigLoaderApi } from './vite-plugin-config-loader.js';
8
+ const virtualModuleId = 'virtual:plugin-translations';
9
+ const resolvedVirtualModuleId = `\0${virtualModuleId}`;
5
10
  /**
6
11
  * @description
7
- * This Vite plugin compiles
12
+ * This Vite plugin compiles the source .po files into JS bundles that can be loaded statically.
13
+ *
14
+ * It handles 2 modes: dev and build.
15
+ *
16
+ * - The dev case is handled in the `load` function using Vite virtual
17
+ * modules to compile and return translations from plugins _only_, which then get merged with the built-in
18
+ * translations in the `loadI18nMessages` function
19
+ * - The build case loads both built-in and plugin translations, merges them, and outputs the compiled
20
+ * files as .js files that can be statically consumed by the built app.
21
+ *
8
22
  * @param options
9
23
  */
10
24
  export function translationsPlugin(options) {
11
- const { externalPoFiles = [], localesDir = 'src/i18n/locales', outputPath = 'assets/i18n' } = options;
12
- const linguiConfig = getConfig({ configPath: path.join(options.packageRoot, 'lingui.config.js') });
13
- const catalogsPromise = getCatalogs(linguiConfig);
14
- async function compileTranslations(files, emitFile) {
15
- const catalogs = await catalogsPromise;
16
- for (const file of files) {
17
- const catalogRelativePath = path.relative(options.packageRoot, file.path);
18
- const fileCatalog = getCatalogForFile(catalogRelativePath, catalogs);
19
- const { locale, catalog } = fileCatalog;
20
- const { messages } = await catalog.getTranslations(locale, {
21
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
22
- fallbackLocales: { default: linguiConfig.sourceLocale },
23
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
24
- sourceLocale: linguiConfig.sourceLocale,
25
- });
26
- const { source: code, errors } = createCompiledCatalog(locale, messages, {
27
- namespace: 'es',
28
- pseudoLocale: linguiConfig.pseudoLocale,
29
- });
30
- if (errors.length) {
31
- const message = createCompilationErrorMessage(locale, errors);
32
- throw new Error(message +
33
- `These errors fail build because \`failOnCompileError=true\` in Lingui Vite plugin configuration.`);
34
- }
35
- // Emit the compiled JavaScript file to the build output
36
- const outputFileName = path.posix.join(outputPath, `${locale}.js`);
37
- emitFile({
38
- type: 'asset',
39
- fileName: outputFileName,
40
- source: code,
41
- });
42
- }
43
- }
25
+ let configLoaderApi;
26
+ let loadVendureConfigResult;
44
27
  return {
45
28
  name: 'vendure:compile-translations',
29
+ configResolved({ plugins }) {
30
+ configLoaderApi = getConfigLoaderApi(plugins);
31
+ },
32
+ resolveId(id) {
33
+ if (id === virtualModuleId) {
34
+ return resolvedVirtualModuleId;
35
+ }
36
+ },
37
+ async load(id) {
38
+ if (id === resolvedVirtualModuleId) {
39
+ this.debug('Loading plugin translations...');
40
+ if (!loadVendureConfigResult) {
41
+ loadVendureConfigResult = await configLoaderApi.getVendureConfig();
42
+ }
43
+ const { pluginInfo } = loadVendureConfigResult;
44
+ const pluginTranslations = await getPluginTranslations(pluginInfo);
45
+ const linguiConfig = getConfig({
46
+ configPath: path.join(options.packageRoot, 'lingui.config.js'),
47
+ });
48
+ const catalogs = await getLinguiCatalogs(linguiConfig, pluginTranslations);
49
+ const pluginFiles = pluginTranslations.flatMap(translation => translation.translations);
50
+ const mergedMessageMap = await createMergedMessageMap({
51
+ files: pluginFiles,
52
+ packageRoot: options.packageRoot,
53
+ catalogs,
54
+ sourceLocale: linguiConfig.sourceLocale,
55
+ });
56
+ return `
57
+ const translations = {
58
+ ${[...mergedMessageMap.entries()]
59
+ .map(([locale, messages]) => {
60
+ const safeLocale = locale.replace(/-/g, '_');
61
+ return `${safeLocale}: ${JSON.stringify(messages)}`;
62
+ })
63
+ .join(',\n')}
64
+ };
65
+ export default translations;
66
+ `;
67
+ }
68
+ },
69
+ // This runs at build-time only
46
70
  async generateBundle() {
47
71
  // This runs during the bundle generation phase - emit files directly to build output
48
72
  try {
49
- const resolvedLocalesDir = path.resolve(options.packageRoot, localesDir);
50
- // Get all built-in .po files
51
- const builtInFiles = fs
52
- .readdirSync(resolvedLocalesDir)
53
- .filter(file => file.endsWith('.po'))
54
- .map(file => ({
55
- name: file,
56
- path: path.join(resolvedLocalesDir, file),
57
- }));
58
- await compileTranslations(builtInFiles, this.emitFile);
59
- this.info(`✓ Processed ${builtInFiles.length} translation files to ${outputPath}`);
73
+ const { pluginInfo } = await configLoaderApi.getVendureConfig();
74
+ // Get any plugin-provided .po files
75
+ const pluginTranslations = await getPluginTranslations(pluginInfo);
76
+ const pluginTranslationFiles = pluginTranslations.flatMap(p => p.translations);
77
+ this.info(`Found ${pluginTranslationFiles.length} translation files from plugins`);
78
+ this.debug(pluginTranslationFiles.join('\n'));
79
+ await compileTranslations(options, pluginTranslations, this.emitFile);
60
80
  }
61
81
  catch (error) {
62
82
  this.error(`Translation plugin error: ${error instanceof Error ? error.message : String(error)}`);
@@ -64,3 +84,94 @@ export function translationsPlugin(options) {
64
84
  },
65
85
  };
66
86
  }
87
+ async function getPluginTranslations(pluginInfo) {
88
+ const dashboardPaths = getDashboardPaths(pluginInfo);
89
+ const pluginTranslations = [];
90
+ for (const dashboardPath of dashboardPaths) {
91
+ const poPatterns = path.join(dashboardPath, '**/*.po');
92
+ const translations = await glob(poPatterns, {
93
+ ignore: [
94
+ // Standard test & doc files
95
+ '**/node_modules/**/node_modules/**',
96
+ '**/*.spec.js',
97
+ '**/*.test.js',
98
+ ],
99
+ onlyFiles: true,
100
+ absolute: true,
101
+ followSymbolicLinks: false,
102
+ stats: false,
103
+ });
104
+ pluginTranslations.push({
105
+ pluginRootPath: dashboardPath,
106
+ translations,
107
+ });
108
+ }
109
+ return pluginTranslations;
110
+ }
111
+ async function compileTranslations(options, pluginTranslations, emitFile) {
112
+ const { localesDir = 'src/i18n/locales', outputPath = 'assets/i18n' } = options;
113
+ const linguiConfig = getConfig({ configPath: path.join(options.packageRoot, 'lingui.config.js') });
114
+ const resolvedLocalesDir = path.resolve(options.packageRoot, localesDir);
115
+ const catalogs = await getLinguiCatalogs(linguiConfig, pluginTranslations);
116
+ // Get all built-in .po files
117
+ const builtInFiles = fs
118
+ .readdirSync(resolvedLocalesDir)
119
+ .filter(file => file.endsWith('.po'))
120
+ .map(file => path.join(resolvedLocalesDir, file));
121
+ const pluginFiles = pluginTranslations.flatMap(translation => translation.translations);
122
+ const mergedMessageMap = await createMergedMessageMap({
123
+ files: [...builtInFiles, ...pluginFiles],
124
+ packageRoot: options.packageRoot,
125
+ catalogs,
126
+ sourceLocale: linguiConfig.sourceLocale,
127
+ });
128
+ for (const [locale, messages] of mergedMessageMap.entries()) {
129
+ const { source: code, errors } = createCompiledCatalog(locale, messages, {
130
+ namespace: 'es',
131
+ pseudoLocale: linguiConfig.pseudoLocale,
132
+ });
133
+ if (errors.length) {
134
+ const message = createCompilationErrorMessage(locale, errors);
135
+ throw new Error(message +
136
+ `These errors fail build because \`failOnCompileError=true\` in Lingui Vite plugin configuration.`);
137
+ }
138
+ // Emit the compiled JavaScript file to the build output
139
+ const outputFileName = path.posix.join(outputPath, `${locale}.js`);
140
+ emitFile({
141
+ type: 'asset',
142
+ fileName: outputFileName,
143
+ source: code,
144
+ });
145
+ }
146
+ }
147
+ async function getLinguiCatalogs(linguiConfig, pluginTranslations) {
148
+ var _a, _b, _c;
149
+ for (const pluginTranslation of pluginTranslations) {
150
+ if (pluginTranslation.translations.length === 0) {
151
+ continue;
152
+ }
153
+ (_a = linguiConfig.catalogs) === null || _a === void 0 ? void 0 : _a.push({
154
+ path: (_c = (_b = pluginTranslation.translations[0]) === null || _b === void 0 ? void 0 : _b.replace(/[a-z_-]+\.po$/, '{locale}')) !== null && _c !== void 0 ? _c : '',
155
+ include: [],
156
+ });
157
+ }
158
+ return getCatalogs(linguiConfig);
159
+ }
160
+ async function createMergedMessageMap({ files, packageRoot, catalogs, sourceLocale, }) {
161
+ var _a;
162
+ const mergedMessageMap = new Map();
163
+ for (const file of files) {
164
+ const catalogRelativePath = path.relative(packageRoot, file);
165
+ const fileCatalog = getCatalogForFile(catalogRelativePath, catalogs);
166
+ const { locale, catalog } = fileCatalog;
167
+ const { messages } = await catalog.getTranslations(locale, {
168
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
169
+ fallbackLocales: { default: sourceLocale },
170
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
171
+ sourceLocale: sourceLocale,
172
+ });
173
+ const mergedMessages = (_a = mergedMessageMap.get(locale)) !== null && _a !== void 0 ? _a : {};
174
+ mergedMessageMap.set(locale, Object.assign(Object.assign({}, mergedMessages), messages));
175
+ }
176
+ return mergedMessageMap;
177
+ }
@@ -77,6 +77,18 @@ export type VitePluginVendureDashboardOptions = {
77
77
  * the location based on the location of the `@vendure/core` package.
78
78
  */
79
79
  pluginPackageScanner?: PackageScannerConfig;
80
+ /**
81
+ * @description
82
+ * Allows you to specify the module system to use when compiling and loading your Vendure config.
83
+ * By default, the compiler will use CommonJS, but you can set it to `esm` if you are using
84
+ * ES Modules in your Vendure project.
85
+ *
86
+ * **Status** Developer preview. If you are using ESM please try this out and provide us with feedback!
87
+ *
88
+ * @since 3.5.1
89
+ * @default 'commonjs'
90
+ */
91
+ module?: 'commonjs' | 'esm';
80
92
  /**
81
93
  * @description
82
94
  * Allows you to selectively disable individual plugins.
@@ -76,6 +76,7 @@ export function vendureDashboardPlugin(options) {
76
76
  outputPath: tempDir,
77
77
  pathAdapter: options.pathAdapter,
78
78
  pluginPackageScanner: options.pluginPackageScanner,
79
+ module: options.module,
79
80
  }),
80
81
  },
81
82
  {
package/lingui.config.js CHANGED
@@ -25,6 +25,7 @@ export default defineConfig({
25
25
  'sv',
26
26
  'tr',
27
27
  'ja',
28
+ 'bg'
28
29
  ],
29
30
  catalogs: [
30
31
  {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vendure/dashboard",
3
3
  "private": false,
4
- "version": "3.6.0-minor-202511061555",
4
+ "version": "3.6.0-minor-202512161454",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "type": "git",
@@ -14,10 +14,11 @@
14
14
  },
15
15
  "scripts": {
16
16
  "dev": "vite",
17
+ "check-types": "tsc --project tsconfig.check.json --noEmit",
17
18
  "build:standalone": "vite build",
18
19
  "build:vite": "tsc --project tsconfig.vite.json",
19
20
  "build:plugin": "tsc --project tsconfig.plugin.json && node scripts/build-plugin.js",
20
- "build": "npm run build:vite && npm run build:plugin",
21
+ "build": "npm run check-types && npm run build:vite && npm run build:plugin",
21
22
  "watch": "tsc --project tsconfig.vite.json --watch",
22
23
  "test": "vitest run",
23
24
  "lint": "eslint .",
@@ -63,7 +64,7 @@
63
64
  "@lingui/cli": "^5.5.0",
64
65
  "@lingui/core": "^5.5.0",
65
66
  "@lingui/react": "^5.5.0",
66
- "@lingui/swc-plugin": "^5.6.1",
67
+ "@lingui/swc-plugin": "5.6.1",
67
68
  "@lingui/vite-plugin": "^5.5.0",
68
69
  "@radix-ui/react-accordion": "^1.2.11",
69
70
  "@radix-ui/react-alert-dialog": "^1.1.14",
@@ -155,8 +156,8 @@
155
156
  "@storybook/addon-vitest": "^10.0.0-beta.9",
156
157
  "@storybook/react-vite": "^10.0.0-beta.9",
157
158
  "@types/node": "^22.13.4",
158
- "@vendure/common": "^3.6.0-minor-202511061555",
159
- "@vendure/core": "^3.6.0-minor-202511061555",
159
+ "@vendure/common": "^3.6.0-minor-202512161454",
160
+ "@vendure/core": "^3.6.0-minor-202512161454",
160
161
  "@vitest/browser": "^3.2.4",
161
162
  "@vitest/coverage-v8": "^3.2.4",
162
163
  "eslint": "^9.19.0",
@@ -172,6 +173,5 @@
172
173
  "optionalDependencies": {
173
174
  "lightningcss-linux-arm64-musl": "^1.29.3",
174
175
  "lightningcss-linux-x64-musl": "^1.29.1"
175
- },
176
- "gitHead": "65e9f71bcdab9ad062707d63d6d7de99547c8970"
176
+ }
177
177
  }