@open-mercato/cli 0.6.7-develop.6756.1.5300c41145 → 0.6.7-develop.6766.1.40c9011995

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/build.mjs +2 -1
  3. package/dist/agentic/guides/extensions.md +20 -3
  4. package/dist/agentic/guides/framework-extension-points.md +36 -0
  5. package/dist/agentic/guides/module-facts.json +39708 -230
  6. package/dist/agentic/guides/modules/ai_assistant.md +49 -9
  7. package/dist/agentic/guides/modules/api_docs.md +11 -1
  8. package/dist/agentic/guides/modules/api_keys.md +24 -1
  9. package/dist/agentic/guides/modules/attachments.md +22 -6
  10. package/dist/agentic/guides/modules/audit_logs.md +35 -1
  11. package/dist/agentic/guides/modules/auth.md +79 -15
  12. package/dist/agentic/guides/modules/business_rules.md +36 -3
  13. package/dist/agentic/guides/modules/catalog.md +160 -22
  14. package/dist/agentic/guides/modules/channel_gmail.md +14 -1
  15. package/dist/agentic/guides/modules/channel_imap.md +14 -1
  16. package/dist/agentic/guides/modules/checkout.md +134 -19
  17. package/dist/agentic/guides/modules/communication_channels.md +110 -20
  18. package/dist/agentic/guides/modules/configs.md +15 -1
  19. package/dist/agentic/guides/modules/content.md +11 -1
  20. package/dist/agentic/guides/modules/currencies.md +50 -9
  21. package/dist/agentic/guides/modules/customer_accounts.md +151 -28
  22. package/dist/agentic/guides/modules/customers.md +299 -52
  23. package/dist/agentic/guides/modules/dashboards.md +30 -1
  24. package/dist/agentic/guides/modules/data_sync.md +40 -7
  25. package/dist/agentic/guides/modules/dictionaries.md +24 -6
  26. package/dist/agentic/guides/modules/directory.md +52 -9
  27. package/dist/agentic/guides/modules/entities.md +41 -1
  28. package/dist/agentic/guides/modules/events.md +11 -1
  29. package/dist/agentic/guides/modules/feature_toggles.md +15 -1
  30. package/dist/agentic/guides/modules/gateway_stripe.md +14 -1
  31. package/dist/agentic/guides/modules/generators.md +11 -1
  32. package/dist/agentic/guides/modules/inbox_ops.md +58 -16
  33. package/dist/agentic/guides/modules/integrations.md +30 -7
  34. package/dist/agentic/guides/modules/messages.md +68 -13
  35. package/dist/agentic/guides/modules/notifications.md +13 -1
  36. package/dist/agentic/guides/modules/onboarding.md +13 -1
  37. package/dist/agentic/guides/modules/payment_gateways.md +51 -12
  38. package/dist/agentic/guides/modules/perspectives.md +16 -1
  39. package/dist/agentic/guides/modules/planner.md +33 -9
  40. package/dist/agentic/guides/modules/portal.md +24 -1
  41. package/dist/agentic/guides/modules/progress.md +34 -9
  42. package/dist/agentic/guides/modules/query_index.md +56 -3
  43. package/dist/agentic/guides/modules/record_locks.md +60 -13
  44. package/dist/agentic/guides/modules/resources.md +79 -18
  45. package/dist/agentic/guides/modules/sales.md +238 -48
  46. package/dist/agentic/guides/modules/scheduler.md +23 -7
  47. package/dist/agentic/guides/modules/search.md +28 -3
  48. package/dist/agentic/guides/modules/security.md +106 -23
  49. package/dist/agentic/guides/modules/shipping_carriers.md +38 -10
  50. package/dist/agentic/guides/modules/sso.md +47 -15
  51. package/dist/agentic/guides/modules/staff.md +117 -38
  52. package/dist/agentic/guides/modules/storage_s3.md +13 -1
  53. package/dist/agentic/guides/modules/sync_akeneo.md +13 -1
  54. package/dist/agentic/guides/modules/sync_excel.md +15 -1
  55. package/dist/agentic/guides/modules/system_status_overlays.md +14 -1
  56. package/dist/agentic/guides/modules/translations.md +25 -5
  57. package/dist/agentic/guides/modules/webhooks.md +85 -15
  58. package/dist/agentic/guides/modules/wms.md +234 -31
  59. package/dist/agentic/guides/modules/workflows.md +114 -30
  60. package/dist/agentic/guides/upstream/BACKWARD_COMPATIBILITY.md +7 -0
  61. package/dist/agentic/guides/upstream/manifest.json +2 -2
  62. package/dist/agentic/shared/AGENTS.md.template +2 -2
  63. package/dist/agentic/shared/ai/harness/README.md +2 -0
  64. package/dist/agentic/shared/ai/harness/cases.json +80 -39
  65. package/dist/agentic/shared/ai/skills/om-system-extension/references/mechanism-selector.md +3 -1
  66. package/dist/agentic/shared/ai/skills/om-system-extension/references/unified-overrides.md +2 -1
  67. package/dist/agentic/shared/scripts/framework-context.mjs +3 -9
  68. package/dist/lib/generators/module-extension-facts.js +1185 -0
  69. package/dist/lib/generators/module-extension-facts.js.map +7 -0
  70. package/dist/lib/generators/module-facts.js +134 -7
  71. package/dist/lib/generators/module-facts.js.map +2 -2
  72. package/dist/lib/generators/module-registry.js +1 -0
  73. package/dist/lib/generators/module-registry.js.map +2 -2
  74. package/package.json +5 -5
  75. package/src/lib/generators/__tests__/module-extension-facts.test.ts +402 -0
  76. package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +39 -2
  77. package/src/lib/generators/module-extension-facts.ts +1428 -0
  78. package/src/lib/generators/module-facts.ts +143 -6
  79. package/src/lib/generators/module-registry.ts +1 -1
