packages feed

keiro-dsl-0.18.0.0: test/conformance-id-admission-domains/Generated/IdAdmissionDomains/IdentityLedger/Codec.hs

-- @generated by keiro-dsl 0.18.0.0 (language keiro-dsl 6) from aggregate IdentityLedger; do not edit.
module Generated.IdAdmissionDomains.IdentityLedger.Codec (
    identityLedgerCodec,
    parseIdentityLedgerEvent,
    encodeIdentityLedgerEvent,
    encodeIdentityEnvelopeMapped,
    decodeIdentityEnvelopeMapped,
) where

import Generated.IdAdmissionDomains.IdentityLedger.Domain
import Generated.IdAdmissionDomains.Nominals (legacyIdText)
import Generated.IdAdmissionDomains.Nominals.Internal (unsafeLegacyIdFromLegacyText)
import Control.Monad (unless)
import Data.Aeson (Value (..), object, parseJSON, toJSON, withObject, (.:), (.=))
import Data.Aeson.Key qualified as Key
import Data.Aeson.KeyMap qualified as KeyMap
import Data.Aeson.Types (Parser, JSONPathElement (..), (<?>), explicitParseField, parseEither)
import Data.List.NonEmpty (NonEmpty (..))
import Data.List.NonEmpty qualified as NonEmpty
import Data.Map.Strict qualified as Map
import Data.Text (Text)
import qualified Data.Text as T
import Keiro.Codec.Structural (bindingFromShape, bindingToShape)
import Keiro.Codec (Codec (..), EventType (..))


import Generated.IdAdmissionDomains.Structural.NominalLeaves (encodeLegacyIdLeaf, parseLegacyIdLeaf)
import Generated.IdAdmissionDomains.Structural.NominalLeaves (parseLegacyIdLeafKey, renderLegacyIdLeafKey)
import Conformance.IdAdmissionDomains.Bindings qualified as Bindings
import Conformance.IdAdmissionDomains.Domain (IdentityEnvelope)
import Generated.IdAdmissionDomains.Structural.Shape.IdentityEnvelope qualified as ShapeIdentityEnvelope



encodeIdentityEnvelopeMapped :: IdentityEnvelope -> Value
encodeIdentityEnvelopeMapped = encodeIdentityEnvelopeShape . bindingToShape Bindings.identityEnvelopeBinding

parseIdentityEnvelopeMapped :: Value -> Parser IdentityEnvelope
parseIdentityEnvelopeMapped value = bindingFromShape Bindings.identityEnvelopeBinding <$> parseIdentityEnvelopeShape value

decodeIdentityEnvelopeMapped :: Value -> Either Text IdentityEnvelope
decodeIdentityEnvelopeMapped = mapLeftText . parseEither parseIdentityEnvelopeMapped

encodeIdentityEnvelopeShape :: ShapeIdentityEnvelope.IdentityEnvelopeShape -> Value
encodeIdentityEnvelopeShape shape =
  object
      [ "legacyId" .= encodeLegacyIdLeaf shape.legacyId
      , "previousId" .= maybe Null (\item0 -> encodeLegacyIdLeaf item0) (shape.previousId)
      , "labelsById" .= Object (KeyMap.fromList [(Key.fromText (renderLegacyIdLeafKey key0), toJSON (item0)) | (key0, item0) <- Map.toList (shape.labelsById)])
      ]

parseIdentityEnvelopeShape :: Value -> Parser ShapeIdentityEnvelope.IdentityEnvelopeShape
parseIdentityEnvelopeShape = withObject "IdentityEnvelopeShape" $ \objectValue -> do
  rejectUnknownFields "IdentityEnvelope" ["legacyId", "previousId", "labelsById"] objectValue
  ShapeIdentityEnvelope.IdentityEnvelope
    <$> explicitParseField (parseLegacyIdLeaf) objectValue "legacyId"
    <*> parseOptionalField (pure Nothing) (\value0 -> case value0 of Null -> pure Nothing; other0 -> Just <$> (parseLegacyIdLeaf) other0) objectValue "previousId"
    <*> explicitParseField (\value0 -> withObject "Map[LegacyId]" (\object0 -> Map.fromList <$> traverse (\(rawKey0, item0) -> do key0 <- parseLegacyIdLeafKey (Key.toText rawKey0) <?> Key rawKey0; parsedItem0 <- (parseJSON) item0 <?> Key rawKey0; pure (key0, parsedItem0)) (KeyMap.toList object0)) value0) objectValue "labelsById"

identityLedgerEventTypes :: NonEmpty EventType
identityLedgerEventTypes = EventType "IdentityRecorded" :| [EventType "IdentityAudited", EventType "LegacyIdentityImported"]

identityLedgerCodec :: Codec IdentityLedgerEvent
identityLedgerCodec =
  Codec
    { eventTypes = identityLedgerEventTypes
    , eventType = \case
        IdentityRecorded{} -> EventType "IdentityRecorded"
        IdentityAudited{} -> EventType "IdentityAudited"
        LegacyIdentityImported{} -> EventType "LegacyIdentityImported"
    , schemaVersion = 1
    , encode = encodeIdentityLedgerEvent
    , decode = parseIdentityLedgerEvent
    , upcasters = []
    }

encodeIdentityLedgerEvent :: IdentityLedgerEvent -> Value
encodeIdentityLedgerEvent = \case
  IdentityRecorded payload ->
    object
      [ "kind" .= ("IdentityRecorded" :: Text)
      , "legacyId" .= legacyIdText payload.legacyId
      , "envelope" .= encodeIdentityEnvelopeMapped payload.envelope
      ]
  IdentityAudited payload ->
    object
      [ "kind" .= ("IdentityAudited" :: Text)
      , "legacyId" .= legacyIdText payload.legacyId
      , "envelope" .= encodeIdentityEnvelopeMapped payload.envelope
      ]
  LegacyIdentityImported payload ->
    object
      [ "kind" .= ("LegacyIdentityImported" :: Text)
      , "legacyId" .= legacyIdText payload.legacyId
      , "envelope" .= encodeIdentityEnvelopeMapped payload.envelope
      ]

parseIdentityLedgerEvent :: EventType -> Value -> Either Text IdentityLedgerEvent
parseIdentityLedgerEvent (EventType tag) = mapLeftText . parseEither (withObject "IdentityLedgerEvent" go)
  where
    go o = do
      case tag of
        "IdentityRecorded" ->
          IdentityRecorded
            <$> ( IdentityRecordedData
                    <$> (unsafeLegacyIdFromLegacyText <$> o .: "legacyId")
                    <*> explicitParseField parseIdentityEnvelopeMapped o "envelope"
                )
        "IdentityAudited" ->
          IdentityAudited
            <$> ( IdentityAuditedData
                    <$> (unsafeLegacyIdFromLegacyText <$> o .: "legacyId")
                    <*> explicitParseField parseIdentityEnvelopeMapped o "envelope"
                )
        "LegacyIdentityImported" ->
          LegacyIdentityImported
            <$> ( LegacyIdentityImportedData
                    <$> (unsafeLegacyIdFromLegacyText <$> o .: "legacyId")
                    <*> explicitParseField parseIdentityEnvelopeMapped o "envelope"
                )
        _ -> fail ("unknown event type " <> show tag <> "; expected one of: " <> renderExpectedEventTypes identityLedgerEventTypes)

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

parseOptionalField :: Parser fieldValue -> (Value -> Parser fieldValue) -> KeyMap.KeyMap Value -> Key.Key -> Parser fieldValue
parseOptionalField onMissing parseItem objectValue key =
  case KeyMap.lookup key objectValue of
    Nothing -> onMissing
    Just _ -> explicitParseField parseItem objectValue key

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))