drizzle-orm 0.40.0-bbf78ae → 0.40.0-ca1033e

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.
@@ -47,39 +47,55 @@ class UpstashCache extends import_core.Cache {
47
47
  keepTtl: config.keepTtl
48
48
  } : void 0;
49
49
  }
50
- async get(key, _tables, _isTag) {
51
- const res = (await this.redis.get(key)) ?? void 0;
52
- return res;
50
+ async get(key, tables, isTag = false) {
51
+ const compositeKey = tables.sort().join(",");
52
+ if (isTag) {
53
+ const tagCompositeKey = await this.redis.hget("tagsMap", key);
54
+ if (tagCompositeKey) {
55
+ return await this.redis.hget(tagCompositeKey, key);
56
+ }
57
+ return void 0;
58
+ }
59
+ return (await this.redis.hget(compositeKey, key)) ?? void 0;
53
60
  }
54
- async put(key, response, tables, isTag, config) {
55
- await this.redis.set(key, response, config ? this.toInternalConfig(config) : this.internalConfig);
56
- for (const table of tables) {
57
- await this.redis.sadd(table, key);
61
+ async put(key, response, tables, isTag = false, _config) {
62
+ if (isTag) {
63
+ const compositeKey = tables.sort().join(",");
64
+ await this.redis.hset(compositeKey, { [key]: response });
65
+ await this.redis.hset("tagsMap", { [key]: compositeKey });
66
+ for (const table of tables) {
67
+ await this.redis.sadd(`prefix_${table}`, compositeKey);
68
+ }
69
+ } else {
70
+ const compositeKey = tables.sort().join(",");
71
+ await this.redis.hset(compositeKey, { [key]: response });
58
72
  }
59
73
  }
60
74
  async onMutate(params) {
61
- const tagsArray = params.tags ? Array.isArray(params.tags) ? params.tags : [params.tags] : [];
62
- const tablesArray = params.tables ? Array.isArray(params.tables) ? params.tables : [params.tables] : [];
75
+ const tags = Array.isArray(params.tags) ? params.tags : params.tags ? [params.tags] : [];
76
+ const tables = Array.isArray(params.tables) ? params.tables : params.tables ? [params.tables] : [];
77
+ const mappedTables = tables.map((table) => (0, import_entity.is)(table, import__.Table) ? table[import__.OriginalName] : table);
78
+ const prefixedMappedTables = tables.map((table) => `prefix_${table}`);
63
79
  const keysToDelete = /* @__PURE__ */ new Set();
64
- for (const table of tablesArray) {
65
- const tableName = (0, import_entity.is)(table, import__.Table) ? table[import__.OriginalName] : table;
66
- const keys = await this.redis.smembers(tableName);
67
- for (const key of keys)
68
- keysToDelete.add(key);
69
- }
70
- if (keysToDelete.size > 0 || tagsArray.length > 0) {
71
- const pipeline = this.redis.pipeline();
72
- for (const tag of tagsArray) {
73
- pipeline.del(tag);
80
+ if (tables.length > 0) {
81
+ const compositeKeys = await this.redis.sunion(...prefixedMappedTables);
82
+ for (const composite of compositeKeys) {
83
+ const keys = await this.redis.hkeys(composite);
84
+ for (const key of keys)
85
+ keysToDelete.add(key);
86
+ await this.redis.del(composite);
74
87
  }
75
- for (const key of keysToDelete) {
76
- pipeline.del(key);
77
- for (const table of tablesArray) {
78
- const tableName = (0, import_entity.is)(table, import__.Table) ? table[import__.OriginalName] : table;
79
- pipeline.srem(tableName, key);
80
- }
88
+ await this.redis.del(...prefixedMappedTables, ...mappedTables);
89
+ }
90
+ for (const tag of tags) {
91
+ const compositeKey = await this.redis.hget("tagsMap", tag);
92
+ if (compositeKey) {
93
+ await this.redis.hdel(compositeKey, tag);
94
+ await this.redis.hdel("tagsMap", tag);
81
95
  }
82
- await pipeline.exec();
96
+ }
97
+ if (keysToDelete.size > 0) {
98
+ await this.redis.del(...keysToDelete);
83
99
  }
84
100
  }
85
101
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cache/upstash/cache.ts"],"sourcesContent":["import type { SetCommandOptions } from '@upstash/redis';\nimport { Redis } from '@upstash/redis';\nimport type { MutationOption } from '~/cache/core/index.ts';\nimport { Cache } from '~/cache/core/index.ts';\nimport { entityKind, is } from '~/entity.ts';\nimport { OriginalName, Table } from '~/index.ts';\nimport type { CacheConfig } from '../core/types.ts';\n\nexport class UpstashCache extends Cache {\n\tstatic override readonly [entityKind]: string = 'UpstashCache';\n\n\tprivate internalConfig?: SetCommandOptions;\n\n\tconstructor(public redis: Redis, config?: CacheConfig, protected useGlobally?: boolean) {\n\t\tsuper();\n\t\tthis.internalConfig = this.toInternalConfig(config);\n\t}\n\n\tpublic strategy() {\n\t\treturn this.useGlobally ? 'all' : 'explicit';\n\t}\n\n\tprivate toInternalConfig(config?: CacheConfig) {\n\t\treturn config\n\t\t\t? {\n\t\t\t\tex: config.ex,\n\t\t\t\texat: config.exat,\n\t\t\t\tpx: config.px,\n\t\t\t\tpxat: config.pxat,\n\t\t\t\tkeepTtl: config.keepTtl,\n\t\t\t} as SetCommandOptions\n\t\t\t: undefined;\n\t}\n\n\toverride async get(key: string, _tables: string[], _isTag: boolean) {\n\t\tconst res = await this.redis.get<any[]>(key) ?? undefined;\n\t\treturn res;\n\t}\n\n\toverride async put(key: string, response: any, tables: string[], isTag: boolean, config?: CacheConfig) {\n\t\tawait this.redis.set(key, response, config ? this.toInternalConfig(config) : this.internalConfig);\n\t\tfor (const table of tables) {\n\t\t\tawait this.redis.sadd(table, key);\n\t\t}\n\t}\n\n\toverride async onMutate(params: MutationOption) {\n\t\tconst tagsArray = params.tags ? Array.isArray(params.tags) ? params.tags : [params.tags] : [];\n\t\tconst tablesArray = params.tables ? Array.isArray(params.tables) ? params.tables : [params.tables] : [];\n\n\t\tconst keysToDelete = new Set<string>();\n\n\t\tfor (const table of tablesArray) {\n\t\t\tconst tableName = is(table, Table) ? table[OriginalName] : table as string;\n\t\t\tconst keys = await this.redis.smembers(tableName);\n\t\t\tfor (const key of keys) keysToDelete.add(key); // Add to the set\n\t\t}\n\n\t\tif (keysToDelete.size > 0 || tagsArray.length > 0) {\n\t\t\tconst pipeline = this.redis.pipeline();\n\n\t\t\tfor (const tag of tagsArray) {\n\t\t\t\tpipeline.del(tag);\n\t\t\t}\n\n\t\t\tfor (const key of keysToDelete) {\n\t\t\t\tpipeline.del(key);\n\t\t\t\tfor (const table of tablesArray) {\n\t\t\t\t\tconst tableName = is(table, Table) ? table[OriginalName] : table as string;\n\t\t\t\t\tpipeline.srem(tableName, key);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait pipeline.exec();\n\t\t}\n\t}\n}\n\nexport function upstashCache(\n\t{ url, token, config, global = false }: { url: string; token: string; config?: CacheConfig; global?: boolean },\n): UpstashCache {\n\tconst redis = new Redis({\n\t\turl,\n\t\ttoken,\n\t});\n\n\treturn new UpstashCache(redis, config, global);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAAsB;AAEtB,kBAAsB;AACtB,oBAA+B;AAC/B,eAAoC;AAG7B,MAAM,qBAAqB,kBAAM;AAAA,EAKvC,YAAmB,OAAc,QAAgC,aAAuB;AACvF,UAAM;AADY;AAA8C;AAEhE,SAAK,iBAAiB,KAAK,iBAAiB,MAAM;AAAA,EACnD;AAAA,EAPA,QAA0B,wBAAU,IAAY;AAAA,EAExC;AAAA,EAOD,WAAW;AACjB,WAAO,KAAK,cAAc,QAAQ;AAAA,EACnC;AAAA,EAEQ,iBAAiB,QAAsB;AAC9C,WAAO,SACJ;AAAA,MACD,IAAI,OAAO;AAAA,MACX,MAAM,OAAO;AAAA,MACb,IAAI,OAAO;AAAA,MACX,MAAM,OAAO;AAAA,MACb,SAAS,OAAO;AAAA,IACjB,IACE;AAAA,EACJ;AAAA,EAEA,MAAe,IAAI,KAAa,SAAmB,QAAiB;AACnE,UAAM,MAAM,MAAM,KAAK,MAAM,IAAW,GAAG,KAAK;AAChD,WAAO;AAAA,EACR;AAAA,EAEA,MAAe,IAAI,KAAa,UAAe,QAAkB,OAAgB,QAAsB;AACtG,UAAM,KAAK,MAAM,IAAI,KAAK,UAAU,SAAS,KAAK,iBAAiB,MAAM,IAAI,KAAK,cAAc;AAChG,eAAW,SAAS,QAAQ;AAC3B,YAAM,KAAK,MAAM,KAAK,OAAO,GAAG;AAAA,IACjC;AAAA,EACD;AAAA,EAEA,MAAe,SAAS,QAAwB;AAC/C,UAAM,YAAY,OAAO,OAAO,MAAM,QAAQ,OAAO,IAAI,IAAI,OAAO,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC;AAC5F,UAAM,cAAc,OAAO,SAAS,MAAM,QAAQ,OAAO,MAAM,IAAI,OAAO,SAAS,CAAC,OAAO,MAAM,IAAI,CAAC;AAEtG,UAAM,eAAe,oBAAI,IAAY;AAErC,eAAW,SAAS,aAAa;AAChC,YAAM,gBAAY,kBAAG,OAAO,cAAK,IAAI,MAAM,qBAAY,IAAI;AAC3D,YAAM,OAAO,MAAM,KAAK,MAAM,SAAS,SAAS;AAChD,iBAAW,OAAO;AAAM,qBAAa,IAAI,GAAG;AAAA,IAC7C;AAEA,QAAI,aAAa,OAAO,KAAK,UAAU,SAAS,GAAG;AAClD,YAAM,WAAW,KAAK,MAAM,SAAS;AAErC,iBAAW,OAAO,WAAW;AAC5B,iBAAS,IAAI,GAAG;AAAA,MACjB;AAEA,iBAAW,OAAO,cAAc;AAC/B,iBAAS,IAAI,GAAG;AAChB,mBAAW,SAAS,aAAa;AAChC,gBAAM,gBAAY,kBAAG,OAAO,cAAK,IAAI,MAAM,qBAAY,IAAI;AAC3D,mBAAS,KAAK,WAAW,GAAG;AAAA,QAC7B;AAAA,MACD;AAEA,YAAM,SAAS,KAAK;AAAA,IACrB;AAAA,EACD;AACD;AAEO,SAAS,aACf,EAAE,KAAK,OAAO,QAAQ,SAAS,MAAM,GACtB;AACf,QAAM,QAAQ,IAAI,mBAAM;AAAA,IACvB;AAAA,IACA;AAAA,EACD,CAAC;AAED,SAAO,IAAI,aAAa,OAAO,QAAQ,MAAM;AAC9C;","names":[]}
1
+ {"version":3,"sources":["../../../src/cache/upstash/cache.ts"],"sourcesContent":["import type { SetCommandOptions } from '@upstash/redis';\nimport { Redis } from '@upstash/redis';\nimport type { MutationOption } from '~/cache/core/index.ts';\nimport { Cache } from '~/cache/core/index.ts';\nimport { entityKind, is } from '~/entity.ts';\nimport { OriginalName, Table } from '~/index.ts';\nimport type { CacheConfig } from '../core/types.ts';\n\nexport class UpstashCache extends Cache {\n\tstatic override readonly [entityKind]: string = 'UpstashCache';\n\n\tprivate internalConfig?: SetCommandOptions;\n\n\tconstructor(public redis: Redis, config?: CacheConfig, protected useGlobally?: boolean) {\n\t\tsuper();\n\t\tthis.internalConfig = this.toInternalConfig(config);\n\t}\n\n\tpublic strategy() {\n\t\treturn this.useGlobally ? 'all' : 'explicit';\n\t}\n\n\tprivate toInternalConfig(config?: CacheConfig) {\n\t\treturn config\n\t\t\t? {\n\t\t\t\tex: config.ex,\n\t\t\t\texat: config.exat,\n\t\t\t\tpx: config.px,\n\t\t\t\tpxat: config.pxat,\n\t\t\t\tkeepTtl: config.keepTtl,\n\t\t\t} as SetCommandOptions\n\t\t\t: undefined;\n\t}\n\n\toverride async get(key: string, tables: string[], isTag: boolean = false): Promise<any[] | undefined> {\n\t\tconst compositeKey = tables.sort().join(','); // Generate the composite key for the query\n\n\t\tif (isTag) {\n\t\t\t// Handle cache lookup for tags\n\t\t\tconst tagCompositeKey = await this.redis.hget<string>('tagsMap', key); // Retrieve composite key associated with the tag\n\t\t\tif (tagCompositeKey) {\n\t\t\t\treturn await this.redis.hget(tagCompositeKey, key) as any[]; // Retrieve the cached result for the tag\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Normal cache lookup for the composite key\n\t\treturn await this.redis.hget(compositeKey, key) ?? undefined; // Retrieve result for normal query\n\t}\n\n\toverride async put(\n\t\tkey: string,\n\t\tresponse: any,\n\t\ttables: string[],\n\t\tisTag: boolean = false,\n\t\t_config?: CacheConfig,\n\t): Promise<void> {\n\t\tif (isTag) {\n\t\t\t// When it's a tag, store the response in the composite key\n\t\t\tconst compositeKey = tables.sort().join(',');\n\t\t\tawait this.redis.hset(compositeKey, { [key]: response }); // Store the result with the tag under the composite key\n\t\t\tawait this.redis.hset('tagsMap', { [key]: compositeKey }); // Store the tag and its composite key in the map\n\t\t\tfor (const table of tables) {\n\t\t\t\tawait this.redis.sadd(`prefix_${table}`, compositeKey);\n\t\t\t}\n\t\t} else {\n\t\t\t// Normal cache store\n\t\t\tconst compositeKey = tables.sort().join(',');\n\t\t\tawait this.redis.hset(compositeKey, { [key]: response }); // Store the result with the composite key\n\t\t}\n\t}\n\n\toverride async onMutate(params: MutationOption) {\n\t\tconst tags = Array.isArray(params.tags) ? params.tags : params.tags ? [params.tags] : [];\n\t\tconst tables = Array.isArray(params.tables) ? params.tables : params.tables ? [params.tables] : [];\n\t\tconst mappedTables = tables.map((table) => is(table, Table) ? table[OriginalName] : table as string);\n\t\tconst prefixedMappedTables = tables.map((table) => `prefix_${table}`);\n\n\t\tconst keysToDelete = new Set<string>();\n\n\t\t// Invalidate by table\n\t\tif (tables.length > 0) {\n\t\t\t// @ts-expect-error\n\t\t\tconst compositeKeys: string[] = await this.redis.sunion(...prefixedMappedTables);\n\t\t\tfor (const composite of compositeKeys) {\n\t\t\t\tconst keys = await this.redis.hkeys(composite);\n\t\t\t\tfor (const key of keys) keysToDelete.add(key);\n\t\t\t\tawait this.redis.del(composite); // Remove composite entry\n\t\t\t}\n\t\t\tawait this.redis.del(...prefixedMappedTables, ...mappedTables); // Remove table mappings\n\t\t}\n\n\t\t// Invalidate by tag (WITHOUT invalidating the entire table)\n\t\tfor (const tag of tags) {\n\t\t\tconst compositeKey = await this.redis.hget<string>('tagsMap', tag);\n\t\t\tif (compositeKey) {\n\t\t\t\tawait this.redis.hdel(compositeKey, tag); // Only remove the tag-related entry\n\t\t\t\tawait this.redis.hdel('tagsMap', tag); // Remove tag reference\n\t\t\t}\n\t\t}\n\n\t\t// Delete affected cache entries\n\t\tif (keysToDelete.size > 0) {\n\t\t\tawait this.redis.del(...keysToDelete);\n\t\t}\n\t}\n}\n\nexport function upstashCache(\n\t{ url, token, config, global = false }: { url: string; token: string; config?: CacheConfig; global?: boolean },\n): UpstashCache {\n\tconst redis = new Redis({\n\t\turl,\n\t\ttoken,\n\t});\n\n\treturn new UpstashCache(redis, config, global);\n}\n"],"mappings":"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","names":[]}
@@ -11,8 +11,8 @@ export declare class UpstashCache extends Cache {
11
11
  constructor(redis: Redis, config?: CacheConfig, useGlobally?: boolean | undefined);
12
12
  strategy(): "all" | "explicit";
13
13
  private toInternalConfig;
14
- get(key: string, _tables: string[], _isTag: boolean): Promise<any[] | undefined>;
15
- put(key: string, response: any, tables: string[], isTag: boolean, config?: CacheConfig): Promise<void>;
14
+ get(key: string, tables: string[], isTag?: boolean): Promise<any[] | undefined>;
15
+ put(key: string, response: any, tables: string[], isTag?: boolean, _config?: CacheConfig): Promise<void>;
16
16
  onMutate(params: MutationOption): Promise<void>;
17
17
  }
18
18
  export declare function upstashCache({ url, token, config, global }: {
@@ -11,8 +11,8 @@ export declare class UpstashCache extends Cache {
11
11
  constructor(redis: Redis, config?: CacheConfig, useGlobally?: boolean | undefined);
12
12
  strategy(): "all" | "explicit";
13
13
  private toInternalConfig;
14
- get(key: string, _tables: string[], _isTag: boolean): Promise<any[] | undefined>;
15
- put(key: string, response: any, tables: string[], isTag: boolean, config?: CacheConfig): Promise<void>;
14
+ get(key: string, tables: string[], isTag?: boolean): Promise<any[] | undefined>;
15
+ put(key: string, response: any, tables: string[], isTag?: boolean, _config?: CacheConfig): Promise<void>;
16
16
  onMutate(params: MutationOption): Promise<void>;
17
17
  }
18
18
  export declare function upstashCache({ url, token, config, global }: {
@@ -23,39 +23,55 @@ class UpstashCache extends Cache {
23
23
  keepTtl: config.keepTtl
24
24
  } : void 0;
25
25
  }
26
- async get(key, _tables, _isTag) {
27
- const res = (await this.redis.get(key)) ?? void 0;
28
- return res;
26
+ async get(key, tables, isTag = false) {
27
+ const compositeKey = tables.sort().join(",");
28
+ if (isTag) {
29
+ const tagCompositeKey = await this.redis.hget("tagsMap", key);
30
+ if (tagCompositeKey) {
31
+ return await this.redis.hget(tagCompositeKey, key);
32
+ }
33
+ return void 0;
34
+ }
35
+ return (await this.redis.hget(compositeKey, key)) ?? void 0;
29
36
  }
30
- async put(key, response, tables, isTag, config) {
31
- await this.redis.set(key, response, config ? this.toInternalConfig(config) : this.internalConfig);
32
- for (const table of tables) {
33
- await this.redis.sadd(table, key);
37
+ async put(key, response, tables, isTag = false, _config) {
38
+ if (isTag) {
39
+ const compositeKey = tables.sort().join(",");
40
+ await this.redis.hset(compositeKey, { [key]: response });
41
+ await this.redis.hset("tagsMap", { [key]: compositeKey });
42
+ for (const table of tables) {
43
+ await this.redis.sadd(`prefix_${table}`, compositeKey);
44
+ }
45
+ } else {
46
+ const compositeKey = tables.sort().join(",");
47
+ await this.redis.hset(compositeKey, { [key]: response });
34
48
  }
35
49
  }
36
50
  async onMutate(params) {
37
- const tagsArray = params.tags ? Array.isArray(params.tags) ? params.tags : [params.tags] : [];
38
- const tablesArray = params.tables ? Array.isArray(params.tables) ? params.tables : [params.tables] : [];
51
+ const tags = Array.isArray(params.tags) ? params.tags : params.tags ? [params.tags] : [];
52
+ const tables = Array.isArray(params.tables) ? params.tables : params.tables ? [params.tables] : [];
53
+ const mappedTables = tables.map((table) => is(table, Table) ? table[OriginalName] : table);
54
+ const prefixedMappedTables = tables.map((table) => `prefix_${table}`);
39
55
  const keysToDelete = /* @__PURE__ */ new Set();
40
- for (const table of tablesArray) {
41
- const tableName = is(table, Table) ? table[OriginalName] : table;
42
- const keys = await this.redis.smembers(tableName);
43
- for (const key of keys)
44
- keysToDelete.add(key);
45
- }
46
- if (keysToDelete.size > 0 || tagsArray.length > 0) {
47
- const pipeline = this.redis.pipeline();
48
- for (const tag of tagsArray) {
49
- pipeline.del(tag);
56
+ if (tables.length > 0) {
57
+ const compositeKeys = await this.redis.sunion(...prefixedMappedTables);
58
+ for (const composite of compositeKeys) {
59
+ const keys = await this.redis.hkeys(composite);
60
+ for (const key of keys)
61
+ keysToDelete.add(key);
62
+ await this.redis.del(composite);
50
63
  }
51
- for (const key of keysToDelete) {
52
- pipeline.del(key);
53
- for (const table of tablesArray) {
54
- const tableName = is(table, Table) ? table[OriginalName] : table;
55
- pipeline.srem(tableName, key);
56
- }
64
+ await this.redis.del(...prefixedMappedTables, ...mappedTables);
65
+ }
66
+ for (const tag of tags) {
67
+ const compositeKey = await this.redis.hget("tagsMap", tag);
68
+ if (compositeKey) {
69
+ await this.redis.hdel(compositeKey, tag);
70
+ await this.redis.hdel("tagsMap", tag);
57
71
  }
58
- await pipeline.exec();
72
+ }
73
+ if (keysToDelete.size > 0) {
74
+ await this.redis.del(...keysToDelete);
59
75
  }
60
76
  }
61
77
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cache/upstash/cache.ts"],"sourcesContent":["import type { SetCommandOptions } from '@upstash/redis';\nimport { Redis } from '@upstash/redis';\nimport type { MutationOption } from '~/cache/core/index.ts';\nimport { Cache } from '~/cache/core/index.ts';\nimport { entityKind, is } from '~/entity.ts';\nimport { OriginalName, Table } from '~/index.ts';\nimport type { CacheConfig } from '../core/types.ts';\n\nexport class UpstashCache extends Cache {\n\tstatic override readonly [entityKind]: string = 'UpstashCache';\n\n\tprivate internalConfig?: SetCommandOptions;\n\n\tconstructor(public redis: Redis, config?: CacheConfig, protected useGlobally?: boolean) {\n\t\tsuper();\n\t\tthis.internalConfig = this.toInternalConfig(config);\n\t}\n\n\tpublic strategy() {\n\t\treturn this.useGlobally ? 'all' : 'explicit';\n\t}\n\n\tprivate toInternalConfig(config?: CacheConfig) {\n\t\treturn config\n\t\t\t? {\n\t\t\t\tex: config.ex,\n\t\t\t\texat: config.exat,\n\t\t\t\tpx: config.px,\n\t\t\t\tpxat: config.pxat,\n\t\t\t\tkeepTtl: config.keepTtl,\n\t\t\t} as SetCommandOptions\n\t\t\t: undefined;\n\t}\n\n\toverride async get(key: string, _tables: string[], _isTag: boolean) {\n\t\tconst res = await this.redis.get<any[]>(key) ?? undefined;\n\t\treturn res;\n\t}\n\n\toverride async put(key: string, response: any, tables: string[], isTag: boolean, config?: CacheConfig) {\n\t\tawait this.redis.set(key, response, config ? this.toInternalConfig(config) : this.internalConfig);\n\t\tfor (const table of tables) {\n\t\t\tawait this.redis.sadd(table, key);\n\t\t}\n\t}\n\n\toverride async onMutate(params: MutationOption) {\n\t\tconst tagsArray = params.tags ? Array.isArray(params.tags) ? params.tags : [params.tags] : [];\n\t\tconst tablesArray = params.tables ? Array.isArray(params.tables) ? params.tables : [params.tables] : [];\n\n\t\tconst keysToDelete = new Set<string>();\n\n\t\tfor (const table of tablesArray) {\n\t\t\tconst tableName = is(table, Table) ? table[OriginalName] : table as string;\n\t\t\tconst keys = await this.redis.smembers(tableName);\n\t\t\tfor (const key of keys) keysToDelete.add(key); // Add to the set\n\t\t}\n\n\t\tif (keysToDelete.size > 0 || tagsArray.length > 0) {\n\t\t\tconst pipeline = this.redis.pipeline();\n\n\t\t\tfor (const tag of tagsArray) {\n\t\t\t\tpipeline.del(tag);\n\t\t\t}\n\n\t\t\tfor (const key of keysToDelete) {\n\t\t\t\tpipeline.del(key);\n\t\t\t\tfor (const table of tablesArray) {\n\t\t\t\t\tconst tableName = is(table, Table) ? table[OriginalName] : table as string;\n\t\t\t\t\tpipeline.srem(tableName, key);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait pipeline.exec();\n\t\t}\n\t}\n}\n\nexport function upstashCache(\n\t{ url, token, config, global = false }: { url: string; token: string; config?: CacheConfig; global?: boolean },\n): UpstashCache {\n\tconst redis = new Redis({\n\t\turl,\n\t\ttoken,\n\t});\n\n\treturn new UpstashCache(redis, config, global);\n}\n"],"mappings":"AACA,SAAS,aAAa;AAEtB,SAAS,aAAa;AACtB,SAAS,YAAY,UAAU;AAC/B,SAAS,cAAc,aAAa;AAG7B,MAAM,qBAAqB,MAAM;AAAA,EAKvC,YAAmB,OAAc,QAAgC,aAAuB;AACvF,UAAM;AADY;AAA8C;AAEhE,SAAK,iBAAiB,KAAK,iBAAiB,MAAM;AAAA,EACnD;AAAA,EAPA,QAA0B,UAAU,IAAY;AAAA,EAExC;AAAA,EAOD,WAAW;AACjB,WAAO,KAAK,cAAc,QAAQ;AAAA,EACnC;AAAA,EAEQ,iBAAiB,QAAsB;AAC9C,WAAO,SACJ;AAAA,MACD,IAAI,OAAO;AAAA,MACX,MAAM,OAAO;AAAA,MACb,IAAI,OAAO;AAAA,MACX,MAAM,OAAO;AAAA,MACb,SAAS,OAAO;AAAA,IACjB,IACE;AAAA,EACJ;AAAA,EAEA,MAAe,IAAI,KAAa,SAAmB,QAAiB;AACnE,UAAM,MAAM,MAAM,KAAK,MAAM,IAAW,GAAG,KAAK;AAChD,WAAO;AAAA,EACR;AAAA,EAEA,MAAe,IAAI,KAAa,UAAe,QAAkB,OAAgB,QAAsB;AACtG,UAAM,KAAK,MAAM,IAAI,KAAK,UAAU,SAAS,KAAK,iBAAiB,MAAM,IAAI,KAAK,cAAc;AAChG,eAAW,SAAS,QAAQ;AAC3B,YAAM,KAAK,MAAM,KAAK,OAAO,GAAG;AAAA,IACjC;AAAA,EACD;AAAA,EAEA,MAAe,SAAS,QAAwB;AAC/C,UAAM,YAAY,OAAO,OAAO,MAAM,QAAQ,OAAO,IAAI,IAAI,OAAO,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC;AAC5F,UAAM,cAAc,OAAO,SAAS,MAAM,QAAQ,OAAO,MAAM,IAAI,OAAO,SAAS,CAAC,OAAO,MAAM,IAAI,CAAC;AAEtG,UAAM,eAAe,oBAAI,IAAY;AAErC,eAAW,SAAS,aAAa;AAChC,YAAM,YAAY,GAAG,OAAO,KAAK,IAAI,MAAM,YAAY,IAAI;AAC3D,YAAM,OAAO,MAAM,KAAK,MAAM,SAAS,SAAS;AAChD,iBAAW,OAAO;AAAM,qBAAa,IAAI,GAAG;AAAA,IAC7C;AAEA,QAAI,aAAa,OAAO,KAAK,UAAU,SAAS,GAAG;AAClD,YAAM,WAAW,KAAK,MAAM,SAAS;AAErC,iBAAW,OAAO,WAAW;AAC5B,iBAAS,IAAI,GAAG;AAAA,MACjB;AAEA,iBAAW,OAAO,cAAc;AAC/B,iBAAS,IAAI,GAAG;AAChB,mBAAW,SAAS,aAAa;AAChC,gBAAM,YAAY,GAAG,OAAO,KAAK,IAAI,MAAM,YAAY,IAAI;AAC3D,mBAAS,KAAK,WAAW,GAAG;AAAA,QAC7B;AAAA,MACD;AAEA,YAAM,SAAS,KAAK;AAAA,IACrB;AAAA,EACD;AACD;AAEO,SAAS,aACf,EAAE,KAAK,OAAO,QAAQ,SAAS,MAAM,GACtB;AACf,QAAM,QAAQ,IAAI,MAAM;AAAA,IACvB;AAAA,IACA;AAAA,EACD,CAAC;AAED,SAAO,IAAI,aAAa,OAAO,QAAQ,MAAM;AAC9C;","names":[]}
1
+ {"version":3,"sources":["../../../src/cache/upstash/cache.ts"],"sourcesContent":["import type { SetCommandOptions } from '@upstash/redis';\nimport { Redis } from '@upstash/redis';\nimport type { MutationOption } from '~/cache/core/index.ts';\nimport { Cache } from '~/cache/core/index.ts';\nimport { entityKind, is } from '~/entity.ts';\nimport { OriginalName, Table } from '~/index.ts';\nimport type { CacheConfig } from '../core/types.ts';\n\nexport class UpstashCache extends Cache {\n\tstatic override readonly [entityKind]: string = 'UpstashCache';\n\n\tprivate internalConfig?: SetCommandOptions;\n\n\tconstructor(public redis: Redis, config?: CacheConfig, protected useGlobally?: boolean) {\n\t\tsuper();\n\t\tthis.internalConfig = this.toInternalConfig(config);\n\t}\n\n\tpublic strategy() {\n\t\treturn this.useGlobally ? 'all' : 'explicit';\n\t}\n\n\tprivate toInternalConfig(config?: CacheConfig) {\n\t\treturn config\n\t\t\t? {\n\t\t\t\tex: config.ex,\n\t\t\t\texat: config.exat,\n\t\t\t\tpx: config.px,\n\t\t\t\tpxat: config.pxat,\n\t\t\t\tkeepTtl: config.keepTtl,\n\t\t\t} as SetCommandOptions\n\t\t\t: undefined;\n\t}\n\n\toverride async get(key: string, tables: string[], isTag: boolean = false): Promise<any[] | undefined> {\n\t\tconst compositeKey = tables.sort().join(','); // Generate the composite key for the query\n\n\t\tif (isTag) {\n\t\t\t// Handle cache lookup for tags\n\t\t\tconst tagCompositeKey = await this.redis.hget<string>('tagsMap', key); // Retrieve composite key associated with the tag\n\t\t\tif (tagCompositeKey) {\n\t\t\t\treturn await this.redis.hget(tagCompositeKey, key) as any[]; // Retrieve the cached result for the tag\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Normal cache lookup for the composite key\n\t\treturn await this.redis.hget(compositeKey, key) ?? undefined; // Retrieve result for normal query\n\t}\n\n\toverride async put(\n\t\tkey: string,\n\t\tresponse: any,\n\t\ttables: string[],\n\t\tisTag: boolean = false,\n\t\t_config?: CacheConfig,\n\t): Promise<void> {\n\t\tif (isTag) {\n\t\t\t// When it's a tag, store the response in the composite key\n\t\t\tconst compositeKey = tables.sort().join(',');\n\t\t\tawait this.redis.hset(compositeKey, { [key]: response }); // Store the result with the tag under the composite key\n\t\t\tawait this.redis.hset('tagsMap', { [key]: compositeKey }); // Store the tag and its composite key in the map\n\t\t\tfor (const table of tables) {\n\t\t\t\tawait this.redis.sadd(`prefix_${table}`, compositeKey);\n\t\t\t}\n\t\t} else {\n\t\t\t// Normal cache store\n\t\t\tconst compositeKey = tables.sort().join(',');\n\t\t\tawait this.redis.hset(compositeKey, { [key]: response }); // Store the result with the composite key\n\t\t}\n\t}\n\n\toverride async onMutate(params: MutationOption) {\n\t\tconst tags = Array.isArray(params.tags) ? params.tags : params.tags ? [params.tags] : [];\n\t\tconst tables = Array.isArray(params.tables) ? params.tables : params.tables ? [params.tables] : [];\n\t\tconst mappedTables = tables.map((table) => is(table, Table) ? table[OriginalName] : table as string);\n\t\tconst prefixedMappedTables = tables.map((table) => `prefix_${table}`);\n\n\t\tconst keysToDelete = new Set<string>();\n\n\t\t// Invalidate by table\n\t\tif (tables.length > 0) {\n\t\t\t// @ts-expect-error\n\t\t\tconst compositeKeys: string[] = await this.redis.sunion(...prefixedMappedTables);\n\t\t\tfor (const composite of compositeKeys) {\n\t\t\t\tconst keys = await this.redis.hkeys(composite);\n\t\t\t\tfor (const key of keys) keysToDelete.add(key);\n\t\t\t\tawait this.redis.del(composite); // Remove composite entry\n\t\t\t}\n\t\t\tawait this.redis.del(...prefixedMappedTables, ...mappedTables); // Remove table mappings\n\t\t}\n\n\t\t// Invalidate by tag (WITHOUT invalidating the entire table)\n\t\tfor (const tag of tags) {\n\t\t\tconst compositeKey = await this.redis.hget<string>('tagsMap', tag);\n\t\t\tif (compositeKey) {\n\t\t\t\tawait this.redis.hdel(compositeKey, tag); // Only remove the tag-related entry\n\t\t\t\tawait this.redis.hdel('tagsMap', tag); // Remove tag reference\n\t\t\t}\n\t\t}\n\n\t\t// Delete affected cache entries\n\t\tif (keysToDelete.size > 0) {\n\t\t\tawait this.redis.del(...keysToDelete);\n\t\t}\n\t}\n}\n\nexport function upstashCache(\n\t{ url, token, config, global = false }: { url: string; token: string; config?: CacheConfig; global?: boolean },\n): UpstashCache {\n\tconst redis = new Redis({\n\t\turl,\n\t\ttoken,\n\t});\n\n\treturn new UpstashCache(redis, config, global);\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drizzle-orm",
3
- "version": "0.40.0-bbf78ae",
3
+ "version": "0.40.0-ca1033e",
4
4
  "description": "Drizzle ORM package for SQL databases",
5
5
  "type": "module",
6
6
  "scripts": {
package/version.cjs CHANGED
@@ -26,7 +26,7 @@ __export(version_exports, {
26
26
  module.exports = __toCommonJS(version_exports);
27
27
 
28
28
  // package.json
29
- var version = "0.40.0-bbf78ae";
29
+ var version = "0.40.0-ca1033e";
30
30
 
31
31
  // src/version.ts
32
32
  var compatibilityVersion = 10;
package/version.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- var version = "0.40.0-bbf78ae";
1
+ var version = "0.40.0-ca1033e";
2
2
 
3
3
  declare const compatibilityVersion = 10;
4
4
 
package/version.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- var version = "0.40.0-bbf78ae";
1
+ var version = "0.40.0-ca1033e";
2
2
 
3
3
  declare const compatibilityVersion = 10;
4
4
 
package/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "0.40.0-bbf78ae";
2
+ var version = "0.40.0-ca1033e";
3
3
 
4
4
  // src/version.ts
5
5
  var compatibilityVersion = 10;