@alexop/openapi-zod-client
Version:
[](https://openapi-zod-client.vercel.app/)
56 lines (42 loc) • 1.94 kB
text/typescript
import type { OpenAPIObject, SchemaObject } from "openapi3-ts";
import { get } from "pastable/server";
import { normalizeString } from "./utils";
const autocorrectRef = (ref: string) => (ref[1] === "/" ? ref : "#/" + ref.slice(1));
type RefInfo = {
ref: string;
name: string;
normalized: string;
};
export const makeSchemaResolver = (doc: OpenAPIObject) => {
// both used for debugging purpose
// eslint-disable-next-line sonarjs/no-unused-collection
const nameByRef = new Map<string, string>();
// eslint-disable-next-line sonarjs/no-unused-collection
const refByName = new Map<string, string>();
const byRef = new Map<string, RefInfo>();
const byNormalized = new Map<string, RefInfo>();
const getSchemaByRef = (ref: string) => {
// #components -> #/components
const correctRef = autocorrectRef(ref);
const split = correctRef.split("/");
// "#/components/schemas/Something.jsonld" -> #/components/schemas
const path = split.slice(1, -1).join("/")!;
const map = get(doc, path.replace("#/", "").replace("#", "").replaceAll("/", ".")) ?? ({} as any);
// "#/components/schemas/Something.jsonld" -> "Something.jsonld"
const name = split[split.length - 1]!;
const normalized = normalizeString(name);
nameByRef.set(correctRef, normalized);
refByName.set(normalized, correctRef);
const infos = { ref: correctRef, name, normalized };
byRef.set(infos.ref, infos);
byNormalized.set(infos.normalized, infos);
// doc.components.schemas["Something.jsonld"]
return map[name] as SchemaObject;
};
return {
getSchemaByRef,
resolveRef: (ref: string) => byRef.get(autocorrectRef(ref))!,
resolveSchemaName: (normalized: string) => byNormalized.get(normalized)!,
};
};
export type DocumentResolver = ReturnType<typeof makeSchemaResolver>;