@open-mercato/cli 0.6.7-develop.6863.1.61001cf9a8 → 0.6.7

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 (278) hide show
  1. package/.turbo/turbo-build.log +4 -4
  2. package/build.mjs +7 -24
  3. package/dist/agentic/claude-code/hooks/entity-migration-check.ts +88 -32
  4. package/dist/agentic/codex/enforcement-rules.md +16 -2
  5. package/dist/agentic/cursor/hooks/entity-migration-check.mjs +50 -19
  6. package/dist/agentic/cursor/rules/entity-guard.mdc +21 -9
  7. package/dist/agentic/cursor/rules/generated-guard.mdc +5 -3
  8. package/dist/agentic/cursor/rules/open-mercato.mdc +29 -3
  9. package/dist/agentic/guides/cache.md +45 -0
  10. package/dist/agentic/guides/core.md +453 -0
  11. package/dist/agentic/guides/events.md +117 -0
  12. package/dist/agentic/guides/module-facts.json +3833 -115419
  13. package/dist/agentic/guides/module-system.md +127 -12
  14. package/dist/agentic/guides/modules/ai_assistant.md +28 -227
  15. package/dist/agentic/guides/modules/api_docs.md +2 -58
  16. package/dist/agentic/guides/modules/api_keys.md +7 -92
  17. package/dist/agentic/guides/modules/attachments.md +14 -119
  18. package/dist/agentic/guides/modules/audit_logs.md +10 -131
  19. package/dist/agentic/guides/modules/auth.md +33 -276
  20. package/dist/agentic/guides/modules/business_rules.md +14 -149
  21. package/dist/agentic/guides/modules/catalog.md +43 -475
  22. package/dist/agentic/guides/modules/channel_gmail.md +3 -82
  23. package/dist/agentic/guides/modules/channel_imap.md +3 -82
  24. package/dist/agentic/guides/modules/checkout.md +27 -299
  25. package/dist/agentic/guides/modules/communication_channels.md +33 -315
  26. package/dist/agentic/guides/modules/configs.md +8 -104
  27. package/dist/agentic/guides/modules/content.md +2 -57
  28. package/dist/agentic/guides/modules/currencies.md +17 -152
  29. package/dist/agentic/guides/modules/customer_accounts.md +45 -387
  30. package/dist/agentic/guides/modules/customers.md +85 -746
  31. package/dist/agentic/guides/modules/dashboards.md +10 -155
  32. package/dist/agentic/guides/modules/data_sync.md +16 -149
  33. package/dist/agentic/guides/modules/dictionaries.md +12 -107
  34. package/dist/agentic/guides/modules/directory.md +15 -148
  35. package/dist/agentic/guides/modules/entities.md +13 -145
  36. package/dist/agentic/guides/modules/events.md +2 -59
  37. package/dist/agentic/guides/modules/feature_toggles.md +9 -119
  38. package/dist/agentic/guides/modules/gateway_stripe.md +4 -92
  39. package/dist/agentic/guides/modules/generators.md +2 -45
  40. package/dist/agentic/guides/modules/inbox_ops.md +27 -207
  41. package/dist/agentic/guides/modules/integrations.md +16 -146
  42. package/dist/agentic/guides/modules/messages.md +24 -223
  43. package/dist/agentic/guides/modules/notifications.md +8 -96
  44. package/dist/agentic/guides/modules/onboarding.md +6 -77
  45. package/dist/agentic/guides/modules/payment_gateways.md +21 -164
  46. package/dist/agentic/guides/modules/perspectives.md +7 -77
  47. package/dist/agentic/guides/modules/planner.md +18 -136
  48. package/dist/agentic/guides/modules/portal.md +2 -93
  49. package/dist/agentic/guides/modules/progress.md +14 -104
  50. package/dist/agentic/guides/modules/query_index.md +15 -154
  51. package/dist/agentic/guides/modules/record_locks.md +21 -206
  52. package/dist/agentic/guides/modules/resources.md +30 -197
  53. package/dist/agentic/guides/modules/sales.md +84 -678
  54. package/dist/agentic/guides/modules/scheduler.md +14 -133
  55. package/dist/agentic/guides/modules/search.md +6 -170
  56. package/dist/agentic/guides/modules/security.md +35 -294
  57. package/dist/agentic/guides/modules/shipping_carriers.md +18 -134
  58. package/dist/agentic/guides/modules/sso.md +26 -151
  59. package/dist/agentic/guides/modules/staff.md +57 -369
  60. package/dist/agentic/guides/modules/storage_s3.md +5 -95
  61. package/dist/agentic/guides/modules/sync_akeneo.md +3 -85
  62. package/dist/agentic/guides/modules/sync_excel.md +6 -75
  63. package/dist/agentic/guides/modules/system_status_overlays.md +2 -60
  64. package/dist/agentic/guides/modules/translations.md +10 -104
  65. package/dist/agentic/guides/modules/webhooks.md +24 -203
  66. package/dist/agentic/guides/modules/wms.md +46 -441
  67. package/dist/agentic/guides/modules/workflows.md +43 -302
  68. package/dist/agentic/guides/queue.md +53 -0
  69. package/dist/agentic/guides/search.md +115 -0
  70. package/dist/agentic/guides/shared.md +108 -0
  71. package/dist/agentic/guides/ui.md +347 -0
  72. package/dist/agentic/shared/AGENTS.md.template +311 -124
  73. package/dist/agentic/shared/ai/agentic.config.json +0 -2
  74. package/dist/agentic/shared/ai/lessons.md +3 -26
  75. package/dist/agentic/shared/ai/skills/om-auto-continue-pr-loop/SKILL.md +27 -0
  76. package/dist/agentic/shared/ai/skills/om-auto-create-pr-loop/SKILL.md +27 -0
  77. package/dist/agentic/shared/ai/skills/om-auto-review-pr/SKILL.md +0 -4
  78. package/dist/agentic/shared/ai/skills/om-backend-ui-design/SKILL.md +241 -20
  79. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/ui-components.md +260 -0
  80. package/dist/agentic/shared/ai/skills/om-data-model-design/SKILL.md +601 -16
  81. package/dist/agentic/shared/ai/skills/om-data-model-design/references/mikro-orm-cheatsheet.md +146 -0
  82. package/dist/agentic/shared/ai/skills/om-eject-and-customize/SKILL.md +310 -14
  83. package/dist/agentic/shared/ai/skills/om-help/SKILL.md +97 -15
  84. package/dist/agentic/shared/ai/skills/om-help/references/skills-catalog.md +84 -0
  85. package/dist/agentic/shared/ai/skills/om-help/references/workflow-sequences.md +193 -0
  86. package/dist/agentic/shared/ai/skills/om-implement-spec/SKILL.md +152 -33
  87. package/dist/agentic/shared/ai/skills/om-integration-builder/SKILL.md +708 -24
  88. package/dist/agentic/shared/ai/skills/om-integration-builder/STANDALONE.md +34 -0
  89. package/dist/agentic/shared/ai/skills/om-integration-builder/references/adapter-contracts.md +762 -0
  90. package/dist/agentic/shared/ai/skills/om-module-scaffold/SKILL.md +820 -20
  91. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/naming-conventions.md +50 -0
  92. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/navigation-patterns.md +97 -0
  93. package/dist/agentic/shared/ai/skills/om-system-extension/SKILL.md +843 -19
  94. package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-contracts.md +271 -0
  95. package/dist/agentic/shared/ai/skills/om-trim-unused-modules/SKILL.md +63 -15
  96. package/dist/agentic/shared/ai/skills/om-troubleshooter/SKILL.md +467 -16
  97. package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnostic-commands.md +101 -0
  98. package/dist/agentic/shared/ai/skills/tiers.json +21 -143
  99. package/dist/agentic/shared/ai/skills/tiers.schema.json +40 -52
  100. package/dist/agentic/shared/ai/specs/README.md +3 -4
  101. package/dist/agentic/shared/ai/specs/SPEC-000-template.md +10 -226
  102. package/dist/agentic/shared/ai/trackers/github.md +4 -108
  103. package/dist/agentic/shared/scripts/install-skills.sh +694 -4
  104. package/dist/bin.js +1 -13
  105. package/dist/bin.js.map +2 -2
  106. package/dist/lib/__integration__/TC-INT-008.spec.js +8 -88
  107. package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
  108. package/dist/lib/agentic-init.js +3 -13
  109. package/dist/lib/agentic-init.js.map +2 -2
  110. package/dist/lib/agentic-setup.js +186 -418
  111. package/dist/lib/agentic-setup.js.map +2 -2
  112. package/dist/lib/generators/extensions/injection-widgets.js +0 -20
  113. package/dist/lib/generators/extensions/injection-widgets.js.map +2 -2
  114. package/dist/lib/generators/module-facts-discovery.js +7 -41
  115. package/dist/lib/generators/module-facts-discovery.js.map +2 -2
  116. package/dist/lib/generators/module-facts.js +45 -1387
  117. package/dist/lib/generators/module-facts.js.map +3 -3
  118. package/dist/lib/generators/module-registry.js +5 -11
  119. package/dist/lib/generators/module-registry.js.map +2 -2
  120. package/dist/lib/resolver.js +0 -2
  121. package/dist/lib/resolver.js.map +2 -2
  122. package/dist/lib/testing/integration.js +0 -5
  123. package/dist/lib/testing/integration.js.map +2 -2
  124. package/dist/mercato.js +1 -23
  125. package/dist/mercato.js.map +2 -2
  126. package/package.json +11 -13
  127. package/src/bin.ts +1 -33
  128. package/src/lib/__integration__/TC-INT-008.spec.ts +9 -107
  129. package/src/lib/__tests__/agentic-init.test.ts +5 -41
  130. package/src/lib/agentic-init.ts +3 -15
  131. package/src/lib/agentic-setup.ts +224 -530
  132. package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +2 -88
  133. package/src/lib/generators/__tests__/module-facts.customers.fixture.test.ts +0 -1
  134. package/src/lib/generators/__tests__/module-facts.discovery.test.ts +10 -54
  135. package/src/lib/generators/__tests__/module-subset.test.ts +0 -18
  136. package/src/lib/generators/extensions/injection-widgets.ts +0 -51
  137. package/src/lib/generators/module-facts-discovery.ts +7 -58
  138. package/src/lib/generators/module-facts.ts +46 -1851
  139. package/src/lib/generators/module-registry.ts +6 -16
  140. package/src/lib/resolver.ts +0 -3
  141. package/src/lib/testing/__tests__/integration.test.ts +0 -4
  142. package/src/lib/testing/integration.ts +0 -5
  143. package/src/mercato.ts +1 -26
  144. package/dist/agentic/guides/ai-workflows.md +0 -76
  145. package/dist/agentic/guides/architecture.md +0 -107
  146. package/dist/agentic/guides/backend-ui.md +0 -80
  147. package/dist/agentic/guides/contracts.md +0 -92
  148. package/dist/agentic/guides/extensions.md +0 -121
  149. package/dist/agentic/guides/framework-extension-points.md +0 -36
  150. package/dist/agentic/guides/integrations.md +0 -81
  151. package/dist/agentic/guides/modules/design_system.md +0 -102
  152. package/dist/agentic/guides/spec-delivery.md +0 -22
  153. package/dist/agentic/guides/testing-debugging.md +0 -80
  154. package/dist/agentic/guides/upstream/AGENTS.md +0 -298
  155. package/dist/agentic/guides/upstream/BACKWARD_COMPATIBILITY.md +0 -316
  156. package/dist/agentic/guides/upstream/manifest.json +0 -8
  157. package/dist/agentic/shared/ai/harness/README.md +0 -50
  158. package/dist/agentic/shared/ai/harness/RELEASE.md +0 -57
  159. package/dist/agentic/shared/ai/harness/cases.json +0 -13680
  160. package/dist/agentic/shared/ai/harness/cases.schema.json +0 -133
  161. package/dist/agentic/shared/ai/harness/fixtures/index.json +0 -49
  162. package/dist/agentic/shared/ai/harness/fixtures/seeds.json +0 -162
  163. package/dist/agentic/shared/ai/harness/generated-code-review-policy.md +0 -21
  164. package/dist/agentic/shared/ai/harness/generated-code-review-response.schema.json +0 -96
  165. package/dist/agentic/shared/ai/harness/generated-code-review-result.schema.json +0 -172
  166. package/dist/agentic/shared/ai/harness/release-matrix.json +0 -158
  167. package/dist/agentic/shared/ai/harness/release-result.schema.json +0 -219
  168. package/dist/agentic/shared/ai/harness/result.schema.json +0 -76
  169. package/dist/agentic/shared/ai/harness/routing-response.schema.json +0 -12
  170. package/dist/agentic/shared/ai/harness/target-validation-result.schema.json +0 -73
  171. package/dist/agentic/shared/ai/harness/validators.json +0 -78
  172. package/dist/agentic/shared/ai/harness/writable-ast-oracles.mjs +0 -2121
  173. package/dist/agentic/shared/ai/harness/writable-behavior-oracles.mjs +0 -1096
  174. package/dist/agentic/shared/ai/lessons/_template.md +0 -16
  175. package/dist/agentic/shared/ai/review-checklist.md +0 -36
  176. package/dist/agentic/shared/ai/skills/om-auto-implement-spec/SKILL.md +0 -21
  177. package/dist/agentic/shared/ai/skills/om-auto-upgrade-0.6.6-to-0.6.7/SKILL.md +0 -98
  178. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/crud-surfaces.md +0 -16
  179. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/frontend-and-design-system.md +0 -53
  180. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/page-and-navigation.md +0 -13
  181. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/quality-states.md +0 -11
  182. package/dist/agentic/shared/ai/skills/om-build-workflow/SKILL.md +0 -30
  183. package/dist/agentic/shared/ai/skills/om-build-workflow/references/activity-contracts.md +0 -12
  184. package/dist/agentic/shared/ai/skills/om-build-workflow/references/durability-and-progress.md +0 -13
  185. package/dist/agentic/shared/ai/skills/om-build-workflow/references/workflow-design.md +0 -14
  186. package/dist/agentic/shared/ai/skills/om-create-ai-agent/SKILL.md +0 -28
  187. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/attachments-and-overrides.md +0 -12
  188. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/module-agents-and-tools.md +0 -22
  189. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/orchestrator-agents.md +0 -12
  190. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/surface-selector.md +0 -19
  191. package/dist/agentic/shared/ai/skills/om-data-model-design/references/integrity-and-concurrency.md +0 -19
  192. package/dist/agentic/shared/ai/skills/om-data-model-design/references/migration-workflow.md +0 -13
  193. package/dist/agentic/shared/ai/skills/om-data-model-design/references/schema-design.md +0 -14
  194. package/dist/agentic/shared/ai/skills/om-data-model-design/references/sensitive-data.md +0 -10
  195. package/dist/agentic/shared/ai/skills/om-eject-and-customize/references/decision-and-procedure.md +0 -17
  196. package/dist/agentic/shared/ai/skills/om-evolve-harness/SKILL.md +0 -29
  197. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-template.md +0 -100
  198. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-workflow.md +0 -16
  199. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/owner-selection.md +0 -17
  200. package/dist/agentic/shared/ai/skills/om-framework-context/SKILL.md +0 -25
  201. package/dist/agentic/shared/ai/skills/om-framework-context/references/resolver-procedure.md +0 -11
  202. package/dist/agentic/shared/ai/skills/om-framework-context/references/skew-and-escalation.md +0 -13
  203. package/dist/agentic/shared/ai/skills/om-help/references/delivery-workflows.md +0 -18
  204. package/dist/agentic/shared/ai/skills/om-help/references/task-families.md +0 -20
  205. package/dist/agentic/shared/ai/skills/om-implement-spec/references/phases-and-gates.md +0 -33
  206. package/dist/agentic/shared/ai/skills/om-implement-spec/references/planning-and-progress.md +0 -40
  207. package/dist/agentic/shared/ai/skills/om-implement-spec/references/report-templates.md +0 -27
  208. package/dist/agentic/shared/ai/skills/om-implement-spec/references/spec-resolution.md +0 -24
  209. package/dist/agentic/shared/ai/skills/om-integration-builder/references/package-and-activation.md +0 -16
  210. package/dist/agentic/shared/ai/skills/om-integration-builder/references/provider-families.md +0 -14
  211. package/dist/agentic/shared/ai/skills/om-integration-builder/references/security-and-reliability.md +0 -15
  212. package/dist/agentic/shared/ai/skills/om-integration-builder/references/sync-and-files.md +0 -12
  213. package/dist/agentic/shared/ai/skills/om-judge-agent-session/SKILL.md +0 -34
  214. package/dist/agentic/shared/ai/skills/om-judge-agent-session/agents/openai.yaml +0 -4
  215. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/agentic-setup.md +0 -11
  216. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/input-normalization.md +0 -31
  217. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/judge-workflow.md +0 -39
  218. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/report-template.md +0 -43
  219. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/rules.md +0 -11
  220. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/api-and-domain.md +0 -19
  221. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/business-one-shot-blueprints.md +0 -172
  222. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/data-and-migrations.md +0 -12
  223. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/discovery-surface-catalog.md +0 -83
  224. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/module-surfaces.md +0 -21
  225. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/planning.md +0 -11
  226. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/runtime-cache-and-queues.md +0 -22
  227. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/verification.md +0 -13
  228. package/dist/agentic/shared/ai/skills/om-share-this-session/SKILL.md +0 -41
  229. package/dist/agentic/shared/ai/skills/om-share-this-session/references/agentic-setup.md +0 -19
  230. package/dist/agentic/shared/ai/skills/om-share-this-session/references/bundle-preparation.md +0 -44
  231. package/dist/agentic/shared/ai/skills/om-share-this-session/references/consent-and-review.md +0 -39
  232. package/dist/agentic/shared/ai/skills/om-share-this-session/references/publication.md +0 -20
  233. package/dist/agentic/shared/ai/skills/om-share-this-session/references/report-templates.md +0 -57
  234. package/dist/agentic/shared/ai/skills/om-share-this-session/references/rules.md +0 -11
  235. package/dist/agentic/shared/ai/skills/om-share-this-session/scripts/prepare-share-bundle.mjs +0 -486
  236. package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-branches.md +0 -18
  237. package/dist/agentic/shared/ai/skills/om-system-extension/references/mechanism-selector.md +0 -27
  238. package/dist/agentic/shared/ai/skills/om-system-extension/references/read-write-roundtrip.md +0 -13
  239. package/dist/agentic/shared/ai/skills/om-system-extension/references/unified-overrides.md +0 -41
  240. package/dist/agentic/shared/ai/skills/om-system-extension/references/verification.md +0 -11
  241. package/dist/agentic/shared/ai/skills/om-trim-unused-modules/references/dependency-and-redirect.md +0 -15
  242. package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnosis-map.md +0 -16
  243. package/dist/agentic/shared/ai/skills/om-troubleshooter/references/regression-oracles.md +0 -14
  244. package/dist/agentic/shared/scripts/agent-harness-tool-server.mjs +0 -187
  245. package/dist/agentic/shared/scripts/check-lessons.mjs +0 -178
  246. package/dist/agentic/shared/scripts/evaluate-agent-harness.mjs +0 -2958
  247. package/dist/agentic/shared/scripts/execution-sandbox.mjs +0 -329
  248. package/dist/agentic/shared/scripts/framework-context.mjs +0 -888
  249. package/dist/agentic/shared/scripts/install-skills.mjs +0 -1029
  250. package/dist/agentic/shared/scripts/prepare-agent-harness-fixture.mjs +0 -222
  251. package/dist/agentic/shared/scripts/run-agent-harness-release.mjs +0 -1774
  252. package/dist/lib/generators/module-extension-facts.js +0 -1840
  253. package/dist/lib/generators/module-extension-facts.js.map +0 -7
  254. package/dist/lib/generators/module-fact-sources.js +0 -70
  255. package/dist/lib/generators/module-fact-sources.js.map +0 -7
  256. package/dist/lib/generators/module-override-targets.js +0 -688
  257. package/dist/lib/generators/module-override-targets.js.map +0 -7
  258. package/dist/lib/load-env.js +0 -24
  259. package/dist/lib/load-env.js.map +0 -7
  260. package/dist/lib/telemetry-init.js +0 -358
  261. package/dist/lib/telemetry-init.js.map +0 -7
  262. package/src/lib/__tests__/agentic-setup.ownership.test.ts +0 -386
  263. package/src/lib/__tests__/injection-widget-id-validation.test.ts +0 -184
  264. package/src/lib/__tests__/load-env.test.ts +0 -65
  265. package/src/lib/__tests__/telemetry-init.test.ts +0 -298
  266. package/src/lib/generators/__tests__/activation-adapter-coverage.test.ts +0 -92
  267. package/src/lib/generators/__tests__/module-extension-activations.test.ts +0 -762
  268. package/src/lib/generators/__tests__/module-extension-facts.test.ts +0 -404
  269. package/src/lib/generators/__tests__/module-facts.extension-hosts.test.ts +0 -108
  270. package/src/lib/generators/__tests__/module-facts.owned-contracts.test.ts +0 -561
  271. package/src/lib/generators/__tests__/module-facts.source-links.test.ts +0 -119
  272. package/src/lib/generators/__tests__/module-override-targets.roundtrip.test.ts +0 -149
  273. package/src/lib/generators/__tests__/module-override-targets.test.ts +0 -304
  274. package/src/lib/generators/module-extension-facts.ts +0 -2365
  275. package/src/lib/generators/module-fact-sources.ts +0 -108
  276. package/src/lib/generators/module-override-targets.ts +0 -863
  277. package/src/lib/load-env.ts +0 -30
  278. package/src/lib/telemetry-init.ts +0 -461
@@ -1,30 +0,0 @@
1
- import fs from 'node:fs'
2
- import path from 'node:path'
3
-
4
- /**
5
- * Bootstrap-free `.env` loader for the CLI binary. `bin.ts` must load the app's
6
- * `.env` BEFORE `initTelemetry()` so `TELEMETRY_*` set only in `.env` resolves a
7
- * real backend for worker/scheduler processes — `run()`'s `ensureEnvLoaded()`
8
- * happens after telemetry init, which is too late. Deliberately read-only (no
9
- * `.env.example` copy — that UX stays in `ensureEnvLoaded`) and pulls in only the
10
- * resolver + dotenv, so nothing here loads `pg` and the OTEL instrumentation
11
- * load-order guarantee is preserved.
12
- */
13
- export async function loadAppEnv(options: { cwd?: string } = {}): Promise<void> {
14
- try {
15
- const { createResolver } = await import('./resolver.js')
16
- const appDir = createResolver(options.cwd).getAppDir()
17
- const envPath = path.join(appDir, '.env')
18
- if (fs.existsSync(envPath)) {
19
- const dotenv = await import('dotenv')
20
- dotenv.config({ path: envPath, quiet: true })
21
- return
22
- }
23
- } catch {
24
- // Resolver can fail outside an app dir — fall through to plain cwd loading.
25
- }
26
- try {
27
- const dotenv = await import('dotenv')
28
- dotenv.config({ quiet: true })
29
- } catch {}
30
- }
@@ -1,461 +0,0 @@
1
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs'
2
- import { dirname, join, resolve } from 'node:path'
3
-
4
- /**
5
- * `mercato telemetry init` — wire `@open-mercato/telemetry` into an app that was
6
- * scaffolded before telemetry existed. Deterministic, idempotent, and safe to
7
- * re-run: each step detects whether it is already applied and skips.
8
- *
9
- * The web-tier wiring lives in app-owned source files (a dependency bump cannot
10
- * touch them), so this patches them in place using the same idioms the rest of
11
- * the CLI uses: JSON edits, detect-before-append for `.env`, a ts-morph edit for
12
- * `next.config.ts`, and anchored insertion for `instrumentation.ts` + the API
13
- * dispatcher. When a file's shape is not recognized (a customized dispatcher, an
14
- * unusual next.config), the step degrades to printing the exact snippet and
15
- * flags it as a manual step rather than editing code it does not understand.
16
- *
17
- * Worker/scheduler telemetry is not handled here — it ships transitively via
18
- * `@open-mercato/cli`'s telemetry dependency once the app updates its packages.
19
- */
20
-
21
- const BULLMQ_OTEL_VERSION = '^1.3.1'
22
-
23
- type StepStatus = 'created' | 'patched' | 'skipped' | 'manual'
24
-
25
- type StepResult = {
26
- file: string
27
- status: StepStatus
28
- detail: string
29
- /** Snippet to show when the step needs manual work. */
30
- manualSnippet?: string
31
- }
32
-
33
- type TelemetryInitOptions = {
34
- dryRun: boolean
35
- }
36
-
37
- const ENV_BLOCK = `
38
- # --- Telemetry & Observability (vendor-neutral OTLP: traces, logs, metrics, errors) ---
39
- # Off by default: leave TELEMETRY_BACKEND unset (or =noop) for a hard no-op
40
- # (the OpenTelemetry SDK is never loaded). Set to 'console' for local span/metric
41
- # output, or an OTLP backend to export: 'signoz' | 'newrelic' | 'otlp' (generic).
42
- # All three OTLP names use the same exporter — they differ only by the endpoint +
43
- # headers below. Any OTLP backend is a one-line swap; no code change.
44
- # TELEMETRY_BACKEND=otlp
45
- # Logs use the shared logger facade and its OM_LOG_LEVEL / OM_LOG_PRETTY /
46
- # OM_LOG_DESTINATION controls. Telemetry adds remote export; it does not create
47
- # a second local output path.
48
- # TELEMETRY_SAMPLING_RATIO=1.0 # 0.0–1.0 (default 1.0 dev / 0.1 prod)
49
- # TELEMETRY_TRUST_INBOUND_TRACE=false # default false: root-per-request (ignore an
50
- # # inbound traceparent from a proxy/LB). Set true
51
- # # only behind a trusted upstream whose trace continues.
52
- # # This also enables richer bullmq-otel spans;
53
- # # otherwise async queues use metadata._trace.
54
- #
55
- # OTLP endpoint + auth — pick ONE vendor (use your region's host):
56
- # SigNoz Cloud:
57
- # OTEL_EXPORTER_OTLP_ENDPOINT=https://ingest.<region>.signoz.cloud:443
58
- # OTEL_EXPORTER_OTLP_HEADERS=signoz-ingestion-key=<your-ingestion-key>
59
- # New Relic (OTLP-native; EU host shown, US is https://otlp.nr-data.net):
60
- # OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp.eu01.nr-data.net
61
- # OTEL_EXPORTER_OTLP_HEADERS=api-key=<your-ingest-license-key>
62
- #
63
- # Resource identity: keep one stable service name across environments and
64
- # separate envs via the deployment.environment resource attribute.
65
- # OTEL_SERVICE_NAME=open-mercato
66
- # OTEL_RESOURCE_ATTRIBUTES=deployment.environment=local
67
- `
68
-
69
- const INSTRUMENTATION_TS = `import { isTelemetryBackendEnabled } from '@open-mercato/shared/lib/telemetry/runtime'
70
-
71
- export async function register(): Promise<void> {
72
- // Initialize telemetry (no-op unless TELEMETRY_BACKEND is set). OTEL's NodeSDK
73
- // is Node-only and incompatible with the edge runtime, so the telemetry
74
- // bootstrap — which can pull in the SDK — is imported only on the Node.js
75
- // runtime. The helper owns init + graceful degrade + shutdown flush.
76
- if (
77
- process.env.NEXT_RUNTIME === 'nodejs'
78
- && isTelemetryBackendEnabled()
79
- ) {
80
- const { registerTelemetryForNextjs } = await import('@open-mercato/telemetry/nextjs')
81
- await registerTelemetryForNextjs()
82
- }
83
- }
84
- `
85
-
86
- const DISPATCHER_SNIPPET = ` // add near the other imports:
87
- import { getTelemetryRuntime } from '@open-mercato/shared/lib/telemetry/runtime'
88
-
89
- // in the dispatcher's success path, just before returning the response:
90
- getTelemetryRuntime()?.recordHttpDuration(method, match.route.path, finalResponse.status, startedAt)
91
-
92
- // in the dispatcher's catch (error) block, before re-throwing:
93
- getTelemetryRuntime()?.reportError(error, {
94
- attributes: { 'http.request.method': method, 'http.route': match.route.path, 'http.response.status_code': 500 },
95
- })
96
- getTelemetryRuntime()?.recordHttpDuration(method, match.route.path, 500, startedAt)`
97
-
98
- function parseArgs(args: string[]): TelemetryInitOptions {
99
- return {
100
- dryRun: args.includes('--dry-run') || args.includes('-n'),
101
- }
102
- }
103
-
104
- /** Read the version an app already pins its `@open-mercato/*` deps to (lockstep). */
105
- function resolveOpenMercatoVersion(pkg: Record<string, unknown>): string {
106
- for (const field of ['dependencies', 'devDependencies'] as const) {
107
- const deps = pkg[field]
108
- if (deps && typeof deps === 'object') {
109
- for (const [name, version] of Object.entries(deps as Record<string, string>)) {
110
- if (name.startsWith('@open-mercato/') && typeof version === 'string') return version
111
- }
112
- }
113
- }
114
- return '*'
115
- }
116
-
117
- function patchPackageJson(appDir: string, options: TelemetryInitOptions): StepResult {
118
- const file = 'package.json'
119
- const path = join(appDir, file)
120
- const raw = readFileSync(path, 'utf8')
121
- const pkg = JSON.parse(raw) as {
122
- dependencies?: Record<string, string>
123
- optionalDependencies?: Record<string, string>
124
- }
125
- const version = resolveOpenMercatoVersion(pkg)
126
- const hasTelemetry = Boolean(pkg.dependencies?.['@open-mercato/telemetry'])
127
- const hasBullmqOtel = Boolean(pkg.optionalDependencies?.['bullmq-otel'])
128
- if (hasTelemetry && hasBullmqOtel) {
129
- return { file, status: 'skipped', detail: '@open-mercato/telemetry already installed' }
130
- }
131
-
132
- const deps = { ...(pkg.dependencies ?? {}) }
133
- if (!hasTelemetry) deps['@open-mercato/telemetry'] = version
134
- const optDeps = { ...(pkg.optionalDependencies ?? {}) }
135
- if (!hasBullmqOtel) optDeps['bullmq-otel'] = BULLMQ_OTEL_VERSION
136
-
137
- const next = {
138
- ...pkg,
139
- dependencies: sortRecord(deps),
140
- optionalDependencies: sortRecord(optDeps),
141
- }
142
- if (!options.dryRun) writeFileSync(path, `${JSON.stringify(next, null, 2)}\n`)
143
- return {
144
- file,
145
- status: 'patched',
146
- detail: `+@open-mercato/telemetry@${version}${hasBullmqOtel ? '' : ` +bullmq-otel@${BULLMQ_OTEL_VERSION} (optional)`} — run \`yarn install\``,
147
- }
148
- }
149
-
150
- function sortRecord(record: Record<string, string>): Record<string, string> {
151
- return Object.fromEntries(Object.entries(record).sort(([a], [b]) => a.localeCompare(b)))
152
- }
153
-
154
- function patchEnvFile(appDir: string, relativePath: string, options: TelemetryInitOptions): StepResult | null {
155
- const path = join(appDir, relativePath)
156
- if (!existsSync(path)) return null
157
- const content = readFileSync(path, 'utf8')
158
- if (content.includes('TELEMETRY_BACKEND')) {
159
- return { file: relativePath, status: 'skipped', detail: 'TELEMETRY_* block already present' }
160
- }
161
- const next = `${content.replace(/\s*$/, '')}\n${ENV_BLOCK}`
162
- if (!options.dryRun) writeFileSync(path, next)
163
- return { file: relativePath, status: 'patched', detail: 'appended commented TELEMETRY_* / OTEL_* block' }
164
- }
165
-
166
- function patchInstrumentation(appDir: string, options: TelemetryInitOptions): StepResult {
167
- const file = 'src/instrumentation.ts'
168
- const path = join(appDir, file)
169
- if (!existsSync(path)) {
170
- if (!options.dryRun) {
171
- mkdirSync(dirname(path), { recursive: true })
172
- writeFileSync(path, INSTRUMENTATION_TS)
173
- }
174
- return { file, status: 'created', detail: 'Node-runtime-guarded registerTelemetryForNextjs() bootstrap' }
175
- }
176
- const content = readFileSync(path, 'utf8')
177
- if (content.includes('registerTelemetryForNextjs')) {
178
- if (content.includes('isTelemetryBackendEnabled')) {
179
- return { file, status: 'skipped', detail: 'telemetry already wired' }
180
- }
181
- const migrated =
182
- `import { isTelemetryBackendEnabled } from '@open-mercato/shared/lib/telemetry/runtime'\n` +
183
- content.replace(
184
- `if (process.env.NEXT_RUNTIME === 'nodejs') {`,
185
- `if (process.env.NEXT_RUNTIME === 'nodejs' && isTelemetryBackendEnabled()) {`,
186
- )
187
- if (!options.dryRun) writeFileSync(path, migrated)
188
- return { file, status: 'patched', detail: 'added the explicit backend import guard' }
189
- }
190
- const anchor = content.match(/export\s+async\s+function\s+register\s*\([^)]*\)\s*:\s*Promise<void>\s*\{/)
191
- if (!anchor || anchor.index === undefined) {
192
- return {
193
- file,
194
- status: 'manual',
195
- detail: 'register() not found — add the telemetry bootstrap manually',
196
- manualSnippet: INSTRUMENTATION_TS,
197
- }
198
- }
199
- const insertAt = anchor.index + anchor[0].length
200
- const block =
201
- `\n // Initialize telemetry (no-op unless TELEMETRY_BACKEND is set); Node-only.` +
202
- `\n if (process.env.NEXT_RUNTIME === 'nodejs' && isTelemetryBackendEnabled()) {` +
203
- `\n const { registerTelemetryForNextjs } = await import('@open-mercato/telemetry/nextjs')` +
204
- `\n await registerTelemetryForNextjs()` +
205
- `\n }`
206
- const importLine = `import { isTelemetryBackendEnabled } from '@open-mercato/shared/lib/telemetry/runtime'\n`
207
- const withImport = content.includes('isTelemetryBackendEnabled')
208
- ? content
209
- : importLine + content
210
- const shiftedInsertAt = insertAt + (withImport.length - content.length)
211
- const next = withImport.slice(0, shiftedInsertAt) + block + withImport.slice(shiftedInsertAt)
212
- if (!options.dryRun) writeFileSync(path, next)
213
- return { file, status: 'patched', detail: 'inserted registerTelemetryForNextjs() into register()' }
214
- }
215
-
216
- async function patchNextConfig(appDir: string, options: TelemetryInitOptions): Promise<StepResult> {
217
- const file = 'next.config.ts'
218
- const path = join(appDir, file)
219
- if (!existsSync(path)) {
220
- return { file, status: 'manual', detail: 'next.config.ts not found', manualSnippet: nextConfigSnippet() }
221
- }
222
- // Use ts-morph to *detect* the real `serverExternalPackages` array literal
223
- // (robust against a match inside a comment/string), then do the *insertion*
224
- // via a formatting-preserving text splice so the user's config stays tidy.
225
- const { Project, SyntaxKind } = await import('ts-morph')
226
- const project = new Project({ skipAddingFilesFromTsConfig: true, skipFileDependencyResolution: true })
227
- const sf = project.addSourceFileAtPath(path)
228
-
229
- const telemetryConfigImport = sf
230
- .getImportDeclarations()
231
- .find((decl) => [
232
- '@open-mercato/telemetry/nextjs',
233
- '@open-mercato/telemetry/nextjs-config',
234
- ].includes(decl.getModuleSpecifierValue()))
235
- const hasImport = Boolean(telemetryConfigImport)
236
- const hasCanonicalImport =
237
- telemetryConfigImport?.getModuleSpecifierValue() === '@open-mercato/telemetry/nextjs-config'
238
-
239
- const arrayProp = sf
240
- .getDescendantsOfKind(SyntaxKind.PropertyAssignment)
241
- .find((prop) => prop.getName() === 'serverExternalPackages')
242
- const arrayInit = arrayProp?.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression)
243
- if (!arrayInit) {
244
- return {
245
- file,
246
- status: 'manual',
247
- detail: 'serverExternalPackages array not found',
248
- manualSnippet: nextConfigSnippet(),
249
- }
250
- }
251
- const hasSpread = arrayInit.getElements().some((el) => el.getText().includes('telemetryServerExternalPackages'))
252
- if (hasCanonicalImport && hasSpread) {
253
- return { file, status: 'skipped', detail: 'telemetryServerExternalPackages already wired' }
254
- }
255
-
256
- let text = readFileSync(path, 'utf8')
257
- // Splice the array first, using the AST node's byte offsets (formatting-agnostic:
258
- // handles both single-line and multi-line arrays). Do this before modifying
259
- // imports, because either an inserted import or the legacy import migration
260
- // shifts the array offsets captured from the original source.
261
- if (!hasSpread) {
262
- const start = arrayInit.getStart()
263
- const end = arrayInit.getEnd()
264
- text = text.slice(0, start) + insertSpread(text.slice(start, end)) + text.slice(end)
265
- }
266
- text = text.replace(
267
- "from '@open-mercato/telemetry/nextjs'",
268
- "from '@open-mercato/telemetry/nextjs-config'",
269
- )
270
- if (!hasImport) {
271
- const importRegex = /^import[^\n]*$/gm
272
- let lastImport: RegExpExecArray | null = null
273
- let match: RegExpExecArray | null
274
- while ((match = importRegex.exec(text)) !== null) lastImport = match
275
- const insertAt = lastImport ? lastImport.index + lastImport[0].length : 0
276
- text =
277
- text.slice(0, insertAt) +
278
- `\nimport { telemetryServerExternalPackages } from '@open-mercato/telemetry/nextjs-config'` +
279
- text.slice(insertAt)
280
- }
281
- if (!options.dryRun) writeFileSync(path, text)
282
- return { file, status: 'patched', detail: 'spread telemetryServerExternalPackages into serverExternalPackages' }
283
- }
284
-
285
- /** Add `...telemetryServerExternalPackages` as the last element of an array literal, preserving its style. */
286
- function insertSpread(arrayText: string): string {
287
- const inner = arrayText.slice(1, -1)
288
- if (inner.includes('\n')) {
289
- const elementIndent = inner.match(/\n([ \t]+)\S/)?.[1] ?? ' '
290
- const closeIndent = arrayText.match(/\n([ \t]*)\]$/)?.[1] ?? ''
291
- const trimmed = inner.replace(/\s*$/, '')
292
- const separator = trimmed === '' || trimmed.endsWith(',') ? '' : ','
293
- return `[${trimmed}${separator}\n${elementIndent}...telemetryServerExternalPackages,\n${closeIndent}]`
294
- }
295
- const flat = inner.trim()
296
- return flat === '' ? '[...telemetryServerExternalPackages]' : `[${flat}, ...telemetryServerExternalPackages]`
297
- }
298
-
299
- function nextConfigSnippet(): string {
300
- return (
301
- `import { telemetryServerExternalPackages } from '@open-mercato/telemetry/nextjs-config'\n` +
302
- `// serverExternalPackages: [ ...existing, ...telemetryServerExternalPackages ]`
303
- )
304
- }
305
-
306
- /**
307
- * Auto-patch the catch-all API dispatcher — but only when it still matches the
308
- * known scaffold shape (all anchors present, telemetry not yet wired). On any
309
- * mismatch, print the snippet and mark it manual rather than editing an
310
- * unrecognized (customized) handler.
311
- */
312
- function patchDispatcher(appDir: string, options: TelemetryInitOptions): StepResult {
313
- const file = 'src/app/api/[...slug]/route.ts'
314
- const path = join(appDir, file)
315
- if (!existsSync(path)) {
316
- return { file, status: 'manual', detail: 'dispatcher not found', manualSnippet: DISPATCHER_SNIPPET }
317
- }
318
- let content = readFileSync(path, 'utf8')
319
- if (
320
- content.includes("from '@open-mercato/shared/lib/telemetry/runtime'")
321
- && content.includes('getTelemetryRuntime()?.recordHttpDuration')
322
- ) {
323
- return { file, status: 'skipped', detail: 'telemetry already wired' }
324
- }
325
- if (
326
- content.includes("import { reportError } from '@open-mercato/telemetry'")
327
- && content.includes("import { recordHttpDuration } from '@open-mercato/telemetry/nextjs'")
328
- ) {
329
- content = content
330
- .replace(
331
- "import { reportError } from '@open-mercato/telemetry'\nimport { recordHttpDuration } from '@open-mercato/telemetry/nextjs'",
332
- "import { getTelemetryRuntime } from '@open-mercato/shared/lib/telemetry/runtime'",
333
- )
334
- .replace(/\brecordHttpDuration\(/g, 'getTelemetryRuntime()?.recordHttpDuration(')
335
- .replace(/\breportError\(/g, 'getTelemetryRuntime()?.reportError(')
336
- if (!options.dryRun) writeFileSync(path, content)
337
- return { file, status: 'patched', detail: 'migrated dispatcher to the default-off runtime bridge' }
338
- }
339
-
340
- const importAnchor = "import { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'"
341
- const returnMatch = content.match(/^([ \t]*)return finalResponse\s*$/m)
342
- // The handleRequest catch is the first `} catch (error) {` after the success return.
343
- const catchRegex = /^([ \t]*)\}\s*catch\s*\(error\)\s*\{[ \t]*$/gm
344
- const catchMatch = findCatchAfter(content, catchRegex, returnMatch?.index ?? -1)
345
-
346
- if (!content.includes(importAnchor) || !returnMatch || returnMatch.index === undefined || !catchMatch) {
347
- return {
348
- file,
349
- status: 'manual',
350
- detail: 'dispatcher shape not recognized — apply the snippet by hand',
351
- manualSnippet: DISPATCHER_SNIPPET,
352
- }
353
- }
354
-
355
- // 1) imports
356
- content = content.replace(
357
- importAnchor,
358
- `${importAnchor}\nimport { getTelemetryRuntime } from '@open-mercato/shared/lib/telemetry/runtime'`,
359
- )
360
-
361
- // 2) success-path metric (re-match after the import edit shifted offsets)
362
- const ret = content.match(/^([ \t]*)return finalResponse\s*$/m)
363
- if (!ret || ret.index === undefined) {
364
- return { file, status: 'manual', detail: 'success-path anchor lost', manualSnippet: DISPATCHER_SNIPPET }
365
- }
366
- const retIndent = ret[1]
367
- content =
368
- content.slice(0, ret.index) +
369
- `${retIndent}getTelemetryRuntime()?.recordHttpDuration(method, match.route.path, finalResponse.status, startedAt)\n` +
370
- content.slice(ret.index)
371
-
372
- // 3) catch-block error funnel + 500 metric
373
- const catch2 = findCatchAfter(content, /^([ \t]*)\}\s*catch\s*\(error\)\s*\{[ \t]*$/gm, content.indexOf('return finalResponse'))
374
- if (!catch2) {
375
- return { file, status: 'manual', detail: 'catch anchor lost', manualSnippet: DISPATCHER_SNIPPET }
376
- }
377
- const bodyIndent = `${catch2.indent} `
378
- const insertAt = catch2.index + catch2.length
379
- const block =
380
- `\n${bodyIndent}getTelemetryRuntime()?.reportError(error, {` +
381
- `\n${bodyIndent} attributes: { 'http.request.method': method, 'http.route': match.route.path, 'http.response.status_code': 500 },` +
382
- `\n${bodyIndent}})` +
383
- `\n${bodyIndent}getTelemetryRuntime()?.recordHttpDuration(method, match.route.path, 500, startedAt)`
384
- content = content.slice(0, insertAt) + block + content.slice(insertAt)
385
-
386
- if (!options.dryRun) writeFileSync(path, content)
387
- return { file, status: 'patched', detail: 'wired reportError (5xx) + http.server.request.duration metric' }
388
- }
389
-
390
- function findCatchAfter(
391
- content: string,
392
- regex: RegExp,
393
- afterIndex: number,
394
- ): { index: number; length: number; indent: string } | null {
395
- regex.lastIndex = 0
396
- let match: RegExpExecArray | null
397
- while ((match = regex.exec(content)) !== null) {
398
- if (match.index > afterIndex) {
399
- return { index: match.index, length: match[0].length, indent: match[1] }
400
- }
401
- }
402
- return null
403
- }
404
-
405
- export async function runTelemetryInit(args: string[]): Promise<number> {
406
- const appDir = resolve('.')
407
- const options = parseArgs(args)
408
-
409
- if (!existsSync(join(appDir, 'src', 'modules.ts'))) {
410
- console.error('❌ Not an Open Mercato app directory (src/modules.ts not found)')
411
- return 1
412
- }
413
- if (!existsSync(join(appDir, 'package.json'))) {
414
- console.error('❌ package.json not found')
415
- return 1
416
- }
417
-
418
- console.log('')
419
- console.log(options.dryRun ? '🔭 Telemetry init (dry run — no files written)\n' : '🔭 Wiring @open-mercato/telemetry into this app\n')
420
-
421
- const results: StepResult[] = []
422
- results.push(patchPackageJson(appDir, options))
423
- const envExample = patchEnvFile(appDir, '.env.example', options)
424
- if (envExample) results.push(envExample)
425
- const env = patchEnvFile(appDir, '.env', options)
426
- if (env) results.push(env)
427
- results.push(patchInstrumentation(appDir, options))
428
- results.push(await patchNextConfig(appDir, options))
429
- results.push(patchDispatcher(appDir, options))
430
-
431
- const icon: Record<StepStatus, string> = { created: '✍️ ', patched: '✅', skipped: '⏭️ ', manual: '⚠️ ' }
432
- for (const result of results) {
433
- console.log(`${icon[result.status]} ${result.file} — ${result.detail}`)
434
- }
435
-
436
- const manual = results.filter((result) => result.status === 'manual')
437
- for (const result of manual) {
438
- if (!result.manualSnippet) continue
439
- console.log('')
440
- console.log(`── manual step for ${result.file} ──`)
441
- console.log(result.manualSnippet)
442
- }
443
-
444
- console.log('')
445
- const changed = results.some((result) => result.status === 'patched' || result.status === 'created')
446
- if (options.dryRun) {
447
- console.log('Dry run complete — re-run without --dry-run to apply.')
448
- } else if (changed) {
449
- console.log('Next steps:')
450
- console.log(' 1. yarn install (resolve @open-mercato/telemetry + the OTEL SDK)')
451
- console.log(' 2. set TELEMETRY_BACKEND + OTEL_EXPORTER_OTLP_* in .env')
452
- console.log(' 3. yarn typecheck && yarn build (verify the wiring)')
453
- } else {
454
- console.log('Nothing to do — telemetry is already wired.')
455
- }
456
- if (manual.length > 0) {
457
- console.log('')
458
- console.log(`⚠️ ${manual.length} file(s) need a manual edit (shown above) — the rest were applied automatically.`)
459
- }
460
- return 0
461
- }