Registry / serialization / multitars

multitars

JSON →
library1.0.0jsnpmunverified

multitars is a JavaScript library providing memory-efficient parsing and production of Tar archives and `multipart/form-data` bodies, built entirely on the Web Streams API. It is currently at version 1.0.0, indicating a stable API after several pre-1.0.0 releases that focused on performance and feature additions. The library's core differentiator is its ability to process arbitrarily-sized stream data without buffering it in full, making it ideal for environments like serverless functions, browsers, and Node.js applications that require efficient handling of large binary data streams. It aims to offer Tar format support comparable to `node-tar`, including PAX headers, and provides both parsing and streaming utilities for both formats.

npm install multitars
INSTALL
IMPORT
SIG · MULTITARS
M
multitars
serializationjavascriptv1.0.0
Install
Import
Disk
Pass rate
0/ 6
Env Coverage0 / 6
glibc
1822
musl
1822
Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
node 18226 runs
build_error
glibc
node 18226 runs
build_error
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

parseMultipart
import { parseMultipart } from 'multitars';
const parseMultipart = require('multitars');
multitars is an ESM-only package. `parseMultipart` returns an AsyncGenerator.
streamMultipart
import { streamMultipart, FormEntry } from 'multitars';
import { streamMultipart } from 'multitars/dist/streamMultipart';
Includes `FormEntry` for type safety when composing multipart data. `streamMultipart` returns an AsyncGenerator of Uint8Array chunks.
untar
import { untar, TarFile, TarChunk, TarTypeFlag } from 'multitars';
const { untar } = require('multitars');
Includes types for Tar entries and flags. `untar` returns an AsyncGenerator of `TarFile` or `TarChunk`.
tar
import { tar } from 'multitars';
`tar` accepts an AsyncIterable of `TarChunk` or `TarFile` and returns an AsyncGenerator of Uint8Array chunks.

Demonstrates how to create and parse multipart/form-data and Tar archives using Web Streams, highlighting the `AsyncGenerator` pattern for consuming entries and file content. This example simulates network request/response flows.

