keyv 5.0.3 → 5.1.1

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/README.md CHANGED
@@ -50,6 +50,36 @@ First, create a new Keyv instance.
50
50
  import Keyv from 'keyv';
51
51
  ```
52
52
 
53
+ ### Type-safe Usage
54
+
55
+ You can create a `Keyv` instance with a generic type to enforce type safety for the values stored. Additionally, both the `get` and `set` methods support specifying custom types for specific use cases.
56
+
57
+ #### Example with Instance-level Generic Type:
58
+
59
+ ```ts
60
+ const keyv = new Keyv<number>(); // Instance handles only numbers
61
+ await keyv.set('key1', 123);
62
+ const value = await keyv.get('key1'); // value is inferred as number
63
+ ```
64
+
65
+ #### Example with Method-level Generic Type:
66
+
67
+ You can also specify a type directly in the `get` or `set` methods, allowing flexibility for different types of values within the same instance.
68
+
69
+ ```ts
70
+ const keyv = new Keyv(); // Generic type not specified at instance level
71
+
72
+ await keyv.set<string>('key2', 'some string'); // Method-level type for this value
73
+ const strValue = await keyv.get<string>('key2'); // Explicitly typed as string
74
+
75
+ await keyv.set<number>('key3', 456); // Storing a number in the same instance
76
+ const numValue = await keyv.get<number>('key3'); // Explicitly typed as number
77
+ ```
78
+
79
+ This makes `Keyv` highly adaptable to different data types while maintaining type safety.
80
+
81
+ ### Using Storage Adapters
82
+
53
83
  Once you have created your Keyv instance you can use it as a simple key-value store with `in-memory` by default. To use a storage adapter, create an instance of the adapter and pass it to the Keyv constructor. Here are some examples:
54
84
 
55
85
  ```js
