SchemaRegistry.findDuplicates
Declaration
ts
registry.findDuplicates(): ReadonlyArray<{
schemaId: string;
pointer: string;
equivalentTo: string;
shape: Record<string, unknown>;
}>Returns a report of inline shapes that structurally match a registered top-level schema. Pure - does not mutate the registry. Run on demand at any point after registration.
Use this when
You want to audit an existing schema set for inline shapes that duplicate a named schema. The output drives an extract-and-$ref-replace refactor: each entry tells you exactly which schema, which JSON pointer, and which named schema the inline shape would be equivalent to.
/**
* findDuplicates — Example 1: One-shot audit of the bookstore registry
* Demonstrates: findDuplicates() returns an array, each entry has schemaId/pointer/equivalentTo
*
* The canonical bookstore registry is structured to avoid inline shapes that
* duplicate named schemas — all primitives are extracted and $ref'd. Running
* findDuplicates() confirms the registry is clean. The result type is shown
* via console.assert on the array.
*/
import { bookstoreEntities } from '../bookstore/index.js';
const dups = bookstoreEntities.registry.findDuplicates();
// The bookstore registry uses named $ref schemas throughout — no inline duplicates.
for (const dup of dups) {
console.log(`${dup.schemaId}#${dup.pointer} duplicates ${dup.equivalentTo}`);
}
console.assert(Array.isArray(dups));
// A well-structured registry with all shapes extracted should have zero duplicates.
console.assert(dups.length === 0);
console.log('duplicate count:', dups.length);
console.log('registry is clean:', dups.length === 0);
Output
Press Execute to run this example against the real library.Don't use this when
You want continuous enforcement at registration time - prefer enableDuplicateDetection (warn) or enableStrictGraph (throw) instead. Don't use it as a validator for instance data; it inspects schema structure, not values.
Examples
Example 1: One-shot audit
/**
* findDuplicates — Example 1: One-shot audit of the bookstore registry
* Demonstrates: findDuplicates() returns an array, each entry has schemaId/pointer/equivalentTo
*
* The canonical bookstore registry is structured to avoid inline shapes that
* duplicate named schemas — all primitives are extracted and $ref'd. Running
* findDuplicates() confirms the registry is clean. The result type is shown
* via console.assert on the array.
*/
import { bookstoreEntities } from '../bookstore/index.js';
const dups = bookstoreEntities.registry.findDuplicates();
// The bookstore registry uses named $ref schemas throughout — no inline duplicates.
for (const dup of dups) {
console.log(`${dup.schemaId}#${dup.pointer} duplicates ${dup.equivalentTo}`);
}
console.assert(Array.isArray(dups));
// A well-structured registry with all shapes extracted should have zero duplicates.
console.assert(dups.length === 0);
console.log('duplicate count:', dups.length);
console.log('registry is clean:', dups.length === 0);
Output
Press Execute to run this example against the real library.Example 2: CI gate
/**
* findDuplicates — Example 2: CI gate — exit non-zero when duplicates found
* Demonstrates: using findDuplicates() as a quality gate in a build script
*
* In a real CI pipeline a non-empty result would log each duplicate and
* call `process.exit(1)`. This file mirrors that shape without actually
* exiting so the docs smoke suite can import it.
*/
import { bookstoreEntities } from '../bookstore/index.js';
const dups = bookstoreEntities.registry.findDuplicates();
const lines: string[] = [];
for (const dup of dups) {
lines.push(` ${dup.schemaId}#${dup.pointer} duplicates ${dup.equivalentTo}`);
}
// In a CI script: `if (dups.length > 0) process.exit(1)`. The example
// captures the boolean instead so importing the file is safe.
const shouldFail = dups.length > 0;
console.assert(typeof shouldFail === 'boolean', 'CI gate result is a boolean');
console.assert(Array.isArray(lines), 'lines is the array a CI script would print');
console.log('duplicates found:', dups.length);
console.log('CI gate would fail:', shouldFail);
if (lines.length > 0) {
for (const line of lines) {
console.log(line);
}
} else {
console.log('no duplicates - registry is clean');
}
Output
Press Execute to run this example against the real library.Comparison
ts
const dups = jt.registry.findDuplicates();
// Returns [{ schemaId, pointer, equivalentTo, shape }] — structural, JSON Pointer-addressed.
// Pure — no mutation. Run at any point after registration.ts
// Zod has no built-in duplicate-detection. All schemas are independent runtime
// objects; structural equivalence is not tracked. You would need to implement
// a manual deep-equal check across all schema definitions.
// Limitation: no registry; no JSON Pointer addresses; no concept of inline vs. named.ts
// Valibot has no duplicate-detection. Schemas are plain objects; no registry
// maintains structural identity. Manual comparison requires traversing the
// schema tree yourself.
// Limitation: no first-class registry; no inline-vs-named concept.ts
// AJV does not track structural equivalence across registered schemas.
// You can inspect ajv.schemas (internal map), but there is no API to detect
// inline shapes that duplicate a named schema.
// Limitation: no findDuplicates equivalent; structural comparison must be
// hand-rolled against the raw schema objects.ts
// TypeBox schemas are plain JSON Schema objects. TypeBox has no registry
// and no duplicate-detection API. A CI lint script must compare schema
// definitions manually via deep-equal.
// Limitation: no registry; no pointer-addressed duplicate report.ts
// json-schema-to-typescript generates TypeScript types but does not detect
// duplicate inline shapes. Structural drift between inline definitions and
// named schemas is invisible until generated types diverge.
// Limitation: no runtime registry; no findDuplicates API.py
# Limitation: feature not directly supported in Pydantic. See /comparisons for the matrix.ts
// Limitation: feature not directly supported in Yup. See /comparisons for the matrix.ts
// Limitation: feature not directly supported in Joi. See /comparisons for the matrix.ts
// Limitation: feature not directly supported in io-ts. See /comparisons for the matrix.ts
// Limitation: feature not directly supported in Effect Schema. See /comparisons for the matrix.ts
// Limitation: feature not directly supported in ArkType. See /comparisons for the matrix.ts
// Limitation: feature not directly supported in Runtypes. See /comparisons for the matrix.Related
enableInlineWarnings- warn-on-register for inline shapesenableDuplicateDetection- run findDuplicates after each registrationenableStrictGraph- throw on inline constrained shapes- Graph-native authoring - the underlying drift problem
See also
- Bookstore domain - schema definitions used in examples
- Schemas guide - schema registration and management