@aifabrix/builder 2.43.0 → 2.44.1

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 (371) hide show
  1. package/.cursor/rules/anchor-docs.mdc +15 -0
  2. package/.cursor/rules/cli-layout.mdc +75 -0
  3. package/.cursor/rules/project-rules.mdc +8 -0
  4. package/.npmrc.token +1 -0
  5. package/.nyc_output/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
  6. package/.nyc_output/processinfo/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
  7. package/.nyc_output/processinfo/index.json +1 -0
  8. package/README.md +1 -1
  9. package/anchor-docs/README.md +10 -0
  10. package/anchor-docs/_TEMPLATE +24 -0
  11. package/bin/aifabrix.js +13 -4
  12. package/integration/hubspot-test/README.md +31 -0
  13. package/integration/hubspot-test/create-hubspot.js +5 -5
  14. package/integration/hubspot-test/hubspot-test-datasource-company.json +58 -462
  15. package/integration/hubspot-test/hubspot-test-datasource-contact.json +61 -555
  16. package/integration/hubspot-test/hubspot-test-datasource-deal.json +63 -506
  17. package/integration/hubspot-test/hubspot-test-datasource-users.json +42 -83
  18. package/integration/hubspot-test/hubspot-test-deploy.json +3 -3
  19. package/integration/hubspot-test/test-dataplane-down-tests.js +1 -7
  20. package/integration/hubspot-test/test-dataplane-down.js +3 -3
  21. package/integration/hubspot-test/test.js +35 -43
  22. package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
  23. package/integration/roundtrip-test-local/README.md +144 -0
  24. package/integration/roundtrip-test-local/application.yaml +13 -0
  25. package/integration/roundtrip-test-local/env.template +15 -0
  26. package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
  27. package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
  28. package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
  29. package/integration/roundtrip-test-local2/README.md +144 -0
  30. package/integration/roundtrip-test-local2/application.yaml +13 -0
  31. package/integration/roundtrip-test-local2/env.template +15 -0
  32. package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
  33. package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
  34. package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
  35. package/integration/test/wizard.yaml +8 -0
  36. package/jest.config.default.js +10 -0
  37. package/jest.config.integration.fixtures.js +22 -0
  38. package/jest.config.integration.js +21 -18
  39. package/jest.config.isolated.js +10 -0
  40. package/jest.projects.js +301 -0
  41. package/lib/api/certificates.api.js +62 -0
  42. package/lib/api/datasources-core.api.js +3 -3
  43. package/lib/api/dev-mtls-request.js +110 -0
  44. package/lib/api/dev-server-https.js +145 -0
  45. package/lib/api/dev.api.js +133 -144
  46. package/lib/api/index.js +11 -3
  47. package/lib/api/pipeline.api.js +67 -20
  48. package/lib/api/types/certificates.types.js +48 -0
  49. package/lib/api/types/dev.types.js +4 -3
  50. package/lib/api/types/pipeline.types.js +8 -5
  51. package/lib/api/types/validation-run.types.js +56 -0
  52. package/lib/api/validation-run.api.js +111 -0
  53. package/lib/api/validation-runner.js +109 -0
  54. package/lib/app/certification-show-enrich.js +129 -0
  55. package/lib/app/certification-verify-rows.js +60 -0
  56. package/lib/app/config.js +1 -1
  57. package/lib/app/deploy-status-display.js +2 -2
  58. package/lib/app/deploy.js +7 -6
  59. package/lib/app/display.js +2 -1
  60. package/lib/app/dockerfile.js +3 -2
  61. package/lib/app/down.js +2 -1
  62. package/lib/app/helpers.js +6 -5
  63. package/lib/app/index.js +27 -8
  64. package/lib/app/list.js +7 -6
  65. package/lib/app/push.js +4 -3
  66. package/lib/app/register.js +16 -7
  67. package/lib/app/rotate-secret.js +14 -13
  68. package/lib/app/run-container-start.js +184 -0
  69. package/lib/app/run-docker-fallback.js +108 -0
  70. package/lib/app/run-env-compose.js +30 -42
  71. package/lib/app/run-helpers.js +49 -126
  72. package/lib/app/run-infra-requirements.js +30 -0
  73. package/lib/app/run-resolve-image.js +21 -0
  74. package/lib/app/run.js +74 -21
  75. package/lib/app/show-display.js +44 -1
  76. package/lib/app/show.js +93 -9
  77. package/lib/build/index.js +13 -10
  78. package/lib/certification/cli-cert-sync-skip.js +21 -0
  79. package/lib/certification/merge-certification-from-artifact.js +185 -0
  80. package/lib/certification/post-unified-cert-sync.js +33 -0
  81. package/lib/certification/sync-after-external-command.js +52 -0
  82. package/lib/certification/sync-system-certification.js +197 -0
  83. package/lib/cli/index.js +2 -0
  84. package/lib/cli/setup-app.help.js +67 -0
  85. package/lib/cli/setup-app.js +61 -121
  86. package/lib/cli/setup-app.test-commands.js +195 -0
  87. package/lib/cli/setup-auth.js +19 -5
  88. package/lib/cli/setup-credential-deployment.js +22 -8
  89. package/lib/cli/setup-dev-path-commands.js +124 -0
  90. package/lib/cli/setup-dev.js +170 -113
  91. package/lib/cli/setup-environment.js +7 -1
  92. package/lib/cli/setup-external-system.js +84 -23
  93. package/lib/cli/setup-infra.js +126 -47
  94. package/lib/cli/setup-parameters.js +32 -0
  95. package/lib/cli/setup-secrets.js +137 -18
  96. package/lib/cli/setup-service-user.js +1 -1
  97. package/lib/cli/setup-utility.js +54 -22
  98. package/lib/commands/app-down.js +5 -7
  99. package/lib/commands/app-install.js +14 -7
  100. package/lib/commands/app-logs.js +13 -10
  101. package/lib/commands/app-shell.js +4 -1
  102. package/lib/commands/app-test.js +25 -19
  103. package/lib/commands/app.js +32 -11
  104. package/lib/commands/auth-config.js +6 -6
  105. package/lib/commands/auth-status.js +4 -3
  106. package/lib/commands/credential-env.js +4 -3
  107. package/lib/commands/credential-list.js +5 -4
  108. package/lib/commands/credential-push.js +4 -3
  109. package/lib/commands/datasource-unified-test-cli.js +428 -0
  110. package/lib/commands/datasource-unified-test-cli.options.js +191 -0
  111. package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +106 -0
  112. package/lib/commands/datasource-validation-cli.js +143 -0
  113. package/lib/commands/datasource.js +125 -95
  114. package/lib/commands/deployment-list.js +6 -5
  115. package/lib/commands/dev-cli-handlers.js +122 -18
  116. package/lib/commands/dev-down.js +4 -3
  117. package/lib/commands/dev-init.js +231 -116
  118. package/lib/commands/dev-show-display.js +473 -0
  119. package/lib/commands/login-credentials.js +3 -2
  120. package/lib/commands/login-device.js +4 -3
  121. package/lib/commands/login.js +5 -4
  122. package/lib/commands/logout.js +8 -7
  123. package/lib/commands/parameters-validate.js +54 -0
  124. package/lib/commands/repair-datasource.js +314 -68
  125. package/lib/commands/repair-env-template.js +2 -2
  126. package/lib/commands/repair.js +21 -3
  127. package/lib/commands/secrets-list.js +23 -12
  128. package/lib/commands/secrets-remove-all.js +220 -0
  129. package/lib/commands/secrets-remove.js +21 -12
  130. package/lib/commands/secrets-set.js +21 -12
  131. package/lib/commands/secrets-validate.js +4 -4
  132. package/lib/commands/secure.js +10 -9
  133. package/lib/commands/service-user.js +26 -25
  134. package/lib/commands/test-e2e-external.js +27 -1
  135. package/lib/commands/up-common.js +3 -2
  136. package/lib/commands/up-dataplane.js +29 -16
  137. package/lib/commands/up-miso.js +19 -29
  138. package/lib/commands/upload.js +149 -39
  139. package/lib/commands/wizard-core-helpers.js +1 -1
  140. package/lib/commands/wizard-dataplane.js +4 -3
  141. package/lib/commands/wizard-helpers.js +3 -3
  142. package/lib/commands/wizard.js +2 -2
  143. package/lib/core/admin-secrets.js +14 -5
  144. package/lib/core/audit-logger.js +12 -4
  145. package/lib/core/config-attach-extensions.js +46 -0
  146. package/lib/core/config-runtime-paths.js +29 -0
  147. package/lib/core/config.js +55 -56
  148. package/lib/core/diff.js +3 -2
  149. package/lib/core/ensure-encryption-key.js +1 -1
  150. package/lib/core/secrets-ensure-infra.js +77 -0
  151. package/lib/core/secrets-ensure.js +120 -64
  152. package/lib/core/secrets-env-write.js +35 -7
  153. package/lib/core/secrets-infra-placeholder-sync.js +61 -0
  154. package/lib/core/secrets.js +200 -37
  155. package/lib/core/templates-env.js +4 -3
  156. package/lib/datasource/abac-validator.js +1 -10
  157. package/lib/datasource/deploy.js +75 -53
  158. package/lib/datasource/field-reference-validator.js +9 -6
  159. package/lib/datasource/integration-context.js +63 -0
  160. package/lib/datasource/list.js +8 -7
  161. package/lib/datasource/log-viewer.js +189 -67
  162. package/lib/datasource/resolve-app.js +4 -4
  163. package/lib/datasource/test-e2e.js +113 -146
  164. package/lib/datasource/test-integration.js +114 -122
  165. package/lib/datasource/unified-validation-run-body.js +68 -0
  166. package/lib/datasource/unified-validation-run-post.js +23 -0
  167. package/lib/datasource/unified-validation-run-resolve.js +43 -0
  168. package/lib/datasource/unified-validation-run.js +93 -0
  169. package/lib/datasource/validate.js +157 -13
  170. package/lib/deployment/deployer.js +4 -3
  171. package/lib/deployment/environment.js +7 -6
  172. package/lib/deployment/push.js +17 -8
  173. package/lib/external-system/delete.js +4 -3
  174. package/lib/external-system/deploy.js +166 -53
  175. package/lib/external-system/download-helpers.js +1 -1
  176. package/lib/external-system/download.js +7 -6
  177. package/lib/external-system/generator.js +92 -6
  178. package/lib/external-system/integration-test-dispatch.js +26 -0
  179. package/lib/external-system/test-execution.js +5 -1
  180. package/lib/external-system/test-helpers.js +0 -4
  181. package/lib/external-system/test-system-level-helpers.js +110 -0
  182. package/lib/external-system/test-system-level.js +83 -44
  183. package/lib/external-system/test.js +59 -8
  184. package/lib/generator/builders.js +23 -11
  185. package/lib/generator/deploy-manifest-azure-kv.js +81 -0
  186. package/lib/generator/external.js +16 -4
  187. package/lib/generator/helpers.js +58 -3
  188. package/lib/generator/index.js +4 -0
  189. package/lib/generator/split-readme.js +12 -7
  190. package/lib/generator/split-variables.js +2 -1
  191. package/lib/generator/split.js +1 -1
  192. package/lib/generator/wizard-readme.js +3 -3
  193. package/lib/generator/wizard.js +8 -8
  194. package/lib/infrastructure/compose.js +70 -7
  195. package/lib/infrastructure/helpers-docker-check.js +67 -0
  196. package/lib/infrastructure/helpers.js +203 -42
  197. package/lib/infrastructure/index.js +31 -18
  198. package/lib/infrastructure/services.js +21 -67
  199. package/lib/internal/fs-real-sync.js +104 -0
  200. package/lib/internal/node-fs.js +98 -0
  201. package/lib/parameters/database-secret-values.js +173 -0
  202. package/lib/parameters/infra-kv-discovery.js +121 -0
  203. package/lib/parameters/infra-parameter-catalog.js +458 -0
  204. package/lib/parameters/infra-parameter-validate.js +64 -0
  205. package/lib/schema/application-schema.json +37 -17
  206. package/lib/schema/datasource-test-run.schema.json +493 -0
  207. package/lib/schema/deployment-rules.yaml +102 -63
  208. package/lib/schema/external-datasource.schema.json +1200 -442
  209. package/lib/schema/external-system.schema.json +203 -5
  210. package/lib/schema/flag-map-validation-run.json +31 -0
  211. package/lib/schema/infra-parameter.schema.json +106 -0
  212. package/lib/schema/infra.parameter.yaml +421 -0
  213. package/lib/schema/type/credential-auth-templates.json +40 -0
  214. package/lib/schema/type/document-storage.json +226 -0
  215. package/lib/schema/type/message-service.json +123 -0
  216. package/lib/schema/type/vector-store.json +88 -0
  217. package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
  218. package/lib/utils/api-error-handler.js +2 -2
  219. package/lib/utils/api.js +77 -17
  220. package/lib/utils/app-register-api.js +3 -2
  221. package/lib/utils/app-register-auth.js +1 -1
  222. package/lib/utils/app-register-config.js +4 -4
  223. package/lib/utils/app-register-display.js +3 -2
  224. package/lib/utils/app-register-validator.js +3 -2
  225. package/lib/utils/app-run-containers.js +26 -22
  226. package/lib/utils/app-scoped-config.js +31 -0
  227. package/lib/utils/app-service-env-from-builder.js +164 -0
  228. package/lib/utils/build-copy.js +1 -1
  229. package/lib/utils/build-helpers.js +20 -20
  230. package/lib/utils/build-resolve-image.js +165 -0
  231. package/lib/utils/cli-layout-chalk.js +8 -0
  232. package/lib/utils/cli-test-layout-chalk.js +267 -0
  233. package/lib/utils/cli-utils.js +88 -11
  234. package/lib/utils/compose-db-passwords.js +138 -0
  235. package/lib/utils/compose-generate-docker-compose.js +216 -0
  236. package/lib/utils/compose-generator.js +197 -291
  237. package/lib/utils/compose-miso-env.js +18 -0
  238. package/lib/utils/compose-traefik-ingress-base.js +158 -0
  239. package/lib/utils/config-paths.js +166 -7
  240. package/lib/utils/config-scoped-resources-preference.js +41 -0
  241. package/lib/utils/configuration-env-resolver.js +11 -8
  242. package/lib/utils/controller-deployment-outcome.js +68 -0
  243. package/lib/utils/credential-display.js +2 -2
  244. package/lib/utils/credential-secrets-env.js +5 -5
  245. package/lib/utils/dataplane-pipeline-warning.js +4 -3
  246. package/lib/utils/datasource-test-run-capability-scope.js +43 -0
  247. package/lib/utils/datasource-test-run-certificate-tty.js +82 -0
  248. package/lib/utils/datasource-test-run-debug-display.js +137 -0
  249. package/lib/utils/datasource-test-run-debug-slice.js +93 -0
  250. package/lib/utils/datasource-test-run-display.js +459 -0
  251. package/lib/utils/datasource-test-run-exit.js +83 -0
  252. package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
  253. package/lib/utils/datasource-test-run-report-version.js +51 -0
  254. package/lib/utils/datasource-test-run-schema-sync.js +59 -0
  255. package/lib/utils/datasource-test-run-tty-log.js +81 -0
  256. package/lib/utils/datasource-validation-watch.js +266 -0
  257. package/lib/utils/declarative-url-ports.js +47 -0
  258. package/lib/utils/derive-env-key-from-client-id.js +41 -0
  259. package/lib/utils/dev-ca-install.js +185 -23
  260. package/lib/utils/dev-cert-helper.js +266 -17
  261. package/lib/utils/dev-hosts-helper.js +307 -0
  262. package/lib/utils/dev-init-cert-hints.js +37 -0
  263. package/lib/utils/dev-init-health-messages.js +52 -0
  264. package/lib/utils/dev-init-resolve.js +86 -0
  265. package/lib/utils/dev-init-ssh-merge.js +65 -0
  266. package/lib/utils/dev-ssh-config-helper.js +196 -0
  267. package/lib/utils/dev-user-groups.js +93 -0
  268. package/lib/utils/docker-build.js +42 -17
  269. package/lib/utils/docker-exec.js +28 -0
  270. package/lib/utils/docker-manifest-public-port.js +116 -0
  271. package/lib/utils/docker-not-running-hint.js +52 -0
  272. package/lib/utils/docker.js +98 -11
  273. package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
  274. package/lib/utils/env-config-loader.js +10 -91
  275. package/lib/utils/env-copy.js +19 -10
  276. package/lib/utils/env-map.js +35 -8
  277. package/lib/utils/env-template.js +2 -2
  278. package/lib/utils/environment-scoped-resources.js +144 -0
  279. package/lib/utils/error-formatter.js +92 -13
  280. package/lib/utils/error-formatters/http-status-errors.js +6 -5
  281. package/lib/utils/error-formatters/network-errors.js +2 -1
  282. package/lib/utils/error-formatters/permission-errors.js +2 -1
  283. package/lib/utils/error-formatters/validation-errors.js +2 -1
  284. package/lib/utils/external-readme.js +8 -1
  285. package/lib/utils/external-system-display.js +242 -136
  286. package/lib/utils/external-system-local-test-tty.js +389 -0
  287. package/lib/utils/external-system-readiness-core.js +377 -0
  288. package/lib/utils/external-system-readiness-deploy-display.js +270 -0
  289. package/lib/utils/external-system-readiness-display-internals.js +150 -0
  290. package/lib/utils/external-system-readiness-display.js +186 -0
  291. package/lib/utils/external-system-system-test-tty-overview.js +120 -0
  292. package/lib/utils/external-system-system-test-tty.js +417 -0
  293. package/lib/utils/external-system-test-helpers.js +24 -6
  294. package/lib/utils/external-system-validators.js +30 -12
  295. package/lib/utils/health-check-url.js +119 -0
  296. package/lib/utils/health-check.js +59 -25
  297. package/lib/utils/help-builder.js +11 -8
  298. package/lib/utils/image-version.js +4 -8
  299. package/lib/utils/infra-containers.js +4 -7
  300. package/lib/utils/infra-env-defaults.js +162 -0
  301. package/lib/utils/infra-status-display.js +167 -0
  302. package/lib/utils/infra-status.js +16 -8
  303. package/lib/utils/local-secrets.js +3 -4
  304. package/lib/utils/paths.js +148 -47
  305. package/lib/utils/port-resolver.js +10 -23
  306. package/lib/utils/redis-env-scope.js +62 -0
  307. package/lib/utils/register-aifabrix-shell-env.js +204 -0
  308. package/lib/utils/remote-builder-validation.js +99 -0
  309. package/lib/utils/remote-dev-auth.js +117 -21
  310. package/lib/utils/remote-docker-env.js +67 -15
  311. package/lib/utils/remote-secrets-loader.js +13 -4
  312. package/lib/utils/resolve-docker-image-ref.js +124 -0
  313. package/lib/utils/schema-loader.js +22 -9
  314. package/lib/utils/secrets-bash-kv.js +25 -0
  315. package/lib/utils/secrets-generator.js +169 -49
  316. package/lib/utils/secrets-helpers.js +70 -59
  317. package/lib/utils/secrets-kv-scope.js +60 -0
  318. package/lib/utils/secrets-utils.js +32 -38
  319. package/lib/utils/secrets-validation.js +3 -1
  320. package/lib/utils/secrets-yaml-preserve.js +109 -0
  321. package/lib/utils/ssh-key-helper.js +4 -2
  322. package/lib/utils/template-helpers.js +2 -2
  323. package/lib/utils/test-log-writer.js +3 -3
  324. package/lib/utils/token-manager.js +1 -2
  325. package/lib/utils/url-declarative-public-base.js +188 -0
  326. package/lib/utils/url-declarative-resolve-build.js +493 -0
  327. package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
  328. package/lib/utils/url-declarative-resolve.js +220 -0
  329. package/lib/utils/url-declarative-token-parse.js +74 -0
  330. package/lib/utils/url-declarative-url-flags.js +50 -0
  331. package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
  332. package/lib/utils/url-public-path-prefix.js +34 -0
  333. package/lib/utils/urls-local-registry.js +220 -0
  334. package/lib/utils/validation-report-tty-kit.js +77 -0
  335. package/lib/utils/validation-run-poll.js +112 -0
  336. package/lib/utils/validation-run-post-retry.js +85 -0
  337. package/lib/utils/validation-run-request.js +116 -0
  338. package/lib/utils/variable-transformer.js +21 -4
  339. package/lib/utils/yaml-preserve.js +33 -14
  340. package/lib/validation/datasource-warnings.js +56 -0
  341. package/lib/validation/env-template-auth.js +1 -1
  342. package/lib/validation/external-manifest-validator.js +27 -7
  343. package/lib/validation/validate-display.js +37 -31
  344. package/lib/validation/validate-external-cert-sync.js +23 -0
  345. package/lib/validation/validate.js +8 -14
  346. package/lib/validation/validator-unresolved-placeholders.js +98 -0
  347. package/lib/validation/validator.js +22 -65
  348. package/lib/validation/wizard-config-validator.js +2 -1
  349. package/package.json +9 -4
  350. package/scripts/check-datasource-test-run-schema-sync.js +34 -0
  351. package/scripts/diagnose-cli.js +150 -0
  352. package/scripts/install-local.js +307 -55
  353. package/scripts/pnpm-global-remove.js +48 -0
  354. package/templates/README.md +15 -2
  355. package/templates/applications/dataplane/application.yaml +52 -2
  356. package/templates/applications/dataplane/env.template +79 -17
  357. package/templates/applications/dataplane/rbac.yaml +8 -0
  358. package/templates/applications/keycloak/application.yaml +9 -1
  359. package/templates/applications/keycloak/env.template +15 -6
  360. package/templates/applications/miso-controller/application.yaml +10 -2
  361. package/templates/applications/miso-controller/env.template +42 -12
  362. package/templates/applications/miso-controller/rbac.yaml +5 -0
  363. package/templates/external-system/README.md.hbs +20 -7
  364. package/templates/external-system/deploy.js.hbs +5 -5
  365. package/templates/external-system/external-datasource.yaml.hbs +197 -118
  366. package/templates/infra/compose.yaml.hbs +33 -16
  367. package/templates/infra/servers.json.hbs +3 -1
  368. package/templates/python/docker-compose.hbs +16 -0
  369. package/templates/typescript/docker-compose.hbs +16 -0
  370. package/lib/api/external-test.api.js +0 -111
  371. package/lib/schema/env-config.yaml +0 -60
