---
title: Core Library API
description: Complete API reference for the @specdiff/core package — diffing functions, rule helpers, formatters, pointer utilities, ref resolution, types, and constants.
url: https://pr-1-ff84656b4b8a.thally.app/specdiff/core-api
---

# Core Library API

Complete API reference for the @specdiff/core package — diffing functions, rule helpers, formatters, pointer utilities, ref resolution, types, and constants.

`@specdiff/core` (version 0.1.0) is the core library for Specdiff. It has zero runtime dependencies and is ESM only, requiring Node.js 22 or later.

```sh
npm install @specdiff/core
```

## Quick example

```ts
import { readFileSync } from "node:fs";
import { diffDocuments, exceedsThreshold, formatMarkdown } from "@specdiff/core";

const before = JSON.parse(readFileSync("examples/user-v1.json", "utf8"));
const after = JSON.parse(readFileSync("examples/user-v2.json", "utf8"));

const result = diffDocuments(before, after, {
  ignoreRules: ["description-changed"],
  overrides: { "default-changed": "breaking" },
});

console.log(formatMarkdown(result));
console.log(exceedsThreshold(result, "warning")); // true
```

---

## Diffing functions

### `diffJsonSchema`

```ts
function diffJsonSchema(
  before: unknown,
  after: unknown,
  options?: DiffOptions,
): DiffResult;
```

Compares two JSON Schema documents and returns a `DiffResult`. The `options.direction` parameter defaults to `"neutral"`.

### `diffOpenApi`

```ts
function diffOpenApi(
  before: unknown,
  after: unknown,
  options?: DiffOptions,
): DiffResult;
```

Compares two OpenAPI 3.x documents. Direction is derived automatically from use position (request body schemas are diffed as `"request"`, response schemas as `"response"`). The `options.direction` field is ignored for OpenAPI diffs.

### `diffDocuments`

```ts
function diffDocuments(
  before: unknown,
  after: unknown,
  options?: DiffOptions,
): DiffResult;
```

Auto-detects whether the documents are OpenAPI or JSON Schema — if either document is an object with a string `openapi` key, it delegates to `diffOpenApi`; otherwise it delegates to `diffJsonSchema`.

### `detectDocumentKind`

```ts
function detectDocumentKind(document: unknown): DocumentKind;
```

Returns `"openapi"` if the document is an object with a string `openapi` key. Returns `"json-schema"` otherwise.

### `exceedsThreshold`

```ts
function exceedsThreshold(result: DiffResult, threshold: FailThreshold): boolean;
```

Returns `true` when `result.maxSeverity` is at or above the given `threshold`. A threshold of `"none"` always returns `false`.

### `finalize`

```ts
function finalize(
  rawChanges: readonly SchemaChange[],
  kind: DocumentKind,
  options?: DiffOptions,
): DiffResult;
```

Applies option filters (ignore rules, ignore paths, severity overrides), sorts the resulting changes, and wraps them into a `DiffResult`.

### `summarize`

```ts
function summarize(changes: readonly SchemaChange[]): DiffSummary;
```

Computes per-severity counts from an array of changes, returning a `DiffSummary`.

### `compareChanges`

```ts
function compareChanges(a: SchemaChange, b: SchemaChange): number;
```

Sort comparator for changes. Orders by severity (breaking first, then warning, then info), then by path, then by code, then by message. Uses code-point comparison, not locale-aware collation.

---

## Rule functions

### `explainRule`

```ts
function explainRule(code: string): RuleInfo | undefined;
```

Looks up a rule by its code string. Returns a `RuleInfo` object for known codes, or `undefined` for unknown codes.

### `listRules`

```ts
function listRules(): RuleInfo[];
```

Returns the entire rule catalogue as an array in catalogue order.

### `isRuleCode`

```ts
function isRuleCode(value: string): value is RuleCode;
```

Type guard that returns `true` when `value` is one of the 45 known rule code strings.

### `severityFor`

```ts
function severityFor(code: RuleCode, direction: Direction): Severity;
```

Returns the effective severity for a rule in a given direction. For the 12 rules with direction-dependent severity, it returns the direction-specific value. For all other rules, it falls back to the rule's `defaultSeverity`.

---

## Formatters

### `formatText`

```ts
function formatText(result: DiffResult, options?: FormatTextOptions): string;
```

Produces a human-readable plain-text report grouped by severity. The header line reads `Specdiff (OpenAPI)` or `Specdiff (JSON Schema)` followed by the summary line. Color is off by default. The output ends with one newline.

### `formatMarkdown`

```ts
function formatMarkdown(result: DiffResult): string;
```

Produces a GitHub-flavoured Markdown report. Opens with `## Specdiff report (OpenAPI)` or `## Specdiff report (JSON Schema)`, followed by a summary table, then per-severity tables. Ends with one newline.

### `formatJson`

```ts
function formatJson(result: DiffResult): string;
```

Returns `JSON.stringify(result, null, 2)` plus a trailing newline.

### `summaryLine`

```ts
function summaryLine(result: DiffResult): string;
```

Returns a one-line summary such as `"29 changes: 13 breaking, 7 warning, 9 info"` or `"No changes detected."`.

### `formatRulesMarkdown`

```ts
function formatRulesMarkdown(): string;
```

Returns the full rule catalogue formatted as a Markdown table with columns: Code, Default severity, Applies to, Description.

---

## Pointer helpers

Utilities for working with RFC 6901 JSON Pointers.

### `escapePointerSegment`

```ts
function escapePointerSegment(segment: string | number): string;
```

Escapes a single pointer segment per RFC 6901: `~` becomes `~0` and `/` becomes `~1`.

### `unescapePointerSegment`

```ts
function unescapePointerSegment(segment: string): string;
```

Inverse of `escapePointerSegment`. Decodes `~1` before `~0`, as required by RFC 6901.

### `joinPointer`

```ts
function joinPointer(base: string, ...segments: Array<string | number>): string;
```

Appends escaped segments to a base pointer. For example, `joinPointer("#/paths", "/pets")` returns `"#/paths/~1pets"`.

### `parsePointer`

```ts
function parsePointer(pointer: string): string[];
```

Splits a pointer into unescaped segments. For example, `"#/paths/~1pets"` becomes `["paths", "/pets"]`. Throws an `Error` for pointers that do not start with `/` or `#/`.

### `normalizePointer`

```ts
function normalizePointer(pointer: string): string;
```

Normalizes a pointer to the `#/...` form. Inputs like `"paths/x"`, `"/paths/x"`, and `"#/paths/x"` all produce `"#/paths/x"`. Trailing slashes are stripped.

### `pointerHasPrefix`

```ts
function pointerHasPrefix(pointer: string, prefix: string): boolean;
```

Segment-aware prefix test after normalization. Using `"#"` as the prefix matches everything.

### `resolvePointer`

```ts
function resolvePointer(document: unknown, pointer: string): unknown;
```

Walks a document tree following the pointer segments. Returns `undefined` when any segment is missing. Handles arrays by numeric index.

---

## Ref resolution

### `isLocalRef`

```ts
function isLocalRef(ref: string): boolean;
```

Returns `true` for references starting with `#/` or exactly equal to `#`.

### `resolveNode`

```ts
function resolveNode(
  document: unknown,
  node: unknown,
  maxDepth?: number,
): Resolved;
```

Follows a chain of local `$ref` references within a document. The `maxDepth` parameter defaults to 32 and limits the number of `$ref` hops to prevent infinite loops. Returns a `Resolved` object containing the resolved schema, the final ref path, and any unresolved ref if resolution fails.

---

## Types

### `Severity`

```ts
type Severity = "breaking" | "warning" | "info";
```

