Skip to content

fix(sections-editor): fill union branch fields the depth cap emptied in a deep Flag<T> - #8438

Merged
viniciusventura29 merged 2 commits into
mainfrom
viniciusventura29/flag-plainschema-depth
Nov 10, 2026
Merged

viniciusventura29 merged 2 commits into
mainfrom
viniciusventura29/flag-plainschema-depth

Conversation

@viniciusventura29

@viniciusventura29 viniciusventura29 commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Resumo da mudança

Num campo com variantes (Flag<T>) aninhado fundo no form, os ramos de um union discriminado por type dentro de T voltam a mostrar seus campos. Hoje o select mostra o ramo escolhido, mas nenhum campo dele. Os demais campos com variantes não mudam.

1. Problema

Quem é afetado?
Quem edita no Studio um bloco em que um prop Flag<T> fica fundo no form (ex.: uma lista de itens dentro de um loader), e T traz um union discriminado por type (ex.: Media = Video | Image | NoMedia, ou Banner = NoBanner | SingleBanner | DoubleBanner).

Como são afetados?
A pessoa escolhe "Imagem" no select do union e nenhum campo aparece (Imagem, Largura, Altura, Texto alternativo). Não dá para preencher pelo form, nem num item novo nem num já preenchido.

Por que isso acontece?

  • apps/web/src/components/sections-editor/schema-form.tsx:325: o ramo isMultivariateBlockRef monta o form interno a partir do variantValueSchema (anyOfRefs[0].schema.properties.variants.items.properties.value).
  • Esse schema fica 3 níveis mais fundo que o plainSchema (ref → variants → items → value). Num caminho como loader → lista[] → content (flag) → variants[].value → desktop.media, os ramos do union passam do MAX_BUILD_PROPERTY_DEPTH = 8 (resolve-schema.ts:144, aplicado em resolve-schema.ts:637) e chegam com schema: undefined.
  • Ramo discriminado por type não tem resolução lazy, então o AnyOfField fica com nestedSchema null e não desenha nada.
  • O plainSchema (o ramo de T sem a flag) tem esses ramos completos, mas não dá para trocar um pelo outro no atacado. Os dois saem de definições brutas separadas do mesmo tipo, e o gerador pode emiti-las de jeitos diferentes. Num caso real, Product[] vem como seletor de loader numa e como lista inline na outra. A primeira versão deste PR preferia o plainSchema inteiro e transformava esse seletor num editor de lista.

2. Evidências visuais

Antes Depois
não capturado: o Chrome da sessão não respondeu, e o Studio local exige a stack do Docker não capturado: mesmo motivo

3. Cenários validados

  • Teste renderField – multivariate object fills depth-capped union branches: falha no origin/main (ramos []) e passa com o fix (bun test src/components/sections-editor/schema-form.test.ts).
  • Testes novos de fillDepthCappedBranches em fields/resolved-schema-cache.test.ts: preenche ramos discriminados vazios; mantém o que o schema já resolveu (seletor de loader × lista inline); não toca ramos vazios de union por módulo, que têm resolução lazy; devolve o mesmo objeto para as mesmas entradas.
  • Suíte do sections-editor: 1716 pass, 0 fail (bun test src/components/sections-editor/).
  • Varredura em 81 sites reais (TanStack e Fresh, pelo /deco/meta público). Rodei o resolveSchema desta branch em todos os blocos do manifest e comparei, em cada campo com variantes, o schema interno antes e depois:
    • 37 778 campos com variantes: 37 773 idênticos, 0 com forma diferente;
    • 5 só ganham ramos que antes vinham sem schema, todos num único site: o union de mídia em dois loaders de lista e o union de banner de um menu de navegação.
    • Com a primeira versão (preferir o plainSchema inteiro), o mesmo site tinha 4 campos com forma diferente: o seletor de loader virava lista. A versão atual zera isso.
  • bun run fmt, bun run lint, bun run knip: exit 0.
  • tsc --noEmit do apps/web (bun run check): exit 0.
  • Etapa bun run test do monorepo inteiro: rodada só na primeira versão, que saiu com exit 1 por ECONNREFUSED em :5432/:4222 (Postgres e NATS fora do ar nesta máquina) e EMFILE do --parallel, nenhuma falha no sections-editor. Não reproduzi no origin/main. Fica com o CI.
  • Abrir o bloco no Studio, escolher Imagem e Vídeo e ver os campos. Não executado: sem stack local do Studio nesta sessão. Dá para conferir no preview do PR.

4. Resultado

  • Problema: os ramos de um union discriminado dentro de Flag<T> profundo chegam sem schema, e o form não mostra os campos do ramo escolhido.
  • Solução: fillDepthCappedBranches (fields/resolved-schema-cache.ts) mantém o variantValueSchema como base e copia do plainSchema só os ramos de union discriminado por type que chegaram sem schema. O resultado fica em cache por par de nós (WeakMap) e devolve o próprio schema quando não há ramo vazio.
  • Impacto esperado: os campos desses ramos voltam a aparecer. Pela varredura, nenhum outro campo com variantes muda.
  • Riscos: um ramo preenchido vem da outra definição bruta; se ela divergir dentro do ramo, o ramo mostra a versão do plainSchema, o que ainda é melhor que nenhum campo. Ficaram de fora a checagem manual no Studio, as screenshots e a suíte completa com Postgres/NATS (seção 3).

🤖 Generated with Claude Code

A multivariate field built its inner form from the variant value schema,
which sits 3 levels deeper than plainSchema. Deep in a form, the depth cap
leaves the branches of a type-discriminated union in T without a schema,
so picking a branch drew no fields. Prefer plainSchema, the same T built
outside the depth cap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the claude PR authored by a coding agent label Nov 10, 2026
plainSchema and the variant value come from separate raw definitions of the
same type, and the generator can emit them differently (an inline list in one,
a loader picker in the other). Preferring plainSchema wholesale turned such a
picker into a list editor. Keep the variant value and take from plainSchema
only the type-discriminated branches that resolved without a schema.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@viniciusventura29 viniciusventura29 changed the title fix(sections-editor): show union branch fields inside a deep Flag<T> fix(sections-editor): fill union branch fields the depth cap emptied in a deep Flag<T> Nov 10, 2026
@viniciusventura29
viniciusventura29 merged commit c552175 into main Nov 10, 2026
23 checks passed
@viniciusventura29
viniciusventura29 deleted the viniciusventura29/flag-plainschema-depth branch November 10, 2026 23:21
decocms Bot pushed a commit that referenced this pull request Nov 10, 2026
PR: #8438 fix(sections-editor): fill union branch fields the depth cap emptied in a deep Flag<T>
Bump type: patch

- decocms (apps/api/package.json): 4.570.0 -> 4.570.1

Deploy-Scope: web
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

claude PR authored by a coding agent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant