payloadcms-cloudflare-kv-plugin 1.0.1 → 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.
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,wBAAwB,EACxB,eAAe,EACf,WAAW,EACZ,MAAM,YAAY,CAAA;AAInB,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,IAAI,EACJ,MAAM,GACP,EAAE;IACD,IAAI,EAAE,eAAe,CAAA;IACrB,MAAM,EAAE,wBAAwB,CAAA;IAChC,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,YAAY,GAAG,SAAS,CAsB3B;AAED,wBAAsB,YAAY,CAAC,CAAC,EAAE,EACpC,GAAG,EACH,EAAE,GACH,EAAE;IACD,GAAG,EAAE,MAAM,CAAA;IACX,EAAE,EAAE,WAAW,CAAA;CAChB,GAAG,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,CAoBpB;AAED,wBAAsB,UAAU,CAAC,CAAC,EAAE,EAClC,IAAI,EACJ,GAAG,EACH,EAAE,EACF,GAAG,GACJ,EAAE;IACD,IAAI,EAAE,CAAC,CAAA;IACP,GAAG,EAAE,MAAM,CAAA;IACX,EAAE,EAAE,WAAW,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;CACZ,GAAG,OAAO,CAAC,IAAI,CAAC,CAMhB;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CAAC,EACxC,EAAE,EACF,OAAO,GACR,EAAE;IACD,EAAE,EAAE,WAAW,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4ChB"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,wBAAwB,EACxB,eAAe,EACf,WAAW,EACZ,MAAM,YAAY,CAAA;AAInB,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,IAAI,EACJ,MAAM,GACP,EAAE;IACD,IAAI,EAAE,eAAe,CAAA;IACrB,MAAM,EAAE,wBAAwB,CAAA;IAChC,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,YAAY,GAAG,SAAS,CAsB3B;AAED,wBAAsB,YAAY,CAAC,CAAC,EAAE,EACpC,GAAG,EACH,EAAE,GACH,EAAE;IACD,GAAG,EAAE,MAAM,CAAA;IACX,EAAE,EAAE,WAAW,CAAA;CAChB,GAAG,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,CAoBpB;AAED,wBAAsB,UAAU,CAAC,CAAC,EAAE,EAClC,IAAI,EACJ,GAAG,EACH,EAAE,EACF,GAAG,GACJ,EAAE;IACD,IAAI,EAAE,CAAC,CAAA;IACP,GAAG,EAAE,MAAM,CAAA;IACX,EAAE,EAAE,WAAW,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;CACZ,GAAG,OAAO,CAAC,IAAI,CAAC,CAMhB;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CAAC,EACxC,EAAE,EACF,OAAO,GACR,EAAE;IACD,EAAE,EAAE,WAAW,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDhB"}
package/dist/cache.js CHANGED
@@ -91,8 +91,12 @@ export async function setInCache({ data, key, kv, ttl }) {
91
91
  prefix
92
92
  });
93
93
  allKeys.push(...result.keys.map((k)=>k.name));
94
- complete = result.complete;
95
- cursor = result.cursor;
94
+ complete = result.list_complete;
95
+ if (!result.list_complete) {
96
+ cursor = result.cursor;
97
+ } else {
98
+ cursor = undefined;
99
+ }
96
100
  }
97
101
  // If pattern has wildcard, filter keys that match the full pattern
98
102
  // Otherwise, all keys with the prefix match
