Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

ky

Package Overview
Dependencies
Maintainers
1
Versions
79
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ky - npm Package Compare versions

Comparing version 1.4.0 to 1.5.0

105

distribution/core/Ky.js

@@ -74,34 +74,9 @@ import { HTTPError } from '../errors/HTTPError.js';

}
request;
abortController;
_retryCount = 0;
_input;
_options;
// eslint-disable-next-line complexity
constructor(input, options = {}) {
Object.defineProperty(this, "request", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "abortController", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "_retryCount", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "_input", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "_options", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this._input = input;

@@ -179,24 +154,24 @@ const credentials = this._input instanceof Request && 'credentials' in Request.prototype

this._retryCount++;
if (this._retryCount <= this._options.retry.limit && !(error instanceof TimeoutError)) {
if (error instanceof HTTPError) {
if (!this._options.retry.statusCodes.includes(error.response.status)) {
return 0;
if (this._retryCount > this._options.retry.limit || error instanceof TimeoutError) {
throw error;
}
if (error instanceof HTTPError) {
if (!this._options.retry.statusCodes.includes(error.response.status)) {
throw error;
}
const retryAfter = error.response.headers.get('Retry-After');
if (retryAfter && this._options.retry.afterStatusCodes.includes(error.response.status)) {
let after = Number(retryAfter) * 1000;
if (Number.isNaN(after)) {
after = Date.parse(retryAfter) - Date.now();
}
const retryAfter = error.response.headers.get('Retry-After');
if (retryAfter && this._options.retry.afterStatusCodes.includes(error.response.status)) {
let after = Number(retryAfter) * 1000;
if (Number.isNaN(after)) {
after = Date.parse(retryAfter) - Date.now();
}
const max = this._options.retry.maxRetryAfter ?? after;
return after < max ? after : max;
}
if (error.response.status === 413) {
return 0;
}
const max = this._options.retry.maxRetryAfter ?? after;
return after < max ? after : max;
}
const retryDelay = this._options.retry.delay(this._retryCount);
return Math.min(this._options.retry.backoffLimit, retryDelay);
if (error.response.status === 413) {
throw error;
}
}
return 0;
const retryDelay = this._options.retry.delay(this._retryCount);
return Math.min(this._options.retry.backoffLimit, retryDelay);
}

@@ -215,20 +190,20 @@ _decorateResponse(response) {

const ms = Math.min(this._calculateRetryDelay(error), maxSafeTimeout);
if (ms !== 0 && this._retryCount > 0) {
await delay(ms, { signal: this._options.signal });
for (const hook of this._options.hooks.beforeRetry) {
// eslint-disable-next-line no-await-in-loop
const hookResult = await hook({
request: this.request,
options: this._options,
error: error,
retryCount: this._retryCount,
});
// If `stop` is returned from the hook, the retry process is stopped
if (hookResult === stop) {
return;
}
if (this._retryCount < 1) {
throw error;
}
await delay(ms, { signal: this._options.signal });
for (const hook of this._options.hooks.beforeRetry) {
// eslint-disable-next-line no-await-in-loop
const hookResult = await hook({
request: this.request,
options: this._options,
error: error,
retryCount: this._retryCount,
});
// If `stop` is returned from the hook, the retry process is stopped
if (hookResult === stop) {
return;
}
return this._retry(function_);
}
throw error;
return this._retry(function_);
}

@@ -235,0 +210,0 @@ }

import type { NormalizedOptions } from '../types/options.js';
import type { KyRequest } from '../types/request.js';
import type { KyResponse } from '../types/response.js';
export declare class HTTPError extends Error {
response: Response;
request: Request;
response: KyResponse;
request: KyRequest;
options: NormalizedOptions;
constructor(response: Response, request: Request, options: NormalizedOptions);
}
// eslint-lint-disable-next-line @typescript-eslint/naming-convention
export class HTTPError extends Error {
response;
request;
options;
constructor(response, request, options) {

@@ -9,20 +12,2 @@ const code = (response.status || response.status === 0) ? response.status : '';

super(`Request failed with ${reason}: ${request.method} ${request.url}`);
Object.defineProperty(this, "response", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "request", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "options", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this.name = 'HTTPError';

@@ -29,0 +14,0 @@ this.response = response;

@@ -0,4 +1,5 @@

import type { KyRequest } from '../types/request.js';
export declare class TimeoutError extends Error {
request: Request;
request: KyRequest;
constructor(request: Request);
}
export class TimeoutError extends Error {
request;
constructor(request) {
super(`Request timed out: ${request.method} ${request.url}`);
Object.defineProperty(this, "request", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this.name = 'TimeoutError';

@@ -11,0 +6,0 @@ this.request = request;

@@ -9,4 +9,5 @@ /*! MIT License © Sindre Sorhus */

export type { ResponsePromise } from './types/ResponsePromise.js';
export type { KyRequest } from './types/request.js';
export type { KyResponse } from './types/response.js';
export { HTTPError } from './errors/HTTPError.js';
export { TimeoutError } from './errors/TimeoutError.js';

@@ -13,3 +13,8 @@ /*! MIT License © Sindre Sorhus */

ky.create = (newDefaults) => createInstance(validateAndMerge(newDefaults));
ky.extend = (newDefaults) => createInstance(validateAndMerge(defaults, newDefaults));
ky.extend = (newDefaults) => {
if (typeof newDefaults === 'function') {
newDefaults = newDefaults(defaults ?? {});
}
return createInstance(validateAndMerge(defaults, newDefaults));
};
ky.stop = stop;

@@ -16,0 +21,0 @@ return ky;

import { type stop } from '../core/constants.js';
import { type HTTPError } from '../index.js';
import type { KyRequest, KyResponse, HTTPError } from '../index.js';
import type { NormalizedOptions } from './options.js';
export type BeforeRequestHook = (request: Request, options: NormalizedOptions) => Request | Response | void | Promise<Request | Response | void>;
export type BeforeRequestHook = (request: KyRequest, options: NormalizedOptions) => Request | Response | void | Promise<Request | Response | void>;
export type BeforeRetryState = {
request: Request;
request: KyRequest;
options: NormalizedOptions;

@@ -12,3 +12,3 @@ error: Error;

export type BeforeRetryHook = (options: BeforeRetryState) => typeof stop | void | Promise<typeof stop | void>;
export type AfterResponseHook = (request: Request, options: NormalizedOptions, response: Response) => Response | void | Promise<Response | void>;
export type AfterResponseHook = (request: KyRequest, options: NormalizedOptions, response: KyResponse) => Response | void | Promise<Response | void>;
export type BeforeErrorHook = (error: HTTPError) => HTTPError | Promise<HTTPError>;

@@ -15,0 +15,0 @@ export type Hooks = {

@@ -75,5 +75,22 @@ import { type stop } from '../core/constants.js';

You can also refer to parent defaults by providing a function to `.extend()`.
@example
```
import ky from 'ky';
const api = ky.create({prefixUrl: 'https://example.com/api'});
const usersApi = api.extend((options) => ({prefixUrl: `${options.prefixUrl}/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) => KyInstance;
extend: (defaultOptions: Options | ((parentOptions: Options) => Options)) => KyInstance;
/**

@@ -80,0 +97,0 @@ A `Symbol` that can be returned by a `beforeRetry` hook to stop the retry. This will also short circuit the remaining `beforeRetry` hooks.

@@ -102,6 +102,8 @@ import type { LiteralUnion, Required } from './common.js';

/**
An object representing `limit`, `methods`, `statusCodes` and `maxRetryAfter` fields for maximum retry count, allowed methods, allowed status codes and maximum [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) time.
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.
If `retry` is a number, it will be used as `limit` and other defaults will remain in place.
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 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.
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.

@@ -108,0 +110,0 @@

@@ -27,2 +27,5 @@ type UndiciHeadersInit = string[][] | Record<string, string | readonly string[]> | Headers;

};
export type KyRequest = {
json: <T = unknown>() => Promise<T>;
} & Request;
export {};

@@ -31,5 +31,4 @@ import { requestMethods } from '../core/constants.js';

...retry,
afterStatusCodes: retryAfterStatusCodes,
};
};
//# sourceMappingURL=normalize.js.map
{
"name": "ky",
"version": "1.4.0",
"description": "Tiny and elegant HTTP client based on the browser Fetch API",
"version": "1.5.0",
"description": "Tiny and elegant HTTP client based on the Fetch API",
"license": "MIT",

@@ -57,3 +57,3 @@ "repository": "sindresorhus/ky",

"devDependencies": {
"@sindresorhus/tsconfig": "^4.0.0",
"@sindresorhus/tsconfig": "^6.0.0",
"@type-challenges/utils": "^0.1.1",

@@ -63,3 +63,3 @@ "@types/body-parser": "^1.19.2",

"@types/express": "^4.17.17",
"@types/node": "^20.5.7",
"@types/node": "^20.14.12",
"ava": "^5.3.1",

@@ -70,10 +70,10 @@ "body-parser": "^1.20.2",

"delay": "^6.0.0",
"expect-type": "^0.16.0",
"expect-type": "^0.19.0",
"express": "^4.18.2",
"pify": "^6.1.0",
"playwright": "^1.40.1",
"playwright": "^1.45.3",
"raw-body": "^2.5.2",
"tsx": "^4.7.0",
"typescript": "^5.2.2",
"xo": "^0.56.0"
"tsx": "^4.16.2",
"typescript": "^5.5.4",
"xo": "^0.58.0"
},

@@ -91,3 +91,4 @@ "xo": {

"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/naming-convention": "off"
"@typescript-eslint/naming-convention": "off",
"n/no-unsupported-features/node-builtins": "off"
}

@@ -94,0 +95,0 @@ },

@@ -54,3 +54,3 @@ <div align="center">

> Ky is a tiny and elegant HTTP client based on the browser [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch)
> Ky is a tiny and elegant HTTP client based on the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch)

@@ -60,5 +60,5 @@ [![Coverage Status](https://codecov.io/gh/sindresorhus/ky/branch/main/graph/badge.svg)](https://codecov.io/gh/sindresorhus/ky)

Ky targets [modern browsers](#browser-support), Node.js, and Deno.
Ky targets [modern browsers](#browser-support), Node.js, Bun, and Deno.
It's just a tiny file with no dependencies.
It's just a tiny package with no dependencies.

@@ -76,2 +76,3 @@ ## Benefits over plain `fetch`

- Hooks
- TypeScript niceties (e.g. `.json()` resolves to `unknown`, not `any`; `.json<T>()` can be used too)

@@ -218,2 +219,3 @@ ## Install

- `statusCodes`: [`408`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408) [`413`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/413) [`429`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) [`500`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500) [`502`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/502) [`503`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/503) [`504`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/504)
- `afterStatusCodes`: [`413`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/413), [`429`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429), [`503`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/503)
- `maxRetryAfter`: `undefined`

@@ -223,6 +225,8 @@ - `backoffLimit`: `undefined`

An object representing `limit`, `methods`, `statusCodes` and `maxRetryAfter` fields for maximum retry count, allowed methods, allowed status codes and maximum [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) time.
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.
If `retry` is a number, it will be used as `limit` and other defaults will remain in place.
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 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.
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 use `maxRetryAfter`.

@@ -518,2 +522,18 @@

You can also refer to parent defaults by providing a function to `.extend()`.
```js
import ky from 'ky';
const api = ky.create({prefixUrl: 'https://example.com/api'});
const usersApi = api.extend((options) => ({prefixUrl: `${options.prefixUrl}/users`}));
const response = await usersApi.get('123');
//=> 'https://example.com/api/users/123'
const response = await api.get('version');
//=> 'https://example.com/api/version'
```
### ky.create(defaultOptions)

@@ -694,3 +714,3 @@

console.log(json.title);
//=> 'delectus aut autem
//=> 'delectus aut autem'
</script>

@@ -727,2 +747,3 @@ ```

- [fetch-extras](https://github.com/sindresorhus/fetch-extras) - Useful utilities for working with Fetch
- [got](https://github.com/sindresorhus/got) - Simplified HTTP requests for Node.js

@@ -729,0 +750,0 @@ - [ky-hooks-change-case](https://github.com/alice-health/ky-hooks-change-case) - Ky hooks to modify cases on requests and responses of objects

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc