Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Require Node.js 10
  • Loading branch information
sindresorhus committed Feb 2, 2020
1 parent cf6ca95 commit 7c1d371
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 61 deletions.
14 changes: 6 additions & 8 deletions package.json
Expand Up @@ -11,7 +11,7 @@
"url": "sindresorhus.com"
},
"engines": {
"node": ">=8"
"node": ">=10"
},
"scripts": {
"build": "rollup index.js --format=umd --name=ky --file=umd.js",
Expand Down Expand Up @@ -48,17 +48,17 @@
],
"devDependencies": {
"abort-controller": "^3.0.0",
"ava": "^1.4.1",
"ava": "^3.2.0",
"body": "^5.1.0",
"codecov": "^3.4.0",
"codecov": "^3.6.4",
"create-test-server": "2.1.1",
"delay": "^4.1.0",
"esm": "^3.2.22",
"form-data": "^3.0.0",
"node-fetch": "^2.5.0",
"nyc": "^14.1.1",
"puppeteer": "^1.15.0",
"rollup": "^1.27.0",
"nyc": "^15.0.0",
"puppeteer": "^2.1.0",
"rollup": "^1.31.0",
"tsd": "^0.11.0",
"xo": "^0.25.3"
},
Expand All @@ -72,8 +72,6 @@
]
},
"ava": {
"babel": false,
"compileEnhancements": false,
"require": [
"esm",
"./test/_require"
Expand Down
14 changes: 2 additions & 12 deletions readme.md
Expand Up @@ -18,7 +18,6 @@ Ky targets [modern browsers](#browser-support) and [Deno](https://github.com/den

It's just a tiny file with no dependencies.


## Benefits over plain `fetch`

- Simpler API
Expand All @@ -31,7 +30,6 @@ It's just a tiny file with no dependencies.
- Instances with custom defaults
- Hooks


## Install

```
Expand All @@ -48,7 +46,6 @@ $ npm install ky
- [jsdelivr](https://www.jsdelivr.com/package/npm/ky)
- [unpkg](https://unpkg.com/ky)


## Usage

```js
Expand Down Expand Up @@ -101,7 +98,6 @@ const ky = require('ky/umd');

With the UMD version, it's also easy to use `ky` [without a bundler](#how-do-i-use-this-without-a-bundler-like-webpack) or module system.


## API

### ky(input, options?)
Expand Down Expand Up @@ -411,10 +407,9 @@ import ky from 'ky';
})();
```


## Tips

### Sending Form Data
### Sending form data

Sending form data in Ky is identical to `fetch`. Just pass a [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) instance to the `body` option. The `Content-Type` header will be automatically set to `multipart/form-data`.

Expand Down Expand Up @@ -479,7 +474,6 @@ setTimeout(() => {
})();
```


## FAQ

#### How do I use this in Node.js?
Expand Down Expand Up @@ -543,23 +537,19 @@ It's just a random short npm package name I managed to get. It does, however, ha

> A form of text-able slang, KY is an abbreviation for 空気読めない (kuuki yomenai), which literally translates into “cannot read the air.” It's a phrase applied to someone who misses the implied meaning.

## Browser support

The latest version of Chrome, Firefox, and Safari.


## Node.js support

Ky requires Node.js 10 or later, but it indicates Node.js 8 in package.json so you can use it with Node.js 8 by polyfilling the globals without having Yarn fail on install. However, you should just use [`ky-universal`](https://github.com/sindresorhus/ky-universal).

Polyfill the needed browser global or just use [`ky-universal`](https://github.com/sindresorhus/ky-universal).

## Related

- [ky-universal](https://github.com/sindresorhus/ky-universal) - Use Ky in both Node.js and browsers
- [got](https://github.com/sindresorhus/got) - Simplified HTTP requests for Node.js


## Maintainers

- [Sindre Sorhus](https://github.com/sindresorhus)
Expand Down
2 changes: 1 addition & 1 deletion test/browser.js
Expand Up @@ -22,7 +22,7 @@ test('prefixUrl option', withPage, async (t, page) => {
return page.evaluate(() => {
return window.ky('/foo', {prefixUrl: '/'});
});
}, /`input` must not begin with a slash when using `prefixUrl`/);
}, {message: /`input` must not begin with a slash when using `prefixUrl`/});

const unprefixed = await page.evaluate(url => {
return window.ky(`${url}/api/unicorn`).text();
Expand Down
30 changes: 18 additions & 12 deletions test/hooks.js
Expand Up @@ -427,13 +427,16 @@ test('catches beforeRetry thrown errors', async t => {
const errorString = 'oops';
const error = new Error(errorString);

await t.throwsAsync(ky.get(server.url, {
hooks: {
beforeRetry: [() => {
throw error;
}]
}
}), errorString);
await t.throwsAsync(
ky.get(server.url, {
hooks: {
beforeRetry: [() => {
throw error;
}]
}
}),
{message: errorString}
);
});

test('catches beforeRetry promise rejections', async t => {
Expand All @@ -453,11 +456,14 @@ test('catches beforeRetry promise rejections', async t => {
const errorString = 'oops';
const error = new Error(errorString);

await t.throwsAsync(ky.get(server.url, {
hooks: {
beforeRetry: [() => Promise.reject(error)]
}
}), errorString);
await t.throwsAsync(
ky.get(server.url, {
hooks: {
beforeRetry: [() => Promise.reject(error)]
}
}),
{message: errorString}
);
});

test('hooks beforeRequest returning Response skips HTTP Request', async t => {
Expand Down
50 changes: 37 additions & 13 deletions test/main.js
Expand Up @@ -111,19 +111,29 @@ test('POST JSON', async t => {
test('cannot use `body` option with GET or HEAD method', t => {
t.throws(() => {
ky.get('https://example.com', {body: 'foobar'});
}, 'Request with GET/HEAD method cannot have body');
}, {
message: 'Request with GET/HEAD method cannot have body'
});

t.throws(() => {
ky.head('https://example.com', {body: 'foobar'});
}, 'Request with GET/HEAD method cannot have body');
}, {
message: 'Request with GET/HEAD method cannot have body'
});
});

test('cannot use `json` option with GET or HEAD method', t => {
t.throws(() => {
ky.get('https://example.com', {json: {}});
}, 'Request with GET/HEAD method cannot have body');
}, {
message: 'Request with GET/HEAD method cannot have body'
});

t.throws(() => {
ky.head('https://example.com', {json: {}});
}, 'Request with GET/HEAD method cannot have body');
}, {
message: 'Request with GET/HEAD method cannot have body'
});
});

test('`json` option overrides the `body` option', async t => {
Expand Down Expand Up @@ -215,7 +225,7 @@ test('.json() with 200 response and empty body', async t => {
response.status(200).end();
});

await t.throwsAsync(ky(server.url).json(), /Unexpected end of JSON input/);
await t.throwsAsync(ky(server.url).json(), {message: /Unexpected end of JSON input/});

await server.close();
});
Expand Down Expand Up @@ -246,7 +256,11 @@ test('timeout option', async t => {
response.end(fixture);
});

await t.throwsAsync(ky(server.url, {timeout: 500}).text(), ky.TimeoutError);
await t.throwsAsync(
ky(server.url, {timeout: 500}).text(),
{instanceOf: ky.TimeoutError}
);

t.is(requestCount, 1);

await server.close();
Expand All @@ -262,7 +276,10 @@ test('timeout:false option', async t => {
response.end(fixture);
});

await t.notThrowsAsync(ky(server.url, {timeout: false}).text(), ky.TimeoutError);
await t.notThrowsAsync(
ky(server.url, {timeout: false}).text()
);

t.is(requestCount, 1);

await server.close();
Expand All @@ -278,7 +295,14 @@ test('invalid timeout option', async t => { // #117
response.end(fixture);
});

await t.throwsAsync(ky(server.url, {timeout: 21474836470}).text(), RangeError, 'The `timeout` option cannot be greater than 2147483647');
await t.throwsAsync(
ky(server.url, {timeout: 21474836470}).text(),
{
instanceOf: RangeError,
message: 'The `timeout` option cannot be greater than 2147483647'
}
);

t.is(requestCount, 0);

await server.close();
Expand Down Expand Up @@ -333,8 +357,7 @@ test('throwHttpErrors option', async t => {
});

await t.notThrowsAsync(
ky.get(server.url, {throwHttpErrors: false}).text(),
/Internal Server Error/
ky.get(server.url, {throwHttpErrors: false}).text()
);

await server.close();
Expand All @@ -347,8 +370,7 @@ test('throwHttpErrors option with POST', async t => {
});

await t.notThrowsAsync(
ky.post(server.url, {throwHttpErrors: false}).text(),
/Internal Server Error/
ky.post(server.url, {throwHttpErrors: false}).text()
);

await server.close();
Expand Down Expand Up @@ -501,7 +523,9 @@ test('supports Request instance as input', async t => {
test('throws when input is not a string, URL, or Request', t => {
t.throws(() => {
ky.get(0);
}, '`input` must be a string, URL, or Request');
}, {
message: '`input` must be a string, URL, or Request'
});
});

test('options override Request instance method', async t => {
Expand Down
4 changes: 3 additions & 1 deletion test/prefix-url.js
Expand Up @@ -25,7 +25,9 @@ test('prefixUrl option', async t => {

t.throws(() => {
ky('/unicorn', {prefixUrl: `${server.url}/api`});
}, '`input` must not begin with a slash when using `prefixUrl`');
}, {
message: '`input` must not begin with a slash when using `prefixUrl`'
});

await server.close();
});

0 comments on commit 7c1d371

Please sign in to comment.