#requires -Modules powershell-yaml param( [string]$StartDir = (Split-Path -Parent $MyInvocation.MyCommand.Path) ) function Find-WorkspaceRoot($startDir) { $current = $startDir while ($true) { if (Test-Path -LiteralPath (Join-Path $current 'workspace.yml')) { return $current } $parent = Split-Path -Parent $current if ($parent -eq $current) { throw "workspace.yml not found from the provided start directory" } $current = $parent } } function Parse-Yaml($text) { try { $parsedYaml = ConvertFrom-Yaml $text return $parsedYaml ?? @{} } catch { throw "Failed to parse YAML content : $_" } } function Parse-YamlFile($path) { return Parse-Yaml (Get-Content -LiteralPath $path -Raw) } function Strip-Quotes($value) { $trim = $value.Trim() if (($trim.StartsWith('"') -and $trim.EndsWith('"')) -or ($trim.StartsWith("'") -and $trim.EndsWith("'"))) { return $trim.Substring(1, $trim.Length - 2) } return $trim } function Parse-Workspace($workspacePath) { $lines = Get-Content -LiteralPath $workspacePath $collections = @() $inCollections = $false $current = $null foreach ($line in $lines) { $trim = $line.Trim() if (-not $inCollections -and $trim -eq 'collections:') { $inCollections = $true continue } if (-not $inCollections) { continue } if (-not ($line.StartsWith(' ') -or $line.StartsWith("`t"))) { # && trimmed? break } if ($line -match '^\s*-\s+name:\s*(.+)$') { $name = Strip-Quotes $Matches[1] $current = [ordered]@{ name = $name } $collections += $current continue } if ($line -match '^\s*path:\s*(.+)$' -and $current) { $current.path = Strip-Quotes $Matches[1] } } return @{ collections = $collections } } function Sanitize-VarName($name) { $sanitized = ([string]$name).Trim() -replace '[{}]', '' -replace '[^A-Za-z0-9_]', '_' -replace '^([0-9])', '_$1' if ([string]::IsNullOrWhiteSpace($sanitized)) { return 'value' } return $sanitized } function Parse-PlaceholderContent($content) { $trimmed = ([string]$content).Trim(); $dotenvMatch = [regex]::Match($trimmed, '^\$dotenv\s+(.+)$', 'IgnoreCase') if ($dotenvMatch.Success) { return @{ name = $dotenvMatch.Groups[1].value.Trim() isDotenv = $true } } return @{ name = $trimmed isDotenv = $false } } function Collect-Placeholders($value) { # Se non è stringa → restituisci array vuoto if ($value -isnot [string]) { return @() } $placeholders = @() $regex = [regex]'\{\{([^{}]+)\}\}' $foundMatches = $regex.Matches($value) foreach ($m in $foundMatches) { $inner = $m.Groups[1].value $parsed = Parse-PlaceholderContent $inner $placeholders += $parsed.name } return $placeholders } function Find-Block ([string[]]$lines, $keyName) { for ($i = 0; $i -lt $lines.Count; $i++) { $trimmed = $lines[$i].Trim() if ($trimmed -ne $keyName -and -not $trimmed.StartsWith("$($keyName):")) { continue } $lineIndent = ([regex]::Match($lines[$i], '^\s*')).value.Length $block = @() for ($j = $i + 1; $j -lt $lines.Count; $j++) { $currentLine = $lines[$j] $currentTrimmed = $currentLine.Trim() if ([string]::IsNullOrWhiteSpace($currentTrimmed)) { $block += $currentLine continue } $currentIndent = ([regex]::Match($currentLine, '^\s*')).value.Length # Caso 1: indentazione <= indentazione della chiave e NON inizia con spazio → fine blocco if ($currentIndent -le $lineIndent -and -not $currentLine.StartsWith(' ')) { break } # Caso 2: indentazione <= indentazione della chiave e riga commento → includi if ($currentIndent -le $lineIndent -and $currentTrimmed.StartsWith('#')) { $block += $currentLine continue } # Caso 3: indentazione <= indentazione della chiave → fine blocco if ($currentIndent -le $lineIndent) { break } # Altrimenti la riga fa parte del blocco $block += $currentLine } return $block } return @() } function Parse-RequestInfo ($text) { $lines = $text -split '\r?\n' $infoLines = Find-Block -Lines $lines -KeyName 'info' $joined = ($infoLines -join "`n") $nameMatch = [regex]::Match($joined, '^\s*name:\s*(.+)$', 'Multiline') if ($nameMatch.Success) { return Strip-Quotes $nameMatch.Groups[1].value } return '' } function Parse-HttpBlock ($text) { # ConvertFrom-Yaml restituisce $null se il testo è vuoto o non valido $parsed = Parse-Yaml $text if (-not $parsed) { $parsed = @{} } $http = $parsed.http if (-not $http) { $http = @{} } $headers = @() $headerList = @() if ($http.headers -is [System.Collections.IEnumerable]) { $headerList = $http.headers } foreach ($header in $headerList) { if (-not $header -or $header -isnot [psobject] -and $header -isnot [hashtable]) { continue } $name = ([string]($header.name ?? '')).Trim() $value = ([string]($header.value ?? '')).Trim() $headers += @{ name = $name value = $value } } $params = @() if ($http.params -is [System.Collections.IEnumerable]) { $params = $http.params } $body = $null if ($http.body -and ($http.body -is [psobject] -or $http.body -is [hashtable])) { $body = $http.body } return @{ method = $http.method ?? 'GET' url = $http.url ?? '' params = $params headers = $headers body = $body } } function Format-VariableValue ($value, [hashtable]$RenderContext = @{}) { if ($null -eq $value) { return "''" } if ($value -is [string]) { if ($value.Trim() -eq '') { return "''" } $renderedValue = $value if ($RenderContext.ContainsKey('renderValue') -and $RenderContext.renderValue) { $renderedValue = $RenderContext.renderValue.Invoke($value) } if ($renderedValue -match '\s') { $escaped = $renderedValue -replace '"', '\"' return '"' + $escaped + '"' } return $renderedValue } return ($value | ConvertTo-Json -Depth 20 -Compress) } function Merge-RequestConfig ($base, $updates) { if (-not $updates -or ($updates -isnot [psobject] -and $updates -isnot [hashtable])) { return $base } # Clona base (shallow clone) $merged = @{} if ($base -is [psobject] -or $base -is [hashtable]) { foreach ($key in $base.Keys) { $merged[$key] = $base[$key] } } if ($updates.ContainsKey('auth')) { $auth = $updates.auth if ($auth -eq 'inherit') { if ($merged.ContainsKey('auth') -and ($merged.auth -is [psobject] -or $merged.auth -is [hashtable])) { $merged.auth = $merged.auth } else { $merged.Remove('auth') } } elseif ($auth -is [psobject] -or $auth -is [hashtable]) { $merged.auth = $auth } else { $merged.Remove('auth') } } else { $merged.Remove('auth') } if ($updates.variables -is [System.Collections.IEnumerable]) { $variables = @() if ($base.variables -is [System.Collections.IEnumerable]) { $variables = @($base.variables) } # Mappa per nome $byName = @{} foreach ($variable in $variables) { if ($variable -and $variable.name) { $byName[[string]$variable.name] = $variable } } foreach ($variable in $updates.variables) { if ($variable -and $variable.name) { $byName[[string]$variable.name] = $variable } } $merged.variables = $byName.Values } return $merged } function Get-RequestConfigForFile ($yamlFile, $sourceDir) { $resolved = @() $seenFiles = New-Object System.Collections.Generic.HashSet[string] function Add-File ($FilePath) { if (-not $FilePath -or $seenFiles.Contains($FilePath)) { return } $seenFiles.Add($FilePath) if (-not (Test-Path $FilePath)) { return } try { $parsed = (Get-Content -Raw $FilePath | ConvertFrom-Yaml) if (-not $parsed) { $parsed = @{} } $requestConfig = $null # Caso 1: parsed.request esiste ed è un oggetto if ($parsed.request -and ($parsed.request -is [psobject] -or $parsed.request -is [hashtable])) { $requestConfig = $parsed.request } # Caso 2: parsed è un oggetto e contiene auth/variables elseif ($parsed -is [psobject] -or $parsed -is [hashtable]) { $config = @{} # auth if ($parsed.ContainsKey('auth')) { $config.auth = $parsed.auth } elseif ($parsed.http -and ($parsed.http -is [psobject] -or $parsed.http -is [hashtable]) -and $parsed.http.ContainsKey('auth')) { $config.auth = $parsed.http.auth } # variables if ($parsed.variables -is [System.Collections.IEnumerable]) { $config.variables = $parsed.variables } if ($config.Count -gt 0) { $requestConfig = $config } } if ($null -ne $requestConfig) { $resolved += $requestConfig } elseif ((Resolve-Path $FilePath).Path -eq (Resolve-Path $yamlFile).Path) { $resolved += @{} } } catch { # Ignora file YAML non validi } } # Costruisci la catena delle directory $dirChain = @() $currentDir = Split-Path -Parent $yamlFile while ($true) { $dirChain = ,$currentDir + $dirChain if ($currentDir -eq $sourceDir) { break } $parentDir = Split-Path -Parent $currentDir if ($parentDir -eq $currentDir) { break } $currentDir = $parentDir } foreach ($dir in $dirChain) { Add-File (Join-Path $dir 'opencollection.yml') Add-File (Join-Path $dir 'folder.yml') } # Aggiungi il file principale Add-File $yamlFile $result = @{} foreach ($config in $resolved) { $result = Merge-RequestConfig $result $config } return $result } function Build-RequestContent ( $request, $requestName, $requestConfig = @{}, [System.Collections.Generic.HashSet[string]]$dotenvVariables = $(New-Object System.Collections.Generic.HashSet[string]) ) { $lines = @() $variableDefinitions = @() $commentedVariableDefinitions = @() $parameterVariableDefinitions = @() $seenVariables = New-Object System.Collections.Generic.HashSet[string] function Add-Variable ($Name, $Value) { if (-not $Name) { return } $normalized = ([string]$Name).Trim() if (-not $normalized) { return } if ($seenVariables.Contains($normalized)) { return } if ($dotenvVariables.Contains($normalized)) { return } $seenVariables.Add($normalized) $variableDefinitions += @{ name=$normalized; value=$Value } } function Add-ParameterVariable ($Name, $Value) { if (-not $Name) { return } $normalized = ([string]$Name).Trim() if (-not $normalized) { return } if ($seenVariables.Contains($normalized)) { return } if ($dotenvVariables.Contains($normalized)) { return } $seenVariables.Add($normalized) $parameterVariableDefinitions += @{ name=$normalized; value=$Value } } function Add-CommentedVariable ($Name, $Value) { if (-not $Name) { return } $normalized = ([string]$Name).Trim() if (-not $normalized) { return } $commentedVariableDefinitions += @{ name=$normalized; value=$Value } } function Add-ReferencedVariables ($Value, $FallbackValue = 'YOUR_VALUE_HERE') { foreach ($placeholder in Collect-Placeholders ([string]$Value)) { Add-Variable $placeholder $FallbackValue } } function RenderJsonValue ($Value) { if ($Value -is [string]) { return Render-Value $Value } elseif ($Value -is [System.Collections.IEnumerable]) { return @($Value | ForEach-Object { RenderJsonValue $_ }) } elseif ($Value -is [psobject] -or $Value -is [hashtable]) { $result = @{} foreach ($key in $Value.Keys) { $result[$key] = RenderJsonValue $Value[$key] } return $result } return $Value } function Add-ParameterVariables ($Name, $Value) { Add-ParameterVariable $Name $Value } function Add-CommentedVariables ($Name, $Value) { Add-CommentedVariable $Name $Value } function Render-Value ($Value) { if ($Value -isnot [string]) { return $Value } return ($Value -replace '\{\{([^{}]+)\}\}', { param($match,$inner) $placeholder = Parse-PlaceholderContent $inner if ($placeholder.isDotenv) { return $match } if ($placeholder.name -and $dotenvVariables.Contains($placeholder.name)) { return "{{$dotenv $($placeholder.name)}}" } return $match }) } # ------------------------- # Variabili da requestConfig # ------------------------- $configVariables = @() if ($requestConfig.variables -is [System.Collections.IEnumerable]) { $configVariables = $requestConfig.variables } foreach ($variable in $configVariables) { if ($variable -and $variable.name) { Add-Variable $variable.name $variable.value } } # ------------------------- # URL # ------------------------- $url = $request.url ?? '' if ($url) { Add-ReferencedVariables $url $url = ($url -replace ':([A-Za-z0-9_]+)', '{{$1}}') $url = Render-Value $url $url = $url.Split('?')[0] } # ------------------------- # Headers # ------------------------- $queryParams = @() $headers = @() function Add-Header ($Name, $Value) { if (-not $Name) { return } Add-ReferencedVariables ($Value ?? '') $headers += @{ name = ([string]$Name).Trim() value = Render-Value ($Value ?? '') } } foreach ($header in ($request.headers ?? @())) { if ($header -and $header.name) { Add-Header $header.name ($header.value ?? '') } } foreach ($header in ($requestConfig.headers ?? @())) { if ($header -and $header.name) { Add-Header $header.name ($header.value ?? '') } } # ------------------------- # Params # ------------------------- foreach ($param in ($request.params ?? @())) { $name = $param.name ?? '' $value = $param.value ?? '' $type = ([string]($param.type ?? 'query')).ToLower() $disabled = ([string]$param.disabled).ToLower() -eq 'true' if ($disabled) { Add-CommentedVariables $name $value continue } Add-ReferencedVariables $value if ($type -eq 'header') { $headers += @{ name=$name; value=(Render-Value $value) } } else { $queryParams += @{ name=$name; value="{{$name}}" } Add-ParameterVariables $name $value } } # ------------------------- # Auth # ------------------------- if ($requestConfig.auth) { switch ($requestConfig.auth.type) { 'bearer' { Add-ReferencedVariables ($requestConfig.auth.token ?? '') Add-Header 'Authorization' ("Bearer " + (Render-Value ($requestConfig.auth.token ?? ''))) } 'basic' { $username = $requestConfig.auth.username ?? '' $password = $requestConfig.auth.password ?? '' Add-ReferencedVariables $username Add-ReferencedVariables $password Add-Header 'Authorization' ("Basic " + (Render-Value $username) + ":" + (Render-Value $password)) } default { $headers += @{ name = "UNKNOWN_$($requestConfig.auth.type)" value = "Basic $($requestConfig.auth.token)" } } } } # ------------------------- # Commented variables # ------------------------- if ($commentedVariableDefinitions.Count -gt 0) { $lines += "# Other variables for $requestName" foreach ($variable in $commentedVariableDefinitions) { $lines += "# @$(Sanitize-VarName $variable.name)$VARIABLE_NAME_VALUE_SEPARATOR$(Format-VariableValue $variable.value @{ renderValue = { param($v) Render-Value $v } })" } } # ------------------------- # Parameter variables # ------------------------- if ($parameterVariableDefinitions.Count -gt 0) { $lines += "# Parameter variables for $requestName" foreach ($variable in $parameterVariableDefinitions) { $lines += "@$(Sanitize-VarName $variable.name)$VARIABLE_NAME_VALUE_SEPARATOR$(Format-VariableValue $variable.value @{ renderValue = { param($v) Render-Value $v } })" } } # ------------------------- # Body # ------------------------- $requestBody = '' if ($request.body -and ($request.body -is [psobject] -or $request.body -is [hashtable])) { $bodyType = ([string]($request.body.type ?? '')).ToLower() if ($bodyType -eq 'json') { $jsonData = ConvertFrom-Json -Depth 20 -InputObject ($request.body.data) if ($jsonData -is [string]) { $requestBody = Render-Value $jsonData } elseif ($jsonData -is [System.Collections.IEnumerable]) { $requestBody = (ConvertTo-Json (RenderJsonValue $jsonData) -Depth 20) } elseif ($jsonData -is [psobject] -or $jsonData -is [hashtable]) { $requestBody = (ConvertTo-Json (RenderJsonValue $jsonData) -Depth 20) } Add-Header 'Content-Type' 'application/json' } elseif ($bodyType -eq 'form-urlencoded') { $parts = @() foreach ($entry in ($request.body.data ?? @())) { if (-not $entry -or -not $entry.name) { continue } Add-ReferencedVariables ($entry.value ?? '') $parts += "$($entry.name)=$(Render-Value ($entry.value ?? ''))" } $requestBody = ($parts -join '&') Add-Header 'Content-Type' 'application/x-www-form-urlencoded' } } # ------------------------- # Variables # ------------------------- if ($variableDefinitions.Count -gt 0) { $lines += "# Variables for $requestName" foreach ($variable in $variableDefinitions) { $lines += "@$(Sanitize-VarName $variable.name)$VARIABLE_NAME_VALUE_SEPARATOR$(Format-VariableValue $variable.value @{ renderValue = { param($v) Render-Value $v } })" } } # ------------------------- # Final request line # ------------------------- $method = ([string]($request.method ?? 'GET')).ToUpper() $requestUrl = $url foreach ($param in $queryParams) { if (-not $param.name) { continue } $separator = ($requestUrl.Contains('?') ? '&' : '?') $requestUrl = "$requestUrl$separator$($param.name)=$($param.value)" } $lines += '' $lines += "$method $requestUrl" foreach ($header in $headers) { $lines += "$($header.name): $($header.value)" } if ($requestBody) { $lines += '' $lines += $requestBody } return ($lines -join "`n") } function Ensure-Dir($path) { if (-not (Test-Path -LiteralPath $path)) { New-Item -ItemType Directory -Path $path | Out-Null } } function Walk-YamlFiles($rootDir) { Get-ChildItem -LiteralPath $rootDir -Recurse -File -Include *.yml, *.yaml | Where-Object { $_.Name -notmatch '^\.|node_modules' } | Select-Object -ExpandProperty FullName } function Clean-Folder($dir) { if (-not (Test-Path -LiteralPath $dir)) { return } foreach ($entry in Get-ChildItem -LiteralPath $dir) { if ($entry.PSIsContainer) { Clean-Folder $entry.FullName $children = Get-ChildItem -LiteralPath $entry.FullName if ($children.Count -eq 0) { Remove-Item -LiteralPath $entry.FullName -Force } } else { if (!$entry.PSIsContainer -and $entry.Name -match '\.js$|\.http$|\.env\.template$') { Remove-Item -LiteralPath $entry.FullName -Force } } } } function Get-DotenvVariablesForTargetDir ($TargetDir, $OutputRoot, $DotenvVariablesByTarget) { $variables = New-Object System.Collections.Generic.HashSet[string] $currentDir = $TargetDir while ($true) { if ($DotenvVariablesByTarget.ContainsKey($currentDir)) { foreach ($variable in $DotenvVariablesByTarget[$currentDir]) { $variables.Add($variable) | Out-Null } } $parentDir = Split-Path -Parent $currentDir if ($currentDir -eq $OutputRoot -or $parentDir -eq $currentDir) { break } $currentDir = $parentDir } return $variables } function Write-EnvironmentTemplates ($sourceDir, $outputRoot) { $targets = @() $dotenvVariablesByTarget = @{} # Hashtable: targetDir → HashSet function Visit ([string]$CurrentDir) { $entries = Get-ChildItem -LiteralPath $CurrentDir -Force $hasEnvironmentsDir = $entries | Where-Object { $_.PSIsContainer -and $_.Name -eq 'environments' } if ($hasEnvironmentsDir) { $targets += $CurrentDir } foreach ($entry in $entries) { if (-not $entry.PSIsContainer) { continue } if ($entry.Name.StartsWith('.')) { continue } if ($entry.Name -eq 'node_modules') { continue } Visit (Join-Path $CurrentDir $entry.Name) } } Visit $sourceDir foreach ($dir in $targets) { $relativeDir = [System.IO.Path]::GetRelativePath($sourceDir, $dir) if ($relativeDir -and $relativeDir -ne '.') { $targetDir = Join-Path $outputRoot $relativeDir } else { $targetDir = $outputRoot } Ensure-Dir $targetDir $environmentsDir = Join-Path $dir 'environments' if (-not (Test-Path $environmentsDir)) { continue } $envFiles = Get-ChildItem -LiteralPath $environmentsDir -Force | Where-Object { -not $_.PSIsContainer -and $_.Name -match '\.ya?ml$' } | ForEach-Object { $_.FullName } $variableNames = @() $seenNames = New-Object System.Collections.Generic.HashSet[string] foreach ($envFile in $envFiles) { $parsed = Parse-Yaml $envFile if (-not $parsed) { continue } $variables = @() if ($parsed.variables -is [System.Collections.IEnumerable]) { $variables = $parsed.variables } foreach ($variable in $variables) { if (-not $variable -or -not $variable.name) { continue } $name = ([string]$variable.name).Trim() if (-not $name) { continue } if ($seenNames.Contains($name)) { continue } $seenNames.Add($name) $variableNames += $name } } if ($variableNames.Count -gt 0) { $templateContent = ($variableNames | ForEach-Object { "$_=$DEFAULT_ENV_VAR_VALUE" }) -join "`n" $templateContent += "`n" } else { $templateContent = "" } $templatePath = Join-Path $targetDir '.env.template' Set-Content -Path $templatePath -Value $templateContent -Encoding UTF8 $dotenvVariablesByTarget[$targetDir] = $seenNames } return $dotenvVariablesByTarget } function Write-JsFiles ($sourceDir, $outputRoot) { $targets = @() function Visit ($CurrentDir) { $entries = Get-ChildItem -LiteralPath $CurrentDir -Force $hasJsFiles = $entries | Where-Object { -not $_.PSIsContainer -and $_.Name -match '\.js$' } if ($hasJsFiles) { $targets += $CurrentDir } # Visita ricorsivamente le sottodirectory foreach ($entry in $entries) { if (-not $entry.PSIsContainer) { continue } if ($entry.Name.StartsWith('.')) { continue } if ($entry.Name -eq 'node_modules') { continue } Visit (Join-Path $CurrentDir $entry.Name) } } Visit $sourceDir foreach ($dir in $targets) { $relativeDir = [System.IO.Path]::GetRelativePath($sourceDir, $dir) if ($relativeDir -and $relativeDir -ne '.') { $targetDir = Join-Path $outputRoot $relativeDir } else { $targetDir = $outputRoot } Ensure-Dir $targetDir if (-not (Test-Path $dir)) { continue } $jsFiles = Get-ChildItem -LiteralPath $dir -Force | Where-Object { -not $_.PSIsContainer -and $_.Name -match '\.js$' } | ForEach-Object { @{ Source = $_.FullName Target = Join-Path $targetDir $_.Name } } foreach ($jsFile in $jsFiles) { Copy-Item -LiteralPath $jsFile.Source -Destination $jsFile.Target -Force } } return $targets } function Invoke-Main { # Workspace root $workspaceRoot = Find-WorkspaceRoot $PSScriptRoot $workspaceFile = Join-Path $workspaceRoot 'workspace.yml' $workspace = Parse-Workspace $workspaceFile $collections = @() if ($workspace.collections -is [System.Collections.IEnumerable]) { $collections = $workspace.collections } if ($collections.Count -eq 0) { throw "No collections found in workspace.yml" } $outputBaseRoot = Join-Path $workspaceRoot 'autogen/httpyac' Clean-Folder $outputBaseRoot foreach ($collection in $collections) { if (-not $collection -or -not $collection.name -or -not $collection.path) { continue } $sourceDir = Join-Path $workspaceRoot $collection.path if (-not (Test-Path $sourceDir)) { Write-Warning "Skipping missing collection path: $($collection.path)" continue } $outputRoot = Join-Path $outputBaseRoot $collection.name Ensure-Dir $outputRoot # JS files $writtenJsFiles = Write-JsFiles $sourceDir $outputRoot # dotenv templates $dotenvVariablesByTarget = Write-EnvironmentTemplates $sourceDir $outputRoot # YAML files $yamlFiles = Walk-YamlFiles $sourceDir $processed = 0 foreach ($yamlFile in $yamlFiles) { $content = Get-Content -LiteralPath $yamlFile -Raw $requestName = Parse-RequestInfo $content if (-not $requestName) { $requestName = [System.IO.Path]::GetFileNameWithoutExtension($yamlFile) } $httpBlock = Parse-HttpBlock $content if (-not $httpBlock -or -not $httpBlock.url) { continue } $relativePath = [System.IO.Path]::GetRelativePath($sourceDir, $yamlFile) $parsedPath = [System.IO.Path]::GetFileNameWithoutExtension($relativePath) $parsedDir = Split-Path $relativePath -Parent $targetDir = Join-Path $outputRoot $parsedDir Ensure-Dir $targetDir $requestConfig = Get-RequestConfigForFile $yamlFile $sourceDir $outputFile = Join-Path $targetDir ("$parsedPath.http") $dotenvVariables = Get-DotenvVariablesForTargetDir $targetDir $outputRoot $dotenvVariablesByTarget $requestContent = Build-RequestContent $httpBlock $requestName $requestConfig $dotenvVariables Set-Content -Path $outputFile -Value ($requestContent + "`n") -Encoding UTF8 $processed++ } $namePadded = $collection.name.PadRight(33) $httpCount = $processed.ToString().PadLeft(3) $jsCount = $writtenJsFiles.Count.ToString().PadLeft(3) Write-Host "$namePadded => generated $httpCount .http file(s) and $jsCount .js file(s)" } } Invoke-Main