@contrail/cli 3.5.1-alpha.68d57e0 → 3.5.1-alpha.9da7ac5
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/README.md +1 -1
- package/node_modules/@contrail/loader/lib/color-processor.js +23 -9
- package/node_modules/@contrail/loader/lib/color-processor.spec.js +62 -112
- package/node_modules/@contrail/loader/lib/common/chunk-by-url-length.d.ts +1 -1
- package/node_modules/@contrail/loader/lib/common/chunk-by-url-length.js +0 -2
- package/node_modules/@contrail/loader/lib/common/chunk-by-url-length.spec.js +0 -4
- package/node_modules/@contrail/loader/lib/common/size-range-helpers.js +1 -0
- package/node_modules/@contrail/loader/lib/constants.d.ts +3 -0
- package/node_modules/@contrail/loader/lib/constants.js +4 -1
- package/node_modules/@contrail/loader/lib/entities-v2/colors-v2/color-processor-v2.js +23 -9
- package/node_modules/@contrail/loader/lib/entities-v2/colors-v2/color-processor-v2.spec.js +62 -112
- package/node_modules/@contrail/loader/lib/entities-v2/entities-helper.js +1 -0
- package/node_modules/@contrail/loader/lib/entities-v2/linesheet-v2/assortment-processor.js +1 -0
- package/node_modules/@contrail/loader/lib/entities-v2/linesheet-v2/item-processor.js +22 -8
- package/node_modules/@contrail/loader/lib/entities-v2/linesheet-v2/item-processor.spec.js +1 -43
- package/node_modules/@contrail/loader/lib/pipeline/item-execute-helpers.js +3 -77
- package/node_modules/@contrail/loader/lib/pipeline/item-execute-helpers.spec.js +0 -82
- package/node_modules/@contrail/loader/lib/pipeline/preview.js +5 -0
- package/node_modules/@contrail/loader/lib/pipeline/preview.spec.js +2 -2
- package/node_modules/@contrail/loader/lib/pipeline/project-item-execute-helpers.js +1 -1
- package/node_modules/@contrail/loader/lib/pipeline/transform.js +0 -18
- package/node_modules/@contrail/loader/lib/pipeline/transform.spec.js +2 -3
- package/node_modules/@contrail/loader/lib/pipeline/types.d.ts +2 -5
- package/node_modules/@contrail/loader/lib/pipeline/types.js +0 -2
- package/node_modules/@contrail/loader/lib/pipeline/validate.js +437 -184
- package/node_modules/@contrail/loader/lib/pipeline/validate.spec.js +53 -157
- package/node_modules/@contrail/loader/package.json +2 -3
- package/oclif.manifest.json +1 -1
- package/package.json +2 -2
- package/node_modules/@contrail/loader/lib/common/color-validation.d.ts +0 -26
- package/node_modules/@contrail/loader/lib/common/color-validation.js +0 -163
- package/node_modules/@contrail/loader/lib/common/color-validation.spec.d.ts +0 -1
- package/node_modules/@contrail/loader/lib/common/color-validation.spec.js +0 -102
- package/node_modules/@contrail/loader/lib/pipeline/identifier-resolver.d.ts +0 -5
- package/node_modules/@contrail/loader/lib/pipeline/identifier-resolver.js +0 -562
- package/node_modules/@contrail/loader/lib/pipeline/identifier-resolver.spec.d.ts +0 -1
- package/node_modules/@contrail/loader/lib/pipeline/identifier-resolver.spec.js +0 -231
- package/node_modules/validate-color/LICENSE +0 -21
- package/node_modules/validate-color/README.md +0 -265
- package/node_modules/validate-color/lib/index.d.ts +0 -10
- package/node_modules/validate-color/lib/index.js +0 -1
- package/node_modules/validate-color/package.json +0 -91
- package/node_modules/validate-color/test/redos.js +0 -29
|
@@ -60,7 +60,7 @@ class ItemProcessor extends base_processor_v2_1.BaseProcessorV2 {
|
|
|
60
60
|
return { errors, warnings, generalErrors, generalWarnings };
|
|
61
61
|
}
|
|
62
62
|
this.validateLoadType(config, generalErrors);
|
|
63
|
-
this.validateTypePathMapping(data, generalErrors);
|
|
63
|
+
this.validateTypePathMapping(config, csvHeaders, data, generalErrors);
|
|
64
64
|
this.validateOptionNameMapping(config, csvHeaders, generalWarnings);
|
|
65
65
|
this.validateItemOptionFederatedIdMapping(config, csvHeaders, generalWarnings);
|
|
66
66
|
this.validateFederatedIds(data, config, errors, generalErrors, csvHeaders);
|
|
@@ -75,13 +75,27 @@ class ItemProcessor extends base_processor_v2_1.BaseProcessorV2 {
|
|
|
75
75
|
});
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
-
static validateTypePathMapping(data, generalErrors) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
78
|
+
static validateTypePathMapping(config, csvHeaders, data, generalErrors) {
|
|
79
|
+
if (Array.isArray(config?.conditionalColumns) && config.conditionalColumns.length) {
|
|
80
|
+
const hasTypePathColumn = config.conditionalColumns.some((column) => column.toProperty === 'typePath');
|
|
81
|
+
const hasRequiredConditionalColumn = config.conditionalColumns.some((column) => column.toProperty === 'typePath' &&
|
|
82
|
+
(column.default === 'item' ||
|
|
83
|
+
(column.default?.startsWith('item:') && column.default?.split(':')[1]?.length > 0)));
|
|
84
|
+
if (hasTypePathColumn && !hasRequiredConditionalColumn) {
|
|
85
|
+
generalErrors.push({
|
|
86
|
+
message: constants_1.ITEM_PROCESSOR_ERRORS.TYPEPATH_INVALID,
|
|
87
|
+
issueType: entity_types_1.IssueType.CONFIG,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else if (csvHeaders.includes('typePath')) {
|
|
92
|
+
const hasCorrectTypePath = data.every((row) => row.typePath === 'item' || (row.typePath?.startsWith('item:') && row.typePath?.split(':')[1]?.length > 0));
|
|
93
|
+
if (!hasCorrectTypePath) {
|
|
94
|
+
generalErrors.push({
|
|
95
|
+
message: constants_1.ITEM_PROCESSOR_ERRORS.TYPEPATH_INVALID,
|
|
96
|
+
issueType: entity_types_1.IssueType.CONFIG,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
85
99
|
}
|
|
86
100
|
}
|
|
87
101
|
static validateOptionNameMapping(config, csvHeaders, generalWarnings) {
|
|
@@ -28,21 +28,18 @@ describe('Item Processor', () => {
|
|
|
28
28
|
family_federated_id: 'family_1',
|
|
29
29
|
input_col_1: 'value_1',
|
|
30
30
|
input_col_2: 'value_2',
|
|
31
|
-
typePath: 'item',
|
|
32
31
|
},
|
|
33
32
|
{
|
|
34
33
|
name: 'item2',
|
|
35
34
|
family_federated_id: 'family_2',
|
|
36
35
|
input_col_1: 'value_3',
|
|
37
36
|
input_col_2: 'value_4',
|
|
38
|
-
typePath: 'item',
|
|
39
37
|
},
|
|
40
38
|
{
|
|
41
39
|
name: 'item3',
|
|
42
40
|
family_federated_id: 'family_3',
|
|
43
41
|
input_col_1: 'value_5',
|
|
44
42
|
input_col_2: 'value_6',
|
|
45
|
-
typePath: 'item',
|
|
46
43
|
},
|
|
47
44
|
];
|
|
48
45
|
const config = {
|
|
@@ -170,7 +167,7 @@ describe('Item Processor', () => {
|
|
|
170
167
|
},
|
|
171
168
|
]);
|
|
172
169
|
});
|
|
173
|
-
it('should throw error if typepath is not present in csv header', () => {
|
|
170
|
+
it('should not throw error if typepath is not present in csv header and config file', () => {
|
|
174
171
|
const data = [
|
|
175
172
|
{
|
|
176
173
|
name: 'item1',
|
|
@@ -196,42 +193,6 @@ describe('Item Processor', () => {
|
|
|
196
193
|
conditionalColumns: [],
|
|
197
194
|
};
|
|
198
195
|
const result = item_processor_1.ItemProcessor.validateLoadFile(data, config);
|
|
199
|
-
expect(result.generalErrors).toEqual([
|
|
200
|
-
{
|
|
201
|
-
message: constants_1.ITEM_PROCESSOR_ERRORS.TYPEPATH_INVALID,
|
|
202
|
-
issueType: entity_types_1.IssueType.CONFIG,
|
|
203
|
-
},
|
|
204
|
-
]);
|
|
205
|
-
});
|
|
206
|
-
it('should not throw error if every row has a valid typePath', () => {
|
|
207
|
-
const data = [
|
|
208
|
-
{
|
|
209
|
-
name: 'item1',
|
|
210
|
-
family_federated_id: 'family_1',
|
|
211
|
-
input_col_1: 'value_1',
|
|
212
|
-
input_col_2: 'value_2',
|
|
213
|
-
typePath: 'item',
|
|
214
|
-
},
|
|
215
|
-
{
|
|
216
|
-
name: 'item2',
|
|
217
|
-
family_federated_id: 'family_2',
|
|
218
|
-
input_col_1: 'value_3',
|
|
219
|
-
input_col_2: 'value_4',
|
|
220
|
-
typePath: 'item:material:fabric:yarn',
|
|
221
|
-
},
|
|
222
|
-
{
|
|
223
|
-
name: 'item3',
|
|
224
|
-
family_federated_id: 'family_3',
|
|
225
|
-
input_col_1: 'value_5',
|
|
226
|
-
input_col_2: 'value_6',
|
|
227
|
-
typePath: 'item:material:fabric:leather',
|
|
228
|
-
},
|
|
229
|
-
];
|
|
230
|
-
const config = {
|
|
231
|
-
...loaderProcess,
|
|
232
|
-
conditionalColumns: [],
|
|
233
|
-
};
|
|
234
|
-
const result = item_processor_1.ItemProcessor.validateLoadFile(data, config);
|
|
235
196
|
expect(result.generalErrors).toEqual([]);
|
|
236
197
|
});
|
|
237
198
|
});
|
|
@@ -639,17 +600,14 @@ describe('Item Processor', () => {
|
|
|
639
600
|
{
|
|
640
601
|
itemFamilyFederatedId: '1',
|
|
641
602
|
name: 'foo',
|
|
642
|
-
typePath: 'item',
|
|
643
603
|
},
|
|
644
604
|
{
|
|
645
605
|
itemFamilyFederatedId: '1',
|
|
646
606
|
name: 'bar',
|
|
647
|
-
typePath: 'item',
|
|
648
607
|
},
|
|
649
608
|
{
|
|
650
609
|
itemFamilyFederatedId: '3',
|
|
651
610
|
name: 'test',
|
|
652
|
-
typePath: 'item',
|
|
653
611
|
},
|
|
654
612
|
];
|
|
655
613
|
const config = {
|
|
@@ -11,97 +11,23 @@ const pLimit = require('p-limit');
|
|
|
11
11
|
const DEFAULT_BATCH_SIZE = 50;
|
|
12
12
|
const DEFAULT_CONCURRENCY = 20;
|
|
13
13
|
const DEFAULT_MAX_RETRIES = 3;
|
|
14
|
-
function findUniquenessPayload(node, depth = 0) {
|
|
15
|
-
if (!node || depth > 6)
|
|
16
|
-
return undefined;
|
|
17
|
-
if (Array.isArray(node?.failedEntities))
|
|
18
|
-
return node;
|
|
19
|
-
if (typeof node === 'string') {
|
|
20
|
-
const trimmed = node.trim();
|
|
21
|
-
if (trimmed.startsWith('[') || trimmed.startsWith('{')) {
|
|
22
|
-
try {
|
|
23
|
-
return findUniquenessPayload(JSON.parse(trimmed), depth + 1);
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
return undefined;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return undefined;
|
|
30
|
-
}
|
|
31
|
-
if (Array.isArray(node)) {
|
|
32
|
-
for (const child of node) {
|
|
33
|
-
const found = findUniquenessPayload(child, depth + 1);
|
|
34
|
-
if (found)
|
|
35
|
-
return found;
|
|
36
|
-
}
|
|
37
|
-
return undefined;
|
|
38
|
-
}
|
|
39
|
-
if (typeof node === 'object') {
|
|
40
|
-
for (const key of ['error', 'response', 'message', 'data', 'body']) {
|
|
41
|
-
if (node[key] !== undefined) {
|
|
42
|
-
const found = findUniquenessPayload(node[key], depth + 1);
|
|
43
|
-
if (found)
|
|
44
|
-
return found;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return undefined;
|
|
49
|
-
}
|
|
50
14
|
function extractApiErrorMessage(err) {
|
|
51
|
-
const validationErrors = err?.error?.response?.validationSummary?.validationErrors
|
|
52
|
-
err?.error?.response?.validationErrors;
|
|
15
|
+
const validationErrors = err?.error?.response?.validationSummary?.validationErrors;
|
|
53
16
|
if (validationErrors && typeof validationErrors === 'object') {
|
|
54
17
|
const messages = [];
|
|
55
18
|
for (const [field, errors] of Object.entries(validationErrors)) {
|
|
56
19
|
if (Array.isArray(errors)) {
|
|
57
20
|
for (const e of errors) {
|
|
58
|
-
|
|
59
|
-
const valuePart = isObj && 'value' in e ? ` (value=${JSON.stringify(e.value)})` : '';
|
|
60
|
-
const msg = isObj ? e.message || JSON.stringify(e) : String(e);
|
|
61
|
-
messages.push(`${field}${valuePart}: ${msg}`);
|
|
21
|
+
messages.push(`${field}: ${e.message || JSON.stringify(e)}`);
|
|
62
22
|
}
|
|
63
23
|
}
|
|
64
24
|
}
|
|
65
25
|
if (messages.length > 0)
|
|
66
|
-
return
|
|
67
|
-
}
|
|
68
|
-
const uniquePayload = findUniquenessPayload(err);
|
|
69
|
-
if (uniquePayload?.failedEntities?.length) {
|
|
70
|
-
const parts = uniquePayload.failedEntities.map((f) => {
|
|
71
|
-
const label = f.propertyLabel ?? f.propertyName ?? '<unknown>';
|
|
72
|
-
const value = f.propertyValue ?? '';
|
|
73
|
-
return `${label}=${JSON.stringify(value)}`;
|
|
74
|
-
});
|
|
75
|
-
const offending = uniquePayload.propertiesMustBeUnique?.length
|
|
76
|
-
? ` (one of ${uniquePayload.propertiesMustBeUnique.join(', ')} is already taken or duplicated in batch)`
|
|
77
|
-
: '';
|
|
78
|
-
return `Uniqueness conflict — attempted: ${parts.join(', ')}${offending}`;
|
|
79
|
-
}
|
|
80
|
-
try {
|
|
81
|
-
console.warn('[extractApiErrorMessage] unknown error shape:', summarizeErrorShape(err));
|
|
82
|
-
}
|
|
83
|
-
catch {
|
|
26
|
+
return messages.join('; ');
|
|
84
27
|
}
|
|
85
28
|
return err?.error?.message ?? err?.error?.response?.message ?? String(err?.error);
|
|
86
29
|
}
|
|
87
30
|
exports.extractApiErrorMessage = extractApiErrorMessage;
|
|
88
|
-
function summarizeErrorShape(err) {
|
|
89
|
-
const truncate = (s, max = 200) => {
|
|
90
|
-
if (s === undefined || s === null)
|
|
91
|
-
return undefined;
|
|
92
|
-
const str = typeof s === 'string' ? s : JSON.stringify(s);
|
|
93
|
-
return str.length > max ? `${str.slice(0, max)}…` : str;
|
|
94
|
-
};
|
|
95
|
-
const errInner = err?.error;
|
|
96
|
-
return {
|
|
97
|
-
topLevelKeys: err && typeof err === 'object' ? Object.keys(err) : undefined,
|
|
98
|
-
errorKeys: errInner && typeof errInner === 'object' ? Object.keys(errInner) : undefined,
|
|
99
|
-
status: errInner?.status ?? errInner?.response?.status,
|
|
100
|
-
name: errInner?.name,
|
|
101
|
-
message: truncate(errInner?.message),
|
|
102
|
-
responseMessage: truncate(errInner?.response?.message),
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
31
|
function extractFailureId(err) {
|
|
106
32
|
return (err?.data?.federatedId ??
|
|
107
33
|
err?.entity?.federatedId ??
|
|
@@ -2,88 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const types_1 = require("@contrail/types");
|
|
4
4
|
const item_execute_helpers_1 = require("./item-execute-helpers");
|
|
5
|
-
describe('extractApiErrorMessage', () => {
|
|
6
|
-
it('formats current-shape validation errors (response.validationErrors)', () => {
|
|
7
|
-
const err = {
|
|
8
|
-
entity: { federatedId: 'TB0A41MG' },
|
|
9
|
-
error: {
|
|
10
|
-
response: {
|
|
11
|
-
validationErrorCount: 1,
|
|
12
|
-
validationErrors: {
|
|
13
|
-
vfAdvConceptsTech: [
|
|
14
|
-
{ value: 'GRIPMAX SLIP RESISTANT', message: 'The value provided is not a valid option for this property.' },
|
|
15
|
-
],
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
status: 400,
|
|
19
|
-
message: 'Bad Request Exception',
|
|
20
|
-
name: 'BadRequestException',
|
|
21
|
-
},
|
|
22
|
-
};
|
|
23
|
-
const msg = (0, item_execute_helpers_1.extractApiErrorMessage)(err);
|
|
24
|
-
expect(msg).toContain('Validation failed');
|
|
25
|
-
expect(msg).toContain('vfAdvConceptsTech');
|
|
26
|
-
expect(msg).toContain('GRIPMAX SLIP RESISTANT');
|
|
27
|
-
expect(msg).toContain('The value provided is not a valid option');
|
|
28
|
-
});
|
|
29
|
-
it('formats older-shape validation errors (validationSummary.validationErrors)', () => {
|
|
30
|
-
const err = {
|
|
31
|
-
error: {
|
|
32
|
-
response: {
|
|
33
|
-
validationSummary: {
|
|
34
|
-
validationErrors: {
|
|
35
|
-
name: [{ message: 'Required.' }],
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
};
|
|
41
|
-
expect((0, item_execute_helpers_1.extractApiErrorMessage)(err)).toBe('Validation failed — name: Required.');
|
|
42
|
-
});
|
|
43
|
-
it('does not throw when a validation-error array contains primitive entries', () => {
|
|
44
|
-
const err = {
|
|
45
|
-
error: {
|
|
46
|
-
response: {
|
|
47
|
-
validationErrors: { someField: ['oops'] },
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
expect(() => (0, item_execute_helpers_1.extractApiErrorMessage)(err)).not.toThrow();
|
|
52
|
-
expect((0, item_execute_helpers_1.extractApiErrorMessage)(err)).toContain('someField');
|
|
53
|
-
});
|
|
54
|
-
describe('uniqueness conflict payloads', () => {
|
|
55
|
-
const sample = [
|
|
56
|
-
{
|
|
57
|
-
failedEntities: [
|
|
58
|
-
{ propertyName: 'federatedId', propertyLabel: 'Federated Id', propertyValue: '0A294C', entityReference: 'item:abc' },
|
|
59
|
-
{ propertyName: 'vfStyleNumber', propertyLabel: 'Style Number', propertyValue: '0A294C', entityReference: 'item:abc' },
|
|
60
|
-
],
|
|
61
|
-
propertiesMustBeUnique: ['federatedId', 'vfStyleNumber'],
|
|
62
|
-
},
|
|
63
|
-
];
|
|
64
|
-
it('finds the payload nested under err.error.response.message (object form)', () => {
|
|
65
|
-
const msg = (0, item_execute_helpers_1.extractApiErrorMessage)({ error: { response: { message: sample } } });
|
|
66
|
-
expect(msg).toContain('Uniqueness conflict');
|
|
67
|
-
expect(msg).toContain('Style Number="0A294C"');
|
|
68
|
-
expect(msg).toContain('vfStyleNumber');
|
|
69
|
-
});
|
|
70
|
-
it('parses the payload when err.error.response.message is a JSON-stringified array', () => {
|
|
71
|
-
const msg = (0, item_execute_helpers_1.extractApiErrorMessage)({ error: { response: { message: JSON.stringify(sample) } } });
|
|
72
|
-
expect(msg).toContain('Uniqueness conflict');
|
|
73
|
-
expect(msg).toContain('Federated Id="0A294C"');
|
|
74
|
-
});
|
|
75
|
-
it('finds the payload at the top level', () => {
|
|
76
|
-
expect((0, item_execute_helpers_1.extractApiErrorMessage)(sample[0])).toContain('Uniqueness conflict');
|
|
77
|
-
});
|
|
78
|
-
it('falls back to a redacted summary for unknown shapes', () => {
|
|
79
|
-
const warn = jest.spyOn(console, 'warn').mockImplementation(() => { });
|
|
80
|
-
const result = (0, item_execute_helpers_1.extractApiErrorMessage)({ error: { something: 'else', message: 'mystery' } });
|
|
81
|
-
expect(result).toBe('mystery');
|
|
82
|
-
expect(warn).toHaveBeenCalledWith('[extractApiErrorMessage] unknown error shape:', expect.objectContaining({ message: 'mystery' }));
|
|
83
|
-
warn.mockRestore();
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
5
|
describe('splitIntoFamiliesAndOptions', () => {
|
|
88
6
|
const makeTypesByPath = (typeProperties) => ({
|
|
89
7
|
item: {
|
|
@@ -21,6 +21,11 @@ async function preview(client, rows, config, columnAnalysis) {
|
|
|
21
21
|
const itemsByFederatedId = entityType !== types_1.EntityType.ITEM ? { ...sharedItemsByFederatedId } : {};
|
|
22
22
|
const clonedRows = rows.map(row => ({ ...row }));
|
|
23
23
|
const result = await entity_processor_v2_1.EntityProcessorV2.setupEntities(client, entityType, clonedRows, undefined, loaderProcess, itemsByFederatedId, doConstructEntities, columnAnalysis.typesByPath ? buildTypesByTypePathCache(columnAnalysis) : undefined);
|
|
24
|
+
if (result.generalWarnings?.length) {
|
|
25
|
+
for (const warning of result.generalWarnings) {
|
|
26
|
+
allWarnings.push(warning.message);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
24
29
|
if (result.badEntities?.length) {
|
|
25
30
|
for (let i = 0; i < result.badEntities.length; i++) {
|
|
26
31
|
const badEntity = result.badEntities[i];
|
|
@@ -122,7 +122,7 @@ describe('preview (non-item entity types)', () => {
|
|
|
122
122
|
expect(result.staleRows[0].details?.incomingTimestamp).toBe('2024-01-01T00:00:00Z');
|
|
123
123
|
expect(result.staleRows[0].details?.existingTimestamp).toBe('2024-06-01T00:00:00Z');
|
|
124
124
|
});
|
|
125
|
-
it('should
|
|
125
|
+
it('should collect warnings from object reference resolution', async () => {
|
|
126
126
|
entity_processor_v2_1.EntityProcessorV2.setupEntities.mockResolvedValue({
|
|
127
127
|
incomingEntities: [],
|
|
128
128
|
badEntities: [],
|
|
@@ -135,7 +135,7 @@ describe('preview (non-item entity types)', () => {
|
|
|
135
135
|
});
|
|
136
136
|
const rows = [{ federatedId: '1' }];
|
|
137
137
|
const result = await (0, preview_1.preview)(mockClient, rows, baseConfig, baseAnalysis);
|
|
138
|
-
expect(result.warnings).
|
|
138
|
+
expect(result.warnings).toContain('ObjectReference not found for vendor with value acme');
|
|
139
139
|
});
|
|
140
140
|
it('should store constructed entities for execute stage', async () => {
|
|
141
141
|
entity_processor_v2_1.EntityProcessorV2.setupEntities.mockResolvedValue({
|
|
@@ -232,7 +232,7 @@ async function executeProjectItemEntities(client, entitySet, config, options) {
|
|
|
232
232
|
failures: [{
|
|
233
233
|
federatedId: 'N/A',
|
|
234
234
|
operation: 'create',
|
|
235
|
-
error: 'Could not resolve a target Project\'s ID
|
|
235
|
+
error: 'Could not resolve a target Project\'s ID from the data or config provided. Include or map a workspaceIdentifier column if loading only ProjectItems, or a projectId column with the project\'s ID directly.',
|
|
236
236
|
}],
|
|
237
237
|
}],
|
|
238
238
|
skippedRows: [],
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.transform = void 0;
|
|
4
4
|
const types_1 = require("./types");
|
|
5
|
-
const identifier_resolver_1 = require("./identifier-resolver");
|
|
6
5
|
const data_transformer_functions_1 = require("../common/data-transformer-functions");
|
|
7
6
|
const type_helper_1 = require("../common/type-helper");
|
|
8
7
|
const types_2 = require("./types");
|
|
@@ -128,22 +127,6 @@ async function transform(client, rows, config) {
|
|
|
128
127
|
typeAware.generalErrors.push({ message: errorMessage, issueType: types_1.IssueType.SYSTEM_ERROR });
|
|
129
128
|
}
|
|
130
129
|
const { columns, unmappedTypeProperties } = analyzeColumns(processedData, typePropertyMaps, config);
|
|
131
|
-
let identifierIssues = [];
|
|
132
|
-
try {
|
|
133
|
-
const resolved = await (0, identifier_resolver_1.resolveIdentifiers)(processedData, config, client);
|
|
134
|
-
identifierIssues = resolved.issues;
|
|
135
|
-
}
|
|
136
|
-
catch (e) {
|
|
137
|
-
const errorMessage = `Error in transform step "Resolve Identifiers": ${e.message}`;
|
|
138
|
-
console.error(errorMessage);
|
|
139
|
-
typeAware.generalErrors.push({ message: errorMessage, issueType: types_1.IssueType.SYSTEM_ERROR });
|
|
140
|
-
}
|
|
141
|
-
typeAware.stepResults.push({
|
|
142
|
-
stepName: 'Resolve Identifiers',
|
|
143
|
-
rowCountAfter: processedData.length,
|
|
144
|
-
errorCount: identifierIssues.filter((i) => i.severity === 'error').length,
|
|
145
|
-
warningCount: identifierIssues.filter((i) => i.severity === 'warning').length,
|
|
146
|
-
});
|
|
147
130
|
const merged = mergeResults(structural, typeAware);
|
|
148
131
|
merged.stepResults.push({
|
|
149
132
|
stepName: 'Analyze Columns',
|
|
@@ -157,7 +140,6 @@ async function transform(client, rows, config) {
|
|
|
157
140
|
typesByPath,
|
|
158
141
|
columns,
|
|
159
142
|
unmappedTypeProperties,
|
|
160
|
-
identifierIssues,
|
|
161
143
|
...collectIssues(merged),
|
|
162
144
|
};
|
|
163
145
|
}
|
|
@@ -63,10 +63,10 @@ describe('transform', () => {
|
|
|
63
63
|
expect(result.stepResults).toEqual([]);
|
|
64
64
|
expect(result.errors).toEqual([]);
|
|
65
65
|
});
|
|
66
|
-
it('should run all
|
|
66
|
+
it('should run all 8 transform steps (including type fetch and column analysis)', async () => {
|
|
67
67
|
const rows = [{ sku: 'ABC-123', name: 'Test', active: 'true' }];
|
|
68
68
|
const result = await (0, transform_1.transform)(mockClient, rows, baseConfig);
|
|
69
|
-
expect(result.stepResults).toHaveLength(
|
|
69
|
+
expect(result.stepResults).toHaveLength(8);
|
|
70
70
|
expect(result.stepResults.map((s) => s.stepName)).toEqual([
|
|
71
71
|
'Evaluate Conditional Columns',
|
|
72
72
|
'Remove Unwanted Properties',
|
|
@@ -75,7 +75,6 @@ describe('transform', () => {
|
|
|
75
75
|
'Fetch Type Definitions',
|
|
76
76
|
'Transform Data Based on Types',
|
|
77
77
|
'Coerce Values by Type',
|
|
78
|
-
'Resolve Identifiers',
|
|
79
78
|
'Analyze Columns',
|
|
80
79
|
]);
|
|
81
80
|
});
|
|
@@ -41,9 +41,7 @@ export declare enum PreValidationCategory {
|
|
|
41
41
|
SELF_REFERENCE = "SELF_REFERENCE",
|
|
42
42
|
UNMAPPED_COLUMN = "UNMAPPED_COLUMN",
|
|
43
43
|
UNMAPPED_TYPE_PROPERTY = "UNMAPPED_TYPE_PROPERTY",
|
|
44
|
-
FORMAT_NUMBER_PRECISION = "FORMAT_NUMBER_PRECISION"
|
|
45
|
-
INVALID_DATA = "INVALID_DATA",
|
|
46
|
-
DUPLICATE_FEDERATED_ID = "DUPLICATE_FEDERATED_ID"
|
|
44
|
+
FORMAT_NUMBER_PRECISION = "FORMAT_NUMBER_PRECISION"
|
|
47
45
|
}
|
|
48
46
|
export declare enum PreValidationSeverity {
|
|
49
47
|
ERROR = "error",
|
|
@@ -135,9 +133,8 @@ export interface TransformResult {
|
|
|
135
133
|
generalErrors: GeneralIssueDetails[];
|
|
136
134
|
generalWarnings: GeneralIssueDetails[];
|
|
137
135
|
stepResults: PreprocessingStepSummary[];
|
|
138
|
-
identifierIssues?: PreValidationIssue[];
|
|
139
136
|
}
|
|
140
|
-
export declare type ColumnAnalysisResult = Pick<TransformResult, 'columns' | 'unmappedTypeProperties' | 'typePropertyMaps' | 'typesByPath'
|
|
137
|
+
export declare type ColumnAnalysisResult = Pick<TransformResult, 'columns' | 'unmappedTypeProperties' | 'typePropertyMaps' | 'typesByPath'>;
|
|
141
138
|
export interface ColumnMetaData {
|
|
142
139
|
csvHeader: string;
|
|
143
140
|
matchedSlug?: string;
|
|
@@ -49,8 +49,6 @@ var PreValidationCategory;
|
|
|
49
49
|
PreValidationCategory["UNMAPPED_COLUMN"] = "UNMAPPED_COLUMN";
|
|
50
50
|
PreValidationCategory["UNMAPPED_TYPE_PROPERTY"] = "UNMAPPED_TYPE_PROPERTY";
|
|
51
51
|
PreValidationCategory["FORMAT_NUMBER_PRECISION"] = "FORMAT_NUMBER_PRECISION";
|
|
52
|
-
PreValidationCategory["INVALID_DATA"] = "INVALID_DATA";
|
|
53
|
-
PreValidationCategory["DUPLICATE_FEDERATED_ID"] = "DUPLICATE_FEDERATED_ID";
|
|
54
52
|
})(PreValidationCategory = exports.PreValidationCategory || (exports.PreValidationCategory = {}));
|
|
55
53
|
var PreValidationSeverity;
|
|
56
54
|
(function (PreValidationSeverity) {
|