Skip to content

Commit 32b2202

Browse files
committed
Add a RESTful server type of Haskell bootstrappable project
1 parent 9eb2de1 commit 32b2202

25 files changed

+590
-148
lines changed

.last-exported-commit

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Last exported commit from parent repo: 182bdb94e8a22c2485f137939855a84f1b5b8ad4
1+
Last exported commit from parent repo: 297f6b375154e7ab9d5329a7038439b907389ab1

.nix-bootstrap.dhall

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,35 @@ let ElmMode = < Bare | Node : NodePackageManager >
77

88
let ElmOptions = { elmMode : ElmMode, provideElmReview : Bool }
99

10+
let HaskellProjectType = < ReplOnly | Basic : Bool | Server : Bool >
11+
12+
let HaskellOptions =
13+
{ ghcVersion : { major : Natural, minor : Natural, patch : Natural }
14+
, haskellProjectType : HaskellProjectType
15+
}
16+
1017
let JavaOptions =
1118
{ installMinishift : Bool
1219
, installLombok : Bool
1320
, setUpJavaBuild : < SetUpJavaBuild : Text | NoJavaBuild >
21+
, jdk : < OpenJDK | GraalVM >
1422
}
1523

1624
let ProjectType =
1725
< Minimal
1826
| Elm : ElmOptions
27+
| Haskell : HaskellOptions
1928
| Node : NodePackageManager
2029
| Go : Bool
2130
| Java : JavaOptions
2231
| Python
32+
| Rust
2333
>
2434

2535
in { projectName = "nix-bootstrap"
2636
, projectType = ProjectType.Minimal
2737
, setUpPreCommitHooks = True
2838
, setUpContinuousIntegration = True
2939
, setUpVSCodeDevContainer = True
30-
, useNixFlakes = True
40+
, target = {=}
3141
}

nix-bootstrap.cabal

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ cabal-version: 2.0
55
-- see: https://github.com/sol/hpack
66

77
name: nix-bootstrap
8-
version: 2.3.0.5
8+
version: 2.4.0.0
99
author: gchquser
1010
maintainer: [email protected]
1111
copyright: Crown Copyright
@@ -43,6 +43,7 @@ library
4343
Bootstrap.Data.Bootstrappable.Haskell.MainHs
4444
Bootstrap.Data.Bootstrappable.Haskell.PackageYaml
4545
Bootstrap.Data.Bootstrappable.Haskell.PreludeHs
46+
Bootstrap.Data.Bootstrappable.Haskell.ServerHs
4647
Bootstrap.Data.Bootstrappable.HaskellPackagesNix
4748
Bootstrap.Data.Bootstrappable.NixPreCommitHookConfig
4849
Bootstrap.Data.Bootstrappable.Python.Requirements
@@ -193,6 +194,7 @@ test-suite nix-bootstrap-test
193194
Bootstrap.Data.Bootstrappable.Haskell.LibHsSpec
194195
Bootstrap.Data.Bootstrappable.Haskell.MainHsSpec
195196
Bootstrap.Data.Bootstrappable.Haskell.PreludeHsSpec
197+
Bootstrap.Data.Bootstrappable.Haskell.ServerHsSpec
196198
Bootstrap.Data.Bootstrappable.HaskellPackagesNixSpec
197199
Bootstrap.Data.Bootstrappable.NixPreCommitHookConfigSpec
198200
Bootstrap.Data.Bootstrappable.ReadmeSpec

package.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414
name: nix-bootstrap
15-
version: 2.3.0.5
15+
version: 2.4.0.0
1616
author: gchquser
1717
maintainer: [email protected]
1818
copyright: Crown Copyright

src/Bootstrap.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import Bootstrap.Data.Bootstrappable.Haskell.LibHs (libHsFor)
4242
import Bootstrap.Data.Bootstrappable.Haskell.MainHs (mainHsFor)
4343
import Bootstrap.Data.Bootstrappable.Haskell.PackageYaml (packageYamlFor)
4444
import Bootstrap.Data.Bootstrappable.Haskell.PreludeHs (preludeHsFor)
45+
import Bootstrap.Data.Bootstrappable.Haskell.ServerHs (serverHsFor)
4546
import Bootstrap.Data.Bootstrappable.HaskellPackagesNix (haskellPackagesNixFor)
4647
import Bootstrap.Data.Bootstrappable.NixPreCommitHookConfig (nixPreCommitHookConfigFor)
4748
import Bootstrap.Data.Bootstrappable.Python.Requirements (Requirements (Requirements))
@@ -496,6 +497,7 @@ makeNonPythonBuildPlan MakeBuildPlanArgs {..} = do
496497
~: packageYamlFor mbpNixBinaryPaths mbpProjectName mbpProjectType
497498
~: preludeHsFor mbpProjectType
498499
~: libHsFor mbpProjectType
500+
~: serverHsFor mbpProjectType
499501
~: mainHsFor mbpProjectType
500502
~: haskellPackagesNixFor mbpProjectType
501503
~: cargoLockFor mbpProjectType mbpProjectName

