SkillAgentSearch skills...

Thwack

A tiny modern data fetching solution

Install / Use

/learn @donavon/Thwack
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<p align="center"> <img alt="Thwack logo" src="https://user-images.githubusercontent.com/887639/79361317-23cd8880-7f13-11ea-9a80-94f1d7e2eb93.png" width="640"> </p> <h1 align="center"> Thwack. A tiny modern data fetching solution </h1>

npm version Build Status All Contributors Tweet Github stars

<h2> <img alt="Thwack logo" src="https://user-images.githubusercontent.com/887639/79779619-a8037f80-8308-11ea-8c4d-e7193fa15ae8.png" width="22"> TL;DR </h2>

Thwack is:

  • 💻 Modern — Thwack is an HTTP data fetching solution built for modern browsers
  • 🔎 Small — Thwack is only ~1.5k gzipped
  • 👩‍🏫 Smarter — Built with modern JavaScript
  • 😘 Familiar — Thwack uses an Axios-like interface
  • 🅰️ Typed — Easier inclusion for TypeScript projects
  • ✨ Support for NodeJS 10 and 12
  • 📱 Support for React Native

This README is a work in progress. You can also ask me a question on Twitter.

<h2> <img alt="Thwack logo" src="https://user-images.githubusercontent.com/887639/79779619-a8037f80-8308-11ea-8c4d-e7193fa15ae8.png" width="22"> Installation </h2>
$ npm i thwack

or

$ yarn add thwack
<h2> <img alt="Thwack logo" src="https://user-images.githubusercontent.com/887639/79779619-a8037f80-8308-11ea-8c4d-e7193fa15ae8.png" width="22"> Why Thwack over Axios? </h2>

Axios was great when it was released back in the day. It gave us a promise based wrapper around XMLHttpRequest, which was difficult to use. But that was a long time ago and times have changed — browsers have gotten smarter. Maybe it's time for your data fetching solution to keep up?

Thwack was built from the ground up with modern browsers in mind. Because of this, it doesn't have the baggage that Axios has. Axios weighs in at around ~5k gzipped. Thwack, on the other hand, is a slender ~1.5k.

They support the same API, but there are some differences — mainly around options — but for the most part, they should be able to be used interchangeably for many applications.

~~Thwack doesn't try to solve every problem, like Axios does, but instead provides the solution for 98% of what users really need. This is what gives Thwack its feather-light footprint.~~

Scratch that. Thwack provides the same level of power as Axios with a much smaller footprint. And Thwack's promise based event system is easier to use.

<h2> <img alt="Thwack logo" src="https://user-images.githubusercontent.com/887639/79779619-a8037f80-8308-11ea-8c4d-e7193fa15ae8.png" width="22"> Methods </h2>

The following methods are available on all Thwack instances.

Data fetching

  • thwack(url: string [,options: ThwackOptions]): Promise<ThwackResponse>;

  • thwack.request(options: ThwackOptions): Promise<ThwackResponse>

  • thwack.get(url: string [,options: ThwackOptions]): Promise<ThwackResponse>;

  • thwack.delete(url: string [,options: ThwackOptions]): Promise<ThwackResponse>;

  • thwack.head(url: string [,options: ThwackOptions]): Promise<ThwackResponse>;

  • thwack.post(url: string, data:any [,options: ThwackOptions]): Promise<ThwackResponse>;

  • thwack.put(url: string, data:any [,options: ThwackOptions]): Promise<ThwackResponse>;

  • thwack.patch(url: string, data:any [,options: ThwackOptions]): Promise<ThwackResponse>;

Utility

  • thwack.create(options: ThwackOptions): ThwackInstance;

    The create method creates (da!) a new child instance of the current Thwack instance with the given options.

  • thwack.getUri(options: ThwackOptions): string;

    Thwacks URL resolution is RFC-3986 compliant. Axios's is not. It's powered by @thwack/resolve.

Event listeners

Thwack supports the following event types: request, response, data, and error.

For more information on Thwack's event system, see Thwack events below.

  • thwack.addEventListener(type: string, callback: (event:ThwackEvent) => Promise<any> ): void;

  • thwack.removeEventListener(type: string, callback: (event:ThwackEvent) => Promise<any> ): void;

