@@ -0,0 +1,191 @@
1+module Web.Fetch.Request
2+ ( Request
3+ , RequestOptions
4+ , UnsafeRequestOptions
5+ , new
6+ , new'
7+ , unsafeNew
8+ , class BuildRequestOptions
9+ , buildRequestOptions
10+ , defaultOptions
11+ , defaultUnsafeOptions
12+ , class ConvertOptions
13+ , convertOptions
14+ , class ConvertOption
15+ , convertOption
16+ ) where
17+
18+import Prelude
19+
20+import Data.ArrayBuffer.Types (ArrayBuffer, ArrayView)
21+import Data.HTTP.Method (Method(..))
22+import Data.Maybe (Maybe(..))
23+import Data.Newtype (un)
24+import Data.Nullable (Nullable, toNullable)
25+import Data.Symbol (class IsSymbol, SProxy(..))
26+import Data.Tuple (Tuple)
27+import Effect (Effect)
28+import Effect.Uncurried (EffectFn2, runEffectFn2)
29+import Foreign.Object (Object)
30+import Prim.Row as Row
31+import Prim.RowList (kind RowList)
32+import Prim.RowList as RowList
33+import Record (merge)
34+import Record.Builder as Record
35+import Type.Data.RowList (RLProxy(..))
36+import Type.Row.Homogeneous (class Homogeneous)
37+import Web.Fetch.Headers (Headers)
38+import Web.Fetch.Headers as Headers
39+import Web.Fetch.Integrity (Integrity(..))
40+import Web.Fetch.Referrer (Referrer)
41+import Web.Fetch.Referrer as Referrer
42+import Web.Fetch.ReferrerPolicy (ReferrerPolicy)
43+import Web.Fetch.ReferrerPolicy as ReferrerPolicy
44+import Web.Fetch.RequestBody (RequestBody)
45+import Web.Fetch.RequestBody as RequestBody
46+import Web.Fetch.RequestCache (RequestCache)
47+import Web.Fetch.RequestCache as RequestCache
48+import Web.Fetch.RequestCredentials (RequestCredentials)
49+import Web.Fetch.RequestCredentials as RequestCredentials
50+import Web.Fetch.RequestMode (RequestMode)
51+import Web.Fetch.RequestMode as RequestMode
52+
53+foreign import data Request :: Type
54+
55+foreign import _unsafeNew :: forall r. EffectFn2 String { | r } Request
56+
57+type UnsafeRequestOptions =
58+ ( method :: String
59+ , headers :: Headers
60+ , body :: RequestBody
61+ , credentials :: String
62+ , cache :: String
63+ , mode :: String
64+ , referrer :: Nullable String
65+ , referrerPolicy :: String
66+ , integrity :: String
67+ )
68+
69+type RequestOptions =
70+ ( method :: Method
71+ , headers :: Headers
72+ , body :: RequestBody
73+ , credentials :: RequestCredentials
74+ , cache :: RequestCache
75+ , mode :: RequestMode
76+ , referrer :: Maybe Referrer
77+ , referrerPolicy :: ReferrerPolicy
78+ , integrity :: Integrity
79+ )
80+
81+defaultOptions :: { | RequestOptions }
82+defaultOptions =
83+ { method: GET
84+ , headers: Headers.empty
85+ , body: RequestBody.empty
86+ , credentials: RequestCredentials.SameOrigin
87+ , cache: RequestCache.Default
88+ , mode: RequestMode.Cors
89+ , referrer: Nothing
90+ , referrerPolicy: ReferrerPolicy.NoReferrer
91+ , integrity: Integrity ""
92+ }
93+
94+defaultUnsafeOptions :: { | UnsafeRequestOptions }
95+defaultUnsafeOptions = toUnsafeOptions defaultOptions
96+
97+toUnsafeOptions :: { | RequestOptions } -> { | UnsafeRequestOptions }
98+toUnsafeOptions opts =
99+ { method: show opts.method
100+ , headers: opts.headers
101+ , body: opts.body
102+ , credentials: RequestCredentials.toString opts.credentials
103+ , cache: RequestCache.toString opts.cache
104+ , mode: RequestMode.toString opts.mode
105+ , referrer: toNullable $ Referrer.toString <$> opts.referrer
106+ , referrerPolicy: ReferrerPolicy.toString opts.referrerPolicy
107+ , integrity: un Integrity opts.integrity
108+ }
109+
110+unsafeNew :: String -> { | UnsafeRequestOptions } -> Effect Request
111+unsafeNew = runEffectFn2 _unsafeNew
112+
113+new :: String -> { | RequestOptions } -> Effect Request
114+new url options = runEffectFn2 _unsafeNew url (toUnsafeOptions options)
115+
116+new' :: forall r. BuildRequestOptions { | r } => String -> { | r } -> Effect Request
117+new' url options = runEffectFn2 _unsafeNew url (toUnsafeOptions (buildRequestOptions options))
118+
119+class BuildRequestOptions a where
120+ buildRequestOptions :: a -> { | RequestOptions }
121+
122+instance buildRequestOptionsRecord
123+ :: ( RowList.RowToList r rl
124+ , ConvertOptions rl r r'
125+ , Row.Union r' RequestOptions r''
126+ , Row.Nub r'' RequestOptions
127+ )
128+ => BuildRequestOptions { | r } where
129+ buildRequestOptions r = merge (Record.build (convertOptions (RLProxy :: _ rl)) r) defaultOptions
130+
131+class ConvertOptions (rl :: RowList) (input :: # Type) (output :: # Type) | rl input -> output where
132+ convertOptions :: RLProxy rl -> Record.Builder { | input } { | output }
133+
134+instance convertOptionsCons ::
135+ ( ConvertOptions rest input' output
136+ , ConvertOption field from to
137+ , Row.Cons field from rx input
138+ , Row.Cons field to rx input'
139+ , IsSymbol field
140+ ) => ConvertOptions (RowList.Cons field from rest) input output where
141+ convertOptions _ =
142+ convertOptions (RLProxy :: _ rest)
143+ <<< Record.modify (SProxy :: _ field) (convertOption (SProxy :: _ field))
144+
145+instance convertOptionsNil :: ConvertOptions RowList.Nil r r where
146+ convertOptions _ = identity
147+
148+class ConvertOption (field :: Symbol) from to | field -> to where
149+ convertOption :: SProxy field -> from -> to
150+
151+instance convertMethod :: ConvertOption "method" Method Method where
152+ convertOption _ = identity
153+
154+instance convertBody :: ConvertOption "body" RequestBody RequestBody where
155+ convertOption _ = identity
156+
157+instance convertBodyString :: ConvertOption "body" String RequestBody where
158+ convertOption _ = RequestBody.fromString
159+
160+instance convertBodyBuffer :: ConvertOption "body" ArrayBuffer RequestBody where
161+ convertOption _ = RequestBody.fromArrayBuffer
162+
163+instance convertBodyView :: ConvertOption "body" (ArrayView t) RequestBody where
164+ convertOption _ = RequestBody.fromArrayView
165+
166+instance convertHeaders :: ConvertOption "headers" Headers Headers where
167+ convertOption _ = identity
168+
169+instance convertHeadersRecord :: Homogeneous r String => ConvertOption "headers" { | r } Headers where
170+ convertOption _ = Headers.fromRecord
171+
172+instance convertHeadersObject :: ConvertOption "headers" (Object String) Headers where
173+ convertOption _ = Headers.fromObject
174+
175+instance convertHeadersArray :: ConvertOption "headers" (Array (Tuple String String)) Headers where
176+ convertOption _ = Headers.fromFoldable
177+
178+instance convertCache :: ConvertOption "cache" RequestCache RequestCache where
179+ convertOption _ = identity
180+
181+instance convertMode :: ConvertOption "mode" RequestMode RequestMode where
182+ convertOption _ = identity
183+
184+instance convertReferrer :: ConvertOption "referrer" Referrer (Maybe Referrer) where
185+ convertOption _ = Just
186+
187+instance convertReferrerPolicy :: ConvertOption "referrerPolicy" ReferrerPolicy ReferrerPolicy where
188+ convertOption _ = identity
189+
190+instance convertIntegrity :: ConvertOption "integrity" Integrity Integrity where
191+ convertOption _ = identity