Add local ADB web remote for Android TV

Node/Express server shells out to adb (connect/pair/keyevent/text/app
launch) and serves a mobile-first installable PWA remote: power, mute,
input switch, volume/channel rockers, D-pad, media transport, text
entry, and one-tap streaming app launch. Supports multiple saved TVs
and the Android 11+ wireless-debugging pairing flow.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RSVyYcrjrbmrMKT85G4fyn
This commit is contained in:
Claude
2026-09-26 12:40:01 +00:00
commit 6db1db70a0
18 changed files with 2246 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
import { test } from "node:test";
import assert from "node:assert/strict";
import * as adb from "../src/adb.js";
test("normalizeTarget adds default port 5555", () => {
assert.equal(adb.normalizeTarget("192.168.1.50"), "192.168.1.50:5555");
});
test("normalizeTarget keeps an explicit port", () => {
assert.equal(adb.normalizeTarget("192.168.1.50:5556"), "192.168.1.50:5556");
});
test("normalizeTarget trims whitespace", () => {
assert.equal(adb.normalizeTarget(" 192.168.1.50 "), "192.168.1.50:5555");
});
test("normalizeTarget rejects shell-hostile input", () => {
assert.throws(() => adb.normalizeTarget("1.2.3.4; rm -rf /"), /doesn't look like/);
});
test("normalizeTarget rejects empty input", () => {
assert.throws(() => adb.normalizeTarget(""), /doesn't look like/);
});
test("connect() rejects cleanly against a closed local port instead of hanging", async () => {
// Nothing listens on 5599 locally, so `adb connect` should fail fast with
// a normal error rather than the process throwing an unhandled exception.
await assert.rejects(adb.connect("127.0.0.1:5599"), (err) => {
assert.equal(err.name, "AdbError");
return true;
});
});
test("pair() rejects a non-6-digit code before touching adb", async () => {
await assert.rejects(adb.pair("127.0.0.1:5599", "12"), /6 digits/);
});