👀 Our most exciting product launch yet 🚀 Join us May 8th for Sanity Connect

How to add multiple custom document actions in Sanity plugins

13 replies
Last updated: Apr 12, 2021
Hello, I am about to create a second plugin to add a document action. How can I make sure the second plugin does not overwrite the first plugin?
I used this documentation to create the first one:
https://www.sanity.io/docs/document-actions
It seems there is no way to reference the previously implemented
sanity/base/document-actions/resolver
part. I might have missed some documentation, so any pointers would be helpful.
Apr 12, 2021, 12:31 PM
Hey there! The resolver you created will work with m
Apr 12, 2021, 5:19 PM
Hey there! The
resolver
you previously created will work with multiple custom document actions.
The document action resolver provides you with a central place to make decisions about the collection of actions enabled for a given document state. 
To add another action, you would need to import the action into your
resolver
file, then add it to the array you’re returning in your
resolveDocumentActions
function.
Apr 12, 2021, 5:22 PM
Hmm, maybe I didn't explain good enough (or simple don't understand).
I envision two isolated plugins that are not aware of each other. Both want to add a custom document action. The method described in the documentation however assumes there is only one implementation of
sanity/base/document-actions/resolver
. Is there a way to obtain a reference to other implementations of
sanity/base/document-actions/resolver
so I don't shadow the implementation of another plugin?
Or maybe I should go about this another way.
Apr 12, 2021, 6:58 PM
I believe you may not be understanding. You do not need to create multiple resolvers. You use a single resolver for all of the custom actions you’ve created. The different actions you’ve created would not need to be aware of each other. They just need to be added to the array your resolver returns.
Apr 12, 2021, 7:14 PM
I still don't understand (sorry).
Plugin 1 implements
sanity/base/document-actions/resolver
and adds an action. Plugin 2 also implements
sanity/base/document-actions/resolver
and also adds an action. Will sanity use all implementations of
sanity/base/document-actions/resolver
and compare the arrays?
Apr 12, 2021, 7:18 PM
Ok, let’s see if I can help clear this up. Can you show me the parts in your sanity.json that refer to those two plugins?
Apr 12, 2021, 7:21 PM
Ok, let’s see if I can help clear this up. Can you show me the parts in your sanity.json that refer to those two plugins?
Apr 12, 2021, 7:21 PM
As well as your resolve document actions file, come to think of it.
Apr 12, 2021, 7:22 PM
I haven't written it yet. But it would be like this:
plugin 1

"parts": [ 
  ... 
  { 
    "implements": "part:@sanity/base/document-actions/resolver", 
    "path": "resolveDocumentActions.js" 
  } 
]
plugin 2

"parts": [ 
  ... 
  { 
    "implements": "part:@sanity/base/document-actions/resolver", 
    "path": "resolveDocumentActions.js" 
  } 
]
project
sanity.json

"plugins": [
  ...
  "plugin1",
  "plugin2"
],

Apr 12, 2021, 7:42 PM
OK, so your
resolveDocumentActions.js
for both of those plugins would be the same file. It would look something like this:
import defaultResolve from 'part:@sanity/base/document-actions'

import {pluginOneAction} from './path/to/pluginOneAction'
import {pluginTwoAction} from './path/to/pluginTwoAction'

export default function resolveDocumentActions(props) {
  return [defaultResolve, pluginOneAction, pluginTwoAction]
}
Apr 12, 2021, 8:04 PM
OK, so your
resolveDocumentActions.js
for both of those plugins would be the same file. It would look something like this:
import defaultResolve from 'part:@sanity/base/document-actions'

import {pluginOneAction} from './path/to/pluginOneAction'
import {pluginTwoAction} from './path/to/pluginTwoAction'

export default function resolveDocumentActions(props) {
  return [defaultResolve, pluginOneAction, pluginTwoAction]
}
Apr 12, 2021, 8:04 PM
Also note, if you only want to show an action under certain conditions, you could conditionally show them using this .
Apr 12, 2021, 8:05 PM
I was afraid this would be the case. So in every project where I would like to use plugins that provide document actions I need to implement a resolver... I hoped there would be a built-in way to prevent that.
I guess my best option is to write a custom document actions plugin that does something like this:


"parts": [ 
  ... 
  { 
    "implements": "part:@sanity/base/document-actions/resolver", 
    "path": "resolveDocumentActions.js" 
  },
  {
    "name": "part:@kaliber/document-actions/resolver",
    "description": "..."
  }
]

// resolveDocumentActions.js
import defaultResolve from 'part:@sanity/base/document-actions'
import resolvers from 'all:@kaliber/document-actions/resolver'

export default function resolveDocumentActions(props) {
  return resolvers.reduce(
    (result, resolver) => resolver(props, result),
    defaultResolve(props)
  )
}
This is just an example of how it could be solved. I'm not sure what a smart API would look like since I did not have time to think about it yet. That was why I was hoping there would be another way to access other implementations of the same part. Maybe you could check if this pattern has been encountered before and has a 'Sanity preferred' way of solving.

Anyway, thank you for your time!
Apr 12, 2021, 10:23 PM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?