minion-htmx (empty) → 0.1.0.0
raw patch · 4 files changed
+183/−0 lines, 4 filesdep +basedep +bytestringdep +http-types
Dependencies added: base, bytestring, http-types, minion, text
Files
- LICENSE +20/−0
- README.md +45/−0
- minion-htmx.cabal +62/−0
- src/Web/Minion/Htmx/Headers.hs +56/−0
+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2024 Danil Berestov++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.
+ README.md view
@@ -0,0 +1,45 @@+# Minion++Minion is Haskell library for developing web applications. It stands between [Scotty](https://hackage.haskell.org/package/scotty) and [Servant](https://hackage.haskell.org/package/servant-server) ++| | Scotty | Minion | Servant |+| ---------------- | ------ | ------ | ------- |+| As simple as ABC | Yes | No | No |+| At term level | Yes | Yes | No |+| Typesafe | No | Yes | Yes |+| Introspectable | No | Yes | Yes |+| Generated client | No | No | Yes |++ +Since Minion defines servers at the term level, it's easier to start and without excess verbosity.++```haskell+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE OverloadedLists #-}+module Main where++import Web.Minion+import Network.Wai.Handler.Warp qualified as Warp++main :: IO ()+main = Warp.run 9001 app++app :: ApplicationM IO+app = serve api ++api :: Router Void IO+api = "api" /> + [ "about" /> handlePlainText @String GET (pure "Hello-World Minion server")+ , "hello" /> capture @String "name" + .> handlePlainText @String GET (\name -> pure $ "Hello, " <> name <> "!")+ ]+```++Documentation and examples can be found on [Hackage](https://hackage.haskell.org/package/minion) ++Minion ecosystem also contains following libraries:+* [minion-conduit](https://hackage.haskell.org/package/minion-conduit) +* [minion-htmx](https://hackage.haskell.org/package/minion-htmx) +* [minion-jwt](https://hackage.haskell.org/package/minion-jwt) +* [minion-wai-extra](https://hackage.haskell.org/package/minion-wai-extra) +* [minion-openapi3](https://hackage.haskell.org/package/minion-openapi3)
+ minion-htmx.cabal view
@@ -0,0 +1,62 @@+cabal-version: 3.0+name: minion-htmx+version: 0.1.0.0+license: MIT+license-file: LICENSE+author: Danil Berestov+synopsis: Minion HTMX support+maintainer: goosedb@yandex.ru+category: Web+build-type: Simple+extra-source-files: README.md++common common+ ghc-options: -Wall+ default-extensions:+ AllowAmbiguousTypes+ BlockArguments+ ConstraintKinds+ DataKinds+ DefaultSignatures+ DeriveAnyClass+ DeriveGeneric+ DerivingStrategies+ DerivingStrategies+ DuplicateRecordFields+ DuplicateRecordFields+ FlexibleContexts+ FlexibleInstances+ FunctionalDependencies+ GADTs+ GeneralizedNewtypeDeriving+ ImportQualifiedPost+ LambdaCase+ MultiParamTypeClasses+ NamedFieldPuns+ OverloadedLists+ OverloadedRecordDot+ OverloadedRecordDot+ OverloadedStrings+ PolyKinds+ RankNTypes+ RecordWildCards+ RoleAnnotations+ ScopedTypeVariables+ TypeApplications+ TypeFamilies+ TypeOperators+ UndecidableInstances+ ViewPatterns++library+ import: common+ exposed-modules: Web.Minion.Htmx.Headers+ build-depends:+ , base >= 4.16 && < 5+ , bytestring+ , http-types+ , minion+ , text++ hs-source-dirs: src+ default-language: Haskell2010
+ src/Web/Minion/Htmx/Headers.hs view
@@ -0,0 +1,56 @@+module Web.Minion.Htmx.Headers where++import Data.Bool (bool)+import Data.List.NonEmpty qualified as Nel+import Data.Maybe (listToMaybe)+import Data.Text (Text)+import Data.Text.Encoding qualified as Text.Encode+import Web.Minion.Args+import Web.Minion.Error+import Web.Minion.Introspect qualified as I+import Web.Minion.Request.Header+import Web.Minion.Router (Router' (..), ValueCombinator)++-- | Matches only `HX-Request:true`. Otherwise throws 'NoMatch' that causes trying another route+hxRequest :: (MonadThrow m, I.Introspection i I.Header Bool) => ValueCombinator i (WithHeader Required Strict m Bool) ts m+hxRequest = Header @Bool @Required @Strict "HX-Request" \_ -> bool (throwM NoMatch) (pure True) . ("true" `elem`)++hxTarget ::+ (I.Introspection i I.Header Text, MonadThrow m) =>+ ValueCombinator i (WithHeader Optional Strict m Text) ts m+hxTarget = header "HX-Target" (const $ pure . fmap Text.Encode.decodeUtf8 . listToMaybe)++hxTarget' ::+ (I.Introspection i I.Header Text, MonadThrow m) =>+ ValueCombinator i (WithHeader Required Strict m Text) ts m+hxTarget' = header' "HX-Target" (const $ pure . Text.Encode.decodeUtf8 . Nel.head)++hxTrigger ::+ (I.Introspection i I.Header Text, MonadThrow m) =>+ ValueCombinator i (WithHeader Optional Strict m Text) ts m+hxTrigger = header "HX-Trigger" (const $ pure . fmap Text.Encode.decodeUtf8 . listToMaybe)++hxTrigger' ::+ (I.Introspection i I.Header Text, MonadThrow m) =>+ ValueCombinator i (WithHeader Required Strict m Text) ts m+hxTrigger' = header' "HX-Trigger" (const $ pure . Text.Encode.decodeUtf8 . Nel.head)++hxTriggerName ::+ (I.Introspection i I.Header Text, MonadThrow m) =>+ ValueCombinator i (WithHeader Optional Strict m Text) ts m+hxTriggerName = header "HX-Trigger-Name" (const $ pure . fmap Text.Encode.decodeUtf8 . listToMaybe)++hxTriggerName' ::+ (I.Introspection i I.Header Text, MonadThrow m) =>+ ValueCombinator i (WithHeader Required Strict m Text) ts m+hxTriggerName' = header' "HX-Trigger-Name" (const $ pure . Text.Encode.decodeUtf8 . Nel.head)++hxCurrentUrl ::+ (I.Introspection i I.Header Text, MonadThrow m) =>+ ValueCombinator i (WithHeader Optional Strict m Text) ts m+hxCurrentUrl = header "HX-Current-URL" (const $ pure . fmap Text.Encode.decodeUtf8 . listToMaybe)++hxCurrentUrl' ::+ (I.Introspection i I.Header Text, MonadThrow m) =>+ ValueCombinator i (WithHeader Required Strict m Text) ts m+hxCurrentUrl' = header' "HX-Current-URL" (const $ pure . Text.Encode.decodeUtf8 . Nel.head)