Skip to main content

Getting Started

Installation

caution

The major version of the plugin must match the major version of the Payload.

npm install payload-dependency-graph

Configuration

In the plugins array of your Payload config, call the plugin with options:

src/payload.config.ts
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.

caution

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.

info

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;