Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/kouks/awi
Versatile, modern and lightweight http client based on promises.
https://github.com/kouks/awi
ajax client http node promise xhr
Last synced: 18 days ago
JSON representation
Versatile, modern and lightweight http client based on promises.
- Host: GitHub
- URL: https://github.com/kouks/awi
- Owner: kouks
- License: mit
- Created: 2019-02-26T21:17:18.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2023-01-07T03:24:23.000Z (almost 2 years ago)
- Last Synced: 2024-10-16T02:27:48.319Z (29 days ago)
- Topics: ajax, client, http, node, promise, xhr
- Language: TypeScript
- Homepage:
- Size: 1020 KB
- Stars: 8
- Watchers: 2
- Forks: 0
- Open Issues: 17
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README
# Awi
[![npm](https://badge.fury.io/js/awi.svg)](https://www.npmjs.com/package/awi)
[![Travis CI](https://travis-ci.org/kouks/awi.svg?branch=master)](https://travis-ci.org/kouks/awi)
[![coverage](https://codecov.io/gh/kouks/awi/branch/master/graph/badge.svg)](https://codecov.io/gh/kouks/awi)Versatile, modern and lightweight http client based on promises.
## Installation
```bash
npm i -S awi
``````html
```
## Requirements
| Node | Chrome | Edge | Firefox | Opera | Safari |
| :----: | :----: | :--: | :-----: | :---: | :----: |
| 6.13.0 | 52 | 17 | 29 | 19 | 10 |## Usage
### Basics
The most basic of requests can be executed seamlessly with Awi. Simply create
a new instance and call the `get` sugar method with the desired URL. This call
returns an instance of Awi's `Response` interface that has the response body,
status and headers easily accessible.```typescript
import { Awi, Response } from 'awi'const response: Response = await new Awi()
.get('http://server.api/todos')console.assert(typeof response.body === 'object')
console.assert(typeof response.headers === 'object')
console.assert(response.status === 200)
```Awi is at its best when used in TypeScript as you can type-hint all responses
and get type checks and nice auto-completion from your IDE.```typescript
import { Awi, Response } from 'awi'interface TodoResponse extends Response {
body: { title: string, completed: boolean }
}const response: Response = await new Awi()
.get('http://server.api/todos/1')console.assert(typeof response.body.title === 'string')
console.assert(typeof response.body.completed === 'boolean')
```Awi provides syntax sugar for all basic request methods. `POST`, `PUT` and
`PATCH` helpers optionally take the body of the request as their second
argument.```typescript
import { Awi, Response } from 'awi'const response: Response = await new Awi()
.post('http://server.api/todos', { title: 'Start using Awi.', completed: true })console.assert(response.status === 201)
```Upon receiving a 400+ response status, Awi automatically rejects the promise so
that you don't have to do arbitrary checks for the response status via `if`
statements.```typescript
import { Awi } from 'awi'await new Awi()
.post('http://server.api/todos', { completed: false })
.catch(response => console.assert(response.status === 422))
```Awi also provides a `body` helper to avoid repeating the infamous
`.then(res => res.body)` promise callback. This helper accepts a generic type
to type-hint the response body.> Note that this helper sends a `GET` request by default. If you desire to use
> a different request method, the method needs to be specified using
> an [interceptor](#interceptors).> Also note that if the promise is rejected, the whole response object is
> returned.```typescript
import { Awi } from 'awi'interface Todo {
title: string
completed: boolean
}const todo: Todo = await new Awi()
.body('http://server.api/todos/1')console.assert(typeof todo.title === 'string')
console.assert(typeof todo.completed === 'boolean')
```Thanks to [@bausano](https://github.com/bausano) and his awesome
[data structures package](https://github.com/bausano/ts-data-structures), Awi
has an `optional` helper that returns the body of the response as an
`Optional` rather than rejecting the promise.> Note that this helper sends a `GET` request by default. If you desire to use
> a different request method, the method needs to be specified using
> an [interceptor](#interceptors).> Also note that if the request fails due to network issues or misconfiguration,
> the promise is still rejected.```typescript
import { Awi, Optional } from 'awi'interface Todo {
title: string
completed: boolean
}const todo: Optional = await new Awi()
.optional('http://server.api/todos/1')console.assert(todo instanceof Optional)
```### Interceptors
Request interceptors are what makes Awi stand out. Inspired by
[Koa](https://koajs.com/), Awi provides a `use` method that accepts an
asynchronous callback that modifies the request object.```typescript
import { Awi, Response } from 'awi'const response: Response = await new Awi()
.use(async req => req.base = 'http://server.api')
.use(async req => req.path = 'todos')
.get()console.assert(response.status === 200))
```> All properties that can be modified on the request object are available in
> Awi's [API reference](https://github.com/kouks/awi/wiki/Request).Every request in Awi is uniquely defined by the array of interceptors assigned
to the request. All Awi's helper methods are nothing more but a sugar for
assigning interceptors. All requests can be sent without using the helpers via
the `send` method.```typescript
import { Awi, Method, Response } from 'awi'const response: Response = await new Awi()
.use(async req => req.base = 'http://server.api')
.use(async req => req.path = 'todos')
.use(async req => req.method = Method.GET)
.send()console.assert(response.status === 200))
```> Although this approach is rather lenghty and using helpers is much cleaner, it
> provides a straightforward way to extend Awi and/or create request templates.As you can see, the interceptor concept provides a way to create request
templates for your application in a very nice and reusable way. This can be
especially useful when making authorized requests.```typescript
import { Awi, Response } from 'awi'// Define the template to be reused.
const auth = () => new Awi()
.use(async req => req.base = 'http://server.api')
.use(async req => req.headers['authorization'] = `Bearer ${localStorage.token}`)// Use the template and provide further parameters.
const response: Response = await auth()
.get('user')console.assert(response.status === 200))
```### API Reference
All of Awi's functionality is summed up on the
[wiki page](https://github.com/kouks/awi/wiki/API-Reference).## Why Awi?
**It's lightweight**
The minified file size is 12kB and we do not intend to make it bigger!
**It's designed for developers, by developers**
Making http requests is something every developer needs to do on daily basis,
especially when it comes to TypeScript or JavaScript. Awi has a neat code base,
is strictly typed and we purposefully leave documentation blocks in the built
files - this way, you can read up on what each method does by simply
ctrl-clicking on it!**It's flexible**
You can either choose to go the easy way and using Awi's built-in helpers to
execute your HTTP request as a one-liner, or you can define and extract reusable
templates for your requests from scratch!Awi is also open-source, so should you be missing any features that would make
your life easier, feel free to contribute.## Credits
The interceptor pattern is heavily inspired by [Koa](https://koajs.com/), which
is also used to create a mock server for our e2e tests.Implemetation of executors for both web and node are inspired by no other than
[axios](https://github.com/axios/axios).## License
MIT