diff --git a/README.md b/README.md index 4231515..1dd6fd4 100644 --- a/README.md +++ b/README.md @@ -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