@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
|
@@ -5,49 +5,82 @@
|
|
|
5
5
|
* @version 2.0.0
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
const path = require('path');
|
|
9
8
|
const fs = require('fs');
|
|
10
9
|
const {
|
|
11
10
|
getIntegrationPath,
|
|
12
11
|
listIntegrationAppNames,
|
|
13
12
|
resolveIntegrationAppKeyFromCwd
|
|
14
13
|
} = require('../utils/paths');
|
|
15
|
-
const {
|
|
16
|
-
|
|
14
|
+
const {
|
|
15
|
+
appHasDatasourceIdentifier,
|
|
16
|
+
pickIntegrationAppForDatasourceIdentifier
|
|
17
|
+
} = require('./datasource-identifier');
|
|
18
|
+
|
|
19
|
+
/** @deprecated Use appHasDatasourceIdentifier — kept for tests and backward compatibility */
|
|
20
|
+
function appHasDatasourceKey(appKey, datasourceKey) {
|
|
21
|
+
return appHasDatasourceIdentifier(appKey, datasourceKey);
|
|
22
|
+
}
|
|
17
23
|
|
|
18
24
|
/**
|
|
19
|
-
*
|
|
20
|
-
* @param {string}
|
|
21
|
-
* @
|
|
22
|
-
* @returns {boolean} True if this app has a datasource with that key
|
|
25
|
+
* @param {string} key
|
|
26
|
+
* @param {string} [explicitApp]
|
|
27
|
+
* @returns {{ appKey: string }|null}
|
|
23
28
|
*/
|
|
24
|
-
function
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
function resolveFromExplicitApp(key, explicitApp) {
|
|
30
|
+
if (!explicitApp || typeof explicitApp !== 'string' || !explicitApp.trim()) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const appKey = explicitApp.trim();
|
|
34
|
+
if (fs.existsSync(getIntegrationPath(appKey))) {
|
|
35
|
+
return { appKey };
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {string} key
|
|
42
|
+
* @param {string[]} appNames
|
|
43
|
+
* @returns {{ appKey: string }|null}
|
|
44
|
+
* @throws {Error}
|
|
45
|
+
*/
|
|
46
|
+
function resolveFromAppScan(key, appNames) {
|
|
47
|
+
const matches = appNames.filter(appName => appHasDatasourceIdentifier(appName, key));
|
|
48
|
+
if (matches.length === 1) {
|
|
49
|
+
return { appKey: matches[0] };
|
|
50
|
+
}
|
|
51
|
+
if (matches.length > 1) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
`More than one app has this datasource; add --app <app>. Apps: ${matches.join(', ')}`
|
|
54
|
+
);
|
|
32
55
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
// skip unreadable or invalid files
|
|
46
|
-
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @param {string} key
|
|
61
|
+
* @param {string[]} appNames
|
|
62
|
+
* @returns {{ appKey: string }|null}
|
|
63
|
+
*/
|
|
64
|
+
function resolveFromPrefixOrSegments(key, appNames) {
|
|
65
|
+
const prefixApp = pickIntegrationAppForDatasourceIdentifier(key, appNames);
|
|
66
|
+
if (prefixApp && appHasDatasourceIdentifier(prefixApp, key)) {
|
|
67
|
+
return { appKey: prefixApp };
|
|
47
68
|
}
|
|
48
|
-
|
|
69
|
+
const segments = key.split('-');
|
|
70
|
+
if (segments.length < 2) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
const candidate = segments.slice(0, -1).join('-');
|
|
74
|
+
const candidatePath = getIntegrationPath(candidate);
|
|
75
|
+
if (fs.existsSync(candidatePath) && appHasDatasourceIdentifier(candidate, key)) {
|
|
76
|
+
return { appKey: candidate };
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
49
79
|
}
|
|
50
80
|
|
|
81
|
+
const RESOLVE_APP_HINT =
|
|
82
|
+
'Could not determine app context. Use --app <app>, a datasource key, a datasource JSON filename (e.g. myapp-datasource-contacts), or run from integration/<systemKey>/ directory.';
|
|
83
|
+
|
|
51
84
|
/**
|
|
52
85
|
* Resolve app key for a datasource: explicit --app, cwd, scan by key, or parse key convention.
|
|
53
86
|
* @async
|
|
@@ -56,7 +89,6 @@ function appHasDatasourceKey(appKey, datasourceKey) {
|
|
|
56
89
|
* @returns {Promise<{appKey: string}>} Resolved app key
|
|
57
90
|
* @throws {Error} When app cannot be determined or multiple apps match
|
|
58
91
|
*/
|
|
59
|
-
/* eslint-disable-next-line max-statements -- Resolution order: explicit, cwd, scan, parse */
|
|
60
92
|
async function resolveAppKeyForDatasource(datasourceKey, explicitApp) {
|
|
61
93
|
if (!datasourceKey || typeof datasourceKey !== 'string') {
|
|
62
94
|
throw new Error('Datasource key is required');
|
|
@@ -66,41 +98,28 @@ async function resolveAppKeyForDatasource(datasourceKey, explicitApp) {
|
|
|
66
98
|
throw new Error('Datasource key cannot be empty');
|
|
67
99
|
}
|
|
68
100
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return { appKey: explicitApp.trim() };
|
|
73
|
-
}
|
|
101
|
+
const explicit = resolveFromExplicitApp(key, explicitApp);
|
|
102
|
+
if (explicit) {
|
|
103
|
+
return explicit;
|
|
74
104
|
}
|
|
75
105
|
|
|
76
106
|
const fromCwd = resolveIntegrationAppKeyFromCwd();
|
|
77
|
-
if (fromCwd &&
|
|
107
|
+
if (fromCwd && appHasDatasourceIdentifier(fromCwd, key)) {
|
|
78
108
|
return { appKey: fromCwd };
|
|
79
109
|
}
|
|
80
110
|
|
|
81
111
|
const appNames = listIntegrationAppNames();
|
|
82
|
-
const
|
|
83
|
-
if (
|
|
84
|
-
return
|
|
85
|
-
}
|
|
86
|
-
if (matches.length > 1) {
|
|
87
|
-
throw new Error(
|
|
88
|
-
`More than one app has this datasource; add --app <app>. Apps: ${matches.join(', ')}`
|
|
89
|
-
);
|
|
112
|
+
const scanned = resolveFromAppScan(key, appNames);
|
|
113
|
+
if (scanned) {
|
|
114
|
+
return scanned;
|
|
90
115
|
}
|
|
91
116
|
|
|
92
|
-
const
|
|
93
|
-
if (
|
|
94
|
-
|
|
95
|
-
const candidatePath = getIntegrationPath(candidate);
|
|
96
|
-
if (fs.existsSync(candidatePath) && appHasDatasourceKey(candidate, key)) {
|
|
97
|
-
return { appKey: candidate };
|
|
98
|
-
}
|
|
117
|
+
const inferred = resolveFromPrefixOrSegments(key, appNames);
|
|
118
|
+
if (inferred) {
|
|
119
|
+
return inferred;
|
|
99
120
|
}
|
|
100
121
|
|
|
101
|
-
throw new Error(
|
|
102
|
-
'Could not determine app context. Use --app <app> or run from integration/<systemKey>/ directory.'
|
|
103
|
-
);
|
|
122
|
+
throw new Error(RESOLVE_APP_HINT);
|
|
104
123
|
}
|
|
105
124
|
|
|
106
125
|
module.exports = {
|
|
@@ -11,7 +11,7 @@ const chalk = require('chalk');
|
|
|
11
11
|
const logger = require('../utils/logger');
|
|
12
12
|
const { getIntegrationPath } = require('../utils/paths');
|
|
13
13
|
const { resolveAppKeyForDatasource } = require('./resolve-app');
|
|
14
|
-
const { infoLine } = require('../utils/cli-test-layout-chalk');
|
|
14
|
+
const { formatProgress, formatSuccessLine, infoLine } = require('../utils/cli-test-layout-chalk');
|
|
15
15
|
const { runUnifiedDatasourceValidation } = require('./unified-validation-run');
|
|
16
16
|
const { includeDebugForRequest } = require('../utils/validation-run-request');
|
|
17
17
|
const { e2eShapeFromEnvelope } = require('../utils/datasource-test-run-legacy-adapter');
|
|
@@ -41,7 +41,12 @@ function buildUnifiedE2eRunOptions(options, timeoutMs, pk) {
|
|
|
41
41
|
minRecordCount: options.minRecordCount,
|
|
42
42
|
capabilityKey: options.capabilityKey,
|
|
43
43
|
timeout: timeoutMs,
|
|
44
|
-
sync: options.sync === true
|
|
44
|
+
sync: options.sync === true,
|
|
45
|
+
force: options.force === true,
|
|
46
|
+
authConfig: options.authConfig,
|
|
47
|
+
dataplaneUrl: options.dataplaneUrl || options.dataplane,
|
|
48
|
+
quietPollUi: options.quietPollUi === true,
|
|
49
|
+
onPollProgress: options.onPollProgress
|
|
45
50
|
};
|
|
46
51
|
}
|
|
47
52
|
|
|
@@ -51,6 +56,25 @@ function logE2eDatasourceBanner(datasourceKey, verbose) {
|
|
|
51
56
|
logger.log(infoLine(`🧪 Running E2E test for datasource: ${datasourceKey}`));
|
|
52
57
|
}
|
|
53
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Compact per-datasource progress (default test-e2e / system rollup when not --verbose).
|
|
61
|
+
* @param {string} datasourceKey
|
|
62
|
+
* @param {boolean} verbose
|
|
63
|
+
*/
|
|
64
|
+
function logE2eDatasourceProgress(datasourceKey, verbose) {
|
|
65
|
+
if (verbose) return;
|
|
66
|
+
logger.log(formatProgress(`Running E2E validation for ${datasourceKey}…`));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @param {string} datasourceKey
|
|
71
|
+
* @param {boolean} verbose
|
|
72
|
+
*/
|
|
73
|
+
function logE2eDatasourceValidated(datasourceKey, verbose) {
|
|
74
|
+
if (verbose) return;
|
|
75
|
+
logger.log(formatSuccessLine(`${datasourceKey} validated`));
|
|
76
|
+
}
|
|
77
|
+
|
|
54
78
|
/**
|
|
55
79
|
* Resolve primaryKeyValue for request body: string as-is, or read and parse JSON from @path
|
|
56
80
|
* @param {string} [value]
|
|
@@ -174,6 +198,7 @@ async function runDatasourceTestE2E(datasourceKey, options = {}) {
|
|
|
174
198
|
const cliWallStartedAt = Date.now();
|
|
175
199
|
const { appKey } = await resolveAppKeyForDatasource(datasourceKey, options.app);
|
|
176
200
|
logE2eDatasourceBanner(datasourceKey, options.verbose);
|
|
201
|
+
logE2eDatasourceProgress(datasourceKey, options.verbose);
|
|
177
202
|
const pk = await resolvePrimaryKeyValue(options.primaryKeyValue);
|
|
178
203
|
const timeoutMs = resolveE2ePollTimeoutMs(options);
|
|
179
204
|
const requestMeta = buildE2eRequestMeta(datasourceKey, options, pk);
|
|
@@ -184,6 +209,8 @@ async function runDatasourceTestE2E(datasourceKey, options = {}) {
|
|
|
184
209
|
|
|
185
210
|
await throwIfUnifiedE2EBlocked(unifiedResult, appKey, options, requestMeta);
|
|
186
211
|
|
|
212
|
+
logE2eDatasourceValidated(datasourceKey, options.verbose);
|
|
213
|
+
|
|
187
214
|
const display = e2eShapeFromEnvelope(unifiedResult.envelope);
|
|
188
215
|
Object.assign(display, { datasourceTestRun: unifiedResult.envelope });
|
|
189
216
|
|
|
@@ -10,6 +10,7 @@ const {
|
|
|
10
10
|
includeDebugForRequest
|
|
11
11
|
} = require('../utils/validation-run-request');
|
|
12
12
|
const testHelpers = require('../utils/external-system-test-helpers');
|
|
13
|
+
const { withStageOnValidationRunBody } = require('../utils/validation-run-stage');
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* @param {Object} params
|
|
@@ -52,7 +53,7 @@ async function buildUnifiedValidationBody(params) {
|
|
|
52
53
|
})
|
|
53
54
|
: undefined;
|
|
54
55
|
|
|
55
|
-
|
|
56
|
+
const body = buildExternalDataSourceValidationRequest({
|
|
56
57
|
systemKey,
|
|
57
58
|
datasourceKey,
|
|
58
59
|
runType,
|
|
@@ -62,6 +63,7 @@ async function buildUnifiedValidationBody(params) {
|
|
|
62
63
|
explain: options.verbose === true,
|
|
63
64
|
e2eOptions: e2eOptions && Object.keys(e2eOptions).length > 0 ? e2eOptions : undefined
|
|
64
65
|
});
|
|
66
|
+
return withStageOnValidationRunBody(body, runType);
|
|
65
67
|
}
|
|
66
68
|
|
|
67
69
|
module.exports = { buildUnifiedValidationBody };
|
|
@@ -4,40 +4,73 @@
|
|
|
4
4
|
* @version 2.0.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
const path = require('path');
|
|
8
7
|
const { getIntegrationPath } = require('../utils/paths');
|
|
9
8
|
const { resolveApplicationConfigPath } = require('../utils/app-config-resolver');
|
|
10
9
|
const { loadConfigFile } = require('../utils/config-format');
|
|
10
|
+
const {
|
|
11
|
+
datasourceIdentifierMatchesFile,
|
|
12
|
+
resolveDatasourceFilePath
|
|
13
|
+
} = require('./datasource-identifier');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param {string} appPath
|
|
17
|
+
* @param {string} schemaBasePath
|
|
18
|
+
* @param {string[]} datasourceFiles
|
|
19
|
+
* @param {string} identifier
|
|
20
|
+
* @returns {string|null}
|
|
21
|
+
*/
|
|
22
|
+
function findDatasourceFileByIdentifier(appPath, schemaBasePath, datasourceFiles, identifier) {
|
|
23
|
+
const fsSync = require('fs');
|
|
24
|
+
for (const fileRef of datasourceFiles) {
|
|
25
|
+
if (!fileRef || typeof fileRef !== 'string') {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const fullPath = resolveDatasourceFilePath(appPath, schemaBasePath, fileRef);
|
|
29
|
+
if (!fsSync.existsSync(fullPath)) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const parsed = loadConfigFile(fullPath);
|
|
34
|
+
if (datasourceIdentifierMatchesFile(identifier, fileRef, parsed)) {
|
|
35
|
+
return fileRef;
|
|
36
|
+
}
|
|
37
|
+
} catch {
|
|
38
|
+
// skip unreadable or invalid files
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
11
43
|
|
|
12
44
|
/**
|
|
13
45
|
* @param {string} appKey
|
|
14
46
|
* @param {string} datasourceKey
|
|
15
47
|
* @param {Function} findDatasourceFileByKey - From integration-context
|
|
16
|
-
* @returns {{ datasource: Object, datasourcePath: string }}
|
|
48
|
+
* @returns {{ datasource: Object, datasourcePath: string, datasourceKey: string }}
|
|
17
49
|
*/
|
|
18
50
|
function loadDatasourceForApp(appKey, datasourceKey, findDatasourceFileByKey) {
|
|
19
51
|
const appPath = getIntegrationPath(appKey);
|
|
20
52
|
const config = loadConfigFile(resolveApplicationConfigPath(appPath));
|
|
21
53
|
const schemaBasePath = config.externalIntegration?.schemaBasePath || './';
|
|
22
54
|
const datasourceFiles = config.externalIntegration?.dataSources || [];
|
|
23
|
-
let datasourceFile =
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
55
|
+
let datasourceFile = findDatasourceFileByIdentifier(
|
|
56
|
+
appPath,
|
|
57
|
+
schemaBasePath,
|
|
58
|
+
datasourceFiles,
|
|
59
|
+
datasourceKey
|
|
60
|
+
);
|
|
27
61
|
if (!datasourceFile) {
|
|
28
62
|
datasourceFile = findDatasourceFileByKey(appPath, schemaBasePath, datasourceFiles, datasourceKey);
|
|
29
63
|
}
|
|
30
64
|
if (!datasourceFile) {
|
|
31
65
|
throw new Error(`Datasource '${datasourceKey}' not found in application config`);
|
|
32
66
|
}
|
|
33
|
-
const datasourcePath =
|
|
34
|
-
? path.join(schemaBasePath, datasourceFile)
|
|
35
|
-
: path.join(appPath, schemaBasePath, datasourceFile);
|
|
67
|
+
const datasourcePath = resolveDatasourceFilePath(appPath, schemaBasePath, datasourceFile);
|
|
36
68
|
const datasource = loadConfigFile(datasourcePath);
|
|
37
|
-
|
|
38
|
-
|
|
69
|
+
const canonicalKey = datasource.key;
|
|
70
|
+
if (!canonicalKey || typeof canonicalKey !== 'string') {
|
|
71
|
+
throw new Error(`Datasource file is missing a valid key: ${datasourcePath}`);
|
|
39
72
|
}
|
|
40
|
-
return { datasource, datasourcePath };
|
|
73
|
+
return { datasource, datasourcePath, datasourceKey: canonicalKey };
|
|
41
74
|
}
|
|
42
75
|
|
|
43
76
|
module.exports = { loadDatasourceForApp };
|
|
@@ -18,6 +18,7 @@ const { buildUnifiedValidationBody } = require('./unified-validation-run-body');
|
|
|
18
18
|
const { postValidationRunAndOptionalPoll } = require('./unified-validation-run-post');
|
|
19
19
|
const { requireBearerForDataplanePipeline } = require('../utils/token-manager');
|
|
20
20
|
const logger = require('../utils/logger');
|
|
21
|
+
const { buildMinimalUploadSyncOptions } = require('../utils/upload-sync-options');
|
|
21
22
|
|
|
22
23
|
function _resourceTypeFromDatasource(datasource) {
|
|
23
24
|
return datasource && typeof datasource === 'object' && typeof datasource.resourceType === 'string'
|
|
@@ -59,7 +60,7 @@ async function maybeSyncDatasourceToDataplane({ options, authConfig, systemKey }
|
|
|
59
60
|
// are updated before validation runs. Datasource-only publish can still fail DP-SEC-013 when the
|
|
60
61
|
// dataplane system permissions[] are stale.
|
|
61
62
|
const { uploadExternalSystem } = require('../commands/upload');
|
|
62
|
-
await uploadExternalSystem(systemKey,
|
|
63
|
+
await uploadExternalSystem(systemKey, buildMinimalUploadSyncOptions(options));
|
|
63
64
|
logger.log(formatSuccessLine('Sync complete'));
|
|
64
65
|
}
|
|
65
66
|
|
|
@@ -71,6 +72,40 @@ function loadDatasourceForAppExport(appKey, datasourceKey) {
|
|
|
71
72
|
return loadDatasourceForApp(appKey, datasourceKey, findDatasourceFileByKey);
|
|
72
73
|
}
|
|
73
74
|
|
|
75
|
+
/**
|
|
76
|
+
* @async
|
|
77
|
+
* @param {string} appKey
|
|
78
|
+
* @param {Object} options
|
|
79
|
+
* @returns {Promise<{ authConfig: Object, dataplaneUrl: string }>}
|
|
80
|
+
*/
|
|
81
|
+
async function resolveValidationAuth(appKey, options) {
|
|
82
|
+
if (options.authConfig && (options.dataplaneUrl || options.dataplane)) {
|
|
83
|
+
return {
|
|
84
|
+
authConfig: options.authConfig,
|
|
85
|
+
dataplaneUrl: options.dataplaneUrl || options.dataplane
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const configObj = await getConfig();
|
|
89
|
+
const auth = await setupIntegrationTestAuth(appKey, options, configObj);
|
|
90
|
+
return { authConfig: auth.authConfig, dataplaneUrl: auth.dataplaneUrl };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @async
|
|
95
|
+
* @param {string} datasourceKey
|
|
96
|
+
* @param {Object} options
|
|
97
|
+
* @returns {Promise<Object>}
|
|
98
|
+
*/
|
|
99
|
+
async function prepareValidationRunContext(datasourceKey, options) {
|
|
100
|
+
const runType = options.runType || 'test';
|
|
101
|
+
const { appKey } = await resolveAppKeyForDatasource(datasourceKey, options.app);
|
|
102
|
+
const systemKey = await getSystemKeyFromAppKey(appKey);
|
|
103
|
+
const { datasource } = loadDatasourceForAppExport(appKey, datasourceKey);
|
|
104
|
+
const { authConfig, dataplaneUrl } = await resolveValidationAuth(appKey, options);
|
|
105
|
+
await maybeSyncDatasourceToDataplane({ options, authConfig, systemKey });
|
|
106
|
+
return { runType, systemKey, datasource, authConfig, dataplaneUrl };
|
|
107
|
+
}
|
|
108
|
+
|
|
74
109
|
/**
|
|
75
110
|
* Run unified validation for one persisted datasource.
|
|
76
111
|
* @async
|
|
@@ -83,41 +118,35 @@ async function runUnifiedDatasourceValidation(datasourceKey, options) {
|
|
|
83
118
|
if (!datasourceKey || typeof datasourceKey !== 'string') {
|
|
84
119
|
throw new Error('Datasource key is required');
|
|
85
120
|
}
|
|
86
|
-
const runType = options.runType || 'test';
|
|
87
|
-
const { appKey } = await resolveAppKeyForDatasource(datasourceKey, options.app);
|
|
88
|
-
const systemKey = await getSystemKeyFromAppKey(appKey);
|
|
89
|
-
const { datasource } = loadDatasourceForAppExport(appKey, datasourceKey);
|
|
90
|
-
|
|
91
|
-
const configObj = await getConfig();
|
|
92
|
-
const { authConfig, dataplaneUrl } = await setupIntegrationTestAuth(appKey, options, configObj);
|
|
93
|
-
|
|
94
|
-
await maybeSyncDatasourceToDataplane({ options, authConfig, systemKey });
|
|
95
121
|
|
|
122
|
+
const ctx = await prepareValidationRunContext(datasourceKey, options);
|
|
96
123
|
const useAsync = options.noAsync ? false : options.async !== false;
|
|
97
124
|
const timeoutMs = parseInt(String(options.timeout || '30000'), 10) || 30000;
|
|
98
|
-
|
|
99
125
|
const body = await buildUnifiedValidationBody({
|
|
100
|
-
systemKey,
|
|
126
|
+
systemKey: ctx.systemKey,
|
|
101
127
|
datasourceKey,
|
|
102
|
-
runType,
|
|
103
|
-
datasource,
|
|
128
|
+
runType: ctx.runType,
|
|
129
|
+
datasource: ctx.datasource,
|
|
104
130
|
payloadPath: options.payload,
|
|
105
131
|
useAsync,
|
|
106
132
|
options
|
|
107
133
|
});
|
|
108
134
|
|
|
109
135
|
const result = await postValidationRunAndOptionalPoll({
|
|
110
|
-
dataplaneUrl,
|
|
111
|
-
authConfig,
|
|
136
|
+
dataplaneUrl: ctx.dataplaneUrl,
|
|
137
|
+
authConfig: ctx.authConfig,
|
|
112
138
|
body,
|
|
113
139
|
timeoutMs,
|
|
114
140
|
useAsync,
|
|
115
141
|
noAsync: options.noAsync === true || options.async === false,
|
|
116
|
-
verbosePoll: options.verbose === true
|
|
142
|
+
verbosePoll: options.verbose === true,
|
|
143
|
+
quietPollUi: options.quietPollUi === true,
|
|
144
|
+
pollSubject: datasourceKey,
|
|
145
|
+
onPollProgress: options.onPollProgress
|
|
117
146
|
});
|
|
118
147
|
|
|
119
148
|
if (result && result.envelope) {
|
|
120
|
-
annotateMissingAutoRbacPermissions(result.envelope, datasourceKey, datasource);
|
|
149
|
+
annotateMissingAutoRbacPermissions(result.envelope, datasourceKey, ctx.datasource);
|
|
121
150
|
}
|
|
122
151
|
return result;
|
|
123
152
|
}
|
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
const path = require('path');
|
|
12
12
|
const fs = require('fs');
|
|
13
13
|
const pathsUtil = require('../utils/paths');
|
|
14
|
+
const {
|
|
15
|
+
datasourceIdentifierMatchesFile,
|
|
16
|
+
pickIntegrationAppForDatasourceIdentifier,
|
|
17
|
+
collectDatasourceFileRefsMatchingIdentifier
|
|
18
|
+
} = require('./datasource-identifier');
|
|
14
19
|
const { loadExternalDataSourceSchema } = require('../utils/schema-loader');
|
|
15
20
|
const { formatValidationErrors } = require('../utils/error-formatter');
|
|
16
21
|
const { validateFieldReferences } = require('./field-reference-validator');
|
|
@@ -46,16 +51,13 @@ function tryResolveAsExistingFile(identifier) {
|
|
|
46
51
|
}
|
|
47
52
|
|
|
48
53
|
/**
|
|
49
|
-
* Pick integration app folder for a datasource
|
|
54
|
+
* Pick integration app folder for a datasource identifier (longest matching prefix wins).
|
|
50
55
|
* @param {string} datasourceKey
|
|
51
56
|
* @param {string[]} appNames
|
|
52
57
|
* @returns {string|null}
|
|
53
58
|
*/
|
|
54
59
|
function pickIntegrationAppForDatasourceKey(datasourceKey, appNames) {
|
|
55
|
-
|
|
56
|
-
if (matches.length === 0) return null;
|
|
57
|
-
matches.sort((a, b) => b.length - a.length);
|
|
58
|
-
return matches[0];
|
|
60
|
+
return pickIntegrationAppForDatasourceIdentifier(datasourceKey, appNames);
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
/**
|
|
@@ -94,7 +96,7 @@ function collectJsonPathsMatchingDatasourceKey(dir, scanOrder, datasourceKey) {
|
|
|
94
96
|
} catch {
|
|
95
97
|
continue;
|
|
96
98
|
}
|
|
97
|
-
if (
|
|
99
|
+
if (datasourceIdentifierMatchesFile(datasourceKey, name, parsed)) {
|
|
98
100
|
hits.push(full);
|
|
99
101
|
}
|
|
100
102
|
}
|
|
@@ -102,21 +104,12 @@ function collectJsonPathsMatchingDatasourceKey(dir, scanOrder, datasourceKey) {
|
|
|
102
104
|
}
|
|
103
105
|
|
|
104
106
|
/**
|
|
105
|
-
*
|
|
107
|
+
* @param {string} appName
|
|
106
108
|
* @param {string} datasourceKey
|
|
107
|
-
* @returns {string}
|
|
109
|
+
* @returns {string}
|
|
108
110
|
* @throws {Error}
|
|
109
111
|
*/
|
|
110
|
-
function
|
|
111
|
-
const appNames = pathsUtil.listIntegrationAppNames();
|
|
112
|
-
const appName = pickIntegrationAppForDatasourceKey(datasourceKey, appNames);
|
|
113
|
-
if (!appName) {
|
|
114
|
-
throw new Error(
|
|
115
|
-
`No integration/<app>/ folder matches datasource key "${datasourceKey}". ` +
|
|
116
|
-
'Pass a path to the JSON file, or use a key whose prefix matches an app under integration/ ' +
|
|
117
|
-
'(e.g. app test-e2e-hubspot for key test-e2e-hubspot-users).'
|
|
118
|
-
);
|
|
119
|
-
}
|
|
112
|
+
function resolvePathFromIntegrationFolderScan(appName, datasourceKey) {
|
|
120
113
|
const dir = pathsUtil.getIntegrationPath(appName);
|
|
121
114
|
if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) {
|
|
122
115
|
throw new Error(`Integration folder not found: ${dir}`);
|
|
@@ -128,16 +121,40 @@ function resolvePathFromIntegrationDatasourceKey(datasourceKey) {
|
|
|
128
121
|
const hits = collectJsonPathsMatchingDatasourceKey(dir, scanOrder, datasourceKey);
|
|
129
122
|
if (hits.length === 0) {
|
|
130
123
|
throw new Error(
|
|
131
|
-
`No datasource JSON
|
|
124
|
+
`No datasource JSON matching "${datasourceKey}" under integration/${appName}/. ` +
|
|
132
125
|
`Checked: ${scanOrder.length ? scanOrder.join(', ') : '(no JSON candidates)'}`
|
|
133
126
|
);
|
|
134
127
|
}
|
|
135
128
|
if (hits.length > 1) {
|
|
136
|
-
throw new Error(`Ambiguous: multiple files
|
|
129
|
+
throw new Error(`Ambiguous: multiple files match "${datasourceKey}": ${hits.join(', ')}`);
|
|
137
130
|
}
|
|
138
131
|
return hits[0];
|
|
139
132
|
}
|
|
140
133
|
|
|
134
|
+
/**
|
|
135
|
+
* Find integration JSON whose parsed `key` equals datasourceKey.
|
|
136
|
+
* @param {string} datasourceKey
|
|
137
|
+
* @returns {string} Absolute file path
|
|
138
|
+
* @throws {Error}
|
|
139
|
+
*/
|
|
140
|
+
function resolvePathFromIntegrationDatasourceKey(datasourceKey) {
|
|
141
|
+
const appNames = pathsUtil.listIntegrationAppNames();
|
|
142
|
+
const appName = pickIntegrationAppForDatasourceKey(datasourceKey, appNames);
|
|
143
|
+
if (!appName) {
|
|
144
|
+
throw new Error(
|
|
145
|
+
`No integration/<app>/ folder matches datasource identifier "${datasourceKey}". ` +
|
|
146
|
+
'Pass a path to the JSON file, or use a datasource key or filename whose prefix matches an app under integration/ ' +
|
|
147
|
+
'(e.g. test-e2e-hubspot-companies or test-e2e-hubspot-datasource-companies for app test-e2e-hubspot).'
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
const manifestHits = collectDatasourceFileRefsMatchingIdentifier(appName, datasourceKey);
|
|
151
|
+
if (manifestHits.length === 1) {
|
|
152
|
+
const dir = pathsUtil.getIntegrationPath(appName);
|
|
153
|
+
return path.join(dir, manifestHits[0]);
|
|
154
|
+
}
|
|
155
|
+
return resolvePathFromIntegrationFolderScan(appName, datasourceKey);
|
|
156
|
+
}
|
|
157
|
+
|
|
141
158
|
/**
|
|
142
159
|
* @param {string} identifier - File path or datasource `key`
|
|
143
160
|
* @returns {string} Absolute path to JSON file
|