packages feed

tasklite-core-0.3.0.0: source/Note.hs

module Note where

import Data.Aeson (
  FromJSON (parseJSON),
  ToJSON,
  withObject,
  (.:),
  (.:?),
 )
import Data.Csv qualified as Csv
import Data.Text as T (Text, intercalate, toLower)
import Data.ULID (ulidFromInteger)
import Database.SQLite.Simple (FromRow, ToRow, field, fromRow, toRow)
import Database.SQLite.Simple.ToField (toField)
import Protolude (
  Alternative ((<|>)),
  Applicative (pure),
  Eq,
  Functor (fmap),
  Generic,
  Hashable (hash),
  Integral (toInteger),
  Num (abs),
  Semigroup ((<>)),
  Show,
  encodeUtf8,
  fromMaybe,
  hush,
  show,
  ($),
  (.),
  (<$>),
  (<&>),
  (<*>),
 )


data Note = Note
  { ulid :: Text
  , body :: Text
  }
  deriving (Generic, Show, Eq)


instance ToRow Note where
  toRow Note{ulid = ulid, body = body} =
    [ toField ulid
    , toField body
    ]


instance FromRow Note where
  fromRow = Note <$> field <*> field


instance ToJSON Note


instance FromJSON Note where
  parseJSON = withObject "note" $ \o -> do
    o_ulid <- o .:? "ulid"

    let
      ulidGenerated = (ulidFromInteger . abs . toInteger . hash) o
      ulid =
        T.toLower $
          fromMaybe "" $
            o_ulid <|> hush (ulidGenerated <&> show)

    body <- o .: "body"

    pure Note{..}


instance Hashable Note


instance Csv.ToField [Note] where
  toField =
    encodeUtf8
      . T.intercalate ","
      . fmap (\Note{ulid = ulid, body = body} -> ulid <> ": " <> body)