keyv 4.2.0 → 4.2.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keyv",
3
- "version": "4.2.0",
3
+ "version": "4.2.5",
4
4
  "description": "Simple key-value storage with support for multiple backends",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -9,9 +9,9 @@
9
9
  "clean": "rm -rf node_modules && rm -rf .nyc_output && rm -rf coverage.lcov && rm -rf ./test/testdb.sqlite"
10
10
  },
11
11
  "xo": {
12
- "extends": "xo-lukechilds",
13
12
  "rules": {
14
- "unicorn/prefer-module": 0
13
+ "unicorn/prefer-module": 0,
14
+ "unicorn/prefer-node-protocol": 0
15
15
  }
16
16
  },
17
17
  "repository": {
@@ -32,20 +32,19 @@
32
32
  },
33
33
  "homepage": "https://github.com/jaredwray/keyv",
34
34
  "dependencies": {
35
- "compress-brotli": "^1.3.6",
35
+ "compress-brotli": "^1.3.8",
36
36
  "json-buffer": "3.0.1"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@keyv/test-suite": "*",
40
- "ava": "^4.1.0",
41
- "eslint-config-xo-lukechilds": "^1.0.1",
40
+ "ava": "^4.2.0",
42
41
  "eslint-plugin-promise": "^6.0.0",
43
42
  "nyc": "^15.1.0",
44
43
  "pify": "5.0.0",
45
44
  "this": "^1.1.0",
46
45
  "timekeeper": "^2.2.0",
47
46
  "tsd": "^0.20.0",
48
- "typescript": "^4.6.3",
47
+ "typescript": "^4.6.4",
49
48
  "xo": "^0.48.0"
50
49
  },
