@aifabrix/builder 2.44.6 → 2.45.5
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 +7 -3
- package/.cursor/rules/docs-rules.mdc +3 -1
- package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +1 -1
- package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +1 -1
- package/integration/hubspot-test/wizard-hubspot-e2e.yaml +1 -1
- package/jest.projects.js +100 -1
- package/lib/api/agent-metadata-validation.api.js +93 -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-scenarios.api.js +39 -0
- package/lib/api/groups.api.js +79 -0
- package/lib/api/index.js +45 -2
- package/lib/api/pipeline.api.js +4 -4
- package/lib/api/protection.api.js +157 -0
- package/lib/api/records-bulk.api.js +30 -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 +3 -3
- package/lib/api/wizard-platform.api.js +3 -3
- package/lib/api/wizard.api.js +21 -21
- package/lib/app/deploy.js +34 -19
- package/lib/app/helpers.js +3 -3
- package/lib/app/index.js +3 -3
- package/lib/app/register.js +7 -6
- package/lib/app/restart-display.js +52 -21
- package/lib/app/rotate-secret.js +7 -6
- package/lib/app/run-helpers.js +15 -8
- package/lib/app/run.js +57 -9
- package/lib/app/show-display.js +7 -0
- package/lib/app/show.js +87 -5
- package/lib/build/index.js +9 -5
- package/lib/cli/index.js +4 -2
- package/lib/cli/infra-guided.js +62 -28
- package/lib/cli/installation-log-command.js +73 -0
- package/lib/cli/setup-app.help.js +50 -2
- package/lib/cli/setup-app.js +44 -25
- package/lib/cli/setup-app.test-commands.js +80 -21
- package/lib/cli/setup-auth.js +124 -52
- package/lib/cli/setup-external-system.js +37 -3
- package/lib/cli/setup-infra-up-dataplane-action.js +111 -0
- package/lib/cli/setup-infra-up-platform-action.js +131 -0
- package/lib/cli/setup-infra.js +60 -119
- package/lib/cli/setup-platform.js +1 -1
- package/lib/cli/setup-utility-help-after.js +45 -0
- package/lib/cli/setup-utility-resolve.js +132 -0
- package/lib/cli/setup-utility.js +148 -116
- package/lib/commands/app-logs.js +81 -33
- package/lib/commands/auth-config.js +116 -18
- package/lib/commands/auth-status-dataplane-version.js +231 -0
- package/lib/commands/auth-status-display.js +94 -0
- package/lib/commands/auth-status.js +70 -6
- 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 +114 -0
- package/lib/commands/datasource-unified-test-cli.js +25 -17
- package/lib/commands/datasource-unified-test-cli.options.js +18 -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/dimension-value.js +43 -13
- package/lib/commands/dimension.js +38 -7
- 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/login.js +46 -16
- package/lib/commands/protection-cli-leaves.js +286 -0
- package/lib/commands/protection.js +50 -0
- package/lib/commands/repair.js +13 -3
- package/lib/commands/setup-modes.js +19 -6
- package/lib/commands/setup-prompts.js +41 -8
- package/lib/commands/setup.js +114 -9
- package/lib/commands/teardown.js +54 -5
- package/lib/commands/test-e2e-external.js +40 -9
- package/lib/commands/test-governance-cli-options.js +47 -0
- package/lib/commands/test-governance-command-action.js +55 -0
- package/lib/commands/test-governance-external.js +88 -0
- package/lib/commands/test-trust-cli-options.js +32 -0
- package/lib/commands/test-trust-command-action.js +118 -0
- package/lib/commands/test-trust-external.js +127 -0
- package/lib/commands/up-common.js +48 -14
- package/lib/commands/up-dataplane.js +21 -18
- package/lib/commands/up-miso.js +12 -8
- package/lib/commands/upload.js +38 -15
- package/lib/commands/wizard-core.js +3 -0
- package/lib/core/audit-logger.js +1 -34
- package/lib/core/config-admin-email.js +56 -0
- package/lib/core/config-device-dataplane.js +185 -0
- package/lib/core/config-normalize.js +60 -0
- package/lib/core/config-registered-controller-urls.js +54 -0
- package/lib/core/config.js +33 -50
- package/lib/core/secrets-ensure-infra.js +1 -1
- package/lib/core/secrets-env-content.js +86 -90
- package/lib/core/secrets-env-declarative-expand.js +170 -0
- package/lib/core/secrets-env-write.js +2 -0
- package/lib/core/secrets-load.js +106 -102
- 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 +93 -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 +103 -0
- package/lib/datasource/audit-evidence-extract.js +177 -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 +177 -0
- package/lib/datasource/audit-evidence-verify.js +108 -0
- package/lib/datasource/bulk-loader-run-batches.js +88 -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 +92 -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 +26 -2
- package/lib/datasource/unified-validation-run-resolve.js +45 -12
- package/lib/datasource/unified-validation-run.js +43 -17
- package/lib/datasource/validate.js +37 -20
- package/lib/external-system/deploy.js +5 -1
- package/lib/external-system/test-system-level.js +25 -4
- package/lib/external-system/test.js +3 -1
- package/lib/governance/governance-pack-loader.js +70 -0
- package/lib/governance/governance-run-display.js +119 -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/internal/fs-real-sync.js +29 -1
- package/lib/internal/node-fs.js +2 -0
- package/lib/protection/auth-context.js +45 -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 +4 -0
- package/lib/schema/external-datasource.schema.json +47 -13
- package/lib/schema/flag-map-validation-run.json +2 -2
- package/lib/schema/infra.parameter.yaml +10 -0
- package/lib/schema/protection.schema.json +374 -0
- package/lib/schema/type/credential-field-registry.json +636 -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/app-config-resolver.js +24 -1
- package/lib/utils/applications-config-defaults.js +206 -0
- package/lib/utils/auth-config-validator.js +2 -12
- package/lib/utils/bash-secret-env.js +1 -1
- package/lib/utils/cli-exit-codes.js +30 -0
- package/lib/utils/cli-sync-options.js +33 -0
- package/lib/utils/compose-generate-docker-compose.js +111 -6
- package/lib/utils/compose-generator.js +17 -8
- package/lib/utils/controller-url.js +50 -7
- package/lib/utils/credential-push-ui.js +90 -0
- package/lib/utils/dataplane-cli-version-gate.js +202 -0
- package/lib/utils/dataplane-cli-version-help.js +74 -0
- 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/env-copy.js +99 -14
- package/lib/utils/env-template.js +5 -1
- package/lib/utils/health-check-url.js +18 -15
- package/lib/utils/health-check.js +7 -5
- package/lib/utils/help-builder.js +30 -24
- package/lib/utils/infra-optional-service-flags.js +69 -0
- package/lib/utils/installation-log-core.js +282 -0
- package/lib/utils/installation-log-record.js +237 -0
- package/lib/utils/installation-log.js +123 -0
- package/lib/utils/log-redaction.js +105 -0
- package/lib/utils/manifest-location.js +164 -0
- package/lib/utils/manifest-source-emit.js +184 -0
- package/lib/utils/paths.js +238 -89
- package/lib/utils/remote-secrets-loader.js +7 -1
- package/lib/utils/run-cli-flags.js +29 -0
- package/lib/utils/secrets-canonical.js +10 -3
- package/lib/utils/secrets-path.js +3 -4
- package/lib/utils/secrets-utils.js +20 -10
- package/lib/utils/semver-compare.js +127 -0
- package/lib/utils/system-builder-root.js +10 -2
- package/lib/utils/upload-pipeline-ui.js +91 -0
- package/lib/utils/url-declarative-public-base.js +80 -12
- package/lib/utils/url-declarative-resolve-build-urls.js +238 -0
- package/lib/utils/url-declarative-resolve-build.js +24 -393
- package/lib/utils/url-declarative-resolve-expand-token.js +189 -0
- package/lib/utils/url-declarative-resolve-load-doc.js +12 -3
- package/lib/utils/url-declarative-resolve-surface-state.js +102 -0
- package/lib/utils/url-declarative-resolve.js +47 -7
- package/lib/utils/url-declarative-runtime-base-path.js +21 -1
- package/lib/utils/urls-local-registry-scan.js +103 -0
- package/lib/utils/urls-local-registry.js +161 -90
- package/lib/utils/validation-poll-ui.js +14 -7
- package/lib/validation/wizard-config-validator.js +58 -19
- package/package.json +3 -1
- package/templates/applications/dataplane/application.yaml +4 -0
- package/templates/applications/dataplane/env.template +13 -1
- package/templates/applications/dataplane/rbac.yaml +4 -0
- package/templates/applications/miso-controller/application.yaml +2 -0
- package/templates/applications/miso-controller/env.template +27 -29
- package/templates/external-system/README.md.hbs +56 -8
- package/.npmrc.token +0 -1
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Match datasource CLI identifiers to integration files (key or filename stem).
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const { getIntegrationPath } = require('../utils/paths');
|
|
11
|
+
const { resolveApplicationConfigPath } = require('../utils/app-config-resolver');
|
|
12
|
+
const { loadConfigFile } = require('../utils/config-format');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {string} fileRef
|
|
16
|
+
* @returns {string}
|
|
17
|
+
*/
|
|
18
|
+
function datasourceFileStem(fileRef) {
|
|
19
|
+
return path.basename(String(fileRef || ''), path.extname(String(fileRef || '')));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* True when identifier matches parsed `key` or the datasource JSON filename (with or without .json).
|
|
24
|
+
* @param {string} identifier
|
|
25
|
+
* @param {string} fileRef - Manifest-relative datasource path
|
|
26
|
+
* @param {Object|null} parsed
|
|
27
|
+
* @returns {boolean}
|
|
28
|
+
*/
|
|
29
|
+
function datasourceIdentifierMatchesFile(identifier, fileRef, parsed) {
|
|
30
|
+
const id = String(identifier || '').trim();
|
|
31
|
+
if (!id || !parsed || typeof parsed !== 'object') {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
if (parsed.key === id) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
const stem = datasourceFileStem(fileRef);
|
|
38
|
+
if (stem === id) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
if (`${stem}.json` === id.toLowerCase()) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Pick integration app folder for a datasource identifier (longest matching prefix wins).
|
|
49
|
+
* @param {string} identifier
|
|
50
|
+
* @param {string[]} appNames
|
|
51
|
+
* @returns {string|null}
|
|
52
|
+
*/
|
|
53
|
+
function pickIntegrationAppForDatasourceIdentifier(identifier, appNames) {
|
|
54
|
+
const id = String(identifier || '').trim();
|
|
55
|
+
if (!id) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
const matches = appNames.filter(app => id === app || id.startsWith(`${app}-`));
|
|
59
|
+
if (matches.length === 0) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
matches.sort((a, b) => b.length - a.length);
|
|
63
|
+
return matches[0];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* List manifest datasource files for an integration app.
|
|
68
|
+
* @param {string} appKey
|
|
69
|
+
* @returns {{ appPath: string, schemaBasePath: string, datasourceFiles: string[] }|null}
|
|
70
|
+
*/
|
|
71
|
+
function listDatasourceFilesForApp(appKey) {
|
|
72
|
+
const appPath = getIntegrationPath(appKey);
|
|
73
|
+
let config;
|
|
74
|
+
try {
|
|
75
|
+
const configPath = resolveApplicationConfigPath(appPath);
|
|
76
|
+
config = loadConfigFile(configPath);
|
|
77
|
+
} catch {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
const schemaBasePath = config.externalIntegration?.schemaBasePath || './';
|
|
81
|
+
const datasourceFiles = config.externalIntegration?.dataSources || [];
|
|
82
|
+
return { appPath, schemaBasePath, datasourceFiles };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @param {string} appPath
|
|
87
|
+
* @param {string} schemaBasePath
|
|
88
|
+
* @param {string} fileRef
|
|
89
|
+
* @returns {string}
|
|
90
|
+
*/
|
|
91
|
+
function resolveDatasourceFilePath(appPath, schemaBasePath, fileRef) {
|
|
92
|
+
if (path.isAbsolute(schemaBasePath)) {
|
|
93
|
+
return path.join(schemaBasePath, fileRef);
|
|
94
|
+
}
|
|
95
|
+
return path.join(appPath, schemaBasePath, fileRef);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Collect datasource file refs in one app that match the identifier.
|
|
100
|
+
* @param {string} appKey
|
|
101
|
+
* @param {string} identifier
|
|
102
|
+
* @returns {string[]}
|
|
103
|
+
*/
|
|
104
|
+
function collectDatasourceFileRefsMatchingIdentifier(appKey, identifier) {
|
|
105
|
+
const listed = listDatasourceFilesForApp(appKey);
|
|
106
|
+
if (!listed) {
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
const fsSync = require('fs');
|
|
110
|
+
const hits = [];
|
|
111
|
+
for (const fileRef of listed.datasourceFiles) {
|
|
112
|
+
if (!fileRef || typeof fileRef !== 'string') {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
const fullPath = resolveDatasourceFilePath(listed.appPath, listed.schemaBasePath, fileRef);
|
|
116
|
+
if (!fsSync.existsSync(fullPath)) {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const parsed = loadConfigFile(fullPath);
|
|
121
|
+
if (datasourceIdentifierMatchesFile(identifier, fileRef, parsed)) {
|
|
122
|
+
hits.push(fileRef);
|
|
123
|
+
}
|
|
124
|
+
} catch {
|
|
125
|
+
// skip unreadable or invalid files
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return hits;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* @param {string} appKey
|
|
133
|
+
* @param {string} identifier
|
|
134
|
+
* @returns {boolean}
|
|
135
|
+
*/
|
|
136
|
+
function appHasDatasourceIdentifier(appKey, identifier) {
|
|
137
|
+
return collectDatasourceFileRefsMatchingIdentifier(appKey, identifier).length > 0;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
module.exports = {
|
|
141
|
+
datasourceFileStem,
|
|
142
|
+
datasourceIdentifierMatchesFile,
|
|
143
|
+
pickIntegrationAppForDatasourceIdentifier,
|
|
144
|
+
listDatasourceFilesForApp,
|
|
145
|
+
resolveDatasourceFilePath,
|
|
146
|
+
collectDatasourceFileRefsMatchingIdentifier,
|
|
147
|
+
appHasDatasourceIdentifier
|
|
148
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Shared context resolution for datasource load/export (plan 144)
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { getConfig } = require('../core/config');
|
|
10
|
+
const { setupIntegrationTestAuth } = require('../external-system/test-auth');
|
|
11
|
+
const { resolveAppKeyForDatasource } = require('./resolve-app');
|
|
12
|
+
const { getSystemKeyFromAppKey } = require('./integration-context');
|
|
13
|
+
const { loadDatasourceForApp } = require('./unified-validation-run-resolve');
|
|
14
|
+
const { findDatasourceFileByKey } = require('./integration-context');
|
|
15
|
+
const { getIntegrationPath } = require('../utils/paths');
|
|
16
|
+
const { resolveApplicationConfigPath } = require('../utils/app-config-resolver');
|
|
17
|
+
const { computeEntitySuffix } = require('./local-data-paths');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} appKey
|
|
21
|
+
* @throws {Error}
|
|
22
|
+
*/
|
|
23
|
+
async function assertExternalIntegrationApp(appKey) {
|
|
24
|
+
const pathsUtil = require('../utils/paths');
|
|
25
|
+
const appType = await pathsUtil.detectAppType(appKey).catch(() => null);
|
|
26
|
+
if (!appType || appType.baseDir !== 'integration') {
|
|
27
|
+
throw new Error(
|
|
28
|
+
'datasource load/export apply to external integration folders only (integration/<systemKey>/).'
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @async
|
|
35
|
+
* @param {string} datasourceKey
|
|
36
|
+
* @param {Object} options
|
|
37
|
+
* @returns {Promise<Object>}
|
|
38
|
+
*/
|
|
39
|
+
async function resolveLoadExportContext(datasourceKey, options = {}) {
|
|
40
|
+
const { appKey } = await resolveAppKeyForDatasource(datasourceKey, options.app);
|
|
41
|
+
await assertExternalIntegrationApp(appKey);
|
|
42
|
+
const systemKey = await getSystemKeyFromAppKey(appKey);
|
|
43
|
+
const {
|
|
44
|
+
datasource,
|
|
45
|
+
datasourcePath,
|
|
46
|
+
datasourceKey: canonicalDatasourceKey
|
|
47
|
+
} = loadDatasourceForApp(appKey, datasourceKey, findDatasourceFileByKey);
|
|
48
|
+
const appPath = getIntegrationPath(appKey);
|
|
49
|
+
const manifestPath = resolveApplicationConfigPath(appPath);
|
|
50
|
+
const entitySuffix = computeEntitySuffix(systemKey, canonicalDatasourceKey);
|
|
51
|
+
|
|
52
|
+
let authConfig = options.authConfig;
|
|
53
|
+
let dataplaneUrl = options.dataplaneUrl || options.dataplane;
|
|
54
|
+
if (!authConfig || !dataplaneUrl) {
|
|
55
|
+
const configObj = await getConfig();
|
|
56
|
+
const auth = await setupIntegrationTestAuth(
|
|
57
|
+
appKey,
|
|
58
|
+
{ environment: options.environment || options.env, dataplane: options.dataplane },
|
|
59
|
+
configObj
|
|
60
|
+
);
|
|
61
|
+
authConfig = auth.authConfig;
|
|
62
|
+
dataplaneUrl = auth.dataplaneUrl;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
appKey,
|
|
67
|
+
systemKey,
|
|
68
|
+
datasourceKey: canonicalDatasourceKey,
|
|
69
|
+
datasource,
|
|
70
|
+
datasourcePath,
|
|
71
|
+
manifestPath,
|
|
72
|
+
entitySuffix,
|
|
73
|
+
authConfig,
|
|
74
|
+
dataplaneUrl,
|
|
75
|
+
environment: options.environment || options.env
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Gray manifest label segment for TTY (integration/<appKey>).
|
|
81
|
+
* @param {string} appKey
|
|
82
|
+
* @returns {string}
|
|
83
|
+
*/
|
|
84
|
+
function integrationManifestLabel(appKey) {
|
|
85
|
+
return `integration/${appKey}`;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = {
|
|
89
|
+
assertExternalIntegrationApp,
|
|
90
|
+
resolveLoadExportContext,
|
|
91
|
+
integrationManifestLabel
|
|
92
|
+
};
|
|
@@ -9,6 +9,10 @@ const fs = require('fs').promises;
|
|
|
9
9
|
const { getIntegrationPath } = require('../utils/paths');
|
|
10
10
|
const { resolveApplicationConfigPath } = require('../utils/app-config-resolver');
|
|
11
11
|
const { loadConfigFile } = require('../utils/config-format');
|
|
12
|
+
const {
|
|
13
|
+
datasourceIdentifierMatchesFile,
|
|
14
|
+
resolveDatasourceFilePath
|
|
15
|
+
} = require('./datasource-identifier');
|
|
12
16
|
|
|
13
17
|
/**
|
|
14
18
|
* @param {string} appKey - Integration app key
|
|
@@ -43,13 +47,11 @@ function findDatasourceFileByKey(appPath, schemaBasePath, datasourceFiles, datas
|
|
|
43
47
|
const fsSync = require('fs');
|
|
44
48
|
for (const f of datasourceFiles) {
|
|
45
49
|
if (!f || typeof f !== 'string') continue;
|
|
46
|
-
const fullPath =
|
|
47
|
-
? path.join(schemaBasePath, f)
|
|
48
|
-
: path.join(appPath, schemaBasePath, f);
|
|
50
|
+
const fullPath = resolveDatasourceFilePath(appPath, schemaBasePath, f);
|
|
49
51
|
if (!fsSync.existsSync(fullPath)) continue;
|
|
50
52
|
try {
|
|
51
53
|
const parsed = loadConfigFile(fullPath);
|
|
52
|
-
if (
|
|
54
|
+
if (datasourceIdentifierMatchesFile(datasourceKey, f, parsed)) return f;
|
|
53
55
|
} catch {
|
|
54
56
|
// skip unreadable or invalid files
|
|
55
57
|
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Resolve integration/.data/ paths for datasource load/export (plan 144)
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const { getCwdIntegrationRoot, getIntegrationRoot } = require('../utils/paths');
|
|
12
|
+
|
|
13
|
+
const DATA_DIR_NAME = '.data';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Absolute path to integration/.data (cwd integration root preferred).
|
|
17
|
+
* @returns {string}
|
|
18
|
+
*/
|
|
19
|
+
function getIntegrationDataDir() {
|
|
20
|
+
const cwdRoot = getCwdIntegrationRoot();
|
|
21
|
+
const base = cwdRoot || getIntegrationRoot();
|
|
22
|
+
return path.join(base, DATA_DIR_NAME);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Entity suffix from datasource key and system key.
|
|
27
|
+
* @param {string} systemKey
|
|
28
|
+
* @param {string} datasourceKey
|
|
29
|
+
* @returns {string}
|
|
30
|
+
*/
|
|
31
|
+
function computeEntitySuffix(systemKey, datasourceKey) {
|
|
32
|
+
const sys = String(systemKey || '').trim();
|
|
33
|
+
const key = String(datasourceKey || '').trim();
|
|
34
|
+
const prefix = `${sys}-`;
|
|
35
|
+
if (sys && key.startsWith(prefix)) {
|
|
36
|
+
return key.slice(prefix.length) || key;
|
|
37
|
+
}
|
|
38
|
+
const lastHyphen = key.lastIndexOf('-');
|
|
39
|
+
if (lastHyphen > 0) {
|
|
40
|
+
return key.slice(lastHyphen + 1);
|
|
41
|
+
}
|
|
42
|
+
return key;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Default fixture basename (without extension).
|
|
47
|
+
* @param {string} systemKey
|
|
48
|
+
* @param {string} entitySuffix
|
|
49
|
+
* @returns {string}
|
|
50
|
+
*/
|
|
51
|
+
function defaultDataBasename(systemKey, entitySuffix) {
|
|
52
|
+
return `${systemKey}-data-${entitySuffix}`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @param {string} dir
|
|
57
|
+
* @param {string} basename
|
|
58
|
+
* @param {'json'|'ndjson'} format
|
|
59
|
+
* @returns {string}
|
|
60
|
+
*/
|
|
61
|
+
function dataFilePath(dir, basename, format) {
|
|
62
|
+
const ext = format === 'ndjson' ? '.ndjson' : '.json';
|
|
63
|
+
return path.join(dir, `${basename}${ext}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Infer format from file extension.
|
|
68
|
+
* @param {string} filePath
|
|
69
|
+
* @returns {'json'|'ndjson'}
|
|
70
|
+
*/
|
|
71
|
+
function inferFormatFromPath(filePath) {
|
|
72
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
73
|
+
if (ext === '.ndjson' || ext === '.jsonl') {
|
|
74
|
+
return 'ndjson';
|
|
75
|
+
}
|
|
76
|
+
return 'json';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Default integration/.data output path (file need not exist).
|
|
81
|
+
* @param {Object} opts
|
|
82
|
+
* @param {string} opts.systemKey
|
|
83
|
+
* @param {string} opts.entitySuffix
|
|
84
|
+
* @param {'json'|'ndjson'} [opts.format]
|
|
85
|
+
* @returns {{ filePath: string, format: 'json'|'ndjson' }}
|
|
86
|
+
*/
|
|
87
|
+
function resolveDefaultDataOutputPath(opts) {
|
|
88
|
+
const dir = getIntegrationDataDir();
|
|
89
|
+
const basename = defaultDataBasename(opts.systemKey, opts.entitySuffix);
|
|
90
|
+
const format = opts.format === 'ndjson' ? 'ndjson' : 'json';
|
|
91
|
+
return { filePath: dataFilePath(dir, basename, format), format };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Resolve data file: --file override or default integration/.data paths.
|
|
96
|
+
* @param {Object} opts
|
|
97
|
+
* @param {string} opts.systemKey
|
|
98
|
+
* @param {string} opts.entitySuffix
|
|
99
|
+
* @param {string} [opts.file] - CLI --file
|
|
100
|
+
* @param {'json'|'ndjson'} [opts.format] - explicit format
|
|
101
|
+
* @returns {{ filePath: string, format: 'json'|'ndjson' }}
|
|
102
|
+
*/
|
|
103
|
+
function resolveDataFilePath(opts) {
|
|
104
|
+
if (opts.file && String(opts.file).trim()) {
|
|
105
|
+
const filePath = path.resolve(String(opts.file).trim());
|
|
106
|
+
const format = opts.format || inferFormatFromPath(filePath);
|
|
107
|
+
return { filePath, format };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const dir = getIntegrationDataDir();
|
|
111
|
+
const basename = defaultDataBasename(opts.systemKey, opts.entitySuffix);
|
|
112
|
+
const jsonPath = dataFilePath(dir, basename, 'json');
|
|
113
|
+
const ndjsonPath = dataFilePath(dir, basename, 'ndjson');
|
|
114
|
+
|
|
115
|
+
if (opts.format === 'json' && fs.existsSync(jsonPath)) {
|
|
116
|
+
return { filePath: jsonPath, format: 'json' };
|
|
117
|
+
}
|
|
118
|
+
if (opts.format === 'ndjson' && fs.existsSync(ndjsonPath)) {
|
|
119
|
+
return { filePath: ndjsonPath, format: 'ndjson' };
|
|
120
|
+
}
|
|
121
|
+
if (!opts.format || opts.format === 'json') {
|
|
122
|
+
if (fs.existsSync(jsonPath)) {
|
|
123
|
+
return { filePath: jsonPath, format: 'json' };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (!opts.format || opts.format === 'ndjson') {
|
|
127
|
+
if (fs.existsSync(ndjsonPath)) {
|
|
128
|
+
return { filePath: ndjsonPath, format: 'ndjson' };
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
throw new Error(
|
|
133
|
+
`No local data file found. Expected one of:\n ${jsonPath}\n ${ndjsonPath}\n` +
|
|
134
|
+
'Use --file <path> to override.'
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
module.exports = {
|
|
139
|
+
getIntegrationDataDir,
|
|
140
|
+
computeEntitySuffix,
|
|
141
|
+
defaultDataBasename,
|
|
142
|
+
inferFormatFromPath,
|
|
143
|
+
resolveDefaultDataOutputPath,
|
|
144
|
+
resolveDataFilePath
|
|
145
|
+
};
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remove saved datasource test debug JSON under integration/<app>/logs/.
|
|
3
|
+
* @fileoverview Local cleanup for test / test-integration / test-e2e / test-trust logs
|
|
4
|
+
* @author AI Fabrix Team
|
|
5
|
+
* @version 1.0.0
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fsp = require('node:fs').promises;
|
|
10
|
+
const chalk = require('chalk');
|
|
11
|
+
const logger = require('../utils/logger');
|
|
12
|
+
const { getIntegrationPath, listIntegrationAppNames } = require('../utils/paths');
|
|
13
|
+
const { isStructuralTestLogFileName } = require('./log-viewer');
|
|
14
|
+
const { formatSuccessLine } = require('../utils/cli-test-layout-chalk');
|
|
15
|
+
|
|
16
|
+
/** @type {readonly string[]} */
|
|
17
|
+
const LOG_CLEAN_TYPES = ['test', 'integration', 'e2e', 'trust', 'all'];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} [type]
|
|
21
|
+
* @returns {'test'|'integration'|'e2e'|'trust'|'all'}
|
|
22
|
+
*/
|
|
23
|
+
function normalizeLogCleanType(type) {
|
|
24
|
+
const raw = (type === undefined || type === null ? 'all' : String(type)).trim().toLowerCase();
|
|
25
|
+
if (raw === '' || raw === 'all') return 'all';
|
|
26
|
+
if (LOG_CLEAN_TYPES.includes(raw)) return raw;
|
|
27
|
+
throw new Error(
|
|
28
|
+
`Invalid --type "${type}". Use: ${LOG_CLEAN_TYPES.join(', ')}`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {string} fileName
|
|
34
|
+
* @param {'test'|'integration'|'e2e'|'trust'|'all'} type
|
|
35
|
+
* @returns {boolean}
|
|
36
|
+
*/
|
|
37
|
+
function matchesLogCleanType(fileName, type) {
|
|
38
|
+
if (!fileName || !fileName.endsWith('.json')) return false;
|
|
39
|
+
if (type === 'all') return true;
|
|
40
|
+
if (type === 'test') return isStructuralTestLogFileName(fileName);
|
|
41
|
+
if (type === 'integration') {
|
|
42
|
+
return fileName.startsWith('test-integration-');
|
|
43
|
+
}
|
|
44
|
+
if (type === 'e2e') return fileName.startsWith('test-e2e-');
|
|
45
|
+
if (type === 'trust') return fileName.startsWith('test-trust-');
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @param {string} logsDir
|
|
51
|
+
* @param {'test'|'integration'|'e2e'|'trust'|'all'} type
|
|
52
|
+
* @returns {Promise<string[]>}
|
|
53
|
+
*/
|
|
54
|
+
async function listMatchingLogFiles(logsDir, type) {
|
|
55
|
+
let entries;
|
|
56
|
+
try {
|
|
57
|
+
entries = await fsp.readdir(logsDir, { withFileTypes: true });
|
|
58
|
+
} catch (err) {
|
|
59
|
+
if (err.code === 'ENOENT') return [];
|
|
60
|
+
throw err;
|
|
61
|
+
}
|
|
62
|
+
return entries
|
|
63
|
+
.filter(e => e.isFile() && matchesLogCleanType(e.name, type))
|
|
64
|
+
.map(e => path.join(logsDir, e.name))
|
|
65
|
+
.sort((a, b) => a.localeCompare(b));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @param {string} appKey
|
|
70
|
+
* @returns {Promise<void>}
|
|
71
|
+
*/
|
|
72
|
+
async function assertIntegrationAppExists(appKey) {
|
|
73
|
+
const appPath = getIntegrationPath(appKey);
|
|
74
|
+
try {
|
|
75
|
+
const st = await fsp.stat(appPath);
|
|
76
|
+
if (!st.isDirectory()) {
|
|
77
|
+
throw new Error(`Integration folder is not a directory: ${appPath}`);
|
|
78
|
+
}
|
|
79
|
+
} catch (err) {
|
|
80
|
+
if (err.code === 'ENOENT') {
|
|
81
|
+
throw new Error(`Integration folder not found: ${appPath}`);
|
|
82
|
+
}
|
|
83
|
+
throw err;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @param {Object} options
|
|
89
|
+
* @param {boolean} [options.all]
|
|
90
|
+
* @param {string} [options.app]
|
|
91
|
+
* @returns {Promise<string[]>}
|
|
92
|
+
*/
|
|
93
|
+
async function resolveTargetAppKeys(options) {
|
|
94
|
+
const useAll = Boolean(options.all);
|
|
95
|
+
const app = options.app && typeof options.app === 'string' ? options.app.trim() : '';
|
|
96
|
+
if (useAll && app) {
|
|
97
|
+
throw new Error('Use either --app <systemKey> or --all, not both');
|
|
98
|
+
}
|
|
99
|
+
if (!useAll && !app) {
|
|
100
|
+
throw new Error('Specify --app <systemKey> or --all');
|
|
101
|
+
}
|
|
102
|
+
if (useAll) {
|
|
103
|
+
return listIntegrationAppNames();
|
|
104
|
+
}
|
|
105
|
+
await assertIntegrationAppExists(app);
|
|
106
|
+
return [app];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @param {string[]} appKeys
|
|
111
|
+
* @param {'test'|'integration'|'e2e'|'trust'|'all'} type
|
|
112
|
+
* @returns {Promise<Array<{ appKey: string, logsDir: string, files: string[] }>>}
|
|
113
|
+
*/
|
|
114
|
+
async function collectLogFilesByApp(appKeys, type) {
|
|
115
|
+
const groups = [];
|
|
116
|
+
for (const appKey of appKeys) {
|
|
117
|
+
const logsDir = path.join(getIntegrationPath(appKey), 'logs');
|
|
118
|
+
const files = await listMatchingLogFiles(logsDir, type);
|
|
119
|
+
if (files.length > 0) {
|
|
120
|
+
groups.push({ appKey, logsDir, files });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return groups;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @param {Array<{ appKey: string, files: string[] }>} groups
|
|
128
|
+
* @param {boolean} dryRun
|
|
129
|
+
* @returns {Promise<{ removedCount: number, paths: string[] }>}
|
|
130
|
+
*/
|
|
131
|
+
async function removeCollectedFiles(groups, dryRun) {
|
|
132
|
+
const paths = groups.flatMap(g => g.files);
|
|
133
|
+
if (dryRun || paths.length === 0) {
|
|
134
|
+
return { removedCount: 0, paths };
|
|
135
|
+
}
|
|
136
|
+
await Promise.all(paths.map(filePath => fsp.unlink(filePath)));
|
|
137
|
+
return { removedCount: paths.length, paths };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @param {Object} options
|
|
142
|
+
* @param {boolean} options.dryRun
|
|
143
|
+
* @param {'test'|'integration'|'e2e'|'trust'|'all'} options.type
|
|
144
|
+
* @param {Array<{ appKey: string, files: string[] }>} groups
|
|
145
|
+
* @param {number} removedCount
|
|
146
|
+
*/
|
|
147
|
+
function printCleanLogsSummary(options, groups, removedCount) {
|
|
148
|
+
const totalFiles = groups.reduce((n, g) => n + g.files.length, 0);
|
|
149
|
+
const appCount = groups.length;
|
|
150
|
+
if (options.dryRun) {
|
|
151
|
+
if (totalFiles === 0) {
|
|
152
|
+
logger.log(chalk.gray('No matching log files found.'));
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
logger.log('');
|
|
156
|
+
logger.log(
|
|
157
|
+
chalk.gray(
|
|
158
|
+
`Would remove ${totalFiles} file(s) from ${appCount} integration folder(s) (type: ${options.type}).`
|
|
159
|
+
)
|
|
160
|
+
);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (totalFiles === 0) {
|
|
164
|
+
logger.log(chalk.gray('No matching log files to remove.'));
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
logger.log('');
|
|
168
|
+
logger.log(formatSuccessLine(`Removed ${removedCount} log file(s) from ${appCount} integration folder(s).`));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* @param {boolean} dryRun
|
|
173
|
+
* @param {Array<{ appKey: string, logsDir: string, files: string[] }>} groups
|
|
174
|
+
*/
|
|
175
|
+
function printCleanLogsFileList(dryRun, groups) {
|
|
176
|
+
const prefix = dryRun ? 'Would remove' : 'Removing';
|
|
177
|
+
for (const { appKey, files } of groups) {
|
|
178
|
+
logger.log('');
|
|
179
|
+
logger.log(chalk.bold.white(`${appKey}/logs/`));
|
|
180
|
+
for (const filePath of files) {
|
|
181
|
+
logger.log(chalk.gray(` ${prefix}: ${filePath}`));
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* @param {Object} result
|
|
188
|
+
* @param {boolean} result.dryRun
|
|
189
|
+
* @param {string} result.type
|
|
190
|
+
* @param {string[]} result.appKeys
|
|
191
|
+
* @param {string[]} result.paths
|
|
192
|
+
* @param {number} result.removedCount
|
|
193
|
+
*/
|
|
194
|
+
function printCleanLogsJson(result) {
|
|
195
|
+
const payload = {
|
|
196
|
+
dryRun: result.dryRun,
|
|
197
|
+
type: result.type,
|
|
198
|
+
appKeys: result.appKeys,
|
|
199
|
+
fileCount: result.paths.length,
|
|
200
|
+
paths: result.paths,
|
|
201
|
+
removedCount: result.removedCount
|
|
202
|
+
};
|
|
203
|
+
logger.log(JSON.stringify(payload, null, 2));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* @async
|
|
208
|
+
* @param {Object} options
|
|
209
|
+
* @param {boolean} [options.all]
|
|
210
|
+
* @param {string} [options.app]
|
|
211
|
+
* @param {string} [options.type]
|
|
212
|
+
* @param {boolean} [options.dryRun]
|
|
213
|
+
* @param {boolean} [options.json]
|
|
214
|
+
* @returns {Promise<{ dryRun: boolean, type: string, appKeys: string[], paths: string[], removedCount: number }>}
|
|
215
|
+
*/
|
|
216
|
+
async function runCleanLogs(options = {}) {
|
|
217
|
+
const dryRun = Boolean(options.dryRun);
|
|
218
|
+
const json = Boolean(options.json);
|
|
219
|
+
const type = normalizeLogCleanType(options.type);
|
|
220
|
+
const appKeys = await resolveTargetAppKeys(options);
|
|
221
|
+
const groups = await collectLogFilesByApp(appKeys, type);
|
|
222
|
+
const { removedCount, paths } = await removeCollectedFiles(groups, dryRun);
|
|
223
|
+
const result = { dryRun, type, appKeys, paths, removedCount };
|
|
224
|
+
if (json) {
|
|
225
|
+
printCleanLogsJson(result);
|
|
226
|
+
} else {
|
|
227
|
+
printCleanLogsFileList(dryRun, groups);
|
|
228
|
+
printCleanLogsSummary({ dryRun, type }, groups, removedCount);
|
|
229
|
+
}
|
|
230
|
+
return result;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
module.exports = {
|
|
234
|
+
LOG_CLEAN_TYPES,
|
|
235
|
+
normalizeLogCleanType,
|
|
236
|
+
matchesLogCleanType,
|
|
237
|
+
listMatchingLogFiles,
|
|
238
|
+
resolveTargetAppKeys,
|
|
239
|
+
collectLogFilesByApp,
|
|
240
|
+
runCleanLogs
|
|
241
|
+
};
|