@open-mercato/cli 0.6.7-develop.6568.1.9f57ffc393 → 0.6.7-develop.6572.1.3d8e83062f

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 (70) hide show
  1. package/dist/agentic/guides/module-facts.json +53 -53
  2. package/dist/agentic/guides/modules/ai_assistant.md +1 -1
  3. package/dist/agentic/guides/modules/api_docs.md +1 -1
  4. package/dist/agentic/guides/modules/api_keys.md +1 -1
  5. package/dist/agentic/guides/modules/attachments.md +1 -1
  6. package/dist/agentic/guides/modules/audit_logs.md +1 -1
  7. package/dist/agentic/guides/modules/auth.md +1 -1
  8. package/dist/agentic/guides/modules/business_rules.md +1 -1
  9. package/dist/agentic/guides/modules/catalog.md +1 -1
  10. package/dist/agentic/guides/modules/channel_gmail.md +1 -1
  11. package/dist/agentic/guides/modules/channel_imap.md +1 -1
  12. package/dist/agentic/guides/modules/checkout.md +1 -1
  13. package/dist/agentic/guides/modules/communication_channels.md +1 -1
  14. package/dist/agentic/guides/modules/configs.md +1 -1
  15. package/dist/agentic/guides/modules/content.md +1 -1
  16. package/dist/agentic/guides/modules/currencies.md +1 -1
  17. package/dist/agentic/guides/modules/customer_accounts.md +1 -1
  18. package/dist/agentic/guides/modules/customers.md +1 -1
  19. package/dist/agentic/guides/modules/dashboards.md +1 -1
  20. package/dist/agentic/guides/modules/data_sync.md +1 -1
  21. package/dist/agentic/guides/modules/dictionaries.md +1 -1
  22. package/dist/agentic/guides/modules/directory.md +1 -1
  23. package/dist/agentic/guides/modules/entities.md +1 -1
  24. package/dist/agentic/guides/modules/events.md +1 -1
  25. package/dist/agentic/guides/modules/feature_toggles.md +1 -1
  26. package/dist/agentic/guides/modules/gateway_stripe.md +1 -1
  27. package/dist/agentic/guides/modules/generators.md +1 -1
  28. package/dist/agentic/guides/modules/inbox_ops.md +1 -1
  29. package/dist/agentic/guides/modules/integrations.md +1 -1
  30. package/dist/agentic/guides/modules/messages.md +1 -1
  31. package/dist/agentic/guides/modules/notifications.md +1 -1
  32. package/dist/agentic/guides/modules/onboarding.md +1 -1
  33. package/dist/agentic/guides/modules/payment_gateways.md +1 -1
  34. package/dist/agentic/guides/modules/perspectives.md +1 -1
  35. package/dist/agentic/guides/modules/planner.md +1 -1
  36. package/dist/agentic/guides/modules/portal.md +1 -1
  37. package/dist/agentic/guides/modules/progress.md +1 -1
  38. package/dist/agentic/guides/modules/query_index.md +1 -1
  39. package/dist/agentic/guides/modules/record_locks.md +1 -1
  40. package/dist/agentic/guides/modules/resources.md +1 -1
  41. package/dist/agentic/guides/modules/sales.md +1 -1
  42. package/dist/agentic/guides/modules/scheduler.md +1 -1
  43. package/dist/agentic/guides/modules/search.md +1 -1
  44. package/dist/agentic/guides/modules/security.md +1 -1
  45. package/dist/agentic/guides/modules/shipping_carriers.md +1 -1
  46. package/dist/agentic/guides/modules/sso.md +1 -1
  47. package/dist/agentic/guides/modules/staff.md +1 -1
  48. package/dist/agentic/guides/modules/storage_s3.md +1 -1
  49. package/dist/agentic/guides/modules/sync_akeneo.md +1 -1
  50. package/dist/agentic/guides/modules/sync_excel.md +1 -1
  51. package/dist/agentic/guides/modules/system_status_overlays.md +1 -1
  52. package/dist/agentic/guides/modules/translations.md +1 -1
  53. package/dist/agentic/guides/modules/webhooks.md +1 -1
  54. package/dist/agentic/guides/modules/workflows.md +1 -1
  55. package/dist/lib/generators/index.js +7 -1
  56. package/dist/lib/generators/index.js.map +2 -2
  57. package/dist/lib/generators/module-registry.js +224 -266
  58. package/dist/lib/generators/module-registry.js.map +3 -3
  59. package/dist/lib/module-install.js +2 -6
  60. package/dist/lib/module-install.js.map +2 -2
  61. package/dist/mercato.js +6 -14
  62. package/dist/mercato.js.map +2 -2
  63. package/package.json +5 -5
  64. package/src/__tests__/mercato.test.ts +13 -27
  65. package/src/lib/generators/__tests__/generators.test.ts +5 -0
  66. package/src/lib/generators/__tests__/output-snapshots.test.ts +37 -1
  67. package/src/lib/generators/index.ts +7 -1
  68. package/src/lib/generators/module-registry.ts +291 -293
  69. package/src/lib/module-install.ts +2 -6
  70. package/src/mercato.ts +6 -14
@@ -1096,6 +1096,118 @@ async function loadWorkerMetadata(sourceFile) {
1096
1096
  const sourceModule = await loadModuleExportsFromSource(sourceFile);
1097
1097
  return normalizeWorkerMetadata(sourceModule?.metadata) ?? normalizeWorkerMetadata(extractNamedObjectLiteralExport(sourceFile, "metadata"));
1098
1098
  }
