Socket
Socket
Sign inDemoInstall

keyv

Package Overview
Dependencies
Maintainers
2
Versions
55
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

keyv - npm Package Compare versions

Comparing version 4.1.1 to 4.2.0

src/index.d.ts

102

package.json
{
"name": "keyv",
"version": "4.1.1",
"description": "Simple key-value storage with support for multiple backends",
"main": "src/index.js",
"scripts": {
"test": "xo && nyc ava --serial",
"coverage": "nyc report --reporter=text-lcov > coverage.lcov",
"clean": "rm -rf node_modules && rm -rf .nyc_output && rm -rf coverage.lcov && rm -rf ./test/testdb.sqlite"
},
"xo": {
"extends": "xo-lukechilds",
"rules": {
"unicorn/prefer-module": 0
}
},
"repository": {
"type": "git",
"url": "git+https://github.com/jaredwray/keyv.git"
},
"keywords": [
"key",
"value",
"store",
"cache",
"ttl"
],
"author": "Jared Wray <me@jaredwray.com> (http://jaredwray.com)",
"license": "MIT",
"bugs": {
"url": "https://github.com/jaredwray/keyv/issues"
},
"homepage": "https://github.com/jaredwray/keyv",
"dependencies": {
"json-buffer": "3.0.1"
},
"devDependencies": {
"@keyv/test-suite": "*",
"ava": "^4.0.1",
"eslint-config-xo-lukechilds": "^1.0.1",
"eslint-plugin-promise": "^6.0.0",
"nyc": "^15.1.0",
"pify": "5.0.0",
"this": "^1.1.0",
"timekeeper": "^2.2.0",
"xo": "^0.47.0"
}
"name": "keyv",
"version": "4.2.0",
"description": "Simple key-value storage with support for multiple backends",
"main": "src/index.js",
"scripts": {
"test": "xo && nyc ava --serial",
"coverage": "nyc report --reporter=text-lcov > coverage.lcov",
"clean": "rm -rf node_modules && rm -rf .nyc_output && rm -rf coverage.lcov && rm -rf ./test/testdb.sqlite"
},
"xo": {
"extends": "xo-lukechilds",
"rules": {
"unicorn/prefer-module": 0
}
},
"repository": {
"type": "git",
"url": "git+https://github.com/jaredwray/keyv.git"
},
"keywords": [
"key",
"value",
"store",
"cache",
"ttl"
],
"author": "Jared Wray <me@jaredwray.com> (http://jaredwray.com)",
"license": "MIT",
"bugs": {
"url": "https://github.com/jaredwray/keyv/issues"
},
"homepage": "https://github.com/jaredwray/keyv",
"dependencies": {
"compress-brotli": "^1.3.6",
"json-buffer": "3.0.1"
},
"devDependencies": {
"@keyv/test-suite": "*",
"ava": "^4.1.0",
"eslint-config-xo-lukechilds": "^1.0.1",
"eslint-plugin-promise": "^6.0.0",
"nyc": "^15.1.0",
"pify": "5.0.0",
"this": "^1.1.0",
"timekeeper": "^2.2.0",
"tsd": "^0.20.0",
"typescript": "^4.6.3",
"xo": "^0.48.0"
},
"tsd" : {
"directory" : "test"
},
"types": "./src/index.d.ts",
"files": [
"src"
]
}

@@ -5,8 +5,4 @@ 'use strict';

