An open API service indexing awesome lists of open source software.

https://github.com/bigskysoftware/rexi

rexi.js - a companion to fixi.js
https://github.com/bigskysoftware/rexi

Last synced: about 2 months ago
JSON representation

rexi.js - a companion to fixi.js

Awesome Lists containing this project

README

          

🐕 rexi.js - a fluent little fetch...

rexi.js is an experimental, minimalist fetch wrapper with HTTP-verb shortcuts, form
serialization, chainable body parsers, and throw-on-error semantics. It's the JSON-side
companion for the [fixi.js](https://github.com/bigskysoftware/fixi) family: for the times
you do need to talk to an API from client code.

Part of the [fixi project](https://fixiproject.org).

Here is an example:

```html

let me = await get("/api/me").json()
await post("/api/login", document.forms.login) // form element
await post("/api/users", {name: "Ada"}) // JSON body
await get("/search", {q: "hi"}, {include: "#filters"}) // query string + extra fields

```

Six verb helpers (`get`, `head`, `post`, `put`, `patch`, `del`) are attached to
`globalThis` for zero-ceremony use. Each returns a decorated `Promise` with
`.json()`, `.text()`, `.blob()`, `.html()`, `.raw()`, and `.abort()` sugar so the common
case is one `await`.

## Minimalism

rexi is deliberately tiny: no interceptor pipeline, no retry logic, no automatic base
URL, no upload progress, no caching layer, no built-in download helper. If your app
outgrows it, reach for [ky](https://github.com/sindresorhus/ky) or
[wretch](https://github.com/elbywan/wretch).

## Installing

Drop `rexi.js` into a script tag:

```html

```

Or install via npm:

```
npm install rexi-js
```

## API

### Verbs

All six verbs share the same shape:

```
get|head|post|put|patch|del(url, body?, opts?)
```

`del` is used instead of `delete` because bare `delete(x)` is a JavaScript syntax trap.
Both `rexi.del` and `window.del` are exposed.

### Body normalization

The second positional arg is a logical "input". Its type decides the wire format:

| Input | Sent as |
|-------------------------------------------|----------------------------------------------------|
| `FormData` | as-is |
| `HTMLFormElement` | `new FormData(el)` |
| single named input element | `FormData` with one `[name, value]` entry |
| iterable of elements (e.g. moxi `q(...)`) | `FormData` collecting each element's `[name,value]`|
| plain object | `JSON.stringify`, `Content-Type: application/json` |
| `string` / `Blob` / `URLSearchParams` / `ArrayBuffer` | passed straight to fetch |
| `null` / `undefined` | no body |

### Method disposition

By default `GET` / `HEAD` / `DEL` URL-encode the body into the query string (with
repeating keys for array values), and `POST` / `PUT` / `PATCH` send it in the request
body. Override with `opts.send: "query" | "body"`.

### Options

```js
{
include: selector | Element | iterable | Array, // merge extra form fields
send: "query" | "body", // override method default
timeout: ms, // abort after N ms
signal: AbortSignal, // external cancel, chains in
headers: {...}, // merged with auto Content-Type
... // passed through to fetch()
}
```

`include` with a JSON body promotes the request to form mode (the JSON object is
flattened into FormData entries).

### Response helpers

```js
let p = get(url, body, opts)
await p.json() // parsed JSON
await p.text() // string
await p.blob() // Blob
await p.html() // DocumentFragment (parsed via )
await p.raw() // the raw Response
p.abort() // cancel the underlying fetch
```

Non-2xx responses throw an `Error` carrying `.status` and `.response` (the raw
Response, for bodies/headers).

### Lifecycle events

rexi dispatches two CustomEvents on `document`:

* `rexi:before` - cancelable; `detail.cfg = {url, init}` can be mutated (e.g. to inject
an `Authorization` header). `preventDefault()` aborts the request with `AbortError`.
* `rexi:after` - fires for every completed fetch (including non-2xx, before rexi
throws); `detail = {cfg, response}`.

```js
document.addEventListener("rexi:before", (e) => {
e.detail.cfg.init.headers.Authorization = `Bearer ${token}`
})
```

## LICENCE

```
Zero-Clause BSD
=============

Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE
FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
```