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 - maybe
- newtype - newtype
- node-buffer - node-buffer
- node-streams
- nullable - nullable
- numbers - numbers
- ordered-collections - ordered-collections
@ -28,6 +29,7 @@ workspace:
- unsafe-coerce - unsafe-coerce
- url - url
- web-file - web-file
- web-streams
test_dependencies: [] test_dependencies: []
build_plan: build_plan:
- aff - aff
@ -57,12 +59,15 @@ workspace:
- identity - identity
- integers - integers
- invariant - invariant
- js-promise
- lazy - lazy
- lists - lists
- maybe - maybe
- media-types - media-types
- newtype - newtype
- node-buffer - node-buffer
- node-event-emitter
- node-streams
- nonempty - nonempty
- nullable - nullable
- numbers - numbers
@ -91,6 +96,7 @@ workspace:
- web-dom - web-dom
- web-events - web-events
- web-file - web-file
- web-streams
package_set: package_set:
address: address:
hash: sha256-nTsd44o7/hrTdk0c6dh0wyBqhFFDJJIeKdQU6L1zv/A= hash: sha256-nTsd44o7/hrTdk0c6dh0wyBqhFFDJJIeKdQU6L1zv/A=
@ -6036,6 +6042,17 @@ packages:
dependencies: dependencies:
- control - control
- prelude - 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: lazy:
type: git type: git
url: https://github.com/purescript/purescript-lazy.git url: https://github.com/purescript/purescript-lazy.git
@ -6096,6 +6113,31 @@ packages:
- nullable - nullable
- st - st
- unsafe-coerce - 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: nonempty:
type: git type: git
url: https://github.com/purescript/purescript-nonempty.git url: https://github.com/purescript/purescript-nonempty.git
@ -6380,3 +6422,15 @@ packages:
- foreign - foreign
- media-types - media-types
- web-dom - 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 - maybe
- newtype - newtype
- node-buffer - node-buffer
- url - node-streams
- nullable - nullable
- numbers - numbers
- ordered-collections - ordered-collections
@ -24,10 +24,12 @@ package:
- transformers - transformers
- tuples - tuples
- unsafe-coerce - unsafe-coerce
- url
- web-file - web-file
- web-streams
name: fetch name: fetch
workspace: workspace:
extra_packages: extraPackages:
url: url:
git: 'https://git.orionkindel.com/thunderstrike/purescript-url-immutable.git' git: 'https://git.orionkindel.com/thunderstrike/purescript-url-immutable.git'
ref: 'dbfa3b6' ref: 'dbfa3b6'
@ -44,6 +46,6 @@ workspace:
- prelude - prelude
- strings - strings
- tuples - tuples
package_set: packageSet:
url: https://raw.githubusercontent.com/purescript/package-sets/psc-0.15.10-20230930/packages.json url: https://raw.githubusercontent.com/purescript/package-sets/psc-0.15.10-20230930/packages.json
hash: sha256-nTsd44o7/hrTdk0c6dh0wyBqhFFDJJIeKdQU6L1zv/A= 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} */ /** @type {(_: Response) => () => Response} */
export const cloneImpl = rep => () => rep.clone() export const cloneImpl = rep => () => rep.clone()
/** @type {(_: Response) => () => ReadableStream} */
export const streamImpl = rep => () => rep.body
/** @type {(_: Response) => () => Promise<unknown>} */ /** @type {(_: Response) => () => Promise<unknown>} */
export const jsonImpl = rep => () => rep.json() export const jsonImpl = rep => () => rep.json()

View File

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