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

    }

}