@open-mercato/cli 0.6.8-develop.7099.1.7ba2771d06 → 0.7.0
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 +1 -7
- package/dist/agentic/guides/module-facts.json +598 -5508
- package/dist/agentic/guides/module-facts.v2.json +598 -5594
- 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/exact-override-targets.md +0 -1
- package/dist/agentic/guides/modules/api_keys/index.md +2 -4
- package/dist/agentic/guides/modules/attachments/di-registrations-rich.md +5 -6
- package/dist/agentic/guides/modules/attachments/di-service-tokens.md +4 -5
- package/dist/agentic/guides/modules/attachments/exact-override-targets.md +5 -6
- package/dist/agentic/guides/modules/attachments/index.md +2 -2
- package/dist/agentic/guides/modules/audit_logs/index.md +1 -1
- package/dist/agentic/guides/modules/auth/di-registrations-rich.md +2 -3
- package/dist/agentic/guides/modules/auth/di-service-tokens.md +2 -3
- package/dist/agentic/guides/modules/auth/exact-override-targets.md +2 -3
- 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/incoming-installed-contributions.md +0 -3
- package/dist/agentic/guides/modules/catalog/index.md +2 -2
- 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/di-registrations-rich.md +8 -9
- package/dist/agentic/guides/modules/communication_channels/exact-override-targets.md +8 -9
- package/dist/agentic/guides/modules/communication_channels/incoming-installed-contributions.md +0 -2
- package/dist/agentic/guides/modules/communication_channels/index.md +3 -3
- 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/active-extension-bindings.md +3 -6
- package/dist/agentic/guides/modules/customers/contribution-resolutions.md +0 -1
- package/dist/agentic/guides/modules/customers/events.md +1 -2
- package/dist/agentic/guides/modules/customers/incoming-installed-contributions.md +0 -7
- package/dist/agentic/guides/modules/customers/index.md +4 -4
- package/dist/agentic/guides/modules/customers/umes-contributions.md +0 -1
- package/dist/agentic/guides/modules/customers/umes-hosts.md +0 -1
- package/dist/agentic/guides/modules/dashboards/index.md +1 -1
- package/dist/agentic/guides/modules/data_sync/exact-override-targets.md +2 -2
- package/dist/agentic/guides/modules/data_sync/index.md +1 -1
- package/dist/agentic/guides/modules/data_sync/workers.md +2 -2
- 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/exact-override-targets.md +0 -2
- package/dist/agentic/guides/modules/directory/index.md +3 -5
- 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/exact-override-targets.md +1 -1
- package/dist/agentic/guides/modules/gateway_stripe/index.md +1 -1
- package/dist/agentic/guides/modules/gateway_stripe/workers.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/active-extension-bindings.md +0 -1
- package/dist/agentic/guides/modules/sales/contribution-resolutions.md +0 -1
- package/dist/agentic/guides/modules/sales/exact-override-targets.md +4 -5
- package/dist/agentic/guides/modules/sales/host-extension-points.md +1 -1
- package/dist/agentic/guides/modules/sales/incoming-installed-contributions.md +0 -2
- package/dist/agentic/guides/modules/sales/index.md +3 -3
- package/dist/agentic/guides/modules/sales/setup.md +1 -1
- package/dist/agentic/guides/modules/sales/umes-contributions.md +0 -1
- package/dist/agentic/guides/modules/sales/umes-diagnostics.md +0 -1
- package/dist/agentic/guides/modules/sales/umes-hosts.md +0 -9
- package/dist/agentic/guides/modules/scheduler/cli-commands.md +0 -1
- package/dist/agentic/guides/modules/scheduler/exact-override-targets.md +1 -3
- package/dist/agentic/guides/modules/scheduler/index.md +2 -2
- package/dist/agentic/guides/modules/scheduler/workers.md +1 -2
- 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/security/owned-contract-module-metadata.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 +2 -2
- package/dist/agentic/guides/reference-modules/example/index.md +1 -1
- package/dist/agentic/guides/upstream/manifest.json +1 -1
- package/dist/agentic/shared/AGENTS.md.template +3 -3
- package/dist/agentic/shared/ai/harness/README.md +2 -2
- package/dist/agentic/shared/ai/harness/RELEASE.md +6 -8
- package/dist/agentic/shared/ai/harness/cases.json +0 -83
- package/dist/agentic/shared/ai/harness/cases.schema.json +4 -4
- package/dist/agentic/shared/ai/harness/validators.json +1 -1
- package/dist/agentic/shared/ai/skills/om-auto-upgrade-0.6.7-to-0.7.0/SKILL.md +12 -3
- package/dist/agentic/shared/scripts/run-agent-harness-release.mjs +11 -37
- package/dist/lib/generators/ast/index.js +1 -4
- package/dist/lib/generators/ast/index.js.map +2 -2
- package/dist/lib/generators/ast/source-file.js +1 -8
- package/dist/lib/generators/ast/source-file.js.map +2 -2
- package/dist/lib/generators/ast/writers.js +1 -9
- package/dist/lib/generators/ast/writers.js.map +2 -2
- package/dist/lib/generators/module-registry.js +189 -424
- package/dist/lib/generators/module-registry.js.map +2 -2
- package/dist/lib/generators/route-manifest-shards.js +1 -4
- package/dist/lib/generators/route-manifest-shards.js.map +2 -2
- package/dist/lib/spawn.js +2 -3
- package/dist/lib/spawn.js.map +2 -2
- package/dist/lib/testing/integration.js +24 -162
- package/dist/lib/testing/integration.js.map +2 -2
- package/dist/mercato.js +0 -14
- package/dist/mercato.js.map +2 -2
- package/package.json +7 -8
- package/src/lib/__tests__/spawn.test.ts +0 -23
- package/src/lib/generators/__tests__/metadata-extraction.test.ts +0 -44
- package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +8 -32
- package/src/lib/generators/__tests__/module-facts.customers.fixture.test.ts +1 -4
- package/src/lib/generators/__tests__/module-facts.extension-hosts.test.ts +1 -1
- package/src/lib/generators/__tests__/module-subset.test.ts +72 -96
- package/src/lib/generators/__tests__/output-snapshots.test.ts +1 -1
- package/src/lib/generators/__tests__/route-manifest-shards.test.ts +0 -15
- package/src/lib/generators/__tests__/structural-contracts.test.ts +3 -7
- package/src/lib/generators/ast/index.ts +1 -2
- package/src/lib/generators/ast/source-file.ts +0 -13
- package/src/lib/generators/ast/writers.ts +1 -26
- package/src/lib/generators/module-registry.ts +227 -534
- package/src/lib/generators/route-manifest-shards.ts +1 -8
- package/src/lib/spawn.ts +4 -5
- package/src/lib/testing/__tests__/integration.test.ts +0 -435
- package/src/lib/testing/integration.ts +32 -254
- package/src/mercato.ts +0 -27
- package/dist/agentic/guides/modules/api_keys/di-registrations-rich.md +0 -11
- package/dist/agentic/guides/modules/api_keys/di-service-tokens.md +0 -11
- package/dist/agentic/guides/modules/channel_discord/acl-features.md +0 -13
- package/dist/agentic/guides/modules/channel_discord/ai-agents.md +0 -11
- package/dist/agentic/guides/modules/channel_discord/backend-pages.md +0 -11
- package/dist/agentic/guides/modules/channel_discord/cli-commands.md +0 -13
- package/dist/agentic/guides/modules/channel_discord/contribution-resolutions.md +0 -14
- package/dist/agentic/guides/modules/channel_discord/di-registrations-rich.md +0 -12
- package/dist/agentic/guides/modules/channel_discord/exact-override-targets.md +0 -26
- package/dist/agentic/guides/modules/channel_discord/index.md +0 -22
- package/dist/agentic/guides/modules/channel_discord/owned-contract-module-metadata.md +0 -11
- package/dist/agentic/guides/modules/channel_discord/setup.md +0 -11
- package/dist/agentic/guides/modules/channel_discord/umes-contributions.md +0 -14
- package/dist/agentic/guides/modules/channel_discord/workers.md +0 -12
- package/dist/agentic/guides/modules/directory/di-registrations-rich.md +0 -12
- package/dist/agentic/guides/modules/directory/di-service-tokens.md +0 -12
- package/dist/agentic/guides/modules/documents/acl-features.md +0 -17
- package/dist/agentic/guides/modules/documents/backend-pages.md +0 -13
- package/dist/agentic/guides/modules/documents/contribution-resolutions.md +0 -27
- package/dist/agentic/guides/modules/documents/di-registrations-rich.md +0 -21
- package/dist/agentic/guides/modules/documents/domain-commands.md +0 -37
- package/dist/agentic/guides/modules/documents/encryption.md +0 -11
- package/dist/agentic/guides/modules/documents/entities.md +0 -21
- package/dist/agentic/guides/modules/documents/events.md +0 -25
- package/dist/agentic/guides/modules/documents/exact-override-targets.md +0 -39
- package/dist/agentic/guides/modules/documents/index.md +0 -25
- package/dist/agentic/guides/modules/documents/notifications.md +0 -13
- package/dist/agentic/guides/modules/documents/owned-contract-module-metadata.md +0 -11
- package/dist/agentic/guides/modules/documents/setup.md +0 -11
- package/dist/agentic/guides/modules/documents/umes-contributions.md +0 -27
- package/dist/agentic/guides/modules/documents/umes-hosts.md +0 -36
- package/src/__tests__/resolve-queue-abandon-hook.test.ts +0 -39
- package/src/lib/generators/__tests__/__snapshots__/bootstrap-registrations.test.ts.snap +0 -14
- package/src/lib/generators/__tests__/__snapshots__/command-loaders.test.ts.snap +0 -23
- package/src/lib/generators/__tests__/ast-writers-escaping.test.ts +0 -64
- package/src/lib/generators/__tests__/bootstrap-registrations.test.ts +0 -176
- package/src/lib/generators/__tests__/command-loaders.test.ts +0 -239
- package/src/lib/generators/__tests__/generated-registry-imports.test.ts +0 -128
- package/src/lib/generators/__tests__/registry-variant-parity.test.ts +0 -258
|
@@ -32,7 +32,6 @@ import {
|
|
|
32
32
|
conditionalExpression,
|
|
33
33
|
createGeneratedSourceFile,
|
|
34
34
|
elementAccess,
|
|
35
|
-
escapeGeneratedJsonLiteral,
|
|
36
35
|
returnStatement,
|
|
37
36
|
getSourceText,
|
|
38
37
|
identifier,
|
|
@@ -45,7 +44,6 @@ import {
|
|
|
45
44
|
optionalPropertyAccess,
|
|
46
45
|
parenthesized,
|
|
47
46
|
propertyAccess,
|
|
48
|
-
renderGeneratedValue,
|
|
49
47
|
spreadExpression,
|
|
50
48
|
type GeneratedObjectEntry,
|
|
51
49
|
variableStatement,
|
|
@@ -135,7 +133,7 @@ type DashboardWidgetEntry = {
|
|
|
135
133
|
importPath: string
|
|
136
134
|
}
|
|
137
135
|
|
|
138
|
-
|
|
136
|
+
type CommandLoaderGenerationEntry = {
|
|
139
137
|
moduleId: string
|
|
140
138
|
key: string
|
|
141
139
|
importPath: string
|
|
@@ -161,7 +159,7 @@ type RuntimeApiMethodMetadata = {
|
|
|
161
159
|
type PageRouteGenerationResult = {
|
|
162
160
|
eagerRoutes: string[]
|
|
163
161
|
runtimeRoutes: string[]
|
|
164
|
-
manifestRoutes:
|
|
162
|
+
manifestRoutes: string[]
|
|
165
163
|
manifestShardRoutes: RouteManifestShardEntry[]
|
|
166
164
|
metadataRoutes: RouteManifestShardEntry[]
|
|
167
165
|
routePatterns: string[]
|
|
@@ -192,7 +190,7 @@ function assertUniqueBackendRoutePattern(
|
|
|
192
190
|
type ApiRouteGenerationResult = {
|
|
193
191
|
eagerApis: string[]
|
|
194
192
|
runtimeApis: string[]
|
|
195
|
-
manifestApis:
|
|
193
|
+
manifestApis: string[]
|
|
196
194
|
manifestShardApis: RouteManifestShardEntry[]
|
|
197
195
|
metadataApis: RouteManifestShardEntry[]
|
|
198
196
|
}
|
|
@@ -246,19 +244,8 @@ type SerializableWorkerMetadata = {
|
|
|
246
244
|
id?: string
|
|
247
245
|
queue?: string
|
|
248
246
|
concurrency?: number
|
|
249
|
-
schedulerSafe?: boolean
|
|
250
|
-
schedulerRequiredFeatures?: string[]
|
|
251
247
|
lockDuration?: number
|
|
252
248
|
maxStalledCount?: number
|
|
253
|
-
/**
|
|
254
|
-
* Whether the worker's metadata declares an `onJobAbandoned` callback.
|
|
255
|
-
*
|
|
256
|
-
* A function cannot be serialized into the registry the way the scalar options are, so the flag is
|
|
257
|
-
* resolved here at build time and the callback itself is emitted as a lazy import beside the
|
|
258
|
-
* handler. Recorded only when the source module could actually be loaded — the object-literal
|
|
259
|
-
* fallback below cannot see whether a referenced identifier is a function.
|
|
260
|
-
*/
|
|
261
|
-
hasJobAbandonedHook?: boolean
|
|
262
249
|
}
|
|
263
250
|
|
|
264
251
|
type PageMetadataManifestLoadResult = {
|
|
@@ -590,55 +577,6 @@ function extractObjectPropertiesFromAst(sourceFile: string, exportName: string):
|
|
|
590
577
|
return Object.keys(result).length > 0 ? result : null
|
|
591
578
|
}
|
|
592
579
|
|
|
593
|
-
/**
|
|
594
|
-
* Whether an exported object literal declares a property, regardless of what it evaluates to.
|
|
595
|
-
*
|
|
596
|
-
* Needed for callbacks: the value resolvers above can read literals and local constants, but a
|
|
597
|
-
* property whose value is an imported function stays unresolvable, so "did the author declare it"
|
|
598
|
-
* cannot be answered by inspecting the extracted value. Answering it from the syntax instead is what
|
|
599
|
-
* lets the generator emit a lazy accessor for a hook it can see but cannot serialize.
|
|
600
|
-
*/
|
|
601
|
-
export function namedObjectLiteralDeclaresProperty(sourceFile: string, exportName: string, propertyName: string): boolean {
|
|
602
|
-
let source = ''
|
|
603
|
-
try {
|
|
604
|
-
source = fs.readFileSync(sourceFile, 'utf8')
|
|
605
|
-
} catch {
|
|
606
|
-
return false
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
const parsed = ts.createSourceFile(sourceFile, source, ts.ScriptTarget.Latest, true, inferScriptKind(sourceFile))
|
|
610
|
-
const exportedNames = new Set<string>()
|
|
611
|
-
for (const statement of parsed.statements) {
|
|
612
|
-
if (
|
|
613
|
-
ts.isExportDeclaration(statement)
|
|
614
|
-
&& statement.exportClause
|
|
615
|
-
&& ts.isNamedExports(statement.exportClause)
|
|
616
|
-
&& !statement.moduleSpecifier
|
|
617
|
-
) {
|
|
618
|
-
for (const element of statement.exportClause.elements) exportedNames.add(element.name.text)
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
for (const statement of parsed.statements) {
|
|
623
|
-
if (!ts.isVariableStatement(statement)) continue
|
|
624
|
-
const exportsDirectly = (ts.canHaveModifiers(statement) ? ts.getModifiers(statement) : undefined)
|
|
625
|
-
?.some((modifier: ts.Modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword)
|
|
626
|
-
for (const declaration of statement.declarationList.declarations) {
|
|
627
|
-
if (!ts.isIdentifier(declaration.name) || declaration.name.text !== exportName) continue
|
|
628
|
-
if (!exportsDirectly && !exportedNames.has(exportName)) continue
|
|
629
|
-
const objectLiteral = unwrapObjectLiteralExpression(declaration.initializer)
|
|
630
|
-
if (!objectLiteral) return false
|
|
631
|
-
return objectLiteral.properties.some((property) => {
|
|
632
|
-
const name = property.name
|
|
633
|
-
if (!name) return false
|
|
634
|
-
const key = ts.isIdentifier(name) ? name.text : ts.isStringLiteral(name) ? name.text : null
|
|
635
|
-
return key === propertyName
|
|
636
|
-
})
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
return false
|
|
640
|
-
}
|
|
641
|
-
|
|
642
580
|
export function extractNamedObjectLiteralExport(sourceFile: string, exportName: string): Record<string, unknown> | null {
|
|
643
581
|
const literal = extractNamedObjectLiteralSource(sourceFile, exportName)
|
|
644
582
|
if (literal) {
|
|
@@ -1198,7 +1136,11 @@ function requiresRuntimePageMetadataFromSourceFile(sourceFile: string): boolean
|
|
|
1198
1136
|
}
|
|
1199
1137
|
|
|
1200
1138
|
function toLiteral(value: unknown): string {
|
|
1201
|
-
return
|
|
1139
|
+
return JSON.stringify(value)
|
|
1140
|
+
.replace(/</g, '\\u003c')
|
|
1141
|
+
.replace(/>/g, '\\u003e')
|
|
1142
|
+
.replace(/\u2028/g, '\\u2028')
|
|
1143
|
+
.replace(/\u2029/g, '\\u2029')
|
|
1202
1144
|
}
|
|
1203
1145
|
|
|
1204
1146
|
const GENERATED_MODULE_RELATIVE_PREFIXES = ['@/', '../../src/modules/', './'] as const
|
|
@@ -1440,81 +1382,32 @@ function collectCommandLoaderEntries(
|
|
|
1440
1382
|
return entries
|
|
1441
1383
|
}
|
|
1442
1384
|
|
|
1443
|
-
|
|
1385
|
+
function renderCommandLoadersFile(entries: CommandLoaderGenerationEntry[]): string {
|
|
1444
1386
|
const seenCommandIds = new Map<string, string>()
|
|
1445
|
-
const
|
|
1387
|
+
const rendered: string[] = []
|
|
1446
1388
|
|
|
1447
1389
|
for (const entry of entries) {
|
|
1448
|
-
const
|
|
1449
|
-
body: importExpression(sanitizeGeneratedModuleSpecifier(entry.importPath)),
|
|
1450
|
-
})
|
|
1390
|
+
const loadExpr = `() => ${buildDynamicImportExpression(entry.importPath)}`
|
|
1451
1391
|
for (const id of entry.ids) {
|
|
1452
1392
|
const previous = seenCommandIds.get(id)
|
|
1453
1393
|
if (previous && previous !== entry.key) {
|
|
1454
1394
|
throw new Error(`[generate] Duplicate command id "${id}" discovered in "${previous}" and "${entry.key}"`)
|
|
1455
1395
|
}
|
|
1456
1396
|
seenCommandIds.set(id, entry.key)
|
|
1457
|
-
|
|
1458
|
-
{ name: 'moduleId', value: entry.moduleId },
|
|
1459
|
-
{ name: 'id', value: id },
|
|
1460
|
-
{ name: 'key', value: entry.key },
|
|
1461
|
-
{ name: 'load', value: loadValue },
|
|
1462
|
-
]))
|
|
1397
|
+
rendered.push(` { moduleId: ${toLiteral(entry.moduleId)}, id: ${toLiteral(id)}, key: ${toLiteral(entry.key)}, load: ${loadExpr} },`)
|
|
1463
1398
|
}
|
|
1464
|
-
|
|
1465
|
-
{ name: 'moduleId', value: entry.moduleId },
|
|
1466
|
-
{ name: 'key', value: entry.key },
|
|
1467
|
-
{ name: 'load', value: loadValue },
|
|
1468
|
-
]))
|
|
1399
|
+
rendered.push(` { moduleId: ${toLiteral(entry.moduleId)}, key: ${toLiteral(entry.key)}, load: ${loadExpr} },`)
|
|
1469
1400
|
}
|
|
1470
1401
|
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
addImportSpec(sourceFile, {
|
|
1475
|
-
moduleSpecifier: '@open-mercato/shared/lib/commands',
|
|
1476
|
-
isTypeOnly: true,
|
|
1477
|
-
namedImports: [{ name: 'CommandLoader' }],
|
|
1478
|
-
})
|
|
1402
|
+
return `// AUTO-GENERATED by mercato generate command-loaders
|
|
1403
|
+
import type { CommandLoader } from '@open-mercato/shared/lib/commands'
|
|
1479
1404
|
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
declarations: [
|
|
1484
|
-
{
|
|
1485
|
-
name: 'commandLoaderEntries',
|
|
1486
|
-
type: 'CommandLoader[]',
|
|
1487
|
-
initializer: arrayLiteral(loaderEntries, writeValue),
|
|
1488
|
-
},
|
|
1489
|
-
],
|
|
1490
|
-
})
|
|
1491
|
-
sourceFile.addExportAssignment({
|
|
1492
|
-
isExportEquals: false,
|
|
1493
|
-
expression: 'commandLoaderEntries',
|
|
1494
|
-
})
|
|
1405
|
+
export const commandLoaderEntries: CommandLoader[] = [
|
|
1406
|
+
${rendered.join('\n')}
|
|
1407
|
+
]
|
|
1495
1408
|
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
export function renderBootstrapRegistrationsFile(options: {
|
|
1500
|
-
entryImports: string[]
|
|
1501
|
-
registrationImports: string[]
|
|
1502
|
-
calls: string[]
|
|
1503
|
-
}): string {
|
|
1504
|
-
const uniqueImports = [...new Set([...options.entryImports, ...options.registrationImports])]
|
|
1505
|
-
|
|
1506
|
-
const sourceFile = createGeneratedSourceFile('bootstrap-registrations.generated.ts')
|
|
1507
|
-
addAutoGeneratedComment(sourceFile, 'registry')
|
|
1508
|
-
addImportStatements(sourceFile, uniqueImports)
|
|
1509
|
-
|
|
1510
|
-
sourceFile.addFunction({
|
|
1511
|
-
name: 'runBootstrapRegistrations',
|
|
1512
|
-
isExported: true,
|
|
1513
|
-
returnType: 'void',
|
|
1514
|
-
statements: options.calls,
|
|
1515
|
-
})
|
|
1516
|
-
|
|
1517
|
-
return getSourceText(sourceFile)
|
|
1409
|
+
export default commandLoaderEntries
|
|
1410
|
+
`
|
|
1518
1411
|
}
|
|
1519
1412
|
|
|
1520
1413
|
function serializeGeneratedImport(statement: GeneratedImportStatement): string {
|
|
@@ -1770,38 +1663,8 @@ function buildPageRouteProps(metaExpr: string, routePath: string): string {
|
|
|
1770
1663
|
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`
|
|
1771
1664
|
}
|
|
1772
1665
|
|
|
1773
|
-
function buildPageRouteManifestSpread(metaExpr: string, routePath: string):
|
|
1774
|
-
return
|
|
1775
|
-
}
|
|
1776
|
-
|
|
1777
|
-
function buildManifestRouteLoader(importPath: string): WriterFunction {
|
|
1778
|
-
return arrowFunction({
|
|
1779
|
-
async: true,
|
|
1780
|
-
body: block((writer) => {
|
|
1781
|
-
writeStatements(writer, [
|
|
1782
|
-
variableStatement({
|
|
1783
|
-
name: 'mod',
|
|
1784
|
-
initializer: awaitExpression(importExpression(sanitizeGeneratedModuleSpecifier(importPath))),
|
|
1785
|
-
}),
|
|
1786
|
-
returnStatement(
|
|
1787
|
-
asExpression(
|
|
1788
|
-
parenthesized(nullishCoalesce([
|
|
1789
|
-
propertyAccess(identifier('mod'), 'default'),
|
|
1790
|
-
identifier('mod'),
|
|
1791
|
-
])),
|
|
1792
|
-
'any',
|
|
1793
|
-
),
|
|
1794
|
-
),
|
|
1795
|
-
])
|
|
1796
|
-
}),
|
|
1797
|
-
})
|
|
1798
|
-
}
|
|
1799
|
-
|
|
1800
|
-
function buildManifestApiLoader(importPath: string): WriterFunction {
|
|
1801
|
-
return arrowFunction({
|
|
1802
|
-
async: true,
|
|
1803
|
-
body: importExpression(sanitizeGeneratedModuleSpecifier(importPath)),
|
|
1804
|
-
})
|
|
1666
|
+
function buildPageRouteManifestSpread(metaExpr: string, routePath: string): string {
|
|
1667
|
+
return `...resolvePageRouteMetadata(${toLiteral(routePath || '/')}, ${metaExpr})`
|
|
1805
1668
|
}
|
|
1806
1669
|
|
|
1807
1670
|
function normalizeBreadcrumb(raw: unknown): SerializablePageMetadata['breadcrumb'] {
|
|
@@ -1914,14 +1777,6 @@ function normalizeWorkerMetadata(raw: unknown): SerializableWorkerMetadata | nul
|
|
|
1914
1777
|
if (typeof source.concurrency === 'number') normalized.concurrency = source.concurrency
|
|
1915
1778
|
if (typeof source.lockDuration === 'number') normalized.lockDuration = source.lockDuration
|
|
1916
1779
|
if (typeof source.maxStalledCount === 'number') normalized.maxStalledCount = source.maxStalledCount
|
|
1917
|
-
if (typeof source.onJobAbandoned === 'function') normalized.hasJobAbandonedHook = true
|
|
1918
|
-
if (source.schedulerSafe === true) normalized.schedulerSafe = true
|
|
1919
|
-
if (Array.isArray(source.schedulerRequiredFeatures)) {
|
|
1920
|
-
const features = source.schedulerRequiredFeatures.filter(
|
|
1921
|
-
(feature): feature is string => typeof feature === 'string' && feature.length > 0,
|
|
1922
|
-
)
|
|
1923
|
-
if (features.length > 0) normalized.schedulerRequiredFeatures = features
|
|
1924
|
-
}
|
|
1925
1780
|
return Object.keys(normalized).length > 0 ? normalized : null
|
|
1926
1781
|
}
|
|
1927
1782
|
|
|
@@ -1933,16 +1788,8 @@ async function loadSubscriberMetadata(sourceFile: string): Promise<SerializableS
|
|
|
1933
1788
|
|
|
1934
1789
|
async function loadWorkerMetadata(sourceFile: string): Promise<SerializableWorkerMetadata | null> {
|
|
1935
1790
|
const sourceModule = await loadModuleExportsFromSource<Record<string, unknown>>(sourceFile)
|
|
1936
|
-
|
|
1791
|
+
return normalizeWorkerMetadata(sourceModule?.metadata)
|
|
1937
1792
|
?? normalizeWorkerMetadata(extractNamedObjectLiteralExport(sourceFile, 'metadata'))
|
|
1938
|
-
if (!metadata) return null
|
|
1939
|
-
// Resolved from the syntax, not the extracted value: a worker module that cannot be imported at
|
|
1940
|
-
// build time falls back to the literal extractor, which cannot tell an imported function from an
|
|
1941
|
-
// unresolvable identifier. Missing this is silent — the hook is simply never installed.
|
|
1942
|
-
if (!metadata.hasJobAbandonedHook && namedObjectLiteralDeclaresProperty(sourceFile, 'metadata', 'onJobAbandoned')) {
|
|
1943
|
-
metadata.hasJobAbandonedHook = true
|
|
1944
|
-
}
|
|
1945
|
-
return metadata
|
|
1946
1793
|
}
|
|
1947
1794
|
|
|
1948
1795
|
async function discoverSubscribers(
|
|
@@ -2127,7 +1974,7 @@ async function processPageFiles(options: {
|
|
|
2127
1974
|
const metaPrefix = type === 'frontend' ? 'M' : 'BM'
|
|
2128
1975
|
const eagerRoutes: string[] = []
|
|
2129
1976
|
const runtimeRoutes: string[] = []
|
|
2130
|
-
const manifestRoutes:
|
|
1977
|
+
const manifestRoutes: string[] = []
|
|
2131
1978
|
const manifestShardRoutes: RouteManifestShardEntry[] = []
|
|
2132
1979
|
const metadataRoutes: RouteManifestShardEntry[] = []
|
|
2133
1980
|
const routePatterns: string[] = []
|
|
@@ -2202,25 +2049,18 @@ async function processPageFiles(options: {
|
|
|
2202
2049
|
const manifestBaseProps = buildPageRouteManifestSpread(manifestMetaExpr, routePath)
|
|
2203
2050
|
eagerRoutes.push(`{ ${baseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`)
|
|
2204
2051
|
runtimeRoutes.push(`{ ${runtimeBaseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`)
|
|
2205
|
-
const
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
]
|
|
2209
|
-
const manifestEntry = objectLiteral([
|
|
2210
|
-
...metadataEntries,
|
|
2211
|
-
{ name: 'load', value: buildManifestRouteLoader(importPath) },
|
|
2212
|
-
])
|
|
2213
|
-
const shardImports = manifestImportStatement ? [manifestImportStatement] : []
|
|
2214
|
-
manifestRoutes.push(manifestEntry)
|
|
2052
|
+
const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, ${manifestBaseProps} }`
|
|
2053
|
+
const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, ${manifestBaseProps}, load: async () => { const mod = await ${buildDynamicImportExpression(importPath)}; return (mod.default ?? mod) as any } }`
|
|
2054
|
+
manifestRoutes.push(manifestDeclaration)
|
|
2215
2055
|
manifestShardRoutes.push({
|
|
2216
2056
|
path: routePath,
|
|
2217
|
-
declaration:
|
|
2218
|
-
imports:
|
|
2057
|
+
declaration: manifestDeclaration,
|
|
2058
|
+
imports: manifestImportStatement ? [manifestImportStatement] : [],
|
|
2219
2059
|
})
|
|
2220
2060
|
metadataRoutes.push({
|
|
2221
2061
|
path: routePath,
|
|
2222
|
-
declaration:
|
|
2223
|
-
imports:
|
|
2062
|
+
declaration: metadataDeclaration,
|
|
2063
|
+
imports: manifestImportStatement ? [manifestImportStatement] : [],
|
|
2224
2064
|
})
|
|
2225
2065
|
routePatterns.push(routePath)
|
|
2226
2066
|
}
|
|
@@ -2300,25 +2140,18 @@ async function processPageFiles(options: {
|
|
|
2300
2140
|
const manifestBaseProps = buildPageRouteManifestSpread(manifestMetaExpr, routePath)
|
|
2301
2141
|
eagerRoutes.push(`{ ${baseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`)
|
|
2302
2142
|
runtimeRoutes.push(`{ ${runtimeBaseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`)
|
|
2303
|
-
const
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
]
|
|
2307
|
-
const manifestEntry = objectLiteral([
|
|
2308
|
-
...metadataEntries,
|
|
2309
|
-
{ name: 'load', value: buildManifestRouteLoader(importPath) },
|
|
2310
|
-
])
|
|
2311
|
-
const shardImports = manifestImportStatement ? [manifestImportStatement] : []
|
|
2312
|
-
manifestRoutes.push(manifestEntry)
|
|
2143
|
+
const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, ${manifestBaseProps} }`
|
|
2144
|
+
const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, ${manifestBaseProps}, load: async () => { const mod = await ${buildDynamicImportExpression(importPath)}; return (mod.default ?? mod) as any } }`
|
|
2145
|
+
manifestRoutes.push(manifestDeclaration)
|
|
2313
2146
|
manifestShardRoutes.push({
|
|
2314
2147
|
path: routePath,
|
|
2315
|
-
declaration:
|
|
2316
|
-
imports:
|
|
2148
|
+
declaration: manifestDeclaration,
|
|
2149
|
+
imports: manifestImportStatement ? [manifestImportStatement] : [],
|
|
2317
2150
|
})
|
|
2318
2151
|
metadataRoutes.push({
|
|
2319
2152
|
path: routePath,
|
|
2320
|
-
declaration:
|
|
2321
|
-
imports:
|
|
2153
|
+
declaration: metadataDeclaration,
|
|
2154
|
+
imports: manifestImportStatement ? [manifestImportStatement] : [],
|
|
2322
2155
|
})
|
|
2323
2156
|
routePatterns.push(routePath)
|
|
2324
2157
|
}
|
|
@@ -2350,7 +2183,7 @@ async function processApiRoutes(options: {
|
|
|
2350
2183
|
|
|
2351
2184
|
const eagerApis: string[] = []
|
|
2352
2185
|
const runtimeApis: string[] = []
|
|
2353
|
-
const manifestApis:
|
|
2186
|
+
const manifestApis: string[] = []
|
|
2354
2187
|
const manifestShardApis: RouteManifestShardEntry[] = []
|
|
2355
2188
|
const metadataApis: RouteManifestShardEntry[] = []
|
|
2356
2189
|
|
|
@@ -2383,19 +2216,11 @@ async function processApiRoutes(options: {
|
|
|
2383
2216
|
eagerImports.push(buildImportStatement(`* as ${importName}`, importPath))
|
|
2384
2217
|
eagerApis.push(`{ path: ((${importName} as any).metadata?.path ?? ${toLiteral(routePath)}), metadata: (${importName} as any).metadata, handlers: ${importName} as any${docsPart} }`)
|
|
2385
2218
|
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(', ')} } }`)
|
|
2386
|
-
const
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
]
|
|
2392
|
-
const manifestEntry = objectLiteral([
|
|
2393
|
-
...metadataEntries,
|
|
2394
|
-
{ name: 'load', value: buildManifestApiLoader(importPath) },
|
|
2395
|
-
])
|
|
2396
|
-
manifestApis.push(manifestEntry)
|
|
2397
|
-
manifestShardApis.push({ path: resolvedPath, declaration: renderGeneratedValue(manifestEntry) })
|
|
2398
|
-
metadataApis.push({ path: resolvedPath, declaration: renderGeneratedValue(objectLiteral(metadataEntries)) })
|
|
2219
|
+
const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('route-file')}, path: ${toLiteral(resolvedPath)}, methods: [${exportedMethods.map((method) => toLiteral(method)).join(', ')}] }`
|
|
2220
|
+
const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('route-file')}, path: ${toLiteral(resolvedPath)}, methods: [${exportedMethods.map((method) => toLiteral(method)).join(', ')}], load: async () => ${buildDynamicImportExpression(importPath)} }`
|
|
2221
|
+
manifestApis.push(manifestDeclaration)
|
|
2222
|
+
manifestShardApis.push({ path: resolvedPath, declaration: manifestDeclaration })
|
|
2223
|
+
metadataApis.push({ path: resolvedPath, declaration: metadataDeclaration })
|
|
2399
2224
|
}
|
|
2400
2225
|
|
|
2401
2226
|
// Single files (plain scripts, not route.*, not tests, skip method dirs)
|
|
@@ -2427,19 +2252,11 @@ async function processApiRoutes(options: {
|
|
|
2427
2252
|
eagerImports.push(buildImportStatement(`* as ${importName}`, importPath))
|
|
2428
2253
|
eagerApis.push(`{ path: ((${importName} as any).metadata?.path ?? ${toLiteral(routePath)}), metadata: (${importName} as any).metadata, handlers: ${importName} as any${docsPart} }`)
|
|
2429
2254
|
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(', ')} } }`)
|
|
2430
|
-
const
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
]
|
|
2436
|
-
const manifestEntry = objectLiteral([
|
|
2437
|
-
...metadataEntries,
|
|
2438
|
-
{ name: 'load', value: buildManifestApiLoader(importPath) },
|
|
2439
|
-
])
|
|
2440
|
-
manifestApis.push(manifestEntry)
|
|
2441
|
-
manifestShardApis.push({ path: resolvedPath, declaration: renderGeneratedValue(manifestEntry) })
|
|
2442
|
-
metadataApis.push({ path: resolvedPath, declaration: renderGeneratedValue(objectLiteral(metadataEntries)) })
|
|
2255
|
+
const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('route-file')}, path: ${toLiteral(resolvedPath)}, methods: [${exportedMethods.map((entryMethod) => toLiteral(entryMethod)).join(', ')}] }`
|
|
2256
|
+
const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('route-file')}, path: ${toLiteral(resolvedPath)}, methods: [${exportedMethods.map((entryMethod) => toLiteral(entryMethod)).join(', ')}], load: async () => ${buildDynamicImportExpression(importPath)} }`
|
|
2257
|
+
manifestApis.push(manifestDeclaration)
|
|
2258
|
+
manifestShardApis.push({ path: resolvedPath, declaration: manifestDeclaration })
|
|
2259
|
+
metadataApis.push({ path: resolvedPath, declaration: metadataDeclaration })
|
|
2443
2260
|
}
|
|
2444
2261
|
|
|
2445
2262
|
// Legacy per-method
|
|
@@ -2481,20 +2298,11 @@ async function processApiRoutes(options: {
|
|
|
2481
2298
|
eagerImports.push(buildImportStatement(`${importName}, * as ${metaName}`, importPath))
|
|
2482
2299
|
eagerApis.push(`{ method: ${toLiteral(method)}, path: (${metaName}.metadata?.path ?? ${toLiteral(routePath)}), handler: ${importName}, metadata: ${metaName}.metadata${docsPart} }`)
|
|
2483
2300
|
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} }`)
|
|
2484
|
-
const
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
{ name: 'methods', value: arrayLiteral([method], writeValue) },
|
|
2490
|
-
]
|
|
2491
|
-
const manifestEntry = objectLiteral([
|
|
2492
|
-
...metadataEntries,
|
|
2493
|
-
{ name: 'load', value: buildManifestApiLoader(importPath) },
|
|
2494
|
-
])
|
|
2495
|
-
manifestApis.push(manifestEntry)
|
|
2496
|
-
manifestShardApis.push({ path: resolvedPath, declaration: renderGeneratedValue(manifestEntry) })
|
|
2497
|
-
metadataApis.push({ path: resolvedPath, declaration: renderGeneratedValue(objectLiteral(metadataEntries)) })
|
|
2301
|
+
const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('legacy')}, method: ${toLiteral(method)}, path: ${toLiteral(resolvedPath)}, methods: [${toLiteral(method)}] }`
|
|
2302
|
+
const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('legacy')}, method: ${toLiteral(method)}, path: ${toLiteral(resolvedPath)}, methods: [${toLiteral(method)}], load: async () => ${buildDynamicImportExpression(importPath)} }`
|
|
2303
|
+
manifestApis.push(manifestDeclaration)
|
|
2304
|
+
manifestShardApis.push({ path: resolvedPath, declaration: manifestDeclaration })
|
|
2305
|
+
metadataApis.push({ path: resolvedPath, declaration: metadataDeclaration })
|
|
2498
2306
|
}
|
|
2499
2307
|
}
|
|
2500
2308
|
|
|
@@ -2507,17 +2315,62 @@ async function processApiRoutes(options: {
|
|
|
2507
2315
|
}
|
|
2508
2316
|
}
|
|
2509
2317
|
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2318
|
+
function processSubscribers(discovered: DiscoveredSubscriber[]): string[] {
|
|
2319
|
+
const subscribers: string[] = []
|
|
2320
|
+
for (const { id, importPath, metadata } of discovered) {
|
|
2321
|
+
const subscriberId = metadata?.id ?? id
|
|
2322
|
+
subscribers.push(
|
|
2323
|
+
`{ 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)}) }`
|
|
2324
|
+
)
|
|
2325
|
+
}
|
|
2326
|
+
return subscribers
|
|
2327
|
+
}
|
|
2518
2328
|
|
|
2519
|
-
function
|
|
2520
|
-
|
|
2329
|
+
function processWorkers(discovered: DiscoveredWorker[]): string[] {
|
|
2330
|
+
const workers: string[] = []
|
|
2331
|
+
for (const { id, importPath, metadata } of discovered) {
|
|
2332
|
+
const workerId = metadata.id ?? id
|
|
2333
|
+
workers.push(
|
|
2334
|
+
`{ 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)}`}, handler: createLazyModuleWorker(() => ${buildDynamicImportExpression(importPath)}, ${toLiteral(workerId)}) }`
|
|
2335
|
+
)
|
|
2336
|
+
}
|
|
2337
|
+
return workers
|
|
2338
|
+
}
|
|
2339
|
+
|
|
2340
|
+
function processTranslations(options: {
|
|
2341
|
+
discovered: DiscoveredTranslation[]
|
|
2342
|
+
modId: string
|
|
2343
|
+
appImportBase: string
|
|
2344
|
+
pkgImportBase: string
|
|
2345
|
+
imports: string[]
|
|
2346
|
+
extraImports?: string[]
|
|
2347
|
+
}): string[] {
|
|
2348
|
+
const { discovered, modId, appImportBase, pkgImportBase, imports, extraImports } = options
|
|
2349
|
+
const translations: string[] = []
|
|
2350
|
+
for (const { locale, coreHas, appHas } of discovered) {
|
|
2351
|
+
if (coreHas && appHas) {
|
|
2352
|
+
const cName = `T_${toVar(modId)}_${toVar(locale)}_C`
|
|
2353
|
+
const aName = `T_${toVar(modId)}_${toVar(locale)}_A`
|
|
2354
|
+
imports.push(buildImportStatement(cName, `${pkgImportBase}/i18n/${locale}.json`))
|
|
2355
|
+
imports.push(buildImportStatement(aName, `${appImportBase}/i18n/${locale}.json`))
|
|
2356
|
+
extraImports?.push(buildImportStatement(cName, `${pkgImportBase}/i18n/${locale}.json`))
|
|
2357
|
+
extraImports?.push(buildImportStatement(aName, `${appImportBase}/i18n/${locale}.json`))
|
|
2358
|
+
translations.push(
|
|
2359
|
+
`'${locale}': { ...( ${cName} as unknown as Record<string,string> ), ...( ${aName} as unknown as Record<string,string> ) }`
|
|
2360
|
+
)
|
|
2361
|
+
} else if (appHas) {
|
|
2362
|
+
const aName = `T_${toVar(modId)}_${toVar(locale)}_A`
|
|
2363
|
+
imports.push(buildImportStatement(aName, `${appImportBase}/i18n/${locale}.json`))
|
|
2364
|
+
extraImports?.push(buildImportStatement(aName, `${appImportBase}/i18n/${locale}.json`))
|
|
2365
|
+
translations.push(`'${locale}': ${aName} as unknown as Record<string,string>`)
|
|
2366
|
+
} else if (coreHas) {
|
|
2367
|
+
const cName = `T_${toVar(modId)}_${toVar(locale)}_C`
|
|
2368
|
+
imports.push(buildImportStatement(cName, `${pkgImportBase}/i18n/${locale}.json`))
|
|
2369
|
+
extraImports?.push(buildImportStatement(cName, `${pkgImportBase}/i18n/${locale}.json`))
|
|
2370
|
+
translations.push(`'${locale}': ${cName} as unknown as Record<string,string>`)
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
return translations
|
|
2521
2374
|
}
|
|
2522
2375
|
|
|
2523
2376
|
/**
|
|
@@ -2664,64 +2517,6 @@ function buildModuleDashboardWidgetsValue(entries: DashboardWidgetEntry[]): Writ
|
|
|
2664
2517
|
)
|
|
2665
2518
|
}
|
|
2666
2519
|
|
|
2667
|
-
/**
|
|
2668
|
-
* Wraps expressions that are still produced as pre-rendered strings by collaborators this
|
|
2669
|
-
* change does not convert (page routes, api handlers, dashboard widgets) so they can sit
|
|
2670
|
-
* inside an AST-built array without being re-quoted as string literals. It disappears once
|
|
2671
|
-
* those producers emit writers themselves — see the follow-up noted in the spec's Non-Goals.
|
|
2672
|
-
*/
|
|
2673
|
-
function preRenderedExpressionList(expressions: readonly string[]): WriterFunction {
|
|
2674
|
-
return arrayLiteral(expressions.map((expression) => identifier(expression)), writeValue)
|
|
2675
|
-
}
|
|
2676
|
-
|
|
2677
|
-
/**
|
|
2678
|
-
* `(X.<first> ?? X.<second>)` — the member-fallback shape the main registry path emits.
|
|
2679
|
-
* It is deliberately not `namespaceFallback`, which the app path uses: that helper walks
|
|
2680
|
-
* the members in an IIFE and treats only `!= null` as present, which is a different
|
|
2681
|
-
* expression. Converging the two is a behaviour change, not a formatting one.
|
|
2682
|
-
*/
|
|
2683
|
-
function legacyNamespaceMemberFallback(importName: string, members: readonly [string, string]): WriterFunction {
|
|
2684
|
-
return parenthesized(nullishCoalesce([
|
|
2685
|
-
propertyAccess(identifier(importName), members[0]),
|
|
2686
|
-
propertyAccess(identifier(importName), members[1]),
|
|
2687
|
-
]))
|
|
2688
|
-
}
|
|
2689
|
-
|
|
2690
|
-
function buildLegacyModuleListValue(options: {
|
|
2691
|
-
importName: string
|
|
2692
|
-
members: readonly [string, string]
|
|
2693
|
-
castType: string
|
|
2694
|
-
}): WriterFunction {
|
|
2695
|
-
return logicalOr([
|
|
2696
|
-
asExpression(legacyNamespaceMemberFallback(options.importName, options.members), options.castType),
|
|
2697
|
-
emptyArray(),
|
|
2698
|
-
])
|
|
2699
|
-
}
|
|
2700
|
-
|
|
2701
|
-
function buildLegacyModuleSetupValue(importName: string): WriterFunction {
|
|
2702
|
-
return logicalOr([
|
|
2703
|
-
legacyNamespaceMemberFallback(importName, ['default', 'setup']),
|
|
2704
|
-
identifier('undefined'),
|
|
2705
|
-
])
|
|
2706
|
-
}
|
|
2707
|
-
|
|
2708
|
-
function buildLegacyIntegrationListValue(
|
|
2709
|
-
importName: string,
|
|
2710
|
-
pluralMember: string,
|
|
2711
|
-
singularMember: string,
|
|
2712
|
-
castType: string,
|
|
2713
|
-
): WriterFunction {
|
|
2714
|
-
const singular = propertyAccess(identifier(importName), singularMember)
|
|
2715
|
-
|
|
2716
|
-
return asExpression(
|
|
2717
|
-
parenthesized(nullishCoalesce([
|
|
2718
|
-
propertyAccess(identifier(importName), pluralMember),
|
|
2719
|
-
parenthesized(conditionalExpression(singular, arrayLiteral([singular], writeValue), emptyArray())),
|
|
2720
|
-
])),
|
|
2721
|
-
castType,
|
|
2722
|
-
)
|
|
2723
|
-
}
|
|
2724
|
-
|
|
2725
2520
|
function buildModuleIntegrationListValue(
|
|
2726
2521
|
importName: string,
|
|
2727
2522
|
pluralMember: string,
|
|
@@ -2769,15 +2564,9 @@ function buildModulesInfoExpression(): WriterFunction {
|
|
|
2769
2564
|
function renderAstModuleRegistryFile(options: {
|
|
2770
2565
|
fileName: string
|
|
2771
2566
|
generator: string
|
|
2772
|
-
|
|
2773
|
-
* Import statements, or the structured specs generator extensions push onto the shared
|
|
2774
|
-
* import array via `processStandaloneConfig`. Both shapes reach this emitter at runtime,
|
|
2775
|
-
* so both are normalised here rather than at each call site.
|
|
2776
|
-
*/
|
|
2777
|
-
imports: GeneratedImportStatement[]
|
|
2567
|
+
imports: string[]
|
|
2778
2568
|
moduleEntries: WriterFunction[]
|
|
2779
2569
|
includeCreateElementImport?: boolean
|
|
2780
|
-
includeAbandonHookImport?: boolean
|
|
2781
2570
|
}): string {
|
|
2782
2571
|
const sourceFile = createGeneratedSourceFile(options.fileName)
|
|
2783
2572
|
addAutoGeneratedComment(sourceFile, options.generator)
|
|
@@ -2793,11 +2582,10 @@ function renderAstModuleRegistryFile(options: {
|
|
|
2793
2582
|
namedImports: [
|
|
2794
2583
|
{ name: 'createLazyModuleSubscriber' },
|
|
2795
2584
|
{ name: 'createLazyModuleWorker' },
|
|
2796
|
-
...(options.includeAbandonHookImport ? [{ name: ABANDON_HOOK_FACTORY }] : []),
|
|
2797
2585
|
{ name: 'Module', isTypeOnly: true },
|
|
2798
2586
|
],
|
|
2799
2587
|
})
|
|
2800
|
-
addImportStatements(sourceFile, options.imports
|
|
2588
|
+
addImportStatements(sourceFile, options.imports)
|
|
2801
2589
|
|
|
2802
2590
|
sourceFile.addVariableStatement({
|
|
2803
2591
|
declarationKind: VariableDeclarationKind.Const,
|
|
@@ -2828,52 +2616,6 @@ function renderAstModuleRegistryFile(options: {
|
|
|
2828
2616
|
return getSourceText(sourceFile)
|
|
2829
2617
|
}
|
|
2830
2618
|
|
|
2831
|
-
function renderAstManifestFile(options: {
|
|
2832
|
-
fileName: string
|
|
2833
|
-
typeName: string
|
|
2834
|
-
exportName: string
|
|
2835
|
-
imports?: string[]
|
|
2836
|
-
entries: WriterFunction[]
|
|
2837
|
-
}): string {
|
|
2838
|
-
const sourceFile = createGeneratedSourceFile(options.fileName)
|
|
2839
|
-
addAutoGeneratedComment(sourceFile, 'registry')
|
|
2840
|
-
|
|
2841
|
-
const usesPageRouteMetadataHelper = options.typeName === 'FrontendRouteManifestEntry'
|
|
2842
|
-
|| options.typeName === 'BackendRouteManifestEntry'
|
|
2843
|
-
addImportSpec(sourceFile, usesPageRouteMetadataHelper
|
|
2844
|
-
? {
|
|
2845
|
-
moduleSpecifier: '@open-mercato/shared/modules/registry',
|
|
2846
|
-
namedImports: [
|
|
2847
|
-
{ name: 'resolvePageRouteMetadata' },
|
|
2848
|
-
{ name: options.typeName, isTypeOnly: true },
|
|
2849
|
-
],
|
|
2850
|
-
}
|
|
2851
|
-
: {
|
|
2852
|
-
moduleSpecifier: '@open-mercato/shared/modules/registry',
|
|
2853
|
-
isTypeOnly: true,
|
|
2854
|
-
namedImports: [{ name: options.typeName }],
|
|
2855
|
-
})
|
|
2856
|
-
addImportStatements(sourceFile, options.imports ?? [])
|
|
2857
|
-
|
|
2858
|
-
sourceFile.addVariableStatement({
|
|
2859
|
-
declarationKind: VariableDeclarationKind.Const,
|
|
2860
|
-
isExported: true,
|
|
2861
|
-
declarations: [
|
|
2862
|
-
{
|
|
2863
|
-
name: options.exportName,
|
|
2864
|
-
type: `${options.typeName}[]`,
|
|
2865
|
-
initializer: arrayLiteral(options.entries, writeValue),
|
|
2866
|
-
},
|
|
2867
|
-
],
|
|
2868
|
-
})
|
|
2869
|
-
sourceFile.addExportAssignment({
|
|
2870
|
-
isExportEquals: false,
|
|
2871
|
-
expression: options.exportName,
|
|
2872
|
-
})
|
|
2873
|
-
|
|
2874
|
-
return getSourceText(sourceFile)
|
|
2875
|
-
}
|
|
2876
|
-
|
|
2877
2619
|
function renderAstLegacyAliasFile(options: {
|
|
2878
2620
|
fileName: string
|
|
2879
2621
|
exportName: string
|
|
@@ -2937,10 +2679,62 @@ function renderEnabledModuleIdsFile(moduleIds: readonly string[]): string {
|
|
|
2937
2679
|
return getSourceText(sourceFile)
|
|
2938
2680
|
}
|
|
2939
2681
|
|
|
2682
|
+
function renderLegacyCompatibleArray(entries: readonly string[]): string {
|
|
2683
|
+
return `[
|
|
2684
|
+
${entries.join(',\n ')}
|
|
2685
|
+
]`
|
|
2686
|
+
}
|
|
2687
|
+
|
|
2940
2688
|
function buildLazyRouteComponentExpression(importPath: string): string {
|
|
2941
2689
|
return `async (props: any) => { const mod = await ${buildDynamicImportExpression(importPath)}; const Component = (mod.default ?? mod) as any; return createElement(Component, props) }`
|
|
2942
2690
|
}
|
|
2943
2691
|
|
|
2692
|
+
function renderAstLegacyModuleRegistryOutput(options: {
|
|
2693
|
+
fileName: string
|
|
2694
|
+
imports: GeneratedImportStatement[]
|
|
2695
|
+
moduleEntries: string[]
|
|
2696
|
+
includeCreateElementImport?: boolean
|
|
2697
|
+
}): string {
|
|
2698
|
+
const importSection = [
|
|
2699
|
+
...(options.includeCreateElementImport ? ["import { createElement } from 'react'"] : []),
|
|
2700
|
+
"import { createLazyModuleSubscriber, createLazyModuleWorker, type Module } from '@open-mercato/shared/modules/registry'",
|
|
2701
|
+
...options.imports.map((entry) => serializeGeneratedImport(entry)),
|
|
2702
|
+
].join('\n')
|
|
2703
|
+
|
|
2704
|
+
return `// AUTO-GENERATED by mercato generate registry
|
|
2705
|
+
${importSection}
|
|
2706
|
+
|
|
2707
|
+
export const modules: Module[] = ${renderLegacyCompatibleArray(options.moduleEntries)}
|
|
2708
|
+
export const modulesInfo = modules.map(m => ({ id: m.id, ...(m.info || {}) }))
|
|
2709
|
+
export default modules
|
|
2710
|
+
`
|
|
2711
|
+
}
|
|
2712
|
+
|
|
2713
|
+
function renderAstLegacyManifestOutput(options: {
|
|
2714
|
+
fileName: string
|
|
2715
|
+
typeName: string
|
|
2716
|
+
exportName: string
|
|
2717
|
+
imports?: GeneratedImportStatement[]
|
|
2718
|
+
entries: string[]
|
|
2719
|
+
}): string {
|
|
2720
|
+
const usesPageRouteMetadataHelper = options.typeName === 'FrontendRouteManifestEntry'
|
|
2721
|
+
|| options.typeName === 'BackendRouteManifestEntry'
|
|
2722
|
+
const importSection = [
|
|
2723
|
+
usesPageRouteMetadataHelper
|
|
2724
|
+
? `import { resolvePageRouteMetadata, type ${options.typeName} } from '@open-mercato/shared/modules/registry'`
|
|
2725
|
+
: `import type { ${options.typeName} } from '@open-mercato/shared/modules/registry'`,
|
|
2726
|
+
...(options.imports ?? []).map((entry) => serializeGeneratedImport(entry)),
|
|
2727
|
+
].join('\n')
|
|
2728
|
+
|
|
2729
|
+
return `// AUTO-GENERATED by mercato generate registry
|
|
2730
|
+
${importSection}
|
|
2731
|
+
|
|
2732
|
+
export const ${options.exportName}: ${options.typeName}[] = ${renderLegacyCompatibleArray(options.entries)}
|
|
2733
|
+
|
|
2734
|
+
export default ${options.exportName}
|
|
2735
|
+
`
|
|
2736
|
+
}
|
|
2737
|
+
|
|
2944
2738
|
function buildRuntimeRouteComponent(importPath: string): WriterFunction {
|
|
2945
2739
|
return arrowFunction({
|
|
2946
2740
|
async: true,
|
|
@@ -3215,21 +3009,8 @@ function processWorkersAst(discovered: DiscoveredWorker[]): WriterFunction[] {
|
|
|
3215
3009
|
{ name: 'id', value: workerId },
|
|
3216
3010
|
{ name: 'queue', value: metadata.queue },
|
|
3217
3011
|
{ name: 'concurrency', value: metadata.concurrency ?? 1 },
|
|
3218
|
-
...(metadata.schedulerSafe === true ? [{ name: 'schedulerSafe', value: true }] : []),
|
|
3219
|
-
...(metadata.schedulerRequiredFeatures
|
|
3220
|
-
? [{ name: 'schedulerRequiredFeatures', value: arrayLiteral(metadata.schedulerRequiredFeatures, writeValue) }]
|
|
3221
|
-
: []),
|
|
3222
3012
|
...(metadata.lockDuration === undefined ? [] : [{ name: 'lockDuration', value: metadata.lockDuration }]),
|
|
3223
3013
|
...(metadata.maxStalledCount === undefined ? [] : [{ name: 'maxStalledCount', value: metadata.maxStalledCount }]),
|
|
3224
|
-
...(metadata.hasJobAbandonedHook
|
|
3225
|
-
? [{
|
|
3226
|
-
name: 'onJobAbandoned',
|
|
3227
|
-
value: callExpression(identifier(ABANDON_HOOK_FACTORY), [
|
|
3228
|
-
arrowFunction({ body: importExpression(importPath) }),
|
|
3229
|
-
workerId,
|
|
3230
|
-
]),
|
|
3231
|
-
}]
|
|
3232
|
-
: []),
|
|
3233
3014
|
{
|
|
3234
3015
|
name: 'handler',
|
|
3235
3016
|
value: callExpression(identifier('createLazyModuleWorker'), [
|
|
@@ -3589,11 +3370,11 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3589
3370
|
const runtimeImports: string[] = []
|
|
3590
3371
|
const frontendRouteManifestImports: string[] = []
|
|
3591
3372
|
const backendRouteManifestImports: string[] = []
|
|
3592
|
-
const moduleDecls:
|
|
3593
|
-
const runtimeModuleDecls:
|
|
3594
|
-
const frontendRouteManifestDecls:
|
|
3595
|
-
const backendRouteManifestDecls:
|
|
3596
|
-
const apiRouteManifestDecls:
|
|
3373
|
+
const moduleDecls: string[] = []
|
|
3374
|
+
const runtimeModuleDecls: string[] = []
|
|
3375
|
+
const frontendRouteManifestDecls: string[] = []
|
|
3376
|
+
const backendRouteManifestDecls: string[] = []
|
|
3377
|
+
const apiRouteManifestDecls: string[] = []
|
|
3597
3378
|
const backendRouteShardEntries: RouteManifestShardEntry[] = []
|
|
3598
3379
|
const backendRouteMetadataEntries: RouteManifestShardEntry[] = []
|
|
3599
3380
|
const apiRouteShardEntries: RouteManifestShardEntry[] = []
|
|
@@ -3603,7 +3384,6 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3603
3384
|
const requiresByModule = new Map<string, string[]>()
|
|
3604
3385
|
const commandLoaderEntries: CommandLoaderGenerationEntry[] = []
|
|
3605
3386
|
let hasRouteComponents = false
|
|
3606
|
-
let hasAbandonHookWorkers = false
|
|
3607
3387
|
|
|
3608
3388
|
// UMES conflict detection: collect file paths during module processing
|
|
3609
3389
|
const umesConflictSources: Array<{
|
|
@@ -3626,9 +3406,9 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3626
3406
|
const runtimeBackendRoutes: string[] = []
|
|
3627
3407
|
const runtimeApis: string[] = []
|
|
3628
3408
|
let cliImportName: string | null = null
|
|
3629
|
-
const translations:
|
|
3630
|
-
const subscribers:
|
|
3631
|
-
const workers:
|
|
3409
|
+
const translations: string[] = []
|
|
3410
|
+
const subscribers: string[] = []
|
|
3411
|
+
const workers: string[] = []
|
|
3632
3412
|
let infoImportName: string | null = null
|
|
3633
3413
|
let extensionsImportName: string | null = null
|
|
3634
3414
|
let fieldsImportName: string | null = null
|
|
@@ -3842,7 +3622,7 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3842
3622
|
}
|
|
3843
3623
|
|
|
3844
3624
|
// 16. Translations
|
|
3845
|
-
translations.push(...
|
|
3625
|
+
translations.push(...processTranslations({
|
|
3846
3626
|
discovered: discovered.translations,
|
|
3847
3627
|
modId,
|
|
3848
3628
|
appImportBase,
|
|
@@ -3852,12 +3632,10 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3852
3632
|
}))
|
|
3853
3633
|
|
|
3854
3634
|
// 17. Subscribers
|
|
3855
|
-
subscribers.push(...
|
|
3635
|
+
subscribers.push(...processSubscribers(await discovered.getSubscribers()))
|
|
3856
3636
|
|
|
3857
3637
|
// 18. Workers
|
|
3858
|
-
|
|
3859
|
-
if (workersDeclareAbandonHook(discoveredWorkersForModule)) hasAbandonHookWorkers = true
|
|
3860
|
-
workers.push(...processWorkersAst(discoveredWorkersForModule))
|
|
3638
|
+
workers.push(...processWorkers(await discovered.getWorkers()))
|
|
3861
3639
|
|
|
3862
3640
|
// Build combined customFieldSets expression
|
|
3863
3641
|
{
|
|
@@ -3880,120 +3658,44 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3880
3658
|
}
|
|
3881
3659
|
}
|
|
3882
3660
|
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
}
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
})
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
name: 'customEntities',
|
|
3922
|
-
value: buildLegacyModuleListValue({
|
|
3923
|
-
importName: customEntitiesImportName,
|
|
3924
|
-
members: ['default', 'entities'],
|
|
3925
|
-
castType: 'any',
|
|
3926
|
-
}),
|
|
3927
|
-
})
|
|
3928
|
-
}
|
|
3929
|
-
|
|
3930
|
-
const setupAndBeyondEntries: GeneratedObjectEntry[] = []
|
|
3931
|
-
if (setupImportName) {
|
|
3932
|
-
setupAndBeyondEntries.push({ name: 'setup', value: buildLegacyModuleSetupValue(setupImportName) })
|
|
3933
|
-
}
|
|
3934
|
-
if (encryptionImportName) {
|
|
3935
|
-
setupAndBeyondEntries.push({
|
|
3936
|
-
name: 'defaultEncryptionMaps',
|
|
3937
|
-
value: buildLegacyModuleListValue({
|
|
3938
|
-
importName: encryptionImportName,
|
|
3939
|
-
members: ['default', 'defaultEncryptionMaps'],
|
|
3940
|
-
castType: "import('@open-mercato/shared/modules/encryption').ModuleEncryptionMap[]",
|
|
3941
|
-
}),
|
|
3942
|
-
})
|
|
3943
|
-
}
|
|
3944
|
-
if (integrationExports) {
|
|
3945
|
-
setupAndBeyondEntries.push({
|
|
3946
|
-
name: 'integrations',
|
|
3947
|
-
value: buildLegacyIntegrationListValue(
|
|
3948
|
-
integrationExports,
|
|
3949
|
-
'integrations',
|
|
3950
|
-
'integration',
|
|
3951
|
-
"import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition[]",
|
|
3952
|
-
),
|
|
3953
|
-
})
|
|
3954
|
-
setupAndBeyondEntries.push({
|
|
3955
|
-
name: 'bundles',
|
|
3956
|
-
value: buildLegacyIntegrationListValue(
|
|
3957
|
-
integrationExports,
|
|
3958
|
-
'bundles',
|
|
3959
|
-
'bundle',
|
|
3960
|
-
"import('@open-mercato/shared/modules/integrations/types').IntegrationBundle[]",
|
|
3961
|
-
),
|
|
3962
|
-
})
|
|
3963
|
-
}
|
|
3964
|
-
|
|
3965
|
-
const eagerEntries: GeneratedObjectEntry[] = [...identityEntries]
|
|
3966
|
-
if (frontendRoutes.length > 0) {
|
|
3967
|
-
eagerEntries.push({ name: 'frontendRoutes', value: preRenderedExpressionList(frontendRoutes) })
|
|
3968
|
-
}
|
|
3969
|
-
if (backendRoutes.length > 0) {
|
|
3970
|
-
eagerEntries.push({ name: 'backendRoutes', value: preRenderedExpressionList(backendRoutes) })
|
|
3971
|
-
}
|
|
3972
|
-
if (apis.length > 0) {
|
|
3973
|
-
eagerEntries.push({ name: 'apis', value: preRenderedExpressionList(apis) })
|
|
3974
|
-
}
|
|
3975
|
-
if (cliImportName) {
|
|
3976
|
-
eagerEntries.push({ name: 'cli', value: identifier(cliImportName) })
|
|
3977
|
-
}
|
|
3978
|
-
eagerEntries.push(...sharedTailEntries)
|
|
3979
|
-
if (dashboardWidgets.length > 0) {
|
|
3980
|
-
eagerEntries.push({ name: 'dashboardWidgets', value: preRenderedExpressionList(dashboardWidgets) })
|
|
3981
|
-
}
|
|
3982
|
-
eagerEntries.push(...setupAndBeyondEntries)
|
|
3983
|
-
moduleDecls.push(objectLiteral(eagerEntries))
|
|
3984
|
-
|
|
3985
|
-
const runtimeEntries: GeneratedObjectEntry[] = [...identityEntries]
|
|
3986
|
-
if (runtimeFrontendRoutes.length > 0) {
|
|
3987
|
-
runtimeEntries.push({ name: 'frontendRoutes', value: preRenderedExpressionList(runtimeFrontendRoutes) })
|
|
3988
|
-
}
|
|
3989
|
-
if (runtimeBackendRoutes.length > 0) {
|
|
3990
|
-
runtimeEntries.push({ name: 'backendRoutes', value: preRenderedExpressionList(runtimeBackendRoutes) })
|
|
3991
|
-
}
|
|
3992
|
-
if (runtimeApis.length > 0) {
|
|
3993
|
-
runtimeEntries.push({ name: 'apis', value: preRenderedExpressionList(runtimeApis) })
|
|
3994
|
-
}
|
|
3995
|
-
runtimeEntries.push(...sharedTailEntries, ...setupAndBeyondEntries)
|
|
3996
|
-
runtimeModuleDecls.push(objectLiteral(runtimeEntries))
|
|
3661
|
+
moduleDecls.push(`{
|
|
3662
|
+
id: ${toLiteral(modId)},
|
|
3663
|
+
${infoImportName ? `info: ${infoImportName}.metadata,` : ''}
|
|
3664
|
+
${frontendRoutes.length ? `frontendRoutes: [${frontendRoutes.join(', ')}],` : ''}
|
|
3665
|
+
${backendRoutes.length ? `backendRoutes: [${backendRoutes.join(', ')}],` : ''}
|
|
3666
|
+
${apis.length ? `apis: [${apis.join(', ')}],` : ''}
|
|
3667
|
+
${cliImportName ? `cli: ${cliImportName},` : ''}
|
|
3668
|
+
${translations.length ? `translations: { ${translations.join(', ')} },` : ''}
|
|
3669
|
+
${subscribers.length ? `subscribers: [${subscribers.join(', ')}],` : ''}
|
|
3670
|
+
${workers.length ? `workers: [${workers.join(', ')}],` : ''}
|
|
3671
|
+
${extensionsImportName ? `entityExtensions: ((${extensionsImportName}.default ?? ${extensionsImportName}.extensions) as import('@open-mercato/shared/modules/entities').EntityExtension[]) || [],` : ''}
|
|
3672
|
+
customFieldSets: ${customFieldSetsExpr},
|
|
3673
|
+
${featuresImportName ? `features: ((${featuresImportName}.default ?? ${featuresImportName}.features) as any) || [],` : ''}
|
|
3674
|
+
${customEntitiesImportName ? `customEntities: ((${customEntitiesImportName}.default ?? ${customEntitiesImportName}.entities) as any) || [],` : ''}
|
|
3675
|
+
${dashboardWidgets.length ? `dashboardWidgets: [${dashboardWidgets.join(', ')}],` : ''}
|
|
3676
|
+
${setupImportName ? `setup: (${setupImportName}.default ?? ${setupImportName}.setup) || undefined,` : ''}
|
|
3677
|
+
${encryptionImportName ? `defaultEncryptionMaps: ((${encryptionImportName}.default ?? ${encryptionImportName}.defaultEncryptionMaps) as import('@open-mercato/shared/modules/encryption').ModuleEncryptionMap[]) || [],` : ''}
|
|
3678
|
+
${integrationExports ? `integrations: ((${integrationExports}.integrations ?? (${integrationExports}.integration ? [${integrationExports}.integration] : [])) as import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition[]),` : ''}
|
|
3679
|
+
${integrationExports ? `bundles: ((${integrationExports}.bundles ?? (${integrationExports}.bundle ? [${integrationExports}.bundle] : [])) as import('@open-mercato/shared/modules/integrations/types').IntegrationBundle[]),` : ''}
|
|
3680
|
+
}`)
|
|
3681
|
+
runtimeModuleDecls.push(`{
|
|
3682
|
+
id: ${toLiteral(modId)},
|
|
3683
|
+
${infoImportName ? `info: ${infoImportName}.metadata,` : ''}
|
|
3684
|
+
${runtimeFrontendRoutes.length ? `frontendRoutes: [${runtimeFrontendRoutes.join(', ')}],` : ''}
|
|
3685
|
+
${runtimeBackendRoutes.length ? `backendRoutes: [${runtimeBackendRoutes.join(', ')}],` : ''}
|
|
3686
|
+
${runtimeApis.length ? `apis: [${runtimeApis.join(', ')}],` : ''}
|
|
3687
|
+
${translations.length ? `translations: { ${translations.join(', ')} },` : ''}
|
|
3688
|
+
${subscribers.length ? `subscribers: [${subscribers.join(', ')}],` : ''}
|
|
3689
|
+
${workers.length ? `workers: [${workers.join(', ')}],` : ''}
|
|
3690
|
+
${extensionsImportName ? `entityExtensions: ((${extensionsImportName}.default ?? ${extensionsImportName}.extensions) as import('@open-mercato/shared/modules/entities').EntityExtension[]) || [],` : ''}
|
|
3691
|
+
customFieldSets: ${customFieldSetsExpr},
|
|
3692
|
+
${featuresImportName ? `features: ((${featuresImportName}.default ?? ${featuresImportName}.features) as any) || [],` : ''}
|
|
3693
|
+
${customEntitiesImportName ? `customEntities: ((${customEntitiesImportName}.default ?? ${customEntitiesImportName}.entities) as any) || [],` : ''}
|
|
3694
|
+
${setupImportName ? `setup: (${setupImportName}.default ?? ${setupImportName}.setup) || undefined,` : ''}
|
|
3695
|
+
${encryptionImportName ? `defaultEncryptionMaps: ((${encryptionImportName}.default ?? ${encryptionImportName}.defaultEncryptionMaps) as import('@open-mercato/shared/modules/encryption').ModuleEncryptionMap[]) || [],` : ''}
|
|
3696
|
+
${integrationExports ? `integrations: ((${integrationExports}.integrations ?? (${integrationExports}.integration ? [${integrationExports}.integration] : [])) as import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition[]),` : ''}
|
|
3697
|
+
${integrationExports ? `bundles: ((${integrationExports}.bundles ?? (${integrationExports}.bundle ? [${integrationExports}.bundle] : [])) as import('@open-mercato/shared/modules/integrations/types').IntegrationBundle[]),` : ''}
|
|
3698
|
+
}`)
|
|
3997
3699
|
}
|
|
3998
3700
|
|
|
3999
3701
|
// === UMES Conflict Detection ===
|
|
@@ -4094,37 +3796,33 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
4094
3796
|
}
|
|
4095
3797
|
}
|
|
4096
3798
|
|
|
4097
|
-
const output =
|
|
3799
|
+
const output = renderAstLegacyModuleRegistryOutput({
|
|
4098
3800
|
fileName: 'modules.generated.ts',
|
|
4099
|
-
generator: 'registry',
|
|
4100
3801
|
imports,
|
|
4101
3802
|
moduleEntries: moduleDecls,
|
|
4102
3803
|
includeCreateElementImport: hasRouteComponents,
|
|
4103
|
-
includeAbandonHookImport: hasAbandonHookWorkers,
|
|
4104
3804
|
})
|
|
4105
|
-
const runtimeOutput =
|
|
3805
|
+
const runtimeOutput = renderAstLegacyModuleRegistryOutput({
|
|
4106
3806
|
fileName: 'modules.runtime.generated.ts',
|
|
4107
|
-
generator: 'registry',
|
|
4108
3807
|
imports: runtimeImports,
|
|
4109
3808
|
moduleEntries: runtimeModuleDecls,
|
|
4110
3809
|
includeCreateElementImport: true,
|
|
4111
|
-
includeAbandonHookImport: hasAbandonHookWorkers,
|
|
4112
3810
|
})
|
|
4113
|
-
const frontendRoutesOutput =
|
|
3811
|
+
const frontendRoutesOutput = renderAstLegacyManifestOutput({
|
|
4114
3812
|
fileName: 'frontend-routes.generated.ts',
|
|
4115
3813
|
typeName: 'FrontendRouteManifestEntry',
|
|
4116
3814
|
exportName: 'frontendRoutes',
|
|
4117
3815
|
imports: frontendRouteManifestImports,
|
|
4118
3816
|
entries: frontendRouteManifestDecls,
|
|
4119
3817
|
})
|
|
4120
|
-
const backendRoutesOutput =
|
|
3818
|
+
const backendRoutesOutput = renderAstLegacyManifestOutput({
|
|
4121
3819
|
fileName: 'backend-routes.generated.ts',
|
|
4122
3820
|
typeName: 'BackendRouteManifestEntry',
|
|
4123
3821
|
exportName: 'backendRoutes',
|
|
4124
3822
|
imports: backendRouteManifestImports,
|
|
4125
3823
|
entries: backendRouteManifestDecls,
|
|
4126
3824
|
})
|
|
4127
|
-
const apiRoutesOutput =
|
|
3825
|
+
const apiRoutesOutput = renderAstLegacyManifestOutput({
|
|
4128
3826
|
fileName: 'api-routes.generated.ts',
|
|
4129
3827
|
typeName: 'ApiRouteManifestEntry',
|
|
4130
3828
|
exportName: 'apiRoutes',
|
|
@@ -4264,11 +3962,15 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
4264
3962
|
allRegImports.push(...reg.registrationImports)
|
|
4265
3963
|
allCalls.push(reg.buildCall(reg.entriesExportName))
|
|
4266
3964
|
}
|
|
4267
|
-
const
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
3965
|
+
const uniqueImports = [...new Set([...allEntryImports, ...allRegImports])]
|
|
3966
|
+
const importSection = uniqueImports.join('\n')
|
|
3967
|
+
const body = ` ${allCalls.join('\n ')}`
|
|
3968
|
+
const bootstrapRegsOutput = `// AUTO-GENERATED by mercato generate registry
|
|
3969
|
+
${importSection ? `${importSection}\n` : ''}
|
|
3970
|
+
export function runBootstrapRegistrations(): void {
|
|
3971
|
+
${body}
|
|
3972
|
+
}
|
|
3973
|
+
`
|
|
4272
3974
|
writeGeneratedFile({ outFile: bootstrapRegsOutFile, checksumFile: bootstrapRegsChecksumFile, content: bootstrapRegsOutput, structureChecksum, result, quiet })
|
|
4273
3975
|
}
|
|
4274
3976
|
|
|
@@ -4308,7 +4010,6 @@ async function generateModuleRegistryAppFromDiscovery(options: ModuleRegistryRen
|
|
|
4308
4010
|
const requiresByModule = new Map<string, string[]>()
|
|
4309
4011
|
const commandLoaderEntries: CommandLoaderGenerationEntry[] = []
|
|
4310
4012
|
let hasRouteComponents = false
|
|
4311
|
-
let hasAbandonHookWorkers = false
|
|
4312
4013
|
const seenBackendRoutePatterns = new Map<string, string>()
|
|
4313
4014
|
|
|
4314
4015
|
for (const discovered of discovery.modules) {
|
|
@@ -4470,9 +4171,7 @@ async function generateModuleRegistryAppFromDiscovery(options: ModuleRegistryRen
|
|
|
4470
4171
|
|
|
4471
4172
|
subscribers.push(...processSubscribersAst(await discovered.getSubscribers()))
|
|
4472
4173
|
|
|
4473
|
-
|
|
4474
|
-
if (workersDeclareAbandonHook(discoveredWorkersForModule)) hasAbandonHookWorkers = true
|
|
4475
|
-
workers.push(...processWorkersAst(discoveredWorkersForModule))
|
|
4174
|
+
workers.push(...processWorkersAst(await discovered.getWorkers()))
|
|
4476
4175
|
|
|
4477
4176
|
{
|
|
4478
4177
|
dashboardWidgetsValue = buildModuleDashboardWidgetsValue(discovered.dashboardWidgetEntries)
|
|
@@ -4596,21 +4295,18 @@ async function generateModuleRegistryAppFromDiscovery(options: ModuleRegistryRen
|
|
|
4596
4295
|
imports,
|
|
4597
4296
|
moduleEntries: moduleDecls,
|
|
4598
4297
|
includeCreateElementImport: hasRouteComponents,
|
|
4599
|
-
includeAbandonHookImport: hasAbandonHookWorkers,
|
|
4600
4298
|
})
|
|
4601
4299
|
const bootstrapOutput = renderAstModuleRegistryFile({
|
|
4602
4300
|
fileName: 'modules.bootstrap.generated.ts',
|
|
4603
4301
|
generator: 'registry (bootstrap version)',
|
|
4604
4302
|
imports: bootstrapImports,
|
|
4605
4303
|
moduleEntries: bootstrapModuleDecls,
|
|
4606
|
-
includeAbandonHookImport: hasAbandonHookWorkers,
|
|
4607
4304
|
})
|
|
4608
4305
|
const i18nOutput = renderAstModuleRegistryFile({
|
|
4609
4306
|
fileName: 'modules.i18n.generated.ts',
|
|
4610
4307
|
generator: 'registry (i18n version)',
|
|
4611
4308
|
imports: i18nImports,
|
|
4612
4309
|
moduleEntries: i18nModuleDecls,
|
|
4613
|
-
includeAbandonHookImport: hasAbandonHookWorkers,
|
|
4614
4310
|
})
|
|
4615
4311
|
const legacyOutput = renderAstLegacyAliasFile({
|
|
4616
4312
|
fileName: 'bootstrap-modules.generated.ts',
|
|
@@ -4701,7 +4397,6 @@ async function generateModuleRegistryAppFromDiscovery(options: ModuleRegistryRen
|
|
|
4701
4397
|
* Excludes: frontend routes, backend routes, API handlers, injection widgets
|
|
4702
4398
|
*/
|
|
4703
4399
|
async function generateModuleRegistryCliFromDiscovery(options: ModuleRegistryRenderOptions): Promise<GeneratorResult> {
|
|
4704
|
-
let hasAbandonHookWorkers = false
|
|
4705
4400
|
const { resolver, quiet = false } = options
|
|
4706
4401
|
const { discovery } = options
|
|
4707
4402
|
const result = createGeneratorResult()
|
|
@@ -4853,7 +4548,6 @@ async function generateModuleRegistryCliFromDiscovery(options: ModuleRegistryRen
|
|
|
4853
4548
|
// Workers
|
|
4854
4549
|
const discoveredWorkers = await discovered.getWorkers()
|
|
4855
4550
|
const workerGenerationEntries = collectWorkerGenerationEntries(discoveredWorkers, modId)
|
|
4856
|
-
if (workersDeclareAbandonHook(discoveredWorkers)) hasAbandonHookWorkers = true
|
|
4857
4551
|
workers.push(...processWorkersAst(discoveredWorkers))
|
|
4858
4552
|
devSupervisorWorkers.push(...workerGenerationEntries.map(({ importPath: _importPath, ...worker }) => worker))
|
|
4859
4553
|
|
|
@@ -4977,7 +4671,6 @@ async function generateModuleRegistryCliFromDiscovery(options: ModuleRegistryRen
|
|
|
4977
4671
|
generator: 'registry (CLI version)',
|
|
4978
4672
|
imports,
|
|
4979
4673
|
moduleEntries: moduleDecls,
|
|
4980
|
-
includeAbandonHookImport: hasAbandonHookWorkers,
|
|
4981
4674
|
})
|
|
4982
4675
|
const legacyOutput = renderAstLegacyAliasFile({
|
|
4983
4676
|
fileName: 'cli-modules.generated.ts',
|