@aifabrix/builder 2.45.0 → 2.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/cli-layout.mdc +2 -0
- package/.cursor/rules/cli-product-neutral.mdc +43 -0
- package/.cursor/rules/docs-rules.mdc +3 -1
- package/.cursor/rules/project-rules.mdc +1 -0
- package/README.md +43 -17
- package/integration/hubspot-test/wizard-hubspot-e2e.yaml +1 -1
- package/jest.config.default.js +2 -1
- package/jest.config.isolated.js +2 -1
- package/jest.global-live-fabrix-hooks.js +36 -0
- package/jest.isolated-projects.js +130 -0
- package/jest.projects.js +69 -121
- package/lib/api/agent-metadata-validation.api.js +93 -0
- package/lib/api/api-response-errors.js +124 -0
- package/lib/api/audit-api-helpers.js +68 -0
- package/lib/api/audit.api.js +119 -0
- package/lib/api/auth-cache.api.js +44 -0
- package/lib/api/certificates.api.js +4 -4
- package/lib/api/credential.api.js +2 -2
- package/lib/api/dataplane-health.api.js +137 -0
- package/lib/api/dataplane-sync.api.js +27 -0
- package/lib/api/datasources-core.api.js +21 -18
- package/lib/api/datasources-extended.api.js +22 -22
- package/lib/api/dimensions.api.js +3 -0
- package/lib/api/external-systems.api.js +13 -13
- package/lib/api/governance-scenario-pack.api.js +159 -0
- package/lib/api/governance-scenarios.api.js +39 -0
- package/lib/api/groups.api.js +79 -0
- package/lib/api/index.js +88 -5
- package/lib/api/lifecycle.api.js +77 -0
- package/lib/api/pipeline.api.js +7 -5
- package/lib/api/protection.api.js +157 -0
- package/lib/api/records-bulk.api.js +43 -0
- package/lib/api/records-search-parse.js +49 -0
- package/lib/api/records-search.api.js +29 -0
- package/lib/api/types/agent-metadata-validation.types.js +67 -0
- package/lib/api/types/audit.types.js +72 -0
- package/lib/api/types/dataplane-health.types.js +27 -0
- package/lib/api/types/dimensions.types.js +2 -0
- package/lib/api/types/governance-scenarios.types.js +39 -0
- package/lib/api/types/protection.types.js +69 -0
- package/lib/api/types/records-bulk.types.js +35 -0
- package/lib/api/types/records-search.types.js +28 -0
- package/lib/api/user-groups.api.js +50 -0
- package/lib/api/users.api.js +95 -0
- package/lib/api/validation-run.api.js +3 -3
- package/lib/api/validation-runner.js +5 -3
- package/lib/api/wizard-platform.api.js +3 -3
- package/lib/api/wizard.api.js +21 -21
- package/lib/app/deploy-config.js +4 -1
- package/lib/app/deploy.js +34 -19
- package/lib/app/down.js +20 -1
- package/lib/app/push.js +4 -5
- package/lib/app/register.js +7 -4
- package/lib/app/run-env-compose.js +84 -30
- package/lib/build/index.js +5 -0
- package/lib/certification/sync-system-certification.js +13 -6
- package/lib/cli/index.js +8 -2
- package/lib/cli/infra-guided-auth.js +109 -0
- package/lib/cli/infra-guided.js +91 -69
- package/lib/cli/setup-app.help.js +19 -2
- package/lib/cli/setup-app.js +58 -23
- package/lib/cli/setup-app.test-commands.js +28 -21
- package/lib/cli/setup-auth.js +55 -3
- package/lib/cli/setup-certification-commands.js +147 -0
- package/lib/cli/setup-certification.help.js +141 -0
- package/lib/cli/setup-environment.js +19 -2
- package/lib/cli/setup-external-system-help.js +62 -0
- package/lib/cli/setup-external-system.js +62 -6
- package/lib/cli/setup-infra.js +9 -1
- package/lib/cli/setup-platform.js +6 -1
- package/lib/cli/setup-secrets.js +33 -1
- package/lib/cli/setup-utility-help-after.js +65 -0
- package/lib/cli/setup-utility-repair.js +198 -0
- package/lib/cli/setup-utility-resolve.js +42 -6
- package/lib/cli/setup-utility-validate.js +197 -0
- package/lib/cli/setup-utility.js +41 -258
- package/lib/commands/auth-status-client-tokens.js +214 -0
- package/lib/commands/auth-status-dataplane-version.js +269 -0
- package/lib/commands/auth-status-display.js +94 -0
- package/lib/commands/auth-status.js +111 -53
- package/lib/commands/credential-push.js +10 -5
- package/lib/commands/datasource-load-export-cli.js +178 -0
- package/lib/commands/datasource-test-trust-cli.js +118 -0
- package/lib/commands/datasource-unified-test-cli.js +31 -20
- package/lib/commands/datasource-unified-test-cli.options.js +22 -3
- package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +5 -5
- package/lib/commands/datasource-verify-audit-cli.js +96 -0
- package/lib/commands/datasource.js +68 -1
- package/lib/commands/dev-show-display.js +8 -1
- package/lib/commands/dimension-value.js +43 -13
- package/lib/commands/dimension.js +38 -7
- package/lib/commands/governance-cli-shared.js +94 -0
- package/lib/commands/governance-command-action.js +132 -0
- package/lib/commands/governance-download-external.js +34 -0
- package/lib/commands/governance-generate-external.js +71 -0
- package/lib/commands/governance-upload-external.js +36 -0
- package/lib/commands/governance-verify-external.js +64 -0
- package/lib/commands/governance.js +144 -0
- package/lib/commands/identity-apply-sync.js +131 -0
- package/lib/commands/identity-group-cli.js +146 -0
- package/lib/commands/identity-membership-role-cache.js +175 -0
- package/lib/commands/identity-shared.js +94 -0
- package/lib/commands/identity-user-cli.js +158 -0
- package/lib/commands/identity.js +43 -0
- package/lib/commands/lifecycle-command-action.js +123 -0
- package/lib/commands/lifecycle-external.js +268 -0
- package/lib/commands/login.js +56 -17
- package/lib/commands/protection-cli-leaves.js +286 -0
- package/lib/commands/protection.js +50 -0
- package/lib/commands/repair-auth-apply.js +127 -0
- package/lib/commands/repair-changed-files.js +41 -0
- package/lib/commands/repair-datasource-keys.js +4 -1
- package/lib/commands/repair-datasource-run.js +59 -0
- package/lib/commands/repair-datasource-test-payload.js +259 -0
- package/lib/commands/repair-datasource.js +1 -51
- package/lib/commands/repair-env-template.js +64 -13
- package/lib/commands/repair-external-run.js +216 -0
- package/lib/commands/repair-openapi-sync.js +23 -0
- package/lib/commands/repair-persist.js +4 -0
- package/lib/commands/repair-rbac.js +52 -1
- package/lib/commands/repair-steps.js +145 -0
- package/lib/commands/repair.js +29 -286
- package/lib/commands/secrets-get.js +184 -0
- package/lib/commands/secrets-remove-all.js +3 -1
- package/lib/commands/setup-image-refresh.js +146 -0
- package/lib/commands/setup-modes.js +158 -162
- package/lib/commands/setup-platform-auth.js +76 -0
- package/lib/commands/setup-prompts-admin.js +244 -0
- package/lib/commands/setup-prompts-platform-mode.js +67 -0
- package/lib/commands/setup-prompts-validators.js +36 -0
- package/lib/commands/setup-prompts.js +24 -76
- package/lib/commands/setup-run-context.js +45 -0
- package/lib/commands/setup-spinners.js +39 -0
- package/lib/commands/setup.js +27 -5
- package/lib/commands/teardown.js +39 -0
- package/lib/commands/test-e2e-external.js +61 -14
- package/lib/commands/test-governance-cli-options.js +47 -0
- package/lib/commands/test-governance-external.js +67 -0
- package/lib/commands/test-trust-cli-options.js +32 -0
- package/lib/commands/test-trust-external.js +126 -0
- package/lib/commands/up-common.js +25 -13
- package/lib/commands/up-dataplane.js +50 -13
- package/lib/commands/upload-publish-context.js +75 -0
- package/lib/commands/upload-sidecar-followups.js +89 -0
- package/lib/commands/upload.js +108 -105
- package/lib/commands/verify-governance-combined-external.js +61 -0
- package/lib/commands/verify-governance-command-action.js +64 -0
- package/lib/commands/verify-governance-db.js +102 -0
- package/lib/commands/verify-governance-external.js +77 -0
- package/lib/commands/verify-governance-result-builders.js +71 -0
- package/lib/commands/verify-operations-command-action.js +68 -0
- package/lib/commands/verify-operations-external.js +268 -0
- package/lib/commands/verify-operations-persist.js +75 -0
- package/lib/commands/verify-operations-step-plan.js +68 -0
- package/lib/commands/verify-operations-steps.js +111 -0
- package/lib/commands/verify-trust-command-action.js +70 -0
- package/lib/commands/verify-trust-external.js +67 -0
- package/lib/commands/wizard-config-normalizer.js +43 -23
- package/lib/commands/wizard-core.js +5 -0
- package/lib/core/admin-password-generator.js +38 -0
- package/lib/core/admin-secrets-bundle.js +111 -0
- package/lib/core/admin-secrets-env-overlay.js +62 -0
- package/lib/core/admin-secrets.js +32 -4
- package/lib/core/config-attach-extensions.js +3 -0
- package/lib/core/config-device-dataplane.js +185 -0
- package/lib/core/config-platform-controller.js +44 -0
- package/lib/core/config-setup-installation-profile.js +42 -0
- package/lib/core/config-setup-platform-mode.js +46 -0
- package/lib/core/config.js +46 -36
- package/lib/core/secrets-admin-env.js +6 -2
- package/lib/core/secrets-ensure.js +4 -0
- package/lib/core/secrets-env-content.js +54 -48
- package/lib/core/secrets-env-write.js +10 -1
- package/lib/core/secrets-infra-placeholder-sync.js +2 -0
- package/lib/core/setup-installation-profile.js +43 -0
- package/lib/core/setup-platform-mode.js +55 -0
- package/lib/datasource/agent-trust-debug-log.js +45 -0
- package/lib/datasource/agent-trust-fetch.js +115 -0
- package/lib/datasource/agent-trust-map.js +101 -0
- package/lib/datasource/agent-trust-mock.js +44 -0
- package/lib/datasource/agent-trust-run.js +95 -0
- package/lib/datasource/agent-trust-timeout.js +25 -0
- package/lib/datasource/audit-evidence-display.js +80 -0
- package/lib/datasource/audit-evidence-extract-debug.js +115 -0
- package/lib/datasource/audit-evidence-extract.js +180 -0
- package/lib/datasource/audit-evidence-matrix-rows.js +158 -0
- package/lib/datasource/audit-evidence-operation-aliases.js +63 -0
- package/lib/datasource/audit-evidence-poll.js +109 -0
- package/lib/datasource/audit-evidence-run.js +177 -0
- package/lib/datasource/audit-evidence-verify-helpers.js +167 -0
- package/lib/datasource/audit-evidence-verify-matrix.js +205 -0
- package/lib/datasource/audit-evidence-verify.js +108 -0
- package/lib/datasource/bulk-loader-run-batches.js +100 -0
- package/lib/datasource/bulk-loader-service-retry.js +52 -0
- package/lib/datasource/bulk-loader-service.js +127 -0
- package/lib/datasource/capability/run-capability-dimension.js +2 -1
- package/lib/datasource/datasource-exporter-resolve.js +82 -0
- package/lib/datasource/datasource-exporter-service.js +144 -0
- package/lib/datasource/datasource-identifier.js +148 -0
- package/lib/datasource/datasource-load-export-context.js +95 -0
- package/lib/datasource/integration-context.js +6 -4
- package/lib/datasource/local-data-paths.js +145 -0
- package/lib/datasource/log-cleaner.js +241 -0
- package/lib/datasource/log-viewer.js +111 -6
- package/lib/datasource/record-file-parser.js +85 -0
- package/lib/datasource/record-mapper.js +129 -0
- package/lib/datasource/resolve-app.js +74 -55
- package/lib/datasource/test-e2e.js +29 -2
- package/lib/datasource/unified-validation-run-body.js +3 -1
- package/lib/datasource/unified-validation-run-resolve.js +45 -12
- package/lib/datasource/unified-validation-run.js +47 -18
- package/lib/datasource/validate.js +37 -20
- package/lib/deployment/environment-poll-status.js +138 -0
- package/lib/deployment/environment.js +42 -34
- package/lib/external-system/download.js +21 -20
- package/lib/external-system/generator.js +5 -1
- package/lib/external-system/integration-auth-context.js +45 -0
- package/lib/external-system/test-auth.js +12 -5
- package/lib/external-system/test-system-level.js +25 -4
- package/lib/external-system/test.js +9 -7
- package/lib/generator/external-controller-manifest.js +15 -0
- package/lib/governance/governance-cli-errors.js +96 -0
- package/lib/governance/governance-download-display.js +38 -0
- package/lib/governance/governance-pack-loader.js +70 -0
- package/lib/governance/governance-run-display.js +309 -0
- package/lib/identity/identity-apply-core.js +108 -0
- package/lib/identity/identity-apply-phases.js +244 -0
- package/lib/identity/identity-apply-service.js +77 -0
- package/lib/identity/identity-csv-parser.js +114 -0
- package/lib/infrastructure/admin-secrets-apply.js +84 -0
- package/lib/infrastructure/admin-secrets-ensure.js +130 -0
- package/lib/infrastructure/admin-secrets-resolve.js +95 -0
- package/lib/infrastructure/admin-secrets-sync.js +91 -0
- package/lib/infrastructure/helpers.js +23 -129
- package/lib/infrastructure/index.js +5 -6
- package/lib/infrastructure/orphan-infra-docker-teardown.js +11 -5
- package/lib/internal/fs-real-sync.js +29 -1
- package/lib/lifecycle/certification-progress.js +231 -0
- package/lib/lifecycle/dataplane-ui-url.js +145 -0
- package/lib/lifecycle/exit-codes.js +24 -0
- package/lib/lifecycle/json-envelope.js +25 -0
- package/lib/lifecycle/lifecycle-governance-options.js +51 -0
- package/lib/lifecycle/logger-quiet.js +29 -0
- package/lib/lifecycle/open-api-published.js +59 -0
- package/lib/lifecycle/operations-readiness-metrics.js +101 -0
- package/lib/lifecycle/product-model.js +196 -0
- package/lib/lifecycle/report-display.js +471 -0
- package/lib/lifecycle/scenario-upload.js +191 -0
- package/lib/lifecycle/verify-step-progress.js +87 -0
- package/lib/parameters/infra-kv-discovery.js +27 -2
- package/lib/protection/auth-context.js +51 -0
- package/lib/protection/convert-batch.js +90 -0
- package/lib/protection/load.js +41 -0
- package/lib/protection/paths.js +158 -0
- package/lib/protection/preflight-datasource-ready.js +46 -0
- package/lib/protection/protection-create-probe-lines.js +142 -0
- package/lib/protection/protection-create-probes.js +95 -0
- package/lib/protection/protection-create-scaffold.js +281 -0
- package/lib/protection/protection-display-helpers.js +445 -0
- package/lib/protection/protection-display.js +215 -0
- package/lib/protection/protection-preset-registry.js +97 -0
- package/lib/protection/report-exit.js +62 -0
- package/lib/protection/resolve.js +202 -0
- package/lib/protection/run-commands-validate.js +130 -0
- package/lib/protection/run-commands.js +216 -0
- package/lib/protection/run-protection-create-helpers.js +134 -0
- package/lib/protection/run-protection-create-probes-flow.js +43 -0
- package/lib/protection/run-protection-create.js +191 -0
- package/lib/protection/scope.js +22 -0
- package/lib/protection/sync-after-upload.js +64 -0
- package/lib/protection/upload-batch.js +127 -0
- package/lib/protection/validate-batch.js +113 -0
- package/lib/protection/validate-local.js +65 -0
- package/lib/resolvers/dimension-file.js +29 -4
- package/lib/schema/application-schema.json +1 -1
- package/lib/schema/datasource-test-run.schema.json +89 -6
- package/lib/schema/external-datasource.schema.json +2636 -2588
- package/lib/schema/external-system.schema.json +1089 -761
- package/lib/schema/flag-map-validation-run.json +2 -2
- package/lib/schema/infra.parameter.yaml +45 -0
- package/lib/schema/protection.schema.json +374 -0
- package/lib/schema/type/credential-field-registry.json +642 -0
- package/lib/schema/wizard-config.schema.json +1 -1
- package/lib/utils/agent-trust-run-display.js +231 -0
- package/lib/utils/agent-trust-run-exit.js +59 -0
- package/lib/utils/agent-trust-wait-ui.js +94 -0
- package/lib/utils/aifabrix-test-runtime-guard.js +125 -0
- package/lib/utils/api.js +55 -31
- package/lib/utils/app-relative-path-env.js +112 -0
- package/lib/utils/cli-exit-codes.js +30 -0
- package/lib/utils/cli-secrets-error-format.js +83 -21
- package/lib/utils/cli-sync-options.js +33 -0
- package/lib/utils/cli-utils.js +16 -4
- package/lib/utils/compose-generate-docker-compose.js +4 -0
- package/lib/utils/compose-traefik-ingress-base.js +16 -1
- package/lib/utils/config-secrets-path.js +46 -0
- package/lib/utils/controller-url.js +88 -1
- package/lib/utils/credential-push-ui.js +90 -0
- package/lib/utils/credential-secrets-env.js +137 -9
- package/lib/utils/dataplane-cli-version-gate.js +202 -0
- package/lib/utils/dataplane-cli-version-help.js +74 -0
- package/lib/utils/dataplane-resolver.js +129 -2
- package/lib/utils/datasource-export-display.js +137 -0
- package/lib/utils/datasource-load-display.js +174 -0
- package/lib/utils/datasource-load-export-ui.js +120 -0
- package/lib/utils/datasource-test-run-capability-scope.js +3 -3
- package/lib/utils/datasource-test-run-display.js +3 -3
- package/lib/utils/datasource-test-run-tty-log.js +5 -1
- package/lib/utils/declarative-url-ports.js +3 -3
- package/lib/utils/deployment-auth-mode.js +41 -0
- package/lib/utils/developer-volume-id.js +33 -0
- package/lib/utils/env-copy.js +14 -9
- package/lib/utils/env-kv-orphan-lines.js +43 -0
- package/lib/utils/error-formatters/network-errors.js +13 -4
- package/lib/utils/external-env-template.js +1 -0
- package/lib/utils/external-system-readiness-core.js +10 -0
- package/lib/utils/external-system-readiness-display.js +80 -23
- package/lib/utils/health-check.js +4 -1
- package/lib/utils/help-builder.js +35 -26
- package/lib/utils/keycloak-realm-ready.js +101 -0
- package/lib/utils/load-cip-capacity-display-config.js +61 -15
- package/lib/utils/manifest-source-emit.js +24 -0
- package/lib/utils/pipeline-upload-auth-retry.js +82 -0
- package/lib/utils/platform-controller-url.js +156 -0
- package/lib/utils/postgres-platform-bootstrap.js +199 -0
- package/lib/utils/postgres-wipe.js +9 -2
- package/lib/utils/resolve-env-mode.js +47 -0
- package/lib/utils/secrets-generator.js +31 -25
- package/lib/utils/secrets-missing-error.js +164 -0
- package/lib/utils/semver-compare.js +127 -0
- package/lib/utils/service-url-label.js +81 -0
- package/lib/utils/setup-quiet-output.js +25 -0
- package/lib/utils/template-helpers.js +15 -0
- package/lib/utils/token-manager-client-credentials.js +201 -0
- package/lib/utils/token-manager-messages.js +8 -0
- package/lib/utils/token-manager-refresh.js +12 -2
- package/lib/utils/token-manager.js +86 -105
- package/lib/utils/upload-pipeline-ui.js +98 -0
- package/lib/utils/upload-sync-options.js +42 -0
- package/lib/utils/url-declarative-public-base.js +21 -3
- package/lib/utils/url-declarative-vdir-inactive-env.js +14 -4
- package/lib/utils/validation-poll-ui.js +22 -7
- package/lib/utils/validation-run-stage.js +45 -0
- package/lib/validation/wizard-config-validator.js +58 -19
- package/package.json +1 -1
- package/templates/applications/dataplane/application.yaml +2 -1
- package/templates/applications/dataplane/env.template +36 -1
- package/templates/applications/dataplane/rbac.yaml +4 -0
- package/templates/applications/miso-controller/env.template +16 -0
- package/templates/external-system/README.md.hbs +116 -11
- package/templates/python/docker-compose.hbs +19 -18
- package/templates/typescript/docker-compose.hbs +18 -17
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview TTY display for `datasource export` (plan 144)
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const logger = require('./logger');
|
|
11
|
+
const {
|
|
12
|
+
sectionTitle,
|
|
13
|
+
headerKeyValue,
|
|
14
|
+
metadata: metaGray,
|
|
15
|
+
formatSuccessLine,
|
|
16
|
+
formatWarningLine
|
|
17
|
+
} = require('./cli-test-layout-chalk');
|
|
18
|
+
const { emitManifestSourceMetadata } = require('./manifest-source-emit');
|
|
19
|
+
const { integrationManifestLabel } = require('../datasource/datasource-load-export-context');
|
|
20
|
+
const { formatElapsedMs } = require('./datasource-load-export-ui');
|
|
21
|
+
|
|
22
|
+
const SEP = '────────────────────────────────────────────────────────';
|
|
23
|
+
|
|
24
|
+
function logExportHeader(ctx, envLabel) {
|
|
25
|
+
logger.log(SEP);
|
|
26
|
+
logger.log(sectionTitle(`Export records — ${ctx.datasourceKey}`));
|
|
27
|
+
logger.log(headerKeyValue('Environment:', envLabel || '—'));
|
|
28
|
+
logger.log(headerKeyValue('System:', ctx.systemKey));
|
|
29
|
+
logger.log(SEP);
|
|
30
|
+
logger.log(metaGray(' Layer: governed records search (ABAC applied)'));
|
|
31
|
+
logger.log(metaGray(' Not used: direct database access'));
|
|
32
|
+
logger.log('');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function logExportVerboseStats(result) {
|
|
36
|
+
const excluded = result.meta?.excluded || {};
|
|
37
|
+
const abac = excluded.abac !== undefined && excluded.abac !== null ? excluded.abac : 0;
|
|
38
|
+
const filterEx =
|
|
39
|
+
excluded.filter !== undefined && excluded.filter !== null ? excluded.filter : 0;
|
|
40
|
+
logger.log(
|
|
41
|
+
metaGray(
|
|
42
|
+
` Fetched: ${result.recordCount} records · excluded abac ${abac} · filter ${filterEx}`
|
|
43
|
+
)
|
|
44
|
+
);
|
|
45
|
+
const stat = fs.statSync(result.outputFile);
|
|
46
|
+
const mb = (stat.size / (1024 * 1024)).toFixed(2);
|
|
47
|
+
logger.log(
|
|
48
|
+
metaGray(` Wrote: ${result.recordCount} line(s) (${result.format}) · ${mb} MB`)
|
|
49
|
+
);
|
|
50
|
+
logger.log('');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @param {Object} result
|
|
55
|
+
*/
|
|
56
|
+
function displayExportAbacZeroRowsWarning(result) {
|
|
57
|
+
const excludedAbac = Number(result.excludedAbac ?? result.meta?.excluded?.abac) || 0;
|
|
58
|
+
if (result.recordCount !== 0 || excludedAbac <= 0) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
logger.log(
|
|
62
|
+
formatWarningLine(
|
|
63
|
+
`Governed search returned 0 rows; ABAC excluded ${excludedAbac} record(s) for your principal.`
|
|
64
|
+
)
|
|
65
|
+
);
|
|
66
|
+
logger.log(
|
|
67
|
+
metaGray(
|
|
68
|
+
' The physical table may still hold data — export only includes rows your token may read.'
|
|
69
|
+
)
|
|
70
|
+
);
|
|
71
|
+
logger.log(
|
|
72
|
+
metaGray(
|
|
73
|
+
' Fix: upload a protection manifest (aifabrix protection upload <datasourceKey>) with dimension grants for your user, then retry.'
|
|
74
|
+
)
|
|
75
|
+
);
|
|
76
|
+
logger.log('');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @param {Object} result
|
|
81
|
+
*/
|
|
82
|
+
function displayExportLimitCapWarning(result) {
|
|
83
|
+
if (!result.hitLimitCap) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
logger.log(
|
|
87
|
+
formatWarningLine(`Fetched ${result.recordCount} records (limit cap). More rows may exist.`)
|
|
88
|
+
);
|
|
89
|
+
logger.log(metaGray(' Re-run with --filter or wait for dataplane search pagination.'));
|
|
90
|
+
logger.log('');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @param {Object} result
|
|
95
|
+
*/
|
|
96
|
+
function logExportDurationFooter(result) {
|
|
97
|
+
if (result.durationMs === undefined || result.durationMs === null) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
logger.log(metaGray(` Completed in ${formatElapsedMs(result.durationMs)}`));
|
|
101
|
+
logger.log('');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @param {Object} result
|
|
106
|
+
* @param {Object} opts
|
|
107
|
+
*/
|
|
108
|
+
function displayDatasourceExportTTY(result, opts = {}) {
|
|
109
|
+
const ctx = result.context || {};
|
|
110
|
+
logExportHeader(ctx, opts.environment);
|
|
111
|
+
|
|
112
|
+
const filterLabel = result.filters ? 'filters (set)' : 'filters (none)';
|
|
113
|
+
logger.log(
|
|
114
|
+
metaGray(` Search: intent ${result.intent} · limit ${result.limit} · ${filterLabel}`)
|
|
115
|
+
);
|
|
116
|
+
emitManifestSourceMetadata({
|
|
117
|
+
tier: 'int',
|
|
118
|
+
configPath: ctx.manifestPath,
|
|
119
|
+
labelPrefix: integrationManifestLabel(ctx.appKey)
|
|
120
|
+
});
|
|
121
|
+
logger.log(metaGray(` Output: ${result.outputFile}`));
|
|
122
|
+
logger.log('');
|
|
123
|
+
|
|
124
|
+
if (opts.verbose) {
|
|
125
|
+
logExportVerboseStats(result);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
displayExportAbacZeroRowsWarning(result);
|
|
129
|
+
displayExportLimitCapWarning(result);
|
|
130
|
+
logger.log(formatSuccessLine('Export complete'));
|
|
131
|
+
logExportDurationFooter(result);
|
|
132
|
+
logger.log(SEP);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
module.exports = {
|
|
136
|
+
displayDatasourceExportTTY
|
|
137
|
+
};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview TTY display for `datasource load` (plan 144)
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const chalk = require('chalk');
|
|
10
|
+
const logger = require('./logger');
|
|
11
|
+
const {
|
|
12
|
+
sectionTitle,
|
|
13
|
+
headerKeyValue,
|
|
14
|
+
metadata: metaGray,
|
|
15
|
+
formatSuccessLine,
|
|
16
|
+
formatBlockingError,
|
|
17
|
+
successGlyph,
|
|
18
|
+
failureGlyph
|
|
19
|
+
} = require('./cli-test-layout-chalk');
|
|
20
|
+
const { emitManifestSourceMetadata } = require('./manifest-source-emit');
|
|
21
|
+
const { integrationManifestLabel } = require('../datasource/datasource-load-export-context');
|
|
22
|
+
const { formatElapsedMs } = require('./datasource-load-export-ui');
|
|
23
|
+
|
|
24
|
+
const SEP = '────────────────────────────────────────────────────────';
|
|
25
|
+
|
|
26
|
+
function logLoadHeader(ctx, envLabel) {
|
|
27
|
+
logger.log(SEP);
|
|
28
|
+
logger.log(sectionTitle(`Load records — ${ctx.datasourceKey}`));
|
|
29
|
+
logger.log(headerKeyValue('Environment:', envLabel || '—'));
|
|
30
|
+
logger.log(headerKeyValue('System:', ctx.systemKey));
|
|
31
|
+
logger.log(SEP);
|
|
32
|
+
logger.log(metaGray(' Layer: dataplane bulk sync'));
|
|
33
|
+
emitManifestSourceMetadata({
|
|
34
|
+
tier: 'int',
|
|
35
|
+
configPath: ctx.manifestPath,
|
|
36
|
+
labelPrefix: integrationManifestLabel(ctx.appKey)
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function displayLoadDryRun(result) {
|
|
41
|
+
logger.log(chalk.cyan(' Mode: dry-run (no upload)'));
|
|
42
|
+
logger.log('');
|
|
43
|
+
const mb = (result.estimatedPayloadBytes / (1024 * 1024)).toFixed(2);
|
|
44
|
+
const batchCount = Math.ceil(result.recordCount / result.batchSize) || 0;
|
|
45
|
+
logger.log(
|
|
46
|
+
metaGray(
|
|
47
|
+
` Parsed: ${result.recordCount} records · format ${result.format} · est. payload ~${mb} MB`
|
|
48
|
+
)
|
|
49
|
+
);
|
|
50
|
+
logger.log(
|
|
51
|
+
metaGray(` Would upload: ${batchCount} batch(es) · syncType ${result.syncType}`)
|
|
52
|
+
);
|
|
53
|
+
logger.log('');
|
|
54
|
+
logger.log(formatSuccessLine('Dry-run passed'));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function displayLoadBatchesVerbose(batches) {
|
|
58
|
+
batches.forEach(batch => {
|
|
59
|
+
if (batch.error) {
|
|
60
|
+
logger.log(
|
|
61
|
+
` Batch ${batch.index}/${batch.total} ${failureGlyph()} failed (${batch.error})`
|
|
62
|
+
);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const failed = Array.isArray(batch.failed) ? batch.failed.length : 0;
|
|
66
|
+
if (failed > 0) {
|
|
67
|
+
logger.log(
|
|
68
|
+
` Batch ${batch.index}/${batch.total} ${failureGlyph()} failed ${failed} of ${batch.recordCount || '?'}`
|
|
69
|
+
);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
logger.log(
|
|
73
|
+
` Batch ${batch.index}/${batch.total} ${successGlyph()} inserted ${batch.insertedCount || 0} · updated ${batch.updatedCount || 0} · failed 0`
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const MAX_FAILURE_LINES = 5;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @param {Object[]} batches
|
|
82
|
+
*/
|
|
83
|
+
function displayLoadFailureSamples(batches) {
|
|
84
|
+
const samples = [];
|
|
85
|
+
(batches || []).forEach(batch => {
|
|
86
|
+
if (!Array.isArray(batch.failed)) return;
|
|
87
|
+
batch.failed.forEach(item => {
|
|
88
|
+
if (samples.length >= MAX_FAILURE_LINES) return;
|
|
89
|
+
const key = item.key ? String(item.key) : '—';
|
|
90
|
+
const message = item.message || batch.error || 'failed';
|
|
91
|
+
samples.push({ key, message });
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
if (samples.length === 0) return;
|
|
95
|
+
logger.log('');
|
|
96
|
+
logger.log(chalk.white(` Failures (first ${MAX_FAILURE_LINES})`));
|
|
97
|
+
samples.forEach(({ key, message }) => {
|
|
98
|
+
logger.log(` • ${key} — ${message}`);
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function displayLoadVerdict(result) {
|
|
103
|
+
const failed = result.totals.failedCount || 0;
|
|
104
|
+
const ok = result.recordCount - failed;
|
|
105
|
+
if (failed > 0) {
|
|
106
|
+
if (result.batches && result.batches.length > 0) {
|
|
107
|
+
displayLoadFailureSamples(result.batches);
|
|
108
|
+
logger.log('');
|
|
109
|
+
}
|
|
110
|
+
logger.log(formatBlockingError(`${ok} ok · ${failed} failed`));
|
|
111
|
+
} else {
|
|
112
|
+
logger.log(
|
|
113
|
+
formatSuccessLine(
|
|
114
|
+
`${result.recordCount} processed · ${result.totals.insertedCount} inserted · ${result.totals.updatedCount} updated · 0 failed`
|
|
115
|
+
)
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @param {Object} result
|
|
122
|
+
*/
|
|
123
|
+
function logLoadDurationFooter(result) {
|
|
124
|
+
if (result.durationMs === undefined || result.durationMs === null) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
logger.log(metaGray(` Completed in ${formatElapsedMs(result.durationMs)}`));
|
|
128
|
+
logger.log('');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* @param {Object} result
|
|
133
|
+
* @param {Object} opts
|
|
134
|
+
*/
|
|
135
|
+
function displayLoadUploadSummary(result, opts) {
|
|
136
|
+
const batchCount = Math.ceil(result.recordCount / result.batchSize) || 0;
|
|
137
|
+
logger.log(
|
|
138
|
+
metaGray(
|
|
139
|
+
` Parsed: ${result.recordCount} records · format ${result.format} · est. ${batchCount} batch(es) @ ${result.batchSize}`
|
|
140
|
+
)
|
|
141
|
+
);
|
|
142
|
+
logger.log('');
|
|
143
|
+
if (opts.verbose) {
|
|
144
|
+
displayLoadBatchesVerbose(result.batches);
|
|
145
|
+
logger.log('');
|
|
146
|
+
}
|
|
147
|
+
displayLoadVerdict(result);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* @param {Object} result
|
|
152
|
+
* @param {Object} opts
|
|
153
|
+
*/
|
|
154
|
+
function displayDatasourceLoadTTY(result, opts = {}) {
|
|
155
|
+
const ctx = result.context || {};
|
|
156
|
+
logLoadHeader(ctx, opts.environment);
|
|
157
|
+
logger.log(metaGray(` Data file: ${result.file}`));
|
|
158
|
+
logger.log('');
|
|
159
|
+
|
|
160
|
+
if (result.dryRun) {
|
|
161
|
+
displayLoadDryRun(result);
|
|
162
|
+
logLoadDurationFooter(result);
|
|
163
|
+
logger.log(SEP);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
displayLoadUploadSummary(result, opts);
|
|
168
|
+
logLoadDurationFooter(result);
|
|
169
|
+
logger.log(SEP);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
module.exports = {
|
|
173
|
+
displayDatasourceLoadTTY
|
|
174
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Spinner + elapsed time for datasource load/export (plan 144)
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const chalk = require('chalk');
|
|
10
|
+
const logger = require('./logger');
|
|
11
|
+
const { formatProgress } = require('./cli-test-layout-chalk');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {number} ms
|
|
15
|
+
* @returns {string}
|
|
16
|
+
*/
|
|
17
|
+
function formatElapsedMs(ms) {
|
|
18
|
+
const n = Math.max(0, Math.round(Number(ms) || 0));
|
|
19
|
+
if (n < 1000) {
|
|
20
|
+
return `${n} ms`;
|
|
21
|
+
}
|
|
22
|
+
if (n < 60000) {
|
|
23
|
+
const sec = n / 1000;
|
|
24
|
+
return sec >= 10 ? `${Math.round(sec)} s` : `${sec.toFixed(1)} s`;
|
|
25
|
+
}
|
|
26
|
+
const min = Math.floor(n / 60000);
|
|
27
|
+
const sec = Math.round((n % 60000) / 1000);
|
|
28
|
+
return sec > 0 ? `${min} m ${sec} s` : `${min} m`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {Object} [options]
|
|
33
|
+
* @param {boolean} [options.json]
|
|
34
|
+
* @returns {boolean}
|
|
35
|
+
*/
|
|
36
|
+
function shouldShowDatasourceLoadExportProgress(options = {}) {
|
|
37
|
+
return options.json !== true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {Object} [options]
|
|
42
|
+
* @returns {boolean}
|
|
43
|
+
*/
|
|
44
|
+
function shouldUseDatasourceLoadExportSpinner(options = {}) {
|
|
45
|
+
if (!shouldShowDatasourceLoadExportProgress(options)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
return Boolean(process && process.stdout && process.stdout.isTTY);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @param {string} operation
|
|
53
|
+
* @param {string} datasourceKey
|
|
54
|
+
* @returns {string}
|
|
55
|
+
*/
|
|
56
|
+
function buildDatasourceLoadExportSpinnerLabel(operation, datasourceKey) {
|
|
57
|
+
const key =
|
|
58
|
+
datasourceKey && String(datasourceKey).trim() ? String(datasourceKey).trim() : 'datasource';
|
|
59
|
+
if (operation === 'export') {
|
|
60
|
+
return `Exporting records for ${key}…`;
|
|
61
|
+
}
|
|
62
|
+
if (operation === 'load-dry-run') {
|
|
63
|
+
return `Parsing records for ${key}…`;
|
|
64
|
+
}
|
|
65
|
+
return `Loading records for ${key} into dataplane…`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @param {string} operation
|
|
70
|
+
* @param {string} datasourceKey
|
|
71
|
+
* @returns {string}
|
|
72
|
+
*/
|
|
73
|
+
function buildDatasourceLoadExportProgressText(operation, datasourceKey) {
|
|
74
|
+
return formatProgress(buildDatasourceLoadExportSpinnerLabel(operation, datasourceKey));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @async
|
|
79
|
+
* @param {Function} work
|
|
80
|
+
* @param {Object} [opts]
|
|
81
|
+
* @param {'load'|'load-dry-run'|'export'} [opts.operation]
|
|
82
|
+
* @param {string} [opts.datasourceKey]
|
|
83
|
+
* @param {boolean} [opts.json]
|
|
84
|
+
* @returns {Promise<*>}
|
|
85
|
+
*/
|
|
86
|
+
async function runWithDatasourceLoadExportSpinner(work, opts = {}) {
|
|
87
|
+
if (!shouldShowDatasourceLoadExportProgress(opts)) {
|
|
88
|
+
return work();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const operation = opts.operation || 'load';
|
|
92
|
+
const datasourceKey = opts.datasourceKey || '';
|
|
93
|
+
|
|
94
|
+
if (!shouldUseDatasourceLoadExportSpinner(opts)) {
|
|
95
|
+
logger.log(buildDatasourceLoadExportProgressText(operation, datasourceKey));
|
|
96
|
+
return work();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const ora = require('ora');
|
|
100
|
+
const label = buildDatasourceLoadExportSpinnerLabel(operation, datasourceKey);
|
|
101
|
+
const spinner = ora({
|
|
102
|
+
text: chalk.white(label),
|
|
103
|
+
spinner: 'dots'
|
|
104
|
+
}).start();
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
return await work();
|
|
108
|
+
} finally {
|
|
109
|
+
spinner.stop();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
module.exports = {
|
|
114
|
+
formatElapsedMs,
|
|
115
|
+
shouldShowDatasourceLoadExportProgress,
|
|
116
|
+
shouldUseDatasourceLoadExportSpinner,
|
|
117
|
+
buildDatasourceLoadExportSpinnerLabel,
|
|
118
|
+
buildDatasourceLoadExportProgressText,
|
|
119
|
+
runWithDatasourceLoadExportSpinner
|
|
120
|
+
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview Single-capability CLI contract when
|
|
2
|
+
* @fileoverview Single-capability CLI contract when positional [capabilityKey] is set.
|
|
3
3
|
* @author AI Fabrix Team
|
|
4
4
|
* @version 2.0.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @param {Object|null|undefined} envelope - DatasourceTestRun-like
|
|
9
|
-
* @param {string|undefined|null} requestedCapabilityKey - From
|
|
9
|
+
* @param {string|undefined|null} requestedCapabilityKey - From positional [capabilityKey]
|
|
10
10
|
* @returns {{ violated: boolean, message?: string, count?: number }}
|
|
11
11
|
*/
|
|
12
12
|
function analyzeCapabilityScope(envelope, requestedCapabilityKey) {
|
|
@@ -34,7 +34,7 @@ function analyzeCapabilityScope(envelope, requestedCapabilityKey) {
|
|
|
34
34
|
return {
|
|
35
35
|
violated: true,
|
|
36
36
|
count: caps.length,
|
|
37
|
-
message: `Capabilities scope: with
|
|
37
|
+
message: `Capabilities scope: with capabilityKey "${key}", expected a single row in capabilities[]; server returned ${caps.length} (${preview}${suffix}).`
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -98,7 +98,7 @@ function colorStepLine(ok, body) {
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
/**
|
|
101
|
-
* Normalize
|
|
101
|
+
* Normalize positional [capabilityKey] for matching envelope.capabilities[].key
|
|
102
102
|
* @param {*} focusCapabilityKey
|
|
103
103
|
* @returns {string} trimmed or ''
|
|
104
104
|
*/
|
|
@@ -354,7 +354,7 @@ function pickExecutiveVerdictLine(envelope) {
|
|
|
354
354
|
}
|
|
355
355
|
|
|
356
356
|
/**
|
|
357
|
-
* Plan §3.9: explicit line when E2E has no capability rows (skipped when
|
|
357
|
+
* Plan §3.9: explicit line when E2E has no capability rows (skipped when capability drill-down is active).
|
|
358
358
|
* @param {string[]} lines
|
|
359
359
|
* @param {Object} envelope
|
|
360
360
|
* @param {{ focusCapabilityKey?: string }} [options]
|
|
@@ -428,7 +428,7 @@ function formatDatasourceTestRunSummary(envelope, options = {}) {
|
|
|
428
428
|
* focusCapabilityKey?: string,
|
|
429
429
|
* includeRefs?: boolean,
|
|
430
430
|
* includeDebugExecutionSummary?: boolean
|
|
431
|
-
* }} [options] - When focusCapabilityKey set (
|
|
431
|
+
* }} [options] - When focusCapabilityKey set (positional [capabilityKey]), append single-cap block (plan §2.3).
|
|
432
432
|
* includeDebugExecutionSummary: show dataplane `debug.executionSummary` in header (TTY debug appendix uses CLI `--debug`).
|
|
433
433
|
* @returns {string}
|
|
434
434
|
*/
|
|
@@ -49,7 +49,11 @@ function printDatasourceTestRunForTTY(envelope, options = {}) {
|
|
|
49
49
|
includeDebugExecutionSummary: Boolean(mode)
|
|
50
50
|
};
|
|
51
51
|
if (options.json) {
|
|
52
|
-
|
|
52
|
+
const payload =
|
|
53
|
+
options.auditEvidenceVerification && typeof options.auditEvidenceVerification === 'object'
|
|
54
|
+
? { ...envelope, auditEvidenceVerification: options.auditEvidenceVerification }
|
|
55
|
+
: envelope;
|
|
56
|
+
logger.log(JSON.stringify(payload));
|
|
53
57
|
return;
|
|
54
58
|
}
|
|
55
59
|
if (options.summary) {
|
|
@@ -21,7 +21,7 @@ function parseDeveloperIdNum(raw) {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
*
|
|
24
|
+
* Host port for compose publish, localhost URLs, and health checks: port + devId×100 (dev 0 → base port).
|
|
25
25
|
* @param {number} appPort - Manifest listen port
|
|
26
26
|
* @param {number} developerIdNum
|
|
27
27
|
* @returns {number}
|
|
@@ -31,13 +31,13 @@ function publishedHostPort(appPort, developerIdNum) {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
34
|
+
* Same as {@link publishedHostPort} (legacy name kept for call sites).
|
|
35
35
|
* @param {number} appPort
|
|
36
36
|
* @param {number} developerIdNum
|
|
37
37
|
* @returns {number}
|
|
38
38
|
*/
|
|
39
39
|
function localHostPort(appPort, developerIdNum) {
|
|
40
|
-
return appPort
|
|
40
|
+
return publishedHostPort(appPort, developerIdNum);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
module.exports = {
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deployment auth mode for pipeline publish / external integration CLI.
|
|
3
|
+
* @fileoverview AIFABRIX_DEPLOYMENT_AUTH and options.deploymentAuth parsing
|
|
4
|
+
* @author AI Fabrix Team
|
|
5
|
+
* @version 1.0.0
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {'auto'|'client-credentials'|'device'} DeploymentAuthMode
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {Object} [options] - CLI or caller options
|
|
16
|
+
* @returns {DeploymentAuthMode}
|
|
17
|
+
*/
|
|
18
|
+
function getDeploymentAuthMode(options = {}) {
|
|
19
|
+
const raw = options.deploymentAuth || process.env.AIFABRIX_DEPLOYMENT_AUTH || 'auto';
|
|
20
|
+
const mode = String(raw).trim().toLowerCase().replace(/_/g, '-');
|
|
21
|
+
if (mode === 'client-credentials' || mode === 'client') {
|
|
22
|
+
return 'client-credentials';
|
|
23
|
+
}
|
|
24
|
+
if (mode === 'device' || mode === 'device-token' || mode === 'bearer') {
|
|
25
|
+
return 'device';
|
|
26
|
+
}
|
|
27
|
+
return 'auto';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {DeploymentAuthMode} mode
|
|
32
|
+
* @returns {boolean}
|
|
33
|
+
*/
|
|
34
|
+
function shouldUseDeviceTokenForDeployment(mode) {
|
|
35
|
+
return mode !== 'client-credentials';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = {
|
|
39
|
+
getDeploymentAuthMode,
|
|
40
|
+
shouldUseDeviceTokenForDeployment
|
|
41
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Developer ID suffix variants for Docker volume names (`dev6` vs `dev06`).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Volume name suffix normalization for multi-dev Docker
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {string|number} developerId
|
|
13
|
+
* @returns {string[]}
|
|
14
|
+
*/
|
|
15
|
+
function collectDeveloperVolumeIdSuffixes(developerId) {
|
|
16
|
+
const raw = String(developerId).trim();
|
|
17
|
+
const idNum = parseInt(raw, 10);
|
|
18
|
+
if (Number.isNaN(idNum) || idNum === 0) {
|
|
19
|
+
return ['0'];
|
|
20
|
+
}
|
|
21
|
+
const suffixes = new Set([String(idNum), raw]);
|
|
22
|
+
if (raw.length === 1) {
|
|
23
|
+
suffixes.add(raw.padStart(2, '0'));
|
|
24
|
+
}
|
|
25
|
+
if (String(idNum).length === 1) {
|
|
26
|
+
suffixes.add(String(idNum).padStart(2, '0'));
|
|
27
|
+
}
|
|
28
|
+
return [...suffixes];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = {
|
|
32
|
+
collectDeveloperVolumeIdSuffixes
|
|
33
|
+
};
|
package/lib/utils/env-copy.js
CHANGED
|
@@ -272,14 +272,16 @@ async function patchEnvContentForLocal(envContent, variables) {
|
|
|
272
272
|
* @param {string} outputPath - Resolved `build.envOutputPath`
|
|
273
273
|
* @param {string} envOutputPathLabel - Label for log (e.g. raw `build.envOutputPath` value)
|
|
274
274
|
*/
|
|
275
|
-
async function syncWrittenBuilderEnvToOutputPath(envPath, outputPath, envOutputPathLabel) {
|
|
275
|
+
async function syncWrittenBuilderEnvToOutputPath(envPath, outputPath, envOutputPathLabel, copyOptions = {}) {
|
|
276
276
|
const { parseEnvContentToMap, mergeEnvMapIntoContent } = require('../core/secrets');
|
|
277
277
|
const raw = fs.readFileSync(envPath, 'utf8');
|
|
278
278
|
const synced = substituteMntDataForLocal(raw, outputPath);
|
|
279
279
|
let toWrite = synced;
|
|
280
|
-
if (fs.existsSync(outputPath)) {
|
|
280
|
+
if (!copyOptions.freshEnv && fs.existsSync(outputPath)) {
|
|
281
281
|
const existingContent = fs.readFileSync(outputPath, 'utf8');
|
|
282
|
-
toWrite = mergeEnvMapIntoContent(existingContent, parseEnvContentToMap(synced)
|
|
282
|
+
toWrite = mergeEnvMapIntoContent(existingContent, parseEnvContentToMap(synced), {
|
|
283
|
+
appendMissingFromNewMap: true
|
|
284
|
+
});
|
|
283
285
|
}
|
|
284
286
|
fs.writeFileSync(outputPath, toWrite, { mode: 0o600 });
|
|
285
287
|
logger.log(formatSuccessLine(`Copied resolved .env to envOutputPath (${envOutputPathLabel})`));
|
|
@@ -300,10 +302,10 @@ async function writeLocalEnvToOutputPath(outputPath, appName, secretsPath, envOu
|
|
|
300
302
|
let localEnvContent = await generateEnvContent(appName, secretsPath, 'local', false, genOpts);
|
|
301
303
|
localEnvContent = substituteMntDataForLocal(localEnvContent, outputPath);
|
|
302
304
|
let toWrite = localEnvContent;
|
|
303
|
-
if (fs.existsSync(outputPath)) {
|
|
305
|
+
if (!extraOpts.freshEnv && fs.existsSync(outputPath)) {
|
|
304
306
|
const existingContent = fs.readFileSync(outputPath, 'utf8');
|
|
305
307
|
const localMap = parseEnvContentToMap(localEnvContent);
|
|
306
|
-
toWrite = mergeEnvMapIntoContent(existingContent, localMap);
|
|
308
|
+
toWrite = mergeEnvMapIntoContent(existingContent, localMap, { appendMissingFromNewMap: true });
|
|
307
309
|
}
|
|
308
310
|
fs.writeFileSync(outputPath, toWrite, { mode: 0o600 });
|
|
309
311
|
logger.log(formatSuccessLine(`Generated local .env at: ${envOutputPathLabel}`));
|
|
@@ -350,15 +352,16 @@ async function copyOrRegenerateEnvForNamedApp(opts) {
|
|
|
350
352
|
secretsPath,
|
|
351
353
|
label,
|
|
352
354
|
preferLocal,
|
|
353
|
-
appPathForLocal
|
|
355
|
+
appPathForLocal,
|
|
356
|
+
freshEnv
|
|
354
357
|
} = opts;
|
|
355
|
-
const localOpts = { appPath: appPathForLocal || undefined };
|
|
358
|
+
const localOpts = { appPath: appPathForLocal || undefined, freshEnv: freshEnv === true };
|
|
356
359
|
if (preferLocal) {
|
|
357
360
|
await writeLocalEnvToOutputPath(outputPath, appName, secretsPath, label, localOpts);
|
|
358
361
|
return;
|
|
359
362
|
}
|
|
360
363
|
if (fs.existsSync(envPath)) {
|
|
361
|
-
await syncWrittenBuilderEnvToOutputPath(envPath, outputPath, label);
|
|
364
|
+
await syncWrittenBuilderEnvToOutputPath(envPath, outputPath, label, { freshEnv: freshEnv === true });
|
|
362
365
|
return;
|
|
363
366
|
}
|
|
364
367
|
await writeLocalEnvToOutputPath(outputPath, appName, secretsPath, label, localOpts);
|
|
@@ -386,6 +389,7 @@ async function processEnvVariables(envPath, variablesPath, appName, secretsPath,
|
|
|
386
389
|
(variablesPath ? path.dirname(variablesPath) : null);
|
|
387
390
|
const preferLocal =
|
|
388
391
|
copyOptions && typeof copyOptions === 'object' && copyOptions.preferLocalEnvOutputPath === true;
|
|
392
|
+
const freshEnv = copyOptions && typeof copyOptions === 'object' && copyOptions.freshEnv === true;
|
|
389
393
|
if (appName) {
|
|
390
394
|
await copyOrRegenerateEnvForNamedApp({
|
|
391
395
|
envPath,
|
|
@@ -394,7 +398,8 @@ async function processEnvVariables(envPath, variablesPath, appName, secretsPath,
|
|
|
394
398
|
secretsPath,
|
|
395
399
|
label,
|
|
396
400
|
preferLocal,
|
|
397
|
-
appPathForLocal
|
|
401
|
+
appPathForLocal,
|
|
402
|
+
freshEnv
|
|
398
403
|
});
|
|
399
404
|
} else {
|
|
400
405
|
await writePatchedEnvToOutputPath(envPath, outputPath, variables, label);
|