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