@geekmidas/cache 0.0.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/dist/__tests__/cache.spec.cjs +76 -0
- package/dist/__tests__/cache.spec.mjs +76 -0
- package/dist/__tests__/integration.spec.cjs +234 -0
- package/dist/__tests__/integration.spec.mjs +234 -0
- package/dist/__tests__/memory.spec.cjs +125 -0
- package/dist/__tests__/memory.spec.mjs +125 -0
- package/dist/__tests__/upstash.spec.cjs +201 -0
- package/dist/__tests__/upstash.spec.mjs +201 -0
- package/dist/cache.cjs +0 -0
- package/dist/cache.mjs +0 -0
- package/dist/chunk-CUT6urMc.cjs +30 -0
- package/dist/magic-string.es-BvJNBYzY.mjs +1014 -0
- package/dist/magic-string.es-CKiDiYoS.cjs +1015 -0
- package/dist/memory-YteQXj7m.mjs +16 -0
- package/dist/memory-n6Iosq6J.cjs +22 -0
- package/dist/memory.cjs +3 -0
- package/dist/memory.mjs +3 -0
- package/dist/upstash-Cpe9W0-L.mjs +26 -0
- package/dist/upstash-s7dedvpn.cjs +32 -0
- package/dist/upstash.cjs +3 -0
- package/dist/upstash.mjs +3 -0
- package/dist/vi.DgezovHB-McgltIC5.mjs +13079 -0
- package/dist/vi.DgezovHB-NqP74KGR.cjs +13104 -0
- package/package.json +23 -0
- package/src/__tests__/cache.spec.ts +111 -0
- package/src/__tests__/integration.spec.ts +273 -0
- package/src/__tests__/memory.spec.ts +134 -0
- package/src/__tests__/upstash.spec.ts +247 -0
- package/src/cache.ts +5 -0
- package/src/memory.ts +17 -0
- package/src/upstash.ts +31 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
2
|
+
import { UpstashCache } from '../upstash';
|
|
3
|
+
|
|
4
|
+
describe('UpstashCache', () => {
|
|
5
|
+
let cache: UpstashCache<any>;
|
|
6
|
+
const testKeyPrefix = `test:${Date.now()}:`;
|
|
7
|
+
let testKeys: string[] = [];
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
cache = new UpstashCache('http://localhost:8079', 'example_token');
|
|
11
|
+
testKeys = [];
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
afterEach(async () => {
|
|
15
|
+
// Clean up test keys
|
|
16
|
+
for (const key of testKeys) {
|
|
17
|
+
try {
|
|
18
|
+
await cache.delete(key);
|
|
19
|
+
} catch (error) {
|
|
20
|
+
// Ignore cleanup errors
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const getTestKey = (suffix: string): string => {
|
|
26
|
+
const key = `${testKeyPrefix}${suffix}`;
|
|
27
|
+
testKeys.push(key);
|
|
28
|
+
return key;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
describe('get', () => {
|
|
32
|
+
it('should return undefined for non-existent key', async () => {
|
|
33
|
+
const key = getTestKey('non-existent');
|
|
34
|
+
const result = await cache.get(key);
|
|
35
|
+
|
|
36
|
+
expect(result).toBeUndefined();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should parse and return JSON value', async () => {
|
|
40
|
+
const key = getTestKey('object');
|
|
41
|
+
const testValue = { id: 1, name: 'test' };
|
|
42
|
+
|
|
43
|
+
await cache.set(key, testValue);
|
|
44
|
+
const result = await cache.get(key);
|
|
45
|
+
|
|
46
|
+
expect(result).toEqual(testValue);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should handle string values', async () => {
|
|
50
|
+
const key = getTestKey('string');
|
|
51
|
+
const testValue = 'simple string';
|
|
52
|
+
|
|
53
|
+
await cache.set(key, testValue);
|
|
54
|
+
const result = await cache.get(key);
|
|
55
|
+
|
|
56
|
+
expect(result).toBe(testValue);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should handle number values', async () => {
|
|
60
|
+
const key = getTestKey('number');
|
|
61
|
+
const testValue = 42;
|
|
62
|
+
|
|
63
|
+
await cache.set(key, testValue);
|
|
64
|
+
const result = await cache.get(key);
|
|
65
|
+
|
|
66
|
+
expect(result).toBe(testValue);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('should handle boolean values', async () => {
|
|
70
|
+
const key = getTestKey('boolean');
|
|
71
|
+
const testValue = true;
|
|
72
|
+
|
|
73
|
+
await cache.set(key, testValue);
|
|
74
|
+
const result = await cache.get(key);
|
|
75
|
+
|
|
76
|
+
expect(result).toBe(testValue);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should handle array values', async () => {
|
|
80
|
+
const key = getTestKey('array');
|
|
81
|
+
const testArray = [1, 2, 3, 'test'];
|
|
82
|
+
|
|
83
|
+
await cache.set(key, testArray);
|
|
84
|
+
const result = await cache.get(key);
|
|
85
|
+
|
|
86
|
+
expect(result).toEqual(testArray);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should handle null values as undefined', async () => {
|
|
90
|
+
const key = getTestKey('null');
|
|
91
|
+
|
|
92
|
+
await cache.set(key, null);
|
|
93
|
+
const result = await cache.get(key);
|
|
94
|
+
|
|
95
|
+
expect(result).toBeUndefined();
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe('set', () => {
|
|
100
|
+
it('should store and retrieve object value', async () => {
|
|
101
|
+
const key = getTestKey('set-object');
|
|
102
|
+
const testValue = { id: 1, name: 'test' };
|
|
103
|
+
|
|
104
|
+
await cache.set(key, testValue);
|
|
105
|
+
const result = await cache.get(key);
|
|
106
|
+
|
|
107
|
+
expect(result).toEqual(testValue);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should store and retrieve string values', async () => {
|
|
111
|
+
const key = getTestKey('set-string');
|
|
112
|
+
const testValue = 'test string';
|
|
113
|
+
|
|
114
|
+
await cache.set(key, testValue);
|
|
115
|
+
const result = await cache.get(key);
|
|
116
|
+
|
|
117
|
+
expect(result).toBe(testValue);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('should store and retrieve number values', async () => {
|
|
121
|
+
const key = getTestKey('set-number');
|
|
122
|
+
const testValue = 42;
|
|
123
|
+
|
|
124
|
+
await cache.set(key, testValue);
|
|
125
|
+
const result = await cache.get(key);
|
|
126
|
+
|
|
127
|
+
expect(result).toBe(testValue);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('should store and retrieve boolean values', async () => {
|
|
131
|
+
const key = getTestKey('set-boolean');
|
|
132
|
+
const testValue = true;
|
|
133
|
+
|
|
134
|
+
await cache.set(key, testValue);
|
|
135
|
+
const result = await cache.get(key);
|
|
136
|
+
|
|
137
|
+
expect(result).toBe(testValue);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('should store and retrieve array values', async () => {
|
|
141
|
+
const key = getTestKey('set-array');
|
|
142
|
+
const testArray = [1, 2, 3];
|
|
143
|
+
|
|
144
|
+
await cache.set(key, testArray);
|
|
145
|
+
const result = await cache.get(key);
|
|
146
|
+
|
|
147
|
+
expect(result).toEqual(testArray);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('should not store and retrieve null values', async () => {
|
|
151
|
+
const key = getTestKey('set-null');
|
|
152
|
+
|
|
153
|
+
await cache.set(key, null);
|
|
154
|
+
const result = await cache.get(key);
|
|
155
|
+
|
|
156
|
+
expect(result).toBeUndefined();
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('should overwrite existing values', async () => {
|
|
160
|
+
const key = getTestKey('overwrite');
|
|
161
|
+
|
|
162
|
+
await cache.set(key, 'initial');
|
|
163
|
+
await cache.set(key, 'updated');
|
|
164
|
+
const result = await cache.get(key);
|
|
165
|
+
|
|
166
|
+
expect(result).toBe('updated');
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
describe('delete', () => {
|
|
171
|
+
it('should delete existing key', async () => {
|
|
172
|
+
const key = getTestKey('delete-test');
|
|
173
|
+
|
|
174
|
+
await cache.set(key, 'value-to-delete');
|
|
175
|
+
await cache.delete(key);
|
|
176
|
+
const result = await cache.get(key);
|
|
177
|
+
|
|
178
|
+
expect(result).toBeUndefined();
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('should handle deletion of non-existent key', async () => {
|
|
182
|
+
const key = getTestKey('non-existent-delete');
|
|
183
|
+
|
|
184
|
+
await expect(cache.delete(key)).resolves.not.toThrow();
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('should only delete specified key', async () => {
|
|
188
|
+
const key1 = getTestKey('delete-key1');
|
|
189
|
+
const key2 = getTestKey('delete-key2');
|
|
190
|
+
|
|
191
|
+
await cache.set(key1, 'value1');
|
|
192
|
+
await cache.set(key2, 'value2');
|
|
193
|
+
|
|
194
|
+
await cache.delete(key1);
|
|
195
|
+
|
|
196
|
+
expect(await cache.get(key1)).toBeUndefined();
|
|
197
|
+
expect(await cache.get(key2)).toBe('value2');
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
describe('integration scenarios', () => {
|
|
202
|
+
it('should handle round-trip operations', async () => {
|
|
203
|
+
const key = getTestKey('user-session');
|
|
204
|
+
const testData = {
|
|
205
|
+
user: { id: 1, name: 'John' },
|
|
206
|
+
preferences: ['dark-mode', 'notifications'],
|
|
207
|
+
count: 42,
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
await cache.set(key, testData);
|
|
211
|
+
const result = await cache.get(key);
|
|
212
|
+
|
|
213
|
+
expect(result).toEqual(testData);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('should handle complex nested objects', async () => {
|
|
217
|
+
const key = getTestKey('complex');
|
|
218
|
+
const complexObject = {
|
|
219
|
+
level1: {
|
|
220
|
+
level2: {
|
|
221
|
+
level3: {
|
|
222
|
+
data: 'deep nested value',
|
|
223
|
+
array: [{ id: 1 }, { id: 2 }],
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
await cache.set(key, complexObject);
|
|
230
|
+
const result = await cache.get(key);
|
|
231
|
+
|
|
232
|
+
expect(result).toEqual(complexObject);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it('should handle concurrent operations', async () => {
|
|
236
|
+
const keys = ['concurrent1', 'concurrent2', 'concurrent3'].map((suffix) =>
|
|
237
|
+
getTestKey(suffix),
|
|
238
|
+
);
|
|
239
|
+
const values = ['value1', 'value2', 'value3'];
|
|
240
|
+
|
|
241
|
+
await Promise.all(keys.map((key, i) => cache.set(key, values[i])));
|
|
242
|
+
const results = await Promise.all(keys.map((key) => cache.get(key)));
|
|
243
|
+
|
|
244
|
+
expect(results).toEqual(values);
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
});
|
package/src/cache.ts
ADDED
package/src/memory.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Cache } from './cache';
|
|
2
|
+
|
|
3
|
+
export class InMemoryCache<T> implements Cache<T> {
|
|
4
|
+
private store: Map<string, T> = new Map();
|
|
5
|
+
|
|
6
|
+
async get(key: string): Promise<T | undefined> {
|
|
7
|
+
return this.store.get(key);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async set(key: string, value: T): Promise<void> {
|
|
11
|
+
this.store.set(key, value);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async delete(key: string): Promise<void> {
|
|
15
|
+
this.store.delete(key);
|
|
16
|
+
}
|
|
17
|
+
}
|
package/src/upstash.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Redis } from '@upstash/redis';
|
|
2
|
+
import type { Cache } from './cache';
|
|
3
|
+
|
|
4
|
+
export class UpstashCache<T> implements Cache<T> {
|
|
5
|
+
private client: Redis;
|
|
6
|
+
|
|
7
|
+
constructor(url: string, token: string) {
|
|
8
|
+
this.client = new Redis({
|
|
9
|
+
url,
|
|
10
|
+
token,
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async get(key: string): Promise<T | undefined> {
|
|
15
|
+
const v = await this.client.get(key);
|
|
16
|
+
|
|
17
|
+
if (v === null) {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return v as T; // Assuming the value is stored as a string, you may need to parse it if it's JSON
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async set(key: string, value: T): Promise<void> {
|
|
25
|
+
await this.client.set(key, value);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async delete(key: string): Promise<void> {
|
|
29
|
+
await this.client.del(key);
|
|
30
|
+
}
|
|
31
|
+
}
|