Skip to content

theme-graph CLI never calls getWebComponentMap, so custom-element references are never resolved #1291

Description

@Aidano-eg

Summary

bin/theme-graph declares a WebComponentMap, passes a getWebComponentDefinitionReference resolver built on it, but never calls getWebComponentMap — so the map is always empty and the resolver always returns undefined.

The result: custom-element references (<my-widget>) are never resolved to the asset that defines them, so an asset referenced only as a custom element is missing from the CLI's graph and looks like dead code.

Calling getWebComponentMap fixes it — verified below.

Versions

  • @shopify/theme-graph 0.3.2
  • @shopify/theme-check-common 3.29.0
  • Node 24.11.1, Windows 11

The code

bin/theme-graph:

/** @type {import('@shopify/theme-graph').WebComponentMap} */
const webComponentDefs = new Map();          // <- created empty

const dependencies = {
  // ...
  getWebComponentDefinitionReference: (customElementName) =>
    webComponentDefs.get(customElementName), // <- always undefined
};
$ grep -c getWebComponentMap bin/theme-graph
0

getWebComponentMap is exported from the package and works correctly; the CLI just never invokes it to populate the map.

Reproduction

sections/widget.liquid — custom element plus an explicit script tag

<script src="{{ 'my-widget.js' | asset_url }}" defer></script>
<my-widget></my-widget>
{% schema %}{"name":"widget"}{% endschema %}

sections/ce-only.liquid — custom element only, no explicit asset reference

<my-orphan-widget></my-orphan-widget>
{% schema %}{"name":"ce-only"}{% endschema %}

assets/my-widget.js

class W extends HTMLElement {}
customElements.define('my-widget', W);

assets/my-orphan-widget.js

class O extends HTMLElement {}
customElements.define('my-orphan-widget', O);
npx theme-graph minitheme > graph.json

Actual (CLI)

nodes: 8  edges: 6

IN GRAPH  my-widget.js          <- only because of the explicit asset_url script tag
ABSENT    my-orphan-widget.js   <- referenced as <my-orphan-widget>, not resolved

sections/ce-only.liquid is in the graph as a section entry point but has zero outbound edges.

With the map populated (library path)

Same theme, same buildThemeGraph, the only change being one added call:

const webComponentDefs = await getWebComponentMap(root, { fs: NodeFS, getSourceCode });
web components discovered: my-orphan-widget, my-widget
nodes: 9  edges: 8

IN GRAPH  my-widget.js
IN GRAPH  my-orphan-widget.js    <- now resolved

So the resolution logic is correct and complete; only the CLI's wiring is missing.

Suggested fix

In bin/theme-graph, replace the empty map with a populated one:

const webComponentDefs = await getWebComponentMap(rootUri, {
  fs: NodeFileSystem,
  getSourceCode,
});

(after the preload, so the source-code cache is warm).

Why it matters

Custom-element-per-component is the dominant architecture in current commercial themes. On a production Clean Canvas Enterprise 2.3.0 theme, four assets (side-drawer.js, quantity-input.js, quantity-input.css, product-recommendations.js) were referenced only via their custom-element tags and were absent from the CLI graph — indistinguishable from genuinely dead assets.

Since the VS Code extension's dependencies / references / dead-code features are built on this graph, anything consuming the CLI output will report these as unused. Related failure mode to #1279 and to #1290 (the parse-error case).

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions