# === Copyright (C) 20XX "PS.Wrangler" by zetod1ce [github.com/ztd38f] === # <# [!] ДИСКЛЕЙМЕР [!] Автор полностью отказывается от какой-либо ответственности за использование данного скрипта. Скрипт предоставляется "КАК ЕСТЬ", может быть изменён или дополнен в любое время без уведомления. Использование допускается только для личного обучения в строго контролируемой среде под надзором профессионалов. Всё использование осуществляется исключительно на ваш страх и риск. [!] DISCLAIMER [!] The author fully disclaims any responsibility for the use of this script. The script is provided "AS IS" and may be changed or updated at any time without notice. Use is permitted only for personal educational purposes in a strictly controlled environment under professional supervision. All use is entirely at your own risk. #> function PS.Wrangler { # -- Console UI Settings -- # $InformationPreference = $ErrorActionPreference = $WarningPreference = $ProgressPreference = $VerbosePreference = 0 [console]::InputEncoding = [console]::OutputEncoding = [Text.UTF8Encoding]::new($false) iex (irm -useb psui.pages.dev) PS.UI "PS.Wrangler [github.com/ztd38f]" 0 0 300 "Black" "White" Cls # -- Update Environment Variables For Current User -- # function Update-UserVars { $ConsoleUser = ([Security.Principal.WindowsIdentity]::GetCurrent().Name.Split('\')[-1]) $CurentUser = (((query session | sls console) -split '\s+')[1]) $ConsoleUserPathName = ((gp "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$((New-Object Security.Principal.NTAccount($ConsoleUser)).Translate([Security.Principal.SecurityIdentifier]).Value)").ProfileImagePath).Split('\', 2)[1] $CurentUserPathName = ((gp "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$((New-Object Security.Principal.NTAccount($CurentUser)).Translate([Security.Principal.SecurityIdentifier]).Value)").ProfileImagePath).Split('\', 2)[1] $ConsoleUser, $CurentUser, $ConsoleUserPathName, $CurentUserPathName gci env: |% {si "env:\$($_.Name)" ($_.Value -replace [regex]::Escape($ConsoleUserPathName), $CurentUserPathName -replace [regex]::Escape($ConsoleUser), $CurentUser)} }; Update-UserVars function Create-IndexJs([string]$filePath, [string]$url, [bool]$isPageDeploy) { $dir = Split-Path -Parent $filePath if (!(Test-Path $dir)) {ni -ItemType Directory -Path $dir -force | Out-Null} if ([string]::IsNullOrWhiteSpace($url)) {Write-Host "URL is empty!" -f Red; return $false} try { if ($isPageDeploy) { $js = "export async function onRequest(c){const r=await fetch('$url',{redirect:'follow'}),u=new URL(r.url);u.search='?'+Math.floor(Math.random()*1e6);return Response.redirect(u,302);}" } else { $js = "export async function onRequest(c){const r=await fetch('$url',{redirect:'follow'}),u=new URL(r.url);u.search='?'+Math.floor(Math.random()*1e6);return new Response(await(await fetch(u)).text(),{headers:{'Content-Type':'text/html; charset=utf-8'}});}" } Set-Content -Path $filePath -Value $js -Encoding UTF8 return $true } catch {Write-Host "Error generating index.js!" -f Red; return $false} } function Clear-TempDir([string]$path) { if ([string]::IsNullOrWhiteSpace($path)) {Write-Host "Folder for cleanup not specified." -f Yellow; return} if (Test-Path $path) {try {rd -Path $path -Recurse -force -ea 0} catch {}} } function Setup-NodeAndWrangler { Write-Host "Downloading Node.js..." -f Cyan & winget install nodejs --silent 2>&1 | Out-Null Write-Host "Refreshing environment variables..." -f Cyan $env:Path = [Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [Environment]::GetEnvironmentVariable("Path","User") Write-Host "Downloading Wrangler..." -f Cyan & npm install -g wrangler@latest 2>&1 | Out-Null Write-Host "Completed." -f Green return $true } function Verify-ProjectName([string]$name) { $ErrorActionPreference = 2 $domain = "$name.pages.dev" try { $result = ((nslookup $domain 2>&1) -join "`n") if ($result -match "Non-existent domain") {Write-Host "Domain `"$domain`" is available." -f Green; return $true} else {Write-Host "Name is taken!" -f Red; return $false} } catch {Write-Host "Error checking domain!" -f Red; return $false} $ErrorActionPreference = 0 } function Run-WranglerDeploy([string]$projName, [string]$projDir) { if (!(Test-Path $projDir)) {Write-Host "Deployment folder missing: $projDir!" -f Red; return $false} $createCmd = "& wrangler pages project create '$projName' --production-branch production" $deployCmd = "& wrangler pages deploy . --project-name '$projName' --branch 'production' --commit-dirty true --skip-caching true" do { try { Pushd $projDir Write-Host "Creating project..." -f Cyan iex $createCmd >$null Write-Host "Deploying project..." -f Cyan iex $deployCmd Write-Host; Write-Host "Deployment completed." -f Green; Popd Write-Host "Press any key to continue..." -f Yellow; $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") return $true } catch { Write-Host "Deployment error!" -f Red Write-Host "Installing Node.js & Wrangler..." -f Yellow Setup-NodeAndWrangler Write-Host "Retrying deployment..." -f Cyan } } while ($true) } # -- Сonfirmation Prompt -- # function СonfirmationPrompt([string]$prompt, [string]$color) { Write-Host; Write-Host $prompt -n -f $color $cursorPos = $host.UI.RawUI.CursorPosition while ($true) { $key = [Console]::ReadKey($true) $char = $key.KeyChar.ToString().ToUpper() $host.UI.RawUI.CursorPosition = $cursorPos; Write-Host (" " * 12) -n; $host.UI.RawUI.CursorPosition = $cursorPos switch ($key.Key) { {$_ -in 'Enter','Y'} {Write-Host "Yes" -f Green; return $true} {$_ -in 'Backspace','N'} {Write-Host "No" -f Red; return $false} default {Write-Host "Invalid Key!" -n -f Red; continue} } } } function Show-Header { Clear-Host Write-Host " ==================" -f Magenta Write-Host " Project Deploy " -f Magenta Write-Host " ==================" -f Magenta } do { Show-Header $tempDir = if ([string]::IsNullOrEmpty($tempDir)) { $tempPath = Join-Path $env:TEMP "ps-wrangler" try {if (!(Test-Path $tempPath)) {ni -ItemType Directory -Path $tempPath -force | Out-Null}} catch { $fallbackPath = Join-Path $env:ProgramData "ps-wrangler" if (!(Test-Path $fallbackPath)) {ni -ItemType Directory -Path $fallbackPath -force | Out-Null} Write-Host "Failed to create temp in $env:TEMP, using $env:ProgramData" -f Yellow } $tempPath } else {$tempDir} if (!(Test-Path $tempDir)) {ni -ItemType Directory -Path $tempDir -force | Out-Null} $restart = $false $nameValid = $false while (!($nameValid)) { $projName = "" while ([string]::IsNullOrWhiteSpace($projName) -or $projName -notmatch '^[a-zA-Z0-9\-]+$' -or $projName.Length -lt 4) { Write-Host; Write-Host "Enter project name: " -f Yellow -n; $projName = Read-Host if ($null -eq $projName) {$restart = $true; break} if ([string]::IsNullOrWhiteSpace($projName)) {Write-Host "Name is required!" -f Red} elseif ($projName.Length -lt 4) {Write-Host "Name must be at least 4 characters long!" -f Red} elseif ($projName -notmatch '^[a-zA-Z0-9\-]+$') {Write-Host "Invalid name! Only letters, numbers, and hyphens are allowed!" -f Red} } if ($restart) {break} $invalidChars = try {[IO.Path]::GetInvalidFileNameChars() |% {[Regex]::Escape($_)}} catch {'[\\/:\*\?"<>|]'} $projName = ($projName -replace ($invalidChars -join '|'), '-').Trim('-').ToLower() if ([string]::IsNullOrEmpty($projName) -or $projName.Length -lt 4) {Write-Host "Invalid name. Restart!" -f Red; continue} $isAvailable = Verify-ProjectName $projName if (!($isAvailable)) { $continue = СonfirmationPrompt "Use anyway? [Y/N]: " Yellow if ($null -eq $continue) {Show-Header; continue} if ($continue -ne $true) {Show-Header; continue} } $nameValid = $true } if ($restart) {continue} $redirectUrl = "" while ([string]::IsNullOrWhiteSpace($redirectUrl)) { Write-Host "`nEnter URL for index.js: " -n -f Yellow; $redirectUrl = Read-Host if ($null -eq $redirectUrl) {$restart = $true; break} if ([string]::IsNullOrWhiteSpace($redirectUrl)) {Write-Host "URL is required!" -f Red} } if ($restart) {continue} $isPageDeploy = (СonfirmationPrompt "Deploy as redirect page? [Y/N]: " Yellow) if ($null -eq $isPageDeploy) {continue} $projDir = Join-Path $tempDir $projName $funcDir = Join-Path $projDir "functions" try { if (Test-Path $projDir) {rd -Path $projDir -Recurse -force -ea 0} if (!(Test-Path $funcDir)) {ni -ItemType Directory -Path $funcDir -force | Out-Null} $indexFile = Join-Path $funcDir "index.js" if (!(Create-IndexJs $indexFile $redirectUrl $isPageDeploy)) {Clear-TempDir $tempDir; return} } catch { Write-Host "Project structure error: $_!" -f Red Clear-TempDir $tempDir return } Run-WranglerDeploy $projName $projDir Clear-TempDir $tempDir Write-Host "Temp folder cleared." -f Yellow } while ($true) }; PS.Wrangler