Skip to content

Latest commit

 

History

History
392 lines (298 loc) · 15.8 KB

File metadata and controls

392 lines (298 loc) · 15.8 KB

← Back to Package Overview

API Reference: @dawmatt/api-grade-core

Detailed reference for all exported functions, classes, and types.

Scope: this page documents the @dawmatt/api-grade-core programmatic library API only. For the MCP server's tools (including the recoveryOption parameter), see MCP Server Tool Reference.


GradeEngine

The main class for grading API specifications.

import { GradeEngine } from '@dawmatt/api-grade-core';
const engine = new GradeEngine();

engine.grade(request: GradeRequest): Promise<GradeResult>

Grades an API specification from a file path on disk.

Parameters:

Name Type Required Description
request.specPath string Yes Path to the spec file (YAML or JSON)
request.rulesetPath string No Path to a custom Spectral-compatible ruleset file. When omitted, the built-in default ruleset for the detected format is used.

Returns: Promise<GradeResult>

Example:

const result = await engine.grade({ specPath: './openapi.yaml' });
console.log(result.letterGrade); // "C"

engine.gradeContent(request: GradeContentRequest): Promise<GradeResult>

Grades an API specification provided as a string. The format is auto-detected from the content.

Parameters:

Name Type Required Description
request.content string Yes The full spec content (YAML or JSON string)
request.rulesetPath string No Path to a custom Spectral-compatible ruleset file
request.rulesetUrl string No URL to a remote Spectral-compatible ruleset
request.rulesetToken string No Bearer token for authenticated access to a remote ruleset URL

Throws: Error if the API format cannot be detected from the content.

Returns: Promise<GradeResult>

Example:

import { readFileSync } from 'fs';
const content = readFileSync('./openapi.yaml', 'utf-8');
const result = await engine.gradeContent({ content });
console.log(result.numericScore); // 74

formatJson(result: GradeResult, top?: number, rulesetAnalysis?: RulesetAnalysis): string

Serialises a GradeResult to a pretty-printed (two-space indented) JSON string suitable for both machine-readable and human-readable output — every JSON document this package emits is pretty-printed, never minified. The output shape matches the --format json CLI output.

Parameters:

Name Type Required Description
result GradeResult Yes The result returned by grade() or gradeContent()
top number No Truncate diagnostics to the first N entries (sets truncated: true if entries were dropped)
rulesetAnalysis RulesetAnalysis No When supplied (see analyseRuleset() below), each diagnostic is decorated in place with riskLevel, confidenceLevel, remediationSafetyLevel, and staleFingerprintWarning — the same remediation-safety signals buildRemediationSafetyOutput() filters on, but applied to every diagnostic, not just one level

Returns: string — a pretty-printed JSON string

Example:

import { GradeEngine, formatJson, analyseRuleset, loadRuleset } from '@dawmatt/api-grade-core';
const engine = new GradeEngine();
const result = await engine.grade({ specPath: './openapi.yaml' });
const rulesetAnalysis = await analyseRuleset(await loadRuleset(result.format, result.rulesetPath));
console.log(formatJson(result, undefined, rulesetAnalysis)); // diagnostics include safety info

formatHuman(result: GradeResult, top?: number, rulesetAnalysis?: RulesetAnalysis): string

Serialises a GradeResult to a human-readable text string. The output matches the default CLI output. When rulesetAnalysis is supplied, a safety=... risk=... confidence=... line is printed under each diagnostic, same as formatJson's decoration.

Parameters:

Name Type Required Description
result GradeResult Yes The result returned by grade() or gradeContent()
top number No Show only the first N diagnostics
rulesetAnalysis RulesetAnalysis No When supplied, annotates each printed diagnostic with its remediation-safety signals

Returns: string — a formatted human-readable report


JSON Output Schema

Canonical reference: this is the single, stable definition of the JSON field names and shapes shared across @dawmatt/api-grade (CLI), @dawmatt/api-grade-mcp, and the Backstage plugins. Every package that emits these concepts in JSON uses these exact field names — see CLI Commands and MCP Server Tool Reference for where each shape is used.

buildCommonGradeOutput(result: GradeResult, options?: { top?: number; rulesetAnalysis?: RulesetAnalysis }): CommonGradeOutput

Shapes a GradeResult for "grade a spec, give me everything" output. Used by the CLI's --format json, MCP's grade-api, and MCP's grade-api-detailed.

