@aifabrix/builder 2.43.0 → 2.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (346) hide show
  1. package/.cursor/rules/anchor-docs.mdc +15 -0
  2. package/README.md +1 -1
  3. package/anchor-docs/README.md +10 -0
  4. package/anchor-docs/_TEMPLATE +24 -0
  5. package/bin/aifabrix.js +13 -4
  6. package/integration/hubspot-test/README.md +31 -0
  7. package/integration/hubspot-test/create-hubspot.js +5 -5
  8. package/integration/hubspot-test/hubspot-test-datasource-company.json +58 -462
  9. package/integration/hubspot-test/hubspot-test-datasource-contact.json +61 -555
  10. package/integration/hubspot-test/hubspot-test-datasource-deal.json +63 -506
  11. package/integration/hubspot-test/hubspot-test-datasource-users.json +42 -83
  12. package/integration/hubspot-test/hubspot-test-deploy.json +3 -3
  13. package/integration/hubspot-test/test-dataplane-down-tests.js +1 -7
  14. package/integration/hubspot-test/test-dataplane-down.js +3 -3
  15. package/integration/hubspot-test/test.js +35 -43
  16. package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
  17. package/integration/roundtrip-test-local/README.md +144 -0
  18. package/integration/roundtrip-test-local/application.yaml +13 -0
  19. package/integration/roundtrip-test-local/env.template +15 -0
  20. package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
  21. package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
  22. package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
  23. package/integration/roundtrip-test-local2/README.md +144 -0
  24. package/integration/roundtrip-test-local2/application.yaml +13 -0
  25. package/integration/roundtrip-test-local2/env.template +15 -0
  26. package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
  27. package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
  28. package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
  29. package/integration/test/wizard.yaml +8 -0
  30. package/jest.config.default.js +10 -0
  31. package/jest.config.integration.fixtures.js +22 -0
  32. package/jest.config.integration.js +21 -18
  33. package/jest.config.isolated.js +10 -0
  34. package/jest.projects.js +288 -0
  35. package/lib/api/datasources-core.api.js +3 -3
  36. package/lib/api/dev-mtls-request.js +110 -0
  37. package/lib/api/dev-server-https.js +145 -0
  38. package/lib/api/dev.api.js +133 -144
  39. package/lib/api/index.js +0 -1
  40. package/lib/api/pipeline.api.js +67 -20
  41. package/lib/api/types/dev.types.js +4 -3
  42. package/lib/api/types/pipeline.types.js +8 -5
  43. package/lib/api/types/validation-run.types.js +56 -0
  44. package/lib/api/validation-run.api.js +99 -0
  45. package/lib/api/validation-runner.js +99 -0
  46. package/lib/app/config.js +1 -1
  47. package/lib/app/deploy-status-display.js +2 -2
  48. package/lib/app/deploy.js +7 -6
  49. package/lib/app/display.js +2 -1
  50. package/lib/app/dockerfile.js +3 -2
  51. package/lib/app/down.js +2 -1
  52. package/lib/app/helpers.js +6 -5
  53. package/lib/app/index.js +27 -8
  54. package/lib/app/list.js +7 -6
  55. package/lib/app/push.js +4 -3
  56. package/lib/app/register.js +16 -7
  57. package/lib/app/rotate-secret.js +14 -13
  58. package/lib/app/run-container-start.js +184 -0
  59. package/lib/app/run-docker-fallback.js +108 -0
  60. package/lib/app/run-env-compose.js +30 -42
  61. package/lib/app/run-helpers.js +49 -126
  62. package/lib/app/run-infra-requirements.js +30 -0
  63. package/lib/app/run-resolve-image.js +21 -0
  64. package/lib/app/run.js +74 -21
  65. package/lib/app/show-display.js +1 -1
  66. package/lib/app/show.js +1 -1
  67. package/lib/build/index.js +13 -10
  68. package/lib/cli/index.js +2 -0
  69. package/lib/cli/setup-app.help.js +67 -0
  70. package/lib/cli/setup-app.js +57 -121
  71. package/lib/cli/setup-app.test-commands.js +179 -0
  72. package/lib/cli/setup-auth.js +19 -5
  73. package/lib/cli/setup-credential-deployment.js +22 -8
  74. package/lib/cli/setup-dev-path-commands.js +124 -0
  75. package/lib/cli/setup-dev.js +170 -113
  76. package/lib/cli/setup-environment.js +7 -1
  77. package/lib/cli/setup-external-system.js +62 -22
  78. package/lib/cli/setup-infra.js +126 -47
  79. package/lib/cli/setup-parameters.js +32 -0
  80. package/lib/cli/setup-secrets.js +106 -8
  81. package/lib/cli/setup-service-user.js +1 -1
  82. package/lib/cli/setup-utility.js +36 -20
  83. package/lib/commands/app-down.js +5 -7
  84. package/lib/commands/app-install.js +14 -7
  85. package/lib/commands/app-logs.js +13 -10
  86. package/lib/commands/app-shell.js +4 -1
  87. package/lib/commands/app-test.js +25 -19
  88. package/lib/commands/app.js +22 -10
  89. package/lib/commands/auth-config.js +6 -6
  90. package/lib/commands/auth-status.js +4 -3
  91. package/lib/commands/credential-env.js +4 -3
  92. package/lib/commands/credential-list.js +5 -4
  93. package/lib/commands/credential-push.js +4 -3
  94. package/lib/commands/datasource-unified-test-cli.js +495 -0
  95. package/lib/commands/datasource-unified-test-cli.options.js +149 -0
  96. package/lib/commands/datasource-validation-cli.js +129 -0
  97. package/lib/commands/datasource.js +105 -98
  98. package/lib/commands/deployment-list.js +6 -5
  99. package/lib/commands/dev-cli-handlers.js +122 -18
  100. package/lib/commands/dev-down.js +4 -3
  101. package/lib/commands/dev-init.js +231 -116
  102. package/lib/commands/dev-show-display.js +473 -0
  103. package/lib/commands/login-credentials.js +3 -2
  104. package/lib/commands/login-device.js +4 -3
  105. package/lib/commands/login.js +5 -4
  106. package/lib/commands/logout.js +8 -7
  107. package/lib/commands/parameters-validate.js +54 -0
  108. package/lib/commands/repair-datasource.js +314 -68
  109. package/lib/commands/repair-env-template.js +2 -2
  110. package/lib/commands/repair.js +21 -3
  111. package/lib/commands/secrets-list.js +23 -12
  112. package/lib/commands/secrets-remove-all.js +220 -0
  113. package/lib/commands/secrets-remove.js +21 -12
  114. package/lib/commands/secrets-set.js +21 -12
  115. package/lib/commands/secrets-validate.js +4 -4
  116. package/lib/commands/secure.js +10 -9
  117. package/lib/commands/service-user.js +26 -25
  118. package/lib/commands/test-e2e-external.js +27 -1
  119. package/lib/commands/up-common.js +3 -2
  120. package/lib/commands/up-dataplane.js +29 -16
  121. package/lib/commands/up-miso.js +19 -29
  122. package/lib/commands/upload.js +138 -39
  123. package/lib/commands/wizard-core-helpers.js +1 -1
  124. package/lib/commands/wizard-dataplane.js +4 -3
  125. package/lib/commands/wizard-helpers.js +3 -3
  126. package/lib/commands/wizard.js +2 -2
  127. package/lib/core/admin-secrets.js +14 -5
  128. package/lib/core/audit-logger.js +12 -4
  129. package/lib/core/config-attach-extensions.js +46 -0
  130. package/lib/core/config-runtime-paths.js +29 -0
  131. package/lib/core/config.js +55 -56
  132. package/lib/core/diff.js +3 -2
  133. package/lib/core/ensure-encryption-key.js +1 -1
  134. package/lib/core/secrets-ensure-infra.js +77 -0
  135. package/lib/core/secrets-ensure.js +120 -64
  136. package/lib/core/secrets-env-write.js +35 -7
  137. package/lib/core/secrets-infra-placeholder-sync.js +61 -0
  138. package/lib/core/secrets.js +200 -37
  139. package/lib/core/templates-env.js +4 -3
  140. package/lib/datasource/abac-validator.js +1 -10
  141. package/lib/datasource/deploy.js +75 -53
  142. package/lib/datasource/field-reference-validator.js +9 -6
  143. package/lib/datasource/integration-context.js +63 -0
  144. package/lib/datasource/list.js +8 -7
  145. package/lib/datasource/log-viewer.js +84 -53
  146. package/lib/datasource/resolve-app.js +4 -4
  147. package/lib/datasource/test-e2e.js +95 -146
  148. package/lib/datasource/test-integration.js +114 -122
  149. package/lib/datasource/unified-validation-run-body.js +65 -0
  150. package/lib/datasource/unified-validation-run-post.js +23 -0
  151. package/lib/datasource/unified-validation-run-resolve.js +43 -0
  152. package/lib/datasource/unified-validation-run.js +92 -0
  153. package/lib/datasource/validate.js +157 -13
  154. package/lib/deployment/deployer.js +4 -3
  155. package/lib/deployment/environment.js +7 -6
  156. package/lib/deployment/push.js +17 -8
  157. package/lib/external-system/delete.js +4 -3
  158. package/lib/external-system/deploy.js +131 -53
  159. package/lib/external-system/download-helpers.js +1 -1
  160. package/lib/external-system/download.js +7 -6
  161. package/lib/external-system/generator.js +92 -6
  162. package/lib/external-system/integration-test-dispatch.js +26 -0
  163. package/lib/external-system/test-execution.js +5 -1
  164. package/lib/external-system/test-helpers.js +0 -4
  165. package/lib/external-system/test-system-level-helpers.js +110 -0
  166. package/lib/external-system/test-system-level.js +83 -44
  167. package/lib/external-system/test.js +59 -8
  168. package/lib/generator/builders.js +23 -11
  169. package/lib/generator/deploy-manifest-azure-kv.js +81 -0
  170. package/lib/generator/external.js +16 -4
  171. package/lib/generator/helpers.js +58 -3
  172. package/lib/generator/index.js +4 -0
  173. package/lib/generator/split-readme.js +12 -7
  174. package/lib/generator/split-variables.js +2 -1
  175. package/lib/generator/split.js +1 -1
  176. package/lib/generator/wizard-readme.js +3 -3
  177. package/lib/generator/wizard.js +8 -8
  178. package/lib/infrastructure/compose.js +60 -6
  179. package/lib/infrastructure/helpers.js +201 -29
  180. package/lib/infrastructure/index.js +28 -17
  181. package/lib/infrastructure/services.js +21 -15
  182. package/lib/internal/fs-real-sync.js +104 -0
  183. package/lib/internal/node-fs.js +98 -0
  184. package/lib/parameters/database-secret-values.js +173 -0
  185. package/lib/parameters/infra-kv-discovery.js +121 -0
  186. package/lib/parameters/infra-parameter-catalog.js +458 -0
  187. package/lib/parameters/infra-parameter-validate.js +64 -0
  188. package/lib/schema/application-schema.json +37 -17
  189. package/lib/schema/datasource-test-run.schema.json +493 -0
  190. package/lib/schema/deployment-rules.yaml +102 -63
  191. package/lib/schema/external-datasource.schema.json +1200 -442
  192. package/lib/schema/external-system.schema.json +181 -5
  193. package/lib/schema/flag-map-validation-run.json +31 -0
  194. package/lib/schema/infra-parameter.schema.json +106 -0
  195. package/lib/schema/infra.parameter.yaml +421 -0
  196. package/lib/schema/type/credential-auth-templates.json +40 -0
  197. package/lib/schema/type/document-storage.json +213 -0
  198. package/lib/schema/type/message-service.json +123 -0
  199. package/lib/schema/type/vector-store.json +88 -0
  200. package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
  201. package/lib/utils/api-error-handler.js +2 -2
  202. package/lib/utils/api.js +49 -14
  203. package/lib/utils/app-register-api.js +3 -2
  204. package/lib/utils/app-register-auth.js +1 -1
  205. package/lib/utils/app-register-config.js +4 -4
  206. package/lib/utils/app-register-display.js +3 -2
  207. package/lib/utils/app-register-validator.js +3 -2
  208. package/lib/utils/app-run-containers.js +26 -22
  209. package/lib/utils/app-scoped-config.js +31 -0
  210. package/lib/utils/app-service-env-from-builder.js +164 -0
  211. package/lib/utils/build-copy.js +1 -1
  212. package/lib/utils/build-helpers.js +20 -20
  213. package/lib/utils/build-resolve-image.js +165 -0
  214. package/lib/utils/cli-layout-chalk.js +8 -0
  215. package/lib/utils/cli-test-layout-chalk.js +267 -0
  216. package/lib/utils/cli-utils.js +88 -11
  217. package/lib/utils/compose-db-passwords.js +138 -0
  218. package/lib/utils/compose-generate-docker-compose.js +216 -0
  219. package/lib/utils/compose-generator.js +197 -291
  220. package/lib/utils/compose-miso-env.js +18 -0
  221. package/lib/utils/compose-traefik-ingress-base.js +158 -0
  222. package/lib/utils/config-paths.js +166 -7
  223. package/lib/utils/config-scoped-resources-preference.js +41 -0
  224. package/lib/utils/controller-deployment-outcome.js +68 -0
  225. package/lib/utils/credential-display.js +2 -2
  226. package/lib/utils/dataplane-pipeline-warning.js +4 -3
  227. package/lib/utils/datasource-test-run-capability-scope.js +43 -0
  228. package/lib/utils/datasource-test-run-debug-display.js +137 -0
  229. package/lib/utils/datasource-test-run-debug-slice.js +93 -0
  230. package/lib/utils/datasource-test-run-display.js +442 -0
  231. package/lib/utils/datasource-test-run-exit.js +58 -0
  232. package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
  233. package/lib/utils/datasource-test-run-report-version.js +51 -0
  234. package/lib/utils/datasource-test-run-schema-sync.js +59 -0
  235. package/lib/utils/datasource-test-run-tty-log.js +81 -0
  236. package/lib/utils/datasource-validation-watch.js +266 -0
  237. package/lib/utils/declarative-url-ports.js +47 -0
  238. package/lib/utils/derive-env-key-from-client-id.js +41 -0
  239. package/lib/utils/dev-ca-install.js +185 -23
  240. package/lib/utils/dev-cert-helper.js +266 -17
  241. package/lib/utils/dev-hosts-helper.js +307 -0
  242. package/lib/utils/dev-init-cert-hints.js +37 -0
  243. package/lib/utils/dev-init-health-messages.js +52 -0
  244. package/lib/utils/dev-init-resolve.js +86 -0
  245. package/lib/utils/dev-init-ssh-merge.js +65 -0
  246. package/lib/utils/dev-ssh-config-helper.js +196 -0
  247. package/lib/utils/dev-user-groups.js +93 -0
  248. package/lib/utils/docker-build.js +42 -17
  249. package/lib/utils/docker-exec.js +28 -0
  250. package/lib/utils/docker-manifest-public-port.js +116 -0
  251. package/lib/utils/docker-not-running-hint.js +52 -0
  252. package/lib/utils/docker.js +98 -11
  253. package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
  254. package/lib/utils/env-config-loader.js +10 -91
  255. package/lib/utils/env-copy.js +19 -10
  256. package/lib/utils/env-map.js +35 -8
  257. package/lib/utils/env-template.js +2 -2
  258. package/lib/utils/environment-scoped-resources.js +144 -0
  259. package/lib/utils/error-formatter.js +92 -13
  260. package/lib/utils/error-formatters/http-status-errors.js +6 -5
  261. package/lib/utils/error-formatters/network-errors.js +2 -1
  262. package/lib/utils/error-formatters/permission-errors.js +2 -1
  263. package/lib/utils/error-formatters/validation-errors.js +2 -1
  264. package/lib/utils/external-readme.js +8 -1
  265. package/lib/utils/external-system-display.js +234 -136
  266. package/lib/utils/external-system-local-test-tty.js +389 -0
  267. package/lib/utils/external-system-readiness-core.js +377 -0
  268. package/lib/utils/external-system-readiness-deploy-display.js +270 -0
  269. package/lib/utils/external-system-readiness-display-internals.js +150 -0
  270. package/lib/utils/external-system-readiness-display.js +186 -0
  271. package/lib/utils/external-system-test-helpers.js +24 -6
  272. package/lib/utils/external-system-validators.js +30 -12
  273. package/lib/utils/health-check-url.js +119 -0
  274. package/lib/utils/health-check.js +59 -25
  275. package/lib/utils/help-builder.js +11 -8
  276. package/lib/utils/image-version.js +4 -8
  277. package/lib/utils/infra-containers.js +4 -7
  278. package/lib/utils/infra-env-defaults.js +162 -0
  279. package/lib/utils/infra-status-display.js +167 -0
  280. package/lib/utils/infra-status.js +16 -8
  281. package/lib/utils/local-secrets.js +3 -4
  282. package/lib/utils/paths.js +134 -47
  283. package/lib/utils/port-resolver.js +10 -23
  284. package/lib/utils/redis-env-scope.js +62 -0
  285. package/lib/utils/register-aifabrix-shell-env.js +204 -0
  286. package/lib/utils/remote-builder-validation.js +99 -0
  287. package/lib/utils/remote-dev-auth.js +117 -21
  288. package/lib/utils/remote-docker-env.js +67 -15
  289. package/lib/utils/remote-secrets-loader.js +13 -4
  290. package/lib/utils/resolve-docker-image-ref.js +124 -0
  291. package/lib/utils/schema-loader.js +22 -9
  292. package/lib/utils/secrets-bash-kv.js +25 -0
  293. package/lib/utils/secrets-generator.js +169 -49
  294. package/lib/utils/secrets-helpers.js +70 -59
  295. package/lib/utils/secrets-kv-scope.js +60 -0
  296. package/lib/utils/secrets-utils.js +32 -38
  297. package/lib/utils/secrets-validation.js +3 -1
  298. package/lib/utils/secrets-yaml-preserve.js +109 -0
  299. package/lib/utils/ssh-key-helper.js +4 -2
  300. package/lib/utils/template-helpers.js +2 -2
  301. package/lib/utils/test-log-writer.js +3 -3
  302. package/lib/utils/token-manager.js +1 -2
  303. package/lib/utils/url-declarative-public-base.js +188 -0
  304. package/lib/utils/url-declarative-resolve-build.js +493 -0
  305. package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
  306. package/lib/utils/url-declarative-resolve.js +220 -0
  307. package/lib/utils/url-declarative-token-parse.js +74 -0
  308. package/lib/utils/url-declarative-url-flags.js +50 -0
  309. package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
  310. package/lib/utils/url-public-path-prefix.js +34 -0
  311. package/lib/utils/urls-local-registry.js +220 -0
  312. package/lib/utils/validation-report-tty-kit.js +77 -0
  313. package/lib/utils/validation-run-poll.js +89 -0
  314. package/lib/utils/validation-run-post-retry.js +73 -0
  315. package/lib/utils/validation-run-request.js +98 -0
  316. package/lib/utils/variable-transformer.js +21 -4
  317. package/lib/utils/yaml-preserve.js +33 -14
  318. package/lib/validation/datasource-warnings.js +56 -0
  319. package/lib/validation/env-template-auth.js +1 -1
  320. package/lib/validation/external-manifest-validator.js +27 -7
  321. package/lib/validation/validate-display.js +37 -31
  322. package/lib/validation/validate.js +4 -13
  323. package/lib/validation/validator-unresolved-placeholders.js +98 -0
  324. package/lib/validation/validator.js +22 -65
  325. package/lib/validation/wizard-config-validator.js +2 -1
  326. package/package.json +7 -3
  327. package/scripts/check-datasource-test-run-schema-sync.js +34 -0
  328. package/scripts/diagnose-cli.js +150 -0
  329. package/scripts/install-local.js +304 -55
  330. package/templates/README.md +15 -2
  331. package/templates/applications/dataplane/application.yaml +52 -2
  332. package/templates/applications/dataplane/env.template +75 -17
  333. package/templates/applications/dataplane/rbac.yaml +8 -0
  334. package/templates/applications/keycloak/application.yaml +9 -1
  335. package/templates/applications/keycloak/env.template +15 -6
  336. package/templates/applications/miso-controller/application.yaml +10 -2
  337. package/templates/applications/miso-controller/env.template +42 -12
  338. package/templates/applications/miso-controller/rbac.yaml +5 -0
  339. package/templates/external-system/README.md.hbs +20 -7
  340. package/templates/external-system/deploy.js.hbs +5 -5
  341. package/templates/external-system/external-datasource.yaml.hbs +197 -118
  342. package/templates/infra/compose.yaml.hbs +20 -4
  343. package/templates/python/docker-compose.hbs +16 -0
  344. package/templates/typescript/docker-compose.hbs +16 -0
  345. package/lib/api/external-test.api.js +0 -111
  346. package/lib/schema/env-config.yaml +0 -60
