@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
@@ -1,3 +1,4 @@
1
+ const { formatSuccessLine, formatSuccessParagraph } = require('../utils/cli-test-layout-chalk');
1
2
  /**
2
3
  * AI Fabrix Builder - App Run Helpers
3
4
  *
@@ -13,24 +14,20 @@ const fs = require('fs').promises;
13
14
  const fsSync = require('fs');
14
15
  const path = require('path');
15
16
  const chalk = require('chalk');
16
- const { exec } = require('child_process');
17
17
  const { loadConfigFile } = require('../utils/config-format');
18
- const { promisify } = require('util');
19
18
  const validator = require('../validation/validator');
20
19
  const config = require('../core/config');
21
20
  const buildCopy = require('../utils/build-copy');
22
21
  const logger = require('../utils/logger');
23
- const { waitForHealthCheck } = require('../utils/health-check');
24
22
  const composeGenerator = require('../utils/compose-generator');
25
- const dockerUtils = require('../utils/docker');
26
23
  const containerHelpers = require('../utils/app-run-containers');
27
24
  const pathsUtil = require('../utils/paths');
28
25
  const runEnvCompose = require('./run-env-compose');
26
+ const { getAppInfraRequirements } = require('./run-infra-requirements');
27
+ const { resolveRunImage } = require('./run-resolve-image');
28
+ const { startContainer } = require('./run-container-start');
29
29
  const { resolveEnvOutputPath, writeEnvOutputForReload, writeEnvOutputForLocal } = require('../utils/env-copy');
30
30
  const { resolveVersionForApp } = require('../utils/image-version');
31
- const { parseImageOverride } = require('../utils/parse-image-ref');
32
-
33
- const execAsync = promisify(exec);
34
31
 
35
32
  /** Template apps (keycloak, miso-controller, dataplane) - never update application config when running */
36
33
  const TEMPLATE_APP_KEYS = ['keycloak', 'miso-controller', 'dataplane'];
@@ -123,6 +120,9 @@ async function validateAppConfiguration(appName) {
123
120
  throw new Error('Application name is required');
124
121
  }
125
122
 
123
+ const { assertRemoteBuilderDeveloperId } = require('../utils/remote-builder-validation');
124
+ assertRemoteBuilderDeveloperId(await config.getRemoteServer(), await config.getDeveloperId());
125
+
126
126
  // Check if running from builder directory
127
127
  checkBuilderDirectory(appName);
128
128
 
@@ -161,28 +161,6 @@ async function resolveAndUpdateVersion(appName, appConfig, debug) {
161
161
  }
162
162
  }
163
163
 
164
- /**
165
- * Resolve image name and tag from app config and optional run override.
166
- * @param {string} appName - Application name
167
- * @param {Object} appConfig - Application configuration
168
- * @param {Object} runOptions - Run options; runOptions.image overrides config
169
- * @returns {{ imageName: string, imageTag: string }} imageName and imageTag
170
- */
171
- function resolveRunImage(appName, appConfig, runOptions) {
172
- const imageOverride = runOptions && runOptions.image;
173
- if (imageOverride) {
174
- const parsed = parseImageOverride(imageOverride);
175
- return {
176
- imageName: parsed ? parsed.name : composeGenerator.getImageName(appConfig, appName),
177
- imageTag: parsed ? parsed.tag : (appConfig.image && appConfig.image.tag) || 'latest'
178
- };
179
- }
180
- return {
181
- imageName: composeGenerator.getImageName(appConfig, appName),
182
- imageTag: (appConfig.image && appConfig.image.tag) || 'latest'
183
- };
184
- }
185
-
186
164
  /**
187
165
  * Checks prerequisites: Docker image and (optionally) infrastructure
188
166
  * @async
@@ -210,12 +188,12 @@ async function checkPrerequisites(appName, appConfig, debug = false, skipInfraCh
210
188
  : `Run 'aifabrix build ${appName}' first`;
211
189
  throw new Error(`Docker image ${fullImageName} not found\n${hint}`);
212
190
  }
213
- logger.log(chalk.green(`✓ Image ${fullImageName} found`));
191
+ logger.log(formatSuccessLine(`Image ${fullImageName} found`));
214
192
 
215
193
  await resolveAndUpdateVersion(appName, appConfig, debug);
216
194
 
217
195
  if (!skipInfraCheck) {
218
- await checkInfraHealthOrThrow(debug);
196
+ await checkInfraHealthOrThrow(debug, appConfig);
219
197
  }
220
198
  }
221
199
 
@@ -223,12 +201,28 @@ async function checkPrerequisites(appName, appConfig, debug = false, skipInfraCh
223
201
  * Checks infrastructure health and throws if unhealthy
224
202
  * @async
225
203
  * @param {boolean} debug - Enable debug logging
204
+ * @param {Object} [appConfig] - Application configuration (for selective infra checks)
226
205
  * @throws {Error} If infrastructure is not healthy
227
206
  */
