From 5929a467ffa3d0151d386cce09d6f65fae6a3937 Mon Sep 17 00:00:00 2001 From: JonLuca DeCaro Date: Tue, 5 Mar 2024 23:00:10 -0800 Subject: [PATCH] feat(cloning): add option to clone input schema, add notice to readme --- README.md | 9 +++++++-- lib/index.ts | 38 +++++++++----------------------------- lib/normalize-args.ts | 5 +++++ lib/options.ts | 9 +++++++++ 4 files changed, 30 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 5c0e85b6..19307080 100644 --- a/README.md +++ b/README.md @@ -75,8 +75,13 @@ Example import $RefParser from "@apidevtools/json-schema-ref-parser"; try { - let schema = await $RefParser.dereference(mySchema); - console.log(schema.definitions.person.properties.firstName); + await $RefParser.dereference(mySchema); + // note - by default, mySchema is modified in place, and the returned value is a reference to the same object + console.log(mySchema.definitions.person.properties.firstName); + + // if you want to avoid modifying the original schema, you can disable the `mutateInputSchema` option + let clonedSchema = await $RefParser.dereference(mySchema, { mutateInputSchema: false }); + console.log(clonedSchema.definitions.person.properties.firstName); } catch (err) { console.error(err); } diff --git a/lib/index.ts b/lib/index.ts index e7364662..bc0b0905 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -19,37 +19,17 @@ import { import { ono } from "@jsdevtools/ono"; import maybe from "./util/maybe.js"; import type { ParserOptions } from "./options.js"; -import type { - Plugin, - $RefsCallback, - JSONSchema, - SchemaCallback, - HTTPResolverOptions, - FileInfo, - ResolverOptions, - JSONSchemaObject, -} from "./types/index.js"; +import type { $RefsCallback, JSONSchema, SchemaCallback } from "./types/index.js"; -export { - JSONSchemaObject, - ResolverOptions, - ParserError, - UnmatchedResolverError, - ResolverError, - HTTPResolverOptions, - FileInfo, - UnmatchedParserError, - ParserOptions, - MissingPointerError, - InvalidPointerError, - JSONParserError, - Plugin, - JSONSchema, - $RefsCallback, - SchemaCallback, -}; +export { JSONParserError }; +export { InvalidPointerError }; +export { MissingPointerError }; +export { ResolverError }; +export { ParserError }; +export { UnmatchedParserError }; +export { UnmatchedResolverError }; -export type RefParserSchema = string | JSONSchema; +type RefParserSchema = string | JSONSchema; /** * This class parses a JSON schema, builds a map of its JSON references and their resolved values, diff --git a/lib/normalize-args.ts b/lib/normalize-args.ts index 3ba66c58..aa58ad0e 100644 --- a/lib/normalize-args.ts +++ b/lib/normalize-args.ts @@ -39,6 +39,11 @@ function normalizeArgs(_args: Partial) { console.log(e); } + if (!options.mutateInputSchema) { + // Make a deep clone of the schema, so that we don't alter the original object + schema = JSON.parse(JSON.stringify(schema)); + } + return { path, schema, diff --git a/lib/options.ts b/lib/options.ts index 3f341139..15e02d0a 100644 --- a/lib/options.ts +++ b/lib/options.ts @@ -91,6 +91,13 @@ interface $RefParserOptions { * Default: `relative` */ externalReferenceResolution?: "relative" | "root"; + + /** + * Whether to clone the schema before dereferencing it. + * This is useful when you want to dereference the same schema multiple times, but you don't want to modify the original schema. + * Default: `true` due to mutating the input being the default behavior historically + */ + mutateInputSchema?: boolean; }; } @@ -159,6 +166,8 @@ const getDefaults = () => { excludedPathMatcher: () => false, referenceResolution: "relative", }, + + mutateInputSchema: true, } as $RefParserOptions; return defaults; };