Getting Started
Quick start
Install nostics and define your first diagnostic catalog.
nostics is for library authors who want errors and warnings to be easy to recognize, document, and fix.
Instead of throwing anonymous strings from different places, you define a small catalog of diagnostic codes. Each code has a stable name, a message, an optional fix, and an optional docs URL.
Install
pnpm add nostics
npm install nostics
yarn add nostics
The package is ESM only.
Define codes
Create one or multiple diagnostics file(s) in your library.
src/diagnostics.ts
import { createConsoleReporter, defineDiagnostics } from 'nostics'
export const diagnostics = defineDiagnostics({
docsBase: code => `https://nuxt.com/e/${code.replace('NUXT_', '').toLowerCase()}`,
reporters: [createConsoleReporter()],
codes: {
NUXT_B2011: {
why: (p: { src: string, mode: 'client' | 'server' }) => {
const expected = p.mode === 'client' ? 'server' : 'client'
return `Plugin "${p.src}" is ${expected}-only but was registered with mode "${p.mode}".`
},
fix: (p: { mode: 'client' | 'server' }) => {
const expected = p.mode === 'client' ? 'server' : 'client'
return `Rename the file or register it with mode "${expected}".`
},
},
NUXT_B5001: {
why: (p: { value: string, configPath: string }) =>
`Invalid compatibilityDate "${p.value}" in ${p.configPath}.`,
fix: (p: { example: string }) => `Use an ISO date like "${p.example}", or "latest".`,
},
},
})
The returned diagnostics object has one function per code. TypeScript checks the params at the call site.
Use them
src/module.ts
import { diagnostics } from './diagnostics'
type PluginMode = 'all' | 'client' | 'server'
export function addRuntimePlugin(plugin: { src: string, mode?: PluginMode }): void {
const suffix = plugin.src.match(/\.(client|server)\./)?.[1] as 'client' | 'server' | undefined
if (suffix && plugin.mode && plugin.mode !== 'all' && plugin.mode !== suffix) {
throw diagnostics.NUXT_B2011({
src: plugin.src,
mode: plugin.mode,
sources: [plugin.src],
})
}
// register plugin
}
export function validateConfig(config: { compatibilityDate?: string, filepath: string }): void {
if (config.compatibilityDate && !/^(\d{4}-\d{2}-\d{2}|latest)$/.test(config.compatibilityDate)) {
diagnostics.NUXT_B5001({
configPath: config.filepath,
value: config.compatibilityDate,
example: '2024-04-03',
})
}
}
Calling a diagnostic reports it and returns a Diagnostic. Throwing the return value raises it.
Output
[NUXT_B2011] Plugin `./runtime/analytics.server.ts` is server-only but was registered with mode `client`. ├▶ fix: Rename the file or register it with mode `server`. ├▶ sources: modules/analytics.ts:18:5 ╰▶ see: https://nuxt.com/e/b2011
The code is stable, the message is readable, and the fix is next to the error.
Catch it
Diagnostic extends Error.
import { Diagnostic } from 'nostics'
try {
const plugin = resolvePlugin()
addRuntimePlugin(plugin)
}
catch (error) {
if (error instanceof Diagnostic) {
console.log(error.name)
console.log(error.fix)
console.log(error.docs)
}
}