interface CommonGradeOutput {
  specPath: string;
  format: ApiFormat;
  letterGrade: LetterGrade;
  gradeLabel: GradeLabel;
  numericScore: number;
  summary: DiagnosticSummary;
  diagnostics: Diagnostic[] | DiagnosticWithSafety[];
  truncated?: boolean;            // present only when `options.top` actually dropped entries
  rulesetSource: 'default' | 'custom';
  rulesetPath?: string;           // present only when a custom ruleset was used
}

interface DiagnosticWithSafety extends Diagnostic {
  riskLevel: RiskLevel | null;
  confidenceLevel: ConfidenceLevel;
  remediationSafetyLevel: RemediationSafetyLevel;
  staleFingerprintWarning: StaleFingerprintWarning | null;
}

diagnostics is DiagnosticWithSafety[] whenever options.rulesetAnalysis is supplied — each entry is the original Diagnostic plus the four remediation-safety fields, looked up via getRemediationSafety() (below) — and plain Diagnostic[] otherwise. Callers that always want safety info on regular grade output (not just the --remediation-safety-filtered view) should always pass rulesetAnalysis; the CLI's --format json/--format human paths do this unconditionally.

Tool-specific data (e.g. MCP's largeSpecWarning, recoveryOptions) is layered additively on top of this shape by the consuming package — it is never renamed or restructured.

buildAssertOutput(result: GradeResult, minimumGrade: LetterGrade): AssertOutput

Shapes a "did this spec meet a minimum grade" pass/fail result. Used by MCP's assert-api-grade and by the CLI's --min-grade gate in --format json mode.

interface AssertOutput {
  passed: boolean;        // true if `actual` is at or above `minimum`
  actual: LetterGrade;
  minimum: LetterGrade;
  specPath: string;
  numericScore: number;
}

analyseRuleset(loadedRuleset: LoadedRuleset, options?: { auth?: AuthConfig | null }): Promise<RulesetAnalysis>

Computes a per-rule remediation-safety analysis for a loaded ruleset — risk level, confidence level, and the derived remediation safety level for every rule, with provenance (assessedBy, source) and a rationale. Checks persisted/bundled stores (workspace override → global override → colocated shared analysis → bundled default for the built-in ruleset) before falling through to the automated heuristic. See the Automated Remediation Safety Algorithm Specification for the full algorithm.

interface RulesetAnalysis {
  rulesetSource: 'default' | 'custom';
  rulesetPath?: string;
  rules: RuleAnalysis[];
}

interface RuleAnalysis {
  ruleId: string;
  riskLevel: RiskLevel | null;                 // "low" | "medium" | "high"
  confidenceLevel: ConfidenceLevel;             // "high" | "medium" | "low"
  remediationSafetyLevel: RemediationSafetyLevel; // "safe" | "humanreview" | "unsafe"
  assessedBy: AssessmentOrigin;                 // "human" | "automated"
  staleFingerprintWarning: StaleFingerprintWarning | null;
  rationale: string;
  source: AnalysisSource;                       // "persisted" | "bundled-default" | "heuristic" | "fallback"
}

getRemediationSafety(diagnostic: Diagnostic, rulesetAnalysis: RulesetAnalysis)

Looks up a single violation's remediation safety against a previously computed RulesetAnalysis, by ruleId. Defaults to { riskLevel: "high", confidenceLevel: "low", remediationSafetyLevel: "unsafe", staleFingerprintWarning: null } when the rule isn't covered by the analysis.

buildRemediationSafetyOutput(result: GradeResult, specContent: string, rulesetAnalysis: RulesetAnalysis, requestedLevel: RemediationSafetyLevel): RemediationSafetyOutput

Shapes the diagnostics matching one remediation-safety level. Used by MCP's grade-api-remediation-safety and the CLI's --remediation-safety <level> --format json.

interface RemediationSafetyOutput {
  specPath: string;
  format: ApiFormat;
  totalViolations: number;
  remediationItemCount: number;
  remediationItems: RemediationItem[];
  requestedLevel: RemediationSafetyLevel;
}

interface RemediationItem {
  ruleId: string;
  message: string;
  severity: DiagnosticSeverity;  // "error" | "warn" | "info" | "hint" — the diagnostic's actual severity
  path: string[];
  location: string;              // dot-joined `path`
  range: Diagnostic['range'];    // line/character location, carried over from the source diagnostic
  currentValue: string | null;
  expectedImprovement: string;
  riskLevel: RiskLevel | null;
  confidenceLevel: ConfidenceLevel;
  remediationSafetyLevel: RemediationSafetyLevel;
  staleFingerprintWarning: StaleFingerprintWarning | null;
}

severity and range are carried over unchanged from the underlying Diagnostic — a RemediationItem is never missing the line-number/severity context a regular diagnostic has, even though it's filtered down to one remediation-safety level and reshaped with remediation-specific fields (location, currentValue, expectedImprovement).

The JSON returned by buildRemediationSafetyOutput() is pretty-printed by every caller (JSON.stringify(output, null, 2)), matching formatJson()'s output style — it is not minified.

formatRemediationSafetyHuman(result: GradeResult, specContent: string, rulesetAnalysis: RulesetAnalysis, requestedLevel: RemediationSafetyLevel): string

Renders the same filtered RemediationItem[] list used by buildRemediationSafetyOutput() as human-readable text, including each item's line number (Line N) when range is present. Used by the CLI's --remediation-safety <level> with --format human (the default).

persistRuleAnalysisCorrection(loadedRuleset, ruleId, remediationSafetyLevel, scope?)

Persists a human-confirmed remediation-safety correction for one rule, written to the colocated shared analysis file (default, for a writable local ruleset) or a personal override (workspace/global scope, or as a fallback for a non-writable remote/built-in ruleset location). Reloaded automatically by analyseRuleset() on future runs against the same ruleset.


Types

GradeRequest

Input to engine.grade().

interface GradeRequest {
  specPath: string;       // path to spec file
  rulesetPath?: string;   // optional custom ruleset path
}

GradeContentRequest

Input to engine.gradeContent().

interface GradeContentRequest {
  content: string;         // spec content as a string
  rulesetPath?: string;    // optional custom ruleset file path
  rulesetUrl?: string;     // optional remote ruleset URL
  rulesetToken?: string;   // optional bearer token for remote ruleset
}

GradeResult

The result returned by both grade() and gradeContent().

interface GradeResult {
  specPath: string;                      // path used (or "inline" for gradeContent)
  format: ApiFormat;                     // detected format: "openapi-2" | "openapi-3" | "asyncapi-2" | "asyncapi-3"
  letterGrade: LetterGrade;              // "A" | "B" | "C" | "D" | "F"
  gradeLabel: GradeLabel;               // "Excellent" | "Good" | "OK" | "Below Standard" | "Poor"
  numericScore: number;                  // 0–100
  summary: DiagnosticSummary;           // diagnostic summary (see below)
  diagnostics: Diagnostic[];            // full list of individual findings
  rulesetSource: 'default' | 'custom'; // whether the built-in or a custom ruleset was used
  rulesetPath?: string;                  // path to custom ruleset, if provided
}

DiagnosticSummary

The computed summary attached to every GradeResult as result.summary. See the API Diagnostic Algorithm Specification for the full scoring, tone, and recommendation-generation logic behind these fields.

interface DiagnosticSummary {
  tone: string;                    // e.g. "OK effort", "Excellent work", "Critical condition"
  severityLevel: string;           // overall severity: "NONE" | "INFO" | "WARNING" | "CRITICAL" | "ERROR"
  errorCount: number;              // number of error-severity findings
  warnCount: number;               // number of warning-severity findings
  infoCount: number;               // number of info-severity findings
  hintCount: number;               // number of hint-severity findings
  commentary: string;              // the full quality assessment paragraph
  text: string;                    // alias for commentary (backward compatibility)
  focusRules: RuleMetadata[];     // top rules to fix first, ordered by impact
  recommendations: string[];      // actionable recommendation strings
}

Diagnostic

A single finding from the linter.

interface Diagnostic {
  ruleId: string;                   // e.g. "oas3-schema"
  message: string;                  // human-readable description of the issue
  severity: DiagnosticSeverity;    // "error" | "warn" | "info" | "hint"
  path: string[];                   // JSON path to the offending element
  range?: {
    start: { line: number; character: number };
    end:   { line: number; character: number };
  };
}

See DiagnosticWithSafety (under buildCommonGradeOutput above) for the shape a Diagnostic takes on once decorated with remediation-safety fields, and RemediationItem (under buildRemediationSafetyOutput above) for the shape it takes on once filtered to one remediation-safety level — both preserve severity and range unchanged from this base type.


RuleMetadata

A focus rule entry in DiagnosticSummary.focusRules.

interface RuleMetadata {
  id: string;          // rule ID, e.g. "oas3-schema"
  title: string;       // human-readable title
  category: string;    // rule category, e.g. "oas3", "operation", "info"
  count: number;       // number of violations
  impact: ImpactLevel; // "HIGH" | "MEDIUM" | "LOW"
  url: string | null;  // documentation URL, if available
}

Further Reading