diff --git a/elm-street.cabal b/elm-street.cabal index 7bab1b3..483e2e1 100644 --- a/elm-street.cabal +++ b/elm-street.cabal @@ -2,7 +2,11 @@ cabal-version: 2.0 name: elm-street version: 0.0.0 synopsis: Crossing the road between Haskell and Elm -description: Crossing the road between Haskell and Elm +description: + `Elm-street` allows you to generate automatically derived from Haskell types + definitions of Elm data types, JSON encoders and decoders. This helps to avoid + writing and maintaining huge chunk of boilerplate code when developing full-stack + applications. homepage: https://github.com/Holmusk/elm-street bug-reports: https://github.com/Holmusk/elm-street/issues license: MPL-2.0 diff --git a/src/Elm/Aeson.hs b/src/Elm/Aeson.hs index 6f8305f..440fcd7 100644 --- a/src/Elm/Aeson.hs +++ b/src/Elm/Aeson.hs @@ -142,7 +142,7 @@ elmStreetJsonOptions = defaultOptions In order to use it with your type @MyType@ add the following deriving to your type: @ - deriving (Elm, ToJSON, FromJSON) via ElmStreet MyType + __deriving__ (Elm, ToJSON, FromJSON) __via__ ElmStreet MyType @ -} newtype ElmStreet a = ElmStreet diff --git a/src/Elm/Ast.hs b/src/Elm/Ast.hs index 2717e17..ec199fd 100644 --- a/src/Elm/Ast.hs +++ b/src/Elm/Ast.hs @@ -23,27 +23,32 @@ import Data.List.NonEmpty (NonEmpty, toList) import Data.Text (Text) +-- | Elm data type definition. data ElmDefinition = DefAlias !ElmAlias | DefType !ElmType | DefPrim !ElmPrim deriving (Show) +-- | AST for @type alias@ in Elm. data ElmAlias = ElmAlias { elmAliasName :: !Text -- ^ Name of the alias , elmAliasFields :: !(NonEmpty ElmRecordField) -- ^ List of fields , elmAliasIsNewtype :: !Bool -- ^ 'True' if Haskell type is a @newtype@ } deriving (Show) +-- | Single file of @type alias@. data ElmRecordField = ElmRecordField { elmRecordFieldType :: !TypeRef , elmRecordFieldName :: !Text } deriving (Show) +-- | Wrapper for name of the type. newtype TypeName = TypeName { unTypeName :: Text } deriving (Show) +-- | AST for @type@ in Elm. data ElmType = ElmType { elmTypeName :: !Text -- ^ Name of the data type , elmTypeVars :: ![Text] -- ^ List of type variables; currently only phantom variables @@ -51,6 +56,7 @@ data ElmType = ElmType , elmTypeConstructors :: !(NonEmpty ElmConstructor) -- ^ List of constructors } deriving (Show) +-- | Constructor of @type@. data ElmConstructor = ElmConstructor { elmConstructorName :: !Text -- ^ Name of the constructor , elmConstructorFields :: ![TypeRef] -- ^ Fields of the constructor diff --git a/src/Elm/Generate.hs b/src/Elm/Generate.hs index 9a0ec4d..33205ab 100644 --- a/src/Elm/Generate.hs +++ b/src/Elm/Generate.hs @@ -9,6 +9,9 @@ module Elm.Generate ( Settings (..) , defaultSettings , generateElm + + -- * Internal helpers + , RenderElm (..) ) where import Data.Kind (Type) @@ -28,7 +31,7 @@ import qualified Data.Text.IO as TIO -- | Settings for outputting generated Elm code. data Settings = Settings - { settingsDirectory :: !FilePath -- ^ Directory to put generated files, e.g. @frontend/src@ + { settingsDirectory :: !FilePath -- ^ Directory to put generated files, e.g. @frontend\/src@ , settingsModule :: ![FilePath] -- ^ List of module parts, like @["ABC", "Core"]@ , settingsTypesFile :: !FilePath -- ^ File name for module with types, e.g. @Types@ , settingsEncoderFile :: !FilePath -- ^ File name for module with JSON encoders, e.g. @Encoder@ @@ -79,14 +82,14 @@ toElmDecoderSource = prettyShowDecoder $ toElmDefinition $ Proxy @a to be called like this: @ -type Types = +__type__ Types = '[ User , UserStatus , Measure ] main :: IO () -main = generateElm @Types $ defaultSettings "frontend/src/" ["ABC", "Core"] +main = generateElm @Types $ defaultSettings "frontend\/src\/" ["ABC", "Core"] @ -} generateElm :: forall (ts :: [Type]) . RenderElm ts => Settings -> IO () diff --git a/src/Elm/Generic.hs b/src/Elm/Generic.hs index 5faacce..0e90233 100644 --- a/src/Elm/Generic.hs +++ b/src/Elm/Generic.hs @@ -30,11 +30,21 @@ module Elm.Generic , GenericConstructor (..) , toElmConstructor - -- * Internals + -- * Type families for compile-time checks , HasNoTypeVars + , TypeVarsError + , HasLessThanEightUnnamedFields + , FieldsError + , CheckFields + , Max + , HasNoNamedSum - , TypeVarsError + , NamedSumError + , CheckNamedSum + , CheckConst + + -- * Internals , stripTypeNamePrefix ) where @@ -141,9 +151,9 @@ instance Elm a => Elm (NonEmpty a) where this: @ -newtype Id a = Id { unId :: Text } +__newtype__ Id a = Id { unId :: Text } -instance Elm (Id a) where +__instance__ Elm (Id a) __where__ toElmDefinition _ = elmNewtype @Text "Id" "unId" @ -} diff --git a/src/Elm/Print.hs b/src/Elm/Print.hs index 562c165..eba9ba5 100644 --- a/src/Elm/Print.hs +++ b/src/Elm/Print.hs @@ -17,6 +17,10 @@ module Elm.Print , decodeChar , decodeEither , decodePair + + -- * Internal functions + , elmAliasDoc + , elmTypeDoc ) where import Data.List.NonEmpty (NonEmpty ((:|)), toList) @@ -36,7 +40,8 @@ import qualified Data.Text as T {- | Pretty shows Elm types. -TODO: more docs later +* See 'elmAliasDoc' for examples of generated @type alias@. +* See 'elmTypeDoc' for examples of generated @type@. -} prettyShowDefinition :: ElmDefinition -> Text prettyShowDefinition = showDoc . elmDoc