Getting Started
Installation
The major version of the plugin must match the major version of the Payload.
- npm
- Yarn
- pnpm
npm install payload-dependency-graph
yarn add payload-dependency-graph
pnpm add payload-dependency-graph
Configuration
In the plugins
array of your Payload config, call the plugin with options:
import { buildConfig } from 'payload/config';
import { DependencyGraphPlugin } from 'payload-dependency-graph';
const config = buildConfig({
// ... rest of your config
plugins: [DependencyGraphPlugin()],
});
export default config;
Plugin Options
Plugin Options are available here.
Factory
By default, the plugin uses the InMemoryDependencyGraph, but you can use another way to manage dependencies as long as you extend the DependencyGraphBase class. You can do this using the factory property.
If you're dealing with a lot of documents, a better approach is to use a database-oriented implementation because the in-memory approach will increase the RAM. The only available database-oriented implementation is MongoDB Dependency Graph and in the future minor versions it will be added a implementation for PostgreSQL which is currently beta.
MongoDB Dependency Graph is available for versions greater than or equal to 2.1.x.
Editor Extractor
Rich Text Fields can have relationships with other documents. The only problem is that the Payload Editor is highly customizable, therefore you can have editor features that use relationships. This can be difficult to extract relations for several reasons:
- You cannot extract an exact schema of what is in Rich Text.
- From Payload 2.x.x you can choose the editor you want to use, meaning that the structure of the value can differ.
Therefore editorExtractor is a function that gives you the ability to parse the Rich Text value and extract its dependencies.
If you are using Payload 2.x.x, you should be aware that each Rich Text field can customize its editor settings. In response, I added the option to customize the EditorExtractor for each field.
import { CollectionConfig } from 'payload/types';
import { lexicalEditor } from '@payloadcms/richtext-lexical';
export const Pages: CollectionConfig = {
slug: 'pages',
fields: [
{
name: 'content',
type: 'richText',
editor: lexicalEditor({
// ... your settings
}),
custom: {
editorExtractor: (args) => {
// ... your editor extractor implementation
},
},
},
],
};
Example
import { buildConfig } from 'payload/config';
import { DependencyGraphPlugin } from 'payload-dependency-graph';
const extract = async (nodes: any[], source, dependencyGraph) => {
for (let node of nodes) {
if ('children' in node) {
await extract(node.children);
} else if (node.type === 'image') {
await dependencyGraph.addDependency(source, {
collection: node.collection,
id: node.doc.id,
});
}
}
};
const config = buildConfig({
// ... rest of your config
plugins: [
DependencyGraphPlugin({
editorExtractor: async ({ source, value, dependencyGraph }) => {
await extract(value, source, dependencyGraph);
},
}),
],
});
export default config;
Usage
The utility of this plugin lies in listening to events on collections or globals and determining resource dependencies.
Listening
If you want to listen for changes, call the subscribe from DependencyGraphService. The DependencyGraphService
is a singletone instance.
import { buildConfig } from 'payload/config';
import { DependencyGraphPlugin, DependencyGraphService } from 'payload-dependency-graph';
const config = buildConfig({
// ... rest of your config
plugins: [DependencyGraphPlugin()],
onInit: (payload) => {
DependencyGraphService.subscribe((event) => {
// write your own logic
});
},
});
export default config;
Determine Dependencies
To determine if a resource is a dependency for another resource use the dependencyGraph from DependencyGraphService:
import { buildConfig } from 'payload/config';
import { DependencyGraphPlugin, DependencyGraphService } from 'payload-dependency-graph';
const config = buildConfig({
// ... rest of your config
plugins: [DependencyGraphPlugin()],
onInit: (payload) => {
DependencyGraphService.subscribe((event) => {
if (event.type === 'update' && event.collection) {
const graph = DependencyGraphService.dependencyGraph;
const resource = {
collection: event.collection,
id: event.doc.id,
};
if (event.collection === 'pages' && event.doc.id === 'home') {
// regenerate home page
} else {
if (
graph.isDependency(
{
collection: 'pages',
id: 'home',
},
resource,
)
) {
// regenerate home page
}
}
}
});
},
});
export default config;