()
| 151 | const ky = new Ky(input, initHookOptions); |
| 152 | |
| 153 | const function_ = async (): Promise<Response | void> => { |
| 154 | if (typeof ky.#options.timeout === 'number' && ky.#options.timeout > maxSafeTimeout) { |
| 155 | throw new RangeError(`The \`timeout\` option cannot be greater than ${maxSafeTimeout}`); |
| 156 | } |
| 157 | |
| 158 | if (typeof ky.#options.totalTimeout === 'number' && ky.#options.totalTimeout > maxSafeTimeout) { |
| 159 | throw new RangeError(`The \`totalTimeout\` option cannot be greater than ${maxSafeTimeout}`); |
| 160 | } |
| 161 | |
| 162 | // Delay the fetch so that body method shortcuts can set the Accept header |
| 163 | await Promise.resolve(); |
| 164 | const beforeRequestResponse = await ky.#runBeforeRequestHooks(); |
| 165 | let response = beforeRequestResponse ?? await ky.#retry(async () => ky.#fetch()); |
| 166 | let responseFromHook = beforeRequestResponse !== undefined |
| 167 | || ky.#consumeReturnedResponseFromBeforeRetryHook(); |
| 168 | |
| 169 | for (;;) { |
| 170 | // `undefined` means a hook stopped the flow without providing a response. |
| 171 | // Non-native Responses still continue through Ky if they pass `isResponseInstance()`. |
| 172 | if (response === undefined) { |
| 173 | return response; |
| 174 | } |
| 175 | |
| 176 | if (isResponseInstance(response)) { |
| 177 | try { |
| 178 | // eslint-disable-next-line no-await-in-loop |
| 179 | response = await ky.#runAfterResponseHooks(response); |
| 180 | } catch (error) { |
| 181 | if (!(error instanceof ForceRetryError)) { |
| 182 | throw error; |
| 183 | } |
| 184 | |
| 185 | // eslint-disable-next-line no-await-in-loop |
| 186 | const retriedResponse: Response | void = await ky.#retryFromError(error, async () => ky.#fetch()); |
| 187 | if (retriedResponse === undefined) { |
| 188 | return retriedResponse; |
| 189 | } |
| 190 | |
| 191 | response = retriedResponse; |
| 192 | responseFromHook = ky.#consumeReturnedResponseFromBeforeRetryHook(); |
| 193 | continue; |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | const currentResponse: Response = response; |
| 198 | |
| 199 | // Opaque responses (`response.type === 'opaque'`) from `no-cors` requests always have `status: 0` and `ok: false`, but this is not a failure - the actual status is hidden by the browser. |
| 200 | if (!currentResponse.ok && currentResponse.type !== 'opaque' && ( |
| 201 | typeof ky.#options.throwHttpErrors === 'function' |
| 202 | ? ky.#options.throwHttpErrors(currentResponse.status) |
| 203 | : ky.#options.throwHttpErrors |
| 204 | )) { |
| 205 | // `request` must reflect the request that actually failed, but `options` stays as Ky's |
| 206 | // normalized options snapshot. Replacement `Request` instances do not preserve the |
| 207 | // original `BodyInit`, so trying to make `options` mirror arbitrary requests would be lossy. |
| 208 | const httpError: HTTPError = new HTTPError(currentResponse, ky.#getResponseRequest(currentResponse), ky.#getNormalizedOptions()); |
| 209 | const errorToThrow: Error = httpError; |
| 210 | // eslint-disable-next-line no-await-in-loop |
nothing calls this directly
no test coverage detected