@ethisyscore/vite-plugin
The Vite plugin collection for EthisysCore plugin-side builds. It provides the
build passes for every UI render mode the platform supports — manifest-driven
HTML entries, Contract A SDUI schema validation and emission, the Contract B
worker bundle, the PlatformReact multi-page bundle orchestrator, and the Tier U
iframe-sandbox pass — plus the codegen that derives manifests from a plugin's
routeMeta.json.
For the render-mode / trust-tier overview see the top-level README. For the per-contract authoring walkthroughs see
docs/authoring/.
Export surface
Each Vite plugin factory returns a standard Vite Plugin; wire the one(s) that
match your render mode into vite.config.ts.
| Export | Purpose |
|---|---|
ethisysContractAPlugin | Contract A pass — validates the SDUI tree against the closed vocabulary and emits declarative resources / reactive rules at build time |
validateDeclarativeResource, validateReactiveRule | Standalone SDUI + reactive-rule validators (ValidationResult / ValidationFailure) for tests and tooling |
ethisysContractBPlugin | Contract B pass — emits the Web Worker bundle and its import map (CONTRACT_B_SEMANTIC_PRIMITIVES, CONTRACT_B_RUNTIME_IMPORTS, CONTRACT_B_IMPORT_MAP_ALLOWLIST) |
ethisysPlatformReactPlugin | PlatformReact pass — builds one ESM bundle per declared page |
buildPlatformReactPages, rewriteAliasedExternalImports, virtualPageEntry | Multi-bundle orchestrator: one isolated Vite sub-build per page, with host-externals dedupe (PLATFORM_REACT_EXTERNALS, PLATFORM_REACT_DEDUPE) and host-loader import rewriting |
generatePlatformReactManifest, computePlatformReactPages | Build-step codegen — derive feature.manifest.json + the extension.manifest.json overlay from routeMeta.json |
parseExportedNames | The runtime-named exports of one module's source text — how the codegen resolves a view whose exported name differs from its filename |
parsePlatformReactPages | Test helper for snapshot-testing PlatformReact page declarations |
ethisysIframeSandboxPlugin, buildIframeSandboxPages | Tier U iframe-sandbox pass — cross-origin sandboxed pages with SHA-256 digest emission |
ethisysManifestPlugin | Legacy manifest-driven pass — auto-generates index.html for pages/surfaces that declare a source field |
Typical usage
// vite.config.ts for a PlatformReact plugin
import { defineConfig } from "vite";
import { ethisysPlatformReactPlugin } from "@ethisyscore/vite-plugin";
export default defineConfig({
plugins: [ethisysPlatformReactPlugin({ /* manifest + page options */ })],
});
Most plugins never call these directly — cc package drives the correct pass
for the plugin's declared render mode. Reach for the factories when you maintain
a bespoke build or need the validators/codegen in tests.
How generatePlatformReactManifest resolves a useView name
Each page's useView("<module>", "<Name>") call becomes one entry of that page's
views map, and build-pages wires it with a named import
(import { <Name> } from "<adapter module>"). <Name> is resolved against the
adapter tree in this order:
-
By filename — an adapter file whose basename is
<Name>(e.g.CompanyCostsView→src/adapter/finance/CompanyCostsView.tsx). This is the original and still the winning rule, so a plugin that follows the filename convention resolves exactly as it always has. -
By exported name — otherwise, the single adapter file that exports
<Name>. An adapter file may legitimately export its component under a name other than its filename:// src/adapter/chat/ChatChannelCreateFormView.tsx export function ChatChannelCreateFormView(/* … */) { /* … */ } export { ChatChannelCreateFormView as ChatChannelCreateForm };useView("chat", "ChatChannelCreateForm")is correct at runtime, and now generates.export function|const|let|var|class X,export { X },export { X as Y }andexport { X } from "…"all count.export default …deliberately does not — a default export cannot satisfy a named import — and neither do type-only exports (export type/export interface), which are erased at runtime.export * from "…"is out of reach of the scan, so a view reachable only that way still reports as unresolvable rather than being mis-resolved. -
Two files export the same name → the generator fails, naming every candidate. Picking one would compile and then render the wrong component. Give the intended file that basename (rule 1 always wins) or rename the view.
-
Nothing matches → the generator fails (unless
strict: false). This error is the point of the pass:useViewis a manifest lookup, not an import, so an unsatisfiable call renders "View not available" at runtime behind a green build.
Retired SDK packages
The PlatformReact build refuses an import of a retired SDK package, naming the file and the fix
(RETIRED_SDK_PACKAGES, rejectRetiredSdkPackages). @ethisyscore/core-utils is the first: run
npx ethisyscore-migrate-core-utils # in the plugin's UI folder; --dry-run to preview
npm install
It rewrites every core-utils import (organisation formatting to @ethisyscore/plugin-ui/org-format,
everything else to @ethisyscore/foundation-utils at the same sub-path) and swaps the dependency in
package.json. See migrating off core-utils.
Build and test
npm ci && npm run build && npm test
Last Updated: 2026-07-10