@open-mercato/cli 0.6.8-develop.7032.1.70d74d4bfe → 0.6.8-develop.7037.1.ea0277b01e

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 (101) hide show
  1. package/dist/agentic/guides/module-facts.json +126 -126
  2. package/dist/agentic/guides/module-facts.v2.json +126 -126
  3. package/dist/agentic/guides/modules/ai_assistant/index.md +1 -1
  4. package/dist/agentic/guides/modules/api_docs/index.md +1 -1
  5. package/dist/agentic/guides/modules/api_keys/index.md +1 -1
  6. package/dist/agentic/guides/modules/attachments/index.md +1 -1
  7. package/dist/agentic/guides/modules/audit_logs/index.md +1 -1
  8. package/dist/agentic/guides/modules/auth/index.md +1 -1
  9. package/dist/agentic/guides/modules/business_rules/index.md +1 -1
  10. package/dist/agentic/guides/modules/catalog/index.md +1 -1
  11. package/dist/agentic/guides/modules/channel_apns/index.md +1 -1
  12. package/dist/agentic/guides/modules/channel_expo/index.md +1 -1
  13. package/dist/agentic/guides/modules/channel_fcm/index.md +1 -1
  14. package/dist/agentic/guides/modules/channel_gmail/index.md +1 -1
  15. package/dist/agentic/guides/modules/channel_imap/index.md +1 -1
  16. package/dist/agentic/guides/modules/checkout/index.md +1 -1
  17. package/dist/agentic/guides/modules/communication_channels/index.md +1 -1
  18. package/dist/agentic/guides/modules/configs/index.md +1 -1
  19. package/dist/agentic/guides/modules/content/index.md +1 -1
  20. package/dist/agentic/guides/modules/currencies/index.md +1 -1
  21. package/dist/agentic/guides/modules/customer_accounts/index.md +1 -1
  22. package/dist/agentic/guides/modules/customers/index.md +1 -1
  23. package/dist/agentic/guides/modules/dashboards/index.md +1 -1
  24. package/dist/agentic/guides/modules/data_sync/index.md +1 -1
  25. package/dist/agentic/guides/modules/design_system/index.md +1 -1
  26. package/dist/agentic/guides/modules/devices/index.md +1 -1
  27. package/dist/agentic/guides/modules/dictionaries/index.md +1 -1
  28. package/dist/agentic/guides/modules/directory/index.md +1 -1
  29. package/dist/agentic/guides/modules/documents/index.md +1 -1
  30. package/dist/agentic/guides/modules/entities/index.md +1 -1
  31. package/dist/agentic/guides/modules/eudr/index.md +1 -1
  32. package/dist/agentic/guides/modules/events/index.md +1 -1
  33. package/dist/agentic/guides/modules/feature_toggles/index.md +1 -1
  34. package/dist/agentic/guides/modules/gateway_stripe/index.md +1 -1
  35. package/dist/agentic/guides/modules/generators/index.md +1 -1
  36. package/dist/agentic/guides/modules/inbox_ops/index.md +1 -1
  37. package/dist/agentic/guides/modules/integrations/index.md +1 -1
  38. package/dist/agentic/guides/modules/messages/index.md +1 -1
  39. package/dist/agentic/guides/modules/notifications/index.md +1 -1
  40. package/dist/agentic/guides/modules/onboarding/index.md +1 -1
  41. package/dist/agentic/guides/modules/payment_gateways/index.md +1 -1
  42. package/dist/agentic/guides/modules/perspectives/index.md +1 -1
  43. package/dist/agentic/guides/modules/planner/index.md +1 -1
  44. package/dist/agentic/guides/modules/portal/index.md +1 -1
  45. package/dist/agentic/guides/modules/progress/index.md +1 -1
  46. package/dist/agentic/guides/modules/push_notifications/index.md +1 -1
  47. package/dist/agentic/guides/modules/query_index/index.md +1 -1
  48. package/dist/agentic/guides/modules/record_locks/index.md +1 -1
  49. package/dist/agentic/guides/modules/resources/index.md +1 -1
  50. package/dist/agentic/guides/modules/sales/index.md +1 -1
  51. package/dist/agentic/guides/modules/scheduler/index.md +1 -1
  52. package/dist/agentic/guides/modules/search/index.md +1 -1
  53. package/dist/agentic/guides/modules/security/index.md +1 -1
  54. package/dist/agentic/guides/modules/shipping_carriers/index.md +1 -1
  55. package/dist/agentic/guides/modules/sso/index.md +1 -1
  56. package/dist/agentic/guides/modules/staff/index.md +1 -1
  57. package/dist/agentic/guides/modules/storage_s3/index.md +1 -1
  58. package/dist/agentic/guides/modules/sync_akeneo/index.md +1 -1
  59. package/dist/agentic/guides/modules/sync_excel/index.md +1 -1
  60. package/dist/agentic/guides/modules/system_status_overlays/index.md +1 -1
  61. package/dist/agentic/guides/modules/translations/index.md +1 -1
  62. package/dist/agentic/guides/modules/warranty_claims/index.md +1 -1
  63. package/dist/agentic/guides/modules/webhooks/index.md +1 -1
  64. package/dist/agentic/guides/modules/wms/index.md +1 -1
  65. package/dist/agentic/guides/modules/workflows/index.md +1 -1
  66. package/dist/agentic/guides/reference-module-facts.json +1 -1
  67. package/dist/agentic/guides/upstream/manifest.json +1 -1
  68. package/dist/lib/generators/ast/index.js +4 -1
  69. package/dist/lib/generators/ast/index.js.map +2 -2
  70. package/dist/lib/generators/ast/source-file.js +8 -1
  71. package/dist/lib/generators/ast/source-file.js.map +2 -2
  72. package/dist/lib/generators/ast/writers.js +9 -1
  73. package/dist/lib/generators/ast/writers.js.map +2 -2
  74. package/dist/lib/generators/module-registry.js +343 -183
  75. package/dist/lib/generators/module-registry.js.map +2 -2
  76. package/dist/lib/generators/route-manifest-shards.js +4 -1
  77. package/dist/lib/generators/route-manifest-shards.js.map +2 -2
  78. package/dist/lib/spawn.js +3 -2
  79. package/dist/lib/spawn.js.map +2 -2
  80. package/dist/lib/testing/integration.js +162 -24
  81. package/dist/lib/testing/integration.js.map +2 -2
  82. package/package.json +6 -6
  83. package/src/lib/__tests__/spawn.test.ts +23 -0
  84. package/src/lib/generators/__tests__/__snapshots__/bootstrap-registrations.test.ts.snap +14 -0
  85. package/src/lib/generators/__tests__/__snapshots__/command-loaders.test.ts.snap +23 -0
  86. package/src/lib/generators/__tests__/ast-writers-escaping.test.ts +64 -0
  87. package/src/lib/generators/__tests__/bootstrap-registrations.test.ts +176 -0
  88. package/src/lib/generators/__tests__/command-loaders.test.ts +239 -0
  89. package/src/lib/generators/__tests__/module-subset.test.ts +96 -72
  90. package/src/lib/generators/__tests__/output-snapshots.test.ts +1 -1
  91. package/src/lib/generators/__tests__/registry-variant-parity.test.ts +258 -0
  92. package/src/lib/generators/__tests__/route-manifest-shards.test.ts +15 -0
  93. package/src/lib/generators/__tests__/structural-contracts.test.ts +3 -3
  94. package/src/lib/generators/ast/index.ts +2 -1
  95. package/src/lib/generators/ast/source-file.ts +13 -0
  96. package/src/lib/generators/ast/writers.ts +26 -1
  97. package/src/lib/generators/module-registry.ts +417 -236
  98. package/src/lib/generators/route-manifest-shards.ts +8 -1
  99. package/src/lib/spawn.ts +5 -4
  100. package/src/lib/testing/__tests__/integration.test.ts +435 -0
  101. package/src/lib/testing/integration.ts +254 -32
