@aifabrix/builder 2.45.0 → 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/docs-rules.mdc +3 -1
- package/.cursor/rules/project-rules.mdc +1 -0
- package/README.md +43 -17
- package/integration/hubspot-test/wizard-hubspot-e2e.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 +69 -121
- package/lib/api/agent-metadata-validation.api.js +93 -0
- package/lib/api/api-response-errors.js +124 -0
- package/lib/api/audit-api-helpers.js +68 -0
- package/lib/api/audit.api.js +119 -0
- package/lib/api/auth-cache.api.js +44 -0
- package/lib/api/certificates.api.js +4 -4
- package/lib/api/credential.api.js +2 -2
- package/lib/api/dataplane-health.api.js +137 -0
- package/lib/api/dataplane-sync.api.js +27 -0
- package/lib/api/datasources-core.api.js +21 -18
- package/lib/api/datasources-extended.api.js +22 -22
- package/lib/api/dimensions.api.js +3 -0
- package/lib/api/external-systems.api.js +13 -13
- package/lib/api/governance-scenario-pack.api.js +159 -0
- package/lib/api/governance-scenarios.api.js +39 -0
- package/lib/api/groups.api.js +79 -0
- package/lib/api/index.js +88 -5
- package/lib/api/lifecycle.api.js +77 -0
- package/lib/api/pipeline.api.js +7 -5
- package/lib/api/protection.api.js +157 -0
- package/lib/api/records-bulk.api.js +43 -0
- package/lib/api/records-search-parse.js +49 -0
- package/lib/api/records-search.api.js +29 -0
- package/lib/api/types/agent-metadata-validation.types.js +67 -0
- package/lib/api/types/audit.types.js +72 -0
- package/lib/api/types/dataplane-health.types.js +27 -0
- package/lib/api/types/dimensions.types.js +2 -0
- package/lib/api/types/governance-scenarios.types.js +39 -0
- package/lib/api/types/protection.types.js +69 -0
- package/lib/api/types/records-bulk.types.js +35 -0
- package/lib/api/types/records-search.types.js +28 -0
- package/lib/api/user-groups.api.js +50 -0
- package/lib/api/users.api.js +95 -0
- package/lib/api/validation-run.api.js +3 -3
- package/lib/api/validation-runner.js +5 -3
- package/lib/api/wizard-platform.api.js +3 -3
- package/lib/api/wizard.api.js +21 -21
- package/lib/app/deploy-config.js +4 -1
- package/lib/app/deploy.js +34 -19
- 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 +8 -2
- package/lib/cli/infra-guided-auth.js +109 -0
- package/lib/cli/infra-guided.js +91 -69
- package/lib/cli/setup-app.help.js +19 -2
- package/lib/cli/setup-app.js +58 -23
- package/lib/cli/setup-app.test-commands.js +28 -21
- package/lib/cli/setup-auth.js +55 -3
- 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 +62 -6
- 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 +65 -0
- package/lib/cli/setup-utility-repair.js +198 -0
- package/lib/cli/setup-utility-resolve.js +42 -6
- package/lib/cli/setup-utility-validate.js +197 -0
- package/lib/cli/setup-utility.js +41 -258
- package/lib/commands/auth-status-client-tokens.js +214 -0
- package/lib/commands/auth-status-dataplane-version.js +269 -0
- package/lib/commands/auth-status-display.js +94 -0
- package/lib/commands/auth-status.js +111 -53
- package/lib/commands/credential-push.js +10 -5
- package/lib/commands/datasource-load-export-cli.js +178 -0
- package/lib/commands/datasource-test-trust-cli.js +118 -0
- package/lib/commands/datasource-unified-test-cli.js +31 -20
- package/lib/commands/datasource-unified-test-cli.options.js +22 -3
- package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +5 -5
- package/lib/commands/datasource-verify-audit-cli.js +96 -0
- package/lib/commands/datasource.js +68 -1
- package/lib/commands/dev-show-display.js +8 -1
- package/lib/commands/dimension-value.js +43 -13
- package/lib/commands/dimension.js +38 -7
- 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 +131 -0
- package/lib/commands/identity-group-cli.js +146 -0
- package/lib/commands/identity-membership-role-cache.js +175 -0
- package/lib/commands/identity-shared.js +94 -0
- package/lib/commands/identity-user-cli.js +158 -0
- package/lib/commands/identity.js +43 -0
- package/lib/commands/lifecycle-command-action.js +123 -0
- package/lib/commands/lifecycle-external.js +268 -0
- package/lib/commands/login.js +56 -17
- package/lib/commands/protection-cli-leaves.js +286 -0
- package/lib/commands/protection.js +50 -0
- 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 -286
- 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 +61 -14
- package/lib/commands/test-governance-cli-options.js +47 -0
- package/lib/commands/test-governance-external.js +67 -0
- package/lib/commands/test-trust-cli-options.js +32 -0
- package/lib/commands/test-trust-external.js +126 -0
- 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 +108 -105
- 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 +5 -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-device-dataplane.js +185 -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 +45 -0
- package/lib/datasource/agent-trust-fetch.js +115 -0
- package/lib/datasource/agent-trust-map.js +101 -0
- package/lib/datasource/agent-trust-mock.js +44 -0
- package/lib/datasource/agent-trust-run.js +95 -0
- package/lib/datasource/agent-trust-timeout.js +25 -0
- package/lib/datasource/audit-evidence-display.js +80 -0
- package/lib/datasource/audit-evidence-extract-debug.js +115 -0
- package/lib/datasource/audit-evidence-extract.js +180 -0
- package/lib/datasource/audit-evidence-matrix-rows.js +158 -0
- package/lib/datasource/audit-evidence-operation-aliases.js +63 -0
- package/lib/datasource/audit-evidence-poll.js +109 -0
- package/lib/datasource/audit-evidence-run.js +177 -0
- package/lib/datasource/audit-evidence-verify-helpers.js +167 -0
- package/lib/datasource/audit-evidence-verify-matrix.js +205 -0
- package/lib/datasource/audit-evidence-verify.js +108 -0
- package/lib/datasource/bulk-loader-run-batches.js +100 -0
- package/lib/datasource/bulk-loader-service-retry.js +52 -0
- package/lib/datasource/bulk-loader-service.js +127 -0
- package/lib/datasource/capability/run-capability-dimension.js +2 -1
- package/lib/datasource/datasource-exporter-resolve.js +82 -0
- package/lib/datasource/datasource-exporter-service.js +144 -0
- package/lib/datasource/datasource-identifier.js +148 -0
- package/lib/datasource/datasource-load-export-context.js +95 -0
- package/lib/datasource/integration-context.js +6 -4
- package/lib/datasource/local-data-paths.js +145 -0
- package/lib/datasource/log-cleaner.js +241 -0
- package/lib/datasource/log-viewer.js +111 -6
- package/lib/datasource/record-file-parser.js +85 -0
- package/lib/datasource/record-mapper.js +129 -0
- package/lib/datasource/resolve-app.js +74 -55
- package/lib/datasource/test-e2e.js +29 -2
- package/lib/datasource/unified-validation-run-body.js +3 -1
- package/lib/datasource/unified-validation-run-resolve.js +45 -12
- package/lib/datasource/unified-validation-run.js +47 -18
- package/lib/datasource/validate.js +37 -20
- 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-system-level.js +25 -4
- package/lib/external-system/test.js +9 -7
- 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-pack-loader.js +70 -0
- package/lib/governance/governance-run-display.js +309 -0
- package/lib/identity/identity-apply-core.js +108 -0
- package/lib/identity/identity-apply-phases.js +244 -0
- package/lib/identity/identity-apply-service.js +77 -0
- package/lib/identity/identity-csv-parser.js +114 -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/internal/fs-real-sync.js +29 -1
- 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 +51 -0
- package/lib/protection/convert-batch.js +90 -0
- package/lib/protection/load.js +41 -0
- package/lib/protection/paths.js +158 -0
- package/lib/protection/preflight-datasource-ready.js +46 -0
- package/lib/protection/protection-create-probe-lines.js +142 -0
- package/lib/protection/protection-create-probes.js +95 -0
- package/lib/protection/protection-create-scaffold.js +281 -0
- package/lib/protection/protection-display-helpers.js +445 -0
- package/lib/protection/protection-display.js +215 -0
- package/lib/protection/protection-preset-registry.js +97 -0
- package/lib/protection/report-exit.js +62 -0
- package/lib/protection/resolve.js +202 -0
- package/lib/protection/run-commands-validate.js +130 -0
- package/lib/protection/run-commands.js +216 -0
- package/lib/protection/run-protection-create-helpers.js +134 -0
- package/lib/protection/run-protection-create-probes-flow.js +43 -0
- package/lib/protection/run-protection-create.js +191 -0
- package/lib/protection/scope.js +22 -0
- package/lib/protection/sync-after-upload.js +64 -0
- package/lib/protection/upload-batch.js +127 -0
- package/lib/protection/validate-batch.js +113 -0
- package/lib/protection/validate-local.js +65 -0
- package/lib/resolvers/dimension-file.js +29 -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 -2588
- package/lib/schema/external-system.schema.json +1089 -761
- package/lib/schema/flag-map-validation-run.json +2 -2
- package/lib/schema/infra.parameter.yaml +45 -0
- package/lib/schema/protection.schema.json +374 -0
- package/lib/schema/type/credential-field-registry.json +642 -0
- package/lib/schema/wizard-config.schema.json +1 -1
- package/lib/utils/agent-trust-run-display.js +231 -0
- package/lib/utils/agent-trust-run-exit.js +59 -0
- package/lib/utils/agent-trust-wait-ui.js +94 -0
- 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-exit-codes.js +30 -0
- package/lib/utils/cli-secrets-error-format.js +83 -21
- package/lib/utils/cli-sync-options.js +33 -0
- 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-push-ui.js +90 -0
- package/lib/utils/credential-secrets-env.js +137 -9
- package/lib/utils/dataplane-cli-version-gate.js +202 -0
- package/lib/utils/dataplane-cli-version-help.js +74 -0
- package/lib/utils/dataplane-resolver.js +129 -2
- package/lib/utils/datasource-export-display.js +137 -0
- package/lib/utils/datasource-load-display.js +174 -0
- package/lib/utils/datasource-load-export-ui.js +120 -0
- package/lib/utils/datasource-test-run-capability-scope.js +3 -3
- package/lib/utils/datasource-test-run-display.js +3 -3
- package/lib/utils/datasource-test-run-tty-log.js +5 -1
- 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 +35 -26
- 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 +24 -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/semver-compare.js +127 -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 +98 -0
- 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 +22 -7
- package/lib/utils/validation-run-stage.js +45 -0
- package/lib/validation/wizard-config-validator.js +58 -19
- package/package.json +1 -1
- package/templates/applications/dataplane/application.yaml +2 -1
- package/templates/applications/dataplane/env.template +36 -1
- package/templates/applications/dataplane/rbac.yaml +4 -0
- package/templates/applications/miso-controller/env.template +16 -0
- package/templates/external-system/README.md.hbs +116 -11
- package/templates/python/docker-compose.hbs +19 -18
- package/templates/typescript/docker-compose.hbs +18 -17
|
@@ -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,7 @@
|
|
|
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');
|
|
14
15
|
|
|
15
16
|
const DEFAULT_SYNC = {
|
|
16
17
|
mode: 'pull',
|
|
@@ -358,25 +359,6 @@ function repairSyncSection(parsed, changes) {
|
|
|
358
359
|
return true;
|
|
359
360
|
}
|
|
360
361
|
|
|
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
362
|
/**
|
|
381
363
|
* Removes unknown top-level keys from testPayload (v2.4.1 closed root).
|
|
382
364
|
* @param {Object} parsed - Parsed datasource (mutated)
|
|
@@ -398,38 +380,6 @@ function sanitizeTestPayloadTopLevel(parsed, changes) {
|
|
|
398
380
|
return true;
|
|
399
381
|
}
|
|
400
382
|
|
|
401
|
-
/**
|
|
402
|
-
* Builds minimal payloadTemplate and expectedResult from attribute expression paths.
|
|
403
|
-
*
|
|
404
|
-
* @param {Object} parsed - Parsed datasource (mutated)
|
|
405
|
-
* @param {string[]} changes - Change log
|
|
406
|
-
* @returns {boolean} True if testPayload was added or updated
|
|
407
|
-
*/
|
|
408
|
-
function repairTestPayload(parsed, changes) {
|
|
409
|
-
const attrs = parsed?.fieldMappings?.attributes;
|
|
410
|
-
if (!attrs || typeof attrs !== 'object') return false;
|
|
411
|
-
const payloadTemplate = {};
|
|
412
|
-
const expectedResult = {};
|
|
413
|
-
for (const [key, config] of Object.entries(attrs)) {
|
|
414
|
-
const type = config?.type || 'string';
|
|
415
|
-
const placeholder = placeholderForType(type);
|
|
416
|
-
expectedResult[key] = placeholder;
|
|
417
|
-
const match = config?.expression?.match(/\{\{\s*([^}|]+)/);
|
|
418
|
-
if (match) {
|
|
419
|
-
let path = match[1].trim();
|
|
420
|
-
if (path.startsWith('raw.')) {
|
|
421
|
-
path = path.slice(4);
|
|
422
|
-
}
|
|
423
|
-
setNested(payloadTemplate, path.split('.'), placeholder);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
if (!parsed.testPayload) parsed.testPayload = {};
|
|
427
|
-
parsed.testPayload.payloadTemplate = payloadTemplate;
|
|
428
|
-
parsed.testPayload.expectedResult = expectedResult;
|
|
429
|
-
changes.push('Generated testPayload.payloadTemplate and testPayload.expectedResult from attributes');
|
|
430
|
-
return true;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
383
|
/**
|
|
434
384
|
* Runs all requested datasource repairs.
|
|
435
385
|
*
|
|
@@ -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.
|
|
@@ -136,7 +138,7 @@ function buildExpectedByKey(effective) {
|
|
|
136
138
|
* @param {Object} [systemParsed] - Parsed system config for template context (preferred)
|
|
137
139
|
* @returns {boolean}
|
|
138
140
|
*/
|
|
139
|
-
function createEnvTemplateIfMissing(envPath, expectedByKey, dryRun, changes, systemParsed) {
|
|
141
|
+
function createEnvTemplateIfMissing(envPath, expectedByKey, dryRun, changes, systemParsed, backupCtx) {
|
|
140
142
|
if (fs.existsSync(envPath)) return false;
|
|
141
143
|
if (expectedByKey.size === 0) return false;
|
|
142
144
|
const content = systemParsed
|
|
@@ -145,6 +147,7 @@ function createEnvTemplateIfMissing(envPath, expectedByKey, dryRun, changes, sys
|
|
|
145
147
|
if (!content || !content.trim()) return false;
|
|
146
148
|
const hasKeyValueLine = /^[A-Z_][A-Z0-9_]*=/m.test(content);
|
|
147
149
|
if (!hasKeyValueLine) return false;
|
|
150
|
+
trackRepairWrite(envPath, backupCtx);
|
|
148
151
|
if (!dryRun) {
|
|
149
152
|
fs.writeFileSync(envPath, content + (content.endsWith('\n') ? '' : '\n'), { mode: 0o644, encoding: 'utf8' });
|
|
150
153
|
}
|
|
@@ -229,6 +232,51 @@ function mergeEnvTemplateContent(content, expectedByKey) {
|
|
|
229
232
|
return { output, changed: changedRef.value };
|
|
230
233
|
}
|
|
231
234
|
|
|
235
|
+
/**
|
|
236
|
+
* Comments active KV_* lines whose env key is not in the system-derived expected set.
|
|
237
|
+
* @param {string} content
|
|
238
|
+
* @param {Map<string, string>} expectedByKey
|
|
239
|
+
* @param {{ value: boolean }} changedRef
|
|
240
|
+
* @returns {string}
|
|
241
|
+
*/
|
|
242
|
+
function commentOrphanKvLines(content, expectedByKey, changedRef) {
|
|
243
|
+
const { content: next, changed } = commentOrphanKvEnvLines(content, expectedByKey);
|
|
244
|
+
if (changed) {
|
|
245
|
+
changedRef.value = true;
|
|
246
|
+
}
|
|
247
|
+
return next;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* @param {string} envPath
|
|
252
|
+
* @param {string} output
|
|
253
|
+
* @param {boolean} dryRun
|
|
254
|
+
* @param {Object} [backupCtx]
|
|
255
|
+
*/
|
|
256
|
+
function persistEnvTemplate(envPath, output, dryRun, backupCtx) {
|
|
257
|
+
trackRepairWrite(envPath, backupCtx);
|
|
258
|
+
if (!dryRun) {
|
|
259
|
+
backupIntegrationFile(envPath, backupCtx);
|
|
260
|
+
fs.writeFileSync(envPath, output, { mode: 0o644, encoding: 'utf8' });
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* @param {string} content
|
|
266
|
+
* @param {Map<string, string>} expectedByKey
|
|
267
|
+
* @returns {{ output: string, mergeChanged: boolean, pruneChanged: boolean }}
|
|
268
|
+
*/
|
|
269
|
+
function mergeAndPruneEnvTemplate(content, expectedByKey) {
|
|
270
|
+
const mergeResult = mergeEnvTemplateContent(content, expectedByKey);
|
|
271
|
+
const pruneChanged = { value: false };
|
|
272
|
+
const output = commentOrphanKvLines(mergeResult.output, expectedByKey, pruneChanged);
|
|
273
|
+
return {
|
|
274
|
+
output,
|
|
275
|
+
mergeChanged: mergeResult.changed,
|
|
276
|
+
pruneChanged: pruneChanged.value
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
232
280
|
/**
|
|
233
281
|
* Repairs env.template so KV_ names and path-style kv:// values match the system file.
|
|
234
282
|
* @param {string} appPath - Application directory path
|
|
@@ -240,29 +288,32 @@ function mergeEnvTemplateContent(content, expectedByKey) {
|
|
|
240
288
|
* @returns {boolean} True if env.template was repaired or created
|
|
241
289
|
*/
|
|
242
290
|
function repairEnvTemplate(appPath, systemParsed, systemKey, dryRun, changes, backupCtx) {
|
|
243
|
-
const
|
|
244
|
-
const expectedByKey = buildExpectedByKey(effective);
|
|
291
|
+
const expectedByKey = buildExpectedByKey(buildEffectiveConfiguration(systemParsed, systemKey));
|
|
245
292
|
const envPath = path.join(appPath, 'env.template');
|
|
246
293
|
|
|
247
|
-
if (createEnvTemplateIfMissing(envPath, expectedByKey, dryRun, changes, systemParsed)) {
|
|
294
|
+
if (createEnvTemplateIfMissing(envPath, expectedByKey, dryRun, changes, systemParsed, backupCtx)) {
|
|
248
295
|
return true;
|
|
249
296
|
}
|
|
250
297
|
if (!fs.existsSync(envPath)) {
|
|
251
298
|
return false;
|
|
252
299
|
}
|
|
253
300
|
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
301
|
+
const { output, mergeChanged, pruneChanged } = mergeAndPruneEnvTemplate(
|
|
302
|
+
fs.readFileSync(envPath, 'utf8'),
|
|
303
|
+
expectedByKey
|
|
304
|
+
);
|
|
305
|
+
if (!mergeChanged && !pruneChanged) {
|
|
306
|
+
return false;
|
|
260
307
|
}
|
|
261
|
-
|
|
308
|
+
|
|
309
|
+
persistEnvTemplate(envPath, output, dryRun, backupCtx);
|
|
310
|
+
if (mergeChanged) {
|
|
262
311
|
changes.push('Repaired env.template (KV_* names and path-style kv:// values)');
|
|
263
|
-
return true;
|
|
264
312
|
}
|
|
265
|
-
|
|
313
|
+
if (pruneChanged) {
|
|
314
|
+
changes.push('Commented stale env.template KV_* lines (not in system authentication)');
|
|
315
|
+
}
|
|
316
|
+
return true;
|
|
266
317
|
}
|
|
267
318
|
|
|
268
319
|
/**
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External integration repair orchestration (local file updates, manifest, README).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Repair external integration run pipeline
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const { normalizeDatasourceKeysAndFilenames } = require('./repair-datasource-keys');
|
|
12
|
+
const { resolveSystemContext } = require('./repair-system-alignment');
|
|
13
|
+
const { persistChangesAndRegenerate, regenerateReadmeIfRequested } = require('./repair-persist');
|
|
14
|
+
const { runRepairSteps } = require('./repair-steps');
|
|
15
|
+
const { runDatasourceRepairs } = require('./repair-datasource-run');
|
|
16
|
+
const { maybeRepairRbac } = require('./repair-rbac');
|
|
17
|
+
const { maybeRunOpenApiSyncForMcp } = require('./repair-openapi-sync');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {Object} steps
|
|
21
|
+
* @param {boolean} anyUpdated
|
|
22
|
+
* @param {boolean} manifestRegenerated
|
|
23
|
+
* @param {boolean} readmeRegenerated
|
|
24
|
+
* @param {Object} ctx
|
|
25
|
+
* @returns {Object}
|
|
26
|
+
*/
|
|
27
|
+
function buildRepairResult(steps, anyUpdated, manifestRegenerated, readmeRegenerated, ctx) {
|
|
28
|
+
return Object.assign(
|
|
29
|
+
{
|
|
30
|
+
updated: anyUpdated,
|
|
31
|
+
actionsPerformed: ctx.actionsPerformed === true,
|
|
32
|
+
changes: ctx.changes,
|
|
33
|
+
warnings: ctx.warnings || [],
|
|
34
|
+
changedFiles: ctx.changedFiles || [],
|
|
35
|
+
systemFiles: ctx.systemFiles,
|
|
36
|
+
datasourceFiles: ctx.datasourceFiles,
|
|
37
|
+
backupPaths: ctx.backupPaths || []
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
appKeyFixed: steps.appKeyFixed,
|
|
41
|
+
datasourceKeysFixed: steps.datasourceKeysFixed,
|
|
42
|
+
rbacFileCreated: steps.rbacFileCreated,
|
|
43
|
+
envTemplateRepaired: steps.envTemplateRepaired,
|
|
44
|
+
manifestRegenerated,
|
|
45
|
+
readmeRegenerated
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @param {Object} params
|
|
52
|
+
* @returns {Object}
|
|
53
|
+
*/
|
|
54
|
+
function prepareRepairWorkspace(params) {
|
|
55
|
+
const {
|
|
56
|
+
options,
|
|
57
|
+
appPath,
|
|
58
|
+
configPath,
|
|
59
|
+
dryRun,
|
|
60
|
+
authOption,
|
|
61
|
+
backupCtx,
|
|
62
|
+
variables,
|
|
63
|
+
systemFiles,
|
|
64
|
+
datasourceFiles: initialDatasourceFiles
|
|
65
|
+
} = params;
|
|
66
|
+
const changes = [];
|
|
67
|
+
const warnings = [];
|
|
68
|
+
const { systemFilePath, systemParsed, systemKey } = resolveSystemContext(appPath, systemFiles);
|
|
69
|
+
const rbacFmt = options.format === 'json' ? 'json' : 'yaml';
|
|
70
|
+
const { updated: keysNormalized, datasourceFiles } = normalizeDatasourceKeysAndFilenames(
|
|
71
|
+
appPath,
|
|
72
|
+
initialDatasourceFiles,
|
|
73
|
+
systemKey,
|
|
74
|
+
{ variables, dryRun, changes, backupCtx }
|
|
75
|
+
);
|
|
76
|
+
return {
|
|
77
|
+
options,
|
|
78
|
+
appPath,
|
|
79
|
+
configPath,
|
|
80
|
+
dryRun,
|
|
81
|
+
authOption,
|
|
82
|
+
backupCtx,
|
|
83
|
+
variables,
|
|
84
|
+
systemFiles,
|
|
85
|
+
changes,
|
|
86
|
+
warnings,
|
|
87
|
+
systemFilePath,
|
|
88
|
+
systemParsed,
|
|
89
|
+
systemKey,
|
|
90
|
+
rbacFmt,
|
|
91
|
+
keysNormalized,
|
|
92
|
+
datasourceFiles
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @param {Object} ws
|
|
98
|
+
* @returns {Promise<Object>}
|
|
99
|
+
*/
|
|
100
|
+
async function runRepairIntegrationFileSteps(ws) {
|
|
101
|
+
const steps = runRepairSteps({
|
|
102
|
+
appPath: ws.appPath,
|
|
103
|
+
configPath: ws.configPath,
|
|
104
|
+
variables: ws.variables,
|
|
105
|
+
systemFilePath: ws.systemFilePath,
|
|
106
|
+
systemParsed: ws.systemParsed,
|
|
107
|
+
systemKey: ws.systemKey,
|
|
108
|
+
systemFiles: ws.systemFiles,
|
|
109
|
+
datasourceFiles: ws.datasourceFiles,
|
|
110
|
+
dryRun: ws.dryRun,
|
|
111
|
+
changes: ws.changes,
|
|
112
|
+
warnings: ws.warnings,
|
|
113
|
+
auth: ws.authOption,
|
|
114
|
+
format: ws.rbacFmt,
|
|
115
|
+
backupCtx: ws.backupCtx
|
|
116
|
+
});
|
|
117
|
+
const datasourceRepairUpdated = runDatasourceRepairs(
|
|
118
|
+
ws.appPath,
|
|
119
|
+
ws.datasourceFiles,
|
|
120
|
+
{
|
|
121
|
+
expose: Boolean(ws.options.expose),
|
|
122
|
+
sync: Boolean(ws.options.sync),
|
|
123
|
+
test: Boolean(ws.options.test),
|
|
124
|
+
backupCtx: ws.backupCtx
|
|
125
|
+
},
|
|
126
|
+
ws.dryRun,
|
|
127
|
+
ws.changes
|
|
128
|
+
);
|
|
129
|
+
const openapiActionsPerformed = await maybeRunOpenApiSyncForMcp({
|
|
130
|
+
options: ws.options,
|
|
131
|
+
dryRun: ws.dryRun,
|
|
132
|
+
appPath: ws.appPath,
|
|
133
|
+
systemKey: ws.systemKey,
|
|
134
|
+
datasourceFiles: ws.datasourceFiles,
|
|
135
|
+
changes: ws.changes
|
|
136
|
+
});
|
|
137
|
+
const { rbacMigratedFromSystem, rbacMergeUpdated } = maybeRepairRbac(
|
|
138
|
+
ws.appPath,
|
|
139
|
+
ws.systemFilePath,
|
|
140
|
+
ws.systemParsed,
|
|
141
|
+
ws.datasourceFiles,
|
|
142
|
+
{ rbac: Boolean(ws.options.rbac), rbacFmt: ws.rbacFmt, dryRun: ws.dryRun, changes: ws.changes, backupCtx: ws.backupCtx }
|
|
143
|
+
);
|
|
144
|
+
const anyLocalUpdated =
|
|
145
|
+
ws.keysNormalized || steps.updated || datasourceRepairUpdated || rbacMigratedFromSystem || rbacMergeUpdated;
|
|
146
|
+
return {
|
|
147
|
+
steps,
|
|
148
|
+
anyLocalUpdated,
|
|
149
|
+
changes: ws.changes,
|
|
150
|
+
warnings: ws.warnings,
|
|
151
|
+
openapiActionsPerformed,
|
|
152
|
+
systemFiles: ws.systemFiles,
|
|
153
|
+
datasourceFiles: ws.datasourceFiles
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* @param {Object} params
|
|
159
|
+
* @returns {Promise<Object>}
|
|
160
|
+
*/
|
|
161
|
+
async function runRepairLocalUpdates(params) {
|
|
162
|
+
const ws = prepareRepairWorkspace(params);
|
|
163
|
+
return runRepairIntegrationFileSteps(ws);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* @param {Object} params
|
|
168
|
+
* @param {Object} local
|
|
169
|
+
* @returns {Promise<Object>}
|
|
170
|
+
*/
|
|
171
|
+
async function finalizeRepairIntegration(params, local) {
|
|
172
|
+
const { appName, options, appPath, configPath, dryRun, backupPaths, backupCtx, variables, originalYamlContent } =
|
|
173
|
+
params;
|
|
174
|
+
const { steps, anyLocalUpdated, changes, warnings, openapiActionsPerformed, systemFiles, datasourceFiles } = local;
|
|
175
|
+
let manifestRegenerated = false;
|
|
176
|
+
if (anyLocalUpdated && !dryRun) {
|
|
177
|
+
manifestRegenerated = await persistChangesAndRegenerate({
|
|
178
|
+
configPath,
|
|
179
|
+
variables,
|
|
180
|
+
appName,
|
|
181
|
+
appPath,
|
|
182
|
+
changes,
|
|
183
|
+
originalYamlContent,
|
|
184
|
+
backupCtx
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
const readmeRegenerated = await regenerateReadmeIfRequested(
|
|
188
|
+
appName,
|
|
189
|
+
appPath,
|
|
190
|
+
{ ...options, backupCtx },
|
|
191
|
+
changes
|
|
192
|
+
);
|
|
193
|
+
const changedFiles = dryRun ? backupCtx.wouldChangeFiles : backupCtx.changedFiles;
|
|
194
|
+
return buildRepairResult(steps, anyLocalUpdated, manifestRegenerated, readmeRegenerated, {
|
|
195
|
+
actionsPerformed: openapiActionsPerformed,
|
|
196
|
+
changes,
|
|
197
|
+
warnings,
|
|
198
|
+
changedFiles,
|
|
199
|
+
systemFiles,
|
|
200
|
+
datasourceFiles,
|
|
201
|
+
backupPaths
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* @param {Object} params
|
|
207
|
+
* @returns {Promise<Object>}
|
|
208
|
+
*/
|
|
209
|
+
async function runRepairExternalIntegration(params) {
|
|
210
|
+
const local = await runRepairLocalUpdates(params);
|
|
211
|
+
return finalizeRepairIntegration(params, local);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
module.exports = {
|
|
215
|
+
runRepairExternalIntegration
|
|
216
|
+
};
|
|
@@ -164,9 +164,32 @@ async function maybeSyncOpenApiFilesForMcp(opts) {
|
|
|
164
164
|
return lines;
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
+
/**
|
|
168
|
+
* @param {Object} args
|
|
169
|
+
* @returns {Promise<boolean>}
|
|
170
|
+
*/
|
|
171
|
+
async function maybeRunOpenApiSyncForMcp({ options, dryRun, appPath, systemKey, datasourceFiles, changes }) {
|
|
172
|
+
if (!options.api) return false;
|
|
173
|
+
try {
|
|
174
|
+
const openapiLines = await maybeSyncOpenApiFilesForMcp({
|
|
175
|
+
enabled: true,
|
|
176
|
+
dryRun,
|
|
177
|
+
appPath,
|
|
178
|
+
systemKey,
|
|
179
|
+
datasourceFiles
|
|
180
|
+
});
|
|
181
|
+
openapiLines.forEach((l) => changes.push(l));
|
|
182
|
+
return openapiLines.length > 0;
|
|
183
|
+
} catch (err) {
|
|
184
|
+
changes.push(`OpenAPI upload for MCP failed: ${err.message}`);
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
167
189
|
module.exports = {
|
|
168
190
|
documentKeyToLocalOpenApiPath,
|
|
169
191
|
maybeSyncOpenApiFilesForMcp,
|
|
192
|
+
maybeRunOpenApiSyncForMcp,
|
|
170
193
|
syncOpenApiFilesForMcp
|
|
171
194
|
};
|
|
172
195
|
|