effect 4.0.0-beta.27 → 4.0.0-beta.29

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.
Files changed (208) hide show
  1. package/dist/Brand.d.ts +1 -1
  2. package/dist/Brand.d.ts.map +1 -1
  3. package/dist/Brand.js +1 -1
  4. package/dist/Brand.js.map +1 -1
  5. package/dist/ConfigProvider.d.ts +1 -1
  6. package/dist/Cron.d.ts +1 -1
  7. package/dist/Data.d.ts +1 -1
  8. package/dist/Data.d.ts.map +1 -1
  9. package/dist/Data.js.map +1 -1
  10. package/dist/Effect.d.ts +300 -184
  11. package/dist/Effect.d.ts.map +1 -1
  12. package/dist/Effect.js +99 -61
  13. package/dist/Effect.js.map +1 -1
  14. package/dist/Encoding.d.ts +1 -1
  15. package/dist/Exit.d.ts +24 -12
  16. package/dist/Exit.d.ts.map +1 -1
  17. package/dist/Exit.js +8 -4
  18. package/dist/Exit.js.map +1 -1
  19. package/dist/Fiber.d.ts +1 -0
  20. package/dist/Fiber.d.ts.map +1 -1
  21. package/dist/Fiber.js.map +1 -1
  22. package/dist/Function.d.ts +1 -9
  23. package/dist/Function.d.ts.map +1 -1
  24. package/dist/Function.js +2 -10
  25. package/dist/Function.js.map +1 -1
  26. package/dist/Graph.d.ts +1 -1
  27. package/dist/Newtype.d.ts +291 -0
  28. package/dist/Newtype.d.ts.map +1 -0
  29. package/dist/Newtype.js +161 -0
  30. package/dist/Newtype.js.map +1 -0
  31. package/dist/PlatformError.d.ts +2 -2
  32. package/dist/References.d.ts +6 -1
  33. package/dist/References.d.ts.map +1 -1
  34. package/dist/References.js +6 -1
  35. package/dist/References.js.map +1 -1
  36. package/dist/RequestResolver.d.ts +19 -19
  37. package/dist/RequestResolver.js +10 -10
  38. package/dist/RequestResolver.js.map +1 -1
  39. package/dist/Schedule.d.ts +142 -80
  40. package/dist/Schedule.d.ts.map +1 -1
  41. package/dist/Schedule.js +58 -32
  42. package/dist/Schedule.js.map +1 -1
  43. package/dist/Scheduler.d.ts +9 -0
  44. package/dist/Scheduler.d.ts.map +1 -1
  45. package/dist/Scheduler.js +11 -0
  46. package/dist/Scheduler.js.map +1 -1
  47. package/dist/Schema.d.ts +1 -1
  48. package/dist/Schema.d.ts.map +1 -1
  49. package/dist/Schema.js +3 -1
  50. package/dist/Schema.js.map +1 -1
  51. package/dist/SchemaAST.d.ts.map +1 -1
  52. package/dist/SchemaAST.js +1 -1
  53. package/dist/SchemaAST.js.map +1 -1
  54. package/dist/Stdio.d.ts +6 -2
  55. package/dist/Stdio.d.ts.map +1 -1
  56. package/dist/Stdio.js +2 -2
  57. package/dist/Stdio.js.map +1 -1
  58. package/dist/Stream.d.ts +8 -4
  59. package/dist/Stream.d.ts.map +1 -1
  60. package/dist/Stream.js +8 -4
  61. package/dist/Stream.js.map +1 -1
  62. package/dist/Types.d.ts +1 -22
  63. package/dist/Types.d.ts.map +1 -1
  64. package/dist/index.d.ts +71 -3
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +71 -3
  67. package/dist/index.js.map +1 -1
  68. package/dist/internal/effect.js +3 -1
  69. package/dist/internal/effect.js.map +1 -1
  70. package/dist/unstable/ai/LanguageModel.d.ts +12 -28
  71. package/dist/unstable/ai/LanguageModel.d.ts.map +1 -1
  72. package/dist/unstable/ai/LanguageModel.js +4 -18
  73. package/dist/unstable/ai/LanguageModel.js.map +1 -1
  74. package/dist/unstable/ai/McpSchema.d.ts +20 -1
  75. package/dist/unstable/ai/McpSchema.d.ts.map +1 -1
  76. package/dist/unstable/ai/McpSchema.js +8 -0
  77. package/dist/unstable/ai/McpSchema.js.map +1 -1
  78. package/dist/unstable/ai/McpServer.d.ts +65 -12
  79. package/dist/unstable/ai/McpServer.d.ts.map +1 -1
  80. package/dist/unstable/ai/McpServer.js +159 -45
  81. package/dist/unstable/ai/McpServer.js.map +1 -1
  82. package/dist/unstable/ai/Toolkit.d.ts +1 -1
  83. package/dist/unstable/ai/Toolkit.d.ts.map +1 -1
  84. package/dist/unstable/ai/Toolkit.js +4 -11
  85. package/dist/unstable/ai/Toolkit.js.map +1 -1
  86. package/dist/unstable/ai/internal/codec-transformer.js +0 -5
  87. package/dist/unstable/ai/internal/codec-transformer.js.map +1 -1
  88. package/dist/unstable/cli/Prompt.js +35 -8
  89. package/dist/unstable/cli/Prompt.js.map +1 -1
  90. package/dist/unstable/cluster/Message.d.ts +5 -5
  91. package/dist/unstable/cluster/Reply.d.ts +3 -3
  92. package/dist/unstable/encoding/Msgpack.d.ts +1 -1
  93. package/dist/unstable/encoding/Ndjson.d.ts +1 -1
  94. package/dist/unstable/encoding/Sse.d.ts +1 -1
  95. package/dist/unstable/eventlog/EventJournal.d.ts +1 -1
  96. package/dist/unstable/eventlog/EventLogRemote.d.ts +1 -1
  97. package/dist/unstable/http/Cookies.d.ts +45 -1
  98. package/dist/unstable/http/Cookies.d.ts.map +1 -1
  99. package/dist/unstable/http/Cookies.js +22 -0
  100. package/dist/unstable/http/Cookies.js.map +1 -1
  101. package/dist/unstable/http/HttpBody.d.ts +1 -1
  102. package/dist/unstable/http/HttpClient.d.ts.map +1 -1
  103. package/dist/unstable/http/HttpClient.js +3 -7
  104. package/dist/unstable/http/HttpClient.js.map +1 -1
  105. package/dist/unstable/http/HttpClientError.d.ts +7 -7
  106. package/dist/unstable/http/HttpClientRequest.d.ts +5 -0
  107. package/dist/unstable/http/HttpClientRequest.d.ts.map +1 -1
  108. package/dist/unstable/http/HttpClientRequest.js +21 -17
  109. package/dist/unstable/http/HttpClientRequest.js.map +1 -1
  110. package/dist/unstable/http/HttpEffect.d.ts +7 -0
  111. package/dist/unstable/http/HttpEffect.d.ts.map +1 -1
  112. package/dist/unstable/http/HttpEffect.js +6 -0
  113. package/dist/unstable/http/HttpEffect.js.map +1 -1
  114. package/dist/unstable/http/HttpServerError.d.ts +6 -6
  115. package/dist/unstable/http/HttpServerRequest.d.ts +11 -0
  116. package/dist/unstable/http/HttpServerRequest.d.ts.map +1 -1
  117. package/dist/unstable/http/HttpServerRequest.js +291 -1
  118. package/dist/unstable/http/HttpServerRequest.js.map +1 -1
  119. package/dist/unstable/http/HttpServerResponse.d.ts +47 -1
  120. package/dist/unstable/http/HttpServerResponse.d.ts.map +1 -1
  121. package/dist/unstable/http/HttpServerResponse.js +227 -0
  122. package/dist/unstable/http/HttpServerResponse.js.map +1 -1
  123. package/dist/unstable/http/HttpStaticServer.d.ts +69 -0
  124. package/dist/unstable/http/HttpStaticServer.d.ts.map +1 -0
  125. package/dist/unstable/http/HttpStaticServer.js +353 -0
  126. package/dist/unstable/http/HttpStaticServer.js.map +1 -0
  127. package/dist/unstable/http/Multipart.d.ts +1 -1
  128. package/dist/unstable/http/UrlParams.d.ts +1 -1
  129. package/dist/unstable/http/index.d.ts +4 -0
  130. package/dist/unstable/http/index.d.ts.map +1 -1
  131. package/dist/unstable/http/index.js +4 -0
  132. package/dist/unstable/http/index.js.map +1 -1
  133. package/dist/unstable/httpapi/HttpApiGroup.d.ts +1 -0
  134. package/dist/unstable/httpapi/HttpApiGroup.d.ts.map +1 -1
  135. package/dist/unstable/httpapi/HttpApiGroup.js.map +1 -1
  136. package/dist/unstable/persistence/KeyValueStore.d.ts +1 -1
  137. package/dist/unstable/reactivity/Atom.d.ts +7 -2
  138. package/dist/unstable/reactivity/Atom.d.ts.map +1 -1
  139. package/dist/unstable/reactivity/Atom.js +33 -15
  140. package/dist/unstable/reactivity/Atom.js.map +1 -1
  141. package/dist/unstable/reactivity/AtomHttpApi.d.ts +4 -6
  142. package/dist/unstable/reactivity/AtomHttpApi.d.ts.map +1 -1
  143. package/dist/unstable/reactivity/AtomHttpApi.js +39 -9
  144. package/dist/unstable/reactivity/AtomHttpApi.js.map +1 -1
  145. package/dist/unstable/reactivity/AtomRegistry.js +26 -2
  146. package/dist/unstable/reactivity/AtomRegistry.js.map +1 -1
  147. package/dist/unstable/reactivity/AtomRpc.d.ts +8 -8
  148. package/dist/unstable/reactivity/AtomRpc.d.ts.map +1 -1
  149. package/dist/unstable/reactivity/AtomRpc.js +46 -20
  150. package/dist/unstable/reactivity/AtomRpc.js.map +1 -1
  151. package/dist/unstable/rpc/Rpc.d.ts +1 -1
  152. package/dist/unstable/rpc/Rpc.d.ts.map +1 -1
  153. package/dist/unstable/rpc/Rpc.js.map +1 -1
  154. package/dist/unstable/rpc/RpcMiddleware.d.ts +5 -5
  155. package/dist/unstable/rpc/RpcMiddleware.d.ts.map +1 -1
  156. package/dist/unstable/rpc/RpcMiddleware.js.map +1 -1
  157. package/dist/unstable/rpc/RpcServer.js +2 -2
  158. package/dist/unstable/rpc/RpcServer.js.map +1 -1
  159. package/dist/unstable/rpc/Utils.js +1 -1
  160. package/dist/unstable/rpc/Utils.js.map +1 -1
  161. package/dist/unstable/socket/SocketServer.d.ts +3 -3
  162. package/dist/unstable/sql/Migrator.d.ts +1 -1
  163. package/dist/unstable/sql/SqlResolver.js +2 -2
  164. package/dist/unstable/sql/SqlResolver.js.map +1 -1
  165. package/dist/unstable/workflow/Workflow.d.ts +1 -1
  166. package/package.json +1 -1
  167. package/src/Brand.ts +1 -1
  168. package/src/Data.ts +1 -2
  169. package/src/Effect.ts +300 -184
  170. package/src/Exit.ts +24 -12
  171. package/src/Fiber.ts +1 -0
  172. package/src/Function.ts +2 -10
  173. package/src/Newtype.ts +308 -0
  174. package/src/References.ts +6 -1
  175. package/src/RequestResolver.ts +20 -20
  176. package/src/Schedule.ts +142 -80
  177. package/src/Scheduler.ts +12 -0
  178. package/src/Schema.ts +4 -2
  179. package/src/SchemaAST.ts +1 -4
  180. package/src/Stdio.ts +8 -4
  181. package/src/Stream.ts +8 -4
  182. package/src/Types.ts +1 -23
  183. package/src/index.ts +72 -3
  184. package/src/internal/effect.ts +3 -0
  185. package/src/unstable/ai/LanguageModel.ts +16 -37
  186. package/src/unstable/ai/McpSchema.ts +14 -0
  187. package/src/unstable/ai/McpServer.ts +224 -53
  188. package/src/unstable/ai/Toolkit.ts +5 -14
  189. package/src/unstable/ai/internal/codec-transformer.ts +0 -7
  190. package/src/unstable/cli/Prompt.ts +31 -9
  191. package/src/unstable/http/Cookies.ts +84 -0
  192. package/src/unstable/http/HttpClient.ts +5 -6
  193. package/src/unstable/http/HttpClientRequest.ts +21 -17
  194. package/src/unstable/http/HttpEffect.ts +8 -0
  195. package/src/unstable/http/HttpServerRequest.ts +388 -1
  196. package/src/unstable/http/HttpServerResponse.ts +328 -1
  197. package/src/unstable/http/HttpStaticServer.ts +456 -0
  198. package/src/unstable/http/index.ts +5 -0
  199. package/src/unstable/httpapi/HttpApiGroup.ts +1 -0
  200. package/src/unstable/reactivity/Atom.ts +62 -35
  201. package/src/unstable/reactivity/AtomHttpApi.ts +45 -11
  202. package/src/unstable/reactivity/AtomRegistry.ts +30 -2
  203. package/src/unstable/reactivity/AtomRpc.ts +48 -17
  204. package/src/unstable/rpc/Rpc.ts +1 -3
  205. package/src/unstable/rpc/RpcMiddleware.ts +12 -6
  206. package/src/unstable/rpc/RpcServer.ts +2 -2
  207. package/src/unstable/rpc/Utils.ts +1 -1
  208. package/src/unstable/sql/SqlResolver.ts +2 -2
