credentials-cli-0.0.1: src/Credentials/CLI/Format.hs
{-# LANGUAGE ExtendedDefaultRules #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-type-defaults #-}
-- |
-- Module : Credentials.CLI.Format
-- Copyright : (c) 2015-2016 Brendan Hay
-- License : Mozilla Public License, v. 2.0.
-- Maintainer : Brendan Hay <brendan.g.hay@gmail.com>
-- Stability : provisional
-- Portability : non-portable (GHC extensions)
--
module Credentials.CLI.Format where
import Credentials
import Credentials.CLI.Types
import Data.Aeson (ToJSON (..), object, (.=))
import Data.Bifunctor
import Data.ByteString (ByteString)
import Data.List (foldl', intersperse)
import Data.List.NonEmpty (NonEmpty (..))
import Data.Monoid
import Network.AWS.Data
import Options.Applicative.Help hiding (list, string)
import qualified Data.ByteString.Lazy as LBS
import qualified Data.Text as Text
data Status
= Deleted
| Truncated
instance ToLog Status where
build = build . toText
instance ToText Status where
toText = \case
Deleted -> "deleted"
Truncated -> "truncated"
data Emit = Emit { store' :: Store, result :: Result }
instance ToJSON Emit where
toJSON (Emit s r) = object [toText s .= r]
instance Pretty Emit where
pretty (Emit s r) = doc s <> char ':' .$. indent 2 (pretty r)
data Result
= SetupR Setup
| TeardownR
| InsertR Name Revision
| SelectR Name Revision ByteString
| DeleteR Name Revision
| TruncateR Name
| ListR [(Name, NonEmpty Revision)]
instance ToLog Result where
build = \case
SetupR s -> build s
TeardownR -> build Deleted
InsertR _ r -> build r
SelectR _ _ v -> build v
DeleteR {} -> build Deleted
TruncateR {} -> build Truncated
ListR rs -> foldMap f rs
where
f (n, v :| vs) =
build n % "," % mconcat (intersperse "," $ map build (v:vs)) % "\n"
instance ToJSON Result where
toJSON = \case
SetupR s -> object ["status" =~ s]
TeardownR -> object ["status" =~ Deleted]
InsertR n r -> object ["name" =~ n, "revision" =~ r]
SelectR n r v -> object ["name" =~ n, "revision" =~ r, "secret" =~ toBS v]
DeleteR n r -> object ["name" =~ n, "revision" =~ r, "status" =~ Deleted]
TruncateR n -> object ["name" =~ n, "status" =~ Truncated]
ListR rs -> object (map go rs)
where
k =~ v = k .= toText v
go (n, v :| vs) = toText n .= map toText (v:vs)
instance Pretty Result where
pretty = \case
SetupR s -> stat s
TeardownR -> stat Deleted
InsertR n r -> name n .$. rev r
SelectR n r v -> name n .$. rev r .$. val v
DeleteR n r -> name n .$. rev r .$. stat Deleted
TruncateR n -> name n .$. stat Truncated
ListR rs -> list rs
where
name n = "name:" <+> doc n
rev r = "revision:" <+> doc r
stat s = "status:" <+> doc s
val v = "secret:" <+> doc (toBS v)
list [] = mempty
list (r:rs) = foldl' (.$.) (f r) (map f rs)
where
f (n, v :| vs) = doc n <> ":" .$.
indent 2 (extractChunk (revs v vs))
revs v vs = table $ (v, "# latest") : map (,mempty) vs
table [] = mempty
table xs = pure $ vcat
[indent 2 (fillBreak n (item k) <+> v) | (k, v) <- ys]
where
n = maximum (map (Text.length . fst) ys) + 2
ys = map (first toText) xs
item x = "-" <+> doc x
doc :: ToText a => a -> Doc
doc = text . string