2025-03-15 19:03:22 +02:00
package pilgrim_conf
2024-10-25 23:57:19 +03:00
import (
"log"
2025-03-18 22:33:44 +02:00
"mvvasilev.dev/pilgrim/internal/pilgrim_common"
2024-10-25 23:57:19 +03:00
)
const DefaultMigrationDirectory = "./migrations"
const DefaultMigrationTable = "pilgrim_migrations"
type MigrationPhase bool
const (
MigrationPhase_Up MigrationPhase = true
MigrationPhase_Down = false
)
type PilgrimConfigurationRetriever interface {
UrlParts ( ) UrlParts
MigrationDirectory ( ) string
MigrationPhase ( ) MigrationPhase
MigrationScript ( ) string
MigrationStrictOrdering ( ) bool
MigrationIsChecksumValidationEnabled ( ) bool
MigrationTable ( ) string
MigrationSchema ( ) string
ValidateChecksums ( ) bool
ValidateLatest ( ) bool
ValidateMigrationOrder ( ) bool
}
type pilgrimContext struct {
urlParts UrlParts
migrationDirectory string
migrationPhase MigrationPhase
migrationScript string
migrationStrictOrdering bool
migrationIsChecksumValidationEnabled bool
migrationSchema string
migrationTable string
validateMigrationOrder bool
validateLatest bool
validateChecksums bool
}
func NewPilgrimContext ( cli CliFlagRetriever , env EnvVarRetriever ) * pilgrimContext {
cliUrl , _ := cli . Url ( )
cliUrlParts := ParseDatabaseUrl ( cliUrl )
envUrl , _ := env . Url ( )
envUrlParts := ParseDatabaseUrl ( envUrl )
urlParts := UrlParts {
2025-03-15 13:02:47 +02:00
Driver : PickFirstAvailable (
2024-10-25 23:57:19 +03:00
cli . Driver ,
func ( ) ( DbDriver , bool ) { return DbDriver ( cliUrlParts . Driver ) , cliUrlParts . Driver != EmptyString } ,
env . Driver ,
func ( ) ( DbDriver , bool ) { return DbDriver ( envUrlParts . Driver ) , envUrlParts . Driver != EmptyString } ,
) ,
2025-03-15 13:02:47 +02:00
Username : PickFirstAvailable (
2024-10-25 23:57:19 +03:00
cli . Username ,
func ( ) ( string , bool ) { return cliUrlParts . Username , cliUrlParts . Username != EmptyString } ,
env . Username ,
func ( ) ( string , bool ) { return envUrlParts . Username , envUrlParts . Username != EmptyString } ,
) ,
2025-03-15 13:02:47 +02:00
Password : PickFirstAvailable (
2024-10-25 23:57:19 +03:00
cli . Password ,
func ( ) ( string , bool ) { return cliUrlParts . Password , cliUrlParts . Password != EmptyString } ,
env . Password ,
func ( ) ( string , bool ) { return envUrlParts . Password , envUrlParts . Password != EmptyString } ,
) ,
2025-03-15 13:02:47 +02:00
Host : PickFirstAvailable (
2024-10-25 23:57:19 +03:00
cli . Host ,
func ( ) ( string , bool ) { return cliUrlParts . Host , cliUrlParts . Host != EmptyString } ,
env . Host ,
func ( ) ( string , bool ) { return envUrlParts . Host , envUrlParts . Host != EmptyString } ,
) ,
2025-03-15 13:02:47 +02:00
Port : PickFirstAvailable (
2024-10-25 23:57:19 +03:00
cli . Port ,
func ( ) ( string , bool ) { return cliUrlParts . Port , cliUrlParts . Port != EmptyString } ,
env . Port ,
func ( ) ( string , bool ) { return envUrlParts . Port , envUrlParts . Port != EmptyString } ,
) ,
2025-03-15 13:02:47 +02:00
Segments : PickFirstAvailable (
2024-10-25 23:57:19 +03:00
cli . Segments ,
func ( ) ( [ ] string , bool ) { return cliUrlParts . Segments , cliUrlParts . Segments != nil } ,
env . Segments ,
func ( ) ( [ ] string , bool ) { return envUrlParts . Segments , envUrlParts . Segments != nil } ,
) ,
2025-03-15 13:02:47 +02:00
Arguments : PickFirstAvailable (
2024-10-25 23:57:19 +03:00
cli . Args ,
func ( ) ( map [ string ] string , bool ) { return cliUrlParts . Arguments , cliUrlParts . Arguments != nil } ,
env . Args ,
func ( ) ( map [ string ] string , bool ) { return envUrlParts . Arguments , envUrlParts . Arguments != nil } ,
) ,
}
isValid , err := urlParts . Validate ( )
if ! isValid {
log . Fatalln ( err )
}
2025-03-15 19:03:22 +02:00
migrationPhase , migrationScript , _ := determineMigrationPhaseAndScript ( cli )
2024-10-25 23:57:19 +03:00
2025-03-15 13:02:47 +02:00
migrationDirectory := PickFirstAvailable ( cli . Directory , env . Directory , func ( ) ( string , bool ) { return DefaultMigrationDirectory , true } )
migrationSchema := PickFirstAvailable ( cli . MigrationTableSchema , env . MigrationTableSchema , pickFirstDefault ( EmptyString ) ) // Default depends on driver, set empty for now
migrationTable := PickFirstAvailable ( cli . MigrationTable , env . MigrationTable , pickFirstDefault ( DefaultMigrationTable ) )
2024-10-25 23:57:19 +03:00
migrationStrictOrdering , _ := cli . IsStrictOrderingEnabled ( )
migrationIsChecksumValidationEnabled , _ := cli . IsChecksumValidationEnabled ( )
validateMigrationOrder , _ := cli . IsValidatingMigrationOrder ( )
validateLatest , _ := cli . IsValidatingLatest ( )
validateChecksums , _ := cli . IsValidatingLatest ( )
return & pilgrimContext {
urlParts ,
migrationDirectory ,
migrationPhase ,
migrationScript ,
migrationStrictOrdering ,
migrationIsChecksumValidationEnabled ,
migrationSchema ,
migrationTable ,
validateMigrationOrder ,
validateLatest ,
validateChecksums ,
}
}
2025-03-15 13:02:47 +02:00
type MigrationPhaseRetriever interface {
Script ( ) ( script string , isScriptProvided bool )
IsUp ( ) ( isUp , isUpProvided bool )
IsDown ( ) ( isDown , isDownProvided bool )
}
func determineMigrationPhaseAndScript ( cli MigrationPhaseRetriever ) ( phase MigrationPhase , script string , err error ) {
2024-10-25 23:57:19 +03:00
script , _ = cli . Script ( )
isUp , isUpProvided := cli . IsUp ( )
_ , isDownProvided := cli . IsDown ( )
if ( ! isUpProvided && ! isDownProvided ) || ( isUpProvided && isDownProvided ) {
2025-03-18 22:33:44 +02:00
return MigrationPhase_Down , EmptyString , pilgrim_common . PilgrimInvalidError ( "Must provide either --up or --down, but not both." )
2024-10-25 23:57:19 +03:00
}
if isUp {
phase = MigrationPhase_Up
} else {
phase = MigrationPhase_Down
}
return
}
func pickFirstDefault [ T any ] ( defaultVal T ) func ( ) ( value T , provided bool ) {
return func ( ) ( value T , provided bool ) {
return defaultVal , true
}
}
2025-03-15 13:02:47 +02:00
func PickFirstAvailable [ T any ] ( valueProviders ... func ( ) ( value T , provided bool ) ) ( value T ) {
2024-10-25 23:57:19 +03:00
for _ , getValue := range valueProviders {
val , provided := getValue ( )
if provided {
return val
}
}
value , _ = valueProviders [ len ( valueProviders ) - 1 ] ( )
return
}
func ( c * pilgrimContext ) UrlParts ( ) UrlParts {
return c . urlParts
}
func ( c * pilgrimContext ) MigrationDirectory ( ) string {
return c . migrationDirectory
}
func ( c * pilgrimContext ) MigrationPhase ( ) MigrationPhase {
return MigrationPhase ( c . migrationPhase )
}
func ( c * pilgrimContext ) MigrationScript ( ) string {
return c . migrationScript
}
func ( c * pilgrimContext ) MigrationStrictOrdering ( ) bool {
return c . migrationStrictOrdering
}
func ( c * pilgrimContext ) MigrationIsChecksumValidationEnabled ( ) bool {
return c . migrationIsChecksumValidationEnabled
}
func ( c * pilgrimContext ) MigrationSchema ( ) string {
return c . migrationSchema
}
func ( c * pilgrimContext ) MigrationTable ( ) string {
return c . migrationTable
}
func ( c * pilgrimContext ) ValidateChecksums ( ) bool {
return c . validateChecksums
}
func ( c * pilgrimContext ) ValidateMigrationOrder ( ) bool {
return c . validateMigrationOrder
}
func ( c * pilgrimContext ) ValidateLatest ( ) bool {
return c . validateLatest
}