@@ -28,6 +28,7 @@ import {
28
28
  conditionalExpression,
29
29
  createGeneratedSourceFile,
30
30
  elementAccess,
31
+ escapeGeneratedJsonLiteral,
31
32
  returnStatement,
32
33
  getSourceText,
33
34
  identifier,
@@ -40,6 +41,7 @@ import {
40
41
  optionalPropertyAccess,
41
42
  parenthesized,
42
43
  propertyAccess,
44
+ renderGeneratedValue,
43
45
  spreadExpression,
44
46
  variableStatement,
45
47
  writeArrayLiteral,
@@ -775,7 +777,7 @@ function requiresRuntimePageMetadataFromSourceFile(sourceFile) {
775
777
  return !/^['"`]/.test(iconMatch[1].trim());
776
778
  }
777
779
  function toLiteral(value) {
778
- return JSON.stringify(value).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
780
+ return escapeGeneratedJsonLiteral(JSON.stringify(value));
779
781
  }
780
782
  const GENERATED_MODULE_RELATIVE_PREFIXES = ["@/", "../../src/modules/", "./"];
781
783
  const GENERATED_MODULE_SPECIFIER_SEGMENT = /^[A-Za-z0-9_.\-[\]()']+$/;
@@ -964,28 +966,66 @@ function collectCommandLoaderEntries(roots, imps, modId, quiet = false) {
964
966
  }
965
967
  function renderCommandLoadersFile(entries) {
966
968
  const seenCommandIds = /* @__PURE__ */ new Map();
967
- const rendered = [];
969
+ const loaderEntries = [];
968
970
  for (const entry of entries) {
969
- const loadExpr = `() => ${buildDynamicImportExpression(entry.importPath)}`;
971
+ const loadValue = arrowFunction({
972
+ body: importExpression(sanitizeGeneratedModuleSpecifier(entry.importPath))
973
+ });
970
974
  for (const id of entry.ids) {
971
975
  const previous = seenCommandIds.get(id);
972
976
  if (previous && previous !== entry.key) {
973
977
  throw new Error(`[generate] Duplicate command id "${id}" discovered in "${previous}" and "${entry.key}"`);
974
978
  }
975
979
  seenCommandIds.set(id, entry.key);
976
- rendered.push(` { moduleId: ${toLiteral(entry.moduleId)}, id: ${toLiteral(id)}, key: ${toLiteral(entry.key)}, load: ${loadExpr} },`);
980
+ loaderEntries.push(objectLiteral([
981
+ { name: "moduleId", value: entry.moduleId },
982
+ { name: "id", value: id },
983
+ { name: "key", value: entry.key },
984
+ { name: "load", value: loadValue }
985
+ ]));
977
986
  }
978
- rendered.push(` { moduleId: ${toLiteral(entry.moduleId)}, key: ${toLiteral(entry.key)}, load: ${loadExpr} },`);
987
+ loaderEntries.push(objectLiteral([
988
+ { name: "moduleId", value: entry.moduleId },
989
+ { name: "key", value: entry.key },
990
+ { name: "load", value: loadValue }
991
+ ]));
979
992
  }
980
- return `// AUTO-GENERATED by mercato generate command-loaders
981
- import type { CommandLoader } from '@open-mercato/shared/lib/commands'
982
-
983
- export const commandLoaderEntries: CommandLoader[] = [
984
- ${rendered.join("\n")}
985
- ]
986
-
987
- export default commandLoaderEntries
988
- `;
993
+ const sourceFile = createGeneratedSourceFile("command-loaders.generated.ts");
994
+ addAutoGeneratedComment(sourceFile, "command-loaders");
995
+ addImportSpec(sourceFile, {
996
+ moduleSpecifier: "@open-mercato/shared/lib/commands",
997
+ isTypeOnly: true,
998
+ namedImports: [{ name: "CommandLoader" }]
999
+ });
1000
+ sourceFile.addVariableStatement({
1001
+ declarationKind: VariableDeclarationKind.Const,
1002
+ isExported: true,
1003
+ declarations: [
1004
+ {
1005
+ name: "commandLoaderEntries",
1006
+ type: "CommandLoader[]",
1007
+ initializer: arrayLiteral(loaderEntries, writeValue)
1008
+ }
1009
+ ]
1010
+ });
1011
+ sourceFile.addExportAssignment({
1012
+ isExportEquals: false,
1013
+ expression: "commandLoaderEntries"
1014
+ });
1015
+ return getSourceText(sourceFile);
1016
+ }
1017
+ function renderBootstrapRegistrationsFile(options) {
1018
+ const uniqueImports = [.../* @__PURE__ */ new Set([...options.entryImports, ...options.registrationImports])];
1019
+ const sourceFile = createGeneratedSourceFile("bootstrap-registrations.generated.ts");
1020
+ addAutoGeneratedComment(sourceFile, "registry");
1021
+ addImportStatements(sourceFile, uniqueImports);
1022
+ sourceFile.addFunction({
1023
+ name: "runBootstrapRegistrations",
1024
+ isExported: true,
1025
+ returnType: "void",
1026
+ statements: options.calls
1027
+ });
1028
+ return getSourceText(sourceFile);
989
1029
  }
990
1030
  function serializeGeneratedImport(statement) {
991
1031
  if (typeof statement === "string") {
@@ -1168,7 +1208,35 @@ function buildPageRouteProps(metaExpr, routePath) {
1168
1208
  return `pattern: ${toLiteral(routePath || "/")}, requireAuth: (${metaExpr})?.requireAuth, requireRoles: (${metaExpr})?.requireRoles, requireFeatures: (${metaExpr})?.requireFeatures, requireCustomerAuth: (${metaExpr})?.requireCustomerAuth, requireCustomerFeatures: (${metaExpr})?.requireCustomerFeatures, nav: (${metaExpr})?.nav, title: (${metaExpr})?.pageTitle ?? (${metaExpr})?.title, titleKey: (${metaExpr})?.pageTitleKey ?? (${metaExpr})?.titleKey, group: (${metaExpr})?.pageGroup ?? (${metaExpr})?.group, groupKey: (${metaExpr})?.pageGroupKey ?? (${metaExpr})?.groupKey, icon: (${metaExpr})?.icon, order: (${metaExpr})?.pageOrder ?? (${metaExpr})?.order, priority: (${metaExpr})?.pagePriority ?? (${metaExpr})?.priority, navHidden: (${metaExpr})?.navHidden, visible: (${metaExpr})?.visible, enabled: (${metaExpr})?.enabled, breadcrumb: (${metaExpr})?.breadcrumb, pageContext: (${metaExpr})?.pageContext, placement: (${metaExpr})?.placement`;
1169
1209
  }
1170
1210
  function buildPageRouteManifestSpread(metaExpr, routePath) {
1171
- return `...resolvePageRouteMetadata(${toLiteral(routePath || "/")}, ${metaExpr})`;
1211
+ return callExpression(identifier("resolvePageRouteMetadata"), [routePath || "/", identifier(metaExpr)]);
1212
+ }
1213
+ function buildManifestRouteLoader(importPath) {
1214
+ return arrowFunction({
1215
+ async: true,
1216
+ body: block((writer) => {
1217
+ writeStatements(writer, [
1218
+ variableStatement({
1219
+ name: "mod",
1220
+ initializer: awaitExpression(importExpression(sanitizeGeneratedModuleSpecifier(importPath)))
1221
+ }),
1222
+ returnStatement(
1223
+ asExpression(
1224
+ parenthesized(nullishCoalesce([
1225
+ propertyAccess(identifier("mod"), "default"),
1226
+ identifier("mod")
1227
+ ])),
1228
+ "any"
1229
+ )
1230
+ )
1231
+ ]);
1232
+ })
1233
+ });
1234
+ }
1235
+ function buildManifestApiLoader(importPath) {
1236
+ return arrowFunction({
1237
+ async: true,
1238
+ body: importExpression(sanitizeGeneratedModuleSpecifier(importPath))
1239
+ });
1172
1240
  }
1173
1241
  function normalizeBreadcrumb(raw) {
1174
1242
  if (!Array.isArray(raw)) return void 0;
@@ -1495,18 +1563,25 @@ async function processPageFiles(options) {
1495
1563
  const manifestBaseProps = buildPageRouteManifestSpread(manifestMetaExpr, routePath);
1496
1564
  eagerRoutes.push(`{ ${baseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`);
1497
1565
  runtimeRoutes.push(`{ ${runtimeBaseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`);
1498
- const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, ${manifestBaseProps} }`;
1499
- const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, ${manifestBaseProps}, load: async () => { const mod = await ${buildDynamicImportExpression(importPath)}; return (mod.default ?? mod) as any } }`;
1500
- manifestRoutes.push(manifestDeclaration);
1566
+ const metadataEntries = [
1567
+ { name: "moduleId", value: modId },
1568
+ { kind: "spread", value: manifestBaseProps }
1569
+ ];
1570
+ const manifestEntry = objectLiteral([
1571
+ ...metadataEntries,
1572
+ { name: "load", value: buildManifestRouteLoader(importPath) }
1573
+ ]);
1574
+ const shardImports = manifestImportStatement ? [manifestImportStatement] : [];
1575
+ manifestRoutes.push(manifestEntry);
1501
1576
  manifestShardRoutes.push({
1502
1577
  path: routePath,
1503
- declaration: manifestDeclaration,
1504
- imports: manifestImportStatement ? [manifestImportStatement] : []
1578
+ declaration: renderGeneratedValue(manifestEntry),
1579
+ imports: shardImports
1505
1580
  });
1506
1581
  metadataRoutes.push({
1507
1582
  path: routePath,
1508
- declaration: metadataDeclaration,
1509
- imports: manifestImportStatement ? [manifestImportStatement] : []
1583
+ declaration: renderGeneratedValue(objectLiteral(metadataEntries)),
1584
+ imports: shardImports
1510
1585
  });
1511
1586
  routePatterns.push(routePath);
1512
1587
  }
@@ -1580,18 +1655,25 @@ async function processPageFiles(options) {
1580
1655
  const manifestBaseProps = buildPageRouteManifestSpread(manifestMetaExpr, routePath);
1581
1656
  eagerRoutes.push(`{ ${baseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`);
1582
1657
  runtimeRoutes.push(`{ ${runtimeBaseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`);
1583
- const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, ${manifestBaseProps} }`;
1584
- const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, ${manifestBaseProps}, load: async () => { const mod = await ${buildDynamicImportExpression(importPath)}; return (mod.default ?? mod) as any } }`;
1585
- manifestRoutes.push(manifestDeclaration);
1658
+ const metadataEntries = [
1659
+ { name: "moduleId", value: modId },
1660
+ { kind: "spread", value: manifestBaseProps }
1661
+ ];
1662
+ const manifestEntry = objectLiteral([
1663
+ ...metadataEntries,
1664
+ { name: "load", value: buildManifestRouteLoader(importPath) }
1665
+ ]);
1666
+ const shardImports = manifestImportStatement ? [manifestImportStatement] : [];
1667
+ manifestRoutes.push(manifestEntry);
1586
1668
  manifestShardRoutes.push({
1587
1669
  path: routePath,
1588
- declaration: manifestDeclaration,
1589
- imports: manifestImportStatement ? [manifestImportStatement] : []
1670
+ declaration: renderGeneratedValue(manifestEntry),
1671
+ imports: shardImports
1590
1672
  });
1591
1673
  metadataRoutes.push({
1592
1674
  path: routePath,
1593
- declaration: metadataDeclaration,
1594
- imports: manifestImportStatement ? [manifestImportStatement] : []
1675
+ declaration: renderGeneratedValue(objectLiteral(metadataEntries)),
1676
+ imports: shardImports
1595
1677
  });
1596
1678
  routePatterns.push(routePath);
1597
1679
  }
@@ -1644,11 +1726,19 @@ async function processApiRoutes(options) {
1644
1726
  eagerImports.push(buildImportStatement(`* as ${importName}`, importPath));
1645
1727
  eagerApis.push(`{ path: ((${importName} as any).metadata?.path ?? ${toLiteral(routePath)}), metadata: (${importName} as any).metadata, handlers: ${importName} as any${docsPart} }`);
1646
1728
  runtimeApis.push(`{ path: ${toLiteral(resolvedPath)}, metadata: ${metadataLiteral}, handlers: { ${exportedMethods.map((method) => `${method}: async (req: Request, ctx?: any) => { const mod = await ${buildDynamicImportExpression(importPath)}; return (mod as any).${method}(req, ctx) }`).join(", ")} } }`);
1647
- const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral("route-file")}, path: ${toLiteral(resolvedPath)}, methods: [${exportedMethods.map((method) => toLiteral(method)).join(", ")}] }`;
1648
- const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral("route-file")}, path: ${toLiteral(resolvedPath)}, methods: [${exportedMethods.map((method) => toLiteral(method)).join(", ")}], load: async () => ${buildDynamicImportExpression(importPath)} }`;
1649
- manifestApis.push(manifestDeclaration);
1650
- manifestShardApis.push({ path: resolvedPath, declaration: manifestDeclaration });
1651
- metadataApis.push({ path: resolvedPath, declaration: metadataDeclaration });
1729
+ const metadataEntries = [
1730
+ { name: "moduleId", value: modId },
1731
+ { name: "kind", value: "route-file" },
1732
+ { name: "path", value: resolvedPath },
1733
+ { name: "methods", value: arrayLiteral(exportedMethods, writeValue) }
1734
+ ];
1735
+ const manifestEntry = objectLiteral([
1736
+ ...metadataEntries,
1737
+ { name: "load", value: buildManifestApiLoader(importPath) }
1738
+ ]);
1739
+ manifestApis.push(manifestEntry);
1740
+ manifestShardApis.push({ path: resolvedPath, declaration: renderGeneratedValue(manifestEntry) });
1741
+ metadataApis.push({ path: resolvedPath, declaration: renderGeneratedValue(objectLiteral(metadataEntries)) });
1652
1742
  }
1653
1743
  const plainFiles = scanModuleDir(roots, SCAN_CONFIGS.apiPlainFiles);
1654
1744
  for (const { relPath, fromApp } of plainFiles) {
@@ -1678,11 +1768,19 @@ async function processApiRoutes(options) {
1678
1768
  eagerImports.push(buildImportStatement(`* as ${importName}`, importPath));
1679
1769
  eagerApis.push(`{ path: ((${importName} as any).metadata?.path ?? ${toLiteral(routePath)}), metadata: (${importName} as any).metadata, handlers: ${importName} as any${docsPart} }`);
1680
1770
  runtimeApis.push(`{ path: ${toLiteral(resolvedPath)}, metadata: ${metadataLiteral}, handlers: { ${exportedMethods.map((entryMethod) => `${entryMethod}: async (req: Request, ctx?: any) => { const mod = await ${buildDynamicImportExpression(importPath)}; return (mod as any).${entryMethod}(req, ctx) }`).join(", ")} } }`);
1681
- const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral("route-file")}, path: ${toLiteral(resolvedPath)}, methods: [${exportedMethods.map((entryMethod) => toLiteral(entryMethod)).join(", ")}] }`;
1682
- const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral("route-file")}, path: ${toLiteral(resolvedPath)}, methods: [${exportedMethods.map((entryMethod) => toLiteral(entryMethod)).join(", ")}], load: async () => ${buildDynamicImportExpression(importPath)} }`;
1683
- manifestApis.push(manifestDeclaration);
1684
- manifestShardApis.push({ path: resolvedPath, declaration: manifestDeclaration });
1685
- metadataApis.push({ path: resolvedPath, declaration: metadataDeclaration });
1771
+ const metadataEntries = [
1772
+ { name: "moduleId", value: modId },
1773
+ { name: "kind", value: "route-file" },
1774
+ { name: "path", value: resolvedPath },
1775
+ { name: "methods", value: arrayLiteral(exportedMethods, writeValue) }
1776
+ ];
1777
+ const manifestEntry = objectLiteral([
1778
+ ...metadataEntries,
1779
+ { name: "load", value: buildManifestApiLoader(importPath) }
1780
+ ]);
1781
+ manifestApis.push(manifestEntry);
1782
+ manifestShardApis.push({ path: resolvedPath, declaration: renderGeneratedValue(manifestEntry) });
1783
+ metadataApis.push({ path: resolvedPath, declaration: renderGeneratedValue(objectLiteral(metadataEntries)) });
1686
1784
  }
1687
1785
  const methods = ["GET", "POST", "PUT", "PATCH", "DELETE"];
1688
1786
  for (const method of methods) {
@@ -1721,11 +1819,20 @@ async function processApiRoutes(options) {
1721
1819
  eagerImports.push(buildImportStatement(`${importName}, * as ${metaName}`, importPath));
1722
1820
  eagerApis.push(`{ method: ${toLiteral(method)}, path: (${metaName}.metadata?.path ?? ${toLiteral(routePath)}), handler: ${importName}, metadata: ${metaName}.metadata${docsPart} }`);
1723
1821
  runtimeApis.push(`{ method: ${toLiteral(method)}, path: ${toLiteral(resolvedPath)}, handler: async (req: Request, ctx?: any) => { const mod = await ${buildDynamicImportExpression(importPath)}; const handler = ((mod as any).default ?? (mod as any).${method} ?? (mod as any).handler) as any; return handler(req, ctx) }, metadata: ${metadataLiteral} }`);
1724
- const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral("legacy")}, method: ${toLiteral(method)}, path: ${toLiteral(resolvedPath)}, methods: [${toLiteral(method)}] }`;
1725
- const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral("legacy")}, method: ${toLiteral(method)}, path: ${toLiteral(resolvedPath)}, methods: [${toLiteral(method)}], load: async () => ${buildDynamicImportExpression(importPath)} }`;
1726
- manifestApis.push(manifestDeclaration);
1727
- manifestShardApis.push({ path: resolvedPath, declaration: manifestDeclaration });
1728
- metadataApis.push({ path: resolvedPath, declaration: metadataDeclaration });
1822
+ const metadataEntries = [
1823
+ { name: "moduleId", value: modId },
1824
+ { name: "kind", value: "legacy" },
1825
+ { name: "method", value: method },
1826
+ { name: "path", value: resolvedPath },
1827
+ { name: "methods", value: arrayLiteral([method], writeValue) }
1828
+ ];
1829
+ const manifestEntry = objectLiteral([
1830
+ ...metadataEntries,
1831
+ { name: "load", value: buildManifestApiLoader(importPath) }
1832
+ ]);
1833
+ manifestApis.push(manifestEntry);
1834
+ manifestShardApis.push({ path: resolvedPath, declaration: renderGeneratedValue(manifestEntry) });
1835
+ metadataApis.push({ path: resolvedPath, declaration: renderGeneratedValue(objectLiteral(metadataEntries)) });
1729
1836
  }
1730
1837
  }