@@ -17,6 +17,8 @@ import * as Stream from "../../Stream.ts"
17
17
  import * as Socket from "../socket/Socket.ts"
18
18
  import * as Cookies from "./Cookies.ts"
19
19
  import * as Headers from "./Headers.ts"
20
+ import * as HttpBody from "./HttpBody.ts"
21
+ import * as HttpClientRequest from "./HttpClientRequest.ts"
20
22
  import * as HttpIncomingMessage from "./HttpIncomingMessage.ts"
21
23
  import { hasBody, type HttpMethod } from "./HttpMethod.ts"
22
24
  import { HttpServerError, type RequestError, RequestParseError } from "./HttpServerError.ts"
@@ -177,7 +179,8 @@ export const schemaBodyJson = <A, I, RD, RE>(
177
179
  }
178
180
 
179
181
  const isMultipart = (request: HttpServerRequest) =>
180
- request.headers["content-type"]?.toLowerCase().includes("multipart/form-data")
182
+ request.headers["content-type"]?.toLowerCase().includes("multipart/form-data") === true ||
183
+ getFormDataBody(request) !== undefined
181
184
 
182
185
  /**
183
186
  * @since 4.0.0
@@ -276,6 +279,15 @@ export const schemaBodyFormJson = <A, I, RD, RE>(
276
279
  }
277
280
  }
278
281
 
282
+ /**
283
+ * @since 4.0.0
284
+ * @category conversions
285
+ */
286
+ export const fromClientRequest = (request: HttpClientRequest.HttpClientRequest): HttpServerRequest => {
287
+ const url = HttpClientRequest.toUrl(request)?.toString() ?? request.url
288
+ return new ClientRequestImpl(request, url)
289
+ }
290
+
279
291
  /**
280
292
  * @since 4.0.0
281
293
  * @category conversions
@@ -283,6 +295,40 @@ export const schemaBodyFormJson = <A, I, RD, RE>(
283
295
  export const fromWeb = (request: globalThis.Request): HttpServerRequest =>
284
296
  new ServerRequestImpl(request, removeHost(request.url))
285
297
 
298
+ /**
299
+ * @since 4.0.0
300
+ * @category conversions
301
+ */
302
+ export const toClientRequest = (request: HttpServerRequest): HttpClientRequest.HttpClientRequest =>
303
+ HttpClientRequest.setUrl(
304
+ HttpClientRequest.makeWith(
305
+ request.method,
306
+ "",
307
+ UrlParams.empty,
308
+ undefined,
309
+ request.headers,
310
+ toClientBody(request)
311
+ ),
312
+ toURL(request) ?? request.url
313
+ )
314
+
315
+ const toClientBody = (request: HttpServerRequest): HttpBody.HttpBody =>
316
+ hasBody(request.method)
317
+ ? HttpBody.stream(
318
+ request.stream,
319
+ request.headers["content-type"],
320
+ parseContentLength(request.headers["content-length"])
321
+ )
322
+ : HttpBody.empty
323
+
324
+ const parseContentLength = (contentLength: string | undefined): number | undefined => {
325
+ if (contentLength === undefined) {
326
+ return undefined
327
+ }
328
+ const parsed = Number.parseInt(contentLength, 10)
329
+ return Number.isNaN(parsed) ? undefined : parsed
330
+ }
331
+
286
332
  const removeHost = (url: string) => {
287
333
  if (url[0] === "/") {
288
334
  return url
@@ -486,6 +532,347 @@ class ServerRequestImpl extends Inspectable.Class implements HttpServerRequest {
486
532
  }
487
533
  }
488
534
 
535
+ class ClientRequestImpl extends Inspectable.Class implements HttpServerRequest {
536
+ readonly [TypeId]: typeof TypeId
537
+ readonly [HttpIncomingMessage.TypeId]: typeof HttpIncomingMessage.TypeId
538
+ readonly source: HttpClientRequest.HttpClientRequest
539
+ public originalUrl: string
540
+ public headersOverride?: Headers.Headers | undefined
541
+ private remoteAddressOverride?: string | undefined
542
+ private urlOverride?: string | undefined
543
+
544
+ constructor(
545
+ source: HttpClientRequest.HttpClientRequest,
546
+ originalUrl: string,
547
+ urlOverride?: string,
548
+ headersOverride?: Headers.Headers,
549
+ remoteAddressOverride?: string
550
+ ) {
551
+ super()
552
+ this[TypeId] = TypeId
553
+ this[HttpIncomingMessage.TypeId] = HttpIncomingMessage.TypeId
554
+ this.source = source
555
+ this.originalUrl = originalUrl
556
+ this.urlOverride = urlOverride
557
+ this.headersOverride = headersOverride
558
+ this.remoteAddressOverride = remoteAddressOverride
559
+ }
560
+
561
+ toJSON(): unknown {
562
+ return HttpIncomingMessage.inspect(this, {
563
+ _id: "HttpServerRequest",
564
+ method: this.method,
565
+ url: this.originalUrl
566
+ })
567
+ }
568
+
569
+ modify(
570
+ options: {
571
+ readonly url?: string | undefined
572
+ readonly headers?: Headers.Headers | undefined
573
+ readonly remoteAddress?: string | undefined
574
+ }
575
+ ) {
576
+ return new ClientRequestImpl(
577
+ this.source,
578
+ this.originalUrl,
579
+ options.url ?? this.url,
580
+ options.headers ?? this.headersOverride,
581
+ options.remoteAddress ?? this.remoteAddressOverride
582
+ )
583
+ }
584
+
585
+ get method(): HttpMethod {
586
+ return this.source.method
587
+ }
588
+
589
+ get url(): string {
590
+ return this.urlOverride ?? removeHost(this.originalUrl)
591
+ }
592
+
593
+ get remoteAddress(): string | undefined {
594
+ return this.remoteAddressOverride ? this.remoteAddressOverride : undefined
595
+ }
596
+
597
+ get headers(): Headers.Headers {
598
+ return this.headersOverride ??= this.source.headers
599
+ }
600
+
601
+ private cachedCookies: ReadonlyRecord<string, string> | undefined
602
+ get cookies() {
603
+ if (this.cachedCookies) {
604
+ return this.cachedCookies
605
+ }
606
+ return this.cachedCookies = Cookies.parseHeader(this.headers.cookie ?? "")
607
+ }
608
+
609
+ get stream(): Stream.Stream<Uint8Array, HttpServerError> {
610
+ const body = this.source.body
611
+ switch (body._tag) {
612
+ case "Empty": {
613
+ return Stream.empty
614
+ }
615
+ case "Uint8Array": {
616
+ return Stream.succeed(body.body)
617
+ }
618
+ case "Stream": {
619
+ return Stream.mapError(body.stream, (cause) => requestParseError(this, undefined, cause))
620
+ }
621
+ case "FormData": {
622
+ return streamFromReadable(this, new Response(body.formData).body)
623
+ }
624
+ case "Raw": {
625
+ return rawBodyStream(this, body.body)
626
+ }
627
+ }
628
+ }
629
+
630
+ private bytesEffect: Effect.Effect<Uint8Array, HttpServerError> | undefined
631
+ private get bytes(): Effect.Effect<Uint8Array, HttpServerError> {
632
+ if (this.bytesEffect) {
633
+ return this.bytesEffect
634
+ }
635
+ const body = this.source.body
636
+ let effect: Effect.Effect<Uint8Array, HttpServerError>
637
+ switch (body._tag) {
638
+ case "Empty": {
639
+ effect = Effect.succeed(new Uint8Array(0))
640
+ break
641
+ }
642
+ case "Uint8Array": {
643
+ effect = Effect.succeed(body.body)
644
+ break
645
+ }
646
+ case "FormData": {
647
+ effect = bytesFromBodyInit(this, body.formData)
648
+ break
649
+ }
650
+ case "Stream": {
651
+ effect = Stream.mkUint8Array(this.stream)
652
+ break
653
+ }
654
+ case "Raw": {
655
+ effect = rawBodyBytes(this, body.body)
656
+ break
657
+ }
658
+ }
659
+ this.bytesEffect = Effect.runSync(Effect.cached(effect))
660
+ return this.bytesEffect
661
+ }
662
+
663
+ get text(): Effect.Effect<string, HttpServerError> {
664
+ return Effect.map(this.bytes, (bytes) => textDecoder.decode(bytes))
665
+ }
666
+
667
+ get json(): Effect.Effect<unknown, HttpServerError> {
668
+ return Effect.flatMap(this.text, (text) =>
669
+ Effect.try({
670
+ try: () => text === "" ? null : JSON.parse(text) as unknown,
671
+ catch: (cause) => requestParseError(this, undefined, cause)
672
+ }))
673
+ }
674
+
675
+ get urlParamsBody(): Effect.Effect<UrlParams.UrlParams, HttpServerError> {
676
+ return Effect.flatMap(this.text, (_) =>
677
+ Effect.try({
678
+ try: () => UrlParams.fromInput(new URLSearchParams(_)),
679
+ catch: (cause) => requestParseError(this, undefined, cause)
680
+ }))
681
+ }
682
+
683
+ private multipartEffect:
684
+ | Effect.Effect<
685
+ Multipart.Persisted,
686
+ Multipart.MultipartError,
687
+ Scope.Scope | FileSystem.FileSystem | Path.Path
688
+ >
689
+ | undefined
690
+ get multipart(): Effect.Effect<
691
+ Multipart.Persisted,
692
+ Multipart.MultipartError,
693
+ Scope.Scope | FileSystem.FileSystem | Path.Path
694
+ > {
695
+ if (this.multipartEffect) {
696
+ return this.multipartEffect
697
+ }
698
+ this.multipartEffect = Effect.runSync(Effect.cached(
699
+ Multipart.toPersisted(this.multipartStream)
700
+ ))
701
+ return this.multipartEffect
702
+ }
703
+
704
+ get multipartStream(): Stream.Stream<Multipart.Part, Multipart.MultipartError> {
705
+ const formData = this.source.body._tag === "FormData" && this.source.body.formData
706
+ if (formData) {
707
+ return Stream.fromIterable(formDataToParts(formData))
708
+ }
709
+ return Stream.pipeThroughChannel(
710
+ Stream.mapError(this.stream, (cause) => Multipart.MultipartError.fromReason("InternalError", cause)),
711
+ Multipart.makeChannel(this.headers)
712
+ )
713
+ }
714
+
715
+ get arrayBuffer(): Effect.Effect<ArrayBuffer, HttpServerError> {
716
+ return Effect.map(this.bytes, (bytes) => bytes.slice().buffer)
717
+ }
718
+
719
+ get upgrade(): Effect.Effect<Socket.Socket, HttpServerError> {
720
+ return Effect.fail(requestParseError(this, "Not an upgradeable ServerRequest"))
721
+ }
722
+ }
723
+
724
+ const getFormDataBody = (request: HttpServerRequest): FormData | undefined => {
725
+ if (!HttpClientRequest.isHttpClientRequest(request.source)) {
726
+ return undefined
727
+ }
728
+ const body = request.source.body
729
+ if (body._tag === "FormData") {
730
+ return body.formData
731
+ }
732
+ if (body._tag === "Raw" && isFormData(body.body)) {
733
+ return body.body
734
+ }
735
+ return undefined
736
+ }
737
+
738
+ const rawBodyStream = (request: HttpServerRequest, body: unknown): Stream.Stream<Uint8Array, HttpServerError> => {
739
+ if (body instanceof Request) {
740
+ return streamFromReadable(request, body.body)
741
+ }
742
+ if (isFormData(body)) {
743
+ return streamFromReadable(request, new Response(body).body)
744
+ }
745
+ if (isReadableStream(body)) {
746
+ return streamFromReadable(request, body)
747
+ }
748
+ return Stream.fail(requestParseError(request, "Unsupported body type"))
749
+ }
750
+
751
+ const rawBodyBytes = (request: HttpServerRequest, body: unknown): Effect.Effect<Uint8Array, HttpServerError> => {
752
+ if (body instanceof Blob) {
753
+ return bytesFromBodyInit(request, body)
754
+ }
755
+ if (body instanceof Request) {
756
+ return Effect.tryPromise({
757
+ try: () => body.arrayBuffer().then((buffer) => new Uint8Array(buffer)),
758
+ catch: (cause) => requestParseError(request, undefined, cause)
759
+ })
760
+ }
761
+ return Effect.fail(requestParseError(request, "Unsupported body type"))
762
+ }
763
+
764
+ const bytesFromBodyInit = (request: HttpServerRequest, body: BodyInit): Effect.Effect<Uint8Array, HttpServerError> =>
765
+ Effect.tryPromise({
766
+ try: () => new Response(body).arrayBuffer().then((buffer) => new Uint8Array(buffer)),
767
+ catch: (cause) => requestParseError(request, undefined, cause)
768
+ })
769
+
770
+ const streamFromReadable = (
771
+ request: HttpServerRequest,
772
+ body: ReadableStream<Uint8Array> | null | undefined
773
+ ): Stream.Stream<Uint8Array, HttpServerError> =>
774
+ body
775
+ ? Stream.fromReadableStream({
776
+ evaluate: () => body,
777
+ onError: (cause) => requestParseError(request, undefined, cause)
778
+ })
779
+ : Stream.empty
780
+
781
+ const requestParseError = (
782
+ request: HttpServerRequest,
783
+ description?: string,
784
+ cause?: unknown
785
+ ) =>
786
+ new HttpServerError({
787
+ reason: new RequestParseError({
788
+ request,
789
+ ...(description === undefined ? undefined : { description }),
790
+ ...(cause === undefined ? undefined : { cause })
791
+ })
792
+ })
793
+
794
+ const formDataToParts = (formData: FormData): Array<Multipart.Part> => {
795
+ const parts: Array<Multipart.Part> = []
796
+ for (const [key, value] of formData.entries()) {
797
+ parts.push(typeof value === "string" ? new MultipartFieldPart(key, value) : new MultipartFilePart(key, value))
798
+ }
799
+ return parts
800
+ }
801
+
802
+ class MultipartFieldPart extends Inspectable.Class implements Multipart.Field {
803
+ readonly [Multipart.TypeId]: typeof Multipart.TypeId
804
+ readonly _tag = "Field"
805
+ readonly contentType = "text/plain"
806
+ readonly key: string
807
+ readonly value: string
808
+
809
+ constructor(
810
+ key: string,
811
+ value: string
812
+ ) {
813
+ super()
814
+ this[Multipart.TypeId] = Multipart.TypeId
815
+ this.key = key
816
+ this.value = value
817
+ }
818
+
819
+ toJSON(): unknown {
820
+ return {
821
+ _id: "@effect/platform/Multipart/Part",
822
+ _tag: "Field",
823
+ key: this.key,
824
+ contentType: this.contentType,
825
+ value: this.value
826
+ }
827
+ }
828
+ }
829
+
830
+ class MultipartFilePart extends Inspectable.Class implements Multipart.File {
831
+ readonly [Multipart.TypeId]: typeof Multipart.TypeId
832
+ readonly _tag = "File"
833
+ readonly key: string
834
+ readonly name: string
835
+ readonly contentType: string
836
+ readonly content: Stream.Stream<Uint8Array, Multipart.MultipartError>
837
+ readonly contentEffect: Effect.Effect<Uint8Array, Multipart.MultipartError>
838
+
839
+ constructor(
840
+ key: string,
841
+ file: File
842
+ ) {
843
+ super()
844
+ this[Multipart.TypeId] = Multipart.TypeId
845
+ this.key = key
846
+ this.name = file.name
847
+ this.contentType = file.type
848
+ this.content = Stream.fromReadableStream({
849
+ evaluate: () => file.stream() as ReadableStream<Uint8Array>,
850
+ onError: (cause) => Multipart.MultipartError.fromReason("InternalError", cause)
851
+ })
852
+ this.contentEffect = Effect.tryPromise({
853
+ try: () => file.arrayBuffer().then((buffer) => new Uint8Array(buffer)),
854
+ catch: (cause) => Multipart.MultipartError.fromReason("InternalError", cause)
855
+ })
856
+ }
857
+
858
+ toJSON(): unknown {
859
+ return {
860
+ _id: "@effect/platform/Multipart/Part",
861
+ _tag: "File",
862
+ key: this.key,
863
+ name: this.name,
864
+ contentType: this.contentType
865
+ }
866
+ }
867
+ }
868
+
869
+ const isReadableStream = (u: unknown): u is ReadableStream<Uint8Array> =>
870
+ typeof ReadableStream !== "undefined" && u instanceof ReadableStream
871
+
872
+ const isFormData = (u: unknown): u is FormData => typeof FormData !== "undefined" && u instanceof FormData
873
+
874
+ const textDecoder = new TextDecoder()
875
+
489
876
  /**
490
877
  * @since 4.0.0
491
878
  * @category conversions