/
Urql.purs
131 lines (108 loc) · 3.99 KB
/
Urql.purs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
-- | Creates GraphQL clients
module GraphQL.Client.BaseClients.Urql
( UrqlClientOptions
, UrqlSubClientOptions
, UrqlClient
, UrqlSubClient
, createClient
, createGlobalClientUnsafe
, createSubscriptionClient
) where
import Prelude
import Affjax (URL)
import Affjax.RequestHeader (RequestHeader, name, value)
import Data.Argonaut.Core (Json)
import Data.Tuple (Tuple(..))
import Effect (Effect)
import Effect.Aff (Aff)
import Effect.Aff.Compat (EffectFnAff, fromEffectFnAff)
import Foreign (Foreign, unsafeToForeign)
import Foreign.Object (Object)
import Foreign.Object as Object
import GraphQL.Client.Types (class QueryClient, class SubscriptionClient, Client(..))
type UrqlClientOptions
= { url :: URL
, headers :: Array RequestHeader
}
type UrqlSubClientOptions
= { url :: URL
, websocketUrl :: URL
, headers :: Array RequestHeader
}
-- | A client to make graphQL queries and mutations.
-- | From the @urql/core npm module
foreign import data UrqlClient :: Type
-- | A client to make graphQL queries, mutations and subscriptions.
-- | Requires a web socket graphQL server.
-- | From the @urql/core npm module
-- | Requires your server to implement GraphQL over WebSocket Protocol
-- | See https://github.com/enisdenjo/graphql-ws details
foreign import data UrqlSubClient :: Type
createClient ::
forall querySchema mutationSchema subscriptionSchema.
UrqlClientOptions -> Effect (Client UrqlClient querySchema mutationSchema subscriptionSchema)
createClient = clientOptsToForeign >>> createClientImpl >>> map Client
createGlobalClientUnsafe ::
forall querySchema mutationSchema subscriptionSchema.
UrqlClientOptions -> Effect (Client UrqlClient querySchema mutationSchema subscriptionSchema)
createGlobalClientUnsafe = clientOptsToForeign >>> createGlobalClientUnsafeImpl >>> map Client
createSubscriptionClient ::
forall querySchema mutationSchema subscriptionSchema.
UrqlSubClientOptions ->
Effect (Client UrqlSubClient querySchema mutationSchema subscriptionSchema)
createSubscriptionClient = clientOptsToForeign >>> createSubscriptionClientImpl >>> map Client
clientOptsToForeign ::
forall r.
{ headers :: Array RequestHeader
| r
} ->
{ headers :: Object String
| r
}
clientOptsToForeign opts =
opts
{ headers = Object.fromFoldable $ map toTup opts.headers
}
where
toTup header = Tuple (name header) (value header)
type UrqlClientOptionsForeign
= { url :: URL
, headers :: Object String
}
type UrqlSubUrqlClientOptionsForeign
= { url :: URL
, websocketUrl :: URL
, headers :: Object String
}
foreign import createClientImpl :: UrqlClientOptionsForeign -> Effect UrqlClient
foreign import createGlobalClientUnsafeImpl :: UrqlClientOptionsForeign -> Effect UrqlClient
foreign import createSubscriptionClientImpl :: UrqlSubUrqlClientOptionsForeign -> Effect UrqlSubClient
instance queryClient :: QueryClient UrqlClient Unit Unit where
clientQuery _ c = queryForeign false c
clientMutation _ c = queryForeign true c
defQueryOpts = const unit
defMutationOpts = const unit
instance queryClientSubscription :: QueryClient UrqlSubClient Unit Unit where
clientQuery _ c = queryForeign false c
clientMutation _ c = queryForeign true c
defQueryOpts = const unit
defMutationOpts = const unit
queryForeign ::
forall client o.
QueryClient client o o =>
Boolean -> client -> String -> String -> Aff Json
queryForeign isMutation client name q_ = fromEffectFnAff $ fn (unsafeToForeign client) q
where
fn = if isMutation then mutationImpl else queryImpl
opStr = if isMutation then "mutation" else "query"
q = opStr <> " " <> name <> " " <> q_
foreign import queryImpl :: Foreign -> String -> EffectFnAff Json
foreign import mutationImpl :: Foreign -> String -> EffectFnAff Json
instance subcriptionClient :: SubscriptionClient UrqlSubClient Unit where
clientSubscription _ = subscriptionImpl
defSubOpts _ = unit
foreign import subscriptionImpl ::
UrqlSubClient ->
String ->
(Json -> Effect Unit) ->
Effect (Effect Unit)