From 81bed8d9fc369f20c64756d0113cbd2aa98574c5 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Fri, 15 May 2026 11:40:59 +0900 Subject: [PATCH] feat(devframe)!: migrate from logs-sdk to nostics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adopts nostics 0.1.0 (the renamed-and-redesigned logs-sdk): `message`/`hint`/`level` become `why`/`fix`/per-call reporter method; `createLogger`/`Logger` are gone (each `defineDiagnostics()` returns its own callable handles); emit shape is `code.throw({...})` / `code.report({...}, { method })` instead of `code({...}).method()`. The `DevToolsDiagnosticsHost` keeps `register()` and `host.logger.CODE` via a Proxy over an internal registry, and `host.defineDiagnostics()` pre-wires the shared ANSI console reporter. `host.createLogger` is dropped (no nostics equivalent — use the typed return of `defineDiagnostics` directly). --- AGENTS.md | 24 +- docs/adapters/cli.md | 2 +- docs/errors/index.md | 2 +- docs/guide/diagnostics.md | 74 ++-- docs/guide/index.md | 2 +- packages/devframe/package.json | 2 +- .../devframe/src/adapters/mcp/build-server.ts | 6 +- packages/devframe/src/helpers/vite.ts | 4 +- packages/devframe/src/node/diagnostics.ts | 57 ++- packages/devframe/src/node/host-agent.ts | 12 +- .../devframe/src/node/host-diagnostics.ts | 44 +-- packages/devframe/src/node/host-functions.ts | 6 +- packages/devframe/src/node/host-views.ts | 4 +- .../devframe/src/node/rpc-shared-state.ts | 4 +- packages/devframe/src/node/rpc-streaming.ts | 10 +- packages/devframe/src/node/storage.ts | 4 +- packages/devframe/src/rpc/collector.ts | 10 +- packages/devframe/src/rpc/diagnostics.ts | 38 +- packages/devframe/src/rpc/dump/collect.ts | 8 +- packages/devframe/src/rpc/handler.ts | 4 +- packages/devframe/src/rpc/serialization.ts | 4 +- packages/devframe/src/rpc/validation.ts | 6 +- packages/devframe/src/types/context.ts | 4 +- packages/devframe/src/types/diagnostics.ts | 83 +++-- .../src/utils/diagnostics-reporter.ts | 12 + pnpm-lock.yaml | 328 ++++++++---------- pnpm-workspace.yaml | 2 +- skills/devframe/SKILL.md | 2 +- .../tsnapi/devframe/index.snapshot.d.ts | 1 + .../tsnapi/devframe/node.snapshot.d.ts | 13 +- .../tsnapi/devframe/types.snapshot.d.ts | 1 + 31 files changed, 359 insertions(+), 414 deletions(-) create mode 100644 packages/devframe/src/utils/diagnostics-reporter.ts diff --git a/AGENTS.md b/AGENTS.md index 26ee9d0..8132964 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -39,14 +39,14 @@ The `pnpm test` script intentionally runs `build` first so `tsnapi` snapshots co These reinforce devframe's positioning as "the container for one devtool integration, portable to multiple viewers". When in doubt, err on the side of "devframe provides primitives, the hub provides UX". - **Single-integration scope.** Devframe describes one tool. If a feature only makes sense when multiple tools share a UI — docking, a unified command palette, cross-tool toasts, terminal aggregation — it belongs in a hub package, not here. -- **Headless by default.** No default startup banners, no opinionated logging to stdout, no default styling. Provide hooks (`onReady`, `cli.configure`, etc.); let the application print its own branding. Structured diagnostics via `logs-sdk` are fine — ad-hoc `console.log`s baked into adapters are not. +- **Headless by default.** No default startup banners, no opinionated logging to stdout, no default styling. Provide hooks (`onReady`, `cli.configure`, etc.); let the application print its own branding. Structured diagnostics via `nostics` are fine — ad-hoc `console.log`s baked into adapters are not. - **Mount path depends on adapter context.** Given `id: 'foo'`, the default mount path is `/__foo/` for *hosted* adapters (`vite`, `embedded`) and `/` for *standalone* adapters (`cli`, `spa`, `build`). Authors override via `DevframeDefinition.basePath`. Don't hardcode mount paths in adapter code paths that may run standalone. - **SPAs own their basePath at runtime.** Build SPAs with relative asset paths (`vite.base: './'`); discover the effective base in the browser from the executing script's location / `document.baseURI`. `createBuild` / `createSpa` copy SPA output verbatim — no HTML rewriting, no build-time `--base` injection. The client (`connectDevframe`) resolves `.connection.json` relative to the runtime base automatically. - **CLI flags compose from both sides.** The `cac` instance backing `createCli` is exposed both to the `DevframeDefinition` (`cli.configure(cli)`) — for capabilities contributed by the tool itself — and to the `createCli` caller — for flags added at the final assembly stage. Parsed flag values are forwarded to `setup(ctx, { flags })`. Never hardcode domain-specific flags into `createCli`. ## 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. +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. Prefix: **`DF`**. Codes are sequential 4-digit numbers (e.g. `DF0033`). Check the existing diagnostics file to find the next available number. @@ -56,23 +56,23 @@ Prefix: **`DF`**. Codes are sequential 4-digit numbers (e.g. `DF0033`). Check th ```ts DF0033: { - message: (p: { name: string }) => `Something went wrong with "${p.name}"`, - hint: 'Optional hint for the user.', - level: 'warn', // defaults to 'error' if omitted + why: (p: { name: string }) => `Something went wrong with "${p.name}"`, + fix: 'Optional resolution hint for the user.', }, ``` -2. **Use the logger** at the call site: +2. **Use the diagnostics** at the call site: ```ts - import { logger } from './diagnostics' + import { diagnostics } from './diagnostics' // For thrown errors — always prefix with `throw` for TypeScript control flow: - throw logger.DF0033({ name }).throw() + throw diagnostics.DF0033.throw({ name }) - // For logged warnings/errors (not thrown): - logger.DF0033({ name }).log() // uses definition level - logger.DF0033({ name }).warn() // override to warn - logger.DF0033({ name }, { cause: error }).log() // attach cause + // For reported warnings/errors (not thrown). The default console method is `warn`; + // override with the 2nd-arg reporter options when needed: + diagnostics.DF0033.report({ name }) // console.warn + diagnostics.DF0033.report({ name }, { method: 'error' }) // console.error + diagnostics.DF0033.report({ name, cause: error }, { method: 'warn' }) // attach cause ``` 3. **Create a docs page** at `docs/errors/DF0033.md` (when `docs/` lands): diff --git a/docs/adapters/cli.md b/docs/adapters/cli.md index e320d90..076108c 100644 --- a/docs/adapters/cli.md +++ b/docs/adapters/cli.md @@ -94,7 +94,7 @@ await createCli(devframe, { }).parse() ``` -Structured diagnostics (via `logs-sdk`) continue to surface through their normal reporters. +Structured diagnostics (via `nostics`) continue to surface through their normal reporters. ## Use your own CLI framework diff --git a/docs/errors/index.md b/docs/errors/index.md index 873afc6..1809e46 100644 --- a/docs/errors/index.md +++ b/docs/errors/index.md @@ -10,7 +10,7 @@ Devframe uses structured diagnostics to surface actionable warnings and errors a - Codes follow the pattern **`DF` + 4-digit number** (e.g., `DF0001`). - Every error page includes the cause, recommended fix, and a reference to the source file that emits it. -- The diagnostics system is powered by [`logs-sdk`](https://github.com/vercel-labs/logs-sdk), which provides structured logging with docs URLs, ANSI-formatted console output, and level-based filtering. +- The diagnostics system is powered by [`nostics`](https://www.npmjs.com/package/nostics), which provides structured diagnostic codes with docs URLs, ANSI-formatted console output, and pluggable reporters. ## Devframe (DF) diff --git a/docs/guide/diagnostics.md b/docs/guide/diagnostics.md index b84f9a6..99e1eba 100644 --- a/docs/guide/diagnostics.md +++ b/docs/guide/diagnostics.md @@ -4,7 +4,7 @@ outline: deep # Structured Diagnostics -`ctx.diagnostics` is a thin layer over [`logs-sdk`](https://github.com/vercel-labs/logs-sdk) that lets integrations register coded errors and warnings into a shared logger without depending on `logs-sdk` directly. Use it for author-defined coded diagnostics — errors, warnings, deprecations — with a stable code, a documentation URL, and a structured payload. For free-form runtime output that should appear in the DevTools UI, use [`ctx.messages`](https://devtools.vite.dev/kit/messages). +`ctx.diagnostics` is a thin layer over [`nostics`](https://www.npmjs.com/package/nostics) that lets integrations register coded errors and warnings into a shared lookup without depending on `nostics` directly. Use it for author-defined coded diagnostics — errors, warnings, deprecations — with a stable code, a documentation URL, and a structured payload. For free-form runtime output that should appear in the DevTools UI, use [`ctx.messages`](https://devtools.vite.dev/kit/messages). | Surface | Purpose | Example | |---------|---------|---------| @@ -15,17 +15,14 @@ outline: deep ```ts interface DevToolsDiagnosticsHost { - /** Combined logs-sdk Logger across all registered diagnostics. */ - readonly logger: Logger + /** Proxy-backed lookup over every registered code. */ + readonly logger: Record /** Register additional diagnostic definitions. */ - register: (definitions: DiagnosticsResult) => void + register: (definitions: Record) => void - /** Re-export of logs-sdk's `defineDiagnostics`. */ + /** Build a typed diagnostics object with the host's ANSI reporter pre-wired. */ defineDiagnostics: typeof defineDiagnostics - - /** Re-export of logs-sdk's `createLogger`. */ - createLogger: typeof createLogger } ``` @@ -43,20 +40,19 @@ export function MyPlugin(): PluginWithDevTools { docsBase: 'https://example.com/errors', codes: { MYP0001: { - message: (p: { name: string }) => `Plugin "${p.name}" is not configured`, - hint: 'Add the plugin to your `vite.config.ts` and pass an options object.', + 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: { - message: 'Cache directory missing — running cold.', - level: 'warn', + why: 'Cache directory missing — running cold.', }, }, }) ctx.diagnostics.register(myDiagnostics) - // Now you can emit codes through the shared logger: - ctx.diagnostics.logger.MYP0002().log() + // Emit through the host's shared reporter: + myDiagnostics.MYP0002.report() }, }, } @@ -76,68 +72,52 @@ Prefixes already in use in this monorepo: | `RDDT` | `@vitejs/devtools-rolldown` | | `VDT` | `@vitejs/devtools-vite` (reserved) | -Each definition supports a `message` (string or function), an optional `hint`, an optional `level` (`'error'` / `'warn'` / `'suggestion'` / `'deprecation'` — defaults to `'error'`), and a `docsBase` for generating documentation URLs. See [`logs-sdk`](https://github.com/vercel-labs/logs-sdk) for the full schema. +Each definition supports a `why` (string or function — the message) and an optional `fix` (string or function — the suggested resolution). The `docsBase` on `defineDiagnostics({...})` auto-attaches the URL to every emitted diagnostic. See [`nostics`](https://www.npmjs.com/package/nostics) for the full schema. ## Emit a diagnostic -Each registered code becomes a callable factory on `ctx.diagnostics.logger`. The factory returns an object with `.throw()`, `.warn()`, `.error()`, `.log()`, and `.format()`. +Each registered code becomes a `DiagnosticHandle` on the typed result of `defineDiagnostics()` (and through the shared `ctx.diagnostics.logger` lookup). Handles expose `.report()` and `.throw()`. ```ts // Throw — control flow stops here -throw ctx.diagnostics.logger.MYP0001({ name: 'foo' }).throw() +throw myDiagnostics.MYP0001.throw({ name: 'foo' }) -// Log without throwing -ctx.diagnostics.logger.MYP0002().log() +// Report without throwing (default console method: `warn`) +myDiagnostics.MYP0002.report() -// Override level per call -ctx.diagnostics.logger.MYP0002().warn() +// Override the console method per call +myDiagnostics.MYP0002.report({}, { method: 'error' }) -// Attach a `cause` -ctx.diagnostics.logger.MYP0001({ name: 'foo' }, { cause: error }).log() +// Attach a `cause` — merged into the params object +myDiagnostics.MYP0001.throw({ name: 'foo', cause: error }) ``` `.throw()` is typed `never`, so TypeScript treats the line after as unreachable. Prefix the call with `throw` for control-flow narrowing: ```ts -throw ctx.diagnostics.logger.MYP0001({ name }).throw() +throw myDiagnostics.MYP0001.throw({ name }) ``` -## Typed logger reference +## Typed handle reference -`ctx.diagnostics.logger` is loosely typed — it covers an unbounded set of registered codes, beyond what TypeScript can narrow. For autocompletion on your plugin's specific codes, keep a typed reference returned from `createLogger`: +`ctx.diagnostics.logger` is loosely typed — it covers an unbounded set of registered codes, beyond what TypeScript can narrow. For autocompletion on your plugin's specific codes, keep the typed result of `defineDiagnostics()`: ```ts const myDiagnostics = ctx.diagnostics.defineDiagnostics({ docsBase: 'https://example.com/errors', codes: { - MYP0001: { message: (p: { name: string }) => `…${p.name}` }, + MYP0001: { why: (p: { name: string }) => `…${p.name}` }, }, }) -// Register so the shared logger can also see it +// Register so the shared lookup can also see it ctx.diagnostics.register(myDiagnostics) -// Keep a typed reference for your own emit sites -const logger = ctx.diagnostics.createLogger({ diagnostics: [myDiagnostics] }) -logger.MYP0001({ name: 'foo' }).warn() -``` - -Both loggers share the formatter and reporter defaults set by the host (ANSI console output). - -## Updating the combined logger - -`ctx.diagnostics.logger` is a getter — it returns the freshest combined logger, rebuilt each time `register()` is called. Don't cache it: - -```ts -// ❌ Stale after a later register() call -const log = ctx.diagnostics.logger -log.MYP0001({ name: 'foo' }).log() - -// ✅ Always fresh -ctx.diagnostics.logger.MYP0001({ name: 'foo' }).log() +// Use the typed handle directly for autocompletion +myDiagnostics.MYP0001.report({ name: 'foo' }) ``` -For a stable reference, use `ctx.diagnostics.createLogger({ diagnostics: [myDiagnostics] })` — that one stays bound to your definitions. +The host's `defineDiagnostics()` pre-wires its ANSI console reporter, so both the typed handle and the shared lookup produce the same output. ## Document your codes diff --git a/docs/guide/index.md b/docs/guide/index.md index 3cf11d6..1c830e3 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -29,7 +29,7 @@ Devframe keeps its surface focused on one tool, so the same definition stays por | **[Devframe Definition](./devframe-definition)** | One `defineDevframe` call describes your tool once; the adapters deploy it anywhere. | | **[RPC](./rpc)** | Type-safe bidirectional calls built on birpc + valibot. Supports `query`, `static`, `action`, and `event` types. | | **[Shared State](./shared-state)** | Observable, patch-synced state that survives reconnects and bridges server ↔ browser. | -| **[Diagnostics](./diagnostics)** | Coded warnings/errors via `logs-sdk` — registered into the host logger so adapters and consumers share the same surface. | +| **[Diagnostics](./diagnostics)** | Coded warnings/errors via `nostics` — registered into the host's shared lookup so adapters and consumers share the same surface. | | **[Streaming](./streaming)** | One-way (RPC streaming) and two-way (uploads) channel primitives for long-running data. | | **[When Clauses](./when-clauses)** | VS Code-style conditional expressions for docks, commands, and custom UI. | | **[Utilities](/helpers/utilities)** | Bundled helpers under `devframe/utils/*` — terminal colors, hashing, editor launch, structured-clone serialization, and more. | diff --git a/packages/devframe/package.json b/packages/devframe/package.json index 51fed9a..fb3e7ee 100644 --- a/packages/devframe/package.json +++ b/packages/devframe/package.json @@ -77,8 +77,8 @@ "birpc": "catalog:deps", "cac": "catalog:deps", "h3": "catalog:deps", - "logs-sdk": "catalog:deps", "mrmime": "catalog:deps", + "nostics": "catalog:deps", "pathe": "catalog:deps", "valibot": "catalog:deps", "ws": "catalog:deps" diff --git a/packages/devframe/src/adapters/mcp/build-server.ts b/packages/devframe/src/adapters/mcp/build-server.ts index 7a0700f..93a2997 100644 --- a/packages/devframe/src/adapters/mcp/build-server.ts +++ b/packages/devframe/src/adapters/mcp/build-server.ts @@ -12,7 +12,7 @@ import { } from '@modelcontextprotocol/sdk/types.js' import { createHostContext } from 'devframe/node' import { join } from 'pathe' -import { logger } from '../../node/diagnostics' +import { diagnostics } from '../../node/diagnostics' import { formatMcpError, stringifyForMcp } from './stringify' import { valibotArgsToJsonSchema, valibotReturnToJsonSchema } from './to-json-schema' @@ -102,7 +102,7 @@ export async function createMcpServer( ): Promise { const transport = options.transport ?? 'stdio' if (transport !== 'stdio') - throw logger.DF0017({ transport, reason: 'Only stdio transport is supported in this release.' }).throw() + throw diagnostics.DF0017.throw({ transport, reason: 'Only stdio transport is supported in this release.' }) const host: DevToolsHost = { mountStatic: () => { /* MCP has no static surface */ }, @@ -132,7 +132,7 @@ export async function createMcpServer( } catch (error) { const reason = error instanceof Error ? error.message : String(error) - throw logger.DF0017({ transport, reason }, { cause: error }).throw() + throw diagnostics.DF0017.throw({ transport, reason, cause: error }) } options.onReady?.({ transport: 'stdio' }) diff --git a/packages/devframe/src/helpers/vite.ts b/packages/devframe/src/helpers/vite.ts index 5258722..7fc0e2b 100644 --- a/packages/devframe/src/helpers/vite.ts +++ b/packages/devframe/src/helpers/vite.ts @@ -4,7 +4,7 @@ import { resolve } from 'pathe' import { resolveBasePath } from '../adapters/_shared' import { createDevServer, resolveDevServerPort } from '../adapters/dev' import { DEVTOOLS_CONNECTION_META_FILENAME } from '../constants' -import { logger } from '../node/diagnostics' +import { diagnostics } from '../node/diagnostics' export interface ViteDevBridgeOptions { /** @@ -106,7 +106,7 @@ export function viteDevBridge(d: DevframeDefinition, options: ViteDevBridgeOptio }) } catch (e) { - logger.DF0033({ id: d.id, reason: String(e) }, { cause: e as Error }).log() + diagnostics.DF0033.report({ id: d.id, reason: String(e), cause: e as Error }, { method: 'warn' }) return } diff --git a/packages/devframe/src/node/diagnostics.ts b/packages/devframe/src/node/diagnostics.ts index 77a2a60..0feadf2 100644 --- a/packages/devframe/src/node/diagnostics.ts +++ b/packages/devframe/src/node/diagnostics.ts @@ -1,72 +1,63 @@ -import { colors as c } from 'devframe/utils/colors' -import { consoleReporter, createLogger, defineDiagnostics } from 'logs-sdk' -import { ansiFormatter } from 'logs-sdk/formatters/ansi' +import { defineDiagnostics } from 'nostics' +import { devframeReporter } from '../utils/diagnostics-reporter' export const diagnostics = defineDiagnostics({ docsBase: 'https://devfra.me/errors', + reporters: [devframeReporter], codes: { DF0006: { - message: (p: { name: string }) => `RPC function "${p.name}" is not registered`, + why: (p: { name: string }) => `RPC function "${p.name}" is not registered`, }, DF0007: { - message: 'AsyncLocalStorage is not set, it likely to be an internal bug of the DevTools foundation', + why: 'AsyncLocalStorage is not set, it likely to be an internal bug of the DevTools foundation', }, DF0008: { - message: (p: { distDir: string }) => `distDir ${p.distDir} does not exist`, + why: (p: { distDir: string }) => `distDir ${p.distDir} does not exist`, }, DF0012: { - message: (p: { filepath: string }) => `Failed to parse storage file: ${p.filepath}, falling back to defaults.`, - level: 'warn', + why: (p: { filepath: string }) => `Failed to parse storage file: ${p.filepath}, falling back to defaults.`, }, DF0013: { - message: (p: { key: string }) => `Shared state of "${p.key}" is not found, please provide an initial value for the first time`, + why: (p: { key: string }) => `Shared state of "${p.key}" is not found, please provide an initial value for the first time`, }, DF0014: { - message: (p: { name: string }) => `RPC function "${p.name}" has an invalid \`agent\` field — \`description\` must be a non-empty string.`, - hint: 'Provide a short description (~1–3 sentences) explaining what the tool does and when agents should invoke it.', + why: (p: { name: string }) => `RPC function "${p.name}" has an invalid \`agent\` field — \`description\` must be a non-empty string.`, + fix: 'Provide a short description (~1–3 sentences) explaining what the tool does and when agents should invoke it.', }, DF0015: { - message: (p: { id: string }) => `Agent tool "${p.id}" is already registered.`, - hint: 'Tool ids must be unique across RPC functions with an `agent` field and tools registered via `ctx.agent.registerTool()`.', + why: (p: { id: string }) => `Agent tool "${p.id}" is already registered.`, + fix: 'Tool ids must be unique across RPC functions with an `agent` field and tools registered via `ctx.agent.registerTool()`.', }, DF0016: { - message: (p: { id: string }) => `Agent resource "${p.id}" is already registered.`, + why: (p: { id: string }) => `Agent resource "${p.id}" is already registered.`, }, DF0017: { - message: (p: { transport: string, reason: string }) => `Failed to start MCP server (${p.transport}): ${p.reason}`, + why: (p: { transport: string, reason: string }) => `Failed to start MCP server (${p.transport}): ${p.reason}`, }, DF0029: { - message: (p: { channel: string, id: string, dropped: number }) => + why: (p: { channel: string, id: string, dropped: number }) => `Stream "${p.channel}#${p.id}" dropped ${p.dropped} chunk(s) after exceeding the client high-water mark.`, - hint: 'The consumer is too slow for the producer. Raise `highWaterMark` on the subscription, slow the producer, or batch chunks.', - level: 'warn', + fix: 'The consumer is too slow for the producer. Raise `highWaterMark` on the subscription, slow the producer, or batch chunks.', }, DF0030: { - message: (p: { channel: string, id: string }) => + why: (p: { channel: string, id: string }) => `Stream "${p.channel}#${p.id}" is unknown — no producer has called \`channel.start({ id: "${p.id}" })\`.`, - hint: 'Ensure the server-side producer is running before clients subscribe, or check for typos in the stream id.', + fix: 'Ensure the server-side producer is running before clients subscribe, or check for typos in the stream id.', }, DF0031: { - message: (p: { channel: string, id: string }) => + why: (p: { channel: string, id: string }) => `Cannot write to closed stream "${p.channel}#${p.id}".`, - hint: 'Track the producer lifecycle — guard writes with the `stream.signal.aborted` flag.', + fix: 'Track the producer lifecycle — guard writes with the `stream.signal.aborted` flag.', }, DF0032: { - message: (p: { channel: string }) => + why: (p: { channel: string }) => `Streaming channel "${p.channel}" is already registered.`, - hint: 'Each channel name must be unique within a context. Pick a different name or reuse the existing channel handle.', + fix: 'Each channel name must be unique within a context. Pick a different name or reuse the existing channel handle.', }, DF0033: { - message: (p: { id: string, reason: string }) => + why: (p: { id: string, reason: string }) => `Failed to start dev RPC bridge for "${p.id}": ${p.reason}`, - hint: 'Verify the bridge port is free and the devframe setup function does not throw. Pin a port via `cli.port` / `cli.portRange` on the definition, or via `devMiddleware.port` on `viteDevBridge`.', - level: 'warn', + fix: 'Verify the bridge port is free and the devframe setup function does not throw. Pin a port via `cli.port` / `cli.portRange` on the definition, or via `devMiddleware.port` on `viteDevBridge`.', }, }, }) - -export const logger = createLogger({ - diagnostics: [diagnostics], - formatter: ansiFormatter(c), - reporters: consoleReporter, -}) diff --git a/packages/devframe/src/node/host-agent.ts b/packages/devframe/src/node/host-agent.ts index 076405a..d40c42d 100644 --- a/packages/devframe/src/node/host-agent.ts +++ b/packages/devframe/src/node/host-agent.ts @@ -14,7 +14,7 @@ import type { RpcFunctionAgentOptions, } from 'devframe/types' import { createEventEmitter } from 'devframe/utils/events' -import { logger } from './diagnostics' +import { diagnostics } from './diagnostics' interface RegisteredTool { readonly tool: AgentTool @@ -74,7 +74,7 @@ export class DevToolsAgentHost implements DevToolsAgentHostType { registerResource(input: AgentResourceInput): AgentHandle { if (this.resources.has(input.id)) - throw logger.DF0016({ id: input.id }).throw() + throw diagnostics.DF0016.throw({ id: input.id }) const resource: AgentResource = { id: input.id, @@ -154,16 +154,16 @@ export class DevToolsAgentHost implements DevToolsAgentHostType { private _validateToolId(id: string): void { if (this.tools.has(id)) - throw logger.DF0015({ id }).throw() + throw diagnostics.DF0015.throw({ id }) // Collision with an RPC function that already carries an `agent` field. const rpcDef = this.context.rpc.definitions.get(id) if (rpcDef?.agent) - throw logger.DF0015({ id }).throw() + throw diagnostics.DF0015.throw({ id }) } private _projectTool(input: AgentToolInput): AgentTool { if (!input.description || typeof input.description !== 'string') - throw logger.DF0014({ name: input.id }).throw() + throw diagnostics.DF0014.throw({ name: input.id }) return { id: input.id, @@ -185,7 +185,7 @@ export class DevToolsAgentHost implements DevToolsAgentHostType { if (!agent) continue if (!agent.description || typeof agent.description !== 'string') - throw logger.DF0014({ name }).throw() + throw diagnostics.DF0014.throw({ name }) const type: RpcFunctionType = def.type ?? 'query' const safety = agent.safety ?? inferSafety(type) diff --git a/packages/devframe/src/node/host-diagnostics.ts b/packages/devframe/src/node/host-diagnostics.ts index 23e5421..4485317 100644 --- a/packages/devframe/src/node/host-diagnostics.ts +++ b/packages/devframe/src/node/host-diagnostics.ts @@ -1,37 +1,31 @@ import type { DevToolsDiagnosticsHost as DevToolsDiagnosticsHostType, DevToolsDiagnosticsLogger, DevToolsNodeContext } from 'devframe/types' -import { colors as c } from 'devframe/utils/colors' -import { consoleReporter, createLogger, defineDiagnostics } from 'logs-sdk' -import { ansiFormatter } from 'logs-sdk/formatters/ansi' +import { defineDiagnostics } from 'nostics' +import { devframeReporter } from '../utils/diagnostics-reporter' export class DevToolsDiagnosticsHost implements DevToolsDiagnosticsHostType { - private _definitions: unknown[] = [] - private _logger!: DevToolsDiagnosticsLogger + private _registry: Record = {} - readonly defineDiagnostics: typeof defineDiagnostics = defineDiagnostics - readonly createLogger: typeof createLogger = createLogger + readonly logger: DevToolsDiagnosticsLogger = new Proxy({} as DevToolsDiagnosticsLogger, { + get: (_, code: string) => this._registry[code], + }) + + readonly defineDiagnostics: DevToolsDiagnosticsHostType['defineDiagnostics'] = (opts) => { + const merged = { + ...opts, + reporters: [devframeReporter, ...(opts.reporters ?? [])], + } as Parameters[0] + return defineDiagnostics(merged) as ReturnType + } constructor( public readonly context: DevToolsNodeContext, - initialDefinitions: unknown[] = [], + initialDefinitions: Array> = [], ) { - this._definitions = [...initialDefinitions] - this._rebuild() - } - - get logger(): DevToolsDiagnosticsLogger { - return this._logger - } - - register(definitions: unknown): void { - this._definitions.push(definitions) - this._rebuild() + for (const d of initialDefinitions) + this.register(d) } - private _rebuild(): void { - this._logger = createLogger({ - diagnostics: this._definitions as any[], - formatter: ansiFormatter(c), - reporters: consoleReporter, - }) as DevToolsDiagnosticsLogger + register(diagnostics: Record): void { + Object.assign(this._registry, diagnostics) } } diff --git a/packages/devframe/src/node/host-functions.ts b/packages/devframe/src/node/host-functions.ts index 66c4a30..90dbd47 100644 --- a/packages/devframe/src/node/host-functions.ts +++ b/packages/devframe/src/node/host-functions.ts @@ -3,7 +3,7 @@ import type { DevToolsNodeContext, DevToolsNodeRpcSession, DevToolsNodeRpcSessio import type { AsyncLocalStorage } from 'node:async_hooks' import { RpcFunctionsCollectorBase } from 'devframe/rpc' import { createDebug } from 'obug' -import { logger } from './diagnostics' +import { diagnostics } from './diagnostics' import { createRpcSharedStateServerHost } from './rpc-shared-state' import { createRpcStreamingServerHost } from './rpc-streaming' @@ -45,7 +45,7 @@ export class RpcFunctionsHost extends RpcFunctionsCollectorBase>> { if (!this.definitions.has(method as string)) { - throw logger.DF0006({ name: String(method) }).throw() + throw diagnostics.DF0006.throw({ name: String(method) }) } const handler = await this.getHandler(method) @@ -80,7 +80,7 @@ export class RpcFunctionsHost extends RpcFunctionsCollectorBase({ diff --git a/packages/devframe/src/node/rpc-streaming.ts b/packages/devframe/src/node/rpc-streaming.ts index 220c2a1..26510ac 100644 --- a/packages/devframe/src/node/rpc-streaming.ts +++ b/packages/devframe/src/node/rpc-streaming.ts @@ -8,7 +8,7 @@ import type { import type { StreamErrorPayload, StreamReader, StreamSink } from 'devframe/utils/streaming-channel' import { createStreamReader, createStreamSink } from 'devframe/utils/streaming-channel' import { createDebug } from 'obug' -import { logger } from './diagnostics' +import { diagnostics } from './diagnostics' const debug = createDebug('vite:devtools:rpc:streaming') @@ -97,12 +97,12 @@ export function createRpcStreamingServerHost(rpc: RpcFunctionsHost): RpcStreamin handler(channelName: string, id: string, opts?: { afterSeq?: number }) { const state = channels.get(channelName) if (!state) { - logger.DF0030({ channel: channelName, id }).log() + diagnostics.DF0030.report({ channel: channelName, id }, { method: 'error' }) return } const record = state.streams.get(id) if (!record) { - logger.DF0030({ channel: channelName, id }).log() + diagnostics.DF0030.report({ channel: channelName, id }, { method: 'error' }) return } const session = rpc.getCurrentRpcSession() @@ -181,7 +181,7 @@ export function createRpcStreamingServerHost(rpc: RpcFunctionsHost): RpcStreamin const state = channels.get(channelName) const record = state?.inbound.get(id) if (!record) { - logger.DF0030({ channel: channelName, id }).log() + diagnostics.DF0030.report({ channel: channelName, id }, { method: 'error' }) return } // Lock the inbound to the first session that writes; subsequent @@ -218,7 +218,7 @@ export function createRpcStreamingServerHost(rpc: RpcFunctionsHost): RpcStreamin function createChannel(name: string, opts: RpcStreamingChannelOptions = {}): RpcStreamingChannel { if (channels.has(name)) - throw logger.DF0032({ channel: name }).throw() + throw diagnostics.DF0032.throw({ channel: name }) const replayWindow = opts.replayWindow ?? 0 const state: ChannelState = { diff --git a/packages/devframe/src/node/storage.ts b/packages/devframe/src/node/storage.ts index 4f4c028..78ca6af 100644 --- a/packages/devframe/src/node/storage.ts +++ b/packages/devframe/src/node/storage.ts @@ -2,7 +2,7 @@ import fs from 'node:fs' import { createSharedState } from 'devframe/utils/shared-state' import { dirname } from 'pathe' import { debounce } from 'perfect-debounce' -import { logger } from './diagnostics' +import { diagnostics } from './diagnostics' export interface CreateStorageOptions { filepath: string @@ -24,7 +24,7 @@ export function createStorage(options: CreateStorageOptions initialValue = mergeInitialValue ? mergeInitialValue(options.initialValue, savedValue) : savedValue } catch (error) { - logger.DF0012({ filepath: options.filepath }, { cause: error }).log() + diagnostics.DF0012.report({ filepath: options.filepath, cause: error }, { method: 'warn' }) initialValue = options.initialValue } } diff --git a/packages/devframe/src/rpc/collector.ts b/packages/devframe/src/rpc/collector.ts index 6fdcd9f..b9c5794 100644 --- a/packages/devframe/src/rpc/collector.ts +++ b/packages/devframe/src/rpc/collector.ts @@ -1,5 +1,5 @@ import type { RpcArgsSchema, RpcFunctionDefinition, RpcFunctionsCollector, RpcReturnSchema } from './types' -import { logger } from './diagnostics' +import { diagnostics } from './diagnostics' import { getRpcHandler } from './handler' export class RpcFunctionsCollectorBase< @@ -41,7 +41,7 @@ export class RpcFunctionsCollectorBase< register(fn: RpcFunctionDefinition, force = false): void { if (this.definitions.has(fn.name) && !force) { - throw logger.DF0021({ name: fn.name }).throw() + throw diagnostics.DF0021.throw({ name: fn.name }) } assertAgentJsonSerializable(fn) this.definitions.set(fn.name, fn) @@ -50,7 +50,7 @@ export class RpcFunctionsCollectorBase< update(fn: RpcFunctionDefinition, force = false): void { if (!this.definitions.has(fn.name) && !force) { - throw logger.DF0022({ name: fn.name }).throw() + throw diagnostics.DF0022.throw({ name: fn.name }) } assertAgentJsonSerializable(fn) this.definitions.set(fn.name, fn) @@ -74,7 +74,7 @@ export class RpcFunctionsCollectorBase< getSchema(name: T): { args: RpcArgsSchema | undefined, returns: RpcReturnSchema | undefined } { const definition = this.definitions.get(name as string) if (!definition) - throw logger.DF0023({ name: String(name) }).throw() + throw diagnostics.DF0023.throw({ name: String(name) }) return { args: definition.args, returns: definition.returns, @@ -98,5 +98,5 @@ function assertAgentJsonSerializable( fn: RpcFunctionDefinition, ): void { if (fn.agent && fn.jsonSerializable !== true) - throw logger.DF0019({ name: fn.name }).throw() + throw diagnostics.DF0019.throw({ name: fn.name }) } diff --git a/packages/devframe/src/rpc/diagnostics.ts b/packages/devframe/src/rpc/diagnostics.ts index 05d023c..d8df584 100644 --- a/packages/devframe/src/rpc/diagnostics.ts +++ b/packages/devframe/src/rpc/diagnostics.ts @@ -1,49 +1,45 @@ -import { consoleReporter, createLogger, defineDiagnostics, plainFormatter } from 'logs-sdk' +import { defineDiagnostics } from 'nostics' +import { devframeReporter } from '../utils/diagnostics-reporter' export const diagnostics = defineDiagnostics({ docsBase: 'https://devfra.me/errors', + reporters: [devframeReporter], codes: { DF0019: { - message: (p: { name: string }) => + why: (p: { name: string }) => `RPC function "${p.name}" has \`agent\` set but \`jsonSerializable\` is not \`true\` — MCP requires JSON-serializable data.`, - hint: 'Set `jsonSerializable: true` if the payload is JSON-safe, or remove `agent` to keep it RPC-only.', + fix: 'Set `jsonSerializable: true` if the payload is JSON-safe, or remove `agent` to keep it RPC-only.', }, DF0020: { - message: (p: { name: string, type: string, path: string }) => + why: (p: { name: string, type: string, path: string }) => `RPC function "${p.name}" declares \`jsonSerializable: true\` but the value at "${p.path}" is a ${p.type}.`, - hint: 'Either drop `jsonSerializable: true` (falls back to structured-clone) or change the value to a JSON-safe shape.', + fix: 'Either drop `jsonSerializable: true` (falls back to structured-clone) or change the value to a JSON-safe shape.', }, DF0021: { - message: (p: { name: string }) => `RPC function "${p.name}" is already registered`, - hint: 'Use the `force` parameter to overwrite an existing registration.', + why: (p: { name: string }) => `RPC function "${p.name}" is already registered`, + fix: 'Use the `force` parameter to overwrite an existing registration.', }, DF0022: { - message: (p: { name: string }) => `RPC function "${p.name}" is not registered. Use register() to add new functions.`, + why: (p: { name: string }) => `RPC function "${p.name}" is not registered. Use register() to add new functions.`, }, DF0023: { - message: (p: { name: string }) => `RPC function "${p.name}" is not registered`, + why: (p: { name: string }) => `RPC function "${p.name}" is not registered`, }, DF0024: { - message: (p: { name: string }) => `Either handler or setup function must be provided for RPC function "${p.name}"`, + why: (p: { name: string }) => `Either handler or setup function must be provided for RPC function "${p.name}"`, }, DF0025: { - message: (p: { name: string }) => `Function "${p.name}" not found in dump store`, + why: (p: { name: string }) => `Function "${p.name}" not found in dump store`, }, DF0026: { - message: (p: { name: string, args: string }) => `No dump match for "${p.name}" with args: ${p.args}`, + why: (p: { name: string, args: string }) => `No dump match for "${p.name}" with args: ${p.args}`, }, DF0027: { - message: (p: { name: string, type: string }) => `Function "${p.name}" with type "${p.type}" cannot have dump configuration. Only "static" and "query" types support dumps.`, + why: (p: { name: string, type: string }) => `Function "${p.name}" with type "${p.type}" cannot have dump configuration. Only "static" and "query" types support dumps.`, }, DF0028: { - message: (p: { name: string, type: string }) => `Function "${p.name}" with type "${p.type}" cannot use \`snapshot: true\`. Only "query" functions support this sugar; "static" functions have equivalent default behavior already.`, - hint: 'Remove `snapshot: true`, or change the function type to `query`.', + why: (p: { name: string, type: string }) => `Function "${p.name}" with type "${p.type}" cannot use \`snapshot: true\`. Only "query" functions support this sugar; "static" functions have equivalent default behavior already.`, + fix: 'Remove `snapshot: true`, or change the function type to `query`.', }, }, }) - -export const logger = createLogger({ - diagnostics: [diagnostics], - formatter: plainFormatter, - reporters: consoleReporter, -}) diff --git a/packages/devframe/src/rpc/dump/collect.ts b/packages/devframe/src/rpc/dump/collect.ts index 5539392..47b1af5 100644 --- a/packages/devframe/src/rpc/dump/collect.ts +++ b/packages/devframe/src/rpc/dump/collect.ts @@ -9,7 +9,7 @@ import type { } from '../types' import { hash } from 'devframe/utils/hash' import pLimit from 'p-limit' -import { logger } from '../diagnostics' +import { diagnostics } from '../diagnostics' import { validateDefinitions } from '../validation' import { reviveDumpError, serializeDumpError } from './error' @@ -75,7 +75,7 @@ export async function dumpFunctions< const handler = setupResult.handler || definition.handler if (!handler) { - throw logger.DF0024({ name: definition.name }).throw() + throw diagnostics.DF0024.throw({ name: definition.name }) } let dump = setupResult.dump ?? definition.dump @@ -211,7 +211,7 @@ export function createClientFromDump>( const client = new Proxy({} as T, { get(_, functionName: string) { if (!(functionName in store.definitions)) { - throw logger.DF0025({ name: functionName }).throw() + throw diagnostics.DF0025.throw({ name: functionName }) } return async (...args: any[]) => { @@ -248,7 +248,7 @@ export function createClientFromDump>( return fallbackRecord.output } - throw logger.DF0026({ name: functionName, args: JSON.stringify(args) }).throw() + throw diagnostics.DF0026.throw({ name: functionName, args: JSON.stringify(args) }) } }, has(_, functionName: string) { diff --git a/packages/devframe/src/rpc/handler.ts b/packages/devframe/src/rpc/handler.ts index a0a5865..8c63ef9 100644 --- a/packages/devframe/src/rpc/handler.ts +++ b/packages/devframe/src/rpc/handler.ts @@ -1,5 +1,5 @@ import type { RpcFunctionDefinition, RpcFunctionSetupResult, RpcFunctionType } from './types' -import { logger } from './diagnostics' +import { diagnostics } from './diagnostics' export async function getRpcResolvedSetupResult< NAME extends string, @@ -42,7 +42,7 @@ export async function getRpcHandler< } const result = await getRpcResolvedSetupResult(definition, context) if (!result.handler) { - throw logger.DF0024({ name: definition.name }).throw() + throw diagnostics.DF0024.throw({ name: definition.name }) } return result.handler } diff --git a/packages/devframe/src/rpc/serialization.ts b/packages/devframe/src/rpc/serialization.ts index 1151ef6..35f85a5 100644 --- a/packages/devframe/src/rpc/serialization.ts +++ b/packages/devframe/src/rpc/serialization.ts @@ -1,4 +1,4 @@ -import { logger } from './diagnostics' +import { diagnostics } from './diagnostics' /** * Wire format used by the WS RPC transport. @@ -84,7 +84,7 @@ export function strictJsonStringify(value: unknown, fnName: string = ''): string function nonJsonAt(fnName: string, type: string, parent: unknown, key: string): Error { const path = formatPath(parent, key) - return logger.DF0020({ name: fnName || '', type, path }).throw() + return diagnostics.DF0020.throw({ name: fnName || '', type, path }) } function formatPath(parent: unknown, key: string): string { diff --git a/packages/devframe/src/rpc/validation.ts b/packages/devframe/src/rpc/validation.ts index 59a3ee6..8ce54bd 100644 --- a/packages/devframe/src/rpc/validation.ts +++ b/packages/devframe/src/rpc/validation.ts @@ -1,5 +1,5 @@ import type { RpcFunctionDefinitionAny } from './types' -import { logger } from './diagnostics' +import { diagnostics } from './diagnostics' /** * Validates RPC function definitions. @@ -12,11 +12,11 @@ export function validateDefinitions(definitions: readonly RpcFunctionDefinitionA const type = definition.type || 'query' if ((type === 'action' || type === 'event') && definition.dump) { - throw logger.DF0027({ name: definition.name, type }).throw() + throw diagnostics.DF0027.throw({ name: definition.name, type }) } if (definition.snapshot && type !== 'query') { - throw logger.DF0028({ name: definition.name, type }).throw() + throw diagnostics.DF0028.throw({ name: definition.name, type }) } } } diff --git a/packages/devframe/src/types/context.ts b/packages/devframe/src/types/context.ts index 78f6d70..a5c4b71 100644 --- a/packages/devframe/src/types/context.ts +++ b/packages/devframe/src/types/context.ts @@ -41,8 +41,8 @@ export interface DevToolsNodeContext { rpc: import('./rpc').RpcFunctionsHost views: DevToolsViewHost /** - * Structured diagnostics host — wraps `logs-sdk` and lets integrations - * register their own coded errors/warnings into the shared logger. + * Structured diagnostics host — wraps `nostics` and lets integrations + * register their own coded errors/warnings into the shared lookup. */ diagnostics: DevToolsDiagnosticsHost /** diff --git a/packages/devframe/src/types/diagnostics.ts b/packages/devframe/src/types/diagnostics.ts index df89e83..dd0a7ee 100644 --- a/packages/devframe/src/types/diagnostics.ts +++ b/packages/devframe/src/types/diagnostics.ts @@ -1,22 +1,37 @@ -import type { createLogger, defineDiagnostics, Logger } from 'logs-sdk' +import type { defineDiagnostics, Diagnostic, DiagnosticDefinition } from 'nostics' /** * A diagnostics definition object built with `defineDiagnostics`. Typed as * `unknown` because each integration's definition has a distinct narrow shape * (e.g. specific code keys like `DF0001` / `MYP0001`), and TypeScript's mapped - * types don't allow assigning a narrow-keyed `DiagnosticsResult` to a - * generically-keyed one. The host stores them in a heterogeneous list and - * rebuilds the logger on `register()`. + * types don't allow assigning a narrow-keyed result to a generically-keyed + * one. The host stores them in a heterogeneous registry. */ -export type DevToolsDiagnosticsDefinition = ReturnType> +export type DevToolsDiagnosticsDefinition = ReturnType> -/** A `logs-sdk` Logger instance built with `createLogger`. */ -export type DevToolsDiagnosticsLogger = Logger +/** + * The shared diagnostics lookup exposed by the host. A `Proxy` that resolves + * any registered code name to its `nostics` handle (with `.report()` and + * `.throw()` methods). Typed loosely because it spans heterogeneous + * definitions registered by different integrations. + */ +export type DevToolsDiagnosticsLogger = Record /** - * Host for structured diagnostics — a thin layer over `logs-sdk` that lets - * integrations register their own coded errors/warnings into the shared - * logger without taking a direct dependency on `logs-sdk`. + * 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`. + */ +export interface DevToolsDefineDiagnosticsOptions> { + docsBase?: string | ((code: keyof Codes) => string | undefined) + codes: Codes + reporters?: ReadonlyArray<(d: Diagnostic, o?: any) => void> +} + +/** + * Host for structured diagnostics — a thin layer over `nostics` that lets + * integrations register their own coded errors/warnings into a shared + * registry without taking a direct dependency on `nostics`. * * Typical usage from a plugin's `setup(ctx)`: * @@ -24,48 +39,42 @@ export type DevToolsDiagnosticsLogger = Logger * const myDiagnostics = ctx.diagnostics.defineDiagnostics({ * docsBase: 'https://example.com/errors', * codes: { - * MYP0001: { message: 'Something went wrong' }, + * MYP0001: { why: 'Something went wrong' }, * }, * }) * ctx.diagnostics.register(myDiagnostics) * - * // Later (loose typing): - * ctx.diagnostics.logger.MYP0001().warn() + * // Through the shared lookup (loose typing): + * ctx.diagnostics.logger.MYP0001.throw() * - * // Or with full typing, keep your own logger reference: - * const logger = ctx.diagnostics.createLogger({ diagnostics: [myDiagnostics] }) - * logger.MYP0001().warn() + * // Or directly on the typed handle returned from `defineDiagnostics`: + * myDiagnostics.MYP0001.throw() * ``` */ export interface DevToolsDiagnosticsHost { /** - * The combined `logs-sdk` Logger including all registered diagnostic - * definitions. The getter always returns the freshest logger — it is - * rebuilt each time `register()` is called, so cached references to - * older loggers will not see codes registered later. + * Proxy-backed lookup of every registered diagnostic handle by code name. + * Resolves to a `nostics` `DiagnosticHandle` with `.report()` / `.throw()`. + * Loosely typed — for autocompletion, keep a reference to the typed + * result of `defineDiagnostics()` instead. */ readonly logger: DevToolsDiagnosticsLogger /** - * Register an additional diagnostic definition with this host. After - * registration, codes from the new definition are accessible on - * `host.logger`. Accepts any `DiagnosticsResult` produced by - * `defineDiagnostics` — the parameter is typed as `unknown` to avoid - * mapped-type variance issues with narrowly-keyed definitions. - */ - register: (definitions: unknown) => void - - /** - * Re-export of `logs-sdk`'s `defineDiagnostics`. Integrations can build - * their own diagnostic definitions without taking a direct dependency on - * `logs-sdk`. + * Register additional diagnostic definitions with this host. After + * registration, codes from the new definition are reachable via + * `host.logger.CODE`. Plugins that want shared output formatting should + * build their diagnostics via `host.defineDiagnostics()` first — that + * factory pre-wires the host's ANSI console reporter. */ - defineDiagnostics: typeof defineDiagnostics + register: (definitions: Record) => void /** - * Re-export of `logs-sdk`'s `createLogger`. Use this when an integration - * wants its own typed Logger reference instead of going through - * `host.logger` (which is loosely typed). + * 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`. */ - createLogger: typeof createLogger + defineDiagnostics: >( + options: DevToolsDefineDiagnosticsOptions, + ) => ReturnType> } diff --git a/packages/devframe/src/utils/diagnostics-reporter.ts b/packages/devframe/src/utils/diagnostics-reporter.ts new file mode 100644 index 0000000..44c9e2b --- /dev/null +++ b/packages/devframe/src/utils/diagnostics-reporter.ts @@ -0,0 +1,12 @@ +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/pnpm-lock.yaml b/pnpm-lock.yaml index 4de7e55..dc08212 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -58,12 +58,12 @@ catalogs: launch-editor: specifier: ^2.13.2 version: 2.13.2 - logs-sdk: - specifier: ^0.0.6 - version: 0.0.6 mrmime: specifier: ^2.0.1 version: 2.0.1 + nostics: + specifier: ^0.1.0 + version: 0.1.0 obug: specifier: ^2.1.1 version: 2.1.1 @@ -168,7 +168,7 @@ importers: devDependencies: '@antfu/eslint-config': specifier: catalog:devtools - version: 9.0.0(@typescript-eslint/rule-tester@8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3))(@typescript-eslint/typescript-estree@8.59.2(typescript@6.0.3))(@typescript-eslint/utils@8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3))(@vue/compiler-sfc@3.5.34)(eslint@10.3.0(jiti@2.7.0))(ts-declaration-location@1.0.7(typescript@6.0.3))(typescript@6.0.3)(vitest@4.1.6(@types/node@25.7.0)(vite@8.0.12(@types/node@25.7.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.21.0)(yaml@2.8.4))) + version: 9.0.0(@typescript-eslint/rule-tester@8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3))(@typescript-eslint/typescript-estree@8.59.2(typescript@6.0.3))(@typescript-eslint/utils@8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3))(@vue/compiler-sfc@3.5.34)(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3)(vitest@4.1.6(@types/node@25.7.0)(vite@8.0.12(@types/node@25.7.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.21.0)(yaml@2.8.4))) '@antfu/ni': specifier: catalog:build version: 30.1.0 @@ -312,12 +312,12 @@ importers: h3: specifier: catalog:deps version: 2.0.1-rc.22(crossws@0.4.5(srvx@0.11.15)) - logs-sdk: - specifier: catalog:deps - version: 0.0.6 mrmime: specifier: catalog:deps version: 2.0.1 + nostics: + specifier: catalog:deps + version: 0.1.0 pathe: specifier: catalog:deps version: 2.0.3 @@ -686,15 +686,9 @@ packages: '@emnapi/core@1.10.0': resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} - '@emnapi/core@1.9.2': - resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==} - '@emnapi/runtime@1.10.0': resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} - '@emnapi/runtime@1.9.2': - resolution: {integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==} - '@emnapi/wasi-threads@1.2.1': resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} @@ -1396,12 +1390,6 @@ packages: cpu: [x64] os: [win32] - '@oxc-parser/binding-android-arm-eabi@0.126.0': - resolution: {integrity: sha512-svyoHt25J4741QJ5aa4R+h0iiBeSRt63Lr3aAZcxy2c/NeSE1IfDeMnSij6rIg7EjxkdlXzz613wUjeCeilBNA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [android] - '@oxc-parser/binding-android-arm-eabi@0.128.0': resolution: {integrity: sha512-aca6ZvzmCBUGOANQRiRQRZuRKYI3ENhcit6GisnknOOmcezfQc7xJ4dxlPU7MV7mOvrC7RNR1u3LAD7xyaiCxA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1414,10 +1402,10 @@ packages: cpu: [arm] os: [android] - '@oxc-parser/binding-android-arm64@0.126.0': - resolution: {integrity: sha512-hPEBRKgplp1mG9GkINFsr4JVMDNrGJLOqfDaadTWpAoTnzYR5Rmv8RMvB3hJZpiNvbk1aacopdHUP1pggMQ/cw==} + '@oxc-parser/binding-android-arm-eabi@0.130.0': + resolution: {integrity: sha512-h/xYU8/7ADWzVSf5I+YalLpj33LOy9CI/zgbJNIZ5eunRBG+Czqa3lZsvuPHHf3rOt6z1c5+UzoxjbAzAvhwVw==} engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] + cpu: [arm] os: [android] '@oxc-parser/binding-android-arm64@0.128.0': @@ -1432,11 +1420,11 @@ packages: cpu: [arm64] os: [android] - '@oxc-parser/binding-darwin-arm64@0.126.0': - resolution: {integrity: sha512-ccRpu9sdYmznePJQG5halhs0FW5tw5a8zRSoZXOzM1OjoeZ4jiRRruFiPclsD59edoVAK1l83dvfjWz1nQi6lg==} + '@oxc-parser/binding-android-arm64@0.130.0': + resolution: {integrity: sha512-oFWFJrsGv9siFM4HjMqKNB7IuIZD/SMmZdCXl8xyx7lDplGvPKyewpOo272rSWgMXe2Wx7bWI0Yj+gkHv4qbeg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] - os: [darwin] + os: [android] '@oxc-parser/binding-darwin-arm64@0.128.0': resolution: {integrity: sha512-tRUHPt80417QmvNpoSslJT1VY8NUbWdrWR+L14Zn+RbOTcaqB8E6PYE/ZGN8jjWBzqporiA/H4MfO50ew/NCNA==} @@ -1450,10 +1438,10 @@ packages: cpu: [arm64] os: [darwin] - '@oxc-parser/binding-darwin-x64@0.126.0': - resolution: {integrity: sha512-CHB4zVjNSKqx8Fw9pHowzQQnjjuq04i4Ng0Avj+DixlwhwAoMYqlFbocYIlbg+q3zOLGlm7vEHm83jqEMitnyg==} + '@oxc-parser/binding-darwin-arm64@0.130.0': + resolution: {integrity: sha512-sGUzupdTplK9jQg7eJZ878HfEgQjJNBc6dAYVWJ9W5aU+J8rLfRJhTVsKThiu1pNwm6Y1qKCcbC6WhNWSXR3Ig==} engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] + cpu: [arm64] os: [darwin] '@oxc-parser/binding-darwin-x64@0.128.0': @@ -1468,11 +1456,11 @@ packages: cpu: [x64] os: [darwin] - '@oxc-parser/binding-freebsd-x64@0.126.0': - resolution: {integrity: sha512-RQ3nEJdcDKBfBjmLJ3Vl1d0KQERPV1P8eUrnBm7+VTYyoaJSPLVFuPg1mlD1hk3n0/879VLFMfusFkBal4ssWQ==} + '@oxc-parser/binding-darwin-x64@0.130.0': + resolution: {integrity: sha512-PsB4cdCISbC00Uy8eiD8bc2AkGWjZqrSrJnkBFuG2ptrrf6mZ2F5gLFSjOAVMMgZPg8B1D7OydJwLWSfyI2Plg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] - os: [freebsd] + os: [darwin] '@oxc-parser/binding-freebsd-x64@0.128.0': resolution: {integrity: sha512-hhpdVMaNCLgQxjgNPeeFzSeJMmZPc5lKfv0NGSI3egZq9EdnEGqeC8JsYsQjK7PoQgbvZ17xlj0SO5ziH5Obkg==} @@ -1486,11 +1474,11 @@ packages: cpu: [x64] os: [freebsd] - '@oxc-parser/binding-linux-arm-gnueabihf@0.126.0': - resolution: {integrity: sha512-onipc2wCDA7Bauzb4KK1mab0GsEDf4ujiIfWECdnmY/2LlzAoX3xdQRLAUyEDB1kn3yilHBrkmXDdHluyHXxiw==} + '@oxc-parser/binding-freebsd-x64@0.130.0': + resolution: {integrity: sha512-DgABp3l38hS77JbXCV4qk1+n6DPym5u8zzwuweokezm2tX194nDSJDENbDRECxVsiNbprKATLbk+Z5wlHT0OHw==} engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [linux] + cpu: [x64] + os: [freebsd] '@oxc-parser/binding-linux-arm-gnueabihf@0.128.0': resolution: {integrity: sha512-093zNw0zZ/e/obML+rhlSdmnzR0mVZluPcAkxunEc5E3F0yBVsFn24Y1ILfsEte11Ud041qn/gp2OJ1jxNqUng==} @@ -1504,8 +1492,8 @@ packages: cpu: [arm] os: [linux] - '@oxc-parser/binding-linux-arm-musleabihf@0.126.0': - resolution: {integrity: sha512-5BuJJPohrV5NJ8lmcYOMbfRCUGoYH5J9HZHeuqOLwkHXWAuPMN3X1h8bC/2mWjmosdbfTtmyIdX3spS/TkqKNg==} + '@oxc-parser/binding-linux-arm-gnueabihf@0.130.0': + resolution: {integrity: sha512-4Kn3CTEmwFrzhTSC/JuUW16qovmaMdX7jeSKbL8w0pLtLww7To1a2XJi9Z5uD8QWUkfUHhqfV+VD6dVzBnWzoA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] @@ -1522,12 +1510,11 @@ packages: cpu: [arm] os: [linux] - '@oxc-parser/binding-linux-arm64-gnu@0.126.0': - resolution: {integrity: sha512-r2KApRgm2pOJaduRm6GOT8x0whcr67AyejNkSdzPt34GJ+Y3axcXN2mwlTs+8lfO/SSmpO5ZJGYiHYnxEE0jkw==} + '@oxc-parser/binding-linux-arm-musleabihf@0.130.0': + resolution: {integrity: sha512-D35KZM3F4rRu1uAFKyBlg3Gaf/ybCjyaPR1hfgvk5ex8NtcTmRgc0JgSighEyNg96TPrFhemFba68SZuxaha8w==} engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] + cpu: [arm] os: [linux] - libc: [glibc] '@oxc-parser/binding-linux-arm64-gnu@0.128.0': resolution: {integrity: sha512-Xvm48jJah8TlIrURIjNOP/gNiGe6aKvCB+r06VliflFo8Kq7VOLE8PxtgShJzZIqubrgdMdYfvuPPozn7F6MbQ==} @@ -1543,12 +1530,12 @@ packages: os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-arm64-musl@0.126.0': - resolution: {integrity: sha512-FQ+MMh7MT0Dr/u8+RWmWKlfoeWPQyHDbhhxJShJlYtROXXPHsRs9EvmQOZZ3sx4Nn7JU8NX+oyw2YzQ7anBJcA==} + '@oxc-parser/binding-linux-arm64-gnu@0.130.0': + resolution: {integrity: sha512-Q9o7oVlo955KHwS8l1u0bCzIx+JsZUA3XToLXC+MsMhye/9LeBQbt84nh120cl2XLy+TEzvugYDiHShg5yaX6Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [musl] + libc: [glibc] '@oxc-parser/binding-linux-arm64-musl@0.128.0': resolution: {integrity: sha512-M7iwBGmYJTx+pKOYFjI0buop4gJvlmcVzFGaXPt21DKpQkbQZG1f63Yg7LloIYT/t9yLxCw0Lhfx/RFlAlMSjA==} @@ -1564,12 +1551,12 @@ packages: os: [linux] libc: [musl] - '@oxc-parser/binding-linux-ppc64-gnu@0.126.0': - resolution: {integrity: sha512-Wv/T8C98hRQhGTlx2XFyLn5raRMp9U1lOQD+YnXNgAr7wHbJJpZ8mDBU7Rw+M3WytGcGTFcr6kqgfyQeHVtLbQ==} + '@oxc-parser/binding-linux-arm64-musl@0.130.0': + resolution: {integrity: sha512-EiJ/gC0ljbcwVpycC8YWw6ggMbtsPX8XMOt0mPx0aqWeMsNR+L9m05Flbvd5T+GlivG+GkSWQL7tM9SRFpM/dw==} engines: {node: ^20.19.0 || >=22.12.0} - cpu: [ppc64] + cpu: [arm64] os: [linux] - libc: [glibc] + libc: [musl] '@oxc-parser/binding-linux-ppc64-gnu@0.128.0': resolution: {integrity: sha512-21LGNIZb1Pcfk5/EGsqabrxv4yqQOWis1407JJrClS7XpFCrbvr74YAB1V+m54cYbwvO6UWwQqS4WecxiyfCRg==} @@ -1585,10 +1572,10 @@ packages: os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-riscv64-gnu@0.126.0': - resolution: {integrity: sha512-DHx1rT1zauW0ZbLHOiQh5AC9Xs3UkWx2XmfZHs+7nnWYr3sagrufoUQC+/XPwwjMIlCFXiFGM0sFh3TyOCZwqA==} + '@oxc-parser/binding-linux-ppc64-gnu@0.130.0': + resolution: {integrity: sha512-b+h/lsLLurp756dMGizNs5uPaJfyEdWrTcV5t8M609jWm1DEHB1StpRXCkyvwtkJx3m+qL5BNQ0dEKan/4yGFA==} engines: {node: ^20.19.0 || >=22.12.0} - cpu: [riscv64] + cpu: [ppc64] os: [linux] libc: [glibc] @@ -1606,12 +1593,12 @@ packages: os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-riscv64-musl@0.126.0': - resolution: {integrity: sha512-umDc2mTShH0U2zcEYf8mIJ163seLJNn54ZUZYeI5jD4qlg9izPwoLrC2aNPKlMJTu6u/ysmQWiEvIiaAG+INkw==} + '@oxc-parser/binding-linux-riscv64-gnu@0.130.0': + resolution: {integrity: sha512-O19Cil83XAyjEFfo8WhkMwY58ALqZ7ckjGL+25mjMIuF84urWBeANH0FC8B8BsSSygWU3/1aY3ADdDbp+wlBnw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] - libc: [musl] + libc: [glibc] '@oxc-parser/binding-linux-riscv64-musl@0.128.0': resolution: {integrity: sha512-X6Q2oKUrP5GyDd2xniuEBLk6aFQCZ97W2+aVXGgJXdjx5t4/oFuA9ri0wLOUrBIX+qdSuK581snMBio4z910eA==} @@ -1627,12 +1614,12 @@ packages: os: [linux] libc: [musl] - '@oxc-parser/binding-linux-s390x-gnu@0.126.0': - resolution: {integrity: sha512-PXXeWayclRtO1pxQEeCpiqIglQdhK2mAI2VX5xnsWdImzSB5GpoQ8TNw7vTCKk2k+GZuxl+q1knncidjCyUP9w==} + '@oxc-parser/binding-linux-riscv64-musl@0.130.0': + resolution: {integrity: sha512-BgXRVC0+83n3YzCscLQjj6nbyeBIVeZYPTI4fFMAE4WNm2+4RXhWp03IVizL7esIz36kgmT48aebk1iM+cs8sw==} engines: {node: ^20.19.0 || >=22.12.0} - cpu: [s390x] + cpu: [riscv64] os: [linux] - libc: [glibc] + libc: [musl] '@oxc-parser/binding-linux-s390x-gnu@0.128.0': resolution: {integrity: sha512-BdzTmqxfxoYkpgokoLaSnOX6T+R3/goL42klre2tnG+kHbG2TXS0VN+P5BPofH1axdKOHy5ei4ENZrjmCOt2lA==} @@ -1648,10 +1635,10 @@ packages: os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-x64-gnu@0.126.0': - resolution: {integrity: sha512-wzocjxm34TbB3bFlqG65JiLtvf6ZDg2ZxRkLLbgXwDQUNU+0MPjQN8zy/0jBKNA5fnPLk3XeVdZ7Uin+7+CVkg==} + '@oxc-parser/binding-linux-s390x-gnu@0.130.0': + resolution: {integrity: sha512-6tJz0xvnGhsokE7N1WlUSBXibpYmT9xSJFS1Ce41Km/+8gQvdlW8MLhRv8PD0L7ix8vRG0FDDepp3jdOFzdVdw==} engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] + cpu: [s390x] os: [linux] libc: [glibc] @@ -1669,12 +1656,12 @@ packages: os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-x64-musl@0.126.0': - resolution: {integrity: sha512-e83uftP60jmkPs2+CW6T6A1GYzN2H6IumDAiTntv9WyHR73PI3ImHNBkYqnA3ukeKI3xjcCbhSh9QeJWmufxGQ==} + '@oxc-parser/binding-linux-x64-gnu@0.130.0': + resolution: {integrity: sha512-9aCWj83dp3heTQGmGnZGdIWgxjZrr/7VQ0TGFHH5PKByxJKF2Hcr4qvaSUHhhGEa3MSsDjTL1YDP8RAgdL5/Cg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [musl] + libc: [glibc] '@oxc-parser/binding-linux-x64-musl@0.128.0': resolution: {integrity: sha512-4NehAe404MRdoZVS9DW8C5XbJwbXIc/KfVlYdpi5vE4081zc9Y0YzKVqyOYj/Puye7/Do+ohaONBFWlEHYl9hw==} @@ -1690,11 +1677,12 @@ packages: os: [linux] libc: [musl] - '@oxc-parser/binding-openharmony-arm64@0.126.0': - resolution: {integrity: sha512-4WiOILHnPrTDY2/L4mE6PZCYwLN1d3ghma6BuTJ452CCgzRMt3uFplCtR+o3r9zdUWJYb370UizpI9CUcWXr1A==} + '@oxc-parser/binding-linux-x64-musl@0.130.0': + resolution: {integrity: sha512-afXt87aZBqrUVli8TB/I8H1G50RDWcwirjWtXGXYqJ2ZqWEiErH7V72j3LUSDZaivmtu2OLX0KQ/mbhP81mr7A==} engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [openharmony] + cpu: [x64] + os: [linux] + libc: [musl] '@oxc-parser/binding-openharmony-arm64@0.128.0': resolution: {integrity: sha512-kVbqgW9xLL8bh8oc7aYOJilRKXE5G33+tE0jan+duo/9OriaFRpijcCwT2waWs2oqYROYq0GlE7/p3ywoshVeg==} @@ -1708,10 +1696,11 @@ packages: cpu: [arm64] os: [openharmony] - '@oxc-parser/binding-wasm32-wasi@0.126.0': - resolution: {integrity: sha512-Y17hhnrQTrxgAxAyAq401vnN9URsAL4s5AjqpG1NDsXSlhe1yBNnns+rC2P6xcMoitgX5nKH2ryYt9oiFRlzLw==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] + '@oxc-parser/binding-openharmony-arm64@0.130.0': + resolution: {integrity: sha512-I0NCrZV/YZuCGWgqwNN/GO/iXlLF2z+Wgc7u+Aa9N4P51oYeIa0XT+zVBUne4csO9GqxskXgI4g8JzzWGRpfOw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] '@oxc-parser/binding-wasm32-wasi@0.128.0': resolution: {integrity: sha512-L38ojghJYHmgiz6fJd7jwLB/ESDBpB02NdFxh+smqVM6P2anCEvHn0jhaSrt5eVNR1Ak8+moOeftUlofeyvniA==} @@ -1723,11 +1712,10 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] - '@oxc-parser/binding-win32-arm64-msvc@0.126.0': - resolution: {integrity: sha512-Znug1u1iRvT4VC3jANz6nhGBHsFwEFMxuimYpJFwMtsB6H5FcEoZRMmH26tHkSTD03JvDmG+gB65W3ajLjPcSw==} + '@oxc-parser/binding-wasm32-wasi@0.130.0': + resolution: {integrity: sha512-sJgQkGaBX0WJvPUDfwciex6IcTk5O5NLQ1bhEb6f3nBruh1GshKMRSMt2bxZlYrgBzjyBbJzsnO+InPG0bg+fA==} engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [win32] + cpu: [wasm32] '@oxc-parser/binding-win32-arm64-msvc@0.128.0': resolution: {integrity: sha512-xgvO35GyHBtjlQ5AEpaYr7Rll1rvY7zqIhT6ty8E3ezBW2J1SFLjIDEvI/tcgDg6oaseDAqVcM+jU1HuCekgZw==} @@ -1741,10 +1729,10 @@ packages: cpu: [arm64] os: [win32] - '@oxc-parser/binding-win32-ia32-msvc@0.126.0': - resolution: {integrity: sha512-qrw7mx5hFFTxVSXToOA40hpnjgNB/DJprZchtB4rDKNLKqkD3F26HbzaQeH1nxAKej0efSZfJd5Sw3qdtOLGhw==} + '@oxc-parser/binding-win32-arm64-msvc@0.130.0': + resolution: {integrity: sha512-bjcma99sQrNh6RY4mPO9yTkfxql6TDFoN3HWdK31RCKXwNhcDgJXW/l8PUtzKNiQ+9vpKJfJtQq+LklBuxSOBA==} engines: {node: ^20.19.0 || >=22.12.0} - cpu: [ia32] + cpu: [arm64] os: [win32] '@oxc-parser/binding-win32-ia32-msvc@0.128.0': @@ -1759,10 +1747,10 @@ packages: cpu: [ia32] os: [win32] - '@oxc-parser/binding-win32-x64-msvc@0.126.0': - resolution: {integrity: sha512-ibB1s+mPUFXvS7MFJO2jpw/aCNs/P6ifnWlRyTYB+WYBpniOiCcHQQskZneJtwcjQMDRol3RGG3ihoYnzXSY4w==} + '@oxc-parser/binding-win32-ia32-msvc@0.130.0': + resolution: {integrity: sha512-hRYbv6HhpSTzT4xTiIkadLI7upLQxuOdLPR/9nL1fTjwhgutBTPXrwaAPb/jTFVx6/8C7Jb5HcUKhmNwloTbFA==} engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] + cpu: [ia32] os: [win32] '@oxc-parser/binding-win32-x64-msvc@0.128.0': @@ -1777,8 +1765,11 @@ packages: cpu: [x64] os: [win32] - '@oxc-project/types@0.126.0': - resolution: {integrity: sha512-oGfVtjAgwQVVpfBrbtk4e1XDyWHRFta6BS3GWVzrF8xYBT2VGQAk39yJS/wFSMrZqoiCU4oghT3Ch0HaHGIHcQ==} + '@oxc-parser/binding-win32-x64-msvc@0.130.0': + resolution: {integrity: sha512-RBpA9TsRucJq6HNVNCFF1iKg+QeTkLdZf7hi4xaOGCPvMZWvDHjQgSOEZMUpuW4JNciHbxNhLEYmz5CVygjVGQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] '@oxc-project/types@0.128.0': resolution: {integrity: sha512-huv1Y/LzBJkBVHt3OlC7u0zHBW9qXf1FdD7sGmc1rXc2P1mTwHssYv7jyGx5KAACSCH+9B3Bhn6Z9luHRvf7pQ==} @@ -1786,6 +1777,9 @@ packages: '@oxc-project/types@0.129.0': resolution: {integrity: sha512-3oz8m3FGdr2nDXVqmFUw7jolKliC4MoyXYIG2c7gpjBnzUWQpUGIYcXYKxTdTi+N2jusvt610ckTMkxdwHkYEg==} + '@oxc-project/types@0.130.0': + resolution: {integrity: sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==} + '@oxc-transform/binding-android-arm-eabi@0.128.0': resolution: {integrity: sha512-qVO4izEs88ZSo7KOK4P+O5nAXXJmkSadInvFjGkhVnm2R2Wr8trU/GLhjAK0S0u8Qv9bkXspNhgpECk+CTQ/ew==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4686,9 +4680,6 @@ packages: lodash@4.18.1: resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} - logs-sdk@0.0.6: - resolution: {integrity: sha512-G4M1C9aLLBOIWpmw/Lqk4zrap/T2IJsoUOuUDjRcVSLy6lHQqxr3wCqIT1FvvpYTUYpEwvu4utsMY42jTNvx8Q==} - longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -5027,6 +5018,9 @@ packages: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} + nostics@0.1.0: + resolution: {integrity: sha512-gSujQXUjmUOFVum7XazE2EcoHYZB3Et0dZwiQh1plulZdolEZL+Y7TOu9yVsXCxxUqfw5q0+svxJJXvynygKEQ==} + npm-run-path@5.3.0: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -5116,10 +5110,6 @@ packages: resolution: {integrity: sha512-VIXQO2W886aB+N17yV55Sack6aCpbUqtuNAYhNcPV6dFiWIZ5+kwOjvvw36igWwoljfjWhasu99CQ5wtvPJDYg==} engines: {node: ^20.19.0 || >=22.12.0} - oxc-parser@0.126.0: - resolution: {integrity: sha512-FktCvLby/mOHyuijZt22+nOt10dS24gGUZE3XwIbUg7Kf4+rer3/5T7RgwzazlNuVsCjPloZ3p8E+4ONT3A8Kw==} - engines: {node: ^20.19.0 || >=22.12.0} - oxc-parser@0.128.0: resolution: {integrity: sha512-XkOw3eiIxAgQ19WRew/Bq9wc5Ga/guaWIzDBzq80z1PyuDNGvWBpPby9k6YGwV8A8uMw+Nlq3xqlzuDYmUFYUw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -5128,6 +5118,10 @@ packages: resolution: {integrity: sha512-S6eFI+VLkpyA+/Lf8z6qURjDV6Mgo74SLNznNopHTlQW3hedv2MB/z31kBRuBCCTqZN9HHdva0ojljEhPnBKFA==} engines: {node: ^20.19.0 || >=22.12.0} + oxc-parser@0.130.0: + resolution: {integrity: sha512-X0PJ+NmOok8qP3vK9uaW431ngkdM9UPEK7KG466urtIL2+EYTEgbZK2yqe2MWKJKBjRlFweP/pJPx0x9muMEVw==} + engines: {node: ^20.19.0 || >=22.12.0} + oxc-transform@0.128.0: resolution: {integrity: sha512-8DfEHlmUiLOHlCK9DGX+d5tORc1xwPPvoRSHSJCYgLHyGjKp4PvfBrvgi59DkEW0SMOWfO8GL9t+R7vdKtupbg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -5963,11 +5957,6 @@ packages: peerDependencies: typescript: '>=4.8.4' - ts-declaration-location@1.0.7: - resolution: {integrity: sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA==} - peerDependencies: - typescript: '>=4.0.0' - ts-dedent@2.2.0: resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} engines: {node: '>=6.10'} @@ -6634,7 +6623,7 @@ packages: snapshots: - '@antfu/eslint-config@9.0.0(@typescript-eslint/rule-tester@8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3))(@typescript-eslint/typescript-estree@8.59.2(typescript@6.0.3))(@typescript-eslint/utils@8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3))(@vue/compiler-sfc@3.5.34)(eslint@10.3.0(jiti@2.7.0))(ts-declaration-location@1.0.7(typescript@6.0.3))(typescript@6.0.3)(vitest@4.1.6(@types/node@25.7.0)(vite@8.0.12(@types/node@25.7.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.21.0)(yaml@2.8.4)))': + '@antfu/eslint-config@9.0.0(@typescript-eslint/rule-tester@8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3))(@typescript-eslint/typescript-estree@8.59.2(typescript@6.0.3))(@typescript-eslint/utils@8.59.2(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3))(@vue/compiler-sfc@3.5.34)(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3)(vitest@4.1.6(@types/node@25.7.0)(vite@8.0.12(@types/node@25.7.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.21.0)(yaml@2.8.4)))': dependencies: '@antfu/install-pkg': 1.1.0 '@clack/prompts': 1.3.0 @@ -6656,7 +6645,7 @@ snapshots: eslint-plugin-import-lite: 0.6.0(eslint@10.3.0(jiti@2.7.0)) eslint-plugin-jsdoc: 62.9.0(eslint@10.3.0(jiti@2.7.0)) eslint-plugin-jsonc: 3.1.2(eslint@10.3.0(jiti@2.7.0)) - eslint-plugin-n: 18.0.1(eslint@10.3.0(jiti@2.7.0))(ts-declaration-location@1.0.7(typescript@6.0.3))(typescript@6.0.3) + eslint-plugin-n: 18.0.1(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) eslint-plugin-no-only-tests: 3.4.0 eslint-plugin-perfectionist: 5.9.0(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3) eslint-plugin-pnpm: 1.6.0(eslint@10.3.0(jiti@2.7.0)) @@ -6968,22 +6957,11 @@ snapshots: tslib: 2.8.1 optional: true - '@emnapi/core@1.9.2': - dependencies: - '@emnapi/wasi-threads': 1.2.1 - tslib: 2.8.1 - optional: true - '@emnapi/runtime@1.10.0': dependencies: tslib: 2.8.1 optional: true - '@emnapi/runtime@1.9.2': - dependencies: - tslib: 2.8.1 - optional: true - '@emnapi/wasi-threads@1.2.1': dependencies: tslib: 2.8.1 @@ -7362,13 +7340,6 @@ snapshots: '@tybys/wasm-util': 0.10.2 optional: true - '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': - dependencies: - '@emnapi/core': 1.9.2 - '@emnapi/runtime': 1.9.2 - '@tybys/wasm-util': 0.10.2 - optional: true - '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -7720,16 +7691,13 @@ snapshots: '@oxc-minify/binding-win32-x64-msvc@0.128.0': optional: true - '@oxc-parser/binding-android-arm-eabi@0.126.0': - optional: true - '@oxc-parser/binding-android-arm-eabi@0.128.0': optional: true '@oxc-parser/binding-android-arm-eabi@0.129.0': optional: true - '@oxc-parser/binding-android-arm64@0.126.0': + '@oxc-parser/binding-android-arm-eabi@0.130.0': optional: true '@oxc-parser/binding-android-arm64@0.128.0': @@ -7738,7 +7706,7 @@ snapshots: '@oxc-parser/binding-android-arm64@0.129.0': optional: true - '@oxc-parser/binding-darwin-arm64@0.126.0': + '@oxc-parser/binding-android-arm64@0.130.0': optional: true '@oxc-parser/binding-darwin-arm64@0.128.0': @@ -7747,7 +7715,7 @@ snapshots: '@oxc-parser/binding-darwin-arm64@0.129.0': optional: true - '@oxc-parser/binding-darwin-x64@0.126.0': + '@oxc-parser/binding-darwin-arm64@0.130.0': optional: true '@oxc-parser/binding-darwin-x64@0.128.0': @@ -7756,7 +7724,7 @@ snapshots: '@oxc-parser/binding-darwin-x64@0.129.0': optional: true - '@oxc-parser/binding-freebsd-x64@0.126.0': + '@oxc-parser/binding-darwin-x64@0.130.0': optional: true '@oxc-parser/binding-freebsd-x64@0.128.0': @@ -7765,7 +7733,7 @@ snapshots: '@oxc-parser/binding-freebsd-x64@0.129.0': optional: true - '@oxc-parser/binding-linux-arm-gnueabihf@0.126.0': + '@oxc-parser/binding-freebsd-x64@0.130.0': optional: true '@oxc-parser/binding-linux-arm-gnueabihf@0.128.0': @@ -7774,7 +7742,7 @@ snapshots: '@oxc-parser/binding-linux-arm-gnueabihf@0.129.0': optional: true - '@oxc-parser/binding-linux-arm-musleabihf@0.126.0': + '@oxc-parser/binding-linux-arm-gnueabihf@0.130.0': optional: true '@oxc-parser/binding-linux-arm-musleabihf@0.128.0': @@ -7783,7 +7751,7 @@ snapshots: '@oxc-parser/binding-linux-arm-musleabihf@0.129.0': optional: true - '@oxc-parser/binding-linux-arm64-gnu@0.126.0': + '@oxc-parser/binding-linux-arm-musleabihf@0.130.0': optional: true '@oxc-parser/binding-linux-arm64-gnu@0.128.0': @@ -7792,7 +7760,7 @@ snapshots: '@oxc-parser/binding-linux-arm64-gnu@0.129.0': optional: true - '@oxc-parser/binding-linux-arm64-musl@0.126.0': + '@oxc-parser/binding-linux-arm64-gnu@0.130.0': optional: true '@oxc-parser/binding-linux-arm64-musl@0.128.0': @@ -7801,7 +7769,7 @@ snapshots: '@oxc-parser/binding-linux-arm64-musl@0.129.0': optional: true - '@oxc-parser/binding-linux-ppc64-gnu@0.126.0': + '@oxc-parser/binding-linux-arm64-musl@0.130.0': optional: true '@oxc-parser/binding-linux-ppc64-gnu@0.128.0': @@ -7810,7 +7778,7 @@ snapshots: '@oxc-parser/binding-linux-ppc64-gnu@0.129.0': optional: true - '@oxc-parser/binding-linux-riscv64-gnu@0.126.0': + '@oxc-parser/binding-linux-ppc64-gnu@0.130.0': optional: true '@oxc-parser/binding-linux-riscv64-gnu@0.128.0': @@ -7819,7 +7787,7 @@ snapshots: '@oxc-parser/binding-linux-riscv64-gnu@0.129.0': optional: true - '@oxc-parser/binding-linux-riscv64-musl@0.126.0': + '@oxc-parser/binding-linux-riscv64-gnu@0.130.0': optional: true '@oxc-parser/binding-linux-riscv64-musl@0.128.0': @@ -7828,7 +7796,7 @@ snapshots: '@oxc-parser/binding-linux-riscv64-musl@0.129.0': optional: true - '@oxc-parser/binding-linux-s390x-gnu@0.126.0': + '@oxc-parser/binding-linux-riscv64-musl@0.130.0': optional: true '@oxc-parser/binding-linux-s390x-gnu@0.128.0': @@ -7837,7 +7805,7 @@ snapshots: '@oxc-parser/binding-linux-s390x-gnu@0.129.0': optional: true - '@oxc-parser/binding-linux-x64-gnu@0.126.0': + '@oxc-parser/binding-linux-s390x-gnu@0.130.0': optional: true '@oxc-parser/binding-linux-x64-gnu@0.128.0': @@ -7846,7 +7814,7 @@ snapshots: '@oxc-parser/binding-linux-x64-gnu@0.129.0': optional: true - '@oxc-parser/binding-linux-x64-musl@0.126.0': + '@oxc-parser/binding-linux-x64-gnu@0.130.0': optional: true '@oxc-parser/binding-linux-x64-musl@0.128.0': @@ -7855,7 +7823,7 @@ snapshots: '@oxc-parser/binding-linux-x64-musl@0.129.0': optional: true - '@oxc-parser/binding-openharmony-arm64@0.126.0': + '@oxc-parser/binding-linux-x64-musl@0.130.0': optional: true '@oxc-parser/binding-openharmony-arm64@0.128.0': @@ -7864,11 +7832,7 @@ snapshots: '@oxc-parser/binding-openharmony-arm64@0.129.0': optional: true - '@oxc-parser/binding-wasm32-wasi@0.126.0': - dependencies: - '@emnapi/core': 1.9.2 - '@emnapi/runtime': 1.9.2 - '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + '@oxc-parser/binding-openharmony-arm64@0.130.0': optional: true '@oxc-parser/binding-wasm32-wasi@0.128.0': @@ -7885,7 +7849,11 @@ snapshots: '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true - '@oxc-parser/binding-win32-arm64-msvc@0.126.0': + '@oxc-parser/binding-wasm32-wasi@0.130.0': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true '@oxc-parser/binding-win32-arm64-msvc@0.128.0': @@ -7894,7 +7862,7 @@ snapshots: '@oxc-parser/binding-win32-arm64-msvc@0.129.0': optional: true - '@oxc-parser/binding-win32-ia32-msvc@0.126.0': + '@oxc-parser/binding-win32-arm64-msvc@0.130.0': optional: true '@oxc-parser/binding-win32-ia32-msvc@0.128.0': @@ -7903,7 +7871,7 @@ snapshots: '@oxc-parser/binding-win32-ia32-msvc@0.129.0': optional: true - '@oxc-parser/binding-win32-x64-msvc@0.126.0': + '@oxc-parser/binding-win32-ia32-msvc@0.130.0': optional: true '@oxc-parser/binding-win32-x64-msvc@0.128.0': @@ -7912,12 +7880,15 @@ snapshots: '@oxc-parser/binding-win32-x64-msvc@0.129.0': optional: true - '@oxc-project/types@0.126.0': {} + '@oxc-parser/binding-win32-x64-msvc@0.130.0': + optional: true '@oxc-project/types@0.128.0': {} '@oxc-project/types@0.129.0': {} + '@oxc-project/types@0.130.0': {} + '@oxc-transform/binding-android-arm-eabi@0.128.0': optional: true @@ -9888,7 +9859,7 @@ snapshots: transitivePeerDependencies: - '@eslint/json' - eslint-plugin-n@18.0.1(eslint@10.3.0(jiti@2.7.0))(ts-declaration-location@1.0.7(typescript@6.0.3))(typescript@6.0.3): + eslint-plugin-n@18.0.1(eslint@10.3.0(jiti@2.7.0))(typescript@6.0.3): dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@10.3.0(jiti@2.7.0)) enhanced-resolve: 5.21.2 @@ -9900,7 +9871,6 @@ snapshots: ignore: 5.3.2 semver: 7.8.0 optionalDependencies: - ts-declaration-location: 1.0.7(typescript@6.0.3) typescript: 6.0.3 eslint-plugin-no-only-tests@3.4.0: {} @@ -10742,12 +10712,6 @@ snapshots: lodash@4.18.1: {} - logs-sdk@0.0.6: - dependencies: - magic-string: 0.30.21 - oxc-parser: 0.126.0 - unplugin: 3.0.0 - longest-streak@3.1.0: {} lru-cache@10.4.3: {} @@ -11370,6 +11334,12 @@ snapshots: normalize-path@3.0.0: {} + nostics@0.1.0: + dependencies: + magic-string: 0.30.21 + oxc-parser: 0.130.0 + unplugin: 3.0.0 + npm-run-path@5.3.0: dependencies: path-key: 4.0.0 @@ -11607,31 +11577,6 @@ snapshots: '@oxc-minify/binding-win32-ia32-msvc': 0.128.0 '@oxc-minify/binding-win32-x64-msvc': 0.128.0 - oxc-parser@0.126.0: - dependencies: - '@oxc-project/types': 0.126.0 - optionalDependencies: - '@oxc-parser/binding-android-arm-eabi': 0.126.0 - '@oxc-parser/binding-android-arm64': 0.126.0 - '@oxc-parser/binding-darwin-arm64': 0.126.0 - '@oxc-parser/binding-darwin-x64': 0.126.0 - '@oxc-parser/binding-freebsd-x64': 0.126.0 - '@oxc-parser/binding-linux-arm-gnueabihf': 0.126.0 - '@oxc-parser/binding-linux-arm-musleabihf': 0.126.0 - '@oxc-parser/binding-linux-arm64-gnu': 0.126.0 - '@oxc-parser/binding-linux-arm64-musl': 0.126.0 - '@oxc-parser/binding-linux-ppc64-gnu': 0.126.0 - '@oxc-parser/binding-linux-riscv64-gnu': 0.126.0 - '@oxc-parser/binding-linux-riscv64-musl': 0.126.0 - '@oxc-parser/binding-linux-s390x-gnu': 0.126.0 - '@oxc-parser/binding-linux-x64-gnu': 0.126.0 - '@oxc-parser/binding-linux-x64-musl': 0.126.0 - '@oxc-parser/binding-openharmony-arm64': 0.126.0 - '@oxc-parser/binding-wasm32-wasi': 0.126.0 - '@oxc-parser/binding-win32-arm64-msvc': 0.126.0 - '@oxc-parser/binding-win32-ia32-msvc': 0.126.0 - '@oxc-parser/binding-win32-x64-msvc': 0.126.0 - oxc-parser@0.128.0: dependencies: '@oxc-project/types': 0.128.0 @@ -11682,6 +11627,31 @@ snapshots: '@oxc-parser/binding-win32-ia32-msvc': 0.129.0 '@oxc-parser/binding-win32-x64-msvc': 0.129.0 + oxc-parser@0.130.0: + dependencies: + '@oxc-project/types': 0.130.0 + optionalDependencies: + '@oxc-parser/binding-android-arm-eabi': 0.130.0 + '@oxc-parser/binding-android-arm64': 0.130.0 + '@oxc-parser/binding-darwin-arm64': 0.130.0 + '@oxc-parser/binding-darwin-x64': 0.130.0 + '@oxc-parser/binding-freebsd-x64': 0.130.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.130.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.130.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.130.0 + '@oxc-parser/binding-linux-arm64-musl': 0.130.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.130.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.130.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.130.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.130.0 + '@oxc-parser/binding-linux-x64-gnu': 0.130.0 + '@oxc-parser/binding-linux-x64-musl': 0.130.0 + '@oxc-parser/binding-openharmony-arm64': 0.130.0 + '@oxc-parser/binding-wasm32-wasi': 0.130.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.130.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.130.0 + '@oxc-parser/binding-win32-x64-msvc': 0.130.0 + oxc-transform@0.128.0: optionalDependencies: '@oxc-transform/binding-android-arm-eabi': 0.128.0 @@ -12562,12 +12532,6 @@ snapshots: dependencies: typescript: 6.0.3 - ts-declaration-location@1.0.7(typescript@6.0.3): - dependencies: - picomatch: 4.0.4 - typescript: 6.0.3 - optional: true - ts-dedent@2.2.0: {} tsdown@0.22.0(tsx@4.21.0)(typescript@6.0.3): diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index e813509..35ee386 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -40,8 +40,8 @@ catalogs: h3: 2.0.1-rc.22 immer: ^11.1.8 launch-editor: ^2.13.2 - logs-sdk: ^0.0.6 mrmime: ^2.0.1 + nostics: ^0.1.0 obug: ^2.1.1 ohash: ^2.0.11 open: ^11.0.0 diff --git a/skills/devframe/SKILL.md b/skills/devframe/SKILL.md index b9b7361..0e4b871 100644 --- a/skills/devframe/SKILL.md +++ b/skills/devframe/SKILL.md @@ -84,7 +84,7 @@ See `templates/counter-devframe.ts` for a runnable counter example, `templates/s |------|---------| | `ctx.rpc` | Register RPC functions, broadcast, shared state, streaming channels | | `ctx.views` | Serve static files via `hostStatic(base, distDir)` | -| `ctx.diagnostics` | Structured diagnostics host (logs-sdk) — register custom error codes | +| `ctx.diagnostics` | Structured diagnostics host (nostics) — register custom error codes | | `ctx.agent` | Expose tools + resources to coding agents (experimental) | | `ctx.host` | Runtime abstraction — `mountStatic`, `resolveOrigin`, `getStorageDir` | | `ctx.mode` | `'dev'` or `'build'` — gate setup work per runtime | diff --git a/tests/__snapshots__/tsnapi/devframe/index.snapshot.d.ts b/tests/__snapshots__/tsnapi/devframe/index.snapshot.d.ts index 272c44b..2bb3743 100644 --- a/tests/__snapshots__/tsnapi/devframe/index.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/devframe/index.snapshot.d.ts @@ -25,6 +25,7 @@ export { DevframeSpaOptions } export { DevToolsAgentHost } export { DevToolsAgentHostEvents } export { DevToolsCapabilities } +export { DevToolsDefineDiagnosticsOptions } export { DevToolsDiagnosticsDefinition } export { DevToolsDiagnosticsHost } export { DevToolsDiagnosticsLogger } diff --git a/tests/__snapshots__/tsnapi/devframe/node.snapshot.d.ts b/tests/__snapshots__/tsnapi/devframe/node.snapshot.d.ts index fe4cf52..7f11684 100644 --- a/tests/__snapshots__/tsnapi/devframe/node.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/devframe/node.snapshot.d.ts @@ -50,14 +50,11 @@ export declare class DevToolsAgentHost implements DevToolsAgentHost$1 { } export declare class DevToolsDiagnosticsHost implements DevToolsDiagnosticsHost$1 { readonly context: DevToolsNodeContext; - private _definitions; - private _logger; - readonly defineDiagnostics: typeof defineDiagnostics; - readonly createLogger: typeof createLogger; - constructor(_: DevToolsNodeContext, _?: unknown[]); - get logger(): DevToolsDiagnosticsLogger; - register(_: unknown): void; - private _rebuild; + private _registry; + readonly logger: DevToolsDiagnosticsLogger; + readonly defineDiagnostics: DevToolsDiagnosticsHost$1['defineDiagnostics']; + constructor(_: DevToolsNodeContext, _?: Array>); + register(_: Record): void; } export declare class DevToolsViewHost implements DevToolsViewHost$1 { readonly context: DevToolsNodeContext; diff --git a/tests/__snapshots__/tsnapi/devframe/types.snapshot.d.ts b/tests/__snapshots__/tsnapi/devframe/types.snapshot.d.ts index b7365ac..f6e3258 100644 --- a/tests/__snapshots__/tsnapi/devframe/types.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/devframe/types.snapshot.d.ts @@ -21,6 +21,7 @@ export { DevframeSpaOptions } export { DevToolsAgentHost } export { DevToolsAgentHostEvents } export { DevToolsCapabilities } +export { DevToolsDefineDiagnosticsOptions } export { DevToolsDiagnosticsDefinition } export { DevToolsDiagnosticsHost } export { DevToolsDiagnosticsLogger }