1 | import type { LiteralUnion, Required } from './common.js';
|
2 | import type { Hooks } from './hooks.js';
|
3 | import type { RetryOptions } from './retry.js';
|
4 | export type SearchParamsInit = string | string[][] | Record<string, string> | URLSearchParams | undefined;
|
5 | export type SearchParamsOption = SearchParamsInit | Record<string, string | number | boolean> | Array<Array<string | number | boolean>>;
|
6 | export type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete';
|
7 | export type Input = string | URL | Request;
|
8 | export type DownloadProgress = {
|
9 | percent: number;
|
10 | transferredBytes: number;
|
11 | /**
|
12 | Note: If it's not possible to retrieve the body size, it will be `0`.
|
13 | */
|
14 | totalBytes: number;
|
15 | };
|
16 | export type KyHeadersInit = NonNullable<RequestInit['headers']> | Record<string, string | undefined>;
|
17 | /**
|
18 | Custom Ky options
|
19 | */
|
20 | export type KyOptions = {
|
21 | /**
|
22 | Shortcut for sending JSON. Use this instead of the `body` option.
|
23 |
|
24 | Accepts any plain object or value, which will be `JSON.stringify()`'d and sent in the body with the correct header set.
|
25 | */
|
26 | json?: unknown;
|
27 | /**
|
28 | User-defined JSON-parsing function.
|
29 |
|
30 | Use-cases:
|
31 | 1. Parse JSON via the [`bourne` package](https://github.com/hapijs/bourne) to protect from prototype pollution.
|
32 | 2. Parse JSON with [`reviver` option of `JSON.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse).
|
33 |
|
34 | @default JSON.parse()
|
35 |
|
36 | @example
|
37 | ```
|
38 | import ky from 'ky';
|
39 | import bourne from '@hapijs/bourne';
|
40 |
|
41 | const json = await ky('https://example.com', {
|
42 | parseJson: text => bourne(text)
|
43 | }).json();
|
44 | ```
|
45 | */
|
46 | parseJson?: (text: string) => unknown;
|
47 | /**
|
48 | User-defined JSON-stringifying function.
|
49 |
|
50 | Use-cases:
|
51 | 1. Stringify JSON with a custom `replacer` function.
|
52 |
|
53 | @default JSON.stringify()
|
54 |
|
55 | @example
|
56 | ```
|
57 | import ky from 'ky';
|
58 | import {DateTime} from 'luxon';
|
59 |
|
60 | const json = await ky('https://example.com', {
|
61 | stringifyJson: data => JSON.stringify(data, (key, value) => {
|
62 | if (key.endsWith('_at')) {
|
63 | return DateTime.fromISO(value).toSeconds();
|
64 | }
|
65 |
|
66 | return value;
|
67 | })
|
68 | }).json();
|
69 | ```
|
70 | */
|
71 | stringifyJson?: (data: unknown) => string;
|
72 | /**
|
73 | Search parameters to include in the request URL. Setting this will override all existing search parameters in the input URL.
|
74 |
|
75 | Accepts any value supported by [`URLSearchParams()`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams).
|
76 | */
|
77 | searchParams?: SearchParamsOption;
|
78 | /**
|
79 | A prefix to prepend to the `input` URL when making the request. It can be any valid URL, either relative or absolute. A trailing slash `/` is optional and will be added automatically, if needed, when it is joined with `input`. Only takes effect when `input` is a string. The `input` argument cannot start with a slash `/` when using this option.
|
80 |
|
81 | Useful when used with [`ky.extend()`](#kyextenddefaultoptions) to create niche-specific Ky-instances.
|
82 |
|
83 | Notes:
|
84 | - After `prefixUrl` and `input` are joined, the result is resolved against the [base URL](https://developer.mozilla.org/en-US/docs/Web/API/Node/baseURI) of the page (if any).
|
85 | - Leading slashes in `input` are disallowed when using this option to enforce consistency and avoid confusion about how the `input` URL is handled, given that `input` will not follow the normal URL resolution rules when `prefixUrl` is being used, which changes the meaning of a leading slash.
|
86 |
|
87 | @example
|
88 | ```
|
89 | import ky from 'ky';
|
90 |
|
91 | // On https://example.com
|
92 |
|
93 | const response = await ky('unicorn', {prefixUrl: '/api'});
|
94 | //=> 'https://example.com/api/unicorn'
|
95 |
|
96 | const response = await ky('unicorn', {prefixUrl: 'https://cats.com'});
|
97 | //=> 'https://cats.com/unicorn'
|
98 | ```
|
99 | */
|
100 | prefixUrl?: URL | string;
|
101 | /**
|
102 | An object representing `limit`, `methods`, `statusCodes`, `afterStatusCodes`, and `maxRetryAfter` fields for maximum retry count, allowed methods, allowed status codes, status codes allowed to use the [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) time, and maximum [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) time.
|
103 |
|
104 | If `retry` is a number, it will be used as `limit` and other defaults will remain in place.
|
105 |
|
106 | If the response provides an HTTP status contained in `afterStatusCodes`, Ky will wait until the date or timeout given in the [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header has passed to retry the request. If `Retry-After` is missing, the non-standard [`RateLimit-Reset`](https://www.ietf.org/archive/id/draft-polli-ratelimit-headers-02.html#section-3.3) header is used in its place as a fallback. If the provided status code is not in the list, the [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header will be ignored.
|
107 |
|
108 | If `maxRetryAfter` is set to `undefined`, it will use `options.timeout`. If [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header is greater than `maxRetryAfter`, it will cancel the request.
|
109 |
|
110 | By default, delays between retries are calculated with the function `0.3 * (2 ** (attemptCount - 1)) * 1000`, where `attemptCount` is the attempt number (starts from 1), however this can be changed by passing a `delay` function.
|
111 |
|
112 | Retries are not triggered following a timeout.
|
113 |
|
114 | @example
|
115 | ```
|
116 | import ky from 'ky';
|
117 |
|
118 | const json = await ky('https://example.com', {
|
119 | retry: {
|
120 | limit: 10,
|
121 | methods: ['get'],
|
122 | statusCodes: [413]
|
123 | }
|
124 | }).json();
|
125 | ```
|
126 | */
|
127 | retry?: RetryOptions | number;
|
128 | /**
|
129 | Timeout in milliseconds for getting a response, including any retries. Can not be greater than 2147483647.
|
130 | If set to `false`, there will be no timeout.
|
131 |
|
132 | @default 10000
|
133 | */
|
134 | timeout?: number | false;
|
135 | /**
|
136 | Hooks allow modifications during the request lifecycle. Hook functions may be async and are run serially.
|
137 | */
|
138 | hooks?: Hooks;
|
139 | /**
|
140 | Throw an `HTTPError` when, after following redirects, the response has a non-2xx status code. To also throw for redirects instead of following them, set the [`redirect`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters) option to `'manual'`.
|
141 |
|
142 | Setting this to `false` may be useful if you are checking for resource availability and are expecting error responses.
|
143 |
|
144 | Note: If `false`, error responses are considered successful and the request will not be retried.
|
145 |
|
146 | @default true
|
147 | */
|
148 | throwHttpErrors?: boolean;
|
149 | /**
|
150 | Download progress event handler.
|
151 |
|
152 | @param chunk - Note: It's empty for the first call.
|
153 |
|
154 | @example
|
155 | ```
|
156 | import ky from 'ky';
|
157 |
|
158 | const response = await ky('https://example.com', {
|
159 | onDownloadProgress: (progress, chunk) => {
|
160 | // Example output:
|
161 | // `0% - 0 of 1271 bytes`
|
162 | // `100% - 1271 of 1271 bytes`
|
163 | console.log(`${progress.percent * 100}% - ${progress.transferredBytes} of ${progress.totalBytes} bytes`);
|
164 | }
|
165 | });
|
166 | ```
|
167 | */
|
168 | onDownloadProgress?: (progress: DownloadProgress, chunk: Uint8Array) => void;
|
169 | /**
|
170 | User-defined `fetch` function.
|
171 | Has to be fully compatible with the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) standard.
|
172 |
|
173 | Use-cases:
|
174 | 1. Use custom `fetch` implementations like [`isomorphic-unfetch`](https://www.npmjs.com/package/isomorphic-unfetch).
|
175 | 2. Use the `fetch` wrapper function provided by some frameworks that use server-side rendering (SSR).
|
176 |
|
177 | @default fetch
|
178 |
|
179 | @example
|
180 | ```
|
181 | import ky from 'ky';
|
182 | import fetch from 'isomorphic-unfetch';
|
183 |
|
184 | const json = await ky('https://example.com', {fetch}).json();
|
185 | ```
|
186 | */
|
187 | fetch?: (input: Input, init?: RequestInit) => Promise<Response>;
|
188 | };
|
189 | /**
|
190 | Each key from KyOptions is present and set to `true`.
|
191 |
|
192 | This type is used for identifying and working with the known keys in KyOptions.
|
193 | */
|
194 | export type KyOptionsRegistry = {
|
195 | [K in keyof KyOptions]-?: true;
|
196 | };
|
197 | /**
|
198 | Options are the same as `window.fetch`, except for the KyOptions
|
199 | */
|
200 | export interface Options extends KyOptions, Omit<RequestInit, 'headers'> {
|
201 | /**
|
202 | HTTP method used to make the request.
|
203 |
|
204 | Internally, the standard methods (`GET`, `POST`, `PUT`, `PATCH`, `HEAD` and `DELETE`) are uppercased in order to avoid server errors due to case sensitivity.
|
205 | */
|
206 | method?: LiteralUnion<HttpMethod, string>;
|
207 | /**
|
208 | HTTP headers used to make the request.
|
209 |
|
210 | You can pass a `Headers` instance or a plain object.
|
211 |
|
212 | You can remove a header with `.extend()` by passing the header with an `undefined` value.
|
213 |
|
214 | @example
|
215 | ```
|
216 | import ky from 'ky';
|
217 |
|
218 | const url = 'https://sindresorhus.com';
|
219 |
|
220 | const original = ky.create({
|
221 | headers: {
|
222 | rainbow: 'rainbow',
|
223 | unicorn: 'unicorn'
|
224 | }
|
225 | });
|
226 |
|
227 | const extended = original.extend({
|
228 | headers: {
|
229 | rainbow: undefined
|
230 | }
|
231 | });
|
232 |
|
233 | const response = await extended(url).json();
|
234 |
|
235 | console.log('rainbow' in response);
|
236 | //=> false
|
237 |
|
238 | console.log('unicorn' in response);
|
239 | //=> true
|
240 | ```
|
241 | */
|
242 | headers?: KyHeadersInit;
|
243 | }
|
244 | export type InternalOptions = Required<Omit<Options, 'hooks' | 'retry'>, 'fetch' | 'prefixUrl' | 'timeout'> & {
|
245 | headers: Required<Headers>;
|
246 | hooks: Required<Hooks>;
|
247 | retry: Required<RetryOptions>;
|
248 | prefixUrl: string;
|
249 | };
|
250 | /**
|
251 | Normalized options passed to the `fetch` call and the `beforeRequest` hooks.
|
252 | */
|
253 | export interface NormalizedOptions extends RequestInit {
|
254 | method: NonNullable<RequestInit['method']>;
|
255 | credentials?: NonNullable<RequestInit['credentials']>;
|
256 | retry: RetryOptions;
|
257 | prefixUrl: string;
|
258 | onDownloadProgress: Options['onDownloadProgress'];
|
259 | }
|
260 | export type { RetryOptions } from './retry.js';
|