package/dist/cache.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cache.ts"],"sourcesContent":["import type {\n CacheOptions,\n CloudflareKVPluginConfig,\n DBOperationArgs,\n KVNamespace,\n} from './types.js'\n\nimport { DEFAULT_TTL } from './utils.js'\n\nexport function getCacheOptions({\n slug,\n args,\n config,\n}: {\n args: DBOperationArgs\n config: CloudflareKVPluginConfig\n slug: string\n}): CacheOptions | undefined {\n if (args.req?.context?.cache) {\n return args.req.context.cache\n }\n for (const [key, value] of Object.entries(config.collections ?? {})) {\n if (key === slug) {\n if (typeof value === 'boolean') {\n return { ttl: config.defaultCacheOptions?.ttl ?? DEFAULT_TTL }\n }\n return value\n }\n }\n for (const [key, value] of Object.entries(config.globals ?? {})) {\n if (key === slug) {\n if (typeof value === 'boolean') {\n return { ttl: config.defaultCacheOptions?.ttl ?? DEFAULT_TTL }\n }\n return value\n }\n }\n\n return undefined\n}\n\nexport async function getFromCache<T>({\n key,\n kv,\n}: {\n key: string\n kv: KVNamespace\n}): Promise<null | T> {\n try {\n const cached = await kv.get(key, { type: 'text' })\n if (cached) {\n try {\n return JSON.parse(cached) as T\n } catch (parseErr) {\n console.error('[CloudflareKVPlugin] Error parsing cached value for key:', key, parseErr)\n // If JSON parsing fails, delete the corrupted cache entry\n await kv.delete(key).catch(() => {\n // Ignore delete errors\n })\n return null\n }\n }\n return null\n } catch (err) {\n console.error('[CloudflareKVPlugin] Error reading from cache for key:', key, err)\n return null\n }\n}\n\nexport async function setInCache<T>({\n data,\n key,\n kv,\n ttl,\n}: {\n data: T\n key: string\n kv: KVNamespace\n ttl: number\n}): Promise<void> {\n try {\n await kv.put(key, JSON.stringify(data), { expirationTtl: ttl })\n } catch (err) {\n console.error('[CloudflareKVPlugin] Error writing to cache: ', err)\n }\n}\n\n/**\n * Invalidates cache entries matching a pattern\n * Since KV doesn't support pattern matching like Redis, we use list() with prefix\n * and filter keys that match the pattern\n *\n * Note: This operation can be slow for large namespaces as it requires listing\n * all keys with the matching prefix. Consider using more specific prefixes\n * or implementing a tag-based invalidation strategy for better performance.\n */\nexport async function invalidateByPattern({\n kv,\n pattern,\n}: {\n kv: KVNamespace\n pattern: string\n}): Promise<void> {\n try {\n // Convert Redis-style pattern (e.g., \"posts:*\") to KV prefix\n // Patterns like \"prefix:posts:*\" become prefix \"prefix:posts:\"\n const prefixMatch = pattern.match(/^(.+?):\\*$/)\n let prefix: string | undefined\n\n if (prefixMatch) {\n prefix = prefixMatch[1] + ':'\n } else if (pattern.endsWith('*')) {\n // Handle patterns like \"prefix*\" (without colon)\n prefix = pattern.replace(/\\*$/, '')\n } else {\n // No wildcard, treat as exact prefix match\n prefix = pattern\n }\n\n // List all keys with the prefix (handles pagination)\n const allKeys: string[] = []\n let cursor: string | undefined\n let complete = false\n\n while (!complete) {\n const result = await kv.list({ cursor, limit: 1000, prefix })\n allKeys.push(...result.keys.map((k) => k.name))\n complete = result.complete\n cursor = result.cursor\n }\n\n // If pattern has wildcard, filter keys that match the full pattern\n // Otherwise, all keys with the prefix match\n const patternRegex = pattern.includes('*')\n ? new RegExp('^' + pattern.replace(/\\*/g, '.*') + '$')\n : null\n\n const keysToDelete = patternRegex ? allKeys.filter((key) => patternRegex.test(key)) : allKeys\n\n // Delete all matching keys in parallel (with error handling)\n if (keysToDelete.length > 0) {\n await Promise.allSettled(keysToDelete.map((key) => kv.delete(key)))\n }\n } catch (err) {\n console.error('[CloudflareKVPlugin] Error invalidating cache for pattern:', pattern, err)\n }\n}\n"],"names":["DEFAULT_TTL","getCacheOptions","slug","args","config","req","context","cache","key","value","Object","entries","collections","ttl","defaultCacheOptions","globals","undefined","getFromCache","kv","cached","get","type","JSON","parse","parseErr","console","error","delete","catch","err","setInCache","data","put","stringify","expirationTtl","invalidateByPattern","pattern","prefixMatch","match","prefix","endsWith","replace","allKeys","cursor","complete","result","list","limit","push","keys","map","k","name","patternRegex","includes","RegExp","keysToDelete","filter","test","length","Promise","allSettled"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/cache.ts"],"sourcesContent":["import type {\n CacheOptions,\n CloudflareKVPluginConfig,\n DBOperationArgs,\n KVNamespace,\n} from './types.js'\n\nimport { DEFAULT_TTL } from './utils.js'\n\nexport function getCacheOptions({\n slug,\n args,\n config,\n}: {\n args: DBOperationArgs\n config: CloudflareKVPluginConfig\n slug: string\n}): CacheOptions | undefined {\n if (args.req?.context?.cache) {\n return args.req.context.cache\n }\n for (const [key, value] of Object.entries(config.collections ?? {})) {\n if (key === slug) {\n if (typeof value === 'boolean') {\n return { ttl: config.defaultCacheOptions?.ttl ?? DEFAULT_TTL }\n }\n return value\n }\n }\n for (const [key, value] of Object.entries(config.globals ?? {})) {\n if (key === slug) {\n if (typeof value === 'boolean') {\n return { ttl: config.defaultCacheOptions?.ttl ?? DEFAULT_TTL }\n }\n return value\n }\n }\n\n return undefined\n}\n\nexport async function getFromCache<T>({\n key,\n kv,\n}: {\n key: string\n kv: KVNamespace\n}): Promise<null | T> {\n try {\n const cached = await kv.get(key, { type: 'text' })\n if (cached) {\n try {\n return JSON.parse(cached) as T\n } catch (parseErr) {\n console.error('[CloudflareKVPlugin] Error parsing cached value for key:', key, parseErr)\n // If JSON parsing fails, delete the corrupted cache entry\n await kv.delete(key).catch(() => {\n // Ignore delete errors\n })\n return null\n }\n }\n return null\n } catch (err) {\n console.error('[CloudflareKVPlugin] Error reading from cache for key:', key, err)\n return null\n }\n}\n\nexport async function setInCache<T>({\n data,\n key,\n kv,\n ttl,\n}: {\n data: T\n key: string\n kv: KVNamespace\n ttl: number\n}): Promise<void> {\n try {\n await kv.put(key, JSON.stringify(data), { expirationTtl: ttl })\n } catch (err) {\n console.error('[CloudflareKVPlugin] Error writing to cache: ', err)\n }\n}\n\n/**\n * Invalidates cache entries matching a pattern\n * Since KV doesn't support pattern matching like Redis, we use list() with prefix\n * and filter keys that match the pattern\n *\n * Note: This operation can be slow for large namespaces as it requires listing\n * all keys with the matching prefix. Consider using more specific prefixes\n * or implementing a tag-based invalidation strategy for better performance.\n */\nexport async function invalidateByPattern({\n kv,\n pattern,\n}: {\n kv: KVNamespace\n pattern: string\n}): Promise<void> {\n try {\n // Convert Redis-style pattern (e.g., \"posts:*\") to KV prefix\n // Patterns like \"prefix:posts:*\" become prefix \"prefix:posts:\"\n const prefixMatch = pattern.match(/^(.+?):\\*$/)\n let prefix: string | undefined\n\n if (prefixMatch) {\n prefix = prefixMatch[1] + ':'\n } else if (pattern.endsWith('*')) {\n // Handle patterns like \"prefix*\" (without colon)\n prefix = pattern.replace(/\\*$/, '')\n } else {\n // No wildcard, treat as exact prefix match\n prefix = pattern\n }\n\n // List all keys with the prefix (handles pagination)\n const allKeys: string[] = []\n let cursor: string | undefined\n let complete = false\n\n while (!complete) {\n const result = await kv.list({ cursor, limit: 1000, prefix })\n allKeys.push(...result.keys.map((k) => k.name))\n complete = result.list_complete\n if (!result.list_complete) {\n cursor = result.cursor\n } else {\n cursor = undefined\n }\n }\n\n // If pattern has wildcard, filter keys that match the full pattern\n // Otherwise, all keys with the prefix match\n const patternRegex = pattern.includes('*')\n ? new RegExp('^' + pattern.replace(/\\*/g, '.*') + '$')\n : null\n\n const keysToDelete = patternRegex ? allKeys.filter((key) => patternRegex.test(key)) : allKeys\n\n // Delete all matching keys in parallel (with error handling)\n if (keysToDelete.length > 0) {\n await Promise.allSettled(keysToDelete.map((key) => kv.delete(key)))\n }\n } catch (err) {\n console.error('[CloudflareKVPlugin] Error invalidating cache for pattern:', pattern, err)\n }\n}\n"],"names":["DEFAULT_TTL","getCacheOptions","slug","args","config","req","context","cache","key","value","Object","entries","collections","ttl","defaultCacheOptions","globals","undefined","getFromCache","kv","cached","get","type","JSON","parse","parseErr","console","error","delete","catch","err","setInCache","data","put","stringify","expirationTtl","invalidateByPattern","pattern","prefixMatch","match","prefix","endsWith","replace","allKeys","cursor","complete","result","list","limit","push","keys","map","k","name","list_complete","patternRegex","includes","RegExp","keysToDelete","filter","test","length","Promise","allSettled"],"mappings":"AAOA,SAASA,WAAW,QAAQ,aAAY;AAExC,OAAO,SAASC,gBAAgB,EAC9BC,IAAI,EACJC,IAAI,EACJC,MAAM,EAKP;IACC,IAAID,KAAKE,GAAG,EAAEC,SAASC,OAAO;QAC5B,OAAOJ,KAAKE,GAAG,CAACC,OAAO,CAACC,KAAK;IAC/B;IACA,KAAK,MAAM,CAACC,KAAKC,MAAM,IAAIC,OAAOC,OAAO,CAACP,OAAOQ,WAAW,IAAI,CAAC,GAAI;QACnE,IAAIJ,QAAQN,MAAM;YAChB,IAAI,OAAOO,UAAU,WAAW;gBAC9B,OAAO;oBAAEI,KAAKT,OAAOU,mBAAmB,EAAED,OAAOb;gBAAY;YAC/D;YACA,OAAOS;QACT;IACF;IACA,KAAK,MAAM,CAACD,KAAKC,MAAM,IAAIC,OAAOC,OAAO,CAACP,OAAOW,OAAO,IAAI,CAAC,GAAI;QAC/D,IAAIP,QAAQN,MAAM;YAChB,IAAI,OAAOO,UAAU,WAAW;gBAC9B,OAAO;oBAAEI,KAAKT,OAAOU,mBAAmB,EAAED,OAAOb;gBAAY;YAC/D;YACA,OAAOS;QACT;IACF;IAEA,OAAOO;AACT;AAEA,OAAO,eAAeC,aAAgB,EACpCT,GAAG,EACHU,EAAE,EAIH;IACC,IAAI;QACF,MAAMC,SAAS,MAAMD,GAAGE,GAAG,CAACZ,KAAK;YAAEa,MAAM;QAAO;QAChD,IAAIF,QAAQ;YACV,IAAI;gBACF,OAAOG,KAAKC,KAAK,CAACJ;YACpB,EAAE,OAAOK,UAAU;gBACjBC,QAAQC,KAAK,CAAC,4DAA4DlB,KAAKgB;gBAC/E,0DAA0D;gBAC1D,MAAMN,GAAGS,MAAM,CAACnB,KAAKoB,KAAK,CAAC;gBACzB,uBAAuB;gBACzB;gBACA,OAAO;YACT;QACF;QACA,OAAO;IACT,EAAE,OAAOC,KAAK;QACZJ,QAAQC,KAAK,CAAC,0DAA0DlB,KAAKqB;QAC7E,OAAO;IACT;AACF;AAEA,OAAO,eAAeC,WAAc,EAClCC,IAAI,EACJvB,GAAG,EACHU,EAAE,EACFL,GAAG,EAMJ;IACC,IAAI;QACF,MAAMK,GAAGc,GAAG,CAACxB,KAAKc,KAAKW,SAAS,CAACF,OAAO;YAAEG,eAAerB;QAAI;IAC/D,EAAE,OAAOgB,KAAK;QACZJ,QAAQC,KAAK,CAAC,iDAAiDG;IACjE;AACF;AAEA;;;;;;;;CAQC,GACD,OAAO,eAAeM,oBAAoB,EACxCjB,EAAE,EACFkB,OAAO,EAIR;IACC,IAAI;QACF,6DAA6D;QAC7D,+DAA+D;QAC/D,MAAMC,cAAcD,QAAQE,KAAK,CAAC;QAClC,IAAIC;QAEJ,IAAIF,aAAa;YACfE,SAASF,WAAW,CAAC,EAAE,GAAG;QAC5B,OAAO,IAAID,QAAQI,QAAQ,CAAC,MAAM;YAChC,iDAAiD;YACjDD,SAASH,QAAQK,OAAO,CAAC,OAAO;QAClC,OAAO;YACL,2CAA2C;YAC3CF,SAASH;QACX;QAEA,qDAAqD;QACrD,MAAMM,UAAoB,EAAE;QAC5B,IAAIC;QACJ,IAAIC,WAAW;QAEf,MAAO,CAACA,SAAU;YAChB,MAAMC,SAAS,MAAM3B,GAAG4B,IAAI,CAAC;gBAAEH;gBAAQI,OAAO;gBAAMR;YAAO;YAC3DG,QAAQM,IAAI,IAAIH,OAAOI,IAAI,CAACC,GAAG,CAAC,CAACC,IAAMA,EAAEC,IAAI;YAC7CR,WAAWC,OAAOQ,aAAa;YAC/B,IAAI,CAACR,OAAOQ,aAAa,EAAE;gBACzBV,SAASE,OAAOF,MAAM;YACxB,OAAO;gBACLA,SAAS3B;YACX;QACF;QAEA,mEAAmE;QACnE,4CAA4C;QAC5C,MAAMsC,eAAelB,QAAQmB,QAAQ,CAAC,OAClC,IAAIC,OAAO,MAAMpB,QAAQK,OAAO,CAAC,OAAO,QAAQ,OAChD;QAEJ,MAAMgB,eAAeH,eAAeZ,QAAQgB,MAAM,CAAC,CAAClD,MAAQ8C,aAAaK,IAAI,CAACnD,QAAQkC;QAEtF,6DAA6D;QAC7D,IAAIe,aAAaG,MAAM,GAAG,GAAG;YAC3B,MAAMC,QAAQC,UAAU,CAACL,aAAaP,GAAG,CAAC,CAAC1C,MAAQU,GAAGS,MAAM,CAACnB;QAC/D;IACF,EAAE,OAAOqB,KAAK;QACZJ,QAAQC,KAAK,CAAC,8DAA8DU,SAASP;IACvF;AACF"}
package/dist/types.d.ts CHANGED
@@ -5,8 +5,11 @@ export interface CollectionCacheOptions extends CacheOptions {
5
5
  }
6
6
  /**
7
7
  * Cloudflare KV Namespace interface
8
- * This matches the KVNamespace type from @cloudflare/workers-types
8
+ * This matches the KVNamespace type from Cloudflare Workers runtime
9
9
  * Reference: https://developers.cloudflare.com/workers/runtime-apis/kv/
10
+ *
11
+ * This interface is compatible with the actual Cloudflare Workers KVNamespace type
12
+ * which uses `list_complete` instead of `complete` in the list() return type.
10
13
  */
11
14
  export interface KVNamespace {
12
15
  /**
@@ -27,19 +30,31 @@ export interface KVNamespace {
27
30
  * Lists keys in the KV namespace
28
31
  * @param options Optional parameters for listing (prefix, limit, cursor)
29
32
  * @returns A promise resolving to an object containing keys and pagination info
33
+ *
34
+ * Note: The actual Cloudflare Workers type returns `list_complete` instead of `complete`,
35
+ * but we provide a compatible interface that works with both.
30
36
  */
31
37
  list(options?: {
32
38
  cursor?: string;
33
39
  limit?: number;
34
- prefix?: string;
40
+ prefix?: null | string;
35
41
  }): Promise<{
36
- complete: boolean;
37
- cursor?: string;
42
+ cacheStatus: null | string;
43
+ cursor: string;
44
+ keys: Array<{
45
+ expiration?: number;
46
+ metadata?: unknown;
47
+ name: string;
48
+ }>;
49
+ list_complete: false;
50
+ } | {
51
+ cacheStatus: null | string;
38
52
  keys: Array<{
39
53
  expiration?: number;
40
54
  metadata?: unknown;
41
55
  name: string;
42
56
  }>;
57
+ list_complete: true;
43
58
  }>;
44
59
  /**
45
60
  * Stores a value in the KV namespace
@@ -52,6 +67,7 @@ export interface KVNamespace {
52
67
  put(key: string, value: string, options?: {
53
68
  expiration?: number;
54
69
  expirationTtl?: number;
70
+ metadata?: unknown;
55
71
  }): Promise<void>;
56
72
  }
57
73
  export type CloudflareKVPluginConfig = {
@@ -74,6 +90,8 @@ export type CloudflareKVPluginConfig = {
74
90
  /**
75
91
  * Cloudflare KV Namespace binding
76
92
  * This should be the KV namespace instance from your Cloudflare Worker environment
93
+ * Accepts the actual Cloudflare Workers KVNamespace type (e.g., KVNamespace<string>)
94
+ * or our compatible KVNamespace interface
77
95
  */
78
96
  kv: KVNamespace;
79
97
  };
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,SAAS,EACT,sBAAsB,EACtB,QAAQ,EACR,cAAc,EACd,WAAW,EACX,UAAU,EACV,eAAe,EAChB,MAAM,SAAS,CAAA;AAEhB,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,sBAAsB,GACtB,QAAQ,GACR,cAAc,GACd,WAAW,GACX,eAAe,CAAA;AAEnB,MAAM,WAAW,sBAAuB,SAAQ,YAAY;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAElC;;;;;OAKG;IACH,GAAG,CACD,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,aAAa,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAA;KAAE,GAC9D,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAAA;IAEzB;;;;OAIG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAC5E,QAAQ,EAAE,OAAO,CAAA;QACjB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,IAAI,EAAE,KAAK,CAAC;YAAE,UAAU,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KACvE,CAAC,CAAA;IAEF;;;;;;;OAOG;IACH,GAAG,CACD,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GACxD,OAAO,CAAC,IAAI,CAAC,CAAA;CACjB;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,sBAAsB,GAAG,IAAI,CAAC,CAAC,CAAA;IAC5E,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,mBAAmB,CAAC,EAAE;QACpB,WAAW,CAAC,EAAE,CAAC,EACb,IAAI,EACJ,SAAS,EACT,QAAQ,GACT,EAAE;YACD,IAAI,EAAE,eAAe,CAAA;YACrB,SAAS,EAAE,MAAM,CAAA;YACjB,QAAQ,EAAE,OAAO,CAAA;SAClB,KAAK,MAAM,CAAA;QACZ,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,QAAQ,CAAC,EAAE,OAAO,CAAA;KACnB,CAAA;IACD,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,sBAAsB,GAAG,IAAI,CAAC,CAAC,CAAA;IACpE;;;OAGG;IACH,EAAE,EAAE,WAAW,CAAA;CAChB,CAAA;AAED,MAAM,WAAW,YAAY;IAC3B,sDAAsD;IACtD,GAAG,CAAC,EAAE,MAAM,CAAA;IAEZ,4DAA4D;IAC5D,IAAI,CAAC,EAAE,OAAO,CAAA;IAEd,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IAEf,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAiB,cAAc;QAC7B,KAAK,CAAC,EAAE,YAAY,CAAA;KACrB;CACF"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type {\n CollectionSlug,\n CountArgs,\n CountGlobalVersionArgs,\n FindArgs,\n FindGlobalArgs,\n FindOneArgs,\n GlobalSlug,\n QueryDraftsArgs,\n} from 'payload'\n\nexport type DBOperationArgs =\n | CountArgs\n | CountGlobalVersionArgs\n | FindArgs\n | FindGlobalArgs\n | FindOneArgs\n | QueryDraftsArgs\n\nexport interface CollectionCacheOptions extends CacheOptions {\n versions?: boolean\n}\n\n/**\n * Cloudflare KV Namespace interface\n * This matches the KVNamespace type from @cloudflare/workers-types\n * Reference: https://developers.cloudflare.com/workers/runtime-apis/kv/\n */\nexport interface KVNamespace {\n /**\n * Deletes a key-value pair from the KV namespace\n * @param key The key to delete\n */\n delete(key: string): Promise<void>\n\n /**\n * Retrieves a value from the KV namespace\n * @param key The key to retrieve\n * @param options Optional type specification for the return value\n * @returns The value as a string (or parsed based on type), or null if not found\n */\n get(\n key: string,\n options?: { type?: 'arrayBuffer' | 'json' | 'stream' | 'text' },\n ): Promise<null | string>\n\n /**\n * Lists keys in the KV namespace\n * @param options Optional parameters for listing (prefix, limit, cursor)\n * @returns A promise resolving to an object containing keys and pagination info\n */\n list(options?: { cursor?: string; limit?: number; prefix?: string }): Promise<{\n complete: boolean\n cursor?: string\n keys: Array<{ expiration?: number; metadata?: unknown; name: string }>\n }>\n\n /**\n * Stores a value in the KV namespace\n * @param key The key to store\n * @param value The value to store (must be a string)\n * @param options Optional expiration settings\n * @param options.expirationTtl Time to live in seconds from now\n * @param options.expiration Unix timestamp (in seconds) when the key should expire\n */\n put(\n key: string,\n value: string,\n options?: { expiration?: number; expirationTtl?: number },\n ): Promise<void>\n}\n\nexport type CloudflareKVPluginConfig = {\n /**\n * List of collections to add KV caching\n */\n collections?: Partial<Record<CollectionSlug, CollectionCacheOptions | true>>\n debug?: boolean\n defaultCacheOptions?: {\n generateKey?: ({\n args,\n operation,\n versions,\n }: {\n args: DBOperationArgs\n operation: string\n versions: boolean\n }) => string\n keyPrefix?: string\n ttl?: number\n versions?: boolean\n }\n globals?: Partial<Record<GlobalSlug, CollectionCacheOptions | true>>\n /**\n * Cloudflare KV Namespace binding\n * This should be the KV namespace instance from your Cloudflare Worker environment\n */\n kv: KVNamespace\n}\n\nexport interface CacheOptions {\n /** Custom cache key (overrides auto-generated key) */\n key?: string\n\n /** Skip cache for this query and always hit the database */\n skip?: boolean\n\n /** Cache tags for grouped invalidation */\n tags?: string[]\n\n /** Custom TTL (time to live) in seconds for this query */\n ttl?: number\n}\n\ndeclare module 'payload' {\n export interface RequestContext {\n cache?: CacheOptions\n }\n}\n"],"names":[],"mappings":"AAoGA,WAYC"}
1
+ {"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type {\n CollectionSlug,\n CountArgs,\n CountGlobalVersionArgs,\n FindArgs,\n FindGlobalArgs,\n FindOneArgs,\n GlobalSlug,\n QueryDraftsArgs,\n} from 'payload'\n\nexport type DBOperationArgs =\n | CountArgs\n | CountGlobalVersionArgs\n | FindArgs\n | FindGlobalArgs\n | FindOneArgs\n | QueryDraftsArgs\n\nexport interface CollectionCacheOptions extends CacheOptions {\n versions?: boolean\n}\n\n/**\n * Cloudflare KV Namespace interface\n * This matches the KVNamespace type from Cloudflare Workers runtime\n * Reference: https://developers.cloudflare.com/workers/runtime-apis/kv/\n *\n * This interface is compatible with the actual Cloudflare Workers KVNamespace type\n * which uses `list_complete` instead of `complete` in the list() return type.\n */\nexport interface KVNamespace {\n /**\n * Deletes a key-value pair from the KV namespace\n * @param key The key to delete\n */\n delete(key: string): Promise<void>\n\n /**\n * Retrieves a value from the KV namespace\n * @param key The key to retrieve\n * @param options Optional type specification for the return value\n * @returns The value as a string (or parsed based on type), or null if not found\n */\n get(\n key: string,\n options?: { type?: 'arrayBuffer' | 'json' | 'stream' | 'text' },\n ): Promise<null | string>\n\n /**\n * Lists keys in the KV namespace\n * @param options Optional parameters for listing (prefix, limit, cursor)\n * @returns A promise resolving to an object containing keys and pagination info\n *\n * Note: The actual Cloudflare Workers type returns `list_complete` instead of `complete`,\n * but we provide a compatible interface that works with both.\n */\n list(options?: { cursor?: string; limit?: number; prefix?: null | string }): Promise<\n | {\n cacheStatus: null | string\n cursor: string\n keys: Array<{ expiration?: number; metadata?: unknown; name: string }>\n list_complete: false\n }\n | {\n cacheStatus: null | string\n keys: Array<{ expiration?: number; metadata?: unknown; name: string }>\n list_complete: true\n }\n >\n\n /**\n * Stores a value in the KV namespace\n * @param key The key to store\n * @param value The value to store (must be a string)\n * @param options Optional expiration settings\n * @param options.expirationTtl Time to live in seconds from now\n * @param options.expiration Unix timestamp (in seconds) when the key should expire\n */\n put(\n key: string,\n value: string,\n options?: { expiration?: number; expirationTtl?: number; metadata?: unknown },\n ): Promise<void>\n}\n\nexport type CloudflareKVPluginConfig = {\n /**\n * List of collections to add KV caching\n */\n collections?: Partial<Record<CollectionSlug, CollectionCacheOptions | true>>\n debug?: boolean\n defaultCacheOptions?: {\n generateKey?: ({\n args,\n operation,\n versions,\n }: {\n args: DBOperationArgs\n operation: string\n versions: boolean\n }) => string\n keyPrefix?: string\n ttl?: number\n versions?: boolean\n }\n globals?: Partial<Record<GlobalSlug, CollectionCacheOptions | true>>\n /**\n * Cloudflare KV Namespace binding\n * This should be the KV namespace instance from your Cloudflare Worker environment\n * Accepts the actual Cloudflare Workers KVNamespace type (e.g., KVNamespace<string>)\n * or our compatible KVNamespace interface\n */\n kv: KVNamespace\n}\n\nexport interface CacheOptions {\n /** Custom cache key (overrides auto-generated key) */\n key?: string\n\n /** Skip cache for this query and always hit the database */\n skip?: boolean\n\n /** Cache tags for grouped invalidation */\n tags?: string[]\n\n /** Custom TTL (time to live) in seconds for this query */\n ttl?: number\n}\n\ndeclare module 'payload' {\n export interface RequestContext {\n cache?: CacheOptions\n }\n}\n"],"names":[],"mappings":"AAoHA,WAYC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payloadcms-cloudflare-kv-plugin",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Cloudflare KV Plugin for PayloadCMS v3",
5
5
  "license": "MIT",
6
6
  "type": "module",