mcpField
N
nostics

nostics

github.com/vercel-labs開発24056 回インストール4 週間前に更新
リポジトリ

nostics について

nostics は、安定したコードや修正案、ドキュメントへのリンクを持つ診断を扱う TypeScript ライブラリです。レポーターとシリアライズに対応し、本番ビルドから報告専用の診断を除去できます。

主な機能

  1. 01型付き診断コードの定義
  2. 02修正案とドキュメントリンクの付与
  3. 03レポーターによる診断出力
  4. 04プロセス間で渡す診断のシリアライズ
  5. 05フォーマッターと Vite ビルドプラグイン

活用シーン

  1. 01ビルドや実行時エラーへの安定コード付与
  2. 02診断記録のファイルまたは URL への送信
  3. 03Vite 開発中の診断収集
  4. 04本番バンドルから報告専用診断を除去

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/vercel-labs/nostics --skill nostics

インストール後、Claude Code で/nosticsを入力して読み込まれたか確認します。

同梱ファイルreferences/documentation-site.mdreferences/migration.md

詳細

nostics

すべてのエラー条件は、安定したコード、ドキュメント URL、実行可能な修正方法を持つ型付きの Diagnostic(Errorを継承)になります。toJSON()でシリアライズできます。

Diagnostic:name(コード)、message/why(補間されたテキスト)、fix?、docs?、sources?('file:line:column')、cause?、toJSON()。これをスローし、instanceof Diagnosticで捕捉し、プロセス間でtoJSON()を送信できます。

defineDiagnostics

コードごとに呼び出し可能なハンドルを返します。ハンドルを呼び出すと、新しいDiagnosticが生成され、すべてのレポーターが順番に実行され、その後にDiagnosticが返されます。返り値をthrowすると例外が発生します(レポーターは引き続き実行されるため、スローされたDiagnosticもレポートされます)。

import { createConsoleReporter, defineDiagnostics } from 'nostics'

const diagnostics = /*#__PURE__*/ defineDiagnostics({
  docsBase: (code) => `https://nuxt.com/e/${code.replace('NUXT_', '').toLowerCase()}`,
  reporters: [/*#__PURE__*/ createConsoleReporter()],
  codes: {
    NUXT_B1001: {
      why: 'Could not compile template.',
      fix: 'Check the template for syntax errors.',
    },
    NUXT_B2011: {
      why: (p: { src: string }) => `Invalid plugin "${p.src}". src option is required.`,
      fix: 'Pass a string path or an object with a `src` to `addPlugin()`.',
    },
    NUXT_W9001: { why: 'message', docs: false }, // per-code: string overrides docsBase, false opts out
  },
})
  • docsBase string | (code) => string | undefined:文字列の場合は/${code.toLowerCase()}が追加されます。関数の場合は完全な URL(または省略する場合はundefined)を返します。
  • codes:各定義にはwhy(string | (params) => string。唯一の必須フィールドであり、Error.messageになります)が必要です。fix(string | (params) => string)、docs(string | false)、data(object | (params) => object)は任意です。各コードで解決されたdataには型が付与され、toJSON()に含まれます。
  • reporters:呼び出しごとに実行されます。省略可能です。optionsの型は交差され、必須のレポーターオプションは呼び出し箇所でも必須になります。コードが常にthrowされるカタログでは、省略する(または[]を渡す)ようにしてください。スローされたDiagnosticにはすでにメッセージが含まれているため、コンソールレポーターを使うと一度出力された後、捕捉されないエラーからも再度表示され、重複が目に見える形で発生します。レポーターが必要な警告のみのケースと、致命的な例外をスローするケースでは、別々のカタログを使用してください。
  • パラメーターの推論:why、fix、dataのパラメーターは交差され、呼び出し箇所で必須になります。whyで{ src }が必要で、fixで{ date }が必要な場合、呼び出しには{ src, date }が必要です。

呼び出し箇所

diagnostics.NUXT_B1001() // no params: report only
diagnostics.NUXT_B2011({ src: '/plugins/bad.ts' }) // params first
diagnostics.NUXT_B2011({
  src,
  cause: originalError,
  sources: ['nuxt.config.ts:42:3'],
}) // runtime fields merge in
diagnostics.NUXT_B2011({ src }, { method: 'error' }) // reporter options second
throw diagnostics.NUXT_B2011({ src }) // raise

