{"version":3,"file":"index.mjs","names":[],"sources":["../src/diagnostics.ts","../src/error.ts","../src/reporter.ts","../src/logger.ts"],"sourcesContent":["import type { ExtractParams, IsEmptyObject, Simplify } from './utils'\n\n/**\n * Severity level of a diagnostic. Controls console routing and formatter styling.\n */\nexport type DiagnosticLevel = 'error' | 'warn' | 'suggestion' | 'deprecation'\n\n/**\n * Source location in user code. Use the `file:line:column` string convention\n * when a simpler representation suffices.\n */\nexport interface SourceLocation {\n  file?: string\n  line?: number\n  column?: number\n}\n\n/**\n * A structured, serializable diagnostic object with a stable code.\n */\nexport interface Diagnostic {\n  /**\n   * Unique, stable identifier for this diagnostic (e.g. `MATH_E001`).\n   */\n  code: string\n  /**\n   * Severity level. Defaults to `'error'` when not specified in the definition.\n   */\n  level: DiagnosticLevel\n  /**\n   * Human-readable description of the problem.\n   */\n  message: string\n  /**\n   * Explains *why* this is a problem — the root cause or rationale.\n   */\n  why?: string\n  /**\n   * Actionable instructions on how to resolve the problem.\n   */\n  fix?: string\n  /**\n   * Lighter guidance or pointers — additional context that may help.\n   */\n  hint?: string\n  /**\n   * URL to extended documentation for this diagnostic code.\n   * Auto-generated from {@link DefineDiagnosticsOptions.docsBase}.\n   */\n  docs?: string\n  /**\n   * Relevant source locations in user code associated with this diagnostic.\n   */\n  sources?: SourceLocation[]\n  /**\n   * Original error or exception that triggered this diagnostic.\n   * Propagated to {@link CodedError.cause} when throwing.\n   */\n  cause?: unknown\n  /**\n   * Arbitrary key-value metadata for machine consumers (reporters, telemetry).\n   * Not rendered by formatters.\n   */\n  context?: Record<string, unknown>\n  /**\n   * Call stack captured by the logger at the call site.\n   * Auto-populated by action methods (`.warn()`, `.error()`, `.throw()`, `.log()`).\n   */\n  stack?: string\n}\n\n/**\n * Fields that can be overridden per-call when invoking a diagnostic factory.\n */\nexport type Overrides = Partial<Pick<Diagnostic, 'level' | 'sources' | 'cause' | 'context'>>\n\n/**\n * A template for a diagnostic text field — either a static string or a function\n * that receives interpolation parameters and returns a string.\n */\nexport type MessageTemplate<P = any> = string | ((params: P) => string)\n\n/**\n * Schema for a single diagnostic code within {@link defineDiagnostics}.\n */\nexport interface DiagnosticDefinition {\n  /**\n   * Message template. If a function, receives typed params for interpolation.\n   */\n  message: MessageTemplate\n  /**\n   * Fix template. Describes how to resolve the problem.\n   */\n  fix?: MessageTemplate\n  /**\n   * Why template. Explains the root cause or rationale.\n   */\n  why?: MessageTemplate\n  /**\n   * Hint template. Provides additional guidance.\n   */\n  hint?: MessageTemplate\n  /**\n   * Default severity for this code. Defaults to `'error'` if omitted.\n   */\n  level?: DiagnosticLevel\n}\n\n/**\n * Callable factory for a single diagnostic code. When the definition uses template\n * functions, the first argument is the interpolation params object; otherwise\n * the only (optional) argument is {@link Overrides}.\n */\nexport type CodeFactory<T>\n  = IsEmptyObject<ExtractParams<T>> extends true\n    ? (overrides?: Overrides) => Diagnostic\n    : (params: Simplify<ExtractParams<T>>, overrides?: Overrides) => Diagnostic\n\n/**\n * Utility methods available on every {@link DiagnosticsResult}.\n */\nexport interface DiagnosticsMethods<C extends Record<string, DiagnosticDefinition>> {\n  /**\n   * Returns all registered diagnostic code strings.\n   */\n  codes: () => (keyof C & string)[]\n  /**\n   * Type-guard that checks whether `code` is a registered diagnostic code.\n   */\n  has: (code: string) => code is Extract<keyof C, string>\n  /**\n   * Returns the raw {@link DiagnosticDefinition} for a given code.\n   */\n  get: <K extends keyof C>(code: K) => C[K]\n  /**\n   * Creates a new diagnostics object that includes both the current codes\n   * and the provided additional definitions.\n   */\n  extend: <U extends Record<string, DiagnosticDefinition>>(defs: U) => DiagnosticsResult<C & U>\n}\n\n/**\n * The return type of {@link defineDiagnostics} — an object whose keys are diagnostic\n * codes (each a {@link CodeFactory}) plus {@link DiagnosticsMethods} for introspection.\n */\nexport type DiagnosticsResult<C extends Record<string, DiagnosticDefinition>> = {\n  [K in keyof C]: CodeFactory<C[K]>\n} & DiagnosticsMethods<C>\n\n/**\n * Options for {@link defineDiagnostics}.\n */\nexport interface DefineDiagnosticsOptions<C extends Record<string, DiagnosticDefinition>> {\n  /**\n   * Base URL or resolver for documentation links. When a string, the code is\n   * appended as a lowercase path segment (e.g. `\"https://docs.example.com\"` →\n   * `\"https://docs.example.com/math_e001\"`). When a function, receives the code\n   * and returns a URL or `undefined`.\n   */\n  docsBase?: string | ((code: string) => string | undefined)\n  /**\n   * Map of diagnostic codes to their definitions.\n   */\n  codes: C\n}\n\n/**\n * Resolves a {@link MessageTemplate} into a string, or `undefined` if the template is absent.\n */\nfunction resolveTemplate(template: MessageTemplate | undefined, params: any): string | undefined {\n  if (template == null)\n    return undefined\n  if (typeof template === 'function')\n    return template(params)\n  return template\n}\n\n/**\n * Creates a typed diagnostics object from a set of code definitions. Each code\n * becomes a callable factory that produces {@link Diagnostic} objects with\n * template interpolation and optional per-call overrides.\n */\nexport function defineDiagnostics<C extends Record<string, DiagnosticDefinition>>(\n  options: DefineDiagnosticsOptions<C>,\n): DiagnosticsResult<C> {\n  const { docsBase, codes } = options\n\n  const result = {} as any\n  const codeKeys = Object.keys(codes)\n\n  for (const code of codeKeys) {\n    const def = codes[code]\n    result[code] = (paramsOrOverrides?: any, maybeOverrides?: Overrides): Diagnostic => {\n      // Determine if first arg is params or overrides\n      const hasParams = typeof def.message === 'function'\n        || typeof def.fix === 'function'\n        || typeof def.why === 'function'\n        || typeof def.hint === 'function'\n\n      const params = hasParams ? paramsOrOverrides : undefined\n      const overrides = hasParams ? maybeOverrides : paramsOrOverrides as Overrides | undefined\n\n      const docs = typeof docsBase === 'function'\n        ? docsBase(code)\n        : docsBase != null\n          ? `${docsBase}/${code.toLowerCase()}`\n          : undefined\n\n      const diagnostic: Diagnostic = {\n        code,\n        level: def.level ?? 'error',\n        message: resolveTemplate(def.message, params)!,\n        ...(docs != null && { docs }),\n        ...resolveTemplate(def.fix, params) != null && { fix: resolveTemplate(def.fix, params) },\n        ...resolveTemplate(def.why, params) != null && { why: resolveTemplate(def.why, params) },\n        ...resolveTemplate(def.hint, params) != null && { hint: resolveTemplate(def.hint, params) },\n        ...overrides,\n      }\n\n      return diagnostic\n    }\n  }\n\n  Object.defineProperties(result, {\n    codes: {\n      value: () => codeKeys,\n      enumerable: false,\n    },\n    has: {\n      value: (code: string) => code in codes,\n      enumerable: false,\n    },\n    get: {\n      value: (code: string) => codes[code],\n      enumerable: false,\n    },\n    extend: {\n      value: <U extends Record<string, DiagnosticDefinition>>(defs: U) =>\n        defineDiagnostics({ ...options, codes: { ...codes, ...defs } as any }),\n      enumerable: false,\n    },\n  })\n\n  return result as DiagnosticsResult<C>\n}\n","import type { Diagnostic } from './diagnostics'\n\nexport class CodedError extends Error {\n  readonly diagnostic: Diagnostic\n\n  constructor(diagnostic: Diagnostic) {\n    super(`[${diagnostic.code}] ${diagnostic.message}`)\n    this.name = 'CodedError'\n    this.diagnostic = diagnostic\n    if (diagnostic.cause != null)\n      this.cause = diagnostic.cause\n  }\n}\n","import type { Diagnostic } from './diagnostics'\n\nexport type Reporter = (diagnostic: Diagnostic, formatted: string) => void\n\nexport const consoleReporter: Reporter = (diagnostic, formatted) => {\n  if (diagnostic.level === 'error')\n    console.error(formatted)\n  else\n    console.warn(formatted)\n}\n\nexport function createFetchReporter(url: string): Reporter {\n  return (diagnostic, _formatted) => {\n    fetch(url, {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify(diagnostic),\n    }).catch(() => { })\n  }\n}\n","import type { Diagnostic } from './diagnostics'\nimport type { Formatter } from './format'\nimport type { Reporter } from './reporter'\nimport { CodedError } from './error'\nimport { plainFormatter } from './format'\nimport { consoleReporter } from './reporter'\n\nexport interface DiagnosticActions extends Diagnostic {\n  throw: () => never\n  warn: () => void\n  error: () => void\n  log: () => void\n  format: () => string\n}\n\n// Type utilities for extracting params from template fields\n\ntype ActionFactories<T> = {\n  [K in keyof T as T[K] extends (...args: any[]) => Diagnostic ? K : never]:\n  T[K] extends (...args: infer A) => Diagnostic\n    ? (...args: A) => DiagnosticActions\n    : never\n}\n\nexport type MergeFactories<D extends readonly any[]>\n  = D extends readonly [infer First, ...infer Rest]\n    ? ActionFactories<First> & MergeFactories<Rest>\n    // eslint-disable-next-line ts/no-empty-object-type\n    : {}\n\nexport interface LoggerMethods {\n  throw: (diagnostic: Diagnostic) => never\n  warn: (diagnostic: Diagnostic) => void\n  error: (diagnostic: Diagnostic) => void\n  log: (diagnostic: Diagnostic) => void\n  format: (diagnostic: Diagnostic) => string\n}\n\nexport type Logger<D extends readonly any[]> = MergeFactories<D> & LoggerMethods\n\nexport interface CreateLoggerOptions<D extends readonly any[]> {\n  diagnostics: [...D]\n  formatter?: Formatter\n  reporters?: Reporter | Reporter[]\n  captureStack?: boolean\n}\n\nfunction captureStackTrace(): string | undefined {\n  const err: { stack?: string } = {}\n  if (typeof Error.captureStackTrace === 'function') {\n    Error.captureStackTrace(err, captureStackTrace)\n  }\n  else {\n    // eslint-disable-next-line unicorn/error-message -- only used for stack capture\n    err.stack = new Error().stack\n  }\n  if (!err.stack)\n    return undefined\n\n  const lines = err.stack.split('\\n')\n\n  // Find where \"at \" frames begin (skip \"Error\" header)\n  let frameStart = 0\n  while (frameStart < lines.length && !lines[frameStart].trimStart().startsWith('at ')) {\n    frameStart++\n  }\n\n  // V8 captureStackTrace already strips captureStackTrace itself,\n  // fallback needs to skip captureStackTrace + the action method (2 frames)\n  const skipInternal = typeof Error.captureStackTrace === 'function' ? 1 : 2\n\n  const frames = lines\n    .slice(frameStart + skipInternal)\n    .filter(line => !line.includes('/node_modules/') && !line.includes('(node:'))\n    .map(line => line.trim())\n\n  return frames.length > 0 ? frames.join('\\n') : undefined\n}\n\nfunction formatAndReport(formatter: Formatter, reporters: Reporter[], diagnostic: Diagnostic): string {\n  const formatted = formatter(diagnostic)\n  for (const reporter of reporters)\n    reporter(diagnostic, formatted)\n  return formatted\n}\n\nfunction createActions(\n  diagnostic: Diagnostic,\n  formatter: Formatter,\n  reporters: Reporter[],\n  shouldCaptureStack: boolean,\n): DiagnosticActions {\n  return Object.assign({}, diagnostic, {\n    throw(): never {\n      const stack = shouldCaptureStack ? captureStackTrace() : undefined\n      const d = stack ? { ...diagnostic, stack } : diagnostic\n      formatAndReport(formatter, reporters, d)\n      throw new CodedError(d)\n    },\n    warn() {\n      const stack = shouldCaptureStack ? captureStackTrace() : undefined\n      formatAndReport(formatter, reporters, { ...diagnostic, level: 'warn' as const, ...(stack && { stack }) })\n    },\n    error() {\n      const stack = shouldCaptureStack ? captureStackTrace() : undefined\n      formatAndReport(formatter, reporters, { ...diagnostic, level: 'error' as const, ...(stack && { stack }) })\n    },\n    log() {\n      const stack = shouldCaptureStack ? captureStackTrace() : undefined\n      const d = stack ? { ...diagnostic, stack } : diagnostic\n      formatAndReport(formatter, reporters, d)\n    },\n    format() {\n      return formatter(diagnostic)\n    },\n  })\n}\n\nexport function createLogger<const D extends readonly any[]>(\n  options: CreateLoggerOptions<D>,\n): Logger<D> {\n  const formatter = options.formatter ?? plainFormatter\n  const reporters = Array.isArray(options.reporters)\n    ? options.reporters\n    : [options.reporters ?? consoleReporter]\n  const shouldCaptureStack = options.captureStack !== false\n\n  const result = {} as any\n\n  // Merge all diagnostic code factories\n  for (const diagnostics of options.diagnostics) {\n    const codeKeys = typeof diagnostics.codes === 'function'\n      ? diagnostics.codes()\n      : Object.keys(diagnostics)\n\n    for (const code of codeKeys) {\n      if (typeof diagnostics[code] === 'function') {\n        result[code] = (...args: any[]) => {\n          const diagnostic = diagnostics[code](...args)\n          return createActions(diagnostic, formatter, reporters, shouldCaptureStack)\n        }\n      }\n    }\n  }\n\n  // Raw logger methods\n  result.throw = (diagnostic: Diagnostic): never => {\n    const stack = shouldCaptureStack ? captureStackTrace() : undefined\n    const d = stack ? { ...diagnostic, stack } : diagnostic\n    formatAndReport(formatter, reporters, d)\n    throw new CodedError(d)\n  }\n  result.warn = (diagnostic: Diagnostic): void => {\n    const stack = shouldCaptureStack ? captureStackTrace() : undefined\n    formatAndReport(formatter, reporters, { ...diagnostic, level: 'warn' as const, ...(stack && { stack }) })\n  }\n  result.error = (diagnostic: Diagnostic): void => {\n    const stack = shouldCaptureStack ? captureStackTrace() : undefined\n    formatAndReport(formatter, reporters, { ...diagnostic, level: 'error' as const, ...(stack && { stack }) })\n  }\n  result.log = (diagnostic: Diagnostic): void => {\n    const stack = shouldCaptureStack ? captureStackTrace() : undefined\n    const d = stack ? { ...diagnostic, stack } : diagnostic\n    formatAndReport(formatter, reporters, d)\n  }\n  result.format = (diagnostic: Diagnostic): string => {\n    return formatter(diagnostic)\n  }\n\n  return result as Logger<D>\n}\n"],"mappings":"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"}