packages feed

Shpadoinkle-console (empty) → 0.0.1.0

raw patch · 5 files changed

+287/−0 lines, 5 filesdep +aesondep +basedep +jsaddle

Dependencies added: aeson, base, jsaddle, lens, text, unliftio

Files

+ CHANGELOG.md view
+ LICENSE view
@@ -0,0 +1,27 @@+Shpadoinkle Debug aka S11 Debug+Copyright © 2020 Isaac Shapira+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 Shpadoinkle nor the names of its 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.
+ README.md view
@@ -0,0 +1,35 @@+# Shpadoinkle Console++[![Goldwater](https://gitlab.com/fresheyeball/Shpadoinkle/badges/master/pipeline.svg)](https://gitlab.com/fresheyeball/Shpadoinkle)+[![Haddock](https://img.shields.io/badge/haddock-master-informational)](https://shpadoinkle.org/console)+[![BSD-3](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)+[![built with nix](https://img.shields.io/badge/built%20with-nix-41439a)](https://builtwithnix.org)+[![Hackage](https://img.shields.io/hackage/v/Shpadoinkle-console.svg)](https://hackage.haskell.org/package/Shpadoinkle-console)+[![Hackage Deps](https://img.shields.io/hackage-deps/v/Shpadoinkle-console.svg)](http://packdeps.haskellers.com/reverse/Shpadoinkle-console)+[![Hackage CI](https://matrix.hackage.haskell.org/api/v2/packages/Shpadoinkle-console/badge)](https://matrix.hackage.haskell.org/#/package/Shpadoinkle-console)++This package exposes some useful debugging functions for tracing the state of Shpadoinkle applications as they change over time. It exposes some type classes currently.++```haskell+class LogJS (c :: Type -> Constraint) where+  logJS :: c a => a -> JSM ()++class LogJS c => Trapper c where+  trapper :: c a => JSContextRef -> a -> a++class Assert (c :: Type -> Constraint) where+  assert :: c a => Bool -> a -> JSM ()+```++These are intended to by used with `TypeApplications`, so you can choose the means of conversion before passing to `console.log`. For example:++```haskell+main :: IO ()+main = runJSorWarp 8080 $ do+  ctx <- askJSM+  simple runParDiff initial (view . trapper @ToJSON ctx) getBody+```++This will log all state by first encoding to JSON with Aeson, then then logging with `JSON.parse` so the browser console has the nice native display. If we change it to `trapper @Show ctx` it will use the `Show` instance instead.++We also export a handful of `console` bindings such as `console.time`, `console.table`, `console.info`, `console.warn`, `console.debug`, and of course `console.log`.
+ Shpadoinkle-console.cabal view
@@ -0,0 +1,42 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.32.0.+--+-- see: https://github.com/sol/hpack+--+-- hash: ed7c83dc76bc4f63bd8d401f7b00f44eae07c11d062de89532fc81d93598aa13++name:           Shpadoinkle-console+version:        0.0.1.0+synopsis:       Support for the native browser console+description:    This package adds support for native browser console features for logging and debugging.+category:       Web+author:         Isaac Shapira+maintainer:     fresheyeball@protonmail.com+license:        BSD3+license-file:   LICENSE+build-type:     Simple+extra-source-files:+    README.md+    CHANGELOG.md++source-repository head+  type: git+  location: https://gitlab.com/fresheyeball/Shpadoinkle.git++library+  exposed-modules:+      Shpadoinkle.Console+  other-modules:+      Paths_Shpadoinkle_console+  hs-source-dirs:+      ./.+  ghc-options: -Wall -Wcompat -fwarn-redundant-constraints -fwarn-incomplete-uni-patterns -fwarn-tabs -fwarn-incomplete-record-updates -fwarn-identities+  build-depends:+      aeson >=1.4.4 && <1.5+    , base >=4.12.0 && <4.16+    , jsaddle >=0.9.7 && <0.20+    , lens >=4.17.1 && <5.0+    , text >=1.2.3 && <1.3+    , unliftio >=0.2.12 && <0.3+  default-language: Haskell2010
+ Shpadoinkle/Console.hs view
@@ -0,0 +1,183 @@+{-# LANGUAGE AllowAmbiguousTypes        #-}+{-# LANGUAGE ConstraintKinds            #-}+{-# LANGUAGE ExtendedDefaultRules       #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE KindSignatures             #-}+{-# LANGUAGE OverloadedStrings          #-}+{-# LANGUAGE ScopedTypeVariables        #-}+{-# LANGUAGE TypeApplications           #-}+{-# OPTIONS_GHC -fno-warn-type-defaults #-}+++{-|+  This module exposes the browser's native console logging and debugging features,+  including underutilized features such as time measurement, table displays, and assertions.+-}+++module Shpadoinkle.Console (+  -- * Classes+  LogJS (..), Assert (..), Trapper (..), askJSM+  -- * Native methods+  -- ** Log levels+  , log, debug, info, warn+  -- ** Fancy display+  , table+  -- ** Time Measurement+  , TimeLabel(..), time, timeEnd+  ) where+++import           Control.Lens+import           Data.Aeson                  (ToJSON, encode)+import           Data.Kind+import           Data.String+import           Data.Text+import           Data.Text.Lazy              (toStrict)+import           Data.Text.Lazy.Encoding+import           Language.Javascript.JSaddle hiding (startTime)+import           Prelude                     hiding (log)+import           System.IO.Unsafe            (unsafePerformIO)+++default (Text)++{-|+   'LogJS' is the base class for logging to the browser console.+   Browser consoles contain rich tooling for exploring JavaScript objects,+   DOM nodes, and much more. To take advantage of these native features, we+   need to choose how we are going to log. The 'LogJS' class is intended to+   be used in conjunction with 'TypeApplications'.++   @+   data Person = Person { first :: String, last :: String, age :: Int } deriving (Generic, ToJSON)+   main = logJS @ToJSON "log" $ Person "bob" "saget" 45+   @++   is effectively equivalent to:++   @+   console.log({first: "bob", last: "saget", age: 45})+   @++   in that the console will render with nice expand/collapse object exploration features.+-}+class LogJS (c :: Type -> Constraint) where+  logJS :: c a => Text -> a -> JSM ()+++-- | Logs against 'ToJSON' will be encoded via 'Aeson' then parsed using+-- native <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse JSON.parse> before being sent to the console.+instance LogJS ToJSON where+  logJS t a = do+    console <- jsg "console"+    json    <- jsg "JSON"+    parsed  <- json ^. js1 "parse" (toStrict . decodeUtf8 $ encode a)+    () <$ console ^. js1 t parsed+++-- | Logs against 'Show' will be converted to a 'String' before being sent to the console.+instance LogJS Show where+  logJS t a = do+    console <- jsg "console"+    () <$ console ^. js1 t (pack $ show a)+++-- | Logs against 'ToJSVal' will be converted to a 'JSVal' before being sent to the console.+instance LogJS ToJSVal where+  logJS t a = do+    console <- jsg "console"+    () <$ console ^. js1 t (toJSVal a)+++{-|+  Trapper is a class intended for continuous logging of your application and the catching of helpless animals.+  Usage is along the lines of 'Debug.Trace.trace' where the effect of logging is implicit.+  To make this work in both GHC and GHCjs contexts, you do need to+  pass the 'JSContextRef' in manually ('askJSM' re-exported here for convenience).++  @+  main :: IO ()+  main = runJSorWarp 8080 $ do+    ctx <- askJSM+    simple runParDiff initial (view . trapper @ToJSON ctx) getBody+  @+-}+class LogJS c => Trapper c where+  trapper :: c a => JSContextRef -> a -> a+  trapper ctx x = unsafePerformIO $ runJSM (x <$ debug @c x) ctx+  {-# NOINLINE trapper #-}++instance Trapper ToJSON+instance Trapper Show+instance Trapper ToJSVal+++{-|+  Assert is a class for assertion programming. It behaves the same as 'LogJS' but calls+  <https://developer.mozilla.org/en-US/docs/Web/API/Console/assert console.assert> instead of+  other console methods. This will only have an effect if the 'Bool' provided to 'assert' is 'False'.+-}+class Assert (c :: Type -> Constraint) where+  assert :: c a => Bool -> a -> JSM ()++instance Assert ToJSON where+  assert b x = do+    console <- jsg "console"+    json <- jsg "JSON"+    parsed <- json ^. js1 "parse" (toStrict . decodeUtf8 $ encode x)+    () <$ console ^. js2 "assert" (toJSVal b) parsed++instance Assert Show where+  assert b x = do+    console <- jsg "console"+    () <$ console ^. js2 "assert" (toJSVal b) (pack $ show x)++instance Assert ToJSVal where+  assert b x = do+    console <- jsg "console"+    () <$ console ^. js2 "assert" (toJSVal b) (toJSVal x)+++-- | Log a list of JSON objects to the console where it will rendered as a table using <https://developer.mozilla.org/en-US/docs/Web/API/Console/table console.table>+table :: ToJSON a => [a] -> JSM ()+table = logJS @ToJSON "table"+++-- | Log to the console using <https://developer.mozilla.org/en-US/docs/Web/API/Console/log console.log>+log :: forall c a. LogJS c => c a => a -> JSM ()+log = logJS @c "log"+++-- | Log with the "warn" log level using <https://developer.mozilla.org/en-US/docs/Web/API/Console/warn console.warn>+warn :: forall c a. LogJS c => c a => a -> JSM ()+warn = logJS @c "warn"+++-- | Log with the "info" log level using <https://developer.mozilla.org/en-US/docs/Web/API/Console/info console.info>+info :: forall c a. LogJS c => c a => a -> JSM ()+info = logJS @c "info"+++-- | Log with the "debug" log level using <https://developer.mozilla.org/en-US/docs/Web/API/Console/debug console.debug>+debug :: forall c a. LogJS c => c a => a -> JSM ()+debug = logJS @c "debug"+++-- | A unique label for a timer. This is used to tie calls to <https://developer.mozilla.org/en-US/docs/Web/API/Console/time console.time> to <https://developer.mozilla.org/en-US/docs/Web/API/Console/timeEnd console.timeEnd>+newtype TimeLabel = TimeLabel { unTimeLabel :: Text }+  deriving (Eq, Ord, Show, IsString)+++-- | Start a timer using <https://developer.mozilla.org/en-US/docs/Web/API/Console/time console.time>+time :: TimeLabel -> JSM ()+time (TimeLabel l) = do+  console <- jsg "console"+  () <$ console ^. js1 "time" l+++-- | End a timer and print the milliseconds elapsed since it started using <https://developer.mozilla.org/en-US/docs/Web/API/Console/timeEnd console.timeEnd>+timeEnd :: TimeLabel -> JSM ()+timeEnd (TimeLabel l) = do+  console <- jsg "console"+  () <$ console ^. js1 "timeEnd" l