Skip to content

UN-4286 [FEAT] Add the v1 plugin manifest, slots and build check - #2394

Open
athul-rs wants to merge 11 commits into
UN-4270-v1-scaffoldfrom
UN-4286-plugin-manifest
Open

athul-rs wants to merge 11 commits into
UN-4270-v1-scaffoldfrom
UN-4286-plugin-manifest

Conversation

@athul-rs

@athul-rs athul-rs commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

What

  • Plugin manifest, slots and registry for Frontend v1 (P0-T07): a plugin declares the routes and slot fillers it adds in plugins/<id>/manifest.ts; shell and pages render <Slot id="…"> from @v1/lib/plugins.
  • plugins/index.ts discovers manifests with import.meta.glob, keeps those for the current VITE_DISTRIBUTION, and builds the registry. PluginProvider hands the slot renderer to lib/ through context, so lib/ keeps importing only lib/.
  • A build check (scripts/v1-plugins.mjs) fails the build when two plugins fill a single-filler slot or claim the same route.
  • .gitignore keeps overlaid cloud plugins out of OSS commits; the frontend Docker build passes VITE_DISTRIBUTION through.

Why

How

  • A slot with no filler renders its fallback, so OSS shows nothing where a cloud plugin would sit. A filler that throws is caught per slot and reported, and the rest of the page renders.
  • skipLibCheck in src/v1/tsconfig.json now comes from the scaffold (UN-4270 [FEAT] v1 scaffold, strict TypeScript and import boundary #2380, 664d1cf), which settled the @types/chai / vitest containSubset clash. This branch merged the scaffold and takes its tsconfig, so the earlier temporary commit no longer changes anything. The scaffold's new rule against dynamic imports it cannot analyse is met by missing-import.test.ts (a template whose fixed prefix names the folder).

Can this PR break any existing features. If yes, please list possible items. If no, please explain why. (PS: Admins do not merge the PR without this section filled)

  • No. Everything is under frontend/src/v1/, which no v0 route renders. Outside it: a .gitignore rule for frontend/src/v1/plugins/*, a VITE_DISTRIBUTION build arg (defaults to OSS behaviour when unset) and a Vite plugin that only inspects src/v1/plugins.

Database Migrations

  • None.

Env Config

  • VITE_DISTRIBUTION (build time, optional). Unset means OSS.

Relevant Docs

  • frontend/src/v1/README.md, section "Plugins".

Related Issues or PRs

Dependencies Versions

  • None.

Notes on Testing

  • bun run typecheck:v1, lint:v1, test:v1: clean; 20 vitest tests and 50 node tests (the scaffold's fixtures plus this PR's build-check and CLI tests).
  • The cloud overlay tests (unstract-cloud#1896) pass 7/7 against this branch. The check runs under Bun with no dependencies installed, as the cloud CI overlay step needs.
  • Frontend CI (typecheck, vitest, biome) runs once this PR targets main, i.e. after UN-4270 [FEAT] v1 scaffold, strict TypeScript and import boundary #2380 merges. The commands above were run locally.
  • The fixture tests cover the build check: duplicate route, two fillers on a single slot, a manifest for another distribution.

Screenshots

None: no UI.

Checklist

I have read and understood the Contribution Guidelines.

🤖 Generated with Claude Code

athul-rs and others added 5 commits October 27, 2026 18:03
v1 finds plugins at build time from src/v1/plugins/<id>/manifest.ts, which
the cloud overlay copies in. An absent plugin has no manifest, so its
slots show their fallbacks with no error; any other load or render error
is reported, and each slot has its own error boundary.

- lib/plugins: the typed slot contract, buildRegistry (distribution
  filter plus conflict checks for every distribution), <Slot> and
  pluginRoutes(). VITE_DISTRIBUTION picks oss, cloud or onprem.
- scripts/v1-plugins.mjs runs in every Vite build: a slot filled twice, a
  route defined twice or a plugin with no distribution fails the build,
  and the distribution matrix is published as plugin-matrix.json.
- v0's optional-plugin stub no longer applies under src/v1, where it
  turned a missing module into an empty object instead of an error.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The cloud workflows set it to cloud or onprem; the default, oss, keeps the
public image unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The cloud overlay copies plugins into frontend/src/v1/plugins/; ignore
them as frontend/src/plugins/* already is, keeping only the .gitkeep.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
… lib through context

The scaffold allows lib/ to import only lib/, and only plugins/ may see the
overlaid manifests. plugins/index.ts now builds the registry and exports
PluginSlot and pluginRoutes(); lib/plugins keeps the contract and a Slot that
reads PluginSlot from PluginProvider, which app/ will mount. With no provider
every slot shows its fallback.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…hai clash

TEMPORARY. With skipLibCheck off, @types/chai 5.2.3 and vitest 3.2.6 both
declare Chai containSubset, so typecheck:v1 fails once any v1 test imports
vitest. Drop this commit when #2380 settles it (pin @types/chai or turn the
option on).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Comment thread frontend/scripts/v1-plugins.mjs Fixed
athul-rs and others added 3 commits October 28, 2026 12:11
…ts with esbuild

The build check now transpiles the registry and each manifest with esbuild,
so it runs on the Node versions the frontend supports. It also fails on a
folder with no manifest.ts, resolves argv[1] before the main-guard compare,
and has CLI tests. The README notes the distribution matrix.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
… the check before installing dependencies

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@greptile-apps

greptile-apps Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

via Greptile

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; no actionable issues remain.

Summary

Adds the v1 plugin contract, distribution-based registry, lazy slot renderer, and build-time conflict check.

  • V1 pages can render plugin slots without importing overlay features.
  • Plugin builds reject conflicting declarations and publish the plugins they include.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  M["Plugin manifests"] --> C["Build check"]
  C --> J["plugin-matrix.json"]
  M --> R["Registry for selected distribution"]
  R --> P["PluginProvider"]
  P --> S["Slot"]
  S --> F["Lazy filler"]
  S --> B["Fallback when absent or failed"]
Loading

Reviews (3) · Last reviewed commit: "UN-4286 [FIX] Give the missing-import te..." · Reviewed by Greptile

Comment thread frontend/scripts/v1-plugins.mjs Resolved
jaseemjaskp added a commit that referenced this pull request Oct 29, 2026
…ins in the ignore check (UN-4270)

Reported by Athul while building #2394/#2395 on this branch:
- src/v1/tsconfig.json: skipLibCheck back on, as in tsconfig.json. Off, tsc
  also checked third-party typings, and @types/chai 5.2.3 and vitest 3.2.6
  both declare `containSubset`, so any v1 test importing vitest failed
  typecheck:v1. A fixture test now imports vitest to keep this covered.
- The "no v1 file is git-ignored" check skips src/v1/plugins/<id>/: cloud
  plugins copied there are git-ignored on purpose (#2394).
…and test slot recovery in place

- v1-plugins.mjs: with no --dir, `flag + 1` was 0, so the first argument
  (the output file) was skipped and the matrix went to stdout. A fixture
  now covers the file argument with and without --dir.
- Slot.test.tsx: the "recovers in place" test wrapped the slot in a <div>,
  which remounted it, so the boundary's resetKey reset never ran. It now
  re-renders the same slot; with resetKey={id} the test fails.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
greptile-apps[bot]
greptile-apps Bot previously approved these changes Oct 29, 2026
athul-rs and others added 2 commits October 29, 2026 20:18
…6-plugin-manifest

# Conflicts:
#	frontend/src/v1/tsconfig.json
…n read

The scaffold now rejects dynamic imports it cannot analyse. A template
whose fixed prefix names the folder still fails at run time, as the test
needs, and passes the guard.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@greptile-apps
greptile-apps Bot dismissed their stale review October 29, 2026 14:56

Dismissed because a newer commit was pushed; Greptile will re-review the current head.

@sonarqubecloud

Copy link
Copy Markdown

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