const JSONB = require('json-buffer');
const compressBrotli = require('compress-brotli');
// eslint-disable-next-line no-extend-native
BigInt.prototype.toJSON = function () {
return this.toString();
};
const loadStore = options => {

@@ -31,20 +27,35 @@ const adapters = {

const iterableAdapters = [
'sqlite',
'postgres',
'mysql',
'mongo',
'redis',
];
class Keyv extends EventEmitter {
constructor(uri, options) {
super();
this.opts = Object.assign(
{
namespace: 'keyv',
serialize: JSONB.stringify,
deserialize: JSONB.parse,
},
(typeof uri === 'string') ? { uri } : uri,
options,
);
this.opts = {
namespace: 'keyv',
serialize: JSONB.stringify,
deserialize: JSONB.parse,
...((typeof uri === 'string') ? { uri } : uri),
...options,
};
if (!this.opts.store) {
const adapterOptions = Object.assign({}, this.opts);
const adapterOptions = { ...this.opts };
this.opts.store = loadStore(adapterOptions);
}
if (this.opts.compress) {
const brotli = compressBrotli(this.opts.compress.opts);
this.opts.serialize = async ({ value, expires }) => brotli.serialize({ value: await brotli.compress(value), expires });
this.opts.deserialize = async data => {
const { value, expires } = brotli.deserialize(data);
return { value: await brotli.decompress(value), expires };
};
}
if (typeof this.opts.store.on === 'function') {

@@ -55,4 +66,36 @@ this.opts.store.on('error', error => this.emit('error', error));

this.opts.store.namespace = this.opts.namespace;
const generateIterator = iterator =>
async function * () {
for await (const [key, raw] of typeof iterator === 'function'
? iterator(this.opts.store.namespace)
: iterator) {
const data = typeof raw === 'string' ? this.opts.deserialize(raw) : raw;
if (this.opts.store.namespace && !key.includes(this.opts.store.namespace)) {
continue;
}
if (typeof data.expires === 'number' && Date.now() > data.expires) {
this.delete(key);
continue;
}
yield [this._getKeyUnprefix(key), data.value];
}
};
// Attach iterators
if (typeof this.opts.store[Symbol.iterator] === 'function' && this.opts.store instanceof Map) {
this.iterator = generateIterator(this.opts.store);
} else if (typeof this.opts.store.iterator === 'function' && this.opts.store.opts
&& this._checkIterableAdaptar()) {
this.iterator = generateIterator(this.opts.store.iterator.bind(this.opts.store));
}
}
_checkIterableAdaptar() {
return iterableAdapters.includes(this.opts.store.opts.dialect)
|| iterableAdapters.findIndex(element => this.opts.store.opts.url.includes(element)) >= 0;
}
_getKeyPrefix(key) {

@@ -62,9 +105,55 @@ return `${this.opts.namespace}:${key}`;

_getKeyPrefixArray(keys) {
return keys.map(key => `${this.opts.namespace}:${key}`);
}
_getKeyUnprefix(key) {
return this.opts.store.namespace
? key
.split(':')
.splice(1)
.join(':')
: key;
}
get(key, options) {
const keyPrefixed = this._getKeyPrefix(key);
const { store } = this.opts;
const isArray = Array.isArray(key);
const keyPrefixed = isArray ? this._getKeyPrefixArray(key) : this._getKeyPrefix(key);
if (isArray && store.getMany === undefined) {
const promises = [];
for (const key of keyPrefixed) {
promises.push(Promise.resolve()
.then(() => store.get(key))
.then(data => (typeof data === 'string') ? this.opts.deserialize(data) : data)
.then(data => {
if (data === undefined || data === null) {
return undefined;
}
if (typeof data.expires === 'number' && Date.now() > data.expires) {
return this.delete(key).then(() => undefined);
}
return (options && options.raw) ? data : data.value;
}),
);
}
return Promise.allSettled(promises)
.then(values => {
const data = [];
for (const value of values) {
data.push(value.value);
}
return data.every(x => x === undefined) ? [] : data;
});
}
return Promise.resolve()
.then(() => store.get(keyPrefixed))
.then(() => isArray ? store.getMany(keyPrefixed) : store.get(keyPrefixed))
.then(data => (typeof data === 'string') ? this.opts.deserialize(data) : data)
.then(data => {
// Console.log('get', data);
if (data === undefined || data === null) {

@@ -74,5 +163,31 @@ return undefined;

if (isArray) {
const result = [];
if (data.length === 0) {
return [];
}
for (let row of data) {
if ((typeof row === 'string')) {
row = this.opts.deserialize(row);
}
if (row === undefined || row === null) {
result.push(undefined);
continue;
}
if (typeof row.expires === 'number' && Date.now() > row.expires) {
this.delete(key).then(() => undefined);
result.push(undefined);
} else {
result.push((options && options.raw) ? row : row.value);
}
}
return result.every(x => x === undefined) ? [] : result;
}
if (typeof data.expires === 'number' && Date.now() > data.expires) {
this.delete(key);
return undefined;
return this.delete(key).then(() => undefined);
}

@@ -111,4 +226,20 @@

delete(key) {
const { store } = this.opts;
if (Array.isArray(key)) {
const keyPrefixed = this._getKeyPrefixArray(key);
if (store.deleteMany === undefined) {
const promises = [];
for (const key of keyPrefixed) {
promises.push(store.delete(key));
}
return Promise.allSettled(promises)
.then(values => values.every(x => x.value === true));
}
return Promise.resolve()
.then(() => store.deleteMany(keyPrefixed));
}
const keyPrefixed = this._getKeyPrefix(key);
const { store } = this.opts;
return Promise.resolve()

@@ -123,4 +254,18 @@ .then(() => store.delete(keyPrefixed));

}
has(key) {
const keyPrefixed = this._getKeyPrefix(key);
const { store } = this.opts;
return Promise.resolve()
.then(async () => {
if (typeof store.has === 'function') {
return store.has(keyPrefixed);
}
const value = await store.get(keyPrefixed);
return value !== undefined;
});
}
}
module.exports = Keyv;
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc