UNPKG

vue-ssh-terminal

Version:

SSH Terminal component based on xterm.js for multiple frontend frameworks

19 lines (18 loc) 6.49 kB
(function(i,u){typeof exports=="object"&&typeof module<"u"?u(exports,require("xterm"),require("xterm-addon-fit"),require("xterm-addon-web-links"),require("xterm-addon-search"),require("vue")):typeof define=="function"&&define.amd?define(["exports","xterm","xterm-addon-fit","xterm-addon-web-links","xterm-addon-search","vue"],u):(i=typeof globalThis<"u"?globalThis:i||self,u(i.SSHTerminal={},i.Terminal,i.FitAddon,i.WebLinksAddon,i.SearchAddon,i.Vue))})(this,function(i,u,g,v,z,h){"use strict";const _={fontSize:14,fontFamily:'Menlo, Monaco, "Courier New", monospace',theme:{background:"#000000",foreground:"#ffffff",cursor:"#ffffff",cursorAccent:"#000000",selection:"rgba(255, 255, 255, 0.3)"},cursorBlink:!0,cursorStyle:"block",scrollback:1e3,allowTransparency:!1,tabStopWidth:8,screenReaderMode:!1,convertEol:!0,disableStdin:!1};function w(o,t,a={}){if(!o)throw new Error("Container element is required");if(!t||!t.host||!t.username||!t.password)throw new Error("SSH configuration (host, username, password) is required");const s={..._,...a.theme?{theme:{..._.theme,...a.theme}}:{},...a},e=new u.Terminal(s),l=new g.FitAddon,c=new v.WebLinksAddon,m=new z.SearchAddon;e.loadAddon(l),e.loadAddon(c),e.loadAddon(m),e.open(o),setTimeout(()=>{l.fit()},0);const p=new ResizeObserver(()=>{l.fit()});p.observe(o);const S=t.wsUrl||"ws://localhost:8080";let n=null,f=!1;const T=()=>{n&&n.close(),n=new WebSocket(S),n.onopen=()=>{f=!0;const d={type:"ssh-connect",host:t.host,username:t.username,password:t.password};n.send(JSON.stringify(d)),e.writeln("Connected to SSH relay server...")},n.onmessage=d=>{try{const r=JSON.parse(d.data);r.type==="ssh-data"?e.write(r.content):r.type==="ssh-error"?e.writeln(`\r Error: ${r.message}\r `):r.type==="ssh-connected"?e.writeln(`\r Connected to ${t.host} as ${t.username}\r `):r.type==="ssh-closed"&&e.writeln(`\r SSH connection closed\r `)}catch{e.write(d.data)}},n.onclose=()=>{f=!1,e.writeln(`\r Connection to SSH relay server closed\r `)},n.onerror=d=>{f=!1,e.writeln(`\r WebSocket error: ${d.message}\r `)},e.onData(d=>{if(f&&n.readyState===WebSocket.OPEN){const r={type:"ssh-data",content:d};n.send(JSON.stringify(r))}}),e.onResize(({cols:d,rows:r})=>{if(f&&n.readyState===WebSocket.OPEN){const q={type:"ssh-resize",cols:d,rows:r};n.send(JSON.stringify(q))}})};return T(),l.fit(),{terminal:e,fitAddon:l,searchAddon:m,reconnect:()=>{T()},resize:()=>{l.fit()},dispose:()=>{n&&n.close(),p.disconnect(),e.dispose()},search:(d,r)=>{m.findNext(d,r)},searchPrevious:(d,r)=>{m.findPrevious(d,r)}}}const C="",$="",b=(o,t)=>{const a=o.__vccOpts||o;for(const[s,e]of t)a[s]=e;return a},k={name:"SSHTerminal",props:{host:{type:String,required:!0},username:{type:String,required:!0},password:{type:String,required:!0},wsUrl:{type:String,default:"ws://localhost:8080"},options:{type:Object,default:()=>({})}},data(){return{terminal:null}},mounted(){this.initTerminal(),window.addEventListener("resize",this.handleResize)},beforeDestroy(){this.terminal&&this.terminal.dispose(),window.removeEventListener("resize",this.handleResize)},methods:{initTerminal(){const o=this.$refs.terminalContainer,t={host:this.host,username:this.username,password:this.password,wsUrl:this.wsUrl};this.terminal=w(o,t,this.options),this.$emit("ready",this.terminal)},handleResize(){this.terminal&&this.terminal.resize()}}},E={ref:"terminalContainer",class:"ssh-terminal-container"};function A(o,t,a,s,e,l){return h.openBlock(),h.createElementBlock("div",E,null,512)}const H=b(k,[["render",A],["__scopeId","data-v-c3dec533"]]),L="",x=b({__name:"SSHTerminal",props:{host:{type:String,required:!0},username:{type:String,required:!0},password:{type:String,required:!0},wsUrl:{type:String,default:"ws://localhost:8080"},options:{type:Object,default:()=>({})}},emits:["ready"],setup(o,{expose:t,emit:a}){const s=o,e=a,l=h.ref(null);let c=null;h.onMounted(()=>{m(),window.addEventListener("resize",p)}),h.onBeforeUnmount(()=>{c&&c.dispose(),window.removeEventListener("resize",p)});function m(){const S=l.value,n={host:s.host,username:s.username,password:s.password,wsUrl:s.wsUrl};c=w(S,n,s.options),e("ready",c)}function p(){c&&c.resize()}return t({getTerminal:()=>c}),(S,n)=>(h.openBlock(),h.createElementBlock("div",{ref_key:"terminalContainer",ref:l,class:"ssh-terminal-container"},null,512))}},[["__scopeId","data-v-5b1c13db"]]);class y extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this.container=document.createElement("div"),this.container.className="ssh-terminal-container",this.styles=document.createElement("style"),this.styles.textContent=` .ssh-terminal-container { width: 100%; height: 100%; min-height: 300px; background-color: #000; } `,this.shadowRoot.appendChild(this.styles),this.shadowRoot.appendChild(this.container),this.terminal=null}static get observedAttributes(){return["host","username","password","ws-url","options"]}connectedCallback(){this.initTerminal(),this.resizeHandler=this.handleResize.bind(this),window.addEventListener("resize",this.resizeHandler)}disconnectedCallback(){this.terminal&&this.terminal.dispose(),window.removeEventListener("resize",this.resizeHandler)}attributeChangedCallback(t,a,s){a!==s&&this.terminal&&["host","username","password","ws-url"].includes(t)&&this.initTerminal()}initTerminal(){this.terminal&&this.terminal.dispose();const t=this.getAttribute("host"),a=this.getAttribute("username"),s=this.getAttribute("password"),e=this.getAttribute("ws-url")||"ws://localhost:8080";let l={};try{const m=this.getAttribute("options");m&&(l=JSON.parse(m))}catch(m){console.error("Invalid options format:",m)}if(!t||!a||!s){console.error("Missing required attributes: host, username, password");return}const c={host:t,username:a,password:s,wsUrl:e};this.terminal=w(this.container,c,l),this.dispatchEvent(new CustomEvent("ready",{detail:{terminal:this.terminal}}))}handleResize(){this.terminal&&this.terminal.resize()}}customElements.define("ssh-terminal",y);const O=Object.freeze(Object.defineProperty({__proto__:null,default:y},Symbol.toStringTag,{value:"Module"}));typeof window<"u"&&window.customElements&&!window.customElements.get("ssh-terminal")&&Promise.resolve().then(()=>O).then(()=>{console.log("SSH Terminal Web Component registered")}).catch(o=>{console.error("Failed to register SSH Terminal Web Component",o)}),i.SSHTerminalElement=y,i.Vue2SSHTerminal=H,i.Vue3SSHTerminal=x,i.createTerminal=w,Object.defineProperty(i,Symbol.toStringTag,{value:"Module"})});