@aifabrix/builder 2.44.5 → 2.45.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 (249) hide show
  1. package/.cursor/rules/cli-layout.mdc +8 -4
  2. package/.cursor/rules/project-rules.mdc +1 -1
  3. package/README.md +15 -23
  4. package/integration/hubspot-test/README.md +2 -0
  5. package/integration/hubspot-test/test.js +5 -3
  6. package/jest.projects.js +104 -2
  7. package/lib/api/controller-health.api.js +49 -0
  8. package/lib/api/dimension-values.api.js +82 -0
  9. package/lib/api/dimensions.api.js +114 -0
  10. package/lib/api/external-systems.api.js +1 -0
  11. package/lib/api/integration-clients.api.js +168 -0
  12. package/lib/api/types/dimension-values.types.js +28 -0
  13. package/lib/api/types/dimensions.types.js +31 -0
  14. package/lib/api/types/integration-clients.types.js +45 -0
  15. package/lib/api/validation-runner.js +46 -25
  16. package/lib/app/deploy-config.js +11 -1
  17. package/lib/app/deploy-status-display.js +3 -3
  18. package/lib/app/deploy.js +36 -14
  19. package/lib/app/display.js +15 -11
  20. package/lib/app/helpers.js +3 -3
  21. package/lib/app/index.js +3 -3
  22. package/lib/app/push.js +46 -23
  23. package/lib/app/register.js +7 -6
  24. package/lib/app/restart-display.js +126 -0
  25. package/lib/app/rotate-secret.js +7 -6
  26. package/lib/app/run-container-start.js +12 -6
  27. package/lib/app/run-env-compose.js +30 -1
  28. package/lib/app/run-helpers.js +58 -19
  29. package/lib/app/run-reload-sync.js +148 -0
  30. package/lib/app/run-resolve-image.js +51 -1
  31. package/lib/app/run.js +148 -74
  32. package/lib/app/show-display.js +7 -0
  33. package/lib/app/show.js +87 -5
  34. package/lib/build/index.js +83 -49
  35. package/lib/cli/doctor-check.js +117 -0
  36. package/lib/cli/index.js +8 -2
  37. package/lib/cli/infra-guided.js +460 -0
  38. package/lib/cli/installation-log-command.js +73 -0
  39. package/lib/cli/setup-app.js +31 -3
  40. package/lib/cli/setup-auth.js +98 -27
  41. package/lib/cli/setup-dev-path-commands.js +50 -3
  42. package/lib/cli/setup-infra-up-dataplane-action.js +111 -0
  43. package/lib/cli/setup-infra-up-platform-action.js +131 -0
  44. package/lib/cli/setup-infra.js +132 -118
  45. package/lib/cli/setup-integration-client.js +182 -0
  46. package/lib/cli/setup-parameters.js +21 -2
  47. package/lib/cli/setup-platform.js +102 -0
  48. package/lib/cli/setup-secrets.js +18 -6
  49. package/lib/cli/setup-utility-resolve.js +132 -0
  50. package/lib/cli/setup-utility.js +143 -84
  51. package/lib/commands/app-logs.js +81 -33
  52. package/lib/commands/auth-config.js +116 -18
  53. package/lib/commands/datasource-capability-dimension-cli.js +128 -0
  54. package/lib/commands/datasource-capability-output.js +29 -0
  55. package/lib/commands/datasource-capability-relate-cli.js +140 -0
  56. package/lib/commands/datasource-capability.js +411 -0
  57. package/lib/commands/datasource-unified-test-cli.options.js +1 -1
  58. package/lib/commands/datasource.js +53 -13
  59. package/lib/commands/dev-down.js +3 -3
  60. package/lib/commands/dev-infra-gate.js +32 -0
  61. package/lib/commands/dev-init.js +13 -7
  62. package/lib/commands/dimension-value.js +179 -0
  63. package/lib/commands/dimension.js +330 -0
  64. package/lib/commands/integration-client.js +430 -0
  65. package/lib/commands/login-device.js +65 -30
  66. package/lib/commands/login.js +21 -10
  67. package/lib/commands/parameters-validate.js +78 -13
  68. package/lib/commands/repair-datasource-auto-rbac.js +166 -0
  69. package/lib/commands/repair-datasource-keys.js +10 -5
  70. package/lib/commands/repair-datasource.js +19 -7
  71. package/lib/commands/repair-env-template.js +4 -1
  72. package/lib/commands/repair-openapi-sync.js +172 -0
  73. package/lib/commands/repair-persist.js +102 -0
  74. package/lib/commands/repair-rbac-extract.js +27 -0
  75. package/lib/commands/repair-rbac-migrate.js +186 -0
  76. package/lib/commands/repair-rbac.js +214 -31
  77. package/lib/commands/repair-system-alignment.js +246 -0
  78. package/lib/commands/repair-system-permissions.js +168 -0
  79. package/lib/commands/repair.js +120 -338
  80. package/lib/commands/secure.js +1 -1
  81. package/lib/commands/setup-modes.js +468 -0
  82. package/lib/commands/setup-prompts.js +421 -0
  83. package/lib/commands/setup.js +254 -0
  84. package/lib/commands/teardown.js +277 -0
  85. package/lib/commands/up-common.js +113 -19
  86. package/lib/commands/up-dataplane.js +44 -19
  87. package/lib/commands/up-miso.js +18 -18
  88. package/lib/commands/upload.js +111 -23
  89. package/lib/commands/wizard-core-helpers.js +14 -11
  90. package/lib/commands/wizard-core.js +6 -5
  91. package/lib/commands/wizard-dataplane.js +2 -2
  92. package/lib/commands/wizard-entity-selection.js +4 -3
  93. package/lib/commands/wizard-headless.js +2 -1
  94. package/lib/commands/wizard.js +2 -1
  95. package/lib/constants/infra-compose-service-names.js +40 -0
  96. package/lib/core/audit-logger.js +1 -34
  97. package/lib/core/config-admin-email.js +56 -0
  98. package/lib/core/config-normalize.js +60 -0
  99. package/lib/core/config-registered-controller-urls.js +54 -0
  100. package/lib/core/config.js +33 -50
  101. package/lib/core/env-reader.js +16 -3
  102. package/lib/core/secrets-admin-env.js +101 -0
  103. package/lib/core/secrets-ensure-infra.js +34 -1
  104. package/lib/core/secrets-ensure.js +88 -66
  105. package/lib/core/secrets-env-content.js +428 -0
  106. package/lib/core/secrets-env-declarative-expand.js +170 -0
  107. package/lib/core/secrets-env-write.js +29 -1
  108. package/lib/core/secrets-load.js +252 -0
  109. package/lib/core/secrets-names.js +32 -0
  110. package/lib/core/secrets.js +17 -757
  111. package/lib/datasource/capability/basic-exposure.js +76 -0
  112. package/lib/datasource/capability/capability-diff-slice.js +41 -0
  113. package/lib/datasource/capability/capability-key.js +34 -0
  114. package/lib/datasource/capability/capability-resolve.js +172 -0
  115. package/lib/datasource/capability/capability-storage-keys.js +22 -0
  116. package/lib/datasource/capability/copy-operations.js +348 -0
  117. package/lib/datasource/capability/copy-test-payload.js +139 -0
  118. package/lib/datasource/capability/create-operations.js +235 -0
  119. package/lib/datasource/capability/dimension-operations.js +151 -0
  120. package/lib/datasource/capability/dimension-validate.js +219 -0
  121. package/lib/datasource/capability/json-pointer.js +31 -0
  122. package/lib/datasource/capability/reference-rewrite.js +51 -0
  123. package/lib/datasource/capability/relate-operations.js +325 -0
  124. package/lib/datasource/capability/relate-validate.js +219 -0
  125. package/lib/datasource/capability/remove-operations.js +275 -0
  126. package/lib/datasource/capability/run-capability-copy.js +152 -0
  127. package/lib/datasource/capability/run-capability-diff.js +135 -0
  128. package/lib/datasource/capability/run-capability-dimension.js +291 -0
  129. package/lib/datasource/capability/run-capability-edit.js +377 -0
  130. package/lib/datasource/capability/run-capability-relate.js +193 -0
  131. package/lib/datasource/capability/run-capability-remove.js +105 -0
  132. package/lib/datasource/capability/templates/minimal-fetch.json +18 -0
  133. package/lib/datasource/capability/validate-capability-slice.js +35 -0
  134. package/lib/datasource/list.js +136 -23
  135. package/lib/datasource/log-viewer.js +2 -4
  136. package/lib/datasource/unified-validation-run.js +51 -16
  137. package/lib/datasource/validate.js +53 -1
  138. package/lib/deployment/deploy-poll-ui.js +60 -0
  139. package/lib/deployment/deployer-status.js +29 -3
  140. package/lib/deployment/deployer.js +48 -30
  141. package/lib/deployment/environment.js +7 -2
  142. package/lib/deployment/poll-interval.js +72 -0
  143. package/lib/deployment/push.js +11 -9
  144. package/lib/external-system/deploy.js +9 -2
  145. package/lib/external-system/download.js +61 -32
  146. package/lib/external-system/sync-deploy-manifest.js +33 -0
  147. package/lib/infrastructure/index.js +49 -19
  148. package/lib/infrastructure/orphan-infra-docker-teardown.js +177 -0
  149. package/lib/internal/node-fs.js +2 -0
  150. package/lib/parameters/infra-kv-discovery.js +29 -4
  151. package/lib/parameters/infra-parameter-catalog.js +6 -3
  152. package/lib/parameters/infra-parameter-validate.js +67 -19
  153. package/lib/resolvers/datasource-resolver.js +53 -0
  154. package/lib/resolvers/dimension-file.js +52 -0
  155. package/lib/resolvers/manifest-resolver.js +133 -0
  156. package/lib/schema/application-schema.json +4 -0
  157. package/lib/schema/external-datasource.schema.json +183 -53
  158. package/lib/schema/external-system.schema.json +23 -10
  159. package/lib/schema/infra.parameter.yaml +26 -1
  160. package/lib/schema/wizard-config.schema.json +1 -1
  161. package/lib/utils/aifabrix-config-dir-walk.js +40 -0
  162. package/lib/utils/aifabrix-runtime-config-dir.js +26 -3
  163. package/lib/utils/app-config-resolver.js +24 -1
  164. package/lib/utils/app-run-containers.js +2 -2
  165. package/lib/utils/applications-config-defaults.js +206 -0
  166. package/lib/utils/auth-config-validator.js +2 -12
  167. package/lib/utils/bash-secret-env.js +59 -0
  168. package/lib/utils/cli-secrets-error-format.js +78 -0
  169. package/lib/utils/cli-test-layout-chalk.js +31 -9
  170. package/lib/utils/cli-utils.js +4 -36
  171. package/lib/utils/compose-generate-docker-compose.js +111 -6
  172. package/lib/utils/compose-generator.js +17 -8
  173. package/lib/utils/controller-url.js +50 -7
  174. package/lib/utils/datasource-test-run-display.js +8 -0
  175. package/lib/utils/dev-hosts-helper.js +3 -2
  176. package/lib/utils/dev-init-ssh-merge.js +2 -1
  177. package/lib/utils/docker-build.js +17 -9
  178. package/lib/utils/docker-reload-mount.js +127 -0
  179. package/lib/utils/env-copy.js +99 -14
  180. package/lib/utils/env-template.js +5 -1
  181. package/lib/utils/external-readme.js +71 -2
  182. package/lib/utils/external-system-local-test-tty.js +3 -2
  183. package/lib/utils/external-system-readiness-core.js +45 -12
  184. package/lib/utils/external-system-readiness-deploy-display.js +3 -3
  185. package/lib/utils/external-system-readiness-display-internals.js +33 -3
  186. package/lib/utils/external-system-readiness-display.js +10 -1
  187. package/lib/utils/file-upload.js +40 -3
  188. package/lib/utils/health-check-db-init.js +107 -0
  189. package/lib/utils/health-check-public-warn.js +69 -0
  190. package/lib/utils/health-check-url.js +28 -10
  191. package/lib/utils/health-check.js +139 -107
  192. package/lib/utils/help-builder.js +5 -1
  193. package/lib/utils/image-name.js +34 -7
  194. package/lib/utils/infra-optional-service-flags.js +69 -0
  195. package/lib/utils/installation-log-core.js +282 -0
  196. package/lib/utils/installation-log-record.js +237 -0
  197. package/lib/utils/installation-log.js +123 -0
  198. package/lib/utils/integration-file-backup.js +74 -0
  199. package/lib/utils/log-redaction.js +105 -0
  200. package/lib/utils/manifest-location.js +164 -0
  201. package/lib/utils/manifest-source-emit.js +162 -0
  202. package/lib/utils/mutagen-install.js +30 -3
  203. package/lib/utils/paths.js +308 -76
  204. package/lib/utils/postgres-wipe.js +212 -0
  205. package/lib/utils/register-aifabrix-shell-env.js +15 -0
  206. package/lib/utils/remote-dev-auth.js +21 -5
  207. package/lib/utils/remote-docker-env.js +9 -1
  208. package/lib/utils/remote-secrets-loader.js +49 -4
  209. package/lib/utils/resolve-docker-image-ref.js +9 -3
  210. package/lib/utils/run-cli-flags.js +29 -0
  211. package/lib/utils/secrets-ancestor-paths.js +47 -0
  212. package/lib/utils/secrets-canonical.js +10 -3
  213. package/lib/utils/secrets-helpers.js +17 -10
  214. package/lib/utils/secrets-kv-refs.js +42 -0
  215. package/lib/utils/secrets-kv-scope.js +19 -2
  216. package/lib/utils/secrets-materialize-local.js +134 -0
  217. package/lib/utils/secrets-path.js +26 -13
  218. package/lib/utils/secrets-utils.js +20 -10
  219. package/lib/utils/system-builder-root.js +42 -0
  220. package/lib/utils/url-declarative-public-base.js +80 -12
  221. package/lib/utils/url-declarative-resolve-build-urls.js +238 -0
  222. package/lib/utils/url-declarative-resolve-build.js +24 -388
  223. package/lib/utils/url-declarative-resolve-expand-token.js +189 -0
  224. package/lib/utils/url-declarative-resolve-load-doc.js +12 -3
  225. package/lib/utils/url-declarative-resolve-surface-state.js +102 -0
  226. package/lib/utils/url-declarative-resolve.js +47 -7
  227. package/lib/utils/url-declarative-runtime-base-path.js +52 -0
  228. package/lib/utils/url-declarative-vdir-inactive-env.js +2 -1
  229. package/lib/utils/urls-local-registry-scan.js +103 -0
  230. package/lib/utils/urls-local-registry.js +158 -76
  231. package/lib/utils/validation-poll-ui.js +81 -0
  232. package/lib/utils/validation-run-poll.js +29 -5
  233. package/lib/utils/with-muted-logger.js +53 -0
  234. package/package.json +3 -1
  235. package/templates/applications/dataplane/application.yaml +5 -1
  236. package/templates/applications/dataplane/rbac.yaml +10 -10
  237. package/templates/applications/keycloak/env.template +8 -6
  238. package/templates/applications/miso-controller/application.yaml +9 -0
  239. package/templates/applications/miso-controller/env.template +27 -29
  240. package/templates/applications/miso-controller/rbac.yaml +9 -9
  241. package/templates/external-system/README.md.hbs +83 -123
  242. package/.npmrc.token +0 -1
  243. package/.nyc_output/55e9d034-ddab-4579-a706-e02a91d75c91.json +0 -1
  244. package/.nyc_output/processinfo/55e9d034-ddab-4579-a706-e02a91d75c91.json +0 -1
  245. package/.nyc_output/processinfo/index.json +0 -1
  246. package/lib/api/service-users.api.js +0 -150
  247. package/lib/api/types/service-users.types.js +0 -65
  248. package/lib/cli/setup-service-user.js +0 -187
  249. package/lib/commands/service-user.js +0 -429
@@ -0,0 +1,238 @@
1
+ /**
2
+ * Public/internal URL string builders for declarative url:// (join + build*).
3
+ *
4
+ * @fileoverview Split from url-declarative-resolve-build.js for ESLint max-lines
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const {
12
+ computePublicUrlBaseString,
13
+ resolveHostPortForDeclarativePublic
14
+ } = require('./url-declarative-public-base');
15
+
16
+ /**
17
+ * Join base URL origin with path segments (no duplicate slashes).
18
+ * @param {string} originOrBase - https://host or https://host:port
19
+ * @param {string} suffixPath - /dev/data
20
+ * @returns {string}
21
+ */
22
+ function joinUrlPath(originOrBase, suffixPath) {
23
+ const base = String(originOrBase || '').replace(/\/+$/, '');
24
+ let suf = suffixPath || '';
25
+ if (!suf.startsWith('/')) {
26
+ suf = `/${suf}`;
27
+ }
28
+ return `${base}${suf}`.replace(/([^:]\/)\/+/g, '$1');
29
+ }
30
+
31
+ /**
32
+ * @param {Object} opts
33
+ * @returns {string}
34
+ */
35
+ function buildPublicUrlString(opts) {
36
+ const {
37
+ profile,
38
+ listenPort,
39
+ developerIdNum,
40
+ remoteServer,
41
+ pathPrefix,
42
+ patternPath,
43
+ traefik,
44
+ hostTemplate,
45
+ tls,
46
+ developerIdRaw,
47
+ infraTlsEnabled,
48
+ frontDoorIngressActive,
49
+ declarativeTargetAppKey,
50
+ declarativeCurrentAppKey,
51
+ declarativePublicUrlsUseLocalhost
52
+ } = opts;
53
+ const base = computePublicUrlBaseString({
54
+ traefik: Boolean(traefik),
55
+ pathActive: Boolean(frontDoorIngressActive),
56
+ hostTemplate: hostTemplate || null,
57
+ tls: tls !== false,
58
+ developerIdRaw,
59
+ remoteServer,
60
+ profile,
61
+ listenPort,
62
+ developerIdNum,
63
+ infraTlsEnabled: Boolean(infraTlsEnabled),
64
+ declarativeTargetAppKey,
65
+ declarativeCurrentAppKey,
66
+ declarativePublicUrlsUseLocalhost
67
+ });
68
+ const patternSegment =
69
+ frontDoorIngressActive === false
70
+ ? ''
71
+ : patternPath === '/' || patternPath === ''
72
+ ? ''
73
+ : patternPath;
74
+ const rawSuffix = `${pathPrefix}${patternSegment}`.replace(/\/{2,}/g, '/');
75
+ if (!rawSuffix || rawSuffix === '/') {
76
+ return String(base).replace(/\/+$/, '');
77
+ }
78
+ const normalizedSuffix = rawSuffix.startsWith('/') ? rawSuffix : `/${rawSuffix}`;
79
+ return joinUrlPath(base, normalizedSuffix);
80
+ }
81
+
82
+ /**
83
+ * Public reachability origin only (no env path prefix, no front-door pattern path).
84
+ * @param {Object} opts
85
+ * @returns {string}
86
+ */
87
+ function buildPublicHostOriginString(opts) {
88
+ const {
89
+ profile,
90
+ listenPort,
91
+ developerIdNum,
92
+ remoteServer,
93
+ traefik,
94
+ hostTemplate,
95
+ tls,
96
+ developerIdRaw,
97
+ infraTlsEnabled,
98
+ frontDoorIngressActive,
99
+ declarativeTargetAppKey,
100
+ declarativeCurrentAppKey,
101
+ declarativePublicUrlsUseLocalhost
102
+ } = opts;
103
+ const base = computePublicUrlBaseString({
104
+ traefik: Boolean(traefik),
105
+ pathActive: Boolean(frontDoorIngressActive),
106
+ hostTemplate: hostTemplate || null,
107
+ tls: tls !== false,
108
+ developerIdRaw,
109
+ remoteServer,
110
+ profile,
111
+ listenPort,
112
+ developerIdNum,
113
+ infraTlsEnabled: Boolean(infraTlsEnabled),
114
+ declarativeTargetAppKey,
115
+ declarativeCurrentAppKey,
116
+ declarativePublicUrlsUseLocalhost
117
+ });
118
+ try {
119
+ return new URL(base).origin;
120
+ } catch {
121
+ const hostPort = resolveHostPortForDeclarativePublic({
122
+ profile,
123
+ listenPort,
124
+ developerIdNum,
125
+ declarativeTargetAppKey,
126
+ declarativeCurrentAppKey
127
+ });
128
+ return `http://localhost:${hostPort}`;
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Internal service origin only (scheme + host + port), no path suffix.
134
+ * @param {Object} opts
135
+ * @returns {string}
136
+ */
137
+ function buildInternalHostOriginString(opts) {
138
+ const {
139
+ profile,
140
+ listenPort,
141
+ targetAppKey,
142
+ remoteServer,
143
+ pathPrefix,
144
+ patternPath,
145
+ developerIdNum,
146
+ traefik,
147
+ hostTemplate,
148
+ tls,
149
+ developerIdRaw,
150
+ infraTlsEnabled,
151
+ frontDoorIngressActive,
152
+ declarativeTargetAppKey,
153
+ declarativeCurrentAppKey,
154
+ declarativePublicUrlsUseLocalhost
155
+ } = opts;
156
+ if (profile === 'docker') {
157
+ return `http://${targetAppKey}:${listenPort}`;
158
+ }
159
+ if (remoteServer && String(remoteServer).trim()) {
160
+ const pub = buildPublicUrlString({
161
+ profile: 'local',
162
+ listenPort,
163
+ developerIdNum,
164
+ remoteServer,
165
+ pathPrefix,
166
+ patternPath,
167
+ traefik,
168
+ hostTemplate,
169
+ tls,
170
+ developerIdRaw,
171
+ infraTlsEnabled,
172
+ frontDoorIngressActive,
173
+ declarativeTargetAppKey: declarativeTargetAppKey || targetAppKey,
174
+ declarativeCurrentAppKey: declarativeCurrentAppKey,
175
+ declarativePublicUrlsUseLocalhost
176
+ });
177
+ try {
178
+ return new URL(pub).origin;
179
+ } catch {
180
+ return `http://${targetAppKey}:${listenPort}`;
181
+ }
182
+ }
183
+ return `http://${targetAppKey}:${listenPort}`;
184
+ }
185
+
186
+ function buildInternalUrlString(opts) {
187
+ const {
188
+ profile,
189
+ listenPort,
190
+ targetAppKey,
191
+ runtimeBasePath,
192
+ remoteServer,
193
+ pathPrefix,
194
+ patternPath,
195
+ developerIdNum,
196
+ traefik,
197
+ hostTemplate,
198
+ tls,
199
+ developerIdRaw,
200
+ infraTlsEnabled,
201
+ frontDoorIngressActive,
202
+ declarativeTargetAppKey,
203
+ declarativeCurrentAppKey,
204
+ declarativePublicUrlsUseLocalhost
205
+ } = opts;
206
+ if (profile === 'docker') {
207
+ const origin = `http://${targetAppKey}:${listenPort}`;
208
+ return runtimeBasePath ? joinUrlPath(origin, runtimeBasePath) : origin;
209
+ }
210
+ if (remoteServer && String(remoteServer).trim()) {
211
+ return buildPublicUrlString({
212
+ profile: 'local',
213
+ listenPort,
214
+ developerIdNum,
215
+ remoteServer,
216
+ pathPrefix,
217
+ patternPath,
218
+ traefik,
219
+ hostTemplate,
220
+ tls,
221
+ developerIdRaw,
222
+ infraTlsEnabled,
223
+ frontDoorIngressActive,
224
+ declarativeTargetAppKey: declarativeTargetAppKey || targetAppKey,
225
+ declarativeCurrentAppKey: declarativeCurrentAppKey,
226
+ declarativePublicUrlsUseLocalhost
227
+ });
228
+ }
229
+ return `http://${targetAppKey}:${listenPort}`;
230
+ }
231
+
232
+ module.exports = {
233
+ joinUrlPath,
234
+ buildPublicUrlString,
235
+ buildPublicHostOriginString,
236
+ buildInternalUrlString,
237
+ buildInternalHostOriginString
238
+ };
@@ -8,17 +8,16 @@
8
8
 
9
9
  'use strict';
10
10
 
11
- const { getRegistryEntryForApp } = require('./urls-local-registry');
11
+ const { getRegistryEntryForApp, readRegistryInternalDockerUseOriginOnly } = require('./urls-local-registry');
12
12
  const { DECLARATIVE_URL_INFRA_DEFAULTS } = require('./infra-env-defaults');
13
13
  const { getContainerPort, getLocalPort } = require('./port-resolver');
14
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');
15
+ const { resolveDeclarativeUrlSurfaceState } = require('./url-declarative-resolve-surface-state');
20
16
  const { loadApplicationYamlDocForUrlResolve } = require('./url-declarative-resolve-load-doc');
21
17
  const { parseUrlToken } = require('./url-declarative-token-parse');
18
+ const { readFrontDoorHostTlsFromDoc } = require('./url-declarative-runtime-base-path');
19
+ const buildUrls = require('./url-declarative-resolve-build-urls');
20
+ const expandToken = require('./url-declarative-resolve-expand-token');
22
21
 
23
22
  /**
24
23
  * Plan 122: **Developer subdomain `devNN` + remote hostname is not derived from envKey `tst`.** It comes only from
@@ -40,226 +39,6 @@ function applyTstRemoteDeveloperHostToOrigin(origin) {
40
39
  return origin;
41
40
  }
42
41
 
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
42
  /**
264
43
  * Ports from application.yaml: `listenPort` = container/process listen ({@link getContainerPort});
265
44
  * `publicPortBasis` = manifest root `port` ({@link getLocalPort}) for browser-published host URLs
@@ -293,10 +72,11 @@ function resolveListenPortAndPatternFromDoc(doc, entry) {
293
72
 
294
73
  /**
295
74
  * Port + pattern + optional Traefik host template for a url:// token.
75
+ * `frontDoorIngressActive` and `perTokenTraefik` come from {@link resolveDeclarativeUrlSurfaceState}.
296
76
  * @param {string} token
297
77
  * @param {Object} ctx
298
78
  * @param {Object} registry
299
- * @returns {{ appKey: string, listenPort: number, publicPortBasis: number, patternStr: string, hostTemplate: string|null, tls: boolean, frontDoorIngressActive: boolean }|null}
79
+ * @returns {{ appKey: string, listenPort: number, publicPortBasis: number, patternStr: string, hostTemplate: string|null, tls: boolean, frontDoorIngressActive: boolean, perTokenTraefik: boolean, declarativeUrlSurfacePhase: string, internalDockerUseOriginOnly: boolean }|null}
300
80
  */
301
81
  function resolveListenPortPatternForToken(token, ctx, registry) {
302
82
  const { targetKey } = parseUrlToken(token);
@@ -313,10 +93,18 @@ function resolveListenPortPatternForToken(token, ctx, registry) {
313
93
  }
314
94
  const { listenPort, publicPortBasis, patternStr } = portPattern;
315
95
  const meta = readFrontDoorHostTlsFromDoc(doc);
316
- const frontDoorIngressActive = computePathActive(
317
- Boolean(ctx.traefik),
318
- Boolean(doc && doc.frontDoorRouting && doc.frontDoorRouting.enabled === true)
96
+ const fromRegistry = readRegistryInternalDockerUseOriginOnly(appKey, registry);
97
+ const internalDockerUseOriginOnly =
98
+ fromRegistry !== undefined ? fromRegistry : meta.internalDockerUseOriginOnly;
99
+ const frontDoorRoutingEnabled = Boolean(
100
+ doc && doc.frontDoorRouting && doc.frontDoorRouting.enabled === true
319
101
  );
102
+ const { phase, perTokenTraefik, frontDoorIngressActive } = resolveDeclarativeUrlSurfaceState({
103
+ userCfg: ctx.userCfg,
104
+ appKey,
105
+ ctxTraefik: ctx.traefik,
106
+ frontDoorRoutingEnabled
107
+ });
320
108
  return {
321
109
  appKey,
322
110
  listenPort,
@@ -324,170 +112,18 @@ function resolveListenPortPatternForToken(token, ctx, registry) {
324
112
  patternStr,
325
113
  hostTemplate: meta.hostTemplate,
326
114
  tls: meta.tls,
327
- frontDoorIngressActive
115
+ frontDoorIngressActive,
116
+ perTokenTraefik,
117
+ declarativeUrlSurfacePhase: phase,
118
+ internalDockerUseOriginOnly
328
119
  };
329
120
  }
330
121
 
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
122
  module.exports = {
484
123
  applyTstRemoteDeveloperHost,
485
124
  applyTstRemoteDeveloperHostToOrigin,
486
- buildPublicUrlString,
487
- buildPublicHostOriginString,
488
- buildInternalUrlString,
489
- buildInternalHostOriginString,
125
+ ...buildUrls,
126
+ ...expandToken,
490
127
  parseUrlToken,
491
- expandResolvedUrlToken,
492
128
  resolveListenPortPatternForToken
493
129
  };