@open-mercato/cli 0.6.8-develop.7032.1.70d74d4bfe → 0.6.8-develop.7037.1.ea0277b01e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agentic/guides/module-facts.json +126 -126
- package/dist/agentic/guides/module-facts.v2.json +126 -126
- package/dist/agentic/guides/modules/ai_assistant/index.md +1 -1
- package/dist/agentic/guides/modules/api_docs/index.md +1 -1
- package/dist/agentic/guides/modules/api_keys/index.md +1 -1
- package/dist/agentic/guides/modules/attachments/index.md +1 -1
- package/dist/agentic/guides/modules/audit_logs/index.md +1 -1
- package/dist/agentic/guides/modules/auth/index.md +1 -1
- package/dist/agentic/guides/modules/business_rules/index.md +1 -1
- package/dist/agentic/guides/modules/catalog/index.md +1 -1
- package/dist/agentic/guides/modules/channel_apns/index.md +1 -1
- package/dist/agentic/guides/modules/channel_expo/index.md +1 -1
- package/dist/agentic/guides/modules/channel_fcm/index.md +1 -1
- package/dist/agentic/guides/modules/channel_gmail/index.md +1 -1
- package/dist/agentic/guides/modules/channel_imap/index.md +1 -1
- package/dist/agentic/guides/modules/checkout/index.md +1 -1
- package/dist/agentic/guides/modules/communication_channels/index.md +1 -1
- package/dist/agentic/guides/modules/configs/index.md +1 -1
- package/dist/agentic/guides/modules/content/index.md +1 -1
- package/dist/agentic/guides/modules/currencies/index.md +1 -1
- package/dist/agentic/guides/modules/customer_accounts/index.md +1 -1
- package/dist/agentic/guides/modules/customers/index.md +1 -1
- package/dist/agentic/guides/modules/dashboards/index.md +1 -1
- package/dist/agentic/guides/modules/data_sync/index.md +1 -1
- package/dist/agentic/guides/modules/design_system/index.md +1 -1
- package/dist/agentic/guides/modules/devices/index.md +1 -1
- package/dist/agentic/guides/modules/dictionaries/index.md +1 -1
- package/dist/agentic/guides/modules/directory/index.md +1 -1
- package/dist/agentic/guides/modules/documents/index.md +1 -1
- package/dist/agentic/guides/modules/entities/index.md +1 -1
- package/dist/agentic/guides/modules/eudr/index.md +1 -1
- package/dist/agentic/guides/modules/events/index.md +1 -1
- package/dist/agentic/guides/modules/feature_toggles/index.md +1 -1
- package/dist/agentic/guides/modules/gateway_stripe/index.md +1 -1
- package/dist/agentic/guides/modules/generators/index.md +1 -1
- package/dist/agentic/guides/modules/inbox_ops/index.md +1 -1
- package/dist/agentic/guides/modules/integrations/index.md +1 -1
- package/dist/agentic/guides/modules/messages/index.md +1 -1
- package/dist/agentic/guides/modules/notifications/index.md +1 -1
- package/dist/agentic/guides/modules/onboarding/index.md +1 -1
- package/dist/agentic/guides/modules/payment_gateways/index.md +1 -1
- package/dist/agentic/guides/modules/perspectives/index.md +1 -1
- package/dist/agentic/guides/modules/planner/index.md +1 -1
- package/dist/agentic/guides/modules/portal/index.md +1 -1
- package/dist/agentic/guides/modules/progress/index.md +1 -1
- package/dist/agentic/guides/modules/push_notifications/index.md +1 -1
- package/dist/agentic/guides/modules/query_index/index.md +1 -1
- package/dist/agentic/guides/modules/record_locks/index.md +1 -1
- package/dist/agentic/guides/modules/resources/index.md +1 -1
- package/dist/agentic/guides/modules/sales/index.md +1 -1
- package/dist/agentic/guides/modules/scheduler/index.md +1 -1
- package/dist/agentic/guides/modules/search/index.md +1 -1
- package/dist/agentic/guides/modules/security/index.md +1 -1
- package/dist/agentic/guides/modules/shipping_carriers/index.md +1 -1
- package/dist/agentic/guides/modules/sso/index.md +1 -1
- package/dist/agentic/guides/modules/staff/index.md +1 -1
- package/dist/agentic/guides/modules/storage_s3/index.md +1 -1
- package/dist/agentic/guides/modules/sync_akeneo/index.md +1 -1
- package/dist/agentic/guides/modules/sync_excel/index.md +1 -1
- package/dist/agentic/guides/modules/system_status_overlays/index.md +1 -1
- package/dist/agentic/guides/modules/translations/index.md +1 -1
- package/dist/agentic/guides/modules/warranty_claims/index.md +1 -1
- package/dist/agentic/guides/modules/webhooks/index.md +1 -1
- package/dist/agentic/guides/modules/wms/index.md +1 -1
- package/dist/agentic/guides/modules/workflows/index.md +1 -1
- package/dist/agentic/guides/reference-module-facts.json +1 -1
- package/dist/agentic/guides/upstream/manifest.json +1 -1
- package/dist/lib/generators/ast/index.js +4 -1
- package/dist/lib/generators/ast/index.js.map +2 -2
- package/dist/lib/generators/ast/source-file.js +8 -1
- package/dist/lib/generators/ast/source-file.js.map +2 -2
- package/dist/lib/generators/ast/writers.js +9 -1
- package/dist/lib/generators/ast/writers.js.map +2 -2
- package/dist/lib/generators/module-registry.js +343 -183
- package/dist/lib/generators/module-registry.js.map +2 -2
- package/dist/lib/generators/route-manifest-shards.js +4 -1
- package/dist/lib/generators/route-manifest-shards.js.map +2 -2
- package/dist/lib/spawn.js +3 -2
- package/dist/lib/spawn.js.map +2 -2
- package/dist/lib/testing/integration.js +162 -24
- package/dist/lib/testing/integration.js.map +2 -2
- package/package.json +6 -6
- package/src/lib/__tests__/spawn.test.ts +23 -0
- package/src/lib/generators/__tests__/__snapshots__/bootstrap-registrations.test.ts.snap +14 -0
- package/src/lib/generators/__tests__/__snapshots__/command-loaders.test.ts.snap +23 -0
- package/src/lib/generators/__tests__/ast-writers-escaping.test.ts +64 -0
- package/src/lib/generators/__tests__/bootstrap-registrations.test.ts +176 -0
- package/src/lib/generators/__tests__/command-loaders.test.ts +239 -0
- package/src/lib/generators/__tests__/module-subset.test.ts +96 -72
- package/src/lib/generators/__tests__/output-snapshots.test.ts +1 -1
- package/src/lib/generators/__tests__/registry-variant-parity.test.ts +258 -0
- package/src/lib/generators/__tests__/route-manifest-shards.test.ts +15 -0
- package/src/lib/generators/__tests__/structural-contracts.test.ts +3 -3
- package/src/lib/generators/ast/index.ts +2 -1
- package/src/lib/generators/ast/source-file.ts +13 -0
- package/src/lib/generators/ast/writers.ts +26 -1
- package/src/lib/generators/module-registry.ts +417 -236
- package/src/lib/generators/route-manifest-shards.ts +8 -1
- package/src/lib/spawn.ts +5 -4
- package/src/lib/testing/__tests__/integration.test.ts +435 -0
- package/src/lib/testing/integration.ts +254 -32
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
conditionalExpression,
|
|
33
33
|
createGeneratedSourceFile,
|
|
34
34
|
elementAccess,
|
|
35
|
+
escapeGeneratedJsonLiteral,
|
|
35
36
|
returnStatement,
|
|
36
37
|
getSourceText,
|
|
37
38
|
identifier,
|
|
@@ -44,6 +45,7 @@ import {
|
|
|
44
45
|
optionalPropertyAccess,
|
|
45
46
|
parenthesized,
|
|
46
47
|
propertyAccess,
|
|
48
|
+
renderGeneratedValue,
|
|
47
49
|
spreadExpression,
|
|
48
50
|
type GeneratedObjectEntry,
|
|
49
51
|
variableStatement,
|
|
@@ -133,7 +135,7 @@ type DashboardWidgetEntry = {
|
|
|
133
135
|
importPath: string
|
|
134
136
|
}
|
|
135
137
|
|
|
136
|
-
type CommandLoaderGenerationEntry = {
|
|
138
|
+
export type CommandLoaderGenerationEntry = {
|
|
137
139
|
moduleId: string
|
|
138
140
|
key: string
|
|
139
141
|
importPath: string
|
|
@@ -159,7 +161,7 @@ type RuntimeApiMethodMetadata = {
|
|
|
159
161
|
type PageRouteGenerationResult = {
|
|
160
162
|
eagerRoutes: string[]
|
|
161
163
|
runtimeRoutes: string[]
|
|
162
|
-
manifestRoutes:
|
|
164
|
+
manifestRoutes: WriterFunction[]
|
|
163
165
|
manifestShardRoutes: RouteManifestShardEntry[]
|
|
164
166
|
metadataRoutes: RouteManifestShardEntry[]
|
|
165
167
|
routePatterns: string[]
|
|
@@ -190,7 +192,7 @@ function assertUniqueBackendRoutePattern(
|
|
|
190
192
|
type ApiRouteGenerationResult = {
|
|
191
193
|
eagerApis: string[]
|
|
192
194
|
runtimeApis: string[]
|
|
193
|
-
manifestApis:
|
|
195
|
+
manifestApis: WriterFunction[]
|
|
194
196
|
manifestShardApis: RouteManifestShardEntry[]
|
|
195
197
|
metadataApis: RouteManifestShardEntry[]
|
|
196
198
|
}
|
|
@@ -1194,11 +1196,7 @@ function requiresRuntimePageMetadataFromSourceFile(sourceFile: string): boolean
|
|
|
1194
1196
|
}
|
|
1195
1197
|
|
|
1196
1198
|
function toLiteral(value: unknown): string {
|
|
1197
|
-
return JSON.stringify(value)
|
|
1198
|
-
.replace(/</g, '\\u003c')
|
|
1199
|
-
.replace(/>/g, '\\u003e')
|
|
1200
|
-
.replace(/\u2028/g, '\\u2028')
|
|
1201
|
-
.replace(/\u2029/g, '\\u2029')
|
|
1199
|
+
return escapeGeneratedJsonLiteral(JSON.stringify(value))
|
|
1202
1200
|
}
|
|
1203
1201
|
|
|
1204
1202
|
const GENERATED_MODULE_RELATIVE_PREFIXES = ['@/', '../../src/modules/', './'] as const
|
|
@@ -1440,32 +1438,81 @@ function collectCommandLoaderEntries(
|
|
|
1440
1438
|
return entries
|
|
1441
1439
|
}
|
|
1442
1440
|
|
|
1443
|
-
function renderCommandLoadersFile(entries: CommandLoaderGenerationEntry[]): string {
|
|
1441
|
+
export function renderCommandLoadersFile(entries: CommandLoaderGenerationEntry[]): string {
|
|
1444
1442
|
const seenCommandIds = new Map<string, string>()
|
|
1445
|
-
const
|
|
1443
|
+
const loaderEntries: WriterFunction[] = []
|
|
1446
1444
|
|
|
1447
1445
|
for (const entry of entries) {
|
|
1448
|
-
const
|
|
1446
|
+
const loadValue = arrowFunction({
|
|
1447
|
+
body: importExpression(sanitizeGeneratedModuleSpecifier(entry.importPath)),
|
|
1448
|
+
})
|
|
1449
1449
|
for (const id of entry.ids) {
|
|
1450
1450
|
const previous = seenCommandIds.get(id)
|
|
1451
1451
|
if (previous && previous !== entry.key) {
|
|
1452
1452
|
throw new Error(`[generate] Duplicate command id "${id}" discovered in "${previous}" and "${entry.key}"`)
|
|
1453
1453
|
}
|
|
1454
1454
|
seenCommandIds.set(id, entry.key)
|
|
1455
|
-
|
|
1455
|
+
loaderEntries.push(objectLiteral([
|
|
1456
|
+
{ name: 'moduleId', value: entry.moduleId },
|
|
1457
|
+
{ name: 'id', value: id },
|
|
1458
|
+
{ name: 'key', value: entry.key },
|
|
1459
|
+
{ name: 'load', value: loadValue },
|
|
1460
|
+
]))
|
|
1456
1461
|
}
|
|
1457
|
-
|
|
1462
|
+
loaderEntries.push(objectLiteral([
|
|
1463
|
+
{ name: 'moduleId', value: entry.moduleId },
|
|
1464
|
+
{ name: 'key', value: entry.key },
|
|
1465
|
+
{ name: 'load', value: loadValue },
|
|
1466
|
+
]))
|
|
1458
1467
|
}
|
|
1459
1468
|
|
|
1460
|
-
|
|
1461
|
-
|
|
1469
|
+
const sourceFile = createGeneratedSourceFile('command-loaders.generated.ts')
|
|
1470
|
+
addAutoGeneratedComment(sourceFile, 'command-loaders')
|
|
1471
|
+
|
|
1472
|
+
addImportSpec(sourceFile, {
|
|
1473
|
+
moduleSpecifier: '@open-mercato/shared/lib/commands',
|
|
1474
|
+
isTypeOnly: true,
|
|
1475
|
+
namedImports: [{ name: 'CommandLoader' }],
|
|
1476
|
+
})
|
|
1477
|
+
|
|
1478
|
+
sourceFile.addVariableStatement({
|
|
1479
|
+
declarationKind: VariableDeclarationKind.Const,
|
|
1480
|
+
isExported: true,
|
|
1481
|
+
declarations: [
|
|
1482
|
+
{
|
|
1483
|
+
name: 'commandLoaderEntries',
|
|
1484
|
+
type: 'CommandLoader[]',
|
|
1485
|
+
initializer: arrayLiteral(loaderEntries, writeValue),
|
|
1486
|
+
},
|
|
1487
|
+
],
|
|
1488
|
+
})
|
|
1489
|
+
sourceFile.addExportAssignment({
|
|
1490
|
+
isExportEquals: false,
|
|
1491
|
+
expression: 'commandLoaderEntries',
|
|
1492
|
+
})
|
|
1493
|
+
|
|
1494
|
+
return getSourceText(sourceFile)
|
|
1495
|
+
}
|
|
1462
1496
|
|
|
1463
|
-
export
|
|
1464
|
-
|
|
1465
|
-
]
|
|
1497
|
+
export function renderBootstrapRegistrationsFile(options: {
|
|
1498
|
+
entryImports: string[]
|
|
1499
|
+
registrationImports: string[]
|
|
1500
|
+
calls: string[]
|
|
1501
|
+
}): string {
|
|
1502
|
+
const uniqueImports = [...new Set([...options.entryImports, ...options.registrationImports])]
|
|
1466
1503
|
|
|
1467
|
-
|
|
1468
|
-
|
|
1504
|
+
const sourceFile = createGeneratedSourceFile('bootstrap-registrations.generated.ts')
|
|
1505
|
+
addAutoGeneratedComment(sourceFile, 'registry')
|
|
1506
|
+
addImportStatements(sourceFile, uniqueImports)
|
|
1507
|
+
|
|
1508
|
+
sourceFile.addFunction({
|
|
1509
|
+
name: 'runBootstrapRegistrations',
|
|
1510
|
+
isExported: true,
|
|
1511
|
+
returnType: 'void',
|
|
1512
|
+
statements: options.calls,
|
|
1513
|
+
})
|
|
1514
|
+
|
|
1515
|
+
return getSourceText(sourceFile)
|
|
1469
1516
|
}
|
|
1470
1517
|
|
|
1471
1518
|
function serializeGeneratedImport(statement: GeneratedImportStatement): string {
|
|
@@ -1721,8 +1768,38 @@ function buildPageRouteProps(metaExpr: string, routePath: string): string {
|
|
|
1721
1768
|
return `pattern: ${toLiteral(routePath || '/')}, requireAuth: (${metaExpr})?.requireAuth, requireRoles: (${metaExpr})?.requireRoles, requireFeatures: (${metaExpr})?.requireFeatures, requireCustomerAuth: (${metaExpr})?.requireCustomerAuth, requireCustomerFeatures: (${metaExpr})?.requireCustomerFeatures, nav: (${metaExpr})?.nav, title: (${metaExpr})?.pageTitle ?? (${metaExpr})?.title, titleKey: (${metaExpr})?.pageTitleKey ?? (${metaExpr})?.titleKey, group: (${metaExpr})?.pageGroup ?? (${metaExpr})?.group, groupKey: (${metaExpr})?.pageGroupKey ?? (${metaExpr})?.groupKey, icon: (${metaExpr})?.icon, order: (${metaExpr})?.pageOrder ?? (${metaExpr})?.order, priority: (${metaExpr})?.pagePriority ?? (${metaExpr})?.priority, navHidden: (${metaExpr})?.navHidden, visible: (${metaExpr})?.visible, enabled: (${metaExpr})?.enabled, breadcrumb: (${metaExpr})?.breadcrumb, pageContext: (${metaExpr})?.pageContext, placement: (${metaExpr})?.placement`
|
|
1722
1769
|
}
|
|
1723
1770
|
|
|
1724
|
-
function buildPageRouteManifestSpread(metaExpr: string, routePath: string):
|
|
1725
|
-
return
|
|
1771
|
+
function buildPageRouteManifestSpread(metaExpr: string, routePath: string): WriterFunction {
|
|
1772
|
+
return callExpression(identifier('resolvePageRouteMetadata'), [routePath || '/', identifier(metaExpr)])
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
function buildManifestRouteLoader(importPath: string): WriterFunction {
|
|
1776
|
+
return arrowFunction({
|
|
1777
|
+
async: true,
|
|
1778
|
+
body: block((writer) => {
|
|
1779
|
+
writeStatements(writer, [
|
|
1780
|
+
variableStatement({
|
|
1781
|
+
name: 'mod',
|
|
1782
|
+
initializer: awaitExpression(importExpression(sanitizeGeneratedModuleSpecifier(importPath))),
|
|
1783
|
+
}),
|
|
1784
|
+
returnStatement(
|
|
1785
|
+
asExpression(
|
|
1786
|
+
parenthesized(nullishCoalesce([
|
|
1787
|
+
propertyAccess(identifier('mod'), 'default'),
|
|
1788
|
+
identifier('mod'),
|
|
1789
|
+
])),
|
|
1790
|
+
'any',
|
|
1791
|
+
),
|
|
1792
|
+
),
|
|
1793
|
+
])
|
|
1794
|
+
}),
|
|
1795
|
+
})
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
function buildManifestApiLoader(importPath: string): WriterFunction {
|
|
1799
|
+
return arrowFunction({
|
|
1800
|
+
async: true,
|
|
1801
|
+
body: importExpression(sanitizeGeneratedModuleSpecifier(importPath)),
|
|
1802
|
+
})
|
|
1726
1803
|
}
|
|
1727
1804
|
|
|
1728
1805
|
function normalizeBreadcrumb(raw: unknown): SerializablePageMetadata['breadcrumb'] {
|
|
@@ -2041,7 +2118,7 @@ async function processPageFiles(options: {
|
|
|
2041
2118
|
const metaPrefix = type === 'frontend' ? 'M' : 'BM'
|
|
2042
2119
|
const eagerRoutes: string[] = []
|
|
2043
2120
|
const runtimeRoutes: string[] = []
|
|
2044
|
-
const manifestRoutes:
|
|
2121
|
+
const manifestRoutes: WriterFunction[] = []
|
|
2045
2122
|
const manifestShardRoutes: RouteManifestShardEntry[] = []
|
|
2046
2123
|
const metadataRoutes: RouteManifestShardEntry[] = []
|
|
2047
2124
|
const routePatterns: string[] = []
|
|
@@ -2116,18 +2193,25 @@ async function processPageFiles(options: {
|
|
|
2116
2193
|
const manifestBaseProps = buildPageRouteManifestSpread(manifestMetaExpr, routePath)
|
|
2117
2194
|
eagerRoutes.push(`{ ${baseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`)
|
|
2118
2195
|
runtimeRoutes.push(`{ ${runtimeBaseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`)
|
|
2119
|
-
const
|
|
2120
|
-
|
|
2121
|
-
|
|
2196
|
+
const metadataEntries: GeneratedObjectEntry[] = [
|
|
2197
|
+
{ name: 'moduleId', value: modId },
|
|
2198
|
+
{ kind: 'spread', value: manifestBaseProps },
|
|
2199
|
+
]
|
|
2200
|
+
const manifestEntry = objectLiteral([
|
|
2201
|
+
...metadataEntries,
|
|
2202
|
+
{ name: 'load', value: buildManifestRouteLoader(importPath) },
|
|
2203
|
+
])
|
|
2204
|
+
const shardImports = manifestImportStatement ? [manifestImportStatement] : []
|
|
2205
|
+
manifestRoutes.push(manifestEntry)
|
|
2122
2206
|
manifestShardRoutes.push({
|
|
2123
2207
|
path: routePath,
|
|
2124
|
-
declaration:
|
|
2125
|
-
imports:
|
|
2208
|
+
declaration: renderGeneratedValue(manifestEntry),
|
|
2209
|
+
imports: shardImports,
|
|
2126
2210
|
})
|
|
2127
2211
|
metadataRoutes.push({
|
|
2128
2212
|
path: routePath,
|
|
2129
|
-
declaration:
|
|
2130
|
-
imports:
|
|
2213
|
+
declaration: renderGeneratedValue(objectLiteral(metadataEntries)),
|
|
2214
|
+
imports: shardImports,
|
|
2131
2215
|
})
|
|
2132
2216
|
routePatterns.push(routePath)
|
|
2133
2217
|
}
|
|
@@ -2207,18 +2291,25 @@ async function processPageFiles(options: {
|
|
|
2207
2291
|
const manifestBaseProps = buildPageRouteManifestSpread(manifestMetaExpr, routePath)
|
|
2208
2292
|
eagerRoutes.push(`{ ${baseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`)
|
|
2209
2293
|
runtimeRoutes.push(`{ ${runtimeBaseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`)
|
|
2210
|
-
const
|
|
2211
|
-
|
|
2212
|
-
|
|
2294
|
+
const metadataEntries: GeneratedObjectEntry[] = [
|
|
2295
|
+
{ name: 'moduleId', value: modId },
|
|
2296
|
+
{ kind: 'spread', value: manifestBaseProps },
|
|
2297
|
+
]
|
|
2298
|
+
const manifestEntry = objectLiteral([
|
|
2299
|
+
...metadataEntries,
|
|
2300
|
+
{ name: 'load', value: buildManifestRouteLoader(importPath) },
|
|
2301
|
+
])
|
|
2302
|
+
const shardImports = manifestImportStatement ? [manifestImportStatement] : []
|
|
2303
|
+
manifestRoutes.push(manifestEntry)
|
|
2213
2304
|
manifestShardRoutes.push({
|
|
2214
2305
|
path: routePath,
|
|
2215
|
-
declaration:
|
|
2216
|
-
imports:
|
|
2306
|
+
declaration: renderGeneratedValue(manifestEntry),
|
|
2307
|
+
imports: shardImports,
|
|
2217
2308
|
})
|
|
2218
2309
|
metadataRoutes.push({
|
|
2219
2310
|
path: routePath,
|
|
2220
|
-
declaration:
|
|
2221
|
-
imports:
|
|
2311
|
+
declaration: renderGeneratedValue(objectLiteral(metadataEntries)),
|
|
2312
|
+
imports: shardImports,
|
|
2222
2313
|
})
|
|
2223
2314
|
routePatterns.push(routePath)
|
|
2224
2315
|
}
|
|
@@ -2250,7 +2341,7 @@ async function processApiRoutes(options: {
|
|
|
2250
2341
|
|
|
2251
2342
|
const eagerApis: string[] = []
|
|
2252
2343
|
const runtimeApis: string[] = []
|
|
2253
|
-
const manifestApis:
|
|
2344
|
+
const manifestApis: WriterFunction[] = []
|
|
2254
2345
|
const manifestShardApis: RouteManifestShardEntry[] = []
|
|
2255
2346
|
const metadataApis: RouteManifestShardEntry[] = []
|
|
2256
2347
|
|
|
@@ -2283,11 +2374,19 @@ async function processApiRoutes(options: {
|
|
|
2283
2374
|
eagerImports.push(buildImportStatement(`* as ${importName}`, importPath))
|
|
2284
2375
|
eagerApis.push(`{ path: ((${importName} as any).metadata?.path ?? ${toLiteral(routePath)}), metadata: (${importName} as any).metadata, handlers: ${importName} as any${docsPart} }`)
|
|
2285
2376
|
runtimeApis.push(`{ path: ${toLiteral(resolvedPath)}, metadata: ${metadataLiteral}, handlers: { ${exportedMethods.map((method) => `${method}: async (req: Request, ctx?: any) => { const mod = await ${buildDynamicImportExpression(importPath)}; return (mod as any).${method}(req, ctx) }`).join(', ')} } }`)
|
|
2286
|
-
const
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2377
|
+
const metadataEntries: GeneratedObjectEntry[] = [
|
|
2378
|
+
{ name: 'moduleId', value: modId },
|
|
2379
|
+
{ name: 'kind', value: 'route-file' },
|
|
2380
|
+
{ name: 'path', value: resolvedPath },
|
|
2381
|
+
{ name: 'methods', value: arrayLiteral(exportedMethods, writeValue) },
|
|
2382
|
+
]
|
|
2383
|
+
const manifestEntry = objectLiteral([
|
|
2384
|
+
...metadataEntries,
|
|
2385
|
+
{ name: 'load', value: buildManifestApiLoader(importPath) },
|
|
2386
|
+
])
|
|
2387
|
+
manifestApis.push(manifestEntry)
|
|
2388
|
+
manifestShardApis.push({ path: resolvedPath, declaration: renderGeneratedValue(manifestEntry) })
|
|
2389
|
+
metadataApis.push({ path: resolvedPath, declaration: renderGeneratedValue(objectLiteral(metadataEntries)) })
|
|
2291
2390
|
}
|
|
2292
2391
|
|
|
2293
2392
|
// Single files (plain scripts, not route.*, not tests, skip method dirs)
|
|
@@ -2319,11 +2418,19 @@ async function processApiRoutes(options: {
|
|
|
2319
2418
|
eagerImports.push(buildImportStatement(`* as ${importName}`, importPath))
|
|
2320
2419
|
eagerApis.push(`{ path: ((${importName} as any).metadata?.path ?? ${toLiteral(routePath)}), metadata: (${importName} as any).metadata, handlers: ${importName} as any${docsPart} }`)
|
|
2321
2420
|
runtimeApis.push(`{ path: ${toLiteral(resolvedPath)}, metadata: ${metadataLiteral}, handlers: { ${exportedMethods.map((entryMethod) => `${entryMethod}: async (req: Request, ctx?: any) => { const mod = await ${buildDynamicImportExpression(importPath)}; return (mod as any).${entryMethod}(req, ctx) }`).join(', ')} } }`)
|
|
2322
|
-
const
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2421
|
+
const metadataEntries: GeneratedObjectEntry[] = [
|
|
2422
|
+
{ name: 'moduleId', value: modId },
|
|
2423
|
+
{ name: 'kind', value: 'route-file' },
|
|
2424
|
+
{ name: 'path', value: resolvedPath },
|
|
2425
|
+
{ name: 'methods', value: arrayLiteral(exportedMethods, writeValue) },
|
|
2426
|
+
]
|
|
2427
|
+
const manifestEntry = objectLiteral([
|
|
2428
|
+
...metadataEntries,
|
|
2429
|
+
{ name: 'load', value: buildManifestApiLoader(importPath) },
|
|
2430
|
+
])
|
|
2431
|
+
manifestApis.push(manifestEntry)
|
|
2432
|
+
manifestShardApis.push({ path: resolvedPath, declaration: renderGeneratedValue(manifestEntry) })
|
|
2433
|
+
metadataApis.push({ path: resolvedPath, declaration: renderGeneratedValue(objectLiteral(metadataEntries)) })
|
|
2327
2434
|
}
|
|
2328
2435
|
|
|
2329
2436
|
// Legacy per-method
|
|
@@ -2365,11 +2472,20 @@ async function processApiRoutes(options: {
|
|
|
2365
2472
|
eagerImports.push(buildImportStatement(`${importName}, * as ${metaName}`, importPath))
|
|
2366
2473
|
eagerApis.push(`{ method: ${toLiteral(method)}, path: (${metaName}.metadata?.path ?? ${toLiteral(routePath)}), handler: ${importName}, metadata: ${metaName}.metadata${docsPart} }`)
|
|
2367
2474
|
runtimeApis.push(`{ method: ${toLiteral(method)}, path: ${toLiteral(resolvedPath)}, handler: async (req: Request, ctx?: any) => { const mod = await ${buildDynamicImportExpression(importPath)}; const handler = ((mod as any).default ?? (mod as any).${method} ?? (mod as any).handler) as any; return handler(req, ctx) }, metadata: ${metadataLiteral} }`)
|
|
2368
|
-
const
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2475
|
+
const metadataEntries: GeneratedObjectEntry[] = [
|
|
2476
|
+
{ name: 'moduleId', value: modId },
|
|
2477
|
+
{ name: 'kind', value: 'legacy' },
|
|
2478
|
+
{ name: 'method', value: method },
|
|
2479
|
+
{ name: 'path', value: resolvedPath },
|
|
2480
|
+
{ name: 'methods', value: arrayLiteral([method], writeValue) },
|
|
2481
|
+
]
|
|
2482
|
+
const manifestEntry = objectLiteral([
|
|
2483
|
+
...metadataEntries,
|
|
2484
|
+
{ name: 'load', value: buildManifestApiLoader(importPath) },
|
|
2485
|
+
])
|
|
2486
|
+
manifestApis.push(manifestEntry)
|
|
2487
|
+
manifestShardApis.push({ path: resolvedPath, declaration: renderGeneratedValue(manifestEntry) })
|
|
2488
|
+
metadataApis.push({ path: resolvedPath, declaration: renderGeneratedValue(objectLiteral(metadataEntries)) })
|
|
2373
2489
|
}
|
|
2374
2490
|
}
|
|
2375
2491
|
|
|
@@ -2382,17 +2498,6 @@ async function processApiRoutes(options: {
|
|
|
2382
2498
|
}
|
|
2383
2499
|
}
|
|
2384
2500
|
|
|
2385
|
-
function processSubscribers(discovered: DiscoveredSubscriber[]): string[] {
|
|
2386
|
-
const subscribers: string[] = []
|
|
2387
|
-
for (const { id, importPath, metadata } of discovered) {
|
|
2388
|
-
const subscriberId = metadata?.id ?? id
|
|
2389
|
-
subscribers.push(
|
|
2390
|
-
`{ 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)}) }`
|
|
2391
|
-
)
|
|
2392
|
-
}
|
|
2393
|
-
return subscribers
|
|
2394
|
-
}
|
|
2395
|
-
|
|
2396
2501
|
/**
|
|
2397
2502
|
* Registry helper emitted for a worker that declares `metadata.onJobAbandoned`.
|
|
2398
2503
|
*
|
|
@@ -2406,53 +2511,6 @@ function workersDeclareAbandonHook(discovered: DiscoveredWorker[]): boolean {
|
|
|
2406
2511
|
return discovered.some(({ metadata }) => metadata.hasJobAbandonedHook === true)
|
|
2407
2512
|
}
|
|
2408
2513
|
|
|
2409
|
-
function processWorkers(discovered: DiscoveredWorker[]): string[] {
|
|
2410
|
-
const workers: string[] = []
|
|
2411
|
-
for (const { id, importPath, metadata } of discovered) {
|
|
2412
|
-
const workerId = metadata.id ?? id
|
|
2413
|
-
workers.push(
|
|
2414
|
-
`{ id: ${toLiteral(workerId)}, queue: ${toLiteral(metadata.queue)}, concurrency: ${toLiteral(metadata.concurrency ?? 1)}${metadata.lockDuration === undefined ? '' : `, lockDuration: ${toLiteral(metadata.lockDuration)}`}${metadata.maxStalledCount === undefined ? '' : `, maxStalledCount: ${toLiteral(metadata.maxStalledCount)}`}${metadata.hasJobAbandonedHook ? `, onJobAbandoned: ${ABANDON_HOOK_FACTORY}(() => ${buildDynamicImportExpression(importPath)}, ${toLiteral(workerId)})` : ''}, handler: createLazyModuleWorker(() => ${buildDynamicImportExpression(importPath)}, ${toLiteral(workerId)}) }`
|
|
2415
|
-
)
|
|
2416
|
-
}
|
|
2417
|
-
return workers
|
|
2418
|
-
}
|
|
2419
|
-
|
|
2420
|
-
function processTranslations(options: {
|
|
2421
|
-
discovered: DiscoveredTranslation[]
|
|
2422
|
-
modId: string
|
|
2423
|
-
appImportBase: string
|
|
2424
|
-
pkgImportBase: string
|
|
2425
|
-
imports: string[]
|
|
2426
|
-
extraImports?: string[]
|
|
2427
|
-
}): string[] {
|
|
2428
|
-
const { discovered, modId, appImportBase, pkgImportBase, imports, extraImports } = options
|
|
2429
|
-
const translations: string[] = []
|
|
2430
|
-
for (const { locale, coreHas, appHas } of discovered) {
|
|
2431
|
-
if (coreHas && appHas) {
|
|
2432
|
-
const cName = `T_${toVar(modId)}_${toVar(locale)}_C`
|
|
2433
|
-
const aName = `T_${toVar(modId)}_${toVar(locale)}_A`
|
|
2434
|
-
imports.push(buildImportStatement(cName, `${pkgImportBase}/i18n/${locale}.json`))
|
|
2435
|
-
imports.push(buildImportStatement(aName, `${appImportBase}/i18n/${locale}.json`))
|
|
2436
|
-
extraImports?.push(buildImportStatement(cName, `${pkgImportBase}/i18n/${locale}.json`))
|
|
2437
|
-
extraImports?.push(buildImportStatement(aName, `${appImportBase}/i18n/${locale}.json`))
|
|
2438
|
-
translations.push(
|
|
2439
|
-
`'${locale}': { ...( ${cName} as unknown as Record<string,string> ), ...( ${aName} as unknown as Record<string,string> ) }`
|
|
2440
|
-
)
|
|
2441
|
-
} else if (appHas) {
|
|
2442
|
-
const aName = `T_${toVar(modId)}_${toVar(locale)}_A`
|
|
2443
|
-
imports.push(buildImportStatement(aName, `${appImportBase}/i18n/${locale}.json`))
|
|
2444
|
-
extraImports?.push(buildImportStatement(aName, `${appImportBase}/i18n/${locale}.json`))
|
|
2445
|
-
translations.push(`'${locale}': ${aName} as unknown as Record<string,string>`)
|
|
2446
|
-
} else if (coreHas) {
|
|
2447
|
-
const cName = `T_${toVar(modId)}_${toVar(locale)}_C`
|
|
2448
|
-
imports.push(buildImportStatement(cName, `${pkgImportBase}/i18n/${locale}.json`))
|
|
2449
|
-
extraImports?.push(buildImportStatement(cName, `${pkgImportBase}/i18n/${locale}.json`))
|
|
2450
|
-
translations.push(`'${locale}': ${cName} as unknown as Record<string,string>`)
|
|
2451
|
-
}
|
|
2452
|
-
}
|
|
2453
|
-
return translations
|
|
2454
|
-
}
|
|
2455
|
-
|
|
2456
2514
|
/**
|
|
2457
2515
|
* Resolves a convention file and pushes its import + config entry to standalone arrays.
|
|
2458
2516
|
* Used for files that produce their own generated output (notifications, AI tools, events, analytics, enrichers, etc.).
|
|
@@ -2597,6 +2655,64 @@ function buildModuleDashboardWidgetsValue(entries: DashboardWidgetEntry[]): Writ
|
|
|
2597
2655
|
)
|
|
2598
2656
|
}
|
|
2599
2657
|
|
|
2658
|
+
/**
|
|
2659
|
+
* Wraps expressions that are still produced as pre-rendered strings by collaborators this
|
|
2660
|
+
* change does not convert (page routes, api handlers, dashboard widgets) so they can sit
|
|
2661
|
+
* inside an AST-built array without being re-quoted as string literals. It disappears once
|
|
2662
|
+
* those producers emit writers themselves — see the follow-up noted in the spec's Non-Goals.
|
|
2663
|
+
*/
|
|
2664
|
+
function preRenderedExpressionList(expressions: readonly string[]): WriterFunction {
|
|
2665
|
+
return arrayLiteral(expressions.map((expression) => identifier(expression)), writeValue)
|
|
2666
|
+
}
|
|
2667
|
+
|
|
2668
|
+
/**
|
|
2669
|
+
* `(X.<first> ?? X.<second>)` — the member-fallback shape the main registry path emits.
|
|
2670
|
+
* It is deliberately not `namespaceFallback`, which the app path uses: that helper walks
|
|
2671
|
+
* the members in an IIFE and treats only `!= null` as present, which is a different
|
|
2672
|
+
* expression. Converging the two is a behaviour change, not a formatting one.
|
|
2673
|
+
*/
|
|
2674
|
+
function legacyNamespaceMemberFallback(importName: string, members: readonly [string, string]): WriterFunction {
|
|
2675
|
+
return parenthesized(nullishCoalesce([
|
|
2676
|
+
propertyAccess(identifier(importName), members[0]),
|
|
2677
|
+
propertyAccess(identifier(importName), members[1]),
|
|
2678
|
+
]))
|
|
2679
|
+
}
|
|
2680
|
+
|
|
2681
|
+
function buildLegacyModuleListValue(options: {
|
|
2682
|
+
importName: string
|
|
2683
|
+
members: readonly [string, string]
|
|
2684
|
+
castType: string
|
|
2685
|
+
}): WriterFunction {
|
|
2686
|
+
return logicalOr([
|
|
2687
|
+
asExpression(legacyNamespaceMemberFallback(options.importName, options.members), options.castType),
|
|
2688
|
+
emptyArray(),
|
|
2689
|
+
])
|
|
2690
|
+
}
|
|
2691
|
+
|
|
2692
|
+
function buildLegacyModuleSetupValue(importName: string): WriterFunction {
|
|
2693
|
+
return logicalOr([
|
|
2694
|
+
legacyNamespaceMemberFallback(importName, ['default', 'setup']),
|
|
2695
|
+
identifier('undefined'),
|
|
2696
|
+
])
|
|
2697
|
+
}
|
|
2698
|
+
|
|
2699
|
+
function buildLegacyIntegrationListValue(
|
|
2700
|
+
importName: string,
|
|
2701
|
+
pluralMember: string,
|
|
2702
|
+
singularMember: string,
|
|
2703
|
+
castType: string,
|
|
2704
|
+
): WriterFunction {
|
|
2705
|
+
const singular = propertyAccess(identifier(importName), singularMember)
|
|
2706
|
+
|
|
2707
|
+
return asExpression(
|
|
2708
|
+
parenthesized(nullishCoalesce([
|
|
2709
|
+
propertyAccess(identifier(importName), pluralMember),
|
|
2710
|
+
parenthesized(conditionalExpression(singular, arrayLiteral([singular], writeValue), emptyArray())),
|
|
2711
|
+
])),
|
|
2712
|
+
castType,
|
|
2713
|
+
)
|
|
2714
|
+
}
|
|
2715
|
+
|
|
2600
2716
|
function buildModuleIntegrationListValue(
|
|
2601
2717
|
importName: string,
|
|
2602
2718
|
pluralMember: string,
|
|
@@ -2644,7 +2760,12 @@ function buildModulesInfoExpression(): WriterFunction {
|
|
|
2644
2760
|
function renderAstModuleRegistryFile(options: {
|
|
2645
2761
|
fileName: string
|
|
2646
2762
|
generator: string
|
|
2647
|
-
|
|
2763
|
+
/**
|
|
2764
|
+
* Import statements, or the structured specs generator extensions push onto the shared
|
|
2765
|
+
* import array via `processStandaloneConfig`. Both shapes reach this emitter at runtime,
|
|
2766
|
+
* so both are normalised here rather than at each call site.
|
|
2767
|
+
*/
|
|
2768
|
+
imports: GeneratedImportStatement[]
|
|
2648
2769
|
moduleEntries: WriterFunction[]
|
|
2649
2770
|
includeCreateElementImport?: boolean
|
|
2650
2771
|
includeAbandonHookImport?: boolean
|
|
@@ -2667,7 +2788,7 @@ function renderAstModuleRegistryFile(options: {
|
|
|
2667
2788
|
{ name: 'Module', isTypeOnly: true },
|
|
2668
2789
|
],
|
|
2669
2790
|
})
|
|
2670
|
-
addImportStatements(sourceFile, options.imports)
|
|
2791
|
+
addImportStatements(sourceFile, options.imports.map((entry) => serializeGeneratedImport(entry)))
|
|
2671
2792
|
|
|
2672
2793
|
sourceFile.addVariableStatement({
|
|
2673
2794
|
declarationKind: VariableDeclarationKind.Const,
|
|
@@ -2698,6 +2819,52 @@ function renderAstModuleRegistryFile(options: {
|
|
|
2698
2819
|
return getSourceText(sourceFile)
|
|
2699
2820
|
}
|
|
2700
2821
|
|
|
2822
|
+
function renderAstManifestFile(options: {
|
|
2823
|
+
fileName: string
|
|
2824
|
+
typeName: string
|
|
2825
|
+
exportName: string
|
|
2826
|
+
imports?: string[]
|
|
2827
|
+
entries: WriterFunction[]
|
|
2828
|
+
}): string {
|
|
2829
|
+
const sourceFile = createGeneratedSourceFile(options.fileName)
|
|
2830
|
+
addAutoGeneratedComment(sourceFile, 'registry')
|
|
2831
|
+
|
|
2832
|
+
const usesPageRouteMetadataHelper = options.typeName === 'FrontendRouteManifestEntry'
|
|
2833
|
+
|| options.typeName === 'BackendRouteManifestEntry'
|
|
2834
|
+
addImportSpec(sourceFile, usesPageRouteMetadataHelper
|
|
2835
|
+
? {
|
|
2836
|
+
moduleSpecifier: '@open-mercato/shared/modules/registry',
|
|
2837
|
+
namedImports: [
|
|
2838
|
+
{ name: 'resolvePageRouteMetadata' },
|
|
2839
|
+
{ name: options.typeName, isTypeOnly: true },
|
|
2840
|
+
],
|
|
2841
|
+
}
|
|
2842
|
+
: {
|
|
2843
|
+
moduleSpecifier: '@open-mercato/shared/modules/registry',
|
|
2844
|
+
isTypeOnly: true,
|
|
2845
|
+
namedImports: [{ name: options.typeName }],
|
|
2846
|
+
})
|
|
2847
|
+
addImportStatements(sourceFile, options.imports ?? [])
|
|
2848
|
+
|
|
2849
|
+
sourceFile.addVariableStatement({
|
|
2850
|
+
declarationKind: VariableDeclarationKind.Const,
|
|
2851
|
+
isExported: true,
|
|
2852
|
+
declarations: [
|
|
2853
|
+
{
|
|
2854
|
+
name: options.exportName,
|
|
2855
|
+
type: `${options.typeName}[]`,
|
|
2856
|
+
initializer: arrayLiteral(options.entries, writeValue),
|
|
2857
|
+
},
|
|
2858
|
+
],
|
|
2859
|
+
})
|
|
2860
|
+
sourceFile.addExportAssignment({
|
|
2861
|
+
isExportEquals: false,
|
|
2862
|
+
expression: options.exportName,
|
|
2863
|
+
})
|
|
2864
|
+
|
|
2865
|
+
return getSourceText(sourceFile)
|
|
2866
|
+
}
|
|
2867
|
+
|
|
2701
2868
|
function renderAstLegacyAliasFile(options: {
|
|
2702
2869
|
fileName: string
|
|
2703
2870
|
exportName: string
|
|
@@ -2761,70 +2928,10 @@ function renderEnabledModuleIdsFile(moduleIds: readonly string[]): string {
|
|
|
2761
2928
|
return getSourceText(sourceFile)
|
|
2762
2929
|
}
|
|
2763
2930
|
|
|
2764
|
-
function renderLegacyCompatibleArray(entries: readonly string[]): string {
|
|
2765
|
-
return `[
|
|
2766
|
-
${entries.join(',\n ')}
|
|
2767
|
-
]`
|
|
2768
|
-
}
|
|
2769
|
-
|
|
2770
2931
|
function buildLazyRouteComponentExpression(importPath: string): string {
|
|
2771
2932
|
return `async (props: any) => { const mod = await ${buildDynamicImportExpression(importPath)}; const Component = (mod.default ?? mod) as any; return createElement(Component, props) }`
|
|
2772
2933
|
}
|
|
2773
2934
|
|
|
2774
|
-
function renderAstLegacyModuleRegistryOutput(options: {
|
|
2775
|
-
fileName: string
|
|
2776
|
-
imports: GeneratedImportStatement[]
|
|
2777
|
-
moduleEntries: string[]
|
|
2778
|
-
includeCreateElementImport?: boolean
|
|
2779
|
-
includeAbandonHookImport?: boolean
|
|
2780
|
-
}): string {
|
|
2781
|
-
// Derived from what is actually being written, not from a flag the caller has to remember: an
|
|
2782
|
-
// import that must be opted into at every render site produces a file referencing an undeclared
|
|
2783
|
-
// name the first time someone forgets, and the file only fails at `build:app`.
|
|
2784
|
-
const needsAbandonHookImport = options.includeAbandonHookImport
|
|
2785
|
-
|| options.moduleEntries.some((entry) => entry.includes(ABANDON_HOOK_FACTORY))
|
|
2786
|
-
const importSection = [
|
|
2787
|
-
...(options.includeCreateElementImport ? ["import { createElement } from 'react'"] : []),
|
|
2788
|
-
needsAbandonHookImport
|
|
2789
|
-
? "import { createLazyModuleSubscriber, createLazyModuleWorker, createLazyModuleWorkerAbandonHook, type Module } from '@open-mercato/shared/modules/registry'"
|
|
2790
|
-
: "import { createLazyModuleSubscriber, createLazyModuleWorker, type Module } from '@open-mercato/shared/modules/registry'",
|
|
2791
|
-
...options.imports.map((entry) => serializeGeneratedImport(entry)),
|
|
2792
|
-
].join('\n')
|
|
2793
|
-
|
|
2794
|
-
return `// AUTO-GENERATED by mercato generate registry
|
|
2795
|
-
${importSection}
|
|
2796
|
-
|
|
2797
|
-
export const modules: Module[] = ${renderLegacyCompatibleArray(options.moduleEntries)}
|
|
2798
|
-
export const modulesInfo = modules.map(m => ({ id: m.id, ...(m.info || {}) }))
|
|
2799
|
-
export default modules
|
|
2800
|
-
`
|
|
2801
|
-
}
|
|
2802
|
-
|
|
2803
|
-
function renderAstLegacyManifestOutput(options: {
|
|
2804
|
-
fileName: string
|
|
2805
|
-
typeName: string
|
|
2806
|
-
exportName: string
|
|
2807
|
-
imports?: GeneratedImportStatement[]
|
|
2808
|
-
entries: string[]
|
|
2809
|
-
}): string {
|
|
2810
|
-
const usesPageRouteMetadataHelper = options.typeName === 'FrontendRouteManifestEntry'
|
|
2811
|
-
|| options.typeName === 'BackendRouteManifestEntry'
|
|
2812
|
-
const importSection = [
|
|
2813
|
-
usesPageRouteMetadataHelper
|
|
2814
|
-
? `import { resolvePageRouteMetadata, type ${options.typeName} } from '@open-mercato/shared/modules/registry'`
|
|
2815
|
-
: `import type { ${options.typeName} } from '@open-mercato/shared/modules/registry'`,
|
|
2816
|
-
...(options.imports ?? []).map((entry) => serializeGeneratedImport(entry)),
|
|
2817
|
-
].join('\n')
|
|
2818
|
-
|
|
2819
|
-
return `// AUTO-GENERATED by mercato generate registry
|
|
2820
|
-
${importSection}
|
|
2821
|
-
|
|
2822
|
-
export const ${options.exportName}: ${options.typeName}[] = ${renderLegacyCompatibleArray(options.entries)}
|
|
2823
|
-
|
|
2824
|
-
export default ${options.exportName}
|
|
2825
|
-
`
|
|
2826
|
-
}
|
|
2827
|
-
|
|
2828
2935
|
function buildRuntimeRouteComponent(importPath: string): WriterFunction {
|
|
2829
2936
|
return arrowFunction({
|
|
2830
2937
|
async: true,
|
|
@@ -3469,11 +3576,11 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3469
3576
|
const runtimeImports: string[] = []
|
|
3470
3577
|
const frontendRouteManifestImports: string[] = []
|
|
3471
3578
|
const backendRouteManifestImports: string[] = []
|
|
3472
|
-
const moduleDecls:
|
|
3473
|
-
const runtimeModuleDecls:
|
|
3474
|
-
const frontendRouteManifestDecls:
|
|
3475
|
-
const backendRouteManifestDecls:
|
|
3476
|
-
const apiRouteManifestDecls:
|
|
3579
|
+
const moduleDecls: WriterFunction[] = []
|
|
3580
|
+
const runtimeModuleDecls: WriterFunction[] = []
|
|
3581
|
+
const frontendRouteManifestDecls: WriterFunction[] = []
|
|
3582
|
+
const backendRouteManifestDecls: WriterFunction[] = []
|
|
3583
|
+
const apiRouteManifestDecls: WriterFunction[] = []
|
|
3477
3584
|
const backendRouteShardEntries: RouteManifestShardEntry[] = []
|
|
3478
3585
|
const backendRouteMetadataEntries: RouteManifestShardEntry[] = []
|
|
3479
3586
|
const apiRouteShardEntries: RouteManifestShardEntry[] = []
|
|
@@ -3506,9 +3613,9 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3506
3613
|
const runtimeBackendRoutes: string[] = []
|
|
3507
3614
|
const runtimeApis: string[] = []
|
|
3508
3615
|
let cliImportName: string | null = null
|
|
3509
|
-
const translations:
|
|
3510
|
-
const subscribers:
|
|
3511
|
-
const workers:
|
|
3616
|
+
const translations: GeneratedObjectEntry[] = []
|
|
3617
|
+
const subscribers: WriterFunction[] = []
|
|
3618
|
+
const workers: WriterFunction[] = []
|
|
3512
3619
|
let infoImportName: string | null = null
|
|
3513
3620
|
let extensionsImportName: string | null = null
|
|
3514
3621
|
let fieldsImportName: string | null = null
|
|
@@ -3722,7 +3829,7 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3722
3829
|
}
|
|
3723
3830
|
|
|
3724
3831
|
// 16. Translations
|
|
3725
|
-
translations.push(...
|
|
3832
|
+
translations.push(...processTranslationsAst({
|
|
3726
3833
|
discovered: discovered.translations,
|
|
3727
3834
|
modId,
|
|
3728
3835
|
appImportBase,
|
|
@@ -3732,12 +3839,12 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3732
3839
|
}))
|
|
3733
3840
|
|
|
3734
3841
|
// 17. Subscribers
|
|
3735
|
-
subscribers.push(...
|
|
3842
|
+
subscribers.push(...processSubscribersAst(await discovered.getSubscribers()))
|
|
3736
3843
|
|
|
3737
3844
|
// 18. Workers
|
|
3738
3845
|
const discoveredWorkersForModule = await discovered.getWorkers()
|
|
3739
3846
|
if (workersDeclareAbandonHook(discoveredWorkersForModule)) hasAbandonHookWorkers = true
|
|
3740
|
-
workers.push(...
|
|
3847
|
+
workers.push(...processWorkersAst(discoveredWorkersForModule))
|
|
3741
3848
|
|
|
3742
3849
|
// Build combined customFieldSets expression
|
|
3743
3850
|
{
|
|
@@ -3760,44 +3867,120 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3760
3867
|
}
|
|
3761
3868
|
}
|
|
3762
3869
|
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3870
|
+
const identityEntries: GeneratedObjectEntry[] = [{ name: 'id', value: modId }]
|
|
3871
|
+
if (infoImportName) {
|
|
3872
|
+
identityEntries.push({ name: 'info', value: propertyAccess(identifier(infoImportName), 'metadata') })
|
|
3873
|
+
}
|
|
3874
|
+
|
|
3875
|
+
const sharedTailEntries: GeneratedObjectEntry[] = []
|
|
3876
|
+
if (translations.length > 0) {
|
|
3877
|
+
sharedTailEntries.push({ name: 'translations', value: objectLiteral(translations) })
|
|
3878
|
+
}
|
|
3879
|
+
if (subscribers.length > 0) {
|
|
3880
|
+
sharedTailEntries.push({ name: 'subscribers', value: arrayLiteral(subscribers, writeValue) })
|
|
3881
|
+
}
|
|
3882
|
+
if (workers.length > 0) {
|
|
3883
|
+
sharedTailEntries.push({ name: 'workers', value: arrayLiteral(workers, writeValue) })
|
|
3884
|
+
}
|
|
3885
|
+
if (extensionsImportName) {
|
|
3886
|
+
sharedTailEntries.push({
|
|
3887
|
+
name: 'entityExtensions',
|
|
3888
|
+
value: buildLegacyModuleListValue({
|
|
3889
|
+
importName: extensionsImportName,
|
|
3890
|
+
members: ['default', 'extensions'],
|
|
3891
|
+
castType: "import('@open-mercato/shared/modules/entities').EntityExtension[]",
|
|
3892
|
+
}),
|
|
3893
|
+
})
|
|
3894
|
+
}
|
|
3895
|
+
sharedTailEntries.push({ name: 'customFieldSets', value: identifier(customFieldSetsExpr) })
|
|
3896
|
+
if (featuresImportName) {
|
|
3897
|
+
sharedTailEntries.push({
|
|
3898
|
+
name: 'features',
|
|
3899
|
+
value: buildLegacyModuleListValue({
|
|
3900
|
+
importName: featuresImportName,
|
|
3901
|
+
members: ['default', 'features'],
|
|
3902
|
+
castType: 'any',
|
|
3903
|
+
}),
|
|
3904
|
+
})
|
|
3905
|
+
}
|
|
3906
|
+
if (customEntitiesImportName) {
|
|
3907
|
+
sharedTailEntries.push({
|
|
3908
|
+
name: 'customEntities',
|
|
3909
|
+
value: buildLegacyModuleListValue({
|
|
3910
|
+
importName: customEntitiesImportName,
|
|
3911
|
+
members: ['default', 'entities'],
|
|
3912
|
+
castType: 'any',
|
|
3913
|
+
}),
|
|
3914
|
+
})
|
|
3915
|
+
}
|
|
3916
|
+
|
|
3917
|
+
const setupAndBeyondEntries: GeneratedObjectEntry[] = []
|
|
3918
|
+
if (setupImportName) {
|
|
3919
|
+
setupAndBeyondEntries.push({ name: 'setup', value: buildLegacyModuleSetupValue(setupImportName) })
|
|
3920
|
+
}
|
|
3921
|
+
if (encryptionImportName) {
|
|
3922
|
+
setupAndBeyondEntries.push({
|
|
3923
|
+
name: 'defaultEncryptionMaps',
|
|
3924
|
+
value: buildLegacyModuleListValue({
|
|
3925
|
+
importName: encryptionImportName,
|
|
3926
|
+
members: ['default', 'defaultEncryptionMaps'],
|
|
3927
|
+
castType: "import('@open-mercato/shared/modules/encryption').ModuleEncryptionMap[]",
|
|
3928
|
+
}),
|
|
3929
|
+
})
|
|
3930
|
+
}
|
|
3931
|
+
if (integrationExports) {
|
|
3932
|
+
setupAndBeyondEntries.push({
|
|
3933
|
+
name: 'integrations',
|
|
3934
|
+
value: buildLegacyIntegrationListValue(
|
|
3935
|
+
integrationExports,
|
|
3936
|
+
'integrations',
|
|
3937
|
+
'integration',
|
|
3938
|
+
"import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition[]",
|
|
3939
|
+
),
|
|
3940
|
+
})
|
|
3941
|
+
setupAndBeyondEntries.push({
|
|
3942
|
+
name: 'bundles',
|
|
3943
|
+
value: buildLegacyIntegrationListValue(
|
|
3944
|
+
integrationExports,
|
|
3945
|
+
'bundles',
|
|
3946
|
+
'bundle',
|
|
3947
|
+
"import('@open-mercato/shared/modules/integrations/types').IntegrationBundle[]",
|
|
3948
|
+
),
|
|
3949
|
+
})
|
|
3950
|
+
}
|
|
3951
|
+
|
|
3952
|
+
const eagerEntries: GeneratedObjectEntry[] = [...identityEntries]
|
|
3953
|
+
if (frontendRoutes.length > 0) {
|
|
3954
|
+
eagerEntries.push({ name: 'frontendRoutes', value: preRenderedExpressionList(frontendRoutes) })
|
|
3955
|
+
}
|
|
3956
|
+
if (backendRoutes.length > 0) {
|
|
3957
|
+
eagerEntries.push({ name: 'backendRoutes', value: preRenderedExpressionList(backendRoutes) })
|
|
3958
|
+
}
|
|
3959
|
+
if (apis.length > 0) {
|
|
3960
|
+
eagerEntries.push({ name: 'apis', value: preRenderedExpressionList(apis) })
|
|
3961
|
+
}
|
|
3962
|
+
if (cliImportName) {
|
|
3963
|
+
eagerEntries.push({ name: 'cli', value: identifier(cliImportName) })
|
|
3964
|
+
}
|
|
3965
|
+
eagerEntries.push(...sharedTailEntries)
|
|
3966
|
+
if (dashboardWidgets.length > 0) {
|
|
3967
|
+
eagerEntries.push({ name: 'dashboardWidgets', value: preRenderedExpressionList(dashboardWidgets) })
|
|
3968
|
+
}
|
|
3969
|
+
eagerEntries.push(...setupAndBeyondEntries)
|
|
3970
|
+
moduleDecls.push(objectLiteral(eagerEntries))
|
|
3971
|
+
|
|
3972
|
+
const runtimeEntries: GeneratedObjectEntry[] = [...identityEntries]
|
|
3973
|
+
if (runtimeFrontendRoutes.length > 0) {
|
|
3974
|
+
runtimeEntries.push({ name: 'frontendRoutes', value: preRenderedExpressionList(runtimeFrontendRoutes) })
|
|
3975
|
+
}
|
|
3976
|
+
if (runtimeBackendRoutes.length > 0) {
|
|
3977
|
+
runtimeEntries.push({ name: 'backendRoutes', value: preRenderedExpressionList(runtimeBackendRoutes) })
|
|
3978
|
+
}
|
|
3979
|
+
if (runtimeApis.length > 0) {
|
|
3980
|
+
runtimeEntries.push({ name: 'apis', value: preRenderedExpressionList(runtimeApis) })
|
|
3981
|
+
}
|
|
3982
|
+
runtimeEntries.push(...sharedTailEntries, ...setupAndBeyondEntries)
|
|
3983
|
+
runtimeModuleDecls.push(objectLiteral(runtimeEntries))
|
|
3801
3984
|
}
|
|
3802
3985
|
|
|
3803
3986
|
// === UMES Conflict Detection ===
|
|
@@ -3898,35 +4081,37 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3898
4081
|
}
|
|
3899
4082
|
}
|
|
3900
4083
|
|
|
3901
|
-
const output =
|
|
4084
|
+
const output = renderAstModuleRegistryFile({
|
|
3902
4085
|
fileName: 'modules.generated.ts',
|
|
4086
|
+
generator: 'registry',
|
|
3903
4087
|
imports,
|
|
3904
4088
|
moduleEntries: moduleDecls,
|
|
3905
4089
|
includeCreateElementImport: hasRouteComponents,
|
|
3906
4090
|
includeAbandonHookImport: hasAbandonHookWorkers,
|
|
3907
4091
|
})
|
|
3908
|
-
const runtimeOutput =
|
|
4092
|
+
const runtimeOutput = renderAstModuleRegistryFile({
|
|
3909
4093
|
fileName: 'modules.runtime.generated.ts',
|
|
4094
|
+
generator: 'registry',
|
|
3910
4095
|
imports: runtimeImports,
|
|
3911
4096
|
moduleEntries: runtimeModuleDecls,
|
|
3912
4097
|
includeCreateElementImport: true,
|
|
3913
4098
|
includeAbandonHookImport: hasAbandonHookWorkers,
|
|
3914
4099
|
})
|
|
3915
|
-
const frontendRoutesOutput =
|
|
4100
|
+
const frontendRoutesOutput = renderAstManifestFile({
|
|
3916
4101
|
fileName: 'frontend-routes.generated.ts',
|
|
3917
4102
|
typeName: 'FrontendRouteManifestEntry',
|
|
3918
4103
|
exportName: 'frontendRoutes',
|
|
3919
4104
|
imports: frontendRouteManifestImports,
|
|
3920
4105
|
entries: frontendRouteManifestDecls,
|
|
3921
4106
|
})
|
|
3922
|
-
const backendRoutesOutput =
|
|
4107
|
+
const backendRoutesOutput = renderAstManifestFile({
|
|
3923
4108
|
fileName: 'backend-routes.generated.ts',
|
|
3924
4109
|
typeName: 'BackendRouteManifestEntry',
|
|
3925
4110
|
exportName: 'backendRoutes',
|
|
3926
4111
|
imports: backendRouteManifestImports,
|
|
3927
4112
|
entries: backendRouteManifestDecls,
|
|
3928
4113
|
})
|
|
3929
|
-
const apiRoutesOutput =
|
|
4114
|
+
const apiRoutesOutput = renderAstManifestFile({
|
|
3930
4115
|
fileName: 'api-routes.generated.ts',
|
|
3931
4116
|
typeName: 'ApiRouteManifestEntry',
|
|
3932
4117
|
exportName: 'apiRoutes',
|
|
@@ -4066,15 +4251,11 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
4066
4251
|
allRegImports.push(...reg.registrationImports)
|
|
4067
4252
|
allCalls.push(reg.buildCall(reg.entriesExportName))
|
|
4068
4253
|
}
|
|
4069
|
-
const
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
export function runBootstrapRegistrations(): void {
|
|
4075
|
-
${body}
|
|
4076
|
-
}
|
|
4077
|
-
`
|
|
4254
|
+
const bootstrapRegsOutput = renderBootstrapRegistrationsFile({
|
|
4255
|
+
entryImports: allEntryImports,
|
|
4256
|
+
registrationImports: allRegImports,
|
|
4257
|
+
calls: allCalls,
|
|
4258
|
+
})
|
|
4078
4259
|
writeGeneratedFile({ outFile: bootstrapRegsOutFile, checksumFile: bootstrapRegsChecksumFile, content: bootstrapRegsOutput, structureChecksum, result, quiet })
|
|
4079
4260
|
}
|
|
4080
4261
|
|