fix: spago

This commit is contained in:
orion 2024-06-10 12:16:33 -05:00
parent edf5207dfc
commit 66f87f413b
Signed by: orion
GPG Key ID: 6D4165AE4C928719
18 changed files with 147 additions and 124 deletions

29
README.md Normal file
View File

@ -0,0 +1,29 @@
# purescript-ezfetch
High-level bindings to the native `fetch` API
## `Effect.Aff.HTTP`
The main entry point is `Effect.Aff.HTTP.fetch`:
```purescript
fetch <method> <url> <options>
```
* `<method>` is `Effect.Aff.HTTP.Request.Method`:
```purescript
data Method
= GET
| PUT
| POST
| DELETE
| PATCH
| HEAD
```
* `<url>` is `Data.URL.URL` (from [`url-immutable`](https://pursuit.purescript.org/packages/purescript-url-immutable/))
* `<options>` is a partial record of:
```purescript
type OptionalFields =
( body :: Body
, headers :: Headers
, credentials :: Credentials
)
```

34
bun/prepare.js Normal file
View File

@ -0,0 +1,34 @@
import { readFile, writeFile } from 'fs/promises'
import { execSync } from 'child_process'
let ver = process.argv[2]
if (!ver) {
console.error(`tag required: bun bun/prepare.js v1.0.0`)
process.exit(1)
} else if (!/v\d+\.\d+\.\d+/.test(ver)) {
console.error(`invalid tag: ${ver}`)
process.exit(1)
}
ver = (/\d+\.\d+\.\d+/.exec(ver) || [])[0] || ''
const pkg = await readFile('./package.json', 'utf8')
const pkgnew = pkg.replace(/"version": ".+"/, `"version": "v${ver}"`)
await writeFile('./package.json', pkgnew)
const spago = await readFile('./spago.yaml', 'utf8')
const spagonew = spago.replace(/version: .+/, `version: '${ver}'`)
await writeFile('./spago.yaml', spagonew)
const readme = await readFile('./README.md', 'utf8')
const readmenew = readme.replace(
/packages\/purescript-fetch\/.+?\//g,
`/packages/purescript-fetch/${ver}/`,
)
await writeFile('./README.md', readmenew)
execSync(`git add spago.yaml package.json README.md`)
execSync(`git commit -m 'chore: prepare v${ver}'`)
execSync(`git tag v${ver}`)
execSync(`git push --tags`)
execSync(`git push --mirror github-mirror`)

View File

@ -1,5 +1,5 @@
{
"name": "purs",
"name": "purescript-ezfetch",
"private": true,
"module": "index.js",
"type": "module",

View File

@ -1,6 +1,6 @@
workspace:
packages:
fetch:
ezfetch:
path: ./
dependencies:
- aff: ">=7.1.0 <8.0.0"
@ -28,7 +28,7 @@ workspace:
- transformers: ">=6.0.0 <7.0.0"
- tuples: ">=7.0.0 <8.0.0"
- unsafe-coerce: ">=6.0.0 <7.0.0"
- url: "*"
- url-immutable: ">=1.0.0 <2.0.0"
- web-file: ">=4.0.0 <5.0.0"
- web-streams: ">=4.0.0 <5.0.0"
test_dependencies: []
@ -86,6 +86,7 @@ workspace:
- simple-json
- st
- strings
- stringutils
- tailrec
- transformers
- tuples
@ -94,29 +95,13 @@ workspace:
- uint
- unfoldable
- unsafe-coerce
- url
- url-immutable
- variant
- web-dom
- web-events
- web-file
- web-streams
extra_packages:
url:
git: https://git.orionkindel.com/thunderstrike/purescript-url-immutable.git
ref: dbfa3b6
dependencies:
- arrays
- effect
- filterable
- foldable-traversable
- integers
- maybe
- newtype
- nullable
- ordered-collections
- prelude
- strings
- tuples
extra_packages: {}
packages:
aff:
type: registry
@ -701,6 +686,17 @@ packages:
- tuples
- unfoldable
- unsafe-coerce
stringutils:
type: registry
version: 0.0.12
integrity: sha256-t63QWBlp49U0nRqUcFryKflSJsNKGTQAHKjn24/+ooI=
dependencies:
- arrays
- integers
- maybe
- partial
- prelude
- strings
tailrec:
type: registry
version: 6.1.0
@ -779,22 +775,28 @@ packages:
version: 6.0.0
integrity: sha256-IqIYW4Vkevn8sI+6aUwRGvd87tVL36BBeOr0cGAE7t0=
dependencies: []
url:
type: git
url: https://git.orionkindel.com/thunderstrike/purescript-url-immutable.git
rev: dbfa3b6e3b01b2d6c7b02202054d52754f000b20
url-immutable:
type: registry
version: 1.0.0
integrity: sha256-6uCg5k4fjrqyTYUYKTmcykXgXCJKsvVpzx+gZJczAx0=
dependencies:
- arrays
- effect
- bifunctors
- either
- filterable
- foldable-traversable
- foreign
- integers
- maybe
- newtype
- nullable
- ordered-collections
- partial
- prelude
- simple-json
- strings
- stringutils
- transformers
- tuples
variant:
type: registry

View File

@ -1,4 +1,6 @@
workspace: {}
package:
name: 'ezfetch'
dependencies:
- aff: ">=7.1.0 <8.0.0"
- aff-promise: ">=4.0.0 <5.0.0"
@ -25,25 +27,6 @@ package:
- transformers: ">=6.0.0 <7.0.0"
- tuples: ">=7.0.0 <8.0.0"
- unsafe-coerce: ">=6.0.0 <7.0.0"
- url: "*"
- url-immutable: ">=1.0.0 <2.0.0"
- web-file: ">=4.0.0 <5.0.0"
- web-streams: ">=4.0.0 <5.0.0"
name: fetch
workspace:
extraPackages:
url:
git: 'https://git.orionkindel.com/thunderstrike/purescript-url-immutable.git'
ref: 'dbfa3b6'
dependencies:
- arrays
- effect
- filterable
- foldable-traversable
- integers
- maybe
- newtype
- nullable
- ordered-collections
- prelude
- strings
- tuples

View File

@ -1,4 +1,4 @@
module HTTP.MIME where
module Data.MIME where
import Prelude

View File

@ -1,25 +0,0 @@
module Data.Tuple.Containing where
import Prelude
import Data.Tuple (Tuple, fst, snd)
import Data.Tuple.Nested (type (/\), (/\))
-- | given a tuple of any size with at least 1 value
-- | of type `a`, `extract` the first occurence of `a`
-- | from the tuple
class TupleContaining a tup where
extract :: tup -> a
instance TupleContaining a a where
extract = identity
else instance TupleContaining a (a /\ b) where
extract = fst
else instance TupleContaining b (a /\ b) where
extract = snd
else instance TupleContaining b (a /\ b /\ rest) where
extract (_ /\ b /\ _) = b
else instance TupleContaining c (a /\ b /\ c /\ Unit) where
extract (_ /\ _ /\ c /\ _) = c
else instance TupleContaining a tail => TupleContaining a (Tuple head tail) where
extract (_ /\ tail) = extract tail

View File

@ -9,5 +9,4 @@
*/
/** @type {(o: RequestInit) => () => Promise<Response>} */
export const fetchImpl = o => () =>
fetch(o.url, {...o, redirect: 'manual'})
export const fetchImpl = o => () => fetch(o.url, { ...o, redirect: 'manual' })

View File

@ -1,4 +1,4 @@
module HTTP (fetch, fetchWithDefaults, OptionalFields, module X) where
module Effect.Aff.HTTP (fetch, fetchWithDefaults, OptionalFields, module X) where
import Prelude
@ -13,12 +13,12 @@ import Effect (Effect)
import Effect.Aff.Class (class MonadAff, liftAff)
import Foreign.Object (Object)
import Foreign.Object as Object
import HTTP.Header (Headers)
import HTTP.Header (headers) as X
import HTTP.Request (Body(..), Credentials(..), Method, RawBody, bodyHeaders, bodyToRaw)
import HTTP.Request (Method(..)) as X
import HTTP.Request as Req
import HTTP.Response (Response)
import Effect.Aff.HTTP.Header (Headers)
import Effect.Aff.HTTP.Header (headers) as X
import Effect.Aff.HTTP.Request (Body(..), Credentials(..), Method, RawBody, bodyHeaders, bodyToRaw)
import Effect.Aff.HTTP.Request (Method(..)) as X
import Effect.Aff.HTTP.Request as Req
import Effect.Aff.HTTP.Response (Response)
import Prim.Row (class Nub, class Union)
import Record as Record
import Type.Prelude (Proxy(..))
@ -54,7 +54,7 @@ makeOptionalFields
=> Union x OptionalFields o
=> Union x xm OptionalFields
=> Record OptionalFields
-> {|x}
-> { | x }
-> Record OptionalFields
makeOptionalFields d x = Record.merge x d
@ -67,7 +67,7 @@ fetchWithDefaults
=> Record OptionalFields
-> Method
-> URL
-> {|x}
-> { | x }
-> m Response
fetchWithDefaults defaults' method url x =
let
@ -86,20 +86,21 @@ fetchWithDefaults defaults' method url x =
fields =
Record.modify (Proxy @"credentials") credsStr
$ Record.modify (Proxy @"headers") (Object.fromFoldableWithIndex <<< unwrap)
$ Record.insert (Proxy @"method") methodStr
$ Record.insert (Proxy @"url") (URL.toString url)
$ makeOptionalFields @x defaults' x
in do
bodyHeaders' <- (Object.fromFoldableWithIndex <<< unwrap) <$> bodyHeaders fields.body
bodyRaw <- Nullable.toNullable <$> bodyToRaw fields.body
let
fields' =
Record.modify (Proxy @"headers") (Object.union bodyHeaders')
$ Record.set (Proxy @"body") bodyRaw
$ fields
$ Record.modify (Proxy @"headers") (Object.fromFoldableWithIndex <<< unwrap)
$ Record.insert (Proxy @"method") methodStr
$ Record.insert (Proxy @"url") (URL.toString url)
$ makeOptionalFields @x defaults' x
in
do
bodyHeaders' <- (Object.fromFoldableWithIndex <<< unwrap) <$> bodyHeaders fields.body
bodyRaw <- Nullable.toNullable <$> bodyToRaw fields.body
let
fields' =
Record.modify (Proxy @"headers") (Object.union bodyHeaders')
$ Record.set (Proxy @"body") bodyRaw
$ fields
liftAff $ Promise.toAffE $ fetchImpl fields'
liftAff $ Promise.toAffE $ fetchImpl fields'
fetch
:: forall x xm m o
@ -109,6 +110,6 @@ fetch
=> Union x xm OptionalFields
=> Method
-> URL
-> {|x}
-> { | x }
-> m Response
fetch = fetchWithDefaults defaults

View File

@ -1,4 +1,4 @@
module HTTP.Form where
module Effect.Aff.HTTP.Form where
import Prelude
@ -25,8 +25,8 @@ import Effect.Exception (error)
import Foreign (Foreign, unsafeReadTagged, unsafeToForeign)
import Foreign.Object (Object)
import Foreign.Object as Object
import HTTP.MIME (MIME)
import HTTP.MIME as MIME
import Data.MIME (MIME)
import Data.MIME as MIME
import Simple.JSON (readImpl, unsafeStringify)
import Unsafe.Coerce (unsafeCoerce)
import Web.File.Blob (Blob)

View File

@ -1,4 +1,4 @@
module HTTP.Header where
module Effect.Aff.HTTP.Header where
import Prelude
@ -14,8 +14,8 @@ import Data.String.Base64 as String.Base64
import Data.Tuple (Tuple(..))
import Effect (Effect)
import Effect.Class (class MonadEffect, liftEffect)
import HTTP.MIME (MIME)
import HTTP.MIME as MIME
import Data.MIME (MIME)
import Data.MIME as MIME
newtype ContentType = ContentType MIME

View File

@ -9,8 +9,8 @@ export const rawBodySize = body => () =>
body instanceof ArrayBuffer
? body.byteLength
: body instanceof FormData
? Array.from(body.entries()).reduce(
(size, [k, v]) => size + k.length + formDataValueSize(v),
0,
)
: 0
? Array.from(body.entries()).reduce(
(size, [k, v]) => size + k.length + formDataValueSize(v),
0,
)
: 0

View File

@ -1,4 +1,4 @@
module HTTP.Request
module Effect.Aff.HTTP.Request
( Credentials(..)
, Body(..)
, RawBody
@ -25,12 +25,12 @@ import Data.Show.Generic (genericShow)
import Effect (Effect)
import Effect.Aff.Class (class MonadAff, liftAff)
import Effect.Class (class MonadEffect, liftEffect)
import HTTP.Form (Form, RawFormData)
import HTTP.Form as Form
import HTTP.Header (ContentType(..), Headers)
import HTTP.Header as Header
import HTTP.MIME (MIME)
import HTTP.MIME as MIME
import Effect.Aff.HTTP.Form (Form, RawFormData)
import Effect.Aff.HTTP.Form as Form
import Effect.Aff.HTTP.Header (ContentType(..), Headers)
import Effect.Aff.HTTP.Header as Header
import Data.MIME (MIME)
import Data.MIME as MIME
import Simple.JSON (class WriteForeign, writeJSON)
import Unsafe.Coerce (unsafeCoerce)
import Web.File.Blob (Blob)

View File

@ -1,5 +1,5 @@
import { Readable } from 'stream';
import { Buffer } from 'buffer';
import { Readable } from 'stream'
import { Buffer } from 'buffer'
/** @type {(r: Response) => () => Promise<Buffer>} */
export const bufferImpl = r => async () => Buffer.from(await r.arrayBuffer())
@ -10,7 +10,7 @@ export const streamImpl = r => () => {
throw new Error('Response body is empty')
}
const reader = r.body.getReader();
const reader = r.body.getReader()
return new Readable({
read() {
reader

View File

@ -1,4 +1,4 @@
module HTTP.Response.Node
module Effect.Aff.HTTP.Response.Node
( module X
, buffer
, stream
@ -11,8 +11,8 @@ 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)
import HTTP.Response hiding (stream) as X
import Effect.Aff.HTTP.Response (Response)
import Effect.Aff.HTTP.Response hiding (stream) as X
import Node.Buffer (Buffer)
import Node.Stream (Readable)

View File

@ -1,4 +1,4 @@
module HTTP.Response
module Effect.Aff.HTTP.Response
( Response(..)
, stream
, clone
@ -31,8 +31,8 @@ import Effect.Class (class MonadEffect, liftEffect)
import Effect.Exception (Error, error)
import Foreign (Foreign)
import Foreign.Object (Object)
import HTTP.Form (Form, RawFormData)
import HTTP.Form as Form
import Effect.Aff.HTTP.Form (Form, RawFormData)
import Effect.Aff.HTTP.Form as Form
import Simple.JSON (class ReadForeign, readImpl)
import Web.File.Blob (Blob)
import Web.Streams.ReadableStream (ReadableStream)