honojs-plugin-memory 0.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.
package/README.md ADDED
@@ -0,0 +1,128 @@
1
+ # @honojs-plugins/memory
2
+
3
+ Cache plugin for HonoJS. Supports two drivers:
4
+
5
+ - **`memory`** — in-process LRU cache (`lru-cache`)
6
+ - **`redis`** — distributed cache (`ioredis`)
7
+
8
+ Both drivers implement the same `CacheDriver` interface, so they are interchangeable.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ pnpm add @honojs-plugins/memory
14
+ ```
15
+
16
+ ## Folder structure
17
+
18
+ ```
19
+ src/
20
+ ├── index.ts # Cache.create() factory + exports
21
+ ├── memory/ # MemoryCache driver (lru-cache backed)
22
+ ├── redis/ # RedisCache driver (ioredis backed)
23
+ ├── schema/
24
+ │ ├── index.ts # CacheSchema (driver: 'memory' | 'redis')
25
+ │ ├── memory.ts # MemorySchema ({ max, ttl })
26
+ │ └── redis.ts # RedisSchema ({ host, port, password, db, keyPrefix, ttl })
27
+ └── types/
28
+ └── cache.ts # CacheDriver interface, CacheType, CacheParams, CacheInstance
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ ### 1. In-memory (LRU) cache
34
+
35
+ ```ts
36
+ import Cache, { MemoryCache } from '@honojs-plugins/memory'
37
+
38
+ const cache = Cache.create({
39
+ cacheType: 'memory',
40
+ params: {
41
+ max: 500, // max entries
42
+ ttl: 60, // default TTL in seconds (optional)
43
+ },
44
+ }) as MemoryCache
45
+
46
+ await cache.set('user:1', { id: 1, name: 'Alice' })
47
+ const user = await cache.get('user:1')
48
+ const exists = await cache.has('user:1')
49
+ await cache.del('user:1')
50
+ await cache.clear()
51
+ ```
52
+
53
+ ### 2. Redis cache
54
+
55
+ ```ts
56
+ import Cache, { RedisCache } from '@honojs-plugins/memory'
57
+
58
+ const cache = Cache.create({
59
+ cacheType: 'redis',
60
+ params: {
61
+ host: '127.0.0.1',
62
+ port: 6379,
63
+ password: process.env.REDIS_PASSWORD,
64
+ db: 0,
65
+ keyPrefix: 'myapp:',
66
+ ttl: 60, // default TTL in seconds (optional)
67
+ },
68
+ }) as RedisCache
69
+
70
+ await cache.set('session:abc', { userId: 1 }, 300) // TTL override, seconds
71
+ const session = await cache.get('session:abc')
72
+ await cache.del('session:abc')
73
+
74
+ // access underlying ioredis client for advanced usage
75
+ cache.client.ping()
76
+ ```
77
+
78
+ ## Example: Hono route with caching
79
+
80
+ ```ts
81
+ import { Hono } from 'hono'
82
+ import Cache, { RedisCache } from '@honojs-plugins/memory'
83
+
84
+ const app = new Hono()
85
+
86
+ const cache = Cache.create({
87
+ cacheType: 'redis',
88
+ params: { host: '127.0.0.1', port: 6379, ttl: 60 },
89
+ }) as RedisCache
90
+
91
+ app.get('/users/:id', async (c) => {
92
+ const id = c.req.param('id')
93
+ const cacheKey = `user:${id}`
94
+
95
+ const cached = await cache.get(cacheKey)
96
+ if (cached) return c.json(cached)
97
+
98
+ const user = await fetchUserFromDb(id) // your own data source
99
+ await cache.set(cacheKey, user)
100
+
101
+ return c.json(user)
102
+ })
103
+
104
+ export default app
105
+
106
+ async function fetchUserFromDb(id: string) {
107
+ return { id, name: 'Alice' }
108
+ }
109
+ ```
110
+
111
+ ## API
112
+
113
+ ### `Cache.create({ cacheType, params })`
114
+
115
+ | `cacheType` | `params` shape |
116
+ |---|---|
117
+ | `'memory'` | `MemoryConfig` — `{ max?: number (default 500), ttl?: number }` |
118
+ | `'redis'` | `RedisConfig` — `{ host?: string (default '127.0.0.1'), port?: number (default 6379), password?, db?, keyPrefix?, ttl? }` |
119
+
120
+ ### `CacheDriver` interface (implemented by both drivers)
121
+
122
+ | Method | Description |
123
+ |---|---|
124
+ | `get<T>(key)` | Returns the cached value, or `undefined` if missing/expired |
125
+ | `set<T>(key, value, ttl?)` | Stores `value`, optionally overriding the default TTL (seconds) |
126
+ | `has(key)` | Returns `true` if `key` exists |
127
+ | `del(key)` | Removes `key` from the cache |
128
+ | `clear()` | Clears the entire cache (or Redis DB via `flushdb` for `RedisCache`) |
package/dist/index.cjs ADDED
@@ -0,0 +1,196 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ //#region \0rolldown/runtime.js
6
+ var __create = Object.create;
7
+ var __defProp = Object.defineProperty;
8
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
9
+ var __getOwnPropNames = Object.getOwnPropertyNames;
10
+ var __getProtoOf = Object.getPrototypeOf;
11
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
14
+ key = keys[i];
15
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
16
+ get: ((k) => from[k]).bind(null, key),
17
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
18
+ });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
23
+ value: mod,
24
+ enumerable: true
25
+ }) : target, mod));
26
+ //#endregion
27
+ let lru_cache = require("lru-cache");
28
+ let ioredis = require("ioredis");
29
+ let zod = require("zod");
30
+ zod = __toESM(zod, 1);
31
+ //#region src/memory/index.ts
32
+ var MemoryCache = class {
33
+ _client;
34
+ _defaultTtl;
35
+ constructor(params) {
36
+ this._defaultTtl = params.ttl;
37
+ this._client = new lru_cache.LRUCache({
38
+ max: params.max,
39
+ ttlAutopurge: false,
40
+ ...params.ttl ? { ttl: params.ttl * 1e3 } : {}
41
+ });
42
+ }
43
+ /**
44
+ * Get a value from the cache
45
+ */
46
+ async get(key) {
47
+ return this._client.get(key)?.value;
48
+ }
49
+ /**
50
+ * Set a value in the cache
51
+ */
52
+ async set(key, value, ttl) {
53
+ const expires = ttl ?? this._defaultTtl;
54
+ if (expires) {
55
+ this._client.set(key, { value }, { ttl: expires * 1e3 });
56
+ return;
57
+ }
58
+ this._client.set(key, { value });
59
+ }
60
+ /**
61
+ * Check if a key exists in the cache
62
+ */
63
+ async has(key) {
64
+ return this._client.has(key);
65
+ }
66
+ /**
67
+ * Delete a value from the cache
68
+ */
69
+ async del(key) {
70
+ this._client.delete(key);
71
+ }
72
+ /**
73
+ * Clear the cache
74
+ */
75
+ async clear() {
76
+ this._client.clear();
77
+ }
78
+ };
79
+ //#endregion
80
+ //#region src/redis/index.ts
81
+ /**
82
+ * Distributed cache backed by Redis
83
+ */
84
+ var RedisCache = class {
85
+ client;
86
+ _defaultTtl;
87
+ constructor(params) {
88
+ this._defaultTtl = params.ttl;
89
+ this.client = new ioredis.Redis({
90
+ host: params.host,
91
+ port: params.port,
92
+ password: params.password,
93
+ db: params.db,
94
+ keyPrefix: params.keyPrefix
95
+ });
96
+ }
97
+ /**
98
+ * Get a value from the cache
99
+ */
100
+ async get(key) {
101
+ const value = await this.client.get(key);
102
+ if (value === null) return;
103
+ return JSON.parse(value);
104
+ }
105
+ /**
106
+ * Set a value in the cache
107
+ */
108
+ async set(key, value, ttl) {
109
+ const serialized = JSON.stringify(value);
110
+ const expires = ttl ?? this._defaultTtl;
111
+ if (expires) {
112
+ await this.client.set(key, serialized, "EX", expires);
113
+ return;
114
+ }
115
+ await this.client.set(key, serialized);
116
+ }
117
+ /**
118
+ * Check if a key exists in the cache
119
+ */
120
+ async has(key) {
121
+ return await this.client.exists(key) === 1;
122
+ }
123
+ /**
124
+ * Delete a value from the cache
125
+ */
126
+ async del(key) {
127
+ await this.client.del(key);
128
+ }
129
+ /**
130
+ * Clear the cache
131
+ */
132
+ async clear() {
133
+ await this.client.flushdb();
134
+ }
135
+ };
136
+ //#endregion
137
+ //#region src/schema/index.ts
138
+ const CacheSchema = zod.default.object({ driver: zod.default.enum(["memory", "redis"]) });
139
+ //#endregion
140
+ //#region src/schema/memory.ts
141
+ const MemorySchema = zod.default.object({
142
+ max: zod.default.number().int().positive().default(500),
143
+ ttl: zod.default.number().int().positive().optional()
144
+ });
145
+ //#endregion
146
+ //#region src/schema/redis.ts
147
+ const RedisSchema = zod.default.object({
148
+ host: zod.default.string().default("127.0.0.1"),
149
+ port: zod.default.number().int().positive().default(6379),
150
+ password: zod.default.string().optional(),
151
+ db: zod.default.number().int().nonnegative().optional(),
152
+ keyPrefix: zod.default.string().optional(),
153
+ ttl: zod.default.number().int().positive().optional()
154
+ });
155
+ //#endregion
156
+ //#region src/index.ts
157
+ /**
158
+ * Cache service
159
+ */
160
+ var Cache = class {
161
+ /**
162
+ * Create a cache service instance
163
+ * @param params - Cache parameters
164
+ * @returns Cache service instance
165
+ */
166
+ static create({ cacheType, params }) {
167
+ const parsed = CacheSchema.safeParse({ driver: cacheType });
168
+ if (!parsed.success) {
169
+ console.log(parsed.error);
170
+ throw new Error("Invalid cache driver");
171
+ }
172
+ switch (parsed.data.driver) {
173
+ case "memory": {
174
+ const config = MemorySchema.safeParse(params);
175
+ if (!config.success) {
176
+ console.log(config.error);
177
+ throw new Error("Invalid memory cache configuration");
178
+ }
179
+ return new MemoryCache(config.data);
180
+ }
181
+ case "redis": {
182
+ const config = RedisSchema.safeParse(params);
183
+ if (!config.success) {
184
+ console.log(config.error);
185
+ throw new Error("Invalid redis cache configuration");
186
+ }
187
+ return new RedisCache(config.data);
188
+ }
189
+ default: throw new Error("Invalid cache type");
190
+ }
191
+ }
192
+ };
193
+ //#endregion
194
+ exports.MemoryCache = MemoryCache;
195
+ exports.RedisCache = RedisCache;
196
+ exports.default = Cache;
@@ -0,0 +1,107 @@
1
+ import z from "zod";
2
+ import { Redis } from "ioredis";
3
+ //#region src/schema/memory.d.ts
4
+ declare const MemorySchema: z.ZodObject<{
5
+ max: z.ZodDefault<z.ZodNumber>;
6
+ ttl: z.ZodOptional<z.ZodNumber>;
7
+ }>;
8
+ type MemoryConfig = z.infer<typeof MemorySchema>;
9
+ //#endregion
10
+ //#region src/memory/index.d.ts
11
+ declare class MemoryCache implements CacheDriver {
12
+ private _client;
13
+ private _defaultTtl;
14
+ constructor(params: MemoryConfig);
15
+ /**
16
+ * Get a value from the cache
17
+ */
18
+ get<T = unknown>(key: string): Promise<T | undefined>;
19
+ /**
20
+ * Set a value in the cache
21
+ */
22
+ set<T = unknown>(key: string, value: T, ttl?: number): Promise<void>;
23
+ /**
24
+ * Check if a key exists in the cache
25
+ */
26
+ has(key: string): Promise<boolean>;
27
+ /**
28
+ * Delete a value from the cache
29
+ */
30
+ del(key: string): Promise<void>;
31
+ /**
32
+ * Clear the cache
33
+ */
34
+ clear(): Promise<void>;
35
+ }
36
+ //#endregion
37
+ //#region src/schema/redis.d.ts
38
+ declare const RedisSchema: z.ZodObject<{
39
+ host: z.ZodDefault<z.ZodString>;
40
+ port: z.ZodDefault<z.ZodNumber>;
41
+ password: z.ZodOptional<z.ZodString>;
42
+ db: z.ZodOptional<z.ZodNumber>;
43
+ keyPrefix: z.ZodOptional<z.ZodString>;
44
+ ttl: z.ZodOptional<z.ZodNumber>;
45
+ }>;
46
+ type RedisConfig = z.infer<typeof RedisSchema>;
47
+ //#endregion
48
+ //#region src/redis/index.d.ts
49
+ /**
50
+ * Distributed cache backed by Redis
51
+ */
52
+ declare class RedisCache implements CacheDriver {
53
+ client: Redis;
54
+ private _defaultTtl;
55
+ constructor(params: RedisConfig);
56
+ /**
57
+ * Get a value from the cache
58
+ */
59
+ get<T = unknown>(key: string): Promise<T | undefined>;
60
+ /**
61
+ * Set a value in the cache
62
+ */
63
+ set<T = unknown>(key: string, value: T, ttl?: number): Promise<void>;
64
+ /**
65
+ * Check if a key exists in the cache
66
+ */
67
+ has(key: string): Promise<boolean>;
68
+ /**
69
+ * Delete a value from the cache
70
+ */
71
+ del(key: string): Promise<void>;
72
+ /**
73
+ * Clear the cache
74
+ */
75
+ clear(): Promise<void>;
76
+ }
77
+ //#endregion
78
+ //#region src/types/cache.d.ts
79
+ type CacheType = "memory" | "redis";
80
+ type CacheParams = {
81
+ cacheType: CacheType;
82
+ params: MemoryConfig | RedisConfig;
83
+ };
84
+ type CacheInstance = MemoryCache | RedisCache;
85
+ interface CacheDriver {
86
+ get<T = unknown>(key: string): Promise<T | undefined>;
87
+ set<T = unknown>(key: string, value: T, ttl?: number): Promise<void>;
88
+ has(key: string): Promise<boolean>;
89
+ del(key: string): Promise<void>;
90
+ clear(): Promise<void>;
91
+ }
92
+ //#endregion
93
+ //#region src/index.d.ts
94
+ /**
95
+ * Cache service
96
+ */
97
+ declare class Cache {
98
+ /**
99
+ * Create a cache service instance
100
+ * @param params - Cache parameters
101
+ * @returns Cache service instance
102
+ */
103
+ static create({ cacheType, params }: CacheParams): CacheInstance;
104
+ }
105
+ //#endregion
106
+ export { type CacheDriver, type CacheInstance, type CacheParams, type CacheType, MemoryCache, RedisCache, Cache as default };
107
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/schema/memory.ts","../src/memory/index.ts","../src/schema/redis.ts","../src/redis/index.ts","../src/types/cache.ts","../src/index.ts"],"mappings":";;;cAEa,cAAc,EAAE;EAC3B,KAAK,EAAE,WAAW,EAAE;EACpB,KAAK,EAAE,YAAY,EAAE;;KAMX,eAAe,EAAE,aAAa;;;cCDrB,uBAAuB;UAClC;UACA;EAER,YAAY,QAAQ;;;;EAapB,IAAU,aAAa,cAAc,QAAQ;;;;EAQ7C,IAAU,aAAa,aAAa,OAAO,GAAG,eAAe;;;;EAc7D,IAAU,cAAc;;;;EAOxB,IAAU,cAAc;;;;EAOxB,SAAe;;;;cC5DJ,aAAa,EAAE;EAC1B,MAAM,EAAE,WAAW,EAAE;EACrB,MAAM,EAAE,WAAW,EAAE;EACrB,UAAU,EAAE,YAAY,EAAE;EAC1B,IAAI,EAAE,YAAY,EAAE;EACpB,WAAW,EAAE,YAAY,EAAE;EAC3B,KAAK,EAAE,YAAY,EAAE;;KAUX,cAAc,EAAE,aAAa;;;;;;cCXpB,sBAAsB;EACzC,QAAe;UACP;EAER,YAAY,QAAQ;;;;EAepB,IAAU,aAAa,cAAc,QAAQ;;;;EAY7C,IAAU,aAAa,aAAa,OAAO,GAAG,eAAe;;;;EAe7D,IAAU,cAAc;;;;EAQxB,IAAU,cAAc;;;;EAOxB,SAAe;;;;KC/DL;KAEA;EACV,WAAW;EACX,QAAQ,eAAe;;KAGb,gBAAgB,cAAc;UAEzB;EACf,IAAI,aAAa,cAAc,QAAQ;EACvC,IAAI,aAAa,aAAa,OAAO,GAAG,eAAe;EACvD,IAAI,cAAc;EAClB,IAAI,cAAc;EAClB,SAAS;;;;;;;cCTU;;;;;;SAMZ,SAAS,WAAW,UAAU,cAAc"}
@@ -0,0 +1,107 @@
1
+ import { Redis } from "ioredis";
2
+ import z from "zod";
3
+ //#region src/schema/memory.d.ts
4
+ declare const MemorySchema: z.ZodObject<{
5
+ max: z.ZodDefault<z.ZodNumber>;
6
+ ttl: z.ZodOptional<z.ZodNumber>;
7
+ }>;
8
+ type MemoryConfig = z.infer<typeof MemorySchema>;
9
+ //#endregion
10
+ //#region src/memory/index.d.ts
11
+ declare class MemoryCache implements CacheDriver {
12
+ private _client;
13
+ private _defaultTtl;
14
+ constructor(params: MemoryConfig);
15
+ /**
16
+ * Get a value from the cache
17
+ */
18
+ get<T = unknown>(key: string): Promise<T | undefined>;
19
+ /**
20
+ * Set a value in the cache
21
+ */
22
+ set<T = unknown>(key: string, value: T, ttl?: number): Promise<void>;
23
+ /**
24
+ * Check if a key exists in the cache
25
+ */
26
+ has(key: string): Promise<boolean>;
27
+ /**
28
+ * Delete a value from the cache
29
+ */
30
+ del(key: string): Promise<void>;
31
+ /**
32
+ * Clear the cache
33
+ */
34
+ clear(): Promise<void>;
35
+ }
36
+ //#endregion
37
+ //#region src/schema/redis.d.ts
38
+ declare const RedisSchema: z.ZodObject<{
39
+ host: z.ZodDefault<z.ZodString>;
40
+ port: z.ZodDefault<z.ZodNumber>;
41
+ password: z.ZodOptional<z.ZodString>;
42
+ db: z.ZodOptional<z.ZodNumber>;
43
+ keyPrefix: z.ZodOptional<z.ZodString>;
44
+ ttl: z.ZodOptional<z.ZodNumber>;
45
+ }>;
46
+ type RedisConfig = z.infer<typeof RedisSchema>;
47
+ //#endregion
48
+ //#region src/redis/index.d.ts
49
+ /**
50
+ * Distributed cache backed by Redis
51
+ */
52
+ declare class RedisCache implements CacheDriver {
53
+ client: Redis;
54
+ private _defaultTtl;
55
+ constructor(params: RedisConfig);
56
+ /**
57
+ * Get a value from the cache
58
+ */
59
+ get<T = unknown>(key: string): Promise<T | undefined>;
60
+ /**
61
+ * Set a value in the cache
62
+ */
63
+ set<T = unknown>(key: string, value: T, ttl?: number): Promise<void>;
64
+ /**
65
+ * Check if a key exists in the cache
66
+ */
67
+ has(key: string): Promise<boolean>;
68
+ /**
69
+ * Delete a value from the cache
70
+ */
71
+ del(key: string): Promise<void>;
72
+ /**
73
+ * Clear the cache
74
+ */
75
+ clear(): Promise<void>;
76
+ }
77
+ //#endregion
78
+ //#region src/types/cache.d.ts
79
+ type CacheType = "memory" | "redis";
80
+ type CacheParams = {
81
+ cacheType: CacheType;
82
+ params: MemoryConfig | RedisConfig;
83
+ };
84
+ type CacheInstance = MemoryCache | RedisCache;
85
+ interface CacheDriver {
86
+ get<T = unknown>(key: string): Promise<T | undefined>;
87
+ set<T = unknown>(key: string, value: T, ttl?: number): Promise<void>;
88
+ has(key: string): Promise<boolean>;
89
+ del(key: string): Promise<void>;
90
+ clear(): Promise<void>;
91
+ }
92
+ //#endregion
93
+ //#region src/index.d.ts
94
+ /**
95
+ * Cache service
96
+ */
97
+ declare class Cache {
98
+ /**
99
+ * Create a cache service instance
100
+ * @param params - Cache parameters
101
+ * @returns Cache service instance
102
+ */
103
+ static create({ cacheType, params }: CacheParams): CacheInstance;
104
+ }
105
+ //#endregion
106
+ export { type CacheDriver, type CacheInstance, type CacheParams, type CacheType, MemoryCache, RedisCache, Cache as default };
107
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/schema/memory.ts","../src/memory/index.ts","../src/schema/redis.ts","../src/redis/index.ts","../src/types/cache.ts","../src/index.ts"],"mappings":";;;cAEa,cAAc,EAAE;EAC3B,KAAK,EAAE,WAAW,EAAE;EACpB,KAAK,EAAE,YAAY,EAAE;;KAMX,eAAe,EAAE,aAAa;;;cCDrB,uBAAuB;UAClC;UACA;EAER,YAAY,QAAQ;;;;EAapB,IAAU,aAAa,cAAc,QAAQ;;;;EAQ7C,IAAU,aAAa,aAAa,OAAO,GAAG,eAAe;;;;EAc7D,IAAU,cAAc;;;;EAOxB,IAAU,cAAc;;;;EAOxB,SAAe;;;;cC5DJ,aAAa,EAAE;EAC1B,MAAM,EAAE,WAAW,EAAE;EACrB,MAAM,EAAE,WAAW,EAAE;EACrB,UAAU,EAAE,YAAY,EAAE;EAC1B,IAAI,EAAE,YAAY,EAAE;EACpB,WAAW,EAAE,YAAY,EAAE;EAC3B,KAAK,EAAE,YAAY,EAAE;;KAUX,cAAc,EAAE,aAAa;;;;;;cCXpB,sBAAsB;EACzC,QAAe;UACP;EAER,YAAY,QAAQ;;;;EAepB,IAAU,aAAa,cAAc,QAAQ;;;;EAY7C,IAAU,aAAa,aAAa,OAAO,GAAG,eAAe;;;;EAe7D,IAAU,cAAc;;;;EAQxB,IAAU,cAAc;;;;EAOxB,SAAe;;;;KC/DL;KAEA;EACV,WAAW;EACX,QAAQ,eAAe;;KAGb,gBAAgB,cAAc;UAEzB;EACf,IAAI,aAAa,cAAc,QAAQ;EACvC,IAAI,aAAa,aAAa,OAAO,GAAG,eAAe;EACvD,IAAI,cAAc;EAClB,IAAI,cAAc;EAClB,SAAS;;;;;;;cCTU;;;;;;SAMZ,SAAS,WAAW,UAAU,cAAc"}
package/dist/index.mjs ADDED
@@ -0,0 +1,169 @@
1
+ import { LRUCache } from "lru-cache";
2
+ import { Redis } from "ioredis";
3
+ import z from "zod";
4
+ //#region src/memory/index.ts
5
+ var MemoryCache = class {
6
+ _client;
7
+ _defaultTtl;
8
+ constructor(params) {
9
+ this._defaultTtl = params.ttl;
10
+ this._client = new LRUCache({
11
+ max: params.max,
12
+ ttlAutopurge: false,
13
+ ...params.ttl ? { ttl: params.ttl * 1e3 } : {}
14
+ });
15
+ }
16
+ /**
17
+ * Get a value from the cache
18
+ */
19
+ async get(key) {
20
+ return this._client.get(key)?.value;
21
+ }
22
+ /**
23
+ * Set a value in the cache
24
+ */
25
+ async set(key, value, ttl) {
26
+ const expires = ttl ?? this._defaultTtl;
27
+ if (expires) {
28
+ this._client.set(key, { value }, { ttl: expires * 1e3 });
29
+ return;
30
+ }
31
+ this._client.set(key, { value });
32
+ }
33
+ /**
34
+ * Check if a key exists in the cache
35
+ */
36
+ async has(key) {
37
+ return this._client.has(key);
38
+ }
39
+ /**
40
+ * Delete a value from the cache
41
+ */
42
+ async del(key) {
43
+ this._client.delete(key);
44
+ }
45
+ /**
46
+ * Clear the cache
47
+ */
48
+ async clear() {
49
+ this._client.clear();
50
+ }
51
+ };
52
+ //#endregion
53
+ //#region src/redis/index.ts
54
+ /**
55
+ * Distributed cache backed by Redis
56
+ */
57
+ var RedisCache = class {
58
+ client;
59
+ _defaultTtl;
60
+ constructor(params) {
61
+ this._defaultTtl = params.ttl;
62
+ this.client = new Redis({
63
+ host: params.host,
64
+ port: params.port,
65
+ password: params.password,
66
+ db: params.db,
67
+ keyPrefix: params.keyPrefix
68
+ });
69
+ }
70
+ /**
71
+ * Get a value from the cache
72
+ */
73
+ async get(key) {
74
+ const value = await this.client.get(key);
75
+ if (value === null) return;
76
+ return JSON.parse(value);
77
+ }
78
+ /**
79
+ * Set a value in the cache
80
+ */
81
+ async set(key, value, ttl) {
82
+ const serialized = JSON.stringify(value);
83
+ const expires = ttl ?? this._defaultTtl;
84
+ if (expires) {
85
+ await this.client.set(key, serialized, "EX", expires);
86
+ return;
87
+ }
88
+ await this.client.set(key, serialized);
89
+ }
90
+ /**
91
+ * Check if a key exists in the cache
92
+ */
93
+ async has(key) {
94
+ return await this.client.exists(key) === 1;
95
+ }
96
+ /**
97
+ * Delete a value from the cache
98
+ */
99
+ async del(key) {
100
+ await this.client.del(key);
101
+ }
102
+ /**
103
+ * Clear the cache
104
+ */
105
+ async clear() {
106
+ await this.client.flushdb();
107
+ }
108
+ };
109
+ //#endregion
110
+ //#region src/schema/index.ts
111
+ const CacheSchema = z.object({ driver: z.enum(["memory", "redis"]) });
112
+ //#endregion
113
+ //#region src/schema/memory.ts
114
+ const MemorySchema = z.object({
115
+ max: z.number().int().positive().default(500),
116
+ ttl: z.number().int().positive().optional()
117
+ });
118
+ //#endregion
119
+ //#region src/schema/redis.ts
120
+ const RedisSchema = z.object({
121
+ host: z.string().default("127.0.0.1"),
122
+ port: z.number().int().positive().default(6379),
123
+ password: z.string().optional(),
124
+ db: z.number().int().nonnegative().optional(),
125
+ keyPrefix: z.string().optional(),
126
+ ttl: z.number().int().positive().optional()
127
+ });
128
+ //#endregion
129
+ //#region src/index.ts
130
+ /**
131
+ * Cache service
132
+ */
133
+ var Cache = class {
134
+ /**
135
+ * Create a cache service instance
136
+ * @param params - Cache parameters
137
+ * @returns Cache service instance
138
+ */
139
+ static create({ cacheType, params }) {
140
+ const parsed = CacheSchema.safeParse({ driver: cacheType });
141
+ if (!parsed.success) {
142
+ console.log(parsed.error);
143
+ throw new Error("Invalid cache driver");
144
+ }
145
+ switch (parsed.data.driver) {
146
+ case "memory": {
147
+ const config = MemorySchema.safeParse(params);
148
+ if (!config.success) {
149
+ console.log(config.error);
150
+ throw new Error("Invalid memory cache configuration");
151
+ }
152
+ return new MemoryCache(config.data);
153
+ }
154
+ case "redis": {
155
+ const config = RedisSchema.safeParse(params);
156
+ if (!config.success) {
157
+ console.log(config.error);
158
+ throw new Error("Invalid redis cache configuration");
159
+ }
160
+ return new RedisCache(config.data);
161
+ }
162
+ default: throw new Error("Invalid cache type");
163
+ }
164
+ }
165
+ };
166
+ //#endregion
167
+ export { MemoryCache, RedisCache, Cache as default };
168
+
169
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/memory/index.ts","../src/redis/index.ts","../src/schema/index.ts","../src/schema/memory.ts","../src/schema/redis.ts","../src/index.ts"],"sourcesContent":["import { LRUCache } from 'lru-cache'\nimport { MemoryConfig } from '../schema/memory'\nimport { CacheDriver } from '../types/cache'\n\n/**\n * In-process memory cache backed by lru-cache\n */\ntype CacheEntry = { value: unknown }\n\nexport default class MemoryCache implements CacheDriver {\n private _client: LRUCache<string, CacheEntry>\n private _defaultTtl: number | undefined\n\n constructor(params: MemoryConfig) {\n this._defaultTtl = params.ttl\n\n this._client = new LRUCache<string, CacheEntry>({\n max: params.max,\n ttlAutopurge: false,\n ...(params.ttl ? { ttl: params.ttl * 1000 } : {}),\n })\n }\n\n /**\n * Get a value from the cache\n */\n async get<T = unknown>(key: string): Promise<T | undefined> {\n const entry = this._client.get(key)\n return entry?.value as T | undefined\n }\n\n /**\n * Set a value in the cache\n */\n async set<T = unknown>(key: string, value: T, ttl?: number): Promise<void> {\n const expires = ttl ?? this._defaultTtl\n\n if (expires) {\n this._client.set(key, { value }, { ttl: expires * 1000 })\n return\n }\n\n this._client.set(key, { value })\n }\n\n /**\n * Check if a key exists in the cache\n */\n async has(key: string): Promise<boolean> {\n return this._client.has(key)\n }\n\n /**\n * Delete a value from the cache\n */\n async del(key: string): Promise<void> {\n this._client.delete(key)\n }\n\n /**\n * Clear the cache\n */\n async clear(): Promise<void> {\n this._client.clear()\n }\n}\n","import { Redis } from 'ioredis'\nimport { RedisConfig } from '../schema/redis'\nimport { CacheDriver } from '../types/cache'\n\n/**\n * Distributed cache backed by Redis\n */\nexport default class RedisCache implements CacheDriver {\n public client: Redis\n private _defaultTtl: number | undefined\n\n constructor(params: RedisConfig) {\n this._defaultTtl = params.ttl\n\n this.client = new Redis({\n host: params.host,\n port: params.port,\n password: params.password,\n db: params.db,\n keyPrefix: params.keyPrefix,\n })\n }\n\n /**\n * Get a value from the cache\n */\n async get<T = unknown>(key: string): Promise<T | undefined> {\n const value = await this.client.get(key)\n if (value === null) {\n return undefined\n }\n\n return JSON.parse(value) as T\n }\n\n /**\n * Set a value in the cache\n */\n async set<T = unknown>(key: string, value: T, ttl?: number): Promise<void> {\n const serialized = JSON.stringify(value)\n const expires = ttl ?? this._defaultTtl\n\n if (expires) {\n await this.client.set(key, serialized, 'EX', expires)\n return\n }\n\n await this.client.set(key, serialized)\n }\n\n /**\n * Check if a key exists in the cache\n */\n async has(key: string): Promise<boolean> {\n const exists = await this.client.exists(key)\n return exists === 1\n }\n\n /**\n * Delete a value from the cache\n */\n async del(key: string): Promise<void> {\n await this.client.del(key)\n }\n\n /**\n * Clear the cache\n */\n async clear(): Promise<void> {\n await this.client.flushdb()\n }\n}\n","import z from 'zod'\n\nexport const CacheSchema: z.ZodObject<{\n driver: z.ZodEnum<{\n memory: 'memory'\n redis: 'redis'\n }>\n}> = z.object({\n driver: z.enum(['memory', 'redis']),\n})\n\nexport type CacheDriverType = z.infer<typeof CacheSchema>['driver']\n","import z from 'zod'\n\nexport const MemorySchema: z.ZodObject<{\n max: z.ZodDefault<z.ZodNumber>\n ttl: z.ZodOptional<z.ZodNumber>\n}> = z.object({\n max: z.number().int().positive().default(500),\n ttl: z.number().int().positive().optional(),\n})\n\nexport type MemoryConfig = z.infer<typeof MemorySchema>\n","import z from 'zod'\n\nexport const RedisSchema: z.ZodObject<{\n host: z.ZodDefault<z.ZodString>\n port: z.ZodDefault<z.ZodNumber>\n password: z.ZodOptional<z.ZodString>\n db: z.ZodOptional<z.ZodNumber>\n keyPrefix: z.ZodOptional<z.ZodString>\n ttl: z.ZodOptional<z.ZodNumber>\n}> = z.object({\n host: z.string().default('127.0.0.1'),\n port: z.number().int().positive().default(6379),\n password: z.string().optional(),\n db: z.number().int().nonnegative().optional(),\n keyPrefix: z.string().optional(),\n ttl: z.number().int().positive().optional(),\n})\n\nexport type RedisConfig = z.infer<typeof RedisSchema>\n","import MemoryCache from './memory'\nimport RedisCache from './redis'\nimport { CacheSchema } from './schema'\nimport { MemorySchema } from './schema/memory'\nimport { RedisSchema } from './schema/redis'\nimport { CacheInstance, CacheParams } from './types/cache'\n\n/**\n * Cache service\n */\nexport default class Cache {\n /**\n * Create a cache service instance\n * @param params - Cache parameters\n * @returns Cache service instance\n */\n static create({ cacheType, params }: CacheParams): CacheInstance {\n const parsed = CacheSchema.safeParse({ driver: cacheType })\n if (!parsed.success) {\n console.log(parsed.error)\n throw new Error('Invalid cache driver')\n }\n\n switch (parsed.data.driver) {\n case 'memory': {\n const config = MemorySchema.safeParse(params)\n if (!config.success) {\n console.log(config.error)\n throw new Error('Invalid memory cache configuration')\n }\n\n return new MemoryCache(config.data)\n }\n\n case 'redis': {\n const config = RedisSchema.safeParse(params)\n if (!config.success) {\n console.log(config.error)\n throw new Error('Invalid redis cache configuration')\n }\n\n return new RedisCache(config.data)\n }\n\n default:\n throw new Error('Invalid cache type')\n }\n }\n}\n\nexport { default as MemoryCache } from './memory'\nexport { default as RedisCache } from './redis'\nexport type { CacheDriver, CacheInstance, CacheParams, CacheType } from './types/cache'\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "honojs-plugin-memory",
3
+ "version": "0.0.0",
4
+ "description": "Memory plugin for HonoJS",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "main": "./dist/index.cjs",
8
+ "module": "./dist/index.mjs",
9
+ "types": "./dist/index.d.cts",
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "keywords": [],
14
+ "author": "masb0ymas <me@masb0ymas.com> (https://github.com/masb0ymas)",
15
+ "dependencies": {
16
+ "ioredis": "^5.11.1",
17
+ "lru-cache": "^11.5.2",
18
+ "zod": "^4.4.3"
19
+ },
20
+ "exports": {
21
+ ".": {
22
+ "import": "./dist/index.mjs",
23
+ "require": "./dist/index.cjs"
24
+ },
25
+ "./package.json": "./package.json"
26
+ },
27
+ "license": "MIT",
28
+ "publishConfig": {
29
+ "registry": "https://registry.npmjs.org",
30
+ "access": "public",
31
+ "provenance": true
32
+ },
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/masb0ymas/honojs-plugins.git",
36
+ "directory": "packages/memory"
37
+ },
38
+ "homepage": "https://github.com/masb0ymas/honojs-plugins",
39
+ "engines": {
40
+ "node": ">=20.0.0"
41
+ },
42
+ "scripts": {
43
+ "build": "pnpm -w run build:pkg",
44
+ "lint": "eslint",
45
+ "typecheck": "tsc -b tsconfig.json"
46
+ }
47
+ }