@@ -191,6 +221,7 @@ The official storage adapters are covered by [over 150 integration tests](https:
191
221
  Database | Adapter | Native TTL
192
222
  ---|---|---
193
223
  Redis | [@keyv/redis](https://github.com/jaredwray/keyv/tree/master/packages/redis) | Yes
224
+ Valkey | [@keyv/valkey](https://github.com/jaredwray/keyv/tree/master/packages/valkey) | Yes
194
225
  MongoDB | [@keyv/mongo](https://github.com/jaredwray/keyv/tree/master/packages/mongo) | Yes
195
226
  SQLite | [@keyv/sqlite](https://github.com/jaredwray/keyv/tree/master/packages/sqlite) | No
196
227
  PostgreSQL | [@keyv/postgres](https://github.com/jaredwray/keyv/tree/master/packages/postgres) | No
@@ -326,6 +357,13 @@ The connection string URI.
326
357
 
327
358
  Merged into the options object as options.uri.
328
359
 
360
+ ### .namespace
361
+
362
+ Type: `String`
363
+ Default: `'keyv'`
364
+
365
+ This is the namespace for the current instance. When you set it it will set it also on the storage adapter. This is the preferred way to set the namespace over `.opts.namespace`.
366
+
329
367
  ### options
330
368
 
331
369
  Type: `Object`
@@ -434,4 +472,4 @@ We welcome contributions to Keyv! 🎉 Here are some guides to get you started w
434
472
 
435
473
  # License
436
474
 
437
- [MIT © Jared Wray](LICENSE)
475
+ [MIT © Jared Wray](LICENSE)
package/dist/index.cjs CHANGED
@@ -275,6 +275,23 @@ var Keyv = class extends event_manager_default {
275
275
  this.stats.enabled = this.opts.stats;
276
276
  }
277
277
  }
278
+ /**
279
+ * Get the current namespace.
280
+ * @returns {string | undefined} The current namespace.
281
+ */
282
+ get namespace() {
283
+ return this.opts.namespace;
284
+ }
285
+ /**
286
+ * Set the current namespace.
287
+ * @param {string | undefined} namespace The namespace to set.
288
+ */
289
+ set namespace(namespace) {
290
+ this.opts.namespace = namespace;
291
+ if (this.opts.store) {
292
+ this.opts.store.namespace = namespace;
293
+ }
294
+ }
278
295
  generateIterator(iterator) {
279
296
  const function_ = async function* () {
280
297
  for await (const [key, raw] of typeof iterator === "function" ? iterator(this.opts.store.namespace) : iterator) {
@@ -389,10 +406,10 @@ var Keyv = class extends event_manager_default {
389
406
  if (typeof value === "symbol") {
390
407
  this.emit("error", "symbol cannot be serialized");
391
408
  }
392
- value = { value, expires };
393
- value = await this.opts.serialize(value);
394
- await store.set(keyPrefixed, value, ttl);
395
- this.hooks.trigger("postSet" /* POST_SET */, { key: keyPrefixed, value, ttl });
409
+ const formattedValue = { value, expires };
410
+ const serializedValue = await this.opts.serialize(formattedValue);
411
+ await store.set(keyPrefixed, serializedValue, ttl);
412
+ this.hooks.trigger("postSet" /* POST_SET */, { key: keyPrefixed, value: serializedValue, ttl });
396
413
  this.stats.set();
397
414
  return true;
398
415
  }
package/dist/index.d.cts CHANGED
@@ -41,7 +41,7 @@ declare class StatsManager extends EventManager {
41
41
 
42
42
  type DeserializedData<Value> = {
43
43
  value?: Value;
44
- expires?: number;
44
+ expires?: number | null;
45
45
  };
46
46
  interface CompressionAdapter {
47
47
  compress(value: any, options?: any): Promise<any>;
@@ -100,32 +100,42 @@ type KeyvOptions_ = Omit<KeyvOptions, 'store'> & {
100
100
  store: KeyvStoreAdapter | Map<any, any> & KeyvStoreAdapter;
101
101
  };
102
102
  type IteratorFunction = (argument: any) => AsyncGenerator<any, void>;
103
- declare class Keyv extends EventManager {
103
+ declare class Keyv<GenericValue = any> extends EventManager {
104
104
  opts: KeyvOptions_;
105
105
  iterator?: IteratorFunction;
106
106
  hooks: HooksManager;
107
107
  stats: StatsManager;
108
108
  constructor(store?: KeyvStoreAdapter | KeyvOptions | Map<any, any>, options?: Omit<KeyvOptions, 'store'>);
109
109
  constructor(options?: KeyvOptions);
110
+ /**
111
+ * Get the current namespace.
112
+ * @returns {string | undefined} The current namespace.
113
+ */
114
+ get namespace(): string | undefined;
115
+ /**
116
+ * Set the current namespace.
117
+ * @param {string | undefined} namespace The namespace to set.
118
+ */
119
+ set namespace(namespace: string | undefined);
110
120
  generateIterator(iterator: IteratorFunction): IteratorFunction;
111
121
  _checkIterableAdapter(): boolean;
112
122
  _getKeyPrefix(key: string): string;
113
123
  _getKeyPrefixArray(keys: string[]): string[];
114
124
  _getKeyUnprefix(key: string): string;
115
125
  _isValidStorageAdapter(store: KeyvStoreAdapter | any): boolean;
116
- get<Value>(key: string, options?: {
126
+ get<Value = GenericValue>(key: string, options?: {
117
127
  raw: false;
118
128
  }): Promise<StoredDataNoRaw<Value>>;
119
- get<Value>(key: string, options?: {
129
+ get<Value = GenericValue>(key: string, options?: {
120
130
  raw: true;
121
131
  }): Promise<StoredDataRaw<Value>>;
122
- get<Value>(key: string[], options?: {
132
+ get<Value = GenericValue>(key: string[], options?: {
123
133
  raw: false;
124
134
  }): Promise<Array<StoredDataNoRaw<Value>>>;
125
- get<Value>(key: string[], options?: {
135
+ get<Value = GenericValue>(key: string[], options?: {
126
136
  raw: true;
127
137
  }): Promise<Array<StoredDataRaw<Value>>>;
128
- set(key: string, value: any, ttl?: number): Promise<boolean>;
138
+ set<Value = GenericValue>(key: string, value: Value, ttl?: number): Promise<boolean>;
129
139
  delete(key: string | string[]): Promise<boolean>;
130
140
  clear(): Promise<void>;
131
141
  has(key: string): Promise<boolean>;
package/dist/index.d.ts CHANGED
@@ -41,7 +41,7 @@ declare class StatsManager extends EventManager {
41
41
 
42
42
  type DeserializedData<Value> = {
43
43
  value?: Value;
44
- expires?: number;
44
+ expires?: number | null;
45
45
  };
46
46
  interface CompressionAdapter {
47
47
  compress(value: any, options?: any): Promise<any>;
@@ -100,32 +100,42 @@ type KeyvOptions_ = Omit<KeyvOptions, 'store'> & {
100
100
  store: KeyvStoreAdapter | Map<any, any> & KeyvStoreAdapter;
101
101
  };
102
102
  type IteratorFunction = (argument: any) => AsyncGenerator<any, void>;
103
- declare class Keyv extends EventManager {
103
+ declare class Keyv<GenericValue = any> extends EventManager {
104
104
  opts: KeyvOptions_;
105
105
  iterator?: IteratorFunction;
106
106
  hooks: HooksManager;
107
107
  stats: StatsManager;
108
108
  constructor(store?: KeyvStoreAdapter | KeyvOptions | Map<any, any>, options?: Omit<KeyvOptions, 'store'>);
109
109
  constructor(options?: KeyvOptions);
110
+ /**
111
+ * Get the current namespace.
112
+ * @returns {string | undefined} The current namespace.
113
+ */
114
+ get namespace(): string | undefined;
115
+ /**
116
+ * Set the current namespace.
117
+ * @param {string | undefined} namespace The namespace to set.
118
+ */
119
+ set namespace(namespace: string | undefined);
110
120
  generateIterator(iterator: IteratorFunction): IteratorFunction;
111
121
  _checkIterableAdapter(): boolean;
112
122
  _getKeyPrefix(key: string): string;
113
123
  _getKeyPrefixArray(keys: string[]): string[];
114
124
  _getKeyUnprefix(key: string): string;
115
125
  _isValidStorageAdapter(store: KeyvStoreAdapter | any): boolean;
116
- get<Value>(key: string, options?: {
126
+ get<Value = GenericValue>(key: string, options?: {
117
127
  raw: false;
118
128
  }): Promise<StoredDataNoRaw<Value>>;
119
- get<Value>(key: string, options?: {
129
+ get<Value = GenericValue>(key: string, options?: {
120
130
  raw: true;
121
131
  }): Promise<StoredDataRaw<Value>>;
122
- get<Value>(key: string[], options?: {
132
+ get<Value = GenericValue>(key: string[], options?: {
123
133
  raw: false;
124
134
  }): Promise<Array<StoredDataNoRaw<Value>>>;
125
- get<Value>(key: string[], options?: {
135
+ get<Value = GenericValue>(key: string[], options?: {
126
136
  raw: true;
127
137
  }): Promise<Array<StoredDataRaw<Value>>>;
128
- set(key: string, value: any, ttl?: number): Promise<boolean>;
138
+ set<Value = GenericValue>(key: string, value: Value, ttl?: number): Promise<boolean>;
129
139
  delete(key: string | string[]): Promise<boolean>;
130
140
  clear(): Promise<void>;
131
141
  has(key: string): Promise<boolean>;
package/dist/index.js CHANGED
@@ -249,6 +249,23 @@ var Keyv = class extends event_manager_default {
249
249
  this.stats.enabled = this.opts.stats;
250
250
  }
251
251
  }
252
+ /**
253
+ * Get the current namespace.
254
+ * @returns {string | undefined} The current namespace.
255
+ */
256
+ get namespace() {
257
+ return this.opts.namespace;
258
+ }
259
+ /**
260
+ * Set the current namespace.
261
+ * @param {string | undefined} namespace The namespace to set.
262
+ */
263
+ set namespace(namespace) {
264
+ this.opts.namespace = namespace;
265
+ if (this.opts.store) {
266
+ this.opts.store.namespace = namespace;
267
+ }
268
+ }
252
269
  generateIterator(iterator) {
253
270
  const function_ = async function* () {
254
271
  for await (const [key, raw] of typeof iterator === "function" ? iterator(this.opts.store.namespace) : iterator) {
@@ -363,10 +380,10 @@ var Keyv = class extends event_manager_default {
363
380
  if (typeof value === "symbol") {
364
381
  this.emit("error", "symbol cannot be serialized");
365
382
  }
366
- value = { value, expires };
367
- value = await this.opts.serialize(value);
368
- await store.set(keyPrefixed, value, ttl);
369
- this.hooks.trigger("postSet" /* POST_SET */, { key: keyPrefixed, value, ttl });
383
+ const formattedValue = { value, expires };
384
+ const serializedValue = await this.opts.serialize(formattedValue);
385
+ await store.set(keyPrefixed, serializedValue, ttl);
386
+ this.hooks.trigger("postSet" /* POST_SET */, { key: keyPrefixed, value: serializedValue, ttl });
370
387
  this.stats.set();
371
388
  return true;
372
389
  }
package/package.json CHANGED
@@ -1,95 +1,99 @@
1
1
  {
2
- "name": "keyv",
3
- "version": "5.0.3",
4
- "description": "Simple key-value storage with support for multiple backends",
5
- "type": "module",
6
- "main": "dist/index.cjs",
7
- "module": "dist/index.js",
8
- "types": "dist/index.d.ts",
9
- "exports": {
10
- ".": {
11
- "require": "./dist/index.cjs",
12
- "import": "./dist/index.js"
13
- }
14
- },
15
- "scripts": {
16
- "build": "rimraf ./dist && tsup src/index.ts --format cjs,esm --dts --clean",
17
- "prepare": "yarn build",
18
- "test": "xo --fix && vitest run --coverage",
19
- "test:ci": "xo && vitest --run --sequence.setupFiles=list",
20
- "clean": "rimraf ./node_modules ./coverage ./test/testdb.sqlite ./dist"
21
- },
22
- "xo": {
23
- "rules": {
24
- "import/no-named-as-default": "off",
25
- "unicorn/prefer-module": "off",
26
- "unicorn/prefer-node-protocol": "off",
27
- "@typescript-eslint/consistent-type-definitions": "off",
28
- "unicorn/no-typeof-undefined": "off",
29
- "unicorn/prefer-event-target": "off",
30
- "import/no-extraneous-dependencies": "off",
31
- "import/extensions": "off",
32
- "@typescript-eslint/ban-ts-comment": "off",
33
- "@typescript-eslint/no-unsafe-call": "off",
34
- "@typescript-eslint/no-for-in-array": "off",
35
- "guard-for-in": "off",
36
- "no-await-in-loop": "off",
37
- "@typescript-eslint/no-unsafe-return": "off",
38
- "@typescript-eslint/no-unsafe-assignment": "off",
39
- "@typescript-eslint/no-unsafe-argument": "off",
40
- "@typescript-eslint/naming-convention": "off",
41
- "@typescript-eslint/consistent-type-assertions": "off",
42
- "@typescript-eslint/no-confusing-void-expression": "off",
43
- "@typescript-eslint/no-var-requires": "off",
44
- "@typescript-eslint/prefer-ts-expect-error": "off"
45
- }
46
- },
47
- "repository": {
48
- "type": "git",
49
- "url": "git+https://github.com/jaredwray/keyv.git"
50
- },
51
- "keywords": [
52
- "key",
53
- "value",
54
- "store",
55
- "cache",
56
- "ttl",
57
- "key-value",
58
- "storage",
59
- "backend",
60
- "adapter",
61
- "redis",
62
- "mongodb",
63
- "sqlite",
64
- "mysql",
65
- "postgresql",
66
- "memory",
67
- "node-cache",
68
- "lru-cache",
69
- "lru",
70
- "cache-manager"
71
- ],
72
- "author": "Jared Wray <me@jaredwray.com> (http://jaredwray.com)",
73
- "license": "MIT",
74
- "bugs": {
75
- "url": "https://github.com/jaredwray/keyv/issues"
76
- },
77
- "homepage": "https://github.com/jaredwray/keyv",
78
- "dependencies": {
79
- "@keyv/serialize": "*"
80
- },
81
- "devDependencies": {
82
- "@keyv/test-suite": "*",
83
- "rimraf": "^6.0.1",
84
- "timekeeper": "^2.3.1",
85
- "tsd": "^0.31.2",
86
- "xo": "^0.59.3"
87
- },
88
- "tsd": {
89
- "directory": "test"
90
- },
91
- "files": [
92
- "dist",
93
- "LISCENCE"
94
- ]
95
- }
2
+ "name": "keyv",
3
+ "version": "5.1.1",
4
+ "description": "Simple key-value storage with support for multiple backends",
5
+ "type": "module",
6
+ "main": "dist/index.cjs",
7
+ "module": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "require": "./dist/index.cjs",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "xo": {
16
+ "rules": {
17
+ "import/no-named-as-default": "off",
18
+ "unicorn/prefer-module": "off",
19
+ "unicorn/prefer-node-protocol": "off",
20
+ "@typescript-eslint/consistent-type-definitions": "off",
21
+ "unicorn/no-typeof-undefined": "off",
22
+ "unicorn/prefer-event-target": "off",
23
+ "import/no-extraneous-dependencies": "off",
24
+ "import/extensions": "off",
25
+ "@typescript-eslint/ban-ts-comment": "off",
26
+ "@typescript-eslint/no-unsafe-call": "off",
27
+ "@typescript-eslint/no-for-in-array": "off",
28
+ "guard-for-in": "off",
29
+ "no-await-in-loop": "off",
30
+ "@typescript-eslint/no-unsafe-return": "off",
31
+ "@typescript-eslint/no-unsafe-assignment": "off",
32
+ "@typescript-eslint/no-unsafe-argument": "off",
33
+ "@typescript-eslint/naming-convention": "off",
34
+ "@typescript-eslint/consistent-type-assertions": "off",
35
+ "@typescript-eslint/no-confusing-void-expression": "off",
36
+ "@typescript-eslint/no-var-requires": "off",
37
+ "@typescript-eslint/prefer-ts-expect-error": "off"
38
+ }
39
+ },
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/jaredwray/keyv.git"
43
+ },
44
+ "keywords": [
45
+ "key",
46
+ "value",
47
+ "store",
48
+ "cache",
49
+ "ttl",
50
+ "key-value",
51
+ "storage",
52
+ "backend",
53
+ "adapter",
54
+ "redis",
55
+ "mongodb",
56
+ "sqlite",
57
+ "mysql",
58
+ "postgresql",
59
+ "memory",
60
+ "node-cache",
61
+ "lru-cache",
62
+ "lru",
63
+ "cache-manager"
64
+ ],
65
+ "author": "Jared Wray <me@jaredwray.com> (http://jaredwray.com)",
66
+ "license": "MIT",
67
+ "bugs": {
68
+ "url": "https://github.com/jaredwray/keyv/issues"
69
+ },
70
+ "homepage": "https://github.com/jaredwray/keyv",
71
+ "dependencies": {
72
+ "@keyv/serialize": "*"
73
+ },
74
+ "devDependencies": {
75
+ "@keyv/compress-brotli": "*",
76
+ "@keyv/compress-gzip": "*",
77
+ "@keyv/memcache": "*",
78
+ "@keyv/mongo": "*",
79
+ "@keyv/sqlite": "*",
80
+ "@keyv/test-suite": "*",
81
+ "rimraf": "^6.0.1",
82
+ "timekeeper": "^2.3.1",
83
+ "tsd": "^0.31.2",
84
+ "xo": "^0.59.3"
85
+ },
86
+ "tsd": {
87
+ "directory": "test"
88
+ },
89
+ "files": [
90
+ "dist",
91
+ "LISCENCE"
92
+ ],
93
+ "scripts": {
94
+ "build": "rimraf ./dist && tsup src/index.ts --format cjs,esm --dts --clean",
95
+ "test": "xo --fix && vitest run --coverage",
96
+ "test:ci": "xo && vitest --run --sequence.setupFiles=list",
97
+ "clean": "rimraf ./node_modules ./coverage ./test/testdb.sqlite ./dist"
98
+ }
99
+ }