packages feed

aeson-typescript 0.4.2.0 → 0.5.0.0

raw patch · 36 files changed

+462/−439 lines, 36 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Data.Aeson.TypeScript.Internal: [fieldDoc] :: TSField -> Maybe String
+ Data.Aeson.TypeScript.Internal: [interfaceDoc] :: TSDeclaration -> Maybe String
+ Data.Aeson.TypeScript.Internal: [typeDoc] :: TSDeclaration -> Maybe String
+ Data.Aeson.TypeScript.LegalName: checkIllegalNameChars :: NonEmpty Char -> Maybe (NonEmpty Char)
+ Data.Aeson.TypeScript.TH: defaultNameFormatter :: String -> String
- Data.Aeson.TypeScript.Internal: TSField :: Bool -> String -> String -> TSField
+ Data.Aeson.TypeScript.Internal: TSField :: Bool -> String -> String -> Maybe String -> TSField
- Data.Aeson.TypeScript.Internal: TSInterfaceDeclaration :: String -> [String] -> [TSField] -> TSDeclaration
+ Data.Aeson.TypeScript.Internal: TSInterfaceDeclaration :: String -> [String] -> [TSField] -> Maybe String -> TSDeclaration
- Data.Aeson.TypeScript.Internal: TSTypeAlternatives :: String -> [String] -> [String] -> TSDeclaration
+ Data.Aeson.TypeScript.Internal: TSTypeAlternatives :: String -> [String] -> [String] -> Maybe String -> TSDeclaration

Files

CHANGELOG.md view
@@ -1,5 +1,17 @@ # Change log ++## (unreleased)++## 0.5.0.0++* [#35](https://github.com/codedownio/aeson-typescript/pull/35)+    * Add `Data.Aeson.TypeScript.LegalName` module for checking whether a name is a legal JavaScript name or not.+    * The `defaultFormatter` will `error` if the name contains illegal characters.+* Be able to transfer Haddock comments to emitted TypeScript (requires GHC >= 9.2 and `-haddock` flag)+* Add support for @no-emit-typescript in Haddocks for constructors and record fields (requires GHC >= 9.2 and `-haddock` flag)+* Support GHC 9.6.1+ ## 0.4.2.0  * Fix TypeScript (A.KeyMap a) instance
README.md view
@@ -16,6 +16,7 @@          | Product String Char a          | Record { testOne   :: Double                   , testTwo   :: Bool+                  -- | This docstring will go into the generated TypeScript!                   , testThree :: D a                   } deriving Eq ```@@ -41,6 +42,7 @@   tag: "record";   One: number;   Two: boolean;+  // This docstring will go into the generated TypeScript!   Three: D<T>; } ```
aeson-typescript.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.35.0.+-- This file has been generated from package.yaml by hpack version 0.35.1. -- -- see: https://github.com/sol/hpack  name:           aeson-typescript-version:        0.4.2.0+version:        0.5.0.0 synopsis:       Generate TypeScript definition files from your ADTs description:    Please see the README on Github at <https://github.com/codedownio/aeson-typescript#readme> category:       Text, Web, JSON@@ -36,6 +36,7 @@       Data.Aeson.TypeScript.TH       Data.Aeson.TypeScript.Internal       Data.Aeson.TypeScript.Recursive+      Data.Aeson.TypeScript.LegalName   other-modules:       Data.Aeson.TypeScript.Formatting       Data.Aeson.TypeScript.Instances@@ -47,6 +48,16 @@       Paths_aeson_typescript   hs-source-dirs:       src+  default-extensions:+      LambdaCase+      MultiWayIf+      NamedFieldPuns+      OverloadedStrings+      QuasiQuotes+      RecordWildCards+      ScopedTypeVariables+      TupleSections+      ViewPatterns   build-depends:       aeson     , base >=4.7 && <5@@ -68,7 +79,9 @@       ClosedTypeFamilies       Formatting       Generic+      GetDoc       HigherKind+      LegalNameSpec       NoOmitNothingFields       ObjectWithSingleFieldNoTagSingleConstructors       ObjectWithSingleFieldTagSingleConstructors@@ -87,6 +100,7 @@       Data.Aeson.TypeScript.Formatting       Data.Aeson.TypeScript.Instances       Data.Aeson.TypeScript.Internal+      Data.Aeson.TypeScript.LegalName       Data.Aeson.TypeScript.Lookup       Data.Aeson.TypeScript.Recursive       Data.Aeson.TypeScript.TH@@ -98,7 +112,21 @@   hs-source-dirs:       test       src-  ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N+  default-extensions:+      LambdaCase+      MultiWayIf+      NamedFieldPuns+      OverloadedStrings+      QuasiQuotes+      RecordWildCards+      ScopedTypeVariables+      TupleSections+      ViewPatterns+      FlexibleContexts+      KindSignatures+      TemplateHaskell+      TypeFamilies+  ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N -haddock -fno-warn-unused-top-binds -fno-warn-orphans   build-depends:       aeson     , aeson-typescript
src/Data/Aeson/TypeScript/Formatting.hs view
@@ -1,8 +1,11 @@-{-# LANGUAGE QuasiQuotes, OverloadedStrings, TemplateHaskell, RecordWildCards, ScopedTypeVariables, NamedFieldPuns, CPP #-}+{-# LANGUAGE CPP #-}  module Data.Aeson.TypeScript.Formatting where  import Data.Aeson.TypeScript.Types+import Data.Function ((&))+import qualified Data.List as L+import Data.Maybe import Data.String.Interpolate import qualified Data.Text as T @@ -17,34 +20,61 @@  -- | Format a single TypeScript declaration. This version accepts a FormattingOptions object in case you want more control over the output. formatTSDeclaration :: FormattingOptions -> TSDeclaration -> String-formatTSDeclaration (FormattingOptions {..}) (TSTypeAlternatives name genericVariables names) =-  case typeAlternativesFormat of-    Enum -> [i|#{exportPrefix exportMode}enum #{typeNameModifier name} { #{alternativesEnum} }|]-    EnumWithType -> [i|#{exportPrefix exportMode}enum #{typeNameModifier name} { #{alternativesEnumWithType} }#{enumType}|]-    TypeAlias -> [i|#{exportPrefix exportMode}type #{typeNameModifier name}#{getGenericBrackets genericVariables} = #{alternatives};|]+formatTSDeclaration (FormattingOptions {..}) (TSTypeAlternatives name genericVariables names maybeDoc) =+  makeDocPrefix maybeDoc <> mainDeclaration   where+    mainDeclaration = case typeAlternativesFormat of+      Enum -> [i|#{exportPrefix exportMode}enum #{typeNameModifier name} { #{alternativesEnum} }|]+      EnumWithType -> [i|#{exportPrefix exportMode}enum #{typeNameModifier name} { #{alternativesEnumWithType} }#{enumType}|]+      TypeAlias -> [i|#{exportPrefix exportMode}type #{typeNameModifier name}#{getGenericBrackets genericVariables} = #{alternatives};|]+     alternatives = T.intercalate " | " (fmap T.pack names)     alternativesEnum = T.intercalate ", " $ [toEnumName entry | entry <- T.pack <$> names]     alternativesEnumWithType = T.intercalate ", " $ [toEnumName entry <> "=" <> entry | entry <- T.pack <$> names]     enumType = [i|\n\ntype #{name} = keyof typeof #{typeNameModifier name};|] :: T.Text     toEnumName = T.replace "\"" "" -formatTSDeclaration (FormattingOptions {..}) (TSInterfaceDeclaration interfaceName genericVariables members) =-  [i|#{exportPrefix exportMode}interface #{modifiedInterfaceName}#{getGenericBrackets genericVariables} {+formatTSDeclaration (FormattingOptions {..}) (TSInterfaceDeclaration interfaceName genericVariables (filter (not . isNoEmitTypeScriptField) -> members) maybeDoc) =+  makeDocPrefix maybeDoc <> [i|#{exportPrefix exportMode}interface #{modifiedInterfaceName}#{getGenericBrackets genericVariables} { #{ls}-}|] where ls = T.intercalate "\n" $ fmap T.pack [(replicate numIndentSpaces ' ') <> formatTSField member <> ";"| member <- members]-          modifiedInterfaceName = (\(li, name) -> li <> interfaceNameModifier name) . splitAt 1 $ interfaceName+}|] where+      ls = T.intercalate "\n" $ [indentTo numIndentSpaces (T.pack (formatTSField member <> ";")) | member <- members]+      modifiedInterfaceName = (\(li, name) -> li <> interfaceNameModifier name) . splitAt 1 $ interfaceName  formatTSDeclaration _ (TSRawDeclaration text) = text +indentTo :: Int -> T.Text -> T.Text+indentTo numIndentSpaces input = T.intercalate "\n" [padding <> line | line <- T.splitOn "\n" input]+  where padding = T.replicate numIndentSpaces " "+ exportPrefix :: ExportMode -> String exportPrefix ExportEach = "export " exportPrefix ExportNone = ""  -- | Format a list of TypeScript declarations into a string, suitable for putting directly into a @.d.ts@ file. formatTSDeclarations' :: FormattingOptions -> [TSDeclaration] -> String-formatTSDeclarations' options declarations = T.unpack $ T.intercalate "\n\n" (fmap (T.pack . formatTSDeclaration (validateFormattingOptions options declarations)) declarations)+formatTSDeclarations' options allDeclarations =+  declarations & fmap (T.pack . formatTSDeclaration (validateFormattingOptions options declarations))+               & T.intercalate "\n\n"+               & T.unpack+  where+    removedDeclarations = filter isNoEmitTypeScriptDeclaration allDeclarations +    getDeclarationName :: TSDeclaration -> Maybe String+    getDeclarationName (TSInterfaceDeclaration {..}) = Just interfaceName+    getDeclarationName (TSTypeAlternatives {..}) = Just typeName+    _ = Nothing++    removedDeclarationNames = mapMaybe getDeclarationName removedDeclarations++    removeReferencesToRemovedNames :: [String] -> TSDeclaration -> TSDeclaration+    removeReferencesToRemovedNames removedNames decl@(TSTypeAlternatives {..}) = decl { alternativeTypes = [x | x <- alternativeTypes, not (x `L.elem` removedNames)] }+    removeReferencesToRemovedNames _ x = x++    declarations = allDeclarations+                 & filter (not . isNoEmitTypeScriptDeclaration)+                 & fmap (removeReferencesToRemovedNames removedDeclarationNames)+ validateFormattingOptions :: FormattingOptions -> [TSDeclaration] -> FormattingOptions validateFormattingOptions options@FormattingOptions{..} decls   | typeAlternativesFormat == Enum && isPlainSumType decls = options@@ -60,8 +90,28 @@     isPlainSumType ds = (not . any isInterface $ ds) && length ds == 1  formatTSField :: TSField -> String-formatTSField (TSField optional name typ) = [i|#{name}#{if optional then ("?" :: String) else ""}: #{typ}|]+formatTSField (TSField optional name typ maybeDoc) = makeDocPrefix maybeDoc <> [i|#{name}#{if optional then ("?" :: String) else ""}: #{typ}|] +makeDocPrefix :: Maybe String -> String+makeDocPrefix maybeDoc = case maybeDoc of+  Nothing -> ""+  Just (T.pack -> text) -> ["// " <> line | line <- T.splitOn "\n" text]+                        & T.intercalate "\n"+                        & (<> "\n")+                        & T.unpack+ getGenericBrackets :: [String] -> String getGenericBrackets [] = "" getGenericBrackets xs = [i|<#{T.intercalate ", " (fmap T.pack xs)}>|]++-- * Support for @no-emit-typescript++noEmitTypeScriptAnnotation :: String+noEmitTypeScriptAnnotation = "@no-emit-typescript"++isNoEmitTypeScriptField (TSField {fieldDoc=(Just doc)}) = noEmitTypeScriptAnnotation `L.isInfixOf` doc+isNoEmitTypeScriptField _ = False++isNoEmitTypeScriptDeclaration (TSInterfaceDeclaration {interfaceDoc=(Just doc)}) = noEmitTypeScriptAnnotation `L.isInfixOf` doc+isNoEmitTypeScriptDeclaration (TSTypeAlternatives {typeDoc=(Just doc)}) = noEmitTypeScriptAnnotation `L.isInfixOf` doc+isNoEmitTypeScriptDeclaration _ = False
src/Data/Aeson/TypeScript/Instances.hs view
@@ -1,8 +1,4 @@-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverlappingInstances #-}@@ -89,9 +85,9 @@  instance (TypeScript a, TypeScript b) => TypeScript (Either a b) where   getTypeScriptType _ = [i|Either<#{getTypeScriptType (Proxy :: Proxy a)}, #{getTypeScriptType (Proxy :: Proxy b)}>|]-  getTypeScriptDeclarations _ = [TSTypeAlternatives "Either" ["T1", "T2"] ["Left<T1>", "Right<T2>"]-                               , TSInterfaceDeclaration "Left" ["T"] [TSField False "Left" "T"]-                               , TSInterfaceDeclaration "Right" ["T"] [TSField False "Right" "T"]+  getTypeScriptDeclarations _ = [TSTypeAlternatives "Either" ["T1", "T2"] ["Left<T1>", "Right<T2>"] Nothing+                               , TSInterfaceDeclaration "Left" ["T"] [TSField False "Left" "T" Nothing] Nothing+                               , TSInterfaceDeclaration "Right" ["T"] [TSField False "Right" "T" Nothing] Nothing                                ]   getParentTypes _ = L.nub [ (TSType (Proxy :: Proxy a))                            , (TSType (Proxy :: Proxy b))
+ src/Data/Aeson/TypeScript/LegalName.hs view
@@ -0,0 +1,39 @@+-- | This module defines functions which are useful for determining if+-- a given name is a legal JavaScript name according to+-- <https://stackoverflow.com/questions/1661197/what-characters-are-valid-for-javascript-variable-names this post>.+module Data.Aeson.TypeScript.LegalName where++import Data.Char+import Data.List.NonEmpty (NonEmpty (..))+import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Set as Set+++-- | The return type is the illegal characters that are in the name. If the+-- input has no illegal characters, then you have 'Nothing'.+checkIllegalNameChars :: NonEmpty Char -> Maybe (NonEmpty Char)+checkIllegalNameChars (firstChar :| restChars) = NonEmpty.nonEmpty $+  let+    legalFirstCategories =+      Set.fromList+        [ UppercaseLetter+        , LowercaseLetter+        , TitlecaseLetter+        , ModifierLetter+        , OtherLetter+        , LetterNumber+        ]+    legalRestCategories =+      Set.fromList+        [ NonSpacingMark+        , SpacingCombiningMark+        , DecimalNumber+        , ConnectorPunctuation+        ]+        `Set.union` legalFirstCategories+    isIllegalFirstChar c = not $+      c `elem` ['$', '_'] || generalCategory c `Set.member` legalFirstCategories+    isIllegalRestChar c = not $+      generalCategory c `Set.member` legalRestCategories+  in+    filter isIllegalFirstChar [firstChar] <> filter isIllegalRestChar restChars
src/Data/Aeson/TypeScript/Lookup.hs view
@@ -1,17 +1,8 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE ViewPatterns #-} {-# LANGUAGE PolyKinds #-}-{-# LANGUAGE LambdaCase #-}  module Data.Aeson.TypeScript.Lookup where @@ -46,16 +37,16 @@   fields <- forM eqns $ \case #if MIN_VERSION_template_haskell(2,15,0)     TySynEqn Nothing (AppT (ConT _) (ConT arg)) result -> do-      [| TSField False (getTypeScriptType (Proxy :: Proxy $(conT arg))) (getTypeScriptType (Proxy :: Proxy $(return result))) |]+      [| TSField False (getTypeScriptType (Proxy :: Proxy $(conT arg))) (getTypeScriptType (Proxy :: Proxy $(return result))) Nothing |]     TySynEqn Nothing (AppT (ConT _) (PromotedT arg)) result -> do-      [| TSField False (getTypeScriptType (Proxy :: Proxy $(promotedT arg))) (getTypeScriptType (Proxy :: Proxy $(return result))) |]+      [| TSField False (getTypeScriptType (Proxy :: Proxy $(promotedT arg))) (getTypeScriptType (Proxy :: Proxy $(return result))) Nothing |] #else     TySynEqn [ConT arg] result -> do-      [| TSField False (getTypeScriptType (Proxy :: Proxy $(conT arg))) (getTypeScriptType (Proxy :: Proxy $(return result))) |]+      [| TSField False (getTypeScriptType (Proxy :: Proxy $(conT arg))) (getTypeScriptType (Proxy :: Proxy $(return result))) Nothing |] #endif     x -> fail [i|aeson-typescript doesn't know yet how to handle this type family equation: '#{x}'|] -  [| TSInterfaceDeclaration $(TH.stringE $ nameBase name) [] (L.sortBy (compare `on` fieldName) $(listE $ fmap return fields)) |]+  [| TSInterfaceDeclaration $(TH.stringE $ nameBase name) [] (L.sortBy (compare `on` fieldName) $(listE $ fmap return fields)) Nothing |]  getClosedTypeFamilyImage :: [TySynEqn] -> Q [Type] getClosedTypeFamilyImage eqns = do
src/Data/Aeson/TypeScript/Recursive.hs view
@@ -1,14 +1,6 @@-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE ViewPatterns #-}-{-# LANGUAGE LambdaCase #-} {-# LANGUAGE PolyKinds #-}  module Data.Aeson.TypeScript.Recursive (@@ -29,6 +21,7 @@ import Control.Monad.Writer import Data.Aeson.TypeScript.Instances () import Data.Aeson.TypeScript.TH+import Data.Aeson.TypeScript.Util (nothingOnFail) import Data.Bifunctor import Data.Function import qualified Data.List as L@@ -135,6 +128,3 @@     addIfNotPresent :: (Eq a) => a -> [a] -> [a]     addIfNotPresent x xs | x `L.elem` xs = xs     addIfNotPresent x xs = x : xs--nothingOnFail :: Q a -> Q (Maybe a)-nothingOnFail action = recover (return Nothing) (Just <$> action)
src/Data/Aeson/TypeScript/TH.hs view
@@ -1,17 +1,8 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE ViewPatterns #-} {-# LANGUAGE PolyKinds #-}-{-# LANGUAGE LambdaCase #-}  {-| Module:      Data.Aeson.TypeScript.TH@@ -127,6 +118,7 @@   , formatTSDeclaration   , FormattingOptions(..)   , defaultFormattingOptions+  , defaultNameFormatter   , SumTypeFormat(..)   , ExportMode(..) @@ -194,7 +186,7 @@         xs -> zip xs allStarConstructors''   genericVariablesAndSuffixes <- forM varsAndTVars $ \(var, tvar) -> do     (_, genericInfos) <- runWriterT $ forM_ (datatypeCons datatypeInfo') $ \ci ->-      forM_ (namesAndTypes options [] ci) $ \(_, typ) -> do+      forM_ (namesAndTypes options [] ci) $ \(_, _, typ) -> do         searchForConstraints extraOptions typ var     return (var, (unifyGenericVariable genericInfos, tvar)) @@ -216,10 +208,11 @@   let typeVariablePreds :: [Pred] = [AppT (ConT ''TypeScript) x | x <- getDataTypeVars dti]    -- Build the declarations-  (types, (extraDeclsOrGenericInfosInitial <>) -> extraDeclsOrGenericInfos) <- runWriterT $ mapM (handleConstructor options dti genericVariablesAndSuffixes) (datatypeCons dti)+  (types, (extraDeclsOrGenericInfosInitial <>) -> extraDeclsOrGenericInfos) <- runWriterT $ mapM (handleConstructor extraOptions options dti genericVariablesAndSuffixes) (datatypeCons dti)   typeDeclaration <- [|TSTypeAlternatives $(TH.stringE $ getTypeName (datatypeName dti))                                           $(genericVariablesListExpr True genericVariablesAndSuffixes)-                                          $(listE $ fmap return types)|]+                                          $(listE $ fmap return types)+                                          $(tryGetDoc (haddockModifier extraOptions) (datatypeName dti))|]    declarationsFunctionBody <- [| $(return typeDeclaration) : $(listE (fmap return [x | ExtraDecl x <- extraDeclsOrGenericInfos])) |] @@ -243,8 +236,8 @@   return (mconcat [x | ExtraTopLevelDecs x <- extraDeclsOrGenericInfos] <> inst)  -- | Return a string to go in the top-level type declaration, plus an optional expression containing a declaration-handleConstructor :: Options -> DatatypeInfo -> [(Name, (Suffix, Var))] -> ConstructorInfo -> WriterT [ExtraDeclOrGenericInfo] Q Exp-handleConstructor options (DatatypeInfo {..}) genericVariables ci = do+handleConstructor :: ExtraTypeScriptOptions -> Options -> DatatypeInfo -> [(Name, (Suffix, Var))] -> ConstructorInfo -> WriterT [ExtraDeclOrGenericInfo] Q Exp+handleConstructor (ExtraTypeScriptOptions {..}) options (DatatypeInfo {..}) genericVariables ci = do   if | (length datatypeCons == 1) && not (getTagSingleConstructors options) -> do          writeSingleConstructorEncoding          brackets <- lift $ getBracketsExpression False genericVariables@@ -269,7 +262,7 @@          lift [|$(TH.stringE interfaceName) <> $(return brackets)|]      | otherwise -> do          tagField :: [Exp] <- lift $ case sumEncoding options of-           TaggedObject tagFieldName _ -> (: []) <$> [|TSField False $(TH.stringE tagFieldName) $(TH.stringE [i|"#{constructorNameToUse options ci}"|])|]+           TaggedObject tagFieldName _ -> (: []) <$> [|TSField False $(TH.stringE tagFieldName) $(TH.stringE [i|"#{constructorNameToUse options ci}"|]) Nothing|]            _ -> return []           tsFields <- getTSFields@@ -294,7 +287,8 @@             _ -> getTypeAsStringExp typ           alternatives <- lift [|TSTypeAlternatives $(TH.stringE interfaceName)                                                     $(genericVariablesListExpr True genericVariables)-                                                    [$(return stringExp)]|]+                                                    [$(return stringExp)]+                                                    $(tryGetDoc haddockModifier (constructorName ci))|]           tell [ExtraDecl alternatives] #endif @@ -309,21 +303,24 @@     tupleEncoding =       lift [|TSTypeAlternatives $(TH.stringE interfaceName)                                 $(genericVariablesListExpr True genericVariables)-                                [getTypeScriptType (Proxy :: Proxy $(return (contentsTupleTypeSubstituted genericVariables ci)))]|]+                                [getTypeScriptType (Proxy :: Proxy $(return (contentsTupleTypeSubstituted genericVariables ci)))]+                                $(tryGetDoc haddockModifier (constructorName ci))|]      assembleInterfaceDeclaration members = [|TSInterfaceDeclaration $(TH.stringE interfaceName)                                                                     $(genericVariablesListExpr True genericVariables)-                                                                    $(return members)|]+                                                                    $(return members)+                                                                    $(tryGetDoc haddockModifier (constructorName ci))|]      getTSFields :: WriterT [ExtraDeclOrGenericInfo] Q [Exp]-    getTSFields = forM (namesAndTypes options genericVariables ci) $ \(nameString, typ) -> do+    getTSFields = forM (namesAndTypes options genericVariables ci) $ \(name, nameString, typ) -> do       (fieldTyp, optAsBool) <- lift $ case typ of         (AppT (ConT name) t) | name == ''Maybe && not (omitNothingFields options) ->           ( , ) <$> [|$(getTypeAsStringExp t) <> " | null"|] <*> getOptionalAsBoolExp t         _ -> ( , ) <$> getTypeAsStringExp typ <*> getOptionalAsBoolExp typ-      lift $ [| TSField $(return optAsBool) $(TH.stringE nameString) $(return fieldTyp) |] -    isSingleRecordConstructor (constructorVariant -> RecordConstructor [x]) = True+      lift [| TSField $(return optAsBool) $(TH.stringE nameString) $(return fieldTyp) $(tryGetDoc haddockModifier name) |]++    isSingleRecordConstructor (constructorVariant -> RecordConstructor [_]) = True     isSingleRecordConstructor _ = False  -- * Convenience functions
src/Data/Aeson/TypeScript/Transform.hs view
@@ -1,17 +1,8 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE ViewPatterns #-} {-# LANGUAGE PolyKinds #-}-{-# LANGUAGE LambdaCase #-}   module Data.Aeson.TypeScript.Transform (
src/Data/Aeson/TypeScript/TypeManipulation.hs view
@@ -1,17 +1,8 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE ViewPatterns #-} {-# LANGUAGE PolyKinds #-}-{-# LANGUAGE LambdaCase #-}  module Data.Aeson.TypeScript.TypeManipulation (   searchForConstraints
src/Data/Aeson/TypeScript/Types.hs view
@@ -1,8 +1,4 @@-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE StandaloneDeriving #-}@@ -10,8 +6,12 @@ module Data.Aeson.TypeScript.Types where  import qualified Data.Aeson as A+import Data.Aeson.TypeScript.LegalName+import Data.Function ((&))+import qualified Data.List.NonEmpty as NonEmpty import Data.Proxy import Data.String+import qualified Data.Text as T import Data.Typeable import Language.Haskell.TH @@ -84,16 +84,22 @@  data TSDeclaration = TSInterfaceDeclaration { interfaceName :: String                                             , interfaceGenericVariables :: [String]-                                            , interfaceMembers :: [TSField] }+                                            , interfaceMembers :: [TSField]+                                            , interfaceDoc :: Maybe String }                    | TSTypeAlternatives { typeName :: String                                         , typeGenericVariables :: [String]-                                        , alternativeTypes :: [String]}+                                        , alternativeTypes :: [String]+                                        , typeDoc :: Maybe String }                    | TSRawDeclaration { text :: String }   deriving (Show, Eq, Ord) -data TSField = TSField { fieldOptional :: Bool-                       , fieldName :: String-                       , fieldType :: String } deriving (Show, Eq, Ord)+data TSField = TSField+  { fieldOptional :: Bool+  , fieldName :: String+  , fieldType :: String+  , fieldDoc :: Maybe String+  -- ^ Haddock documentation for the field, if present+  } deriving (Show, Eq, Ord)  newtype TSString a = TSString { unpackTSString :: String } deriving Show @@ -131,12 +137,30 @@ defaultFormattingOptions :: FormattingOptions defaultFormattingOptions = FormattingOptions   { numIndentSpaces = 2-  , interfaceNameModifier = id-  , typeNameModifier = id+  , interfaceNameModifier = defaultNameFormatter+  , typeNameModifier = defaultNameFormatter   , exportMode = ExportNone   , typeAlternativesFormat = TypeAlias   } +-- | The 'defaultNameFormatter' in the 'FormattingOptions' checks to see if+-- the name is a legal TypeScript name. If it is not, then it throws+-- a runtime error.+defaultNameFormatter :: String -> String+defaultNameFormatter str =+  case NonEmpty.nonEmpty str of+    Nothing ->+      error "Name cannot be empty"+    Just nameChars ->+      case checkIllegalNameChars nameChars of+        Just badChars ->+          error $ concat+            [ "The name ", str, " contains illegal characters: ", NonEmpty.toList badChars+            , "\nConsider setting a default name formatter that replaces these characters, or renaming the type."+            ]+        Nothing ->+          str+ -- | Convenience typeclass class you can use to "attach" a set of Aeson encoding options to a type. class HasJSONOptions a where   getJSONOptions :: (Proxy a) -> A.Options@@ -178,11 +202,24 @@  data ExtraTypeScriptOptions = ExtraTypeScriptOptions {   typeFamiliesToMapToTypeScript :: [Name]+   , keyType :: Maybe String++  -- | Function which is applied to all Haddocks we read in.+  -- By default, just drops leading whitespace from each line.+  , haddockModifier :: String -> String   }  defaultExtraTypeScriptOptions :: ExtraTypeScriptOptions-defaultExtraTypeScriptOptions = ExtraTypeScriptOptions [] Nothing+defaultExtraTypeScriptOptions = ExtraTypeScriptOptions [] Nothing stripStartEachLine+  where+    stripStartEachLine :: String -> String+    stripStartEachLine s = s+                         & T.pack+                         & T.splitOn "\n"+                         & fmap T.stripStart+                         & T.intercalate "\n"+                         & T.unpack  data ExtraDeclOrGenericInfo = ExtraDecl Exp                             | ExtraGeneric GenericInfo
src/Data/Aeson/TypeScript/Util.hs view
@@ -1,14 +1,7 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE ViewPatterns #-} {-# LANGUAGE PolyKinds #-}  module Data.Aeson.TypeScript.Util where@@ -148,14 +141,14 @@ mkInstance = InstanceD #endif -namesAndTypes :: Options -> [(Name, (Suffix, Var))] -> ConstructorInfo -> [(String, Type)]+namesAndTypes :: Options -> [(Name, (Suffix, Var))] -> ConstructorInfo -> [(Name, String, Type)] namesAndTypes options genericVariables ci = case constructorVariant ci of-  RecordConstructor names -> zip (fmap ((fieldLabelModifier options) . lastNameComponent') names) (constructorFields ci)+  RecordConstructor names -> zip3 names (fmap ((fieldLabelModifier options) . lastNameComponent') names) (constructorFields ci)   _ -> case sumEncoding options of     TaggedObject _ contentsFieldName       | isConstructorNullary ci -> []-      | otherwise -> [(contentsFieldName, contentsTupleTypeSubstituted genericVariables ci)]-    _ -> [(constructorNameToUse options ci, contentsTupleTypeSubstituted genericVariables ci)]+      | otherwise -> [(mkName "", contentsFieldName, contentsTupleTypeSubstituted genericVariables ci)]+    _ -> [(constructorName ci, constructorNameToUse options ci, contentsTupleTypeSubstituted genericVariables ci)]  constructorNameToUse :: Options -> ConstructorInfo -> String constructorNameToUse options ci = (constructorTagModifier options) $ lastNameComponent' (constructorName ci)@@ -224,3 +217,20 @@ isStarType :: Type -> Maybe Name isStarType (SigT (VarT n) StarT) = Just n isStarType _ = Nothing++nothingOnFail :: Q a -> Q (Maybe a)+nothingOnFail action = recover (return Nothing) (Just <$> action)++tryGetDoc :: (String -> String) -> Name -> Q Exp+tryGetDoc haddockModifier n = do+#if MIN_VERSION_template_haskell(2,18,0)+  maybeDoc <- nothingOnFail (getDoc (DeclDoc n)) >>= \case+    Just (Just doc) -> return $ Just $ Just $ haddockModifier doc+    x -> return x+#else+  let maybeDoc = Nothing+#endif++  case maybeDoc of+    Just (Just doc) -> [|Just $(TH.stringE doc)|]+    _ -> [|Nothing|]
test/Basic.hs view
@@ -1,17 +1,3 @@-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}  module Basic (tests) where @@ -36,12 +22,14 @@   describe "tagSingleConstructors and constructorTagModifier" $ do     it [i|Works with a normal unit|] $ do       (getTypeScriptDeclarations (Proxy :: Proxy Unit1)) `shouldBe` ([-        TSTypeAlternatives "Unit1" [] ["IUnit1"]-        , TSTypeAlternatives "IUnit1" [] ["void[]"]+        TSTypeAlternatives "Unit1" [] ["IUnit1"] Nothing+        , TSTypeAlternatives "IUnit1" [] ["void[]"] Nothing         ])      it [i|Works with a unit with constructorTagModifier|] $ do-      (getTypeScriptDeclarations (Proxy :: Proxy Unit2)) `shouldBe` ([])+      (getTypeScriptDeclarations (Proxy :: Proxy Unit2)) `shouldBe` ([+        TSTypeAlternatives "Unit2" [] ["\"foo\""] Nothing+        ])   main :: IO ()
test/ClosedTypeFamilies.hs view
@@ -1,18 +1,5 @@-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeFamilyDependencies #-}-{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}  module ClosedTypeFamilies (tests) where @@ -53,38 +40,38 @@     it [i|makes the declaration and types correctly|] $ do       (getTypeScriptDeclarationsRecursively (Proxy :: Proxy (Simple T))) `shouldBe` ([         TSInterfaceDeclaration "DeployEnvironment2" [] [-          TSField False "\"k8s_env\"" "\"k8s\""-          , TSField False "\"single_node_env\"" "\"single\""-          , TSField False "T" "void"-          ]-        , TSTypeAlternatives "ISimple" ["T extends keyof DeployEnvironment2"] ["DeployEnvironment2[T]"]-        , TSTypeAlternatives "Simple" ["T extends keyof DeployEnvironment2"] ["ISimple<T>"]+          TSField False "\"k8s_env\"" "\"k8s\"" Nothing+          , TSField False "\"single_node_env\"" "\"single\"" Nothing+          , TSField False "T" "void" Nothing+          ] Nothing+        , TSTypeAlternatives "ISimple" ["T extends keyof DeployEnvironment2"] ["DeployEnvironment2[T]"] Nothing+        , TSTypeAlternatives "Simple" ["T extends keyof DeployEnvironment2"] ["ISimple<T>"] Nothing         ])    describe "Complicated Beam-like user type" $ do     it [i|makes the declaration and types correctly|] $ do       (getTypeScriptDeclarations (Proxy :: Proxy (UserT T Identity))) `shouldBe` ([-        TSTypeAlternatives "UserT" ["T extends keyof DeployEnvironment"] ["IUser<T>"]+        TSTypeAlternatives "UserT" ["T extends keyof DeployEnvironment"] ["IUser<T>"] Nothing         , TSInterfaceDeclaration "IUser" ["T extends keyof DeployEnvironment"] [-            TSField False "_userUsername" "string"-            , TSField False "_userCreatedAt" "number"-            , TSField False "_userDeployEnvironment" "DeployEnvironment[T]"-            ]+            TSField False "_userUsername" "string" Nothing+            , TSField False "_userCreatedAt" "number" Nothing+            , TSField False "_userDeployEnvironment" "DeployEnvironment[T]" Nothing+            ] Nothing         ])      it [i|get the declarations recursively|] $ do       (getTypeScriptDeclarationsRecursively (Proxy :: Proxy (UserT T Identity))) `shouldBe` ([         TSInterfaceDeclaration "DeployEnvironment" [] [-          TSField False "\"k8s_env\"" "\"k8s\""-          , TSField False "\"single_node_env\"" "\"single\""-          , TSField False "T" "void"-          ]+          TSField False "\"k8s_env\"" "\"k8s\"" Nothing+          , TSField False "\"single_node_env\"" "\"single\"" Nothing+          , TSField False "T" "void" Nothing+          ] Nothing         , TSInterfaceDeclaration "IUser" ["T extends keyof DeployEnvironment"] [-            TSField False "_userUsername" "string"-            , TSField False "_userCreatedAt" "number"-            , TSField False "_userDeployEnvironment" "DeployEnvironment[T]"-            ]-        , TSTypeAlternatives "UserT" ["T extends keyof DeployEnvironment"] ["IUser<T>"]+            TSField False "_userUsername" "string" Nothing+            , TSField False "_userCreatedAt" "number" Nothing+            , TSField False "_userDeployEnvironment" "DeployEnvironment[T]" Nothing+            ] Nothing+        , TSTypeAlternatives "UserT" ["T extends keyof DeployEnvironment"] ["IUser<T>"] Nothing         ])  main :: IO ()
test/Formatting.hs view
@@ -1,34 +1,79 @@-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE TypeApplications #-}-{-# LANGUAGE QuasiQuotes #-}  module Formatting (tests) where +import Control.Exception import Data.Aeson (defaultOptions) import Data.Aeson.TypeScript.TH-import Data.Aeson.TypeScript.Types import Data.Proxy import Data.String.Interpolate import Test.Hspec -data D = S | F deriving (Eq, Show) +data D = S | F deriving (Eq, Show) $(deriveTypeScript defaultOptions ''D) +data PrimeInType' = PrimeInType+$(deriveTypeScript defaultOptions ''PrimeInType')++data PrimeInConstr = PrimeInConstr'+$(deriveTypeScript defaultOptions ''PrimeInConstr)++data FooBar =+  Foo {+    -- | @no-emit-typescript+    recordString :: String+    , recordInt :: Int+    }+  |+  -- | @no-emit-typescript+  Bar {+      barInt :: Int+  }+$(deriveTypeScript defaultOptions ''FooBar)++data NormalConstructors =+  -- | @no-emit-typescript+  Con1 String+  | Con2 Int+$(deriveTypeScript defaultOptions ''NormalConstructors)+ tests :: Spec-tests = do-  describe "Formatting" $-    describe "when given a Sum Type" $ do-      describe "and the TypeAlias format option is set" $-        it "should generate a TS string literal type" $-          formatTSDeclarations' defaultFormattingOptions (getTypeScriptDeclarations @D Proxy) `shouldBe`-            [i|type D = "S" | "F";|]-      describe "and the Enum format option is set" $-        it "should generate a TS Enum" $-          formatTSDeclarations' (defaultFormattingOptions { typeAlternativesFormat = Enum }) (getTypeScriptDeclarations @D Proxy) `shouldBe`-            [i|enum D { S, F }|]-      describe "and the EnumWithType format option is set" $-        it "should generate a TS Enum with a type declaration" $-          formatTSDeclarations' (defaultFormattingOptions { typeAlternativesFormat = EnumWithType }) (getTypeScriptDeclarations @D Proxy) `shouldBe`-            [i|enum DEnum { S="S", F="F" }\n\ntype D = keyof typeof DEnum;|]+tests = describe "Formatting" $ do+  describe "when given a Sum Type" $ do+    describe "and the TypeAlias format option is set" $+      it "should generate a TS string literal type" $+        formatTSDeclarations' defaultFormattingOptions (getTypeScriptDeclarations @D Proxy) `shouldBe`+          [i|type D = "S" | "F";|]++    describe "and the Enum format option is set" $+      it "should generate a TS Enum" $+        formatTSDeclarations' (defaultFormattingOptions { typeAlternativesFormat = Enum }) (getTypeScriptDeclarations @D Proxy) `shouldBe`+          [i|enum D { S, F }|]++    describe "and the EnumWithType format option is set" $+      it "should generate a TS Enum with a type declaration" $+        formatTSDeclarations' (defaultFormattingOptions { typeAlternativesFormat = EnumWithType }) (getTypeScriptDeclarations @D Proxy) `shouldBe`+          [i|enum DEnum { S="S", F="F" }\n\ntype D = keyof typeof DEnum;|]++  describe "when the name has an apostrophe" $ do+    describe "in the type" $ do+      it "throws an error" $ do+        evaluate (formatTSDeclarations' defaultFormattingOptions (getTypeScriptDeclarations @PrimeInType' Proxy)) `shouldThrow` anyErrorCall++    describe "in the constructor" $ do+      it "throws an error" $ do+        evaluate (formatTSDeclarations' defaultFormattingOptions (getTypeScriptDeclarations @PrimeInConstr Proxy)) `shouldThrow` anyErrorCall++#if MIN_VERSION_template_haskell(2,18,0)+  describe "when @no-emit-typescript is present" $ do+    it [i|works on records and constructors of record types|] $ do+      formatTSDeclarations' defaultFormattingOptions (getTypeScriptDeclarations @FooBar Proxy) `shouldBe` [i|type FooBar = IFoo;\n\ninterface IFoo {\n  tag: "Foo";\n  recordInt: number;\n}|]++    it [i|works on normal constructors|] $ do+      formatTSDeclarations' defaultFormattingOptions (getTypeScriptDeclarations @NormalConstructors Proxy) `shouldBe` [i|type NormalConstructors = ICon2;\n\ninterface ICon2 {\n  tag: "Con2";\n  contents: number;\n}|]+#endif++main :: IO ()+main = hspec tests
test/Generic.hs view
@@ -1,18 +1,3 @@-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeFamilyDependencies #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}  module Generic (tests) where @@ -44,38 +29,32 @@ tests = describe "Generic instances" $ do   it [i|Complex makes the declaration and types correctly|] $ do     (getTypeScriptDeclarationsRecursively (Proxy :: Proxy (Complex String))) `shouldBe` [-      TSInterfaceDeclaration {interfaceName = "IProduct", interfaceGenericVariables = ["T"], interfaceMembers = [TSField {fieldOptional = False, fieldName = "tag", fieldType = "\"Product\""},TSField {fieldOptional = False, fieldName = "contents", fieldType = "[number, T]"}]}-      ,TSInterfaceDeclaration {interfaceName = "IUnary", interfaceGenericVariables = ["T"], interfaceMembers = [TSField {fieldOptional = False, fieldName = "tag", fieldType = "\"Unary\""},TSField {fieldOptional = False, fieldName = "contents", fieldType = "number"}]}-      ,TSTypeAlternatives {typeName = "Complex", typeGenericVariables = ["T"], alternativeTypes = ["IProduct<T>","IUnary<T>"]}+      TSInterfaceDeclaration "IProduct" ["T"] [TSField False "tag" "\"Product\"" Nothing, TSField False "contents" "[number, T]" Nothing] Nothing+      ,TSInterfaceDeclaration "IUnary" ["T"] [TSField False "tag" "\"Unary\"" Nothing, TSField False "contents" "number" Nothing] Nothing+      ,TSTypeAlternatives "Complex" ["T"] ["IProduct<T>","IUnary<T>"] Nothing       ]    it [i|Complex2 makes the declaration and types correctly|] $ do     (getTypeScriptDeclarationsRecursively (Proxy :: Proxy (Complex2 String))) `shouldBe` [-      TSTypeAlternatives {typeName = "Complex2", typeGenericVariables = ["T"], alternativeTypes = ["IProduct2<T>"]}-      ,TSTypeAlternatives {typeName = "IProduct2", typeGenericVariables = ["T"], alternativeTypes = ["[number, T]"]}+      TSTypeAlternatives "Complex2" ["T"] ["IProduct2<T>"] Nothing+      ,TSTypeAlternatives "IProduct2" ["T"] ["[number, T]"] Nothing       ]    it [i|Complex3 makes the declaration and types correctly|] $ do     (getTypeScriptDeclarationsRecursively (Proxy :: Proxy (Complex3 String))) `shouldBe` [-      TSInterfaceDeclaration {interfaceName = "IProduct3", interfaceGenericVariables = ["T"], interfaceMembers = [-                                 TSField {fieldOptional = False, fieldName = "record3", fieldType = "T[]"}-                                 ]}-      ,TSTypeAlternatives {typeName = "Complex3", typeGenericVariables = ["T"], alternativeTypes = ["IProduct3<T>"]}+      TSInterfaceDeclaration "IProduct3" ["T"] [TSField False "record3" "T[]" Nothing] Nothing+      ,TSTypeAlternatives "Complex3" ["T"] ["IProduct3<T>"] Nothing       ]      (getTypeScriptDeclarationsRecursively (Proxy :: Proxy (Complex3 Int))) `shouldBe` [-      TSInterfaceDeclaration {interfaceName = "IProduct3", interfaceGenericVariables = ["T"], interfaceMembers = [-                                 TSField {fieldOptional = False, fieldName = "record3", fieldType = "T[]"}-                                 ]}-      ,TSTypeAlternatives {typeName = "Complex3", typeGenericVariables = ["T"], alternativeTypes = ["IProduct3<T>"]}+      TSInterfaceDeclaration "IProduct3" ["T"] [TSField False "record3" "T[]" Nothing] Nothing+      ,TSTypeAlternatives "Complex3" ["T"] ["IProduct3<T>"] Nothing       ]    it [i|Complex4 makes the declaration and types correctly|] $ do     (getTypeScriptDeclarationsRecursively (Proxy :: Proxy (Complex4 String))) `shouldBe` [-      TSInterfaceDeclaration {interfaceName = "IProduct4", interfaceGenericVariables = ["T"], interfaceMembers = [-                                 TSField {fieldOptional = False, fieldName = "record4", fieldType = "{[k in string]?: T}"}-                                 ]}-      ,TSTypeAlternatives {typeName = "Complex4", typeGenericVariables = ["T"], alternativeTypes = ["IProduct4<T>"]}+      TSInterfaceDeclaration "IProduct4" ["T"] [TSField False "record4" "{[k in string]?: T}" Nothing] Nothing+      ,TSTypeAlternatives "Complex4" ["T"] ["IProduct4<T>"] Nothing       ]  main :: IO ()
+ test/GetDoc.hs view
@@ -0,0 +1,33 @@++module GetDoc (tests) where++import Data.Aeson as A+import Data.Aeson.TypeScript.TH+import Data.Aeson.TypeScript.Types+import Data.Proxy+import Data.String.Interpolate+import Prelude hiding (Double)+import Test.Hspec+++-- | OneField type doc+data OneField =+  -- | OneField constructor doc+  OneField {+    -- | This is a simple string+    simpleString :: String+    }+$(deriveTypeScript A.defaultOptions ''OneField)++tests :: SpecWith ()+tests = describe "getDoc tests" $ do+  it [i|Works with a simple record type|] $ do+    (getTypeScriptDeclarations (Proxy :: Proxy OneField)) `shouldBe` ([+      TSTypeAlternatives "OneField" [] ["IOneField"] (Just "OneField type doc")+      , TSInterfaceDeclaration "IOneField" [] [+          TSField False "simpleString" "string" (Just "This is a simple string")+          ] (Just "OneField constructor doc")+      ])++main :: IO ()+main = hspec tests
test/HigherKind.hs view
@@ -1,17 +1,3 @@-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}  module HigherKind (tests) where @@ -50,8 +36,8 @@   describe "Kind * -> *" $ do     it [i|makes the declaration and types correctly|] $ do       (getTypeScriptDeclarations (Proxy :: Proxy (HigherKind T))) `shouldBe` ([-        TSTypeAlternatives "HigherKind" ["T"] ["IHigherKind<T>"],-        TSInterfaceDeclaration "IHigherKind" ["T"] [TSField False "higherKindList" "T[]"]+        TSTypeAlternatives "HigherKind" ["T"] ["IHigherKind<T>"] Nothing,+        TSInterfaceDeclaration "IHigherKind" ["T"] [TSField False "higherKindList" "T[]" Nothing] Nothing         ])        (getTypeScriptType (Proxy :: Proxy (HigherKind Int))) `shouldBe` "HigherKind<number>"@@ -59,23 +45,23 @@      it [i|works when referenced in another type|] $ do       (getTypeScriptDeclarations (Proxy :: Proxy Foo)) `shouldBe` ([-        TSTypeAlternatives "Foo" [] ["IFoo"],-        TSInterfaceDeclaration "IFoo" [] [TSField False "fooString" "string"-                                         , TSField False "fooHigherKindReference" "HigherKind<string>"]+        TSTypeAlternatives "Foo" [] ["IFoo"] Nothing,+        TSInterfaceDeclaration "IFoo" [] [TSField False "fooString" "string" Nothing+                                         , TSField False "fooHigherKindReference" "HigherKind<string>" Nothing] Nothing         ])      it [i|works with an interface inside|] $ do       (getTypeScriptDeclarations (Proxy :: Proxy (HigherKindWithUnary T))) `shouldBe` ([-        TSTypeAlternatives "HigherKindWithUnary" ["T"] ["IUnary<T>"],-        TSTypeAlternatives "IUnary" ["T"] ["number"]+        TSTypeAlternatives "HigherKindWithUnary" ["T"] ["IUnary<T>"] Nothing,+        TSTypeAlternatives "IUnary" ["T"] ["number"] Nothing         ])    describe "Kind * -> * -> *" $ do     it [i|makes the declaration and type correctly|] $ do       (getTypeScriptDeclarations (Proxy :: Proxy (DoubleHigherKind T1 T2))) `shouldBe` ([-        TSTypeAlternatives "DoubleHigherKind" ["T1","T2"] ["IDoubleHigherKind<T1, T2>"],-        TSInterfaceDeclaration "IDoubleHigherKind" ["T1","T2"] [TSField False "someList" "T2[]"-                                                               , TSField False "higherKindThing" "HigherKind<T1>"]+        TSTypeAlternatives "DoubleHigherKind" ["T1","T2"] ["IDoubleHigherKind<T1, T2>"] Nothing,+        TSInterfaceDeclaration "IDoubleHigherKind" ["T1","T2"] [TSField False "someList" "T2[]" Nothing+                                                               , TSField False "higherKindThing" "HigherKind<T1>" Nothing] Nothing         ])        (getTypeScriptType (Proxy :: Proxy (DoubleHigherKind Int String))) `shouldBe` "DoubleHigherKind<number, string>"
+ test/LegalNameSpec.hs view
@@ -0,0 +1,24 @@++module LegalNameSpec where++import Data.Aeson.TypeScript.LegalName+import Data.List.NonEmpty (NonEmpty (..))+import Test.Hspec++tests :: Spec+tests = describe "Data.Aeson.TypeScript.LegalName" $ do+  describe "checkIllegalNameChars" $ do+    describe "legal Haskell names" $ do+      it "allows an uppercase letter" $ do+        checkIllegalNameChars ('A' :| [])+          `shouldBe` Nothing+      it "allows an underscore" $ do+        checkIllegalNameChars ('_' :| "asdf")+          `shouldBe` Nothing+      it "reports that ' is illegal" $ do+        checkIllegalNameChars ('F' :| "oo'")+          `shouldBe` Just ('\'' :| [])+    describe "illegal Haskell names" $ do+      it "allows a $" $ do+        checkIllegalNameChars ('$' :| "asdf")+          `shouldBe` Nothing
test/NoOmitNothingFields.hs view
@@ -1,15 +1,3 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE MonoLocalBinds #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}  module NoOmitNothingFields (allTests) where @@ -27,17 +15,7 @@   it "encodes as expected" $ do     let decls = getTypeScriptDeclarations (Proxy :: Proxy Optional) -    decls `shouldBe` [TSTypeAlternatives {-                         typeName = "Optional"-                         , typeGenericVariables = []-                         , alternativeTypes = ["IOptional"]-                         }-                     , TSInterfaceDeclaration {-                         interfaceName = "IOptional"-                         , interfaceGenericVariables = []-                         , interfaceMembers = [TSField {fieldOptional = False-                                                       , fieldName = "optionalInt"-                                                       , fieldType = "number | null"}]-                         }]+    decls `shouldBe` [TSTypeAlternatives "Optional" [] ["IOptional"] Nothing+                     , TSInterfaceDeclaration "IOptional" [] [TSField False "optionalInt" "number | null" Nothing] Nothing]    tests
test/ObjectWithSingleFieldNoTagSingleConstructors.hs view
@@ -1,15 +1,3 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE MonoLocalBinds #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}  module ObjectWithSingleFieldNoTagSingleConstructors (main, tests) where 
test/ObjectWithSingleFieldTagSingleConstructors.hs view
@@ -1,15 +1,3 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE MonoLocalBinds #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}  module ObjectWithSingleFieldTagSingleConstructors (main, tests) where 
test/OmitNothingFields.hs view
@@ -1,15 +1,3 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE MonoLocalBinds #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}  module OmitNothingFields (main, tests) where @@ -31,10 +19,9 @@                          interfaceName = "Optional"                          , interfaceGenericVariables = []                          , interfaceMembers = [-                             TSField {fieldOptional = True-                                     , fieldName = "optionalInt"-                                     , fieldType = "number"}+                             TSField True "optionalInt" "number" Nothing                              ]+                         , interfaceDoc = Nothing                          }]    tests
test/OpenTypeFamilies.hs view
@@ -1,18 +1,5 @@-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeFamilyDependencies #-}-{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}  module OpenTypeFamilies (tests) where @@ -53,38 +40,38 @@     it [i|makes the declaration and types correctly|] $ do       (getTypeScriptDeclarationsRecursively (Proxy :: Proxy (Simple T))) `shouldBe` ([         TSInterfaceDeclaration "DeployEnvironment2" [] [-          TSField False "\"single_node_env\"" "\"single\""-          , TSField False "\"k8s_env\"" "\"k8s\""-          , TSField False "T" "void"-          ]-        , TSTypeAlternatives "ISimple" ["T extends keyof DeployEnvironment2"] ["DeployEnvironment2[T]"]-        , TSTypeAlternatives "Simple" ["T extends keyof DeployEnvironment2"] ["ISimple<T>"]+          TSField False "\"single_node_env\"" "\"single\"" Nothing+          , TSField False "\"k8s_env\"" "\"k8s\"" Nothing+          , TSField False "T" "void" Nothing+          ] Nothing+        , TSTypeAlternatives "ISimple" ["T extends keyof DeployEnvironment2"] ["DeployEnvironment2[T]"] Nothing+        , TSTypeAlternatives "Simple" ["T extends keyof DeployEnvironment2"] ["ISimple<T>"] Nothing         ])    describe "Complicated Beam-like user type" $ do     it [i|makes the declaration and types correctly|] $ do       (getTypeScriptDeclarations (Proxy :: Proxy (UserT T Identity))) `shouldBe` ([-        TSTypeAlternatives "UserT" ["T extends keyof DeployEnvironment"] ["IUser<T>"]+        TSTypeAlternatives "UserT" ["T extends keyof DeployEnvironment"] ["IUser<T>"] Nothing         , TSInterfaceDeclaration "IUser" ["T extends keyof DeployEnvironment"] [-            TSField False "_userUsername" "string"-            , TSField False "_userCreatedAt" "number"-            , TSField False "_userDeployEnvironment" "DeployEnvironment[T]"-            ]+            TSField False "_userUsername" "string" Nothing+            , TSField False "_userCreatedAt" "number" Nothing+            , TSField False "_userDeployEnvironment" "DeployEnvironment[T]" Nothing+            ] Nothing         ])      it [i|get the declarations recursively|] $ do       (getTypeScriptDeclarationsRecursively (Proxy :: Proxy (UserT T Identity))) `shouldBe` ([         TSInterfaceDeclaration "DeployEnvironment" [] [-          TSField False "\"single_node_env\"" "\"single\""-          , TSField False "\"k8s_env\"" "\"k8s\""-          , TSField False "T" "void"-          ]+          TSField False "\"single_node_env\"" "\"single\"" Nothing+          , TSField False "\"k8s_env\"" "\"k8s\"" Nothing+          , TSField False "T" "void" Nothing+          ] Nothing         , TSInterfaceDeclaration "IUser" ["T extends keyof DeployEnvironment"] [-            TSField False "_userUsername" "string"-            , TSField False "_userCreatedAt" "number"-            , TSField False "_userDeployEnvironment" "DeployEnvironment[T]"-            ]-        , TSTypeAlternatives "UserT" ["T extends keyof DeployEnvironment"] ["IUser<T>"]+            TSField False "_userUsername" "string" Nothing+            , TSField False "_userCreatedAt" "number" Nothing+            , TSField False "_userDeployEnvironment" "DeployEnvironment[T]" Nothing+            ] Nothing+        , TSTypeAlternatives "UserT" ["T extends keyof DeployEnvironment"] ["IUser<T>"] Nothing         ])  main :: IO ()
test/Spec.hs view
@@ -1,41 +1,50 @@+{-# LANGUAGE CPP #-}  module Main where  import Test.Hspec +import qualified Basic import qualified Formatting import qualified Generic+import qualified GetDoc import qualified HigherKind import qualified ClosedTypeFamilies +import qualified LegalNameSpec+import qualified NoOmitNothingFields import qualified ObjectWithSingleFieldNoTagSingleConstructors import qualified ObjectWithSingleFieldTagSingleConstructors+import qualified OmitNothingFields import qualified TaggedObjectNoTagSingleConstructors import qualified TaggedObjectTagSingleConstructors import qualified TwoElemArrayNoTagSingleConstructors import qualified TwoElemArrayTagSingleConstructors import qualified UntaggedNoTagSingleConstructors import qualified UntaggedTagSingleConstructors-import qualified OmitNothingFields-import qualified NoOmitNothingFields import qualified UnwrapUnaryRecords   main :: IO ()-main = hspec $ do+main = hspec $ parallel $ do+  Basic.tests+  ClosedTypeFamilies.tests   Formatting.tests   Generic.tests+#if MIN_VERSION_template_haskell(2,18,0)+  GetDoc.tests+#endif   HigherKind.tests-  ClosedTypeFamilies.tests -  ObjectWithSingleFieldTagSingleConstructors.tests+  LegalNameSpec.tests+  NoOmitNothingFields.allTests   ObjectWithSingleFieldNoTagSingleConstructors.tests-  TaggedObjectTagSingleConstructors.tests+  ObjectWithSingleFieldTagSingleConstructors.tests+  OmitNothingFields.tests   TaggedObjectNoTagSingleConstructors.tests-  TwoElemArrayTagSingleConstructors.tests+  TaggedObjectTagSingleConstructors.tests   TwoElemArrayNoTagSingleConstructors.tests-  UntaggedTagSingleConstructors.tests+  TwoElemArrayTagSingleConstructors.tests   UntaggedNoTagSingleConstructors.tests-  OmitNothingFields.tests-  NoOmitNothingFields.allTests+  UntaggedTagSingleConstructors.tests   UnwrapUnaryRecords.allTests
test/TaggedObjectNoTagSingleConstructors.hs view
@@ -1,15 +1,3 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE MonoLocalBinds #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}  module TaggedObjectNoTagSingleConstructors (main, tests) where 
test/TaggedObjectTagSingleConstructors.hs view
@@ -1,15 +1,3 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE MonoLocalBinds #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}  module TaggedObjectTagSingleConstructors (main, tests) where 
test/TestBoilerplate.hs view
@@ -1,16 +1,4 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}  module TestBoilerplate where 
test/TwoElemArrayNoTagSingleConstructors.hs view
@@ -1,15 +1,3 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE MonoLocalBinds #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}  module TwoElemArrayNoTagSingleConstructors (main, tests) where 
test/TwoElemArrayTagSingleConstructors.hs view
@@ -1,15 +1,3 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE MonoLocalBinds #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}  module TwoElemArrayTagSingleConstructors (main, tests) where 
test/UntaggedNoTagSingleConstructors.hs view
@@ -1,15 +1,4 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE MonoLocalBinds #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}  module UntaggedNoTagSingleConstructors (main, tests) where 
test/UntaggedTagSingleConstructors.hs view
@@ -1,15 +1,4 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE MonoLocalBinds #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}  module UntaggedTagSingleConstructors (main, tests) where 
test/UnwrapUnaryRecords.hs view
@@ -1,15 +1,4 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE MonoLocalBinds #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}  module UnwrapUnaryRecords (allTests) where @@ -30,8 +19,8 @@     let decls = getTypeScriptDeclarations (Proxy :: Proxy OneField)      decls `shouldBe` [-      TSTypeAlternatives {typeName = "OneField", typeGenericVariables = [], alternativeTypes = ["IOneField"]}-      ,TSTypeAlternatives {typeName = "IOneField", typeGenericVariables = [], alternativeTypes = ["string"]}+      TSTypeAlternatives "OneField" [] ["IOneField"] Nothing+      ,TSTypeAlternatives "IOneField" [] ["string"] Nothing       ]    tests@@ -42,5 +31,5 @@ allTests = tests #endif --- main :: IO ()--- main = hspec allTests+main :: IO ()+main = hspec allTests
test/Util.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, QuasiQuotes, OverloadedStrings, TemplateHaskell, RecordWildCards, ScopedTypeVariables, NamedFieldPuns, LambdaCase #-}+{-# LANGUAGE CPP #-}  module Util where @@ -14,7 +14,8 @@ import System.Exit import System.FilePath import System.IO.Temp-import System.Process+import System.Process hiding (cwd)+  npmInstallScript, yarnInstallScript, localTSC :: String npmInstallScript = "test/assets/npm_install.sh"
test/Util/Aeson.hs view
@@ -3,8 +3,10 @@ module Util.Aeson where  #if MIN_VERSION_aeson(2,0,0)+import qualified Data.Aeson.Key as K import qualified Data.Aeson.KeyMap as KM +aesonFromList :: [(K.Key, v)] -> KM.KeyMap v aesonFromList = KM.fromList #else import Data.HashMap.Strict as HM