@@ -1,7 +1,16 @@
1
1
  import fs from 'node:fs'
2
2
  import path from 'node:path'
3
3
  import ts from 'typescript-js'
4
+ import type { ModuleExtensionContributionFact, ModuleExtensionSurfaceFacts } from '@open-mercato/shared/modules/widgets/extension-points'
4
5
  import { toSnake } from '../utils'
6
+ import {
7
+ assertNoUnresolvedExtensionTargets,
8
+ correlateModuleExtensionFacts,
9
+ extractKnownApiRouteIds,
10
+ extractKnownCommandIds,
11
+ extractModuleExtensionFacts,
12
+ renderFrameworkExtensionPointsMarkdown,
13
+ } from './module-extension-facts'
5
14
 
6
15
  export interface ModuleEntityFact {
7
16
  id: string
@@ -49,6 +58,8 @@ export interface ModuleEventFact {
49
58
  label?: string
50
59
  category: string | null
51
60
  entity: string | null
61
+ clientBroadcast?: boolean
62
+ portalBroadcast?: boolean
52
63
  }
53
64
 
54
65
  export interface ModuleHostTokens {
@@ -78,6 +89,7 @@ export interface ModuleFacts {
78
89
  cliCommands: ModuleCliCommandFact[]
79
90
  aiTools: ModuleAiToolFact[]
80
91
  aiAgents: ModuleAiAgentFact[]
92
+ extensionSurfaces?: ModuleExtensionSurfaceFacts
81
93
  warnings: string[]
82
94
  }
83
95
 
@@ -414,7 +426,11 @@ function extractEvents(eventsFilePath: string | null): ModuleEventFact[] {
414
426
  category: category ?? null,
415
427
  entity: entity ?? null,
416
428
  }
429
+ const clientBroadcast = readBooleanPropertyInitializer(element, 'clientBroadcast')
430
+ const portalBroadcast = readBooleanPropertyInitializer(element, 'portalBroadcast')
417
431
  if (label !== undefined) fact.label = label
432
+ if (clientBroadcast !== undefined) fact.clientBroadcast = clientBroadcast
433
+ if (portalBroadcast !== undefined) fact.portalBroadcast = portalBroadcast
418
434
  facts.push(fact)
419
435
  }
420
436
 
@@ -1035,6 +1051,18 @@ export function extractModuleFacts(options: ExtractModuleFactsOptions): ModuleFa
1035
1051
  entityIds: extractHostEntityIds(entities),
1036
1052
  tableIds: extractTableIds(moduleRoot),
1037
1053
  }
1054
+ const extensionSurfaces = extractModuleExtensionFacts({
1055
+ moduleId,
1056
+ moduleRoot,
1057
+ sourceRoot,
1058
+ entities,
1059
+ events,
1060
+ apiRoutes,
1061
+ searchEntities,
1062
+ notifications,
1063
+ aiTools,
1064
+ aiAgents,
1065
+ })
1038
1066
 
