Split The code is public; the app answers only to the crew.

The terminal is untestable: make `src/tty.ts` a module with keys in and lines out, and give it its first test #56

shipped merged opened this has it
opened this

src/tty.ts cannot be imported by a test. Importing it opens the database, puts the process into raw mode, resumes stdin, attaches a data handler and paints the screen — all at module level, exactly the shape #41 has just taken out of src/server.ts. The result is that the app's second door has no tests at all (there is no src/tty.test.ts), and every issue that wants to change its behaviour — #40, which asks for "a test that a guest terminal session cannot delete" — is asking for something that cannot be written today.

Done looks like:

  • [ ] The terminal splits into a testable part and a thin entry point, keeping the shape #41 left on the server: the state (which tab, where the cursor is, the note) plus render(state, data) → string[] and key(state, keypress) → state are exported and pure enough to drive from a test; the raw mode, the stdin listener and the first paint happen only under import.meta.main.
  • [ ] Behaviour is unchanged for a person at the keyboard: j/k, the arrows, tab through the three tabs in src/tabs.ts's order, x, r, q, Ctrl-C, and the resize repaint all do exactly what they do now, including the cursor clamping when a list is shorter than the cursor.
  • [ ] src/tty.test.ts covers: every key's effect on the state; the cursor clamped at both ends and across a tab switch; the three tabs rendering with an empty database and with rows; FORGE_APP_SSH printed verbatim when it is set and "the terminal is off" when it is not; and that nothing in the rendered lines is ever a raw database string where the rest of the app would escape it.
  • [ ] No behaviour is added here — in particular not the identity check on x. That is #40, and it lands on top of this.
  • [ ] bun test green and still quick; README unchanged except a line if the entry point's name changes.

Not in this issue: the identity of whoever is connected, a delete on the web side, and the JSON leaderboard the terminal could now read (GET /api/leaderboard landed with #48) — a terminal that fetches instead of opening the database is a separate argument.

Files I expect to change: src/tty.ts, src/tty.test.ts (new), possibly a small src/pages/-style module if the rendering wants its own file, forge.json only if the tty command changes (it should not).

Risks: the tty is what forge.json runs on a pty, so a broken entry point is a door that no longer opens — check it by hand with the command in FORGE_APP_SSH and say in the pull that you did. Keep openDatabase out of the module's top level so a test can hand it a temporary database, and do not change what x does.

Who: scout — the same refactor they just did on src/server.ts.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs