Skip to content

fix: clone embedded Rich Text entries [] - #10765

Draft
Mitch Goudy (mgoudy91) wants to merge 3 commits into
masterfrom
codex/deep-clone-rich-text
Draft

fix: clone embedded Rich Text entries []#10765
Mitch Goudy (mgoudy91) wants to merge 3 commits into
masterfrom
codex/deep-clone-rich-text

Conversation

@mgoudy91

Copy link
Copy Markdown
Contributor

Summary

Deep Clone currently skips embedded entry references inside Rich Text fields, which leaves cloned documents pointing at the original embedded entries. This change teaches the cloner to traverse Rich Text nodes so embedded entry blocks and inline embedded entries are discovered, cloned, and rewritten to the cloned targets.

Changes

  • recurse through Rich Text document nodes when collecting entry references for deep cloning
  • rewrite embedded entry targets inside Rich Text during the reference update pass
  • add unit coverage for embedded entry block and inline entry cloning while leaving embedded assets unchanged

Notes

This came out of a support-thread investigation where the current behavior looked surprising for customers using Deep Clone on Rich Text-heavy models.

Updated in:

  • apps/deep-clone

@mgoudy91
Mitch Goudy (mgoudy91) requested a review from a team as a code owner March 26, 2026 16:07
Copilot AI review requested due to automatic review settings March 26, 2026 16:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the deep-clone app to correctly deep-clone and rewrite embedded Entry references inside Rich Text fields, and adds configurability to the closest-preview app for which field id identifies “previewable” (page/root) entries.

Changes:

  • Deep Clone: traverse Rich Text node trees to discover embedded entry links and rewrite them to cloned targets during the update pass.
  • Deep Clone: add unit coverage for embedded-entry-block and embedded-entry-inline cloning (while leaving embedded assets unchanged).
  • Closest Preview: introduce an installation parameter (slugFieldId) to configure the “preview field”, and thread it through content-type filtering + root-entry detection with updated tests/mocks.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
apps/deep-clone/src/utils/EntryCloner.ts Adds Rich Text traversal + embedded entry target rewriting during clone/update passes.
apps/deep-clone/test/utils/EntryCloner.spec.ts Adds unit test ensuring embedded entry links in Rich Text are cloned/rewritten and assets are left unchanged.
apps/closest-preview/src/types.ts Adds installation parameter typing and a default slug field constant.
apps/closest-preview/src/utils/livePreviewUtils.ts Makes “slug field” configurable in filtering and live preview detection; reads from installation parameters.
apps/closest-preview/src/locations/ConfigScreen.tsx Adds UI + persistence for configuring the preview field id.
apps/closest-preview/src/components/ContentTypeMultiSelect.tsx Threads slugFieldId into content type filtering and stabilizes default excluded list.
apps/closest-preview/test/mocks/mockSdk.ts Extends SDK mock to include installation parameters.
apps/closest-preview/test/mocks/mockCma.ts Extends CMA mock content types/entries with a url field used by new tests.
apps/closest-preview/test/locations/Sidebar.spec.tsx Adds coverage that configured preview field id is honored when finding root entries.
apps/closest-preview/test/locations/ConfigScreen.spec.tsx Adds coverage for loading/saving custom preview field id and failure-to-load behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +164 to +190
if (Array.isArray(fieldValue)) {
await Promise.all(
fieldValue.map((f: any) => {
return this.inspectField(f);
fieldValue.map((nestedValue) => {
return this.inspectField(nestedValue);
})
);
return;
}

if (this.isReference(fieldValue)) {
await this.findReferences(fieldValue.sys.id);
return;
}

if (this.isRichTextNode(fieldValue)) {
const embeddedEntryTarget = this.getEmbeddedEntryTarget(fieldValue);
if (embeddedEntryTarget) {
await this.findReferences(embeddedEntryTarget.sys.id);
}

if (Array.isArray(fieldValue.content)) {
await Promise.all(
fieldValue.content.map((nestedValue) => {
return this.inspectField(nestedValue);
})
);
}

Copilot AI Mar 26, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inspectField now traverses all arrays (including rich text content) using Promise.all, which can fan out into a large number of concurrent findReferences calls (and thus CMA entry.get requests) for Rich Text-heavy entries. Consider limiting concurrency (e.g., a queue/p-limit) or switching these deep traversals to a sequential for...of to reduce the risk of rate limiting/timeouts when cloning large documents.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Rich Text traversal now walks arrays and rich-text content sequentially instead of fanning out nested Promise.all calls, and I added regression coverage that fails if embedded-entry fetches overlap.

Comment on lines +6 to +10
export interface AppInstallationParameters {
slugFieldId?: string;
}

export const DEFAULT_SLUG_FIELD_ID = 'slug';

Copilot AI Mar 26, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description notes updates only in apps/deep-clone, but this PR also changes apps/closest-preview (new installation parameter + filtering logic + tests). Please either update the PR description/title/scope to reflect Closest Preview changes, or split these into a separate PR to keep review and release impact clear.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is valid and I am not treating it as ignorable. The PR currently mixes Deep Clone and Closest Preview changes, so before merge it should either be split into focused PRs or have its title/description updated to reflect the full scope.

@mgoudy91
Mitch Goudy (mgoudy91) marked this pull request as draft March 26, 2026 18:30
Support Deep Clone traversing embedded entry references inside Rich Text so cloned documents point at cloned entries instead of the originals.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants