diff --git a/.dockerignore b/.dockerignore index 3c3629e..126b9d1 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1 +1,2 @@ node_modules +.esm-cache diff --git a/.eslintignore b/.eslintignore index 0a03045..53117f7 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,3 @@ node_modules/ public/ +.esm-cache diff --git a/.gitignore b/.gitignore index 03fe0f5..38311e2 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,5 @@ logs results npm-debug.log -node_modules/* \ No newline at end of file +node_modules/* +.esm-cache diff --git a/app.js b/app.js index 76b7c4e..d786c14 100644 --- a/app.js +++ b/app.js @@ -1,93 +1,4 @@ #! /usr/bin/env node -const wetty = require('./wetty.js'); -const fs = require('fs-extra'); -const path = require('path'); -const optimist = require('optimist'); - -const opts = optimist - .options({ - sslkey: { - demand : false, - description: 'path to SSL key', - }, - sslcert: { - demand : false, - description: 'path to SSL certificate', - }, - sshhost: { - demand : false, - description: 'ssh server host', - }, - sshport: { - demand : false, - description: 'ssh server port', - }, - sshuser: { - demand : false, - description: 'ssh user', - }, - sshauth: { - demand : false, - description: 'defaults to "password", you can use "publickey,password" instead', - }, - port: { - demand : false, - alias : 'p', - description: 'wetty listen port', - }, - help: { - demand : false, - alias : 'h', - description: 'Print help message', - }, - }) - .boolean('allow_discovery').argv; - -if (opts.help) { - optimist.showHelp(); - process.exit(0); -} - -const sshuser = opts.sshuser || process.env.SSHUSER || ''; -const sshhost = opts.sshhost || process.env.SSHHOST || 'localhost'; -const sshauth = opts.sshauth || process.env.SSHAUTH || 'password,keyboard-interactive'; -const sshport = opts.sshport || process.env.SSHPOST || 22; -const port = opts.port || process.env.PORT || 3000; - -loadSSL(opts).then(ssl => { - opts.ssl = ssl; -}); - -process.on('uncaughtException', err => { - console.error(`Error: ${err}`); -}); - -const tty = wetty.serve(port, sshuser, sshhost, sshport, sshauth, opts.ssl); - -tty.on('exit', code => { - console.log(`exit with code: ${code}`); -}); - -tty.on('disconnect', () => { - console.log('disconnect'); -}); - -function loadSSL({ sslkey, sslcert }) { - return new Promise((resolve, reject) => { - if (sslkey && sslcert) { - const ssl = {}; - fs - .readFile(path.resolve(sslkey)) - .then(key => { - ssl.key = key; - }) - .then(fs.readFile(path.resolve(sslcert))) - .then(cert => { - ssl.cert = cert; - }) - .then(resolve(ssl)) - .catch(reject); - } - resolve({}); - }); -} +require('@std/esm'); +require('./cli'); +module.exports = require('./wetty').default; diff --git a/cli.js b/cli.js new file mode 100644 index 0000000..609c12b --- /dev/null +++ b/cli.js @@ -0,0 +1,90 @@ +import fs from 'fs-extra'; +import path from 'path'; +import optimist from 'optimist'; +import wetty from './wetty'; + +const opts = optimist + .options({ + sslkey: { + demand : false, + description: 'path to SSL key', + }, + sslcert: { + demand : false, + description: 'path to SSL certificate', + }, + sshhost: { + demand : false, + description: 'ssh server host', + }, + sshport: { + demand : false, + description: 'ssh server port', + }, + sshuser: { + demand : false, + description: 'ssh user', + }, + sshauth: { + demand : false, + description: 'defaults to "password", you can use "publickey,password" instead', + }, + port: { + demand : false, + alias : 'p', + description: 'wetty listen port', + }, + help: { + demand : false, + alias : 'h', + description: 'Print help message', + }, + }) + .boolean('allow_discovery').argv; + +if (opts.help) { + optimist.showHelp(); + process.exit(0); +} + +const sshuser = opts.sshuser || process.env.SSHUSER || ''; +const sshhost = opts.sshhost || process.env.SSHHOST || 'localhost'; +const sshauth = opts.sshauth || process.env.SSHAUTH || 'password,keyboard-interactive'; +const sshport = opts.sshport || process.env.SSHPOST || 22; +const port = opts.port || process.env.PORT || 3000; + +loadSSL(opts).then(ssl => { + opts.ssl = ssl; +}); + +process.on('uncaughtException', err => { + console.error(`Error: ${err}`); +}); + +const tty = wetty(port, sshuser, sshhost, sshport, sshauth, opts.ssl); +tty.on('exit', code => { + console.log(`exit with code: ${code}`); +}); +tty.on('disconnect', () => { + console.log('disconnect'); +}); + +function loadSSL({ sslkey, sslcert }) { + return new Promise((resolve, reject) => { + if (sslkey && sslcert) { + const ssl = {}; + fs + .readFile(path.resolve(sslkey)) + .then(key => { + ssl.key = key; + }) + .then(fs.readFile(path.resolve(sslcert))) + .then(cert => { + ssl.cert = cert; + }) + .then(resolve(ssl)) + .catch(reject); + } + resolve({}); + }); +} diff --git a/package.json b/package.json index d6e0fcf..1adb75b 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "wetty.js", "version": "0.3.0", "dependencies": { + "@std/esm": "^0.2.2", "express": "^4.15.3", "fs-extra": "^4.0.1", "optimist": "^0.6", @@ -23,10 +24,10 @@ "del": "^3.0.0", "es6-promise": "^4.1.1", "eslint": "3.19.0", - "eslint-config-standard": "10.2.1", "eslint-config-airbnb": "^15.1.0", - "eslint-plugin-jsx-a11y": "^5.1.1", + "eslint-config-standard": "10.2.1", "eslint-plugin-import": "^2.7.0", + "eslint-plugin-jsx-a11y": "^5.1.1", "eslint-plugin-node": "^5.1.1", "eslint-plugin-promise": "^3.5.0", "eslint-plugin-react": "^7.1.0", @@ -54,6 +55,10 @@ "bin": { "wetty": "./app.js" }, + "@std/esm": { + "esm": "js", + "cjs": "true" + }, "files": ["bin", "public"], "scripts": { "lint": "eslint .", diff --git a/wetty.js b/wetty.js index cce0993..7848c1a 100644 --- a/wetty.js +++ b/wetty.js @@ -1,27 +1,27 @@ -const express = require('express'); -const http = require('http'); -const https = require('https'); -const path = require('path'); -const server = require('socket.io'); -const pty = require('pty.js'); -const EventEmitter = require('events'); -const favicon = require('serve-favicon'); +import express from 'express'; +import http from 'http'; +import https from 'https'; +import path from 'path'; +import server from 'socket.io'; +import pty from 'pty.js'; +import EventEmitter from 'events'; +import favicon from 'serve-favicon'; const app = express(); app.use(favicon(`${__dirname}/public/favicon.ico`)); // For using wetty at /wetty on a vhost app.get('/wetty/ssh/:user', (req, res) => { - res.sendfile(`${__dirname}/public/wetty/index.html`); + res.sendFile(`${__dirname}/public/wetty/index.html`); }); app.get('/wetty/', (req, res) => { - res.sendfile(`${__dirname}/public/wetty/index.html`); + res.sendFile(`${__dirname}/public/wetty/index.html`); }); // For using wetty on a vhost by itself app.get('/ssh/:user', (req, res) => { - res.sendfile(`${__dirname}/public/wetty/index.html`); + res.sendFile(`${__dirname}/public/wetty/index.html`); }); app.get('/', (req, res) => { - res.sendfile(`${__dirname}/public/wetty/index.html`); + res.sendFile(`${__dirname}/public/wetty/index.html`); }); // For serving css and javascript app.use('/', express.static(path.join(__dirname, 'public'))); @@ -36,9 +36,8 @@ function createServer(port, sslopts) { }); } -exports.serve = (port, globalsshuser, sshhost, sshport, sshauth, sslopts) => { +export default (port, globalsshuser, sshhost, sshport, sshauth, sslopts) => { const httpserv = createServer(port, sslopts); - const events = new EventEmitter(); const io = server(httpserv, { path: '/wetty/socket.io' }); io.on('connection', socket => { @@ -69,12 +68,12 @@ exports.serve = (port, globalsshuser, sshhost, sshport, sshauth, sslopts) => { socket.on('resize', ({ col, row }) => { term.resize(col, row); }); - socket.on('input', term.write); + socket.on('input', input => term.write(input)); socket.on('disconnect', () => { term.end(); + term.destroy(); events.emit('disconnect'); }); }); - return events; }; diff --git a/yarn.lock b/yarn.lock index 049af46..091f2fb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,10 @@ # yarn lockfile v1 +"@std/esm@^0.2.2": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@std/esm/-/esm-0.2.2.tgz#8d3fdacae23015eae01db739a9f76d7cd1ab617d" + abbrev@1: version "1.1.0" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f"