chore: pin dependencies and use native TypeScript

This commit is contained in:
Mario Zechner
2026-05-20 12:44:04 +02:00
parent 849f9d9c5a
commit 2e02c74dcb
260 changed files with 862 additions and 897 deletions

View File

@@ -7,7 +7,7 @@
"scripts": {
"clean": "shx rm -rf dist",
"build": "tsgo -p tsconfig.build.json",
"test": "node --test --import tsx test/*.test.ts",
"test": "node --test test/*.test.ts",
"prepublishOnly": "npm run clean && npm run build"
},
"files": [
@@ -35,15 +35,15 @@
},
"types": "./dist/index.d.ts",
"dependencies": {
"get-east-asian-width": "^1.3.0",
"marked": "^15.0.12"
"get-east-asian-width": "1.6.0",
"marked": "15.0.12"
},
"optionalDependencies": {
"koffi": "^2.9.0"
"koffi": "2.16.2"
},
"devDependencies": {
"@xterm/headless": "^5.5.0",
"@xterm/xterm": "^5.5.0",
"chalk": "^5.5.0"
"@xterm/headless": "5.5.0",
"@xterm/xterm": "5.5.0",
"chalk": "5.6.2"
}
}

View File

@@ -4,7 +4,7 @@ import { mkdirSync, mkdtempSync, rmSync, symlinkSync, writeFileSync } from "node
import { tmpdir } from "node:os";
import { dirname, join } from "node:path";
import { afterEach, beforeEach, describe, it, test } from "node:test";
import { CombinedAutocompleteProvider } from "../src/autocomplete.js";
import { CombinedAutocompleteProvider } from "../src/autocomplete.ts";
const resolveFdPath = (): string | null => {
const command = process.platform === "win32" ? "where" : "which";

View File

@@ -56,7 +56,7 @@ describe("Bug regression: isImageLine() crash with image escape sequences", () =
});
it("new implementation returns true correctly", async () => {
const { isImageLine } = await import("../src/terminal-image.js");
const { isImageLine } = await import("../src/terminal-image.ts");
// Line containing image escape sequence with text before it
const lineWithImageSequence =
@@ -68,7 +68,7 @@ describe("Bug regression: isImageLine() crash with image escape sequences", () =
});
it("new implementation detects Kitty sequences in any position", async () => {
const { isImageLine } = await import("../src/terminal-image.js");
const { isImageLine } = await import("../src/terminal-image.ts");
const scenarios = [
"At start: \x1b_Ga=T,f=100,data...\x1b\\",
@@ -85,7 +85,7 @@ describe("Bug regression: isImageLine() crash with image escape sequences", () =
});
it("new implementation detects iTerm2 sequences in any position", async () => {
const { isImageLine } = await import("../src/terminal-image.js");
const { isImageLine } = await import("../src/terminal-image.ts");
const scenarios = [
"At start: \x1b]1337;File=size=100,100:base64...\x07",
@@ -121,7 +121,7 @@ describe("Bug regression: isImageLine() crash with image escape sequences", () =
*/
it("detects image sequences in read tool output", async () => {
const { isImageLine } = await import("../src/terminal-image.js");
const { isImageLine } = await import("../src/terminal-image.ts");
// Simulate output when read tool processes an image
// The line might have text from the read result plus the image escape sequence
@@ -131,7 +131,7 @@ describe("Bug regression: isImageLine() crash with image escape sequences", () =
});
it("detects Kitty sequences from Image component", async () => {
const { isImageLine } = await import("../src/terminal-image.js");
const { isImageLine } = await import("../src/terminal-image.ts");
// Kitty image component creates multi-line output with escape sequences
const kittyLine = "\x1b_Ga=T,f=100,t=f,d=base64data...\x1b\\\x1b_Gm=i=1;\x1b\\";
@@ -140,7 +140,7 @@ describe("Bug regression: isImageLine() crash with image escape sequences", () =
});
it("handles ANSI codes before image sequences", async () => {
const { isImageLine } = await import("../src/terminal-image.js");
const { isImageLine } = await import("../src/terminal-image.ts");
// Line might have styling (error, warning, etc.) before image data
const lines = [
@@ -161,7 +161,7 @@ describe("Bug regression: isImageLine() crash with image escape sequences", () =
describe("Crash scenario simulation", () => {
it("does NOT crash on very long lines with image sequences", async () => {
const { isImageLine } = await import("../src/terminal-image.js");
const { isImageLine } = await import("../src/terminal-image.ts");
/**
* Simulate the exact crash scenario:
@@ -190,7 +190,7 @@ describe("Bug regression: isImageLine() crash with image escape sequences", () =
});
it("handles lines exactly matching crash log dimensions", async () => {
const { isImageLine } = await import("../src/terminal-image.js");
const { isImageLine } = await import("../src/terminal-image.ts");
/**
* Crash log showed: line 58649 chars wide, terminal width 115
@@ -211,7 +211,7 @@ describe("Bug regression: isImageLine() crash with image escape sequences", () =
describe("Negative cases: Don't false positive", () => {
it("does not detect images in regular long text", async () => {
const { isImageLine } = await import("../src/terminal-image.js");
const { isImageLine } = await import("../src/terminal-image.ts");
// Very long line WITHOUT image sequences
const longText = "A".repeat(100000);
@@ -220,7 +220,7 @@ describe("Bug regression: isImageLine() crash with image escape sequences", () =
});
it("does not detect images in lines with file paths", async () => {
const { isImageLine } = await import("../src/terminal-image.js");
const { isImageLine } = await import("../src/terminal-image.ts");
const filePaths = [
"/path/to/1337/image.jpg",

View File

@@ -3,14 +3,14 @@
*/
import chalk from "chalk";
import { CombinedAutocompleteProvider } from "../src/autocomplete.js";
import { Editor } from "../src/components/editor.js";
import { Loader } from "../src/components/loader.js";
import { Markdown } from "../src/components/markdown.js";
import { Text } from "../src/components/text.js";
import { ProcessTerminal } from "../src/terminal.js";
import { TUI } from "../src/tui.js";
import { defaultEditorTheme, defaultMarkdownTheme } from "./test-themes.js";
import { CombinedAutocompleteProvider } from "../src/autocomplete.ts";
import { Editor } from "../src/components/editor.ts";
import { Loader } from "../src/components/loader.ts";
import { Markdown } from "../src/components/markdown.ts";
import { Text } from "../src/components/text.ts";
import { ProcessTerminal } from "../src/terminal.ts";
import { TUI } from "../src/tui.ts";
import { defaultEditorTheme, defaultMarkdownTheme } from "./test-themes.ts";
// Create terminal
const terminal = new ProcessTerminal();

View File

@@ -1,12 +1,12 @@
import assert from "node:assert";
import { describe, it } from "node:test";
import { stripVTControlCharacters } from "node:util";
import { type AutocompleteProvider, CombinedAutocompleteProvider } from "../src/autocomplete.js";
import { Editor, wordWrapLine } from "../src/components/editor.js";
import { TUI } from "../src/tui.js";
import { visibleWidth } from "../src/utils.js";
import { defaultEditorTheme } from "./test-themes.js";
import { VirtualTerminal } from "./virtual-terminal.js";
import { type AutocompleteProvider, CombinedAutocompleteProvider } from "../src/autocomplete.ts";
import { Editor, wordWrapLine } from "../src/components/editor.ts";
import { TUI } from "../src/tui.ts";
import { visibleWidth } from "../src/utils.ts";
import { defaultEditorTheme } from "./test-themes.ts";
import { VirtualTerminal } from "./virtual-terminal.ts";
/** Create a TUI with a virtual terminal for testing */
function createTestTUI(cols = 80, rows = 24): TUI {

View File

@@ -1,6 +1,6 @@
import assert from "node:assert";
import { describe, it } from "node:test";
import { fuzzyFilter, fuzzyMatch } from "../src/fuzzy.js";
import { fuzzyFilter, fuzzyMatch } from "../src/fuzzy.ts";
describe("fuzzyMatch", () => {
it("empty query matches everything with score 0", () => {

View File

@@ -1,10 +1,10 @@
import { readFileSync } from "fs";
import { Image } from "../src/components/image.js";
import { Spacer } from "../src/components/spacer.js";
import { Text } from "../src/components/text.js";
import { ProcessTerminal } from "../src/terminal.js";
import { getCapabilities, getImageDimensions } from "../src/terminal-image.js";
import { TUI } from "../src/tui.js";
import { Image } from "../src/components/image.ts";
import { Spacer } from "../src/components/spacer.ts";
import { Text } from "../src/components/text.ts";
import { ProcessTerminal } from "../src/terminal.ts";
import { getCapabilities, getImageDimensions } from "../src/terminal-image.ts";
import { TUI } from "../src/tui.ts";
const testImagePath = process.argv[2] || "/tmp/test-image.png";

View File

@@ -1,7 +1,7 @@
import assert from "node:assert";
import { describe, it } from "node:test";
import { Input } from "../src/components/input.js";
import { visibleWidth } from "../src/utils.js";
import { Input } from "../src/components/input.ts";
import { visibleWidth } from "../src/utils.ts";
describe("Input component", () => {
it("submits value including backslash on Enter", () => {

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env node
import { matchesKey } from "../src/keys.js";
import { ProcessTerminal } from "../src/terminal.js";
import { type Component, TUI } from "../src/tui.js";
import { matchesKey } from "../src/keys.ts";
import { ProcessTerminal } from "../src/terminal.ts";
import { type Component, TUI } from "../src/tui.ts";
/**
* Simple key code logger component

View File

@@ -1,6 +1,6 @@
import assert from "node:assert";
import { describe, it } from "node:test";
import { KeybindingsManager, TUI_KEYBINDINGS } from "../src/keybindings.js";
import { KeybindingsManager, TUI_KEYBINDINGS } from "../src/keybindings.ts";
describe("KeybindingsManager", () => {
it("does not evict selector confirm when input submit is rebound", () => {

View File

@@ -11,7 +11,7 @@ import {
matchesKey,
parseKey,
setKittyProtocolActive,
} from "../src/keys.js";
} from "../src/keys.ts";
function withEnv(name: string, value: string | undefined, fn: () => void): void {
const previous = process.env[name];

View File

@@ -2,11 +2,11 @@ import assert from "node:assert";
import { afterEach, describe, it } from "node:test";
import type { Terminal as XtermTerminalType } from "@xterm/headless";
import { Chalk } from "chalk";
import { Markdown } from "../src/components/markdown.js";
import { resetCapabilitiesCache, setCapabilities } from "../src/terminal-image.js";
import { type Component, TUI } from "../src/tui.js";
import { defaultMarkdownTheme } from "./test-themes.js";
import { VirtualTerminal } from "./virtual-terminal.js";
import { Markdown } from "../src/components/markdown.ts";
import { resetCapabilitiesCache, setCapabilities } from "../src/terminal-image.ts";
import { type Component, TUI } from "../src/tui.ts";
import { defaultMarkdownTheme } from "./test-themes.ts";
import { VirtualTerminal } from "./virtual-terminal.ts";
// Force full color in CI so ANSI assertions are deterministic
const chalk = new Chalk({ level: 3 });

View File

@@ -1,8 +1,8 @@
import assert from "node:assert";
import { describe, it } from "node:test";
import type { Component, Focusable } from "../src/tui.js";
import { TUI } from "../src/tui.js";
import { VirtualTerminal } from "./virtual-terminal.js";
import type { Component, Focusable } from "../src/tui.ts";
import { TUI } from "../src/tui.ts";
import { VirtualTerminal } from "./virtual-terminal.ts";
class StaticOverlay implements Component {
private lines: string[];

View File

@@ -1,8 +1,8 @@
import assert from "node:assert";
import { describe, it } from "node:test";
import type { Component } from "../src/tui.js";
import { TUI } from "../src/tui.js";
import { VirtualTerminal } from "./virtual-terminal.js";
import type { Component } from "../src/tui.ts";
import { TUI } from "../src/tui.ts";
import { VirtualTerminal } from "./virtual-terminal.ts";
class StaticOverlay implements Component {
private lines: string[];

View File

@@ -1,7 +1,7 @@
import assert from "node:assert";
import { describe, it } from "node:test";
import { type Component, TUI } from "../src/tui.js";
import { VirtualTerminal } from "./virtual-terminal.js";
import { type Component, TUI } from "../src/tui.ts";
import { VirtualTerminal } from "./virtual-terminal.ts";
class SimpleContent implements Component {
private lines: string[];

View File

@@ -1,6 +1,6 @@
import assert from "node:assert";
import { describe, it } from "node:test";
import { visibleWidth, wrapTextWithAnsi } from "../src/utils.js";
import { visibleWidth, wrapTextWithAnsi } from "../src/utils.ts";
describe("regional indicator width regression", () => {
it("treats partial flag grapheme as full-width to avoid streaming render drift", () => {

View File

@@ -1,7 +1,7 @@
import assert from "node:assert";
import { describe, it } from "node:test";
import { SelectList } from "../src/components/select-list.js";
import { visibleWidth } from "../src/utils.js";
import { SelectList } from "../src/components/select-list.ts";
import { visibleWidth } from "../src/utils.ts";
const testTheme = {
selectedPrefix: (text: string) => text,

View File

@@ -7,7 +7,7 @@
import assert from "node:assert";
import { beforeEach, describe, it } from "node:test";
import { StdinBuffer } from "../src/stdin-buffer.js";
import { StdinBuffer } from "../src/stdin-buffer.ts";
describe("StdinBuffer", () => {
let buffer: StdinBuffer;

View File

@@ -4,7 +4,7 @@
import assert from "node:assert";
import { describe, it } from "node:test";
import { Image } from "../src/components/image.js";
import { Image } from "../src/components/image.ts";
import {
deleteAllKittyImages,
deleteKittyImage,
@@ -16,7 +16,7 @@ import {
resetCapabilitiesCache,
setCapabilities,
setCellDimensions,
} from "../src/terminal-image.js";
} from "../src/terminal-image.ts";
const ENV_KEYS = [
"TERM",

View File

@@ -1,6 +1,6 @@
import assert from "node:assert";
import { describe, it } from "node:test";
import { ProcessTerminal } from "../src/terminal.js";
import { ProcessTerminal } from "../src/terminal.ts";
describe("ProcessTerminal dimensions", () => {
it("falls back to COLUMNS and LINES before default dimensions", () => {

View File

@@ -3,7 +3,7 @@
*/
import { Chalk } from "chalk";
import type { EditorTheme, MarkdownTheme, SelectListTheme } from "../src/index.js";
import type { EditorTheme, MarkdownTheme, SelectListTheme } from "../src/index.ts";
const chalk = new Chalk({ level: 3 });

View File

@@ -1,6 +1,6 @@
import assert from "node:assert";
import { describe, it } from "node:test";
import { normalizeTerminalOutput, truncateToWidth, visibleWidth } from "../src/utils.js";
import { normalizeTerminalOutput, truncateToWidth, visibleWidth } from "../src/utils.ts";
describe("truncateToWidth", () => {
it("keeps output within width for very large unicode input", () => {

View File

@@ -1,8 +1,8 @@
import assert from "node:assert";
import { describe, it } from "node:test";
import { Chalk } from "chalk";
import { TruncatedText } from "../src/components/truncated-text.js";
import { visibleWidth } from "../src/utils.js";
import { TruncatedText } from "../src/components/truncated-text.ts";
import { visibleWidth } from "../src/utils.ts";
// Force full color in CI so ANSI assertions are deterministic
const chalk = new Chalk({ level: 3 });

View File

@@ -1,8 +1,8 @@
import assert from "node:assert";
import { describe, it } from "node:test";
import { getCellDimensions, resetCapabilitiesCache, setCellDimensions } from "../src/terminal-image.js";
import { type Component, TUI } from "../src/tui.js";
import { VirtualTerminal } from "./virtual-terminal.js";
import { getCellDimensions, resetCapabilitiesCache, setCellDimensions } from "../src/terminal-image.ts";
import { type Component, TUI } from "../src/tui.ts";
import { VirtualTerminal } from "./virtual-terminal.ts";
class InputRecorder implements Component {
readonly inputs: string[] = [];

View File

@@ -1,8 +1,8 @@
import assert from "node:assert";
import { describe, it } from "node:test";
import type { Terminal as XtermTerminalType } from "@xterm/headless";
import { type Component, TUI } from "../src/tui.js";
import { VirtualTerminal } from "./virtual-terminal.js";
import { type Component, TUI } from "../src/tui.ts";
import { VirtualTerminal } from "./virtual-terminal.ts";
class StaticLines implements Component {
private readonly lines: string[];

View File

@@ -1,9 +1,9 @@
import assert from "node:assert";
import { describe, it } from "node:test";
import type { Terminal as XtermTerminalType } from "@xterm/headless";
import { deleteKittyImage, encodeKitty } from "../src/terminal-image.js";
import { type Component, TUI } from "../src/tui.js";
import { VirtualTerminal } from "./virtual-terminal.js";
import { deleteKittyImage, encodeKitty } from "../src/terminal-image.ts";
import { type Component, TUI } from "../src/tui.ts";
import { VirtualTerminal } from "./virtual-terminal.ts";
class TestComponent implements Component {
lines: string[] = [];

View File

@@ -17,8 +17,8 @@
* - When content exceeds the viewport and new lines arrive after a tool-call pause,
* some earlier PRE-TOOL lines near the bottom are overwritten by POST-TOOL lines.
*/
import { ProcessTerminal } from "../src/terminal.js";
import { type Component, TUI } from "../src/tui.js";
import { ProcessTerminal } from "../src/terminal.ts";
import { type Component, TUI } from "../src/tui.ts";
const sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));

View File

@@ -1,6 +1,6 @@
import type { Terminal as XtermTerminalType } from "@xterm/headless";
import xterm from "@xterm/headless";
import type { Terminal } from "../src/terminal.js";
import type { Terminal } from "../src/terminal.ts";
// Extract Terminal class from the module
const XtermTerminal = xterm.Terminal;

View File

@@ -1,6 +1,6 @@
import assert from "node:assert";
import { describe, it } from "node:test";
import { visibleWidth, wrapTextWithAnsi } from "../src/utils.js";
import { visibleWidth, wrapTextWithAnsi } from "../src/utils.ts";
describe("wrapTextWithAnsi", () => {
describe("underline styling", () => {