packages feed

azure-functions-worker-0.0.0.0: src/Azure/Functions/Commands/Init.hs

{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE OverloadedStrings #-}
module Azure.Functions.Commands.Init
where

import qualified Azure.Functions.Internal.Templates as Tpl
import           Azure.Functions.Registry           (RegisteredFunction (..), Registry (..))
import           Control.Monad                      (forM_, unless)
import           Data.Aeson                         (Value (Null), object, (.=))
import qualified Data.Aeson                         as Aeson
import qualified Data.Map.Strict                    as Map
import           Data.Text                          (Text)
import qualified Data.Text                          as Text
import qualified Data.Text.IO                       as Text
import           GHC.Generics                       (Generic)
import           Options.Applicative
import           System.Directory                   as Dir
import           System.Environment                 (getExecutablePath)
import           System.FilePath                    (takeFileName, (<.>), (</>))

data Options = Options
  { scriptRoot     :: String
  , syncExtensions :: Bool
  } deriving (Generic)

optionsParser :: Parser Options
optionsParser = Options
  <$> strOption
        (  long "script-root"
        <> metavar "DIR"
        <> help "The script root directory to initialize the application in"
        )
  <*> switch
        (  long "sync-extensions"
        <> help "Synchronize the Azure Function binding extensions"
        )

initCommand :: Registry -> Parser (IO ())
initCommand registry = runInitCommand registry <$> optionsParser

runInitCommand :: Registry -> Options -> IO ()
runInitCommand registry opts = do
  funcRoot    <- Dir.getCurrentDirectory
  execPath    <- getExecutablePath
  projectRoot <- Dir.makeAbsolute (scriptRoot opts)

  let execFileName = takeFileName execPath

  let workerDir = projectRoot </> "workers" </> "haskell"
  let workerExecPath = workerDir </> execFileName

  createDirectoryIfMissing True workerDir

  Dir.copyFileWithMetadata "host.json" (projectRoot </> "host.json")
  Dir.copyFileWithMetadata "local.settings.json" (projectRoot </> "local.settings.json")

  Dir.copyFileWithMetadata execPath workerExecPath

  Tpl.writeFile (workerDir </> "worker.config.json") Tpl.workerConfigJson [("execPath", Text.pack workerExecPath)]

  forM_ (Map.toList (registeredFunctions registry)) (uncurry $ initRegisteredFunction projectRoot)

initRegisteredFunction :: FilePath -> Text -> RegisteredFunction -> IO ()
initRegisteredFunction path functionName function = do
  let functionPath = path </> (Text.unpack functionName)
  let jsonFile     = functionPath </> "function.json"
  let functionFile = functionPath </> (Text.unpack functionName) <.> "hs"

  createDirectoryIfMissing True functionPath

  Aeson.encodeFile jsonFile $
    object  [ "generatedBy" .= ("azure-functions-haskell-worker" :: Text)
            , "disabled" .= False
            , "bindings" .= filter (/= Null)
                              [ registeredInBinding function
                              , registeredOutBinding function
                              ]
            ]

  Text.writeFile functionFile ""