From b4c4aafc9972665143d53b4d0723105f55575d66 Mon Sep 17 00:00:00 2001 From: MaysWind Date: Tue, 17 Feb 2026 17:22:23 +0800 Subject: [PATCH] support loading environment variables from .env file --- .gitignore | 4 ++ scripts/ebktools.ps1 | 92 +++++++++++++++++++++++++++++++++++++++++++- scripts/ebktools.sh | 74 +++++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index bd626db5..eea2c649 100644 --- a/.gitignore +++ b/.gitignore @@ -152,6 +152,10 @@ dist/ ezbookkeeping package/ +# Environment variable files +.env +**/.env + # Other directories data/ storage/ diff --git a/scripts/ebktools.ps1 b/scripts/ebktools.ps1 index 40b19961..179f81e4 100755 --- a/scripts/ebktools.ps1 +++ b/scripts/ebktools.ps1 @@ -20,6 +20,9 @@ param( [string[]]$CommandArgs ) +$script:EBKTOOL_SERVER_BASEURL = $env:EBKTOOL_SERVER_BASEURL +$script:EBKTOOL_TOKEN = $env:EBKTOOL_TOKEN + # API Configuration Structure $API_CONFIGS = @( @{ @@ -699,6 +702,87 @@ function Write-Yellow($msg) { Write-Host $msg -ForegroundColor Yellow } +function Import-DotEnvFile { + param( + [string]$Path + ) + + if (-not (Test-Path -Path $Path -PathType Leaf)) { + return $false + } + + try { + Get-Content -Path $Path -ErrorAction Stop | ForEach-Object { + $line = $_.Trim() + + if ([string]::IsNullOrWhiteSpace($line) -or $line.StartsWith('#')) { + return + } + + if ($line -match '^([^=]+)=(.*)$') { + $key = $matches[1].Trim() + $value = $matches[2].Trim() + + if ($value -match '^["''](.*)["'']$') { + $value = $matches[1] + } + + if ($key -eq 'EBKTOOL_SERVER_BASEURL' -or $key -eq 'EBKTOOL_TOKEN') { + Set-Variable -Name $key -Value $value -Scope Script -Force + } + } + } + return $true + } catch { + return $false + } +} + +function Initialize-EnvironmentVariables { + if ($script:EBKTOOL_SERVER_BASEURL -and $script:EBKTOOL_TOKEN) { + return + } + + $currentDir = Get-Location + $parentDir = Split-Path -Path $currentDir -Parent + $homeDir = if ($IsWindows -or $env:OS -match 'Windows') { + $env:USERPROFILE + } else { + $env:HOME + } + + if (-not $script:EBKTOOL_SERVER_BASEURL -or -not $script:EBKTOOL_TOKEN) { + $envPath = Join-Path -Path $currentDir -ChildPath '.env' + if (Import-DotEnvFile -Path $envPath) { + if ($script:EBKTOOL_SERVER_BASEURL -and $script:EBKTOOL_TOKEN) { + return + } + } + } + + if (-not $script:EBKTOOL_SERVER_BASEURL -or -not $script:EBKTOOL_TOKEN) { + if ($parentDir) { + $envPath = Join-Path -Path $parentDir -ChildPath '.env' + if (Import-DotEnvFile -Path $envPath) { + if ($script:EBKTOOL_SERVER_BASEURL -and $script:EBKTOOL_TOKEN) { + return + } + } + } + } + + if (-not $script:EBKTOOL_SERVER_BASEURL -or -not $script:EBKTOOL_TOKEN) { + if ($homeDir) { + $envPath = Join-Path -Path $homeDir -ChildPath '.env' + if (Import-DotEnvFile -Path $envPath) { + if ($script:EBKTOOL_SERVER_BASEURL -and $script:EBKTOOL_TOKEN) { + return + } + } + } + } +} + function Url-Encode { param([string]$text) return [System.Uri]::EscapeDataString($text) @@ -1085,6 +1169,8 @@ function Show-Help { Write-Host " EBKTOOL_SERVER_BASEURL ezBookkeeping server base URL (e.g., http://localhost:8080)" Write-Host " EBKTOOL_TOKEN ezBookkeeping API token" Write-Host "" + Write-Host " You can also set the above environment variables in a .env file located in the current directory, parent directory or home directory." + Write-Host "" Write-Host "Global Options:" Write-Host " -tzName The IANA timezone name of current timezone. For example, for Beijing Time it is 'Asia/Shanghai'." Write-Host " -tzOffset The offset in minutes of the current timezone from UTC. For example, for Beijing Time which is UTC+8, the value is '480'. If both '-tzName' and '-tzOffset' are set, '-tzName' takes priority. If neither is set, the current system time zone is used by default." @@ -1284,8 +1370,8 @@ function Invoke-Api { exit 1 } - $serverBaseUrl = $env:EBKTOOL_SERVER_BASEURL - $authToken = $env:EBKTOOL_TOKEN + $serverBaseUrl = $script:EBKTOOL_SERVER_BASEURL + $authToken = $script:EBKTOOL_TOKEN if (-not $serverBaseUrl) { Write-Red "Error: Environment variable 'EBKTOOL_SERVER_BASEURL' is not set." @@ -1416,6 +1502,8 @@ function Invoke-Api { } function Main { + Initialize-EnvironmentVariables + if ($Command -eq "list") { Show-CommandList exit 0 diff --git a/scripts/ebktools.sh b/scripts/ebktools.sh index 31bd810e..0219769c 100755 --- a/scripts/ebktools.sh +++ b/scripts/ebktools.sh @@ -531,6 +531,8 @@ API_CONFIGS='[ } ]' +EBKTOOL_SERVER_BASEURL="${EBKTOOL_SERVER_BASEURL}" +EBKTOOL_TOKEN="${EBKTOOL_TOKEN}" TIMEZONE_NAME="" TIMEZONE_OFFSET="" RAW_RESPONSE="false" @@ -553,6 +555,74 @@ check_dependency() { done } +load_env_file() { + env_file="$1" + + if [ ! -f "$env_file" ]; then + return 1 + fi + + while IFS= read -r line || [ -n "$line" ]; do + case "$line" in + ''|'#'*) continue ;; + esac + + line="$(echo "$line" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + + if ! echo "$line" | grep -q '='; then + continue + fi + + key="$(echo "$line" | cut -d'=' -f1)" + value="$(echo "$line" | cut -d'=' -f2-)" + value="$(echo "$value" | sed -e 's/^["'"'"']//' -e 's/["'"'"']$//')" + + case "$key" in + EBKTOOL_SERVER_BASEURL|EBKTOOL_TOKEN) + eval "$key=\"\$value\"" + ;; + esac + done < "$env_file" + + return 0 +} + +load_env_from_paths() { + if [ -n "$EBKTOOL_SERVER_BASEURL" ] && [ -n "$EBKTOOL_TOKEN" ]; then + return 0 + fi + + current_dir="$(pwd)" + parent_dir="$(dirname "$current_dir")" + home_dir="$HOME" + + if [ -z "$EBKTOOL_SERVER_BASEURL" ] || [ -z "$EBKTOOL_TOKEN" ]; then + if load_env_file "$current_dir/.env"; then + if [ -n "$EBKTOOL_SERVER_BASEURL" ] && [ -n "$EBKTOOL_TOKEN" ]; then + return 0 + fi + fi + fi + + if [ -z "$EBKTOOL_SERVER_BASEURL" ] || [ -z "$EBKTOOL_TOKEN" ]; then + if load_env_file "$parent_dir/.env"; then + if [ -n "$EBKTOOL_SERVER_BASEURL" ] && [ -n "$EBKTOOL_TOKEN" ]; then + return 0 + fi + fi + fi + + if [ -z "$EBKTOOL_SERVER_BASEURL" ] || [ -z "$EBKTOOL_TOKEN" ]; then + if load_env_file "$home_dir/.env"; then + if [ -n "$EBKTOOL_SERVER_BASEURL" ] && [ -n "$EBKTOOL_TOKEN" ]; then + return 0 + fi + fi + fi + + return 0 +} + url_encode() { text="$1" printf "%s" "$text" | jq -sRr @uri @@ -747,6 +817,8 @@ Environment Variables (Required): EBKTOOL_SERVER_BASEURL ezBookkeeping server base URL (e.g., http://localhost:8080) EBKTOOL_TOKEN ezBookkeeping API token + You can also set the above environment variables in a .env file located in the current directory, parent directory or home directory. + Global Options: --tz-name The IANA timezone name of current timezone. For example, for Beijing Time it is 'Asia/Shanghai'. --tz-offset The offset in minutes of the current timezone from UTC. For example, for Beijing Time which is UTC+8, the value is '480'. If both '--tz-name' and '--tz-offset' are set, '--tz-name' takes priority. If neither is set, the current system time zone is used by default. @@ -1128,6 +1200,8 @@ call_api() { main() { check_dependency "grep sed awk date curl jq" + load_env_from_paths + COMMAND="" while [ $# -gt 0 ]; do