Detect cyclic dependencies in a JSON schema (or more precisely a JSON schema with the definitions
property for the individual type definitions). This package doesn't handle external references, you need to use a ref-parser and squash all types into one schema before using this package.
json-schema-cycles
exports a function analyzeTypes
which takes a JSON schema object and returns a result object on the same format as AnalysisResult
in graph-cycles but with an additional graph
property containing the type dependency graph as an array of [ from: string, to: Array< string > ]
where from
is the type and to
is the dependent types.
import { analyzeTypes } from 'json-schema-cycles'
const { cycles, entrypoints, dependencies, all, graph } = analyzeTypes( schemaObject );
Check graph-cycles for an understanding of the result object, apart from graph
.
Given the following JSON Schema:
const jsonSchema = {
definitions: {
Link: {}, // Non-cyclic but dependency of Message
Subscriber: {
type: 'object',
properties: {
user: { $ref: '#/definitions/User' },
},
},
Message: {
type: 'object',
properties: {
replyTo: { $ref: '#/definitions/Message' },
link: { $ref: '#/definitions/Link' },
subscriber: { $ref: '#/definitions/Subscriber' },
},
},
User: {
type: 'object',
properties: {
parent: { $ref: '#/definitions/User' },
lastMessage: { $ref: '#/definitions/Message' },
},
},
DM: {
type: 'object',
properties: {
lastUser: { $ref: '#/definitions/User' },
},
},
Actions: {
type: 'object',
properties: {
dms: {
type: 'array',
items: { $ref: '#/definitions/DM' },
},
},
},
// Has dependencies, but nothing cyclic
Product: {},
Cart: {
type: 'array',
items: { $ref: '#/definitions/Product' },
},
}
};
the analysis will be:
{
entrypoints: [
[ "DM" ],
[ "Actions", "DM" ],
],
cycles: [
[ 'User' ],
[ 'Message' ],
[ 'User', 'Message', 'Subscriber' ],
],
all: [ 'User', 'Message', 'DM', 'Actions', 'Subscriber' ],
dependencies: [ "Link" ],
graph: [
[ 'Link', [ ] ],
[ 'Subscriber', [ 'User' ] ],
[ 'Message', [ 'Message', 'Link', 'Subscriber' ] ],
[ 'User', [ 'Message', 'User' ] ],
[ 'DM', [ 'User' ] ],
[ 'Actions', [ 'DM' ] ],
[ 'Product', [ ] ],
[ 'Cart', [ 'Product' ] ],
],
}
Another function sortTypeAnalysisResult
is exported, which takes an analysis result (of type TypeAnalysisResult
) and returns new object of the same type, with all fields sorted in a deterministic way, which is useful in tests.