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
muslnode 18–226 runs
build_error
glibcnode 18–226 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);
})();
Errors
Common errors & fixes
TypeError: require is not a function
Attempting to use CommonJS `require()` syntax to import `multitars`.
fixUse 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.
fixEnsure 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.
fixProvide 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.
fixConvert `Buffer` instances to `Uint8Array` before passing them to `multitars` functions: `new Uint8Array(buffer)`.
Audit
Dependencies
No dependency data recorded yet.