diff --git a/README.md b/README.md index d090bc76..d7164c34 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +NOTE: This is a temporary fork of [APIDevTools/json-schema-ref-parser](https://github.com/APIDevTools/json-schema-ref-parser). Context [here](https://github.com/bcherny/json-schema-to-typescript/issues/469). + JSON Schema $Ref Parser ============================ #### Parse, Resolve, and Dereference JSON Schema $ref pointers diff --git a/docs/options.md b/docs/options.md index 8cfc4cae..3efb2b04 100644 --- a/docs/options.md +++ b/docs/options.md @@ -31,7 +31,9 @@ $RefParser.dereference("my-schema.yaml", { dereference: { circular: false, // Don't allow circular $refs excludedPathMatcher: (path) => // Skip dereferencing content under any 'example' key - path.includes("/example/") + path.includes("/example/"), + onDereference: (path, value) => // Callback invoked during dereferencing + console.log(path, value) } }); ``` @@ -77,4 +79,5 @@ The `dereference` options control how JSON Schema $Ref Parser will dereference ` |Option(s) |Type |Description |:---------------------|:-------------------|:------------ |`circular`|`boolean` or `"ignore"`|Determines whether [circular `$ref` pointers](README.md#circular-refs) are handled.

If set to `false`, then a `ReferenceError` will be thrown if the schema contains any circular references.

If set to `"ignore"`, then circular references will simply be ignored. No error will be thrown, but the [`$Refs.circular`](refs.md#circular) property will still be set to `true`. -|`excludedPathMatcher`|`(string) => boolean`|A function, called for each path, which can return true to stop this path and all subpaths from being dereferenced further. This is useful in schemas where some subpaths contain literal $ref keys that should not be dereferenced. +|`excludedPathMatcher`|`(string) => boolean`|A function, called for each path, which can return true to stop this path and all subpaths from being dereferenced further. This is useful in schemas where some subpaths contain literal `$ref` keys that should not be dereferenced. +|`onDereference`|`(string, JSONSchemaObjectType) => void`|A function, called immediately after dereferencing, with the resolved JSON Schema value and the `$ref` being dereferenced. diff --git a/lib/dereference.js b/lib/dereference.js index f6b2b203..cb9e3833 100644 --- a/lib/dereference.js +++ b/lib/dereference.js @@ -71,6 +71,9 @@ function crawl (obj, path, pathFromRoot, parents, processedObjects, dereferenced // Avoid pointless mutations; breaks frozen objects to no profit if (obj[key] !== dereferenced.value) { obj[key] = dereferenced.value; + if (options.dereference.onDereference) { + options.dereference.onDereference(value.$ref, obj[key]) + } } } else { diff --git a/lib/index.d.ts b/lib/index.d.ts index 547f27fe..2590fe82 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -1,4 +1,4 @@ -import { JSONSchema4, JSONSchema4Type, JSONSchema6, JSONSchema6Type, JSONSchema7, JSONSchema7Type } from "json-schema"; +import { JSONSchema4, JSONSchema4Object, JSONSchema4Type, JSONSchema6, JSONSchema6Object, JSONSchema6Type, JSONSchema7, JSONSchema7Object, JSONSchema7Type } from "json-schema"; export = $RefParser; @@ -174,6 +174,7 @@ declare class $RefParser { declare namespace $RefParser { export type JSONSchema = JSONSchema4 | JSONSchema6 | JSONSchema7; + export type JSONSchemaObject = JSONSchema4Object | JSONSchema6Object | JSONSchema7Object; export type SchemaCallback = (err: Error | null, schema?: JSONSchema) => any; export type $RefsCallback = (err: Error | null, $refs?: $Refs) => any; @@ -238,6 +239,14 @@ declare namespace $RefParser { * subpaths contain literal $ref keys that should not be dereferenced. */ excludedPathMatcher?(path: string): boolean; + + /** + * Callback invoked during dereferencing. + * + * @argument {string} path The path being dereferenced (ie. the `$ref` string). + * @argument {JSONSchemaObject} object The JSON-Schema that the `$ref` resolved to. + */ + onDereference(path: string, value: JSONSchemaObject): void; }; } diff --git a/package.json b/package.json index 4cea85a6..4c6457da 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@apidevtools/json-schema-ref-parser", + "name": "@bcherny/json-schema-ref-parser", "version": "0.0.0-dev", "description": "Parse, Resolve, and Dereference JSON Schema $ref pointers", "keywords": [ diff --git a/test/specs/dereference-callback/dereference-callback.spec.js b/test/specs/dereference-callback/dereference-callback.spec.js new file mode 100644 index 00000000..074fd687 --- /dev/null +++ b/test/specs/dereference-callback/dereference-callback.spec.js @@ -0,0 +1,26 @@ +"use strict"; + +const { expect } = require("chai"); +const $RefParser = require("../../.."); +const path = require("../../utils/path"); + +describe("Schema with a $ref", () => { + it("should call onDereference", async () => { + let parser = new $RefParser(); + const calls = []; + const schema = await parser.dereference( + path.rel("specs/dereference-callback/dereference-callback.yaml"), + { + dereference: { + onDereference(path, object) { + calls.push({ path, object }); + }, + }, + } + ); + expect(calls).to.deep.equal([ + { path: "#/definitions/b", object: { $ref: "#/definitions/a" } }, + { path: "#/definitions/a", object: { $ref: "#/definitions/a" } }, + ]); + }); +}); diff --git a/test/specs/dereference-callback/dereference-callback.yaml b/test/specs/dereference-callback/dereference-callback.yaml new file mode 100644 index 00000000..f9c40dd9 --- /dev/null +++ b/test/specs/dereference-callback/dereference-callback.yaml @@ -0,0 +1,12 @@ +title: test +type: object +definitions: + a: + $ref: "#/definitions/b" + b: + $ref: "#/definitions/a" +properties: + c: + type: string + d: + $ref: "#/definitions/a"