mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
- Web: base bundles built from the app's entry at start (content-hashed, served forever), plugin scripts that register themselves and one combined file, WebScripts/TuiScripts showing the current set, startPage with the connection loop, in-place plugin reloads and a reload on a new base bundle. - React bindings: HostProvider, useHold, useWatch, useRegistry, useRefState. - Terminal: startTerminal, a launcher that signs in with a token, a token file or device pairing and always runs the app's terminal code in a sandboxed child process (pipes, empty environment, --permission granting nothing, no SQLite, a builtin allowlist and a frozen process inside); output filter, confirmed copy/open/attach actions; startTerminalRuntime and TuiScope inside. - Themes: the Themes registry, ThemeChoice per principal, CSS variables on the page, terminal colours by role; CSS modules in plugin builds. - App kit: startServer gains web and tui; startApp renamed startServer, exportAddress/importAddress renamed exportData/importData and export no longer stops the worker; ephemeral sessions end with their client's last link. - Examples 56-web, 57-tui, 58-themes, 59-chat.
36 lines
1.4 KiB
TypeScript
36 lines
1.4 KiB
TypeScript
// Tests of the launcher's credentials (slice 11 §4; fix round 1, Fable M2): a pairing answer the server sends is shown
|
|
// on the real terminal only when it is a plain code; anything else (an escape sequence) fails the pairing.
|
|
|
|
import { createServer } from "node:http";
|
|
import { describe, expect, it } from "vitest";
|
|
import { tokenOf } from "../../../src/next-node/tui/credentials.ts";
|
|
|
|
/** A server answering every pairing request with `answer`. */
|
|
async function pairingServer(answer: unknown): Promise<{ url: URL; close(): void }> {
|
|
const server = createServer((_request, response) => {
|
|
response.writeHead(200, { "content-type": "application/json" });
|
|
response.end(JSON.stringify(answer));
|
|
});
|
|
await new Promise<void>((resolve) => server.listen(0, "127.0.0.1", resolve));
|
|
const { port } = server.address() as { port: number };
|
|
return { url: new URL(`http://127.0.0.1:${port}`), close: () => server.close() };
|
|
}
|
|
|
|
describe("pairing", () => {
|
|
it("refuses a code that is no plain code, showing nothing", async () => {
|
|
for (const code of ["\x1b]52;c;Y3VybA==\x07", "AB\r\nCD", "x".repeat(40), 7]) {
|
|
const server = await pairingServer({ code, poll: "p" });
|
|
const said: string[] = [];
|
|
await expect(
|
|
tokenOf(
|
|
{ kind: "pairing", label: "t" },
|
|
server.url,
|
|
(line) => said.push(line),
|
|
new AbortController().signal,
|
|
),
|
|
).rejects.toThrow("pairing answer is malformed");
|
|
expect(said).toEqual([]);
|
|
server.close();
|
|
}
|
|
});
|
|
});
|