@aifabrix/builder 2.43.0 → 2.44.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (371) hide show
  1. package/.cursor/rules/anchor-docs.mdc +15 -0
  2. package/.cursor/rules/cli-layout.mdc +75 -0
  3. package/.cursor/rules/project-rules.mdc +8 -0
  4. package/.npmrc.token +1 -0
  5. package/.nyc_output/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
  6. package/.nyc_output/processinfo/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
  7. package/.nyc_output/processinfo/index.json +1 -0
  8. package/README.md +1 -1
  9. package/anchor-docs/README.md +10 -0
  10. package/anchor-docs/_TEMPLATE +24 -0
  11. package/bin/aifabrix.js +13 -4
  12. package/integration/hubspot-test/README.md +31 -0
  13. package/integration/hubspot-test/create-hubspot.js +5 -5
  14. package/integration/hubspot-test/hubspot-test-datasource-company.json +58 -462
  15. package/integration/hubspot-test/hubspot-test-datasource-contact.json +61 -555
  16. package/integration/hubspot-test/hubspot-test-datasource-deal.json +63 -506
  17. package/integration/hubspot-test/hubspot-test-datasource-users.json +42 -83
  18. package/integration/hubspot-test/hubspot-test-deploy.json +3 -3
  19. package/integration/hubspot-test/test-dataplane-down-tests.js +1 -7
  20. package/integration/hubspot-test/test-dataplane-down.js +3 -3
  21. package/integration/hubspot-test/test.js +35 -43
  22. package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
  23. package/integration/roundtrip-test-local/README.md +144 -0
  24. package/integration/roundtrip-test-local/application.yaml +13 -0
  25. package/integration/roundtrip-test-local/env.template +15 -0
  26. package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
  27. package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
  28. package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
  29. package/integration/roundtrip-test-local2/README.md +144 -0
  30. package/integration/roundtrip-test-local2/application.yaml +13 -0
  31. package/integration/roundtrip-test-local2/env.template +15 -0
  32. package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
  33. package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
  34. package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
  35. package/integration/test/wizard.yaml +8 -0
  36. package/jest.config.default.js +10 -0
  37. package/jest.config.integration.fixtures.js +22 -0
  38. package/jest.config.integration.js +21 -18
  39. package/jest.config.isolated.js +10 -0
  40. package/jest.projects.js +301 -0
  41. package/lib/api/certificates.api.js +62 -0
  42. package/lib/api/datasources-core.api.js +3 -3
  43. package/lib/api/dev-mtls-request.js +110 -0
  44. package/lib/api/dev-server-https.js +145 -0
  45. package/lib/api/dev.api.js +133 -144
  46. package/lib/api/index.js +11 -3
  47. package/lib/api/pipeline.api.js +67 -20
  48. package/lib/api/types/certificates.types.js +48 -0
  49. package/lib/api/types/dev.types.js +4 -3
  50. package/lib/api/types/pipeline.types.js +8 -5
  51. package/lib/api/types/validation-run.types.js +56 -0
  52. package/lib/api/validation-run.api.js +111 -0
  53. package/lib/api/validation-runner.js +109 -0
  54. package/lib/app/certification-show-enrich.js +129 -0
  55. package/lib/app/certification-verify-rows.js +60 -0
  56. package/lib/app/config.js +1 -1
  57. package/lib/app/deploy-status-display.js +2 -2
  58. package/lib/app/deploy.js +7 -6
  59. package/lib/app/display.js +2 -1
  60. package/lib/app/dockerfile.js +3 -2
  61. package/lib/app/down.js +2 -1
  62. package/lib/app/helpers.js +6 -5
  63. package/lib/app/index.js +27 -8
  64. package/lib/app/list.js +7 -6
  65. package/lib/app/push.js +4 -3
  66. package/lib/app/register.js +16 -7
  67. package/lib/app/rotate-secret.js +14 -13
  68. package/lib/app/run-container-start.js +184 -0
  69. package/lib/app/run-docker-fallback.js +108 -0
  70. package/lib/app/run-env-compose.js +30 -42
  71. package/lib/app/run-helpers.js +49 -126
  72. package/lib/app/run-infra-requirements.js +30 -0
  73. package/lib/app/run-resolve-image.js +21 -0
  74. package/lib/app/run.js +74 -21
  75. package/lib/app/show-display.js +44 -1
  76. package/lib/app/show.js +93 -9
  77. package/lib/build/index.js +13 -10
  78. package/lib/certification/cli-cert-sync-skip.js +21 -0
  79. package/lib/certification/merge-certification-from-artifact.js +185 -0
  80. package/lib/certification/post-unified-cert-sync.js +33 -0
  81. package/lib/certification/sync-after-external-command.js +52 -0
  82. package/lib/certification/sync-system-certification.js +197 -0
  83. package/lib/cli/index.js +2 -0
  84. package/lib/cli/setup-app.help.js +67 -0
  85. package/lib/cli/setup-app.js +61 -121
  86. package/lib/cli/setup-app.test-commands.js +195 -0
  87. package/lib/cli/setup-auth.js +19 -5
  88. package/lib/cli/setup-credential-deployment.js +22 -8
  89. package/lib/cli/setup-dev-path-commands.js +124 -0
  90. package/lib/cli/setup-dev.js +170 -113
  91. package/lib/cli/setup-environment.js +7 -1
  92. package/lib/cli/setup-external-system.js +84 -23
  93. package/lib/cli/setup-infra.js +126 -47
  94. package/lib/cli/setup-parameters.js +32 -0
  95. package/lib/cli/setup-secrets.js +137 -18
  96. package/lib/cli/setup-service-user.js +1 -1
  97. package/lib/cli/setup-utility.js +54 -22
  98. package/lib/commands/app-down.js +5 -7
  99. package/lib/commands/app-install.js +14 -7
  100. package/lib/commands/app-logs.js +13 -10
  101. package/lib/commands/app-shell.js +4 -1
  102. package/lib/commands/app-test.js +25 -19
  103. package/lib/commands/app.js +32 -11
  104. package/lib/commands/auth-config.js +6 -6
  105. package/lib/commands/auth-status.js +4 -3
  106. package/lib/commands/credential-env.js +4 -3
  107. package/lib/commands/credential-list.js +5 -4
  108. package/lib/commands/credential-push.js +4 -3
  109. package/lib/commands/datasource-unified-test-cli.js +428 -0
  110. package/lib/commands/datasource-unified-test-cli.options.js +191 -0
  111. package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +106 -0
  112. package/lib/commands/datasource-validation-cli.js +143 -0
  113. package/lib/commands/datasource.js +125 -95
  114. package/lib/commands/deployment-list.js +6 -5
  115. package/lib/commands/dev-cli-handlers.js +122 -18
  116. package/lib/commands/dev-down.js +4 -3
  117. package/lib/commands/dev-init.js +231 -116
  118. package/lib/commands/dev-show-display.js +473 -0
  119. package/lib/commands/login-credentials.js +3 -2
  120. package/lib/commands/login-device.js +4 -3
  121. package/lib/commands/login.js +5 -4
  122. package/lib/commands/logout.js +8 -7
  123. package/lib/commands/parameters-validate.js +54 -0
  124. package/lib/commands/repair-datasource.js +314 -68
  125. package/lib/commands/repair-env-template.js +2 -2
  126. package/lib/commands/repair.js +21 -3
  127. package/lib/commands/secrets-list.js +23 -12
  128. package/lib/commands/secrets-remove-all.js +220 -0
  129. package/lib/commands/secrets-remove.js +21 -12
  130. package/lib/commands/secrets-set.js +21 -12
  131. package/lib/commands/secrets-validate.js +4 -4
  132. package/lib/commands/secure.js +10 -9
  133. package/lib/commands/service-user.js +26 -25
  134. package/lib/commands/test-e2e-external.js +27 -1
  135. package/lib/commands/up-common.js +3 -2
  136. package/lib/commands/up-dataplane.js +29 -16
  137. package/lib/commands/up-miso.js +19 -29
  138. package/lib/commands/upload.js +149 -39
  139. package/lib/commands/wizard-core-helpers.js +1 -1
  140. package/lib/commands/wizard-dataplane.js +4 -3
  141. package/lib/commands/wizard-helpers.js +3 -3
  142. package/lib/commands/wizard.js +2 -2
  143. package/lib/core/admin-secrets.js +14 -5
  144. package/lib/core/audit-logger.js +12 -4
  145. package/lib/core/config-attach-extensions.js +46 -0
  146. package/lib/core/config-runtime-paths.js +29 -0
  147. package/lib/core/config.js +55 -56
  148. package/lib/core/diff.js +3 -2
  149. package/lib/core/ensure-encryption-key.js +1 -1
  150. package/lib/core/secrets-ensure-infra.js +77 -0
  151. package/lib/core/secrets-ensure.js +120 -64
  152. package/lib/core/secrets-env-write.js +35 -7
  153. package/lib/core/secrets-infra-placeholder-sync.js +61 -0
  154. package/lib/core/secrets.js +200 -37
  155. package/lib/core/templates-env.js +4 -3
  156. package/lib/datasource/abac-validator.js +1 -10
  157. package/lib/datasource/deploy.js +75 -53
  158. package/lib/datasource/field-reference-validator.js +9 -6
  159. package/lib/datasource/integration-context.js +63 -0
  160. package/lib/datasource/list.js +8 -7
  161. package/lib/datasource/log-viewer.js +189 -67
  162. package/lib/datasource/resolve-app.js +4 -4
  163. package/lib/datasource/test-e2e.js +113 -146
  164. package/lib/datasource/test-integration.js +114 -122
  165. package/lib/datasource/unified-validation-run-body.js +68 -0
  166. package/lib/datasource/unified-validation-run-post.js +23 -0
  167. package/lib/datasource/unified-validation-run-resolve.js +43 -0
  168. package/lib/datasource/unified-validation-run.js +93 -0
  169. package/lib/datasource/validate.js +157 -13
  170. package/lib/deployment/deployer.js +4 -3
  171. package/lib/deployment/environment.js +7 -6
  172. package/lib/deployment/push.js +17 -8
  173. package/lib/external-system/delete.js +4 -3
  174. package/lib/external-system/deploy.js +166 -53
  175. package/lib/external-system/download-helpers.js +1 -1
  176. package/lib/external-system/download.js +7 -6
  177. package/lib/external-system/generator.js +92 -6
  178. package/lib/external-system/integration-test-dispatch.js +26 -0
  179. package/lib/external-system/test-execution.js +5 -1
  180. package/lib/external-system/test-helpers.js +0 -4
  181. package/lib/external-system/test-system-level-helpers.js +110 -0
  182. package/lib/external-system/test-system-level.js +83 -44
  183. package/lib/external-system/test.js +59 -8
  184. package/lib/generator/builders.js +23 -11
  185. package/lib/generator/deploy-manifest-azure-kv.js +81 -0
  186. package/lib/generator/external.js +16 -4
  187. package/lib/generator/helpers.js +58 -3
  188. package/lib/generator/index.js +4 -0
  189. package/lib/generator/split-readme.js +12 -7
  190. package/lib/generator/split-variables.js +2 -1
  191. package/lib/generator/split.js +1 -1
  192. package/lib/generator/wizard-readme.js +3 -3
  193. package/lib/generator/wizard.js +8 -8
  194. package/lib/infrastructure/compose.js +70 -7
  195. package/lib/infrastructure/helpers-docker-check.js +67 -0
  196. package/lib/infrastructure/helpers.js +203 -42
  197. package/lib/infrastructure/index.js +31 -18
  198. package/lib/infrastructure/services.js +21 -67
  199. package/lib/internal/fs-real-sync.js +104 -0
  200. package/lib/internal/node-fs.js +98 -0
  201. package/lib/parameters/database-secret-values.js +173 -0
  202. package/lib/parameters/infra-kv-discovery.js +121 -0
  203. package/lib/parameters/infra-parameter-catalog.js +458 -0
  204. package/lib/parameters/infra-parameter-validate.js +64 -0
  205. package/lib/schema/application-schema.json +37 -17
  206. package/lib/schema/datasource-test-run.schema.json +493 -0
  207. package/lib/schema/deployment-rules.yaml +102 -63
  208. package/lib/schema/external-datasource.schema.json +1200 -442
  209. package/lib/schema/external-system.schema.json +203 -5
  210. package/lib/schema/flag-map-validation-run.json +31 -0
  211. package/lib/schema/infra-parameter.schema.json +106 -0
  212. package/lib/schema/infra.parameter.yaml +421 -0
  213. package/lib/schema/type/credential-auth-templates.json +40 -0
  214. package/lib/schema/type/document-storage.json +226 -0
  215. package/lib/schema/type/message-service.json +123 -0
  216. package/lib/schema/type/vector-store.json +88 -0
  217. package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
  218. package/lib/utils/api-error-handler.js +2 -2
  219. package/lib/utils/api.js +77 -17
  220. package/lib/utils/app-register-api.js +3 -2
  221. package/lib/utils/app-register-auth.js +1 -1
  222. package/lib/utils/app-register-config.js +4 -4
  223. package/lib/utils/app-register-display.js +3 -2
  224. package/lib/utils/app-register-validator.js +3 -2
  225. package/lib/utils/app-run-containers.js +26 -22
  226. package/lib/utils/app-scoped-config.js +31 -0
  227. package/lib/utils/app-service-env-from-builder.js +164 -0
  228. package/lib/utils/build-copy.js +1 -1
  229. package/lib/utils/build-helpers.js +20 -20
  230. package/lib/utils/build-resolve-image.js +165 -0
  231. package/lib/utils/cli-layout-chalk.js +8 -0
  232. package/lib/utils/cli-test-layout-chalk.js +267 -0
  233. package/lib/utils/cli-utils.js +88 -11
  234. package/lib/utils/compose-db-passwords.js +138 -0
  235. package/lib/utils/compose-generate-docker-compose.js +216 -0
  236. package/lib/utils/compose-generator.js +197 -291
  237. package/lib/utils/compose-miso-env.js +18 -0
  238. package/lib/utils/compose-traefik-ingress-base.js +158 -0
  239. package/lib/utils/config-paths.js +166 -7
  240. package/lib/utils/config-scoped-resources-preference.js +41 -0
  241. package/lib/utils/configuration-env-resolver.js +11 -8
  242. package/lib/utils/controller-deployment-outcome.js +68 -0
  243. package/lib/utils/credential-display.js +2 -2
  244. package/lib/utils/credential-secrets-env.js +5 -5
  245. package/lib/utils/dataplane-pipeline-warning.js +4 -3
  246. package/lib/utils/datasource-test-run-capability-scope.js +43 -0
  247. package/lib/utils/datasource-test-run-certificate-tty.js +82 -0
  248. package/lib/utils/datasource-test-run-debug-display.js +137 -0
  249. package/lib/utils/datasource-test-run-debug-slice.js +93 -0
  250. package/lib/utils/datasource-test-run-display.js +459 -0
  251. package/lib/utils/datasource-test-run-exit.js +83 -0
  252. package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
  253. package/lib/utils/datasource-test-run-report-version.js +51 -0
  254. package/lib/utils/datasource-test-run-schema-sync.js +59 -0
  255. package/lib/utils/datasource-test-run-tty-log.js +81 -0
  256. package/lib/utils/datasource-validation-watch.js +266 -0
  257. package/lib/utils/declarative-url-ports.js +47 -0
  258. package/lib/utils/derive-env-key-from-client-id.js +41 -0
  259. package/lib/utils/dev-ca-install.js +185 -23
  260. package/lib/utils/dev-cert-helper.js +266 -17
  261. package/lib/utils/dev-hosts-helper.js +307 -0
  262. package/lib/utils/dev-init-cert-hints.js +37 -0
  263. package/lib/utils/dev-init-health-messages.js +52 -0
  264. package/lib/utils/dev-init-resolve.js +86 -0
  265. package/lib/utils/dev-init-ssh-merge.js +65 -0
  266. package/lib/utils/dev-ssh-config-helper.js +196 -0
  267. package/lib/utils/dev-user-groups.js +93 -0
  268. package/lib/utils/docker-build.js +42 -17
  269. package/lib/utils/docker-exec.js +28 -0
  270. package/lib/utils/docker-manifest-public-port.js +116 -0
  271. package/lib/utils/docker-not-running-hint.js +52 -0
  272. package/lib/utils/docker.js +98 -11
  273. package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
  274. package/lib/utils/env-config-loader.js +10 -91
  275. package/lib/utils/env-copy.js +19 -10
  276. package/lib/utils/env-map.js +35 -8
  277. package/lib/utils/env-template.js +2 -2
  278. package/lib/utils/environment-scoped-resources.js +144 -0
  279. package/lib/utils/error-formatter.js +92 -13
  280. package/lib/utils/error-formatters/http-status-errors.js +6 -5
  281. package/lib/utils/error-formatters/network-errors.js +2 -1
  282. package/lib/utils/error-formatters/permission-errors.js +2 -1
  283. package/lib/utils/error-formatters/validation-errors.js +2 -1
  284. package/lib/utils/external-readme.js +8 -1
  285. package/lib/utils/external-system-display.js +242 -136
  286. package/lib/utils/external-system-local-test-tty.js +389 -0
  287. package/lib/utils/external-system-readiness-core.js +377 -0
  288. package/lib/utils/external-system-readiness-deploy-display.js +270 -0
  289. package/lib/utils/external-system-readiness-display-internals.js +150 -0
  290. package/lib/utils/external-system-readiness-display.js +186 -0
  291. package/lib/utils/external-system-system-test-tty-overview.js +120 -0
  292. package/lib/utils/external-system-system-test-tty.js +417 -0
  293. package/lib/utils/external-system-test-helpers.js +24 -6
  294. package/lib/utils/external-system-validators.js +30 -12
  295. package/lib/utils/health-check-url.js +119 -0
  296. package/lib/utils/health-check.js +59 -25
  297. package/lib/utils/help-builder.js +11 -8
  298. package/lib/utils/image-version.js +4 -8
  299. package/lib/utils/infra-containers.js +4 -7
  300. package/lib/utils/infra-env-defaults.js +162 -0
  301. package/lib/utils/infra-status-display.js +167 -0
  302. package/lib/utils/infra-status.js +16 -8
  303. package/lib/utils/local-secrets.js +3 -4
  304. package/lib/utils/paths.js +148 -47
  305. package/lib/utils/port-resolver.js +10 -23
  306. package/lib/utils/redis-env-scope.js +62 -0
  307. package/lib/utils/register-aifabrix-shell-env.js +204 -0
  308. package/lib/utils/remote-builder-validation.js +99 -0
  309. package/lib/utils/remote-dev-auth.js +117 -21
  310. package/lib/utils/remote-docker-env.js +67 -15
  311. package/lib/utils/remote-secrets-loader.js +13 -4
  312. package/lib/utils/resolve-docker-image-ref.js +124 -0
  313. package/lib/utils/schema-loader.js +22 -9
  314. package/lib/utils/secrets-bash-kv.js +25 -0
  315. package/lib/utils/secrets-generator.js +169 -49
  316. package/lib/utils/secrets-helpers.js +70 -59
  317. package/lib/utils/secrets-kv-scope.js +60 -0
  318. package/lib/utils/secrets-utils.js +32 -38
  319. package/lib/utils/secrets-validation.js +3 -1
  320. package/lib/utils/secrets-yaml-preserve.js +109 -0
  321. package/lib/utils/ssh-key-helper.js +4 -2
  322. package/lib/utils/template-helpers.js +2 -2
  323. package/lib/utils/test-log-writer.js +3 -3
  324. package/lib/utils/token-manager.js +1 -2
  325. package/lib/utils/url-declarative-public-base.js +188 -0
  326. package/lib/utils/url-declarative-resolve-build.js +493 -0
  327. package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
  328. package/lib/utils/url-declarative-resolve.js +220 -0
  329. package/lib/utils/url-declarative-token-parse.js +74 -0
  330. package/lib/utils/url-declarative-url-flags.js +50 -0
  331. package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
  332. package/lib/utils/url-public-path-prefix.js +34 -0
  333. package/lib/utils/urls-local-registry.js +220 -0
  334. package/lib/utils/validation-report-tty-kit.js +77 -0
  335. package/lib/utils/validation-run-poll.js +112 -0
  336. package/lib/utils/validation-run-post-retry.js +85 -0
  337. package/lib/utils/validation-run-request.js +116 -0
  338. package/lib/utils/variable-transformer.js +21 -4
  339. package/lib/utils/yaml-preserve.js +33 -14
  340. package/lib/validation/datasource-warnings.js +56 -0
  341. package/lib/validation/env-template-auth.js +1 -1
  342. package/lib/validation/external-manifest-validator.js +27 -7
  343. package/lib/validation/validate-display.js +37 -31
  344. package/lib/validation/validate-external-cert-sync.js +23 -0
  345. package/lib/validation/validate.js +8 -14
  346. package/lib/validation/validator-unresolved-placeholders.js +98 -0
  347. package/lib/validation/validator.js +22 -65
  348. package/lib/validation/wizard-config-validator.js +2 -1
  349. package/package.json +9 -4
  350. package/scripts/check-datasource-test-run-schema-sync.js +34 -0
  351. package/scripts/diagnose-cli.js +150 -0
  352. package/scripts/install-local.js +307 -55
  353. package/scripts/pnpm-global-remove.js +48 -0
  354. package/templates/README.md +15 -2
  355. package/templates/applications/dataplane/application.yaml +52 -2
  356. package/templates/applications/dataplane/env.template +79 -17
  357. package/templates/applications/dataplane/rbac.yaml +8 -0
  358. package/templates/applications/keycloak/application.yaml +9 -1
  359. package/templates/applications/keycloak/env.template +15 -6
  360. package/templates/applications/miso-controller/application.yaml +10 -2
  361. package/templates/applications/miso-controller/env.template +42 -12
  362. package/templates/applications/miso-controller/rbac.yaml +5 -0
  363. package/templates/external-system/README.md.hbs +20 -7
  364. package/templates/external-system/deploy.js.hbs +5 -5
  365. package/templates/external-system/external-datasource.yaml.hbs +197 -118
  366. package/templates/infra/compose.yaml.hbs +33 -16
  367. package/templates/infra/servers.json.hbs +3 -1
  368. package/templates/python/docker-compose.hbs +16 -0
  369. package/templates/typescript/docker-compose.hbs +16 -0
  370. package/lib/api/external-test.api.js +0 -111
  371. package/lib/schema/env-config.yaml +0 -60
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Public URL base for url:// expansion when Traefik + frontDoorRouting.host (plan 122 phase 2).
3
+ *
4
+ * @fileoverview Traefik host template vs remote-server vs localhost+port (no app-specific rules)
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const { expandFrontDoorHostPlaceholders } = require('./compose-generator');
12
+ const { publishedHostPort, localHostPort } = require('./declarative-url-ports');
13
+
14
+ /**
15
+ * Expand frontDoorRouting.host placeholders for url:// (same rules as Traefik labels in compose-generator).
16
+ *
17
+ * @param {string} template
18
+ * @param {Object} opts
19
+ * @param {string|number|null|undefined} opts.developerIdRaw
20
+ * @param {string|null|undefined} opts.remoteServer
21
+ * @returns {string}
22
+ */
23
+ function expandFrontDoorHostTemplateForUrls(template, opts) {
24
+ const { developerIdRaw, remoteServer } = opts || {};
25
+ return expandFrontDoorHostPlaceholders(template, developerIdRaw, remoteServer);
26
+ }
27
+
28
+ function hostPortForProfile(profile, listenPort, developerIdNum) {
29
+ return profile === 'docker'
30
+ ? publishedHostPort(listenPort, developerIdNum)
31
+ : localHostPort(listenPort, developerIdNum);
32
+ }
33
+
34
+ /**
35
+ * Local profile: workstation `+10` applies only to the app being resolved (`currentAppKey`).
36
+ * Cross-app tokens (e.g. `url://keycloak-public` from miso-controller) use `publishedHostPort`
37
+ * (manifest + dev*100, no +10) so sibling services keep compose-published offsets only.
38
+ *
39
+ * @param {Object} opts
40
+ * @param {'docker'|'local'} opts.profile
41
+ * @param {number} opts.listenPort - published/manifest basis for public URLs
42
+ * @param {number} opts.developerIdNum
43
+ * @param {string|undefined} opts.declarativeTargetAppKey - target of the url:// token
44
+ * @param {string|undefined} opts.declarativeCurrentAppKey - app whose env is being generated
45
+ * @returns {number}
46
+ */
47
+ function resolveHostPortForDeclarativePublic(opts) {
48
+ const {
49
+ profile,
50
+ listenPort,
51
+ developerIdNum,
52
+ declarativeTargetAppKey,
53
+ declarativeCurrentAppKey
54
+ } = opts;
55
+ if (profile !== 'local') {
56
+ return hostPortForProfile(profile, listenPort, developerIdNum);
57
+ }
58
+ const cur = String(declarativeCurrentAppKey || '').trim();
59
+ const tgt = String(declarativeTargetAppKey || '').trim();
60
+ const isCurrentApp = !cur || !tgt || tgt === cur;
61
+ return isCurrentApp ? localHostPort(listenPort, developerIdNum) : publishedHostPort(listenPort, developerIdNum);
62
+ }
63
+
64
+ /**
65
+ * Without Traefik, `remote-server` is the dev machine host. Apps bind published host ports, not 443 + path.
66
+ * If the URL already has an explicit port, keep host:port but **scheme follows `infraTlsEnabled`**, not the
67
+ * literal `https://` in `remote-server` when TLS is off (`up-infra` without `--tls`).
68
+ * If `remote-server` omits a port, append the profile-specific published/listen-derived port.
69
+ *
70
+ * @param {string} rawRemote
71
+ * @param {'docker'|'local'} profile
72
+ * @param {number} listenPort
73
+ * @param {number} developerIdNum
74
+ * @param {boolean} infraTlsEnabled
75
+ * @returns {string}
76
+ */
77
+ function remotePublicBaseWithoutTraefik(
78
+ rawRemote,
79
+ profile,
80
+ listenPort,
81
+ developerIdNum,
82
+ infraTlsEnabled,
83
+ declarativePortOpts
84
+ ) {
85
+ const raw = String(rawRemote || '').trim().replace(/\/+$/, '');
86
+ const withScheme = /^[a-z][a-z0-9+.-]*:\/\//i.test(raw) ? raw : (infraTlsEnabled ? `https://${raw}` : `http://${raw}`);
87
+ const u = new URL(withScheme);
88
+ const scheme = infraTlsEnabled ? 'https' : 'http';
89
+
90
+ if (u.port !== '') {
91
+ return `${scheme}://${u.host}`;
92
+ }
93
+
94
+ const hostPort = resolveHostPortForDeclarativePublic({
95
+ profile,
96
+ listenPort,
97
+ developerIdNum,
98
+ declarativeTargetAppKey: declarativePortOpts && declarativePortOpts.declarativeTargetAppKey,
99
+ declarativeCurrentAppKey: declarativePortOpts && declarativePortOpts.declarativeCurrentAppKey
100
+ });
101
+ const defaultPort = scheme === 'https' ? 443 : 80;
102
+ if (Number(hostPort) === defaultPort) {
103
+ return `${scheme}://${u.hostname}`;
104
+ }
105
+ return `${scheme}://${u.hostname}:${hostPort}`;
106
+ }
107
+
108
+ /**
109
+ * @param {Object} opts - same shape as computePublicUrlBaseString
110
+ * @returns {string|null}
111
+ */
112
+ function buildTraefikPublicBaseIfApplicable(opts) {
113
+ const { traefik, pathActive, hostTemplate, tls, developerIdRaw, remoteServer, infraTlsEnabled } =
114
+ opts;
115
+ // Plan 124: Traefik host authority only when pathActive (traefik ∧ frontDoorRouting.enabled)
116
+ if (!traefik || !pathActive || !hostTemplate || !String(hostTemplate).trim()) {
117
+ return null;
118
+ }
119
+ const expanded = expandFrontDoorHostTemplateForUrls(hostTemplate, {
120
+ developerIdRaw,
121
+ remoteServer
122
+ });
123
+ if (!expanded) {
124
+ return null;
125
+ }
126
+ const useHttps = Boolean(infraTlsEnabled) || tls !== false;
127
+ const scheme = useHttps ? 'https' : 'http';
128
+ return `${scheme}://${expanded}`.replace(/\/+$/, '');
129
+ }
130
+
131
+ /**
132
+ * Scheme + authority (no path) for public url://* when Traefik, remote, or localhost.
133
+ *
134
+ * @param {Object} opts
135
+ * @param {boolean} [opts.traefik]
136
+ * @param {string|null|undefined} opts.hostTemplate
137
+ * @param {boolean} [opts.tls]
138
+ * @param {string|number|null|undefined} opts.developerIdRaw
139
+ * @param {string|null|undefined} opts.remoteServer
140
+ * @param {'docker'|'local'} opts.profile
141
+ * @param {number} opts.listenPort
142
+ * @param {number} opts.developerIdNum
143
+ * @param {boolean} [opts.infraTlsEnabled] - `tlsEnabled` from ~/.aifabrix/config.yaml (`up-infra --tls`); when true, Traefik front-door public URLs use https even if application.yaml has `frontDoorRouting.tls: false`
144
+ * @param {boolean} [opts.pathActive] - traefik ∧ frontDoorRouting.enabled; required for Traefik host branch (plan 124)
145
+ * @returns {string}
146
+ */
147
+ function computePublicUrlBaseString(opts) {
148
+ const { remoteServer, profile, listenPort, developerIdNum, infraTlsEnabled } = opts;
149
+ const declarativePortOpts = {
150
+ declarativeTargetAppKey: opts.declarativeTargetAppKey,
151
+ declarativeCurrentAppKey: opts.declarativeCurrentAppKey
152
+ };
153
+
154
+ const traefikBase = buildTraefikPublicBaseIfApplicable({
155
+ ...opts,
156
+ pathActive: Boolean(opts.pathActive)
157
+ });
158
+ if (traefikBase) {
159
+ return traefikBase;
160
+ }
161
+
162
+ if (remoteServer && String(remoteServer).trim()) {
163
+ return remotePublicBaseWithoutTraefik(
164
+ remoteServer,
165
+ profile,
166
+ listenPort,
167
+ developerIdNum,
168
+ Boolean(infraTlsEnabled),
169
+ declarativePortOpts
170
+ );
171
+ }
172
+
173
+ const hostPort = resolveHostPortForDeclarativePublic({
174
+ profile,
175
+ listenPort,
176
+ developerIdNum,
177
+ declarativeTargetAppKey: declarativePortOpts.declarativeTargetAppKey,
178
+ declarativeCurrentAppKey: declarativePortOpts.declarativeCurrentAppKey
179
+ });
180
+ const scheme = infraTlsEnabled ? 'https' : 'http';
181
+ return `${scheme}://localhost:${hostPort}`;
182
+ }
183
+
184
+ module.exports = {
185
+ expandFrontDoorHostTemplateForUrls,
186
+ computePublicUrlBaseString,
187
+ resolveHostPortForDeclarativePublic
188
+ };
@@ -0,0 +1,493 @@
1
+ /**
2
+ * URL string builders and token expansion for declarative url:// resolution (plan 122).
3
+ *
4
+ * @fileoverview Split from url-declarative-resolve.js for ESLint max-lines limits
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const { getRegistryEntryForApp } = require('./urls-local-registry');
12
+ const { DECLARATIVE_URL_INFRA_DEFAULTS } = require('./infra-env-defaults');
13
+ const { getContainerPort, getLocalPort } = require('./port-resolver');
14
+ const pathsUtil = require('./paths');
15
+ const {
16
+ computePublicUrlBaseString,
17
+ resolveHostPortForDeclarativePublic
18
+ } = require('./url-declarative-public-base');
19
+ const { computePathActive } = require('./url-declarative-url-flags');
20
+ const { loadApplicationYamlDocForUrlResolve } = require('./url-declarative-resolve-load-doc');
21
+ const { parseUrlToken } = require('./url-declarative-token-parse');
22
+
23
+ /**
24
+ * Plan 122: **Developer subdomain `devNN` + remote hostname is not derived from envKey `tst`.** It comes only from
25
+ * expanding **`frontDoorRouting.host`** (e.g. `${DEV_USERNAME}.${REMOTE_HOST}`) when **`traefik`** is on.
26
+ * Kept as a no-op for backward compatibility; callers must not rely on tst-based host mutation.
27
+ *
28
+ * @param {string} absoluteUrl
29
+ * @returns {string}
30
+ */
31
+ function applyTstRemoteDeveloperHost(absoluteUrl) {
32
+ return absoluteUrl;
33
+ }
34
+
35
+ /**
36
+ * @param {string} origin
37
+ * @returns {string}
38
+ */
39
+ function applyTstRemoteDeveloperHostToOrigin(origin) {
40
+ return origin;
41
+ }
42
+
43
+ /**
44
+ * Join base URL origin with path segments (no duplicate slashes).
45
+ * @param {string} originOrBase - https://host or https://host:port
46
+ * @param {string} suffixPath - /dev/data
47
+ * @returns {string}
48
+ */
49
+ function joinUrlPath(originOrBase, suffixPath) {
50
+ const base = String(originOrBase || '').replace(/\/+$/, '');
51
+ let suf = suffixPath || '';
52
+ if (!suf.startsWith('/')) {
53
+ suf = `/${suf}`;
54
+ }
55
+ return `${base}${suf}`.replace(/([^:]\/)\/+/g, '$1');
56
+ }
57
+
58
+ /**
59
+ * @param {Object} opts
60
+ * @returns {string}
61
+ */
62
+ function buildPublicUrlString(opts) {
63
+ const {
64
+ profile,
65
+ listenPort,
66
+ developerIdNum,
67
+ remoteServer,
68
+ pathPrefix,
69
+ patternPath,
70
+ traefik,
71
+ hostTemplate,
72
+ tls,
73
+ developerIdRaw,
74
+ infraTlsEnabled,
75
+ frontDoorIngressActive,
76
+ declarativeTargetAppKey,
77
+ declarativeCurrentAppKey
78
+ } = opts;
79
+ const base = computePublicUrlBaseString({
80
+ traefik: Boolean(traefik),
81
+ pathActive: Boolean(frontDoorIngressActive),
82
+ hostTemplate: hostTemplate || null,
83
+ tls: tls !== false,
84
+ developerIdRaw,
85
+ remoteServer,
86
+ profile,
87
+ listenPort,
88
+ developerIdNum,
89
+ infraTlsEnabled: Boolean(infraTlsEnabled),
90
+ declarativeTargetAppKey,
91
+ declarativeCurrentAppKey
92
+ });
93
+ const patternSegment =
94
+ frontDoorIngressActive === false
95
+ ? ''
96
+ : patternPath === '/' || patternPath === ''
97
+ ? ''
98
+ : patternPath;
99
+ const rawSuffix = `${pathPrefix}${patternSegment}`.replace(/\/{2,}/g, '/');
100
+ if (!rawSuffix || rawSuffix === '/') {
101
+ return String(base).replace(/\/+$/, '');
102
+ }
103
+ const normalizedSuffix = rawSuffix.startsWith('/') ? rawSuffix : `/${rawSuffix}`;
104
+ return joinUrlPath(base, normalizedSuffix);
105
+ }
106
+
107
+ /**
108
+ * Public reachability origin only (no env path prefix, no front-door pattern path).
109
+ * @param {Object} opts
110
+ * @returns {string}
111
+ */
112
+ function buildPublicHostOriginString(opts) {
113
+ const {
114
+ profile,
115
+ listenPort,
116
+ developerIdNum,
117
+ remoteServer,
118
+ traefik,
119
+ hostTemplate,
120
+ tls,
121
+ developerIdRaw,
122
+ infraTlsEnabled,
123
+ frontDoorIngressActive,
124
+ declarativeTargetAppKey,
125
+ declarativeCurrentAppKey
126
+ } = opts;
127
+ const base = computePublicUrlBaseString({
128
+ traefik: Boolean(traefik),
129
+ pathActive: Boolean(frontDoorIngressActive),
130
+ hostTemplate: hostTemplate || null,
131
+ tls: tls !== false,
132
+ developerIdRaw,
133
+ remoteServer,
134
+ profile,
135
+ listenPort,
136
+ developerIdNum,
137
+ infraTlsEnabled: Boolean(infraTlsEnabled),
138
+ declarativeTargetAppKey,
139
+ declarativeCurrentAppKey
140
+ });
141
+ try {
142
+ return new URL(base).origin;
143
+ } catch {
144
+ const hostPort = resolveHostPortForDeclarativePublic({
145
+ profile,
146
+ listenPort,
147
+ developerIdNum,
148
+ declarativeTargetAppKey,
149
+ declarativeCurrentAppKey
150
+ });
151
+ return `http://localhost:${hostPort}`;
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Internal service origin only (scheme + host + port), no path suffix.
157
+ * @param {Object} opts
158
+ * @returns {string}
159
+ */
160
+ function buildInternalHostOriginString(opts) {
161
+ const {
162
+ profile,
163
+ listenPort,
164
+ targetAppKey,
165
+ remoteServer,
166
+ pathPrefix,
167
+ patternPath,
168
+ developerIdNum,
169
+ traefik,
170
+ hostTemplate,
171
+ tls,
172
+ developerIdRaw,
173
+ infraTlsEnabled,
174
+ frontDoorIngressActive,
175
+ declarativeTargetAppKey,
176
+ declarativeCurrentAppKey
177
+ } = opts;
178
+ if (profile === 'docker') {
179
+ return `http://${targetAppKey}:${listenPort}`;
180
+ }
181
+ if (remoteServer && String(remoteServer).trim()) {
182
+ const pub = buildPublicUrlString({
183
+ profile: 'local',
184
+ listenPort,
185
+ developerIdNum,
186
+ remoteServer,
187
+ pathPrefix,
188
+ patternPath,
189
+ traefik,
190
+ hostTemplate,
191
+ tls,
192
+ developerIdRaw,
193
+ infraTlsEnabled,
194
+ frontDoorIngressActive,
195
+ declarativeTargetAppKey: declarativeTargetAppKey || targetAppKey,
196
+ declarativeCurrentAppKey: declarativeCurrentAppKey
197
+ });
198
+ try {
199
+ return new URL(pub).origin;
200
+ } catch {
201
+ return `http://${targetAppKey}:${listenPort}`;
202
+ }
203
+ }
204
+ return `http://${targetAppKey}:${listenPort}`;
205
+ }
206
+
207
+ function buildInternalUrlString(opts) {
208
+ const {
209
+ profile,
210
+ listenPort,
211
+ targetAppKey,
212
+ remoteServer,
213
+ pathPrefix,
214
+ patternPath,
215
+ developerIdNum,
216
+ traefik,
217
+ hostTemplate,
218
+ tls,
219
+ developerIdRaw,
220
+ infraTlsEnabled,
221
+ frontDoorIngressActive,
222
+ declarativeTargetAppKey,
223
+ declarativeCurrentAppKey
224
+ } = opts;
225
+ if (profile === 'docker') {
226
+ return `http://${targetAppKey}:${listenPort}`;
227
+ }
228
+ if (remoteServer && String(remoteServer).trim()) {
229
+ return buildPublicUrlString({
230
+ profile: 'local',
231
+ listenPort,
232
+ developerIdNum,
233
+ remoteServer,
234
+ pathPrefix,
235
+ patternPath,
236
+ traefik,
237
+ hostTemplate,
238
+ tls,
239
+ developerIdRaw,
240
+ infraTlsEnabled,
241
+ frontDoorIngressActive,
242
+ declarativeTargetAppKey: declarativeTargetAppKey || targetAppKey,
243
+ declarativeCurrentAppKey: declarativeCurrentAppKey
244
+ });
245
+ }
246
+ return `http://${targetAppKey}:${listenPort}`;
247
+ }
248
+
249
+ /**
250
+ * @param {object|null|undefined} doc
251
+ * @returns {{ hostTemplate: string|null, tls: boolean }}
252
+ */
253
+ function readFrontDoorHostTlsFromDoc(doc) {
254
+ if (!doc || !doc.frontDoorRouting) {
255
+ return { hostTemplate: null, tls: true };
256
+ }
257
+ const fd = doc.frontDoorRouting;
258
+ const hostTemplate =
259
+ typeof fd.host === 'string' && fd.host.trim() ? fd.host.trim() : null;
260
+ return { hostTemplate, tls: fd.tls !== false };
261
+ }
262
+
263
+ /**
264
+ * Ports from application.yaml: `listenPort` = container/process listen ({@link getContainerPort});
265
+ * `publicPortBasis` = manifest root `port` ({@link getLocalPort}) for browser-published host URLs
266
+ * (url://host-public, url://public origin) when Traefik is not serving the app — not the internal
267
+ * container port (e.g. Keycloak 8082 published vs 8080 in-container).
268
+ *
269
+ * @param {object|null|undefined} doc
270
+ * @param {{ port: number, containerPort: number|null, pattern: string }|null} entry
271
+ * @returns {{ listenPort: number, publicPortBasis: number, patternStr: string }|null}
272
+ */
273
+ function resolveListenPortAndPatternFromDoc(doc, entry) {
274
+ if (doc) {
275
+ const listenPort = getContainerPort(doc);
276
+ const publicPortBasis = getLocalPort(doc);
277
+ const raw = doc.frontDoorRouting && doc.frontDoorRouting.pattern;
278
+ const patternStr =
279
+ typeof raw === 'string'
280
+ ? raw
281
+ : entry && typeof entry.pattern === 'string'
282
+ ? entry.pattern
283
+ : DECLARATIVE_URL_INFRA_DEFAULTS.frontDoorPatternWhenUnspecified;
284
+ return { listenPort, publicPortBasis, patternStr };
285
+ }
286
+ if (entry) {
287
+ const c = entry.containerPort;
288
+ const listenPort = typeof c === 'number' && c > 0 ? c : entry.port;
289
+ return { listenPort, publicPortBasis: entry.port, patternStr: entry.pattern };
290
+ }
291
+ return null;
292
+ }
293
+
294
+ /**
295
+ * Port + pattern + optional Traefik host template for a url:// token.
296
+ * @param {string} token
297
+ * @param {Object} ctx
298
+ * @param {Object} registry
299
+ * @returns {{ appKey: string, listenPort: number, publicPortBasis: number, patternStr: string, hostTemplate: string|null, tls: boolean, frontDoorIngressActive: boolean }|null}
300
+ */
301
+ function resolveListenPortPatternForToken(token, ctx, registry) {
302
+ const { targetKey } = parseUrlToken(token);
303
+ const currentAppKey = ctx.currentAppKey || '';
304
+ const appKey = targetKey || currentAppKey;
305
+ if (!appKey) {
306
+ return null;
307
+ }
308
+ const doc = loadApplicationYamlDocForUrlResolve(appKey, ctx, pathsUtil);
309
+ const entry = getRegistryEntryForApp(appKey, registry);
310
+ const portPattern = resolveListenPortAndPatternFromDoc(doc, entry);
311
+ if (!portPattern) {
312
+ return null;
313
+ }
314
+ const { listenPort, publicPortBasis, patternStr } = portPattern;
315
+ const meta = readFrontDoorHostTlsFromDoc(doc);
316
+ const frontDoorIngressActive = computePathActive(
317
+ Boolean(ctx.traefik),
318
+ Boolean(doc && doc.frontDoorRouting && doc.frontDoorRouting.enabled === true)
319
+ );
320
+ return {
321
+ appKey,
322
+ listenPort,
323
+ publicPortBasis,
324
+ patternStr,
325
+ hostTemplate: meta.hostTemplate,
326
+ tls: meta.tls,
327
+ frontDoorIngressActive
328
+ };
329
+ }
330
+
331
+ /**
332
+ * Published/browser origin port basis for url:// public surfaces (manifest `port`), not container listen.
333
+ * @param {Object} r
334
+ * @returns {number}
335
+ */
336
+ function publishedOriginPortBasis(r) {
337
+ const b = r.publicPortBasis;
338
+ if (b !== undefined && b !== null && Number.isFinite(Number(b))) {
339
+ return Number(b);
340
+ }
341
+ return r.listenPort;
342
+ }
343
+
344
+ /**
345
+ * @param {Object} r - resolved app + patternPath + pathPrefix + remoteServer + profile + devNum + derivedEnvKey
346
+ * @returns {string}
347
+ */
348
+ function expandHostSurfacePublic(r) {
349
+ return buildPublicHostOriginString({
350
+ profile: r.profile,
351
+ listenPort: publishedOriginPortBasis(r),
352
+ developerIdNum: r.devNum,
353
+ remoteServer: r.remoteServer,
354
+ traefik: r.traefik,
355
+ hostTemplate: r.hostTemplate,
356
+ tls: r.tls,
357
+ developerIdRaw: r.developerIdRaw,
358
+ infraTlsEnabled: r.infraTlsEnabled,
359
+ frontDoorIngressActive: r.frontDoorIngressActive,
360
+ declarativeTargetAppKey: r.appKey,
361
+ declarativeCurrentAppKey: r.currentAppKey
362
+ });
363
+ }
364
+
365
+ /**
366
+ * Local workstation `.env` (no remote-server): browser-reachable URLs only — internal tokens match public.
367
+ * Remote dev keeps internal = public mirroring via {@link buildInternalUrlString} when `remoteServer` is set.
368
+ *
369
+ * @param {Object} r
370
+ * @returns {boolean}
371
+ */
372
+ function isLocalProfileWithoutRemoteServer(r) {
373
+ return r.profile === 'local' && !String(r.remoteServer || '').trim();
374
+ }
375
+
376
+ /**
377
+ * @param {Object} r
378
+ * @returns {string}
379
+ */
380
+ function expandHostSurfaceInternal(r) {
381
+ if (isLocalProfileWithoutRemoteServer(r)) {
382
+ return expandHostSurfacePublic(r);
383
+ }
384
+ return buildInternalHostOriginString({
385
+ profile: r.profile,
386
+ listenPort: r.listenPort,
387
+ targetAppKey: r.appKey,
388
+ remoteServer: r.remoteServer,
389
+ pathPrefix: r.pathPrefix,
390
+ patternPath: r.patternPath,
391
+ developerIdNum: r.devNum,
392
+ derivedEnvKey: r.derivedEnvKey,
393
+ traefik: r.traefik,
394
+ hostTemplate: r.hostTemplate,
395
+ tls: r.tls,
396
+ developerIdRaw: r.developerIdRaw,
397
+ infraTlsEnabled: r.infraTlsEnabled,
398
+ frontDoorIngressActive: r.frontDoorIngressActive,
399
+ declarativeTargetAppKey: r.appKey,
400
+ declarativeCurrentAppKey: r.currentAppKey
401
+ });
402
+ }
403
+
404
+ /**
405
+ * @param {Object} r
406
+ * @returns {string}
407
+ */
408
+ function expandFullSurfacePublic(r) {
409
+ return buildPublicUrlString({
410
+ profile: r.profile,
411
+ listenPort: publishedOriginPortBasis(r),
412
+ developerIdNum: r.devNum,
413
+ remoteServer: r.remoteServer,
414
+ pathPrefix: r.pathPrefix,
415
+ patternPath: r.patternPath,
416
+ traefik: r.traefik,
417
+ hostTemplate: r.hostTemplate,
418
+ tls: r.tls,
419
+ developerIdRaw: r.developerIdRaw,
420
+ infraTlsEnabled: r.infraTlsEnabled,
421
+ frontDoorIngressActive: r.frontDoorIngressActive,
422
+ declarativeTargetAppKey: r.appKey,
423
+ declarativeCurrentAppKey: r.currentAppKey
424
+ });
425
+ }
426
+
427
+ /**
428
+ * @param {Object} r
429
+ * @returns {string}
430
+ */
431
+ function expandFullSurfaceInternal(r) {
432
+ if (isLocalProfileWithoutRemoteServer(r)) {
433
+ return expandFullSurfacePublic(r);
434
+ }
435
+ return buildInternalUrlString({
436
+ profile: r.profile,
437
+ listenPort: r.listenPort,
438
+ targetAppKey: r.appKey,
439
+ remoteServer: r.remoteServer,
440
+ pathPrefix: r.pathPrefix,
441
+ patternPath: r.patternPath,
442
+ developerIdNum: r.devNum,
443
+ derivedEnvKey: r.derivedEnvKey,
444
+ traefik: r.traefik,
445
+ hostTemplate: r.hostTemplate,
446
+ tls: r.tls,
447
+ developerIdRaw: r.developerIdRaw,
448
+ infraTlsEnabled: r.infraTlsEnabled,
449
+ frontDoorIngressActive: r.frontDoorIngressActive,
450
+ declarativeTargetAppKey: r.appKey,
451
+ declarativeCurrentAppKey: r.currentAppKey
452
+ });
453
+ }
454
+
455
+ /**
456
+ * @param {{ kind: string, surface: string }} parsed
457
+ * @param {Object} r
458
+ * @returns {string}
459
+ */
460
+ function expandResolvedUrlToken(parsed, r) {
461
+ if (parsed.surface === 'vdir') {
462
+ if (!r.frontDoorIngressActive) {
463
+ return '';
464
+ }
465
+ // Plan 124: docker PRIVATEVDIR is always empty; public vdir still carries pattern
466
+ if (parsed.kind === 'internal' && r.profile === 'docker') {
467
+ return '';
468
+ }
469
+ const prefix = String(r.pathPrefix || '');
470
+ const pat = r.patternPath || '/';
471
+ if (!pat || pat === '/') {
472
+ return prefix || '';
473
+ }
474
+ const joined = `${prefix}${pat}`.replace(/\/{2,}/g, '/');
475
+ return joined.startsWith('/') ? joined : `/${joined}`;
476
+ }
477
+ if (parsed.surface === 'host') {
478
+ return parsed.kind === 'public' ? expandHostSurfacePublic(r) : expandHostSurfaceInternal(r);
479
+ }
480
+ return parsed.kind === 'public' ? expandFullSurfacePublic(r) : expandFullSurfaceInternal(r);
481
+ }
482
+
483
+ module.exports = {
484
+ applyTstRemoteDeveloperHost,
485
+ applyTstRemoteDeveloperHostToOrigin,
486
+ buildPublicUrlString,
487
+ buildPublicHostOriginString,
488
+ buildInternalUrlString,
489
+ buildInternalHostOriginString,
490
+ parseUrlToken,
491
+ expandResolvedUrlToken,
492
+ resolveListenPortPatternForToken
493
+ };