@open-mercato/cli 0.6.7-develop.6569.1.c06dee4866 → 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.
- package/.turbo/turbo-build.log +2 -2
- package/dist/agentic/guides/module-facts.json +53 -53
- package/dist/agentic/guides/modules/ai_assistant.md +1 -1
- package/dist/agentic/guides/modules/api_docs.md +1 -1
- package/dist/agentic/guides/modules/api_keys.md +1 -1
- package/dist/agentic/guides/modules/attachments.md +1 -1
- package/dist/agentic/guides/modules/audit_logs.md +1 -1
- package/dist/agentic/guides/modules/auth.md +1 -1
- package/dist/agentic/guides/modules/business_rules.md +1 -1
- package/dist/agentic/guides/modules/catalog.md +1 -1
- package/dist/agentic/guides/modules/channel_gmail.md +1 -1
- package/dist/agentic/guides/modules/channel_imap.md +1 -1
- package/dist/agentic/guides/modules/checkout.md +1 -1
- package/dist/agentic/guides/modules/communication_channels.md +1 -1
- package/dist/agentic/guides/modules/configs.md +1 -1
- package/dist/agentic/guides/modules/content.md +1 -1
- package/dist/agentic/guides/modules/currencies.md +1 -1
- package/dist/agentic/guides/modules/customer_accounts.md +1 -1
- package/dist/agentic/guides/modules/customers.md +1 -1
- package/dist/agentic/guides/modules/dashboards.md +1 -1
- package/dist/agentic/guides/modules/data_sync.md +1 -1
- package/dist/agentic/guides/modules/dictionaries.md +1 -1
- package/dist/agentic/guides/modules/directory.md +1 -1
- package/dist/agentic/guides/modules/entities.md +1 -1
- package/dist/agentic/guides/modules/events.md +1 -1
- package/dist/agentic/guides/modules/feature_toggles.md +1 -1
- package/dist/agentic/guides/modules/gateway_stripe.md +1 -1
- package/dist/agentic/guides/modules/generators.md +1 -1
- package/dist/agentic/guides/modules/inbox_ops.md +1 -1
- package/dist/agentic/guides/modules/integrations.md +1 -1
- package/dist/agentic/guides/modules/messages.md +1 -1
- package/dist/agentic/guides/modules/notifications.md +1 -1
- package/dist/agentic/guides/modules/onboarding.md +1 -1
- package/dist/agentic/guides/modules/payment_gateways.md +1 -1
- package/dist/agentic/guides/modules/perspectives.md +1 -1
- package/dist/agentic/guides/modules/planner.md +1 -1
- package/dist/agentic/guides/modules/portal.md +1 -1
- package/dist/agentic/guides/modules/progress.md +1 -1
- package/dist/agentic/guides/modules/query_index.md +1 -1
- package/dist/agentic/guides/modules/record_locks.md +1 -1
- package/dist/agentic/guides/modules/resources.md +1 -1
- package/dist/agentic/guides/modules/sales.md +1 -1
- package/dist/agentic/guides/modules/scheduler.md +1 -1
- package/dist/agentic/guides/modules/search.md +1 -1
- package/dist/agentic/guides/modules/security.md +1 -1
- package/dist/agentic/guides/modules/shipping_carriers.md +1 -1
- package/dist/agentic/guides/modules/sso.md +1 -1
- package/dist/agentic/guides/modules/staff.md +1 -1
- package/dist/agentic/guides/modules/storage_s3.md +1 -1
- package/dist/agentic/guides/modules/sync_akeneo.md +1 -1
- package/dist/agentic/guides/modules/sync_excel.md +1 -1
- package/dist/agentic/guides/modules/system_status_overlays.md +1 -1
- package/dist/agentic/guides/modules/translations.md +1 -1
- package/dist/agentic/guides/modules/webhooks.md +1 -1
- package/dist/agentic/guides/modules/workflows.md +1 -1
- package/dist/lib/generators/index.js +7 -1
- package/dist/lib/generators/index.js.map +2 -2
- package/dist/lib/generators/module-registry.js +224 -266
- package/dist/lib/generators/module-registry.js.map +3 -3
- package/dist/lib/module-install.js +2 -6
- package/dist/lib/module-install.js.map +2 -2
- package/dist/mercato.js +6 -14
- package/dist/mercato.js.map +2 -2
- package/package.json +5 -5
- package/src/__tests__/mercato.test.ts +13 -27
- package/src/lib/generators/__tests__/generators.test.ts +5 -0
- package/src/lib/generators/__tests__/output-snapshots.test.ts +37 -1
- package/src/lib/generators/index.ts +7 -1
- package/src/lib/generators/module-registry.ts +291 -293
- package/src/lib/module-install.ts +2 -6
- package/src/mercato.ts +6 -14
|
@@ -3,7 +3,7 @@ import path from 'node:path'
|
|
|
3
3
|
import { pathToFileURL } from 'node:url'
|
|
4
4
|
import { VariableDeclarationKind, type WriterFunction } from 'ts-morph'
|
|
5
5
|
import ts from 'typescript-js'
|
|
6
|
-
import type { PackageResolver } from '../resolver'
|
|
6
|
+
import type { ModuleEntry, PackageResolver } from '../resolver'
|
|
7
7
|
import {
|
|
8
8
|
calculateStructureChecksum,
|
|
9
9
|
toVar,
|
|
@@ -59,6 +59,8 @@ import {
|
|
|
59
59
|
MODULE_CODE_EXTENSIONS,
|
|
60
60
|
type ModuleRoots,
|
|
61
61
|
type ModuleImports,
|
|
62
|
+
type ScannedFile,
|
|
63
|
+
type ResolvedFile,
|
|
62
64
|
stripModuleCodeExtension,
|
|
63
65
|
isModulePageFile,
|
|
64
66
|
resolveStandaloneSourceMirrorBase,
|
|
@@ -73,6 +75,45 @@ export interface ModuleRegistryOptions {
|
|
|
73
75
|
quiet?: boolean
|
|
74
76
|
}
|
|
75
77
|
|
|
78
|
+
interface ModuleRegistryDiscovery {
|
|
79
|
+
enabled: ModuleEntry[]
|
|
80
|
+
modules: ModuleRegistryDiscoveryEntry[]
|
|
81
|
+
getStructureChecksum: () => string
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
type DiscoveredSubscriber = {
|
|
85
|
+
id: string
|
|
86
|
+
importPath: string
|
|
87
|
+
metadata: SerializableSubscriberMetadata | null
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
type DiscoveredWorker = {
|
|
91
|
+
id: string
|
|
92
|
+
importPath: string
|
|
93
|
+
metadata: SerializableWorkerMetadata
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
type DiscoveredTranslation = {
|
|
97
|
+
locale: string
|
|
98
|
+
coreHas: boolean
|
|
99
|
+
appHas: boolean
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
type ModuleRegistryDiscoveryEntry = {
|
|
103
|
+
modId: string
|
|
104
|
+
roots: ModuleRoots
|
|
105
|
+
imps: ModuleImports
|
|
106
|
+
appImportBase: string
|
|
107
|
+
resolve: (relativePath: string) => ResolvedFile | null
|
|
108
|
+
frontendFiles: ScannedFile[]
|
|
109
|
+
backendFiles: ScannedFile[]
|
|
110
|
+
commandLoaderEntries: CommandLoaderGenerationEntry[]
|
|
111
|
+
getSubscribers: () => Promise<DiscoveredSubscriber[]>
|
|
112
|
+
getWorkers: () => Promise<DiscoveredWorker[]>
|
|
113
|
+
translations: DiscoveredTranslation[]
|
|
114
|
+
dashboardWidgetEntries: DashboardWidgetEntry[]
|
|
115
|
+
}
|
|
116
|
+
|
|
76
117
|
type DashboardWidgetEntry = {
|
|
77
118
|
moduleId: string
|
|
78
119
|
key: string
|
|
@@ -1504,6 +1545,135 @@ async function loadWorkerMetadata(sourceFile: string): Promise<SerializableWorke
|
|
|
1504
1545
|
?? normalizeWorkerMetadata(extractNamedObjectLiteralExport(sourceFile, 'metadata'))
|
|
1505
1546
|
}
|
|
1506
1547
|
|
|
1548
|
+
async function discoverSubscribers(
|
|
1549
|
+
roots: ModuleRoots,
|
|
1550
|
+
imps: ModuleImports,
|
|
1551
|
+
modId: string,
|
|
1552
|
+
): Promise<DiscoveredSubscriber[]> {
|
|
1553
|
+
const subscribers: DiscoveredSubscriber[] = []
|
|
1554
|
+
for (const { relPath } of scanModuleDir(roots, SCAN_CONFIGS.subscribers)) {
|
|
1555
|
+
const resolved = resolveModuleFile(
|
|
1556
|
+
roots,
|
|
1557
|
+
imps,
|
|
1558
|
+
path.posix.join('subscribers', relPath.replace(/\\/g, '/')),
|
|
1559
|
+
)
|
|
1560
|
+
if (!resolved) continue
|
|
1561
|
+
const segs = relPath.split('/')
|
|
1562
|
+
const file = segs.pop()!
|
|
1563
|
+
const name = stripModuleCodeExtension(file)
|
|
1564
|
+
subscribers.push({
|
|
1565
|
+
id: [modId, ...segs, name].filter(Boolean).join(':'),
|
|
1566
|
+
importPath: sanitizeGeneratedModuleSpecifier(resolved.importPath),
|
|
1567
|
+
metadata: await loadSubscriberMetadata(resolved.absolutePath),
|
|
1568
|
+
})
|
|
1569
|
+
}
|
|
1570
|
+
return subscribers
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
async function discoverWorkers(
|
|
1574
|
+
roots: ModuleRoots,
|
|
1575
|
+
imps: ModuleImports,
|
|
1576
|
+
modId: string,
|
|
1577
|
+
): Promise<DiscoveredWorker[]> {
|
|
1578
|
+
const workers: DiscoveredWorker[] = []
|
|
1579
|
+
for (const { relPath } of scanModuleDir(roots, SCAN_CONFIGS.workers)) {
|
|
1580
|
+
const resolved = resolveModuleFile(
|
|
1581
|
+
roots,
|
|
1582
|
+
imps,
|
|
1583
|
+
path.posix.join('workers', relPath.replace(/\\/g, '/')),
|
|
1584
|
+
)
|
|
1585
|
+
if (!resolved) continue
|
|
1586
|
+
const metadata = await loadWorkerMetadata(resolved.absolutePath)
|
|
1587
|
+
if (!metadata?.queue) continue
|
|
1588
|
+
const segs = relPath.split('/')
|
|
1589
|
+
const file = segs.pop()!
|
|
1590
|
+
const name = stripModuleCodeExtension(file)
|
|
1591
|
+
workers.push({
|
|
1592
|
+
id: [modId, 'workers', ...segs, name].filter(Boolean).join(':'),
|
|
1593
|
+
importPath: sanitizeGeneratedModuleSpecifier(resolved.importPath),
|
|
1594
|
+
metadata,
|
|
1595
|
+
})
|
|
1596
|
+
}
|
|
1597
|
+
return workers
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1600
|
+
function discoverTranslations(roots: ModuleRoots): DiscoveredTranslation[] {
|
|
1601
|
+
const i18nApp = path.join(roots.appBase, 'i18n')
|
|
1602
|
+
const pkgI18nBase = resolveStandaloneSourceMirrorBase(roots.pkgBase) ?? roots.pkgBase
|
|
1603
|
+
const i18nCore = path.join(pkgI18nBase, 'i18n')
|
|
1604
|
+
const locales = new Set<string>()
|
|
1605
|
+
if (fs.existsSync(i18nCore)) {
|
|
1606
|
+
for (const entry of fs.readdirSync(i18nCore, { withFileTypes: true })) {
|
|
1607
|
+
if (entry.isFile() && entry.name.endsWith('.json')) locales.add(entry.name.replace(/\.json$/, ''))
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
if (fs.existsSync(i18nApp)) {
|
|
1611
|
+
for (const entry of fs.readdirSync(i18nApp, { withFileTypes: true })) {
|
|
1612
|
+
if (entry.isFile() && entry.name.endsWith('.json')) locales.add(entry.name.replace(/\.json$/, ''))
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
return Array.from(locales, (locale) => ({
|
|
1616
|
+
locale,
|
|
1617
|
+
coreHas: fs.existsSync(path.join(i18nCore, `${locale}.json`)),
|
|
1618
|
+
appHas: fs.existsSync(path.join(i18nApp, `${locale}.json`)),
|
|
1619
|
+
}))
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
async function createModuleRegistryDiscovery(
|
|
1623
|
+
resolver: PackageResolver,
|
|
1624
|
+
): Promise<ModuleRegistryDiscovery> {
|
|
1625
|
+
const enabled = resolver.loadEnabledModules()
|
|
1626
|
+
const modules: ModuleRegistryDiscoveryEntry[] = []
|
|
1627
|
+
const trackedRoots = new Set<string>()
|
|
1628
|
+
|
|
1629
|
+
for (const entry of enabled) {
|
|
1630
|
+
const modId = entry.id
|
|
1631
|
+
const roots = resolver.getModulePaths(entry)
|
|
1632
|
+
verifyThirdPartyModuleShape(entry, roots.pkgBase)
|
|
1633
|
+
const rawImps = resolver.getModuleImportBase(entry)
|
|
1634
|
+
const appImportBase = entry.from === '@app' ? `../../src/modules/${modId}` : rawImps.appBase
|
|
1635
|
+
const imps: ModuleImports = { appBase: appImportBase, pkgBase: rawImps.pkgBase }
|
|
1636
|
+
trackedRoots.add(roots.appBase)
|
|
1637
|
+
trackedRoots.add(roots.pkgBase)
|
|
1638
|
+
|
|
1639
|
+
let subscribers: Promise<DiscoveredSubscriber[]> | undefined
|
|
1640
|
+
let workers: Promise<DiscoveredWorker[]> | undefined
|
|
1641
|
+
const resolvedFiles = new Map<string, ResolvedFile | null>()
|
|
1642
|
+
const resolve = (relativePath: string): ResolvedFile | null => {
|
|
1643
|
+
if (!resolvedFiles.has(relativePath)) {
|
|
1644
|
+
resolvedFiles.set(relativePath, resolveModuleFile(roots, imps, relativePath))
|
|
1645
|
+
}
|
|
1646
|
+
return resolvedFiles.get(relativePath) ?? null
|
|
1647
|
+
}
|
|
1648
|
+
modules.push({
|
|
1649
|
+
modId,
|
|
1650
|
+
roots,
|
|
1651
|
+
imps,
|
|
1652
|
+
appImportBase,
|
|
1653
|
+
resolve,
|
|
1654
|
+
frontendFiles: scanModuleDir(roots, SCAN_CONFIGS.frontendPages),
|
|
1655
|
+
backendFiles: scanModuleDir(roots, SCAN_CONFIGS.backendPages),
|
|
1656
|
+
commandLoaderEntries: collectCommandLoaderEntries(roots, imps, modId),
|
|
1657
|
+
getSubscribers: () => subscribers ??= discoverSubscribers(roots, imps, modId),
|
|
1658
|
+
getWorkers: () => workers ??= discoverWorkers(roots, imps, modId),
|
|
1659
|
+
translations: discoverTranslations(roots),
|
|
1660
|
+
dashboardWidgetEntries: scanDashboardWidgetEntries({
|
|
1661
|
+
modId,
|
|
1662
|
+
roots,
|
|
1663
|
+
appImportBase,
|
|
1664
|
+
pkgImportBase: imps.pkgBase,
|
|
1665
|
+
}),
|
|
1666
|
+
})
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
let structureChecksum: string | undefined
|
|
1670
|
+
return {
|
|
1671
|
+
enabled,
|
|
1672
|
+
modules,
|
|
1673
|
+
getStructureChecksum: () => structureChecksum ??= calculateStructureChecksum(Array.from(trackedRoots)),
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1507
1677
|
async function loadPageMetadataForManifest(options: {
|
|
1508
1678
|
sourceFile: string
|
|
1509
1679
|
metaPath?: string
|
|
@@ -1842,90 +2012,39 @@ async function processApiRoutes(options: {
|
|
|
1842
2012
|
}
|
|
1843
2013
|
}
|
|
1844
2014
|
|
|
1845
|
-
|
|
1846
|
-
roots: ModuleRoots
|
|
1847
|
-
modId: string
|
|
1848
|
-
appImportBase: string
|
|
1849
|
-
pkgImportBase: string
|
|
1850
|
-
}): Promise<string[]> {
|
|
1851
|
-
const { roots, modId, appImportBase, pkgImportBase } = options
|
|
1852
|
-
const files = scanModuleDir(roots, SCAN_CONFIGS.subscribers)
|
|
2015
|
+
function processSubscribers(discovered: DiscoveredSubscriber[]): string[] {
|
|
1853
2016
|
const subscribers: string[] = []
|
|
1854
|
-
for (const {
|
|
1855
|
-
const
|
|
1856
|
-
roots,
|
|
1857
|
-
{ appBase: appImportBase, pkgBase: pkgImportBase },
|
|
1858
|
-
path.posix.join('subscribers', relPath.replace(/\\/g, '/')),
|
|
1859
|
-
)
|
|
1860
|
-
if (!resolved) continue
|
|
1861
|
-
const segs = relPath.split('/')
|
|
1862
|
-
const file = segs.pop()!
|
|
1863
|
-
const name = stripModuleCodeExtension(file)
|
|
1864
|
-
const importPath = sanitizeGeneratedModuleSpecifier(resolved.importPath)
|
|
1865
|
-
const sid = [modId, ...segs, name].filter(Boolean).join(':')
|
|
1866
|
-
const sourceFile = resolved.absolutePath
|
|
1867
|
-
const metadata = await loadSubscriberMetadata(sourceFile)
|
|
2017
|
+
for (const { id, importPath, metadata } of discovered) {
|
|
2018
|
+
const subscriberId = metadata?.id ?? id
|
|
1868
2019
|
subscribers.push(
|
|
1869
|
-
`{ id: ${toLiteral(
|
|
2020
|
+
`{ id: ${toLiteral(subscriberId)}, event: ${toLiteral(metadata?.event ?? '')}, persistent: ${metadata?.persistent === undefined ? 'undefined' : toLiteral(metadata.persistent)}, sync: ${metadata?.sync === undefined ? 'undefined' : toLiteral(metadata.sync)}, priority: ${metadata?.priority === undefined ? 'undefined' : toLiteral(metadata.priority)}, handler: createLazyModuleSubscriber(() => ${buildDynamicImportExpression(importPath)}, ${toLiteral(subscriberId)}) }`
|
|
1870
2021
|
)
|
|
1871
2022
|
}
|
|
1872
2023
|
return subscribers
|
|
1873
2024
|
}
|
|
1874
2025
|
|
|
1875
|
-
|
|
1876
|
-
roots: ModuleRoots
|
|
1877
|
-
modId: string
|
|
1878
|
-
appImportBase: string
|
|
1879
|
-
pkgImportBase: string
|
|
1880
|
-
}): Promise<string[]> {
|
|
1881
|
-
const { roots, modId, appImportBase, pkgImportBase } = options
|
|
1882
|
-
const files = scanModuleDir(roots, SCAN_CONFIGS.workers)
|
|
2026
|
+
function processWorkers(discovered: DiscoveredWorker[]): string[] {
|
|
1883
2027
|
const workers: string[] = []
|
|
1884
|
-
for (const {
|
|
1885
|
-
const
|
|
1886
|
-
roots,
|
|
1887
|
-
{ appBase: appImportBase, pkgBase: pkgImportBase },
|
|
1888
|
-
path.posix.join('workers', relPath.replace(/\\/g, '/')),
|
|
1889
|
-
)
|
|
1890
|
-
if (!resolved) continue
|
|
1891
|
-
const segs = relPath.split('/')
|
|
1892
|
-
const file = segs.pop()!
|
|
1893
|
-
const name = stripModuleCodeExtension(file)
|
|
1894
|
-
const importPath = sanitizeGeneratedModuleSpecifier(resolved.importPath)
|
|
1895
|
-
const sourceFile = resolved.absolutePath
|
|
1896
|
-
const metadata = await loadWorkerMetadata(sourceFile)
|
|
1897
|
-
if (!metadata?.queue) continue
|
|
1898
|
-
const wid = [modId, 'workers', ...segs, name].filter(Boolean).join(':')
|
|
2028
|
+
for (const { id, importPath, metadata } of discovered) {
|
|
2029
|
+
const workerId = metadata.id ?? id
|
|
1899
2030
|
workers.push(
|
|
1900
|
-
`{ id: ${toLiteral(
|
|
2031
|
+
`{ id: ${toLiteral(workerId)}, queue: ${toLiteral(metadata.queue)}, concurrency: ${toLiteral(metadata.concurrency ?? 1)}, handler: createLazyModuleWorker(() => ${buildDynamicImportExpression(importPath)}, ${toLiteral(workerId)}) }`
|
|
1901
2032
|
)
|
|
1902
2033
|
}
|
|
1903
2034
|
return workers
|
|
1904
2035
|
}
|
|
1905
2036
|
|
|
1906
2037
|
function processTranslations(options: {
|
|
1907
|
-
|
|
2038
|
+
discovered: DiscoveredTranslation[]
|
|
1908
2039
|
modId: string
|
|
1909
2040
|
appImportBase: string
|
|
1910
2041
|
pkgImportBase: string
|
|
1911
2042
|
imports: string[]
|
|
1912
2043
|
extraImports?: string[]
|
|
1913
2044
|
}): string[] {
|
|
1914
|
-
const {
|
|
1915
|
-
const i18nApp = path.join(roots.appBase, 'i18n')
|
|
1916
|
-
const pkgI18nBase = resolveStandaloneSourceMirrorBase(roots.pkgBase) ?? roots.pkgBase
|
|
1917
|
-
const i18nCore = path.join(pkgI18nBase, 'i18n')
|
|
1918
|
-
const locales = new Set<string>()
|
|
1919
|
-
if (fs.existsSync(i18nCore))
|
|
1920
|
-
for (const e of fs.readdirSync(i18nCore, { withFileTypes: true }))
|
|
1921
|
-
if (e.isFile() && e.name.endsWith('.json')) locales.add(e.name.replace(/\.json$/, ''))
|
|
1922
|
-
if (fs.existsSync(i18nApp))
|
|
1923
|
-
for (const e of fs.readdirSync(i18nApp, { withFileTypes: true }))
|
|
1924
|
-
if (e.isFile() && e.name.endsWith('.json')) locales.add(e.name.replace(/\.json$/, ''))
|
|
2045
|
+
const { discovered, modId, appImportBase, pkgImportBase, imports, extraImports } = options
|
|
1925
2046
|
const translations: string[] = []
|
|
1926
|
-
for (const locale of
|
|
1927
|
-
const coreHas = fs.existsSync(path.join(i18nCore, `${locale}.json`))
|
|
1928
|
-
const appHas = fs.existsSync(path.join(i18nApp, `${locale}.json`))
|
|
2047
|
+
for (const { locale, coreHas, appHas } of discovered) {
|
|
1929
2048
|
if (coreHas && appHas) {
|
|
1930
2049
|
const cName = `T_${toVar(modId)}_${toVar(locale)}_C`
|
|
1931
2050
|
const aName = `T_${toVar(modId)}_${toVar(locale)}_A`
|
|
@@ -2547,28 +2666,10 @@ async function processPageFilesAst(options: {
|
|
|
2547
2666
|
return routes
|
|
2548
2667
|
}
|
|
2549
2668
|
|
|
2550
|
-
|
|
2551
|
-
roots: ModuleRoots
|
|
2552
|
-
modId: string
|
|
2553
|
-
appImportBase: string
|
|
2554
|
-
pkgImportBase: string
|
|
2555
|
-
}): Promise<WriterFunction[]> {
|
|
2556
|
-
const { roots, modId, appImportBase, pkgImportBase } = options
|
|
2557
|
-
const files = scanModuleDir(roots, SCAN_CONFIGS.subscribers)
|
|
2669
|
+
function processSubscribersAst(discovered: DiscoveredSubscriber[]): WriterFunction[] {
|
|
2558
2670
|
const subscribers: WriterFunction[] = []
|
|
2559
|
-
for (const {
|
|
2560
|
-
const
|
|
2561
|
-
roots,
|
|
2562
|
-
{ appBase: appImportBase, pkgBase: pkgImportBase },
|
|
2563
|
-
path.posix.join('subscribers', relPath.replace(/\\/g, '/')),
|
|
2564
|
-
)
|
|
2565
|
-
if (!resolved) continue
|
|
2566
|
-
const segs = relPath.split('/')
|
|
2567
|
-
const file = segs.pop()!
|
|
2568
|
-
const name = stripModuleCodeExtension(file)
|
|
2569
|
-
const sid = [modId, ...segs, name].filter(Boolean).join(':')
|
|
2570
|
-
const metadata = await loadSubscriberMetadata(resolved.absolutePath)
|
|
2571
|
-
const subscriberId = metadata?.id ?? sid
|
|
2671
|
+
for (const { id, importPath, metadata } of discovered) {
|
|
2672
|
+
const subscriberId = metadata?.id ?? id
|
|
2572
2673
|
subscribers.push(
|
|
2573
2674
|
objectLiteral([
|
|
2574
2675
|
{ name: 'id', value: subscriberId },
|
|
@@ -2580,7 +2681,7 @@ async function processSubscribersAst(options: {
|
|
|
2580
2681
|
name: 'handler',
|
|
2581
2682
|
value: callExpression(identifier('createLazyModuleSubscriber'), [
|
|
2582
2683
|
arrowFunction({
|
|
2583
|
-
body: importExpression(
|
|
2684
|
+
body: importExpression(importPath),
|
|
2584
2685
|
}),
|
|
2585
2686
|
subscriberId,
|
|
2586
2687
|
]),
|
|
@@ -2591,28 +2692,10 @@ async function processSubscribersAst(options: {
|
|
|
2591
2692
|
return subscribers
|
|
2592
2693
|
}
|
|
2593
2694
|
|
|
2594
|
-
|
|
2595
|
-
roots: ModuleRoots
|
|
2596
|
-
modId: string
|
|
2597
|
-
appImportBase: string
|
|
2598
|
-
pkgImportBase: string
|
|
2599
|
-
}): Promise<WriterFunction[]> {
|
|
2600
|
-
const { roots, modId, appImportBase, pkgImportBase } = options
|
|
2601
|
-
const files = scanModuleDir(roots, SCAN_CONFIGS.workers)
|
|
2695
|
+
function processWorkersAst(discovered: DiscoveredWorker[]): WriterFunction[] {
|
|
2602
2696
|
const workers: WriterFunction[] = []
|
|
2603
|
-
for (const {
|
|
2604
|
-
const
|
|
2605
|
-
roots,
|
|
2606
|
-
{ appBase: appImportBase, pkgBase: pkgImportBase },
|
|
2607
|
-
path.posix.join('workers', relPath.replace(/\\/g, '/')),
|
|
2608
|
-
)
|
|
2609
|
-
if (!resolved) continue
|
|
2610
|
-
const segs = relPath.split('/')
|
|
2611
|
-
const file = segs.pop()!
|
|
2612
|
-
const name = stripModuleCodeExtension(file)
|
|
2613
|
-
const metadata = await loadWorkerMetadata(resolved.absolutePath)
|
|
2614
|
-
if (!metadata?.queue) continue
|
|
2615
|
-
const workerId = metadata.id ?? [modId, 'workers', ...segs, name].filter(Boolean).join(':')
|
|
2697
|
+
for (const { id, importPath, metadata } of discovered) {
|
|
2698
|
+
const workerId = metadata.id ?? id
|
|
2616
2699
|
workers.push(
|
|
2617
2700
|
objectLiteral([
|
|
2618
2701
|
{ name: 'id', value: workerId },
|
|
@@ -2622,7 +2705,7 @@ async function processWorkersAst(options: {
|
|
|
2622
2705
|
name: 'handler',
|
|
2623
2706
|
value: callExpression(identifier('createLazyModuleWorker'), [
|
|
2624
2707
|
arrowFunction({
|
|
2625
|
-
body: importExpression(
|
|
2708
|
+
body: importExpression(importPath),
|
|
2626
2709
|
}),
|
|
2627
2710
|
workerId,
|
|
2628
2711
|
]),
|
|
@@ -2634,40 +2717,18 @@ async function processWorkersAst(options: {
|
|
|
2634
2717
|
}
|
|
2635
2718
|
|
|
2636
2719
|
function processTranslationsAst(options: {
|
|
2637
|
-
|
|
2720
|
+
discovered: DiscoveredTranslation[]
|
|
2638
2721
|
modId: string
|
|
2639
2722
|
appImportBase: string
|
|
2640
2723
|
pkgImportBase: string
|
|
2641
2724
|
imports: string[]
|
|
2642
2725
|
extraImports?: string[]
|
|
2643
2726
|
}): GeneratedObjectEntry[] {
|
|
2644
|
-
const {
|
|
2645
|
-
const i18nApp = path.join(roots.appBase, 'i18n')
|
|
2646
|
-
const pkgI18nBase = resolveStandaloneSourceMirrorBase(roots.pkgBase) ?? roots.pkgBase
|
|
2647
|
-
const i18nCore = path.join(pkgI18nBase, 'i18n')
|
|
2648
|
-
const locales = new Set<string>()
|
|
2649
|
-
|
|
2650
|
-
if (fs.existsSync(i18nCore)) {
|
|
2651
|
-
for (const entry of fs.readdirSync(i18nCore, { withFileTypes: true })) {
|
|
2652
|
-
if (entry.isFile() && entry.name.endsWith('.json')) {
|
|
2653
|
-
locales.add(entry.name.replace(/\.json$/, ''))
|
|
2654
|
-
}
|
|
2655
|
-
}
|
|
2656
|
-
}
|
|
2657
|
-
|
|
2658
|
-
if (fs.existsSync(i18nApp)) {
|
|
2659
|
-
for (const entry of fs.readdirSync(i18nApp, { withFileTypes: true })) {
|
|
2660
|
-
if (entry.isFile() && entry.name.endsWith('.json')) {
|
|
2661
|
-
locales.add(entry.name.replace(/\.json$/, ''))
|
|
2662
|
-
}
|
|
2663
|
-
}
|
|
2664
|
-
}
|
|
2727
|
+
const { discovered, modId, appImportBase, pkgImportBase, imports, extraImports } = options
|
|
2665
2728
|
|
|
2666
2729
|
const translations: GeneratedObjectEntry[] = []
|
|
2667
2730
|
|
|
2668
|
-
for (const locale of
|
|
2669
|
-
const coreHas = fs.existsSync(path.join(i18nCore, `${locale}.json`))
|
|
2670
|
-
const appHas = fs.existsSync(path.join(i18nApp, `${locale}.json`))
|
|
2731
|
+
for (const { locale, coreHas, appHas } of discovered) {
|
|
2671
2732
|
|
|
2672
2733
|
if (coreHas && appHas) {
|
|
2673
2734
|
const coreName = `T_${toVar(modId)}_${toVar(locale)}_C`
|
|
@@ -2712,9 +2773,7 @@ function processTranslationsAst(options: {
|
|
|
2712
2773
|
}
|
|
2713
2774
|
|
|
2714
2775
|
function resolveConventionFile(
|
|
2715
|
-
|
|
2716
|
-
imps: ModuleImports,
|
|
2717
|
-
relativePath: string,
|
|
2776
|
+
resolved: ResolvedFile | null,
|
|
2718
2777
|
prefix: string,
|
|
2719
2778
|
modId: string,
|
|
2720
2779
|
importIdRef: { value: number },
|
|
@@ -2722,7 +2781,6 @@ function resolveConventionFile(
|
|
|
2722
2781
|
extraImports?: string[],
|
|
2723
2782
|
importStyle: 'namespace' | 'default' = 'namespace'
|
|
2724
2783
|
): { importName: string; importPath: string; fromApp: boolean } | null {
|
|
2725
|
-
const resolved = resolveModuleFile(roots, imps, relativePath)
|
|
2726
2784
|
if (!resolved) return null
|
|
2727
2785
|
const importName = `${prefix}_${toVar(modId)}_${importIdRef.value++}`
|
|
2728
2786
|
const importPath = sanitizeGeneratedModuleSpecifier(resolved.importPath)
|
|
@@ -2736,8 +2794,13 @@ function resolveConventionFile(
|
|
|
2736
2794
|
return { importName, importPath, fromApp: resolved.fromApp }
|
|
2737
2795
|
}
|
|
2738
2796
|
|
|
2739
|
-
|
|
2797
|
+
type ModuleRegistryRenderOptions = ModuleRegistryOptions & {
|
|
2798
|
+
discovery: ModuleRegistryDiscovery
|
|
2799
|
+
}
|
|
2800
|
+
|
|
2801
|
+
async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRenderOptions): Promise<GeneratorResult> {
|
|
2740
2802
|
const { resolver, quiet = false } = options
|
|
2803
|
+
const { discovery } = options
|
|
2741
2804
|
const result = createGeneratorResult()
|
|
2742
2805
|
|
|
2743
2806
|
const outputDir = resolver.getOutputDir()
|
|
@@ -2758,22 +2821,14 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
2758
2821
|
const commandLoadersOutFile = path.join(outputDir, 'command-loaders.generated.ts')
|
|
2759
2822
|
const commandLoadersChecksumFile = path.join(outputDir, 'command-loaders.generated.checksum')
|
|
2760
2823
|
|
|
2761
|
-
const enabled =
|
|
2762
|
-
for (const entry of enabled) {
|
|
2763
|
-
verifyThirdPartyModuleShape(entry, resolver.getModulePaths(entry).pkgBase)
|
|
2764
|
-
}
|
|
2824
|
+
const enabled = discovery.enabled
|
|
2765
2825
|
const extensions = loadGeneratorExtensions()
|
|
2766
2826
|
|
|
2767
2827
|
// Pre-pass: collect generator plugins from each enabled module's generators.ts
|
|
2768
2828
|
const pluginRegistry = new Map<string, import('@open-mercato/shared/modules/generators').GeneratorPlugin>()
|
|
2769
2829
|
const pluginState = new Map<string, { imports: string[]; configs: string[] }>()
|
|
2770
|
-
for (const
|
|
2771
|
-
const
|
|
2772
|
-
const rawImps = resolver.getModuleImportBase(entry)
|
|
2773
|
-
const isAppMod = entry.from === '@app'
|
|
2774
|
-
const appImportBase = isAppMod ? `../../src/modules/${entry.id}` : rawImps.appBase
|
|
2775
|
-
const imps: ModuleImports = { appBase: appImportBase, pkgBase: rawImps.pkgBase }
|
|
2776
|
-
const resolved = resolveModuleFile(roots, imps, 'generators.ts')
|
|
2830
|
+
for (const discovered of discovery.modules) {
|
|
2831
|
+
const resolved = discovered.resolve('generators.ts')
|
|
2777
2832
|
if (!resolved) continue
|
|
2778
2833
|
try {
|
|
2779
2834
|
const pluginMod = await import(buildCacheBustedSourceImportUrl(resolved.absolutePath))
|
|
@@ -2799,7 +2854,6 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
2799
2854
|
const apiRouteManifestDecls: string[] = []
|
|
2800
2855
|
// Mutable ref so extracted helper functions can increment the shared counter
|
|
2801
2856
|
const importIdRef = { value: 0 }
|
|
2802
|
-
const trackedRoots = new Set<string>()
|
|
2803
2857
|
const requiresByModule = new Map<string, string[]>()
|
|
2804
2858
|
const commandLoaderEntries: CommandLoaderGenerationEntry[] = []
|
|
2805
2859
|
let hasRouteComponents = false
|
|
@@ -2812,17 +2866,9 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
2812
2866
|
aclPath?: string
|
|
2813
2867
|
}> = []
|
|
2814
2868
|
|
|
2815
|
-
for (const
|
|
2816
|
-
const modId =
|
|
2817
|
-
|
|
2818
|
-
const rawImps = resolver.getModuleImportBase(entry)
|
|
2819
|
-
trackedRoots.add(roots.appBase)
|
|
2820
|
-
trackedRoots.add(roots.pkgBase)
|
|
2821
|
-
|
|
2822
|
-
const isAppModule = entry.from === '@app'
|
|
2823
|
-
const appImportBase = isAppModule ? `../../src/modules/${modId}` : rawImps.appBase
|
|
2824
|
-
const imps: ModuleImports = { appBase: appImportBase, pkgBase: rawImps.pkgBase }
|
|
2825
|
-
commandLoaderEntries.push(...collectCommandLoaderEntries(roots, imps, modId))
|
|
2869
|
+
for (const discovered of discovery.modules) {
|
|
2870
|
+
const { modId, roots, imps, appImportBase } = discovered
|
|
2871
|
+
commandLoaderEntries.push(...discovered.commandLoaderEntries)
|
|
2826
2872
|
|
|
2827
2873
|
const frontendRoutes: string[] = []
|
|
2828
2874
|
const backendRoutes: string[] = []
|
|
@@ -2848,7 +2894,7 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
2848
2894
|
// === Processing order MUST match original import ID sequence ===
|
|
2849
2895
|
|
|
2850
2896
|
// 1. Module metadata: index.ts (overrideable)
|
|
2851
|
-
const indexResolved =
|
|
2897
|
+
const indexResolved = discovered.resolve('index.ts')
|
|
2852
2898
|
if (indexResolved) {
|
|
2853
2899
|
infoImportName = `I${importIdRef.value++}_${toVar(modId)}`
|
|
2854
2900
|
const importPath = sanitizeGeneratedModuleSpecifier(indexResolved.importPath)
|
|
@@ -2867,7 +2913,7 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
2867
2913
|
{
|
|
2868
2914
|
const feApp = path.join(roots.appBase, 'frontend')
|
|
2869
2915
|
const fePkg = path.join(roots.pkgBase, 'frontend')
|
|
2870
|
-
const feFiles =
|
|
2916
|
+
const feFiles = discovered.frontendFiles
|
|
2871
2917
|
if (feFiles.length) {
|
|
2872
2918
|
const generatedFrontendRoutes = await processPageFiles({
|
|
2873
2919
|
files: feFiles,
|
|
@@ -2891,13 +2937,13 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
2891
2937
|
|
|
2892
2938
|
// 3. Entity extensions: data/extensions.ts
|
|
2893
2939
|
{
|
|
2894
|
-
const ext = resolveConventionFile(
|
|
2940
|
+
const ext = resolveConventionFile(discovered.resolve('data/extensions.ts'), 'X', modId, importIdRef, imports, runtimeImports)
|
|
2895
2941
|
if (ext) extensionsImportName = ext.importName
|
|
2896
2942
|
}
|
|
2897
2943
|
|
|
2898
2944
|
// 4. RBAC: acl.ts
|
|
2899
2945
|
{
|
|
2900
|
-
const aclResolved =
|
|
2946
|
+
const aclResolved = discovered.resolve('acl.ts')
|
|
2901
2947
|
if (aclResolved) {
|
|
2902
2948
|
const importName = `ACL_${toVar(modId)}_${importIdRef.value++}`
|
|
2903
2949
|
const importPath = sanitizeGeneratedModuleSpecifier(aclResolved.importPath)
|
|
@@ -2909,7 +2955,7 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
2909
2955
|
|
|
2910
2956
|
// 5. Custom entities: ce.ts
|
|
2911
2957
|
{
|
|
2912
|
-
const ce = resolveConventionFile(
|
|
2958
|
+
const ce = resolveConventionFile(discovered.resolve('ce.ts'), 'CE', modId, importIdRef, imports, runtimeImports)
|
|
2913
2959
|
if (ce) customEntitiesImportName = ce.importName
|
|
2914
2960
|
}
|
|
2915
2961
|
|
|
@@ -2930,9 +2976,9 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
2930
2976
|
|
|
2931
2977
|
// Track file paths for UMES conflict detection
|
|
2932
2978
|
{
|
|
2933
|
-
const compOverridesFile =
|
|
2934
|
-
const interceptorsFile =
|
|
2935
|
-
const aclFile =
|
|
2979
|
+
const compOverridesFile = discovered.resolve('widgets/components.ts')
|
|
2980
|
+
const interceptorsFile = discovered.resolve('api/interceptors.ts')
|
|
2981
|
+
const aclFile = discovered.resolve('acl.ts')
|
|
2936
2982
|
umesConflictSources.push({
|
|
2937
2983
|
moduleId: modId,
|
|
2938
2984
|
componentOverridesPath: compOverridesFile?.absolutePath,
|
|
@@ -2955,19 +3001,19 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
2955
3001
|
|
|
2956
3002
|
// 11. Setup: setup.ts
|
|
2957
3003
|
{
|
|
2958
|
-
const setup = resolveConventionFile(
|
|
3004
|
+
const setup = resolveConventionFile(discovered.resolve('setup.ts'), 'SETUP', modId, importIdRef, imports, runtimeImports)
|
|
2959
3005
|
if (setup) setupImportName = setup.importName
|
|
2960
3006
|
}
|
|
2961
3007
|
|
|
2962
3008
|
// 11a. Encryption defaults: encryption.ts
|
|
2963
3009
|
{
|
|
2964
|
-
const encryption = resolveConventionFile(
|
|
3010
|
+
const encryption = resolveConventionFile(discovered.resolve('encryption.ts'), 'ENCRYPTION', modId, importIdRef, imports, runtimeImports)
|
|
2965
3011
|
if (encryption) encryptionImportName = encryption.importName
|
|
2966
3012
|
}
|
|
2967
3013
|
|
|
2968
3014
|
// 11b. Integration manifest: integration.ts
|
|
2969
3015
|
{
|
|
2970
|
-
const resolved =
|
|
3016
|
+
const resolved = discovered.resolve('integration.ts')
|
|
2971
3017
|
if (resolved) {
|
|
2972
3018
|
const importName = `INTEGRATION_${toVar(modId)}_${importIdRef.value++}`
|
|
2973
3019
|
imports.push(buildImportStatement(`* as ${importName}`, resolved.importPath))
|
|
@@ -2978,7 +3024,7 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
2978
3024
|
|
|
2979
3025
|
// 12. Custom fields: data/fields.ts
|
|
2980
3026
|
{
|
|
2981
|
-
const fields = resolveConventionFile(
|
|
3027
|
+
const fields = resolveConventionFile(discovered.resolve('data/fields.ts'), 'F', modId, importIdRef, imports, runtimeImports)
|
|
2982
3028
|
if (fields) fieldsImportName = fields.importName
|
|
2983
3029
|
}
|
|
2984
3030
|
|
|
@@ -2986,7 +3032,7 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
2986
3032
|
{
|
|
2987
3033
|
const beApp = path.join(roots.appBase, 'backend')
|
|
2988
3034
|
const bePkg = path.join(roots.pkgBase, 'backend')
|
|
2989
|
-
const beFiles =
|
|
3035
|
+
const beFiles = discovered.backendFiles
|
|
2990
3036
|
if (beFiles.length) {
|
|
2991
3037
|
const generatedBackendRoutes = await processPageFiles({
|
|
2992
3038
|
files: beFiles,
|
|
@@ -3025,7 +3071,7 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
3025
3071
|
|
|
3026
3072
|
// 15. CLI
|
|
3027
3073
|
{
|
|
3028
|
-
const cliResolved =
|
|
3074
|
+
const cliResolved = discovered.resolve('cli.ts')
|
|
3029
3075
|
if (cliResolved) {
|
|
3030
3076
|
const importName = `CLI_${toVar(modId)}`
|
|
3031
3077
|
imports.push(buildImportStatement(importName, sanitizeGeneratedModuleSpecifier(cliResolved.importPath)))
|
|
@@ -3035,7 +3081,7 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
3035
3081
|
|
|
3036
3082
|
// 16. Translations
|
|
3037
3083
|
translations.push(...processTranslations({
|
|
3038
|
-
|
|
3084
|
+
discovered: discovered.translations,
|
|
3039
3085
|
modId,
|
|
3040
3086
|
appImportBase,
|
|
3041
3087
|
pkgImportBase: imps.pkgBase,
|
|
@@ -3044,20 +3090,10 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
3044
3090
|
}))
|
|
3045
3091
|
|
|
3046
3092
|
// 17. Subscribers
|
|
3047
|
-
subscribers.push(...await
|
|
3048
|
-
roots,
|
|
3049
|
-
modId,
|
|
3050
|
-
appImportBase,
|
|
3051
|
-
pkgImportBase: imps.pkgBase,
|
|
3052
|
-
}))
|
|
3093
|
+
subscribers.push(...processSubscribers(await discovered.getSubscribers()))
|
|
3053
3094
|
|
|
3054
3095
|
// 18. Workers
|
|
3055
|
-
workers.push(...await
|
|
3056
|
-
roots,
|
|
3057
|
-
modId,
|
|
3058
|
-
appImportBase,
|
|
3059
|
-
pkgImportBase: imps.pkgBase,
|
|
3060
|
-
}))
|
|
3096
|
+
workers.push(...processWorkers(await discovered.getWorkers()))
|
|
3061
3097
|
|
|
3062
3098
|
// Build combined customFieldSets expression
|
|
3063
3099
|
{
|
|
@@ -3073,13 +3109,7 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
3073
3109
|
|
|
3074
3110
|
// 19. Dashboard widgets
|
|
3075
3111
|
{
|
|
3076
|
-
const
|
|
3077
|
-
modId,
|
|
3078
|
-
roots,
|
|
3079
|
-
appImportBase,
|
|
3080
|
-
pkgImportBase: imps.pkgBase,
|
|
3081
|
-
})
|
|
3082
|
-
for (const entry of entries) {
|
|
3112
|
+
for (const entry of discovered.dashboardWidgetEntries) {
|
|
3083
3113
|
dashboardWidgets.push(
|
|
3084
3114
|
`{ moduleId: ${toLiteral(entry.moduleId)}, key: ${toLiteral(entry.key)}, source: ${toLiteral(entry.source)}, loader: () => ${buildDynamicImportExpression(entry.importPath)}.then((mod) => mod.default ?? mod) }`
|
|
3085
3115
|
)
|
|
@@ -3296,9 +3326,7 @@ export async function generateModuleRegistry(options: ModuleRegistryOptions): Pr
|
|
|
3296
3326
|
}
|
|
3297
3327
|
}
|
|
3298
3328
|
|
|
3299
|
-
const structureChecksum =
|
|
3300
|
-
...Array.from(trackedRoots),
|
|
3301
|
-
])
|
|
3329
|
+
const structureChecksum = discovery.getStructureChecksum()
|
|
3302
3330
|
|
|
3303
3331
|
writeGeneratedFile({ outFile, checksumFile, content: output, structureChecksum, result, quiet })
|
|
3304
3332
|
writeGeneratedFile({ outFile: runtimeOutFile, checksumFile: runtimeChecksumFile, content: runtimeOutput, structureChecksum, result, quiet })
|
|
@@ -3373,8 +3401,9 @@ ${body}
|
|
|
3373
3401
|
return result
|
|
3374
3402
|
}
|
|
3375
3403
|
|
|
3376
|
-
|
|
3404
|
+
async function generateModuleRegistryAppFromDiscovery(options: ModuleRegistryRenderOptions): Promise<GeneratorResult> {
|
|
3377
3405
|
const { resolver, quiet = false } = options
|
|
3406
|
+
const { discovery } = options
|
|
3378
3407
|
const result = createGeneratorResult()
|
|
3379
3408
|
|
|
3380
3409
|
const outputDir = resolver.getOutputDir()
|
|
@@ -3391,10 +3420,7 @@ export async function generateModuleRegistryApp(options: ModuleRegistryOptions):
|
|
|
3391
3420
|
const commandLoadersOutFile = path.join(outputDir, 'command-loaders.generated.ts')
|
|
3392
3421
|
const commandLoadersChecksumFile = path.join(outputDir, 'command-loaders.generated.checksum')
|
|
3393
3422
|
|
|
3394
|
-
const enabled =
|
|
3395
|
-
for (const entry of enabled) {
|
|
3396
|
-
verifyThirdPartyModuleShape(entry, resolver.getModulePaths(entry).pkgBase)
|
|
3397
|
-
}
|
|
3423
|
+
const enabled = discovery.enabled
|
|
3398
3424
|
const imports: string[] = []
|
|
3399
3425
|
const bootstrapImports: string[] = []
|
|
3400
3426
|
const i18nImports: string[] = []
|
|
@@ -3402,22 +3428,13 @@ export async function generateModuleRegistryApp(options: ModuleRegistryOptions):
|
|
|
3402
3428
|
const bootstrapModuleDecls: WriterFunction[] = []
|
|
3403
3429
|
const i18nModuleDecls: WriterFunction[] = []
|
|
3404
3430
|
const importIdRef = { value: 0 }
|
|
3405
|
-
const trackedRoots = new Set<string>()
|
|
3406
3431
|
const requiresByModule = new Map<string, string[]>()
|
|
3407
3432
|
const commandLoaderEntries: CommandLoaderGenerationEntry[] = []
|
|
3408
3433
|
let hasRouteComponents = false
|
|
3409
3434
|
|
|
3410
|
-
for (const
|
|
3411
|
-
const modId =
|
|
3412
|
-
|
|
3413
|
-
const rawImps = resolver.getModuleImportBase(entry)
|
|
3414
|
-
trackedRoots.add(roots.appBase)
|
|
3415
|
-
trackedRoots.add(roots.pkgBase)
|
|
3416
|
-
|
|
3417
|
-
const isAppModule = entry.from === '@app'
|
|
3418
|
-
const appImportBase = isAppModule ? `../../src/modules/${modId}` : rawImps.appBase
|
|
3419
|
-
const imps: ModuleImports = { appBase: appImportBase, pkgBase: rawImps.pkgBase }
|
|
3420
|
-
commandLoaderEntries.push(...collectCommandLoaderEntries(roots, imps, modId))
|
|
3435
|
+
for (const discovered of discovery.modules) {
|
|
3436
|
+
const { modId, roots, imps, appImportBase } = discovered
|
|
3437
|
+
commandLoaderEntries.push(...discovered.commandLoaderEntries)
|
|
3421
3438
|
|
|
3422
3439
|
const frontendRoutes: WriterFunction[] = []
|
|
3423
3440
|
const backendRoutes: WriterFunction[] = []
|
|
@@ -3434,7 +3451,7 @@ export async function generateModuleRegistryApp(options: ModuleRegistryOptions):
|
|
|
3434
3451
|
let encryptionImportName: string | null = null
|
|
3435
3452
|
let integrationImportName: string | null = null
|
|
3436
3453
|
|
|
3437
|
-
const indexResolved =
|
|
3454
|
+
const indexResolved = discovered.resolve('index.ts')
|
|
3438
3455
|
if (indexResolved) {
|
|
3439
3456
|
infoImportName = `I${importIdRef.value++}_${toVar(modId)}`
|
|
3440
3457
|
const importPath = sanitizeGeneratedModuleSpecifier(indexResolved.importPath)
|
|
@@ -3450,19 +3467,19 @@ export async function generateModuleRegistryApp(options: ModuleRegistryOptions):
|
|
|
3450
3467
|
}
|
|
3451
3468
|
|
|
3452
3469
|
{
|
|
3453
|
-
const setup = resolveConventionFile(
|
|
3470
|
+
const setup = resolveConventionFile(discovered.resolve('setup.ts'), 'SETUP', modId, importIdRef, imports)
|
|
3454
3471
|
if (setup) bootstrapImports.push(buildImportStatement(`* as ${setup.importName}`, setup.importPath))
|
|
3455
3472
|
if (setup) setupImportName = setup.importName
|
|
3456
3473
|
}
|
|
3457
3474
|
|
|
3458
3475
|
{
|
|
3459
|
-
const encryption = resolveConventionFile(
|
|
3476
|
+
const encryption = resolveConventionFile(discovered.resolve('encryption.ts'), 'ENCRYPTION', modId, importIdRef, imports)
|
|
3460
3477
|
if (encryption) bootstrapImports.push(buildImportStatement(`* as ${encryption.importName}`, encryption.importPath))
|
|
3461
3478
|
if (encryption) encryptionImportName = encryption.importName
|
|
3462
3479
|
}
|
|
3463
3480
|
|
|
3464
3481
|
{
|
|
3465
|
-
const resolved =
|
|
3482
|
+
const resolved = discovered.resolve('integration.ts')
|
|
3466
3483
|
if (resolved) {
|
|
3467
3484
|
const importName = `INTEGRATION_${toVar(modId)}_${importIdRef.value++}`
|
|
3468
3485
|
imports.push(buildImportStatement(`* as ${importName}`, resolved.importPath))
|
|
@@ -3472,12 +3489,12 @@ export async function generateModuleRegistryApp(options: ModuleRegistryOptions):
|
|
|
3472
3489
|
}
|
|
3473
3490
|
|
|
3474
3491
|
{
|
|
3475
|
-
const ext = resolveConventionFile(
|
|
3492
|
+
const ext = resolveConventionFile(discovered.resolve('data/extensions.ts'), 'X', modId, importIdRef, imports, bootstrapImports)
|
|
3476
3493
|
if (ext) extensionsImportName = ext.importName
|
|
3477
3494
|
}
|
|
3478
3495
|
|
|
3479
3496
|
{
|
|
3480
|
-
const aclResolved =
|
|
3497
|
+
const aclResolved = discovered.resolve('acl.ts')
|
|
3481
3498
|
if (aclResolved) {
|
|
3482
3499
|
const importName = `ACL_${toVar(modId)}_${importIdRef.value++}`
|
|
3483
3500
|
const importPath = sanitizeGeneratedModuleSpecifier(aclResolved.importPath)
|
|
@@ -3488,19 +3505,19 @@ export async function generateModuleRegistryApp(options: ModuleRegistryOptions):
|
|
|
3488
3505
|
}
|
|
3489
3506
|
|
|
3490
3507
|
{
|
|
3491
|
-
const ce = resolveConventionFile(
|
|
3508
|
+
const ce = resolveConventionFile(discovered.resolve('ce.ts'), 'CE', modId, importIdRef, imports, bootstrapImports)
|
|
3492
3509
|
if (ce) customEntitiesImportName = ce.importName
|
|
3493
3510
|
}
|
|
3494
3511
|
|
|
3495
3512
|
{
|
|
3496
|
-
const fields = resolveConventionFile(
|
|
3513
|
+
const fields = resolveConventionFile(discovered.resolve('data/fields.ts'), 'F', modId, importIdRef, imports, bootstrapImports)
|
|
3497
3514
|
if (fields) fieldsImportName = fields.importName
|
|
3498
3515
|
}
|
|
3499
3516
|
|
|
3500
3517
|
{
|
|
3501
3518
|
const feApp = path.join(roots.appBase, 'frontend')
|
|
3502
3519
|
const fePkg = path.join(roots.pkgBase, 'frontend')
|
|
3503
|
-
const feFiles =
|
|
3520
|
+
const feFiles = discovered.frontendFiles
|
|
3504
3521
|
if (feFiles.length > 0) {
|
|
3505
3522
|
frontendRoutes.push(...await processPageFilesAst({
|
|
3506
3523
|
files: feFiles,
|
|
@@ -3520,7 +3537,7 @@ export async function generateModuleRegistryApp(options: ModuleRegistryOptions):
|
|
|
3520
3537
|
{
|
|
3521
3538
|
const beApp = path.join(roots.appBase, 'backend')
|
|
3522
3539
|
const bePkg = path.join(roots.pkgBase, 'backend')
|
|
3523
|
-
const beFiles =
|
|
3540
|
+
const beFiles = discovered.backendFiles
|
|
3524
3541
|
if (beFiles.length > 0) {
|
|
3525
3542
|
backendRoutes.push(...await processPageFilesAst({
|
|
3526
3543
|
files: beFiles,
|
|
@@ -3539,7 +3556,7 @@ export async function generateModuleRegistryApp(options: ModuleRegistryOptions):
|
|
|
3539
3556
|
|
|
3540
3557
|
const translationImports: string[] = []
|
|
3541
3558
|
translations.push(...processTranslationsAst({
|
|
3542
|
-
|
|
3559
|
+
discovered: discovered.translations,
|
|
3543
3560
|
modId,
|
|
3544
3561
|
appImportBase,
|
|
3545
3562
|
pkgImportBase: imps.pkgBase,
|
|
@@ -3549,28 +3566,12 @@ export async function generateModuleRegistryApp(options: ModuleRegistryOptions):
|
|
|
3549
3566
|
bootstrapImports.push(...translationImports)
|
|
3550
3567
|
i18nImports.push(...translationImports)
|
|
3551
3568
|
|
|
3552
|
-
subscribers.push(...await
|
|
3553
|
-
roots,
|
|
3554
|
-
modId,
|
|
3555
|
-
appImportBase,
|
|
3556
|
-
pkgImportBase: imps.pkgBase,
|
|
3557
|
-
}))
|
|
3569
|
+
subscribers.push(...processSubscribersAst(await discovered.getSubscribers()))
|
|
3558
3570
|
|
|
3559
|
-
workers.push(...await
|
|
3560
|
-
roots,
|
|
3561
|
-
modId,
|
|
3562
|
-
appImportBase,
|
|
3563
|
-
pkgImportBase: imps.pkgBase,
|
|
3564
|
-
}))
|
|
3571
|
+
workers.push(...processWorkersAst(await discovered.getWorkers()))
|
|
3565
3572
|
|
|
3566
3573
|
{
|
|
3567
|
-
|
|
3568
|
-
modId,
|
|
3569
|
-
roots,
|
|
3570
|
-
appImportBase,
|
|
3571
|
-
pkgImportBase: imps.pkgBase,
|
|
3572
|
-
})
|
|
3573
|
-
dashboardWidgetsValue = buildModuleDashboardWidgetsValue(entries)
|
|
3574
|
+
dashboardWidgetsValue = buildModuleDashboardWidgetsValue(discovered.dashboardWidgetEntries)
|
|
3574
3575
|
}
|
|
3575
3576
|
|
|
3576
3577
|
const moduleEntries: GeneratedObjectEntry[] = [
|
|
@@ -3732,7 +3733,7 @@ export async function generateModuleRegistryApp(options: ModuleRegistryOptions):
|
|
|
3732
3733
|
}
|
|
3733
3734
|
}
|
|
3734
3735
|
|
|
3735
|
-
const structureChecksum =
|
|
3736
|
+
const structureChecksum = discovery.getStructureChecksum()
|
|
3736
3737
|
writeGeneratedFile({ outFile, checksumFile, content: output, structureChecksum, result, quiet })
|
|
3737
3738
|
writeGeneratedFile({ outFile: bootstrapOutFile, checksumFile: bootstrapChecksumFile, content: bootstrapOutput, structureChecksum, result, quiet })
|
|
3738
3739
|
writeGeneratedFile({ outFile: i18nOutFile, checksumFile: i18nChecksumFile, content: i18nOutput, structureChecksum, result, quiet })
|
|
@@ -3755,8 +3756,9 @@ export async function generateModuleRegistryApp(options: ModuleRegistryOptions):
|
|
|
3755
3756
|
* features/ACL, custom entities, vector config, custom fields, dashboard widgets
|
|
3756
3757
|
* Excludes: frontend routes, backend routes, API handlers, injection widgets
|
|
3757
3758
|
*/
|
|
3758
|
-
|
|
3759
|
+
async function generateModuleRegistryCliFromDiscovery(options: ModuleRegistryRenderOptions): Promise<GeneratorResult> {
|
|
3759
3760
|
const { resolver, quiet = false } = options
|
|
3761
|
+
const { discovery } = options
|
|
3760
3762
|
const result = createGeneratorResult()
|
|
3761
3763
|
|
|
3762
3764
|
const outputDir = resolver.getOutputDir()
|
|
@@ -3767,29 +3769,17 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
3767
3769
|
const commandLoadersOutFile = path.join(outputDir, 'command-loaders.generated.ts')
|
|
3768
3770
|
const commandLoadersChecksumFile = path.join(outputDir, 'command-loaders.generated.checksum')
|
|
3769
3771
|
|
|
3770
|
-
const enabled =
|
|
3771
|
-
for (const entry of enabled) {
|
|
3772
|
-
verifyThirdPartyModuleShape(entry, resolver.getModulePaths(entry).pkgBase)
|
|
3773
|
-
}
|
|
3772
|
+
const enabled = discovery.enabled
|
|
3774
3773
|
const imports: string[] = []
|
|
3775
3774
|
const moduleDecls: WriterFunction[] = []
|
|
3776
3775
|
// Mutable ref so extracted helper functions can increment the shared counter
|
|
3777
3776
|
const importIdRef = { value: 0 }
|
|
3778
|
-
const trackedRoots = new Set<string>()
|
|
3779
3777
|
const requiresByModule = new Map<string, string[]>()
|
|
3780
3778
|
const commandLoaderEntries: CommandLoaderGenerationEntry[] = []
|
|
3781
3779
|
|
|
3782
|
-
for (const
|
|
3783
|
-
const modId =
|
|
3784
|
-
|
|
3785
|
-
const rawImps = resolver.getModuleImportBase(entry)
|
|
3786
|
-
trackedRoots.add(roots.appBase)
|
|
3787
|
-
trackedRoots.add(roots.pkgBase)
|
|
3788
|
-
|
|
3789
|
-
const isAppModule = entry.from === '@app'
|
|
3790
|
-
const appImportBase = isAppModule ? `../../src/modules/${modId}` : rawImps.appBase
|
|
3791
|
-
const imps: ModuleImports = { appBase: appImportBase, pkgBase: rawImps.pkgBase }
|
|
3792
|
-
commandLoaderEntries.push(...collectCommandLoaderEntries(roots, imps, modId))
|
|
3780
|
+
for (const discovered of discovery.modules) {
|
|
3781
|
+
const { modId, roots, imps, appImportBase } = discovered
|
|
3782
|
+
commandLoaderEntries.push(...discovered.commandLoaderEntries)
|
|
3793
3783
|
|
|
3794
3784
|
let cliImportName: string | null = null
|
|
3795
3785
|
const translations: GeneratedObjectEntry[] = []
|
|
@@ -3807,7 +3797,7 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
3807
3797
|
let integrationImportName: string | null = null
|
|
3808
3798
|
|
|
3809
3799
|
// Module metadata: index.ts (overrideable)
|
|
3810
|
-
const indexResolved =
|
|
3800
|
+
const indexResolved = discovered.resolve('index.ts')
|
|
3811
3801
|
if (indexResolved) {
|
|
3812
3802
|
infoImportName = `I${importIdRef.value++}_${toVar(modId)}`
|
|
3813
3803
|
const importPath = sanitizeGeneratedModuleSpecifier(indexResolved.importPath)
|
|
@@ -3823,19 +3813,19 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
3823
3813
|
|
|
3824
3814
|
// Module setup configuration: setup.ts
|
|
3825
3815
|
{
|
|
3826
|
-
const setup = resolveConventionFile(
|
|
3816
|
+
const setup = resolveConventionFile(discovered.resolve('setup.ts'), 'SETUP', modId, importIdRef, imports)
|
|
3827
3817
|
if (setup) setupImportName = setup.importName
|
|
3828
3818
|
}
|
|
3829
3819
|
|
|
3830
3820
|
// Module encryption defaults: encryption.ts
|
|
3831
3821
|
{
|
|
3832
|
-
const encryption = resolveConventionFile(
|
|
3822
|
+
const encryption = resolveConventionFile(discovered.resolve('encryption.ts'), 'ENCRYPTION', modId, importIdRef, imports)
|
|
3833
3823
|
if (encryption) encryptionImportName = encryption.importName
|
|
3834
3824
|
}
|
|
3835
3825
|
|
|
3836
3826
|
// Integration manifest: integration.ts
|
|
3837
3827
|
{
|
|
3838
|
-
const resolved =
|
|
3828
|
+
const resolved = discovered.resolve('integration.ts')
|
|
3839
3829
|
if (resolved) {
|
|
3840
3830
|
const importName = `INTEGRATION_${toVar(modId)}_${importIdRef.value++}`
|
|
3841
3831
|
imports.push(buildImportStatement(`* as ${importName}`, resolved.importPath))
|
|
@@ -3845,13 +3835,13 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
3845
3835
|
|
|
3846
3836
|
// Entity extensions: data/extensions.ts
|
|
3847
3837
|
{
|
|
3848
|
-
const ext = resolveConventionFile(
|
|
3838
|
+
const ext = resolveConventionFile(discovered.resolve('data/extensions.ts'), 'X', modId, importIdRef, imports)
|
|
3849
3839
|
if (ext) extensionsImportName = ext.importName
|
|
3850
3840
|
}
|
|
3851
3841
|
|
|
3852
3842
|
// RBAC: acl.ts
|
|
3853
3843
|
{
|
|
3854
|
-
const aclResolved =
|
|
3844
|
+
const aclResolved = discovered.resolve('acl.ts')
|
|
3855
3845
|
if (aclResolved) {
|
|
3856
3846
|
const importName = `ACL_${toVar(modId)}_${importIdRef.value++}`
|
|
3857
3847
|
const importPath = sanitizeGeneratedModuleSpecifier(aclResolved.importPath)
|
|
@@ -3862,25 +3852,25 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
3862
3852
|
|
|
3863
3853
|
// Custom entities: ce.ts
|
|
3864
3854
|
{
|
|
3865
|
-
const ce = resolveConventionFile(
|
|
3855
|
+
const ce = resolveConventionFile(discovered.resolve('ce.ts'), 'CE', modId, importIdRef, imports)
|
|
3866
3856
|
if (ce) customEntitiesImportName = ce.importName
|
|
3867
3857
|
}
|
|
3868
3858
|
|
|
3869
3859
|
// Vector search configuration: vector.ts
|
|
3870
3860
|
{
|
|
3871
|
-
const vec = resolveConventionFile(
|
|
3861
|
+
const vec = resolveConventionFile(discovered.resolve('vector.ts'), 'VECTOR', modId, importIdRef, imports)
|
|
3872
3862
|
if (vec) vectorImportName = vec.importName
|
|
3873
3863
|
}
|
|
3874
3864
|
|
|
3875
3865
|
// Custom fields: data/fields.ts
|
|
3876
3866
|
{
|
|
3877
|
-
const fields = resolveConventionFile(
|
|
3867
|
+
const fields = resolveConventionFile(discovered.resolve('data/fields.ts'), 'F', modId, importIdRef, imports)
|
|
3878
3868
|
if (fields) fieldsImportName = fields.importName
|
|
3879
3869
|
}
|
|
3880
3870
|
|
|
3881
3871
|
// CLI
|
|
3882
3872
|
{
|
|
3883
|
-
const cliResolved =
|
|
3873
|
+
const cliResolved = discovered.resolve('cli.ts')
|
|
3884
3874
|
if (cliResolved) {
|
|
3885
3875
|
const importName = `CLI_${toVar(modId)}`
|
|
3886
3876
|
imports.push(buildImportStatement(importName, sanitizeGeneratedModuleSpecifier(cliResolved.importPath)))
|
|
@@ -3890,7 +3880,7 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
3890
3880
|
|
|
3891
3881
|
// Translations
|
|
3892
3882
|
translations.push(...processTranslationsAst({
|
|
3893
|
-
|
|
3883
|
+
discovered: discovered.translations,
|
|
3894
3884
|
modId,
|
|
3895
3885
|
appImportBase,
|
|
3896
3886
|
pkgImportBase: imps.pkgBase,
|
|
@@ -3898,30 +3888,14 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
3898
3888
|
}))
|
|
3899
3889
|
|
|
3900
3890
|
// Subscribers
|
|
3901
|
-
subscribers.push(...await
|
|
3902
|
-
roots,
|
|
3903
|
-
modId,
|
|
3904
|
-
appImportBase,
|
|
3905
|
-
pkgImportBase: imps.pkgBase,
|
|
3906
|
-
}))
|
|
3891
|
+
subscribers.push(...processSubscribersAst(await discovered.getSubscribers()))
|
|
3907
3892
|
|
|
3908
3893
|
// Workers
|
|
3909
|
-
workers.push(...await
|
|
3910
|
-
roots,
|
|
3911
|
-
modId,
|
|
3912
|
-
appImportBase,
|
|
3913
|
-
pkgImportBase: imps.pkgBase,
|
|
3914
|
-
}))
|
|
3894
|
+
workers.push(...processWorkersAst(await discovered.getWorkers()))
|
|
3915
3895
|
|
|
3916
3896
|
// Dashboard widgets
|
|
3917
3897
|
{
|
|
3918
|
-
|
|
3919
|
-
modId,
|
|
3920
|
-
roots,
|
|
3921
|
-
appImportBase,
|
|
3922
|
-
pkgImportBase: imps.pkgBase,
|
|
3923
|
-
})
|
|
3924
|
-
dashboardWidgetsValue = buildModuleDashboardWidgetsValue(entries)
|
|
3898
|
+
dashboardWidgetsValue = buildModuleDashboardWidgetsValue(discovered.dashboardWidgetEntries)
|
|
3925
3899
|
}
|
|
3926
3900
|
|
|
3927
3901
|
const moduleEntries: GeneratedObjectEntry[] = [
|
|
@@ -4079,7 +4053,7 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
4079
4053
|
}
|
|
4080
4054
|
}
|
|
4081
4055
|
|
|
4082
|
-
const structureChecksum =
|
|
4056
|
+
const structureChecksum = discovery.getStructureChecksum()
|
|
4083
4057
|
writeGeneratedFile({ outFile, checksumFile, content: output, structureChecksum, result, quiet })
|
|
4084
4058
|
writeGeneratedFile({ outFile: legacyOutFile, checksumFile: legacyChecksumFile, content: legacyOutput, structureChecksum, result, quiet })
|
|
4085
4059
|
const commandLoadersOutput = renderCommandLoadersFile(commandLoaderEntries)
|
|
@@ -4087,3 +4061,27 @@ export async function generateModuleRegistryCli(options: ModuleRegistryOptions):
|
|
|
4087
4061
|
|
|
4088
4062
|
return result
|
|
4089
4063
|
}
|
|
4064
|
+
|
|
4065
|
+
export async function generateModuleRegistry(options: ModuleRegistryOptions): Promise<GeneratorResult> {
|
|
4066
|
+
const discovery = await createModuleRegistryDiscovery(options.resolver)
|
|
4067
|
+
return generateModuleRegistryFromDiscovery({ ...options, discovery })
|
|
4068
|
+
}
|
|
4069
|
+
|
|
4070
|
+
export async function generateModuleRegistryApp(options: ModuleRegistryOptions): Promise<GeneratorResult> {
|
|
4071
|
+
const discovery = await createModuleRegistryDiscovery(options.resolver)
|
|
4072
|
+
return generateModuleRegistryAppFromDiscovery({ ...options, discovery })
|
|
4073
|
+
}
|
|
4074
|
+
|
|
4075
|
+
export async function generateModuleRegistryCli(options: ModuleRegistryOptions): Promise<GeneratorResult> {
|
|
4076
|
+
const discovery = await createModuleRegistryDiscovery(options.resolver)
|
|
4077
|
+
return generateModuleRegistryCliFromDiscovery({ ...options, discovery })
|
|
4078
|
+
}
|
|
4079
|
+
|
|
4080
|
+
export async function generateModuleRegistries(options: ModuleRegistryOptions): Promise<GeneratorResult[]> {
|
|
4081
|
+
const discovery = await createModuleRegistryDiscovery(options.resolver)
|
|
4082
|
+
return [
|
|
4083
|
+
await generateModuleRegistryFromDiscovery({ ...options, discovery }),
|
|
4084
|
+
await generateModuleRegistryAppFromDiscovery({ ...options, discovery }),
|
|
4085
|
+
await generateModuleRegistryCliFromDiscovery({ ...options, discovery }),
|
|
4086
|
+
]
|
|
4087
|
+
}
|