payload-smart-cache 1.1.10 → 1.2.1
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 +29 -11
- package/dist/exports/create-request.d.ts +15 -1
- package/dist/exports/create-request.d.ts.map +1 -1
- package/dist/exports/create-request.js +13 -4
- package/dist/exports/create-request.js.map +1 -1
- package/dist/hooks.d.ts +12 -4
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +98 -107
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +12 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -18
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +18 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/dependency-graph.d.ts +3 -10
- package/dist/utils/dependency-graph.d.ts.map +1 -1
- package/dist/utils/dependency-graph.js +27 -50
- package/dist/utils/dependency-graph.js.map +1 -1
- package/dist/utils/tracked-collections.d.ts.map +1 -1
- package/dist/utils/tracked-collections.js.map +1 -1
- package/package.json +6 -26
- package/dist/components/PublishButton.d.ts +0 -2
- package/dist/components/PublishButton.d.ts.map +0 -1
- package/dist/components/PublishButton.js +0 -52
- package/dist/components/PublishButton.js.map +0 -1
- package/dist/const.d.ts +0 -7
- package/dist/const.d.ts.map +0 -1
- package/dist/const.js +0 -13
- package/dist/const.js.map +0 -1
- package/dist/endpoints/check.d.ts +0 -3
- package/dist/endpoints/check.d.ts.map +0 -1
- package/dist/endpoints/check.js +0 -21
- package/dist/endpoints/check.js.map +0 -1
- package/dist/endpoints/publish.d.ts +0 -4
- package/dist/endpoints/publish.d.ts.map +0 -1
- package/dist/endpoints/publish.js +0 -109
- package/dist/endpoints/publish.js.map +0 -1
- package/dist/entities.d.ts +0 -26
- package/dist/entities.d.ts.map +0 -1
- package/dist/entities.js +0 -28
- package/dist/entities.js.map +0 -1
- package/dist/exports/client.d.ts +0 -2
- package/dist/exports/client.d.ts.map +0 -1
- package/dist/exports/client.js +0 -3
- package/dist/exports/client.js.map +0 -1
- package/dist/exports/rsc.d.ts +0 -2
- package/dist/exports/rsc.d.ts.map +0 -1
- package/dist/exports/rsc.js +0 -3
- package/dist/exports/rsc.js.map +0 -1
- package/dist/payload-types.d.ts +0 -241
- package/dist/payload-types.d.ts.map +0 -1
- package/dist/utils/collection-changes.d.ts +0 -8
- package/dist/utils/collection-changes.d.ts.map +0 -1
- package/dist/utils/collection-changes.js +0 -27
- package/dist/utils/collection-changes.js.map +0 -1
package/README.md
CHANGED
|
@@ -7,14 +7,14 @@ Intelligent, dependency-aware cache invalidation for Next.js + Payload CMS appli
|
|
|
7
7
|
|
|
8
8
|
## Overview
|
|
9
9
|
|
|
10
|
-
payload-smart-cache
|
|
10
|
+
payload-smart-cache hooks into Payload's save and publish flow to provide automatic, dependency-aware cache invalidation. It builds a dependency graph from your collection and global relationships and walks it on every change, revalidating all affected Next.js cache tags — including indirectly related collections and globals.
|
|
11
11
|
|
|
12
12
|
**Features**
|
|
13
13
|
|
|
14
|
-
- **Deferred publishing** — changes are queued and only pushed to the cache when you explicitly publish.
|
|
15
14
|
- **Dependency graph** — automatically discovers relationships between collections, so changing a referenced document revalidates its dependents.
|
|
16
15
|
- **Tag-based revalidation** — precise, granular cache invalidation via Next.js `revalidateTag()`.
|
|
17
|
-
- **
|
|
16
|
+
- **Versions-aware** — for versioned collections, cache invalidation only fires on publish, not on draft saves.
|
|
17
|
+
- **Request caching utility** — `createRequestHandler` wraps data-fetching functions with collection/global-level cache tags for automatic revalidation.
|
|
18
18
|
|
|
19
19
|
## Installation
|
|
20
20
|
|
|
@@ -44,7 +44,7 @@ export default buildConfig({
|
|
|
44
44
|
});
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
Wrap your data-fetching functions with `createRequestHandler` so they are cached by
|
|
47
|
+
Wrap your data-fetching functions with `createRequestHandler` so they are cached by collection/global tags and automatically revalidated when those collections or globals change:
|
|
48
48
|
|
|
49
49
|
```ts
|
|
50
50
|
import { createRequestHandler } from "payload-smart-cache";
|
|
@@ -54,18 +54,36 @@ const getPosts = createRequestHandler(
|
|
|
54
54
|
const payload = await getPayload({ config });
|
|
55
55
|
return payload.find({ collection: "posts" });
|
|
56
56
|
},
|
|
57
|
-
["posts"], //
|
|
57
|
+
["posts"], // collection/global slugs — revalidated when posts change
|
|
58
58
|
);
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
+
You can pass additional cache options as a third argument:
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
const getPosts = createRequestHandler(
|
|
65
|
+
async () => {
|
|
66
|
+
const payload = await getPayload({ config });
|
|
67
|
+
return payload.find({ collection: "posts" });
|
|
68
|
+
},
|
|
69
|
+
["posts"],
|
|
70
|
+
{ revalidate: 60 }, // also revalidate every 60 seconds
|
|
71
|
+
);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
| Cache Option | Type | Default | Description |
|
|
75
|
+
| ------------- | ------------------ | ------- | -------------------------------------------------------------------- |
|
|
76
|
+
| `tags` | `string[]` | `[]` | Additional cache tags beyond the collection/global slugs. |
|
|
77
|
+
| `revalidate` | `number \| false` | `false` | Time-based revalidation in seconds, or `false` for tag-based only. |
|
|
78
|
+
|
|
61
79
|
### Options
|
|
62
80
|
|
|
63
|
-
| Option | Type
|
|
64
|
-
| --------------------- |
|
|
65
|
-
| `collections` | `CollectionSlug[]`
|
|
66
|
-
| `globals` | `GlobalSlug[]`
|
|
67
|
-
| `disableAutoTracking` | `boolean`
|
|
68
|
-
| `
|
|
81
|
+
| Option | Type | Default | Description |
|
|
82
|
+
| --------------------- | ----------------------------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
83
|
+
| `collections` | `CollectionSlug[]` | `[]` | Collections to track changes for. Referenced collections are auto-tracked. |
|
|
84
|
+
| `globals` | `GlobalSlug[]` | `[]` | Globals to track changes for. Referenced collections are auto-tracked. |
|
|
85
|
+
| `disableAutoTracking` | `boolean` | `false` | Disable automatic tracking of collections referenced via relationship/upload fields. |
|
|
86
|
+
| `onInvalidate` | `(change) => void \| Promise<void>` | — | Called when cache invalidation fires for a registered collection (`{ type: 'collection', slug, docID }`) or global (`{ type: 'global', slug }`). |
|
|
69
87
|
|
|
70
88
|
## Contributing
|
|
71
89
|
|
|
@@ -1,3 +1,17 @@
|
|
|
1
1
|
import type { EntitySlug } from '../types';
|
|
2
|
-
export
|
|
2
|
+
export interface RequestHandlerCacheOptions {
|
|
3
|
+
/** Additional cache tags beyond the collection/global slugs. */
|
|
4
|
+
tags?: string[];
|
|
5
|
+
/** Time-based revalidation in seconds, or `false` to rely solely on tag-based revalidation. */
|
|
6
|
+
revalidate?: number | false;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Wraps a data-fetching function with Next.js `unstable_cache`, tagging it with
|
|
10
|
+
* collection/global slugs so it is automatically revalidated when those collections or globals change.
|
|
11
|
+
*
|
|
12
|
+
* @param handler - The async function to cache.
|
|
13
|
+
* @param slugs - Collection or global slugs used as cache tags (e.g. `['posts', 'media']`).
|
|
14
|
+
* @param options - Additional cache options passed to `unstable_cache`.
|
|
15
|
+
*/
|
|
16
|
+
export declare const createRequestHandler: <Data, Inputs extends unknown[]>(handler: (...inputs: Inputs) => Promise<Data>, slugs: EntitySlug[], options?: RequestHandlerCacheOptions) => ((...inputs: Inputs) => Promise<Data>);
|
|
3
17
|
//# sourceMappingURL=create-request.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-request.d.ts","sourceRoot":"","sources":["../../src/exports/create-request.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"create-request.d.ts","sourceRoot":"","sources":["../../src/exports/create-request.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,WAAW,0BAA0B;IACzC,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,+FAA+F;IAC/F,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,GAAI,IAAI,EAAE,MAAM,SAAS,OAAO,EAAE,WACxD,CAAC,GAAG,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,SACtC,UAAU,EAAE,YACT,0BAA0B,KACnC,CAAC,CAAC,GAAG,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAIpC,CAAC"}
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import { unstable_cache } from 'next/cache';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Wraps a data-fetching function with Next.js `unstable_cache`, tagging it with
|
|
4
|
+
* collection/global slugs so it is automatically revalidated when those collections or globals change.
|
|
5
|
+
*
|
|
6
|
+
* @param handler - The async function to cache.
|
|
7
|
+
* @param slugs - Collection or global slugs used as cache tags (e.g. `['posts', 'media']`).
|
|
8
|
+
* @param options - Additional cache options passed to `unstable_cache`.
|
|
9
|
+
*/ export const createRequestHandler = (handler, slugs, options)=>unstable_cache(handler, undefined, {
|
|
10
|
+
tags: [
|
|
11
|
+
...slugs,
|
|
12
|
+
...options?.tags ?? []
|
|
13
|
+
],
|
|
14
|
+
revalidate: options?.revalidate ?? false
|
|
6
15
|
});
|
|
7
16
|
|
|
8
17
|
//# sourceMappingURL=create-request.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/exports/create-request.ts"],"sourcesContent":["import { unstable_cache } from 'next/cache';\n\nimport type { EntitySlug } from '../types';\n\n
|
|
1
|
+
{"version":3,"sources":["../../src/exports/create-request.ts"],"sourcesContent":["import { unstable_cache } from 'next/cache';\n\nimport type { EntitySlug } from '../types';\n\nexport interface RequestHandlerCacheOptions {\n /** Additional cache tags beyond the collection/global slugs. */\n tags?: string[];\n /** Time-based revalidation in seconds, or `false` to rely solely on tag-based revalidation. */\n revalidate?: number | false;\n}\n\n/**\n * Wraps a data-fetching function with Next.js `unstable_cache`, tagging it with\n * collection/global slugs so it is automatically revalidated when those collections or globals change.\n *\n * @param handler - The async function to cache.\n * @param slugs - Collection or global slugs used as cache tags (e.g. `['posts', 'media']`).\n * @param options - Additional cache options passed to `unstable_cache`.\n */\nexport const createRequestHandler = <Data, Inputs extends unknown[]>(\n handler: (...inputs: Inputs) => Promise<Data>,\n slugs: EntitySlug[],\n options?: RequestHandlerCacheOptions,\n): ((...inputs: Inputs) => Promise<Data>) =>\n unstable_cache(handler, undefined, {\n tags: [...slugs, ...(options?.tags ?? [])],\n revalidate: options?.revalidate ?? false,\n });\n"],"names":["unstable_cache","createRequestHandler","handler","slugs","options","undefined","tags","revalidate"],"mappings":"AAAA,SAASA,cAAc,QAAQ,aAAa;AAW5C;;;;;;;CAOC,GACD,OAAO,MAAMC,uBAAuB,CAClCC,SACAC,OACAC,UAEAJ,eAAeE,SAASG,WAAW;QACjCC,MAAM;eAAIH;eAAWC,SAASE,QAAQ,EAAE;SAAE;QAC1CC,YAAYH,SAASG,cAAc;IACrC,GAAG"}
|
package/dist/hooks.d.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
import type { CollectionAfterChangeHook, CollectionAfterDeleteHook, GlobalAfterChangeHook
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export declare
|
|
1
|
+
import type { CollectionAfterChangeHook, CollectionAfterDeleteHook, GlobalAfterChangeHook } from 'payload';
|
|
2
|
+
import type { DocumentInvalidationCallback, DocumentWithStatus } from './types';
|
|
3
|
+
import type { EntitiesGraph } from './utils/dependency-graph';
|
|
4
|
+
export declare function invalidateCollectionCache({ graph, invalidationCallback, }: {
|
|
5
|
+
graph: EntitiesGraph;
|
|
6
|
+
invalidationCallback: DocumentInvalidationCallback | undefined;
|
|
7
|
+
}): CollectionAfterChangeHook<DocumentWithStatus>;
|
|
8
|
+
export declare function invalidateCollectionCacheOnDelete({ graph, invalidationCallback, }: {
|
|
9
|
+
graph: EntitiesGraph;
|
|
10
|
+
invalidationCallback: DocumentInvalidationCallback;
|
|
11
|
+
}): CollectionAfterDeleteHook<DocumentWithStatus>;
|
|
12
|
+
export declare function invalidateGlobalCache(invalidationCallback: DocumentInvalidationCallback): GlobalAfterChangeHook;
|
|
5
13
|
//# sourceMappingURL=hooks.d.ts.map
|
package/dist/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,yBAAyB,EACzB,yBAAyB,EAEzB,qBAAqB,EACtB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,4BAA4B,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAChF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AA4G9D,wBAAgB,yBAAyB,CAAC,EACxC,KAAK,EACL,oBAAoB,GACrB,EAAE;IACD,KAAK,EAAE,aAAa,CAAC;IACrB,oBAAoB,EAAE,4BAA4B,GAAG,SAAS,CAAC;CAChE,GAAG,yBAAyB,CAAC,kBAAkB,CAAC,CAgBhD;AAED,wBAAgB,iCAAiC,CAAC,EAChD,KAAK,EACL,oBAAoB,GACrB,EAAE;IACD,KAAK,EAAE,aAAa,CAAC;IACrB,oBAAoB,EAAE,4BAA4B,CAAC;CACpD,GAAG,yBAAyB,CAAC,kBAAkB,CAAC,CAWhD;AAED,wBAAgB,qBAAqB,CACnC,oBAAoB,EAAE,4BAA4B,GACjD,qBAAqB,CAWvB"}
|
package/dist/hooks.js
CHANGED
|
@@ -1,119 +1,110 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
{
|
|
15
|
-
entityId: {
|
|
16
|
-
equals: entityId
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
]
|
|
20
|
-
},
|
|
21
|
-
limit: 1
|
|
22
|
-
});
|
|
23
|
-
if (existingChange) {
|
|
24
|
-
// Update existing change record
|
|
25
|
-
await payload.update({
|
|
26
|
-
collection: 'publish-queue',
|
|
27
|
-
id: existingChange.id,
|
|
28
|
-
data: {
|
|
29
|
-
updatedAt: new Date().toISOString()
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
} else {
|
|
33
|
-
await payload.create({
|
|
34
|
-
collection: 'publish-queue',
|
|
35
|
-
data: {
|
|
36
|
-
entityType,
|
|
37
|
-
entityId
|
|
38
|
-
}
|
|
1
|
+
import { revalidateTag } from 'next/cache';
|
|
2
|
+
async function invalidateWithDependents(payload, { graph, invalidationCallback, collection, ids }) {
|
|
3
|
+
const tagsToInvalidate = new Set();
|
|
4
|
+
tagsToInvalidate.add(collection);
|
|
5
|
+
await walkDependents(graph, payload, collection, ids, new Set());
|
|
6
|
+
for (const tag of tagsToInvalidate){
|
|
7
|
+
revalidateTag(tag);
|
|
8
|
+
}
|
|
9
|
+
for (const id of ids){
|
|
10
|
+
await invalidationCallback?.({
|
|
11
|
+
type: 'collection',
|
|
12
|
+
slug: collection,
|
|
13
|
+
docID: id
|
|
39
14
|
});
|
|
40
15
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
16
|
+
async function walkDependents(graph, payload, changedCollection, changedIds, visited) {
|
|
17
|
+
const dependents = graph.getDependants(changedCollection);
|
|
18
|
+
if (dependents.length === 0) return;
|
|
19
|
+
for (const dependent of dependents){
|
|
20
|
+
if (dependent.entity.type === 'global') {
|
|
21
|
+
tagsToInvalidate.add(dependent.entity.slug);
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
if (visited.has(dependent.entity.slug)) continue;
|
|
25
|
+
const allAffectedItems = new Map();
|
|
26
|
+
for (const field of dependent.fields){
|
|
27
|
+
const { docs } = await payload.find({
|
|
28
|
+
collection: dependent.entity.slug,
|
|
29
|
+
where: field.polymorphic ? {
|
|
30
|
+
and: [
|
|
31
|
+
{
|
|
32
|
+
[`${field.field}.relationTo`]: {
|
|
33
|
+
equals: changedCollection
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
[`${field.field}.value`]: {
|
|
38
|
+
in: changedIds
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
} : {
|
|
43
|
+
[field.field]: {
|
|
44
|
+
in: changedIds
|
|
45
|
+
}
|
|
58
46
|
}
|
|
47
|
+
});
|
|
48
|
+
for (const item of docs){
|
|
49
|
+
allAffectedItems.set(item.id.toString(), item);
|
|
59
50
|
}
|
|
60
|
-
]
|
|
61
|
-
},
|
|
62
|
-
limit: 1
|
|
63
|
-
});
|
|
64
|
-
if (existingChange) {
|
|
65
|
-
// Update existing change record
|
|
66
|
-
await payload.update({
|
|
67
|
-
collection: 'publish-queue',
|
|
68
|
-
id: existingChange.id,
|
|
69
|
-
data: {
|
|
70
|
-
updatedAt: new Date().toISOString()
|
|
71
51
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
52
|
+
const affectedItems = Array.from(allAffectedItems.values());
|
|
53
|
+
visited.add(dependent.entity.slug);
|
|
54
|
+
if (affectedItems.length === 0) continue;
|
|
55
|
+
tagsToInvalidate.add(dependent.entity.slug);
|
|
56
|
+
for (const item of affectedItems){
|
|
57
|
+
await invalidationCallback?.({
|
|
58
|
+
type: 'collection',
|
|
59
|
+
slug: dependent.entity.slug,
|
|
60
|
+
docID: item.id.toString()
|
|
61
|
+
});
|
|
79
62
|
}
|
|
80
|
-
|
|
63
|
+
await walkDependents(graph, payload, dependent.entity.slug, affectedItems.map((item)=>item.id.toString()), visited);
|
|
64
|
+
}
|
|
81
65
|
}
|
|
82
|
-
}
|
|
83
|
-
export
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
66
|
+
}
|
|
67
|
+
export function invalidateCollectionCache({ graph, invalidationCallback }) {
|
|
68
|
+
return async ({ req, doc, collection, previousDoc })=>{
|
|
69
|
+
if (req.context.skipRevalidation) return;
|
|
70
|
+
if (collection.versions?.drafts) {
|
|
71
|
+
if (doc._status === 'draft' && previousDoc._status !== 'published') return;
|
|
72
|
+
}
|
|
73
|
+
await invalidateWithDependents(req.payload, {
|
|
74
|
+
graph,
|
|
75
|
+
invalidationCallback,
|
|
76
|
+
collection: collection.slug,
|
|
77
|
+
ids: [
|
|
78
|
+
doc.id.toString()
|
|
95
79
|
]
|
|
96
|
-
},
|
|
97
|
-
limit: 1
|
|
98
|
-
});
|
|
99
|
-
if (existingChange) {
|
|
100
|
-
// Update existing change record
|
|
101
|
-
await payload.update({
|
|
102
|
-
collection: 'publish-queue',
|
|
103
|
-
id: existingChange.id,
|
|
104
|
-
data: {
|
|
105
|
-
updatedAt: new Date().toISOString()
|
|
106
|
-
}
|
|
107
80
|
});
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export function invalidateCollectionCacheOnDelete({ graph, invalidationCallback }) {
|
|
84
|
+
return async ({ req, doc, collection })=>{
|
|
85
|
+
if (req.context.skipRevalidation) return;
|
|
86
|
+
await invalidateWithDependents(req.payload, {
|
|
87
|
+
graph,
|
|
88
|
+
invalidationCallback,
|
|
89
|
+
collection: collection.slug,
|
|
90
|
+
ids: [
|
|
91
|
+
doc.id.toString()
|
|
92
|
+
]
|
|
115
93
|
});
|
|
116
|
-
}
|
|
117
|
-
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export function invalidateGlobalCache(invalidationCallback) {
|
|
97
|
+
return async ({ req, global, doc, previousDoc })=>{
|
|
98
|
+
if (global.versions?.drafts) {
|
|
99
|
+
if (doc._status === 'draft' && previousDoc._status !== 'published') return;
|
|
100
|
+
}
|
|
101
|
+
if (req.context.skipRevalidation) return;
|
|
102
|
+
revalidateTag(global.slug);
|
|
103
|
+
await invalidationCallback?.({
|
|
104
|
+
type: 'global',
|
|
105
|
+
slug: global.slug
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
}
|
|
118
109
|
|
|
119
110
|
//# sourceMappingURL=hooks.js.map
|
package/dist/hooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks.ts"],"sourcesContent":["import type {\n CollectionAfterChangeHook,\n CollectionAfterDeleteHook,\n
|
|
1
|
+
{"version":3,"sources":["../src/hooks.ts"],"sourcesContent":["import { revalidateTag } from 'next/cache';\nimport type {\n BasePayload,\n CollectionAfterChangeHook,\n CollectionAfterDeleteHook,\n CollectionSlug,\n GlobalAfterChangeHook,\n} from 'payload';\nimport type { DocumentInvalidationCallback, DocumentWithStatus } from './types';\nimport type { EntitiesGraph } from './utils/dependency-graph';\n\nasync function invalidateWithDependents(\n payload: BasePayload,\n {\n graph,\n invalidationCallback,\n collection,\n ids,\n }: {\n graph: EntitiesGraph;\n invalidationCallback: DocumentInvalidationCallback | undefined;\n collection: CollectionSlug;\n ids: string[];\n },\n): Promise<void> {\n const tagsToInvalidate = new Set<string>();\n\n tagsToInvalidate.add(collection);\n\n await walkDependents(graph, payload, collection, ids, new Set());\n\n for (const tag of tagsToInvalidate) {\n revalidateTag(tag);\n }\n\n for (const id of ids) {\n await invalidationCallback?.({\n type: 'collection',\n slug: collection,\n docID: id,\n });\n }\n\n async function walkDependents(\n graph: EntitiesGraph,\n payload: BasePayload,\n changedCollection: CollectionSlug,\n changedIds: string[],\n visited: Set<string>,\n ): Promise<void> {\n const dependents = graph.getDependants(changedCollection);\n\n if (dependents.length === 0) return;\n\n for (const dependent of dependents) {\n if (dependent.entity.type === 'global') {\n tagsToInvalidate.add(dependent.entity.slug);\n continue;\n }\n\n if (visited.has(dependent.entity.slug)) continue;\n\n const allAffectedItems = new Map<string, { id: string | number }>();\n\n for (const field of dependent.fields) {\n const { docs } = await payload.find({\n collection: dependent.entity.slug,\n where: field.polymorphic\n ? {\n and: [\n {\n [`${field.field}.relationTo`]: {\n equals: changedCollection,\n },\n },\n { [`${field.field}.value`]: { in: changedIds } },\n ],\n }\n : {\n [field.field]: {\n in: changedIds,\n },\n },\n });\n\n for (const item of docs) {\n allAffectedItems.set(item.id.toString(), item);\n }\n }\n\n const affectedItems = Array.from(allAffectedItems.values());\n\n visited.add(dependent.entity.slug);\n\n if (affectedItems.length === 0) continue;\n\n tagsToInvalidate.add(dependent.entity.slug);\n\n for (const item of affectedItems) {\n await invalidationCallback?.({\n type: 'collection',\n slug: dependent.entity.slug,\n docID: item.id.toString(),\n });\n }\n\n await walkDependents(\n graph,\n payload,\n dependent.entity.slug,\n affectedItems.map((item) => item.id.toString()),\n visited,\n );\n }\n }\n}\n\nexport function invalidateCollectionCache({\n graph,\n invalidationCallback,\n}: {\n graph: EntitiesGraph;\n invalidationCallback: DocumentInvalidationCallback | undefined;\n}): CollectionAfterChangeHook<DocumentWithStatus> {\n return async ({ req, doc, collection, previousDoc }) => {\n if (req.context.skipRevalidation) return;\n\n if (collection.versions?.drafts) {\n if (doc._status === 'draft' && previousDoc._status !== 'published')\n return;\n }\n\n await invalidateWithDependents(req.payload, {\n graph,\n invalidationCallback,\n collection: collection.slug,\n ids: [doc.id.toString()],\n });\n };\n}\n\nexport function invalidateCollectionCacheOnDelete({\n graph,\n invalidationCallback,\n}: {\n graph: EntitiesGraph;\n invalidationCallback: DocumentInvalidationCallback;\n}): CollectionAfterDeleteHook<DocumentWithStatus> {\n return async ({ req, doc, collection }) => {\n if (req.context.skipRevalidation) return;\n\n await invalidateWithDependents(req.payload, {\n graph,\n invalidationCallback,\n collection: collection.slug,\n ids: [doc.id.toString()],\n });\n };\n}\n\nexport function invalidateGlobalCache(\n invalidationCallback: DocumentInvalidationCallback,\n): GlobalAfterChangeHook {\n return async ({ req, global, doc, previousDoc }) => {\n if (global.versions?.drafts) {\n if (doc._status === 'draft' && previousDoc._status !== 'published')\n return;\n }\n if (req.context.skipRevalidation) return;\n\n revalidateTag(global.slug);\n await invalidationCallback?.({ type: 'global', slug: global.slug });\n };\n}\n"],"names":["revalidateTag","invalidateWithDependents","payload","graph","invalidationCallback","collection","ids","tagsToInvalidate","Set","add","walkDependents","tag","id","type","slug","docID","changedCollection","changedIds","visited","dependents","getDependants","length","dependent","entity","has","allAffectedItems","Map","field","fields","docs","find","where","polymorphic","and","equals","in","item","set","toString","affectedItems","Array","from","values","map","invalidateCollectionCache","req","doc","previousDoc","context","skipRevalidation","versions","drafts","_status","invalidateCollectionCacheOnDelete","invalidateGlobalCache","global"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,26 +1,30 @@
|
|
|
1
1
|
import type { CollectionSlug, GlobalSlug, Plugin } from 'payload';
|
|
2
|
-
import type {
|
|
3
|
-
export
|
|
2
|
+
import type { DocumentInvalidationCallback } from './types';
|
|
3
|
+
export { createRequestHandler, type RequestHandlerCacheOptions, } from './exports/create-request';
|
|
4
|
+
export type { DocumentInvalidation as InvalidationChange, DocumentInvalidationCallback as OnInvalidate, } from './types';
|
|
5
|
+
export interface SmartCachePluginConfig<C extends CollectionSlug = CollectionSlug, G extends GlobalSlug = GlobalSlug> {
|
|
4
6
|
/**
|
|
5
7
|
* The collections to track changes for.
|
|
6
8
|
* By default, collections referenced via relationship or upload fields
|
|
7
9
|
* are automatically tracked as well.
|
|
8
10
|
*/
|
|
9
|
-
collections?:
|
|
11
|
+
collections?: C[];
|
|
10
12
|
/**
|
|
11
13
|
* The globals to track changes for.
|
|
12
14
|
* Collections referenced by these globals via relationship or upload
|
|
13
15
|
* fields are automatically tracked as well.
|
|
14
16
|
*/
|
|
15
|
-
globals?:
|
|
17
|
+
globals?: G[];
|
|
16
18
|
/**
|
|
17
19
|
* Disable automatic tracking of collections referenced by the configured ones.
|
|
18
20
|
* @default false
|
|
19
21
|
*/
|
|
20
22
|
disableAutoTracking?: boolean;
|
|
21
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Called when cache invalidation is triggered.
|
|
25
|
+
* Only fires for collections/globals explicitly registered in the config.
|
|
26
|
+
*/
|
|
27
|
+
onInvalidate?: DocumentInvalidationCallback<C, G>;
|
|
22
28
|
}
|
|
23
|
-
export declare const smartCachePlugin: ({ collections, globals,
|
|
24
|
-
export { createRequestHandler } from './exports/create-request';
|
|
25
|
-
export type { ChangedDocuments } from './types';
|
|
29
|
+
export declare const smartCachePlugin: <C extends CollectionSlug = string, G extends GlobalSlug = string>({ collections, globals, onInvalidate, disableAutoTracking, }: SmartCachePluginConfig<C, G>) => Plugin;
|
|
26
30
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAMlE,OAAO,KAAK,EAEV,4BAA4B,EAE7B,MAAM,SAAS,CAAC;AAIjB,OAAO,EACL,oBAAoB,EACpB,KAAK,0BAA0B,GAChC,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,oBAAoB,IAAI,kBAAkB,EAC1C,4BAA4B,IAAI,YAAY,GAC7C,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,sBAAsB,CACrC,CAAC,SAAS,cAAc,GAAG,cAAc,EACzC,CAAC,SAAS,UAAU,GAAG,UAAU;IAEjC;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,EAAE,CAAC;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;IACd;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;OAGG;IACH,YAAY,CAAC,EAAE,4BAA4B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CACnD;AAED,eAAO,MAAM,gBAAgB,GAEzB,CAAC,SAAS,cAAc,WACxB,CAAC,SAAS,UAAU,yEAMnB,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,MAmDjC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,25 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { PublishQueue } from './entities';
|
|
4
|
-
import { trackCollectionChange, trackCollectionDelete, trackGlobalChange } from './hooks';
|
|
1
|
+
import { invalidateCollectionCache, invalidateCollectionCacheOnDelete, invalidateGlobalCache } from './hooks';
|
|
2
|
+
import { createDependencyGraph } from './utils/dependency-graph';
|
|
5
3
|
import { getTrackedCollections } from './utils/tracked-collections';
|
|
6
|
-
export
|
|
4
|
+
export { createRequestHandler } from './exports/create-request';
|
|
5
|
+
export const smartCachePlugin = ({ collections = [], globals = [], onInvalidate, disableAutoTracking })=>(config)=>{
|
|
7
6
|
if (collections.length + globals.length === 0) {
|
|
8
7
|
console.warn('[payload-smart-cache] No collections or globals are configured to track changes for, hence this plugin will have no effect.');
|
|
9
8
|
return config;
|
|
10
9
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
const graph = createDependencyGraph(config);
|
|
11
|
+
const invalidationCallback = wrapInvalidationCallback({
|
|
12
|
+
collections,
|
|
13
|
+
globals,
|
|
14
|
+
onInvalidate: onInvalidate
|
|
16
15
|
});
|
|
17
16
|
config.globals ??= [];
|
|
18
17
|
for (const global of config.globals){
|
|
19
18
|
if (!globals.includes(global.slug)) continue;
|
|
20
19
|
global.hooks ??= {};
|
|
21
20
|
global.hooks.afterChange ??= [];
|
|
22
|
-
global.hooks.afterChange.push(
|
|
21
|
+
global.hooks.afterChange.push(invalidateGlobalCache(invalidationCallback));
|
|
23
22
|
}
|
|
24
23
|
config.collections ??= [];
|
|
25
24
|
const collectionsToTrack = disableAutoTracking ? new Set(collections) : getTrackedCollections({
|
|
@@ -33,16 +32,27 @@ export const smartCachePlugin = ({ collections = [], globals = [], publishHandle
|
|
|
33
32
|
if (!collectionsToTrack.has(collection.slug)) continue;
|
|
34
33
|
collection.hooks ??= {};
|
|
35
34
|
collection.hooks.afterChange ??= [];
|
|
36
|
-
collection.hooks.afterChange.push(
|
|
35
|
+
collection.hooks.afterChange.push(invalidateCollectionCache({
|
|
36
|
+
graph,
|
|
37
|
+
invalidationCallback
|
|
38
|
+
}));
|
|
37
39
|
collection.hooks.afterDelete ??= [];
|
|
38
|
-
collection.hooks.afterDelete.push(
|
|
40
|
+
collection.hooks.afterDelete.push(invalidateCollectionCacheOnDelete({
|
|
41
|
+
graph,
|
|
42
|
+
invalidationCallback
|
|
43
|
+
}));
|
|
39
44
|
}
|
|
40
|
-
config.collections.push(PublishQueue);
|
|
41
|
-
config.endpoints ??= [];
|
|
42
|
-
config.endpoints.push(createPublishChangesEndpoint(publishHandler));
|
|
43
|
-
config.endpoints.push(checkEndpoint);
|
|
44
45
|
return config;
|
|
45
46
|
};
|
|
46
|
-
|
|
47
|
+
function wrapInvalidationCallback({ collections, globals, onInvalidate }) {
|
|
48
|
+
if (!onInvalidate) return ()=>void 0;
|
|
49
|
+
const registeredCollections = new Set(collections);
|
|
50
|
+
const registeredGlobals = new Set(globals);
|
|
51
|
+
return (change)=>{
|
|
52
|
+
if (change.type === 'collection' && !registeredCollections.has(change.slug)) return;
|
|
53
|
+
if (change.type === 'global' && !registeredGlobals.has(change.slug)) return;
|
|
54
|
+
return onInvalidate(change);
|
|
55
|
+
};
|
|
56
|
+
}
|
|
47
57
|
|
|
48
58
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionSlug, GlobalSlug, Plugin } from 'payload';\nimport {
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionSlug, GlobalSlug, Plugin } from 'payload';\nimport {\n invalidateCollectionCache,\n invalidateCollectionCacheOnDelete,\n invalidateGlobalCache,\n} from './hooks';\nimport type {\n DocumentInvalidation,\n DocumentInvalidationCallback,\n ResolvedPluginOptions,\n} from './types';\nimport { createDependencyGraph } from './utils/dependency-graph';\nimport { getTrackedCollections } from './utils/tracked-collections';\n\nexport {\n createRequestHandler,\n type RequestHandlerCacheOptions,\n} from './exports/create-request';\nexport type {\n DocumentInvalidation as InvalidationChange,\n DocumentInvalidationCallback as OnInvalidate,\n} from './types';\n\nexport interface SmartCachePluginConfig<\n C extends CollectionSlug = CollectionSlug,\n G extends GlobalSlug = GlobalSlug,\n> {\n /**\n * The collections to track changes for.\n * By default, collections referenced via relationship or upload fields\n * are automatically tracked as well.\n */\n collections?: C[];\n /**\n * The globals to track changes for.\n * Collections referenced by these globals via relationship or upload\n * fields are automatically tracked as well.\n */\n globals?: G[];\n /**\n * Disable automatic tracking of collections referenced by the configured ones.\n * @default false\n */\n disableAutoTracking?: boolean;\n /**\n * Called when cache invalidation is triggered.\n * Only fires for collections/globals explicitly registered in the config.\n */\n onInvalidate?: DocumentInvalidationCallback<C, G>;\n}\n\nexport const smartCachePlugin =\n <\n C extends CollectionSlug = CollectionSlug,\n G extends GlobalSlug = GlobalSlug,\n >({\n collections = [],\n globals = [],\n onInvalidate,\n disableAutoTracking,\n }: SmartCachePluginConfig<C, G>): Plugin =>\n (config) => {\n if (collections.length + globals.length === 0) {\n console.warn(\n '[payload-smart-cache] No collections or globals are configured to track changes for, hence this plugin will have no effect.',\n );\n return config;\n }\n\n const graph = createDependencyGraph(config);\n\n const invalidationCallback = wrapInvalidationCallback({\n collections,\n globals,\n onInvalidate: onInvalidate as DocumentInvalidationCallback,\n });\n\n config.globals ??= [];\n for (const global of config.globals) {\n if (!globals.includes(global.slug as G)) continue;\n global.hooks ??= {};\n global.hooks.afterChange ??= [];\n global.hooks.afterChange.push(\n invalidateGlobalCache(invalidationCallback),\n );\n }\n\n config.collections ??= [];\n const collectionsToTrack = disableAutoTracking\n ? new Set(collections)\n : getTrackedCollections(\n { collections, globals },\n { collections: config.collections, globals: config.globals },\n );\n for (const collection of config.collections) {\n if (!collectionsToTrack.has(collection.slug as CollectionSlug)) continue;\n collection.hooks ??= {};\n collection.hooks.afterChange ??= [];\n collection.hooks.afterChange.push(\n invalidateCollectionCache({ graph, invalidationCallback }),\n );\n collection.hooks.afterDelete ??= [];\n collection.hooks.afterDelete.push(\n invalidateCollectionCacheOnDelete({\n graph,\n invalidationCallback,\n }),\n );\n }\n\n return config;\n };\n\nfunction wrapInvalidationCallback({\n collections,\n globals,\n onInvalidate,\n}: ResolvedPluginOptions<\n 'collections' | 'globals',\n 'onInvalidate'\n>): DocumentInvalidationCallback {\n if (!onInvalidate) return () => void 0;\n\n const registeredCollections = new Set(collections);\n const registeredGlobals = new Set(globals);\n\n return (change: DocumentInvalidation) => {\n if (change.type === 'collection' && !registeredCollections.has(change.slug))\n return;\n if (change.type === 'global' && !registeredGlobals.has(change.slug)) return;\n return onInvalidate(change);\n };\n}\n"],"names":["invalidateCollectionCache","invalidateCollectionCacheOnDelete","invalidateGlobalCache","createDependencyGraph","getTrackedCollections","createRequestHandler","smartCachePlugin","collections","globals","onInvalidate","disableAutoTracking","config","length","console","warn","graph","invalidationCallback","wrapInvalidationCallback","global","includes","slug","hooks","afterChange","push","collectionsToTrack","Set","collection","has","afterDelete","registeredCollections","registeredGlobals","change","type"],"mappings":"AACA,SACEA,yBAAyB,EACzBC,iCAAiC,EACjCC,qBAAqB,QAChB,UAAU;AAMjB,SAASC,qBAAqB,QAAQ,2BAA2B;AACjE,SAASC,qBAAqB,QAAQ,8BAA8B;AAEpE,SACEC,oBAAoB,QAEf,2BAA2B;AAkClC,OAAO,MAAMC,mBACX,CAGE,EACAC,cAAc,EAAE,EAChBC,UAAU,EAAE,EACZC,YAAY,EACZC,mBAAmB,EACU,GAC/B,CAACC;QACC,IAAIJ,YAAYK,MAAM,GAAGJ,QAAQI,MAAM,KAAK,GAAG;YAC7CC,QAAQC,IAAI,CACV;YAEF,OAAOH;QACT;QAEA,MAAMI,QAAQZ,sBAAsBQ;QAEpC,MAAMK,uBAAuBC,yBAAyB;YACpDV;YACAC;YACAC,cAAcA;QAChB;QAEAE,OAAOH,OAAO,KAAK,EAAE;QACrB,KAAK,MAAMU,UAAUP,OAAOH,OAAO,CAAE;YACnC,IAAI,CAACA,QAAQW,QAAQ,CAACD,OAAOE,IAAI,GAAQ;YACzCF,OAAOG,KAAK,KAAK,CAAC;YAClBH,OAAOG,KAAK,CAACC,WAAW,KAAK,EAAE;YAC/BJ,OAAOG,KAAK,CAACC,WAAW,CAACC,IAAI,CAC3BrB,sBAAsBc;QAE1B;QAEAL,OAAOJ,WAAW,KAAK,EAAE;QACzB,MAAMiB,qBAAqBd,sBACvB,IAAIe,IAAIlB,eACRH,sBACE;YAAEG;YAAaC;QAAQ,GACvB;YAAED,aAAaI,OAAOJ,WAAW;YAAEC,SAASG,OAAOH,OAAO;QAAC;QAEjE,KAAK,MAAMkB,cAAcf,OAAOJ,WAAW,CAAE;YAC3C,IAAI,CAACiB,mBAAmBG,GAAG,CAACD,WAAWN,IAAI,GAAqB;YAChEM,WAAWL,KAAK,KAAK,CAAC;YACtBK,WAAWL,KAAK,CAACC,WAAW,KAAK,EAAE;YACnCI,WAAWL,KAAK,CAACC,WAAW,CAACC,IAAI,CAC/BvB,0BAA0B;gBAAEe;gBAAOC;YAAqB;YAE1DU,WAAWL,KAAK,CAACO,WAAW,KAAK,EAAE;YACnCF,WAAWL,KAAK,CAACO,WAAW,CAACL,IAAI,CAC/BtB,kCAAkC;gBAChCc;gBACAC;YACF;QAEJ;QAEA,OAAOL;IACT,EAAE;AAEJ,SAASM,yBAAyB,EAChCV,WAAW,EACXC,OAAO,EACPC,YAAY,EAIb;IACC,IAAI,CAACA,cAAc,OAAO,IAAM,KAAK;IAErC,MAAMoB,wBAAwB,IAAIJ,IAAIlB;IACtC,MAAMuB,oBAAoB,IAAIL,IAAIjB;IAElC,OAAO,CAACuB;QACN,IAAIA,OAAOC,IAAI,KAAK,gBAAgB,CAACH,sBAAsBF,GAAG,CAACI,OAAOX,IAAI,GACxE;QACF,IAAIW,OAAOC,IAAI,KAAK,YAAY,CAACF,kBAAkBH,GAAG,CAACI,OAAOX,IAAI,GAAG;QACrE,OAAOX,aAAasB;IACtB;AACF"}
|