{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
import Language.JsonGrammar
import Types
import Prelude hiding (id, (.))
import Control.Category (Category(..))
import Data.Aeson.Types (Value, parseMaybe)
import Data.Char (toLower)
import Data.Monoid ((<>))
import Data.StackPrism (StackPrism)
import Data.StackPrism.TH (deriveStackPrismsWith)
import Language.TypeScript (renderDeclarationSourceFile)
import Test.Framework (Test, defaultMain)
import Test.Framework.Providers.HUnit (testCase)
import Test.HUnit (assertBool)
-- Create stack prisms for our three datatypes (defined in module Types)
deriveStackPrismsWith (map toLower) ''Person
deriveStackPrismsWith (map toLower) ''Coords
deriveStackPrismsWith (map toLower) ''Gender
-- Write Json instances for the datatypes
instance Json Gender where
grammar = fromPrism male . literal "male"
<> fromPrism female . literal "female"
instance Json Person where
grammar = label "Person" $
fromPrism person . object
( prop "name"
. prop "gender"
. (prop "age" <> defaultValue 42)
. fromPrism coords
. property "coords" (array (el . el))
)
-- Create two example values
alice :: Person
alice = Person "Alice" Female 21 (Coords 52 5)
bob :: Person
bob = Person "Bob" Male 22 (Coords 53 6)
-- Two tests: one for lists, the other for tuples
test1, test2 :: Test
test1 = testCase "PersonList" $ assertBool "" (checkInverse [alice, bob])
test2 = testCase "PersonTuple" $ assertBool "" (checkInverse (alice, bob))
checkInverse :: (Json a, Eq a) => a -> Bool
checkInverse value = value == value'
where
Just json = serialize grammar value
Just value' = parseMaybe (parse grammar) json
-- Write the TypeScript definition to stdout and run the tests
main :: IO ()
main = do
printInterfaces [SomeGrammar personGrammar]
defaultMain [test1, test2]
personGrammar :: Grammar Val (Value :- t) (Person :- t)
personGrammar = grammar
printInterfaces :: [SomeGrammar Val] -> IO ()
printInterfaces gs = putStrLn (renderDeclarationSourceFile (interfaces gs))