# Manage database migrations def --env load-migration-env [project_root: string] { let server_dir = ($project_root | path join "server") let env_files = [ ($server_dir | path join ".env") ($server_dir | path join ".env.local") ] mut loaded_files = [] for env_file in $env_files { if ($env_file | path exists) { let env_vars = (open $env_file | lines | each { |line| $line | str trim } | where { |line| not ($line | str starts-with '#') and ($line | str length) > 0 and ($line | str contains '=') } | split column "=" -n 2 | rename key value | update key { |it| $it.key | str trim } | update value { |it| if ($it.value | is-empty) { "" } else { let raw_value = ($it.value | str trim) let is_quoted = (($raw_value | str starts-with '"') or ($raw_value | str starts-with "'")) let normalized = ($raw_value | str trim -c '"' | str trim -c "'") if $is_quoted { $normalized } else { $normalized | str replace -r '\s+#.*$' '' } } } | reduce -f {} { |item, acc| $acc | upsert $item.key $item.value }) if (($env_vars | columns | length) > 0) { load-env $env_vars } $loaded_files = ($loaded_files | append ($env_file | path basename)) } } if (($loaded_files | length) > 0) { print $"($env.ALGA_COLOR_CYAN)Loaded migration env from ($loaded_files | str join ', '); server/.env.local overrides server/.env.($env.ALGA_COLOR_RESET)" } else { print $"($env.ALGA_COLOR_YELLOW)No server env files found (expected server/.env and optionally server/.env.local). Using current shell env only.($env.ALGA_COLOR_RESET)" } } export def run-migrate [ action: string # The migration action to perform: up, latest, down, or status --ee # Run combined CE + EE migrations (latest, down, status) ] { let project_root = find-project-root load-migration-env $project_root if $ee { if not ($action in ["latest", "down", "status"]) { error make { msg: $"($env.ALGA_COLOR_RED)--ee is only supported with 'latest', 'down', or 'status' actions($env.ALGA_COLOR_RESET)" } } # Map action to npm script name let npm_script = match $action { "latest" => "migrate:ee", "down" => "migrate:ee:down", "status" => "migrate:ee:status" } print $"($env.ALGA_COLOR_CYAN)Running CE + EE migrations ($action)...($env.ALGA_COLOR_RESET)" let result = do { cd $project_root npm -w server run $npm_script | complete } if $result.exit_code == 0 { if not ($result.stdout | is-empty) { print $result.stdout } print $"($env.ALGA_COLOR_GREEN)CE + EE migrations ($action) completed successfully.($env.ALGA_COLOR_RESET)" return } if not ($result.stderr | is-empty) { print $"($env.ALGA_COLOR_RED)($result.stderr)($env.ALGA_COLOR_RESET)" } error make { msg: $"($env.ALGA_COLOR_RED)CE + EE migrations ($action) failed($env.ALGA_COLOR_RESET)", code: $result.exit_code } } match $action { "up" => { print $"($env.ALGA_COLOR_CYAN)Running next pending database migration...($env.ALGA_COLOR_RESET)" # Change to the server directory and run the knex command # Capture stdout and stderr let result = do { cd ($project_root | path join "server") npx knex migrate:up --knexfile knexfile.cjs --env migration | complete # Use migrate:up } # Print output or error if $result.exit_code == 0 { print $result.stdout # Keep knex output as is print $"($env.ALGA_COLOR_GREEN)Migration 'up' completed successfully.($env.ALGA_COLOR_RESET)" } else { print $"($env.ALGA_COLOR_RED)($result.stderr)($env.ALGA_COLOR_RESET)" error make { msg: $"($env.ALGA_COLOR_RED)Migration 'up' failed($env.ALGA_COLOR_RESET)", code: $result.exit_code } } } "latest" => { # Add separate case for 'latest' print $"($env.ALGA_COLOR_CYAN)Running all pending database migrations...($env.ALGA_COLOR_RESET)" # Change to the server directory and run the knex command # Capture stdout and stderr let result = do { cd ($project_root | path join "server") npx knex migrate:latest --knexfile knexfile.cjs --env migration | complete # Use migrate:latest } # Print output or error if $result.exit_code == 0 { print $result.stdout # Keep knex output as is print $"($env.ALGA_COLOR_GREEN)Migrations 'latest' completed successfully.($env.ALGA_COLOR_RESET)" } else { print $"($env.ALGA_COLOR_RED)($result.stderr)($env.ALGA_COLOR_RESET)" error make { msg: $"($env.ALGA_COLOR_RED)Migration 'latest' failed($env.ALGA_COLOR_RESET)", code: $result.exit_code } } } "down" => { print $"($env.ALGA_COLOR_CYAN)Reverting last database migration...($env.ALGA_COLOR_RESET)" # Change to the server directory and run the knex command # Capture stdout and stderr let result = do { cd ($project_root | path join "server") npx knex migrate:down --knexfile knexfile.cjs --env migration | complete } # Print output or error if $result.exit_code == 0 { print $result.stdout # Keep knex output as is print $"($env.ALGA_COLOR_GREEN)Migration reverted successfully.($env.ALGA_COLOR_RESET)" } else { print $"($env.ALGA_COLOR_RED)($result.stderr)($env.ALGA_COLOR_RESET)" error make { msg: $"($env.ALGA_COLOR_RED)Migration revert failed($env.ALGA_COLOR_RESET)", code: $result.exit_code } } } "status" => { print $"($env.ALGA_COLOR_CYAN)Checking migration status...($env.ALGA_COLOR_RESET)" # Change to the server directory and run the knex command # Capture stdout and stderr let result = do { cd ($project_root | path join "server") npx knex migrate:status --knexfile knexfile.cjs --env migration | complete } # Print output or error if $result.exit_code == 0 { print $result.stdout # Keep knex output as is print $"($env.ALGA_COLOR_GREEN)Migration status checked successfully.($env.ALGA_COLOR_RESET)" } else { print $"($env.ALGA_COLOR_RED)($result.stderr)($env.ALGA_COLOR_RESET)" error make { msg: $"($env.ALGA_COLOR_RED)Checking migration status failed($env.ALGA_COLOR_RESET)", code: $result.exit_code } } } _ => { # This case should technically not be reachable due to the type annotation # but it's good practice to include it. error make { msg: $"($env.ALGA_COLOR_RED)Unknown migration action: ($action)($env.ALGA_COLOR_RESET)" } } } }