@remix-run/multipart-parser 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Michael Jackson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,235 @@
1
+ # multipart-parser
2
+
3
+ `multipart-parser` is a fast, streaming multipart parser that works in **any JavaScript environment**, from serverless functions to traditional servers. Whether you're handling file uploads, parsing email attachments, or working with multipart API responses, `multipart-parser` has you covered.
4
+
5
+ ## 🚀 Why multipart-parser?
6
+
7
+ - **Universal JavaScript** - One library that works everywhere: Node.js, Bun, Deno, Cloudflare Workers, and browsers
8
+ - **Blazing Fast** - Consistently outperforms popular alternatives like busboy in benchmarks
9
+ - **Zero Dependencies** - Lightweight and secure with no external dependencies
10
+ - **Memory Efficient** - Streaming architecture that `yield`s files as they are found in the stream
11
+ - **Type Safe** - Written in TypeScript with comprehensive type definitions
12
+ - **Standards Based** - Built on the web standard [Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) for maximum compatibility
13
+ - **Production Ready** - Battle-tested error handling with specific error types for common scenarios
14
+
15
+ ## 📦 Features
16
+
17
+ - Parse file uploads (`multipart/form-data`) with automatic field and file detection
18
+ - Support for all `multipart/*` content types (mixed, alternative, related, etc.)
19
+ - Convenient `MultipartPart` API with `arrayBuffer`, `bytes`, `text`, `size`, and metadata access
20
+ - Built-in file size limiting to prevent abuse
21
+ - First-class Node.js support with native `http.IncomingMessage` compatibility
22
+ - [Examples for every major runtime](https://github.com/remix-run/remix/tree/v3/packages/multipart-parser/examples)
23
+
24
+ ## Installation
25
+
26
+ Install from [npm](https://www.npmjs.com/):
27
+
28
+ ```sh
29
+ npm install @remix-run/multipart-parser
30
+ ```
31
+
32
+ Or install from [JSR](https://jsr.io/):
33
+
34
+ ```sh
35
+ deno add @remix-run/multipart-parser
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ The most common use case for `multipart-parser` is handling file uploads when you're building a web server. For this case, the `parseMultipartRequest` function is your friend. It automatically validates the request is `multipart/form-data`, extracts the multipart boundary from the `Content-Type` header, parses all fields and files in the `request.body` stream, and gives each one to you as a `MultipartPart` object with a rich API for accessing its metadata and content.
41
+
42
+ ```ts
43
+ import { MultipartParseError, parseMultipartRequest } from '@remix-run/multipart-parser';
44
+
45
+ async function handleRequest(request: Request): void {
46
+ try {
47
+ for await (let part of parseMultipartRequest(request)) {
48
+ if (part.isFile) {
49
+ // Access file data in multiple formats
50
+ let buffer = part.arrayBuffer; // ArrayBuffer
51
+ console.log(`File received: ${part.filename} (${buffer.byteLength} bytes)`);
52
+ console.log(`Content type: ${part.mediaType}`);
53
+ console.log(`Field name: ${part.name}`);
54
+
55
+ // Save to disk, upload to cloud storage, etc.
56
+ await saveFile(part.filename, part.bytes);
57
+ } else {
58
+ let text = part.text; // string
59
+ console.log(`Field received: ${part.name} = ${JSON.stringify(text)}`);
60
+ }
61
+ }
62
+ } catch (error) {
63
+ if (error instanceof MultipartParseError) {
64
+ console.error('Failed to parse multipart request:', error.message);
65
+ } else {
66
+ console.error('An unexpected error occurred:', error);
67
+ }
68
+ }
69
+ }
70
+ ```
71
+
72
+ ## Limiting File Upload Size
73
+
74
+ A common use case when handling file uploads is limiting the size of uploaded files to prevent malicious users from sending very large files that may overload your server's memory and/or storage capacity. You can set a file upload size limit using the `maxFileSize` option, and return a 413 "Payload Too Large" response when you receive a request that exceeds the limit.
75
+
76
+ ```ts
77
+ import {
78
+ MultipartParseError,
79
+ MaxFileSizeExceededError,
80
+ parseMultipartRequest,
81
+ } from '@remix-run/multipart-parser/node';
82
+
83
+ const oneMb = Math.pow(2, 20);
84
+ const maxFileSize = 10 * oneMb;
85
+
86
+ async function handleRequest(request: Request): Promise<Response> {
87
+ try {
88
+ for await (let part of parseMultipartRequest(request, { maxFileSize })) {
89
+ // ...
90
+ }
91
+ } catch (error) {
92
+ if (error instanceof MaxFileSizeExceededError) {
93
+ return new Response('File size limit exceeded', { status: 413 });
94
+ } else if (error instanceof MultipartParseError) {
95
+ return new Response('Failed to parse multipart request', { status: 400 });
96
+ } else {
97
+ console.error(error);
98
+ return new Response('Internal Server Error', { status: 500 });
99
+ }
100
+ }
101
+ }
102
+ ```
103
+
104
+ ## Node.js Bindings
105
+
106
+ The main module (`import from "@remix-run/multipart-parser"`) assumes you're working with [the fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) (`Request`, `ReadableStream`, etc). Support for these interfaces was added to Node.js by the [undici](https://github.com/nodejs/undici) project in [version 16.5.0](https://nodejs.org/en/blog/release/v16.5.0).
107
+
108
+ If however you're building a server for Node.js that relies on node-specific APIs like `http.IncomingMessage`, `stream.Readable`, and `buffer.Buffer` (ala Express or `http.createServer`), `multipart-parser` ships with an additional module that works directly with these APIs.
109
+
110
+ ```ts
111
+ import * as http from 'node:http';
112
+ import { MultipartParseError, parseMultipartRequest } from '@remix-run/multipart-parser/node';
113
+
114
+ let server = http.createServer(async (req, res) => {
115
+ try {
116
+ for await (let part of parseMultipartRequest(req)) {
117
+ // ...
118
+ }
119
+ } catch (error) {
120
+ if (error instanceof MultipartParseError) {
121
+ console.error('Failed to parse multipart request:', error.message);
122
+ } else {
123
+ console.error('An unexpected error occurred:', error);
124
+ }
125
+ }
126
+ });
127
+
128
+ server.listen(8080);
129
+ ```
130
+
131
+ ## Low-level API
132
+
133
+ If you're working directly with multipart boundaries and buffers/streams of multipart data that are not necessarily part of a request, `multipart-parser` provides a low-level `parseMultipart()` API that you can use directly:
134
+
135
+ ```ts
136
+ import { parseMultipart } from '@remix-run/multipart-parser';
137
+
138
+ let message = new Uint8Array(/* ... */);
139
+ let boundary = '----WebKitFormBoundary56eac3x';
140
+
141
+ for (let part of parseMultipart(message, { boundary })) {
142
+ // ...
143
+ }
144
+ ```
145
+
146
+ In addition, the `parseMultipartStream` function provides an `async` generator interface for multipart data in a `ReadableStream`:
147
+
148
+ ```ts
149
+ import { parseMultipartStream } from '@remix-run/multipart-parser';
150
+
151
+ let message = new ReadableStream(/* ... */);
152
+ let boundary = '----WebKitFormBoundary56eac3x';
153
+
154
+ for await (let part of parseMultipartStream(message, { boundary })) {
155
+ // ...
156
+ }
157
+ ```
158
+
159
+ ## Examples
160
+
161
+ The [`examples` directory](https://github.com/remix-run/remix/tree/v3/packages/multipart-parser/examples) contains a few working examples of how you can use this library:
162
+
163
+ - [`examples/bun`](https://github.com/remix-run/remix/tree/v3/packages/multipart-parser/examples/bun) - using multipart-parser in Bun
164
+ - [`examples/cf-workers`](https://github.com/remix-run/remix/tree/v3/packages/multipart-parser/examples/cf-workers) - using multipart-parser in a Cloudflare Worker and storing file uploads in R2
165
+ - [`examples/deno`](https://github.com/remix-run/remix/tree/v3/packages/multipart-parser/examples/deno) - using multipart-parser in Deno
166
+ - [`examples/node`](https://github.com/remix-run/remix/tree/v3/packages/multipart-parser/examples/node) - using multipart-parser in Node.js
167
+
168
+ ## Benchmark
169
+
170
+ `multipart-parser` is designed to be as efficient as possible, operating on streams of data and rarely buffering in common usage. This design yields exceptional performance when handling multipart payloads of any size. In benchmarks, `multipart-parser` is as fast or faster than `busboy`.
171
+
172
+ The results of running the benchmarks on my laptop:
173
+
174
+ ```
175
+ > @remix-run/multipart-parser@0.10.1 bench:node /Users/michael/Projects/remix-the-web/packages/multipart-parser
176
+ > node --disable-warning=ExperimentalWarning ./bench/runner.ts
177
+
178
+ Platform: Darwin (24.5.0)
179
+ CPU: Apple M1 Pro
180
+ Date: 6/13/2025, 12:27:09 PM
181
+ Node.js v24.0.2
182
+ ┌──────────────────┬──────────────────┬──────────────────┬──────────────────┬───────────────────┐
183
+ │ (index) │ 1 small file │ 1 large file │ 100 small files │ 5 large files │
184
+ ├──────────────────┼──────────────────┼──────────────────┼──────────────────┼───────────────────┤
185
+ │ multipart-parser │ '0.01 ms ± 0.03' │ '1.08 ms ± 0.08' │ '0.04 ms ± 0.01' │ '10.50 ms ± 0.38' │
186
+ │ multipasta │ '0.02 ms ± 0.06' │ '1.07 ms ± 0.02' │ '0.15 ms ± 0.02' │ '10.46 ms ± 0.11' │
187
+ │ busboy │ '0.06 ms ± 0.17' │ '3.07 ms ± 0.24' │ '0.24 ms ± 0.05' │ '29.85 ms ± 0.18' │
188
+ │ @fastify/busboy │ '0.05 ms ± 0.13' │ '1.23 ms ± 0.09' │ '0.45 ms ± 0.22' │ '11.81 ms ± 0.11' │
189
+ └──────────────────┴──────────────────┴──────────────────┴──────────────────┴───────────────────┘
190
+
191
+ > @remix-run/multipart-parser@0.10.1 bench:bun /Users/michael/Projects/remix-the-web/packages/multipart-parser
192
+ > bun run ./bench/runner.ts
193
+
194
+ Platform: Darwin (24.5.0)
195
+ CPU: Apple M1 Pro
196
+ Date: 6/13/2025, 12:27:31 PM
197
+ Bun 1.2.13
198
+ ┌──────────────────┬────────────────┬────────────────┬─────────────────┬─────────────────┐
199
+ │ │ 1 small file │ 1 large file │ 100 small files │ 5 large files │
200
+ ├──────────────────┼────────────────┼────────────────┼─────────────────┼─────────────────┤
201
+ │ multipart-parser │ 0.01 ms ± 0.04 │ 0.86 ms ± 0.09 │ 0.04 ms ± 0.01 │ 8.32 ms ± 0.26 │
202
+ │ multipasta │ 0.02 ms ± 0.07 │ 0.87 ms ± 0.03 │ 0.25 ms ± 0.21 │ 8.27 ms ± 0.09 │
203
+ │ busboy │ 0.05 ms ± 0.17 │ 3.54 ms ± 0.10 │ 0.30 ms ± 0.03 │ 34.79 ms ± 0.38 │
204
+ │ @fastify/busboy │ 0.06 ms ± 0.18 │ 4.04 ms ± 0.08 │ 0.48 ms ± 0.06 │ 39.91 ms ± 0.37 │
205
+ └──────────────────┴────────────────┴────────────────┴─────────────────┴─────────────────┘
206
+
207
+ > @remix-run/multipart-parser@0.10.1 bench:deno /Users/michael/Projects/remix-the-web/packages/multipart-parser
208
+ > deno run --allow-sys ./bench/runner.ts
209
+
210
+ Platform: Darwin (24.5.0)
211
+ CPU: Apple M1 Pro
212
+ Date: 6/13/2025, 12:28:12 PM
213
+ Deno 2.3.6
214
+ ┌──────────────────┬──────────────────┬────────────────────┬──────────────────┬─────────────────────┐
215
+ │ (idx) │ 1 small file │ 1 large file │ 100 small files │ 5 large files │
216
+ ├──────────────────┼──────────────────┼────────────────────┼──────────────────┼─────────────────────┤
217
+ │ multipart-parser │ "0.01 ms ± 0.03" │ "1.03 ms ± 0.04" │ "0.05 ms ± 0.01" │ "10.05 ms ± 0.20" │
218
+ │ multipasta │ "0.02 ms ± 0.07" │ "1.04 ms ± 0.03" │ "0.16 ms ± 0.02" │ "10.10 ms ± 0.08" │
219
+ │ busboy │ "0.05 ms ± 0.19" │ "3.06 ms ± 0.15" │ "0.32 ms ± 0.05" │ "29.92 ms ± 0.24" │
220
+ │ @fastify/busboy │ "0.06 ms ± 0.14" │ "14.72 ms ± 11.42" │ "0.81 ms ± 0.20" │ "127.63 ms ± 35.77" │
221
+ └──────────────────┴──────────────────┴────────────────────┴──────────────────┴─────────────────────┘
222
+ ```
223
+
224
+ ## Related Packages
225
+
226
+ - [`form-data-parser`](https://github.com/remix-run/remix/tree/v3/packages/form-data-parser) - Uses `multipart-parser` internally to parse multipart requests and generate `FileUpload`s for storage
227
+ - [`headers`](https://github.com/remix-run/remix/tree/v3/packages/headers) - Used internally to parse HTTP headers and get metadata (filename, content type) for each `MultipartPart`
228
+
229
+ ## Credits
230
+
231
+ Thanks to Jacob Ebey who gave me several code reviews on this project prior to publishing.
232
+
233
+ ## License
234
+
235
+ See [LICENSE](https://github.com/remix-run/remix/blob/v3/LICENSE)
@@ -0,0 +1,9 @@
1
+ export interface SearchFunction {
2
+ (haystack: Uint8Array, start?: number): number;
3
+ }
4
+ export declare function createSearch(pattern: string): SearchFunction;
5
+ export interface PartialTailSearchFunction {
6
+ (haystack: Uint8Array): number;
7
+ }
8
+ export declare function createPartialTailSearch(pattern: string): PartialTailSearchFunction;
9
+ //# sourceMappingURL=buffer-search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buffer-search.d.ts","sourceRoot":"","sources":["../../src/lib/buffer-search.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAChD;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CA+B5D;AAED,MAAM,WAAW,yBAAyB;IACxC,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,CAAC;CAChC;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,yBAAyB,CAyBlF"}
@@ -0,0 +1,25 @@
1
+ import type { MultipartParserOptions, MultipartPart } from './multipart.ts';
2
+ /**
3
+ * Extracts the boundary string from a `multipart/*` content type.
4
+ *
5
+ * @param contentType The `Content-Type` header value from the request
6
+ * @return The boundary string if found, or null if not present
7
+ */
8
+ export declare function getMultipartBoundary(contentType: string): string | null;
9
+ /**
10
+ * Returns true if the given request contains multipart data.
11
+ *
12
+ * @param request The `Request` object to check
13
+ * @return `true` if the request is a multipart request, `false` otherwise
14
+ */
15
+ export declare function isMultipartRequest(request: Request): boolean;
16
+ /**
17
+ * Parse a multipart [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) and yield each part as
18
+ * a `MultipartPart` object. Useful in HTTP server contexts for handling incoming `multipart/*` requests.
19
+ *
20
+ * @param request The `Request` object containing multipart data
21
+ * @param options Optional parser options, such as `maxHeaderSize` and `maxFileSize`
22
+ * @return An async generator yielding `MultipartPart` objects
23
+ */
24
+ export declare function parseMultipartRequest(request: Request, options?: MultipartParserOptions): AsyncGenerator<MultipartPart, void, unknown>;
25
+ //# sourceMappingURL=multipart-request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multipart-request.d.ts","sourceRoot":"","sources":["../../src/lib/multipart-request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAG5E;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGvE;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAG5D;AAED;;;;;;;GAOG;AACH,wBAAuB,qBAAqB,CAC1C,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,cAAc,CAAC,aAAa,EAAE,IAAI,EAAE,OAAO,CAAC,CAkB9C"}
@@ -0,0 +1,145 @@
1
+ import Headers from '@remix-run/headers';
2
+ /**
3
+ * The base class for errors thrown by the multipart parser.
4
+ */
5
+ export declare class MultipartParseError extends Error {
6
+ constructor(message: string);
7
+ }
8
+ /**
9
+ * An error thrown when the maximum allowed size of a header is exceeded.
10
+ */
11
+ export declare class MaxHeaderSizeExceededError extends MultipartParseError {
12
+ constructor(maxHeaderSize: number);
13
+ }
14
+ /**
15
+ * An error thrown when the maximum allowed size of a file is exceeded.
16
+ */
17
+ export declare class MaxFileSizeExceededError extends MultipartParseError {
18
+ constructor(maxFileSize: number);
19
+ }
20
+ export interface ParseMultipartOptions {
21
+ /**
22
+ * The boundary string used to separate parts in the multipart message,
23
+ * e.g. the `boundary` parameter in the `Content-Type` header.
24
+ */
25
+ boundary: string;
26
+ /**
27
+ * The maximum allowed size of a header in bytes. If an individual part's header
28
+ * exceeds this size, a `MaxHeaderSizeExceededError` will be thrown.
29
+ *
30
+ * Default: 8 KiB
31
+ */
32
+ maxHeaderSize?: number;
33
+ /**
34
+ * The maximum allowed size of a file in bytes. If an individual part's content
35
+ * exceeds this size, a `MaxFileSizeExceededError` will be thrown.
36
+ *
37
+ * Default: 2 MiB
38
+ */
39
+ maxFileSize?: number;
40
+ }
41
+ /**
42
+ * Parse a `multipart/*` message from a buffer/iterable and yield each part as a `MultipartPart` object.
43
+ *
44
+ * Note: This is a low-level API that requires manual handling of the content and boundary. If you're
45
+ * building a web server, consider using `parseMultipartRequest(request)` instead.
46
+ *
47
+ * @param message The multipart message as a `Uint8Array` or an iterable of `Uint8Array` chunks
48
+ * @param options Options for the parser
49
+ * @return A generator that yields `MultipartPart` objects
50
+ */
51
+ export declare function parseMultipart(message: Uint8Array | Iterable<Uint8Array>, options: ParseMultipartOptions): Generator<MultipartPart, void, unknown>;
52
+ /**
53
+ * Parse a `multipart/*` message stream and yield each part as a `MultipartPart` object.
54
+ *
55
+ * Note: This is a low-level API that requires manual handling of the content and boundary. If you're
56
+ * building a web server, consider using `parseMultipartRequest(request)` instead.
57
+ *
58
+ * @param stream A stream containing multipart data as a `ReadableStream<Uint8Array>`
59
+ * @param options Options for the parser
60
+ * @return An async generator that yields `MultipartPart` objects
61
+ */
62
+ export declare function parseMultipartStream(stream: ReadableStream<Uint8Array>, options: ParseMultipartOptions): AsyncGenerator<MultipartPart, void, unknown>;
63
+ export type MultipartParserOptions = Omit<ParseMultipartOptions, 'boundary'>;
64
+ /**
65
+ * A streaming parser for `multipart/*` HTTP messages.
66
+ */
67
+ export declare class MultipartParser {
68
+ #private;
69
+ readonly boundary: string;
70
+ readonly maxHeaderSize: number;
71
+ readonly maxFileSize: number;
72
+ constructor(boundary: string, options?: MultipartParserOptions);
73
+ /**
74
+ * Write a chunk of data to the parser.
75
+ *
76
+ * @param chunk A chunk of data to write to the parser
77
+ * @return A generator yielding `MultipartPart` objects as they are parsed
78
+ */
79
+ write(chunk: Uint8Array): Generator<MultipartPart, void, unknown>;
80
+ /**
81
+ * Should be called after all data has been written to the parser.
82
+ *
83
+ * Note: This will throw if the multipart message is incomplete or
84
+ * wasn't properly terminated.
85
+ *
86
+ * @return void
87
+ */
88
+ finish(): void;
89
+ }
90
+ /**
91
+ * A part of a `multipart/*` HTTP message.
92
+ */
93
+ export declare class MultipartPart {
94
+ #private;
95
+ /**
96
+ * The raw content of this part as an array of `Uint8Array` chunks.
97
+ */
98
+ readonly content: Uint8Array[];
99
+ constructor(header: Uint8Array, content: Uint8Array[]);
100
+ /**
101
+ * The content of this part as an `ArrayBuffer`.
102
+ */
103
+ get arrayBuffer(): ArrayBuffer;
104
+ /**
105
+ * The content of this part as a single `Uint8Array`. In `multipart/form-data` messages, this is useful
106
+ * for reading the value of files that were uploaded using `<input type="file">` fields.
107
+ */
108
+ get bytes(): Uint8Array;
109
+ /**
110
+ * The headers associated with this part.
111
+ */
112
+ get headers(): Headers;
113
+ /**
114
+ * True if this part originated from a file upload.
115
+ */
116
+ get isFile(): boolean;
117
+ /**
118
+ * True if this part originated from a text input field in a form submission.
119
+ */
120
+ get isText(): boolean;
121
+ /**
122
+ * The filename of the part, if it is a file upload.
123
+ */
124
+ get filename(): string | undefined;
125
+ /**
126
+ * The media type of the part.
127
+ */
128
+ get mediaType(): string | undefined;
129
+ /**
130
+ * The name of the part, usually the `name` of the field in the `<form>` that submitted the request.
131
+ */
132
+ get name(): string | undefined;
133
+ /**
134
+ * The size of the content in bytes.
135
+ */
136
+ get size(): number;
137
+ /**
138
+ * The content of this part as a string. In `multipart/form-data` messages, this is useful for
139
+ * reading the value of parts that originated from `<input type="text">` fields.
140
+ *
141
+ * Note: Do not use this for binary data, use `part.bytes` or `part.arrayBuffer` instead.
142
+ */
143
+ get text(): string;
144
+ }
145
+ //# sourceMappingURL=multipart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multipart.d.ts","sourceRoot":"","sources":["../../src/lib/multipart.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,oBAAoB,CAAC;AAMzC;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,0BAA2B,SAAQ,mBAAmB;gBACrD,aAAa,EAAE,MAAM;CAIlC;AAED;;GAEG;AACH,qBAAa,wBAAyB,SAAQ,mBAAmB;gBACnD,WAAW,EAAE,MAAM;CAIhC;AAED,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;GASG;AACH,wBAAiB,cAAc,CAC7B,OAAO,EAAE,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC,EAC1C,OAAO,EAAE,qBAAqB,GAC7B,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,OAAO,CAAC,CAmBzC;AAED;;;;;;;;;GASG;AACH,wBAAuB,oBAAoB,CACzC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,EAClC,OAAO,EAAE,qBAAqB,GAC7B,cAAc,CAAC,aAAa,EAAE,IAAI,EAAE,OAAO,CAAC,CAe9C;AAED,MAAM,MAAM,sBAAsB,GAAG,IAAI,CAAC,qBAAqB,EAAE,UAAU,CAAC,CAAC;AAa7E;;GAEG;AACH,qBAAa,eAAe;;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAajB,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,sBAAsB;IAY9D;;;;;OAKG;IACF,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,OAAO,CAAC;IA0HlE;;;;;;;OAOG;IACH,MAAM,IAAI,IAAI;CAKf;AAID;;GAEG;AACH,qBAAa,aAAa;;IACxB;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC;gBAKnB,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE;IAKrD;;OAEG;IACH,IAAI,WAAW,IAAI,WAAW,CAE7B;IAED;;;OAGG;IACH,IAAI,KAAK,IAAI,UAAU,CAUtB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,CAMrB;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,MAAM,GAAG,SAAS,CAEjC;IAED;;OAEG;IACH,IAAI,SAAS,IAAI,MAAM,GAAG,SAAS,CAElC;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,GAAG,SAAS,CAE7B;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAQjB;IAED;;;;;OAKG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
@@ -0,0 +1,41 @@
1
+ import type * as http from 'node:http';
2
+ import { Readable } from 'node:stream';
3
+ import type { ParseMultipartOptions, MultipartParserOptions, MultipartPart } from './multipart.ts';
4
+ /**
5
+ * Parse a `multipart/*` Node.js `Buffer` and yield each part as a `MultipartPart` object.
6
+ *
7
+ * Note: This is a low-level API that requires manual handling of the content and boundary. If you're
8
+ * building a web server, consider using `parseMultipartRequest(request)` instead.
9
+ *
10
+ * @param message The multipart message as a `Buffer` or an iterable of `Buffer` chunks
11
+ * @param options Options for the parser
12
+ * @return A generator yielding `MultipartPart` objects
13
+ */
14
+ export declare function parseMultipart(message: Buffer | Iterable<Buffer>, options: ParseMultipartOptions): Generator<MultipartPart, void, unknown>;
15
+ /**
16
+ * Parse a `multipart/*` Node.js `Readable` stream and yield each part as a `MultipartPart` object.
17
+ *
18
+ * Note: This is a low-level API that requires manual handling of the stream and boundary. If you're
19
+ * building a web server, consider using `parseMultipartRequest(request)` instead.
20
+ *
21
+ * @param stream A Node.js `Readable` stream containing multipart data
22
+ * @param options Options for the parser
23
+ * @return An async generator yielding `MultipartPart` objects
24
+ */
25
+ export declare function parseMultipartStream(stream: Readable, options: ParseMultipartOptions): AsyncGenerator<MultipartPart, void, unknown>;
26
+ /**
27
+ * Returns true if the given request is a multipart request.
28
+ *
29
+ * @param req The Node.js `http.IncomingMessage` object to check
30
+ * @return `true` if the request is a multipart request, `false` otherwise
31
+ */
32
+ export declare function isMultipartRequest(req: http.IncomingMessage): boolean;
33
+ /**
34
+ * Parse a multipart Node.js request and yield each part as a `MultipartPart` object.
35
+ *
36
+ * @param req The Node.js `http.IncomingMessage` object containing multipart data
37
+ * @param options Options for the parser
38
+ * @return An async generator yielding `MultipartPart` objects
39
+ */
40
+ export declare function parseMultipartRequest(req: http.IncomingMessage, options?: MultipartParserOptions): AsyncGenerator<MultipartPart, void, unknown>;
41
+ //# sourceMappingURL=multipart.node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multipart.node.d.ts","sourceRoot":"","sources":["../../src/lib/multipart.node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,IAAI,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,KAAK,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAQnG;;;;;;;;;GASG;AACH,wBAAiB,cAAc,CAC7B,OAAO,EAAE,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,EAClC,OAAO,EAAE,qBAAqB,GAC7B,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,OAAO,CAAC,CAEzC;AAED;;;;;;;;;GASG;AACH,wBAAuB,oBAAoB,CACzC,MAAM,EAAE,QAAQ,EAChB,OAAO,EAAE,qBAAqB,GAC7B,cAAc,CAAC,aAAa,EAAE,IAAI,EAAE,OAAO,CAAC,CAE9C;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,GAAG,OAAO,CAGrE;AAED;;;;;;GAMG;AACH,wBAAuB,qBAAqB,CAC1C,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,cAAc,CAAC,aAAa,EAAE,IAAI,EAAE,OAAO,CAAC,CAe9C"}
@@ -0,0 +1,2 @@
1
+ export declare function readStream(stream: ReadableStream<Uint8Array>): AsyncIterable<Uint8Array>;
2
+ //# sourceMappingURL=read-stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-stream.d.ts","sourceRoot":"","sources":["../../src/lib/read-stream.ts"],"names":[],"mappings":"AAEA,wBAAuB,UAAU,CAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,aAAa,CAAC,UAAU,CAAC,CAY/F"}