@aifabrix/builder 2.43.0 → 2.44.1
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/anchor-docs.mdc +15 -0
- package/.cursor/rules/cli-layout.mdc +75 -0
- package/.cursor/rules/project-rules.mdc +8 -0
- package/.npmrc.token +1 -0
- package/.nyc_output/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
- package/.nyc_output/processinfo/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
- package/.nyc_output/processinfo/index.json +1 -0
- package/README.md +1 -1
- package/anchor-docs/README.md +10 -0
- package/anchor-docs/_TEMPLATE +24 -0
- package/bin/aifabrix.js +13 -4
- package/integration/hubspot-test/README.md +31 -0
- package/integration/hubspot-test/create-hubspot.js +5 -5
- package/integration/hubspot-test/hubspot-test-datasource-company.json +58 -462
- package/integration/hubspot-test/hubspot-test-datasource-contact.json +61 -555
- package/integration/hubspot-test/hubspot-test-datasource-deal.json +63 -506
- package/integration/hubspot-test/hubspot-test-datasource-users.json +42 -83
- package/integration/hubspot-test/hubspot-test-deploy.json +3 -3
- package/integration/hubspot-test/test-dataplane-down-tests.js +1 -7
- package/integration/hubspot-test/test-dataplane-down.js +3 -3
- package/integration/hubspot-test/test.js +35 -43
- package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
- package/integration/roundtrip-test-local/README.md +144 -0
- package/integration/roundtrip-test-local/application.yaml +13 -0
- package/integration/roundtrip-test-local/env.template +15 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
- package/integration/roundtrip-test-local2/README.md +144 -0
- package/integration/roundtrip-test-local2/application.yaml +13 -0
- package/integration/roundtrip-test-local2/env.template +15 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
- package/integration/test/wizard.yaml +8 -0
- package/jest.config.default.js +10 -0
- package/jest.config.integration.fixtures.js +22 -0
- package/jest.config.integration.js +21 -18
- package/jest.config.isolated.js +10 -0
- package/jest.projects.js +301 -0
- package/lib/api/certificates.api.js +62 -0
- package/lib/api/datasources-core.api.js +3 -3
- package/lib/api/dev-mtls-request.js +110 -0
- package/lib/api/dev-server-https.js +145 -0
- package/lib/api/dev.api.js +133 -144
- package/lib/api/index.js +11 -3
- package/lib/api/pipeline.api.js +67 -20
- package/lib/api/types/certificates.types.js +48 -0
- package/lib/api/types/dev.types.js +4 -3
- package/lib/api/types/pipeline.types.js +8 -5
- package/lib/api/types/validation-run.types.js +56 -0
- package/lib/api/validation-run.api.js +111 -0
- package/lib/api/validation-runner.js +109 -0
- package/lib/app/certification-show-enrich.js +129 -0
- package/lib/app/certification-verify-rows.js +60 -0
- package/lib/app/config.js +1 -1
- package/lib/app/deploy-status-display.js +2 -2
- package/lib/app/deploy.js +7 -6
- package/lib/app/display.js +2 -1
- package/lib/app/dockerfile.js +3 -2
- package/lib/app/down.js +2 -1
- package/lib/app/helpers.js +6 -5
- package/lib/app/index.js +27 -8
- package/lib/app/list.js +7 -6
- package/lib/app/push.js +4 -3
- package/lib/app/register.js +16 -7
- package/lib/app/rotate-secret.js +14 -13
- package/lib/app/run-container-start.js +184 -0
- package/lib/app/run-docker-fallback.js +108 -0
- package/lib/app/run-env-compose.js +30 -42
- package/lib/app/run-helpers.js +49 -126
- package/lib/app/run-infra-requirements.js +30 -0
- package/lib/app/run-resolve-image.js +21 -0
- package/lib/app/run.js +74 -21
- package/lib/app/show-display.js +44 -1
- package/lib/app/show.js +93 -9
- package/lib/build/index.js +13 -10
- package/lib/certification/cli-cert-sync-skip.js +21 -0
- package/lib/certification/merge-certification-from-artifact.js +185 -0
- package/lib/certification/post-unified-cert-sync.js +33 -0
- package/lib/certification/sync-after-external-command.js +52 -0
- package/lib/certification/sync-system-certification.js +197 -0
- package/lib/cli/index.js +2 -0
- package/lib/cli/setup-app.help.js +67 -0
- package/lib/cli/setup-app.js +61 -121
- package/lib/cli/setup-app.test-commands.js +195 -0
- package/lib/cli/setup-auth.js +19 -5
- package/lib/cli/setup-credential-deployment.js +22 -8
- package/lib/cli/setup-dev-path-commands.js +124 -0
- package/lib/cli/setup-dev.js +170 -113
- package/lib/cli/setup-environment.js +7 -1
- package/lib/cli/setup-external-system.js +84 -23
- package/lib/cli/setup-infra.js +126 -47
- package/lib/cli/setup-parameters.js +32 -0
- package/lib/cli/setup-secrets.js +137 -18
- package/lib/cli/setup-service-user.js +1 -1
- package/lib/cli/setup-utility.js +54 -22
- package/lib/commands/app-down.js +5 -7
- package/lib/commands/app-install.js +14 -7
- package/lib/commands/app-logs.js +13 -10
- package/lib/commands/app-shell.js +4 -1
- package/lib/commands/app-test.js +25 -19
- package/lib/commands/app.js +32 -11
- package/lib/commands/auth-config.js +6 -6
- package/lib/commands/auth-status.js +4 -3
- package/lib/commands/credential-env.js +4 -3
- package/lib/commands/credential-list.js +5 -4
- package/lib/commands/credential-push.js +4 -3
- package/lib/commands/datasource-unified-test-cli.js +428 -0
- package/lib/commands/datasource-unified-test-cli.options.js +191 -0
- package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +106 -0
- package/lib/commands/datasource-validation-cli.js +143 -0
- package/lib/commands/datasource.js +125 -95
- package/lib/commands/deployment-list.js +6 -5
- package/lib/commands/dev-cli-handlers.js +122 -18
- package/lib/commands/dev-down.js +4 -3
- package/lib/commands/dev-init.js +231 -116
- package/lib/commands/dev-show-display.js +473 -0
- package/lib/commands/login-credentials.js +3 -2
- package/lib/commands/login-device.js +4 -3
- package/lib/commands/login.js +5 -4
- package/lib/commands/logout.js +8 -7
- package/lib/commands/parameters-validate.js +54 -0
- package/lib/commands/repair-datasource.js +314 -68
- package/lib/commands/repair-env-template.js +2 -2
- package/lib/commands/repair.js +21 -3
- package/lib/commands/secrets-list.js +23 -12
- package/lib/commands/secrets-remove-all.js +220 -0
- package/lib/commands/secrets-remove.js +21 -12
- package/lib/commands/secrets-set.js +21 -12
- package/lib/commands/secrets-validate.js +4 -4
- package/lib/commands/secure.js +10 -9
- package/lib/commands/service-user.js +26 -25
- package/lib/commands/test-e2e-external.js +27 -1
- package/lib/commands/up-common.js +3 -2
- package/lib/commands/up-dataplane.js +29 -16
- package/lib/commands/up-miso.js +19 -29
- package/lib/commands/upload.js +149 -39
- package/lib/commands/wizard-core-helpers.js +1 -1
- package/lib/commands/wizard-dataplane.js +4 -3
- package/lib/commands/wizard-helpers.js +3 -3
- package/lib/commands/wizard.js +2 -2
- package/lib/core/admin-secrets.js +14 -5
- package/lib/core/audit-logger.js +12 -4
- package/lib/core/config-attach-extensions.js +46 -0
- package/lib/core/config-runtime-paths.js +29 -0
- package/lib/core/config.js +55 -56
- package/lib/core/diff.js +3 -2
- package/lib/core/ensure-encryption-key.js +1 -1
- package/lib/core/secrets-ensure-infra.js +77 -0
- package/lib/core/secrets-ensure.js +120 -64
- package/lib/core/secrets-env-write.js +35 -7
- package/lib/core/secrets-infra-placeholder-sync.js +61 -0
- package/lib/core/secrets.js +200 -37
- package/lib/core/templates-env.js +4 -3
- package/lib/datasource/abac-validator.js +1 -10
- package/lib/datasource/deploy.js +75 -53
- package/lib/datasource/field-reference-validator.js +9 -6
- package/lib/datasource/integration-context.js +63 -0
- package/lib/datasource/list.js +8 -7
- package/lib/datasource/log-viewer.js +189 -67
- package/lib/datasource/resolve-app.js +4 -4
- package/lib/datasource/test-e2e.js +113 -146
- package/lib/datasource/test-integration.js +114 -122
- package/lib/datasource/unified-validation-run-body.js +68 -0
- package/lib/datasource/unified-validation-run-post.js +23 -0
- package/lib/datasource/unified-validation-run-resolve.js +43 -0
- package/lib/datasource/unified-validation-run.js +93 -0
- package/lib/datasource/validate.js +157 -13
- package/lib/deployment/deployer.js +4 -3
- package/lib/deployment/environment.js +7 -6
- package/lib/deployment/push.js +17 -8
- package/lib/external-system/delete.js +4 -3
- package/lib/external-system/deploy.js +166 -53
- package/lib/external-system/download-helpers.js +1 -1
- package/lib/external-system/download.js +7 -6
- package/lib/external-system/generator.js +92 -6
- package/lib/external-system/integration-test-dispatch.js +26 -0
- package/lib/external-system/test-execution.js +5 -1
- package/lib/external-system/test-helpers.js +0 -4
- package/lib/external-system/test-system-level-helpers.js +110 -0
- package/lib/external-system/test-system-level.js +83 -44
- package/lib/external-system/test.js +59 -8
- package/lib/generator/builders.js +23 -11
- package/lib/generator/deploy-manifest-azure-kv.js +81 -0
- package/lib/generator/external.js +16 -4
- package/lib/generator/helpers.js +58 -3
- package/lib/generator/index.js +4 -0
- package/lib/generator/split-readme.js +12 -7
- package/lib/generator/split-variables.js +2 -1
- package/lib/generator/split.js +1 -1
- package/lib/generator/wizard-readme.js +3 -3
- package/lib/generator/wizard.js +8 -8
- package/lib/infrastructure/compose.js +70 -7
- package/lib/infrastructure/helpers-docker-check.js +67 -0
- package/lib/infrastructure/helpers.js +203 -42
- package/lib/infrastructure/index.js +31 -18
- package/lib/infrastructure/services.js +21 -67
- package/lib/internal/fs-real-sync.js +104 -0
- package/lib/internal/node-fs.js +98 -0
- package/lib/parameters/database-secret-values.js +173 -0
- package/lib/parameters/infra-kv-discovery.js +121 -0
- package/lib/parameters/infra-parameter-catalog.js +458 -0
- package/lib/parameters/infra-parameter-validate.js +64 -0
- package/lib/schema/application-schema.json +37 -17
- package/lib/schema/datasource-test-run.schema.json +493 -0
- package/lib/schema/deployment-rules.yaml +102 -63
- package/lib/schema/external-datasource.schema.json +1200 -442
- package/lib/schema/external-system.schema.json +203 -5
- package/lib/schema/flag-map-validation-run.json +31 -0
- package/lib/schema/infra-parameter.schema.json +106 -0
- package/lib/schema/infra.parameter.yaml +421 -0
- package/lib/schema/type/credential-auth-templates.json +40 -0
- package/lib/schema/type/document-storage.json +226 -0
- package/lib/schema/type/message-service.json +123 -0
- package/lib/schema/type/vector-store.json +88 -0
- package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
- package/lib/utils/api-error-handler.js +2 -2
- package/lib/utils/api.js +77 -17
- package/lib/utils/app-register-api.js +3 -2
- package/lib/utils/app-register-auth.js +1 -1
- package/lib/utils/app-register-config.js +4 -4
- package/lib/utils/app-register-display.js +3 -2
- package/lib/utils/app-register-validator.js +3 -2
- package/lib/utils/app-run-containers.js +26 -22
- package/lib/utils/app-scoped-config.js +31 -0
- package/lib/utils/app-service-env-from-builder.js +164 -0
- package/lib/utils/build-copy.js +1 -1
- package/lib/utils/build-helpers.js +20 -20
- package/lib/utils/build-resolve-image.js +165 -0
- package/lib/utils/cli-layout-chalk.js +8 -0
- package/lib/utils/cli-test-layout-chalk.js +267 -0
- package/lib/utils/cli-utils.js +88 -11
- package/lib/utils/compose-db-passwords.js +138 -0
- package/lib/utils/compose-generate-docker-compose.js +216 -0
- package/lib/utils/compose-generator.js +197 -291
- package/lib/utils/compose-miso-env.js +18 -0
- package/lib/utils/compose-traefik-ingress-base.js +158 -0
- package/lib/utils/config-paths.js +166 -7
- package/lib/utils/config-scoped-resources-preference.js +41 -0
- package/lib/utils/configuration-env-resolver.js +11 -8
- package/lib/utils/controller-deployment-outcome.js +68 -0
- package/lib/utils/credential-display.js +2 -2
- package/lib/utils/credential-secrets-env.js +5 -5
- package/lib/utils/dataplane-pipeline-warning.js +4 -3
- package/lib/utils/datasource-test-run-capability-scope.js +43 -0
- package/lib/utils/datasource-test-run-certificate-tty.js +82 -0
- package/lib/utils/datasource-test-run-debug-display.js +137 -0
- package/lib/utils/datasource-test-run-debug-slice.js +93 -0
- package/lib/utils/datasource-test-run-display.js +459 -0
- package/lib/utils/datasource-test-run-exit.js +83 -0
- package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
- package/lib/utils/datasource-test-run-report-version.js +51 -0
- package/lib/utils/datasource-test-run-schema-sync.js +59 -0
- package/lib/utils/datasource-test-run-tty-log.js +81 -0
- package/lib/utils/datasource-validation-watch.js +266 -0
- package/lib/utils/declarative-url-ports.js +47 -0
- package/lib/utils/derive-env-key-from-client-id.js +41 -0
- package/lib/utils/dev-ca-install.js +185 -23
- package/lib/utils/dev-cert-helper.js +266 -17
- package/lib/utils/dev-hosts-helper.js +307 -0
- package/lib/utils/dev-init-cert-hints.js +37 -0
- package/lib/utils/dev-init-health-messages.js +52 -0
- package/lib/utils/dev-init-resolve.js +86 -0
- package/lib/utils/dev-init-ssh-merge.js +65 -0
- package/lib/utils/dev-ssh-config-helper.js +196 -0
- package/lib/utils/dev-user-groups.js +93 -0
- package/lib/utils/docker-build.js +42 -17
- package/lib/utils/docker-exec.js +28 -0
- package/lib/utils/docker-manifest-public-port.js +116 -0
- package/lib/utils/docker-not-running-hint.js +52 -0
- package/lib/utils/docker.js +98 -11
- package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
- package/lib/utils/env-config-loader.js +10 -91
- package/lib/utils/env-copy.js +19 -10
- package/lib/utils/env-map.js +35 -8
- package/lib/utils/env-template.js +2 -2
- package/lib/utils/environment-scoped-resources.js +144 -0
- package/lib/utils/error-formatter.js +92 -13
- package/lib/utils/error-formatters/http-status-errors.js +6 -5
- package/lib/utils/error-formatters/network-errors.js +2 -1
- package/lib/utils/error-formatters/permission-errors.js +2 -1
- package/lib/utils/error-formatters/validation-errors.js +2 -1
- package/lib/utils/external-readme.js +8 -1
- package/lib/utils/external-system-display.js +242 -136
- package/lib/utils/external-system-local-test-tty.js +389 -0
- package/lib/utils/external-system-readiness-core.js +377 -0
- package/lib/utils/external-system-readiness-deploy-display.js +270 -0
- package/lib/utils/external-system-readiness-display-internals.js +150 -0
- package/lib/utils/external-system-readiness-display.js +186 -0
- package/lib/utils/external-system-system-test-tty-overview.js +120 -0
- package/lib/utils/external-system-system-test-tty.js +417 -0
- package/lib/utils/external-system-test-helpers.js +24 -6
- package/lib/utils/external-system-validators.js +30 -12
- package/lib/utils/health-check-url.js +119 -0
- package/lib/utils/health-check.js +59 -25
- package/lib/utils/help-builder.js +11 -8
- package/lib/utils/image-version.js +4 -8
- package/lib/utils/infra-containers.js +4 -7
- package/lib/utils/infra-env-defaults.js +162 -0
- package/lib/utils/infra-status-display.js +167 -0
- package/lib/utils/infra-status.js +16 -8
- package/lib/utils/local-secrets.js +3 -4
- package/lib/utils/paths.js +148 -47
- package/lib/utils/port-resolver.js +10 -23
- package/lib/utils/redis-env-scope.js +62 -0
- package/lib/utils/register-aifabrix-shell-env.js +204 -0
- package/lib/utils/remote-builder-validation.js +99 -0
- package/lib/utils/remote-dev-auth.js +117 -21
- package/lib/utils/remote-docker-env.js +67 -15
- package/lib/utils/remote-secrets-loader.js +13 -4
- package/lib/utils/resolve-docker-image-ref.js +124 -0
- package/lib/utils/schema-loader.js +22 -9
- package/lib/utils/secrets-bash-kv.js +25 -0
- package/lib/utils/secrets-generator.js +169 -49
- package/lib/utils/secrets-helpers.js +70 -59
- package/lib/utils/secrets-kv-scope.js +60 -0
- package/lib/utils/secrets-utils.js +32 -38
- package/lib/utils/secrets-validation.js +3 -1
- package/lib/utils/secrets-yaml-preserve.js +109 -0
- package/lib/utils/ssh-key-helper.js +4 -2
- package/lib/utils/template-helpers.js +2 -2
- package/lib/utils/test-log-writer.js +3 -3
- package/lib/utils/token-manager.js +1 -2
- package/lib/utils/url-declarative-public-base.js +188 -0
- package/lib/utils/url-declarative-resolve-build.js +493 -0
- package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
- package/lib/utils/url-declarative-resolve.js +220 -0
- package/lib/utils/url-declarative-token-parse.js +74 -0
- package/lib/utils/url-declarative-url-flags.js +50 -0
- package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
- package/lib/utils/url-public-path-prefix.js +34 -0
- package/lib/utils/urls-local-registry.js +220 -0
- package/lib/utils/validation-report-tty-kit.js +77 -0
- package/lib/utils/validation-run-poll.js +112 -0
- package/lib/utils/validation-run-post-retry.js +85 -0
- package/lib/utils/validation-run-request.js +116 -0
- package/lib/utils/variable-transformer.js +21 -4
- package/lib/utils/yaml-preserve.js +33 -14
- package/lib/validation/datasource-warnings.js +56 -0
- package/lib/validation/env-template-auth.js +1 -1
- package/lib/validation/external-manifest-validator.js +27 -7
- package/lib/validation/validate-display.js +37 -31
- package/lib/validation/validate-external-cert-sync.js +23 -0
- package/lib/validation/validate.js +8 -14
- package/lib/validation/validator-unresolved-placeholders.js +98 -0
- package/lib/validation/validator.js +22 -65
- package/lib/validation/wizard-config-validator.js +2 -1
- package/package.json +9 -4
- package/scripts/check-datasource-test-run-schema-sync.js +34 -0
- package/scripts/diagnose-cli.js +150 -0
- package/scripts/install-local.js +307 -55
- package/scripts/pnpm-global-remove.js +48 -0
- package/templates/README.md +15 -2
- package/templates/applications/dataplane/application.yaml +52 -2
- package/templates/applications/dataplane/env.template +79 -17
- package/templates/applications/dataplane/rbac.yaml +8 -0
- package/templates/applications/keycloak/application.yaml +9 -1
- package/templates/applications/keycloak/env.template +15 -6
- package/templates/applications/miso-controller/application.yaml +10 -2
- package/templates/applications/miso-controller/env.template +42 -12
- package/templates/applications/miso-controller/rbac.yaml +5 -0
- package/templates/external-system/README.md.hbs +20 -7
- package/templates/external-system/deploy.js.hbs +5 -5
- package/templates/external-system/external-datasource.yaml.hbs +197 -118
- package/templates/infra/compose.yaml.hbs +33 -16
- package/templates/infra/servers.json.hbs +3 -1
- package/templates/python/docker-compose.hbs +16 -0
- package/templates/typescript/docker-compose.hbs +16 -0
- package/lib/api/external-test.api.js +0 -111
- package/lib/schema/env-config.yaml +0 -60
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Datasource repair helpers: align dimensions, metadataSchema, exposed, sync, testPayload
|
|
3
|
-
* with fieldMappings.attributes as source of truth.
|
|
3
|
+
* with fieldMappings.attributes as source of truth (external-datasource schema v2.4+).
|
|
4
4
|
*
|
|
5
5
|
* @fileoverview Repair datasource files for external integration
|
|
6
6
|
* @author AI Fabrix Team
|
|
7
|
-
* @version 2.
|
|
7
|
+
* @version 2.2.0
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
11
11
|
|
|
12
12
|
const DEFAULT_SYNC = {
|
|
13
13
|
mode: 'pull',
|
|
14
|
-
batchSize: 500
|
|
15
|
-
maxParallelRequests: 5
|
|
14
|
+
batchSize: 500
|
|
16
15
|
};
|
|
17
16
|
|
|
18
17
|
const MINIMAL_METADATA_SCHEMA = {
|
|
@@ -20,6 +19,61 @@ const MINIMAL_METADATA_SCHEMA = {
|
|
|
20
19
|
additionalProperties: true
|
|
21
20
|
};
|
|
22
21
|
|
|
22
|
+
/** Plan 346 / v2.4.1 closed root for testPayload */
|
|
23
|
+
const TEST_PAYLOAD_TOP_LEVEL_ALLOW = new Set([
|
|
24
|
+
'mode',
|
|
25
|
+
'primaryKey',
|
|
26
|
+
'scenarios',
|
|
27
|
+
'fk',
|
|
28
|
+
'actors',
|
|
29
|
+
'payloadTemplate',
|
|
30
|
+
'expectedResult'
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param {string|undefined} entityType - entityType from datasource
|
|
35
|
+
* @returns {boolean}
|
|
36
|
+
*/
|
|
37
|
+
function isNoneEntityType(entityType) {
|
|
38
|
+
return entityType === 'none';
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {string|undefined} entityType - entityType from datasource
|
|
43
|
+
* @returns {boolean}
|
|
44
|
+
*/
|
|
45
|
+
function isStorageEntityType(entityType) {
|
|
46
|
+
return entityType === 'recordStorage' || entityType === 'documentStorage';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Ensures metadataSchema.properties.externalId for recordStorage/documentStorage (schema v2.4).
|
|
51
|
+
* @param {Object} parsed - Parsed datasource (mutated)
|
|
52
|
+
* @param {string[]} changes - Change log
|
|
53
|
+
* @returns {boolean} True if externalId was added or corrected
|
|
54
|
+
*/
|
|
55
|
+
function ensureStorageExternalIdMetadataProperty(parsed, changes) {
|
|
56
|
+
if (!isStorageEntityType(parsed?.entityType)) return false;
|
|
57
|
+
if (!parsed.metadataSchema || typeof parsed.metadataSchema !== 'object') return false;
|
|
58
|
+
if (!parsed.metadataSchema.properties || typeof parsed.metadataSchema.properties !== 'object') {
|
|
59
|
+
parsed.metadataSchema.properties = {};
|
|
60
|
+
}
|
|
61
|
+
const props = parsed.metadataSchema.properties;
|
|
62
|
+
const ext = props.externalId;
|
|
63
|
+
const ok = ext
|
|
64
|
+
&& typeof ext === 'object'
|
|
65
|
+
&& ext.type === 'string'
|
|
66
|
+
&& ext.index === true;
|
|
67
|
+
if (ok) return false;
|
|
68
|
+
props.externalId = {
|
|
69
|
+
...(typeof ext === 'object' && ext !== null ? ext : {}),
|
|
70
|
+
type: 'string',
|
|
71
|
+
index: true
|
|
72
|
+
};
|
|
73
|
+
changes.push('Ensured metadataSchema.properties.externalId (type string, index true) for storage entityType');
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
|
|
23
77
|
/**
|
|
24
78
|
* Returns the set of attribute keys from fieldMappings.attributes.
|
|
25
79
|
* @param {Object} parsed - Parsed datasource object
|
|
@@ -32,12 +86,24 @@ function getAttributeKeys(parsed) {
|
|
|
32
86
|
}
|
|
33
87
|
|
|
34
88
|
/**
|
|
35
|
-
*
|
|
89
|
+
* @param {string} path - Normalized path (raw. prefix already stripped)
|
|
90
|
+
* @param {string[]} paths
|
|
91
|
+
* @param {Set<string>} topLevelKeys
|
|
92
|
+
* @param {Set<string>} referencedSchemaPropertyNames
|
|
93
|
+
*/
|
|
94
|
+
function accumulatePathSegments(path, paths, topLevelKeys, referencedSchemaPropertyNames) {
|
|
95
|
+
paths.push(path);
|
|
96
|
+
const segments = path.split('.');
|
|
97
|
+
const first = segments[0];
|
|
98
|
+
if (first) topLevelKeys.add(first);
|
|
99
|
+
if (first === 'metadata' && segments.length >= 2 && segments[1]) {
|
|
100
|
+
referencedSchemaPropertyNames.add(segments[1]);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Extracts paths from attribute expressions (e.g. {{ metadata.email }}, {{ raw.id }}).
|
|
36
106
|
* Skips record_ref: expressions.
|
|
37
|
-
* - topLevelKeys: first segment of each path (e.g. "metadata" from "metadata.id").
|
|
38
|
-
* - referencedSchemaPropertyNames: for paths like "metadata.xxx" or "metadata.xxx.yyy", the name "xxx"
|
|
39
|
-
* (the first property under metadata). Used to prune metadataSchema.properties so we only keep
|
|
40
|
-
* properties that are referenced; we do not compare against "metadata" or the schema would be wiped.
|
|
41
107
|
*
|
|
42
108
|
* @param {Object} attributes - fieldMappings.attributes object
|
|
43
109
|
* @returns {{ paths: string[], topLevelKeys: Set<string>, referencedSchemaPropertyNames: Set<string> }}
|
|
@@ -46,111 +112,246 @@ function parsePathsFromExpressions(attributes) {
|
|
|
46
112
|
const paths = [];
|
|
47
113
|
const topLevelKeys = new Set();
|
|
48
114
|
const referencedSchemaPropertyNames = new Set();
|
|
49
|
-
if (!attributes || typeof attributes !== 'object')
|
|
115
|
+
if (!attributes || typeof attributes !== 'object') {
|
|
116
|
+
return { paths, topLevelKeys, referencedSchemaPropertyNames };
|
|
117
|
+
}
|
|
50
118
|
for (const attr of Object.values(attributes)) {
|
|
51
119
|
const expr = attr?.expression;
|
|
52
120
|
if (typeof expr !== 'string') continue;
|
|
53
121
|
if (/^\s*record_ref:/i.test(expr.trim())) continue;
|
|
54
122
|
const match = expr.match(/\{\{\s*([^}]+)\s*\}\}/);
|
|
55
123
|
if (!match) continue;
|
|
56
|
-
|
|
57
|
-
if (path)
|
|
58
|
-
|
|
59
|
-
const segments = path.split('.');
|
|
60
|
-
const first = segments[0];
|
|
61
|
-
if (first) topLevelKeys.add(first);
|
|
62
|
-
if (first === 'metadata' && segments.length >= 2 && segments[1]) {
|
|
63
|
-
referencedSchemaPropertyNames.add(segments[1]);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
124
|
+
let path = match[1].trim().split('|')[0].trim();
|
|
125
|
+
if (path.startsWith('raw.')) path = path.slice(4);
|
|
126
|
+
if (path) accumulatePathSegments(path, paths, topLevelKeys, referencedSchemaPropertyNames);
|
|
66
127
|
}
|
|
67
128
|
return { paths, topLevelKeys, referencedSchemaPropertyNames };
|
|
68
129
|
}
|
|
69
130
|
|
|
70
131
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
132
|
+
* @param {Object} binding - dimension binding
|
|
133
|
+
* @param {string} dimKey - dimension key
|
|
134
|
+
* @param {string[]} changes - Change log
|
|
135
|
+
* @returns {boolean}
|
|
136
|
+
*/
|
|
137
|
+
function removeOperatorWithoutActor(binding, dimKey, changes) {
|
|
138
|
+
if (binding.operator && !binding.actor) {
|
|
139
|
+
delete binding.operator;
|
|
140
|
+
changes.push(`Removed 'operator' from dimension '${dimKey}' (no actor)`);
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @param {string} dimKey - dimension key
|
|
148
|
+
* @param {Object} binding - dimension binding
|
|
149
|
+
* @param {string[]} changes - Change log
|
|
150
|
+
* @returns {boolean}
|
|
151
|
+
*/
|
|
152
|
+
function repairFkDimensionBinding(dimKey, binding, changes) {
|
|
153
|
+
let updated = false;
|
|
154
|
+
if (binding.field !== undefined) {
|
|
155
|
+
delete binding.field;
|
|
156
|
+
changes.push(`Removed invalid 'field' from FK dimension '${dimKey}'`);
|
|
157
|
+
updated = true;
|
|
158
|
+
}
|
|
159
|
+
return removeOperatorWithoutActor(binding, dimKey, changes) || updated;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* @param {string} dimKey - dimension key
|
|
164
|
+
* @param {Object} binding - dimension binding
|
|
165
|
+
* @param {string[]} changes - Change log
|
|
166
|
+
* @returns {boolean}
|
|
167
|
+
*/
|
|
168
|
+
function repairLocalDimensionBinding(dimKey, binding, changes) {
|
|
169
|
+
let updated = false;
|
|
170
|
+
if (binding.via !== undefined) {
|
|
171
|
+
delete binding.via;
|
|
172
|
+
changes.push(`Removed invalid 'via' from local dimension '${dimKey}'`);
|
|
173
|
+
updated = true;
|
|
174
|
+
}
|
|
175
|
+
return removeOperatorWithoutActor(binding, dimKey, changes) || updated;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Normalizes dimension bindings: FK vs local invariants; strip operator without actor.
|
|
180
|
+
* @param {Object} parsed - Parsed datasource (mutated)
|
|
181
|
+
* @param {string[]} changes - Change log
|
|
182
|
+
* @returns {boolean}
|
|
183
|
+
*/
|
|
184
|
+
function repairDimensionBindingShape(parsed, changes) {
|
|
185
|
+
const dims = parsed?.dimensions;
|
|
186
|
+
if (!dims || typeof dims !== 'object') return false;
|
|
187
|
+
let updated = false;
|
|
188
|
+
for (const [dimKey, binding] of Object.entries(dims)) {
|
|
189
|
+
if (!binding || typeof binding !== 'object') continue;
|
|
190
|
+
const t = binding.type;
|
|
191
|
+
if (t === 'fk') {
|
|
192
|
+
updated = repairFkDimensionBinding(dimKey, binding, changes) || updated;
|
|
193
|
+
} else if (t === 'local' || t === undefined) {
|
|
194
|
+
updated = repairLocalDimensionBinding(dimKey, binding, changes) || updated;
|
|
195
|
+
} else {
|
|
196
|
+
updated = removeOperatorWithoutActor(binding, dimKey, changes) || updated;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return updated;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Removes root local dimension bindings whose field is not in fieldMappings.attributes.
|
|
204
|
+
* Skips FK bindings.
|
|
74
205
|
* @param {Object} parsed - Parsed datasource (mutated)
|
|
75
|
-
* @param {string[]} changes -
|
|
206
|
+
* @param {string[]} changes - Change log
|
|
76
207
|
* @returns {boolean} True if any dimension was removed
|
|
77
208
|
*/
|
|
78
|
-
function
|
|
79
|
-
const dims = parsed?.
|
|
209
|
+
function repairRootDimensionsFromAttributes(parsed, changes) {
|
|
210
|
+
const dims = parsed?.dimensions;
|
|
80
211
|
if (!dims || typeof dims !== 'object') return false;
|
|
81
212
|
const attributeKeys = getAttributeKeys(parsed);
|
|
82
213
|
let updated = false;
|
|
83
|
-
for (const [dimKey,
|
|
84
|
-
if (typeof
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
|
|
214
|
+
for (const [dimKey, binding] of Object.entries(dims)) {
|
|
215
|
+
if (!binding || typeof binding !== 'object') continue;
|
|
216
|
+
if (binding.type === 'fk') continue;
|
|
217
|
+
if (binding.type !== undefined && binding.type !== 'local') continue;
|
|
218
|
+
const field = binding.field;
|
|
219
|
+
if (typeof field !== 'string') continue;
|
|
220
|
+
if (attributeKeys.has(field)) continue;
|
|
88
221
|
delete dims[dimKey];
|
|
89
|
-
changes.push(`Removed dimension '${dimKey}': ${
|
|
222
|
+
changes.push(`Removed root dimension '${dimKey}': field '${field}' not in fieldMappings.attributes`);
|
|
90
223
|
updated = true;
|
|
91
224
|
}
|
|
92
225
|
return updated;
|
|
93
226
|
}
|
|
94
227
|
|
|
95
228
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
229
|
+
* Adds metadataSchema property stubs for metadata.* paths referenced in attributes.
|
|
230
|
+
* @param {Object} parsed - Parsed datasource (mutated)
|
|
231
|
+
* @param {Set<string>} referencedSchemaPropertyNames - Property names under metadata
|
|
232
|
+
* @param {string[]} changes - Change log
|
|
233
|
+
* @returns {boolean}
|
|
234
|
+
*/
|
|
235
|
+
function ensureMetadataSchemaPropertyStubs(parsed, referencedSchemaPropertyNames, changes) {
|
|
236
|
+
if (!referencedSchemaPropertyNames || referencedSchemaPropertyNames.size === 0) return false;
|
|
237
|
+
if (!parsed.metadataSchema || typeof parsed.metadataSchema !== 'object') return false;
|
|
238
|
+
if (!parsed.metadataSchema.properties || typeof parsed.metadataSchema.properties !== 'object') {
|
|
239
|
+
parsed.metadataSchema.properties = {};
|
|
240
|
+
}
|
|
241
|
+
const props = parsed.metadataSchema.properties;
|
|
242
|
+
const added = [];
|
|
243
|
+
for (const name of referencedSchemaPropertyNames) {
|
|
244
|
+
if (!name || props[name] !== undefined) continue;
|
|
245
|
+
props[name] = { type: 'string' };
|
|
246
|
+
added.push(name);
|
|
247
|
+
}
|
|
248
|
+
if (added.length === 0) return false;
|
|
249
|
+
changes.push(`Added metadataSchema.properties stubs for [${added.join(', ')}]`);
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* @param {Object} parsed - Parsed datasource (mutated)
|
|
255
|
+
* @param {Set<string>} referencedSchemaPropertyNames - metadata.* names from expressions
|
|
256
|
+
* @param {string[]} changes - Change log
|
|
257
|
+
* @returns {boolean}
|
|
258
|
+
*/
|
|
259
|
+
function pruneMetadataSchemaPropertiesByAttributeRefs(parsed, referencedSchemaPropertyNames, changes) {
|
|
260
|
+
const props = parsed.metadataSchema?.properties;
|
|
261
|
+
if (
|
|
262
|
+
!props || typeof props !== 'object'
|
|
263
|
+
|| referencedSchemaPropertyNames.size === 0
|
|
264
|
+
) {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
const toRemove = Object.keys(props).filter(k => {
|
|
268
|
+
if (referencedSchemaPropertyNames.has(k)) return false;
|
|
269
|
+
if (isStorageEntityType(parsed.entityType) && k === 'externalId') return false;
|
|
270
|
+
return true;
|
|
271
|
+
});
|
|
272
|
+
if (toRemove.length === 0) return false;
|
|
273
|
+
toRemove.forEach(k => delete props[k]);
|
|
274
|
+
changes.push(`Pruned metadataSchema.properties: removed [${toRemove.join(', ')}] (not referenced by attributes)`);
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Ensures metadataSchema exists (minimal stub if missing). Prunes top-level properties not
|
|
280
|
+
* referenced by metadata.* paths in expressions (after stripping raw. prefix).
|
|
281
|
+
* Skipped entirely for entityType 'none'.
|
|
100
282
|
*
|
|
101
283
|
* @param {Object} parsed - Parsed datasource (mutated)
|
|
102
|
-
* @param {string[]} changes -
|
|
284
|
+
* @param {string[]} changes - Change log
|
|
103
285
|
* @returns {boolean} True if schema was added or pruned
|
|
104
286
|
*/
|
|
105
287
|
function repairMetadataSchemaFromAttributes(parsed, changes) {
|
|
288
|
+
if (isNoneEntityType(parsed?.entityType)) {
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
106
291
|
const { referencedSchemaPropertyNames } = parsePathsFromExpressions(parsed?.fieldMappings?.attributes ?? {});
|
|
292
|
+
let updated = false;
|
|
293
|
+
|
|
107
294
|
if (!parsed.metadataSchema || typeof parsed.metadataSchema !== 'object') {
|
|
108
|
-
parsed.metadataSchema = { ...MINIMAL_METADATA_SCHEMA };
|
|
295
|
+
parsed.metadataSchema = { ...MINIMAL_METADATA_SCHEMA, properties: {} };
|
|
109
296
|
changes.push('Added minimal metadataSchema (was missing)');
|
|
110
|
-
|
|
297
|
+
ensureMetadataSchemaPropertyStubs(parsed, referencedSchemaPropertyNames, changes);
|
|
298
|
+
updated = true;
|
|
299
|
+
} else {
|
|
300
|
+
if (pruneMetadataSchemaPropertiesByAttributeRefs(parsed, referencedSchemaPropertyNames, changes)) {
|
|
301
|
+
updated = true;
|
|
302
|
+
}
|
|
303
|
+
if (ensureMetadataSchemaPropertyStubs(parsed, referencedSchemaPropertyNames, changes)) {
|
|
304
|
+
updated = true;
|
|
305
|
+
}
|
|
111
306
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if (toRemove.length === 0) return false;
|
|
117
|
-
toRemove.forEach(k => delete props[k]);
|
|
118
|
-
changes.push(`Pruned metadataSchema.properties: removed [${toRemove.join(', ')}] (not referenced by attributes)`);
|
|
119
|
-
return true;
|
|
307
|
+
if (ensureStorageExternalIdMetadataProperty(parsed, changes)) {
|
|
308
|
+
updated = true;
|
|
309
|
+
}
|
|
310
|
+
return updated;
|
|
120
311
|
}
|
|
121
312
|
|
|
122
313
|
/**
|
|
123
|
-
* Sets exposed.
|
|
124
|
-
*
|
|
314
|
+
* Sets exposed.schema from fieldMappings.attributes keys (metadata.<key> leaves). v2.4 canonical.
|
|
315
|
+
* Removes deprecated exposed.attributes when present so output matches schema.
|
|
125
316
|
*
|
|
126
317
|
* @param {Object} parsed - Parsed datasource (mutated)
|
|
127
|
-
* @param {string[]} changes -
|
|
318
|
+
* @param {string[]} changes - Change log
|
|
128
319
|
* @returns {boolean} True if exposed was updated
|
|
129
320
|
*/
|
|
130
321
|
function repairExposeFromAttributes(parsed, changes) {
|
|
131
322
|
const keys = Array.from(getAttributeKeys(parsed)).filter(Boolean).sort();
|
|
132
323
|
if (keys.length === 0) return false;
|
|
133
324
|
if (!parsed.exposed) parsed.exposed = {};
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
325
|
+
const schema = {};
|
|
326
|
+
keys.forEach(k => {
|
|
327
|
+
schema[k] = `metadata.${k}`;
|
|
328
|
+
});
|
|
329
|
+
const prev = parsed.exposed.schema;
|
|
330
|
+
const same = prev && typeof prev === 'object'
|
|
331
|
+
&& keys.length === Object.keys(prev).length
|
|
332
|
+
&& keys.every(k => prev[k] === schema[k]);
|
|
333
|
+
if (same && parsed.exposed.attributes === undefined) return false;
|
|
334
|
+
parsed.exposed.schema = schema;
|
|
335
|
+
if (parsed.exposed.attributes !== undefined) {
|
|
336
|
+
delete parsed.exposed.attributes;
|
|
337
|
+
}
|
|
338
|
+
changes.push(`Set exposed.schema for [${keys.join(', ')}]`);
|
|
139
339
|
return true;
|
|
140
340
|
}
|
|
141
341
|
|
|
142
342
|
/**
|
|
143
|
-
* Adds default sync section if missing or empty.
|
|
343
|
+
* Adds default sync section if missing or empty. Not applied for entityType 'none'.
|
|
144
344
|
*
|
|
145
345
|
* @param {Object} parsed - Parsed datasource (mutated)
|
|
146
|
-
* @param {string[]} changes -
|
|
346
|
+
* @param {string[]} changes - Change log
|
|
147
347
|
* @returns {boolean} True if sync was added
|
|
148
348
|
*/
|
|
149
349
|
function repairSyncSection(parsed, changes) {
|
|
350
|
+
if (isNoneEntityType(parsed?.entityType)) return false;
|
|
150
351
|
const sync = parsed.sync;
|
|
151
352
|
if (sync && typeof sync === 'object' && Object.keys(sync).length > 0) return false;
|
|
152
353
|
parsed.sync = { ...DEFAULT_SYNC };
|
|
153
|
-
changes.push('Added default sync section (mode: pull, batchSize: 500
|
|
354
|
+
changes.push('Added default sync section (mode: pull, batchSize: 500)');
|
|
154
355
|
return true;
|
|
155
356
|
}
|
|
156
357
|
|
|
@@ -173,11 +374,32 @@ function setNested(obj, pathParts, value) {
|
|
|
173
374
|
if (last) cur[last] = value;
|
|
174
375
|
}
|
|
175
376
|
|
|
377
|
+
/**
|
|
378
|
+
* Removes unknown top-level keys from testPayload (v2.4.1 closed root).
|
|
379
|
+
* @param {Object} parsed - Parsed datasource (mutated)
|
|
380
|
+
* @param {string[]} changes - Change log
|
|
381
|
+
* @returns {boolean}
|
|
382
|
+
*/
|
|
383
|
+
function sanitizeTestPayloadTopLevel(parsed, changes) {
|
|
384
|
+
const tp = parsed?.testPayload;
|
|
385
|
+
if (!tp || typeof tp !== 'object' || Array.isArray(tp)) return false;
|
|
386
|
+
const removed = [];
|
|
387
|
+
for (const key of Object.keys(tp)) {
|
|
388
|
+
if (!TEST_PAYLOAD_TOP_LEVEL_ALLOW.has(key)) {
|
|
389
|
+
delete tp[key];
|
|
390
|
+
removed.push(key);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
if (removed.length === 0) return false;
|
|
394
|
+
changes.push(`Removed unknown testPayload keys: [${removed.join(', ')}]`);
|
|
395
|
+
return true;
|
|
396
|
+
}
|
|
397
|
+
|
|
176
398
|
/**
|
|
177
399
|
* Builds minimal payloadTemplate and expectedResult from attribute expression paths.
|
|
178
400
|
*
|
|
179
401
|
* @param {Object} parsed - Parsed datasource (mutated)
|
|
180
|
-
* @param {string[]} changes -
|
|
402
|
+
* @param {string[]} changes - Change log
|
|
181
403
|
* @returns {boolean} True if testPayload was added or updated
|
|
182
404
|
*/
|
|
183
405
|
function repairTestPayload(parsed, changes) {
|
|
@@ -191,7 +413,10 @@ function repairTestPayload(parsed, changes) {
|
|
|
191
413
|
expectedResult[key] = placeholder;
|
|
192
414
|
const match = config?.expression?.match(/\{\{\s*([^}|]+)/);
|
|
193
415
|
if (match) {
|
|
194
|
-
|
|
416
|
+
let path = match[1].trim();
|
|
417
|
+
if (path.startsWith('raw.')) {
|
|
418
|
+
path = path.slice(4);
|
|
419
|
+
}
|
|
195
420
|
setNested(payloadTemplate, path.split('.'), placeholder);
|
|
196
421
|
}
|
|
197
422
|
}
|
|
@@ -203,7 +428,7 @@ function repairTestPayload(parsed, changes) {
|
|
|
203
428
|
}
|
|
204
429
|
|
|
205
430
|
/**
|
|
206
|
-
* Runs all requested datasource repairs.
|
|
431
|
+
* Runs all requested datasource repairs.
|
|
207
432
|
*
|
|
208
433
|
* @param {Object} parsed - Parsed datasource object (mutated)
|
|
209
434
|
* @param {Object} options - { expose?: boolean, sync?: boolean, test?: boolean }
|
|
@@ -213,23 +438,44 @@ function repairTestPayload(parsed, changes) {
|
|
|
213
438
|
function repairDatasourceFile(parsed, options = {}, changes = []) {
|
|
214
439
|
const out = Array.isArray(changes) ? changes : [];
|
|
215
440
|
let updated = false;
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
if (
|
|
219
|
-
|
|
220
|
-
|
|
441
|
+
const none = isNoneEntityType(parsed?.entityType);
|
|
442
|
+
|
|
443
|
+
if (!none) {
|
|
444
|
+
updated = repairDimensionBindingShape(parsed, out) || updated;
|
|
445
|
+
updated = repairRootDimensionsFromAttributes(parsed, out) || updated;
|
|
446
|
+
updated = repairMetadataSchemaFromAttributes(parsed, out) || updated;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (options.expose) {
|
|
450
|
+
updated = repairExposeFromAttributes(parsed, out) || updated;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
if (!none && options.sync) {
|
|
454
|
+
updated = repairSyncSection(parsed, out) || updated;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
if (options.test) {
|
|
458
|
+
sanitizeTestPayloadTopLevel(parsed, out);
|
|
459
|
+
updated = repairTestPayload(parsed, out) || updated;
|
|
460
|
+
updated = sanitizeTestPayloadTopLevel(parsed, out) || updated;
|
|
461
|
+
}
|
|
462
|
+
|
|
221
463
|
return { updated, changes: out };
|
|
222
464
|
}
|
|
223
465
|
|
|
224
466
|
module.exports = {
|
|
225
467
|
getAttributeKeys,
|
|
226
468
|
parsePathsFromExpressions,
|
|
227
|
-
|
|
469
|
+
repairDimensionBindingShape,
|
|
470
|
+
repairRootDimensionsFromAttributes,
|
|
228
471
|
repairMetadataSchemaFromAttributes,
|
|
229
472
|
repairExposeFromAttributes,
|
|
230
473
|
repairSyncSection,
|
|
231
474
|
repairTestPayload,
|
|
475
|
+
sanitizeTestPayloadTopLevel,
|
|
232
476
|
repairDatasourceFile,
|
|
233
477
|
DEFAULT_SYNC,
|
|
234
|
-
MINIMAL_METADATA_SCHEMA
|
|
478
|
+
MINIMAL_METADATA_SCHEMA,
|
|
479
|
+
TEST_PAYLOAD_TOP_LEVEL_ALLOW,
|
|
480
|
+
isNoneEntityType
|
|
235
481
|
};
|
|
@@ -15,7 +15,7 @@ const { generateExternalEnvTemplateContent } = require('../utils/external-env-te
|
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Normalizes a keyvault config entry to canonical KV_* name and path-style value.
|
|
18
|
-
* Path format: kv://<
|
|
18
|
+
* Path format: kv://<systemKey>/<variable> (e.g. kv://microsoft-teams/clientId).
|
|
19
19
|
* @param {Object} entry - Config entry with name, value, location
|
|
20
20
|
* @param {string} prefix - KV prefix (e.g. MICROSOFT_TEAMS)
|
|
21
21
|
* @param {string} systemKey - System key (e.g. microsoft-teams) for path namespace
|
|
@@ -66,7 +66,7 @@ function addFromConfiguration(effective, config, prefix, seenNames, systemKey) {
|
|
|
66
66
|
|
|
67
67
|
/**
|
|
68
68
|
* Adds effective config entries from authentication.security.
|
|
69
|
-
* Path format: kv://<
|
|
69
|
+
* Path format: kv://<systemKey>/<variable> (e.g. kv://microsoft-teams/clientId).
|
|
70
70
|
* @param {Array} effective - Mutable result array
|
|
71
71
|
* @param {Object} systemParsed - Parsed system config
|
|
72
72
|
* @param {string} prefix - KV prefix
|
package/lib/commands/repair.js
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
/* eslint-disable max-lines -- Repair flow with auth, normalization, and steps */
|
|
13
13
|
|
|
14
14
|
'use strict';
|
|
15
|
+
const { formatSuccessLine } = require('../utils/cli-test-layout-chalk');
|
|
15
16
|
|
|
16
17
|
const path = require('path');
|
|
17
18
|
const fs = require('fs');
|
|
@@ -32,6 +33,22 @@ const { normalizeDatasourceKeysAndFilenames } = require('./repair-datasource-key
|
|
|
32
33
|
/** Allowed authentication methods for repair --auth (matches external-system schema) */
|
|
33
34
|
const ALLOWED_AUTH = ['oauth2', 'aad', 'apikey', 'basic', 'queryParam', 'oidc', 'hmac', 'none'];
|
|
34
35
|
|
|
36
|
+
/**
|
|
37
|
+
* README "Files" section should match integration config format on disk (YAML vs JSON).
|
|
38
|
+
* @param {string} appPath - Integration directory
|
|
39
|
+
* @returns {string} '.yaml' or '.json'
|
|
40
|
+
*/
|
|
41
|
+
function inferExternalReadmeFileExt(appPath) {
|
|
42
|
+
try {
|
|
43
|
+
const configPath = resolveApplicationConfigPath(appPath);
|
|
44
|
+
const ext = path.extname(configPath).toLowerCase();
|
|
45
|
+
if (ext === '.yaml' || ext === '.yml') return '.yaml';
|
|
46
|
+
} catch {
|
|
47
|
+
/* use default */
|
|
48
|
+
}
|
|
49
|
+
return '.json';
|
|
50
|
+
}
|
|
51
|
+
|
|
35
52
|
/**
|
|
36
53
|
* Extracts roles and permissions from system object for rbac.yaml
|
|
37
54
|
* @param {Object} system - Parsed system config
|
|
@@ -296,7 +313,7 @@ function createRbacFromSystemIfNeeded(appPath, systemFilePath, systemParsed, dry
|
|
|
296
313
|
}
|
|
297
314
|
|
|
298
315
|
/**
|
|
299
|
-
* Runs datasource repair for each file (dimensions, metadataSchema
|
|
316
|
+
* Runs datasource repair for each file (v2.4 root dimensions, metadataSchema; optional expose/sync/test).
|
|
300
317
|
* @param {string} appPath - Application path
|
|
301
318
|
* @param {string[]} datasourceFiles - Datasource file names
|
|
302
319
|
* @param {Object} options - { expose?: boolean, sync?: boolean, test?: boolean }
|
|
@@ -359,7 +376,8 @@ async function regenerateReadmeIfRequested(appName, appPath, options, changes) {
|
|
|
359
376
|
if (!fs.existsSync(deployJsonPath)) return false;
|
|
360
377
|
try {
|
|
361
378
|
const deployment = JSON.parse(fs.readFileSync(deployJsonPath, 'utf8'));
|
|
362
|
-
const
|
|
379
|
+
const fileExt = inferExternalReadmeFileExt(appPath);
|
|
380
|
+
const readmeContent = generateReadmeFromDeployJson(deployment, { fileExt });
|
|
363
381
|
const readmePath = path.join(appPath, 'README.md');
|
|
364
382
|
if (!options.dryRun) {
|
|
365
383
|
fs.writeFileSync(readmePath, readmeContent, { mode: 0o644, encoding: 'utf8' });
|
|
@@ -378,7 +396,7 @@ function persistChangesAndRegenerate(configPath, variables, appName, appPath, ch
|
|
|
378
396
|
} else {
|
|
379
397
|
writeConfigFile(configPath, variables);
|
|
380
398
|
}
|
|
381
|
-
logger.log(
|
|
399
|
+
logger.log(formatSuccessLine(`Updated ${path.basename(configPath)}`));
|
|
382
400
|
changes.forEach(c => logger.log(chalk.gray(` ${c}`)));
|
|
383
401
|
return regenerateManifest(appName, appPath, changes);
|
|
384
402
|
}
|
|
@@ -11,7 +11,7 @@ const chalk = require('chalk');
|
|
|
11
11
|
const logger = require('../utils/logger');
|
|
12
12
|
const { getAifabrixSecretsPath } = require('../core/config');
|
|
13
13
|
const pathsUtil = require('../utils/paths');
|
|
14
|
-
const
|
|
14
|
+
const remoteDevAuth = require('../utils/remote-dev-auth');
|
|
15
15
|
const devApi = require('../api/dev.api');
|
|
16
16
|
|
|
17
17
|
const REMOTE_NOT_CONFIGURED_MSG = 'Remote server is not configured. Set remote-server and run "aifabrix dev init" first.';
|
|
@@ -38,8 +38,8 @@ function listKeysAndValuesFromFile(filePath) {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
const KEY_COL_WIDTH =
|
|
42
|
-
const TABLE_SEPARATOR_LENGTH =
|
|
41
|
+
const KEY_COL_WIDTH = 55;
|
|
42
|
+
const TABLE_SEPARATOR_LENGTH = 130;
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* Log a list of secret keys and values as a table (header, column headers, separator, rows).
|
|
@@ -70,19 +70,26 @@ function logKeyValueList(emptyMessage, title, items) {
|
|
|
70
70
|
* @returns {Promise<void>}
|
|
71
71
|
*/
|
|
72
72
|
async function listSharedSecrets(generalSecretsPath) {
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
const target = await remoteDevAuth.resolveSharedSecretsEndpoint(generalSecretsPath);
|
|
74
|
+
if (remoteDevAuth.isRemoteSecretsUrl(target)) {
|
|
75
|
+
const auth = await remoteDevAuth.getRemoteDevAuth();
|
|
75
76
|
if (!auth) {
|
|
76
77
|
throw new Error(REMOTE_NOT_CONFIGURED_MSG);
|
|
77
78
|
}
|
|
78
|
-
const items = await devApi.listSecrets(
|
|
79
|
+
const items = await devApi.listSecrets(
|
|
80
|
+
auth.serverUrl,
|
|
81
|
+
auth.clientCertPem,
|
|
82
|
+
auth.serverCaPem || undefined,
|
|
83
|
+
target
|
|
84
|
+
);
|
|
79
85
|
const keyValues = items.map(i => ({ key: i.name || i.key || '', value: (i.value !== null && i.value !== undefined) ? String(i.value) : '' }));
|
|
80
|
-
|
|
86
|
+
const { title, emptyMessage } = remoteDevAuth.getSharedSecretsRemoteListLabels(target);
|
|
87
|
+
logKeyValueList(emptyMessage, title, keyValues);
|
|
81
88
|
return;
|
|
82
89
|
}
|
|
83
|
-
const resolvedPath = path.isAbsolute(
|
|
84
|
-
?
|
|
85
|
-
: path.resolve(process.cwd(),
|
|
90
|
+
const resolvedPath = path.isAbsolute(target)
|
|
91
|
+
? target
|
|
92
|
+
: path.resolve(process.cwd(), target);
|
|
86
93
|
const keyValues = listKeysAndValuesFromFile(resolvedPath);
|
|
87
94
|
const fileTitle = `Shared secrets (file: ${resolvedPath})`;
|
|
88
95
|
logKeyValueList('No shared secrets in file.', fileTitle, keyValues);
|
|
@@ -90,9 +97,13 @@ async function listSharedSecrets(generalSecretsPath) {
|
|
|
90
97
|
|
|
91
98
|
/** List user secrets and log key and value. */
|
|
92
99
|
function listUserSecrets() {
|
|
93
|
-
const userSecretsPath =
|
|
100
|
+
const userSecretsPath = pathsUtil.getPrimaryUserSecretsLocalPath();
|
|
94
101
|
const keyValues = listKeysAndValuesFromFile(userSecretsPath);
|
|
95
|
-
logKeyValueList(
|
|
102
|
+
logKeyValueList(
|
|
103
|
+
`No user secrets (file: ${userSecretsPath}). Use "aifabrix secret set <KEY> <value>" or resolve/up-infra to populate.`,
|
|
104
|
+
'User secrets',
|
|
105
|
+
keyValues
|
|
106
|
+
);
|
|
96
107
|
}
|
|
97
108
|
|
|
98
109
|
/**
|