@aifabrix/builder 2.42.1 → 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 (392) hide show
  1. package/.cursor/rules/anchor-docs.mdc +15 -0
  2. package/README.md +2 -2
  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 +157 -0
  7. package/integration/{hubspot → hubspot-test}/application.json +6 -6
  8. package/integration/{hubspot → hubspot-test}/create-hubspot.js +10 -10
  9. package/integration/hubspot-test/env.template +4 -0
  10. package/integration/hubspot-test/hubspot-test-datasource-company.json +138 -0
  11. package/integration/hubspot-test/hubspot-test-datasource-contact.json +146 -0
  12. package/integration/hubspot-test/hubspot-test-datasource-deal.json +146 -0
  13. package/integration/hubspot-test/hubspot-test-datasource-users.json +76 -0
  14. package/integration/{hubspot/hubspot-deploy.json → hubspot-test/hubspot-test-deploy.json} +201 -24
  15. package/integration/{hubspot/hubspot-system.json → hubspot-test/hubspot-test-system.json} +8 -7
  16. package/integration/hubspot-test/rbac.json +166 -0
  17. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-hubspot-credential-real.yaml +3 -3
  18. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-hubspot-env-vars.yaml +2 -2
  19. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-add-datasource.yaml +1 -1
  20. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-credential-create.yaml +1 -1
  21. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-credential-select.yaml +1 -1
  22. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-known-platform.yaml +1 -1
  23. package/integration/hubspot-test/test-artifacts/wizard-invalid-missing-source.yaml +2 -0
  24. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-mode.yaml +1 -1
  25. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-openapi-file.yaml +1 -1
  26. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-openapi-url.yaml +1 -1
  27. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-source.yaml +1 -1
  28. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-dimension-array-test.yaml +1 -1
  29. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-key-test.yaml +5 -0
  30. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-path-test.yaml +5 -0
  31. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-dimension-test.yaml +1 -1
  32. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-rbac-test.yaml +1 -1
  33. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-rbac-yaml-test.yaml +1 -1
  34. package/integration/{hubspot → hubspot-test}/test-dataplane-down-tests.js +1 -7
  35. package/integration/{hubspot → hubspot-test}/test-dataplane-down.js +3 -3
  36. package/integration/{hubspot → hubspot-test}/test.js +137 -102
  37. package/integration/{hubspot → hubspot-test}/wizard-hubspot-e2e.yaml +2 -2
  38. package/integration/{hubspot → hubspot-test}/wizard-hubspot-platform.yaml +1 -1
  39. package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
  40. package/integration/roundtrip-test-local/README.md +144 -0
  41. package/integration/roundtrip-test-local/application.yaml +13 -0
  42. package/integration/roundtrip-test-local/env.template +15 -0
  43. package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
  44. package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
  45. package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
  46. package/integration/roundtrip-test-local2/README.md +144 -0
  47. package/integration/roundtrip-test-local2/application.yaml +13 -0
  48. package/integration/roundtrip-test-local2/env.template +15 -0
  49. package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
  50. package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
  51. package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
  52. package/integration/test/wizard.yaml +8 -0
  53. package/jest.config.default.js +10 -0
  54. package/jest.config.integration.fixtures.js +22 -0
  55. package/jest.config.integration.js +21 -18
  56. package/jest.config.isolated.js +10 -0
  57. package/jest.projects.js +288 -0
  58. package/lib/api/datasources-core.api.js +3 -3
  59. package/lib/api/dev-mtls-request.js +110 -0
  60. package/lib/api/dev-server-https.js +145 -0
  61. package/lib/api/dev.api.js +133 -144
  62. package/lib/api/index.js +0 -1
  63. package/lib/api/pipeline.api.js +67 -20
  64. package/lib/api/service-users.api.js +111 -2
  65. package/lib/api/types/dev.types.js +4 -3
  66. package/lib/api/types/pipeline.types.js +8 -5
  67. package/lib/api/types/service-users.types.js +41 -0
  68. package/lib/api/types/validation-run.types.js +56 -0
  69. package/lib/api/validation-run.api.js +99 -0
  70. package/lib/api/validation-runner.js +99 -0
  71. package/lib/app/config.js +1 -1
  72. package/lib/app/deploy-status-display.js +2 -2
  73. package/lib/app/deploy.js +7 -6
  74. package/lib/app/display.js +2 -1
  75. package/lib/app/dockerfile.js +3 -2
  76. package/lib/app/down.js +2 -1
  77. package/lib/app/helpers.js +6 -5
  78. package/lib/app/index.js +27 -8
  79. package/lib/app/list.js +7 -6
  80. package/lib/app/push.js +4 -3
  81. package/lib/app/register.js +19 -8
  82. package/lib/app/rotate-secret.js +17 -13
  83. package/lib/app/run-container-start.js +184 -0
  84. package/lib/app/run-docker-fallback.js +108 -0
  85. package/lib/app/run-env-compose.js +30 -42
  86. package/lib/app/run-helpers.js +49 -126
  87. package/lib/app/run-infra-requirements.js +30 -0
  88. package/lib/app/run-resolve-image.js +21 -0
  89. package/lib/app/run.js +74 -21
  90. package/lib/app/show-display.js +1 -1
  91. package/lib/app/show.js +1 -1
  92. package/lib/build/index.js +13 -10
  93. package/lib/cli/index.js +2 -0
  94. package/lib/cli/setup-app.help.js +67 -0
  95. package/lib/cli/setup-app.js +59 -123
  96. package/lib/cli/setup-app.test-commands.js +179 -0
  97. package/lib/cli/setup-auth.js +36 -14
  98. package/lib/cli/setup-credential-deployment.js +22 -8
  99. package/lib/cli/setup-dev-path-commands.js +124 -0
  100. package/lib/cli/setup-dev.js +190 -103
  101. package/lib/cli/setup-environment.js +11 -20
  102. package/lib/cli/setup-external-system.js +62 -22
  103. package/lib/cli/setup-infra.js +139 -47
  104. package/lib/cli/setup-parameters.js +32 -0
  105. package/lib/cli/setup-secrets.js +147 -10
  106. package/lib/cli/setup-service-user.js +146 -20
  107. package/lib/cli/setup-utility.js +47 -19
  108. package/lib/commands/app-down.js +5 -7
  109. package/lib/commands/app-install.js +14 -7
  110. package/lib/commands/app-logs.js +13 -10
  111. package/lib/commands/app-shell.js +4 -1
  112. package/lib/commands/app-test.js +25 -19
  113. package/lib/commands/app.js +22 -10
  114. package/lib/commands/auth-config.js +10 -14
  115. package/lib/commands/auth-status.js +4 -3
  116. package/lib/commands/credential-env.js +4 -3
  117. package/lib/commands/credential-list.js +5 -4
  118. package/lib/commands/credential-push.js +4 -3
  119. package/lib/commands/datasource-unified-test-cli.js +495 -0
  120. package/lib/commands/datasource-unified-test-cli.options.js +149 -0
  121. package/lib/commands/datasource-validation-cli.js +129 -0
  122. package/lib/commands/datasource.js +123 -71
  123. package/lib/commands/deployment-list.js +6 -5
  124. package/lib/commands/dev-cli-handlers.js +122 -18
  125. package/lib/commands/dev-down.js +4 -3
  126. package/lib/commands/dev-init.js +231 -116
  127. package/lib/commands/dev-show-display.js +473 -0
  128. package/lib/commands/login-credentials.js +3 -2
  129. package/lib/commands/login-device.js +4 -3
  130. package/lib/commands/login.js +5 -4
  131. package/lib/commands/logout.js +8 -7
  132. package/lib/commands/parameters-validate.js +54 -0
  133. package/lib/commands/repair-datasource.js +314 -68
  134. package/lib/commands/repair-env-template.js +16 -10
  135. package/lib/commands/repair-rbac.js +25 -19
  136. package/lib/commands/repair.js +116 -32
  137. package/lib/commands/secrets-list.js +23 -12
  138. package/lib/commands/secrets-remove-all.js +220 -0
  139. package/lib/commands/secrets-remove.js +22 -13
  140. package/lib/commands/secrets-set.js +21 -12
  141. package/lib/commands/secrets-validate.js +20 -7
  142. package/lib/commands/secure.js +10 -9
  143. package/lib/commands/service-user.js +243 -13
  144. package/lib/commands/test-e2e-external.js +27 -1
  145. package/lib/commands/up-common.js +28 -2
  146. package/lib/commands/up-dataplane.js +31 -18
  147. package/lib/commands/up-miso.js +19 -29
  148. package/lib/commands/upload.js +138 -39
  149. package/lib/commands/wizard-core-helpers.js +1 -1
  150. package/lib/commands/wizard-dataplane.js +4 -3
  151. package/lib/commands/wizard-helpers.js +3 -3
  152. package/lib/commands/wizard.js +2 -2
  153. package/lib/core/admin-secrets.js +16 -5
  154. package/lib/core/audit-logger.js +12 -4
  155. package/lib/core/config-attach-extensions.js +46 -0
  156. package/lib/core/config-runtime-paths.js +29 -0
  157. package/lib/core/config.js +59 -58
  158. package/lib/core/diff.js +3 -2
  159. package/lib/core/ensure-encryption-key.js +2 -4
  160. package/lib/core/secrets-ensure-infra.js +77 -0
  161. package/lib/core/secrets-ensure.js +120 -64
  162. package/lib/core/secrets-env-write.js +35 -7
  163. package/lib/core/secrets-infra-placeholder-sync.js +61 -0
  164. package/lib/core/secrets.js +228 -42
  165. package/lib/core/templates-env.js +4 -3
  166. package/lib/core/templates.js +1 -1
  167. package/lib/datasource/abac-validator.js +148 -0
  168. package/lib/datasource/deploy.js +75 -53
  169. package/lib/datasource/field-reference-validator.js +77 -36
  170. package/lib/datasource/integration-context.js +63 -0
  171. package/lib/datasource/list.js +8 -7
  172. package/lib/datasource/log-viewer.js +252 -0
  173. package/lib/datasource/resolve-app.js +109 -0
  174. package/lib/datasource/test-e2e.js +95 -155
  175. package/lib/datasource/test-integration.js +121 -109
  176. package/lib/datasource/unified-validation-run-body.js +65 -0
  177. package/lib/datasource/unified-validation-run-post.js +23 -0
  178. package/lib/datasource/unified-validation-run-resolve.js +43 -0
  179. package/lib/datasource/unified-validation-run.js +92 -0
  180. package/lib/datasource/validate.js +162 -15
  181. package/lib/deployment/deployer.js +4 -3
  182. package/lib/deployment/environment.js +7 -6
  183. package/lib/deployment/push.js +17 -8
  184. package/lib/external-system/delete.js +4 -3
  185. package/lib/external-system/deploy.js +131 -53
  186. package/lib/external-system/download-helpers.js +1 -1
  187. package/lib/external-system/download.js +7 -6
  188. package/lib/external-system/generator.js +104 -14
  189. package/lib/external-system/integration-test-dispatch.js +26 -0
  190. package/lib/external-system/test-execution.js +5 -1
  191. package/lib/external-system/test-helpers.js +0 -4
  192. package/lib/external-system/test-system-level-helpers.js +110 -0
  193. package/lib/external-system/test-system-level.js +83 -44
  194. package/lib/external-system/test.js +59 -8
  195. package/lib/generator/builders.js +23 -11
  196. package/lib/generator/deploy-manifest-azure-kv.js +81 -0
  197. package/lib/generator/external-controller-manifest.js +3 -3
  198. package/lib/generator/external.js +23 -11
  199. package/lib/generator/helpers.js +71 -12
  200. package/lib/generator/index.js +8 -4
  201. package/lib/generator/split-readme.js +12 -7
  202. package/lib/generator/split-variables.js +2 -1
  203. package/lib/generator/split.js +46 -11
  204. package/lib/generator/wizard-readme.js +3 -3
  205. package/lib/generator/wizard.js +16 -13
  206. package/lib/infrastructure/compose.js +60 -6
  207. package/lib/infrastructure/helpers.js +238 -51
  208. package/lib/infrastructure/index.js +64 -37
  209. package/lib/infrastructure/services.js +21 -15
  210. package/lib/internal/fs-real-sync.js +104 -0
  211. package/lib/internal/node-fs.js +98 -0
  212. package/lib/parameters/database-secret-values.js +173 -0
  213. package/lib/parameters/infra-kv-discovery.js +121 -0
  214. package/lib/parameters/infra-parameter-catalog.js +458 -0
  215. package/lib/parameters/infra-parameter-validate.js +64 -0
  216. package/lib/schema/application-schema.json +37 -17
  217. package/lib/schema/datasource-test-run.schema.json +493 -0
  218. package/lib/schema/deployment-rules.yaml +102 -63
  219. package/lib/schema/external-datasource.schema.json +1201 -433
  220. package/lib/schema/external-system.schema.json +181 -5
  221. package/lib/schema/flag-map-validation-run.json +31 -0
  222. package/lib/schema/infra-parameter.schema.json +106 -0
  223. package/lib/schema/infra.parameter.yaml +421 -0
  224. package/lib/schema/type/credential-auth-templates.json +40 -0
  225. package/lib/schema/type/document-storage.json +213 -0
  226. package/lib/schema/type/message-service.json +123 -0
  227. package/lib/schema/type/vector-store.json +88 -0
  228. package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
  229. package/lib/utils/api-error-handler.js +2 -2
  230. package/lib/utils/api.js +49 -14
  231. package/lib/utils/app-config-resolver.js +23 -1
  232. package/lib/utils/app-register-api.js +3 -2
  233. package/lib/utils/app-register-auth.js +1 -1
  234. package/lib/utils/app-register-config.js +4 -4
  235. package/lib/utils/app-register-display.js +3 -2
  236. package/lib/utils/app-register-validator.js +3 -2
  237. package/lib/utils/app-run-containers.js +26 -22
  238. package/lib/utils/app-scoped-config.js +31 -0
  239. package/lib/utils/app-service-env-from-builder.js +164 -0
  240. package/lib/utils/build-copy.js +1 -1
  241. package/lib/utils/build-helpers.js +20 -20
  242. package/lib/utils/build-resolve-image.js +165 -0
  243. package/lib/utils/cli-layout-chalk.js +8 -0
  244. package/lib/utils/cli-test-layout-chalk.js +267 -0
  245. package/lib/utils/cli-utils.js +88 -11
  246. package/lib/utils/compose-db-passwords.js +138 -0
  247. package/lib/utils/compose-generate-docker-compose.js +216 -0
  248. package/lib/utils/compose-generator.js +197 -291
  249. package/lib/utils/compose-miso-env.js +18 -0
  250. package/lib/utils/compose-traefik-ingress-base.js +158 -0
  251. package/lib/utils/config-paths.js +209 -6
  252. package/lib/utils/config-scoped-resources-preference.js +41 -0
  253. package/lib/utils/controller-deployment-outcome.js +68 -0
  254. package/lib/utils/credential-display.js +2 -2
  255. package/lib/utils/credential-secrets-env.js +16 -1
  256. package/lib/utils/dataplane-pipeline-warning.js +4 -3
  257. package/lib/utils/datasource-test-run-capability-scope.js +43 -0
  258. package/lib/utils/datasource-test-run-debug-display.js +137 -0
  259. package/lib/utils/datasource-test-run-debug-slice.js +93 -0
  260. package/lib/utils/datasource-test-run-display.js +442 -0
  261. package/lib/utils/datasource-test-run-exit.js +58 -0
  262. package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
  263. package/lib/utils/datasource-test-run-report-version.js +51 -0
  264. package/lib/utils/datasource-test-run-schema-sync.js +59 -0
  265. package/lib/utils/datasource-test-run-tty-log.js +81 -0
  266. package/lib/utils/datasource-validation-watch.js +266 -0
  267. package/lib/utils/declarative-url-ports.js +47 -0
  268. package/lib/utils/derive-env-key-from-client-id.js +41 -0
  269. package/lib/utils/dev-ca-install.js +185 -23
  270. package/lib/utils/dev-cert-helper.js +266 -17
  271. package/lib/utils/dev-hosts-helper.js +307 -0
  272. package/lib/utils/dev-init-cert-hints.js +37 -0
  273. package/lib/utils/dev-init-health-messages.js +52 -0
  274. package/lib/utils/dev-init-resolve.js +86 -0
  275. package/lib/utils/dev-init-ssh-merge.js +65 -0
  276. package/lib/utils/dev-ssh-config-helper.js +196 -0
  277. package/lib/utils/dev-user-groups.js +93 -0
  278. package/lib/utils/docker-build.js +42 -17
  279. package/lib/utils/docker-exec.js +28 -0
  280. package/lib/utils/docker-manifest-public-port.js +116 -0
  281. package/lib/utils/docker-not-running-hint.js +52 -0
  282. package/lib/utils/docker.js +98 -11
  283. package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
  284. package/lib/utils/env-config-loader.js +10 -91
  285. package/lib/utils/env-copy.js +19 -10
  286. package/lib/utils/env-map.js +42 -11
  287. package/lib/utils/env-template.js +2 -2
  288. package/lib/utils/environment-scoped-resources.js +144 -0
  289. package/lib/utils/error-formatter.js +125 -9
  290. package/lib/utils/error-formatters/http-status-errors.js +6 -5
  291. package/lib/utils/error-formatters/network-errors.js +2 -1
  292. package/lib/utils/error-formatters/permission-errors.js +2 -1
  293. package/lib/utils/error-formatters/validation-errors.js +2 -1
  294. package/lib/utils/external-env-template.js +180 -0
  295. package/lib/utils/external-readme.js +8 -1
  296. package/lib/utils/external-system-display.js +277 -136
  297. package/lib/utils/external-system-local-test-tty.js +389 -0
  298. package/lib/utils/external-system-readiness-core.js +377 -0
  299. package/lib/utils/external-system-readiness-deploy-display.js +270 -0
  300. package/lib/utils/external-system-readiness-display-internals.js +150 -0
  301. package/lib/utils/external-system-readiness-display.js +186 -0
  302. package/lib/utils/external-system-test-helpers.js +24 -6
  303. package/lib/utils/external-system-validators.js +32 -14
  304. package/lib/utils/health-check-url.js +119 -0
  305. package/lib/utils/health-check.js +59 -25
  306. package/lib/utils/help-builder.js +14 -13
  307. package/lib/utils/image-version.js +4 -8
  308. package/lib/utils/infra-containers.js +4 -7
  309. package/lib/utils/infra-env-defaults.js +162 -0
  310. package/lib/utils/infra-status-display.js +167 -0
  311. package/lib/utils/infra-status.js +16 -8
  312. package/lib/utils/local-secrets.js +29 -7
  313. package/lib/utils/paths.js +136 -48
  314. package/lib/utils/port-resolver.js +10 -23
  315. package/lib/utils/redis-env-scope.js +62 -0
  316. package/lib/utils/register-aifabrix-shell-env.js +204 -0
  317. package/lib/utils/remote-builder-validation.js +99 -0
  318. package/lib/utils/remote-dev-auth.js +117 -21
  319. package/lib/utils/remote-docker-env.js +67 -15
  320. package/lib/utils/remote-secrets-loader.js +13 -4
  321. package/lib/utils/resolve-docker-image-ref.js +124 -0
  322. package/lib/utils/schema-loader.js +22 -9
  323. package/lib/utils/secrets-bash-kv.js +25 -0
  324. package/lib/utils/secrets-generator.js +171 -51
  325. package/lib/utils/secrets-helpers.js +70 -59
  326. package/lib/utils/secrets-kv-scope.js +60 -0
  327. package/lib/utils/secrets-utils.js +35 -37
  328. package/lib/utils/secrets-validation.js +3 -1
  329. package/lib/utils/secrets-yaml-preserve.js +109 -0
  330. package/lib/utils/secure-file-permissions.js +91 -0
  331. package/lib/utils/ssh-key-helper.js +4 -2
  332. package/lib/utils/template-helpers.js +2 -2
  333. package/lib/utils/test-log-writer.js +3 -3
  334. package/lib/utils/token-manager.js +37 -5
  335. package/lib/utils/url-declarative-public-base.js +188 -0
  336. package/lib/utils/url-declarative-resolve-build.js +493 -0
  337. package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
  338. package/lib/utils/url-declarative-resolve.js +220 -0
  339. package/lib/utils/url-declarative-token-parse.js +74 -0
  340. package/lib/utils/url-declarative-url-flags.js +50 -0
  341. package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
  342. package/lib/utils/url-public-path-prefix.js +34 -0
  343. package/lib/utils/urls-local-registry.js +220 -0
  344. package/lib/utils/validation-report-tty-kit.js +77 -0
  345. package/lib/utils/validation-run-poll.js +89 -0
  346. package/lib/utils/validation-run-post-retry.js +73 -0
  347. package/lib/utils/validation-run-request.js +98 -0
  348. package/lib/utils/variable-transformer.js +21 -4
  349. package/lib/utils/yaml-preserve.js +78 -1
  350. package/lib/validation/datasource-warnings.js +56 -0
  351. package/lib/validation/env-template-auth.js +50 -2
  352. package/lib/validation/external-manifest-validator.js +35 -7
  353. package/lib/validation/validate-display.js +37 -31
  354. package/lib/validation/validate.js +9 -10
  355. package/lib/validation/validator-unresolved-placeholders.js +98 -0
  356. package/lib/validation/validator.js +32 -78
  357. package/lib/validation/wizard-config-validator.js +2 -1
  358. package/package.json +11 -3
  359. package/scripts/check-datasource-test-run-schema-sync.js +34 -0
  360. package/scripts/diagnose-cli.js +150 -0
  361. package/scripts/install-local.js +304 -55
  362. package/templates/README.md +15 -2
  363. package/templates/applications/dataplane/application.yaml +52 -2
  364. package/templates/applications/dataplane/env.template +80 -18
  365. package/templates/applications/dataplane/rbac.yaml +8 -0
  366. package/templates/applications/keycloak/application.yaml +9 -1
  367. package/templates/applications/keycloak/env.template +15 -6
  368. package/templates/applications/miso-controller/application.yaml +10 -2
  369. package/templates/applications/miso-controller/env.template +55 -14
  370. package/templates/applications/miso-controller/rbac.yaml +5 -0
  371. package/templates/external-system/README.md.hbs +20 -7
  372. package/templates/external-system/deploy.js.hbs +5 -5
  373. package/templates/external-system/env.template.hbs +22 -0
  374. package/templates/external-system/external-datasource.yaml.hbs +197 -118
  375. package/templates/infra/compose.yaml.hbs +20 -4
  376. package/templates/python/docker-compose.hbs +16 -0
  377. package/templates/typescript/docker-compose.hbs +16 -0
  378. package/integration/hubspot/README.md +0 -102
  379. package/integration/hubspot/env.template +0 -4
  380. package/integration/hubspot/hubspot-datasource-company.json +0 -541
  381. package/integration/hubspot/hubspot-datasource-contact.json +0 -639
  382. package/integration/hubspot/hubspot-datasource-deal.json +0 -588
  383. package/integration/hubspot/hubspot-datasource-users.json +0 -116
  384. package/integration/hubspot/test-artifacts/wizard-invalid-missing-source.yaml +0 -2
  385. package/integration/hubspot/test-artifacts/wizard-valid-for-dimension-key-test.yaml +0 -5
  386. package/integration/hubspot/test-artifacts/wizard-valid-for-dimension-path-test.yaml +0 -5
  387. package/lib/api/external-test.api.js +0 -111
  388. package/lib/schema/env-config.yaml +0 -43
  389. /package/integration/{hubspot → hubspot-test}/companies.json +0 -0
  390. /package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-app-name.yaml +0 -0
  391. /package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-missing-app.yaml +0 -0
  392. /package/integration/{hubspot → hubspot-test}/test-dataplane-down-helpers.js +0 -0
@@ -17,6 +17,16 @@ const { publishDatasourceViaPipeline } = require('../api/pipeline.api');
17
17
  const { formatApiError } = require('../utils/api-error-handler');
18
18
  const logger = require('../utils/logger');
19
19
  const { logDataplanePipelineWarning } = require('../utils/dataplane-pipeline-warning');
20
+ const {
21
+ sectionTitle,
22
+ headerKeyValue,
23
+ metadata,
24
+ infoLine,
25
+ formatStatusKeyValue,
26
+ formatBlockingError,
27
+ successGlyph,
28
+ failureGlyph
29
+ } = require('../utils/cli-test-layout-chalk');
20
30
  const {
21
31
  buildResolvedEnvMapForIntegration,
22
32
  resolveConfigurationValues
@@ -64,41 +74,41 @@ async function getDataplaneUrl(controllerUrl, appKey, environment, authConfig) {
64
74
  }
65
75
 
66
76
  /**
67
- * Validate deployment inputs
68
- * @param {string} appKey - Application key
69
- * @param {string} filePath - File path
70
- * @param {Object} options - Options
77
+ * Validate deploy CLI input (file path or datasource key, same rules as `datasource validate`).
78
+ * @param {string} fileOrKey - Path to JSON or datasource `key` under integration/<app>/
71
79
  * @throws {Error} If validation fails
72
80
  */
73
- function validateDeploymentInputs(appKey, filePath) {
74
- if (!appKey || typeof appKey !== 'string') {
75
- throw new Error('Application key is required');
76
- }
77
- if (!filePath || typeof filePath !== 'string') {
78
- throw new Error('File path is required');
81
+ function validateDeployFileOrKeyInput(fileOrKey) {
82
+ if (!fileOrKey || typeof fileOrKey !== 'string' || !fileOrKey.trim()) {
83
+ throw new Error('File path or datasource key is required');
79
84
  }
80
85
  }
81
86
 
82
87
  /**
83
- * Validate and load datasource file
88
+ * Validate and load datasource file (path or datasource key, resolved like `datasource validate`).
84
89
  * @async
85
- * @param {string} filePath - Path to datasource file
90
+ * @param {string} filePathOrKey - Path to datasource JSON or datasource `key`
86
91
  * @returns {Promise<Object>} Datasource configuration
87
92
  * @throws {Error} If validation or loading fails
88
93
  */
89
- async function validateAndLoadDatasourceFile(filePath) {
90
- logger.log(chalk.blue('🔍 Validating datasource file...'));
91
- const validation = await validateDatasourceFile(filePath);
94
+ async function validateAndLoadDatasourceFile(filePathOrKey) {
95
+ logger.log(infoLine(' Validating datasource file'));
96
+ const validation = await validateDatasourceFile(filePathOrKey);
92
97
  if (!validation.valid) {
93
- logger.error(chalk.red('❌ Datasource validation failed:'));
98
+ logger.log('');
99
+ logger.error(formatBlockingError('Datasource validation failed'));
94
100
  validation.errors.forEach(error => {
95
- logger.error(chalk.red(` • ${error}`));
101
+ logger.error(formatBlockingError(error));
96
102
  });
97
103
  throw new Error('Datasource file validation failed');
98
104
  }
99
- logger.log(chalk.green('✓ Datasource file is valid'));
100
105
 
101
- const content = fs.readFileSync(filePath, 'utf8');
106
+ const resolvedPath = validation.resolvedPath;
107
+ logger.log(headerKeyValue('File:', resolvedPath));
108
+ logger.log(`${successGlyph()} ${chalk.white('Datasource file is valid.')}`);
109
+ logger.log('');
110
+
111
+ const content = fs.readFileSync(resolvedPath, 'utf8');
102
112
  try {
103
113
  return JSON.parse(content);
104
114
  } catch (error) {
@@ -116,28 +126,28 @@ async function validateAndLoadDatasourceFile(filePath) {
116
126
  */
117
127
  async function setupDeploymentAuth(controllerUrl, environment, appKey) {
118
128
  const { resolveDataplaneUrl } = require('../utils/dataplane-resolver');
119
- logger.log(chalk.blue('🔐 Getting authentication...'));
129
+ logger.log(infoLine(' Resolving authentication'));
120
130
  const authConfig = await getDeploymentAuth(controllerUrl, environment, appKey);
121
- logger.log(chalk.green('Authentication successful'));
131
+ logger.log(`${successGlyph()} ${chalk.white('Authentication ready')}`);
122
132
 
123
- logger.log(chalk.blue('🌐 Resolving dataplane URL...'));
133
+ logger.log(infoLine(' Resolving dataplane URL'));
124
134
  let dataplaneUrl;
125
135
  try {
126
136
  dataplaneUrl = await resolveDataplaneUrl(controllerUrl, environment, authConfig);
127
- logger.log(chalk.green(`✓ Dataplane URL: ${dataplaneUrl}`));
137
+ logger.log(`${metadata('Dataplane:')} ${chalk.cyan(dataplaneUrl)}`);
128
138
  } catch (error) {
129
- logger.error(chalk.red('Failed to resolve dataplane URL:'), error.message);
130
- logger.error(chalk.gray('\nThe dataplane URL is automatically discovered from the controller.'));
131
- logger.error(chalk.gray('If discovery fails, ensure you are logged in and the controller is accessible:'));
132
- logger.error(chalk.gray(' aifabrix login'));
139
+ logger.error(`${failureGlyph()} ${chalk.red('Failed to resolve dataplane URL:')} ${chalk.red(error.message)}`);
140
+ logger.error(metadata('The dataplane URL is automatically discovered from the controller.'));
141
+ logger.error(metadata('If discovery fails, ensure you are logged in and the controller is accessible:'));
142
+ logger.error(metadata('aifabrix login'));
133
143
  throw error;
134
144
  }
135
145
 
136
146
  // Validate dataplane URL
137
147
  if (!dataplaneUrl || !dataplaneUrl.trim()) {
138
- logger.error(chalk.red('Dataplane URL is empty.'));
139
- logger.error(chalk.gray('The dataplane URL could not be discovered from the controller.'));
140
- logger.error(chalk.gray('Ensure the dataplane service is registered in the controller.'));
148
+ logger.error(`${failureGlyph()} ${chalk.red('Dataplane URL is empty.')}`);
149
+ logger.error(metadata('The dataplane URL could not be discovered from the controller.'));
150
+ logger.error(metadata('Ensure the dataplane service is registered in the controller.'));
141
151
  throw new Error('Dataplane URL is empty');
142
152
  }
143
153
 
@@ -156,30 +166,32 @@ async function setupDeploymentAuth(controllerUrl, environment, appKey) {
156
166
  */
157
167
  async function publishDatasourceToDataplane(dataplaneUrl, systemKey, authConfig, datasourceConfig) {
158
168
  requireBearerForDataplanePipeline(authConfig);
159
- logger.log(chalk.blue('\n🚀 Publishing datasource to dataplane...'));
169
+ logger.log('');
170
+ logger.log(sectionTitle('Publish'));
160
171
  logDataplanePipelineWarning();
161
172
 
162
173
  const publishResponse = await publishDatasourceViaPipeline(dataplaneUrl, systemKey, authConfig, datasourceConfig);
163
174
 
164
175
  if (!publishResponse.success) {
165
176
  const formattedError = publishResponse.formattedError || formatApiError(publishResponse);
166
- logger.error(chalk.red('Publish failed:'));
167
- logger.error(formattedError);
177
+ logger.error(`${failureGlyph()} ${chalk.red('Publish failed:')} ${chalk.red(formattedError)}`);
168
178
 
169
179
  // Show dataplane URL and endpoint information
170
180
  if (publishResponse.errorData && publishResponse.errorData.endpointUrl) {
171
- logger.error(chalk.gray(`\nEndpoint URL: ${publishResponse.errorData.endpointUrl}`));
181
+ logger.error(
182
+ `\n${metadata('Endpoint URL:')} ${chalk.cyan(publishResponse.errorData.endpointUrl)}`
183
+ );
172
184
  } else if (dataplaneUrl) {
173
- logger.error(chalk.gray(`\nDataplane URL: ${dataplaneUrl}`));
174
- logger.error(chalk.gray(`System Key: ${systemKey}`));
185
+ logger.error(`\n${metadata('Dataplane URL:')} ${chalk.cyan(dataplaneUrl)}`);
186
+ logger.error(headerKeyValue('System Key:', systemKey));
175
187
  }
176
188
 
177
- logger.error(chalk.gray('\nFull response for debugging:'));
178
- logger.error(chalk.gray(JSON.stringify(publishResponse, null, 2)));
189
+ logger.error(metadata('\nFull response for debugging:'));
190
+ logger.error(metadata(JSON.stringify(publishResponse, null, 2)));
179
191
  throw new Error(`Dataplane publish failed: ${formattedError}`);
180
192
  }
181
193
 
182
- logger.log(chalk.green('\n✓ Datasource published successfully!'));
194
+ logger.log(`${successGlyph()} ${chalk.white('Configuration published to dataplane.')}`);
183
195
  return publishResponse;
184
196
  }
185
197
 
@@ -190,9 +202,21 @@ async function publishDatasourceToDataplane(dataplaneUrl, systemKey, authConfig,
190
202
  * @param {string} environment - Environment key
191
203
  */
192
204
  function displayDeploymentResults(datasourceConfig, systemKey, environment) {
193
- logger.log(chalk.blue(`\nDatasource: ${datasourceConfig.key || datasourceConfig.displayName}`));
194
- logger.log(chalk.blue(`System: ${systemKey}`));
195
- logger.log(chalk.blue(`Environment: ${environment}`));
205
+ const datasourceLabel = datasourceConfig.key || datasourceConfig.displayName || '(unknown)';
206
+ logger.log('');
207
+ logger.log(sectionTitle('Result'));
208
+ logger.log(headerKeyValue('Datasource:', datasourceLabel));
209
+ logger.log(headerKeyValue('System:', systemKey));
210
+ logger.log(headerKeyValue('Environment:', environment));
211
+ logger.log('');
212
+ logger.log(formatStatusKeyValue('ok', '✔'));
213
+ }
214
+
215
+ function logDatasourceUploadSectionHeader() {
216
+ logger.log('');
217
+ logger.log(sectionTitle('Datasource upload'));
218
+ logger.log(metadata('Publish one datasource JSON to the dataplane'));
219
+ logger.log('');
196
220
  }
197
221
 
198
222
  /**
@@ -201,18 +225,17 @@ function displayDeploymentResults(datasourceConfig, systemKey, environment) {
201
225
  *
202
226
  * @async
203
227
  * @function deployDatasource
204
- * @param {string} appKey - Application key
205
- * @param {string} filePath - Path to datasource JSON file
228
+ * @param {string} fileOrKey - Path to datasource JSON file, or datasource `key` under integration/<app>/ (same resolution as `datasource validate`)
206
229
  * @param {Object} [_options] - Deployment options (reserved)
207
230
  * @returns {Promise<Object>} Deployment result
208
231
  * @throws {Error} If deployment fails
209
232
  */
210
- async function deployDatasource(appKey, filePath, _options) {
233
+ async function deployDatasource(fileOrKey, _options) {
211
234
  const { resolveControllerUrl } = require('../utils/controller-url');
212
235
  const { resolveEnvironment } = require('../core/config');
213
236
  const { displayCommandHeader } = require('../utils/command-header');
214
237
 
215
- validateDeploymentInputs(appKey, filePath);
238
+ validateDeployFileOrKeyInput(fileOrKey);
216
239
 
217
240
  // Resolve controller and environment from config
218
241
  const controllerUrl = await resolveControllerUrl();
@@ -220,13 +243,12 @@ async function deployDatasource(appKey, filePath, _options) {
220
243
 
221
244
  // Display command header
222
245
  displayCommandHeader(controllerUrl, environment);
246
+ logDatasourceUploadSectionHeader();
223
247
 
224
- logger.log(chalk.blue('📋 Deploying datasource...\n'));
225
-
226
- // Validate and load datasource file
227
- const datasourceConfig = await validateAndLoadDatasourceFile(filePath);
248
+ // Validate and load datasource file (resolves key → path like validate)
249
+ const datasourceConfig = await validateAndLoadDatasourceFile(fileOrKey.trim());
228
250
 
229
- // Extract systemKey
251
+ // Extract systemKey (required in JSON; also used as controller app key for external systems)
230
252
  const systemKey = datasourceConfig.systemKey;
231
253
  if (!systemKey) {
232
254
  throw new Error('systemKey is required in datasource configuration');
@@ -237,8 +259,8 @@ async function deployDatasource(appKey, filePath, _options) {
237
259
  resolveConfigurationValues(datasourceConfig.configuration, envMap, secrets, systemKey);
238
260
  }
239
261
 
240
- // Setup authentication and get dataplane URL
241
- const { authConfig, dataplaneUrl } = await setupDeploymentAuth(controllerUrl, environment, appKey);
262
+ // Setup authentication and get dataplane URL (application key matches systemKey for external integrations)
263
+ const { authConfig, dataplaneUrl } = await setupDeploymentAuth(controllerUrl, environment, systemKey);
242
264
 
243
265
  // Publish to dataplane
244
266
  await publishDatasourceToDataplane(dataplaneUrl, systemKey, authConfig, datasourceConfig);
@@ -11,78 +11,119 @@
11
11
  */
12
12
 
13
13
  /**
14
- * Validates that all field references in indexing, validation, and quality
15
- * exist in fieldMappings.attributes. When fieldMappings.attributes is missing
16
- * or empty, returns no errors (skip check, matching dataplane behavior).
14
+ * Set of attribute names plus root dimension keys valid for field references.
15
+ * Used for primaryKey (schema allows dimension keys or attributes) and other paths (attributes only).
17
16
  *
18
- * @function validateFieldReferences
19
- * @param {Object} parsed - Parsed datasource object (after JSON parse)
20
- * @returns {string[]} Array of error messages; empty if no invalid references
21
- *
22
- * @example
23
- * const errors = validateFieldReferences(parsed);
24
- * if (errors.length > 0) {
25
- * errors.forEach(e => console.error(e));
26
- * }
17
+ * @param {Object} parsed - Parsed datasource object
18
+ * @returns {{ attributes: string[], attributesAndDimensions: Set<string> }}
27
19
  */
28
- function validateFieldReferences(parsed) {
29
- const errors = [];
30
- const normalizedAttributes = Object.keys(
31
- parsed?.fieldMappings?.attributes ?? {}
32
- );
20
+ function getNormalizedSets(parsed) {
21
+ const attributes = Object.keys(parsed?.fieldMappings?.attributes ?? {});
22
+ const rootDims = Object.keys(parsed?.dimensions ?? {}).filter(k => {
23
+ const b = parsed.dimensions[k];
24
+ return b && typeof b === 'object';
25
+ });
26
+ const attributesAndDimensions = new Set([...attributes, ...rootDims]);
27
+ return { attributes, attributesAndDimensions };
28
+ }
33
29
 
34
- if (normalizedAttributes.length === 0) {
35
- return [];
36
- }
30
+ /** @param {string[]} errors */
31
+ function checkPrimaryKey(parsed, attributesAndDimensions, errors) {
32
+ const primaryKey = parsed?.primaryKey;
33
+ if (!Array.isArray(primaryKey)) return;
34
+ primaryKey.forEach((field, i) => {
35
+ if (typeof field === 'string' && field !== '' && !attributesAndDimensions.has(field)) {
36
+ errors.push(
37
+ `primaryKey[${i}]: field '${field}' does not exist in fieldMappings.attributes or root dimensions. Each primaryKey value must reference an attribute or dimension key.`
38
+ );
39
+ }
40
+ });
41
+ }
42
+
43
+ /** @param {string[]} errors */
44
+ function checkExposedProfiles(parsed, attrSet, errors) {
45
+ const profiles = parsed?.exposed?.profiles;
46
+ if (!profiles || typeof profiles !== 'object' || Array.isArray(profiles)) return;
47
+ Object.entries(profiles).forEach(([profileName, fields]) => {
48
+ if (!Array.isArray(fields)) return;
49
+ fields.forEach((field, idx) => {
50
+ if (typeof field === 'string' && !attrSet.has(field)) {
51
+ errors.push(
52
+ `exposed.profiles.${profileName}[${idx}]: field '${field}' does not exist in fieldMappings.attributes. Add the attribute or remove the reference.`
53
+ );
54
+ }
55
+ });
56
+ });
57
+ }
37
58
 
38
- // indexing.embedding: array of field names
59
+ /** @param {string[]} errors */
60
+ function checkIndexingAndValidation(parsed, normalizedAttributes, errors) {
39
61
  const embedding = parsed?.indexing?.embedding;
40
62
  if (Array.isArray(embedding)) {
41
63
  embedding.forEach((field, i) => {
42
64
  if (typeof field === 'string' && !normalizedAttributes.includes(field)) {
43
65
  errors.push(
44
- `indexing.embedding[${i}]: field '${field}' does not exist in fieldMappings.attributes`
66
+ `indexing.embedding[${i}]: field '${field}' does not exist in fieldMappings.attributes. Add the attribute or remove the reference.`
45
67
  );
46
68
  }
47
69
  });
48
70
  }
49
-
50
- // indexing.uniqueKey: single field name
51
71
  const uniqueKey = parsed?.indexing?.uniqueKey;
52
- if (typeof uniqueKey === 'string' && uniqueKey !== '') {
53
- if (!normalizedAttributes.includes(uniqueKey)) {
54
- errors.push(
55
- `indexing.uniqueKey: field '${uniqueKey}' does not exist in fieldMappings.attributes`
56
- );
57
- }
72
+ if (typeof uniqueKey === 'string' && uniqueKey !== '' && !normalizedAttributes.includes(uniqueKey)) {
73
+ errors.push(
74
+ `indexing.uniqueKey: field '${uniqueKey}' does not exist in fieldMappings.attributes. Add the attribute or remove the reference.`
75
+ );
58
76
  }
59
-
60
- // validation.repeatingValues[].field
61
77
  const repeatingValues = parsed?.validation?.repeatingValues;
62
78
  if (Array.isArray(repeatingValues)) {
63
79
  repeatingValues.forEach((rule, index) => {
64
80
  const field = rule?.field;
65
81
  if (typeof field === 'string' && !normalizedAttributes.includes(field)) {
66
82
  errors.push(
67
- `validation.repeatingValues[${index}].field: field '${field}' does not exist in fieldMappings.attributes`
83
+ `validation.repeatingValues[${index}].field: field '${field}' does not exist in fieldMappings.attributes. Add the attribute or remove the reference.`
68
84
  );
69
85
  }
70
86
  });
71
87
  }
72
-
73
- // quality.rejectIf[].field
74
88
  const rejectIf = parsed?.quality?.rejectIf;
75
89
  if (Array.isArray(rejectIf)) {
76
90
  rejectIf.forEach((rule, index) => {
77
91
  const field = rule?.field;
78
92
  if (typeof field === 'string' && !normalizedAttributes.includes(field)) {
79
93
  errors.push(
80
- `quality.rejectIf[${index}].field: field '${field}' does not exist in fieldMappings.attributes`
94
+ `quality.rejectIf[${index}].field: field '${field}' does not exist in fieldMappings.attributes. Add the attribute or remove the reference.`
81
95
  );
82
96
  }
83
97
  });
84
98
  }
99
+ }
100
+
101
+ /**
102
+ * Validates that all field references in indexing, validation, quality,
103
+ * primaryKey, and exposed.profiles exist in fieldMappings.attributes (or
104
+ * root dimension keys for primaryKey per schema). When fieldMappings.attributes is
105
+ * missing or empty, returns no errors (skip check, matching dataplane behavior).
106
+ *
107
+ * @function validateFieldReferences
108
+ * @param {Object} parsed - Parsed datasource object (after JSON parse)
109
+ * @returns {string[]} Array of error messages; empty if no invalid references
110
+ *
111
+ * @example
112
+ * const errors = validateFieldReferences(parsed);
113
+ * if (errors.length > 0) {
114
+ * errors.forEach(e => console.error(e));
115
+ * }
116
+ */
117
+ function validateFieldReferences(parsed) {
118
+ const errors = [];
119
+ const { attributes: normalizedAttributes, attributesAndDimensions } = getNormalizedSets(parsed);
120
+ const attrSet = new Set(normalizedAttributes);
121
+
122
+ checkPrimaryKey(parsed, attributesAndDimensions, errors);
123
+ checkExposedProfiles(parsed, attrSet, errors);
124
+ if (normalizedAttributes.length === 0) return errors;
85
125
 
126
+ checkIndexingAndValidation(parsed, normalizedAttributes, errors);
86
127
  return errors;
87
128
  }
88
129
 
@@ -0,0 +1,63 @@
1
+ /**
2
+ * @fileoverview Shared integration app resolution (system key, datasource file lookup).
3
+ * @author AI Fabrix Team
4
+ * @version 2.0.0
5
+ */
6
+
7
+ const path = require('path');
8
+ const fs = require('fs').promises;
9
+ const { getIntegrationPath } = require('../utils/paths');
10
+ const { resolveApplicationConfigPath } = require('../utils/app-config-resolver');
11
+ const { loadConfigFile } = require('../utils/config-format');
12
+
13
+ /**
14
+ * @param {string} appKey - Integration app key
15
+ * @returns {Promise<string>} systemKey
16
+ */
17
+ async function getSystemKeyFromAppKey(appKey) {
18
+ const appPath = getIntegrationPath(appKey);
19
+ const configPath = resolveApplicationConfigPath(appPath);
20
+ const config = loadConfigFile(configPath);
21
+ if (!config.externalIntegration || !config.externalIntegration.systems || config.externalIntegration.systems.length === 0) {
22
+ throw new Error(`No externalIntegration.systems found in ${configPath}`);
23
+ }
24
+ const systemFile = config.externalIntegration.systems[0];
25
+ const systemPath = path.isAbsolute(systemFile)
26
+ ? systemFile
27
+ : path.join(appPath, systemFile);
28
+ const systemContent = await fs.readFile(systemPath, 'utf8');
29
+ const yaml = require('js-yaml');
30
+ const systemConfig = yaml.load(systemContent);
31
+ return systemConfig?.key || path.basename(systemFile, '-system.yaml').replace('-system', '');
32
+ }
33
+
34
+ /**
35
+ * Find a datasource filename by matching the key inside the file.
36
+ * @param {string} appPath
37
+ * @param {string} schemaBasePath
38
+ * @param {string[]} datasourceFiles
39
+ * @param {string} datasourceKey
40
+ * @returns {string|null}
41
+ */
42
+ function findDatasourceFileByKey(appPath, schemaBasePath, datasourceFiles, datasourceKey) {
43
+ const fsSync = require('fs');
44
+ for (const f of datasourceFiles) {
45
+ if (!f || typeof f !== 'string') continue;
46
+ const fullPath = path.isAbsolute(schemaBasePath)
47
+ ? path.join(schemaBasePath, f)
48
+ : path.join(appPath, schemaBasePath, f);
49
+ if (!fsSync.existsSync(fullPath)) continue;
50
+ try {
51
+ const parsed = loadConfigFile(fullPath);
52
+ if (parsed && parsed.key === datasourceKey) return f;
53
+ } catch {
54
+ // skip unreadable or invalid files
55
+ }
56
+ }
57
+ return null;
58
+ }
59
+
60
+ module.exports = {
61
+ getSystemKeyFromAppKey,
62
+ findDatasourceFileByKey
63
+ };
@@ -1,7 +1,8 @@
1
+ const { formatBlockingError } = require('../utils/cli-test-layout-chalk');
1
2
  /**
2
3
  * Datasource List Command
3
4
  *
4
- * Lists datasources from the dataplane (GET /api/v1/external/).
5
+ * Lists datasources from the dataplane (GET /api/v1/external).
5
6
  * Resolves dataplane URL from the controller, then calls the dataplane list API.
6
7
  *
7
8
  * @fileoverview Datasource listing for AI Fabrix Builder
@@ -74,7 +75,7 @@ function extractFromPaginatedFormat(apiResponse) {
74
75
  * @param {Object} apiResponse - API response object
75
76
  */
76
77
  function logInvalidResponseError(apiResponse) {
77
- logger.error(chalk.red('Invalid response: expected data array or items array'));
78
+ logger.error(formatBlockingError('Invalid response: expected data array or items array'));
78
79
  logger.error(chalk.gray('\nAPI response type:'), typeof apiResponse);
79
80
  logger.error(chalk.gray('API response:'), JSON.stringify(apiResponse, null, 2));
80
81
  }
@@ -177,7 +178,7 @@ async function getDeviceTokenFromConfig(config) {
177
178
  */
178
179
  function validateDatasourceListingAuth(token, controllerUrl) {
179
180
  if (!token || !controllerUrl || (typeof controllerUrl === 'string' && !controllerUrl.trim())) {
180
- logger.error(chalk.red('Not logged in. Run: aifabrix login'));
181
+ logger.error(formatBlockingError('Not logged in. Run: aifabrix login'));
181
182
  logger.error(chalk.gray(' Use device code flow: aifabrix login --method device --controller <url>'));
182
183
  process.exit(1);
183
184
  }
@@ -215,7 +216,7 @@ function handleDatasourceApiError(response, dataplaneUrl = null) {
215
216
  function validateControllerUrl(controllerUrl) {
216
217
  const trimmed = controllerUrl.trim();
217
218
  if (!trimmed) {
218
- logger.error(chalk.red('Controller URL is empty.'));
219
+ logger.error(formatBlockingError('Controller URL is empty.'));
219
220
  logger.error(chalk.gray(` Controller URL from config: ${JSON.stringify(controllerUrl)}`));
220
221
  logger.error(chalk.gray(' Run: aifabrix login --method device --controller <url>'));
221
222
  process.exit(1);
@@ -238,7 +239,7 @@ async function resolveAndValidateDataplaneUrl(controllerUrl, environment, authCo
238
239
  // discoverDataplaneUrl already logs progress and success messages
239
240
  dataplaneUrl = await resolveDataplaneUrl(controllerUrl, environment, authConfig);
240
241
  } catch (error) {
241
- logger.error(chalk.red('Failed to resolve dataplane URL:'), error.message);
242
+ logger.error(formatBlockingError('Failed to resolve dataplane URL:'), error.message);
242
243
  logger.error(chalk.gray('\nThe dataplane URL is automatically discovered from the controller.'));
243
244
  logger.error(chalk.gray('If discovery fails, ensure you are logged in and the controller is accessible:'));
244
245
  logger.error(chalk.gray(' aifabrix login'));
@@ -248,7 +249,7 @@ async function resolveAndValidateDataplaneUrl(controllerUrl, environment, authCo
248
249
  }
249
250
 
250
251
  if (!dataplaneUrl || typeof dataplaneUrl !== 'string' || !dataplaneUrl.trim()) {
251
- logger.error(chalk.red('Dataplane URL is empty.'));
252
+ logger.error(formatBlockingError('Dataplane URL is empty.'));
252
253
  logger.error(chalk.gray('The dataplane URL could not be discovered from the controller.'));
253
254
  logger.error(chalk.gray('Ensure the dataplane service is registered in the controller.'));
254
255
  process.exit(1);
@@ -295,7 +296,7 @@ async function listDatasources(_options) {
295
296
  // Resolve dataplane URL first (required for list call)
296
297
  const dataplaneUrl = await resolveAndValidateDataplaneUrl(controllerUrl, environment, authConfig);
297
298
 
298
- // List datasources from dataplane (GET /api/v1/external/)
299
+ // List datasources from dataplane (GET /api/v1/external)
299
300
  const response = await listDatasourcesFromDataplane(dataplaneUrl, authConfig);
300
301
 
301
302
  if (!response.success || !response.data) {