@@ -0,0 +1,146 @@
1+#! /usr/bin/env nix-shell
2+#! nix-shell "./script-env/ob-init.nix" -i "runghc"
3+--TODO: Don't depend on the user's environment - everything should be based on nixpkgs via reflex-platform
4+{-|
5+ Description: This script prompts user for the project name, and
6+ initializes the Obelisk submodules along with appropriate
7+ directory layout fit for best developer environment results.
8+ This script is to be used within an existing
9+ github repository and assumes that you have already
10+ configured/added your SSH key with both github and gitlab.
11+-}
12+
13+
14+{-# LANGUAGE OverloadedStrings #-}
15+{-# LANGUAGE LambdaCase #-}
16+{-# LANGUAGE TemplateHaskell #-}
17+
18+import System.Process (callProcess)
19+import System.Directory ( doesDirectoryExist
20+ , createDirectoryIfMissing
21+ , doesFileExist)
22+import Data.Text (Text)
23+import qualified Data.Text as Text
24+import qualified Data.Text.IO as Text
25+import Data.Monoid ((<>))
26+
27+main :: IO ()
28+main = do
29+ --TODO consider passing an arg instead of using a prompt
30+ putStr "Project name: "
31+ projectName <- Text.getLine
32+ doesDirectoryExist "obelisk" >>= \case
33+ True -> putStrLn "Skipping obelisk (already exists)"
34+ False -> do
35+ callProcess "git"
36+ [ "submodule"
37+ , "add"
38+ , "-b"
39+ , "develop"
40+ , "git@github.com:obsidiansystems/obelisk.git"
41+ ]
42+ callProcess "git"
43+ [ "submodule"
44+ , "update"
45+ , "--init"
46+ , "--recursive"
47+ ]
48+ mkdirs ["common/src", "frontend/src", "backend/src", "static", "config"]
49+ let defNix = "default.nix" :: FilePath
50+ let frontend = "frontend/src/Main.hs" :: FilePath
51+ let backend = "backend/src/Main.hs" :: FilePath
52+ createFileIfMissing defNix $ nixExpr projectName
53+ createFileIfMissing frontend frontSrc
54+ createFileIfMissing backend backSrc
55+
56+
57+--TODO: Consider using fileEmbed to generate default.nix in initializing folder
58+nixExpr :: Text -- ^ The name of the project; this must be a valid Cabal package name
59+ -> Text
60+nixExpr projectName = Text.unlines
61+ [ "{}: (import ./obelisk {}).mkDerivation {"
62+ , " name = \"" <> projectName <> "\";"
63+ , " version = \"0.1\";"
64+ , " commonDepends = p: with p; ["
65+ , " data-default"
66+ , " file-embed"
67+ , " ];"
68+ , " frontendDepends = p: with p; ["
69+ , " data-default"
70+ , " file-embed"
71+ , " obelisk-asset-th"
72+ , " ghcjs-dom"
73+ , " reflex"
74+ , " reflex-dom"
75+ , " these"
76+ , " ];"
77+ , " backendDepends = p: with p; ["
78+ , " data-default"
79+ , " resource-pool"
80+ , " snap"
81+ , " snap-core"
82+ , " snap-loader-static"
83+ , " snap-server"
84+ , " ];"
85+ , "}"
86+ ]
87+
88+
89+frontSrc :: Text
90+frontSrc = Text.unlines
91+ [ "{-# LANGUAGE OverloadedStrings #-}"
92+ , ""
93+ , "import Reflex.Dom"
94+ , "import GHCJS.DOM.Types (JSM, MonadJSM)"
95+ , ""
96+ , "#ifdef MIN_VERSION_jsaddle_warp"
97+ , "import Language.Javascript.JSaddle.Warp (run)"
98+ , "#endif"
99+ , ""
100+ , "#ifdef MIN_VERSION_jsaddle_wkwebview"
101+ , "import Language.Javascript.JSaddle.WKWebView (runFile)"
102+ , "#endif"
103+ , ""
104+ , "#if defined(__GHCJS__) && !defined(MIN_VERSION_jsaddle_warp) && !defined(MIN_VERSION_jsaddle_wkwebview)"
105+ , "runApp :: JSM () -> IO ()"
106+ , "runApp = id"
107+ , "#endif"
108+ , ""
109+ , "#ifdef MIN_VERSION_jsaddle_warp"
110+ , "runApp :: JSM () -> IO ()"
111+ , "runApp = run 3913"
112+ , "#endif"
113+ , ""
114+ , "#ifdef MIN_VERSION_jsaddle_wkwebview"
115+ , "runApp :: JSM () -> IO ()"
116+ , "runApp = runFile \"index.html\" \"\""
117+ , "#endif"
118+ , ""
119+ , "main = mainWidget $ text \"Hello new project\""
120+ ]
121+
122+backSrc :: Text
123+backSrc = Text.unlines
124+ [ "{-# LANGUAGE OverloadedStrings #-}"
125+ , ""
126+ , "import Data.Default"
127+ , "import Obelisk.Backend"
128+ , "import Obelisk.Backend.Snap"
129+ , "import Snap"
130+ , ""
131+ , "main :: IO ()"
132+ , "main = quickHttpServe $ rootHandler"
133+ , ""
134+ , "rootHandler :: Snap ()"
135+ , "rootHandler = route [(\"\", serveApp \"\" $ def)]"
136+ ]
137+
138+
139+mkdirs :: [FilePath] -> IO ()
140+mkdirs = mapM_ $ createDirectoryIfMissing True
141+
142+createFileIfMissing :: FilePath -> Text -> IO ()
143+createFileIfMissing aFile content =
144+ doesFileExist aFile >>= \case
145+ True -> putStrLn ("Skipping " ++ show aFile ++ "(already exist)")
146+ False -> Text.writeFile aFile content