import { z } from "zod"; /** * The interface records the workbench renders from — brett's deployment shape: a * discriminating `type`, a federation `moduleId`, and (on `app`) dock * `metadata`. A local dev server forwards the same records plus the `src` file * it serves (see {@link LocalInterface}); the create-from-local helpers strip * `src` to read them as one shape. The authoring half (`unstable_defineView` / * `unstable_defineService`) lives with the CLI build helpers. */ const InterfaceBase = z.object({ id: z.string(), name: z.string(), title: z.string(), version: z.string().optional(), moduleId: z.string(), }); const AppInterfaceMetadata = z .object({ group: z.string().optional(), priority: z.number().optional() }) .nullable(); /** * A tile's footprint family — the shape it occupies on the dashboard. Not a * linear scale (`banner` is full-width and shallow), so it's an enum, not a * magnitude. The dashboard maps a family to a layout slot. * @public */ export type TileSize = "small" | "large" | "banner"; // Parsing strips unknown keys, so the footprint the CLI stores on a tile record // only survives the bus boundary if it's modelled. `app` is the only other type // that carries any metadata. `priority` (a dashboard sort key) is optional. const TileInterfaceMetadata = z.object({ priority: z.number().optional(), size: z.enum(["small", "large", "banner"]), }); const PanelInterfaceSchema = InterfaceBase.extend({ type: z.literal("panel") }); const WorkerInterfaceSchema = InterfaceBase.extend({ type: z.literal("worker"), }); const AssetSourceInterfaceSchema = InterfaceBase.extend({ type: z.literal("asset_source"), }); // A tile docks on the dashboard, so it carries footprint `metadata` the same // per-type opt-in way `app` carries its dock metadata. const TileInterfaceSchema = InterfaceBase.extend({ type: z.literal("tile"), metadata: TileInterfaceMetadata, }); // Only the navigable `app` interface docks today, so it alone carries // `metadata`; adding it to another type is a per-type opt-in here. const AppInterfaceSchema = InterfaceBase.extend({ type: z.literal("app"), metadata: AppInterfaceMetadata, }); /** * The shape the workbench renders from — a `panel` renders in the dock, a * `worker` runs a background service, an `app` is the navigable full-page view. * @public */ export const InterfaceSchema = z.discriminatedUnion("type", [ PanelInterfaceSchema, WorkerInterfaceSchema, AssetSourceInterfaceSchema, TileInterfaceSchema, AppInterfaceSchema, ]); /** @public */ export type Interface = z.output; /** The interface record for a given `type`. @public */ export type InterfaceOfType = Extract< Interface, { type: T } >; /** * What `interfaces(type?)` returns: narrowed to `type`, or every interface when * `type` is omitted or `undefined` — so a caller can forward an optional type * through without branching on it. * @public */ export type InterfacesOf = readonly (T extends Interface["type"] ? InterfaceOfType : Interface)[]; /** @public */ export type Panel = InterfaceOfType<"panel">; /** * The interface a local CLI dev server forwards — a deployed interface plus the * `src` file it serves. The create-from-local helpers strip `src` to read it as * an {@link Interface}. * @public */ export const LocalInterfaceSchema = z.discriminatedUnion("type", [ PanelInterfaceSchema.extend({ src: z.string() }), WorkerInterfaceSchema.extend({ src: z.string() }), AssetSourceInterfaceSchema.extend({ src: z.string() }), TileInterfaceSchema.extend({ src: z.string() }), AppInterfaceSchema.extend({ src: z.string() }), ]); /** @public */ export type LocalInterface = z.output; /** * A panel's view-component slots, in render order — each its own federation * island (`${id}/views/${name}/${component}`). * @public */ export type PanelComponent = "title" | "panel"; /** * Where an application docks — the `group` value the workbench reads to place an * app in the dock. * @public */ export type DockGroup = "dock.system" | "dock.applications" | "dock.user";