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

xhttp

v0.15.3

Published

Tiny shortcuts for using the native fetch API. Provides a fluent builder-style API for request building and response reading.

Downloads

281

Readme

Overview

Tiny syntactic shortcuts for native Request/Response/Headers/fetch.

  • Fluent builder-style API.
  • Interoperable with built-ins.
  • Shortcuts for common actions, such as:
    • Building HTTP requests.
      • A builder-style API is more concise and flexible than the native one.
    • Handling HTTP errors in responses.
      • Constructing descriptive exceptions with HTTP status and response text.
  • Tiny, dependency-free, single file, native module.

TOC

Usage

In browsers and Deno, import by URL:

import * as h from 'https://cdn.jsdelivr.net/npm/[email protected]/xhttp.mjs'

When using Node or NPM-oriented bundlers like Esbuild:

npm i -E xhttp

Example usage:

const reqBody = {msg: `hello world`}
const resBody = await h.req().to(`/api`).post().json(reqBody).fetchOkJson()

API

function req

Same as #new Req but syntactically shorter.

class Err

Subclass of Error for HTTP responses. The error message includes the HTTP status code, if any.

class Err extends Error {
  message: string
  status: int
  res?: Response

  constructor(message: string, status: int, res?: Response)
}

class Req

Request builder. Does not subclass Request. Call .req() to create a native request, or the various .fetchX() methods to immediately execute. Unlike the native request, the body is not always a stream. This means Req can be stored and reused several times.

class Req extends RequestInit {
  /*
  Similar to `fetch(this.req())`, but also constructs `Res` from the resulting
  response.
  */
  fetch(): Promise<Res>

  /*
  Returns the resulting `Res` if the response is OK. If the response is
  received, but HTTP status code is non-OK, throws a descriptive `Err`.

  Shortcut for `(await this.fetch()).okRes()`.
  */
  fetchOk(): Promise<Res>

  // Shortcut for `(await this.fetch()).okText()`.
  fetchOkText(): Promise<string>

  // Shortcut for `(await this.fetch()).okJson()`.
  fetchOkJson(): Promise<any>

  /*
  Mutates the request by applying the given options and returns the same
  reference. Automatically merges headers.
  */
  mut(init: RequestInit): Req

  // Shortcut for `new Request(this.url, this)`.
  req(): Request

  // Sets `.url` and returns the same reference.
  to(val: string | {toString(): string}): Res

  // Sets `.signal` and returns the same reference.
  sig(val: AbortSignal): Res

  // Sets `.method` and returns the same reference.
  meth(val: string): Res

  // Sets `.body` and returns the same reference. Short for "input".
  inp(val: BodyInit): Res

  // JSON-encodes the input, sets `.body`, and sets JSON request headers.
  // Does NOT set the `accept` header. Returns the same reference.
  json(val: any): Res

  // Shortcuts for setting the corresponding HTTP method.
  get(): Res
  post(): Res
  put(): Res
  patch(): Res
  delete(): Res

  // Idempotently sets `.headers` and returns the resulting reference.
  head(): Head

  // Shortcuts for modifying the headers. All mutate and return the request.
  headSet(key, val: string): Res
  headAppend(key, val: string): Res
  headDelete(key: string): Res
  headMut(src: Headers | Record<string, string>): Res

  // Class used for `.headers`. Can override in subclass.
  get Head(): {new(): Head}

  // Class used for responses. Can override in subclass.
  get Res(): {new(): Res; static from(res: Response): Res}
}

class Res

Subclass of Response with additional shortcuts for response handling. Always wraps a native response received from another source. #Req automatically uses this for responses. You don't need to construct this.

class Res extends Response {
  // Reference to the wrapped response.
  res: Response

  /*
  Same as the native constructor, but takes an additional response reference
  to wrap. Defers the following getters to the original:

    get redirected
    get type
    get url
  */
  constructor(body?: BodyInit | null, init?: ResponseInit, res: Response)

  /*
  If `res.ok`, returns the response as-is. Otherwise throws an instance of
  `Err` with the status code and response text in its error message.
  */
  okRes(): Promise<Res>

  /*
  Shortcut for `(await this.okRes()).text()`. On unsuccessful response,
  throws a descriptive error. On success, returns response text.
  */
  okText(): Promise<string>

  /*
  Shortcut for `(await this.okRes()).json()`. On unsuccessful response,
  throws a descriptive error. On success, returns decoded JSON.
  */
  okJson(): Promise<any>

  // Class used for response errors. Can override in subclass.
  get Err(): {new(): Err}

  // Shortcut for constructing from another response.
  static from(res: Response): Res
}

class Head

Subclass of Headers with additional shortcuts. Used internally by Req.

class Head extends Headers {
  /*
  Merges the headers from the given source into the receiver. Mutates and
  returns the same reference.
  */
  mut(src: Headers | Record<string, string>): Head

  /*
  Overrides `Headers.prototype.set` to return the same reference, instead of
  void. Also asserts input types.
  */
  set(key, val: string): Head

  /*
  Overrides `Headers.prototype.append` to return the same reference, instead of
  void. Also asserts input types.
  */
  append(key, val: string): Head

  /*
  Similar to `.set`, but does nothing if the key is already present, or if the
  value is empty.
  */
  setOpt(key: string, val?: string): Head

  /*
  Similar to `Set.prototype.clear`. Removes all content. Mutates and returns
  the same reference.
  */
  clear(): Head
}

function jsonDecode

Sanity-checking wrapper for JSON.parse. If the input is nil or an empty string, returns null. Otherwise the input must be a primitive string. Throws on other inputs, without trying to stringify them.

function jsonEncode

Sanity-checking wrapper for JSON.stringify. Equivalent to JSON.stringify(val ?? null). If the input is undefined, returns 'null' (string) rather than undefined (nil). Output is always a valid JSON string.

Undocumented

Some APIs are exported but undocumented to avoid bloating the docs. Check the source files and look for export.

Changelog

0.15.3

Add Head..setOpt, Res..Err. Minor bugfixes.

0.15.2

Bugfix for previous version.

0.15.1

Add req shortcut.

0.15.0

Full revision.

  • Now provides shortcuts for fetch and other built-ins.
  • Now provides only 1 module for all environments.
  • No longer uses Node APIs.
  • No longer uses XMLHttpRequest.

License

https://unlicense.org

Misc

I'm receptive to suggestions. If this library almost satisfies you but needs changes, open an issue or chat me up. Contacts: https://mitranim.com/#contacts