import { parseMultipart, streamMultipart, FormEntry, untar, tar, TarTypeFlag } from 'multitars'; // --- Simulate a multipart/form-data request body --- async function createMultipartBody() { const entries: FormEntry[] = [ ['field1', 'hello world'], ['file1', new Uint8Array([1, 2, 3, 4])], ['file2', new Blob(['another file content'], { type: 'text/plain' })], ]; const multipartStream = streamMultipart(entries); // To get the full body as a ReadableStream, you'd typically do: // const bodyStream = new ReadableStream({ // async pull(controller) { // const { value, done } = await multipartStream.next(); // if (done) { // controller.close(); // } else { // controller.enqueue(value); // } // }, // }); // For quickstart, let's collect chunks to simulate a full body const chunks: Uint8Array[] = []; for await (const chunk of multipartStream) { chunks.push(chunk); } return new ReadableStream({ start(controller) { chunks.forEach(chunk => controller.enqueue(chunk)); controller.close(); } }); } async function handleMultipartRequest(requestBodyStream: ReadableStream<Uint8Array>, contentTypeHeader: string) { console.log('--- Parsing Multipart Request ---'); for await (const entry of parseMultipart(requestBodyStream, { contentType: contentTypeHeader })) { console.log(`Found entry: ${entry.name}, type: ${entry.type}, filename: ${entry.name}, size: ${entry.size}`); if (entry.type === 'file') { const fileContent = await new Response(entry.stream).arrayBuffer(); console.log(` File content length: ${fileContent.byteLength}`); } } } // --- Simulate a tar archive --- async function createTarArchive() { const tarEntries = [ { name: 'hello.txt', size: 13, typeflag: TarTypeFlag.FILE, mtime: Date.now() / 1000, stream: new ReadableStream({ start(controller) { controller.enqueue(new TextEncoder().encode('Hello, Tar!\n')); controller.close(); } }) }, { name: 'dir/', typeflag: TarTypeFlag.DIRECTORY, mtime: Date.now() / 1000 }, { name: 'link.txt', typeflag: TarTypeFlag.SYMLINK, linkname: 'hello.txt', mtime: Date.now() / 1000 } ]; const tarStream = tar(tarEntries); const chunks: Uint8Array[] = []; for await (const chunk of tarStream) { chunks.push(chunk); } return new ReadableStream({ start(controller) { chunks.forEach(chunk => controller.enqueue(chunk)); controller.close(); } }); } async function handleTarArchive(tarBodyStream: ReadableStream<Uint8Array>) { console.log('\n--- Untarring Archive ---'); for await (const entry of untar(tarBodyStream)) { console.log(`Found entry: ${entry.name}, type: ${entry.typeflag === TarTypeFlag.FILE ? 'file' : entry.typeflag === TarTypeFlag.DIRECTORY ? 'directory' : 'link'}`); if (entry.typeflag === TarTypeFlag.FILE && 'stream' in entry) { const fileContent = await new Response(entry.stream).text(); console.log(` File content: ${fileContent.trim()}`); } } } (async () => { // Example Usage: const multipartRequestStream = await createMultipartBody(); const multipartBoundary = `----------${Math.random().toString(36).substring(2)}`; // Simulate a boundary await handleMultipartRequest(multipartRequestStream, `multipart/form-data; boundary=${multipartBoundary}`); const tarArchiveStream = await createTarArchive(); await handleTarArchive(tarArchiveStream); })();
Debug
Known issues
gotchaThis library is built exclusively for the Web Streams API and expects `Uint8Array` for binary data. Directly using Node.js `Buffer` or older Node.js `stream` interfaces will not work or will negate the memory efficiency benefits by forcing intermediate buffering.
fix
Ensure all input and output data adheres to `ReadableStream<Uint8Array>` or `AsyncIterable<Uint8Array>` patterns. Convert `Buffer` instances to `Uint8Array` if necessary, though this typically indicates a non-streaming pattern.
affects: >=0.1.0
gotchaAll parsing and streaming functions (`parseMultipart`, `streamMultipart`, `untar`, `tar`) return `AsyncGenerator`s. These must be iterated using `for await...of` loops or manually with `.next()` calls to initiate and process data. Merely calling the function does not trigger any stream operations.
fix
Always consume the `AsyncGenerator` return value. For example: `for await (const item of parseMultipart(...)) { ... }`.
affects: >=0.1.0
gotchaWhen parsing multipart or tar archives, `StreamFile`, `TarFile`, and `TarChunk` objects contain their *own* internal `ReadableStream` (accessible via the `stream` property for `TarFile`/`StreamFile`). These inner streams must be fully consumed or explicitly skipped/cancelled before the outer `AsyncGenerator` can yield the *next* file or chunk. Failing to do so will cause the outer stream to hang or not advance.
fix
After receiving a `StreamFile` or `TarFile`, ensure its `stream` property is either fully read (e.g., using `new Response(entry.stream).arrayBuffer()`) or explicitly drained/skipped (e.g., `for await (const _ of entry.stream) {}`) before the next iteration of the outer `for await...of` loop.
affects: >=0.1.0
breakingVersion 1.0.0 included a patch fix for an accidental typo in the tar decoder that previously broke non-PAX GNU long name support. While a bug fix, this corrects previous incorrect behavior, which might be a breaking behavioral change for systems that inadvertently relied on the prior buggy implementation for specific tar archives.
fix
Upgrade to `v1.0.0` or higher to correctly handle non-PAX GNU long names in tar archives. Review any workflows that might have relied on or compensated for the previous incorrect decoding.
affects: >=1.0.0
gotchaThe `multipartContentType` utility provides a dynamically seeded boundary. While convenient for automatically generating a unique boundary for outgoing multipart messages, if your application requires a specific, static, or truly random boundary (e.g., for compatibility with external services or deterministic testing), you will need to manage boundary generation and the `Content-Type` header manually.
fix
For specific boundary requirements, generate your own boundary string and construct the `Content-Type` header (`multipart/form-data; boundary=YOUR_BOUNDARY_STRING`) before passing it to `parseMultipart` or including it with `streamMultipart`'s output.
affects: >=0.0.2
Errors
Common errors & fixes
TypeError: require is not a function
Attempting to use CommonJS `require()` syntax to import `multitars`.
fix
Use ES Module `import` syntax: `import { ... } from 'multitars';`
Code appears to run but no data is processed / Stream hangs unexpectedly.
Not properly iterating the `AsyncGenerator` returned by `parseMultipart`, `untar`, `streamMultipart`, or `tar`, or failing to consume inner file streams.
fix
Ensure all functions returning `AsyncGenerator` are consumed with `for await...of`. For `TarFile`/`StreamFile` entries, explicitly read or drain their internal `stream` property.
TypeError: Cannot read properties of undefined (reading 'contentType') when calling parseMultipart.
The `parseMultipart` function requires a `params` object with a `contentType` property.
fix
Provide the `contentType` parameter: `parseMultipart(stream, { contentType: 'multipart/form-data; boundary=...' });`
TS2345: Argument of type 'Buffer' is not assignable to parameter of type 'Uint8Array'.
`multitars` operates on `Uint8Array` for binary data, but a Node.js `Buffer` was provided.
fix
Convert `Buffer` instances to `Uint8Array` before passing them to `multitars` functions: `new Uint8Array(buffer)`.
Upgrade
Version history
1.0.0latest on npm
Audit
Dependencies

No dependency data recorded yet.

Agent activity
12 hits · last 30 days
node
12
Resources