@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
@@ -0,0 +1,495 @@
1
+ const { formatBlockingError } = require('../utils/cli-test-layout-chalk');
2
+ /**
3
+ * @fileoverview CLI wiring for `datasource test`, `test-integration`, and `test-e2e` (unified validation + watch).
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 { runDatasourceTestIntegration } = require('../datasource/test-integration');
11
+ const { runDatasourceTestE2E } = require('../datasource/test-e2e');
12
+ const { runUnifiedDatasourceValidation } = require('../datasource/unified-validation-run');
13
+ const { displayIntegrationTestResults, displayE2EResults } = require('../utils/external-system-display');
14
+ const path = require('path');
15
+ const { getIntegrationPath } = require('../utils/paths');
16
+ const { writeTestLog } = require('../utils/test-log-writer');
17
+ const { includeDebugForRequest } = require('../utils/validation-run-request');
18
+ const {
19
+ exitFromUnifiedValidationResult,
20
+ finalizeUnifiedValidationResult,
21
+ unifiedCliResultFromIntegrationReturn,
22
+ exitAfterIntegrationDisplay,
23
+ finalizeAfterIntegrationDisplay,
24
+ emitCapabilityScopeDiagnostics
25
+ } = require('./datasource-validation-cli');
26
+ const { resolveAppKeyForDatasource } = require('../datasource/resolve-app');
27
+ const { runDatasourceValidationWatchLoop } = require('../utils/datasource-validation-watch');
28
+ const { computeExitCodeFromDatasourceTestRun } = require('../utils/datasource-test-run-exit');
29
+ const { analyzeCapabilityScope } = require('../utils/datasource-test-run-capability-scope');
30
+ const {
31
+ resolveDebugDisplayMode,
32
+ formatDatasourceTestRunDebugBlock
33
+ } = require('../utils/datasource-test-run-debug-display');
34
+ const { formatCapabilityFocusSection } = require('../utils/datasource-test-run-display');
35
+ const {
36
+ datasourceTestHelpAfter,
37
+ datasourceTestIntegrationHelpAfter,
38
+ datasourceTestE2eHelpAfter,
39
+ attachDatasourceWatchOptions,
40
+ attachDatasourceTestCommonOptions
41
+ } = require('./datasource-unified-test-cli.options');
42
+
43
+ function integrationBaseDirForLogs(appKey) {
44
+ return path.dirname(getIntegrationPath(appKey));
45
+ }
46
+
47
+ async function writeDatasourceTestDebugLogIfRequested(appKey, datasourceKey, result, options) {
48
+ if (!options || !options.debug) return;
49
+ const requestMeta = {
50
+ datasourceKey,
51
+ runType: 'test',
52
+ includeDebug: includeDebugForRequest(options.debug)
53
+ };
54
+ const envelope = result && typeof result === 'object' ? result.envelope : null;
55
+ const apiError = result && typeof result === 'object' ? result.apiError : null;
56
+ const errorMessage = apiError
57
+ ? apiError.formattedError || apiError.error || 'Request failed'
58
+ : null;
59
+ const data = errorMessage
60
+ ? { request: requestMeta, error: errorMessage }
61
+ : { request: requestMeta, response: envelope };
62
+ const logPath = await writeTestLog(
63
+ appKey,
64
+ data,
65
+ 'test',
66
+ integrationBaseDirForLogs(appKey)
67
+ );
68
+ logger.log(chalk.gray(` Debug log: ${logPath}`));
69
+ }
70
+
71
+ function logDatasourceTestRunDebugAppendix(envelope, debugOpt) {
72
+ const mode = resolveDebugDisplayMode(debugOpt);
73
+ if (!mode || !envelope) return;
74
+ const block = formatDatasourceTestRunDebugBlock(envelope, mode, process.stdout.isTTY);
75
+ if (block) logger.log(block);
76
+ }
77
+
78
+ function logE2eCapabilityFocusFromEnvelope(env, capabilityOpt) {
79
+ if (!env) return;
80
+ const capKey =
81
+ capabilityOpt !== undefined && capabilityOpt !== null
82
+ ? String(capabilityOpt).trim()
83
+ : '';
84
+ if (!capKey) return;
85
+ const sec = formatCapabilityFocusSection(env, capKey);
86
+ if (sec) logger.log(sec);
87
+ }
88
+
89
+ /**
90
+ * Exit code from envelope only (no stderr diagnostics; use when TTY output already ran emit via logEnvelope).
91
+ * @param {Object|null|undefined} env
92
+ * @param {Object} options
93
+ * @returns {number|null} null if no envelope
94
+ */
95
+ function exitCodeFromDatasourceTestRunEnvelope(env, options) {
96
+ if (!env || typeof env !== 'object') return null;
97
+ let code = computeExitCodeFromDatasourceTestRun(env, {
98
+ warningsAsErrors: false,
99
+ requireCert: false
100
+ });
101
+ const scope = analyzeCapabilityScope(env, options.capability);
102
+ if (options.strictCapabilityScope === true && scope.violated) {
103
+ code = Math.max(code, 1);
104
+ }
105
+ return code;
106
+ }
107
+
108
+ /**
109
+ * Legacy E2E display + exit code (no process.exit; watch mode).
110
+ * @param {Object} data
111
+ * @param {Object} options
112
+ * @returns {number}
113
+ */
114
+ function finalizeDatasourceTestE2ELegacyPath(data, options) {
115
+ displayE2EResults(data, options.verbose);
116
+ logDatasourceTestRunDebugAppendix(data.datasourceTestRun, options.debug);
117
+ logE2eCapabilityFocusFromEnvelope(data.datasourceTestRun, options.capability);
118
+ const env = data.datasourceTestRun;
119
+ if (env) {
120
+ emitCapabilityScopeDiagnostics(env, { requestedCapabilityKey: options.capability });
121
+ const code = exitCodeFromDatasourceTestRunEnvelope(env, options);
122
+ return code === null ? 1 : code;
123
+ }
124
+ const steps = data.steps || data.completedActions || [];
125
+ const failed = data.success === false || steps.some(s => s.success === false || s.error);
126
+ return failed ? 1 : 0;
127
+ }
128
+
129
+ /**
130
+ * Human TTY for single-datasource E2E when DatasourceTestRun envelope is present.
131
+ * @param {string} datasourceKey
132
+ * @param {Object} env
133
+ * @param {Object} options
134
+ */
135
+ function displayDatasourceTestE2EEnvelopeResults(datasourceKey, env, options) {
136
+ const success = env.status !== 'fail';
137
+ displayIntegrationTestResults(
138
+ {
139
+ systemKey: env.systemKey || 'unknown',
140
+ success,
141
+ datasourceResults: [{ key: datasourceKey, success, datasourceTestRun: env }]
142
+ },
143
+ options.verbose,
144
+ {
145
+ debug: options.debug,
146
+ runType: 'e2e',
147
+ requestedCapabilityKey: options.capability
148
+ }
149
+ );
150
+ logE2eCapabilityFocusFromEnvelope(env, options.capability);
151
+ }
152
+
153
+ function buildDatasourceTestRunOpts(options) {
154
+ return {
155
+ app: options.app,
156
+ environment: options.env,
157
+ runType: 'test',
158
+ payload: options.payload,
159
+ debug: options.debug,
160
+ verbose: options.verbose,
161
+ timeout: options.timeout,
162
+ async: options.async !== false,
163
+ noAsync: options.async === false,
164
+ sync: options.sync === true
165
+ };
166
+ }
167
+
168
+ function buildDatasourceTestDisplayOpts(options) {
169
+ return {
170
+ json: options.json,
171
+ summary: options.summary,
172
+ warningsAsErrors: options.warningsAsErrors,
173
+ requireCert: options.requireCert,
174
+ debug: options.debug
175
+ };
176
+ }
177
+
178
+ async function runDatasourceUnifiedTestOnceForWatch(datasourceKey, runOpts, displayOpts) {
179
+ try {
180
+ const result = await runUnifiedDatasourceValidation(datasourceKey, runOpts);
181
+ return {
182
+ exitCode: finalizeUnifiedValidationResult(result, displayOpts),
183
+ envelope: result.envelope
184
+ };
185
+ } catch (err) {
186
+ logger.error(formatBlockingError('Datasource test failed:'), err.message);
187
+ return { exitCode: 4, envelope: null };
188
+ }
189
+ }
190
+
191
+ async function datasourceTestCommandAction(datasourceKey, options) {
192
+ const runOpts = buildDatasourceTestRunOpts(options);
193
+ const displayOpts = buildDatasourceTestDisplayOpts(options);
194
+ try {
195
+ if (options.watch) {
196
+ const { appKey } = await resolveAppKeyForDatasource(datasourceKey, options.app);
197
+ await runDatasourceValidationWatchLoop({
198
+ appKey,
199
+ extraPaths: options.watchPath || [],
200
+ includeApplicationYaml: options.watchApplicationYaml === true,
201
+ watchCi: options.watchCi === true,
202
+ watchFullDiff: options.watchFullDiff === true,
203
+ runOnce: async() => {
204
+ const result = await runUnifiedDatasourceValidation(datasourceKey, runOpts);
205
+ await writeDatasourceTestDebugLogIfRequested(appKey, datasourceKey, result, options);
206
+ return {
207
+ exitCode: finalizeUnifiedValidationResult(result, displayOpts),
208
+ envelope: result.envelope
209
+ };
210
+ }
211
+ });
212
+ return;
213
+ }
214
+ const result = await runUnifiedDatasourceValidation(datasourceKey, runOpts);
215
+ if (options.debug) {
216
+ try {
217
+ const { appKey } = await resolveAppKeyForDatasource(datasourceKey, options.app);
218
+ await writeDatasourceTestDebugLogIfRequested(appKey, datasourceKey, result, options);
219
+ } catch (e) {
220
+ logger.warn(chalk.yellow(`⚠ Could not write debug log: ${e.message}`));
221
+ }
222
+ }
223
+ exitFromUnifiedValidationResult(result, displayOpts);
224
+ } catch (error) {
225
+ logger.error(formatBlockingError('Datasource test failed:'), error.message);
226
+ process.exit(4);
227
+ }
228
+ }
229
+
230
+ function chainDatasourceTestCommand(datasource) {
231
+ const cmd = datasource
232
+ .command('test <datasourceKey>')
233
+ .description('Structural/policy validation for one datasource (unified dataplane API, runType=test)');
234
+ attachDatasourceTestCommonOptions(cmd, {
235
+ includeNoAsync: true,
236
+ verboseHelp: 'Set explain=true on validation request',
237
+ timeoutHelp: 'Aggregate timeout for POST + polls'
238
+ });
239
+ return cmd.addHelpText('after', datasourceTestHelpAfter());
240
+ }
241
+
242
+ function setupDatasourceTestCommand(datasource) {
243
+ // watch flags are already attached by attachDatasourceTestCommonOptions()
244
+ chainDatasourceTestCommand(datasource).action(datasourceTestCommandAction);
245
+ }
246
+
247
+ function buildIntegrationTestOpts(options) {
248
+ return {
249
+ app: options.app,
250
+ payload: options.payload,
251
+ environment: options.env,
252
+ debug: options.debug,
253
+ verbose: options.verbose,
254
+ timeout: options.timeout,
255
+ sync: options.sync === true
256
+ };
257
+ }
258
+
259
+ function buildIntegrationUnifiedDisplayOpts(options) {
260
+ return {
261
+ json: options.json,
262
+ summary: options.summary,
263
+ warningsAsErrors: options.warningsAsErrors,
264
+ requireCert: options.requireCert,
265
+ debug: options.debug
266
+ };
267
+ }
268
+
269
+ async function runIntegrationOnceForWatch(datasourceKey, integOpts, options, unifiedDisplayOpts) {
270
+ try {
271
+ const result = await runDatasourceTestIntegration(datasourceKey, integOpts);
272
+ const unifiedModes =
273
+ options.json || options.summary || options.warningsAsErrors || options.requireCert;
274
+ if (unifiedModes) {
275
+ const uni = unifiedCliResultFromIntegrationReturn(result);
276
+ const exitCode = finalizeUnifiedValidationResult(uni, unifiedDisplayOpts);
277
+ return { exitCode, envelope: uni.envelope };
278
+ }
279
+ displayIntegrationTestResults(
280
+ {
281
+ systemKey: result.systemKey || 'unknown',
282
+ datasourceResults: [result],
283
+ success: result.success
284
+ },
285
+ options.verbose,
286
+ { debug: options.debug, runType: 'integration' }
287
+ );
288
+ const exitCode = finalizeAfterIntegrationDisplay(result, {});
289
+ return { exitCode, envelope: result.datasourceTestRun || null };
290
+ } catch (err) {
291
+ logger.error(formatBlockingError('Integration test failed:'), err.message);
292
+ return { exitCode: 4, envelope: null };
293
+ }
294
+ }
295
+
296
+ async function integrationTestCommandAction(datasourceKey, options) {
297
+ const integOpts = buildIntegrationTestOpts(options);
298
+ const unifiedDisplayOpts = buildIntegrationUnifiedDisplayOpts(options);
299
+ try {
300
+ if (options.watch) {
301
+ const { appKey } = await resolveAppKeyForDatasource(datasourceKey, options.app);
302
+ await runDatasourceValidationWatchLoop({
303
+ appKey,
304
+ extraPaths: options.watchPath || [],
305
+ includeApplicationYaml: options.watchApplicationYaml === true,
306
+ watchCi: options.watchCi === true,
307
+ watchFullDiff: options.watchFullDiff === true,
308
+ runOnce: () => runIntegrationOnceForWatch(datasourceKey, integOpts, options, unifiedDisplayOpts)
309
+ });
310
+ return;
311
+ }
312
+ const result = await runDatasourceTestIntegration(datasourceKey, integOpts);
313
+ const unifiedModes =
314
+ options.json || options.summary || options.warningsAsErrors || options.requireCert;
315
+ if (unifiedModes) {
316
+ exitFromUnifiedValidationResult(unifiedCliResultFromIntegrationReturn(result), unifiedDisplayOpts);
317
+ return;
318
+ }
319
+ displayIntegrationTestResults(
320
+ {
321
+ systemKey: result.systemKey || 'unknown',
322
+ datasourceResults: [result],
323
+ success: result.success
324
+ },
325
+ options.verbose,
326
+ { debug: options.debug, runType: 'integration' }
327
+ );
328
+ exitAfterIntegrationDisplay(result, {});
329
+ } catch (error) {
330
+ logger.error(formatBlockingError('Integration test failed:'), error.message);
331
+ process.exit(4);
332
+ }
333
+ }
334
+
335
+ function chainDatasourceTestIntegrationCommand(datasource) {
336
+ const cmd = datasource
337
+ .command('test-integration <datasourceKey>')
338
+ .description('Integration test one datasource (unified validation API, runType=integration)');
339
+ attachDatasourceTestCommonOptions(cmd, {
340
+ includeNoAsync: false,
341
+ debugHelp: 'includeDebug + log under integration/<systemKey>/logs/; TTY appendix: summary, full, or raw'
342
+ });
343
+ return cmd.addHelpText('after', datasourceTestIntegrationHelpAfter());
344
+ }
345
+
346
+ function setupDatasourceTestIntegrationCommand(datasource) {
347
+ // watch flags are already attached by attachDatasourceTestCommonOptions()
348
+ chainDatasourceTestIntegrationCommand(datasource).action(integrationTestCommandAction);
349
+ }
350
+
351
+ /**
352
+ * @param {string} datasourceKey
353
+ * @param {Object} options
354
+ * @returns {Promise<{ exitCode: number, envelope: Object|null }>}
355
+ */
356
+ async function runDatasourceTestE2ECliOnce(datasourceKey, options) {
357
+ const data = await runDatasourceTestE2E(datasourceKey, {
358
+ app: options.app,
359
+ environment: options.env,
360
+ debug: options.debug,
361
+ verbose: options.verbose,
362
+ async: options.async !== false,
363
+ testCrud: options.testCrud,
364
+ recordId: options.recordId,
365
+ cleanup: options.cleanup,
366
+ primaryKeyValue: options.primaryKeyValue,
367
+ timeout: options.timeout,
368
+ capabilityKey: options.capability,
369
+ sync: options.sync === true
370
+ });
371
+ const unifiedModes =
372
+ options.json || options.summary || options.warningsAsErrors || options.requireCert;
373
+ if (unifiedModes && data.datasourceTestRun) {
374
+ const exitCode = finalizeUnifiedValidationResult(
375
+ {
376
+ apiError: null,
377
+ pollTimedOut: false,
378
+ incompleteNoAsync: false,
379
+ envelope: data.datasourceTestRun
380
+ },
381
+ {
382
+ json: options.json,
383
+ summary: options.summary,
384
+ warningsAsErrors: options.warningsAsErrors,
385
+ requireCert: options.requireCert,
386
+ debug: options.debug,
387
+ requestedCapabilityKey: options.capability,
388
+ strictCapabilityScope: options.strictCapabilityScope === true
389
+ }
390
+ );
391
+ return { exitCode, envelope: data.datasourceTestRun };
392
+ }
393
+ const env = data.datasourceTestRun;
394
+ if (env && !unifiedModes) {
395
+ displayDatasourceTestE2EEnvelopeResults(datasourceKey, env, options);
396
+ const exitCode = exitCodeFromDatasourceTestRunEnvelope(env, options);
397
+ return { exitCode: exitCode === null ? 1 : exitCode, envelope: env };
398
+ }
399
+ const exitCode = finalizeDatasourceTestE2ELegacyPath(data, options);
400
+ return { exitCode, envelope: data.datasourceTestRun || null };
401
+ }
402
+
403
+ async function runDatasourceTestE2ECliAction(datasourceKey, options) {
404
+ const { exitCode } = await runDatasourceTestE2ECliOnce(datasourceKey, options);
405
+ process.exit(exitCode);
406
+ }
407
+
408
+ async function e2eTestCommandAction(datasourceKey, capabilityKey, options) {
409
+ const optObj = options && typeof options === 'object' ? options : {};
410
+ const capFromArg = typeof capabilityKey === 'string' ? capabilityKey.trim() : '';
411
+ const capFromFlag = optObj.capability !== undefined && optObj.capability !== null
412
+ ? String(optObj.capability).trim()
413
+ : '';
414
+ const requestedCapability = capFromArg || capFromFlag;
415
+ if (capFromArg && capFromFlag && capFromArg !== capFromFlag) {
416
+ logger.warn(
417
+ chalk.yellow('⚠ Capability mismatch:'),
418
+ `using positional '${capFromArg}' instead of --capability '${capFromFlag}'.`
419
+ );
420
+ }
421
+ const mergedOptions = { ...optObj, capability: requestedCapability || undefined };
422
+ try {
423
+ if (mergedOptions.watch) {
424
+ const { appKey } = await resolveAppKeyForDatasource(datasourceKey, mergedOptions.app);
425
+ await runDatasourceValidationWatchLoop({
426
+ appKey,
427
+ extraPaths: mergedOptions.watchPath || [],
428
+ includeApplicationYaml: mergedOptions.watchApplicationYaml === true,
429
+ watchCi: mergedOptions.watchCi === true,
430
+ watchFullDiff: mergedOptions.watchFullDiff === true,
431
+ runOnce: async() => {
432
+ try {
433
+ return await runDatasourceTestE2ECliOnce(datasourceKey, mergedOptions);
434
+ } catch (err) {
435
+ logger.error(formatBlockingError('E2E test failed:'), err.message);
436
+ return { exitCode: 3, envelope: null };
437
+ }
438
+ }
439
+ });
440
+ return;
441
+ }
442
+ await runDatasourceTestE2ECliAction(datasourceKey, mergedOptions);
443
+ } catch (error) {
444
+ logger.error(formatBlockingError('E2E test failed:'), error.message);
445
+ process.exit(3);
446
+ }
447
+ }
448
+
449
+ function chainDatasourceTestE2ECommand(datasource) {
450
+ const cmd = datasource
451
+ .command('test-e2e <datasourceKey> [capabilityKey]')
452
+ .description('E2E test one datasource (unified validation API, runType=e2e)');
453
+ attachDatasourceTestCommonOptions(cmd, {
454
+ includeNoAsync: true,
455
+ includePayload: false,
456
+ appHelp: 'Integration folder name (default: resolve from cwd if inside integration/<systemKey>/)',
457
+ verboseHelp: 'Audit / explain-oriented request flags where applicable',
458
+ debugHelp: 'includeDebug + log under integration/<systemKey>/logs/; TTY appendix: summary, full, or raw',
459
+ timeoutHelp: 'Aggregate timeout for POST + polls (default 15m)',
460
+ timeoutDefault: String(15 * 60 * 1000)
461
+ });
462
+ return cmd
463
+ .option('--test-crud', 'Enable CRUD lifecycle test (e2eOptions.testCrud)')
464
+ .option('--record-id <id>', 'Record ID for test (e2eOptions.recordId)')
465
+ .option('--no-cleanup', 'Disable cleanup after test (e2eOptions.cleanup: false)')
466
+ .option(
467
+ '--primary-key-value <value|@path>',
468
+ 'Primary key value or path to JSON file (e.g. @pk.json) for e2eOptions.primaryKeyValue'
469
+ )
470
+ .option('--capability <key>', 'Capability drill-down (deprecated; use positional [capabilityKey])')
471
+ .option(
472
+ '--strict-capability-scope',
473
+ 'Exit 1 if a capability drill-down is requested but the report lists more than one capabilities[] row (plan §2.3)'
474
+ )
475
+ .addHelpText('after', datasourceTestE2eHelpAfter());
476
+ }
477
+
478
+ function setupDatasourceTestE2ECommand(datasource) {
479
+ // watch flags are already attached by attachDatasourceTestCommonOptions()
480
+ chainDatasourceTestE2ECommand(datasource).action(e2eTestCommandAction);
481
+ }
482
+
483
+ module.exports = {
484
+ setupDatasourceTestCommand,
485
+ setupDatasourceTestIntegrationCommand,
486
+ setupDatasourceTestE2ECommand,
487
+ attachDatasourceWatchOptions,
488
+ /** @internal Exported for Jest: CLI action coverage without Commander. */
489
+ runDatasourceUnifiedTestOnceForWatch,
490
+ datasourceTestCommandAction,
491
+ runIntegrationOnceForWatch,
492
+ integrationTestCommandAction,
493
+ runDatasourceTestE2ECliOnce,
494
+ e2eTestCommandAction
495
+ };
@@ -0,0 +1,149 @@
1
+ /**
2
+ * @fileoverview Shared option builders + help text for datasource test CLI commands.
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ function datasourceTestHelpAfter() {
8
+ return `
9
+ Examples:
10
+ $ aifabrix datasource test hubspot-users
11
+ $ aifabrix datasource test hubspot-users --app test-e2e-hubspot -v
12
+ $ aifabrix datasource test hubspot-users -a test-e2e-hubspot --debug full
13
+ $ aifabrix datasource test hubspot-users --json
14
+
15
+ Notes:
16
+ - For integration pipeline tests, use:
17
+ aifabrix datasource test-integration <datasourceKey>
18
+ - For system-level rollup across datasources, use:
19
+ aifabrix test <systemKey>
20
+ `;
21
+ }
22
+
23
+ function datasourceTestIntegrationHelpAfter() {
24
+ return `
25
+ Examples:
26
+ $ aifabrix datasource test-integration hubspot-users
27
+ $ aifabrix datasource test-integration hubspot-users --app test-e2e-hubspot --debug
28
+ $ aifabrix datasource test-integration hubspot-users -a test-e2e-hubspot -e tst --timeout 60000
29
+
30
+ Notes:
31
+ - For structural/policy validation, use:
32
+ aifabrix datasource test <datasourceKey>
33
+ - For E2E capability execution, use:
34
+ aifabrix datasource test-e2e <datasourceKey>
35
+ - For system-level integration rollup across datasources, use:
36
+ aifabrix test-integration <systemKey>
37
+ `;
38
+ }
39
+
40
+ function datasourceTestE2eHelpAfter() {
41
+ return `
42
+ Examples:
43
+ $ aifabrix datasource test-e2e hubspot-users
44
+ $ aifabrix datasource test-e2e hubspot-users --app test-e2e-hubspot -v --debug
45
+ $ aifabrix datasource test-e2e hubspot-users -a test-e2e-hubspot --no-async
46
+ $ aifabrix datasource test-e2e hubspot-users read
47
+
48
+ Notes:
49
+ - For structural/policy validation, use:
50
+ aifabrix datasource test <datasourceKey>
51
+ - For integration pipeline tests, use:
52
+ aifabrix datasource test-integration <datasourceKey>
53
+ - For system-level E2E rollup across datasources, use:
54
+ aifabrix test-e2e <systemKey>
55
+ `;
56
+ }
57
+
58
+ /**
59
+ * @param {object} cmd - Commander command (chainable)
60
+ * @returns {object}
61
+ */
62
+ function attachDatasourceWatchOptions(cmd) {
63
+ return cmd
64
+ .option(
65
+ '--watch',
66
+ 'Re-run when watched files change (debounced; integration tree + optional paths)'
67
+ )
68
+ .option(
69
+ '--watch-path <path>',
70
+ 'Extra file or directory to watch (repeatable)',
71
+ (value, previous) => (Array.isArray(previous) ? previous : []).concat(value),
72
+ []
73
+ )
74
+ .option('--watch-application-yaml', 'Include integration/<app>/application.yaml in the watch set')
75
+ .option('--watch-ci', 'Exit after the first run with the normal exit code (CI one-shot)')
76
+ .option('--watch-full-diff', 'Print full before/after fingerprint lines when the result changes');
77
+ }
78
+
79
+ /**
80
+ * Shared options for datasource-level `test`, `test-integration`, and `test-e2e`.
81
+ *
82
+ * Registration order matches intended `--help` order: core run flags → payload/timeout →
83
+ * `--sync` (pre-run publish) → machine/exit modifiers → async → watch (last before `--help`).
84
+ * Callers must append `addHelpText('after', …)` **after** any command-specific options (e.g. E2E).
85
+ *
86
+ * @param {object} cmd - Commander command (chainable)
87
+ * @param {Object} opts
88
+ * @param {boolean} [opts.includeNoAsync]
89
+ * @param {boolean} [opts.includePayload]
90
+ * @param {string} [opts.appHelp]
91
+ * @param {string} [opts.verboseHelp]
92
+ * @param {string} [opts.debugHelp]
93
+ * @param {string} [opts.timeoutHelp]
94
+ * @param {string} [opts.timeoutDefault]
95
+ * @returns {object}
96
+ */
97
+ function attachDatasourceTestCommonOptions(cmd, opts) {
98
+ const includeNoAsync = opts.includeNoAsync === true;
99
+ const includePayload = opts.includePayload !== false;
100
+
101
+ cmd
102
+ .option(
103
+ '-a, --app <app>',
104
+ opts.appHelp ||
105
+ 'Integration folder name (optional: resolve from cwd or datasource key if single match)'
106
+ )
107
+ .option('-e, --env <env>', 'Environment: dev, tst, or pro')
108
+ .option('-v, --verbose', opts.verboseHelp || 'Explain mode and detailed output where available')
109
+ .option(
110
+ '-d, --debug [level]',
111
+ opts.debugHelp ||
112
+ 'includeDebug on request; TTY appendix: summary (default), full, or raw (not with --json)'
113
+ );
114
+
115
+ if (includePayload) {
116
+ cmd.option('-p, --payload <file>', 'Optional custom payload file (sets payloadTemplate on request)');
117
+ }
118
+
119
+ cmd
120
+ .option(
121
+ '--timeout <ms>',
122
+ opts.timeoutHelp || 'Aggregate timeout for POST + polls (ms)',
123
+ opts.timeoutDefault || '30000'
124
+ )
125
+ .option(
126
+ '--sync',
127
+ 'Publish this datasource JSON from disk to the dataplane before running the test (requires login / same auth as upload)'
128
+ )
129
+ .option('--json', 'Print raw DatasourceTestRun JSON to stdout')
130
+ .option('--summary', 'Print compact summary line')
131
+ .option('--warnings-as-errors', 'Exit 1 when root status is warn')
132
+ .option('--require-cert', 'Exit 2 when certificate missing or not_passed');
133
+
134
+ if (includeNoAsync) {
135
+ cmd.option('--no-async', 'Do not poll; fail if report is not complete in first response');
136
+ }
137
+
138
+ attachDatasourceWatchOptions(cmd);
139
+ return cmd;
140
+ }
141
+
142
+ module.exports = {
143
+ datasourceTestHelpAfter,
144
+ datasourceTestIntegrationHelpAfter,
145
+ datasourceTestE2eHelpAfter,
146
+ attachDatasourceWatchOptions,
147
+ attachDatasourceTestCommonOptions
148
+ };
149
+