Skip to content

Structured Diagnostics ​

ctx.diagnostics is a thin layer over nostics for author-defined coded diagnostics, each with a stable code, docs URL, and structured payload.

SurfacePurposeExample
ctx.diagnosticsCoded errors and warnings emitted from node-side plugin codeMYP0001: Plugin foo not configured
ctx.messagesFree-form, user-facing notifications shown in the Messages panel'Audit complete — 3 issues found'

Shape ​

ts
interface DevframeDiagnosticsHost {
  /** Proxy-backed lookup over every registered code. */
  readonly logger: Record<string, DiagnosticHandle>

  /** Register additional diagnostic definitions. */
  register: (definitions: Record<string, unknown>) => void

  /** Build a typed diagnostics object with the host's ANSI reporter pre-wired. */
  defineDiagnostics: typeof defineDiagnostics
}

The host ships pre-seeded with devframe's DF* codes plus the host package's (DTK*, etc.); call register() to add your own.

Register your own codes ​

ts
export function MyPlugin(): PluginWithDevTools {
  return {
    name: 'my-plugin',
    devtools: {
      setup(ctx) {
        const myDiagnostics = ctx.diagnostics.defineDiagnostics({
          docsBase: 'https://example.com/errors',
          codes: {
            MYP0001: {
              why: (p: { name: string }) => `Plugin "${p.name}" is not configured`,
              fix: 'Add the plugin to your `vite.config.ts` and pass an options object.',
            },
            MYP0002: {
              why: 'Cache directory missing — running cold.',
            },
          },
        })

        ctx.diagnostics.register(myDiagnostics)

        // Emit through the host's shared reporter:
        myDiagnostics.MYP0002()
      },
    },
  }
}

Code conventions ​

Codes are a 4-letter prefix + 4-digit number (e.g. MYP0001); pick one distinctive enough to avoid collisions.

Prefixes in use:

PrefixOwner
DFdevframe
DTK@vitejs/devtools (Vite-specific)
RDDT@vitejs/devtools-rolldown
VDT@vitejs/devtools-vite (reserved)

A definition takes a why (message) and optional fix (resolution), string or function; docsBase auto-attaches the URL to each diagnostic.

Emit a diagnostic ​

Each registered code becomes a callable DiagnosticHandle — call it to report, or throw to raise.

ts
// Throw — control flow stops here
throw myDiagnostics.MYP0001({ name: 'foo' })

// Report without throwing (default console method: `warn`)
myDiagnostics.MYP0002()

// Override the console method per call
myDiagnostics.MYP0002({}, { method: 'error' })

// Attach a `cause` — merged into the params object
throw myDiagnostics.MYP0001({ name: 'foo', cause: error })

The returned Diagnostic extends Error, so throw narrows following lines as unreachable.

Typed handle reference ​

ctx.diagnostics.logger is loosely typed over all registered codes; for autocompletion, keep and call the typed result of defineDiagnostics() directly, whose pre-wired ANSI reporter gives it and the lookup identical output.

Document your codes ​

Pair each code with a documentation page:

docs/errors/
  index.md            # Table of all codes
  MYP0001.md          # One page per code
  MYP0002.md

Each page covers message, cause, example, and fix; see any DF code page for the template.

When to use what ​

ctx.diagnostics covers coded, docs-backed conditions, targeting tool authors and CI; ctx.messages covers user-facing UI activity, targeting the human at the panel.

Released under the MIT License.