yesod-autoreload (empty) → 0.0.0.0
raw patch · 5 files changed
+196/−0 lines, 5 filesdep +basedep +shakespearedep +text
Dependencies added: base, shakespeare, text, yesod-autoreload, yesod-core, yesod-websockets
Files
- LICENSE +8/−0
- example/Main.hs +29/−0
- src/Yesod/AutoReload.hs +95/−0
- test/Spec.hs +2/−0
- yesod-autoreload.cabal +62/−0
+ LICENSE view
@@ -0,0 +1,8 @@+Copyright 2020-2021 Tom Sydney Kerckhove++Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.+
+ example/Main.hs view
@@ -0,0 +1,29 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}++import Yesod.AutoReload+import Yesod.Core++data App = App++mkYesod+ "App"+ [parseRoutes|+ / HomeR GET+ /ws WebsocketR GET+|]++instance Yesod App++getHomeR :: Handler Html+getHomeR = defaultLayout $ "Hello World" <> autoReloadWidgetFor WebsocketR++getWebsocketR :: Handler ()+getWebsocketR = getAutoReloadR++main :: IO ()+main = warp 8000 App
+ src/Yesod/AutoReload.hs view
@@ -0,0 +1,95 @@+{-# LANGUAGE NumericUnderscores #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}++-- | This module contains helper functions to help you implement auto-reloading in your yesod site.+--+-- If this is implemented correctly, you should be able to work on your application and see the browser automatically reload when you save.+--+-- To achieve this, your site will need to have a route that serves a websocket connection.+-- You can use the helper functions in this library to implement that route.+-- You will then add a little piece of javascript to the page you want to have reload.+-- The 'autoReloadWidgetFor' function can help you add that piece of javascript.+--+-- The browser will then make a websocket connection to the websocket route and reload (semi-intelligently) as soon as the connection is closed.+module Yesod.AutoReload+ ( -- * The websocket route+ getAutoReloadR,+ getAutoReloadRWith,++ -- * The bit of javascript+ autoReloadWidgetFor,+ )+where++import Control.Concurrent+import Control.Monad+import Data.Text (Text)+import Text.Julius+import Yesod.Core+import Yesod.WebSockets++-- | A widget that takes care of reloading the page whenever the websocket connection to the given route is closed.+--+-- See 'getAutoReloadRWith' about implementing such a websocket route.+autoReloadWidgetFor :: Route site -> WidgetFor site ()+autoReloadWidgetFor reloadWebsocketRoute =+ toWidget+ [julius|++function connect (reloadAfterConnecting) {+ var uri = new URL("@{reloadWebsocketRoute}",document.baseURI).href.replace(/^http/i, "ws");+ var conn = new WebSocket(uri)+ conn.onopen = function() {+ console.log("Listening for file changes.");+ if(reloadAfterConnecting) {+ reloadAfterConnecting = false; // Just incase this is run twice+ location.reload();+ }+ }+ conn.onclose = function(e) {+ console.log("Connection closed using the following event, reloading.");+ console.log(e);+ if (e) {+ console.log(e.reason);+ if (e.reason && e.reason === "change") {+ console.log("Only reloading, not reconnecting.");+ location.reload();+ } else {+ console.log("Reconnecting before we reload.");+ setTimeout(function() {+ connect(true);+ }, 1000);+ }+ } else {+ console.log("Received something that didn't look like an event, not reloading.");+ }+ }+}++connect(false);++ |]++-- | A helper function to implement the websocket route that 'autoReloadWidgetFor' will call.+--+-- The argument is a function that will block until the page is supposed to be reloaded.+-- When watching a directory for example, you will want to block until a file has changed.+-- You can use an empty 'MVar ()', a callback that fills it, and 'takeMVar' to implement such a thing.+getAutoReloadRWith :: (MonadHandler m, MonadUnliftIO m) => WebSocketsT m () -> m ()+getAutoReloadRWith waitingFunc = webSockets $ do+ waitingFunc+ sendClose ("change" :: Text)++-- | A helper function to implement the websocket route that 'autoReloadWidgetFor' will call.+--+-- This function is like 'getAutoReloadRWith' except it takes no argument and just waits forever.+--+-- You can use this function to reload whenever the server restarts.+-- This can work nicely with @stack build --file-watch@.+getAutoReloadR :: (MonadHandler m, MonadUnliftIO m) => m ()+getAutoReloadR =+ webSockets $+ forever $ do+ sendPing ("Ping" :: Text)+ liftIO $ threadDelay 1_000_000 -- 1 second
+ test/Spec.hs view
@@ -0,0 +1,2 @@+main :: IO ()+main = putStrLn "Test suite not yet implemented"
+ yesod-autoreload.cabal view
@@ -0,0 +1,62 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.34.4.+--+-- see: https://github.com/sol/hpack++name: yesod-autoreload+version: 0.0.0.0+synopsis: Auto-reload a yesod app during development+homepage: https://github.com/NorfairKing/yesod-autoreload#readme+bug-reports: https://github.com/NorfairKing/yesod-autoreload/issues+author: Tom Sydney Kerckhove+maintainer: syd@cs-syd.eu+copyright: Copyright (c) 2020-2021 Tom Sydney Kerckhove+license: MIT+license-file: LICENSE+build-type: Simple++source-repository head+ type: git+ location: https://github.com/NorfairKing/yesod-autoreload++library+ exposed-modules:+ Yesod.AutoReload+ other-modules:+ Paths_yesod_autoreload+ hs-source-dirs:+ src+ build-depends:+ base >=4.7 && <5+ , shakespeare+ , text+ , yesod-core+ , yesod-websockets+ default-language: Haskell2010++executable yesod-autoreload-example+ main-is: Main.hs+ other-modules:+ Paths_yesod_autoreload+ hs-source-dirs:+ example+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ base >=4.7 && <5+ , yesod-autoreload+ , yesod-core+ default-language: Haskell2010++test-suite yesod-autoreload-test+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ other-modules:+ Paths_yesod_autoreload+ hs-source-dirs:+ test+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ base >=4.7 && <5+ , yesod-autoreload+ default-language: Haskell2010