@kikiutils/shared 13.6.1 → 14.0.0

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.
Files changed (51) hide show
  1. package/dist/storages/lru/keyed-store.d.ts +22 -0
  2. package/dist/storages/lru/keyed-store.d.ts.map +1 -0
  3. package/dist/storages/lru/keyed-store.js +17 -0
  4. package/dist/storages/lru/keyed-store.js.map +1 -0
  5. package/dist/storages/redis/keyed-store.d.ts +16 -0
  6. package/dist/storages/redis/keyed-store.d.ts.map +1 -0
  7. package/dist/storages/redis/keyed-store.js +18 -0
  8. package/dist/storages/redis/keyed-store.js.map +1 -0
  9. package/dist/storages/redis/msgpack.d.ts +7 -0
  10. package/dist/storages/redis/msgpack.d.ts.map +1 -0
  11. package/dist/storages/redis/msgpack.js +23 -0
  12. package/dist/storages/redis/msgpack.js.map +1 -0
  13. package/dist/storages/redis/types.d.ts +22 -0
  14. package/dist/storages/redis/types.d.ts.map +1 -0
  15. package/dist/storages/redis/types.js +1 -0
  16. package/package.json +8 -28
  17. package/src/storages/lru/keyed-store.ts +23 -0
  18. package/src/storages/redis/keyed-store.ts +17 -0
  19. package/src/storages/redis/msgpack.ts +30 -0
  20. package/src/storages/redis/types.ts +19 -0
  21. package/dist/storage/enhanced/local/core.d.ts +0 -61
  22. package/dist/storage/enhanced/local/core.d.ts.map +0 -1
  23. package/dist/storage/enhanced/local/core.js +0 -63
  24. package/dist/storage/enhanced/local/core.js.map +0 -1
  25. package/dist/storage/enhanced/local/index.d.ts +0 -3
  26. package/dist/storage/enhanced/local/index.js +0 -4
  27. package/dist/storage/enhanced/local/keyed-store.d.ts +0 -36
  28. package/dist/storage/enhanced/local/keyed-store.d.ts.map +0 -1
  29. package/dist/storage/enhanced/local/keyed-store.js +0 -36
  30. package/dist/storage/enhanced/local/keyed-store.js.map +0 -1
  31. package/dist/storage/enhanced/redis/core.d.ts +0 -85
  32. package/dist/storage/enhanced/redis/core.d.ts.map +0 -1
  33. package/dist/storage/enhanced/redis/core.js +0 -85
  34. package/dist/storage/enhanced/redis/core.js.map +0 -1
  35. package/dist/storage/enhanced/redis/index.d.ts +0 -3
  36. package/dist/storage/enhanced/redis/index.js +0 -4
  37. package/dist/storage/enhanced/redis/keyed-store.d.ts +0 -44
  38. package/dist/storage/enhanced/redis/keyed-store.d.ts.map +0 -1
  39. package/dist/storage/enhanced/redis/keyed-store.js +0 -41
  40. package/dist/storage/enhanced/redis/keyed-store.js.map +0 -1
  41. package/dist/storage/lru/keyed-store.d.ts +0 -44
  42. package/dist/storage/lru/keyed-store.d.ts.map +0 -1
  43. package/dist/storage/lru/keyed-store.js +0 -40
  44. package/dist/storage/lru/keyed-store.js.map +0 -1
  45. package/src/storage/enhanced/local/core.ts +0 -106
  46. package/src/storage/enhanced/local/index.ts +0 -2
  47. package/src/storage/enhanced/local/keyed-store.ts +0 -36
  48. package/src/storage/enhanced/redis/core.ts +0 -151
  49. package/src/storage/enhanced/redis/index.ts +0 -2
  50. package/src/storage/enhanced/redis/keyed-store.ts +0 -43
  51. package/src/storage/lru/keyed-store.ts +0 -46
@@ -1,151 +0,0 @@
1
- import { Buffer } from 'node:buffer';
2
-
3
- import { Redis } from 'ioredis';
4
- import {
5
- deserialize,
6
- serialize,
7
- } from 'superjson';
8
-
9
- enum StorageValueEncodingType {
10
- Buffer = 0,
11
- Json = 1,
12
- String = 2,
13
- }
14
-
15
- const customValueHeader = Buffer.of(
16
- 0xE2,
17
- 0x81,
18
- 0xA0,
19
- );
20
-
21
- const customValueHeaderLength = customValueHeader.byteLength + 1;
22
-
23
- /**
24
- * Creates an enhanced Redis-based storage interface using SuperJSON encoding.
25
- *
26
- * This utility provides a typed, serializable key-value store backed by Redis,
27
- * supporting TTL operations and safe deserialization of complex types (e.g. Date, Map).
28
- *
29
- * @param {Redis | string} ioRedisInstanceOrUrl - Either an existing `ioredis` instance or a Redis connection string
30
- *
31
- * @returns A frozen object that wraps Redis commands with typed get/set logic and encoding
32
- *
33
- * @example
34
- * ```typescript
35
- * import { createEnhancedRedisStorage } from '@kikiutils/shared/storage/enhanced/redis';
36
- *
37
- * const redisStorage = createEnhancedRedisStorage('redis://localhost');
38
- * await redisStorage.setItem('user:1', { name: 'user' });
39
- * const user = await redisStorage.getItem<{ name: string }>('user:1');
40
- * ```
41
- */
42
- export function createEnhancedRedisStorage(ioRedisInstanceOrUrl: Redis | string) {
43
- const instance = ioRedisInstanceOrUrl instanceof Redis ? ioRedisInstanceOrUrl : new Redis(ioRedisInstanceOrUrl);
44
- return Object.freeze({
45
- /**
46
- * Retrieves a value from Redis and decodes it.
47
- *
48
- * @template T - The expected return type
49
- *
50
- * @param {string} key - The Redis key
51
- *
52
- * @returns {Promise<null | T>} The decoded value or null if not found
53
- */
54
- async getItem<T = unknown>(key: string) {
55
- const rawValue = await instance.getBuffer(key);
56
- return rawValue ? decodeStorageValue(rawValue) as T : null;
57
- },
58
- /**
59
- * Gets the remaining TTL (in seconds) for a given key.
60
- *
61
- * @param {string} key - The Redis key
62
- *
63
- * @returns {Promise<number>} The number of seconds until the key expires, or -1 if no expiration is set
64
- */
65
- getItemTtl: (key: string) => instance.ttl(key),
66
- /**
67
- * Checks whether a key exists in Redis.
68
- *
69
- * @param {string} key - The Redis key
70
- *
71
- * @returns {Promise<boolean>} True if the key exists, false otherwise
72
- */
73
- hasItem: async (key: string) => await instance.exists(key) === 1,
74
- /**
75
- * The underlying Redis instance, exposed for advanced operations.
76
- * Use with caution; most use cases should rely on the wrapper methods.
77
- *
78
- * @returns {Redis} The underlying Redis instance
79
- */
80
- get instance() {
81
- return instance;
82
- },
83
- /**
84
- * Removes a key from Redis.
85
- *
86
- * @param {string} key - The Redis key to delete
87
- *
88
- * @returns {Promise<boolean>} A Promise that resolves to `true` if the key was removed,
89
- * or `false` if it did not exist.
90
- */
91
- removeItem: async (key: string) => await instance.del(key) === 1,
92
- /**
93
- * Stores a value in Redis without expiration.
94
- *
95
- * @param {string} key - The Redis key
96
- * @param {any} value - The value to store. Will be serialized
97
- */
98
- setItem: (key: string, value: any) => instance.set(key, encodeToStorageValue(value)),
99
- /**
100
- * Stores a value in Redis with a time-to-live (TTL).
101
- *
102
- * @param {string} key - The Redis key
103
- * @param {number} seconds - Expiration time in seconds
104
- * @param {any} value - The value to store. Will be serialized
105
- */
106
- setItemWithTtl(key: string, seconds: number, value: any) {
107
- return instance.setex(key, seconds, encodeToStorageValue(value));
108
- },
109
- });
110
- }
111
-
112
- function decodeStorageValue(data: Buffer) {
113
- if (!isCustomFormat(data)) return data;
114
- const payload = data.subarray(customValueHeaderLength);
115
- const type = data[customValueHeader.byteLength];
116
- switch (type) {
117
- case StorageValueEncodingType.Buffer: return payload;
118
- case StorageValueEncodingType.Json:
119
- try {
120
- return deserialize(JSON.parse(payload.toString()));
121
- } catch {
122
- throw new Error('[RedisStorage] Failed to parse JSON payload');
123
- }
124
- case StorageValueEncodingType.String: return payload.toString();
125
- default:
126
- throw new Error(`[RedisStorage] Unknown encoding type: ${type}`);
127
- }
128
- }
129
-
130
- function encodeToStorageValue(value: any) {
131
- if (Buffer.isBuffer(value)) return toCustomValue(StorageValueEncodingType.Buffer, value);
132
- if (typeof value === 'string') return toCustomValue(StorageValueEncodingType.String, Buffer.from(value));
133
- return toCustomValue(StorageValueEncodingType.Json, Buffer.from(JSON.stringify(serialize(value))));
134
- }
135
-
136
- function isCustomFormat(buffer: Buffer) {
137
- return (
138
- buffer.length >= customValueHeaderLength
139
- && buffer[0] === customValueHeader[0]
140
- && buffer[1] === customValueHeader[1]
141
- && buffer[2] === customValueHeader[2]
142
- );
143
- }
144
-
145
- function toCustomValue(type: StorageValueEncodingType, payload: Buffer) {
146
- return Buffer.concat([
147
- customValueHeader,
148
- Buffer.of(type),
149
- payload,
150
- ]);
151
- }
@@ -1,2 +0,0 @@
1
- export { createEnhancedRedisStorage } from './core';
2
- export { createKeyedEnhancedRedisStore } from './keyed-store';
@@ -1,43 +0,0 @@
1
- import type { createEnhancedRedisStorage } from './core';
2
-
3
- /**
4
- * Creates a reusable, type-safe Redis-backed storage interface based on `createEnhancedRedisStorage`
5
- * and a dynamic key-generation function.
6
- *
7
- * This utility abstracts away key construction and provides high-level access
8
- * to Redis operations such as `getItem`, `setItem`, `setItemWithTtl`, and `getItemTtl`.
9
- * It is ideal for namespaced data, caching, and session handling.
10
- *
11
- * @template D - The value type to store
12
- *
13
- * @param {ReturnType<typeof createEnhancedRedisStorage>} storage - The enhanced Redis storage instance
14
- *
15
- * @returns A factory that accepts a key generator function and returns a scoped Redis storage interface
16
- *
17
- * @example
18
- * ```typescript
19
- * import { createKeyedEnhancedRedisStore } from '@kikiutils/shared/storage/enhanced/redis';
20
- *
21
- * const userStore = createKeyedEnhancedRedisStore<User>(redisStorage)((id: number) => `user:${id}`);
22
- * await userStore.setItem({ id: 123, name: 'user' }, 123);
23
- * const user = await userStore.getItem(123);
24
- * ```
25
- */
26
- export function createKeyedEnhancedRedisStore<D = unknown>(storage: ReturnType<typeof createEnhancedRedisStorage>) {
27
- return <P extends any[]>(getKeyFunction: (...args: P) => string) => Object.freeze({
28
- getItem: (...args: P) => storage.getItem<D>(getKeyFunction(...args)),
29
- getItemTtl: (...args: P) => storage.getItemTtl(getKeyFunction(...args)),
30
- hasItem: (...args: P) => storage.hasItem(getKeyFunction(...args)),
31
- removeItem: (...args: P) => storage.removeItem(getKeyFunction(...args)),
32
- /**
33
- * Resolves the storage key from the given arguments.
34
- *
35
- * @returns {string} The final string key used internally
36
- */
37
- resolveKey: (...args: P) => getKeyFunction(...args),
38
- setItem: (value: D, ...args: P) => storage.setItem(getKeyFunction(...args), value),
39
- setItemWithTtl(seconds: number, value: D, ...args: P) {
40
- return storage.setItemWithTtl(getKeyFunction(...args), seconds, value);
41
- },
42
- });
43
- }
@@ -1,46 +0,0 @@
1
- import type { LRUCache } from 'lru-cache';
2
-
3
- /**
4
- * Creates a reusable, type-safe keyed store wrapper for an LRUCache instance.
5
- *
6
- * This utility allows structured access to cache entries using a dynamic key-generation function.
7
- *
8
- * @template D - The specific value type exposed by this store (must extend `V`)
9
- *
10
- * @param {LRUCache<any, any, any>} lruInstance - An instance of `lru-cache`
11
- *
12
- * @returns A factory that accepts a key generator and returns a scoped, type-safe LRU-based store
13
- *
14
- * @example
15
- * ```typescript
16
- * import { createKeyedLruStore } from '@kikiutils/shared/storage/lru/keyed-store';
17
- *
18
- * const lruCache = new LRUCache({ max: 5000 });
19
- * const userStore = createKeyedLruStore<User>(lruCache)((id: number) => `user:${id}`);
20
- * userStore.setItem({ id: 1 }, 1);
21
- * const user = userStore.getItem(1);
22
- * ```
23
- */
24
- export function createKeyedLruStore<D = unknown>(lruInstance: LRUCache<any, any, any>) {
25
- return <P extends any[]>(getKeyFunction: (...args: P) => string) => Object.freeze({
26
- /**
27
- * Return a value from the cache. Will update the recency of the cache entry found.
28
- *
29
- * If the key is not found, returns `null`.
30
- */
31
- getItem(...args: P) {
32
- const rawValue = lruInstance.get(getKeyFunction(...args));
33
- return rawValue as D ?? null;
34
- },
35
- getItemTtl: (...args: P) => lruInstance.getRemainingTTL(getKeyFunction(...args)),
36
- hasItem: (...args: P) => lruInstance.has(getKeyFunction(...args)),
37
- removeItem: (...args: P) => lruInstance.delete(getKeyFunction(...args)),
38
- /**
39
- * Resolves the full cache key from the given arguments.
40
- */
41
- resolveKey: (...args: P) => getKeyFunction(...args),
42
- setItem(value: D, ...args: P) {
43
- lruInstance.set(getKeyFunction(...args), value);
44
- },
45
- });
46
- }