fix(web): bundle deps into the server (noExternals) — kill the 47k-file install
apple / swift (push) Successful in 1m0s
ci / rust (push) Successful in 1m18s
ci / web (push) Successful in 43s
ci / docs-site (push) Successful in 1m4s
android / android (push) Successful in 3m26s
deb / build-publish (push) Successful in 2m37s
apple / screenshots (push) Successful in 5m9s
decky / build-publish (push) Successful in 14s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 25s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
windows-host / package (push) Successful in 6m51s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
ci / bench (push) Successful in 4m35s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 47s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m3s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 9m8s
docker / deploy-docs (push) Successful in 19s
apple / swift (push) Successful in 1m0s
ci / rust (push) Successful in 1m18s
ci / web (push) Successful in 43s
ci / docs-site (push) Successful in 1m4s
android / android (push) Successful in 3m26s
deb / build-publish (push) Successful in 2m37s
apple / screenshots (push) Successful in 5m9s
decky / build-publish (push) Successful in 14s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 25s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
windows-host / package (push) Successful in 6m51s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
ci / bench (push) Successful in 4m35s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 47s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m3s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 9m8s
docker / deploy-docs (push) Successful in 19s
The Windows installer ballooned to 154 MB and installed forever because the node-server
bundle externalized the WHOLE @unom/ui dependency tree (payload, lexical, date-fns,
prismjs…) to .output/server/node_modules — 47,567 files / 730 MB copied into Program
Files. Set Nitro `noExternals: true` so every dependency is bundled + tree-shaken into the
server output: .output drops to ~75 files / 10 MB, and the bare external imports
(srvx, seroval…) bun couldn't resolve at runtime are gone — so the console runs on bun
(no node, no node_modules), which is the issue we previously worked around with node.
Windows installer now ships bun.exe + the ~75-file .output (was node.exe + a node_modules
forest) and runs `bun .output\server\index.mjs`:
- windows-host.yml: fetch a pinned portable bun (build tool AND shipped runtime); drop the
node fetch + the .output/server install; smoke-boot under the bundled bun.
- pack-host-installer.ps1 / punktfunk-host.iss: -NodeExe -> -BunExe; stage {app}\bun\bun.exe.
- web-run.cmd / build-web.ps1: run/restart on bun; docs updated.
Net win everywhere: the Linux .deb shrinks (node still runs the self-contained output), and
the docker web image — which already ran `bun run .output/server/index.mjs` with only
.output copied — is fixed (the externals had no node_modules to resolve at runtime).
Validated locally: noExternals build = 75 files / 10 MB; node AND bun both serve /login
(200) + static assets (200) + gate /api (401).
(A true single binary via `bun build --compile` is blocked for now: Nitro serves public
assets from an import.meta-relative path `--compile` doesn't embed (/$bunfs/public); the
75-file payload is the clean result.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# Build the punktfunk Windows HOST as a signed Inno Setup installer and publish it to Gitea's generic
|
||||
# package registry, so a Windows GPU box can install the streaming host (SYSTEM service + bundled
|
||||
# SudoVDA virtual-display driver + the web management console, run by a scheduled task on a bundled
|
||||
# Node) from one signed setup.exe. Runs on the self-hosted Windows runner
|
||||
# bun) from one signed setup.exe. Runs on the self-hosted Windows runner
|
||||
# (host mode; scripts/ci/setup-windows-runner.ps1) — same MSVC/Windows-SDK/LLVM env as windows.yml.
|
||||
#
|
||||
# Why an installer and not MSIX (like the client): the host installs a LocalSystem SCM service that
|
||||
@@ -104,46 +104,36 @@ jobs:
|
||||
choco install innosetup -y --no-progress
|
||||
}
|
||||
|
||||
- name: Fetch portable Node runtime (bundled to run the console)
|
||||
- name: Fetch portable bun runtime (build tool + bundled to run the console)
|
||||
shell: pwsh
|
||||
run: |
|
||||
# The installer ships a self-contained node.exe so the web console runs with no system-Node
|
||||
# prerequisite. Pinned LTS (>= 20, matching the punktfunk-web .deb's `nodejs (>= 20)`); the
|
||||
# smoke test below validates the .output bundle runs under exactly this node before shipping.
|
||||
$ver = 'v22.11.0'
|
||||
$url = "https://nodejs.org/dist/$ver/node-$ver-win-x64.zip"
|
||||
# ONE pinned bun, used both to BUILD the console and shipped in the installer to RUN it. The
|
||||
# .output is self-contained (Nitro noExternals — deps bundled + tree-shaken, no node_modules),
|
||||
# so the installer ships just bun + a ~75-file .output instead of node + a node_modules forest.
|
||||
$ver = 'bun-v1.3.14'
|
||||
$url = "https://github.com/oven-sh/bun/releases/download/$ver/bun-windows-x64.zip"
|
||||
New-Item -ItemType Directory -Force -Path C:\t | Out-Null
|
||||
$zip = 'C:\t\node.zip'; $dst = 'C:\t\nodedist'
|
||||
$zip = 'C:\t\bun.zip'; $dst = 'C:\t\bundist'
|
||||
Invoke-WebRequest -Uri $url -OutFile $zip
|
||||
if (Test-Path $dst) { Remove-Item $dst -Recurse -Force }
|
||||
Expand-Archive -Path $zip -DestinationPath $dst -Force
|
||||
$node = (Get-ChildItem -Path $dst -Recurse -Filter node.exe | Select-Object -First 1).FullName
|
||||
if (-not $node) { throw "node.exe not found in $url" }
|
||||
"NODE_EXE=$node" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
||||
& $node --version
|
||||
$bun = (Get-ChildItem -Path $dst -Recurse -Filter bun.exe | Select-Object -First 1).FullName
|
||||
if (-not $bun) { throw "bun.exe not found in $url" }
|
||||
"BUN_EXE=$bun" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
||||
& $bun --version
|
||||
|
||||
- name: Build + smoke-boot web console (node-server preset)
|
||||
- name: Build + smoke-boot web console (bun)
|
||||
shell: pwsh
|
||||
env:
|
||||
# PAT with read access to the unom org packages — the @unom npm registry needs auth.
|
||||
# PAT with read access to the unom org packages — the @unom npm registry needs auth to BUILD.
|
||||
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||
# Same shape as deb.yml: bun builds the Nitro node-server bundle, node runs it; the installer
|
||||
# bundles web\.output (handed over via WEB_OUTPUT_DIR) + the portable node above. The runner
|
||||
# runs as SYSTEM (no dev-user PATH/npmrc), so bootstrap bun if absent and supply the private
|
||||
# @unom registry token via the SYSTEM home .npmrc — kept OUT of the shipped bundle.
|
||||
# The bun fetched above builds the Nitro server AND runs it. noExternals (vite.config) makes the
|
||||
# output self-contained, so there's no .output/server install — the installer ships bun + the
|
||||
# ~75-file .output. The runner is SYSTEM with no ~/.npmrc, so supply the private @unom token in
|
||||
# the SYSTEM home .npmrc to BUILD (kept OUT of the shipped bundle — web\.npmrc has only the
|
||||
# registry mapping, and nothing copies it into .output).
|
||||
run: |
|
||||
$bun = (Get-Command bun -ErrorAction SilentlyContinue).Source
|
||||
if (-not $bun) { foreach ($p in @("$env:USERPROFILE\.bun\bin\bun.exe", 'C:\Users\Public\bun\bin\bun.exe')) { if (Test-Path $p) { $bun = $p; break } } }
|
||||
if (-not $bun) {
|
||||
Write-Output "bun not found - installing via bun.sh"
|
||||
Invoke-RestMethod https://bun.sh/install.ps1 | Invoke-Expression
|
||||
$bun = Join-Path $env:USERPROFILE '.bun\bin\bun.exe'
|
||||
}
|
||||
if (-not (Test-Path $bun)) { throw "bun unavailable (install failed?): $bun" }
|
||||
& $bun --version
|
||||
# @unom is a private Gitea npm registry. The committed web\.npmrc has only the registry
|
||||
# mapping; put the mapping + auth token in the SYSTEM home .npmrc so the token never lands in
|
||||
# the shipped bundle (.output\server\.npmrc stays the clean mapping-only copy).
|
||||
$bun = $env:BUN_EXE
|
||||
if ($env:REGISTRY_TOKEN) {
|
||||
$rc = Join-Path $env:USERPROFILE '.npmrc'
|
||||
Add-Content -Path $rc -Value '@unom:registry=https://git.unom.io/api/packages/unom/npm/'
|
||||
@@ -155,19 +145,16 @@ jobs:
|
||||
if (Select-String -Path .output\server\index.mjs -Pattern 'Bun\.serve' -Quiet) {
|
||||
throw "web build is a bun bundle (Bun.serve) - need the node-server preset"
|
||||
}
|
||||
# Externalized @unom SSR deps must be installed inside .output\server (registry mapping via .npmrc).
|
||||
Copy-Item .npmrc .output\server\.npmrc -Force
|
||||
Push-Location .output\server; & $bun install; if ($LASTEXITCODE) { throw ".output/server dep install failed ($LASTEXITCODE)" }; Pop-Location
|
||||
Pop-Location
|
||||
# Gate the installer on a real node boot serving /login (the runtime the installer ships).
|
||||
# Gate the installer on a real boot under the BUNDLED bun (the runtime it ships), serving /login.
|
||||
$env:PORT = '3009'; $env:HOST = '127.0.0.1'; $env:PUNKTFUNK_UI_PASSWORD = 'ci'
|
||||
$server = (Resolve-Path 'web\.output\server\index.mjs').Path
|
||||
$p = Start-Process -FilePath $env:NODE_EXE -ArgumentList $server -PassThru -WindowStyle Hidden
|
||||
$p = Start-Process -FilePath $bun -ArgumentList $server -PassThru -WindowStyle Hidden
|
||||
Start-Sleep -Seconds 4
|
||||
try { $code = (Invoke-WebRequest -Uri 'http://127.0.0.1:3009/login' -UseBasicParsing -TimeoutSec 10).StatusCode } catch { $code = 0 }
|
||||
Stop-Process -Id $p.Id -Force -ErrorAction SilentlyContinue
|
||||
Write-Output "web console smoke: /login -> $code"
|
||||
if ($code -ne 200) { throw "web console failed to boot under node" }
|
||||
Write-Output "web console smoke (bun): /login -> $code"
|
||||
if ($code -ne 200) { throw "web console failed to boot under bun" }
|
||||
"WEB_OUTPUT_DIR=$((Resolve-Path 'web\.output').Path)" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
||||
|
||||
- name: Pack + sign installer
|
||||
|
||||
@@ -33,7 +33,7 @@ and the CLI `punktfunk-host service install` path) are in
|
||||
[`packaging/windows`](https://git.unom.io/unom/punktfunk/src/branch/main/packaging/windows/README.md).
|
||||
|
||||
The installer also sets up the **web management console** (status, paired devices, the PIN pairing
|
||||
flow): it bundles the console plus its own Node runtime and runs it as the **`PunktfunkWeb`** service
|
||||
flow): it bundles the console plus its own bun runtime and runs it as the **`PunktfunkWeb`** service
|
||||
on **`http://<this-PC>:3000`**, starting at boot. During setup you choose the console **login
|
||||
password** (pre-filled with a secure random default and shown again on the final page); change it
|
||||
later in `%ProgramData%\punktfunk\web-password`. Open the console from any browser on the LAN and log
|
||||
|
||||
@@ -33,11 +33,12 @@ exe into `C:\Program Files\punktfunk\` and calls that subcommand, elevated.
|
||||
display without it).
|
||||
- Runs `punktfunk-host service install` (idempotent; writes a default `host.env` only if absent, so
|
||||
user config survives upgrades) and, by the *Start service now* task, `service start`.
|
||||
- **Web management console** (bundled when packed with `-WebDir`/`-NodeExe`, which the CI always is):
|
||||
lays down the built `.output` server + a portable Node, prompts for a console login password
|
||||
(pre-filled with a secure random default, shown again on the final page; kept on upgrade), then
|
||||
`web-setup.ps1` writes the ACL'd `%ProgramData%\punktfunk\web-password`, registers the
|
||||
**`PunktfunkWeb`** scheduled task (boot, SYSTEM, restart-on-failure → `web-run.cmd` → `node` on
|
||||
- **Web management console** (bundled when packed with `-WebDir`/`-BunExe`, which the CI always is):
|
||||
lays down the built **self-contained** `.output` server (Nitro `noExternals` — deps bundled +
|
||||
tree-shaken, ~75 files, no `node_modules`) + a portable **bun**, prompts for a console login
|
||||
password (pre-filled with a secure random default, shown again on the final page; kept on upgrade),
|
||||
then `web-setup.ps1` writes the ACL'd `%ProgramData%\punktfunk\web-password`, registers the
|
||||
**`PunktfunkWeb`** scheduled task (boot, SYSTEM, restart-on-failure → `web-run.cmd` → `bun` on
|
||||
`:3000`), opens TCP 3000, and starts it. It proxies the host's loopback mgmt API with the host's
|
||||
own `%ProgramData%\punktfunk\mgmt-token`.
|
||||
- **Upgrade:** stops a running `PunktfunkHost` service and waits for `STOPPED` before replacing files
|
||||
@@ -63,10 +64,10 @@ read it from `%ProgramData%\punktfunk\web-password`.
|
||||
| File | Role |
|
||||
|------|------|
|
||||
| `punktfunk-host.iss` | Inno Setup script (the installer definition). |
|
||||
| `pack-host-installer.ps1` | Orchestrator: cert + sign, stage the driver + FFmpeg + **web console** (`.output` + node) bundles, run ISCC, sign setup.exe, emit registry paths. |
|
||||
| `pack-host-installer.ps1` | Orchestrator: cert + sign, stage the driver + FFmpeg + **web console** (`.output` + bun) bundles, run ISCC, sign setup.exe, emit registry paths. |
|
||||
| `stage-sudovda.ps1` | Stage the **vendored** SudoVDA driver + fetch/verify the **pinned** nefcon release into the bundle. |
|
||||
| `install-sudovda.ps1` | Runs at install time (elevated): trust cert → gated device-node create → `pnputil` install. |
|
||||
| `../../scripts/windows/web-run.cmd` | The `PunktfunkWeb` task action: loads the mgmt token + login password env, runs the bundled `node` on the Nitro server (`:3000`). |
|
||||
| `../../scripts/windows/web-run.cmd` | The `PunktfunkWeb` task action: loads the mgmt token + login password env, runs the bundled `bun` on the Nitro server (`:3000`). |
|
||||
| `../../scripts/windows/web-setup.ps1` | Install-time (elevated): write the ACL'd console password, register the `PunktfunkWeb` task + firewall rule, start it. |
|
||||
| `sudovda/` | **Vendored** prebuilt SudoVDA driver: `SudoVDA.inf` / `sudovda.cat` / `SudoVDA.dll` / `sudovda.cer`. |
|
||||
| `nvenc/nvenc.def`, `nvenc/gen-nvenc-importlib.ps1` | Synthesise `nvencodeapi.lib` for the `--features nvenc` link (llvm-dlltool / lib.exe). |
|
||||
|
||||
@@ -27,7 +27,7 @@ param(
|
||||
[string]$PfxPassword = $env:MSIX_CERT_PASSWORD,
|
||||
[string]$FfmpegDir = $env:FFMPEG_DIR, # bundle its bin\*.dll (amf-qsv build)
|
||||
[string]$WebDir = $env:WEB_OUTPUT_DIR, # built web .output tree -> bundle the mgmt console
|
||||
[string]$NodeExe = $env:NODE_EXE, # portable node.exe (>= 20) runtime for the console
|
||||
[string]$BunExe = $env:BUN_EXE, # portable bun.exe runtime for the console
|
||||
[switch]$NoDriver, # build without the bundled SudoVDA driver
|
||||
[switch]$NoSign # skip signing (local debug)
|
||||
)
|
||||
@@ -184,30 +184,30 @@ if ($ffmpegBinSrc -and (Test-Path $ffmpegBinSrc)) {
|
||||
}
|
||||
else { Write-Host "no FFMPEG_DIR\bin -> installer built WITHOUT FFmpeg DLLs (nvenc/software-only host)" }
|
||||
|
||||
# --- stage the web management console (the built .output tree + a portable node + the launcher) ---
|
||||
# The console runs as the PunktfunkWeb scheduled task (`node {app}\web\.output\server\index.mjs`),
|
||||
# --- stage the web management console (the self-contained .output tree + a portable bun + launcher) -
|
||||
# The console runs as the PunktfunkWeb scheduled task (`bun {app}\web\.output\server\index.mjs`),
|
||||
# auto-wired to the host's loopback mgmt API. Stage everything ISCC reads into $OutDir (the
|
||||
# non-WOW64-redirected C:\t area, same reason as the .iss/host.env staging above). Built upstream
|
||||
# (windows-host.yml mirrors deb.yml: bun build -> node-server preset + the .output/server deps);
|
||||
# omitted when -WebDir/-NodeExe are unset (host-only installer, e.g. a local debug pack).
|
||||
if ($WebDir -and (Test-Path $WebDir) -and $NodeExe -and (Test-Path $NodeExe)) {
|
||||
# non-WOW64-redirected C:\t area, same reason as the .iss/host.env staging above). The .output is
|
||||
# self-contained (Nitro noExternals — deps bundled + tree-shaken, no node_modules), so bun runs it
|
||||
# directly; omitted when -WebDir/-BunExe are unset (host-only installer, e.g. a local debug pack).
|
||||
if ($WebDir -and (Test-Path $WebDir) -and $BunExe -and (Test-Path $BunExe)) {
|
||||
$webStage = Join-Path $OutDir 'web'
|
||||
if (Test-Path $webStage) { Remove-Item $webStage -Recurse -Force }
|
||||
New-Item -ItemType Directory -Force -Path $webStage | Out-Null
|
||||
Copy-Item (Join-Path $WebDir '*') -Destination $webStage -Recurse -Force
|
||||
$nodeStage = Join-Path $OutDir 'node.exe'
|
||||
Copy-Item -LiteralPath $NodeExe -Destination $nodeStage -Force
|
||||
$bunStage = Join-Path $OutDir 'bun.exe'
|
||||
Copy-Item -LiteralPath $BunExe -Destination $bunStage -Force
|
||||
$webRun = Join-Path $OutDir 'web-run.cmd'
|
||||
$webSetup = Join-Path $OutDir 'web-setup.ps1'
|
||||
Copy-Item (Join-Path $repoRoot 'scripts\windows\web-run.cmd') -Destination $webRun -Force
|
||||
Copy-Item (Join-Path $repoRoot 'scripts\windows\web-setup.ps1') -Destination $webSetup -Force
|
||||
$defines += "/DWebDir=$webStage"
|
||||
$defines += "/DNodeExe=$nodeStage"
|
||||
$defines += "/DBunExe=$bunStage"
|
||||
$defines += "/DWebRunCmd=$webRun"
|
||||
$defines += "/DWebSetup=$webSetup"
|
||||
Write-Host "bundling the web console from $WebDir (+ node $NodeExe)"
|
||||
Write-Host "bundling the web console from $WebDir (+ bun $BunExe)"
|
||||
}
|
||||
else { Write-Host "no -WebDir/-NodeExe -> installer built WITHOUT the web console" }
|
||||
else { Write-Host "no -WebDir/-BunExe -> installer built WITHOUT the web console" }
|
||||
|
||||
# --- build the installer (from the non-redirected copy under C:\t) -----------------------------
|
||||
Write-Host "==> ISCC $($defines -join ' ') $issLocal"
|
||||
|
||||
@@ -49,10 +49,10 @@
|
||||
#ifdef FfmpegBin
|
||||
#define WithFfmpeg
|
||||
#endif
|
||||
; WebDir (the built web .output tree) + NodeExe (a portable node.exe) are passed together by
|
||||
; WebDir (the built web .output tree) + BunExe (a portable bun.exe) are passed together by
|
||||
; pack-host-installer.ps1 to bundle the management console. Both required → WithWeb.
|
||||
#ifdef WebDir
|
||||
#ifdef NodeExe
|
||||
#ifdef BunExe
|
||||
#define WithWeb
|
||||
#endif
|
||||
#endif
|
||||
@@ -102,12 +102,12 @@ Source: "{#Readme}"; DestDir: "{app}"; DestName: "README.txt"; Flags: ignorevers
|
||||
Source: "{#FfmpegBin}\*.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
#endif
|
||||
#ifdef WithWeb
|
||||
; The web management console: the built Nitro/Node SSR bundle (.output = server + public assets) →
|
||||
; {app}\web\.output, a portable Node runtime → {app}\node\node.exe, and the launcher the
|
||||
; PunktfunkWeb task runs → {app}\web\web-run.cmd. web-setup.ps1 (the provisioner) goes to {tmp} and
|
||||
; is removed after install.
|
||||
; The web management console: the self-contained Nitro SSR bundle (.output = server + public; deps
|
||||
; bundled in, no node_modules) → {app}\web\.output, a portable bun runtime → {app}\bun\bun.exe, and
|
||||
; the launcher the PunktfunkWeb task runs → {app}\web\web-run.cmd. web-setup.ps1 (the provisioner)
|
||||
; goes to {tmp} and is removed after install.
|
||||
Source: "{#WebDir}\*"; DestDir: "{app}\web\.output"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
Source: "{#NodeExe}"; DestDir: "{app}\node"; DestName: "node.exe"; Flags: ignoreversion
|
||||
Source: "{#BunExe}"; DestDir: "{app}\bun"; DestName: "bun.exe"; Flags: ignoreversion
|
||||
Source: "{#WebRunCmd}"; DestDir: "{app}\web"; DestName: "web-run.cmd"; Flags: ignoreversion
|
||||
Source: "{#WebSetup}"; DestDir: "{tmp}"; DestName: "web-setup.ps1"; Flags: deleteafterinstall
|
||||
#endif
|
||||
|
||||
@@ -35,10 +35,10 @@ won't start. The service is down only for the build duration.
|
||||
## Web management console
|
||||
|
||||
On an **installed** host (the `setup.exe`) the console is set up automatically — no manual steps.
|
||||
The installer bundles the built `.output` server + a portable Node and runs
|
||||
`scripts\windows\web-setup.ps1`, which registers the **`PunktfunkWeb`** scheduled task (at boot, as
|
||||
SYSTEM, restart-on-failure) running `{app}\web\web-run.cmd` → `node …\.output\server\index.mjs` on
|
||||
`:3000`, opens inbound TCP 3000, and writes the login password to
|
||||
The installer bundles the built (self-contained, no-`node_modules`) `.output` server + a portable
|
||||
bun and runs `scripts\windows\web-setup.ps1`, which registers the **`PunktfunkWeb`** scheduled task
|
||||
(at boot, as SYSTEM, restart-on-failure) running `{app}\web\web-run.cmd` →
|
||||
`bun …\.output\server\index.mjs` on `:3000`, opens inbound TCP 3000, and writes the login password to
|
||||
`%ProgramData%\punktfunk\web-password` (ACL'd to Administrators + SYSTEM). The mgmt bearer token it
|
||||
proxies with is the host's own `%ProgramData%\punktfunk\mgmt-token`. Browse `http://<host-ip>:3000`
|
||||
and log in with the password the installer shows on its final page. To change it, edit
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
|
||||
powershell -ExecutionPolicy Bypass -File scripts\windows\build-web.ps1
|
||||
|
||||
bun = build tool, node = runtime (the Nitro bundle externalizes srvx/@unom for SSR, which
|
||||
bun fails to resolve at runtime). The PunktfunkWeb scheduled task runs web\web-run.cmd ->
|
||||
node .output\server\index.mjs on :3000.
|
||||
bun is both the build tool AND the runtime: vite.config's Nitro noExternals bundles every dep
|
||||
into the self-contained .output (no node_modules, nothing for bun to fail to resolve), so the
|
||||
PunktfunkWeb task runs web\web-run.cmd -> bun .output\server\index.mjs on :3000.
|
||||
#>
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$repo = Split-Path (Split-Path $PSScriptRoot)
|
||||
@@ -19,17 +19,11 @@ Write-Host "bun install + build ..."
|
||||
& $bun install
|
||||
& $bun run build
|
||||
if ($LASTEXITCODE -ne 0) { throw "web build failed (exit $LASTEXITCODE)" }
|
||||
|
||||
# The Nitro server bundle externalizes its runtime deps - install them in .output/server,
|
||||
# with the @unom registry .npmrc present (else @unom/* 404s on npmjs).
|
||||
Write-Host "installing externalized server deps ..."
|
||||
Copy-Item "$web\.npmrc" "$web\.output\server\.npmrc" -Force
|
||||
Set-Location "$web\.output\server"
|
||||
& $bun install
|
||||
# No .output/server install: noExternals means the output has no externalized deps to resolve.
|
||||
|
||||
Write-Host "restarting $task ..."
|
||||
& schtasks /end /tn $task 2>$null | Out-Null
|
||||
Get-CimInstance Win32_Process -Filter "Name='node.exe'" -ErrorAction SilentlyContinue |
|
||||
Get-CimInstance Win32_Process -Filter "Name='bun.exe'" -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.CommandLine -match 'index\.mjs' } |
|
||||
ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }
|
||||
Start-Sleep 2
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
rem punktfunk web console launcher — the action the PunktfunkWeb scheduled task runs at boot.
|
||||
rem
|
||||
rem Lays out next to the installed payload: {app}\web\web-run.cmd, {app}\web\.output\... and
|
||||
rem {app}\node\node.exe (so %~dp0 = {app}\web\). Auto-wires the console the same way the Linux
|
||||
rem {app}\bun\bun.exe (so %~dp0 = {app}\web\). Auto-wires the console the same way the Linux
|
||||
rem systemd unit does: it sources the host's mgmt bearer token + the console login password from
|
||||
rem %ProgramData%\punktfunk\, points the /api proxy at the host's loopback HTTPS mgmt API, and runs
|
||||
rem the Nitro/Node server on :3000. No env editing on a packaged install.
|
||||
rem the (self-contained, no-node_modules) Nitro server on :3000 with the bundled bun. No env editing.
|
||||
setlocal EnableExtensions
|
||||
|
||||
set "PFDATA=%ProgramData%\punktfunk"
|
||||
@@ -31,10 +31,10 @@ set "HOST=0.0.0.0"
|
||||
set "PUNKTFUNK_MGMT_URL=https://127.0.0.1:47990"
|
||||
set "NODE_TLS_REJECT_UNAUTHORIZED=0"
|
||||
|
||||
set "NODE=%~dp0..\node\node.exe"
|
||||
set "BUN=%~dp0..\bun\bun.exe"
|
||||
set "SERVER=%~dp0.output\server\index.mjs"
|
||||
if not exist "%NODE%" (
|
||||
echo [punktfunk-web] bundled node runtime missing at "%NODE%".
|
||||
if not exist "%BUN%" (
|
||||
echo [punktfunk-web] bundled bun runtime missing at "%BUN%".
|
||||
exit /b 1
|
||||
)
|
||||
"%NODE%" "%SERVER%"
|
||||
"%BUN%" "%SERVER%"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<#
|
||||
Provision the punktfunk web console after the host installer has laid down its payload
|
||||
({app}\web\.output, {app}\node\node.exe, {app}\web\web-run.cmd). Invoked elevated from the
|
||||
({app}\web\.output, {app}\bun\bun.exe, {app}\web\web-run.cmd). Invoked elevated from the
|
||||
installer's [Run] section; idempotent (safe to re-run on upgrade).
|
||||
|
||||
1. Sets the console login password file %ProgramData%\punktfunk\web-password
|
||||
@@ -71,7 +71,7 @@ $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoi
|
||||
-StartWhenAvailable -RestartInterval (New-TimeSpan -Minutes 1) -RestartCount 10 `
|
||||
-ExecutionTimeLimit (New-TimeSpan -Seconds 0)
|
||||
Register-ScheduledTask -TaskName $TaskName -Action $action -Trigger $trigger -Principal $principal `
|
||||
-Settings $settings -Description 'punktfunk web management console (Nitro/Node SSR on :3000)' `
|
||||
-Settings $settings -Description 'punktfunk web management console (Nitro SSR on bun, :3000)' `
|
||||
-Force | Out-Null
|
||||
Write-Host "registered scheduled task $TaskName -> $cmd"
|
||||
|
||||
|
||||
@@ -46,6 +46,14 @@ export default defineConfig({
|
||||
// .deb depend on apt-native `nodejs (>= 20)` instead of vendoring bun. CI still BUILDS with
|
||||
// bun; only the runtime target changes. (dev `vite dev` is unaffected.)
|
||||
preset: 'node-server',
|
||||
// BUNDLE every dependency into the server output (no externalized node_modules). Three wins:
|
||||
// (1) the .output tree drops from ~47k files / 730 MB (the whole untree-shaken @unom/ui dep
|
||||
// tree — payload, lexical, date-fns…) to a handful of tree-shaken chunks; (2) it makes the
|
||||
// output a self-contained graph `bun build --compile` can fold into ONE native binary (the
|
||||
// Windows installer ships that instead of node + a node_modules forest); (3) it removes the
|
||||
// bare external imports (`srvx`, `seroval`…) bun couldn't resolve at runtime — the reason we
|
||||
// used to need node. node still runs the same self-contained output for the Linux .deb.
|
||||
noExternals: true,
|
||||
compatibilityDate: '2026-06-10',
|
||||
// Scan server/{middleware,routes} for the auth gate + the /api proxy.
|
||||
scanDirs: [serverDir],
|
||||
|
||||
Reference in New Issue
Block a user