@smartive/datocms-utils 3.0.0-next.6 → 3.0.0-next.7

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
@@ -80,24 +80,24 @@ npm install @neondatabase/serverless
80
80
  3. Create and use the store:
81
81
 
82
82
  ```typescript
83
- import { createCacheTagsStore } from '@smartive/datocms-utils/cache/neon';
83
+ import { NeonCacheTagsProvider } from '@smartive/datocms-utils/cache/neon';
84
84
 
85
- const store = createCacheTagsStore({
85
+ const provider = new NeonCacheTagsProvider({
86
86
  connectionString: process.env.DATABASE_URL!,
87
87
  table: 'query_cache_tags',
88
88
  });
89
89
 
90
90
  // Store cache tags for a query
91
- await store.storeQueryCacheTags(queryId, ['item:42', 'product']);
91
+ await provider.storeQueryCacheTags(queryId, ['item:42', 'product']);
92
92
 
93
93
  // Find queries that reference specific tags
94
- const queries = await store.queriesReferencingCacheTags(['item:42']);
94
+ const queries = await provider.queriesReferencingCacheTags(['item:42']);
95
95
 
96
96
  // Delete specific cache tags
97
- await store.deleteCacheTags(['item:42']);
97
+ await provider.deleteCacheTags(['item:42']);
98
98
 
99
99
  // Clear all cache tags
100
- await store.truncateCacheTags();
100
+ await provider.truncateCacheTags();
101
101
  ```
102
102
 
103
103
  ##### Redis Provider
@@ -112,21 +112,21 @@ Use Redis to store cache tag mappings with better performance for high-traffic a
112
112
  npm install ioredis
113
113
  ```
114
114
 
115
- 2. Create and use the store:
115
+ 2. Create and use the provider:
116
116
 
117
117
  ```typescript
118
- import { createCacheTagsStore } from '@smartive/datocms-utils/cache/redis';
118
+ import { RedisCacheTagsProvider } from '@smartive/datocms-utils/cache/redis';
119
119
 
