fork of hey-api/openapi-ts because I need some additional things
1import { ono } from '@jsdevtools/ono';
2
3import type { FileInfo } from '../types';
4import { ResolverError } from '../util/errors';
5import { resolve } from '../util/url';
6
7export const sendRequest = async ({
8 fetchOptions,
9 redirects = [],
10 timeout = 60_000,
11 url,
12}: {
13 fetchOptions?: RequestInit;
14 redirects?: string[];
15 timeout?: number;
16 url: URL | string;
17}): Promise<{
18 fetchOptions?: RequestInit;
19 response: Response;
20}> => {
21 url = new URL(url);
22 redirects.push(url.href);
23
24 const controller = new AbortController();
25 const timeoutId = setTimeout(() => {
26 controller.abort();
27 }, timeout);
28 const response = await fetch(url, {
29 signal: controller.signal,
30 ...fetchOptions,
31 });
32 clearTimeout(timeoutId);
33
34 if (response.status >= 300 && response.status <= 399) {
35 if (redirects.length > 5) {
36 throw new ResolverError(
37 ono(
38 { status: response.status },
39 `Error requesting ${redirects[0]}. \nToo many redirects: \n ${redirects.join(' \n ')}`,
40 ),
41 );
42 }
43
44 if (!('location' in response.headers) || !response.headers.location) {
45 throw ono(
46 { status: response.status },
47 `HTTP ${response.status} redirect with no location header`,
48 );
49 }
50
51 return sendRequest({
52 fetchOptions,
53 redirects,
54 timeout,
55 url: resolve(url.href, response.headers.location as string),
56 });
57 }
58
59 return { fetchOptions, response };
60};
61
62export const urlResolver = {
63 handler: async ({
64 arrayBuffer,
65 fetch: _fetch,
66 file,
67 }: {
68 arrayBuffer?: ArrayBuffer;
69 fetch?: RequestInit;
70 file: FileInfo;
71 }): Promise<void> => {
72 let data = arrayBuffer;
73
74 if (!data) {
75 try {
76 const { fetchOptions, response } = await sendRequest({
77 fetchOptions: {
78 method: 'GET',
79 ..._fetch,
80 },
81 url: file.url,
82 });
83
84 if (response.status >= 400) {
85 // gracefully handle HEAD method not allowed
86 if (response.status !== 405 || fetchOptions?.method !== 'HEAD') {
87 throw ono({ status: response.status }, `HTTP ERROR ${response.status}`);
88 }
89 }
90
91 data = response.body ? await response.arrayBuffer() : new ArrayBuffer(0);
92 } catch (error: any) {
93 throw new ResolverError(ono(error, `Error requesting ${file.url}`), file.url);
94 }
95 }
96
97 file.data = Buffer.from(data!);
98 },
99};