1731
1838
  return {
@@ -1736,58 +1843,10 @@ async function processApiRoutes(options) {
1736
1843
  metadataApis
1737
1844
  };
1738
1845
  }
1739
- function processSubscribers(discovered) {
1740
- const subscribers = [];
1741
- for (const { id, importPath, metadata } of discovered) {
1742
- const subscriberId = metadata?.id ?? id;
1743
- subscribers.push(
1744
- `{ id: ${toLiteral(subscriberId)}, event: ${toLiteral(metadata?.event ?? "")}, persistent: ${metadata?.persistent === void 0 ? "undefined" : toLiteral(metadata.persistent)}, sync: ${metadata?.sync === void 0 ? "undefined" : toLiteral(metadata.sync)}, priority: ${metadata?.priority === void 0 ? "undefined" : toLiteral(metadata.priority)}, handler: createLazyModuleSubscriber(() => ${buildDynamicImportExpression(importPath)}, ${toLiteral(subscriberId)}) }`
1745
- );
1746
- }
1747
- return subscribers;
1748
- }
1749
1846
  const ABANDON_HOOK_FACTORY = "createLazyModuleWorkerAbandonHook";
1750
1847
  function workersDeclareAbandonHook(discovered) {
1751
1848
  return discovered.some(({ metadata }) => metadata.hasJobAbandonedHook === true);
1752
1849
  }