228
- async function checkInfraHealthOrThrow(debug) {
207
+ async function checkInfraHealthOrThrow(debug, appConfig) {
208
+ const requirements = getAppInfraRequirements(appConfig);
209
+ if (requirements && !requirements.needsPostgres && !requirements.needsRedis) {
210
+ logger.log(
211
+ chalk.blue('Skipping infrastructure check (application does not require database or redis)...')
212
+ );
213
+ return;
214
+ }
215
+
229
216
  logger.log(chalk.blue('Checking infrastructure health...'));
230
217
  const infra = require('../infrastructure');
231
- const infraHealth = await infra.checkInfraHealth();
218
+ const healthOptions =
219
+ requirements === null
220
+ ? {}
221
+ : {
222
+ postgres: requirements.needsPostgres,
223
+ redis: requirements.needsRedis
224
+ };
225
+ const infraHealth = await infra.checkInfraHealth(null, healthOptions);
232
226
  if (debug) {
233
227
  logger.log(chalk.gray(`[DEBUG] Infrastructure health: ${JSON.stringify(infraHealth, null, 2)}`));
234
228
  }
@@ -239,7 +233,7 @@ async function checkInfraHealthOrThrow(debug) {
239
233
  if (unhealthyServices.length > 0) {
240
234
  throw new Error(`Infrastructure services not healthy: ${unhealthyServices.join(', ')}\nRun 'aifabrix up-infra' first`);
241
235
  }
242
- logger.log(chalk.green('Infrastructure is running'));
236
+ logger.log(formatSuccessLine('Infrastructure is running'));
243
237
  }
244
238
 
245
239
  /**
@@ -334,15 +328,31 @@ async function writeEnvOutputIfConfigured(appName, appConfig, runEnvPath, option
334
328
  async function prepareEnvironment(appName, appConfig, options) {
335
329
  const developerId = await config.getDeveloperId();
336
330
  const devDir = await ensureDevDirectory(appName, developerId);
331
+ const runEnvKey = (options.env || 'dev').toLowerCase();
332
+ const userCfg = await config.getConfig();
333
+ const { computeEffectiveEnvironmentScopedResources } = require('../utils/environment-scoped-resources');
334
+ const effectiveEnvironmentScopedResources = computeEffectiveEnvironmentScopedResources(
335
+ Boolean(userCfg.useEnvironmentScopedResources),
336
+ appConfig.environmentScopedResources === true,
337
+ runEnvKey
338
+ );
337
339
 
338
340
  runEnvCompose.cleanApplicationsDir(developerId);
339
341
  logger.log(chalk.blue('Building merged .env (admin + app secrets)...'));
340
- const { runEnvPath, runEnvAdminPath } = await runEnvCompose.buildMergedRunEnvAndWrite(appName, appConfig, devDir, developerId);
342
+ const { runEnvPath, runEnvAdminPath } = await runEnvCompose.buildMergedRunEnvAndWrite(
343
+ appName,
344
+ appConfig,
345
+ devDir,
346
+ developerId,
347
+ { runEnvKey, effectiveEnvironmentScopedResources }
348
+ );
341
349
 
342
350
  const composeOptions = {
343
351
  ...options,
344
352
  envFilePath: runEnvPath,
345
- dbInitEnvFilePath: runEnvAdminPath
353
+ dbInitEnvFilePath: runEnvAdminPath,
354
+ effectiveEnvironmentScopedResources,
355
+ env: runEnvKey
346
356
  };
347
357
  composeOptions.port = calculateComposePort(composeOptions, appConfig, developerId);
348
358
  const composePath = await generateComposeFile(appName, appConfig, composeOptions, devDir);
@@ -352,105 +362,18 @@ async function prepareEnvironment(appName, appConfig, options) {
352
362
  return { composePath, runEnvPath, runEnvAdminPath };
353
363
  }
354
364
 
355
- /**
356
- * Prepare environment variables for docker compose (no secrets in host env; compose uses env_file).
357
- * @async
358
- * @param {boolean} debug - Enable debug logging
359
- * @returns {Promise<Object>} Environment variables object for child process
360
- */
361
- async function prepareContainerEnv(debug) {
362
- const env = { ...process.env };
363
-
364
- if (typeof process.getuid === 'function' && typeof process.getgid === 'function') {
365
- env.AIFABRIX_UID = String(process.getuid());
366
- env.AIFABRIX_GID = String(process.getgid());
367
- } else {
368
- env.AIFABRIX_UID = '1000';
369
- env.AIFABRIX_GID = '1000';
370
- }
371
-
372
- const { getRemoteDockerEnv } = require('../utils/remote-docker-env');
373
- const remoteDocker = await getRemoteDockerEnv();
374
- Object.assign(env, remoteDocker);
375
-
376
- if (debug) {
377
- logger.log(chalk.gray('[DEBUG] Container env prepared (secrets via env_file)'));
378
- }
379
-
380
- return env;
381
- }
382
-
383
- /**
384
- * Execute docker-compose up command. Services get env from env_file in the compose (e.g. .env.run).
385
- * @async
386
- * @param {string} composeCmdBase - Base compose command
387
- * @param {string} composePath - Path to compose file
388
- * @param {Object} env - Environment variables for the child process
389
- * @param {boolean} debug - Enable debug logging
390
- */
391
- async function executeComposeUp(composeCmdBase, composePath, env, debug) {
392
- const composeCmd = `${composeCmdBase} -f "${composePath}" up -d`;
393
- if (debug) {
394
- logger.log(chalk.gray(`[DEBUG] Executing: ${composeCmd}`));
395
- logger.log(chalk.gray(`[DEBUG] Compose file: ${composePath}`));
396
- }
397
- await execAsync(composeCmd, { env });
398
- }
399
-
400
- /**
401
- * Starts the container and waits for health check. Deletes run .env files after success (ISO 27K).
402
- * @async
403
- * @param {string} appName - Application name
404
- * @param {string} composePath - Path to Docker Compose file
405
- * @param {number} port - Application port
406
- * @param {Object} appConfig - Application configuration
407
- * @param {Object} [opts] - Options
408
- * @param {boolean} [opts.debug=false] - Enable debug logging
409
- * @param {string|null} [opts.runEnvPath=null] - Path to .env.run (app-only) to delete after successful start
410
- * @param {string|null} [opts.runEnvAdminPath=null] - Path to .env.run.admin (start-only) to delete after successful start
411
- * @throws {Error} If container fails to start or become healthy
412
- */
413
- async function startContainer(appName, composePath, port, appConfig = null, opts = {}) {
414
- const { debug = false, runEnvPath = null, runEnvAdminPath = null } = opts;
415
- logger.log(chalk.blue(`Starting ${appName}...`));
416
-
417
- const composeCmdBase = await dockerUtils.ensureDockerAndCompose().then(() => dockerUtils.getComposeCommand());
418
- const env = await prepareContainerEnv(debug);
419
- await executeComposeUp(composeCmdBase, composePath, env, debug);
420
-
421
- const idNum = typeof appConfig.developerId === 'string' ? parseInt(appConfig.developerId, 10) : appConfig.developerId;
422
- const containerName = idNum === 0 ? `aifabrix-${appName}` : `aifabrix-dev${appConfig.developerId}-${appName}`;
423
- logger.log(chalk.green(`✓ Container ${containerName} started`));
424
- await containerHelpers.logContainerStatus(containerName, debug);
425
-
426
- const healthCheckPath = appConfig?.healthCheck?.path || '/health';
427
- logger.log(chalk.blue(`Waiting for application to be healthy at http://localhost:${port}${healthCheckPath}...`));
428
- await waitForHealthCheck(appName, 90, port, appConfig, debug);
429
-
430
- for (const p of [runEnvPath, runEnvAdminPath]) {
431
- if (p && typeof p === 'string') {
432
- try {
433
- await fs.unlink(p);
434
- } catch (err) {
435
- if (err.code !== 'ENOENT') logger.log(chalk.yellow(`Warning: could not remove run .env: ${err.message}`));
436
- }
437
- }
438
- }
439
- }
440
-
441
365
  /**
442
366
  * Displays run status after successful start
443
367
  * @param {string} appName - Application name
444
368
  * @param {number} port - Application port
445
369
  * @param {Object} appConfig - Application configuration (with developerId property)
446
370
  */
447
- async function displayRunStatus(appName, port, appConfig) {
448
- const idNum = typeof appConfig.developerId === 'string' ? parseInt(appConfig.developerId, 10) : appConfig.developerId;
449
- const containerName = idNum === 0 ? `aifabrix-${appName}` : `aifabrix-dev${appConfig.developerId}-${appName}`;
371
+ async function displayRunStatus(appName, port, appConfig, runScopeOpts = null) {
372
+ const containerName = containerHelpers.getContainerName(appName, appConfig.developerId, runScopeOpts);
450
373
  const healthCheckPath = appConfig?.healthCheck?.path || '/health';
451
374
  const healthCheckUrl = `http://localhost:${port}${healthCheckPath}`;
452
375
 
453
- logger.log(chalk.green(`\n✓ App running at http://localhost:${port}`));
376
+ logger.log(formatSuccessParagraph(`App running at http://localhost:${port}`));
454
377
  logger.log(chalk.blue(`Health check: ${healthCheckUrl}`));
455
378
  logger.log(chalk.gray(`Container: ${containerName}`));
456
379
  }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Derives local infra (Postgres/Redis) needs from application.yaml for `run`.
3
+ *
4
+ * @fileoverview Shared by infra health skip and docker-run-without-compose fallback
5
+ * @author AI Fabrix Team
6
+ * @version 2.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ /**
12
+ * Reads application.yaml `requires` to decide which local infra services apply.
13
+ * Missing `requires` → null (legacy: assume Postgres + Redis may be required).
14
+ *
15
+ * @param {Object} appConfig - Application configuration from application.yaml
16
+ * @returns {null|{ needsPostgres: boolean, needsRedis: boolean }}
17
+ */
18
+ function getAppInfraRequirements(appConfig) {
19
+ const r = appConfig && appConfig.requires;
20
+ if (!r || typeof r !== 'object') {
21
+ return null;
22
+ }
23
+ const needsPostgres =
24
+ r.database === true ||
25
+ (Array.isArray(r.databases) && r.databases.length > 0);
26
+ const needsRedis = r.redis === true;
27
+ return { needsPostgres, needsRedis };
28
+ }
29
+
30
+ module.exports = { getAppInfraRequirements };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Resolve Docker image name/tag for run (config + optional --image / --registry overrides).
3
+ *
4
+ * @fileoverview Shared by checkPrerequisites and container start / docker run fallback
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { resolveDockerImageRef } = require('../utils/resolve-docker-image-ref');
10
+
11
+ /**
12
+ * @param {string} appName
13
+ * @param {Object} appConfig
14
+ * @param {Object} runOptions - runOptions.image / runOptions.registry override config
15
+ * @returns {{ imageName: string, imageTag: string }}
16
+ */
17
+ function resolveRunImage(appName, appConfig, runOptions) {
18
+ return resolveDockerImageRef(appName, appConfig, runOptions);
19
+ }
20
+
21
+ module.exports = { resolveRunImage };
package/lib/app/run.js CHANGED
@@ -10,8 +10,6 @@
10
10
  */
11
11
 
12
12
  const chalk = require('chalk');
13
- const { exec } = require('child_process');
14
- const { promisify } = require('util');
15
13
  const config = require('../core/config');
16
14
  const logger = require('../utils/logger');
17
15
  const pathsUtil = require('../utils/paths');
@@ -21,8 +19,7 @@ const containerHelpers = require('../utils/app-run-containers');
21
19
  const mutagen = require('../utils/mutagen');
22
20
  // Helper functions extracted to reduce file size and complexity
23
21
  const helpers = require('./run-helpers');
24
-
25
- const execAsync = promisify(exec);
22
+ const { execWithDockerEnv } = require('../utils/docker-exec');
26
23
 
27
24
  /**
28
25
  * True if host is localhost or 127.0.0.1 (case-insensitive).
@@ -76,7 +73,7 @@ async function validateAppForRun(appName, _debug) {
76
73
  try {
77
74
  const { isExternal, baseDir } = await detectAppType(appName);
78
75
  if (baseDir !== 'builder' || isExternal) {
79
- logger.log(chalk.yellow('⚠️ External systems don\'t run as Docker containers.'));
76
+ logger.log(chalk.yellow(' External systems don\'t run as Docker containers.'));
80
77
  logger.log(chalk.blue('Use "aifabrix build" to deploy to dataplane, then test via OpenAPI endpoints.'));
81
78
  return false;
82
79
  }
@@ -98,17 +95,27 @@ async function validateAppForRun(appName, _debug) {
98
95
  * @param {boolean} debug - Debug flag
99
96
  * @returns {Promise<void>}
100
97
  */
101
- async function checkAndStopContainer(appName, developerId, debug) {
102
- const containerRunning = await helpers.checkContainerRunning(appName, developerId, debug);
98
+ async function checkAndStopContainer(appName, appConfig, options, debug) {
99
+ const developerId = appConfig.developerId;
100
+ const runEnvKey = (options.env || 'dev').toLowerCase();
101
+ const userCfg = await config.getConfig();
102
+ const { computeEffectiveEnvironmentScopedResources } = require('../utils/environment-scoped-resources');
103
+ const effectiveEnvironmentScopedResources = computeEffectiveEnvironmentScopedResources(
104
+ Boolean(userCfg.useEnvironmentScopedResources),
105
+ appConfig.environmentScopedResources === true,
106
+ runEnvKey
107
+ );
108
+ const scopeOpts = effectiveEnvironmentScopedResources
109
+ ? { effectiveEnvironmentScopedResources: true, env: runEnvKey }
110
+ : null;
111
+ const containerRunning = await helpers.checkContainerRunning(appName, developerId, debug, scopeOpts);
103
112
  if (!containerRunning) {
104
113
  return;
105
114
  }
106
115
 
107
- // Dev 0: aifabrix-{appName} (no dev-0 suffix), Dev > 0: aifabrix-dev{id}-{appName}
108
- const idNum = typeof developerId === 'string' ? parseInt(developerId, 10) : developerId;
109
- const containerName = idNum === 0 ? `aifabrix-${appName}` : `aifabrix-dev${developerId}-${appName}`;
116
+ const containerName = containerHelpers.getContainerName(appName, developerId, scopeOpts);
110
117
  logger.log(chalk.yellow(`Container ${containerName} is already running`));
111
- await helpers.stopAndRemoveContainer(appName, developerId, debug);
118
+ await helpers.stopAndRemoveContainer(appName, developerId, debug, scopeOpts);
112
119
  }
113
120
 
114
121
  /**
@@ -214,10 +221,24 @@ async function loadAndConfigureApp(appName, debug) {
214
221
  * @throws {Error} If container start fails
215
222
  */
216
223
  async function startAppContainer(appName, tempComposePath, hostPort, appConfig, opts) {
217
- const { debug, runEnvPath = null, runEnvAdminPath = null } = opts;
224
+ const {
225
+ debug,
226
+ runEnvPath = null,
227
+ runEnvAdminPath = null,
228
+ runOptions = {},
229
+ devMountPath = null
230
+ } = opts;
231
+ const misoEnvironment = opts.misoEnvironment ?? composeGenerator.resolveMisoEnvironment(runOptions);
218
232
  try {
219
- await helpers.startContainer(appName, tempComposePath, hostPort, appConfig, { debug, runEnvPath, runEnvAdminPath });
220
- await helpers.displayRunStatus(appName, hostPort, appConfig);
233
+ await helpers.startContainer(appName, tempComposePath, hostPort, appConfig, {
234
+ debug,
235
+ runEnvPath,
236
+ runEnvAdminPath,
237
+ runOptions,
238
+ devMountPath,
239
+ misoEnvironment
240
+ });
241
+ await helpers.displayRunStatus(appName, hostPort, appConfig, opts.runScopeOpts || null);
221
242
  } catch (error) {
222
243
  logger.log(chalk.yellow(`\n⚠️ Compose file preserved at: ${tempComposePath}`));
223
244
  logger.log(chalk.yellow(' Review the file to debug issues'));
@@ -240,8 +261,12 @@ async function startAppContainer(appName, tempComposePath, hostPort, appConfig,
240
261
  * @param {boolean} debug - Debug flag
241
262
  * @returns {Promise<Object>} Run options with optional devMountPath
242
263
  */
243
- async function resolveRunOptions(appName, appConfig, options, envKey, debug) {
244
- const runOptions = { ...options, env: envKey };
264
+ async function resolveRunOptions(appName, appConfig, options, envKey, debug, effectiveEnvironmentScopedResources) {
265
+ const runOptions = {
266
+ ...options,
267
+ env: envKey,
268
+ effectiveEnvironmentScopedResources: Boolean(effectiveEnvironmentScopedResources)
269
+ };
245
270
  const builderPath = pathsUtil.getBuilderPath(appName);
246
271
  const codePath = pathsUtil.resolveBuildContext(builderPath, appConfig.build?.context || '.');
247
272
  if (options.reload && envKey === 'dev') {
@@ -269,12 +294,37 @@ async function prepareAppRun(appName, options, debug) {
269
294
  return null;
270
295
  }
271
296
  const appConfig = await loadAndConfigureApp(appName, debug);
297
+ const userCfg = await config.getConfig();
298
+ const { computeEffectiveEnvironmentScopedResources } = require('../utils/environment-scoped-resources');
299
+ const effectiveEnvironmentScopedResources = computeEffectiveEnvironmentScopedResources(
300
+ Boolean(userCfg.useEnvironmentScopedResources),
301
+ appConfig.environmentScopedResources === true,
302
+ envKey
303
+ );
304
+ const runScopeOpts = effectiveEnvironmentScopedResources
305
+ ? { effectiveEnvironmentScopedResources: true, env: envKey }
306
+ : null;
272
307
  await helpers.checkPrerequisites(appName, appConfig, debug, options.skipInfraCheck === true, options);
273
- await checkAndStopContainer(appName, appConfig.developerId, debug);
308
+ await checkAndStopContainer(appName, appConfig, options, debug);
274
309
  const hostPort = await calculateHostPort(appConfig, options, debug);
275
- const runOptions = await resolveRunOptions(appName, appConfig, options, envKey, debug);
310
+ const runOptions = await resolveRunOptions(
311
+ appName,
312
+ appConfig,
313
+ options,
314
+ envKey,
315
+ debug,
316
+ effectiveEnvironmentScopedResources
317
+ );
276
318
  const { composePath: tempComposePath, runEnvPath, runEnvAdminPath } = await helpers.prepareEnvironment(appName, appConfig, runOptions);
277
- const result = { appConfig, tempComposePath, hostPort, runEnvPath, runEnvAdminPath };
319
+ const result = {
320
+ appConfig,
321
+ tempComposePath,
322
+ hostPort,
323
+ runEnvPath,
324
+ runEnvAdminPath,
325
+ runScopeOpts,
326
+ mergedRunOptions: runOptions
327
+ };
278
328
  if (runOptions.devMountPath) result.devMountPath = runOptions.devMountPath;
279
329
  return result;
280
330
  }
@@ -317,7 +367,10 @@ async function runApp(appName, options = {}) {
317
367
  await startAppContainer(appName, prepared.tempComposePath, prepared.hostPort, prepared.appConfig, {
318
368
  debug,
319
369
  runEnvPath: prepared.runEnvPath,
320
- runEnvAdminPath: prepared.runEnvAdminPath
370
+ runEnvAdminPath: prepared.runEnvAdminPath,
371
+ runOptions: prepared.mergedRunOptions,
372
+ devMountPath: prepared.devMountPath,
373
+ runScopeOpts: prepared.runScopeOpts
321
374
  });
322
375
  } catch (error) {
323
376
  if (debug) {
@@ -347,7 +400,7 @@ async function restartApp(appName) {
347
400
  const developerId = await config.getDeveloperId();
348
401
  const containerName = containerHelpers.getContainerName(appName, developerId);
349
402
  try {
350
- await execAsync(`docker restart ${containerName}`);
403
+ await execWithDockerEnv(`docker restart ${containerName}`);
351
404
  } catch (error) {
352
405
  const msg = (error.stderr || error.stdout || error.message || '').toLowerCase();
353
406
  if (msg.includes('no such container') || msg.includes('is not running')) {
@@ -81,7 +81,7 @@ function logApplicationExternalIntegration(ei, options = {}) {
81
81
  logger.log(` systems: [${(ei.systems || []).join(', ')}]`);
82
82
  logger.log(` dataSources: [${(ei.dataSources || []).join(', ')}]`);
83
83
  if (!options.skipHint) {
84
- logger.log(chalk.gray('\n For external system data as on dataplane, run: aifabrix show <appKey> --online or aifabrix app show <appKey>.'));
84
+ logger.log(chalk.gray('\n For external system data as on dataplane, run: aifabrix show <app> --online or aifabrix app show <app>.'));
85
85
  }
86
86
  }
87
87
 
package/lib/app/show.js CHANGED
@@ -440,7 +440,7 @@ function formatBuildForDisplay(build) {
440
440
  if (!build) return '—';
441
441
  const parts = [];
442
442
  if (build.language) parts.push(build.language);
443
- const port = build.port ?? build.localPort;
443
+ const port = build.port;
444
444
  if (port !== undefined && port !== null) parts.push(`port ${port}`);
445
445
  if (build.dockerfile) parts.push('dockerfile');
446
446
  if (build.envOutputPath) parts.push(`envOutputPath: ${build.envOutputPath}`);
@@ -1,3 +1,4 @@
1
+ const { formatSuccessLine, formatSuccessParagraph } = require('../utils/cli-test-layout-chalk');
1
2
  /**
2
3
  * AI Fabrix Builder Build Functions
3
4
  *
@@ -127,7 +128,9 @@ async function generateDockerfile(appNameOrPath, language, config, buildConfig =
127
128
 
128
129
  const template = dockerfileUtils.loadDockerfileTemplate(language);
129
130
  const isAppFlag = buildConfig.context === '../..';
130
- const appSourcePath = isAppFlag ? `apps/${appName}/` : '.';
131
+ // Use "./" (not ".") so Dockerfile lines are "COPY ./requirements*.txt" — a bare "."
132
+ // concatenates with "requirements" and becomes ".requirements*.txt", which matches nothing.
133
+ const appSourcePath = isAppFlag ? `apps/${appName}/` : './';
131
134
 
132
135
  const templateVars = {
133
136
  port: config.port || 3000,
@@ -185,11 +188,11 @@ async function generateDockerfile(appNameOrPath, language, config, buildConfig =
185
188
  async function postBuildTasks(appName, buildConfig) {
186
189
  try {
187
190
  const envPath = await secrets.generateEnvFile(appName, buildConfig.secrets, 'docker');
188
- logger.log(chalk.green(`✓ Generated .env file: ${envPath}`));
191
+ logger.log(formatSuccessLine(`Generated .env file: ${envPath}`));
189
192
  // Note: processEnvVariables is already called by generateEnvFile to generate local .env
190
193
  // at the envOutputPath, so we don't need to manually copy the docker .env file
191
194
  } catch (error) {
192
- logger.log(chalk.yellow(`⚠️ Warning: Could not generate .env file: ${error.message}`));
195
+ logger.log(chalk.yellow(`⚠ Warning: Could not generate .env file: ${error.message}`));
193
196
  }
194
197
  }
195
198
 
@@ -229,7 +232,7 @@ async function copyApplicationSourceFiles(appName, devDir) {
229
232
  const appsPath = path.join(process.cwd(), 'apps', appName);
230
233
  if (fsSync.existsSync(appsPath)) {
231
234
  await buildCopy.copyAppSourceFiles(appsPath, devDir);
232
- logger.log(chalk.green(`✓ Copied application source files from apps/${appName}`));
235
+ logger.log(formatSuccessLine(`Copied application source files from apps/${appName}`));
233
236
  return true;
234
237
  }
235
238
  return false;
@@ -253,12 +256,12 @@ async function copyTemplateFilesIfNeeded(devDir, language, buildConfig, options)
253
256
  const projectRoot = getProjectRoot();
254
257
  const templatePath = path.join(projectRoot, 'templates', 'typescript');
255
258
  await buildCopy.copyTemplateFilesToDevDir(templatePath, devDir, detectedLanguage);
256
- logger.log(chalk.green(`✓ Generated application files from ${detectedLanguage} template`));
259
+ logger.log(formatSuccessLine(`Generated application files from ${detectedLanguage} template`));
257
260
  } else if (detectedLanguage === 'python' && !fsSync.existsSync(requirementsPath)) {
258
261
  const projectRoot = getProjectRoot();
259
262
  const templatePath = path.join(projectRoot, 'templates', 'python');
260
263
  await buildCopy.copyTemplateFilesToDevDir(templatePath, devDir, detectedLanguage);
261
- logger.log(chalk.green(`✓ Generated application files from ${detectedLanguage} template`));
264
+ logger.log(formatSuccessLine(`Generated application files from ${detectedLanguage} template`));
262
265
  }
263
266
  }
264
267
 
@@ -268,7 +271,7 @@ async function prepareDevDirectory(appName, buildConfig, options) {
268
271
  const directoryName = idNum === 0 ? 'applications' : `dev-${developerId}`;
269
272
  logger.log(chalk.blue(`Copying files to developer-specific directory (${directoryName})...`));
270
273
  const devDir = await buildCopy.copyBuilderToDevDirectory(appName, developerId);
271
- logger.log(chalk.green(`✓ Files copied to: ${devDir}`));
274
+ logger.log(formatSuccessLine(`Files copied to: ${devDir}`));
272
275
 
273
276
  const { config: appConfig, imageName } = await buildHelpers.loadAndValidateConfig(appName);
274
277
  const effectiveImageName = buildDevImageName(imageName, developerId);
@@ -294,7 +297,7 @@ function prepareBuildContext(buildConfig, devDir) {
294
297
  // Check if context is using old format (../appName) - these are incompatible with dev directory structure
295
298
  if (buildConfig.context && buildConfig.context.startsWith('../') && buildConfig.context !== '../..') {
296
299
  // Old format detected - always use devDir instead
297
- logger.log(chalk.yellow(`⚠️ Warning: Build context uses old format: ${buildConfig.context}`));
300
+ logger.log(chalk.yellow(`⚠ Warning: Build context uses old format: ${buildConfig.context}`));
298
301
  logger.log(chalk.yellow(` Using dev directory instead: ${devDir}`));
299
302
  contextPath = devDir;
300
303
  } else if (buildConfig.context && buildConfig.context !== '../..') {
@@ -353,7 +356,7 @@ async function handleDockerfileGeneration(appName, params, options, buildHelpers
353
356
  language = 'typescript';
354
357
  }
355
358
  if (!hasExistingDockerfile) {
356
- logger.log(chalk.green(`✓ Detected language: ${language}`));
359
+ logger.log(formatSuccessLine(`Detected language: ${language}`));
357
360
  }
358
361
 
359
362
  // Determine Dockerfile (needs context path to generate in correct location)
@@ -425,7 +428,7 @@ async function buildApp(appName, options = {}) {
425
428
  // 7. Post-build tasks
426
429
  await postBuildTasks(appName, buildConfig);
427
430
 
428
- logger.log(chalk.green('\n✅ Build completed successfully!'));
431
+ logger.log(formatSuccessParagraph('Build completed successfully!'));
429
432
  return `${imageName}:${tag}`;
430
433
 
431
434
  } catch (error) {
package/lib/cli/index.js CHANGED
@@ -17,6 +17,7 @@ const { setupEnvironmentCommands } = require('./setup-environment');
17
17
  const { setupUtilityCommands } = require('./setup-utility');
18
18
  const { setupDevCommands } = require('./setup-dev');
19
19
  const { setupSecretsCommands } = require('./setup-secrets');
20
+ const { setupParametersCommands } = require('./setup-parameters');
20
21
  const { setupExternalSystemCommands } = require('./setup-external-system');
21
22
  const { setupAppCommands: setupAppManagementCommands } = require('../commands/app');
22
23
  const { setupDatasourceCommands } = require('../commands/datasource');
@@ -40,6 +41,7 @@ function setupCommands(program) {
40
41
  setupExternalSystemCommands(program);
41
42
  setupDevCommands(program);
42
43
  setupSecretsCommands(program);
44
+ setupParametersCommands(program);
43
45
  }
44
46
 
45
47
  module.exports = {