commit
bbaecce036
@ -1,4 +1,5 @@
|
||||
import { ServerRegistry } from './servers'
|
||||
import { SocketManager } from './socket'
|
||||
import { SortController } from './sort'
|
||||
import { GraphDisplayManager } from './graph'
|
||||
import { MojangUpdater } from './mojang'
|
||||
@ -13,6 +14,7 @@ export class App {
|
||||
this.tooltip = new Tooltip()
|
||||
this.caption = new Caption()
|
||||
this.serverRegistry = new ServerRegistry(this)
|
||||
this.socketManager = new SocketManager(this)
|
||||
this.sortController = new SortController(this)
|
||||
this.graphDisplayManager = new GraphDisplayManager(this)
|
||||
this.mojangUpdater = new MojangUpdater()
|
||||
@ -22,6 +24,11 @@ export class App {
|
||||
this._taskIds = []
|
||||
}
|
||||
|
||||
// Called once the DOM is ready and the app can begin setup
|
||||
init () {
|
||||
this.socketManager.createWebSocket()
|
||||
}
|
||||
|
||||
setPageReady (isReady) {
|
||||
document.getElementById('push').style.display = isReady ? 'block' : 'none'
|
||||
document.getElementById('footer').style.display = isReady ? 'block' : 'none'
|
||||
@ -60,6 +67,7 @@ export class App {
|
||||
|
||||
// Reset individual tracker elements to flush any held data
|
||||
this.serverRegistry.reset()
|
||||
this.socketManager.reset()
|
||||
this.sortController.reset()
|
||||
this.graphDisplayManager.reset()
|
||||
this.mojangUpdater.reset()
|
||||
@ -81,9 +89,6 @@ export class App {
|
||||
document.getElementById('stat_totalPlayers').innerText = 0
|
||||
document.getElementById('stat_networks').innerText = 0
|
||||
|
||||
// Modify page state to display loading overlay
|
||||
this.caption.set('Lost connection!')
|
||||
|
||||
this.setPageReady(false)
|
||||
}
|
||||
|
||||
|
@ -1,123 +1,9 @@
|
||||
import { App } from './app'
|
||||
|
||||
import io from 'socket.io-client'
|
||||
|
||||
const app = new App()
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const socket = io.connect({
|
||||
reconnect: true,
|
||||
reconnectDelay: 1000,
|
||||
reconnectionAttempts: 10
|
||||
})
|
||||
|
||||
// The backend will automatically push data once connected
|
||||
socket.on('connect', function () {
|
||||
app.caption.set('Loading...')
|
||||
})
|
||||
|
||||
socket.on('disconnect', function () {
|
||||
app.handleDisconnect()
|
||||
|
||||
// Reset modified DOM structures
|
||||
document.getElementById('big-graph-mobile-load-request').style.display = 'none'
|
||||
})
|
||||
|
||||
socket.on('historyGraph', function (data) {
|
||||
// Consider the graph visible since a payload has been received
|
||||
// This is used for the manual graph load request behavior
|
||||
app.graphDisplayManager.isVisible = true
|
||||
|
||||
app.graphDisplayManager.buildPlotInstance(data)
|
||||
|
||||
// Build checkbox elements for graph controls
|
||||
let lastRowCounter = 0
|
||||
let controlsHTML = ''
|
||||
|
||||
app.serverRegistry.getServerRegistrations()
|
||||
.map(serverRegistration => serverRegistration.data.name)
|
||||
.sort()
|
||||
.forEach(serverName => {
|
||||
const serverRegistration = app.serverRegistry.getServerRegistration(serverName)
|
||||
|
||||
controlsHTML += '<td>' +
|
||||
'<input type="checkbox" class="graph-control" minetrack-server-id="' + serverRegistration.serverId + '" ' + (serverRegistration.isVisible ? 'checked' : '') + '>' +
|
||||
' ' + serverName +
|
||||
'</input></td>'
|
||||
|
||||
// Occasionally break table rows using a magic number
|
||||
if (++lastRowCounter % 6 === 0) {
|
||||
controlsHTML += '</tr><tr>'
|
||||
}
|
||||
})
|
||||
|
||||
// Apply generated HTML and show controls
|
||||
document.getElementById('big-graph-checkboxes').innerHTML = '<table><tr>' +
|
||||
controlsHTML +
|
||||
'</tr></table>'
|
||||
|
||||
document.getElementById('big-graph-controls').style.display = 'block'
|
||||
|
||||
// Bind click event for updating graph data
|
||||
app.graphDisplayManager.initEventListeners()
|
||||
})
|
||||
|
||||
socket.on('add', function (data) {
|
||||
data.forEach(app.addServer)
|
||||
})
|
||||
|
||||
socket.on('update', function (data) {
|
||||
// The backend may send "update" events prior to receiving all "add" events
|
||||
// A server has only been added once it's ServerRegistration is defined
|
||||
// Checking undefined protects from this race condition
|
||||
const serverRegistration = app.serverRegistry.getServerRegistration(data.serverId)
|
||||
|
||||
if (serverRegistration) {
|
||||
serverRegistration.updateServerStatus(data, false, app.publicConfig.minecraftVersions)
|
||||
}
|
||||
|
||||
// Use update payloads to conditionally append data to graph
|
||||
// Skip any incoming updates if the graph is disabled
|
||||
if (data.updateHistoryGraph && app.graphDisplayManager.isVisible) {
|
||||
// Update may not be successful, safely append 0 points
|
||||
const playerCount = data.result ? data.result.players.online : 0
|
||||
|
||||
app.graphDisplayManager.addGraphPoint(serverRegistration.serverId, data.timestamp, playerCount)
|
||||
|
||||
// Only redraw the graph if not mutating hidden data
|
||||
if (serverRegistration.isVisible) {
|
||||
app.graphDisplayManager.requestRedraw()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
socket.on('updateMojangServices', function (data) {
|
||||
app.mojangUpdater.updateStatus(data)
|
||||
})
|
||||
|
||||
socket.on('setPublicConfig', function (data) {
|
||||
app.setPublicConfig(data)
|
||||
|
||||
// Display the main page component
|
||||
// Called here instead of syncComplete so the DOM can be drawn prior to the graphs being drawn
|
||||
// Otherwise flot.js will cause visual alignment bugs
|
||||
app.setPageReady(true)
|
||||
|
||||
// Allow the graphDisplayManager to control whether or not the historical graph is loaded
|
||||
// Defer to isGraphVisible from the publicConfig to understand if the frontend will ever receive a graph payload
|
||||
if (data.isGraphVisible) {
|
||||
if (app.graphDisplayManager.isVisible) {
|
||||
socket.emit('requestHistoryGraph')
|
||||
} else {
|
||||
document.getElementById('big-graph-mobile-load-request').style.display = 'block'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Fired once the backend has sent all requested data
|
||||
socket.on('syncComplete', function () {
|
||||
app.handleSyncComplete()
|
||||
})
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
app.init()
|
||||
|
||||
window.addEventListener('resize', function () {
|
||||
app.percentageBar.redraw()
|
||||
@ -128,7 +14,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
|
||||
document.getElementById('big-graph-mobile-load-request-button').addEventListener('click', function () {
|
||||
// Send a graph data request to the backend
|
||||
socket.emit('requestHistoryGraph')
|
||||
app.socketManager.sendHistoryGraphRequest()
|
||||
|
||||
// Hide the activation link to avoid multiple requests
|
||||
document.getElementById('big-graph-mobile-load-request').style.display = 'none'
|
||||
|
191
assets/js/socket.js
Normal file
191
assets/js/socket.js
Normal file
@ -0,0 +1,191 @@
|
||||
export class SocketManager {
|
||||
constructor (app) {
|
||||
this._app = app
|
||||
this._hasRequestedHistoryGraph = false
|
||||
this._reconnectDelayBase = 0
|
||||
}
|
||||
|
||||
reset () {
|
||||
this._hasRequestedHistoryGraph = false
|
||||
}
|
||||
|
||||
createWebSocket () {
|
||||
this._webSocket = new WebSocket('ws://' + location.host)
|
||||
|
||||
// The backend will automatically push data once connected
|
||||
this._webSocket.onopen = () => {
|
||||
this._app.caption.set('Loading...')
|
||||
|
||||
// Reset reconnection scheduling since the WebSocket has been established
|
||||
this._reconnectDelayBase = 0
|
||||
}
|
||||
|
||||
this._webSocket.onclose = (event) => {
|
||||
this._app.handleDisconnect()
|
||||
|
||||
// Modify page state to display loading overlay
|
||||
// Code 1006 denotes "Abnormal closure", most likely from the server or client losing connection
|
||||
// See https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
|
||||
// Treat other codes as active errors (besides connectivity errors) when displaying the message
|
||||
if (event.code === 1006) {
|
||||
this._app.caption.set('Lost connection!')
|
||||
} else {
|
||||
this._app.caption.set('Disconnected due to error.')
|
||||
}
|
||||
|
||||
// Reset modified DOM structures
|
||||
document.getElementById('big-graph-mobile-load-request').style.display = 'none'
|
||||
|
||||
// Schedule socket reconnection attempt
|
||||
this.scheduleReconnect()
|
||||
}
|
||||
|
||||
this._webSocket.onmessage = (message) => {
|
||||
const payload = JSON.parse(message.data)
|
||||
|
||||
switch (payload.message) {
|
||||
case 'init':
|
||||
this._app.setPublicConfig(payload.config)
|
||||
|
||||
// Display the main page component
|
||||
// Called here instead of syncComplete so the DOM can be drawn prior to the graphs being drawn
|
||||
// Otherwise flot.js will cause visual alignment bugs
|
||||
this._app.setPageReady(true)
|
||||
|
||||
// Allow the graphDisplayManager to control whether or not the historical graph is loaded
|
||||
// Defer to isGraphVisible from the publicConfig to understand if the frontend will ever receive a graph payload
|
||||
if (this._app.publicConfig.isGraphVisible) {
|
||||
if (this._app.graphDisplayManager.isVisible) {
|
||||
this.sendHistoryGraphRequest()
|
||||
} else {
|
||||
document.getElementById('big-graph-mobile-load-request').style.display = 'block'
|
||||
}
|
||||
}
|
||||
|
||||
payload.servers.forEach(this._app.addServer)
|
||||
|
||||
if (payload.mojangServices) {
|
||||
this._app.mojangUpdater.updateStatus(payload.mojangServices)
|
||||
}
|
||||
|
||||
// Init payload contains all data needed to render the page
|
||||
// Alert the app it is ready
|
||||
this._app.handleSyncComplete()
|
||||
|
||||
break
|
||||
|
||||
case 'updateServer': {
|
||||
// The backend may send "update" events prior to receiving all "add" events
|
||||
// A server has only been added once it's ServerRegistration is defined
|
||||
// Checking undefined protects from this race condition
|
||||
const serverRegistration = this._app.serverRegistry.getServerRegistration(payload.serverId)
|
||||
|
||||
if (serverRegistration) {
|
||||
serverRegistration.updateServerStatus(payload, false, this._app.publicConfig.minecraftVersions)
|
||||
}
|
||||
|
||||
// Use update payloads to conditionally append data to graph
|
||||
// Skip any incoming updates if the graph is disabled
|
||||
if (payload.updateHistoryGraph && this._app.graphDisplayManager.isVisible) {
|
||||
// Update may not be successful, safely append 0 points
|
||||
const playerCount = payload.result ? payload.result.players.online : 0
|
||||
|
||||
this._app.graphDisplayManager.addGraphPoint(serverRegistration.serverId, payload.timestamp, playerCount)
|
||||
|
||||
// Only redraw the graph if not mutating hidden data
|
||||
if (serverRegistration.isVisible) {
|
||||
this._app.graphDisplayManager.requestRedraw()
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case 'updateMojangServices': {
|
||||
this._app.mojangUpdater.updateStatus(payload)
|
||||
break
|
||||
}
|
||||
|
||||
case 'historyGraph': {
|
||||
// Consider the graph visible since a payload has been received
|
||||
// This is used for the manual graph load request behavior
|
||||
this._app.graphDisplayManager.isVisible = true
|
||||
|
||||
this._app.graphDisplayManager.buildPlotInstance(payload.graphData)
|
||||
|
||||
// Build checkbox elements for graph controls
|
||||
let lastRowCounter = 0
|
||||
let controlsHTML = ''
|
||||
|
||||
this._app.serverRegistry.getServerRegistrations()
|
||||
.map(serverRegistration => serverRegistration.data.name)
|
||||
.sort()
|
||||
.forEach(serverName => {
|
||||
const serverRegistration = this._app.serverRegistry.getServerRegistration(serverName)
|
||||
|
||||
controlsHTML += '<td>' +
|
||||
'<input type="checkbox" class="graph-control" minetrack-server-id="' + serverRegistration.serverId + '" ' + (serverRegistration.isVisible ? 'checked' : '') + '>' +
|
||||
' ' + serverName +
|
||||
'</input></td>'
|
||||
|
||||
// Occasionally break table rows using a magic number
|
||||
if (++lastRowCounter % 6 === 0) {
|
||||
controlsHTML += '</tr><tr>'
|
||||
}
|
||||
})
|
||||
|
||||
// Apply generated HTML and show controls
|
||||
document.getElementById('big-graph-checkboxes').innerHTML = '<table><tr>' +
|
||||
controlsHTML +
|
||||
'</tr></table>'
|
||||
|
||||
document.getElementById('big-graph-controls').style.display = 'block'
|
||||
|
||||
// Bind click event for updating graph data
|
||||
this._app.graphDisplayManager.initEventListeners()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scheduleReconnect () {
|
||||
// Release any active WebSocket references
|
||||
this._webSocket = undefined
|
||||
|
||||
this._reconnectDelayBase++
|
||||
|
||||
// Exponential backoff for reconnection attempts
|
||||
// Clamp ceiling value to 30 seconds
|
||||
this._reconnectDelaySeconds = Math.min((this._reconnectDelayBase * this._reconnectDelayBase), 30)
|
||||
|
||||
const reconnectInterval = setInterval(() => {
|
||||
this._reconnectDelaySeconds--
|
||||
|
||||
if (this._reconnectDelaySeconds === 0) {
|
||||
// Explicitly clear interval, this avoids race conditions
|
||||
// #clearInterval first to avoid potential errors causing pre-mature returns
|
||||
clearInterval(reconnectInterval)
|
||||
|
||||
// Update displayed text
|
||||
this._app.caption.set('Reconnecting...')
|
||||
|
||||
// Attempt reconnection
|
||||
// Only attempt when reconnectDelaySeconds === 0 and not <= 0, otherwise multiple attempts may be started
|
||||
this.createWebSocket()
|
||||
} else if (this._reconnectDelaySeconds > 0) {
|
||||
// Update displayed text
|
||||
this._app.caption.set('Reconnecting in ' + this._reconnectDelaySeconds + 's...')
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
sendHistoryGraphRequest () {
|
||||
if (!this._hasRequestedHistoryGraph) {
|
||||
this._hasRequestedHistoryGraph = true
|
||||
|
||||
// Send request as a plain text string to avoid the server needing to parse JSON
|
||||
// This is mostly to simplify the backend server's need for error handling
|
||||
this._webSocket.send('requestHistoryGraph')
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,8 @@
|
||||
**5.3.0** *(May 5 2020)*
|
||||
- Replaces socket.io library (and dependency) with vanilla WebSockets.
|
||||
- Frontend reconnect behavior has been improved to use exponential backoff behavior (up to 30 seconds) with unlimited retries.
|
||||
- The "Lost connection!" message will now show the reconnection attempt timer.
|
||||
|
||||
**5.2.1** *(May 1 2020)*
|
||||
- The historical graph will now auto scale its yaxis steps.
|
||||
|
||||
|
64
lib/app.js
64
lib/app.js
@ -2,6 +2,7 @@ const Database = require('./database')
|
||||
const MojangUpdater = require('./mojang')
|
||||
const PingController = require('./ping')
|
||||
const Server = require('./server')
|
||||
const MessageOf = require('./message')
|
||||
|
||||
const config = require('../config')
|
||||
const minecraftVersions = require('../minecraft_versions')
|
||||
@ -36,43 +37,46 @@ class App {
|
||||
|
||||
handleClientConnection = (client) => {
|
||||
if (config.logToDatabase) {
|
||||
client.on('requestHistoryGraph', () => {
|
||||
// Send historical graphData built from all serverRegistrations
|
||||
const graphData = {}
|
||||
client.on('message', (message) => {
|
||||
if (message === 'requestHistoryGraph') {
|
||||
// Send historical graphData built from all serverRegistrations
|
||||
const graphData = {}
|
||||
|
||||
this.serverRegistrations.forEach((serverRegistration) => {
|
||||
graphData[serverRegistration.serverId] = serverRegistration.graphData
|
||||
})
|
||||
this.serverRegistrations.forEach((serverRegistration) => {
|
||||
graphData[serverRegistration.serverId] = serverRegistration.graphData
|
||||
})
|
||||
|
||||
client.emit('historyGraph', graphData)
|
||||
// Send graphData in object wrapper to avoid needing to explicity filter
|
||||
// any header data being appended by #MessageOf since the graph data is fed
|
||||
// directly into the flot.js graphing system
|
||||
client.send(MessageOf('historyGraph', {
|
||||
graphData: graphData
|
||||
}))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
client.emit('setPublicConfig', (() => {
|
||||
// Remap minecraftVersion entries into name values
|
||||
const minecraftVersionNames = {}
|
||||
Object.keys(minecraftVersions).forEach(function (key) {
|
||||
minecraftVersionNames[key] = minecraftVersions[key].map(version => version.name)
|
||||
})
|
||||
const initMessage = {
|
||||
config: (() => {
|
||||
// Remap minecraftVersion entries into name values
|
||||
const minecraftVersionNames = {}
|
||||
Object.keys(minecraftVersions).forEach(function (key) {
|
||||
minecraftVersionNames[key] = minecraftVersions[key].map(version => version.name)
|
||||
})
|
||||
|
||||
// Send configuration data for rendering the page
|
||||
return {
|
||||
graphDuration: config.graphDuration,
|
||||
servers: this.serverRegistrations.map(serverRegistration => serverRegistration.data),
|
||||
minecraftVersions: minecraftVersionNames,
|
||||
isGraphVisible: config.logToDatabase
|
||||
}
|
||||
})())
|
||||
// Send configuration data for rendering the page
|
||||
return {
|
||||
graphDuration: config.graphDuration,
|
||||
servers: this.serverRegistrations.map(serverRegistration => serverRegistration.data),
|
||||
minecraftVersions: minecraftVersionNames,
|
||||
isGraphVisible: config.logToDatabase
|
||||
}
|
||||
})(),
|
||||
mojangServices: this.mojangUpdater.getLastUpdate(),
|
||||
servers: this.serverRegistrations.map(serverRegistration => serverRegistration.getPingHistory())
|
||||
}
|
||||
|
||||
// Send last Mojang update, if any
|
||||
this.mojangUpdater.sendLastUpdate(client)
|
||||
|
||||
// Send pingHistory of all ServerRegistrations
|
||||
client.emit('add', this.serverRegistrations.map(serverRegistration => serverRegistration.getPingHistory()))
|
||||
|
||||
// Always send last
|
||||
// This tells the frontend to do final processing and render
|
||||
client.emit('syncComplete')
|
||||
client.send(MessageOf('init', initMessage))
|
||||
}
|
||||
}
|
||||
|
||||
|
6
lib/message.js
Normal file
6
lib/message.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = function MessageOf (name, data) {
|
||||
return JSON.stringify({
|
||||
message: name,
|
||||
...data
|
||||
})
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
const request = require('request')
|
||||
|
||||
const logger = require('./logger')
|
||||
const MessageOf = require('./message')
|
||||
|
||||
const config = require('../config')
|
||||
|
||||
@ -65,14 +66,12 @@ class MojangUpdater {
|
||||
if (this._hasUpdated) {
|
||||
this._hasUpdated = false
|
||||
|
||||
this._app.server.broadcast('updateMojangServices', this._services)
|
||||
this._app.server.broadcast(MessageOf('updateMojangServices', this._services))
|
||||
}
|
||||
}
|
||||
|
||||
sendLastUpdate (client) {
|
||||
if (this._services) {
|
||||
client.emit('updateMojangServices', this._services)
|
||||
}
|
||||
getLastUpdate () {
|
||||
return this._services
|
||||
}
|
||||
|
||||
handleServiceUpdate (url, color) {
|
||||
|
@ -4,6 +4,7 @@ const minecraftJavaPing = require('mc-ping-updated')
|
||||
const minecraftBedrockPing = require('mcpe-ping-fixed')
|
||||
|
||||
const logger = require('./logger')
|
||||
const MessageOf = require('./message')
|
||||
|
||||
const config = require('../config')
|
||||
|
||||
@ -125,7 +126,9 @@ class PingController {
|
||||
// Generate a combined update payload
|
||||
// This includes any modified fields and flags used by the frontend
|
||||
// This will not be cached and can contain live metadata
|
||||
this._app.server.broadcast('update', serverRegistration.getUpdate(timestamp, resp, err, version, updateHistoryGraph))
|
||||
const updateMessage = serverRegistration.getUpdate(timestamp, resp, err, version, updateHistoryGraph)
|
||||
|
||||
this._app.server.broadcast(MessageOf('updateServer', updateMessage))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
const http = require('http')
|
||||
|
||||
const WebSocket = require('ws')
|
||||
const finalHttpHandler = require('finalhandler')
|
||||
const serveStatic = require('serve-static')
|
||||
const io = require('socket.io')
|
||||
|
||||
const logger = require('./logger')
|
||||
|
||||
@ -12,52 +12,65 @@ function getRemoteAddr (req) {
|
||||
|
||||
class Server {
|
||||
constructor (clientSocketHandler) {
|
||||
this._clientSocketHandler = clientSocketHandler
|
||||
this._connectedSockets = 0
|
||||
this.createHttpServer()
|
||||
this.createWebSocketServer(clientSocketHandler)
|
||||
}
|
||||
|
||||
this._http = http.createServer(this.handleHttpRequest)
|
||||
createHttpServer () {
|
||||
const distServeStatic = serveStatic('dist/')
|
||||
const faviconsServeStatic = serveStatic('favicons/')
|
||||
|
||||
this._distServeStatic = serveStatic('dist/')
|
||||
this._faviconsServeStatic = serveStatic('favicons/')
|
||||
this._http = http.createServer((req, res) => {
|
||||
logger.log('info', '%s requested: %s', getRemoteAddr(req), req.url)
|
||||
|
||||
// Attempt to handle req using distServeStatic, otherwise fail over to faviconServeStatic
|
||||
// If faviconServeStatic fails, pass to finalHttpHandler to terminate
|
||||
distServeStatic(req, res, () => {
|
||||
faviconsServeStatic(req, res, finalHttpHandler(req, res))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
createWebSocketServer (proxyClientSocketHandler) {
|
||||
this._wss = new WebSocket.Server({
|
||||
server: this._http
|
||||
})
|
||||
|
||||
this._wss.on('connection', (client, req) => {
|
||||
logger.log('info', '%s connected, total clients: %d', getRemoteAddr(req), this.getConnectedClients())
|
||||
|
||||
// Bind disconnect event for logging
|
||||
client.on('close', () => {
|
||||
logger.log('info', '%s disconnected, total clients: %d', getRemoteAddr(req), this.getConnectedClients())
|
||||
})
|
||||
|
||||
// Pass client off to proxy handler
|
||||
proxyClientSocketHandler(client)
|
||||
})
|
||||
}
|
||||
|
||||
listen (host, port) {
|
||||
this._http.listen(port, host)
|
||||
|
||||
this._io = io.listen(this._http)
|
||||
this._io.on('connect', this.handleClientSocket)
|
||||
|
||||
logger.log('info', 'Started on %s:%d', host, port)
|
||||
}
|
||||
|
||||
broadcast (event, payload) {
|
||||
this._io.sockets.emit(event, payload)
|
||||
}
|
||||
|
||||
handleHttpRequest = (req, res) => {
|
||||
logger.log('info', '%s requested: %s', getRemoteAddr(req), req.url)
|
||||
|
||||
// Attempt to handle req using distServeStatic, otherwise fail over to faviconServeStatic
|
||||
// If faviconServeStatic fails, pass to finalHttpHandler to terminate
|
||||
this._distServeStatic(req, res, () => {
|
||||
this._faviconsServeStatic(req, res, finalHttpHandler(req, res))
|
||||
broadcast (payload) {
|
||||
this._wss.clients.forEach(client => {
|
||||
if (client.readyState === WebSocket.OPEN) {
|
||||
client.send(payload)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
handleClientSocket = (client) => {
|
||||
this._connectedSockets++
|
||||
|
||||
logger.log('info', '%s connected, total clients: %d', getRemoteAddr(client.request), this._connectedSockets)
|
||||
|
||||
// Bind disconnect event for logging
|
||||
client.on('disconnect', () => {
|
||||
this._connectedSockets--
|
||||
|
||||
logger.log('info', '%s disconnected, total clients: %d', getRemoteAddr(client.request), this._connectedSockets)
|
||||
getConnectedClients () {
|
||||
let count = 0
|
||||
this._wss.clients.forEach(client => {
|
||||
if (client.readyState === WebSocket.OPEN) {
|
||||
count++
|
||||
}
|
||||
})
|
||||
|
||||
// Pass client off to proxy handler
|
||||
this._clientSocketHandler(client)
|
||||
return count
|
||||
}
|
||||
}
|
||||
|
||||
|
300
package-lock.json
generated
300
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "minetrack",
|
||||
"version": "5.2.1",
|
||||
"version": "5.3.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@ -1132,15 +1132,6 @@
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
|
||||
},
|
||||
"accepts": {
|
||||
"version": "1.3.7",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
|
||||
"integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
|
||||
"requires": {
|
||||
"mime-types": "~2.1.24",
|
||||
"negotiator": "0.6.2"
|
||||
}
|
||||
},
|
||||
"acorn": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz",
|
||||
@ -1177,11 +1168,6 @@
|
||||
"integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==",
|
||||
"dev": true
|
||||
},
|
||||
"after": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
|
||||
"integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8="
|
||||
},
|
||||
"ajv": {
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz",
|
||||
@ -1334,11 +1320,6 @@
|
||||
"es-abstract": "^1.17.0-next.1"
|
||||
}
|
||||
},
|
||||
"arraybuffer.slice": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
|
||||
"integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog=="
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
|
||||
@ -1422,7 +1403,8 @@
|
||||
"async-limiter": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
|
||||
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
|
||||
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
|
||||
"dev": true
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
@ -1517,11 +1499,6 @@
|
||||
"lodash.clone": "^4.5.0"
|
||||
}
|
||||
},
|
||||
"backo2": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
|
||||
"integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
@ -1582,22 +1559,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"base64-arraybuffer": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
|
||||
"integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg="
|
||||
},
|
||||
"base64-js": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
|
||||
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==",
|
||||
"dev": true
|
||||
},
|
||||
"base64id": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
|
||||
"integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="
|
||||
},
|
||||
"bcrypt-pbkdf": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
@ -1606,14 +1573,6 @@
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
},
|
||||
"better-assert": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
|
||||
"integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
|
||||
"requires": {
|
||||
"callsite": "1.0.0"
|
||||
}
|
||||
},
|
||||
"binary-extensions": {
|
||||
"version": "1.13.1",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
|
||||
@ -1629,11 +1588,6 @@
|
||||
"file-uri-to-path": "1.0.0"
|
||||
}
|
||||
},
|
||||
"blob": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
|
||||
"integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig=="
|
||||
},
|
||||
"bn.js": {
|
||||
"version": "4.11.8",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
|
||||
@ -1836,6 +1790,15 @@
|
||||
"integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
|
||||
"dev": true
|
||||
},
|
||||
"bufferutil": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.1.tgz",
|
||||
"integrity": "sha512-xowrxvpxojqkagPcWRQVXZl0YXhRhAtBEIq3VoER1NH5Mw1n1o0ojdspp+GS2J//2gCVyrzQDApQ4unGF+QOoA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"node-gyp-build": "~3.7.0"
|
||||
}
|
||||
},
|
||||
"bufferview": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bufferview/-/bufferview-1.0.1.tgz",
|
||||
@ -1905,11 +1868,6 @@
|
||||
"caller-callsite": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"callsite": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
|
||||
"integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA="
|
||||
},
|
||||
"callsites": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
||||
@ -2207,20 +2165,11 @@
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"component-bind": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
|
||||
"integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E="
|
||||
},
|
||||
"component-emitter": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
|
||||
"integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
|
||||
},
|
||||
"component-inherit": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
|
||||
"integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM="
|
||||
"integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
@ -2279,11 +2228,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"cookie": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
|
||||
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
|
||||
},
|
||||
"copy-descriptor": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
|
||||
@ -2735,6 +2679,7 @@
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
@ -3024,59 +2969,6 @@
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
|
||||
},
|
||||
"engine.io": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.4.0.tgz",
|
||||
"integrity": "sha512-XCyYVWzcHnK5cMz7G4VTu2W7zJS7SM1QkcelghyIk/FmobWBtXE7fwhBusEKvCSqc3bMh8fNFMlUkCKTFRxH2w==",
|
||||
"requires": {
|
||||
"accepts": "~1.3.4",
|
||||
"base64id": "2.0.0",
|
||||
"cookie": "0.3.1",
|
||||
"debug": "~4.1.0",
|
||||
"engine.io-parser": "~2.2.0",
|
||||
"ws": "^7.1.2"
|
||||
}
|
||||
},
|
||||
"engine.io-client": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.0.tgz",
|
||||
"integrity": "sha512-a4J5QO2k99CM2a0b12IznnyQndoEvtA4UAldhGzKqnHf42I3Qs2W5SPnDvatZRcMaNZs4IevVicBPayxYt6FwA==",
|
||||
"requires": {
|
||||
"component-emitter": "1.2.1",
|
||||
"component-inherit": "0.0.3",
|
||||
"debug": "~4.1.0",
|
||||
"engine.io-parser": "~2.2.0",
|
||||
"has-cors": "1.1.0",
|
||||
"indexof": "0.0.1",
|
||||
"parseqs": "0.0.5",
|
||||
"parseuri": "0.0.5",
|
||||
"ws": "~6.1.0",
|
||||
"xmlhttprequest-ssl": "~1.5.4",
|
||||
"yeast": "0.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"ws": {
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz",
|
||||
"integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==",
|
||||
"requires": {
|
||||
"async-limiter": "~1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"engine.io-parser": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.0.tgz",
|
||||
"integrity": "sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w==",
|
||||
"requires": {
|
||||
"after": "0.8.2",
|
||||
"arraybuffer.slice": "~0.0.7",
|
||||
"base64-arraybuffer": "0.1.5",
|
||||
"blob": "0.0.5",
|
||||
"has-binary2": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"entities": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
|
||||
@ -4632,19 +4524,6 @@
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"has-binary2": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz",
|
||||
"integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==",
|
||||
"requires": {
|
||||
"isarray": "2.0.1"
|
||||
}
|
||||
},
|
||||
"has-cors": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
|
||||
"integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk="
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
@ -4926,11 +4805,6 @@
|
||||
"integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=",
|
||||
"dev": true
|
||||
},
|
||||
"indexof": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
|
||||
"integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
@ -5326,7 +5200,8 @@
|
||||
"isarray": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
|
||||
"integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
|
||||
"integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
|
||||
"dev": true
|
||||
},
|
||||
"isexe": {
|
||||
"version": "2.0.0",
|
||||
@ -5790,7 +5665,8 @@
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"mute-stream": {
|
||||
"version": "0.0.8",
|
||||
@ -5853,11 +5729,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"negotiator": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
|
||||
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
|
||||
},
|
||||
"nice-try": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
|
||||
@ -5876,6 +5747,12 @@
|
||||
"integrity": "sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw==",
|
||||
"dev": true
|
||||
},
|
||||
"node-gyp-build": {
|
||||
"version": "3.7.0",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz",
|
||||
"integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==",
|
||||
"optional": true
|
||||
},
|
||||
"node-libs-browser": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz",
|
||||
@ -6041,11 +5918,6 @@
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz",
|
||||
"integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A="
|
||||
},
|
||||
"object-component": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
|
||||
"integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE="
|
||||
},
|
||||
"object-copy": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
|
||||
@ -6431,22 +6303,6 @@
|
||||
"integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==",
|
||||
"dev": true
|
||||
},
|
||||
"parseqs": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
|
||||
"integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=",
|
||||
"requires": {
|
||||
"better-assert": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"parseuri": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz",
|
||||
"integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=",
|
||||
"requires": {
|
||||
"better-assert": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"parseurl": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||
@ -7864,82 +7720,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"socket.io": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.3.0.tgz",
|
||||
"integrity": "sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==",
|
||||
"requires": {
|
||||
"debug": "~4.1.0",
|
||||
"engine.io": "~3.4.0",
|
||||
"has-binary2": "~1.0.2",
|
||||
"socket.io-adapter": "~1.1.0",
|
||||
"socket.io-client": "2.3.0",
|
||||
"socket.io-parser": "~3.4.0"
|
||||
}
|
||||
},
|
||||
"socket.io-adapter": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz",
|
||||
"integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g=="
|
||||
},
|
||||
"socket.io-client": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz",
|
||||
"integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==",
|
||||
"requires": {
|
||||
"backo2": "1.0.2",
|
||||
"base64-arraybuffer": "0.1.5",
|
||||
"component-bind": "1.0.0",
|
||||
"component-emitter": "1.2.1",
|
||||
"debug": "~4.1.0",
|
||||
"engine.io-client": "~3.4.0",
|
||||
"has-binary2": "~1.0.2",
|
||||
"has-cors": "1.1.0",
|
||||
"indexof": "0.0.1",
|
||||
"object-component": "0.0.3",
|
||||
"parseqs": "0.0.5",
|
||||
"parseuri": "0.0.5",
|
||||
"socket.io-parser": "~3.3.0",
|
||||
"to-array": "0.1.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"socket.io-parser": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz",
|
||||
"integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==",
|
||||
"requires": {
|
||||
"component-emitter": "1.2.1",
|
||||
"debug": "~3.1.0",
|
||||
"isarray": "2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"socket.io-parser": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.0.tgz",
|
||||
"integrity": "sha512-/G/VOI+3DBp0+DJKW4KesGnQkQPFmUCbA/oO2QGT6CWxU7hLGWqU3tyuzeSK/dqcyeHsQg1vTe9jiZI8GU9SCQ==",
|
||||
"requires": {
|
||||
"component-emitter": "1.2.1",
|
||||
"debug": "~4.1.0",
|
||||
"isarray": "2.0.1"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||
@ -8466,11 +8246,6 @@
|
||||
"os-tmpdir": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"to-array": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
|
||||
"integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA="
|
||||
},
|
||||
"to-arraybuffer": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
|
||||
@ -8782,6 +8557,15 @@
|
||||
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
|
||||
"dev": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.2.tgz",
|
||||
"integrity": "sha512-SwV++i2gTD5qh2XqaPzBnNX88N6HdyhQrNNRykvcS0QKvItV9u3vPEJr+X5Hhfb1JC0r0e1alL0iB09rY8+nmw==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"node-gyp-build": "~3.7.0"
|
||||
}
|
||||
},
|
||||
"util": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
|
||||
@ -9041,9 +8825,9 @@
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz",
|
||||
"integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ=="
|
||||
"version": "7.2.5",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.2.5.tgz",
|
||||
"integrity": "sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA=="
|
||||
},
|
||||
"xml-name-validator": {
|
||||
"version": "3.0.0",
|
||||
@ -9057,11 +8841,6 @@
|
||||
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
|
||||
"dev": true
|
||||
},
|
||||
"xmlhttprequest-ssl": {
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
|
||||
"integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4="
|
||||
},
|
||||
"xtend": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
@ -9190,11 +8969,6 @@
|
||||
"camelcase": "^5.0.0",
|
||||
"decamelize": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"yeast": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
|
||||
"integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
10
package.json
10
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "minetrack",
|
||||
"version": "5.2.1",
|
||||
"version": "5.3.0",
|
||||
"description": "A Minecraft server tracker that lets you focus on the basics.",
|
||||
"main": "main.js",
|
||||
"dependencies": {
|
||||
@ -9,9 +9,9 @@
|
||||
"mcpe-ping-fixed": "0.0.3",
|
||||
"request": "2.88.2",
|
||||
"serve-static": "^1.14.1",
|
||||
"socket.io": "2.3.0",
|
||||
"sqlite3": "4.1.1",
|
||||
"winston": "^2.0.0"
|
||||
"winston": "^2.0.0",
|
||||
"ws": "^7.2.5"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -44,5 +44,9 @@
|
||||
"scripts": {
|
||||
"build": "eslint assets/js/*.js && parcel build assets/html/index.html",
|
||||
"dev": "parcel build assets/html/index.html --no-minify"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user