1/**
2 * Bun-specific helpers for parsing HTTP `multipart/form-data` request bodies.
3 *
4 * This module adapts a Bun `Request` body and headers into the shared
5 * `Multipart` model. `stream` returns multipart parts as a `Stream`, while
6 * `persisted` collects the form and writes file parts to scoped temporary files
7 * through the current `FileSystem`, `Path`, and `Scope` services.
8 *
9 * @since 4.0.0
10 */
11import type * as Effect from "effect/Effect"
12import type { FileSystem } from "effect/FileSystem"
13import * as Multipart from "effect/http/Multipart"
14import type { Path } from "effect/Path"
15import type * as Scope from "effect/Scope"
16import * as Stream from "effect/Stream"
17import * as BunStream from "./BunStream.ts"
18
19/**
20 * Parses a Bun `Request` body as multipart data and returns a stream of multipart parts.
21 *
22 * @category constructors
23 * @since 4.0.0
24 */
25export const stream = (source: Request): Stream.Stream<Multipart.Part, Multipart.MultipartError> =>
26 BunStream.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 Bun `Request`, requiring file-system, path, and scope services.
41 *
42 * @category constructors
43 * @since 4.0.0
44 */
45export 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))