Skip to main content
This guide will help you get up and running with Meros quickly. You’ll learn how to handle multipart responses in both browser and Node.js environments with real working examples.

Installation

1

Install Meros

Install Meros using your preferred package manager:
npm install meros
2

Import and use

Meros automatically detects your environment (browser or Node.js):
import { meros } from 'meros';

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

for await (const part of parts) {
  console.log(part.body);
}

Basic usage

Browser example

Here’s a complete browser example that fetches and displays multipart data:
import { meros } from 'meros';

async function run() {
  const app = document.querySelector('#app');

  const parts = await fetch('/data').then((r) =>
    meros<{ letter: string }>(r)
  );

  for await (let part of parts) {
    const el = document.createElement('div');
    el.innerText = part.body.letter;
    app.appendChild(el);
  }
}

if (document.readyState !== 'complete') run();
else window.addEventListener('load', run);
You can also import directly from meros/browser for browser-specific builds, or use https://cdn.skypack.dev/meros for CDN access.

Node.js example

For Node.js, use the meros/node import:
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);

for await (const part of parts) {
  console.log(part.body);
}

Understanding the Part object

Each part yielded by Meros follows this structure:
When the part contains JSON data:
{
  json: true,
  headers: { 'content-type': 'application/json' },
  body: { /* your parsed JSON object */ }
}
The Part type gives you:
  • json: boolean - Indicates if the body is a parsed JavaScript object
  • headers: object - Key-value pairs of all headers from this part
  • body: T | Fallback - The part’s body, either as a JavaScript object (when json is true) or as the base type (Buffer for Node.js, string for browser)

Using the multiple mode

The multiple option is an optimization technique that yields all available parts of a chunk at once, rather than yielding once per part. This is particularly useful for technologies like GraphQL where you can process multiple parts synchronously.
const chunks = await fetch('/api').then((response) => 
  meros(response, { multiple: true })
);

for await (const parts of chunks) {
  // parts is now an array
  for (const part of parts) {
    console.log(part.body);
  }
}
Setting multiple: true changes the behavior to yield arrays instead of individual parts. Make sure to adjust your code accordingly.

Working with RxJS

Meros integrates seamlessly with RxJS streams:
import { meros } from 'meros';
import { from } from 'rxjs';

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

from(parts).subscribe((part) => {
  if (part.json) {
    console.log('JSON data:', part.body);
  } else {
    console.log('Raw data:', part.body);
  }
});

GraphQL defer and stream directives

Meros is designed to work with GraphQL’s @defer and @stream directives for incremental delivery:
import { meros } from 'meros';

interface GraphQLResponse {
  data?: any;
  errors?: any[];
  hasNext?: boolean;
}

const parts = await fetch('/graphql', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    query: `
      query {
        user {
          id
          name
          ... @defer {
            posts {
              title
            }
          }
        }
      }
    `
  })
}).then((r) => meros<GraphQLResponse>(r, { multiple: true }));

for await (const batch of parts) {
  for (const part of batch) {
    if (part.json) {
      // Process GraphQL response
      if (part.body.data) {
        console.log('Data chunk:', part.body.data);
      }
      if (part.body.errors) {
        console.error('Errors:', part.body.errors);
      }
    }
  }
}
Use multiple: true with GraphQL to batch process multiple deferred fragments that arrive in the same chunk.

Handling non-multipart responses

Meros will return the original response if the content type is not multipart. This makes it safe to use as middleware:
import { meros } from 'meros';

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

if (parts[Symbol.asyncIterator]) {
  // It's multipart - iterate over parts
  for await (const part of parts) {
    console.log(part.body);
  }
} else {
  // It's a regular response - handle normally
  const data = await parts.json();
  console.log(data);
}
Meros returns the original response unchanged when the content type is not multipart/mixed, making it perfect for middleware chains.

Error handling

Handle errors gracefully when working with multipart streams:
import { meros } from 'meros';

try {
  const parts = await fetch('/api').then(meros);
  
  for await (const part of parts) {
    try {
      if (part.json) {
        // Process JSON part
        console.log(part.body);
      } else {
        // Process raw part
        console.log(part.body.toString());
      }
    } catch (partError) {
      console.error('Error processing part:', partError);
      // Continue processing other parts
    }
  }
} catch (error) {
  console.error('Error fetching or parsing multipart response:', error);
}

Type safety with TypeScript

Meros provides full TypeScript support with generic types:
import { meros } from 'meros';
import type { Part } from 'meros';

interface User {
  id: string;
  name: string;
  email: string;
}

const parts = await fetch('/users').then((r) => meros<User>(r));

for await (const part of parts) {
  if (part.json) {
    // part.body is typed as User
    console.log(part.body.name);
  }
}

Next steps

API Reference

Explore the complete API documentation

Examples

See more real-world examples

Guides

Learn environment-specific usage patterns

Performance

Understand Meros performance characteristics

Build docs developers (and LLMs) love