feat: response.node stream, buffer

This commit is contained in:
orion 2024-04-21 18:00:07 -05:00
parent aa6b8b811f
commit e3168981ef
Signed by: orion
GPG Key ID: 6D4165AE4C928719
7 changed files with 125 additions and 4 deletions

BIN
bun.lockb

Binary file not shown.

View File

@ -18,6 +18,7 @@ workspace:
- maybe
- newtype
- node-buffer
- node-streams
- nullable
- numbers
- ordered-collections
@ -28,6 +29,7 @@ workspace:
- unsafe-coerce
- url
- web-file
- web-streams
test_dependencies: []
build_plan:
- aff
@ -57,12 +59,15 @@ workspace:
- identity
- integers
- invariant
- js-promise
- lazy
- lists
- maybe
- media-types
- newtype
- node-buffer
- node-event-emitter
- node-streams
- nonempty
- nullable
- numbers
@ -91,6 +96,7 @@ workspace:
- web-dom
- web-events
- web-file
- web-streams
package_set:
address:
hash: sha256-nTsd44o7/hrTdk0c6dh0wyBqhFFDJJIeKdQU6L1zv/A=
@ -6036,6 +6042,17 @@ packages:
dependencies:
- control
- prelude
js-promise:
type: git
url: https://github.com/purescript-contrib/purescript-js-promise.git
rev: ff731bceb7f22827322d5cabdb50f4427dbe9940
dependencies:
- effect
- exceptions
- foldable-traversable
- functions
- maybe
- prelude
lazy:
type: git
url: https://github.com/purescript/purescript-lazy.git
@ -6096,6 +6113,31 @@ packages:
- nullable
- st
- unsafe-coerce
node-event-emitter:
type: git
url: https://github.com/purescript-node/purescript-node-event-emitter.git
rev: b283c3eb6abc32a88fd8876af746b9548e78d93f
dependencies:
- effect
- either
- functions
- maybe
- nullable
- prelude
- unsafe-coerce
node-streams:
type: git
url: https://github.com/purescript-node/purescript-node-streams.git
rev: 8aaec35f1c6316924e360274cd248edee01eae4f
dependencies:
- aff
- effect
- either
- exceptions
- node-buffer
- node-event-emitter
- nullable
- prelude
nonempty:
type: git
url: https://github.com/purescript/purescript-nonempty.git
@ -6380,3 +6422,15 @@ packages:
- foreign
- media-types
- web-dom
web-streams:
type: git
url: https://github.com/purescript-web/purescript-web-streams.git
rev: b89cd269b71e818cc32a9452c590f14cfaf50c59
dependencies:
- arraybuffer-types
- effect
- exceptions
- js-promise
- nullable
- prelude
- tuples

View File

@ -15,7 +15,7 @@ package:
- maybe
- newtype
- node-buffer
- url
- node-streams
- nullable
- numbers
- ordered-collections
@ -24,10 +24,12 @@ package:
- transformers
- tuples
- unsafe-coerce
- url
- web-file
- web-streams
name: fetch
workspace:
extra_packages:
extraPackages:
url:
git: 'https://git.orionkindel.com/thunderstrike/purescript-url-immutable.git'
ref: 'dbfa3b6'
@ -44,6 +46,6 @@ workspace:
- prelude
- strings
- tuples
package_set:
packageSet:
url: https://raw.githubusercontent.com/purescript/package-sets/psc-0.15.10-20230930/packages.json
hash: sha256-nTsd44o7/hrTdk0c6dh0wyBqhFFDJJIeKdQU6L1zv/A=

30
src/HTTP/Response.Node.js Normal file
View File

@ -0,0 +1,30 @@
import { Readable } from 'stream';
import { Buffer } from 'buffer';
/** @type {(r: Response) => () => Promise<Buffer>} */
export const bufferImpl = r => async () => Buffer.from(await r.arrayBuffer())
/** @type {(r: Response) => () => Readable} */
export const streamImpl = r => () => {
if (!r.body) {
throw new Error('Response body is empty')
}
const reader = r.body.getReader();
return new Readable({
read() {
reader
.read()
.then(chunk => {
if (chunk.value) {
this.push(Buffer.from(chunk.value))
}
if (chunk.done) {
this.push(null)
}
})
.catch(e => this.destroy(e))
},
})
}

View File

@ -0,0 +1,26 @@
module HTTP.Response.Node
( module X
, buffer
, stream
) where
import Prelude
import Control.Promise (Promise)
import Control.Promise as Promise
import Effect (Effect)
import Effect.Aff.Class (class MonadAff, liftAff)
import Effect.Class (class MonadEffect, liftEffect)
import HTTP.Response (Response, stream)
import HTTP.Response hiding (stream) as X
import Node.Buffer (Buffer)
import Node.Stream (Stream, Readable)
foreign import bufferImpl :: Response -> Effect (Promise Buffer)
foreign import streamImpl :: Response -> Effect (Readable ())
buffer :: forall m. MonadAff m => Response -> m Buffer
buffer = liftAff <<< Promise.toAffE <<< bufferImpl
stream :: forall m. MonadEffect m => Response -> m (Readable ())
stream = liftEffect <<< streamImpl

View File

@ -3,6 +3,9 @@
/** @type {(_: Response) => () => Response} */
export const cloneImpl = rep => () => rep.clone()
/** @type {(_: Response) => () => ReadableStream} */
export const streamImpl = rep => () => rep.body
/** @type {(_: Response) => () => Promise<unknown>} */
export const jsonImpl = rep => () => rep.json()

View File

@ -1,5 +1,6 @@
module HTTP.Response
( Response(..)
, stream
, clone
, json
, text
@ -18,7 +19,7 @@ import Control.Monad.Error.Class (class MonadThrow, liftEither, throwError)
import Control.Monad.Except (runExcept)
import Control.Promise (Promise)
import Control.Promise as Promise
import Data.ArrayBuffer.Types (ArrayBuffer)
import Data.ArrayBuffer.Types (ArrayBuffer, ArrayView, Uint8)
import Data.Bifunctor (lmap)
import Data.Int as Int
import Data.Map (Map)
@ -34,6 +35,7 @@ import HTTP.Form (Form, RawFormData)
import HTTP.Form as Form
import Simple.JSON (class ReadForeign, readImpl)
import Web.File.Blob (Blob)
import Web.Streams.ReadableStream (ReadableStream)
foreign import data Response :: Type
@ -46,6 +48,7 @@ foreign import textImpl :: Response -> Effect (Promise String)
foreign import abImpl :: Response -> Effect (Promise ArrayBuffer)
foreign import blobImpl :: Response -> Effect (Promise Blob)
foreign import formImpl :: Response -> Effect (Promise RawFormData)
foreign import streamImpl :: Response -> Effect (ReadableStream (ArrayView Uint8))
guardStatusOk :: forall m. MonadAff m => MonadThrow Error m => Response -> m Unit
guardStatusOk rep = do
@ -68,6 +71,9 @@ text = liftAff <<< Promise.toAffE <<< textImpl
blob :: forall m. MonadAff m => Response -> m Blob
blob = liftAff <<< Promise.toAffE <<< blobImpl
stream :: forall m. MonadEffect m => Response -> m (ReadableStream (ArrayView Uint8))
stream = liftEffect <<< streamImpl
arrayBuffer :: forall m. MonadAff m => Response -> m ArrayBuffer
arrayBuffer = liftAff <<< Promise.toAffE <<< abImpl