feat(workbench): build app view artifacts and register them on deploy#1149
feat(workbench): build app view artifacts and register them on deploy#1149gu-stav wants to merge 11 commits into
Conversation
Threads the app's declared views from sanity.cli.ts through to the federation vite plugin (build + dev), so each view's src is built into a render artifact under .sanity/federation/views. On deploy, the views are validated into the application-service payload and logged — the service that stores them doesn't exist yet, so nothing is sent, but a malformed view declaration fails the deploy before the bundle ships.
|
Claude finished @gu-stav's task in 2m 52s —— View job Review
Blockers before merge1. 2. No tests for
Issues3. Zod error surfaced to user is unreadable. 4. Production deploy output dumps full JSON payload. 5. Lenient/strict schema split can pass dev and fail deploy. 6. Regex error message echoes the pattern. 7. Changeset summary doesn't match repo product-copy conventions.
Nits (non-blocking)
|
📦 Bundle Stats —
|
| Metric | Value | vs feat/cli-dock-group-priority (4265702) |
|---|---|---|
| Internal (raw) | 2.6 KB | +214 B, +8.7% |
| Internal (gzip) | 1.0 KB | +115 B, +12.5% |
| Bundled (raw) | 11.10 MB | - |
| Bundled (gzip) | 2.09 MB | - |
| Import time | 852ms | +3ms, +0.3% |
bin:sanity
| Metric | Value | vs feat/cli-dock-group-priority (4265702) |
|---|---|---|
| Internal (raw) | 1023 B | - |
| Internal (gzip) | 486 B | - |
| Bundled (raw) | 9.84 MB | - |
| Bundled (gzip) | 1.77 MB | - |
| Import time | 2.00s | +2ms, +0.1% |
🗺️ View treemap · Artifacts
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
📦 Bundle Stats — @sanity/cli-core
Compared against feat/cli-dock-group-priority (4265702c)
| Metric | Value | vs feat/cli-dock-group-priority (4265702) |
|---|---|---|
| Internal (raw) | 102.3 KB | - |
| Internal (gzip) | 24.7 KB | - |
| Bundled (raw) | 21.77 MB | - |
| Bundled (gzip) | 3.45 MB | - |
| Import time | 800ms | -0ms, -0.1% |
🗺️ View treemap · Artifacts
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
📦 Bundle Stats — create-sanity
Compared against feat/cli-dock-group-priority (4265702c)
| Metric | Value | vs feat/cli-dock-group-priority (4265702) |
|---|---|---|
| Internal (raw) | 908 B | - |
| Internal (gzip) | 483 B | - |
| Bundled (raw) | 931 B | - |
| Bundled (gzip) | 491 B | - |
| Import time | ❌ ChildProcess denied: node | - |
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
Coverage Delta
Comparing 36 changed files against main @ Overall Coverage
|
`views` is an `unstable_defineApp` field — its source of truth is `DefineAppInput` in @sanity/federation, not the legacy `app` config object on CliConfig. Drop it from the cli-core type and read it through the `isWorkbenchApp` narrowing at each call site (build, dev, deploy), so the field lives in one place.
Studio dev already threaded views (shared getDevServerConfig), but studio build dropped them — so a studio opting into unstable_defineApp with views emitted no artifacts. Read views off the branded app and thread them through buildStudio for parity with apps. Views apply to coreApp and studio alike, per each one's cli config.
So local panels render without a deploy: carry the branded app's views on the dev-server registry entry (alongside the manifest, not inside it — views live in the application service) and include them in the local-applications payload the workbench subscribes to.
Preview this PR with pkg.pr.newRun the Sanity CLInpx https://pkg.pr.new/sanity-io/cli/@sanity/cli@b545773 <command>...Or upgrade project dependencies📦
|
Pin @sanity/federation to the sanity-io/workbench#236 pkg.pr.new preview so the views/ViewArtifact surface resolves at typecheck time, and un-export viewDeploymentPayloadSchema / ViewDeploymentPayload (used only internally) so knip's depcheck passes.
So view src files can import it alongside unstable_defineApp until the sanity runtime package surfaces it. Canonical impl stays in @sanity/federation; no prop types re-exported (inferred at the call site).
Importing unstable_defineView from the main @sanity/cli entry dragged cli-core's Node worker loader into the browser federation bundle and broke view builds. Move the runtime helper to a dedicated @sanity/cli/runtime entry that re-exports only from @sanity/federation — no cli-core/Node imports — so view src files (and the future sanity runtime re-export) stay out of the CLI's dependency graph. defineApp stays config-time on the main entry.
The workbench renamed the application-surface concept from views to
interfaces (one per interface_type, the shape the application service
returns). Map each declared view to that local interface shape on the
dev-server registry entry — { interface_type, name, entry_point }, with
the local dev server as the entry_point — so the workbench parses and
renders local panels. Non-local (deployed) entry_points are deferred.
CLI side of workbench US3 (panel views). Stacked on #1146.
Threads the app's declared
viewsfromsanity.cli.tsthrough build and dev into the@sanity/federation/viteplugin, so each view'ssrcis built into a render artifact (exposed via module federation as./views/<name>).On
sanity deploy, the views are validated into the application-service payload and logged — the service that stores them doesn't exist yet, so nothing is sent, but a malformed view declaration fails the deploy before the bundle ships. Addsapp.viewsto the CLI config type.Depends on the
unstable_defineView/ views surface in@sanity/federation(sanity-io/workbench#236); consumed via a pkg.pr.new preview once it lands.