@keyv/mongo 2.1.5 → 2.1.8
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/README.md +3 -2
- package/package.json +24 -9
- package/src/index.d.ts +13 -10
- package/src/index.js +84 -86
package/README.md
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
> MongoDB storage adapter for Keyv
|
|
4
4
|
|
|
5
5
|
[](https://github.com/jaredwray/keyv/actions/workflows/tests.yaml)
|
|
6
|
-
[](https://codecov.io/gh/jaredwray/keyv)
|
|
7
7
|
[](https://www.npmjs.com/package/@keyv/mongo)
|
|
8
|
+
[](https://npmjs.com/package/@keyv/mongo)
|
|
8
9
|
|
|
9
10
|
MongoDB storage adapter for [Keyv](https://github.com/jaredwray/keyv).
|
|
10
11
|
|
|
@@ -35,4 +36,4 @@ const keyv = new Keyv('mongodb://user:pass@localhost:27017/dbname', { collection
|
|
|
35
36
|
|
|
36
37
|
## License
|
|
37
38
|
|
|
38
|
-
MIT © Jared Wray
|
|
39
|
+
MIT © Jared Wray
|
package/package.json
CHANGED
|
@@ -1,24 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keyv/mongo",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.8",
|
|
4
4
|
"description": "MongoDB storage adapter for Keyv",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"test": "xo && nyc ava",
|
|
7
|
+
"test": "xo && nyc ava --serial",
|
|
8
8
|
"coverage": "nyc report --reporter=text-lcov > coverage.lcov",
|
|
9
9
|
"clean": "rm -rf node_modules && rm -rf .nyc_output && rm -rf coverage.lcov"
|
|
10
10
|
},
|
|
11
11
|
"xo": {
|
|
12
|
-
"extends": "xo-lukechilds",
|
|
13
12
|
"rules": {
|
|
14
13
|
"unicorn/prefer-module": 0,
|
|
15
14
|
"unicorn/no-array-reduce": 0,
|
|
16
|
-
"unicorn/prefer-object-from-entries": 0
|
|
15
|
+
"unicorn/prefer-object-from-entries": 0,
|
|
16
|
+
"unicorn/prefer-node-protocol": 0,
|
|
17
|
+
"ava/no-ignored-test-files": [
|
|
18
|
+
"error",
|
|
19
|
+
{
|
|
20
|
+
"extensions": [
|
|
21
|
+
"js",
|
|
22
|
+
"ts"
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
]
|
|
17
26
|
}
|
|
18
27
|
},
|
|
19
28
|
"ava": {
|
|
20
29
|
"require": [
|
|
21
|
-
"requirable"
|
|
30
|
+
"requirable",
|
|
31
|
+
"ts-node/register"
|
|
32
|
+
],
|
|
33
|
+
"extensions": [
|
|
34
|
+
"js",
|
|
35
|
+
"ts"
|
|
22
36
|
]
|
|
23
37
|
},
|
|
24
38
|
"repository": {
|
|
@@ -44,19 +58,20 @@
|
|
|
44
58
|
},
|
|
45
59
|
"homepage": "https://github.com/jaredwray/keyv",
|
|
46
60
|
"dependencies": {
|
|
47
|
-
"mongodb": "^4.
|
|
61
|
+
"mongodb": "^4.5.0",
|
|
48
62
|
"pify": "^5.0.0"
|
|
49
63
|
},
|
|
50
64
|
"devDependencies": {
|
|
51
65
|
"@keyv/test-suite": "*",
|
|
52
|
-
"ava": "^4.
|
|
53
|
-
"eslint-config-xo-lukechilds": "^1.0.1",
|
|
66
|
+
"ava": "^4.2.0",
|
|
54
67
|
"keyv": "*",
|
|
55
68
|
"nyc": "^15.1.0",
|
|
56
69
|
"requirable": "^1.0.5",
|
|
57
70
|
"this": "^1.1.0",
|
|
71
|
+
"ts-node": "^10.8.2",
|
|
72
|
+
"@types/keyv": "^3.1.4",
|
|
58
73
|
"tsd": "^0.20.0",
|
|
59
|
-
"typescript": "^4.6.
|
|
74
|
+
"typescript": "^4.6.4",
|
|
60
75
|
"xo": "^0.48.0"
|
|
61
76
|
},
|
|
62
77
|
"tsd" : {
|
package/src/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import EventEmitter from '
|
|
1
|
+
import {EventEmitter} from 'events';
|
|
2
2
|
import GridFSBucket from 'mongodb';
|
|
3
|
+
import {Store, StoredData} from 'keyv';
|
|
3
4
|
|
|
4
|
-
declare class KeyvMongo extends EventEmitter {
|
|
5
|
+
declare class KeyvMongo<Value=any> extends EventEmitter implements Store<Value> {
|
|
5
6
|
readonly ttlSupport: false;
|
|
6
7
|
opts: Record<string, any>;
|
|
7
8
|
connect: Promise<any>;
|
|
@@ -9,16 +10,18 @@ declare class KeyvMongo extends EventEmitter {
|
|
|
9
10
|
bucket: GridFSBucket;
|
|
10
11
|
store: import('mongodb').Collection<import('bson').Document>;
|
|
11
12
|
constructor(options?: string | KeyvMongo.Options);
|
|
12
|
-
get(key: string): Promise<
|
|
13
|
-
getMany(
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
get(key: string): Promise<Value>;
|
|
14
|
+
getMany?(
|
|
15
|
+
keys: string[]
|
|
16
|
+
): Array<StoredData<Value>> | Promise<Array<StoredData<Value>>> | undefined;
|
|
17
|
+
set(key: string, value: Value, ttl?: number): any;
|
|
18
|
+
delete(key: string): boolean | Promise<boolean>;
|
|
16
19
|
deleteMany(keys: string[]): boolean;
|
|
17
|
-
|
|
18
|
-
clearUnusedFor(seconds: any): false | Promise<boolean>;
|
|
19
|
-
clear(): Promise<void>;
|
|
20
|
+
clear(): void | Promise<void>;
|
|
20
21
|
iterator(namespace: string | undefined): AsyncGenerator<any, void, any>;
|
|
21
|
-
has(key: string): boolean
|
|
22
|
+
has?(key: string): boolean | Promise<boolean>;
|
|
23
|
+
clearExpired(): boolean | Promise<boolean>;
|
|
24
|
+
clearUnusedFor(seconds: any): boolean | Promise<boolean>;
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
export = KeyvMongo;
|
package/src/index.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
// @ts-ignore
|
|
2
1
|
'use strict';
|
|
3
2
|
|
|
4
3
|
const EventEmitter = require('events');
|
|
5
|
-
const {
|
|
4
|
+
const {Buffer} = require('buffer');
|
|
6
5
|
const mongoClient = require('mongodb').MongoClient;
|
|
7
|
-
const {
|
|
6
|
+
const {GridFSBucket} = require('mongodb');
|
|
8
7
|
const pify = require('pify');
|
|
9
8
|
|
|
10
9
|
const keyvMongoKeys = new Set(['url', 'collection', 'namespace', 'serialize', 'deserialize', 'uri', 'useGridFS', 'dialect']);
|
|
@@ -14,11 +13,11 @@ class KeyvMongo extends EventEmitter {
|
|
|
14
13
|
this.ttlSupport = false;
|
|
15
14
|
url = url || {};
|
|
16
15
|
if (typeof url === 'string') {
|
|
17
|
-
url = {
|
|
16
|
+
url = {url};
|
|
18
17
|
}
|
|
19
18
|
|
|
20
19
|
if (url.uri) {
|
|
21
|
-
url = {
|
|
20
|
+
url = {url: url.uri, ...url};
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
this.opts = {
|
|
@@ -42,77 +41,76 @@ class KeyvMongo extends EventEmitter {
|
|
|
42
41
|
|
|
43
42
|
// Implementation from sql by lukechilds,
|
|
44
43
|
this.connect = new Promise(resolve => {
|
|
45
|
-
mongoClient.connect(this.opts.url, mongoOptions
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
this.db = client.db(this.opts.db);
|
|
52
|
-
if (this.opts.useGridFS) {
|
|
53
|
-
this.bucket = new GridFSBucket(this.db, {
|
|
54
|
-
readPreference: this.opts.readPreference || 'primary',
|
|
55
|
-
bucketName: this.opts.collection,
|
|
56
|
-
});
|
|
57
|
-
this.store = this.db.collection(this.opts.collection + '.files');
|
|
58
|
-
this.store.createIndex({
|
|
59
|
-
filename: 'hashed',
|
|
60
|
-
});
|
|
61
|
-
this.store.createIndex({
|
|
62
|
-
uploadDate: -1,
|
|
63
|
-
});
|
|
64
|
-
this.store.createIndex({
|
|
65
|
-
'metadata.expiresAt': 1,
|
|
66
|
-
});
|
|
67
|
-
this.store.createIndex({
|
|
68
|
-
'metadata.lastAccessed': 1,
|
|
69
|
-
});
|
|
44
|
+
mongoClient.connect(this.opts.url, mongoOptions, (error, client) => {
|
|
45
|
+
if (error) {
|
|
46
|
+
return this.emit('error', error);
|
|
47
|
+
}
|
|
70
48
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
49
|
+
this.db = client.db(this.opts.db);
|
|
50
|
+
if (this.opts.useGridFS) {
|
|
51
|
+
this.bucket = new GridFSBucket(this.db, {
|
|
52
|
+
readPreference: this.opts.readPreference || 'primary',
|
|
53
|
+
bucketName: this.opts.collection,
|
|
54
|
+
});
|
|
55
|
+
this.store = this.db.collection(this.opts.collection + '.files');
|
|
56
|
+
this.store.createIndex({
|
|
57
|
+
filename: 'hashed',
|
|
58
|
+
});
|
|
59
|
+
this.store.createIndex({
|
|
60
|
+
uploadDate: -1,
|
|
61
|
+
});
|
|
62
|
+
this.store.createIndex({
|
|
63
|
+
'metadata.expiresAt': 1,
|
|
64
|
+
});
|
|
65
|
+
this.store.createIndex({
|
|
66
|
+
'metadata.lastAccessed': 1,
|
|
67
|
+
});
|
|
77
68
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
69
|
+
for (const method of [
|
|
70
|
+
'updateOne',
|
|
71
|
+
'count',
|
|
72
|
+
]) {
|
|
73
|
+
this.store[method] = pify(this.store[method].bind(this.store));
|
|
74
|
+
}
|
|
84
75
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
unique: true,
|
|
92
|
-
background: true,
|
|
93
|
-
},
|
|
94
|
-
);
|
|
95
|
-
this.store.createIndex(
|
|
96
|
-
{ expiresAt: 1 },
|
|
97
|
-
{
|
|
98
|
-
expireAfterSeconds: 0,
|
|
99
|
-
background: true,
|
|
100
|
-
},
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
for (const method of [
|
|
104
|
-
'updateOne',
|
|
105
|
-
'findOne',
|
|
106
|
-
'deleteOne',
|
|
107
|
-
'deleteMany',
|
|
108
|
-
'count',
|
|
109
|
-
]) {
|
|
110
|
-
this.store[method] = pify(this.store[method].bind(this.store));
|
|
111
|
-
}
|
|
76
|
+
for (const method of [
|
|
77
|
+
'find',
|
|
78
|
+
'drop',
|
|
79
|
+
]) {
|
|
80
|
+
this.bucket[method] = pify(this.bucket[method].bind(this.bucket));
|
|
81
|
+
}
|
|
112
82
|
|
|
113
|
-
|
|
83
|
+
resolve({bucket: this.bucket, store: this.store, db: this.db});
|
|
84
|
+
} else {
|
|
85
|
+
this.store = this.db.collection(this.opts.collection);
|
|
86
|
+
this.store.createIndex(
|
|
87
|
+
{key: 1},
|
|
88
|
+
{
|
|
89
|
+
unique: true,
|
|
90
|
+
background: true,
|
|
91
|
+
},
|
|
92
|
+
);
|
|
93
|
+
this.store.createIndex(
|
|
94
|
+
{expiresAt: 1},
|
|
95
|
+
{
|
|
96
|
+
expireAfterSeconds: 0,
|
|
97
|
+
background: true,
|
|
98
|
+
},
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
for (const method of [
|
|
102
|
+
'updateOne',
|
|
103
|
+
'findOne',
|
|
104
|
+
'deleteOne',
|
|
105
|
+
'deleteMany',
|
|
106
|
+
'count',
|
|
107
|
+
]) {
|
|
108
|
+
this.store[method] = pify(this.store[method].bind(this.store));
|
|
114
109
|
}
|
|
115
|
-
|
|
110
|
+
|
|
111
|
+
resolve(this.store);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
116
114
|
});
|
|
117
115
|
}
|
|
118
116
|
|
|
@@ -145,7 +143,7 @@ class KeyvMongo extends EventEmitter {
|
|
|
145
143
|
}
|
|
146
144
|
|
|
147
145
|
return this.connect.then(store =>
|
|
148
|
-
store.findOne({
|
|
146
|
+
store.findOne({key: {$eq: key}}).then(doc => {
|
|
149
147
|
if (!doc) {
|
|
150
148
|
return undefined;
|
|
151
149
|
}
|
|
@@ -169,15 +167,15 @@ class KeyvMongo extends EventEmitter {
|
|
|
169
167
|
data.push(value.value);
|
|
170
168
|
}
|
|
171
169
|
|
|
172
|
-
return data
|
|
170
|
+
return data;
|
|
173
171
|
});
|
|
174
172
|
}
|
|
175
173
|
|
|
176
174
|
const results = [...keys];
|
|
177
175
|
return this.connect.then(store =>
|
|
178
176
|
store.s.db.collection(this.opts.collection)
|
|
179
|
-
.find({
|
|
180
|
-
.project({
|
|
177
|
+
.find({key: {$in: keys}})
|
|
178
|
+
.project({_id: 0, value: 1, key: 1})
|
|
181
179
|
.toArray().then(values => {
|
|
182
180
|
let i = 0;
|
|
183
181
|
for (const key of keys) {
|
|
@@ -192,7 +190,7 @@ class KeyvMongo extends EventEmitter {
|
|
|
192
190
|
i++;
|
|
193
191
|
}
|
|
194
192
|
|
|
195
|
-
return results
|
|
193
|
+
return results;
|
|
196
194
|
}),
|
|
197
195
|
);
|
|
198
196
|
}
|
|
@@ -220,9 +218,9 @@ class KeyvMongo extends EventEmitter {
|
|
|
220
218
|
|
|
221
219
|
return this.connect.then(store =>
|
|
222
220
|
store.updateOne(
|
|
223
|
-
{
|
|
224
|
-
{
|
|
225
|
-
{
|
|
221
|
+
{key: {$eq: key}},
|
|
222
|
+
{$set: {key, value, expiresAt}},
|
|
223
|
+
{upsert: true},
|
|
226
224
|
),
|
|
227
225
|
);
|
|
228
226
|
}
|
|
@@ -238,7 +236,7 @@ class KeyvMongo extends EventEmitter {
|
|
|
238
236
|
const bucket = new GridFSBucket(connection, {
|
|
239
237
|
bucketName: this.opts.collection,
|
|
240
238
|
});
|
|
241
|
-
return bucket.find({
|
|
239
|
+
return bucket.find({filename: key}).toArray()
|
|
242
240
|
.then(files => client.bucket.delete(files[0]._id).then(() => true))
|
|
243
241
|
.catch(() => false);
|
|
244
242
|
});
|
|
@@ -246,7 +244,7 @@ class KeyvMongo extends EventEmitter {
|
|
|
246
244
|
|
|
247
245
|
return this.connect.then(store =>
|
|
248
246
|
store
|
|
249
|
-
.deleteOne({
|
|
247
|
+
.deleteOne({key: {$eq: key}})
|
|
250
248
|
.then(object => object.deletedCount > 0),
|
|
251
249
|
);
|
|
252
250
|
}
|
|
@@ -258,7 +256,7 @@ class KeyvMongo extends EventEmitter {
|
|
|
258
256
|
const bucket = new GridFSBucket(connection, {
|
|
259
257
|
bucketName: this.opts.collection,
|
|
260
258
|
});
|
|
261
|
-
return bucket.find({
|
|
259
|
+
return bucket.find({filename: {$in: keys}}).toArray()
|
|
262
260
|
.then(
|
|
263
261
|
files => {
|
|
264
262
|
if (files.length === 0) {
|
|
@@ -273,7 +271,7 @@ class KeyvMongo extends EventEmitter {
|
|
|
273
271
|
|
|
274
272
|
return this.connect.then(store =>
|
|
275
273
|
store
|
|
276
|
-
.deleteMany({
|
|
274
|
+
.deleteMany({key: {$in: keys}})
|
|
277
275
|
.then(object => object.deletedCount > 0),
|
|
278
276
|
);
|
|
279
277
|
}
|
|
@@ -286,7 +284,7 @@ class KeyvMongo extends EventEmitter {
|
|
|
286
284
|
return this.connect.then(store =>
|
|
287
285
|
store
|
|
288
286
|
.deleteMany({
|
|
289
|
-
key: {
|
|
287
|
+
key: {$regex: this.namespace ? `^${this.namespace}:*` : ''},
|
|
290
288
|
})
|
|
291
289
|
.then(() => undefined),
|
|
292
290
|
);
|
|
@@ -346,13 +344,13 @@ class KeyvMongo extends EventEmitter {
|
|
|
346
344
|
has(key) {
|
|
347
345
|
if (this.opts.useGridFS) {
|
|
348
346
|
return this.connect.then(client => client.store.count(
|
|
349
|
-
{
|
|
347
|
+
{filename: {$eq: key}},
|
|
350
348
|
).then(doc => doc !== 0));
|
|
351
349
|
}
|
|
352
350
|
|
|
353
351
|
return this.connect.then(store =>
|
|
354
352
|
store.count(
|
|
355
|
-
{
|
|
353
|
+
{key: {$eq: key}},
|
|
356
354
|
),
|
|
357
355
|
).then(doc => doc !== 0);
|
|
358
356
|
}
|