@joint-ops/hitlimit-bun 1.2.0 → 1.3.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 CHANGED
@@ -94,10 +94,19 @@ new Elysia()
94
94
 
95
95
  ---
96
96
 
97
- ## 4 Storage Backends
97
+ ## 6 Storage Backends
98
98
 
99
99
  All built in. No extra packages to install.
100
100
 
101
+ | Store | Best For | Peer Dependency |
102
+ |---|---|---|
103
+ | Memory | Development, single server | None |
104
+ | bun:sqlite | Single server + persistence | None (built-in) |
105
+ | Redis | Distributed, production | `ioredis` |
106
+ | **Valkey** | **Distributed, open-source Redis alternative** | `ioredis` |
107
+ | **DragonflyDB** | **High-throughput distributed** | `ioredis` |
108
+ | PostgreSQL | Shared database infrastructure | `pg` |
109
+
101
110
  ```typescript
102
111
  import { hitlimit } from '@joint-ops/hitlimit-bun'
103
112
 
@@ -112,6 +121,14 @@ Bun.serve({ fetch: hitlimit({ store: sqliteStore({ path: './ratelimit.db' }) },
112
121
  import { redisStore } from '@joint-ops/hitlimit-bun/stores/redis'
113
122
  Bun.serve({ fetch: hitlimit({ store: redisStore({ url: 'redis://localhost:6379' }) }, handler) })
114
123
 
124
+ // Valkey — open-source Redis alternative
125
+ import { valkeyStore } from '@joint-ops/hitlimit-bun/stores/valkey'
126
+ Bun.serve({ fetch: hitlimit({ store: valkeyStore({ url: 'redis://localhost:6379' }) }, handler) })
127
+
128
+ // DragonflyDB — high-throughput Redis alternative
129
+ import { dragonflyStore } from '@joint-ops/hitlimit-bun/stores/dragonfly'
130
+ Bun.serve({ fetch: hitlimit({ store: dragonflyStore({ url: 'redis://localhost:6379' }) }, handler) })
131
+
115
132
  // Postgres — distributed, atomic upserts
116
133
  import { postgresStore } from '@joint-ops/hitlimit-bun/stores/postgres'
117
134
  Bun.serve({ fetch: hitlimit({ store: postgresStore({ url: 'postgres://localhost:5432/mydb' }) }, handler) })
@@ -124,6 +141,34 @@ Bun.serve({ fetch: hitlimit({ store: postgresStore({ url: 'postgres://localhost:
124
141
  | Redis | 6,700 | 148μs | Multi-server / distributed |
125
142
  | Postgres | 3,700 | 273μs | Multi-server / already using Postgres |
126
143
 
144
+ ### Valkey (Redis Alternative)
145
+ ```typescript
146
+ import { hitlimit } from '@joint-ops/hitlimit-bun'
147
+ import { valkeyStore } from '@joint-ops/hitlimit-bun/stores/valkey'
148
+
149
+ Bun.serve({
150
+ fetch: hitlimit({
151
+ store: valkeyStore({ url: 'redis://localhost:6379' }),
152
+ limit: 100,
153
+ window: '1m'
154
+ }, handler)
155
+ })
156
+ ```
157
+
158
+ ### DragonflyDB
159
+ ```typescript
160
+ import { hitlimit } from '@joint-ops/hitlimit-bun'
161
+ import { dragonflyStore } from '@joint-ops/hitlimit-bun/stores/dragonfly'
162
+
163
+ Bun.serve({
164
+ fetch: hitlimit({
165
+ store: dragonflyStore({ url: 'redis://localhost:6379' }),
166
+ limit: 100,
167
+ window: '1m'
168
+ }, handler)
169
+ })
170
+ ```
171
+
127
172
  ---
128
173
 
129
174
  ## Performance
@@ -0,0 +1,9 @@
1
+ import type { HitLimitStore } from '@joint-ops/hitlimit-types';
2
+ export interface DragonflyStoreOptions {
3
+ /** DragonflyDB connection URL. Default: 'redis://localhost:6379' */
4
+ url?: string;
5
+ /** Key prefix for all rate limit keys. Default: 'hitlimit:' */
6
+ keyPrefix?: string;
7
+ }
8
+ export declare function dragonflyStore(options?: DragonflyStoreOptions): HitLimitStore;
9
+ //# sourceMappingURL=dragonfly.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dragonfly.d.ts","sourceRoot":"","sources":["../../src/stores/dragonfly.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAG9D,MAAM,WAAW,qBAAqB;IACpC,oEAAoE;IACpE,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,aAAa,CAE7E"}
@@ -0,0 +1,133 @@
1
+ // @bun
2
+ // src/stores/redis.ts
3
+ import Redis from "ioredis";
4
+ var HIT_SCRIPT = `
5
+ local key = KEYS[1]
6
+ local windowMs = tonumber(ARGV[1])
7
+ local count = redis.call('INCR', key)
8
+ local ttl = redis.call('PTTL', key)
9
+ if ttl < 0 then
10
+ redis.call('PEXPIRE', key, windowMs)
11
+ ttl = windowMs
12
+ end
13
+ return {count, ttl}
14
+ `;
15
+ var HIT_WITH_BAN_SCRIPT = `
16
+ local hitKey = KEYS[1]
17
+ local banKey = KEYS[2]
18
+ local violationKey = KEYS[3]
19
+ local windowMs = tonumber(ARGV[1])
20
+ local limit = tonumber(ARGV[2])
21
+ local banThreshold = tonumber(ARGV[3])
22
+ local banDurationMs = tonumber(ARGV[4])
23
+
24
+ -- Check ban first
25
+ local banTTL = redis.call('PTTL', banKey)
26
+ if banTTL > 0 then
27
+ return {-1, banTTL, 1, 0}
28
+ end
29
+
30
+ -- Hit counter
31
+ local count = redis.call('INCR', hitKey)
32
+ local ttl = redis.call('PTTL', hitKey)
33
+ if ttl < 0 then
34
+ redis.call('PEXPIRE', hitKey, windowMs)
35
+ ttl = windowMs
36
+ end
37
+
38
+ -- Track violations if over limit
39
+ local banned = 0
40
+ local violations = 0
41
+ if count > limit then
42
+ violations = redis.call('INCR', violationKey)
43
+ local vTTL = redis.call('PTTL', violationKey)
44
+ if vTTL < 0 then
45
+ redis.call('PEXPIRE', violationKey, banDurationMs)
46
+ end
47
+ if violations >= banThreshold then
48
+ redis.call('SET', banKey, '1', 'PX', banDurationMs)
49
+ banned = 1
50
+ end
51
+ end
52
+ return {count, ttl, banned, violations}
53
+ `;
54
+
55
+ class RedisStore {
56
+ redis;
57
+ prefix;
58
+ banPrefix;
59
+ violationPrefix;
60
+ constructor(options = {}) {
61
+ this.redis = new Redis(options.url ?? "redis://localhost:6379");
62
+ this.prefix = options.keyPrefix ?? "hitlimit:";
63
+ this.banPrefix = (options.keyPrefix ?? "hitlimit:") + "ban:";
64
+ this.violationPrefix = (options.keyPrefix ?? "hitlimit:") + "violations:";
65
+ this.redis.defineCommand("hitlimitHit", {
66
+ numberOfKeys: 1,
67
+ lua: HIT_SCRIPT
68
+ });
69
+ this.redis.defineCommand("hitlimitHitWithBan", {
70
+ numberOfKeys: 3,
71
+ lua: HIT_WITH_BAN_SCRIPT
72
+ });
73
+ }
74
+ async hit(key, windowMs, _limit) {
75
+ const redisKey = this.prefix + key;
76
+ const result = await this.redis.hitlimitHit(redisKey, windowMs);
77
+ const count = result[0];
78
+ const ttl = result[1];
79
+ return { count, resetAt: Date.now() + ttl };
80
+ }
81
+ async hitWithBan(key, windowMs, limit, banThreshold, banDurationMs) {
82
+ const hitKey = this.prefix + key;
83
+ const banKey = this.banPrefix + key;
84
+ const violationKey = this.violationPrefix + key;
85
+ const result = await this.redis.hitlimitHitWithBan(hitKey, banKey, violationKey, windowMs, limit, banThreshold, banDurationMs);
86
+ const count = result[0];
87
+ const ttl = result[1];
88
+ const banned = result[2] === 1;
89
+ const violations = result[3];
90
+ if (count === -1) {
91
+ return { count: 0, resetAt: Date.now() + ttl, banned: true, violations: 0, banExpiresAt: Date.now() + ttl };
92
+ }
93
+ return {
94
+ count,
95
+ resetAt: Date.now() + ttl,
96
+ banned,
97
+ violations,
98
+ banExpiresAt: banned ? Date.now() + banDurationMs : 0
99
+ };
100
+ }
101
+ async isBanned(key) {
102
+ const result = await this.redis.exists(this.banPrefix + key);
103
+ return result === 1;
104
+ }
105
+ async ban(key, durationMs) {
106
+ await this.redis.set(this.banPrefix + key, "1", "PX", durationMs);
107
+ }
108
+ async recordViolation(key, windowMs) {
109
+ const redisKey = this.violationPrefix + key;
110
+ const count = await this.redis.incr(redisKey);
111
+ if (count === 1) {
112
+ await this.redis.pexpire(redisKey, windowMs);
113
+ }
114
+ return count;
115
+ }
116
+ async reset(key) {
117
+ await this.redis.del(this.prefix + key, this.banPrefix + key, this.violationPrefix + key);
118
+ }
119
+ async shutdown() {
120
+ await this.redis.quit();
121
+ }
122
+ }
123
+ function redisStore(options) {
124
+ return new RedisStore(options);
125
+ }
126
+
127
+ // src/stores/dragonfly.ts
128
+ function dragonflyStore(options) {
129
+ return new RedisStore(options);
130
+ }
131
+ export {
132
+ dragonflyStore
133
+ };
@@ -1,7 +1,23 @@
1
- import type { HitLimitStore } from '@joint-ops/hitlimit-types';
1
+ import type { HitLimitStore, HitWithBanResult, StoreResult } from '@joint-ops/hitlimit-types';
2
2
  export interface RedisStoreOptions {
3
3
  url?: string;
4
4
  keyPrefix?: string;
5
5
  }
6
+ export declare const HIT_SCRIPT = "\nlocal key = KEYS[1]\nlocal windowMs = tonumber(ARGV[1])\nlocal count = redis.call('INCR', key)\nlocal ttl = redis.call('PTTL', key)\nif ttl < 0 then\n redis.call('PEXPIRE', key, windowMs)\n ttl = windowMs\nend\nreturn {count, ttl}\n";
7
+ export declare const HIT_WITH_BAN_SCRIPT = "\nlocal hitKey = KEYS[1]\nlocal banKey = KEYS[2]\nlocal violationKey = KEYS[3]\nlocal windowMs = tonumber(ARGV[1])\nlocal limit = tonumber(ARGV[2])\nlocal banThreshold = tonumber(ARGV[3])\nlocal banDurationMs = tonumber(ARGV[4])\n\n-- Check ban first\nlocal banTTL = redis.call('PTTL', banKey)\nif banTTL > 0 then\n return {-1, banTTL, 1, 0}\nend\n\n-- Hit counter\nlocal count = redis.call('INCR', hitKey)\nlocal ttl = redis.call('PTTL', hitKey)\nif ttl < 0 then\n redis.call('PEXPIRE', hitKey, windowMs)\n ttl = windowMs\nend\n\n-- Track violations if over limit\nlocal banned = 0\nlocal violations = 0\nif count > limit then\n violations = redis.call('INCR', violationKey)\n local vTTL = redis.call('PTTL', violationKey)\n if vTTL < 0 then\n redis.call('PEXPIRE', violationKey, banDurationMs)\n end\n if violations >= banThreshold then\n redis.call('SET', banKey, '1', 'PX', banDurationMs)\n banned = 1\n end\nend\nreturn {count, ttl, banned, violations}\n";
8
+ export declare class RedisStore implements HitLimitStore {
9
+ private redis;
10
+ private prefix;
11
+ private banPrefix;
12
+ private violationPrefix;
13
+ constructor(options?: RedisStoreOptions);
14
+ hit(key: string, windowMs: number, _limit: number): Promise<StoreResult>;
15
+ hitWithBan(key: string, windowMs: number, limit: number, banThreshold: number, banDurationMs: number): Promise<HitWithBanResult>;
16
+ isBanned(key: string): Promise<boolean>;
17
+ ban(key: string, durationMs: number): Promise<void>;
18
+ recordViolation(key: string, windowMs: number): Promise<number>;
19
+ reset(key: string): Promise<void>;
20
+ shutdown(): Promise<void>;
21
+ }
6
22
  export declare function redisStore(options?: RedisStoreOptions): HitLimitStore;
7
23
  //# sourceMappingURL=redis.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../src/stores/redis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAiC,MAAM,2BAA2B,CAAA;AAG7F,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAmJD,wBAAgB,UAAU,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,aAAa,CAErE"}
1
+ {"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../src/stores/redis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAG7F,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAGD,eAAO,MAAM,UAAU,iPAUtB,CAAA;AAGD,eAAO,MAAM,mBAAmB,s9BAsC/B,CAAA;AAED,qBAAa,UAAW,YAAW,aAAa;IAC9C,OAAO,CAAC,KAAK,CAAO;IACpB,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,eAAe,CAAQ;gBAEnB,OAAO,GAAE,iBAAsB;IAiBrC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IASxE,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA4BhI,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKvC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAInD,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAS/D,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQjC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAGhC;AAED,wBAAgB,UAAU,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,aAAa,CAErE"}
@@ -124,5 +124,8 @@ function redisStore(options) {
124
124
  return new RedisStore(options);
125
125
  }
126
126
  export {
127
- redisStore
127
+ redisStore,
128
+ RedisStore,
129
+ HIT_WITH_BAN_SCRIPT,
130
+ HIT_SCRIPT
128
131
  };
@@ -0,0 +1,9 @@
1
+ import type { HitLimitStore } from '@joint-ops/hitlimit-types';
2
+ export interface ValkeyStoreOptions {
3
+ /** Valkey connection URL. Default: 'redis://localhost:6379' */
4
+ url?: string;
5
+ /** Key prefix for all rate limit keys. Default: 'hitlimit:' */
6
+ keyPrefix?: string;
7
+ }
8
+ export declare function valkeyStore(options?: ValkeyStoreOptions): HitLimitStore;
9
+ //# sourceMappingURL=valkey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"valkey.d.ts","sourceRoot":"","sources":["../../src/stores/valkey.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAG9D,MAAM,WAAW,kBAAkB;IACjC,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,aAAa,CAEvE"}
@@ -0,0 +1,133 @@
1
+ // @bun
2
+ // src/stores/redis.ts
3
+ import Redis from "ioredis";
4
+ var HIT_SCRIPT = `
5
+ local key = KEYS[1]
6
+ local windowMs = tonumber(ARGV[1])
7
+ local count = redis.call('INCR', key)
8
+ local ttl = redis.call('PTTL', key)
9
+ if ttl < 0 then
10
+ redis.call('PEXPIRE', key, windowMs)
11
+ ttl = windowMs
12
+ end
13
+ return {count, ttl}
14
+ `;
15
+ var HIT_WITH_BAN_SCRIPT = `
16
+ local hitKey = KEYS[1]
17
+ local banKey = KEYS[2]
18
+ local violationKey = KEYS[3]
19
+ local windowMs = tonumber(ARGV[1])
20
+ local limit = tonumber(ARGV[2])
21
+ local banThreshold = tonumber(ARGV[3])
22
+ local banDurationMs = tonumber(ARGV[4])
23
+
24
+ -- Check ban first
25
+ local banTTL = redis.call('PTTL', banKey)
26
+ if banTTL > 0 then
27
+ return {-1, banTTL, 1, 0}
28
+ end
29
+
30
+ -- Hit counter
31
+ local count = redis.call('INCR', hitKey)
32
+ local ttl = redis.call('PTTL', hitKey)
33
+ if ttl < 0 then
34
+ redis.call('PEXPIRE', hitKey, windowMs)
35
+ ttl = windowMs
36
+ end
37
+
38
+ -- Track violations if over limit
39
+ local banned = 0
40
+ local violations = 0
41
+ if count > limit then
42
+ violations = redis.call('INCR', violationKey)
43
+ local vTTL = redis.call('PTTL', violationKey)
44
+ if vTTL < 0 then
45
+ redis.call('PEXPIRE', violationKey, banDurationMs)
46
+ end
47
+ if violations >= banThreshold then
48
+ redis.call('SET', banKey, '1', 'PX', banDurationMs)
49
+ banned = 1
50
+ end
51
+ end
52
+ return {count, ttl, banned, violations}
53
+ `;
54
+
55
+ class RedisStore {
56
+ redis;
57
+ prefix;
58
+ banPrefix;
59
+ violationPrefix;
60
+ constructor(options = {}) {
61
+ this.redis = new Redis(options.url ?? "redis://localhost:6379");
62
+ this.prefix = options.keyPrefix ?? "hitlimit:";
63
+ this.banPrefix = (options.keyPrefix ?? "hitlimit:") + "ban:";
64
+ this.violationPrefix = (options.keyPrefix ?? "hitlimit:") + "violations:";
65
+ this.redis.defineCommand("hitlimitHit", {
66
+ numberOfKeys: 1,
67
+ lua: HIT_SCRIPT
68
+ });
69
+ this.redis.defineCommand("hitlimitHitWithBan", {
70
+ numberOfKeys: 3,
71
+ lua: HIT_WITH_BAN_SCRIPT
72
+ });
73
+ }
74
+ async hit(key, windowMs, _limit) {
75
+ const redisKey = this.prefix + key;
76
+ const result = await this.redis.hitlimitHit(redisKey, windowMs);
77
+ const count = result[0];
78
+ const ttl = result[1];
79
+ return { count, resetAt: Date.now() + ttl };
80
+ }
81
+ async hitWithBan(key, windowMs, limit, banThreshold, banDurationMs) {
82
+ const hitKey = this.prefix + key;
83
+ const banKey = this.banPrefix + key;
84
+ const violationKey = this.violationPrefix + key;
85
+ const result = await this.redis.hitlimitHitWithBan(hitKey, banKey, violationKey, windowMs, limit, banThreshold, banDurationMs);
86
+ const count = result[0];
87
+ const ttl = result[1];
88
+ const banned = result[2] === 1;
89
+ const violations = result[3];
90
+ if (count === -1) {
91
+ return { count: 0, resetAt: Date.now() + ttl, banned: true, violations: 0, banExpiresAt: Date.now() + ttl };
92
+ }
93
+ return {
94
+ count,
95
+ resetAt: Date.now() + ttl,
96
+ banned,
97
+ violations,
98
+ banExpiresAt: banned ? Date.now() + banDurationMs : 0
99
+ };
100
+ }
101
+ async isBanned(key) {
102
+ const result = await this.redis.exists(this.banPrefix + key);
103
+ return result === 1;
104
+ }
105
+ async ban(key, durationMs) {
106
+ await this.redis.set(this.banPrefix + key, "1", "PX", durationMs);
107
+ }
108
+ async recordViolation(key, windowMs) {
109
+ const redisKey = this.violationPrefix + key;
110
+ const count = await this.redis.incr(redisKey);
111
+ if (count === 1) {
112
+ await this.redis.pexpire(redisKey, windowMs);
113
+ }
114
+ return count;
115
+ }
116
+ async reset(key) {
117
+ await this.redis.del(this.prefix + key, this.banPrefix + key, this.violationPrefix + key);
118
+ }
119
+ async shutdown() {
120
+ await this.redis.quit();
121
+ }
122
+ }
123
+ function redisStore(options) {
124
+ return new RedisStore(options);
125
+ }
126
+
127
+ // src/stores/valkey.ts
128
+ function valkeyStore(options) {
129
+ return new RedisStore(options);
130
+ }
131
+ export {
132
+ valkeyStore
133
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@joint-ops/hitlimit-bun",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Ultra-fast Bun-native rate limiting - Memory-first with 6M+ ops/sec for Bun.serve, Elysia & Hono",
5
5
  "author": {
6
6
  "name": "Shayan M Hussain",
@@ -86,7 +86,13 @@
86
86
  "bun-framework",
87
87
  "lightweight",
88
88
  "zero-dependency",
89
- "esm"
89
+ "esm",
90
+ "valkey",
91
+ "valkey-rate-limit",
92
+ "dragonfly",
93
+ "dragonflydb",
94
+ "dragonfly-rate-limit",
95
+ "redis-alternative"
90
96
  ],
91
97
  "type": "module",
92
98
  "main": "./dist/index.js",
@@ -127,6 +133,16 @@
127
133
  "types": "./dist/stores/postgres.d.ts",
128
134
  "bun": "./dist/stores/postgres.js",
129
135
  "import": "./dist/stores/postgres.js"
136
+ },
137
+ "./stores/valkey": {
138
+ "types": "./dist/stores/valkey.d.ts",
139
+ "bun": "./dist/stores/valkey.js",
140
+ "import": "./dist/stores/valkey.js"
141
+ },
142
+ "./stores/dragonfly": {
143
+ "types": "./dist/stores/dragonfly.d.ts",
144
+ "bun": "./dist/stores/dragonfly.js",
145
+ "import": "./dist/stores/dragonfly.js"
130
146
  }
131
147
  },
132
148
  "files": [
@@ -134,13 +150,13 @@
134
150
  ],
135
151
  "sideEffects": false,
136
152
  "scripts": {
137
- "build": "bun build ./src/index.ts ./src/elysia.ts ./src/hono.ts ./src/stores/memory.ts ./src/stores/redis.ts ./src/stores/sqlite.ts ./src/stores/postgres.ts --outdir=./dist --target=bun --external=elysia --external=hono --external=ioredis --external=pg --external=@sinclair/typebox && tsc --emitDeclarationOnly",
153
+ "build": "bun build ./src/index.ts ./src/elysia.ts ./src/hono.ts ./src/stores/memory.ts ./src/stores/redis.ts ./src/stores/sqlite.ts ./src/stores/postgres.ts ./src/stores/valkey.ts ./src/stores/dragonfly.ts --outdir=./dist --root=./src --target=bun --external=elysia --external=hono --external=ioredis --external=pg --external=@sinclair/typebox && tsc --emitDeclarationOnly",
138
154
  "clean": "rm -rf dist",
139
155
  "test": "bun test",
140
156
  "test:watch": "bun test --watch"
141
157
  },
142
158
  "dependencies": {
143
- "@joint-ops/hitlimit-types": "1.2.0"
159
+ "@joint-ops/hitlimit-types": "1.3.0"
144
160
  },
145
161
  "peerDependencies": {
146
162
  "elysia": ">=1.0.0",