Skip to content

Instantly share code, notes, and snippets.

@ingenieroariel
Last active July 24, 2020 20:47
Show Gist options
  • Save ingenieroariel/ca5cd6bc3f0e382e00c1b4982b4f2dc6 to your computer and use it in GitHub Desktop.
Save ingenieroariel/ca5cd6bc3f0e382e00c1b4982b4f2dc6 to your computer and use it in GitHub Desktop.

nix develop gives you the hability to do runghc or ghcide or ghci. nix shell gives you the ability to just invoke app and have the running application. nix run does nothing, but if you are a Nix committer and you are reading this, can you help?

No binary cache setup is needed to start developing, but you will likely need the official Obelisk to create the android and ios apps.

In order to compile this locally I copied over the Obelisk sources to my project folder. Can Obelisk packages be available in hackage?

module Backend where
import Obelisk.Backend
import Route
backend :: Backend BackendRoute FrontendRoute
backend = Backend
{ _backend_run = \serve -> serve $ const $ return ()
, _backend_routeEncoder = fullRouteEncoder
}
diff --git a/snap-core.cabal b/snap-core.cabal
index 3188e87..ac3fe53 100644
--- a/snap-core.cabal
+++ b/snap-core.cabal
@@ -112,6 +112,7 @@ Library
Snap.Internal.Debug,
Snap.Internal.Http.Types,
Snap.Internal.Parsing,
+ Snap.Internal.Util.FileServe
Snap.Test,
Snap.Types.Headers,
Snap.Util.CORS,
@@ -125,7 +126,6 @@ Library
Snap.Internal.Routing,
Snap.Internal.Test.RequestBuilder,
Snap.Internal.Test.Assertions,
- Snap.Internal.Util.FileServe,
Snap.Internal.Util.FileUploads
diff --git a/src/Snap/Internal/Util/FileServe.hs b/src/Snap/Internal/Util/FileServe.hs
index 447223c..fef6bcd 100644
--- a/src/Snap/Internal/Util/FileServe.hs
+++ b/src/Snap/Internal/Util/FileServe.hs
@@ -24,6 +24,7 @@ module Snap.Internal.Util.FileServe
, serveFileAs
-- * Internal functions
, decodeFilePath
+ , checkRangeReq
) where
------------------------------------------------------------------------------
{
description = "Basic haskell flake";
inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-unstable;
outputs = { self, nixpkgs }: {
defaultPackage.x86_64-linux =
with import nixpkgs { system = "x86_64-linux"; };
let
haskellDeps = ps: with ps; [
reflex-dom
ghcide
categories
cookie
either
ref-tf
snap
snap-server
modern-uri
websockets
warp
warp-tls
http-reverse-proxy
jsaddle
jsaddle-warp
(pkgs.haskell.lib.appendPatch snap-core ./check-range.patch)
monad-control
universe
universe-dependent-sum
];
ghc = pkgs.haskellPackages.ghcWithPackages haskellDeps;
in
stdenv.mkDerivation {
name = "app";
buildInputs = [ ghc pkgs.ghcid ];
src = self;
buildPhase = "ghc -o $name Main.hs";
installPhase = "mkdir -p $out/bin; install -t $out/bin $name";
};
};
}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
module Frontend where
import Control.Monad
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Language.Javascript.JSaddle (eval, liftJSM)
import Obelisk.Frontend
import Obelisk.Configs
import Obelisk.Route
import Reflex.Dom.Core
import Api
import Route
-- This runs in a monad that can be run on the client or the server.
-- To run code in a pure client or pure server context, use one of the
-- `prerender` functions.
frontend :: Frontend (R FrontendRoute)
frontend = Frontend
{ _frontend_head = do
el "title" $ text "Obelisk Minimal Example"
, _frontend_body = do
el "h1" $ text "Welcome to Obelisk!"
el "p" $ text $ T.pack commonStuff
-- `prerender` and `prerender_` let you choose a widget to run on the server
-- during prerendering and a different widget to run on the client with
-- JavaScript. The following will generate a `blank` widget on the server and
-- print "Hello, World!" on the client.
prerender_ blank $ liftJSM $ void $ eval ("console.log('Hello, World!')" :: T.Text)
el "div" $ do
exampleConfig <- getConfig "common/example"
case exampleConfig of
Nothing -> text "No config file found in config/common/example"
Just s -> text $ T.decodeUtf8 s
return ()
}
x@sensei ~/f/rf (master)> nix develop
[x@sensei:~/frp/rf]$ ghci
GHCi, version 8.8.3: https://www.haskell.org/ghc/ :? for help
Prelude> :l Main.hs
[ 1 of 20] Compiling Api ( Api.hs, interpreted )
[ 2 of 20] Compiling Data.Tabulation ( Data/Tabulation.hs, interpreted )
[ 3 of 20] Compiling Obelisk.Asset.Accept ( Obelisk/Asset/Accept.hs, interpreted )
[ 4 of 20] Compiling Obelisk.Configs ( Obelisk/Configs.hs, interpreted )
[ 5 of 20] Compiling Obelisk.Configs.Internal.Directory ( Obelisk/Configs/Internal/Directory.hs, interpreted )
[ 6 of 20] Compiling Obelisk.ExecutableConfig.Inject ( Obelisk/ExecutableConfig/Inject.hs, interpreted )
[ 7 of 20] Compiling Obelisk.ExecutableConfig.Lookup ( Obelisk/ExecutableConfig/Lookup.hs, interpreted )
[ 8 of 20] Compiling Obelisk.Route.TH ( Obelisk/Route/TH.hs, interpreted )
[ 9 of 20] Compiling Obelisk.Route ( Obelisk/Route.hs, interpreted )
[10 of 20] Compiling Obelisk.Route.Frontend ( Obelisk/Route/Frontend.hs, interpreted )
[11 of 20] Compiling Obelisk.Frontend.Cookie ( Obelisk/Frontend/Cookie.hs, interpreted )
[12 of 20] Compiling Obelisk.Frontend ( Obelisk/Frontend.hs, interpreted )
[13 of 20] Compiling Obelisk.Snap.Extras ( Obelisk/Snap/Extras.hs, interpreted )
[14 of 20] Compiling Obelisk.Asset.Serve.Snap ( Obelisk/Asset/Serve/Snap.hs, interpreted )
[15 of 20] Compiling Obelisk.Backend ( Obelisk/Backend.hs, interpreted )
[16 of 20] Compiling Obelisk.Run ( Obelisk/Run.hs, interpreted )
[17 of 20] Compiling Route ( Route.hs, interpreted )
[18 of 20] Compiling Frontend ( Frontend.hs, interpreted )
[19 of 20] Compiling Backend ( Backend.hs, interpreted )
[20 of 20] Compiling Main ( Main.hs, interpreted )
Ok, 20 modules loaded.
*Main> main
Frontend running on http://localhost:8000/
module Main where
import Backend (backend)
import Frontend (frontend)
import Obelisk.Run (run, runServeAsset)
main = run 8001 (runServeAsset "static") backend frontend
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
module Route where
{- -- You will probably want these imports for composing Encoders.
import Prelude hiding (id, (.))
import Control.Category
-}
import Data.Text (Text)
import Data.Functor.Identity
import Obelisk.Route
import Obelisk.Route.TH
data BackendRoute :: * -> * where
-- | Used to handle unparseable routes.
BackendRoute_Missing :: BackendRoute ()
-- You can define any routes that will be handled specially by the backend here.
-- i.e. These do not serve the frontend, but do something different, such as serving static files.
data FrontendRoute :: * -> * where
FrontendRoute_Main :: FrontendRoute ()
-- This type is used to define frontend routes, i.e. ones for which the backend will serve the frontend.
fullRouteEncoder
:: Encoder (Either Text) Identity (R (FullRoute BackendRoute FrontendRoute)) PageName
fullRouteEncoder = mkFullRouteEncoder
(FullRoute_Backend BackendRoute_Missing :/ ())
(\case
BackendRoute_Missing -> PathSegment "missing" $ unitEncoder mempty)
(\case
FrontendRoute_Main -> PathEnd $ unitEncoder mempty)
concat <$> mapM deriveRouteComponent
[ ''BackendRoute
, ''FrontendRoute
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment