Skip to content

Commit

Permalink
WIP - Frontend Component Gen
Browse files Browse the repository at this point in the history
  • Loading branch information
ErasedSoul committed Aug 12, 2024
1 parent b7eedfa commit 0860a9e
Show file tree
Hide file tree
Showing 15 changed files with 589 additions and 8 deletions.
8 changes: 8 additions & 0 deletions lib/namma-dsl/namma-dsl.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ library
NammaDSL.App
NammaDSL.Config
NammaDSL.DSL.Parser.API
NammaDSL.DSL.Parser.Frontend.Purs
NammaDSL.DSL.Parser.Storage
NammaDSL.DSL.Parser.TechDesign
NammaDSL.DSL.Syntax.API
NammaDSL.DSL.Syntax.Common
NammaDSL.DSL.Syntax.Frontend.Purs
NammaDSL.DSL.Syntax.Storage
NammaDSL.DSL.Syntax.TechDesign
NammaDSL.Generator.Haskell
Expand All @@ -49,6 +51,8 @@ library
NammaDSL.Generator.Haskell.Servant
NammaDSL.Generator.Purs
NammaDSL.Generator.Purs.API
NammaDSL.Generator.Purs.Common
NammaDSL.Generator.Purs.Component
NammaDSL.Generator.Purs.CST
NammaDSL.Generator.Purs.TechDesign
NammaDSL.Generator.SQL
Expand Down Expand Up @@ -152,10 +156,12 @@ test-suite namma-dsl-tests
NammaDSL.App
NammaDSL.Config
NammaDSL.DSL.Parser.API
NammaDSL.DSL.Parser.Frontend.Purs
NammaDSL.DSL.Parser.Storage
NammaDSL.DSL.Parser.TechDesign
NammaDSL.DSL.Syntax.API
NammaDSL.DSL.Syntax.Common
NammaDSL.DSL.Syntax.Frontend.Purs
NammaDSL.DSL.Syntax.Storage
NammaDSL.DSL.Syntax.TechDesign
NammaDSL.Generator.Haskell
Expand All @@ -171,6 +177,8 @@ test-suite namma-dsl-tests
NammaDSL.Generator.Haskell.Servant
NammaDSL.Generator.Purs
NammaDSL.Generator.Purs.API
NammaDSL.Generator.Purs.Common
NammaDSL.Generator.Purs.Component
NammaDSL.Generator.Purs.CST
NammaDSL.Generator.Purs.TechDesign
NammaDSL.Generator.SQL
Expand Down
4 changes: 4 additions & 0 deletions lib/namma-dsl/src/NammaDSL/AccessorTH.hs
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,9 @@ $( makeAccKeysTH
extImports
moduleMapper
tdComments
modelType
defaults
defaultType
viewConfigType
|]
)
39 changes: 38 additions & 1 deletion lib/namma-dsl/src/NammaDSL/App.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,19 @@ import Dhall (inputFile)
import Dhall.Marshal.Decode (auto)
import NammaDSL.Config
import NammaDSL.DSL.Parser.API
import NammaDSL.DSL.Parser.Frontend.Purs
import NammaDSL.DSL.Parser.Storage
import NammaDSL.DSL.Parser.TechDesign (techDesignParser)
import NammaDSL.DSL.Syntax.API
import NammaDSL.DSL.Syntax.Common as ReExport
import NammaDSL.DSL.Syntax.Frontend.Purs
import NammaDSL.DSL.Syntax.Storage
import NammaDSL.DSL.Syntax.TechDesign (TechDRead (..))
import NammaDSL.Generator.Haskell
import NammaDSL.Generator.Haskell.ApiTypes
import NammaDSL.Generator.Purs
import NammaDSL.Generator.Purs.TechDesign (applyTechDesignChanges)
import NammaDSL.Generator.Purs.Component
import NammaDSL.Generator.Purs.TechDesign (applyChange, applyTechDesignChanges)
import NammaDSL.Generator.SQL
import NammaDSL.Utils
import System.Directory
Expand Down Expand Up @@ -99,6 +102,40 @@ runTechDesign configPath yamlPath = do
tDChanges <- techDesignParser techDesignRead yamlPath
applyTechDesignChanges tDChanges

runFrontendGenerator :: FilePath -> FilePath -> IO ()
runFrontendGenerator configPath _yamlPath = do
config <- (inputFile auto configPath) :: IO FrontendConfig
let frontendPursRead =
FrontendPursRead
{ _fPursDefaultImportMapper = config ^. fDefaultImportMapper,
_fPursYamlObject = mempty,
_fPursDefaultImports = config ^. fDefaultImports,
_fPursComponentModulePrefix = config ^. fComponentModulePrefix,
_fPursScreenModulePrefix = config ^. fScreenModulePrefix
}
pursFrontendDef <- frontendPursParser frontendPursRead _yamlPath
let when' = \(t, f) -> when (elem t (config ^. fGenerate)) $ f config pursFrontendDef frontendPursRead
mapM_
when'
[ (PURE_SCRIPT_FRONTEND_COMPONENT, mkPursComponent),
(PURE_SCRIPT_FRONTEND_SCREEN, mkPursScreen)
]

mkPursComponent :: FrontendConfig -> PursFrontend -> FrontendPursRead -> IO ()
mkPursComponent config pursfrontend pursRead = do
let allComponentCode = generateAllComponents pursRead config (pursfrontend ^. components)
mapM_
( \(ComponentGenCode {..}) -> do
writeToFileIfNotExists componentGenPath (componentGenName <> ".purs") (show reExportModule)
writeToFileIfNotExists componentGenPath ("Controller.purs") (show controllerBaseCode)
writeToFileIfNotExists componentGenPath ("View.purs") (show viewCode)
mapM_ applyChange controllerExtraChanges
)
allComponentCode

mkPursScreen :: FrontendConfig -> PursFrontend -> FrontendPursRead -> IO ()
mkPursScreen = error "TODO" -- sai moonohar

getHashObjectAtHEAD :: FilePath -> IO (Maybe String)
getHashObjectAtHEAD filePath = do
let gitCommand = "git ls-tree -r HEAD " ++ filePath
Expand Down
14 changes: 14 additions & 0 deletions lib/namma-dsl/src/NammaDSL/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ data GenerationType
| DOMAIN_TYPE
| SQL
| PURE_SCRIPT_FRONTEND
| PURE_SCRIPT_FRONTEND_COMPONENT
| PURE_SCRIPT_FRONTEND_SCREEN
deriving (Generic, Show, Eq, FromDhall)

data InputPath = InputPath
Expand Down Expand Up @@ -103,3 +105,15 @@ data TechDesignConfig = TechDesignConfig
deriving (Generic, Show, FromDhall)

$(makeLenses ''TechDesignConfig)

data FrontendConfig = FrontendConfig
{ _fGenRootPath :: FilePath,
_fComponentModulePrefix :: String,
_fScreenModulePrefix :: String,
_fDefaultImportMapper :: [(String, String)],
_fDefaultImports :: [String],
_fGenerate :: [GenerationType]
}
deriving (Generic, Show, FromDhall)

