@termlink/terminal 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +12 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/pty.d.ts +19 -0
- package/dist/pty.d.ts.map +1 -0
- package/dist/pty.js +36 -0
- package/dist/pty.js.map +1 -0
- package/dist/screen.d.ts +22 -0
- package/dist/screen.d.ts.map +1 -0
- package/dist/screen.js +50 -0
- package/dist/screen.js.map +1 -0
- package/dist/shell.d.ts +11 -0
- package/dist/shell.d.ts.map +1 -0
- package/dist/shell.js +37 -0
- package/dist/shell.js.map +1 -0
- package/dist/terminal.d.ts +42 -0
- package/dist/terminal.d.ts.map +1 -0
- package/dist/terminal.js +132 -0
- package/dist/terminal.js.map +1 -0
- package/package.json +42 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bert Shim
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# @termlink/terminal
|
|
2
|
+
|
|
3
|
+
A shell in a PTY with a headless screen for reconnects. `createTerminal()` starts the
|
|
4
|
+
user's shell (PowerShell on Windows, `$SHELL` elsewhere), streams its bytes, keeps a copy
|
|
5
|
+
of the screen and scrollback with `@xterm/headless`, and can hand a late client the
|
|
6
|
+
current screen as bytes to write after a reset.
|
|
7
|
+
|
|
8
|
+
The PTY comes from `@lydell/node-pty`, a prebuilt binary per platform installed as an
|
|
9
|
+
optional dependency: nothing is compiled on the user's machine. On a platform without one,
|
|
10
|
+
`ptyStatus()` says so and `createTerminal()` throws `PtyUnavailableError`.
|
|
11
|
+
|
|
12
|
+
Used by `@termlink/cli`. Knows nothing about hosts, relays or clients.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createTerminal, terminalEnv, type Terminal, type TerminalExit, type TerminalOptions } from "./terminal.js";
|
|
2
|
+
export { PtyUnavailableError, ptyStatus } from "./pty.js";
|
|
3
|
+
export { defaultShell, type ShellCommand } from "./shell.js";
|
|
4
|
+
export { Screen } from "./screen.js";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,KAAK,QAAQ,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AACpH,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,WAAW,EAA0D,MAAM,eAAe,CAAC;AACpH,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAqB,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/pty.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type * as NodePty from "@lydell/node-pty";
|
|
2
|
+
export type PtyModule = typeof NodePty;
|
|
3
|
+
export type { IPty } from "@lydell/node-pty";
|
|
4
|
+
/** The PTY binary for this platform is missing. The host runs without terminals then. */
|
|
5
|
+
export declare class PtyUnavailableError extends Error {
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Loads @lydell/node-pty once. It ships a prebuilt binary per platform as an optional
|
|
10
|
+
* dependency, so nothing is compiled on the user's machine; on an unsupported platform
|
|
11
|
+
* (or an install that skipped optional dependencies) the require fails and the error
|
|
12
|
+
* says so.
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadPty(): PtyModule;
|
|
15
|
+
export declare function ptyStatus(): {
|
|
16
|
+
available: boolean;
|
|
17
|
+
detail: string | null;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=pty.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pty.d.ts","sourceRoot":"","sources":["../src/pty.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAEjD,MAAM,MAAM,SAAS,GAAG,OAAO,OAAO,CAAC;AACvC,YAAY,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,yFAAyF;AACzF,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAKD;;;;;GAKG;AACH,wBAAgB,OAAO,IAAI,SAAS,CAInC;AAED,wBAAgB,SAAS,IAAI;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAGzE"}
|
package/dist/pty.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
/** The PTY binary for this platform is missing. The host runs without terminals then. */
|
|
3
|
+
export class PtyUnavailableError extends Error {
|
|
4
|
+
constructor(message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "PtyUnavailableError";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
10
|
+
let loaded = null;
|
|
11
|
+
/**
|
|
12
|
+
* Loads @lydell/node-pty once. It ships a prebuilt binary per platform as an optional
|
|
13
|
+
* dependency, so nothing is compiled on the user's machine; on an unsupported platform
|
|
14
|
+
* (or an install that skipped optional dependencies) the require fails and the error
|
|
15
|
+
* says so.
|
|
16
|
+
*/
|
|
17
|
+
export function loadPty() {
|
|
18
|
+
loaded ??= tryLoad();
|
|
19
|
+
if ("error" in loaded)
|
|
20
|
+
throw new PtyUnavailableError(loaded.error);
|
|
21
|
+
return loaded.module;
|
|
22
|
+
}
|
|
23
|
+
export function ptyStatus() {
|
|
24
|
+
loaded ??= tryLoad();
|
|
25
|
+
return "error" in loaded ? { available: false, detail: loaded.error } : { available: true, detail: null };
|
|
26
|
+
}
|
|
27
|
+
function tryLoad() {
|
|
28
|
+
try {
|
|
29
|
+
return { module: require("@lydell/node-pty") };
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
const message = err instanceof Error ? err.message.split("\n")[0] ?? err.message : String(err);
|
|
33
|
+
return { error: `terminal support is not available on ${process.platform}-${process.arch}: ${message}` };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=pty.js.map
|
package/dist/pty.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pty.js","sourceRoot":"","sources":["../src/pty.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAM5C,yFAAyF;AACzF,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,IAAI,MAAM,GAAqD,IAAI,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,UAAU,OAAO;IACrB,MAAM,KAAK,OAAO,EAAE,CAAC;IACrB,IAAI,OAAO,IAAI,MAAM;QAAE,MAAM,IAAI,mBAAmB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACnE,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,MAAM,KAAK,OAAO,EAAE,CAAC;IACrB,OAAO,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAC5G,CAAC;AAED,SAAS,OAAO;IACd,IAAI,CAAC;QACH,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,kBAAkB,CAAc,EAAE,CAAC;IAC9D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC/F,OAAO,EAAE,KAAK,EAAE,wCAAwC,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,EAAE,CAAC;IAC3G,CAAC;AACH,CAAC"}
|
package/dist/screen.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A headless copy of what the user's terminal shows. Every byte the shell writes goes
|
|
3
|
+
* through here too, so a client that attaches later can be given the current screen
|
|
4
|
+
* and scrollback instead of nothing. Pure JavaScript; the same on every platform.
|
|
5
|
+
*/
|
|
6
|
+
export declare class Screen {
|
|
7
|
+
#private;
|
|
8
|
+
constructor(cols: number, rows: number, scrollback: number);
|
|
9
|
+
get cols(): number;
|
|
10
|
+
get rows(): number;
|
|
11
|
+
write(data: string): void;
|
|
12
|
+
resize(cols: number, rows: number): void;
|
|
13
|
+
/** Waits for everything written so far to be parsed. */
|
|
14
|
+
flush(): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* The screen and scrollback as bytes a terminal can write after a reset to look the
|
|
17
|
+
* same: text, colors, cursor position.
|
|
18
|
+
*/
|
|
19
|
+
snapshot(): Promise<string>;
|
|
20
|
+
dispose(): void;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=screen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../src/screen.ts"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,qBAAa,MAAM;;IAKjB,YAAY,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAKzD;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAExB;IAED,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAEvC;IAED,wDAAwD;IACxD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAErB;IAED;;;OAGG;IACG,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,CAGhC;IAED,OAAO,IAAI,IAAI,CAEd;CACF"}
|
package/dist/screen.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
// Both are CommonJS bundles; a plain require works everywhere the ESM named-export
|
|
3
|
+
// detection might not.
|
|
4
|
+
const require = createRequire(import.meta.url);
|
|
5
|
+
const { Terminal: HeadlessTerminal } = require("@xterm/headless");
|
|
6
|
+
const { SerializeAddon } = require("@xterm/addon-serialize");
|
|
7
|
+
/**
|
|
8
|
+
* A headless copy of what the user's terminal shows. Every byte the shell writes goes
|
|
9
|
+
* through here too, so a client that attaches later can be given the current screen
|
|
10
|
+
* and scrollback instead of nothing. Pure JavaScript; the same on every platform.
|
|
11
|
+
*/
|
|
12
|
+
export class Screen {
|
|
13
|
+
#terminal;
|
|
14
|
+
#serializer;
|
|
15
|
+
#scrollback;
|
|
16
|
+
constructor(cols, rows, scrollback) {
|
|
17
|
+
this.#scrollback = scrollback;
|
|
18
|
+
this.#terminal = new HeadlessTerminal({ cols, rows, scrollback, allowProposedApi: true });
|
|
19
|
+
this.#serializer = new SerializeAddon();
|
|
20
|
+
this.#terminal.loadAddon(this.#serializer);
|
|
21
|
+
}
|
|
22
|
+
get cols() {
|
|
23
|
+
return this.#terminal.cols;
|
|
24
|
+
}
|
|
25
|
+
get rows() {
|
|
26
|
+
return this.#terminal.rows;
|
|
27
|
+
}
|
|
28
|
+
write(data) {
|
|
29
|
+
this.#terminal.write(data);
|
|
30
|
+
}
|
|
31
|
+
resize(cols, rows) {
|
|
32
|
+
this.#terminal.resize(cols, rows);
|
|
33
|
+
}
|
|
34
|
+
/** Waits for everything written so far to be parsed. */
|
|
35
|
+
flush() {
|
|
36
|
+
return new Promise((resolve) => this.#terminal.write("", resolve));
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The screen and scrollback as bytes a terminal can write after a reset to look the
|
|
40
|
+
* same: text, colors, cursor position.
|
|
41
|
+
*/
|
|
42
|
+
async snapshot() {
|
|
43
|
+
await this.flush();
|
|
44
|
+
return this.#serializer.serialize({ scrollback: this.#scrollback });
|
|
45
|
+
}
|
|
46
|
+
dispose() {
|
|
47
|
+
this.#terminal.dispose();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=screen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screen.js","sourceRoot":"","sources":["../src/screen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,mFAAmF;AACnF,uBAAuB;AACvB,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAqC,CAAC;AACtG,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,wBAAwB,CAA4C,CAAC;AAExG;;;;GAIG;AACH,MAAM,OAAO,MAAM;IACR,SAAS,CAAwC;IACjD,WAAW,CAAsC;IACjD,WAAW,CAAS;IAE7B,YAAY,IAAY,EAAE,IAAY,EAAE,UAAkB;QACxD,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;QAC9B,IAAI,CAAC,SAAS,GAAG,IAAI,gBAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1F,IAAI,CAAC,WAAW,GAAG,IAAI,cAAc,EAAE,CAAC;QACxC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;IAC7B,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,IAAY;QAChB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,CAAC,IAAY,EAAE,IAAY;QAC/B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,wDAAwD;IACxD,KAAK;QACH,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;IACrE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,QAAQ;QACZ,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,OAAO;QACL,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;CACF"}
|
package/dist/shell.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface ShellCommand {
|
|
2
|
+
file: string;
|
|
3
|
+
args: string[];
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* The shell a terminal session runs when none is configured: like an ssh login, the
|
|
7
|
+
* user's own shell. Windows prefers PowerShell 7 (pwsh), then Windows PowerShell,
|
|
8
|
+
* then cmd. Elsewhere $SHELL, then bash, then sh, as a login shell.
|
|
9
|
+
*/
|
|
10
|
+
export declare function defaultShell(platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv): ShellCommand;
|
|
11
|
+
//# sourceMappingURL=shell.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../src/shell.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,kBAAmB,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,YAAY,CAe5G"}
|
package/dist/shell.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* The shell a terminal session runs when none is configured: like an ssh login, the
|
|
5
|
+
* user's own shell. Windows prefers PowerShell 7 (pwsh), then Windows PowerShell,
|
|
6
|
+
* then cmd. Elsewhere $SHELL, then bash, then sh, as a login shell.
|
|
7
|
+
*/
|
|
8
|
+
export function defaultShell(platform = process.platform, env = process.env) {
|
|
9
|
+
if (platform === "win32") {
|
|
10
|
+
const pwsh = findOnPath("pwsh.exe", env);
|
|
11
|
+
if (pwsh)
|
|
12
|
+
return { file: pwsh, args: ["-NoLogo"] };
|
|
13
|
+
const system = env.SystemRoot ?? env.windir ?? "C:\\Windows";
|
|
14
|
+
const powershell = path.join(system, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
|
|
15
|
+
if (existsSync(powershell))
|
|
16
|
+
return { file: powershell, args: ["-NoLogo"] };
|
|
17
|
+
return { file: path.join(system, "System32", "cmd.exe"), args: [] };
|
|
18
|
+
}
|
|
19
|
+
const own = env.SHELL;
|
|
20
|
+
if (own && existsSync(own))
|
|
21
|
+
return { file: own, args: ["-l"] };
|
|
22
|
+
for (const candidate of ["/bin/bash", "/usr/bin/bash", "/bin/zsh", "/bin/sh"]) {
|
|
23
|
+
if (existsSync(candidate))
|
|
24
|
+
return { file: candidate, args: ["-l"] };
|
|
25
|
+
}
|
|
26
|
+
return { file: "sh", args: ["-l"] };
|
|
27
|
+
}
|
|
28
|
+
function findOnPath(name, env) {
|
|
29
|
+
const entries = (env.PATH ?? env.Path ?? "").split(path.delimiter).filter(Boolean);
|
|
30
|
+
for (const dir of entries) {
|
|
31
|
+
const candidate = path.join(dir, name);
|
|
32
|
+
if (existsSync(candidate))
|
|
33
|
+
return candidate;
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=shell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell.js","sourceRoot":"","sources":["../src/shell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,WAAW,CAAC;AAO7B;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,EAAE,GAAG,GAAsB,OAAO,CAAC,GAAG;IAC5F,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACzC,IAAI,IAAI;YAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;QACnD,MAAM,MAAM,GAAG,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,MAAM,IAAI,aAAa,CAAC;QAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC;QAChG,IAAI,UAAU,CAAC,UAAU,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3E,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IACtE,CAAC;IACD,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC;IACtB,IAAI,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;IAC/D,KAAK,MAAM,SAAS,IAAI,CAAC,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,CAAC;QAC9E,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;IACtE,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;AACtC,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,GAAsB;IACtD,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACnF,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACvC,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;IAC9C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface TerminalOptions {
|
|
2
|
+
/** Shell executable. Defaults to the user's shell (see defaultShell). */
|
|
3
|
+
shell?: string | undefined;
|
|
4
|
+
/** Arguments for the shell. Defaults depend on the shell chosen. */
|
|
5
|
+
args?: string[] | undefined;
|
|
6
|
+
cwd: string;
|
|
7
|
+
/** Added on top of the host process environment. */
|
|
8
|
+
env?: Record<string, string> | undefined;
|
|
9
|
+
cols: number;
|
|
10
|
+
rows: number;
|
|
11
|
+
/** Lines kept above the screen for reconnects. Default 5000. */
|
|
12
|
+
scrollback?: number | undefined;
|
|
13
|
+
}
|
|
14
|
+
export interface TerminalExit {
|
|
15
|
+
exitCode: number;
|
|
16
|
+
signal?: number | undefined;
|
|
17
|
+
}
|
|
18
|
+
export interface Terminal {
|
|
19
|
+
readonly pid: number;
|
|
20
|
+
readonly cols: number;
|
|
21
|
+
readonly rows: number;
|
|
22
|
+
/** Set once the shell has exited. */
|
|
23
|
+
readonly exit: TerminalExit | null;
|
|
24
|
+
/** Keyboard input, pasted text, control bytes such as 0x03 for Ctrl+C. */
|
|
25
|
+
write(data: Uint8Array | string): void;
|
|
26
|
+
resize(cols: number, rows: number): void;
|
|
27
|
+
/** Output as the shell wrote it. */
|
|
28
|
+
onData(listener: (data: Uint8Array) => void): () => void;
|
|
29
|
+
onExit(listener: (exit: TerminalExit) => void): () => void;
|
|
30
|
+
/** The current screen and scrollback as bytes a terminal can write after a reset. */
|
|
31
|
+
snapshot(): Promise<Uint8Array>;
|
|
32
|
+
/** Stops reading from the shell, so it blocks on its next write. For flow control. */
|
|
33
|
+
pause(): void;
|
|
34
|
+
resume(): void;
|
|
35
|
+
/** Ends the shell. onExit follows. */
|
|
36
|
+
kill(): void;
|
|
37
|
+
}
|
|
38
|
+
/** Starts a shell in a PTY. Throws PtyUnavailableError when this platform has no PTY binary. */
|
|
39
|
+
export declare function createTerminal(options: TerminalOptions): Terminal;
|
|
40
|
+
/** What the shell inherits: the host's environment plus what a terminal expects. */
|
|
41
|
+
export declare function terminalEnv(extra?: Record<string, string>, base?: NodeJS.ProcessEnv): Record<string, string>;
|
|
42
|
+
//# sourceMappingURL=terminal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,oDAAoD;IACpD,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IACnC,0EAA0E;IAC1E,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAAC;IACvC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,oCAAoC;IACpC,MAAM,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACzD,MAAM,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC3D,qFAAqF;IACrF,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;IAChC,sFAAsF;IACtF,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,IAAI,IAAI,CAAC;IACf,sCAAsC;IACtC,IAAI,IAAI,IAAI,CAAC;CACd;AAKD,gGAAgG;AAChG,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,QAAQ,CAYjE;AAED,oFAAoF;AACpF,wBAAgB,WAAW,CAAC,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EAAE,IAAI,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAU7H"}
|
package/dist/terminal.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { loadPty } from "./pty.js";
|
|
2
|
+
import { Screen } from "./screen.js";
|
|
3
|
+
import { defaultShell } from "./shell.js";
|
|
4
|
+
const DEFAULT_SCROLLBACK = 5000;
|
|
5
|
+
const encoder = new TextEncoder();
|
|
6
|
+
/** Starts a shell in a PTY. Throws PtyUnavailableError when this platform has no PTY binary. */
|
|
7
|
+
export function createTerminal(options) {
|
|
8
|
+
const pty = loadPty();
|
|
9
|
+
const shell = options.shell ? { file: options.shell, args: options.args ?? [] } : defaultShell();
|
|
10
|
+
const args = options.args ?? shell.args;
|
|
11
|
+
const child = pty.spawn(shell.file, args, {
|
|
12
|
+
name: "xterm-256color",
|
|
13
|
+
cols: options.cols,
|
|
14
|
+
rows: options.rows,
|
|
15
|
+
cwd: options.cwd,
|
|
16
|
+
env: terminalEnv(options.env),
|
|
17
|
+
});
|
|
18
|
+
return new PtyTerminal(child, options.cols, options.rows, options.scrollback ?? DEFAULT_SCROLLBACK);
|
|
19
|
+
}
|
|
20
|
+
/** What the shell inherits: the host's environment plus what a terminal expects. */
|
|
21
|
+
export function terminalEnv(extra = {}, base = process.env) {
|
|
22
|
+
const env = {};
|
|
23
|
+
for (const [key, value] of Object.entries(base))
|
|
24
|
+
if (value !== undefined)
|
|
25
|
+
env[key] = value;
|
|
26
|
+
env.TERM = "xterm-256color";
|
|
27
|
+
env.COLORTERM = "truecolor";
|
|
28
|
+
env.TERM_PROGRAM = "termlink";
|
|
29
|
+
if (process.platform !== "win32" && !env.LANG && !env.LC_ALL && !env.LC_CTYPE) {
|
|
30
|
+
env.LANG = process.platform === "darwin" ? "en_US.UTF-8" : "C.UTF-8";
|
|
31
|
+
}
|
|
32
|
+
return { ...env, ...extra };
|
|
33
|
+
}
|
|
34
|
+
class PtyTerminal {
|
|
35
|
+
pid;
|
|
36
|
+
#pty;
|
|
37
|
+
#screen;
|
|
38
|
+
#decoder = new TextDecoder("utf-8");
|
|
39
|
+
#dataListeners = new Set();
|
|
40
|
+
#exitListeners = new Set();
|
|
41
|
+
#cols;
|
|
42
|
+
#rows;
|
|
43
|
+
#exit = null;
|
|
44
|
+
constructor(pty, cols, rows, scrollback) {
|
|
45
|
+
this.#pty = pty;
|
|
46
|
+
this.pid = pty.pid;
|
|
47
|
+
this.#cols = cols;
|
|
48
|
+
this.#rows = rows;
|
|
49
|
+
this.#screen = new Screen(cols, rows, scrollback);
|
|
50
|
+
pty.onData((text) => {
|
|
51
|
+
this.#screen.write(text);
|
|
52
|
+
const bytes = encoder.encode(text);
|
|
53
|
+
for (const listener of this.#dataListeners)
|
|
54
|
+
listener(bytes);
|
|
55
|
+
});
|
|
56
|
+
pty.onExit((exit) => {
|
|
57
|
+
this.#exit = { exitCode: exit.exitCode, signal: exit.signal };
|
|
58
|
+
// On Windows the ConPTY worker stays referenced after the child exits until the
|
|
59
|
+
// pty is killed, which would keep the host process alive. Harmless elsewhere.
|
|
60
|
+
try {
|
|
61
|
+
pty.kill();
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// Already released.
|
|
65
|
+
}
|
|
66
|
+
for (const listener of this.#exitListeners)
|
|
67
|
+
listener(this.#exit);
|
|
68
|
+
this.#exitListeners.clear();
|
|
69
|
+
this.#dataListeners.clear();
|
|
70
|
+
this.#screen.dispose();
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
get cols() {
|
|
74
|
+
return this.#cols;
|
|
75
|
+
}
|
|
76
|
+
get rows() {
|
|
77
|
+
return this.#rows;
|
|
78
|
+
}
|
|
79
|
+
get exit() {
|
|
80
|
+
return this.#exit;
|
|
81
|
+
}
|
|
82
|
+
write(data) {
|
|
83
|
+
if (this.#exit)
|
|
84
|
+
return;
|
|
85
|
+
// A multi-byte character split across two frames is joined here.
|
|
86
|
+
this.#pty.write(typeof data === "string" ? data : this.#decoder.decode(data, { stream: true }));
|
|
87
|
+
}
|
|
88
|
+
resize(cols, rows) {
|
|
89
|
+
if (this.#exit || (cols === this.#cols && rows === this.#rows))
|
|
90
|
+
return;
|
|
91
|
+
this.#cols = cols;
|
|
92
|
+
this.#rows = rows;
|
|
93
|
+
this.#pty.resize(cols, rows);
|
|
94
|
+
this.#screen.resize(cols, rows);
|
|
95
|
+
}
|
|
96
|
+
onData(listener) {
|
|
97
|
+
this.#dataListeners.add(listener);
|
|
98
|
+
return () => this.#dataListeners.delete(listener);
|
|
99
|
+
}
|
|
100
|
+
onExit(listener) {
|
|
101
|
+
if (this.#exit) {
|
|
102
|
+
listener(this.#exit);
|
|
103
|
+
return () => { };
|
|
104
|
+
}
|
|
105
|
+
this.#exitListeners.add(listener);
|
|
106
|
+
return () => this.#exitListeners.delete(listener);
|
|
107
|
+
}
|
|
108
|
+
async snapshot() {
|
|
109
|
+
if (this.#exit)
|
|
110
|
+
return new Uint8Array();
|
|
111
|
+
return encoder.encode(await this.#screen.snapshot());
|
|
112
|
+
}
|
|
113
|
+
pause() {
|
|
114
|
+
if (!this.#exit)
|
|
115
|
+
this.#pty.pause();
|
|
116
|
+
}
|
|
117
|
+
resume() {
|
|
118
|
+
if (!this.#exit)
|
|
119
|
+
this.#pty.resume();
|
|
120
|
+
}
|
|
121
|
+
kill() {
|
|
122
|
+
if (this.#exit)
|
|
123
|
+
return;
|
|
124
|
+
try {
|
|
125
|
+
this.#pty.kill();
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// Already gone.
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=terminal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal.js","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@termlink/terminal",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A shell in a PTY with a headless screen for reconnects. Knows nothing about hosts or clients.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"source": "./src/index.ts",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc -b",
|
|
18
|
+
"test": "node --conditions=source --import tsx --test \"test/**/*.test.ts\"",
|
|
19
|
+
"prepublishOnly": "tsc -b"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@xterm/addon-serialize": "^0.14.0",
|
|
23
|
+
"@xterm/headless": "^6.0.0"
|
|
24
|
+
},
|
|
25
|
+
"optionalDependencies": {
|
|
26
|
+
"@lydell/node-pty": "^1.2.0-beta.15"
|
|
27
|
+
},
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"author": "Bert Shim",
|
|
30
|
+
"homepage": "https://getterm.link",
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"termlink",
|
|
36
|
+
"pty",
|
|
37
|
+
"terminal"
|
|
38
|
+
],
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=22"
|
|
41
|
+
}
|
|
42
|
+
}
|