#!/usr/bin/env pwsh <# .SYNOPSIS Manage the local Postgres container used by the YesChef backend in dev. .DESCRIPTION Spins up a postgres:17 container named "yeschef-pg" on localhost:5432 with the database/user/password the API's appsettings.json expects. Persists data in a Docker volume so restarts retain state until reset is run. .PARAMETER Command start - Create + start the container (no-op if already running). stop - Stop the container, leaving the volume intact. reset - Stop and remove the container AND its data volume. Next start is a fresh DB; the API will run all migrations from scratch. status - Print the container state and connection string. logs - Tail the container logs. .EXAMPLE ./scripts/dev-db.ps1 start ./scripts/dev-db.ps1 reset #> param( [Parameter(Position = 0)] [ValidateSet('start', 'stop', 'reset', 'status', 'logs')] [string]$Command = 'status' ) $ErrorActionPreference = 'Stop' $Name = 'yeschef-pg' $Volume = 'yeschef-pgdata-dev' $Image = 'postgres:17' $ConnectionString = 'Host=localhost;Database=yeschef;Username=yeschef;Password=yeschef' function Get-ContainerState { # docker inspect exits non-zero when the container is missing; swallow # that so $ErrorActionPreference='Stop' doesn't abort the script and # so the caller's exit code stays clean. $state = & docker inspect --format '{{.State.Status}}' $Name 2>$null $code = $LASTEXITCODE $global:LASTEXITCODE = 0 if ($code -ne 0) { return 'absent' } return $state } function Start-DevDb { $state = Get-ContainerState if ($state -eq 'running') { Write-Host "Container '$Name' already running." -ForegroundColor Green return } if ($state -ne 'absent') { Write-Host "Starting existing container '$Name'..." docker start $Name | Out-Null } else { Write-Host "Creating new container '$Name'..." docker run -d ` --name $Name ` -p 5432:5432 ` -e POSTGRES_DB=yeschef ` -e POSTGRES_USER=yeschef ` -e POSTGRES_PASSWORD=yeschef ` -v "${Volume}:/var/lib/postgresql/data" ` $Image | Out-Null } # Wait until pg_isready returns healthy so the caller can immediately # start the API without racing on the listener. Write-Host "Waiting for Postgres to accept connections..." for ($i = 0; $i -lt 30; $i++) { docker exec $Name pg_isready -U yeschef -d yeschef -q 2>$null if ($LASTEXITCODE -eq 0) { Write-Host "Ready. Connection string:" -ForegroundColor Green Write-Host " $ConnectionString" return } Start-Sleep -Seconds 1 } Write-Warning "Postgres did not become ready within 30s. Check 'docker logs $Name'." } function Stop-DevDb { $state = Get-ContainerState if ($state -eq 'absent') { Write-Host "Container '$Name' is not present." return } docker stop $Name | Out-Null Write-Host "Stopped '$Name'." -ForegroundColor Yellow } function Reset-DevDb { $state = Get-ContainerState if ($state -ne 'absent') { docker rm -f $Name | Out-Null Write-Host "Removed container '$Name'." } docker volume rm $Volume 2>$null | Out-Null Write-Host "Removed volume '$Volume'. Next 'start' will create a fresh database." -ForegroundColor Yellow } function Show-Status { $state = Get-ContainerState Write-Host "Container: $Name" Write-Host " State : $state" Write-Host " Volume: $Volume" Write-Host " Conn : $ConnectionString" } switch ($Command) { 'start' { Start-DevDb } 'stop' { Stop-DevDb } 'reset' { Reset-DevDb } 'status' { Show-Status } 'logs' { docker logs -f $Name } }