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)