@@ -0,0 +1,106 @@
1
+ /**
2
+ * @fileoverview E2E / envelope exit helpers for datasource unified test CLI (keeps main CLI file under max-lines).
3
+ * @author AI Fabrix Team
4
+ * @version 2.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const logger = require('../utils/logger');
10
+ const { displayIntegrationTestResults, displayE2EResults } = require('../utils/external-system-display');
11
+ const { computeExitCodeFromDatasourceTestRun } = require('../utils/datasource-test-run-exit');
12
+ const { analyzeCapabilityScope } = require('../utils/datasource-test-run-capability-scope');
13
+ const {
14
+ resolveDebugDisplayMode,
15
+ formatDatasourceTestRunDebugBlock
16
+ } = require('../utils/datasource-test-run-debug-display');
17
+ const { formatCapabilityFocusSection } = require('../utils/datasource-test-run-display');
18
+ const { emitCapabilityScopeDiagnostics } = require('./datasource-validation-cli');
19
+
20
+ function logDatasourceTestRunDebugAppendix(envelope, debugOpt) {
21
+ const mode = resolveDebugDisplayMode(debugOpt);
22
+ if (!mode || !envelope) return;
23
+ const block = formatDatasourceTestRunDebugBlock(envelope, mode, process.stdout.isTTY);
24
+ if (block) logger.log(block);
25
+ }
26
+
27
+ function logE2eCapabilityFocusFromEnvelope(env, capabilityOpt) {
28
+ if (!env) return;
29
+ const capKey =
30
+ capabilityOpt !== undefined && capabilityOpt !== null
31
+ ? String(capabilityOpt).trim()
32
+ : '';
33
+ if (!capKey) return;
34
+ const sec = formatCapabilityFocusSection(env, capKey);
35
+ if (sec) logger.log(sec);
36
+ }
37
+
38
+ /**
39
+ * @param {Object|null|undefined} env
40
+ * @param {Object} options
41
+ * @returns {number|null} null if no envelope
42
+ */
43
+ function exitCodeFromDatasourceTestRunEnvelope(env, options) {
44
+ if (!env || typeof env !== 'object') return null;
45
+ let code = computeExitCodeFromDatasourceTestRun(env, {
46
+ warningsAsErrors: options.warningsAsErrors === true,
47
+ requireCert: options.requireCert === true
48
+ });
49
+ const scope = analyzeCapabilityScope(env, options.capability);
50
+ if (options.strictCapabilityScope === true && scope.violated) {
51
+ code = Math.max(code, 1);
52
+ }
53
+ return code;
54
+ }
55
+
56
+ /**
57
+ * Legacy E2E display + exit code (no process.exit; watch mode).
58
+ * @param {Object} data
59
+ * @param {Object} options
60
+ * @returns {number}
61
+ */
62
+ function finalizeDatasourceTestE2ELegacyPath(data, options) {
63
+ displayE2EResults(data, options.verbose);
64
+ logDatasourceTestRunDebugAppendix(data.datasourceTestRun, options.debug);
65
+ logE2eCapabilityFocusFromEnvelope(data.datasourceTestRun, options.capability);
66
+ const env = data.datasourceTestRun;
67
+ if (env) {
68
+ emitCapabilityScopeDiagnostics(env, { requestedCapabilityKey: options.capability });
69
+ const code = exitCodeFromDatasourceTestRunEnvelope(env, options);
70
+ return code === null ? 1 : code;
71
+ }
72
+ const steps = data.steps || data.completedActions || [];
73
+ const failed = data.success === false || steps.some(s => s.success === false || s.error);
74
+ return failed ? 1 : 0;
75
+ }
76
+
77
+ /**
78
+ * @param {string} datasourceKey
79
+ * @param {Object} env
80
+ * @param {Object} options
81
+ */
82
+ function displayDatasourceTestE2EEnvelopeResults(datasourceKey, env, options) {
83
+ const success = env.status !== 'fail';
84
+ displayIntegrationTestResults(
85
+ {
86
+ systemKey: env.systemKey || 'unknown',
87
+ success,
88
+ datasourceResults: [{ key: datasourceKey, success, datasourceTestRun: env }]
89
+ },
90
+ options.verbose,
91
+ {
92
+ debug: options.debug,
93
+ runType: 'e2e',
94
+ requestedCapabilityKey: options.capability
95
+ }
96
+ );
97
+ logE2eCapabilityFocusFromEnvelope(env, options.capability);
98
+ }
99
+
100
+ module.exports = {
101
+ logDatasourceTestRunDebugAppendix,
102
+ logE2eCapabilityFocusFromEnvelope,
103
+ exitCodeFromDatasourceTestRunEnvelope,
104
+ finalizeDatasourceTestE2ELegacyPath,
105
+ displayDatasourceTestE2EEnvelopeResults
106
+ };
@@ -0,0 +1,143 @@
1
+ const { formatBlockingError } = require('../utils/cli-test-layout-chalk');
2
+ /**
3
+ * @fileoverview Shared CLI handling for unified validation (DatasourceTestRun + exit matrix).
4
+ * @author AI Fabrix Team
5
+ * @version 2.0.0
6
+ */
7
+
8
+ const chalk = require('chalk');
9
+ const logger = require('../utils/logger');
10
+ const { computeExitCodeFromDatasourceTestRun, exitCodeForPollTimeout } = require('../utils/datasource-test-run-exit');
11
+ const { analyzeCapabilityScope } = require('../utils/datasource-test-run-capability-scope');
12
+ const ttyLog = require('../utils/datasource-test-run-tty-log');
13
+ const { logEnvelopeForInteractiveCli } = ttyLog;
14
+
15
+ /**
16
+ * Build unified CLI result from integration test return shape.
17
+ * @param {Object} r - runDatasourceTestIntegration result
18
+ * @returns {{ envelope: Object|null, apiError: Object|null, pollTimedOut: boolean, incompleteNoAsync: boolean }}
19
+ */
20
+ function unifiedCliResultFromIntegrationReturn(r) {
21
+ const meta = r.runMeta || {};
22
+ return {
23
+ apiError: meta.apiError || null,
24
+ pollTimedOut: meta.pollTimedOut === true,
25
+ incompleteNoAsync: meta.incompleteNoAsync === true,
26
+ envelope: r.datasourceTestRun || null
27
+ };
28
+ }
29
+
30
+ function logApiError(apiError) {
31
+ logger.error(
32
+ formatBlockingError('Dataplane request failed:'),
33
+ apiError.formattedError || apiError.error || 'Request failed'
34
+ );
35
+ if (apiError.status) {
36
+ logger.error(chalk.gray(` HTTP ${apiError.status}`));
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Print unified validation outcome and return exit code (plan §3.14 watch — no process.exit).
42
+ * @param {Object} result - From runUnifiedDatasourceValidation
43
+ * @param {Object} options - CLI flags
44
+ * @returns {number}
45
+ */
46
+ function finalizeUnifiedValidationResult(result, options = {}) {
47
+ if (result.apiError) {
48
+ logApiError(result.apiError);
49
+ return 3;
50
+ }
51
+ if (result.pollTimedOut) {
52
+ logger.error(formatBlockingError('Report incomplete: timeout'));
53
+ return exitCodeForPollTimeout(result.envelope);
54
+ }
55
+ if (result.incompleteNoAsync) {
56
+ logger.error(
57
+ chalk.red(
58
+ '✖ Report incomplete: async polling disabled (--no-async) but server returned partial/minimal report.'
59
+ )
60
+ );
61
+ return 3;
62
+ }
63
+
64
+ const envelope = result.envelope;
65
+ logEnvelopeForInteractiveCli(envelope, options);
66
+
67
+ let exitCode = computeExitCodeFromDatasourceTestRun(envelope, {
68
+ warningsAsErrors: options.warningsAsErrors === true,
69
+ requireCert: options.requireCert === true
70
+ });
71
+ const scope = analyzeCapabilityScope(envelope, options.requestedCapabilityKey);
72
+ if (options.strictCapabilityScope === true && scope.violated) {
73
+ exitCode = Math.max(exitCode, 1);
74
+ }
75
+ if (
76
+ exitCode === 2 &&
77
+ options.requireCert &&
78
+ !envelope.certificate
79
+ ) {
80
+ logger.error(formatBlockingError('Certification not returned; cannot verify.'));
81
+ }
82
+ return exitCode;
83
+ }
84
+
85
+ /**
86
+ * Handle unified validation result: logs, stdout JSON, process.exit.
87
+ * @param {Object} result - From runUnifiedDatasourceValidation
88
+ * @param {Object} options - CLI flags
89
+ * @returns {void} Exits process
90
+ */
91
+ function exitFromUnifiedValidationResult(result, options = {}) {
92
+ process.exit(finalizeUnifiedValidationResult(result, options));
93
+ }
94
+
95
+ /**
96
+ * Compute exit code after integration CLI display (no process.exit; plan §3.14 watch).
97
+ * @param {Object} integrationResult - From runDatasourceTestIntegration
98
+ * @param {Object} [exitOpts]
99
+ * @returns {number}
100
+ */
101
+ function finalizeAfterIntegrationDisplay(integrationResult, exitOpts = {}) {
102
+ const env = integrationResult.datasourceTestRun;
103
+ if (!env) {
104
+ return integrationResult.success ? 0 : 1;
105
+ }
106
+ let exitCode = computeExitCodeFromDatasourceTestRun(env, {
107
+ warningsAsErrors: exitOpts.warningsAsErrors === true,
108
+ requireCert: exitOpts.requireCert === true
109
+ });
110
+ if (exitOpts.strictCapabilityScope === true) {
111
+ const scope = analyzeCapabilityScope(env, exitOpts.requestedCapabilityKey);
112
+ if (scope.violated) {
113
+ exitCode = Math.max(exitCode, 1);
114
+ }
115
+ }
116
+ if (
117
+ exitCode === 2 &&
118
+ exitOpts.requireCert &&
119
+ !env.certificate
120
+ ) {
121
+ logger.error(formatBlockingError('Certification not returned; cannot verify.'));
122
+ }
123
+ return exitCode;
124
+ }
125
+
126
+ /**
127
+ * Exit after integration CLI when not using raw unified output modes.
128
+ * @param {Object} integrationResult - From runDatasourceTestIntegration
129
+ * @param {Object} [exitOpts]
130
+ */
131
+ function exitAfterIntegrationDisplay(integrationResult, exitOpts = {}) {
132
+ process.exit(finalizeAfterIntegrationDisplay(integrationResult, exitOpts));
133
+ }
134
+
135
+ module.exports = {
136
+ exitFromUnifiedValidationResult,
137
+ finalizeUnifiedValidationResult,
138
+ emitReportVersionDiagnostics: ttyLog.emitReportVersionDiagnostics,
139
+ emitCapabilityScopeDiagnostics: ttyLog.emitCapabilityScopeDiagnostics,
140
+ unifiedCliResultFromIntegrationReturn,
141
+ finalizeAfterIntegrationDisplay,
142
+ exitAfterIntegrationDisplay
143
+ };
@@ -1,40 +1,103 @@
1
1
  /**
2
2
  * AI Fabrix Builder - Datasource Commands
3
3
  *
4
- * Handles datasource validation, listing, comparison, and deployment
5
- * Commands: datasource validate, datasource list, datasource diff, datasource upload
4
+ * Handles datasource validation, listing, comparison, deployment, and online validation runs.
5
+ * Subcommands `test`, `test-integration`, and `test-e2e` call the dataplane unified validation API; `log-test` / `log-integration` / `log-e2e` read saved debug JSON locally. Permissions are summarized in `docs/commands/permissions.md`.
6
6
  *
7
7
  * @fileoverview Datasource management commands for AI Fabrix Builder
8
8
  * @author AI Fabrix Team
9
9
  * @version 2.0.0
10
10
  */
11
11
 
12
+ const path = require('path');
12
13
  const chalk = require('chalk');
13
14
  const logger = require('../utils/logger');
15
+ const { sectionTitle, headerKeyValue, metadata, formatSuccessLine, formatBlockingError } = require('../utils/cli-test-layout-chalk');
14
16
  const { validateDatasourceFile } = require('../datasource/validate');
15
17
  const { listDatasources } = require('../datasource/list');
16
18
  const { compareDatasources } = require('../datasource/diff');
17
19
  const { deployDatasource } = require('../datasource/deploy');
18
- const { runDatasourceTestIntegration } = require('../datasource/test-integration');
19
- const { runDatasourceTestE2E } = require('../datasource/test-e2e');
20
20
  const { runLogViewer } = require('../datasource/log-viewer');
21
- const { displayIntegrationTestResults, displayE2EResults } = require('../utils/external-system-display');
21
+ const {
22
+ setupDatasourceTestCommand,
23
+ setupDatasourceTestIntegrationCommand,
24
+ setupDatasourceTestE2ECommand
25
+ } = require('./datasource-unified-test-cli');
26
+
27
+ const DATASOURCE_HELP_AFTER = `
28
+ Subcommands:
29
+ validate <file-or-key> Validate datasource JSON (path or datasource key under integration/<app>/)
30
+ list List datasources (env from config)
31
+ upload <file-or-key> Deploy one datasource JSON to the dataplane (path or key; systemKey in file)
32
+ diff Compare two datasource JSON files
33
+ test <key> Structural/policy validation via unified dataplane API (DatasourceTestRun)
34
+ test-integration / test-e2e Integration or E2E run via the same unified validation API
35
+ log-test / log-integration / log-e2e Show saved debug logs (structural, integration, E2E)
36
+ `;
37
+
38
+ const DATASOURCE_VALIDATE_HELP_AFTER = `
39
+ Examples:
40
+ $ aifabrix datasource validate test-e2e-hubspot-users
41
+ $ aifabrix datasource validate integration/myapp/myapp-datasource-contacts.json
42
+ $ aifabrix datasource validate ./test-e2e-hubspot-datasource-users.json
43
+ $ aifabrix datasource validate /path/to/system-datasource-entity.json
44
+ $ af ds validate ../integration/hubspot/hubspot-datasource-deals.json
45
+ `;
46
+
47
+ const DATASOURCE_UPLOAD_HELP_AFTER = `
48
+ Examples:
49
+ $ aifabrix datasource upload test-e2e-hubspot-users
50
+ $ aifabrix datasource upload integration/myapp/myapp-datasource-contacts.json
51
+ $ aifabrix datasource upload ./test-e2e-hubspot-datasource-users.json
52
+ $ aifabrix datasource upload /path/to/system-datasource-entity.json
53
+ $ af ds upload ../integration/hubspot/hubspot-datasource-deals.json
54
+ `;
55
+
56
+ /**
57
+ * TTY layout for local datasource JSON validation (aligned with cli-test-layout-chalk).
58
+ * @param {{ valid: boolean, errors: string[], resolvedPath: string }} result
59
+ * @param {string} trimmed - original CLI argument
60
+ * @param {boolean} showMapping - show Key + File when key resolved to a path
61
+ */
62
+ function logDatasourceValidateOutcome(result, trimmed, showMapping) {
63
+ logger.log('');
64
+ logger.log(sectionTitle('Datasource validation'));
65
+ logger.log(metadata('Offline — JSON schema and integration wiring'));
66
+ logger.log('');
67
+ if (!result.valid) {
68
+ logger.log(headerKeyValue('File:', result.resolvedPath));
69
+ logger.log('');
70
+ logger.log(formatBlockingError('Datasource file has errors:'));
71
+ result.errors.forEach(error => logger.log(chalk.red(` • ${error}`)));
72
+ return;
73
+ }
74
+ if (showMapping) {
75
+ logger.log(headerKeyValue('Key:', trimmed));
76
+ logger.log(headerKeyValue('File:', result.resolvedPath));
77
+ } else {
78
+ logger.log(headerKeyValue('File:', result.resolvedPath));
79
+ }
80
+ logger.log('');
81
+ logger.log(formatSuccessLine('Datasource file is valid.'));
82
+ }
22
83
 
23
84
  function setupDatasourceValidateCommand(datasource) {
24
- datasource.command('validate <file>')
25
- .description('Validate external datasource JSON file')
26
- .action(async(file) => {
85
+ datasource.command('validate <file-or-key>')
86
+ .description('Validate datasource JSON (file path or datasource key under integration/<app>/)')
87
+ .addHelpText('after', DATASOURCE_VALIDATE_HELP_AFTER)
88
+ .action(async(fileOrKey) => {
27
89
  try {
28
- const result = await validateDatasourceFile(file);
29
- if (result.valid) {
30
- logger.log(chalk.green(`\n✓ Datasource file is valid: ${file}`));
31
- } else {
32
- logger.log(chalk.red(`\n✗ Datasource file has errors: ${file}`));
33
- result.errors.forEach(error => logger.log(chalk.red(` • ${error}`)));
90
+ const trimmed = fileOrKey.trim();
91
+ const result = await validateDatasourceFile(trimmed);
92
+ const resolvedPath = result.resolvedPath;
93
+ const argResolved = path.resolve(trimmed);
94
+ const showMapping = resolvedPath && argResolved !== resolvedPath && trimmed !== resolvedPath;
95
+ logDatasourceValidateOutcome(result, trimmed, showMapping);
96
+ if (!result.valid) {
34
97
  process.exit(1);
35
98
  }
36
99
  } catch (error) {
37
- logger.error(chalk.red('Validation failed:'), error.message);
100
+ logger.error(formatBlockingError('Validation failed:'), error.message);
38
101
  process.exit(1);
39
102
  }
40
103
  });
@@ -42,12 +105,12 @@ function setupDatasourceValidateCommand(datasource) {
42
105
 
43
106
  function setupDatasourceListCommand(datasource) {
44
107
  datasource.command('list')
45
- .description('List datasources from environment (uses environment from config.yaml)')
108
+ .description('List datasources for environment in config')
46
109
  .action(async() => {
47
110
  try {
48
111
  await listDatasources({});
49
112
  } catch (error) {
50
- logger.error(chalk.red('Failed to list datasources:'), error.message);
113
+ logger.error(formatBlockingError('Failed to list datasources:'), error.message);
51
114
  process.exit(1);
52
115
  }
53
116
  });
@@ -55,130 +118,92 @@ function setupDatasourceListCommand(datasource) {
55
118
 
56
119
  function setupDatasourceDiffCommand(datasource) {
57
120
  datasource.command('diff <file1> <file2>')
58
- .description('Compare two datasource configuration files (for dataplane)')
121
+ .description('Diff two datasource JSON files')
59
122
  .action(async(file1, file2) => {
60
123
  try {
61
124
  await compareDatasources(file1, file2);
62
125
  } catch (error) {
63
- logger.error(chalk.red('Diff failed:'), error.message);
126
+ logger.error(formatBlockingError('Diff failed:'), error.message);
64
127
  process.exit(1);
65
128
  }
66
129
  });
67
130
  }
68
131
 
69
132
  function setupDatasourceUploadCommand(datasource) {
70
- datasource.command('upload <myapp> <file>')
71
- .description('Upload datasource to dataplane')
72
- .action(async(myapp, file, options) => {
133
+ datasource.command('upload <file-or-key>')
134
+ .description('Deploy datasource JSON to dataplane (file path or datasource key under integration/<app>/)')
135
+ .addHelpText('after', DATASOURCE_UPLOAD_HELP_AFTER)
136
+ .action(async(fileOrKey, options) => {
73
137
  try {
74
- await deployDatasource(myapp, file, options);
138
+ await deployDatasource(fileOrKey, options);
75
139
  } catch (error) {
76
- logger.error(chalk.red('Upload failed:'), error.message);
140
+ logger.error(formatBlockingError('Upload failed:'), error.message);
77
141
  process.exit(1);
78
142
  }
79
143
  });
80
144
  }
81
145
 
82
- function setupDatasourceTestIntegrationCommand(datasource) {
83
- datasource.command('test-integration <datasourceKey>')
84
- .description('Run integration (config) test for one datasource via dataplane pipeline')
85
- .option('-a, --app <appKey>', 'App key (optional: resolve from cwd or datasource key if single match)')
86
- .option('-p, --payload <file>', 'Path to custom test payload file')
87
- .option('-e, --env <env>', 'Environment: dev, tst, or pro')
88
- .option('-v, --verbose', 'Show detailed step and validation output')
89
- .option('--debug', 'Include debug output and write log to integration/<appKey>/logs/')
90
- .option('--timeout <ms>', 'Request timeout in milliseconds', '30000')
91
- .action(async(datasourceKey, options) => {
92
- try {
93
- const result = await runDatasourceTestIntegration(datasourceKey, {
94
- app: options.app,
95
- payload: options.payload,
96
- environment: options.env,
97
- debug: options.debug,
98
- timeout: options.timeout
99
- });
100
- displayIntegrationTestResults({
101
- systemKey: result.systemKey || 'unknown',
102
- datasourceResults: [result],
103
- success: result.success
104
- }, options.verbose);
105
- if (!result.success) process.exit(1);
106
- } catch (error) {
107
- logger.error(chalk.red('❌ Integration test failed:'), error.message);
108
- process.exit(1);
109
- }
110
- });
111
- }
112
-
113
- function setupDatasourceTestE2ECommand(datasource) {
114
- datasource.command('test-e2e <datasourceKey>')
115
- .description('Run E2E test for one datasource (config, credential, sync, data, CIP) via dataplane')
116
- .option('-a, --app <appKey>', 'App key (default: resolve from cwd if inside integration/<appKey>/)')
117
- .option('-e, --env <env>', 'Environment: dev, tst, or pro')
118
- .option('-v, --verbose', 'Show detailed step output and poll progress')
119
- .option('--debug', 'Include debug output and write log to integration/<appKey>/logs/')
120
- .option('--test-crud', 'Enable CRUD lifecycle test (body testCrud: true)')
121
- .option('--record-id <id>', 'Record ID for test (body recordId)')
122
- .option('--no-cleanup', 'Disable cleanup after test (body cleanup: false)')
123
- .option('--primary-key-value <value|@path>', 'Primary key value or path to JSON file (e.g. @pk.json) for body primaryKeyValue')
124
- .option('--no-async', 'Use sync mode (no polling); single POST, no asyncRun')
146
+ function setupDatasourceLogE2ECommand(datasource) {
147
+ datasource.command('log-e2e <datasourceKey>')
148
+ .description('Show E2E test log (latest or --file)')
149
+ .option(
150
+ '-a, --app <app>',
151
+ 'Integration folder name (optional: resolve from cwd or datasource key if single match)'
152
+ )
153
+ .option('-f, --file <path>', 'Path to log file (default: latest in app logs folder)')
125
154
  .action(async(datasourceKey, options) => {
126
155
  try {
127
- const data = await runDatasourceTestE2E(datasourceKey, {
156
+ await runLogViewer(datasourceKey, {
128
157
  app: options.app,
129
- environment: options.env,
130
- debug: options.debug,
131
- verbose: options.verbose,
132
- async: options.async !== false,
133
- testCrud: options.testCrud,
134
- recordId: options.recordId,
135
- cleanup: options.cleanup,
136
- primaryKeyValue: options.primaryKeyValue
158
+ file: options.file,
159
+ logType: 'test-e2e'
137
160
  });
138
- displayE2EResults(data, options.verbose);
139
- const steps = data.steps || data.completedActions || [];
140
- const failed = data.success === false || steps.some(s => s.success === false || s.error);
141
- if (failed) process.exit(1);
142
161
  } catch (error) {
143
- logger.error(chalk.red(' E2E test failed:'), error.message);
162
+ logger.error(formatBlockingError('log-e2e failed:'), error.message);
144
163
  process.exit(1);
145
164
  }
146
165
  });
147
166
  }
148
167
 
149
- function setupDatasourceLogE2ECommand(datasource) {
150
- datasource.command('log-e2e <datasourceKey>')
151
- .description('Display latest or specified E2E test log in readable format')
152
- .option('-a, --app <appKey>', 'App key (optional: resolve from cwd or datasource key if single match)')
168
+ function setupDatasourceLogIntegrationCommand(datasource) {
169
+ datasource.command('log-integration <datasourceKey>')
170
+ .description('Show integration test log (latest or --file)')
171
+ .option(
172
+ '-a, --app <app>',
173
+ 'Integration folder name (optional: resolve from cwd or datasource key if single match)'
174
+ )
153
175
  .option('-f, --file <path>', 'Path to log file (default: latest in app logs folder)')
154
176
  .action(async(datasourceKey, options) => {
155
177
  try {
156
178
  await runLogViewer(datasourceKey, {
157
179
  app: options.app,
158
180
  file: options.file,
159
- logType: 'test-e2e'
181
+ logType: 'test-integration'
160
182
  });
161
183
  } catch (error) {
162
- logger.error(chalk.red('log-e2e failed:'), error.message);
184
+ logger.error(formatBlockingError('log-integration failed:'), error.message);
163
185
  process.exit(1);
164
186
  }
165
187
  });
166
188
  }
167
189
 
168
- function setupDatasourceLogIntegrationCommand(datasource) {
169
- datasource.command('log-integration <datasourceKey>')
170
- .description('Display latest or specified integration test log in readable format')
171
- .option('-a, --app <appKey>', 'App key (optional: resolve from cwd or datasource key if single match)')
172
- .option('-f, --file <path>', 'Path to log file (default: latest in app logs folder)')
190
+ function setupDatasourceLogTestCommand(datasource) {
191
+ datasource.command('log-test <datasourceKey>')
192
+ .description('Show structural validation log from datasource test (latest test-*.json or --file)')
193
+ .option(
194
+ '-a, --app <app>',
195
+ 'Integration folder name (optional: resolve from cwd or datasource key if single match)'
196
+ )
197
+ .option('-f, --file <path>', 'Path to log file (default: latest structural log in app logs folder)')
173
198
  .action(async(datasourceKey, options) => {
174
199
  try {
175
200
  await runLogViewer(datasourceKey, {
176
201
  app: options.app,
177
202
  file: options.file,
178
- logType: 'test-integration'
203
+ logType: 'test'
179
204
  });
180
205
  } catch (error) {
181
- logger.error(chalk.red('log-integration failed:'), error.message);
206
+ logger.error(formatBlockingError('log-test failed:'), error.message);
182
207
  process.exit(1);
183
208
  }
184
209
  });
@@ -189,7 +214,10 @@ function setupDatasourceLogIntegrationCommand(datasource) {
189
214
  * @param {Command} program - Commander program instance
190
215
  */
191
216
  function setupDatasourceCommands(program) {
192
- const datasource = program.command('datasource').description('Manage external data sources');
217
+ const datasource = program
218
+ .command('datasource')
219
+ .description('Datasource JSON: validate, list, deploy, test, logs')
220
+ .addHelpText('after', DATASOURCE_HELP_AFTER);
193
221
  if (typeof datasource.alias === 'function') {
194
222
  datasource.alias('ds');
195
223
  }
@@ -197,10 +225,12 @@ function setupDatasourceCommands(program) {
197
225
  setupDatasourceListCommand(datasource);
198
226
  setupDatasourceDiffCommand(datasource);
199
227
  setupDatasourceUploadCommand(datasource);
228
+ setupDatasourceTestCommand(datasource);
200
229
  setupDatasourceTestIntegrationCommand(datasource);
201
230
  setupDatasourceTestE2ECommand(datasource);
202
231
  setupDatasourceLogE2ECommand(datasource);
203
232
  setupDatasourceLogIntegrationCommand(datasource);
233
+ setupDatasourceLogTestCommand(datasource);
204
234
  }
205
235
 
206
236
  module.exports = { setupDatasourceCommands };
@@ -1,3 +1,4 @@
1
+ const { formatBlockingError } = require('../utils/cli-test-layout-chalk');
1
2
  /**
2
3
  * Deployment list commands – list deployments for environment or for an app
3
4
  * Uses GET .../deployments and GET .../applications/{appKey}/deployments.
@@ -97,7 +98,7 @@ async function runDeploymentList(options = {}) {
97
98
  );
98
99
  displayDeploymentList(extractDeployments(response), environment, authResult.controllerUrl);
99
100
  } catch (error) {
100
- logger.error(chalk.red(`❌ Failed to list deployments: ${error.message}`));
101
+ logger.error(formatBlockingError(`Failed to list deployments: ${error.message}`));
101
102
  process.exit(1);
102
103
  }
103
104
  }
@@ -133,13 +134,13 @@ function displayAppDeploymentList(deployments, appKey, environment, controllerUr
133
134
  async function resolveDeploymentListContext(options) {
134
135
  const controllerUrl = options.controller || (await resolveControllerUrl());
135
136
  if (!controllerUrl) {
136
- logger.error(chalk.red('Controller URL is required. Run "aifabrix login" first.'));
137
+ logger.error(formatBlockingError('Controller URL is required. Run "aifabrix login" first.'));
137
138
  process.exit(1);
138
139
  }
139
140
  const environment = options.environment || (await resolveEnvironment());
140
141
  const authResult = await getDeploymentListAuth(controllerUrl);
141
142
  if (!authResult || !authResult.token) {
142
- logger.error(chalk.red(`❌ No authentication token for controller: ${controllerUrl}`));
143
+ logger.error(formatBlockingError(`No authentication token for controller: ${controllerUrl}`));
143
144
  logger.error(chalk.gray('Run: aifabrix login'));
144
145
  process.exit(1);
145
146
  }
@@ -158,7 +159,7 @@ async function resolveDeploymentListContext(options) {
158
159
  */
159
160
  async function runAppDeploymentList(appKey, options = {}) {
160
161
  if (!appKey || typeof appKey !== 'string') {
161
- logger.error(chalk.red('Application key is required.'));
162
+ logger.error(formatBlockingError('Application key is required.'));
162
163
  process.exit(1);
163
164
  return;
164
165
  }
@@ -180,7 +181,7 @@ async function runAppDeploymentList(appKey, options = {}) {
180
181
  authResult.controllerUrl
181
182
  );
182
183
  } catch (error) {
183
- logger.error(chalk.red(`❌ Failed to list deployments for ${appKey}: ${error.message}`));
184
+ logger.error(formatBlockingError(`Failed to list deployments for ${appKey}: ${error.message}`));
184
185
  process.exit(1);
185
186
  }
186
187
  }