@aifabrix/builder 2.43.0 → 2.44.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (371) hide show
  1. package/.cursor/rules/anchor-docs.mdc +15 -0
  2. package/.cursor/rules/cli-layout.mdc +75 -0
  3. package/.cursor/rules/project-rules.mdc +8 -0
  4. package/.npmrc.token +1 -0
  5. package/.nyc_output/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
  6. package/.nyc_output/processinfo/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
  7. package/.nyc_output/processinfo/index.json +1 -0
  8. package/README.md +1 -1
  9. package/anchor-docs/README.md +10 -0
  10. package/anchor-docs/_TEMPLATE +24 -0
  11. package/bin/aifabrix.js +13 -4
  12. package/integration/hubspot-test/README.md +31 -0
  13. package/integration/hubspot-test/create-hubspot.js +5 -5
  14. package/integration/hubspot-test/hubspot-test-datasource-company.json +58 -462
  15. package/integration/hubspot-test/hubspot-test-datasource-contact.json +61 -555
  16. package/integration/hubspot-test/hubspot-test-datasource-deal.json +63 -506
  17. package/integration/hubspot-test/hubspot-test-datasource-users.json +42 -83
  18. package/integration/hubspot-test/hubspot-test-deploy.json +3 -3
  19. package/integration/hubspot-test/test-dataplane-down-tests.js +1 -7
  20. package/integration/hubspot-test/test-dataplane-down.js +3 -3
  21. package/integration/hubspot-test/test.js +35 -43
  22. package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
  23. package/integration/roundtrip-test-local/README.md +144 -0
  24. package/integration/roundtrip-test-local/application.yaml +13 -0
  25. package/integration/roundtrip-test-local/env.template +15 -0
  26. package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
  27. package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
  28. package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
  29. package/integration/roundtrip-test-local2/README.md +144 -0
  30. package/integration/roundtrip-test-local2/application.yaml +13 -0
  31. package/integration/roundtrip-test-local2/env.template +15 -0
  32. package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
  33. package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
  34. package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
  35. package/integration/test/wizard.yaml +8 -0
  36. package/jest.config.default.js +10 -0
  37. package/jest.config.integration.fixtures.js +22 -0
  38. package/jest.config.integration.js +21 -18
  39. package/jest.config.isolated.js +10 -0
  40. package/jest.projects.js +301 -0
  41. package/lib/api/certificates.api.js +62 -0
  42. package/lib/api/datasources-core.api.js +3 -3
  43. package/lib/api/dev-mtls-request.js +110 -0
  44. package/lib/api/dev-server-https.js +145 -0
  45. package/lib/api/dev.api.js +133 -144
  46. package/lib/api/index.js +11 -3
  47. package/lib/api/pipeline.api.js +67 -20
  48. package/lib/api/types/certificates.types.js +48 -0
  49. package/lib/api/types/dev.types.js +4 -3
  50. package/lib/api/types/pipeline.types.js +8 -5
  51. package/lib/api/types/validation-run.types.js +56 -0
  52. package/lib/api/validation-run.api.js +111 -0
  53. package/lib/api/validation-runner.js +109 -0
  54. package/lib/app/certification-show-enrich.js +129 -0
  55. package/lib/app/certification-verify-rows.js +60 -0
  56. package/lib/app/config.js +1 -1
  57. package/lib/app/deploy-status-display.js +2 -2
  58. package/lib/app/deploy.js +7 -6
  59. package/lib/app/display.js +2 -1
  60. package/lib/app/dockerfile.js +3 -2
  61. package/lib/app/down.js +2 -1
  62. package/lib/app/helpers.js +6 -5
  63. package/lib/app/index.js +27 -8
  64. package/lib/app/list.js +7 -6
  65. package/lib/app/push.js +4 -3
  66. package/lib/app/register.js +16 -7
  67. package/lib/app/rotate-secret.js +14 -13
  68. package/lib/app/run-container-start.js +184 -0
  69. package/lib/app/run-docker-fallback.js +108 -0
  70. package/lib/app/run-env-compose.js +30 -42
  71. package/lib/app/run-helpers.js +49 -126
  72. package/lib/app/run-infra-requirements.js +30 -0
  73. package/lib/app/run-resolve-image.js +21 -0
  74. package/lib/app/run.js +74 -21
  75. package/lib/app/show-display.js +44 -1
  76. package/lib/app/show.js +93 -9
  77. package/lib/build/index.js +13 -10
  78. package/lib/certification/cli-cert-sync-skip.js +21 -0
  79. package/lib/certification/merge-certification-from-artifact.js +185 -0
  80. package/lib/certification/post-unified-cert-sync.js +33 -0
  81. package/lib/certification/sync-after-external-command.js +52 -0
  82. package/lib/certification/sync-system-certification.js +197 -0
  83. package/lib/cli/index.js +2 -0
  84. package/lib/cli/setup-app.help.js +67 -0
  85. package/lib/cli/setup-app.js +61 -121
  86. package/lib/cli/setup-app.test-commands.js +195 -0
  87. package/lib/cli/setup-auth.js +19 -5
  88. package/lib/cli/setup-credential-deployment.js +22 -8
  89. package/lib/cli/setup-dev-path-commands.js +124 -0
  90. package/lib/cli/setup-dev.js +170 -113
  91. package/lib/cli/setup-environment.js +7 -1
  92. package/lib/cli/setup-external-system.js +84 -23
  93. package/lib/cli/setup-infra.js +126 -47
  94. package/lib/cli/setup-parameters.js +32 -0
  95. package/lib/cli/setup-secrets.js +137 -18
  96. package/lib/cli/setup-service-user.js +1 -1
  97. package/lib/cli/setup-utility.js +54 -22
  98. package/lib/commands/app-down.js +5 -7
  99. package/lib/commands/app-install.js +14 -7
  100. package/lib/commands/app-logs.js +13 -10
  101. package/lib/commands/app-shell.js +4 -1
  102. package/lib/commands/app-test.js +25 -19
  103. package/lib/commands/app.js +32 -11
  104. package/lib/commands/auth-config.js +6 -6
  105. package/lib/commands/auth-status.js +4 -3
  106. package/lib/commands/credential-env.js +4 -3
  107. package/lib/commands/credential-list.js +5 -4
  108. package/lib/commands/credential-push.js +4 -3
  109. package/lib/commands/datasource-unified-test-cli.js +428 -0
  110. package/lib/commands/datasource-unified-test-cli.options.js +191 -0
  111. package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +106 -0
  112. package/lib/commands/datasource-validation-cli.js +143 -0
  113. package/lib/commands/datasource.js +125 -95
  114. package/lib/commands/deployment-list.js +6 -5
  115. package/lib/commands/dev-cli-handlers.js +122 -18
  116. package/lib/commands/dev-down.js +4 -3
  117. package/lib/commands/dev-init.js +231 -116
  118. package/lib/commands/dev-show-display.js +473 -0
  119. package/lib/commands/login-credentials.js +3 -2
  120. package/lib/commands/login-device.js +4 -3
  121. package/lib/commands/login.js +5 -4
  122. package/lib/commands/logout.js +8 -7
  123. package/lib/commands/parameters-validate.js +54 -0
  124. package/lib/commands/repair-datasource.js +314 -68
  125. package/lib/commands/repair-env-template.js +2 -2
  126. package/lib/commands/repair.js +21 -3
  127. package/lib/commands/secrets-list.js +23 -12
  128. package/lib/commands/secrets-remove-all.js +220 -0
  129. package/lib/commands/secrets-remove.js +21 -12
  130. package/lib/commands/secrets-set.js +21 -12
  131. package/lib/commands/secrets-validate.js +4 -4
  132. package/lib/commands/secure.js +10 -9
  133. package/lib/commands/service-user.js +26 -25
  134. package/lib/commands/test-e2e-external.js +27 -1
  135. package/lib/commands/up-common.js +3 -2
  136. package/lib/commands/up-dataplane.js +29 -16
  137. package/lib/commands/up-miso.js +19 -29
  138. package/lib/commands/upload.js +149 -39
  139. package/lib/commands/wizard-core-helpers.js +1 -1
  140. package/lib/commands/wizard-dataplane.js +4 -3
  141. package/lib/commands/wizard-helpers.js +3 -3
  142. package/lib/commands/wizard.js +2 -2
  143. package/lib/core/admin-secrets.js +14 -5
  144. package/lib/core/audit-logger.js +12 -4
  145. package/lib/core/config-attach-extensions.js +46 -0
  146. package/lib/core/config-runtime-paths.js +29 -0
  147. package/lib/core/config.js +55 -56
  148. package/lib/core/diff.js +3 -2
  149. package/lib/core/ensure-encryption-key.js +1 -1
  150. package/lib/core/secrets-ensure-infra.js +77 -0
  151. package/lib/core/secrets-ensure.js +120 -64
  152. package/lib/core/secrets-env-write.js +35 -7
  153. package/lib/core/secrets-infra-placeholder-sync.js +61 -0
  154. package/lib/core/secrets.js +200 -37
  155. package/lib/core/templates-env.js +4 -3
  156. package/lib/datasource/abac-validator.js +1 -10
  157. package/lib/datasource/deploy.js +75 -53
  158. package/lib/datasource/field-reference-validator.js +9 -6
  159. package/lib/datasource/integration-context.js +63 -0
  160. package/lib/datasource/list.js +8 -7
  161. package/lib/datasource/log-viewer.js +189 -67
  162. package/lib/datasource/resolve-app.js +4 -4
  163. package/lib/datasource/test-e2e.js +113 -146
  164. package/lib/datasource/test-integration.js +114 -122
  165. package/lib/datasource/unified-validation-run-body.js +68 -0
  166. package/lib/datasource/unified-validation-run-post.js +23 -0
  167. package/lib/datasource/unified-validation-run-resolve.js +43 -0
  168. package/lib/datasource/unified-validation-run.js +93 -0
  169. package/lib/datasource/validate.js +157 -13
  170. package/lib/deployment/deployer.js +4 -3
  171. package/lib/deployment/environment.js +7 -6
  172. package/lib/deployment/push.js +17 -8
  173. package/lib/external-system/delete.js +4 -3
  174. package/lib/external-system/deploy.js +166 -53
  175. package/lib/external-system/download-helpers.js +1 -1
  176. package/lib/external-system/download.js +7 -6
  177. package/lib/external-system/generator.js +92 -6
  178. package/lib/external-system/integration-test-dispatch.js +26 -0
  179. package/lib/external-system/test-execution.js +5 -1
  180. package/lib/external-system/test-helpers.js +0 -4
  181. package/lib/external-system/test-system-level-helpers.js +110 -0
  182. package/lib/external-system/test-system-level.js +83 -44
  183. package/lib/external-system/test.js +59 -8
  184. package/lib/generator/builders.js +23 -11
  185. package/lib/generator/deploy-manifest-azure-kv.js +81 -0
  186. package/lib/generator/external.js +16 -4
  187. package/lib/generator/helpers.js +58 -3
  188. package/lib/generator/index.js +4 -0
  189. package/lib/generator/split-readme.js +12 -7
  190. package/lib/generator/split-variables.js +2 -1
  191. package/lib/generator/split.js +1 -1
  192. package/lib/generator/wizard-readme.js +3 -3
  193. package/lib/generator/wizard.js +8 -8
  194. package/lib/infrastructure/compose.js +70 -7
  195. package/lib/infrastructure/helpers-docker-check.js +67 -0
  196. package/lib/infrastructure/helpers.js +203 -42
  197. package/lib/infrastructure/index.js +31 -18
  198. package/lib/infrastructure/services.js +21 -67
  199. package/lib/internal/fs-real-sync.js +104 -0
  200. package/lib/internal/node-fs.js +98 -0
  201. package/lib/parameters/database-secret-values.js +173 -0
  202. package/lib/parameters/infra-kv-discovery.js +121 -0
  203. package/lib/parameters/infra-parameter-catalog.js +458 -0
  204. package/lib/parameters/infra-parameter-validate.js +64 -0
  205. package/lib/schema/application-schema.json +37 -17
  206. package/lib/schema/datasource-test-run.schema.json +493 -0
  207. package/lib/schema/deployment-rules.yaml +102 -63
  208. package/lib/schema/external-datasource.schema.json +1200 -442
  209. package/lib/schema/external-system.schema.json +203 -5
  210. package/lib/schema/flag-map-validation-run.json +31 -0
  211. package/lib/schema/infra-parameter.schema.json +106 -0
  212. package/lib/schema/infra.parameter.yaml +421 -0
  213. package/lib/schema/type/credential-auth-templates.json +40 -0
  214. package/lib/schema/type/document-storage.json +226 -0
  215. package/lib/schema/type/message-service.json +123 -0
  216. package/lib/schema/type/vector-store.json +88 -0
  217. package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
  218. package/lib/utils/api-error-handler.js +2 -2
  219. package/lib/utils/api.js +77 -17
  220. package/lib/utils/app-register-api.js +3 -2
  221. package/lib/utils/app-register-auth.js +1 -1
  222. package/lib/utils/app-register-config.js +4 -4
  223. package/lib/utils/app-register-display.js +3 -2
  224. package/lib/utils/app-register-validator.js +3 -2
  225. package/lib/utils/app-run-containers.js +26 -22
  226. package/lib/utils/app-scoped-config.js +31 -0
  227. package/lib/utils/app-service-env-from-builder.js +164 -0
  228. package/lib/utils/build-copy.js +1 -1
  229. package/lib/utils/build-helpers.js +20 -20
  230. package/lib/utils/build-resolve-image.js +165 -0
  231. package/lib/utils/cli-layout-chalk.js +8 -0
  232. package/lib/utils/cli-test-layout-chalk.js +267 -0
  233. package/lib/utils/cli-utils.js +88 -11
  234. package/lib/utils/compose-db-passwords.js +138 -0
  235. package/lib/utils/compose-generate-docker-compose.js +216 -0
  236. package/lib/utils/compose-generator.js +197 -291
  237. package/lib/utils/compose-miso-env.js +18 -0
  238. package/lib/utils/compose-traefik-ingress-base.js +158 -0
  239. package/lib/utils/config-paths.js +166 -7
  240. package/lib/utils/config-scoped-resources-preference.js +41 -0
  241. package/lib/utils/configuration-env-resolver.js +11 -8
  242. package/lib/utils/controller-deployment-outcome.js +68 -0
  243. package/lib/utils/credential-display.js +2 -2
  244. package/lib/utils/credential-secrets-env.js +5 -5
  245. package/lib/utils/dataplane-pipeline-warning.js +4 -3
  246. package/lib/utils/datasource-test-run-capability-scope.js +43 -0
  247. package/lib/utils/datasource-test-run-certificate-tty.js +82 -0
  248. package/lib/utils/datasource-test-run-debug-display.js +137 -0
  249. package/lib/utils/datasource-test-run-debug-slice.js +93 -0
  250. package/lib/utils/datasource-test-run-display.js +459 -0
  251. package/lib/utils/datasource-test-run-exit.js +83 -0
  252. package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
  253. package/lib/utils/datasource-test-run-report-version.js +51 -0
  254. package/lib/utils/datasource-test-run-schema-sync.js +59 -0
  255. package/lib/utils/datasource-test-run-tty-log.js +81 -0
  256. package/lib/utils/datasource-validation-watch.js +266 -0
  257. package/lib/utils/declarative-url-ports.js +47 -0
  258. package/lib/utils/derive-env-key-from-client-id.js +41 -0
  259. package/lib/utils/dev-ca-install.js +185 -23
  260. package/lib/utils/dev-cert-helper.js +266 -17
  261. package/lib/utils/dev-hosts-helper.js +307 -0
  262. package/lib/utils/dev-init-cert-hints.js +37 -0
  263. package/lib/utils/dev-init-health-messages.js +52 -0
  264. package/lib/utils/dev-init-resolve.js +86 -0
  265. package/lib/utils/dev-init-ssh-merge.js +65 -0
  266. package/lib/utils/dev-ssh-config-helper.js +196 -0
  267. package/lib/utils/dev-user-groups.js +93 -0
  268. package/lib/utils/docker-build.js +42 -17
  269. package/lib/utils/docker-exec.js +28 -0
  270. package/lib/utils/docker-manifest-public-port.js +116 -0
  271. package/lib/utils/docker-not-running-hint.js +52 -0
  272. package/lib/utils/docker.js +98 -11
  273. package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
  274. package/lib/utils/env-config-loader.js +10 -91
  275. package/lib/utils/env-copy.js +19 -10
  276. package/lib/utils/env-map.js +35 -8
  277. package/lib/utils/env-template.js +2 -2
  278. package/lib/utils/environment-scoped-resources.js +144 -0
  279. package/lib/utils/error-formatter.js +92 -13
  280. package/lib/utils/error-formatters/http-status-errors.js +6 -5
  281. package/lib/utils/error-formatters/network-errors.js +2 -1
  282. package/lib/utils/error-formatters/permission-errors.js +2 -1
  283. package/lib/utils/error-formatters/validation-errors.js +2 -1
  284. package/lib/utils/external-readme.js +8 -1
  285. package/lib/utils/external-system-display.js +242 -136
  286. package/lib/utils/external-system-local-test-tty.js +389 -0
  287. package/lib/utils/external-system-readiness-core.js +377 -0
  288. package/lib/utils/external-system-readiness-deploy-display.js +270 -0
  289. package/lib/utils/external-system-readiness-display-internals.js +150 -0
  290. package/lib/utils/external-system-readiness-display.js +186 -0
  291. package/lib/utils/external-system-system-test-tty-overview.js +120 -0
  292. package/lib/utils/external-system-system-test-tty.js +417 -0
  293. package/lib/utils/external-system-test-helpers.js +24 -6
  294. package/lib/utils/external-system-validators.js +30 -12
  295. package/lib/utils/health-check-url.js +119 -0
  296. package/lib/utils/health-check.js +59 -25
  297. package/lib/utils/help-builder.js +11 -8
  298. package/lib/utils/image-version.js +4 -8
  299. package/lib/utils/infra-containers.js +4 -7
  300. package/lib/utils/infra-env-defaults.js +162 -0
  301. package/lib/utils/infra-status-display.js +167 -0
  302. package/lib/utils/infra-status.js +16 -8
  303. package/lib/utils/local-secrets.js +3 -4
  304. package/lib/utils/paths.js +148 -47
  305. package/lib/utils/port-resolver.js +10 -23
  306. package/lib/utils/redis-env-scope.js +62 -0
  307. package/lib/utils/register-aifabrix-shell-env.js +204 -0
  308. package/lib/utils/remote-builder-validation.js +99 -0
  309. package/lib/utils/remote-dev-auth.js +117 -21
  310. package/lib/utils/remote-docker-env.js +67 -15
  311. package/lib/utils/remote-secrets-loader.js +13 -4
  312. package/lib/utils/resolve-docker-image-ref.js +124 -0
  313. package/lib/utils/schema-loader.js +22 -9
  314. package/lib/utils/secrets-bash-kv.js +25 -0
  315. package/lib/utils/secrets-generator.js +169 -49
  316. package/lib/utils/secrets-helpers.js +70 -59
  317. package/lib/utils/secrets-kv-scope.js +60 -0
  318. package/lib/utils/secrets-utils.js +32 -38
  319. package/lib/utils/secrets-validation.js +3 -1
  320. package/lib/utils/secrets-yaml-preserve.js +109 -0
  321. package/lib/utils/ssh-key-helper.js +4 -2
  322. package/lib/utils/template-helpers.js +2 -2
  323. package/lib/utils/test-log-writer.js +3 -3
  324. package/lib/utils/token-manager.js +1 -2
  325. package/lib/utils/url-declarative-public-base.js +188 -0
  326. package/lib/utils/url-declarative-resolve-build.js +493 -0
  327. package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
  328. package/lib/utils/url-declarative-resolve.js +220 -0
  329. package/lib/utils/url-declarative-token-parse.js +74 -0
  330. package/lib/utils/url-declarative-url-flags.js +50 -0
  331. package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
  332. package/lib/utils/url-public-path-prefix.js +34 -0
  333. package/lib/utils/urls-local-registry.js +220 -0
  334. package/lib/utils/validation-report-tty-kit.js +77 -0
  335. package/lib/utils/validation-run-poll.js +112 -0
  336. package/lib/utils/validation-run-post-retry.js +85 -0
  337. package/lib/utils/validation-run-request.js +116 -0
  338. package/lib/utils/variable-transformer.js +21 -4
  339. package/lib/utils/yaml-preserve.js +33 -14
  340. package/lib/validation/datasource-warnings.js +56 -0
  341. package/lib/validation/env-template-auth.js +1 -1
  342. package/lib/validation/external-manifest-validator.js +27 -7
  343. package/lib/validation/validate-display.js +37 -31
  344. package/lib/validation/validate-external-cert-sync.js +23 -0
  345. package/lib/validation/validate.js +8 -14
  346. package/lib/validation/validator-unresolved-placeholders.js +98 -0
  347. package/lib/validation/validator.js +22 -65
  348. package/lib/validation/wizard-config-validator.js +2 -1
  349. package/package.json +9 -4
  350. package/scripts/check-datasource-test-run-schema-sync.js +34 -0
  351. package/scripts/diagnose-cli.js +150 -0
  352. package/scripts/install-local.js +307 -55
  353. package/scripts/pnpm-global-remove.js +48 -0
  354. package/templates/README.md +15 -2
  355. package/templates/applications/dataplane/application.yaml +52 -2
  356. package/templates/applications/dataplane/env.template +79 -17
  357. package/templates/applications/dataplane/rbac.yaml +8 -0
  358. package/templates/applications/keycloak/application.yaml +9 -1
  359. package/templates/applications/keycloak/env.template +15 -6
  360. package/templates/applications/miso-controller/application.yaml +10 -2
  361. package/templates/applications/miso-controller/env.template +42 -12
  362. package/templates/applications/miso-controller/rbac.yaml +5 -0
  363. package/templates/external-system/README.md.hbs +20 -7
  364. package/templates/external-system/deploy.js.hbs +5 -5
  365. package/templates/external-system/external-datasource.yaml.hbs +197 -118
  366. package/templates/infra/compose.yaml.hbs +33 -16
  367. package/templates/infra/servers.json.hbs +3 -1
  368. package/templates/python/docker-compose.hbs +16 -0
  369. package/templates/typescript/docker-compose.hbs +16 -0
  370. package/lib/api/external-test.api.js +0 -111
  371. package/lib/schema/env-config.yaml +0 -60
