UNPKG

schema-finder

Version:

A simple React component for viewing and exploring a JSONSchema

96 lines (82 loc) 2.43 kB
import {JSONSchema7} from "json-schema"; import {DerefBuilder, DerefOptions} from "./internal"; export const buildDeref: DerefBuilder = (root, options) => async (ref) => { if (ref === undefined) return [{}]; // if (ref in idDict) return [idDict[ref]]; const [address, jp] = ref.split(/\/?#\/?/); let refschema = root; if (address.length && options?.unsafeAllowRemoteUriResolution) { const [val, err] = await resolveAddress(address); if (err !== undefined) { return [{}, err]; } refschema = val; } return evaljp(refschema, parseJsonPointer(jp)); }; /** * Resolves $ref * @param options Additional options * @param idDict Dictionary of schemas with $id * @param rootSchema Fallback schema so use if ref doesn't specify an id * or an address or remote address resolution is not enabled. * @param ref [JSON pointer] to referenced schema * * [JSON pointer]: https://datatracker.ietf.org/doc/html/rfc6901 */ export async function deref( options: DerefOptions, idDict: Record<string, JSONSchema7>, rootSchema: JSONSchema7, ref?: string ): Promise<[unknown, Error?]> { if (ref === undefined) return [{}]; if (ref in idDict) return [idDict[ref]]; const [address, jp] = ref.split(/\/?#\/?/); if (address.length && options.unsafeAllowRemoteUriResolution) { const [val, err] = await resolveAddress(address); if (err !== undefined) { return [{}, err]; } rootSchema = val; } return evaljp(rootSchema, parseJsonPointer(jp)); } async function resolveAddress( address: string ): Promise<[Record<string, unknown>, Error?]> { try { const r = await fetch(address); if (!r.ok) { return [{}, new Error(`${r.status}: ${r.statusText}`)]; } return [await r.json()]; } catch (e) { return [{}, e as Error]; } } /** * Returns whatever the JSONPointer is pointing to in a schema */ function evaljp(j: JSONSchema7, keys: string[]): [unknown, Error?] { for (const key of keys) { if (!(key in j)) { return [ j, new Error( `No key "${key}" in given object: ${JSON.stringify( j, undefined, "\t" )}` ), ]; } // @ts-expect-error Indexing with {string} j = j[key]; } return [j]; } function parseJsonPointer(jp: string): string[] { return jp.split("/").map((key) => key.replace("~1", "/").replace("~0", "~")); }