fix(cms): expand recursive schema types when their nested items are opened
What is this contribution about?
#7899 stopped resolveSchema from re-expanding a $ref that is already on the current path. That fixed the hang on recursive commerce types (Product → hasVariant: Product[]), but the cut node lost its properties/items. Recursive data types broke as a result. A site's menu Item has children?: Item[], so the child items appear in the list, but each child opens as an empty form: only the multivariate variant/rule chrome shows and there are no fields to edit.
This change keeps the cut and makes it lazy:
resolve-schema.ts: the cut node now carriesrecursiveRef(the re-entered$ref), and the newresolveSchemaRef(ref, meta)builds that definition on its own.fields/resolved-schema-cache.ts:expandRecursiveSchemafills in the skipped level (properties/required/items) and keeps the field's own title and description. It caches the result per node, so re-renders get the same object back.renderFieldexpands cut array and object fields.ArrayFieldexpands a cut item schema (e.g.Product[]items). Each drill expands one level, and the next re-entry is cut again, so the hang guard still holds.
How did you verify your code works?
- I ran
resolveSchemaagainst the real/live/_metaof an affected site. Before the fix,navItems → desktop[] → childrenresolved to{ type: "array" }with noitems. After it,expandRecursiveSchemagives the child item and the grandchild item all their fields (label,flagNew,banner,countBadge,children,url,display). The whole header section still resolves in about 10ms. - New tests in
resolve-schema.test.ts: the cut node carriesrecursiveRefforProduct;resolveSchemaRefbuilds the skipped level and cuts the next re-entry again; a recursive array def (Item.children: Item[]) is marked and expands withtitleBy. - New tests in
fields/resolved-schema-cache.test.ts: the expansion keeps the field title, returns the same object on every call, and is a no-op withoutrecursiveReformeta. bun run verifypasses: 10865 tests, 0 failures.- Not run: a manual check in the Site Editor UI.
Screenshots/Demonstration
No screenshots: I didn't run the Site Editor against an affected site.
How to Test
- Open the Site Editor on a site whose section has a recursive array prop, e.g. a header menu whose
Itemhaschildren?: Item[]. - Open the nav items, open a top-level item, then click one of its "children" items.
- Expected: the child item's fields (text, URL, flag, banner, …) render and save. Before this fix the panel was empty below the variant rule.
Review Checklist
- PR title is clear and descriptive
- Changes are tested and working
- Documentation is updated (if needed)
- No breaking changes
🤖 Generated with Claude Code
Summary by cubic
Fixes recursive data-type forms that opened empty after #7899's recursion guard. When a recursive type re-entered itself (Product → hasVariant: Product[], menu Item with children?: Item[]), the cut node kept its type but lost its properties/items, so child items appeared in the list but each one rendered no fields.
The cut node now carries a recursiveRef, and the form fills in that skipped level on demand via the cached expandRecursiveSchema helper when renderField or ArrayField reaches it—restoring editable fields while keeping the recursion guard intact, one level at a time.
Bug Fixes
- Recursive object and array properties now render their nested fields instead of an empty panel.
- Re-expanding the same node returns a cached object, so re-renders get stable references.