@seip/blue-bird 1.0.1 → 1.0.2

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/AGENTS.md CHANGED
@@ -87,9 +87,17 @@ If an Express route involves heavy processing or database queries, utilize the `
87
87
  ```javascript
88
88
  import Cache from "@seip/blue-bird/core/cache.js";
89
89
 
90
+ // Express route middleware caching
90
91
  router.get("/stats", Cache.middleware(60), (req, res) => {
91
92
  res.json({ ok: true });
92
93
  });
94
+
95
+ // Programmatic cache manipulation
96
+ await Cache.set("custom_key", { data: "value" }, 120);
97
+ const cachedData = await Cache.get("custom_key");
98
+
99
+ // Invalidate route cache manually (e.g. after updating DB)
100
+ await Cache.delete("/api/public/config");
93
101
  ```
94
102
 
95
103
  The Cache module integrates with Redis when `REDIS_HOST` is configured in the environment. If Redis is unavailable or fails, it transparently falls back to an in-memory cache system without interrupting requests.
package/README.md CHANGED
@@ -222,6 +222,20 @@ router.get("/stats", Cache.middleware(60), (req, res) => {
222
222
  });
223
223
  ```
224
224
 
225
+ #### Programmatic Cache Manipulation & Invalidation
226
+
227
+ ```javascript
228
+ // Get / Set keys programmatically
229
+ await Cache.set("custom_key", { data: "value" }, 120);
230
+ const cachedData = await Cache.get("custom_key");
231
+
232
+ // Manually invalidate route cache (e.g. after updating DB)
233
+ await Cache.delete("/api/public/config");
234
+
235
+ // Clear all cache entries
236
+ await Cache.clear();
237
+ ```
238
+
225
239
  #### Custom Database & Data Caching with `getRedisClient()`
226
240
 
227
241
  ```javascript
package/core/cache.js CHANGED
@@ -162,6 +162,137 @@ class Cache {
162
162
  next();
163
163
  };
164
164
  }
165
+
166
+ /**
167
+ * Retrieves cached value by key.
168
+ * @param {string} key - Cache key.
169
+ * @returns {Promise<any|null>} Cached payload or null.
170
+ */
171
+ static async get(key) {
172
+ key = key.trim();
173
+ if (!key) return null;
174
+
175
+ if (redisHost && !redisClient) {
176
+ await initRedis().catch(() => { });
177
+ }
178
+
179
+ if (isRedisConnected && redisClient) {
180
+ try {
181
+ const cachedData = await redisClient.get(key);
182
+ if (cachedData) {
183
+ try {
184
+ const cached = JSON.parse(cachedData);
185
+ return cached && typeof cached === "object" && "data" in cached ? cached.data : cached;
186
+ } catch {
187
+ return cachedData;
188
+ }
189
+ }
190
+ return null;
191
+ } catch (err) {
192
+ isRedisConnected = false;
193
+ }
194
+ }
195
+
196
+ if (CACHE[key]) {
197
+ if (CACHE[key].expiry > Date.now()) {
198
+ const cached = CACHE[key];
199
+ return cached.data !== undefined ? cached.data : cached;
200
+ }
201
+ delete CACHE[key];
202
+ }
203
+
204
+ return null;
205
+ }
206
+
207
+ /**
208
+ * Sets data into cache with a specified TTL in seconds.
209
+ * @param {string} key - Cache key.
210
+ * @param {any} value - Data to cache.
211
+ * @param {number} [seconds=60] - Expiry time in seconds.
212
+ * @returns {Promise<boolean>} True if set successfully.
213
+ */
214
+ static async set(key, value, seconds = 60) {
215
+ key = key.trim();
216
+ if (!key) return false;
217
+
218
+ if (redisHost && !redisClient) {
219
+ await initRedis().catch(() => { });
220
+ }
221
+
222
+ const cacheObject = {
223
+ type: typeof value === "string" ? "html" : "json",
224
+ data: value,
225
+ expiry: Date.now() + seconds * 1000,
226
+ };
227
+
228
+ if (isRedisConnected && redisClient) {
229
+ try {
230
+ await redisClient.set(key, JSON.stringify(cacheObject), {
231
+ EX: seconds,
232
+ });
233
+ } catch (err) {
234
+ CACHE[key] = cacheObject;
235
+ }
236
+ } else {
237
+ CACHE[key] = cacheObject;
238
+ }
239
+
240
+ return true;
241
+ }
242
+
243
+ /**
244
+ * Deletes one or more entries from cache.
245
+ * @param {string|string[]} keys - Single key or array of keys to delete.
246
+ * @returns {Promise<boolean>} True if deleted.
247
+ */
248
+ static async delete(keys) {
249
+ if (!keys) return false;
250
+ const keyList = Array.isArray(keys) ? keys : [keys];
251
+
252
+ if (redisHost && !redisClient) {
253
+ await initRedis().catch(() => { });
254
+ }
255
+
256
+ for (const key of keyList) {
257
+ delete CACHE[key];
258
+ if (isRedisConnected && redisClient) {
259
+ try {
260
+ await redisClient.del(key);
261
+ } catch (err) {
262
+ isRedisConnected = false;
263
+ }
264
+ }
265
+ }
266
+
267
+ return true;
268
+ }
269
+
270
+ /**
271
+ * Alias for delete.
272
+ * @param {string|string[]} keys - Single key or array of keys to delete.
273
+ * @returns {Promise<boolean>} True if deleted.
274
+ */
275
+ static async del(keys) {
276
+ return this.delete(keys);
277
+ }
278
+
279
+ /**
280
+ * Flushes all cached data in memory (and Redis if connected).
281
+ * @returns {Promise<boolean>} True if flushed.
282
+ */
283
+ static async clear() {
284
+ for (const key in CACHE) {
285
+ delete CACHE[key];
286
+ }
287
+ if (isRedisConnected && redisClient) {
288
+ try {
289
+ await redisClient.flushDb();
290
+ } catch (err) {
291
+ isRedisConnected = false;
292
+ }
293
+ }
294
+ return true;
295
+ }
165
296
  }
166
297
 
167
298
  /**
package/core/index.d.ts CHANGED
@@ -112,6 +112,11 @@ export class Auth {
112
112
 
113
113
  export class Cache {
114
114
  static middleware(seconds?: number): (req: Request, res: Response, next: NextFunction) => Promise<any>;
115
+ static get(key: string): Promise<any | null>;
116
+ static set(key: string, value: any, seconds?: number): Promise<boolean>;
117
+ static delete(keys: string | string[]): Promise<boolean>;
118
+ static del(keys: string | string[]): Promise<boolean>;
119
+ static clear(): Promise<boolean>;
115
120
  }
116
121
 
117
122
  export function getRedisClient(): any;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seip/blue-bird",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Express opinionated API framework with built-in JWT auth, validation, and caching",
5
5
  "type": "module",
6
6
  "types": "core/index.d.ts",