npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

json-schema-cycles

v3.0.0

Published

Analyize recursive (cyclic) JSON Schema types

Downloads

74,714

Readme

npm version downloads build status coverage status Node.JS version

json-schema-cycles

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.

There are two types of analysis functions, analyzeTypes and analyzeTypesFast. The former provides a more in-depth analysis but can be slow on large input. If the input is extremely complex with massive cyclicity, it might even crash the process or run out of memory.

Unless an in-depth analysis is necessary, choose the analyzeTypesFast function.

Versions

  • Since v2 this is a pure ESM package, and requires Node.js >=12.20. It cannot be used from CommonJS.

Example

analyzeTypes takes a JSON schema object and returns a result object on the same format as FullAnalysisResult 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.

analyzeTypesFast also takes a JSON schema object, but returns an object on the same format as FastAnalysisResult in graph-cycles, with the same additional graph property as from analyzeTypes.

import { analyzeTypes, analyzeTypesFast } from 'json-schema-cycles'

const { cycles, entrypoints, dependencies, dependents, all, graph } = analyzeTypes( schemaObject );
// or
const { cyclic, dependencies, dependents, graph } = analyzeTypesFast( schemaObject );

Check graph-cycles for an understanding of the result object, apart from graph.

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' },
        },
    }
};

... which can be viewed as:

Cart -> Product
                 __       ___
                |  |     |   |
                v  |     v   |
Action -> DM -> User -> Message -> Link
                  ^        |
                  |        v
                  `--- Subscriber

for a full analysis, the result will be (of the type TypeAnalysisFullResult):

{
    entrypoints: [
        [ 'DM' ],
        [ 'Actions', 'DM' ],
    ],
    cycles: [
        [ 'User' ],
        [ 'Message' ],
        [ 'User', 'Message', 'Subscriber' ],
    ],
    all: [ 'User', 'Message', 'DM', 'Actions', 'Subscriber' ],
    dependencies: [ 'Link' ],
    dependents: [ ],
    graph: [
        [ 'Link', [ ] ],
        [ 'Subscriber', [ 'User' ] ],
        [ 'Message', [ 'Message', 'Link', 'Subscriber' ] ],
        [ 'User', [ 'Message', 'User' ] ],
        [ 'DM', [ 'User' ] ],
        [ 'Actions', [ 'DM' ] ],
        [ 'Product', [ ] ],
        [ 'Cart', [ 'Product' ] ],
    ],
}

for a fast analysis, the result will be (of the type TypeAnalysisFastResult):

{
    cyclic: [ 'User', 'Message', 'DM', 'Actions', 'Subscriber' ],
    dependencies: [ 'Link' ],
    dependents: [ ],
    graph: [
        [ 'Link', [ ] ],
        [ 'Subscriber', [ 'User' ] ],
        [ 'Message', [ 'Message', 'Link', 'Subscriber' ] ],
        [ 'User', [ 'Message', 'User' ] ],
        [ 'DM', [ 'User' ] ],
        [ 'Actions', [ 'DM' ] ],
        [ 'Product', [ ] ],
        [ 'Cart', [ 'Product' ] ],
    ],
}

Helpers

Two helper functions are exported; sortTypeAnalysisFullResult and sortTypeAnalysisFastResult. They take an analysis result (of type TypeAnalysisFullResult or TypeAnalysisFastResult) and return a new object of the same type, with all fields sorted in a deterministic way, which is useful in tests.