Skip to content

Local API draft parameter documentation unclear and misleadingΒ #13393

@cideM

Description

@cideM

The documentation states that:

specify if you are creating or updating a draft, or if you're just sending your changes straight to the published document.

The example below that paragraph uses it like this:

await payload.create({
  collection: 'your-collection',
  data: {
    // your data here
  },
  draft: true, // This is required to create a draft
})

If I use the test/_community playground to simulate this, I get very unexpected and confusing results. I'll attach the code snippet I use at the end of this post, so it doesn't clutter the text.

If I take the documentation at face value, setting draft: false should send my changes straight to the published document. But p.create({ collection: postsSlug, draft: false, data: { title: "hello" }, req }) results in a _status: "draft" document in posts and _posts_versions. There is no published document. Unless "published document" here doesn't refer to the _status at all, and just means the posts collection.

Now let's set draft: true. p.create({ collection: postsSlug, draft: true, data: { title: "hello" }, req }) gives me exactly the same database state as the previous call. One document in each collection, both with _status: draft. At least this database state makes sense, somehow. There's no published document, since I was writing to a draft.

What if I add _status to the mix? Making the same call as above but with status set to "published", p.create({ collection: postsSlug, draft: true, data: { title: "hello", _status: "published" }, req }) results in a published document. So I guess the draft: true was overridden by _status?

In fact, the only scenario where the draft parameter plays the pivotal role that is ascribed to it in the documentation, is when you create a published document, and then make an update call without an explicit status. Here, draft: true leaves the published document untouched, draft: false changes it.

I also considered that the draft parameter's issues might be limited to create, but that's not the case. Creating a published document and updating it with draft: true while also setting _status: "published" changes the published document. Again, the draft parameter is overridden by _status.

The documentation of the draft parameter should explain the interaction between draft and _status. The documentation should be exhaustive, and list all combinations, including null/undefined. Accidentally publishing or unpublishing something is quite unfortunate, so I think the documentation for this part specifically should be as unambiguous as possible.


Replace test/_community/collections/Posts/index.ts with this new snippet. Then run the playground with START_MEMORY_DB=true pnpm dev _community. In your terminal, you'll see the usual Payload startup messages, and 3 console.log messages:

  • running hook
  • the content of the posts collection
  • the content of the _posts_versions collection
import type { CollectionConfig } from 'payload'

export const postsSlug = 'posts'

export const PostsCollection: CollectionConfig = {
  slug: postsSlug,
  versions: {
    drafts: true,
  },
  admin: {
    useAsTitle: 'title',
  },
  fields: [
    {
      name: 'title',
      type: 'text',
    },
  ],
  hooks: {
    beforeChange: [
      async ({ collection, data, req, context }) => {
        if (context.foo) {
          return data
        }

        console.log('running hook')
        const p = req.payload

        const doc = await p.create({
          collection: postsSlug,
          draft: false,
          data: {
            title: 'hello',
          },
          context: {
            foo: true,
          },
          req,
        })

        await p.update({
          collection: postsSlug,
          id: doc.id,
          draft: false,
          data: {
            title: 'again',
          },
          context: {
            foo: true,
          },
          req,
        })

        const posts = await req.payload.db.find({
          collection: 'posts',
          limit: 0,
          req,
        })
        console.log(posts.docs)

        const postsVersions = await req.payload.db.findVersions({
          collection: 'posts',
          limit: 0,
          req,
        })
        console.log(postsVersions.docs)

        return data
      },
    ],
  },
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions