UNPKG

2.47 kBJavaScriptView Raw
1'use strict';
2
3const EventEmitter = require('events');
4const JSONB = require('json-buffer');
5
6const loadStore = options => {
7 const adapters = {
8 redis: '@keyv/redis',
9 mongodb: '@keyv/mongo',
10 mongo: '@keyv/mongo',
11 sqlite: '@keyv/sqlite',
12 postgresql: '@keyv/postgres',
13 postgres: '@keyv/postgres',
14 mysql: '@keyv/mysql',
15 };
16 if (options.adapter || options.uri) {
17 const adapter = options.adapter || /^[^:]*/.exec(options.uri)[0];
18 return new (require(adapters[adapter]))(options);
19 }
20
21 return new Map();
22};
23
24class Keyv extends EventEmitter {
25 constructor(uri, options) {
26 super();
27 this.opts = Object.assign(
28 {
29 namespace: 'keyv',
30 serialize: JSONB.stringify,
31 deserialize: JSONB.parse,
32 },
33 (typeof uri === 'string') ? { uri } : uri,
34 options,
35 );
36
37 if (!this.opts.store) {
38 const adapterOptions = Object.assign({}, this.opts);
39 this.opts.store = loadStore(adapterOptions);
40 }
41
42 if (typeof this.opts.store.on === 'function') {
43 this.opts.store.on('error', error => this.emit('error', error));
44 }
45
46 this.opts.store.namespace = this.opts.namespace;
47 }
48
49 _getKeyPrefix(key) {
50 return `${this.opts.namespace}:${key}`;
51 }
52
53 get(key, options) {
54 const keyPrefixed = this._getKeyPrefix(key);
55 const { store } = this.opts;
56 return Promise.resolve()
57 .then(() => store.get(keyPrefixed))
58 .then(data => (typeof data === 'string') ? this.opts.deserialize(data) : data)
59 .then(data => {
60 if (data === undefined) {
61 return undefined;
62 }
63
64 if (typeof data.expires === 'number' && Date.now() > data.expires) {
65 this.delete(key);
66 return undefined;
67 }
68
69 return (options && options.raw) ? data : data.value;
70 });
71 }
72
73 set(key, value, ttl) {
74 const keyPrefixed = this._getKeyPrefix(key);
75 if (typeof ttl === 'undefined') {
76 ttl = this.opts.ttl;
77 }
78
79 if (ttl === 0) {
80 ttl = undefined;
81 }
82
83 const { store } = this.opts;
84
85 return Promise.resolve()
86 .then(() => {
87 const expires = (typeof ttl === 'number') ? (Date.now() + ttl) : null;
88 value = { value, expires };
89 return this.opts.serialize(value);
90 })
91 .then(value => store.set(keyPrefixed, value, ttl))
92 .then(() => true);
93 }
94
95 delete(key) {
96 const keyPrefixed = this._getKeyPrefix(key);
97 const { store } = this.opts;
98 return Promise.resolve()
99 .then(() => store.delete(keyPrefixed));
100 }
101
102 clear() {
103 const { store } = this.opts;
104 return Promise.resolve()
105 .then(() => store.clear());
106 }
107}
108
109module.exports = Keyv;