Files
YMhut-box-C-/scripts/prepare-music-api.ps1
T

131 lines
6.2 KiB
PowerShell

param(
[string]$Destination,
[string]$NodeVersion = '22.18.0',
[switch]$Force
)
$ErrorActionPreference = 'Stop'
function Get-Sha256Hex([string]$Path) {
$stream = [IO.File]::OpenRead($Path)
$algorithm = [Security.Cryptography.SHA256]::Create()
try {
return ([BitConverter]::ToString($algorithm.ComputeHash($stream))).Replace('-', '')
} finally {
$algorithm.Dispose()
$stream.Dispose()
}
}
$RepoRoot = Split-Path -Parent $PSScriptRoot
$SourceRoot = Join-Path $RepoRoot 'third_party\MoeKoeMusic'
$ApiSource = Join-Path $SourceRoot 'api'
if ([string]::IsNullOrWhiteSpace($Destination)) {
$Destination = Join-Path $RepoRoot 'build\music-api'
}
$Destination = [IO.Path]::GetFullPath($Destination)
$BuildRoot = [IO.Path]::GetFullPath((Join-Path $RepoRoot 'build'))
if (-not $Destination.StartsWith($BuildRoot + [IO.Path]::DirectorySeparatorChar, [StringComparison]::OrdinalIgnoreCase)) {
throw "Music API destination must be inside $BuildRoot"
}
$requiredSource = @(
(Join-Path $SourceRoot 'UPSTREAM_COMMIT'),
(Join-Path $SourceRoot 'API_SUBMODULE_COMMIT'),
(Join-Path $SourceRoot 'MOEKOE_LICENSE'),
(Join-Path $SourceRoot 'MOEKOE_README.md'),
(Join-Path $ApiSource 'package.json'),
(Join-Path $ApiSource 'pnpm-lock.yaml'),
(Join-Path $ApiSource 'LICENSE'),
(Join-Path $ApiSource 'README.md'),
(Join-Path $ApiSource 'ymhut-sidecar.js')
)
foreach ($path in $requiredSource) {
if (-not (Test-Path -LiteralPath $path -PathType Leaf)) { throw "Required music API source is missing: $path" }
}
$fingerprintLines = Get-ChildItem -LiteralPath $SourceRoot -Recurse -File |
Where-Object { $_.FullName -notlike '*\node_modules\*' } |
Sort-Object FullName |
ForEach-Object {
$relative = $_.FullName.Substring($SourceRoot.TrimEnd('\').Length + 1).Replace('\', '/')
"$relative|$(Get-Sha256Hex $_.FullName)"
}
$fingerprintBytes = [Text.Encoding]::UTF8.GetBytes(($fingerprintLines -join "`n"))
$sha256 = [Security.Cryptography.SHA256]::Create()
try {
$fingerprint = ([BitConverter]::ToString($sha256.ComputeHash($fingerprintBytes))).Replace('-', '')
} finally {
$sha256.Dispose()
}
$markerPath = Join-Path $Destination 'payload.json'
if (-not $Force -and (Test-Path -LiteralPath $markerPath)) {
try {
$marker = Get-Content -LiteralPath $markerPath -Raw | ConvertFrom-Json
if ($marker.nodeVersion -eq $NodeVersion -and $marker.sourceFingerprint -eq $fingerprint -and
(Test-Path -LiteralPath (Join-Path $Destination 'node.exe')) -and
(Test-Path -LiteralPath (Join-Path $Destination 'api\node_modules\express\package.json') -PathType Leaf) -and
(Test-Path -LiteralPath (Join-Path $Destination 'api\pnpm-lock.yaml')) -and
(Test-Path -LiteralPath (Join-Path $Destination 'api\LICENSE'))) {
return
}
} catch {
}
}
$CacheRoot = Join-Path $RepoRoot '.cache\node-runtime'
New-Item -ItemType Directory -Force -Path $CacheRoot | Out-Null
$archiveName = "node-v$NodeVersion-win-x64.zip"
$archivePath = Join-Path $CacheRoot $archiveName
$checksumsPath = Join-Path $CacheRoot "SHASUMS256-$NodeVersion.txt"
$distRoot = "https://nodejs.org/dist/v$NodeVersion"
if (-not (Test-Path -LiteralPath $archivePath)) {
Invoke-WebRequest -UseBasicParsing "$distRoot/$archiveName" -OutFile $archivePath
}
if (-not (Test-Path -LiteralPath $checksumsPath)) {
Invoke-WebRequest -UseBasicParsing "$distRoot/SHASUMS256.txt" -OutFile $checksumsPath
}
$checksumLine = Get-Content -LiteralPath $checksumsPath | Where-Object { $_ -match "\s$([regex]::Escape($archiveName))$" } | Select-Object -First 1
if (-not $checksumLine) { throw "Node checksum was not found for $archiveName" }
$expectedHash = ($checksumLine -split '\s+')[0].ToUpperInvariant()
$actualHash = (Get-Sha256Hex $archivePath).ToUpperInvariant()
if ($actualHash -ne $expectedHash) { throw "Node runtime checksum mismatch for $archiveName" }
$staging = Join-Path $BuildRoot ("music-api.staging." + $PID)
if (Test-Path -LiteralPath $staging) { Remove-Item -LiteralPath $staging -Recurse -Force }
New-Item -ItemType Directory -Force -Path $staging | Out-Null
$extractRoot = Join-Path $staging '_node'
Expand-Archive -LiteralPath $archivePath -DestinationPath $extractRoot -Force
$nodeRoot = Join-Path $extractRoot "node-v$NodeVersion-win-x64"
Copy-Item -LiteralPath (Join-Path $nodeRoot 'node.exe') -Destination (Join-Path $staging 'node.exe')
Copy-Item -LiteralPath (Join-Path $nodeRoot 'LICENSE') -Destination (Join-Path $staging 'NODE_LICENSE')
Copy-Item -LiteralPath (Join-Path $nodeRoot 'README.md') -Destination (Join-Path $staging 'NODE_README.md')
Remove-Item -LiteralPath $extractRoot -Recurse -Force
$apiDestination = Join-Path $staging 'api'
robocopy $ApiSource $apiDestination /E /XD node_modules .git /NFL /NDL /NJH /NJS /NP | Out-Null
if ($LASTEXITCODE -ge 8) { throw "Failed to copy music API source (robocopy exit $LASTEXITCODE)." }
Copy-Item -LiteralPath (Join-Path $SourceRoot 'MOEKOE_LICENSE') -Destination (Join-Path $staging 'MOEKOE_LICENSE')
Copy-Item -LiteralPath (Join-Path $SourceRoot 'MOEKOE_README.md') -Destination (Join-Path $staging 'MOEKOE_README.md')
Copy-Item -LiteralPath (Join-Path $SourceRoot 'UPSTREAM_COMMIT') -Destination (Join-Path $staging 'UPSTREAM_COMMIT')
Copy-Item -LiteralPath (Join-Path $SourceRoot 'API_SUBMODULE_COMMIT') -Destination (Join-Path $staging 'API_SUBMODULE_COMMIT')
Copy-Item -LiteralPath (Join-Path $SourceRoot 'YMhut_PATCHES.md') -Destination (Join-Path $staging 'YMhut_PATCHES.md')
Push-Location $apiDestination
try {
& corepack pnpm install --prod --frozen-lockfile --ignore-scripts --package-import-method=copy --config.node-linker=hoisted --store-dir (Join-Path $RepoRoot '.cache\pnpm-store-music')
if ($LASTEXITCODE -ne 0) { throw "pnpm failed to install the locked music API dependencies." }
} finally {
Pop-Location
}
[ordered]@{
protocolVersion = 1
moekoeCommit = '4581660209c9cdd07669e8bd5bcbe136b7d91e02'
apiCommit = '06560e3e053bda1ab830750db6f645bab703f824'
nodeVersion = $NodeVersion
sourceFingerprint = $fingerprint
} | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $staging 'payload.json') -Encoding utf8
if (Test-Path -LiteralPath $Destination) { Remove-Item -LiteralPath $Destination -Recurse -Force }
Move-Item -LiteralPath $staging -Destination $Destination