@termfleet/terminal 0.1.2 → 0.1.3

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/README.md CHANGED
@@ -30,6 +30,12 @@ claim or terminate unmarked sessions. Terminal attachment is intentionally
30
30
  separate from session termination: disposing a viewer only detaches its
31
31
  ephemeral PTY client and releases all handles.
32
32
 
33
+ `@termfleet/terminal/local-terminal.js` opens a structured command in the
34
+ user's macOS Terminal without constructing AppleScript from caller data. Every
35
+ program, argument, working directory, and environment value is POSIX-quoted
36
+ before the fixed AppleScript receives it as a single argv value. Unsupported
37
+ platforms fail honestly instead of guessing a terminal emulator.
38
+
33
39
  `createSession` accepts a structured `{ program, arguments }` command plus an
34
40
  environment map. Arguments are passed directly without constructing a shell
35
41
  command, and the credential bootstrap deletes itself before the command starts.
@@ -0,0 +1,13 @@
1
+ export interface LocalTerminalCommand {
2
+ program: string;
3
+ arguments?: readonly string[];
4
+ cwd?: string;
5
+ env?: Readonly<Record<string, string>>;
6
+ }
7
+ export type LocalTerminalRunner = (program: string, arguments_: readonly string[]) => Promise<void>;
8
+ export interface OpenLocalTerminalOptions {
9
+ platform?: NodeJS.Platform;
10
+ runner?: LocalTerminalRunner;
11
+ }
12
+ export declare function terminalShellCommand(command: LocalTerminalCommand): string;
13
+ export declare function openLocalTerminal(command: LocalTerminalCommand, options?: OpenLocalTerminalOptions): Promise<void>;
@@ -0,0 +1,39 @@
1
+ import { runAsync } from "./internal/exec.js";
2
+ const APPLE_SCRIPT = [
3
+ "on run argv",
4
+ 'tell application "Terminal"',
5
+ "activate",
6
+ "do script (item 1 of argv)",
7
+ "end tell",
8
+ "end run",
9
+ ].join("\n");
10
+ export function terminalShellCommand(command) {
11
+ if (!command.program)
12
+ throw new Error("A terminal command program is required.");
13
+ const environment = Object.entries(command.env ?? {}).map(([name, value]) => {
14
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {
15
+ throw new Error(`Invalid terminal environment variable name: ${JSON.stringify(name)}.`);
16
+ }
17
+ return `${name}=${value}`;
18
+ });
19
+ const launch = [
20
+ ...(environment.length ? ["env", ...environment] : []),
21
+ command.program,
22
+ ...(command.arguments ?? []),
23
+ ].map(shellQuote).join(" ");
24
+ return command.cwd ? `cd ${shellQuote(command.cwd)} && exec ${launch}` : `exec ${launch}`;
25
+ }
26
+ export async function openLocalTerminal(command, options = {}) {
27
+ const platform = options.platform ?? process.platform;
28
+ if (platform !== "darwin") {
29
+ throw new Error(`Opening a local terminal is not supported on ${platform}.`);
30
+ }
31
+ const runner = options.runner ?? defaultRunner;
32
+ await runner("osascript", ["-e", APPLE_SCRIPT, terminalShellCommand(command)]);
33
+ }
34
+ async function defaultRunner(program, arguments_) {
35
+ await runAsync(program, [...arguments_], { timeoutMs: 5_000 });
36
+ }
37
+ function shellQuote(value) {
38
+ return `'${value.replaceAll("'", `'"'"'`)}'`;
39
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@termfleet/terminal",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Framework-neutral terminal transport and durable tmux session substrate extracted from Termfleet.",
5
5
  "keywords": [
6
6
  "pty",
@@ -32,6 +32,11 @@
32
32
  "development": "./src/client.ts",
33
33
  "default": "./dist/client.js"
34
34
  },
35
+ "./local-terminal.js": {
36
+ "types": "./dist/local-terminal.d.ts",
37
+ "development": "./src/local-terminal.ts",
38
+ "default": "./dist/local-terminal.js"
39
+ },
35
40
  "./tmux-stream.js": {
36
41
  "types": "./dist/tmux-stream.d.ts",
37
42
  "development": "./src/tmux-stream.ts",
@@ -48,7 +53,8 @@
48
53
  ],
49
54
  "scripts": {
50
55
  "build": "tsc -p tsconfig.json",
51
- "prepack": "tsc -p tsconfig.json"
56
+ "test": "npm run build && node --test test/*.test.mjs",
57
+ "prepack": "npm test"
52
58
  },
53
59
  "engines": {
54
60
  "node": ">=20"