@ethisyscore/vite-plugin
v1.154.0
Published
Vite plugin for EthisysCore Contract A plugins: manifest-driven HTML entry points (legacy iframe mode) plus build-time SDUI/ReactiveRule schema validation and declarative-resource emission.
Maintainers
Readme
@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.
Build and test
npm ci && npm run build && npm testLast Updated: 2026-07-10
