🐞 fix(resolver): Fixing circular-reference handling to avoid call stack errors#340
Open
Charles Hudson (phobetron) wants to merge 1 commit into
Open
Conversation
…ck errors ## Summary Fixes circular-reference handling in optimized Contentful entry resolution by making generic Contentful entry fields pass-through data during schema validation. Resolved Contentful graphs can contain repeated or circular references, especially through rich-text `data.target` links. Previously, `EntryFields` used `z.json()`, which recursively walked arbitrary consumer fields. When `resolveOptimizedEntry` validated a selected optimization path against an entry graph containing cycles, Zod could overflow the stack and cause personalization resolution to fail. ## Changes - Changed `EntryFields` from recursive JSON validation to pass-through field validation with `z.any()`. - Updated schema documentation to clarify that consumer-defined Contentful fields are intentionally not strongly validated by SDK schemas. - Added schema tests proving: - arbitrary/circular consumer fields are accepted without recursive traversal; - Contentful `sys` metadata is still validated; - SDK-owned optimization fields such as `nt_config` and `nt_experiences` are still validated. - Added resolver regression coverage for circular Contentful-like graphs: - unrelated rich-text linked-entry cycles under the baseline graph; - rich-text linked-entry cycles inside the selected variant entry. ## Rationale The SDK only needs to validate and inspect SDK-owned fields and Contentful structural metadata. Consumer-authored entry fields can contain resolved Contentful entries, rich-text documents, assets, and repeated references. Treating those fields as JSON-only data is too strict for real resolved CDA graphs and can trigger recursive validation failures. This change keeps validation where it matters while avoiding traversal of arbitrary consumer content graphs. ## Validation - `pnpm exec eslint ...` on touched files - `pnpm exec prettier --check ...` on touched files - `pnpm --filter @contentful/optimization-api-schemas typecheck` - `pnpm --filter @contentful/optimization-api-schemas test:unit` - `pnpm --filter @contentful/optimization-api-client typecheck` - `pnpm --filter @contentful/optimization-core typecheck` - `pnpm --filter @contentful/optimization-core exec rstest run src/resolvers/OptimizedEntryResolver.test.ts` - `pnpm --filter @contentful/optimization-core test:unit` - `pnpm --filter @contentful/optimization-api-schemas size:check` - `pnpm --filter @contentful/optimization-api-client size:check` - `pnpm --filter @contentful/optimization-core size:check` [[NT-3567](https://contentful.atlassian.net/browse/NT-3567)]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes circular-reference handling in optimized Contentful entry resolution by making generic Contentful entry fields pass-through data during schema validation.
Resolved Contentful graphs can contain repeated or circular references, especially through rich-text
data.targetlinks. Previously,EntryFieldsusedz.json(), which recursively walked arbitrary consumer fields. WhenresolveOptimizedEntryvalidated a selected optimization path against an entry graph containing cycles, Zod could overflow the stack and cause personalization resolution to fail.Changes
EntryFieldsfrom recursive JSON validation to pass-through field validation withz.any().sysmetadata is still validated;nt_configandnt_experiencesare still validated.Rationale
The SDK only needs to validate and inspect SDK-owned fields and Contentful structural metadata. Consumer-authored entry fields can contain resolved Contentful entries, rich-text documents, assets, and repeated references. Treating those fields as JSON-only data is too strict for real resolved CDA graphs and can trigger recursive validation failures.
This change keeps validation where it matters while avoiding traversal of arbitrary consumer content graphs.
Validation
pnpm exec eslint ...on touched filespnpm exec prettier --check ...on touched filespnpm --filter @contentful/optimization-api-schemas typecheckpnpm --filter @contentful/optimization-api-schemas test:unitpnpm --filter @contentful/optimization-api-client typecheckpnpm --filter @contentful/optimization-core typecheckpnpm --filter @contentful/optimization-core exec rstest run src/resolvers/OptimizedEntryResolver.test.tspnpm --filter @contentful/optimization-core test:unitpnpm --filter @contentful/optimization-api-schemas size:checkpnpm --filter @contentful/optimization-api-client size:checkpnpm --filter @contentful/optimization-core size:check[NT-3567]