Add initial servant API implementation

This commit is contained in:
Correl Roush 2022-03-22 22:59:25 -04:00
parent 624486cf50
commit 746ca6a507
8 changed files with 351 additions and 0 deletions

2
Setup.hs Normal file
View file

@ -0,0 +1,2 @@
import Distribution.Simple
main = defaultMain

6
app/Main.hs Normal file
View file

@ -0,0 +1,6 @@
module Main where
import Lib
main :: IO ()
main = startApp

57
package.yaml Normal file
View file

@ -0,0 +1,57 @@
name: tutor
version: 0.1.0.0
github: "githubuser/tutor"
license: BSD3
author: "Author name here"
maintainer: "example@example.com"
copyright: "2022 Author name here"
extra-source-files:
- README.org
# Metadata used when publishing your package
# synopsis: Short description of your package
# category: Web
# To avoid duplicated efforts in documentation and dealing with the
# complications of embedding Haddock markup inside cabal files, it is
# common to point users to the README.md file.
description: Please see the README on GitHub at <https://github.com/githubuser/tutor#readme>
dependencies:
- base >= 4.7 && < 5
- aeson
- servant-server
- wai
- warp
library:
source-dirs: src
executables:
tutor-exe:
main: Main.hs
source-dirs: app
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
dependencies:
- base
- tutor
tests:
tutor-test:
main: Spec.hs
source-dirs: test
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
dependencies:
- base
- tutor
- hspec
- hspec-wai
- hspec-wai-json
- aeson

113
src/Lib.hs Normal file
View file

@ -0,0 +1,113 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
module Lib
( startApp,
app,
)
where
import Data.Aeson
import Data.Aeson.TH
import Network.Wai
import Network.Wai.Handler.Warp
import Servant
data Prices = Prices
{ usd :: Maybe String,
usd_foil :: Maybe String,
eur :: Maybe String,
eur_foil :: Maybe String,
tix :: Maybe String
}
deriving (Eq, Show)
$(deriveJSON defaultOptions ''Prices)
data Card = Card
{ scryfall_id :: String,
name :: String,
set_code :: String,
collector_number :: String,
rarity :: String,
color_identity :: String,
oracle_text :: Maybe String,
prices :: Prices
}
deriving (Eq, Show)
$(deriveJSON defaultOptions ''Card)
type API =
"search" :> Get '[JSON] [Card]
:<|> Raw
startApp :: IO ()
startApp = run 8080 app
app :: Application
app = serve api server
api :: Proxy API
api = Proxy
server :: Server API
server =
return cards
:<|> serveDirectoryFileServer "www/public"
cards :: [Card]
cards =
[ Card
{ scryfall_id = "f6cd7465-9dd0-473c-ac5e-dd9e2f22f5f6",
name = "Esika, God of the Tree // The Prismatic Bridge",
set_code = "KHM",
collector_number = "168",
rarity = "mythic",
color_identity = "WUBGR",
oracle_text = Nothing,
prices =
Prices
{ usd = Just "9.07",
usd_foil = Just "10.77",
eur = Just "7.79",
eur_foil = Just "12.27",
tix = Just "1.08"
}
},
Card
{ scryfall_id = "d761ff73-0717-4ee4-996b-f5547bcf9b2f",
name = "Go-Shintai of Life's Origin",
set_code = "NEC",
collector_number = "66",
rarity = "mythic",
color_identity = "WUBGR",
oracle_text = Just "{W}{U}{B}{R}{G}, {T}: Return target enchantment card from your graveyard to the battlefield.\nWhenever Go-Shintai of Life's Origin or another nontoken Shrine enters the battlefield under your control, create a 1/1 colorless Shrine enchantment creature token.",
prices =
Prices
{ usd = Just "23.28",
usd_foil = Nothing,
eur = Just "23.05",
eur_foil = Nothing,
tix = Nothing
}
},
Card
{ scryfall_id = "e2539ff7-2b7d-47e3-bd77-3138a6c42d2b",
name = "Godsire",
set_code = "ALA",
collector_number = "170",
rarity = "mythic",
color_identity = "WGR",
oracle_text = Just "Vigilance\n{T}: Create an 8/8 Beast creature token that's red, green, and white.",
prices =
Prices
{ usd = Just "7.22",
usd_foil = Just "16.56",
eur = Just "4.00",
eur_foil = Just "13.95",
tix = Just "0.02"
}
}
]

67
stack.yaml Normal file
View file