1099
+ async function discoverSubscribers(roots, imps, modId) {
1100
+ const subscribers = [];
1101
+ for (const { relPath } of scanModuleDir(roots, SCAN_CONFIGS.subscribers)) {
1102
+ const resolved = resolveModuleFile(
1103
+ roots,
1104
+ imps,
1105
+ path.posix.join("subscribers", relPath.replace(/\\/g, "/"))
1106
+ );
1107
+ if (!resolved) continue;
1108
+ const segs = relPath.split("/");
1109
+ const file = segs.pop();
1110
+ const name = stripModuleCodeExtension(file);
1111
+ subscribers.push({
1112
+ id: [modId, ...segs, name].filter(Boolean).join(":"),
1113
+ importPath: sanitizeGeneratedModuleSpecifier(resolved.importPath),
1114
+ metadata: await loadSubscriberMetadata(resolved.absolutePath)
1115
+ });
1116
+ }
1117
+ return subscribers;
1118
+ }
1119
+ async function discoverWorkers(roots, imps, modId) {
1120
+ const workers = [];
1121
+ for (const { relPath } of scanModuleDir(roots, SCAN_CONFIGS.workers)) {
1122
+ const resolved = resolveModuleFile(
1123
+ roots,
1124
+ imps,
1125
+ path.posix.join("workers", relPath.replace(/\\/g, "/"))
1126
+ );
1127
+ if (!resolved) continue;
1128
+ const metadata = await loadWorkerMetadata(resolved.absolutePath);
1129
+ if (!metadata?.queue) continue;
1130
+ const segs = relPath.split("/");
1131
+ const file = segs.pop();
1132
+ const name = stripModuleCodeExtension(file);
1133
+ workers.push({
1134
+ id: [modId, "workers", ...segs, name].filter(Boolean).join(":"),
1135
+ importPath: sanitizeGeneratedModuleSpecifier(resolved.importPath),
1136
+ metadata
1137
+ });
1138
+ }
1139
+ return workers;
1140
+ }
1141
+ function discoverTranslations(roots) {
1142
+ const i18nApp = path.join(roots.appBase, "i18n");
1143
+ const pkgI18nBase = resolveStandaloneSourceMirrorBase(roots.pkgBase) ?? roots.pkgBase;
1144
+ const i18nCore = path.join(pkgI18nBase, "i18n");
1145
+ const locales = /* @__PURE__ */ new Set();
1146
+ if (fs.existsSync(i18nCore)) {
1147
+ for (const entry of fs.readdirSync(i18nCore, { withFileTypes: true })) {
1148
+ if (entry.isFile() && entry.name.endsWith(".json")) locales.add(entry.name.replace(/\.json$/, ""));
1149
+ }
1150
+ }
1151
+ if (fs.existsSync(i18nApp)) {
1152
+ for (const entry of fs.readdirSync(i18nApp, { withFileTypes: true })) {
1153
+ if (entry.isFile() && entry.name.endsWith(".json")) locales.add(entry.name.replace(/\.json$/, ""));
1154
+ }
1155
+ }
1156
+ return Array.from(locales, (locale) => ({
1157
+ locale,
1158
+ coreHas: fs.existsSync(path.join(i18nCore, `${locale}.json`)),
1159
+ appHas: fs.existsSync(path.join(i18nApp, `${locale}.json`))
1160
+ }));
1161
+ }
1162
+ async function createModuleRegistryDiscovery(resolver) {
1163
+ const enabled = resolver.loadEnabledModules();
1164
+ const modules = [];
1165
+ const trackedRoots = /* @__PURE__ */ new Set();
1166
+ for (const entry of enabled) {
1167
+ const modId = entry.id;
1168
+ const roots = resolver.getModulePaths(entry);
1169
+ verifyThirdPartyModuleShape(entry, roots.pkgBase);
1170
+ const rawImps = resolver.getModuleImportBase(entry);
1171
+ const appImportBase = entry.from === "@app" ? `../../src/modules/${modId}` : rawImps.appBase;
1172
+ const imps = { appBase: appImportBase, pkgBase: rawImps.pkgBase };
1173
+ trackedRoots.add(roots.appBase);
1174
+ trackedRoots.add(roots.pkgBase);
1175
+ let subscribers;
1176
+ let workers;
1177
+ const resolvedFiles = /* @__PURE__ */ new Map();
1178
+ const resolve = (relativePath) => {
1179
+ if (!resolvedFiles.has(relativePath)) {
1180
+ resolvedFiles.set(relativePath, resolveModuleFile(roots, imps, relativePath));
1181
+ }
1182
+ return resolvedFiles.get(relativePath) ?? null;
1183
+ };
1184
+ modules.push({
1185
+ modId,
1186
+ roots,
1187
+ imps,
1188
+ appImportBase,
1189
+ resolve,
1190
+ frontendFiles: scanModuleDir(roots, SCAN_CONFIGS.frontendPages),
1191
+ backendFiles: scanModuleDir(roots, SCAN_CONFIGS.backendPages),
1192
+ commandLoaderEntries: collectCommandLoaderEntries(roots, imps, modId),
1193
+ getSubscribers: () => subscribers ??= discoverSubscribers(roots, imps, modId),
1194
+ getWorkers: () => workers ??= discoverWorkers(roots, imps, modId),
1195
+ translations: discoverTranslations(roots),
1196
+ dashboardWidgetEntries: scanDashboardWidgetEntries({
1197
+ modId,
1198
+ roots,
1199
+ appImportBase,
1200
+ pkgImportBase: imps.pkgBase
1201
+ })
1202
+ });
1203
+ }
1204
+ let structureChecksum;
1205
+ return {
1206
+ enabled,
1207
+ modules,
1208
+ getStructureChecksum: () => structureChecksum ??= calculateStructureChecksum(Array.from(trackedRoots))
1209
+ };
1210
+ }
1099
1211
  async function loadPageMetadataForManifest(options) {
1100
1212
  const metadataModule = options.metaPath ?? options.sourceFile;
1101
1213
  const sourceModule = await loadModuleExportsFromSource(metadataModule);
@@ -1380,73 +1492,30 @@ async function processApiRoutes(options) {
1380
1492
  manifestApis
1381
1493
  };
1382
1494
  }
