init nix-features
This commit is contained in:
parent
d04ddd4c32
commit
b929e21f82
14 changed files with 1646 additions and 61 deletions
37
elm.json
Normal file
37
elm.json
Normal file
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"type": "application",
|
||||
"source-directories": [
|
||||
"src"
|
||||
],
|
||||
"elm-version": "0.19.1",
|
||||
"dependencies": {
|
||||
"direct": {
|
||||
"NoRedInk/elm-json-decode-pipeline": "1.0.1",
|
||||
"bartavelle/json-helpers": "2.0.2",
|
||||
"elm/browser": "1.0.2",
|
||||
"elm/core": "1.0.5",
|
||||
"elm/html": "1.0.0",
|
||||
"elm/json": "1.1.3",
|
||||
"elm/time": "1.0.0",
|
||||
"elm/url": "1.0.0",
|
||||
"lobanov/elm-localstorage": "1.0.1",
|
||||
"rtfeldman/elm-css": "18.0.0",
|
||||
"rtfeldman/elm-iso8601-date-strings": "1.1.4"
|
||||
},
|
||||
"indirect": {
|
||||
"elm/bytes": "1.0.8",
|
||||
"elm/file": "1.0.5",
|
||||
"elm/http": "2.0.0",
|
||||
"elm/parser": "1.1.0",
|
||||
"elm/random": "1.0.0",
|
||||
"elm/virtual-dom": "1.0.3",
|
||||
"lobanov/elm-taskport": "2.0.1",
|
||||
"robinheghan/murmur3": "1.0.0",
|
||||
"rtfeldman/elm-hex": "1.0.0"
|
||||
}
|
||||
},
|
||||
"test-dependencies": {
|
||||
"direct": {},
|
||||
"indirect": {}
|
||||
}
|
||||
}
|
34
elmskell-frontend.nix
Normal file
34
elmskell-frontend.nix
Normal file
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
esbuild,
|
||||
stdenv,
|
||||
elmPackages,
|
||||
...
|
||||
}: let
|
||||
elmConfig = elmPackages.fetchElmDeps {
|
||||
elmPackages = import ./frontend/elm-srcs.nix;
|
||||
elmVersion = "0.19.1";
|
||||
registryDat = ./frontend/registry.dat;
|
||||
};
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
pname = "elmskell-backend";
|
||||
version = "0.1.0";
|
||||
src = ./frontend;
|
||||
nativeBuildInputs = [
|
||||
esbuild
|
||||
elmPackages.elm
|
||||
];
|
||||
buildInputs = [
|
||||
];
|
||||
configurePhase = ''
|
||||
${elmConfig}
|
||||
'';
|
||||
buildPhase = ''
|
||||
elm make src/Main.elm --optimize --output=tmp.js
|
||||
esbuild tmp.js --minify --target=es5 --outfile=main.js
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
cp main.js $out/main.js
|
||||
'';
|
||||
}
|
26
flake.lock
generated
Normal file
26
flake.lock
generated
Normal file
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1748708770,
|
||||
"narHash": "sha256-q8jG2HJWgooWa9H0iatZqBPF3bp0504e05MevFmnFLY=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a59eb7800787c926045d51b70982ae285faa2346",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-25.05",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
14
flake.nix
Normal file
14
flake.nix
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "nixpkgs/nixos-25.05";
|
||||
};
|
||||
outputs = {nixpkgs, ...}: let
|
||||
system = "x86_64-linux";
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
in {
|
||||
packages.${system} = {
|
||||
default = pkgs.callPackage ./package.nix {};
|
||||
frontend = pkgs.callPackage ./elmskell-frontend.nix {};
|
||||
};
|
||||
};
|
||||
}
|
102
frontend/elm-srcs.nix
Normal file
102
frontend/elm-srcs.nix
Normal file
|
@ -0,0 +1,102 @@
|
|||
{
|
||||
|
||||
"NoRedInk/elm-json-decode-pipeline" = {
|
||||
sha256 = "1k241pjz1wj5rqv95f1j86msa0s0p6w4v8n0jn26aw6cbadw363b";
|
||||
version = "1.0.1";
|
||||
};
|
||||
|
||||
"bartavelle/json-helpers" = {
|
||||
sha256 = "0k96qra2nq1j4j4ahfl98dkpkc6f2831mq5d5xxg27mp31qwq5nn";
|
||||
version = "2.0.2";
|
||||
};
|
||||
|
||||
"elm/browser" = {
|
||||
sha256 = "0nagb9ajacxbbg985r4k9h0jadqpp0gp84nm94kcgbr5sf8i9x13";
|
||||
version = "1.0.2";
|
||||
};
|
||||
|
||||
"elm/core" = {
|
||||
sha256 = "19w0iisdd66ywjayyga4kv2p1v9rxzqjaxhckp8ni6n8i0fb2dvf";
|
||||
version = "1.0.5";
|
||||
};
|
||||
|
||||
"elm/html" = {
|
||||
sha256 = "1n3gpzmpqqdsldys4ipgyl1zacn0kbpc3g4v3hdpiyfjlgh8bf3k";
|
||||
version = "1.0.0";
|
||||
};
|
||||
|
||||
"elm/json" = {
|
||||
sha256 = "0kjwrz195z84kwywaxhhlnpl3p251qlbm5iz6byd6jky2crmyqyh";
|
||||
version = "1.1.3";
|
||||
};
|
||||
|
||||
"elm/time" = {
|
||||
sha256 = "0vch7i86vn0x8b850w1p69vplll1bnbkp8s383z7pinyg94cm2z1";
|
||||
version = "1.0.0";
|
||||
};
|
||||
|
||||
"elm/url" = {
|
||||
sha256 = "0av8x5syid40sgpl5vd7pry2rq0q4pga28b4yykn9gd9v12rs3l4";
|
||||
version = "1.0.0";
|
||||
};
|
||||
|
||||
"lobanov/elm-localstorage" = {
|
||||
sha256 = "00n3hk6gzrg637n4vfwk7arbj78bppqjn0mcnl7yp2ypva971dia";
|
||||
version = "1.0.1";
|
||||
};
|
||||
|
||||
"rtfeldman/elm-css" = {
|
||||
sha256 = "1gwhgqwclc7clk1ns4qqzyn7b4wvcmccg9qavvb8m694qmwlkzjy";
|
||||
version = "18.0.0";
|
||||
};
|
||||
|
||||
"rtfeldman/elm-iso8601-date-strings" = {
|
||||
sha256 = "1ah491kgyicgvy1c9myylqvhzb7ya9kgmn0hcsv23ymvqgaf6b1a";
|
||||
version = "1.1.4";
|
||||
};
|
||||
|
||||
"elm/bytes" = {
|
||||
sha256 = "02ywbf52akvxclpxwj9n04jydajcbsbcbsnjs53yjc5lwck3abwj";
|
||||
version = "1.0.8";
|
||||
};
|
||||
|
||||
"elm/file" = {
|
||||
sha256 = "1rljcb41dl97myidyjih2yliyzddkr2m7n74x7gg46rcw4jl0ny8";
|
||||
version = "1.0.5";
|
||||
};
|
||||
|
||||
"elm/http" = {
|
||||
sha256 = "008bs76mnp48b4dw8qwjj4fyvzbxvlrl4xpa2qh1gg2kfwyw56v1";
|
||||
version = "2.0.0";
|
||||
};
|
||||
|
||||
"elm/parser" = {
|
||||
sha256 = "0a3cxrvbm7mwg9ykynhp7vjid58zsw03r63qxipxp3z09qks7512";
|
||||
version = "1.1.0";
|
||||
};
|
||||
|
||||
"elm/random" = {
|
||||
sha256 = "138n2455wdjwa657w6sjq18wx2r0k60ibpc4frhbqr50sncxrfdl";
|
||||
version = "1.0.0";
|
||||
};
|
||||
|
||||
"elm/virtual-dom" = {
|
||||
sha256 = "1yvb8px2z62xd578ag2q0r5hd1vkz9y7dfkx05355iiy1d7jwq4v";
|
||||
version = "1.0.3";
|
||||
};
|
||||
|
||||
"lobanov/elm-taskport" = {
|
||||
sha256 = "16vf3k80sicmhnr1k2nmdc9713ips7nyaxzjzkb6w8mi5w4qsmc0";
|
||||
version = "2.0.1";
|
||||
};
|
||||
|
||||
"robinheghan/murmur3" = {
|
||||
sha256 = "15asmgr2zqh7rkywrg5647rpdqkpzxk02v5qc6ndj60jza3gsmjk";
|
||||
version = "1.0.0";
|
||||
};
|
||||
|
||||
"rtfeldman/elm-hex" = {
|
||||
sha256 = "1y0aa16asvwdqmgbskh5iba6psp43lkcjjw9mgzj3gsrg33lp00d";
|
||||
version = "1.0.0";
|
||||
};
|
||||
}
|
BIN
frontend/registry.dat
Normal file
BIN
frontend/registry.dat
Normal file
Binary file not shown.
32
justfile
32
justfile
|
@ -1,32 +0,0 @@
|
|||
produce: produce-elm haskell
|
||||
echo "REMEMBER to RESTART elmskell.service TO UPDATE SITE IN PLACE"
|
||||
echo "REMEMBER to RUN sudo iptables-apply -t 60 /etc/iptables/iptables.rules IF YOU HAVEN'T SINCE RESTART"
|
||||
|
||||
types: haskell
|
||||
rm -rf frontend/src/ElmskellTypes/Generated
|
||||
stack exec ~/.local/bin/hs-server-exe
|
||||
|
||||
compile: elm haskell
|
||||
|
||||
run: produce exec
|
||||
|
||||
exec:
|
||||
stack exec ~/.local/bin/hs-server-exe
|
||||
|
||||
haskell:
|
||||
cd backend && stack install
|
||||
|
||||
elm:
|
||||
cd frontend && elm make src/Main.elm --output=../assets/js/main.js
|
||||
rm -rf frontend/elm-stuff
|
||||
|
||||
produce-elm:
|
||||
cd frontend && elm make src/Main.elm --optimize --output=tmp.js
|
||||
mv frontend/tmp.js assets/js/tmp.js
|
||||
rm -rf frontend/elm-stuff
|
||||
rm assets/js/main.js
|
||||
esbuild assets/js/tmp.js --minify --target=es5 --outfile=assets/js/main.js
|
||||
rm assets/js/tmp.js
|
||||
|
||||
format-elm:
|
||||
elm-format frontend/src/Main.elm --yes
|
53
package.nix
Normal file
53
package.nix
Normal file
|
@ -0,0 +1,53 @@
|
|||
{
|
||||
esbuild,
|
||||
elmPackages,
|
||||
haskellPackages,
|
||||
stdenv,
|
||||
...
|
||||
}: let
|
||||
ghcExeOptions = "-Wall -Wcompact -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N";
|
||||
ghcPackages = p: [
|
||||
p.aeson
|
||||
p.blaze-html
|
||||
p.blaze-markup
|
||||
p.directory
|
||||
p.elm-street
|
||||
p.http-types
|
||||
p.scotty
|
||||
p.text
|
||||
p.wai-extra
|
||||
p.warp
|
||||
];
|
||||
elmConfig = elmPackages.fetchElmDeps {
|
||||
elmPackages = import ./frontend/elm-srcs.nix;
|
||||
elmVersion = "0.19.1";
|
||||
registryDat = ./frontend/registry.dat;
|
||||
};
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
pname = "elmskell";
|
||||
version = "0.1.0";
|
||||
src = ./src;
|
||||
nativeBuildInputs = [
|
||||
esbuild
|
||||
(haskellPackages.ghcWithPackages ghcPackages)
|
||||
elmPackages.elm
|
||||
];
|
||||
buildInputs = [
|
||||
];
|
||||
configurePhase = ''
|
||||
${elmConfig}
|
||||
'';
|
||||
buildPhase = ''
|
||||
ghc -v ${ghcExeOptions} ./Main.hs -o ./main
|
||||
elm make ./Main.elm --optimize --output=tmp.js
|
||||
esbuild ./tmp.js --minify --target=es5 --outfile=main.js
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
mkdir -p $out/src
|
||||
cp ./main $out/bin/elmskell
|
||||
cp ./main.js $out/src/main.js
|
||||
cp ./init.js $out/src/init.js
|
||||
'';
|
||||
}
|
1
result
Symbolic link
1
result
Symbolic link
|
@ -0,0 +1 @@
|
|||
/nix/store/afnd25aqbkrr55z46pld1yg1fdnv893w-elmskell-0.1.0
|
27
shell.nix
27
shell.nix
|
@ -1,27 +0,0 @@
|
|||
{pkgs ? import <nixpkgs> {}}: let
|
||||
elmInputs = [
|
||||
pkgs.elmPackages.elm
|
||||
pkgs.elmPackages.elm-format
|
||||
pkgs.esbuild
|
||||
];
|
||||
haskellInputs = [
|
||||
pkgs.stack
|
||||
];
|
||||
buildTools = [
|
||||
pkgs.just
|
||||
];
|
||||
cliTools = [
|
||||
pkgs.httpie
|
||||
pkgs.ungoogled-chromium
|
||||
];
|
||||
in
|
||||
pkgs.mkShell {
|
||||
buildInputs = [
|
||||
elmInputs
|
||||
haskellInputs
|
||||
];
|
||||
packages = [
|
||||
buildTools
|
||||
cliTools
|
||||
];
|
||||
}
|
98
src/ElmskellTypes.hs
Normal file
98
src/ElmskellTypes.hs
Normal file
|
@ -0,0 +1,98 @@
|
|||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE DeriveGeneric #-}
|
||||
{-# LANGUAGE DerivingStrategies #-}
|
||||
{-# LANGUAGE DerivingVia #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
|
||||
module ElmskellTypes (generateElmskellTypes) where
|
||||
|
||||
import Data.Aeson (ToJSON (..), FromJSON (..))
|
||||
import Elm
|
||||
import GHC.Generics
|
||||
|
||||
data Command
|
||||
= ClearCommand
|
||||
| ColorsCommand
|
||||
| CookiesCommand
|
||||
| DebugCommand
|
||||
| FontCommand
|
||||
| HelloCommand
|
||||
| HelpCommand
|
||||
| PromptCommand
|
||||
| ThemeCommand
|
||||
| TodoCommand
|
||||
deriving (Generic)
|
||||
deriving (Elm, ToJSON, FromJSON) via ElmStreet Command
|
||||
|
||||
data CookiesKept = CookiesKept
|
||||
{ cookiesKeptKeepFont :: Bool
|
||||
, cookiesKeptKeepPrompt :: Bool
|
||||
, cookiesKeptKeepTheme :: Bool
|
||||
} deriving (Generic)
|
||||
deriving (Elm, ToJSON, FromJSON) via ElmStreet CookiesKept
|
||||
|
||||
data CoreColor
|
||||
= Red
|
||||
| Green
|
||||
| Yellow
|
||||
| Blue
|
||||
| Magenta
|
||||
| Cyan
|
||||
| BrightRed
|
||||
| BrightGreen
|
||||
| BrightYellow
|
||||
| BrightBlue
|
||||
| BrightMagenta
|
||||
| BrightCyan
|
||||
deriving (Generic)
|
||||
deriving (Elm, ToJSON, FromJSON) via ElmStreet CoreColor
|
||||
|
||||
data Font = Font
|
||||
{ fontFontSize :: Float
|
||||
} deriving (Generic)
|
||||
deriving (Elm, ToJSON, FromJSON) via ElmStreet Font
|
||||
|
||||
data Input = Input
|
||||
{ inputCommand :: Command
|
||||
, inputArgs :: [String]
|
||||
}
|
||||
deriving (Generic)
|
||||
deriving (Elm, ToJSON, FromJSON) via ElmStreet Input
|
||||
|
||||
data Prompt = Prompt
|
||||
{ promptPrompt :: String
|
||||
} deriving (Generic)
|
||||
deriving (Elm, ToJSON, FromJSON) via ElmStreet Prompt
|
||||
|
||||
data Theme
|
||||
= Pit
|
||||
| Dim
|
||||
| Sky
|
||||
| Sun
|
||||
deriving (Generic)
|
||||
deriving (Elm, ToJSON, FromJSON) via ElmStreet Theme
|
||||
|
||||
data ThemeColor
|
||||
= Background
|
||||
| Foreground
|
||||
| Cursor
|
||||
| Black
|
||||
| White
|
||||
| BrightBlack
|
||||
| BrightWhite
|
||||
deriving (Generic)
|
||||
deriving (Elm, ToJSON, FromJSON) via ElmStreet ThemeColor
|
||||
|
||||
type Types =
|
||||
'[Command
|
||||
, CookiesKept
|
||||
, CoreColor
|
||||
, Font
|
||||
, Input
|
||||
, Prompt
|
||||
, Theme
|
||||
, ThemeColor
|
||||
]
|
||||
|
||||
generateElmskellTypes :: IO ()
|
||||
generateElmskellTypes = generateElm @Types $ defaultSettings "frontend/src" ["ElmskellTypes", "Generated"]
|
|
@ -1 +0,0 @@
|
|||
../frontend/src/Main.elm
|
1173
src/Main.elm
Normal file
1173
src/Main.elm
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1 +0,0 @@
|
|||
../backend/app/Main.hs
|
108
src/Main.hs
Normal file
108
src/Main.hs
Normal file
|
@ -0,0 +1,108 @@
|
|||
{-# LANGUAGE DeriveGeneric #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
module Main (main) where
|
||||
|
||||
import ElmskellTypes
|
||||
import Data.Text.Lazy (Text)
|
||||
import Network.Wai.Handler.Warp (Port)
|
||||
import Network.Wai.Middleware.RequestLogger (logStdoutDev)
|
||||
import Text.Blaze ((!))
|
||||
import Text.Blaze.Html.Renderer.Text (renderHtml)
|
||||
|
||||
import Network.HTTP.Types
|
||||
import Network.Wai.Middleware.Gzip
|
||||
import Web.Scotty as S
|
||||
|
||||
import qualified Control.Exception as E
|
||||
import qualified Text.Blaze.Html5 as H
|
||||
import qualified Text.Blaze.Html5.Attributes as A
|
||||
|
||||
-- HTML
|
||||
index :: H.Html -> Text
|
||||
index compiledElmApp = renderHtml $ do
|
||||
H.docTypeHtml $ do
|
||||
H.head $ do
|
||||
H.title "TESTING Scotty+Elm"
|
||||
H.meta ! A.charset "utf-8"
|
||||
H.style "body{margin:0px;}"
|
||||
(H.body ! A.id "body") $ do
|
||||
embedJs compiledElmApp
|
||||
|
||||
-- CONF
|
||||
port :: Port
|
||||
port = 8080
|
||||
|
||||
adminContact :: String
|
||||
adminContact = "[Matrix] @mtgmonkey:calitabby.net"
|
||||
|
||||
compiledElmAppFile :: AssetPath
|
||||
compiledElmAppFile = "/js/main.js"
|
||||
|
||||
boilerplateJsFile :: AssetPath
|
||||
boilerplateJsFile = "/js/init.js"
|
||||
|
||||
assetsFolder :: FilePath
|
||||
assetsFolder = "/home/mtgmonkey/elmskell/assets"
|
||||
|
||||
-- MAIN
|
||||
main :: IO ()
|
||||
main = do
|
||||
|
||||
generateElmskellTypes
|
||||
|
||||
compiledElmAppOrExc <- E.try $ readFile $ assetsFolder ++ compiledElmAppFile :: IO (Either E.IOException String)
|
||||
let compiledElmApp = case compiledElmAppOrExc of
|
||||
Left e -> serverErrorReadFile e
|
||||
Right contents -> H.toHtml $ contents
|
||||
|
||||
boilerplateJsOrExc <- E.try $ readFile $ assetsFolder ++ boilerplateJsFile :: IO (Either E.IOException String)
|
||||
let boilerplateJs = case boilerplateJsOrExc of
|
||||
Left e -> serverErrorReadFile e
|
||||
Right contents -> H.toHtml $ contents
|
||||
|
||||
let anyRoute = regex "^.*$"
|
||||
scotty port $ do
|
||||
|
||||
middleware $ gzip $ def { gzipFiles = GzipCompress }
|
||||
middleware logStdoutDev
|
||||
|
||||
-- GET requests
|
||||
get "/" $ do
|
||||
shortCache
|
||||
status ok200
|
||||
S.html $ index $ do
|
||||
compiledElmApp
|
||||
boilerplateJs
|
||||
|
||||
get "/favicon.ico/" $ do
|
||||
shortCache
|
||||
status notFound404
|
||||
S.html $ "you want a favi-<i>what</i>now!?"
|
||||
|
||||
-- ERR
|
||||
notFound $ do
|
||||
noCache
|
||||
status methodNotAllowed405
|
||||
S.text "Verb disallowed; OR, route doesn't exist :("
|
||||
|
||||
|
||||
-- FUNC
|
||||
serverErrorReadFile :: E.IOException -> Js
|
||||
serverErrorReadFile e = H.toHtml $ "document.getElementById('body').innerHTML='Server-side error occurred: "
|
||||
++ (show e)
|
||||
++ "; report this to a site administrator: "
|
||||
++ adminContact
|
||||
++ "';"
|
||||
|
||||
shortCache :: ActionM ()
|
||||
shortCache = addHeader "Cache-Control" "max-age=21600"
|
||||
|
||||
noCache :: ActionM ()
|
||||
noCache = addHeader "Cache-Control" "no-cache"
|
||||
|
||||
embedJs :: Js -> H.Html
|
||||
embedJs js = H.script $ js
|
||||
|
||||
-- TYPES
|
||||
type AssetPath = FilePath
|
||||
type Js = H.Html
|
Loading…
Add table
Add a link
Reference in a new issue