@aifabrix/builder 2.45.5 → 2.47.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 (355) hide show
  1. package/.cursor/rules/cli-layout.mdc +2 -0
  2. package/.cursor/rules/cli-product-neutral.mdc +43 -0
  3. package/.cursor/rules/project-rules.mdc +1 -0
  4. package/.npmrc.token +1 -0
  5. package/.temp/jest-protection-convert/run-IFN2nv/.protection/hubspot-companies.json +1 -0
  6. package/.temp/jest-protection-convert/run-IvmKLO/.protection/hubspot-companies.yaml +17 -0
  7. package/.temp/jest-protection-convert/run-SdvblF/.protection/hubspot-companies.json +1 -0
  8. package/.temp/jest-protection-convert/run-b51TsW/.protection/hubspot-companies.json +1 -0
  9. package/.temp/jest-protection-convert/run-fiLmb1/.protection/hubspot-companies.json +1 -0
  10. package/.temp/jest-protection-convert/run-qYGHMU/.protection/hubspot-companies.yaml +17 -0
  11. package/.temp/jest-protection-fixtures/hubspot-Mq5re8/hubspot-companies.yaml +17 -0
  12. package/.temp/jest-protection-fixtures/hubspot-f3u4YL/hubspot-companies.yaml +17 -0
  13. package/.temp/jest-protection-fixtures/hubspot-iQtd1O/hubspot-companies.yaml +17 -0
  14. package/.temp/jest-protection-fixtures/hubspot-mdmz5M/hubspot-companies.yaml +17 -0
  15. package/.temp/jest-protection-fixtures/hubspot-qbKYxQ/hubspot-companies.yaml +17 -0
  16. package/.temp/jest-protection-fixtures/hubspot-yzlJy6/hubspot-companies.yaml +17 -0
  17. package/.temp/validation/summary.txt +5 -0
  18. package/README.md +43 -17
  19. package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +1 -1
  20. package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +1 -1
  21. package/jest.config.default.js +2 -1
  22. package/jest.config.isolated.js +2 -1
  23. package/jest.global-live-fabrix-hooks.js +36 -0
  24. package/jest.isolated-projects.js +146 -0
  25. package/jest.projects.js +65 -136
  26. package/lib/api/api-response-errors.js +124 -0
  27. package/lib/api/dataplane-health.api.js +19 -7
  28. package/lib/api/governance-scenario-pack.api.js +159 -0
  29. package/lib/api/index.js +43 -3
  30. package/lib/api/lifecycle.api.js +98 -0
  31. package/lib/api/pipeline.api.js +3 -1
  32. package/lib/api/records-bulk.api.js +14 -1
  33. package/lib/api/resource-types.api.js +107 -0
  34. package/lib/api/runtime-configuration.api.js +72 -0
  35. package/lib/api/types/resource-types.types.js +45 -0
  36. package/lib/api/user-groups.api.js +9 -9
  37. package/lib/api/users.api.js +8 -8
  38. package/lib/api/validation-runner.js +3 -1
  39. package/lib/api/wizard.api.js +10 -2
  40. package/lib/app/deploy-config.js +4 -1
  41. package/lib/app/down.js +78 -27
  42. package/lib/app/index.js +2 -2
  43. package/lib/app/push.js +4 -5
  44. package/lib/app/register.js +7 -4
  45. package/lib/app/run-env-compose.js +84 -30
  46. package/lib/app/run-resolve-image.js +2 -1
  47. package/lib/app/run-stop-containers.js +113 -0
  48. package/lib/app/run.js +1 -31
  49. package/lib/app/show-display.js +35 -0
  50. package/lib/app/show.js +32 -1
  51. package/lib/build/index.js +22 -5
  52. package/lib/build/miso-controller-npm-sdk-guard.js +25 -0
  53. package/lib/certification/sync-system-certification.js +13 -6
  54. package/lib/channels/add-channel.js +348 -0
  55. package/lib/channels/channel-artifact-generator.js +141 -0
  56. package/lib/channels/channel-audit.js +101 -0
  57. package/lib/channels/channel-auth-context.js +37 -0
  58. package/lib/channels/channel-credential.js +200 -0
  59. package/lib/channels/channel-display-name.js +64 -0
  60. package/lib/channels/channel-external-system.js +106 -0
  61. package/lib/channels/channel-integration-generator.js +274 -0
  62. package/lib/channels/channel-probe.js +89 -0
  63. package/lib/channels/channel-runtime-resolver.js +152 -0
  64. package/lib/channels/channel-status-display.js +141 -0
  65. package/lib/channels/channel-targets.js +115 -0
  66. package/lib/cli/index.js +20 -4
  67. package/lib/cli/infra-guided-auth.js +109 -0
  68. package/lib/cli/infra-guided.js +84 -81
  69. package/lib/cli/setup-app.help.js +0 -31
  70. package/lib/cli/setup-app.js +82 -5
  71. package/lib/cli/setup-app.test-commands.js +5 -57
  72. package/lib/cli/setup-auth.js +25 -0
  73. package/lib/cli/setup-certification-commands.js +147 -0
  74. package/lib/cli/setup-certification.help.js +141 -0
  75. package/lib/cli/setup-environment.js +19 -2
  76. package/lib/cli/setup-external-system-help.js +62 -0
  77. package/lib/cli/setup-external-system.js +25 -3
  78. package/lib/cli/setup-infra-up-dataplane-action.js +2 -2
  79. package/lib/cli/setup-infra-up-platform-action.js +2 -1
  80. package/lib/cli/setup-infra.js +9 -1
  81. package/lib/cli/setup-platform.js +6 -1
  82. package/lib/cli/setup-secrets.js +33 -1
  83. package/lib/cli/setup-utility-help-after.js +25 -2
  84. package/lib/cli/setup-utility-repair.js +198 -0
  85. package/lib/cli/setup-utility-resolve.js +44 -5
  86. package/lib/cli/setup-utility-validate.js +197 -0
  87. package/lib/cli/setup-utility.js +4 -239
  88. package/lib/commands/app-logs.js +54 -26
  89. package/lib/commands/app.js +41 -0
  90. package/lib/commands/auth-status-client-tokens.js +214 -0
  91. package/lib/commands/auth-status-dataplane-version.js +142 -68
  92. package/lib/commands/auth-status.js +43 -54
  93. package/lib/commands/channel.js +58 -0
  94. package/lib/commands/datasource-test-trust-cli.js +27 -23
  95. package/lib/commands/datasource-unified-test-cli.js +6 -3
  96. package/lib/commands/datasource-unified-test-cli.options.js +5 -1
  97. package/lib/commands/datasource.js +8 -8
  98. package/lib/commands/dev-show-display.js +8 -1
  99. package/lib/commands/governance-cli-shared.js +94 -0
  100. package/lib/commands/governance-command-action.js +132 -0
  101. package/lib/commands/governance-download-external.js +34 -0
  102. package/lib/commands/governance-generate-external.js +71 -0
  103. package/lib/commands/governance-upload-external.js +36 -0
  104. package/lib/commands/governance-verify-external.js +64 -0
  105. package/lib/commands/governance.js +144 -0
  106. package/lib/commands/identity-apply-sync.js +49 -8
  107. package/lib/commands/identity-group-cli.js +66 -26
  108. package/lib/commands/identity-membership-role-cache.js +58 -37
  109. package/lib/commands/identity-shared.js +22 -1
  110. package/lib/commands/identity-user-cli.js +80 -34
  111. package/lib/commands/lifecycle-command-action.js +123 -0
  112. package/lib/commands/lifecycle-external.js +268 -0
  113. package/lib/commands/login.js +11 -2
  114. package/lib/commands/repair-auth-apply.js +153 -0
  115. package/lib/commands/repair-auth-config.js +8 -13
  116. package/lib/commands/repair-changed-files.js +41 -0
  117. package/lib/commands/repair-datasource-com-v2.js +15 -0
  118. package/lib/commands/repair-datasource-keys.js +4 -1
  119. package/lib/commands/repair-datasource-run.js +59 -0
  120. package/lib/commands/repair-datasource-service-contract.js +206 -0
  121. package/lib/commands/repair-datasource-test-payload.js +259 -0
  122. package/lib/commands/repair-datasource.js +49 -64
  123. package/lib/commands/repair-env-template.js +76 -25
  124. package/lib/commands/repair-external-run.js +216 -0
  125. package/lib/commands/repair-openapi-sync.js +49 -4
  126. package/lib/commands/repair-persist.js +4 -0
  127. package/lib/commands/repair-rbac.js +52 -1
  128. package/lib/commands/repair-steps.js +160 -0
  129. package/lib/commands/repair-system-alignment.js +7 -4
  130. package/lib/commands/repair.js +29 -296
  131. package/lib/commands/resource-type.js +371 -0
  132. package/lib/commands/secrets-get.js +184 -0
  133. package/lib/commands/secrets-remove-all.js +3 -1
  134. package/lib/commands/setup-image-refresh.js +146 -0
  135. package/lib/commands/setup-modes.js +158 -162
  136. package/lib/commands/setup-platform-auth.js +76 -0
  137. package/lib/commands/setup-prompts-admin.js +244 -0
  138. package/lib/commands/setup-prompts-platform-mode.js +70 -0
  139. package/lib/commands/setup-prompts-validators.js +36 -0
  140. package/lib/commands/setup-prompts.js +24 -76
  141. package/lib/commands/setup-run-context.js +45 -0
  142. package/lib/commands/setup-spinners.js +39 -0
  143. package/lib/commands/setup.js +27 -5
  144. package/lib/commands/teardown.js +39 -0
  145. package/lib/commands/test-e2e-external.js +24 -8
  146. package/lib/commands/test-governance-external.js +3 -24
  147. package/lib/commands/test-trust-external.js +48 -100
  148. package/lib/commands/up-common.js +57 -13
  149. package/lib/commands/up-dataplane.js +56 -15
  150. package/lib/commands/upload-publish-context.js +75 -0
  151. package/lib/commands/upload-sidecar-followups.js +89 -0
  152. package/lib/commands/upload.js +113 -110
  153. package/lib/commands/verify-governance-combined-external.js +61 -0
  154. package/lib/commands/verify-governance-command-action.js +64 -0
  155. package/lib/commands/verify-governance-db.js +102 -0
  156. package/lib/commands/verify-governance-external.js +77 -0
  157. package/lib/commands/verify-governance-result-builders.js +71 -0
  158. package/lib/commands/verify-operations-command-action.js +68 -0
  159. package/lib/commands/verify-operations-external.js +268 -0
  160. package/lib/commands/verify-operations-persist.js +75 -0
  161. package/lib/commands/verify-operations-step-plan.js +68 -0
  162. package/lib/commands/verify-operations-steps.js +111 -0
  163. package/lib/commands/verify-trust-command-action.js +73 -0
  164. package/lib/commands/verify-trust-external.js +59 -0
  165. package/lib/commands/wizard-config-normalizer.js +43 -23
  166. package/lib/commands/wizard-core.js +2 -0
  167. package/lib/core/admin-password-generator.js +38 -0
  168. package/lib/core/admin-secrets-bundle.js +111 -0
  169. package/lib/core/admin-secrets-env-overlay.js +62 -0
  170. package/lib/core/admin-secrets.js +32 -4
  171. package/lib/core/config-attach-extensions.js +3 -0
  172. package/lib/core/config-platform-controller.js +44 -0
  173. package/lib/core/config-setup-installation-profile.js +42 -0
  174. package/lib/core/config-setup-platform-mode.js +46 -0
  175. package/lib/core/config.js +46 -36
  176. package/lib/core/secrets-admin-env.js +6 -2
  177. package/lib/core/secrets-ensure.js +4 -0
  178. package/lib/core/secrets-env-content.js +54 -48
  179. package/lib/core/secrets-env-write.js +10 -1
  180. package/lib/core/secrets-infra-placeholder-sync.js +2 -0
  181. package/lib/core/setup-installation-profile.js +43 -0
  182. package/lib/core/setup-platform-mode.js +90 -0
  183. package/lib/datasource/agent-trust-debug-log.js +1 -1
  184. package/lib/datasource/agent-trust-run.js +5 -3
  185. package/lib/datasource/audit-evidence-extract-debug.js +30 -18
  186. package/lib/datasource/audit-evidence-extract.js +7 -4
  187. package/lib/datasource/audit-evidence-verify-matrix.js +54 -26
  188. package/lib/datasource/bulk-loader-run-batches.js +15 -3
  189. package/lib/datasource/capability/capability-diff-slice.js +2 -2
  190. package/lib/datasource/capability/capability-manifest.js +254 -0
  191. package/lib/datasource/capability/capability-resolve.js +3 -4
  192. package/lib/datasource/capability/copy-operations.js +5 -3
  193. package/lib/datasource/capability/remove-operations.js +2 -1
  194. package/lib/datasource/capability/run-capability-copy.js +32 -4
  195. package/lib/datasource/capability/run-capability-diff.js +3 -3
  196. package/lib/datasource/capability/run-capability-dimension.js +2 -4
  197. package/lib/datasource/capability/run-capability-edit.js +4 -7
  198. package/lib/datasource/capability/run-capability-relate.js +2 -4
  199. package/lib/datasource/capability/run-capability-remove.js +2 -4
  200. package/lib/datasource/capability/validate-capability-slice.js +2 -1
  201. package/lib/datasource/datasource-identifier.js +2 -1
  202. package/lib/datasource/datasource-load-export-context.js +3 -0
  203. package/lib/datasource/datasource-validate-display.js +1 -1
  204. package/lib/datasource/field-reference-validator.js +24 -3
  205. package/lib/datasource/log-cleaner.js +2 -2
  206. package/lib/datasource/log-viewer.js +8 -8
  207. package/lib/datasource/orphan-profiles-validator.js +98 -0
  208. package/lib/datasource/test-e2e.js +4 -1
  209. package/lib/datasource/unified-validation-run-body.js +3 -1
  210. package/lib/datasource/unified-validation-run.js +5 -2
  211. package/lib/datasource/validate.js +41 -23
  212. package/lib/deployment/environment-poll-status.js +138 -0
  213. package/lib/deployment/environment.js +42 -34
  214. package/lib/external-system/download-helpers.js +87 -0
  215. package/lib/external-system/download.js +78 -138
  216. package/lib/external-system/generator.js +1 -55
  217. package/lib/external-system/integration-auth-context.js +45 -0
  218. package/lib/external-system/test-auth.js +12 -5
  219. package/lib/external-system/test.js +16 -21
  220. package/lib/generator/builders.js +11 -1
  221. package/lib/generator/external-controller-manifest.js +18 -0
  222. package/lib/generator/split.js +3 -1
  223. package/lib/generator/wizard.js +1 -28
  224. package/lib/governance/governance-cli-errors.js +96 -0
  225. package/lib/governance/governance-download-display.js +38 -0
  226. package/lib/governance/governance-run-display.js +215 -25
  227. package/lib/identity/fk-reference.js +65 -0
  228. package/lib/identity/identity-apply-core.js +13 -58
  229. package/lib/identity/identity-apply-phases.js +5 -1
  230. package/lib/identity/identity-display.js +243 -0
  231. package/lib/identity/identity-response-helpers.js +52 -0
  232. package/lib/identity/identity-sync-errors.js +62 -0
  233. package/lib/identity/resolve-user-id.js +129 -0
  234. package/lib/identity/username-default.js +31 -0
  235. package/lib/infrastructure/admin-secrets-apply.js +84 -0
  236. package/lib/infrastructure/admin-secrets-ensure.js +130 -0
  237. package/lib/infrastructure/admin-secrets-resolve.js +95 -0
  238. package/lib/infrastructure/admin-secrets-sync.js +91 -0
  239. package/lib/infrastructure/helpers.js +23 -129
  240. package/lib/infrastructure/index.js +5 -6
  241. package/lib/infrastructure/orphan-infra-docker-teardown.js +11 -5
  242. package/lib/lifecycle/certification-progress.js +231 -0
  243. package/lib/lifecycle/dataplane-ui-url.js +145 -0
  244. package/lib/lifecycle/exit-codes.js +24 -0
  245. package/lib/lifecycle/json-envelope.js +25 -0
  246. package/lib/lifecycle/lifecycle-governance-options.js +51 -0
  247. package/lib/lifecycle/logger-quiet.js +29 -0
  248. package/lib/lifecycle/open-api-published.js +59 -0
  249. package/lib/lifecycle/operations-readiness-metrics.js +101 -0
  250. package/lib/lifecycle/product-model.js +196 -0
  251. package/lib/lifecycle/report-display-trust.js +70 -0
  252. package/lib/lifecycle/report-display.js +472 -0
  253. package/lib/lifecycle/scenario-upload.js +191 -0
  254. package/lib/lifecycle/verify-step-progress.js +87 -0
  255. package/lib/parameters/infra-kv-discovery.js +27 -2
  256. package/lib/protection/auth-context.js +10 -4
  257. package/lib/resolvers/datasource-resolver.js +2 -3
  258. package/lib/resolvers/resource-type-file.js +159 -0
  259. package/lib/schema/application-schema.json +17 -1
  260. package/lib/schema/datasource-test-run.schema.json +89 -6
  261. package/lib/schema/deployment-rules.yaml +2 -1
  262. package/lib/schema/external-datasource.schema.json +2947 -2619
  263. package/lib/schema/external-system.schema.json +1418 -761
  264. package/lib/schema/infra.parameter.yaml +45 -0
  265. package/lib/schema/type/credential-field-registry.json +103 -97
  266. package/lib/schema/type/document-storage.json +9 -5
  267. package/lib/utils/aifabrix-test-runtime-guard.js +125 -0
  268. package/lib/utils/api.js +55 -31
  269. package/lib/utils/app-relative-path-env.js +112 -0
  270. package/lib/utils/app-run-containers.js +25 -2
  271. package/lib/utils/authentication-shape.js +224 -0
  272. package/lib/utils/build-copy.js +36 -5
  273. package/lib/utils/build-resolve-image.js +66 -12
  274. package/lib/utils/celery-companion-apps.js +53 -0
  275. package/lib/utils/cli-secrets-error-format.js +83 -21
  276. package/lib/utils/cli-utils.js +20 -4
  277. package/lib/utils/compose-celery-worker.js +23 -0
  278. package/lib/utils/compose-generate-docker-compose.js +13 -1
  279. package/lib/utils/compose-traefik-ingress-base.js +16 -1
  280. package/lib/utils/config-secrets-path.js +46 -0
  281. package/lib/utils/configuration-env-resolver.js +36 -0
  282. package/lib/utils/controller-url.js +88 -1
  283. package/lib/utils/credential-secrets-env-kv.js +216 -0
  284. package/lib/utils/credential-secrets-env.js +175 -257
  285. package/lib/utils/dataplane-resolver.js +18 -2
  286. package/lib/utils/declarative-url-ports.js +27 -4
  287. package/lib/utils/deployment-auth-mode.js +41 -0
  288. package/lib/utils/developer-volume-id.js +33 -0
  289. package/lib/utils/docker-build.js +1 -4
  290. package/lib/utils/env-copy.js +14 -9
  291. package/lib/utils/env-kv-orphan-lines.js +43 -0
  292. package/lib/utils/error-formatters/network-errors.js +13 -4
  293. package/lib/utils/external-env-template.js +11 -3
  294. package/lib/utils/external-system-readiness-core.js +10 -0
  295. package/lib/utils/external-system-readiness-display.js +80 -23
  296. package/lib/utils/external-system-validators.js +8 -2
  297. package/lib/utils/health-check.js +4 -1
  298. package/lib/utils/help-builder.js +13 -8
  299. package/lib/utils/keycloak-realm-ready.js +101 -0
  300. package/lib/utils/load-cip-capacity-display-config.js +61 -15
  301. package/lib/utils/manifest-source-emit.js +2 -0
  302. package/lib/utils/paths.js +25 -0
  303. package/lib/utils/pipeline-upload-auth-retry.js +82 -0
  304. package/lib/utils/platform-controller-url.js +157 -0
  305. package/lib/utils/platform-kv-ref.js +57 -0
  306. package/lib/utils/postgres-platform-bootstrap.js +199 -0
  307. package/lib/utils/postgres-wipe.js +9 -2
  308. package/lib/utils/resolve-env-mode.js +47 -0
  309. package/lib/utils/runtime-configuration-download.js +189 -0
  310. package/lib/utils/runtime-configuration-values.js +119 -0
  311. package/lib/utils/schema-loader.js +19 -4
  312. package/lib/utils/secrets-generator.js +31 -25
  313. package/lib/utils/secrets-missing-error.js +164 -0
  314. package/lib/utils/service-url-label.js +81 -0
  315. package/lib/utils/setup-quiet-output.js +25 -0
  316. package/lib/utils/template-helpers.js +15 -0
  317. package/lib/utils/token-manager-client-credentials.js +201 -0
  318. package/lib/utils/token-manager-messages.js +8 -0
  319. package/lib/utils/token-manager-refresh.js +12 -2
  320. package/lib/utils/token-manager.js +86 -105
  321. package/lib/utils/upload-pipeline-ui.js +12 -5
  322. package/lib/utils/upload-sync-options.js +42 -0
  323. package/lib/utils/url-declarative-public-base.js +21 -3
  324. package/lib/utils/url-declarative-vdir-inactive-env.js +14 -4
  325. package/lib/utils/validation-poll-ui.js +8 -0
  326. package/lib/utils/validation-run-stage.js +45 -0
  327. package/lib/utils/worker-sidecars.js +142 -0
  328. package/lib/validation/external-manifest-validator.js +2 -0
  329. package/lib/validation/runtime-configuration-rules.js +98 -0
  330. package/lib/validation/validate-display-dimensions.js +154 -0
  331. package/lib/validation/validate-display-sections.js +276 -0
  332. package/lib/validation/validate-display-steps.js +67 -0
  333. package/lib/validation/validate-display.js +24 -402
  334. package/package.json +1 -1
  335. package/templates/applications/dataplane/application.yaml +7 -1
  336. package/templates/applications/dataplane/env.template +50 -14
  337. package/templates/applications/dataplane/rbac.yaml +108 -1
  338. package/templates/applications/miso-controller/application.yaml +2 -2
  339. package/templates/applications/miso-controller/env.template +53 -122
  340. package/templates/applications/miso-controller/rbac.yaml +28 -13
  341. package/templates/channels/chatgpt/install.template.md.hbs +49 -0
  342. package/templates/channels/chatgpt/manifest.template.json.hbs +9 -0
  343. package/templates/channels/microsoft-copilot/install.template.md.hbs +49 -0
  344. package/templates/channels/microsoft-copilot/manifest.template.json.hbs +8 -0
  345. package/templates/channels/slack/install.template.md.hbs +49 -0
  346. package/templates/channels/slack/manifest.template.json.hbs +66 -0
  347. package/templates/channels/teams-bot/install.template.md.hbs +49 -0
  348. package/templates/channels/teams-bot/manifest.template.json.hbs +13 -0
  349. package/templates/channels/web-embed/install.template.md.hbs +49 -0
  350. package/templates/channels/web-embed/manifest.template.json.hbs +8 -0
  351. package/templates/external-system/README.md.hbs +74 -17
  352. package/templates/python/docker-compose.hbs +75 -18
  353. package/templates/typescript/docker-compose.hbs +70 -17
  354. package/lib/commands/test-governance-command-action.js +0 -55
  355. package/lib/commands/test-trust-command-action.js +0 -118