1383
- async function processSubscribers(options) {
1384
- const { roots, modId, appImportBase, pkgImportBase } = options;
1385
- const files = scanModuleDir(roots, SCAN_CONFIGS.subscribers);
1495
+ function processSubscribers(discovered) {
1386
1496
  const subscribers = [];
1387
- for (const { relPath } of files) {
1388
- const resolved = resolveModuleFile(
1389
- roots,
1390
- { appBase: appImportBase, pkgBase: pkgImportBase },
1391
- path.posix.join("subscribers", relPath.replace(/\\/g, "/"))
1392
- );
1393
- if (!resolved) continue;
1394
- const segs = relPath.split("/");
1395
- const file = segs.pop();
1396
- const name = stripModuleCodeExtension(file);
1397
- const importPath = sanitizeGeneratedModuleSpecifier(resolved.importPath);
1398
- const sid = [modId, ...segs, name].filter(Boolean).join(":");
1399
- const sourceFile = resolved.absolutePath;
1400
- const metadata = await loadSubscriberMetadata(sourceFile);
1497
+ for (const { id, importPath, metadata } of discovered) {
1498
+ const subscriberId = metadata?.id ?? id;
1401
1499
  subscribers.push(
1402
- `{ id: ${toLiteral(metadata?.id ?? sid)}, 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(metadata?.id ?? sid)}) }`
1500
+ `{ 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)}) }`
1403
1501
  );
1404
1502
  }
1405
1503
  return subscribers;
1406
1504
  }
1407
- async function processWorkers(options) {
1408
- const { roots, modId, appImportBase, pkgImportBase } = options;
1409
- const files = scanModuleDir(roots, SCAN_CONFIGS.workers);
1505
+ function processWorkers(discovered) {
1410
1506
  const workers = [];
1411
- for (const { relPath } of files) {
1412
- const resolved = resolveModuleFile(
1413
- roots,
1414
- { appBase: appImportBase, pkgBase: pkgImportBase },
1415
- path.posix.join("workers", relPath.replace(/\\/g, "/"))
1416
- );
1417
- if (!resolved) continue;
1418
- const segs = relPath.split("/");
1419
- const file = segs.pop();
1420
- const name = stripModuleCodeExtension(file);
1421
- const importPath = sanitizeGeneratedModuleSpecifier(resolved.importPath);
1422
- const sourceFile = resolved.absolutePath;
1423
- const metadata = await loadWorkerMetadata(sourceFile);
1424
- if (!metadata?.queue) continue;
1425
- const wid = [modId, "workers", ...segs, name].filter(Boolean).join(":");
1507
+ for (const { id, importPath, metadata } of discovered) {
1508
+ const workerId = metadata.id ?? id;
1426
1509
  workers.push(
1427
- `{ id: ${toLiteral(metadata.id ?? wid)}, queue: ${toLiteral(metadata.queue)}, concurrency: ${toLiteral(metadata.concurrency ?? 1)}, handler: createLazyModuleWorker(() => ${buildDynamicImportExpression(importPath)}, ${toLiteral(metadata.id ?? wid)}) }`
1510
+ `{ id: ${toLiteral(workerId)}, queue: ${toLiteral(metadata.queue)}, concurrency: ${toLiteral(metadata.concurrency ?? 1)}, handler: createLazyModuleWorker(() => ${buildDynamicImportExpression(importPath)}, ${toLiteral(workerId)}) }`
1428
1511
  );
1429
1512
  }
1430
1513
  return workers;
1431
1514
  }
1432
1515
  function processTranslations(options) {
1433
- const { roots, modId, appImportBase, pkgImportBase, imports, extraImports } = options;
1434
- const i18nApp = path.join(roots.appBase, "i18n");
1435
- const pkgI18nBase = resolveStandaloneSourceMirrorBase(roots.pkgBase) ?? roots.pkgBase;
1436
- const i18nCore = path.join(pkgI18nBase, "i18n");
1437
- const locales = /* @__PURE__ */ new Set();
1438
- if (fs.existsSync(i18nCore)) {
1439
- for (const e of fs.readdirSync(i18nCore, { withFileTypes: true }))
1440
- if (e.isFile() && e.name.endsWith(".json")) locales.add(e.name.replace(/\.json$/, ""));
1441
- }
1442
- if (fs.existsSync(i18nApp)) {
1443
- for (const e of fs.readdirSync(i18nApp, { withFileTypes: true }))
1444
- if (e.isFile() && e.name.endsWith(".json")) locales.add(e.name.replace(/\.json$/, ""));
1445
- }
1516
+ const { discovered, modId, appImportBase, pkgImportBase, imports, extraImports } = options;
1446
1517
  const translations = [];
1447
- for (const locale of locales) {
1448
- const coreHas = fs.existsSync(path.join(i18nCore, `${locale}.json`));
1449
- const appHas = fs.existsSync(path.join(i18nApp, `${locale}.json`));
1518
+ for (const { locale, coreHas, appHas } of discovered) {
1450
1519
  if (coreHas && appHas) {
1451
1520
  const cName = `T_${toVar(modId)}_${toVar(locale)}_C`;
1452
1521
  const aName = `T_${toVar(modId)}_${toVar(locale)}_A`;
@@ -1964,23 +2033,10 @@ async function processPageFilesAst(options) {
1964
2033
  }
1965
2034
  return routes;
1966
2035
  }
1967
- async function processSubscribersAst(options) {
1968
- const { roots, modId, appImportBase, pkgImportBase } = options;
1969
- const files = scanModuleDir(roots, SCAN_CONFIGS.subscribers);
2036
+ function processSubscribersAst(discovered) {
1970
2037
  const subscribers = [];
1971
- for (const { relPath } of files) {
1972
- const resolved = resolveModuleFile(
1973
- roots,
1974
- { appBase: appImportBase, pkgBase: pkgImportBase },
1975
- path.posix.join("subscribers", relPath.replace(/\\/g, "/"))
1976
- );
1977
- if (!resolved) continue;
1978
- const segs = relPath.split("/");
1979
- const file = segs.pop();
1980
- const name = stripModuleCodeExtension(file);
1981
- const sid = [modId, ...segs, name].filter(Boolean).join(":");
1982
- const metadata = await loadSubscriberMetadata(resolved.absolutePath);
1983
- const subscriberId = metadata?.id ?? sid;
2038
+ for (const { id, importPath, metadata } of discovered) {
2039
+ const subscriberId = metadata?.id ?? id;
1984
2040
  subscribers.push(
1985
2041
  objectLiteral([
1986
2042
  { name: "id", value: subscriberId },
@@ -1992,7 +2048,7 @@ async function processSubscribersAst(options) {
1992
2048
  name: "handler",
1993
2049
  value: callExpression(identifier("createLazyModuleSubscriber"), [
1994
2050
  arrowFunction({
1995
- body: importExpression(resolved.importPath)
2051
+ body: importExpression(importPath)
1996
2052
  }),
1997
2053
  subscriberId
1998
2054
  ])
@@ -2002,23 +2058,10 @@ async function processSubscribersAst(options) {
2002
2058
  }
2003
2059
  return subscribers;
2004
2060
  }
2005
- async function processWorkersAst(options) {
2006
- const { roots, modId, appImportBase, pkgImportBase } = options;
2007
- const files = scanModuleDir(roots, SCAN_CONFIGS.workers);
2061
+ function processWorkersAst(discovered) {
2008
2062
  const workers = [];
2009
- for (const { relPath } of files) {
2010
- const resolved = resolveModuleFile(
2011
- roots,
2012
- { appBase: appImportBase, pkgBase: pkgImportBase },
2013
- path.posix.join("workers", relPath.replace(/\\/g, "/"))
2014
- );
2015
- if (!resolved) continue;
2016
- const segs = relPath.split("/");
2017
- const file = segs.pop();
2018
- const name = stripModuleCodeExtension(file);
2019
- const metadata = await loadWorkerMetadata(resolved.absolutePath);
2020
- if (!metadata?.queue) continue;
2021
- const workerId = metadata.id ?? [modId, "workers", ...segs, name].filter(Boolean).join(":");
2063
+ for (const { id, importPath, metadata } of discovered) {
2064
+ const workerId = metadata.id ?? id;
2022
2065
  workers.push(
2023
2066
  objectLiteral([
2024
2067
  { name: "id", value: workerId },
@@ -2028,7 +2071,7 @@ async function processWorkersAst(options) {
2028
2071
  name: "handler",
2029
2072
  value: callExpression(identifier("createLazyModuleWorker"), [
2030
2073
  arrowFunction({
2031
- body: importExpression(resolved.importPath)
2074
+ body: importExpression(importPath)
2032
2075
  }),
2033
2076
  workerId
2034
2077
  ])
@@ -2039,29 +2082,9 @@ async function processWorkersAst(options) {
2039
2082
  return workers;
2040
2083
  }
2041
2084
  function processTranslationsAst(options) {
2042
- const { roots, modId, appImportBase, pkgImportBase, imports, extraImports } = options;
2043
- const i18nApp = path.join(roots.appBase, "i18n");
2044
- const pkgI18nBase = resolveStandaloneSourceMirrorBase(roots.pkgBase) ?? roots.pkgBase;
2045
- const i18nCore = path.join(pkgI18nBase, "i18n");
2046
- const locales = /* @__PURE__ */ new Set();
2047
- if (fs.existsSync(i18nCore)) {
2048
- for (const entry of fs.readdirSync(i18nCore, { withFileTypes: true })) {
2049
- if (entry.isFile() && entry.name.endsWith(".json")) {
2050
- locales.add(entry.name.replace(/\.json$/, ""));
2051
- }
2052
- }
2053
- }
2054
- if (fs.existsSync(i18nApp)) {
2055
- for (const entry of fs.readdirSync(i18nApp, { withFileTypes: true })) {
2056
- if (entry.isFile() && entry.name.endsWith(".json")) {
2057
- locales.add(entry.name.replace(/\.json$/, ""));
2058
- }
2059
- }
2060
- }
2085
+ const { discovered, modId, appImportBase, pkgImportBase, imports, extraImports } = options;
2061
2086
  const translations = [];
2062
- for (const locale of locales) {
2063
- const coreHas = fs.existsSync(path.join(i18nCore, `${locale}.json`));
2064
- const appHas = fs.existsSync(path.join(i18nApp, `${locale}.json`));
2087
+ for (const { locale, coreHas, appHas } of discovered) {
2065
2088
  if (coreHas && appHas) {
2066
2089
  const coreName = `T_${toVar(modId)}_${toVar(locale)}_C`;
2067
2090
  const appName = `T_${toVar(modId)}_${toVar(locale)}_A`;
@@ -2100,8 +2123,7 @@ function processTranslationsAst(options) {
2100
2123
  }
2101
2124
  return translations;
2102
2125
  }
2103
- function resolveConventionFile(roots, imps, relativePath, prefix, modId, importIdRef, imports, extraImports, importStyle = "namespace") {
2104
- const resolved = resolveModuleFile(roots, imps, relativePath);
2126
+ function resolveConventionFile(resolved, prefix, modId, importIdRef, imports, extraImports, importStyle = "namespace") {
2105
2127
  if (!resolved) return null;
2106
2128
  const importName = `${prefix}_${toVar(modId)}_${importIdRef.value++}`;
2107
2129
  const importPath = sanitizeGeneratedModuleSpecifier(resolved.importPath);
@@ -2114,8 +2136,9 @@ function resolveConventionFile(roots, imps, relativePath, prefix, modId, importI
2114
2136
  }
2115
2137
  return { importName, importPath, fromApp: resolved.fromApp };
2116
2138
  }
2117
- async function generateModuleRegistry(options) {
2139
+ async function generateModuleRegistryFromDiscovery(options) {
2118
2140
  const { resolver, quiet = false } = options;
2141
+ const { discovery } = options;
2119
2142
  const result = createGeneratorResult();
2120
2143
  const outputDir = resolver.getOutputDir();
2121
2144
  const outFile = path.join(outputDir, "modules.generated.ts");
@@ -2134,20 +2157,12 @@ async function generateModuleRegistry(options) {
2134
2157
  const legacySubscribersChecksumFile = path.join(outputDir, "subscribers.generated.checksum");
2135
2158
  const commandLoadersOutFile = path.join(outputDir, "command-loaders.generated.ts");
2136
2159
  const commandLoadersChecksumFile = path.join(outputDir, "command-loaders.generated.checksum");
2137
- const enabled = resolver.loadEnabledModules();
2138
- for (const entry of enabled) {
2139
- verifyThirdPartyModuleShape(entry, resolver.getModulePaths(entry).pkgBase);
2140
- }
2160
+ const enabled = discovery.enabled;
2141
2161
  const extensions = loadGeneratorExtensions();
2142
2162
  const pluginRegistry = /* @__PURE__ */ new Map();
2143
2163
  const pluginState = /* @__PURE__ */ new Map();
2144
- for (const entry of enabled) {
2145
- const roots = resolver.getModulePaths(entry);
2146
- const rawImps = resolver.getModuleImportBase(entry);
2147
- const isAppMod = entry.from === "@app";
2148
- const appImportBase = isAppMod ? `../../src/modules/${entry.id}` : rawImps.appBase;
2149
- const imps = { appBase: appImportBase, pkgBase: rawImps.pkgBase };
2150
- const resolved = resolveModuleFile(roots, imps, "generators.ts");
2164
+ for (const discovered of discovery.modules) {
2165
+ const resolved = discovered.resolve("generators.ts");
2151
2166
  if (!resolved) continue;
2152
2167
  try {
2153
2168
  const pluginMod = await import(buildCacheBustedSourceImportUrl(resolved.absolutePath));
@@ -2171,21 +2186,13 @@ async function generateModuleRegistry(options) {
2171
2186
  const backendRouteManifestDecls = [];
2172
2187
  const apiRouteManifestDecls = [];
2173
2188
  const importIdRef = { value: 0 };
2174
- const trackedRoots = /* @__PURE__ */ new Set();
2175
2189
  const requiresByModule = /* @__PURE__ */ new Map();
2176
2190
  const commandLoaderEntries = [];
2177
2191
  let hasRouteComponents = false;
2178
2192
  const umesConflictSources = [];
2179
- for (const entry of enabled) {
2180
- const modId = entry.id;
2181
- const roots = resolver.getModulePaths(entry);
2182
- const rawImps = resolver.getModuleImportBase(entry);
2183
- trackedRoots.add(roots.appBase);
2184
- trackedRoots.add(roots.pkgBase);
2185
- const isAppModule = entry.from === "@app";
2186
- const appImportBase = isAppModule ? `../../src/modules/${modId}` : rawImps.appBase;
2187
- const imps = { appBase: appImportBase, pkgBase: rawImps.pkgBase };
2188
- commandLoaderEntries.push(...collectCommandLoaderEntries(roots, imps, modId));
2193
+ for (const discovered of discovery.modules) {
2194
+ const { modId, roots, imps, appImportBase } = discovered;
2195
+ commandLoaderEntries.push(...discovered.commandLoaderEntries);
2189
2196
  const frontendRoutes = [];
2190
2197
  const backendRoutes = [];
2191
2198
  const apis = [];
@@ -2206,7 +2213,7 @@ async function generateModuleRegistry(options) {
2206
2213
  let setupImportName = null;
2207
2214
  let encryptionImportName = null;
2208
2215
  let integrationImportName = null;
2209
- const indexResolved = resolveModuleFile(roots, imps, "index.ts");
2216
+ const indexResolved = discovered.resolve("index.ts");
2210
2217
  if (indexResolved) {
2211
2218
  infoImportName = `I${importIdRef.value++}_${toVar(modId)}`;
2212
2219
  const importPath = sanitizeGeneratedModuleSpecifier(indexResolved.importPath);
@@ -2222,7 +2229,7 @@ async function generateModuleRegistry(options) {
2222
2229
  {
2223
2230
  const feApp = path.join(roots.appBase, "frontend");
2224
2231
  const fePkg = path.join(roots.pkgBase, "frontend");
2225
- const feFiles = scanModuleDir(roots, SCAN_CONFIGS.frontendPages);
2232
+ const feFiles = discovered.frontendFiles;
2226
2233
  if (feFiles.length) {
2227
2234
  const generatedFrontendRoutes = await processPageFiles({
2228
2235
  files: feFiles,
@@ -2244,11 +2251,11 @@ async function generateModuleRegistry(options) {
2244
2251
  }
2245
2252
  }
2246
2253
  {
2247
- const ext = resolveConventionFile(roots, imps, "data/extensions.ts", "X", modId, importIdRef, imports, runtimeImports);
2254
+ const ext = resolveConventionFile(discovered.resolve("data/extensions.ts"), "X", modId, importIdRef, imports, runtimeImports);
2248
2255
  if (ext) extensionsImportName = ext.importName;
2249
2256
  }
2250
2257
  {
2251
- const aclResolved = resolveModuleFile(roots, imps, "acl.ts");
2258
+ const aclResolved = discovered.resolve("acl.ts");
2252
2259
  if (aclResolved) {
2253
2260
  const importName = `ACL_${toVar(modId)}_${importIdRef.value++}`;
2254
2261
  const importPath = sanitizeGeneratedModuleSpecifier(aclResolved.importPath);
@@ -2258,7 +2265,7 @@ async function generateModuleRegistry(options) {
2258
2265
  }
2259
2266
  }
2260
2267
  {
2261
- const ce = resolveConventionFile(roots, imps, "ce.ts", "CE", modId, importIdRef, imports, runtimeImports);
2268
+ const ce = resolveConventionFile(discovered.resolve("ce.ts"), "CE", modId, importIdRef, imports, runtimeImports);
2262
2269
  if (ce) customEntitiesImportName = ce.importName;
2263
2270
  }
2264
2271
  const extensionContext = {
@@ -2276,9 +2283,9 @@ async function generateModuleRegistry(options) {
2276
2283
  extension.scanModule(extensionContext);
2277
2284
  }
2278
2285
  {
2279
- const compOverridesFile = resolveModuleFile(roots, imps, "widgets/components.ts");
2280
- const interceptorsFile = resolveModuleFile(roots, imps, "api/interceptors.ts");
2281
- const aclFile = resolveModuleFile(roots, imps, "acl.ts");
2286
+ const compOverridesFile = discovered.resolve("widgets/components.ts");
2287
+ const interceptorsFile = discovered.resolve("api/interceptors.ts");
2288
+ const aclFile = discovered.resolve("acl.ts");
2282
2289
  umesConflictSources.push({
2283
2290
  moduleId: modId,
2284
2291
  componentOverridesPath: compOverridesFile?.absolutePath,
@@ -2300,15 +2307,15 @@ async function generateModuleRegistry(options) {
2300
2307
  });
2301
2308
  }
2302
2309
  {
2303
- const setup = resolveConventionFile(roots, imps, "setup.ts", "SETUP", modId, importIdRef, imports, runtimeImports);
2310
+ const setup = resolveConventionFile(discovered.resolve("setup.ts"), "SETUP", modId, importIdRef, imports, runtimeImports);
2304
2311
  if (setup) setupImportName = setup.importName;
2305
2312
  }
2306
2313
  {
2307
- const encryption = resolveConventionFile(roots, imps, "encryption.ts", "ENCRYPTION", modId, importIdRef, imports, runtimeImports);
2314
+ const encryption = resolveConventionFile(discovered.resolve("encryption.ts"), "ENCRYPTION", modId, importIdRef, imports, runtimeImports);
2308
2315
  if (encryption) encryptionImportName = encryption.importName;
2309
2316
  }
2310
2317
  {
2311
- const resolved = resolveModuleFile(roots, imps, "integration.ts");
2318
+ const resolved = discovered.resolve("integration.ts");
2312
2319
  if (resolved) {
2313
2320
  const importName = `INTEGRATION_${toVar(modId)}_${importIdRef.value++}`;
2314
2321
  imports.push(buildImportStatement(`* as ${importName}`, resolved.importPath));
@@ -2317,13 +2324,13 @@ async function generateModuleRegistry(options) {
2317
2324
  }
2318
2325
  }
2319
2326
  {
2320
- const fields = resolveConventionFile(roots, imps, "data/fields.ts", "F", modId, importIdRef, imports, runtimeImports);
2327
+ const fields = resolveConventionFile(discovered.resolve("data/fields.ts"), "F", modId, importIdRef, imports, runtimeImports);
2321
2328
  if (fields) fieldsImportName = fields.importName;
2322
2329
  }
2323
2330
  {
2324
2331
  const beApp = path.join(roots.appBase, "backend");
2325
2332
  const bePkg = path.join(roots.pkgBase, "backend");
2326
- const beFiles = scanModuleDir(roots, SCAN_CONFIGS.backendPages);
2333
+ const beFiles = discovered.backendFiles;
2327
2334
  if (beFiles.length) {
2328
2335
  const generatedBackendRoutes = await processPageFiles({
2329
2336
  files: beFiles,
@@ -2358,7 +2365,7 @@ async function generateModuleRegistry(options) {
2358
2365
  apiRouteManifestDecls.push(...generatedApis.manifestApis);
2359
2366
  }
2360
2367
  {
2361
- const cliResolved = resolveModuleFile(roots, imps, "cli.ts");
2368
+ const cliResolved = discovered.resolve("cli.ts");
2362
2369
  if (cliResolved) {
2363
2370
  const importName = `CLI_${toVar(modId)}`;
2364
2371
  imports.push(buildImportStatement(importName, sanitizeGeneratedModuleSpecifier(cliResolved.importPath)));
@@ -2366,25 +2373,15 @@ async function generateModuleRegistry(options) {
2366
2373
  }
2367
2374
  }
2368
2375
  translations.push(...processTranslations({
2369
- roots,
2376
+ discovered: discovered.translations,
2370
2377
  modId,
2371
2378
  appImportBase,
2372
2379
  pkgImportBase: imps.pkgBase,
2373
2380
  imports,
2374
2381
  extraImports: runtimeImports
2375
2382
  }));
2376
- subscribers.push(...await processSubscribers({
2377
- roots,
2378
- modId,
2379
- appImportBase,
2380
- pkgImportBase: imps.pkgBase
2381
- }));
2382
- workers.push(...await processWorkers({
2383
- roots,
2384
- modId,
2385
- appImportBase,
2386
- pkgImportBase: imps.pkgBase
2387
- }));
2383
+ subscribers.push(...processSubscribers(await discovered.getSubscribers()));
2384
+ workers.push(...processWorkers(await discovered.getWorkers()));
2388
2385
  {
2389
2386
  const parts = [];
2390
2387
  if (fieldsImportName)
@@ -2396,15 +2393,9 @@ async function generateModuleRegistry(options) {
2396
2393
  customFieldSetsExpr = parts.length ? `[...${parts.join(", ...")}]` : "[]";
2397
2394
  }
2398
2395
  {
2399
- const entries = scanDashboardWidgetEntries({
2400
- modId,
2401
- roots,
2402
- appImportBase,
2403
- pkgImportBase: imps.pkgBase
2404
- });
2405
- for (const entry2 of entries) {
2396
+ for (const entry of discovered.dashboardWidgetEntries) {
2406
2397
  dashboardWidgets.push(
2407
- `{ moduleId: ${toLiteral(entry2.moduleId)}, key: ${toLiteral(entry2.key)}, source: ${toLiteral(entry2.source)}, loader: () => ${buildDynamicImportExpression(entry2.importPath)}.then((mod) => mod.default ?? mod) }`
2398
+ `{ moduleId: ${toLiteral(entry.moduleId)}, key: ${toLiteral(entry.key)}, source: ${toLiteral(entry.source)}, loader: () => ${buildDynamicImportExpression(entry.importPath)}.then((mod) => mod.default ?? mod) }`
2408
2399
  );
2409
2400
  }
2410
2401
  }
@@ -2606,9 +2597,7 @@ async function generateModuleRegistry(options) {
2606
2597
  process.exit(1);
2607
2598
  }
2608
2599
  }
2609
- const structureChecksum = calculateStructureChecksum([
2610
- ...Array.from(trackedRoots)
2611
- ]);
2600
+ const structureChecksum = discovery.getStructureChecksum();
2612
2601
  writeGeneratedFile({ outFile, checksumFile, content: output, structureChecksum, result, quiet });
2613
2602
  writeGeneratedFile({ outFile: runtimeOutFile, checksumFile: runtimeChecksumFile, content: runtimeOutput, structureChecksum, result, quiet });
2614
2603
  writeGeneratedFile({ outFile: frontendRoutesOutFile, checksumFile: frontendRoutesChecksumFile, content: frontendRoutesOutput, structureChecksum, result, quiet });
@@ -2673,8 +2662,9 @@ ${body}
2673
2662
  }
2674
2663
  return result;
2675
2664
  }
2676
- async function generateModuleRegistryApp(options) {
2665
+ async function generateModuleRegistryAppFromDiscovery(options) {
2677
2666
  const { resolver, quiet = false } = options;
2667
+ const { discovery } = options;
2678
2668
  const result = createGeneratorResult();
2679
2669
  const outputDir = resolver.getOutputDir();
2680
2670
  const outFile = path.join(outputDir, "modules.app.generated.ts");
@@ -2689,10 +2679,7 @@ async function generateModuleRegistryApp(options) {
2689
2679
  const enabledIdsChecksumFile = path.join(outputDir, "enabled-module-ids.generated.checksum");
2690
2680
  const commandLoadersOutFile = path.join(outputDir, "command-loaders.generated.ts");
2691
2681
  const commandLoadersChecksumFile = path.join(outputDir, "command-loaders.generated.checksum");
2692
- const enabled = resolver.loadEnabledModules();
2693
- for (const entry of enabled) {
2694
- verifyThirdPartyModuleShape(entry, resolver.getModulePaths(entry).pkgBase);
2695
- }
2682
+ const enabled = discovery.enabled;
2696
2683
  const imports = [];
2697
2684
  const bootstrapImports = [];
2698
2685
  const i18nImports = [];
@@ -2700,20 +2687,12 @@ async function generateModuleRegistryApp(options) {
2700
2687
  const bootstrapModuleDecls = [];
2701
2688
  const i18nModuleDecls = [];
2702
2689
  const importIdRef = { value: 0 };
2703
- const trackedRoots = /* @__PURE__ */ new Set();
2704
2690
  const requiresByModule = /* @__PURE__ */ new Map();
2705
2691
  const commandLoaderEntries = [];
2706
2692
  let hasRouteComponents = false;
2707
- for (const entry of enabled) {
2708
- const modId = entry.id;
2709
- const roots = resolver.getModulePaths(entry);
2710
- const rawImps = resolver.getModuleImportBase(entry);
2711
- trackedRoots.add(roots.appBase);
2712
- trackedRoots.add(roots.pkgBase);
2713
- const isAppModule = entry.from === "@app";
2714
- const appImportBase = isAppModule ? `../../src/modules/${modId}` : rawImps.appBase;
2715
- const imps = { appBase: appImportBase, pkgBase: rawImps.pkgBase };
2716
- commandLoaderEntries.push(...collectCommandLoaderEntries(roots, imps, modId));
2693
+ for (const discovered of discovery.modules) {
2694
+ const { modId, roots, imps, appImportBase } = discovered;
2695
+ commandLoaderEntries.push(...discovered.commandLoaderEntries);
2717
2696
  const frontendRoutes = [];
2718
2697
  const backendRoutes = [];
2719
2698
  const translations = [];
@@ -2728,7 +2707,7 @@ async function generateModuleRegistryApp(options) {
2728
2707
  let setupImportName = null;
2729
2708
  let encryptionImportName = null;
2730
2709
  let integrationImportName = null;
2731
- const indexResolved = resolveModuleFile(roots, imps, "index.ts");
2710
+ const indexResolved = discovered.resolve("index.ts");
2732
2711
  if (indexResolved) {
2733
2712
  infoImportName = `I${importIdRef.value++}_${toVar(modId)}`;
2734
2713
  const importPath = sanitizeGeneratedModuleSpecifier(indexResolved.importPath);
@@ -2742,17 +2721,17 @@ async function generateModuleRegistryApp(options) {
2742
2721
  }
2743
2722
  }
2744
2723
  {
2745
- const setup = resolveConventionFile(roots, imps, "setup.ts", "SETUP", modId, importIdRef, imports);
2724
+ const setup = resolveConventionFile(discovered.resolve("setup.ts"), "SETUP", modId, importIdRef, imports);
2746
2725
  if (setup) bootstrapImports.push(buildImportStatement(`* as ${setup.importName}`, setup.importPath));
2747
2726
  if (setup) setupImportName = setup.importName;
2748
2727
  }
2749
2728
  {
2750
- const encryption = resolveConventionFile(roots, imps, "encryption.ts", "ENCRYPTION", modId, importIdRef, imports);
2729
+ const encryption = resolveConventionFile(discovered.resolve("encryption.ts"), "ENCRYPTION", modId, importIdRef, imports);
2751
2730
  if (encryption) bootstrapImports.push(buildImportStatement(`* as ${encryption.importName}`, encryption.importPath));
2752
2731
  if (encryption) encryptionImportName = encryption.importName;
2753
2732
  }
2754
2733
  {
2755
- const resolved = resolveModuleFile(roots, imps, "integration.ts");
2734
+ const resolved = discovered.resolve("integration.ts");
2756
2735
  if (resolved) {
2757
2736
  const importName = `INTEGRATION_${toVar(modId)}_${importIdRef.value++}`;
2758
2737
  imports.push(buildImportStatement(`* as ${importName}`, resolved.importPath));
@@ -2761,11 +2740,11 @@ async function generateModuleRegistryApp(options) {
2761
2740
  }
2762
2741
  }
2763
2742
  {
2764
- const ext = resolveConventionFile(roots, imps, "data/extensions.ts", "X", modId, importIdRef, imports, bootstrapImports);
2743
+ const ext = resolveConventionFile(discovered.resolve("data/extensions.ts"), "X", modId, importIdRef, imports, bootstrapImports);
2765
2744
  if (ext) extensionsImportName = ext.importName;
2766
2745
  }
2767
2746
  {
2768
- const aclResolved = resolveModuleFile(roots, imps, "acl.ts");
2747
+ const aclResolved = discovered.resolve("acl.ts");
2769
2748
  if (aclResolved) {
2770
2749
  const importName = `ACL_${toVar(modId)}_${importIdRef.value++}`;
2771
2750
  const importPath = sanitizeGeneratedModuleSpecifier(aclResolved.importPath);
@@ -2775,17 +2754,17 @@ async function generateModuleRegistryApp(options) {
2775
2754
  }
2776
2755
  }
2777
2756
  {
2778
- const ce = resolveConventionFile(roots, imps, "ce.ts", "CE", modId, importIdRef, imports, bootstrapImports);
2757
+ const ce = resolveConventionFile(discovered.resolve("ce.ts"), "CE", modId, importIdRef, imports, bootstrapImports);
2779
2758
  if (ce) customEntitiesImportName = ce.importName;
2780
2759
  }
2781
2760
  {
2782
- const fields = resolveConventionFile(roots, imps, "data/fields.ts", "F", modId, importIdRef, imports, bootstrapImports);
2761
+ const fields = resolveConventionFile(discovered.resolve("data/fields.ts"), "F", modId, importIdRef, imports, bootstrapImports);
2783
2762
  if (fields) fieldsImportName = fields.importName;
2784
2763
  }
2785
2764
  {
2786
2765
  const feApp = path.join(roots.appBase, "frontend");
2787
2766
  const fePkg = path.join(roots.pkgBase, "frontend");
2788
- const feFiles = scanModuleDir(roots, SCAN_CONFIGS.frontendPages);
2767
+ const feFiles = discovered.frontendFiles;
2789
2768
  if (feFiles.length > 0) {
2790
2769
  frontendRoutes.push(...await processPageFilesAst({
2791
2770
  files: feFiles,
@@ -2804,7 +2783,7 @@ async function generateModuleRegistryApp(options) {
2804
2783
  {
2805
2784
  const beApp = path.join(roots.appBase, "backend");
2806
2785
  const bePkg = path.join(roots.pkgBase, "backend");
2807
- const beFiles = scanModuleDir(roots, SCAN_CONFIGS.backendPages);
2786
+ const beFiles = discovered.backendFiles;
2808
2787
  if (beFiles.length > 0) {
2809
2788
  backendRoutes.push(...await processPageFilesAst({
2810
2789
  files: beFiles,
@@ -2822,7 +2801,7 @@ async function generateModuleRegistryApp(options) {
2822
2801
  }
2823
2802
  const translationImports = [];
2824
2803
  translations.push(...processTranslationsAst({
2825
- roots,
2804
+ discovered: discovered.translations,
2826
2805
  modId,
2827
2806
  appImportBase,
2828
2807
  pkgImportBase: imps.pkgBase,
@@ -2831,26 +2810,10 @@ async function generateModuleRegistryApp(options) {
2831
2810
  }));
2832
2811
  bootstrapImports.push(...translationImports);
2833
2812
  i18nImports.push(...translationImports);
2834
- subscribers.push(...await processSubscribersAst({
2835
- roots,
2836
- modId,
2837
- appImportBase,
2838
- pkgImportBase: imps.pkgBase
2839
- }));
2840
- workers.push(...await processWorkersAst({
2841
- roots,
2842
- modId,
2843
- appImportBase,
2844
- pkgImportBase: imps.pkgBase
2845
- }));
2813
+ subscribers.push(...processSubscribersAst(await discovered.getSubscribers()));
2814
+ workers.push(...processWorkersAst(await discovered.getWorkers()));
2846
2815
  {
2847
- const entries = scanDashboardWidgetEntries({
2848
- modId,
2849
- roots,
2850
- appImportBase,
2851
- pkgImportBase: imps.pkgBase
2852
- });
2853
- dashboardWidgetsValue = buildModuleDashboardWidgetsValue(entries);
2816
+ dashboardWidgetsValue = buildModuleDashboardWidgetsValue(discovered.dashboardWidgetEntries);
2854
2817
  }
2855
2818
  const moduleEntries = [
2856
2819
  { name: "id", value: modId },
@@ -3003,7 +2966,7 @@ async function generateModuleRegistryApp(options) {
3003
2966
  process.exit(1);
3004
2967
  }
3005
2968
  }
3006
- const structureChecksum = calculateStructureChecksum(Array.from(trackedRoots));
2969
+ const structureChecksum = discovery.getStructureChecksum();
3007
2970
  writeGeneratedFile({ outFile, checksumFile, content: output, structureChecksum, result, quiet });
3008
2971
  writeGeneratedFile({ outFile: bootstrapOutFile, checksumFile: bootstrapChecksumFile, content: bootstrapOutput, structureChecksum, result, quiet });
3009
2972
  writeGeneratedFile({ outFile: i18nOutFile, checksumFile: i18nChecksumFile, content: i18nOutput, structureChecksum, result, quiet });
@@ -3014,8 +2977,9 @@ async function generateModuleRegistryApp(options) {
3014
2977
  writeGeneratedFile({ outFile: commandLoadersOutFile, checksumFile: commandLoadersChecksumFile, content: commandLoadersOutput, structureChecksum, result, quiet });
3015
2978
  return result;
3016
2979
  }
3017
- async function generateModuleRegistryCli(options) {
2980
+ async function generateModuleRegistryCliFromDiscovery(options) {
3018
2981
  const { resolver, quiet = false } = options;
2982
+ const { discovery } = options;
3019
2983
  const result = createGeneratorResult();
3020
2984
  const outputDir = resolver.getOutputDir();
3021
2985
  const outFile = path.join(outputDir, "modules.cli.generated.ts");
@@ -3024,26 +2988,15 @@ async function generateModuleRegistryCli(options) {
3024
2988
  const legacyChecksumFile = path.join(outputDir, "cli-modules.generated.checksum");
3025
2989
  const commandLoadersOutFile = path.join(outputDir, "command-loaders.generated.ts");
3026
2990
  const commandLoadersChecksumFile = path.join(outputDir, "command-loaders.generated.checksum");
3027
- const enabled = resolver.loadEnabledModules();
3028
- for (const entry of enabled) {
3029
- verifyThirdPartyModuleShape(entry, resolver.getModulePaths(entry).pkgBase);
3030
- }
2991
+ const enabled = discovery.enabled;
3031
2992
  const imports = [];
3032
2993
  const moduleDecls = [];
3033
2994
  const importIdRef = { value: 0 };
3034
- const trackedRoots = /* @__PURE__ */ new Set();
3035
2995
  const requiresByModule = /* @__PURE__ */ new Map();
3036
2996
  const commandLoaderEntries = [];
3037
- for (const entry of enabled) {
3038
- const modId = entry.id;
3039
- const roots = resolver.getModulePaths(entry);
3040
- const rawImps = resolver.getModuleImportBase(entry);
3041
- trackedRoots.add(roots.appBase);
3042
- trackedRoots.add(roots.pkgBase);
3043
- const isAppModule = entry.from === "@app";
3044
- const appImportBase = isAppModule ? `../../src/modules/${modId}` : rawImps.appBase;
3045
- const imps = { appBase: appImportBase, pkgBase: rawImps.pkgBase };
3046
- commandLoaderEntries.push(...collectCommandLoaderEntries(roots, imps, modId));
2997
+ for (const discovered of discovery.modules) {
2998
+ const { modId, roots, imps, appImportBase } = discovered;
2999
+ commandLoaderEntries.push(...discovered.commandLoaderEntries);
3047
3000
  let cliImportName = null;
3048
3001
  const translations = [];
3049
3002
  const subscribers = [];
@@ -3058,7 +3011,7 @@ async function generateModuleRegistryCli(options) {
3058
3011
  let setupImportName = null;
3059
3012
  let encryptionImportName = null;
3060
3013
  let integrationImportName = null;
3061
- const indexResolved = resolveModuleFile(roots, imps, "index.ts");
3014
+ const indexResolved = discovered.resolve("index.ts");
3062
3015
  if (indexResolved) {
3063
3016
  infoImportName = `I${importIdRef.value++}_${toVar(modId)}`;
3064
3017
  const importPath = sanitizeGeneratedModuleSpecifier(indexResolved.importPath);
@@ -3071,15 +3024,15 @@ async function generateModuleRegistryCli(options) {
3071
3024
  }
3072
3025
  }
3073
3026
  {
3074
- const setup = resolveConventionFile(roots, imps, "setup.ts", "SETUP", modId, importIdRef, imports);
3027
+ const setup = resolveConventionFile(discovered.resolve("setup.ts"), "SETUP", modId, importIdRef, imports);
3075
3028
  if (setup) setupImportName = setup.importName;
3076
3029
  }
3077
3030
  {
3078
- const encryption = resolveConventionFile(roots, imps, "encryption.ts", "ENCRYPTION", modId, importIdRef, imports);
3031
+ const encryption = resolveConventionFile(discovered.resolve("encryption.ts"), "ENCRYPTION", modId, importIdRef, imports);
3079
3032
  if (encryption) encryptionImportName = encryption.importName;
3080
3033
  }
3081
3034
  {
3082
- const resolved = resolveModuleFile(roots, imps, "integration.ts");
3035
+ const resolved = discovered.resolve("integration.ts");
3083
3036
  if (resolved) {
3084
3037
  const importName = `INTEGRATION_${toVar(modId)}_${importIdRef.value++}`;
3085
3038
  imports.push(buildImportStatement(`* as ${importName}`, resolved.importPath));
@@ -3087,11 +3040,11 @@ async function generateModuleRegistryCli(options) {
3087
3040
  }
3088
3041
  }
3089
3042
  {
3090
- const ext = resolveConventionFile(roots, imps, "data/extensions.ts", "X", modId, importIdRef, imports);
3043
+ const ext = resolveConventionFile(discovered.resolve("data/extensions.ts"), "X", modId, importIdRef, imports);
3091
3044
  if (ext) extensionsImportName = ext.importName;
3092
3045
  }
3093
3046
  {
3094
- const aclResolved = resolveModuleFile(roots, imps, "acl.ts");
3047
+ const aclResolved = discovered.resolve("acl.ts");
3095
3048
  if (aclResolved) {
3096
3049
  const importName = `ACL_${toVar(modId)}_${importIdRef.value++}`;
3097
3050
  const importPath = sanitizeGeneratedModuleSpecifier(aclResolved.importPath);
@@ -3100,19 +3053,19 @@ async function generateModuleRegistryCli(options) {
3100
3053
  }
3101
3054
  }
3102
3055
  {
3103
- const ce = resolveConventionFile(roots, imps, "ce.ts", "CE", modId, importIdRef, imports);
3056
+ const ce = resolveConventionFile(discovered.resolve("ce.ts"), "CE", modId, importIdRef, imports);
3104
3057
  if (ce) customEntitiesImportName = ce.importName;
3105
3058
  }
3106
3059
  {
3107
- const vec = resolveConventionFile(roots, imps, "vector.ts", "VECTOR", modId, importIdRef, imports);
3060
+ const vec = resolveConventionFile(discovered.resolve("vector.ts"), "VECTOR", modId, importIdRef, imports);
3108
3061
  if (vec) vectorImportName = vec.importName;
3109
3062
  }
3110
3063
  {
3111
- const fields = resolveConventionFile(roots, imps, "data/fields.ts", "F", modId, importIdRef, imports);
3064
+ const fields = resolveConventionFile(discovered.resolve("data/fields.ts"), "F", modId, importIdRef, imports);
3112
3065
  if (fields) fieldsImportName = fields.importName;
3113
3066
  }
3114
3067
  {
3115
- const cliResolved = resolveModuleFile(roots, imps, "cli.ts");
3068
+ const cliResolved = discovered.resolve("cli.ts");
3116
3069
  if (cliResolved) {
3117
3070
  const importName = `CLI_${toVar(modId)}`;
3118
3071
  imports.push(buildImportStatement(importName, sanitizeGeneratedModuleSpecifier(cliResolved.importPath)));
@@ -3120,32 +3073,16 @@ async function generateModuleRegistryCli(options) {
3120
3073
  }
3121
3074
  }
3122
3075
  translations.push(...processTranslationsAst({
3123
- roots,
3076
+ discovered: discovered.translations,
3124
3077
  modId,
3125
3078
  appImportBase,
3126
3079
  pkgImportBase: imps.pkgBase,
3127
3080
  imports
3128
3081
  }));
3129
- subscribers.push(...await processSubscribersAst({
3130
- roots,
3131
- modId,
3132
- appImportBase,
3133
- pkgImportBase: imps.pkgBase
3134
- }));
3135
- workers.push(...await processWorkersAst({
3136
- roots,
3137
- modId,
3138
- appImportBase,
3139
- pkgImportBase: imps.pkgBase
3140
- }));
3082
+ subscribers.push(...processSubscribersAst(await discovered.getSubscribers()));
3083
+ workers.push(...processWorkersAst(await discovered.getWorkers()));
3141
3084
  {
3142
- const entries = scanDashboardWidgetEntries({
3143
- modId,
3144
- roots,
3145
- appImportBase,
3146
- pkgImportBase: imps.pkgBase
3147
- });
3148
- dashboardWidgetsValue = buildModuleDashboardWidgetsValue(entries);
3085
+ dashboardWidgetsValue = buildModuleDashboardWidgetsValue(discovered.dashboardWidgetEntries);
3149
3086
  }
3150
3087
  const moduleEntries = [
3151
3088
  { name: "id", value: modId },
@@ -3294,15 +3231,36 @@ async function generateModuleRegistryCli(options) {
3294
3231
  process.exit(1);
3295
3232
  }
3296
3233
  }
3297
- const structureChecksum = calculateStructureChecksum(Array.from(trackedRoots));
3234
+ const structureChecksum = discovery.getStructureChecksum();
3298
3235
  writeGeneratedFile({ outFile, checksumFile, content: output, structureChecksum, result, quiet });
3299
3236
  writeGeneratedFile({ outFile: legacyOutFile, checksumFile: legacyChecksumFile, content: legacyOutput, structureChecksum, result, quiet });
3300
3237
  const commandLoadersOutput = renderCommandLoadersFile(commandLoaderEntries);
3301
3238
  writeGeneratedFile({ outFile: commandLoadersOutFile, checksumFile: commandLoadersChecksumFile, content: commandLoadersOutput, structureChecksum, result, quiet });
3302
3239
  return result;
3303
3240
  }
3241
+ async function generateModuleRegistry(options) {
3242
+ const discovery = await createModuleRegistryDiscovery(options.resolver);
3243
+ return generateModuleRegistryFromDiscovery({ ...options, discovery });
3244
+ }
3245
+ async function generateModuleRegistryApp(options) {
3246
+ const discovery = await createModuleRegistryDiscovery(options.resolver);
3247
+ return generateModuleRegistryAppFromDiscovery({ ...options, discovery });
3248
+ }
3249
+ async function generateModuleRegistryCli(options) {
3250
+ const discovery = await createModuleRegistryDiscovery(options.resolver);
3251
+ return generateModuleRegistryCliFromDiscovery({ ...options, discovery });
3252
+ }
3253
+ async function generateModuleRegistries(options) {
3254
+ const discovery = await createModuleRegistryDiscovery(options.resolver);
3255
+ return [
3256
+ await generateModuleRegistryFromDiscovery({ ...options, discovery }),
3257
+ await generateModuleRegistryAppFromDiscovery({ ...options, discovery }),
3258
+ await generateModuleRegistryCliFromDiscovery({ ...options, discovery })
3259
+ ];
3260
+ }
3304
3261
  export {
3305
3262
  extractNamedObjectLiteralExport,
3263
+ generateModuleRegistries,
3306
3264
  generateModuleRegistry,
3307
3265
  generateModuleRegistryApp,
3308
3266
  generateModuleRegistryCli,