on master help sign in
Merge branch 'cg-tabulation-nodevelop' into cg-tabulation
aaa4e84Cale Gibbard
lib/route/obelisk-route.cabal+2
@@ -6,6 +6,8 @@ build-type: Simple
6library
6library
7 hs-source-dirs: src
7 hs-source-dirs: src
8 build-depends: base,
8 build-depends: base,
9+ aeson,
10+ bytestring,
9 categories,
11 categories,
10 constraints,
12 constraints,
11 constraints-extras,
13 constraints-extras,
lib/route/src/Obelisk/Route.hs+21−1
@@ -90,6 +90,7 @@ module Obelisk.Route
90 , Decoder(..)
90 , Decoder(..)
91 , dmapEncoder
91 , dmapEncoder
92 , fieldMapEncoder
92 , fieldMapEncoder
93+ , jsonEncoder
93 ) where
94 ) where
94
95
95import Prelude hiding ((.), id)
96import Prelude hiding ((.), id)
@@ -102,6 +103,7 @@ import Control.Category.Associative
102import Control.Category.Monoidal
103import Control.Category.Monoidal
103import Control.Lens (Identity (..), Prism', makePrisms, itraverse, imap, prism, (^.), re, matching, (^?), _Just, _Nothing, Iso', from, view, Wrapped (..))
104import Control.Lens (Identity (..), Prism', makePrisms, itraverse, imap, prism, (^.), re, matching, (^?), _Just, _Nothing, Iso', from, view, Wrapped (..))
104import Control.Monad.Except
105import Control.Monad.Except
106+import qualified Data.ByteString.Lazy as BSL
105import Data.Dependent.Sum (DSum (..))
107import Data.Dependent.Sum (DSum (..))
106import Data.Dependent.Map (DMap)
108import Data.Dependent.Map (DMap)
107import qualified Data.Dependent.Map as DMap
109import qualified Data.Dependent.Map as DMap
@@ -130,6 +132,8 @@ import qualified Numeric.Lens
130import Obelisk.Route.TH
132import Obelisk.Route.TH
131import Text.Read (readMaybe)
133import Text.Read (readMaybe)
132import Data.Tabulation
134import Data.Tabulation
135+import qualified Data.Aeson as Aeson
136+import Data.Aeson (FromJSON, ToJSON)
133
137
134-- Design goals:
138-- Design goals:
135-- No start-up time on the frontend (not yet met)
139-- No start-up time on the frontend (not yet met)
@@ -349,7 +353,7 @@ maybeEncoder f g = shadowEncoder f g . maybeToEitherEncoder
349justEncoder :: (Applicative check, MonadError Text parse) => Encoder check parse a (Maybe a)
353justEncoder :: (Applicative check, MonadError Text parse) => Encoder check parse a (Maybe a)
350justEncoder = prismEncoder _Just
354justEncoder = prismEncoder _Just
351
355
352−-- |
356+-- | Encode () to 'Nothing'.
353nothingEncoder :: (Applicative check, MonadError Text parse) => Encoder check parse () (Maybe a)
357nothingEncoder :: (Applicative check, MonadError Text parse) => Encoder check parse () (Maybe a)
354nothingEncoder = prismEncoder _Nothing
358nothingEncoder = prismEncoder _Nothing
355
359
@@ -933,4 +937,20 @@ fieldMapEncoder = unsafeEncoder $ do
933 Just (Identity v) -> return v
937 Just (Identity v) -> return v
934 }
938 }
935
939
940+-- | Use ToJSON/FromJSON to encode to Text. The correctness of this encoder is dependent on the encoding being injective and round-tripping correctly.
941+jsonEncoder :: forall check parse r.
942+ ( ToJSON r
943+ , FromJSON r
944+ , Applicative check
945+ , MonadError Text parse
946+ )
947+ => Encoder check parse r Text
948+jsonEncoder = unsafeEncoder $ do
949+ pure $ EncoderImpl
950+ { _encoderImpl_encode = \r -> decodeUtf8 . BSL.toStrict $ Aeson.encode r
951+ , _encoderImpl_decode = \t -> case Aeson.eitherDecodeStrict $ encodeUtf8 t of
952+ Left err -> throwError ("jsonEncoder: " <> T.pack err)
953+ Right x -> return x
954+ }
955+
936--TODO: decodeURIComponent as appropriate
956--TODO: decodeURIComponent as appropriate