drizzle-redis 1.0.0 → 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.
@@ -0,0 +1,283 @@
1
+ let bun = require("bun");
2
+ let drizzle_orm = require("drizzle-orm");
3
+ let drizzle_orm_cache_core = require("drizzle-orm/cache/core");
4
+ let drizzle_orm_entity = require("drizzle-orm/entity");
5
+
6
+ //#region src/bun/cache.ts
7
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
8
+ try {
9
+ var info = gen[key](arg);
10
+ var value = info.value;
11
+ } catch (error) {
12
+ reject(error);
13
+ return;
14
+ }
15
+ if (info.done) {
16
+ resolve(value);
17
+ } else {
18
+ Promise.resolve(value).then(_next, _throw);
19
+ }
20
+ }
21
+ function _async_to_generator(fn) {
22
+ return function() {
23
+ var self = this, args = arguments;
24
+ return new Promise(function(resolve, reject) {
25
+ var gen = fn.apply(self, args);
26
+ function _next(value) {
27
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
28
+ }
29
+ function _throw(err) {
30
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
31
+ }
32
+ _next(undefined);
33
+ });
34
+ };
35
+ }
36
+ function _define_property(obj, key, value) {
37
+ if (key in obj) {
38
+ Object.defineProperty(obj, key, {
39
+ value,
40
+ enumerable: true,
41
+ configurable: true,
42
+ writable: true
43
+ });
44
+ } else {
45
+ obj[key] = value;
46
+ }
47
+ return obj;
48
+ }
49
+ /**
50
+ * Lua script to atomically get a cached value by tag.
51
+ * Looks up the composite table name from the tags map, then retrieves the value.
52
+ */ const getByTagScript = `
53
+ local tagsMapKey = KEYS[1] -- tags map key
54
+ local tag = ARGV[1] -- tag
55
+
56
+ local compositeTableName = redis.call('HGET', tagsMapKey, tag)
57
+ if not compositeTableName then
58
+ return nil
59
+ end
60
+
61
+ local value = redis.call('HGET', compositeTableName, tag)
62
+ return value
63
+ `;
64
+ /**
65
+ * Lua script to atomically invalidate cache entries on mutation.
66
+ * Handles both tag-based and table-based invalidation.
67
+ */ const onMutateScript = `
68
+ local tagsMapKey = KEYS[1] -- tags map key
69
+ local tables = {} -- initialize tables array
70
+ local tags = ARGV -- tags array
71
+
72
+ for i = 2, #KEYS do
73
+ tables[#tables + 1] = KEYS[i] -- add all keys except the first one to tables
74
+ end
75
+
76
+ if #tags > 0 then
77
+ for _, tag in ipairs(tags) do
78
+ if tag ~= nil and tag ~= '' then
79
+ local compositeTableName = redis.call('HGET', tagsMapKey, tag)
80
+ if compositeTableName then
81
+ redis.call('HDEL', compositeTableName, tag)
82
+ end
83
+ end
84
+ end
85
+ redis.call('HDEL', tagsMapKey, unpack(tags))
86
+ end
87
+
88
+ local keysToDelete = {}
89
+
90
+ if #tables > 0 then
91
+ local compositeTableNames = redis.call('SUNION', unpack(tables))
92
+ for _, compositeTableName in ipairs(compositeTableNames) do
93
+ keysToDelete[#keysToDelete + 1] = compositeTableName
94
+ end
95
+ for _, table in ipairs(tables) do
96
+ keysToDelete[#keysToDelete + 1] = table
97
+ end
98
+ redis.call('DEL', unpack(keysToDelete))
99
+ end
100
+ `;
101
+ var BunCache = class BunCache extends drizzle_orm_cache_core.Cache {
102
+ toInternalConfig(config) {
103
+ var _config_ex;
104
+ return config ? {
105
+ seconds: (_config_ex = config.ex) !== null && _config_ex !== void 0 ? _config_ex : 1,
106
+ hexOptions: config.hexOptions
107
+ } : { seconds: 1 };
108
+ }
109
+ strategy() {
110
+ return this.useGlobally ? "all" : "explicit";
111
+ }
112
+ get(key, tables, isTag, isAutoInvalidate) {
113
+ return _async_to_generator(function* () {
114
+ if (!isAutoInvalidate) {
115
+ const result = yield this.client.hget(this.addPrefix(BunCache.nonAutoInvalidateTablePrefix), key);
116
+ return result === null ? undefined : JSON.parse(result);
117
+ }
118
+ if (isTag) {
119
+ const result = yield this.client.send("EVAL", [
120
+ getByTagScript,
121
+ "1",
122
+ this.addPrefix(BunCache.tagsMapKey),
123
+ key
124
+ ]);
125
+ if (result === null) {
126
+ return undefined;
127
+ }
128
+ return JSON.parse(result);
129
+ }
130
+ const compositeKey = this.getCompositeKey(tables);
131
+ const result = yield this.client.hget(compositeKey, key);
132
+ return result === null ? undefined : JSON.parse(result);
133
+ }).call(this);
134
+ }
135
+ put(key, response, tables, isTag = false, config) {
136
+ return _async_to_generator(function* () {
137
+ var _this_internalConfig;
138
+ const isAutoInvalidate = tables.length !== 0;
139
+ const ttlSeconds = config && config.ex ? config.ex : this.internalConfig.seconds;
140
+ const hexOptions = config && config.hexOptions ? config.hexOptions : (_this_internalConfig = this.internalConfig) === null || _this_internalConfig === void 0 ? void 0 : _this_internalConfig.hexOptions;
141
+ const serializedResponse = JSON.stringify(response);
142
+ if (!isAutoInvalidate) {
143
+ const nonAutoInvalidateKey = this.addPrefix(BunCache.nonAutoInvalidateTablePrefix);
144
+ const commands = [];
145
+ if (isTag) {
146
+ const tagsMapKey = this.addPrefix(BunCache.tagsMapKey);
147
+ commands.push(this.client.send("HSET", [
148
+ tagsMapKey,
149
+ key,
150
+ nonAutoInvalidateKey
151
+ ]));
152
+ commands.push(this.hexpire(tagsMapKey, key, ttlSeconds, hexOptions));
153
+ }
154
+ commands.push(this.client.send("HSET", [
155
+ nonAutoInvalidateKey,
156
+ key,
157
+ serializedResponse
158
+ ]));
159
+ commands.push(this.hexpire(nonAutoInvalidateKey, key, ttlSeconds, hexOptions));
160
+ yield Promise.all(commands);
161
+ return;
162
+ }
163
+ const compositeKey = this.getCompositeKey(tables);
164
+ const commands = [];
165
+ commands.push(this.client.send("HSET", [
166
+ compositeKey,
167
+ key,
168
+ serializedResponse
169
+ ]));
170
+ commands.push(this.hexpire(compositeKey, key, ttlSeconds, hexOptions));
171
+ if (isTag) {
172
+ const tagsMapKey = this.addPrefix(BunCache.tagsMapKey);
173
+ commands.push(this.client.send("HSET", [
174
+ tagsMapKey,
175
+ key,
176
+ compositeKey
177
+ ]));
178
+ commands.push(this.hexpire(tagsMapKey, key, ttlSeconds, hexOptions));
179
+ }
180
+ for (const table of tables) {
181
+ commands.push(this.client.sadd(this.addTablePrefix(table), compositeKey));
182
+ }
183
+ yield Promise.all(commands);
184
+ }).call(this);
185
+ }
186
+ onMutate(params) {
187
+ return _async_to_generator(function* () {
188
+ const tags = Array.isArray(params.tags) ? params.tags : params.tags ? [params.tags] : [];
189
+ const tables = Array.isArray(params.tables) ? params.tables : params.tables ? [params.tables] : [];
190
+ const tableNames = tables.map((table) => (0, drizzle_orm_entity.is)(table, drizzle_orm.Table) ? (0, drizzle_orm.getTableName)(table) : table);
191
+ const compositeTableSets = tableNames.map((table) => this.addTablePrefix(table));
192
+ const tagsMapKey = this.addPrefix(BunCache.tagsMapKey);
193
+ yield this.client.send("EVAL", [
194
+ onMutateScript,
195
+ (1 + compositeTableSets.length).toString(),
196
+ tagsMapKey,
197
+ ...compositeTableSets,
198
+ ...tags
199
+ ]);
200
+ }).call(this);
201
+ }
202
+ /**
203
+ * Add the user-defined prefix to a key.
204
+ */ addPrefix(key) {
205
+ return `${this.prefix}:${key}`;
206
+ }
207
+ /**
208
+ * Add the composite table set prefix with user prefix.
209
+ */ addTablePrefix(table) {
210
+ return this.addPrefix(`${BunCache.compositeTableSetPrefix}${table}`);
211
+ }
212
+ /**
213
+ * Generate a composite key from sorted table names.
214
+ */ getCompositeKey(tables) {
215
+ return this.addPrefix(`${BunCache.compositeTablePrefix}${tables.sort().join(",")}`);
216
+ }
217
+ /**
218
+ * Execute HEXPIRE command using send().
219
+ * HEXPIRE requires Redis 7.4+
220
+ */ hexpire(key, field, seconds, hexOptions) {
221
+ if (hexOptions) {
222
+ return this.client.send("HEXPIRE", [
223
+ key,
224
+ seconds.toString(),
225
+ hexOptions,
226
+ "FIELDS",
227
+ "1",
228
+ field
229
+ ]);
230
+ } else {
231
+ return this.client.send("HEXPIRE", [
232
+ key,
233
+ seconds.toString(),
234
+ "FIELDS",
235
+ "1",
236
+ field
237
+ ]);
238
+ }
239
+ }
240
+ constructor(options) {
241
+ var _options_prefix, _options_global;
242
+ super(), _define_property(this, "client", void 0), _define_property(this, "prefix", void 0), _define_property(this, "useGlobally", void 0), _define_property(this, "internalConfig", void 0);
243
+ this.prefix = (_options_prefix = options.prefix) !== null && _options_prefix !== void 0 ? _options_prefix : "drizzle-redis";
244
+ this.useGlobally = (_options_global = options.global) !== null && _options_global !== void 0 ? _options_global : false;
245
+ this.internalConfig = this.toInternalConfig(options.config);
246
+ if ("client" in options) {
247
+ this.client = options.client;
248
+ } else {
249
+ this.client = new bun.RedisClient(options.url);
250
+ }
251
+ }
252
+ };
253
+ _define_property(BunCache, drizzle_orm_entity.entityKind, "BunCache");
254
+ /**
255
+ * Prefix for sets which denote the composite table names for each unique table.
256
+ *
257
+ * Example: In the composite table set of "table1", you may find
258
+ * `${compositeTableSetPrefix}table1,table2` and `${compositeTableSetPrefix}table1,table3`
259
+ */ _define_property(BunCache, "compositeTableSetPrefix", "__CTS__");
260
+ /**
261
+ * Prefix for hashes which map hash or tags to cache values.
262
+ */ _define_property(BunCache, "compositeTablePrefix", "__CT__");
263
+ /**
264
+ * Key which holds the mapping of tags to composite table names.
265
+ *
266
+ * Using this tagsMapKey, you can find the composite table name for a given tag
267
+ * and get the cache value for that tag.
268
+ */ _define_property(BunCache, "tagsMapKey", "__tagsMap__");
269
+ /**
270
+ * Queries whose auto invalidation is false aren't stored in their respective
271
+ * composite table hashes because those hashes are deleted when a mutation
272
+ * occurs on related tables.
273
+ *
274
+ * Instead, they are stored in a separate hash with this prefix
275
+ * to prevent them from being deleted when a mutation occurs.
276
+ */ _define_property(BunCache, "nonAutoInvalidateTablePrefix", "__nonAutoInvalidate__");
277
+ function bunCache(options) {
278
+ return new BunCache(options);
279
+ }
280
+
281
+ //#endregion
282
+ exports.bunCache = bunCache;
283
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["RedisClient","Table","getTableName","Cache","entityKind","is","getByTagScript","onMutateScript","BunCache","toInternalConfig","config","seconds","ex","hexOptions","strategy","useGlobally","get","key","tables","isTag","isAutoInvalidate","result","client","hget","addPrefix","nonAutoInvalidateTablePrefix","undefined","JSON","parse","send","tagsMapKey","compositeKey","getCompositeKey","put","response","length","ttlSeconds","internalConfig","serializedResponse","stringify","nonAutoInvalidateKey","commands","push","hexpire","Promise","all","table","sadd","addTablePrefix","onMutate","params","tags","Array","isArray","tableNames","map","compositeTableSets","toString","prefix","compositeTableSetPrefix","compositeTablePrefix","sort","join","field","options","global","url","bunCache"],"sources":["../../src/bun/cache.ts"],"sourcesContent":["import { RedisClient } from \"bun\";\nimport { Table, getTableName } from \"drizzle-orm\";\nimport type { MutationOption } from \"drizzle-orm/cache/core\";\nimport { Cache } from \"drizzle-orm/cache/core\";\nimport type { CacheConfig } from \"drizzle-orm/cache/core/types\";\nimport { entityKind, is } from \"drizzle-orm/entity\";\nimport type { BunCacheOptions } from \"../types/main\";\n\n/**\n * Lua script to atomically get a cached value by tag.\n * Looks up the composite table name from the tags map, then retrieves the value.\n */\nconst getByTagScript = `\nlocal tagsMapKey = KEYS[1] -- tags map key\nlocal tag = ARGV[1] -- tag\n\nlocal compositeTableName = redis.call('HGET', tagsMapKey, tag)\nif not compositeTableName then\n return nil\nend\n\nlocal value = redis.call('HGET', compositeTableName, tag)\nreturn value\n`;\n\n/**\n * Lua script to atomically invalidate cache entries on mutation.\n * Handles both tag-based and table-based invalidation.\n */\nconst onMutateScript = `\nlocal tagsMapKey = KEYS[1] -- tags map key\nlocal tables = {} -- initialize tables array\nlocal tags = ARGV -- tags array\n\nfor i = 2, #KEYS do\n tables[#tables + 1] = KEYS[i] -- add all keys except the first one to tables\nend\n\nif #tags > 0 then\n for _, tag in ipairs(tags) do\n if tag ~= nil and tag ~= '' then\n local compositeTableName = redis.call('HGET', tagsMapKey, tag)\n if compositeTableName then\n redis.call('HDEL', compositeTableName, tag)\n end\n end\n end\n redis.call('HDEL', tagsMapKey, unpack(tags))\nend\n\nlocal keysToDelete = {}\n\nif #tables > 0 then\n local compositeTableNames = redis.call('SUNION', unpack(tables))\n for _, compositeTableName in ipairs(compositeTableNames) do\n keysToDelete[#keysToDelete + 1] = compositeTableName\n end\n for _, table in ipairs(tables) do\n keysToDelete[#keysToDelete + 1] = table\n end\n redis.call('DEL', unpack(keysToDelete))\nend\n`;\n\ninterface InternalConfig {\n seconds: number;\n hexOptions?: \"NX\" | \"nx\" | \"XX\" | \"xx\" | \"GT\" | \"gt\" | \"LT\" | \"lt\";\n}\n\nexport class BunCache extends Cache {\n static override readonly [entityKind]: string = \"BunCache\";\n\n private readonly client: RedisClient;\n private readonly prefix: string;\n private readonly useGlobally: boolean;\n private readonly internalConfig: InternalConfig;\n\n /**\n * Prefix for sets which denote the composite table names for each unique table.\n *\n * Example: In the composite table set of \"table1\", you may find\n * `${compositeTableSetPrefix}table1,table2` and `${compositeTableSetPrefix}table1,table3`\n */\n private static readonly compositeTableSetPrefix = \"__CTS__\";\n\n /**\n * Prefix for hashes which map hash or tags to cache values.\n */\n private static readonly compositeTablePrefix = \"__CT__\";\n\n /**\n * Key which holds the mapping of tags to composite table names.\n *\n * Using this tagsMapKey, you can find the composite table name for a given tag\n * and get the cache value for that tag.\n */\n private static readonly tagsMapKey = \"__tagsMap__\";\n\n /**\n * Queries whose auto invalidation is false aren't stored in their respective\n * composite table hashes because those hashes are deleted when a mutation\n * occurs on related tables.\n *\n * Instead, they are stored in a separate hash with this prefix\n * to prevent them from being deleted when a mutation occurs.\n */\n private static readonly nonAutoInvalidateTablePrefix =\n \"__nonAutoInvalidate__\";\n\n constructor(options: BunCacheOptions) {\n super();\n this.prefix = options.prefix ?? \"drizzle-redis\";\n this.useGlobally = options.global ?? false;\n this.internalConfig = this.toInternalConfig(options.config);\n\n if (\"client\" in options) {\n this.client = options.client;\n } else {\n this.client = new RedisClient(options.url);\n }\n }\n\n private toInternalConfig(config?: CacheConfig): InternalConfig {\n return config\n ? {\n seconds: config.ex ?? 1,\n hexOptions: config.hexOptions,\n }\n : {\n seconds: 1,\n };\n }\n\n override strategy(): \"explicit\" | \"all\" {\n return this.useGlobally ? \"all\" : \"explicit\";\n }\n\n override async get(\n key: string,\n tables: string[],\n isTag: boolean,\n isAutoInvalidate?: boolean\n ): Promise<any[] | undefined> {\n // Handle non-auto-invalidate queries\n if (!isAutoInvalidate) {\n const result = await this.client.hget(\n this.addPrefix(BunCache.nonAutoInvalidateTablePrefix),\n key\n );\n return result === null ? undefined : JSON.parse(result);\n }\n\n // Handle tag-based lookup using Lua script\n if (isTag) {\n const result = await this.client.send(\"EVAL\", [\n getByTagScript,\n \"1\",\n this.addPrefix(BunCache.tagsMapKey),\n key,\n ]);\n if (result === null) {\n return undefined;\n }\n return JSON.parse(result as string);\n }\n\n // Handle normal table-based lookup\n const compositeKey = this.getCompositeKey(tables);\n const result = await this.client.hget(compositeKey, key);\n return result === null ? undefined : JSON.parse(result);\n }\n\n override async put(\n key: string,\n response: any,\n tables: string[],\n isTag: boolean = false,\n config?: CacheConfig\n ): Promise<void> {\n const isAutoInvalidate = tables.length !== 0;\n const ttlSeconds =\n config && config.ex ? config.ex : this.internalConfig.seconds;\n const hexOptions =\n config && config.hexOptions\n ? config.hexOptions\n : this.internalConfig?.hexOptions;\n\n const serializedResponse = JSON.stringify(response);\n\n // Handle non-auto-invalidate queries\n if (!isAutoInvalidate) {\n const nonAutoInvalidateKey = this.addPrefix(\n BunCache.nonAutoInvalidateTablePrefix\n );\n\n const commands: Promise<any>[] = [];\n\n if (isTag) {\n const tagsMapKey = this.addPrefix(BunCache.tagsMapKey);\n commands.push(\n this.client.send(\"HSET\", [tagsMapKey, key, nonAutoInvalidateKey])\n );\n commands.push(this.hexpire(tagsMapKey, key, ttlSeconds, hexOptions));\n }\n\n commands.push(\n this.client.send(\"HSET\", [\n nonAutoInvalidateKey,\n key,\n serializedResponse,\n ])\n );\n commands.push(\n this.hexpire(nonAutoInvalidateKey, key, ttlSeconds, hexOptions)\n );\n\n await Promise.all(commands);\n return;\n }\n\n // Handle auto-invalidate queries\n const compositeKey = this.getCompositeKey(tables);\n const commands: Promise<any>[] = [];\n\n commands.push(\n this.client.send(\"HSET\", [compositeKey, key, serializedResponse])\n );\n commands.push(this.hexpire(compositeKey, key, ttlSeconds, hexOptions));\n\n if (isTag) {\n const tagsMapKey = this.addPrefix(BunCache.tagsMapKey);\n commands.push(this.client.send(\"HSET\", [tagsMapKey, key, compositeKey]));\n commands.push(this.hexpire(tagsMapKey, key, ttlSeconds, hexOptions));\n }\n\n // Track composite keys for each table (for invalidation)\n for (const table of tables) {\n commands.push(this.client.sadd(this.addTablePrefix(table), compositeKey));\n }\n\n await Promise.all(commands);\n }\n\n override async onMutate(params: MutationOption): Promise<void> {\n const tags = Array.isArray(params.tags)\n ? params.tags\n : params.tags\n ? [params.tags]\n : [];\n\n const tables = Array.isArray(params.tables)\n ? params.tables\n : params.tables\n ? [params.tables]\n : [];\n\n // Extract table names, handling Table objects via is() + getTableName\n const tableNames = tables.map((table) =>\n is(table, Table) ? getTableName(table) : (table as string)\n );\n\n const compositeTableSets = tableNames.map((table) =>\n this.addTablePrefix(table)\n );\n\n const tagsMapKey = this.addPrefix(BunCache.tagsMapKey);\n\n // Execute the Lua script for atomic invalidation\n await this.client.send(\"EVAL\", [\n onMutateScript,\n (1 + compositeTableSets.length).toString(),\n tagsMapKey,\n ...compositeTableSets,\n ...tags,\n ]);\n }\n\n /**\n * Add the user-defined prefix to a key.\n */\n private addPrefix(key: string): string {\n return `${this.prefix}:${key}`;\n }\n\n /**\n * Add the composite table set prefix with user prefix.\n */\n private addTablePrefix(table: string): string {\n return this.addPrefix(`${BunCache.compositeTableSetPrefix}${table}`);\n }\n\n /**\n * Generate a composite key from sorted table names.\n */\n private getCompositeKey(tables: string[]): string {\n return this.addPrefix(\n `${BunCache.compositeTablePrefix}${tables.sort().join(\",\")}`\n );\n }\n\n /**\n * Execute HEXPIRE command using send().\n * HEXPIRE requires Redis 7.4+\n */\n private hexpire(\n key: string,\n field: string,\n seconds: number,\n hexOptions?: \"NX\" | \"nx\" | \"XX\" | \"xx\" | \"GT\" | \"gt\" | \"LT\" | \"lt\"\n ): Promise<any> {\n if (hexOptions) {\n return this.client.send(\"HEXPIRE\", [\n key,\n seconds.toString(),\n hexOptions,\n \"FIELDS\",\n \"1\",\n field,\n ]);\n } else {\n return this.client.send(\"HEXPIRE\", [\n key,\n seconds.toString(),\n \"FIELDS\",\n \"1\",\n field,\n ]);\n }\n }\n}\n\nexport function bunCache(options: BunCacheOptions): BunCache {\n return new BunCache(options);\n}\n"],"mappings":"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"}
@@ -0,0 +1,130 @@
1
+ import { Cache, MutationOption } from "drizzle-orm/cache/core";
2
+ import { CacheConfig } from "drizzle-orm/cache/core/types";
3
+ import { entityKind } from "drizzle-orm/entity";
4
+ import { RedisClient } from "bun";
5
+ import { Redis } from "ioredis";
6
+
7
+ //#region src/types/main.d.ts
8
+ interface RedisCacheWithClient {
9
+ /**
10
+ * The Redis client to use for the cache.
11
+ */
12
+ client: Redis;
13
+ }
14
+ interface RedisCacheWithConnection {
15
+ /**
16
+ * The URL to use to connect to the Redis server.
17
+ */
18
+ url: string;
19
+ }
20
+ type RedisCacheOptions = (RedisCacheWithClient | RedisCacheWithConnection) & {
21
+ /**
22
+ * The prefix to use for the cache keys. Defaults to "drizzle-redis".
23
+ * @default "drizzle-redis"
24
+ */
25
+ prefix?: string;
26
+ /**
27
+ * Default cache configuration (TTL settings).
28
+ */
29
+ config?: CacheConfig;
30
+ /**
31
+ * Whether to enable global caching for all queries.
32
+ * When true, all queries will be cached automatically.
33
+ * When false (default), only queries with explicit .cache() will be cached.
34
+ * @default false
35
+ */
36
+ global?: boolean;
37
+ };
38
+ interface BunCacheWithClient {
39
+ /**
40
+ * The Bun RedisClient instance to use for the cache.
41
+ */
42
+ client: RedisClient;
43
+ }
44
+ interface BunCacheWithConnection {
45
+ /**
46
+ * The URL to use to connect to the Redis server.
47
+ */
48
+ url: string;
49
+ }
50
+ type BunCacheOptions = (BunCacheWithClient | BunCacheWithConnection) & {
51
+ /**
52
+ * The prefix to use for the cache keys. Defaults to "drizzle-redis".
53
+ * @default "drizzle-redis"
54
+ */
55
+ prefix?: string;
56
+ /**
57
+ * Default cache configuration (TTL settings).
58
+ */
59
+ config?: CacheConfig;
60
+ /**
61
+ * Whether to enable global caching for all queries.
62
+ * When true, all queries will be cached automatically.
63
+ * When false (default), only queries with explicit .cache() will be cached.
64
+ * @default false
65
+ */
66
+ global?: boolean;
67
+ };
68
+ //#endregion
69
+ //#region src/bun/cache.d.ts
70
+ declare class BunCache extends Cache {
71
+ static readonly [entityKind]: string;
72
+ private readonly client;
73
+ private readonly prefix;
74
+ private readonly useGlobally;
75
+ private readonly internalConfig;
76
+ /**
77
+ * Prefix for sets which denote the composite table names for each unique table.
78
+ *
79
+ * Example: In the composite table set of "table1", you may find
80
+ * `${compositeTableSetPrefix}table1,table2` and `${compositeTableSetPrefix}table1,table3`
81
+ */
82
+ private static readonly compositeTableSetPrefix;
83
+ /**
84
+ * Prefix for hashes which map hash or tags to cache values.
85
+ */
86
+ private static readonly compositeTablePrefix;
87
+ /**
88
+ * Key which holds the mapping of tags to composite table names.
89
+ *
90
+ * Using this tagsMapKey, you can find the composite table name for a given tag
91
+ * and get the cache value for that tag.
92
+ */
93
+ private static readonly tagsMapKey;
94
+ /**
95
+ * Queries whose auto invalidation is false aren't stored in their respective
96
+ * composite table hashes because those hashes are deleted when a mutation
97
+ * occurs on related tables.
98
+ *
99
+ * Instead, they are stored in a separate hash with this prefix
100
+ * to prevent them from being deleted when a mutation occurs.
101
+ */
102
+ private static readonly nonAutoInvalidateTablePrefix;
103
+ constructor(options: BunCacheOptions);
104
+ private toInternalConfig;
105
+ strategy(): "explicit" | "all";
106
+ get(key: string, tables: string[], isTag: boolean, isAutoInvalidate?: boolean): Promise<any[] | undefined>;
107
+ put(key: string, response: any, tables: string[], isTag?: boolean, config?: CacheConfig): Promise<void>;
108
+ onMutate(params: MutationOption): Promise<void>;
109
+ /**
110
+ * Add the user-defined prefix to a key.
111
+ */
112
+ private addPrefix;
113
+ /**
114
+ * Add the composite table set prefix with user prefix.
115
+ */
116
+ private addTablePrefix;
117
+ /**
118
+ * Generate a composite key from sorted table names.
119
+ */
120
+ private getCompositeKey;
121
+ /**
122
+ * Execute HEXPIRE command using send().
123
+ * HEXPIRE requires Redis 7.4+
124
+ */
125
+ private hexpire;
126
+ }
127
+ declare function bunCache(options: BunCacheOptions): BunCache;
128
+ //#endregion
129
+ export { type BunCacheOptions, bunCache };
130
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1,130 @@
1
+ import { RedisClient } from "bun";
2
+ import { Cache, MutationOption } from "drizzle-orm/cache/core";
3
+ import { entityKind } from "drizzle-orm/entity";
4
+ import { CacheConfig } from "drizzle-orm/cache/core/types";
5
+ import { Redis } from "ioredis";
6
+
7
+ //#region src/types/main.d.ts
8
+ interface RedisCacheWithClient {
9
+ /**
10
+ * The Redis client to use for the cache.
11
+ */
12
+ client: Redis;
13
+ }
14
+ interface RedisCacheWithConnection {
15
+ /**
16
+ * The URL to use to connect to the Redis server.
17
+ */
18
+ url: string;
19
+ }
20
+ type RedisCacheOptions = (RedisCacheWithClient | RedisCacheWithConnection) & {
21
+ /**
22
+ * The prefix to use for the cache keys. Defaults to "drizzle-redis".
23
+ * @default "drizzle-redis"
24
+ */
25
+ prefix?: string;
26
+ /**
27
+ * Default cache configuration (TTL settings).
28
+ */
29
+ config?: CacheConfig;
30
+ /**
31
+ * Whether to enable global caching for all queries.
32
+ * When true, all queries will be cached automatically.
33
+ * When false (default), only queries with explicit .cache() will be cached.
34
+ * @default false
35
+ */
36
+ global?: boolean;
37
+ };
38
+ interface BunCacheWithClient {
39
+ /**
40
+ * The Bun RedisClient instance to use for the cache.
41
+ */
42
+ client: RedisClient;
43
+ }
44
+ interface BunCacheWithConnection {
45
+ /**
46
+ * The URL to use to connect to the Redis server.
47
+ */
48
+ url: string;
49
+ }
50
+ type BunCacheOptions = (BunCacheWithClient | BunCacheWithConnection) & {
51
+ /**
52
+ * The prefix to use for the cache keys. Defaults to "drizzle-redis".
53
+ * @default "drizzle-redis"
54
+ */
55
+ prefix?: string;
56
+ /**
57
+ * Default cache configuration (TTL settings).
58
+ */
59
+ config?: CacheConfig;
60
+ /**
61
+ * Whether to enable global caching for all queries.
62
+ * When true, all queries will be cached automatically.
63
+ * When false (default), only queries with explicit .cache() will be cached.
64
+ * @default false
65
+ */
66
+ global?: boolean;
67
+ };
68
+ //#endregion
69
+ //#region src/bun/cache.d.ts
70
+ declare class BunCache extends Cache {
71
+ static readonly [entityKind]: string;
72
+ private readonly client;
73
+ private readonly prefix;
74
+ private readonly useGlobally;
75
+ private readonly internalConfig;
76
+ /**
77
+ * Prefix for sets which denote the composite table names for each unique table.
78
+ *
79
+ * Example: In the composite table set of "table1", you may find
80
+ * `${compositeTableSetPrefix}table1,table2` and `${compositeTableSetPrefix}table1,table3`
81
+ */
82
+ private static readonly compositeTableSetPrefix;
83
+ /**
84
+ * Prefix for hashes which map hash or tags to cache values.
85
+ */
86
+ private static readonly compositeTablePrefix;
87
+ /**
88
+ * Key which holds the mapping of tags to composite table names.
89
+ *
90
+ * Using this tagsMapKey, you can find the composite table name for a given tag
91
+ * and get the cache value for that tag.
92
+ */
93
+ private static readonly tagsMapKey;
94
+ /**
95
+ * Queries whose auto invalidation is false aren't stored in their respective
96
+ * composite table hashes because those hashes are deleted when a mutation
97
+ * occurs on related tables.
98
+ *
99
+ * Instead, they are stored in a separate hash with this prefix
100
+ * to prevent them from being deleted when a mutation occurs.
101
+ */
102
+ private static readonly nonAutoInvalidateTablePrefix;
103
+ constructor(options: BunCacheOptions);
104
+ private toInternalConfig;
105
+ strategy(): "explicit" | "all";
106
+ get(key: string, tables: string[], isTag: boolean, isAutoInvalidate?: boolean): Promise<any[] | undefined>;
107
+ put(key: string, response: any, tables: string[], isTag?: boolean, config?: CacheConfig): Promise<void>;
108
+ onMutate(params: MutationOption): Promise<void>;
109
+ /**
110
+ * Add the user-defined prefix to a key.
111
+ */
112
+ private addPrefix;
113
+ /**
114
+ * Add the composite table set prefix with user prefix.
115
+ */
116
+ private addTablePrefix;
117
+ /**
118
+ * Generate a composite key from sorted table names.
119
+ */
120
+ private getCompositeKey;
121
+ /**
122
+ * Execute HEXPIRE command using send().
123
+ * HEXPIRE requires Redis 7.4+
124
+ */
125
+ private hexpire;
126
+ }
127
+ declare function bunCache(options: BunCacheOptions): BunCache;
128
+ //#endregion
129
+ export { type BunCacheOptions, bunCache };
130
+ //# sourceMappingURL=index.d.mts.map