@aifabrix/builder 2.46.0 → 2.47.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.
Files changed (175) hide show
  1. package/.npmrc.token +1 -0
  2. package/.temp/jest-protection-convert/run-IFN2nv/.protection/hubspot-companies.json +1 -0
  3. package/.temp/jest-protection-convert/run-IvmKLO/.protection/hubspot-companies.yaml +17 -0
  4. package/.temp/jest-protection-convert/run-SdvblF/.protection/hubspot-companies.json +1 -0
  5. package/.temp/jest-protection-convert/run-b51TsW/.protection/hubspot-companies.json +1 -0
  6. package/.temp/jest-protection-convert/run-fiLmb1/.protection/hubspot-companies.json +1 -0
  7. package/.temp/jest-protection-convert/run-qYGHMU/.protection/hubspot-companies.yaml +17 -0
  8. package/.temp/jest-protection-fixtures/hubspot-Mq5re8/hubspot-companies.yaml +17 -0
  9. package/.temp/jest-protection-fixtures/hubspot-f3u4YL/hubspot-companies.yaml +17 -0
  10. package/.temp/jest-protection-fixtures/hubspot-iQtd1O/hubspot-companies.yaml +17 -0
  11. package/.temp/jest-protection-fixtures/hubspot-mdmz5M/hubspot-companies.yaml +17 -0
  12. package/.temp/jest-protection-fixtures/hubspot-qbKYxQ/hubspot-companies.yaml +17 -0
  13. package/.temp/jest-protection-fixtures/hubspot-yzlJy6/hubspot-companies.yaml +17 -0
  14. package/.temp/validation/summary.txt +5 -0
  15. package/jest.isolated-projects.js +18 -2
  16. package/jest.projects.js +24 -0
  17. package/lib/api/dataplane-health.api.js +19 -7
  18. package/lib/api/lifecycle.api.js +22 -1
  19. package/lib/api/resource-types.api.js +107 -0
  20. package/lib/api/runtime-configuration.api.js +72 -0
  21. package/lib/api/types/resource-types.types.js +45 -0
  22. package/lib/api/user-groups.api.js +9 -9
  23. package/lib/api/users.api.js +8 -8
  24. package/lib/api/wizard.api.js +10 -2
  25. package/lib/app/down.js +58 -26
  26. package/lib/app/index.js +2 -2
  27. package/lib/app/run-resolve-image.js +2 -1
  28. package/lib/app/run-stop-containers.js +113 -0
  29. package/lib/app/run.js +1 -31
  30. package/lib/app/show-display.js +35 -0
  31. package/lib/app/show.js +32 -1
  32. package/lib/build/index.js +17 -5
  33. package/lib/build/miso-controller-npm-sdk-guard.js +25 -0
  34. package/lib/channels/add-channel.js +348 -0
  35. package/lib/channels/channel-artifact-generator.js +141 -0
  36. package/lib/channels/channel-audit.js +101 -0
  37. package/lib/channels/channel-auth-context.js +37 -0
  38. package/lib/channels/channel-credential.js +200 -0
  39. package/lib/channels/channel-display-name.js +64 -0
  40. package/lib/channels/channel-external-system.js +106 -0
  41. package/lib/channels/channel-integration-generator.js +274 -0
  42. package/lib/channels/channel-probe.js +89 -0
  43. package/lib/channels/channel-runtime-resolver.js +152 -0
  44. package/lib/channels/channel-status-display.js +141 -0
  45. package/lib/channels/channel-targets.js +115 -0
  46. package/lib/cli/index.js +16 -4
  47. package/lib/cli/setup-app.js +54 -3
  48. package/lib/cli/setup-infra-up-dataplane-action.js +2 -2
  49. package/lib/cli/setup-infra-up-platform-action.js +2 -1
  50. package/lib/cli/setup-platform.js +1 -1
  51. package/lib/cli/setup-utility-help-after.js +4 -1
  52. package/lib/cli/setup-utility-resolve.js +8 -5
  53. package/lib/commands/app-logs.js +54 -26
  54. package/lib/commands/app.js +41 -0
  55. package/lib/commands/auth-status-dataplane-version.js +97 -61
  56. package/lib/commands/auth-status.js +2 -7
  57. package/lib/commands/channel.js +58 -0
  58. package/lib/commands/datasource.js +1 -1
  59. package/lib/commands/identity-apply-sync.js +49 -8
  60. package/lib/commands/identity-group-cli.js +66 -26
  61. package/lib/commands/identity-membership-role-cache.js +58 -37
  62. package/lib/commands/identity-shared.js +22 -1
  63. package/lib/commands/identity-user-cli.js +80 -34
  64. package/lib/commands/repair-auth-apply.js +30 -4
  65. package/lib/commands/repair-auth-config.js +8 -13
  66. package/lib/commands/repair-datasource-com-v2.js +15 -0
  67. package/lib/commands/repair-datasource-service-contract.js +206 -0
  68. package/lib/commands/repair-datasource.js +53 -18
  69. package/lib/commands/repair-env-template.js +12 -12
  70. package/lib/commands/repair-openapi-sync.js +26 -4
  71. package/lib/commands/repair-steps.js +28 -13
  72. package/lib/commands/repair-system-alignment.js +7 -4
  73. package/lib/commands/resource-type.js +371 -0
  74. package/lib/commands/setup-modes.js +1 -1
  75. package/lib/commands/setup-prompts-platform-mode.js +24 -21
  76. package/lib/commands/test-trust-external.js +39 -90
  77. package/lib/commands/up-common.js +33 -1
  78. package/lib/commands/up-dataplane.js +8 -4
  79. package/lib/commands/upload.js +24 -3
  80. package/lib/commands/verify-trust-command-action.js +4 -1
  81. package/lib/commands/verify-trust-external.js +12 -20
  82. package/lib/core/config-setup-platform-mode.js +3 -3
  83. package/lib/core/setup-platform-mode.js +41 -6
  84. package/lib/datasource/capability/capability-diff-slice.js +2 -2
  85. package/lib/datasource/capability/capability-manifest.js +254 -0
  86. package/lib/datasource/capability/capability-resolve.js +3 -4
  87. package/lib/datasource/capability/copy-operations.js +5 -3
  88. package/lib/datasource/capability/remove-operations.js +2 -1
  89. package/lib/datasource/capability/run-capability-copy.js +32 -4
  90. package/lib/datasource/capability/run-capability-diff.js +3 -3
  91. package/lib/datasource/capability/run-capability-dimension.js +2 -4
  92. package/lib/datasource/capability/run-capability-edit.js +4 -7
  93. package/lib/datasource/capability/run-capability-relate.js +2 -4
  94. package/lib/datasource/capability/run-capability-remove.js +2 -4
  95. package/lib/datasource/capability/validate-capability-slice.js +2 -1
  96. package/lib/datasource/datasource-identifier.js +2 -1
  97. package/lib/datasource/datasource-validate-display.js +1 -1
  98. package/lib/datasource/field-reference-validator.js +24 -3
  99. package/lib/datasource/orphan-profiles-validator.js +98 -0
  100. package/lib/datasource/validate.js +41 -23
  101. package/lib/external-system/download-helpers.js +87 -0
  102. package/lib/external-system/download.js +61 -122
  103. package/lib/external-system/generator.js +1 -59
  104. package/lib/external-system/test.js +10 -15
  105. package/lib/generator/builders.js +11 -1
  106. package/lib/generator/external-controller-manifest.js +5 -2
  107. package/lib/generator/split.js +3 -1
  108. package/lib/generator/wizard.js +1 -28
  109. package/lib/identity/fk-reference.js +65 -0
  110. package/lib/identity/identity-apply-core.js +13 -58
  111. package/lib/identity/identity-apply-phases.js +5 -1
  112. package/lib/identity/identity-display.js +243 -0
  113. package/lib/identity/identity-response-helpers.js +52 -0
  114. package/lib/identity/identity-sync-errors.js +62 -0
  115. package/lib/identity/resolve-user-id.js +129 -0
  116. package/lib/identity/username-default.js +31 -0
  117. package/lib/lifecycle/certification-progress.js +2 -2
  118. package/lib/lifecycle/report-display-trust.js +70 -0
  119. package/lib/lifecycle/report-display.js +14 -13
  120. package/lib/resolvers/datasource-resolver.js +2 -3
  121. package/lib/resolvers/resource-type-file.js +159 -0
  122. package/lib/schema/application-schema.json +16 -0
  123. package/lib/schema/deployment-rules.yaml +2 -1
  124. package/lib/schema/external-datasource.schema.json +372 -58
  125. package/lib/schema/external-system.schema.json +331 -2
  126. package/lib/schema/type/document-storage.json +9 -5
  127. package/lib/utils/app-run-containers.js +25 -2
  128. package/lib/utils/authentication-shape.js +224 -0
  129. package/lib/utils/build-copy.js +36 -5
  130. package/lib/utils/build-resolve-image.js +66 -12
  131. package/lib/utils/celery-companion-apps.js +53 -0
  132. package/lib/utils/cli-utils.js +4 -0
  133. package/lib/utils/compose-celery-worker.js +23 -0
  134. package/lib/utils/compose-generate-docker-compose.js +9 -1
  135. package/lib/utils/configuration-env-resolver.js +36 -0
  136. package/lib/utils/credential-secrets-env-kv.js +216 -0
  137. package/lib/utils/credential-secrets-env.js +52 -262
  138. package/lib/utils/dataplane-resolver.js +4 -115
  139. package/lib/utils/declarative-url-ports.js +24 -1
  140. package/lib/utils/docker-build.js +1 -4
  141. package/lib/utils/external-env-template.js +10 -3
  142. package/lib/utils/external-system-validators.js +8 -2
  143. package/lib/utils/help-builder.js +2 -0
  144. package/lib/utils/paths.js +25 -0
  145. package/lib/utils/platform-controller-url.js +2 -1
  146. package/lib/utils/platform-kv-ref.js +57 -0
  147. package/lib/utils/runtime-configuration-download.js +189 -0
  148. package/lib/utils/runtime-configuration-values.js +119 -0
  149. package/lib/utils/schema-loader.js +19 -4
  150. package/lib/utils/worker-sidecars.js +142 -0
  151. package/lib/validation/external-manifest-validator.js +2 -0
  152. package/lib/validation/runtime-configuration-rules.js +98 -0
  153. package/lib/validation/validate-display-dimensions.js +154 -0
  154. package/lib/validation/validate-display-sections.js +276 -0
  155. package/lib/validation/validate-display-steps.js +67 -0
  156. package/lib/validation/validate-display.js +24 -402
  157. package/package.json +1 -1
  158. package/templates/applications/dataplane/application.yaml +5 -0
  159. package/templates/applications/dataplane/env.template +26 -13
  160. package/templates/applications/dataplane/rbac.yaml +108 -1
  161. package/templates/applications/miso-controller/application.yaml +2 -2
  162. package/templates/applications/miso-controller/env.template +37 -122
  163. package/templates/applications/miso-controller/rbac.yaml +28 -13
  164. package/templates/channels/chatgpt/install.template.md.hbs +49 -0
  165. package/templates/channels/chatgpt/manifest.template.json.hbs +9 -0
  166. package/templates/channels/microsoft-copilot/install.template.md.hbs +49 -0
  167. package/templates/channels/microsoft-copilot/manifest.template.json.hbs +8 -0
  168. package/templates/channels/slack/install.template.md.hbs +49 -0
  169. package/templates/channels/slack/manifest.template.json.hbs +66 -0
  170. package/templates/channels/teams-bot/install.template.md.hbs +49 -0
  171. package/templates/channels/teams-bot/manifest.template.json.hbs +13 -0
  172. package/templates/channels/web-embed/install.template.md.hbs +49 -0
  173. package/templates/channels/web-embed/manifest.template.json.hbs +8 -0
  174. package/templates/python/docker-compose.hbs +56 -0
  175. package/templates/typescript/docker-compose.hbs +52 -0
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Runtime configuration validation for external system manifests.
3
+ *
4
+ * @fileoverview Datasource override rules (v1: no keyvault overrides)
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ /**
10
+ * @param {Array<{ name?: string, location?: string }>|undefined} systemConfiguration
11
+ * @returns {Map<string, { name?: string, location?: string }>}
12
+ */
13
+ function systemConfigDefsByName(systemConfiguration) {
14
+ const defsByName = new Map();
15
+ for (const item of systemConfiguration || []) {
16
+ if (item && item.name) {
17
+ defsByName.set(String(item.name).trim(), item);
18
+ }
19
+ }
20
+ return defsByName;
21
+ }
22
+
23
+ /**
24
+ * @param {string} prefix
25
+ * @param {Map<string, { name?: string, location?: string }>} defsByName
26
+ * @param {{ name?: string, value?: string }} override
27
+ * @returns {string[]}
28
+ */
29
+ function validateOverrideEntry(prefix, defsByName, override) {
30
+ if (!override || !override.name) {
31
+ return [];
32
+ }
33
+ const name = String(override.name).trim();
34
+ const def = defsByName.get(name);
35
+ if (!def) {
36
+ return [`${prefix}configuration override '${name}' is not declared on the parent system.`];
37
+ }
38
+ const errors = [];
39
+ if (String(def.location || 'variable').toLowerCase() === 'keyvault') {
40
+ errors.push(
41
+ `${prefix}configuration override '${name}' targets a keyvault system definition (not allowed in v1).`
42
+ );
43
+ }
44
+ const extraKeys = Object.keys(override).filter((key) => key !== 'name' && key !== 'value');
45
+ if (extraKeys.length > 0) {
46
+ errors.push(
47
+ `${prefix}configuration override '${name}' must contain only name and value (found: ${extraKeys.join(', ')}).`
48
+ );
49
+ }
50
+ return errors;
51
+ }
52
+
53
+ /**
54
+ * Validates datasource configuration[] overrides against parent system definitions.
55
+ *
56
+ * @param {Array<{ name?: string, location?: string }>|undefined} systemConfiguration
57
+ * @param {Array<{ name?: string, value?: string }>|undefined} datasourceConfiguration
58
+ * @param {string} [datasourceKey] - For error prefixes
59
+ * @returns {string[]} Validation errors
60
+ */
61
+ function validateDatasourceConfigurationOverrides(
62
+ systemConfiguration,
63
+ datasourceConfiguration,
64
+ datasourceKey
65
+ ) {
66
+ if (!Array.isArray(datasourceConfiguration) || datasourceConfiguration.length === 0) {
67
+ return [];
68
+ }
69
+ const prefix = datasourceKey ? `Datasource '${datasourceKey}': ` : '';
70
+ const defsByName = systemConfigDefsByName(systemConfiguration);
71
+ return datasourceConfiguration.flatMap((override) =>
72
+ validateOverrideEntry(prefix, defsByName, override)
73
+ );
74
+ }
75
+
76
+ /**
77
+ * @param {{ system?: { configuration?: unknown[] }, dataSources?: Array<{ key?: string, configuration?: unknown[] }> }} manifest
78
+ * @returns {string[]}
79
+ */
80
+ function validateManifestRuntimeConfiguration(manifest) {
81
+ const errors = [];
82
+ const systemConfiguration = manifest?.system?.configuration;
83
+ for (const ds of manifest?.dataSources || []) {
84
+ errors.push(
85
+ ...validateDatasourceConfigurationOverrides(
86
+ systemConfiguration,
87
+ ds?.configuration,
88
+ ds?.key
89
+ )
90
+ );
91
+ }
92
+ return errors;
93
+ }
94
+
95
+ module.exports = {
96
+ validateDatasourceConfigurationOverrides,
97
+ validateManifestRuntimeConfiguration
98
+ };
@@ -0,0 +1,154 @@
1
+ /**
2
+ * @fileoverview Dimensions (ABAC) display helpers for validate-display.
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { loadConfigFile } = require('../utils/config-format');
10
+ const { flattenRootDimensionsForDisplay } = require('./dimension-display-helpers');
11
+ const { formatDatasourceListRow } = require('../utils/cli-test-layout-chalk');
12
+ const logger = require('../utils/logger');
13
+ const {
14
+ logSectionTitle,
15
+ logWarnRow,
16
+ logDimLine
17
+ } = require('./validate-display-log-helpers');
18
+
19
+ /**
20
+ * True when datasource is orchestration-only (no ABAC dimensions contract).
21
+ * @param {string} filePath - Path to datasource JSON
22
+ * @returns {boolean}
23
+ */
24
+ function isOrchestrationOnlyDatasource(filePath) {
25
+ try {
26
+ const parsed = loadConfigFile(filePath);
27
+ return String(parsed?.entityType || '').trim() === 'none';
28
+ } catch {
29
+ return false;
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Extracts dimensions from a datasource file for CLI display.
35
+ * Local bindings become `metadata.<field>`; FK bindings become `fk:<fk>→<dimension>...` plus optional `(actor: ...)`.
36
+ * @function extractDimensionsFromDatasource
37
+ * @param {string} filePath - Path to datasource file
38
+ * @returns {Object} Dimensions info { dimensions: Object, dimensionKeys: string[], hasDimensions: boolean }
39
+ */
40
+ function extractDimensionsFromDatasource(filePath) {
41
+ try {
42
+ const parsed = loadConfigFile(filePath);
43
+
44
+ const rootFlat = flattenRootDimensionsForDisplay(parsed.dimensions);
45
+ const abacDimensions = parsed.abac?.dimensions || {};
46
+ const allDimensions = { ...rootFlat, ...abacDimensions };
47
+ const dimensionKeys = Object.keys(allDimensions);
48
+
49
+ return {
50
+ dimensions: allDimensions,
51
+ dimensionKeys,
52
+ hasDimensions: dimensionKeys.length > 0
53
+ };
54
+ } catch {
55
+ return { dimensions: {}, dimensionKeys: [], hasDimensions: false };
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Displays Dimensions (ABAC) validation results for datasources
61
+ * @function displayDimensionsValidation
62
+ * @param {Array} externalFiles - External files validation results
63
+ * @returns {Array} Warnings to add to aggregated warnings
64
+ */
65
+ function displayDimensionsValidation(externalFiles) {
66
+ if (!externalFiles || externalFiles.length === 0) {
67
+ return [];
68
+ }
69
+
70
+ const datasourceFiles = externalFiles.filter(f =>
71
+ f.type === 'datasource' || f.type === 'external-datasource'
72
+ );
73
+
74
+ if (datasourceFiles.length === 0) {
75
+ return [];
76
+ }
77
+
78
+ logSectionTitle('Dimensions (ABAC)');
79
+
80
+ const warnings = [];
81
+ let anyDatasourceHasDimensions = false;
82
+
83
+ datasourceFiles.forEach(file => {
84
+ if (file.path && isOrchestrationOnlyDatasource(file.path)) {
85
+ logger.log(formatDatasourceListRow('ok', file.file, file.type));
86
+ logDimLine('orchestration-only (entityType=none) — dimensions N/A');
87
+ return;
88
+ }
89
+ const dimensionsInfo = extractDimensionsFromDatasource(file.path);
90
+
91
+ if (dimensionsInfo.hasDimensions) {
92
+ anyDatasourceHasDimensions = true;
93
+ logger.log(formatDatasourceListRow('ok', file.file, file.type));
94
+ dimensionsInfo.dimensionKeys.forEach(key => {
95
+ const mapping = dimensionsInfo.dimensions[key];
96
+ logDimLine(`${key} → ${mapping}`);
97
+ });
98
+ } else {
99
+ logWarnRow(`${file.file} — no dimensions configured`);
100
+ warnings.push(`${file.file} - no dimensions configured, ABAC filtering disabled`);
101
+ }
102
+ });
103
+
104
+ if (!anyDatasourceHasDimensions && datasourceFiles.some(
105
+ (file) => !(file.path && isOrchestrationOnlyDatasource(file.path))
106
+ )) {
107
+ logWarnRow('No dimensions configured — ABAC filtering disabled for all datasources');
108
+ }
109
+
110
+ return warnings;
111
+ }
112
+
113
+ /**
114
+ * Displays dimensions validation for datasources
115
+ * @function displayDimensionsStep
116
+ * @param {Array} datasourceFiles - Datasource files
117
+ * @returns {void}
118
+ */
119
+ function displayDimensionsStep(datasourceFiles) {
120
+ if (datasourceFiles.length === 0) {
121
+ return;
122
+ }
123
+
124
+ logSectionTitle('Dimensions (ABAC)');
125
+ datasourceFiles.forEach(file => {
126
+ try {
127
+ const dsPath = file.path || file.file;
128
+ if (dsPath && isOrchestrationOnlyDatasource(dsPath)) {
129
+ logger.log(formatDatasourceListRow('ok', file.file, file.type));
130
+ logDimLine('orchestration-only (entityType=none) — dimensions N/A');
131
+ return;
132
+ }
133
+ const dimensionsInfo = extractDimensionsFromDatasource(dsPath);
134
+ if (dimensionsInfo.hasDimensions) {
135
+ logger.log(formatDatasourceListRow('ok', file.file, file.type));
136
+ dimensionsInfo.dimensionKeys.forEach(key => {
137
+ const mapping = dimensionsInfo.dimensions[key];
138
+ logDimLine(`${key} → ${mapping}`);
139
+ });
140
+ } else {
141
+ logWarnRow(`${file.file} — no dimensions configured`);
142
+ }
143
+ } catch {
144
+ // Skip if file path not available
145
+ }
146
+ });
147
+ }
148
+
149
+ module.exports = {
150
+ isOrchestrationOnlyDatasource,
151
+ extractDimensionsFromDatasource,
152
+ displayDimensionsValidation,
153
+ displayDimensionsStep
154
+ };
@@ -0,0 +1,276 @@
1
+ /**
2
+ * @fileoverview Section renderers for validate-display (application, files, RBAC, manifest).
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const chalk = require('chalk');
10
+ const logger = require('../utils/logger');
11
+ const {
12
+ headerKeyValue,
13
+ formatDatasourceListRow,
14
+ formatBlockingError,
15
+ successGlyph,
16
+ failureGlyph
17
+ } = require('../utils/cli-test-layout-chalk');
18
+ const {
19
+ logSectionTitle,
20
+ logOkRowRest,
21
+ logErrorDetail
22
+ } = require('./validate-display-log-helpers');
23
+
24
+ /**
25
+ * Displays application validation results
26
+ * @function displayApplicationValidation
27
+ * @param {Object} application - Application validation result
28
+ */
29
+ function displayApplicationValidation(application) {
30
+ if (!application) {
31
+ return;
32
+ }
33
+
34
+ logSectionTitle('Application');
35
+ if (application.valid) {
36
+ logOkRowRest('Application configuration is valid');
37
+ } else {
38
+ logger.log(` ${failureGlyph()} ${chalk.red('Application configuration has errors:')}`);
39
+ if (application.errors && application.errors.length > 0) {
40
+ application.errors.forEach(error => {
41
+ logErrorDetail(error);
42
+ });
43
+ }
44
+ }
45
+ if (application.warnings && application.warnings.length > 0) {
46
+ application.warnings.forEach(warning => {
47
+ logger.log(` ${chalk.yellow('⚠')} ${chalk.white(warning)}`);
48
+ });
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Displays external files validation results
54
+ * @function displayExternalFilesValidation
55
+ * @param {Array} externalFiles - External files validation results
56
+ */
57
+ function displayExternalFilesValidation(externalFiles) {
58
+ if (!externalFiles || externalFiles.length === 0) {
59
+ return;
60
+ }
61
+
62
+ logSectionTitle('External integration files');
63
+ externalFiles.forEach(file => {
64
+ if (file.valid) {
65
+ logger.log(formatDatasourceListRow('ok', file.file, file.type));
66
+ } else {
67
+ logger.log(formatDatasourceListRow('fail', file.file, file.type));
68
+ file.errors.forEach(error => {
69
+ logErrorDetail(error);
70
+ });
71
+ }
72
+ if (file.warnings && file.warnings.length > 0) {
73
+ file.warnings.forEach(warning => {
74
+ logger.log(` ${chalk.yellow('⚠')} ${chalk.white(warning)}`);
75
+ });
76
+ }
77
+ });
78
+ }
79
+
80
+ /**
81
+ * Displays RBAC validation results
82
+ * @function displayRbacValidation
83
+ * @param {Object} rbac - RBAC validation result
84
+ */
85
+ function displayRbacValidation(rbac) {
86
+ if (!rbac) {
87
+ return;
88
+ }
89
+
90
+ logSectionTitle('RBAC configuration');
91
+ if (rbac.valid) {
92
+ logOkRowRest('RBAC configuration is valid');
93
+ } else {
94
+ logger.log(` ${failureGlyph()} ${chalk.red('RBAC configuration has errors:')}`);
95
+ rbac.errors.forEach(error => {
96
+ logErrorDetail(error);
97
+ });
98
+ }
99
+ if (rbac.warnings && rbac.warnings.length > 0) {
100
+ rbac.warnings.forEach(warning => {
101
+ logger.log(` ${chalk.yellow('⚠')} ${chalk.white(warning)}`);
102
+ });
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Displays file validation results (for direct file validation)
108
+ * @function displayFileValidation
109
+ * @param {Object} result - Validation result
110
+ */
111
+ function displayFileValidation(result) {
112
+ if (!result.file) {
113
+ return;
114
+ }
115
+
116
+ logSectionTitle('File');
117
+ logger.log(` ${headerKeyValue('Path:', result.file)}`);
118
+ logger.log(` ${headerKeyValue('Type:', String(result.type))}`);
119
+ if (result.valid) {
120
+ logOkRowRest('File is valid');
121
+ } else {
122
+ logger.log(` ${failureGlyph()} ${chalk.red('File has errors:')}`);
123
+ result.errors.forEach(error => {
124
+ logErrorDetail(error);
125
+ });
126
+ }
127
+ if (result.warnings && result.warnings.length > 0) {
128
+ result.warnings.forEach(warning => {
129
+ logger.log(` ${chalk.yellow('⚠')} ${chalk.white(warning)}`);
130
+ });
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Displays aggregated warnings
136
+ * @function displayAggregatedWarnings
137
+ * @param {Array} warnings - Array of warning messages
138
+ */
139
+ function displayAggregatedWarnings(warnings) {
140
+ if (!warnings || warnings.length === 0) {
141
+ return;
142
+ }
143
+
144
+ logSectionTitle('Warnings');
145
+ warnings.forEach(warning => {
146
+ logger.log(` ${chalk.yellow('⚠')} ${chalk.white(warning)}`);
147
+ });
148
+ }
149
+
150
+ /**
151
+ * Displays application validation step
152
+ * @function displayApplicationStep
153
+ * @param {Object} application - Application validation result
154
+ * @returns {void}
155
+ */
156
+ function displayApplicationStep(application) {
157
+ logSectionTitle('Application');
158
+ if (application.valid) {
159
+ logOkRowRest('Application configuration is valid');
160
+ } else {
161
+ logger.log(` ${failureGlyph()} ${chalk.red('Application configuration has errors:')}`);
162
+ application.errors.forEach(error => {
163
+ logErrorDetail(error);
164
+ });
165
+ }
166
+ if (application.warnings && application.warnings.length > 0) {
167
+ application.warnings.forEach(warning => {
168
+ logger.log(` ${chalk.yellow('⚠')} ${chalk.white(warning)}`);
169
+ });
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Displays external integration files step
175
+ * @function displayComponentsStep
176
+ * @param {Object} components - Components validation result
177
+ * @returns {void}
178
+ */
179
+ function displayComponentsStep(components) {
180
+ const hasFiles = components.files && components.files.length > 0;
181
+ const hasErrors = components.errors && components.errors.length > 0;
182
+ if (!hasFiles && !hasErrors) {
183
+ return;
184
+ }
185
+
186
+ logSectionTitle('External integration files');
187
+ if (hasFiles) {
188
+ components.files.forEach(file => {
189
+ if (file.valid) {
190
+ logger.log(formatDatasourceListRow('ok', file.file, file.type));
191
+ } else {
192
+ logger.log(formatDatasourceListRow('fail', file.file, file.type));
193
+ }
194
+ });
195
+ }
196
+ if (hasErrors) {
197
+ components.errors.forEach(error => {
198
+ logger.log(formatBlockingError(error));
199
+ });
200
+ }
201
+ }
202
+
203
+ /**
204
+ * Displays deployment manifest step
205
+ * @function displayManifestStep
206
+ * @param {Object} manifest - Manifest validation result
207
+ * @param {Array} componentFiles - Component files
208
+ * @returns {void}
209
+ */
210
+ function displayManifestStep(manifest, componentFiles) {
211
+ logSectionTitle('Deployment manifest');
212
+ if (manifest.skipped) {
213
+ logger.log(` ${chalk.gray('⏭')} ${chalk.white('Skipped (fix errors above first)')}`);
214
+ } else if (manifest.valid) {
215
+ logOkRowRest('Full deployment manifest is valid');
216
+ if (componentFiles) {
217
+ const datasourceFiles = componentFiles.filter(f => f.type === 'datasource' || f.type === 'external-datasource');
218
+ logger.log(` ${successGlyph()} ${chalk.white('System configuration valid')}`);
219
+ logger.log(` ${successGlyph()} ${chalk.white(`${datasourceFiles.length} datasource(s) valid`)}`);
220
+ logger.log(` ${successGlyph()} ${chalk.white('Schema validation passed')}`);
221
+ }
222
+ } else {
223
+ logger.log(` ${failureGlyph()} ${chalk.red('Full deployment manifest validation failed:')}`);
224
+ const errs = manifest.errors && manifest.errors.length > 0 ? manifest.errors : [];
225
+ if (errs.length > 0) {
226
+ errs.forEach(error => {
227
+ const msg = typeof error === 'string' ? error : String(error);
228
+ logErrorDetail(msg);
229
+ });
230
+ } else {
231
+ logErrorDetail('No error details available (check schema and manifest structure).');
232
+ }
233
+ }
234
+ if (manifest.warnings && manifest.warnings.length > 0) {
235
+ manifest.warnings.forEach(warning => {
236
+ logger.log(` ${chalk.yellow('⚠')} ${chalk.white(warning)}`);
237
+ });
238
+ }
239
+ }
240
+
241
+ /**
242
+ * Displays overall validation status
243
+ * @param {Object} result - Validation result
244
+ */
245
+ function displayOverallStatus(result) {
246
+ let hasErrors = result.errors && result.errors.length > 0;
247
+ if (!hasErrors && result.steps) {
248
+ const stepErrors = [result.steps.application, result.steps.components, result.steps.manifest]
249
+ .filter(Boolean)
250
+ .some(s => s.errors && s.errors.length > 0);
251
+ if (stepErrors) {
252
+ hasErrors = true;
253
+ }
254
+ }
255
+ const hasWarnings = result.warnings && result.warnings.length > 0;
256
+ logger.log('');
257
+ if (hasErrors) {
258
+ logger.log(headerKeyValue('Overall:', chalk.red('Failed')));
259
+ } else if (hasWarnings) {
260
+ logger.log(headerKeyValue('Overall:', chalk.yellow('Passed with warnings')));
261
+ } else {
262
+ logger.log(headerKeyValue('Overall:', chalk.green('Passed')));
263
+ }
264
+ }
265
+
266
+ module.exports = {
267
+ displayApplicationValidation,
268
+ displayExternalFilesValidation,
269
+ displayRbacValidation,
270
+ displayFileValidation,
271
+ displayAggregatedWarnings,
272
+ displayApplicationStep,
273
+ displayComponentsStep,
274
+ displayManifestStep,
275
+ displayOverallStatus
276
+ };
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @fileoverview Step-by-step validation display for external-system validate flow.
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const path = require('path');
10
+ const logger = require('../utils/logger');
11
+ const {
12
+ metadata,
13
+ formatBlockingError,
14
+ formatSuccessParagraph
15
+ } = require('../utils/cli-test-layout-chalk');
16
+ const {
17
+ displayApplicationStep,
18
+ displayComponentsStep,
19
+ displayManifestStep,
20
+ displayRbacValidation,
21
+ displayAggregatedWarnings,
22
+ displayOverallStatus
23
+ } = require('./validate-display-sections');
24
+ const { displayDimensionsStep } = require('./validate-display-dimensions');
25
+
26
+ /**
27
+ * Displays step-by-step validation results for external systems
28
+ * @function displayStepByStepValidation
29
+ * @param {Object} result - Validation result with steps
30
+ */
31
+ function displayStepByStepValidation(result) {
32
+ if (result.valid) {
33
+ logger.log(formatSuccessParagraph('Validation passed!'));
34
+ } else {
35
+ logger.log(`\n${formatBlockingError('Validation failed!')}`);
36
+ }
37
+
38
+ displayApplicationStep(result.steps.application);
39
+
40
+ if (!result.steps.components.valid || (result.steps.components.files && result.steps.components.files.length > 0)) {
41
+ displayComponentsStep(result.steps.components);
42
+ }
43
+
44
+ const datasourceFiles = result.steps.components.files?.filter(f =>
45
+ f.type === 'datasource' || f.type === 'external-datasource'
46
+ ) || [];
47
+ displayDimensionsStep(datasourceFiles);
48
+
49
+ if (result.rbac) {
50
+ displayRbacValidation(result.rbac);
51
+ }
52
+
53
+ displayManifestStep(result.steps.manifest, result.steps.components.files);
54
+
55
+ if (result.warnings && result.warnings.length > 0) {
56
+ displayAggregatedWarnings(result.warnings);
57
+ }
58
+
59
+ displayOverallStatus(result);
60
+ if (result.appPath) {
61
+ logger.log(`\n${metadata(path.resolve(result.appPath))}`);
62
+ }
63
+ }
64
+
65
+ module.exports = {
66
+ displayStepByStepValidation
67
+ };