1039
1067
  return {
1040
1068
  module: moduleId,
@@ -1058,6 +1086,7 @@ export function extractModuleFacts(options: ExtractModuleFactsOptions): ModuleFa
1058
1086
  cliCommands,
1059
1087
  aiTools,
1060
1088
  aiAgents,
1089
+ extensionSurfaces,
1061
1090
  warnings,
1062
1091
  }
1063
1092
  }
@@ -1066,6 +1095,8 @@ export interface ModuleFactsJsonEvent {
1066
1095
  id: string
1067
1096
  category: string | null
1068
1097
  entity: string | null
1098
+ clientBroadcast?: boolean
1099
+ portalBroadcast?: boolean
1069
1100
  }
1070
1101
 
1071
1102
  export interface ModuleFactsJsonEntry {
@@ -1089,6 +1120,7 @@ export interface ModuleFactsJsonEntry {
1089
1120
  cliCommands: ModuleCliCommandFact[]
1090
1121
  aiTools: ModuleAiToolFact[]
1091
1122
  aiAgents: ModuleAiAgentFact[]
1123
+ extensionSurfaces?: ModuleExtensionSurfaceFacts
1092
1124
  }
1093
1125
 
1094
1126
  const EMPTY_SECTION_MARKER = '_none_'
@@ -1119,9 +1151,13 @@ function renderEntitiesSection(entities: ModuleEntityFact[]): string {
1119
1151
  function renderEventsSection(events: ModuleEventFact[]): string {
1120
1152
  const heading = `## Events (${events.length})`
1121
1153
  if (events.length === 0) return `${heading}\n\n${EMPTY_SECTION_MARKER}`
1122
- const header = '| ID | Category | Entity |'
1123
- const divider = '|---|---|---|'
1124
- const rows = events.map((event) => `| ${event.id} | ${event.category ?? '—'} | ${event.entity ?? '—'} |`)
1154
+ const header = '| ID | Category | Entity | Browser transport |'
1155
+ const divider = '|---|---|---|---|'
1156
+ const rows = events.map((event) => {
1157
+ const transports = [event.clientBroadcast ? 'client' : null, event.portalBroadcast ? 'portal' : null]
1158
+ .filter((value): value is string => value !== null)
1159
+ return `| ${event.id} | ${event.category ?? '—'} | ${event.entity ?? '—'} | ${transports.join(', ') || '—'} |`
1160
+ })
1125
1161
  return [heading, '', header, divider, ...rows].join('\n')
1126
1162
  }
1127
1163
 
@@ -1179,7 +1215,71 @@ function renderHostTokensSection(hostTokens: ModuleHostTokens): string {
1179
1215
  return ['## Host extension points', '', `- Entity IDs: ${entityIdsLine}`, `- Table IDs: ${tableIdsLine}`].join('\n')
1180
1216
  }
1181
1217
 
1218
+ function renderExtensionHostContext(host: ModuleExtensionSurfaceFacts['hosts'][number]): string {
1219
+ return host.contextContract ?? host.runtimeContract ?? host.scopeContract ?? '—'
1220
+ }
1221
+
1222
+ function renderExtensionHostsSection(extensionSurfaces: ModuleExtensionSurfaceFacts): string {
1223
+ const boundHosts = extensionSurfaces.hosts.filter((host) => host.bound)
1224
+ if (boundHosts.length === 0) return `## UMES hosts\n\n${EMPTY_SECTION_MARKER}`
1225
+ const rows = boundHosts.map((host) =>
1226
+ `| ${host.id} | ${host.family} | ${host.capabilities.join(', ') || '—'} | ${renderExtensionHostContext(host)} | ${host.stability.toUpperCase()} |`,
1227
+ )
1228
+ return [
1229
+ '## UMES hosts',
1230
+ '',
1231
+ '| ID / pattern | Family | Supports | Context | Stability |',
1232
+ '|---|---|---|---|---|',
1233
+ ...rows,
1234
+ ].join('\n')
1235
+ }
1236
+
1237
+ function compactContributionDetails(contribution: ModuleExtensionContributionFact): string {
1238
+ const details = contribution.details as unknown as Record<string, unknown>
1239
+ return Object.keys(details).sort((left, right) => left.localeCompare(right)).flatMap((key) => {
1240
+ const value = details[key]
1241
+ if (value === undefined) return []
1242
+ if (Array.isArray(value)) return [`${key}=${value.join(',') || 'none'}`]
1243
+ if (value && typeof value === 'object') {
1244
+ const nested = Object.keys(value as Record<string, unknown>).sort((left, right) => left.localeCompare(right)).map((nestedKey) => {
1245
+ const nestedValue = (value as Record<string, unknown>)[nestedKey]
1246
+ return `${nestedKey}:${Array.isArray(nestedValue) ? nestedValue.join(',') : String(nestedValue)}`
1247
+ })
1248
+ return [`${key}={${nested.join(';')}}`]
1249
+ }
1250
+ return [`${key}=${String(value)}`]
1251
+ }).join('; ')
1252
+ }
1253
+
1254
+ function renderExtensionContributionsSection(extensionSurfaces: ModuleExtensionSurfaceFacts): string {
1255
+ if (extensionSurfaces.contributions.length === 0) return `## UMES contributions\n\n${EMPTY_SECTION_MARKER}`
1256
+ const rows = extensionSurfaces.contributions.map((contribution) => {
1257
+ const targets = contribution.targets.map((entry) => entry.id).join(', ')
1258
+ const resolution = contribution.targets.map((entry) => entry.resolution).join(', ')
1259
+ const phases = [...(contribution.phases ?? []), ...(contribution.operations ?? [])].join(', ') || '—'
1260
+ return `| ${contribution.id} | ${contribution.kind} | ${targets || '—'} | ${phases} | ${compactContributionDetails(contribution)} | ${resolution || '—'} |`
1261
+ })
1262
+ return [
1263
+ '## UMES contributions',
1264
+ '',
1265
+ '| ID | Kind | Target | Phase / operations | Contract | Resolution |',
1266
+ '|---|---|---|---|---|---|',
1267
+ ...rows,
1268
+ ].join('\n')
1269
+ }
1270
+
1271
+ function renderExtensionDiagnosticsSection(extensionSurfaces: ModuleExtensionSurfaceFacts): string {
1272
+ const unbound = extensionSurfaces.hosts.filter((host) => !host.bound)
1273
+ if (unbound.length === 0 && extensionSurfaces.unresolved.length === 0) return ''
1274
+ const diagnostics = [
1275
+ ...unbound.map((host) => `- unbound-helper: ${host.id}`),
1276
+ ...extensionSurfaces.unresolved.map((entry) => `- ${entry.reason}: ${entry.key} (${entry.source.path})`),
1277
+ ]
1278
+ return ['## UMES diagnostics', '', ...diagnostics].join('\n')
1279
+ }
1280
+
1182
1281
  export function renderModuleFactsMarkdown(facts: ModuleFacts): string {
1282
+ const extensionSurfaces = facts.extensionSurfaces ?? { hosts: [], contributions: [], unresolved: [] }
1183
1283
  const sections = [
1184
1284
  `# ${facts.module} — module facts (generated, do not edit)`,
1185
1285
  renderVersionStamp(facts.coreVersion, facts.sourcePackage, facts.sourceVersion),
@@ -1203,6 +1303,12 @@ export function renderModuleFactsMarkdown(facts: ModuleFacts): string {
1203
1303
  '',
1204
1304
  renderHostTokensSection(facts.hostTokens),
1205
1305
  '',
1306
+ renderExtensionHostsSection(extensionSurfaces),
1307
+ '',
1308
+ renderExtensionContributionsSection(extensionSurfaces),
1309
+ '',
1310
+ renderExtensionDiagnosticsSection(extensionSurfaces),
1311
+ '',
1206
1312
  renderInlineListSection('## Notifications', facts.notifications),
1207
1313
  '',
1208
1314
  renderLinkedFactsSection('## CLI commands', facts.cliCommands.map((command) => ({ label: command.command, sourcePath: command.sourcePath }))),
@@ -1224,7 +1330,13 @@ export function toModuleFactsJsonEntry(facts: ModuleFacts): ModuleFactsJsonEntry
1224
1330
  sourceVersion: facts.sourceVersion,
1225
1331
  sourceRoot: facts.sourceRoot,
1226
1332
  entities: facts.entities,
1227
- events: facts.events.map((event) => ({ id: event.id, category: event.category, entity: event.entity })),
1333
+ events: facts.events.map((event) => ({
1334
+ id: event.id,
1335
+ category: event.category,
1336
+ entity: event.entity,
1337
+ ...(event.clientBroadcast !== undefined ? { clientBroadcast: event.clientBroadcast } : {}),
1338
+ ...(event.portalBroadcast !== undefined ? { portalBroadcast: event.portalBroadcast } : {}),
1339
+ })),
1228
1340
  aclFeatures: facts.aclFeatures,
1229
1341
  apiRoutes: facts.apiRoutes,
1230
1342
  diTokens: facts.diTokens,
@@ -1237,6 +1349,7 @@ export function toModuleFactsJsonEntry(facts: ModuleFacts): ModuleFactsJsonEntry
1237
1349
  cliCommands: facts.cliCommands,
1238
1350
  aiTools: facts.aiTools,
1239
1351
  aiAgents: facts.aiAgents,
1352
+ ...(facts.extensionSurfaces ? { extensionSurfaces: facts.extensionSurfaces } : {}),
1240
1353
  }
1241
1354
  }
1242
1355
 
@@ -1273,6 +1386,7 @@ export interface ExtractAllModuleFactsResult {
1273
1386
  factsByModule: Record<string, ModuleFacts>
1274
1387
  markdownByModule: Record<string, string>
1275
1388
  warnings: string[]
1389
+ frameworkMarkdown: string
1276
1390
  }
1277
1391
 
1278
1392
  export function extractAllModuleFacts(options: ExtractAllModuleFactsOptions): ExtractAllModuleFactsResult {
@@ -1299,8 +1413,31 @@ export function extractAllModuleFacts(options: ExtractAllModuleFactsOptions): Ex
1299
1413
  registrySource: options.registrySource ?? null,
1300
1414
  })
1301
1415
  factsByModule[source.moduleId] = facts
1302
- markdownByModule[source.moduleId] = renderModuleFactsMarkdown(facts)
1303
1416
  warnings.push(...facts.warnings)
1304
1417
  }
1305
- return { factsByModule, markdownByModule, warnings }
1418
+ const surfacesByModule = Object.fromEntries(
1419
+ Object.entries(factsByModule).map(([moduleId, facts]) => [
1420
+ moduleId,
1421
+ facts.extensionSurfaces ?? { hosts: [], contributions: [], unresolved: [] },
1422
+ ]),
1423
+ )
1424
+ const correlated = correlateModuleExtensionFacts({
1425
+ surfacesByModule,
1426
+ entityIds: new Set(Object.values(factsByModule).flatMap((facts) => facts.entities.map((entity) => entity.id))),
1427
+ eventIds: new Set(Object.values(factsByModule).flatMap((facts) => facts.events.map((event) => event.id))),
1428
+ apiRoutes: new Set([
1429
+ ...Object.values(factsByModule).flatMap((facts) => facts.apiRoutes.map((route) => route.path)),
1430
+ ...sources.flatMap((source) => extractKnownApiRouteIds(source.moduleId, source.moduleRoot)),
1431
+ ]),
1432
+ commandIds: new Set(sources.flatMap((source) => extractKnownCommandIds(source.moduleId, source.moduleRoot))),
1433
+ })
1434
+ assertNoUnresolvedExtensionTargets(correlated)
1435
+ for (const moduleId of Object.keys(factsByModule).sort((left, right) => left.localeCompare(right))) {
1436
+ factsByModule[moduleId].extensionSurfaces = correlated[moduleId]
1437
+ markdownByModule[moduleId] = renderModuleFactsMarkdown(factsByModule[moduleId])
1438
+ warnings.push(...correlated[moduleId].unresolved.map((entry) =>
1439
+ `[module-facts] ${moduleId} ${entry.reason}: ${entry.key} (${entry.source.path})`,
1440
+ ))
1441
+ }
1442
+ return { factsByModule, markdownByModule, warnings, frameworkMarkdown: renderFrameworkExtensionPointsMarkdown() }
1306
1443
  }
@@ -1157,7 +1157,7 @@ function collectStringArrayElements(expr: ts.Expression, stringConstants: Map<st
1157
1157
  return values
1158
1158
  }
1159
1159
 
1160
- function extractCommandIdsFromSource(sourcePath: string): string[] {
1160
+ export function extractCommandIdsFromSource(sourcePath: string): string[] {
1161
1161
  const sourceText = fs.readFileSync(sourcePath, 'utf8')
1162
1162
  const sourceFile = ts.createSourceFile(sourcePath, sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX)
1163
1163
  const ids = new Set<string>()