@contrail/flexplm 1.5.1-alpha.c9b11be → 1.6.0-alpha.6f15d4e
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/lib/cli/commands/compile.d.ts +4 -0
- package/lib/cli/commands/compile.js +73 -0
- package/lib/cli/commands/compile.spec.d.ts +1 -0
- package/lib/cli/commands/compile.spec.js +80 -0
- package/lib/cli/commands/create.d.ts +5 -0
- package/lib/cli/commands/create.js +77 -0
- package/lib/cli/commands/create.spec.d.ts +1 -0
- package/lib/cli/commands/create.spec.js +78 -0
- package/lib/cli/commands/upload.d.ts +17 -0
- package/lib/cli/commands/upload.js +228 -0
- package/lib/cli/commands/upload.spec.d.ts +1 -0
- package/lib/cli/commands/upload.spec.js +88 -0
- package/lib/cli/index.d.ts +5 -0
- package/lib/cli/index.js +70 -0
- package/lib/cli/index.spec.d.ts +1 -0
- package/lib/cli/index.spec.js +85 -0
- package/lib/cli/template/mapping-template.ts.template +62 -0
- package/lib/entity-processor/base-entity-processor.d.ts +65 -0
- package/lib/entity-processor/base-entity-processor.js +71 -0
- package/lib/entity-processor/base-entity-processor.spec.js +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/interfaces/mapping-file.d.ts +460 -0
- package/lib/interfaces/mapping-file.js +2 -0
- package/lib/publish/base-process-publish-assortment.d.ts +25 -1
- package/lib/publish/base-process-publish-assortment.js +67 -48
- package/lib/publish/base-process-publish-assortment.spec.js +22 -143
- package/lib/publish/mockData.js +5 -0
- package/lib/transform/identifier-conversion-spec-mockData.js +34 -6
- package/lib/transform/identifier-conversion.d.ts +36 -0
- package/lib/transform/identifier-conversion.js +36 -0
- package/lib/transform/identifier-conversion.spec.js +4 -0
- package/lib/util/config-defaults.js +3 -0
- package/lib/util/config-defaults.spec.js +9 -0
- package/lib/util/data-converter-spec-mockData.js +17 -3
- package/lib/util/data-converter.d.ts +97 -0
- package/lib/util/data-converter.js +127 -1
- package/lib/util/data-converter.spec.js +2 -0
- package/lib/util/error-response-object.d.ts +5 -0
- package/lib/util/error-response-object.js +7 -0
- package/lib/util/event-short-message-status.js +1 -0
- package/lib/util/federation.js +8 -0
- package/lib/util/flexplm-connect.d.ts +7 -0
- package/lib/util/flexplm-connect.js +14 -0
- package/lib/util/logger-config.js +1 -0
- package/lib/util/map-util-spec-mockData.js +17 -3
- package/lib/util/map-utils.d.ts +27 -0
- package/lib/util/map-utils.js +27 -0
- package/lib/util/thumbnail-util.d.ts +21 -0
- package/lib/util/thumbnail-util.js +28 -1
- package/lib/util/thumbnail-util.spec.js +6 -0
- package/lib/util/type-conversion-utils-spec-mockData.js +3 -3
- package/lib/util/type-conversion-utils.d.ts +151 -0
- package/lib/util/type-conversion-utils.js +154 -0
- package/lib/util/type-defaults.d.ts +66 -0
- package/lib/util/type-defaults.js +66 -0
- package/lib/util/type-defaults.spec.js +5 -5
- package/lib/util/type-utils.d.ts +21 -0
- package/lib/util/type-utils.js +23 -0
- package/lib/util/type-utils.spec.js +2 -0
- package/package.json +21 -6
- package/scripts/copy-template.js +10 -0
- package/.github/pull_request_template.md +0 -31
- package/.github/workflows/flexplm-lib.yml +0 -27
- package/.github/workflows/publish-to-npm.yml +0 -121
- package/CHANGELOG.md +0 -49
- package/publish.bat +0 -5
- package/publish.sh +0 -5
- package/src/entity-processor/base-entity-processor.spec.ts +0 -689
- package/src/entity-processor/base-entity-processor.ts +0 -583
- package/src/flexplm-request.ts +0 -28
- package/src/flexplm-utils.spec.ts +0 -27
- package/src/flexplm-utils.ts +0 -29
- package/src/index.ts +0 -22
- package/src/interfaces/interfaces.ts +0 -122
- package/src/interfaces/item-family-changes.ts +0 -67
- package/src/interfaces/publish-change-data.ts +0 -43
- package/src/publish/base-process-publish-assortment-callback.ts +0 -50
- package/src/publish/base-process-publish-assortment.spec.ts +0 -2154
- package/src/publish/base-process-publish-assortment.ts +0 -1173
- package/src/publish/mockData.ts +0 -4561
- package/src/transform/identifier-conversion-spec-mockData.ts +0 -496
- package/src/transform/identifier-conversion.spec.ts +0 -386
- package/src/transform/identifier-conversion.ts +0 -282
- package/src/util/config-defaults.spec.ts +0 -445
- package/src/util/config-defaults.ts +0 -106
- package/src/util/data-converter-spec-mockData.ts +0 -231
- package/src/util/data-converter.spec.ts +0 -1622
- package/src/util/data-converter.ts +0 -819
- package/src/util/error-response-object.spec.ts +0 -116
- package/src/util/error-response-object.ts +0 -50
- package/src/util/event-short-message-status.ts +0 -22
- package/src/util/federation.ts +0 -172
- package/src/util/flexplm-connect.spec.ts +0 -132
- package/src/util/flexplm-connect.ts +0 -208
- package/src/util/logger-config.ts +0 -20
- package/src/util/map-util-spec-mockData.ts +0 -231
- package/src/util/map-utils.spec.ts +0 -103
- package/src/util/map-utils.ts +0 -41
- package/src/util/mockData.ts +0 -101
- package/src/util/thumbnail-util.spec.ts +0 -508
- package/src/util/thumbnail-util.ts +0 -272
- package/src/util/type-conversion-utils-spec-mockData.ts +0 -272
- package/src/util/type-conversion-utils.spec.ts +0 -1031
- package/src/util/type-conversion-utils.ts +0 -490
- package/src/util/type-defaults.spec.ts +0 -797
- package/src/util/type-defaults.ts +0 -320
- package/src/util/type-utils.spec.ts +0 -227
- package/src/util/type-utils.ts +0 -144
- package/tsconfig.json +0 -24
- package/tslint.json +0 -57
|
@@ -45,16 +45,22 @@ class DataConverter {
|
|
|
45
45
|
if (this.isVerboseDebugOn()) {
|
|
46
46
|
console.debug('newData: ' + JSON.stringify(newData));
|
|
47
47
|
}
|
|
48
|
+
//Using event to get propertyDiffs to find emptied values
|
|
49
|
+
//Add standard atts to skip
|
|
48
50
|
dataToSkip = dataToSkip.concat(['updatedOn', 'updatedById', 'createdOn', 'createdById', 'modifiedAt', 'orgId', 'createdAt', 'id', 'typeId', 'workspaceId']);
|
|
51
|
+
// const oldData = event.oldData;
|
|
49
52
|
const data = {};
|
|
50
53
|
const typeId = newData?.typeId;
|
|
51
54
|
if (!typeId) {
|
|
52
|
-
return;
|
|
55
|
+
return; // Don't have a type; so can't process
|
|
53
56
|
}
|
|
54
57
|
data['typePath'] = newData['typePath'];
|
|
55
58
|
const type = await this.typeUtils.getTypeById(typeId);
|
|
56
59
|
const typeProps = this.typeUtils.filterTypeProperties(type, newData);
|
|
57
60
|
for (const prop of typeProps) {
|
|
61
|
+
// if(this.logger.isTraceOn()){
|
|
62
|
+
// this.logger.log('prop: ' + JSON.stringify(prop));
|
|
63
|
+
// }
|
|
58
64
|
const slug = prop['slug'];
|
|
59
65
|
if (dataToSkip.includes(slug)) {
|
|
60
66
|
continue;
|
|
@@ -70,6 +76,7 @@ class DataConverter {
|
|
|
70
76
|
const propertyType = prop['propertyType'];
|
|
71
77
|
const slug = prop['slug'];
|
|
72
78
|
const nd = newData[slug];
|
|
79
|
+
// console.log('getFlexPLMValue: ' + propertyType + ', ' +slug + ', ' + nd + ', ' + od);
|
|
73
80
|
let value;
|
|
74
81
|
if (['string', 'text'].includes(propertyType)) {
|
|
75
82
|
value = nd || '';
|
|
@@ -80,6 +87,10 @@ class DataConverter {
|
|
|
80
87
|
else if ('date' === propertyType) {
|
|
81
88
|
if (nd) {
|
|
82
89
|
value = nd;
|
|
90
|
+
// const d = new Date(nd);
|
|
91
|
+
// console.log('Date.getTimezoneOffset(): ' + d.getTimezoneOffset());
|
|
92
|
+
// value = d.toISOString();
|
|
93
|
+
// console.log('date: ' + nd + ' -- ' + value);
|
|
83
94
|
}
|
|
84
95
|
else {
|
|
85
96
|
value = null;
|
|
@@ -101,11 +112,13 @@ class DataConverter {
|
|
|
101
112
|
}
|
|
102
113
|
}
|
|
103
114
|
else if ('image' === propertyType) {
|
|
115
|
+
// console.log('image-TODO');
|
|
104
116
|
}
|
|
105
117
|
else if ('formula' === propertyType) {
|
|
106
118
|
value = nd;
|
|
107
119
|
}
|
|
108
120
|
else if ('json' === propertyType) {
|
|
121
|
+
// console.log('json-TODO');
|
|
109
122
|
value = nd;
|
|
110
123
|
}
|
|
111
124
|
else if ('userList' === propertyType) {
|
|
@@ -116,6 +129,12 @@ class DataConverter {
|
|
|
116
129
|
}
|
|
117
130
|
return value;
|
|
118
131
|
}
|
|
132
|
+
/** Returns the display values for list properties (choice & multi_select)
|
|
133
|
+
*
|
|
134
|
+
* @param prop
|
|
135
|
+
* @param newData
|
|
136
|
+
* @returns
|
|
137
|
+
*/
|
|
119
138
|
getEnumerationValue(prop, nd) {
|
|
120
139
|
const propertyType = prop['propertyType'];
|
|
121
140
|
let value;
|
|
@@ -199,6 +218,14 @@ class DataConverter {
|
|
|
199
218
|
this.objRefCache[entityId] = value;
|
|
200
219
|
return value;
|
|
201
220
|
}
|
|
221
|
+
/** (Deprecated) Use TypeConversionUtils.getMapKey()
|
|
222
|
+
* Will return the class to use to get mapping.
|
|
223
|
+
* This is needed because mappings will be different for different sub types
|
|
224
|
+
* of custom-entity
|
|
225
|
+
*
|
|
226
|
+
* @param obj: Entity being checked
|
|
227
|
+
* @param mapping: The whole mapping file
|
|
228
|
+
*/
|
|
202
229
|
getMappingClass(entity, mapping) {
|
|
203
230
|
const entityTypePath = entity['typePath'];
|
|
204
231
|
const typeMapKey = mapping['typeMapKey'];
|
|
@@ -212,11 +239,22 @@ class DataConverter {
|
|
|
212
239
|
}
|
|
213
240
|
return objClass;
|
|
214
241
|
}
|
|
242
|
+
/** Sets entity values from FlexPLM data passed in
|
|
243
|
+
* Assumes the entity has a VibeIQ typeId and 'roles' value to filter if necessary.
|
|
244
|
+
* @param entity the entity to update
|
|
245
|
+
* @param data the FlexPLM data
|
|
246
|
+
* @param keysToSkip properties to skip
|
|
247
|
+
* @returns the modified entity with VibeIQ values
|
|
248
|
+
*/
|
|
215
249
|
async setEntityValues(entity, data, keysToSkip = []) {
|
|
250
|
+
// this.logger.log('setEntityValues: ' + JSON.stringify(entity));
|
|
251
|
+
// this.logger.log('data: ' + JSON.stringify(data));
|
|
216
252
|
const type = await this.typeUtils.getTypeById(entity.typeId);
|
|
217
253
|
keysToSkip = keysToSkip.concat(['updatedOn', 'updatedById', 'createdOn', 'createdById', 'modifiedAt', 'orgId', 'createdAt', 'id', 'typeId', 'typePath', 'workspaceId']);
|
|
218
254
|
let typeProps = this.typeUtils.filterTypeProperties(type, entity);
|
|
219
255
|
typeProps = typeProps.filter(prop => !keysToSkip.includes(prop['slug']));
|
|
256
|
+
//Only process properties that had a value sent; to not accidentally clear out values
|
|
257
|
+
//for properties that weren't sent.
|
|
220
258
|
const dataKeys = Object.getOwnPropertyNames(data);
|
|
221
259
|
typeProps = typeProps.filter(prop => dataKeys.includes(prop['slug']));
|
|
222
260
|
for (const prop of typeProps) {
|
|
@@ -227,9 +265,17 @@ class DataConverter {
|
|
|
227
265
|
keyName = slug + 'Id';
|
|
228
266
|
}
|
|
229
267
|
entity[keyName] = await this.getEntityValue(prop, data);
|
|
268
|
+
// console.log('entity[slug]: ' + entity[slug]);
|
|
230
269
|
}
|
|
231
270
|
return entity;
|
|
232
271
|
}
|
|
272
|
+
/** Gets the entity values from FlexPLM data
|
|
273
|
+
* Assumes there isn't a VibeIQ typeId, so uses FlexPLM data to determine type
|
|
274
|
+
* @param objectClass FlexPLM object class
|
|
275
|
+
* @param data object data
|
|
276
|
+
* @param keysToSkip type properties to not process
|
|
277
|
+
* @returns object with VibeIQ values
|
|
278
|
+
*/
|
|
233
279
|
async getEntityValues(objectClass, data, keysToSkip = []) {
|
|
234
280
|
const entityValues = {};
|
|
235
281
|
const tco = await this.typeUtils.getEntityTypeClientOptionsUsingMapping(this.transformMapFile, this.mapFileUtil, data);
|
|
@@ -254,10 +300,17 @@ class DataConverter {
|
|
|
254
300
|
}
|
|
255
301
|
return entityValues;
|
|
256
302
|
}
|
|
303
|
+
/** Gets the VibeIQ value for the property from data
|
|
304
|
+
*
|
|
305
|
+
* @param prop the VibeIQ property
|
|
306
|
+
* @param data the FlexPLM data
|
|
307
|
+
* @returns value to be set in VibeIQ
|
|
308
|
+
*/
|
|
257
309
|
async getEntityValue(prop, data) {
|
|
258
310
|
const propertyType = prop['propertyType'];
|
|
259
311
|
const slug = prop['slug'];
|
|
260
312
|
const nd = data[slug];
|
|
313
|
+
// this.logger.log('getValue: ' + propertyType + ', ' +slug + ', ' + nd);
|
|
261
314
|
let value;
|
|
262
315
|
if (['string', 'text'].includes(propertyType)) {
|
|
263
316
|
value = nd;
|
|
@@ -267,6 +320,11 @@ class DataConverter {
|
|
|
267
320
|
}
|
|
268
321
|
else if ('date' === propertyType) {
|
|
269
322
|
if (nd) {
|
|
323
|
+
// const offset = new Date(nd).getTimezoneOffset() * 60 * 1_000;
|
|
324
|
+
// this.logger.log('nd: ' + nd);
|
|
325
|
+
// this.logger.log(offset);
|
|
326
|
+
// this.logger.log('No Offset: ' + new Date(nd).toISOString());
|
|
327
|
+
// const d = new Date(nd + offset);// Take system Timezone into account.
|
|
270
328
|
const d = new Date(nd);
|
|
271
329
|
value = d.toISOString();
|
|
272
330
|
}
|
|
@@ -287,10 +345,13 @@ class DataConverter {
|
|
|
287
345
|
value = await this.setObjectReferenceValue(prop, nd);
|
|
288
346
|
}
|
|
289
347
|
else if ('image' === propertyType) {
|
|
348
|
+
// console.log('TODO-image');
|
|
290
349
|
}
|
|
291
350
|
else if ('formula' === propertyType) {
|
|
351
|
+
// console.log('TODO-formula');
|
|
292
352
|
}
|
|
293
353
|
else if ('json' === propertyType) {
|
|
354
|
+
// console.log('TODO-json');
|
|
294
355
|
}
|
|
295
356
|
else if ('userList' === propertyType) {
|
|
296
357
|
value = await this.setUserListValue(prop, nd);
|
|
@@ -298,12 +359,14 @@ class DataConverter {
|
|
|
298
359
|
else if ('size_range' === propertyType) {
|
|
299
360
|
value = nd;
|
|
300
361
|
}
|
|
362
|
+
// console.log(value);
|
|
301
363
|
return value;
|
|
302
364
|
}
|
|
303
365
|
setEnumerationKeys(prop, nd, matchByDisplay) {
|
|
304
366
|
const propertyType = prop['propertyType'];
|
|
305
367
|
let value;
|
|
306
368
|
if (['choice', 'multi_select'].includes(propertyType)) {
|
|
369
|
+
//If there are no options, use empty array to not error out and don't set anything
|
|
307
370
|
const options = prop['options'] || [];
|
|
308
371
|
if ('choice' === propertyType) {
|
|
309
372
|
if (nd) {
|
|
@@ -333,6 +396,12 @@ class DataConverter {
|
|
|
333
396
|
}
|
|
334
397
|
return value;
|
|
335
398
|
}
|
|
399
|
+
/** Compares the potential changes to the entity and returns only the actual differences.
|
|
400
|
+
*
|
|
401
|
+
* @param entity the full entity
|
|
402
|
+
* @param changes the potential changes
|
|
403
|
+
* @returns only the change values that are different from the entity's value
|
|
404
|
+
*/
|
|
336
405
|
getPersistableChanges(entity, changes) {
|
|
337
406
|
const entityCompareValues = {};
|
|
338
407
|
for (const key of (Object.getOwnPropertyNames(changes))) {
|
|
@@ -347,6 +416,12 @@ class DataConverter {
|
|
|
347
416
|
}
|
|
348
417
|
return diffValues;
|
|
349
418
|
}
|
|
419
|
+
/** Sets object reference value from FlexPLM data passed in
|
|
420
|
+
*
|
|
421
|
+
* @param prop the VibeIQ property
|
|
422
|
+
* @param nd the VibeIQ data
|
|
423
|
+
* @returns the object reference id from VibeIQ
|
|
424
|
+
*/
|
|
350
425
|
async setObjectReferenceValue(prop, nd) {
|
|
351
426
|
if (!nd) {
|
|
352
427
|
return "";
|
|
@@ -439,6 +514,13 @@ class DataConverter {
|
|
|
439
514
|
}
|
|
440
515
|
return results[0];
|
|
441
516
|
}
|
|
517
|
+
/**
|
|
518
|
+
* Retrieves all object references of a specified entity type based on the provided criteria.
|
|
519
|
+
* This function handles pagination and asynchronously fetches object references until there are no more pages.
|
|
520
|
+
* @param {string} entityType - The type of entity for which object references are to be retrieved.
|
|
521
|
+
* @param {object} rootTypeCriteria - The criteria used to filter object references.
|
|
522
|
+
* @returns {Promise<Array>} A Promise that resolves to an array containing all object references.
|
|
523
|
+
*/
|
|
442
524
|
async getAllObjectReferences(entityType, rootTypeCriteria, postProcessCriteria = null) {
|
|
443
525
|
const entities = new sdk_1.Entities();
|
|
444
526
|
let loads = [];
|
|
@@ -494,6 +576,14 @@ class DataConverter {
|
|
|
494
576
|
}
|
|
495
577
|
return loads;
|
|
496
578
|
}
|
|
579
|
+
/**
|
|
580
|
+
* Checks if all keys and values of a given object are present in an array of objects.
|
|
581
|
+
* @param {Object} criteria - The object whose keys and values are to be checked in the array of objects.
|
|
582
|
+
* @param {Array<Object>} arrayOfObjects - The array of objects to be searched for matching keys and values.
|
|
583
|
+
* @param {string} entityTypePath - The type / subtype for the property; objects must be this type or a sub type of it.
|
|
584
|
+
* @returns {(Object|boolean)} Returns the array of objects that matches all keys and values of the provided object.
|
|
585
|
+
* If no match is found, returns empty array.
|
|
586
|
+
*/
|
|
497
587
|
checkKeysAndValues(criteria, arrayOfObjects, entityTypePath) {
|
|
498
588
|
let arrOfMatchObjects = [];
|
|
499
589
|
for (let i = 0; i < arrayOfObjects.length; i++) {
|
|
@@ -517,6 +607,11 @@ class DataConverter {
|
|
|
517
607
|
}
|
|
518
608
|
return arrOfMatchObjects;
|
|
519
609
|
}
|
|
610
|
+
/** Filters out archived and trashed entities from the provided array of entities.
|
|
611
|
+
*
|
|
612
|
+
* @param entities
|
|
613
|
+
* @returns
|
|
614
|
+
*/
|
|
520
615
|
filterOutArchivedAndTrashedEntities(entities) {
|
|
521
616
|
if (!entities || !Array.isArray(entities) || entities.length === 0) {
|
|
522
617
|
return [];
|
|
@@ -527,6 +622,12 @@ class DataConverter {
|
|
|
527
622
|
return !isArchived && !isTrashed;
|
|
528
623
|
});
|
|
529
624
|
}
|
|
625
|
+
/** Sets userListId value from FlexPLM data passed in
|
|
626
|
+
*
|
|
627
|
+
* @param prop the VibeIQ property
|
|
628
|
+
* @param nd the VibeIQ data
|
|
629
|
+
* @returns the modified entity with FlexPLM values
|
|
630
|
+
*/
|
|
530
631
|
async setUserListValue(prop, nd) {
|
|
531
632
|
if (!nd?.email) {
|
|
532
633
|
return "";
|
|
@@ -547,6 +648,13 @@ class DataConverter {
|
|
|
547
648
|
}
|
|
548
649
|
return userId;
|
|
549
650
|
}
|
|
651
|
+
/** Makes batch calls of 1000 of user-org entities until
|
|
652
|
+
* it find one with userEmail of passed in nd.email.
|
|
653
|
+
* Maxes out after querying for 15,000 user-org entities
|
|
654
|
+
*
|
|
655
|
+
* @param nd
|
|
656
|
+
* @returns
|
|
657
|
+
*/
|
|
550
658
|
async getUserByEmail(nd) {
|
|
551
659
|
let userOrg = undefined;
|
|
552
660
|
let count = 0;
|
|
@@ -563,6 +671,11 @@ class DataConverter {
|
|
|
563
671
|
} while (!userOrg && size == getOptionsCriteria.take && count < 15);
|
|
564
672
|
return userOrg?.user;
|
|
565
673
|
}
|
|
674
|
+
/** Shows warning if user email address not present in group associated to property
|
|
675
|
+
*
|
|
676
|
+
* @param prop the VibeIQ property
|
|
677
|
+
* @param userEmail user email address
|
|
678
|
+
*/
|
|
566
679
|
async processGroupMemberCheck(prop, userEmail) {
|
|
567
680
|
let arrUserList = [];
|
|
568
681
|
if (this.userRefCache[prop.typePropertyUserListId]) {
|
|
@@ -585,6 +698,12 @@ class DataConverter {
|
|
|
585
698
|
}
|
|
586
699
|
}
|
|
587
700
|
}
|
|
701
|
+
/** Gets the VibeIQ value for the userList property from data
|
|
702
|
+
*
|
|
703
|
+
* @param prop the VibeIQ property
|
|
704
|
+
* @param newData the FlexPLM data
|
|
705
|
+
* @returns value to be set in VibeIQ
|
|
706
|
+
*/
|
|
588
707
|
async getUserListValue(prop, newData) {
|
|
589
708
|
const slug = prop['slug'];
|
|
590
709
|
if (app_framework_1.Logger.isDebugOn()) {
|
|
@@ -613,6 +732,13 @@ class DataConverter {
|
|
|
613
732
|
}
|
|
614
733
|
return value;
|
|
615
734
|
}
|
|
735
|
+
/** Makes batch calls of 1000 of user-org entities until
|
|
736
|
+
* it find one with user.id of passed in userId.
|
|
737
|
+
* Maxes out after querying for 15,000 user-org entities
|
|
738
|
+
*
|
|
739
|
+
* @param userId
|
|
740
|
+
* @returns
|
|
741
|
+
*/
|
|
616
742
|
async getUserById(userId) {
|
|
617
743
|
let userOrg = undefined;
|
|
618
744
|
let count = 0;
|
|
@@ -1037,6 +1037,7 @@ describe('checkKeysAndValues', () => {
|
|
|
1037
1037
|
{ name: 'Group 4', typePath: 'custom-entity:grouping:sub' },
|
|
1038
1038
|
{ name: 'Group 5', typePath: 'custom-entity:grouping:sub' }
|
|
1039
1039
|
];
|
|
1040
|
+
//item:product:newBalance:accessories, item:product:newBalance:apparel
|
|
1040
1041
|
it('Group 1', () => {
|
|
1041
1042
|
const criteria = {
|
|
1042
1043
|
name: 'Group 1'
|
|
@@ -1258,6 +1259,7 @@ describe('getUserListValue', () => {
|
|
|
1258
1259
|
];
|
|
1259
1260
|
const mapFileUtil = new transform_data_1.MapFileUtil(new sdk_1.Entities());
|
|
1260
1261
|
const dc = new data_converter_1.DataConverter(config, mapFileUtil);
|
|
1262
|
+
//getUserById
|
|
1261
1263
|
let spyGetUserById = jest.spyOn(dc, 'getUserById')
|
|
1262
1264
|
.mockImplementation(async (nd) => {
|
|
1263
1265
|
return userEmailMapping.find((user) => user.id === nd);
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { AppActionCallBack } from "@contrail/app-framework";
|
|
2
2
|
export declare class ErrorResponseObject {
|
|
3
|
+
/** Returns a response, checking for multiple possible error details
|
|
4
|
+
*
|
|
5
|
+
* @param e
|
|
6
|
+
* @returns
|
|
7
|
+
*/
|
|
3
8
|
static getResponse(e: any): AppActionCallBack;
|
|
4
9
|
}
|
|
@@ -3,6 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ErrorResponseObject = void 0;
|
|
4
4
|
const app_framework_1 = require("@contrail/app-framework");
|
|
5
5
|
class ErrorResponseObject {
|
|
6
|
+
/** Returns a response, checking for multiple possible error details
|
|
7
|
+
*
|
|
8
|
+
* @param e
|
|
9
|
+
* @returns
|
|
10
|
+
*/
|
|
6
11
|
static getResponse(e) {
|
|
7
12
|
if (!e) {
|
|
8
13
|
const response = {
|
|
@@ -20,6 +25,7 @@ class ErrorResponseObject {
|
|
|
20
25
|
}
|
|
21
26
|
};
|
|
22
27
|
const output = response.output;
|
|
28
|
+
//Errors when persisting in VibeIQ
|
|
23
29
|
if (e.details)
|
|
24
30
|
output.errorDetails = e.details;
|
|
25
31
|
if (e.code)
|
|
@@ -30,6 +36,7 @@ class ErrorResponseObject {
|
|
|
30
36
|
output.type = e.type;
|
|
31
37
|
if (e.name)
|
|
32
38
|
output.errorName = e.name;
|
|
39
|
+
//Has original cause
|
|
33
40
|
if (e.cause) {
|
|
34
41
|
output.cause = {};
|
|
35
42
|
const cause = output.cause;
|
|
@@ -16,6 +16,7 @@ var EventShortMessageStatus;
|
|
|
16
16
|
EventShortMessageStatus["PRIMARY_CONTENT_UPDATED"] = "Primary_Content_Updated";
|
|
17
17
|
EventShortMessageStatus["TOO_MANY_ENTITIES_FOUND"] = "Too_Many_Entities_Found";
|
|
18
18
|
EventShortMessageStatus["UPDATED"] = "Updated";
|
|
19
|
+
//Publish
|
|
19
20
|
EventShortMessageStatus["NOT_PUBLISHABLE"] = "Not_Publishable";
|
|
20
21
|
EventShortMessageStatus["NO_FEDERATION_INFO"] = "No_Federation_Information";
|
|
21
22
|
EventShortMessageStatus["NO_EVENTS_TO_SEND"] = "No_Events_to_Send";
|
package/lib/util/federation.js
CHANGED
|
@@ -43,9 +43,11 @@ class Federation {
|
|
|
43
43
|
mappedReference: itemResults[i].federatedId,
|
|
44
44
|
federationSchema: FED_CONFIG.federationSchema
|
|
45
45
|
};
|
|
46
|
+
// console.log('createFederatedRecord: ' + JSON.stringify(payload));
|
|
46
47
|
try {
|
|
47
48
|
const results = await new sdk_1.Entities().create({ entityName: 'federation', object: payload });
|
|
48
49
|
return results;
|
|
50
|
+
// console.log(JSON.stringify(results));
|
|
49
51
|
}
|
|
50
52
|
catch (error) {
|
|
51
53
|
console.log('createFederatedRecord-error: ', error);
|
|
@@ -79,13 +81,16 @@ class Federation {
|
|
|
79
81
|
return { entityType, entityId };
|
|
80
82
|
}
|
|
81
83
|
async getEntityFromMappedRefId(mappedRefId) {
|
|
84
|
+
// console.log('!---getEntityFromMappedRefId: ' + mappedRefId);
|
|
82
85
|
const fedRecord = await this.getFederationRecordFromMappedRefId(mappedRefId);
|
|
83
86
|
console.log('fedRecord: ' + JSON.stringify(fedRecord));
|
|
84
87
|
if (!fedRecord) {
|
|
88
|
+
//Not creating from FlexPLM at this time.
|
|
85
89
|
console.log('Federation Record doesnt exist. Cant get entity!');
|
|
86
90
|
return;
|
|
87
91
|
}
|
|
88
92
|
const { entityType, entityId } = Federation.getEntityId(fedRecord);
|
|
93
|
+
// console.log(entityType + ':' + entityId);
|
|
89
94
|
const criteria = {
|
|
90
95
|
id: entityId
|
|
91
96
|
};
|
|
@@ -94,6 +99,7 @@ class Federation {
|
|
|
94
99
|
criteria
|
|
95
100
|
});
|
|
96
101
|
const entity = (entities && entities[0]) ? entities[0] : undefined;
|
|
102
|
+
// console.log(' entities: ' +JSON.stringify(entities));
|
|
97
103
|
return entity;
|
|
98
104
|
}
|
|
99
105
|
async getFederationRecordsFromIds(ids) {
|
|
@@ -104,6 +110,7 @@ class Federation {
|
|
|
104
110
|
appIdentifier: FED_CONFIG.appIdentifier,
|
|
105
111
|
federationSchema: FED_CONFIG.federationSchema
|
|
106
112
|
};
|
|
113
|
+
// this.logger.log('getFederatedMappedRefId: ' + JSON.stringify(criteria));
|
|
107
114
|
const recs = await new sdk_1.Entities().get({
|
|
108
115
|
entityName: 'federation',
|
|
109
116
|
criteria
|
|
@@ -126,6 +133,7 @@ class Federation {
|
|
|
126
133
|
appIdentifier: FED_CONFIG.appIdentifier,
|
|
127
134
|
federationSchema: FED_CONFIG.federationSchema
|
|
128
135
|
};
|
|
136
|
+
// this.logger.log('getFederatedMappedRefId: ' + JSON.stringify(criteria));
|
|
129
137
|
const records = await entities.get({
|
|
130
138
|
entityName: 'federation',
|
|
131
139
|
criteria
|
|
@@ -14,6 +14,13 @@ export declare class FlexPLMConnect {
|
|
|
14
14
|
protected processRequest(payload: any): Promise<FlexPLMResponseData>;
|
|
15
15
|
sendToFlexPLM(payload: PayloadType): Promise<FlexPLMResponseData>;
|
|
16
16
|
sendMultipleToFlexPLM(payload: PayloadType[]): Promise<FlexPLMResponseData>;
|
|
17
|
+
/** Runs a GET request to FlexPLM.
|
|
18
|
+
* @param params - Optional configuration for the request.
|
|
19
|
+
* @param params.urlPath - Custom URL path to use instead of the default `/servlet/rest` + endpoint.
|
|
20
|
+
* @param params.includeUrlContext - Whether to include the urlContext in the URL. Defaults to `true`.
|
|
21
|
+
* @param params.returnFullResponse - If `true`, returns the raw `Response` object instead of parsed JSON. Defaults to `false`.
|
|
22
|
+
* @returns The parsed JSON response body, or the raw `Response` object if `returnFullResponse` is `true`.
|
|
23
|
+
*/
|
|
17
24
|
getRequest(params?: {
|
|
18
25
|
urlPath?: string;
|
|
19
26
|
includeUrlContext?: boolean;
|
|
@@ -18,6 +18,9 @@ class FlexPLMConnect {
|
|
|
18
18
|
this.staticHeaders = this.config?.flexplmConnect?.staticHeaders;
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
22
|
+
///////// Custom getRequestOptions: start
|
|
23
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
21
24
|
getRequestOptions(method) {
|
|
22
25
|
const csrfOptions = {
|
|
23
26
|
method,
|
|
@@ -37,6 +40,9 @@ class FlexPLMConnect {
|
|
|
37
40
|
}
|
|
38
41
|
return csrfOptions;
|
|
39
42
|
}
|
|
43
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
44
|
+
///////// Custom getRequestOptions: end
|
|
45
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
40
46
|
async getCSRF() {
|
|
41
47
|
const urlContext = this.config.urlContext;
|
|
42
48
|
const csrfEndpoint = this.config.csrfEndpoint;
|
|
@@ -130,6 +136,7 @@ class FlexPLMConnect {
|
|
|
130
136
|
}
|
|
131
137
|
}
|
|
132
138
|
console.log('eventResponse.status: ' + status);
|
|
139
|
+
// console.log('eventBody: ', JSON.stringify(data));
|
|
133
140
|
return res;
|
|
134
141
|
}
|
|
135
142
|
catch (e) {
|
|
@@ -145,6 +152,13 @@ class FlexPLMConnect {
|
|
|
145
152
|
async sendMultipleToFlexPLM(payload) {
|
|
146
153
|
return await this.processRequest(payload);
|
|
147
154
|
}
|
|
155
|
+
/** Runs a GET request to FlexPLM.
|
|
156
|
+
* @param params - Optional configuration for the request.
|
|
157
|
+
* @param params.urlPath - Custom URL path to use instead of the default `/servlet/rest` + endpoint.
|
|
158
|
+
* @param params.includeUrlContext - Whether to include the urlContext in the URL. Defaults to `true`.
|
|
159
|
+
* @param params.returnFullResponse - If `true`, returns the raw `Response` object instead of parsed JSON. Defaults to `false`.
|
|
160
|
+
* @returns The parsed JSON response body, or the raw `Response` object if `returnFullResponse` is `true`.
|
|
161
|
+
*/
|
|
148
162
|
async getRequest(params) {
|
|
149
163
|
const { urlPath, includeUrlContext = true, returnFullResponse = false } = params || {};
|
|
150
164
|
const urlContext = includeUrlContext ? this.config.urlContext : '';
|
|
@@ -5,6 +5,7 @@ const app_framework_1 = require("@contrail/app-framework");
|
|
|
5
5
|
async function setLoggerConfig(appConfig) {
|
|
6
6
|
let logLevel = app_framework_1.LogLevel.INFO;
|
|
7
7
|
if (!appConfig.logLevel) {
|
|
8
|
+
//pass
|
|
8
9
|
}
|
|
9
10
|
else if (appConfig.logLevel === 'error') {
|
|
10
11
|
logLevel = app_framework_1.LogLevel.ERROR;
|
|
@@ -31,12 +31,26 @@ exports.mapping = {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
+
// flex2vibe: {
|
|
35
|
+
// LCSRevisableEntity: {
|
|
36
|
+
// getMapKey: (object) =>{ return object;}
|
|
37
|
+
// },
|
|
38
|
+
// LCSLast: {
|
|
39
|
+
// getMapKey: (object) => {return object;}
|
|
40
|
+
// },
|
|
41
|
+
// LCSMaterial: {
|
|
42
|
+
// getMapKey: (object) =>{ return object;}
|
|
43
|
+
// },
|
|
44
|
+
// LCSBusinessObject: {
|
|
45
|
+
// getMapKey: (object) => {return object;}
|
|
46
|
+
// }
|
|
47
|
+
// },
|
|
34
48
|
},
|
|
35
49
|
LCSProduct: {
|
|
36
50
|
vibeOwningKeys: ['itemNumber', 'lifecycleStage'],
|
|
37
51
|
vibe2flex: {
|
|
38
52
|
getClass: () => 'LCSProduct',
|
|
39
|
-
getSoftType: (entity) => {
|
|
53
|
+
getSoftType: (entity /*, dependencies*/) => {
|
|
40
54
|
const prodType = entity['prodType'];
|
|
41
55
|
let val = '';
|
|
42
56
|
switch (prodType) {
|
|
@@ -61,7 +75,7 @@ exports.mapping = {
|
|
|
61
75
|
vibeIQIdentifier: 'itemNumber'
|
|
62
76
|
},
|
|
63
77
|
valueTransform: {
|
|
64
|
-
transformEx: (row) => {
|
|
78
|
+
transformEx: (row /*, dependencies*/) => {
|
|
65
79
|
return row['otherProp'] + 'xxx';
|
|
66
80
|
}
|
|
67
81
|
}
|
|
@@ -79,7 +93,7 @@ exports.mapping = {
|
|
|
79
93
|
vibeOwningKeys: ['itemNumber', 'lifecycleStage'],
|
|
80
94
|
vibe2flex: {
|
|
81
95
|
getClass: () => 'LCSSKU',
|
|
82
|
-
getSoftType: (entity) => {
|
|
96
|
+
getSoftType: (entity /*, dependencies*/) => {
|
|
83
97
|
const prodType = entity['prodType'];
|
|
84
98
|
let val = '';
|
|
85
99
|
switch (prodType) {
|
package/lib/util/map-utils.d.ts
CHANGED
|
@@ -1,6 +1,33 @@
|
|
|
1
1
|
import { MapFileUtil } from '@contrail/transform-data';
|
|
2
2
|
export declare class MapUtil {
|
|
3
|
+
/** Transforms the data, assumes mapSectionKey has been correctly determined.
|
|
4
|
+
*
|
|
5
|
+
* @param transformMapFile id of map file
|
|
6
|
+
* @param mapFileUtil
|
|
7
|
+
* @param data
|
|
8
|
+
* @param mapSectionKey key for section of map file
|
|
9
|
+
* @param direction vibe2flex or flex2vibe
|
|
10
|
+
* @param transformTaskOrderKey key for the list of tasks to be processed. default is 'transformOrder'
|
|
11
|
+
* @returns The converted data
|
|
12
|
+
*/
|
|
3
13
|
static applyTransformMap(transformMapFile: any, mapFileUtil: any, data: any, mapSectionKey: string, direction: string, transformTaskOrderKey?: string): Promise<any>;
|
|
14
|
+
/** Returns the mapKey based on the 'typeConversion' section of the map file.
|
|
15
|
+
* If the map file doesn't have a section for the type in question, 'undefined' is returned.
|
|
16
|
+
*
|
|
17
|
+
* @param fileId
|
|
18
|
+
* @param mapFileUtil
|
|
19
|
+
* @param data The full object
|
|
20
|
+
* @param type The entity or object class of the object. The functions are keyed based on this.
|
|
21
|
+
* @param direction
|
|
22
|
+
* @returns
|
|
23
|
+
*/
|
|
4
24
|
static getMapKey(transformMapFile: any, mapFileUtil: MapFileUtil, data: any, type: string, direction: string): Promise<string>;
|
|
25
|
+
/** Returns the full map section with both directions; identifier and informational properties; etc.
|
|
26
|
+
*
|
|
27
|
+
* @param transformMapFile id if map file
|
|
28
|
+
* @param mapFileUtil
|
|
29
|
+
* @param mapSectionKey key of the map section
|
|
30
|
+
* @returns
|
|
31
|
+
*/
|
|
5
32
|
static getFullMapSection(transformMapFile: string, mapFileUtil: MapFileUtil, mapSectionKey: string): Promise<any>;
|
|
6
33
|
}
|
package/lib/util/map-utils.js
CHANGED
|
@@ -2,12 +2,39 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MapUtil = void 0;
|
|
4
4
|
class MapUtil {
|
|
5
|
+
/** Transforms the data, assumes mapSectionKey has been correctly determined.
|
|
6
|
+
*
|
|
7
|
+
* @param transformMapFile id of map file
|
|
8
|
+
* @param mapFileUtil
|
|
9
|
+
* @param data
|
|
10
|
+
* @param mapSectionKey key for section of map file
|
|
11
|
+
* @param direction vibe2flex or flex2vibe
|
|
12
|
+
* @param transformTaskOrderKey key for the list of tasks to be processed. default is 'transformOrder'
|
|
13
|
+
* @returns The converted data
|
|
14
|
+
*/
|
|
5
15
|
static async applyTransformMap(transformMapFile, mapFileUtil, data, mapSectionKey, direction, transformTaskOrderKey = 'transformOrder') {
|
|
6
16
|
return await mapFileUtil.applyTransformMap(transformMapFile, data, mapSectionKey, direction, transformTaskOrderKey);
|
|
7
17
|
}
|
|
18
|
+
/** Returns the mapKey based on the 'typeConversion' section of the map file.
|
|
19
|
+
* If the map file doesn't have a section for the type in question, 'undefined' is returned.
|
|
20
|
+
*
|
|
21
|
+
* @param fileId
|
|
22
|
+
* @param mapFileUtil
|
|
23
|
+
* @param data The full object
|
|
24
|
+
* @param type The entity or object class of the object. The functions are keyed based on this.
|
|
25
|
+
* @param direction
|
|
26
|
+
* @returns
|
|
27
|
+
*/
|
|
8
28
|
static async getMapKey(transformMapFile, mapFileUtil, data, type, direction) {
|
|
9
29
|
return await mapFileUtil.getMapKey(transformMapFile, data, type, direction);
|
|
10
30
|
}
|
|
31
|
+
/** Returns the full map section with both directions; identifier and informational properties; etc.
|
|
32
|
+
*
|
|
33
|
+
* @param transformMapFile id if map file
|
|
34
|
+
* @param mapFileUtil
|
|
35
|
+
* @param mapSectionKey key of the map section
|
|
36
|
+
* @returns
|
|
37
|
+
*/
|
|
11
38
|
static async getFullMapSection(transformMapFile, mapFileUtil, mapSectionKey) {
|
|
12
39
|
return await mapFileUtil.getFullMapSection(transformMapFile, mapSectionKey);
|
|
13
40
|
}
|
|
@@ -6,6 +6,7 @@ interface ContentCustomSize {
|
|
|
6
6
|
}
|
|
7
7
|
export declare class ThumbnailUtil {
|
|
8
8
|
private config;
|
|
9
|
+
/** The max_thumbnail_size is for limiting the size of the thumbnail being sent to FlexPLM. It is used when checking the size of the auto generated thumbnails (smallViewable, tinyViewable, etc.). */
|
|
9
10
|
private max_thumbnail_size;
|
|
10
11
|
private entities;
|
|
11
12
|
static NEW_THUMBNAIL_ID: string;
|
|
@@ -16,11 +17,31 @@ export declare class ThumbnailUtil {
|
|
|
16
17
|
}[];
|
|
17
18
|
constructor(config: FCConfig);
|
|
18
19
|
setOutboundThumbnail(data: any, event: any): Promise<any>;
|
|
20
|
+
/** Determines if a new image has been generated. If any viewable is new, there might be a better
|
|
21
|
+
* sized image. So send the fileId as new.
|
|
22
|
+
*/
|
|
19
23
|
isThumbnailNew(event: any, customSizes: any[]): boolean;
|
|
20
24
|
getFileId(primaryViewableId: string): Promise<string | undefined>;
|
|
21
25
|
getCustomSizes(): Promise<ContentCustomSize[]>;
|
|
22
26
|
getContentEntity(primaryViewableId: any, sizes: ContentCustomSize[]): Promise<any>;
|
|
27
|
+
/** This outputs the content entity, without the inflated file entities.
|
|
28
|
+
* To help debugging issues with sending the thumbnail info.
|
|
29
|
+
* The inflated entities are removed, because are large and cause
|
|
30
|
+
* problems with log file size limits.
|
|
31
|
+
*
|
|
32
|
+
* @param content: the content with inflated objects
|
|
33
|
+
* @param relations: string[] of the slugs for inflated objects
|
|
34
|
+
*/
|
|
23
35
|
logContentResults(content: any, relations: string[]): void;
|
|
36
|
+
/** Syncs the thumbnail from FlexPLM to VibeIQ. Handles creating, replacing, or removing
|
|
37
|
+
* the primary viewable content and persists the updates directly to the entity.
|
|
38
|
+
*
|
|
39
|
+
* @param entityId - The ID of the entity to update with thumbnail properties.
|
|
40
|
+
* @param primaryViewableId - The existing primary viewable content ID, if any.
|
|
41
|
+
* @param event - The inbound event containing thumbnail data (NEW_THUMBNAIL_ID / EXISTING_THUMBNAIL_ID).
|
|
42
|
+
* @param entityName - The entity type name (e.g. 'item', 'color') used for API calls.
|
|
43
|
+
* @returns The updated entity, or undefined if no thumbnail changes were needed.
|
|
44
|
+
*/
|
|
24
45
|
syncThumbnailToVibeIQ({ entityId, primaryViewableId, event, entityName }: {
|
|
25
46
|
entityId: string;
|
|
26
47
|
primaryViewableId?: string;
|