@restorecommerce/resource-base-interface 0.2.2 → 0.2.3
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/CHANGELOG.md +5 -0
- package/lib/core/GraphResourcesServiceBase.js +120 -100
- package/lib/core/GraphResourcesServiceBase.js.map +1 -1
- package/lib/core/ResourcesAPI.js +283 -282
- package/lib/core/ResourcesAPI.js.map +1 -1
- package/lib/core/ServiceBase.js +244 -244
- package/lib/core/ServiceBase.js.map +1 -1
- package/lib/core/interfaces.d.ts +32 -0
- package/lib/core/interfaces.js +8 -1
- package/lib/core/interfaces.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +20 -1
- package/lib/index.js.map +1 -1
- package/package.json +14 -13
- package/tsconfig.json +12 -4
- package/test.js +0 -16
- package/testFilter.js +0 -221
package/lib/core/ResourcesAPI.js
CHANGED
|
@@ -1,21 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
23
|
};
|
|
11
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
25
|
exports.ResourcesAPIBase = void 0;
|
|
13
|
-
const _ = require("lodash");
|
|
14
|
-
const
|
|
26
|
+
const _ = __importStar(require("lodash"));
|
|
27
|
+
const bluebird_1 = __importDefault(require("bluebird"));
|
|
15
28
|
const chassis_srv_1 = require("@restorecommerce/chassis-srv");
|
|
16
|
-
const uuid = require("uuid");
|
|
17
|
-
const redis = require("redis");
|
|
18
|
-
|
|
29
|
+
const uuid = __importStar(require("uuid"));
|
|
30
|
+
const redis = __importStar(require("redis"));
|
|
31
|
+
bluebird_1.default.promisifyAll(redis.RedisClient.prototype);
|
|
19
32
|
let redisClient;
|
|
20
33
|
const Strategies = {
|
|
21
34
|
INCREMENT: 'increment',
|
|
@@ -29,22 +42,22 @@ const uuidGen = () => {
|
|
|
29
42
|
const isEmptyObject = (obj) => {
|
|
30
43
|
return !Object.keys(obj).length;
|
|
31
44
|
};
|
|
32
|
-
const setDefaults = (obj, collectionName) =>
|
|
45
|
+
const setDefaults = async (obj, collectionName) => {
|
|
33
46
|
const o = obj;
|
|
34
47
|
if (_.isEmpty(o.meta)) {
|
|
35
48
|
throw new chassis_srv_1.errors.InvalidArgument('Object does not contain ownership information');
|
|
36
49
|
}
|
|
37
50
|
const now = Date.now();
|
|
38
51
|
if (redisClient) {
|
|
39
|
-
const values =
|
|
52
|
+
const values = await redisClient.hgetallAsync(collectionName);
|
|
40
53
|
if (values) {
|
|
41
54
|
for (let field in values) {
|
|
42
55
|
const strategy = values[field];
|
|
43
56
|
switch (strategy) {
|
|
44
57
|
case Strategies.INCREMENT:
|
|
45
58
|
const key = collectionName + ':' + field;
|
|
46
|
-
o[field] =
|
|
47
|
-
|
|
59
|
+
o[field] = await redisClient.getAsync(key);
|
|
60
|
+
await redisClient.incrAsync(key);
|
|
48
61
|
break;
|
|
49
62
|
case Strategies.UUID:
|
|
50
63
|
o[field] = uuidGen();
|
|
@@ -53,7 +66,7 @@ const setDefaults = (obj, collectionName) => __awaiter(void 0, void 0, void 0, f
|
|
|
53
66
|
o[field] = uuidGen();
|
|
54
67
|
break;
|
|
55
68
|
case Strategies.TIMESTAMP:
|
|
56
|
-
o[field] =
|
|
69
|
+
o[field] = await redisClient.timeAsync()[0];
|
|
57
70
|
break;
|
|
58
71
|
}
|
|
59
72
|
}
|
|
@@ -67,7 +80,7 @@ const setDefaults = (obj, collectionName) => __awaiter(void 0, void 0, void 0, f
|
|
|
67
80
|
o.id = uuidGen();
|
|
68
81
|
}
|
|
69
82
|
return o;
|
|
70
|
-
}
|
|
83
|
+
};
|
|
71
84
|
const updateMetadata = (docMeta, newDoc) => {
|
|
72
85
|
if (_.isEmpty(newDoc.meta)) {
|
|
73
86
|
// docMeta.owner = newDoc.owner;
|
|
@@ -188,120 +201,116 @@ class ResourcesAPIBase {
|
|
|
188
201
|
* @param {object} field key value, key=field value: 0=exclude, 1=include
|
|
189
202
|
* @returns {an Object that contains an items field}
|
|
190
203
|
*/
|
|
191
|
-
read(filter = {}, limit = 1000, offset = 0, sort = {}, field = {}, customQueries = [], customArgs = {}) {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
return entities;
|
|
212
|
-
});
|
|
204
|
+
async read(filter = {}, limit = 1000, offset = 0, sort = {}, field = {}, customQueries = [], customArgs = {}) {
|
|
205
|
+
const options = {
|
|
206
|
+
limit: Math.min(limit, 1000),
|
|
207
|
+
offset,
|
|
208
|
+
sort,
|
|
209
|
+
fields: field,
|
|
210
|
+
customQueries,
|
|
211
|
+
customArguments: customArgs.value ? JSON.parse(customArgs.value.toString()) : {}
|
|
212
|
+
};
|
|
213
|
+
const entities = await this.db.find(this.collectionName, filter, options);
|
|
214
|
+
if (this.bufferField) {
|
|
215
|
+
// encode the msg obj back to buffer obj and send it back
|
|
216
|
+
entities.forEach(element => {
|
|
217
|
+
if (element[this.bufferField]) {
|
|
218
|
+
element = encodeMsgObj(element, this.bufferField);
|
|
219
|
+
return element;
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
return entities;
|
|
213
224
|
}
|
|
214
225
|
/**
|
|
215
226
|
* Inserts documents to the database.
|
|
216
227
|
*
|
|
217
228
|
* @param {array.object} documents
|
|
218
229
|
*/
|
|
219
|
-
create(documents) {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
230
|
+
async create(documents) {
|
|
231
|
+
const collection = this.collectionName;
|
|
232
|
+
const toInsert = [];
|
|
233
|
+
let result = [];
|
|
234
|
+
try {
|
|
223
235
|
let result = [];
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
if (this.bufferField) {
|
|
236
|
-
toInsert.push(decodeBufferObj(_.cloneDeep(documents[i]), this.bufferField));
|
|
237
|
-
}
|
|
236
|
+
// check if all the required fields are present
|
|
237
|
+
if (this.requiredFields && this.requiredFields[this.resourceName]) {
|
|
238
|
+
const requiredFieldsResult = this.checkRequiredFields(this.requiredFields[this.resourceName], documents, result);
|
|
239
|
+
documents = requiredFieldsResult.documents;
|
|
240
|
+
result = requiredFieldsResult.result;
|
|
241
|
+
}
|
|
242
|
+
for (let i = 0; i < documents.length; i += 1) {
|
|
243
|
+
documents[i] = await setDefaults(documents[i], collection);
|
|
244
|
+
// decode the buffer and store it to DB
|
|
245
|
+
if (this.bufferField) {
|
|
246
|
+
toInsert.push(decodeBufferObj(_.cloneDeep(documents[i]), this.bufferField));
|
|
238
247
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
else {
|
|
265
|
-
yield this.db.createEdge(eachEdgeCfg.edgeName, null, `${fromVerticeName}/${from_id}`, `${toVerticeName}/${to_id}`);
|
|
248
|
+
}
|
|
249
|
+
if (this.isGraphDB(this.db)) {
|
|
250
|
+
await this.db.createGraphDB(this.graphName);
|
|
251
|
+
await this.db.addVertexCollection(collection);
|
|
252
|
+
let createVertexResp = await this.db.createVertex(collection, this.bufferField ? toInsert : documents);
|
|
253
|
+
for (let document of documents) {
|
|
254
|
+
if (this.edgeCfg && _.isArray(this.edgeCfg) && this.edgeCfg.length > 0) {
|
|
255
|
+
for (let eachEdgeCfg of this.edgeCfg) {
|
|
256
|
+
const fromIDkey = eachEdgeCfg.from;
|
|
257
|
+
const from_id = document[fromIDkey];
|
|
258
|
+
const toIDkey = eachEdgeCfg.to;
|
|
259
|
+
const to_id = document[toIDkey];
|
|
260
|
+
// edges are created outbound, if it is inbound - check for direction
|
|
261
|
+
const direction = eachEdgeCfg.direction;
|
|
262
|
+
let fromVerticeName = collection;
|
|
263
|
+
let toVerticeName = eachEdgeCfg.toVerticeName;
|
|
264
|
+
if (direction === 'inbound') {
|
|
265
|
+
fromVerticeName = eachEdgeCfg.fromVerticeName;
|
|
266
|
+
toVerticeName = collection;
|
|
267
|
+
}
|
|
268
|
+
if (from_id && to_id) {
|
|
269
|
+
if (_.isArray(to_id)) {
|
|
270
|
+
for (let toID of to_id) {
|
|
271
|
+
await this.db.createEdge(eachEdgeCfg.edgeName, null, `${fromVerticeName}/${from_id}`, `${toVerticeName}/${toID}`);
|
|
266
272
|
}
|
|
267
273
|
}
|
|
274
|
+
else {
|
|
275
|
+
await this.db.createEdge(eachEdgeCfg.edgeName, null, `${fromVerticeName}/${from_id}`, `${toVerticeName}/${to_id}`);
|
|
276
|
+
}
|
|
268
277
|
}
|
|
269
278
|
}
|
|
270
279
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
}
|
|
276
|
-
else {
|
|
277
|
-
result.push(createVertexResp);
|
|
280
|
+
}
|
|
281
|
+
if (_.isArray(createVertexResp)) {
|
|
282
|
+
for (let eachVertexResp of createVertexResp) {
|
|
283
|
+
result.push(eachVertexResp);
|
|
278
284
|
}
|
|
279
|
-
return result;
|
|
280
285
|
}
|
|
281
286
|
else {
|
|
282
|
-
|
|
283
|
-
if (!_.isEmpty(result)) {
|
|
284
|
-
checkReqFieldResult = result;
|
|
285
|
-
}
|
|
286
|
-
result = yield this.db.insert(collection, this.bufferField ? toInsert : documents);
|
|
287
|
-
if (!_.isEmpty(checkReqFieldResult)) {
|
|
288
|
-
for (let reqFieldResult of checkReqFieldResult) {
|
|
289
|
-
result.push(reqFieldResult);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
return result;
|
|
287
|
+
result.push(createVertexResp);
|
|
293
288
|
}
|
|
289
|
+
return result;
|
|
294
290
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
291
|
+
else {
|
|
292
|
+
let checkReqFieldResult = [];
|
|
293
|
+
if (!_.isEmpty(result)) {
|
|
294
|
+
checkReqFieldResult = result;
|
|
295
|
+
}
|
|
296
|
+
result = await this.db.insert(collection, this.bufferField ? toInsert : documents);
|
|
297
|
+
if (!_.isEmpty(checkReqFieldResult)) {
|
|
298
|
+
for (let reqFieldResult of checkReqFieldResult) {
|
|
299
|
+
result.push(reqFieldResult);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
302
|
return result;
|
|
303
303
|
}
|
|
304
|
-
}
|
|
304
|
+
}
|
|
305
|
+
catch (e) {
|
|
306
|
+
this.logger.error('Error creating documents', { error: e.message });
|
|
307
|
+
result.push({
|
|
308
|
+
error: true,
|
|
309
|
+
errorNum: e.code,
|
|
310
|
+
errorMessage: e.details ? e.details : e.message
|
|
311
|
+
});
|
|
312
|
+
return result;
|
|
313
|
+
}
|
|
305
314
|
}
|
|
306
315
|
isGraphDB(db) {
|
|
307
316
|
return !!this.edgeCfg;
|
|
@@ -340,114 +349,108 @@ class ResourcesAPIBase {
|
|
|
340
349
|
*
|
|
341
350
|
* @param [array.string] ids List of document IDs.
|
|
342
351
|
*/
|
|
343
|
-
delete(ids) {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
ids = [ids];
|
|
349
|
-
}
|
|
350
|
-
if (this.isGraphDB(this.db)) {
|
|
351
|
-
// Modify the Ids to include documentHandle
|
|
352
|
-
if (ids.length > 0) {
|
|
353
|
-
ids = _.map(ids, (id) => {
|
|
354
|
-
return `${this.collectionName}/${id}`;
|
|
355
|
-
});
|
|
356
|
-
deleteResponse = yield this.db.removeVertex(this.collectionName, ids);
|
|
357
|
-
return deleteResponse;
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
deleteResponse = yield this.db.delete(this.collectionName, ids);
|
|
361
|
-
return deleteResponse;
|
|
352
|
+
async delete(ids) {
|
|
353
|
+
let deleteResponse = [];
|
|
354
|
+
try {
|
|
355
|
+
if (!_.isArray(ids)) {
|
|
356
|
+
ids = [ids];
|
|
362
357
|
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
358
|
+
if (this.isGraphDB(this.db)) {
|
|
359
|
+
// Modify the Ids to include documentHandle
|
|
360
|
+
if (ids.length > 0) {
|
|
361
|
+
ids = _.map(ids, (id) => {
|
|
362
|
+
return `${this.collectionName}/${id}`;
|
|
363
|
+
});
|
|
364
|
+
deleteResponse = await this.db.removeVertex(this.collectionName, ids);
|
|
365
|
+
return deleteResponse;
|
|
366
|
+
}
|
|
371
367
|
}
|
|
372
|
-
|
|
368
|
+
deleteResponse = await this.db.delete(this.collectionName, ids);
|
|
369
|
+
return deleteResponse;
|
|
370
|
+
}
|
|
371
|
+
catch (err) {
|
|
372
|
+
this.logger.error('Error deleting documents', { error: err.message });
|
|
373
|
+
deleteResponse.push({
|
|
374
|
+
error: true,
|
|
375
|
+
errorNum: err.code,
|
|
376
|
+
errorMessage: err.details ? err.details : err.message
|
|
377
|
+
});
|
|
378
|
+
return deleteResponse;
|
|
379
|
+
}
|
|
373
380
|
}
|
|
374
381
|
/**
|
|
375
382
|
* Delete all documents in the collection.
|
|
376
383
|
*/
|
|
377
|
-
deleteCollection() {
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
}
|
|
397
|
-
});
|
|
384
|
+
async deleteCollection() {
|
|
385
|
+
if (this.isGraphDB(this.db)) {
|
|
386
|
+
// graph edges are only deleted automatically when a specific vertex is deleted
|
|
387
|
+
// (`truncate` does not work in this case)
|
|
388
|
+
const ids = await this.db.find(this.collectionName, {}, {
|
|
389
|
+
fields: {
|
|
390
|
+
id: 1
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
await this.delete(_.map(ids, (doc) => {
|
|
394
|
+
return doc.id;
|
|
395
|
+
}));
|
|
396
|
+
return ids;
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
const entities = await this.db.find(this.collectionName, {}, { fields: { id: 1 } });
|
|
400
|
+
await this.db.truncate(this.collectionName);
|
|
401
|
+
return entities;
|
|
402
|
+
}
|
|
398
403
|
}
|
|
399
404
|
/**
|
|
400
405
|
* Upserts documents.
|
|
401
406
|
*
|
|
402
407
|
* @param [array.object] documents
|
|
403
408
|
*/
|
|
404
|
-
upsert(documents, events, resourceName) {
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
});
|
|
419
|
-
}
|
|
420
|
-
let eventName;
|
|
421
|
-
if (_.isEmpty(foundDocs)) {
|
|
422
|
-
// insert
|
|
423
|
-
setDefaults(doc, this.collectionName);
|
|
424
|
-
eventName = 'Created';
|
|
425
|
-
}
|
|
426
|
-
else {
|
|
427
|
-
// update
|
|
428
|
-
const dbDoc = foundDocs[0];
|
|
429
|
-
updateMetadata(dbDoc.meta, doc);
|
|
430
|
-
eventName = 'Modified';
|
|
431
|
-
}
|
|
432
|
-
dispatch.push(events.emit(`${resourceName}${eventName}`, doc));
|
|
409
|
+
async upsert(documents, events, resourceName) {
|
|
410
|
+
let result = [];
|
|
411
|
+
try {
|
|
412
|
+
const dispatch = []; // CRUD events to be dispatched
|
|
413
|
+
for (let i = 0; i < documents.length; i += 1) {
|
|
414
|
+
let doc = documents[i];
|
|
415
|
+
decodeBufferObj(doc, this.bufferField);
|
|
416
|
+
let foundDocs;
|
|
417
|
+
if (doc && doc.id) {
|
|
418
|
+
foundDocs = await this.db.find(this.collectionName, { id: doc.id }, {
|
|
419
|
+
fields: {
|
|
420
|
+
meta: 1
|
|
421
|
+
}
|
|
422
|
+
});
|
|
433
423
|
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
424
|
+
let eventName;
|
|
425
|
+
if (_.isEmpty(foundDocs)) {
|
|
426
|
+
// insert
|
|
427
|
+
setDefaults(doc, this.collectionName);
|
|
428
|
+
eventName = 'Created';
|
|
438
429
|
}
|
|
439
|
-
|
|
430
|
+
else {
|
|
431
|
+
// update
|
|
432
|
+
const dbDoc = foundDocs[0];
|
|
433
|
+
updateMetadata(dbDoc.meta, doc);
|
|
434
|
+
eventName = 'Modified';
|
|
435
|
+
}
|
|
436
|
+
dispatch.push(events.emit(`${resourceName}${eventName}`, doc));
|
|
440
437
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
errorNum: error.code,
|
|
446
|
-
errorMessage: error.details ? error.details : error.message
|
|
447
|
-
});
|
|
448
|
-
return result;
|
|
438
|
+
result = await this.db.upsert(this.collectionName, documents);
|
|
439
|
+
await dispatch;
|
|
440
|
+
if (this.bufferField) {
|
|
441
|
+
return _.map(result, doc => encodeMsgObj(doc, this.bufferField));
|
|
449
442
|
}
|
|
450
|
-
|
|
443
|
+
return result;
|
|
444
|
+
}
|
|
445
|
+
catch (error) {
|
|
446
|
+
this.logger.error('Error upserting documents', { error: error.message });
|
|
447
|
+
result.push({
|
|
448
|
+
error: true,
|
|
449
|
+
errorNum: error.code,
|
|
450
|
+
errorMessage: error.details ? error.details : error.message
|
|
451
|
+
});
|
|
452
|
+
return result;
|
|
453
|
+
}
|
|
451
454
|
}
|
|
452
455
|
/**
|
|
453
456
|
* Finds documents by id and updates them.
|
|
@@ -455,95 +458,93 @@ class ResourcesAPIBase {
|
|
|
455
458
|
* @param [array.object] documents
|
|
456
459
|
* A list of documents or partial documents. Each document must contain an id field.
|
|
457
460
|
*/
|
|
458
|
-
update(documents) {
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
461
|
+
async update(documents) {
|
|
462
|
+
let updateResponse = [];
|
|
463
|
+
try {
|
|
464
|
+
const collectionName = this.collectionName;
|
|
465
|
+
let docsWithUpMetadata = [];
|
|
466
|
+
for (let i = 0; i < documents.length; i += 1) {
|
|
467
|
+
let doc = documents[i];
|
|
468
|
+
if (this.bufferField) {
|
|
469
|
+
doc = decodeBufferObj(_.cloneDeep(documents[i]), this.bufferField);
|
|
470
|
+
}
|
|
471
|
+
const foundDocs = await this.db.find(collectionName, { id: doc.id });
|
|
472
|
+
let dbDoc;
|
|
473
|
+
if (foundDocs && foundDocs.length === 1) {
|
|
474
|
+
dbDoc = foundDocs[0];
|
|
475
|
+
doc = updateMetadata(dbDoc.meta, doc);
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
dbDoc = doc; // doc not existing assigning to generate error message in response
|
|
479
|
+
}
|
|
480
|
+
if (this.isGraphDB(this.db)) {
|
|
481
|
+
const db = this.db;
|
|
482
|
+
for (let eachEdgeCfg of this.edgeCfg) {
|
|
483
|
+
const toIDkey = eachEdgeCfg.to;
|
|
484
|
+
let modified_to_idValues = doc[toIDkey];
|
|
485
|
+
let db_to_idValues = dbDoc[toIDkey];
|
|
486
|
+
if (_.isArray(modified_to_idValues)) {
|
|
487
|
+
modified_to_idValues = _.sortBy(modified_to_idValues);
|
|
488
|
+
}
|
|
489
|
+
if (_.isArray(db_to_idValues)) {
|
|
490
|
+
db_to_idValues = _.sortBy(db_to_idValues);
|
|
491
|
+
}
|
|
492
|
+
// delete and recreate only if there is a difference in references
|
|
493
|
+
if (!_.isEqual(modified_to_idValues, db_to_idValues)) {
|
|
494
|
+
// TODO delete and recreate the edge (since there is no way to update the edge as we dont add id to the edge as for doc)
|
|
495
|
+
const fromIDkey = eachEdgeCfg.from;
|
|
496
|
+
const from_id = doc[fromIDkey];
|
|
497
|
+
let fromVerticeName = collectionName;
|
|
498
|
+
let toVerticeName = eachEdgeCfg.toVerticeName;
|
|
499
|
+
const direction = eachEdgeCfg.direction;
|
|
500
|
+
if (direction === 'inbound') {
|
|
501
|
+
fromVerticeName = eachEdgeCfg.fromVerticeName;
|
|
502
|
+
toVerticeName = collectionName;
|
|
489
503
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
let fromVerticeName = collectionName;
|
|
496
|
-
let toVerticeName = eachEdgeCfg.toVerticeName;
|
|
497
|
-
const direction = eachEdgeCfg.direction;
|
|
498
|
-
if (direction === 'inbound') {
|
|
499
|
-
fromVerticeName = eachEdgeCfg.fromVerticeName;
|
|
500
|
-
toVerticeName = collectionName;
|
|
504
|
+
const edgeCollectionName = eachEdgeCfg.edgeName;
|
|
505
|
+
let outgoingEdges = await db.getOutEdges(edgeCollectionName, `${collectionName}/${dbDoc.id}`);
|
|
506
|
+
if (_.isArray(outgoingEdges.edges)) {
|
|
507
|
+
for (let outgoingEdge of outgoingEdges.edges) {
|
|
508
|
+
await db.removeEdge(edgeCollectionName, outgoingEdge._id);
|
|
501
509
|
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
}
|
|
510
|
+
}
|
|
511
|
+
let incomingEdges = await db.getInEdges(edgeCollectionName, `${collectionName}/${dbDoc.id}`);
|
|
512
|
+
if (_.isArray(incomingEdges.edges)) {
|
|
513
|
+
for (let incomingEdge of incomingEdges.edges) {
|
|
514
|
+
await db.removeEdge(edgeCollectionName, incomingEdge._id);
|
|
508
515
|
}
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
516
|
+
}
|
|
517
|
+
// Create new edges
|
|
518
|
+
if (from_id && modified_to_idValues) {
|
|
519
|
+
if (_.isArray(modified_to_idValues)) {
|
|
520
|
+
for (let toID of modified_to_idValues) {
|
|
521
|
+
await db.createEdge(eachEdgeCfg.edgeName, null, `${fromVerticeName}/${from_id}`, `${toVerticeName}/${toID}`);
|
|
513
522
|
}
|
|
514
523
|
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
if (_.isArray(modified_to_idValues)) {
|
|
518
|
-
for (let toID of modified_to_idValues) {
|
|
519
|
-
yield db.createEdge(eachEdgeCfg.edgeName, null, `${fromVerticeName}/${from_id}`, `${toVerticeName}/${toID}`);
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
else {
|
|
523
|
-
yield db.createEdge(edgeCollectionName, null, `${fromVerticeName}/${from_id}`, `${toVerticeName}/${modified_to_idValues}`);
|
|
524
|
-
}
|
|
524
|
+
else {
|
|
525
|
+
await db.createEdge(edgeCollectionName, null, `${fromVerticeName}/${from_id}`, `${toVerticeName}/${modified_to_idValues}`);
|
|
525
526
|
}
|
|
526
527
|
}
|
|
527
528
|
}
|
|
528
529
|
}
|
|
529
|
-
docsWithUpMetadata.push(doc);
|
|
530
530
|
}
|
|
531
|
-
|
|
532
|
-
if (this.bufferField) {
|
|
533
|
-
updateResponse = _.map(updateResponse, patch => encodeMsgObj(patch, this.bufferField));
|
|
534
|
-
}
|
|
535
|
-
return updateResponse;
|
|
531
|
+
docsWithUpMetadata.push(doc);
|
|
536
532
|
}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
updateResponse.
|
|
540
|
-
error: true,
|
|
541
|
-
errorNum: e.code,
|
|
542
|
-
errorMessage: e.message
|
|
543
|
-
});
|
|
544
|
-
return updateResponse;
|
|
533
|
+
updateResponse = await this.db.update(collectionName, docsWithUpMetadata);
|
|
534
|
+
if (this.bufferField) {
|
|
535
|
+
updateResponse = _.map(updateResponse, patch => encodeMsgObj(patch, this.bufferField));
|
|
545
536
|
}
|
|
546
|
-
|
|
537
|
+
return updateResponse;
|
|
538
|
+
}
|
|
539
|
+
catch (e) {
|
|
540
|
+
this.logger.error('Error updating documents', { error: e.message });
|
|
541
|
+
updateResponse.push({
|
|
542
|
+
error: true,
|
|
543
|
+
errorNum: e.code,
|
|
544
|
+
errorMessage: e.message
|
|
545
|
+
});
|
|
546
|
+
return updateResponse;
|
|
547
|
+
}
|
|
547
548
|
}
|
|
548
549
|
}
|
|
549
550
|
exports.ResourcesAPIBase = ResourcesAPIBase;
|