@@ -11,9 +11,10 @@
11
11
  const chalk = require('chalk');
12
12
  const logger = require('./logger');
13
13
  const { execWithDockerEnv } = require('./docker-exec');
14
+ const { buildDevImageName } = require('./image-name');
14
15
  const {
15
- resolveDockerImageRef,
16
- getRepositoryPathFromConfig
16
+ getRepositoryPathFromConfig,
17
+ resolveDockerImageRef
17
18
  } = require('./resolve-docker-image-ref');
18
19
 
19
20
  /**
@@ -47,20 +48,44 @@ function repositoryTail(repoPath) {
47
48
  return parts[parts.length - 1] || repoPath;
48
49
  }
49
50
 
51
+ /**
52
+ * Remove registry host prefix from a Docker repository path (local build only).
53
+ * @param {string} repository
54
+ * @returns {string}
55
+ */
56
+ function stripRegistryHostFromRepository(repository) {
57
+ if (!repository || typeof repository !== 'string') {
58
+ return repository;
59
+ }
60
+ const parts = repository.split('/');
61
+ if (parts.length <= 1) {
62
+ return repository;
63
+ }
64
+ const host = parts[0];
65
+ if (host.includes('.') || host.includes(':') || host === 'localhost') {
66
+ return parts.slice(1).join('/');
67
+ }
68
+ return repository;
69
+ }
70
+
50
71
  /**
51
72
  * Strip dev-scoped or -extra suffix from a Docker repository path.
52
73
  * @param {string} repo
53
74
  * @returns {string}
54
75
  */
