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

meros

v1.3.0

Published

A fast 642B utility that makes reading multipart responses simple

Downloads

14,111,761

Readme

npm add meros makes reading multipart responses simple

npm stats bundle size

⚡ Features

  • No dependencies
  • Seemless api
  • Super performant
  • Supports any[^1] content-type
  • preamble and epilogue don't yield
  • Browser/Node Compatible
  • Plugs into existing libraries like Relay and rxjs

[^1]: By default, we'll look for JSON, and parse that for you. If not, we'll give you the body as what was streamed.

🚀 Usage

Visit /examples for more info!

// Relies on bundler/environment detection
import { meros } from 'meros';

const parts = await fetch('/api').then(meros);

// As a simple Async Generator
for await (const part of parts) {
  // Do something with this part
}

// Used with rxjs streams
from(parts).subscribe((part) => {
  // Do something with it
});

Specific Environment

Browser

import { meros } from 'meros/browser';
// import { meros } from 'https://cdn.skypack.dev/meros';

const parts = await fetch('/api').then(meros);

Node

import http from 'http';
import { meros } from 'meros/node';

const response = await new Promise((resolve) => {
  const request = http.get(`http://example.com/api`, (response) => {
    resolve(response);
  });
  request.end();
});

const parts = await meros(response);

🔎 API

Meros offers two flavours, both for the browser and for node; but their api's are fundamentally the same.

Note: The type Response is used loosely here and simply alludes to Node's IncomingMessage or the browser's Response type.

meros(response: Response, options?: Options)

Returns: Promise<Response | AsyncGenerator<Part | Part[]>

Meros returns a promise that will resolve to an AsyncGenerator if the response is of multipart/mixed mime, or simply returns the Response if something else; helpful for middlewares. The idea here being that you run meros as a chain off fetch.

fetch('/api').then(meros);

If the content-type is NOT a multipart, then meros will resolve with the response argument.

import { meros } from 'meros';

const response = await fetch('/api'); // Assume this isnt multipart
const parts = await meros(response);

if (parts[Symbol.asyncIterator] < 'u') {
  for await (const part of parts) {
    // Do something with this part
  }
} else {
  const data = await parts.json();
}

each Part gives you access to:

  • json: boolean ~ Tells you the body would be a JavaScript object of your defined generic T.
  • headers: object ~ A key-value pair of all headers discovered from this part.
  • body: T | Fallback ~ Is the body of the part, either as a JavaScript object (noted by json) or the base type of the environment (Buffer | string, for Node and Browser respectively).

options.multiple: boolean

Default: false

Setting this to true will yield once for all available parts of a chunk, rather than yielding once per part. This is an optimization technique for technologies like GraphQL where rather than commit the payload to the store, to be added-to in the next process-tick we can simply do that synchronously.

Warning: This will alter the behaviour and yield arrays—than yield payloads.

const chunks = await fetch('/api').then((response) => meros(response, { multiple: true }));

// As a simple Async Generator
for await (const parts of chunks) {
  for (const part of parts) {
    // Do something with this part, maybe aggregate?
  }
}

💨 Benchmark

via the /bench directory with Node v18.0.0

Node
✔ meros        ~ 1,271,218 ops/sec ± 0.84%
✘ it-multipart ~   700,039 ops/sec ± 0.72%
--
it-multipart (FAILED @ "should match reference patch set")

Browser
✔ meros                   ~ 800,941 ops/sec ± 1.06%
✘ fetch-multipart-graphql ~ 502,175 ops/sec ± 0.75%
--
fetch-multipart-graphql (FAILED @ "should match reference patch set")

🎒 Notes

Why the name? meros comes from Ancient Greek μέρος méros, meaning "part".

This library aims to implement RFC1341 in its entirety, however we aren't there yet. That being said, you may very well use this library in other scenarios like streaming in file form uploads.

Another goal here is to aide in being the defacto standard transport library to support @defer and @stream GraphQL directives

Caveats

  • No support the /alternative , /digest or /parallel subtype at this time.
  • No support for nested multiparts

❤ Thanks

Special thanks to Luke Edwards for performance guidance and high level api design.

😇 Compassion

This library is simple, a meer few hundred bytes. It's easy to copy, and easy to alter. If you do, that is fine ❤️ im all for the freedom of software. But please give credit where credit is due.

License

MIT © Marais Rossouw