mirror of
https://github.com/tailscale/tailscale.git
synced 2025-04-16 11:41:39 +00:00
cmd/tsconnect: expose runSSHSession in npm package
Move it to lib/ so that it can be used in both the app and the package. Updates #5415 Signed-off-by: Mihai Parparita <mihai@tailscale.com>
This commit is contained in:
parent
e4b5b92b82
commit
7d1357162e
@ -3,13 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
import { useState, useCallback } from "preact/hooks"
|
import { useState, useCallback } from "preact/hooks"
|
||||||
import { Terminal } from "xterm"
|
import { runSSHSession, SSHSessionDef } from "../lib/ssh"
|
||||||
import { FitAddon } from "xterm-addon-fit"
|
|
||||||
|
|
||||||
type SSHSessionDef = {
|
|
||||||
username: string
|
|
||||||
hostname: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export function SSH({ netMap, ipn }: { netMap: IPNNetMap; ipn: IPN }) {
|
export function SSH({ netMap, ipn }: { netMap: IPNNetMap; ipn: IPN }) {
|
||||||
const [sshSessionDef, setSSHSessionDef] = useState<SSHSessionDef | null>(null)
|
const [sshSessionDef, setSSHSessionDef] = useState<SSHSessionDef | null>(null)
|
||||||
@ -55,51 +49,6 @@ function SSHSession({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function runSSHSession(
|
|
||||||
termContainerNode: HTMLDivElement,
|
|
||||||
def: SSHSessionDef,
|
|
||||||
ipn: IPN,
|
|
||||||
onDone: () => void
|
|
||||||
) {
|
|
||||||
const term = new Terminal({
|
|
||||||
cursorBlink: true,
|
|
||||||
})
|
|
||||||
const fitAddon = new FitAddon()
|
|
||||||
term.loadAddon(fitAddon)
|
|
||||||
term.open(termContainerNode)
|
|
||||||
fitAddon.fit()
|
|
||||||
|
|
||||||
let onDataHook: ((data: string) => void) | undefined
|
|
||||||
term.onData((e) => {
|
|
||||||
onDataHook?.(e)
|
|
||||||
})
|
|
||||||
|
|
||||||
term.focus()
|
|
||||||
|
|
||||||
const sshSession = ipn.ssh(def.hostname, def.username, {
|
|
||||||
writeFn: (input) => term.write(input),
|
|
||||||
setReadFn: (hook) => (onDataHook = hook),
|
|
||||||
rows: term.rows,
|
|
||||||
cols: term.cols,
|
|
||||||
onDone: () => {
|
|
||||||
resizeObserver.disconnect()
|
|
||||||
term.dispose()
|
|
||||||
window.removeEventListener("beforeunload", handleBeforeUnload)
|
|
||||||
onDone()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
// Make terminal and SSH session track the size of the containing DOM node.
|
|
||||||
const resizeObserver = new ResizeObserver(() => fitAddon.fit())
|
|
||||||
resizeObserver.observe(termContainerNode)
|
|
||||||
term.onResize(({ rows, cols }) => sshSession.resize(rows, cols))
|
|
||||||
|
|
||||||
// Close the session if the user closes the window without an explicit
|
|
||||||
// exit.
|
|
||||||
const handleBeforeUnload = () => sshSession.close()
|
|
||||||
window.addEventListener("beforeunload", handleBeforeUnload)
|
|
||||||
}
|
|
||||||
|
|
||||||
function NoSSHPeers() {
|
function NoSSHPeers() {
|
||||||
return (
|
return (
|
||||||
<div class="container mx-auto px-4 text-center">
|
<div class="container mx-auto px-4 text-center">
|
||||||
|
52
cmd/tsconnect/src/lib/ssh.ts
Normal file
52
cmd/tsconnect/src/lib/ssh.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { Terminal } from "xterm"
|
||||||
|
import { FitAddon } from "xterm-addon-fit"
|
||||||
|
|
||||||
|
export type SSHSessionDef = {
|
||||||
|
username: string
|
||||||
|
hostname: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function runSSHSession(
|
||||||
|
termContainerNode: HTMLDivElement,
|
||||||
|
def: SSHSessionDef,
|
||||||
|
ipn: IPN,
|
||||||
|
onDone: () => void
|
||||||
|
) {
|
||||||
|
const term = new Terminal({
|
||||||
|
cursorBlink: true,
|
||||||
|
})
|
||||||
|
const fitAddon = new FitAddon()
|
||||||
|
term.loadAddon(fitAddon)
|
||||||
|
term.open(termContainerNode)
|
||||||
|
fitAddon.fit()
|
||||||
|
|
||||||
|
let onDataHook: ((data: string) => void) | undefined
|
||||||
|
term.onData((e) => {
|
||||||
|
onDataHook?.(e)
|
||||||
|
})
|
||||||
|
|
||||||
|
term.focus()
|
||||||
|
|
||||||
|
const sshSession = ipn.ssh(def.hostname, def.username, {
|
||||||
|
writeFn: (input) => term.write(input),
|
||||||
|
setReadFn: (hook) => (onDataHook = hook),
|
||||||
|
rows: term.rows,
|
||||||
|
cols: term.cols,
|
||||||
|
onDone: () => {
|
||||||
|
resizeObserver.disconnect()
|
||||||
|
term.dispose()
|
||||||
|
window.removeEventListener("beforeunload", handleBeforeUnload)
|
||||||
|
onDone()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Make terminal and SSH session track the size of the containing DOM node.
|
||||||
|
const resizeObserver = new ResizeObserver(() => fitAddon.fit())
|
||||||
|
resizeObserver.observe(termContainerNode)
|
||||||
|
term.onResize(({ rows, cols }) => sshSession.resize(rows, cols))
|
||||||
|
|
||||||
|
// Close the session if the user closes the window without an explicit
|
||||||
|
// exit.
|
||||||
|
const handleBeforeUnload = () => sshSession.close()
|
||||||
|
window.addEventListener("beforeunload", handleBeforeUnload)
|
||||||
|
}
|
@ -37,3 +37,5 @@ export async function createIPN(config: IPNPackageConfig): Promise<IPN> {
|
|||||||
|
|
||||||
return newIPN(config)
|
return newIPN(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export { runSSHSession } from "../lib/ssh"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user