Source/Set-DotEnvValue.ps1
|
<# .SYNOPSIS Sets a single key's value in a .env file. .DESCRIPTION Writes a KEY=VALUE line into the specified .env file. Replaces the value in place if the key already exists, appends a new line if it doesn't, and creates the file if it doesn't exist yet. Accepts either a key-value pair, or a single "KEY=VALUE" formatted string, validated against that shape. Never touches any environment variable. .PARAMETER Name The key to set. Used together with -Value. .PARAMETER Value The value to write for that key. Any object is accepted and converted to string. Used together with -Name. .PARAMETER Text A single "KEY=VALUE" formatted line, as an alternative to passing -Name and -Value separately, converted via ConvertFrom-DotEnv. Throws if it doesn't match that shape. .PARAMETER Path The path to the .env file. If not specified, writes to .env in the current directory. .EXAMPLE Set-DotEnvValue -Name "Foo" -Value "Bar" -Path ".env" .EXAMPLE Set-DotEnvValue -Text "Foo=Bar" -Path ".env" .EXAMPLE [pscustomobject]@{ Name = "Foo"; Value = "Bar" } | Set-DotEnvValue -Path ".env" .EXAMPLE "Foo=Bar", "Baz=Qux" | Set-DotEnvValue -Path ".env" .INPUTS [System.Management.Automation.PSObject] Accepts objects with Name and Value properties via pipeline by property name. [System.String] A single "KEY=VALUE" formatted line. Accepts pipeline input by value. .OUTPUTS None. #> function Set-DotEnvValue { [CmdletBinding(DefaultParameterSetName = "Text", SupportsShouldProcess)] param( [Parameter(Mandatory, ParameterSetName = "Object", ValueFromPipelineByPropertyName)] [string] $Name, [Parameter(Mandatory, ParameterSetName = "Object", ValueFromPipelineByPropertyName)] [object] $Value, [Parameter(Mandatory, ParameterSetName = "Text", ValueFromPipeline)] [string] $Text, [string] $Path = ".env" ) process { if ($PSCmdlet.ParameterSetName -eq "Text") { $parsed = ConvertFrom-DotEnv -Text $Text $Name = @($parsed.Keys)[0] $Value = $parsed[$Name] } $line = "$Name=$Value" if (-not $PSCmdlet.ShouldProcess($Path, "Set '$Name' in .env file")) { return } if (-not (Test-Path -Path $Path)) { Set-Content -Path $Path -Value $line return } $found = $False $lines = Get-Content -Path $Path | ForEach-Object -Process { if ($_ -match '^\s*([^#][^=]+)=(.*)$' -and $matches[1].Trim() -eq $Name) { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "")] $found = $True $line } else { $_ } } if (-not $found) { $lines = @($lines) + $line } Set-Content -Path $Path -Value $lines } } |