From d3c7ccebe16434034bf8674cddc4724b57417534 Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Sat, 10 Sep 2011 23:21:35 -0400 Subject: [PATCH 001/189] Provide sane defaults with less scaffolding Yesod.Settings provides the typical definitions for AppConfig, AppEnvironment, and loadConfig (read from YAML). Yesod.Main provides a single defaultMain function which accepts your usual withSiteArg function and runs via Warp calling the now provided loadConfig to figure out what to do. Note: Yesod re-exports Y.Settings and Y.Main -- This is probably not the right thing to do since it would cause collisions with users not using the provided functionality (including all existing users). --- yesod-core/Yesod/Main.hs | 51 ++++++++++++++++++++++++++++++++++++ yesod-core/Yesod/Settings.hs | 42 +++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 yesod-core/Yesod/Main.hs create mode 100644 yesod-core/Yesod/Settings.hs diff --git a/yesod-core/Yesod/Main.hs b/yesod-core/Yesod/Main.hs new file mode 100644 index 00000000..fda8f99a --- /dev/null +++ b/yesod-core/Yesod/Main.hs @@ -0,0 +1,51 @@ +{-# LANGUAGE CPP, DeriveDataTypeable #-} +module Yesod.Main (defaultMain) where + +import Yesod.Logger (Logger, makeLogger) +import Yesod.Settings (AppEnvironment(..), AppConfig(..), loadConfig) +import Network.Wai (Application) +import Network.Wai.Handler.Warp (run) +import System.Console.CmdArgs hiding (args) +import Data.Char (toUpper, toLower) + +defaultMain :: (AppConfig -> Logger -> (Application -> IO ()) -> IO ()) -> IO () +defaultMain withSite = do + logger <- makeLogger + args <- cmdArgs argConfig + env <- getAppEnv args + config <- loadConfig env + + let c = if port args /= 0 + then config { appPort = port args } + else config + + withSite c logger $ run (appPort c) + +data ArgConfig = ArgConfig + { environment :: String + , port :: Int + } deriving (Show, Data, Typeable) + +argConfig :: ArgConfig +argConfig = ArgConfig + { environment = def + &= help ("application environment, one of: " ++ (foldl1 (\a b -> a ++ ", " ++ b) environments)) + &= typ "ENVIRONMENT" + , port = def + &= help "the port to listen on" + &= typ "PORT" + } + +getAppEnv :: ArgConfig -> IO AppEnvironment +getAppEnv cfg = do + let e = if environment cfg /= "" + then environment cfg + else "development" + return $ read $ capitalize e + + where + capitalize [] = [] + capitalize (x:xs) = toUpper x : map toLower xs + +environments :: [String] +environments = map ((map toLower) . show) ([minBound..maxBound] :: [AppEnvironment]) diff --git a/yesod-core/Yesod/Settings.hs b/yesod-core/Yesod/Settings.hs new file mode 100644 index 00000000..840264ca --- /dev/null +++ b/yesod-core/Yesod/Settings.hs @@ -0,0 +1,42 @@ +module Yesod.Settings where + +import Control.Monad (join) +import Data.Object +import Data.Text (Text) + +import qualified Data.Object.Yaml as YAML +import qualified Data.Text as T + +data AppEnvironment = Development + | Test + | Staging + | Production + deriving (Eq, Show, Read, Enum, Bounded) + +data AppConfig = AppConfig + { appEnv :: AppEnvironment + , appPort :: Int + , connectionPoolSize :: Int + , appRoot :: Text + } deriving (Show) + +loadConfig :: AppEnvironment -> IO AppConfig +loadConfig env = do + allSettings <- (join $ YAML.decodeFile ("config/settings.yml" :: String)) >>= fromMapping + settings <- lookupMapping (show env) allSettings + hostS <- lookupScalar "host" settings + port <- fmap read $ lookupScalar "port" settings + connectionPoolSizeS <- lookupScalar "connectionPoolSize" settings + + return $ AppConfig + { appEnv = env + , appPort = port + , appRoot = T.pack $ hostS ++ addPort port + , connectionPoolSize = read connectionPoolSizeS + } + + where + addPort :: Int -> String + addPort p = case env of + Production -> "" + _ -> ":" ++ show p From b5a3bd4671edbde2375eb902879f3f85a07eec7b Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Sat, 10 Sep 2011 23:32:41 -0400 Subject: [PATCH 002/189] Add dependencies and expose new modules --- yesod-core/yesod-core.cabal | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/yesod-core/yesod-core.cabal b/yesod-core/yesod-core.cabal index f33a1f88..9fa70f24 100644 --- a/yesod-core/yesod-core.cabal +++ b/yesod-core/yesod-core.cabal @@ -54,6 +54,10 @@ library , case-insensitive >= 0.2 && < 0.4 , parsec >= 2 && < 3.2 , directory >= 1 && < 1.2 + , cmdargs >= 0.8 && < 0.9 + , data-object >= 0.3 && < 0.4 + , data-object-yaml >= 0.3 && < 0.4 + , warp >= 0.4 && < 0.5 -- for logger. Probably logger should be a separate package , strict-concurrency >= 0.2.4 && < 0.2.5 @@ -65,6 +69,8 @@ library Yesod.Request Yesod.Widget Yesod.Message + Yesod.Settings + Yesod.Main other-modules: Yesod.Internal Yesod.Internal.Core Yesod.Internal.Session From 63d34a3bb46f612a8285cc0fbd954f19ed05f0c4 Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Sat, 10 Sep 2011 23:33:17 -0400 Subject: [PATCH 003/189] Update scaffold for defaultMain --- yesod/Scaffolding/Scaffolder.hs | 4 +- yesod/scaffold/Application.hs.cg | 2 +- yesod/scaffold/Foundation.hs.cg | 4 +- yesod/scaffold/Settings.hs.cg | 66 +------------------------- yesod/scaffold/main.hs.cg | 67 +-------------------------- yesod/scaffold/tiny/Application.hs.cg | 3 +- yesod/scaffold/tiny/Foundation.hs.cg | 5 +- yesod/scaffold/tiny/Settings.hs.cg | 52 +-------------------- 8 files changed, 14 insertions(+), 189 deletions(-) diff --git a/yesod/Scaffolding/Scaffolder.hs b/yesod/Scaffolding/Scaffolder.hs index 287bb8a9..c8fe885d 100644 --- a/yesod/Scaffolding/Scaffolder.hs +++ b/yesod/Scaffolding/Scaffolder.hs @@ -95,8 +95,8 @@ scaffold = do Tiny -> "" settingsTextImport = case backend of - Postgresql -> "import Data.Text (Text, pack, concat)\nimport Prelude hiding (concat)" - _ -> "import Data.Text (Text, pack)" + Postgresql -> "import Data.Text (Text, concat)\nimport Prelude hiding (concat)" + _ -> "import Data.Text (Text)" packages = if backend == MongoDB diff --git a/yesod/scaffold/Application.hs.cg b/yesod/scaffold/Application.hs.cg index 03153b5a..8688fe02 100644 --- a/yesod/scaffold/Application.hs.cg +++ b/yesod/scaffold/Application.hs.cg @@ -68,7 +68,7 @@ withDevelAppPort = where go :: ((Int, Application) -> IO ()) -> IO () go f = do - conf <- Settings.loadConfig Settings.Development + conf <- loadConfig Development let port = appPort conf logger <- makeLogger logString logger $ "Devel application launched, listening on port " ++ show port diff --git a/yesod/scaffold/Foundation.hs.cg b/yesod/scaffold/Foundation.hs.cg index 3f000eb5..a925401f 100644 --- a/yesod/scaffold/Foundation.hs.cg +++ b/yesod/scaffold/Foundation.hs.cg @@ -45,7 +45,7 @@ import Text.Shakespeare.Text (stext) -- starts running, such as database connections. Every handler will have -- access to the data present here. data ~sitearg~ = ~sitearg~ - { settings :: Settings.AppConfig + { settings :: AppConfig , getLogger :: Logger , getStatic :: Static -- ^ Settings for static file serving. , connPool :: Settings.ConnectionPool -- ^ Database connection pool. @@ -75,7 +75,7 @@ mkYesodData "~sitearg~" $(parseRoutesFile "config/routes") -- Please see the documentation for the Yesod typeclass. There are a number -- of settings which can be configured by overriding methods here. instance Yesod ~sitearg~ where - approot = Settings.appRoot . settings + approot = appRoot . settings -- Place the session key file in the config folder encryptKey _ = fmap Just $ getKey "config/client_session_key.aes" diff --git a/yesod/scaffold/Settings.hs.cg b/yesod/scaffold/Settings.hs.cg index 9109198e..fdcf3c59 100644 --- a/yesod/scaffold/Settings.hs.cg +++ b/yesod/scaffold/Settings.hs.cg @@ -18,9 +18,6 @@ module Settings , runConnectionPool , staticRoot , staticDir - , loadConfig - , AppEnvironment(..) - , AppConfig(..) ) where import qualified Text.Hamlet as S @@ -32,6 +29,7 @@ import Text.Shakespeare.Text (st) import Language.Haskell.TH.Syntax import Database.Persist.~importPersist~ import Yesod (liftIO, MonadControlIO, addWidget, addCassius, addJulius, addLucius, whamletFile) +import Yesod.Settings import Data.Monoid (mempty) import System.Directory (doesFileExist) ~settingsTextImport~ @@ -39,68 +37,6 @@ import Data.Object import qualified Data.Object.Yaml as YAML import Control.Monad (join) -data AppEnvironment = Test - | Development - | Staging - | Production - deriving (Eq, Show, Read, Enum, Bounded) - --- | Dynamic per-environment configuration loaded from the YAML file Settings.yaml. --- Use dynamic settings to avoid the need to re-compile the application (between staging and production environments). --- --- By convention these settings should be overwritten by any command line arguments. --- See config/Foundation.hs for command line arguments --- Command line arguments provide some convenience but are also required for hosting situations where a setting is read from the environment (appPort on Heroku). --- -data AppConfig = AppConfig { - appEnv :: AppEnvironment - - , appPort :: Int - - -- | Your application will keep a connection pool and take connections from - -- there as necessary instead of continually creating new connections. This - -- value gives the maximum number of connections to be open at a given time. - -- If your application requests a connection when all connections are in - -- use, that request will fail. Try to choose a number that will work well - -- with the system resources available to you while providing enough - -- connections for your expected load. - -- - -- Connections are returned to the pool as quickly as possible by - -- Yesod to avoid resource exhaustion. A connection is only considered in - -- use while within a call to runDB. - , connectionPoolSize :: Int - - -- | The base URL for your application. This will usually be different for - -- development and production. Yesod automatically constructs URLs for you, - -- so this value must be accurate to create valid links. - -- Please note that there is no trailing slash. - -- - -- You probably want to change this! If your domain name was "yesod.com", - -- you would probably want it to be: - -- > "http://yesod.com" - , appRoot :: Text -} deriving (Show) - -loadConfig :: AppEnvironment -> IO AppConfig -loadConfig env = do - allSettings <- (join $ YAML.decodeFile ("config/settings.yml" :: String)) >>= fromMapping - settings <- lookupMapping (show env) allSettings - hostS <- lookupScalar "host" settings - port <- fmap read $ lookupScalar "port" settings - connectionPoolSizeS <- lookupScalar "connectionPoolSize" settings - return $ AppConfig { - appEnv = env - , appPort = port - , appRoot = pack $ hostS ++ addPort port - , connectionPoolSize = read connectionPoolSizeS - } - where - addPort :: Int -> String -#ifdef PRODUCTION - addPort _ = "" -#else - addPort p = ":" ++ (show p) -#endif -- Static setting below. Changing these requires a recompile diff --git a/yesod/scaffold/main.hs.cg b/yesod/scaffold/main.hs.cg index eede5e55..1e7f88ac 100644 --- a/yesod/scaffold/main.hs.cg +++ b/yesod/scaffold/main.hs.cg @@ -1,68 +1,5 @@ -{-# LANGUAGE CPP, DeriveDataTypeable #-} -import Settings (AppEnvironment(..), AppConfig(..), loadConfig) +import Yesod.Main (defaultMain) import Application (with~sitearg~) -import Network.Wai.Handler.Warp (run) -import System.Console.CmdArgs hiding (args) -import Data.Char (toUpper, toLower) - -#ifndef PRODUCTION -import Network.Wai.Middleware.Debug (debugHandle) -import Yesod.Logger (logString, logLazyText, flushLogger, makeLogger) -#else -import Yesod.Logger (makeLogger) -#endif main :: IO () -main = do - logger <- makeLogger - args <- cmdArgs argConfig - env <- getAppEnv args - config <- loadConfig env - let c = if port args /= 0 - then config { appPort = port args } - else config - -#if PRODUCTION - with~sitearg~ c logger $ run (appPort c) -#else - logString logger $ (show env) ++ " application launched, listening on port " ++ show (appPort c) - with~sitearg~ c logger $ run (appPort c) . debugHandle (logHandle logger) - flushLogger logger - - where - logHandle logger msg = logLazyText logger msg >> flushLogger logger -#endif - -data ArgConfig = ArgConfig - { environment :: String - , port :: Int - } deriving (Show, Data, Typeable) - -argConfig :: ArgConfig -argConfig = ArgConfig - { environment = def - &= help ("application environment, one of: " ++ (foldl1 (\a b -> a ++ ", " ++ b) environments)) - &= typ "ENVIRONMENT" - , port = def - &= typ "PORT" - } - -environments :: [String] -environments = map ((map toLower) . show) ([minBound..maxBound] :: [AppEnvironment]) - --- | retrieve the -e environment option -getAppEnv :: ArgConfig -> IO AppEnvironment -getAppEnv cfg = do - let e = if environment cfg /= "" - then environment cfg - else -#if PRODUCTION - "production" -#else - "development" -#endif - return $ read $ capitalize e - - where - capitalize [] = [] - capitalize (x:xs) = toUpper x : map toLower xs +main = defaultMain with~sitearg~ diff --git a/yesod/scaffold/tiny/Application.hs.cg b/yesod/scaffold/tiny/Application.hs.cg index 99e4d7f9..e4e2aaef 100644 --- a/yesod/scaffold/tiny/Application.hs.cg +++ b/yesod/scaffold/tiny/Application.hs.cg @@ -11,6 +11,7 @@ module Application import Foundation import Settings import Yesod.Static +import Yesod.Settings import Yesod.Logger (makeLogger, flushLogger, Logger, logLazyText, logString) import Data.ByteString (ByteString) import Network.Wai (Application) @@ -54,7 +55,7 @@ withDevelAppPort = where go :: ((Int, Application) -> IO ()) -> IO () go f = do - conf <- Settings.loadConfig Settings.Development + conf <- loadConfig Development let port = appPort conf logger <- makeLogger logString logger $ "Devel application launched, listening on port " ++ show port diff --git a/yesod/scaffold/tiny/Foundation.hs.cg b/yesod/scaffold/tiny/Foundation.hs.cg index 72993157..5e950805 100644 --- a/yesod/scaffold/tiny/Foundation.hs.cg +++ b/yesod/scaffold/tiny/Foundation.hs.cg @@ -14,6 +14,7 @@ module Foundation ) where import Yesod.Core +import Yesod.Settings (AppConfig(..)) import Yesod.Static (Static, base64md5, StaticRoute(..)) import Settings.StaticFiles import Yesod.Logger (Logger, logLazyText) @@ -32,7 +33,7 @@ import Web.ClientSession (getKey) -- starts running, such as database connections. Every handler will have -- access to the data present here. data ~sitearg~ = ~sitearg~ - { settings :: Settings.AppConfig + { settings :: AppConfig , getLogger :: Logger , getStatic :: Static -- ^ Settings for static file serving. } @@ -61,7 +62,7 @@ mkYesodData "~sitearg~" $(parseRoutesFile "config/routes") -- Please see the documentation for the Yesod typeclass. There are a number -- of settings which can be configured by overriding methods here. instance Yesod ~sitearg~ where - approot = Settings.appRoot . settings + approot = appRoot . settings -- Place the session key file in the config folder encryptKey _ = fmap Just $ getKey "config/client_session_key.aes" diff --git a/yesod/scaffold/tiny/Settings.hs.cg b/yesod/scaffold/tiny/Settings.hs.cg index bec5d248..73e226ad 100644 --- a/yesod/scaffold/tiny/Settings.hs.cg +++ b/yesod/scaffold/tiny/Settings.hs.cg @@ -14,9 +14,6 @@ module Settings , widgetFile , staticRoot , staticDir - , loadConfig - , AppEnvironment(..) - , AppConfig(..) ) where import qualified Text.Hamlet as S @@ -27,6 +24,7 @@ import qualified Text.Shakespeare.Text as S import Text.Shakespeare.Text (st) import Language.Haskell.TH.Syntax import Yesod.Widget (addWidget, addCassius, addJulius, addLucius, whamletFile) +import Yesod.Settings import Data.Monoid (mempty) import System.Directory (doesFileExist) ~settingsTextImport~ @@ -34,54 +32,6 @@ import Data.Object import qualified Data.Object.Yaml as YAML import Control.Monad (join) -data AppEnvironment = Test - | Development - | Staging - | Production - deriving (Eq, Show, Read, Enum, Bounded) - --- | Dynamic per-environment configuration loaded from the YAML file Settings.yaml. --- Use dynamic settings to avoid the need to re-compile the application (between staging and production environments). --- --- By convention these settings should be overwritten by any command line arguments. --- See config/~sitearg~.hs for command line arguments --- Command line arguments provide some convenience but are also required for hosting situations where a setting is read from the environment (appPort on Heroku). --- -data AppConfig = AppConfig { - appEnv :: AppEnvironment - - , appPort :: Int - - -- | The base URL for your application. This will usually be different for - -- development and production. Yesod automatically constructs URLs for you, - -- so this value must be accurate to create valid links. - -- Please note that there is no trailing slash. - -- - -- You probably want to change this! If your domain name was "yesod.com", - -- you would probably want it to be: - -- > "http://yesod.com" - , appRoot :: Text -} deriving (Show) - -loadConfig :: AppEnvironment -> IO AppConfig -loadConfig env = do - allSettings <- (join $ YAML.decodeFile ("config/settings.yml" :: String)) >>= fromMapping - settings <- lookupMapping (show env) allSettings - hostS <- lookupScalar "host" settings - port <- fmap read $ lookupScalar "port" settings - return $ AppConfig { - appEnv = env - , appPort = port - , appRoot = pack $ hostS ++ addPort port - } - where - addPort :: Int -> String -#ifdef PRODUCTION - addPort _ = "" -#else - addPort p = ":" ++ (show p) -#endif - -- | The location of static files on your system. This is a file system -- path. The default value works properly with your scaffolded site. staticDir :: FilePath From 4654776fa42fdfebba758f95114858809c3ee652 Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Sat, 10 Sep 2011 23:33:31 -0400 Subject: [PATCH 004/189] Re-export new modules --- yesod/Yesod.hs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/yesod/Yesod.hs b/yesod/Yesod.hs index 7724a345..6fc6ee98 100644 --- a/yesod/Yesod.hs +++ b/yesod/Yesod.hs @@ -7,6 +7,8 @@ module Yesod , module Yesod.Form , module Yesod.Json , module Yesod.Persist + , module Yesod.Settings + , module Yesod.Main -- * Running your application , warp , warpDebug @@ -46,6 +48,8 @@ import Text.Julius import Yesod.Form import Yesod.Json import Yesod.Persist +import Yesod.Settings +import Yesod.Main import Network.Wai (Application) import Network.Wai.Middleware.Debug import Control.Monad.Trans.Class (lift) From 86c8abb853fd25f65143ade8f49816e05a777484 Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Sun, 11 Sep 2011 00:16:43 -0400 Subject: [PATCH 005/189] Limit exports --- yesod-core/Yesod/Settings.hs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/yesod-core/Yesod/Settings.hs b/yesod-core/Yesod/Settings.hs index 840264ca..4d84e144 100644 --- a/yesod-core/Yesod/Settings.hs +++ b/yesod-core/Yesod/Settings.hs @@ -1,4 +1,8 @@ -module Yesod.Settings where +module Yesod.Settings + ( AppEnvironment(..) + , AppConfig(..) + , loadConfig + ) where import Control.Monad (join) import Data.Object From dcb27df1fc0ce6c58c9655818c42d51d67e51380 Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Sun, 11 Sep 2011 00:17:07 -0400 Subject: [PATCH 006/189] Be a little more configurable --- yesod-core/Yesod/Main.hs | 91 +++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 33 deletions(-) diff --git a/yesod-core/Yesod/Main.hs b/yesod-core/Yesod/Main.hs index fda8f99a..fab4ead0 100644 --- a/yesod-core/Yesod/Main.hs +++ b/yesod-core/Yesod/Main.hs @@ -1,5 +1,9 @@ -{-# LANGUAGE CPP, DeriveDataTypeable #-} -module Yesod.Main (defaultMain) where +{-# LANGUAGE DeriveDataTypeable #-} +module Yesod.Main + ( defaultMain + , fromArgs + , fromArgsWith + ) where import Yesod.Logger (Logger, makeLogger) import Yesod.Settings (AppEnvironment(..), AppConfig(..), loadConfig) @@ -8,44 +12,65 @@ import Network.Wai.Handler.Warp (run) import System.Console.CmdArgs hiding (args) import Data.Char (toUpper, toLower) -defaultMain :: (AppConfig -> Logger -> (Application -> IO ()) -> IO ()) -> IO () -defaultMain withSite = do - logger <- makeLogger - args <- cmdArgs argConfig - env <- getAppEnv args - config <- loadConfig env - - let c = if port args /= 0 - then config { appPort = port args } - else config - - withSite c logger $ run (appPort c) - data ArgConfig = ArgConfig { environment :: String , port :: Int } deriving (Show, Data, Typeable) -argConfig :: ArgConfig -argConfig = ArgConfig - { environment = def - &= help ("application environment, one of: " ++ (foldl1 (\a b -> a ++ ", " ++ b) environments)) - &= typ "ENVIRONMENT" - , port = def - &= help "the port to listen on" - &= typ "PORT" - } +-- | Load an @'AppConfig'@ using the provided function, then start your +-- app via Warp on the configured port. +-- +-- > -- main.hs +-- > import Application (withMySite) +-- > import Yesod.Main (defaultMain, fromArgs) +-- > +-- > main :: IO () +-- > main = defaultMain fromArgs withMySite +-- +defaultMain :: IO AppConfig -> (AppConfig -> Logger -> (Application -> IO ()) -> IO ()) -> IO () +defaultMain load withSite = do + config <- load + logger <- makeLogger + withSite config logger $ run (appPort config) -getAppEnv :: ArgConfig -> IO AppEnvironment -getAppEnv cfg = do - let e = if environment cfg /= "" - then environment cfg - else "development" - return $ read $ capitalize e +-- | Call the @'Yesod.Settings.loadConfig'@ function for the environment +-- passed on the commandline (or the default, \"development\") and +-- override the port if passed. +fromArgs :: IO AppConfig +fromArgs = fromArgsWith loadConfig + +-- | Same, but allows one to provide their own custom @'loadConfig'@ +fromArgsWith :: (AppEnvironment -> IO AppConfig) -> IO AppConfig +fromArgsWith load = do + args <- cmdArgs argConfig + + let env = read + $ capitalize + $ if environment args /= "" + then environment args + else "development" + + config <- load env + + let c = if port args /= 0 + then config { appPort = port args } + else config + + return $ config where + argConfig :: ArgConfig + argConfig = ArgConfig + { environment = def + &= help ("application environment, one of: " ++ (foldl1 (\a b -> a ++ ", " ++ b) environments)) + &= typ "ENVIRONMENT" + , port = def + &= help "the port to listen on" + &= typ "PORT" + } + + environments :: [String] + environments = map ((map toLower) . show) ([minBound..maxBound] :: [AppEnvironment]) + capitalize [] = [] capitalize (x:xs) = toUpper x : map toLower xs - -environments :: [String] -environments = map ((map toLower) . show) ([minBound..maxBound] :: [AppEnvironment]) From fed3f0c0fa72ea97e680c1918e227330f6bc3214 Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Sun, 11 Sep 2011 00:35:34 -0400 Subject: [PATCH 007/189] Fix logical error --- yesod-core/Yesod/Main.hs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/yesod-core/Yesod/Main.hs b/yesod-core/Yesod/Main.hs index fab4ead0..bba1fd3e 100644 --- a/yesod-core/Yesod/Main.hs +++ b/yesod-core/Yesod/Main.hs @@ -47,16 +47,14 @@ fromArgsWith load = do let env = read $ capitalize $ if environment args /= "" - then environment args - else "development" + then environment args + else "development" config <- load env - let c = if port args /= 0 - then config { appPort = port args } - else config - - return $ config + return $ if port args /= 0 + then config { appPort = port args } + else config where argConfig :: ArgConfig From 6360cb5e62535b3cf88f9e6c46c5995a9064df78 Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Sun, 11 Sep 2011 00:35:46 -0400 Subject: [PATCH 008/189] Update scaffold to use fromArgs --- yesod/scaffold/main.hs.cg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yesod/scaffold/main.hs.cg b/yesod/scaffold/main.hs.cg index 1e7f88ac..94f61c28 100644 --- a/yesod/scaffold/main.hs.cg +++ b/yesod/scaffold/main.hs.cg @@ -1,5 +1,5 @@ -import Yesod.Main (defaultMain) +import Yesod.Main (defaultMain, fromArgs) import Application (with~sitearg~) main :: IO () -main = defaultMain with~sitearg~ +main = defaultMain fromArgs with~sitearg~ From bd843a7acc629bc0cf592e9ab5fdae8861944070 Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Sun, 11 Sep 2011 12:30:22 -0400 Subject: [PATCH 009/189] Add typical connStr loading functions --- yesod-core/Yesod/Settings.hs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/yesod-core/Yesod/Settings.hs b/yesod-core/Yesod/Settings.hs index 4d84e144..f42862e9 100644 --- a/yesod-core/Yesod/Settings.hs +++ b/yesod-core/Yesod/Settings.hs @@ -1,12 +1,16 @@ +{-# LANGUAGE QuasiQuotes #-} module Yesod.Settings ( AppEnvironment(..) , AppConfig(..) , loadConfig + , loadPostgresqlConnStr + , loadSqliteConnStr ) where import Control.Monad (join) import Data.Object import Data.Text (Text) +import Text.Shakespeare.Text (st) import qualified Data.Object.Yaml as YAML import qualified Data.Text as T @@ -44,3 +48,22 @@ loadConfig env = do addPort p = case env of Production -> "" _ -> ":" ++ show p + +loadPostgresqlConnStr :: AppEnvironment -> IO Text +loadPostgresqlConnStr env = do + allSettings <- (join $ YAML.decodeFile ("config/postgesql.yml" :: String)) >>= fromMapping + settings <- lookupMapping (show env) allSettings + database <- lookupScalar "database" settings :: IO Text + + connPart <- fmap T.concat $ (flip mapM) ["user", "password", "host", "port"] $ \key -> do + value <- lookupScalar key settings + return $ [st| #{key}=#{value} |] + return $ [st|#{connPart} dbname=#{database}|] + +loadSqliteConnStr :: AppEnvironment -> IO Text +loadSqliteConnStr env = do + allSettings <- (join $ YAML.decodeFile ("config/sqlite.yml" :: String)) >>= fromMapping + settings <- lookupMapping (show env) allSettings + lookupScalar "database" settings + +-- TODO: Mongo From 80314a4027befb522e5922d78807a0e8e92a1b64 Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Sun, 11 Sep 2011 12:30:31 -0400 Subject: [PATCH 010/189] Add shakespeare-text dep --- yesod-core/yesod-core.cabal | 1 + 1 file changed, 1 insertion(+) diff --git a/yesod-core/yesod-core.cabal b/yesod-core/yesod-core.cabal index 6b33e2f5..ce7a8c0c 100644 --- a/yesod-core/yesod-core.cabal +++ b/yesod-core/yesod-core.cabal @@ -38,6 +38,7 @@ library , shakespeare >= 0.10 && < 0.11 , shakespeare-js >= 0.10 && < 0.11 , shakespeare-css >= 0.10 && < 0.11 + , shakespeare-text >= 0.10 && < 0.11 , blaze-builder >= 0.2.1 && < 0.4 , transformers >= 0.2 && < 0.3 , clientsession >= 0.7.2 && < 0.8 From 256245cd2b186305ea3f22f08511d9ae88b89709 Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Sun, 11 Sep 2011 13:06:53 -0400 Subject: [PATCH 011/189] Add mongo connection loader --- yesod-core/Yesod/Settings.hs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/yesod-core/Yesod/Settings.hs b/yesod-core/Yesod/Settings.hs index f42862e9..8e303972 100644 --- a/yesod-core/Yesod/Settings.hs +++ b/yesod-core/Yesod/Settings.hs @@ -1,10 +1,12 @@ -{-# LANGUAGE QuasiQuotes #-} +{-# OPTIONS -fno-warn-missing-signatures #-} +{-# LANGUAGE QuasiQuotes #-} module Yesod.Settings ( AppEnvironment(..) , AppConfig(..) , loadConfig , loadPostgresqlConnStr , loadSqliteConnStr + , loadMongoConnParams ) where import Control.Monad (join) @@ -63,7 +65,14 @@ loadPostgresqlConnStr env = do loadSqliteConnStr :: AppEnvironment -> IO Text loadSqliteConnStr env = do allSettings <- (join $ YAML.decodeFile ("config/sqlite.yml" :: String)) >>= fromMapping - settings <- lookupMapping (show env) allSettings + settings <- lookupMapping (show env) allSettings lookupScalar "database" settings --- TODO: Mongo +-- note: no type signature to avoid Persistent.MongoDB dep +--loadMongoConnParams :: AppEnvironment -> IO (Database, HostName) +loadMongoConnParams env = do + allSettings <- (join $ YAML.decodeFile ("config/mongoDB.yml" :: String)) >>= fromMapping + settings <- lookupMapping (show env) allSettings + database <- lookupScalar "database" settings + host <- lookupScalar "host" settings + return (database, host) From fa3fabcfbaadc8977dd888b4bd50e7da13e332a8 Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Sun, 11 Sep 2011 14:57:06 -0400 Subject: [PATCH 012/189] Update scaffolding with new load connection functions Yesod.Settings provides load functions which were previously scaffolded. They load the ConsStrs for SQL and ConnParams for Mongo. This prevents the need for a lot of the imports in the scaffolding settings and simplifies the existing Text import. --- yesod/Scaffolding/Scaffolder.hs | 4 ---- yesod/scaffold/Settings.hs.cg | 5 +---- yesod/scaffold/mongoDBConnPool.cg | 12 ++---------- yesod/scaffold/postgresqlConnPool.cg | 15 +-------------- yesod/scaffold/sqliteConnPool.cg | 10 +--------- yesod/scaffold/tiny/Settings.hs.cg | 5 +---- 6 files changed, 6 insertions(+), 45 deletions(-) diff --git a/yesod/Scaffolding/Scaffolder.hs b/yesod/Scaffolding/Scaffolder.hs index c8fe885d..293032b6 100644 --- a/yesod/Scaffolding/Scaffolder.hs +++ b/yesod/Scaffolding/Scaffolder.hs @@ -94,10 +94,6 @@ scaffold = do MongoDB -> $(codegen $ "mongoDBConnPool") Tiny -> "" - settingsTextImport = case backend of - Postgresql -> "import Data.Text (Text, concat)\nimport Prelude hiding (concat)" - _ -> "import Data.Text (Text)" - packages = if backend == MongoDB then " , persistent-mongoDB >= 0.6.1 && < 0.7\n , mongoDB >= 1.1\n , bson >= 0.1.5\n" diff --git a/yesod/scaffold/Settings.hs.cg b/yesod/scaffold/Settings.hs.cg index fdcf3c59..36bd1576 100644 --- a/yesod/scaffold/Settings.hs.cg +++ b/yesod/scaffold/Settings.hs.cg @@ -32,10 +32,7 @@ import Yesod (liftIO, MonadControlIO, addWidget, addCassius, addJulius, addLuciu import Yesod.Settings import Data.Monoid (mempty) import System.Directory (doesFileExist) -~settingsTextImport~ -import Data.Object -import qualified Data.Object.Yaml as YAML -import Control.Monad (join) +import Data.Text (Text) -- Static setting below. Changing these requires a recompile diff --git a/yesod/scaffold/mongoDBConnPool.cg b/yesod/scaffold/mongoDBConnPool.cg index 57cb2aa0..4292d22f 100644 --- a/yesod/scaffold/mongoDBConnPool.cg +++ b/yesod/scaffold/mongoDBConnPool.cg @@ -3,14 +3,6 @@ runConnectionPool = runMongoDBConn (ConfirmWrites [u"j" =: True]) withConnectionPool :: (MonadControlIO m, Applicative m) => AppConfig -> (ConnectionPool -> m b) -> m b withConnectionPool conf f = do - (database,host) <- liftIO $ loadConnParams (appEnv conf) + (database,host) <- liftIO $ loadMongoConnParams (appEnv conf) withMongoDBPool (u database) host (connectionPoolSize conf) f - where - -- | The database connection parameters. - -- loadConnParams :: AppEnvironment -> IO (Database, HostName) - loadConnParams env = do - allSettings <- (join $ YAML.decodeFile ("config/mongoDB.yml" :: String)) >>= fromMapping - settings <- lookupMapping (show env) allSettings - database <- lookupScalar "database" settings - host <- lookupScalar "host" settings - return (database, host) + diff --git a/yesod/scaffold/postgresqlConnPool.cg b/yesod/scaffold/postgresqlConnPool.cg index 9cf1129b..e8597e4f 100644 --- a/yesod/scaffold/postgresqlConnPool.cg +++ b/yesod/scaffold/postgresqlConnPool.cg @@ -3,21 +3,8 @@ runConnectionPool = runSqlPool withConnectionPool :: MonadControlIO m => AppConfig -> (ConnectionPool -> m a) -> m a withConnectionPool conf f = do - cs <- liftIO $ loadConnStr (appEnv conf) + cs <- liftIO $ load~upper~ConnStr (appEnv conf) with~upper~Pool cs (connectionPoolSize conf) f - where - -- | The database connection string. The meaning of this string is backend- - -- specific. - loadConnStr :: AppEnvironment -> IO Text - loadConnStr env = do - allSettings <- (join $ YAML.decodeFile ("config/~backendLower~.yml" :: String)) >>= fromMapping - settings <- lookupMapping (show env) allSettings - database <- lookupScalar "database" settings :: IO Text - - connPart <- fmap concat $ (flip mapM) ["user", "password", "host", "port"] $ \key -> do - value <- lookupScalar key settings - return $ [st| #{key}=#{value} |] - return $ [st|#{connPart} dbname=#{database}|] -- Example of making a dynamic configuration static -- use /return $(mkConnStr Production)/ instead of loadConnStr diff --git a/yesod/scaffold/sqliteConnPool.cg b/yesod/scaffold/sqliteConnPool.cg index ba4981f2..e8597e4f 100644 --- a/yesod/scaffold/sqliteConnPool.cg +++ b/yesod/scaffold/sqliteConnPool.cg @@ -3,16 +3,8 @@ runConnectionPool = runSqlPool withConnectionPool :: MonadControlIO m => AppConfig -> (ConnectionPool -> m a) -> m a withConnectionPool conf f = do - cs <- liftIO $ loadConnStr (appEnv conf) + cs <- liftIO $ load~upper~ConnStr (appEnv conf) with~upper~Pool cs (connectionPoolSize conf) f - where - -- | The database connection string. The meaning of this string is backend- - -- specific. - loadConnStr :: AppEnvironment -> IO Text - loadConnStr env = do - allSettings <- (join $ YAML.decodeFile ("config/~backendLower~.yml" :: String)) >>= fromMapping - settings <- lookupMapping (show env) allSettings - lookupScalar "database" settings -- Example of making a dynamic configuration static -- use /return $(mkConnStr Production)/ instead of loadConnStr diff --git a/yesod/scaffold/tiny/Settings.hs.cg b/yesod/scaffold/tiny/Settings.hs.cg index 73e226ad..a36c764b 100644 --- a/yesod/scaffold/tiny/Settings.hs.cg +++ b/yesod/scaffold/tiny/Settings.hs.cg @@ -27,10 +27,7 @@ import Yesod.Widget (addWidget, addCassius, addJulius, addLucius, whamletFile) import Yesod.Settings import Data.Monoid (mempty) import System.Directory (doesFileExist) -~settingsTextImport~ -import Data.Object -import qualified Data.Object.Yaml as YAML -import Control.Monad (join) +import Data.Text (Text) -- | The location of static files on your system. This is a file system -- path. The default value works properly with your scaffolded site. From a9ac0a11b600e8ffcd5e344aebf984f6078ab4e5 Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Sun, 11 Sep 2011 14:59:32 -0400 Subject: [PATCH 013/189] Fix up scaffold.sh Use bash -e instead of single pipeline Unregister foobar after testing it --- yesod/test/scaffold.sh | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/yesod/test/scaffold.sh b/yesod/test/scaffold.sh index 34798202..303a9656 100755 --- a/yesod/test/scaffold.sh +++ b/yesod/test/scaffold.sh @@ -1,3 +1,12 @@ -#!/bin/bash -x +#!/bin/bash -ex -rm -rf foobar && runghc main.hs init && cd foobar && cabal install && cabal install -fdevel && cd .. +rm -rf foobar +runghc main.hs init + +( + cd foobar + cabal install + cabal install -fdevel +) + +ghc-pkg unregister foobar From 2aa6f989a6b66405ac532a379841d468b764f64a Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Sun, 11 Sep 2011 15:00:20 -0400 Subject: [PATCH 014/189] Complete rewrite of test/run.sh Output is more useful (IMO). Everything is silenced for the duration of the tests but a count of tests/failures and any errors are output at the end. Pass --verbose to watch stdout during the tests. Logic is also seperated into core setup/runners and individual test definitions. Should be more easily extensible. --- yesod/test/run.sh | 111 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 91 insertions(+), 20 deletions(-) diff --git a/yesod/test/run.sh b/yesod/test/run.sh index 948e7689..3b81e612 100755 --- a/yesod/test/run.sh +++ b/yesod/test/run.sh @@ -1,26 +1,97 @@ -#!/bin/bash -ex +#!/bin/bash -e # -# A wrapper for the shelltest test. Passes along options to shelltest. +# Runs test/scaffold.sh with a variety of inputs. Hides all output +# besides failure details. # -# cabal install shelltestrunner +### -cabal clean && cabal install && cabal sdist +[[ "$1" =~ -v|--verbose ]] && stdout=/dev/stdout || stdout=/dev/null -# I am not that good at shell scripting -# this for loop only operates on 1 file (as per tail -1) -for f in $(ls -1rt dist/*.tar.gz | tail -1) -do - tar -xzvf $f && cd `basename $f .tar.gz` +tmp='/tmp' +pwd="$PWD" - # shelltest is designed to show you the diff of an expected stdout/stdin. We don't care about that. If it compiles, it compiles - # shelltest ../test/scaffold.shelltest --color --diff --all $@ -- --hide-successes +pkg= +dir= - ../test/scaffold.sh < ../test/sqlite-input.txt && - ../test/scaffold.sh < ../test/postgresql-input.txt && - ../test/scaffold.sh < ../test/tiny-input.txt && - ../test/scaffold.sh < ../test/mongodb-input.txt || - (echo "FAILED" && exit 1) - cd .. - rm -r `basename $f .tar.gz` -done -echo "PASSED" +failures=() +n_tested=0 +n_failed=0 + +# runs the function named by $1, silencing stdout and redirecting stderr +# to /tmp/function.errors. failures are tracked to be reported on during +# cleanup +run_test() { # {{{ + local test_function="$*" + + n_tested=$((n_tested+1)) + + if $test_function >"$stdout" 2>"$tmp/$test_function.errors"; then + echo -n '.' + [[ -f "$tmp/$test_function.errors" ]] && rm "$tmp/$test_function.errors" + else + echo -n 'F' + failures+=( "$test_function" ) + n_failed=$((n_failed+1)) + fi +} +# }}} + +# changes back to the original directory, removes the dist file and +# outputs a report of tests and failures +cleanup() { # {{{ + cd "$pwd" + [[ -d "$dir" ]] && rm -r "$dir" + + echo + echo + echo "Tests: $n_tested, Failures: $n_failed." + echo + + [[ $n_failed -eq 0 ]] && return 0 + + for test in ${failures[@]}; do + echo "Failure: $test" + echo 'details:' + echo + + if [[ -f "$tmp/$test.errors" ]]; then + cat "$tmp/$test.errors" + rm "$tmp/$test.errors" + else + echo '' + fi + + echo + done + + return $n_failed +} +# }}} + +# compilation is test #1, sets global variable dir. other tests are run +# from within this directory and it is removed as part of cleanup +test_compile() { + cabal clean + cabal install + cabal sdist + + read -r pkg < <(find dist/ -type f -name '*.tar.gz' | sort -rV) + dir="$(basename "$pkg" .tar.gz)" + + tar -xzf "$pkg" && cd "$dir" +} + +test_sqlite() { ../test/scaffold.sh < ../test/sqlite-input.txt ; } +test_postgresql() { ../test/scaffold.sh < ../test/postgresql-input.txt; } +test_mongodb() { ../test/scaffold.sh < ../test/mongodb-input.txt ; } +test_tiny() { ../test/scaffold.sh < ../test/tiny-input.txt ; } + +echo 'Started' +run_test 'test_compile' +run_test 'test_sqlite' +run_test 'test_postgresql' +run_test 'test_mongodb' +run_test 'test_tiny' +cleanup + +exit $? From b9bc2ee1c5efce1bb2571ecb3f457c8730e1a953 Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Sun, 11 Sep 2011 15:12:06 -0400 Subject: [PATCH 015/189] Fix typo in the postgres yaml name --- yesod-core/Yesod/Settings.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yesod-core/Yesod/Settings.hs b/yesod-core/Yesod/Settings.hs index 8e303972..7b924472 100644 --- a/yesod-core/Yesod/Settings.hs +++ b/yesod-core/Yesod/Settings.hs @@ -53,7 +53,7 @@ loadConfig env = do loadPostgresqlConnStr :: AppEnvironment -> IO Text loadPostgresqlConnStr env = do - allSettings <- (join $ YAML.decodeFile ("config/postgesql.yml" :: String)) >>= fromMapping + allSettings <- (join $ YAML.decodeFile ("config/postgresql.yml" :: String)) >>= fromMapping settings <- lookupMapping (show env) allSettings database <- lookupScalar "database" settings :: IO Text From 41f17183877d5700e8407a302a465d9bbb7bf970 Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Sun, 11 Sep 2011 16:52:54 -0400 Subject: [PATCH 016/189] Provide a default for withDevelAppPort --- yesod-core/Yesod/Main.hs | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/yesod-core/Yesod/Main.hs b/yesod-core/Yesod/Main.hs index bba1fd3e..98b13de4 100644 --- a/yesod-core/Yesod/Main.hs +++ b/yesod-core/Yesod/Main.hs @@ -3,12 +3,15 @@ module Yesod.Main ( defaultMain , fromArgs , fromArgsWith + , defaultDevelApp + , defaultDevelAppWith ) where -import Yesod.Logger (Logger, makeLogger) +import Yesod.Logger (Logger, makeLogger, logString, logLazyText, flushLogger) import Yesod.Settings (AppEnvironment(..), AppConfig(..), loadConfig) import Network.Wai (Application) import Network.Wai.Handler.Warp (run) +import Network.Wai.Middleware.Debug (debugHandle) import System.Console.CmdArgs hiding (args) import Data.Char (toUpper, toLower) @@ -72,3 +75,33 @@ fromArgsWith load = do capitalize [] = [] capitalize (x:xs) = toUpper x : map toLower xs + +-- | A default argument for use with yesod devel with debug logging +-- enabled. Uses @'Yesod.Settings.loadConfig'@ for the @'Development'@ +-- environment. +-- +-- > -- Application.hs +-- > +-- > withDevelAppPort :: Dynamic +-- > withDevelAppPort = toDyn $ defaultDevelApp withMySite +-- +defaultDevelApp :: (AppConfig -> Logger -> (Application -> IO ()) -> IO ()) + -> ((Int, Application) -> IO ()) + -> IO () +defaultDevelApp = defaultDevelAppWith loadConfig + +-- | Same, but allows one to provide their own cust @'loadConfig'@ +defaultDevelAppWith :: (AppEnvironment -> IO AppConfig) + -> (AppConfig -> Logger -> (Application -> IO ()) -> IO ()) + -> ((Int, Application) -> IO ()) + -> IO () +defaultDevelAppWith load withSite f = do + conf <- load Development + logger <- makeLogger + let p = appPort conf + logString logger $ "Devel application launched, listening on port " ++ show p + withSite conf logger $ \app -> f (p, debugHandle (logHandle logger) app) + flushLogger logger + + where + logHandle logger msg = logLazyText logger msg >> flushLogger logger From f06f11ff2616da1ce43d70c21fb85445a68f9d7c Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Sun, 11 Sep 2011 17:15:35 -0400 Subject: [PATCH 017/189] Simplify scaffold futher by using defaultDevelApp --- yesod/scaffold/Application.hs.cg | 17 ++--------------- yesod/scaffold/tiny/Application.hs.cg | 18 +++--------------- 2 files changed, 5 insertions(+), 30 deletions(-) diff --git a/yesod/scaffold/Application.hs.cg b/yesod/scaffold/Application.hs.cg index 8688fe02..02d95819 100644 --- a/yesod/scaffold/Application.hs.cg +++ b/yesod/scaffold/Application.hs.cg @@ -12,11 +12,10 @@ import Foundation import Settings import Settings.StaticFiles (static) import Yesod.Auth -import Yesod.Logger (makeLogger, flushLogger, Logger, logString, logLazyText) +import Yesod.Logger (Logger) import Database.Persist.~importGenericDB~ import Data.ByteString (ByteString) import Data.Dynamic (Dynamic, toDyn) -import Network.Wai.Middleware.Debug (debugHandle) #ifndef WINDOWS import qualified System.Posix.Signals as Signal @@ -63,16 +62,4 @@ with~sitearg~ conf logger f = do -- for yesod devel withDevelAppPort :: Dynamic -withDevelAppPort = - toDyn go - where - go :: ((Int, Application) -> IO ()) -> IO () - go f = do - conf <- loadConfig Development - let port = appPort conf - logger <- makeLogger - logString logger $ "Devel application launched, listening on port " ++ show port - with~sitearg~ conf logger $ \app -> f (port, debugHandle (logHandle logger) app) - flushLogger logger - where - logHandle logger msg = logLazyText logger msg >> flushLogger logger +withDevelAppPort = toDyn $ defaultDevelApp with~sitearg~ diff --git a/yesod/scaffold/tiny/Application.hs.cg b/yesod/scaffold/tiny/Application.hs.cg index e4e2aaef..77c73898 100644 --- a/yesod/scaffold/tiny/Application.hs.cg +++ b/yesod/scaffold/tiny/Application.hs.cg @@ -12,11 +12,11 @@ import Foundation import Settings import Yesod.Static import Yesod.Settings -import Yesod.Logger (makeLogger, flushLogger, Logger, logLazyText, logString) +import Yesod.Main (defaultDevelApp) +import Yesod.Logger (Logger) import Data.ByteString (ByteString) import Network.Wai (Application) import Data.Dynamic (Dynamic, toDyn) -import Network.Wai.Middleware.Debug (debugHandle) -- Import all relevant handler modules here. import Handler.Root @@ -50,16 +50,4 @@ with~sitearg~ conf logger f = do -- for yesod devel withDevelAppPort :: Dynamic -withDevelAppPort = - toDyn go - where - go :: ((Int, Application) -> IO ()) -> IO () - go f = do - conf <- loadConfig Development - let port = appPort conf - logger <- makeLogger - logString logger $ "Devel application launched, listening on port " ++ show port - with~sitearg~ conf logger $ \app -> f (port, debugHandle (logHandle logger) app) - flushLogger logger - where - logHandle logger msg = logLazyText logger msg >> flushLogger logger +withDevelAppPort = toDyn $ defaultDevelApp with~sitearg~ From 900e9476f3bd88ab10b445e7c5c374c2c0398c2c Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Tue, 13 Sep 2011 21:28:33 -0400 Subject: [PATCH 018/189] Move Settings/Main out of -core --- yesod-core/yesod-core.cabal | 7 ------- {yesod-core => yesod}/Yesod/Main.hs | 0 {yesod-core => yesod}/Yesod/Settings.hs | 0 yesod/yesod.cabal | 6 ++++++ 4 files changed, 6 insertions(+), 7 deletions(-) rename {yesod-core => yesod}/Yesod/Main.hs (100%) rename {yesod-core => yesod}/Yesod/Settings.hs (100%) diff --git a/yesod-core/yesod-core.cabal b/yesod-core/yesod-core.cabal index ce7a8c0c..1b520dc4 100644 --- a/yesod-core/yesod-core.cabal +++ b/yesod-core/yesod-core.cabal @@ -38,7 +38,6 @@ library , shakespeare >= 0.10 && < 0.11 , shakespeare-js >= 0.10 && < 0.11 , shakespeare-css >= 0.10 && < 0.11 - , shakespeare-text >= 0.10 && < 0.11 , blaze-builder >= 0.2.1 && < 0.4 , transformers >= 0.2 && < 0.3 , clientsession >= 0.7.2 && < 0.8 @@ -55,10 +54,6 @@ library , case-insensitive >= 0.2 && < 0.4 , parsec >= 2 && < 3.2 , directory >= 1 && < 1.2 - , cmdargs >= 0.8 && < 0.9 - , data-object >= 0.3 && < 0.4 - , data-object-yaml >= 0.3 && < 0.4 - , warp >= 0.4 && < 0.5 -- for logger. Probably logger should be a separate package , strict-concurrency >= 0.2.4 && < 0.2.5 @@ -70,8 +65,6 @@ library Yesod.Request Yesod.Widget Yesod.Message - Yesod.Settings - Yesod.Main other-modules: Yesod.Internal Yesod.Internal.Core Yesod.Internal.Session diff --git a/yesod-core/Yesod/Main.hs b/yesod/Yesod/Main.hs similarity index 100% rename from yesod-core/Yesod/Main.hs rename to yesod/Yesod/Main.hs diff --git a/yesod-core/Yesod/Settings.hs b/yesod/Yesod/Settings.hs similarity index 100% rename from yesod-core/Yesod/Settings.hs rename to yesod/Yesod/Settings.hs diff --git a/yesod/yesod.cabal b/yesod/yesod.cabal index 94a340d4..37c0634a 100644 --- a/yesod/yesod.cabal +++ b/yesod/yesod.cabal @@ -74,9 +74,15 @@ library , hamlet >= 0.10 && < 0.11 , shakespeare-js >= 0.10 && < 0.11 , shakespeare-css >= 0.10 && < 0.11 + , shakespeare-text >= 0.10 && < 0.11 , warp >= 0.4 && < 0.5 , blaze-html >= 0.4 && < 0.5 + , cmdargs >= 0.8 && < 0.9 + , data-object >= 0.3 && < 0.4 + , data-object-yaml >= 0.3 && < 0.4 exposed-modules: Yesod + Yesod.Settings + Yesod.Main ghc-options: -Wall executable yesod From 2d0d70fd60c93f6aa29ddadd9e40d83670f3a660 Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Tue, 13 Sep 2011 21:55:11 -0400 Subject: [PATCH 019/189] bring comments back in --- yesod/Yesod/Settings.hs | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/yesod/Yesod/Settings.hs b/yesod/Yesod/Settings.hs index 7b924472..148b081a 100644 --- a/yesod/Yesod/Settings.hs +++ b/yesod/Yesod/Settings.hs @@ -23,13 +23,41 @@ data AppEnvironment = Development | Production deriving (Eq, Show, Read, Enum, Bounded) +-- | Dynamic per-environment configuration which can be loaded at +-- run-time negating the need to recompile between environments. data AppConfig = AppConfig - { appEnv :: AppEnvironment - , appPort :: Int + { appEnv :: AppEnvironment + , appPort :: Int + + -- | Your application will keep a connection pool and take + -- connections from there as necessary instead of continually + -- creating new connections. This value gives the maximum number + -- of connections to be open at a given time. If your application + -- requests a connection when all connections are in use, that + -- request will fail. Try to choose a number that will work well + -- with the system resources available to you while providing + -- enough connections for your expected load. + -- + -- Connections are returned to the pool as quickly as possible by + -- Yesod to avoid resource exhaustion. A connection is only + -- considered in use while within a call to runDB. , connectionPoolSize :: Int - , appRoot :: Text + + -- | The base URL for your application. This will usually be + -- different for development and production. Yesod automatically + -- constructs URLs for you, so this value must be accurate to + -- create valid links. + -- + -- If your domain name was "yesod.com", you would probably want it + -- to be: + -- + -- > "http://yesod.com" + -- + , appRoot :: Text } deriving (Show) +-- | Load an @'AppConfig'@ from a YAML-formatted file located at +-- @config\/settings.yml@. loadConfig :: AppEnvironment -> IO AppConfig loadConfig env = do allSettings <- (join $ YAML.decodeFile ("config/settings.yml" :: String)) >>= fromMapping @@ -51,6 +79,8 @@ loadConfig env = do Production -> "" _ -> ":" ++ show p +-- | Load Postgresql settings from a YAML-formatted file located at +-- @config\/postgresql.yml@. loadPostgresqlConnStr :: AppEnvironment -> IO Text loadPostgresqlConnStr env = do allSettings <- (join $ YAML.decodeFile ("config/postgresql.yml" :: String)) >>= fromMapping @@ -62,13 +92,16 @@ loadPostgresqlConnStr env = do return $ [st| #{key}=#{value} |] return $ [st|#{connPart} dbname=#{database}|] +-- | Load Sqlite settings from a YAML-formatted file located at +-- @config\/sqlite.yml@. loadSqliteConnStr :: AppEnvironment -> IO Text loadSqliteConnStr env = do allSettings <- (join $ YAML.decodeFile ("config/sqlite.yml" :: String)) >>= fromMapping settings <- lookupMapping (show env) allSettings lookupScalar "database" settings --- note: no type signature to avoid Persistent.MongoDB dep +-- note: no type signature to avoid an extra Persistent.MongoDB dep for +-- those that don't need it --loadMongoConnParams :: AppEnvironment -> IO (Database, HostName) loadMongoConnParams env = do allSettings <- (join $ YAML.decodeFile ("config/mongoDB.yml" :: String)) >>= fromMapping From f41029fd4cc53454f353fa56855e9c5ef080751c Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Tue, 13 Sep 2011 23:07:27 -0400 Subject: [PATCH 020/189] Add yesod dep to tiny scaffold --- yesod/scaffold/tiny/project.cabal.cg | 1 + 1 file changed, 1 insertion(+) diff --git a/yesod/scaffold/tiny/project.cabal.cg b/yesod/scaffold/tiny/project.cabal.cg index 527f265b..6e5c3cc5 100644 --- a/yesod/scaffold/tiny/project.cabal.cg +++ b/yesod/scaffold/tiny/project.cabal.cg @@ -46,6 +46,7 @@ executable ~project~ hs-source-dirs: . build-depends: base >= 4 && < 5 + , yesod >= 0.9 && < 0.10 , yesod-core >= 0.9 && < 0.10 , yesod-static , clientsession From cfb6e1e24a6eb5f8ebafc6d1c1c038b3278ce98f Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Mon, 19 Sep 2011 15:12:19 -0400 Subject: [PATCH 021/189] Move bulk of Settings/Main out of -core Trim settings to only the AppConfig def and an AppEnv typeclass, rename to Config but leave in -core --- .../Settings.hs => yesod-core/Yesod/Config.hs | 40 +++---- yesod-core/Yesod/Core.hs | 2 + yesod-core/yesod-core.cabal | 4 + yesod/Yesod/Main.hs | 107 ------------------ 4 files changed, 19 insertions(+), 134 deletions(-) rename yesod/Yesod/Settings.hs => yesod-core/Yesod/Config.hs (70%) delete mode 100644 yesod/Yesod/Main.hs diff --git a/yesod/Yesod/Settings.hs b/yesod-core/Yesod/Config.hs similarity index 70% rename from yesod/Yesod/Settings.hs rename to yesod-core/Yesod/Config.hs index 148b081a..2fccc1e6 100644 --- a/yesod/Yesod/Settings.hs +++ b/yesod-core/Yesod/Config.hs @@ -1,7 +1,7 @@ {-# OPTIONS -fno-warn-missing-signatures #-} {-# LANGUAGE QuasiQuotes #-} -module Yesod.Settings - ( AppEnvironment(..) +module Yesod.Config + ( AppEnv(..) , AppConfig(..) , loadConfig , loadPostgresqlConnStr @@ -17,30 +17,16 @@ import Text.Shakespeare.Text (st) import qualified Data.Object.Yaml as YAML import qualified Data.Text as T -data AppEnvironment = Development - | Test - | Staging - | Production - deriving (Eq, Show, Read, Enum, Bounded) +class AppEnv e where + displayPort :: e -> Bool -- | Dynamic per-environment configuration which can be loaded at -- run-time negating the need to recompile between environments. -data AppConfig = AppConfig - { appEnv :: AppEnvironment +data AppConfig e = AppConfig + { appEnv :: e , appPort :: Int - -- | Your application will keep a connection pool and take - -- connections from there as necessary instead of continually - -- creating new connections. This value gives the maximum number - -- of connections to be open at a given time. If your application - -- requests a connection when all connections are in use, that - -- request will fail. Try to choose a number that will work well - -- with the system resources available to you while providing - -- enough connections for your expected load. - -- - -- Connections are returned to the pool as quickly as possible by - -- Yesod to avoid resource exhaustion. A connection is only - -- considered in use while within a call to runDB. + -- TODO: put this in db configs , connectionPoolSize :: Int -- | The base URL for your application. This will usually be @@ -56,9 +42,10 @@ data AppConfig = AppConfig , appRoot :: Text } deriving (Show) + -- | Load an @'AppConfig'@ from a YAML-formatted file located at -- @config\/settings.yml@. -loadConfig :: AppEnvironment -> IO AppConfig +loadConfig :: AppEnv e => e -> IO (AppConfig e) loadConfig env = do allSettings <- (join $ YAML.decodeFile ("config/settings.yml" :: String)) >>= fromMapping settings <- lookupMapping (show env) allSettings @@ -75,13 +62,12 @@ loadConfig env = do where addPort :: Int -> String - addPort p = case env of - Production -> "" - _ -> ":" ++ show p + addPort p = if displayPort env + then ":" ++ show p else "" -- | Load Postgresql settings from a YAML-formatted file located at -- @config\/postgresql.yml@. -loadPostgresqlConnStr :: AppEnvironment -> IO Text +loadPostgresqlConnStr :: Show e => e -> IO Text loadPostgresqlConnStr env = do allSettings <- (join $ YAML.decodeFile ("config/postgresql.yml" :: String)) >>= fromMapping settings <- lookupMapping (show env) allSettings @@ -94,7 +80,7 @@ loadPostgresqlConnStr env = do -- | Load Sqlite settings from a YAML-formatted file located at -- @config\/sqlite.yml@. -loadSqliteConnStr :: AppEnvironment -> IO Text +loadSqliteConnStr :: Show e => e -> IO Text loadSqliteConnStr env = do allSettings <- (join $ YAML.decodeFile ("config/sqlite.yml" :: String)) >>= fromMapping settings <- lookupMapping (show env) allSettings diff --git a/yesod-core/Yesod/Core.hs b/yesod-core/Yesod/Core.hs index 9f137991..2e395856 100644 --- a/yesod-core/Yesod/Core.hs +++ b/yesod-core/Yesod/Core.hs @@ -33,6 +33,7 @@ module Yesod.Core , module Yesod.Request , module Yesod.Widget , module Yesod.Message + , module Yesod.Config ) where import Yesod.Internal.Core @@ -42,6 +43,7 @@ import Yesod.Handler import Yesod.Request import Yesod.Widget import Yesod.Message +import Yesod.Config import Language.Haskell.TH.Syntax import Data.Text (Text) diff --git a/yesod-core/yesod-core.cabal b/yesod-core/yesod-core.cabal index 1b520dc4..a499a2d3 100644 --- a/yesod-core/yesod-core.cabal +++ b/yesod-core/yesod-core.cabal @@ -38,6 +38,7 @@ library , shakespeare >= 0.10 && < 0.11 , shakespeare-js >= 0.10 && < 0.11 , shakespeare-css >= 0.10 && < 0.11 + , shakespeare-text >= 0.10 && < 0.11 , blaze-builder >= 0.2.1 && < 0.4 , transformers >= 0.2 && < 0.3 , clientsession >= 0.7.2 && < 0.8 @@ -54,6 +55,8 @@ library , case-insensitive >= 0.2 && < 0.4 , parsec >= 2 && < 3.2 , directory >= 1 && < 1.2 + , data-object >= 0.3 && < 0.4 + , data-object-yaml >= 0.3 && < 0.4 -- for logger. Probably logger should be a separate package , strict-concurrency >= 0.2.4 && < 0.2.5 @@ -65,6 +68,7 @@ library Yesod.Request Yesod.Widget Yesod.Message + Yesod.Config other-modules: Yesod.Internal Yesod.Internal.Core Yesod.Internal.Session diff --git a/yesod/Yesod/Main.hs b/yesod/Yesod/Main.hs deleted file mode 100644 index 98b13de4..00000000 --- a/yesod/Yesod/Main.hs +++ /dev/null @@ -1,107 +0,0 @@ -{-# LANGUAGE DeriveDataTypeable #-} -module Yesod.Main - ( defaultMain - , fromArgs - , fromArgsWith - , defaultDevelApp - , defaultDevelAppWith - ) where - -import Yesod.Logger (Logger, makeLogger, logString, logLazyText, flushLogger) -import Yesod.Settings (AppEnvironment(..), AppConfig(..), loadConfig) -import Network.Wai (Application) -import Network.Wai.Handler.Warp (run) -import Network.Wai.Middleware.Debug (debugHandle) -import System.Console.CmdArgs hiding (args) -import Data.Char (toUpper, toLower) - -data ArgConfig = ArgConfig - { environment :: String - , port :: Int - } deriving (Show, Data, Typeable) - --- | Load an @'AppConfig'@ using the provided function, then start your --- app via Warp on the configured port. --- --- > -- main.hs --- > import Application (withMySite) --- > import Yesod.Main (defaultMain, fromArgs) --- > --- > main :: IO () --- > main = defaultMain fromArgs withMySite --- -defaultMain :: IO AppConfig -> (AppConfig -> Logger -> (Application -> IO ()) -> IO ()) -> IO () -defaultMain load withSite = do - config <- load - logger <- makeLogger - withSite config logger $ run (appPort config) - --- | Call the @'Yesod.Settings.loadConfig'@ function for the environment --- passed on the commandline (or the default, \"development\") and --- override the port if passed. -fromArgs :: IO AppConfig -fromArgs = fromArgsWith loadConfig - --- | Same, but allows one to provide their own custom @'loadConfig'@ -fromArgsWith :: (AppEnvironment -> IO AppConfig) -> IO AppConfig -fromArgsWith load = do - args <- cmdArgs argConfig - - let env = read - $ capitalize - $ if environment args /= "" - then environment args - else "development" - - config <- load env - - return $ if port args /= 0 - then config { appPort = port args } - else config - - where - argConfig :: ArgConfig - argConfig = ArgConfig - { environment = def - &= help ("application environment, one of: " ++ (foldl1 (\a b -> a ++ ", " ++ b) environments)) - &= typ "ENVIRONMENT" - , port = def - &= help "the port to listen on" - &= typ "PORT" - } - - environments :: [String] - environments = map ((map toLower) . show) ([minBound..maxBound] :: [AppEnvironment]) - - capitalize [] = [] - capitalize (x:xs) = toUpper x : map toLower xs - --- | A default argument for use with yesod devel with debug logging --- enabled. Uses @'Yesod.Settings.loadConfig'@ for the @'Development'@ --- environment. --- --- > -- Application.hs --- > --- > withDevelAppPort :: Dynamic --- > withDevelAppPort = toDyn $ defaultDevelApp withMySite --- -defaultDevelApp :: (AppConfig -> Logger -> (Application -> IO ()) -> IO ()) - -> ((Int, Application) -> IO ()) - -> IO () -defaultDevelApp = defaultDevelAppWith loadConfig - --- | Same, but allows one to provide their own cust @'loadConfig'@ -defaultDevelAppWith :: (AppEnvironment -> IO AppConfig) - -> (AppConfig -> Logger -> (Application -> IO ()) -> IO ()) - -> ((Int, Application) -> IO ()) - -> IO () -defaultDevelAppWith load withSite f = do - conf <- load Development - logger <- makeLogger - let p = appPort conf - logString logger $ "Devel application launched, listening on port " ++ show p - withSite conf logger $ \app -> f (p, debugHandle (logHandle logger) app) - flushLogger logger - - where - logHandle logger msg = logLazyText logger msg >> flushLogger logger From 4f52f22a2ccb89f87257ef66d0871066012d587b Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Mon, 19 Sep 2011 15:14:41 -0400 Subject: [PATCH 022/189] Put yesod module back as it was --- yesod/Yesod.hs | 4 ---- yesod/yesod.cabal | 6 ------ 2 files changed, 10 deletions(-) diff --git a/yesod/Yesod.hs b/yesod/Yesod.hs index 6fc6ee98..7724a345 100644 --- a/yesod/Yesod.hs +++ b/yesod/Yesod.hs @@ -7,8 +7,6 @@ module Yesod , module Yesod.Form , module Yesod.Json , module Yesod.Persist - , module Yesod.Settings - , module Yesod.Main -- * Running your application , warp , warpDebug @@ -48,8 +46,6 @@ import Text.Julius import Yesod.Form import Yesod.Json import Yesod.Persist -import Yesod.Settings -import Yesod.Main import Network.Wai (Application) import Network.Wai.Middleware.Debug import Control.Monad.Trans.Class (lift) diff --git a/yesod/yesod.cabal b/yesod/yesod.cabal index 37c0634a..94a340d4 100644 --- a/yesod/yesod.cabal +++ b/yesod/yesod.cabal @@ -74,15 +74,9 @@ library , hamlet >= 0.10 && < 0.11 , shakespeare-js >= 0.10 && < 0.11 , shakespeare-css >= 0.10 && < 0.11 - , shakespeare-text >= 0.10 && < 0.11 , warp >= 0.4 && < 0.5 , blaze-html >= 0.4 && < 0.5 - , cmdargs >= 0.8 && < 0.9 - , data-object >= 0.3 && < 0.4 - , data-object-yaml >= 0.3 && < 0.4 exposed-modules: Yesod - Yesod.Settings - Yesod.Main ghc-options: -Wall executable yesod From b031702a9bec56c9a1bfba6275ce867a260f182b Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Mon, 19 Sep 2011 15:15:04 -0400 Subject: [PATCH 023/189] Add yesod-default Still needs the cabal, Setup, etc etc but at least it compiles and is somewhat extensible. --- yesod-default/Yesod/Default/Config.hs | 76 +++++++++++++++++++++++++++ yesod-default/Yesod/Default/Main.hs | 65 +++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 yesod-default/Yesod/Default/Config.hs create mode 100644 yesod-default/Yesod/Default/Main.hs diff --git a/yesod-default/Yesod/Default/Config.hs b/yesod-default/Yesod/Default/Config.hs new file mode 100644 index 00000000..7f92b3b8 --- /dev/null +++ b/yesod-default/Yesod/Default/Config.hs @@ -0,0 +1,76 @@ +{-# LANGUAGE DeriveDataTypeable #-} +module Yesod.Default.Config + ( DefaultEnv(..) + , ArgConfig(..) + , defaultArgConfig + , fromArgs + , fromArgsWith + , loadDevelopmentConfig + + -- reexport + , module Yesod.Config + ) where + +import Yesod.Config +import Data.Char (toUpper, toLower) +import System.Console.CmdArgs hiding (args) + +-- | A yesod-provided @'AppEnv'@, allows for Development, Testing, and +-- Production environments +data DefaultEnv = Development + | Testing + | Production deriving (Read, Show, Enum, Bounded) + +instance AppEnv DefaultEnv where + displayPort Production = False + displayPort _ = True + +-- | Setup commandline arguments for environment and port +data ArgConfig = ArgConfig + { environment :: String + , port :: Int + } deriving (Show, Data, Typeable) + +-- | A default @'ArgConfig'@ if using the provided @'DefaultEnv'@ type. +defaultArgConfig :: ArgConfig +defaultArgConfig = + ArgConfig + { environment = def + &= opt "development" + &= help ("application environment, one of: " ++ environments) + &= typ "ENVIRONMENT" + , port = def + &= help "the port to listen on" + &= typ "PORT" + } + + where + environments :: String + environments = foldl1 (\a b -> a ++ ", " ++ b) + . map ((map toLower) . show) + $ ([minBound..maxBound] :: [DefaultEnv]) + +-- | Load an @'AppConfig'@ using the @'DefaultEnv'@ environments from +-- commandline arguments. +fromArgs :: IO (AppConfig DefaultEnv) +fromArgs = fromArgsWith defaultArgConfig + +fromArgsWith :: AppEnv e => ArgConfig -> IO (AppConfig e) +fromArgsWith argConfig = do + args <- cmdArgs argConfig + + let env = read $ capitalize $ environment args + + config <- loadConfig env + + return $ if port args /= 0 + then config { appPort = port args } + else config + + where + capitalize [] = [] + capitalize (x:xs) = toUpper x : map toLower xs + +-- | Load your development config (when using @'DefaultEnv'@) +loadDevelopmentConfig :: IO (AppConfig DefaultEnv) +loadDevelopmentConfig = loadConfig Development diff --git a/yesod-default/Yesod/Default/Main.hs b/yesod-default/Yesod/Default/Main.hs new file mode 100644 index 00000000..9a1e2e45 --- /dev/null +++ b/yesod-default/Yesod/Default/Main.hs @@ -0,0 +1,65 @@ +{-# LANGUAGE DeriveDataTypeable #-} +module Yesod.Default.Main + ( defaultMain + , defaultDevelApp + , defaultDevelAppWith + ) where + +import Yesod.Default.Config +import Yesod.Logger (Logger, makeLogger, logString, logLazyText, flushLogger) +import Network.Wai (Application) +import Network.Wai.Handler.Warp (run) +import Network.Wai.Middleware.Debug (debugHandle) + +-- | Run your app, taking environment and port settings from the +-- commandline. +-- +-- Use @'fromArgs'@ when using the provided @'DefaultEnv'@ type, or +-- @'fromArgsWith'@ when using a custom type +-- +-- > main :: IO () +-- > main = defaultMain fromArgs withMySite +-- +-- or +-- +-- > main :: IO () +-- > main = defaultMain (fromArgsWith customArgConfig) withMySite +-- +defaultMain :: AppEnv e => IO (AppConfig e) -> (AppConfig e -> Logger -> (Application -> IO ()) -> IO ()) -> IO () +defaultMain load withSite = do + config <- load + logger <- makeLogger + withSite config logger $ run (appPort config) + +-- | Run your development app using the provided @'DefaultEnv'@ type +-- +-- > withDevelAppPort :: Dynamic +-- > withDevelAppPort = toDyn $ defaultDevelApp withMySite +-- +defaultDevelApp :: (AppConfig DefaultEnv -> Logger -> (Application -> IO ()) -> IO ()) + -> ((Int, Application) -> IO ()) + -> IO () +defaultDevelApp = defaultDevelAppWith loadDevelopmentConfig + +-- | Run your development app using a custom environment type and loader +-- function +-- +-- > withDevelAppPort :: Dynamic +-- > withDevelAppPort = toDyn $ (defaultDevelAppWith customLoadAppConfig) withMySite +-- +defaultDevelAppWith :: AppEnv e + -- | A means to load your development @'AppConfig'@ + => IO (AppConfig e) + -- | Your @withMySite@ function + -> (AppConfig e -> Logger -> (Application -> IO ()) -> IO ()) + -> ((Int, Application) -> IO ()) -> IO () +defaultDevelAppWith load withSite f = do + conf <- load + logger <- makeLogger + let p = appPort conf + logString logger $ "Devel application launched, listening on port " ++ show p + withSite conf logger $ \app -> f (p, debugHandle (logHandle logger) app) + flushLogger logger + + where + logHandle logger msg = logLazyText logger msg >> flushLogger logger From aef2992005a53a8a49c1e2bb5c266072bbdc9d73 Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Mon, 19 Sep 2011 16:10:46 -0400 Subject: [PATCH 024/189] fix haddock parse --- yesod-default/Yesod/Default/Main.hs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/yesod-default/Yesod/Default/Main.hs b/yesod-default/Yesod/Default/Main.hs index 9a1e2e45..2ac9ee69 100644 --- a/yesod-default/Yesod/Default/Main.hs +++ b/yesod-default/Yesod/Default/Main.hs @@ -48,10 +48,8 @@ defaultDevelApp = defaultDevelAppWith loadDevelopmentConfig -- > withDevelAppPort = toDyn $ (defaultDevelAppWith customLoadAppConfig) withMySite -- defaultDevelAppWith :: AppEnv e - -- | A means to load your development @'AppConfig'@ - => IO (AppConfig e) - -- | Your @withMySite@ function - -> (AppConfig e -> Logger -> (Application -> IO ()) -> IO ()) + => IO (AppConfig e) -- ^ A means to load your development @'AppConfig'@ + -> (AppConfig e -> Logger -> (Application -> IO ()) -> IO ()) -- ^ Your @withMySite@ function -> ((Int, Application) -> IO ()) -> IO () defaultDevelAppWith load withSite f = do conf <- load From 0563a2d5e47a650a774c2b7c084bf91c1205f6b9 Mon Sep 17 00:00:00 2001 From: patrick brisbin Date: Mon, 19 Sep 2011 16:10:59 -0400 Subject: [PATCH 025/189] Make yesod-default installable --- yesod-default/LICENSE | 25 +++++++++++++++++++++++++ yesod-default/README | 0 yesod-default/Setup.lhs | 7 +++++++ yesod-default/yesod-default.cabal | 31 +++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+) create mode 100644 yesod-default/LICENSE create mode 100644 yesod-default/README create mode 100755 yesod-default/Setup.lhs create mode 100644 yesod-default/yesod-default.cabal diff --git a/yesod-default/LICENSE b/yesod-default/LICENSE new file mode 100644 index 00000000..8643e5d8 --- /dev/null +++ b/yesod-default/LICENSE @@ -0,0 +1,25 @@ +The following license covers this documentation, and the source code, except +where otherwise indicated. + +Copyright 2010, Michael Snoyman. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/yesod-default/README b/yesod-default/README new file mode 100644 index 00000000..e69de29b diff --git a/yesod-default/Setup.lhs b/yesod-default/Setup.lhs new file mode 100755 index 00000000..06e2708f --- /dev/null +++ b/yesod-default/Setup.lhs @@ -0,0 +1,7 @@ +#!/usr/bin/env runhaskell + +> module Main where +> import Distribution.Simple + +> main :: IO () +> main = defaultMain diff --git a/yesod-default/yesod-default.cabal b/yesod-default/yesod-default.cabal new file mode 100644 index 00000000..306b6fb1 --- /dev/null +++ b/yesod-default/yesod-default.cabal @@ -0,0 +1,31 @@ +name: yesod-default +version: 0.3.1 +license: BSD3 +license-file: LICENSE +author: Patrick Brisbin +maintainer: Patrick Brisbin +synopsis: Default config and main functions for your yesod application +category: Web, Yesod +stability: Stable +cabal-version: >= 1.6 +build-type: Simple +homepage: http://www.yesodweb.com/ +description: Convenient wrappers for your the configuration and + execution of your yesod application + +library + build-depends: base >= 4 && < 5 + , yesod-core >= 0.9 && < 0.10 + , cmdargs >= 0.8 && < 0.9 + , warp >= 0.4 && < 0.5 + , wai >= 0.4 && < 0.5 + , wai-extra >= 0.4 && < 0.5 + + exposed-modules: Yesod.Default.Config + , Yesod.Default.Main + + ghc-options: -Wall + +source-repository head + type: git + location: git://github.com/yesodweb/yesod.git From d2e93341c0762e3996bd6bde28f5a268bd14fbc8 Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Tue, 20 Sep 2011 10:25:26 +0300 Subject: [PATCH 026/189] OptionList --- yesod-form/Yesod/Form/Fields.hs | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/yesod-form/Yesod/Form/Fields.hs b/yesod-form/Yesod/Form/Fields.hs index 32dfb93f..6ea1db92 100644 --- a/yesod-form/Yesod/Form/Fields.hs +++ b/yesod-form/Yesod/Form/Fields.hs @@ -35,6 +35,8 @@ module Yesod.Form.Fields , selectField' , radioField' , Option (..) + , OptionList (..) + , mkOptionList , optionsPersist , optionsPairs , optionsEnum @@ -76,6 +78,7 @@ import Yesod.Request (FileInfo) import Yesod.Core (toSinglePiece, GGHandler, SinglePiece) import Yesod.Persist (selectList, runDB, Filter, SelectOpt, YesodPersistBackend, Key, YesodPersist, PersistEntity, PersistBackend) +import Control.Arrow ((&&&)) #if __GLASGOW_HASKELL__ >= 700 #define WHAMLET whamlet @@ -303,7 +306,7 @@ urlField = Field selectField :: (Eq a, RenderMessage master FormMessage) => [(Text, a)] -> Field sub master a selectField = selectField' . optionsPairs -selectField' :: (Eq a, RenderMessage master FormMessage) => GGHandler sub master IO [Option a] -> Field sub master a +selectField' :: (Eq a, RenderMessage master FormMessage) => GGHandler sub master IO (OptionList a) -> Field sub master a selectField' = selectFieldHelper (\theId name inside -> [WHAMLET|