Strict graph mode
json-tology offers three escalating levels of inline-shape detection at the registry boundary: silent reporting, warn-on-register, and throw-on-register. All three operate on the canonical graph and rely on the same structural-equality test that drives findDuplicates.
The lowest level is the on-demand audit. The middle level emits warnings as schemas are registered. The strict level promotes those warnings to SchemaError throws and forbids inline constrained shapes outright.
enableInlineWarnings: true - gentle nudges
Emits logger.warn at registration when inline-object or inline-primitive shapes are found. No throws. Requires a logger to be set.
const jt = JsonTology.create({
baseIRI: 'https://example.com',
enableInlineWarnings: true,
logger: myLogger
});Use when you want passive feedback during development without breaking the build.
enableDuplicateDetection: true - auto-run at registration
Runs findDuplicates() after each schema is registered and emits logger.warn if duplicates are found.
const jt = JsonTology.create({
baseIRI: 'https://example.com',
enableDuplicateDetection: true,
logger: myLogger
});Use when you have already extracted some named schemas and want continuous detection of regressions without a manual audit step.
enableStrictGraph: true - CI enforcement
Promotes warnings to SchemaError throws. Every sub-schema must be either:
- A
{ $ref: registeredSchemaId }reference - A bare base type with no constraint keywords:
{ type: 'string' },{ type: 'integer' },{ type: 'boolean' },{ type: 'array', items: <allowed> } - Declared in the schema's own
$defsnamespace (the schema's internal ontology)
Inline constrained shapes - objects with properties, primitives with pattern/format/minimum/etc., array items with constraints - are all forbidden.
const jt = JsonTology.create({
baseIRI: 'https://example.com',
enableStrictGraph: true,
schemas: [...] as const // all inline shapes throw SchemaError here
});What's allowed inline in strict mode:
{ type: 'string' }- no constraints{ type: 'integer' }- no constraints{ type: 'boolean' }- no constraints{ type: 'array', items: { $ref: '...' } }- array of named schemas{ type: 'array', items: { type: 'string' } }- array of base types$defsentries - the schema's own internal named types
Migration path
- Run
registry.findDuplicates()on your existing schema set. - For each duplicate, extract the shape to a named schema file.
- Replace inline occurrences with
{ $ref: newSchema.$id }. - Enable
enableInlineWarnings: truefirst (warn-only) to find stragglers. - Once warnings are clean, upgrade to
enableStrictGraph: true.
CI script example
// scripts/check-graph.ts
import { JsonTology } from 'json-tology';
import { schemas } from '../src/schemas.js';
const jt = JsonTology.create({ baseIRI: 'https://example.com', schemas });
const dups = jt.registry.findDuplicates();
if (dups.length > 0) {
console.error('Duplicate inline shapes found:');
for (const dup of dups) {
console.error(` ${dup.schemaId}#${dup.pointer} duplicates ${dup.equivalentTo}`);
}
process.exit(1);
}When inline is OK
Not every project needs strict graph mode. Inline shapes are fine when:
- The schema has a single consumer and will never be reused.
- It's a throwaway script or one-off data validation utility.
- You're prototyping and the ontology contract isn't relevant yet.
The cost of inline shapes is borne only by graph users: OWL/SHACL output is less precise, findDuplicates() reports noise, and global type changes require manual find-and-replace. If you're not using the ontology output, inline shapes have no runtime cost.
Related
findDuplicates- on-demand audit- Graph-native authoring - the drift problem these modes address
- Ontology and Graphs - what graph users get from clean named schemas