@contrail/flexplm 1.0.11 → 1.0.13
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/flexplm-request.d.ts +3 -0
- package/lib/flexplm-request.js +34 -0
- package/lib/flexplm-utils.d.ts +5 -0
- package/lib/flexplm-utils.js +33 -0
- package/lib/index.d.ts +12 -0
- package/lib/index.js +28 -0
- package/lib/process-entity/process-entity.d.ts +26 -0
- package/lib/process-entity/process-entity.js +141 -0
- package/lib/util/config-defaults.d.ts +6 -0
- package/lib/util/config-defaults.js +71 -0
- package/lib/util/data-converter.d.ts +22 -0
- package/lib/util/data-converter.js +318 -0
- package/lib/util/federation.d.ts +15 -0
- package/lib/util/federation.js +149 -0
- package/lib/util/flexplm-connect.d.ts +16 -0
- package/lib/util/flexplm-connect.js +130 -0
- package/lib/util/interfaces.d.ts +91 -0
- package/lib/util/interfaces.js +2 -0
- package/lib/util/logger-config.d.ts +1 -0
- package/lib/util/logger-config.js +26 -0
- package/lib/util/map-utils.d.ts +3 -0
- package/lib/util/map-utils.js +20 -0
- package/lib/util/mockData.d.ts +39 -0
- package/lib/util/mockData.js +100 -0
- package/lib/util/thumbnail-util.d.ts +15 -0
- package/lib/util/thumbnail-util.js +112 -0
- package/lib/util/type-utils.d.ts +12 -0
- package/lib/util/type-utils.js +101 -0
- package/package.json +1 -1
- package/lib/package.json +0 -46
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DataConverter = void 0;
|
|
4
|
+
const sdk_1 = require("@contrail/sdk");
|
|
5
|
+
const type_utils_1 = require("./type-utils");
|
|
6
|
+
const transform_data_1 = require("@contrail/transform-data");
|
|
7
|
+
const app_framework_1 = require("@contrail/app-framework");
|
|
8
|
+
const util_1 = require("@contrail/util");
|
|
9
|
+
class DataConverter {
|
|
10
|
+
constructor(config, mapFileUtil) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
this.mapFileUtil = mapFileUtil;
|
|
13
|
+
this.useDisplayForEnumerationMatching = false;
|
|
14
|
+
this.objRefCache = {};
|
|
15
|
+
this.typeUtils = new type_utils_1.TypeUtils();
|
|
16
|
+
this.transformMapFile = this.config['transformMapFile'];
|
|
17
|
+
this.useDisplayForEnumerationMatching = this.config['dataConverter']
|
|
18
|
+
&& this.config['dataConverter']['useDisplayForEnumerationMatching'];
|
|
19
|
+
}
|
|
20
|
+
async getFlexPLMObjectDataFromEvent(event, dataToSkip) {
|
|
21
|
+
return this.getFlexPLMObjectData(event.newData, dataToSkip, true);
|
|
22
|
+
}
|
|
23
|
+
async getFlexPLMObjectData(newData, dataToSkip, expandObjRef) {
|
|
24
|
+
if (app_framework_1.Logger.isDebugOn()) {
|
|
25
|
+
console.debug('newData: ' + JSON.stringify(newData));
|
|
26
|
+
}
|
|
27
|
+
dataToSkip = dataToSkip.concat(['updatedOn', 'updatedById', 'createdOn', 'createdById', 'modifiedAt', 'orgId', 'createdAt', 'id', 'typeId', 'workspaceId']);
|
|
28
|
+
const data = {};
|
|
29
|
+
const typeId = newData?.typeId;
|
|
30
|
+
if (!typeId) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
data['typePath'] = newData['typePath'];
|
|
34
|
+
const type = await this.typeUtils.getTypeById(typeId);
|
|
35
|
+
const typeProps = this.typeUtils.filterTypeProperties(type, newData);
|
|
36
|
+
for (const prop of typeProps) {
|
|
37
|
+
const slug = prop['slug'];
|
|
38
|
+
if (dataToSkip.includes(slug)) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
data[slug] = await this.getFlexPLMValue(prop, newData, expandObjRef);
|
|
42
|
+
}
|
|
43
|
+
if (app_framework_1.Logger.isDebugOn()) {
|
|
44
|
+
console.debug('getFlexPLMObjectData-data: ' + JSON.stringify(data));
|
|
45
|
+
}
|
|
46
|
+
return data;
|
|
47
|
+
}
|
|
48
|
+
async getFlexPLMValue(prop, newData, expandObjRef) {
|
|
49
|
+
const propertyType = prop['propertyType'];
|
|
50
|
+
const slug = prop['slug'];
|
|
51
|
+
const nd = newData[slug];
|
|
52
|
+
let value;
|
|
53
|
+
if (['string', 'text'].includes(propertyType)) {
|
|
54
|
+
value = nd || '';
|
|
55
|
+
}
|
|
56
|
+
else if (['number', 'currency', 'percent', 'sequence'].includes(propertyType)) {
|
|
57
|
+
value = nd || 0;
|
|
58
|
+
}
|
|
59
|
+
else if ('date' === propertyType) {
|
|
60
|
+
if (nd) {
|
|
61
|
+
value = nd;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
value = null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else if ('boolean' === propertyType) {
|
|
68
|
+
value = (nd) ? true : false;
|
|
69
|
+
}
|
|
70
|
+
else if ('choice' === propertyType) {
|
|
71
|
+
value = this.getEnumerationValue(prop, nd);
|
|
72
|
+
}
|
|
73
|
+
else if ('multi_select' === propertyType) {
|
|
74
|
+
value = this.getEnumerationValue(prop, nd);
|
|
75
|
+
}
|
|
76
|
+
else if ('object_reference' === propertyType) {
|
|
77
|
+
value = await this.getObjectReferenceValue(prop, newData, expandObjRef);
|
|
78
|
+
if (app_framework_1.Logger.isDebugOn()) {
|
|
79
|
+
console.debug('object_reference: ' + JSON.stringify(value));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else if ('image' === propertyType) {
|
|
83
|
+
}
|
|
84
|
+
else if ('formula' === propertyType) {
|
|
85
|
+
value = nd;
|
|
86
|
+
}
|
|
87
|
+
else if ('json' === propertyType) {
|
|
88
|
+
value = nd;
|
|
89
|
+
}
|
|
90
|
+
return value;
|
|
91
|
+
}
|
|
92
|
+
getEnumerationValue(prop, nd) {
|
|
93
|
+
const propertyType = prop['propertyType'];
|
|
94
|
+
let value;
|
|
95
|
+
if (['choice', 'multi_select'].includes(propertyType)) {
|
|
96
|
+
const options = prop['options'];
|
|
97
|
+
if ('choice' === propertyType) {
|
|
98
|
+
if (nd) {
|
|
99
|
+
const option = options.find(option => option.value == nd);
|
|
100
|
+
if (option) {
|
|
101
|
+
value = Object.assign({}, option);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
value = {};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else if ('multi_select' === propertyType) {
|
|
109
|
+
value = [];
|
|
110
|
+
if (nd instanceof Array) {
|
|
111
|
+
nd.forEach(key => {
|
|
112
|
+
const optionObject = options.find(option => option.value == key);
|
|
113
|
+
if (optionObject) {
|
|
114
|
+
const option = Object.assign({}, optionObject);
|
|
115
|
+
value.push(option);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
else if (typeof nd === 'string' && '' !== nd) {
|
|
120
|
+
const optionObject = options.find(option => option.value == nd);
|
|
121
|
+
if (optionObject) {
|
|
122
|
+
const option = Object.assign({}, optionObject);
|
|
123
|
+
value.push(option);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return value;
|
|
129
|
+
}
|
|
130
|
+
async getObjectReferenceValue(prop, newData, expandObjRef = false) {
|
|
131
|
+
const slug = prop['slug'];
|
|
132
|
+
console.debug('getObjectReferenceValue-prop: ' + slug);
|
|
133
|
+
let value = newData[slug];
|
|
134
|
+
const entityType = prop['referencedTypeRootSlug'];
|
|
135
|
+
const entityId = newData[slug + 'Id'];
|
|
136
|
+
if (!value && expandObjRef) {
|
|
137
|
+
if (entityId) {
|
|
138
|
+
if (this.objRefCache[entityId]) {
|
|
139
|
+
console.log('cache hit: ' + entityId);
|
|
140
|
+
return this.objRefCache[entityId];
|
|
141
|
+
}
|
|
142
|
+
const criteria = {
|
|
143
|
+
id: entityId
|
|
144
|
+
};
|
|
145
|
+
const entities = await new sdk_1.Entities().get({
|
|
146
|
+
entityName: entityType,
|
|
147
|
+
criteria
|
|
148
|
+
});
|
|
149
|
+
value = (entities && entities[0]) ? entities[0] : undefined;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (value) {
|
|
153
|
+
const unprocessedValue = value;
|
|
154
|
+
const objectClass = this.typeUtils.getEventObjectClass(entityType, newData);
|
|
155
|
+
value = await this.getFlexPLMObjectData(value, [], false);
|
|
156
|
+
value['entityReference'] = entityType + ':' + entityId;
|
|
157
|
+
value['objectClass'] = objectClass;
|
|
158
|
+
value['typePath'] = unprocessedValue['typePath'];
|
|
159
|
+
if (this.transformMapFile) {
|
|
160
|
+
const wholeMap = await this.mapFileUtil.getMapFile(this.transformMapFile);
|
|
161
|
+
const objClass = this.getMappingClass(unprocessedValue, wholeMap);
|
|
162
|
+
const mapping = await this.mapFileUtil.getMappingSection(this.transformMapFile, objClass, 'vibe2flex');
|
|
163
|
+
if (mapping) {
|
|
164
|
+
const tasks = transform_data_1.MapFileUtil.getTransformTasks(mapping);
|
|
165
|
+
if (tasks.length > 0) {
|
|
166
|
+
const convertedArray = transform_data_1.TransformProcessor.transformData([value], tasks);
|
|
167
|
+
value = convertedArray[0];
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
value = {};
|
|
174
|
+
}
|
|
175
|
+
this.objRefCache[entityId] = value;
|
|
176
|
+
return value;
|
|
177
|
+
}
|
|
178
|
+
getMappingClass(entity, mapping) {
|
|
179
|
+
const entityTypePath = entity['typePath'];
|
|
180
|
+
const typeMapKey = mapping['typeMapKey'];
|
|
181
|
+
let objClass = typeMapKey[entityTypePath];
|
|
182
|
+
const entityType = entity['entityType'];
|
|
183
|
+
if (!objClass) {
|
|
184
|
+
objClass = this.typeUtils.getEventObjectClass(entityType, entity);
|
|
185
|
+
}
|
|
186
|
+
if (!objClass) {
|
|
187
|
+
objClass = entityType;
|
|
188
|
+
}
|
|
189
|
+
return objClass;
|
|
190
|
+
}
|
|
191
|
+
async setEntityValues(entity, data, keysToSkip = []) {
|
|
192
|
+
const type = await this.typeUtils.getTypeById(entity.typeId);
|
|
193
|
+
keysToSkip = keysToSkip.concat(['updatedOn', 'updatedById', 'createdOn', 'createdById', 'modifiedAt', 'orgId', 'createdAt', 'id', 'typeId', 'workspaceId']);
|
|
194
|
+
let typeProps = this.typeUtils.filterTypeProperties(type, entity);
|
|
195
|
+
typeProps = typeProps.filter(prop => !keysToSkip.includes(prop['slug']));
|
|
196
|
+
const dataKeys = Object.getOwnPropertyNames(data);
|
|
197
|
+
typeProps = typeProps.filter(prop => dataKeys.includes(prop['slug']));
|
|
198
|
+
for (const prop of typeProps) {
|
|
199
|
+
const slug = prop['slug'];
|
|
200
|
+
entity[slug] = await this.getEntityValue(prop, data);
|
|
201
|
+
}
|
|
202
|
+
return entity;
|
|
203
|
+
}
|
|
204
|
+
async getEntityValues(objectClass, data, keysToSkip = []) {
|
|
205
|
+
const entityValues = {};
|
|
206
|
+
const tco = this.typeUtils.getEntityTypeClientOptions(objectClass, data);
|
|
207
|
+
const type = await this.typeUtils.getByRootAndPath(tco);
|
|
208
|
+
const typePath = type['typePath'];
|
|
209
|
+
if (typePath && (typePath.startsWith('item') || typePath.startsWith('project-item'))) {
|
|
210
|
+
if (['LCSProduct', 'LCSProductSeasonLink'].includes(objectClass)) {
|
|
211
|
+
entityValues['roles'] = ['family'];
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
entityValues['roles'] = ['color', 'option'];
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
let typeProps = this.typeUtils.filterTypeProperties(type, entityValues);
|
|
218
|
+
typeProps = typeProps.filter(prop => !keysToSkip.includes(prop['slug']));
|
|
219
|
+
for (const prop of typeProps) {
|
|
220
|
+
const slug = prop['slug'];
|
|
221
|
+
const value = await this.getEntityValue(prop, data);
|
|
222
|
+
if (value) {
|
|
223
|
+
entityValues[slug] = value;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return entityValues;
|
|
227
|
+
}
|
|
228
|
+
async getEntityValue(prop, data) {
|
|
229
|
+
const propertyType = prop['propertyType'];
|
|
230
|
+
const slug = prop['slug'];
|
|
231
|
+
const nd = data[slug];
|
|
232
|
+
let value;
|
|
233
|
+
if (['string', 'text'].includes(propertyType)) {
|
|
234
|
+
value = nd;
|
|
235
|
+
}
|
|
236
|
+
else if (['number', 'currency', 'percent', 'sequence'].includes(propertyType)) {
|
|
237
|
+
value = (null === nd) ? 0 : nd;
|
|
238
|
+
}
|
|
239
|
+
else if ('date' === propertyType) {
|
|
240
|
+
if (nd) {
|
|
241
|
+
const d = new Date(nd);
|
|
242
|
+
value = d.toISOString();
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
value = null;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
else if ('boolean' === propertyType) {
|
|
249
|
+
value = (nd) ? true : false;
|
|
250
|
+
}
|
|
251
|
+
else if ('choice' === propertyType) {
|
|
252
|
+
value = this.setEnumerationKeys(prop, nd, this.useDisplayForEnumerationMatching);
|
|
253
|
+
}
|
|
254
|
+
else if ('multi_select' === propertyType) {
|
|
255
|
+
value = this.setEnumerationKeys(prop, nd, this.useDisplayForEnumerationMatching);
|
|
256
|
+
}
|
|
257
|
+
else if ('object_reference' === propertyType) {
|
|
258
|
+
}
|
|
259
|
+
else if ('image' === propertyType) {
|
|
260
|
+
console.log('TODO');
|
|
261
|
+
}
|
|
262
|
+
else if ('formula' === propertyType) {
|
|
263
|
+
console.log('TODO');
|
|
264
|
+
}
|
|
265
|
+
else if ('json' === propertyType) {
|
|
266
|
+
console.log('TODO');
|
|
267
|
+
}
|
|
268
|
+
return value;
|
|
269
|
+
}
|
|
270
|
+
setEnumerationKeys(prop, nd, matchByDisplay) {
|
|
271
|
+
const propertyType = prop['propertyType'];
|
|
272
|
+
let value;
|
|
273
|
+
if (['choice', 'multi_select'].includes(propertyType)) {
|
|
274
|
+
const options = prop['options'];
|
|
275
|
+
if ('choice' === propertyType) {
|
|
276
|
+
if (nd) {
|
|
277
|
+
const matchKey = (matchByDisplay) ? 'display' : 'value';
|
|
278
|
+
const option = options.find(option => option[matchKey] == nd[matchKey]);
|
|
279
|
+
if (option) {
|
|
280
|
+
value = option.value;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
value = undefined;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
else if ('multi_select' === propertyType) {
|
|
288
|
+
value = [];
|
|
289
|
+
const matchKey = (matchByDisplay) ? 'display' : 'value';
|
|
290
|
+
if (nd instanceof Array) {
|
|
291
|
+
nd.forEach(selectedOpt => {
|
|
292
|
+
const optionObject = options.find(option => option[matchKey] == selectedOpt[matchKey]);
|
|
293
|
+
if (optionObject) {
|
|
294
|
+
const option = optionObject.value;
|
|
295
|
+
value.push(option);
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return value;
|
|
302
|
+
}
|
|
303
|
+
getPersistableChanges(entity, changes) {
|
|
304
|
+
const entityCompareValues = {};
|
|
305
|
+
for (const key of (Object.getOwnPropertyNames(changes))) {
|
|
306
|
+
entityCompareValues[key] = entity[key];
|
|
307
|
+
}
|
|
308
|
+
const diffs = util_1.ObjectUtil.compareDeep(entityCompareValues, changes, '');
|
|
309
|
+
const diffValues = {};
|
|
310
|
+
if (diffs && diffs.length > 0) {
|
|
311
|
+
for (const diff of diffs) {
|
|
312
|
+
diffValues[diff.propertyName] = diff.newValue;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return diffValues;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
exports.DataConverter = DataConverter;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FederationRecord } from './interfaces';
|
|
2
|
+
export declare class Federation {
|
|
3
|
+
private CHUNK_SIZE;
|
|
4
|
+
getFederatedMappedRefId(entityType: string, entityId: string): Promise<string>;
|
|
5
|
+
createFederatedRecord(eventBody: any): Promise<any>;
|
|
6
|
+
getFederationRecordFromMappedRefId(mappedRefId: string): Promise<FederationRecord>;
|
|
7
|
+
static getEntityId(fedRecord: FederationRecord): {
|
|
8
|
+
entityType: string;
|
|
9
|
+
entityId: string;
|
|
10
|
+
};
|
|
11
|
+
getEntityFromMappedRefId(mappedRefId: string): Promise<any>;
|
|
12
|
+
getFederationRecordsFromIds(ids: string[]): Promise<FederationRecord[]>;
|
|
13
|
+
getFederationRecordsFromIdsBulk(ids: string[]): Promise<FederationRecord[]>;
|
|
14
|
+
splitIntoChunksByLen(arr: any, len: any): any[];
|
|
15
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Federation = void 0;
|
|
7
|
+
const sdk_1 = require("@contrail/sdk");
|
|
8
|
+
const p_limit_1 = __importDefault(require("p-limit"));
|
|
9
|
+
const limit = (0, p_limit_1.default)(30);
|
|
10
|
+
const FED_CONFIG = {
|
|
11
|
+
appIdentifier: '@vibeiq/flexplm-connector',
|
|
12
|
+
federationSchema: 'DEFAULT'
|
|
13
|
+
};
|
|
14
|
+
class Federation {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.CHUNK_SIZE = 50;
|
|
17
|
+
}
|
|
18
|
+
async getFederatedMappedRefId(entityType, entityId) {
|
|
19
|
+
const criteria = {
|
|
20
|
+
reference: entityType + ':' + entityId,
|
|
21
|
+
appIdentifier: FED_CONFIG.appIdentifier,
|
|
22
|
+
federationSchema: FED_CONFIG.federationSchema
|
|
23
|
+
};
|
|
24
|
+
console.log('getFederatedMappedRefId: ' + JSON.stringify(criteria));
|
|
25
|
+
const fedRecords = await new sdk_1.Entities().get({
|
|
26
|
+
entityName: 'federation',
|
|
27
|
+
criteria
|
|
28
|
+
});
|
|
29
|
+
const federatedId = (fedRecords[0])
|
|
30
|
+
? fedRecords[0]['mappedReference']
|
|
31
|
+
: '';
|
|
32
|
+
return federatedId;
|
|
33
|
+
}
|
|
34
|
+
async createFederatedRecord(eventBody) {
|
|
35
|
+
const itemResults = eventBody.payload;
|
|
36
|
+
for (let i = 0; i < itemResults.length; i++) {
|
|
37
|
+
if (!itemResults[i].federatedId) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const payload = {
|
|
41
|
+
appIdentifier: FED_CONFIG.appIdentifier,
|
|
42
|
+
reference: itemResults[i].entityReference,
|
|
43
|
+
mappedReference: itemResults[i].federatedId,
|
|
44
|
+
federationSchema: FED_CONFIG.federationSchema
|
|
45
|
+
};
|
|
46
|
+
try {
|
|
47
|
+
const results = await new sdk_1.Entities().create({ entityName: 'federation', object: payload });
|
|
48
|
+
return results;
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
console.log('createFederatedRecord-error: ', error);
|
|
52
|
+
throw new Error('Error creating federation record: ' + error.message);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async getFederationRecordFromMappedRefId(mappedRefId) {
|
|
57
|
+
const criteria = {
|
|
58
|
+
appIdentifier: FED_CONFIG.appIdentifier,
|
|
59
|
+
mappedReference: mappedRefId,
|
|
60
|
+
federationSchema: FED_CONFIG.federationSchema
|
|
61
|
+
};
|
|
62
|
+
try {
|
|
63
|
+
const fedRecords = await new sdk_1.Entities().get({
|
|
64
|
+
entityName: 'federation',
|
|
65
|
+
criteria
|
|
66
|
+
});
|
|
67
|
+
return (fedRecords && fedRecords[0]) ? fedRecords[0] : undefined;
|
|
68
|
+
}
|
|
69
|
+
catch (e) {
|
|
70
|
+
console.log('getFederationData-error: ' + e.message);
|
|
71
|
+
}
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
static getEntityId(fedRecord) {
|
|
75
|
+
const entityString = fedRecord['reference'];
|
|
76
|
+
const entitySplit = entityString.split(':');
|
|
77
|
+
const entityType = entitySplit[0];
|
|
78
|
+
const entityId = entitySplit[1];
|
|
79
|
+
return { entityType, entityId };
|
|
80
|
+
}
|
|
81
|
+
async getEntityFromMappedRefId(mappedRefId) {
|
|
82
|
+
const fedRecord = await this.getFederationRecordFromMappedRefId(mappedRefId);
|
|
83
|
+
console.log('fedRecord: ' + JSON.stringify(fedRecord));
|
|
84
|
+
if (!fedRecord) {
|
|
85
|
+
console.log('Federation Record doesnt exist. Cant get entity!');
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const { entityType, entityId } = Federation.getEntityId(fedRecord);
|
|
89
|
+
const criteria = {
|
|
90
|
+
id: entityId
|
|
91
|
+
};
|
|
92
|
+
const entities = await new sdk_1.Entities().get({
|
|
93
|
+
entityName: entityType,
|
|
94
|
+
criteria
|
|
95
|
+
});
|
|
96
|
+
const entity = (entities && entities[0]) ? entities[0] : undefined;
|
|
97
|
+
return entity;
|
|
98
|
+
}
|
|
99
|
+
async getFederationRecordsFromIds(ids) {
|
|
100
|
+
const fedRecords = [];
|
|
101
|
+
for (let i = 0; i < ids.length; i++) {
|
|
102
|
+
const criteria = {
|
|
103
|
+
reference: ids[i],
|
|
104
|
+
appIdentifier: FED_CONFIG.appIdentifier,
|
|
105
|
+
federationSchema: FED_CONFIG.federationSchema
|
|
106
|
+
};
|
|
107
|
+
const recs = await new sdk_1.Entities().get({
|
|
108
|
+
entityName: 'federation',
|
|
109
|
+
criteria
|
|
110
|
+
});
|
|
111
|
+
if (recs[0]) {
|
|
112
|
+
fedRecords.push(recs[0]);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return fedRecords;
|
|
116
|
+
}
|
|
117
|
+
async getFederationRecordsFromIdsBulk(ids) {
|
|
118
|
+
const chunks = this.splitIntoChunksByLen(ids, this.CHUNK_SIZE);
|
|
119
|
+
const fedRecords = [];
|
|
120
|
+
const federatedPromises = [];
|
|
121
|
+
const entities = new sdk_1.Entities();
|
|
122
|
+
for (const chunk of chunks) {
|
|
123
|
+
const fedPromise = limit(async () => {
|
|
124
|
+
const criteria = {
|
|
125
|
+
references: chunk,
|
|
126
|
+
appIdentifier: FED_CONFIG.appIdentifier,
|
|
127
|
+
federationSchema: FED_CONFIG.federationSchema
|
|
128
|
+
};
|
|
129
|
+
const records = await entities.get({
|
|
130
|
+
entityName: 'federation',
|
|
131
|
+
criteria
|
|
132
|
+
});
|
|
133
|
+
fedRecords.push(...records);
|
|
134
|
+
});
|
|
135
|
+
federatedPromises.push(fedPromise);
|
|
136
|
+
}
|
|
137
|
+
await Promise.all(federatedPromises);
|
|
138
|
+
return fedRecords;
|
|
139
|
+
}
|
|
140
|
+
splitIntoChunksByLen(arr, len) {
|
|
141
|
+
const chunks = [], n = arr?.length;
|
|
142
|
+
let i = 0;
|
|
143
|
+
while (i < n) {
|
|
144
|
+
chunks.push(arr.slice(i, i += len));
|
|
145
|
+
}
|
|
146
|
+
return chunks;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
exports.Federation = Federation;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { FCConfig, FlexPLMResponseData, PayloadType } from './interfaces';
|
|
2
|
+
export declare class FlexPLMConnect {
|
|
3
|
+
private config;
|
|
4
|
+
private vibeEventEndpoint;
|
|
5
|
+
payloadSendAsArray: boolean;
|
|
6
|
+
constructor(_config: FCConfig, endPoint?: any, payloadAsArray?: any);
|
|
7
|
+
private getRequestOptions;
|
|
8
|
+
getCSRF(): Promise<{
|
|
9
|
+
nonce_key: any;
|
|
10
|
+
nonce: any;
|
|
11
|
+
}>;
|
|
12
|
+
sendRequest(csrf: any, payload: any): Promise<Response>;
|
|
13
|
+
protected processRequest(payload: any): Promise<FlexPLMResponseData>;
|
|
14
|
+
sendToFlexPLM(payload: PayloadType): Promise<FlexPLMResponseData>;
|
|
15
|
+
sendMultipleToFlexPLM(payload: PayloadType[]): Promise<FlexPLMResponseData>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FlexPLMConnect = void 0;
|
|
4
|
+
const app_framework_1 = require("@contrail/app-framework");
|
|
5
|
+
class FlexPLMConnect {
|
|
6
|
+
constructor(_config, endPoint = undefined, payloadAsArray = undefined) {
|
|
7
|
+
this.vibeEventEndpoint = '';
|
|
8
|
+
this.payloadSendAsArray = true;
|
|
9
|
+
this.config = _config;
|
|
10
|
+
this.vibeEventEndpoint = (endPoint)
|
|
11
|
+
? endPoint
|
|
12
|
+
: this.config.vibeEventEndpoint;
|
|
13
|
+
this.payloadSendAsArray = (payloadAsArray != undefined)
|
|
14
|
+
? payloadAsArray
|
|
15
|
+
: this.config['payloadDefaultAsArray'];
|
|
16
|
+
}
|
|
17
|
+
getRequestOptions(method) {
|
|
18
|
+
const csrfOptions = {
|
|
19
|
+
method,
|
|
20
|
+
headers: {
|
|
21
|
+
'Content-Type': 'application/json',
|
|
22
|
+
PLM_ENV: this.config.plmEnviornment,
|
|
23
|
+
Authorization: 'Basic ' + Buffer.from(`${this.config.userName()}:${this.config.password()}`, 'binary').toString('base64')
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
if (app_framework_1.Logger.isInfoOn()) {
|
|
27
|
+
const logOptions = JSON.parse(JSON.stringify(csrfOptions));
|
|
28
|
+
logOptions['headers']['Authorization'] = logOptions?.headers?.Authorization.substring(0, 9);
|
|
29
|
+
console.info('csrfOptions: ' + JSON.stringify(logOptions));
|
|
30
|
+
}
|
|
31
|
+
return csrfOptions;
|
|
32
|
+
}
|
|
33
|
+
async getCSRF() {
|
|
34
|
+
const urlContext = this.config.urlContext;
|
|
35
|
+
const csrfEndpoint = this.config.csrfEndpoint;
|
|
36
|
+
const csrfURL = this.config.apiHost + urlContext + csrfEndpoint;
|
|
37
|
+
console.info('csrfURL: ' + csrfURL);
|
|
38
|
+
const csrfOptions = this.getRequestOptions('GET');
|
|
39
|
+
const response = await fetch(csrfURL, csrfOptions);
|
|
40
|
+
if (response.status >= 300) {
|
|
41
|
+
const message = 'Error connecting to FlexPLM:status: ' + response.status;
|
|
42
|
+
console.error(message);
|
|
43
|
+
console.error(await response.text());
|
|
44
|
+
throw new Error(message);
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const body = await response.json();
|
|
48
|
+
const nonce_key = body.items[0].attributes.nonce_key;
|
|
49
|
+
const nonce = body.items[0].attributes.nonce;
|
|
50
|
+
console.info('nonce_key: ' + nonce_key);
|
|
51
|
+
console.info('nonce: ' + nonce);
|
|
52
|
+
return {
|
|
53
|
+
nonce_key,
|
|
54
|
+
nonce
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
const message = 'Error connecting to FlexPLM: ' + e.message;
|
|
59
|
+
console.error(message);
|
|
60
|
+
console.error(await response.text());
|
|
61
|
+
throw new Error(message);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async sendRequest(csrf, payload) {
|
|
65
|
+
if (this.payloadSendAsArray && !Array.isArray(payload)) {
|
|
66
|
+
payload = [payload];
|
|
67
|
+
}
|
|
68
|
+
const xferOptions = this.getRequestOptions('POST');
|
|
69
|
+
xferOptions['body'] = JSON.stringify(payload);
|
|
70
|
+
xferOptions.headers[csrf.nonce_key] = csrf.nonce;
|
|
71
|
+
const urlContext = this.config.urlContext;
|
|
72
|
+
const vibeEventsURL = this.config.apiHost + urlContext + '/servlet/rest' + this.vibeEventEndpoint;
|
|
73
|
+
if (app_framework_1.Logger.isInfoOn()) {
|
|
74
|
+
console.info('Request:');
|
|
75
|
+
console.info('vibeEventsURL: ' + vibeEventsURL);
|
|
76
|
+
const logOptions = JSON.parse(JSON.stringify(xferOptions));
|
|
77
|
+
logOptions['headers']['Authorization'] = logOptions?.headers?.Authorization.substring(0, 9);
|
|
78
|
+
console.info('csrfOptions: ' + JSON.stringify(logOptions));
|
|
79
|
+
console.info('Making call to xfer data to FlexPLM');
|
|
80
|
+
}
|
|
81
|
+
const eventResponse = await fetch(vibeEventsURL, xferOptions);
|
|
82
|
+
return eventResponse;
|
|
83
|
+
}
|
|
84
|
+
async processRequest(payload) {
|
|
85
|
+
if (!payload) {
|
|
86
|
+
const message = 'No payload to send to FlexPLM';
|
|
87
|
+
console.error(message);
|
|
88
|
+
throw new Error(message);
|
|
89
|
+
}
|
|
90
|
+
if (app_framework_1.Logger.isInfoOn()) {
|
|
91
|
+
console.info('payload: ' + JSON.stringify(payload));
|
|
92
|
+
}
|
|
93
|
+
const csrf = await this.getCSRF();
|
|
94
|
+
if (!csrf) {
|
|
95
|
+
const message = 'Failed to get CSRF nonce';
|
|
96
|
+
console.error(message);
|
|
97
|
+
throw new Error(message);
|
|
98
|
+
}
|
|
99
|
+
const response = await this.sendRequest(csrf, payload);
|
|
100
|
+
const status = response.status;
|
|
101
|
+
if (status >= 300) {
|
|
102
|
+
const message = 'Error sending data to FlexPLM:status: ' + response.status;
|
|
103
|
+
console.error(message);
|
|
104
|
+
console.error(await response.text());
|
|
105
|
+
throw new Error(message);
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
const data = await response.json();
|
|
109
|
+
const res = {
|
|
110
|
+
status,
|
|
111
|
+
data
|
|
112
|
+
};
|
|
113
|
+
console.log('eventResponse.status: ' + status);
|
|
114
|
+
return res;
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
const message = 'Error getting json data from FlexPLM: ' + e.message;
|
|
118
|
+
console.error(message);
|
|
119
|
+
console.error(await response.text());
|
|
120
|
+
throw new Error(message);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async sendToFlexPLM(payload) {
|
|
124
|
+
return await this.processRequest(payload);
|
|
125
|
+
}
|
|
126
|
+
async sendMultipleToFlexPLM(payload) {
|
|
127
|
+
return await this.processRequest(payload);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
exports.FlexPLMConnect = FlexPLMConnect;
|