|
| 1 | +/** |
| 2 | + * Web-standard helpers for parsing HTTP `multipart/form-data` request bodies. |
| 3 | + * |
| 4 | + * This module mirrors `BunMultipart`, adapting a web `Request` body and headers |
| 5 | + * into the shared `Multipart` model. `stream` returns multipart parts as a |
| 6 | + * `Stream`, while `persisted` collects the form and writes file parts to scoped |
| 7 | + * temporary files through the current `FileSystem`, `Path`, and `Scope` |
| 8 | + * services. |
| 9 | + * |
| 10 | + * @since 4.0.0 |
| 11 | + */ |
| 12 | +import type * as Effect from "effect/Effect" |
| 13 | +import type { FileSystem } from "effect/FileSystem" |
| 14 | +import type { Path } from "effect/Path" |
| 15 | +import type * as Scope from "effect/Scope" |
| 16 | +import * as Stream from "effect/Stream" |
| 17 | +import * as Multipart from "effect/unstable/http/Multipart" |
| 18 | + |
| 19 | +/** |
| 20 | + * Parses a web `Request` body as multipart data and returns a stream of multipart parts. |
| 21 | + * |
| 22 | + * @category constructors |
| 23 | + * @since 4.0.0 |
| 24 | + */ |
| 25 | +export const stream = (source: Request): Stream.Stream<Multipart.Part, Multipart.MultipartError> => |
| 26 | + Stream.fromReadableStream({ |
| 27 | + evaluate: () => |
| 28 | + source.body ?? new ReadableStream({ |
| 29 | + start(controller) { |
| 30 | + controller.enqueue(new Uint8Array()) |
| 31 | + controller.close() |
| 32 | + } |
| 33 | + }), |
| 34 | + onError: (cause) => Multipart.MultipartError.fromReason("InternalError", cause) |
| 35 | + }).pipe( |
| 36 | + Stream.pipeThroughChannel(Multipart.makeChannel(Object.fromEntries(source.headers))) |
| 37 | + ) |
| 38 | + |
| 39 | +/** |
| 40 | + * Parses and persists multipart data from a web `Request`, requiring file-system, path, and scope services. |
| 41 | + * |
| 42 | + * @category constructors |
| 43 | + * @since 4.0.0 |
| 44 | + */ |
| 45 | +export const persisted = ( |
| 46 | + source: Request |
| 47 | +): Effect.Effect< |
| 48 | + Multipart.Persisted, |
| 49 | + Multipart.MultipartError, |
| 50 | + | FileSystem |
| 51 | + | Path |
| 52 | + | Scope.Scope |
| 53 | +> => Multipart.toPersisted(stream(source)) |
0 commit comments