wingbot-mongodb 3.2.6 → 4.0.0-alpha.2

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.
@@ -1 +1 @@
1
- {"parent":null,"pid":38479,"argv":["/usr/local/bin/node","/Users/david/Development/wingbot-mongodb/node_modules/.bin/mocha","./test"],"execArgv":[],"cwd":"/Users/david/Development/wingbot-mongodb","time":1692102034748,"ppid":38478,"coverageFilename":"/Users/david/Development/wingbot-mongodb/.nyc_output/1091dc07-773b-48f1-9817-b8048f05d575.json","externalId":"","uuid":"1091dc07-773b-48f1-9817-b8048f05d575","files":["/Users/david/Development/wingbot-mongodb/src/BaseStorage.js","/Users/david/Development/wingbot-mongodb/src/defaultLogger.js","/Users/david/Development/wingbot-mongodb/src/AttachmentCache.js","/Users/david/Development/wingbot-mongodb/src/AuditLogStorage.js","/Users/david/Development/wingbot-mongodb/src/BotConfigStorage.js","/Users/david/Development/wingbot-mongodb/src/BotTokenStorage.js","/Users/david/Development/wingbot-mongodb/src/tokenFactory.js","/Users/david/Development/wingbot-mongodb/src/ChatLogStorage.js","/Users/david/Development/wingbot-mongodb/src/NotificationsStorage.js","/Users/david/Development/wingbot-mongodb/src/StateStorage.js"]}
1
+ {"parent":null,"pid":94202,"argv":["/usr/local/bin/node","/Users/david/Development/wingbot-mongodb/node_modules/.bin/mocha","./test"],"execArgv":[],"cwd":"/Users/david/Development/wingbot-mongodb","time":1695123947917,"ppid":94201,"coverageFilename":"/Users/david/Development/wingbot-mongodb/.nyc_output/c5005d32-ad45-472c-811c-860ccef899fe.json","externalId":"","uuid":"c5005d32-ad45-472c-811c-860ccef899fe","files":["/Users/david/Development/wingbot-mongodb/src/BaseStorage.js","/Users/david/Development/wingbot-mongodb/src/defaultLogger.js","/Users/david/Development/wingbot-mongodb/src/AttachmentCache.js","/Users/david/Development/wingbot-mongodb/src/AuditLogStorage.js","/Users/david/Development/wingbot-mongodb/src/BotConfigStorage.js","/Users/david/Development/wingbot-mongodb/src/BotTokenStorage.js","/Users/david/Development/wingbot-mongodb/src/tokenFactory.js","/Users/david/Development/wingbot-mongodb/src/ChatLogStorage.js","/Users/david/Development/wingbot-mongodb/src/NotificationsStorage.js","/Users/david/Development/wingbot-mongodb/src/StateStorage.js"]}
@@ -1 +1 @@
1
- {"processes":{"1091dc07-773b-48f1-9817-b8048f05d575":{"parent":null,"children":[]}},"files":{"/Users/david/Development/wingbot-mongodb/src/BaseStorage.js":["1091dc07-773b-48f1-9817-b8048f05d575"],"/Users/david/Development/wingbot-mongodb/src/defaultLogger.js":["1091dc07-773b-48f1-9817-b8048f05d575"],"/Users/david/Development/wingbot-mongodb/src/AttachmentCache.js":["1091dc07-773b-48f1-9817-b8048f05d575"],"/Users/david/Development/wingbot-mongodb/src/AuditLogStorage.js":["1091dc07-773b-48f1-9817-b8048f05d575"],"/Users/david/Development/wingbot-mongodb/src/BotConfigStorage.js":["1091dc07-773b-48f1-9817-b8048f05d575"],"/Users/david/Development/wingbot-mongodb/src/BotTokenStorage.js":["1091dc07-773b-48f1-9817-b8048f05d575"],"/Users/david/Development/wingbot-mongodb/src/tokenFactory.js":["1091dc07-773b-48f1-9817-b8048f05d575"],"/Users/david/Development/wingbot-mongodb/src/ChatLogStorage.js":["1091dc07-773b-48f1-9817-b8048f05d575"],"/Users/david/Development/wingbot-mongodb/src/NotificationsStorage.js":["1091dc07-773b-48f1-9817-b8048f05d575"],"/Users/david/Development/wingbot-mongodb/src/StateStorage.js":["1091dc07-773b-48f1-9817-b8048f05d575"]},"externalIds":{}}
1
+ {"processes":{"c5005d32-ad45-472c-811c-860ccef899fe":{"parent":null,"children":[]}},"files":{"/Users/david/Development/wingbot-mongodb/src/BaseStorage.js":["c5005d32-ad45-472c-811c-860ccef899fe"],"/Users/david/Development/wingbot-mongodb/src/defaultLogger.js":["c5005d32-ad45-472c-811c-860ccef899fe"],"/Users/david/Development/wingbot-mongodb/src/AttachmentCache.js":["c5005d32-ad45-472c-811c-860ccef899fe"],"/Users/david/Development/wingbot-mongodb/src/AuditLogStorage.js":["c5005d32-ad45-472c-811c-860ccef899fe"],"/Users/david/Development/wingbot-mongodb/src/BotConfigStorage.js":["c5005d32-ad45-472c-811c-860ccef899fe"],"/Users/david/Development/wingbot-mongodb/src/BotTokenStorage.js":["c5005d32-ad45-472c-811c-860ccef899fe"],"/Users/david/Development/wingbot-mongodb/src/tokenFactory.js":["c5005d32-ad45-472c-811c-860ccef899fe"],"/Users/david/Development/wingbot-mongodb/src/ChatLogStorage.js":["c5005d32-ad45-472c-811c-860ccef899fe"],"/Users/david/Development/wingbot-mongodb/src/NotificationsStorage.js":["c5005d32-ad45-472c-811c-860ccef899fe"],"/Users/david/Development/wingbot-mongodb/src/StateStorage.js":["c5005d32-ad45-472c-811c-860ccef899fe"]},"externalIds":{}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wingbot-mongodb",
3
- "version": "3.2.6",
3
+ "version": "4.0.0-alpha.2",
4
4
  "description": "MongoDB storage for wingbot.ai",
5
5
  "main": "src/main.js",
6
6
  "scripts": {
@@ -27,7 +27,7 @@
27
27
  "author": "wingbot.ai",
28
28
  "license": "MIT",
29
29
  "engines": {
30
- "node": ">=12.0.0"
30
+ "node": ">=14.0.0"
31
31
  },
32
32
  "bugs": {
33
33
  "url": "https://github.com/wingbotai/wingbot-mongodb/issues"
@@ -45,12 +45,12 @@
45
45
  "jsdoc-to-markdown": "^7.1.1",
46
46
  "jsdoc-tsimport-plugin": "^1.0.5",
47
47
  "mocha": "^10.1.0",
48
- "mongodb": "^4.12.1",
48
+ "mongodb": "^6.1.0",
49
49
  "nyc": "^15.1.0",
50
50
  "wingbot": "^3.46.3"
51
51
  },
52
52
  "peerDependencies": {
53
- "mongodb": "^4.0.0"
53
+ "mongodb": "^6.0.0"
54
54
  },
55
55
  "optionalDependencies": {
56
56
  "wingbot": "^3.0.0"
@@ -4,6 +4,7 @@
4
4
  'use strict';
5
5
 
6
6
  const { ObjectId } = require('mongodb');
7
+ const { strict: assert } = require('assert');
7
8
  const crypto = require('crypto');
8
9
  const defaultLogger = require('./defaultLogger');
9
10
 
@@ -130,6 +131,10 @@ class BaseStorage {
130
131
  }
131
132
  });
132
133
  }
134
+
135
+ this._indexing = null;
136
+ this._shouldIndexBeforeRead = null;
137
+ this._shouldWaitForIndex = null;
133
138
  }
134
139
 
135
140
  /**
@@ -178,7 +183,7 @@ class BaseStorage {
178
183
  /**
179
184
  * Insert defalt document to DB
180
185
  *
181
- * @param {...any} objects
186
+ * @param {...{ _id: string|number|ObjectId }} objects
182
187
  */
183
188
  addFixtureDoc (...objects) {
184
189
  this._fixtures.push(...objects);
@@ -256,7 +261,20 @@ class BaseStorage {
256
261
  collection = db.collection(name);
257
262
  }
258
263
 
259
- await this._ensureIndexes(this._indexes, collection);
264
+ this._shouldIndexBeforeRead = this._fixtures.length !== 0;
265
+ this._shouldWaitForIndex = this._isCosmo
266
+ || this._shouldIndexBeforeRead
267
+ || this._indexes.some((i) => i.options.unique);
268
+
269
+ this._indexing = this._ensureIndexes(this._indexes, collection)
270
+ .then(() => {
271
+ this._indexing = false;
272
+ })
273
+ .catch((e) => {
274
+ this._collection = null;
275
+ this._log.log(`DB.${this._collectionName} - init failed`, e);
276
+ return e;
277
+ });
260
278
 
261
279
  return collection;
262
280
  }
@@ -265,9 +283,10 @@ class BaseStorage {
265
283
  * Returns the collection to operate with
266
284
  *
267
285
  * @protected
286
+ * @param {boolean} [forRead]
268
287
  * @returns {Promise<Collection>}
269
288
  */
270
- async _getCollection () {
289
+ async _getCollection (forRead = false) {
271
290
  if (this._collection === null) {
272
291
  let c;
273
292
  try {
@@ -280,6 +299,16 @@ class BaseStorage {
280
299
  throw e;
281
300
  }
282
301
  }
302
+
303
+ if (this._indexing
304
+ && this._shouldWaitForIndex
305
+ && (!forRead || this._shouldIndexBeforeRead)) {
306
+
307
+ const err = await this._indexing;
308
+ this._indexing = false;
309
+ if (err) throw err;
310
+ }
311
+
283
312
  return this._collection;
284
313
  }
285
314
 
@@ -290,12 +319,10 @@ class BaseStorage {
290
319
  * @returns {Promise}
291
320
  */
292
321
  async _ensureIndexes (indexes, collection) {
293
- let existing;
294
- try {
295
- existing = await collection.indexes();
296
- } catch (e) {
297
- existing = [];
298
- }
322
+ const [existing, fixtures] = await Promise.all([
323
+ this._checkExistingIndexes(collection),
324
+ this._checkFixtures(collection)
325
+ ]);
299
326
 
300
327
  await existing
301
328
  .filter((e) => !this.systemIndexes.includes(e.name)
@@ -309,7 +336,7 @@ class BaseStorage {
309
336
  });
310
337
  }, Promise.resolve());
311
338
 
312
- let updated = await indexes
339
+ await indexes
313
340
  .filter((i) => !existing.some((e) => e.name === i.options.name))
314
341
  .reduce((p, i) => {
315
342
  this._log.log(`DB.${this._collectionName} creating index ${i.options.name}`);
@@ -324,31 +351,7 @@ class BaseStorage {
324
351
  .then(() => true);
325
352
  }, Promise.resolve(false));
326
353
 
327
- if (!updated) {
328
- updated = existing.every((i) => this.systemIndexes.includes(i.name));
329
- }
330
-
331
- let fixtures = this._fixtures;
332
-
333
- const $in = fixtures
334
- .map((f) => f._id)
335
- .filter((f) => !!f);
336
-
337
- if (!updated && $in.length !== 0) {
338
- const found = await collection
339
- .find({ _id: { $in } })
340
- .project({ _id: 1 })
341
- .map((doc) => doc._id.toString())
342
- .toArray();
343
-
344
- if (found.length !== $in.length) {
345
- updated = true;
346
- fixtures = fixtures
347
- .filter((f) => !f._id || !found.includes(f._id.toString()));
348
- }
349
- }
350
-
351
- if (!updated || fixtures.length === 0) {
354
+ if (fixtures.length === 0) {
352
355
  return;
353
356
  }
354
357
 
@@ -367,6 +370,45 @@ class BaseStorage {
367
370
  );
368
371
  }
369
372
 
373
+ async _checkExistingIndexes (collection) {
374
+ let existing;
375
+ try {
376
+ existing = await collection.indexes();
377
+ } catch (e) {
378
+ existing = [];
379
+ }
380
+ return existing;
381
+ }
382
+
383
+ async _checkFixtures (collection) {
384
+ if (this._fixtures.length === 0) {
385
+ return this._fixtures;
386
+ }
387
+
388
+ const fixtures = this._fixtures
389
+ .map((f) => {
390
+ assert(f._id, `DB.${this._collectionName} fixture must have _id property`);
391
+ return {
392
+ ...f,
393
+ _id: this._id(f._id)
394
+ };
395
+ });
396
+
397
+ const $in = fixtures.map((f) => f._id);
398
+
399
+ const found = await collection
400
+ .find({ _id: { $in } })
401
+ .project({ _id: 1 })
402
+ .map((doc) => doc._id.toString())
403
+ .toArray();
404
+
405
+ if (found.length === $in.length) {
406
+ return [];
407
+ }
408
+
409
+ return fixtures.filter((f) => !found.includes(f._id.toString()));
410
+ }
411
+
370
412
  /**
371
413
  *
372
414
  * @template T
@@ -134,9 +134,6 @@ class BotTokenStorage {
134
134
  returnDocument: 'after'
135
135
  });
136
136
 
137
- // @ts-ignore
138
- res = res.value;
139
-
140
137
  // @ts-ignore
141
138
  if (res.token === temporaryInsecureToken) {
142
139
 
@@ -403,8 +403,8 @@ class NotificationsStorage {
403
403
  sort: { enqueue: 1 },
404
404
  returnDocument: 'after'
405
405
  });
406
- if (found.value) {
407
- pop.push(this._mapGenericObject(found.value));
406
+ if (found) {
407
+ pop.push(this._mapGenericObject(found));
408
408
  go = pop.length < limit;
409
409
  } else {
410
410
  go = false;
@@ -498,7 +498,7 @@ class NotificationsStorage {
498
498
  returnDocument: 'after'
499
499
  });
500
500
 
501
- return this._mapGenericObject(res.value);
501
+ return this._mapGenericObject(res);
502
502
  }
503
503
 
504
504
  /**
@@ -590,7 +590,7 @@ class NotificationsStorage {
590
590
  );
591
591
 
592
592
  return result
593
- .map((res) => (res.value ? this._mapGenericObject(res.value) : null))
593
+ .map((res) => (res ? this._mapGenericObject(res) : null))
594
594
  .filter((r) => r !== null);
595
595
  }
596
596
 
@@ -624,7 +624,7 @@ class NotificationsStorage {
624
624
  upsert: true,
625
625
  returnDocument: 'after'
626
626
  });
627
- ret = this._mapCampaign(res.value);
627
+ ret = this._mapCampaign(res);
628
628
  } else {
629
629
  const id = new ObjectId();
630
630
  ret = { id: id.toHexString(), _id: id, ...campaign };
@@ -684,7 +684,7 @@ class NotificationsStorage {
684
684
  returnDocument: 'after'
685
685
  });
686
686
 
687
- return this._mapCampaign(res.value);
687
+ return this._mapCampaign(res);
688
688
  }
689
689
 
690
690
  /**
@@ -704,7 +704,7 @@ class NotificationsStorage {
704
704
  returnDocument: 'before'
705
705
  });
706
706
 
707
- return this._mapCampaign(res.value);
707
+ return this._mapCampaign(res);
708
708
  }
709
709
 
710
710
  /**
@@ -845,9 +845,9 @@ class NotificationsStorage {
845
845
  returnDocument: 'after'
846
846
  });
847
847
 
848
- if (res.value) {
848
+ if (res) {
849
849
  ret.push(tag);
850
- removeWholeSubscribtion = res.value.subs.length === 0;
850
+ removeWholeSubscribtion = res.subs.length === 0;
851
851
  } else {
852
852
  return [];
853
853
  }
@@ -855,8 +855,8 @@ class NotificationsStorage {
855
855
 
856
856
  if (removeWholeSubscribtion) {
857
857
  const res = await c.findOneAndDelete({ pageId, senderId });
858
- if (res.value) {
859
- ret.push(...res.value.subs);
858
+ if (res) {
859
+ ret.push(...res.subs);
860
860
  }
861
861
  }
862
862
 
@@ -137,7 +137,7 @@ class StateStorage extends BaseStorage {
137
137
  }
138
138
  }));
139
139
 
140
- if (this._uniqueIndexFailed && !res.value.lastInteraction) {
140
+ if (this._uniqueIndexFailed && !res.lastInteraction) {
141
141
  // check if there was a locked state
142
142
  const existing = await c.find({
143
143
  senderId,
@@ -155,7 +155,7 @@ class StateStorage extends BaseStorage {
155
155
 
156
156
  const logLevel = this.logCollisionsAsErrors ? 'error' : 'log';
157
157
  this._log[logLevel]('StateStorage: unique index workaround DETECTED', {
158
- v: res.value, existing, $in: $in.map((i) => i.toString())
158
+ v: res, existing, $in: $in.map((i) => i.toString())
159
159
  });
160
160
 
161
161
  if ($in.length > 0) {
@@ -164,11 +164,11 @@ class StateStorage extends BaseStorage {
164
164
 
165
165
  throw Object.assign(new Error('State was locked'), { code: 11000 });
166
166
  } else {
167
- this._log.log('StateStorage: unique index workaround OK', res.value);
167
+ this._log.log('StateStorage: unique index workaround OK', res);
168
168
  }
169
169
  }
170
170
 
171
- return res.value;
171
+ return res;
172
172
  }
173
173
 
174
174
  /**