<h2> <img alt="Thwack logo" src="https://user-images.githubusercontent.com/887639/79779619-a8037f80-8308-11ea-8c4d-e7193fa15ae8.png" width="22"> Static Methods </h2>

Concurrency

Thwack has the following helper functions for making simultaneous requests. They are mostly for Axios compatibility. See the "How To" section below for example usage.

  • thwack.all(Promise<ThwackResponse>[])

  • thwack.spread(callback<results>)

<h2> <img alt="Thwack logo" src="https://user-images.githubusercontent.com/887639/79779619-a8037f80-8308-11ea-8c4d-e7193fa15ae8.png" width="22"> ThwackOptions </h2>

The options argument has the following properties.

url

This is either a fully qualified or a relative URL.

baseURL

Defines a base URL that will be used to build a fully qualified URL from url above. Must be an absolute URL or undefined. Defaults to the origin + pathname of the current web page if running in a browser or undefined on Node or React Native.

For example, if you did this:

thwack('foo', {
  baseURL: 'http://example.com',
});

the fetched URL will be:

http://example.com/foo

method

A string containing one of the following HTTP methods: get, post, put, patch, delete, or head.

data

If the method is post, put, or patch, this is the data that will be used to build the request body.

headers

This is where you can place any optional HTTP request headers. Any header you specify here are merged in with any instance header values.

For example, if we set a Thwack instance like this:

const api = thwack.create({
  headers: {
    'x-app-name': 'My Awesome App',
  },
});

Then later, when you use the instance, you make a call like this:

const { data } = await api.get('foo', {
  headers: {
    'some-other-header': 'My Awesome App',
  },
});

The headers that would be sent are:

x-app-name: My Awesome App
some-other-header': 'My Awesome App'

defaults

This allows you to read/set the default options for this instance and, in effect, any child instances.

Example:

thwack.defaults.baseURL = 'https://example.com/api';

For an instance, defaults is the same object passed to create. For example, the following will output "https://example.com/api".

const instance = thwack.create({
  baseURL: 'https://example.com/api',
});
console.log(instance.defaults.baseURL);

Also note that setting defaults on an instance (or even passing options) to an instance does NOT effect the parent. So for the following example, thwack.defaults.baseURL will still be "https://api1.example.net/".

thwack.defaults.baseURL = 'https://api1.example.net/';
const instance = thwack.create();
instance.defaults.baseURL = 'https://example.com/api';

console.log(thwack.defaults.baseURL);

params

This is an optional object that contains the key/value pairs that will be used to build the fetch URL. Is there are any :key segments of the baseURL or the url, they will be replaced with the value of the matching key. For example, if you did this:

thwack('orders/:id', {
  params: { id: 123 },
  baseURL: 'http://example.com',
});

the fetched URL will be:

http://example.com/orders/123

If you don't specify a :name, or there are more params than there are :names, then the remaining key/values will be set as search parameters (i.e. ?key=value).

maxDepth

The maximum level of recursive requests that can be made in a callbck before Thwack throws an error. This is used to prevent an event callback from causing a recursive loop, This if it issues another request without proper safeguards in place. Default = 3.

responseType

By default, Thwack will automatically determine how to decode the response data based on the value of the response header content-type. However, if the server responds with an incorrect value, you can override the parser by setting responseType. Valid values are arraybuffer, document (i.e. formdata), json, text, stream, and blob. Defaults to automatic.

What is returned by Thwack is determined by the following table. The "fetch method" column is what is resolved in data. If you do not specify a responseType, Thwack will automatically determine the fetch method based on content-type and the responseParserMap table (see below).

| Content-Type | responseType | fetch method | | :-------------------: | :------------: | :------------------------------------------------------: | | application/json | json | response.json() | | multipart/form-data | formdata | response.formData() | | text/event-stream | stream | passes back response.body as data without processing | | | blob | response.blob() | | | arraybuffer | response.arrayBuffer() | | */* | text | response.text() |

Note: stream is

View on GitHub
GitHub Stars271
CategoryDevelopment
Updated8mo ago
Forks11

Languages

JavaScript

Security Score

92/100

Audited on Jul 25, 2025

No findings