@aifabrix/builder 2.45.5 → 2.46.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.
- package/.cursor/rules/cli-layout.mdc +2 -0
- package/.cursor/rules/cli-product-neutral.mdc +43 -0
- package/.cursor/rules/project-rules.mdc +1 -0
- package/README.md +43 -17
- package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +1 -1
- package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +1 -1
- package/jest.config.default.js +2 -1
- package/jest.config.isolated.js +2 -1
- package/jest.global-live-fabrix-hooks.js +36 -0
- package/jest.isolated-projects.js +130 -0
- package/jest.projects.js +41 -136
- package/lib/api/api-response-errors.js +124 -0
- package/lib/api/governance-scenario-pack.api.js +159 -0
- package/lib/api/index.js +43 -3
- package/lib/api/lifecycle.api.js +77 -0
- package/lib/api/pipeline.api.js +3 -1
- package/lib/api/records-bulk.api.js +14 -1
- package/lib/api/validation-runner.js +3 -1
- package/lib/app/deploy-config.js +4 -1
- package/lib/app/down.js +20 -1
- package/lib/app/push.js +4 -5
- package/lib/app/register.js +7 -4
- package/lib/app/run-env-compose.js +84 -30
- package/lib/build/index.js +5 -0
- package/lib/certification/sync-system-certification.js +13 -6
- package/lib/cli/index.js +4 -0
- package/lib/cli/infra-guided-auth.js +109 -0
- package/lib/cli/infra-guided.js +84 -81
- package/lib/cli/setup-app.help.js +0 -31
- package/lib/cli/setup-app.js +28 -2
- package/lib/cli/setup-app.test-commands.js +5 -57
- package/lib/cli/setup-auth.js +25 -0
- package/lib/cli/setup-certification-commands.js +147 -0
- package/lib/cli/setup-certification.help.js +141 -0
- package/lib/cli/setup-environment.js +19 -2
- package/lib/cli/setup-external-system-help.js +62 -0
- package/lib/cli/setup-external-system.js +25 -3
- package/lib/cli/setup-infra.js +9 -1
- package/lib/cli/setup-platform.js +6 -1
- package/lib/cli/setup-secrets.js +33 -1
- package/lib/cli/setup-utility-help-after.js +22 -2
- package/lib/cli/setup-utility-repair.js +198 -0
- package/lib/cli/setup-utility-resolve.js +40 -4
- package/lib/cli/setup-utility-validate.js +197 -0
- package/lib/cli/setup-utility.js +4 -239
- package/lib/commands/auth-status-client-tokens.js +214 -0
- package/lib/commands/auth-status-dataplane-version.js +58 -20
- package/lib/commands/auth-status.js +41 -47
- package/lib/commands/datasource-test-trust-cli.js +27 -23
- package/lib/commands/datasource-unified-test-cli.js +6 -3
- package/lib/commands/datasource-unified-test-cli.options.js +5 -1
- package/lib/commands/datasource.js +7 -7
- package/lib/commands/dev-show-display.js +8 -1
- package/lib/commands/governance-cli-shared.js +94 -0
- package/lib/commands/governance-command-action.js +132 -0
- package/lib/commands/governance-download-external.js +34 -0
- package/lib/commands/governance-generate-external.js +71 -0
- package/lib/commands/governance-upload-external.js +36 -0
- package/lib/commands/governance-verify-external.js +64 -0
- package/lib/commands/governance.js +144 -0
- package/lib/commands/lifecycle-command-action.js +123 -0
- package/lib/commands/lifecycle-external.js +268 -0
- package/lib/commands/login.js +11 -2
- package/lib/commands/repair-auth-apply.js +127 -0
- package/lib/commands/repair-changed-files.js +41 -0
- package/lib/commands/repair-datasource-keys.js +4 -1
- package/lib/commands/repair-datasource-run.js +59 -0
- package/lib/commands/repair-datasource-test-payload.js +259 -0
- package/lib/commands/repair-datasource.js +1 -51
- package/lib/commands/repair-env-template.js +64 -13
- package/lib/commands/repair-external-run.js +216 -0
- package/lib/commands/repair-openapi-sync.js +23 -0
- package/lib/commands/repair-persist.js +4 -0
- package/lib/commands/repair-rbac.js +52 -1
- package/lib/commands/repair-steps.js +145 -0
- package/lib/commands/repair.js +29 -296
- package/lib/commands/secrets-get.js +184 -0
- package/lib/commands/secrets-remove-all.js +3 -1
- package/lib/commands/setup-image-refresh.js +146 -0
- package/lib/commands/setup-modes.js +158 -162
- package/lib/commands/setup-platform-auth.js +76 -0
- package/lib/commands/setup-prompts-admin.js +244 -0
- package/lib/commands/setup-prompts-platform-mode.js +67 -0
- package/lib/commands/setup-prompts-validators.js +36 -0
- package/lib/commands/setup-prompts.js +24 -76
- package/lib/commands/setup-run-context.js +45 -0
- package/lib/commands/setup-spinners.js +39 -0
- package/lib/commands/setup.js +27 -5
- package/lib/commands/teardown.js +39 -0
- package/lib/commands/test-e2e-external.js +24 -8
- package/lib/commands/test-governance-external.js +3 -24
- package/lib/commands/test-trust-external.js +20 -21
- package/lib/commands/up-common.js +25 -13
- package/lib/commands/up-dataplane.js +50 -13
- package/lib/commands/upload-publish-context.js +75 -0
- package/lib/commands/upload-sidecar-followups.js +89 -0
- package/lib/commands/upload.js +90 -108
- package/lib/commands/verify-governance-combined-external.js +61 -0
- package/lib/commands/verify-governance-command-action.js +64 -0
- package/lib/commands/verify-governance-db.js +102 -0
- package/lib/commands/verify-governance-external.js +77 -0
- package/lib/commands/verify-governance-result-builders.js +71 -0
- package/lib/commands/verify-operations-command-action.js +68 -0
- package/lib/commands/verify-operations-external.js +268 -0
- package/lib/commands/verify-operations-persist.js +75 -0
- package/lib/commands/verify-operations-step-plan.js +68 -0
- package/lib/commands/verify-operations-steps.js +111 -0
- package/lib/commands/verify-trust-command-action.js +70 -0
- package/lib/commands/verify-trust-external.js +67 -0
- package/lib/commands/wizard-config-normalizer.js +43 -23
- package/lib/commands/wizard-core.js +2 -0
- package/lib/core/admin-password-generator.js +38 -0
- package/lib/core/admin-secrets-bundle.js +111 -0
- package/lib/core/admin-secrets-env-overlay.js +62 -0
- package/lib/core/admin-secrets.js +32 -4
- package/lib/core/config-attach-extensions.js +3 -0
- package/lib/core/config-platform-controller.js +44 -0
- package/lib/core/config-setup-installation-profile.js +42 -0
- package/lib/core/config-setup-platform-mode.js +46 -0
- package/lib/core/config.js +46 -36
- package/lib/core/secrets-admin-env.js +6 -2
- package/lib/core/secrets-ensure.js +4 -0
- package/lib/core/secrets-env-content.js +54 -48
- package/lib/core/secrets-env-write.js +10 -1
- package/lib/core/secrets-infra-placeholder-sync.js +2 -0
- package/lib/core/setup-installation-profile.js +43 -0
- package/lib/core/setup-platform-mode.js +55 -0
- package/lib/datasource/agent-trust-debug-log.js +1 -1
- package/lib/datasource/agent-trust-run.js +5 -3
- package/lib/datasource/audit-evidence-extract-debug.js +30 -18
- package/lib/datasource/audit-evidence-extract.js +7 -4
- package/lib/datasource/audit-evidence-verify-matrix.js +54 -26
- package/lib/datasource/bulk-loader-run-batches.js +15 -3
- package/lib/datasource/datasource-load-export-context.js +3 -0
- package/lib/datasource/log-cleaner.js +2 -2
- package/lib/datasource/log-viewer.js +8 -8
- package/lib/datasource/test-e2e.js +4 -1
- package/lib/datasource/unified-validation-run-body.js +3 -1
- package/lib/datasource/unified-validation-run.js +5 -2
- package/lib/deployment/environment-poll-status.js +138 -0
- package/lib/deployment/environment.js +42 -34
- package/lib/external-system/download.js +21 -20
- package/lib/external-system/generator.js +5 -1
- package/lib/external-system/integration-auth-context.js +45 -0
- package/lib/external-system/test-auth.js +12 -5
- package/lib/external-system/test.js +6 -6
- package/lib/generator/external-controller-manifest.js +15 -0
- package/lib/governance/governance-cli-errors.js +96 -0
- package/lib/governance/governance-download-display.js +38 -0
- package/lib/governance/governance-run-display.js +215 -25
- package/lib/infrastructure/admin-secrets-apply.js +84 -0
- package/lib/infrastructure/admin-secrets-ensure.js +130 -0
- package/lib/infrastructure/admin-secrets-resolve.js +95 -0
- package/lib/infrastructure/admin-secrets-sync.js +91 -0
- package/lib/infrastructure/helpers.js +23 -129
- package/lib/infrastructure/index.js +5 -6
- package/lib/infrastructure/orphan-infra-docker-teardown.js +11 -5
- package/lib/lifecycle/certification-progress.js +231 -0
- package/lib/lifecycle/dataplane-ui-url.js +145 -0
- package/lib/lifecycle/exit-codes.js +24 -0
- package/lib/lifecycle/json-envelope.js +25 -0
- package/lib/lifecycle/lifecycle-governance-options.js +51 -0
- package/lib/lifecycle/logger-quiet.js +29 -0
- package/lib/lifecycle/open-api-published.js +59 -0
- package/lib/lifecycle/operations-readiness-metrics.js +101 -0
- package/lib/lifecycle/product-model.js +196 -0
- package/lib/lifecycle/report-display.js +471 -0
- package/lib/lifecycle/scenario-upload.js +191 -0
- package/lib/lifecycle/verify-step-progress.js +87 -0
- package/lib/parameters/infra-kv-discovery.js +27 -2
- package/lib/protection/auth-context.js +10 -4
- package/lib/schema/application-schema.json +1 -1
- package/lib/schema/datasource-test-run.schema.json +89 -6
- package/lib/schema/external-datasource.schema.json +2636 -2622
- package/lib/schema/external-system.schema.json +1089 -761
- package/lib/schema/infra.parameter.yaml +45 -0
- package/lib/schema/type/credential-field-registry.json +103 -97
- package/lib/utils/aifabrix-test-runtime-guard.js +125 -0
- package/lib/utils/api.js +55 -31
- package/lib/utils/app-relative-path-env.js +112 -0
- package/lib/utils/cli-secrets-error-format.js +83 -21
- package/lib/utils/cli-utils.js +16 -4
- package/lib/utils/compose-generate-docker-compose.js +4 -0
- package/lib/utils/compose-traefik-ingress-base.js +16 -1
- package/lib/utils/config-secrets-path.js +46 -0
- package/lib/utils/controller-url.js +88 -1
- package/lib/utils/credential-secrets-env.js +137 -9
- package/lib/utils/dataplane-resolver.js +129 -2
- package/lib/utils/declarative-url-ports.js +3 -3
- package/lib/utils/deployment-auth-mode.js +41 -0
- package/lib/utils/developer-volume-id.js +33 -0
- package/lib/utils/env-copy.js +14 -9
- package/lib/utils/env-kv-orphan-lines.js +43 -0
- package/lib/utils/error-formatters/network-errors.js +13 -4
- package/lib/utils/external-env-template.js +1 -0
- package/lib/utils/external-system-readiness-core.js +10 -0
- package/lib/utils/external-system-readiness-display.js +80 -23
- package/lib/utils/health-check.js +4 -1
- package/lib/utils/help-builder.js +11 -8
- package/lib/utils/keycloak-realm-ready.js +101 -0
- package/lib/utils/load-cip-capacity-display-config.js +61 -15
- package/lib/utils/manifest-source-emit.js +2 -0
- package/lib/utils/pipeline-upload-auth-retry.js +82 -0
- package/lib/utils/platform-controller-url.js +156 -0
- package/lib/utils/postgres-platform-bootstrap.js +199 -0
- package/lib/utils/postgres-wipe.js +9 -2
- package/lib/utils/resolve-env-mode.js +47 -0
- package/lib/utils/secrets-generator.js +31 -25
- package/lib/utils/secrets-missing-error.js +164 -0
- package/lib/utils/service-url-label.js +81 -0
- package/lib/utils/setup-quiet-output.js +25 -0
- package/lib/utils/template-helpers.js +15 -0
- package/lib/utils/token-manager-client-credentials.js +201 -0
- package/lib/utils/token-manager-messages.js +8 -0
- package/lib/utils/token-manager-refresh.js +12 -2
- package/lib/utils/token-manager.js +86 -105
- package/lib/utils/upload-pipeline-ui.js +12 -5
- package/lib/utils/upload-sync-options.js +42 -0
- package/lib/utils/url-declarative-public-base.js +21 -3
- package/lib/utils/url-declarative-vdir-inactive-env.js +14 -4
- package/lib/utils/validation-poll-ui.js +8 -0
- package/lib/utils/validation-run-stage.js +45 -0
- package/package.json +1 -1
- package/templates/applications/dataplane/application.yaml +2 -1
- package/templates/applications/dataplane/env.template +24 -1
- package/templates/applications/miso-controller/env.template +16 -0
- package/templates/external-system/README.md.hbs +74 -17
- package/templates/python/docker-compose.hbs +19 -18
- package/templates/typescript/docker-compose.hbs +18 -17
- package/lib/commands/test-governance-command-action.js +0 -55
- package/lib/commands/test-trust-command-action.js +0 -118
|
@@ -128,25 +128,94 @@ function logServerValidationWarnings(validationBody) {
|
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
/**
|
|
132
|
+
* @param {Object[]} results - Probe result rows
|
|
133
|
+
* @returns {boolean}
|
|
134
|
+
*/
|
|
135
|
+
function connectivityCheckFailed(results) {
|
|
136
|
+
return results.some(
|
|
137
|
+
row =>
|
|
138
|
+
row?.endpointTestResults?.success === false
|
|
139
|
+
|| row?.endpointTestResults?.endpointReachable === false
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
131
143
|
/**
|
|
132
144
|
* @param {Object} results - Probe result rows
|
|
133
145
|
* @param {Object} summary - summarizeProbeResults output
|
|
134
146
|
*/
|
|
135
147
|
function logProbeCredentialLine(results, summary) {
|
|
136
148
|
logSeparator();
|
|
137
|
-
logSectionTitle('
|
|
138
|
-
|
|
139
|
-
if (anyEndpointFail) {
|
|
149
|
+
logSectionTitle('Connectivity check:');
|
|
150
|
+
if (connectivityCheckFailed(results)) {
|
|
140
151
|
logger.log(formatBlockingError('Failed (see Key Issues / endpoint test)'));
|
|
141
|
-
} else if (summary.failed > 0) {
|
|
142
|
-
logger.log(formatBlockingError('Some datasource checks failed'));
|
|
143
|
-
} else if (summary.partial > 0) {
|
|
144
|
-
logger.log(chalk.yellow('⚠ Completed with warnings'));
|
|
145
152
|
} else {
|
|
146
|
-
logger.log(formatSuccessLine('Passed'));
|
|
153
|
+
logger.log(formatSuccessLine('Passed (system credential / testEndpoint)'));
|
|
154
|
+
}
|
|
155
|
+
if (summary.partial > 0 || summary.failed > 0) {
|
|
156
|
+
logSeparator();
|
|
157
|
+
logSectionTitle('Datasource readiness:');
|
|
158
|
+
if (summary.failed > 0) {
|
|
159
|
+
logger.log(formatBlockingError('Some datasource checks failed'));
|
|
160
|
+
} else {
|
|
161
|
+
logger.log(
|
|
162
|
+
chalk.yellow(
|
|
163
|
+
'⚠ Partial — validation or certification warnings (not a failed credential test)'
|
|
164
|
+
)
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
logger.log(
|
|
168
|
+
chalk.gray(
|
|
169
|
+
' Upload --probe runs structural validation + certification tiers; live .env connectivity is separate.'
|
|
170
|
+
)
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* @param {Object[]} results
|
|
177
|
+
*/
|
|
178
|
+
function logProbeEmptyResultsWarningIfNeeded(results) {
|
|
179
|
+
if (results.length === 0) {
|
|
180
|
+
logger.log(chalk.yellow('⚠ No runtime datasource results were returned by the dataplane probe.'));
|
|
181
|
+
logger.log(chalk.gray(' Endpoint credential test may still pass even if datasource checks were not reported.'));
|
|
147
182
|
}
|
|
148
183
|
}
|
|
149
184
|
|
|
185
|
+
/**
|
|
186
|
+
* @param {Array<{ key: string, lines: string[] }>} issues
|
|
187
|
+
*/
|
|
188
|
+
function logProbeKeyIssues(issues) {
|
|
189
|
+
if (issues.length === 0) return;
|
|
190
|
+
logSeparator();
|
|
191
|
+
logSectionTitle('Key Issues:');
|
|
192
|
+
for (const { key, lines } of issues) {
|
|
193
|
+
logger.log(chalk.white(key));
|
|
194
|
+
for (const line of lines) {
|
|
195
|
+
logger.log(chalk.red(`- ${line}`));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* @param {Object[]} results
|
|
202
|
+
* @param {Object} summary
|
|
203
|
+
* @returns {string[]}
|
|
204
|
+
*/
|
|
205
|
+
function buildProbeNextActionHints(results, summary) {
|
|
206
|
+
const hints = [];
|
|
207
|
+
if (connectivityCheckFailed(results)) {
|
|
208
|
+
hints.push('Fix API credentials or permissions (connectivity check failed)');
|
|
209
|
+
}
|
|
210
|
+
if (summary.failed > 0) {
|
|
211
|
+
hints.push('Fix datasource errors listed under Key Issues');
|
|
212
|
+
}
|
|
213
|
+
if (summary.partial > 0 && summary.failed === 0) {
|
|
214
|
+
hints.push('Review Key Issues for certification/validation warnings (ICC, MCP, dimensions)');
|
|
215
|
+
}
|
|
216
|
+
return hints;
|
|
217
|
+
}
|
|
218
|
+
|
|
150
219
|
/**
|
|
151
220
|
* @param {Object} probeRaw - Unwrapped POST /validation/run body
|
|
152
221
|
* @param {string} systemKey
|
|
@@ -156,25 +225,13 @@ function logProbeRuntimeBlock(probeRaw, systemKey) {
|
|
|
156
225
|
const summary = summarizeProbeResults(results);
|
|
157
226
|
logSeparator();
|
|
158
227
|
logger.log(chalk.bold('Runtime Readiness:'));
|
|
159
|
-
|
|
160
|
-
logger.log(chalk.yellow('⚠ No runtime datasource results were returned by the dataplane probe.'));
|
|
161
|
-
logger.log(chalk.gray(' Endpoint credential test may still pass even if datasource checks were not reported.'));
|
|
162
|
-
}
|
|
228
|
+
logProbeEmptyResultsWarningIfNeeded(results);
|
|
163
229
|
logDatasourceTable(summary.rows, summary);
|
|
164
|
-
|
|
165
|
-
logSeparator();
|
|
166
|
-
logSectionTitle('Key Issues:');
|
|
167
|
-
for (const { key, lines } of summary.issues) {
|
|
168
|
-
logger.log(chalk.white(key));
|
|
169
|
-
for (const line of lines) {
|
|
170
|
-
logger.log(chalk.red(`- ${line}`));
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
230
|
+
logProbeKeyIssues(summary.issues);
|
|
174
231
|
logProbeCredentialLine(results, summary);
|
|
175
232
|
logSeparator();
|
|
176
233
|
logNextActions(
|
|
177
|
-
|
|
234
|
+
buildProbeNextActionHints(results, summary),
|
|
178
235
|
`Run: aifabrix datasource test-e2e <datasourceKey> --app ${systemKey}`
|
|
179
236
|
);
|
|
180
237
|
}
|
|
@@ -357,7 +357,10 @@ async function performHealthCheckAttempt(healthCheckUrl, attempt, maxAttempts, d
|
|
|
357
357
|
}
|
|
358
358
|
const healthCheckPassed = await checkHealthEndpoint(healthCheckUrl, debug);
|
|
359
359
|
if (healthCheckPassed) {
|
|
360
|
-
|
|
360
|
+
const { isSetupQuietOutput } = require('./setup-quiet-output');
|
|
361
|
+
if (!isSetupQuietOutput()) {
|
|
362
|
+
logger.log(formatSuccessLine('Application is healthy'));
|
|
363
|
+
}
|
|
361
364
|
if (debug) {
|
|
362
365
|
logger.log(chalk.gray(`[DEBUG] Health check passed after ${attempt + 1} attempt(s)`));
|
|
363
366
|
}
|
|
@@ -73,7 +73,11 @@ const CATEGORIES = [
|
|
|
73
73
|
{ name: 'app' },
|
|
74
74
|
{ name: 'credential' },
|
|
75
75
|
{ name: 'deployment' },
|
|
76
|
-
{ name: 'integration-client' }
|
|
76
|
+
{ name: 'integration-client' },
|
|
77
|
+
{ name: 'dimension' },
|
|
78
|
+
{ name: 'dimension value', term: 'dimension value <command>' },
|
|
79
|
+
{ name: 'identity' },
|
|
80
|
+
{ name: 'protection' }
|
|
77
81
|
]
|
|
78
82
|
},
|
|
79
83
|
{
|
|
@@ -100,15 +104,14 @@ const CATEGORIES = [
|
|
|
100
104
|
{ name: 'datasource' },
|
|
101
105
|
{ name: 'datasource load', term: 'datasource load <datasourceKey>' },
|
|
102
106
|
{ name: 'datasource export', term: 'datasource export <datasourceKey>' },
|
|
103
|
-
{ name: 'dimension' },
|
|
104
|
-
{ name: 'dimension value', term: 'dimension value <command>' },
|
|
105
|
-
{ name: 'identity' },
|
|
106
|
-
{ name: 'protection' },
|
|
107
107
|
{ name: 'test', term: 'test <appKey|systemKey>' },
|
|
108
|
+
{ name: 'test-integration', term: 'test-integration <appKey|systemKey>' },
|
|
108
109
|
{ name: 'test-e2e', term: 'test-e2e <appKey|systemKey>' },
|
|
109
|
-
{ name: '
|
|
110
|
-
{ name: '
|
|
111
|
-
{ name: '
|
|
110
|
+
{ name: 'verify-operations', term: 'verify-operations <systemKey>' },
|
|
111
|
+
{ name: 'verify-trust', term: 'verify-trust <systemKey>' },
|
|
112
|
+
{ name: 'verify-governance', term: 'verify-governance <systemKey>' },
|
|
113
|
+
{ name: 'governance', term: 'governance <generate|verify|download|upload> <systemKey>' },
|
|
114
|
+
{ name: 'lifecycle', term: 'lifecycle <systemKey>' }
|
|
112
115
|
]
|
|
113
116
|
},
|
|
114
117
|
{
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Poll Keycloak until the `aifabrix` realm is available (post-wipe / fresh install).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Keycloak realm readiness for setup auth
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const { computeAppBaseUrl } = require('./platform-controller-url');
|
|
12
|
+
const config = require('../core/config');
|
|
13
|
+
const { readUrlsLocalRegistrySync } = require('./urls-local-registry');
|
|
14
|
+
const { normalizeFrontDoorPatternForHealth } = require('./health-check-url');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {string} keycloakBase
|
|
18
|
+
* @returns {string}
|
|
19
|
+
*/
|
|
20
|
+
function buildRealmWellKnownUrl(keycloakBase) {
|
|
21
|
+
const base = String(keycloakBase || '').replace(/\/+$/, '');
|
|
22
|
+
return `${base}/realms/aifabrix/.well-known/openid-configuration`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @async
|
|
27
|
+
* @param {string} url
|
|
28
|
+
* @returns {Promise<boolean>}
|
|
29
|
+
*/
|
|
30
|
+
async function probeRealmWellKnown(url) {
|
|
31
|
+
const controller = new AbortController();
|
|
32
|
+
const timer = setTimeout(() => controller.abort(), 8000);
|
|
33
|
+
try {
|
|
34
|
+
const res = await fetch(url, { method: 'GET', signal: controller.signal });
|
|
35
|
+
return res.ok;
|
|
36
|
+
} catch {
|
|
37
|
+
return false;
|
|
38
|
+
} finally {
|
|
39
|
+
clearTimeout(timer);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function computeKeycloakDirectBaseUrlFromRegistry(registry, developerIdNum) {
|
|
44
|
+
const portRaw = registry && registry['keycloak-port'];
|
|
45
|
+
const port =
|
|
46
|
+
typeof portRaw === 'number'
|
|
47
|
+
? portRaw
|
|
48
|
+
: typeof portRaw === 'string' && /^\d+$/.test(portRaw.trim())
|
|
49
|
+
? parseInt(portRaw.trim(), 10)
|
|
50
|
+
: null;
|
|
51
|
+
if (!port || port <= 0) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const patternRaw = registry && registry['keycloak-pattern'];
|
|
55
|
+
const pattern = typeof patternRaw === 'string' && patternRaw.trim() ? patternRaw.trim() : null;
|
|
56
|
+
const mount = pattern ? normalizeFrontDoorPatternForHealth(pattern) : null;
|
|
57
|
+
const adjusted = port + (Number.isFinite(developerIdNum) ? developerIdNum : 0) * 100;
|
|
58
|
+
return `http://localhost:${adjusted}${mount || ''}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Wait until Keycloak serves the aifabrix realm OIDC metadata.
|
|
63
|
+
*
|
|
64
|
+
* @async
|
|
65
|
+
* @param {{ timeoutSeconds?: number, intervalMs?: number }} [opts]
|
|
66
|
+
* @returns {Promise<void>}
|
|
67
|
+
* @throws {Error} On timeout
|
|
68
|
+
*/
|
|
69
|
+
async function waitForKeycloakRealmReady(opts = {}) {
|
|
70
|
+
const timeoutSeconds = Number.isFinite(opts.timeoutSeconds) ? opts.timeoutSeconds : 180;
|
|
71
|
+
const intervalMs = Number.isFinite(opts.intervalMs) ? opts.intervalMs : 3000;
|
|
72
|
+
const keycloakBase = await computeAppBaseUrl('keycloak');
|
|
73
|
+
const url = buildRealmWellKnownUrl(keycloakBase);
|
|
74
|
+
const registry = readUrlsLocalRegistrySync();
|
|
75
|
+
const developerIdRaw = await config.getDeveloperId();
|
|
76
|
+
const developerIdNum = typeof developerIdRaw === 'string' ? parseInt(developerIdRaw, 10) : developerIdRaw;
|
|
77
|
+
const directBase = computeKeycloakDirectBaseUrlFromRegistry(registry, developerIdNum);
|
|
78
|
+
const directUrl = directBase ? buildRealmWellKnownUrl(directBase) : null;
|
|
79
|
+
const deadline = Date.now() + timeoutSeconds * 1000;
|
|
80
|
+
|
|
81
|
+
while (Date.now() < deadline) {
|
|
82
|
+
if (await probeRealmWellKnown(url)) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (directUrl && (await probeRealmWellKnown(directUrl))) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
throw new Error(
|
|
92
|
+
`Keycloak realm "aifabrix" was not ready within ${timeoutSeconds}s (checked ${url}${directUrl ? ` and ${directUrl}` : ''}). ` +
|
|
93
|
+
'Ensure Miso Controller finished onboarding after the database wipe.'
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
module.exports = {
|
|
98
|
+
buildRealmWellKnownUrl,
|
|
99
|
+
waitForKeycloakRealmReady,
|
|
100
|
+
computeKeycloakDirectBaseUrlFromRegistry
|
|
101
|
+
};
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
'use strict';
|
|
10
10
|
|
|
11
|
-
const fs = require('fs');
|
|
12
11
|
const path = require('path');
|
|
12
|
+
const { existsSync, readFileSync } = require('../internal/fs-real-sync');
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* @param {object|null} schema - Parsed external-datasource.schema.json
|
|
@@ -33,8 +33,8 @@ function extractStandardOperationOrderFromSchema(schema) {
|
|
|
33
33
|
*/
|
|
34
34
|
function tryReadJsonFile(p) {
|
|
35
35
|
try {
|
|
36
|
-
if (!p || !
|
|
37
|
-
return JSON.parse(
|
|
36
|
+
if (!p || !existsSync(p)) return null;
|
|
37
|
+
return JSON.parse(readFileSync(p, 'utf8'));
|
|
38
38
|
} catch {
|
|
39
39
|
return null;
|
|
40
40
|
}
|
|
@@ -48,25 +48,74 @@ function tryReadJsonFile(p) {
|
|
|
48
48
|
function resolveExternalDatasourceSchemaPath() {
|
|
49
49
|
if (process.env.AIFABRIX_EXTERNAL_DATASOURCE_SCHEMA) {
|
|
50
50
|
const envPath = String(process.env.AIFABRIX_EXTERNAL_DATASOURCE_SCHEMA).trim();
|
|
51
|
-
if (envPath &&
|
|
51
|
+
if (envPath && existsSync(envPath)) return envPath;
|
|
52
52
|
}
|
|
53
53
|
const candidates = [
|
|
54
|
+
path.join(__dirname, '../schema/external-datasource.schema.json'),
|
|
54
55
|
path.join(process.cwd(), 'app/schemas/json/external-datasource.schema.json'),
|
|
55
56
|
path.join(process.cwd(), 'aifabrix-dataplane/app/schemas/json/external-datasource.schema.json'),
|
|
56
57
|
path.join(process.cwd(), '..', 'aifabrix-dataplane', 'app/schemas/json/external-datasource.schema.json'),
|
|
57
58
|
path.join(__dirname, '../../../aifabrix-dataplane/app/schemas/json/external-datasource.schema.json')
|
|
58
59
|
];
|
|
59
60
|
for (const c of candidates) {
|
|
60
|
-
if (c &&
|
|
61
|
+
if (c && existsSync(c)) return c;
|
|
61
62
|
}
|
|
62
63
|
return null;
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
const FALLBACK_PATH = path.join(__dirname, '../schema/cip-capacity-display.fallback.json');
|
|
66
67
|
|
|
68
|
+
/**
|
|
69
|
+
* When schema/fallback JSON cannot be read (missing file, parse error, or Jest fs mocks in a shared worker).
|
|
70
|
+
* Must stay aligned with `cip-capacity-display.fallback.json` and dataplane `cipDefinition.operations`.
|
|
71
|
+
*/
|
|
72
|
+
const HARDCODED_STANDARD_OPERATION_ORDER = ['list', 'get', 'create', 'update', 'delete'];
|
|
73
|
+
const HARDCODED_DISPLAY_ALIASES = { create: 'insert (create)' };
|
|
74
|
+
|
|
67
75
|
/** @type {{ standardOrder: string[], aliases: Record<string, string> }|null} */
|
|
68
76
|
let _cache = null;
|
|
69
77
|
|
|
78
|
+
/**
|
|
79
|
+
* @returns {{ standardOperationOrder: string[], displayAliases: Record<string, string> }}
|
|
80
|
+
*/
|
|
81
|
+
function readFallbackDisplayConfig() {
|
|
82
|
+
const fromFile = tryReadJsonFile(FALLBACK_PATH);
|
|
83
|
+
const order =
|
|
84
|
+
fromFile && Array.isArray(fromFile.standardOperationOrder) && fromFile.standardOperationOrder.length
|
|
85
|
+
? fromFile.standardOperationOrder
|
|
86
|
+
: HARDCODED_STANDARD_OPERATION_ORDER;
|
|
87
|
+
const aliases =
|
|
88
|
+
fromFile && fromFile.displayAliases && typeof fromFile.displayAliases === 'object'
|
|
89
|
+
? fromFile.displayAliases
|
|
90
|
+
: HARDCODED_DISPLAY_ALIASES;
|
|
91
|
+
return { standardOperationOrder: order, displayAliases: aliases };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Prefer schema key order, then append any fallback standard ops missing from the schema
|
|
96
|
+
* (guards partial/stale schema files and cross-test cache pollution in Jest).
|
|
97
|
+
* @param {string[]|null} fromSchema
|
|
98
|
+
* @param {string[]} fbOrder
|
|
99
|
+
* @returns {string[]}
|
|
100
|
+
*/
|
|
101
|
+
function mergeStandardOperationOrders(fromSchema, fbOrder) {
|
|
102
|
+
const schemaOps = Array.isArray(fromSchema)
|
|
103
|
+
? fromSchema.map(op => String(op).trim().toLowerCase()).filter(Boolean)
|
|
104
|
+
: [];
|
|
105
|
+
const fallbackOps = Array.isArray(fbOrder)
|
|
106
|
+
? fbOrder.map(op => String(op).trim().toLowerCase()).filter(Boolean)
|
|
107
|
+
: [];
|
|
108
|
+
if (!schemaOps.length) return fallbackOps;
|
|
109
|
+
const seen = new Set(schemaOps);
|
|
110
|
+
const merged = [...schemaOps];
|
|
111
|
+
for (const op of fallbackOps) {
|
|
112
|
+
if (seen.has(op)) continue;
|
|
113
|
+
seen.add(op);
|
|
114
|
+
merged.push(op);
|
|
115
|
+
}
|
|
116
|
+
return merged;
|
|
117
|
+
}
|
|
118
|
+
|
|
70
119
|
/**
|
|
71
120
|
* @returns {{ standardOrder: string[], aliases: Record<string, string> }}
|
|
72
121
|
*/
|
|
@@ -75,16 +124,12 @@ function getCipCapacityDisplayConfig() {
|
|
|
75
124
|
const schemaPath = resolveExternalDatasourceSchemaPath();
|
|
76
125
|
const schema = schemaPath ? tryReadJsonFile(schemaPath) : null;
|
|
77
126
|
const fromSchema = extractStandardOperationOrderFromSchema(schema);
|
|
78
|
-
const fallback =
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
fallback.displayAliases && typeof fallback.displayAliases === 'object'
|
|
85
|
-
? fallback.displayAliases
|
|
86
|
-
: { create: 'insert (create)' };
|
|
87
|
-
_cache = { standardOrder, aliases };
|
|
127
|
+
const fallback = readFallbackDisplayConfig();
|
|
128
|
+
const standardOrder = mergeStandardOperationOrders(
|
|
129
|
+
fromSchema,
|
|
130
|
+
fallback.standardOperationOrder
|
|
131
|
+
);
|
|
132
|
+
_cache = { standardOrder, aliases: fallback.displayAliases };
|
|
88
133
|
return _cache;
|
|
89
134
|
}
|
|
90
135
|
|
|
@@ -122,6 +167,7 @@ function clearCipCapacityDisplayConfigCacheForTests() {
|
|
|
122
167
|
|
|
123
168
|
module.exports = {
|
|
124
169
|
extractStandardOperationOrderFromSchema,
|
|
170
|
+
mergeStandardOperationOrders,
|
|
125
171
|
resolveExternalDatasourceSchemaPath,
|
|
126
172
|
getCipCapacityDisplayConfig,
|
|
127
173
|
standardOperationRank,
|
|
@@ -104,6 +104,8 @@ function isStdoutTty() {
|
|
|
104
104
|
function emitManifestMetadataLineIfTTY(logger, opts) {
|
|
105
105
|
if (!logger || typeof logger.log !== 'function') return;
|
|
106
106
|
if (!opts || opts.json || opts.envOnly) return;
|
|
107
|
+
const { isSetupQuietOutput } = require('./setup-quiet-output');
|
|
108
|
+
if (isSetupQuietOutput()) return;
|
|
107
109
|
if (!isStdoutTty()) return;
|
|
108
110
|
const appKey = opts.appKey && typeof opts.appKey === 'string' ? opts.appKey.trim() : '';
|
|
109
111
|
const appPath = opts.appPath && typeof opts.appPath === 'string' ? opts.appPath.trim() : '';
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry dataplane pipeline upload with application client token when device Bearer fails.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Pipeline publish auth fallback when device Bearer is rejected
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const chalk = require('chalk');
|
|
12
|
+
const logger = require('./logger');
|
|
13
|
+
const { uploadApplicationViaPipeline } = require('../api/pipeline.api');
|
|
14
|
+
const { getDeploymentAuth } = require('./token-manager');
|
|
15
|
+
const { resolveControllerUrl } = require('./controller-url');
|
|
16
|
+
const config = require('../core/config');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {Object} apiResponse
|
|
20
|
+
* @returns {boolean}
|
|
21
|
+
*/
|
|
22
|
+
function isPipelineAuthFailure(apiResponse) {
|
|
23
|
+
if (!apiResponse || apiResponse.success !== false) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
const status = Number(apiResponse.status) || 0;
|
|
27
|
+
if (status === 401 || status === 403) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
const text = String(
|
|
31
|
+
apiResponse.formattedError || apiResponse.error || apiResponse.message || ''
|
|
32
|
+
).toLowerCase();
|
|
33
|
+
return text.includes('invalid token') || text.includes('unauthorized') || text.includes('authentication');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {string} systemKey
|
|
38
|
+
* @returns {Promise<Object|null>}
|
|
39
|
+
*/
|
|
40
|
+
async function resolveClientTokenAuthForPipelineRetry(systemKey) {
|
|
41
|
+
try {
|
|
42
|
+
const controllerUrl = await resolveControllerUrl();
|
|
43
|
+
const environment = await config.resolveEnvironment();
|
|
44
|
+
return await getDeploymentAuth(controllerUrl, environment, systemKey, {
|
|
45
|
+
deploymentAuth: 'client-credentials'
|
|
46
|
+
});
|
|
47
|
+
} catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* POST /api/v1/pipeline/upload with optional client-token retry after device Bearer 401.
|
|
54
|
+
*
|
|
55
|
+
* @async
|
|
56
|
+
* @param {string} dataplaneUrl
|
|
57
|
+
* @param {Object} authConfig
|
|
58
|
+
* @param {Object} payload
|
|
59
|
+
* @param {string} systemKey - External system key for credential lookup on retry
|
|
60
|
+
* @returns {Promise<Object>}
|
|
61
|
+
*/
|
|
62
|
+
async function uploadApplicationViaPipelineWithAuthRetry(dataplaneUrl, authConfig, payload, systemKey) {
|
|
63
|
+
const first = await uploadApplicationViaPipeline(dataplaneUrl, authConfig, payload);
|
|
64
|
+
if (!isPipelineAuthFailure(first) || authConfig.type !== 'bearer') {
|
|
65
|
+
return first;
|
|
66
|
+
}
|
|
67
|
+
const clientAuth = await resolveClientTokenAuthForPipelineRetry(systemKey);
|
|
68
|
+
if (!clientAuth || clientAuth.type === 'bearer') {
|
|
69
|
+
return first;
|
|
70
|
+
}
|
|
71
|
+
logger.log(
|
|
72
|
+
chalk.yellow(
|
|
73
|
+
'Device login token was rejected for pipeline publish; retrying with application client token…'
|
|
74
|
+
)
|
|
75
|
+
);
|
|
76
|
+
return uploadApplicationViaPipeline(dataplaneUrl, clientAuth, payload);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
module.exports = {
|
|
80
|
+
isPipelineAuthFailure,
|
|
81
|
+
uploadApplicationViaPipelineWithAuthRetry
|
|
82
|
+
};
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Absolute public base URLs for platform apps (Keycloak, Miso Controller, Dataplane).
|
|
3
|
+
* Used by setup (`platform-controller`), guided footers, and declarative routing.
|
|
4
|
+
*
|
|
5
|
+
* @fileoverview Platform app public URL resolution (Traefik / localhost + dev ports)
|
|
6
|
+
* @author AI Fabrix Team
|
|
7
|
+
* @version 1.0.0
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
|
|
15
|
+
const config = require('../core/config');
|
|
16
|
+
const pathsUtil = require('./paths');
|
|
17
|
+
const { loadConfigFile } = require('./config-format');
|
|
18
|
+
const { computePublicUrlBaseString } = require('./url-declarative-public-base');
|
|
19
|
+
const { joinUrlPath, normalizeFrontDoorPatternForHealth } = require('./health-check-url');
|
|
20
|
+
const { getDevPorts } = require('./dev-config');
|
|
21
|
+
|
|
22
|
+
const MISO_CONTROLLER_APP = 'miso-controller';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Bundled `templates/applications/<app>/application.yaml` (fresh install has no builder copy yet).
|
|
26
|
+
*
|
|
27
|
+
* @param {string} appName
|
|
28
|
+
* @returns {Object|null}
|
|
29
|
+
*/
|
|
30
|
+
function loadBundledApplicationVariables(appName) {
|
|
31
|
+
const templateConfigPath = path.join(
|
|
32
|
+
pathsUtil.getProjectRoot(),
|
|
33
|
+
'templates',
|
|
34
|
+
'applications',
|
|
35
|
+
appName,
|
|
36
|
+
'application.yaml'
|
|
37
|
+
);
|
|
38
|
+
if (!fs.existsSync(templateConfigPath)) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const variables = loadConfigFile(templateConfigPath);
|
|
42
|
+
return variables && typeof variables === 'object' ? variables : null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Load platform app variables from materialized builder config, or from bundled template
|
|
47
|
+
* when `aifabrix setup` runs before `up-platform` has copied templates.
|
|
48
|
+
*
|
|
49
|
+
* @param {string} appName
|
|
50
|
+
* @returns {Object}
|
|
51
|
+
*/
|
|
52
|
+
function loadAppVariables(appName) {
|
|
53
|
+
const builderPath = pathsUtil.getBuilderPath(appName);
|
|
54
|
+
if (fs.existsSync(builderPath)) {
|
|
55
|
+
try {
|
|
56
|
+
const configPath = pathsUtil.resolveApplicationConfigPath(builderPath);
|
|
57
|
+
return loadConfigFile(configPath) || {};
|
|
58
|
+
} catch (err) {
|
|
59
|
+
const msg = err && err.message ? String(err.message) : '';
|
|
60
|
+
if (!msg.includes('Application config not found')) {
|
|
61
|
+
throw err;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const fromTemplate = loadBundledApplicationVariables(appName);
|
|
66
|
+
if (fromTemplate) {
|
|
67
|
+
return fromTemplate;
|
|
68
|
+
}
|
|
69
|
+
throw new Error(
|
|
70
|
+
`Application config not found for platform app "${appName}". ` +
|
|
71
|
+
'Run `aifabrix setup` or `aifabrix up-platform` to materialize builder templates.'
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function computeLocalFullPlatformFrontDoorUrl(params) {
|
|
76
|
+
const { setupPlatformMode, remoteServer, developerIdNum, frontDoorRouting } = params;
|
|
77
|
+
if (setupPlatformMode !== 'full') {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
if (remoteServer && String(remoteServer).trim()) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
const ports = getDevPorts(Number.isFinite(developerIdNum) ? developerIdNum : 0);
|
|
84
|
+
const mount = normalizeFrontDoorPatternForHealth(frontDoorRouting.pattern);
|
|
85
|
+
// Full local platform uses a single front-door port (3000 + devId×100), not the infra Traefik port.
|
|
86
|
+
return joinUrlPath(`http://localhost:${ports.app}`, mount);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Compute the absolute base URL for a platform app (same rules as guided `up-platform` footer).
|
|
91
|
+
*
|
|
92
|
+
* @async
|
|
93
|
+
* @param {string} appName - e.g. `miso-controller`, `keycloak`, `dataplane`
|
|
94
|
+
* @returns {Promise<string>}
|
|
95
|
+
*/
|
|
96
|
+
async function computeAppBaseUrl(appName) {
|
|
97
|
+
const variables = loadAppVariables(appName);
|
|
98
|
+
const basePort = Number(variables.port || 3000);
|
|
99
|
+
const developerIdRaw = await config.getDeveloperId();
|
|
100
|
+
const developerIdNum =
|
|
101
|
+
typeof developerIdRaw === 'string' ? parseInt(developerIdRaw, 10) : developerIdRaw;
|
|
102
|
+
const userCfg = await config.getConfig();
|
|
103
|
+
const remoteServer = await config.getRemoteServer();
|
|
104
|
+
const infraTlsEnabled = Boolean(userCfg && userCfg.tlsEnabled);
|
|
105
|
+
|
|
106
|
+
const fd = variables.frontDoorRouting || null;
|
|
107
|
+
const frontDoorEnabled = Boolean(fd && fd.enabled === true);
|
|
108
|
+
const traefikOn = Boolean(userCfg && userCfg.traefik);
|
|
109
|
+
const pathActive = Boolean(traefikOn && frontDoorEnabled);
|
|
110
|
+
const setupPlatformMode = await config.getSetupPlatformMode();
|
|
111
|
+
|
|
112
|
+
const publicBase = computePublicUrlBaseString({
|
|
113
|
+
traefik: traefikOn,
|
|
114
|
+
pathActive,
|
|
115
|
+
hostTemplate: fd ? fd.host : null,
|
|
116
|
+
tls: fd ? fd.tls : true,
|
|
117
|
+
developerIdRaw,
|
|
118
|
+
remoteServer,
|
|
119
|
+
profile: 'docker',
|
|
120
|
+
listenPort: basePort,
|
|
121
|
+
developerIdNum,
|
|
122
|
+
infraTlsEnabled
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
if (pathActive) {
|
|
126
|
+
const localFullUrl = computeLocalFullPlatformFrontDoorUrl({
|
|
127
|
+
setupPlatformMode,
|
|
128
|
+
remoteServer,
|
|
129
|
+
developerIdNum,
|
|
130
|
+
frontDoorRouting: fd
|
|
131
|
+
});
|
|
132
|
+
if (localFullUrl) return localFullUrl;
|
|
133
|
+
const mount = normalizeFrontDoorPatternForHealth(fd.pattern);
|
|
134
|
+
return joinUrlPath(publicBase, mount);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return String(publicBase).replace(/\/+$/, '');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Absolute Miso Controller URL for local platform install / setup auth.
|
|
142
|
+
*
|
|
143
|
+
* @async
|
|
144
|
+
* @returns {Promise<string>}
|
|
145
|
+
*/
|
|
146
|
+
async function resolvePlatformControllerUrl() {
|
|
147
|
+
return computeAppBaseUrl(MISO_CONTROLLER_APP);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
module.exports = {
|
|
151
|
+
MISO_CONTROLLER_APP,
|
|
152
|
+
loadAppVariables,
|
|
153
|
+
loadBundledApplicationVariables,
|
|
154
|
+
computeAppBaseUrl,
|
|
155
|
+
resolvePlatformControllerUrl
|
|
156
|
+
};
|