51
50
  "tsd" : {
package/src/index.d.ts CHANGED
@@ -1,20 +1,88 @@
1
- import EventEmitter from 'node:events';
1
+ import {EventEmitter} from 'events';
2
2
 
3
- declare class Keyv extends EventEmitter {
4
- constructor(uri: string, options: Keyv.Options);
5
- get(key: string, options: any): Promise<any>;
6
- set(key: string, value: any, ttl: number): Promise<boolean>;
7
- delete(key: string): Promise<boolean>;
3
+ type WithRequiredProperties<T, K extends keyof T> = T & Required<Pick<T, K>>;
4
+
5
+ declare class Keyv<Value = any, Options extends Record<string, any> = Record<string, unknown>> extends EventEmitter {
6
+ /**
7
+ * `this.opts` is an object containing at least the properties listed
8
+ * below. However, `Keyv.Options` allows arbitrary properties as well.
9
+ * These properties can be specified as the second type parameter to `Keyv`.
10
+ */
11
+ opts: WithRequiredProperties<
12
+ Keyv.Options<Value>,
13
+ 'deserialize' | 'namespace' | 'serialize' | 'store' | 'uri'
14
+ > &
15
+ Options;
16
+
17
+ /**
18
+ * @param opts The options object is also passed through to the storage adapter. Check your storage adapter docs for any extra options.
19
+ */
20
+ constructor(options?: Keyv.Options<Value> & Options);
21
+ /**
22
+ * @param uri The connection string URI.
23
+ *
24
+ * Merged into the options object as options.uri.
25
+ * @param opts The options object is also passed through to the storage adapter. Check your storage adapter docs for any extra options.
26
+ */
27
+ constructor(uri?: string, options?: Keyv.Options<Value> & Options);
28
+
29
+ /** Returns the value. */
30
+ get<Raw extends boolean = false>(key: string | string[] = [], options?: {raw?: Raw}):
31
+ Promise<(Raw extends false
32
+ ? Value
33
+ : Keyv.DeserializedData<Value>) | undefined>;
34
+ /**
35
+ * Set a value.
36
+ *
37
+ * By default keys are persistent. You can set an expiry TTL in milliseconds.
38
+ */
39
+ set(key: string, value: Value, ttl?: number): Promise<true>;
40
+ /**
41
+ * Deletes an entry.
42
+ *
43
+ * Returns `true` if the key existed, `false` if not.
44
+ */
45
+ delete(key: string | string[] = []): Promise<boolean>;
46
+ /** Delete all entries in the current namespace. */
8
47
  clear(): Promise<void>;
48
+ /** Check if key exists in current namespace. */
9
49
  has(key: string): Promise<boolean>;
50
+ /** Iterator */
51
+ iterator(namespace: string | undefined): AsyncGenerator<any, void, any>;
10
52
  }
11
53
 
12
54
  declare namespace Keyv {
13
- interface Options {
55
+ interface Options<Value> {
56
+ [key: string]: any;
57
+
58
+ /** Namespace for the current instance. */
14
59
  namespace?: string | undefined;
15
- serialize?: ((data: any) => string) | undefined;
16
- deserialize?: ((data: string) => any | undefined) | undefined;
60
+ /** A custom serialization function. */
61
+ serialize?: ((data: DeserializedData<Value>) => string) | undefined;
62
+ /** A custom deserialization function. */
63
+ deserialize?: ((data: string) => DeserializedData<Value> | undefined) | undefined;
64
+ /** The connection string URI. */
65
+ uri?: string | undefined;
66
+ /** The storage adapter instance to be used by Keyv. */
67
+ store?: Store<Value> | undefined;
68
+ /** Default TTL. Can be overridden by specififying a TTL on `.set()`. */
17
69
  ttl?: number | undefined;
70
+ /** Specify an adapter to use. e.g `'redis'` or `'mongodb'`. */
71
+ adapter?: 'redis' | 'mongodb' | 'mongo' | 'sqlite' | 'postgresql' | 'postgres' | 'mysql' | undefined;
72
+ /** Enable compression option **/
73
+ compress?: Record<string, unknown> | undefined;
74
+ }
75
+
76
+ interface DeserializedData<Value> {
77
+ value: Value; expires: number | undefined;
78
+ }
79
+
80
+ interface Store<Value> {
81
+ get(key: string): Value | Promise<Value | undefined> | undefined;
82
+ set(key: string, value: Value, ttl?: number): any;
83
+ delete(key: string): boolean | Promise<boolean>;
84
+ clear(): void | Promise<void>;
85
+ has(key: string): boolean | Promise<boolean>;
18
86
  }
19
87
  }
20
88
 
package/src/index.js CHANGED
@@ -14,9 +14,11 @@ const loadStore = options => {
14
14
  postgres: '@keyv/postgres',
15
15
  mysql: '@keyv/mysql',
16
16
  etcd: '@keyv/etcd',
17
+ offline: '@keyv/offline',
18
+ tiered: '@keyv/tiered',
17
19
  };
18
20
  if (options.adapter || options.uri) {
19
- const adapter = options.adapter || /^[^:]*/.exec(options.uri)[0];
21
+ const adapter = options.adapter || /^[^:+]*/.exec(options.uri)[0];
20
22
  return new (require(adapters[adapter]))(options);
21
23
  }
22
24
 
@@ -29,6 +31,7 @@ const iterableAdapters = [
29
31
  'mysql',
30
32
  'mongo',
31
33
  'redis',
34
+ 'tiered',
32
35
  ];
33
36
 
34
37
  class Keyv extends EventEmitter {
@@ -38,21 +41,21 @@ class Keyv extends EventEmitter {
38
41
  namespace: 'keyv',
39
42
  serialize: JSONB.stringify,
40
43
  deserialize: JSONB.parse,
41
- ...((typeof uri === 'string') ? { uri } : uri),
44
+ ...((typeof uri === 'string') ? {uri} : uri),
42
45
  ...options,
43
46
  };
44
47
 
45
48
  if (!this.opts.store) {
46
- const adapterOptions = { ...this.opts };
49
+ const adapterOptions = {...this.opts};
47
50
  this.opts.store = loadStore(adapterOptions);
48
51
  }
49
52
 
50
53
  if (this.opts.compress) {
51
54
  const brotli = compressBrotli(this.opts.compress.opts);
52
- this.opts.serialize = async ({ value, expires }) => brotli.serialize({ value: await brotli.compress(value), expires });
55
+ this.opts.serialize = async ({value, expires}) => brotli.serialize({value: await brotli.compress(value), expires});
53
56
  this.opts.deserialize = async data => {
54
- const { value, expires } = brotli.deserialize(data);
55
- return { value: await brotli.decompress(value), expires };
57
+ const {value, expires} = brotli.deserialize(data);
58
+ return {value: await brotli.decompress(value), expires};
56
59
  };
57
60
  }
58
61
 
@@ -62,24 +65,23 @@ class Keyv extends EventEmitter {
62
65
 
63
66
  this.opts.store.namespace = this.opts.namespace;
64
67
 
65
- const generateIterator = iterator =>
66
- async function * () {
67
- for await (const [key, raw] of typeof iterator === 'function'
68
- ? iterator(this.opts.store.namespace)
69
- : iterator) {
70
- const data = typeof raw === 'string' ? this.opts.deserialize(raw) : raw;
71
- if (this.opts.store.namespace && !key.includes(this.opts.store.namespace)) {
72
- continue;
73
- }
74
-
75
- if (typeof data.expires === 'number' && Date.now() > data.expires) {
76
- this.delete(key);
77
- continue;
78
- }
68
+ const generateIterator = iterator => async function * () {
69
+ for await (const [key, raw] of typeof iterator === 'function'
70
+ ? iterator(this.opts.store.namespace)
71
+ : iterator) {
72
+ const data = this.opts.deserialize(raw);
73
+ if (this.opts.store.namespace && !key.includes(this.opts.store.namespace)) {
74
+ continue;
75
+ }
79
76
 
80
- yield [this._getKeyUnprefix(key), data.value];
77
+ if (typeof data.expires === 'number' && Date.now() > data.expires) {
78
+ this.delete(key);
79
+ continue;
81
80
  }
82
- };
81
+
82
+ yield [this._getKeyUnprefix(key), data.value];
83
+ }
84
+ };
83
85
 
84
86
  // Attach iterators
85
87
  if (typeof this.opts.store[Symbol.iterator] === 'function' && this.opts.store instanceof Map) {
@@ -104,16 +106,14 @@ class Keyv extends EventEmitter {
104
106
  }
105
107
 
106
108
  _getKeyUnprefix(key) {
107
- return this.opts.store.namespace
108
- ? key
109
- .split(':')
110
- .splice(1)
111
- .join(':')
112
- : key;
109
+ return key
110
+ .split(':')
111
+ .splice(1)
112
+ .join(':');
113
113
  }
114
114
 
115
115
  get(key, options) {
116
- const { store } = this.opts;
116
+ const {store} = this.opts;
117
117
  const isArray = Array.isArray(key);
118
118
  const keyPrefixed = isArray ? this._getKeyPrefixArray(key) : this._getKeyPrefix(key);
119
119
  if (isArray && store.getMany === undefined) {
@@ -151,13 +151,13 @@ class Keyv extends EventEmitter {
151
151
  .then(() => isArray ? store.getMany(keyPrefixed) : store.get(keyPrefixed))
152
152
  .then(data => (typeof data === 'string') ? this.opts.deserialize(data) : data)
153
153
  .then(data => {
154
- // Console.log('get', data);
155
154
  if (data === undefined || data === null) {
156
155
  return undefined;
157
156
  }
158
157
 
159
158
  if (isArray) {
160
159
  const result = [];
160
+
161
161
  if (data.length === 0) {
162
162
  return [];
163
163
  }
@@ -201,7 +201,7 @@ class Keyv extends EventEmitter {
201
201
  ttl = undefined;
202
202
  }
203
203
 
204
- const { store } = this.opts;
204
+ const {store} = this.opts;
205
205
 
206
206
  return Promise.resolve()
207
207
  .then(() => {
@@ -210,7 +210,7 @@ class Keyv extends EventEmitter {
210
210
  this.emit('error', 'symbol cannot be serialized');
211
211
  }
212
212
 
213
- value = { value, expires };
213
+ value = {value, expires};
214
214
  return this.opts.serialize(value);
215
215
  })
216
216
  .then(value => store.set(keyPrefixed, value, ttl))
@@ -218,7 +218,7 @@ class Keyv extends EventEmitter {
218
218
  }
219
219
 
220
220
  delete(key) {
221
- const { store } = this.opts;
221
+ const {store} = this.opts;
222
222
  if (Array.isArray(key)) {
223
223
  const keyPrefixed = this._getKeyPrefixArray(key);
224
224
  if (store.deleteMany === undefined) {
@@ -241,14 +241,14 @@ class Keyv extends EventEmitter {
241
241
  }
242
242
 
243
243
  clear() {
244
- const { store } = this.opts;
244
+ const {store} = this.opts;
245
245
  return Promise.resolve()
246
246
  .then(() => store.clear());
247
247
  }
248
248
 
249
249
  has(key) {
250
250
  const keyPrefixed = this._getKeyPrefix(key);
251
- const { store } = this.opts;
251
+ const {store} = this.opts;
252
252
  return Promise.resolve()
253
253
  .then(async () => {
254
254
  if (typeof store.has === 'function') {
@@ -259,6 +259,13 @@ class Keyv extends EventEmitter {
259
259
  return value !== undefined;
260
260
  });
261
261
  }
262
+
263
+ disconnect() {
264
+ const {store} = this.opts;
265
+ if (typeof store.disconnect === 'function') {
266
+ return store.disconnect();
267
+ }
268
+ }
262
269
  }
263
270
 
264
271
  module.exports = Keyv;