|
@ -6,18 +6,23 @@ const JSONB = require('json-buffer') |
|
|
class Keyv extends EventEmitter { |
|
|
class Keyv extends EventEmitter { |
|
|
constructor ({ emitErrors = true, ...options } = {}) { |
|
|
constructor ({ emitErrors = true, ...options } = {}) { |
|
|
super() |
|
|
super() |
|
|
this.options = Object.assign( |
|
|
|
|
|
|
|
|
const normalizedOptions = Object.assign( |
|
|
{ |
|
|
{ |
|
|
namespace: 'keyv', |
|
|
namespace: 'keyv', |
|
|
serialize: JSONB.stringify, |
|
|
serialize: JSONB.stringify, |
|
|
deserialize: JSONB.parse, |
|
|
deserialize: JSONB.parse, |
|
|
emitErrors: true |
|
|
emitErrors: true, |
|
|
|
|
|
store: new Map() |
|
|
}, |
|
|
}, |
|
|
options |
|
|
options |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
this.store = this.options.store || new Map() |
|
|
Object.keys(normalizedOptions).forEach( |
|
|
this.store.namespace = this.options.namespace |
|
|
key => (this[key] = normalizedOptions[key]) |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
this.store.namespace = this.namespace |
|
|
|
|
|
|
|
|
if (typeof this.store.on === 'function' && emitErrors) { |
|
|
if (typeof this.store.on === 'function' && emitErrors) { |
|
|
this.store.on('error', error => this.emit('error', error)) |
|
|
this.store.on('error', error => this.emit('error', error)) |
|
@ -28,12 +33,8 @@ class Keyv extends EventEmitter { |
|
|
for await (const [key, raw] of typeof iterator === 'function' |
|
|
for await (const [key, raw] of typeof iterator === 'function' |
|
|
? iterator() |
|
|
? iterator() |
|
|
: iterator) { |
|
|
: iterator) { |
|
|
const data = |
|
|
const data = typeof raw === 'string' ? this.deserialize(raw) : raw |
|
|
typeof raw === 'string' ? this.options.deserialize(raw) : raw |
|
|
if (!key.includes(this.namespace) || typeof data !== 'object') { |
|
|
if ( |
|
|
|
|
|
!key.includes(this.options.namespace) || |
|
|
|
|
|
typeof data !== 'object' |
|
|
|
|
|
) { |
|
|
|
|
|
continue |
|
|
continue |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -60,11 +61,11 @@ class Keyv extends EventEmitter { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
_getKeyPrefix (key) { |
|
|
_getKeyPrefix (key) { |
|
|
return this.options.namespace ? `${this.options.namespace}:${key}` : key |
|
|
return this.namespace ? `${this.namespace}:${key}` : key |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
_getKeyUnprefix (key) { |
|
|
_getKeyUnprefix (key) { |
|
|
return this.options.namespace |
|
|
return this.namespace |
|
|
? key |
|
|
? key |
|
|
.split(':') |
|
|
.split(':') |
|
|
.splice(1) |
|
|
.splice(1) |
|
@ -72,75 +73,43 @@ class Keyv extends EventEmitter { |
|
|
: key |
|
|
: key |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
get (key, options) { |
|
|
async get (key, { raw: asRaw = false } = {}) { |
|
|
const keyPrefixed = this._getKeyPrefix(key) |
|
|
const raw = await this.store.get(this._getKeyPrefix(key)) |
|
|
const store = this.store |
|
|
if (raw === undefined) return undefined |
|
|
return Promise.resolve() |
|
|
|
|
|
.then(() => store.get(keyPrefixed)) |
|
|
|
|
|
.then(data => { |
|
|
|
|
|
return typeof data === 'string' ? this.options.deserialize(data) : data |
|
|
|
|
|
}) |
|
|
|
|
|
.then(data => { |
|
|
|
|
|
if (data === undefined) { |
|
|
|
|
|
return undefined |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (typeof data.expires === 'number' && Date.now() > data.expires) { |
|
|
|
|
|
this.delete(key) |
|
|
|
|
|
return undefined |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return options && options.raw ? data : data.value |
|
|
const data = typeof raw === 'string' ? await this.deserialize(raw) : raw |
|
|
}) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
has (key) { |
|
|
if (typeof data.expires === 'number' && Date.now() > data.expires) { |
|
|
const keyPrefixed = this._getKeyPrefix(key) |
|
|
this.delete(key) |
|
|
const store = this.store |
|
|
return undefined |
|
|
if (typeof store.has === 'function') { |
|
|
|
|
|
return Promise.resolve().then(() => store.has(keyPrefixed)) |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return Promise.resolve() |
|
|
return asRaw ? data : data.value |
|
|
.then(() => store.get(keyPrefixed)) |
|
|
|
|
|
.then(data => data !== undefined) |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
set (key, value, ttl) { |
|
|
async has (key) { |
|
|
if (value === undefined) return false |
|
|
return typeof this.store.has === 'function' |
|
|
const keyPrefixed = this._getKeyPrefix(key) |
|
|
? this.store.has(this._getKeyPrefix(key)) |
|
|
if (typeof ttl === 'undefined') { |
|
|
: (await this.store.get(this._getKeyPrefix(key))) !== undefined |
|
|
ttl = this.options.ttl |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (ttl === 0) { |
|
|
|
|
|
ttl = undefined |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const store = this.store |
|
|
|
|
|
return Promise.resolve() |
|
|
|
|
|
.then(() => { |
|
|
|
|
|
const expires = typeof ttl === 'number' ? Date.now() + ttl : null |
|
|
|
|
|
value = { value, expires } |
|
|
|
|
|
return this.options.serialize(value) |
|
|
|
|
|
}) |
|
|
|
|
|
.then(value => store.set(keyPrefixed, value, ttl)) |
|
|
|
|
|
.then(() => true) |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
delete (key) { |
|
|
async set (key, value, ttl) { |
|
|
const keyPrefixed = this._getKeyPrefix(key) |
|
|
if (value === undefined) return false |
|
|
const store = this.store |
|
|
if (ttl === undefined) ttl = this.ttl |
|
|
return Promise.resolve().then(() => store.delete(keyPrefixed)) |
|
|
if (ttl === 0) ttl = undefined |
|
|
|
|
|
const expires = typeof ttl === 'number' ? Date.now() + ttl : null |
|
|
|
|
|
const valueSerialized = await this.serialize({ value, expires }) |
|
|
|
|
|
await this.store.set(this._getKeyPrefix(key), valueSerialized, ttl) |
|
|
|
|
|
return true |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
clear () { |
|
|
async delete (key) { |
|
|
if (!this.options.namespace) { |
|
|
return this.store.delete(this._getKeyPrefix(key)) |
|
|
return Promise.resolve().then(() => undefined) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const store = this.store |
|
|
async clear () { |
|
|
return Promise.resolve().then(() => store.clear()) |
|
|
if (!this.namespace) return undefined |
|
|
|
|
|
return this.store.clear() |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
module.exports = Keyv |
|
|
module.exports = Keyv |
|
|