npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

awi

v0.0.11

Published

Versatile, modern and lightweight http client based on promises.

Downloads

14

Readme

Awi

npm Travis CI coverage

Versatile, modern and lightweight http client based on promises.

Installation

npm i -S awi
<script src="https://cdn.jsdelivr.net/npm/awi/dist/awi.js"></script>

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.

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.

import { Awi, Response } from 'awi'

interface TodoResponse extends Response {
  body: { title: string, completed: boolean }
}

const response: Response = await new Awi()
  .get<TodoResponse>('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.

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.

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.

Also note that if the promise is rejected, the whole response object is returned.

import { Awi } from 'awi'

interface Todo {
  title: string
  completed: boolean
}

const todo: Todo = await new Awi()
  .body<Todo>('http://server.api/todos/1')

console.assert(typeof todo.title === 'string')
console.assert(typeof todo.completed === 'boolean')

Thanks to @bausano and his awesome data structures package, Awi has an optional helper that returns the body of the response as an Optional<T> 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.

Also note that if the request fails due to network issues or misconfiguration, the promise is still rejected.

import { Awi, Optional } from 'awi'

interface Todo {
  title: string
  completed: boolean
}

const todo: Optional<Todo> = await new Awi()
  .optional<Todo>('http://server.api/todos/1')

console.assert(todo instanceof Optional)

Interceptors

Request interceptors are what makes Awi stand out. Inspired by Koa, Awi provides a use method that accepts an asynchronous callback that modifies the request object.

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.

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.

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.

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.

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, 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.

License

MIT