packages feed

pg-migrate-1.0.0.0: src/Database/PostgreSQL/Migrate/Types.hs

module Database.PostgreSQL.Migrate.Types
  ( ComponentName (..),
    MigrationName (..),
    MigrationId (..),
    MigrationChecksum (..),
    TransactionMode (..),
    MigrationKind (..),
    MigrationAction (..),
    Migration (..),
    MigrationComponent (..),
    MigrationPlan (..),
    componentNameText,
    migrationNameText,
    migrationIdComponent,
    migrationIdName,
    migrationNameOf,
    migrationChecksumOf,
    migrationKindOf,
    migrationModeOf,
    migrationActionOf,
    componentNameOf,
    componentDependenciesOf,
    componentMigrationsOf,
    planComponentsOf,
  )
where

import Hasql.Session qualified as Hasql.Session
import Hasql.Transaction qualified as Hasql.Transaction
import PgMigrate.Prelude

-- | Validated, application-stable component identifier.
newtype ComponentName = ComponentName
  { unComponentName :: Text
  }
  deriving stock (Generic, Eq, Ord, Show)

-- | Validated migration identifier local to one component.
newtype MigrationName = MigrationName
  { unMigrationName :: Text
  }
  deriving stock (Generic, Eq, Ord, Show)

-- | Globally unique migration identity: component plus local name.
data MigrationId = MigrationId
  { component :: !ComponentName,
    name :: !MigrationName
  }
  deriving stock (Generic, Eq, Ord, Show)

-- | SHA-256 fingerprint of the immutable migration payload.
newtype MigrationChecksum = MigrationChecksum
  { unMigrationChecksum :: ByteString
  }
  deriving stock (Generic, Eq, Ord, Show)

data TransactionMode
  = Transactional
  | NonTransactional
  deriving stock (Generic, Eq, Ord, Show)

data MigrationKind
  = SqlKind
  | HaskellKind
  deriving stock (Generic, Eq, Ord, Show)

data MigrationAction
  = SqlAction !ByteString
  | TransactionAction !(Hasql.Transaction.Transaction ())
  | SessionAction !(Hasql.Session.Session ())

-- | Validated migration definition with an immutable action and fingerprint.
data Migration = Migration
  { name :: !MigrationName,
    description :: !(Maybe Text),
    mode :: !TransactionMode,
    kind :: !MigrationKind,
    checksum :: !MigrationChecksum,
    action :: !MigrationAction
  }

-- | Ordered, non-empty migrations owned by one library component.
data MigrationComponent = MigrationComponent
  { name :: !ComponentName,
    dependencies :: !(Set ComponentName),
    migrations :: !(NonEmpty Migration)
  }

-- | Validated dependency-ordered composition of components.
newtype MigrationPlan = MigrationPlan
  { components :: NonEmpty MigrationComponent
  }

instance Show MigrationPlan where
  showsPrec precedence (MigrationPlan planComponents) =
    showsPrec precedence (summarizeComponent <$> planComponents)

summarizeComponent ::
  MigrationComponent ->
  (ComponentName, Set ComponentName, NonEmpty (MigrationName, MigrationChecksum, MigrationKind, TransactionMode))
summarizeComponent migrationComponent =
  ( componentNameOf migrationComponent,
    componentDependenciesOf migrationComponent,
    summarizeMigration <$> componentMigrationsOf migrationComponent
  )

summarizeMigration ::
  Migration ->
  (MigrationName, MigrationChecksum, MigrationKind, TransactionMode)
summarizeMigration migration =
  ( migrationNameOf migration,
    migrationChecksumOf migration,
    migrationKindOf migration,
    migrationModeOf migration
  )

componentNameText :: ComponentName -> Text
componentNameText (ComponentName value) = value

migrationNameText :: MigrationName -> Text
migrationNameText (MigrationName value) = value

migrationIdComponent :: MigrationId -> ComponentName
migrationIdComponent MigrationId {component} = component

migrationIdName :: MigrationId -> MigrationName
migrationIdName MigrationId {name} = name

migrationNameOf :: Migration -> MigrationName
migrationNameOf Migration {name} = name

migrationChecksumOf :: Migration -> MigrationChecksum
migrationChecksumOf Migration {checksum} = checksum

migrationKindOf :: Migration -> MigrationKind
migrationKindOf Migration {kind} = kind

migrationModeOf :: Migration -> TransactionMode
migrationModeOf Migration {mode} = mode

migrationActionOf :: Migration -> MigrationAction
migrationActionOf Migration {action} = action

componentNameOf :: MigrationComponent -> ComponentName
componentNameOf MigrationComponent {name} = name

componentDependenciesOf :: MigrationComponent -> Set ComponentName
componentDependenciesOf MigrationComponent {dependencies} = dependencies

componentMigrationsOf :: MigrationComponent -> NonEmpty Migration
componentMigrationsOf MigrationComponent {migrations} = migrations

planComponentsOf :: MigrationPlan -> NonEmpty MigrationComponent
planComponentsOf MigrationPlan {components} = components