feat: 운영 안정성과 세션 음성 경험 개선

This commit is contained in:
Yun Chan 2026-07-31 00:13:08 +09:00
parent facc4ad2d9
commit c788343467
95 changed files with 8431 additions and 1785 deletions

View file

@ -0,0 +1,103 @@
param(
[string]$DistPath = "D:\workspace\vignette\apps\web\dist",
[string[]]$DeploymentBases = @(
"https://1b3b6d5b.vignette-b1q.pages.dev",
"https://0a339b77.vignette-b1q.pages.dev",
"https://f323a41d.vignette-b1q.pages.dev",
"https://1332ccbe.vignette-b1q.pages.dev",
"https://564dbed9.vignette-b1q.pages.dev"
)
)
$ErrorActionPreference = "Stop"
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
$OutputEncoding = [System.Text.UTF8Encoding]::new($false)
$distRoot = [IO.Path]::GetFullPath((Resolve-Path -LiteralPath $DistPath).Path)
$distPrefix = $distRoot.TrimEnd([IO.Path]::DirectorySeparatorChar) + [IO.Path]::DirectorySeparatorChar
$totalAdded = 0
function Resolve-DistTarget {
param([string]$AssetPath)
$relative = $AssetPath.TrimStart("/").Replace("/", [IO.Path]::DirectorySeparatorChar)
$target = [IO.Path]::GetFullPath((Join-Path $distRoot $relative))
if (!$target.StartsWith($distPrefix, [StringComparison]::OrdinalIgnoreCase)) {
throw "Asset target escaped the deployment directory: $AssetPath"
}
return $target
}
foreach ($base in $DeploymentBases) {
$origin = $base.TrimEnd("/")
$seen = [System.Collections.Generic.HashSet[string]]::new(
[System.StringComparer]::OrdinalIgnoreCase
)
$queue = [System.Collections.Generic.Queue[string]]::new()
$html = (
Invoke-WebRequest `
-Uri "$origin/login?preserve=$([guid]::NewGuid().ToString('N'))" `
-UseBasicParsing `
-TimeoutSec 30
).Content
foreach ($match in [regex]::Matches(
$html,
'(?:src|href)="(/assets/[^\"]+\.(?:js|css))"'
)) {
$queue.Enqueue($match.Groups[1].Value)
}
$added = 0
while ($queue.Count -gt 0) {
$asset = $queue.Dequeue()
if (!$seen.Add($asset)) {
continue
}
$target = Resolve-DistTarget -AssetPath $asset
$parent = Split-Path -Parent $target
if (!(Test-Path -LiteralPath $parent)) {
New-Item -ItemType Directory -Path $parent -Force | Out-Null
}
$download = "$target.download"
$response = Invoke-WebRequest `
-Uri "$origin$asset" `
-UseBasicParsing `
-TimeoutSec 30 `
-OutFile $download `
-PassThru
$contentType = [string]$response.Headers["Content-Type"]
if ($asset.EndsWith(".js") -and $contentType -notmatch "javascript") {
Remove-Item -LiteralPath $download -Force
throw "Expected JavaScript response: $origin$asset ($contentType)"
}
if ($asset.EndsWith(".css") -and $contentType -notmatch "text/css") {
Remove-Item -LiteralPath $download -Force
throw "Expected CSS response: $origin$asset ($contentType)"
}
if (Test-Path -LiteralPath $target) {
Remove-Item -LiteralPath $download -Force
} else {
Move-Item -LiteralPath $download -Destination $target
$added += 1
$totalAdded += 1
}
if ($asset -match '\.(?:js|css)$') {
$source = Get-Content -LiteralPath $target -Raw -Encoding UTF8
foreach ($match in [regex]::Matches(
$source,
'(?:(?:/assets/)|(?:\./))([A-Za-z0-9_.-]+\.(?:js|css))'
)) {
$queue.Enqueue("/assets/$($match.Groups[1].Value)")
}
}
}
Write-Output "Preserved $origin (graph=$($seen.Count), added=$added)"
}
Write-Output "Total previous deployment assets added: $totalAdded"