@aifabrix/builder 2.44.4 → 2.44.6
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 +1 -1
- package/.cursor/rules/project-rules.mdc +1 -1
- package/.npmrc.token +1 -1
- package/README.md +15 -23
- package/integration/hubspot-test/README.md +2 -0
- package/integration/hubspot-test/test.js +5 -3
- package/jest.projects.js +68 -17
- package/lib/api/controller-health.api.js +49 -0
- package/lib/api/dimension-values.api.js +82 -0
- package/lib/api/dimensions.api.js +114 -0
- package/lib/api/external-systems.api.js +1 -0
- package/lib/api/integration-clients.api.js +168 -0
- package/lib/api/types/dimension-values.types.js +28 -0
- package/lib/api/types/dimensions.types.js +31 -0
- package/lib/api/types/integration-clients.types.js +45 -0
- package/lib/api/types/wizard.types.js +2 -1
- package/lib/api/validation-runner.js +46 -25
- package/lib/app/deploy-config.js +11 -1
- package/lib/app/deploy-status-display.js +3 -3
- package/lib/app/deploy.js +36 -14
- package/lib/app/display.js +15 -11
- package/lib/app/push.js +46 -23
- package/lib/app/register.js +1 -1
- package/lib/app/restart-display.js +95 -0
- package/lib/app/rotate-secret.js +1 -1
- package/lib/app/run-container-start.js +12 -6
- package/lib/app/run-env-compose.js +30 -1
- package/lib/app/run-helpers.js +44 -12
- package/lib/app/run-reload-sync.js +148 -0
- package/lib/app/run-resolve-image.js +51 -1
- package/lib/app/run.js +99 -73
- package/lib/build/index.js +75 -45
- package/lib/cli/doctor-check.js +117 -0
- package/lib/cli/index.js +8 -2
- package/lib/cli/infra-guided.js +445 -0
- package/lib/cli/setup-app.help.js +1 -1
- package/lib/cli/setup-app.js +20 -2
- package/lib/cli/setup-app.test-commands.js +9 -5
- package/lib/cli/setup-auth.js +26 -0
- package/lib/cli/setup-dev-path-commands.js +50 -3
- package/lib/cli/setup-infra.js +138 -61
- package/lib/cli/setup-integration-client.js +182 -0
- package/lib/cli/setup-parameters.js +21 -2
- package/lib/cli/setup-platform.js +102 -0
- package/lib/cli/setup-secrets.js +18 -6
- package/lib/cli/setup-utility.js +97 -33
- package/lib/commands/datasource-capability-dimension-cli.js +128 -0
- package/lib/commands/datasource-capability-output.js +29 -0
- package/lib/commands/datasource-capability-relate-cli.js +140 -0
- package/lib/commands/datasource-capability.js +411 -0
- package/lib/commands/datasource-unified-test-cli.options.js +1 -1
- package/lib/commands/datasource.js +53 -13
- package/lib/commands/dev-down.js +3 -3
- package/lib/commands/dev-infra-gate.js +32 -0
- package/lib/commands/dev-init.js +13 -7
- package/lib/commands/dimension-value.js +179 -0
- package/lib/commands/dimension.js +330 -0
- package/lib/commands/integration-client.js +430 -0
- package/lib/commands/login-device.js +65 -30
- package/lib/commands/login.js +21 -10
- package/lib/commands/parameters-validate.js +78 -13
- package/lib/commands/repair-datasource-auto-rbac.js +166 -0
- package/lib/commands/repair-datasource-keys.js +10 -5
- package/lib/commands/repair-datasource.js +19 -7
- package/lib/commands/repair-env-template.js +4 -1
- package/lib/commands/repair-openapi-sync.js +172 -0
- package/lib/commands/repair-persist.js +102 -0
- package/lib/commands/repair-rbac-extract.js +27 -0
- package/lib/commands/repair-rbac-migrate.js +186 -0
- package/lib/commands/repair-rbac.js +225 -19
- package/lib/commands/repair-system-alignment.js +246 -0
- package/lib/commands/repair-system-permissions.js +168 -0
- package/lib/commands/repair.js +120 -354
- package/lib/commands/secure.js +1 -1
- package/lib/commands/setup-modes.js +455 -0
- package/lib/commands/setup-prompts.js +388 -0
- package/lib/commands/setup.js +149 -0
- package/lib/commands/teardown.js +228 -0
- package/lib/commands/test-e2e-external.js +4 -3
- package/lib/commands/up-common.js +97 -12
- package/lib/commands/up-dataplane.js +33 -11
- package/lib/commands/up-miso.js +7 -11
- package/lib/commands/upload.js +109 -23
- package/lib/commands/wizard-core-helpers.js +14 -11
- package/lib/commands/wizard-core.js +58 -15
- package/lib/commands/wizard-dataplane.js +2 -2
- package/lib/commands/wizard-entity-selection.js +72 -14
- package/lib/commands/wizard-headless.js +7 -3
- package/lib/commands/wizard-helpers.js +13 -1
- package/lib/commands/wizard.js +210 -61
- package/lib/constants/infra-compose-service-names.js +40 -0
- package/lib/core/env-reader.js +16 -3
- package/lib/core/secrets-admin-env.js +101 -0
- package/lib/core/secrets-ensure-infra.js +34 -1
- package/lib/core/secrets-ensure.js +88 -66
- package/lib/core/secrets-env-content.js +432 -0
- package/lib/core/secrets-env-write.js +27 -1
- package/lib/core/secrets-load.js +248 -0
- package/lib/core/secrets-names.js +32 -0
- package/lib/core/secrets.js +17 -757
- package/lib/datasource/capability/basic-exposure.js +76 -0
- package/lib/datasource/capability/capability-diff-slice.js +41 -0
- package/lib/datasource/capability/capability-key.js +34 -0
- package/lib/datasource/capability/capability-resolve.js +172 -0
- package/lib/datasource/capability/capability-storage-keys.js +22 -0
- package/lib/datasource/capability/copy-operations.js +348 -0
- package/lib/datasource/capability/copy-test-payload.js +139 -0
- package/lib/datasource/capability/create-operations.js +235 -0
- package/lib/datasource/capability/dimension-operations.js +151 -0
- package/lib/datasource/capability/dimension-validate.js +219 -0
- package/lib/datasource/capability/json-pointer.js +31 -0
- package/lib/datasource/capability/reference-rewrite.js +51 -0
- package/lib/datasource/capability/relate-operations.js +325 -0
- package/lib/datasource/capability/relate-validate.js +219 -0
- package/lib/datasource/capability/remove-operations.js +275 -0
- package/lib/datasource/capability/run-capability-copy.js +152 -0
- package/lib/datasource/capability/run-capability-diff.js +135 -0
- package/lib/datasource/capability/run-capability-dimension.js +291 -0
- package/lib/datasource/capability/run-capability-edit.js +377 -0
- package/lib/datasource/capability/run-capability-relate.js +193 -0
- package/lib/datasource/capability/run-capability-remove.js +105 -0
- package/lib/datasource/capability/templates/minimal-fetch.json +18 -0
- package/lib/datasource/capability/validate-capability-slice.js +35 -0
- package/lib/datasource/list.js +136 -23
- package/lib/datasource/log-viewer.js +2 -4
- package/lib/datasource/unified-validation-run.js +51 -16
- package/lib/datasource/validate.js +53 -1
- package/lib/deployment/deploy-poll-ui.js +60 -0
- package/lib/deployment/deployer-status.js +29 -3
- package/lib/deployment/deployer.js +48 -30
- package/lib/deployment/environment.js +7 -2
- package/lib/deployment/poll-interval.js +72 -0
- package/lib/deployment/push.js +11 -9
- package/lib/external-system/deploy.js +4 -1
- package/lib/external-system/download.js +61 -32
- package/lib/external-system/sync-deploy-manifest.js +33 -0
- package/lib/generator/wizard-prompts.js +7 -1
- package/lib/generator/wizard.js +34 -0
- package/lib/infrastructure/index.js +49 -19
- package/lib/infrastructure/orphan-infra-docker-teardown.js +177 -0
- package/lib/parameters/infra-kv-discovery.js +29 -4
- package/lib/parameters/infra-parameter-catalog.js +6 -3
- package/lib/parameters/infra-parameter-validate.js +67 -19
- package/lib/resolvers/datasource-resolver.js +53 -0
- package/lib/resolvers/dimension-file.js +52 -0
- package/lib/resolvers/manifest-resolver.js +133 -0
- package/lib/schema/external-datasource.schema.json +183 -53
- package/lib/schema/external-system.schema.json +23 -10
- package/lib/schema/infra.parameter.yaml +26 -11
- package/lib/schema/wizard-config.schema.json +2 -2
- package/lib/utils/aifabrix-config-dir-walk.js +40 -0
- package/lib/utils/aifabrix-runtime-config-dir.js +26 -3
- package/lib/utils/app-run-containers.js +2 -2
- package/lib/utils/bash-secret-env.js +59 -0
- package/lib/utils/cli-secrets-error-format.js +78 -0
- package/lib/utils/cli-test-layout-chalk.js +31 -9
- package/lib/utils/cli-utils.js +4 -36
- package/lib/utils/datasource-test-run-display.js +8 -0
- package/lib/utils/dev-hosts-helper.js +3 -2
- package/lib/utils/dev-init-ssh-merge.js +2 -1
- package/lib/utils/docker-build.js +17 -9
- package/lib/utils/docker-reload-mount.js +127 -0
- package/lib/utils/external-readme.js +117 -4
- package/lib/utils/external-system-local-test-tty.js +3 -2
- package/lib/utils/external-system-readiness-core.js +45 -12
- package/lib/utils/external-system-readiness-deploy-display.js +3 -3
- package/lib/utils/external-system-readiness-display-internals.js +33 -3
- package/lib/utils/external-system-readiness-display.js +10 -1
- package/lib/utils/file-upload.js +40 -3
- package/lib/utils/health-check-db-init.js +107 -0
- package/lib/utils/health-check-public-warn.js +69 -0
- package/lib/utils/health-check-url.js +19 -4
- package/lib/utils/health-check.js +135 -105
- package/lib/utils/help-builder.js +5 -1
- package/lib/utils/image-name.js +34 -7
- package/lib/utils/integration-file-backup.js +74 -0
- package/lib/utils/mutagen-install.js +30 -3
- package/lib/utils/paths.js +108 -25
- package/lib/utils/postgres-wipe.js +212 -0
- package/lib/utils/register-aifabrix-shell-env.js +15 -0
- package/lib/utils/remote-dev-auth.js +21 -5
- package/lib/utils/remote-docker-env.js +9 -1
- package/lib/utils/remote-secrets-loader.js +42 -3
- package/lib/utils/resolve-docker-image-ref.js +9 -3
- package/lib/utils/secrets-ancestor-paths.js +47 -0
- package/lib/utils/secrets-helpers.js +17 -10
- package/lib/utils/secrets-kv-refs.js +42 -0
- package/lib/utils/secrets-kv-scope.js +19 -2
- package/lib/utils/secrets-materialize-local.js +134 -0
- package/lib/utils/secrets-path.js +24 -10
- package/lib/utils/secrets-utils.js +2 -2
- package/lib/utils/system-builder-root.js +34 -0
- package/lib/utils/url-declarative-resolve-build.js +6 -1
- package/lib/utils/url-declarative-runtime-base-path.js +32 -0
- package/lib/utils/url-declarative-vdir-inactive-env.js +2 -1
- package/lib/utils/urls-local-registry.js +73 -20
- package/lib/utils/validation-poll-ui.js +81 -0
- package/lib/utils/validation-run-poll.js +29 -5
- package/lib/utils/with-muted-logger.js +53 -0
- package/package.json +1 -1
- package/templates/applications/dataplane/application.yaml +1 -1
- package/templates/applications/dataplane/rbac.yaml +10 -10
- package/templates/applications/keycloak/env.template +8 -6
- package/templates/applications/miso-controller/application.yaml +7 -0
- package/templates/applications/miso-controller/env.template +7 -7
- package/templates/applications/miso-controller/rbac.yaml +9 -9
- package/templates/external-system/README.md.hbs +89 -102
- package/.nyc_output/55e9d034-ddab-4579-a706-e02a91d75c91.json +0 -1
- package/.nyc_output/processinfo/55e9d034-ddab-4579-a706-e02a91d75c91.json +0 -1
- package/.nyc_output/processinfo/index.json +0 -1
- package/lib/api/service-users.api.js +0 -150
- package/lib/api/types/service-users.types.js +0 -65
- package/lib/cli/setup-service-user.js +0 -187
- package/lib/commands/service-user.js +0 -429
package/lib/commands/repair.js
CHANGED
|
@@ -9,292 +9,38 @@
|
|
|
9
9
|
* @author AI Fabrix Team
|
|
10
10
|
* @version 2.0.0
|
|
11
11
|
*/
|
|
12
|
-
/* eslint-disable max-lines -- Repair flow with auth, normalization, and steps */
|
|
13
12
|
|
|
14
13
|
'use strict';
|
|
15
|
-
const { formatSuccessLine } = require('../utils/cli-test-layout-chalk');
|
|
16
14
|
|
|
17
15
|
const path = require('path');
|
|
18
16
|
const fs = require('fs');
|
|
19
17
|
const chalk = require('chalk');
|
|
20
|
-
const { detectAppType
|
|
18
|
+
const { detectAppType } = require('../utils/paths');
|
|
21
19
|
const { resolveApplicationConfigPath, resolveRbacPath } = require('../utils/app-config-resolver');
|
|
22
|
-
const { loadConfigFile, writeConfigFile,
|
|
23
|
-
const { systemKeyToKvPrefix, securityKeyToVar } = require('../utils/credential-secrets-env');
|
|
20
|
+
const { loadConfigFile, writeConfigFile, isYamlPath } = require('../utils/config-format');
|
|
24
21
|
const logger = require('../utils/logger');
|
|
25
|
-
const generator = require('../generator');
|
|
26
22
|
const { repairEnvTemplate, normalizeSystemFileAuthAndConfig } = require('./repair-env-template');
|
|
27
|
-
const { generateReadmeFromDeployJson } = require('../generator/split-readme');
|
|
28
23
|
const { repairDatasourceFile } = require('./repair-datasource');
|
|
29
|
-
const { mergeRbacFromDatasources } = require('./repair-rbac');
|
|
24
|
+
const { mergeRbacFromDatasources, extractRbacFromSystem, migrateSystemRbacIntoRbacFile } = require('./repair-rbac');
|
|
30
25
|
const { discoverIntegrationFiles, buildEffectiveDatasourceFiles } = require('./repair-internal');
|
|
31
26
|
const { normalizeDatasourceKeysAndFilenames } = require('./repair-datasource-keys');
|
|
27
|
+
const { backupIntegrationFile } = require('../utils/integration-file-backup');
|
|
28
|
+
const { maybeSyncOpenApiFilesForMcp } = require('./repair-openapi-sync');
|
|
29
|
+
const {
|
|
30
|
+
alignAppKeyWithSystem,
|
|
31
|
+
alignDatasourceSystemKeys,
|
|
32
|
+
alignSystemFileDataSources,
|
|
33
|
+
ensureExternalIntegrationBlock,
|
|
34
|
+
removeAuthVarsFromConfiguration,
|
|
35
|
+
resolveSystemContext
|
|
36
|
+
} = require('./repair-system-alignment');
|
|
37
|
+
const { persistChangesAndRegenerate, regenerateReadmeIfRequested } = require('./repair-persist');
|
|
32
38
|
|
|
33
39
|
/** Allowed authentication methods for repair --auth (matches external-system schema) */
|
|
34
40
|
const ALLOWED_AUTH = ['oauth2', 'aad', 'apikey', 'basic', 'queryParam', 'oidc', 'hmac', 'none'];
|
|
35
41
|
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Extracts roles and permissions from system object for rbac.yaml
|
|
54
|
-
* @param {Object} system - Parsed system config
|
|
55
|
-
* @returns {Object|null} RBAC object or null
|
|
56
|
-
*/
|
|
57
|
-
function extractRbacFromSystem(system) {
|
|
58
|
-
if (!system || typeof system !== 'object') return null;
|
|
59
|
-
const hasRoles = system.roles && Array.isArray(system.roles) && system.roles.length > 0;
|
|
60
|
-
const hasPermissions = system.permissions && Array.isArray(system.permissions) && system.permissions.length > 0;
|
|
61
|
-
if (!hasRoles && !hasPermissions) return null;
|
|
62
|
-
const rbac = {};
|
|
63
|
-
if (hasRoles) rbac.roles = system.roles;
|
|
64
|
-
if (hasPermissions) rbac.permissions = system.permissions;
|
|
65
|
-
return rbac;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Loads first system file and returns parsed object with key
|
|
70
|
-
* @param {string} appPath - Application path
|
|
71
|
-
* @param {string} systemFileName - System file name
|
|
72
|
-
* @returns {Object} Parsed system config
|
|
73
|
-
*/
|
|
74
|
-
function loadFirstSystemFile(appPath, systemFileName) {
|
|
75
|
-
const systemPath = path.join(appPath, systemFileName);
|
|
76
|
-
if (!fs.existsSync(systemPath)) {
|
|
77
|
-
throw new Error(`System file not found: ${systemPath}`);
|
|
78
|
-
}
|
|
79
|
-
return loadConfigFile(systemPath);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function resolveSystemContext(appPath, systemFiles) {
|
|
83
|
-
const systemFilePath = path.join(appPath, systemFiles[0]);
|
|
84
|
-
const systemParsed = loadFirstSystemFile(appPath, systemFiles[0]);
|
|
85
|
-
const systemKey = systemParsed.key ||
|
|
86
|
-
path.basename(systemFiles[0], path.extname(systemFiles[0])).replace(/-system$/, '');
|
|
87
|
-
return { systemFilePath, systemParsed, systemKey };
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function ensureExternalIntegrationBlock(variables, systemFiles, datasourceFiles, changes) {
|
|
91
|
-
const extInt = variables.externalIntegration;
|
|
92
|
-
let updated = false;
|
|
93
|
-
if (!extInt) {
|
|
94
|
-
variables.externalIntegration = {
|
|
95
|
-
schemaBasePath: './',
|
|
96
|
-
systems: systemFiles,
|
|
97
|
-
dataSources: datasourceFiles,
|
|
98
|
-
autopublish: true,
|
|
99
|
-
version: '1.0.0'
|
|
100
|
-
};
|
|
101
|
-
changes.push('Created externalIntegration block from discovered files');
|
|
102
|
-
updated = true;
|
|
103
|
-
} else {
|
|
104
|
-
const prevSystems = extInt.systems || [];
|
|
105
|
-
const prevDataSources = extInt.dataSources || [];
|
|
106
|
-
if (JSON.stringify(prevSystems) !== JSON.stringify(systemFiles)) {
|
|
107
|
-
changes.push(`systems: [${prevSystems.join(', ')}] → [${systemFiles.join(', ')}]`);
|
|
108
|
-
extInt.systems = systemFiles;
|
|
109
|
-
updated = true;
|
|
110
|
-
}
|
|
111
|
-
if (JSON.stringify(prevDataSources) !== JSON.stringify(datasourceFiles)) {
|
|
112
|
-
changes.push(`dataSources: [${prevDataSources.join(', ')}] → [${datasourceFiles.join(', ')}]`);
|
|
113
|
-
extInt.dataSources = datasourceFiles;
|
|
114
|
-
updated = true;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
return updated;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function alignAppKeyWithSystem(variables, systemKey, systemParsed, changes) {
|
|
121
|
-
const appKey = variables.app?.key;
|
|
122
|
-
if (!appKey || appKey === systemKey) return false;
|
|
123
|
-
if (!variables.app) variables.app = {};
|
|
124
|
-
variables.app.key = systemKey;
|
|
125
|
-
changes.push(`app.key: ${appKey} → ${systemKey}`);
|
|
126
|
-
return true;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Aligns datasource systemKey values to match the system key.
|
|
131
|
-
* Updates each datasource file whose systemKey differs from the system key.
|
|
132
|
-
*
|
|
133
|
-
* @param {string} appPath - Application directory path
|
|
134
|
-
* @param {string[]} datasourceFiles - Datasource file names
|
|
135
|
-
* @param {string} systemKey - Expected system key
|
|
136
|
-
* @param {boolean} dryRun - If true, report changes but do not write
|
|
137
|
-
* @param {string[]} changes - Array to append change descriptions to
|
|
138
|
-
* @returns {boolean} True if any file was updated (or would be in dry-run)
|
|
139
|
-
*/
|
|
140
|
-
function alignDatasourceSystemKeys(appPath, datasourceFiles, systemKey, dryRun, changes) {
|
|
141
|
-
if (!datasourceFiles || datasourceFiles.length === 0) return false;
|
|
142
|
-
let updated = false;
|
|
143
|
-
for (const datasourceFile of datasourceFiles) {
|
|
144
|
-
const datasourcePath = path.join(appPath, datasourceFile);
|
|
145
|
-
if (!fs.existsSync(datasourcePath)) continue;
|
|
146
|
-
const parsed = loadConfigFile(datasourcePath);
|
|
147
|
-
const old = parsed.systemKey;
|
|
148
|
-
if (old !== systemKey) {
|
|
149
|
-
parsed.systemKey = systemKey;
|
|
150
|
-
if (!dryRun) {
|
|
151
|
-
writeConfigFile(datasourcePath, parsed);
|
|
152
|
-
}
|
|
153
|
-
changes.push(`${datasourceFile}: systemKey ${old} → ${systemKey}`);
|
|
154
|
-
updated = true;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
return updated;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Derives a datasource key from filename when the file has no key.
|
|
162
|
-
* - hubspot-datasource-company.json → hubspot-company
|
|
163
|
-
* - datasource-companies.json → {systemKey}-companies (e.g. test-hubspot-companies)
|
|
164
|
-
*
|
|
165
|
-
* @param {string} fileName - Datasource file name
|
|
166
|
-
* @param {string} systemKey - System key (e.g. test-hubspot), used for datasource-*.json style names
|
|
167
|
-
* @returns {string}
|
|
168
|
-
*/
|
|
169
|
-
function deriveDatasourceKeyFromFileName(fileName, systemKey) {
|
|
170
|
-
const base = path.basename(fileName, path.extname(fileName));
|
|
171
|
-
if (/^datasource-/.test(base)) {
|
|
172
|
-
const suffix = base.slice('datasource-'.length);
|
|
173
|
-
return systemKey && typeof systemKey === 'string' ? `${systemKey}-${suffix}` : base;
|
|
174
|
-
}
|
|
175
|
-
return base.replace(/-datasource-/, '-');
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Aligns system file dataSources array to match datasource keys from discovered files.
|
|
180
|
-
* The system file holds logical keys (not filenames): each key comes from that datasource
|
|
181
|
-
* file's "key" property, or is derived from the filename when missing (e.g. datasource-companies.json → {systemKey}-companies).
|
|
182
|
-
*
|
|
183
|
-
* @param {string} appPath - Application directory path
|
|
184
|
-
* @param {Object} systemParsed - Parsed system config (mutated)
|
|
185
|
-
* @param {string[]} datasourceFiles - Datasource file names
|
|
186
|
-
* @param {string} systemKey - System key for deriving key when missing
|
|
187
|
-
* @param {boolean} dryRun - If true, report changes but do not write
|
|
188
|
-
* @param {string[]} changes - Array to append change descriptions to
|
|
189
|
-
* @returns {boolean} True if dataSources was updated (or would be in dry-run)
|
|
190
|
-
*/
|
|
191
|
-
function alignSystemFileDataSources(appPath, systemParsed, datasourceFiles, systemKey, dryRun, changes) {
|
|
192
|
-
const keys = [];
|
|
193
|
-
for (const fileName of datasourceFiles) {
|
|
194
|
-
const filePath = path.join(appPath, fileName);
|
|
195
|
-
if (!fs.existsSync(filePath)) continue;
|
|
196
|
-
try {
|
|
197
|
-
const parsed = loadConfigFile(filePath);
|
|
198
|
-
const key = parsed && typeof parsed.key === 'string' && parsed.key.trim()
|
|
199
|
-
? parsed.key.trim()
|
|
200
|
-
: deriveDatasourceKeyFromFileName(fileName, systemKey);
|
|
201
|
-
keys.push(key);
|
|
202
|
-
} catch (err) {
|
|
203
|
-
logger.log(chalk.yellow(`⚠ Could not load datasource file ${fileName}: ${err.message}; using derived key`));
|
|
204
|
-
keys.push(deriveDatasourceKeyFromFileName(fileName, systemKey));
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
const prev = Array.isArray(systemParsed.dataSources) ? [...systemParsed.dataSources] : [];
|
|
208
|
-
if (JSON.stringify(prev) === JSON.stringify(keys)) return false;
|
|
209
|
-
systemParsed.dataSources = keys;
|
|
210
|
-
changes.push(`dataSources: [${prev.join(', ') || '(none)'}] → [${keys.join(', ')}] (keys from each datasource file's "key" or filename)`);
|
|
211
|
-
return true;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Builds the set of auth variable names (UPPERCASE, no underscores) from authentication.variables and authentication.security.
|
|
216
|
-
* Used to detect configuration entries that belong only in the authentication section.
|
|
217
|
-
* Canonical keys per method are in lib/schema/external-system.schema.json $defs.authenticationVariablesByMethod
|
|
218
|
-
* (e.g. oauth2: variables baseUrl, tokenUrl, scope; security clientId, clientSecret).
|
|
219
|
-
*
|
|
220
|
-
* @param {Object} systemParsed - Parsed system config
|
|
221
|
-
* @param {string} _systemKey - System key (unused; for API consistency)
|
|
222
|
-
* @returns {Set<string>}
|
|
223
|
-
*/
|
|
224
|
-
function buildAuthVarNames(systemParsed, _systemKey) {
|
|
225
|
-
const names = new Set();
|
|
226
|
-
const auth = systemParsed.authentication;
|
|
227
|
-
if (auth && typeof auth.variables === 'object') {
|
|
228
|
-
for (const k of Object.keys(auth.variables)) {
|
|
229
|
-
names.add(String(k).toUpperCase().replace(/_/g, ''));
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
if (auth && typeof auth.security === 'object') {
|
|
233
|
-
for (const k of Object.keys(auth.security)) {
|
|
234
|
-
names.add(securityKeyToVar(k));
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
return names;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* Removes from system configuration any entry that represents standard auth variables
|
|
242
|
-
* (BASEURL, CLIENTID, CLIENTSECRET, TOKENURL, APIKEY, USERNAME, PASSWORD, etc.).
|
|
243
|
-
* These are supplied from the selected credential at runtime; the configuration array
|
|
244
|
-
* should contain only custom variables. Removes both plain and keyvault auth entries.
|
|
245
|
-
*
|
|
246
|
-
* @param {Object} systemParsed - Parsed system config (mutated)
|
|
247
|
-
* @param {string} systemKey - System key for naming consistency
|
|
248
|
-
* @param {boolean} dryRun - If true, report changes but do not write
|
|
249
|
-
* @param {string[]} changes - Array to append change descriptions to
|
|
250
|
-
* @returns {boolean} True if any entry was removed
|
|
251
|
-
*/
|
|
252
|
-
/**
|
|
253
|
-
* Derives the normalized auth variable part from a config entry name (for matching against authNames).
|
|
254
|
-
* E.g. KV_HUBSPOT_CLIENTID → CLIENTID, BASEURL → BASEURL.
|
|
255
|
-
* @param {string} name - Entry name
|
|
256
|
-
* @param {string} systemKey - System key for KV_ prefix
|
|
257
|
-
* @returns {string}
|
|
258
|
-
*/
|
|
259
|
-
function normalizedAuthPartFromConfigName(name, systemKey) {
|
|
260
|
-
const n = String(name).trim();
|
|
261
|
-
if (!n) return '';
|
|
262
|
-
const prefix = systemKeyToKvPrefix(systemKey);
|
|
263
|
-
const kvPrefix = `KV_${prefix}_`;
|
|
264
|
-
if (n.toUpperCase().startsWith(kvPrefix)) {
|
|
265
|
-
const rest = n.slice(kvPrefix.length);
|
|
266
|
-
return rest.toUpperCase().replace(/_/g, '');
|
|
267
|
-
}
|
|
268
|
-
// Old-style or other KV_* names: treat last segment as var (e.g. KV_HUBSPOT_CLIENTID → CLIENTID)
|
|
269
|
-
if (n.toUpperCase().startsWith('KV_')) {
|
|
270
|
-
const parts = n.split('_').filter(Boolean);
|
|
271
|
-
if (parts.length >= 2) return parts[parts.length - 1].toUpperCase();
|
|
272
|
-
}
|
|
273
|
-
return n.toUpperCase().replace(/_/g, '');
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
function removeAuthVarsFromConfiguration(systemParsed, systemKey, dryRun, changes) {
|
|
277
|
-
const config = systemParsed.configuration;
|
|
278
|
-
if (!Array.isArray(config)) return false;
|
|
279
|
-
const authNames = buildAuthVarNames(systemParsed, systemKey);
|
|
280
|
-
if (authNames.size === 0) return false;
|
|
281
|
-
const removed = [];
|
|
282
|
-
const filtered = config.filter((entry) => {
|
|
283
|
-
if (!entry || !entry.name) return true;
|
|
284
|
-
const authPart = normalizedAuthPartFromConfigName(entry.name, systemKey);
|
|
285
|
-
if (authNames.has(authPart)) {
|
|
286
|
-
removed.push(entry.name);
|
|
287
|
-
return false;
|
|
288
|
-
}
|
|
289
|
-
return true;
|
|
290
|
-
});
|
|
291
|
-
if (removed.length === 0) return false;
|
|
292
|
-
systemParsed.configuration = filtered;
|
|
293
|
-
changes.push(`Removed authentication variable(s) from configuration: ${removed.join(', ')}`);
|
|
294
|
-
return true;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
function createRbacFromSystemIfNeeded(appPath, systemFilePath, systemParsed, dryRun, changes, format) {
|
|
42
|
+
function createRbacFromSystemIfNeeded(opts) {
|
|
43
|
+
const { appPath, systemFilePath, systemParsed, dryRun, changes, format, backupCtx } = opts;
|
|
298
44
|
if (resolveRbacPath(appPath)) return false;
|
|
299
45
|
const rbacFromSystem = extractRbacFromSystem(systemParsed);
|
|
300
46
|
if (!rbacFromSystem) return false;
|
|
@@ -304,6 +50,7 @@ function createRbacFromSystemIfNeeded(appPath, systemFilePath, systemParsed, dry
|
|
|
304
50
|
writeConfigFile(defaultRbacPath, rbacFromSystem, rbacFormat);
|
|
305
51
|
delete systemParsed.roles;
|
|
306
52
|
delete systemParsed.permissions;
|
|
53
|
+
backupIntegrationFile(systemFilePath, backupCtx);
|
|
307
54
|
writeConfigFile(systemFilePath, systemParsed);
|
|
308
55
|
}
|
|
309
56
|
changes.push('Created rbac.yaml from system roles/permissions');
|
|
@@ -337,6 +84,7 @@ function runDatasourceRepairs(appPath, datasourceFiles, options, dryRun, changes
|
|
|
337
84
|
updated = true;
|
|
338
85
|
fileChanges.forEach(c => changes.push(`${fileName}: ${c}`));
|
|
339
86
|
if (!dryRun) {
|
|
87
|
+
backupIntegrationFile(filePath, options.backupCtx);
|
|
340
88
|
writeConfigFile(filePath, parsed);
|
|
341
89
|
}
|
|
342
90
|
}
|
|
@@ -347,57 +95,17 @@ function runDatasourceRepairs(appPath, datasourceFiles, options, dryRun, changes
|
|
|
347
95
|
return updated;
|
|
348
96
|
}
|
|
349
97
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* Regenerates README.md from deployment manifest when options.doc is set.
|
|
363
|
-
* @param {string} appName - Application name
|
|
364
|
-
* @param {string} appPath - Application path
|
|
365
|
-
* @param {Object} options - Options (doc, dryRun)
|
|
366
|
-
* @param {string[]} changes - Array to append change messages to
|
|
367
|
-
* @returns {Promise<boolean>} True if README was regenerated
|
|
368
|
-
*/
|
|
369
|
-
async function regenerateReadmeIfRequested(appName, appPath, options, changes) {
|
|
370
|
-
if (!options.doc) return false;
|
|
371
|
-
const deployJsonPath = getDeployJsonPath(appName, 'external', true);
|
|
372
|
-
if (!fs.existsSync(deployJsonPath) && !options.dryRun) {
|
|
373
|
-
await regenerateManifest(appName, appPath, changes);
|
|
374
|
-
}
|
|
375
|
-
if (!fs.existsSync(deployJsonPath)) return false;
|
|
376
|
-
try {
|
|
377
|
-
const deployment = JSON.parse(fs.readFileSync(deployJsonPath, 'utf8'));
|
|
378
|
-
const fileExt = inferExternalReadmeFileExt(appPath);
|
|
379
|
-
const readmeContent = generateReadmeFromDeployJson(deployment, { fileExt });
|
|
380
|
-
const readmePath = path.join(appPath, 'README.md');
|
|
381
|
-
if (!options.dryRun) {
|
|
382
|
-
fs.writeFileSync(readmePath, readmeContent, { mode: 0o644, encoding: 'utf8' });
|
|
383
|
-
}
|
|
384
|
-
changes.push('Regenerated README.md from deployment manifest');
|
|
385
|
-
return true;
|
|
386
|
-
} catch (err) {
|
|
387
|
-
logger.log(chalk.yellow(`⚠ Could not regenerate README: ${err.message}`));
|
|
388
|
-
return false;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
function persistChangesAndRegenerate(configPath, variables, appName, appPath, changes, originalYamlContent) {
|
|
393
|
-
if (originalYamlContent !== null && originalYamlContent !== undefined && typeof originalYamlContent === 'string' && isYamlPath(configPath)) {
|
|
394
|
-
writeYamlPreservingComments(configPath, originalYamlContent, variables);
|
|
395
|
-
} else {
|
|
396
|
-
writeConfigFile(configPath, variables);
|
|
397
|
-
}
|
|
398
|
-
logger.log(formatSuccessLine(`Updated ${path.basename(configPath)}`));
|
|
399
|
-
changes.forEach(c => logger.log(chalk.gray(` ${c}`)));
|
|
400
|
-
return regenerateManifest(appName, appPath, changes);
|
|
98
|
+
function maybeRepairRbac(appPath, systemFilePath, systemParsed, datasourceFiles, options) {
|
|
99
|
+
if (!options.rbac) return { rbacMigratedFromSystem: false, rbacMergeUpdated: false };
|
|
100
|
+
const { dryRun, changes, backupCtx, rbacFmt } = options;
|
|
101
|
+
const rbacMigratedFromSystem = migrateSystemRbacIntoRbacFile(appPath, systemFilePath, systemParsed, { dryRun, changes, backupCtx });
|
|
102
|
+
const rbacMergeUpdated = mergeRbacFromDatasources(appPath, systemParsed, datasourceFiles, extractRbacFromSystem, {
|
|
103
|
+
format: rbacFmt,
|
|
104
|
+
dryRun,
|
|
105
|
+
changes,
|
|
106
|
+
backupCtx
|
|
107
|
+
});
|
|
108
|
+
return { rbacMigratedFromSystem, rbacMergeUpdated };
|
|
401
109
|
}
|
|
402
110
|
|
|
403
111
|
/**
|
|
@@ -432,10 +140,11 @@ function applyAuthMethod(ctx) {
|
|
|
432
140
|
|
|
433
141
|
/**
|
|
434
142
|
* Runs all repair steps (integration block, system dataSources, auth/config, app key, datasource keys, rbac, env.template).
|
|
435
|
-
* @param {Object} ctx - Context with appPath, configPath, variables, systemFilePath, systemParsed, systemKey, systemFiles, datasourceFiles, dryRun, changes, auth?
|
|
143
|
+
* @param {Object} ctx - Context with appPath, configPath, variables, systemFilePath, systemParsed, systemKey, systemFiles, datasourceFiles, dryRun, changes, auth?, backupCtx?
|
|
436
144
|
* @returns {{ updated: boolean, appKeyFixed: boolean, datasourceKeysFixed: boolean, rbacFileCreated: boolean, envTemplateRepaired: boolean }}
|
|
437
145
|
*/
|
|
438
146
|
function runRepairSteps(ctx) {
|
|
147
|
+
const bc = ctx.backupCtx;
|
|
439
148
|
let updated = ensureExternalIntegrationBlock(
|
|
440
149
|
ctx.variables, ctx.systemFiles, ctx.datasourceFiles, ctx.changes
|
|
441
150
|
);
|
|
@@ -450,21 +159,30 @@ function runRepairSteps(ctx) {
|
|
|
450
159
|
const authVarsRemoved = removeAuthVarsFromConfiguration(
|
|
451
160
|
ctx.systemParsed, ctx.systemKey, ctx.dryRun, ctx.changes
|
|
452
161
|
);
|
|
453
|
-
|
|
162
|
+
const systemFileUpdated =
|
|
163
|
+
authReplaced || systemAuthConfigNormalized || systemDataSourcesAligned || authVarsRemoved;
|
|
164
|
+
if (systemFileUpdated && !ctx.dryRun) {
|
|
165
|
+
backupIntegrationFile(ctx.systemFilePath, bc);
|
|
454
166
|
writeConfigFile(ctx.systemFilePath, ctx.systemParsed);
|
|
455
167
|
}
|
|
456
|
-
updated = updated ||
|
|
168
|
+
updated = updated || systemFileUpdated;
|
|
457
169
|
const appKeyFixed = alignAppKeyWithSystem(
|
|
458
170
|
ctx.variables, ctx.systemKey, ctx.systemParsed, ctx.changes
|
|
459
171
|
);
|
|
460
172
|
const datasourceKeysFixed = alignDatasourceSystemKeys(
|
|
461
|
-
ctx.appPath, ctx.datasourceFiles, ctx.systemKey, ctx.dryRun, ctx.changes
|
|
462
|
-
);
|
|
463
|
-
const rbacFileCreated = createRbacFromSystemIfNeeded(
|
|
464
|
-
ctx.appPath, ctx.systemFilePath, ctx.systemParsed, ctx.dryRun, ctx.changes, ctx.format
|
|
173
|
+
ctx.appPath, ctx.datasourceFiles, ctx.systemKey, ctx.dryRun, ctx.changes, bc
|
|
465
174
|
);
|
|
175
|
+
const rbacFileCreated = createRbacFromSystemIfNeeded({
|
|
176
|
+
appPath: ctx.appPath,
|
|
177
|
+
systemFilePath: ctx.systemFilePath,
|
|
178
|
+
systemParsed: ctx.systemParsed,
|
|
179
|
+
dryRun: ctx.dryRun,
|
|
180
|
+
changes: ctx.changes,
|
|
181
|
+
format: ctx.format,
|
|
182
|
+
backupCtx: bc
|
|
183
|
+
});
|
|
466
184
|
const envTemplateRepaired = repairEnvTemplate(
|
|
467
|
-
ctx.appPath, ctx.systemParsed, ctx.systemKey, ctx.dryRun, ctx.changes
|
|
185
|
+
ctx.appPath, ctx.systemParsed, ctx.systemKey, ctx.dryRun, ctx.changes, bc
|
|
468
186
|
);
|
|
469
187
|
updated = updated || appKeyFixed || datasourceKeysFixed || rbacFileCreated || envTemplateRepaired;
|
|
470
188
|
return {
|
|
@@ -516,7 +234,14 @@ function loadConfigAndDiscover(appPath, configPath) {
|
|
|
516
234
|
*/
|
|
517
235
|
function buildRepairResult(steps, anyUpdated, manifestRegenerated, readmeRegenerated, ctx) {
|
|
518
236
|
return Object.assign(
|
|
519
|
-
{
|
|
237
|
+
{
|
|
238
|
+
updated: anyUpdated,
|
|
239
|
+
actionsPerformed: ctx.actionsPerformed === true,
|
|
240
|
+
changes: ctx.changes,
|
|
241
|
+
systemFiles: ctx.systemFiles,
|
|
242
|
+
datasourceFiles: ctx.datasourceFiles,
|
|
243
|
+
backupPaths: ctx.backupPaths || []
|
|
244
|
+
},
|
|
520
245
|
{
|
|
521
246
|
appKeyFixed: steps.appKeyFixed,
|
|
522
247
|
datasourceKeysFixed: steps.datasourceKeysFixed,
|
|
@@ -547,20 +272,45 @@ async function validateAndResolveRepairPaths(appName, options) {
|
|
|
547
272
|
return { appPath, configPath, dryRun, authOption };
|
|
548
273
|
}
|
|
549
274
|
|
|
275
|
+
/**
|
|
276
|
+
* @param {Object} options - CLI options (noBackup, backup)
|
|
277
|
+
* @param {boolean} dryRun
|
|
278
|
+
* @returns {{ backupPaths: string[], backupCtx: Object }}
|
|
279
|
+
*/
|
|
280
|
+
function createRepairBackupContext(options, dryRun) {
|
|
281
|
+
const noBackup = options.noBackup === true || options.backup === false;
|
|
282
|
+
const backupPaths = [];
|
|
283
|
+
const backedUpFiles = new Set();
|
|
284
|
+
const backupCtx = { dryRun, noBackup, backupPaths, backedUpFiles };
|
|
285
|
+
return { backupPaths, backupCtx };
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
async function maybeRunOpenApiSyncForMcp({ options, dryRun, appPath, systemKey, datasourceFiles, changes }) {
|
|
289
|
+
if (!options.api) return false;
|
|
290
|
+
try {
|
|
291
|
+
const openapiLines = await maybeSyncOpenApiFilesForMcp({
|
|
292
|
+
enabled: true,
|
|
293
|
+
dryRun,
|
|
294
|
+
appPath,
|
|
295
|
+
systemKey,
|
|
296
|
+
datasourceFiles
|
|
297
|
+
});
|
|
298
|
+
openapiLines.forEach((l) => changes.push(l));
|
|
299
|
+
return openapiLines.length > 0;
|
|
300
|
+
} catch (err) {
|
|
301
|
+
changes.push(`OpenAPI upload for MCP failed: ${err.message}`);
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
550
306
|
async function repairExternalIntegration(appName, options = {}) {
|
|
551
307
|
const { appPath, configPath, dryRun, authOption } = await validateAndResolveRepairPaths(appName, options);
|
|
552
|
-
|
|
308
|
+
const { backupPaths, backupCtx } = createRepairBackupContext(options, dryRun);
|
|
553
309
|
const { variables, originalYamlContent, systemFiles, datasourceFiles: initialDatasourceFiles } = loadConfigAndDiscover(appPath, configPath);
|
|
554
310
|
const changes = [];
|
|
555
311
|
const { systemFilePath, systemParsed, systemKey } = resolveSystemContext(appPath, systemFiles);
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
initialDatasourceFiles,
|
|
559
|
-
systemKey,
|
|
560
|
-
variables,
|
|
561
|
-
dryRun,
|
|
562
|
-
changes
|
|
563
|
-
);
|
|
312
|
+
const rbacFmt = options.format === 'json' ? 'json' : 'yaml';
|
|
313
|
+
const { updated: keysNormalized, datasourceFiles } = normalizeDatasourceKeysAndFilenames(appPath, initialDatasourceFiles, systemKey, { variables, dryRun, changes, backupCtx });
|
|
564
314
|
const steps = runRepairSteps({
|
|
565
315
|
appPath,
|
|
566
316
|
configPath,
|
|
@@ -573,26 +323,42 @@ async function repairExternalIntegration(appName, options = {}) {
|
|
|
573
323
|
dryRun,
|
|
574
324
|
changes,
|
|
575
325
|
auth: authOption,
|
|
576
|
-
format:
|
|
326
|
+
format: rbacFmt,
|
|
327
|
+
backupCtx
|
|
577
328
|
});
|
|
578
329
|
const datasourceRepairUpdated = runDatasourceRepairs(appPath, datasourceFiles, {
|
|
579
330
|
expose: Boolean(options.expose),
|
|
580
331
|
sync: Boolean(options.sync),
|
|
581
|
-
test: Boolean(options.test)
|
|
332
|
+
test: Boolean(options.test),
|
|
333
|
+
backupCtx
|
|
582
334
|
}, dryRun, changes);
|
|
583
|
-
const
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
const
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
335
|
+
const openapiActionsPerformed = await maybeRunOpenApiSyncForMcp({
|
|
336
|
+
options,
|
|
337
|
+
dryRun,
|
|
338
|
+
appPath,
|
|
339
|
+
systemKey,
|
|
340
|
+
datasourceFiles,
|
|
341
|
+
changes
|
|
342
|
+
});
|
|
343
|
+
const { rbacMigratedFromSystem, rbacMergeUpdated } = maybeRepairRbac(
|
|
344
|
+
appPath,
|
|
345
|
+
systemFilePath,
|
|
346
|
+
systemParsed,
|
|
347
|
+
datasourceFiles,
|
|
348
|
+
{ rbac: Boolean(options.rbac), rbacFmt, dryRun, changes, backupCtx }
|
|
349
|
+
);
|
|
350
|
+
const anyLocalUpdated = keysNormalized || steps.updated || datasourceRepairUpdated || rbacMigratedFromSystem || rbacMergeUpdated;
|
|
351
|
+
const manifestRegenerated = (anyLocalUpdated && !dryRun) ? await persistChangesAndRegenerate(
|
|
352
|
+
{ configPath, variables, appName, appPath, changes, originalYamlContent, backupCtx }
|
|
353
|
+
) : false;
|
|
354
|
+
const readmeRegenerated = await regenerateReadmeIfRequested(appName, appPath, { ...options, backupCtx }, changes);
|
|
355
|
+
return buildRepairResult(steps, anyLocalUpdated, manifestRegenerated, readmeRegenerated, {
|
|
356
|
+
actionsPerformed: openapiActionsPerformed,
|
|
357
|
+
changes,
|
|
358
|
+
systemFiles,
|
|
359
|
+
datasourceFiles,
|
|
360
|
+
backupPaths
|
|
361
|
+
});
|
|
596
362
|
}
|
|
597
363
|
|
|
598
364
|
module.exports = {
|
package/lib/commands/secure.js
CHANGED
|
@@ -179,7 +179,7 @@ async function processSecretsFiles(secretsFiles, encryptionKey) {
|
|
|
179
179
|
totalValues += result.total;
|
|
180
180
|
|
|
181
181
|
if (result.encrypted > 0) {
|
|
182
|
-
logger.log(chalk.green(
|
|
182
|
+
logger.log(chalk.green(' ') + formatSuccessLine(`Encrypted ${result.encrypted} of ${result.total} values`));
|
|
183
183
|
} else {
|
|
184
184
|
logger.log(chalk.gray(` - All values already encrypted (${result.total} total)`));
|
|
185
185
|
}
|