{"id":11299,"library":"meros","title":"Meros: Multipart Response Utility","description":"Meros is a lightweight (642B gzipped) utility designed to simplify the parsing of `multipart/mixed` HTTP responses, a common pattern in technologies like GraphQL for deferred or streamed results. Currently at version 1.3.2, the project appears actively maintained with a stable release cadence. Its key differentiators include a zero-dependency runtime, a minimal footprint, high performance, and seamless integration with `fetch` and `rxjs`. It supports both Node.js (requiring `node >=13`) and browser environments, automatically parsing JSON content within parts. Meros returns an `AsyncGenerator` for `multipart/mixed` responses, or the original `Response` object for other content types, offering flexibility for use in middleware or chained `fetch` calls.","status":"active","version":"1.3.2","language":"javascript","source_language":"en","source_url":"https://github.com/maraisr/meros","tags":["javascript","defer","fetch","graphql","multipart mixed","multipart","reader","stream","utility","typescript"],"install":[{"cmd":"npm install meros","lang":"bash","label":"npm"},{"cmd":"yarn add meros","lang":"bash","label":"yarn"},{"cmd":"pnpm add meros","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Provides type definitions for Node.js environments when using TypeScript; a peer dependency for proper type checking.","package":"@types/node","optional":false}],"imports":[{"note":"Meros exclusively uses named exports. The main 'meros' import relies on bundler or environment detection to serve the correct version. For explicit control and potential optimizations, consider using environment-specific subpath imports (`meros/browser` or `meros/node`).","wrong":"import meros from 'meros';","symbol":"meros","correct":"import { meros } from 'meros';"},{"note":"This import explicitly targets browser environments. It's recommended when building for the web to ensure correct module resolution and take advantage of any browser-specific optimizations or tree-shaking by bundlers.","wrong":"import { meros } from 'meros';","symbol":"meros (Browser)","correct":"import { meros } from 'meros/browser';"},{"note":"This import explicitly targets Node.js environments (requires `node >=13`). It's recommended for server-side applications to ensure correct module resolution and access to Node.js-specific streaming interfaces. The package is designed for ESM usage.","wrong":"const { meros } = require('meros/node');","symbol":"meros (Node.js)","correct":"import { meros } from 'meros/node';"}],"quickstart":{"code":"import { meros } from 'meros';\n\nasync function fetchAndProcessMultipart() {\n  // Simulate a multipart/mixed response or a regular JSON response\n  // In a real application, replace with your actual fetch call\n  const mockFetch = async (url: string) => {\n    if (url === '/api/multipart') {\n      // Example multipart response\n      return new Response(\n        `--boundary\\r\\nContent-Type: application/json\\r\\n\\r\\n{\"data\": \"part1\"}\\r\\n--boundary\\r\\nContent-Type: text/plain\\r\\n\\r\\nhello from part 2\\r\\n--boundary--`,\n        {\n          headers: { 'Content-Type': 'multipart/mixed; boundary=boundary' }\n        }\n      );\n    } else {\n      // Example non-multipart JSON response\n      return new Response(JSON.stringify({ message: 'Not multipart' }), {\n        headers: { 'Content-Type': 'application/json' }\n      });\n    }\n  };\n\n  try {\n    const response = await mockFetch('/api/multipart'); // Try with '/api/json' to see the other path\n    const parts = await meros(response);\n\n    if (parts && typeof (parts as any)[Symbol.asyncIterator] === 'function') {\n      console.log('Processing multipart response:');\n      for await (const part of parts) {\n        if (part.json) {\n          console.log('  JSON Part:', part.body);\n        } else {\n          console.log('  Text/Other Part:', new TextDecoder().decode(part.body as Uint8Array));\n        }\n      }\n    } else {\n      console.log('Not a multipart response, processing as regular response:');\n      const data = await (parts as Response).json();\n      console.log('  Response Data:', data);\n    }\n  } catch (error) {\n    console.error('Error fetching or processing:', error);\n  }\n}\n\nfetchAndProcessMultipart();","lang":"typescript","description":"Demonstrates fetching a response, processing it with `meros`, and gracefully handling both `multipart/mixed` and non-multipart (e.g., JSON) responses using an async generator pattern."},"warnings":[{"fix":"Implement a runtime check for the return value, such as `if (parts && typeof (parts as any)[Symbol.asyncIterator] === 'function')` to safely differentiate between an iterable of parts and the raw Response object.","message":"Meros returns an `AsyncGenerator<Part>` only if the `content-type` HTTP header is `multipart/mixed`. For any other content type, it resolves with the original `Response` object. Developers must explicitly check the return type before attempting to iterate over `parts`.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"For explicit and robust environment targeting, use the specific subpath imports: `import { meros } from 'meros/browser';` for browser-based applications, or `import { meros } from 'meros/node';` for Node.js environments.","message":"The main `meros` entry point (`import { meros } from 'meros';`) relies on bundler or environment detection to load the correct browser or Node.js-specific code. This can sometimes lead to unexpected behavior or larger bundle sizes if not configured correctly, or if a browser build is incorrectly served in Node or vice-versa.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Before iterating, always check if the returned `parts` object is an async iterable using `if (parts && typeof (parts as any)[Symbol.asyncIterator] === 'function')`. If not, process `parts` as a standard `Response` object (e.g., `parts.json()`).","cause":"This error occurs when attempting to use `for await (const part of parts)` on the value returned by `meros` when the HTTP response's `Content-Type` header was not `multipart/mixed`. In such cases, `meros` returns the original `Response` object, which is not an async iterable.","error":"TypeError: parts is not async iterable"},{"fix":"Meros is primarily designed for ESM. Update your import statements to use `import { meros } from 'meros';` (or specific subpath imports) and ensure your project's `package.json` specifies `\"type\": \"module\"` or your build setup correctly handles ESM.","cause":"Attempting to use `require('meros')` or `require('meros/node')` in an environment that expects ECMAScript Modules (ESM) syntax, such as a modern Node.js project or a browser module without proper CommonJS transpilation.","error":"ReferenceError: require is not defined"}],"ecosystem":"npm"}