param( [string]$OutputDirectory = 'dist\source' ) $ErrorActionPreference = 'Stop' $repo = (Resolve-Path -LiteralPath $PSScriptRoot).Path $version = (Get-Content -LiteralPath (Join-Path $repo 'VERSION') -Raw).Trim() $output = [System.IO.Path]::GetFullPath((Join-Path $repo $OutputDirectory)) $archive = Join-Path $output "dat-gpt-v$version-source.zip" $excludedRoots = @('build', 'dist', 'local-data', 'test-deps', '.git') $excludedDirectories = @('node_modules') $excludedFiles = @( 'config.h', 'config.mk', 'config.log', 'dpid_comm_keys', 'identity.key', 'room-secret.key', 'secret_key', 'Cookies.txt', 'cookies.txt', 'known_hosts', 'authorized_keys', 'id_rsa', 'id_ed25519' ) if (!$output.StartsWith($repo + [System.IO.Path]::DirectorySeparatorChar, [StringComparison]::OrdinalIgnoreCase)) { throw "Source archive output must be inside the repository: $output" } New-Item -ItemType Directory -Path $output -Force | Out-Null if (Test-Path -LiteralPath $archive) { Remove-Item -LiteralPath $archive -Force } Add-Type -AssemblyName System.IO.Compression.FileSystem $zip = [System.IO.Compression.ZipFile]::Open($archive, [System.IO.Compression.ZipArchiveMode]::Create) try { $pending = [System.Collections.Generic.Stack[string]]::new() $pending.Push($repo) while ($pending.Count -gt 0) { $directory = $pending.Pop() foreach ($item in Get-ChildItem -LiteralPath $directory -Force) { $relative = $item.FullName.Substring($repo.Length).TrimStart('\') if (($item.Attributes -band [System.IO.FileAttributes]::ReparsePoint) -ne 0) { continue } if ($item.PSIsContainer) { $parts = $relative -split '[\\/]' if ($excludedRoots -contains $parts[0] -or $excludedDirectories -contains $item.Name -or $item.Name -eq '.git') { continue } $pending.Push($item.FullName) continue } if ($excludedFiles -contains $item.Name -or $item.Name -eq '.env' -or $item.Name.StartsWith('.env.', [StringComparison]::OrdinalIgnoreCase)) { continue } $entryName = "dat-gpt-v$version/" + ($relative -replace '\\', '/') [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile( $zip, $item.FullName, $entryName, [System.IO.Compression.CompressionLevel]::Optimal ) | Out-Null } } } finally { $zip.Dispose() } Write-Host "Source archive created: $archive"