@aifabrix/builder 2.43.0 → 2.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (346) hide show
  1. package/.cursor/rules/anchor-docs.mdc +15 -0
  2. package/README.md +1 -1
  3. package/anchor-docs/README.md +10 -0
  4. package/anchor-docs/_TEMPLATE +24 -0
  5. package/bin/aifabrix.js +13 -4
  6. package/integration/hubspot-test/README.md +31 -0
  7. package/integration/hubspot-test/create-hubspot.js +5 -5
  8. package/integration/hubspot-test/hubspot-test-datasource-company.json +58 -462
  9. package/integration/hubspot-test/hubspot-test-datasource-contact.json +61 -555
  10. package/integration/hubspot-test/hubspot-test-datasource-deal.json +63 -506
  11. package/integration/hubspot-test/hubspot-test-datasource-users.json +42 -83
  12. package/integration/hubspot-test/hubspot-test-deploy.json +3 -3
  13. package/integration/hubspot-test/test-dataplane-down-tests.js +1 -7
  14. package/integration/hubspot-test/test-dataplane-down.js +3 -3
  15. package/integration/hubspot-test/test.js +35 -43
  16. package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
  17. package/integration/roundtrip-test-local/README.md +144 -0
  18. package/integration/roundtrip-test-local/application.yaml +13 -0
  19. package/integration/roundtrip-test-local/env.template +15 -0
  20. package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
  21. package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
  22. package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
  23. package/integration/roundtrip-test-local2/README.md +144 -0
  24. package/integration/roundtrip-test-local2/application.yaml +13 -0
  25. package/integration/roundtrip-test-local2/env.template +15 -0
  26. package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
  27. package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
  28. package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
  29. package/integration/test/wizard.yaml +8 -0
  30. package/jest.config.default.js +10 -0
  31. package/jest.config.integration.fixtures.js +22 -0
  32. package/jest.config.integration.js +21 -18
  33. package/jest.config.isolated.js +10 -0
  34. package/jest.projects.js +288 -0
  35. package/lib/api/datasources-core.api.js +3 -3
  36. package/lib/api/dev-mtls-request.js +110 -0
  37. package/lib/api/dev-server-https.js +145 -0
  38. package/lib/api/dev.api.js +133 -144
  39. package/lib/api/index.js +0 -1
  40. package/lib/api/pipeline.api.js +67 -20
  41. package/lib/api/types/dev.types.js +4 -3
  42. package/lib/api/types/pipeline.types.js +8 -5
  43. package/lib/api/types/validation-run.types.js +56 -0
  44. package/lib/api/validation-run.api.js +99 -0
  45. package/lib/api/validation-runner.js +99 -0
  46. package/lib/app/config.js +1 -1
  47. package/lib/app/deploy-status-display.js +2 -2
  48. package/lib/app/deploy.js +7 -6
  49. package/lib/app/display.js +2 -1
  50. package/lib/app/dockerfile.js +3 -2
  51. package/lib/app/down.js +2 -1
  52. package/lib/app/helpers.js +6 -5
  53. package/lib/app/index.js +27 -8
  54. package/lib/app/list.js +7 -6
  55. package/lib/app/push.js +4 -3
  56. package/lib/app/register.js +16 -7
  57. package/lib/app/rotate-secret.js +14 -13
  58. package/lib/app/run-container-start.js +184 -0
  59. package/lib/app/run-docker-fallback.js +108 -0
  60. package/lib/app/run-env-compose.js +30 -42
  61. package/lib/app/run-helpers.js +49 -126
  62. package/lib/app/run-infra-requirements.js +30 -0
  63. package/lib/app/run-resolve-image.js +21 -0
  64. package/lib/app/run.js +74 -21
  65. package/lib/app/show-display.js +1 -1
  66. package/lib/app/show.js +1 -1
  67. package/lib/build/index.js +13 -10
  68. package/lib/cli/index.js +2 -0
  69. package/lib/cli/setup-app.help.js +67 -0
  70. package/lib/cli/setup-app.js +57 -121
  71. package/lib/cli/setup-app.test-commands.js +179 -0
  72. package/lib/cli/setup-auth.js +19 -5
  73. package/lib/cli/setup-credential-deployment.js +22 -8
  74. package/lib/cli/setup-dev-path-commands.js +124 -0
  75. package/lib/cli/setup-dev.js +170 -113
  76. package/lib/cli/setup-environment.js +7 -1
  77. package/lib/cli/setup-external-system.js +62 -22
  78. package/lib/cli/setup-infra.js +126 -47
  79. package/lib/cli/setup-parameters.js +32 -0
  80. package/lib/cli/setup-secrets.js +106 -8
  81. package/lib/cli/setup-service-user.js +1 -1
  82. package/lib/cli/setup-utility.js +36 -20
  83. package/lib/commands/app-down.js +5 -7
  84. package/lib/commands/app-install.js +14 -7
  85. package/lib/commands/app-logs.js +13 -10
  86. package/lib/commands/app-shell.js +4 -1
  87. package/lib/commands/app-test.js +25 -19
  88. package/lib/commands/app.js +22 -10
  89. package/lib/commands/auth-config.js +6 -6
  90. package/lib/commands/auth-status.js +4 -3
  91. package/lib/commands/credential-env.js +4 -3
  92. package/lib/commands/credential-list.js +5 -4
  93. package/lib/commands/credential-push.js +4 -3
  94. package/lib/commands/datasource-unified-test-cli.js +495 -0
  95. package/lib/commands/datasource-unified-test-cli.options.js +149 -0
  96. package/lib/commands/datasource-validation-cli.js +129 -0
  97. package/lib/commands/datasource.js +105 -98
  98. package/lib/commands/deployment-list.js +6 -5
  99. package/lib/commands/dev-cli-handlers.js +122 -18
  100. package/lib/commands/dev-down.js +4 -3
  101. package/lib/commands/dev-init.js +231 -116
  102. package/lib/commands/dev-show-display.js +473 -0
  103. package/lib/commands/login-credentials.js +3 -2
  104. package/lib/commands/login-device.js +4 -3
  105. package/lib/commands/login.js +5 -4
  106. package/lib/commands/logout.js +8 -7
  107. package/lib/commands/parameters-validate.js +54 -0
  108. package/lib/commands/repair-datasource.js +314 -68
  109. package/lib/commands/repair-env-template.js +2 -2
  110. package/lib/commands/repair.js +21 -3
  111. package/lib/commands/secrets-list.js +23 -12
  112. package/lib/commands/secrets-remove-all.js +220 -0
  113. package/lib/commands/secrets-remove.js +21 -12
  114. package/lib/commands/secrets-set.js +21 -12
  115. package/lib/commands/secrets-validate.js +4 -4
  116. package/lib/commands/secure.js +10 -9
  117. package/lib/commands/service-user.js +26 -25
  118. package/lib/commands/test-e2e-external.js +27 -1
  119. package/lib/commands/up-common.js +3 -2
  120. package/lib/commands/up-dataplane.js +29 -16
  121. package/lib/commands/up-miso.js +19 -29
  122. package/lib/commands/upload.js +138 -39
  123. package/lib/commands/wizard-core-helpers.js +1 -1
  124. package/lib/commands/wizard-dataplane.js +4 -3
  125. package/lib/commands/wizard-helpers.js +3 -3
  126. package/lib/commands/wizard.js +2 -2
  127. package/lib/core/admin-secrets.js +14 -5
  128. package/lib/core/audit-logger.js +12 -4
  129. package/lib/core/config-attach-extensions.js +46 -0
  130. package/lib/core/config-runtime-paths.js +29 -0
  131. package/lib/core/config.js +55 -56
  132. package/lib/core/diff.js +3 -2
  133. package/lib/core/ensure-encryption-key.js +1 -1
  134. package/lib/core/secrets-ensure-infra.js +77 -0
  135. package/lib/core/secrets-ensure.js +120 -64
  136. package/lib/core/secrets-env-write.js +35 -7
  137. package/lib/core/secrets-infra-placeholder-sync.js +61 -0
  138. package/lib/core/secrets.js +200 -37
  139. package/lib/core/templates-env.js +4 -3
  140. package/lib/datasource/abac-validator.js +1 -10
  141. package/lib/datasource/deploy.js +75 -53
  142. package/lib/datasource/field-reference-validator.js +9 -6
  143. package/lib/datasource/integration-context.js +63 -0
  144. package/lib/datasource/list.js +8 -7
  145. package/lib/datasource/log-viewer.js +84 -53
  146. package/lib/datasource/resolve-app.js +4 -4
  147. package/lib/datasource/test-e2e.js +95 -146
  148. package/lib/datasource/test-integration.js +114 -122
  149. package/lib/datasource/unified-validation-run-body.js +65 -0
  150. package/lib/datasource/unified-validation-run-post.js +23 -0
  151. package/lib/datasource/unified-validation-run-resolve.js +43 -0
  152. package/lib/datasource/unified-validation-run.js +92 -0
  153. package/lib/datasource/validate.js +157 -13
  154. package/lib/deployment/deployer.js +4 -3
  155. package/lib/deployment/environment.js +7 -6
  156. package/lib/deployment/push.js +17 -8
  157. package/lib/external-system/delete.js +4 -3
  158. package/lib/external-system/deploy.js +131 -53
  159. package/lib/external-system/download-helpers.js +1 -1
  160. package/lib/external-system/download.js +7 -6
  161. package/lib/external-system/generator.js +92 -6
  162. package/lib/external-system/integration-test-dispatch.js +26 -0
  163. package/lib/external-system/test-execution.js +5 -1
  164. package/lib/external-system/test-helpers.js +0 -4
  165. package/lib/external-system/test-system-level-helpers.js +110 -0
  166. package/lib/external-system/test-system-level.js +83 -44
  167. package/lib/external-system/test.js +59 -8
  168. package/lib/generator/builders.js +23 -11
  169. package/lib/generator/deploy-manifest-azure-kv.js +81 -0
  170. package/lib/generator/external.js +16 -4
  171. package/lib/generator/helpers.js +58 -3
  172. package/lib/generator/index.js +4 -0
  173. package/lib/generator/split-readme.js +12 -7
  174. package/lib/generator/split-variables.js +2 -1
  175. package/lib/generator/split.js +1 -1
  176. package/lib/generator/wizard-readme.js +3 -3
  177. package/lib/generator/wizard.js +8 -8
  178. package/lib/infrastructure/compose.js +60 -6
  179. package/lib/infrastructure/helpers.js +201 -29
  180. package/lib/infrastructure/index.js +28 -17
  181. package/lib/infrastructure/services.js +21 -15
  182. package/lib/internal/fs-real-sync.js +104 -0
  183. package/lib/internal/node-fs.js +98 -0
  184. package/lib/parameters/database-secret-values.js +173 -0
  185. package/lib/parameters/infra-kv-discovery.js +121 -0
  186. package/lib/parameters/infra-parameter-catalog.js +458 -0
  187. package/lib/parameters/infra-parameter-validate.js +64 -0
  188. package/lib/schema/application-schema.json +37 -17
  189. package/lib/schema/datasource-test-run.schema.json +493 -0
  190. package/lib/schema/deployment-rules.yaml +102 -63
  191. package/lib/schema/external-datasource.schema.json +1200 -442
  192. package/lib/schema/external-system.schema.json +181 -5
  193. package/lib/schema/flag-map-validation-run.json +31 -0
  194. package/lib/schema/infra-parameter.schema.json +106 -0
  195. package/lib/schema/infra.parameter.yaml +421 -0
  196. package/lib/schema/type/credential-auth-templates.json +40 -0
  197. package/lib/schema/type/document-storage.json +213 -0
  198. package/lib/schema/type/message-service.json +123 -0
  199. package/lib/schema/type/vector-store.json +88 -0
  200. package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
  201. package/lib/utils/api-error-handler.js +2 -2
  202. package/lib/utils/api.js +49 -14
  203. package/lib/utils/app-register-api.js +3 -2
  204. package/lib/utils/app-register-auth.js +1 -1
  205. package/lib/utils/app-register-config.js +4 -4
  206. package/lib/utils/app-register-display.js +3 -2
  207. package/lib/utils/app-register-validator.js +3 -2
  208. package/lib/utils/app-run-containers.js +26 -22
  209. package/lib/utils/app-scoped-config.js +31 -0
  210. package/lib/utils/app-service-env-from-builder.js +164 -0
  211. package/lib/utils/build-copy.js +1 -1
  212. package/lib/utils/build-helpers.js +20 -20
  213. package/lib/utils/build-resolve-image.js +165 -0
  214. package/lib/utils/cli-layout-chalk.js +8 -0
  215. package/lib/utils/cli-test-layout-chalk.js +267 -0
  216. package/lib/utils/cli-utils.js +88 -11
  217. package/lib/utils/compose-db-passwords.js +138 -0
  218. package/lib/utils/compose-generate-docker-compose.js +216 -0
  219. package/lib/utils/compose-generator.js +197 -291
  220. package/lib/utils/compose-miso-env.js +18 -0
  221. package/lib/utils/compose-traefik-ingress-base.js +158 -0
  222. package/lib/utils/config-paths.js +166 -7
  223. package/lib/utils/config-scoped-resources-preference.js +41 -0
  224. package/lib/utils/controller-deployment-outcome.js +68 -0
  225. package/lib/utils/credential-display.js +2 -2
  226. package/lib/utils/dataplane-pipeline-warning.js +4 -3
  227. package/lib/utils/datasource-test-run-capability-scope.js +43 -0
  228. package/lib/utils/datasource-test-run-debug-display.js +137 -0
  229. package/lib/utils/datasource-test-run-debug-slice.js +93 -0
  230. package/lib/utils/datasource-test-run-display.js +442 -0
  231. package/lib/utils/datasource-test-run-exit.js +58 -0
  232. package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
  233. package/lib/utils/datasource-test-run-report-version.js +51 -0
  234. package/lib/utils/datasource-test-run-schema-sync.js +59 -0
  235. package/lib/utils/datasource-test-run-tty-log.js +81 -0
  236. package/lib/utils/datasource-validation-watch.js +266 -0
  237. package/lib/utils/declarative-url-ports.js +47 -0
  238. package/lib/utils/derive-env-key-from-client-id.js +41 -0
  239. package/lib/utils/dev-ca-install.js +185 -23
  240. package/lib/utils/dev-cert-helper.js +266 -17
  241. package/lib/utils/dev-hosts-helper.js +307 -0
  242. package/lib/utils/dev-init-cert-hints.js +37 -0
  243. package/lib/utils/dev-init-health-messages.js +52 -0
  244. package/lib/utils/dev-init-resolve.js +86 -0
  245. package/lib/utils/dev-init-ssh-merge.js +65 -0
  246. package/lib/utils/dev-ssh-config-helper.js +196 -0
  247. package/lib/utils/dev-user-groups.js +93 -0
  248. package/lib/utils/docker-build.js +42 -17
  249. package/lib/utils/docker-exec.js +28 -0
  250. package/lib/utils/docker-manifest-public-port.js +116 -0
  251. package/lib/utils/docker-not-running-hint.js +52 -0
  252. package/lib/utils/docker.js +98 -11
  253. package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
  254. package/lib/utils/env-config-loader.js +10 -91
  255. package/lib/utils/env-copy.js +19 -10
  256. package/lib/utils/env-map.js +35 -8
  257. package/lib/utils/env-template.js +2 -2
  258. package/lib/utils/environment-scoped-resources.js +144 -0
  259. package/lib/utils/error-formatter.js +92 -13
  260. package/lib/utils/error-formatters/http-status-errors.js +6 -5
  261. package/lib/utils/error-formatters/network-errors.js +2 -1
  262. package/lib/utils/error-formatters/permission-errors.js +2 -1
  263. package/lib/utils/error-formatters/validation-errors.js +2 -1
  264. package/lib/utils/external-readme.js +8 -1
  265. package/lib/utils/external-system-display.js +234 -136
  266. package/lib/utils/external-system-local-test-tty.js +389 -0
  267. package/lib/utils/external-system-readiness-core.js +377 -0
  268. package/lib/utils/external-system-readiness-deploy-display.js +270 -0
  269. package/lib/utils/external-system-readiness-display-internals.js +150 -0
  270. package/lib/utils/external-system-readiness-display.js +186 -0
  271. package/lib/utils/external-system-test-helpers.js +24 -6
  272. package/lib/utils/external-system-validators.js +30 -12
  273. package/lib/utils/health-check-url.js +119 -0
  274. package/lib/utils/health-check.js +59 -25
  275. package/lib/utils/help-builder.js +11 -8
  276. package/lib/utils/image-version.js +4 -8
  277. package/lib/utils/infra-containers.js +4 -7
  278. package/lib/utils/infra-env-defaults.js +162 -0
  279. package/lib/utils/infra-status-display.js +167 -0
  280. package/lib/utils/infra-status.js +16 -8
  281. package/lib/utils/local-secrets.js +3 -4
  282. package/lib/utils/paths.js +134 -47
  283. package/lib/utils/port-resolver.js +10 -23
  284. package/lib/utils/redis-env-scope.js +62 -0
  285. package/lib/utils/register-aifabrix-shell-env.js +204 -0
  286. package/lib/utils/remote-builder-validation.js +99 -0
  287. package/lib/utils/remote-dev-auth.js +117 -21
  288. package/lib/utils/remote-docker-env.js +67 -15
  289. package/lib/utils/remote-secrets-loader.js +13 -4
  290. package/lib/utils/resolve-docker-image-ref.js +124 -0
  291. package/lib/utils/schema-loader.js +22 -9
  292. package/lib/utils/secrets-bash-kv.js +25 -0
  293. package/lib/utils/secrets-generator.js +169 -49
  294. package/lib/utils/secrets-helpers.js +70 -59
  295. package/lib/utils/secrets-kv-scope.js +60 -0
  296. package/lib/utils/secrets-utils.js +32 -38
  297. package/lib/utils/secrets-validation.js +3 -1
  298. package/lib/utils/secrets-yaml-preserve.js +109 -0
  299. package/lib/utils/ssh-key-helper.js +4 -2
  300. package/lib/utils/template-helpers.js +2 -2
  301. package/lib/utils/test-log-writer.js +3 -3
  302. package/lib/utils/token-manager.js +1 -2
  303. package/lib/utils/url-declarative-public-base.js +188 -0
  304. package/lib/utils/url-declarative-resolve-build.js +493 -0
  305. package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
  306. package/lib/utils/url-declarative-resolve.js +220 -0
  307. package/lib/utils/url-declarative-token-parse.js +74 -0
  308. package/lib/utils/url-declarative-url-flags.js +50 -0
  309. package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
  310. package/lib/utils/url-public-path-prefix.js +34 -0
  311. package/lib/utils/urls-local-registry.js +220 -0
  312. package/lib/utils/validation-report-tty-kit.js +77 -0
  313. package/lib/utils/validation-run-poll.js +89 -0
  314. package/lib/utils/validation-run-post-retry.js +73 -0
  315. package/lib/utils/validation-run-request.js +98 -0
  316. package/lib/utils/variable-transformer.js +21 -4
  317. package/lib/utils/yaml-preserve.js +33 -14
  318. package/lib/validation/datasource-warnings.js +56 -0
  319. package/lib/validation/env-template-auth.js +1 -1
  320. package/lib/validation/external-manifest-validator.js +27 -7
  321. package/lib/validation/validate-display.js +37 -31
  322. package/lib/validation/validate.js +4 -13
  323. package/lib/validation/validator-unresolved-placeholders.js +98 -0
  324. package/lib/validation/validator.js +22 -65
  325. package/lib/validation/wizard-config-validator.js +2 -1
  326. package/package.json +7 -3
  327. package/scripts/check-datasource-test-run-schema-sync.js +34 -0
  328. package/scripts/diagnose-cli.js +150 -0
  329. package/scripts/install-local.js +304 -55
  330. package/templates/README.md +15 -2
  331. package/templates/applications/dataplane/application.yaml +52 -2
  332. package/templates/applications/dataplane/env.template +75 -17
  333. package/templates/applications/dataplane/rbac.yaml +8 -0
  334. package/templates/applications/keycloak/application.yaml +9 -1
  335. package/templates/applications/keycloak/env.template +15 -6
  336. package/templates/applications/miso-controller/application.yaml +10 -2
  337. package/templates/applications/miso-controller/env.template +42 -12
  338. package/templates/applications/miso-controller/rbac.yaml +5 -0
  339. package/templates/external-system/README.md.hbs +20 -7
  340. package/templates/external-system/deploy.js.hbs +5 -5
  341. package/templates/external-system/external-datasource.yaml.hbs +197 -118
  342. package/templates/infra/compose.yaml.hbs +20 -4
  343. package/templates/python/docker-compose.hbs +16 -0
  344. package/templates/typescript/docker-compose.hbs +16 -0
  345. package/lib/api/external-test.api.js +0 -111
  346. package/lib/schema/env-config.yaml +0 -60
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @fileoverview Help text blocks for app-level CLI commands.
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ const TEST_HELP_AFTER = `
8
+ Examples:
9
+ # External system (integration/<systemKey>/) — local validation
10
+ $ aifabrix test hubspot
11
+ $ aifabrix test hubspot -v
12
+ $ aifabrix test hubspot -d
13
+
14
+ # Builder app (builder/<app>/) — runs in container
15
+ $ aifabrix test myapp -e dev
16
+ $ aifabrix test myapp -e tst
17
+
18
+ Notes:
19
+ - To run unit test for one datasource, use:
20
+ aifabrix datasource test <datasourceKey>
21
+ - To run integration test, use:
22
+ aifabrix test-integration <app>
23
+ - Option --sync is not supported here (local validation only); use upload or dataplane test commands with --sync.
24
+ `;
25
+
26
+ const TEST_INTEGRATION_HELP_AFTER = `
27
+ Examples:
28
+ # External system (integration/<systemKey>/) — integration health across datasources via dataplane
29
+ $ aifabrix test-integration hubspot
30
+ $ aifabrix test-integration hubspot -v
31
+ $ aifabrix test-integration hubspot -d
32
+
33
+ # Builder app (builder/<app>/) — runs in container
34
+ $ aifabrix test-integration myapp -e dev
35
+ $ aifabrix test-integration myapp -e tst
36
+
37
+ Notes:
38
+ - To run integration test for one datasource, use:
39
+ aifabrix datasource test-integration <datasourceKey>
40
+ - To run E2E test, use:
41
+ aifabrix test-e2e <app>
42
+ - Optional --sync publishes local files to the dataplane first (external integration under integration/<systemKey>/ only).
43
+ `;
44
+
45
+ const TEST_E2E_HELP_AFTER = `
46
+ Examples:
47
+ # External system (integration/<systemKey>/) — E2E across datasources via dataplane
48
+ $ aifabrix test-e2e hubspot
49
+ $ aifabrix test-e2e hubspot -v
50
+ $ aifabrix test-e2e hubspot -d
51
+
52
+ # Builder app (builder/<app>/) — runs in container
53
+ $ aifabrix test-e2e myapp -e dev
54
+ $ aifabrix test-e2e myapp -e tst
55
+
56
+ Notes:
57
+ - To run E2E for one datasource, use:
58
+ aifabrix datasource test-e2e <datasourceKey>
59
+ - Optional --sync publishes local files to the dataplane first (external integration only).
60
+ `;
61
+
62
+ module.exports = {
63
+ TEST_HELP_AFTER,
64
+ TEST_INTEGRATION_HELP_AFTER,
65
+ TEST_E2E_HELP_AFTER
66
+ };
67
+
@@ -1,3 +1,4 @@
1
+ const { formatSuccessParagraph } = require('../utils/cli-test-layout-chalk');
1
2
  /**
2
3
  * CLI application lifecycle command setup (create, wizard, build, run, push, deploy, dockerfile).
3
4
  *
@@ -11,6 +12,24 @@ const path = require('path');
11
12
  const app = require('../app');
12
13
  const logger = require('../utils/logger');
13
14
  const { handleCommandError } = require('../utils/cli-utils');
15
+ const { setupInstallTestE2eLintCommands } = require('./setup-app.test-commands');
16
+
17
+ const CREATE_HELP_AFTER = `
18
+ Examples:
19
+ $ aifabrix create myapi --type webapp -l typescript
20
+ $ aifabrix create mycrm --wizard
21
+ `;
22
+
23
+ const DEPLOY_HELP_AFTER = `
24
+ Examples:
25
+ $ aifabrix deploy myapp
26
+ $ aifabrix deploy myext --local
27
+ `;
28
+
29
+ const PUSH_HELP_AFTER = `
30
+ Example:
31
+ $ aifabrix push myapp -t v1.0.0
32
+ `;
14
33
 
15
34
  /**
16
35
  * Normalize options for external system creation
@@ -102,7 +121,8 @@ async function handleCreateCommand(appName, options) {
102
121
 
103
122
  function setupCreateCommand(program) {
104
123
  program.command('create <app>')
105
- .description('Create new application with configuration files')
124
+ .description('Scaffold builder or external app (flags or --wizard)')
125
+ .addHelpText('after', CREATE_HELP_AFTER)
106
126
  .option('-p, --port <port>', 'Application port', '3000')
107
127
  .option('-d, --database', 'Requires database')
108
128
  .option('-r, --redis', 'Requires Redis')
@@ -142,15 +162,15 @@ Examples:
142
162
  $ aifabrix wizard --config wizard.yaml Run headless from a wizard config file
143
163
  $ aifabrix wizard hubspot-test --debug Enable debug output and save debug manifests on validation failure
144
164
 
145
- Config path: When appName is provided, integration/<appName>/wizard.yaml is used for load/save and error.log.
165
+ Config path: When appName is provided, integration/<systemKey>/wizard.yaml is used for load/save and error.log.
146
166
  To change settings after a run, edit that file and run "aifabrix wizard <app>" again.
147
167
  Headless config must include: appName, mode (create-system|add-datasource), source (type + filePath/url/platform).
148
168
  See integration/hubspot-test/wizard-hubspot-e2e.yaml for an example.`;
149
169
  program.command('wizard [appName]')
150
- .description('Create or extend external systems (OpenAPI, MCP, or known platforms like HubSpot) via guided steps or a config file')
170
+ .description('Guided external system setup (OpenAPI, MCP, HubSpot, ) or headless wizard.yaml')
151
171
  .option('-a, --app <app>', 'Application name (synonym for positional appName)')
152
172
  .option('--config <file>', 'Run headless using a wizard.yaml file (appName, mode, source, credential, preferences)')
153
- .option('--silent', 'Run with saved integration/<app>/wizard.yaml only; no prompts (requires app name and existing wizard.yaml)')
173
+ .option('--silent', 'Run with saved integration/<systemKey>/wizard.yaml only; no prompts (requires app name and existing wizard.yaml)')
154
174
  .option('--debug', 'Enable debug output and save debug manifests on validation failure')
155
175
  .addHelpText('after', wizardHelp)
156
176
  .action(async(positionalAppName, options) => {
@@ -172,9 +192,10 @@ In dev: use --reload for sync and mount (requires remote server with Mutagen, or
172
192
  Examples:
173
193
  $ aifabrix run myapp
174
194
  $ aifabrix run myapp --env tst
195
+ $ aifabrix run myapp --tag v1.0.0
175
196
  $ aifabrix run myapp --reload`;
176
197
  program.command('run <app>')
177
- .description('Run application locally (or remotely on your Docker host)')
198
+ .description('Run app locally or on remote Docker host')
178
199
  .option('-p, --port <port>', 'Override local port')
179
200
  .option('-d, --debug', 'Enable debug output with detailed container information')
180
201
  .option('-t, --tag <tag>', 'Image tag to run (e.g. v1.0.0); overrides application.yaml image.tag')
@@ -193,14 +214,15 @@ Examples:
193
214
 
194
215
  function setupBuildRunLogsDownCommands(program) {
195
216
  program.command('build <app>')
196
- .description('Build container image (auto-detects runtime)')
217
+ .description('Build Docker image (auto-detect runtime)')
197
218
  .option('-l, --language <lang>', 'Override language detection')
198
219
  .option('-f, --force-template', 'Force rebuild from template')
220
+ .option('--no-cache', 'Full Docker rebuild (disable layer cache); use after Dockerfile or context fixes')
199
221
  .option('-t, --tag <tag>', 'Image tag (default: latest). Set image.tag in application.yaml to match for deploy.')
200
222
  .action(async(appName, options) => {
201
223
  try {
202
224
  const imageTag = await app.buildApp(appName, options);
203
- logger.log(`✅ Built image: ${imageTag}`);
225
+ logger.log(`✔ Built image: ${imageTag}`);
204
226
  } catch (error) {
205
227
  handleCommandError(error, 'build');
206
228
  process.exit(1);
@@ -210,7 +232,7 @@ function setupBuildRunLogsDownCommands(program) {
210
232
  registerRunCommand(program);
211
233
 
212
234
  program.command('logs <app>')
213
- .description('Show application container logs (and optional env summary with secrets masked)')
235
+ .description('Tail app container logs (optional env summary; secrets masked)')
214
236
  .option('-f', 'Follow log stream')
215
237
  .option('-t, --tail <lines>', 'Number of lines (default: 100); 0 = full list', '100')
216
238
  .option('-l, --level <level>', 'Show only logs at this level or above (debug|info|warn|error)')
@@ -227,7 +249,7 @@ function setupBuildRunLogsDownCommands(program) {
227
249
  });
228
250
 
229
251
  program.command('down-app <app>')
230
- .description('Stop and remove application container; optionally remove volume and image')
252
+ .description('Stop and remove app container (--volumes removes data volume)')
231
253
  .option('--volumes', 'Remove application Docker volume')
232
254
  .action(async(appName, options) => {
233
255
  try {
@@ -242,7 +264,7 @@ function setupBuildRunLogsDownCommands(program) {
242
264
 
243
265
  function setupShellTestStopCommands(program) {
244
266
  program.command('stop <app>')
245
- .description('Stop and remove application container (alias for down-app)')
267
+ .description('Alias for down-app: stop and remove container')
246
268
  .option('--volumes', 'Remove application Docker volume')
247
269
  .action(async(appName, options) => {
248
270
  try {
@@ -255,7 +277,7 @@ function setupShellTestStopCommands(program) {
255
277
  });
256
278
 
257
279
  program.command('shell <app>')
258
- .description('Open interactive shell in the application container')
280
+ .description('Interactive shell in running or ephemeral container')
259
281
  .option('--env <env>', 'Environment (dev|tst); dev uses running container', 'dev')
260
282
  .action(async(appName, options) => {
261
283
  try {
@@ -266,105 +288,20 @@ function setupShellTestStopCommands(program) {
266
288
  process.exit(1);
267
289
  }
268
290
  });
269
-
270
- program.command('test <app>')
271
- .description('Run tests (builder app: in container; external system: local validation)')
272
- .option('--env <env>', 'For builder app: dev (running container) or tst (ephemeral)', 'dev')
273
- .option('-d, --datasource <key>', 'For external system: test specific datasource only')
274
- .option('-v, --verbose', 'Verbose output')
275
- .action(async(appName, options) => {
276
- try {
277
- const pathsUtil = require('../utils/paths');
278
- const appType = await pathsUtil.detectAppType(appName).catch(() => null);
279
- if (appType && appType.baseDir === 'integration') {
280
- const test = require('../external-system/test');
281
- const results = await test.testExternalSystem(appName, options);
282
- test.displayTestResults(results, options.verbose);
283
- if (!results.valid) process.exit(1);
284
- } else {
285
- const { runAppTest } = require('../commands/app-test');
286
- await runAppTest(appName, { env: options.env });
287
- }
288
- } catch (error) {
289
- handleCommandError(error, 'test');
290
- process.exit(1);
291
- }
292
- });
293
291
  }
294
292
 
295
- async function runTestE2ECommand(appName, options) {
296
- const pathsUtil = require('../utils/paths');
297
- const appType = await pathsUtil.detectAppType(appName).catch(() => null);
298
- if (appType && appType.baseDir === 'integration') {
299
- const { runTestE2EForExternalSystem } = require('../commands/test-e2e-external');
300
- const { success, results } = await runTestE2EForExternalSystem(appName, {
301
- env: options.env,
302
- debug: options.debug,
303
- verbose: options.verbose,
304
- async: options.async !== false
305
- });
306
- results.forEach(r => {
307
- const icon = r.success ? chalk.green('✓') : chalk.red('✗');
308
- const msg = r.error ? `${r.key}: ${r.error}` : r.key;
309
- logger.log(` ${icon} ${msg}`);
310
- });
311
- if (!success) process.exit(1);
312
- return;
313
- }
314
- const { runAppTestE2e } = require('../commands/app-test');
315
- await runAppTestE2e(appName, { env: options.env });
316
- }
317
-
318
- function setupInstallTestE2eLintCommands(program) {
319
- program.command('install <app>')
320
- .description('Install dependencies in container (builder apps only)')
321
- .option('--env <env>', 'dev (running container) or tst (ephemeral with .env)', 'dev')
322
- .action(async(appName, options) => {
323
- try {
324
- const pathsUtil = require('../utils/paths');
325
- const appType = await pathsUtil.detectAppType(appName).catch(() => null);
326
- if (appType && appType.baseDir === 'integration') {
327
- logger.log(chalk.gray('Install is for builder applications only. Use aifabrix shell <app> to run commands in external setups.'));
328
- return;
329
- }
330
- const { runAppInstall } = require('../commands/app-install');
331
- await runAppInstall(appName, { env: options.env });
332
- } catch (error) {
333
- handleCommandError(error, 'install');
334
- process.exit(1);
335
- }
336
- });
337
-
338
- program.command('test-e2e <app>')
339
- .description('Run e2e tests (builder: in container; external system: all datasources via dataplane)')
340
- .option('-e, --env <env>', 'Environment: dev, tst, or pro (builder: dev/tst for container)')
341
- .option('-v, --verbose', 'Show detailed step output and poll progress')
342
- .option('--debug', 'Include debug output and write log to integration/<app>/logs/')
343
- .option('--no-async', 'Use sync mode (no polling); single POST per datasource')
344
- .action(async(appName, options) => {
345
- try {
346
- await runTestE2ECommand(appName, options);
347
- } catch (error) {
348
- handleCommandError(error, 'test-e2e');
349
- process.exit(1);
350
- }
351
- });
352
-
353
- program.command('lint <app>')
354
- .description('Run lint in container (builder apps only)')
355
- .option('--env <env>', 'dev (running container) or tst (ephemeral with .env)', 'dev')
293
+ function setupDockerfileGenerateCommand(program) {
294
+ program.command('dockerfile <app>')
295
+ .description('Generate Dockerfile from detected runtime')
296
+ .option('-l, --language <lang>', 'Override language detection')
297
+ .option('-f, --force', 'Overwrite existing Dockerfile')
356
298
  .action(async(appName, options) => {
357
299
  try {
358
- const pathsUtil = require('../utils/paths');
359
- const appType = await pathsUtil.detectAppType(appName).catch(() => null);
360
- if (appType && appType.baseDir === 'integration') {
361
- logger.log(chalk.gray('lint is for builder applications only. Use aifabrix shell <app> then make lint or pnpm lint.'));
362
- return;
363
- }
364
- const { runAppLint } = require('../commands/app-test');
365
- await runAppLint(appName, { env: options.env });
300
+ const dockerfilePath = await app.generateDockerfileForApp(appName, options);
301
+ logger.log(formatSuccessParagraph('Dockerfile generated successfully!'));
302
+ logger.log(chalk.gray(`Location: ${dockerfilePath}`));
366
303
  } catch (error) {
367
- handleCommandError(error, 'lint');
304
+ handleCommandError(error, 'dockerfile');
368
305
  process.exit(1);
369
306
  }
370
307
  });
@@ -373,6 +310,7 @@ function setupInstallTestE2eLintCommands(program) {
373
310
  function setupPushDeployDockerfileCommands(program) {
374
311
  program.command('push <app>')
375
312
  .description('Push image to Azure Container Registry')
313
+ .addHelpText('after', PUSH_HELP_AFTER)
376
314
  .option('-r, --registry <registry>', 'ACR registry URL (overrides application.yaml)')
377
315
  .option('-t, --tag <tag>', 'Image tag(s) - comma-separated for multiple (default: latest)')
378
316
  .action(async(appName, options) => {
@@ -385,15 +323,26 @@ function setupPushDeployDockerfileCommands(program) {
385
323
  });
386
324
 
387
325
  program.command('deploy <app>')
388
- .description('Deploy to Azure or locally via Miso Controller')
326
+ .description('Deploy via Miso Controller (Azure or --local)')
327
+ .addHelpText('after', DEPLOY_HELP_AFTER)
389
328
  .option('--local', 'Send manifest to controller then run app locally (app: same as aifabrix run <app>; external: restart dataplane)')
390
329
  .option('--client-id <id>', 'Client ID (overrides config)')
391
330
  .option('--client-secret <secret>', 'Client Secret (overrides config)')
392
331
  .option('--poll', 'Poll for deployment status', true)
393
332
  .option('--no-poll', 'Do not poll for status')
333
+ .option('--probe', 'After external deploy, run dataplane runtime checks (validation/run); slower')
334
+ .option('--probe-timeout <ms>', 'Timeout for --probe on external deploy (default: 120000)', '120000')
394
335
  .action(async(appName, options) => {
395
336
  try {
396
- const opts = { ...options, local: !!options.local };
337
+ const probeTimeout =
338
+ options.probeTimeout === undefined || options.probeTimeout === null
339
+ ? 120000
340
+ : Number(options.probeTimeout);
341
+ const opts = {
342
+ ...options,
343
+ local: !!options.local,
344
+ probeTimeout: Number.isFinite(probeTimeout) ? probeTimeout : 120000
345
+ };
397
346
  const outcome = await app.deployApp(appName, opts);
398
347
  if (opts.local && outcome) {
399
348
  if (outcome.usedExternalDeploy) await app.restartApp('dataplane');
@@ -405,20 +354,7 @@ function setupPushDeployDockerfileCommands(program) {
405
354
  }
406
355
  });
407
356
 
408
- program.command('dockerfile <app>')
409
- .description('Generate Dockerfile for an application')
410
- .option('-l, --language <lang>', 'Override language detection')
411
- .option('-f, --force', 'Overwrite existing Dockerfile')
412
- .action(async(appName, options) => {
413
- try {
414
- const dockerfilePath = await app.generateDockerfileForApp(appName, options);
415
- logger.log(chalk.green('\n✅ Dockerfile generated successfully!'));
416
- logger.log(chalk.gray(`Location: ${dockerfilePath}`));
417
- } catch (error) {
418
- handleCommandError(error, 'dockerfile');
419
- process.exit(1);
420
- }
421
- });
357
+ setupDockerfileGenerateCommand(program);
422
358
  }
423
359
 
424
360
  /**
@@ -0,0 +1,179 @@
1
+ /**
2
+ * @fileoverview CLI test/install/lint command setup (builder app + external integration dispatch).
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ const chalk = require('chalk');
8
+ const logger = require('../utils/logger');
9
+ const { handleCommandError } = require('../utils/cli-utils');
10
+ const { TEST_HELP_AFTER, TEST_E2E_HELP_AFTER } = require('./setup-app.help');
11
+
12
+ function setupTestCommand(program) {
13
+ program.command('test <app>')
14
+ .description('Tests: builder in container; external = local validation')
15
+ .option('-e, --env <env>', 'For builder app: dev (running container) or tst (ephemeral)', 'dev')
16
+ .option('-v, --verbose', 'Verbose output')
17
+ .option('-d, --debug', 'Write debug log to integration/<systemKey>/logs/ (external only)')
18
+ .option(
19
+ '--sync',
20
+ 'Not supported for this command (local validation only). Use aifabrix upload <systemKey> or dataplane test commands with --sync.'
21
+ )
22
+ .addHelpText('after', TEST_HELP_AFTER)
23
+ .action(async(appName, options, cmd) => {
24
+ try {
25
+ const rawArgs = Array.isArray(cmd?.rawArgs) ? cmd.rawArgs : [];
26
+ const envExplicit = rawArgs.includes('-e') || rawArgs.includes('--env');
27
+ const pathsUtil = require('../utils/paths');
28
+ const appType = await pathsUtil.detectAppType(appName).catch(() => null);
29
+ if (options.sync === true) {
30
+ throw new Error(
31
+ 'Option --sync is not supported for aifabrix test (local or container runs do not publish to the dataplane). ' +
32
+ 'Use: aifabrix upload <systemKey>, then aifabrix test-integration <systemKey> --sync or aifabrix datasource test-integration <datasourceKey> --sync.'
33
+ );
34
+ }
35
+ if (appType && appType.baseDir === 'integration') {
36
+ const test = require('../external-system/test');
37
+ const externalOpts = {
38
+ ...options,
39
+ // Keep help default but don't override auth/env behavior unless user explicitly set it.
40
+ env: envExplicit ? options.env : undefined
41
+ };
42
+ const results = await test.testExternalSystem(appName, externalOpts);
43
+ test.displayTestResults(results, options.verbose, appName);
44
+ if (!results.valid) process.exit(1);
45
+ return;
46
+ }
47
+ const { runAppTest } = require('../commands/app-test');
48
+ await runAppTest(appName, { env: options.env });
49
+ } catch (error) {
50
+ handleCommandError(error, 'test');
51
+ process.exit(1);
52
+ }
53
+ });
54
+ }
55
+
56
+ async function runTestE2ECommand(appName, options) {
57
+ const pathsUtil = require('../utils/paths');
58
+ const appType = await pathsUtil.detectAppType(appName).catch(() => null);
59
+ if (options.sync === true && appType && appType.baseDir === 'builder') {
60
+ throw new Error(
61
+ 'Option --sync applies only to external integration E2E (integration/<systemKey>/). ' +
62
+ 'Remove --sync for builder app E2E, or use aifabrix upload from the integration folder first.'
63
+ );
64
+ }
65
+ if (appType && appType.baseDir === 'integration') {
66
+ const { runTestE2EForExternalSystem } = require('../commands/test-e2e-external');
67
+ const { success, results } = await runTestE2EForExternalSystem(appName, {
68
+ env: options.env,
69
+ debug: options.debug,
70
+ verbose: options.verbose,
71
+ async: options.async !== false,
72
+ sync: options.sync === true
73
+ });
74
+ const { displayIntegrationTestResults } = require('../utils/external-system-display');
75
+ displayIntegrationTestResults(
76
+ {
77
+ systemKey: appName,
78
+ success,
79
+ datasourceResults: results.map(r => ({
80
+ key: r.key,
81
+ success: r.success,
82
+ error: r.error,
83
+ skipped: false,
84
+ datasourceTestRun: r.datasourceTestRun
85
+ }))
86
+ },
87
+ options.verbose,
88
+ { debug: options.debug, runType: 'e2e' }
89
+ );
90
+ if (!success) process.exit(1);
91
+ return;
92
+ }
93
+ const { runAppTestE2e } = require('../commands/app-test');
94
+ await runAppTestE2e(appName, { env: options.env });
95
+ }
96
+
97
+ function setupInstallCommand(program) {
98
+ program.command('install <app>')
99
+ .description('Install deps in container (builder apps only)')
100
+ .option('--env <env>', 'dev (running container) or tst (ephemeral with .env)', 'dev')
101
+ .action(async(appName, options) => {
102
+ try {
103
+ const pathsUtil = require('../utils/paths');
104
+ const appType = await pathsUtil.detectAppType(appName).catch(() => null);
105
+ if (appType && appType.baseDir === 'integration') {
106
+ logger.log(
107
+ chalk.gray('Install is for builder applications only. Use aifabrix shell <app> to run commands in external setups.')
108
+ );
109
+ return;
110
+ }
111
+ const { runAppInstall } = require('../commands/app-install');
112
+ await runAppInstall(appName, { env: options.env });
113
+ } catch (error) {
114
+ handleCommandError(error, 'install');
115
+ process.exit(1);
116
+ }
117
+ });
118
+ }
119
+
120
+ function setupTestE2eCommand(program) {
121
+ program.command('test-e2e <app>')
122
+ .description('E2E: builder in container; external = all datasources via dataplane')
123
+ .option('-e, --env <env>', 'Environment: dev, tst, or pro (builder: dev/tst for container)', 'dev')
124
+ .option('-v, --verbose', 'Show detailed step output and poll progress')
125
+ .option('-d, --debug', 'Include debug output and write log to integration/<systemKey>/logs/')
126
+ .option(
127
+ '--sync',
128
+ 'Publish local system and datasource files to the dataplane before running E2E (same as aifabrix upload <systemKey>; external integration only)'
129
+ )
130
+ .addHelpText('after', TEST_E2E_HELP_AFTER)
131
+ .action(async(appName, options, cmd) => {
132
+ try {
133
+ const rawArgs = Array.isArray(cmd?.rawArgs) ? cmd.rawArgs : [];
134
+ const envExplicit = rawArgs.includes('-e') || rawArgs.includes('--env');
135
+ const externalOpts = {
136
+ ...options,
137
+ env: envExplicit ? options.env : undefined,
138
+ async: true // system-level command surface omits --no-async; always poll for completeness
139
+ };
140
+ await runTestE2ECommand(appName, externalOpts);
141
+ } catch (error) {
142
+ handleCommandError(error, 'test-e2e');
143
+ process.exit(1);
144
+ }
145
+ });
146
+ }
147
+
148
+ function setupLintCommand(program) {
149
+ program.command('lint <app>')
150
+ .description('Lint in container (builder apps only)')
151
+ .option('--env <env>', 'dev (running container) or tst (ephemeral with .env)', 'dev')
152
+ .action(async(appName, options) => {
153
+ try {
154
+ const pathsUtil = require('../utils/paths');
155
+ const appType = await pathsUtil.detectAppType(appName).catch(() => null);
156
+ if (appType && appType.baseDir === 'integration') {
157
+ logger.log(chalk.gray('lint is for builder applications only. Use aifabrix shell <app> then make lint or pnpm lint.'));
158
+ return;
159
+ }
160
+ const { runAppLint } = require('../commands/app-test');
161
+ await runAppLint(appName, { env: options.env });
162
+ } catch (error) {
163
+ handleCommandError(error, 'lint');
164
+ process.exit(1);
165
+ }
166
+ });
167
+ }
168
+
169
+ function setupInstallTestE2eLintCommands(program) {
170
+ setupInstallCommand(program);
171
+ setupTestCommand(program);
172
+ setupTestE2eCommand(program);
173
+ setupLintCommand(program);
174
+ }
175
+
176
+ module.exports = {
177
+ setupInstallTestE2eLintCommands
178
+ };
179
+
@@ -14,9 +14,22 @@ const { handleLogout } = require('../commands/logout');
14
14
  const { handleAuthStatus } = require('../commands/auth-status');
15
15
  const { handleAuthConfig } = require('../commands/auth-config');
16
16
 
17
+ const LOGIN_HELP_AFTER = `
18
+ Examples:
19
+ $ aifabrix login
20
+ $ aifabrix login -m credentials -a myapp -e dev
21
+ `;
22
+
23
+ const AUTH_HELP_AFTER = `
24
+ Without options: show auth status (same as: aifabrix auth status).
25
+ With --set-controller or --set-environment: write defaults to config.yaml.
26
+ Subcommand: auth status [--validate] for CI/scripts.
27
+ `;
28
+
17
29
  function setupLoginCommand(program) {
18
30
  program.command('login')
19
- .description('Authenticate with Miso Controller')
31
+ .description('Sign in to Miso Controller (device or credentials flow)')
32
+ .addHelpText('after', LOGIN_HELP_AFTER)
20
33
  .option('-c, --controller <url>', 'Controller URL (default: from config or developer ID, e.g. http://localhost:3000)')
21
34
  .option('-m, --method <method>', 'Authentication method (device|credentials)', 'device')
22
35
  .option('-a, --app <app>', 'Application name (required for credentials method, reads from secrets.local.yaml)')
@@ -29,7 +42,7 @@ function setupLoginCommand(program) {
29
42
  try {
30
43
  await handleLogin(options);
31
44
  } catch (error) {
32
- logger.error(chalk.red('\n Login failed:'), error.message);
45
+ logger.error(chalk.red('\n Login failed:'), error.message);
33
46
  process.exit(1);
34
47
  }
35
48
  });
@@ -37,7 +50,7 @@ function setupLoginCommand(program) {
37
50
 
38
51
  function setupLogoutCommand(program) {
39
52
  program.command('logout')
40
- .description('Clear authentication tokens')
53
+ .description('Clear stored tokens (optional filter by controller/env/app)')
41
54
  .option('-c, --controller <url>', 'Clear device tokens for specific controller')
42
55
  .option('-e, --environment <env>', 'Clear client tokens for specific environment')
43
56
  .option('-a, --app <app>', 'Clear client tokens for specific app (requires --environment)')
@@ -61,7 +74,8 @@ function setupAuthSubcommands(program) {
61
74
  }
62
75
  };
63
76
  const auth = program.command('auth')
64
- .description('Authentication status and config (controller, environment)')
77
+ .description('Show auth status or set default controller/environment')
78
+ .addHelpText('after', AUTH_HELP_AFTER)
65
79
  .option('--set-controller <url>', 'Set default controller URL in config')
66
80
  .option('--set-environment <env>', 'Set default environment in config')
67
81
  .action(async(options) => {
@@ -82,7 +96,7 @@ function setupAuthSubcommands(program) {
82
96
  }
83
97
  });
84
98
  auth.command('status')
85
- .description('Display authentication status for current controller and environment')
99
+ .description('Show tokens/session for current controller and environment')
86
100
  .option('--validate', 'Exit with code 1 when not authenticated (for scripted use, e.g. manual test setup)')
87
101
  .action(authStatusHandler);
88
102
  }
@@ -15,10 +15,22 @@ const { runCredentialEnv } = require('../commands/credential-env');
15
15
  const { runCredentialPush } = require('../commands/credential-push');
16
16
  const { runDeploymentList } = require('../commands/deployment-list');
17
17
 
18
+ const CREDENTIAL_HELP_AFTER = `
19
+ Subcommands:
20
+ env <systemKey> Prompt for KV_* values → integration/<key>/.env
21
+ push <systemKey> Upload secrets from .env to Dataplane
22
+ list List credentials (pagination: --page-size)
23
+ `;
24
+
25
+ const DEPLOYMENT_HELP_AFTER = `
26
+ Subcommand:
27
+ list Recent deployments for the current environment
28
+ `;
29
+
18
30
  function setupCredentialEnvAndPush(credential) {
19
31
  credential
20
- .command('env <system-key>')
21
- .description('Prompt for KV_* credential values and write integration/<system-key>/.env')
32
+ .command('env <systemKey>')
33
+ .description('Interactive KV_* prompts integration/<key>/.env')
22
34
  .action(async(systemKey, _options) => {
23
35
  try {
24
36
  await runCredentialEnv(systemKey);
@@ -29,8 +41,8 @@ function setupCredentialEnvAndPush(credential) {
29
41
  }
30
42
  });
31
43
  credential
32
- .command('push <system-key>')
33
- .description('Push credential secrets from .env to Dataplane (KV_* vars)')
44
+ .command('push <systemKey>')
45
+ .description('Push KV_* secrets from .env to Dataplane')
34
46
  .action(async(systemKey, _options) => {
35
47
  try {
36
48
  await runCredentialPush(systemKey);
@@ -49,11 +61,12 @@ function setupCredentialEnvAndPush(credential) {
49
61
  function setupCredentialDeploymentCommands(program) {
50
62
  const credential = program
51
63
  .command('credential')
52
- .description('Manage credentials');
64
+ .description('Dataplane credentials: env, push, list')
65
+ .addHelpText('after', CREDENTIAL_HELP_AFTER);
53
66
  setupCredentialEnvAndPush(credential);
54
67
  credential
55
68
  .command('list')
56
- .description('Get credentials from Dataplane')
69
+ .description('List credentials from Dataplane')
57
70
  .option('--active-only', 'List only active credentials')
58
71
  .option('--page-size <n>', 'Items per page', '50')
59
72
  .action(async(options) => {
@@ -72,11 +85,12 @@ function setupCredentialDeploymentCommands(program) {
72
85
 
73
86
  const deployment = program
74
87
  .command('deployment')
75
- .description('List deployments');
88
+ .description('Controller deployments (list)')
89
+ .addHelpText('after', DEPLOYMENT_HELP_AFTER);
76
90
 
77
91
  deployment
78
92
  .command('list')
79
- .description('List last N deployments for current environment (default pageSize=50)')
93
+ .description('List recent deployments for current environment')
80
94
  .option('--controller <url>', 'Controller URL (default: from config)')
81
95
  .option('--environment <env>', 'Environment key (default: from config)')
82
96
  .option('--page-size <n>', 'Items per page', '50')