120
- const store = createCacheTagsStore({
120
+ const provider = new RedisCacheTagsProvider({
121
121
  url: process.env.REDIS_URL!,
122
122
  keyPrefix: 'prod:', // Optional: namespace for multi-environment setups
123
123
  });
124
124
 
125
125
  // Same API as Neon provider
126
- await store.storeQueryCacheTags(queryId, ['item:42', 'product']);
126
+ await provider.storeQueryCacheTags(queryId, ['item:42', 'product']);
127
127
  const queries = await store.queriesReferencingCacheTags(['item:42']);
128
- await store.deleteCacheTags(['item:42']);
129
- await store.truncateCacheTags();
128
+ await provider.deleteCacheTags(['item:42']);
129
+ await provider.truncateCacheTags();
130
130
  ```
131
131
 
132
132
  **Redis connection string examples:**
@@ -142,7 +142,7 @@ REDIS_URL=redis://username:password@redis-host:6379
142
142
  REDIS_URL=redis://localhost:6379
143
143
  ```
144
144
 
145
- #### `CacheTagsStore` Interface
145
+ #### `CacheTagsProvider` Interface
146
146
 
147
147
  Both providers implement:
148
148
 
@@ -155,9 +155,9 @@ Both providers implement:
155
155
 
156
156
  ```typescript
157
157
  import { generateQueryId, parseXCacheTagsResponseHeader } from '@smartive/datocms-utils/cache';
158
- import { createCacheTagsStore } from '@smartive/datocms-utils/cache/redis';
158
+ import { RedisCacheTagsProvider } from '@smartive/datocms-utils/cache/redis';
159
159
 
160
- const store = createCacheTagsStore({
160
+ const provider = new RedisCacheTagsProvider({
161
161
  url: process.env.REDIS_URL!,
162
162
  keyPrefix: 'myapp:',
163
163
  });
@@ -165,12 +165,12 @@ const store = createCacheTagsStore({
165
165
  // After making a DatoCMS query
166
166
  const queryId = generateQueryId(query, variables);
167
167
  const cacheTags = parseXCacheTagsResponseHeader(response.headers['x-cache-tags']);
168
- await store.storeQueryCacheTags(queryId, cacheTags);
168
+ await provider.storeQueryCacheTags(queryId, cacheTags);
169
169
 
170
170
  // When handling DatoCMS webhook for cache invalidation
171
- const affectedQueries = await store.queriesReferencingCacheTags(webhook.entity.attributes.tags);
171
+ const affectedQueries = await provider.queriesReferencingCacheTags(webhook.entity.attributes.tags);
172
172
  // Revalidate affected queries...
173
- await store.deleteCacheTags(webhook.entity.attributes.tags);
173
+ await provider.deleteCacheTags(webhook.entity.attributes.tags);
174
174
  ```
175
175
 
176
176
  ## TypeScript Types
@@ -179,7 +179,7 @@ The package includes TypeScript types for DatoCMS webhooks and cache tags:
179
179
 
180
180
  - `CacheTag`: A branded type for cache tags, ensuring type safety
181
181
  - `CacheTagsInvalidateWebhook`: Type definition for DatoCMS cache tag invalidation webhook payloads
182
- - `CacheTagsStore`: Interface for cache tag storage implementations
182
+ - `CacheTagsProvider`: Interface for cache tag storage implementations
183
183
 
184
184
  ## License
185
185
 
@@ -1,4 +1,4 @@
1
- import { type CacheTagsStore } from '../types.js';
1
+ import { type CacheTag, type CacheTagsProvider } from '../types.js';
2
2
  type NeonCacheTagsStoreConfig = {
3
3
  /**
4
4
  * Neon connection string. You can find it in the "Connection" tab of your Neon project dashboard.
@@ -19,10 +19,15 @@ type NeonCacheTagsStoreConfig = {
19
19
  readonly table: string;
20
20
  };
21
21
  /**
22
- * Creates a `CacheTagsStore` implementation using Neon as the storage backend. Neon is a serverless Postgres database service.
23
- *
24
- * @param {NeonCacheTagsStoreConfig} config Configuration object containing the Neon connection string and table name.
25
- * @returns An object implementing the `CacheTagsStore` interface, allowing you to store and manage cache tags in a Neon database.
22
+ * A `CacheTagsProvider` implementation that uses Neon as the storage backend.
26
23
  */
27
- export declare const createCacheTagsStore: ({ connectionUrl, table }: NeonCacheTagsStoreConfig) => CacheTagsStore;
24
+ export declare class NeonCacheTagsProvider implements CacheTagsProvider {
25
+ private readonly sql;
26
+ private readonly table;
27
+ constructor({ connectionUrl, table }: NeonCacheTagsStoreConfig);
28
+ storeQueryCacheTags(queryId: string, cacheTags: CacheTag[]): Promise<void>;
29
+ queriesReferencingCacheTags(cacheTags: CacheTag[]): Promise<string[]>;
30
+ deleteCacheTags(cacheTags: CacheTag[]): Promise<number>;
31
+ truncateCacheTags(): Promise<number>;
32
+ }
28
33
  export {};
@@ -1,46 +1,44 @@
1
1
  import { neon } from '@neondatabase/serverless';
2
2
  /**
3
- * Creates a `CacheTagsStore` implementation using Neon as the storage backend. Neon is a serverless Postgres database service.
4
- *
5
- * @param {NeonCacheTagsStoreConfig} config Configuration object containing the Neon connection string and table name.
6
- * @returns An object implementing the `CacheTagsStore` interface, allowing you to store and manage cache tags in a Neon database.
3
+ * A `CacheTagsProvider` implementation that uses Neon as the storage backend.
7
4
  */
8
- export const createCacheTagsStore = ({ connectionUrl, table }) => {
9
- const sql = neon(connectionUrl, { fullResults: true });
10
- const storeQueryCacheTags = async (queryId, cacheTags) => {
5
+ export class NeonCacheTagsProvider {
6
+ sql;
7
+ table;
8
+ constructor({ connectionUrl, table }) {
9
+ this.sql = neon(connectionUrl, { fullResults: true });
10
+ this.table = table;
11
+ }
12
+ async storeQueryCacheTags(queryId, cacheTags) {
11
13
  if (!cacheTags?.length) {
12
14
  return;
13
15
  }
14
16
  const tags = cacheTags.flatMap((_, i) => [queryId, cacheTags[i]]);
15
17
  const placeholders = cacheTags.map((_, i) => `($${2 * i + 1}, $${2 * i + 2})`).join(',');
16
- await sql.query(`INSERT INTO ${table} VALUES ${placeholders} ON CONFLICT DO NOTHING`, tags);
17
- };
18
- const queriesReferencingCacheTags = async (cacheTags) => {
18
+ await this.sql.query(`INSERT INTO ${this.table} VALUES ${placeholders} ON CONFLICT DO NOTHING`, tags);
19
+ }
20
+ async queriesReferencingCacheTags(cacheTags) {
19
21
  if (!cacheTags?.length) {
20
22
  return [];
21
23
  }
22
24
  const placeholders = cacheTags.map((_, i) => `$${i + 1}`).join(',');
23
- const { rows } = await sql.query(`SELECT DISTINCT query_id FROM ${table} WHERE cache_tag IN (${placeholders})`, cacheTags);
25
+ const { rows } = await this.sql.query(`SELECT DISTINCT query_id FROM ${this.table} WHERE cache_tag IN (${placeholders})`, cacheTags);
24
26
  return rows.reduce((queryIds, row) => {
25
27
  if (typeof row.query_id === 'string') {
26
28
  queryIds.push(row.query_id);
27
29
  }
28
30
  return queryIds;
29
31
  }, []);
30
- };
31
- const deleteCacheTags = async (cacheTags) => {
32
+ }
33
+ async deleteCacheTags(cacheTags) {
32
34
  if (cacheTags.length === 0) {
33
35
  return 0;
34
36
  }
35
37
  const placeholders = cacheTags.map((_, i) => `$${i + 1}`).join(',');
36
- return (await sql.query(`DELETE FROM ${table} WHERE cache_tag IN (${placeholders})`, cacheTags)).rowCount ?? 0;
37
- };
38
- const truncateCacheTags = async () => (await sql.query(`DELETE FROM ${table}`)).rowCount ?? 0;
39
- return {
40
- storeQueryCacheTags,
41
- queriesReferencingCacheTags,
42
- deleteCacheTags,
43
- truncateCacheTags,
44
- };
45
- };
38
+ return (await this.sql.query(`DELETE FROM ${this.table} WHERE cache_tag IN (${placeholders})`, cacheTags)).rowCount ?? 0;
39
+ }
40
+ async truncateCacheTags() {
41
+ return (await this.sql.query(`DELETE FROM ${this.table}`)).rowCount ?? 0;
42
+ }
43
+ }
46
44
  //# sourceMappingURL=neon.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"neon.js","sourceRoot":"","sources":["../../../src/cache/provider/neon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAuBhD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,EAAE,aAAa,EAAE,KAAK,EAA4B,EAAkB,EAAE;IACzG,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;IAEvD,MAAM,mBAAmB,GAAG,KAAK,EAAE,OAAe,EAAE,SAAqB,EAAE,EAAE;QAC3E,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClE,MAAM,YAAY,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEzF,MAAM,GAAG,CAAC,KAAK,CAAC,eAAe,KAAK,WAAW,YAAY,yBAAyB,EAAE,IAAI,CAAC,CAAC;IAC9F,CAAC,CAAC;IAEF,MAAM,2BAA2B,GAAG,KAAK,EAAE,SAAqB,EAAqB,EAAE;QACrF,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;YACvB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,YAAY,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEpE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,GAAG,CAAC,KAAK,CAC9B,iCAAiC,KAAK,wBAAwB,YAAY,GAAG,EAC7E,SAAS,CACV,CAAC;QAEF,OAAO,IAAI,CAAC,MAAM,CAAW,CAAC,QAAQ,EAAE,GAAG,EAAE,EAAE;YAC7C,IAAI,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBACrC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC9B,CAAC;YAED,OAAO,QAAQ,CAAC;QAClB,CAAC,EAAE,EAAE,CAAC,CAAC;IACT,CAAC,CAAC;IAEF,MAAM,eAAe,GAAG,KAAK,EAAE,SAAqB,EAAE,EAAE;QACtD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,CAAC;QACX,CAAC;QACD,MAAM,YAAY,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEpE,OAAO,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,eAAe,KAAK,wBAAwB,YAAY,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC;IACjH,CAAC,CAAC;IAEF,MAAM,iBAAiB,GAAG,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,eAAe,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC;IAE9F,OAAO;QACL,mBAAmB;QACnB,2BAA2B;QAC3B,eAAe;QACf,iBAAiB;KAClB,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"neon.js","sourceRoot":"","sources":["../../../src/cache/provider/neon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAuBhD;;GAEG;AACH,MAAM,OAAO,qBAAqB;IACf,GAAG,CAAC;IACJ,KAAK,CAAC;IAEvB,YAAY,EAAE,aAAa,EAAE,KAAK,EAA4B;QAC5D,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,aAAa,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAEM,KAAK,CAAC,mBAAmB,CAAC,OAAe,EAAE,SAAqB;QACrE,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClE,MAAM,YAAY,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEzF,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,eAAe,IAAI,CAAC,KAAK,WAAW,YAAY,yBAAyB,EAAE,IAAI,CAAC,CAAC;IACxG,CAAC;IAEM,KAAK,CAAC,2BAA2B,CAAC,SAAqB;QAC5D,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;YACvB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,YAAY,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEpE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,CACnC,iCAAiC,IAAI,CAAC,KAAK,wBAAwB,YAAY,GAAG,EAClF,SAAS,CACV,CAAC;QAEF,OAAO,IAAI,CAAC,MAAM,CAAW,CAAC,QAAQ,EAAE,GAAG,EAAE,EAAE;YAC7C,IAAI,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBACrC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC9B,CAAC;YAED,OAAO,QAAQ,CAAC;QAClB,CAAC,EAAE,EAAE,CAAC,CAAC;IACT,CAAC;IAEM,KAAK,CAAC,eAAe,CAAC,SAAqB;QAChD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,CAAC;QACX,CAAC;QACD,MAAM,YAAY,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEpE,OAAO,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,eAAe,IAAI,CAAC,KAAK,wBAAwB,YAAY,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC;IAC3H,CAAC;IAEM,KAAK,CAAC,iBAAiB;QAC5B,OAAO,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,eAAe,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC;IAC3E,CAAC;CACF"}
@@ -1,9 +1,12 @@
1
- import { type CacheTagsStore } from '../types.js';
1
+ import { type CacheTag, type CacheTagsProvider } from '../types.js';
2
2
  /**
3
- * Creates a `CacheTagsStore` implementation that does not perform any actual storage operations.
3
+ * A `CacheTagsProvider` implementation that does not perform any actual storage operations.
4
4
  *
5
5
  * _Note: This implementation is useful for testing purposes or when you want to disable caching without changing the code that interacts with the cache._
6
- *
7
- * @returns An object implementing the `CacheTagsStore` interface.
8
6
  */
9
- export declare const createCacheTagsStore: () => CacheTagsStore;
7
+ export declare class NoopCacheTagsProvider implements CacheTagsProvider {
8
+ storeQueryCacheTags(queryId: string, cacheTags: CacheTag[]): Promise<void>;
9
+ queriesReferencingCacheTags(cacheTags: CacheTag[]): Promise<string[]>;
10
+ deleteCacheTags(cacheTags: CacheTag[]): Promise<number>;
11
+ truncateCacheTags(): Promise<number>;
12
+ }
@@ -1,32 +1,24 @@
1
1
  /**
2
- * Creates a `CacheTagsStore` implementation that does not perform any actual storage operations.
2
+ * A `CacheTagsProvider` implementation that does not perform any actual storage operations.
3
3
  *
4
4
  * _Note: This implementation is useful for testing purposes or when you want to disable caching without changing the code that interacts with the cache._
5
- *
6
- * @returns An object implementing the `CacheTagsStore` interface.
7
5
  */
8
- export const createCacheTagsStore = () => {
9
- const storeQueryCacheTags = async (queryId, cacheTags) => {
6
+ export class NoopCacheTagsProvider {
7
+ async storeQueryCacheTags(queryId, cacheTags) {
10
8
  console.debug('-- storeQueryCacheTags called', { queryId, cacheTags });
11
9
  return Promise.resolve();
12
- };
13
- const queriesReferencingCacheTags = async (cacheTags) => {
10
+ }
11
+ async queriesReferencingCacheTags(cacheTags) {
14
12
  console.debug('-- queriesReferencingCacheTags called', { cacheTags });
15
13
  return Promise.resolve([]);
16
- };
17
- const deleteCacheTags = async (cacheTags) => {
14
+ }
15
+ async deleteCacheTags(cacheTags) {
18
16
  console.debug('-- deleteCacheTags called', { cacheTags });
19
17
  return Promise.resolve(0);
20
- };
21
- const truncateCacheTags = async () => {
18
+ }
19
+ async truncateCacheTags() {
22
20
  console.debug('-- truncateCacheTags called');
23
21
  return Promise.resolve(0);
24
- };
25
- return {
26
- storeQueryCacheTags,
27
- queriesReferencingCacheTags,
28
- deleteCacheTags,
29
- truncateCacheTags,
30
- };
31
- };
22
+ }
23
+ }
32
24
  //# sourceMappingURL=noop.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"noop.js","sourceRoot":"","sources":["../../../src/cache/provider/noop.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAmB,EAAE;IACvD,MAAM,mBAAmB,GAAG,KAAK,EAAE,OAAe,EAAE,SAAqB,EAAE,EAAE;QAC3E,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;QAEvE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC,CAAC;IAEF,MAAM,2BAA2B,GAAG,KAAK,EAAE,SAAqB,EAAE,EAAE;QAClE,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QAEtE,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7B,CAAC,CAAC;IAEF,MAAM,eAAe,GAAG,KAAK,EAAE,SAAqB,EAAE,EAAE;QACtD,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QAE1D,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC;IAEF,MAAM,iBAAiB,GAAG,KAAK,IAAI,EAAE;QACnC,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAE7C,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC;IAEF,OAAO;QACL,mBAAmB;QACnB,2BAA2B;QAC3B,eAAe;QACf,iBAAiB;KAClB,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"noop.js","sourceRoot":"","sources":["../../../src/cache/provider/noop.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,OAAO,qBAAqB;IACzB,KAAK,CAAC,mBAAmB,CAAC,OAAe,EAAE,SAAqB;QACrE,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;QAEvE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAEM,KAAK,CAAC,2BAA2B,CAAC,SAAqB;QAC5D,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QAEtE,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7B,CAAC;IAEM,KAAK,CAAC,eAAe,CAAC,SAAqB;QAChD,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QAE1D,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC;IAEM,KAAK,CAAC,iBAAiB;QAC5B,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAE7C,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC;CACF"}
@@ -1,4 +1,4 @@
1
- import { type CacheTagsStore } from '../types.js';
1
+ import { type CacheTag, type CacheTagsProvider } from '../types.js';
2
2
  type RedisCacheTagsStoreConfig = {
3
3
  /**
4
4
  * Redis connection string. For example, `redis://user:pass@host:port/db`.
@@ -12,10 +12,15 @@ type RedisCacheTagsStoreConfig = {
12
12
  readonly keyPrefix?: string;
13
13
  };
14
14
  /**
15
- * Creates a `CacheTagsStore` implementation using Redis as the storage backend.
16
- *
17
- * @param {RedisCacheTagsStoreConfig} config Configuration object containing the Redis connection string and optional key prefix.
18
- * @returns An object implementing the `CacheTagsStore` interface, allowing you to store and manage cache tags in a Redis database.
15
+ * A `CacheTagsProvider` implementation that uses Redis as the storage backend.
19
16
  */
20
- export declare const createCacheTagsStore: ({ connectionUrl, keyPrefix }: RedisCacheTagsStoreConfig) => CacheTagsStore;
17
+ export declare class RedisCacheTagsProvider implements CacheTagsProvider {
18
+ private readonly redis;
19
+ private readonly keyPrefix;
20
+ constructor({ connectionUrl, keyPrefix }: RedisCacheTagsStoreConfig);
21
+ storeQueryCacheTags(queryId: string, cacheTags: CacheTag[]): Promise<void>;
22
+ queriesReferencingCacheTags(cacheTags: CacheTag[]): Promise<string[]>;
23
+ deleteCacheTags(cacheTags: CacheTag[]): Promise<number>;
24
+ truncateCacheTags(): Promise<number>;
25
+ }
21
26
  export {};
@@ -1,52 +1,48 @@
1
1
  import { Redis } from 'ioredis';
2
2
  /**
3
- * Creates a `CacheTagsStore` implementation using Redis as the storage backend.
4
- *
5
- * @param {RedisCacheTagsStoreConfig} config Configuration object containing the Redis connection string and optional key prefix.
6
- * @returns An object implementing the `CacheTagsStore` interface, allowing you to store and manage cache tags in a Redis database.
3
+ * A `CacheTagsProvider` implementation that uses Redis as the storage backend.
7
4
  */
8
- export const createCacheTagsStore = ({ connectionUrl, keyPrefix = '' }) => {
9
- const redis = new Redis(connectionUrl, {
10
- maxRetriesPerRequest: 3,
11
- lazyConnect: true,
12
- });
13
- const storeQueryCacheTags = async (queryId, cacheTags) => {
5
+ export class RedisCacheTagsProvider {
6
+ redis;
7
+ keyPrefix;
8
+ constructor({ connectionUrl, keyPrefix }) {
9
+ this.redis = new Redis(connectionUrl, {
10
+ maxRetriesPerRequest: 3,
11
+ lazyConnect: true,
12
+ });
13
+ this.keyPrefix = keyPrefix ?? '';
14
+ }
15
+ async storeQueryCacheTags(queryId, cacheTags) {
14
16
  if (!cacheTags?.length) {
15
17
  return;
16
18
  }
17
- const pipeline = redis.pipeline();
19
+ const pipeline = this.redis.pipeline();
18
20
  for (const tag of cacheTags) {
19
- pipeline.sadd(`${keyPrefix}${tag}`, queryId);
21
+ pipeline.sadd(`${this.keyPrefix}${tag}`, queryId);
20
22
  }
21
23
  await pipeline.exec();
22
- };
23
- const queriesReferencingCacheTags = async (cacheTags) => {
24
+ }
25
+ async queriesReferencingCacheTags(cacheTags) {
24
26
  if (!cacheTags?.length) {
25
27
  return [];
26
28
  }
27
- const keys = cacheTags.map((tag) => `${keyPrefix}${tag}`);
28
- return redis.sunion(...keys);
29
- };
30
- const deleteCacheTags = async (cacheTags) => {
29
+ const keys = cacheTags.map((tag) => `${this.keyPrefix}${tag}`);
30
+ return this.redis.sunion(...keys);
31
+ }
32
+ async deleteCacheTags(cacheTags) {
31
33
  if (!cacheTags?.length) {
32
34
  return 0;
33
35
  }
34
- const keys = cacheTags.map((tag) => `${keyPrefix}${tag}`);
35
- return redis.del(...keys);
36
- };
37
- const truncateCacheTags = async () => {
38
- const pattern = `${keyPrefix}*`;
39
- const keys = await redis.keys(pattern);
36
+ const keys = cacheTags.map((tag) => `${this.keyPrefix}${tag}`);
37
+ return this.redis.del(...keys);
38
+ }
39
+ async truncateCacheTags() {
40
+ const pattern = `${this.keyPrefix}*`;
41
+ const keys = await this.redis.keys(pattern);
40
42
  if (keys.length === 0) {
41
43
  return 0;
42
44
  }
43
- return await redis.del(...keys);
44
- };
45
- return {
46
- storeQueryCacheTags,
47
- queriesReferencingCacheTags,
48
- deleteCacheTags,
49
- truncateCacheTags,
50
- };
51
- };
45
+ return await this.redis.del(...keys);
46
+ }
47
+ }
52
48
  //# sourceMappingURL=redis.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"redis.js","sourceRoot":"","sources":["../../../src/cache/provider/redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAgBhC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,EAAE,aAAa,EAAE,SAAS,GAAG,EAAE,EAA6B,EAAkB,EAAE;IACnH,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,aAAa,EAAE;QACrC,oBAAoB,EAAE,CAAC;QACvB,WAAW,EAAE,IAAI;KAClB,CAAC,CAAC;IAEH,MAAM,mBAAmB,GAAG,KAAK,EAAE,OAAe,EAAE,SAAqB,EAAE,EAAE;QAC3E,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QAElC,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;YAC5B,QAAQ,CAAC,IAAI,CAAC,GAAG,SAAS,GAAG,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;QAC/C,CAAC;QAED,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC,CAAC;IAEF,MAAM,2BAA2B,GAAG,KAAK,EAAE,SAAqB,EAAE,EAAE;QAClE,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;YACvB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,SAAS,GAAG,GAAG,EAAE,CAAC,CAAC;QAE1D,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;IAC/B,CAAC,CAAC;IAEF,MAAM,eAAe,GAAG,KAAK,EAAE,SAAqB,EAAE,EAAE;QACtD,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;YACvB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,SAAS,GAAG,GAAG,EAAE,CAAC,CAAC;QAE1D,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5B,CAAC,CAAC;IAEF,MAAM,iBAAiB,GAAG,KAAK,IAAI,EAAE;QACnC,MAAM,OAAO,GAAG,GAAG,SAAS,GAAG,CAAC;QAChC,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEvC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,OAAO,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC;IAEF,OAAO;QACL,mBAAmB;QACnB,2BAA2B;QAC3B,eAAe;QACf,iBAAiB;KAClB,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"redis.js","sourceRoot":"","sources":["../../../src/cache/provider/redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAgBhC;;GAEG;AACH,MAAM,OAAO,sBAAsB;IAChB,KAAK,CAAC;IACN,SAAS,CAAC;IAE3B,YAAY,EAAE,aAAa,EAAE,SAAS,EAA6B;QACjE,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,aAAa,EAAE;YACpC,oBAAoB,EAAE,CAAC;YACvB,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;QACH,IAAI,CAAC,SAAS,GAAG,SAAS,IAAI,EAAE,CAAC;IACnC,CAAC;IAEM,KAAK,CAAC,mBAAmB,CAAC,OAAe,EAAE,SAAqB;QACrE,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QAEvC,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;YAC5B,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,GAAG,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;QACpD,CAAC;QAED,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC;IAEM,KAAK,CAAC,2BAA2B,CAAC,SAAqB;QAC5D,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;YACvB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC,CAAC;QAE/D,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;IACpC,CAAC;IAEM,KAAK,CAAC,eAAe,CAAC,SAAqB;QAChD,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;YACvB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC,CAAC;QAE/D,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,iBAAiB;QAC5B,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC;QACrC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE5C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IACvC,CAAC;CACF"}
@@ -26,7 +26,7 @@ export type CacheTagsInvalidateWebhook = {
26
26
  /**
27
27
  * Configuration object for creating a `CacheTagsStore` implementation.
28
28
  */
29
- export type CacheTagsStore = {
29
+ export interface CacheTagsProvider {
30
30
  /**
31
31
  * Stores the cache tags of a query.
32
32
  *
@@ -60,4 +60,4 @@ export type CacheTagsStore = {
60
60
  * ⚠️ **Warning**: This will delete all cache tag data. Use with caution!
61
61
  */
62
62
  truncateCacheTags(): Promise<number>;
63
- };
63
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartive/datocms-utils",
3
- "version": "3.0.0-next.6",
3
+ "version": "3.0.0-next.7",
4
4
  "description": "A set of utilities and helpers to work with DatoCMS in a Next.js project.",
5
5
  "type": "module",
6
6
  "source": "./src/index.ts",
@@ -1,5 +1,5 @@
1
1
  import { neon } from '@neondatabase/serverless';
2
- import { type CacheTag, type CacheTagsStore } from '../types.js';
2
+ import { type CacheTag, type CacheTagsProvider } from '../types.js';
3
3
 
4
4
  type NeonCacheTagsStoreConfig = {
5
5
  /**
@@ -22,15 +22,18 @@ type NeonCacheTagsStoreConfig = {
22
22
  };
23
23
 
24
24
  /**
25
- * Creates a `CacheTagsStore` implementation using Neon as the storage backend. Neon is a serverless Postgres database service.
26
- *
27
- * @param {NeonCacheTagsStoreConfig} config Configuration object containing the Neon connection string and table name.
28
- * @returns An object implementing the `CacheTagsStore` interface, allowing you to store and manage cache tags in a Neon database.
25
+ * A `CacheTagsProvider` implementation that uses Neon as the storage backend.
29
26
  */
30
- export const createCacheTagsStore = ({ connectionUrl, table }: NeonCacheTagsStoreConfig): CacheTagsStore => {
31
- const sql = neon(connectionUrl, { fullResults: true });
27
+ export class NeonCacheTagsProvider implements CacheTagsProvider {
28
+ private readonly sql;
29
+ private readonly table;
32
30
 
33
- const storeQueryCacheTags = async (queryId: string, cacheTags: CacheTag[]) => {
31
+ constructor({ connectionUrl, table }: NeonCacheTagsStoreConfig) {
32
+ this.sql = neon(connectionUrl, { fullResults: true });
33
+ this.table = table;
34
+ }
35
+
36
+ public async storeQueryCacheTags(queryId: string, cacheTags: CacheTag[]) {
34
37
  if (!cacheTags?.length) {
35
38
  return;
36
39
  }
@@ -38,18 +41,18 @@ export const createCacheTagsStore = ({ connectionUrl, table }: NeonCacheTagsStor
38
41
  const tags = cacheTags.flatMap((_, i) => [queryId, cacheTags[i]]);
39
42
  const placeholders = cacheTags.map((_, i) => `($${2 * i + 1}, $${2 * i + 2})`).join(',');
40
43
 
41
- await sql.query(`INSERT INTO ${table} VALUES ${placeholders} ON CONFLICT DO NOTHING`, tags);
42
- };
44
+ await this.sql.query(`INSERT INTO ${this.table} VALUES ${placeholders} ON CONFLICT DO NOTHING`, tags);
45
+ }
43
46
 
44
- const queriesReferencingCacheTags = async (cacheTags: CacheTag[]): Promise<string[]> => {
47
+ public async queriesReferencingCacheTags(cacheTags: CacheTag[]): Promise<string[]> {
45
48
  if (!cacheTags?.length) {
46
49
  return [];
47
50
  }
48
51
 
49
52
  const placeholders = cacheTags.map((_, i) => `$${i + 1}`).join(',');
50
53
 
51
- const { rows } = await sql.query(
52
- `SELECT DISTINCT query_id FROM ${table} WHERE cache_tag IN (${placeholders})`,
54
+ const { rows } = await this.sql.query(
55
+ `SELECT DISTINCT query_id FROM ${this.table} WHERE cache_tag IN (${placeholders})`,
53
56
  cacheTags,
54
57
  );
55
58
 
@@ -60,23 +63,18 @@ export const createCacheTagsStore = ({ connectionUrl, table }: NeonCacheTagsStor
60
63
 
61
64
  return queryIds;
62
65
  }, []);
63
- };
66
+ }
64
67
 
65
- const deleteCacheTags = async (cacheTags: CacheTag[]) => {
68
+ public async deleteCacheTags(cacheTags: CacheTag[]) {
66
69
  if (cacheTags.length === 0) {
67
70
  return 0;
68
71
  }
69
72
  const placeholders = cacheTags.map((_, i) => `$${i + 1}`).join(',');
70
73
 
71
- return (await sql.query(`DELETE FROM ${table} WHERE cache_tag IN (${placeholders})`, cacheTags)).rowCount ?? 0;
72
- };
73
-
74
- const truncateCacheTags = async () => (await sql.query(`DELETE FROM ${table}`)).rowCount ?? 0;
74
+ return (await this.sql.query(`DELETE FROM ${this.table} WHERE cache_tag IN (${placeholders})`, cacheTags)).rowCount ?? 0;
75
+ }
75
76
 
76
- return {
77
- storeQueryCacheTags,
78
- queriesReferencingCacheTags,
79
- deleteCacheTags,
80
- truncateCacheTags,
81
- };
82
- };
77
+ public async truncateCacheTags() {
78
+ return (await this.sql.query(`DELETE FROM ${this.table}`)).rowCount ?? 0;
79
+ }
80
+ }
@@ -1,41 +1,32 @@
1
- import { type CacheTag, type CacheTagsStore } from '../types.js';
1
+ import { type CacheTag, type CacheTagsProvider } from '../types.js';
2
2
 
3
3
  /**
4
- * Creates a `CacheTagsStore` implementation that does not perform any actual storage operations.
4
+ * A `CacheTagsProvider` implementation that does not perform any actual storage operations.
5
5
  *
6
6
  * _Note: This implementation is useful for testing purposes or when you want to disable caching without changing the code that interacts with the cache._
7
- *
8
- * @returns An object implementing the `CacheTagsStore` interface.
9
7
  */
10
- export const createCacheTagsStore = (): CacheTagsStore => {
11
- const storeQueryCacheTags = async (queryId: string, cacheTags: CacheTag[]) => {
8
+ export class NoopCacheTagsProvider implements CacheTagsProvider {
9
+ public async storeQueryCacheTags(queryId: string, cacheTags: CacheTag[]) {
12
10
  console.debug('-- storeQueryCacheTags called', { queryId, cacheTags });
13
11
 
14
12
  return Promise.resolve();
15
- };
13
+ }
16
14
 
17
- const queriesReferencingCacheTags = async (cacheTags: CacheTag[]) => {
15
+ public async queriesReferencingCacheTags(cacheTags: CacheTag[]): Promise<string[]> {
18
16
  console.debug('-- queriesReferencingCacheTags called', { cacheTags });
19
17
 
20
18
  return Promise.resolve([]);
21
- };
19
+ }
22
20
 
23
- const deleteCacheTags = async (cacheTags: CacheTag[]) => {
21
+ public async deleteCacheTags(cacheTags: CacheTag[]) {
24
22
  console.debug('-- deleteCacheTags called', { cacheTags });
25
23
 
26
24
  return Promise.resolve(0);
27
- };
25
+ }
28
26
 
29
- const truncateCacheTags = async () => {
27
+ public async truncateCacheTags() {
30
28
  console.debug('-- truncateCacheTags called');
31
29
 
32
30
  return Promise.resolve(0);
33
- };
34
-
35
- return {
36
- storeQueryCacheTags,
37
- queriesReferencingCacheTags,
38
- deleteCacheTags,
39
- truncateCacheTags,
40
- };
41
- };
31
+ }
32
+ }
@@ -1,5 +1,5 @@
1
1
  import { Redis } from 'ioredis';
2
- import { type CacheTag, type CacheTagsStore } from '../types.js';
2
+ import { type CacheTag, type CacheTagsProvider } from '../types.js';
3
3
 
4
4
  type RedisCacheTagsStoreConfig = {
5
5
  /**
@@ -15,66 +15,62 @@ type RedisCacheTagsStoreConfig = {
15
15
  };
16
16
 
17
17
  /**
18
- * Creates a `CacheTagsStore` implementation using Redis as the storage backend.
19
- *
20
- * @param {RedisCacheTagsStoreConfig} config Configuration object containing the Redis connection string and optional key prefix.
21
- * @returns An object implementing the `CacheTagsStore` interface, allowing you to store and manage cache tags in a Redis database.
18
+ * A `CacheTagsProvider` implementation that uses Redis as the storage backend.
22
19
  */
23
- export const createCacheTagsStore = ({ connectionUrl, keyPrefix = '' }: RedisCacheTagsStoreConfig): CacheTagsStore => {
24
- const redis = new Redis(connectionUrl, {
25
- maxRetriesPerRequest: 3,
26
- lazyConnect: true,
27
- });
28
-
29
- const storeQueryCacheTags = async (queryId: string, cacheTags: CacheTag[]) => {
20
+ export class RedisCacheTagsProvider implements CacheTagsProvider {
21
+ private readonly redis;
22
+ private readonly keyPrefix;
23
+
24
+ constructor({ connectionUrl, keyPrefix }: RedisCacheTagsStoreConfig) {
25
+ this.redis = new Redis(connectionUrl, {
26
+ maxRetriesPerRequest: 3,
27
+ lazyConnect: true,
28
+ });
29
+ this.keyPrefix = keyPrefix ?? '';
30
+ }
31
+
32
+ public async storeQueryCacheTags(queryId: string, cacheTags: CacheTag[]) {
30
33
  if (!cacheTags?.length) {
31
34
  return;
32
35
  }
33
36
 
34
- const pipeline = redis.pipeline();
37
+ const pipeline = this.redis.pipeline();
35
38
 
36
39
  for (const tag of cacheTags) {
37
- pipeline.sadd(`${keyPrefix}${tag}`, queryId);
40
+ pipeline.sadd(`${this.keyPrefix}${tag}`, queryId);
38
41
  }
39
42
 
40
43
  await pipeline.exec();
41
- };
44
+ }
42
45
 
43
- const queriesReferencingCacheTags = async (cacheTags: CacheTag[]) => {
46
+ public async queriesReferencingCacheTags(cacheTags: CacheTag[]) {
44
47
  if (!cacheTags?.length) {
45
48
  return [];
46
49
  }
47
50
 
48
- const keys = cacheTags.map((tag) => `${keyPrefix}${tag}`);
51
+ const keys = cacheTags.map((tag) => `${this.keyPrefix}${tag}`);
49
52
 
50
- return redis.sunion(...keys);
51
- };
53
+ return this.redis.sunion(...keys);
54
+ }
52
55
 
53
- const deleteCacheTags = async (cacheTags: CacheTag[]) => {
56
+ public async deleteCacheTags(cacheTags: CacheTag[]) {
54
57
  if (!cacheTags?.length) {
55
58
  return 0;
56
59
  }
57
60
 
58
- const keys = cacheTags.map((tag) => `${keyPrefix}${tag}`);
61
+ const keys = cacheTags.map((tag) => `${this.keyPrefix}${tag}`);
59
62
 
60
- return redis.del(...keys);
61
- };
63
+ return this.redis.del(...keys);
64
+ }
62
65
 
63
- const truncateCacheTags = async () => {
64
- const pattern = `${keyPrefix}*`;
65
- const keys = await redis.keys(pattern);
66
+ public async truncateCacheTags() {
67
+ const pattern = `${this.keyPrefix}*`;
68
+ const keys = await this.redis.keys(pattern);
66
69
 
67
70
  if (keys.length === 0) {
68
71
  return 0;
69
72
  }
70
73
 
71
- return await redis.del(...keys);
72
- };
73
-
74
- return {
75
- storeQueryCacheTags,
76
- queriesReferencingCacheTags,
77
- deleteCacheTags,
78
- truncateCacheTags,
79
- };
80
- };
74
+ return await this.redis.del(...keys);
75
+ }
76
+ }
@@ -26,7 +26,7 @@ export type CacheTagsInvalidateWebhook = {
26
26
  /**
27
27
  * Configuration object for creating a `CacheTagsStore` implementation.
28
28
  */
29
- export type CacheTagsStore = {
29
+ export interface CacheTagsProvider {
30
30
  /**
31
31
  * Stores the cache tags of a query.
32
32
  *
@@ -63,4 +63,4 @@ export type CacheTagsStore = {
63
63
  * ⚠️ **Warning**: This will delete all cache tag data. Use with caution!
64
64
  */
65
65
  truncateCacheTags(): Promise<number>;
66
- };
66
+ }