@ -0,0 +1,67 @@
# This file was automatically generated by 'stack init'
#
# Some commonly used options have been documented as comments in this file.
# For advanced use and comprehensive documentation of the format, please see:
# https://docs.haskellstack.org/en/stable/yaml_configuration/
# Resolver to choose a 'specific' stackage snapshot or a compiler version.
# A snapshot resolver dictates the compiler version and the set of packages
# to be used for project dependencies. For example:
#
# resolver: lts-3.5
# resolver: nightly-2015-09-21
# resolver: ghc-7.10.2
#
# The location of a snapshot can be provided as a file or url. Stack assumes
# a snapshot provided as a file might change, whereas a url resource does not.
#
# resolver: ./custom-snapshot.yaml
# resolver: https://example.com/snapshots/2018-01-01.yaml
resolver:
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/28.yaml
# User packages to be built.
# Various formats can be used as shown in the example below.
#
# packages:
# - some-directory
# - https://example.com/foo/bar/baz-0.0.2.tar.gz
# subdirs:
# - auto-update
# - wai
packages:
- .
# Dependency packages to be pulled from upstream that are not in the resolver.
# These entries can reference officially published versions as well as
# forks / in-progress versions pinned to a git hash. For example:
#
# extra-deps:
# - acme-missiles-0.3
# - git: https://github.com/commercialhaskell/stack.git
# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
#
# extra-deps: []
# Override default flag values for local packages and extra-deps
# flags: {}
# Extra package databases containing global packages
# extra-package-dbs: []
# Control whether we use the GHC we find on the path
# system-ghc: true
#
# Require a specific version of stack, using version ranges
# require-stack-version: -any # Default
# require-stack-version: ">=2.7"
#
# Override the architecture used by stack, especially useful on Windows
# arch: i386
# arch: x86_64
#
# Extra directories used by stack for building
# extra-include-dirs: [/path/to/dir]
# extra-lib-dirs: [/path/to/dir]
#
# Allow a newer minor version of GHC than the snapshot specifies
# compiler-check: newer-minor

13
stack.yaml.lock Normal file
View file

@ -0,0 +1,13 @@
# This file was autogenerated by Stack.
# You should not edit this file by hand.
# For more information, please see the documentation at:
# https://docs.haskellstack.org/en/stable/lock_files
packages: []
snapshots:
- completed:
size: 590100
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/28.yaml
sha256: 428ec8d5ce932190d3cbe266b9eb3c175cd81e984babf876b64019e2cbe4ea68
original:
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/28.yaml

20
test/Spec.hs Normal file
View file

@ -0,0 +1,20 @@
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE OverloadedStrings #-}
module Main (main) where
import Lib (app)
import Test.Hspec
import Test.Hspec.Wai
import Test.Hspec.Wai.JSON
main :: IO ()
main = hspec spec
spec :: Spec
spec = with (return app) $ do
describe "GET /search" $ do
it "responds with 200" $ do
get "/search" `shouldRespondWith` 200
it "responds with [Card]" $ do
let cards = "[{\"scryfall_id\":\"f6cd7465-9dd0-473c-ac5e-dd9e2f22f5f6\",\"name\":\"Esika, God of the Tree // The Prismatic Bridge\",\"set_code\":\"KHM\",\"collector_number\":\"168\",\"rarity\":\"mythic\",\"color_identity\":\"WUBGR\",\"oracle_text\":null,\"prices\":{\"usd\":\"9.07\",\"usd_foil\":\"10.77\",\"eur\":\"7.79\",\"eur_foil\":\"12.27\",\"tix\":\"1.08\"}},{\"scryfall_id\":\"d761ff73-0717-4ee4-996b-f5547bcf9b2f\",\"name\":\"Go-Shintai of Life's Origin\",\"set_code\":\"NEC\",\"collector_number\":\"66\",\"rarity\":\"mythic\",\"color_identity\":\"WUBGR\",\"oracle_text\":\"{W}{U}{B}{R}{G}, {T}: Return target enchantment card from your graveyard to the battlefield.\\nWhenever Go-Shintai of Life's Origin or another nontoken Shrine enters the battlefield under your control, create a 1/1 colorless Shrine enchantment creature token.\",\"prices\":{\"usd\":\"23.28\",\"usd_foil\":null,\"eur\":\"23.05\",\"eur_foil\":null,\"tix\":null}},{\"scryfall_id\":\"e2539ff7-2b7d-47e3-bd77-3138a6c42d2b\",\"name\":\"Godsire\",\"set_code\":\"ALA\",\"collector_number\":\"170\",\"rarity\":\"mythic\",\"color_identity\":\"WGR\",\"oracle_text\":\"Vigilance\\n{T}: Create an 8/8 Beast creature token that's red, green, and white.\",\"prices\":{\"usd\":\"7.22\",\"usd_foil\":\"16.56\",\"eur\":\"4.00\",\"eur_foil\":\"13.95\",\"tix\":\"0.02\"}}]"
get "/search" `shouldRespondWith` cards

73
tutor.cabal Normal file
View file

@ -0,0 +1,73 @@
cabal-version: 1.12
-- This file has been generated from package.yaml by hpack version 0.34.4.
--
-- see: https://github.com/sol/hpack
name: tutor
version: 0.1.0.0
description: Please see the README on GitHub at <https://github.com/githubuser/tutor#readme>
homepage: https://github.com/githubuser/tutor#readme
bug-reports: https://github.com/githubuser/tutor/issues
author: Author name here
maintainer: example@example.com
copyright: 2022 Author name here
license: BSD3
build-type: Simple
extra-source-files:
README.org
source-repository head
type: git
location: https://github.com/githubuser/tutor
library
exposed-modules:
Lib
other-modules:
Paths_tutor
hs-source-dirs:
src
build-depends:
aeson
, base >=4.7 && <5
, servant-server
, wai
, warp
default-language: Haskell2010
executable tutor-exe
main-is: Main.hs
other-modules:
Paths_tutor
hs-source-dirs:
app
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends:
aeson
, base
, servant-server
, tutor
, wai
, warp
default-language: Haskell2010
test-suite tutor-test
type: exitcode-stdio-1.0
main-is: Spec.hs
other-modules:
Paths_tutor
hs-source-dirs:
test
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends:
aeson
, base
, hspec
, hspec-wai
, hspec-wai-json
, servant-server
, tutor
, wai
, warp
default-language: Haskell2010