{"id":15491800,"url":"https://github.com/grantila/json-schema-cycles","last_synced_at":"2025-04-22T19:22:46.492Z","repository":{"id":57154529,"uuid":"353850296","full_name":"grantila/json-schema-cycles","owner":"grantila","description":"Analyize recursive (cyclic) JSON Schema types","archived":false,"fork":false,"pushed_at":"2023-02-02T22:07:34.000Z","size":1265,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-07T22:37:21.322Z","etag":null,"topics":["cycles","cyclic","json","jsonschema","rescursive","schema","types"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/grantila.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-04-01T23:20:01.000Z","updated_at":"2023-06-28T03:30:01.000Z","dependencies_parsed_at":"2023-02-18T00:55:19.448Z","dependency_job_id":null,"html_url":"https://github.com/grantila/json-schema-cycles","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grantila%2Fjson-schema-cycles","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grantila%2Fjson-schema-cycles/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grantila%2Fjson-schema-cycles/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grantila%2Fjson-schema-cycles/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/grantila","download_url":"https://codeload.github.com/grantila/json-schema-cycles/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249528552,"owners_count":21286390,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cycles","cyclic","json","jsonschema","rescursive","schema","types"],"created_at":"2024-10-02T07:56:29.054Z","updated_at":"2025-04-22T19:22:46.472Z","avatar_url":"https://github.com/grantila.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![npm version][npm-image]][npm-url]\n[![downloads][downloads-image]][npm-url]\n[![build status][build-image]][build-url]\n[![coverage status][coverage-image]][coverage-url]\n[![Node.JS version][node-version]][node-url]\n\n\n# json-schema-cycles\n\nDetect 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.\n\nThere 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.\n\nUnless an in-depth analysis is necessary, choose the `analyzeTypesFast` function.\n\n\n## Versions\n\n * Since v2 this is a [pure ESM][pure-esm] package, and requires Node.js \u003e=12.20. It cannot be used from CommonJS.\n\n\n## Example\n\n`analyzeTypes` takes a JSON schema object and returns a result object on the same format as [`FullAnalysisResult` in graph-cycles](https://github.com/grantila/graph-cycles/#full-analysis-mode) but with an additional `graph` property containing the type dependency graph as an array of `[ from: string, to: Array\u003c string \u003e ]` where `from` is the type and `to` is the dependent types.\n\n`analyzeTypesFast` also takes a JSON schema object, but returns an object on the same format as [`FastAnalysisResult` in graph-cycles](https://github.com/grantila/graph-cycles/#fast-analysis-mode), with the same additional `graph` property as from `analyzeTypes`.\n\n```ts\nimport { analyzeTypes, analyzeTypesFast } from 'json-schema-cycles'\n\nconst { cycles, entrypoints, dependencies, dependents, all, graph } = analyzeTypes( schemaObject );\n// or\nconst { cyclic, dependencies, dependents, graph } = analyzeTypesFast( schemaObject );\n```\n\nCheck [graph-cycles](https://github.com/grantila/graph-cycles) for an understanding of the result object, apart from `graph`.\n\n\u003cdetails style=\"padding-left: 32px; border-left: 4px solid gray;\"\u003e\n\u003csummary\u003eGiven the following JSON Schema:\u003c/summary\u003e\n\u003cp\u003e\n\n```ts\nconst jsonSchema = {\n    definitions: {\n        Link: {}, // Non-cyclic but dependency of Message\n        Subscriber: {\n            type: 'object',\n            properties: {\n                user: { $ref: '#/definitions/User' },\n            },\n        },\n        Message: {\n            type: 'object',\n            properties: {\n                replyTo: { $ref: '#/definitions/Message' },\n                link: { $ref: '#/definitions/Link' },\n                subscriber: { $ref: '#/definitions/Subscriber' },\n            },\n        },\n        User: {\n            type: 'object',\n            properties: {\n                parent: { $ref: '#/definitions/User' },\n                lastMessage: { $ref: '#/definitions/Message' },\n            },\n        },\n        DM: {\n            type: 'object',\n            properties: {\n                lastUser: { $ref: '#/definitions/User' },\n            },\n        },\n        Actions: {\n            type: 'object',\n            properties: {\n                dms: {\n                    type: 'array',\n                    items: { $ref: '#/definitions/DM' },\n                },\n            },\n        },\n        // Has dependencies, but nothing cyclic\n        Product: {},\n        Cart: {\n            type: 'array',\n            items: { $ref: '#/definitions/Product' },\n        },\n    }\n};\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n... which can be viewed as:\n\n```\nCart -\u003e Product\n                 __       ___\n                |  |     |   |\n                v  |     v   |\nAction -\u003e DM -\u003e User -\u003e Message -\u003e Link\n                  ^        |\n                  |        v\n                  `--- Subscriber\n\n```\n\nfor a full analysis, the result will be (of the type `TypeAnalysisFullResult`):\n\n```ts\n{\n    entrypoints: [\n        [ 'DM' ],\n        [ 'Actions', 'DM' ],\n    ],\n    cycles: [\n        [ 'User' ],\n        [ 'Message' ],\n        [ 'User', 'Message', 'Subscriber' ],\n    ],\n    all: [ 'User', 'Message', 'DM', 'Actions', 'Subscriber' ],\n    dependencies: [ 'Link' ],\n    dependents: [ ],\n    graph: [\n        [ 'Link', [ ] ],\n        [ 'Subscriber', [ 'User' ] ],\n        [ 'Message', [ 'Message', 'Link', 'Subscriber' ] ],\n        [ 'User', [ 'Message', 'User' ] ],\n        [ 'DM', [ 'User' ] ],\n        [ 'Actions', [ 'DM' ] ],\n        [ 'Product', [ ] ],\n        [ 'Cart', [ 'Product' ] ],\n    ],\n}\n```\n\nfor a fast analysis, the result will be (of the type `TypeAnalysisFastResult`):\n\n```ts\n{\n    cyclic: [ 'User', 'Message', 'DM', 'Actions', 'Subscriber' ],\n    dependencies: [ 'Link' ],\n    dependents: [ ],\n    graph: [\n        [ 'Link', [ ] ],\n        [ 'Subscriber', [ 'User' ] ],\n        [ 'Message', [ 'Message', 'Link', 'Subscriber' ] ],\n        [ 'User', [ 'Message', 'User' ] ],\n        [ 'DM', [ 'User' ] ],\n        [ 'Actions', [ 'DM' ] ],\n        [ 'Product', [ ] ],\n        [ 'Cart', [ 'Product' ] ],\n    ],\n}\n```\n\n\n## Helpers\n\nTwo 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.\n\n\n\n[npm-image]: https://img.shields.io/npm/v/json-schema-cycles.svg\n[npm-url]: https://npmjs.org/package/json-schema-cycles\n[downloads-image]: https://img.shields.io/npm/dm/json-schema-cycles.svg\n[build-image]: https://img.shields.io/github/actions/workflow/status/grantila/json-schema-cycles/master.yml?branch=master\n[build-url]: https://github.com/grantila/json-schema-cycles/actions?query=workflow%3AMaster\n[coverage-image]: https://coveralls.io/repos/github/grantila/json-schema-cycles/badge.svg?branch=master\n[coverage-url]: https://coveralls.io/github/grantila/json-schema-cycles?branch=master\n[node-version]: https://img.shields.io/node/v/json-schema-cycles\n[node-url]: https://nodejs.org/en/\n[pure-esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrantila%2Fjson-schema-cycles","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgrantila%2Fjson-schema-cycles","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrantila%2Fjson-schema-cycles/lists"}