cause/sourcesはparamsオブジェクトに含めます。sourcesは、JSのスタックがライブラリ内部を指すビルド/設定の診断で特に重要です。if (err instanceof Diagnostic)で捕捉してから、.name、.message、.fix、.docs、.dataを読み取ります。

定義時のdataはdefineProdDiagnostics()には含まれません。その.dataはundefinedです。そのため、開発版/本番版の三項演算子では、.dataの型はコードのdata型またはundefinedになります。

レポーター

(diagnostic: Diagnostic, options?: Opts) => void。必須のoptions型を宣言すると、呼び出し箇所で2番目の引数が必須になり、型が付与されます。

レポーターインポート説明
createConsoleReporter(options?)nosticsconsole[method](formatter(d))。methodのデフォルトは'warn'('log'|'warn'|'error')、formatterのデフォルトはformatDiagnosticです。どちらもオプションで指定でき、methodは呼び出しごとに上書きすることもできます。
createFetchReporter(url)nostics/reporters/fetch診断JSONをURLにPOSTします。失敗は無視されます。
createFileReporter(options?)nostics/reporters/nodeNDJSONをローカルファイル(デフォルトは.nostics.log)に追記します。
createDevReporter()nostics/reporters/devimport.meta.hot.send()を介して、toJSON()をVite開発サーバーに送信します。
import type { DiagnosticReporter } from 'nostics'
const sentryReporter: DiagnosticReporter = (d) =>
  sentry.captureMessage(d.message, { tags: { code: d.name } })
const audited: DiagnosticReporter<{ priority: number }> = (d, o) =>
  audit.log({ name: d.name, priority: o.priority })
// → audited makes diagnostics.X({...}, { priority: 1 }) required and type-checked.

フォーマッター

フォーマッターインポート説明
formatDiagnosticnosticsUnicode 文字で装飾されたプレーン文字列です(組み込みのレポーターが使用します)。
ansiFormatter(colors)nostics/formatters/ansi色付きです。Colors インターフェース(red/yellow/cyan/gray/bold/dim。それぞれ (s) => string)を受け取ります。
jsonFormatternostics/formatters/jsontoJSON() を介した JSON.stringify(diagnostic) です。

formatDiagnostic の出力では、詳細の順序は fix → sources → see で固定され、欠落しているフィールドは省略されます。

[NUXT_B2011] Invalid plugin `/plugins/bad.ts`. src option is required.
├▶ fix: Pass a string path or an object with a `src` to `addPlugin()`.
├▶ sources: nuxt.config.ts:42:3
╰▶ see: https://nuxt.com/e/b2011

Vite プラグイン(@nostics/unplugin、開発依存関係)

