| Leo Repp | 58b9f11 | 2021-11-22 11:57:47 +0100 | [diff] [blame^] | 1 | 'use strict'; |
| 2 | |
| 3 | const EventEmitter = require('events'); |
| 4 | const JSONB = require('json-buffer'); |
| 5 | |
| 6 | const loadStore = opts => { |
| 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 (opts.adapter || opts.uri) { |
| 17 | const adapter = opts.adapter || /^[^:]*/.exec(opts.uri)[0]; |
| 18 | return new (require(adapters[adapter]))(opts); |
| 19 | } |
| 20 | return new Map(); |
| 21 | }; |
| 22 | |
| 23 | class Keyv extends EventEmitter { |
| 24 | constructor(uri, opts) { |
| 25 | super(); |
| 26 | this.opts = Object.assign( |
| 27 | { namespace: 'keyv' }, |
| 28 | (typeof uri === 'string') ? { uri } : uri, |
| 29 | opts |
| 30 | ); |
| 31 | |
| 32 | if (!this.opts.store) { |
| 33 | const adapterOpts = Object.assign({}, this.opts); |
| 34 | this.opts.store = loadStore(adapterOpts); |
| 35 | } |
| 36 | |
| 37 | if (typeof this.opts.store.on === 'function') { |
| 38 | this.opts.store.on('error', err => this.emit('error', err)); |
| 39 | } |
| 40 | |
| 41 | this.opts.store.namespace = this.opts.namespace; |
| 42 | } |
| 43 | |
| 44 | _getKeyPrefix(key) { |
| 45 | return `${this.opts.namespace}:${key}`; |
| 46 | } |
| 47 | |
| 48 | get(key) { |
| 49 | key = this._getKeyPrefix(key); |
| 50 | const store = this.opts.store; |
| 51 | return Promise.resolve() |
| 52 | .then(() => store.get(key)) |
| 53 | .then(data => { |
| 54 | data = (typeof data === 'string') ? JSONB.parse(data) : data; |
| 55 | if (data === undefined) { |
| 56 | return undefined; |
| 57 | } |
| 58 | if (typeof data.expires === 'number' && Date.now() > data.expires) { |
| 59 | this.delete(key); |
| 60 | return undefined; |
| 61 | } |
| 62 | return data.value; |
| 63 | }); |
| 64 | } |
| 65 | |
| 66 | set(key, value, ttl) { |
| 67 | key = this._getKeyPrefix(key); |
| 68 | if (typeof ttl === 'undefined') { |
| 69 | ttl = this.opts.ttl; |
| 70 | } |
| 71 | if (ttl === 0) { |
| 72 | ttl = undefined; |
| 73 | } |
| 74 | const store = this.opts.store; |
| 75 | |
| 76 | return Promise.resolve() |
| 77 | .then(() => { |
| 78 | const expires = (typeof ttl === 'number') ? (Date.now() + ttl) : null; |
| 79 | value = { value, expires }; |
| 80 | return store.set(key, JSONB.stringify(value), ttl); |
| 81 | }) |
| 82 | .then(() => true); |
| 83 | } |
| 84 | |
| 85 | delete(key) { |
| 86 | key = this._getKeyPrefix(key); |
| 87 | const store = this.opts.store; |
| 88 | return Promise.resolve() |
| 89 | .then(() => store.delete(key)); |
| 90 | } |
| 91 | |
| 92 | clear() { |
| 93 | const store = this.opts.store; |
| 94 | return Promise.resolve() |
| 95 | .then(() => store.clear()); |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | module.exports = Keyv; |