UNPKG

@hey-api/json-schema-ref-parser

Version:

Parse, Resolve, and Dereference JSON Schema $ref pointers

96 lines (84 loc) 2.42 kB
import { ono } from "@jsdevtools/ono"; import { resolve } from "../util/url.js"; import { ResolverError } from "../util/errors.js"; import type { FileInfo } from "../types/index.js"; export const sendRequest = async ({ fetchOptions, redirects = [], timeout = 60_000, url, }: { fetchOptions?: RequestInit; redirects?: string[]; timeout?: number; url: URL | string; }): Promise<{ fetchOptions?: RequestInit; response: Response; }> => { url = new URL(url); redirects.push(url.href); const controller = new AbortController(); const timeoutId = setTimeout(() => { controller.abort(); }, timeout); const response = await fetch(url, { signal: controller.signal, ...fetchOptions, }); clearTimeout(timeoutId); if (response.status >= 300 && response.status <= 399) { if (redirects.length > 5) { throw new ResolverError( ono( { status: response.status }, `Error requesting ${redirects[0]}. \nToo many redirects: \n ${redirects.join(" \n ")}`, ), ); } if (!("location" in response.headers) || !response.headers.location) { throw ono({ status: response.status }, `HTTP ${response.status} redirect with no location header`); } return sendRequest({ fetchOptions, redirects, timeout, url: resolve(url.href, response.headers.location as string), }); } return { fetchOptions, response }; } export const urlResolver = { handler: async ({ arrayBuffer, fetch: _fetch, file, }: { arrayBuffer?: ArrayBuffer; fetch?: RequestInit; file: FileInfo; }): Promise<void> => { let data = arrayBuffer; if (!data) { try { const { fetchOptions, response } = await sendRequest({ fetchOptions: { method: 'GET', ..._fetch, }, url: file.url, }); if (response.status >= 400) { // gracefully handle HEAD method not allowed if (response.status !== 405 || fetchOptions?.method !== 'HEAD') { throw ono({ status: response.status }, `HTTP ERROR ${response.status}`); } } data = response.body ? await response.arrayBuffer() : new ArrayBuffer(0); } catch (error: any) { throw new ResolverError(ono(error, `Error requesting ${file.url}`), file.url); } } file.data = Buffer.from(data!); }, };