The three severity levels for schema changes.

### `Direction`

```ts
type Direction = "request" | "response" | "neutral";
```

Indicates the context in which a schema is used. Some rules change severity depending on direction.

### `DocumentKind`

```ts
type DocumentKind = "openapi" | "json-schema";
```

### `FailThreshold`

```ts
type FailThreshold = Severity | "none";
```

Used by `exceedsThreshold` to determine whether a diff result should cause a failure. `"none"` means never fail.

### `RuleCode`

```ts
type RuleCode = keyof typeof RULES;
```

A union of all 45 rule code string literals.

### `RuleInfo`

```ts
type RuleInfo = {
  code: RuleCode;
  defaultSeverity: Severity;
  title: string;
  description: string;
  remediation: string;
  appliesTo: DocumentKind | "both";
};
```

Metadata about a single rule, returned by `explainRule` and `listRules`.

### `SchemaChange`

```ts
type SchemaChange = {
  code: RuleCode;
  severity: Severity;
  path: string;
  message: string;
  before?: unknown;
  after?: unknown;
};
```

A single detected change. The `path` is a JSON Pointer to the location in the document. The optional `before` and `after` fields carry the old and new values when available.

### `DiffSummary`

```ts
type DiffSummary = {
  breaking: number;
  warning: number;
  info: number;
  total: number;
};
```

Per-severity counts of changes.

### `DiffResult`

```ts
type DiffResult = {
  changes: SchemaChange[];
  summary: DiffSummary;
  maxSeverity: Severity | null;
  kind: DocumentKind;
};
```

The complete result of a diff operation. `maxSeverity` is `null` when no changes are detected.

### `DiffOptions`

```ts
type DiffOptions = {
  ignoreRules?: RuleCode[];
  overrides?: Partial<Record<RuleCode, Severity>>;
  ignorePaths?: string[];
  direction?: Direction;
};
```

Options accepted by the diffing functions.

- `ignoreRules` -- rule codes whose changes should be dropped from the result.
- `overrides` -- maps rule codes to a custom severity, replacing the default.
- `ignorePaths` -- JSON Pointer prefixes; changes under any matching path are dropped.
- `direction` -- sets the direction for JSON Schema diffs (defaults to `"neutral"`). Ignored by `diffOpenApi`, which derives direction from context.

### `FormatTextOptions`

```ts
type FormatTextOptions = {
  color?: boolean;
};
```

Options for `formatText`. Color is off by default.

### `Resolved`

```ts
type Resolved = {
  schema: unknown;
  ref: string | undefined;
  unresolved: string | undefined;
};
```

Returned by `resolveNode`. The `schema` field holds the resolved value. The `ref` field is the final `$ref` path that was followed. The `unresolved` field is set when a `$ref` could not be resolved (remote or missing reference).

---

## Constants

### `SEVERITY_ORDER`

```ts
const SEVERITY_ORDER: { breaking: 0; warning: 1; info: 2 };
```

Maps each severity to its sort rank. Lower numbers indicate higher severity.

### `SEVERITIES`

```ts
const SEVERITIES: readonly Severity[]; // ["breaking", "warning", "info"]
```

All severity levels in order from most to least severe.

### `RULES`

```ts
const RULES: Record<RuleCode, RuleDefinition & { code: RuleCode }>;
```

Object with 45 entries keyed by rule code. Each entry contains the full rule definition including code, default severity, title, description, remediation text, and the document kind it applies to. See the [Rule Catalogue](/specdiff/rules) for the complete list.

### `DIRECTION_SEVERITY`

```ts
const DIRECTION_SEVERITY: Partial<Record<RuleCode, Record<Direction, Severity>>>;
```

Contains entries for the 12 rules whose severity changes depending on direction. Rules not present in this object keep their `defaultSeverity` regardless of direction. See the [direction severity table](/specdiff/rules#direction-dependent-severity) for details.