diff --git a/scripts/start-local.ps1 b/scripts/start-local.ps1 index 857bb23..d2fee5a 100644 --- a/scripts/start-local.ps1 +++ b/scripts/start-local.ps1 @@ -280,11 +280,36 @@ Reserved ranges: netsh interface ipv4 show excludedportrange protocol=tcp function Install-IfMissing { param([string]$Directory) $name = Split-Path -Leaf $Directory - if (Test-Path (Join-Path $Directory 'node_modules')) { - Write-Note "$name dependencies already installed" - return + + # Whether node_modules matches the lockfile, not merely whether it exists. + # + # This used to ask only `Test-Path node_modules`, which meant a branch that + # ADDED a dependency never installed it for anyone who already had the + # directory — and almost everyone always does. The build then failed on + # "Cannot find module", naming a package that is right there in + # package.json, which reads as a broken checkout rather than a missing + # install. It cost an afternoon the first time #37 added @simplewebauthn. + # + # npm writes node_modules/.package-lock.json describing exactly what it put + # there, so comparing its timestamp against package-lock.json answers the + # real question: is what is installed what is currently asked for. A pull + # that changes dependencies makes the lockfile newer, and this notices. + $lockfile = Join-Path $Directory 'package-lock.json' + $installed = Join-Path $Directory 'node_modules/.package-lock.json' + + if ((Test-Path $installed) -and (Test-Path $lockfile)) { + $lockTime = (Get-Item $lockfile).LastWriteTimeUtc + $installedTime = (Get-Item $installed).LastWriteTimeUtc + if ($installedTime -ge $lockTime) { + Write-Note "$name dependencies are up to date" + return + } + Write-Step "Installing $name dependencies (the lockfile has changed)" } - Write-Step "Installing $name dependencies" + else { + Write-Step "Installing $name dependencies" + } + Push-Location $Directory try { Invoke-Checked { npm install } "$name npm install" } finally { Pop-Location } }