diff --git a/packages/plugin-nested-docs/src/hooks/resaveChildren.ts b/packages/plugin-nested-docs/src/hooks/resaveChildren.ts index 114d097cec5..783cde5bab4 100644 --- a/packages/plugin-nested-docs/src/hooks/resaveChildren.ts +++ b/packages/plugin-nested-docs/src/hooks/resaveChildren.ts @@ -22,64 +22,91 @@ type ResaveArgs = { const resave = async ({ collection, doc, draft, pluginConfig, req }: ResaveArgs) => { const parentSlug = pluginConfig?.parentFieldSlug || 'parent' - const parentDocIsPublished = doc._status === 'published' - const children = await req.payload.find({ - collection: collection.slug, - depth: 0, - draft: true, - limit: 0, - locale: req.locale, - req, - where: { - [parentSlug]: { - equals: doc.id, - }, - }, - }) - const breadcrumbSlug = pluginConfig.breadcrumbsFieldSlug || 'breadcrumbs' - try { - for (const child of children.docs) { - const childIsPublished = - typeof collection.versions === 'object' && - collection.versions.drafts && - child._status === 'published' + if (draft) { + // If the parent is a draft, don't resave children + return + } else { + const initialDraftChildren = await req.payload.find({ + collection: collection.slug, + depth: 0, + draft: true, + limit: 0, + locale: req.locale, + req, + where: { + [parentSlug]: { + equals: doc.id, + }, + }, + }) - if (!parentDocIsPublished && childIsPublished) { - continue - } + const draftChildren = initialDraftChildren.docs.filter((child) => child._status === 'draft') - await req.payload.update({ - id: child.id, - collection: collection.slug, - data: { - ...child, - [breadcrumbSlug]: await populateBreadcrumbs(req, pluginConfig, collection, child), + const publishedChildren = await req.payload.find({ + collection: collection.slug, + depth: 0, + draft: false, + limit: 0, + locale: req.locale, + req, + where: { + [parentSlug]: { + equals: doc.id, }, - depth: 0, - draft: !childIsPublished, - locale: req.locale, - req, + }, + }) + + const childrenById = [...draftChildren, ...publishedChildren.docs].reduce((acc, child) => { + acc[child.id] = acc[child.id] || [] + acc[child.id].push(child) + return acc + }, {}) + + const sortedChildren = Object.values(childrenById).flatMap((group: JsonObject[]) => { + return group.sort((a, b) => { + if (a.updatedAt !== b.updatedAt) { + return a.updatedAt > b.updatedAt ? 1 : -1 + } + return a._status === 'published' ? 1 : -1 }) - } - } catch (err: unknown) { - req.payload.logger.error( - `Nested Docs plugin has had an error while re-saving a child document${ - draft ? ' as draft' : ' as published' - }.`, - ) - req.payload.logger.error(err) + }) + + if (sortedChildren) { + try { + for (const child of sortedChildren) { + const isDraft = child._status !== 'published' + + await req.payload.update({ + id: child.id, + collection: collection.slug, + data: { + ...child, + [breadcrumbSlug]: await populateBreadcrumbs(req, pluginConfig, collection, child), + }, + depth: 0, + draft: isDraft, + locale: req.locale, + req, + }) + } + } catch (err: unknown) { + req.payload.logger.error( + `Nested Docs plugin encountered an error while re-saving a child document.`, + ) + req.payload.logger.error(err) - // Use type assertion until we can use instanceof reliably with our Error types - if ( - (err as ValidationError)?.name === 'ValidationError' && - (err as ValidationError)?.data?.errors?.length - ) { - throw new APIError( - 'Could not publish or save changes: One or more children are invalid.', - 400, - ) + if ( + (err as ValidationError)?.name === 'ValidationError' && + (err as ValidationError)?.data?.errors?.length + ) { + throw new APIError( + 'Could not publish or save changes: One or more children are invalid.', + 400, + ) + } + } } } } @@ -90,20 +117,10 @@ export const resaveChildren = await resave({ collection, doc, - draft: true, + draft: doc._status === 'published' ? false : true, pluginConfig, req, }) - if (doc._status === 'published') { - await resave({ - collection, - doc, - draft: false, - pluginConfig, - req, - }) - } - return undefined } diff --git a/test/plugin-nested-docs/int.spec.ts b/test/plugin-nested-docs/int.spec.ts index defadf9534c..6c7359cd9b0 100644 --- a/test/plugin-nested-docs/int.spec.ts +++ b/test/plugin-nested-docs/int.spec.ts @@ -72,6 +72,7 @@ describe('@payloadcms/plugin-nested-docs', () => { title: `Child ${i + 1}`, slug: `child-${i + 1}`, parent: parentDoc.id, + _status: 'published', }, }) } @@ -83,6 +84,7 @@ describe('@payloadcms/plugin-nested-docs', () => { data: { title: '11 children updated', slug: '11-children-updated', + _status: 'published', }, }) @@ -90,7 +92,6 @@ describe('@payloadcms/plugin-nested-docs', () => { const { docs } = await payload.find({ collection: 'pages', limit: 0, - draft: true, where: { parent: { equals: parentDoc.id,