├── README.md ├── examples ├── 01-events.js ├── 02.1-readableStream.js ├── 02.2-read-iterators.js ├── 02.3-redableStream.js ├── 03.writableStream.js ├── 04.1-piping.js ├── 04.2-piping │ ├── index.js │ ├── package-lock.json │ ├── package.json │ └── test.csv ├── 05-childProcess.js ├── 0x-readStream.js ├── logger.log └── test.csv ├── notes.txt └── remote-access-app ├── .gitignore ├── .gitmodules ├── README.md ├── client ├── Procfile ├── deps │ └── socket.io.slim.js ├── index.html ├── package-lock.json ├── package.json ├── resources │ ├── bootstrap.min.css │ └── desktop.png ├── sharer │ ├── app.js │ ├── index.html │ └── screen.js └── watcher │ ├── app.js │ └── index.html └── server ├── index.html ├── package-lock.json ├── package.json └── server.js /README.md: -------------------------------------------------------------------------------- 1 | # talk-deep-dive-into-nodejs-streams 2 | 3 | - All code sources are in [./examples](./examples) 4 | - There's a remote app using Node.js Streams + WebRTC (plus) in [./remote-access-app](./remote-access-app) 5 | 6 | ## Event 7 | 8 | - Slides in [example](erickwendel.com) 9 | - Event link: [Geegle.us](https://geekle.us) 10 | -------------------------------------------------------------------------------- /examples/01-events.js: -------------------------------------------------------------------------------- 1 | const log = (...args) => console.log(...args) 2 | const EventEmitter = require('events') 3 | class Downloader extends EventEmitter { } 4 | 5 | const downloader = new Downloader() 6 | downloader.on('data', msg => log('msg arrived!', msg)) 7 | downloader.on('error', msg => log('error!', msg)) 8 | 9 | downloader.on('my-custom-event', msg => log('custom!', msg)) 10 | 11 | setInterval(() => { 12 | downloader.emit('my-custom-event', { message: 'Hello!' }) 13 | downloader.emit('data', 'Hey there!') 14 | }, 1000); 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/02.1-readableStream.js: -------------------------------------------------------------------------------- 1 | let counter = 0 2 | const log = (...args) => console.log(`[${++counter}]`, ...args) 3 | const { Readable } = require('stream') 4 | const readable = new Readable() 5 | 6 | readable.on("resume", _ => log(`resuming..`)) 7 | readable.on("pause", _ => log(`pausing..`)) 8 | readable.on("end", _ => log(`No more data!`)) 9 | readable.on("close", () => log(`closing..`)) 10 | 11 | readable.on("error", msg => log(`Caught error!: ${msg}`)) 12 | readable.on("data", msg => log(`Chunk read: ${msg}`)) 13 | 14 | readable.push("ping") 15 | readable.pause() 16 | readable.push("pong") 17 | readable.resume() 18 | readable.push(null) 19 | 20 | readable.emit("error", new Error('**raising error!!')) 21 | 22 | -------------------------------------------------------------------------------- /examples/02.2-read-iterators.js: -------------------------------------------------------------------------------- 1 | const { createReadStream } = require('fs') 2 | const rs = createReadStream("/dev/urandom"); 3 | 4 | ; 5 | (async () => { 6 | for await (const chunk of rs) { 7 | console.log('words:\n', chunk.toString()) 8 | } 9 | })() 10 | 11 | -------------------------------------------------------------------------------- /examples/02.3-redableStream.js: -------------------------------------------------------------------------------- 1 | const log = (...args) => console.log(...args) 2 | const { createReadStream } = require("fs"); 3 | // forcing multiple events splitting in bytes 4 | const rs = createReadStream(__filename, { highWaterMark: 100}); 5 | let eventCounter = 0 6 | rs.on("data", msg => log(`${[++eventCounter]}`, msg.toString())) 7 | -------------------------------------------------------------------------------- /examples/03.writableStream.js: -------------------------------------------------------------------------------- 1 | let counter = 0 2 | const log = (...args) => console.log(`[${++counter}]`, ...args) 3 | const { createWriteStream, promises: { readFile } } = require('fs') 4 | ;(async () => { 5 | const filename = `test.csv` 6 | const ws = createWriteStream(filename) 7 | ws.on("open", _ => log('opened!')) 8 | ws.on("close", _ => log('close!')) 9 | ws.on("drain", _ => log('drain!')) 10 | ws.on("finish", _ => log('finished!')) 11 | ws.on("error", (error) => log('error!', error.toString())) 12 | 13 | ws.write('name,age\n') 14 | ws.write(`Erick,25\n`) 15 | ws.write(`Mary,20\n`) 16 | ws.write(`Jose,30\n`) 17 | ws.emit('error', new Error('raising error!')) 18 | ws.end("Footer: I'm done bro") 19 | 20 | log(`\n${(await readFile(filename)).toString()}`) 21 | })() 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /examples/04.1-piping.js: -------------------------------------------------------------------------------- 1 | // process.stdin.pipe(process.stdout) 2 | 3 | const { Transform } = require('stream') 4 | const { 5 | createWriteStream, 6 | readFileSync 7 | } = require('fs') 8 | 9 | const filename = `${__dirname}/logger.log` 10 | 11 | const mapCommands = new Transform({ 12 | transform(chunk, enc, cb) { 13 | const cmd = chunk.toString().trim() 14 | if (!cmd) return cb() 15 | 16 | const at = new Date().toISOString() 17 | const item = `cmd: ${cmd},at: ${at},\n` 18 | 19 | cb(null, item) 20 | } 21 | }) 22 | 23 | console.log('Write commands and then + C to show output') 24 | process.stdin 25 | .pipe(mapCommands) 26 | .pipe(createWriteStream(filename)) 27 | 28 | process.on("SIGINT", msg => { 29 | console.log() 30 | console.log(readFileSync(filename).toString()) 31 | process.exit(0) 32 | }) -------------------------------------------------------------------------------- /examples/04.2-piping/index.js: -------------------------------------------------------------------------------- 1 | let counter = 0 2 | const log = (...args) => console.log(`[${++counter}]`, ...args) 3 | 4 | const { createReadStream } = require('fs') 5 | const { Transform, Writable, pipeline } = require('stream') 6 | const csvtojson = require('csvtojson') 7 | 8 | const { promisify } = require('util') 9 | const pipelineAsync = promisify(pipeline) 10 | const datasource = `${__dirname}/test.csv` 11 | const currentYear = new Date().getFullYear() 12 | 13 | const mapAge = new Transform({ 14 | objectMode: true, 15 | transform: (chunk, enc, cb) => { 16 | const item = JSON.parse(chunk) 17 | const age = currentYear - item.birthYear 18 | if (age < 0) { 19 | const message = 'invalid age' 20 | const error = JSON.stringify({ message, item }) 21 | return cb(error) 22 | } 23 | 24 | const data = JSON.stringify({ 25 | name: item.name, 26 | age 27 | }) 28 | 29 | return cb(null, data) 30 | } 31 | }) 32 | 33 | const showOutput = new Writable({ 34 | write: (chunk, encoding, cb) => { 35 | const data = JSON.parse(chunk) 36 | 37 | log('name', chunk.toString()) 38 | cb() 39 | } 40 | }) 41 | 42 | 43 | createReadStream(datasource) 44 | .pipe(csvtojson()) 45 | .on("error", msg => log('csvtojson error!', msg)) 46 | 47 | .pipe(mapAge) 48 | .on("error", msg => log('mapAge error!', msg)) 49 | 50 | .pipe(showOutput) 51 | .on("error", msg => log('showOutput error!', msg)) 52 | 53 | 54 | { 55 | (async () => { 56 | try { 57 | await pipelineAsync( 58 | createReadStream(datasource), 59 | csvtojson(), 60 | mapAge, 61 | showOutput, 62 | ) 63 | console.log('finished!') 64 | } catch (error) { 65 | log('error on pipeline!', error) 66 | } 67 | 68 | })() 69 | } 70 | -------------------------------------------------------------------------------- /examples/04.2-piping/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "04.2-piping", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "bluebird": { 8 | "version": "3.7.2", 9 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", 10 | "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" 11 | }, 12 | "csvtojson": { 13 | "version": "2.0.10", 14 | "resolved": "https://registry.npmjs.org/csvtojson/-/csvtojson-2.0.10.tgz", 15 | "integrity": "sha512-lUWFxGKyhraKCW8Qghz6Z0f2l/PqB1W3AO0HKJzGIQ5JRSlR651ekJDiGJbBT4sRNNv5ddnSGVEnsxP9XRCVpQ==", 16 | "requires": { 17 | "bluebird": "^3.5.1", 18 | "lodash": "^4.17.3", 19 | "strip-bom": "^2.0.0" 20 | } 21 | }, 22 | "is-utf8": { 23 | "version": "0.2.1", 24 | "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", 25 | "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" 26 | }, 27 | "lodash": { 28 | "version": "4.17.15", 29 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 30 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" 31 | }, 32 | "strip-bom": { 33 | "version": "2.0.0", 34 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", 35 | "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", 36 | "requires": { 37 | "is-utf8": "^0.2.0" 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /examples/04.2-piping/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "04.2-piping", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "csvtojson": "^2.0.10" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/04.2-piping/test.csv: -------------------------------------------------------------------------------- 1 | name,birthYear 2 | Erick,1995 3 | Mary,1970 4 | Ana,2021 5 | Jose,1965 -------------------------------------------------------------------------------- /examples/05-childProcess.js: -------------------------------------------------------------------------------- 1 | 2 | "use strict"; 3 | const { promisify } = require('util') 4 | const { pipeline: pipeSync } = require('stream') 5 | const pipeline = promisify(pipeSync) 6 | 7 | const { spawn } = require("child_process"); 8 | const subprocess = spawn( 9 | "sh", 10 | [ 11 | "-c", 12 | ` 13 | node -e "setInterval(() => { 14 | console.log(process.pid) 15 | }, 500);" 16 | ` 17 | ], 18 | { 19 | stdio: "pipe", 20 | } 21 | ); 22 | 23 | 24 | pipeline( 25 | subprocess.stdout, 26 | async function* (source) { 27 | for await (const chunk of source) { 28 | console.log('chunk', chunk.toString()) 29 | yield chunk 30 | } 31 | } 32 | ).catch(err => console.log('error', err)) 33 | 34 | setTimeout(() => { 35 | subprocess.kill(); // Does not terminate the Node.js process in the shell. 36 | }, 2000); -------------------------------------------------------------------------------- /examples/0x-readStream.js: -------------------------------------------------------------------------------- 1 | const { Duplex } = require('stream') 2 | let counter = 0 3 | const dp = new Duplex({ 4 | write(c, e, cb) { 5 | console.log('c', c.toString()) 6 | cb(null, c) 7 | }, 8 | // called on creation! 9 | read(size) { 10 | console.log('called!', size) 11 | 12 | // this.push(`${++counter}`) 13 | // if (counter > 10) 14 | // this.push(null) 15 | } 16 | }) 17 | 18 | dp.on("data", msg => console.log('msg', msg.toString())) 19 | // dp.push("1") 20 | // dp.push("2") 21 | // dp.push(null) 22 | 23 | dp.write("avc") 24 | dp.write("acc") 25 | 26 | dpc.pipe((dest) => dest1 => { 27 | console.log('called!!') 28 | }) -------------------------------------------------------------------------------- /examples/logger.log: -------------------------------------------------------------------------------- 1 | cmd: git clone,at: 2020-05-23T23:51:55.422Z, 2 | cmd: git status,at: 2020-05-23T23:51:57.829Z, 3 | cmd: echo 'hey dude',at: 2020-05-23T23:52:01.339Z, 4 | cmd: test,at: 2020-05-23T23:52:02.577Z, 5 | -------------------------------------------------------------------------------- /examples/test.csv: -------------------------------------------------------------------------------- 1 | name,age 2 | Erick,25 3 | Mary,20 4 | Jose,30 5 | Footer: I'm done bro -------------------------------------------------------------------------------- /notes.txt: -------------------------------------------------------------------------------- 1 | What 2 | Why 3 | Where 4 | How 5 | 6 | 7 | - Deep Dive on Node.js Streams 8 | 9 | - Problem 10 | single thread 11 | - vs traditional approach 12 | - axios.get ... wait download 05 gb 13 | - process on file 14 | - remove file 15 | -> time to feedback 16 | -> storage 17 | -> memory usage 18 | 19 | high volume of data 20 | events 21 | error handling 22 | 23 | What 24 | 25 | - Node.js has Streams since v0 26 | - Created to upload videos feature 27 | Concepts: 28 | - Event emitter class 29 | -> on.data 30 | -> on.error 31 | 32 | - Divided in categories: 33 | - Readable Streams 34 | -> read from a source and emit new events 35 | -> read a file and emit each chunk 36 | 37 | - Writable Streams 38 | -> output, such as new file or redirect to other stream 39 | - Duplex Streams 40 | -> Readable events table 41 | -> Writable events table 42 | -> produces the both events 43 | -> differences 44 | 45 | - Transform Streams 46 | -> change each chunk 47 | When 48 | on-demand processing 49 | If you need to handle large files 50 | If you need to handle videos on demand 51 | If you need to download and process on demand 52 | If you need to handle large events 53 | - team viewer 54 | .. to process data on demand in general 55 | - many automated processes running in the machine building reports 56 | - emit events to each other 57 | 58 | How 59 | 60 | Simple example of a readable stream pipe to writable 61 | - animation on events of readable 62 | - animation on events of writable 63 | Controlling streams flow 64 | - resume, pause stop and push null 65 | https://github.com/ErickWendel/nodejs-certification/blob/master/draft/index8.js (this) 66 | https://github.com/ErickWendel/nodejs-certification/blob/master/draft/index16.js (r) 67 | https://github.com/ErickWendel/nodejs-certification/blob/master/draft/index7.js (pause, resume) 68 | Iterators 69 | for await.. 70 | 71 | Piping 72 | = examples using normal pipe 73 | - process.stdin.pipe().pipe(process.stdout) 74 | However, notice there are no proper error handlers attached. If a chunk of data were to fail to be properly received, the Readable source or gzip stream will not be destroyed. 75 | 76 | = customizing pipe function 77 | = examples using Pipeline from node 78 | = only pipe a readable stream 79 | show csvToJSON 80 | 81 | Using child_processes 82 | avoid running in node.js main thread 83 | https://github.com/ErickWendel/nodejs-certification/blob/master/draft/examples/get-data-from-child.js 84 | Donwloading large data (kaggle) 85 | -> show show to download data with percentil 86 | 87 | Promises vs Streams 88 | promises hapens once 89 | bad practice 90 | new Promise(r -> ev.on('data') => ) 91 | Back pressure 92 | - DEBUG=* -> find streams debugger 93 | mechanism to handle high data volume 94 | 95 | more in 96 | https://nodejs.org/es/docs/guides/backpressuring-in-streams/#lifecycle-of-pipe 97 | get image 98 | 99 | If the consumer is unable to consume data as fast as the producer can produce it, then the producer will be paused until the consumer catches up. 100 | Node 14 101 | - calls destroy after finishing by default 102 | -> show video using node 11 and node 14 103 | 104 | Conclusion 105 | Node.js streams are beautiful, try it out 106 | 107 | 108 | 109 | https://giphy.com 110 | https://www.electronjs.org/docs/api/desktop-capturer 111 | https://nodejs.org/es/docs/guides/backpressuring-in-streams/#lifecycle-of-pipe 112 | https://github.com/ErickWendel/nodejs-certification/blob/master/draft/index9.js 113 | https://devhints.io/nodejs-stream 114 | https://github.com/substack/stream-handbook 115 | 116 | https://s3.amazonaws.com/four.livejournal/20091117/jsconf.pdf 117 | https://nodejs.org/docs/ 118 | https://nodejs.org/docs/v0.1.100/api.html 119 | https://medium.com/autodesk-tlv/streams-in-depth-in-node-js-c8cc7f1eb0d6 120 | http://codewinds.com/blog/2013-08-31-nodejs-duplex-streams.html#what_is_a_duplex_stream_ 121 | https://stackoverflow.com/questions/18335499/nodejs-whats-the-difference-between-a-duplex-stream-and-a-transform-stream 122 | https://nodejs.org/api/stream.html 123 | -------------------------------------------------------------------------------- /remote-access-app/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | saved_recordings -------------------------------------------------------------------------------- /remote-access-app/.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "server-remote-viewer"] 2 | path = server-remote-viewer 3 | url = https://git.heroku.com/server-remote-viewer.git 4 | [submodule "app-remote-viewer"] 5 | path = app-remote-viewer 6 | url = https://git.heroku.com/app-remote-viewer.git 7 | -------------------------------------------------------------------------------- /remote-access-app/README.md: -------------------------------------------------------------------------------- 1 | # remote access app using WebRTC 2 | 3 | ## Starting 4 | 5 | - You'll find the front end in /app. There are two projects in which; 6 | 7 | 1. watcher: app for receiving incoming video, audio and screen 8 | 2. sharer: app for sharing video, audio and screen 9 | 10 | - On `server` folder, you'll run it to start websocket server i which is responsible to delegate incoming connections 11 | 12 | ## Runing 13 | 14 | - To run, you'll need to use the socket server URL. If empty, default is `localhost:4000` 15 | -------------------------------------------------------------------------------- /remote-access-app/client/Procfile: -------------------------------------------------------------------------------- 1 | web: npm start -------------------------------------------------------------------------------- /remote-access-app/client/deps/socket.io.slim.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Socket.IO v2.3.0 3 | * (c) 2014-2019 Guillermo Rauch 4 | * Released under the MIT License. 5 | */ 6 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.io=e():t.io=e()}(this,function(){return function(t){function e(n){if(r[n])return r[n].exports;var o=r[n]={exports:{},id:n,loaded:!1};return t[n].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var r={};return e.m=t,e.c=r,e.p="",e(0)}([function(t,e,r){"use strict";function n(t,e){"object"===("undefined"==typeof t?"undefined":o(t))&&(e=t,t=void 0),e=e||{};var r,n=i(t),s=n.source,p=n.id,h=n.path,u=c[p]&&h in c[p].nsps,f=e.forceNew||e["force new connection"]||!1===e.multiplex||u;return f?r=a(s,e):(c[p]||(c[p]=a(s,e)),r=c[p]),n.query&&!e.query&&(e.query=n.query),r.socket(n.path,e)}var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=r(1),s=r(4),a=r(9);r(3)("socket.io-client");t.exports=e=n;var c=e.managers={};e.protocol=s.protocol,e.connect=n,e.Manager=r(9),e.Socket=r(33)},function(t,e,r){"use strict";function n(t,e){var r=t;e=e||"undefined"!=typeof location&&location,null==t&&(t=e.protocol+"//"+e.host),"string"==typeof t&&("/"===t.charAt(0)&&(t="/"===t.charAt(1)?e.protocol+t:e.host+t),/^(https?|wss?):\/\//.test(t)||(t="undefined"!=typeof e?e.protocol+"//"+t:"https://"+t),r=o(t)),r.port||(/^(http|ws)$/.test(r.protocol)?r.port="80":/^(http|ws)s$/.test(r.protocol)&&(r.port="443")),r.path=r.path||"/";var n=r.host.indexOf(":")!==-1,i=n?"["+r.host+"]":r.host;return r.id=r.protocol+"://"+i+":"+r.port,r.href=r.protocol+"://"+i+(e&&e.port===r.port?"":":"+r.port),r}var o=r(2);r(3)("socket.io-client:url");t.exports=n},function(t,e){var r=/^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/,n=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"];t.exports=function(t){var e=t,o=t.indexOf("["),i=t.indexOf("]");o!=-1&&i!=-1&&(t=t.substring(0,o)+t.substring(o,i).replace(/:/g,";")+t.substring(i,t.length));for(var s=r.exec(t||""),a={},c=14;c--;)a[n[c]]=s[c]||"";return o!=-1&&i!=-1&&(a.source=e,a.host=a.host.substring(1,a.host.length-1).replace(/;/g,":"),a.authority=a.authority.replace("[","").replace("]","").replace(/;/g,":"),a.ipv6uri=!0),a}},function(t,e){"use strict";t.exports=function(){return function(){}}},function(t,e,r){function n(){}function o(t){var r=""+t.type;if(e.BINARY_EVENT!==t.type&&e.BINARY_ACK!==t.type||(r+=t.attachments+"-"),t.nsp&&"/"!==t.nsp&&(r+=t.nsp+","),null!=t.id&&(r+=t.id),null!=t.data){var n=i(t.data);if(n===!1)return m;r+=n}return r}function i(t){try{return JSON.stringify(t)}catch(t){return!1}}function s(t,e){function r(t){var r=l.deconstructPacket(t),n=o(r.packet),i=r.buffers;i.unshift(n),e(i)}l.removeBlobs(t,r)}function a(){this.reconstructor=null}function c(t){var r=0,n={type:Number(t.charAt(0))};if(null==e.types[n.type])return u("unknown packet type "+n.type);if(e.BINARY_EVENT===n.type||e.BINARY_ACK===n.type){for(var o="";"-"!==t.charAt(++r)&&(o+=t.charAt(r),r!=t.length););if(o!=Number(o)||"-"!==t.charAt(r))throw new Error("Illegal attachments");n.attachments=Number(o)}if("/"===t.charAt(r+1))for(n.nsp="";++r;){var i=t.charAt(r);if(","===i)break;if(n.nsp+=i,r===t.length)break}else n.nsp="/";var s=t.charAt(r+1);if(""!==s&&Number(s)==s){for(n.id="";++r;){var i=t.charAt(r);if(null==i||Number(i)!=i){--r;break}if(n.id+=t.charAt(r),r===t.length)break}n.id=Number(n.id)}if(t.charAt(++r)){var a=p(t.substr(r)),c=a!==!1&&(n.type===e.ERROR||d(a));if(!c)return u("invalid payload");n.data=a}return n}function p(t){try{return JSON.parse(t)}catch(t){return!1}}function h(t){this.reconPack=t,this.buffers=[]}function u(t){return{type:e.ERROR,data:"parser error: "+t}}var f=(r(3)("socket.io-parser"),r(5)),l=r(6),d=r(7),y=r(8);e.protocol=4,e.types=["CONNECT","DISCONNECT","EVENT","ACK","ERROR","BINARY_EVENT","BINARY_ACK"],e.CONNECT=0,e.DISCONNECT=1,e.EVENT=2,e.ACK=3,e.ERROR=4,e.BINARY_EVENT=5,e.BINARY_ACK=6,e.Encoder=n,e.Decoder=a;var m=e.ERROR+'"encode error"';n.prototype.encode=function(t,r){if(e.BINARY_EVENT===t.type||e.BINARY_ACK===t.type)s(t,r);else{var n=o(t);r([n])}},f(a.prototype),a.prototype.add=function(t){var r;if("string"==typeof t)r=c(t),e.BINARY_EVENT===r.type||e.BINARY_ACK===r.type?(this.reconstructor=new h(r),0===this.reconstructor.reconPack.attachments&&this.emit("decoded",r)):this.emit("decoded",r);else{if(!y(t)&&!t.base64)throw new Error("Unknown type: "+t);if(!this.reconstructor)throw new Error("got binary data when not reconstructing a packet");r=this.reconstructor.takeBinaryData(t),r&&(this.reconstructor=null,this.emit("decoded",r))}},a.prototype.destroy=function(){this.reconstructor&&this.reconstructor.finishedReconstruction()},h.prototype.takeBinaryData=function(t){if(this.buffers.push(t),this.buffers.length===this.reconPack.attachments){var e=l.reconstructPacket(this.reconPack,this.buffers);return this.finishedReconstruction(),e}return null},h.prototype.finishedReconstruction=function(){this.reconPack=null,this.buffers=[]}},function(t,e,r){function n(t){if(t)return o(t)}function o(t){for(var e in n.prototype)t[e]=n.prototype[e];return t}t.exports=n,n.prototype.on=n.prototype.addEventListener=function(t,e){return this._callbacks=this._callbacks||{},(this._callbacks["$"+t]=this._callbacks["$"+t]||[]).push(e),this},n.prototype.once=function(t,e){function r(){this.off(t,r),e.apply(this,arguments)}return r.fn=e,this.on(t,r),this},n.prototype.off=n.prototype.removeListener=n.prototype.removeAllListeners=n.prototype.removeEventListener=function(t,e){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var r=this._callbacks["$"+t];if(!r)return this;if(1==arguments.length)return delete this._callbacks["$"+t],this;for(var n,o=0;o0&&!this.encoding){var t=this.packetBuffer.shift();this.packet(t)}},n.prototype.cleanup=function(){for(var t=this.subs.length,e=0;e=this._reconnectionAttempts)this.backoff.reset(),this.emitAll("reconnect_failed"),this.reconnecting=!1;else{var e=this.backoff.duration();this.reconnecting=!0;var r=setTimeout(function(){t.skipReconnect||(t.emitAll("reconnect_attempt",t.backoff.attempts),t.emitAll("reconnecting",t.backoff.attempts),t.skipReconnect||t.open(function(e){e?(t.reconnecting=!1,t.reconnect(),t.emitAll("reconnect_error",e.data)):t.onreconnect()}))},e);this.subs.push({destroy:function(){clearTimeout(r)}})}},n.prototype.onreconnect=function(){var t=this.backoff.attempts;this.reconnecting=!1,this.backoff.reset(),this.updateSocketIds(),this.emitAll("reconnect",t)}},function(t,e,r){t.exports=r(11),t.exports.parser=r(18)},function(t,e,r){function n(t,e){return this instanceof n?(e=e||{},t&&"object"==typeof t&&(e=t,t=null),t?(t=p(t),e.hostname=t.host,e.secure="https"===t.protocol||"wss"===t.protocol,e.port=t.port,t.query&&(e.query=t.query)):e.host&&(e.hostname=p(e.host).host),this.secure=null!=e.secure?e.secure:"undefined"!=typeof location&&"https:"===location.protocol,e.hostname&&!e.port&&(e.port=this.secure?"443":"80"),this.agent=e.agent||!1,this.hostname=e.hostname||("undefined"!=typeof location?location.hostname:"localhost"),this.port=e.port||("undefined"!=typeof location&&location.port?location.port:this.secure?443:80),this.query=e.query||{},"string"==typeof this.query&&(this.query=h.decode(this.query)),this.upgrade=!1!==e.upgrade,this.path=(e.path||"/engine.io").replace(/\/$/,"")+"/",this.forceJSONP=!!e.forceJSONP,this.jsonp=!1!==e.jsonp,this.forceBase64=!!e.forceBase64,this.enablesXDR=!!e.enablesXDR,this.withCredentials=!1!==e.withCredentials,this.timestampParam=e.timestampParam||"t",this.timestampRequests=e.timestampRequests,this.transports=e.transports||["polling","websocket"],this.transportOptions=e.transportOptions||{},this.readyState="",this.writeBuffer=[],this.prevBufferLen=0,this.policyPort=e.policyPort||843,this.rememberUpgrade=e.rememberUpgrade||!1,this.binaryType=null,this.onlyBinaryUpgrades=e.onlyBinaryUpgrades,this.perMessageDeflate=!1!==e.perMessageDeflate&&(e.perMessageDeflate||{}),!0===this.perMessageDeflate&&(this.perMessageDeflate={}),this.perMessageDeflate&&null==this.perMessageDeflate.threshold&&(this.perMessageDeflate.threshold=1024),this.pfx=e.pfx||null,this.key=e.key||null,this.passphrase=e.passphrase||null,this.cert=e.cert||null,this.ca=e.ca||null,this.ciphers=e.ciphers||null,this.rejectUnauthorized=void 0===e.rejectUnauthorized||e.rejectUnauthorized,this.forceNode=!!e.forceNode,this.isReactNative="undefined"!=typeof navigator&&"string"==typeof navigator.product&&"reactnative"===navigator.product.toLowerCase(),("undefined"==typeof self||this.isReactNative)&&(e.extraHeaders&&Object.keys(e.extraHeaders).length>0&&(this.extraHeaders=e.extraHeaders),e.localAddress&&(this.localAddress=e.localAddress)),this.id=null,this.upgrades=null,this.pingInterval=null,this.pingTimeout=null,this.pingIntervalTimer=null,this.pingTimeoutTimer=null,void this.open()):new n(t,e)}function o(t){var e={};for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);return e}var i=r(12),s=r(5),a=(r(3)("engine.io-client:socket"),r(32)),c=r(18),p=r(2),h=r(26);t.exports=n,n.priorWebsocketSuccess=!1,s(n.prototype),n.protocol=c.protocol,n.Socket=n,n.Transport=r(17),n.transports=r(12),n.parser=r(18),n.prototype.createTransport=function(t){var e=o(this.query);e.EIO=c.protocol,e.transport=t;var r=this.transportOptions[t]||{};this.id&&(e.sid=this.id);var n=new i[t]({query:e,socket:this,agent:r.agent||this.agent,hostname:r.hostname||this.hostname,port:r.port||this.port,secure:r.secure||this.secure,path:r.path||this.path,forceJSONP:r.forceJSONP||this.forceJSONP,jsonp:r.jsonp||this.jsonp,forceBase64:r.forceBase64||this.forceBase64,enablesXDR:r.enablesXDR||this.enablesXDR,withCredentials:r.withCredentials||this.withCredentials,timestampRequests:r.timestampRequests||this.timestampRequests,timestampParam:r.timestampParam||this.timestampParam,policyPort:r.policyPort||this.policyPort,pfx:r.pfx||this.pfx,key:r.key||this.key,passphrase:r.passphrase||this.passphrase,cert:r.cert||this.cert,ca:r.ca||this.ca,ciphers:r.ciphers||this.ciphers,rejectUnauthorized:r.rejectUnauthorized||this.rejectUnauthorized,perMessageDeflate:r.perMessageDeflate||this.perMessageDeflate,extraHeaders:r.extraHeaders||this.extraHeaders,forceNode:r.forceNode||this.forceNode,localAddress:r.localAddress||this.localAddress,requestTimeout:r.requestTimeout||this.requestTimeout,protocols:r.protocols||void 0,isReactNative:this.isReactNative});return n},n.prototype.open=function(){var t;if(this.rememberUpgrade&&n.priorWebsocketSuccess&&this.transports.indexOf("websocket")!==-1)t="websocket";else{if(0===this.transports.length){var e=this;return void setTimeout(function(){e.emit("error","No transports available")},0)}t=this.transports[0]}this.readyState="opening";try{t=this.createTransport(t)}catch(t){return this.transports.shift(),void this.open()}t.open(),this.setTransport(t)},n.prototype.setTransport=function(t){var e=this;this.transport&&this.transport.removeAllListeners(),this.transport=t,t.on("drain",function(){e.onDrain()}).on("packet",function(t){e.onPacket(t)}).on("error",function(t){e.onError(t)}).on("close",function(){e.onClose("transport close")})},n.prototype.probe=function(t){function e(){if(u.onlyBinaryUpgrades){var t=!this.supportsBinary&&u.transport.supportsBinary;h=h||t}h||(p.send([{type:"ping",data:"probe"}]),p.once("packet",function(t){if(!h)if("pong"===t.type&&"probe"===t.data){if(u.upgrading=!0,u.emit("upgrading",p),!p)return;n.priorWebsocketSuccess="websocket"===p.name,u.transport.pause(function(){h||"closed"!==u.readyState&&(c(),u.setTransport(p),p.send([{type:"upgrade"}]),u.emit("upgrade",p),p=null,u.upgrading=!1,u.flush())})}else{var e=new Error("probe error");e.transport=p.name,u.emit("upgradeError",e)}}))}function r(){h||(h=!0,c(),p.close(),p=null)}function o(t){var e=new Error("probe error: "+t);e.transport=p.name,r(),u.emit("upgradeError",e)}function i(){o("transport closed")}function s(){o("socket closed")}function a(t){p&&t.name!==p.name&&r()}function c(){p.removeListener("open",e),p.removeListener("error",o),p.removeListener("close",i),u.removeListener("close",s),u.removeListener("upgrading",a)}var p=this.createTransport(t,{probe:1}),h=!1,u=this;n.priorWebsocketSuccess=!1,p.once("open",e),p.once("error",o),p.once("close",i),this.once("close",s),this.once("upgrading",a),p.open()},n.prototype.onOpen=function(){if(this.readyState="open",n.priorWebsocketSuccess="websocket"===this.transport.name,this.emit("open"),this.flush(),"open"===this.readyState&&this.upgrade&&this.transport.pause)for(var t=0,e=this.upgrades.length;t1?{type:b[o],data:t.substring(1)}:{type:b[o]}:k}var i=new Uint8Array(t),o=i[0],s=f(t,1);return w&&"blob"===r&&(s=new w([s])),{type:b[o],data:s}},e.decodeBase64Packet=function(t,e){var r=b[t.charAt(0)];if(!p)return{type:r,data:{base64:!0,data:t.substr(1)}};var n=p.decode(t.substr(1));return"blob"===e&&w&&(n=new w([n])),{type:r,data:n}},e.encodePayload=function(t,r,n){function o(t){return t.length+":"+t}function i(t,n){e.encodePacket(t,!!s&&r,!1,function(t){n(null,o(t))})}"function"==typeof r&&(n=r,r=null);var s=u(t);return r&&s?w&&!g?e.encodePayloadAsBlob(t,n):e.encodePayloadAsArrayBuffer(t,n):t.length?void c(t,i,function(t,e){return n(e.join(""))}):n("0:")},e.decodePayload=function(t,r,n){if("string"!=typeof t)return e.decodePayloadAsBinary(t,r,n);"function"==typeof r&&(n=r,r=null);var o;if(""===t)return n(k,0,1);for(var i,s,a="",c=0,p=t.length;c0;){for(var s=new Uint8Array(o),a=0===s[0],c="",p=1;255!==s[p];p++){if(c.length>310)return n(k,0,1);c+=s[p]}o=f(o,2+c.length),c=parseInt(c);var h=f(o,0,c);if(a)try{h=String.fromCharCode.apply(null,new Uint8Array(h))}catch(t){var u=new Uint8Array(h);h="";for(var p=0;pn&&(r=n),e>=n||e>=r||0===n)return new ArrayBuffer(0);for(var o=new Uint8Array(t),i=new Uint8Array(r-e),s=e,a=0;s=55296&&e<=56319&&o65535&&(e-=65536,o+=d(e>>>10&1023|55296),e=56320|1023&e),o+=d(e);return o}function o(t,e){if(t>=55296&&t<=57343){if(e)throw Error("Lone surrogate U+"+t.toString(16).toUpperCase()+" is not a scalar value");return!1}return!0}function i(t,e){return d(t>>e&63|128)}function s(t,e){if(0==(4294967168&t))return d(t);var r="";return 0==(4294965248&t)?r=d(t>>6&31|192):0==(4294901760&t)?(o(t,e)||(t=65533),r=d(t>>12&15|224),r+=i(t,6)):0==(4292870144&t)&&(r=d(t>>18&7|240),r+=i(t,12),r+=i(t,6)),r+=d(63&t|128)}function a(t,e){e=e||{};for(var n,o=!1!==e.strict,i=r(t),a=i.length,c=-1,p="";++c=f)throw Error("Invalid byte index");var t=255&u[l];if(l++,128==(192&t))return 63&t;throw Error("Invalid continuation byte")}function p(t){var e,r,n,i,s;if(l>f)throw Error("Invalid byte index");if(l==f)return!1;if(e=255&u[l],l++,0==(128&e))return e;if(192==(224&e)){if(r=c(),s=(31&e)<<6|r,s>=128)return s;throw Error("Invalid continuation byte")}if(224==(240&e)){if(r=c(),n=c(),s=(15&e)<<12|r<<6|n,s>=2048)return o(s,t)?s:65533;throw Error("Invalid continuation byte")}if(240==(248&e)&&(r=c(),n=c(),i=c(),s=(7&e)<<18|r<<12|n<<6|i,s>=65536&&s<=1114111))return s;throw Error("Invalid UTF-8 detected")}function h(t,e){e=e||{};var o=!1!==e.strict;u=r(t),f=u.length,l=0;for(var i,s=[];(i=p(o))!==!1;)s.push(i);return n(s)}/*! https://mths.be/utf8js v2.1.2 by @mathias */ 8 | var u,f,l,d=String.fromCharCode;t.exports={version:"2.1.2",encode:a,decode:h}},function(t,e){!function(){"use strict";for(var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",r=new Uint8Array(256),n=0;n>2],i+=t[(3&n[r])<<4|n[r+1]>>4],i+=t[(15&n[r+1])<<2|n[r+2]>>6],i+=t[63&n[r+2]];return o%3===2?i=i.substring(0,i.length-1)+"=":o%3===1&&(i=i.substring(0,i.length-2)+"=="),i},e.decode=function(t){var e,n,o,i,s,a=.75*t.length,c=t.length,p=0;"="===t[t.length-1]&&(a--,"="===t[t.length-2]&&a--);var h=new ArrayBuffer(a),u=new Uint8Array(h);for(e=0;e>4,u[p++]=(15&o)<<4|i>>2,u[p++]=(3&i)<<6|63&s;return h}}()},function(t,e){function r(t){return t.map(function(t){if(t.buffer instanceof ArrayBuffer){var e=t.buffer;if(t.byteLength!==e.byteLength){var r=new Uint8Array(t.byteLength);r.set(new Uint8Array(e,t.byteOffset,t.byteLength)),e=r.buffer}return e}return t})}function n(t,e){e=e||{};var n=new i;return r(t).forEach(function(t){n.append(t)}),e.type?n.getBlob(e.type):n.getBlob()}function o(t,e){return new Blob(r(t),e||{})}var i="undefined"!=typeof i?i:"undefined"!=typeof WebKitBlobBuilder?WebKitBlobBuilder:"undefined"!=typeof MSBlobBuilder?MSBlobBuilder:"undefined"!=typeof MozBlobBuilder&&MozBlobBuilder,s=function(){try{var t=new Blob(["hi"]);return 2===t.size}catch(t){return!1}}(),a=s&&function(){try{var t=new Blob([new Uint8Array([1,2])]);return 2===t.size}catch(t){return!1}}(),c=i&&i.prototype.append&&i.prototype.getBlob;"undefined"!=typeof Blob&&(n.prototype=Blob.prototype,o.prototype=Blob.prototype),t.exports=function(){return s?a?Blob:o:c?n:void 0}()},function(t,e){e.encode=function(t){var e="";for(var r in t)t.hasOwnProperty(r)&&(e.length&&(e+="&"),e+=encodeURIComponent(r)+"="+encodeURIComponent(t[r]));return e},e.decode=function(t){for(var e={},r=t.split("&"),n=0,o=r.length;n0);return e}function n(t){var e=0;for(h=0;h';i=document.createElement(t)}catch(t){i=document.createElement("iframe"),i.name=o.iframeId,i.src="javascript:0"}i.id=o.iframeId,o.form.appendChild(i),o.iframe=i}var o=this;if(!this.form){var i,s=document.createElement("form"),a=document.createElement("textarea"),c=this.iframeId="eio_iframe_"+this.index;s.className="socketio",s.style.position="absolute",s.style.top="-1000px",s.style.left="-1000px",s.target=c,s.method="POST",s.setAttribute("accept-charset","utf-8"),a.name="d",s.appendChild(a),document.body.appendChild(s),this.form=s,this.area=a}this.form.action=this.uri(),n(),t=t.replace(h,"\\\n"),this.area.value=t.replace(p,"\\n");try{this.form.submit()}catch(t){}this.iframe.attachEvent?this.iframe.onreadystatechange=function(){"complete"===o.iframe.readyState&&r()}:this.iframe.onload=r}}).call(e,function(){return this}())},function(t,e,r){function n(t){var e=t&&t.forceBase64;e&&(this.supportsBinary=!1),this.perMessageDeflate=t.perMessageDeflate,this.usingBrowserWebSocket=o&&!t.forceNode,this.protocols=t.protocols,this.usingBrowserWebSocket||(u=i),s.call(this,t)}var o,i,s=r(17),a=r(18),c=r(26),p=r(27),h=r(28);r(3)("engine.io-client:websocket");if("undefined"!=typeof WebSocket?o=WebSocket:"undefined"!=typeof self&&(o=self.WebSocket||self.MozWebSocket),"undefined"==typeof window)try{i=r(31)}catch(t){}var u=o||i;t.exports=n,p(n,s),n.prototype.name="websocket",n.prototype.supportsBinary=!0,n.prototype.doOpen=function(){if(this.check()){var t=this.uri(),e=this.protocols,r={agent:this.agent,perMessageDeflate:this.perMessageDeflate};r.pfx=this.pfx,r.key=this.key,r.passphrase=this.passphrase,r.cert=this.cert,r.ca=this.ca,r.ciphers=this.ciphers,r.rejectUnauthorized=this.rejectUnauthorized,this.extraHeaders&&(r.headers=this.extraHeaders),this.localAddress&&(r.localAddress=this.localAddress);try{this.ws=this.usingBrowserWebSocket&&!this.isReactNative?e?new u(t,e):new u(t):new u(t,e,r)}catch(t){return this.emit("error",t)}void 0===this.ws.binaryType&&(this.supportsBinary=!1),this.ws.supports&&this.ws.supports.binary?(this.supportsBinary=!0,this.ws.binaryType="nodebuffer"):this.ws.binaryType="arraybuffer",this.addEventListeners()}},n.prototype.addEventListeners=function(){var t=this;this.ws.onopen=function(){t.onOpen()},this.ws.onclose=function(){t.onClose()},this.ws.onmessage=function(e){t.onData(e.data)},this.ws.onerror=function(e){t.onError("websocket error",e)}},n.prototype.write=function(t){function e(){r.emit("flush"),setTimeout(function(){r.writable=!0,r.emit("drain")},0)}var r=this;this.writable=!1;for(var n=t.length,o=0,i=n;o0&&t.jitter<=1?t.jitter:0,this.attempts=0}t.exports=r,r.prototype.duration=function(){var t=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var e=Math.random(),r=Math.floor(e*this.jitter*t);t=0==(1&Math.floor(10*e))?t-r:t+r}return 0|Math.min(t,this.max)},r.prototype.reset=function(){this.attempts=0},r.prototype.setMin=function(t){this.ms=t},r.prototype.setMax=function(t){this.max=t},r.prototype.setJitter=function(t){this.jitter=t}}])}); 9 | //# sourceMappingURL=socket.io.slim.js.map -------------------------------------------------------------------------------- /remote-access-app/client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Remote Access App 7 | 8 | 18 | 19 | 20 | 21 |
22 |
23 | 26 |
27 | 30 |
31 | 32 |
33 | 34 | 35 | -------------------------------------------------------------------------------- /remote-access-app/client/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.7", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 10 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 11 | "requires": { 12 | "mime-types": "~2.1.24", 13 | "negotiator": "0.6.2" 14 | } 15 | }, 16 | "after": { 17 | "version": "0.8.2", 18 | "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", 19 | "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" 20 | }, 21 | "arraybuffer.slice": { 22 | "version": "0.0.7", 23 | "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", 24 | "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" 25 | }, 26 | "async": { 27 | "version": "2.6.3", 28 | "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", 29 | "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", 30 | "dev": true, 31 | "requires": { 32 | "lodash": "^4.17.14" 33 | } 34 | }, 35 | "async-limiter": { 36 | "version": "1.0.1", 37 | "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", 38 | "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" 39 | }, 40 | "backo2": { 41 | "version": "1.0.2", 42 | "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", 43 | "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" 44 | }, 45 | "base64-arraybuffer": { 46 | "version": "0.1.5", 47 | "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", 48 | "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" 49 | }, 50 | "base64id": { 51 | "version": "2.0.0", 52 | "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", 53 | "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" 54 | }, 55 | "basic-auth": { 56 | "version": "1.1.0", 57 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", 58 | "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=", 59 | "dev": true 60 | }, 61 | "better-assert": { 62 | "version": "1.0.2", 63 | "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", 64 | "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", 65 | "requires": { 66 | "callsite": "1.0.0" 67 | } 68 | }, 69 | "blob": { 70 | "version": "0.0.5", 71 | "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", 72 | "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" 73 | }, 74 | "callsite": { 75 | "version": "1.0.0", 76 | "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", 77 | "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" 78 | }, 79 | "colors": { 80 | "version": "1.4.0", 81 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", 82 | "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", 83 | "dev": true 84 | }, 85 | "component-bind": { 86 | "version": "1.0.0", 87 | "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", 88 | "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" 89 | }, 90 | "component-emitter": { 91 | "version": "1.2.1", 92 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", 93 | "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" 94 | }, 95 | "component-inherit": { 96 | "version": "0.0.3", 97 | "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", 98 | "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" 99 | }, 100 | "cookie": { 101 | "version": "0.3.1", 102 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 103 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 104 | }, 105 | "corser": { 106 | "version": "2.0.1", 107 | "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", 108 | "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=", 109 | "dev": true 110 | }, 111 | "debug": { 112 | "version": "4.1.1", 113 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 114 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 115 | "requires": { 116 | "ms": "^2.1.1" 117 | } 118 | }, 119 | "ecstatic": { 120 | "version": "3.3.2", 121 | "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz", 122 | "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==", 123 | "dev": true, 124 | "requires": { 125 | "he": "^1.1.1", 126 | "mime": "^1.6.0", 127 | "minimist": "^1.1.0", 128 | "url-join": "^2.0.5" 129 | } 130 | }, 131 | "engine.io": { 132 | "version": "3.4.1", 133 | "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.4.1.tgz", 134 | "integrity": "sha512-8MfIfF1/IIfxuc2gv5K+XlFZczw/BpTvqBdl0E2fBLkYQp4miv4LuDTVtYt4yMyaIFLEr4vtaSgV4mjvll8Crw==", 135 | "requires": { 136 | "accepts": "~1.3.4", 137 | "base64id": "2.0.0", 138 | "cookie": "0.3.1", 139 | "debug": "~4.1.0", 140 | "engine.io-parser": "~2.2.0", 141 | "ws": "^7.1.2" 142 | } 143 | }, 144 | "engine.io-client": { 145 | "version": "3.4.1", 146 | "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.1.tgz", 147 | "integrity": "sha512-RJNmA+A9Js+8Aoq815xpGAsgWH1VoSYM//2VgIiu9lNOaHFfLpTjH4tOzktBpjIs5lvOfiNY1dwf+NuU6D38Mw==", 148 | "requires": { 149 | "component-emitter": "1.2.1", 150 | "component-inherit": "0.0.3", 151 | "debug": "~4.1.0", 152 | "engine.io-parser": "~2.2.0", 153 | "has-cors": "1.1.0", 154 | "indexof": "0.0.1", 155 | "parseqs": "0.0.5", 156 | "parseuri": "0.0.5", 157 | "ws": "~6.1.0", 158 | "xmlhttprequest-ssl": "~1.5.4", 159 | "yeast": "0.1.2" 160 | }, 161 | "dependencies": { 162 | "ws": { 163 | "version": "6.1.4", 164 | "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", 165 | "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", 166 | "requires": { 167 | "async-limiter": "~1.0.0" 168 | } 169 | } 170 | } 171 | }, 172 | "engine.io-parser": { 173 | "version": "2.2.0", 174 | "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.0.tgz", 175 | "integrity": "sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w==", 176 | "requires": { 177 | "after": "0.8.2", 178 | "arraybuffer.slice": "~0.0.7", 179 | "base64-arraybuffer": "0.1.5", 180 | "blob": "0.0.5", 181 | "has-binary2": "~1.0.2" 182 | } 183 | }, 184 | "eventemitter3": { 185 | "version": "4.0.4", 186 | "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", 187 | "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", 188 | "dev": true 189 | }, 190 | "follow-redirects": { 191 | "version": "1.11.0", 192 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.11.0.tgz", 193 | "integrity": "sha512-KZm0V+ll8PfBrKwMzdo5D13b1bur9Iq9Zd/RMmAoQQcl2PxxFml8cxXPaaPYVbV0RjNjq1CU7zIzAOqtUPudmA==", 194 | "dev": true, 195 | "requires": { 196 | "debug": "^3.0.0" 197 | }, 198 | "dependencies": { 199 | "debug": { 200 | "version": "3.2.6", 201 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 202 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 203 | "dev": true, 204 | "requires": { 205 | "ms": "^2.1.1" 206 | } 207 | } 208 | } 209 | }, 210 | "has-binary2": { 211 | "version": "1.0.3", 212 | "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", 213 | "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", 214 | "requires": { 215 | "isarray": "2.0.1" 216 | } 217 | }, 218 | "has-cors": { 219 | "version": "1.1.0", 220 | "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", 221 | "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" 222 | }, 223 | "he": { 224 | "version": "1.2.0", 225 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 226 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 227 | "dev": true 228 | }, 229 | "http-proxy": { 230 | "version": "1.18.0", 231 | "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz", 232 | "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==", 233 | "dev": true, 234 | "requires": { 235 | "eventemitter3": "^4.0.0", 236 | "follow-redirects": "^1.0.0", 237 | "requires-port": "^1.0.0" 238 | } 239 | }, 240 | "http-server": { 241 | "version": "0.12.3", 242 | "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.12.3.tgz", 243 | "integrity": "sha512-be0dKG6pni92bRjq0kvExtj/NrrAd28/8fCXkaI/4piTwQMSDSLMhWyW0NI1V+DBI3aa1HMlQu46/HjVLfmugA==", 244 | "dev": true, 245 | "requires": { 246 | "basic-auth": "^1.0.3", 247 | "colors": "^1.4.0", 248 | "corser": "^2.0.1", 249 | "ecstatic": "^3.3.2", 250 | "http-proxy": "^1.18.0", 251 | "minimist": "^1.2.5", 252 | "opener": "^1.5.1", 253 | "portfinder": "^1.0.25", 254 | "secure-compare": "3.0.1", 255 | "union": "~0.5.0" 256 | } 257 | }, 258 | "indexof": { 259 | "version": "0.0.1", 260 | "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", 261 | "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" 262 | }, 263 | "isarray": { 264 | "version": "2.0.1", 265 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", 266 | "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" 267 | }, 268 | "lodash": { 269 | "version": "4.17.15", 270 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 271 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", 272 | "dev": true 273 | }, 274 | "mime": { 275 | "version": "1.6.0", 276 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 277 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 278 | "dev": true 279 | }, 280 | "mime-db": { 281 | "version": "1.44.0", 282 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", 283 | "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" 284 | }, 285 | "mime-types": { 286 | "version": "2.1.27", 287 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", 288 | "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", 289 | "requires": { 290 | "mime-db": "1.44.0" 291 | } 292 | }, 293 | "minimist": { 294 | "version": "1.2.5", 295 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 296 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 297 | "dev": true 298 | }, 299 | "mkdirp": { 300 | "version": "0.5.5", 301 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 302 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 303 | "dev": true, 304 | "requires": { 305 | "minimist": "^1.2.5" 306 | } 307 | }, 308 | "ms": { 309 | "version": "2.1.2", 310 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 311 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 312 | }, 313 | "negotiator": { 314 | "version": "0.6.2", 315 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 316 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 317 | }, 318 | "object-component": { 319 | "version": "0.0.3", 320 | "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", 321 | "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" 322 | }, 323 | "opener": { 324 | "version": "1.5.1", 325 | "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz", 326 | "integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==", 327 | "dev": true 328 | }, 329 | "parseqs": { 330 | "version": "0.0.5", 331 | "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", 332 | "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", 333 | "requires": { 334 | "better-assert": "~1.0.0" 335 | } 336 | }, 337 | "parseuri": { 338 | "version": "0.0.5", 339 | "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", 340 | "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", 341 | "requires": { 342 | "better-assert": "~1.0.0" 343 | } 344 | }, 345 | "portfinder": { 346 | "version": "1.0.26", 347 | "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.26.tgz", 348 | "integrity": "sha512-Xi7mKxJHHMI3rIUrnm/jjUgwhbYMkp/XKEcZX3aG4BrumLpq3nmoQMX+ClYnDZnZ/New7IatC1no5RX0zo1vXQ==", 349 | "dev": true, 350 | "requires": { 351 | "async": "^2.6.2", 352 | "debug": "^3.1.1", 353 | "mkdirp": "^0.5.1" 354 | }, 355 | "dependencies": { 356 | "debug": { 357 | "version": "3.2.6", 358 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 359 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 360 | "dev": true, 361 | "requires": { 362 | "ms": "^2.1.1" 363 | } 364 | } 365 | } 366 | }, 367 | "qs": { 368 | "version": "6.9.4", 369 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", 370 | "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", 371 | "dev": true 372 | }, 373 | "requires-port": { 374 | "version": "1.0.0", 375 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", 376 | "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", 377 | "dev": true 378 | }, 379 | "secure-compare": { 380 | "version": "3.0.1", 381 | "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", 382 | "integrity": "sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=", 383 | "dev": true 384 | }, 385 | "socket.io": { 386 | "version": "2.3.0", 387 | "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.3.0.tgz", 388 | "integrity": "sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==", 389 | "requires": { 390 | "debug": "~4.1.0", 391 | "engine.io": "~3.4.0", 392 | "has-binary2": "~1.0.2", 393 | "socket.io-adapter": "~1.1.0", 394 | "socket.io-client": "2.3.0", 395 | "socket.io-parser": "~3.4.0" 396 | } 397 | }, 398 | "socket.io-adapter": { 399 | "version": "1.1.2", 400 | "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", 401 | "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==" 402 | }, 403 | "socket.io-client": { 404 | "version": "2.3.0", 405 | "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz", 406 | "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==", 407 | "requires": { 408 | "backo2": "1.0.2", 409 | "base64-arraybuffer": "0.1.5", 410 | "component-bind": "1.0.0", 411 | "component-emitter": "1.2.1", 412 | "debug": "~4.1.0", 413 | "engine.io-client": "~3.4.0", 414 | "has-binary2": "~1.0.2", 415 | "has-cors": "1.1.0", 416 | "indexof": "0.0.1", 417 | "object-component": "0.0.3", 418 | "parseqs": "0.0.5", 419 | "parseuri": "0.0.5", 420 | "socket.io-parser": "~3.3.0", 421 | "to-array": "0.1.4" 422 | }, 423 | "dependencies": { 424 | "ms": { 425 | "version": "2.0.0", 426 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 427 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 428 | }, 429 | "socket.io-parser": { 430 | "version": "3.3.0", 431 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", 432 | "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", 433 | "requires": { 434 | "component-emitter": "1.2.1", 435 | "debug": "~3.1.0", 436 | "isarray": "2.0.1" 437 | }, 438 | "dependencies": { 439 | "debug": { 440 | "version": "3.1.0", 441 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 442 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 443 | "requires": { 444 | "ms": "2.0.0" 445 | } 446 | } 447 | } 448 | } 449 | } 450 | }, 451 | "socket.io-parser": { 452 | "version": "3.4.0", 453 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.0.tgz", 454 | "integrity": "sha512-/G/VOI+3DBp0+DJKW4KesGnQkQPFmUCbA/oO2QGT6CWxU7hLGWqU3tyuzeSK/dqcyeHsQg1vTe9jiZI8GU9SCQ==", 455 | "requires": { 456 | "component-emitter": "1.2.1", 457 | "debug": "~4.1.0", 458 | "isarray": "2.0.1" 459 | } 460 | }, 461 | "to-array": { 462 | "version": "0.1.4", 463 | "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", 464 | "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" 465 | }, 466 | "union": { 467 | "version": "0.5.0", 468 | "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", 469 | "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", 470 | "dev": true, 471 | "requires": { 472 | "qs": "^6.4.0" 473 | } 474 | }, 475 | "url-join": { 476 | "version": "2.0.5", 477 | "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", 478 | "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=", 479 | "dev": true 480 | }, 481 | "ws": { 482 | "version": "7.3.0", 483 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz", 484 | "integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w==" 485 | }, 486 | "xmlhttprequest-ssl": { 487 | "version": "1.5.5", 488 | "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", 489 | "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" 490 | }, 491 | "yeast": { 492 | "version": "0.1.2", 493 | "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", 494 | "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" 495 | } 496 | } 497 | } 498 | -------------------------------------------------------------------------------- /remote-access-app/client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "npx http-server -p $PORT ." 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "socket.io": "^2.3.0", 14 | "socket.io-client": "^2.3.0", 15 | "http-server": "^0.12.3" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /remote-access-app/client/resources/desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ErickWendel/talk-deep-dive-into-nodejs-streams/3f041416f2e73fb005de6a4adb2beca736efe255/remote-access-app/client/resources/desktop.png -------------------------------------------------------------------------------- /remote-access-app/client/sharer/app.js: -------------------------------------------------------------------------------- 1 | let host = prompt('What is your socket server host?') 2 | if (!host) host = "http://localhost:4000" 3 | 4 | const socket = io.connect(host); 5 | 6 | async function initialize() { 7 | console.log('initializing..') 8 | const remoteScreen = new RemoteScreen({ socket }) 9 | await remoteScreen.showSources(); 10 | } 11 | 12 | window.onload = async function () { 13 | socket.on('connect', initialize); 14 | } 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /remote-access-app/client/sharer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Sharer! 4 | 5 | 23 | 24 | 25 | 26 |
27 | 28 | 29 |
30 | 31 |
32 | 33 | 34 |
35 | 36 |
37 |
38 | 39 |
40 |
41 | 42 |
43 |
44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /remote-access-app/client/sharer/screen.js: -------------------------------------------------------------------------------- 1 | // const { name: appName } = require('./../package.json') 2 | const peerConnections = {}; 3 | const config = { 4 | iceServers: [ 5 | { 6 | urls: ["stun:stun.l.google.com:19302"] 7 | } 8 | ] 9 | }; 10 | const videoCamera = document.getElementById('camera') 11 | const videoScreen = document.getElementById('screen') 12 | 13 | const audioSelect = document.querySelector("select#audioSource"); 14 | const videoSelect = document.querySelector("select#videoSource"); 15 | 16 | 17 | function getDevices() { 18 | return navigator.mediaDevices.enumerateDevices(); 19 | } 20 | 21 | function gotDevices(deviceInfos) { 22 | window.deviceInfos = deviceInfos; 23 | for (const deviceInfo of deviceInfos) { 24 | const option = document.createElement("option"); 25 | option.value = deviceInfo.deviceId; 26 | if (deviceInfo.kind === "audioinput") { 27 | option.text = deviceInfo.label || `Microphone ${audioSelect.length + 1}`; 28 | audioSelect.appendChild(option); 29 | } else if (deviceInfo.kind === "videoinput") { 30 | option.text = deviceInfo.label || `Camera ${videoSelect.length + 1}`; 31 | videoSelect.appendChild(option); 32 | } 33 | } 34 | } 35 | 36 | async function getCameraStream() { 37 | if (window.cameraScreen) { 38 | window.cameraScreen.getTracks().forEach(track => { 39 | track.stop(); 40 | }); 41 | } 42 | const audioSource = audioSelect.value; 43 | const videoSource = videoSelect.value; 44 | const constraints = { 45 | audio: { deviceId: audioSource ? { exact: audioSource } : undefined }, 46 | video: { deviceId: videoSource ? { exact: videoSource } : undefined } 47 | }; 48 | const str = await navigator.mediaDevices.getUserMedia(constraints) 49 | return handleSelects(str) 50 | } 51 | 52 | function handleSelects(stream) { 53 | window.cameraScreen = stream; 54 | audioSelect.selectedIndex = [...audioSelect.options].findIndex( 55 | option => option.text === stream.getAudioTracks()[0].label 56 | ); 57 | videoCamera.selectedIndex = [...videoSelect.options].findIndex( 58 | option => option.text === stream.getVideoTracks()[0].label 59 | ); 60 | videoCamera.srcObject = stream; 61 | socket.emit("broadcaster"); 62 | } 63 | 64 | function handleError(error) { 65 | console.error("Error: ", error); 66 | } 67 | 68 | 69 | class RemoteScreen { 70 | constructor({ socket }) { 71 | this.socket = socket 72 | this.registerSocketEvents(socket) 73 | } 74 | 75 | registerSocketEvents(socket) { 76 | socket.on("answer", (id, description) => { 77 | peerConnections[id].setRemoteDescription(description); 78 | }); 79 | 80 | socket.on("watcher", id => { 81 | const peerConnection = new RTCPeerConnection(config); 82 | peerConnections[id] = peerConnection; 83 | 84 | const screenStream = videoScreen.srcObject; 85 | const cameraStream = videoCamera.srcObject; 86 | 87 | screenStream.getTracks() 88 | .forEach(track => peerConnection.addTrack(track, screenStream)); 89 | 90 | cameraStream.getTracks() 91 | .forEach(track => peerConnection.addTrack(track, cameraStream)); 92 | 93 | 94 | peerConnection.onicecandidate = event => { 95 | if (event.candidate) { 96 | socket.emit("candidate", id, event.candidate); 97 | } 98 | }; 99 | 100 | peerConnection 101 | .createOffer() 102 | .then(sdp => peerConnection.setLocalDescription(sdp)) 103 | .then(() => { 104 | socket.emit("offer", id, peerConnection.localDescription); 105 | }); 106 | }); 107 | 108 | socket.on("candidate", (id, candidate) => { 109 | peerConnections[id].addIceCandidate(new RTCIceCandidate(candidate)); 110 | }); 111 | 112 | socket.on("disconnectPeer", id => { 113 | peerConnections[id].close(); 114 | delete peerConnections[id]; 115 | }); 116 | 117 | window.onunload = window.onbeforeunload = () => { 118 | socket.close(); 119 | }; 120 | } 121 | async handleScreen() { 122 | const screen = await navigator.mediaDevices.getDisplayMedia() 123 | this.shareScreen(screen) 124 | } 125 | async handleCamera() { 126 | const str = await getCameraStream() 127 | const devices = await getDevices(str) 128 | await gotDevices(devices) 129 | } 130 | async showSources() { 131 | 132 | 133 | await Promise.all([ 134 | this.handleScreen(), 135 | this.handleCamera() 136 | ]) 137 | 138 | this.socket.emit("broadcaster"); 139 | 140 | audioSelect.onchange = getCameraStream; 141 | videoSelect.onchange = getCameraStream; 142 | } 143 | 144 | shareScreen(screen) { 145 | 146 | if (!screen) { 147 | console.log('Desktop Capture access rejected.'); 148 | return; 149 | } 150 | if (window.stream) { 151 | window.stream 152 | .getTracks() 153 | .forEach(track => track.stop()); 154 | } 155 | 156 | console.log("Desktop sharing started.. desktop_id:" + screen.id); 157 | 158 | try { 159 | videoScreen.srcObject = screen 160 | window.stream = screen; 161 | 162 | videoScreen.onloadedmetadata = (e) => videoScreen.play() 163 | } catch (e) { 164 | console.log('ERROR***', e) 165 | // System Preferences / Security & Privacy / Camera / Checkbox next to "Chrome" 166 | } 167 | 168 | } 169 | 170 | } 171 | -------------------------------------------------------------------------------- /remote-access-app/client/watcher/app.js: -------------------------------------------------------------------------------- 1 | let peerConnection; 2 | const config = { 3 | iceServers: [ 4 | { 5 | urls: ["stun:stun.l.google.com:19302"] 6 | } 7 | ] 8 | }; 9 | let host = prompt('What is your socket server host?') 10 | if (!host) host = "http://localhost:4000" 11 | 12 | const socket = io.connect(host); 13 | const camera = document.getElementById('camera') 14 | const video = document.getElementById('screen') 15 | 16 | socket.on("offer", (id, description) => { 17 | peerConnection = new RTCPeerConnection(config); 18 | peerConnection 19 | .setRemoteDescription(description) 20 | .then(() => peerConnection.createAnswer()) 21 | .then(sdp => peerConnection.setLocalDescription(sdp)) 22 | .then(() => { 23 | socket.emit("answer", id, peerConnection.localDescription); 24 | }); 25 | 26 | peerConnection.ontrack = event => { 27 | const item = event.streams[0] 28 | const isCamera = item.getVideoTracks().length && item.getAudioTracks().length 29 | 30 | if(isCamera) { 31 | camera.srcObject = item; 32 | return; 33 | } 34 | 35 | video.srcObject = item; 36 | }; 37 | peerConnection.onicecandidate = event => { 38 | if (event.candidate) { 39 | socket.emit("candidate", id, event.candidate); 40 | } 41 | }; 42 | }); 43 | 44 | socket.on("candidate", (id, candidate) => { 45 | peerConnection 46 | .addIceCandidate(new RTCIceCandidate(candidate)) 47 | .catch(e => console.error(e)); 48 | }); 49 | 50 | socket.on("connect", () => { 51 | console.log('connected!') 52 | socket.emit("watcher"); 53 | }); 54 | 55 | socket.on("broadcaster", () => { 56 | console.log('broadcaster!') 57 | socket.emit("watcher"); 58 | }); 59 | 60 | socket.on("disconnectPeer", () => { 61 | console.log('disconnectPeer!') 62 | peerConnection.close(); 63 | }); 64 | 65 | window.onunload = window.onbeforeunload = () => { 66 | socket.close(); 67 | }; 68 | 69 | -------------------------------------------------------------------------------- /remote-access-app/client/watcher/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Watcher 4 | 5 | 22 | 23 | 24 | 25 |
26 |
27 | 28 |
29 |
30 | 31 |
32 |
33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /remote-access-app/server/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Hello world1 7 | 8 | 9 | Hello! 10 | 11 | -------------------------------------------------------------------------------- /remote-access-app/server/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@sindresorhus/is": { 8 | "version": "0.14.0", 9 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", 10 | "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", 11 | "dev": true 12 | }, 13 | "@szmarczak/http-timer": { 14 | "version": "1.1.2", 15 | "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", 16 | "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", 17 | "dev": true, 18 | "requires": { 19 | "defer-to-connect": "^1.0.1" 20 | } 21 | }, 22 | "@types/color-name": { 23 | "version": "1.1.1", 24 | "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", 25 | "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", 26 | "dev": true 27 | }, 28 | "abbrev": { 29 | "version": "1.1.1", 30 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 31 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", 32 | "dev": true 33 | }, 34 | "accepts": { 35 | "version": "1.3.7", 36 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 37 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 38 | "requires": { 39 | "mime-types": "~2.1.24", 40 | "negotiator": "0.6.2" 41 | } 42 | }, 43 | "after": { 44 | "version": "0.8.2", 45 | "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", 46 | "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" 47 | }, 48 | "ansi-align": { 49 | "version": "3.0.0", 50 | "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", 51 | "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", 52 | "dev": true, 53 | "requires": { 54 | "string-width": "^3.0.0" 55 | }, 56 | "dependencies": { 57 | "string-width": { 58 | "version": "3.1.0", 59 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 60 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 61 | "dev": true, 62 | "requires": { 63 | "emoji-regex": "^7.0.1", 64 | "is-fullwidth-code-point": "^2.0.0", 65 | "strip-ansi": "^5.1.0" 66 | } 67 | } 68 | } 69 | }, 70 | "ansi-regex": { 71 | "version": "4.1.0", 72 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 73 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 74 | "dev": true 75 | }, 76 | "ansi-styles": { 77 | "version": "4.2.1", 78 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", 79 | "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", 80 | "dev": true, 81 | "requires": { 82 | "@types/color-name": "^1.1.1", 83 | "color-convert": "^2.0.1" 84 | } 85 | }, 86 | "anymatch": { 87 | "version": "3.1.1", 88 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", 89 | "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", 90 | "dev": true, 91 | "requires": { 92 | "normalize-path": "^3.0.0", 93 | "picomatch": "^2.0.4" 94 | } 95 | }, 96 | "arraybuffer.slice": { 97 | "version": "0.0.7", 98 | "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", 99 | "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" 100 | }, 101 | "async-limiter": { 102 | "version": "1.0.1", 103 | "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", 104 | "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" 105 | }, 106 | "backo2": { 107 | "version": "1.0.2", 108 | "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", 109 | "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" 110 | }, 111 | "balanced-match": { 112 | "version": "1.0.0", 113 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 114 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 115 | "dev": true 116 | }, 117 | "base64-arraybuffer": { 118 | "version": "0.1.5", 119 | "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", 120 | "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" 121 | }, 122 | "base64id": { 123 | "version": "2.0.0", 124 | "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", 125 | "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" 126 | }, 127 | "better-assert": { 128 | "version": "1.0.2", 129 | "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", 130 | "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", 131 | "requires": { 132 | "callsite": "1.0.0" 133 | } 134 | }, 135 | "binary-extensions": { 136 | "version": "2.0.0", 137 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", 138 | "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", 139 | "dev": true 140 | }, 141 | "blob": { 142 | "version": "0.0.5", 143 | "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", 144 | "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" 145 | }, 146 | "boxen": { 147 | "version": "4.2.0", 148 | "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", 149 | "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", 150 | "dev": true, 151 | "requires": { 152 | "ansi-align": "^3.0.0", 153 | "camelcase": "^5.3.1", 154 | "chalk": "^3.0.0", 155 | "cli-boxes": "^2.2.0", 156 | "string-width": "^4.1.0", 157 | "term-size": "^2.1.0", 158 | "type-fest": "^0.8.1", 159 | "widest-line": "^3.1.0" 160 | } 161 | }, 162 | "brace-expansion": { 163 | "version": "1.1.11", 164 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 165 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 166 | "dev": true, 167 | "requires": { 168 | "balanced-match": "^1.0.0", 169 | "concat-map": "0.0.1" 170 | } 171 | }, 172 | "braces": { 173 | "version": "3.0.2", 174 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 175 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 176 | "dev": true, 177 | "requires": { 178 | "fill-range": "^7.0.1" 179 | } 180 | }, 181 | "cacheable-request": { 182 | "version": "6.1.0", 183 | "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", 184 | "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", 185 | "dev": true, 186 | "requires": { 187 | "clone-response": "^1.0.2", 188 | "get-stream": "^5.1.0", 189 | "http-cache-semantics": "^4.0.0", 190 | "keyv": "^3.0.0", 191 | "lowercase-keys": "^2.0.0", 192 | "normalize-url": "^4.1.0", 193 | "responselike": "^1.0.2" 194 | }, 195 | "dependencies": { 196 | "get-stream": { 197 | "version": "5.1.0", 198 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", 199 | "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", 200 | "dev": true, 201 | "requires": { 202 | "pump": "^3.0.0" 203 | } 204 | }, 205 | "lowercase-keys": { 206 | "version": "2.0.0", 207 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", 208 | "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", 209 | "dev": true 210 | } 211 | } 212 | }, 213 | "callsite": { 214 | "version": "1.0.0", 215 | "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", 216 | "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" 217 | }, 218 | "camelcase": { 219 | "version": "5.3.1", 220 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 221 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 222 | "dev": true 223 | }, 224 | "chalk": { 225 | "version": "3.0.0", 226 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", 227 | "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", 228 | "dev": true, 229 | "requires": { 230 | "ansi-styles": "^4.1.0", 231 | "supports-color": "^7.1.0" 232 | }, 233 | "dependencies": { 234 | "has-flag": { 235 | "version": "4.0.0", 236 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 237 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 238 | "dev": true 239 | }, 240 | "supports-color": { 241 | "version": "7.1.0", 242 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", 243 | "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", 244 | "dev": true, 245 | "requires": { 246 | "has-flag": "^4.0.0" 247 | } 248 | } 249 | } 250 | }, 251 | "chokidar": { 252 | "version": "3.4.0", 253 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz", 254 | "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==", 255 | "dev": true, 256 | "requires": { 257 | "anymatch": "~3.1.1", 258 | "braces": "~3.0.2", 259 | "fsevents": "~2.1.2", 260 | "glob-parent": "~5.1.0", 261 | "is-binary-path": "~2.1.0", 262 | "is-glob": "~4.0.1", 263 | "normalize-path": "~3.0.0", 264 | "readdirp": "~3.4.0" 265 | } 266 | }, 267 | "ci-info": { 268 | "version": "2.0.0", 269 | "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", 270 | "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", 271 | "dev": true 272 | }, 273 | "cli-boxes": { 274 | "version": "2.2.0", 275 | "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", 276 | "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", 277 | "dev": true 278 | }, 279 | "clone-response": { 280 | "version": "1.0.2", 281 | "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", 282 | "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", 283 | "dev": true, 284 | "requires": { 285 | "mimic-response": "^1.0.0" 286 | } 287 | }, 288 | "color-convert": { 289 | "version": "2.0.1", 290 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 291 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 292 | "dev": true, 293 | "requires": { 294 | "color-name": "~1.1.4" 295 | } 296 | }, 297 | "color-name": { 298 | "version": "1.1.4", 299 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 300 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 301 | "dev": true 302 | }, 303 | "component-bind": { 304 | "version": "1.0.0", 305 | "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", 306 | "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" 307 | }, 308 | "component-emitter": { 309 | "version": "1.2.1", 310 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", 311 | "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" 312 | }, 313 | "component-inherit": { 314 | "version": "0.0.3", 315 | "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", 316 | "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" 317 | }, 318 | "concat-map": { 319 | "version": "0.0.1", 320 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 321 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 322 | "dev": true 323 | }, 324 | "configstore": { 325 | "version": "5.0.1", 326 | "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", 327 | "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", 328 | "dev": true, 329 | "requires": { 330 | "dot-prop": "^5.2.0", 331 | "graceful-fs": "^4.1.2", 332 | "make-dir": "^3.0.0", 333 | "unique-string": "^2.0.0", 334 | "write-file-atomic": "^3.0.0", 335 | "xdg-basedir": "^4.0.0" 336 | } 337 | }, 338 | "cookie": { 339 | "version": "0.3.1", 340 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 341 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 342 | }, 343 | "crypto-random-string": { 344 | "version": "2.0.0", 345 | "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", 346 | "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", 347 | "dev": true 348 | }, 349 | "debug": { 350 | "version": "4.1.1", 351 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 352 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 353 | "requires": { 354 | "ms": "^2.1.1" 355 | } 356 | }, 357 | "decompress-response": { 358 | "version": "3.3.0", 359 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", 360 | "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", 361 | "dev": true, 362 | "requires": { 363 | "mimic-response": "^1.0.0" 364 | } 365 | }, 366 | "deep-extend": { 367 | "version": "0.6.0", 368 | "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", 369 | "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", 370 | "dev": true 371 | }, 372 | "defer-to-connect": { 373 | "version": "1.1.3", 374 | "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", 375 | "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", 376 | "dev": true 377 | }, 378 | "dot-prop": { 379 | "version": "5.2.0", 380 | "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", 381 | "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==", 382 | "dev": true, 383 | "requires": { 384 | "is-obj": "^2.0.0" 385 | } 386 | }, 387 | "duplexer3": { 388 | "version": "0.1.4", 389 | "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", 390 | "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", 391 | "dev": true 392 | }, 393 | "emoji-regex": { 394 | "version": "7.0.3", 395 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 396 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 397 | "dev": true 398 | }, 399 | "end-of-stream": { 400 | "version": "1.4.4", 401 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 402 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 403 | "dev": true, 404 | "requires": { 405 | "once": "^1.4.0" 406 | } 407 | }, 408 | "engine.io": { 409 | "version": "3.4.1", 410 | "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.4.1.tgz", 411 | "integrity": "sha512-8MfIfF1/IIfxuc2gv5K+XlFZczw/BpTvqBdl0E2fBLkYQp4miv4LuDTVtYt4yMyaIFLEr4vtaSgV4mjvll8Crw==", 412 | "requires": { 413 | "accepts": "~1.3.4", 414 | "base64id": "2.0.0", 415 | "cookie": "0.3.1", 416 | "debug": "~4.1.0", 417 | "engine.io-parser": "~2.2.0", 418 | "ws": "^7.1.2" 419 | } 420 | }, 421 | "engine.io-client": { 422 | "version": "3.4.1", 423 | "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.1.tgz", 424 | "integrity": "sha512-RJNmA+A9Js+8Aoq815xpGAsgWH1VoSYM//2VgIiu9lNOaHFfLpTjH4tOzktBpjIs5lvOfiNY1dwf+NuU6D38Mw==", 425 | "requires": { 426 | "component-emitter": "1.2.1", 427 | "component-inherit": "0.0.3", 428 | "debug": "~4.1.0", 429 | "engine.io-parser": "~2.2.0", 430 | "has-cors": "1.1.0", 431 | "indexof": "0.0.1", 432 | "parseqs": "0.0.5", 433 | "parseuri": "0.0.5", 434 | "ws": "~6.1.0", 435 | "xmlhttprequest-ssl": "~1.5.4", 436 | "yeast": "0.1.2" 437 | }, 438 | "dependencies": { 439 | "ws": { 440 | "version": "6.1.4", 441 | "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", 442 | "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", 443 | "requires": { 444 | "async-limiter": "~1.0.0" 445 | } 446 | } 447 | } 448 | }, 449 | "engine.io-parser": { 450 | "version": "2.2.0", 451 | "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.0.tgz", 452 | "integrity": "sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w==", 453 | "requires": { 454 | "after": "0.8.2", 455 | "arraybuffer.slice": "~0.0.7", 456 | "base64-arraybuffer": "0.1.5", 457 | "blob": "0.0.5", 458 | "has-binary2": "~1.0.2" 459 | } 460 | }, 461 | "escape-goat": { 462 | "version": "2.1.1", 463 | "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", 464 | "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", 465 | "dev": true 466 | }, 467 | "fill-range": { 468 | "version": "7.0.1", 469 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 470 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 471 | "dev": true, 472 | "requires": { 473 | "to-regex-range": "^5.0.1" 474 | } 475 | }, 476 | "fsevents": { 477 | "version": "2.1.3", 478 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", 479 | "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", 480 | "dev": true, 481 | "optional": true 482 | }, 483 | "get-stream": { 484 | "version": "4.1.0", 485 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", 486 | "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", 487 | "dev": true, 488 | "requires": { 489 | "pump": "^3.0.0" 490 | } 491 | }, 492 | "glob-parent": { 493 | "version": "5.1.1", 494 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", 495 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", 496 | "dev": true, 497 | "requires": { 498 | "is-glob": "^4.0.1" 499 | } 500 | }, 501 | "global-dirs": { 502 | "version": "2.0.1", 503 | "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", 504 | "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==", 505 | "dev": true, 506 | "requires": { 507 | "ini": "^1.3.5" 508 | } 509 | }, 510 | "got": { 511 | "version": "9.6.0", 512 | "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", 513 | "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", 514 | "dev": true, 515 | "requires": { 516 | "@sindresorhus/is": "^0.14.0", 517 | "@szmarczak/http-timer": "^1.1.2", 518 | "cacheable-request": "^6.0.0", 519 | "decompress-response": "^3.3.0", 520 | "duplexer3": "^0.1.4", 521 | "get-stream": "^4.1.0", 522 | "lowercase-keys": "^1.0.1", 523 | "mimic-response": "^1.0.1", 524 | "p-cancelable": "^1.0.0", 525 | "to-readable-stream": "^1.0.0", 526 | "url-parse-lax": "^3.0.0" 527 | } 528 | }, 529 | "graceful-fs": { 530 | "version": "4.2.3", 531 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", 532 | "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", 533 | "dev": true 534 | }, 535 | "has-binary2": { 536 | "version": "1.0.3", 537 | "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", 538 | "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", 539 | "requires": { 540 | "isarray": "2.0.1" 541 | }, 542 | "dependencies": { 543 | "isarray": { 544 | "version": "2.0.1", 545 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", 546 | "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" 547 | } 548 | } 549 | }, 550 | "has-cors": { 551 | "version": "1.1.0", 552 | "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", 553 | "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" 554 | }, 555 | "has-flag": { 556 | "version": "3.0.0", 557 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 558 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 559 | "dev": true 560 | }, 561 | "has-yarn": { 562 | "version": "2.1.0", 563 | "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", 564 | "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", 565 | "dev": true 566 | }, 567 | "http-cache-semantics": { 568 | "version": "4.1.0", 569 | "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", 570 | "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", 571 | "dev": true 572 | }, 573 | "ignore-by-default": { 574 | "version": "1.0.1", 575 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", 576 | "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", 577 | "dev": true 578 | }, 579 | "import-lazy": { 580 | "version": "2.1.0", 581 | "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", 582 | "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", 583 | "dev": true 584 | }, 585 | "imurmurhash": { 586 | "version": "0.1.4", 587 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 588 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 589 | "dev": true 590 | }, 591 | "indexof": { 592 | "version": "0.0.1", 593 | "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", 594 | "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" 595 | }, 596 | "ini": { 597 | "version": "1.3.5", 598 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", 599 | "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", 600 | "dev": true 601 | }, 602 | "is-binary-path": { 603 | "version": "2.1.0", 604 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 605 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 606 | "dev": true, 607 | "requires": { 608 | "binary-extensions": "^2.0.0" 609 | } 610 | }, 611 | "is-ci": { 612 | "version": "2.0.0", 613 | "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", 614 | "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", 615 | "dev": true, 616 | "requires": { 617 | "ci-info": "^2.0.0" 618 | } 619 | }, 620 | "is-extglob": { 621 | "version": "2.1.1", 622 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 623 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 624 | "dev": true 625 | }, 626 | "is-fullwidth-code-point": { 627 | "version": "2.0.0", 628 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 629 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 630 | "dev": true 631 | }, 632 | "is-glob": { 633 | "version": "4.0.1", 634 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 635 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 636 | "dev": true, 637 | "requires": { 638 | "is-extglob": "^2.1.1" 639 | } 640 | }, 641 | "is-installed-globally": { 642 | "version": "0.3.2", 643 | "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", 644 | "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", 645 | "dev": true, 646 | "requires": { 647 | "global-dirs": "^2.0.1", 648 | "is-path-inside": "^3.0.1" 649 | } 650 | }, 651 | "is-npm": { 652 | "version": "4.0.0", 653 | "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", 654 | "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", 655 | "dev": true 656 | }, 657 | "is-number": { 658 | "version": "7.0.0", 659 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 660 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 661 | "dev": true 662 | }, 663 | "is-obj": { 664 | "version": "2.0.0", 665 | "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", 666 | "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", 667 | "dev": true 668 | }, 669 | "is-path-inside": { 670 | "version": "3.0.2", 671 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", 672 | "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==", 673 | "dev": true 674 | }, 675 | "is-typedarray": { 676 | "version": "1.0.0", 677 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 678 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 679 | "dev": true 680 | }, 681 | "is-yarn-global": { 682 | "version": "0.3.0", 683 | "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", 684 | "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", 685 | "dev": true 686 | }, 687 | "json-buffer": { 688 | "version": "3.0.0", 689 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", 690 | "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", 691 | "dev": true 692 | }, 693 | "keyv": { 694 | "version": "3.1.0", 695 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", 696 | "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", 697 | "dev": true, 698 | "requires": { 699 | "json-buffer": "3.0.0" 700 | } 701 | }, 702 | "latest-version": { 703 | "version": "5.1.0", 704 | "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", 705 | "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", 706 | "dev": true, 707 | "requires": { 708 | "package-json": "^6.3.0" 709 | } 710 | }, 711 | "lowercase-keys": { 712 | "version": "1.0.1", 713 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", 714 | "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", 715 | "dev": true 716 | }, 717 | "make-dir": { 718 | "version": "3.1.0", 719 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", 720 | "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", 721 | "dev": true, 722 | "requires": { 723 | "semver": "^6.0.0" 724 | }, 725 | "dependencies": { 726 | "semver": { 727 | "version": "6.3.0", 728 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 729 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 730 | "dev": true 731 | } 732 | } 733 | }, 734 | "mime-db": { 735 | "version": "1.44.0", 736 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", 737 | "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" 738 | }, 739 | "mime-types": { 740 | "version": "2.1.27", 741 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", 742 | "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", 743 | "requires": { 744 | "mime-db": "1.44.0" 745 | } 746 | }, 747 | "mimic-response": { 748 | "version": "1.0.1", 749 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", 750 | "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", 751 | "dev": true 752 | }, 753 | "minimatch": { 754 | "version": "3.0.4", 755 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 756 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 757 | "dev": true, 758 | "requires": { 759 | "brace-expansion": "^1.1.7" 760 | } 761 | }, 762 | "minimist": { 763 | "version": "1.2.5", 764 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 765 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 766 | "dev": true 767 | }, 768 | "ms": { 769 | "version": "2.1.2", 770 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 771 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 772 | }, 773 | "negotiator": { 774 | "version": "0.6.2", 775 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 776 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 777 | }, 778 | "nodemon": { 779 | "version": "2.0.3", 780 | "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.3.tgz", 781 | "integrity": "sha512-lLQLPS90Lqwc99IHe0U94rDgvjo+G9I4uEIxRG3evSLROcqQ9hwc0AxlSHKS4T1JW/IMj/7N5mthiN58NL/5kw==", 782 | "dev": true, 783 | "requires": { 784 | "chokidar": "^3.2.2", 785 | "debug": "^3.2.6", 786 | "ignore-by-default": "^1.0.1", 787 | "minimatch": "^3.0.4", 788 | "pstree.remy": "^1.1.7", 789 | "semver": "^5.7.1", 790 | "supports-color": "^5.5.0", 791 | "touch": "^3.1.0", 792 | "undefsafe": "^2.0.2", 793 | "update-notifier": "^4.0.0" 794 | }, 795 | "dependencies": { 796 | "debug": { 797 | "version": "3.2.6", 798 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 799 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 800 | "dev": true, 801 | "requires": { 802 | "ms": "^2.1.1" 803 | } 804 | }, 805 | "semver": { 806 | "version": "5.7.1", 807 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 808 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 809 | "dev": true 810 | } 811 | } 812 | }, 813 | "nopt": { 814 | "version": "1.0.10", 815 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", 816 | "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", 817 | "dev": true, 818 | "requires": { 819 | "abbrev": "1" 820 | } 821 | }, 822 | "normalize-path": { 823 | "version": "3.0.0", 824 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 825 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 826 | "dev": true 827 | }, 828 | "normalize-url": { 829 | "version": "4.5.0", 830 | "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", 831 | "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", 832 | "dev": true 833 | }, 834 | "object-component": { 835 | "version": "0.0.3", 836 | "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", 837 | "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" 838 | }, 839 | "once": { 840 | "version": "1.4.0", 841 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 842 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 843 | "dev": true, 844 | "requires": { 845 | "wrappy": "1" 846 | } 847 | }, 848 | "p-cancelable": { 849 | "version": "1.1.0", 850 | "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", 851 | "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", 852 | "dev": true 853 | }, 854 | "package-json": { 855 | "version": "6.5.0", 856 | "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", 857 | "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", 858 | "dev": true, 859 | "requires": { 860 | "got": "^9.6.0", 861 | "registry-auth-token": "^4.0.0", 862 | "registry-url": "^5.0.0", 863 | "semver": "^6.2.0" 864 | }, 865 | "dependencies": { 866 | "semver": { 867 | "version": "6.3.0", 868 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 869 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 870 | "dev": true 871 | } 872 | } 873 | }, 874 | "parseqs": { 875 | "version": "0.0.5", 876 | "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", 877 | "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", 878 | "requires": { 879 | "better-assert": "~1.0.0" 880 | } 881 | }, 882 | "parseuri": { 883 | "version": "0.0.5", 884 | "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", 885 | "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", 886 | "requires": { 887 | "better-assert": "~1.0.0" 888 | } 889 | }, 890 | "picomatch": { 891 | "version": "2.2.2", 892 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", 893 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", 894 | "dev": true 895 | }, 896 | "prepend-http": { 897 | "version": "2.0.0", 898 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", 899 | "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", 900 | "dev": true 901 | }, 902 | "pstree.remy": { 903 | "version": "1.1.7", 904 | "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.7.tgz", 905 | "integrity": "sha512-xsMgrUwRpuGskEzBFkH8NmTimbZ5PcPup0LA8JJkHIm2IMUbQcpo3yeLNWVrufEYjh8YwtSVh0xz6UeWc5Oh5A==", 906 | "dev": true 907 | }, 908 | "pump": { 909 | "version": "3.0.0", 910 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 911 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 912 | "dev": true, 913 | "requires": { 914 | "end-of-stream": "^1.1.0", 915 | "once": "^1.3.1" 916 | } 917 | }, 918 | "pupa": { 919 | "version": "2.0.1", 920 | "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.0.1.tgz", 921 | "integrity": "sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==", 922 | "dev": true, 923 | "requires": { 924 | "escape-goat": "^2.0.0" 925 | } 926 | }, 927 | "rc": { 928 | "version": "1.2.8", 929 | "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", 930 | "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", 931 | "dev": true, 932 | "requires": { 933 | "deep-extend": "^0.6.0", 934 | "ini": "~1.3.0", 935 | "minimist": "^1.2.0", 936 | "strip-json-comments": "~2.0.1" 937 | } 938 | }, 939 | "readdirp": { 940 | "version": "3.4.0", 941 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", 942 | "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", 943 | "dev": true, 944 | "requires": { 945 | "picomatch": "^2.2.1" 946 | } 947 | }, 948 | "registry-auth-token": { 949 | "version": "4.1.1", 950 | "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.1.1.tgz", 951 | "integrity": "sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==", 952 | "dev": true, 953 | "requires": { 954 | "rc": "^1.2.8" 955 | } 956 | }, 957 | "registry-url": { 958 | "version": "5.1.0", 959 | "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", 960 | "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", 961 | "dev": true, 962 | "requires": { 963 | "rc": "^1.2.8" 964 | } 965 | }, 966 | "responselike": { 967 | "version": "1.0.2", 968 | "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", 969 | "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", 970 | "dev": true, 971 | "requires": { 972 | "lowercase-keys": "^1.0.0" 973 | } 974 | }, 975 | "semver-diff": { 976 | "version": "3.1.1", 977 | "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", 978 | "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", 979 | "dev": true, 980 | "requires": { 981 | "semver": "^6.3.0" 982 | }, 983 | "dependencies": { 984 | "semver": { 985 | "version": "6.3.0", 986 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 987 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 988 | "dev": true 989 | } 990 | } 991 | }, 992 | "signal-exit": { 993 | "version": "3.0.3", 994 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", 995 | "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", 996 | "dev": true 997 | }, 998 | "socket.io": { 999 | "version": "2.3.0", 1000 | "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.3.0.tgz", 1001 | "integrity": "sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==", 1002 | "requires": { 1003 | "debug": "~4.1.0", 1004 | "engine.io": "~3.4.0", 1005 | "has-binary2": "~1.0.2", 1006 | "socket.io-adapter": "~1.1.0", 1007 | "socket.io-client": "2.3.0", 1008 | "socket.io-parser": "~3.4.0" 1009 | } 1010 | }, 1011 | "socket.io-adapter": { 1012 | "version": "1.1.2", 1013 | "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", 1014 | "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==" 1015 | }, 1016 | "socket.io-client": { 1017 | "version": "2.3.0", 1018 | "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz", 1019 | "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==", 1020 | "requires": { 1021 | "backo2": "1.0.2", 1022 | "base64-arraybuffer": "0.1.5", 1023 | "component-bind": "1.0.0", 1024 | "component-emitter": "1.2.1", 1025 | "debug": "~4.1.0", 1026 | "engine.io-client": "~3.4.0", 1027 | "has-binary2": "~1.0.2", 1028 | "has-cors": "1.1.0", 1029 | "indexof": "0.0.1", 1030 | "object-component": "0.0.3", 1031 | "parseqs": "0.0.5", 1032 | "parseuri": "0.0.5", 1033 | "socket.io-parser": "~3.3.0", 1034 | "to-array": "0.1.4" 1035 | }, 1036 | "dependencies": { 1037 | "isarray": { 1038 | "version": "2.0.1", 1039 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", 1040 | "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" 1041 | }, 1042 | "ms": { 1043 | "version": "2.0.0", 1044 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1045 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1046 | }, 1047 | "socket.io-parser": { 1048 | "version": "3.3.0", 1049 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", 1050 | "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", 1051 | "requires": { 1052 | "component-emitter": "1.2.1", 1053 | "debug": "~3.1.0", 1054 | "isarray": "2.0.1" 1055 | }, 1056 | "dependencies": { 1057 | "debug": { 1058 | "version": "3.1.0", 1059 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 1060 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 1061 | "requires": { 1062 | "ms": "2.0.0" 1063 | } 1064 | } 1065 | } 1066 | } 1067 | } 1068 | }, 1069 | "socket.io-parser": { 1070 | "version": "3.4.0", 1071 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.0.tgz", 1072 | "integrity": "sha512-/G/VOI+3DBp0+DJKW4KesGnQkQPFmUCbA/oO2QGT6CWxU7hLGWqU3tyuzeSK/dqcyeHsQg1vTe9jiZI8GU9SCQ==", 1073 | "requires": { 1074 | "component-emitter": "1.2.1", 1075 | "debug": "~4.1.0", 1076 | "isarray": "2.0.1" 1077 | }, 1078 | "dependencies": { 1079 | "isarray": { 1080 | "version": "2.0.1", 1081 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", 1082 | "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" 1083 | } 1084 | } 1085 | }, 1086 | "string-width": { 1087 | "version": "4.2.0", 1088 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", 1089 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", 1090 | "dev": true, 1091 | "requires": { 1092 | "emoji-regex": "^8.0.0", 1093 | "is-fullwidth-code-point": "^3.0.0", 1094 | "strip-ansi": "^6.0.0" 1095 | }, 1096 | "dependencies": { 1097 | "ansi-regex": { 1098 | "version": "5.0.0", 1099 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 1100 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 1101 | "dev": true 1102 | }, 1103 | "emoji-regex": { 1104 | "version": "8.0.0", 1105 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1106 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 1107 | "dev": true 1108 | }, 1109 | "is-fullwidth-code-point": { 1110 | "version": "3.0.0", 1111 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1112 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 1113 | "dev": true 1114 | }, 1115 | "strip-ansi": { 1116 | "version": "6.0.0", 1117 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 1118 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 1119 | "dev": true, 1120 | "requires": { 1121 | "ansi-regex": "^5.0.0" 1122 | } 1123 | } 1124 | } 1125 | }, 1126 | "strip-ansi": { 1127 | "version": "5.2.0", 1128 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 1129 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 1130 | "dev": true, 1131 | "requires": { 1132 | "ansi-regex": "^4.1.0" 1133 | } 1134 | }, 1135 | "strip-json-comments": { 1136 | "version": "2.0.1", 1137 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 1138 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 1139 | "dev": true 1140 | }, 1141 | "supports-color": { 1142 | "version": "5.5.0", 1143 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1144 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1145 | "dev": true, 1146 | "requires": { 1147 | "has-flag": "^3.0.0" 1148 | } 1149 | }, 1150 | "term-size": { 1151 | "version": "2.2.0", 1152 | "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz", 1153 | "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==", 1154 | "dev": true 1155 | }, 1156 | "to-array": { 1157 | "version": "0.1.4", 1158 | "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", 1159 | "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" 1160 | }, 1161 | "to-readable-stream": { 1162 | "version": "1.0.0", 1163 | "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", 1164 | "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", 1165 | "dev": true 1166 | }, 1167 | "to-regex-range": { 1168 | "version": "5.0.1", 1169 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1170 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1171 | "dev": true, 1172 | "requires": { 1173 | "is-number": "^7.0.0" 1174 | } 1175 | }, 1176 | "touch": { 1177 | "version": "3.1.0", 1178 | "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", 1179 | "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", 1180 | "dev": true, 1181 | "requires": { 1182 | "nopt": "~1.0.10" 1183 | } 1184 | }, 1185 | "type-fest": { 1186 | "version": "0.8.1", 1187 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", 1188 | "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", 1189 | "dev": true 1190 | }, 1191 | "typedarray-to-buffer": { 1192 | "version": "3.1.5", 1193 | "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", 1194 | "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", 1195 | "dev": true, 1196 | "requires": { 1197 | "is-typedarray": "^1.0.0" 1198 | } 1199 | }, 1200 | "undefsafe": { 1201 | "version": "2.0.3", 1202 | "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", 1203 | "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==", 1204 | "dev": true, 1205 | "requires": { 1206 | "debug": "^2.2.0" 1207 | }, 1208 | "dependencies": { 1209 | "debug": { 1210 | "version": "2.6.9", 1211 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1212 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1213 | "dev": true, 1214 | "requires": { 1215 | "ms": "2.0.0" 1216 | } 1217 | }, 1218 | "ms": { 1219 | "version": "2.0.0", 1220 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1221 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 1222 | "dev": true 1223 | } 1224 | } 1225 | }, 1226 | "unique-string": { 1227 | "version": "2.0.0", 1228 | "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", 1229 | "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", 1230 | "dev": true, 1231 | "requires": { 1232 | "crypto-random-string": "^2.0.0" 1233 | } 1234 | }, 1235 | "update-notifier": { 1236 | "version": "4.1.0", 1237 | "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.0.tgz", 1238 | "integrity": "sha512-w3doE1qtI0/ZmgeoDoARmI5fjDoT93IfKgEGqm26dGUOh8oNpaSTsGNdYRN/SjOuo10jcJGwkEL3mroKzktkew==", 1239 | "dev": true, 1240 | "requires": { 1241 | "boxen": "^4.2.0", 1242 | "chalk": "^3.0.0", 1243 | "configstore": "^5.0.1", 1244 | "has-yarn": "^2.1.0", 1245 | "import-lazy": "^2.1.0", 1246 | "is-ci": "^2.0.0", 1247 | "is-installed-globally": "^0.3.1", 1248 | "is-npm": "^4.0.0", 1249 | "is-yarn-global": "^0.3.0", 1250 | "latest-version": "^5.0.0", 1251 | "pupa": "^2.0.1", 1252 | "semver-diff": "^3.1.1", 1253 | "xdg-basedir": "^4.0.0" 1254 | } 1255 | }, 1256 | "url-parse-lax": { 1257 | "version": "3.0.0", 1258 | "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", 1259 | "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", 1260 | "dev": true, 1261 | "requires": { 1262 | "prepend-http": "^2.0.0" 1263 | } 1264 | }, 1265 | "widest-line": { 1266 | "version": "3.1.0", 1267 | "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", 1268 | "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", 1269 | "dev": true, 1270 | "requires": { 1271 | "string-width": "^4.0.0" 1272 | } 1273 | }, 1274 | "wrappy": { 1275 | "version": "1.0.2", 1276 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1277 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1278 | "dev": true 1279 | }, 1280 | "write-file-atomic": { 1281 | "version": "3.0.3", 1282 | "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", 1283 | "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", 1284 | "dev": true, 1285 | "requires": { 1286 | "imurmurhash": "^0.1.4", 1287 | "is-typedarray": "^1.0.0", 1288 | "signal-exit": "^3.0.2", 1289 | "typedarray-to-buffer": "^3.1.5" 1290 | } 1291 | }, 1292 | "ws": { 1293 | "version": "7.3.0", 1294 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz", 1295 | "integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w==" 1296 | }, 1297 | "xdg-basedir": { 1298 | "version": "4.0.0", 1299 | "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", 1300 | "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", 1301 | "dev": true 1302 | }, 1303 | "xmlhttprequest-ssl": { 1304 | "version": "1.5.5", 1305 | "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", 1306 | "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" 1307 | }, 1308 | "yeast": { 1309 | "version": "0.1.2", 1310 | "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", 1311 | "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" 1312 | } 1313 | } 1314 | } 1315 | -------------------------------------------------------------------------------- /remote-access-app/server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "description": "A minimal Electron application", 5 | "main": "main.js", 6 | "scripts": { 7 | "start": "node server.js", 8 | "start:old": "nodemon --exec electron ." 9 | }, 10 | "repository": "https://github.com/electron/electron-quick-start", 11 | "keywords": [ 12 | "Electron", 13 | "quick", 14 | "start", 15 | "tutorial", 16 | "demo" 17 | ], 18 | "author": "Erick Wendel", 19 | "license": "CC0-1.0", 20 | "devDependencies": { 21 | "nodemon": "^2.0.3" 22 | }, 23 | "dependencies": { 24 | "socket.io": "^2.3.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /remote-access-app/server/server.js: -------------------------------------------------------------------------------- 1 | const { promises: { readFile } } = require('fs'); 2 | 3 | const server = require('http').createServer(handler) 4 | const io = require('socket.io')(server); 5 | 6 | 7 | let broadcaster 8 | const port = process.env.PORT || 4000 9 | 10 | async function handler(req, res) { 11 | const data = await readFile(__dirname + '/index.html') 12 | res.writeHead(200); 13 | res.end(data); 14 | } 15 | 16 | 17 | io.sockets.on("error", e => console.log(e)); 18 | io.sockets.on("connection", socket => { 19 | console.log('connection received!', socket.id) 20 | 21 | socket.on("broadcaster", () => { 22 | broadcaster = socket.id; 23 | socket.broadcast.emit("broadcaster"); 24 | }); 25 | socket.on("watcher", () => { 26 | socket.to(broadcaster).emit("watcher", socket.id); 27 | }); 28 | socket.on("offer", (id, message) => { 29 | console.log('offer', message) 30 | socket.to(id).emit("offer", socket.id, message); 31 | }); 32 | socket.on("answer", (id, message) => { 33 | console.log('answer', message) 34 | socket.to(id).emit("answer", socket.id, message); 35 | }); 36 | socket.on("candidate", (id, message) => { 37 | console.log('candidate', message) 38 | socket.to(id).emit("candidate", socket.id, message); 39 | }); 40 | socket.on("disconnect", () => { 41 | socket.to(broadcaster).emit("disconnectPeer", socket.id); 42 | }); 43 | 44 | 45 | }); 46 | 47 | server.listen(port, () => console.log(`Server is running on port ${port}`)); 48 | 49 | 50 | //Move the mouse down by 100 pixels. 51 | // setInterval(() => { 52 | 53 | // const mouse = robot.getMousePos(); 54 | // console.log("Mouse is at x:" + mouse.x + " y:" + mouse.y); 55 | // // robot.moveMouse(mouse.x, mouse.y + 100); 56 | // }, 1000); 57 | 58 | //Left click! 59 | // robot.mouseClick(); --------------------------------------------------------------------------------