wingbot-mongodb
Advanced tools
Comparing version 2.16.3 to 2.17.0-alpha.1
@@ -1,1 +0,1 @@ | ||
{"processes":{"5a4dc5e6-8e98-4d63-a4fc-e2fe688626a9":{"parent":null,"children":["ccf7d45a-e479-43d4-862d-f3f229049ae1"]},"ccf7d45a-e479-43d4-862d-f3f229049ae1":{"parent":"5a4dc5e6-8e98-4d63-a4fc-e2fe688626a9","children":[]}},"files":{"/Users/davidmenger/Development/wingbot-mongodb/src/AttachmentCache.js":["ccf7d45a-e479-43d4-862d-f3f229049ae1"],"/Users/davidmenger/Development/wingbot-mongodb/src/BotConfigStorage.js":["ccf7d45a-e479-43d4-862d-f3f229049ae1"],"/Users/davidmenger/Development/wingbot-mongodb/src/BotTokenStorage.js":["ccf7d45a-e479-43d4-862d-f3f229049ae1"],"/Users/davidmenger/Development/wingbot-mongodb/src/tokenFactory.js":["ccf7d45a-e479-43d4-862d-f3f229049ae1"],"/Users/davidmenger/Development/wingbot-mongodb/src/ChatLogStorage.js":["ccf7d45a-e479-43d4-862d-f3f229049ae1"],"/Users/davidmenger/Development/wingbot-mongodb/src/BaseStorage.js":["ccf7d45a-e479-43d4-862d-f3f229049ae1"],"/Users/davidmenger/Development/wingbot-mongodb/src/NotificationsStorage.js":["ccf7d45a-e479-43d4-862d-f3f229049ae1"],"/Users/davidmenger/Development/wingbot-mongodb/src/StateStorage.js":["ccf7d45a-e479-43d4-862d-f3f229049ae1"]},"externalIds":{}} | ||
{"processes":{"c50dc91d-0a7c-4ebe-80c8-8786cdcd0d7e":{"parent":null,"children":[]}},"files":{"/Users/david/Downloads/wingbot-mongodb/src/AttachmentCache.js":["c50dc91d-0a7c-4ebe-80c8-8786cdcd0d7e"],"/Users/david/Downloads/wingbot-mongodb/src/BotConfigStorage.js":["c50dc91d-0a7c-4ebe-80c8-8786cdcd0d7e"],"/Users/david/Downloads/wingbot-mongodb/src/BotTokenStorage.js":["c50dc91d-0a7c-4ebe-80c8-8786cdcd0d7e"],"/Users/david/Downloads/wingbot-mongodb/src/tokenFactory.js":["c50dc91d-0a7c-4ebe-80c8-8786cdcd0d7e"],"/Users/david/Downloads/wingbot-mongodb/src/ChatLogStorage.js":["c50dc91d-0a7c-4ebe-80c8-8786cdcd0d7e"],"/Users/david/Downloads/wingbot-mongodb/src/BaseStorage.js":["c50dc91d-0a7c-4ebe-80c8-8786cdcd0d7e"],"/Users/david/Downloads/wingbot-mongodb/src/NotificationsStorage.js":["c50dc91d-0a7c-4ebe-80c8-8786cdcd0d7e"],"/Users/david/Downloads/wingbot-mongodb/src/StateStorage.js":["c50dc91d-0a7c-4ebe-80c8-8786cdcd0d7e"]},"externalIds":{}} |
{ | ||
"name": "wingbot-mongodb", | ||
"version": "2.16.3", | ||
"version": "2.17.0-alpha.1", | ||
"description": "MongoDB storage for wingbot.ai", | ||
@@ -10,4 +10,4 @@ "main": "src/main.js", | ||
"test:unit:watch": "npm run test:unit -- --watch", | ||
"test:cosmos": "cross-env DB_TYPE=cosmos mocha --opts ./test/mocha.opts ./test", | ||
"test:coverage": "nyc --reporter=html mocha --opts ./test/mocha.opts ./test && nyc report", | ||
"test:cosmos": "cross-env DB_TYPE=cosmos mocha ./test", | ||
"test:coverage": "nyc --reporter=html mocha ./test && nyc report", | ||
"test:coverage:threshold": "nyc check-coverage --lines 80 --functions 79 --branches 75", | ||
@@ -38,22 +38,20 @@ "test:lint": "eslint ./src/**/*.js ./bin/**/*.js ./test/**/*.js ", | ||
"devDependencies": { | ||
"cross-env": "^5.2.0", | ||
"eslint": "^5.16.0", | ||
"eslint-config-airbnb": "^17.1.0", | ||
"eslint-mocha": "^0.5.0", | ||
"eslint-plugin-import": "^2.17.2", | ||
"eslint-plugin-jsdoc": "^4.8.4", | ||
"eslint-plugin-jsx-a11y": "^6.2.1", | ||
"eslint-plugin-mocha": "^5.3.0", | ||
"eslint-plugin-react": "^7.13.0", | ||
"jsdoc-to-markdown": "^5.0.0", | ||
"mocha": "^6.1.4", | ||
"mongodb": "^3.2.4", | ||
"nyc": "^14.1.1", | ||
"wingbot": "^2.10.0" | ||
"cross-env": "^7.0.3", | ||
"eslint": "^7.2.0", | ||
"eslint-config-airbnb": "^18.2.1", | ||
"eslint-plugin-import": "^2.25.2", | ||
"eslint-plugin-jsdoc": "^37.0.3", | ||
"eslint-plugin-jsx-a11y": "^6.4.1", | ||
"eslint-plugin-mocha": "^9.0.0", | ||
"eslint-plugin-react": "^7.26.1", | ||
"jsdoc-to-markdown": "^7.1.0", | ||
"mocha": "^9.1.3", | ||
"mongodb": "^3.7.3", | ||
"nyc": "^15.1.0", | ||
"wingbot": "^3.22.4" | ||
}, | ||
"peerDependencies": { | ||
"mongodb": ">=3.0.0", | ||
"wingbot": ">=2.10.0" | ||
}, | ||
"dependencies": {} | ||
"mongodb": "^3.0.0", | ||
"wingbot": "^3.0.0" | ||
} | ||
} |
@@ -60,3 +60,3 @@ /** | ||
* | ||
* @param {Object} index | ||
* @param {object} index | ||
* @param {IndexOptions} options | ||
@@ -85,3 +85,3 @@ */ | ||
collection = collections | ||
.find(c => c.collectionName === name); | ||
.find((c) => c.collectionName === name); | ||
@@ -99,2 +99,5 @@ if (!collection) { | ||
} | ||
await this._ensureIndexes(this._indexes, collection); | ||
return collection; | ||
@@ -114,2 +117,3 @@ } | ||
c = await this._collection; | ||
this._collection = c; | ||
} catch (e) { | ||
@@ -119,4 +123,2 @@ this._collection = null; | ||
} | ||
await this._ensureIndexes(this._indexes, c); | ||
} | ||
@@ -135,4 +137,4 @@ return this._collection; | ||
await Promise.all(existing | ||
.filter(e => !['_id_', '_id'].includes(e.name) | ||
&& !indexes.some(i => e.name === i.options.name)) | ||
.filter((e) => !['_id_', '_id'].includes(e.name) | ||
&& !indexes.some((i) => e.name === i.options.name)) | ||
.map((e) => { | ||
@@ -149,13 +151,8 @@ // eslint-disable-next-line no-console | ||
await Promise.all(indexes | ||
.filter(i => !existing.some(e => e.name === i.options.name)) | ||
.map(i => collection | ||
.filter((i) => !existing.some((e) => e.name === i.options.name)) | ||
.map((i) => collection | ||
.createIndex(i.index, i.options) | ||
// @ts-ignore | ||
.catch((e) => { | ||
if (i.isTextIndex) { | ||
this._doesNotSupportTextIndex = true; | ||
} else { | ||
this._log.error(`failed to create index ${i.options.name} on ${collection.collectionName}`); | ||
throw e; | ||
} | ||
this._log.error(`failed to create index ${i.options.name} on ${collection.collectionName}`, e); | ||
}))); | ||
@@ -162,0 +159,0 @@ } |
@@ -111,3 +111,3 @@ /* | ||
/** | ||
* @returns {Promise<Object|null>} | ||
* @returns {Promise<object | null>} | ||
*/ | ||
@@ -114,0 +114,0 @@ async getConfig () { |
@@ -13,3 +13,3 @@ /* | ||
/** | ||
* @typedef {Object} Token | ||
* @typedef {object} Token | ||
* @prop {string} senderId | ||
@@ -170,3 +170,3 @@ * @prop {string} pageId | ||
_wait (ms) { | ||
return new Promise(r => setTimeout(r, ms)); | ||
return new Promise((r) => setTimeout(r, ms)); | ||
} | ||
@@ -173,0 +173,0 @@ |
@@ -97,5 +97,5 @@ /* | ||
* @param {string} senderId | ||
* @param {Object[]} responses - list of sent responses | ||
* @param {Object} request - event request | ||
* @param {Object} [metadata] - request metadata | ||
* @param {object[]} responses - list of sent responses | ||
* @param {object} request - event request | ||
* @param {object} [metadata] - request metadata | ||
* @returns {Promise} | ||
@@ -114,3 +114,3 @@ */ | ||
return this._getCollection() | ||
.then(c => c.insertOne(log)) | ||
.then((c) => c.insertOne(log)) | ||
.catch((err) => { | ||
@@ -132,5 +132,5 @@ this._log.error('Failed to store chat log', err, log); | ||
* @param {string} senderId | ||
* @param {Object[]} [responses] - list of sent responses | ||
* @param {Object} [request] - event request | ||
* @param {Object} [metadata] - request metadata | ||
* @param {object[]} [responses] - list of sent responses | ||
* @param {object} [request] - event request | ||
* @param {object} [metadata] - request metadata | ||
* @returns {Promise} | ||
@@ -150,3 +150,3 @@ */ | ||
return this._getCollection() | ||
.then(c => c.insertOne(log)) | ||
.then((c) => c.insertOne(log)) | ||
.catch((storeError) => { | ||
@@ -153,0 +153,0 @@ this._log.error('Failed to store chat log', storeError, log); |
@@ -24,3 +24,3 @@ /** | ||
/** | ||
* @typedef Campaign {Object} | ||
* @typedef Campaign {object} | ||
* @prop {string} id | ||
@@ -49,3 +49,3 @@ * @prop {string} name | ||
* @prop {string} action | ||
* @prop {Object} [data] | ||
* @prop {object} [data] | ||
* | ||
@@ -77,3 +77,2 @@ * Setup | ||
const MAX_TS = 9999999999999; | ||
@@ -120,3 +119,3 @@ const COSMO_LIMIT = 999; | ||
collection = collections | ||
.find(c => c.collectionName === name); | ||
.find((c) => c.collectionName === name); | ||
@@ -230,3 +229,3 @@ if (!collection) { | ||
await Promise.all(existing | ||
.filter(e => !['_id_', '_id'].includes(e.name) && !indexes.some(i => e.name === i.options.name)) | ||
.filter((e) => !['_id_', '_id'].includes(e.name) && !indexes.some((i) => e.name === i.options.name)) | ||
.map((e) => { | ||
@@ -243,4 +242,4 @@ // eslint-disable-next-line no-console | ||
await Promise.all(indexes | ||
.filter(i => !existing.some(e => e.name === i.options.name)) | ||
.map(i => collection | ||
.filter((i) => !existing.some((e) => e.name === i.options.name)) | ||
.map((i) => collection | ||
.createIndex(i.index, i.options) | ||
@@ -260,3 +259,3 @@ // @ts-ignore | ||
* | ||
* @param {Object} tasks | ||
* @param {object} tasks | ||
* @returns {Promise<Task[]>} | ||
@@ -277,3 +276,3 @@ */ | ||
const $set = Object.assign({}, task); | ||
const $set = { ...task }; | ||
@@ -349,3 +348,3 @@ const filter = { | ||
} | ||
return Object.assign({}, task, override); | ||
return { ...task, ...override }; | ||
}); | ||
@@ -476,3 +475,3 @@ } | ||
* @param {string} taskId | ||
* @param {Object} data | ||
* @param {object} data | ||
*/ | ||
@@ -543,3 +542,3 @@ async updateTask (taskId, data) { | ||
return data.map(d => d.campaignId); | ||
return data.map((d) => d.campaignId); | ||
} | ||
@@ -572,3 +571,3 @@ } | ||
const result = await Promise.all( | ||
tasks.map(task => c.findOneAndUpdate({ | ||
tasks.map((task) => c.findOneAndUpdate({ | ||
_id: task._id, | ||
@@ -586,4 +585,4 @@ [eventType]: null | ||
return result | ||
.map(res => (res.value ? this._mapGenericObject(res.value) : null)) | ||
.filter(r => r !== null); | ||
.map((res) => (res.value ? this._mapGenericObject(res.value) : null)) | ||
.filter((r) => r !== null); | ||
} | ||
@@ -593,4 +592,4 @@ | ||
* | ||
* @param {Object} campaign | ||
* @param {Object} [updateCampaign] | ||
* @param {object} campaign | ||
* @param {object} [updateCampaign] | ||
* @returns {Promise<Campaign>} | ||
@@ -603,3 +602,3 @@ */ | ||
if (campaign.id) { | ||
const $setOnInsert = Object.assign({}, campaign); | ||
const $setOnInsert = { ...campaign }; | ||
delete $setOnInsert.id; | ||
@@ -626,3 +625,3 @@ const update = {}; | ||
const id = new ObjectID(); | ||
ret = Object.assign({ id: id.toHexString(), _id: id }, campaign); | ||
ret = { id: id.toHexString(), _id: id, ...campaign }; | ||
if (updateCampaign) { | ||
@@ -654,3 +653,3 @@ Object.assign(ret, updateCampaign); | ||
* @param {string} campaignId | ||
* @param {Object} increment | ||
* @param {object} increment | ||
* @returns {Promise} | ||
@@ -671,3 +670,3 @@ */ | ||
* @param {string} campaignId | ||
* @param {Object} data | ||
* @param {object} data | ||
* @returns {Promise<Campaign|null>} | ||
@@ -738,3 +737,3 @@ */ | ||
.limit(campaignIds.length) | ||
.map(camp => this._mapCampaign(camp)); | ||
.map((camp) => this._mapCampaign(camp)); | ||
@@ -746,5 +745,5 @@ return cursor.toArray(); | ||
* | ||
* @param {Object} condition | ||
* @param {object} condition | ||
* @param {number} [limit] | ||
* @param {Object} [lastKey] | ||
* @param {object} [lastKey] | ||
* @returns {Promise<{data:Campaign[],lastKey:string}>} | ||
@@ -760,7 +759,8 @@ */ | ||
useCondition = Object.assign({}, useCondition, { | ||
useCondition = { | ||
...useCondition, | ||
_id: { | ||
$lt: ObjectID.createFromHexString(key._id) | ||
} | ||
}); | ||
}; | ||
} | ||
@@ -788,3 +788,3 @@ | ||
return { | ||
data: data.map(camp => this._mapCampaign(camp)), | ||
data: data.map((camp) => this._mapCampaign(camp)), | ||
lastKey: nextLastKey | ||
@@ -905,7 +905,8 @@ }; | ||
condition = Object.assign({}, condition, { | ||
condition = { | ||
...condition, | ||
_id: { | ||
$gt: ObjectID.createFromHexString(key._id) | ||
} | ||
}); | ||
}; | ||
} | ||
@@ -998,3 +999,2 @@ | ||
const arr = await res.toArray(); | ||
@@ -1001,0 +1001,0 @@ |
@@ -7,2 +7,3 @@ /* | ||
const mongodb = require('mongodb'); // eslint-disable-line no-unused-vars | ||
const BaseStorage = require('./BaseStorage'); | ||
@@ -14,10 +15,10 @@ const USER_INDEX = 'senderId_1_pageId_1'; | ||
/** | ||
* @typedef {Object} State | ||
* @typedef {object} State | ||
* @prop {string} senderId | ||
* @prop {string} pageId | ||
* @prop {Object} state | ||
* @prop {object} state | ||
*/ | ||
/** | ||
* @typedef {Object} StateCondition | ||
* @typedef {object} StateCondition | ||
* @prop {string} [search] | ||
@@ -31,3 +32,3 @@ */ | ||
*/ | ||
class StateStorage { | ||
class StateStorage extends BaseStorage { | ||
@@ -41,15 +42,21 @@ /** | ||
*/ | ||
constructor (mongoDb, collectionName = 'states', log = console, isCosmo = false) { | ||
this._mongoDb = mongoDb; | ||
this._collectionName = collectionName; | ||
this._isCosmo = isCosmo; | ||
this._log = log; | ||
constructor (mongoDb, collectionName = 'chatlogs', log = console, isCosmo = false) { | ||
super(mongoDb, collectionName, log, isCosmo); | ||
/** | ||
* @type {Promise<mongodb.Collection>} | ||
*/ | ||
this._collection = null; | ||
this._doesNotSupportTextIndex = isCosmo; | ||
this.addIndex( | ||
{ senderId: 1, pageId: 1 }, | ||
{ name: USER_INDEX, unique: true, dropDups: true } | ||
); | ||
this.addIndex( | ||
{ lastInteraction: isCosmo ? 1 : -1 }, | ||
{ name: LAST_INTERACTION_INDEX } | ||
); | ||
this._customIndexes = []; | ||
if (!isCosmo) { | ||
this.addIndex( | ||
{ '$**': 'text' }, | ||
{ name: SEARCH } | ||
); | ||
} | ||
} | ||
@@ -60,121 +67,12 @@ | ||
* | ||
* @param {Object} index | ||
* @param {Object} options | ||
* @param {object} index | ||
* @param {object} options | ||
* @param {string} options.name | ||
* @deprecated | ||
*/ | ||
addCustomIndex (index, options) { | ||
this._customIndexes.push({ | ||
index, | ||
options | ||
}); | ||
this.addIndex(index, options); | ||
} | ||
_getIndexes () { | ||
const indexes = [ | ||
{ | ||
index: { senderId: 1, pageId: 1 }, | ||
options: { name: USER_INDEX, unique: true, dropDups: true } | ||
}, | ||
{ | ||
index: { lastInteraction: this._isCosmo ? 1 : -1 }, | ||
options: { name: LAST_INTERACTION_INDEX } | ||
} | ||
]; | ||
if (!this._doesNotSupportTextIndex) { | ||
indexes.push({ | ||
// @ts-ignore | ||
index: { '$**': 'text' }, | ||
options: { name: SEARCH }, | ||
isTextIndex: true | ||
}); | ||
} | ||
return [...indexes, ...this._customIndexes]; | ||
} | ||
async _getOrCreateCollection (name) { | ||
const db = typeof this._mongoDb === 'function' | ||
? await this._mongoDb() | ||
: this._mongoDb; | ||
let collection; | ||
if (this._isCosmo) { | ||
const collections = await db.collections(); | ||
collection = collections | ||
.find(c => c.collectionName === name); | ||
if (!collection) { | ||
try { | ||
collection = await db.createCollection(name); | ||
} catch (e) { | ||
collection = db.collection(name); | ||
} | ||
} | ||
} else { | ||
collection = db.collection(name); | ||
} | ||
return collection; | ||
} | ||
/** | ||
* @returns {Promise<mongodb.Collection>} | ||
*/ | ||
async _getCollection () { | ||
if (this._collection === null) { | ||
let c; | ||
try { | ||
this._collection = this._getOrCreateCollection(this._collectionName); | ||
c = await this._collection; | ||
} catch (e) { | ||
this._collection = null; | ||
throw e; | ||
} | ||
const indexes = this._getIndexes(); | ||
await this._ensureIndexes(indexes, c); | ||
} | ||
return this._collection; | ||
} | ||
async _ensureIndexes (indexes, collection) { | ||
let existing; | ||
try { | ||
existing = await collection.indexes(); | ||
} catch (e) { | ||
existing = []; | ||
} | ||
await Promise.all(existing | ||
.filter(e => !['_id_', '_id'].includes(e.name) && !indexes.some(i => e.name === i.options.name)) | ||
.map((e) => { | ||
// eslint-disable-next-line no-console | ||
this._log.log(`dropping index ${e.name}`); | ||
return collection.dropIndex(e.name) | ||
.catch((err) => { | ||
// eslint-disable-next-line no-console | ||
this._log.error(`dropping index ${e.name} FAILED`, err); | ||
}); | ||
})); | ||
await Promise.all(indexes | ||
.filter(i => !existing.some(e => e.name === i.options.name)) | ||
.map(i => collection | ||
.createIndex(i.index, i.options) | ||
// @ts-ignore | ||
.catch((e) => { | ||
if (i.isTextIndex) { | ||
this._doesNotSupportTextIndex = true; | ||
} else { | ||
this._log.error(`failed to create index ${i.options.name} on ${collection.collectionName}`); | ||
throw e; | ||
} | ||
}))); | ||
} | ||
/** | ||
* | ||
@@ -195,5 +93,5 @@ * @param {string} senderId | ||
* @param {string} pageId - page identifier | ||
* @param {Object} [defaultState] - default state of the conversation | ||
* @param {object} [defaultState] - default state of the conversation | ||
* @param {number} [timeout=300] - given default state | ||
* @returns {Promise<Object>} - conversation state | ||
* @returns {Promise<object>} - conversation state | ||
*/ | ||
@@ -266,3 +164,3 @@ async getOrCreateAndLock (senderId, pageId, defaultState = {}, timeout = 300) { | ||
if (searchStates) { | ||
if (this._doesNotSupportTextIndex) { | ||
if (this._isCosmo) { | ||
Object.assign(useCondition, { | ||
@@ -280,3 +178,3 @@ name: { $regex: condition.search, $options: 'i' } | ||
.skip(skip); | ||
if (!this._doesNotSupportTextIndex) { | ||
if (!this._isCosmo) { | ||
cursor | ||
@@ -312,3 +210,3 @@ .project({ score: { $meta: 'textScore' } }) | ||
return { | ||
data: data.map(camp => this._mapState(camp)), | ||
data: data.map((camp) => this._mapState(camp)), | ||
lastKey: nextLastKey | ||
@@ -335,4 +233,4 @@ }; | ||
* | ||
* @param {Object} state - conversation state | ||
* @returns {Promise<Object>} | ||
* @param {object} state - conversation state | ||
* @returns {Promise<object>} | ||
*/ | ||
@@ -339,0 +237,0 @@ async saveState (state) { |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
13
185446
18
1686
1