@nostics/unplugin/strip-transform(ライブラリ作成者向け、ビルド最適化)と @nostics/unplugin/dev-server-collector(アプリ開発者向け、開発時の収集)があります。どちらも unplugin ベースで、.vite()、.webpack()、.rollup() などを使用できます。

  • nosticsStrip は defineDiagnostics() に /*#__PURE__*/ を付け、裸の診断式文を NODE_ENV ガードで囲み、本番環境でツリーシェイクできるようにします。オプションは packageName?(デフォルトは 'nostics')です。throw/return/代入は動作の一部であるため、そのまま残ります。追跡するには、相対インポートを使用し、カタログを直接エクスポートしてください。ファクトリーラッパーや深いバレルは使わないでください。
    • プラグインは任意です。カタログに手動でアノテーションを付ければ、ビルド変換なしでも同じ本番出力になります。defineDiagnostics( の前と、その内部の各レポーターファクトリー呼び出しの前に /*#__PURE__*/ を付け(ここにあるすべての例と同様)、レポート専用の各呼び出し箇所を開発用ガードで囲んでください(process.env.NODE_ENV !== 'production' && diagnostics.CODE(p))。アノテーションは常にソースに記述してください。レポート専用の呼び出し箇所がガードされておらず、それらに手を加えずに取り除きたい場合は、プラグインを使用してください。
  • nosticsCollector は、Vite の WebSocket 経由で createDevReporter() の診断を監視し、createFileReporter を介して NDJSON として書き込みます。Vite 専用です。オプションは logFile?(デフォルトは .nostics.log)、debug?(デフォルトは !!process.env.DEBUG)です。
// vite.config.ts
import { nosticsStrip } from '@nostics/unplugin/strip-transform'
import { nosticsCollector } from '@nostics/unplugin/dev-server-collector'
export default defineConfig({
  plugins: [nosticsStrip.vite(), nosticsCollector.vite()],
})

// src/diagnostics.ts — pair the collector with createDevReporter()
import { createConsoleReporter, defineDiagnostics } from 'nostics'
import { createDevReporter } from 'nostics/reporters/dev'
export const diagnostics = /*#__PURE__*/ defineDiagnostics({
  reporters: [/*#__PURE__*/ createConsoleReporter(), /*#__PURE__*/ createDevReporter()],
  codes: {/* ... */},
})

本番ビルド

  • レポート専用の診断(裸の diagnostics.X())は取り除かれるはずです。nosticsStrip または手動のアノテーションでそれらを削除すると、未使用のカタログがツリーシェイクされます。
  • 残る診断(throw/return/代入/引数)はそのまま残り、各診断からカタログ全体に到達可能になるため、すべての why/fix が同梱されます。すべてのライブラリが本番環境で throw するわけではありません。レポートのみを行う場合は、ストリッピングだけで十分なので、ここで説明は終わりです。

ライブラリが本番環境で throw する場合は、定義時に NODE_ENV の三項演算子を使って defineProdDiagnostics を選択してください。これにより、利用側のバンドラーが開発用ブランチ(カタログ内のすべてのテキスト)を削除できます。

import { defineDiagnostics, defineProdDiagnostics } from 'nostics'
export const diagnostics =
  process.env.NODE_ENV === 'production'
    ? /*#__PURE__*/ defineProdDiagnostics({ docsBase })
    : /*#__PURE__*/ defineDiagnostics({
        docsBase,
        reporters: [/* ... */],
        codes: {/* text */},
      })

アクセスされたコードがインスタンスの name になり、docs は引き続き docsBase から導出されます。why はドキュメント URL が存在する場合はその URL を指し、存在しない場合は空になります。why/fix のテキストは同梱されません。デフォルトでは reporters はありません(そのため、残った throw がログを出力した後に未捕捉エラーとして再度表面化することはありません)。本番環境のテレメトリーを維持するには、reporters を渡してください。nosticsStrip は、この三項演算子を直接のカタログエクスポートと同様に追跡します。

規約

  • コードは、安定した完全修飾の PREFIX_XNNNN(B はビルド、R はランタイム、C は設定、D は非推奨)です。公開済みのコードを再利用したり、割り当て直したりしないでください。
  • テストでは、メッセージや整形済みテキストではなく、診断コードを検証してください。スローされた Diagnostic の .name、またはレポーターの出力に含まれる [CODE] を確認してください。
  • 常に why を指定し、解決方法が分かっている場合は fix も指定してください(人間とエージェントにとって最も実用的なフィールドです)。ランタイム値にはパラメーター化されたテンプレートを使い、ファクトリーの外で文字列を連結しないでください。
  • why は診断、fix は解決策です。両者を分け、重複させないでください。 why には問題点のみを記載し、fix には対処方法のみを記載します。レポーターは両方を出力するため、両方に含まれる文言は冗長です。1つの文に両方の内容が含まれている場合("A hash must start with '#'. Prefix it with '#'.")、文全体を why に入れて fix でも繰り返すのではなく、診断を why に、解決策を fix に分けてください。fix にもパラメーター関数((p) => ...)を指定できるため、値を含む解決策(use "#${p.hash}")は why に残さず、fix に移してください。
  • エラーを再スローするときは cause を渡し、JS のスタックがユーザーのソースを反映していない場合は sources を渡してください。
  • 大規模なカタログはドメインごとに分割してください(diagnostics/build.ts、runtime.ts、config.ts)。それぞれ index.ts から再エクスポートし、各 defineDiagnostics() で独自のコード範囲を使用しながら docsBase を共有します。

参考資料

  • 既存ライブラリを nostics に移行する場合(ランタイムの動作を変えずに、console.warn/console.error/warn()/スローされる Error を診断コードに置き換える場合):references/migration.md の手順を最初から最後まで実施してください。
  • エラーコードのドキュメントサイトの構築(ページテンプレート、デプロイ、エージェントの最適化):references/documentation-site.md。

コメント