337 lines
9.7 KiB
PowerShell
337 lines
9.7 KiB
PowerShell
#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"
|
|
}
|
|
$current = $parent
|
|
}
|
|
}
|
|
|
|
function Parse-YamlFile($path) {
|
|
try {
|
|
return ConvertFrom-Yaml (Get-Content -LiteralPath $path -Raw)
|
|
} catch {
|
|
throw "Failed to parse YAML file $path : $_"
|
|
}
|
|
}
|
|
|
|
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"))) {
|
|
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 Walk-YamlFiles($rootDir) {
|
|
Get-ChildItem -LiteralPath $rootDir -Recurse -File -Include *.yml, *.yaml |
|
|
Where-Object { $_.Name -notmatch '^\.|node_modules' } |
|
|
Select-Object -ExpandProperty FullName
|
|
}
|
|
|
|
function Ensure-Dir($path) {
|
|
if (-not (Test-Path -LiteralPath $path)) {
|
|
New-Item -ItemType Directory -Path $path | Out-Null
|
|
}
|
|
}
|
|
|
|
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 Parse-HttpBlock($text) {
|
|
$parsed = ConvertFrom-Yaml $text
|
|
$http = $parsed.http
|
|
|
|
$headers = @()
|
|
foreach ($h in ($http.headers | Where-Object { $_ })) {
|
|
$headers += [ordered]@{
|
|
name = $h.name
|
|
value = $h.value
|
|
}
|
|
}
|
|
|
|
return @{
|
|
method = $http.method
|
|
url = $http.url
|
|
params = $http.params
|
|
headers = $headers
|
|
body = $http.body
|
|
}
|
|
}
|
|
|
|
function Build-RequestContent($http, $name, $config, $dotenvVars) {
|
|
$lines = @()
|
|
$vars = @()
|
|
$paramsVars = @()
|
|
$commentVars = @()
|
|
$seen = New-Object System.Collections.Generic.HashSet[string]
|
|
|
|
function Add-Var($n, $v) {
|
|
if (-not $n) { return }
|
|
if ($seen.Contains($n)) { return }
|
|
if ($dotenvVars.Contains($n)) { return }
|
|
$seen.Add($n) | Out-Null
|
|
$vars += @{ name = $n; value = $v }
|
|
}
|
|
|
|
function Add-ParamVar($n, $v) {
|
|
if (-not $n) { return }
|
|
if ($seen.Contains($n)) { return }
|
|
if ($dotenvVars.Contains($n)) { return }
|
|
$seen.Add($n) | Out-Null
|
|
$paramsVars += @{ name = $n; value = $v }
|
|
}
|
|
|
|
function Add-CommentVar($n, $v) {
|
|
if (-not $n) { return }
|
|
$commentVars += @{ name = $n; value = $v }
|
|
}
|
|
|
|
# Variables from config
|
|
foreach ($v in ($config.variables | Where-Object { $_ })) {
|
|
Add-Var $v.name $v.value
|
|
}
|
|
|
|
# URL
|
|
$url = $http.url
|
|
if ($url) {
|
|
$url = $url -replace ':(\w+)', '{{$1}}'
|
|
$url = $url.Split('?')[0]
|
|
}
|
|
|
|
# Params
|
|
$queryParams = @()
|
|
$headers = @()
|
|
|
|
foreach ($h in $http.headers) {
|
|
$headers += $h
|
|
}
|
|
|
|
foreach ($p in $http.params) {
|
|
$name = $p.name
|
|
$value = $p.value
|
|
$type = ($p.type).ToLower()
|
|
$disabled = ($p.disabled -eq $true)
|
|
|
|
if ($disabled) {
|
|
Add-CommentVar $name $value
|
|
continue
|
|
}
|
|
|
|
if ($type -eq 'header') {
|
|
$headers += @{ name = $name; value = $value }
|
|
} else {
|
|
$queryParams += @{ name = $name; value = "{{$name}}" }
|
|
Add-ParamVar $name $value
|
|
}
|
|
}
|
|
|
|
# Auth
|
|
if ($config.auth) {
|
|
switch ($config.auth.type) {
|
|
'bearer' {
|
|
$headers += @{ name = 'Authorization'; value = "Bearer $($config.auth.token)" }
|
|
}
|
|
'basic' {
|
|
$headers += @{ name = 'Authorization'; value = "Basic $($config.auth.username):$($config.auth.password)" }
|
|
}
|
|
}
|
|
}
|
|
|
|
# Commented vars
|
|
if ($commentVars.Count -gt 0) {
|
|
$lines += "# Other variables for $name"
|
|
foreach ($v in $commentVars) {
|
|
$lines += "# @$($v.name)=$($v.value)"
|
|
}
|
|
}
|
|
|
|
# Parameter vars
|
|
if ($paramsVars.Count -gt 0) {
|
|
$lines += "# Parameter variables for $name"
|
|
foreach ($v in $paramsVars) {
|
|
$lines += "@$($v.name)=$($v.value)"
|
|
}
|
|
}
|
|
|
|
# Vars
|
|
if ($vars.Count -gt 0) {
|
|
$lines += "# Variables for $name"
|
|
foreach ($v in $vars) {
|
|
$lines += "@$($v.name)=$($v.value)"
|
|
}
|
|
}
|
|
|
|
# Build URL
|
|
foreach ($qp in $queryParams) {
|
|
$sep = ($url.Contains('?')) ? '&' : '?'
|
|
$url = "$url$sep$($qp.name)=$($qp.value)"
|
|
}
|
|
|
|
$lines += ""
|
|
$lines += "$($http.method.ToUpper()) $url"
|
|
|
|
foreach ($h in $headers) {
|
|
$lines += "$($h.name): $($h.value)"
|
|
}
|
|
|
|
if ($http.body) {
|
|
if ($http.body.type -eq 'json') {
|
|
$lines += ""
|
|
try {
|
|
$lines += ($http.body.data | ConvertFrom-Json -Depth 10 | ConvertTo-Json -Depth 10)
|
|
}
|
|
catch {
|
|
<#Do this if a terminating exception happens#>
|
|
Write-Warning "Failed to parse JSON for request $name, will use original content"
|
|
$lines += $http.body.data
|
|
}
|
|
}
|
|
}
|
|
|
|
return ($lines -join "`n")
|
|
}
|
|
|
|
function Main {
|
|
$workspaceRoot = Find-WorkspaceRoot $StartDir
|
|
$workspace = Parse-Workspace (Join-Path $workspaceRoot 'workspace.yml')
|
|
$collections = $workspace.collections
|
|
|
|
$outputBase = Join-Path $workspaceRoot 'autogen/httpyac_ps1'
|
|
Clean-Folder $outputBase
|
|
|
|
foreach ($col in $collections) {
|
|
$sourceDir = Join-Path $workspaceRoot $col.path
|
|
if (-not (Test-Path -LiteralPath $sourceDir)) {
|
|
Write-Warning "Skipping missing collection path: $($col.path)"
|
|
continue
|
|
}
|
|
|
|
$outputRoot = Join-Path $outputBase $col.name
|
|
Ensure-Dir $outputRoot
|
|
|
|
# Copy JS
|
|
Get-ChildItem $sourceDir -Recurse -File -Include *.js |
|
|
ForEach-Object {
|
|
$rel = $_.FullName.Substring($sourceDir.Length).TrimStart('\')
|
|
$dest = Join-Path $outputRoot $rel
|
|
Ensure-Dir (Split-Path -Parent $dest)
|
|
Copy-Item $_.FullName $dest -Force
|
|
}
|
|
|
|
# Env templates
|
|
$envDir = Join-Path $sourceDir 'environments'
|
|
$dotenvVars = New-Object System.Collections.Generic.HashSet[string]
|
|
|
|
if (Test-Path -LiteralPath $envDir) {
|
|
$vars = @()
|
|
foreach ($f in Get-ChildItem $envDir -File -Include *.yml, *.yaml) {
|
|
$parsed = Parse-YamlFile $f.FullName
|
|
foreach ($v in ($parsed.variables | Where-Object { $_ })) {
|
|
if (-not $dotenvVars.Contains($v.name)) {
|
|
$dotenvVars.Add($v.name) | Out-Null
|
|
$vars += $v.name
|
|
}
|
|
}
|
|
}
|
|
|
|
$template = ($vars | ForEach-Object { "$_=`"EDIT_VALUE_HERE`"" }) -join "`n"
|
|
Set-Content -LiteralPath (Join-Path $outputRoot '.env.template') -Value $template
|
|
}
|
|
|
|
# YAML → .http
|
|
$yamlFiles = Walk-YamlFiles $sourceDir
|
|
$count = 0
|
|
|
|
foreach ($file in $yamlFiles) {
|
|
$content = Get-Content -LiteralPath $file -Raw
|
|
$http = Parse-HttpBlock $content
|
|
if (-not $http.url) { continue }
|
|
|
|
$rel = $file.Substring($sourceDir.Length).TrimStart('\')
|
|
$parsed = Split-Path $rel -LeafBase
|
|
$dir = Split-Path $rel -Parent
|
|
|
|
$targetDir = Join-Path $outputRoot $dir
|
|
Ensure-Dir $targetDir
|
|
|
|
$requestName = $parsed
|
|
$config = @{ variables = @(); auth = $null }
|
|
|
|
$dotenv = $dotenvVars
|
|
$outFile = Join-Path $targetDir "$parsed.http"
|
|
|
|
$reqContent = Build-RequestContent $http $requestName $config $dotenv
|
|
Set-Content -LiteralPath $outFile -Value $reqContent
|
|
|
|
$count++
|
|
}
|
|
|
|
Write-Host ("{0,-33} => generated {1,3} .http file(s)" -f $col.name, $count)
|
|
}
|
|
}
|
|
|
|
Main
|