@@ -10,118 +10,29 @@
10
10
 
11
11
  const chalk = require('chalk');
12
12
  const logger = require('./logger');
13
+ const { SEP, statusGlyph } = require('./datasource-test-run-display');
14
+ const { logEnvelopeForInteractiveCli } = require('./datasource-test-run-tty-log');
15
+ const { displayLocalExternalTestPlanLayout } = require('./external-system-local-test-tty');
16
+ const {
17
+ sectionTitle,
18
+ headerKeyValue,
19
+ formatStatusKeyValue,
20
+ formatDatasourceListRow,
21
+ integrationFooterLine,
22
+ formatSuccessParagraph,
23
+ formatBlockingError,
24
+ successGlyph,
25
+ failureGlyph
26
+ } = require('./cli-test-layout-chalk');
13
27
 
14
28
  /**
15
- * Displays system file results
16
- * @function displaySystemResults
17
- * @param {Object[]} systemResults - System file results
18
- */
19
- function displaySystemResults(systemResults) {
20
- if (systemResults.length === 0) {
21
- return;
22
- }
23
- logger.log(chalk.blue('System Files:'));
24
- for (const systemResult of systemResults) {
25
- if (systemResult.valid) {
26
- logger.log(chalk.green(` āœ“ ${systemResult.file}`));
27
- } else {
28
- logger.log(chalk.red(` āœ— ${systemResult.file}`));
29
- }
30
- }
31
- }
32
-
33
- /**
34
- * Displays verbose datasource details
35
- * @function displayVerboseDatasourceDetails
36
- * @param {Object} dsResult - Datasource result
37
- */
38
- function displayVerboseDatasourceDetails(dsResult) {
39
- if (dsResult.warnings.length > 0) {
40
- dsResult.warnings.forEach(warn => logger.log(chalk.yellow(` ⚠ ${warn}`)));
41
- }
42
-
43
- if (dsResult.fieldMappingResults) {
44
- const fm = dsResult.fieldMappingResults;
45
- logger.log(chalk.gray(` Field mappings: ${Object.keys(fm.mappedFields || {}).length} fields`));
46
- }
47
-
48
- if (dsResult.metadataSchemaResults) {
49
- const ms = dsResult.metadataSchemaResults;
50
- const statusMsg = ms.valid ? ' Metadata schema: āœ“ Valid' : ' Metadata schema: āœ— Invalid';
51
- logger.log(ms.valid ? chalk.gray(statusMsg) : chalk.red(statusMsg));
52
- }
53
- }
54
-
55
- /**
56
- * Displays datasource file results
57
- * @function displayDatasourceResults
58
- * @param {Object[]} datasourceResults - Datasource file results
59
- * @param {boolean} verbose - Show detailed output
60
- */
61
- function displayDatasourceResults(datasourceResults, verbose) {
62
- if (datasourceResults.length === 0) {
63
- return;
64
- }
65
- logger.log(chalk.blue('\nDatasource Files:'));
66
- for (const dsResult of datasourceResults) {
67
- if (dsResult.valid) {
68
- logger.log(chalk.green(` āœ“ ${dsResult.key} (${dsResult.file})`));
69
- } else {
70
- logger.log(chalk.red(` āœ— ${dsResult.key} (${dsResult.file})`));
71
- if (verbose && dsResult.errors.length > 0) {
72
- dsResult.errors.forEach(err => logger.log(chalk.red(` - ${err}`)));
73
- }
74
- }
75
-
76
- if (verbose) {
77
- displayVerboseDatasourceDetails(dsResult);
78
- }
79
- }
80
- }
81
-
82
- /**
83
- * Displays errors and warnings
84
- * @function displayErrorsAndWarnings
85
- * @param {string[]} errors - Error messages
86
- * @param {string[]} warnings - Warning messages
87
- */
88
- function displayErrorsAndWarnings(errors, warnings) {
89
- if (errors.length > 0) {
90
- logger.log(chalk.red('\nāŒ Errors:'));
91
- errors.forEach(err => logger.log(chalk.red(` - ${err}`)));
92
- }
93
-
94
- if (warnings.length > 0) {
95
- logger.log(chalk.yellow('\n⚠ Warnings:'));
96
- warnings.forEach(warn => logger.log(chalk.yellow(` - ${warn}`)));
97
- }
98
- }
99
-
100
- /**
101
- * Displays final test status
102
- * @function displayFinalTestStatus
103
- * @param {boolean} valid - Whether all tests passed
104
- */
105
- function displayFinalTestStatus(valid) {
106
- if (valid) {
107
- logger.log(chalk.green('\nāœ… All tests passed!'));
108
- } else {
109
- logger.log(chalk.red('\nāŒ Some tests failed'));
110
- }
111
- }
112
-
113
- /**
114
- * Displays formatted test results
29
+ * Displays formatted test results (local external `aifabrix test` — structured report layout).
115
30
  * @param {Object} results - Test results
116
31
  * @param {boolean} verbose - Show detailed output
32
+ * @param {string} [appName] - Integration folder / app key for header
117
33
  */
118
- function displayTestResults(results, verbose = false) {
119
- logger.log(chalk.blue('\nšŸ“Š Test Results\n'));
120
-
121
- displaySystemResults(results.systemResults);
122
- displayDatasourceResults(results.datasourceResults, verbose);
123
- displayErrorsAndWarnings(results.errors, results.warnings);
124
- displayFinalTestStatus(results.valid);
34
+ function displayTestResults(results, verbose = false, appName = '') {
35
+ displayLocalExternalTestPlanLayout(results, verbose, appName || results.appName || results.systemKey || 'unknown');
125
36
  }
126
37
 
127
38
  /**
@@ -131,9 +42,9 @@ function displayTestResults(results, verbose = false) {
131
42
  */
132
43
  function displayVerboseValidationResults(vr) {
133
44
  if (vr.isValid) {
134
- logger.log(chalk.gray(' Validation: āœ“ Valid'));
45
+ logger.log(chalk.gray(' Validation: āœ” Valid'));
135
46
  } else {
136
- logger.log(chalk.red(' Validation: āœ— Invalid'));
47
+ logger.log(chalk.red(' Validation: āœ– Invalid'));
137
48
  }
138
49
  if (vr.errors && vr.errors.length > 0) {
139
50
  vr.errors.forEach(err => logger.log(chalk.red(` - ${err}`)));
@@ -163,7 +74,7 @@ function displayVerboseFieldMappingResults(fmr) {
163
74
  */
164
75
  function displayVerboseEndpointResults(etr) {
165
76
  if (etr.endpointConfigured) {
166
- logger.log(chalk.gray(' Endpoint: āœ“ Configured'));
77
+ logger.log(chalk.gray(' Endpoint: āœ” Configured'));
167
78
  } else {
168
79
  logger.log(chalk.gray(' Endpoint: Not configured'));
169
80
  }
@@ -191,54 +102,237 @@ function displayVerboseIntegrationDetails(dsResult) {
191
102
  }
192
103
 
193
104
  /**
194
- * Displays a single datasource integration test result
195
- * @function displayDatasourceIntegrationResult
105
+ * @param {Object} dsResult
106
+ * @returns {'ok'|'warn'|'fail'|'skipped'}
107
+ */
108
+ function legacyIntegrationRowStatus(dsResult) {
109
+ if (dsResult.skipped) return 'skipped';
110
+ if (!dsResult.success) return 'fail';
111
+ const w = dsResult.validationResults && dsResult.validationResults.warnings;
112
+ if (Array.isArray(w) && w.length > 0) return 'warn';
113
+ return 'ok';
114
+ }
115
+
116
+ function legacyIntegrationRowHint(dsResult) {
117
+ if (dsResult.skipped) return dsResult.reason || 'Skipped';
118
+ if (!dsResult.success) return 'Failed';
119
+ return legacyIntegrationRowStatus(dsResult) === 'warn' ? 'Partial' : 'Ready';
120
+ }
121
+
122
+ /**
123
+ * Displays a single datasource integration test result (legacy pipeline row).
196
124
  * @param {Object} dsResult - Datasource result
197
125
  * @param {boolean} verbose - Show detailed output
198
126
  */
199
127
  function displayDatasourceIntegrationResult(dsResult, verbose) {
128
+ const rowSt = legacyIntegrationRowStatus(dsResult);
129
+ const hint = legacyIntegrationRowHint(dsResult);
130
+ logger.log(formatDatasourceListRow(rowSt, dsResult.key, hint));
131
+
132
+ if (!dsResult.skipped && !dsResult.success && dsResult.error) {
133
+ logger.log(chalk.red(` Error: ${dsResult.error}`));
134
+ }
135
+
136
+ if (verbose) {
137
+ displayVerboseIntegrationDetails(dsResult);
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Worst status across server runs (envelope.status or transport failure).
143
+ * @param {Object} results
144
+ * @returns {'ok'|'warn'|'fail'}
145
+ */
146
+ function serverRowFails(r) {
147
+ if (r.skipped) return false;
148
+ if (r.datasourceTestRun && r.datasourceTestRun.status === 'fail') return true;
149
+ return !r.datasourceTestRun && r.success === false;
150
+ }
151
+
152
+ function serverRowWarns(r) {
153
+ if (r.skipped) return false;
154
+ return !!(r.datasourceTestRun && r.datasourceTestRun.status === 'warn');
155
+ }
156
+
157
+ function deriveAggregateServerStatus(results) {
158
+ const ds = results.datasourceResults || [];
159
+ if (ds.length === 0) {
160
+ return results.success === false ? 'fail' : 'ok';
161
+ }
162
+ if (ds.some(serverRowFails)) return 'fail';
163
+ if (ds.some(serverRowWarns)) return 'warn';
164
+ return results.success === false ? 'fail' : 'ok';
165
+ }
166
+
167
+ /**
168
+ * Aggregate status for legacy pipeline integration results (no DatasourceTestRun envelope).
169
+ * @param {Object} results
170
+ * @returns {'ok'|'warn'|'fail'}
171
+ */
172
+ function deriveAggregateLegacyIntegrationStatus(results) {
173
+ const ds = results.datasourceResults || [];
174
+ if (ds.length === 0) {
175
+ return results.success === false ? 'fail' : 'ok';
176
+ }
177
+ if (ds.some(r => !r.skipped && r.success === false)) return 'fail';
178
+ if (ds.some(r => legacyIntegrationRowStatus(r) === 'warn')) return 'warn';
179
+ return results.success === false ? 'fail' : 'ok';
180
+ }
181
+
182
+ function integrationResultsHaveEnvelope(results) {
183
+ return (results.datasourceResults || []).some(
184
+ r => r.datasourceTestRun && typeof r.datasourceTestRun === 'object'
185
+ );
186
+ }
187
+
188
+ /**
189
+ * One datasource with DatasourceTestRun — same display path as `aifabrix datasource test` (no server wrapper).
190
+ * @param {Object} results
191
+ * @returns {boolean}
192
+ */
193
+ function isSingleUnskippedEnvelopeRun(results) {
194
+ const rows = results.datasourceResults || [];
195
+ if (rows.length !== 1) return false;
196
+ const r = rows[0];
197
+ return Boolean(
198
+ r && !r.skipped && r.datasourceTestRun && typeof r.datasourceTestRun === 'object'
199
+ );
200
+ }
201
+
202
+ function runLabelForServerRun(runType) {
203
+ return runType === 'e2e' ? 'test-e2e (dataplane)' : 'test-integration (dataplane)';
204
+ }
205
+
206
+ function renderOneServerDatasourceRow(dsResult, verbose, opts) {
207
+ logger.log('');
208
+ if (!dsResult.datasourceTestRun) {
209
+ logger.log(headerKeyValue('Datasource:', dsResult.key));
210
+ }
200
211
  if (dsResult.skipped) {
201
- logger.log(chalk.yellow(` ⚠ ${dsResult.key}: ${dsResult.reason}`));
212
+ logger.log(formatDatasourceListRow('skipped', dsResult.key, dsResult.reason || 'Skipped'));
202
213
  return;
203
214
  }
215
+ if (dsResult.datasourceTestRun) {
216
+ logEnvelopeForInteractiveCli(dsResult.datasourceTestRun, {
217
+ json: false,
218
+ summary: false,
219
+ debug: opts.debug,
220
+ requestedCapabilityKey: opts.requestedCapabilityKey
221
+ });
222
+ return;
223
+ }
224
+ displayDatasourceIntegrationResult(dsResult, verbose);
225
+ }
204
226
 
205
- if (dsResult.success) {
206
- logger.log(chalk.green(` āœ“ ${dsResult.key}`));
207
- } else {
208
- logger.log(chalk.red(` āœ— ${dsResult.key}`));
209
- if (dsResult.error) {
210
- logger.log(chalk.red(` Error: ${dsResult.error}`));
211
- }
227
+ function logServerDatasourceTestRunHeader(results, runType, agg) {
228
+ logger.log('');
229
+ logger.log(sectionTitle('Server test results'));
230
+ logger.log('');
231
+ logger.log(headerKeyValue('System:', results.systemKey));
232
+ logger.log(headerKeyValue('Run:', runLabelForServerRun(runType)));
233
+ logger.log(formatStatusKeyValue(agg, statusGlyph(agg)));
234
+ logger.log('');
235
+ logger.log(chalk.gray(SEP));
236
+ }
237
+
238
+ function logServerDatasourceTestRunFooter(success, agg) {
239
+ logger.log(
240
+ integrationFooterLine(
241
+ success,
242
+ agg,
243
+ 'All server tests passed.',
244
+ 'Server tests completed with warnings.',
245
+ 'Some server tests failed.'
246
+ )
247
+ );
248
+ }
249
+
250
+ /**
251
+ * Dataplane DatasourceTestRun layout (multi- or single-datasource).
252
+ * @param {Object} results
253
+ * @param {boolean} verbose
254
+ * @param {Object} opts
255
+ * @param {boolean|string} [opts.debug]
256
+ * @param {'integration'|'e2e'} [opts.runType]
257
+ */
258
+ function displayServerDatasourceTestRunResults(results, verbose, opts = {}) {
259
+ const runType = opts.runType === 'e2e' ? 'e2e' : 'integration';
260
+
261
+ if (isSingleUnskippedEnvelopeRun(results)) {
262
+ const row = results.datasourceResults[0];
263
+ logEnvelopeForInteractiveCli(row.datasourceTestRun, {
264
+ json: false,
265
+ summary: false,
266
+ debug: opts.debug,
267
+ requestedCapabilityKey: opts.requestedCapabilityKey
268
+ });
269
+ return;
212
270
  }
213
271
 
214
- if (verbose) {
215
- displayVerboseIntegrationDetails(dsResult);
272
+ const agg = deriveAggregateServerStatus(results);
273
+ logServerDatasourceTestRunHeader(results, runType, agg);
274
+
275
+ if (results.datasourceResults.length === 0) {
276
+ logger.log('');
277
+ logger.log(chalk.yellow('No datasources tested'));
278
+ logger.log('');
279
+ return;
280
+ }
281
+
282
+ for (const dsResult of results.datasourceResults) {
283
+ renderOneServerDatasourceRow(dsResult, verbose, opts);
284
+ logger.log('');
285
+ logger.log(chalk.gray(SEP));
216
286
  }
287
+
288
+ logServerDatasourceTestRunFooter(results.success, agg);
217
289
  }
218
290
 
219
291
  /**
220
- * Displays formatted integration test results
292
+ * Displays formatted integration / E2E test results (legacy or DatasourceTestRun TTY).
221
293
  * @param {Object} results - Integration test results
222
294
  * @param {boolean} verbose - Show detailed output
295
+ * @param {Object} [displayOpts]
296
+ * @param {boolean|string} [displayOpts.debug] - Debug appendix for each envelope
297
+ * @param {'integration'|'e2e'} [displayOpts.runType]
298
+ * @param {string} [displayOpts.requestedCapabilityKey]
223
299
  */
224
- function displayIntegrationTestResults(results, verbose = false) {
225
- logger.log(chalk.blue('\nšŸ“Š Integration Test Results\n'));
226
- logger.log(chalk.blue(`System: ${results.systemKey}`));
300
+ function displayIntegrationTestResults(results, verbose = false, displayOpts = {}) {
301
+ if (integrationResultsHaveEnvelope(results)) {
302
+ displayServerDatasourceTestRunResults(results, verbose, displayOpts);
303
+ return;
304
+ }
305
+
306
+ const agg = deriveAggregateLegacyIntegrationStatus(results);
307
+ logger.log('');
308
+ logger.log(sectionTitle('Integration test results'));
309
+ logger.log('');
310
+ logger.log(headerKeyValue('System:', results.systemKey));
311
+ logger.log(headerKeyValue('Run:', 'test-integration (pipeline)'));
312
+ logger.log(formatStatusKeyValue(agg, statusGlyph(agg)));
313
+ logger.log('');
314
+ logger.log(chalk.gray(SEP));
227
315
 
228
316
  if (results.datasourceResults.length === 0) {
317
+ logger.log('');
229
318
  logger.log(chalk.yellow('No datasources tested'));
230
319
  return;
231
320
  }
232
321
 
322
+ logger.log('');
233
323
  for (const dsResult of results.datasourceResults) {
234
324
  displayDatasourceIntegrationResult(dsResult, verbose);
235
325
  }
236
326
 
237
- if (results.success) {
238
- logger.log(chalk.green('\nāœ… All integration tests passed!'));
239
- } else {
240
- logger.log(chalk.red('\nāŒ Some integration tests failed'));
241
- }
327
+ logger.log(
328
+ integrationFooterLine(
329
+ results.success,
330
+ agg,
331
+ 'All integration tests passed.',
332
+ 'Integration tests completed with warnings.',
333
+ 'Some integration tests failed.'
334
+ )
335
+ );
242
336
  }
243
337
 
244
338
  /**
@@ -256,7 +350,9 @@ function displayIntegrationTestResults(results, verbose = false) {
256
350
  */
257
351
  /* eslint-disable max-statements,complexity -- Step iteration and status display */
258
352
  function displayE2EResults(data, verbose = false) {
259
- logger.log(chalk.blue('\nšŸ“Š E2E Test Results\n'));
353
+ logger.log('');
354
+ logger.log(sectionTitle('E2E test results'));
355
+ logger.log('');
260
356
  if (data.status) {
261
357
  const statusLabel = data.status === 'running'
262
358
  ? chalk.yellow('running')
@@ -265,12 +361,12 @@ function displayE2EResults(data, verbose = false) {
265
361
  : data.status === 'failed'
266
362
  ? chalk.red('failed')
267
363
  : data.status;
268
- logger.log(`Status: ${statusLabel}`);
364
+ logger.log(`${chalk.gray('Status:')} ${statusLabel}`);
269
365
  }
270
366
  const steps = data.steps || data.completedActions || [];
271
367
  if (steps.length === 0) {
272
368
  if (data.success === false) {
273
- logger.log(chalk.red('āœ— E2E test failed'));
369
+ logger.log(formatBlockingError('E2E test failed.'));
274
370
  if (data.error) logger.log(chalk.red(` Error: ${data.error}`));
275
371
  } else if (data.status === 'running') {
276
372
  logger.log(chalk.gray(' No steps completed yet'));
@@ -286,7 +382,7 @@ function displayE2EResults(data, verbose = false) {
286
382
  for (const step of steps) {
287
383
  const name = step.name || step.step || 'unknown';
288
384
  const ok = step.success !== false && !step.error;
289
- logger.log(` ${ok ? chalk.green('āœ“') : chalk.red('āœ—')} ${name}`);
385
+ logger.log(` ${ok ? successGlyph() : failureGlyph()} ${chalk.white(name)}`);
290
386
  if (!ok && (step.error || step.message)) logger.log(chalk.red(` ${step.error || step.message}`));
291
387
  if (verbose && step.message && ok) logger.log(chalk.gray(` ${step.message}`));
292
388
  if (verbose && ok && (name === 'sync' || step.step === 'sync') && step.evidence && step.evidence.jobs) {
@@ -308,7 +404,9 @@ function displayE2EResults(data, verbose = false) {
308
404
  return;
309
405
  }
310
406
  const allPassed = steps.every(s => s.success !== false && !s.error);
311
- logger.log(allPassed ? chalk.green('\nāœ… E2E test passed!') : chalk.red('\nāŒ E2E test failed'));
407
+ logger.log(
408
+ allPassed ? formatSuccessParagraph('E2E test passed.') : `\n${formatBlockingError('E2E test failed.')}`
409
+ );
312
410
  }
313
411
 
314
412
  /**