@aifabrix/builder 2.32.2 → 2.33.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/project-rules.mdc +8 -0
- package/README.md +36 -8
- package/bin/aifabrix.js +6 -8
- package/integration/hubspot/README.md +8 -7
- package/integration/hubspot/companies.json +2048 -0
- package/integration/hubspot/create-hubspot.js +665 -0
- package/integration/hubspot/{hubspot-deploy-company.json → hubspot-datasource-company.json} +1 -1
- package/integration/hubspot/{hubspot-deploy-contact.json → hubspot-datasource-contact.json} +1 -1
- package/integration/hubspot/{hubspot-deploy-deal.json → hubspot-datasource-deal.json} +1 -1
- package/integration/hubspot/hubspot-deploy.json +832 -81
- package/integration/hubspot/hubspot-system.json +99 -0
- package/integration/hubspot/test-artifacts/wizard-hubspot-credential-real.yaml +20 -0
- package/integration/hubspot/test-artifacts/wizard-hubspot-env-vars.yaml +9 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-add-datasource.yaml +5 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-app-name.yaml +5 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-credential-create.yaml +7 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-credential-select.yaml +7 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-known-platform.yaml +4 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-missing-app.yaml +4 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-missing-source.yaml +2 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-mode.yaml +5 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-openapi-file.yaml +5 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-openapi-url.yaml +4 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-source.yaml +4 -0
- package/integration/hubspot/test-artifacts/wizard-valid-for-dimension-array-test.yaml +5 -0
- package/integration/hubspot/test-artifacts/wizard-valid-for-dimension-key-test.yaml +5 -0
- package/integration/hubspot/test-artifacts/wizard-valid-for-dimension-path-test.yaml +5 -0
- package/integration/hubspot/test-artifacts/wizard-valid-for-dimension-test.yaml +5 -0
- package/integration/hubspot/test-artifacts/wizard-valid-for-rbac-test.yaml +5 -0
- package/integration/hubspot/test-artifacts/wizard-valid-for-rbac-yaml-test.yaml +5 -0
- package/integration/hubspot/test-dataplane-down-helpers.js +246 -0
- package/integration/hubspot/test-dataplane-down-tests.js +419 -0
- package/integration/hubspot/test-dataplane-down.js +157 -0
- package/integration/hubspot/test.js +1517 -0
- package/integration/hubspot/variables.yaml +4 -4
- package/integration/hubspot/wizard-hubspot-e2e.yaml +16 -0
- package/integration/hubspot/wizard-hubspot-platform.yaml +8 -0
- package/lib/api/applications.api.js +1 -0
- package/lib/api/index.js +10 -5
- package/lib/api/types/wizard.types.js +176 -38
- package/lib/api/wizard.api.js +207 -38
- package/lib/app/deploy.js +116 -54
- package/lib/app/display.js +6 -5
- package/lib/app/dockerfile.js +2 -1
- package/lib/app/list.js +78 -37
- package/lib/app/prompts.js +9 -5
- package/lib/app/readme.js +41 -112
- package/lib/app/register.js +44 -9
- package/lib/app/rotate-secret.js +50 -32
- package/lib/cli.js +243 -65
- package/lib/commands/app.js +4 -9
- package/lib/commands/auth-config.js +125 -0
- package/lib/commands/auth-status.js +261 -0
- package/lib/commands/datasource.js +3 -6
- package/lib/commands/login-credentials.js +4 -4
- package/lib/commands/login-device.js +43 -29
- package/lib/commands/login.js +22 -13
- package/lib/commands/wizard-config-normalizer.js +92 -0
- package/lib/commands/wizard-core.js +515 -0
- package/lib/commands/wizard-dataplane.js +122 -0
- package/lib/commands/wizard-headless.js +115 -0
- package/lib/commands/wizard.js +129 -357
- package/lib/core/config.js +46 -0
- package/lib/core/secrets.js +3 -22
- package/lib/core/templates-env.js +1 -1
- package/lib/datasource/deploy.js +34 -23
- package/lib/datasource/list.js +8 -6
- package/lib/deployment/deployer.js +25 -0
- package/lib/deployment/environment.js +10 -13
- package/lib/external-system/delete.js +151 -0
- package/lib/external-system/deploy.js +54 -378
- package/lib/external-system/download-helpers.js +45 -65
- package/lib/external-system/download.js +34 -13
- package/lib/external-system/generator.js +11 -7
- package/lib/external-system/test-auth.js +5 -3
- package/lib/generator/builders.js +3 -1
- package/lib/generator/external-controller-manifest.js +157 -0
- package/lib/generator/external-schema-utils.js +236 -0
- package/lib/generator/external.js +55 -3
- package/lib/generator/index.js +22 -10
- package/lib/generator/wizard-prompts.js +33 -10
- package/lib/generator/wizard.js +69 -86
- package/lib/infrastructure/compose.js +100 -0
- package/lib/infrastructure/helpers.js +139 -0
- package/lib/infrastructure/index.js +52 -311
- package/lib/infrastructure/services.js +168 -0
- package/lib/schema/application-schema.json +24 -5
- package/lib/schema/external-datasource.schema.json +303 -17
- package/lib/schema/external-system.schema.json +1 -1
- package/lib/schema/wizard-config.schema.json +234 -0
- package/lib/utils/api.js +37 -42
- package/lib/utils/app-existence.js +42 -0
- package/lib/utils/app-register-config.js +7 -2
- package/lib/utils/app-register-display.js +2 -1
- package/lib/utils/auth-config-validator.js +92 -0
- package/lib/utils/cli-utils.js +3 -1
- package/lib/utils/command-header.js +43 -0
- package/lib/utils/compose-generator.js +113 -70
- package/lib/utils/controller-url.js +115 -0
- package/lib/utils/dataplane-health.js +115 -0
- package/lib/utils/dataplane-resolver.js +29 -0
- package/lib/utils/dev-config.js +6 -2
- package/lib/utils/env-copy.js +2 -1
- package/lib/utils/env-map.js +2 -1
- package/lib/utils/env-ports.js +2 -1
- package/lib/utils/env-template.js +1 -1
- package/lib/utils/error-formatter.js +149 -28
- package/lib/utils/external-readme.js +125 -0
- package/lib/utils/help-builder.js +190 -0
- package/lib/utils/infra-status.js +13 -3
- package/lib/utils/paths.js +17 -2
- package/lib/utils/port-resolver.js +111 -0
- package/lib/utils/secrets-helpers.js +3 -15
- package/lib/utils/secrets-utils.js +2 -2
- package/lib/utils/token-manager.js +69 -4
- package/lib/utils/variable-transformer.js +7 -2
- package/lib/validation/external-manifest-validator.js +202 -0
- package/lib/validation/validate-display.js +406 -0
- package/lib/validation/validate.js +159 -123
- package/lib/validation/validator.js +38 -4
- package/lib/validation/wizard-config-validator.js +267 -0
- package/package.json +4 -2
- package/templates/applications/README.md.hbs +19 -17
- package/templates/applications/miso-controller/env.template +1 -1
- package/templates/applications/miso-controller/rbac.yaml +7 -7
- package/templates/external-system/README.md.hbs +99 -0
- package/templates/external-system/external-system.json.hbs +1 -1
- package/templates/infra/compose.yaml.hbs +35 -0
- package/templates/python/docker-compose.hbs +26 -0
- package/templates/typescript/docker-compose.hbs +26 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External System Manifest Validator
|
|
3
|
+
*
|
|
4
|
+
* Validates controller deployment manifest for external systems.
|
|
5
|
+
* Validates against application-schema.json and component schemas.
|
|
6
|
+
*
|
|
7
|
+
* @fileoverview Manifest validation for external systems
|
|
8
|
+
* @author AI Fabrix Team
|
|
9
|
+
* @version 2.0.0
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const Ajv = require('ajv');
|
|
13
|
+
const fs = require('fs');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const { formatValidationErrors } = require('../utils/error-formatter');
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Sets up AJV validator with external schemas
|
|
19
|
+
* @async
|
|
20
|
+
* @function setupAjvWithSchemas
|
|
21
|
+
* @returns {Promise<Object>} AJV instance and schemas
|
|
22
|
+
*/
|
|
23
|
+
async function setupAjvWithSchemas() {
|
|
24
|
+
const ajv = new Ajv({
|
|
25
|
+
allErrors: true,
|
|
26
|
+
strict: false,
|
|
27
|
+
removeAdditional: false
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Load raw schema objects (not compiled validators)
|
|
31
|
+
const externalSystemSchemaPath = path.join(__dirname, '..', 'schema', 'external-system.schema.json');
|
|
32
|
+
const externalDatasourceSchemaPath = path.join(__dirname, '..', 'schema', 'external-datasource.schema.json');
|
|
33
|
+
|
|
34
|
+
const externalSystemSchema = JSON.parse(fs.readFileSync(externalSystemSchemaPath, 'utf8'));
|
|
35
|
+
let externalDatasourceSchema = JSON.parse(fs.readFileSync(externalDatasourceSchemaPath, 'utf8'));
|
|
36
|
+
|
|
37
|
+
// Remove $schema for draft-2020-12 to avoid AJV issues
|
|
38
|
+
if (externalDatasourceSchema.$schema && externalDatasourceSchema.$schema.includes('2020-12')) {
|
|
39
|
+
const schemaCopy = { ...externalDatasourceSchema };
|
|
40
|
+
delete schemaCopy.$schema;
|
|
41
|
+
externalDatasourceSchema = schemaCopy;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const externalSystemSchemaId = externalSystemSchema.$id || 'https://raw.githubusercontent.com/esystemsdev/aifabrix-builder/refs/heads/main/lib/schema/external-system.schema.json';
|
|
45
|
+
const externalDatasourceSchemaId = externalDatasourceSchema.$id || 'https://raw.githubusercontent.com/esystemsdev/aifabrix-builder/refs/heads/main/lib/schema/external-datasource.schema.json';
|
|
46
|
+
|
|
47
|
+
ajv.addSchema(externalSystemSchema, externalSystemSchemaId);
|
|
48
|
+
ajv.addSchema(externalDatasourceSchema, externalDatasourceSchemaId);
|
|
49
|
+
|
|
50
|
+
return { ajv, externalSystemSchema, externalDatasourceSchema };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Validates manifest structure
|
|
55
|
+
* @function validateManifestStructure
|
|
56
|
+
* @param {Object} manifest - Manifest object
|
|
57
|
+
* @param {Object} ajv - AJV instance
|
|
58
|
+
* @param {Object} applicationSchema - Application schema
|
|
59
|
+
* @param {Array} errors - Errors array to append to
|
|
60
|
+
* @returns {void}
|
|
61
|
+
*/
|
|
62
|
+
function validateManifestStructure(manifest, ajv, applicationSchema, errors) {
|
|
63
|
+
const validateManifest = ajv.compile(applicationSchema);
|
|
64
|
+
const manifestValid = validateManifest(manifest);
|
|
65
|
+
|
|
66
|
+
if (!manifestValid) {
|
|
67
|
+
const manifestErrors = formatValidationErrors(validateManifest.errors);
|
|
68
|
+
errors.push(...manifestErrors.map(err => `Manifest validation: ${err}`));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Validates inline system
|
|
74
|
+
* @function validateInlineSystem
|
|
75
|
+
* @param {Object} manifest - Manifest object
|
|
76
|
+
* @param {Object} ajv - AJV instance
|
|
77
|
+
* @param {Object} externalSystemSchema - External system schema
|
|
78
|
+
* @param {Array} errors - Errors array to append to
|
|
79
|
+
* @returns {void}
|
|
80
|
+
*/
|
|
81
|
+
function validateInlineSystem(manifest, ajv, externalSystemSchema, errors) {
|
|
82
|
+
if (manifest.system) {
|
|
83
|
+
const validateSystem = ajv.compile(externalSystemSchema);
|
|
84
|
+
const systemValid = validateSystem(manifest.system);
|
|
85
|
+
|
|
86
|
+
if (!systemValid) {
|
|
87
|
+
const systemErrors = formatValidationErrors(validateSystem.errors);
|
|
88
|
+
errors.push(...systemErrors.map(err => `System validation: ${err}`));
|
|
89
|
+
}
|
|
90
|
+
} else if (manifest.type === 'external') {
|
|
91
|
+
errors.push('System is required for external type applications');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Validates datasources
|
|
97
|
+
* @function validateDatasources
|
|
98
|
+
* @param {Object} manifest - Manifest object
|
|
99
|
+
* @param {Object} ajv - AJV instance
|
|
100
|
+
* @param {Object} externalDatasourceSchema - External datasource schema
|
|
101
|
+
* @param {Array} errors - Errors array to append to
|
|
102
|
+
* @param {Array} warnings - Warnings array to append to
|
|
103
|
+
* @returns {void}
|
|
104
|
+
*/
|
|
105
|
+
function validateDatasources(manifest, ajv, externalDatasourceSchema, errors, warnings) {
|
|
106
|
+
if (manifest.dataSources) {
|
|
107
|
+
if (!Array.isArray(manifest.dataSources)) {
|
|
108
|
+
errors.push('dataSources must be an array');
|
|
109
|
+
} else {
|
|
110
|
+
const validateDatasource = ajv.compile(externalDatasourceSchema);
|
|
111
|
+
manifest.dataSources.forEach((datasource, index) => {
|
|
112
|
+
const datasourceValid = validateDatasource(datasource);
|
|
113
|
+
if (!datasourceValid) {
|
|
114
|
+
const datasourceErrors = formatValidationErrors(validateDatasource.errors);
|
|
115
|
+
errors.push(...datasourceErrors.map(err => `Datasource ${index + 1} (${datasource.key || 'unknown'}): ${err}`));
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
} else if (manifest.type === 'external') {
|
|
120
|
+
warnings.push('No dataSources specified - external system may not have any datasources');
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Validates conditional requirements
|
|
126
|
+
* @function validateConditionalRequirements
|
|
127
|
+
* @param {Object} manifest - Manifest object
|
|
128
|
+
* @param {Array} errors - Errors array to append to
|
|
129
|
+
* @param {Array} warnings - Warnings array to append to
|
|
130
|
+
* @returns {void}
|
|
131
|
+
*/
|
|
132
|
+
function validateConditionalRequirements(manifest, errors, warnings) {
|
|
133
|
+
if (manifest.type === 'external') {
|
|
134
|
+
if (!manifest.system) {
|
|
135
|
+
errors.push('System is required for external type applications');
|
|
136
|
+
}
|
|
137
|
+
if (!manifest.dataSources || manifest.dataSources.length === 0) {
|
|
138
|
+
warnings.push('No dataSources specified for external system');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Validates required fields
|
|
145
|
+
* @function validateRequiredFields
|
|
146
|
+
* @param {Object} manifest - Manifest object
|
|
147
|
+
* @param {Array} errors - Errors array to append to
|
|
148
|
+
* @returns {void}
|
|
149
|
+
*/
|
|
150
|
+
function validateRequiredFields(manifest, errors) {
|
|
151
|
+
const requiredFields = ['key', 'displayName', 'description', 'type', 'deploymentKey'];
|
|
152
|
+
requiredFields.forEach(field => {
|
|
153
|
+
if (!manifest[field]) {
|
|
154
|
+
errors.push(`Required field "${field}" is missing`);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Validates controller deployment manifest for external systems
|
|
161
|
+
* Validates manifest structure and inline system/dataSources against their schemas
|
|
162
|
+
*
|
|
163
|
+
* @async
|
|
164
|
+
* @function validateControllerManifest
|
|
165
|
+
* @param {Object} manifest - Controller manifest object
|
|
166
|
+
* @returns {Promise<Object>} Validation result
|
|
167
|
+
* @throws {Error} If validation fails critically
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* const result = await validateControllerManifest(manifest);
|
|
171
|
+
* // Returns: { valid: true, errors: [], warnings: [] }
|
|
172
|
+
*/
|
|
173
|
+
async function validateControllerManifest(manifest) {
|
|
174
|
+
if (!manifest || typeof manifest !== 'object') {
|
|
175
|
+
return {
|
|
176
|
+
valid: false,
|
|
177
|
+
errors: ['Manifest is required and must be an object'],
|
|
178
|
+
warnings: []
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const errors = [];
|
|
183
|
+
const warnings = [];
|
|
184
|
+
const applicationSchema = require('../schema/application-schema.json');
|
|
185
|
+
const { ajv, externalSystemSchema, externalDatasourceSchema } = await setupAjvWithSchemas();
|
|
186
|
+
|
|
187
|
+
validateManifestStructure(manifest, ajv, applicationSchema, errors);
|
|
188
|
+
validateInlineSystem(manifest, ajv, externalSystemSchema, errors);
|
|
189
|
+
validateDatasources(manifest, ajv, externalDatasourceSchema, errors, warnings);
|
|
190
|
+
validateConditionalRequirements(manifest, errors, warnings);
|
|
191
|
+
validateRequiredFields(manifest, errors);
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
valid: errors.length === 0,
|
|
195
|
+
errors,
|
|
196
|
+
warnings
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
module.exports = {
|
|
201
|
+
validateControllerManifest
|
|
202
|
+
};
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation Display Utilities
|
|
3
|
+
*
|
|
4
|
+
* Display functions for validation results output.
|
|
5
|
+
*
|
|
6
|
+
* @fileoverview Validation display utilities for AI Fabrix Builder
|
|
7
|
+
* @author AI Fabrix Team
|
|
8
|
+
* @version 2.0.0
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const chalk = require('chalk');
|
|
13
|
+
const logger = require('../utils/logger');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Displays application validation results
|
|
17
|
+
* @function displayApplicationValidation
|
|
18
|
+
* @param {Object} application - Application validation result
|
|
19
|
+
*/
|
|
20
|
+
function displayApplicationValidation(application) {
|
|
21
|
+
if (!application) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
logger.log(chalk.blue('\nApplication:'));
|
|
26
|
+
if (application.valid) {
|
|
27
|
+
logger.log(chalk.green(' ✓ Application configuration is valid'));
|
|
28
|
+
} else {
|
|
29
|
+
logger.log(chalk.red(' ✗ Application configuration has errors:'));
|
|
30
|
+
if (application.errors && application.errors.length > 0) {
|
|
31
|
+
application.errors.forEach(error => {
|
|
32
|
+
logger.log(chalk.red(` • ${error}`));
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (application.warnings && application.warnings.length > 0) {
|
|
37
|
+
application.warnings.forEach(warning => {
|
|
38
|
+
logger.log(chalk.yellow(` ⚠ ${warning}`));
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Extracts dimensions from a datasource file
|
|
45
|
+
* @function extractDimensionsFromDatasource
|
|
46
|
+
* @param {string} filePath - Path to datasource file
|
|
47
|
+
* @returns {Object} Dimensions info { dimensions: Object, hasDimensions: boolean }
|
|
48
|
+
*/
|
|
49
|
+
function extractDimensionsFromDatasource(filePath) {
|
|
50
|
+
try {
|
|
51
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
52
|
+
const parsed = JSON.parse(content);
|
|
53
|
+
|
|
54
|
+
// Check fieldMappings.dimensions (primary location)
|
|
55
|
+
const dimensions = parsed.fieldMappings?.dimensions || {};
|
|
56
|
+
const abacDimensions = parsed.abac?.dimensions || {};
|
|
57
|
+
|
|
58
|
+
// Merge both sources (abac.dimensions can override fieldMappings.dimensions)
|
|
59
|
+
const allDimensions = { ...dimensions, ...abacDimensions };
|
|
60
|
+
const dimensionKeys = Object.keys(allDimensions);
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
dimensions: allDimensions,
|
|
64
|
+
dimensionKeys,
|
|
65
|
+
hasDimensions: dimensionKeys.length > 0
|
|
66
|
+
};
|
|
67
|
+
} catch {
|
|
68
|
+
return { dimensions: {}, dimensionKeys: [], hasDimensions: false };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Displays external files validation results
|
|
74
|
+
* @function displayExternalFilesValidation
|
|
75
|
+
* @param {Array} externalFiles - External files validation results
|
|
76
|
+
*/
|
|
77
|
+
function displayExternalFilesValidation(externalFiles) {
|
|
78
|
+
if (!externalFiles || externalFiles.length === 0) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
logger.log(chalk.blue('\nExternal Integration Files:'));
|
|
83
|
+
externalFiles.forEach(file => {
|
|
84
|
+
if (file.valid) {
|
|
85
|
+
logger.log(chalk.green(` ✓ ${file.file} (${file.type})`));
|
|
86
|
+
} else {
|
|
87
|
+
logger.log(chalk.red(` ✗ ${file.file} (${file.type}):`));
|
|
88
|
+
file.errors.forEach(error => {
|
|
89
|
+
logger.log(chalk.red(` • ${error}`));
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
if (file.warnings && file.warnings.length > 0) {
|
|
93
|
+
file.warnings.forEach(warning => {
|
|
94
|
+
logger.log(chalk.yellow(` ⚠ ${warning}`));
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Displays Dimensions (ABAC) validation results for datasources
|
|
102
|
+
* @function displayDimensionsValidation
|
|
103
|
+
* @param {Array} externalFiles - External files validation results
|
|
104
|
+
* @returns {Array} Warnings to add to aggregated warnings
|
|
105
|
+
*/
|
|
106
|
+
function displayDimensionsValidation(externalFiles) {
|
|
107
|
+
if (!externalFiles || externalFiles.length === 0) {
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const datasourceFiles = externalFiles.filter(f =>
|
|
112
|
+
f.type === 'datasource' || f.type === 'external-datasource'
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
if (datasourceFiles.length === 0) {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
logger.log(chalk.blue('\nDimensions (ABAC):'));
|
|
120
|
+
|
|
121
|
+
const warnings = [];
|
|
122
|
+
let anyDatasourceHasDimensions = false;
|
|
123
|
+
|
|
124
|
+
datasourceFiles.forEach(file => {
|
|
125
|
+
const dimensionsInfo = extractDimensionsFromDatasource(file.path);
|
|
126
|
+
|
|
127
|
+
if (dimensionsInfo.hasDimensions) {
|
|
128
|
+
anyDatasourceHasDimensions = true;
|
|
129
|
+
logger.log(chalk.green(` ✓ ${file.file}`));
|
|
130
|
+
dimensionsInfo.dimensionKeys.forEach(key => {
|
|
131
|
+
const mapping = dimensionsInfo.dimensions[key];
|
|
132
|
+
logger.log(chalk.gray(` ${key} → ${mapping}`));
|
|
133
|
+
});
|
|
134
|
+
} else {
|
|
135
|
+
logger.log(chalk.yellow(` ⚠ ${file.file} - no dimensions configured`));
|
|
136
|
+
warnings.push(`${file.file} - no dimensions configured, ABAC filtering disabled`);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
if (!anyDatasourceHasDimensions) {
|
|
141
|
+
logger.log(chalk.yellow(' ⚠ No dimensions configured - ABAC filtering disabled for all datasources'));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return warnings;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Displays RBAC validation results
|
|
149
|
+
* @function displayRbacValidation
|
|
150
|
+
* @param {Object} rbac - RBAC validation result
|
|
151
|
+
*/
|
|
152
|
+
function displayRbacValidation(rbac) {
|
|
153
|
+
if (!rbac) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
logger.log(chalk.blue('\nRBAC Configuration:'));
|
|
158
|
+
if (rbac.valid) {
|
|
159
|
+
logger.log(chalk.green(' ✓ RBAC configuration is valid'));
|
|
160
|
+
} else {
|
|
161
|
+
logger.log(chalk.red(' ✗ RBAC configuration has errors:'));
|
|
162
|
+
rbac.errors.forEach(error => {
|
|
163
|
+
logger.log(chalk.red(` • ${error}`));
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
if (rbac.warnings && rbac.warnings.length > 0) {
|
|
167
|
+
rbac.warnings.forEach(warning => {
|
|
168
|
+
logger.log(chalk.yellow(` ⚠ ${warning}`));
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Displays file validation results (for direct file validation)
|
|
175
|
+
* @function displayFileValidation
|
|
176
|
+
* @param {Object} result - Validation result
|
|
177
|
+
*/
|
|
178
|
+
function displayFileValidation(result) {
|
|
179
|
+
if (!result.file) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
logger.log(chalk.blue(`\nFile: ${result.file}`));
|
|
184
|
+
logger.log(chalk.blue(`Type: ${result.type}`));
|
|
185
|
+
if (result.valid) {
|
|
186
|
+
logger.log(chalk.green(' ✓ File is valid'));
|
|
187
|
+
} else {
|
|
188
|
+
logger.log(chalk.red(' ✗ File has errors:'));
|
|
189
|
+
result.errors.forEach(error => {
|
|
190
|
+
logger.log(chalk.red(` • ${error}`));
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
if (result.warnings && result.warnings.length > 0) {
|
|
194
|
+
result.warnings.forEach(warning => {
|
|
195
|
+
logger.log(chalk.yellow(` ⚠ ${warning}`));
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Displays aggregated warnings
|
|
202
|
+
* @function displayAggregatedWarnings
|
|
203
|
+
* @param {Array} warnings - Array of warning messages
|
|
204
|
+
*/
|
|
205
|
+
function displayAggregatedWarnings(warnings) {
|
|
206
|
+
if (!warnings || warnings.length === 0) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
logger.log(chalk.yellow('\nWarnings:'));
|
|
211
|
+
warnings.forEach(warning => {
|
|
212
|
+
logger.log(chalk.yellow(` • ${warning}`));
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Displays application validation step
|
|
218
|
+
* @function displayApplicationStep
|
|
219
|
+
* @param {Object} application - Application validation result
|
|
220
|
+
* @returns {void}
|
|
221
|
+
*/
|
|
222
|
+
function displayApplicationStep(application) {
|
|
223
|
+
logger.log(chalk.blue('\nApplication:'));
|
|
224
|
+
if (application.valid) {
|
|
225
|
+
logger.log(chalk.green(' ✓ Application configuration is valid'));
|
|
226
|
+
} else {
|
|
227
|
+
logger.log(chalk.red(' ✗ Application configuration has errors:'));
|
|
228
|
+
application.errors.forEach(error => {
|
|
229
|
+
logger.log(chalk.red(` • ${error}`));
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
if (application.warnings && application.warnings.length > 0) {
|
|
233
|
+
application.warnings.forEach(warning => {
|
|
234
|
+
logger.log(chalk.yellow(` ⚠ ${warning}`));
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Displays external integration files step
|
|
241
|
+
* @function displayComponentsStep
|
|
242
|
+
* @param {Object} components - Components validation result
|
|
243
|
+
* @returns {void}
|
|
244
|
+
*/
|
|
245
|
+
function displayComponentsStep(components) {
|
|
246
|
+
if (!components.files || components.files.length === 0) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
logger.log(chalk.blue('\nExternal Integration Files:'));
|
|
251
|
+
components.files.forEach(file => {
|
|
252
|
+
if (file.valid) {
|
|
253
|
+
logger.log(chalk.green(` ✓ ${file.file} (${file.type})`));
|
|
254
|
+
} else {
|
|
255
|
+
logger.log(chalk.red(` ✗ ${file.file} (${file.type})`));
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
if (components.errors && components.errors.length > 0) {
|
|
260
|
+
components.errors.forEach(error => {
|
|
261
|
+
logger.log(chalk.red(` • ${error}`));
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Displays dimensions validation for datasources
|
|
268
|
+
* @function displayDimensionsStep
|
|
269
|
+
* @param {Array} datasourceFiles - Datasource files
|
|
270
|
+
* @returns {void}
|
|
271
|
+
*/
|
|
272
|
+
function displayDimensionsStep(datasourceFiles) {
|
|
273
|
+
if (datasourceFiles.length === 0) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
logger.log(chalk.blue('\nDimensions (ABAC):'));
|
|
278
|
+
datasourceFiles.forEach(file => {
|
|
279
|
+
try {
|
|
280
|
+
const dimensionsInfo = extractDimensionsFromDatasource(file.path || file.file);
|
|
281
|
+
if (dimensionsInfo.hasDimensions) {
|
|
282
|
+
logger.log(chalk.green(` ✓ ${file.file}`));
|
|
283
|
+
dimensionsInfo.dimensionKeys.forEach(key => {
|
|
284
|
+
const mapping = dimensionsInfo.dimensions[key];
|
|
285
|
+
logger.log(chalk.gray(` ${key} → ${mapping}`));
|
|
286
|
+
});
|
|
287
|
+
} else {
|
|
288
|
+
logger.log(chalk.yellow(` ⚠ ${file.file} - no dimensions configured`));
|
|
289
|
+
}
|
|
290
|
+
} catch {
|
|
291
|
+
// Skip if file path not available
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Displays deployment manifest step
|
|
298
|
+
* @function displayManifestStep
|
|
299
|
+
* @param {Object} manifest - Manifest validation result
|
|
300
|
+
* @param {Array} componentFiles - Component files
|
|
301
|
+
* @returns {void}
|
|
302
|
+
*/
|
|
303
|
+
function displayManifestStep(manifest, componentFiles) {
|
|
304
|
+
logger.log(chalk.blue('\nDeployment Manifest:'));
|
|
305
|
+
if (manifest.valid) {
|
|
306
|
+
logger.log(chalk.green(' ✓ Full deployment manifest is valid'));
|
|
307
|
+
if (componentFiles) {
|
|
308
|
+
const datasourceFiles = componentFiles.filter(f => f.type === 'datasource' || f.type === 'external-datasource');
|
|
309
|
+
logger.log(chalk.green(' ✓ System configuration valid'));
|
|
310
|
+
logger.log(chalk.green(` ✓ ${datasourceFiles.length} datasource(s) valid`));
|
|
311
|
+
logger.log(chalk.green(' ✓ Schema validation passed'));
|
|
312
|
+
}
|
|
313
|
+
} else {
|
|
314
|
+
logger.log(chalk.red(' ✗ Full deployment manifest validation failed:'));
|
|
315
|
+
if (manifest.errors && manifest.errors.length > 0) {
|
|
316
|
+
manifest.errors.forEach(error => {
|
|
317
|
+
logger.log(chalk.red(` • ${error}`));
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if (manifest.warnings && manifest.warnings.length > 0) {
|
|
322
|
+
manifest.warnings.forEach(warning => {
|
|
323
|
+
logger.log(chalk.yellow(` ⚠ ${warning}`));
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Displays step-by-step validation results for external systems
|
|
330
|
+
* @function displayStepByStepValidation
|
|
331
|
+
* @param {Object} result - Validation result with steps
|
|
332
|
+
*/
|
|
333
|
+
function displayStepByStepValidation(result) {
|
|
334
|
+
if (result.valid) {
|
|
335
|
+
logger.log(chalk.green('\n✓ Validation passed!'));
|
|
336
|
+
} else {
|
|
337
|
+
logger.log(chalk.red('\n✗ Validation failed!'));
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
displayApplicationStep(result.steps.application);
|
|
341
|
+
|
|
342
|
+
if (result.steps.components.files && result.steps.components.files.length > 0) {
|
|
343
|
+
displayComponentsStep(result.steps.components);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const datasourceFiles = result.steps.components.files?.filter(f =>
|
|
347
|
+
f.type === 'datasource' || f.type === 'external-datasource'
|
|
348
|
+
) || [];
|
|
349
|
+
displayDimensionsStep(datasourceFiles);
|
|
350
|
+
|
|
351
|
+
if (result.rbac) {
|
|
352
|
+
displayRbacValidation(result.rbac);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
displayManifestStep(result.steps.manifest, result.steps.components.files);
|
|
356
|
+
|
|
357
|
+
if (result.warnings && result.warnings.length > 0) {
|
|
358
|
+
displayAggregatedWarnings(result.warnings);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Displays validation results in a user-friendly format
|
|
364
|
+
*
|
|
365
|
+
* @function displayValidationResults
|
|
366
|
+
* @param {Object} result - Validation result from validateAppOrFile
|
|
367
|
+
*/
|
|
368
|
+
function displayValidationResults(result) {
|
|
369
|
+
// Check if this is a step-by-step result (from validateExternalSystemComplete)
|
|
370
|
+
if (result.steps) {
|
|
371
|
+
displayStepByStepValidation(result);
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// Legacy format (for regular apps)
|
|
376
|
+
if (result.valid) {
|
|
377
|
+
logger.log(chalk.green('\n✓ Validation passed!'));
|
|
378
|
+
} else {
|
|
379
|
+
logger.log(chalk.red('\n✗ Validation failed!'));
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
displayApplicationValidation(result.application);
|
|
383
|
+
displayExternalFilesValidation(result.externalFiles);
|
|
384
|
+
|
|
385
|
+
// Display Dimensions (ABAC) for datasources and collect warnings
|
|
386
|
+
const dimensionWarnings = displayDimensionsValidation(result.externalFiles);
|
|
387
|
+
|
|
388
|
+
displayRbacValidation(result.rbac);
|
|
389
|
+
displayFileValidation(result);
|
|
390
|
+
|
|
391
|
+
// Combine all warnings
|
|
392
|
+
const allWarnings = [...(result.warnings || []), ...dimensionWarnings];
|
|
393
|
+
displayAggregatedWarnings(allWarnings);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
module.exports = {
|
|
397
|
+
displayValidationResults,
|
|
398
|
+
displayStepByStepValidation,
|
|
399
|
+
displayApplicationValidation,
|
|
400
|
+
displayExternalFilesValidation,
|
|
401
|
+
displayDimensionsValidation,
|
|
402
|
+
displayRbacValidation,
|
|
403
|
+
displayFileValidation,
|
|
404
|
+
displayAggregatedWarnings,
|
|
405
|
+
extractDimensionsFromDatasource
|
|
406
|
+
};
|