@vitejs/devtools-kit 0.0.0-alpha.8 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +2 -17
- package/dist/client.js +1734 -19
- package/dist/constants.d.ts +14 -0
- package/dist/constants.js +28 -0
- package/dist/events-B41U-zeg.d.ts +71 -0
- package/dist/index-Bl6l5FTi.d.ts +642 -0
- package/dist/index.d.ts +6 -5
- package/dist/index.js +4 -16
- package/dist/shared-state-BFKKxNt1.d.ts +53 -0
- package/dist/utils/events.d.ts +9 -0
- package/dist/utils/events.js +40 -0
- package/dist/utils/nanoid.d.ts +4 -0
- package/dist/utils/nanoid.js +10 -0
- package/dist/utils/shared-state.d.ts +2 -0
- package/dist/utils/shared-state.js +36 -0
- package/package.json +19 -10
- package/skills/vite-devtools-kit/SKILL.md +436 -0
- package/skills/vite-devtools-kit/references/dock-entry-types.md +295 -0
- package/skills/vite-devtools-kit/references/logs-patterns.md +188 -0
- package/skills/vite-devtools-kit/references/project-structure.md +256 -0
- package/skills/vite-devtools-kit/references/rpc-patterns.md +185 -0
- package/skills/vite-devtools-kit/references/shared-state-patterns.md +292 -0
- package/dist/index-BtaHil_c.d.ts +0 -156
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# Dock Entry Types
|
|
2
|
+
|
|
3
|
+
Detailed configuration for each dock entry type.
|
|
4
|
+
|
|
5
|
+
## Common Properties
|
|
6
|
+
|
|
7
|
+
All dock entries share these properties:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
interface DockEntryBase {
|
|
11
|
+
id: string // Unique identifier
|
|
12
|
+
title: string // Display title
|
|
13
|
+
icon: string // URL, data URI, or Iconify name
|
|
14
|
+
category?: string // Grouping category
|
|
15
|
+
defaultOrder?: number // Sort order (higher = earlier)
|
|
16
|
+
isHidden?: boolean // Hide from dock
|
|
17
|
+
badge?: string // Badge text on dock icon (e.g., count)
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Icons
|
|
22
|
+
|
|
23
|
+
<!-- eslint-skip -->
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
// Iconify (recommended)
|
|
27
|
+
icon: 'ph:chart-bar-duotone' // Phosphor Icons
|
|
28
|
+
icon: 'carbon:analytics' // Carbon Icons
|
|
29
|
+
icon: 'mdi:view-dashboard' // Material Design
|
|
30
|
+
|
|
31
|
+
// URL
|
|
32
|
+
icon: 'https://example.com/logo.svg'
|
|
33
|
+
|
|
34
|
+
// Data URI
|
|
35
|
+
icon: 'data:image/svg+xml,<svg>...</svg>'
|
|
36
|
+
|
|
37
|
+
// Light/dark variants
|
|
38
|
+
icon: {
|
|
39
|
+
light: 'https://example.com/logo-light.svg',
|
|
40
|
+
dark: 'https://example.com/logo-dark.svg',
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Browse icons at [Iconify](https://icon-sets.iconify.design/).
|
|
45
|
+
|
|
46
|
+
## Iframe Entries
|
|
47
|
+
|
|
48
|
+
Most common type. Displays your UI in an isolated iframe.
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
interface IframeEntry extends DockEntryBase {
|
|
52
|
+
type: 'iframe'
|
|
53
|
+
url: string // URL to load
|
|
54
|
+
frameId?: string // Share iframe between entries
|
|
55
|
+
clientScript?: ClientScriptEntry // Optional client script
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Example
|
|
59
|
+
ctx.docks.register({
|
|
60
|
+
id: 'my-plugin',
|
|
61
|
+
title: 'My Plugin',
|
|
62
|
+
icon: 'ph:house-duotone',
|
|
63
|
+
type: 'iframe',
|
|
64
|
+
url: '/.my-plugin/',
|
|
65
|
+
})
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Hosting Your Own UI
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { fileURLToPath } from 'node:url'
|
|
72
|
+
|
|
73
|
+
const clientDist = fileURLToPath(
|
|
74
|
+
new URL('../dist/client', import.meta.url)
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
ctx.views.hostStatic('/.my-plugin/', clientDist)
|
|
78
|
+
|
|
79
|
+
ctx.docks.register({
|
|
80
|
+
id: 'my-plugin',
|
|
81
|
+
title: 'My Plugin',
|
|
82
|
+
icon: 'ph:house-duotone',
|
|
83
|
+
type: 'iframe',
|
|
84
|
+
url: '/.my-plugin/',
|
|
85
|
+
})
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Action Entries
|
|
89
|
+
|
|
90
|
+
Buttons that trigger client-side scripts. Perfect for inspectors and toggles.
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
interface ActionEntry extends DockEntryBase {
|
|
94
|
+
type: 'action'
|
|
95
|
+
action: {
|
|
96
|
+
importFrom: string // Package export path
|
|
97
|
+
importName?: string // Export name (default: 'default')
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Registration
|
|
102
|
+
ctx.docks.register({
|
|
103
|
+
id: 'my-inspector',
|
|
104
|
+
title: 'Inspector',
|
|
105
|
+
icon: 'ph:cursor-duotone',
|
|
106
|
+
type: 'action',
|
|
107
|
+
action: {
|
|
108
|
+
importFrom: 'my-plugin/devtools-action',
|
|
109
|
+
importName: 'default',
|
|
110
|
+
},
|
|
111
|
+
})
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Client Script Implementation
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
// src/devtools-action.ts
|
|
118
|
+
import type { DevToolsClientScriptContext } from '@vitejs/devtools-kit/client'
|
|
119
|
+
|
|
120
|
+
export default function setup(ctx: DevToolsClientScriptContext) {
|
|
121
|
+
let overlay: HTMLElement | null = null
|
|
122
|
+
|
|
123
|
+
ctx.current.events.on('entry:activated', () => {
|
|
124
|
+
overlay = document.createElement('div')
|
|
125
|
+
overlay.style.cssText = `
|
|
126
|
+
position: fixed;
|
|
127
|
+
inset: 0;
|
|
128
|
+
cursor: crosshair;
|
|
129
|
+
z-index: 99999;
|
|
130
|
+
`
|
|
131
|
+
overlay.onclick = (e) => {
|
|
132
|
+
const target = document.elementFromPoint(e.clientX, e.clientY)
|
|
133
|
+
console.log('Selected:', target)
|
|
134
|
+
}
|
|
135
|
+
document.body.appendChild(overlay)
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
ctx.current.events.on('entry:deactivated', () => {
|
|
139
|
+
overlay?.remove()
|
|
140
|
+
overlay = null
|
|
141
|
+
})
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Package Export
|
|
146
|
+
|
|
147
|
+
```json
|
|
148
|
+
{
|
|
149
|
+
"exports": {
|
|
150
|
+
".": "./dist/index.mjs",
|
|
151
|
+
"./devtools-action": "./dist/devtools-action.mjs"
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Custom Render Entries
|
|
157
|
+
|
|
158
|
+
Render directly into the DevTools panel DOM. Use when you need direct DOM access or framework mounting.
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
interface CustomRenderEntry extends DockEntryBase {
|
|
162
|
+
type: 'custom-render'
|
|
163
|
+
renderer: {
|
|
164
|
+
importFrom: string
|
|
165
|
+
importName?: string
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
ctx.docks.register({
|
|
170
|
+
id: 'my-custom',
|
|
171
|
+
title: 'Custom View',
|
|
172
|
+
icon: 'ph:code-duotone',
|
|
173
|
+
type: 'custom-render',
|
|
174
|
+
renderer: {
|
|
175
|
+
importFrom: 'my-plugin/devtools-renderer',
|
|
176
|
+
importName: 'default',
|
|
177
|
+
},
|
|
178
|
+
})
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Renderer Implementation
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
// src/devtools-renderer.ts
|
|
185
|
+
import type { DevToolsClientScriptContext } from '@vitejs/devtools-kit/client'
|
|
186
|
+
|
|
187
|
+
export default function setup(ctx: DevToolsClientScriptContext) {
|
|
188
|
+
ctx.current.events.on('dom:panel:mounted', (panel) => {
|
|
189
|
+
// Vanilla JS
|
|
190
|
+
panel.innerHTML = `<div style="padding: 16px;">Hello</div>`
|
|
191
|
+
|
|
192
|
+
// Or mount Vue
|
|
193
|
+
// import { createApp } from 'vue'
|
|
194
|
+
// import App from './App.vue'
|
|
195
|
+
// createApp(App).mount(panel)
|
|
196
|
+
|
|
197
|
+
// Or mount React
|
|
198
|
+
// import { createRoot } from 'react-dom/client'
|
|
199
|
+
// createRoot(panel).render(<App />)
|
|
200
|
+
})
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Launcher Entries
|
|
205
|
+
|
|
206
|
+
Actionable setup cards for running initialization tasks. Shows a card with title, description, and a launch button.
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
type LauncherStatus = 'idle' | 'loading' | 'success' | 'error'
|
|
210
|
+
|
|
211
|
+
interface LauncherEntry extends DockEntryBase {
|
|
212
|
+
type: 'launcher'
|
|
213
|
+
launcher: {
|
|
214
|
+
title: string // Card title
|
|
215
|
+
description?: string // Card description
|
|
216
|
+
icon?: string | { light: string, dark: string } // Card icon
|
|
217
|
+
buttonStart?: string // Start button text
|
|
218
|
+
buttonLoading?: string // Loading button text
|
|
219
|
+
status?: LauncherStatus // Current status
|
|
220
|
+
error?: string // Error message when status is 'error'
|
|
221
|
+
onLaunch: () => Promise<void> // Callback when user clicks launch
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Registration
|
|
226
|
+
const entry = ctx.docks.register({
|
|
227
|
+
id: 'my-setup',
|
|
228
|
+
title: 'My Setup',
|
|
229
|
+
icon: 'ph:rocket-launch-duotone',
|
|
230
|
+
type: 'launcher',
|
|
231
|
+
launcher: {
|
|
232
|
+
title: 'Initialize My Plugin',
|
|
233
|
+
description: 'Run the initial setup before the plugin can be used',
|
|
234
|
+
buttonStart: 'Start Setup',
|
|
235
|
+
buttonLoading: 'Setting up...',
|
|
236
|
+
onLaunch: async () => {
|
|
237
|
+
// Perform initialization
|
|
238
|
+
await runSetup()
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
// Update status after launch completes
|
|
244
|
+
entry.update({
|
|
245
|
+
launcher: {
|
|
246
|
+
...entry.launcher,
|
|
247
|
+
status: 'success',
|
|
248
|
+
},
|
|
249
|
+
})
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Launcher Use Cases
|
|
253
|
+
|
|
254
|
+
- **First-run setup** — Run initial scans or configuration before showing results
|
|
255
|
+
- **Build triggers** — Start a build or analysis pass on demand
|
|
256
|
+
- **Authentication** — Prompt user to connect external services
|
|
257
|
+
|
|
258
|
+
## Client Script Events
|
|
259
|
+
|
|
260
|
+
| Event | Payload | Description |
|
|
261
|
+
|-------|---------|-------------|
|
|
262
|
+
| `entry:activated` | - | Entry was selected |
|
|
263
|
+
| `entry:deactivated` | - | Entry was deselected |
|
|
264
|
+
| `entry:updated` | `DevToolsDockUserEntry` | Entry metadata changed |
|
|
265
|
+
| `dom:panel:mounted` | `HTMLDivElement` | Panel DOM ready (custom-render only) |
|
|
266
|
+
| `dom:iframe:mounted` | `HTMLIFrameElement` | Iframe mounted (iframe only) |
|
|
267
|
+
|
|
268
|
+
## Category Order
|
|
269
|
+
|
|
270
|
+
Default category ordering:
|
|
271
|
+
|
|
272
|
+
```ts
|
|
273
|
+
DEFAULT_CATEGORIES_ORDER = {
|
|
274
|
+
'~viteplus': -1000, // First
|
|
275
|
+
'default': 0,
|
|
276
|
+
'app': 100,
|
|
277
|
+
'framework': 200,
|
|
278
|
+
'web': 300,
|
|
279
|
+
'advanced': 400,
|
|
280
|
+
'~builtin': 1000, // Last
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Use `category` to group related entries:
|
|
285
|
+
|
|
286
|
+
```ts
|
|
287
|
+
ctx.docks.register({
|
|
288
|
+
id: 'my-plugin',
|
|
289
|
+
title: 'My Plugin',
|
|
290
|
+
icon: 'ph:house-duotone',
|
|
291
|
+
type: 'iframe',
|
|
292
|
+
url: '/.my-plugin/',
|
|
293
|
+
category: 'framework',
|
|
294
|
+
})
|
|
295
|
+
```
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# Logs & Notification Patterns
|
|
2
|
+
|
|
3
|
+
Structured log entries and toast notifications from both server and client contexts.
|
|
4
|
+
|
|
5
|
+
## Log Entry Types
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
type DevToolsLogLevel = 'info' | 'warn' | 'error' | 'success' | 'debug'
|
|
9
|
+
|
|
10
|
+
interface DevToolsLogEntryInput {
|
|
11
|
+
message: string // Required: short title
|
|
12
|
+
level: DevToolsLogLevel // Required: severity
|
|
13
|
+
description?: string // Detailed explanation
|
|
14
|
+
stacktrace?: string // Stack trace string
|
|
15
|
+
filePosition?: { file: string, line?: number, column?: number }
|
|
16
|
+
elementPosition?: { selector?: string, boundingBox?: { x: number, y: number, width: number, height: number }, description?: string }
|
|
17
|
+
notify?: boolean // Show as toast
|
|
18
|
+
category?: string // Grouping (e.g., 'a11y', 'lint')
|
|
19
|
+
labels?: string[] // Tags for filtering
|
|
20
|
+
autoDismiss?: number // Toast dismiss time in ms (default: 5000)
|
|
21
|
+
autoDelete?: number // Auto-delete time in ms
|
|
22
|
+
status?: 'loading' | 'idle' // Shows spinner when loading
|
|
23
|
+
id?: string // Explicit id for deduplication
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The `from` field (`'server' | 'browser'`) is set automatically.
|
|
28
|
+
|
|
29
|
+
## Server-Side Patterns
|
|
30
|
+
|
|
31
|
+
### Fire-and-Forget in Setup
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
export function myPlugin() {
|
|
35
|
+
return {
|
|
36
|
+
name: 'my-plugin',
|
|
37
|
+
devtools: {
|
|
38
|
+
setup(ctx) {
|
|
39
|
+
ctx.logs.add({
|
|
40
|
+
message: 'Plugin initialized',
|
|
41
|
+
level: 'info',
|
|
42
|
+
})
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Handle-Based Updates
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
export function myPlugin() {
|
|
53
|
+
return {
|
|
54
|
+
name: 'my-plugin',
|
|
55
|
+
devtools: {
|
|
56
|
+
async setup(ctx) {
|
|
57
|
+
const log = await ctx.logs.add({
|
|
58
|
+
id: 'my-plugin:build',
|
|
59
|
+
message: 'Analyzing...',
|
|
60
|
+
level: 'info',
|
|
61
|
+
status: 'loading',
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
// Later, after work completes
|
|
65
|
+
await log.update({
|
|
66
|
+
message: 'Analysis complete — 42 modules',
|
|
67
|
+
level: 'success',
|
|
68
|
+
status: 'idle',
|
|
69
|
+
})
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### File Position (Clickable Links)
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
ctx.logs.add({
|
|
80
|
+
message: 'Unused import detected',
|
|
81
|
+
level: 'warn',
|
|
82
|
+
category: 'lint',
|
|
83
|
+
filePosition: {
|
|
84
|
+
file: '/src/App.vue',
|
|
85
|
+
line: 12,
|
|
86
|
+
column: 1,
|
|
87
|
+
},
|
|
88
|
+
})
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Element Position (DOM Highlighting)
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
ctx.logs.add({
|
|
95
|
+
message: 'Missing alt attribute on image',
|
|
96
|
+
level: 'warn',
|
|
97
|
+
category: 'a11y',
|
|
98
|
+
labels: ['WCAG 1.1.1'],
|
|
99
|
+
elementPosition: {
|
|
100
|
+
selector: 'img.hero-image',
|
|
101
|
+
description: '<img class="hero-image">',
|
|
102
|
+
},
|
|
103
|
+
})
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Client-Side Patterns
|
|
107
|
+
|
|
108
|
+
### Client Script with Logs
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import type { DockClientScriptContext } from '@vitejs/devtools-kit/client'
|
|
112
|
+
|
|
113
|
+
export default async function (ctx: DockClientScriptContext) {
|
|
114
|
+
const log = await ctx.logs.add({
|
|
115
|
+
message: 'Running audit...',
|
|
116
|
+
level: 'info',
|
|
117
|
+
status: 'loading',
|
|
118
|
+
notify: true,
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
// ... perform work ...
|
|
122
|
+
|
|
123
|
+
log.update({
|
|
124
|
+
message: 'Audit complete — 3 issues found',
|
|
125
|
+
level: 'warn',
|
|
126
|
+
status: 'idle',
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Toast Notifications
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
// Short-lived notification
|
|
135
|
+
ctx.logs.add({
|
|
136
|
+
message: 'URL copied to clipboard',
|
|
137
|
+
level: 'success',
|
|
138
|
+
notify: true,
|
|
139
|
+
autoDismiss: 2000,
|
|
140
|
+
})
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Toasts appear as overlay notifications regardless of whether the Logs panel is open. Default auto-dismiss is 5 seconds.
|
|
144
|
+
|
|
145
|
+
## Deduplication
|
|
146
|
+
|
|
147
|
+
Re-adding with the same `id` updates the existing entry:
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
// Creates entry
|
|
151
|
+
ctx.logs.add({ id: 'my-scan', message: 'Scanning...', level: 'info', status: 'loading' })
|
|
152
|
+
|
|
153
|
+
// Updates same entry (no duplicate)
|
|
154
|
+
ctx.logs.add({ id: 'my-scan', message: 'Scan complete', level: 'success', status: 'idle' })
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Log Handle API
|
|
158
|
+
|
|
159
|
+
`ctx.logs.add()` returns `Promise<DevToolsLogHandle>`:
|
|
160
|
+
|
|
161
|
+
| Property/Method | Description |
|
|
162
|
+
|-----------------|-------------|
|
|
163
|
+
| `handle.id` | The log entry id |
|
|
164
|
+
| `handle.entry` | The current `DevToolsLogEntry` data |
|
|
165
|
+
| `handle.update(patch)` | Partially update the entry (returns `Promise`) |
|
|
166
|
+
| `handle.dismiss()` | Remove the entry (returns `Promise`) |
|
|
167
|
+
|
|
168
|
+
Both `update()` and `dismiss()` can be used without `await` for fire-and-forget.
|
|
169
|
+
|
|
170
|
+
## Managing Logs
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
// Remove specific log
|
|
174
|
+
ctx.logs.remove(entryId)
|
|
175
|
+
|
|
176
|
+
// Clear all logs
|
|
177
|
+
ctx.logs.clear()
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Max capacity is 1000 entries; oldest entries are auto-removed when full.
|
|
181
|
+
|
|
182
|
+
## Dock Badge
|
|
183
|
+
|
|
184
|
+
The built-in Logs dock icon automatically shows a badge with the total log count and is hidden when empty.
|
|
185
|
+
|
|
186
|
+
## Real-World Example
|
|
187
|
+
|
|
188
|
+
See [`examples/plugin-a11y-checker`](https://github.com/vitejs/devtools/tree/main/examples/plugin-a11y-checker) for a complete plugin that uses logs to report accessibility violations with severity levels, element positions, WCAG labels, and log handle updates.
|