diff --git a/.dockerignore b/.dockerignore index 758e312..3e6289c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,3 +4,4 @@ tmp prometheus-stack/data webrtcperf* chromium +*.traineddata diff --git a/.gitignore b/.gitignore index c25456f..86de42a 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ webrtcperf.exe webrtcperf_*.gz build _docs +*.traineddata diff --git a/Dockerfile b/Dockerfile index a2e9d7f..cfa3deb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -144,7 +144,7 @@ RUN \ mkdir -p /etc/apt/keyrings; \ curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \ | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg; \ - echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" \ + echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" \ > /etc/apt/sources.list.d/nodesource.list; \ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -; \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list; \ diff --git a/README.md b/README.md index 6b43d0e..4a9ee25 100644 --- a/README.md +++ b/README.md @@ -272,16 +272,15 @@ DEBUG_LEVEL=DEBUG:* yarn start \ --server-data=/data ``` 2. The sent/received videos will be saved in the `/data` directory. -3. Run the VMAF calculator comparing the sent (`_send_.ivf`) with the received video (`_recv_.ivf`): +3. Run the VMAF calculator comparing the sent/received videos: ```sh docker run --rm \ -e DEBUG_LEVEL=INFO \ -v $PWD/data:/data \ ghcr.io/vpalmisano/webrtcperf:devel \ - --vmaf-reference-path /data/1_send_89c58e0f-0307-4ab0-8eff-3ba86fb8ccf0.ivf \ - --vmaf-degraded-paths /data/1_recv_9e03aba3-5fa3-4fe3-9ee2-4166a2256c1d.ivf + --vmaf-path /data \ ``` - The tool will generate a `.vmaf.json` and a `.plotly` files in the `data` directory. + The tool will generate a `.vmaf.json` and a `.plotly` files in the `data/vmaf` directory. Adding the `--vmaf-preview` option, a `.mp4` file containing the side-by-side video comparison will be generated. diff --git a/package.json b/package.json index faf179d..6d283f4 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ }, "license": "AGPL-3.0-or-later", "dependencies": { - "axios": "^1.5.1", + "axios": "^1.6.2", "browserify": "^17.0.0", "camel-case": "^4.1.2", "chalk": "^4.1.2", @@ -75,36 +75,37 @@ "puppeteer-intercept-and-modify-requests": "^1.3.0", "sprintf-js": "^1.1.3", "tar-fs": "^2.1.1", - "terser": "^5.22.0", + "terser": "^5.26.0", "tesseract.js": "^5.0.3", "uuid": "^9.0.1", "word-wrap": "^1.2.5", - "ws": "^8.14.2", - "yaml": "^2.3.3" + "ws": "^8.15.1", + "yaml": "^2.3.4" }, "devDependencies": { - "@types/browserify": "^12.0.39", - "@types/compression": "^1.7.4", - "@types/convict": "^6.1.5", - "@types/convict-format-with-validator": "^6.0.4", - "@types/fast-stats": "^0.0.34", - "@types/node-fetch": "^2.6.7", - "@types/node-os-utils": "^1.3.3", - "@types/pem": "^1.14.3", - "@types/pidusage": "^2.0.4", - "@types/ps-tree": "^1.1.4", - "@types/sprintf-js": "^1.1.3", - "@types/tar-fs": "^2.0.3", - "@types/uuid": "^9.0.6", + "@types/browserify": "^12.0.40", + "@types/compression": "^1.7.5", + "@types/convict": "^6.1.6", + "@types/convict-format-with-validator": "^6.0.5", + "@types/fast-stats": "^0.0.35", + "@types/node": "^20.10.5", + "@types/node-fetch": "^2.6.9", + "@types/node-os-utils": "^1.3.4", + "@types/pem": "^1.14.4", + "@types/pidusage": "^2.0.5", + "@types/ps-tree": "^1.1.6", + "@types/sprintf-js": "^1.1.4", + "@types/tar-fs": "^2.0.4", + "@types/uuid": "^9.0.7", "@types/ws": "^8.5.10", "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", - "eslint": "^8.52.0", - "eslint-config-prettier": "^8.10.0", - "eslint-config-standard": "^16.0.3", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-config-standard": "^17.1.0", "eslint-import-resolver-typescript": "^3.6.1", - "eslint-plugin-import": "^2.29.0", - "eslint-plugin-jest": "^27.4.3", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jest": "^27.6.0", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-promise": "^6.1.1", @@ -114,10 +115,10 @@ "nodemon": "^2.0.22", "prettier": "^2.8.8", "terser-webpack-plugin": "^5.3.9", - "ts-loader": "^9.5.0", - "ts-node": "^10.9.1", - "typedoc": "^0.25.2", - "typescript": "^4.9.5", + "ts-loader": "^9.5.1", + "ts-node": "^10.9.2", + "typedoc": "^0.25.4", + "typescript": "^5.2.3", "webpack": "^5.89.0", "webpack-cli": "^5.1.4", "webpack-node-externals": "^3.0.0", diff --git a/scripts/get-user-media.js b/scripts/get-user-media.js index 9f506e4..05986e7 100644 --- a/scripts/get-user-media.js +++ b/scripts/get-user-media.js @@ -1,4 +1,4 @@ -/* global log, loadScript, sleep, Tesseract, streamWriter */ +/* global log, loadScript, sleep, Tesseract, streamWriter, isDisplayTrack */ const applyOverride = (constraints, override) => { if (override) { @@ -127,12 +127,14 @@ function collectMediaTracks(mediaStream) { * Save the MediaStream video track to disk. * @param {MediaStreamTrack} videoTrack */ -window.saveMediaStreamTrack = async (videoTrack, tag, quality = 0.75) => { +window.saveMediaStreamTrack = async (videoTrack, sendrecv, quality = 0.75) => { const settings = videoTrack.getSettings() const width = settings.width || window.VIDEO_WIDTH const height = settings.height || window.VIDEO_HEIGHT const frameRate = settings.frameRate || window.VIDEO_FRAMERATE - const fname = `${window.WEBRTC_STRESS_TEST_INDEX}_${tag}_${videoTrack.id}.ivf` + const fname = `${window.getParticipantName()}-${sendrecv}_${ + videoTrack.id + }.ivf` log(`saveMediaStreamTrack ${fname} ${width}x${height} ${frameRate}fps`) const writer = await streamWriter(fname, width, height, frameRate, 'MJPG') @@ -215,6 +217,8 @@ const applyTimestampWatermark = mediaStream => { const fontSize = Math.ceil(canvas.height / 18) ctx.font = `${fontSize}px Sans` const textHeight = fontSize + 6 + const participantName = + window.getParticipantName() + (isDisplayTrack(videoTrack) ? ' -s' : '') const transformer = new window.TransformStream({ async transform(videoFrame, controller) { @@ -231,6 +235,11 @@ const applyTimestampWatermark = mediaStream => { ctx.fillStyle = 'white' ctx.fillText(text, 0, fontSize) + ctx.fillStyle = 'black' + ctx.fillRect(0, height - textHeight, width, height) + ctx.fillStyle = 'white' + ctx.fillText(participantName, 0, height - 6) + const newBitmap = await createImageBitmap(canvas) const newFrame = new VideoFrame(newBitmap, { timestamp }) newBitmap.close() diff --git a/src/app.ts b/src/app.ts index ad91e69..bac2c58 100644 --- a/src/app.ts +++ b/src/app.ts @@ -58,7 +58,7 @@ async function main(): Promise { } // VMAF score. - if (config.vmafReferencePath && config.vmafDegradedPaths) { + if (config.vmafPath) { await calculateVmafScore(config) process.exit(0) } diff --git a/src/config.ts b/src/config.ts index b9f0ed0..989c257 100644 --- a/src/config.ts +++ b/src/config.ts @@ -666,21 +666,13 @@ alert will be successful only when at least 95% of the checks pass.`, env: 'SERVER_DATA', arg: 'server-data', }, - vmafReferencePath: { - doc: `The reference video path to use for VMAF calculation.`, + vmafPath: { + doc: `When set, it runs the VMAF calculator for the videos saved under the provided directory path.`, format: String, nullable: true, default: '', - env: 'VMAF_REFERENCE_PATH', - arg: 'vmaf-reference-path', - }, - vmafDegradedPaths: { - doc: `The degraded video paths (comma-separated) to use for VMAF calculation.`, - format: String, - nullable: true, - default: '', - env: 'VMAF_DEGRADED_PATHS', - arg: 'vmaf-degraded-paths', + env: 'VMAF_PATH', + arg: 'vmaf-path', }, vmafPreview: { doc: `If true, for each VMAF comparison it creates a side-by-side video with \ @@ -690,6 +682,13 @@ the reference and degraded versions.`, env: 'VMAF_PREVIEW', arg: 'vmaf-preview', }, + vmafKeepIntermediateFiles: { + doc: `If true, the VMAF intermediate files will not be deleted.`, + format: 'Boolean', + default: false, + env: 'VMAF_KEEP_INTERMEDIATE_FILES', + arg: 'vmaf-keep-intermediate-files', + }, }) type ConfigDocs = Record< diff --git a/src/utils.ts b/src/utils.ts index 88c8405..ab11e17 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -187,7 +187,7 @@ async function updateSystemStats(): Promise { SystemStatsCache.set('default', stat) } -let systemStatsInterval: NodeJS.Timer | null = null +let systemStatsInterval: NodeJS.Timeout | null = null export function getSystemStats(): SystemStats | undefined { if (!systemStatsInterval) { diff --git a/src/vmaf.ts b/src/vmaf.ts index 921870f..8bd6669 100644 --- a/src/vmaf.ts +++ b/src/vmaf.ts @@ -8,7 +8,6 @@ import { logger, runShellCommand } from './utils' const log = logger('app:vmaf') -// VMAF score methods. export type IvfFrame = { index: number position: number @@ -21,6 +20,7 @@ export type IvfInfo = { frameRate: number ptsIndex: number[] frames: Map + participantDisplayName?: string } const chunkedPromiseAll = async ( @@ -57,12 +57,13 @@ export async function parseIvf( const den = headerView.getUint32(16, true) const num = headerView.getUint32(20, true) const frameRate = den / num + let participantDisplayName = '' const frameHeaderView = new DataView(new ArrayBuffer(12)) let index = 0 let position = 32 let bytesRead = 0 - const frames = new Map() + let frames = new Map() do { const ret = await fd.read( frameHeaderView, @@ -99,36 +100,33 @@ export async function parseIvf( }) tesseractScheduler.addWorker(worker) } + const participantDisplayNameWorker = await createWorker('eng') + await participantDisplayNameWorker.setParameters({ + tessedit_pageseg_mode: PSM.SINGLE_LINE, + }) + + const ptsToRecognized = new Map() + const textHeight = Math.ceil(height / 18) + 6 const recognizeFrame = async (pts: number, index: number) => { const frame = frames.get(pts) if (!frame) { log.warn(`IVF file ${fpath}: pts ${pts} not found, skipping`) - frames.delete(pts) return } const { size, position } = frame const frameView = new DataView(new ArrayBuffer(size)) await fd.read(frameView, 0, size, position + 12) + const buffer = Buffer.from(frameView.buffer, 0, frameView.byteLength) - let image = await Jimp.read( - Buffer.from(frameView.buffer, 0, frameView.byteLength), - ) - image = image.crop(0, 0, width / 2, Math.ceil(height / 18) + 6) + const image = (await Jimp.read(buffer)).crop(0, 0, width / 2, textHeight) const ret = await tesseractScheduler.addJob( 'recognize', await image.getBufferAsync(Jimp.MIME_BMP), ) const { data } = ret const recognizedTime = parseInt(data.text.trim() || '0') - log.debug( - `recognize pts=${index}/${ - frames.size - } text=${data.text.trim()} confidence=${ - data.confidence - } recognizedTime=${recognizedTime}`, - ) if (data.confidence < 75 || !recognizedTime) { log.warn( `recognize pts=${index}/${ @@ -137,13 +135,45 @@ export async function parseIvf( data.confidence } recognizedTime=${recognizedTime}`, ) - frames.delete(pts) + ptsToRecognized.set(pts, 0) return + } else { + log.debug( + `recognize pts=${index}/${ + frames.size + } text=${data.text.trim()} confidence=${ + data.confidence + } recognizedTime=${recognizedTime ? new Date(recognizedTime) : ''}`, + ) } const recognizedPts = Math.round((frameRate * recognizedTime) / 1000) - if (recognizedPts !== pts) { - frames.delete(pts) - frames.set(recognizedPts, frame) + ptsToRecognized.set(pts, recognizedPts) + + if (!participantDisplayName) { + participantDisplayName = '-' + const image = (await Jimp.read(buffer)).crop( + 0, + height - textHeight, + width, + height, + ) + const ret = await participantDisplayNameWorker.recognize( + await image.getBufferAsync(Jimp.MIME_BMP), + ) + const { data } = ret + if (data.confidence > 75) { + participantDisplayName = data.text.trim() + log.debug( + `participantDisplayName="${participantDisplayName}" confidence=${data.confidence}`, + ) + } else { + log.warn( + `participantDisplayName failed text="${data.text.trim()}" confidence=${ + data.confidence + }`, + ) + participantDisplayName = '' + } } } @@ -156,31 +186,61 @@ export async function parseIvf( log.info(`parseIvf ${fpath} running recognizer done`) await tesseractScheduler.terminate() + + const ptsIndex = Array.from(ptsToRecognized.keys()).sort((a, b) => a - b) + for (const [i, pts] of ptsIndex.entries()) { + const recognizedPts = ptsToRecognized.get(pts) + if (!recognizedPts && i) { + const prevRecognizedPts = ptsToRecognized.get(ptsIndex[i - 1]) + if (prevRecognizedPts) { + ptsToRecognized.set(pts, prevRecognizedPts + pts - ptsIndex[i - 1]) + } else { + ptsToRecognized.delete(pts) + } + } + } + + const recognizedFrames = new Map() + for (const [pts, frame] of frames) { + const recognizedPts = ptsToRecognized.get(pts) + if (recognizedPts) { + recognizedFrames.set(recognizedPts, frame) + } + } + frames.clear() + frames = recognizedFrames } const ptsIndex = Array.from(frames.keys()).sort((a, b) => a - b) await fd.close() - return { width, height, frameRate, ptsIndex, frames } + return { width, height, frameRate, ptsIndex, frames, participantDisplayName } } -export async function fixIvfFrames(fpath: string) { - const fixedPath = fpath.replace('.ivf', '.fixed.ivf') - if (fs.existsSync(fixedPath)) { - const { width, height, frameRate, ptsIndex } = await parseIvf(fixedPath) - return { width, height, frameRate, startPts: ptsIndex[0] } +export async function fixIvfFrames(fpath: string, outDir: string) { + const { width, height, frameRate, frames, ptsIndex, participantDisplayName } = + await parseIvf(fpath, true) + if (!participantDisplayName) { + throw new Error(`IVF file ${fpath}: no participant name found`) } - - const { width, height, frameRate, frames, ptsIndex } = await parseIvf( - fpath, - true, - ) if (!ptsIndex.length) { throw new Error(`IVF file ${fpath}: no frames found`) } log.debug(`fixIvfFrames ${fpath}`, { width, height, frameRate }) const fd = await fs.promises.open(fpath, 'r') - const fixedFd = await fs.promises.open(fixedPath, 'w') + + const parts = path.basename(fpath).split('_') + const outFilePath = path.join( + outDir, + parts[0].endsWith('-send') + ? `${participantDisplayName}.ivf` + : `${participantDisplayName}_recv-by_${parts[0].replace( + '-recv', + '', + )}.ivf`, + ) + + const fixedFd = await fs.promises.open(outFilePath, 'w') const headerView = new DataView(new ArrayBuffer(32)) await fd.read(headerView, 0, headerView.byteLength, 0) @@ -198,18 +258,18 @@ export async function fixIvfFrames(fpath: string) { continue } - if (previousFrame && previousPts >= 0 && previousPts < pts - 1) { - const missing = pts - previousPts - 1 + if (previousFrame && previousPts >= 0 && pts - 1 - previousPts > 0) { + const missing = pts - 1 - previousPts if (missing > frameRate * 60 * 60) { throw new Error( `IVF file ${fpath}: too many frames missing: ${missing}`, ) } - log.debug( + /* log.debug( `IVF file ${fpath}: pts ${pts} missing ${missing} frames, copying previous`, - ) + ) */ while (pts - previousPts - 1 > 0) { - previousPts++ + previousPts += 1 previousFrame.setBigUint64(4, BigInt(previousPts), true) await fixedFd.write( new Uint8Array(previousFrame.buffer), @@ -257,27 +317,7 @@ export async function fixIvfFrames(fpath: string) { `IVF file ${fpath}: frames written: ${writtenFrames} duplicated: ${duplicatedFrames}`, ) - return { width, height, frameRate, startPts } -} - -async function alignVideos(referencePath: string, degradedPath: string) { - if (!referencePath.endsWith('.ivf') || !degradedPath.endsWith('.ivf')) { - throw new Error('Only IVF files are supported') - } - - log.debug( - `alignVideos referencePath: ${referencePath} degradedPath: ${degradedPath}`, - ) - const { - width, - height, - frameRate, - startPts: referenceStartPts, - } = await fixIvfFrames(referencePath) - const { startPts: degradedFirstPts } = await fixIvfFrames(degradedPath) - - const ptsDiff = degradedFirstPts - referenceStartPts - return { width, height, frameRate, ptsDiff } + return { participantDisplayName, outFilePath, startPts } } async function runVmaf( @@ -286,24 +326,30 @@ async function runVmaf( preview: boolean, ) { log.info('runVmaf', { referencePath, degradedPath, preview }) - const comparisonPath = - referencePath.replace(/\.[^.]+$/, '_compared-with_') + - path.basename(degradedPath.replace(/\.[^.]+$/, '')) + const comparisonPath = degradedPath.replace(/\.[^.]+$/, '') const vmafLogPath = comparisonPath + '.vmaf.json' const cpus = os.cpus().length - const { width, height, frameRate, ptsDiff } = await alignVideos( + const { + width, + height, + frameRate, + ptsIndex: referencePtsIndex, + } = await parseIvf(referencePath, false) + const { ptsIndex: degradedPtsIndex } = await parseIvf(degradedPath, false) + const ptsDiff = degradedPtsIndex[0] - referencePtsIndex[0] + log.debug('runVmaf', { referencePath, degradedPath, - ) - - const degradedPathFixed = degradedPath.replace('.ivf', '.fixed.ivf') - const referencePathFixed = referencePath.replace('.ivf', '.fixed.ivf') + referencePtsIndex: referencePtsIndex[0], + degradedPtsIndex: degradedPtsIndex[0], + ptsDiff, + }) const cmd = preview ? `ffmpeg -loglevel warning -y -threads ${cpus} \ --i ${degradedPathFixed} \ --ss ${ptsDiff / frameRate} -i ${referencePathFixed} \ +-i ${degradedPath} \ +-ss ${ptsDiff / frameRate} -i ${referencePath} \ -filter_complex "\ [0:v]scale=w=${width}:h=${height}:flags=bicubic:eval=frame,fps=fps=${frameRate},split[deg1][deg2];\ [1:v]scale=w=${width}:h=${height}:flags=bicubic:eval=frame,fps=fps=${frameRate},split[ref1][ref2];\ @@ -313,8 +359,8 @@ async function runVmaf( -map [stacked] -c:v libx264 -crf 20 -f mp4 ${comparisonPath + '.mp4'} \ ` : `ffmpeg -loglevel warning -y -threads ${cpus} \ --i ${degradedPathFixed} \ --ss ${ptsDiff / frameRate} -i ${referencePathFixed} \ +-i ${degradedPath} \ +-ss ${ptsDiff / frameRate} -i ${referencePath} \ -filter_complex "\ [0:v]scale=w=${width}:h=${height}:flags=bicubic:eval=frame,fps=fps=${frameRate}[deg];\ [1:v]scale=w=${width}:h=${height}:flags=bicubic:eval=frame,fps=fps=${frameRate}[ref];\ @@ -328,9 +374,9 @@ async function runVmaf( log.debug('runVmaf', { stdout, stderr, - vmafLog: vmafLog['pooled_metrics']['vmaf'], }) - log.info('VMAF metrics:', vmafLog['pooled_metrics']['vmaf']) + const metrics = vmafLog['pooled_metrics']['vmaf'] + log.info(`VMAF metrics ${comparisonPath}:`, metrics) const plotlyPath = comparisonPath + '.plotly' const title = path.basename(comparisonPath) @@ -372,33 +418,73 @@ async function runVmaf( frames: [], } await fs.promises.writeFile(plotlyPath, JSON.stringify(plotlyData)) + + return metrics } type VmafConfig = { - vmafReferencePath: string - vmafDegradedPaths: string + vmafPath: string vmafPreview: boolean + vmafKeepIntermediateFiles: boolean } export async function calculateVmafScore(config: VmafConfig): Promise { - const { vmafReferencePath, vmafDegradedPaths, vmafPreview } = config - if (!fs.existsSync(config.vmafReferencePath)) { - throw new Error( - `VMAF reference file ${config.vmafReferencePath} does not exist`, - ) + const { vmafPath, vmafPreview, vmafKeepIntermediateFiles } = config + if (!fs.existsSync(config.vmafPath)) { + throw new Error(`VMAF path ${config.vmafPath} does not exist`) } - const vmafDegradedPathsSplit = vmafDegradedPaths.split(',') - vmafDegradedPathsSplit.forEach(path => { - if (!fs.existsSync(path)) { - throw new Error(`VMAF degraded file ${path} does not exist`) + log.debug(`calculateVmafScore referencePath=${vmafPath}`) + + const files = ( + await fs.promises.readdir(vmafPath, { recursive: true }) + ).filter(f => f.endsWith('.ivf') && !f.startsWith('vmaf/')) + log.debug(`calculateVmafScore files=${files}`) + const outPath = path.join(vmafPath, 'vmaf') + await fs.promises.mkdir(outPath, { recursive: true }) + + const reference = new Map() + const degraded = new Map() + for (const file of files) { + const filePath = path.join(vmafPath, file) + const { participantDisplayName, outFilePath } = await fixIvfFrames( + filePath, + outPath, + ) + if (outFilePath.includes('recv-by')) { + if (!degraded.has(participantDisplayName)) { + degraded.set(participantDisplayName, []) + } + degraded.get(participantDisplayName)?.push(outFilePath) + } else { + reference.set(participantDisplayName, outFilePath) } - }) - - log.debug( - ` calculateVmafScore referencePath=${vmafReferencePath} degradedPaths=${vmafDegradedPathsSplit}`, - ) + } - for (const degradedPath of vmafDegradedPathsSplit) { - await runVmaf(vmafReferencePath, degradedPath, vmafPreview) + const ret: Record = {} + for (const participantDisplayName of reference.keys()) { + const vmafReferencePath = reference.get(participantDisplayName) + if (!vmafReferencePath) continue + for (const degradedPath of degraded.get(participantDisplayName) || []) { + try { + const metrics = await runVmaf( + vmafReferencePath, + degradedPath, + vmafPreview, + ) + ret[path.basename(degradedPath).replace('.ivf', '')] = metrics + if (!vmafKeepIntermediateFiles) { + await fs.promises.unlink(degradedPath) + } + } catch (err) { + log.error(`runVmaf error: ${(err as Error).message}`) + } + } + if (!vmafKeepIntermediateFiles) { + await fs.promises.unlink(vmafReferencePath) + } } + await fs.promises.writeFile( + path.join(outPath, 'vmaf.json'), + JSON.stringify(ret, undefined, 2), + ) } diff --git a/yarn.lock b/yarn.lock index 8fb581c..4fe0f5d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -381,10 +381,10 @@ resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== -"@eslint/eslintrc@^2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.2.tgz#c6936b4b328c64496692f76944e755738be62396" - integrity sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g== +"@eslint/eslintrc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== dependencies: ajv "^6.12.4" debug "^4.3.2" @@ -396,10 +396,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.52.0": - version "8.52.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.52.0.tgz#78fe5f117840f69dc4a353adf9b9cd926353378c" - integrity sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA== +"@eslint/js@8.56.0": + version "8.56.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.56.0.tgz#ef20350fec605a7f7035a01764731b2de0f3782b" + integrity sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A== "@humanwhocodes/config-array@^0.11.13": version "0.11.13" @@ -853,10 +853,10 @@ "@types/connect" "*" "@types/node" "*" -"@types/browserify@^12.0.39": - version "12.0.39" - resolved "https://registry.yarnpkg.com/@types/browserify/-/browserify-12.0.39.tgz#b5dff7fb61fb429d656a1ae0e31fd40fb2250f12" - integrity sha512-10PbToKgqw+thhmttL9zqZtrfaeYn2cIY2MPJLWUYWE6D0SFUFvjc0u4hJAb0qiXM2mMQ14rfTocgozZ+JEsXA== +"@types/browserify@^12.0.40": + version "12.0.40" + resolved "https://registry.yarnpkg.com/@types/browserify/-/browserify-12.0.40.tgz#5505c783bd6cce0344456614c4495a5226203a7e" + integrity sha512-vH5hW7Kt2OoSkCDLzCATlG43lrA2sMIVDvN5PaXsMBPxR4aZSdGJj3de6Z8O8cglnTWp6GuPE0B2HKHi0E4T0w== dependencies: "@types/insert-module-globals" "*" "@types/node" "*" @@ -871,10 +871,10 @@ "@types/node" "*" "@types/responselike" "*" -"@types/compression@^1.7.4": - version "1.7.4" - resolved "https://registry.yarnpkg.com/@types/compression/-/compression-1.7.4.tgz#c1af4a0f2d72ea6c96300ae58b9842aa87d77b6e" - integrity sha512-sdFVnQJRkQBX83ydsLCBm4A39p45y0QkxdAR689yOtAFNbbS9Acrp86RZWJj6BHRXyZH9tX4t1dU7XDiGdY3nA== +"@types/compression@^1.7.5": + version "1.7.5" + resolved "https://registry.yarnpkg.com/@types/compression/-/compression-1.7.5.tgz#0f80efef6eb031be57b12221c4ba6bc3577808f7" + integrity sha512-AAQvK5pxMpaT+nDvhHrsBhLSYG5yQdtkaJE1WYieSNY2mVFKAgmU4ks65rkZD5oqnGCFLyQpUr1CqI4DmUMyDg== dependencies: "@types/express" "*" @@ -885,10 +885,10 @@ dependencies: "@types/node" "*" -"@types/convict-format-with-validator@^6.0.4": - version "6.0.4" - resolved "https://registry.yarnpkg.com/@types/convict-format-with-validator/-/convict-format-with-validator-6.0.4.tgz#04ea3f208c8665498aa31006c0f8886b3e99bad4" - integrity sha512-M6Mp0a2KH5I4NUmtDemJaFrD8I2USS/dv13AxrvEo5I7wgoMtOiQ3nFFRhHgofWchwRrOvSPlGlOJ3enkYJs1g== +"@types/convict-format-with-validator@^6.0.5": + version "6.0.5" + resolved "https://registry.yarnpkg.com/@types/convict-format-with-validator/-/convict-format-with-validator-6.0.5.tgz#84f7c95cd341c2de732907846b7cc90f661a9a11" + integrity sha512-C2a0tbzs2V99BmCOZMgMbu1T5Oi31Ui1Yp8zVU4VH4BB8DwiJkREoEjENBvJyrCJpBrRYK1h+YRv8mCWnuWedQ== dependencies: "@types/convict" "*" @@ -899,10 +899,10 @@ dependencies: "@types/node" "*" -"@types/convict@^6.1.5": - version "6.1.5" - resolved "https://registry.yarnpkg.com/@types/convict/-/convict-6.1.5.tgz#d2336e78b5b6bdcbcbdae223e7bd7926a3247d82" - integrity sha512-3tsoWY0lxXLDps6RRYwPb+0zOnzDv/cXAruPGngR2mvItsoxdfaX+mAxp3x2xAaEue1bLXa+Jd0JaLOM7YjXKQ== +"@types/convict@^6.1.6": + version "6.1.6" + resolved "https://registry.yarnpkg.com/@types/convict/-/convict-6.1.6.tgz#bb3643dcdfd388599237f006120a113e56c3f98e" + integrity sha512-1B6jqWHWQud+7yyWAqbxnPmzlHrrOtJzZr1DhhYJ/NbpS4irfZSnq+N5Fm76J9LNRlUZvCmYxTVhhohWRvtqHw== dependencies: "@types/node" "*" @@ -953,10 +953,10 @@ "@types/qs" "*" "@types/serve-static" "*" -"@types/fast-stats@^0.0.34": - version "0.0.34" - resolved "https://registry.yarnpkg.com/@types/fast-stats/-/fast-stats-0.0.34.tgz#6e84c61632ddbe2347f1f17adcb1e890dbb591df" - integrity sha512-34GouOObmjsEJ1g40wIEQBkCtJ+wpilw++g1/yM5b+41PGsO4mCdXoiQjPpFMMIp4odqLU9BkhTW7OukiYI0Kg== +"@types/fast-stats@^0.0.35": + version "0.0.35" + resolved "https://registry.yarnpkg.com/@types/fast-stats/-/fast-stats-0.0.35.tgz#6ae9258b324b79d61bad18108f94e79c51c600b2" + integrity sha512-aNBUXsXKgDqzYqAGm2TIsY/1mccMSf8IX9P2tIgRrarenRHDBud37SwL6PBa3+IIM8MqvwPjYHhU/vxAyYeyyw== "@types/http-cache-semantics@*": version "4.0.1" @@ -1002,18 +1002,18 @@ resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== -"@types/node-fetch@^2.6.7": - version "2.6.7" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.7.tgz#a1abe2ce24228b58ad97f99480fdcf9bbc6ab16d" - integrity sha512-lX17GZVpJ/fuCjguZ5b3TjEbSENxmEk1B2z02yoXSK9WMEWRivhdSY73wWMn6bpcCDAOh6qAdktpKHIlkDk2lg== +"@types/node-fetch@^2.6.9": + version "2.6.9" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.9.tgz#15f529d247f1ede1824f7e7acdaa192d5f28071e" + integrity sha512-bQVlnMLFJ2d35DkPNjEPmd9ueO/rh5EiaZt2bhqiSarPjZIuIV6bPQVqcrEyvNo+AfTrRGVazle1tl597w3gfA== dependencies: "@types/node" "*" form-data "^4.0.0" -"@types/node-os-utils@^1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@types/node-os-utils/-/node-os-utils-1.3.3.tgz#a9fe0ef6cdef3b9cf2277639f3d0f34bca103879" - integrity sha512-iO0aVIeFXY6dVQvzaXzC8t6BuKdywypvRV3+K0kpVGvF0nfnnShFT9Y6AHDFDFVFtop4tL3FVwPej2+qDUzXfA== +"@types/node-os-utils@^1.3.4": + version "1.3.4" + resolved "https://registry.yarnpkg.com/@types/node-os-utils/-/node-os-utils-1.3.4.tgz#2a1c34f56b15d89ddfafcec69f60675638400542" + integrity sha512-BCUYrbdoO4FUbx6MB9atLNFnkxdliFaxdiTJMIPPiecXIApc5zf4NIqV5G1jWv/ReZvtYyHLs40RkBjHX+vykA== "@types/node@*": version "18.0.6" @@ -1025,22 +1025,29 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-16.9.1.tgz#0611b37db4246c937feef529ddcc018cf8e35708" integrity sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g== -"@types/pem@^1.14.3": - version "1.14.3" - resolved "https://registry.yarnpkg.com/@types/pem/-/pem-1.14.3.tgz#6f0fdbacba266fbde3eb9708247127c79a104c3c" - integrity sha512-3guR3b6UQMafMLiFSMp1jWxIOHBIQvgokG2QV0p+B9KyqxNP0JP58V0mJaaWbA3hmJDmsIvjUnxrOd9GW7f7mA== +"@types/node@^20.10.5": + version "20.10.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.5.tgz#47ad460b514096b7ed63a1dae26fad0914ed3ab2" + integrity sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw== + dependencies: + undici-types "~5.26.4" + +"@types/pem@^1.14.4": + version "1.14.4" + resolved "https://registry.yarnpkg.com/@types/pem/-/pem-1.14.4.tgz#020740e26383289c04361b4894bc4d7e8e41a982" + integrity sha512-Xt6qY6kX1RD4UmYNhWCCf3OSJrRcwbQIaJ/mQSjjAHxIjXMHx/vHNPOgEU3HdVKS1k/U5CZ6ClQlRo8egkl8xg== dependencies: "@types/node" "*" -"@types/pidusage@^2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/pidusage/-/pidusage-2.0.4.tgz#0538aea04cdf2a3b439418d2acd2f319c52dcd25" - integrity sha512-yku7awugpbqBz+MjVFzDkJIW8eaN9jySnotHxYfOY5dqnsjRgvG4HQFMQ7wtEaGjk+WjJ8R3Ll3iaaZtVKY3JA== +"@types/pidusage@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@types/pidusage/-/pidusage-2.0.5.tgz#ec8477720e390b78e3d88b7b522d9e2d4c7995a8" + integrity sha512-MIiyZI4/MK9UGUXWt0jJcCZhVw7YdhBuTOuqP/BjuLDLZ2PmmViMIQgZiWxtaMicQfAz/kMrZ5T7PKxFSkTeUA== -"@types/ps-tree@^1.1.4": - version "1.1.4" - resolved "https://registry.yarnpkg.com/@types/ps-tree/-/ps-tree-1.1.4.tgz#762883fb62e03080ced3fc15e702321968bf0009" - integrity sha512-CJyu2BqU/aZN/s8Ili3jiMctqXfTjCaWXirEcjRD8y1lUQZJ8eNohnal8+LXeWFs1VbdAOrCIdgATFsv+lnQ5Q== +"@types/ps-tree@^1.1.6": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@types/ps-tree/-/ps-tree-1.1.6.tgz#fbb22dabe3d64b79295f37ce0afb7320a26ac9a6" + integrity sha512-PtrlVaOaI44/3pl3cvnlK+GxOM3re2526TJvPvh7W+keHIXdV4TE0ylpPBAcvFQCbGitaTXwL9u+RF7qtVeazQ== "@types/qs@*": version "6.9.7" @@ -1072,15 +1079,15 @@ "@types/mime" "^1" "@types/node" "*" -"@types/sprintf-js@^1.1.3": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@types/sprintf-js/-/sprintf-js-1.1.3.tgz#cdad9076d288921cea5b336ab07b915ab27f7921" - integrity sha512-Z9z6EMpwsroPp4BivsuVi/LYWi7jnuMCz9gWD/tZYhlEOSV2MO3fawrwHUEl05mshHyzHejPwe6PM0ZBDQD9yw== +"@types/sprintf-js@^1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@types/sprintf-js/-/sprintf-js-1.1.4.tgz#d27022638127111a79aab777d4d9292d1a11519a" + integrity sha512-aWK1reDYWxcjgcIIPmQi3u+OQDuYa9b+lr6eIsGWrekJ9vr1NSjr4Eab8oQ1iKuH1ltFHpXGyerAv1a3FMKxzQ== -"@types/tar-fs@^2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/tar-fs/-/tar-fs-2.0.3.tgz#99c128ccd8a8a24e9446e0893d6fa393f9cf7e16" - integrity sha512-ADS99HAnztB8MD+LSOdzDrDLcSe5oBIg+SUQwwsgnsOgZobWoSqYmg9ZJWdvLppoKV8R8kZinX6Om+LlsNuIlQ== +"@types/tar-fs@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/tar-fs/-/tar-fs-2.0.4.tgz#7c7502d281d436db0ad0f78282acef71da02a292" + integrity sha512-ipPec0CjTmVDWE+QKr9cTmIIoTl7dFG/yARCM5MqK8i6CNLIG1P8x4kwDsOQY1ChZOZjH0wO9nvfgBvWl4R3kA== dependencies: "@types/node" "*" "@types/tar-stream" "*" @@ -1092,10 +1099,10 @@ dependencies: "@types/node" "*" -"@types/uuid@^9.0.6": - version "9.0.6" - resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.6.tgz#c91ae743d8344a54b2b0c691195f5ff5265f6dfb" - integrity sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew== +"@types/uuid@^9.0.7": + version "9.0.7" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.7.tgz#b14cebc75455eeeb160d5fe23c2fcc0c64f724d8" + integrity sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g== "@types/ws@^8.5.10": version "8.5.10" @@ -1748,10 +1755,10 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -axios@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.5.1.tgz#11fbaa11fc35f431193a9564109c88c1f27b585f" - integrity sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A== +axios@^1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.2.tgz#de67d42c755b571d3e698df1b6504cde9b0ee9f2" + integrity sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A== dependencies: follow-redirects "^1.15.0" form-data "^4.0.0" @@ -3295,15 +3302,15 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -eslint-config-prettier@^8.10.0: - version "8.10.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz#3a06a662130807e2502fc3ff8b4143d8a0658e11" - integrity sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg== +eslint-config-prettier@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f" + integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw== -eslint-config-standard@^16.0.3: - version "16.0.3" - resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz#6c8761e544e96c531ff92642eeb87842b8488516" - integrity sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg== +eslint-config-standard@^17.1.0: + version "17.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz#40ffb8595d47a6b242e07cbfd49dc211ed128975" + integrity sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q== eslint-import-resolver-node@^0.3.9: version "0.3.9" @@ -3349,10 +3356,10 @@ eslint-plugin-es@^3.0.0: eslint-utils "^2.0.0" regexpp "^3.0.0" -eslint-plugin-import@^2.29.0: - version "2.29.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz#8133232e4329ee344f2f612885ac3073b0b7e155" - integrity sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg== +eslint-plugin-import@^2.29.1: + version "2.29.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" + integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw== dependencies: array-includes "^3.1.7" array.prototype.findlastindex "^1.2.3" @@ -3370,12 +3377,12 @@ eslint-plugin-import@^2.29.0: object.groupby "^1.0.1" object.values "^1.1.7" semver "^6.3.1" - tsconfig-paths "^3.14.2" + tsconfig-paths "^3.15.0" -eslint-plugin-jest@^27.4.3: - version "27.4.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.4.3.tgz#7b2330a9e1819b66d06e66b45dfa8e8ef0c23f79" - integrity sha512-7S6SmmsHsgIm06BAGCAxL+ABd9/IB3MWkz2pudj6Qqor2y1qQpWPfuFU4SG9pWj4xDjF0e+D7Llh5useuSzAZw== +eslint-plugin-jest@^27.6.0: + version "27.6.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.6.0.tgz#e5c0cf735b3c8cad0ef9db5b565b2fc99f5e55ed" + integrity sha512-MTlusnnDMChbElsszJvrwD1dN3x6nZl//s4JD23BxB6MgR66TZlL064su24xEIS3VACfAoHV1vgyMgPw8nkdng== dependencies: "@typescript-eslint/utils" "^5.10.0" @@ -3475,15 +3482,15 @@ eslint-visitor-keys@^3.4.3: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint@^8.52.0: - version "8.52.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.52.0.tgz#d0cd4a1fac06427a61ef9242b9353f36ea7062fc" - integrity sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg== +eslint@^8.56.0: + version "8.56.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.56.0.tgz#4957ce8da409dc0809f99ab07a1b94832ab74b15" + integrity sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.2" - "@eslint/js" "8.52.0" + "@eslint/eslintrc" "^2.1.4" + "@eslint/js" "8.56.0" "@humanwhocodes/config-array" "^0.11.13" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" @@ -8040,10 +8047,10 @@ terser@^5.16.8: commander "^2.20.0" source-map-support "~0.5.20" -terser@^5.22.0: - version "5.22.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.22.0.tgz#4f18103f84c5c9437aafb7a14918273310a8a49d" - integrity sha512-hHZVLgRA2z4NWcN6aS5rQDc+7Dcy58HOf2zbYwmFcQ+ua3h6eEFf5lIDKTzbWwlazPyOZsFQO8V80/IjVNExEw== +terser@^5.26.0: + version "5.26.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.26.0.tgz#ee9f05d929f4189a9c28a0feb889d96d50126fe1" + integrity sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.8.2" @@ -8193,10 +8200,10 @@ trim-repeated@^1.0.0: dependencies: escape-string-regexp "^1.0.2" -ts-loader@^9.5.0: - version "9.5.0" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.5.0.tgz#f0a51dda37cc4d8e43e6cb14edebbc599b0c3aa2" - integrity sha512-LLlB/pkB4q9mW2yLdFMnK3dEHbrBjeZTYguaaIfusyojBgAGf5kF+O6KcWqiGzWqHk0LBsoolrp4VftEURhybg== +ts-loader@^9.5.1: + version "9.5.1" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.5.1.tgz#63d5912a86312f1fbe32cef0859fb8b2193d9b89" + integrity sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg== dependencies: chalk "^4.1.0" enhanced-resolve "^5.0.0" @@ -8204,10 +8211,10 @@ ts-loader@^9.5.0: semver "^7.3.4" source-map "^0.7.4" -ts-node@^10.9.1: - version "10.9.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" - integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== +ts-node@^10.9.2: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== dependencies: "@cspotcode/source-map-support" "^0.8.0" "@tsconfig/node10" "^1.0.7" @@ -8223,10 +8230,10 @@ ts-node@^10.9.1: v8-compile-cache-lib "^3.0.1" yn "3.1.1" -tsconfig-paths@^3.14.2: - version "3.14.2" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" - integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g== +tsconfig-paths@^3.15.0: + version "3.15.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" + integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== dependencies: "@types/json5" "^0.0.29" json5 "^1.0.2" @@ -8331,20 +8338,20 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== -typedoc@^0.25.2: - version "0.25.2" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.25.2.tgz#39f525c28b6eb61da54dda4ec6b1500df620bed8" - integrity sha512-286F7BeATBiWe/qC4PCOCKlSTwfnsLbC/4cZ68oGBbvAqb9vV33quEOXx7q176OXotD+JdEerdQ1OZGJ818lnA== +typedoc@^0.25.4: + version "0.25.4" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.25.4.tgz#5c2c0677881f504e41985f29d9aef0dbdb6f1e6f" + integrity sha512-Du9ImmpBCw54bX275yJrxPVnjdIyJO/84co0/L9mwe0R3G4FSR6rQ09AlXVRvZEGMUg09+z/usc8mgygQ1aidA== dependencies: lunr "^2.3.9" marked "^4.3.0" minimatch "^9.0.3" shiki "^0.14.1" -typescript@^4.9.5: - version "4.9.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" - integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== +typescript@^5.2.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" + integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== umd@^3.0.0: version "3.0.3" @@ -8390,6 +8397,11 @@ undefsafe@^2.0.5: resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + union-value@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" @@ -8757,10 +8769,10 @@ ws@8.13.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== -ws@^8.14.2: - version "8.14.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f" - integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g== +ws@^8.15.1: + version "8.15.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.15.1.tgz#271ba33a45ca0cc477940f7f200cd7fba7ee1997" + integrity sha512-W5OZiCjXEmk0yZ66ZN82beM5Sz7l7coYxpRkzS+p9PP+ToQry8szKh+61eNktr7EA9DOwvFGhfC605jDHbP6QQ== xhr@^2.0.1: version "2.6.0" @@ -8815,10 +8827,10 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.3.tgz#01f6d18ef036446340007db8e016810e5d64aad9" - integrity sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ== +yaml@^2.3.4: + version "2.3.4" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.4.tgz#53fc1d514be80aabf386dc6001eb29bf3b7523b2" + integrity sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA== yargs-parser@^20.2.7: version "20.2.9"