1753
- function processWorkers(discovered) {
1754
- const workers = [];
1755
- for (const { id, importPath, metadata } of discovered) {
1756
- const workerId = metadata.id ?? id;
1757
- workers.push(
1758
- `{ id: ${toLiteral(workerId)}, queue: ${toLiteral(metadata.queue)}, concurrency: ${toLiteral(metadata.concurrency ?? 1)}${metadata.lockDuration === void 0 ? "" : `, lockDuration: ${toLiteral(metadata.lockDuration)}`}${metadata.maxStalledCount === void 0 ? "" : `, maxStalledCount: ${toLiteral(metadata.maxStalledCount)}`}${metadata.hasJobAbandonedHook ? `, onJobAbandoned: ${ABANDON_HOOK_FACTORY}(() => ${buildDynamicImportExpression(importPath)}, ${toLiteral(workerId)})` : ""}, handler: createLazyModuleWorker(() => ${buildDynamicImportExpression(importPath)}, ${toLiteral(workerId)}) }`
1759
- );
1760
- }
1761
- return workers;
1762
- }
1763
- function processTranslations(options) {
1764
- const { discovered, modId, appImportBase, pkgImportBase, imports, extraImports } = options;
1765
- const translations = [];
1766
- for (const { locale, coreHas, appHas } of discovered) {
1767
- if (coreHas && appHas) {
1768
- const cName = `T_${toVar(modId)}_${toVar(locale)}_C`;
1769
- const aName = `T_${toVar(modId)}_${toVar(locale)}_A`;
1770
- imports.push(buildImportStatement(cName, `${pkgImportBase}/i18n/${locale}.json`));
1771
- imports.push(buildImportStatement(aName, `${appImportBase}/i18n/${locale}.json`));
1772
- extraImports?.push(buildImportStatement(cName, `${pkgImportBase}/i18n/${locale}.json`));
1773
- extraImports?.push(buildImportStatement(aName, `${appImportBase}/i18n/${locale}.json`));
1774
- translations.push(
1775
- `'${locale}': { ...( ${cName} as unknown as Record<string,string> ), ...( ${aName} as unknown as Record<string,string> ) }`
1776
- );
1777
- } else if (appHas) {
1778
- const aName = `T_${toVar(modId)}_${toVar(locale)}_A`;
1779
- imports.push(buildImportStatement(aName, `${appImportBase}/i18n/${locale}.json`));
1780
- extraImports?.push(buildImportStatement(aName, `${appImportBase}/i18n/${locale}.json`));
1781
- translations.push(`'${locale}': ${aName} as unknown as Record<string,string>`);
1782
- } else if (coreHas) {
1783
- const cName = `T_${toVar(modId)}_${toVar(locale)}_C`;
1784
- imports.push(buildImportStatement(cName, `${pkgImportBase}/i18n/${locale}.json`));
1785
- extraImports?.push(buildImportStatement(cName, `${pkgImportBase}/i18n/${locale}.json`));
1786
- translations.push(`'${locale}': ${cName} as unknown as Record<string,string>`);
1787
- }
1788
- }
1789
- return translations;
1790
- }
1791
1850
  function processStandaloneConfig(options) {
1792
1851
  const {
1793
1852
  roots,
@@ -1912,6 +1971,37 @@ function buildModuleDashboardWidgetsValue(entries) {
1912
1971
  writeValue
1913
1972
  );
1914
1973
  }
1974
+ function preRenderedExpressionList(expressions) {
1975
+ return arrayLiteral(expressions.map((expression) => identifier(expression)), writeValue);
1976
+ }
1977
+ function legacyNamespaceMemberFallback(importName, members) {
1978
+ return parenthesized(nullishCoalesce([
1979
+ propertyAccess(identifier(importName), members[0]),
1980
+ propertyAccess(identifier(importName), members[1])
1981
+ ]));
1982
+ }
1983
+ function buildLegacyModuleListValue(options) {
1984
+ return logicalOr([
1985
+ asExpression(legacyNamespaceMemberFallback(options.importName, options.members), options.castType),
1986
+ emptyArray()
1987
+ ]);
1988
+ }
1989
+ function buildLegacyModuleSetupValue(importName) {
1990
+ return logicalOr([
1991
+ legacyNamespaceMemberFallback(importName, ["default", "setup"]),
1992
+ identifier("undefined")
1993
+ ]);
1994
+ }
1995
+ function buildLegacyIntegrationListValue(importName, pluralMember, singularMember, castType) {
1996
+ const singular = propertyAccess(identifier(importName), singularMember);
1997
+ return asExpression(
1998
+ parenthesized(nullishCoalesce([
1999
+ propertyAccess(identifier(importName), pluralMember),
2000
+ parenthesized(conditionalExpression(singular, arrayLiteral([singular], writeValue), emptyArray()))
2001
+ ])),
2002
+ castType
2003
+ );
2004
+ }
1915
2005
  function buildModuleIntegrationListValue(importName, pluralMember, singularMember, castType) {
1916
2006
  const plural = namespaceLookup(importName, pluralMember);
1917
2007
  const singular = namespaceLookup(importName, singularMember);
@@ -1966,7 +2056,7 @@ function renderAstModuleRegistryFile(options) {
1966
2056
  { name: "Module", isTypeOnly: true }
1967
2057
  ]
1968
2058
  });
