diff --git a/AGENTS.md b/AGENTS.md index 038d6386..b8915526 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -92,7 +92,7 @@ Any change to one lands in the other in the same PR: adding a dock, wiring a new ## Structured Diagnostics (Error Codes) -All node-side warnings and errors use structured diagnostics via [`nostics`](https://www.npmjs.com/package/nostics). Never use raw `console.warn`, `console.error`, or `throw new Error` with ad-hoc messages in node-side code - always define a coded diagnostic. +All node-side warnings and errors use structured diagnostics via [`nostics`](https://www.npmjs.com/package/nostics). Never use raw `console.warn`, `console.error`, or `throw new Error` with ad-hoc messages in node-side code - always define a coded diagnostic. Import `defineDiagnostics` (and `Diagnostic` for `instanceof` checks) from `devframe/utils/nostics` rather than from `nostics` directly - it pre-wires devframe's ANSI console reporter, so a plugin's `diagnostics.ts` never builds its own reporter (`colors`, `ansiFormatter`) or depends on `nostics` itself. Prefix: **`DF`**. Codes are sequential 4-digit numbers (e.g. `DF0033`). Check the existing diagnostics file to find the next available number. diff --git a/alias.ts b/alias.ts index 53913c2b..839d87a0 100644 --- a/alias.ts +++ b/alias.ts @@ -29,6 +29,7 @@ export const alias = { 'devframe/utils/hash': r('devframe/src/utils/hash.ts'), 'devframe/utils/launch-editor': r('devframe/src/utils/launch-editor.ts'), 'devframe/utils/nanoid': r('devframe/src/utils/nanoid.ts'), + 'devframe/utils/nostics': r('devframe/src/utils/nostics.ts'), 'devframe/utils/open': r('devframe/src/utils/open.ts'), 'devframe/utils/remote-assets': r('devframe/src/utils/remote-assets.ts'), 'devframe/utils/simple-schema': r('devframe/src/utils/simple-schema.ts'), diff --git a/packages/devframe/package.json b/packages/devframe/package.json index e0711008..836889a7 100644 --- a/packages/devframe/package.json +++ b/packages/devframe/package.json @@ -51,6 +51,7 @@ "./utils/hash": "./dist/utils/hash.mjs", "./utils/launch-editor": "./dist/utils/launch-editor.mjs", "./utils/nanoid": "./dist/utils/nanoid.mjs", + "./utils/nostics": "./dist/utils/nostics.mjs", "./utils/open": "./dist/utils/open.mjs", "./utils/remote-assets": "./dist/utils/remote-assets.mjs", "./utils/simple-schema": "./dist/utils/simple-schema.mjs", diff --git a/packages/devframe/src/adapters/mcp/__tests__/stringify.test.ts b/packages/devframe/src/adapters/mcp/__tests__/stringify.test.ts index c628f0da..4d45e748 100644 --- a/packages/devframe/src/adapters/mcp/__tests__/stringify.test.ts +++ b/packages/devframe/src/adapters/mcp/__tests__/stringify.test.ts @@ -1,4 +1,4 @@ -import { Diagnostic } from 'nostics' +import { Diagnostic } from 'devframe/utils/nostics' import { describe, expect, it } from 'vitest' import { formatMcpError, stringifyForMcp } from '../stringify' diff --git a/packages/devframe/src/adapters/mcp/stringify.ts b/packages/devframe/src/adapters/mcp/stringify.ts index e8bb43dd..bc0d41a6 100644 --- a/packages/devframe/src/adapters/mcp/stringify.ts +++ b/packages/devframe/src/adapters/mcp/stringify.ts @@ -1,4 +1,4 @@ -import { Diagnostic } from 'nostics' +import { Diagnostic } from 'devframe/utils/nostics' /** * JSON-coercing serializer for MCP text payloads. diff --git a/packages/devframe/src/cli/connect.ts b/packages/devframe/src/cli/connect.ts index dd13bbaa..a42b4405 100644 --- a/packages/devframe/src/cli/connect.ts +++ b/packages/devframe/src/cli/connect.ts @@ -2,7 +2,7 @@ import type { Tool } from '@modelcontextprotocol/server' import type { DevframeInstanceRecord } from '../node/instance-registry' import process from 'node:process' import { toAgentToolName } from 'devframe/utils/agent-tool-name' -import { Diagnostic } from 'nostics' +import { Diagnostic } from 'devframe/utils/nostics' import { joinURL } from 'ufo' import { diagnostics } from '../node/diagnostics' import { listLiveDevframeInstances, probeDevframeOrigin } from '../node/instance-registry' diff --git a/packages/devframe/src/node/diagnostics.ts b/packages/devframe/src/node/diagnostics.ts index 6b8b193a..c4fed343 100644 --- a/packages/devframe/src/node/diagnostics.ts +++ b/packages/devframe/src/node/diagnostics.ts @@ -1,12 +1,10 @@ -import { defineDiagnostics } from 'nostics' -import { devframeReporter } from '../utils/diagnostics-reporter' +import { defineDiagnostics } from 'devframe/utils/nostics' // DF00xx codes are allocated across packages (e.g. @devframes/json-render // owns DF0037–DF0041), so this file alone doesn't show the next free // number — check `docs/errors/` for the full allocation before adding one. export const diagnostics = defineDiagnostics({ docsBase: 'https://devfra.me/errors', - reporters: [devframeReporter], codes: { DF0006: { why: (p: { name: string }) => `RPC function "${p.name}" is not registered`, diff --git a/packages/devframe/src/node/host-diagnostics.ts b/packages/devframe/src/node/host-diagnostics.ts index 1353bfa8..9703b877 100644 --- a/packages/devframe/src/node/host-diagnostics.ts +++ b/packages/devframe/src/node/host-diagnostics.ts @@ -1,6 +1,5 @@ import type { DevframeDiagnosticsHost as DevframeDiagnosticsHostType, DevframeDiagnosticsLogger, DevframeNodeContext } from 'devframe/types' -import { defineDiagnostics } from 'nostics' -import { devframeReporter } from '../utils/diagnostics-reporter' +import { defineDiagnostics } from 'devframe/utils/nostics' export class DevframeDiagnosticsHost implements DevframeDiagnosticsHostType { private _registry: Record = {} @@ -9,16 +8,9 @@ export class DevframeDiagnosticsHost implements DevframeDiagnosticsHostType { get: (_, code: string) => this._registry[code], }) - readonly defineDiagnostics: DevframeDiagnosticsHostType['defineDiagnostics'] = (opts) => { - const merged = { - ...opts, - reporters: [devframeReporter, ...(opts.reporters ?? [])], - } as Parameters[0] - // Runtime passthrough: the per-call `Codes` generic can't be threaded - // through this assigned arrow, so the narrow return type is restored by - // the property's declared signature at every call site. - return defineDiagnostics(merged) as any - } + // Already pre-wires devframe's ANSI console reporter — no extra merging + // needed here, the host's `defineDiagnostics` just is the shared one. + readonly defineDiagnostics: DevframeDiagnosticsHostType['defineDiagnostics'] = defineDiagnostics constructor( public readonly context: DevframeNodeContext, diff --git a/packages/devframe/src/rpc/diagnostics.ts b/packages/devframe/src/rpc/diagnostics.ts index 3ba5b711..96b3ab9e 100644 --- a/packages/devframe/src/rpc/diagnostics.ts +++ b/packages/devframe/src/rpc/diagnostics.ts @@ -1,9 +1,7 @@ -import { defineDiagnostics } from 'nostics' -import { devframeReporter } from '../utils/diagnostics-reporter' +import { defineDiagnostics } from 'devframe/utils/nostics' export const diagnostics = defineDiagnostics({ docsBase: 'https://devfra.me/errors', - reporters: [devframeReporter], codes: { DF0019: { why: (p: { name: string }) => diff --git a/packages/devframe/src/types/diagnostics.ts b/packages/devframe/src/types/diagnostics.ts index 15fd09eb..4b48b5fc 100644 --- a/packages/devframe/src/types/diagnostics.ts +++ b/packages/devframe/src/types/diagnostics.ts @@ -1,4 +1,4 @@ -import type { defineDiagnostics, Diagnostic, DiagnosticDefinition } from 'nostics' +import type { defineDiagnostics } from 'devframe/utils/nostics' /** * The shared diagnostics lookup exposed by the host. A `Proxy` that resolves @@ -10,15 +10,14 @@ import type { defineDiagnostics, Diagnostic, DiagnosticDefinition } from 'nostic export type DevframeDiagnosticsLogger = Record /** - * Options accepted by the host's `defineDiagnostics()` factory — mirrors - * `nostics`'s shape but the host pre-wires its ANSI console reporter, so - * plugins typically omit `reporters`. + * Options accepted by the host's `defineDiagnostics()` factory. Re-exported + * from `devframe/utils/nostics` — the same shape every module-level + * `diagnostics.ts` (devframe core, `@devframes/hub`, the built-in plugins) + * accepts, since `host.defineDiagnostics()` and the top-level + * `defineDiagnostics` from `devframe/utils/nostics` pre-wire the identical + * ANSI console reporter. */ -export interface DevframeDefineDiagnosticsOptions> { - docsBase?: string | ((code: keyof Codes) => string | undefined) - codes: Codes - reporters?: ReadonlyArray<(d: Diagnostic, o?: any) => void> -} +export type { DevframeDefineDiagnosticsOptions } from 'devframe/utils/nostics' /** * Host for structured diagnostics — a thin layer over `nostics` that lets @@ -64,10 +63,9 @@ export interface DevframeDiagnosticsHost { /** * Build a typed diagnostics object with the host's ANSI console reporter - * pre-wired. Mirrors `nostics`'s `defineDiagnostics` so integrations don't - * need to take a direct dependency on `nostics`. + * pre-wired. The same `devframe/utils/nostics` `defineDiagnostics` every + * built-in plugin's module-level `diagnostics.ts` uses, so integrations + * don't need to take a direct dependency on `nostics`. */ - defineDiagnostics: >( - options: DevframeDefineDiagnosticsOptions, - ) => ReturnType> + defineDiagnostics: typeof defineDiagnostics } diff --git a/packages/devframe/src/utils/diagnostics-reporter.ts b/packages/devframe/src/utils/diagnostics-reporter.ts deleted file mode 100644 index 44c9e2b1..00000000 --- a/packages/devframe/src/utils/diagnostics-reporter.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { Diagnostic } from 'nostics' -import { colors as c } from 'devframe/utils/colors' -import { ansiFormatter } from 'nostics/formatters/ansi' - -const formatAnsi = ansiFormatter(c) - -export interface DevframeReporterOptions { method?: 'log' | 'warn' | 'error' } - -export function devframeReporter(d: Diagnostic, { method = 'warn' }: DevframeReporterOptions = {}): void { - // eslint-disable-next-line no-console - console[method](formatAnsi(d)) -} diff --git a/packages/devframe/src/utils/nostics.ts b/packages/devframe/src/utils/nostics.ts new file mode 100644 index 00000000..d0aace0d --- /dev/null +++ b/packages/devframe/src/utils/nostics.ts @@ -0,0 +1,70 @@ +import type { AnyDiagnosticReporter, Diagnostic, DiagnosticDefinition, Diagnostics } from 'nostics' +import { colors } from 'devframe/utils/colors' +import { defineDiagnostics as defineNosticsDiagnostics } from 'nostics' +import { ansiFormatter } from 'nostics/formatters/ansi' + +const formatAnsi = ansiFormatter(colors) + +/** + * The reporter every {@link defineDiagnostics} call below wires in ahead of + * any caller-supplied ones: prints the diagnostic through devframe's own + * ANSI colors via `console[method]` (default `'warn'`). + */ +function devframeReporter(d: Diagnostic, { method = 'warn' }: { method?: 'log' | 'warn' | 'error' } = {}): void { + // eslint-disable-next-line no-console + console[method](formatAnsi(d)) +} + +/** + * Options accepted by {@link defineDiagnostics} — identical to `nostics`'s + * own `DefineDiagnosticsOptions`, minus the reporter devframe already + * prepends. + */ +export type DevframeDefineDiagnosticsOptions< + Codes extends Record, + Reporters extends readonly AnyDiagnosticReporter[] = [], +> = Parameters>[0] + +/** + * Drop-in replacement for `nostics`'s `defineDiagnostics()` with devframe's + * ANSI console reporter pre-wired ahead of any `reporters` passed in. Every + * `diagnostics.ts` in devframe core, `@devframes/hub`, `@devframes/json-render`, + * and the built-in plugins defines its codes through this instead of + * `nostics`'s own `defineDiagnostics` — the reporter registration lives + * here, once, so none of them need to build their own reporter (`colors`, + * `ansiFormatter`) or take a direct dependency on `nostics` themselves. + */ +export function defineDiagnostics< + const Codes extends Record, + const Reporters extends readonly AnyDiagnosticReporter[] = [], +>(options: { + docsBase?: string | ((code: keyof Codes) => string | undefined) + codes: Codes + reporters?: Reporters +}): Diagnostics { + return defineNosticsDiagnostics({ + ...options, + reporters: [devframeReporter, ...(options.reporters ?? [])], + }) as Diagnostics +} + +export { + createConsoleReporter, + defineProdDiagnostics, + Diagnostic, + formatDiagnostic, +} from 'nostics' + +export type { + AnyDiagnosticReporter, + ConsoleMethod, + ConsoleReporterOptions, + DiagnosticCallParams, + DiagnosticDefinition, + DiagnosticHandle, + DiagnosticInit, + DiagnosticReporter, + Diagnostics, +} from 'nostics' + +export { ansiFormatter } from 'nostics/formatters/ansi' diff --git a/packages/devframe/tsdown.config.ts b/packages/devframe/tsdown.config.ts index 5dd0ce62..68e88616 100644 --- a/packages/devframe/tsdown.config.ts +++ b/packages/devframe/tsdown.config.ts @@ -103,6 +103,7 @@ const serverEntries = { 'node/hub-internals': 'src/node/hub-internals/index.ts', 'internal/index': 'src/internal/index.ts', 'utils/launch-editor': 'src/utils/launch-editor.ts', + 'utils/nostics': 'src/utils/nostics.ts', 'utils/open': 'src/utils/open.ts', 'utils/remote-assets': 'src/utils/remote-assets.ts', 'utils/serve-static': 'src/utils/serve-static.ts', diff --git a/packages/hub/package.json b/packages/hub/package.json index 2d4b834c..0406d1fd 100644 --- a/packages/hub/package.json +++ b/packages/hub/package.json @@ -46,7 +46,6 @@ "@standard-schema/spec": "catalog:deps", "destr": "catalog:deps", "h3": "catalog:deps", - "nostics": "catalog:deps", "pathe": "catalog:deps", "perfect-debounce": "catalog:deps", "tinyexec": "catalog:deps", diff --git a/packages/hub/src/node/diagnostics.ts b/packages/hub/src/node/diagnostics.ts index 5905188f..f682b364 100644 --- a/packages/hub/src/node/diagnostics.ts +++ b/packages/hub/src/node/diagnostics.ts @@ -1,5 +1,4 @@ -import { defineDiagnostics } from 'nostics' -import { hubReporter } from '../utils/diagnostics-reporter' +import { defineDiagnostics } from 'devframe/utils/nostics' // Hub-side diagnostics for docks, terminals, messages, and commands. // Shares the `DF` prefix with devframe core; the hub reserves the @@ -12,7 +11,6 @@ import { hubReporter } from '../utils/diagnostics-reporter' // DF8400-DF8499 — commands export const diagnostics = defineDiagnostics({ docsBase: 'https://devfra.me/errors', - reporters: [hubReporter], codes: { DF8000: { why: (p: { id: string }) => `Devframe id "${p.id}" collides with a reserved hub path — it cannot be mounted directly under the hub base.`, diff --git a/packages/hub/src/utils/diagnostics-reporter.ts b/packages/hub/src/utils/diagnostics-reporter.ts deleted file mode 100644 index 335b7732..00000000 --- a/packages/hub/src/utils/diagnostics-reporter.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { Diagnostic } from 'nostics' -import { colors as c } from 'devframe/utils/colors' -import { ansiFormatter } from 'nostics/formatters/ansi' - -const formatAnsi = ansiFormatter(c) - -export interface HubReporterOptions { method?: 'log' | 'warn' | 'error' } - -export function hubReporter(d: Diagnostic, { method = 'warn' }: HubReporterOptions = {}): void { - // eslint-disable-next-line no-console - console[method](formatAnsi(d)) -} diff --git a/packages/json-render/package.json b/packages/json-render/package.json index b9ab2471..9187f922 100644 --- a/packages/json-render/package.json +++ b/packages/json-render/package.json @@ -46,7 +46,6 @@ }, "dependencies": { "@json-render/core": "catalog:deps", - "nostics": "catalog:deps", "zod": "catalog:deps" }, "devDependencies": { diff --git a/packages/json-render/src/node/diagnostics.ts b/packages/json-render/src/node/diagnostics.ts index ee0c8c4c..f2b8927a 100644 --- a/packages/json-render/src/node/diagnostics.ts +++ b/packages/json-render/src/node/diagnostics.ts @@ -1,16 +1,4 @@ -import type { Diagnostic } from 'nostics' -import { colors as c } from 'devframe/utils/colors' -import { defineDiagnostics } from 'nostics' -import { ansiFormatter } from 'nostics/formatters/ansi' - -const formatAnsi = ansiFormatter(c) - -interface ReporterOptions { method?: 'log' | 'warn' | 'error' } - -function jsonRenderReporter(d: Diagnostic, { method = 'warn' }: ReporterOptions = {}): void { - // eslint-disable-next-line no-console - console[method](formatAnsi(d)) -} +import { defineDiagnostics } from 'devframe/utils/nostics' // `@devframes/json-render` protocol/runtime diagnostics. These share the // `DF` prefix and live in the devframe core range (next free after the @@ -18,7 +6,6 @@ function jsonRenderReporter(d: Diagnostic, { method = 'warn' }: ReporterOptions // `console.*` in the UI package. export const diagnostics = defineDiagnostics({ docsBase: 'https://devfra.me/errors', - reporters: [jsonRenderReporter], codes: { DF0038: { why: (p: { id: string, key: string, issues: string }) => diff --git a/plugins/assets/package.json b/plugins/assets/package.json index 4808ef66..b8b4f98c 100644 --- a/plugins/assets/package.json +++ b/plugins/assets/package.json @@ -59,7 +59,6 @@ "cac": "catalog:deps", "chokidar": "catalog:deps", "image-meta": "catalog:deps", - "nostics": "catalog:deps", "pathe": "catalog:deps", "perfect-debounce": "catalog:deps", "tinyglobby": "catalog:deps", diff --git a/plugins/assets/src/diagnostics.ts b/plugins/assets/src/diagnostics.ts index fad59a0b..89627a06 100644 --- a/plugins/assets/src/diagnostics.ts +++ b/plugins/assets/src/diagnostics.ts @@ -1,4 +1,4 @@ -import { defineDiagnostics } from 'nostics' +import { defineDiagnostics } from 'devframe/utils/nostics' // Uses the plugin's own `DP_ASSETS_` prefix per the built-in plugin // convention, keeping it collision-free with devframe core (`DF`) and the diff --git a/plugins/code-server/package.json b/plugins/code-server/package.json index 0c968611..8bc152cd 100644 --- a/plugins/code-server/package.json +++ b/plugins/code-server/package.json @@ -61,8 +61,7 @@ "dependencies": { "@devframes/vite": "workspace:*", "cac": "catalog:deps", - "get-port-please": "catalog:deps", - "nostics": "catalog:deps" + "get-port-please": "catalog:deps" }, "devDependencies": { "@antfu/design": "catalog:frontend", diff --git a/plugins/code-server/src/node/diagnostics.ts b/plugins/code-server/src/node/diagnostics.ts index 5b505de5..486527f5 100644 --- a/plugins/code-server/src/node/diagnostics.ts +++ b/plugins/code-server/src/node/diagnostics.ts @@ -1,16 +1,4 @@ -import type { Diagnostic } from 'nostics' -import { colors as c } from 'devframe/utils/colors' -import { defineDiagnostics } from 'nostics' -import { ansiFormatter } from 'nostics/formatters/ansi' - -const formatAnsi = ansiFormatter(c) - -interface ReporterOptions { method?: 'log' | 'warn' | 'error' } - -function reporter(d: Diagnostic, { method = 'warn' }: ReporterOptions = {}): void { - // eslint-disable-next-line no-console - console[method](formatAnsi(d)) -} +import { defineDiagnostics } from 'devframe/utils/nostics' /** * Structured diagnostics for the code-server plugin. Uses the plugin's own @@ -19,7 +7,6 @@ function reporter(d: Diagnostic, { method = 'warn' }: ReporterOptions = {}): voi */ export const diagnostics = defineDiagnostics({ docsBase: 'https://devfra.me/errors', - reporters: [reporter], codes: { DP_CODE_SERVER_0001: { why: (p: { bin: string }) => diff --git a/plugins/data-inspector/package.json b/plugins/data-inspector/package.json index 07949691..a7a999ad 100644 --- a/plugins/data-inspector/package.json +++ b/plugins/data-inspector/package.json @@ -60,8 +60,7 @@ "dependencies": { "cac": "catalog:deps", "get-port-please": "catalog:deps", - "jora": "catalog:deps", - "nostics": "catalog:deps" + "jora": "catalog:deps" }, "devDependencies": { "@antfu/design": "catalog:frontend", diff --git a/plugins/data-inspector/src/node/diagnostics.ts b/plugins/data-inspector/src/node/diagnostics.ts index 3736944d..2fbc1779 100644 --- a/plugins/data-inspector/src/node/diagnostics.ts +++ b/plugins/data-inspector/src/node/diagnostics.ts @@ -1,16 +1,4 @@ -import type { Diagnostic } from 'nostics' -import { colors as c } from 'devframe/utils/colors' -import { defineDiagnostics } from 'nostics' -import { ansiFormatter } from 'nostics/formatters/ansi' - -const formatAnsi = ansiFormatter(c) - -interface ReporterOptions { method?: 'log' | 'warn' | 'error' } - -function reporter(d: Diagnostic, { method = 'warn' }: ReporterOptions = {}): void { - // eslint-disable-next-line no-console - console[method](formatAnsi(d)) -} +import { defineDiagnostics } from 'devframe/utils/nostics' /** * Structured diagnostics for `@devframes/plugin-data-inspector`. Node-side @@ -19,7 +7,6 @@ function reporter(d: Diagnostic, { method = 'warn' }: ReporterOptions = {}): voi */ export const diagnostics = defineDiagnostics({ docsBase: 'https://devfra.me/errors', - reporters: [reporter], codes: { DP_DATA_INSPECTOR_0001: { why: (p: { id: string }) => `No data source is registered under "${p.id}".`, diff --git a/plugins/inspect/package.json b/plugins/inspect/package.json index 399893c0..32a7beeb 100644 --- a/plugins/inspect/package.json +++ b/plugins/inspect/package.json @@ -55,8 +55,7 @@ } }, "dependencies": { - "cac": "catalog:deps", - "nostics": "catalog:deps" + "cac": "catalog:deps" }, "devDependencies": { "@antfu/design": "catalog:frontend", diff --git a/plugins/inspect/src/diagnostics.ts b/plugins/inspect/src/diagnostics.ts index f5dacb38..eae8c662 100644 --- a/plugins/inspect/src/diagnostics.ts +++ b/plugins/inspect/src/diagnostics.ts @@ -1,4 +1,4 @@ -import { defineDiagnostics } from 'nostics' +import { defineDiagnostics } from 'devframe/utils/nostics' /** * Structured diagnostics for `@devframes/plugin-inspect`. Node-side only. diff --git a/plugins/messages/package.json b/plugins/messages/package.json index b56b0598..38e2223d 100644 --- a/plugins/messages/package.json +++ b/plugins/messages/package.json @@ -59,8 +59,7 @@ } }, "dependencies": { - "cac": "catalog:deps", - "nostics": "catalog:deps" + "cac": "catalog:deps" }, "devDependencies": { "@antfu/design": "catalog:frontend", diff --git a/plugins/messages/src/diagnostics.ts b/plugins/messages/src/diagnostics.ts index 33c82a16..2ae922a7 100644 --- a/plugins/messages/src/diagnostics.ts +++ b/plugins/messages/src/diagnostics.ts @@ -1,16 +1,4 @@ -import type { Diagnostic } from 'nostics' -import { colors as c } from 'devframe/utils/colors' -import { defineDiagnostics } from 'nostics' -import { ansiFormatter } from 'nostics/formatters/ansi' - -const formatAnsi = ansiFormatter(c) - -interface ReporterOptions { method?: 'log' | 'warn' | 'error' } - -function reporter(d: Diagnostic, { method = 'warn' }: ReporterOptions = {}): void { - // eslint-disable-next-line no-console - console[method](formatAnsi(d)) -} +import { defineDiagnostics } from 'devframe/utils/nostics' /** * Structured diagnostics for `@devframes/plugin-messages`. Node-side only. @@ -20,7 +8,6 @@ function reporter(d: Diagnostic, { method = 'warn' }: ReporterOptions = {}): voi */ export const diagnostics = defineDiagnostics({ docsBase: 'https://devfra.me/errors', - reporters: [reporter], codes: { DP_MESSAGES_0001: { why: (p: { id: string }) => diff --git a/plugins/og/package.json b/plugins/og/package.json index 5329a166..43f27b69 100644 --- a/plugins/og/package.json +++ b/plugins/og/package.json @@ -58,7 +58,6 @@ }, "dependencies": { "cac": "catalog:deps", - "nostics": "catalog:deps", "parse5": "catalog:deps" }, "devDependencies": { diff --git a/plugins/og/src/diagnostics.ts b/plugins/og/src/diagnostics.ts index b36ad4ba..21a112d5 100644 --- a/plugins/og/src/diagnostics.ts +++ b/plugins/og/src/diagnostics.ts @@ -1,4 +1,4 @@ -import { defineDiagnostics } from 'nostics' +import { defineDiagnostics } from 'devframe/utils/nostics' export const diagnostics = defineDiagnostics({ docsBase: 'https://devfra.me/errors', diff --git a/plugins/terminals/package.json b/plugins/terminals/package.json index 2aaa9367..6498a2d4 100644 --- a/plugins/terminals/package.json +++ b/plugins/terminals/package.json @@ -61,7 +61,6 @@ "dependencies": { "@devframes/vite": "workspace:*", "cac": "catalog:deps", - "nostics": "catalog:deps", "zigpty": "catalog:deps" }, "devDependencies": { diff --git a/plugins/terminals/src/node/diagnostics.ts b/plugins/terminals/src/node/diagnostics.ts index 5cf3ddd7..b6460db4 100644 --- a/plugins/terminals/src/node/diagnostics.ts +++ b/plugins/terminals/src/node/diagnostics.ts @@ -1,16 +1,4 @@ -import type { Diagnostic } from 'nostics' -import { colors as c } from 'devframe/utils/colors' -import { defineDiagnostics } from 'nostics' -import { ansiFormatter } from 'nostics/formatters/ansi' - -const formatAnsi = ansiFormatter(c) - -interface ReporterOptions { method?: 'log' | 'warn' | 'error' } - -function reporter(d: Diagnostic, { method = 'warn' }: ReporterOptions = {}): void { - // eslint-disable-next-line no-console - console[method](formatAnsi(d)) -} +import { defineDiagnostics } from 'devframe/utils/nostics' /** * Structured diagnostics for the terminals plugin. Uses the plugin's own @@ -19,7 +7,6 @@ function reporter(d: Diagnostic, { method = 'warn' }: ReporterOptions = {}): voi */ export const diagnostics = defineDiagnostics({ docsBase: 'https://devfra.me/errors', - reporters: [reporter], codes: { DP_TERMINALS_0001: { why: (p: { id: string }) => `Terminal session "${p.id}" does not exist`, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d6d8a45d..51f2dbb5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1217,9 +1217,6 @@ importers: h3: specifier: catalog:deps version: 2.0.1-rc.26(crossws@0.4.10(srvx@0.12.4)) - nostics: - specifier: catalog:deps - version: 1.2.0 pathe: specifier: catalog:deps version: 2.0.3 @@ -1326,9 +1323,6 @@ importers: '@json-render/core': specifier: catalog:deps version: 0.19.0(zod@4.4.3) - nostics: - specifier: catalog:deps - version: 1.2.0 zod: specifier: catalog:deps version: 4.4.3 @@ -1557,9 +1551,6 @@ importers: image-meta: specifier: catalog:deps version: 0.2.2 - nostics: - specifier: catalog:deps - version: 1.2.0 pathe: specifier: catalog:deps version: 2.0.3 @@ -1645,9 +1636,6 @@ importers: get-port-please: specifier: catalog:deps version: 3.2.0 - nostics: - specifier: catalog:deps - version: 1.2.0 devDependencies: '@antfu/design': specifier: catalog:frontend @@ -1703,9 +1691,6 @@ importers: jora: specifier: catalog:deps version: 1.0.0-beta.16 - nostics: - specifier: catalog:deps - version: 1.2.0 devDependencies: '@antfu/design': specifier: catalog:frontend @@ -1864,9 +1849,6 @@ importers: cac: specifier: catalog:deps version: 7.0.0 - nostics: - specifier: catalog:deps - version: 1.2.0 devDependencies: '@antfu/design': specifier: catalog:frontend @@ -1945,9 +1927,6 @@ importers: cac: specifier: catalog:deps version: 7.0.0 - nostics: - specifier: catalog:deps - version: 1.2.0 devDependencies: '@antfu/design': specifier: catalog:frontend @@ -2021,9 +2000,6 @@ importers: cac: specifier: catalog:deps version: 7.0.0 - nostics: - specifier: catalog:deps - version: 1.2.0 parse5: specifier: catalog:deps version: 8.0.1 @@ -2088,9 +2064,6 @@ importers: cac: specifier: catalog:deps version: 7.0.0 - nostics: - specifier: catalog:deps - version: 1.2.0 zigpty: specifier: catalog:deps version: 0.2.1 diff --git a/tests/__snapshots__/tsnapi/@devframes/json-render/node.snapshot.d.ts b/tests/__snapshots__/tsnapi/@devframes/json-render/node.snapshot.d.ts index f6c0ee0b..cda01523 100644 --- a/tests/__snapshots__/tsnapi/@devframes/json-render/node.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/@devframes/json-render/node.snapshot.d.ts @@ -15,7 +15,7 @@ export declare function createJsonRenderView(_: AnyContext, _: CreateJsonRenderV // #endregion // #region Variables -export declare const jsonRenderDiagnostics: import("nostics").Diagnostics<{ +export declare const jsonRenderDiagnostics: Diagnostics<{ readonly DF0038: { readonly why: (p: { id: string; @@ -44,5 +44,7 @@ export declare const jsonRenderDiagnostics: import("nostics").Diagnostics<{ }) => string; readonly fix: "Specs and state travel as strict JSON — remove functions, symbols, class instances, Map/Set, or circular references."; }; -}, readonly [typeof jsonRenderReporter]>; +}, readonly [(d: Diagnostic, { method }?: { + method?: "log" | "warn" | "error"; +}) => void]>; // #endregion \ No newline at end of file diff --git a/tests/__snapshots__/tsnapi/@devframes/plugin-code-server/node.snapshot.d.ts b/tests/__snapshots__/tsnapi/@devframes/plugin-code-server/node.snapshot.d.ts index 11c3bdba..102447b0 100644 --- a/tests/__snapshots__/tsnapi/@devframes/plugin-code-server/node.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/@devframes/plugin-code-server/node.snapshot.d.ts @@ -89,7 +89,7 @@ export declare function setupCodeServer(_: DevframeNodeContext, _?: CodeServerOp // #endregion // #region Variables -export declare const diagnostics: import("nostics").Diagnostics<{ +export declare const diagnostics: Diagnostics<{ readonly DP_CODE_SERVER_0001: { readonly why: (p: { bin: string; @@ -125,5 +125,7 @@ export declare const diagnostics: import("nostics").Diagnostics<{ }) => string; readonly fix: "Check the tunnel logs, ensure the `code` CLI is signed in, or raise `startTimeout`."; }; -}, readonly [typeof reporter]>; +}, readonly [(d: Diagnostic, { method }?: { + method?: "log" | "warn" | "error"; +}) => void]>; // #endregion \ No newline at end of file diff --git a/tests/__snapshots__/tsnapi/@devframes/plugin-terminals/node.snapshot.d.ts b/tests/__snapshots__/tsnapi/@devframes/plugin-terminals/node.snapshot.d.ts index 3732906a..235d0c40 100644 --- a/tests/__snapshots__/tsnapi/@devframes/plugin-terminals/node.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/@devframes/plugin-terminals/node.snapshot.d.ts @@ -50,7 +50,7 @@ export declare function setupTerminals(_: DevframeNodeContext, _?: TerminalsOpti // #endregion // #region Variables -export declare const diagnostics: import("nostics").Diagnostics<{ +export declare const diagnostics: Diagnostics<{ readonly DP_TERMINALS_0001: { readonly why: (p: { id: string; @@ -88,5 +88,7 @@ export declare const diagnostics: import("nostics").Diagnostics<{ readonly why: "Terminals manager is not initialised on this context"; readonly fix: "Call setupTerminals(ctx) (or use createTerminalsDevframe) before invoking terminal RPCs."; }; -}, readonly [typeof reporter]>; +}, readonly [(d: Diagnostic, { method }?: { + method?: "log" | "warn" | "error"; +}) => void]>; // #endregion \ No newline at end of file diff --git a/tests/__snapshots__/tsnapi/devframe/index.snapshot.d.ts b/tests/__snapshots__/tsnapi/devframe/index.snapshot.d.ts index 2d89978c..a5a5e5bb 100644 --- a/tests/__snapshots__/tsnapi/devframe/index.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/devframe/index.snapshot.d.ts @@ -127,11 +127,6 @@ export interface DevframeCliOptions { flags?: CliFlagsSchema; } export interface DevframeConnectionConfigsRegistry {} -export interface DevframeDefineDiagnosticsOptions> { - docsBase?: string | ((_: keyof Codes) => string | undefined); - codes: Codes; - reporters?: ReadonlyArray<(d: Diagnostic, o?: any) => void>; -} export interface DevframeDefinition { id: string; name: string; @@ -156,7 +151,7 @@ export interface DevframeDefinition { export interface DevframeDiagnosticsHost { readonly logger: DevframeDiagnosticsLogger; register: (_: Record) => void; - defineDiagnostics: >(_: DevframeDefineDiagnosticsOptions) => ReturnType>; + defineDiagnostics: typeof defineDiagnostics; } export interface DevframeDockDefaults { title?: string; @@ -435,6 +430,7 @@ export interface ScopedBroadcastOptions { // #region Types export type AgentToolProvider = () => readonly AgentToolInput[]; +export type DevframeDefineDiagnosticsOptions, Reporters extends readonly AnyDiagnosticReporter[] = []> = Parameters>[0]; export type DevframeDeploymentKind = 'standalone' | 'hosted'; export type DevframeDiagnosticsLogger = Record; export type DevframeDuplicationStrategy = 'warn' | 'silent' | 'throw' | 'duplicate'; diff --git a/tests/__snapshots__/tsnapi/devframe/internal.snapshot.d.ts b/tests/__snapshots__/tsnapi/devframe/internal.snapshot.d.ts index 31097203..3769beec 100644 --- a/tests/__snapshots__/tsnapi/devframe/internal.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/devframe/internal.snapshot.d.ts @@ -305,7 +305,9 @@ export declare const diagnostics: import("nostics").Diagnostics<{ }) => string; readonly fix: "A remote-assets `package` must be a valid npm package name and `version` an exact semver version (e.g. `1.2.3`) — they are interpolated into CDN URLs and the cache path."; }; -}, readonly [typeof devframeReporter]>; +}, readonly [(d: import("nostics").Diagnostic, { method }?: { + method?: "log" | "warn" | "error"; +}) => void]>; // #endregion // #region Other diff --git a/tests/__snapshots__/tsnapi/devframe/utils/nostics.snapshot.d.ts b/tests/__snapshots__/tsnapi/devframe/utils/nostics.snapshot.d.ts new file mode 100644 index 00000000..cbd4208a --- /dev/null +++ b/tests/__snapshots__/tsnapi/devframe/utils/nostics.snapshot.d.ts @@ -0,0 +1,21 @@ +/** + * Generated by tsnapi — public API snapshot of `devframe/utils/nostics` + */ +// #region Other +export { ansiFormatter } +export { AnyDiagnosticReporter } +export { ConsoleMethod } +export { ConsoleReporterOptions } +export { createConsoleReporter } +export { defineDiagnostics } +export { defineProdDiagnostics } +export { DevframeDefineDiagnosticsOptions } +export { Diagnostic } +export { DiagnosticCallParams } +export { DiagnosticDefinition } +export { DiagnosticHandle } +export { DiagnosticInit } +export { DiagnosticReporter } +export { Diagnostics } +export { formatDiagnostic } +// #endregion \ No newline at end of file diff --git a/tests/__snapshots__/tsnapi/devframe/utils/nostics.snapshot.js b/tests/__snapshots__/tsnapi/devframe/utils/nostics.snapshot.js new file mode 100644 index 00000000..9945358a --- /dev/null +++ b/tests/__snapshots__/tsnapi/devframe/utils/nostics.snapshot.js @@ -0,0 +1,11 @@ +/** + * Generated by tsnapi — public API snapshot of `devframe/utils/nostics` + */ +// #region Other +export { ansiFormatter } +export { createConsoleReporter } +export { defineDiagnostics } +export { defineProdDiagnostics } +export { Diagnostic } +export { formatDiagnostic } +// #endregion \ No newline at end of file diff --git a/tsconfig.base.json b/tsconfig.base.json index 2275de5e..62e621e2 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -73,6 +73,9 @@ "devframe/utils/nanoid": [ "./packages/devframe/src/utils/nanoid.ts" ], + "devframe/utils/nostics": [ + "./packages/devframe/src/utils/nostics.ts" + ], "devframe/utils/open": [ "./packages/devframe/src/utils/open.ts" ],