@aifabrix/builder 2.44.3 → 2.44.4
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/.npmrc.token +1 -1
- package/integration/roundtrip-test-local/README.md +1 -2
- package/integration/roundtrip-test-local2/README.md +1 -2
- package/jest.projects.js +12 -1
- package/lib/api/certificates.api.js +21 -3
- package/lib/certification/post-unified-cert-sync.js +13 -2
- package/lib/certification/sync-after-external-command.js +6 -3
- package/lib/certification/sync-system-certification.js +60 -14
- package/lib/cli/setup-app.test-commands.js +67 -35
- package/lib/cli/setup-utility.js +1 -1
- package/lib/commands/datasource-unified-test-cli.js +81 -46
- package/lib/commands/datasource-unified-test-cli.options.js +4 -2
- package/lib/commands/datasource.js +3 -31
- package/lib/commands/repair-datasource-keys.js +1 -1
- package/lib/commands/repair-datasource-openapi.js +57 -0
- package/lib/commands/repair-datasource.js +5 -0
- package/lib/commands/repair-internal.js +2 -4
- package/lib/commands/repair.js +1 -2
- package/lib/commands/test-e2e-external.js +5 -6
- package/lib/commands/upload.js +18 -4
- package/lib/commands/wizard-dataplane.js +14 -6
- package/lib/datasource/datasource-validate-display.js +162 -0
- package/lib/datasource/datasource-validate-summary.js +194 -0
- package/lib/datasource/test-e2e.js +65 -37
- package/lib/datasource/unified-validation-run-body.js +1 -2
- package/lib/datasource/validate.js +14 -6
- package/lib/external-system/test.js +12 -8
- package/lib/generator/external-controller-manifest.js +12 -2
- package/lib/schema/cip-capacity-display.fallback.json +7 -0
- package/lib/schema/datasource-test-run.schema.json +79 -1
- package/lib/schema/external-datasource.schema.json +94 -2
- package/lib/schema/flag-map-validation-run.json +1 -2
- package/lib/schema/type/document-storage.json +83 -3
- package/lib/utils/configuration-env-resolver.js +38 -0
- package/lib/utils/dataplane-resolver.js +3 -2
- package/lib/utils/datasource-test-run-capacity-operations.js +149 -0
- package/lib/utils/datasource-test-run-debug-display.js +143 -1
- package/lib/utils/datasource-test-run-display.js +46 -33
- package/lib/utils/datasource-test-run-tty-log.js +6 -2
- package/lib/utils/datasource-test-run-tty-meta-lines.js +123 -0
- package/lib/utils/error-formatter.js +32 -2
- package/lib/utils/external-system-readiness-core.js +39 -0
- package/lib/utils/external-system-readiness-deploy-display.js +2 -3
- package/lib/utils/external-system-readiness-display-internals.js +3 -2
- package/lib/utils/external-system-system-test-tty.js +33 -9
- package/lib/utils/external-system-validators.js +62 -5
- package/lib/utils/load-cip-capacity-display-config.js +130 -0
- package/lib/utils/paths.js +10 -3
- package/lib/utils/schema-resolver.js +98 -2
- package/lib/utils/validation-run-poll.js +15 -4
- package/lib/utils/validation-run-request.js +4 -6
- package/lib/validation/dimension-display-helpers.js +60 -0
- package/lib/validation/validate-display-log-helpers.js +39 -0
- package/lib/validation/validate-display.js +89 -83
- package/package.json +1 -1
- package/templates/external-system/README.md.hbs +1 -2
|
@@ -175,6 +175,96 @@ function resolveDatasourceFiles(schemaBasePath, datasourceFiles) {
|
|
|
175
175
|
return datasourceFiles.map(fileName => resolveSingleExternalFile(schemaBasePath, fileName, 'datasource'));
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
+
/**
|
|
179
|
+
* @param {string} schemaBasePath
|
|
180
|
+
* @param {string[]} systemFileNames
|
|
181
|
+
* @returns {string[]|null}
|
|
182
|
+
*/
|
|
183
|
+
function readSystemDatasourceKeyOrder(schemaBasePath, systemFileNames) {
|
|
184
|
+
if (!Array.isArray(systemFileNames) || systemFileNames.length === 0) {
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
const systemPath = path.join(schemaBasePath, systemFileNames[0]);
|
|
188
|
+
if (!fs.existsSync(systemPath)) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
try {
|
|
192
|
+
const systemParsed = loadConfigFile(systemPath);
|
|
193
|
+
const orderKeys = Array.isArray(systemParsed.dataSources) ? systemParsed.dataSources : null;
|
|
194
|
+
return orderKeys && orderKeys.length > 0 ? orderKeys : null;
|
|
195
|
+
} catch {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* @param {string} schemaBasePath
|
|
202
|
+
* @param {string[]} datasourceFileNames
|
|
203
|
+
* @returns {Map<string, string>}
|
|
204
|
+
*/
|
|
205
|
+
function mapDatasourceKeysToFilenames(schemaBasePath, datasourceFileNames) {
|
|
206
|
+
const byKey = new Map();
|
|
207
|
+
for (const fileName of datasourceFileNames) {
|
|
208
|
+
if (typeof fileName !== 'string') {
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
const fp = path.join(schemaBasePath, fileName);
|
|
212
|
+
if (!fs.existsSync(fp)) {
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
try {
|
|
216
|
+
const d = loadConfigFile(fp);
|
|
217
|
+
const k = d && typeof d.key === 'string' ? d.key.trim() : '';
|
|
218
|
+
if (k) {
|
|
219
|
+
byKey.set(k, fileName);
|
|
220
|
+
}
|
|
221
|
+
} catch {
|
|
222
|
+
/* tail via original list */
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return byKey;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Reorder datasource filenames to match external system JSON `dataSources` key order when present.
|
|
230
|
+
* Keeps application.yaml list membership but fixes FK-safe sequencing when filenames were sorted or drifted.
|
|
231
|
+
*
|
|
232
|
+
* @param {string} schemaBasePath
|
|
233
|
+
* @param {string[]} systemFileNames - externalIntegration.systems
|
|
234
|
+
* @param {string[]} datasourceFileNames - externalIntegration.dataSources filenames
|
|
235
|
+
* @returns {string[]} Same filenames, system-declaration order first, then any leftovers in original order
|
|
236
|
+
*/
|
|
237
|
+
function orderDatasourceFileNamesBySystemKeys(
|
|
238
|
+
schemaBasePath,
|
|
239
|
+
systemFileNames,
|
|
240
|
+
datasourceFileNames
|
|
241
|
+
) {
|
|
242
|
+
if (!Array.isArray(datasourceFileNames) || datasourceFileNames.length <= 1) {
|
|
243
|
+
return datasourceFileNames;
|
|
244
|
+
}
|
|
245
|
+
const orderKeys = readSystemDatasourceKeyOrder(schemaBasePath, systemFileNames);
|
|
246
|
+
if (!orderKeys) {
|
|
247
|
+
return datasourceFileNames;
|
|
248
|
+
}
|
|
249
|
+
const byKey = mapDatasourceKeysToFilenames(schemaBasePath, datasourceFileNames);
|
|
250
|
+
const out = [];
|
|
251
|
+
const used = new Set();
|
|
252
|
+
for (const k of orderKeys) {
|
|
253
|
+
const ks = typeof k === 'string' ? k.trim() : '';
|
|
254
|
+
const f = ks ? byKey.get(ks) : null;
|
|
255
|
+
if (f && !used.has(f)) {
|
|
256
|
+
out.push(f);
|
|
257
|
+
used.add(f);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
for (const fileName of datasourceFileNames) {
|
|
261
|
+
if (fileName && !used.has(fileName)) {
|
|
262
|
+
out.push(fileName);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return out.length ? out : datasourceFileNames;
|
|
266
|
+
}
|
|
267
|
+
|
|
178
268
|
/**
|
|
179
269
|
* Loads and validates application config
|
|
180
270
|
* @async
|
|
@@ -206,13 +296,19 @@ async function resolveExternalFiles(appName, options = {}) {
|
|
|
206
296
|
|
|
207
297
|
const schemaBasePath = await resolveSchemaBasePath(appName, options);
|
|
208
298
|
const systemFiles = resolveSystemFiles(schemaBasePath, variables.externalIntegration.systems);
|
|
209
|
-
const
|
|
299
|
+
const orderedNames = orderDatasourceFileNamesBySystemKeys(
|
|
300
|
+
schemaBasePath,
|
|
301
|
+
variables.externalIntegration.systems,
|
|
302
|
+
variables.externalIntegration.dataSources || []
|
|
303
|
+
);
|
|
304
|
+
const datasourceFiles = resolveDatasourceFiles(schemaBasePath, orderedNames);
|
|
210
305
|
|
|
211
306
|
return [...systemFiles, ...datasourceFiles];
|
|
212
307
|
}
|
|
213
308
|
|
|
214
309
|
module.exports = {
|
|
215
310
|
resolveSchemaBasePath,
|
|
216
|
-
resolveExternalFiles
|
|
311
|
+
resolveExternalFiles,
|
|
312
|
+
orderDatasourceFileNamesBySystemKeys
|
|
217
313
|
};
|
|
218
314
|
|
|
@@ -8,16 +8,25 @@ const chalk = require('chalk');
|
|
|
8
8
|
const logger = require('./logger');
|
|
9
9
|
const { getValidationRunWithTransportRetry } = require('./validation-run-post-retry');
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
/** Short fixed delay while waiting for async E2E (typically a few seconds). */
|
|
12
|
+
const FAST_POLL_COUNT = 24;
|
|
13
|
+
const FAST_POLL_INTERVAL_MS = 400;
|
|
14
|
+
/** After fast phase, exponential backoff to limit load on long runs. */
|
|
15
|
+
const SLOW_BASE_INTERVAL_MS = 2000;
|
|
12
16
|
const MAX_INTERVAL_MS = 15000;
|
|
13
17
|
|
|
14
18
|
/**
|
|
15
|
-
* Delay between polls after attempt `n` (0-based)
|
|
19
|
+
* Delay between polls after attempt `n` (0-based).
|
|
20
|
+
* Fast phase (~10s of 400ms gaps) so CLI detects completion quickly; then 2s, 4s, … cap 15s.
|
|
16
21
|
* @param {number} attemptIndex - Zero-based poll index after initial POST
|
|
17
22
|
* @returns {number}
|
|
18
23
|
*/
|
|
19
24
|
function nextPollDelayMs(attemptIndex) {
|
|
20
|
-
|
|
25
|
+
if (attemptIndex < FAST_POLL_COUNT) {
|
|
26
|
+
return FAST_POLL_INTERVAL_MS;
|
|
27
|
+
}
|
|
28
|
+
const slowIndex = attemptIndex - FAST_POLL_COUNT;
|
|
29
|
+
const raw = SLOW_BASE_INTERVAL_MS * 2 ** Math.max(0, slowIndex);
|
|
21
30
|
return Math.min(raw, MAX_INTERVAL_MS);
|
|
22
31
|
}
|
|
23
32
|
|
|
@@ -104,7 +113,9 @@ async function pollValidationRunUntilComplete(opts) {
|
|
|
104
113
|
}
|
|
105
114
|
|
|
106
115
|
module.exports = {
|
|
107
|
-
|
|
116
|
+
FAST_POLL_COUNT,
|
|
117
|
+
FAST_POLL_INTERVAL_MS,
|
|
118
|
+
SLOW_BASE_INTERVAL_MS,
|
|
108
119
|
MAX_INTERVAL_MS,
|
|
109
120
|
nextPollDelayMs,
|
|
110
121
|
pollValidationRunUntilComplete,
|
|
@@ -36,9 +36,8 @@ function assignOptionalNonNegativeInt(e2e, key, raw) {
|
|
|
36
36
|
* @param {Object} options - CLI-derived options
|
|
37
37
|
* @param {boolean} [options.debug]
|
|
38
38
|
* @param {boolean} [options.verbose]
|
|
39
|
-
* @param {boolean} [options.testCrud]
|
|
40
|
-
* @param {string} [options.recordId]
|
|
41
39
|
* @param {boolean} [options.cleanup]
|
|
40
|
+
* @param {boolean} [options.runScenarios] - false when --no-run-scenarios
|
|
42
41
|
* @param {string|Object} [options.primaryKeyValue]
|
|
43
42
|
* @param {Object} [options.e2eOptionsExtra] - Shallow-merged last (e.g. server-specific drill-down fields)
|
|
44
43
|
* @returns {Object}
|
|
@@ -47,15 +46,14 @@ function buildE2eOptionsFromCli(options = {}) {
|
|
|
47
46
|
const e2e = {};
|
|
48
47
|
if (options.debug) e2e.includeDebug = true;
|
|
49
48
|
if (options.verbose) e2e.audit = true;
|
|
50
|
-
if (options.testCrud === true) e2e.testCrud = true;
|
|
51
|
-
if (options.recordId !== undefined && options.recordId !== null && options.recordId !== '') {
|
|
52
|
-
e2e.recordId = String(options.recordId);
|
|
53
|
-
}
|
|
54
49
|
if (options.cleanup === false) e2e.cleanup = false;
|
|
55
50
|
else if (options.cleanup === true) e2e.cleanup = true;
|
|
56
51
|
if (options.primaryKeyValue !== undefined && options.primaryKeyValue !== null) {
|
|
57
52
|
e2e.primaryKeyValue = options.primaryKeyValue;
|
|
58
53
|
}
|
|
54
|
+
if (options.runScenarios === false) {
|
|
55
|
+
e2e.runScenarios = false;
|
|
56
|
+
}
|
|
59
57
|
assignOptionalNonNegativeInt(e2e, 'minVectorHits', options.minVectorHits);
|
|
60
58
|
assignOptionalNonNegativeInt(e2e, 'minProcessed', options.minProcessed);
|
|
61
59
|
assignOptionalNonNegativeInt(e2e, 'minRecordCount', options.minRecordCount);
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Flatten datasource root `dimensions` for validate CLI output.
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {Array<{ fk?: string, dimension?: string }>} via - dimensionBinding.via
|
|
9
|
+
* @returns {string}
|
|
10
|
+
*/
|
|
11
|
+
function formatFkViaChain(via) {
|
|
12
|
+
return via
|
|
13
|
+
.map(v =>
|
|
14
|
+
v && typeof v.fk === 'string' && typeof v.dimension === 'string' ? `${v.fk}→${v.dimension}` : ''
|
|
15
|
+
)
|
|
16
|
+
.filter(Boolean)
|
|
17
|
+
.join(', ');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {unknown} actor - dimensionBinding.actor
|
|
22
|
+
* @returns {string}
|
|
23
|
+
*/
|
|
24
|
+
function formatFkActorSuffix(actor) {
|
|
25
|
+
return typeof actor === 'string' && actor.length > 0 ? ` (actor: ${actor})` : '';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Flatten root dimensions: local → metadata.<field>, fk → fk:<chain> (actor: ...).
|
|
30
|
+
* @param {Record<string, unknown>|null|undefined} root - datasource.dimensions
|
|
31
|
+
* @returns {Record<string, string>}
|
|
32
|
+
*/
|
|
33
|
+
function flattenRootDimensionsForDisplay(root) {
|
|
34
|
+
const rootFlat = {};
|
|
35
|
+
if (!root || typeof root !== 'object' || Array.isArray(root)) {
|
|
36
|
+
return rootFlat;
|
|
37
|
+
}
|
|
38
|
+
for (const [dimKey, binding] of Object.entries(root)) {
|
|
39
|
+
if (!binding || typeof binding !== 'object') {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (typeof binding.field === 'string') {
|
|
43
|
+
rootFlat[dimKey] = `metadata.${binding.field}`;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (binding.type !== 'fk' || !Array.isArray(binding.via)) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const chain = formatFkViaChain(binding.via);
|
|
50
|
+
if (!chain) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
rootFlat[dimKey] = `fk:${chain}${formatFkActorSuffix(binding.actor)}`;
|
|
54
|
+
}
|
|
55
|
+
return rootFlat;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
module.exports = {
|
|
59
|
+
flattenRootDimensionsForDisplay
|
|
60
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Shared log helpers for validate-display (layout.md tty-summary).
|
|
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 { sectionTitle, metadata, successGlyph } = require('../utils/cli-test-layout-chalk');
|
|
12
|
+
|
|
13
|
+
function logSectionTitle(title) {
|
|
14
|
+
logger.log(`\n${sectionTitle(title)}`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function logOkRowRest(message) {
|
|
18
|
+
logger.log(` ${successGlyph()} ${chalk.white(message)}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function logWarnRow(message) {
|
|
22
|
+
logger.log(` ${chalk.yellow('⚠')} ${chalk.white(message)}`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function logDimLine(text) {
|
|
26
|
+
logger.log(metadata(` ${text}`));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function logErrorDetail(message) {
|
|
30
|
+
logger.log(` ${chalk.red(`• ${message}`)}`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports = {
|
|
34
|
+
logSectionTitle,
|
|
35
|
+
logOkRowRest,
|
|
36
|
+
logWarnRow,
|
|
37
|
+
logDimLine,
|
|
38
|
+
logErrorDetail
|
|
39
|
+
};
|