1969
- addImportStatements(sourceFile, options.imports);
2059
+ addImportStatements(sourceFile, options.imports.map((entry) => serializeGeneratedImport(entry)));
1970
2060
  sourceFile.addVariableStatement({
1971
2061
  declarationKind: VariableDeclarationKind.Const,
1972
2062
  isExported: true,
@@ -1994,6 +2084,39 @@ function renderAstModuleRegistryFile(options) {
1994
2084
  });
1995
2085
  return getSourceText(sourceFile);
1996
2086
  }
2087
+ function renderAstManifestFile(options) {
2088
+ const sourceFile = createGeneratedSourceFile(options.fileName);
2089
+ addAutoGeneratedComment(sourceFile, "registry");
2090
+ const usesPageRouteMetadataHelper = options.typeName === "FrontendRouteManifestEntry" || options.typeName === "BackendRouteManifestEntry";
2091
+ addImportSpec(sourceFile, usesPageRouteMetadataHelper ? {
2092
+ moduleSpecifier: "@open-mercato/shared/modules/registry",
2093
+ namedImports: [
2094
+ { name: "resolvePageRouteMetadata" },
2095
+ { name: options.typeName, isTypeOnly: true }
2096
+ ]
2097
+ } : {
2098
+ moduleSpecifier: "@open-mercato/shared/modules/registry",
2099
+ isTypeOnly: true,
2100
+ namedImports: [{ name: options.typeName }]
2101
+ });
2102
+ addImportStatements(sourceFile, options.imports ?? []);
2103
+ sourceFile.addVariableStatement({
2104
+ declarationKind: VariableDeclarationKind.Const,
2105
+ isExported: true,
2106
+ declarations: [
2107
+ {
2108
+ name: options.exportName,
2109
+ type: `${options.typeName}[]`,
2110
+ initializer: arrayLiteral(options.entries, writeValue)
2111
+ }
2112
+ ]
2113
+ });
2114
+ sourceFile.addExportAssignment({
2115
+ isExportEquals: false,
2116
+ expression: options.exportName
2117
+ });
2118
+ return getSourceText(sourceFile);
2119
+ }
1997
2120
  function renderAstLegacyAliasFile(options) {
1998
2121
  const sourceFile = createGeneratedSourceFile(options.fileName);
1999
2122
  addAutoGeneratedComment(sourceFile, "registry");
@@ -2044,43 +2167,9 @@ function renderEnabledModuleIdsFile(moduleIds) {
2044
2167
  });
