Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@ packages/kit/skills
docs/.vitepress/cache
.turbo
.context

# Agent skills from npm packages (managed by skills-npm)
**/skills/npm-*
67 changes: 67 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,73 @@ pnpm -C docs run docs # docs dev server
- Shared UI components/preset in `packages/ui`; use `presetDevToolsUI` from `@vitejs/devtools-ui/unocss`.
- Currently focused on Rolldown build-mode analysis; dev-mode support is deferred.

## Structured Diagnostics (Error Codes)

All node-side warnings and errors use structured diagnostics via [`logs-sdk`](https://github.com/vercel-labs/logs-sdk). Never use raw `console.warn`, `console.error`, or `throw new Error` with ad-hoc messages in node-side code — always define a coded diagnostic.

### Code prefixes

| Prefix | Package(s) | Diagnostics file |
|--------|-----------|-----------------|
| `DTK` | `packages/rpc`, `packages/core` | `packages/rpc/src/diagnostics.ts`, `packages/core/src/node/diagnostics.ts` |
| `RDDT` | `packages/rolldown` | `packages/rolldown/src/node/diagnostics.ts` |
| `VDT` | `packages/vite` (reserved) | — |

Codes are sequential 4-digit numbers per prefix (e.g. `DTK0033`, `RDDT0003`). Check the existing diagnostics file to find the next available number.

### Adding a new error

1. **Define the code** in the appropriate `diagnostics.ts`:
```txt
// diagnostics.ts
DTK0033: {
message: (p: { name: string }) => `Something went wrong with "${p.name}"`,
hint: 'Optional hint for the user.',
level: 'warn', // defaults to 'error' if omitted
},
```

2. **Use the logger** at the call site:
```ts
import { logger } from './diagnostics'

// For thrown errors — always prefix with `throw` for TypeScript control flow:
throw logger.DTK0033({ name }).throw()

// For logged warnings/errors (not thrown):
logger.DTK0033({ name }).log() // uses definition level
logger.DTK0033({ name }).warn() // override to warn
logger.DTK0033({ name }, { cause: error }).log() // attach cause
```

3. **Create a docs page** at `docs/errors/DTK0033.md`:
```md
---
outline: deep
---
# DTK0033: Short Title
> Package: `@vitejs/devtools`
## Message
> Something went wrong with "`{name}`"
## Cause
When and why this occurs.
## Example
Code that triggers it.
## Fix
How to resolve it.
## Source
`packages/core/src/node/filename.ts`
```

4. **Update the index** at `docs/errors/index.md` — add a row to the table.

5. **Update the sidebar** in `docs/.vitepress/config.ts` — the DTK items are auto-generated from `Array.from({ length: N })`, so increment the length. RDDT items are listed manually.

### Scope

- **Node-side only**: `packages/rpc`, `packages/core/src/node`, `packages/rolldown/src/node`.
- **Client-side excluded**: Vue components, webcomponents, and browser-only code keep using `console.*` / `throw`.

## Before PRs

```sh
Expand Down
23 changes: 23 additions & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,29 @@ export default extendConfig(withMermaid(defineConfig({
{ text: 'Examples', link: '/kit/examples' },
],
},
{
text: 'Error Reference',
link: '/errors/',
collapsed: true,
items: [
{
text: 'DevTools Kit (DTK)',
collapsed: true,
items: Array.from({ length: 32 }, (_, i) => {
const code = `DTK${String(i + 1).padStart(4, '0')}`
return { text: code, link: `/errors/${code}` }
}),
},
{
text: 'Rolldown DevTools (RDDT)',
collapsed: true,
items: [
{ text: 'RDDT0001', link: '/errors/RDDT0001' },
{ text: 'RDDT0002', link: '/errors/RDDT0002' },
],
},
],
},
],

search: {
Expand Down
60 changes: 60 additions & 0 deletions docs/errors/DTK0001.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
outline: deep
---

# DTK0001: RPC Function Already Registered

> Package: `@vitejs/devtools-rpc`

## Message

> RPC function "`{name}`" is already registered

## Cause

This error is thrown by `RpcFunctionsCollectorBase.register()` when you attempt to register an RPC function with a name that already exists in the collector. Each function name must be unique within a collector instance unless you explicitly opt into overwriting.

## Example

```ts
import { defineRpcFunction } from '@vitejs/devtools-kit'

const getVersion = defineRpcFunction({
name: 'my-plugin:get-version',
type: 'static',
handler: () => '1.0.0',
})

const getVersionAlt = defineRpcFunction({
name: 'my-plugin:get-version', // same name as above
type: 'static',
handler: () => '2.0.0',
})

// First registration succeeds
collector.register(getVersion)

// Second registration throws DTK0001
collector.register(getVersionAlt)
```

## Fix

Either use a unique name for each function, or pass `force: true` to overwrite the existing registration:

```ts
// Option 1: Use a unique name
const getVersionAlt = defineRpcFunction({
name: 'my-plugin:get-version-alt',
type: 'static',
handler: () => '2.0.0',
})
collector.register(getVersionAlt)

// Option 2: Force overwrite
collector.register(getVersionAlt, true)
```

## Source

`packages/rpc/src/collector.ts`
48 changes: 48 additions & 0 deletions docs/errors/DTK0002.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
outline: deep
---

# DTK0002: RPC Function Not Registered (Update)

> Package: `@vitejs/devtools-rpc`

## Message

> RPC function "`{name}`" is not registered. Use register() to add new functions.

## Cause

This error is thrown by `RpcFunctionsCollectorBase.update()` when you attempt to update a function definition that has not been registered yet. The `update()` method is intended for replacing an existing definition, not for adding new ones.

## Example

```ts
import { defineRpcFunction } from '@vitejs/devtools-kit'

const getVersion = defineRpcFunction({
name: 'my-plugin:get-version',
type: 'static',
handler: () => '2.0.0',
})

// Throws DTK0002 because 'my-plugin:get-version' was never registered
collector.update(getVersion)
```

## Fix

Register the function first with `register()`, then use `update()` for subsequent changes. Alternatively, pass `force: true` to `update()` to allow upserting:

```ts
// Option 1: Register first, update later
collector.register(getVersion)
// ... later ...
collector.update(getVersionUpdated)

// Option 2: Force update (creates if missing)
collector.update(getVersion, true)
```

## Source

`packages/rpc/src/collector.ts`
51 changes: 51 additions & 0 deletions docs/errors/DTK0003.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
outline: deep
---

# DTK0003: RPC Function Schema Not Found

> Package: `@vitejs/devtools-rpc`

## Message

> RPC function "`{name}`" is not registered

## Cause

This error is thrown by `RpcFunctionsCollectorBase.getSchema()` when you request the argument and return schemas for a function name that does not exist in the collector. The function must be registered before its schema can be queried.

## Example

```ts
// Throws DTK0003 because 'my-plugin:get-config' was never registered
const schema = collector.getSchema('my-plugin:get-config')
```

## Fix

Ensure the function is registered before querying its schema. You can check whether a function exists first using `has()`:

```ts
import { defineRpcFunction } from '@vitejs/devtools-kit'

const getConfig = defineRpcFunction({
name: 'my-plugin:get-config',
type: 'query',
handler: () => ({ debug: false }),
})

// Register first
collector.register(getConfig)

// Now getSchema works
const schema = collector.getSchema('my-plugin:get-config')

// Or guard with has()
if (collector.has('my-plugin:get-config')) {
const schema = collector.getSchema('my-plugin:get-config')
}
```

## Source

`packages/rpc/src/collector.ts`
76 changes: 76 additions & 0 deletions docs/errors/DTK0004.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
outline: deep
---

# DTK0004: Missing RPC Handler

> Package: `@vitejs/devtools-rpc`

## Message

> Either handler or setup function must be provided for RPC function "`{name}`"

## Cause

This error is thrown by `getRpcHandler()` when an RPC function definition provides neither a `handler` property nor a `setup` function that returns a `handler`. It can occur in two situations:

1. When the collector's proxy tries to resolve a handler for a registered function.
2. During `dumpFunctions()` when resolving handlers for pre-computation.

Every RPC function must have a way to produce a handler -- either directly via `handler` or lazily via `setup`.

## Example

```ts
import { defineRpcFunction } from '@vitejs/devtools-kit'

// Missing both handler and setup
const broken = defineRpcFunction({
name: 'my-plugin:broken',
type: 'query',
})

collector.register(broken)

// Throws DTK0004 when the handler is resolved
await collector.getHandler('my-plugin:broken')
```

A `setup` function that forgets to return a handler also triggers this error:

```ts
const alsoMissing = defineRpcFunction({
name: 'my-plugin:also-missing',
type: 'query',
setup: (ctx) => {
// Forgot to return { handler: ... }
return {}
},
})
```

## Fix

Provide a `handler` directly, or return one from `setup`:

```ts
// Option 1: Direct handler
const getVersion = defineRpcFunction({
name: 'my-plugin:get-version',
type: 'static',
handler: () => '1.0.0',
})

// Option 2: Handler via setup (useful when you need context)
const getConfig = defineRpcFunction({
name: 'my-plugin:get-config',
type: 'query',
setup: ctx => ({
handler: () => ctx.config,
}),
})
```

## Source

`packages/rpc/src/handler.ts`
Loading
Loading