217 lines
7.1 KiB
PowerShell
217 lines
7.1 KiB
PowerShell
param(
|
|
[ValidateSet("web", "tauri")]
|
|
[string]$Target = "web",
|
|
[ValidateSet("Release", "Debug")]
|
|
[string]$Configuration = "Release",
|
|
[ValidateSet("none", "nsis", "msi")]
|
|
[string]$TauriBundles = "none",
|
|
[switch]$InstallDeps,
|
|
[switch]$SkipInstall,
|
|
[switch]$DryRun
|
|
)
|
|
|
|
$commonScript = Join-Path $PSScriptRoot "script-common.ps1"
|
|
if (-not (Test-Path $commonScript)) {
|
|
throw "Missing helper script: $commonScript"
|
|
}
|
|
. $commonScript
|
|
|
|
$repoRoot = Resolve-JournalRepoRoot -StartPath $PSScriptRoot
|
|
$appRoot = Resolve-JournalAppRoot -RepoRoot $repoRoot
|
|
|
|
Clear-JournalProxyEnv
|
|
|
|
# Keep npm cache and temp local to the repo.
|
|
$npmCacheDir = Join-Path $repoRoot ".npm\cache"
|
|
$npmTempDir = Join-Path $repoRoot ".tmp\npm-temp"
|
|
New-Item -ItemType Directory -Force -Path $npmCacheDir, $npmTempDir | Out-Null
|
|
$env:npm_config_cache = $npmCacheDir
|
|
$env:npm_config_update_notifier = "false"
|
|
$env:npm_config_fund = "false"
|
|
$env:npm_config_audit = "false"
|
|
$env:npm_config_offline = "false"
|
|
$env:npm_config_prefer_offline = "false"
|
|
$env:npm_config_prefer_online = "true"
|
|
$env:TEMP = $npmTempDir
|
|
$env:TMP = $npmTempDir
|
|
|
|
if (-not (Get-Command npm -ErrorAction SilentlyContinue)) {
|
|
throw "npm is required but was not found in PATH."
|
|
}
|
|
|
|
$nodeModulesPath = Join-Path $appRoot "node_modules"
|
|
$packageJsonPath = Join-Path $appRoot "package.json"
|
|
$packageLockPath = Join-Path $appRoot "package-lock.json"
|
|
$depsHashPath = Join-Path $appRoot "node_modules\.journal-deps.sha256"
|
|
|
|
function Get-JournalNodeDepsHash {
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[string[]]$Paths
|
|
)
|
|
|
|
$hashLines = foreach ($path in $Paths) {
|
|
if (-not (Test-Path $path)) {
|
|
continue
|
|
}
|
|
(Get-FileHash -Algorithm SHA256 -Path $path).Hash
|
|
}
|
|
return ($hashLines -join "`n").Trim()
|
|
}
|
|
|
|
$hashInputs = @()
|
|
if (Test-Path $packageJsonPath) {
|
|
$hashInputs += $packageJsonPath
|
|
}
|
|
if (Test-Path $packageLockPath) {
|
|
$hashInputs += $packageLockPath
|
|
}
|
|
if ($hashInputs.Count -eq 0) {
|
|
throw "package.json not found under $appRoot."
|
|
}
|
|
|
|
$expectedDepsHash = Get-JournalNodeDepsHash -Paths $hashInputs
|
|
$shouldInstall = $InstallDeps -or (-not (Test-Path $nodeModulesPath))
|
|
$installReason = $null
|
|
|
|
if (-not $shouldInstall -and -not $SkipInstall) {
|
|
if (-not (Test-Path $depsHashPath)) {
|
|
$shouldInstall = $true
|
|
$installReason = "dependency hash missing"
|
|
}
|
|
else {
|
|
$currentDepsHash = (Get-Content $depsHashPath -Raw).Trim()
|
|
if ($currentDepsHash -ne $expectedDepsHash) {
|
|
$shouldInstall = $true
|
|
$installReason = "package.json/lockfile changed"
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($SkipInstall) {
|
|
$shouldInstall = $false
|
|
if ($installReason) {
|
|
Write-Host "SkipInstall set; dependencies may be stale ($installReason)." -ForegroundColor Yellow
|
|
}
|
|
}
|
|
|
|
Write-Host "Building Journal.App target '$Target' ($Configuration)..." -ForegroundColor Cyan
|
|
Write-Host "Using app root: $appRoot" -ForegroundColor DarkGray
|
|
|
|
Push-Location $appRoot
|
|
try {
|
|
if ($shouldInstall) {
|
|
$installArgs = if (Test-Path $packageLockPath) {
|
|
@("ci", "--no-audit", "--fund=false")
|
|
}
|
|
else {
|
|
@("install", "--no-audit", "--fund=false")
|
|
}
|
|
|
|
if ($installReason) {
|
|
Write-Host "Dependencies changed ($installReason). Installing..." -ForegroundColor Yellow
|
|
}
|
|
|
|
Write-Host "> npm $($installArgs -join ' ')" -ForegroundColor DarkGray
|
|
if (-not $DryRun) {
|
|
& npm @installArgs
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Dependency install failed with exit code $LASTEXITCODE."
|
|
}
|
|
|
|
$depsDir = Split-Path $depsHashPath -Parent
|
|
if (-not (Test-Path $depsDir)) {
|
|
New-Item -ItemType Directory -Force -Path $depsDir | Out-Null
|
|
}
|
|
$expectedDepsHash | Set-Content -Path $depsHashPath -NoNewline
|
|
}
|
|
}
|
|
else {
|
|
Write-Host "Skipping dependency install (node_modules present and deps unchanged)." -ForegroundColor DarkGray
|
|
}
|
|
|
|
if ($Target -eq "web") {
|
|
$buildArgs = @("run", "build")
|
|
Write-Host "> npm $($buildArgs -join ' ')" -ForegroundColor DarkGray
|
|
if (-not $DryRun) {
|
|
& npm @buildArgs
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Frontend build failed with exit code $LASTEXITCODE."
|
|
}
|
|
}
|
|
|
|
$outputPath = Join-Path $appRoot "build"
|
|
if ($DryRun) {
|
|
Write-Host "`nDry run complete (no commands executed)." -ForegroundColor Yellow
|
|
Write-Host "Expected output: $outputPath" -ForegroundColor Gray
|
|
}
|
|
else {
|
|
Write-Host "`nFrontend build successful." -ForegroundColor Green
|
|
Write-Host "Output: $outputPath" -ForegroundColor Gray
|
|
}
|
|
}
|
|
else {
|
|
$tauriArgs = @("run", "tauri", "build")
|
|
$tauriCliArgs = @()
|
|
if ($TauriBundles -eq "none") {
|
|
$tauriCliArgs += "--no-bundle"
|
|
}
|
|
else {
|
|
$tauriCliArgs += @("--bundles", $TauriBundles)
|
|
}
|
|
if ($Configuration -eq "Debug") {
|
|
$tauriCliArgs += "--debug"
|
|
}
|
|
if ($tauriCliArgs.Count -gt 0) {
|
|
$tauriArgs += "--"
|
|
$tauriArgs += $tauriCliArgs
|
|
}
|
|
|
|
Write-Host "> npm $($tauriArgs -join ' ')" -ForegroundColor DarkGray
|
|
if (-not $DryRun) {
|
|
& npm @tauriArgs
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Tauri build failed with exit code $LASTEXITCODE."
|
|
}
|
|
}
|
|
|
|
$targetConfigDir = if ($Configuration -eq "Debug") { "debug" } else { "release" }
|
|
$tauriTargetPath = Join-Path $appRoot "src-tauri\target"
|
|
$rawExePath = Join-Path $tauriTargetPath "$targetConfigDir\journalapp.exe"
|
|
if ($DryRun) {
|
|
Write-Host "`nDry run complete (no commands executed)." -ForegroundColor Yellow
|
|
if ($TauriBundles -eq "none") {
|
|
Write-Host "Expected executable: $rawExePath" -ForegroundColor Gray
|
|
}
|
|
else {
|
|
Write-Host "Expected output root: $tauriTargetPath" -ForegroundColor Gray
|
|
}
|
|
}
|
|
else {
|
|
Write-Host "`nTauri build successful." -ForegroundColor Green
|
|
if ($TauriBundles -eq "none") {
|
|
if (Test-Path $rawExePath) {
|
|
Write-Host "Executable location: $rawExePath" -ForegroundColor Gray
|
|
}
|
|
else {
|
|
$exeCandidates = Get-ChildItem -Path (Join-Path $tauriTargetPath $targetConfigDir) -File -Filter *.exe -ErrorAction SilentlyContinue |
|
|
Sort-Object LastWriteTime -Descending
|
|
if ($exeCandidates -and $exeCandidates.Count -gt 0) {
|
|
Write-Host "Executable location: $($exeCandidates[0].FullName)" -ForegroundColor Gray
|
|
}
|
|
else {
|
|
Write-Host "Output root: $tauriTargetPath" -ForegroundColor Gray
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
Write-Host "Output root: $tauriTargetPath" -ForegroundColor Gray
|
|
}
|
|
}
|
|
}
|
|
}
|
|
finally {
|
|
Pop-Location
|
|
}
|
|
|