diff --git a/core/components/HealthMonitor/index.js b/core/components/HealthMonitor/index.js index e8d333ab5..7b7679534 100644 --- a/core/components/HealthMonitor/index.js +++ b/core/components/HealthMonitor/index.js @@ -183,8 +183,6 @@ export default class HealthMonitor { const currTimestamp = now(); const elapsedRefreshStatus = currTimestamp - this.lastRefreshStatus; if (this.lastRefreshStatus !== null && elapsedRefreshStatus > 10) { - globals.databus.txStatsData.monitorStats.freezeSeconds.push(elapsedRefreshStatus - 1); - if (globals.databus.txStatsData.monitorStats.freezeSeconds.length > 30) globals.databus.txStatsData.monitorStats.freezeSeconds.shift(); console.error(`FXServer was frozen for ${elapsedRefreshStatus - 1} seconds for unknown reason (random issue, VPS Lag, DDoS, etc).`); console.error('Don\'t worry, txAdmin is preventing the server from being restarted.'); this.lastRefreshStatus = currTimestamp; @@ -232,7 +230,7 @@ export default class HealthMonitor { //Check if fxChild is closed, in this case no need to wait the failure count const processStatus = globals.fxRunner.getStatus(); if (processStatus == 'closed') { - globals.databus.txStatsData.monitorStats.restartReasons.close++; + globals.statisticsManager.registerFxserverRestart('close'); this.restartFXServer( 'server close detected', globals.translator.t('restarter.crash_detected'), @@ -324,13 +322,13 @@ export default class HealthMonitor { } } else if (elapsedHealthCheck > this.hardConfigs.healthCheck.failLimit) { //FIXME: se der hang tanto HB quanto HC, ele ainda sim cai nesse caso - globals.databus.txStatsData.monitorStats.restartReasons.healthCheck++; + globals.statisticsManager.registerFxserverRestart('healthCheck'); this.restartFXServer( 'server partial hang detected', globals.translator.t('restarter.hang_detected'), ); } else { - globals.databus.txStatsData.monitorStats.restartReasons.heartBeat++; + globals.statisticsManager.registerFxserverRestart('heartBeat'); this.restartFXServer( 'server hang detected', globals.translator.t('restarter.hang_detected'), @@ -349,7 +347,7 @@ export default class HealthMonitor { && tsNow - this.lastSuccessfulHTTPHeartBeat > 15 && tsNow - this.lastSuccessfulFD3HeartBeat < 5 ) { - globals.databus.txStatsData.monitorStats.heartBeatStats.httpFailed++; + globals.statisticsManager.registerFxserverRestart('http'); } this.lastSuccessfulFD3HeartBeat = tsNow; } else if (source === 'http') { @@ -358,7 +356,7 @@ export default class HealthMonitor { && tsNow - this.lastSuccessfulFD3HeartBeat > 15 && tsNow - this.lastSuccessfulHTTPHeartBeat < 5 ) { - globals.databus.txStatsData.monitorStats.heartBeatStats.fd3Failed++; + globals.statisticsManager.registerFxserverRestart('fd3'); } this.lastSuccessfulHTTPHeartBeat = tsNow; } diff --git a/core/components/ResourcesManager.js b/core/components/ResourcesManager.ts similarity index 64% rename from core/components/ResourcesManager.js rename to core/components/ResourcesManager.ts index 8d21d1bec..dbf5089fb 100644 --- a/core/components/ResourcesManager.js +++ b/core/components/ResourcesManager.ts @@ -3,58 +3,35 @@ import consoleFactory from '@extras/console'; const console = consoleFactory(modulename); -/* -NOTE Resource load scenarios knowledge base: -- resource lua error: - - `onResourceStarting` sourceRes - - print lua error - - `onResourceStart` sourceRes -- resource lua crash/hang: - - `onResourceStarting` sourceRes - - crash/hang -- dependency missing: - - `onResourceStarting` sourceRes - - does not get to `onResourceStart` -- dependency success: - - `onResourceStarting` sourceRes - - `onResourceStarting` dependency - - `onResourceStart` dependency - - `onResourceStart` sourceRes -- webpack/yarn fail: - - `onResourceStarting` sourceRes - - does not get to `onResourceStart` -- webpack/yarn success: - - `onResourceStarting` chat - - `onResourceStarting` yarn - - `onResourceStart` yarn - - `onResourceStarting` webpack - - `onResourceStart` webpack - - server first tick - - wait for build - - `onResourceStarting` chat - - `onResourceStart` chat -- ensure started resource: - - `onResourceStop` sourceRes - - `onResourceStarting` sourceRes - - `onResourceStart` sourceRes - - `onServerResourceStop` sourceRes - - `onServerResourceStart` sourceRes -*/ +type ResourceEventType = { + type: 'txAdminResourceEvent'; + resource: string; + event: 'onResourceStarting' + | 'onResourceStart' + | 'onServerResourceStart' + | 'onResourceListRefresh' + | 'onResourceStop' + | 'onServerResourceStop'; +}; + +type ResourceReportType = { + ts: Date, + resources: any[] +} export default class ResourcesManager { - constructor() { - this.activeStartingTime = null; - this.activeStartingResource = null; - this.lastResourceStartTime = null; - } + activeStartingTime: Date | null = null; + activeStartingResource: string | null = null; + lastResourceStartTime: Date | null = null; + resourceReport?: ResourceReportType; + + constructor() {} /** - * Handler for all txAdminResourceStatus structured trace events - * @param {object} payload - * @param {string} mutex + * Handler for all txAdminResourceEvent structured trace events */ - handleServerEvents(payload, mutex) { + handleServerEvents(payload: ResourceEventType, mutex: string) { // console.log(`${payload.event}: ${payload.resource}`); if (payload.event === 'onResourceStarting') { this.activeStartingResource = payload.resource; @@ -77,11 +54,12 @@ export default class ResourcesManager { /** - * Handler for server restart + * Handler for server restart. + * NOTE: replace this when we start tracking resource states internally */ tmpGetPendingStart() { - const getSecondsDiff = (date) => { - return date !== null ? Math.round((new Date() - date) / 1000) : null; + const getSecondsDiff = (date: Date | null) => { + return date !== null ? Math.round((Date.now() - date.getTime()) / 1000) : null; } return { startingResName: this.activeStartingResource, @@ -89,4 +67,54 @@ export default class ResourcesManager { lastStartElapsedSecs: getSecondsDiff(this.lastResourceStartTime), }; } + + + /** + * Handle resource report. + * NOTE: replace this when we start tracking resource states internally + */ + tmpUpdateResourceList(resources: any[]) { + this.resourceReport = { + ts: new Date(), + resources, + } + } }; + +/* +NOTE Resource load scenarios knowledge base: +- resource lua error: + - `onResourceStarting` sourceRes + - print lua error + - `onResourceStart` sourceRes +- resource lua crash/hang: + - `onResourceStarting` sourceRes + - crash/hang +- dependency missing: + - `onResourceStarting` sourceRes + - does not get to `onResourceStart` +- dependency success: + - `onResourceStarting` sourceRes + - `onResourceStarting` dependency + - `onResourceStart` dependency + - `onResourceStart` sourceRes +- webpack/yarn fail: + - `onResourceStarting` sourceRes + - does not get to `onResourceStart` +- webpack/yarn success: + - `onResourceStarting` chat + - `onResourceStarting` yarn + - `onResourceStart` yarn + - `onResourceStarting` webpack + - `onResourceStart` webpack + - server first tick + - wait for build + - `onResourceStarting` chat + - `onResourceStart` chat +- ensure started resource: + - `onResourceStop` sourceRes + - `onResourceStarting` sourceRes + - `onResourceStart` sourceRes + - `onServerResourceStop` sourceRes + - `onServerResourceStart` sourceRes +*/ diff --git a/core/components/StatisticsManager/index.ts b/core/components/StatisticsManager/index.ts index 22f4248e3..210bfa90b 100644 --- a/core/components/StatisticsManager/index.ts +++ b/core/components/StatisticsManager/index.ts @@ -24,6 +24,7 @@ const jweHeader = { /** * Responsible for collecting runtime data for statistics + * NOTE: the register functions don't throw because we rather break stats than txAdmin itself */ export default class StatisticsManager { readonly #txAdmin: TxAdmin; @@ -39,18 +40,31 @@ export default class StatisticsManager { public readonly whitelistCheckTime = new QuantileArray(5000, 50); public currHbData: string = '{"error": "not yet initialized in StatisticsManager"}'; + public monitorStats = { + healthIssues: { + fd3: 0, + http: 0, + }, + restartReasons: { + close: 0, + heartBeat: 0, + healthCheck: 0, + }, + }; + + constructor(txAdmin: TxAdmin) { this.#txAdmin = txAdmin; this.loadStatsPublicKey(); //Delaying this because host static data takes 10+ seconds to be set setTimeout(() => { - this.refreshHbData().catch((e) => {}); + this.refreshHbData().catch((e) => { }); }, 15_000); //Cron function setInterval(() => { - this.refreshHbData().catch((e) => {}); + this.refreshHbData().catch((e) => { }); }, 60_000); } @@ -70,7 +84,6 @@ export default class StatisticsManager { /** * Called by HealthMonitor to keep track of the last boot time - * NOTE: we are not throwing an error because this is not a fundamental part of txAdmin */ registerFxserverBoot(seconds: number) { if (!Number.isInteger(seconds) || seconds < 0) { @@ -81,6 +94,24 @@ export default class StatisticsManager { } + /** + * Called by HealthMonitor to keep track of the fxserver restart reasons + */ + registerFxserverRestart(reason: keyof typeof this.monitorStats.restartReasons) { + if (!(reason in this.monitorStats.restartReasons)) return; + this.monitorStats.restartReasons[reason]++; + } + + + /** + * Called by HealthMonitor to keep track of the fxserver HB/HC failures + */ + registerFxserverHealthIssue(type: keyof typeof this.monitorStats.healthIssues) { + if (!(type in this.monitorStats.healthIssues)) return; + this.monitorStats.healthIssues[type]++; + } + + /** * Processes general txadmin stuff to generate the HB data. * @@ -109,7 +140,7 @@ export default class StatisticsManager { const tmpDurationDebugLog = (msg: string) => { // @ts-expect-error - if(globals?.tmpSetHbDataTracking){ + if (globals?.tmpSetHbDataTracking) { console.verbose.debug(`refreshHbData: ${msg}`); } } diff --git a/core/components/UpdateChecker.ts b/core/components/UpdateChecker.ts new file mode 100644 index 000000000..5ea66cfa1 --- /dev/null +++ b/core/components/UpdateChecker.ts @@ -0,0 +1,170 @@ +const modulename = 'UpdateChecker'; +import semver from 'semver'; +import { z } from "zod"; +import got from '@core/extras/got.js'; +import { txEnv } from '@core/globalData'; +import consoleFactory from '@extras/console'; +import { convars } from '@core/globalData'; +const console = consoleFactory(modulename); + + +type txUpdateDataType = { + semverDiff: semver.ReleaseType | null; + latest: string; + color: 'info' | 'secondary' | 'success' | 'warning' | 'danger'; +}; + +type fxsUpdateDataType = { + color: 'info' | 'secondary' | 'success' | 'warning' | 'danger'; + message: string; + subtext: string; + downloadLink: string; +}; + +const txVersion = z.string().refine( + (x) => x !== '0.0.0', + { message: 'must not be 0.0.0' } +); +const changelogRespSchema = z.object({ + recommended: z.coerce.number().positive(), + recommended_download: z.string().url(), + recommended_txadmin: txVersion, + optional: z.coerce.number().positive(), + optional_download: z.string().url(), + optional_txadmin: txVersion, + latest: z.coerce.number().positive(), + latest_download: z.string().url(), + latest_txadmin: txVersion, + critical: z.coerce.number().positive(), + critical_download: z.string().url(), + critical_txadmin: txVersion, +}); + + + +export default class UpdateChecker { + txUpdateData?: txUpdateDataType; + fxsUpdateData?: fxsUpdateDataType; + + constructor() { + //Check for updates ASAP + this.checkChangelog(); + + //Check again every 15 mins + setInterval(() => { + this.checkChangelog(); + }, 15 * 60_000); + } + + + /** + * Check for txAdmin and FXServer updates + */ + async checkChangelog() { + //GET changelog data + let apiResponse: z.infer; + try { + //perform request - cache busting every ~1.4h + const osTypeApiUrl = (txEnv.isWindows) ? 'win32' : 'linux'; + const cacheBuster = Math.floor(Date.now() / 5_000_000); + const reqUrl = `https://changelogs-live.fivem.net/api/changelog/versions/${osTypeApiUrl}/server?${cacheBuster}`; + const resp = await got(reqUrl).json() + apiResponse = changelogRespSchema.parse(resp); + } catch (error) { + console.verbose.warn(`Failed to retrieve FXServer/txAdmin update data with error: ${error.message}`); + return; + } + + //Checking txAdmin version + try { + const isOutdated = semver.lt(txEnv.txAdminVersion, apiResponse.latest_txadmin); + if (isOutdated) { + const semverDiff = semver.diff(txEnv.txAdminVersion, apiResponse.latest_txadmin); + if (semverDiff === 'patch') { + console.warn('This version of txAdmin is outdated.'); + console.warn('A patch (bug fix) update is available for txAdmin.'); + console.warn('If you are experiencing any kind of issue, please update now.'); + console.warn('For more information: https://discord.gg/uAmsGa2'); + this.txUpdateData = { + semverDiff, + latest: apiResponse.latest_txadmin, + color: 'secondary', + }; + } else { + console.error('This version of txAdmin is outdated.'); + console.error('Please update as soon as possible.'); + console.error('For more information: https://discord.gg/uAmsGa2'); + this.txUpdateData = { + semverDiff, + latest: apiResponse.latest_txadmin, + color: 'danger', + }; + } + } + } catch (error) { + console.verbose.warn('Error checking for txAdmin updates. Enable verbosity for more information.'); + console.verbose.dir(error); + } + + //Checking FXServer version + //TODO: logic copied from dashboard webroute, adapt to new thing + try { + if (txEnv.fxServerVersion < apiResponse.critical) { + const shouldUpdate = { + color: 'danger', + message: 'A critical update is available for FXServer, you should update now.', + } as const; + if (apiResponse.critical > apiResponse.recommended) { + this.fxsUpdateData = { + ...shouldUpdate, + subtext: `critical update ${txEnv.fxServerVersion} ➤ ${apiResponse.critical}`, + downloadLink: apiResponse.critical_download, + } + } else { + this.fxsUpdateData = { + ...shouldUpdate, + subtext: `recommended update ${txEnv.fxServerVersion} ➤ ${apiResponse.recommended}`, + downloadLink: apiResponse.recommended_download, + } + } + } else if (txEnv.fxServerVersion < apiResponse.recommended) { + this.fxsUpdateData = { + color: 'warning', + message: 'A recommended update is available for FXServer, you should update.', + subtext: `recommended update ${txEnv.fxServerVersion} ➤ ${apiResponse.recommended}`, + downloadLink: apiResponse.recommended_download, + }; + } else if (txEnv.fxServerVersion < apiResponse.optional) { + this.fxsUpdateData = { + color: 'info', + message: 'An optional update is available for FXServer.', + subtext: `optional update ${txEnv.fxServerVersion} ➤ ${apiResponse.optional}`, + downloadLink: apiResponse.optional_download, + }; + } + } catch (error) { + console.warn('Error checking for FXServer updates. Enable verbosity for more information.'); + console.verbose.dir(error); + } + } +}; + +/* + TODO: + Create an page with the changelog, that queries for the following endpoint and caches it for 15 minutes: + https://changelogs-live.fivem.net/api/changelog/versions/2385/2375?tag=server + Maybe even grab the data from commits: + https://changelogs-live.fivem.net/api/changelog/versions/5562 + Other relevant apis: + https://changelogs-live.fivem.net/api/changelog/versions/win32/server? (the one being used below) + https://changelogs-live.fivem.net/api/changelog/versions + https://api.github.com/repos/tabarra/txAdmin/releases (changelog in [].body) + + NOTE: old logic + if == recommended, you're fine + if > recommended && < optional, pls update to optional + if == optional, you're fine + if > optional && < latest, pls update to latest + if == latest, duh + if < critical, BIG WARNING +*/ diff --git a/core/components/WebServer/ctxUtils.js b/core/components/WebServer/ctxUtils.js index ba44c00a3..4f44d97df 100644 --- a/core/components/WebServer/ctxUtils.js +++ b/core/components/WebServer/ctxUtils.js @@ -267,8 +267,8 @@ export default async function WebCtxUtils(ctx, next) { uiTheme: (ctx.cookies.get('txAdmin-darkMode') === 'true' || !isWebInterface) ? THEME_DARK : '', fxServerVersion: displayFxserverVersion, txAdminVersion: txEnv.txAdminVersion, - txaOutdated: globals.databus.updateChecker?.txadmin, - fxsOutdated: globals.databus.updateChecker?.fxserver, + txaOutdated: globals.updateChecker?.txUpdateData, + fxsOutdated: globals.updateChecker?.fxsUpdateData, jsInjection: getJavascriptConsts({ isZapHosting: convars.isZapHosting, //not in use isPterodactyl: convars.isPterodactyl, //not in use diff --git a/core/components/WebServer/index.js b/core/components/WebServer/index.js index c8d5f04a9..40b300b76 100644 --- a/core/components/WebServer/index.js +++ b/core/components/WebServer/index.js @@ -34,6 +34,7 @@ export default class WebServer { this.luaComToken = nanoid(); this.webSocket = null; this.isListening = false; + this.httpRequestsCounter = 0; //Generate cookie key const pathHash = crypto.createHash('shake256', { outputLength: 6 }) @@ -46,14 +47,18 @@ export default class WebServer { this.setupWebSocket(); this.setupServerCallbacks(); - //Cron function + //Counting requests per minute setInterval(() => { - const httpCounter = globals.databus.txStatsData.httpCounter; - httpCounter.log.push(httpCounter.current); - if (httpCounter.log.length > 10) httpCounter.log.shift(); - if (httpCounter.current > httpCounter.max) httpCounter.max = httpCounter.current; - httpCounter.current = 0; - }, 60 * 1000); + if(this.httpRequestsCounter > 10_000){ + const numberFormatter = new Intl.NumberFormat('en-US'); + console.majorMultilineError([ + `txAdmin might be under a DDoS attack!`, + `We detected ${numberFormatter.format(this.httpRequestsCounter)} HTTP requests in the last minute.`, + 'Make sure you have a proper firewall setup and/or a reverse proxy with rate limiting.', + ]); + } + this.httpRequestsCounter = 0; + }, 60_000); } @@ -210,7 +215,7 @@ export default class WebServer { //Calls the appropriate callback try { - globals.databus.txStatsData.httpCounter.current++; + this.httpRequestsCounter++; if (req.url.startsWith('/socket.io')) { this.io.engine.handleRequest(req, res); } else { diff --git a/core/extras/updateChecker.js b/core/extras/updateChecker.js deleted file mode 100644 index aac93445a..000000000 --- a/core/extras/updateChecker.js +++ /dev/null @@ -1,140 +0,0 @@ -const modulename = 'updateChecker'; -import semver from 'semver'; -import got from '@core/extras/got.js'; -import { txEnv } from '@core/globalData'; -import consoleFactory from '@extras/console'; -const console = consoleFactory(modulename); - - -//Helpers -const now = () => { return Math.round(Date.now() / 1000); }; - -/* - TODO: - Create an page with the changelog, that queries for the following endpoint and caches it for 15 minutes: - https://changelogs-live.fivem.net/api/changelog/versions/2385/2375?tag=server - Maybe even grab the data from commits: - https://changelogs-live.fivem.net/api/changelog/versions/5562 - Other relevant apis: - https://changelogs-live.fivem.net/api/changelog/versions/win32/server? (the one being used below) - https://changelogs-live.fivem.net/api/changelog/versions - https://api.github.com/repos/tabarra/txAdmin/releases (changelog in [].body) - - NOTE: old logic - if == recommended, you're fine - if > recommended && < optional, pls update to optional - if == optional, you're fine - if > optional && < latest, pls update to latest - if == latest, duh - if < critical, BIG WARNING -*/ - -export default async () => { - let apiResponse; - try { - //perform request - cache busting every ~1.4h - const osTypeApiUrl = (txEnv.isWindows) ? 'win32' : 'linux'; - const cacheBuster = Math.floor(now() / 5e3); - const reqUrl = `https://changelogs-live.fivem.net/api/changelog/versions/${osTypeApiUrl}/server?${cacheBuster}`; - apiResponse = await got.get(reqUrl).json(); - - //validate response - if (!apiResponse) throw new Error('request failed'); - const requiredFields = [ - 'recommended', - 'recommended_download', - 'recommended_txadmin', - 'optional', - 'optional_download', - 'optional_txadmin', - 'latest', - 'latest_download', - 'latest_txadmin', - 'critical', - 'critical_download', - 'critical_txadmin', - ]; - const missing = requiredFields.find((x) => !apiResponse.hasOwnProperty(x)); - if (missing) { - throw new Error(`expected prop ${missing} not found in api response.`); - } - } catch (error) { - console.verbose.warn(`Failed to retrieve FXServer/txAdmin update data with error: ${error.message}`); - if (globals.databus.updateChecker === null) globals.databus.updateChecker = false; - return; - } - - //Checking txAdmin version - let txOutput = false; - try { - const isOutdated = semver.lt(txEnv.txAdminVersion, apiResponse.latest_txadmin); - if (isOutdated) { - const semverDiff = semver.diff(txEnv.txAdminVersion, apiResponse.latest_txadmin); - if (semverDiff === 'patch') { - console.warn('This version of txAdmin is outdated.'); - console.warn('A patch (bug fix) update is available for txAdmin.'); - console.warn('If you are experiencing any kind of issue, please update now.'); - console.warn('For more information: https://discord.gg/uAmsGa2'); - txOutput = { - semverDiff, - latest: apiResponse.latest_txadmin, - color: 'secondary', - }; - } else { - console.error('This version of txAdmin is outdated.'); - console.error('Please update as soon as possible.'); - console.error('For more information: https://discord.gg/uAmsGa2'); - txOutput = { - semverDiff, - latest: apiResponse.latest_txadmin, - color: 'danger', - }; - } - } - } catch (error) { - console.verbose.warn('Error checking for txAdmin updates. Enable verbosity for more information.'); - console.verbose.dir(error); - } - - //Checking FXServer version - //FIXME: logic copied from dashboard webroute, adapt to new thing - let fxsOutput = false; - try { - if (txEnv.fxServerVersion < apiResponse.critical) { - fxsOutput = { - color: 'danger', - message: 'A critical update is available for FXServer, you should update now.', - }; - if (apiResponse.critical > apiResponse.recommended) { - fxsOutput.subtext = `critical update ${txEnv.fxServerVersion} ➤ ${apiResponse.critical}`; - fxsOutput.artifactsLink = apiResponse.critical_download; - } else { - fxsOutput.subtext = `recommended update ${txEnv.fxServerVersion} ➤ ${apiResponse.recommended}`; - fxsOutput.artifactsLink = apiResponse.recommended_download; - } - } else if (txEnv.fxServerVersion < apiResponse.recommended) { - fxsOutput = { - color: 'warning', - message: 'A recommended update is available for FXServer, you should update.', - subtext: `recommended update ${txEnv.fxServerVersion} ➤ ${apiResponse.recommended}`, - artifactsLink: apiResponse.recommended_download, - }; - } else if (txEnv.fxServerVersion < apiResponse.optional) { - fxsOutput = { - color: 'info', - message: 'An optional update is available for FXServer.', - subtext: `optional update ${txEnv.fxServerVersion} ➤ ${apiResponse.optional}`, - artifactsLink: apiResponse.optional_download, - }; - } - } catch (error) { - console.warn('Error checking for FXServer updates. Enable verbosity for more information.'); - console.verbose.dir(error); - } - - //Output - globals.databus.updateChecker = { - txadmin: txOutput, - fxserver: fxsOutput, - }; -}; diff --git a/core/txAdmin.ts b/core/txAdmin.ts index f3bbd03fd..df5c10e4c 100644 --- a/core/txAdmin.ts +++ b/core/txAdmin.ts @@ -24,6 +24,7 @@ import ResourcesManager from '@core/components/ResourcesManager'; import PlayerlistManager from '@core/components/PlayerlistManager'; import PlayerDatabase from '@core/components/PlayerDatabase'; import PersistentCache from '@core/components/PersistentCache'; +import UpdateChecker from '@core/components/UpdateChecker'; import consoleFactory from '@extras/console'; const console = consoleFactory(`v${txEnv.txAdminVersion}`); @@ -54,63 +55,12 @@ const globalsInternal: Record = { playerDatabase: null, config: null, deployer: null, + updateChecker: null, info: {}, //FIXME: settings:save webroute cannot call txAdmin.refreshConfig for now //so this hack allows it to call it func_txAdminRefreshConfig: ()=>{}, - - //NOTE: still not ideal, but since the extensions system changed entirely, - // will have to rethink the plans for this variable. - databus: { - //internal - resourcesList: null, - updateChecker: null, - joinCheckHistory: [], - - //stats - txStatsData: { - playerDBStats: null, - lastFD3Error: '', - monitorStats: { - heartBeatStats: { - httpFailed: 0, - fd3Failed: 0, - }, - restartReasons: { - close: 0, - heartBeat: 0, - healthCheck: 0, - }, - bootSeconds: [], - freezeSeconds: [], - }, - randIDFailures: 0, - pageViews: {}, - httpCounter: { - current: 0, - max: 0, - log: [], - }, - login: { - origins: { - localhost: 0, - cfxre: 0, - ip: 0, - other: 0, - webpipe: 0, - }, - methods: { - discord: 0, - citizenfx: 0, - password: 0, - zap: 0, - nui: 0, - iframe: 0, - }, - }, - }, - }, }; //@ts-ignore: yes i know this is wrong @@ -137,6 +87,7 @@ export default class TxAdmin { playerlistManager; playerDatabase; persistentCache; + updateChecker; //Runtime readonly info: { @@ -248,6 +199,9 @@ export default class TxAdmin { this.persistentCache = new PersistentCache(this); globalsInternal.persistentCache = this.persistentCache; + + this.updateChecker = new UpdateChecker(); + globalsInternal.updateChecker = this.updateChecker; } catch (error) { console.error(`Error starting main components:`); console.dir(error); @@ -261,10 +215,6 @@ export default class TxAdmin { console.dir(error); } - //Run Update Checker every 15 minutes - updateChecker(); - setInterval(updateChecker, 15 * 60 * 1000); - //TODO: cron to update setTTYTitle } diff --git a/core/webroutes/advanced/actions.js b/core/webroutes/advanced/actions.js index ee41ec6fa..f9affdaed 100644 --- a/core/webroutes/advanced/actions.js +++ b/core/webroutes/advanced/actions.js @@ -61,22 +61,6 @@ export default async function AdvancedActions(ctx) { memory = 'error'; } return ctx.send({ type: 'success', message: memory }); - } else if (action == 'joinCheckHistory') { - let outData; - try { - const currTime = Date.now(); - const log = globals.databus.joinCheckHistory.map((e) => { - return { - when: humanizeDuration(currTime - e.ts, { round: true }), - playerName: e.playerName, - idArray: e.idArray, - }; - }); - outData = JSON.stringify(log, null, 2); - } catch (error) { - outData = error.message; - } - return ctx.send({ type: 'success', message: outData }); } else if (action == 'freeze') { console.warn('Freezing process for 50 seconds.'); Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 50 * 1000); diff --git a/core/webroutes/diagnostics/diagnosticsFuncs.ts b/core/webroutes/diagnostics/diagnosticsFuncs.ts index cad11f991..a13316fe6 100644 --- a/core/webroutes/diagnostics/diagnosticsFuncs.ts +++ b/core/webroutes/diagnostics/diagnosticsFuncs.ts @@ -286,7 +286,6 @@ export const getTxAdminData = async () => { const webServer = (globals.webServer as WebServer); const logger = (globals.logger as Logger); const statisticsManager = (globals.statisticsManager as StatisticsManager); - const databus = (globals.databus as any); const humanizeOptions: HumanizerOptions = { round: true, @@ -308,21 +307,16 @@ export const getTxAdminData = async () => { const banCheckTime = joinTimesToString(statisticsManager.banCheckTime.result()); const whitelistCheckTime = joinTimesToString(statisticsManager.whitelistCheckTime.result()); - const httpCounter = databus.txStatsData.httpCounter; return { //Stats uptime: humanizeDuration(process.uptime() * 1000, humanizeOptions), - httpCounterLog: httpCounter.log.join(', ') || '--', - httpCounterMax: httpCounter.max || '--', monitorRestarts: { - close: databus.txStatsData.monitorStats.restartReasons.close, - heartBeat: databus.txStatsData.monitorStats.restartReasons.heartBeat, - healthCheck: databus.txStatsData.monitorStats.restartReasons.healthCheck, + close: statisticsManager.monitorStats.restartReasons.close, + heartBeat: statisticsManager.monitorStats.restartReasons.heartBeat, + healthCheck: statisticsManager.monitorStats.restartReasons.healthCheck, }, - hbFD3Fails: databus.txStatsData.monitorStats.heartBeatStats.fd3Failed, - hbHTTPFails: databus.txStatsData.monitorStats.heartBeatStats.httpFailed, - hbBootSeconds: databus.txStatsData.monitorStats.bootSeconds.join(', ') || '--', - freezeSeconds: databus.txStatsData.monitorStats.freezeSeconds.join(', ') || '--', + hbFD3Fails: statisticsManager.monitorStats.healthIssues.fd3, + hbHTTPFails: statisticsManager.monitorStats.healthIssues.http, koaSessions: Object.keys(webServer.koaSessionMemoryStore.sessions).length || '--', banCheckTime, whitelistCheckTime, diff --git a/core/webroutes/intercom.js b/core/webroutes/intercom.js index d6c11f15c..573546287 100644 --- a/core/webroutes/intercom.js +++ b/core/webroutes/intercom.js @@ -37,10 +37,7 @@ export default async function Intercom(ctx) { if (!Array.isArray(postData.resources)) { return ctx.utils.error(400, 'Invalid Request'); } - globals.databus.resourcesList = { - timestamp: new Date(), - data: postData.resources, - }; + globals.resourcesManager.tmpUpdateResourceList(postData.resources); } else { return ctx.send({ type: 'danger', diff --git a/core/webroutes/player/checkJoin.ts b/core/webroutes/player/checkJoin.ts index f1a688e8e..c88a055fa 100644 --- a/core/webroutes/player/checkJoin.ts +++ b/core/webroutes/player/checkJoin.ts @@ -91,16 +91,6 @@ export default async function PlayerCheckJoin(ctx: Context) { } const { playerName, playerIds, playerHwids } = ctx.request.body; - //DEBUG: save join log - const toLog = { - ts: Date.now(), - playerName, - playerIds, - playerHwids, - }; - globals.databus.joinCheckHistory.push(toLog); - if (globals.databus.joinCheckHistory.length > 25) globals.databus.joinCheckHistory.shift(); - //Validating body data if (typeof playerName !== 'string') return sendTypedResp({ error: 'playerName should be an string.' }); if (!Array.isArray(playerIds)) return sendTypedResp({ error: 'playerIds should be an array.' }); diff --git a/core/webroutes/resources.js b/core/webroutes/resources.js index cd475ddab..ffb312ff0 100644 --- a/core/webroutes/resources.js +++ b/core/webroutes/resources.js @@ -70,13 +70,13 @@ export default async function Resources(ctx) { const tList = new Promise((resolve, reject) => { tListTimer = setInterval(() => { if ( - globals.databus.resourcesList !== null - && (new Date() - globals.databus.resourcesList.timestamp) <= 1000 - && Array.isArray(globals.databus.resourcesList.data) + globals.resourcesManager.resourceReport !== null + && (new Date() - globals.resourcesManager.resourceReport.ts) <= 1000 + && Array.isArray(globals.resourcesManager.resourceReport.resources) ) { clearTimeout(tListTimer); clearTimeout(tErrorTimer); - const resGroups = processResources(globals.databus.resourcesList.data); + const resGroups = processResources(globals.resourcesManager.resourceReport.resources); const renderData = { headerTitle: 'Resources', resGroupsJS: JSON.stringify(resGroups), diff --git a/docs/dev_notes.md b/docs/dev_notes.md index 818415d75..548802163 100644 --- a/docs/dev_notes.md +++ b/docs/dev_notes.md @@ -7,7 +7,7 @@ - [x] add txAdmin:events:adminAuth - [x] merge PRs - [x] add warning to whitelist page when server is not on license whitelist mode -- [ ] clean a few of the dead stuff from databus +- [x] deprecate globals.databus > next up - [ ] Add a tracking for % of redm/fivem/libertym servers to txTracker @@ -23,6 +23,20 @@ ScanResourceRoot('E:/FiveM/txData/default.base/', (data: object) => { }) +### Zod error parsing +if (error instanceof z.ZodError) { + const outString = error.issues.map(issue => { + return issue.path.length + ? `${issue.path.join('.')}: ${issue.message}` + : issue.message; + }).join('\n'); + console.error(outString); + console.error(error.issues); +} else { + console.dir(error); +} + + txAdmin:events:menuAction - player: number diff --git a/package-lock.json b/package-lock.json index bdbb9c945..58cbbecda 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "@mui/material": "5.13.6", "boxen": "^7.1.0", "bytes": "^3.1.2", - "chalk": "^5.2.0", + "chalk": "^5.3.0", "d3-array": "^3.2.4", "dateformat": "^5.0.3", "discord.js": "^14.11.0", @@ -44,7 +44,7 @@ "lodash-es": "^4.17.21", "lowdb": "^6.0.1", "mnemonist": "^0.39.5", - "mysql2": "^3.4.2", + "mysql2": "^3.4.3", "nanoid": "^4.0.2", "nanoid-dictionary": "^4.3.0", "node-polyglot": "^2.5.0", @@ -60,14 +60,15 @@ "semver": "^7.5.3", "slash": "^5.1.0", "slug": "^8.2.2", - "socket.io": "^4.7.0", + "socket.io": "^4.7.1", "source-map-support": "^0.5.21", "stream-json": "^1.8.0", "string-argv": "^0.3.2", - "systeminformation": "^5.18.5", + "systeminformation": "^5.18.6", "unicode-emoji-json": "^0.4.0", "windows-release": "^4.0.0", - "xss": "^1.0.14" + "xss": "^1.0.14", + "zod": "^3.21.4" }, "devDependencies": { "@commitlint/cli": "^17.6.6", @@ -82,23 +83,33 @@ "@types/node-polyglot": "^2.4.2", "@types/react": "^18.2.14", "@types/react-dom": "^18.2.6", + "@types/semver": "^7.5.0", "@types/slug": "^5.0.3", "@types/source-map-support": "^0.5.6", "@vitejs/plugin-react": "^4.0.1", "chokidar": "^3.5.3", - "esbuild": "~0.18.10", - "eslint": "^8.43.0", + "esbuild": "~0.18.11", + "eslint": "^8.44.0", "husky": "^8.0.3", "lodash": "^4.17.21", "react": "^18.2.0", "react-dom": "^18.2.0", "rimraf": "^5.0.1", "tsc-watch": "^6.0.4", - "typescript": "^5.1.3", + "typescript": "^5.1.6", "vite": "^4.3.9", "vite-tsconfig-paths": "^4.2.0" } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -1108,9 +1119,9 @@ "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, "node_modules/@esbuild/android-arm": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.10.tgz", - "integrity": "sha512-3KClmVNd+Fku82uZJz5C4Rx8m1PPmWUFz5Zkw8jkpZPOmsq+EG1TTOtw1OXkHuX3WczOFQigrtf60B1ijKwNsg==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.11.tgz", + "integrity": "sha512-q4qlUf5ucwbUJZXF5tEQ8LF7y0Nk4P58hOsGk3ucY0oCwgQqAnqXVbUuahCddVHfrxmpyewRpiTHwVHIETYu7Q==", "cpu": [ "arm" ], @@ -1124,9 +1135,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.10.tgz", - "integrity": "sha512-ynm4naLbNbK0ajf9LUWtQB+6Vfg1Z/AplArqr4tGebC00Z6m9Y91OVIcjDa461wGcZwcaHYaZAab4yJxfhisTQ==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.11.tgz", + "integrity": "sha512-snieiq75Z1z5LJX9cduSAjUr7vEI1OdlzFPMw0HH5YI7qQHDd3qs+WZoMrWYDsfRJSq36lIA6mfZBkvL46KoIw==", "cpu": [ "arm64" ], @@ -1140,9 +1151,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.10.tgz", - "integrity": "sha512-vFfXj8P9Yfjh54yqUDEHKzqzYuEfPyAOl3z7R9hjkwt+NCvbn9VMxX+IILnAfdImRBfYVItgSUsqGKhJFnBwZw==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.11.tgz", + "integrity": "sha512-iPuoxQEV34+hTF6FT7om+Qwziv1U519lEOvekXO9zaMMlT9+XneAhKL32DW3H7okrCOBQ44BMihE8dclbZtTuw==", "cpu": [ "x64" ], @@ -1156,9 +1167,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.10.tgz", - "integrity": "sha512-k2OJQ7ZxE6sVc91+MQeZH9gFeDAH2uIYALPAwTjTCvcPy9Dzrf7V7gFUQPYkn09zloWhQ+nvxWHia2x2ZLR0sQ==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.11.tgz", + "integrity": "sha512-Gm0QkI3k402OpfMKyQEEMG0RuW2LQsSmI6OeO4El2ojJMoF5NLYb3qMIjvbG/lbMeLOGiW6ooU8xqc+S0fgz2w==", "cpu": [ "arm64" ], @@ -1172,9 +1183,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.10.tgz", - "integrity": "sha512-tnz/mdZk1L1Z3WpGjin/L2bKTe8/AKZpI8fcCLtH+gq8WXWsCNJSxlesAObV4qbtTl6pG5vmqFXfWUQ5hV8PAQ==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.11.tgz", + "integrity": "sha512-N15Vzy0YNHu6cfyDOjiyfJlRJCB/ngKOAvoBf1qybG3eOq0SL2Lutzz9N7DYUbb7Q23XtHPn6lMDF6uWbGv9Fw==", "cpu": [ "x64" ], @@ -1188,9 +1199,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.10.tgz", - "integrity": "sha512-QJluV0LwBrbHnYYwSKC+K8RGz0g/EyhpQH1IxdoFT0nM7PfgjE+aS8wxq/KFEsU0JkL7U/EEKd3O8xVBxXb2aA==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.11.tgz", + "integrity": "sha512-atEyuq6a3omEY5qAh5jIORWk8MzFnCpSTUruBgeyN9jZq1K/QI9uke0ATi3MHu4L8c59CnIi4+1jDKMuqmR71A==", "cpu": [ "arm64" ], @@ -1204,9 +1215,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.10.tgz", - "integrity": "sha512-Hi/ycUkS6KTw+U9G5PK5NoK7CZboicaKUSVs0FSiPNtuCTzK6HNM4DIgniH7hFaeuszDS9T4dhAHWiLSt/Y5Ng==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.11.tgz", + "integrity": "sha512-XtuPrEfBj/YYYnAAB7KcorzzpGTvOr/dTtXPGesRfmflqhA4LMF0Gh/n5+a9JBzPuJ+CGk17CA++Hmr1F/gI0Q==", "cpu": [ "x64" ], @@ -1220,9 +1231,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.10.tgz", - "integrity": "sha512-HfFoxY172tVHPIvJy+FHxzB4l8xU7e5cxmNS11cQ2jt4JWAukn/7LXaPdZid41UyTweqa4P/1zs201gRGCTwHw==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.11.tgz", + "integrity": "sha512-Idipz+Taso/toi2ETugShXjQ3S59b6m62KmLHkJlSq/cBejixmIydqrtM2XTvNCywFl3VC7SreSf6NV0i6sRyg==", "cpu": [ "arm" ], @@ -1236,9 +1247,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.10.tgz", - "integrity": "sha512-Nz6XcfRBOO7jSrVpKAyEyFOPGhySPNlgumSDhWAspdQQ11ub/7/NZDMhWDFReE9QH/SsCOCLQbdj0atAk/HMOQ==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.11.tgz", + "integrity": "sha512-c6Vh2WS9VFKxKZ2TvJdA7gdy0n6eSy+yunBvv4aqNCEhSWVor1TU43wNRp2YLO9Vng2G+W94aRz+ILDSwAiYog==", "cpu": [ "arm64" ], @@ -1252,9 +1263,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.10.tgz", - "integrity": "sha512-otMdmSmkMe+pmiP/bZBjfphyAsTsngyT9RCYwoFzqrveAbux9nYitDTpdgToG0Z0U55+PnH654gCH2GQ1aB6Yw==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.11.tgz", + "integrity": "sha512-S3hkIF6KUqRh9n1Q0dSyYcWmcVa9Cg+mSoZEfFuzoYXXsk6196qndrM+ZiHNwpZKi3XOXpShZZ+9dfN5ykqjjw==", "cpu": [ "ia32" ], @@ -1268,9 +1279,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.10.tgz", - "integrity": "sha512-t8tjFuON1koxskzQ4VFoh0T5UDUMiLYjwf9Wktd0tx8AoK6xgU+5ubKOpWpcnhEQ2tESS5u0v6QuN8PX/ftwcQ==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.11.tgz", + "integrity": "sha512-MRESANOoObQINBA+RMZW+Z0TJWpibtE7cPFnahzyQHDCA9X9LOmGh68MVimZlM9J8n5Ia8lU773te6O3ILW8kw==", "cpu": [ "loong64" ], @@ -1284,9 +1295,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.10.tgz", - "integrity": "sha512-+dUkcVzcfEJHz3HEnVpIJu8z8Wdn2n/nWMWdl6FVPFGJAVySO4g3+XPzNKFytVFwf8hPVDwYXzVcu8GMFqsqZw==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.11.tgz", + "integrity": "sha512-qVyPIZrXNMOLYegtD1u8EBccCrBVshxMrn5MkuFc3mEVsw7CCQHaqZ4jm9hbn4gWY95XFnb7i4SsT3eflxZsUg==", "cpu": [ "mips64el" ], @@ -1300,9 +1311,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.10.tgz", - "integrity": "sha512-sO3PjjxEGy+PY2qkGe2gwJbXdZN9wAYpVBZWFD0AwAoKuXRkWK0/zaMQ5ekUFJDRDCRm8x5U0Axaub7ynH/wVg==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.11.tgz", + "integrity": "sha512-T3yd8vJXfPirZaUOoA9D2ZjxZX4Gr3QuC3GztBJA6PklLotc/7sXTOuuRkhE9W/5JvJP/K9b99ayPNAD+R+4qQ==", "cpu": [ "ppc64" ], @@ -1316,9 +1327,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.10.tgz", - "integrity": "sha512-JDtdbJg3yjDeXLv4lZYE1kiTnxv73/8cbPHY9T/dUKi8rYOM/k5b3W4UJLMUksuQ6nTm5c89W1nADsql6FW75A==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.11.tgz", + "integrity": "sha512-evUoRPWiwuFk++snjH9e2cAjF5VVSTj+Dnf+rkO/Q20tRqv+644279TZlPK8nUGunjPAtQRCj1jQkDAvL6rm2w==", "cpu": [ "riscv64" ], @@ -1332,9 +1343,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.10.tgz", - "integrity": "sha512-NLuSKcp8WckjD2a7z5kzLiCywFwBTMlIxDNuud1AUGVuwBBJSkuubp6cNjJ0p5c6CZaA3QqUGwjHJBiG1SoOFw==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.11.tgz", + "integrity": "sha512-/SlRJ15XR6i93gRWquRxYCfhTeC5PdqEapKoLbX63PLCmAkXZHY2uQm2l9bN0oPHBsOw2IswRZctMYS0MijFcg==", "cpu": [ "s390x" ], @@ -1348,9 +1359,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.10.tgz", - "integrity": "sha512-wj2KRsCsFusli+6yFgNO/zmmLslislAWryJnodteRmGej7ZzinIbMdsyp13rVGde88zxJd5vercNYK9kuvlZaQ==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.11.tgz", + "integrity": "sha512-xcncej+wF16WEmIwPtCHi0qmx1FweBqgsRtEL1mSHLFR6/mb3GEZfLQnx+pUDfRDEM4DQF8dpXIW7eDOZl1IbA==", "cpu": [ "x64" ], @@ -1364,9 +1375,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.10.tgz", - "integrity": "sha512-pQ9QqxEPI3cVRZyUtCoZxhZK3If+7RzR8L2yz2+TDzdygofIPOJFaAPkEJ5rYIbUO101RaiYxfdOBahYexLk5A==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.11.tgz", + "integrity": "sha512-aSjMHj/F7BuS1CptSXNg6S3M4F3bLp5wfFPIJM+Km2NfIVfFKhdmfHF9frhiCLIGVzDziggqWll0B+9AUbud/Q==", "cpu": [ "x64" ], @@ -1380,9 +1391,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.10.tgz", - "integrity": "sha512-k8GTIIW9I8pEEfoOUm32TpPMgSg06JhL5DO+ql66aLTkOQUs0TxCA67Wi7pv6z8iF8STCGcNbm3UWFHLuci+ag==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.11.tgz", + "integrity": "sha512-tNBq+6XIBZtht0xJGv7IBB5XaSyvYPCm1PxJ33zLQONdZoLVM0bgGqUrXnJyiEguD9LU4AHiu+GCXy/Hm9LsdQ==", "cpu": [ "x64" ], @@ -1396,9 +1407,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.10.tgz", - "integrity": "sha512-vIGYJIdEI6d4JBucAx8py792G8J0GP40qSH+EvSt80A4zvGd6jph+5t1g+eEXcS2aRpgZw6CrssNCFZxTdEsxw==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.11.tgz", + "integrity": "sha512-kxfbDOrH4dHuAAOhr7D7EqaYf+W45LsAOOhAet99EyuxxQmjbk8M9N4ezHcEiCYPaiW8Dj3K26Z2V17Gt6p3ng==", "cpu": [ "x64" ], @@ -1412,9 +1423,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.10.tgz", - "integrity": "sha512-kRhNcMZFGMW+ZHCarAM1ypr8OZs0k688ViUCetVCef9p3enFxzWeBg9h/575Y0nsFu0ZItluCVF5gMR2pwOEpA==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.11.tgz", + "integrity": "sha512-Sh0dDRyk1Xi348idbal7lZyfSkjhJsdFeuC13zqdipsvMetlGiFQNdO+Yfp6f6B4FbyQm7qsk16yaZk25LChzg==", "cpu": [ "arm64" ], @@ -1428,9 +1439,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.10.tgz", - "integrity": "sha512-AR9PX1whYaYh9p0EOaKna0h48F/A101Mt/ag72+kMkkBZXPQ7cjbz2syXI/HI3OlBdUytSdHneljfjvUoqwqiQ==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.11.tgz", + "integrity": "sha512-o9JUIKF1j0rqJTFbIoF4bXj6rvrTZYOrfRcGyL0Vm5uJ/j5CkBD/51tpdxe9lXEDouhRgdr/BYzUrDOvrWwJpg==", "cpu": [ "ia32" ], @@ -1444,9 +1455,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.10.tgz", - "integrity": "sha512-5sTkYhAGHNRr6bVf4RM0PsscqVr6/DBYdrlMh168oph3usid3lKHcHEEHmr34iZ9GHeeg2juFOxtpl6XyC3tpw==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.11.tgz", + "integrity": "sha512-rQI4cjLHd2hGsM1LqgDI7oOCYbQ6IBOVsX9ejuRMSze0GqXUG2ekwiKkiBU1pRGSeCqFFHxTrcEydB2Hyoz9CA==", "cpu": [ "x64" ], @@ -1484,14 +1495,14 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", - "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", + "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.2", + "espree": "^9.6.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -1544,9 +1555,9 @@ "dev": true }, "node_modules/@eslint/js": { - "version": "8.43.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz", - "integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==", + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", + "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2390,6 +2401,12 @@ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" }, + "node_modules/@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, "node_modules/@types/serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", @@ -2472,9 +2489,9 @@ } }, "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz", + "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -3020,9 +3037,9 @@ ] }, "node_modules/chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -3770,9 +3787,9 @@ } }, "node_modules/esbuild": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.10.tgz", - "integrity": "sha512-33WKo67auOXzZHBY/9DTJRo7kIvfU12S+D4sp2wIz39N88MDIaCGyCwbW01RR70pK6Iya0I74lHEpyLfFqOHPA==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.11.tgz", + "integrity": "sha512-i8u6mQF0JKJUlGR3OdFLKldJQMMs8OqM9Cc3UCi9XXziJ9WERM5bfkHaEAy0YAvPRMgqSW55W7xYn84XtEFTtA==", "dev": true, "hasInstallScript": true, "bin": { @@ -3782,28 +3799,28 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.18.10", - "@esbuild/android-arm64": "0.18.10", - "@esbuild/android-x64": "0.18.10", - "@esbuild/darwin-arm64": "0.18.10", - "@esbuild/darwin-x64": "0.18.10", - "@esbuild/freebsd-arm64": "0.18.10", - "@esbuild/freebsd-x64": "0.18.10", - "@esbuild/linux-arm": "0.18.10", - "@esbuild/linux-arm64": "0.18.10", - "@esbuild/linux-ia32": "0.18.10", - "@esbuild/linux-loong64": "0.18.10", - "@esbuild/linux-mips64el": "0.18.10", - "@esbuild/linux-ppc64": "0.18.10", - "@esbuild/linux-riscv64": "0.18.10", - "@esbuild/linux-s390x": "0.18.10", - "@esbuild/linux-x64": "0.18.10", - "@esbuild/netbsd-x64": "0.18.10", - "@esbuild/openbsd-x64": "0.18.10", - "@esbuild/sunos-x64": "0.18.10", - "@esbuild/win32-arm64": "0.18.10", - "@esbuild/win32-ia32": "0.18.10", - "@esbuild/win32-x64": "0.18.10" + "@esbuild/android-arm": "0.18.11", + "@esbuild/android-arm64": "0.18.11", + "@esbuild/android-x64": "0.18.11", + "@esbuild/darwin-arm64": "0.18.11", + "@esbuild/darwin-x64": "0.18.11", + "@esbuild/freebsd-arm64": "0.18.11", + "@esbuild/freebsd-x64": "0.18.11", + "@esbuild/linux-arm": "0.18.11", + "@esbuild/linux-arm64": "0.18.11", + "@esbuild/linux-ia32": "0.18.11", + "@esbuild/linux-loong64": "0.18.11", + "@esbuild/linux-mips64el": "0.18.11", + "@esbuild/linux-ppc64": "0.18.11", + "@esbuild/linux-riscv64": "0.18.11", + "@esbuild/linux-s390x": "0.18.11", + "@esbuild/linux-x64": "0.18.11", + "@esbuild/netbsd-x64": "0.18.11", + "@esbuild/openbsd-x64": "0.18.11", + "@esbuild/sunos-x64": "0.18.11", + "@esbuild/win32-arm64": "0.18.11", + "@esbuild/win32-ia32": "0.18.11", + "@esbuild/win32-x64": "0.18.11" } }, "node_modules/escalade": { @@ -3832,15 +3849,15 @@ } }, "node_modules/eslint": { - "version": "8.43.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz", - "integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==", + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.44.0.tgz", + "integrity": "sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.43.0", + "@eslint/eslintrc": "^2.1.0", + "@eslint/js": "8.44.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -3852,7 +3869,7 @@ "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.2.0", "eslint-visitor-keys": "^3.4.1", - "espree": "^9.5.2", + "espree": "^9.6.0", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -3872,7 +3889,7 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" @@ -3969,12 +3986,12 @@ "dev": true }, "node_modules/espree": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.0.tgz", + "integrity": "sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==", "dev": true, "dependencies": { - "acorn": "^8.8.0", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" }, @@ -6054,9 +6071,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/mysql2": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.4.2.tgz", - "integrity": "sha512-hdGwVNke2TJE37gzVvzWRwCFKhrT+5Gy00FDgJUDYArapx3HcaYCJAQUbBiVnB491zLC6HVHNfsmweIotkCRtQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.4.3.tgz", + "integrity": "sha512-pgXnfmZlJ2JnJk9A5z3tnJcG4w8ly/AbVsVsgcavhiOQ7VQpxMwmIyR2CTNxNLKQWQUdD5QOkKkY1DdoRDgSnA==", "dependencies": { "denque": "^2.1.0", "generate-function": "^2.3.1", @@ -6380,17 +6397,17 @@ } }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "type-check": "^0.4.0" }, "engines": { "node": ">= 0.8.0" @@ -7395,9 +7412,9 @@ } }, "node_modules/socket.io": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.0.tgz", - "integrity": "sha512-eOpu7oCNiPGBHn9Falg0cAGivp6TpDI3Yt596fbsf+vln8kRLFWxXKrecFrybn/xNYVn9HcdJNAkYToCmTjsyg==", + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.1.tgz", + "integrity": "sha512-W+utHys2w//dhFjy7iQQu9sGd3eokCjGbl2r59tyLqNiJJBdIebn3GAKEXBr3osqHTObJi2die/25bCx2zsaaw==", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", @@ -7816,9 +7833,9 @@ } }, "node_modules/systeminformation": { - "version": "5.18.5", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.18.5.tgz", - "integrity": "sha512-es2jgMdpjNv9B/sQc0afGlnS2ip7/Nzlo9hAgkaq22NZftQuqHTnf/CuBadzOwl/DZB2aCTLDtzw83nAnT2owg==", + "version": "5.18.6", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.18.6.tgz", + "integrity": "sha512-pLXv6kjJZ1xUcVs9SrCqbQ9y0x1rgRWxBUc8/KxpOp9IRxFGFfzVK5efsxBn/KdYog4C9rPcKk+kHNIL2SB/8Q==", "os": [ "darwin", "linux", @@ -8062,9 +8079,9 @@ } }, "node_modules/typescript": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", - "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", + "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -8802,15 +8819,6 @@ "node": ">=8.12.0" } }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -8977,9 +8985,23 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", + "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } }, "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, "@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -9771,156 +9793,156 @@ "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, "@esbuild/android-arm": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.10.tgz", - "integrity": "sha512-3KClmVNd+Fku82uZJz5C4Rx8m1PPmWUFz5Zkw8jkpZPOmsq+EG1TTOtw1OXkHuX3WczOFQigrtf60B1ijKwNsg==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.11.tgz", + "integrity": "sha512-q4qlUf5ucwbUJZXF5tEQ8LF7y0Nk4P58hOsGk3ucY0oCwgQqAnqXVbUuahCddVHfrxmpyewRpiTHwVHIETYu7Q==", "dev": true, "optional": true }, "@esbuild/android-arm64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.10.tgz", - "integrity": "sha512-ynm4naLbNbK0ajf9LUWtQB+6Vfg1Z/AplArqr4tGebC00Z6m9Y91OVIcjDa461wGcZwcaHYaZAab4yJxfhisTQ==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.11.tgz", + "integrity": "sha512-snieiq75Z1z5LJX9cduSAjUr7vEI1OdlzFPMw0HH5YI7qQHDd3qs+WZoMrWYDsfRJSq36lIA6mfZBkvL46KoIw==", "dev": true, "optional": true }, "@esbuild/android-x64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.10.tgz", - "integrity": "sha512-vFfXj8P9Yfjh54yqUDEHKzqzYuEfPyAOl3z7R9hjkwt+NCvbn9VMxX+IILnAfdImRBfYVItgSUsqGKhJFnBwZw==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.11.tgz", + "integrity": "sha512-iPuoxQEV34+hTF6FT7om+Qwziv1U519lEOvekXO9zaMMlT9+XneAhKL32DW3H7okrCOBQ44BMihE8dclbZtTuw==", "dev": true, "optional": true }, "@esbuild/darwin-arm64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.10.tgz", - "integrity": "sha512-k2OJQ7ZxE6sVc91+MQeZH9gFeDAH2uIYALPAwTjTCvcPy9Dzrf7V7gFUQPYkn09zloWhQ+nvxWHia2x2ZLR0sQ==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.11.tgz", + "integrity": "sha512-Gm0QkI3k402OpfMKyQEEMG0RuW2LQsSmI6OeO4El2ojJMoF5NLYb3qMIjvbG/lbMeLOGiW6ooU8xqc+S0fgz2w==", "dev": true, "optional": true }, "@esbuild/darwin-x64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.10.tgz", - "integrity": "sha512-tnz/mdZk1L1Z3WpGjin/L2bKTe8/AKZpI8fcCLtH+gq8WXWsCNJSxlesAObV4qbtTl6pG5vmqFXfWUQ5hV8PAQ==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.11.tgz", + "integrity": "sha512-N15Vzy0YNHu6cfyDOjiyfJlRJCB/ngKOAvoBf1qybG3eOq0SL2Lutzz9N7DYUbb7Q23XtHPn6lMDF6uWbGv9Fw==", "dev": true, "optional": true }, "@esbuild/freebsd-arm64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.10.tgz", - "integrity": "sha512-QJluV0LwBrbHnYYwSKC+K8RGz0g/EyhpQH1IxdoFT0nM7PfgjE+aS8wxq/KFEsU0JkL7U/EEKd3O8xVBxXb2aA==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.11.tgz", + "integrity": "sha512-atEyuq6a3omEY5qAh5jIORWk8MzFnCpSTUruBgeyN9jZq1K/QI9uke0ATi3MHu4L8c59CnIi4+1jDKMuqmR71A==", "dev": true, "optional": true }, "@esbuild/freebsd-x64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.10.tgz", - "integrity": "sha512-Hi/ycUkS6KTw+U9G5PK5NoK7CZboicaKUSVs0FSiPNtuCTzK6HNM4DIgniH7hFaeuszDS9T4dhAHWiLSt/Y5Ng==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.11.tgz", + "integrity": "sha512-XtuPrEfBj/YYYnAAB7KcorzzpGTvOr/dTtXPGesRfmflqhA4LMF0Gh/n5+a9JBzPuJ+CGk17CA++Hmr1F/gI0Q==", "dev": true, "optional": true }, "@esbuild/linux-arm": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.10.tgz", - "integrity": "sha512-HfFoxY172tVHPIvJy+FHxzB4l8xU7e5cxmNS11cQ2jt4JWAukn/7LXaPdZid41UyTweqa4P/1zs201gRGCTwHw==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.11.tgz", + "integrity": "sha512-Idipz+Taso/toi2ETugShXjQ3S59b6m62KmLHkJlSq/cBejixmIydqrtM2XTvNCywFl3VC7SreSf6NV0i6sRyg==", "dev": true, "optional": true }, "@esbuild/linux-arm64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.10.tgz", - "integrity": "sha512-Nz6XcfRBOO7jSrVpKAyEyFOPGhySPNlgumSDhWAspdQQ11ub/7/NZDMhWDFReE9QH/SsCOCLQbdj0atAk/HMOQ==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.11.tgz", + "integrity": "sha512-c6Vh2WS9VFKxKZ2TvJdA7gdy0n6eSy+yunBvv4aqNCEhSWVor1TU43wNRp2YLO9Vng2G+W94aRz+ILDSwAiYog==", "dev": true, "optional": true }, "@esbuild/linux-ia32": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.10.tgz", - "integrity": "sha512-otMdmSmkMe+pmiP/bZBjfphyAsTsngyT9RCYwoFzqrveAbux9nYitDTpdgToG0Z0U55+PnH654gCH2GQ1aB6Yw==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.11.tgz", + "integrity": "sha512-S3hkIF6KUqRh9n1Q0dSyYcWmcVa9Cg+mSoZEfFuzoYXXsk6196qndrM+ZiHNwpZKi3XOXpShZZ+9dfN5ykqjjw==", "dev": true, "optional": true }, "@esbuild/linux-loong64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.10.tgz", - "integrity": "sha512-t8tjFuON1koxskzQ4VFoh0T5UDUMiLYjwf9Wktd0tx8AoK6xgU+5ubKOpWpcnhEQ2tESS5u0v6QuN8PX/ftwcQ==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.11.tgz", + "integrity": "sha512-MRESANOoObQINBA+RMZW+Z0TJWpibtE7cPFnahzyQHDCA9X9LOmGh68MVimZlM9J8n5Ia8lU773te6O3ILW8kw==", "dev": true, "optional": true }, "@esbuild/linux-mips64el": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.10.tgz", - "integrity": "sha512-+dUkcVzcfEJHz3HEnVpIJu8z8Wdn2n/nWMWdl6FVPFGJAVySO4g3+XPzNKFytVFwf8hPVDwYXzVcu8GMFqsqZw==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.11.tgz", + "integrity": "sha512-qVyPIZrXNMOLYegtD1u8EBccCrBVshxMrn5MkuFc3mEVsw7CCQHaqZ4jm9hbn4gWY95XFnb7i4SsT3eflxZsUg==", "dev": true, "optional": true }, "@esbuild/linux-ppc64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.10.tgz", - "integrity": "sha512-sO3PjjxEGy+PY2qkGe2gwJbXdZN9wAYpVBZWFD0AwAoKuXRkWK0/zaMQ5ekUFJDRDCRm8x5U0Axaub7ynH/wVg==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.11.tgz", + "integrity": "sha512-T3yd8vJXfPirZaUOoA9D2ZjxZX4Gr3QuC3GztBJA6PklLotc/7sXTOuuRkhE9W/5JvJP/K9b99ayPNAD+R+4qQ==", "dev": true, "optional": true }, "@esbuild/linux-riscv64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.10.tgz", - "integrity": "sha512-JDtdbJg3yjDeXLv4lZYE1kiTnxv73/8cbPHY9T/dUKi8rYOM/k5b3W4UJLMUksuQ6nTm5c89W1nADsql6FW75A==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.11.tgz", + "integrity": "sha512-evUoRPWiwuFk++snjH9e2cAjF5VVSTj+Dnf+rkO/Q20tRqv+644279TZlPK8nUGunjPAtQRCj1jQkDAvL6rm2w==", "dev": true, "optional": true }, "@esbuild/linux-s390x": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.10.tgz", - "integrity": "sha512-NLuSKcp8WckjD2a7z5kzLiCywFwBTMlIxDNuud1AUGVuwBBJSkuubp6cNjJ0p5c6CZaA3QqUGwjHJBiG1SoOFw==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.11.tgz", + "integrity": "sha512-/SlRJ15XR6i93gRWquRxYCfhTeC5PdqEapKoLbX63PLCmAkXZHY2uQm2l9bN0oPHBsOw2IswRZctMYS0MijFcg==", "dev": true, "optional": true }, "@esbuild/linux-x64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.10.tgz", - "integrity": "sha512-wj2KRsCsFusli+6yFgNO/zmmLslislAWryJnodteRmGej7ZzinIbMdsyp13rVGde88zxJd5vercNYK9kuvlZaQ==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.11.tgz", + "integrity": "sha512-xcncej+wF16WEmIwPtCHi0qmx1FweBqgsRtEL1mSHLFR6/mb3GEZfLQnx+pUDfRDEM4DQF8dpXIW7eDOZl1IbA==", "dev": true, "optional": true }, "@esbuild/netbsd-x64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.10.tgz", - "integrity": "sha512-pQ9QqxEPI3cVRZyUtCoZxhZK3If+7RzR8L2yz2+TDzdygofIPOJFaAPkEJ5rYIbUO101RaiYxfdOBahYexLk5A==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.11.tgz", + "integrity": "sha512-aSjMHj/F7BuS1CptSXNg6S3M4F3bLp5wfFPIJM+Km2NfIVfFKhdmfHF9frhiCLIGVzDziggqWll0B+9AUbud/Q==", "dev": true, "optional": true }, "@esbuild/openbsd-x64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.10.tgz", - "integrity": "sha512-k8GTIIW9I8pEEfoOUm32TpPMgSg06JhL5DO+ql66aLTkOQUs0TxCA67Wi7pv6z8iF8STCGcNbm3UWFHLuci+ag==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.11.tgz", + "integrity": "sha512-tNBq+6XIBZtht0xJGv7IBB5XaSyvYPCm1PxJ33zLQONdZoLVM0bgGqUrXnJyiEguD9LU4AHiu+GCXy/Hm9LsdQ==", "dev": true, "optional": true }, "@esbuild/sunos-x64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.10.tgz", - "integrity": "sha512-vIGYJIdEI6d4JBucAx8py792G8J0GP40qSH+EvSt80A4zvGd6jph+5t1g+eEXcS2aRpgZw6CrssNCFZxTdEsxw==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.11.tgz", + "integrity": "sha512-kxfbDOrH4dHuAAOhr7D7EqaYf+W45LsAOOhAet99EyuxxQmjbk8M9N4ezHcEiCYPaiW8Dj3K26Z2V17Gt6p3ng==", "dev": true, "optional": true }, "@esbuild/win32-arm64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.10.tgz", - "integrity": "sha512-kRhNcMZFGMW+ZHCarAM1ypr8OZs0k688ViUCetVCef9p3enFxzWeBg9h/575Y0nsFu0ZItluCVF5gMR2pwOEpA==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.11.tgz", + "integrity": "sha512-Sh0dDRyk1Xi348idbal7lZyfSkjhJsdFeuC13zqdipsvMetlGiFQNdO+Yfp6f6B4FbyQm7qsk16yaZk25LChzg==", "dev": true, "optional": true }, "@esbuild/win32-ia32": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.10.tgz", - "integrity": "sha512-AR9PX1whYaYh9p0EOaKna0h48F/A101Mt/ag72+kMkkBZXPQ7cjbz2syXI/HI3OlBdUytSdHneljfjvUoqwqiQ==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.11.tgz", + "integrity": "sha512-o9JUIKF1j0rqJTFbIoF4bXj6rvrTZYOrfRcGyL0Vm5uJ/j5CkBD/51tpdxe9lXEDouhRgdr/BYzUrDOvrWwJpg==", "dev": true, "optional": true }, "@esbuild/win32-x64": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.10.tgz", - "integrity": "sha512-5sTkYhAGHNRr6bVf4RM0PsscqVr6/DBYdrlMh168oph3usid3lKHcHEEHmr34iZ9GHeeg2juFOxtpl6XyC3tpw==", + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.11.tgz", + "integrity": "sha512-rQI4cjLHd2hGsM1LqgDI7oOCYbQ6IBOVsX9ejuRMSze0GqXUG2ekwiKkiBU1pRGSeCqFFHxTrcEydB2Hyoz9CA==", "dev": true, "optional": true }, @@ -9940,14 +9962,14 @@ "dev": true }, "@eslint/eslintrc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", - "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", + "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.2", + "espree": "^9.6.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -9986,9 +10008,9 @@ } }, "@eslint/js": { - "version": "8.43.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz", - "integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==", + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", + "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", "dev": true }, "@humanwhocodes/config-array": { @@ -10596,6 +10618,12 @@ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" }, + "@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, "@types/serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", @@ -10664,9 +10692,9 @@ } }, "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz", + "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==", "dev": true }, "acorn-jsx": { @@ -11017,9 +11045,9 @@ "dev": true }, "chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==" + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==" }, "chokidar": { "version": "3.5.3", @@ -11569,33 +11597,33 @@ } }, "esbuild": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.10.tgz", - "integrity": "sha512-33WKo67auOXzZHBY/9DTJRo7kIvfU12S+D4sp2wIz39N88MDIaCGyCwbW01RR70pK6Iya0I74lHEpyLfFqOHPA==", - "dev": true, - "requires": { - "@esbuild/android-arm": "0.18.10", - "@esbuild/android-arm64": "0.18.10", - "@esbuild/android-x64": "0.18.10", - "@esbuild/darwin-arm64": "0.18.10", - "@esbuild/darwin-x64": "0.18.10", - "@esbuild/freebsd-arm64": "0.18.10", - "@esbuild/freebsd-x64": "0.18.10", - "@esbuild/linux-arm": "0.18.10", - "@esbuild/linux-arm64": "0.18.10", - "@esbuild/linux-ia32": "0.18.10", - "@esbuild/linux-loong64": "0.18.10", - "@esbuild/linux-mips64el": "0.18.10", - "@esbuild/linux-ppc64": "0.18.10", - "@esbuild/linux-riscv64": "0.18.10", - "@esbuild/linux-s390x": "0.18.10", - "@esbuild/linux-x64": "0.18.10", - "@esbuild/netbsd-x64": "0.18.10", - "@esbuild/openbsd-x64": "0.18.10", - "@esbuild/sunos-x64": "0.18.10", - "@esbuild/win32-arm64": "0.18.10", - "@esbuild/win32-ia32": "0.18.10", - "@esbuild/win32-x64": "0.18.10" + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.11.tgz", + "integrity": "sha512-i8u6mQF0JKJUlGR3OdFLKldJQMMs8OqM9Cc3UCi9XXziJ9WERM5bfkHaEAy0YAvPRMgqSW55W7xYn84XtEFTtA==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.18.11", + "@esbuild/android-arm64": "0.18.11", + "@esbuild/android-x64": "0.18.11", + "@esbuild/darwin-arm64": "0.18.11", + "@esbuild/darwin-x64": "0.18.11", + "@esbuild/freebsd-arm64": "0.18.11", + "@esbuild/freebsd-x64": "0.18.11", + "@esbuild/linux-arm": "0.18.11", + "@esbuild/linux-arm64": "0.18.11", + "@esbuild/linux-ia32": "0.18.11", + "@esbuild/linux-loong64": "0.18.11", + "@esbuild/linux-mips64el": "0.18.11", + "@esbuild/linux-ppc64": "0.18.11", + "@esbuild/linux-riscv64": "0.18.11", + "@esbuild/linux-s390x": "0.18.11", + "@esbuild/linux-x64": "0.18.11", + "@esbuild/netbsd-x64": "0.18.11", + "@esbuild/openbsd-x64": "0.18.11", + "@esbuild/sunos-x64": "0.18.11", + "@esbuild/win32-arm64": "0.18.11", + "@esbuild/win32-ia32": "0.18.11", + "@esbuild/win32-x64": "0.18.11" } }, "escalade": { @@ -11615,15 +11643,15 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" }, "eslint": { - "version": "8.43.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz", - "integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==", + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.44.0.tgz", + "integrity": "sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.43.0", + "@eslint/eslintrc": "^2.1.0", + "@eslint/js": "8.44.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -11635,7 +11663,7 @@ "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.2.0", "eslint-visitor-keys": "^3.4.1", - "espree": "^9.5.2", + "espree": "^9.6.0", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -11655,7 +11683,7 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" @@ -11717,12 +11745,12 @@ "dev": true }, "espree": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.0.tgz", + "integrity": "sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==", "dev": true, "requires": { - "acorn": "^8.8.0", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } @@ -13262,9 +13290,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "mysql2": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.4.2.tgz", - "integrity": "sha512-hdGwVNke2TJE37gzVvzWRwCFKhrT+5Gy00FDgJUDYArapx3HcaYCJAQUbBiVnB491zLC6HVHNfsmweIotkCRtQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.4.3.tgz", + "integrity": "sha512-pgXnfmZlJ2JnJk9A5z3tnJcG4w8ly/AbVsVsgcavhiOQ7VQpxMwmIyR2CTNxNLKQWQUdD5QOkKkY1DdoRDgSnA==", "requires": { "denque": "^2.1.0", "generate-function": "^2.3.1", @@ -13489,17 +13517,17 @@ } }, "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "type-check": "^0.4.0" } }, "p-cancelable": { @@ -14170,9 +14198,9 @@ "integrity": "sha512-5ByW6qXqPeG0Tmlkh24JhdXhvQsbaJSjVr3GgGxUV0BSskZKKBZZfFWxezap8+fh1vxBN9GVbqI1V6nqAFxlBg==" }, "socket.io": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.0.tgz", - "integrity": "sha512-eOpu7oCNiPGBHn9Falg0cAGivp6TpDI3Yt596fbsf+vln8kRLFWxXKrecFrybn/xNYVn9HcdJNAkYToCmTjsyg==", + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.1.tgz", + "integrity": "sha512-W+utHys2w//dhFjy7iQQu9sGd3eokCjGbl2r59tyLqNiJJBdIebn3GAKEXBr3osqHTObJi2die/25bCx2zsaaw==", "requires": { "accepts": "~1.3.4", "base64id": "~2.0.0", @@ -14483,9 +14511,9 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, "systeminformation": { - "version": "5.18.5", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.18.5.tgz", - "integrity": "sha512-es2jgMdpjNv9B/sQc0afGlnS2ip7/Nzlo9hAgkaq22NZftQuqHTnf/CuBadzOwl/DZB2aCTLDtzw83nAnT2owg==" + "version": "5.18.6", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.18.6.tgz", + "integrity": "sha512-pLXv6kjJZ1xUcVs9SrCqbQ9y0x1rgRWxBUc8/KxpOp9IRxFGFfzVK5efsxBn/KdYog4C9rPcKk+kHNIL2SB/8Q==" }, "text-extensions": { "version": "1.9.0", @@ -14628,9 +14656,9 @@ } }, "typescript": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", - "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", + "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", "dev": true }, "unbox-primitive": { @@ -15026,12 +15054,6 @@ } } }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -15142,6 +15164,11 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true + }, + "zod": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", + "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==" } } } diff --git a/package.json b/package.json index 5da7519aa..1893616a7 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "@mui/material": "5.13.6", "boxen": "^7.1.0", "bytes": "^3.1.2", - "chalk": "^5.2.0", + "chalk": "^5.3.0", "d3-array": "^3.2.4", "dateformat": "^5.0.3", "discord.js": "^14.11.0", @@ -76,7 +76,7 @@ "lodash-es": "^4.17.21", "lowdb": "^6.0.1", "mnemonist": "^0.39.5", - "mysql2": "^3.4.2", + "mysql2": "^3.4.3", "nanoid": "^4.0.2", "nanoid-dictionary": "^4.3.0", "node-polyglot": "^2.5.0", @@ -92,14 +92,15 @@ "semver": "^7.5.3", "slash": "^5.1.0", "slug": "^8.2.2", - "socket.io": "^4.7.0", + "socket.io": "^4.7.1", "source-map-support": "^0.5.21", "stream-json": "^1.8.0", "string-argv": "^0.3.2", - "systeminformation": "^5.18.5", + "systeminformation": "^5.18.6", "unicode-emoji-json": "^0.4.0", "windows-release": "^4.0.0", - "xss": "^1.0.14" + "xss": "^1.0.14", + "zod": "^3.21.4" }, "devDependencies": { "@commitlint/cli": "^17.6.6", @@ -114,19 +115,20 @@ "@types/node-polyglot": "^2.4.2", "@types/react": "^18.2.14", "@types/react-dom": "^18.2.6", + "@types/semver": "^7.5.0", "@types/slug": "^5.0.3", "@types/source-map-support": "^0.5.6", "@vitejs/plugin-react": "^4.0.1", "chokidar": "^3.5.3", - "esbuild": "~0.18.10", - "eslint": "^8.43.0", + "esbuild": "~0.18.11", + "eslint": "^8.44.0", "husky": "^8.0.3", "lodash": "^4.17.21", "react": "^18.2.0", "react-dom": "^18.2.0", "rimraf": "^5.0.1", "tsc-watch": "^6.0.4", - "typescript": "^5.1.3", + "typescript": "^5.1.6", "vite": "^4.3.9", "vite-tsconfig-paths": "^4.2.0" } diff --git a/web/main/dashboard.ejs b/web/main/dashboard.ejs index 48e69ba80..f005d93d8 100644 --- a/web/main/dashboard.ejs +++ b/web/main/dashboard.ejs @@ -266,7 +266,7 @@ <% if (fxsOutdated) { %> diff --git a/web/main/diagnostics.ejs b/web/main/diagnostics.ejs index 26e97deb6..8d15e65ae 100644 --- a/web/main/diagnostics.ejs +++ b/web/main/diagnostics.ejs @@ -41,16 +41,12 @@ Uptime: <%= txadmin.uptime %>
FXServer Path: <%= txadmin.fxServerPath %>
Connect Endpoint: <%= txadmin.fxServerHost %>
- HTTP Counter: - <%= txadmin.httpCounterLog %> < <%= txadmin.httpCounterMax %>
Monitor Restarts: CL <%= txadmin.monitorRestarts.close %> / HB <%= txadmin.monitorRestarts.heartBeat %> / HC <%= txadmin.monitorRestarts.healthCheck %>
HB Fails: HTTP <%= txadmin.hbHTTPFails %> / FD3 <%= txadmin.hbFD3Fails %>
- Boot Seconds: <%= txadmin.hbBootSeconds %>
- Freeze Seconds: <%= txadmin.freezeSeconds %>
Koa Sessions: <%= txadmin.koaSessions %>
Logs Storage Size: <%= txadmin.logStorageSize %>
Logger Status: