@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
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema-aware testPayload repair (payloadTemplate / expectedResult).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Helpers for repair-datasource testPayload generation
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 2.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {string|string[]|undefined} type - JSON Schema type
|
|
13
|
+
* @returns {string}
|
|
14
|
+
*/
|
|
15
|
+
function primarySchemaType(type) {
|
|
16
|
+
if (Array.isArray(type)) {
|
|
17
|
+
const nonNull = type.filter(t => t !== 'null');
|
|
18
|
+
return nonNull[0] || 'string';
|
|
19
|
+
}
|
|
20
|
+
return type || 'string';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @param {Object|null|undefined} schema - JSON Schema node
|
|
25
|
+
* @param {string} key - Property name
|
|
26
|
+
* @returns {Object|null}
|
|
27
|
+
*/
|
|
28
|
+
function getSchemaProperty(schema, key) {
|
|
29
|
+
if (!schema || typeof schema !== 'object') return null;
|
|
30
|
+
const props = schema.properties;
|
|
31
|
+
if (props && typeof props === 'object' && Object.prototype.hasOwnProperty.call(props, key)) {
|
|
32
|
+
return props[key];
|
|
33
|
+
}
|
|
34
|
+
if (schema.additionalProperties === true) {
|
|
35
|
+
return { type: 'string' };
|
|
36
|
+
}
|
|
37
|
+
if (schema.additionalProperties && typeof schema.additionalProperties === 'object') {
|
|
38
|
+
return schema.additionalProperties;
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param {Object|null|undefined} rootSchema - metadataSchema root
|
|
45
|
+
* @param {string[]} pathParts - Dot path under raw payload (no raw. prefix)
|
|
46
|
+
* @returns {Object|null}
|
|
47
|
+
*/
|
|
48
|
+
function getSchemaNodeAtPath(rootSchema, pathParts) {
|
|
49
|
+
if (!rootSchema || !pathParts.length) return rootSchema;
|
|
50
|
+
let node = rootSchema;
|
|
51
|
+
for (const part of pathParts) {
|
|
52
|
+
if (!part) continue;
|
|
53
|
+
const next = getSchemaProperty(node, part);
|
|
54
|
+
if (!next) return null;
|
|
55
|
+
node = next;
|
|
56
|
+
}
|
|
57
|
+
return node;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @param {Object|null|undefined} node - JSON Schema node
|
|
62
|
+
* @returns {*}
|
|
63
|
+
*/
|
|
64
|
+
function placeholderFromSchemaNode(node) {
|
|
65
|
+
if (!node || typeof node !== 'object') return '';
|
|
66
|
+
const type = primarySchemaType(node.type);
|
|
67
|
+
if (node.format === 'date-time') return '2025-01-15T10:30:00Z';
|
|
68
|
+
if (node.format === 'date') return '2025-01-15';
|
|
69
|
+
if (node.format === 'uuid') return '00000000-0000-4000-8000-000000000001';
|
|
70
|
+
if (type === 'boolean') return false;
|
|
71
|
+
if (type === 'integer' || type === 'number') return 0;
|
|
72
|
+
if (type === 'array') return [];
|
|
73
|
+
if (type === 'object') {
|
|
74
|
+
if (node.properties && typeof node.properties === 'object') {
|
|
75
|
+
const out = {};
|
|
76
|
+
for (const [k, sub] of Object.entries(node.properties)) {
|
|
77
|
+
out[k] = placeholderFromSchemaNode(sub);
|
|
78
|
+
}
|
|
79
|
+
return out;
|
|
80
|
+
}
|
|
81
|
+
return {};
|
|
82
|
+
}
|
|
83
|
+
return '';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @param {string} type - Legacy attribute type
|
|
88
|
+
* @returns {*}
|
|
89
|
+
*/
|
|
90
|
+
function placeholderForType(type) {
|
|
91
|
+
if (type === 'number' || type === 'integer') return 0;
|
|
92
|
+
if (type === 'boolean') return false;
|
|
93
|
+
if (type === 'array') return [];
|
|
94
|
+
if (type === 'object') return {};
|
|
95
|
+
return '';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* @param {Object} parsed - Datasource config
|
|
100
|
+
* @param {string[]} pathParts - Path under raw payload
|
|
101
|
+
* @param {Object} [attrConfig] - Attribute config (optional type fallback)
|
|
102
|
+
* @returns {*}
|
|
103
|
+
*/
|
|
104
|
+
function resolvePlaceholderForPath(parsed, pathParts, attrConfig) {
|
|
105
|
+
const node = getSchemaNodeAtPath(parsed?.metadataSchema, pathParts);
|
|
106
|
+
if (node) return placeholderFromSchemaNode(node);
|
|
107
|
+
return placeholderForType(attrConfig?.type || 'string');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @param {Object} obj - Target object (mutated)
|
|
112
|
+
* @param {string[]} pathParts - Path segments
|
|
113
|
+
* @param {*} value - Value to set
|
|
114
|
+
*/
|
|
115
|
+
function setNestedValue(obj, pathParts, value) {
|
|
116
|
+
const parts = pathParts.filter(Boolean);
|
|
117
|
+
if (!parts.length) return;
|
|
118
|
+
let cur = obj;
|
|
119
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
120
|
+
const p = parts[i];
|
|
121
|
+
if (!(p in cur) || typeof cur[p] !== 'object' || cur[p] === null || Array.isArray(cur[p])) {
|
|
122
|
+
cur[p] = {};
|
|
123
|
+
}
|
|
124
|
+
cur = cur[p];
|
|
125
|
+
}
|
|
126
|
+
const last = parts[parts.length - 1];
|
|
127
|
+
const existing = cur[last];
|
|
128
|
+
if (
|
|
129
|
+
existing &&
|
|
130
|
+
typeof existing === 'object' &&
|
|
131
|
+
!Array.isArray(existing) &&
|
|
132
|
+
value &&
|
|
133
|
+
typeof value === 'object' &&
|
|
134
|
+
!Array.isArray(value)
|
|
135
|
+
) {
|
|
136
|
+
cur[last] = { ...existing, ...value };
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
cur[last] = value;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* @param {Object} parsed - Datasource config
|
|
144
|
+
* @param {Array<{ path: string, config: Object }>} pathEntries - Sorted deepest-first
|
|
145
|
+
* @param {Object} payloadTemplate - payloadTemplate (mutated)
|
|
146
|
+
*/
|
|
147
|
+
function enrichObjectLeavesFromNestedPaths(parsed, pathEntries, payloadTemplate) {
|
|
148
|
+
const propertiesNode = getSchemaNodeAtPath(parsed?.metadataSchema, ['properties']);
|
|
149
|
+
for (const { path } of pathEntries) {
|
|
150
|
+
if (!path.startsWith('properties.')) continue;
|
|
151
|
+
const leaf = path.slice('properties.'.length);
|
|
152
|
+
if (!leaf || leaf.includes('.')) continue;
|
|
153
|
+
if (!payloadTemplate.properties || typeof payloadTemplate.properties !== 'object') {
|
|
154
|
+
payloadTemplate.properties = placeholderFromSchemaNode(propertiesNode);
|
|
155
|
+
}
|
|
156
|
+
if (payloadTemplate.properties[leaf] === undefined || payloadTemplate.properties[leaf] === '') {
|
|
157
|
+
const leafNode = getSchemaNodeAtPath(parsed?.metadataSchema, ['properties', leaf]);
|
|
158
|
+
payloadTemplate.properties[leaf] = leafNode
|
|
159
|
+
? placeholderFromSchemaNode(leafNode)
|
|
160
|
+
: 'sample';
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* @param {string} expressionPath - Path from {{ ... }} token
|
|
167
|
+
* @returns {string|null}
|
|
168
|
+
*/
|
|
169
|
+
function stripExpressionPathPrefix(expressionPath) {
|
|
170
|
+
const path = expressionPath.trim();
|
|
171
|
+
if (path.startsWith('raw.')) return path.slice(4);
|
|
172
|
+
if (path.startsWith('metadata.')) return path.slice(9);
|
|
173
|
+
return path;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* @param {Object} parsed - Datasource config
|
|
178
|
+
* @param {Object} attrs - fieldMappings.attributes
|
|
179
|
+
* @returns {Array<{ attrKey: string, path: string|null, config: Object, expectedOnly: *|null }>}
|
|
180
|
+
*/
|
|
181
|
+
function buildPathEntriesFromAttributes(parsed, attrs) {
|
|
182
|
+
const pathEntries = [];
|
|
183
|
+
for (const [attrKey, config] of Object.entries(attrs)) {
|
|
184
|
+
const match = config?.expression?.match(/\{\{\s*([^}|]+)/);
|
|
185
|
+
if (!match) {
|
|
186
|
+
const metaNode = parsed.metadataSchema?.properties?.[attrKey];
|
|
187
|
+
const expected = metaNode
|
|
188
|
+
? placeholderFromSchemaNode(metaNode)
|
|
189
|
+
: placeholderForType(config?.type || 'string');
|
|
190
|
+
pathEntries.push({ attrKey, path: null, config, expectedOnly: expected });
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
pathEntries.push({
|
|
194
|
+
attrKey,
|
|
195
|
+
path: stripExpressionPathPrefix(match[1]),
|
|
196
|
+
config,
|
|
197
|
+
expectedOnly: null
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
return pathEntries.sort((a, b) => {
|
|
201
|
+
const depthA = a.path ? a.path.split('.').length : 0;
|
|
202
|
+
const depthB = b.path ? b.path.split('.').length : 0;
|
|
203
|
+
return depthB - depthA;
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* @param {Object} parsed - Datasource config
|
|
209
|
+
* @param {Array} pathEntries - From buildPathEntriesFromAttributes
|
|
210
|
+
* @returns {{ payloadTemplate: Object, expectedResult: Object }}
|
|
211
|
+
*/
|
|
212
|
+
function buildTemplatesFromPathEntries(parsed, pathEntries) {
|
|
213
|
+
const payloadTemplate = {};
|
|
214
|
+
const expectedResult = {};
|
|
215
|
+
for (const entry of pathEntries) {
|
|
216
|
+
const { attrKey, path, config, expectedOnly } = entry;
|
|
217
|
+
const metaNode = parsed.metadataSchema?.properties?.[attrKey];
|
|
218
|
+
expectedResult[attrKey] = metaNode
|
|
219
|
+
? placeholderFromSchemaNode(metaNode)
|
|
220
|
+
: (expectedOnly ?? placeholderForType(config?.type || 'string'));
|
|
221
|
+
if (!path) continue;
|
|
222
|
+
const parts = path.split('.');
|
|
223
|
+
setNestedValue(payloadTemplate, parts, resolvePlaceholderForPath(parsed, parts, config));
|
|
224
|
+
}
|
|
225
|
+
enrichObjectLeavesFromNestedPaths(parsed, pathEntries, payloadTemplate);
|
|
226
|
+
return { payloadTemplate, expectedResult };
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Builds minimal payloadTemplate and expectedResult from attributes + metadataSchema.
|
|
231
|
+
*
|
|
232
|
+
* @param {Object} parsed - Parsed datasource (mutated)
|
|
233
|
+
* @param {string[]} changes - Change log
|
|
234
|
+
* @returns {boolean} True if testPayload was added or updated
|
|
235
|
+
*/
|
|
236
|
+
function repairTestPayload(parsed, changes) {
|
|
237
|
+
const attrs = parsed?.fieldMappings?.attributes;
|
|
238
|
+
if (!attrs || typeof attrs !== 'object') return false;
|
|
239
|
+
|
|
240
|
+
const pathEntries = buildPathEntriesFromAttributes(parsed, attrs);
|
|
241
|
+
const { payloadTemplate, expectedResult } = buildTemplatesFromPathEntries(parsed, pathEntries);
|
|
242
|
+
|
|
243
|
+
if (!parsed.testPayload) parsed.testPayload = {};
|
|
244
|
+
parsed.testPayload.payloadTemplate = payloadTemplate;
|
|
245
|
+
parsed.testPayload.expectedResult = expectedResult;
|
|
246
|
+
changes.push(
|
|
247
|
+
'Generated testPayload.payloadTemplate and testPayload.expectedResult from attributes and metadataSchema'
|
|
248
|
+
);
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
module.exports = {
|
|
253
|
+
primarySchemaType,
|
|
254
|
+
getSchemaNodeAtPath,
|
|
255
|
+
placeholderFromSchemaNode,
|
|
256
|
+
placeholderForType,
|
|
257
|
+
resolvePlaceholderForPath,
|
|
258
|
+
repairTestPayload
|
|
259
|
+
};
|
|
@@ -11,6 +11,13 @@
|
|
|
11
11
|
|
|
12
12
|
const { repairOpenapiSection } = require('./repair-datasource-openapi');
|
|
13
13
|
const { normalizeAutoRbacOperationKeys } = require('./repair-datasource-auto-rbac');
|
|
14
|
+
const { repairTestPayload } = require('./repair-datasource-test-payload');
|
|
15
|
+
const { repairComV2Manifest } = require('./repair-datasource-com-v2');
|
|
16
|
+
const {
|
|
17
|
+
isDeprecatedNoneLlmManifest,
|
|
18
|
+
repairNoneLlmToServiceContract,
|
|
19
|
+
stripDeprecatedServiceCategory
|
|
20
|
+
} = require('./repair-datasource-service-contract');
|
|
14
21
|
|
|
15
22
|
const DEFAULT_SYNC = {
|
|
16
23
|
mode: 'pull',
|
|
@@ -358,25 +365,6 @@ function repairSyncSection(parsed, changes) {
|
|
|
358
365
|
return true;
|
|
359
366
|
}
|
|
360
367
|
|
|
361
|
-
function placeholderForType(type) {
|
|
362
|
-
if (type === 'number' || type === 'integer') return 0;
|
|
363
|
-
if (type === 'boolean') return false;
|
|
364
|
-
if (type === 'array') return [];
|
|
365
|
-
if (type === 'object') return {};
|
|
366
|
-
return '';
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
function setNested(obj, pathParts, value) {
|
|
370
|
-
let cur = obj;
|
|
371
|
-
for (let i = 0; i < pathParts.length - 1; i++) {
|
|
372
|
-
const p = pathParts[i];
|
|
373
|
-
if (!(p in cur) || typeof cur[p] !== 'object') cur[p] = {};
|
|
374
|
-
cur = cur[p];
|
|
375
|
-
}
|
|
376
|
-
const last = pathParts[pathParts.length - 1];
|
|
377
|
-
if (last) cur[last] = value;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
368
|
/**
|
|
381
369
|
* Removes unknown top-level keys from testPayload (v2.4.1 closed root).
|
|
382
370
|
* @param {Object} parsed - Parsed datasource (mutated)
|
|
@@ -399,35 +387,38 @@ function sanitizeTestPayloadTopLevel(parsed, changes) {
|
|
|
399
387
|
}
|
|
400
388
|
|
|
401
389
|
/**
|
|
402
|
-
*
|
|
403
|
-
*
|
|
404
|
-
* @
|
|
405
|
-
* @param {string[]} changes - Change log
|
|
406
|
-
* @returns {boolean} True if testPayload was added or updated
|
|
390
|
+
* @param {Object} parsed
|
|
391
|
+
* @param {Object} options
|
|
392
|
+
* @returns {boolean}
|
|
407
393
|
*/
|
|
408
|
-
function
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
394
|
+
function shouldApplyServiceContractRepair(parsed, options) {
|
|
395
|
+
return (
|
|
396
|
+
isDeprecatedNoneLlmManifest(parsed) ||
|
|
397
|
+
(options.serviceContract && parsed?.resourceType === 'llm')
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* @param {Object} parsed
|
|
403
|
+
* @param {Object} options
|
|
404
|
+
* @param {boolean} none
|
|
405
|
+
* @param {string[]} changes
|
|
406
|
+
* @returns {boolean}
|
|
407
|
+
*/
|
|
408
|
+
function applyOptionalDatasourceRepairs(parsed, options, none, changes) {
|
|
409
|
+
let updated = false;
|
|
410
|
+
if (options.expose) {
|
|
411
|
+
updated = repairExposeFromAttributes(parsed, changes) || updated;
|
|
425
412
|
}
|
|
426
|
-
if (!
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
413
|
+
if (!none && options.sync) {
|
|
414
|
+
updated = repairSyncSection(parsed, changes) || updated;
|
|
415
|
+
}
|
|
416
|
+
if (options.test) {
|
|
417
|
+
sanitizeTestPayloadTopLevel(parsed, changes);
|
|
418
|
+
updated = repairTestPayload(parsed, changes) || updated;
|
|
419
|
+
updated = sanitizeTestPayloadTopLevel(parsed, changes) || updated;
|
|
420
|
+
}
|
|
421
|
+
return updated;
|
|
431
422
|
}
|
|
432
423
|
|
|
433
424
|
/**
|
|
@@ -440,32 +431,24 @@ function repairTestPayload(parsed, changes) {
|
|
|
440
431
|
*/
|
|
441
432
|
function repairDatasourceFile(parsed, options = {}, changes = []) {
|
|
442
433
|
const out = Array.isArray(changes) ? changes : [];
|
|
443
|
-
let updated =
|
|
444
|
-
const none = isNoneEntityType(parsed?.entityType);
|
|
445
|
-
|
|
446
|
-
updated = applyBaseDatasourceRepairs(parsed, none, out) || updated;
|
|
447
|
-
updated = applyOpenapiDatasourceRepairs(parsed, out) || updated;
|
|
434
|
+
let updated = stripDeprecatedServiceCategory(parsed, out);
|
|
448
435
|
|
|
449
|
-
if (options
|
|
450
|
-
updated =
|
|
436
|
+
if (shouldApplyServiceContractRepair(parsed, options)) {
|
|
437
|
+
updated = repairNoneLlmToServiceContract(parsed, out) || updated;
|
|
451
438
|
}
|
|
452
439
|
|
|
453
|
-
|
|
454
|
-
updated = repairSyncSection(parsed, out) || updated;
|
|
455
|
-
}
|
|
440
|
+
const none = isNoneEntityType(parsed?.entityType);
|
|
456
441
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
updated = sanitizeTestPayloadTopLevel(parsed, out) || updated;
|
|
461
|
-
}
|
|
442
|
+
updated = applyBaseDatasourceRepairs(parsed, none, out) || updated;
|
|
443
|
+
updated = applyOpenapiDatasourceRepairs(parsed, out) || updated;
|
|
444
|
+
updated = applyOptionalDatasourceRepairs(parsed, options, none, out) || updated;
|
|
462
445
|
|
|
463
446
|
return { updated, changes: out };
|
|
464
447
|
}
|
|
465
448
|
|
|
466
449
|
function applyBaseDatasourceRepairs(parsed, none, changes) {
|
|
467
|
-
|
|
468
|
-
|
|
450
|
+
let updated = repairComV2Manifest(parsed, changes);
|
|
451
|
+
if (none) return updated;
|
|
469
452
|
updated = repairDimensionBindingShape(parsed, changes) || updated;
|
|
470
453
|
updated = repairRootDimensionsFromAttributes(parsed, changes) || updated;
|
|
471
454
|
updated = repairMetadataSchemaFromAttributes(parsed, changes) || updated;
|
|
@@ -494,5 +477,7 @@ module.exports = {
|
|
|
494
477
|
DEFAULT_SYNC,
|
|
495
478
|
MINIMAL_METADATA_SCHEMA,
|
|
496
479
|
TEST_PAYLOAD_TOP_LEVEL_ALLOW,
|
|
497
|
-
isNoneEntityType
|
|
480
|
+
isNoneEntityType,
|
|
481
|
+
isDeprecatedNoneLlmManifest,
|
|
482
|
+
repairNoneLlmToServiceContract
|
|
498
483
|
};
|
|
@@ -10,9 +10,11 @@
|
|
|
10
10
|
const path = require('path');
|
|
11
11
|
const fs = require('fs');
|
|
12
12
|
const { backupIntegrationFile } = require('../utils/integration-file-backup');
|
|
13
|
+
const { trackRepairWrite } = require('./repair-changed-files');
|
|
13
14
|
const { systemKeyToKvPrefix, kvEnvKeyToPath, securityKeyToVar } = require('../utils/credential-secrets-env');
|
|
14
15
|
const { extractEnvTemplate } = require('../generator/split');
|
|
15
16
|
const { generateExternalEnvTemplateContent } = require('../utils/external-env-template');
|
|
17
|
+
const { commentOrphanKvEnvLines } = require('../utils/env-kv-orphan-lines');
|
|
16
18
|
|
|
17
19
|
/**
|
|
18
20
|
* Normalizes a keyvault config entry to canonical KV_* name and path-style value.
|
|
@@ -75,9 +77,16 @@ function addFromConfiguration(effective, config, prefix, seenNames, systemKey) {
|
|
|
75
77
|
* @param {string} systemKey - System key for path namespace
|
|
76
78
|
*/
|
|
77
79
|
function addFromAuthSecurity(effective, systemParsed, prefix, seenNames, systemKey) {
|
|
78
|
-
const
|
|
80
|
+
const { getAuthCredentialTemplate } = require('../utils/authentication-shape');
|
|
81
|
+
const { isPlatformCatalogKvRef } = require('../utils/platform-kv-ref');
|
|
82
|
+
const credential = getAuthCredentialTemplate(systemParsed.authentication);
|
|
83
|
+
const security = credential?.security ?? systemParsed.authentication?.security;
|
|
79
84
|
if (!security || typeof security !== 'object') return;
|
|
80
85
|
for (const key of Object.keys(security)) {
|
|
86
|
+
const securityVal = security[key];
|
|
87
|
+
if (typeof securityVal === 'string' && isPlatformCatalogKvRef(securityVal)) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
81
90
|
const envName = `KV_${prefix}_${securityKeyToVar(key)}`;
|
|
82
91
|
if (seenNames.has(envName)) continue;
|
|
83
92
|
const pathVal = kvEnvKeyToPath(envName, systemKey);
|
|
@@ -136,7 +145,7 @@ function buildExpectedByKey(effective) {
|
|
|
136
145
|
* @param {Object} [systemParsed] - Parsed system config for template context (preferred)
|
|
137
146
|
* @returns {boolean}
|
|
138
147
|
*/
|
|
139
|
-
function createEnvTemplateIfMissing(envPath, expectedByKey, dryRun, changes, systemParsed) {
|
|
148
|
+
function createEnvTemplateIfMissing(envPath, expectedByKey, dryRun, changes, systemParsed, backupCtx) {
|
|
140
149
|
if (fs.existsSync(envPath)) return false;
|
|
141
150
|
if (expectedByKey.size === 0) return false;
|
|
142
151
|
const content = systemParsed
|
|
@@ -145,6 +154,7 @@ function createEnvTemplateIfMissing(envPath, expectedByKey, dryRun, changes, sys
|
|
|
145
154
|
if (!content || !content.trim()) return false;
|
|
146
155
|
const hasKeyValueLine = /^[A-Z_][A-Z0-9_]*=/m.test(content);
|
|
147
156
|
if (!hasKeyValueLine) return false;
|
|
157
|
+
trackRepairWrite(envPath, backupCtx);
|
|
148
158
|
if (!dryRun) {
|
|
149
159
|
fs.writeFileSync(envPath, content + (content.endsWith('\n') ? '' : '\n'), { mode: 0o644, encoding: 'utf8' });
|
|
150
160
|
}
|
|
@@ -229,6 +239,51 @@ function mergeEnvTemplateContent(content, expectedByKey) {
|
|
|
229
239
|
return { output, changed: changedRef.value };
|
|
230
240
|
}
|
|
231
241
|
|
|
242
|
+
/**
|
|
243
|
+
* Comments active KV_* lines whose env key is not in the system-derived expected set.
|
|
244
|
+
* @param {string} content
|
|
245
|
+
* @param {Map<string, string>} expectedByKey
|
|
246
|
+
* @param {{ value: boolean }} changedRef
|
|
247
|
+
* @returns {string}
|
|
248
|
+
*/
|
|
249
|
+
function commentOrphanKvLines(content, expectedByKey, changedRef) {
|
|
250
|
+
const { content: next, changed } = commentOrphanKvEnvLines(content, expectedByKey);
|
|
251
|
+
if (changed) {
|
|
252
|
+
changedRef.value = true;
|
|
253
|
+
}
|
|
254
|
+
return next;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* @param {string} envPath
|
|
259
|
+
* @param {string} output
|
|
260
|
+
* @param {boolean} dryRun
|
|
261
|
+
* @param {Object} [backupCtx]
|
|
262
|
+
*/
|
|
263
|
+
function persistEnvTemplate(envPath, output, dryRun, backupCtx) {
|
|
264
|
+
trackRepairWrite(envPath, backupCtx);
|
|
265
|
+
if (!dryRun) {
|
|
266
|
+
backupIntegrationFile(envPath, backupCtx);
|
|
267
|
+
fs.writeFileSync(envPath, output, { mode: 0o644, encoding: 'utf8' });
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* @param {string} content
|
|
273
|
+
* @param {Map<string, string>} expectedByKey
|
|
274
|
+
* @returns {{ output: string, mergeChanged: boolean, pruneChanged: boolean }}
|
|
275
|
+
*/
|
|
276
|
+
function mergeAndPruneEnvTemplate(content, expectedByKey) {
|
|
277
|
+
const mergeResult = mergeEnvTemplateContent(content, expectedByKey);
|
|
278
|
+
const pruneChanged = { value: false };
|
|
279
|
+
const output = commentOrphanKvLines(mergeResult.output, expectedByKey, pruneChanged);
|
|
280
|
+
return {
|
|
281
|
+
output,
|
|
282
|
+
mergeChanged: mergeResult.changed,
|
|
283
|
+
pruneChanged: pruneChanged.value
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
232
287
|
/**
|
|
233
288
|
* Repairs env.template so KV_ names and path-style kv:// values match the system file.
|
|
234
289
|
* @param {string} appPath - Application directory path
|
|
@@ -240,41 +295,35 @@ function mergeEnvTemplateContent(content, expectedByKey) {
|
|
|
240
295
|
* @returns {boolean} True if env.template was repaired or created
|
|
241
296
|
*/
|
|
242
297
|
function repairEnvTemplate(appPath, systemParsed, systemKey, dryRun, changes, backupCtx) {
|
|
243
|
-
const
|
|
244
|
-
const expectedByKey = buildExpectedByKey(effective);
|
|
298
|
+
const expectedByKey = buildExpectedByKey(buildEffectiveConfiguration(systemParsed, systemKey));
|
|
245
299
|
const envPath = path.join(appPath, 'env.template');
|
|
246
300
|
|
|
247
|
-
if (createEnvTemplateIfMissing(envPath, expectedByKey, dryRun, changes, systemParsed)) {
|
|
301
|
+
if (createEnvTemplateIfMissing(envPath, expectedByKey, dryRun, changes, systemParsed, backupCtx)) {
|
|
248
302
|
return true;
|
|
249
303
|
}
|
|
250
304
|
if (!fs.existsSync(envPath)) {
|
|
251
305
|
return false;
|
|
252
306
|
}
|
|
253
307
|
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
308
|
+
const { output, mergeChanged, pruneChanged } = mergeAndPruneEnvTemplate(
|
|
309
|
+
fs.readFileSync(envPath, 'utf8'),
|
|
310
|
+
expectedByKey
|
|
311
|
+
);
|
|
312
|
+
if (!mergeChanged && !pruneChanged) {
|
|
313
|
+
return false;
|
|
260
314
|
}
|
|
261
|
-
|
|
315
|
+
|
|
316
|
+
persistEnvTemplate(envPath, output, dryRun, backupCtx);
|
|
317
|
+
if (mergeChanged) {
|
|
262
318
|
changes.push('Repaired env.template (KV_* names and path-style kv:// values)');
|
|
263
|
-
return true;
|
|
264
319
|
}
|
|
265
|
-
|
|
320
|
+
if (pruneChanged) {
|
|
321
|
+
changes.push('Commented stale env.template KV_* lines (not in system authentication)');
|
|
322
|
+
}
|
|
323
|
+
return true;
|
|
266
324
|
}
|
|
267
325
|
|
|
268
|
-
|
|
269
|
-
* Returns true if a kv value looks like legacy format (KeyVault suffix or no path segments).
|
|
270
|
-
* @param {string} val - Value from authentication.security or configuration
|
|
271
|
-
* @returns {boolean}
|
|
272
|
-
*/
|
|
273
|
-
function isLegacyKvValue(val) {
|
|
274
|
-
if (typeof val !== 'string' || !val.trim().toLowerCase().startsWith('kv://')) return false;
|
|
275
|
-
const after = val.trim().slice(5); // after 'kv://'
|
|
276
|
-
return after.includes('KeyVault') || !after.includes('/');
|
|
277
|
-
}
|
|
326
|
+
const { isLegacyKvValue } = require('../utils/platform-kv-ref');
|
|
278
327
|
|
|
279
328
|
/**
|
|
280
329
|
* Normalizes authentication.security values to path-style kv:// (kv://systemKey/variable).
|
|
@@ -341,7 +390,9 @@ function normalizeConfigurationSection(config, prefix, systemKey, changes) {
|
|
|
341
390
|
function normalizeSystemFileAuthAndConfig(systemParsed, systemKey, changes) {
|
|
342
391
|
const prefix = systemKeyToKvPrefix(systemKey);
|
|
343
392
|
if (!prefix) return false;
|
|
344
|
-
const
|
|
393
|
+
const { getAuthCredentialTemplate } = require('../utils/authentication-shape');
|
|
394
|
+
const credential = getAuthCredentialTemplate(systemParsed.authentication);
|
|
395
|
+
const security = credential?.security ?? systemParsed.authentication?.security;
|
|
345
396
|
let updated = (security && typeof security === 'object' && normalizeSecuritySection(security, prefix, systemKey, changes));
|
|
346
397
|
const config = systemParsed.configuration;
|
|
347
398
|
if (Array.isArray(config)) {
|