diff --git a/.travis.yml b/.travis.yml index c8accca..1825fbe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,4 +8,5 @@ before_script: - mkdir -p ~/.config/nixpkgs script: - - nix-build ./release.nix -A backend --option trusted-public-keys "masser-ebook-manager.cachix.org-1:mtFSkQ2MO5MvjUpulZoFKjKUIa8g8CTcdPVuJaPKS1w= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" --option binary-caches "https://cache.nixos.org https://masser-ebook-manager.cachix.org" + - nix-build ./release.nix --option trusted-public-keys "masser-ebook-manager.cachix.org-1:mtFSkQ2MO5MvjUpulZoFKjKUIa8g8CTcdPVuJaPKS1w= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" --option binary-caches "https://masser-ebook-manager.cachix.org https://cache.nixos.org" -A ghc.backend -A ghc.frontend + - nix-build ./release.nix --option trusted-public-keys "masser-ebook-manager.cachix.org-1:mtFSkQ2MO5MvjUpulZoFKjKUIa8g8CTcdPVuJaPKS1w= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" --option binary-caches "https://masser-ebook-manager.cachix.org https://cache.nixos.org" -A ghcjs.frontend diff --git a/backend/src/API.hs b/backend/src/API.hs index 7ac4389..ceb52c7 100644 --- a/backend/src/API.hs +++ b/backend/src/API.hs @@ -1,27 +1,27 @@ -{-# Language DataKinds #-} -{-# Language TypeFamilies #-} -{-# Language TypeOperators #-} -{-# Language NoImplicitPrelude #-} -{-# Language MultiParamTypeClasses #-} -{-# Language OverloadedStrings #-} -{-# Language TemplateHaskell #-} -{-# Language QuasiQuotes #-} -{-# Language RecordWildCards #-} -{-# Language DeriveGeneric #-} -{-# Language FlexibleInstances #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE QuasiQuotes #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeOperators #-} module API (API, handler) where -import Servant -import Servant.HTML.Lucid (HTML) -import Types +import Servant +import Servant.HTML.Lucid (HTML) +import Types -import View +import View -import qualified API.Users as Users -import qualified API.Channels as Channels -import qualified API.Books as Books -import qualified API.Catalogue as Catalogue +import qualified API.Books as Books +import qualified API.Catalogue as Catalogue +import qualified API.Channels as Channels +import qualified API.Users as Users data Index = Index diff --git a/default.nix b/default.nix index c85da76..c4bca78 100644 --- a/default.nix +++ b/default.nix @@ -1,12 +1,59 @@ { nixpkgs, haskellPackages }: +let + miso = nixpkgs.fetchFromGitHub { + owner = "dmjio"; + repo = "miso"; + rev = "630e823dd40a434b73124e12b229a79d9fefb01d"; + sha256 = "046gdp3ah2lsipfcy89rh20mn08xbhcgrj549v8zzy69j33xjm2l"; + }; + miso-jsaddle = super: if haskellPackages.ghc.isGhcjs or false then (super.callPackage (miso + "/miso-ghcjs.nix") {}) else (super.callPackage (miso + "/miso-ghc-jsaddle.nix") {}); + + dontCheck = nixpkgs.haskell.lib.dontCheck; + +in + (import ./project.nix nixpkgs) { + haskellPackages = haskellPackages; packages = { common = ./common; backend = ./backend; + frontend = ./frontend; }; overrides = self: super: { generic-lens = nixpkgs.haskell.lib.dontCheck super.generic-lens; + miso = miso-jsaddle super; + # doctest = null; # Not compilable with ghcjs + # comonad = dontCheck super.comonad; + # Glob = dontCheck super.Glob; + # SHA = dontCheck super.SHA; + # iproute = dontCheck super.iproute; + # semigroupoids = dontCheck super.semigroupoids; + # wai-app-static = dontCheck super.wai-app-static; + # attoparsec = dontCheck super.attoparsec; + # http-date = dontCheck super.http-date; + # lens = dontCheck super.lens; + # unix-time = dontCheck super.unix-time; + # http-types = dontCheck super.http-types; + # servant = dontCheck super.servant; + # servant-server = dontCheck super.servant-server; + # servant-auth-docs = dontCheck super.servant-auth-docs; + # lens-aeson = dontCheck super.lens-aeson; + # word8 = dontCheck super.word8; + # http2 = dontCheck super.http2; + # wai-extra = dontCheck super.wai-extra; + # pgp-wordlist = dontCheck super.pgp-wordlist; + # prettyprinter = dontCheck super.prettyprinter; + # unliftio = dontCheck super.unliftio; + # prettyprinter-ansi-terminal = dontCheck super.prettyprinter-ansi-terminal; + # distributive = dontCheck super.distributive; + # genvalidity-property = dontCheck super.genvalidity-property; + # genvalidity-hspec = dontCheck super.genvalidity-hspec; + # genvalidity = dontCheck super.genvalidity; + # megaparsec = dontCheck super.megaparsec; + # ncurses = null; + # haskeline = super.callHackage "haskeline" "0.7.4.2" {}; + # terminfo = super.callHackage "terminfo" "0.4.1.1" {}; }; tools = with haskellPackages; [ ghcid diff --git a/frontend/ChangeLog.md b/frontend/ChangeLog.md new file mode 100644 index 0000000..231ccd6 --- /dev/null +++ b/frontend/ChangeLog.md @@ -0,0 +1,5 @@ +# Revision history for frontend + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/frontend/LICENSE b/frontend/LICENSE new file mode 100644 index 0000000..00aedcc --- /dev/null +++ b/frontend/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2018, Mats Rauhala + +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. + + * Neither the name of Mats Rauhala nor the names of other + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"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 +OWNER OR CONTRIBUTORS 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/frontend/Setup.hs b/frontend/Setup.hs new file mode 100644 index 0000000..9a994af --- /dev/null +++ b/frontend/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/frontend/frontend.cabal b/frontend/frontend.cabal new file mode 100644 index 0000000..5d63e6e --- /dev/null +++ b/frontend/frontend.cabal @@ -0,0 +1,27 @@ +-- Initial frontend.cabal generated by cabal init. For further +-- documentation, see http://haskell.org/cabal/users-guide/ + +name: frontend +version: 0.1.0.0 +-- synopsis: +-- description: +license: BSD3 +license-file: LICENSE +author: Mats Rauhala +maintainer: mats.rauhala@iki.fi +-- copyright: +category: Web +build-type: Simple +extra-source-files: ChangeLog.md +cabal-version: >=1.10 + +executable frontend + main-is: Main.hs + -- other-modules: + -- other-extensions: + build-depends: base >=4.11 && <4.12 + , miso + , jsaddle-warp + , mtl + hs-source-dirs: src + default-language: Haskell2010 diff --git a/frontend/src/Main.hs b/frontend/src/Main.hs new file mode 100644 index 0000000..57fe622 --- /dev/null +++ b/frontend/src/Main.hs @@ -0,0 +1,41 @@ +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RecordWildCards #-} +module Main where + +import Control.Monad.Trans (liftIO) +import Language.Javascript.JSaddle.Warp +import Miso +import Miso.String + +data Action = Add + | Subtract + | SayHello + | NoOp + +newtype Model = Model Int deriving (Eq, Num, ToMisoString) + +updateModel :: Action -> Model -> Effect Action Model +updateModel Add m = noEff (m + 1) +updateModel Subtract m = noEff (m - 1) +updateModel SayHello m = m <# (liftIO (putStrLn "Hello world") >> pure NoOp) +updateModel NoOp m = noEff m + +viewModel :: Model -> View Action +viewModel x = + div_ [] [ button_ [ onClick Add ] [ text "+" ] + , text (ms x) + , button_ [ onClick Subtract ] [ text "-" ] + ] + +main :: IO () +main = run 8081 $ startApp App{..} + where + model = Model 0 + initialAction = SayHello + update = updateModel + view = viewModel + subs = [] + events = defaultEvents + mountPoint = Nothing diff --git a/ghcjs.patch b/ghcjs.patch new file mode 100644 index 0000000..e9aa190 --- /dev/null +++ b/ghcjs.patch @@ -0,0 +1,16 @@ +diff --git a/lib/boot/shims/src/string.js b/lib/boot/shims/src/string.js +index d82f75a..f16e55a 100644 +--- a/lib/boot/shims/src/string.js ++++ b/lib/boot/shims/src/string.js +@@ -780,11 +780,7 @@ function h$throwJSException(e) { + // adding the Exception dictionary + var strVal = e.toString() + '\n' + Array.prototype.join.call(e.stack, '\n'); + var someE = MK_SOMEEXCEPTION(HS_JSEXCEPTION_EXCEPTION, +-#ifdef GHCJS_PROF +- MK_JSEXCEPTION(MK_JSVAL(e), h$toHsString(strVal), h$CCS_SYSTEM)) +-#else + MK_JSEXCEPTION(MK_JSVAL(e), h$toHsString(strVal)) +-#endif + ); + return h$throw(someE, true); + } diff --git a/jsaddle-warp-ghcjs.nix b/jsaddle-warp-ghcjs.nix new file mode 100644 index 0000000..d0fc9bc --- /dev/null +++ b/jsaddle-warp-ghcjs.nix @@ -0,0 +1,14 @@ +{ mkDerivation, base, fetchgit, stdenv }: +mkDerivation { + pname = "jsaddle-warp"; + version = "0.9.5.0"; + src = fetchgit { + url = "https://github.com/ghcjs/jsaddle.git"; + rev = "34fe7d61b3f387b81aa748294ac8d993243f53b4"; + sha256 = "0qdh5qdk23vcp1yp910zgw2hs4zpbx9ig25xgaax0iwj2m1ifh5x"; + }; + postUnpack = "sourceRoot+=/jsaddle-warp; echo source root reset to $sourceRoot"; + libraryHaskellDepends = [ base ]; + description = "Interface for JavaScript that works with GHCJS and GHC"; + license = stdenv.lib.licenses.mit; +} diff --git a/nixpkgs-version.json b/nixpkgs-version.json index 404acd5..11bb483 100644 --- a/nixpkgs-version.json +++ b/nixpkgs-version.json @@ -1,7 +1,7 @@ { "url": "https://github.com/nixos/nixpkgs.git", - "rev": "e0d250e5cf6d179e1ccc775472d89718f61fcfd1", + "rev": "4507926b80c6b8f73053775ffee17f6781c7e7c8", "date": "2018-01-08T11:52:28+01:00", - "sha256": "1iqpjz4czcpghbv924a5h4jvfmj6c8q6sl3b1z7blz3mi740aivs", + "sha256": "068v9xh7d8klk62p2qwr76fyfqfh1bp08xc12x138g5q6pg6yfzb", "fetchSubmodules": true } diff --git a/project.nix b/project.nix index 079c033..91c74c6 100644 --- a/project.nix +++ b/project.nix @@ -6,7 +6,8 @@ let in -{ packages +{ haskellPackages +, packages , overrides ? _ : _ : {} , tools ? [] }: @@ -17,12 +18,12 @@ let (self: super: mapAttrs (name: path: self.callCabal2nix name path {}) packages) overrides ]; - haskellPackages = nixpkgs.haskellPackages.override { overrides = overrides'; }; - packages' = mapAttrs (name: _: haskellPackages."${name}") packages; + haskellPackages' = haskellPackages.extend overrides'; + packages' = mapAttrs (name: _: haskellPackages'."${name}") packages; mkShell = name: pkg: let n = "${name}-shell"; - deps = haskellPackages.ghcWithHoogle (pkgs: pkg.buildInputs ++ pkg.propagatedBuildInputs); + deps = haskellPackages'.ghcWithHoogle (pkgs: pkg.buildInputs ++ pkg.propagatedBuildInputs); in { name = "${n}"; diff --git a/release.nix b/release.nix index afd47d4..c29eb4e 100644 --- a/release.nix +++ b/release.nix @@ -2,14 +2,66 @@ let + jsaddle = nixpkgs.fetchFromGitHub { + owner = "ghcjs"; + repo = "jsaddle"; + rev = "34fe7d61b3f387b81aa748294ac8d993243f53b4"; + sha256 = "0qdh5qdk23vcp1yp910zgw2hs4zpbx9ig25xgaax0iwj2m1ifh5x"; + }; + config = { + packageOverrides = pkgs: with pkgs.haskell.lib; with pkgs.lib; { + haskell = pkgs.haskell // { + packages = pkgs.haskell.packages // { + ghccustom = pkgs.haskell.packages.ghc843.override { + overrides = self: super: { + jsaddle-warp = dontCheck (super.callPackage (jsaddle + "/jsaddle-warp") {}); + # jsaddle-warp = super.callPackage ./jsaddle-warp-ghcjs.nix {}; + jsaddle = dontCheck (super.callPackage (jsaddle + "/jsaddle") {}); + }; + }; + ghcjscustom = pkgs.haskell.packages.ghcjs84.override { + overrides = self: super: { + doctest = null; + directory-tree = dontCheck (super.directory-tree); + http-types = dontCheck (super.http-types); + tasty-quickcheck = dontCheck (super.tasty-quickcheck); + scientific = dontCheck (super.scientific); + servant = dontCheck (super.servant); + jsaddle-warp = super.callPackage ./jsaddle-warp-ghcjs.nix {}; + ghc = overrideDerivation (super.ghc.override { + ghcjsSrc = pkgs.fetchgit { + url = "https://github.com/ghcjs/ghcjs.git"; + rev = "dc190b1bb2453cfa484124e9f335ee3cad1492f7"; + sha256 = "0dh52gj0f3700zfyrhisy44b6y9p1bsawwrmd5pllpdyw21zd9lw"; + fetchSubmodules = true; + }; + }) (drv: { patches = (drv.patches or []) ++ [ ./ghcjs.patch ]; }); + }; + }; + }; + }; + }; + }; pinnedVersion = nixpkgs.lib.importJSON ./nixpkgs-version.json; pinnedPkgs = import (nixpkgs.fetchFromGitHub { owner = "NixOS"; repo = "nixpkgs"; inherit (pinnedVersion) rev sha256; - }) {}; + }) { inherit config; }; + ghc = import ./default.nix { nixpkgs = pinnedPkgs; haskellPackages = pinnedPkgs.haskell.packages.ghccustom; }; + ghcjs = import ./default.nix { nixpkgs = pinnedPkgs; haskellPackages = pinnedPkgs.haskell.packages.ghcjscustom; }; inherit (pinnedPkgs) pkgs; in -import ./default.nix { nixpkgs = pinnedPkgs; haskellPackages = pinnedPkgs.haskellPackages; } +{ + inherit ghc ghcjs; + deps = pkgs.buildEnv { + name = "deps"; + paths = [ + (pkgs.haskell.packages.ghccustom.ghcWithPackages (_: ghc.backend.buildInputs ++ ghc.backend.propagatedBuildInputs)) + (pkgs.haskell.packages.ghcjscustom.ghcWithPackages (_: ghcjs.frontend.buildInputs ++ ghcjs.frontend.propagatedBuildInputs)) + ]; + buildInputs = [ ]; + }; +}