import { type stop, type retry } from '../core/constants.js'; import type { Input, Options } from './options.js'; import type { ResponsePromise } from './ResponsePromise.js'; export type KyInstance = { /** Fetch the given `url`. Invalid options, an invalid `input`, and an error thrown by an `init` hook reject the returned promise instead of throwing, the same way `fetch()` reports them. They are not passed to `beforeError` hooks, because no request was made. @param url - `Request` object, `URL` object, or URL string. @returns A promise with `Body` method added. @example ``` import ky from 'ky'; const json = await ky('https://example.com', {json: {foo: true}}).json(); console.log(json); //=> `{data: '🦄'}` ``` */ (url: Input, options?: Options): ResponsePromise; /** Fetch the given `url` using the option `{method: 'get'}`. @param url - `Request` object, `URL` object, or URL string. @returns A promise with `Body` methods added. */ get: (url: Input, options?: Options) => ResponsePromise; /** Fetch the given `url` using the option `{method: 'post'}`. @param url - `Request` object, `URL` object, or URL string. @returns A promise with `Body` methods added. */ post: (url: Input, options?: Options) => ResponsePromise; /** Fetch the given `url` using the option `{method: 'put'}`. @param url - `Request` object, `URL` object, or URL string. @returns A promise with `Body` methods added. */ put: (url: Input, options?: Options) => ResponsePromise; /** Fetch the given `url` using the option `{method: 'delete'}`. @param url - `Request` object, `URL` object, or URL string. @returns A promise with `Body` methods added. */ delete: (url: Input, options?: Options) => ResponsePromise; /** Fetch the given `url` using the option `{method: 'patch'}`. @param url - `Request` object, `URL` object, or URL string. @returns A promise with `Body` methods added. */ patch: (url: Input, options?: Options) => ResponsePromise; /** Fetch the given `url` using the option `{method: 'head'}`. @param url - `Request` object, `URL` object, or URL string. @returns A promise with `Body` methods added. */ head: (url: Input, options?: Options) => ResponsePromise; /** Fetch the given `url` using the option `{method: 'query'}`. @param url - `Request` object, `URL` object, or URL string. @returns A promise with `Body` methods added. */ query: (url: Input, options?: Options) => ResponsePromise; /** Create a new Ky instance with complete new defaults, without inheriting from any parent instance. @returns A new Ky instance. */ create: (defaultOptions?: Options) => KyInstance; /** Create a new Ky instance with some defaults overridden with your own. In contrast to `ky.create()`, `ky.extend()` inherits defaults from its parent. You can pass headers as a `Headers` instance or a plain object. Headers are normalized to a plain object with lowercase names when options are merged, so `init` hooks start with a plain object with lowercase keys. A header removed with `undefined` stays in that object with an `undefined` value. You can remove a header with `.extend()` by passing the header with an `undefined` value. Passing `undefined` as a string removes the header only if it comes from a `Headers` instance. Similarly, you can remove existing `hooks` entries by extending the hook with an explicit `undefined`. By default, `.extend()` deep-merges options: hooks are appended, headers are merged, and search parameters are accumulated. Use `replaceOption` when you want to fully replace a merged property instead. When extending an instance, signals are combined. Use `replaceOption(signal)` to replace inherited signals, or `signal: undefined` to remove them. You can also refer to parent defaults by providing a function to `.extend()`. @example ``` import ky from 'ky'; const api = ky.create({prefix: 'https://example.com/api'}); const usersApi = api.extend((options) => ({prefix: `${options.prefix}/users`})); const response = await usersApi.get('123'); //=> 'https://example.com/api/users/123' const response = await api.get('version'); //=> 'https://example.com/api/version' ``` @returns A new Ky instance. */ extend: (defaultOptions: Options | ((parentOptions: Options) => Options)) => KyInstance; /** A `Symbol` that can be returned by a `beforeRetry` hook to stop the retry. This will also short circuit the remaining `beforeRetry` hooks. Note: Returning this symbol makes Ky abort and return with an `undefined` response. Be sure to check for a response before accessing any properties on it or use [optional chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining). It is also incompatible with body methods, such as `.json()` or `.text()`, because there is no response to parse. Calling one throws a `TypeError` explaining this. In general, we recommend throwing an error instead of returning this symbol, as that will cause Ky to abort and then throw, which avoids these limitations. A valid use-case for `ky.stop` is to prevent retries when making requests for side effects, where the returned data is not important. For example, logging client activity to the server. @example ``` import ky from 'ky'; // Note that `response` will be `undefined` in case `ky.stop` is returned. const response = await ky.post('https://example.com', { hooks: { beforeRetry: [ async ({request, options, error, retryCount}) => { const shouldStopRetry = await ky('https://example.com/api'); if (shouldStopRetry) { return ky.stop; } } ] } }); // Using `.text()` or other body methods is not supported, because there is no response to parse. ``` */ readonly stop: typeof stop; /** Force a retry from an `afterResponse` hook. This allows you to retry a request based on the response content, even if the response has a successful status code. The retry will respect the `retry.limit` option and skip the `shouldRetry` check. The forced retry is observable in `beforeRetry` hooks, where the error will be a `ForceRetryError`. A marker returned by a second copy of Ky, which happens with a duplicated dependency, is still recognised, the same way the Ky error guards accept branded errors. @example ``` import ky, {isForceRetryError} from 'ky'; const api = ky.extend({ hooks: { afterResponse: [ async ({response}) => { // Retry based on response body content if (response.status === 200) { const data = await response.json(); // Simple retry with default delay if (data.error?.code === 'TEMPORARY_ERROR') { return ky.retry(); } // Retry with custom delay from API response if (data.error?.code === 'RATE_LIMIT') { return ky.retry({ delay: data.error.retryAfter * 1000, code: 'RATE_LIMIT' }); } } } ], beforeRetry: [ ({error, retryCount}) => { // Observable in beforeRetry hooks if (isForceRetryError(error)) { console.log(`Forced retry #${retryCount}: ${error.message}`); // Example output: "Forced retry #1: Forced retry: RATE_LIMIT" } } ] } }); const response = await api.get('https://example.com/api'); ``` */ readonly retry: typeof retry; };