Skip to content

Transform must resolve component dependencies before emitting #376

Description

@nathanacurtis

Sub-issue of #229.

A spec names other components in two ways, and specs transform currently honours neither when deciding what to build or in what order:

  • Nested instances — an element with instanceOf pointing at a sibling component
  • Bound primitives — a text, glyph or container element resolved to this platform's designated component (ADR-074)

transform walks components in name order and emits each in isolation. Two failures follow.

1. Output depends on alphabetical order

Primitive resolution originally tested for the target's generated scaffold on disk. A component whose name sorts before its dependency found no scaffold and silently skipped the binding — so an image component processed before the layout component it binds to emitted a host div instead.

Measured on a real catalogue, this silently dropped roughly a third of all bindings: 57 of 86 components bound in React, 54 of 83 in Web Components. A second consecutive run "fixed" different ones.

Worked around for now by testing for the target's api.yaml, which generate writes before any transform runs. That makes correctness order-independent, but it is a sidestep: it proves the dependency exists rather than that it has been built.

2. A scoped run emits references to components it did not build

specs transform --components card transforms exactly one component, while its generated stories import five others — image, favorite button, badge, scrim, paging carousel. The output references components the run never built, and is only usable because a previous unscoped run happened to leave them on disk.

What this asks for

A resolved dependency graph as a first-class step between generate and transform:

  • Collect each component's dependencies from instanceOf references and from the platform's primitive bindings
  • Transform in dependency order, so a component's dependencies are always emitted before it
  • For a scoped run, either pull in the dependency closure or fail naming what is missing — never emit references to components that were not built
  • Detect and report cycles rather than looping

Why order matters beyond correctness

Order-independence via api.yaml only permits emitting a reference. A transform that could read an already-built dependency could do more — validating that a prop value is in the target's accepted set, for instance, rather than passing it through and hoping. That is only available once the dependency is guaranteed built.

Acceptance

  • Transforming a component whose dependencies are absent either builds them first or fails with a message naming them
  • Two consecutive full runs produce byte-identical output
  • A scoped run produces no reference to a component outside the built set

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

clispecs-cli commandsreact-from-specsTransformer from specs into React codewebcomponents-from-specsTransformer from specs into web components code

Type

No type

Fields

Priority

Low

Projects

  • Status
    Backlog

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions