@mercurjs/dashboard-sdk 2.0.0-canary.80 → 2.0.0-canary.81

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/index.cjs CHANGED
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ generatePluginEntryModule: () => generatePluginEntryModule,
33
34
  mercurDashboardPlugin: () => mercurDashboardPlugin
34
35
  });
35
36
  module.exports = __toCommonJS(index_exports);
@@ -69,9 +70,9 @@ function resolveExports(moduleExports) {
69
70
  }
70
71
  return moduleExports;
71
72
  }
72
- async function getFileExports(path6) {
73
+ async function getFileExports(path7) {
73
74
  const { unregister } = await safeRegister();
74
- const module2 = require(path6);
75
+ const module2 = require(path7);
75
76
  unregister();
76
77
  return resolveExports(module2);
77
78
  }
@@ -97,13 +98,13 @@ function hasDefaultExport(ast) {
97
98
  ExportDefaultDeclaration() {
98
99
  found = true;
99
100
  },
100
- AssignmentExpression(path6) {
101
- if (path6.node.left.type === "MemberExpression" && path6.node.left.object.type === "Identifier" && path6.node.left.object.name === "exports" && path6.node.left.property.type === "Identifier" && path6.node.left.property.name === "default") {
101
+ AssignmentExpression(path7) {
102
+ if (path7.node.left.type === "MemberExpression" && path7.node.left.object.type === "Identifier" && path7.node.left.object.name === "exports" && path7.node.left.property.type === "Identifier" && path7.node.left.property.name === "default") {
102
103
  found = true;
103
104
  }
104
105
  },
105
- ExportNamedDeclaration(path6) {
106
- const specifiers = path6.node.specifiers;
106
+ ExportNamedDeclaration(path7) {
107
+ const specifiers = path7.node.specifiers;
107
108
  if (specifiers?.some(
108
109
  (s) => s.type === "ExportSpecifier" && s.exported.type === "Identifier" && s.exported.name === "default"
109
110
  )) {
@@ -140,17 +141,17 @@ var import_path4 = __toESM(require("path"), 1);
140
141
  // src/routes.ts
141
142
  var import_fs = __toESM(require("fs"), 1);
142
143
  var import_path = __toESM(require("path"), 1);
143
- function getRoute(file, pagesDir) {
144
+ function getRoute(file, routesDir) {
144
145
  const importPath = normalizePath(file);
145
- const normalizedPagesDir = normalizePath(pagesDir);
146
- return importPath.replace(normalizedPagesDir, "").replace(/\[\[\*\]\]/g, "*?").replace(/\[\*\]/g, "*").replace(/\(([^\[\]\)]+)\)/g, "$1?").replace(/\[\[([^\]]+)\]\]/g, ":$1?").replace(/\[([^\]]+)\]/g, ":$1").replace(
146
+ const normalizedRoutesDir = normalizePath(routesDir);
147
+ return importPath.replace(normalizedRoutesDir, "").replace(/\[\[\*\]\]/g, "*?").replace(/\[\*\]/g, "*").replace(/\(([^\[\]\)]+)\)/g, "$1?").replace(/\[\[([^\]]+)\]\]/g, ":$1?").replace(/\[([^\]]+)\]/g, ":$1").replace(
147
148
  new RegExp(
148
149
  `/page\\.(${VALID_FILE_EXTENSIONS.map((ext) => ext.slice(1)).join("|")})$`
149
150
  ),
150
151
  ""
151
152
  ) || "/";
152
153
  }
153
- function crawlPages(dir, pattern = "page") {
154
+ function crawlRoutes(dir, pattern = "page") {
154
155
  const files = [];
155
156
  if (!import_fs.default.existsSync(dir)) {
156
157
  return files;
@@ -159,7 +160,7 @@ function crawlPages(dir, pattern = "page") {
159
160
  for (const entry of entries) {
160
161
  const fullPath = import_path.default.join(dir, entry.name);
161
162
  if (entry.isDirectory()) {
162
- files.push(...crawlPages(fullPath, pattern));
163
+ files.push(...crawlRoutes(fullPath, pattern));
163
164
  } else if (entry.isFile()) {
164
165
  const ext = import_path.default.extname(entry.name);
165
166
  const baseName = import_path.default.basename(entry.name, ext);
@@ -173,8 +174,8 @@ function crawlPages(dir, pattern = "page") {
173
174
  function hasConfigPublic(ast) {
174
175
  let found = false;
175
176
  traverse(ast, {
176
- ExportNamedDeclaration(path6) {
177
- const declaration = path6.node.declaration;
177
+ ExportNamedDeclaration(path7) {
178
+ const declaration = path7.node.declaration;
178
179
  if (!(0, import_types.isVariableDeclaration)(declaration)) return;
179
180
  for (const decl of declaration.declarations) {
180
181
  if ((0, import_types.isVariableDeclarator)(decl) && (0, import_types.isIdentifier)(decl.id, { name: "config" }) && decl.init?.type === "ObjectExpression") {
@@ -194,8 +195,8 @@ function getNamedExports(ast) {
194
195
  let hasHandle = false;
195
196
  let hasLoader = false;
196
197
  traverse(ast, {
197
- ExportNamedDeclaration(path6) {
198
- const declaration = path6.node.declaration;
198
+ ExportNamedDeclaration(path7) {
199
+ const declaration = path7.node.declaration;
199
200
  if (declaration?.type === "VariableDeclaration") {
200
201
  declaration.declarations.forEach((decl) => {
201
202
  if (decl.id.type === "Identifier" && decl.id.name === "handle") {
@@ -279,7 +280,7 @@ ${indent} ]`;
279
280
  ${indent}}`;
280
281
  return result;
281
282
  }
282
- function parseFile(file, pagesDir, index) {
283
+ function parseFile(file, routesDir, index) {
283
284
  try {
284
285
  const code = import_fs.default.readFileSync(file, "utf-8");
285
286
  const ast = (0, import_parser.parse)(code, getParserOptions(file));
@@ -288,7 +289,7 @@ function parseFile(file, pagesDir, index) {
288
289
  }
289
290
  const { hasHandle, hasLoader } = getNamedExports(ast);
290
291
  const isPublic = hasConfigPublic(ast);
291
- const routePath = getRoute(file, pagesDir);
292
+ const routePath = getRoute(file, routesDir);
292
293
  const imports = generateImports(file, index, hasHandle, hasLoader);
293
294
  const route = generateRouteObject(routePath, index, hasHandle, hasLoader, isPublic);
294
295
  return {
@@ -327,11 +328,11 @@ function buildRouteTree(results) {
327
328
  return Array.from(routeMap.values());
328
329
  }
329
330
  function generateRoutes({ srcDir, pluginExtensions }) {
330
- const pagesDir = import_path.default.join(srcDir, "pages");
331
+ const routesDir = import_path.default.join(srcDir, "routes");
331
332
  let index = 0;
332
333
  const results = [];
333
- for (const file of crawlPages(pagesDir)) {
334
- const result = parseFile(file, pagesDir, index);
334
+ for (const file of crawlRoutes(routesDir)) {
335
+ const result = parseFile(file, routesDir, index);
335
336
  if (result) {
336
337
  results.push(result);
337
338
  index++;
@@ -363,7 +364,7 @@ ${allRoutes.join(",\n")}
363
364
  // src/menu-items.ts
364
365
  var import_fs2 = __toESM(require("fs"), 1);
365
366
  var import_path2 = __toESM(require("path"), 1);
366
- function crawlPages2(dir, pattern = "page") {
367
+ function crawlRoutes2(dir, pattern = "page") {
367
368
  const files = [];
368
369
  if (!import_fs2.default.existsSync(dir)) {
369
370
  return files;
@@ -372,7 +373,7 @@ function crawlPages2(dir, pattern = "page") {
372
373
  for (const entry of entries) {
373
374
  const fullPath = import_path2.default.join(dir, entry.name);
374
375
  if (entry.isDirectory()) {
375
- files.push(...crawlPages2(fullPath, pattern));
376
+ files.push(...crawlRoutes2(fullPath, pattern));
376
377
  } else if (entry.isFile()) {
377
378
  const ext = import_path2.default.extname(entry.name);
378
379
  const baseName = import_path2.default.basename(entry.name, ext);
@@ -383,19 +384,19 @@ function crawlPages2(dir, pattern = "page") {
383
384
  }
384
385
  return files;
385
386
  }
386
- function getRoute2(file, pagesDir) {
387
+ function getRoute2(file, routesDir) {
387
388
  const importPath = normalizePath(file);
388
- const normalizedPagesDir = normalizePath(pagesDir);
389
- return importPath.replace(normalizedPagesDir, "").replace(/\[\[\*\]\]/g, "*?").replace(/\[\*\]/g, "*").replace(/\(([^\[\]\)]+)\)/g, "$1?").replace(/\[\[([^\]]+)\]\]/g, ":$1?").replace(/\[([^\]]+)\]/g, ":$1").replace(
389
+ const normalizedRoutesDir = normalizePath(routesDir);
390
+ return importPath.replace(normalizedRoutesDir, "").replace(/\[\[\*\]\]/g, "*?").replace(/\[\*\]/g, "*").replace(/\(([^\[\]\)]+)\)/g, "$1?").replace(/\[\[([^\]]+)\]\]/g, ":$1?").replace(/\[([^\]]+)\]/g, ":$1").replace(
390
391
  new RegExp(
391
392
  `/page\\.(${VALID_FILE_EXTENSIONS.map((ext) => ext.slice(1)).join("|")})$`
392
393
  ),
393
394
  ""
394
395
  ) || "/";
395
396
  }
396
- function getConfigObjectProperties(path6) {
397
- if ((0, import_types.isVariableDeclarator)(path6.node)) {
398
- const decl = (0, import_types.isIdentifier)(path6.node.id, { name: "config" }) ? path6.node : null;
397
+ function getConfigObjectProperties(path7) {
398
+ if ((0, import_types.isVariableDeclarator)(path7.node)) {
399
+ const decl = (0, import_types.isIdentifier)(path7.node.id, { name: "config" }) ? path7.node : null;
399
400
  if (!decl) return null;
400
401
  if ((0, import_types.isCallExpression)(decl.init) && decl.init.arguments.length > 0 && (0, import_types.isObjectExpression)(decl.init.arguments[0])) {
401
402
  return decl.init.arguments[0].properties;
@@ -405,7 +406,7 @@ function getConfigObjectProperties(path6) {
405
406
  }
406
407
  return null;
407
408
  }
408
- const declaration = path6.node.declaration;
409
+ const declaration = path7.node.declaration;
409
410
  if ((0, import_types.isVariableDeclaration)(declaration)) {
410
411
  const configDecl = declaration.declarations.find(
411
412
  (d) => (0, import_types.isVariableDeclarator)(d) && (0, import_types.isIdentifier)(d.id, { name: "config" })
@@ -461,16 +462,16 @@ function getRouteConfig(file) {
461
462
  let config = null;
462
463
  let configFound = false;
463
464
  traverse(ast, {
464
- VariableDeclarator(path6) {
465
+ VariableDeclarator(path7) {
465
466
  if (configFound) return;
466
- const properties = getConfigObjectProperties(path6);
467
+ const properties = getConfigObjectProperties(path7);
467
468
  if (!properties) return;
468
469
  config = processConfigProperties(properties);
469
470
  if (config) configFound = true;
470
471
  },
471
- ExportNamedDeclaration(path6) {
472
+ ExportNamedDeclaration(path7) {
472
473
  if (configFound) return;
473
- const properties = getConfigObjectProperties(path6);
474
+ const properties = getConfigObjectProperties(path7);
474
475
  if (!properties) return;
475
476
  config = processConfigProperties(properties);
476
477
  if (config) configFound = true;
@@ -488,12 +489,12 @@ function generateImport(file, index) {
488
489
  const importPath = normalizePath(file);
489
490
  return `import { config as ${generateRouteConfigName(index)} } from "${importPath}"`;
490
491
  }
491
- function generateMenuItem(config, file, pagesDir, index) {
492
+ function generateMenuItem(config, file, routesDir, index) {
492
493
  const configName = generateRouteConfigName(index);
493
494
  return {
494
495
  label: `${configName}.label`,
495
496
  icon: config.icon ? `${configName}.icon` : void 0,
496
- path: getRoute2(file, pagesDir),
497
+ path: getRoute2(file, routesDir),
497
498
  rank: config.rank,
498
499
  nested: config.nested,
499
500
  translationNs: config.translationNs ? `${configName}.translationNs` : void 0
@@ -512,22 +513,22 @@ function formatMenuItem(menuItem) {
512
513
  ${parts.join(",\n")}
513
514
  }`;
514
515
  }
515
- function parseFile2(file, pagesDir, index) {
516
+ function parseMenuItemFile(file, routesDir, index) {
516
517
  const config = getRouteConfig(file);
517
518
  if (!config) {
518
519
  return null;
519
520
  }
520
521
  return {
521
522
  import: generateImport(file, index),
522
- menuItem: generateMenuItem(config, file, pagesDir, index)
523
+ menuItem: generateMenuItem(config, file, routesDir, index)
523
524
  };
524
525
  }
525
526
  function generateMenuItems({ srcDir, pluginExtensions }) {
526
- const pagesDir = import_path2.default.join(srcDir, "pages");
527
+ const routesDir = import_path2.default.join(srcDir, "routes");
527
528
  let index = 0;
528
529
  const results = [];
529
- for (const file of crawlPages2(pagesDir)) {
530
- const result = parseFile2(file, pagesDir, index);
530
+ for (const file of crawlRoutes2(routesDir)) {
531
+ const result = parseMenuItemFile(file, routesDir, index);
531
532
  if (result) {
532
533
  results.push(result);
533
534
  index++;
@@ -644,14 +645,11 @@ function loadI18nModule(mercurConfig) {
644
645
  }
645
646
 
646
647
  // src/plugin.ts
647
- function isPageFile(file) {
648
+ function isRouteFile(file) {
648
649
  const basename = import_path5.default.basename(file, import_path5.default.extname(file));
649
650
  return basename === "page";
650
651
  }
651
- var UI_MODULE_KEYS = [
652
- "admin_ui",
653
- "vendor_ui"
654
- ];
652
+ var UI_MODULE_KEYS = ["admin_ui", "vendor_ui"];
655
653
  function findNodeModulesRoot(configDir) {
656
654
  let dir = configDir;
657
655
  while (dir !== import_path5.default.dirname(dir)) {
@@ -691,7 +689,12 @@ function resolvePluginExtensions(plugins, configDir) {
691
689
  const pluginRoot = resolvePluginRoot(resolve, configDir, nodeModulesRoot);
692
690
  if (!pluginRoot) continue;
693
691
  for (const appType of appTypes) {
694
- const extFile = import_path5.default.join(pluginRoot, ".medusa/server/src", appType, "index.mjs");
692
+ const extFile = import_path5.default.join(
693
+ pluginRoot,
694
+ ".medusa/server/src",
695
+ appType,
696
+ "index.mjs"
697
+ );
695
698
  if (import_fs4.default.existsSync(extFile)) {
696
699
  extensions.push(extFile);
697
700
  }
@@ -708,14 +711,17 @@ async function loadMedusaConfig(medusaConfigPath, root) {
708
711
  let base;
709
712
  for (const key of UI_MODULE_KEYS) {
710
713
  const value = modules[key];
711
- if (!value || typeof value !== "object" || !value.options?.appDir) continue;
714
+ if (!value || typeof value !== "object" || !value.options?.appDir)
715
+ continue;
712
716
  const appDir = import_path5.default.resolve(configDir, value.options.appDir);
713
717
  if (appDir === root) {
714
718
  base = value.options.path;
715
719
  break;
716
720
  }
717
721
  }
718
- const plugins = medusaConfig?.plugins?.filter((plugin) => plugin.resolve !== "@medusajs/draft-order") ?? [];
722
+ const plugins = medusaConfig?.plugins?.filter(
723
+ (plugin) => plugin.resolve !== "@medusajs/draft-order"
724
+ ) ?? [];
719
725
  const pluginExtensions = resolvePluginExtensions(plugins, configDir);
720
726
  return { base, pluginExtensions };
721
727
  } catch {
@@ -729,8 +735,14 @@ function mercurDashboardPlugin(pluginConfig) {
729
735
  name: "@mercurjs/dashboard-sdk",
730
736
  async config(viteConfig) {
731
737
  root = viteConfig.root || process.cwd();
732
- const medusaConfigPath = import_path5.default.resolve(root, pluginConfig.medusaConfigPath);
733
- const { base, pluginExtensions } = await loadMedusaConfig(medusaConfigPath, root);
738
+ const medusaConfigPath = import_path5.default.resolve(
739
+ root,
740
+ pluginConfig.medusaConfigPath
741
+ );
742
+ const { base, pluginExtensions } = await loadMedusaConfig(
743
+ medusaConfigPath,
744
+ root
745
+ );
734
746
  const srcDir = import_path5.default.join(root, "src");
735
747
  const backendUrl = pluginConfig.backendUrl ?? "http://localhost:9000";
736
748
  config = {
@@ -744,11 +756,28 @@ function mercurDashboardPlugin(pluginConfig) {
744
756
  return {
745
757
  base: config.base,
746
758
  define: {
747
- "__BACKEND_URL__": JSON.stringify(config.backendUrl),
748
- "__BASE__": JSON.stringify(config.base || "/")
759
+ __BACKEND_URL__: JSON.stringify(config.backendUrl),
760
+ __BASE__: JSON.stringify(config.base || "/")
749
761
  },
750
762
  optimizeDeps: {
751
- exclude: ["virtual:mercur/config", "virtual:mercur/routes", "virtual:mercur/components", "virtual:mercur/menu-items", "virtual:mercur/i18n"]
763
+ exclude: [
764
+ "virtual:mercur/config",
765
+ "virtual:mercur/routes",
766
+ "virtual:mercur/components",
767
+ "virtual:mercur/menu-items",
768
+ "virtual:mercur/i18n"
769
+ ],
770
+ include: [
771
+ "react",
772
+ "react/jsx-runtime",
773
+ "react-dom/client",
774
+ "react-router-dom",
775
+ "react-i18next",
776
+ "@medusajs/ui",
777
+ "@medusajs/dashboard",
778
+ "@medusajs/js-sdk",
779
+ "@tanstack/react-query"
780
+ ]
752
781
  }
753
782
  };
754
783
  },
@@ -765,19 +794,19 @@ function mercurDashboardPlugin(pluginConfig) {
765
794
  return loadVirtualModule({ cwd: root, id, mercurConfig: config });
766
795
  },
767
796
  configureServer(server) {
768
- const handlePageChange = (file) => {
769
- if (!isPageFile(file)) return;
797
+ const handleRouteChange = (file) => {
798
+ if (!isRouteFile(file)) return;
770
799
  const mod = server.moduleGraph.getModuleById(RESOLVED_ROUTES_MODULE);
771
800
  if (mod) {
772
801
  server.moduleGraph.invalidateModule(mod);
773
802
  server.ws.send({ type: "full-reload" });
774
803
  }
775
804
  };
776
- server.watcher.on("add", handlePageChange);
777
- server.watcher.on("unlink", handlePageChange);
805
+ server.watcher.on("add", handleRouteChange);
806
+ server.watcher.on("unlink", handleRouteChange);
778
807
  },
779
808
  handleHotUpdate({ file, server }) {
780
- if (isPageFile(file)) {
809
+ if (isRouteFile(file)) {
781
810
  const mod = server.moduleGraph.getModuleById(RESOLVED_ROUTES_MODULE);
782
811
  if (mod) {
783
812
  server.moduleGraph.invalidateModule(mod);
@@ -786,7 +815,72 @@ function mercurDashboardPlugin(pluginConfig) {
786
815
  }
787
816
  };
788
817
  }
818
+
819
+ // src/generate-plugin-entry.ts
820
+ var import_path6 = __toESM(require("path"), 1);
821
+ var import_fs5 = __toESM(require("fs"), 1);
822
+ function findI18nIndex2(srcDir) {
823
+ const i18nDir = import_path6.default.join(srcDir, "i18n");
824
+ if (!import_fs5.default.existsSync(i18nDir)) return null;
825
+ for (const ext of VALID_FILE_EXTENSIONS) {
826
+ const filePath = import_path6.default.join(i18nDir, `index${ext}`);
827
+ if (import_fs5.default.existsSync(filePath)) return filePath;
828
+ }
829
+ return null;
830
+ }
831
+ function generatePluginEntryModule(srcDir) {
832
+ const routesDir = import_path6.default.join(srcDir, "routes");
833
+ const files = crawlRoutes(routesDir);
834
+ let index = 0;
835
+ const routeResults = [];
836
+ const menuItemResults = [];
837
+ for (const file of files) {
838
+ const route = parseFile(file, routesDir, index);
839
+ if (route) {
840
+ routeResults.push(route);
841
+ }
842
+ const menuItem = parseMenuItemFile(file, routesDir, index);
843
+ if (menuItem) {
844
+ menuItemResults.push(menuItem);
845
+ }
846
+ index++;
847
+ }
848
+ const routeTree = buildRouteTree(routeResults.filter(Boolean));
849
+ const routeImports = routeTree.flatMap((r) => r.imports);
850
+ const routes = routeTree.map((r) => formatRoute(r.route));
851
+ const menuItemImports = menuItemResults.filter(Boolean).map((r) => r.import);
852
+ const menuItems = menuItemResults.filter(Boolean).map((r) => formatMenuItem(r.menuItem));
853
+ const i18nFile = findI18nIndex2(srcDir);
854
+ const i18nImport = i18nFile ? `import i18nResources from "${normalizePath(i18nFile)}"` : "";
855
+ const i18nValue = i18nFile ? "i18nResources" : "{}";
856
+ const allImports = [...routeImports, ...menuItemImports];
857
+ if (i18nImport) allImports.push(i18nImport);
858
+ return `// Auto-generated plugin extensions entry
859
+ ${allImports.join("\n")}
860
+
861
+ const routeModule = {
862
+ routes: [
863
+ ${routes.join(",\n")}
864
+ ]
865
+ }
866
+
867
+ const menuItemModule = {
868
+ menuItems: [
869
+ ${menuItems.join(",\n")}
870
+ ]
871
+ }
872
+
873
+ const plugin = {
874
+ routeModule,
875
+ menuItemModule,
876
+ i18nModule: ${i18nValue},
877
+ }
878
+
879
+ export default plugin
880
+ `;
881
+ }
789
882
  // Annotate the CommonJS export names for ESM import in node:
790
883
  0 && (module.exports = {
884
+ generatePluginEntryModule,
791
885
  mercurDashboardPlugin
792
886
  });
package/dist/index.d.cts CHANGED
@@ -34,4 +34,11 @@ type RouteConfig = {
34
34
 
35
35
  declare function mercurDashboardPlugin(pluginConfig: MercurConfig): Vite.Plugin;
36
36
 
37
- export { type BuiltMercurConfig, type MercurConfig, type RouteConfig, mercurDashboardPlugin };
37
+ /**
38
+ * Generates a plugin entry module for a given source directory (e.g. src/vendor).
39
+ * Scans routes, menu items, and i18n — outputs a single module string
40
+ * that exports default `{ routeModule, menuItemModule, i18nModule }`.
41
+ */
42
+ declare function generatePluginEntryModule(srcDir: string): string;
43
+
44
+ export { type BuiltMercurConfig, type MercurConfig, type RouteConfig, generatePluginEntryModule, mercurDashboardPlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mercurjs/dashboard-sdk",
3
- "version": "2.0.0-canary.80",
3
+ "version": "2.0.0-canary.81",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/mercurjs/mercur",