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