Initial commit

This commit is contained in:
Mike Solomon 2021-05-19 12:34:42 +03:00
commit 92258eb6b2
7 changed files with 1604 additions and 0 deletions

1315
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

18
package.json Normal file
View File

@ -0,0 +1,18 @@
{
"name": "purescript-graphql-fundeps",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"postinstall": "spago install && spago build",
"test": "spago test"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"purescript": "^0.14.1",
"spago": "^0.20.3",
"xhr2": "^0.2.1"
}
}

104
packages.dhall Normal file
View File

@ -0,0 +1,104 @@
{-
Welcome to your new Dhall package-set!
Below are instructions for how to edit this file for most use
cases, so that you don't need to know Dhall to use it.
## Use Cases
Most will want to do one or both of these options:
1. Override/Patch a package's dependency
2. Add a package not already in the default package set
This file will continue to work whether you use one or both options.
Instructions for each option are explained below.
### Overriding/Patching a package
Purpose:
- Change a package's dependency to a newer/older release than the
default package set's release
- Use your own modified version of some dependency that may
include new API, changed API, removed API by
using your custom git repo of the library rather than
the package set's repo
Syntax:
where `entityName` is one of the following:
- dependencies
- repo
- version
-------------------------------
let upstream = --
in upstream
with packageName.entityName = "new value"
-------------------------------
Example:
-------------------------------
let upstream = --
in upstream
with halogen.version = "master"
with halogen.repo = "https://example.com/path/to/git/repo.git"
with halogen-vdom.version = "v4.0.0"
with halogen-vdom.dependencies = [ "extra-dependency" ] # halogen-vdom.dependencies
-------------------------------
### Additions
Purpose:
- Add packages that aren't already included in the default package set
Syntax:
where `<version>` is:
- a tag (i.e. "v4.0.0")
- a branch (i.e. "master")
- commit hash (i.e. "701f3e44aafb1a6459281714858fadf2c4c2a977")
-------------------------------
let upstream = --
in upstream
with new-package-name =
{ dependencies =
[ "dependency1"
, "dependency2"
]
, repo =
"https://example.com/path/to/git/repo.git"
, version =
"<version>"
}
-------------------------------
Example:
-------------------------------
let upstream = --
in upstream
with benchotron =
{ dependencies =
[ "arrays"
, "exists"
, "profunctor"
, "strings"
, "quickcheck"
, "lcg"
, "transformers"
, "foldable-traversable"
, "exceptions"
, "node-fs"
, "node-buffer"
, "node-readline"
, "datetime"
, "now"
]
, repo =
"https://github.com/hdgarrood/purescript-benchotron.git"
, version =
"v7.0.0"
}
-------------------------------
-}
let upstream =
https://github.com/purescript/package-sets/releases/download/psc-0.14.1-20210516/packages.dhall sha256:f5e978371d4cdc4b916add9011021509c8d869f4c3f6d0d2694c0e03a85046c8
in upstream

30
spago.dhall Normal file
View File

@ -0,0 +1,30 @@
{-
Welcome to a Spago project!
You can edit this file as you like.
Need help? See the following resources:
- Spago documentation: https://github.com/purescript/spago
- Dhall language tour: https://docs.dhall-lang.org/tutorials/Language-Tour.html
When creating a new Spago project, you can use
`spago init --no-comments` or `spago init -C`
to generate this file without the comments in this block.
-}
{ name = "my-project"
, dependencies =
[ "aff"
, "affjax"
, "console"
, "effect"
, "either"
, "http-methods"
, "maybe"
, "media-types"
, "prelude"
, "psci-support"
, "simple-json"
, "strings"
]
, packages = ./packages.dhall
, sources = [ "src/**/*.purs" ]
}

62
src/GraphQL.purs Normal file
View File

@ -0,0 +1,62 @@
module GraphQL.FunDeps where
import Prelude
import Affjax as AX
import Affjax.RequestBody as RequestBody
import Affjax.RequestHeader (RequestHeader(..))
import Affjax.ResponseFormat as ResponseFormat
import Data.Either (Either(..))
import Data.HTTP.Method (Method(..))
import Data.Maybe (Maybe(..))
import Data.MediaType (MediaType(..))
import Data.String as String
import Data.Symbol (class IsSymbol, reflectSymbol)
import Effect.Aff (Aff, error, throwError)
import Effect.Class (liftEffect)
import Effect.Class.Console as Log
import Simple.JSON as JSON
import Type.Proxy (Proxy(..))
data GraphQL
data Gql (operation :: GraphQL)
= Gql
class GraphQLReqRes (operation :: GraphQL) (gql :: Symbol) (i :: Row Type) (o :: Row Type) | operation -> gql i o
type Endpoint = String
type GraphQLClient' (operation :: GraphQL) (gql :: Symbol) (i :: Row Type) (o :: Row Type) = GraphQLReqRes operation gql i o => IsSymbol gql => JSON.WriteForeign { | i } => JSON.ReadForeign { | o } => Gql operation -> Record i -> Aff { | o }
type GraphQLClient = forall (operation :: GraphQL) (gql :: Symbol) (i :: Row Type) (o :: Row Type). GraphQLClient' operation gql i o
graphQL :: Endpoint -> Array RequestHeader -> (forall (operation :: GraphQL) (gql :: Symbol) (i :: Row Type) (o :: Row Type). GraphQLReqRes operation gql i o => IsSymbol gql => JSON.WriteForeign { | i } => JSON.ReadForeign { | o } => Gql operation -> Record i -> Aff { | o })
graphQL endpoint headers = go
where
go :: forall (operation :: GraphQL) (gql :: Symbol) (i :: Row Type) (o :: Row Type). GraphQLReqRes operation gql i o => IsSymbol gql => JSON.WriteForeign { | i } => JSON.ReadForeign { | o } => Gql operation -> Record i -> Aff { | o }
go _ variables = do
let
input =
{ variables
, query: String.replaceAll (String.Pattern "\n") (String.Replacement " ") (String.replaceAll (String.Pattern "\r\n") (String.Replacement " ") (reflectSymbol (Proxy :: Proxy gql)))
}
res <-
AX.request
( AX.defaultRequest
{ url = endpoint
, method = Left POST
, responseFormat = ResponseFormat.string
, content =
Just
(RequestBody.string (JSON.writeJSON input))
, headers = headers <> [ContentType $ MediaType "application/json"]
}
)
case res of
Left err -> do
liftEffect $ Log.info "Request did not go through"
throwError (error $ AX.printError err)
Right response -> case (JSON.readJSON response.body) of
Left err1 -> throwError (error $ ("Got an error " <> show response.body <> " err " <> show err1 <> " using input " <> (JSON.writeJSON input)))
Right ({ data: d } :: { data :: { | o } }) -> pure d

6
test.dhall Normal file
View File

@ -0,0 +1,6 @@
let conf = ./spago.dhall
in conf // {
sources = conf.sources # [ "test/**/*.purs" ],
dependencies = conf.dependencies # [ "spec", "foldable-traversable" ]
}

69
test/Main.purs Normal file
View File

@ -0,0 +1,69 @@
module Test.Main where
import Prelude
import Data.Foldable (for_)
import Data.Maybe (Maybe(..))
import Effect (Effect)
import Effect.Aff (Milliseconds(..), launchAff_)
import Effect.Class.Console as Log
import GraphQL.FunDeps (class GraphQLReqRes, Gql(..), GraphQL, GraphQLClient, graphQL)
import Test.Spec (describe, it)
import Test.Spec.Reporter.Console (consoleReporter)
import Test.Spec.Runner (defaultConfig, runSpec')
endpoint = "https://api.react-finland.fi/graphql" :: String
foreign import data ReactFinlandConferences :: GraphQL
instance graphqlReactFinlandConferences ::
GraphQLReqRes ReactFinlandConferences """query {
conferences {
name
id
}
}
""" () ( conferences :: Array { name :: String, id :: String } )
foreign import data ReactFinlandConference :: GraphQL
instance graphqlReactFinlandConference ::
GraphQLReqRes ReactFinlandConference """query($id:ID!) {
conference(id:$id) {
year
websiteUrl
speakers {
firstName
lastName
}
}
}
""" ( id :: String ) ( conference ::
{ year :: String
, websiteUrl :: String
, speakers ::
Array
{ firstName :: String
, lastName :: String
}
}
)
client :: GraphQLClient
client = graphQL "https://api.react-finland.fi/graphql" []
main ∷ Effect Unit
main =
launchAff_
$ runSpec'
( defaultConfig
{ timeout = Just (Milliseconds 10000.0)
}
)
[ consoleReporter ] do
describe "GraphQL Fundeps" do
it "Works" do
{ conferences } <- client (Gql :: Gql ReactFinlandConferences) {}
for_ conferences \{ id } -> do
{ conference: { websiteUrl, speakers } } <- client (Gql :: Gql ReactFinlandConference) { id }
Log.info websiteUrl
Log.info $ show speakers