Skip to content

Commit

Permalink
Merge pull request #135 from OxfordAbstracts/fix-gql-vars-edge-cases
Browse files Browse the repository at this point in the history
Fix gql vars edge cases
  • Loading branch information
roryc89 authored Dec 11, 2023
2 parents 8b450ea + 105be21 commit bbc6928
Show file tree
Hide file tree
Showing 25 changed files with 224 additions and 166 deletions.
3 changes: 1 addition & 2 deletions src/GraphQL/Client/Alias.purs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
module GraphQL.Client.Alias where

data Alias al t
= Alias al t
data Alias al t = Alias al t

infixr 6 Alias as :
6 changes: 2 additions & 4 deletions src/GraphQL/Client/Alias/Dynamic.purs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,11 @@ import GraphQL.Hasura.Encode (class EncodeHasura, encodeHasura)
-- | _3: update_users(where: {id : 3}, _set: { value: 20 }) { affected_rows }
-- | }
-- | ```
data Spread alias args fields
= Spread alias (Array args) fields
data Spread alias args fields = Spread alias (Array args) fields

-- | The return type of a query made with a dynamic alias spread
-- | This type has encodes/decodes as an object with "_n" as a key
newtype SpreadRes a
= SpreadRes (Array a)
newtype SpreadRes a = SpreadRes (Array a)

derive instance genericSpreadRes :: Generic (SpreadRes a) _

Expand Down
2 changes: 1 addition & 1 deletion src/GraphQL/Client/Args.purs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ else instance argToGqlArray :: ArgGqlAt at param arg => ArgGqlAt at (Array param
else instance argToGqlArrayOne :: ArgGqlAt at param arg => ArgGqlAt at (Array param) arg
else instance argToGqlRecord :: RecordArg p a u => ArgGqlAt at { | p } { | a }
else instance allowedArgMismatchSame :: ArgGqlAt at p (AllowedMismatch p a)
else instance allowedArgMismatchNested :: ArgGqlAt at p a => ArgGqlAt at p (AllowedMismatch schema a)
else instance allowedArgMismatchNested :: ArgGqlAt at p a => ArgGqlAt at p (AllowedMismatch schema a)
else instance argGqlIdentity :: ArgGqlAt at a a
else instance argToGqlNewtypeRecord :: (Newtype n { | p }, RecordArg p a u) => ArgGqlAt at n { | a }
else instance argMismatch ::
Expand Down
3 changes: 0 additions & 3 deletions src/GraphQL/Client/Args/AllowedMismatch.purs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,10 @@ import Data.Newtype (class Newtype)
import GraphQL.Hasura.Decode (class DecodeHasura)
import GraphQL.Hasura.Encode (class EncodeHasura)


-- | Allow a type does not match the schema to be used in a query as an argument.
newtype AllowedMismatch :: forall k. k -> Type -> Type
newtype AllowedMismatch schemaType arg = AllowedMismatch arg


derive instance Newtype (AllowedMismatch schemaType arg) _

derive newtype instance DecodeJson arg => DecodeJson (AllowedMismatch schemaType arg)
Expand All @@ -22,4 +20,3 @@ derive newtype instance DecodeHasura arg => DecodeHasura (AllowedMismatch schema
derive newtype instance EncodeHasura arg => EncodeHasura (AllowedMismatch schemaType arg)
derive newtype instance Eq arg => Eq (AllowedMismatch schemaType arg)


21 changes: 10 additions & 11 deletions src/GraphQL/Client/BaseClients/Affjax/Internal.purs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ module GraphQL.Client.BaseClients.Affjax.Internal where

import Prelude


import Affjax (Error, Request, URL, defaultRequest, printError)
import Affjax.RequestBody as RequestBody
import Affjax.RequestHeader (RequestHeader(..))
Expand All @@ -20,21 +19,21 @@ throwLeft = case _ of
Left err -> throwError $ error $ printError err
Right { body } -> pure body

makeAffjaxGqlRequest ::
String -> URL -> Array RequestHeader -> String -> String -> Json -> Request Json
makeAffjaxGqlRequest
:: String -> URL -> Array RequestHeader -> String -> String -> Json -> Request Json
makeAffjaxGqlRequest opStr url headers queryName q vars =
defaultRequest
{ withCredentials = true
, url = url
, method = Left Method.POST
, responseFormat = ResponseFormat.json
, content =
defaultRequest
{ withCredentials = true
, url = url
, method = Left Method.POST
, responseFormat = ResponseFormat.json
, content =
Just
$ RequestBody.Json
$ encodeJson
{ query: opStr <> " " <> queryName <> " " <> q
, variables: vars
, operationName: queryName
}
, headers = headers <> [ ContentType applicationJSON ]
}
, headers = headers <> [ ContentType applicationJSON ]
}
7 changes: 3 additions & 4 deletions src/GraphQL/Client/BaseClients/Affjax/Node.purs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@ import Effect.Aff (Aff)
import GraphQL.Client.BaseClients.Affjax.Internal (makeAffjaxGqlRequest, throwLeft)
import GraphQL.Client.Types (class QueryClient)

data AffjaxNodeClient
= AffjaxNodeClient URL (Array RequestHeader)
data AffjaxNodeClient = AffjaxNodeClient URL (Array RequestHeader)

instance queryClient :: QueryClient AffjaxNodeClient Unit Unit where
clientQuery _ (AffjaxNodeClient url headers) name q vars = throwLeft =<< queryPostForeign "query" url headers name q vars
clientMutation _ (AffjaxNodeClient url headers) name q vars = throwLeft =<< queryPostForeign "mutation" url headers name q vars
defQueryOpts = const unit
defMutationOpts = const unit

queryPostForeign ::
String -> URL -> Array RequestHeader -> String -> String -> Json -> Aff (Either Error (Response Json))
queryPostForeign
:: String -> URL -> Array RequestHeader -> String -> String -> Json -> Aff (Either Error (Response Json))
queryPostForeign opStr url headers queryName q vars =
request (makeAffjaxGqlRequest opStr url headers queryName q vars)
7 changes: 3 additions & 4 deletions src/GraphQL/Client/BaseClients/Affjax/Web.purs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@ import Effect.Aff (Aff)
import GraphQL.Client.BaseClients.Affjax.Internal (makeAffjaxGqlRequest, throwLeft)
import GraphQL.Client.Types (class QueryClient)

data AffjaxWebClient
= AffjaxWebClient URL (Array RequestHeader)
data AffjaxWebClient = AffjaxWebClient URL (Array RequestHeader)

instance queryClient :: QueryClient AffjaxWebClient Unit Unit where
clientQuery _ (AffjaxWebClient url headers) name q vars = throwLeft =<< queryPostForeign "query" url headers name q vars
clientMutation _ (AffjaxWebClient url headers) name q vars = throwLeft =<< queryPostForeign "mutation" url headers name q vars
defQueryOpts = const unit
defMutationOpts = const unit

queryPostForeign ::
String -> URL -> Array RequestHeader -> String -> String -> Json -> Aff (Either Error (Response Json))
queryPostForeign
:: String -> URL -> Array RequestHeader -> String -> String -> Json -> Aff (Either Error (Response Json))
queryPostForeign opStr url headers queryName q vars =
request (makeAffjaxGqlRequest opStr url headers queryName q vars)
2 changes: 1 addition & 1 deletion src/GraphQL/Client/BaseClients/Apollo/ErrorPolicy.purs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ data ErrorPolicy

derive instance eqErrorPolicy :: Eq ErrorPolicy

instance encodeJsonErrorPolicy :: EncodeJson ErrorPolicy where
instance encodeJsonErrorPolicy :: EncodeJson ErrorPolicy where
encodeJson = errorPolicyToForeign >>> encodeJson

errorPolicyToForeign :: ErrorPolicy -> String
Expand Down
3 changes: 1 addition & 2 deletions src/GraphQL/Client/BaseClients/Apollo/FetchPolicy.purs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import Prelude

import Data.Argonaut.Encode (class EncodeJson, encodeJson)


data FetchPolicy
= CacheFirst
| CacheOnly
Expand All @@ -15,7 +14,7 @@ data FetchPolicy

derive instance eqFetchPolicy :: Eq FetchPolicy

instance encodeJsonFetchPolicy :: EncodeJson FetchPolicy where
instance encodeJsonFetchPolicy :: EncodeJson FetchPolicy where
encodeJson = fetchPolicyToForeign >>> encodeJson

fetchPolicyToForeign :: FetchPolicy -> String
Expand Down
100 changes: 54 additions & 46 deletions src/GraphQL/Client/BaseClients/Urql.purs
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ 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 UrqlClientOptions =
{ url :: URL
, headers :: Array RequestHeader
}

type UrqlSubClientOptions
= { url :: URL
, websocketUrl :: 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
Expand All @@ -45,47 +45,49 @@ foreign import data UrqlClient :: Type
-- | See https://github.com/enisdenjo/graphql-ws details
foreign import data UrqlSubClient :: Type

createClient ::
forall schema.
UrqlClientOptions -> Effect (Client UrqlClient schema)
createClient
:: forall schema
. UrqlClientOptions
-> Effect (Client UrqlClient schema)
createClient = clientOptsToForeign >>> createClientImpl >>> map Client

createGlobalClientUnsafe ::
forall schema.
UrqlClientOptions -> Effect (Client UrqlClient schema)
createGlobalClientUnsafe
:: forall schema
. UrqlClientOptions
-> Effect (Client UrqlClient schema)
createGlobalClientUnsafe = clientOptsToForeign >>> createGlobalClientUnsafeImpl >>> map Client

createSubscriptionClient ::
forall schema.
UrqlSubClientOptions ->
Effect (Client UrqlSubClient schema)
createSubscriptionClient
:: forall schema
. UrqlSubClientOptions
-> Effect (Client UrqlSubClient schema)
createSubscriptionClient = clientOptsToForeign >>> createSubscriptionClientImpl >>> map Client

clientOptsToForeign ::
forall r.
{ headers :: Array RequestHeader
| r
} ->
{ headers :: Object String
| r
}
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 UrqlClientOptionsForeign =
{ url :: URL
, headers :: Object String
}

type UrqlSubUrqlClientOptionsForeign
= { url :: URL
, websocketUrl :: URL
, headers :: Object String
}
type UrqlSubUrqlClientOptionsForeign =
{ url :: URL
, websocketUrl :: URL
, headers :: Object String
}

foreign import createClientImpl :: UrqlClientOptionsForeign -> Effect UrqlClient

Expand All @@ -105,10 +107,15 @@ instance queryClientSubscription :: QueryClient UrqlSubClient Unit Unit where
defQueryOpts = const unit
defMutationOpts = const unit

queryForeign ::
forall client o.
QueryClient client o o =>
Boolean -> client -> String -> String -> Json -> Aff Json
queryForeign
:: forall client o
. QueryClient client o o
=> Boolean
-> client
-> String
-> String
-> Json
-> Aff Json
queryForeign isMutation client name q_ vars = fromEffectFnAff $ fn (unsafeToForeign client) q vars
where
fn = if isMutation then mutationImpl else queryImpl
Expand All @@ -124,9 +131,10 @@ foreign import mutationImpl :: Foreign -> String -> Json -> EffectFnAff Json
instance subcriptionClient :: SubscriptionClient UrqlSubClient Unit where
clientSubscription _ = subscriptionImpl
defSubOpts _ = unit
foreign import subscriptionImpl ::
UrqlSubClient ->
String ->
Json ->
(Json -> Effect Unit) ->
Effect (Effect Unit)

foreign import subscriptionImpl
:: UrqlSubClient
-> String
-> Json
-> (Json -> Effect Unit)
-> Effect (Effect Unit)
13 changes: 6 additions & 7 deletions src/GraphQL/Client/Directive/Definition.purs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ import Data.Symbol (class IsSymbol)

-- | A directive definition
data Directive :: forall k1 k2 k3 k4. k1 -> k2 -> k3 -> k4 -> Type
data Directive name description arguments locations
= Directive
data Directive name description arguments locations = Directive

directive ::
forall name description arguments location.
IsSymbol name =>
Directive name description { | arguments } location
directive
:: forall name description arguments location
. IsSymbol name
=> Directive name description { | arguments } location
directive =
Directive
Directive
10 changes: 3 additions & 7 deletions src/GraphQL/Client/Directive/Location.purs
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
module GraphQL.Client.Directive.Location where


class ExecutableDirectiveLocation :: forall k. k -> Constraint
class ExecutableDirectiveLocation a

data QUERY
= QUERY
data QUERY = QUERY

instance executableDirectiveLocationQUERY :: ExecutableDirectiveLocation QUERY

data MUTATION
= MUTATION
data MUTATION = MUTATION

instance executableDirectiveLocationMUTATION :: ExecutableDirectiveLocation MUTATION

data SUBSCRIPTION
= SUBSCRIPTION
data SUBSCRIPTION = SUBSCRIPTION

instance executableDirectiveLocationSUBSCRIPTION :: ExecutableDirectiveLocation SUBSCRIPTION
3 changes: 1 addition & 2 deletions src/GraphQL/Client/ErrorBoundary.purs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ module GraphQL.Client.ErrorBoundary
, putErrorsInPaths
, putErrorsInPathsImpl
, toEither
)
where
) where

import Prelude

Expand Down
1 change: 0 additions & 1 deletion src/GraphQL/Client/GqlError.purs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import Data.Either (Either)
import Data.Maybe (Maybe)
import Foreign.Object (Object)


type GqlError =
{ message :: String
, locations :: ErrorLocations
Expand Down
4 changes: 2 additions & 2 deletions src/GraphQL/Client/ID.purs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import GraphQL.Hasura.Encode (class EncodeHasura)
newtype ID = ID String

derive instance eqID :: Eq ID
derive instance ordID :: Ord ID
derive instance ordID :: Ord ID
derive instance newtypeID :: Newtype ID _
derive instance genericID :: Generic ID _
derive newtype instance showID :: Show ID
derive newtype instance showID :: Show ID
derive newtype instance gqlArgStringID :: GqlArgString ID
derive newtype instance decodeHasuraID :: DecodeHasura ID
derive newtype instance encodeHasuraID :: EncodeHasura ID
Expand Down
1 change: 0 additions & 1 deletion src/GraphQL/Client/NullArray.purs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
module GraphQL.Client.NullArray where


-- | An empty array that can be used as an argument in a GraphQL query. Useful when you dont want to add type annotations
data NullArray = NullArray
Loading

0 comments on commit bbc6928

Please sign in to comment.