Document packaging, and add a script that verifies a package runs

A package broken in the ways that matter still builds, installs and starts;
native modules left inside the asar fail on a user's machine the first time
they open a terminal. scripts/verify-package.mjs extracts the AppImage and
asserts the binaries really are unpacked beside it.

Also records that the deb metadata fields are placeholders.
This commit is contained in:
ylhan
2026-09-17 03:14:17 +08:00
parent 430d78b9f0
commit 1538d42793
+40 -1
View File
@@ -22,7 +22,7 @@ Early. See the milestone table in the implementation plan.
| M6 | Flow control and reconnect resilience | done |
| M7 | Port forwarding (`-L` / `-R` / `-D`) | |
| M8 | Local terminal + serial | local terminal done, serial not |
| M9 | Packaging | |
| M9 | Packaging | done |
## Prerequisites
@@ -151,6 +151,45 @@ That covers the whole outbound path, and the result cannot be faked by a
rendering bug. The final report carries `remoteUser`, read back from a file the
remote wrote — which is the return path proven separately.
## Packaging
```sh
npm run dist # AppImage + deb into release/
npm run verify:package # check the result can actually run
```
`scripts/verify-package.mjs` exists because a package that is broken in the
ways that matter still builds, still installs, and still starts. Native modules
cannot be loaded from inside an asar archive, and when they are left there the
failure appears on a user's machine the first time they open a terminal — not
in CI, and not in `npm test`. So the script extracts the AppImage and asserts
that each native binary really is in `app.asar.unpacked`.
Two things it checks that are easy to get wrong:
- **`ssh2` carries a native module.** `sshcrypto.node` is easy to miss because
the library reads as pure JavaScript — and because a failed load falls back
to a JS implementation silently, so nothing would ever report it.
- **`node-pty` must be unpacked whole, not just its `.node` files.** On macOS
and Windows it ships `spawn-helper`, a real executable loaded from disk rather
than `dlopen`ed, which stays trapped in the archive if only `*.node` is
unpacked.
`npmRebuild` is off: every native module here is built on `node-addon-api`, so
the binaries from `npm install` load unchanged in Electron's Node. Rebuilding
would cost time and risk replacing working binaries for no gain.
Both `.deb` metadata and `desktopName` are set, and the AppImage's
`.desktop` entry is generated from `linux.desktop.entry`.
### Packaging notes for whoever picks this up
- The `author`, `homepage` and `maintainer` fields are **placeholders**
(`ylhan@example.com`, `example.com`). They are required by the deb format and
must be replaced before distributing.
- `asarUnpack` lists `node_modules/@serialport/**` for a backend that does not
exist yet. Harmless now; load-bearing once the serial transport lands.
## Toolchain constraints
### Why Electron is pinned exactly