55
76
  function baseRepositoryFromDevScoped(repo) {
56
- const devMatch = repo.match(/^(.*)-dev\d+$/);
77
+ const localRepo = stripRegistryHostFromRepository(repo);
78
+ const tail = repositoryTail(localRepo);
79
+ const devMatch = tail.match(/^(.*)-dev\d+$/);
57
80
  if (devMatch) {
58
- return devMatch[1];
81
+ const prefix = localRepo.slice(0, localRepo.length - tail.length);
82
+ return `${prefix}${devMatch[1]}`;
59
83
  }
60
- if (repo.endsWith('-extra')) {
61
- return repo.slice(0, -'-extra'.length);
84
+ if (tail.endsWith('-extra')) {
85
+ const prefix = localRepo.slice(0, localRepo.length - tail.length);
86
+ return `${prefix}${tail.slice(0, -'-extra'.length)}`;
62
87
  }
63
- return repo;
88
+ return localRepo;
64
89
  }
65
90
 
66
91
  /**
@@ -140,7 +165,33 @@ async function discoverLocalBaseImageRepository(appName, developerId) {
140
165
  }
141
166
 
142
167
  /**
143
- * Repository path (may include registry prefix) used for `docker build -t`.
168
+ * Resolve local `docker build -t` repository path(s) from the manifest or discovery.
169
+ * When `application.yaml` declares `image`, the manifest ref is used exactly (registry + name).
170
+ * Developer-scoped `-devN` suffixes apply only when the manifest omits `image` and Docker is scanned.
171
+ *
172
+ * @param {string} appName
173
+ * @param {Object} variables - application manifest
174
+ * @param {string|number} developerId
175
+ * @param {Object} [options] - CLI build options (`base`, `tag`, `registry`)
176
+ * @returns {Promise<{ buildImageName: string, compatBaseName: string|null }>}
177
+ */
178
+ async function resolveBuildDockerTagNames(appName, variables, developerId, options = {}) {
179
+ if (!wantsLocalDockerImageDiscovery(variables)) {
180
+ const { imageName } = resolveDockerImageRef(appName, variables, options);
181
+ return { buildImageName: imageName, compatBaseName: null };
182
+ }
183
+ const baseRepo = await resolveBuildImageRepositoryName(appName, variables, developerId);
184
+ const buildImageName = buildDevImageName(baseRepo, developerId);
185
+ const wantCompat =
186
+ buildImageName !== baseRepo && options && options.base === true;
187
+ return {
188
+ buildImageName,
189
+ compatBaseName: wantCompat ? baseRepo : null
190
+ };
191
+ }
192
+
193
+ /**
194
+ * Repository path for local `docker build -t` when manifest omits `image` (discovery / app key).
144
195
  * @param {string} appName
145
196
  * @param {Object} variables - application manifest
146
197
  * @param {string|number} developerId
@@ -148,18 +199,21 @@ async function discoverLocalBaseImageRepository(appName, developerId) {
148
199
  */
149
200
  async function resolveBuildImageRepositoryName(appName, variables, developerId) {
150
201
  if (!wantsLocalDockerImageDiscovery(variables)) {
151
- return resolveDockerImageRef(appName, variables, {}).imageName;
202
+ return getRepositoryPathFromConfig(variables, appName);
152
203
  }
153
204
  const discovered = await discoverLocalBaseImageRepository(appName, developerId);
154
205
  if (discovered) {
155
- logger.log(chalk.blue(`Using image repository from local Docker: ${discovered}`));
156
- return discovered;
206
+ const localRepo = stripRegistryHostFromRepository(discovered);
207
+ logger.log(chalk.blue(`Using image repository from local Docker: ${localRepo}`));
208
+ return localRepo;
157
209
  }
158
210
  return getRepositoryPathFromConfig(variables, appName);
159
211
  }
160
212
 
161
213
  module.exports = {
214
+ resolveBuildDockerTagNames,
162
215
  resolveBuildImageRepositoryName,
163
216
  wantsLocalDockerImageDiscovery,
164
- pickBaseFromDockerLines
217
+ pickBaseFromDockerLines,
218
+ stripRegistryHostFromRepository
165
219
  };
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Worker companion helpers for run/logs/down lifecycle.
3
+ *
4
+ * @fileoverview Loads application.yaml and resolves worker sidecar app keys
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+ const yaml = require('js-yaml');
12
+ const paths = require('./paths');
13
+ const {
14
+ getWorkerCompanionAppKeys,
15
+ resolveWorkerSidecars
16
+ } = require('./worker-sidecars');
17
+
18
+ /**
19
+ * @param {string} appName
20
+ * @param {object|null|undefined} appConfig
21
+ * @returns {boolean}
22
+ */
23
+ function isCeleryWorkerStackEnabled(appName, appConfig) {
24
+ return resolveWorkerSidecars(appName, appConfig).enabled;
25
+ }
26
+
27
+ /**
28
+ * @param {string} appName
29
+ * @param {object|null|undefined} appConfig
30
+ * @returns {string[]}
31
+ */
32
+ function getCeleryCompanionAppKeys(appName, appConfig) {
33
+ return getWorkerCompanionAppKeys(appName, appConfig);
34
+ }
35
+
36
+ /**
37
+ * @param {string} appName
38
+ * @returns {object|null}
39
+ */
40
+ function loadBuilderApplicationConfig(appName) {
41
+ const configPath = path.join(paths.getBuilderPath(appName), 'application.yaml');
42
+ if (!fs.existsSync(configPath)) {
43
+ return null;
44
+ }
45
+ return yaml.load(fs.readFileSync(configPath, 'utf8'));
46
+ }
47
+
48
+ module.exports = {
49
+ isCeleryWorkerStackEnabled,
50
+ getCeleryCompanionAppKeys,
51
+ loadBuilderApplicationConfig,
52
+ resolveWorkerSidecars
53
+ };
@@ -8,6 +8,7 @@
8
8
 
9
9
  const chalk = require('chalk');
10
10
  const { metadata, sectionTitle } = require('./cli-layout-chalk');
11
+ const { kvRefToSecretSetKey } = require('./secrets-missing-error');
11
12
 
12
13
  /**
13
14
  * @param {string[]} messages - Output lines
@@ -25,34 +26,72 @@ function pushMissingSecretsBodyLines(messages, missingSecretsMatch) {
25
26
  for (const ref of parts) {
26
27
  messages.push(` ${chalk.cyan('-')} ${chalk.white(ref)}`);
27
28
  }
28
- return;
29
+ return parts;
29
30
  }
30
31
  if (parts.length === 1) {
31
32
  messages.push(` ${sectionTitle('Missing secrets:')} ${chalk.white(parts[0])}`);
32
- return;
33
+ return parts;
33
34
  }
34
35
  messages.push(` ${sectionTitle('Missing secrets:')}`);
35
- return;
36
+ return [];
36
37
  }
37
38
  messages.push(` ${chalk.white('Missing secrets in secrets file.')}`);
39
+ return [];
38
40
  }
39
41
 
40
42
  /**
41
- * @param {string[]} messages - Output lines
42
- * @param {RegExpMatchArray|null} fileInfoMatch - File location capture
43
- * @param {RegExpMatchArray|null} resolveMatch - Resolve command capture
43
+ * @param {string} errorMsg
44
+ * @returns {Map<string, string>}
45
+ */
46
+ function parseEnvTemplateLineHints(errorMsg) {
47
+ const map = new Map();
48
+ const re = /^Env-template-line: (kv:\/\/[^\s|]+)\|(.+)$/gm;
49
+ let m;
50
+ while ((m = re.exec(errorMsg)) !== null) {
51
+ map.set(m[1].trim(), m[2].trim());
52
+ }
53
+ return map;
54
+ }
55
+
56
+ /**
57
+ * @param {string[]} messages
58
+ * @param {string[]} missingRefs
59
+ * @param {Map<string, string>} templateLinesByRef
60
+ * @param {string|null} envTemplatePath
44
61
  */
45
- function pushSecretsResolutionHintLines(messages, fileInfoMatch, resolveMatch) {
62
+ function pushRemediationHintLines(messages, missingRefs, templateLinesByRef, envTemplatePath) {
63
+ messages.push(` ${sectionTitle('You can fix this two ways:')}`);
64
+ messages.push(
65
+ ` ${chalk.cyan('1.')} ${chalk.white('Not used by your external system?')} Comment out or delete the line in env.template.`
66
+ );
67
+ if (envTemplatePath) {
68
+ messages.push(` ${metadata('env.template:')} ${chalk.white(envTemplatePath)}`);
69
+ }
70
+ for (const ref of missingRefs) {
71
+ const line = templateLinesByRef.get(ref);
72
+ if (line) {
73
+ messages.push(` ${metadata('Comment or delete:')} ${chalk.gray(line)}`);
74
+ }
75
+ }
76
+ messages.push(
77
+ ` ${chalk.cyan('2.')} ${chalk.white('Store the value:')} ${metadata('aifabrix secret set')} ${chalk.yellow('<key>')} ${chalk.gray('"<your-value>"')}`
78
+ );
79
+ for (const ref of missingRefs) {
80
+ const key = kvRefToSecretSetKey(ref);
81
+ if (key) {
82
+ messages.push(` ${metadata('Example:')} ${chalk.yellow(`aifabrix secret set ${key} "<your-value>"`)}`);
83
+ }
84
+ }
85
+ }
86
+
87
+ /**
88
+ * @param {string[]} messages
89
+ * @param {RegExpMatchArray|null} fileInfoMatch
90
+ */
91
+ function pushSecretsFileLocationLine(messages, fileInfoMatch) {
46
92
  if (fileInfoMatch) {
47
93
  messages.push(` ${metadata('Secrets file location:')} ${chalk.white(fileInfoMatch[1])}`);
48
94
  }
49
- if (resolveMatch) {
50
- messages.push(
51
- ` ${metadata('Run:')} ${chalk.yellow(`aifabrix resolve ${resolveMatch[1]} to generate missing secrets.`)}`
52
- );
53
- return;
54
- }
55
- messages.push(` ${metadata('Run:')} ${chalk.yellow('aifabrix resolve <app-name> to generate missing secrets.')}`);
56
95
  }
57
96
 
58
97
  /**
@@ -66,13 +105,36 @@ function formatSecretsError(errorMsg) {
66
105
  }
67
106
 
68
107
  const messages = [];
69
- pushMissingSecretsBodyLines(messages, errorMsg.match(/Missing secrets: ([^\n]+)/));
70
- pushSecretsResolutionHintLines(
71
- messages,
72
- errorMsg.match(/Secrets file location: ([^\n]+)/),
73
- errorMsg.match(/Run "aifabrix resolve ([^"]+)"/)
74
- );
108
+ const missingRefs = pushMissingSecretsBodyLines(messages, errorMsg.match(/Missing secrets: ([^\n]+)/));
109
+ pushSecretsFileLocationLine(messages, errorMsg.match(/Secrets file location: ([^\n]+)/));
110
+ const envTemplatePathMatch = errorMsg.match(/Env-template-path: ([^\n]+)/);
111
+ const envTemplatePath = envTemplatePathMatch ? envTemplatePathMatch[1].trim() : null;
112
+ const templateLinesByRef = parseEnvTemplateLineHints(errorMsg);
113
+ const refs =
114
+ missingRefs.length > 0
115
+ ? missingRefs
116
+ : [...templateLinesByRef.keys()];
117
+ if (refs.length > 0) {
118
+ pushRemediationHintLines(messages, refs, templateLinesByRef, envTemplatePath);
119
+ }
120
+ const staleMatch = errorMsg.match(/Stale-template-hint: oauth-leftover \| repair ([^\n]+)/);
121
+ if (staleMatch) {
122
+ messages.push(
123
+ ` ${chalk.yellow('⚠')} ${chalk.white('These keys are often left over after switching to apikey/bearerToken auth.')}`
124
+ );
125
+ messages.push(
126
+ ` ${metadata('Run:')} ${chalk.yellow(`aifabrix repair ${staleMatch[1].trim()}`)} ${chalk.gray('to comment stale OAuth lines in env.template')}`
127
+ );
128
+ }
75
129
  return messages;
76
130
  }
77
131
 
78
- module.exports = { formatSecretsError };
132
+ /**
133
+ * @param {string} errorMsg
134
+ * @returns {boolean}
135
+ */
136
+ function isMissingSecretsErrorMessage(errorMsg) {
137
+ return typeof errorMsg === 'string' && errorMsg.includes('Missing secrets');
138
+ }
139
+
140
+ module.exports = { formatSecretsError, isMissingSecretsErrorMessage };
@@ -12,7 +12,7 @@ const path = require('path');
12
12
  const chalk = require('chalk');
13
13
  const logger = require('./logger');
14
14
  const { formatBlockingError, infoLine } = require('./cli-layout-chalk');
15
- const { formatSecretsError } = require('./cli-secrets-error-format');
15
+ const { formatSecretsError, isMissingSecretsErrorMessage } = require('./cli-secrets-error-format');
16
16
  const { getDockerDaemonStartHintSentence, getDockerApiOverTcpHintLines } = require('./docker-not-running-hint');
17
17
 
18
18
  /**
@@ -215,6 +215,10 @@ function formatAzureError(errorMsg) {
215
215
  ' Use format: *.azurecr.io (e.g., myacr.azurecr.io)'
216
216
  ];
217
217
  }
218
+ // Docker build failures may mention azurecr.io in the local tag; show the real build error instead.
219
+ if (errorMsg.includes('Docker build failed') || errorMsg.includes('Build failed: Docker')) {
220
+ return null;
221
+ }
218
222
  // Only match ACR-specific authentication errors, not general authentication failures
219
223
  if (errorMsg.includes('ACR') || errorMsg.includes('azurecr.io') ||
220
224
  (errorMsg.includes('authenticate') && (errorMsg.includes('registry') || errorMsg.includes('container')))) {
@@ -337,6 +341,15 @@ function formatError(error) {
337
341
  return formatFormattedError(error.formatted);
338
342
  }
339
343
 
344
+ if (error.network === true) {
345
+ const { formatNetworkError } = require('./api-error-handler');
346
+ const formatted = formatNetworkError(error.message || 'Network error', {
347
+ endpointUrl: error.endpointUrl,
348
+ serviceLabel: error.serviceLabel || 'service'
349
+ });
350
+ return formatFormattedError(formatted);
351
+ }
352
+
340
353
  const errorMsg = error.message || '';
341
354
 
342
355
  // Try different error formatters in order of specificity
@@ -355,10 +368,12 @@ function formatError(error) {
355
368
  * @param {string} command - Command that failed
356
369
  * @param {string[]} errorMessages - Error message lines
357
370
  */
358
- function logError(command, errorMessages) {
371
+ function logError(command, errorMessages, options = {}) {
359
372
  logger.error(`\n${formatBlockingError(`Error in ${command} command:`)}`);
360
373
  errorMessages.forEach(msg => logger.error(msg));
361
- logger.log(`\n${infoLine('ℹ Run "aifabrix doctor" for environment diagnostics.')}\n`);
374
+ if (!options.skipDoctor) {
375
+ logger.log(`\n${infoLine('ℹ Run "aifabrix doctor" for environment diagnostics.')}\n`);
376
+ }
362
377
  }
363
378
 
364
379
  /**
@@ -396,7 +411,8 @@ function isAuthenticationError(error) {
396
411
  */
397
412
  function handleCommandError(error, command) {
398
413
  const errorMessages = formatError(error);
399
- logError(command, errorMessages);
414
+ const skipDoctor = isMissingSecretsErrorMessage(error && error.message);
415
+ logError(command, errorMessages, { skipDoctor });
400
416
  if (error.wizardResumeMessage) {
401
417
  logger.log(error.wizardResumeMessage);
402
418
  }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Worker/beat compose fragment for local runs.
3
+ *
4
+ * @fileoverview Compose context for optional worker and beat services from application.yaml
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { buildWorkerSidecarComposeContext } = require('./worker-sidecars');
10
+
11
+ /**
12
+ * @param {string} appKey
13
+ * @param {object} appConfig
14
+ * @param {{ devId: string|number, idNum: number }} ids
15
+ * @returns {ReturnType<typeof buildWorkerSidecarComposeContext>}
16
+ */
17
+ function buildCeleryWorkerComposeContext(appKey, appConfig, ids) {
18
+ return buildWorkerSidecarComposeContext(appKey, appConfig, ids);
19
+ }
20
+
21
+ module.exports = {
22
+ buildCeleryWorkerComposeContext
23
+ };
@@ -14,6 +14,7 @@ const buildCopy = require('./build-copy');
14
14
  const paths = require('./paths');
15
15
  const { getInfraDirName } = require('../infrastructure/helpers');
16
16
  const { resolveMisoEnvironment } = require('./compose-miso-env');
17
+ const { buildCeleryWorkerComposeContext } = require('./compose-celery-worker');
17
18
 
18
19
  /**
19
20
  * When running a pulled Python image (no bind-mounted source), the image CMD may invoke the
@@ -61,6 +62,10 @@ function normalizePythonReloadForComposeMounted(raw) {
61
62
  if (/^python3?\s+-m\s+uvicorn\s+/i.test(s)) {
62
63
  return s;
63
64
  }
65
+ const envPrefixed = s.match(/^((?:[A-Za-z_][A-Za-z0-9_]*=\S+\s+)*)(uvicorn\s+.*)$/);
66
+ if (envPrefixed) {
67
+ return `${envPrefixed[1]}python -m uvicorn ${envPrefixed[2].slice('uvicorn '.length)}`;
68
+ }
64
69
  if (s.startsWith('uvicorn ')) {
65
70
  return `python -m uvicorn ${s.slice('uvicorn '.length)}`;
66
71
  }
@@ -145,7 +150,11 @@ function buildComposeTemplateContext(ctx) {
145
150
  devMountPath: ctx.devMountPath,
146
151
  reloadStartCommand: ctx.reloadStartCommand,
147
152
  infraPgpassPath: ctx.useInfraPgpass ? ctx.infraPgpassPath : null,
148
- useInfraPgpass: !!ctx.useInfraPgpass
153
+ useInfraPgpass: !!ctx.useInfraPgpass,
154
+ workerSidecars: buildCeleryWorkerComposeContext(ctx.appName, ctx.appConfig, {
155
+ devId: ctx.devId,
156
+ idNum: ctx.idNum
157
+ })
149
158
  };
150
159
  }
151
160
 
@@ -299,6 +308,9 @@ async function generateDockerComposeImpl(deps, appName, appConfig, options) {
299
308
  ...layouts,
300
309
  ...side,
301
310
  idNum: head.idNum,
311
+ appName,
312
+ appConfig,
313
+ devId: head.devId,
302
314
  options
303
315
  })
304
316
  );
@@ -86,6 +86,19 @@ function expandFrontDoorHostPlaceholders(template, developerIdRaw, remoteServer)
86
86
  return t;
87
87
  }
88
88
 
89
+ function templateUsesRemoteHostPlaceholder(hostTemplate) {
90
+ return /\$\{REMOTE_HOST\}/.test(String(hostTemplate || ''));
91
+ }
92
+
93
+ function resolveTraefikRouterHost(hostTemplate, developerIdRaw, remoteServer) {
94
+ const usesRemote = templateUsesRemoteHostPlaceholder(hostTemplate);
95
+ const hasRemote = Boolean(remoteServer && String(remoteServer).trim());
96
+ if (usesRemote && !hasRemote) {
97
+ return 'localhost';
98
+ }
99
+ return expandFrontDoorHostPlaceholders(hostTemplate, developerIdRaw, remoteServer);
100
+ }
101
+
89
102
  /**
90
103
  * Traefik PathPrefix / host / TLS from frontDoorRouting (public ingress). Does not include StripPrefix — that follows
91
104
  * the in-container health path: private URL is `http://<service>:<port>` plus the probe path; `/dev`, `/tst`, `/auth`,
@@ -105,7 +118,7 @@ function buildTraefikIngressBase(config, devId, scopeOpts, remoteServer) {
105
118
  if (!frontDoor.host || typeof frontDoor.host !== 'string') {
106
119
  throw new Error('frontDoorRouting.host is required when frontDoorRouting.enabled is true');
107
120
  }
108
- const host = expandFrontDoorHostPlaceholders(frontDoor.host, devId, remoteServer);
121
+ const host = resolveTraefikRouterHost(frontDoor.host, devId, remoteServer);
109
122
  const basePath = derivePathFromPattern(frontDoor.pattern);
110
123
  let pathOut = basePath;
111
124
  if (
@@ -153,6 +166,8 @@ module.exports = {
153
166
  resolveTraefikTlsEnabled,
154
167
  buildDevUsernameForFrontDoorHost,
155
168
  expandFrontDoorHostPlaceholders,
169
+ templateUsesRemoteHostPlaceholder,
170
+ resolveTraefikRouterHost,
156
171
  buildTraefikIngressBase,
157
172
  computeTraefikStripPathPrefix
158
173
  };
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Secrets path config helpers.
3
+ *
4
+ * @fileoverview Keeps lib/core/config.js under max-lines
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const os = require('os');
10
+ const path = require('path');
11
+
12
+ /**
13
+ * Expand leading ~ to home directory so config paths like ~/.aifabrix/secrets.local.yaml resolve correctly.
14
+ * @param {string} filePath - Path that may start with ~ or ~/
15
+ * @returns {string} Path with ~ expanded, or unchanged if no leading ~
16
+ */
17
+ function expandTilde(filePath) {
18
+ if (!filePath || typeof filePath !== 'string') return filePath;
19
+ if (filePath === '~') return os.homedir();
20
+ if (filePath.startsWith('~/') || filePath.startsWith('~' + path.sep)) {
21
+ return path.join(os.homedir(), filePath.slice(2));
22
+ }
23
+ return filePath;
24
+ }
25
+
26
+ function createSecretsPathFunctions(getConfig, saveConfig) {
27
+ async function getSecretsPath() {
28
+ const cfg = await getConfig();
29
+ const raw = cfg['aifabrix-secrets'] || cfg['secrets-path'] || null;
30
+ return raw ? expandTilde(raw) : null;
31
+ }
32
+
33
+ async function setSecretsPath(secretsPath) {
34
+ if (typeof secretsPath !== 'string') {
35
+ throw new Error('Secrets path is required and must be a string');
36
+ }
37
+ const cfg = await getConfig();
38
+ cfg['aifabrix-secrets'] = secretsPath.trim() || undefined;
39
+ await saveConfig(cfg);
40
+ }
41
+
42
+ return { getSecretsPath, setSecretsPath };
43
+ }
44
+
45
+ module.exports = { createSecretsPathFunctions };
46
+
@@ -190,6 +190,40 @@ function retemplateConfigurationFromEnvTemplate(configArray, envTemplateVariable
190
190
  }
191
191
  }
192
192
 
193
+ /**
194
+ * Re-templates every system variable definition to {{NAME}} (download/export safe).
195
+ *
196
+ * @param {Array<{ name?: string, location?: string }>} configArray - Configuration array (mutated)
197
+ */
198
+ function retemplateAllVariableDefinitions(configArray) {
199
+ if (!Array.isArray(configArray)) return;
200
+ for (const item of configArray) {
201
+ if (!item || String(item.location || 'variable').toLowerCase() !== 'variable') continue;
202
+ const name = item.name && String(item.name).trim();
203
+ if (name) {
204
+ item.value = `{{${name}}}`;
205
+ }
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Re-templates datasource override literals to {{NAME}} placeholders.
211
+ *
212
+ * @param {Array<{ name?: string, value?: string }>} configArray - Datasource configuration (mutated)
213
+ */
214
+ function retemplateDatasourceConfigurationOverrides(configArray) {
215
+ if (!Array.isArray(configArray)) return;
216
+ for (const item of configArray) {
217
+ if (!item || !item.name) continue;
218
+ const name = String(item.name).trim();
219
+ const raw = item.value;
220
+ if (typeof raw !== 'string') continue;
221
+ const value = raw.trim();
222
+ if (!value || value.startsWith('kv://') || value.includes('{{')) continue;
223
+ item.value = `{{${name}}}`;
224
+ }
225
+ }
226
+
193
227
  /**
194
228
  * Reads env.template at integration path, re-templates the given configuration array,
195
229
  * and returns the updated array (mutates in place). If env.template is missing, does nothing.
@@ -215,6 +249,8 @@ module.exports = {
215
249
  collectResolvedVariableConfigurationNames,
216
250
  getEnvTemplateVariableNames,
217
251
  retemplateConfigurationFromEnvTemplate,
252
+ retemplateAllVariableDefinitions,
253
+ retemplateDatasourceConfigurationOverrides,
218
254
  retemplateConfigurationForDownload,
219
255
  substituteVarPlaceholders
220
256
  };