2045
2168
  return getSourceText(sourceFile);
2046
2169
  }
2047
- function renderLegacyCompatibleArray(entries) {
2048
- return `[
2049
- ${entries.join(",\n ")}
2050
- ]`;
2051
- }
2052
2170
  function buildLazyRouteComponentExpression(importPath) {
2053
2171
  return `async (props: any) => { const mod = await ${buildDynamicImportExpression(importPath)}; const Component = (mod.default ?? mod) as any; return createElement(Component, props) }`;
2054
2172
  }
2055
- function renderAstLegacyModuleRegistryOutput(options) {
2056
- const needsAbandonHookImport = options.includeAbandonHookImport || options.moduleEntries.some((entry) => entry.includes(ABANDON_HOOK_FACTORY));
2057
- const importSection = [
2058
- ...options.includeCreateElementImport ? ["import { createElement } from 'react'"] : [],
2059
- needsAbandonHookImport ? "import { createLazyModuleSubscriber, createLazyModuleWorker, createLazyModuleWorkerAbandonHook, type Module } from '@open-mercato/shared/modules/registry'" : "import { createLazyModuleSubscriber, createLazyModuleWorker, type Module } from '@open-mercato/shared/modules/registry'",
2060
- ...options.imports.map((entry) => serializeGeneratedImport(entry))
2061
- ].join("\n");
2062
- return `// AUTO-GENERATED by mercato generate registry
2063
- ${importSection}
2064
-
2065
- export const modules: Module[] = ${renderLegacyCompatibleArray(options.moduleEntries)}
2066
- export const modulesInfo = modules.map(m => ({ id: m.id, ...(m.info || {}) }))
2067
- export default modules
2068
- `;
2069
- }
2070
- function renderAstLegacyManifestOutput(options) {
2071
- const usesPageRouteMetadataHelper = options.typeName === "FrontendRouteManifestEntry" || options.typeName === "BackendRouteManifestEntry";
2072
- const importSection = [
2073
- usesPageRouteMetadataHelper ? `import { resolvePageRouteMetadata, type ${options.typeName} } from '@open-mercato/shared/modules/registry'` : `import type { ${options.typeName} } from '@open-mercato/shared/modules/registry'`,
2074
- ...(options.imports ?? []).map((entry) => serializeGeneratedImport(entry))
2075
- ].join("\n");
2076
- return `// AUTO-GENERATED by mercato generate registry
2077
- ${importSection}
2078
-
2079
- export const ${options.exportName}: ${options.typeName}[] = ${renderLegacyCompatibleArray(options.entries)}
2080
-
2081
- export default ${options.exportName}
2082
- `;
2083
- }
2084
2173
  function buildRuntimeRouteComponent(importPath) {
2085
2174
  return arrowFunction({
2086
2175
  async: true,
@@ -2834,7 +2923,7 @@ async function generateModuleRegistryFromDiscovery(options) {
2834
2923
  cliImportName = importName;
2835
2924
  }
2836
2925
  }
2837
- translations.push(...processTranslations({
2926
+ translations.push(...processTranslationsAst({
2838
2927
  discovered: discovered.translations,
2839
2928
  modId,
2840
2929
  appImportBase,
@@ -2842,10 +2931,10 @@ async function generateModuleRegistryFromDiscovery(options) {
2842
2931
  imports,
2843
2932
  extraImports: runtimeImports
2844
2933
  }));
2845
- subscribers.push(...processSubscribers(await discovered.getSubscribers()));
2934
+ subscribers.push(...processSubscribersAst(await discovered.getSubscribers()));
2846
2935
  const discoveredWorkersForModule = await discovered.getWorkers();
2847
2936
  if (workersDeclareAbandonHook(discoveredWorkersForModule)) hasAbandonHookWorkers = true;
2848
- workers.push(...processWorkers(discoveredWorkersForModule));
2937
+ workers.push(...processWorkersAst(discoveredWorkersForModule));
2849
2938
  {
2850
2939
  const parts = [];
2851
2940
  if (fieldsImportName)
@@ -2863,44 +2952,116 @@ async function generateModuleRegistryFromDiscovery(options) {
2863
2952
  );
2864
2953
  }
2865
2954
  }
2866
- moduleDecls.push(`{
2867
- id: ${toLiteral(modId)},
2868
- ${infoImportName ? `info: ${infoImportName}.metadata,` : ""}
2869
- ${frontendRoutes.length ? `frontendRoutes: [${frontendRoutes.join(", ")}],` : ""}
2870
- ${backendRoutes.length ? `backendRoutes: [${backendRoutes.join(", ")}],` : ""}
2871
- ${apis.length ? `apis: [${apis.join(", ")}],` : ""}
2872
- ${cliImportName ? `cli: ${cliImportName},` : ""}
2873
- ${translations.length ? `translations: { ${translations.join(", ")} },` : ""}
2874
- ${subscribers.length ? `subscribers: [${subscribers.join(", ")}],` : ""}
2875
- ${workers.length ? `workers: [${workers.join(", ")}],` : ""}
2876
- ${extensionsImportName ? `entityExtensions: ((${extensionsImportName}.default ?? ${extensionsImportName}.extensions) as import('@open-mercato/shared/modules/entities').EntityExtension[]) || [],` : ""}
2877
- customFieldSets: ${customFieldSetsExpr},
2878
- ${featuresImportName ? `features: ((${featuresImportName}.default ?? ${featuresImportName}.features) as any) || [],` : ""}
2879
- ${customEntitiesImportName ? `customEntities: ((${customEntitiesImportName}.default ?? ${customEntitiesImportName}.entities) as any) || [],` : ""}
2880
- ${dashboardWidgets.length ? `dashboardWidgets: [${dashboardWidgets.join(", ")}],` : ""}
2881
- ${setupImportName ? `setup: (${setupImportName}.default ?? ${setupImportName}.setup) || undefined,` : ""}
2882
- ${encryptionImportName ? `defaultEncryptionMaps: ((${encryptionImportName}.default ?? ${encryptionImportName}.defaultEncryptionMaps) as import('@open-mercato/shared/modules/encryption').ModuleEncryptionMap[]) || [],` : ""}
2883
- ${integrationExports ? `integrations: ((${integrationExports}.integrations ?? (${integrationExports}.integration ? [${integrationExports}.integration] : [])) as import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition[]),` : ""}
2884
- ${integrationExports ? `bundles: ((${integrationExports}.bundles ?? (${integrationExports}.bundle ? [${integrationExports}.bundle] : [])) as import('@open-mercato/shared/modules/integrations/types').IntegrationBundle[]),` : ""}
2885
- }`);
2886
- runtimeModuleDecls.push(`{
2887
- id: ${toLiteral(modId)},
2888
- ${infoImportName ? `info: ${infoImportName}.metadata,` : ""}
2889
- ${runtimeFrontendRoutes.length ? `frontendRoutes: [${runtimeFrontendRoutes.join(", ")}],` : ""}
2890
- ${runtimeBackendRoutes.length ? `backendRoutes: [${runtimeBackendRoutes.join(", ")}],` : ""}
2891
- ${runtimeApis.length ? `apis: [${runtimeApis.join(", ")}],` : ""}
2892
- ${translations.length ? `translations: { ${translations.join(", ")} },` : ""}
2893
- ${subscribers.length ? `subscribers: [${subscribers.join(", ")}],` : ""}
2894
- ${workers.length ? `workers: [${workers.join(", ")}],` : ""}
2895
- ${extensionsImportName ? `entityExtensions: ((${extensionsImportName}.default ?? ${extensionsImportName}.extensions) as import('@open-mercato/shared/modules/entities').EntityExtension[]) || [],` : ""}
2896
- customFieldSets: ${customFieldSetsExpr},
2897
- ${featuresImportName ? `features: ((${featuresImportName}.default ?? ${featuresImportName}.features) as any) || [],` : ""}
2898
- ${customEntitiesImportName ? `customEntities: ((${customEntitiesImportName}.default ?? ${customEntitiesImportName}.entities) as any) || [],` : ""}
2899
- ${setupImportName ? `setup: (${setupImportName}.default ?? ${setupImportName}.setup) || undefined,` : ""}
2900
- ${encryptionImportName ? `defaultEncryptionMaps: ((${encryptionImportName}.default ?? ${encryptionImportName}.defaultEncryptionMaps) as import('@open-mercato/shared/modules/encryption').ModuleEncryptionMap[]) || [],` : ""}
2901
- ${integrationExports ? `integrations: ((${integrationExports}.integrations ?? (${integrationExports}.integration ? [${integrationExports}.integration] : [])) as import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition[]),` : ""}
2902
- ${integrationExports ? `bundles: ((${integrationExports}.bundles ?? (${integrationExports}.bundle ? [${integrationExports}.bundle] : [])) as import('@open-mercato/shared/modules/integrations/types').IntegrationBundle[]),` : ""}
2903
- }`);
2955
+ const identityEntries = [{ name: "id", value: modId }];
2956
+ if (infoImportName) {
2957
+ identityEntries.push({ name: "info", value: propertyAccess(identifier(infoImportName), "metadata") });
2958
+ }
2959
+ const sharedTailEntries = [];
2960
+ if (translations.length > 0) {
2961
+ sharedTailEntries.push({ name: "translations", value: objectLiteral(translations) });
2962
+ }
2963
+ if (subscribers.length > 0) {
2964
+ sharedTailEntries.push({ name: "subscribers", value: arrayLiteral(subscribers, writeValue) });
2965
+ }
2966
+ if (workers.length > 0) {
2967
+ sharedTailEntries.push({ name: "workers", value: arrayLiteral(workers, writeValue) });
2968
+ }
2969
+ if (extensionsImportName) {
2970
+ sharedTailEntries.push({
2971
+ name: "entityExtensions",
2972
+ value: buildLegacyModuleListValue({
2973
+ importName: extensionsImportName,
2974
+ members: ["default", "extensions"],
2975
+ castType: "import('@open-mercato/shared/modules/entities').EntityExtension[]"
2976
+ })
2977
+ });
2978
+ }
2979
+ sharedTailEntries.push({ name: "customFieldSets", value: identifier(customFieldSetsExpr) });
2980
+ if (featuresImportName) {
2981
+ sharedTailEntries.push({
2982
+ name: "features",
2983
+ value: buildLegacyModuleListValue({
2984
+ importName: featuresImportName,
2985
+ members: ["default", "features"],
2986
+ castType: "any"
2987
+ })
2988
+ });
2989
+ }
2990
+ if (customEntitiesImportName) {
2991
+ sharedTailEntries.push({
2992
+ name: "customEntities",
2993
+ value: buildLegacyModuleListValue({
2994
+ importName: customEntitiesImportName,
2995
+ members: ["default", "entities"],
2996
+ castType: "any"
2997
+ })
2998
+ });
2999
+ }
3000
+ const setupAndBeyondEntries = [];
3001
+ if (setupImportName) {
3002
+ setupAndBeyondEntries.push({ name: "setup", value: buildLegacyModuleSetupValue(setupImportName) });
3003
+ }
3004
+ if (encryptionImportName) {
3005
+ setupAndBeyondEntries.push({
3006
+ name: "defaultEncryptionMaps",
3007
+ value: buildLegacyModuleListValue({
3008
+ importName: encryptionImportName,
3009
+ members: ["default", "defaultEncryptionMaps"],
3010
+ castType: "import('@open-mercato/shared/modules/encryption').ModuleEncryptionMap[]"
3011
+ })
3012
+ });
3013
+ }
3014
+ if (integrationExports) {
3015
+ setupAndBeyondEntries.push({
3016
+ name: "integrations",
3017
+ value: buildLegacyIntegrationListValue(
3018
+ integrationExports,
3019
+ "integrations",
3020
+ "integration",
3021
+ "import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition[]"
3022
+ )
3023
+ });
3024
+ setupAndBeyondEntries.push({
3025
+ name: "bundles",
3026
+ value: buildLegacyIntegrationListValue(
3027
+ integrationExports,
3028
+ "bundles",
3029
+ "bundle",
3030
+ "import('@open-mercato/shared/modules/integrations/types').IntegrationBundle[]"
3031
+ )
3032
+ });
3033
+ }
3034
+ const eagerEntries = [...identityEntries];
3035
+ if (frontendRoutes.length > 0) {
3036
+ eagerEntries.push({ name: "frontendRoutes", value: preRenderedExpressionList(frontendRoutes) });
3037
+ }
3038
+ if (backendRoutes.length > 0) {
3039
+ eagerEntries.push({ name: "backendRoutes", value: preRenderedExpressionList(backendRoutes) });
3040
+ }
3041
+ if (apis.length > 0) {
3042
+ eagerEntries.push({ name: "apis", value: preRenderedExpressionList(apis) });
3043
+ }
3044
+ if (cliImportName) {
3045
+ eagerEntries.push({ name: "cli", value: identifier(cliImportName) });
3046
+ }
3047
+ eagerEntries.push(...sharedTailEntries);
3048
+ if (dashboardWidgets.length > 0) {
3049
+ eagerEntries.push({ name: "dashboardWidgets", value: preRenderedExpressionList(dashboardWidgets) });
3050
+ }
3051
+ eagerEntries.push(...setupAndBeyondEntries);
3052
+ moduleDecls.push(objectLiteral(eagerEntries));
3053
+ const runtimeEntries = [...identityEntries];
3054
+ if (runtimeFrontendRoutes.length > 0) {
3055
+ runtimeEntries.push({ name: "frontendRoutes", value: preRenderedExpressionList(runtimeFrontendRoutes) });
3056
+ }
3057
+ if (runtimeBackendRoutes.length > 0) {
3058
+ runtimeEntries.push({ name: "backendRoutes", value: preRenderedExpressionList(runtimeBackendRoutes) });
3059
+ }
3060
+ if (runtimeApis.length > 0) {
3061
+ runtimeEntries.push({ name: "apis", value: preRenderedExpressionList(runtimeApis) });
3062
+ }
3063
+ runtimeEntries.push(...sharedTailEntries, ...setupAndBeyondEntries);
3064
+ runtimeModuleDecls.push(objectLiteral(runtimeEntries));
2904
3065
  }
2905
3066
  {
2906
3067
  const { detectConflicts } = await import("@open-mercato/shared/lib/umes/conflict-detection");
@@ -2993,35 +3154,37 @@ async function generateModuleRegistryFromDiscovery(options) {
2993
3154
  );
2994
3155
  }
2995
3156
  }
2996
- const output = renderAstLegacyModuleRegistryOutput({
3157
+ const output = renderAstModuleRegistryFile({
2997
3158
  fileName: "modules.generated.ts",
3159
+ generator: "registry",
2998
3160
  imports,
2999
3161
  moduleEntries: moduleDecls,
3000
3162
  includeCreateElementImport: hasRouteComponents,
3001
3163
  includeAbandonHookImport: hasAbandonHookWorkers
3002
3164
  });
3003
- const runtimeOutput = renderAstLegacyModuleRegistryOutput({
3165
+ const runtimeOutput = renderAstModuleRegistryFile({
3004
3166
  fileName: "modules.runtime.generated.ts",
3167
+ generator: "registry",
3005
3168
  imports: runtimeImports,
3006
3169
  moduleEntries: runtimeModuleDecls,
3007
3170
  includeCreateElementImport: true,
3008
3171
  includeAbandonHookImport: hasAbandonHookWorkers
3009
3172
  });
3010
- const frontendRoutesOutput = renderAstLegacyManifestOutput({
3173
+ const frontendRoutesOutput = renderAstManifestFile({
3011
3174
  fileName: "frontend-routes.generated.ts",
3012
3175
  typeName: "FrontendRouteManifestEntry",
3013
3176
  exportName: "frontendRoutes",
3014
3177
  imports: frontendRouteManifestImports,
3015
3178
  entries: frontendRouteManifestDecls
3016
3179
  });
3017
- const backendRoutesOutput = renderAstLegacyManifestOutput({
3180
+ const backendRoutesOutput = renderAstManifestFile({
3018
3181
  fileName: "backend-routes.generated.ts",
3019
3182
  typeName: "BackendRouteManifestEntry",
3020
3183
  exportName: "backendRoutes",
3021
3184
  imports: backendRouteManifestImports,
3022
3185
  entries: backendRouteManifestDecls
3023
3186
  });
3024
- const apiRoutesOutput = renderAstLegacyManifestOutput({
3187
+ const apiRoutesOutput = renderAstManifestFile({
3025
3188
  fileName: "api-routes.generated.ts",
3026
3189
  typeName: "ApiRouteManifestEntry",
3027
3190
  exportName: "apiRoutes",
@@ -3148,16 +3311,11 @@ async function generateModuleRegistryFromDiscovery(options) {
3148
3311
  allRegImports.push(...reg.registrationImports);
3149
3312
  allCalls.push(reg.buildCall(reg.entriesExportName));
3150
3313
  }
3151
- const uniqueImports = [.../* @__PURE__ */ new Set([...allEntryImports, ...allRegImports])];
3152
- const importSection = uniqueImports.join("\n");
3153
- const body = ` ${allCalls.join("\n ")}`;
3154
- const bootstrapRegsOutput = `// AUTO-GENERATED by mercato generate registry
3155
- ${importSection ? `${importSection}
3156
- ` : ""}
3157
- export function runBootstrapRegistrations(): void {
3158
- ${body}
3159
- }
3160
- `;
3314
+ const bootstrapRegsOutput = renderBootstrapRegistrationsFile({
3315
+ entryImports: allEntryImports,
3316
+ registrationImports: allRegImports,
3317
+ calls: allCalls
3318
+ });
3161
3319
  writeGeneratedFile({ outFile: bootstrapRegsOutFile, checksumFile: bootstrapRegsChecksumFile, content: bootstrapRegsOutput, structureChecksum, result, quiet });
3162
3320
  }
3163
3321
  return result;
@@ -3872,6 +4030,8 @@ export {
3872
4030
  generateModuleRegistryCli,
3873
4031
  hasNamedExport,
3874
4032
  namedObjectLiteralDeclaresProperty,
4033
+ renderBootstrapRegistrationsFile,
4034
+ renderCommandLoadersFile,
3875
4035
  resetConventionWarnings,
3876
4036
  resolveNamedObjectExport,
3877
4037
  warnIfPageMetaMissingMetadataExport,