| title | Plugin |
|---|---|
| description | Plugin protocol schemas |
{/*
@module studio/plugin
Studio Plugin Protocol
Defines the specification for Studio plugins — a VS Code-like extension model
that allows each metadata type to contribute custom viewers, designers,
sidebar groups, actions, and commands.
Like VS Code extensions, Studio plugins have two layers:
-
Manifest (Declarative) — JSON-serializable contribution points
-
Activation (Imperative) — Runtime registration of React components & handlers
┌─────────────────────────────────────────────────────────┐
│ Studio Host │
│ ┌───────────────────────────────────────────────────┐ │
│ │ Plugin Registry │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ Object │ │ Flow │ │ Agent │ ... │ │
│ │ │ Plugin │ │ Plugin │ │ Plugin │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ └───────────────────────────────────────────────────┘ │
│ │
│ ┌─── Sidebar ───┐ ┌──── Main Panel ────────────────┐ │
│ │ [plugin icons] │ │ PluginHost renders viewer │ │
│ │ [plugin groups]│ │ from highest-priority plugin │ │
│ └────────────────┘ └────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
@example
import \{ StudioPluginManifestSchema \} from '@objectstack/spec/studio';
const manifest = StudioPluginManifestSchema.parse(\{
id: 'objectstack.object-designer',
name: 'Object Designer',
version: '1.0.0',
contributes: \{
metadataViewers: [\{
id: 'object-explorer',
metadataTypes: ['object', 'objects'],
label: 'Object Explorer',
priority: 100,
modes: ['preview', 'design', 'data'],
\}],
\},
\});import { ActionContributionSchema, ActionContributionLocationSchema, CommandContributionSchema, MetadataIconContributionSchema, MetadataViewerContributionSchema, PanelContributionSchema, PanelLocationSchema, SidebarGroupContributionSchema, StudioPluginContributionsSchema, StudioPluginManifestSchema, ViewModeSchema } from '@objectstack/spec/studio';
import type { ActionContribution, ActionContributionLocation, CommandContribution, MetadataIconContribution, MetadataViewerContribution, PanelContribution, SidebarGroupContribution, StudioPluginContributions, StudioPluginManifest, ViewMode } from '@objectstack/spec/studio';
// Validate data
const result = ActionContributionSchema.parse(data);| Property | Type | Required | Description |
|---|---|---|---|
| id | string |
✅ | Unique action identifier |
| label | string |
✅ | Action display label |
| icon | string |
optional | Lucide icon name |
| location | Enum<'toolbar' | 'contextMenu' | 'commandPalette'> |
✅ | UI location |
| metadataTypes | string[] |
✅ | Applicable metadata types |
toolbarcontextMenucommandPalette
| Property | Type | Required | Description |
|---|---|---|---|
| id | string |
✅ | Unique command identifier |
| label | string |
✅ | Command display label |
| shortcut | string |
optional | Keyboard shortcut |
| icon | string |
optional | Lucide icon name |
| Property | Type | Required | Description |
|---|---|---|---|
| metadataType | string |
✅ | Metadata type |
| label | string |
✅ | Display label |
| icon | string |
✅ | Lucide icon name |
| Property | Type | Required | Description |
|---|---|---|---|
| id | string |
✅ | Unique viewer identifier |
| metadataTypes | string[] |
✅ | Metadata types this viewer can handle |
| label | string |
✅ | Viewer display label |
| priority | number |
✅ | Viewer priority (higher wins) |
| modes | Enum<'preview' | 'design' | 'code' | 'data' | 'history'>[] |
✅ | Supported view modes |
| Property | Type | Required | Description |
|---|---|---|---|
| id | string |
✅ | Unique panel identifier |
| label | string |
✅ | Panel display label |
| icon | string |
optional | Lucide icon name |
| location | Enum<'bottom' | 'right' | 'modal'> |
✅ | Panel location |
bottomrightmodal
| Property | Type | Required | Description |
|---|---|---|---|
| key | string |
✅ | Unique group key |
| label | string |
✅ | Group display label |
| icon | string |
optional | Lucide icon name |
| metadataTypes | string[] |
✅ | Metadata types in this group |
| order | number |
✅ | Sort order (lower = higher) |
| Property | Type | Required | Description |
|---|---|---|---|
| metadataViewers | { id: string; metadataTypes: string[]; label: string; priority: number; … }[] |
✅ | |
| sidebarGroups | { key: string; label: string; icon?: string; metadataTypes: string[]; … }[] |
✅ | |
| actions | { id: string; label: string; icon?: string; location: Enum<'toolbar' | 'contextMenu' | 'commandPalette'>; … }[] |
✅ | |
| metadataIcons | { metadataType: string; label: string; icon: string }[] |
✅ | |
| panels | { id: string; label: string; icon?: string; location: Enum<'bottom' | 'right' | 'modal'> }[] |
✅ | |
| commands | { id: string; label: string; shortcut?: string; icon?: string }[] |
✅ |
| Property | Type | Required | Description |
|---|---|---|---|
| id | string |
✅ | Plugin ID (dot-separated lowercase) |
| name | string |
✅ | Plugin display name |
| version | string |
✅ | Plugin version |
| description | string |
optional | Plugin description |
| author | string |
optional | Author |
| contributes | { metadataViewers: { id: string; metadataTypes: string[]; label: string; priority: number; … }[]; sidebarGroups: { key: string; label: string; icon?: string; metadataTypes: string[]; … }[]; actions: { id: string; label: string; icon?: string; location: Enum<'toolbar' | 'contextMenu' | 'commandPalette'>; … }[]; metadataIcons: { metadataType: string; label: string; icon: string }[]; … } |
✅ | |
| activationEvents | { type: Enum<'onCommand' | 'onRoute' | 'onObject' | 'onEvent' | 'onService' | 'onSchedule' | 'onStartup' | 'onMetadataType' | 'onView'>; pattern: string }[] |
✅ |
previewdesigncodedatahistory