@@ -0,0 +1,428 @@
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 } = 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
+ finalizeUnifiedValidationResult,
20
+ unifiedCliResultFromIntegrationReturn,
21
+ finalizeAfterIntegrationDisplay
22
+ } = require('./datasource-validation-cli');
23
+ const { afterUnifiedValidationCertSync } = require('../certification/post-unified-cert-sync');
24
+ const { resolveAppKeyForDatasource } = require('../datasource/resolve-app');
25
+ const { runDatasourceValidationWatchLoop } = require('../utils/datasource-validation-watch');
26
+ const {
27
+ exitCodeFromDatasourceTestRunEnvelope,
28
+ finalizeDatasourceTestE2ELegacyPath,
29
+ displayDatasourceTestE2EEnvelopeResults
30
+ } = require('./datasource-unified-test-e2e-cli-helpers');
31
+ const {
32
+ datasourceTestHelpAfter,
33
+ datasourceTestIntegrationHelpAfter,
34
+ datasourceTestE2eHelpAfter,
35
+ attachDatasourceWatchOptions,
36
+ attachDatasourceTestCommonOptions,
37
+ attachDatasourceTestE2eExclusiveOptions
38
+ } = require('./datasource-unified-test-cli.options');
39
+
40
+ function integrationBaseDirForLogs(appKey) {
41
+ return path.dirname(getIntegrationPath(appKey));
42
+ }
43
+
44
+ async function writeDatasourceTestDebugLogIfRequested(appKey, datasourceKey, result, options) {
45
+ if (!options || !options.debug) return;
46
+ const requestMeta = {
47
+ datasourceKey,
48
+ runType: 'test',
49
+ includeDebug: includeDebugForRequest(options.debug)
50
+ };
51
+ const envelope = result && typeof result === 'object' ? result.envelope : null;
52
+ const apiError = result && typeof result === 'object' ? result.apiError : null;
53
+ const errorMessage = apiError
54
+ ? apiError.formattedError || apiError.error || 'Request failed'
55
+ : null;
56
+ const data = errorMessage
57
+ ? { request: requestMeta, error: errorMessage }
58
+ : { request: requestMeta, response: envelope };
59
+ const logPath = await writeTestLog(
60
+ appKey,
61
+ data,
62
+ 'test',
63
+ integrationBaseDirForLogs(appKey)
64
+ );
65
+ logger.log(chalk.gray(` Debug log: ${logPath}`));
66
+ }
67
+
68
+ function buildDatasourceTestRunOpts(options) {
69
+ return {
70
+ app: options.app,
71
+ environment: options.env,
72
+ runType: 'test',
73
+ payload: options.payload,
74
+ debug: options.debug,
75
+ verbose: options.verbose,
76
+ timeout: options.timeout,
77
+ async: options.async !== false,
78
+ noAsync: options.async === false,
79
+ sync: options.sync === true
80
+ };
81
+ }
82
+
83
+ function buildDatasourceTestDisplayOpts(options) {
84
+ return {
85
+ json: options.json,
86
+ summary: options.summary,
87
+ warningsAsErrors: options.warningsAsErrors,
88
+ requireCert: options.requireCert,
89
+ debug: options.debug
90
+ };
91
+ }
92
+
93
+ async function runDatasourceUnifiedTestOnceForWatch(datasourceKey, runOpts, displayOpts, certCliOptions = {}) {
94
+ try {
95
+ const result = await runUnifiedDatasourceValidation(datasourceKey, runOpts);
96
+ const exitCode = finalizeUnifiedValidationResult(result, displayOpts);
97
+ await afterUnifiedValidationCertSync(exitCode, datasourceKey, certCliOptions, 'datasource test');
98
+ return {
99
+ exitCode,
100
+ envelope: result.envelope
101
+ };
102
+ } catch (err) {
103
+ logger.error(formatBlockingError('Datasource test failed:'), err.message);
104
+ return { exitCode: 4, envelope: null };
105
+ }
106
+ }
107
+
108
+ async function datasourceTestCommandAction(datasourceKey, options) {
109
+ const runOpts = buildDatasourceTestRunOpts(options);
110
+ const displayOpts = buildDatasourceTestDisplayOpts(options);
111
+ try {
112
+ if (options.watch) {
113
+ const { appKey } = await resolveAppKeyForDatasource(datasourceKey, options.app);
114
+ await runDatasourceValidationWatchLoop({
115
+ appKey,
116
+ extraPaths: options.watchPath || [],
117
+ includeApplicationYaml: options.watchApplicationYaml === true,
118
+ watchCi: options.watchCi === true,
119
+ watchFullDiff: options.watchFullDiff === true,
120
+ runOnce: async() => {
121
+ const result = await runUnifiedDatasourceValidation(datasourceKey, runOpts);
122
+ await writeDatasourceTestDebugLogIfRequested(appKey, datasourceKey, result, options);
123
+ const exitCode = finalizeUnifiedValidationResult(result, displayOpts);
124
+ await afterUnifiedValidationCertSync(exitCode, datasourceKey, options, 'datasource test (watch)');
125
+ return {
126
+ exitCode,
127
+ envelope: result.envelope
128
+ };
129
+ }
130
+ });
131
+ return;
132
+ }
133
+ const result = await runUnifiedDatasourceValidation(datasourceKey, runOpts);
134
+ if (options.debug) {
135
+ try {
136
+ const { appKey } = await resolveAppKeyForDatasource(datasourceKey, options.app);
137
+ await writeDatasourceTestDebugLogIfRequested(appKey, datasourceKey, result, options);
138
+ } catch (e) {
139
+ logger.warn(chalk.yellow(`⚠ Could not write debug log: ${e.message}`));
140
+ }
141
+ }
142
+ const exitCode = finalizeUnifiedValidationResult(result, displayOpts);
143
+ await afterUnifiedValidationCertSync(exitCode, datasourceKey, options, 'datasource test');
144
+ process.exit(exitCode);
145
+ } catch (error) {
146
+ logger.error(formatBlockingError('Datasource test failed:'), error.message);
147
+ process.exit(4);
148
+ }
149
+ }
150
+
151
+ function chainDatasourceTestCommand(datasource) {
152
+ const cmd = datasource
153
+ .command('test <datasourceKey>')
154
+ .description('Structural/policy validation for one datasource (unified dataplane API, runType=test)');
155
+ attachDatasourceTestCommonOptions(cmd, {
156
+ includeNoAsync: true,
157
+ verboseHelp: 'Set explain=true on validation request',
158
+ timeoutHelp: 'Aggregate timeout for POST + polls'
159
+ });
160
+ return cmd.addHelpText('after', datasourceTestHelpAfter());
161
+ }
162
+
163
+ function setupDatasourceTestCommand(datasource) {
164
+ // watch flags are already attached by attachDatasourceTestCommonOptions()
165
+ chainDatasourceTestCommand(datasource).action(datasourceTestCommandAction);
166
+ }
167
+
168
+ function buildIntegrationTestOpts(options) {
169
+ return {
170
+ app: options.app,
171
+ payload: options.payload,
172
+ environment: options.env,
173
+ debug: options.debug,
174
+ verbose: options.verbose,
175
+ timeout: options.timeout,
176
+ sync: options.sync === true
177
+ };
178
+ }
179
+
180
+ function buildIntegrationUnifiedDisplayOpts(options) {
181
+ return {
182
+ json: options.json,
183
+ summary: options.summary,
184
+ warningsAsErrors: options.warningsAsErrors,
185
+ requireCert: options.requireCert,
186
+ debug: options.debug
187
+ };
188
+ }
189
+
190
+ async function runIntegrationOnceForWatch(datasourceKey, integOpts, options, unifiedDisplayOpts) {
191
+ try {
192
+ const result = await runDatasourceTestIntegration(datasourceKey, integOpts);
193
+ const unifiedModes =
194
+ options.json || options.summary || options.warningsAsErrors || options.requireCert;
195
+ if (unifiedModes) {
196
+ const uni = unifiedCliResultFromIntegrationReturn(result);
197
+ const exitCode = finalizeUnifiedValidationResult(uni, unifiedDisplayOpts);
198
+ await afterUnifiedValidationCertSync(exitCode, datasourceKey, options, 'datasource test-integration (watch)');
199
+ return { exitCode, envelope: uni.envelope };
200
+ }
201
+ displayIntegrationTestResults(
202
+ {
203
+ systemKey: result.systemKey || 'unknown',
204
+ datasourceResults: [result],
205
+ success: result.success
206
+ },
207
+ options.verbose,
208
+ { debug: options.debug, runType: 'integration' }
209
+ );
210
+ const exitCode = finalizeAfterIntegrationDisplay(result, {
211
+ warningsAsErrors: unifiedDisplayOpts.warningsAsErrors === true,
212
+ requireCert: unifiedDisplayOpts.requireCert === true
213
+ });
214
+ await afterUnifiedValidationCertSync(exitCode, datasourceKey, options, 'datasource test-integration (watch)');
215
+ return { exitCode, envelope: result.datasourceTestRun || null };
216
+ } catch (err) {
217
+ logger.error(formatBlockingError('Integration test failed:'), err.message);
218
+ return { exitCode: 4, envelope: null };
219
+ }
220
+ }
221
+
222
+ async function integrationTestCommandAction(datasourceKey, options) {
223
+ const integOpts = buildIntegrationTestOpts(options);
224
+ const unifiedDisplayOpts = buildIntegrationUnifiedDisplayOpts(options);
225
+ try {
226
+ if (options.watch) {
227
+ const { appKey } = await resolveAppKeyForDatasource(datasourceKey, options.app);
228
+ await runDatasourceValidationWatchLoop({
229
+ appKey,
230
+ extraPaths: options.watchPath || [],
231
+ includeApplicationYaml: options.watchApplicationYaml === true,
232
+ watchCi: options.watchCi === true,
233
+ watchFullDiff: options.watchFullDiff === true,
234
+ runOnce: () => runIntegrationOnceForWatch(datasourceKey, integOpts, options, unifiedDisplayOpts)
235
+ });
236
+ return;
237
+ }
238
+ const result = await runDatasourceTestIntegration(datasourceKey, integOpts);
239
+ const unifiedModes =
240
+ options.json || options.summary || options.warningsAsErrors || options.requireCert;
241
+ if (unifiedModes) {
242
+ const exitCode = finalizeUnifiedValidationResult(
243
+ unifiedCliResultFromIntegrationReturn(result),
244
+ unifiedDisplayOpts
245
+ );
246
+ await afterUnifiedValidationCertSync(exitCode, datasourceKey, options, 'datasource test-integration');
247
+ process.exit(exitCode);
248
+ return;
249
+ }
250
+ displayIntegrationTestResults(
251
+ {
252
+ systemKey: result.systemKey || 'unknown',
253
+ datasourceResults: [result],
254
+ success: result.success
255
+ },
256
+ options.verbose,
257
+ { debug: options.debug, runType: 'integration' }
258
+ );
259
+ const integExit = finalizeAfterIntegrationDisplay(result, {
260
+ warningsAsErrors: unifiedDisplayOpts.warningsAsErrors === true,
261
+ requireCert: unifiedDisplayOpts.requireCert === true
262
+ });
263
+ await afterUnifiedValidationCertSync(integExit, datasourceKey, options, 'datasource test-integration');
264
+ process.exit(integExit);
265
+ } catch (error) {
266
+ logger.error(formatBlockingError('Integration test failed:'), error.message);
267
+ process.exit(4);
268
+ }
269
+ }
270
+
271
+ function chainDatasourceTestIntegrationCommand(datasource) {
272
+ const cmd = datasource
273
+ .command('test-integration <datasourceKey>')
274
+ .description('Integration test one datasource (unified validation API, runType=integration)');
275
+ attachDatasourceTestCommonOptions(cmd, {
276
+ includeNoAsync: false,
277
+ debugHelp: 'includeDebug + log under integration/<systemKey>/logs/; TTY appendix: summary, full, or raw'
278
+ });
279
+ return cmd.addHelpText('after', datasourceTestIntegrationHelpAfter());
280
+ }
281
+
282
+ function setupDatasourceTestIntegrationCommand(datasource) {
283
+ // watch flags are already attached by attachDatasourceTestCommonOptions()
284
+ chainDatasourceTestIntegrationCommand(datasource).action(integrationTestCommandAction);
285
+ }
286
+
287
+ /**
288
+ * @param {string} datasourceKey
289
+ * @param {Object} options
290
+ * @returns {Promise<{ exitCode: number, envelope: Object|null }>}
291
+ */
292
+ async function runDatasourceTestE2ECliOnce(datasourceKey, options) {
293
+ const data = await runDatasourceTestE2E(datasourceKey, {
294
+ app: options.app,
295
+ environment: options.env,
296
+ debug: options.debug,
297
+ verbose: options.verbose,
298
+ async: options.async !== false,
299
+ testCrud: options.testCrud,
300
+ recordId: options.recordId,
301
+ cleanup: options.cleanup,
302
+ primaryKeyValue: options.primaryKeyValue,
303
+ minVectorHits: options.minVectorHits,
304
+ minProcessed: options.minProcessed,
305
+ minRecordCount: options.minRecordCount,
306
+ timeout: options.timeout,
307
+ capabilityKey: options.capability,
308
+ sync: options.sync === true
309
+ });
310
+ const unifiedModes =
311
+ options.json || options.summary || options.warningsAsErrors || options.requireCert;
312
+ if (unifiedModes && data.datasourceTestRun) {
313
+ const exitCode = finalizeUnifiedValidationResult(
314
+ {
315
+ apiError: null,
316
+ pollTimedOut: false,
317
+ incompleteNoAsync: false,
318
+ envelope: data.datasourceTestRun
319
+ },
320
+ {
321
+ json: options.json,
322
+ summary: options.summary,
323
+ warningsAsErrors: options.warningsAsErrors,
324
+ requireCert: options.requireCert,
325
+ debug: options.debug,
326
+ requestedCapabilityKey: options.capability,
327
+ strictCapabilityScope: options.strictCapabilityScope === true
328
+ }
329
+ );
330
+ return { exitCode, envelope: data.datasourceTestRun };
331
+ }
332
+ const env = data.datasourceTestRun;
333
+ if (env && !unifiedModes) {
334
+ displayDatasourceTestE2EEnvelopeResults(datasourceKey, env, options);
335
+ const exitCode = exitCodeFromDatasourceTestRunEnvelope(env, options);
336
+ return { exitCode: exitCode === null ? 1 : exitCode, envelope: env };
337
+ }
338
+ const exitCode = finalizeDatasourceTestE2ELegacyPath(data, options);
339
+ return { exitCode, envelope: data.datasourceTestRun || null };
340
+ }
341
+
342
+ async function runDatasourceTestE2ECliAction(datasourceKey, options) {
343
+ const { exitCode } = await runDatasourceTestE2ECliOnce(datasourceKey, options);
344
+ await afterUnifiedValidationCertSync(exitCode, datasourceKey, options, 'datasource test-e2e');
345
+ process.exit(exitCode);
346
+ }
347
+
348
+ async function e2eTestCommandAction(datasourceKey, capabilityKey, options) {
349
+ const optObj = options && typeof options === 'object' ? options : {};
350
+ const capFromArg = typeof capabilityKey === 'string' ? capabilityKey.trim() : '';
351
+ const capFromFlag = optObj.capability !== undefined && optObj.capability !== null
352
+ ? String(optObj.capability).trim()
353
+ : '';
354
+ const requestedCapability = capFromArg || capFromFlag;
355
+ if (capFromArg && capFromFlag && capFromArg !== capFromFlag) {
356
+ logger.warn(
357
+ chalk.yellow('⚠ Capability mismatch:'),
358
+ `using positional '${capFromArg}' instead of --capability '${capFromFlag}'.`
359
+ );
360
+ }
361
+ const mergedOptions = { ...optObj, capability: requestedCapability || undefined };
362
+ try {
363
+ if (mergedOptions.watch) {
364
+ const { appKey } = await resolveAppKeyForDatasource(datasourceKey, mergedOptions.app);
365
+ await runDatasourceValidationWatchLoop({
366
+ appKey,
367
+ extraPaths: mergedOptions.watchPath || [],
368
+ includeApplicationYaml: mergedOptions.watchApplicationYaml === true,
369
+ watchCi: mergedOptions.watchCi === true,
370
+ watchFullDiff: mergedOptions.watchFullDiff === true,
371
+ runOnce: async() => {
372
+ try {
373
+ const r = await runDatasourceTestE2ECliOnce(datasourceKey, mergedOptions);
374
+ await afterUnifiedValidationCertSync(r.exitCode, datasourceKey, mergedOptions, 'datasource test-e2e (watch)');
375
+ return r;
376
+ } catch (err) {
377
+ logger.error(formatBlockingError('E2E test failed:'), err.message);
378
+ return { exitCode: 3, envelope: null };
379
+ }
380
+ }
381
+ });
382
+ return;
383
+ }
384
+ await runDatasourceTestE2ECliAction(datasourceKey, mergedOptions);
385
+ } catch (error) {
386
+ logger.error(formatBlockingError('E2E test failed:'), error.message);
387
+ process.exit(3);
388
+ }
389
+ }
390
+
391
+ function chainDatasourceTestE2ECommand(datasource) {
392
+ const cmd = datasource
393
+ .command('test-e2e <datasourceKey> [capabilityKey]')
394
+ .description('E2E test one datasource (unified validation API, runType=e2e)');
395
+ attachDatasourceTestCommonOptions(cmd, {
396
+ includeNoAsync: true,
397
+ includePayload: false,
398
+ appHelp: 'Integration folder name (default: resolve from cwd if inside integration/<systemKey>/)',
399
+ verboseHelp: 'Audit / explain-oriented request flags where applicable',
400
+ debugHelp: 'includeDebug + log under integration/<systemKey>/logs/; TTY appendix: summary, full, or raw',
401
+ timeoutHelp:
402
+ 'Wall-clock budget for validation (ms); also raises per-request HTTP wait for slow E2E POST/polls (default 15m)',
403
+ timeoutDefault: String(15 * 60 * 1000)
404
+ });
405
+ return attachDatasourceTestE2eExclusiveOptions(cmd).addHelpText(
406
+ 'after',
407
+ datasourceTestE2eHelpAfter()
408
+ );
409
+ }
410
+
411
+ function setupDatasourceTestE2ECommand(datasource) {
412
+ // watch flags are already attached by attachDatasourceTestCommonOptions()
413
+ chainDatasourceTestE2ECommand(datasource).action(e2eTestCommandAction);
414
+ }
415
+
416
+ module.exports = {
417
+ setupDatasourceTestCommand,
418
+ setupDatasourceTestIntegrationCommand,
419
+ setupDatasourceTestE2ECommand,
420
+ attachDatasourceWatchOptions,
421
+ /** @internal Exported for Jest: CLI action coverage without Commander. */
422
+ runDatasourceUnifiedTestOnceForWatch,
423
+ datasourceTestCommandAction,
424
+ runIntegrationOnceForWatch,
425
+ integrationTestCommandAction,
426
+ runDatasourceTestE2ECliOnce,
427
+ e2eTestCommandAction
428
+ };
@@ -0,0 +1,191 @@
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 my-documents-ds --min-vector-hits 7 -v --debug
46
+ $ aifabrix datasource test-e2e hubspot-users -a test-e2e-hubspot --no-async
47
+ $ aifabrix datasource test-e2e hubspot-users read
48
+
49
+ Notes:
50
+ - For structural/policy validation, use:
51
+ aifabrix datasource test <datasourceKey>
52
+ - For integration pipeline tests, use:
53
+ aifabrix datasource test-integration <datasourceKey>
54
+ - For system-level E2E rollup across datasources, use:
55
+ aifabrix test-e2e <systemKey>
56
+ `;
57
+ }
58
+
59
+ /**
60
+ * @param {object} cmd - Commander command (chainable)
61
+ * @returns {object}
62
+ */
63
+ function attachDatasourceWatchOptions(cmd) {
64
+ return cmd
65
+ .option(
66
+ '--watch',
67
+ 'Re-run when watched files change (debounced; integration tree + optional paths)'
68
+ )
69
+ .option(
70
+ '--watch-path <path>',
71
+ 'Extra file or directory to watch (repeatable)',
72
+ (value, previous) => (Array.isArray(previous) ? previous : []).concat(value),
73
+ []
74
+ )
75
+ .option('--watch-application-yaml', 'Include integration/<app>/application.yaml in the watch set')
76
+ .option('--watch-ci', 'Exit after the first run with the normal exit code (CI one-shot)')
77
+ .option('--watch-full-diff', 'Print full before/after fingerprint lines when the result changes');
78
+ }
79
+
80
+ /**
81
+ * Shared options for datasource-level `test`, `test-integration`, and `test-e2e`.
82
+ *
83
+ * Registration order matches intended `--help` order: core run flags → payload/timeout →
84
+ * `--sync` (pre-run publish) → machine/exit modifiers → async → watch (last before `--help`).
85
+ * Callers must append `addHelpText('after', …)` **after** any command-specific options (e.g. E2E).
86
+ *
87
+ * @param {object} cmd - Commander command (chainable)
88
+ * @param {Object} opts
89
+ * @param {boolean} [opts.includeNoAsync]
90
+ * @param {boolean} [opts.includePayload]
91
+ * @param {string} [opts.appHelp]
92
+ * @param {string} [opts.verboseHelp]
93
+ * @param {string} [opts.debugHelp]
94
+ * @param {string} [opts.timeoutHelp]
95
+ * @param {string} [opts.timeoutDefault]
96
+ * @returns {object}
97
+ */
98
+ function attachDatasourceTestCommonOptions(cmd, opts) {
99
+ const includeNoAsync = opts.includeNoAsync === true;
100
+ const includePayload = opts.includePayload !== false;
101
+
102
+ cmd
103
+ .option(
104
+ '-a, --app <app>',
105
+ opts.appHelp ||
106
+ 'Integration folder name (optional: resolve from cwd or datasource key if single match)'
107
+ )
108
+ .option('-e, --env <env>', 'Environment: dev, tst, or pro')
109
+ .option('-v, --verbose', opts.verboseHelp || 'Explain mode and detailed output where available')
110
+ .option(
111
+ '-d, --debug [level]',
112
+ opts.debugHelp ||
113
+ 'includeDebug on request; TTY appendix: summary (default), full, or raw (not with --json)'
114
+ );
115
+
116
+ if (includePayload) {
117
+ cmd.option('-p, --payload <file>', 'Optional custom payload file (sets payloadTemplate on request)');
118
+ }
119
+
120
+ cmd
121
+ .option(
122
+ '--timeout <ms>',
123
+ opts.timeoutHelp || 'Aggregate timeout for POST + polls (ms)',
124
+ opts.timeoutDefault || '30000'
125
+ )
126
+ .option(
127
+ '--sync',
128
+ 'Publish this datasource JSON from disk to the dataplane before running the test (requires login / same auth as upload)'
129
+ )
130
+ .option('--json', 'Print raw DatasourceTestRun JSON to stdout')
131
+ .option('--summary', 'Print compact summary line')
132
+ .option('--warnings-as-errors', 'Exit 1 when root status is warn')
133
+ .option('--require-cert', 'Exit 2 when certificate missing or not_passed')
134
+ .option(
135
+ '--no-cert-sync',
136
+ 'Skip updating system file certification from the dataplane after a successful run'
137
+ );
138
+
139
+ if (includeNoAsync) {
140
+ cmd.option('--no-async', 'Do not poll; fail if report is not complete in first response');
141
+ }
142
+
143
+ attachDatasourceWatchOptions(cmd);
144
+ return cmd;
145
+ }
146
+
147
+ /**
148
+ * E2E-only Commander flags (kept out of datasource-unified-test-cli.js for file size limits).
149
+ * @param {object} cmd
150
+ * @returns {object}
151
+ */
152
+ function attachDatasourceTestE2eExclusiveOptions(cmd) {
153
+ return cmd
154
+ .option(
155
+ '--min-vector-hits <n>',
156
+ 'Assert at least N vector search hits after sync (e2eOptions.minVectorHits)',
157
+ (v) => parseInt(String(v), 10)
158
+ )
159
+ .option(
160
+ '--min-processed <n>',
161
+ 'Minimum records processed in sync step (e2eOptions.minProcessed)',
162
+ (v) => parseInt(String(v), 10)
163
+ )
164
+ .option(
165
+ '--min-record-count <n>',
166
+ 'Minimum record count assertion (e2eOptions.minRecordCount)',
167
+ (v) => parseInt(String(v), 10)
168
+ )
169
+ .option('--test-crud', 'Enable CRUD lifecycle test (e2eOptions.testCrud)')
170
+ .option('--record-id <id>', 'Record ID for test (e2eOptions.recordId)')
171
+ .option('--no-cleanup', 'Disable cleanup after test (e2eOptions.cleanup: false)')
172
+ .option(
173
+ '--primary-key-value <value|@path>',
174
+ 'Primary key value or path to JSON file (e.g. @pk.json) for e2eOptions.primaryKeyValue'
175
+ )
176
+ .option('--capability <key>', 'Capability drill-down (deprecated; use positional [capabilityKey])')
177
+ .option(
178
+ '--strict-capability-scope',
179
+ 'Exit 1 if a capability drill-down is requested but the report lists more than one capabilities[] row (plan §2.3)'
180
+ );
181
+ }
182
+
183
+ module.exports = {
184
+ datasourceTestHelpAfter,
185
+ datasourceTestIntegrationHelpAfter,
186
+ datasourceTestE2eHelpAfter,
187
+ attachDatasourceWatchOptions,
188
+ attachDatasourceTestCommonOptions,
189
+ attachDatasourceTestE2eExclusiveOptions
190
+ };
191
+