All files / scripts/fetch-calendar/mcp errors.ts

100% Statements 6/6
100% Branches 0/0
100% Functions 2/2
100% Lines 6/6

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41                                9x             25x                     18x 18x 18x 18x      
/**
 * @module scripts/fetch-calendar/mcp/errors
 * @description Typed transport-error class and HTML-error detector for the
 * MCP calendar transport.
 *
 * Per `Threat_Modeling.md` (trust-boundary rule for external HTML), an HTML
 * response from a JSON-RPC endpoint is treated as a hostile / error response
 * — never parsed as JSON — and the orchestrator falls back to the web
 * scraper instead.
 *
 * @author Hack23 AB
 * @license Apache-2.0
 */
 
// HTML detection: common HTML document / fragment leading tags.
export const HTML_PREFIX_RE =
  /^\s*(?:<!doctype(?=[\s>])|<html(?=[\s>/])|<head(?=[\s>/])|<body(?=[\s>/])|<title(?=[\s>/])|<meta(?=[\s>/]))/i;
 
/**
 * Returns true when `text` looks like an HTML document rather than JSON.
 * Used to detect when the MCP endpoint returns an error page instead of JSON.
 */
export function isHtmlErrorResponse(text: string): boolean {
  return HTML_PREFIX_RE.test(text);
}
 
/** Typed error for MCP transport / protocol failures. */
export class CalendarMcpError extends Error {
  /** Error category. */
  readonly kind: 'html' | 'http' | 'network' | 'json' | 'tool';
  /** Raw response body (only present for `html` / `http` kinds). */
  readonly responseText?: string;
 
  constructor(message: string, kind: CalendarMcpError['kind'], responseText?: string) {
    super(message);
    this.name = 'CalendarMcpError';
    this.kind = kind;
    this.responseText = responseText;
  }
}