README
@tkrotoff/fetch
A Fetch wrapper.
- Simplifies the use of Fetch
- Tiny: less than 200 lines of code
- No dependencies
- Fully tested
- Written in TypeScript
- Comes with test utilities
Why?
When using Fetch, you must write some boilerplate:
const url = 'https://example.com/profile';
const data = { username: 'example' };
try {
const response = await fetch(url, {
method: 'POST',
body: JSON.stringify(data),
headers: {
'content-type': 'application/json'
}
});
if (!response.ok) {
throw new Error('Network response was not ok');
}
const json = await response.json();
console.log('Success:', json);
} catch (e) {
console.error('Error:', e);
}
With @tkrotoff/fetch it becomes:
try {
const response = await postJSON(url, data).json();
console.log('Success:', response);
} catch (e /* HttpError | TypeError | DOMException */) {
console.error('Error:', e);
}
You don't have to worry about:
- HTTP headers: Accept and Content-Type are already set
- stringifying the request body
- One
await
instead of two - No need to manually throw an exception on HTTP error status (like 404 or 500)
Usage
Examples:
- https://codesandbox.io/s/github/tkrotoff/fetch/tree/codesandbox.io/examples/web
- https://codesandbox.io/s/github/tkrotoff/fetch/tree/codesandbox.io/examples/node
npm install @tkrotoff/fetch
import { defaults, postJSON } from '@tkrotoff/fetch';
defaults.init = { /* ... */ };
const response = await postJSON(
'https://jsonplaceholder.typicode.com/posts',
{
title: 'foo',
body: 'bar',
userId: 1
}
).json();
console.log(response);
Or copy-paste Http.ts into your source code.
JavaScript runtimes support
@tkrotoff/fetch supports Node.js, all modern browsers + IE 11
With Node.js you need:
Check examples/node
With IE 11 you need:
- whatwg-fetch polyfill
- core-js for other modern JS features like async/await
- to transpile @tkrotoff/fetch code to ES5
Check examples/web
API
get(input:
RequestInfo
, init?:
RequestInit
): ResponsePromiseWithBodyMethods
post(input: RequestInfo, body:
BodyInit
, init?: RequestInit): ResponsePromiseWithBodyMethods
postJSON(input: RequestInfo, body: object, init?: RequestInit): ResponsePromiseWithBodyMethods
put(input: RequestInfo, body: BodyInit, init?: Init): ResponsePromiseWithBodyMethods
putJSON(input: RequestInfo, body: object, init?: RequestInit): ResponsePromiseWithBodyMethods
patch(input: RequestInfo, body: BodyInit, init?: Init): ResponsePromiseWithBodyMethods
patchJSON(input: RequestInfo, body: object, init?: RequestInit): ResponsePromiseWithBodyMethods
del(input: RequestInfo, init?: RequestInit): ResponsePromiseWithBodyMethods
isJSONResponse(response:
Response
): boolean
ResponsePromiseWithBodyMethods
being Promise<
Response
>
with added methods from Body
.
HttpError
@tkrotoff/fetch throws HttpError
with a response
property when the HTTP status code is < 200
or >= 300
.
Test utilities
createResponsePromise(body?:
BodyInit
, init?:
ResponseInit
): ResponsePromiseWithBodyMethods
createJSONResponsePromise(body: object, init?: ResponseInit): ResponsePromiseWithBodyMethods
createHttpError(body?: BodyInit, status = 0, statusText?: string): HttpError
createJSONHttpError(body: object, status = 0, statusText?: string): HttpError
HttpStatus
Instead of writing HTTP statuses as numbers 201
, 403
, 503
... you can replace them with HttpStatus
and write more explicit code:
import { HttpStatus } from '@tkrotoff/fetch';
console.log(HttpStatus._201_Created);
console.log(HttpStatus._403_Forbidden);
console.log(HttpStatus._503_ServiceUnavailable);
Configuration
@tkrotoff/fetch exposes defaults.init
that will be applied to every request.
import { defaults } from '@tkrotoff/fetch';
defaults.init.mode = 'cors';
defaults.init.credentials = 'include';
Testing
When testing your code, use createResponsePromise()
and createJSONResponsePromise()
:
import * as Http from '@tkrotoff/fetch';
test('OK', async () => {
const getSpy = jest.spyOn(Http, 'get').mockImplementation(() =>
Http.createResponsePromise('test')
);
const response = await Http.get(url).text();
expect(response).toEqual('test');
expect(getSpy).toHaveBeenCalledTimes(1);
expect(getSpy).toHaveBeenCalledWith(url);
getSpy.mockRestore();
});
test('fail', async () => {
const getSpy = jest.spyOn(Http, 'get').mockImplementation(() =>
Http.createResponsePromise('<!DOCTYPE html><title>404</title>', {
status: 404,
statusText: 'Not Found'
})
);
await expect(Http.get(url).text()).rejects.toThrow('Not Found');
expect(getSpy).toHaveBeenCalledTimes(1);
expect(getSpy).toHaveBeenCalledWith(url);
getSpy.mockRestore();
});
Check examples/node and examples/web.