packages feed

keiro-dsl-0.17.0.0: test/conformance-workspace-nominals/Generated/WorkspaceNominalProof/Project/Codec.hs

-- @generated by keiro-dsl 0.17.0.0 (language keiro-dsl 6) from aggregate Project; do not edit.
module Generated.WorkspaceNominalProof.Project.Codec (
    projectCodec,
    parseProjectEvent,
    encodeProjectEvent,
    encodeProjectClaimMapped,
    decodeProjectClaimMapped,
) where

import Generated.WorkspaceNominalProof.Project.Domain
import Generated.WorkspaceNominalProof.Nominals (projectIdText, ProjectPhase (..), projectPhaseText)
import Generated.WorkspaceNominalProof.Nominals.Internal (unsafeProjectIdFromLegacyText)
import Control.Monad (unless)
import Data.Aeson (Value, object, withObject, withText, (.:), (.=))
import Data.Aeson.Key qualified as Key
import Data.Aeson.KeyMap qualified as KeyMap
import Data.Aeson.Types (Parser, explicitParseField, parseEither)
import Data.List.NonEmpty (NonEmpty (..))
import Data.List.NonEmpty qualified as NonEmpty
import Data.Text (Text)
import qualified Data.Text as T
import Keiro.Codec.Structural (bindingFromShape, bindingToShape)
import Keiro.Codec (Codec (..), EventType (..))


import Generated.WorkspaceNominalProof.Structural.NominalLeaves (encodeClaimIdLeaf, parseClaimIdLeaf)
import Generated.WorkspaceNominalProof.Structural.Shape.ProjectClaim qualified as ShapeProjectClaim
import WorkspaceNominalProof.Bindings qualified as Bindings
import WorkspaceNominalProof.Domain (ProjectClaim)

parseProjectPhase :: Text -> Parser ProjectPhase
parseProjectPhase = \case
  "draft" -> pure Draft
  "active" -> pure Active
  tag -> fail ("unknown ProjectPhase " <> show tag <> "; expected one of: draft, active")

encodeProjectClaimMapped :: ProjectClaim -> Value
encodeProjectClaimMapped = encodeProjectClaimShape . bindingToShape Bindings.projectClaimBinding

parseProjectClaimMapped :: Value -> Parser ProjectClaim
parseProjectClaimMapped value = bindingFromShape Bindings.projectClaimBinding <$> parseProjectClaimShape value

decodeProjectClaimMapped :: Value -> Either Text ProjectClaim
decodeProjectClaimMapped = mapLeftText . parseEither parseProjectClaimMapped

encodeProjectClaimShape :: ShapeProjectClaim.ProjectClaimShape -> Value
encodeProjectClaimShape shape =
  object
      [ "claimId" .= encodeClaimIdLeaf shape.claimId
      ]

parseProjectClaimShape :: Value -> Parser ShapeProjectClaim.ProjectClaimShape
parseProjectClaimShape = withObject "ProjectClaimShape" $ \objectValue -> do
  rejectUnknownFields "ProjectClaim" ["claimId"] objectValue
  ShapeProjectClaim.ProjectClaim
    <$> explicitParseField (parseClaimIdLeaf) objectValue "claimId"

projectEventTypes :: NonEmpty EventType
projectEventTypes = EventType "ProjectRegistered" :| [EventType "ArchivalRecorded"]

projectCodec :: Codec ProjectEvent
projectCodec =
  Codec
    { eventTypes = projectEventTypes
    , eventType = \case
        ProjectRegistered{} -> EventType "ProjectRegistered"
        ArchivalRecorded{} -> EventType "ArchivalRecorded"
    , schemaVersion = 1
    , encode = encodeProjectEvent
    , decode = parseProjectEvent
    , upcasters = []
    }

encodeProjectEvent :: ProjectEvent -> Value
encodeProjectEvent = \case
  ProjectRegistered payload ->
    object
      [ "kind" .= ("ProjectRegistered" :: Text)
      , "projectId" .= projectIdText payload.projectId
      , "phase" .= projectPhaseText payload.phase
      , "claim" .= encodeProjectClaimMapped payload.claim
      ]
  ArchivalRecorded payload ->
    object
      [ "kind" .= ("ArchivalRecorded" :: Text)
      , "projectId" .= projectIdText payload.projectId
      , "phase" .= projectPhaseText payload.phase
      ]

parseProjectEvent :: EventType -> Value -> Either Text ProjectEvent
parseProjectEvent (EventType tag) = mapLeftText . parseEither (withObject "ProjectEvent" go)
  where
    go o = do
      case tag of
        "ProjectRegistered" ->
          ProjectRegistered
            <$> ( ProjectRegisteredData
                    <$> (unsafeProjectIdFromLegacyText <$> o .: "projectId")
                    <*> explicitParseField (withText "ProjectPhase" parseProjectPhase) o "phase"
                    <*> explicitParseField parseProjectClaimMapped o "claim"
                )
        "ArchivalRecorded" ->
          ArchivalRecorded
            <$> ( ArchivalRecordedData
                    <$> (unsafeProjectIdFromLegacyText <$> o .: "projectId")
                    <*> explicitParseField (withText "ProjectPhase" parseProjectPhase) o "phase"
                )
        _ -> fail ("unknown event type " <> show tag <> "; expected one of: " <> renderExpectedEventTypes projectEventTypes)

mapLeftText :: Either String b -> Either Text b
mapLeftText = either (Left . T.pack) Right

renderExpectedEventTypes :: NonEmpty EventType -> String
renderExpectedEventTypes =
  T.unpack
    . T.intercalate ", "
    . map (\(EventType eventTypeName) -> eventTypeName)
    . NonEmpty.toList

rejectUnknownFields :: String -> [Text] -> KeyMap.KeyMap Value -> Parser ()
rejectUnknownFields label allowed objectValue =
  unless (null extras) (fail (label <> " contains unknown fields: " <> show extras))
  where
    extras = filter (`notElem` allowed) (map Key.toText (KeyMap.keys objectValue))