raffel 1.1.20 → 1.1.25

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
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Raffel
4
4
 
5
- ### One server. HTTP, WebSocket, gRPC, TCP, UDP — all at once.
5
+ ### One server. HTTP, WebSocket, gRPC, TCP, UDP, SSH — all at once.
6
6
 
7
7
  [![npm version](https://img.shields.io/npm/v/raffel.svg?style=flat-square&color=8b5cf6)](https://www.npmjs.com/package/raffel)
8
8
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-3178C6?style=flat-square&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
@@ -17,7 +17,7 @@
17
17
 
18
18
  Raffel is a TypeScript runtime for building APIs, proxies, and traffic-aware infrastructure in one stack.
19
19
 
20
- - Build HTTP, WebSocket, gRPC, JSON-RPC, GraphQL, TCP, and UDP services with one project.
20
+ - Build HTTP, WebSocket, gRPC, JSON-RPC, GraphQL, TCP, UDP, SMTP, and SSH services with one project.
21
21
  - Run reverse proxy, explicit proxy, CONNECT MITM, SOCKS5/SOCKS5h, and transparent proxy modes.
22
22
  - Export service-mesh style telemetry with `source -> destination -> protocol`, p50/p90/p95, throughput, bytes, and error rates.
23
23
  - Add resilience and policy with rate limit, retry, timeout, circuit breaker, validation, auth/session, filters, and proxy middleware.
@@ -26,7 +26,7 @@ Heavy edge features stay off by default. Telemetry, graph snapshots, Prometheus
26
26
 
27
27
  Need the right guide fast? Use the docs or the built-in MCP tools: `raffel_feature_catalog`, `raffel_proxy_capabilities`, `raffel_get_guide`, and `raffel_search`.
28
28
 
29
- - **Protocols:** [HTTP](https://forattini-dev.github.io/raffel/#/protocols/http), [WebSocket](https://forattini-dev.github.io/raffel/#/protocols/websocket), [gRPC](https://forattini-dev.github.io/raffel/#/protocols/grpc), [UDP](https://forattini-dev.github.io/raffel/#/protocols/udp)
29
+ - **Protocols:** [HTTP](https://forattini-dev.github.io/raffel/#/protocols/http), [WebSocket](https://forattini-dev.github.io/raffel/#/protocols/websocket), [gRPC](https://forattini-dev.github.io/raffel/#/protocols/grpc), [UDP](https://forattini-dev.github.io/raffel/#/protocols/udp), [SMTP](https://forattini-dev.github.io/raffel/#/protocols/smtp), [SSH](https://forattini-dev.github.io/raffel/#/protocols/ssh)
30
30
  - **Proxies:** [Overview](https://forattini-dev.github.io/raffel/#/proxy), [Modes](https://forattini-dev.github.io/raffel/#/proxy/modes), [Routing](https://forattini-dev.github.io/raffel/#/proxy/routing), [Service Mesh](https://forattini-dev.github.io/raffel/#/proxy/service-mesh)
31
31
  - **Observability:** [Flow Metrics](https://forattini-dev.github.io/raffel/#/proxy/flow-metrics), [Observability](https://forattini-dev.github.io/raffel/#/observability), [Tracing](https://forattini-dev.github.io/raffel/#/observability/tracing)
32
32
 
@@ -547,6 +547,58 @@ await proxy.start()
547
547
 
548
548
  ---
549
549
 
550
+ ## SSH Server (TUI over `ssh your.app`)
551
+
552
+ Ship terminal apps the way [terminal.shop](https://terminal.shop) does — users
553
+ type `ssh your.app` and land in a real, rendered TUI. The adapter exposes raw
554
+ streams, parsed key events, resize handling, and an optional TTY-compatible
555
+ bridge for [tuiuiu.js](https://www.npmjs.com/package/tuiuiu.js) so reactive
556
+ components render straight into the SSH session.
557
+
558
+ ```typescript
559
+ import { createSshAdapter } from 'raffel'
560
+
561
+ const ssh = createSshAdapter({
562
+ port: 2222,
563
+ // auth defaults to anonymous (terminal.shop style); add password/publicKey
564
+ // verifiers to mix public and private access in the same adapter.
565
+ onSession: async (session) => {
566
+ session.write(`☕ Hi ${session.user}!\r\n`)
567
+ for await (const key of session.keys) {
568
+ if (key.ctrl && key.name === 'c') break
569
+ session.write(key.str)
570
+ }
571
+ },
572
+ })
573
+
574
+ await ssh.start()
575
+ // Now: ssh -p 2222 anything@localhost
576
+ ```
577
+
578
+ With **tuiuiu.js** plugged in:
579
+
580
+ ```typescript
581
+ import { render, Box, Text } from 'tuiuiu.js'
582
+
583
+ createSshAdapter({
584
+ port: 2222,
585
+ onSession: async (session) => {
586
+ const app = render(
587
+ () => Box({}, Text({ color: 'cyan' }, `Hello, ${session.user}!`)),
588
+ session.tui, // TTY-compatible bridge
589
+ )
590
+ await app.waitUntilExit()
591
+ },
592
+ })
593
+ ```
594
+
595
+ Install peer deps when you use the adapter: `pnpm add ssh2` (required),
596
+ `pnpm add tuiuiu.js` (only for reactive UIs).
597
+
598
+ Full details: [SSH protocol guide](https://forattini-dev.github.io/raffel/#/protocols/ssh).
599
+
600
+ ---
601
+
550
602
  ## Session Store
551
603
 
552
604
  ```typescript
@@ -15,6 +15,10 @@ export { createGrpcAdapter } from './grpc.js';
15
15
  export type { GrpcAdapter, GrpcAdapterOptions, GrpcTlsOptions, GrpcMethodInfo } from './grpc.js';
16
16
  export { createSmtpAdapter, createSmtpClient } from './smtp.js';
17
17
  export type { SmtpAdapter, SmtpAdapterOptions, SmtpContextCapability, SmtpTlsOptions, SmtpAuthVerifier, SmtpRecipientValidator } from './smtp.js';
18
+ export { createSshAdapter } from './ssh.js';
19
+ export { generateEphemeralHostKey } from './ssh-host-key.js';
20
+ export { parseKeys } from './ssh-keys.js';
21
+ export type { SshAdapter, SshAdapterOptions, SshAuthOptions, SshAuthHandler, SshAuthRequest, SshClientInfo, SshHostKey, SshPtyInfo, SshSession, SshSessionHandler, KeyEvent, TtyReadable, TtyWritable, } from './ssh-types.js';
18
22
  export { checkConnectionFilter, checkWebSocketConnectionFilter } from './utils/connection-filter.js';
19
23
  export type { ConnectionFilter, WebSocketConnectionFilter } from './utils/connection-filter.js';
20
24
  export { validateChannelName, DEFAULT_CHANNEL_NAME_PATTERN, DEFAULT_CHANNEL_NAME_MAX_LENGTH, } from './utils/channel-name.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AACvD,YAAY,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AAGpG,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAGhF,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC5D,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAG7D,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC5D,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAG7D,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACtF,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,eAAe,EACf,YAAY,GACb,MAAM,cAAc,CAAA;AAGrB,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAGhG,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAC/D,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,cAAc,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAA;AAGjJ,OAAO,EAAE,qBAAqB,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAA;AACpG,YAAY,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAA;AAG/F,OAAO,EACL,mBAAmB,EACnB,4BAA4B,EAC5B,+BAA+B,GAChC,MAAM,yBAAyB,CAAA;AAChC,YAAY,EACV,qBAAqB,EACrB,4BAA4B,GAC7B,MAAM,yBAAyB,CAAA;AAGhC,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAA;AACzF,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AACvD,YAAY,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AAGpG,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAGhF,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC5D,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAG7D,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC5D,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAG7D,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACtF,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,eAAe,EACf,YAAY,GACb,MAAM,cAAc,CAAA;AAGrB,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAGhG,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAC/D,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,cAAc,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAA;AAGjJ,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,YAAY,EACV,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,cAAc,EACd,aAAa,EACb,UAAU,EACV,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,QAAQ,EACR,WAAW,EACX,WAAW,GACZ,MAAM,gBAAgB,CAAA;AAGvB,OAAO,EAAE,qBAAqB,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAA;AACpG,YAAY,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAA;AAG/F,OAAO,EACL,mBAAmB,EACnB,4BAA4B,EAC5B,+BAA+B,GAChC,MAAM,yBAAyB,CAAA;AAChC,YAAY,EACV,qBAAqB,EACrB,4BAA4B,GAC7B,MAAM,yBAAyB,CAAA;AAGhC,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAA;AACzF,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA"}
@@ -16,6 +16,10 @@ export { createJsonRpcAdapter, JsonRpcErrorCode, HttpMetadataKey } from './jsonr
16
16
  export { createGrpcAdapter } from './grpc.js';
17
17
  // SMTP adapter
18
18
  export { createSmtpAdapter, createSmtpClient } from './smtp.js';
19
+ // SSH adapter
20
+ export { createSshAdapter } from './ssh.js';
21
+ export { generateEphemeralHostKey } from './ssh-host-key.js';
22
+ export { parseKeys } from './ssh-keys.js';
19
23
  // Connection Filter (TCP, UDP, WebSocket)
20
24
  export { checkConnectionFilter, checkWebSocketConnectionFilter } from './utils/connection-filter.js';
21
25
  // Channel name validation (WebSocket subscribe/publish ingress, issue #106)
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,iDAAiD;AAEjD,oBAAoB;AACpB,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAGvD,eAAe;AACf,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAG7C,cAAc;AACd,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAG5D,cAAc;AACd,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAG5D,uBAAuB;AACvB,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAStF,eAAe;AACf,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAG7C,eAAe;AACf,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAG/D,0CAA0C;AAC1C,OAAO,EAAE,qBAAqB,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAA;AAGpG,4EAA4E;AAC5E,OAAO,EACL,mBAAmB,EACnB,4BAA4B,EAC5B,+BAA+B,GAChC,MAAM,yBAAyB,CAAA;AAMhC,wCAAwC;AACxC,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,iDAAiD;AAEjD,oBAAoB;AACpB,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAGvD,eAAe;AACf,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAG7C,cAAc;AACd,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAG5D,cAAc;AACd,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAG5D,uBAAuB;AACvB,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAStF,eAAe;AACf,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAG7C,eAAe;AACf,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAG/D,cAAc;AACd,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAiBzC,0CAA0C;AAC1C,OAAO,EAAE,qBAAqB,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAA;AAGpG,4EAA4E;AAC5E,OAAO,EACL,mBAAmB,EACnB,4BAA4B,EAC5B,+BAA+B,GAChC,MAAM,yBAAyB,CAAA;AAMhC,wCAAwC;AACxC,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAA"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * SSH Adapter — Host key utilities
3
+ *
4
+ * Auto-generates an ephemeral RSA host key for dev. For production,
5
+ * users should provide a persistent key via `hostKeys` so clients don't
6
+ * see a "host key changed" warning each restart.
7
+ */
8
+ /**
9
+ * Generate an ephemeral RSA 2048 private key in PEM (PKCS#1) format.
10
+ * Suitable for ssh2 ServerConfig.hostKeys.
11
+ *
12
+ * RSA + PKCS#1 was chosen because it is the format ssh2 parses most
13
+ * reliably across versions. Ed25519 in PKCS#8 (Node's default) is not
14
+ * accepted by ssh2's key parser.
15
+ */
16
+ export declare function generateEphemeralHostKey(): Buffer;
17
+ //# sourceMappingURL=ssh-host-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-host-key.d.ts","sourceRoot":"","sources":["../../src/adapters/ssh-host-key.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAOjD"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * SSH Adapter — Host key utilities
3
+ *
4
+ * Auto-generates an ephemeral RSA host key for dev. For production,
5
+ * users should provide a persistent key via `hostKeys` so clients don't
6
+ * see a "host key changed" warning each restart.
7
+ */
8
+ import { generateKeyPairSync } from 'node:crypto';
9
+ /**
10
+ * Generate an ephemeral RSA 2048 private key in PEM (PKCS#1) format.
11
+ * Suitable for ssh2 ServerConfig.hostKeys.
12
+ *
13
+ * RSA + PKCS#1 was chosen because it is the format ssh2 parses most
14
+ * reliably across versions. Ed25519 in PKCS#8 (Node's default) is not
15
+ * accepted by ssh2's key parser.
16
+ */
17
+ export function generateEphemeralHostKey() {
18
+ const { privateKey } = generateKeyPairSync('rsa', {
19
+ modulusLength: 2048,
20
+ privateKeyEncoding: { type: 'pkcs1', format: 'pem' },
21
+ publicKeyEncoding: { type: 'pkcs1', format: 'pem' },
22
+ });
23
+ return Buffer.from(privateKey, 'utf8');
24
+ }
25
+ //# sourceMappingURL=ssh-host-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-host-key.js","sourceRoot":"","sources":["../../src/adapters/ssh-host-key.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEjD;;;;;;;GAOG;AACH,MAAM,UAAU,wBAAwB;IACtC,MAAM,EAAE,UAAU,EAAE,GAAG,mBAAmB,CAAC,KAAK,EAAE;QAChD,aAAa,EAAE,IAAI;QACnB,kBAAkB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE;QACpD,iBAAiB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE;KACpD,CAAC,CAAA;IACF,OAAO,MAAM,CAAC,IAAI,CAAC,UAAoB,EAAE,MAAM,CAAC,CAAA;AAClD,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * SSH Adapter — Key parser
3
+ *
4
+ * Parses raw bytes from a pty stdin into structured KeyEvent objects.
5
+ * Recognises common ANSI escape sequences (arrows, function keys, navigation)
6
+ * and ASCII control codes.
7
+ *
8
+ * Inspired by Node's internal `readline` keypress parser but kept minimal
9
+ * and self-contained (no readline dep, no process.stdin coupling).
10
+ */
11
+ import type { KeyEvent } from './ssh-types.js';
12
+ /**
13
+ * Parse one buffer chunk into zero or more KeyEvents.
14
+ *
15
+ * Best-effort: an incoming chunk may contain multiple keys (bracketed
16
+ * paste, key spam) and we emit them in order. An incomplete escape
17
+ * sequence at the end is dropped (the next chunk should re-deliver it
18
+ * since terminals send escape sequences in one frame in practice).
19
+ */
20
+ export declare function parseKeys(buf: Buffer): KeyEvent[];
21
+ //# sourceMappingURL=ssh-keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-keys.d.ts","sourceRoot":"","sources":["../../src/adapters/ssh-keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAwC9C;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,EAAE,CAuGjD"}
@@ -0,0 +1,211 @@
1
+ /**
2
+ * SSH Adapter — Key parser
3
+ *
4
+ * Parses raw bytes from a pty stdin into structured KeyEvent objects.
5
+ * Recognises common ANSI escape sequences (arrows, function keys, navigation)
6
+ * and ASCII control codes.
7
+ *
8
+ * Inspired by Node's internal `readline` keypress parser but kept minimal
9
+ * and self-contained (no readline dep, no process.stdin coupling).
10
+ */
11
+ const NAMED_CSI = {
12
+ A: 'up',
13
+ B: 'down',
14
+ C: 'right',
15
+ D: 'left',
16
+ H: 'home',
17
+ F: 'end',
18
+ // CSI ~ family
19
+ '2~': 'insert',
20
+ '3~': 'delete',
21
+ '5~': 'pageup',
22
+ '6~': 'pagedown',
23
+ '7~': 'home',
24
+ '8~': 'end',
25
+ '11~': 'f1',
26
+ '12~': 'f2',
27
+ '13~': 'f3',
28
+ '14~': 'f4',
29
+ '15~': 'f5',
30
+ '17~': 'f6',
31
+ '18~': 'f7',
32
+ '19~': 'f8',
33
+ '20~': 'f9',
34
+ '21~': 'f10',
35
+ '23~': 'f11',
36
+ '24~': 'f12',
37
+ };
38
+ // SS3 sequences (ESC O X) — common for F1-F4
39
+ const SS3 = {
40
+ P: 'f1',
41
+ Q: 'f2',
42
+ R: 'f3',
43
+ S: 'f4',
44
+ H: 'home',
45
+ F: 'end',
46
+ };
47
+ /**
48
+ * Parse one buffer chunk into zero or more KeyEvents.
49
+ *
50
+ * Best-effort: an incoming chunk may contain multiple keys (bracketed
51
+ * paste, key spam) and we emit them in order. An incomplete escape
52
+ * sequence at the end is dropped (the next chunk should re-deliver it
53
+ * since terminals send escape sequences in one frame in practice).
54
+ */
55
+ export function parseKeys(buf) {
56
+ const out = [];
57
+ let i = 0;
58
+ while (i < buf.length) {
59
+ const byte = buf[i];
60
+ // ESC — start of escape sequence
61
+ if (byte === 0x1b) {
62
+ // ESC alone (would be ambiguous; emit as 'escape' if it's the only byte)
63
+ if (i === buf.length - 1) {
64
+ out.push(makeKey(buf.slice(i, i + 1), { name: 'escape' }));
65
+ i++;
66
+ continue;
67
+ }
68
+ const next = buf[i + 1];
69
+ // ESC [ — CSI
70
+ if (next === 0x5b /* [ */) {
71
+ const end = findCsiEnd(buf, i + 2);
72
+ if (end === -1) {
73
+ // Incomplete — bail; client likely sends the rest in another chunk
74
+ break;
75
+ }
76
+ const seq = buf.slice(i, end + 1);
77
+ out.push(parseCsi(seq));
78
+ i = end + 1;
79
+ continue;
80
+ }
81
+ // ESC O — SS3
82
+ if (next === 0x4f /* O */ && i + 2 < buf.length) {
83
+ const c = String.fromCharCode(buf[i + 2]);
84
+ const name = SS3[c];
85
+ out.push(makeKey(buf.slice(i, i + 3), {
86
+ name,
87
+ sequence: `\x1bO${c}`,
88
+ }));
89
+ i += 3;
90
+ continue;
91
+ }
92
+ // ESC <char> — alt+char
93
+ if (next >= 0x20 && next < 0x7f) {
94
+ const ch = String.fromCharCode(next);
95
+ out.push(makeKey(buf.slice(i, i + 2), {
96
+ str: ch,
97
+ name: ch.toLowerCase(),
98
+ meta: true,
99
+ shift: ch >= 'A' && ch <= 'Z',
100
+ }));
101
+ i += 2;
102
+ continue;
103
+ }
104
+ // Unknown ESC sequence — drop ESC, treat next bytes normally
105
+ i++;
106
+ continue;
107
+ }
108
+ // ASCII control codes
109
+ if (byte < 0x20 || byte === 0x7f) {
110
+ out.push(parseControl(byte, buf.slice(i, i + 1)));
111
+ i++;
112
+ continue;
113
+ }
114
+ // UTF-8 character (single byte fast path)
115
+ if (byte < 0x80) {
116
+ const ch = String.fromCharCode(byte);
117
+ out.push(makeKey(buf.slice(i, i + 1), {
118
+ str: ch,
119
+ name: ch.toLowerCase(),
120
+ shift: ch >= 'A' && ch <= 'Z',
121
+ }));
122
+ i++;
123
+ continue;
124
+ }
125
+ // Multi-byte UTF-8 — find length
126
+ let len = 1;
127
+ if ((byte & 0xe0) === 0xc0)
128
+ len = 2;
129
+ else if ((byte & 0xf0) === 0xe0)
130
+ len = 3;
131
+ else if ((byte & 0xf8) === 0xf0)
132
+ len = 4;
133
+ if (i + len > buf.length)
134
+ break; // incomplete
135
+ const slice = buf.slice(i, i + len);
136
+ out.push(makeKey(slice, {
137
+ str: slice.toString('utf8'),
138
+ }));
139
+ i += len;
140
+ }
141
+ return out;
142
+ }
143
+ function findCsiEnd(buf, start) {
144
+ // CSI final byte is in range 0x40..0x7e
145
+ for (let i = start; i < buf.length; i++) {
146
+ const b = buf[i];
147
+ if (b >= 0x40 && b <= 0x7e)
148
+ return i;
149
+ }
150
+ return -1;
151
+ }
152
+ function parseCsi(seq) {
153
+ const str = seq.toString('ascii');
154
+ const params = str.slice(2, -1); // strip ESC [ and final byte
155
+ const final = str[str.length - 1];
156
+ // CSI <num>~ family (e.g. 5~ = pageup)
157
+ if (final === '~') {
158
+ const key = `${params}~`;
159
+ const name = NAMED_CSI[key];
160
+ return makeKey(seq, { name, sequence: str });
161
+ }
162
+ // CSI <letter> family (arrows, home, end)
163
+ // May include modifier params: ESC[1;5A means ctrl+up
164
+ const name = NAMED_CSI[final];
165
+ let ctrl = false;
166
+ let shift = false;
167
+ let meta = false;
168
+ if (params.includes(';')) {
169
+ const mod = parseInt(params.split(';')[1] ?? '1', 10) - 1;
170
+ if (mod & 1)
171
+ shift = true;
172
+ if (mod & 2)
173
+ meta = true;
174
+ if (mod & 4)
175
+ ctrl = true;
176
+ }
177
+ return makeKey(seq, { name, ctrl, shift, meta, sequence: str });
178
+ }
179
+ function parseControl(byte, raw) {
180
+ if (byte === 0x0d /* \r */ || byte === 0x0a /* \n */) {
181
+ return makeKey(raw, { name: 'return', str: '\n' });
182
+ }
183
+ if (byte === 0x09 /* \t */)
184
+ return makeKey(raw, { name: 'tab', str: '\t' });
185
+ if (byte === 0x7f)
186
+ return makeKey(raw, { name: 'backspace' });
187
+ if (byte === 0x08)
188
+ return makeKey(raw, { name: 'backspace', ctrl: true });
189
+ if (byte === 0x20 /* space */)
190
+ return makeKey(raw, { name: 'space', str: ' ' });
191
+ if (byte === 0x1b)
192
+ return makeKey(raw, { name: 'escape' });
193
+ // Ctrl+A..Ctrl+Z map to 0x01..0x1a
194
+ if (byte >= 0x01 && byte <= 0x1a) {
195
+ const letter = String.fromCharCode(0x60 + byte); // 'a' + (byte - 1)
196
+ return makeKey(raw, { name: letter, ctrl: true, str: letter });
197
+ }
198
+ return makeKey(raw, { sequence: `\\x${byte.toString(16).padStart(2, '0')}` });
199
+ }
200
+ function makeKey(raw, partial) {
201
+ return {
202
+ raw,
203
+ str: partial.str ?? '',
204
+ name: partial.name,
205
+ ctrl: partial.ctrl ?? false,
206
+ shift: partial.shift ?? false,
207
+ meta: partial.meta ?? false,
208
+ sequence: partial.sequence,
209
+ };
210
+ }
211
+ //# sourceMappingURL=ssh-keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-keys.js","sourceRoot":"","sources":["../../src/adapters/ssh-keys.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * SSH Adapter — Session factory
3
+ *
4
+ * Wraps an ssh2 ServerChannel into the user-facing SshSession surface.
5
+ * Owns the lifecycle: parses input keys, manages window-resize, dispatches
6
+ * close events, builds the lazy tuiuiu bridge.
7
+ */
8
+ import type { Writable } from 'node:stream';
9
+ import type { SshClientInfo, SshPtyInfo, SshSession } from './ssh-types.js';
10
+ import { type TuiBridge } from './ssh-tui-bridge.js';
11
+ /**
12
+ * Minimal subset of ssh2 ServerChannel we depend on. Declared structurally
13
+ * so we don't need to import ssh2 types into adapter session code.
14
+ */
15
+ export interface SshChannelLike {
16
+ stderr: Writable;
17
+ write(chunk: string | Uint8Array): boolean;
18
+ end(): void;
19
+ exit(code: number): void;
20
+ on(event: 'data', listener: (chunk: Buffer) => void): this;
21
+ on(event: 'close' | 'end', listener: () => void): this;
22
+ once(event: 'close' | 'end', listener: () => void): this;
23
+ off(event: string, listener: (...args: unknown[]) => void): this;
24
+ destroyed?: boolean;
25
+ pipe?: unknown;
26
+ }
27
+ export interface CreateSshSessionOptions {
28
+ id: string;
29
+ user: string;
30
+ authMethod: 'none' | 'password' | 'publickey';
31
+ authData: {
32
+ publicKey?: {
33
+ algo: string;
34
+ data: Buffer;
35
+ };
36
+ };
37
+ client: SshClientInfo;
38
+ env: Record<string, string>;
39
+ pty: SshPtyInfo | null;
40
+ channel: SshChannelLike;
41
+ kind: 'shell' | 'exec' | 'subsystem';
42
+ command?: string;
43
+ subsystem?: string;
44
+ }
45
+ export interface InternalSshSession extends SshSession {
46
+ /** Update pty size — called when the SSH client sends window-change. */
47
+ _updateSize(cols: number, rows: number): void;
48
+ /** Notify the session that the underlying channel closed. */
49
+ _notifyClosed(): void;
50
+ /** Get the tui bridge if it was created, else null (for cleanup). */
51
+ _tuiBridge(): TuiBridge | null;
52
+ }
53
+ export declare function createSshSession(opts: CreateSshSessionOptions): InternalSshSession;
54
+ //# sourceMappingURL=ssh-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-session.d.ts","sourceRoot":"","sources":["../../src/adapters/ssh-session.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAY,QAAQ,EAAE,MAAM,aAAa,CAAA;AACrD,OAAO,KAAK,EAEV,aAAa,EACb,UAAU,EACV,UAAU,EAGX,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAErE;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,QAAQ,CAAA;IAChB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAA;IAC1C,GAAG,IAAI,IAAI,CAAA;IACX,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAA;IAC1D,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAA;IACtD,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAA;IACxD,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI,CAAA;IAChE,SAAS,CAAC,EAAE,OAAO,CAAA;IAEnB,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,WAAW,CAAA;IAC7C,QAAQ,EAAE;QAAE,SAAS,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAA;IACxD,MAAM,EAAE,aAAa,CAAA;IACrB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC3B,GAAG,EAAE,UAAU,GAAG,IAAI,CAAA;IACtB,OAAO,EAAE,cAAc,CAAA;IACvB,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,WAAW,CAAA;IACpC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,kBAAmB,SAAQ,UAAU;IACpD,wEAAwE;IACxE,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7C,6DAA6D;IAC7D,aAAa,IAAI,IAAI,CAAA;IACrB,qEAAqE;IACrE,UAAU,IAAI,SAAS,GAAG,IAAI,CAAA;CAC/B;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,uBAAuB,GAAG,kBAAkB,CAkMlF"}