# Script-level parameters and cmdlet binding to support -Verbose and common parameters [CmdletBinding()] param ( [switch]$Quiet = $false ) function Write-LogMessage { param ( [string]$message, [ValidateSet('Info','Warning')] [string]$Level = 'Info' ) if ($Quiet) { return } $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" if ($Level -eq 'Warning') { Write-Host "[$timestamp] WARNING: $message" } else { Write-Host "[$timestamp] $message" } } function Save-ElxInternals { param( [ValidateScript({ Test-Path $_ -PathType Leaf })][Parameter(Mandatory)]$ModulePath ) if (-not $Quiet) { Write-Host "Switching to ELX Tools directory..." } $extractElxToolsScriptPath = Join-Path $PSScriptRoot "../tools/extract-elx/" Push-Location -StackName ElxTools $extractElxToolsScriptPath if (-not $Quiet) { Write-Host "Executing ELX extraction..." } & node "extract-elx.js" $ModulePath --clean if ($LASTEXITCODE -ne 0) { Write-Error "ELX extraction failed with exit code $LASTEXITCODE." exit 1 } if (-not $Quiet) { Write-Host "ELX extraction completed successfully!" -ForegroundColor Green Write-Host "Switching back to original directory..." } Pop-Location -StackName ElxTools } function New-EnvFileContent { param( [ValidateNotNullOrEmpty()][Parameter(Mandatory)][string]$ModuleTag ) $envValues = Get-EnvironmentFromFile -ModuleTag $ModuleTag $out = ($envValues.Keys | ForEach-Object { "$_='$($envValues[$_])'" }) -join "`n" } function Get-EnvironmentFromFile { param( [ValidateNotNullOrEmpty()][Parameter(Mandatory)][string]$ModuleTag ) $envFileScriptPath = Join-Path $PSScriptRoot "../" # Load existing .env if present $envPath = Join-Path $envFileScriptPath '.env' if (-not (Test-Path $envPath)) { Write-Error "No existing .env file found!" exit 1 } $envValues = @{} $envLines = Get-Content -Raw -Path $envPath -ErrorAction Stop foreach ($line in $envLines -split "`n") { $l = $line.Trim() if ($l -eq '' -or $l.StartsWith('#') -or $l.StartsWith(';')) { continue } if ($l -match '=') { $parts = $l -split '=', 2 $name = $parts[0].Trim() $value = $parts[1].Trim().Trim("'").Trim('"') $envValues[$name] = $value } if ($name -eq 'ELIXFORMS_MODULE_TAG') { $envValues[$name] = $ModuleTag } } $envValues } function Export-ElxModule { param( [ValidateNotNullOrEmpty()][Parameter(Mandatory)][string]$ModuleTag, [ValidateScript({ Test-Path $_ })][Parameter(Mandatory)]$ModulePath ) if (-not $Quiet) { Write-Host "Switching to Selenium directory..." } $seleniumToolsScriptPath = Join-Path $PSScriptRoot "../tools/selenium/" Push-Location -StackName Selenium $seleniumToolsScriptPath try { if (-not $Quiet) { Write-Host "Executing module export for '$ModuleTag'..." } $NpmPath = (Get-Command npm).Source if (-not $NpmPath) { Write-Error "npm is not installed or not found in PATH. Please install Node.js and npm, then try again." exit 1 } Start-Process pwsh -ArgumentList "$NpmPath run export" -Environment (Get-EnvironmentFromFile -ModuleTag $ModuleTag) -NoNewWindow -Wait -PassThru | Out-Null if ($LASTEXITCODE -and ($LASTEXITCODE -ne 0)) { Write-Error "Module export for '$ModuleTag' failed with exit code $LASTEXITCODE." exit 1 } if (-not $Quiet) { Write-Host "Module export for '$ModuleTag' completed successfully!" -ForegroundColor Green Write-Host "Switching back to original directory..." } $seleniumDownloadDir = Join-Path $seleniumToolsScriptPath "downloads" if (-not (Test-Path -Path $seleniumDownloadDir)) { Write-Error "Selenium download directory not found at '$seleniumDownloadDir'." exit 1 } $latestDownloadedFile = Get-ChildItem -Path $seleniumDownloadDir -Filter "*.elx" | Sort-Object LastWriteTime -Descending | Select-Object -First 1 if (-not $latestDownloadedFile) { Write-Error "No .elx file found in Selenium download directory '$seleniumDownloadDir'." exit 1 } Move-Item -Path $latestDownloadedFile.FullName -Destination (Join-Path $ModulePath $latestDownloadedFile.Name) -Force } finally { Pop-Location -StackName Selenium } } function Convert-UrlToElixAutocompleteFormat { param ( [Parameter(Mandatory)][ValidateNotNullOrEmpty()][uri]$AbsoluteUrl ) Write-LogMessage "Converting URL '$($AbsoluteUrl.Host)' to elixForms WS call format..." $domain = $AbsoluteUrl.Host -replace '-', '--' -replace '\.', '-' $path = $AbsoluteUrl.AbsolutePath.TrimStart('/') -replace '-', '--' -replace '/', '-' $url = "/eF/services/api/remote/$domain/$path/v1" # Preserve query parameter order using an ordered hashtable and URL-decode values $queryParams = [ordered]@{} $rawQuery = $AbsoluteUrl.Query.TrimStart('?') if ($rawQuery) { $rawQuery.Split('&') | ForEach-Object { if ($_ -ne '') { $pair = $_ -split '=', 2 $key = $pair[0] $value = if ($pair.Count -gt 1) { $pair[1] } else { '' } if ($queryParams.Contains($key)) { # Append duplicate values with a comma, preserving existing empty-string handling if ($queryParams[$key] -eq '') { $queryParams[$key] = $value } else { $queryParams[$key] = "{0},{1}" -f $queryParams[$key], $value } } else { $queryParams[$key] = $value } } } } [PSCustomObject]@{ URL = $url QueryParams = $queryParams QueryString = ($queryParams.Keys | ForEach-Object { "$_=$($queryParams[$_])" }) -Join "&" } | ConvertTo-Json -Depth 2 -EscapeHandling None } Export-ModuleMember -Function Convert-UrlToElixAutocompleteFormat Export-ModuleMember -Function Save-ElxInternals Export-ModuleMember -Function Export-ElxModule Export-ModuleMember -Function New-EnvFileContent