src/Bootstrap/Data/Bootstrappable.hs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ data HaskellImport
8989
= -- | import ModName
9090
HaskellImportAll THS.ModName
9191
| -- | import ModName (name1, name2)
92-
HaskellImport THS.ModName [TH.Name]
92+
HaskellImport THS.ModName [Text]
9393

9494
-- | Creates a `HaskellModule` with the minimum required information
9595
haskellModule ::
@@ -134,10 +134,8 @@ bootstrapContentHaskell HaskellModule {..} =
134134
"import "
135135
<> toText iModName
136136
<> " ("
137-
<> formatNames names
137+
<> T.intercalate ", " names
138138
<> ")"
139-
formatNames :: [TH.Name] -> Text
140-
formatNames = T.intercalate ", " . fmap (toText . TH.pprint . TH.VarE)
141139

142140
-- | A helper function when the generated file should be nix code
143141
bootstrapContentNix :: (IsNixExpr a, MonadIO m) => a -> m (Either String Text)

src/Bootstrap/Data/Bootstrappable/BuildNix.hs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import Bootstrap.Data.Bootstrappable
1212
import Bootstrap.Data.ProjectName (ProjectName)
1313
import Bootstrap.Data.ProjectType
1414
( HaskellOptions (HaskellOptions),
15-
HaskellProjectType (HaskellProjectTypeBasic),
15+
HaskellProjectType (HaskellProjectTypeBasic, HaskellProjectTypeServer),
1616
JavaOptions (JavaOptions),
1717
ProjectType
1818
( Elm,
@@ -79,6 +79,8 @@ buildExprFor srcDir projectName = \case
7979
Elm _ -> Nothing
8080
Haskell (HaskellOptions _ (HaskellProjectTypeBasic (SetUpHaskellBuild True))) ->
8181
Just . reproducibleHaskellBuild projectName $ srcDirExpr srcDir
82+
Haskell (HaskellOptions _ (HaskellProjectTypeServer (SetUpHaskellBuild True))) ->
83+
Just . reproducibleHaskellBuild projectName $ srcDirExpr srcDir
8284
Haskell _ -> Nothing
8385
Node _ -> Nothing
8486
Go (SetUpGoBuild True) -> Just $ reproducibleGoBuild projectName

src/Bootstrap/Data/Bootstrappable/FlakeNix.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import Bootstrap.Data.ProjectType
2222
( ElmMode (ElmModeBare, ElmModeNode),
2323
ElmOptions (elmOptionElmMode),
2424
HaskellOptions (HaskellOptions),
25-
HaskellProjectType (HaskellProjectTypeBasic, HaskellProjectTypeReplOnly),
25+
HaskellProjectType (HaskellProjectTypeBasic, HaskellProjectTypeReplOnly, HaskellProjectTypeServer),
2626
InstallMinishift (unInstallMinishift),
2727
JavaOptions (JavaOptions),
2828
JdkPackage (GraalVM, OpenJDK),
@@ -130,6 +130,7 @@ flakeNixFor
130130
( case haskellProjectType of
131131
HaskellProjectTypeReplOnly -> [[nixident|cabal-install|]]
132132
HaskellProjectTypeBasic _ -> [[nixident|cabal-install|], [nixident|haskell-language-server|]]
133+
HaskellProjectTypeServer _ -> [[nixident|cabal-install|], [nixident|haskell-language-server|]]
133134
)
134135
]
135136
Node _ -> []

src/Bootstrap/Data/Bootstrappable/Haskell/LibHs.hs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,16 @@ import Bootstrap.Data.Bootstrappable
1515
)
1616
import Bootstrap.Data.ProjectType
1717
( HaskellOptions (HaskellOptions),
18-
HaskellProjectType (HaskellProjectTypeBasic, HaskellProjectTypeReplOnly),
18+
HaskellProjectType (HaskellProjectTypeBasic, HaskellProjectTypeReplOnly, HaskellProjectTypeServer),
1919
ProjectType (Haskell),
2020
)
2121
import Control.Lens ((?~))
22+
import Language.Haskell.TH (conT, varE)
2223
import Language.Haskell.TH.Syntax
2324
( Body (NormalB),
2425
Clause (Clause),
2526
Dec (FunD, SigD),
26-
Exp (AppE, VarE),
2727
ModName (ModName),
28-
Type (AppT, ConT),
2928
mkName,
3029
)
3130

@@ -36,19 +35,18 @@ instance Bootstrappable LibHs where
3635
bootstrapReason = const "The entrypoint of your haskell library"
3736
bootstrapContent LibHs = do
3837
let lib = mkName "lib"
39-
errorFunc = mkName "error"
40-
io = mkName "IO"
41-
unitType <- [t|()|]
42-
errorLine <- AppE (VarE errorFunc) <$> [|"todo: write the body of the lib function in src/Lib.hs"|]
38+
ioUnit <- [t|$(conT $ mkName "IO") ()|]
39+
errorLine <- [|$(varE $ mkName "error") "todo: write the body of the lib function in src/Lib.hs"|]
4340
pure . pure . bootstrapContentHaskell $
4441
haskellModule (ModName "Lib") (one "lib")
4542
& haskellModuleDecs
46-
?~ SigD lib (AppT (ConT io) unitType)
43+
?~ SigD lib ioUnit
4744
:| [FunD lib [Clause [] (NormalB errorLine) []]]
4845

4946
libHsFor :: ProjectType -> Maybe LibHs
5047
libHsFor = \case
5148
Haskell (HaskellOptions _ haskellProjectType) -> case haskellProjectType of
5249
HaskellProjectTypeReplOnly -> Nothing
5350
HaskellProjectTypeBasic _ -> Just LibHs
51+
HaskellProjectTypeServer _ -> Nothing
5452
_ -> Nothing
Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# LANGUAGE QuasiQuotes #-}
12
{-# LANGUAGE TemplateHaskellQuotes #-}
23

34
-- | Copyright : (c) Crown Copyright GCHQ
@@ -17,41 +18,65 @@ import Bootstrap.Data.Bootstrappable
1718
)
1819
import Bootstrap.Data.ProjectType
1920
( HaskellOptions (HaskellOptions),
20-
HaskellProjectType (HaskellProjectTypeBasic, HaskellProjectTypeReplOnly),
21+
HaskellProjectType (HaskellProjectTypeBasic, HaskellProjectTypeReplOnly, HaskellProjectTypeServer),
2122
ProjectType (Haskell),
2223
)
2324
import Control.Lens ((?~))
25+
import Language.Haskell.TH (appE, conT, varE)
2426
import Language.Haskell.TH.Syntax
2527
( Body (NormalB),
2628
Clause (Clause),
2729
Dec (FunD, SigD),
28-
Exp (VarE),
30+
Exp (DoE, VarE),
2931
ModName (ModName),
30-
Type (AppT, ConT),
32+
Stmt (NoBindS),
3133
mkName,
3234
)
3335

34-
data MainHs = MainHs
36+
data MainHs
37+
= -- | Simply calls Lib.lib
38+
MainHsLib
39+
| -- | Uses Server.app (a WAI Application) to run a warp server on port 8080
40+
MainHsWarp
3541

3642
instance Bootstrappable MainHs where
3743
bootstrapName = const "app/Main.hs"
3844
bootstrapReason = const "The entrypoint of your haskell executable"
39-
bootstrapContent MainHs = do
40-
let main = mkName "main"
41-
io = mkName "IO"
45+
bootstrapContent mainHs = do
46+
let app = mkName "app"
4247
lib = mkName "lib"
43-
unitType <- [t|()|]
48+
main = mkName "main"
49+
run = mkName "run"
50+
ioUnit <- [t|$(conT $ mkName "IO") ()|]
51+
logServing <- [|putTextLn "Serving on 8080..."|]
52+
runServer <- varE run `appE` [|8080|] `appE` varE app
4453
pure . pure . bootstrapContentHaskell $
4554
haskellModule (ModName "Main") (one "main")
4655
& haskellModuleImports
47-
?~ one (HaskellImport (ModName "Lib") [lib])
56+
?~ ( case mainHs of
57+
MainHsLib -> one (HaskellImport (ModName "Lib") ["lib"])
58+
MainHsWarp ->
59+
HaskellImport (ModName "Network.Wai.Handler.Warp") ["run"]
60+
:| [HaskellImport (ModName "Server") ["app"]]
61+
)
4862
& haskellModuleDecs
49-
?~ SigD main (AppT (ConT io) unitType)
50-
:| [FunD main [Clause [] (NormalB $ VarE lib) []]]
63+
?~ SigD main ioUnit
64+
:| [ FunD
65+
main
66+
[ Clause
67+
[]
68+
( NormalB $ case mainHs of
69+
MainHsLib -> VarE lib
70+
MainHsWarp -> DoE Nothing [NoBindS logServing, NoBindS runServer]
71+
)
72+
[]
73+
]
74+
]
5175

5276
mainHsFor :: ProjectType -> Maybe MainHs
5377
mainHsFor = \case
5478
Haskell (HaskellOptions _ haskellProjectType) -> case haskellProjectType of
5579
HaskellProjectTypeReplOnly -> Nothing
56-
HaskellProjectTypeBasic _ -> Just MainHs
80+
HaskellProjectTypeBasic _ -> Just MainHsLib
81+
HaskellProjectTypeServer _ -> Just MainHsWarp
5782
_ -> Nothing

0 commit comments

Comments
 (0)