$(makeLenses ''FrontendConfig)
124 changes: 124 additions & 0 deletions lib/namma-dsl/src/NammaDSL/DSL/Parser/Frontend/Purs.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS_GHC -Wno-unused-imports #-}
{-# OPTIONS_GHC -Wno-unused-local-binds #-}
{-# OPTIONS_GHC -Wno-unused-top-binds #-}

module NammaDSL.DSL.Parser.Frontend.Purs where

import Control.Lens.Combinators
import Control.Lens.Operators
import Control.Monad.Trans.RWS.Lazy
import Data.Aeson
import Data.Aeson.Lens (key, _Array, _Object, _String, _Value)
import Data.Bifunctor
import qualified Data.ByteString as BS
import Data.Default
import Data.List (find)
import qualified Data.List.Extra as L
import Data.Maybe
import qualified Data.Text as T
import qualified Data.Yaml as Yaml
import NammaDSL.AccessorTH
import NammaDSL.DSL.Parser.TechDesign (etImp, getRequiredDeclType)
import NammaDSL.DSL.Syntax.Common
import NammaDSL.DSL.Syntax.Frontend.Purs
import NammaDSL.DSL.Syntax.TechDesign
import NammaDSL.Utils (makeTypeQualified, mkList, toModelList)
import Prelude

frontendPursParser :: FrontendPursRead -> FilePath -> IO PursFrontend
frontendPursParser frontendPursRead filepath = do
contents <- BS.readFile filepath
case Yaml.decodeEither' contents of
Left _ -> error "Not a Valid Yaml"
Right yml -> do
evalParser parsePursFrontend (frontendPursRead {_fPursYamlObject = yml}) def

parsePursFrontend :: FrontendPursM ()
parsePursFrontend = do
parseModelList
makeComponentsQualified

parseModelList :: FrontendPursM ()
parseModelList = do
yaml <- asks _fPursYamlObject
let modelList = filter ((/= "imports") . fst) $ toModelList yaml
mapM_
( \(modelName, model) -> do
let modelType = fromMaybe (error $ "Model type required for purs model " <> modelName) (model ^? ix acc_modelType . _String)
case modelType of
"Component" -> parseComponent modelName model
"Screen" -> parseScreen modelName model
_ -> error $ "Invalid model type for purs model " <> modelName
)
modelList

parseComponent :: String -> Object -> FrontendPursM ()
parseComponent _compName _obj = do
let typeList = fromMaybe [] $ _obj ^? ix acc_types . _Value . to mkList
mkTypeList =
map
( \(typeName, typeObj) ->
let fields = mkList typeObj
declType = maybe PTYPE (getRequiredDeclType . T.pack . snd) $ find (("declType" ==) . fst) fields
actualFields = filter (("declType" /=) . fst) fields
in PursType typeName declType (map (\(fieldName, fieldType) -> PursField fieldName fieldType) actualFields)
)
typeList
defaultList = fromMaybe [] $ _obj ^? ix acc_defaults . _Value . to mkList
mkDefaultList =
map
( \(defaultName, defaultObj) ->
let fields = mkList defaultObj
defaultType = maybe PTYPE (getRequiredDeclType . T.pack . snd) $ find (("defaultType" ==) . fst) fields
actualFields = filter (("defaultType" /=) . fst) fields
in PursDefaultObj defaultName defaultType (map (\(fieldName, fieldType) -> PursField fieldName fieldType) actualFields)
)
defaultList
viewConfigType' = _obj ^? ix acc_viewConfigType . _String . to T.unpack
pCom = Component _compName mkTypeList mkDefaultList [] viewConfigType'
modify $ \s -> s {_components = _components s ++ [pCom]}

makeComponentsQualified :: FrontendPursM ()
makeComponentsQualified = do
defaultTypeImportMapper <- asks _fPursDefaultImportMapper
yaml <- asks _fPursYamlObject
pf <- get
let dNames = (pf ^. components) & map _componentName
qType = makeTypeQualified defaultTypeImportMapper Nothing Nothing (Just dNames) mempty yaml
qualifiedComponents =
map
( \comp ->
let types = comp ^. componentTypes
qualifiedTypes =
map
( \tp ->
let fields = tp ^. ptypeFields
qualifiedFields =
map
( \field ->
let fieldType = field ^. pfieldType
in field & pfieldType .~ qType fieldType
)
fields
in tp & ptypeFields .~ qualifiedFields
)
types
in comp & componentTypes .~ qualifiedTypes
)
(pf ^. components)
modify $ \s -> s {_components = figureComponentImports <$> qualifiedComponents}

figureComponentImports :: Component -> Component
figureComponentImports comp = do
let potentialImportStrings = map _pfieldType $ (comp ^. componentTypes & concatMap _ptypeFields) <> (comp ^. componentDefauts & concatMap _pdefaultFieldsValue)
figuredImports = etImp potentialImportStrings
comp & componentImports .~ (L.nub figuredImports)

parseScreen :: String -> Object -> FrontendPursM ()
parseScreen _screenName _obj = pure () -- TODO
6 changes: 0 additions & 6 deletions lib/namma-dsl/src/NammaDSL/DSL/Parser/Storage.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1190,12 +1190,6 @@ getProperConstraint txt = case L.trim txt of
"!SecondaryKey" -> Forced SecondaryKey
_ -> error "No a proper contraint type"

toModelList :: Object -> [(String, Object)]
toModelList obj =
KM.toList obj >>= \(k, v) -> case v of
Object o -> [(toString k, o)]
_ -> []

mkListObject :: Value -> [(String, Object)]
mkListObject (Object obj) =
KM.toList obj >>= \(k, v) -> case v of
Expand Down
78 changes: 78 additions & 0 deletions lib/namma-dsl/src/NammaDSL/DSL/Syntax/Frontend/Purs.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
{-# LANGUAGE TemplateHaskell #-}

module NammaDSL.DSL.Syntax.Frontend.Purs where

import Control.Lens
import Data.Aeson
import Data.Default
import NammaDSL.DSL.Syntax.Common
import NammaDSL.DSL.Syntax.TechDesign
import Prelude

data Screen = Screen
{
} -- TODO

$(makeLenses ''Screen)

data PursField = PursField
{ _pfieldName :: String,
_pfieldType :: String
}

$(makeLenses ''PursField)

data PursDefaultObj = PursDefaultObj
{ _pdefaultObjName :: String,
_pdefaultObjType :: PRecordType,
_pdefaultFieldsValue :: [PursField]
}

$(makeLenses ''PursDefaultObj)

data PursType = PursType
{ _ptypeName :: String,
_ptypeOf :: PRecordType,
_ptypeFields :: [PursField]
}

$(makeLenses ''PursType)

data Component = Component
{ _componentName :: String,
_componentTypes :: [PursType],
_componentDefauts :: [PursDefaultObj],
_componentImports :: [String],
_viewConfigType :: Maybe String
}

$(makeLenses ''Component)

instance Default Component where
def = Component mempty [] [] [] Nothing

data PursFrontend = PursFrontend
{ _extraFileChanges :: [Ann Change],
_components :: [Component],
_screens :: [Screen]
}

$(makeLenses ''PursFrontend)

data FrontendPursRead = FrontendPursRead
{ _fPursDefaultImportMapper :: [(String, String)],
_fPursDefaultImports :: [String],
_fPursYamlObject :: Object,
_fPursComponentModulePrefix :: String,
_fPursScreenModulePrefix :: String
}

$(makeLenses ''FrontendPursRead)

instance Default FrontendPursRead where
def = FrontendPursRead [] [] mempty mempty mempty

type FrontendPursM = ParserM FrontendPursRead PursFrontend

instance Default PursFrontend where
def = PursFrontend [] [] []
Loading

0 comments on commit 0860a9e

Please sign in to comment.