Skip to content

feat: add plugin-aware component discovery - #524

Open
Mohamed Mansour (mohamedmansour) wants to merge 3 commits into
mainfrom
mohamedmansour/plugin-aware-discovery
Open

feat: add plugin-aware component discovery#524
Mohamed Mansour (mohamedmansour) wants to merge 3 commits into
mainfrom
mohamedmansour/plugin-aware-discovery

Conversation

@mohamedmansour

@mohamedmansour Mohamed Mansour (mohamedmansour) commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Component discovery should follow the selected plugin without making filename-only applications pay for FAST metadata work. This separates the default filesystem convention from FAST's manifest-driven discovery and makes npm package/scope resolution predictable.

Changes

  • Derive default WebUI/none component names from HTML filenames, with matching CSS and TS/JS siblings.
  • Make package metadata loading, parsing, and cache hashing opt-in. FAST ownership and export/CEM processing stay on the FAST path.
  • Resolve FAST manifest declarations using only converted *.template-webui.html assets. Raw *.template.html files are not accepted as a substitute; ordinary <component-name>.html app components remain supported.
  • Preserve symlinked package lookup, search ancestors for requested packages/scopes, support collection spellings, and surface failures in declared components.
  • Keep generic/default discovery in plugin/mod.rs and FAST-specific behavior and documentation under plugin/fast.

Validation

  • Standalone cargo xtask check.
  • Public discovery regressions for metadata isolation, naming, cache inputs, scoped lookup, and strict FAST variant selection.
  • FAST 2 and FAST 3 build/render coverage for converted package templates and ordinary app-folder HTML.
  • Real-package verification confirms converted template bytes are selected; packages with only raw FAST templates report an actionable error.

This is the base layer of the split. WebUI Press content mode is the separate dependent PR #525.

Keep default component discovery filename-based and metadata-free. Resolve FAST manifest declarations through converted template-webui assets while preserving ordinary HTML fallback, scoped package lookup, and actionable errors.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved critical and moderate findings affect cache safety, package-path validation, and FAST metadata handling.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds plugin-aware component discovery, separating native filename discovery from FAST manifest-based discovery.

Changes:

  • Adds catalog scanning, package/scope resolution, and metadata-aware caching.
  • Restricts FAST discovery to converted template assets with fallback support.
  • Updates documentation, tests, fixtures, and plugin contracts.
File summaries
File Reviewed change
docs/guide/concepts/components/index.md Documents native package discovery.
docs/guide/cli/index.md Updates CLI discovery guidance.
docs/ai.md Adds component discovery guidance.
DESIGN.md Defines discovery contracts and behavior.
crates/webui/src/tests/fast.rs Adds FAST integration coverage.
crates/webui-discovery/tests/scopes.rs Tests scoped resolution and fallbacks.
crates/webui-discovery/tests/metadata.rs Tests metadata isolation and caching.
crates/webui-discovery/tests/catalog.rs Tests catalog and FAST asset discovery.
crates/webui-discovery/src/plugin/mod.rs Defines the plugin contract and native discovery.
crates/webui-discovery/src/plugin/fast/tests.rs Adds FAST unit coverage.
crates/webui-discovery/src/plugin/fast/README.md Documents FAST discovery.
crates/webui-discovery/src/plugin/fast/mod.rs Implements FAST-specific discovery.
crates/webui-discovery/src/npm.rs Refactors package resolution and metadata handling.
crates/webui-discovery/src/lib.rs Registers discovery modules.
crates/webui-discovery/src/catalog.rs Implements filename-based catalog scanning.
crates/webui-discovery/src/cache.rs Supports optional metadata fingerprints.
crates/webui-discovery/README.md Documents discovery conventions.
crates/webui-cli/src/commands/build.rs Updates discovery fixtures.
.gitignore Ignores macOS metadata files.
Review details

Suppressed comments (5)

crates/webui-discovery/README.md:32

  • The new public API/behavior leaves docs/guide/concepts/plugins/index.md describing the removed .template.html FAST layout and the old DiscoveryPlugin trait; its example lacks requires_package_metadata and supports_package. Developers following that canonical guide will implement or author against a contract this PR no longer accepts. Update that public guide alongside this change.
Plugin-specific behavior is documented in the [FAST discovery guide](src/plugin/fast/README.md).

crates/webui-discovery/src/catalog.rs:71

  • These dependencies are enumerated only from HTML files that already exist. Because DiscoveryCache::fingerprint hashes only this returned list, adding a new <component-name>.html (or nested directory) leaves the list and fingerprint unchanged, so an old cache entry is returned and the new component is invisible until another tracked file changes. Include a deterministic catalog-membership input (or otherwise invalidate when the catalog directory changes) before caching discovery results.
pub(crate) fn cache_files(root: &Path) -> Result<Vec<PathBuf>> {
    cache_files_matching(root, |_| true)
}

pub(crate) fn cache_files_matching(
    root: &Path,
    include: impl Fn(&Path) -> bool,
) -> Result<Vec<PathBuf>> {
    let mut files = Vec::new();
    for template in templates(root) {
        let template = template?;
        if !include(&template) {
            continue;
        }
        for extension in ["css", "ts", "js"] {
            files.push(template.with_extension(extension));
        }
        files.push(template);

crates/webui-discovery/src/catalog.rs:118

  • has_sibling_script only checks try_exists(), so a directory named <tag>.ts or <tag>.js is treated as authored even though it is not a sibling script file. In npm discovery these same paths are also fingerprinted and fs::read then fails on the directory, so a non-file sidecar either changes ownership or breaks discovery; require the candidates to be regular files while preserving metadata errors.
            is_client_owned: has_sibling_script(&template)?,

crates/webui-discovery/src/plugin/fast/mod.rs:127

  • This branch treats every customElements manifest with no parsed declarations as an ordinary fallback, but declarations() returns an empty list for malformed shapes such as a missing or non-array modules field. That lets an invalid FAST manifest build successfully when an ordinary HTML file exists, contrary to the documented contract that malformed metadata is an error; distinguish a valid empty inventory from malformed metadata before taking this fallback.
    docs/guide/concepts/components/index.md:210
  • This behavior change leaves docs/guide/concepts/plugins/index.md:152-166 describing FAST files and CEM mappings with the rejected .template.html suffix. That page is linked from the component guide, so FAST package authors can still follow stale instructions and select the raw variant that this PR explicitly rejects; update the plugin guide to the .template-webui.html and current export/fallback rules.
Install the package into `node_modules/`. Default WebUI discovery derives the
component name from each hyphenated `<component-name>.html` filename, exactly as
for local components. It scans the package's `components/` directory when present,
otherwise the package root. Nested directories are supported; a directory does
  • Files reviewed: 18/19 changed files
  • Comments generated: 6
  • Review effort level: Lite

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread crates/webui-discovery/src/cache.rs
Comment thread crates/webui-discovery/src/npm.rs
Comment thread crates/webui-discovery/src/catalog.rs
Comment thread DESIGN.md
Comment thread docs/ai.md Outdated
Comment thread docs/guide/cli/index.md
Stream dependency fingerprints through a reused bounded buffer, validate npm source identifiers before filesystem lookup, and align the discovery documentation with plugin-selected cache inputs.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: bf3fdbed-b6e0-4b3e-8b29-667f44831c4e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants