wingbot-mongodb 2.16.3 → 2.19.0

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.
@@ -4,20 +4,21 @@
4
4
  'use strict';
5
5
 
6
6
  const mongodb = require('mongodb'); // eslint-disable-line no-unused-vars
7
+ const BaseStorage = require('./BaseStorage');
7
8
 
8
9
  const USER_INDEX = 'senderId_1_pageId_1';
9
10
  const LAST_INTERACTION_INDEX = 'lastInteraction_1';
10
11
  const SEARCH = 'search-text';
11
12
 
12
13
  /**
13
- * @typedef {Object} State
14
+ * @typedef {object} State
14
15
  * @prop {string} senderId
15
16
  * @prop {string} pageId
16
- * @prop {Object} state
17
+ * @prop {object} state
17
18
  */
18
19
 
19
20
  /**
20
- * @typedef {Object} StateCondition
21
+ * @typedef {object} StateCondition
21
22
  * @prop {string} [search]
22
23
  */
23
24
 
@@ -26,7 +27,7 @@ const SEARCH = 'search-text';
26
27
  *
27
28
  * @class
28
29
  */
29
- class StateStorage {
30
+ class StateStorage extends BaseStorage {
30
31
 
31
32
  /**
32
33
  *
@@ -35,140 +36,37 @@ class StateStorage {
35
36
  * @param {{error:Function,log:Function}} [log] - console like logger
36
37
  * @param {boolean} isCosmo
37
38
  */
38
- constructor (mongoDb, collectionName = 'states', log = console, isCosmo = false) {
39
- this._mongoDb = mongoDb;
40
- this._collectionName = collectionName;
41
- this._isCosmo = isCosmo;
42
- this._log = log;
43
-
44
- /**
45
- * @type {Promise<mongodb.Collection>}
46
- */
47
- this._collection = null;
48
- this._doesNotSupportTextIndex = isCosmo;
49
-
50
- this._customIndexes = [];
39
+ constructor (mongoDb, collectionName = 'chatlogs', log = console, isCosmo = false) {
40
+ super(mongoDb, collectionName, log, isCosmo);
41
+
42
+ this.addIndex(
43
+ { senderId: 1, pageId: 1 },
44
+ { name: USER_INDEX, unique: true, dropDups: true }
45
+ );
46
+ this.addIndex(
47
+ { lastInteraction: isCosmo ? 1 : -1 },
48
+ { name: LAST_INTERACTION_INDEX }
49
+ );
50
+
51
+ if (!isCosmo) {
52
+ this.addIndex(
53
+ { '$**': 'text' },
54
+ { name: SEARCH }
55
+ );
56
+ }
57
+
51
58
  }
52
59
 
53
60
  /**
54
61
  * Add custom indexing rule
55
62
  *
56
- * @param {Object} index
57
- * @param {Object} options
63
+ * @param {object} index
64
+ * @param {object} options
58
65
  * @param {string} options.name
66
+ * @deprecated
59
67
  */
60
68
  addCustomIndex (index, options) {
61
- this._customIndexes.push({
62
- index,
63
- options
64
- });
65
- }
66
-
67
- _getIndexes () {
68
- const indexes = [
69
- {
70
- index: { senderId: 1, pageId: 1 },
71
- options: { name: USER_INDEX, unique: true, dropDups: true }
72
- },
73
- {
74
- index: { lastInteraction: this._isCosmo ? 1 : -1 },
75
- options: { name: LAST_INTERACTION_INDEX }
76
- }
77
- ];
78
-
79
- if (!this._doesNotSupportTextIndex) {
80
- indexes.push({
81
- // @ts-ignore
82
- index: { '$**': 'text' },
83
- options: { name: SEARCH },
84
- isTextIndex: true
85
- });
86
- }
87
-
88
- return [...indexes, ...this._customIndexes];
89
- }
90
-
91
- async _getOrCreateCollection (name) {
92
- const db = typeof this._mongoDb === 'function'
93
- ? await this._mongoDb()
94
- : this._mongoDb;
95
-
96
- let collection;
97
-
98
- if (this._isCosmo) {
99
- const collections = await db.collections();
100
-
101
- collection = collections
102
- .find(c => c.collectionName === name);
103
-
104
- if (!collection) {
105
- try {
106
- collection = await db.createCollection(name);
107
- } catch (e) {
108
- collection = db.collection(name);
109
- }
110
- }
111
-
112
- } else {
113
- collection = db.collection(name);
114
- }
115
- return collection;
116
- }
117
-
118
- /**
119
- * @returns {Promise<mongodb.Collection>}
120
- */
121
- async _getCollection () {
122
- if (this._collection === null) {
123
- let c;
124
- try {
125
- this._collection = this._getOrCreateCollection(this._collectionName);
126
- c = await this._collection;
127
- } catch (e) {
128
- this._collection = null;
129
- throw e;
130
- }
131
-
132
- const indexes = this._getIndexes();
133
-
134
- await this._ensureIndexes(indexes, c);
135
- }
136
- return this._collection;
137
- }
138
-
139
- async _ensureIndexes (indexes, collection) {
140
- let existing;
141
- try {
142
- existing = await collection.indexes();
143
- } catch (e) {
144
- existing = [];
145
- }
146
-
147
- await Promise.all(existing
148
- .filter(e => !['_id_', '_id'].includes(e.name) && !indexes.some(i => e.name === i.options.name))
149
- .map((e) => {
150
- // eslint-disable-next-line no-console
151
- this._log.log(`dropping index ${e.name}`);
152
- return collection.dropIndex(e.name)
153
- .catch((err) => {
154
- // eslint-disable-next-line no-console
155
- this._log.error(`dropping index ${e.name} FAILED`, err);
156
- });
157
- }));
158
-
159
- await Promise.all(indexes
160
- .filter(i => !existing.some(e => e.name === i.options.name))
161
- .map(i => collection
162
- .createIndex(i.index, i.options)
163
- // @ts-ignore
164
- .catch((e) => {
165
- if (i.isTextIndex) {
166
- this._doesNotSupportTextIndex = true;
167
- } else {
168
- this._log.error(`failed to create index ${i.options.name} on ${collection.collectionName}`);
169
- throw e;
170
- }
171
- })));
69
+ this.addIndex(index, options);
172
70
  }
173
71
 
174
72
  /**
@@ -187,9 +85,9 @@ class StateStorage {
187
85
  *
188
86
  * @param {string} senderId - sender identifier
189
87
  * @param {string} pageId - page identifier
190
- * @param {Object} [defaultState] - default state of the conversation
88
+ * @param {object} [defaultState] - default state of the conversation
191
89
  * @param {number} [timeout=300] - given default state
192
- * @returns {Promise<Object>} - conversation state
90
+ * @returns {Promise<object>} - conversation state
193
91
  */
194
92
  async getOrCreateAndLock (senderId, pageId, defaultState = {}, timeout = 300) {
195
93
  const now = Date.now();
@@ -217,7 +115,7 @@ class StateStorage {
217
115
  $set
218
116
  }, {
219
117
  upsert: true,
220
- returnOriginal: false,
118
+ returnDocument: 'after',
221
119
  projection: {
222
120
  _id: 0
223
121
  }
@@ -257,7 +155,7 @@ class StateStorage {
257
155
  const searchStates = typeof condition.search === 'string';
258
156
 
259
157
  if (searchStates) {
260
- if (this._doesNotSupportTextIndex) {
158
+ if (this._isCosmo) {
261
159
  Object.assign(useCondition, {
262
160
  name: { $regex: condition.search, $options: 'i' }
263
161
  });
@@ -270,7 +168,7 @@ class StateStorage {
270
168
  .find(useCondition)
271
169
  .limit(limit + 1)
272
170
  .skip(skip);
273
- if (!this._doesNotSupportTextIndex) {
171
+ if (!this._isCosmo) {
274
172
  cursor
275
173
  .project({ score: { $meta: 'textScore' } })
276
174
  .sort({ score: { $meta: 'textScore' } });
@@ -301,7 +199,7 @@ class StateStorage {
301
199
  }
302
200
 
303
201
  return {
304
- data: data.map(camp => this._mapState(camp)),
202
+ data: data.map((camp) => this._mapState(camp)),
305
203
  lastKey: nextLastKey
306
204
  };
307
205
  }
@@ -323,8 +221,8 @@ class StateStorage {
323
221
  /**
324
222
  * Save the state to database
325
223
  *
326
- * @param {Object} state - conversation state
327
- * @returns {Promise<Object>}
224
+ * @param {object} state - conversation state
225
+ * @returns {Promise<object>}
328
226
  */
329
227
  async saveState (state) {
330
228
  Object.assign(state, {
package/src/main.js CHANGED
@@ -9,6 +9,7 @@ const BotTokenStorage = require('./BotTokenStorage');
9
9
  const ChatLogStorage = require('./ChatLogStorage');
10
10
  const BotConfigStorage = require('./BotConfigStorage');
11
11
  const AttachmentCache = require('./AttachmentCache');
12
+ const AuditLogStorage = require('./AuditLogStorage');
12
13
  const NotificationsStorage = require('./NotificationsStorage');
13
14
 
14
15
  module.exports = {
@@ -18,5 +19,6 @@ module.exports = {
18
19
  ChatLogStorage,
19
20
  BotConfigStorage,
20
21
  AttachmentCache,
21
- NotificationsStorage
22
+ NotificationsStorage,
23
+ AuditLogStorage
22
24
  };