From 09263b3e15d4608de0d10cc9469f57c59c111aa4 Mon Sep 17 00:00:00 2001 From: butlerx Date: Mon, 21 Oct 2019 19:11:03 +0100 Subject: [PATCH 1/8] ensure wetty can build on node 12 --- README.md | 15 +++++++++++++++ package.json | 4 ++-- yarn.lock | 17 ++++++----------- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index facbc17..5c13055 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,17 @@ websockets rather then Ajax and hence better response time. ## Install +### Requiments + +To instal WeTTy you'll need to have the following installed: + +- Node.JS 10+ +- make +- python +- build-essential + +### From source + WeTTy can be installed from source or from npm. To install from source run: @@ -20,11 +31,15 @@ $ yarn $ yarn build ``` +### From NPM + To install it globally from npm use yarn or npm: - yarn, `yarn global add wetty` - npm, `npm i -g wetty` +### Autologin + For auto-login feature you'll need sshpass installed (NOT required for rest of the program). diff --git a/package.json b/package.json index b6dcaac..3c23eb7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wetty", - "version": "1.1.5", + "version": "1.1.6", "description": "WeTTY = Web + TTY. Terminal access in browser over http/https", "homepage": "https://github.com/krishnasrinivas/wetty", "repository": { @@ -55,7 +55,7 @@ "helmet": "^3.20.1", "lodash": "^4.17.15", "morgan": "^1.9.1", - "node-pty": "^0.8.1", + "node-pty": "0.9.0-beta28", "serve-favicon": "^2.5.0", "socket.io": "^2.2.0", "socket.io-client": "^2.2.0", diff --git a/yarn.lock b/yarn.lock index 92b726d..962fded 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4910,12 +4910,7 @@ mute-stream@0.0.7: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= -nan@2.12.1: - version "2.12.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" - integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== - -nan@^2.12.1, nan@^2.13.2: +nan@^2.12.1, nan@^2.13.2, nan@^2.14.0: version "2.14.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== @@ -5047,12 +5042,12 @@ node-pre-gyp@^0.12.0: semver "^5.3.0" tar "^4" -node-pty@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.8.1.tgz#94b457bec013e7a09b8d9141f63b0787fa25c23f" - integrity sha512-j+/g0Q5dR+vkELclpJpz32HcS3O/3EdPSGPvDXJZVJQLCvgG0toEbfmymxAEyQyZEpaoKHAcoL+PvKM+4N9nlw== +node-pty@0.9.0-beta28: + version "0.9.0-beta28" + resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.9.0-beta28.tgz#f086cea157b4640bace2ea787136fde73a26b273" + integrity sha512-qpLJE52oLRIOEvIeVmPzymn+zqUnYhPmlNjSRW60PwEZvhcdmazdP0IJcQfEK6ivwml14TzQLObMjEj8FFO7xg== dependencies: - nan "2.12.1" + nan "^2.14.0" node-releases@^1.1.29: version "1.1.29" From f56f374031413c17075794050c3774616e1440a1 Mon Sep 17 00:00:00 2001 From: butlerx Date: Mon, 21 Oct 2019 19:49:45 +0100 Subject: [PATCH 2/8] upgrade eslint --- .eslintrc.js | 15 ++-- .github/workflows/publish.yml | 2 +- .github/workflows/rebase.yml | 2 +- package.json | 11 +-- src/client/index.ts | 6 +- src/server/server.ts | 2 +- src/server/term.ts | 4 +- src/server/wetty.ts | 2 +- webpack.config.babel.js | 10 +-- yarn.lock | 156 ++++++++++++++++++++-------------- 10 files changed, 119 insertions(+), 91 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 26503e2..a1e07b0 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,6 +1,6 @@ module.exports = { - parser: 'eslint-plugin-typescript/parser', - plugins: ['typescript', 'prettier'], + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint', 'prettier'], env: { es6: true, node: true, @@ -9,24 +9,23 @@ module.exports = { root: true, extends: [ 'airbnb-base', - 'plugin:typescript/recommended', - 'plugin:prettier/recommended', + 'plugin:@typescript-eslint/recommended', + 'prettier', + 'prettier/@typescript-eslint', ], rules: { - 'typescript/indent': 'off', 'linebreak-style': ['error', 'unix'], 'arrow-parens': ['error', 'as-needed'], 'no-param-reassign': ['error', { props: false }], 'func-style': ['error', 'declaration', { allowArrowFunctions: true }], 'no-use-before-define': ['error', { functions: false }], - 'typescript/no-use-before-define': ['error', { functions: false }], + '@typescript-eslint/no-use-before-define': ['error', { functions: false }], }, settings: { 'import/resolver': { - 'typescript-eslint-parser': ['.ts', '.tsx'], node: { extensions: ['.ts', '.js'], }, }, - }, + } }; diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 64e033f..a0d1be4 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -18,7 +18,7 @@ jobs: - run: yarn name: Install dependencies - name: ESLint checks - uses: gimenete/eslint-action@1.0 + run: yarn lint - run: yarn build name: Compile Typescript - name: Publish diff --git a/.github/workflows/rebase.yml b/.github/workflows/rebase.yml index faab0c7..2ab53a2 100644 --- a/.github/workflows/rebase.yml +++ b/.github/workflows/rebase.yml @@ -10,4 +10,4 @@ jobs: - name: Automatic Rebase uses: cirrus-actions/rebase@1.0 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.node_github_token }} diff --git a/package.json b/package.json index 3c23eb7..04abe44 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ }, "main": "index.js", "scripts": { - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --ext .ts .", "build": "babel-node node_modules/.bin/webpack", "start": "node .", "dev": "NODE_ENV=development concurrently --kill-others --success first \"babel-node node_modules/.bin/webpack --watch\" \"nodemon .\"", @@ -82,16 +82,17 @@ "@types/socket.io-client": "^1.4.32", "@types/webpack-env": "^1.14.0", "@types/yargs": "^13.0.2", + "@typescript-eslint/eslint-plugin": "^2.5.0", + "@typescript-eslint/parser": "^2.5.0", "babel-loader": "^8.0.6", "babel-plugin-lodash": "^3.3.4", "concurrently": "^4.1.2", "css-loader": "^3.2.0", - "eslint": "^6.3.0", - "eslint-config-airbnb-base": "^14.0.0", - "eslint-config-prettier": "^6.2.0", + "eslint": "6.1.0", + "eslint-config-airbnb-base": "14.0.0", + "eslint-config-prettier": "^6.4.0", "eslint-plugin-import": "^2.18.2", "eslint-plugin-prettier": "^3.1.0", - "eslint-plugin-typescript": "^1.0.0-rc.1", "file-loader": "^4.2.0", "husky": "^3.0.5", "lint-staged": "~9.2.5", diff --git a/src/client/index.ts b/src/client/index.ts index 81f8cf4..bd879eb 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -16,7 +16,7 @@ socket.on('connect', () => { const term = new Terminal(); term.open(document.getElementById('terminal')); const defaultOptions = { fontSize: 14 }; - let options: any; + let options: object; try { if (localStorage.options === undefined) { options = defaultOptions; @@ -31,9 +31,9 @@ socket.on('connect', () => { term.setOption(key, value); }); const code = JSON.stringify(options, null, 2); - const editor = document.querySelector('#options .editor'); + const editor = document.querySelector('#options .editor') || {value: code}; editor.value = code; - editor.addEventListener('keyup', e => { + editor.addEventListener('keyup', () => { try { const updated = JSON.parse(editor.value); const updatedCode = JSON.stringify(updated, null, 2); diff --git a/src/server/server.ts b/src/server/server.ts index 5d47e0d..1bcb5c1 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -67,7 +67,7 @@ export default function createServer( .use(favicon(path.join(distDir, 'favicon.ico'))) .use(`${basePath}/public`, express.static(distDir)) .use((req, res, next) => { - if (req.url === basePath) res.redirect(301, req.url + '/'); + if (req.url === basePath) res.redirect(301, `${req.url }/`); else next(); }); diff --git a/src/server/term.ts b/src/server/term.ts index af5ba89..742a46a 100644 --- a/src/server/term.ts +++ b/src/server/term.ts @@ -44,9 +44,9 @@ export default class Term { public static login(socket: SocketIO.Socket): Promise { // Check request-header for username - let remoteUser = socket.request.headers['remote-user']; + const remoteUser = socket.request.headers['remote-user']; if (remoteUser) { - return new Promise((resolve,reject) => { + return new Promise(resolve => { resolve(remoteUser); }); } diff --git a/src/server/wetty.ts b/src/server/wetty.ts index 7e18f6b..6bacd86 100644 --- a/src/server/wetty.ts +++ b/src/server/wetty.ts @@ -17,7 +17,7 @@ export default class WeTTy extends EventEmitter { public start( ssh: SSH = { user: '', host: 'localhost', auth: 'password', port: 22 }, serverConf: Server = { base: '/wetty/', port: 3000, host: '0.0.0.0' }, - command: string = '', + command = '', ssl?: SSL ): Promise { return loadSSL(ssl).then((sslBuffer: SSLBuffer) => { diff --git a/webpack.config.babel.js b/webpack.config.babel.js index ee1a8f7..cf410c5 100644 --- a/webpack.config.babel.js +++ b/webpack.config.babel.js @@ -4,9 +4,8 @@ import MiniCssExtractPlugin from 'mini-css-extract-plugin'; import nodeExternals from 'webpack-node-externals'; const template = override => - Object.assign( - { - mode: process.env.NODE_ENV || 'development', + ({ + mode: process.env.NODE_ENV || 'development', resolve: { modules: [path.resolve(__dirname, 'src'), 'node_modules'], extensions: ['.ts', '.json', '.js', '.node'], @@ -15,9 +14,8 @@ const template = override => stats: { colors: true, }, - }, - override - ); + ...override + }); const entry = (folder, file) => path.join(__dirname, 'src', folder, `${file}.ts`); diff --git a/yarn.lock b/yarn.lock index 962fded..93a4328 100644 --- a/yarn.lock +++ b/yarn.lock @@ -756,6 +756,11 @@ dependencies: "@types/node" "*" +"@types/eslint-visitor-keys@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" + integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== + "@types/events@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" @@ -801,6 +806,11 @@ dependencies: "@types/express" "*" +"@types/json-schema@^7.0.3": + version "7.0.3" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636" + integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A== + "@types/lodash@^4.14.138": version "4.14.138" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.138.tgz#34f52640d7358230308344e579c15b378d91989e" @@ -882,6 +892,47 @@ dependencies: "@types/yargs-parser" "*" +"@typescript-eslint/eslint-plugin@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.5.0.tgz#101d96743ce3365b3223df73d641078c9b775903" + integrity sha512-ddrJZxp5ns1Lh5ofZQYk3P8RyvKfyz/VcRR4ZiJLHO/ljnQAO8YvTfj268+WJOOadn99mvDiqJA65+HAKoeSPA== + dependencies: + "@typescript-eslint/experimental-utils" "2.5.0" + eslint-utils "^1.4.2" + functional-red-black-tree "^1.0.1" + regexpp "^2.0.1" + tsutils "^3.17.1" + +"@typescript-eslint/experimental-utils@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.5.0.tgz#383a97ded9a7940e5053449f6d73995e782b8fb1" + integrity sha512-UgcQGE0GKJVChyRuN1CWqDW8Pnu7+mVst0aWrhiyuUD1J9c+h8woBdT4XddCvhcXDodTDVIfE3DzGHVjp7tUeQ== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/typescript-estree" "2.5.0" + eslint-scope "^5.0.0" + +"@typescript-eslint/parser@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.5.0.tgz#858030ddd808fbbe88e03f42e5971efaccb8218a" + integrity sha512-9UBMiAwIDWSl79UyogaBdj3hidzv6exjKUx60OuZuFnJf56tq/UMpdPcX09YmGqE8f4AnAueYtBxV8IcAT3jdQ== + dependencies: + "@types/eslint-visitor-keys" "^1.0.0" + "@typescript-eslint/experimental-utils" "2.5.0" + "@typescript-eslint/typescript-estree" "2.5.0" + eslint-visitor-keys "^1.1.0" + +"@typescript-eslint/typescript-estree@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.5.0.tgz#40ada624d6217ef092a3a79ed30d947ad4f212ce" + integrity sha512-AXURyF8NcA3IsnbjNX1v9qbwa0dDoY9YPcKYR2utvMHoUcu3636zrz0gRWtVAyxbPCkhyKuGg6WZIyi2Fc79CA== + dependencies: + debug "^4.1.1" + glob "^7.1.4" + is-glob "^4.0.1" + lodash.unescape "4.0.1" + semver "^6.3.0" + "@webassemblyjs/ast@1.8.5": version "1.8.5" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" @@ -1051,20 +1102,20 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" -acorn-jsx@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.2.tgz#84b68ea44b373c4f8686023a551f61a21b7c4a4f" - integrity sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw== +acorn-jsx@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" + integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== acorn@^6.2.1: version "6.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== -acorn@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.0.0.tgz#26b8d1cd9a9b700350b71c0905546f64d1284e7a" - integrity sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ== +acorn@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" + integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ== after@0.8.2: version "0.8.2" @@ -2667,7 +2718,7 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -eslint-config-airbnb-base@^14.0.0: +eslint-config-airbnb-base@14.0.0: version "14.0.0" resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.0.0.tgz#8a7bcb9643d13c55df4dd7444f138bf4efa61e17" integrity sha512-2IDHobw97upExLmsebhtfoD3NAKhV4H0CJWP3Uprd/uk+cHuWYOczPVxQ8PxLFUAw7o3Th1RAU8u1DoUpr+cMA== @@ -2676,10 +2727,10 @@ eslint-config-airbnb-base@^14.0.0: object.assign "^4.1.0" object.entries "^1.1.0" -eslint-config-prettier@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.2.0.tgz#80e0b8714e3f6868c4ac2a25fbf39c02e73527a7" - integrity sha512-VLsgK/D+S/FEsda7Um1+N8FThec6LqE3vhcMyp8mlmto97y3fGf3DX7byJexGuOb1QY0Z/zz222U5t+xSfcZDQ== +eslint-config-prettier@^6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.4.0.tgz#0a04f147e31d33c6c161b2dd0971418ac52d0477" + integrity sha512-YrKucoFdc7SEko5Sxe4r6ixqXPDP1tunGw91POeZTTRKItf/AMFYt/YLEQtZMkR2LVpAVhcAcZgcWpm1oGPW7w== dependencies: get-stdin "^6.0.0" @@ -2723,15 +2774,7 @@ eslint-plugin-prettier@^3.1.0: dependencies: prettier-linter-helpers "^1.0.0" -eslint-plugin-typescript@^1.0.0-rc.1: - version "1.0.0-rc.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-typescript/-/eslint-plugin-typescript-1.0.0-rc.3.tgz#aa5359248dc6172ee261bc6574b5b540573e9b67" - integrity sha512-urXH7sKqRkFLcDj6dP3tvQALfWIRGn8J8Kg9dYSoavXvy62FxfUv6JgjDAHQZudi9fSRQpEZA/LqdJXDOwKHPA== - dependencies: - requireindex "^1.2.0" - typescript-eslint-parser "21.0.2" - -eslint-scope@^4.0.0, eslint-scope@^4.0.3: +eslint-scope@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== @@ -2747,6 +2790,13 @@ eslint-scope@^5.0.0: esrecurse "^4.1.0" estraverse "^4.1.1" +eslint-utils@^1.3.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" + integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== + dependencies: + eslint-visitor-keys "^1.1.0" + eslint-utils@^1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab" @@ -2759,10 +2809,10 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== -eslint@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.3.0.tgz#1f1a902f67bfd4c354e7288b81e40654d927eb6a" - integrity sha512-ZvZTKaqDue+N8Y9g0kp6UPZtS4FSY3qARxBs7p4f0H0iof381XHduqVerFWtK8DPtKmemqbqCFENWSQgPR/Gow== +eslint@6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.1.0.tgz#06438a4a278b1d84fb107d24eaaa35471986e646" + integrity sha512-QhrbdRD7ofuV09IuE2ySWBz0FyXCq0rriLTZXZqaWSI79CVtHVRdkFuFTViiqzZhkCgfOh9USpriuGN2gIpZDQ== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" @@ -2771,9 +2821,9 @@ eslint@^6.3.0: debug "^4.0.1" doctrine "^3.0.0" eslint-scope "^5.0.0" - eslint-utils "^1.4.2" - eslint-visitor-keys "^1.1.0" - espree "^6.1.1" + eslint-utils "^1.3.1" + eslint-visitor-keys "^1.0.0" + espree "^6.0.0" esquery "^1.0.1" esutils "^2.0.2" file-entry-cache "^5.0.1" @@ -2802,13 +2852,13 @@ eslint@^6.3.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.1.tgz#7f80e5f7257fc47db450022d723e356daeb1e5de" - integrity sha512-EYbr8XZUhWbYCqQRW0duU5LxzL5bETN6AjKBGy1302qqzPaCH10QbRg3Wvco79Z8x9WbiE8HYB4e75xl6qUYvQ== +espree@^6.0.0: + version "6.1.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" + integrity sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA== dependencies: - acorn "^7.0.0" - acorn-jsx "^5.0.2" + acorn "^7.1.0" + acorn-jsx "^5.1.0" eslint-visitor-keys "^1.1.0" esprima@^4.0.0: @@ -6208,11 +6258,6 @@ require-package-name@^2.0.1: resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9" integrity sha1-wR6XJ2tluOKSP3Xav1+y7ww4Qbk= -requireindex@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.2.0.tgz#3463cdb22ee151902635aa6c9535d4de9c2ef1ef" - integrity sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww== - resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" @@ -6423,11 +6468,6 @@ semver-diff@^2.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" - integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== - semver@^6.1.2, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" @@ -7203,11 +7243,18 @@ triple-beam@^1.2.0, triple-beam@^1.3.0: dependencies: glob "^7.1.2" -tslib@^1.9.0: +tslib@^1.8.1, tslib@^1.9.0: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== +tsutils@^3.17.1: + version "3.17.1" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" + integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== + dependencies: + tslib "^1.8.1" + tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" @@ -7250,23 +7297,6 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript-eslint-parser@21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/typescript-eslint-parser/-/typescript-eslint-parser-21.0.2.tgz#270af10e4724528677fbcf34ea495284bec3a894" - integrity sha512-u+pj4RVJBr4eTzj0n5npoXD/oRthvfUCjSKndhNI714MG0mQq2DJw5WP7qmonRNIFgmZuvdDOH3BHm9iOjIAfg== - dependencies: - eslint-scope "^4.0.0" - eslint-visitor-keys "^1.0.0" - typescript-estree "5.3.0" - -typescript-estree@5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/typescript-estree/-/typescript-estree-5.3.0.tgz#fb6c977b5e21073eb16cbdc0338a7f752da99ff5" - integrity sha512-Vu0KmYdSCkpae+J48wsFC1ti19Hq3Wi/lODUaE+uesc3gzqhWbZ5itWbsjylLVbjNW4K41RqDzSfnaYNbmEiMQ== - dependencies: - lodash.unescape "4.0.1" - semver "5.5.0" - typescript@~3.6.2: version "3.6.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.2.tgz#105b0f1934119dde543ac8eb71af3a91009efe54" From ccb31f0e765efe9f7760394ac2bb08637fd14f43 Mon Sep 17 00:00:00 2001 From: butlerx Date: Mon, 21 Oct 2019 20:04:16 +0100 Subject: [PATCH 3/8] update rebase action --- .github/workflows/rebase.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rebase.yml b/.github/workflows/rebase.yml index 2ab53a2..d5f83ca 100644 --- a/.github/workflows/rebase.yml +++ b/.github/workflows/rebase.yml @@ -1,13 +1,16 @@ --- name: Automatic Rebase -on: issue_comment +on: + issue_comment: + types: [created] jobs: rebase: name: Rebase + if: contains(github.event.comment.body, '/rebase') runs-on: ubuntu-latest steps: - uses: actions/checkout@master - name: Automatic Rebase - uses: cirrus-actions/rebase@1.0 + uses: cirrus-actions/rebase@master env: GITHUB_TOKEN: ${{ secrets.node_github_token }} From a337d78571da33f6452b3d4457e013a8d52329cf Mon Sep 17 00:00:00 2001 From: butlerx Date: Mon, 21 Oct 2019 20:18:13 +0100 Subject: [PATCH 4/8] tag ssh container --- docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.yml b/docker-compose.yml index 28b21eb..a1ea398 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -32,6 +32,7 @@ services: build: context: . dockerfile: Dockerfile-ssh + image: butlerx/wetty:ssh container_name: 'wetty-ssh' networks: From 651d4ff23cdd143e41d88c728bb60cf861cda6c1 Mon Sep 17 00:00:00 2001 From: butlerx Date: Mon, 21 Oct 2019 20:42:37 +0100 Subject: [PATCH 5/8] update docs --- docs/API.md | 109 ++++++++++++++++++--------------------- src/server/index.ts | 3 +- src/server/interfaces.ts | 1 + src/server/wetty.ts | 8 ++- 4 files changed, 60 insertions(+), 61 deletions(-) diff --git a/docs/API.md b/docs/API.md index d767747..c789771 100644 --- a/docs/API.md +++ b/docs/API.md @@ -1,93 +1,86 @@ - - ## WeTTy Create WeTTY server -* [WeTTy](#module_WeTTy) - * [~start](#module_WeTTy..start) ⇒ Promise - * ["connection"](#event_connection) - * ["spawn"](#event_spawn) - * ["exit"](#event_exit) - * ["disconnect"](#event_disconnect) - * ["server"](#event_server) - - +- [WeTTy](#module_WeTTy) + - [start](#module_WeTTy..start) ⇒ `Promise` + - [connection](#event_connection) + - [spawn](#event_spawn) + - [exit](#event_exit) + - [disconnect](#event_disconnect) + - [server](#event_server) -### WeTTy~start ⇒ Promise +### WeTTy.start ⇒ `Promise` Starts WeTTy Server -**Kind**: inner property of [WeTTy](#module_WeTTy) -**Returns**: Promise - Promise resolves once server is running - -| Param | Type | Default | Description | -| ------------ | ------------------- | ------------------------------------- | --------------------------- | -| [ssh] | Object | | SSH settings | -| [ssh.user] | string | "''" | default user for ssh | -| [ssh.host] | string | "localhost" | machine to ssh too | -| [ssh.auth] | string | "password" | authtype to use | -| [ssh.port] | number | 22 | port to connect to over ssh | -| [serverPort] | number | 3000 | Port to run server on | -| [ssl] | Object | | SSL settings | -| [ssl.key] | string | | Path to ssl key | -| [ssl.cert] | string | | Path to ssl cert | - - +**Kind**: inner property of [`WeTTy`](#module_WeTTy) +**Returns**: `Promise` - Promise resolves once server is running + +| Param | Type | Default | Description | +| :------------------------ | --------- | ------------- | ---------------------------------------------------------------------------------------------------------------------- | +| [ssh] | `Object` | | SSH settings | +| [ssh.user] | `string` | `"''"` | default user for ssh | +| [ssh.host] | `string` | `"localhost"` | machine to ssh too | +| [ssh.auth] | `string` | `"password"` | authtype to use | +| [ssh.port] | `number` | `22` | port to connect to over ssh | +| [serverConf] | `Object` | | Server settings | +| [serverConf.base] | `Object` | `'/wetty/'` | Server settings | +| [serverConf.port] | `number` | `3000` | Port to run server on | +| [serverConf.host] | `string` | `'0.0.0.0'` | Host address for server | +| [serverConf.title] | `string` | `'WeTTy'` | Title of the server | +| [serverConf.bypasshelmet] | `boolean` | `false` | if helmet should be disabled on the sever | +| [command] | `string` | `"''"` | The command to execute. If running as root and no host specified this will be login if a host is specified will be ssh | +| [ssl] | `Object` | | SSL settings | +| [ssl.key] | `string` | | Path to ssl key | +| [ssl.cert] | `string` | | Path to ssl cert | ### "connection" -**Kind**: event emitted by [WeTTy](#module_WeTTy) +**Kind**: event emitted by [`WeTTy`](#module_WeTTy) **Properties** -| Name | Type | Description | -| ---- | ------------------- | --------------------------- | -| msg | string | Message for logs | -| date | Date | date and time of connection | - - +| Name | Type | Description | +| ---- | -------- | --------------------------- | +| msg | `string` | Message for logs | +| date | `Date` | date and time of connection | ### "spawn" Terminal process spawned -**Kind**: event emitted by [WeTTy](#module_WeTTy) +**Kind**: event emitted by [`WeTTy`](#module_WeTTy) **Properties** -| Name | Type | Description | -| ------- | ------------------- | -------------------------------------- | -| msg | string | Message containing pid info and status | -| pid | number | Pid of the terminal | -| address | string | address of connecting user | - - +| Name | Type | Description | +| ------- | -------- | -------------------------------------- | +| msg | `string` | Message containing pid info and status | +| pid | `number` | Pid of the terminal | +| address | `string` | address of connecting user | ### "exit" Terminal process exits -**Kind**: event emitted by [WeTTy](#module_WeTTy) +**Kind**: event emitted by [`WeTTy`](#module_WeTTy) **Properties** -| Name | Type | Description | -| ---- | ------------------- | -------------------------------------- | -| code | number | the exit code | -| msg | string | Message containing pid info and status | - - +| Name | Type | Description | +| ---- | -------- | -------------------------------------- | +| code | `number` | the exit code | +| msg | `string` | Message containing pid info and status | ### "disconnect" -**Kind**: event emitted by [WeTTy](#module_WeTTy) - +**Kind**: event emitted by [`WeTTy`](#module_WeTTy) ### "server" -**Kind**: event emitted by [WeTTy](#module_WeTTy) +**Kind**: event emitted by [`WeTTy`](#module_WeTTy) **Properties** -| Name | Type | Description | -| ---------- | ------------------- | ------------------------------- | -| msg | string | Message for logging | -| port | number | port sever is on | -| connection | string | connection type for web traffic | +| Name | Type | Description | +| ---------- | -------- | ------------------------------- | +| msg | `string` | Message for logging | +| port | `number` | port sever is on | +| connection | `string` | connection type for web traffic | diff --git a/src/server/index.ts b/src/server/index.ts index 408fe4c..65e54ae 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -58,11 +58,10 @@ export default class Server { host: sshhost, auth: sshauth, port: sshport, - title, pass: sshpass, key: sshkey, }, - { base, host, port, title, bypasshelmet }, + { base, host, port, title, bypasshelmet}, command, { key: sslkey, cert: sslcert } ); diff --git a/src/server/interfaces.ts b/src/server/interfaces.ts index 05b391c..89d8172 100644 --- a/src/server/interfaces.ts +++ b/src/server/interfaces.ts @@ -20,6 +20,7 @@ export interface SSLBuffer { export interface Server { port: number; host: string; + title: string; base: string; bypasshelmet: boolean; } diff --git a/src/server/wetty.ts b/src/server/wetty.ts index 6bacd86..9eab321 100644 --- a/src/server/wetty.ts +++ b/src/server/wetty.ts @@ -16,7 +16,13 @@ export default class WeTTy extends EventEmitter { */ public start( ssh: SSH = { user: '', host: 'localhost', auth: 'password', port: 22 }, - serverConf: Server = { base: '/wetty/', port: 3000, host: '0.0.0.0' }, + serverConf: Server = { + base: '/wetty/', + port: 3000, + host: '0.0.0.0', + title: 'WeTTy', + bypasshelmet: false, + }, command = '', ssl?: SSL ): Promise { From d1584354d53b67cf39f0e659ae9fc92cbdc82f90 Mon Sep 17 00:00:00 2001 From: butlerx Date: Mon, 21 Oct 2019 20:46:05 +0100 Subject: [PATCH 6/8] Fix #202, check if ssl is defined --- package.json | 2 +- src/server/ssl.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 04abe44..b84f84d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wetty", - "version": "1.1.6", + "version": "1.1.7", "description": "WeTTY = Web + TTY. Terminal access in browser over http/https", "homepage": "https://github.com/krishnasrinivas/wetty", "repository": { diff --git a/src/server/ssl.ts b/src/server/ssl.ts index 1ab223d..958185b 100644 --- a/src/server/ssl.ts +++ b/src/server/ssl.ts @@ -4,7 +4,7 @@ import { isUndefined } from 'lodash'; import { SSL, SSLBuffer } from './interfaces'; export default async function loadSSL(ssl: SSL): Promise { - if (isUndefined(ssl.key) || isUndefined(ssl.cert)) return {}; + if (isUndefined(ssl) || isUndefined(ssl.key) || isUndefined(ssl.cert)) return {}; const files = [readFile(resolve(ssl.key)), readFile(resolve(ssl.cert))]; const [key, cert]: Buffer[] = await Promise.all(files); return { key, cert }; From eec9862fece795cd4e247c3a4af37d5ce180fba5 Mon Sep 17 00:00:00 2001 From: butlerx Date: Mon, 21 Oct 2019 20:51:53 +0100 Subject: [PATCH 7/8] Fix #203, update docs with uptodate args --- docs/API.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/API.md b/docs/API.md index c789771..89bc3b1 100644 --- a/docs/API.md +++ b/docs/API.md @@ -24,6 +24,8 @@ Starts WeTTy Server | [ssh.host] | `string` | `"localhost"` | machine to ssh too | | [ssh.auth] | `string` | `"password"` | authtype to use | | [ssh.port] | `number` | `22` | port to connect to over ssh | +| [ssh.pass] | `string` | | Optional param of a password to use for ssh | +| [ssh.key] | `string` | | path to an optional client private key (connection will be password-less and insecure!) | | [serverConf] | `Object` | | Server settings | | [serverConf.base] | `Object` | `'/wetty/'` | Server settings | | [serverConf.port] | `number` | `3000` | Port to run server on | From 11f715e1b0b5faf4bb6ecdb5543051517a9c6333 Mon Sep 17 00:00:00 2001 From: Ben Letchford Date: Tue, 22 Oct 2019 15:46:24 +1100 Subject: [PATCH 8/8] Downloading of files via wetty terminal (#206) * Feature for download of files via Blob * Document file download feature and bump version. --- README.md | 29 ++++++++++++++++ package.json | 7 ++-- src/client/index.ts | 78 ++++++++++++++++++++++++++++++++++++++++++- src/client/wetty.scss | 6 ++++ yarn.lock | 10 ++++++ 5 files changed, 127 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5c13055..414a8ce 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,35 @@ the user like this (Only while running wetty as a non root account): This is not a required feature and the security implications for passing the password in the url will have to be considered by the user +### File Downloading + +Wetty supports file downloads by printing terminal escape sequences between a +base64 encoded file. + +The terminal escape sequences used are `^[[5i` and `^[[4i` (VT100 for "enter +auto print" and "exit auto print" respectively - +https://vt100.net/docs/tp83/appendixc.html). + +An example of a helper script that prints the terminal escape characters and +base64s stdin: + +``` +$ cat wetty-download.sh +#!/bin/sh +echo '^[[5i'$(cat /dev/stdin | base64)'^[[4i' +``` + +You are then able to download files via wetty! + +``` +$ cat my-pdf-file.pdf | ./wetty-download.sh +``` + +Wetty will then issue a popup like the following that links to a local file +blob: + +`Download ready: file-20191015233654.pdf` + ## Run wetty behind nginx or apache As said earlier you can use a proxy to add https to WeTTy. diff --git a/package.json b/package.json index b84f84d..82ea695 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wetty", - "version": "1.1.7", + "version": "1.1.8", "description": "WeTTY = Web + TTY. Terminal access in browser over http/https", "homepage": "https://github.com/krishnasrinivas/wetty", "repository": { @@ -51,6 +51,7 @@ "dependencies": { "compression": "^1.7.4", "express": "^4.17.1", + "file-type": "^12.3.0", "fs-extra": "^8.1.0", "helmet": "^3.20.1", "lodash": "^4.17.15", @@ -60,6 +61,7 @@ "socket.io": "^2.2.0", "socket.io-client": "^2.2.0", "source-map-loader": "^0.2.4", + "toastify-js": "^1.6.1", "winston": "^3.2.1", "xterm": "^3.14.5", "yargs": "^14.0.0" @@ -126,6 +128,7 @@ "Strubbl ", "koushikmln ", "mirtouf ", - "nosemeocurrenada " + "nosemeocurrenada ", + "Ben Letchford " ] } diff --git a/src/client/index.ts b/src/client/index.ts index bd879eb..f8afcce 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -2,6 +2,8 @@ import { Terminal } from 'xterm'; import { isUndefined } from 'lodash'; import * as io from 'socket.io-client'; import { fit } from 'xterm/lib/addons/fit/fit'; +import * as fileType from 'file-type'; +import Toastify from 'toastify-js'; import './wetty.scss'; import './favicon.ico'; @@ -12,8 +14,12 @@ const socket = io(window.location.origin, { path: `${trim(socketBase)}/socket.io`, }); +const FILE_BEGIN = '\u001b[5i'; +const FILE_END = '\u001b[4i'; + socket.on('connect', () => { const term = new Terminal(); + let fileBuffer = []; term.open(document.getElementById('terminal')); const defaultOptions = { fontSize: 14 }; let options: object; @@ -82,6 +88,52 @@ socket.on('connect', () => { disconnect(data); } + function onCompleteFile() { + let bufferCharacters = fileBuffer.join(''); + bufferCharacters = bufferCharacters.substring(bufferCharacters.lastIndexOf(FILE_BEGIN) + FILE_BEGIN.length, bufferCharacters.lastIndexOf(FILE_END)); + + // Try to decode it as base64, if it fails we assume it's not base64 + try { + bufferCharacters = window.atob(bufferCharacters); + } catch (err) { + // Assuming it's not base64... + } + + const bytes = new Uint8Array(bufferCharacters.length); + for (let i = 0; i < bufferCharacters.length; i += 1) { + bytes[i] = bufferCharacters.charCodeAt(i); + } + + let mimeType = 'application/octet-stream'; + let fileExt = ''; + const typeData = fileType(bytes); + if (typeData) { + mimeType = typeData.mime; + fileExt = typeData.ext; + } + const fileName = `file-${new Date() + .toISOString() + .split('.')[0] + .replace(/-/g, '') + .replace('T', '') + .replace(/:/g, '')}${fileExt ? `.${fileExt}` : ''}`; + + const blob = new Blob([new Uint8Array(bytes.buffer)], { type: mimeType }); + const blobUrl = URL.createObjectURL(blob); + + fileBuffer = []; + + Toastify({ + text: `Download ready: ${fileName}`, + duration: 10000, + newWindow: true, + gravity: 'bottom', + position: 'right', + backgroundColor: '#fff', + stopOnFocus: true, + }).showToast(); + } + term.on('data', data => { socket.emit('input', data); }); @@ -90,7 +142,31 @@ socket.on('connect', () => { }); socket .on('data', (data: string) => { - term.write(data); + const indexOfFileBegin = data.indexOf(FILE_BEGIN); + const indexOfFileEnd = data.indexOf(FILE_END); + + // If we've got the entire file in one chunk + if (indexOfFileBegin !== -1 && indexOfFileEnd !== -1) { + fileBuffer.push(data); + onCompleteFile(); + } + // If we've found a beginning marker + else if (indexOfFileBegin !== -1) { + fileBuffer.push(data); + } + // If we've found an ending marker + else if (indexOfFileEnd !== -1) { + fileBuffer.push(data); + onCompleteFile(); + } + // If we've found the continuation of a file + else if (fileBuffer.length > 0) { + fileBuffer.push(data); + } + // Just treat it as normal data + else { + term.write(data); + } }) .on('login', () => { term.writeln(''); diff --git a/src/client/wetty.scss b/src/client/wetty.scss index c8ae18c..aa5816a 100644 --- a/src/client/wetty.scss +++ b/src/client/wetty.scss @@ -1,4 +1,5 @@ @import '~xterm/dist/xterm'; +@import '~toastify-js/src/toastify.css'; $black: #000; $grey: rgba(0, 0, 0, 0.75); @@ -94,4 +95,9 @@ body { display: flex; } } + + .toastify { + border-radius: 0; + color: $black; + } } diff --git a/yarn.lock b/yarn.lock index 93a4328..99316e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3152,6 +3152,11 @@ file-loader@^4.2.0: loader-utils "^1.2.3" schema-utils "^2.0.0" +file-type@^12.3.0: + version "12.3.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-12.3.0.tgz#74d755e5dc9c5cbc7ee6f182529b453906ac88c2" + integrity sha512-4E4Esq9KLwjYCY32E7qSmd0h7LefcniZHX+XcdJ4Wfx1uGJX7QCigiqw/U0yT7WOslm28yhxl87DJ0wHYv0RAA== + fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -7196,6 +7201,11 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" +toastify-js@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/toastify-js/-/toastify-js-1.6.1.tgz#2ec20654925d6f83f935d5a6907c146e6bcb67d6" + integrity sha512-yosiXPEdr3B9KL1rF7M/IMdw8d8Z69UJe2JsvxbfdpaL2/olqSB8tvp7/N6gkT9G46y6nqR2e62CCnf0LxeIBQ== + toidentifier@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"