payloadcms-cloudflare-kv-plugin 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +484 -0
- package/dist/adapter.d.ts +8 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +682 -0
- package/dist/adapter.js.map +1 -0
- package/dist/cache.d.ts +30 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +110 -0
- package/dist/cache.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +95 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +36 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +94 -0
- package/dist/utils.js.map +1 -0
- package/package.json +108 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Isaiah
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
# PayloadCMS Cloudflare KV Plugin
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/payloadcms-cloudflare-kv-plugin)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
A transparent Cloudflare KV caching layer plugin for Payload CMS v3 that automatically caches database queries to improve performance using Cloudflare's globally distributed key-value store.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **Automatic Query Caching** - Transparently caches all read operations (find, findOne, count, etc.)
|
|
11
|
+
- **Smart Invalidation** - Automatically invalidates cache on write operations (create, update, delete)
|
|
12
|
+
- **Flexible Configuration** - Enable caching per collection or globally with custom TTL
|
|
13
|
+
- **Per-Request Override** - Control cache behavior on individual requests
|
|
14
|
+
- **Custom Cache Keys** - Generate custom cache keys based on your needs
|
|
15
|
+
- **Pattern-Based Invalidation** - Invalidate related cache entries using KV prefix matching
|
|
16
|
+
- **Debug Mode** - Optional logging for cache hits, misses, and invalidations
|
|
17
|
+
- **Zero Breaking Changes** - Works seamlessly with existing Payload applications
|
|
18
|
+
- **Global Distribution** - Leverages Cloudflare's edge network for low-latency reads
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install payloadcms-cloudflare-kv-plugin
|
|
24
|
+
# or
|
|
25
|
+
yarn add payloadcms-cloudflare-kv-plugin
|
|
26
|
+
# or
|
|
27
|
+
pnpm add payloadcms-cloudflare-kv-plugin
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Requirements
|
|
31
|
+
|
|
32
|
+
- Payload CMS v3.37.0 or higher
|
|
33
|
+
- Node.js 18.20.2+ or 20.9.0+
|
|
34
|
+
- Cloudflare Workers KV namespace
|
|
35
|
+
- Cloudflare Workers environment (for production) or local development setup
|
|
36
|
+
|
|
37
|
+
## Quick Start
|
|
38
|
+
|
|
39
|
+
### Basic Setup
|
|
40
|
+
|
|
41
|
+
First, create a KV namespace in your Cloudflare dashboard or using Wrangler:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
wrangler kv:namespace create "CACHE"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
This will output a namespace ID. Add it to your `wrangler.toml`:
|
|
48
|
+
|
|
49
|
+
```toml
|
|
50
|
+
[[kv_namespaces]]
|
|
51
|
+
binding = "CACHE"
|
|
52
|
+
id = "your-namespace-id"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Then configure the plugin in your Payload config:
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
import { buildConfig } from 'payload'
|
|
59
|
+
import { cloudflareKVCache } from 'payloadcms-cloudflare-kv-plugin'
|
|
60
|
+
|
|
61
|
+
export default buildConfig({
|
|
62
|
+
plugins: [
|
|
63
|
+
cloudflareKVCache({
|
|
64
|
+
// Pass the KV namespace from your Cloudflare Worker environment
|
|
65
|
+
kv: env.CACHE, // or your KV namespace binding
|
|
66
|
+
// Enable caching for specific collections
|
|
67
|
+
collections: {
|
|
68
|
+
posts: true,
|
|
69
|
+
articles: true,
|
|
70
|
+
},
|
|
71
|
+
}),
|
|
72
|
+
],
|
|
73
|
+
// ... rest of your config
|
|
74
|
+
})
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Using in Cloudflare Workers
|
|
78
|
+
|
|
79
|
+
When using in a Cloudflare Worker, pass the KV namespace from the environment:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { cloudflareKVCache } from 'payloadcms-cloudflare-kv-plugin'
|
|
83
|
+
|
|
84
|
+
export default {
|
|
85
|
+
async fetch(request: Request, env: Env): Promise<Response> {
|
|
86
|
+
const config = buildConfig({
|
|
87
|
+
plugins: [
|
|
88
|
+
cloudflareKVCache({
|
|
89
|
+
kv: env.CACHE, // KV namespace from Worker environment
|
|
90
|
+
collections: {
|
|
91
|
+
posts: true,
|
|
92
|
+
},
|
|
93
|
+
}),
|
|
94
|
+
],
|
|
95
|
+
// ... rest of config
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
// ... your handler
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Configuration
|
|
104
|
+
|
|
105
|
+
### Plugin Options
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
type CloudflareKVPluginConfig = {
|
|
109
|
+
// Cloudflare KV Namespace binding (required)
|
|
110
|
+
kv: KVNamespace
|
|
111
|
+
|
|
112
|
+
// Collections to cache
|
|
113
|
+
collections?: Partial<Record<CollectionSlug, CacheOptions | true>>
|
|
114
|
+
|
|
115
|
+
// Globals to cache
|
|
116
|
+
globals?: Partial<Record<GlobalSlug, CacheOptions | true>>
|
|
117
|
+
|
|
118
|
+
// Enable debug logging
|
|
119
|
+
debug?: boolean
|
|
120
|
+
|
|
121
|
+
// Default cache behavior
|
|
122
|
+
defaultCacheOptions?: {
|
|
123
|
+
generateKey?: (operation: string, args: DBOperationArgs) => string
|
|
124
|
+
keyPrefix?: string
|
|
125
|
+
ttl?: number // in seconds, default: 300 (5 minutes)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Cache Options
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
type CacheOptions = {
|
|
134
|
+
key?: string // Custom cache key override
|
|
135
|
+
skip?: boolean // Skip cache for this collection/query
|
|
136
|
+
tags?: string[] // Tags for grouped invalidation (future feature)
|
|
137
|
+
ttl?: number // Time-to-live in seconds
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Advanced Configuration
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
cloudflareKVCache({
|
|
145
|
+
kv: env.CACHE,
|
|
146
|
+
|
|
147
|
+
// Configure collections with custom TTL
|
|
148
|
+
collections: {
|
|
149
|
+
posts: {
|
|
150
|
+
ttl: 600, // Cache posts for 10 minutes
|
|
151
|
+
skip: false,
|
|
152
|
+
},
|
|
153
|
+
articles: {
|
|
154
|
+
ttl: 1800, // Cache articles for 30 minutes
|
|
155
|
+
},
|
|
156
|
+
users: true, // Use default TTL (5 minutes)
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
// Cache global configurations
|
|
160
|
+
globals: {
|
|
161
|
+
settings: true,
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
// Custom default options
|
|
165
|
+
defaultCacheOptions: {
|
|
166
|
+
keyPrefix: 'myapp',
|
|
167
|
+
ttl: 300,
|
|
168
|
+
generateKey: (operation, args) => {
|
|
169
|
+
// Custom key generation logic
|
|
170
|
+
const { slug, where, locale } = args
|
|
171
|
+
return `${slug}:${operation}:${locale || 'default'}:${JSON.stringify(where)}`
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
// Enable debug logging
|
|
176
|
+
debug: true,
|
|
177
|
+
})
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Usage
|
|
181
|
+
|
|
182
|
+
### Per-Request Cache Control
|
|
183
|
+
|
|
184
|
+
Override cache behavior for individual requests:
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
// Skip cache for a specific query
|
|
188
|
+
const freshPosts = await payload.find({
|
|
189
|
+
collection: 'posts',
|
|
190
|
+
req: {
|
|
191
|
+
context: {
|
|
192
|
+
cache: {
|
|
193
|
+
skip: true, // Bypass cache, always hit database
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
// Custom TTL for a specific query
|
|
200
|
+
const shortLivedPosts = await payload.find({
|
|
201
|
+
collection: 'posts',
|
|
202
|
+
req: {
|
|
203
|
+
context: {
|
|
204
|
+
cache: {
|
|
205
|
+
ttl: 60, // Cache for 1 minute only
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
// Custom cache key
|
|
212
|
+
const customCachedPosts = await payload.find({
|
|
213
|
+
collection: 'posts',
|
|
214
|
+
req: {
|
|
215
|
+
context: {
|
|
216
|
+
cache: {
|
|
217
|
+
key: 'posts:featured',
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
})
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Cached Operations
|
|
225
|
+
|
|
226
|
+
The following database operations are automatically cached:
|
|
227
|
+
|
|
228
|
+
**Read Operations** (cached before hitting database):
|
|
229
|
+
|
|
230
|
+
- `find` - Query collections with pagination
|
|
231
|
+
- `findOne` - Query single document by ID
|
|
232
|
+
- `findGlobal` - Query global configurations
|
|
233
|
+
- `findGlobalVersions` - Query global version history
|
|
234
|
+
- `count` - Count documents
|
|
235
|
+
- `countVersions` - Count document versions
|
|
236
|
+
- `countGlobalVersions` - Count global versions
|
|
237
|
+
- `queryDrafts` - Query draft documents
|
|
238
|
+
|
|
239
|
+
**Write Operations** (invalidate cache after database update):
|
|
240
|
+
|
|
241
|
+
- `create` - Create new document
|
|
242
|
+
- `createMany` - Batch create
|
|
243
|
+
- `updateOne` - Update single document
|
|
244
|
+
- `updateMany` - Batch update
|
|
245
|
+
- `deleteOne` - Delete single document
|
|
246
|
+
- `deleteMany` - Batch delete
|
|
247
|
+
- `upsert` - Create or update
|
|
248
|
+
- `updateGlobal` - Update global config
|
|
249
|
+
- `updateGlobalVersion` - Update global version
|
|
250
|
+
- `deleteVersions` - Delete document versions
|
|
251
|
+
|
|
252
|
+
## How It Works
|
|
253
|
+
|
|
254
|
+
### Cache Key Generation
|
|
255
|
+
|
|
256
|
+
By default, cache keys are generated using MD5 hashing:
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
[prefix]:[slug]:[operation]:[md5-hash]
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
The hash includes: `{ slug, locale, operation, where }`
|
|
263
|
+
|
|
264
|
+
Example keys:
|
|
265
|
+
|
|
266
|
+
```
|
|
267
|
+
posts:find:a1b2c3d4e5f6g7h8
|
|
268
|
+
myapp:articles:count:x9y8z7w6v5u4t3s2
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Cache Flow
|
|
272
|
+
|
|
273
|
+
**Read Operations:**
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
Request → Check cache config → Check skip flag
|
|
277
|
+
↓ (cache enabled)
|
|
278
|
+
Check KV → HIT: Return cached → MISS: Hit DB → Store in KV → Return
|
|
279
|
+
↓ (cache disabled/skipped)
|
|
280
|
+
Hit DB directly
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
**Write Operations:**
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
Request → Execute on DB → Get cache config → Check skip flag
|
|
287
|
+
↓ (cache enabled)
|
|
288
|
+
Invalidate pattern → Return result
|
|
289
|
+
↓ (cache disabled/skipped)
|
|
290
|
+
Return result directly
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Automatic Invalidation
|
|
294
|
+
|
|
295
|
+
When data changes, the plugin automatically invalidates related cache entries using prefix matching:
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
// Creating a post invalidates all post queries
|
|
299
|
+
await payload.create({
|
|
300
|
+
collection: 'posts',
|
|
301
|
+
data: { title: 'New Post' },
|
|
302
|
+
})
|
|
303
|
+
// Invalidates: posts:*, myapp:*:posts:*, etc.
|
|
304
|
+
|
|
305
|
+
// Updating an article invalidates all article queries
|
|
306
|
+
await payload.update({
|
|
307
|
+
collection: 'articles',
|
|
308
|
+
id: '123',
|
|
309
|
+
data: { title: 'Updated' },
|
|
310
|
+
})
|
|
311
|
+
// Invalidates: articles:*, myapp:*:articles:*, etc.
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**Note:** Cloudflare KV uses prefix-based listing instead of pattern matching. The plugin converts patterns like `posts:*` to prefix queries and filters matching keys.
|
|
315
|
+
|
|
316
|
+
## Debug Mode
|
|
317
|
+
|
|
318
|
+
Enable debug logging to monitor cache behavior:
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
cloudflareKVCache({
|
|
322
|
+
kv: env.CACHE,
|
|
323
|
+
collections: { posts: true },
|
|
324
|
+
debug: true,
|
|
325
|
+
})
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Console output:
|
|
329
|
+
|
|
330
|
+
```
|
|
331
|
+
[CloudflareKVPlugin] [find] [posts] Cache HIT
|
|
332
|
+
[CloudflareKVPlugin] [find] [articles] Cache MISS
|
|
333
|
+
[CloudflareKVPlugin] [create] [posts] Invalidating pattern: posts:*
|
|
334
|
+
[CloudflareKVPlugin] [update] [posts] Cache SKIP (per-request)
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## TypeScript Support
|
|
338
|
+
|
|
339
|
+
The plugin includes full TypeScript definitions and extends Payload's `RequestContext` type:
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
declare module 'payload' {
|
|
343
|
+
export interface RequestContext {
|
|
344
|
+
cache?: {
|
|
345
|
+
key?: string
|
|
346
|
+
skip?: boolean
|
|
347
|
+
tags?: string[]
|
|
348
|
+
ttl?: number
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
## Performance Considerations
|
|
355
|
+
|
|
356
|
+
- **Default TTL**: 5 minutes (300 seconds)
|
|
357
|
+
- **Prefix Matching**: Uses KV `list()` with prefix for invalidation (may be slower with large keyspaces)
|
|
358
|
+
- **Silent Failures**: Cache errors don't break database queries
|
|
359
|
+
- **Memory**: KV has a 25 MB value size limit per key
|
|
360
|
+
- **Expiration**: KV automatically removes expired keys
|
|
361
|
+
- **Eventual Consistency**: KV is eventually consistent - writes may take a few seconds to propagate globally
|
|
362
|
+
- **Read Performance**: KV is optimized for high-read, low-write workloads
|
|
363
|
+
|
|
364
|
+
## Cloudflare KV Limitations
|
|
365
|
+
|
|
366
|
+
- **Eventual Consistency**: KV is eventually consistent. Writes may take a few seconds to be visible globally
|
|
367
|
+
- **No Transactions**: KV doesn't support transactions or atomic operations
|
|
368
|
+
- **Value Size Limit**: Maximum 25 MB per value
|
|
369
|
+
- **List Performance**: Listing keys with prefixes can be slower with very large keyspaces
|
|
370
|
+
- **No Pattern Matching**: Uses prefix-based listing instead of Redis-style pattern matching
|
|
371
|
+
|
|
372
|
+
## Development
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
# Install dependencies
|
|
376
|
+
pnpm install
|
|
377
|
+
|
|
378
|
+
# Run development server
|
|
379
|
+
pnpm dev
|
|
380
|
+
|
|
381
|
+
# Run tests
|
|
382
|
+
pnpm test
|
|
383
|
+
|
|
384
|
+
# Build plugin
|
|
385
|
+
pnpm build
|
|
386
|
+
|
|
387
|
+
# Lint code
|
|
388
|
+
pnpm lint
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
## Examples
|
|
392
|
+
|
|
393
|
+
### E-commerce Site
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
cloudflareKVCache({
|
|
397
|
+
kv: env.CACHE,
|
|
398
|
+
collections: {
|
|
399
|
+
products: { ttl: 3600 }, // Cache products for 1 hour
|
|
400
|
+
categories: { ttl: 7200 }, // Cache categories for 2 hours
|
|
401
|
+
orders: { skip: true }, // Never cache orders
|
|
402
|
+
customers: { ttl: 600 }, // Cache customers for 10 minutes
|
|
403
|
+
},
|
|
404
|
+
globals: {
|
|
405
|
+
siteSettings: { ttl: 86400 }, // Cache site settings for 24 hours
|
|
406
|
+
},
|
|
407
|
+
})
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### Blog Platform
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
cloudflareKVCache({
|
|
414
|
+
kv: env.CACHE,
|
|
415
|
+
collections: {
|
|
416
|
+
posts: { ttl: 1800 }, // Cache posts for 30 minutes
|
|
417
|
+
authors: { ttl: 3600 }, // Cache authors for 1 hour
|
|
418
|
+
comments: { ttl: 300 }, // Cache comments for 5 minutes
|
|
419
|
+
},
|
|
420
|
+
defaultCacheOptions: {
|
|
421
|
+
keyPrefix: 'blog',
|
|
422
|
+
ttl: 600,
|
|
423
|
+
},
|
|
424
|
+
debug: process.env.NODE_ENV === 'development',
|
|
425
|
+
})
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
## Troubleshooting
|
|
429
|
+
|
|
430
|
+
### KV Namespace Not Accessible
|
|
431
|
+
|
|
432
|
+
```typescript
|
|
433
|
+
// Verify KV namespace is properly bound
|
|
434
|
+
// In wrangler.toml:
|
|
435
|
+
[[kv_namespaces]]
|
|
436
|
+
binding = "CACHE"
|
|
437
|
+
id = "your-namespace-id"
|
|
438
|
+
|
|
439
|
+
// In your code:
|
|
440
|
+
cloudflareKVCache({
|
|
441
|
+
kv: env.CACHE, // Make sure this matches the binding name
|
|
442
|
+
// ...
|
|
443
|
+
})
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### Cache Not Working
|
|
447
|
+
|
|
448
|
+
1. Enable debug mode to see cache behavior
|
|
449
|
+
2. Verify collection/global is configured for caching
|
|
450
|
+
3. Check if `skip: true` is set
|
|
451
|
+
4. Ensure KV namespace is properly bound and accessible
|
|
452
|
+
5. Check Cloudflare Workers logs for errors
|
|
453
|
+
|
|
454
|
+
### High Memory Usage
|
|
455
|
+
|
|
456
|
+
1. Reduce TTL values
|
|
457
|
+
2. Be selective about which collections to cache
|
|
458
|
+
3. Monitor KV usage in Cloudflare dashboard
|
|
459
|
+
4. Consider using KV max keys limits
|
|
460
|
+
|
|
461
|
+
### Eventual Consistency Issues
|
|
462
|
+
|
|
463
|
+
If you need immediate consistency:
|
|
464
|
+
- Use `skip: true` for critical queries
|
|
465
|
+
- Implement cache warming strategies
|
|
466
|
+
- Consider using Cloudflare Durable Objects for strongly consistent data
|
|
467
|
+
|
|
468
|
+
## Contributing
|
|
469
|
+
|
|
470
|
+
Contributions are welcome! Please see the [GitHub repository](https://github.com/thejemish/payloadcms-cloudflare-kv-plugin) for issues and pull requests.
|
|
471
|
+
|
|
472
|
+
> **Note:** This repository was originally created for a Redis plugin but has been converted to use Cloudflare KV. The repository name may be updated in the future.
|
|
473
|
+
|
|
474
|
+
## License
|
|
475
|
+
|
|
476
|
+
MIT
|
|
477
|
+
|
|
478
|
+
## Links
|
|
479
|
+
|
|
480
|
+
- [GitHub Repository](https://github.com/thejemish/payloadcms-cloudflare-kv-plugin)
|
|
481
|
+
- [NPM Package](https://www.npmjs.com/package/payloadcms-cloudflare-kv-plugin)
|
|
482
|
+
- [Payload CMS Documentation](https://payloadcms.com/docs)
|
|
483
|
+
- [Cloudflare KV Documentation](https://developers.cloudflare.com/kv/)
|
|
484
|
+
- [Cloudflare Workers Documentation](https://developers.cloudflare.com/workers/)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DatabaseAdapter } from 'payload';
|
|
2
|
+
import type { CloudflareKVPluginConfig, KVNamespace } from './types.js';
|
|
3
|
+
export declare function dbAdapterWithCache({ baseAdapter, kv, config, }: {
|
|
4
|
+
baseAdapter: DatabaseAdapter;
|
|
5
|
+
config: CloudflareKVPluginConfig;
|
|
6
|
+
kv: KVNamespace;
|
|
7
|
+
}): DatabaseAdapter;
|
|
8
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EAShB,MAAM,SAAS,CAAA;AAEhB,OAAO,KAAK,EAAE,wBAAwB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAYvE,wBAAgB,kBAAkB,CAAC,EACjC,WAAW,EACX,EAAE,EACF,MAA6E,GAC9E,EAAE;IACD,WAAW,EAAE,eAAe,CAAA;IAC5B,MAAM,EAAE,wBAAwB,CAAA;IAChC,EAAE,EAAE,WAAW,CAAA;CAChB,GAAG,eAAe,CA8TlB"}
|