From 1e3bb4cfec8abb5f3dd20bac0abe3781554626c8 Mon Sep 17 00:00:00 2001 From: Space_Fox <44732812+emanuelfranklyn@users.noreply.github.com> Date: Tue, 26 Mar 2024 15:03:34 -0300 Subject: [PATCH 01/10] (feat): Initial Rewrite Logging to console and main base Logger class already works, Saving to file and AutoLogEnd are WIP --- .eslintignore | 3 +- .gitignore | 1 + src/main/autoLogEnd.ts | 2 +- src/main/defaults/standard.ts | 27 ++ src/main/interfaces/IDefault.ts | 18 + src/main/interfaces/IEngineSettings.ts | 3 + src/main/interfaces/IFileStorageSettings.ts | 10 + src/main/interfaces/ILogMessage.ts | 44 ++ src/main/interfaces/ILoggerOption.ts | 62 +-- src/main/interfaces/index.ts | 3 + src/main/logger.ts | 475 +++++++++----------- src/main/outputEngines/consoleEngine.ts | 192 ++++++++ src/main/outputEngines/engine.ts | 42 ++ src/main/outputEngines/fileStorageEngine.ts | 60 +++ src/main/outputEngines/index.ts | 3 + 15 files changed, 643 insertions(+), 302 deletions(-) mode change 100644 => 100755 src/main/autoLogEnd.ts create mode 100755 src/main/defaults/standard.ts create mode 100755 src/main/interfaces/IDefault.ts create mode 100755 src/main/interfaces/IEngineSettings.ts create mode 100755 src/main/interfaces/IFileStorageSettings.ts create mode 100644 src/main/interfaces/ILogMessage.ts mode change 100644 => 100755 src/main/interfaces/ILoggerOption.ts mode change 100644 => 100755 src/main/interfaces/index.ts mode change 100644 => 100755 src/main/logger.ts create mode 100755 src/main/outputEngines/consoleEngine.ts create mode 100755 src/main/outputEngines/engine.ts create mode 100755 src/main/outputEngines/fileStorageEngine.ts create mode 100755 src/main/outputEngines/index.ts diff --git a/.eslintignore b/.eslintignore index 63063a1..ae13b2d 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1 +1,2 @@ -build/**/* \ No newline at end of file +build/**/* +*.js diff --git a/.gitignore b/.gitignore index c7addbb..1f6cec1 100644 --- a/.gitignore +++ b/.gitignore @@ -105,3 +105,4 @@ dist # Typescript compiled files build/ +.directory diff --git a/src/main/autoLogEnd.ts b/src/main/autoLogEnd.ts old mode 100644 new mode 100755 index 6274e02..dcd4943 --- a/src/main/autoLogEnd.ts +++ b/src/main/autoLogEnd.ts @@ -33,7 +33,7 @@ function exitHandler({ err, options, exitCode }: {err?: {stack: any, message: an } export function activate(uncaughtException?: boolean, logger?: Logger): void { - logger = logger ?? new Logger({ prefix: 'SYSTEM' }); + logger = logger ?? new Logger({ prefixes: ['SYSTEM'] }); logger?.debug('AutoLogEnd activated!'); process.on('exit', (exitCode) => exitHandler({ exitCode, options: { uncaughtException: false } })); process.on('SIGINT', (error) => { exitHandler({ err: { message: error, name: null, stack: null }, options: { uncaughtException: false }, exitCode: 'SIGINT' }); }); diff --git a/src/main/defaults/standard.ts b/src/main/defaults/standard.ts new file mode 100755 index 0000000..1133e86 --- /dev/null +++ b/src/main/defaults/standard.ts @@ -0,0 +1,27 @@ +import { EStyles } from '../interfaces'; +import { IDefault } from '../interfaces/IDefault'; + +export default { + logLevelMainColors: { + 0: '#cc80ff', + 1: '#ff8a1c', + 2: '#ff4a4a', + 3: '#ffffff', + 4: '#555555', + }, + logLevelAccentColors: { + 0: '#ffffff', + 1: '#ffffff', + 2: '#ffffff', + 3: '#ff0000', + 4: '#ffffff', + }, + prefixMainColor: '#777777', + prefixAccentColor: '#000000', + redactionText: '[REDACTED]', + undefinedColor: '#5555aa', + causedByTextColor: '#ffffff', + causedByBackgroundColor: '#ff0000', + variableStyling: [EStyles.bold, EStyles.textColor], + variableStylingParams: ['', '#55ff55'], +} as IDefault; diff --git a/src/main/interfaces/IDefault.ts b/src/main/interfaces/IDefault.ts new file mode 100755 index 0000000..5a1239c --- /dev/null +++ b/src/main/interfaces/IDefault.ts @@ -0,0 +1,18 @@ +import { EStyles } from './ILogMessage'; + +export interface IDefault { + logLevelMainColors: { + [key: number]: string, + }, + logLevelAccentColors: { + [key: number]: string, + }, + prefixMainColor: string, + prefixAccentColor: string, + redactionText: string, + undefinedColor: string, + causedByTextColor?: string, + causedByBackgroundColor?: string, + variableStyling: EStyles[], + variableStylingParams: string[], +} diff --git a/src/main/interfaces/IEngineSettings.ts b/src/main/interfaces/IEngineSettings.ts new file mode 100755 index 0000000..fbddda2 --- /dev/null +++ b/src/main/interfaces/IEngineSettings.ts @@ -0,0 +1,3 @@ +export interface IEngineSettings { + debug?: boolean; +} diff --git a/src/main/interfaces/IFileStorageSettings.ts b/src/main/interfaces/IFileStorageSettings.ts new file mode 100755 index 0000000..ebacf50 --- /dev/null +++ b/src/main/interfaces/IFileStorageSettings.ts @@ -0,0 +1,10 @@ +import { IEngineSettings } from './'; + +export interface IFileStorageSettings extends IEngineSettings { + logFolderPath: string; + enableLatestLog?: boolean; + enableDebugLog?: boolean; + enableErrorLog?: boolean; + enableFatalLog?: boolean; + compressLogFilesAfterNewExecution?: boolean; +} diff --git a/src/main/interfaces/ILogMessage.ts b/src/main/interfaces/ILogMessage.ts new file mode 100644 index 0000000..5c741de --- /dev/null +++ b/src/main/interfaces/ILogMessage.ts @@ -0,0 +1,44 @@ +import { ILogSettings, IPrefix } from "./ILoggerOption"; + +export enum EStyles { + bold = 1, + italic = 2, + textColor = 3, + backgroundColor = 4, + specialSubLine = 5, + reset = 6, +} + +export enum ELoggerLevel { + INFO = 0, + WARN = 1, + ALERT = 1, + ERROR = 2, + SEVERE = 2, + FATAL = 3, + DEBUG = 4 +} + +export enum ELoggerLevelNames { + 'INFO', + 'WARN', + 'ERROR', + 'FATAL', + 'DEBUG' +} + +export interface IMessageChunk { + content: string; + styling: EStyles[]; + stylingParams: string[]; + subLine: boolean; +} + +export interface ILogMessage { + messageChunks: IMessageChunk[]; + subLines: IMessageChunk[]; + prefixes: IPrefix[]; + timestamp: Date; + logLevel: ELoggerLevel; + settings: ILogSettings; +} diff --git a/src/main/interfaces/ILoggerOption.ts b/src/main/interfaces/ILoggerOption.ts old mode 100644 new mode 100755 index 425326b..264fc68 --- a/src/main/interfaces/ILoggerOption.ts +++ b/src/main/interfaces/ILoggerOption.ts @@ -1,59 +1,27 @@ /* eslint-disable no-unused-vars */ -export enum ELoggerLevel { - INFO = 0, - LOG = 0, - WARN = 1, - ALERT = 1, - ERROR = 2, - SEVERE = 2, - FATAL = 3, - DEBUG = 4 -} +import { IDefault } from './IDefault'; +import { ELoggerLevel } from './ILogMessage'; -export enum ELoggerLevelNames { - 'INFO', - 'WARN', - 'ERROR', - 'FATAL', - 'DEBUG' +export interface IPrefix { + content: string; + color: ((text: string) => string | string[]) | string | string[]; + backgroundColor: ((text: string) => string | string[]) | string | string[] | null; } -// color for text or colored background -export enum ELoggerLevelBaseColors { - '#cc80ff', - '#ff8a1c', - '#ff4a4a', - '#ffffff', - '#555555', +export interface ISharedLogSettings { + coloredBackground?: boolean; } -// color for text on colored background -export const ELoggerLevelAlternateColors = [ - '#000000', - '#000000', - '#000000', - '#ff0000', - '#D4D4D4' -] - -export interface ILoggerFileProperties { - enable: boolean; - logFolderPath: string; - enableLatestLog?: boolean; - enableDebugLog?: boolean; - enableErrorLog?: boolean; - enableFatalLog?: boolean; - generateHTMLLog?: boolean; - compressLogFilesAfterNewExecution?: boolean; +export interface ILogSettings extends ISharedLogSettings { + default: IDefault; } -export interface ILoggerOptions { +export interface ILoggerOptions extends ISharedLogSettings { defaultLevel?: ELoggerLevel; - prefix?: string; - debug?: boolean; - coloredBackground?: boolean; - allLineColored?: boolean; + prefixes: (IPrefix | string)[]; disableFatalCrash?: boolean; - fileProperties?: ILoggerFileProperties + redactedContent?: string[]; + allLineColored?: boolean; + defaultSettings?: IDefault; } diff --git a/src/main/interfaces/index.ts b/src/main/interfaces/index.ts old mode 100644 new mode 100755 index e43a52e..b6097b4 --- a/src/main/interfaces/index.ts +++ b/src/main/interfaces/index.ts @@ -1 +1,4 @@ export * from './ILoggerOption'; +export * from './IFileStorageSettings'; +export * from './ILogMessage'; +export * from './IEngineSettings'; diff --git a/src/main/logger.ts b/src/main/logger.ts old mode 100644 new mode 100755 index d3b6d37..8c2529c --- a/src/main/logger.ts +++ b/src/main/logger.ts @@ -1,300 +1,269 @@ -import { ILoggerOptions, ELoggerLevel, ILoggerFileProperties, ELoggerLevelNames, ELoggerLevelBaseColors, ELoggerLevelAlternateColors } from './interfaces'; -import escape from 'escape-html'; -import admZip from 'adm-zip'; -import chalk from 'chalk'; -import Path from 'path'; -import fs from 'fs'; +import { ELoggerLevel, EStyles, ILogMessage, IMessageChunk } from './interfaces/ILogMessage'; +import { ILoggerOptions, IPrefix } from './interfaces'; +import { Engine } from './outputEngines/engine'; import utils from 'util'; +import { IDefault } from './interfaces/IDefault'; +import Standard from './defaults/standard'; export class Logger { - private defaultLevel: ELoggerLevel = ELoggerLevel.LOG; - private debugActive = false; - private prefix?: string; - private coloredBackground: boolean; + private defaultLevel: ELoggerLevel = ELoggerLevel.INFO; + private prefixes: IPrefix[]; private disableFatalCrash: boolean; + private logListeners: Engine[] = []; + private redactedContent: string[]; + private coloredBackground: boolean; private allLineColored: boolean; - private fileProperties: ILoggerFileProperties; - private latestFileStream?: fs.WriteStream; - private debugLogStream?: fs.WriteStream; - private errorLogStream?: fs.WriteStream; - private htmlBackgroundColor: string; - private htmlTextColor: string; - private defaultHeader = ''; - - constructor({ prefix, debug, defaultLevel, coloredBackground, disableFatalCrash, allLineColored, fileProperties }: ILoggerOptions) { - this.prefix = prefix ?? ''; - this.debugActive = debug ?? false; + private defaultSettings: IDefault; + + constructor({ prefixes, defaultLevel, disableFatalCrash, redactedContent, allLineColored, coloredBackground, defaultSettings }: ILoggerOptions) { this.defaultLevel = defaultLevel ?? ELoggerLevel.INFO; - this.coloredBackground = coloredBackground ?? false; this.disableFatalCrash = disableFatalCrash ?? false; + this.redactedContent = redactedContent ?? []; + this.allLineColored = allLineColored ?? false; + this.coloredBackground = coloredBackground ?? false; + this.defaultSettings = defaultSettings ?? Standard; - this.htmlBackgroundColor = '#0a002b'; - this.htmlTextColor = '#ffffff'; - - this.fileProperties = { - enable: false, - logFolderPath: Path.join(__dirname, 'logs'), - enableLatestLog: true, - enableDebugLog: false, - enableErrorLog: false, - enableFatalLog: true, - generateHTMLLog: false, - compressLogFilesAfterNewExecution: true, - }; + this.prefixes = this.parseMessagePrefix(prefixes); + } - this.fileProperties = { ...this.fileProperties, ...fileProperties ?? {} }; + private parseMessagePrefix(prefixes: (IPrefix | string)[]): IPrefix[] { + if (!prefixes || prefixes.length === 0) return []; + return prefixes.map((prefix) => { + if (typeof prefix !== 'string') return prefix; + return { + content: prefix, + color: this.defaultSettings.prefixMainColor, + backgroundColor: null, + }; + }); + } - if (this.fileProperties.enable) { - // create log folder if not exists - if (!fs.existsSync(this.fileProperties.logFolderPath)) fs.mkdirSync(this.fileProperties.logFolderPath); - else this.compressLastSessionLogs(); + private redactText(text: string): string { + let modifiedString = text; + this.redactedContent.forEach((redaction) => { + const reg = new RegExp(redaction, 'gi'); + const matches = modifiedString.matchAll(reg); + let accumulator = 0; + for (const match of matches) { + if (typeof match.index !== 'number') continue; + modifiedString = + `${modifiedString.slice(0, match.index + accumulator)}${this.defaultSettings.redactionText}${modifiedString.slice(match.index + match[0].length + accumulator)}`; + accumulator += this.defaultSettings.redactionText.length - match[0].length; + } + }); + return modifiedString; + } - // creates folders for fatal-crash and latest logs - if (!fs.existsSync(Path.join(this.fileProperties.logFolderPath, 'fatal-crash'))) fs.mkdirSync(Path.join(this.fileProperties.logFolderPath, 'fatal-crash')); - if (!fs.existsSync(Path.join(this.fileProperties.logFolderPath, 'latestLogs'))) fs.mkdirSync(Path.join(this.fileProperties.logFolderPath, 'latestLogs')); + /** + * Parses the message and returns an array of IMessageChunk objects + * the first IMessageChunk object is the main message, the rest are subLines + * @param text - The content to be parsed + * @param args - The arguments to be passed to the content + * @returns IMessageChunk[] + */ + private processMessage(text: string | string[] | Error, forceSubline: boolean, ...args: any[]): IMessageChunk[] { + if (!text) { + return [{ + content: 'undefined', + styling: [EStyles.textColor], + stylingParams: [this.defaultSettings.undefinedColor], + subLine: forceSubline, + }]; + } - // eslint-disable-next-line max-len - this.defaultHeader = `\n`; + // String handling + if (typeof text !== 'object') { + return [...text.toString().split('\n').map((line) => { + return { + content: this.redactText(utils.format(line, ...args)), + styling: [], + stylingParams: [], + subLine: forceSubline, + }; + })]; + + // Error handling + } else if (text instanceof Error) { + const finalMessage = []; + finalMessage.push({ + content: (forceSubline ? 'Error: ' : '') + this.redactText(utils.format(text.message, ...args)), + styling: [], + stylingParams: [], + subLine: forceSubline, + }); - if (this.fileProperties.enableLatestLog) { - this.latestFileStream = fs.createWriteStream( - Path.join(this.fileProperties.logFolderPath, `latest.${this.fileProperties.generateHTMLLog ? 'html' : 'log'}`), { flags: 'a' }, - ); - if (this.fileProperties.generateHTMLLog) this.latestFileStream.write(this.defaultHeader); - } - if (this.fileProperties.enableDebugLog) { - this.debugLogStream = fs.createWriteStream( - Path.join(this.fileProperties.logFolderPath, 'latestLogs', `debug.${this.fileProperties.generateHTMLLog ? 'html' : 'log'}`), { flags: 'a' }, - ); - if (this.fileProperties.generateHTMLLog) this.debugLogStream.write(this.defaultHeader); - } - if (this.fileProperties.enableErrorLog) { - this.errorLogStream = fs.createWriteStream( - Path.join(this.fileProperties.logFolderPath, 'latestLogs', `error.${this.fileProperties.generateHTMLLog ? 'html' : 'log'}`), { flags: 'a' }, - ); - if (this.fileProperties.generateHTMLLog) this.errorLogStream.write(this.defaultHeader); - } + const stack = text.stack?.split('\n'); + stack?.shift(); - // handles process exists to properly close the streams - process.on('exit', (exitCode) => { - // eslint-disable-next-line max-len - this.closeFileStreams(`${this.fileProperties.generateHTMLLog ? '
\n' : '\n'}Process exited with code (${exitCode})${this.fileProperties.generateHTMLLog ? '\n
' : '\n'}`); + stack?.forEach((line) => { + finalMessage.push({ + content: this.redactText(line.trim()), + styling: [], + stylingParams: [], + subLine: true, + }); }); - } else { - this.fileProperties.enableLatestLog = false; - this.fileProperties.enableDebugLog = false; - this.fileProperties.enableErrorLog = false; - this.fileProperties.enableFatalLog = false; - this.fileProperties.generateHTMLLog = false; - this.fileProperties.compressLogFilesAfterNewExecution = false; + + if (text.cause) { + const causedBy = { + content: '# Caused by:', + styling: [EStyles.specialSubLine], + stylingParams: [''], + subLine: true, + }; + + if (this.defaultSettings.causedByBackgroundColor) { + causedBy.styling.push(EStyles.backgroundColor); + causedBy.stylingParams.push(this.defaultSettings.causedByBackgroundColor); + } + if (this.defaultSettings.causedByTextColor) { + causedBy.styling.push(EStyles.textColor); + causedBy.stylingParams.push(this.defaultSettings.causedByTextColor); + } + + finalMessage.push(causedBy); + + if (typeof text.cause === 'string' || Array.isArray(text.cause) || text.cause instanceof Error) { + finalMessage.push(...this.processMessage(text.cause, true, ...args)); + } else { + finalMessage.push({ + content: this.redactText(JSON.stringify(text.cause)), + styling: [], + stylingParams: [], + subLine: true, + }); + } + } + return finalMessage; + } else if (!Array.isArray(text) || (Array.isArray(text) && (!args || args.length === 0))) { + return [{ + content: this.redactText(utils.format(text, ...args)), + styling: [EStyles.specialSubLine, EStyles.reset], + stylingParams: ['', ''], + subLine: true, + }]; } - } - private closeFileStreams(closeStreamMessage?: string, customFatalMessage?: string): void { - this.writeToAllStreams(closeStreamMessage ?? '', customFatalMessage); - this.latestFileStream?.end(); - this.debugLogStream?.end(); - this.errorLogStream?.end(); - } + const finalMessage: (IMessageChunk & {subLine: boolean})[] = []; + + let switchedToSublines = forceSubline; + text.forEach((line, index) => { + const variable = args[index]; + if (line) { + finalMessage.push({ + content: this.redactText(line.toString()), + styling: [EStyles.specialSubLine], + stylingParams: [''], + subLine: switchedToSublines, + }); + } + if (variable) { + const chunks = this.processMessage(variable, switchedToSublines); + chunks[0].styling.push(...this.defaultSettings.variableStyling); + chunks[0].stylingParams.push(...this.defaultSettings.variableStylingParams); + if (!forceSubline && chunks.find((sublineFinder) => sublineFinder.subLine)) switchedToSublines = true; + finalMessage.push(...chunks); + } + }); - private writeToAllStreams(message: string, customFatalLog?: string): void { - if (this.fileProperties.enableLatestLog) this.latestFileStream?.write(message); - if (this.fileProperties.enableDebugLog) this.debugLogStream?.write(message); - if (this.fileProperties.enableErrorLog) this.errorLogStream?.write(message); - if (this.fileProperties.enableFatalLog && customFatalLog) { - // create a new stream for fatal log - // 4 random alphanumeric characters - const uniqueId = Math.random().toString(36).substring(2, 6); - const fatalLogStream = fs.createWriteStream( - Path.join(this.fileProperties.logFolderPath, 'fatal-crash', `fatal-${uniqueId}-${this.getTime(true, true)}.${this.fileProperties.generateHTMLLog ? 'html' : 'log'}`), - ); - fatalLogStream.write(this.defaultHeader); - fatalLogStream.end(customFatalLog); - } + return finalMessage; } - private compressLastSessionLogs(): void { - if (!this.fileProperties.compressLogFilesAfterNewExecution) return; - - const zip = new admZip(); - - var files = fs.readdirSync(this.fileProperties.logFolderPath); - // const fatalCrashFiles = fs.readdirSync(Path.join(this.fileProperties.logFolderPath, 'fatal-crash')); - const latestLogsFiles = fs.readdirSync(Path.join(this.fileProperties.logFolderPath, 'latestLogs')); - // files = files.concat(fatalCrashFiles.map((file) => Path.join('fatal-crash', file))); - files = files.concat(latestLogsFiles.map((file) => Path.join('latestLogs', file))); - // use fs.stat on latest.log/html to get its last modified date - const latestLogPath = Path.join(this.fileProperties.logFolderPath, `latest.${this.fileProperties.generateHTMLLog ? 'html' : 'log'}`); - const latestLogStats = fs.statSync(latestLogPath); - // get mtime and replace : with - to avoid windows file system errors - const latestLogDate = latestLogStats.mtime.toISOString().replace(/:/g, '-').split('.')[0]; - files.forEach((file) => { - if (file.endsWith('.log') || file.endsWith('.html')) { - zip.addLocalFile(Path.join(this.fileProperties.logFolderPath, file)); - // don't delete fatal-crash logs - if (!file.startsWith('fatal')) fs.unlinkSync(Path.join(this.fileProperties.logFolderPath, file)); + private handleMessage(text: string | string[] | Error, level: ELoggerLevel, ...args: any[]): void { + const chunks = this.processMessage(text, false, ...args); + const messageChunks: IMessageChunk[] = []; + const subLines: IMessageChunk[] = []; + + chunks.forEach((chunk) => { + if (chunk.subLine) subLines.push(chunk); + else { + if (level === ELoggerLevel.FATAL) { + chunk.styling.unshift(EStyles.textColor, EStyles.backgroundColor); + chunk.stylingParams.unshift(this.defaultSettings.logLevelAccentColors[level], this.defaultSettings.logLevelMainColors[level]); + } + if (this.allLineColored) { + const txtColor = this.coloredBackground ? this.defaultSettings.logLevelAccentColors[level] : this.defaultSettings.logLevelMainColors[level]; + const bgColor = this.coloredBackground ? this.defaultSettings.logLevelMainColors[level] : this.defaultSettings.logLevelAccentColors[level]; + if (txtColor) { + chunk.styling.unshift(EStyles.textColor); + chunk.stylingParams.unshift(txtColor); + } + if (bgColor) { + chunk.styling.unshift(EStyles.backgroundColor); + chunk.stylingParams.unshift(bgColor); + } + } + messageChunks.push(chunk); } }); - const uniqueId = Math.random().toString(36).substring(2, 6); - fs.writeFileSync(Path.resolve(this.fileProperties.logFolderPath, `logs-${uniqueId}-${latestLogDate}.zip`), zip.toBuffer()); - } - private getFormattedPrefix(): string { - var prefix = ''; - prefix += chalk.hex('#5c5c5c')('['); - prefix += chalk.gray(this.prefix); - prefix += chalk.hex('#5c5c5c')(']'); + const message: ILogMessage = { + messageChunks, + subLines, + prefixes: this.prefixes, + timestamp: new Date(), + logLevel: level, + settings: { + coloredBackground: this.coloredBackground, + default: this.defaultSettings, + }, + }; - return this.prefix !== '' ? prefix : ''; + this.logListeners.forEach((logListener) => { + logListener.log(message); + }); } - private getTime(fullDate?: boolean, friendlySymbols?: boolean): string { - const time = new Date(Date.now()); - const day = time.getDate() < 10 ? '0' + time.getDate() : time.getDate(); - const month = time.getMonth() < 10 ? '0' + time.getMonth() : time.getMonth(); - const year = time.getFullYear(); - const seconds = time.getSeconds() < 10 ? '0' + time.getSeconds() : time.getSeconds(); - const minutes = time.getMinutes() < 10 ? '0' + time.getMinutes() : time.getMinutes(); - const hours = time.getHours() < 10 ? '0' + time.getHours() : time.getHours(); - - // eslint-disable-next-line max-len - return `${friendlySymbols ? '' : '['}${fullDate ? day : ''}${fullDate ? (friendlySymbols ? '-' : ':') : ''}${fullDate ? month : ''}${fullDate ? (friendlySymbols ? '-' : ':') : ''}${fullDate ? year : ''}${fullDate ? (friendlySymbols ? 'T' : '-') : ''}${hours}${friendlySymbols ? '-' : ':'}${minutes}${friendlySymbols ? '-' : ':'}${seconds}${friendlySymbols ? '' : ']'}`; + log(text: string | string[], ...args: any[]): void { + this.handleMessage(text, this.defaultLevel, ...args); } - private generateMessagePrefix(level: ELoggerLevel): { coloredMessagePrefix: string; rawMessagePrefix: string, textColor: string } { - const fgColor = [ELoggerLevelBaseColors[level], ELoggerLevelAlternateColors[level]]; - var time = chalk.hex(fgColor[Number(this.coloredBackground)])(this.getTime() + ' '); - var prefix = chalk.hex(fgColor[Number(this.coloredBackground)])(this.getFormattedPrefix() + ' '); - var levelText = chalk.hex(fgColor[Number(this.coloredBackground)])(ELoggerLevelNames[level].toUpperCase() + ':'); - - if (this.coloredBackground) { - time = chalk.bgHex(ELoggerLevelBaseColors[level])(time); - prefix = chalk.bgHex(ELoggerLevelBaseColors[level])(prefix); - levelText = chalk.bgHex(ELoggerLevelBaseColors[level])(levelText); - } - - return { - coloredMessagePrefix: `${time}${prefix}${levelText}`, - rawMessagePrefix: `${this.getTime()} [${this.prefix}] ${ELoggerLevelNames[level].toUpperCase()}:`, - textColor: fgColor[Number(this.coloredBackground)], - }; + info(text: string | string[], ...args: any[]): void { + this.handleMessage(text, ELoggerLevel.INFO, ...args); } - log(text: any, levelToLog?: ELoggerLevel, ...args: any): void { - const level = levelToLog ?? this.defaultLevel; - if (text instanceof Error) { - text = text.toString(); - } - text = utils.format(text, ...args); - if (level === ELoggerLevel.FATAL) return this.fatal(text, ...args); - const consoleLevels = { - [ELoggerLevel.INFO]: console.log, - [ELoggerLevel.WARN]: console.warn, - [ELoggerLevel.ERROR]: console.error, - [ELoggerLevel.DEBUG]: console.debug, - }; - - const { coloredMessagePrefix, rawMessagePrefix, textColor } = this.generateMessagePrefix(level); - - const messageToConsole = (this.coloredBackground && this.allLineColored) - ? chalk.bgHex(ELoggerLevelBaseColors[level])(chalk.hex(ELoggerLevelAlternateColors[level])(' ' + text)) - : (this.allLineColored ? chalk.hex(ELoggerLevelBaseColors[level])(' ' + text) : ' ' + text) - ; - - if ((this.debugActive && level === ELoggerLevel.DEBUG) || (level !== ELoggerLevel.DEBUG)) { - consoleLevels[level](coloredMessagePrefix + messageToConsole); - } - - // escapes the text to a be secure to be used in html - const escapedText = escape(text.toString()); - - // eslint-disable-next-line max-len - const textSpanElement = this.allLineColored ? `${escapedText}` : `${escapedText}`; - // eslint-disable-next-line max-len - const parentSpanElement = `${rawMessagePrefix} ${textSpanElement}\n`; - - if (this.fileProperties.enableDebugLog) { - this.debugLogStream?.write(this.fileProperties.generateHTMLLog ? parentSpanElement : (rawMessagePrefix + ' ' + text + '\n')); - } - if (this.fileProperties.enableErrorLog && level === ELoggerLevel.ERROR) { - // eslint-disable-next-line max-len - this.errorLogStream?.write(this.fileProperties.generateHTMLLog ? parentSpanElement : (rawMessagePrefix + ' ' + text + '\n')); - } - if (this.fileProperties.enableLatestLog && level !== ELoggerLevel.DEBUG) { - this.latestFileStream?.write(this.fileProperties.generateHTMLLog ? parentSpanElement : (rawMessagePrefix + ' ' + text + '\n')); - } + warn(text: string | string[], ...args: any[]): void { + this.handleMessage(text, ELoggerLevel.WARN, ...args); } - info(text: any, ...args: any): void { - this.log(text, ELoggerLevel.INFO, ...args); + error(text: string | string[] | Error, ...args: any[]): void { + this.handleMessage(text, ELoggerLevel.ERROR, ...args); } - warn(text: any, ...args: any): void { - this.log(text, ELoggerLevel.WARN, ...args); + debug(text: string | string[], ...args: any[]): void { + this.handleMessage(text, ELoggerLevel.DEBUG, ...args); } - error(text: any, ...args: any): void { - this.log(text, ELoggerLevel.ERROR, ...args); + fatal(text: string | string[] | Error, ...args: any[]): void { + this.handleMessage(text, ELoggerLevel.FATAL, ...args); } - debug(text: any, ...args: any): void { - this.log(text, ELoggerLevel.DEBUG, ...args); + alert(text: string | string[], ...args: any[]): void { + this.handleMessage(text, ELoggerLevel.ALERT, ...args); } - fatal(text: any, ...args: any): void { - var message = text.toString(); - var stack: string[] | undefined = []; - var fullString = text.toString(); - if (text instanceof Error) { - stack = text.stack?.split('\n'); - if (stack) { - fullString = stack.join('\n'); - message = stack.shift() ?? ''; - } - } - - message = utils.format(message, ...args); - - const time = this.getTime(); - const prefix = this.getFormattedPrefix(); - const levelMsg = text.toString().startsWith('Error') ? ELoggerLevelNames[3] : `${ELoggerLevelNames[3]} ${ELoggerLevelNames[2]}:`; - - message = `${time} ${prefix} ${levelMsg} ${message.toString()}${stack ? '\n' + stack.join('\n') : ''}`; - - const msg = chalk.bgWhite(chalk.redBright(message)); - - var escapedFullText = escape(fullString); - const escapedText = escape(text.toString()); - - // convert tabs to html - escapedFullText = escapedFullText.replace(/\t/g, '    '); - escapedFullText = escapedFullText.replace(/ /g, ' '); - - const splitFullEscapedText = escapedFullText.split('\n'); - const htmlFullText = '' + splitFullEscapedText.join('') + ''; - - const textSpan = `${escapedText}`; - const fullSpan = `${htmlFullText}`; - // eslint-disable-next-line max-len - const prefixSpan = `${time} [${this.prefix}] ${levelMsg} ${textSpan}\n`; - // eslint-disable-next-line max-len - const fullPrefixSpan = `${time} [${this.prefix}] ${levelMsg} ${fullSpan}\n`; + severe(text: string | string[] | Error, ...args: any[]): void { + this.handleMessage(text, ELoggerLevel.SEVERE, ...args); + } - // eslint-disable-next-line max-len - const finalMessage = (this.fileProperties.generateHTMLLog ? prefixSpan : (time + ' [' + this.prefix + '] ' + levelMsg + ' ' + text + '\n')) + 'Please check the fatal log file for more details.\n'; - const finalFatalMessage = this.fileProperties.generateHTMLLog ? fullPrefixSpan : (time + ' [' + this.prefix + '] ' + levelMsg + ' ' + fullString + '\n'); + /** + * Allows the assignment of a listener callback that will be called every log made + * @param listenerCallback void function with the actions to be executed every log. Receives ILogMessage object. + */ + registerListener(listenerEngine: Engine): void { + this.logListeners.push(listenerEngine); + } - if (this.disableFatalCrash) { - this.writeToAllStreams(finalMessage, finalFatalMessage); - } else { - this.closeFileStreams(finalMessage, finalFatalMessage); - } + unRegisterListener(listenerEngine: Engine): void { + this.logListeners = this.logListeners.filter((listener) => listener !== listenerEngine); + } - console.error(msg); + setColoredBackground(coloredBackground: boolean): void { + this.coloredBackground = coloredBackground; + } - if (!this.disableFatalCrash) { - process.exit(5); - } + setAllLineColored(allLineColored: boolean): void { + this.allLineColored = allLineColored; } } diff --git a/src/main/outputEngines/consoleEngine.ts b/src/main/outputEngines/consoleEngine.ts new file mode 100755 index 0000000..983368e --- /dev/null +++ b/src/main/outputEngines/consoleEngine.ts @@ -0,0 +1,192 @@ +import { ELoggerLevel, ELoggerLevelNames, EStyles, ILogMessage, IMessageChunk, IPrefix } from '../interfaces'; +import { Engine } from './'; +import chalk from 'chalk'; + +export class ConsoleEngine extends Engine { + private prefixes = new Map(); + + private consoleLoggers = { + [ELoggerLevel.INFO]: console.info, + [ELoggerLevel.WARN]: console.warn, + [ELoggerLevel.ERROR]: console.error, + [ELoggerLevel.FATAL]: console.error, + [ELoggerLevel.DEBUG]: console.debug, + }; + + private parseTextStyles(chunk: IMessageChunk, subLine?: boolean, backgroundColor?: string, customFGColor?: string): string { + let finalMsg = subLine ? (backgroundColor ? chalk.bgHex(backgroundColor).gray : chalk.gray) : chalk.reset; + let special = false; + chunk.styling.forEach((style, index) => { + switch (style) { + case EStyles.bold: + finalMsg = finalMsg.bold; + break; + case EStyles.italic: + finalMsg = finalMsg.italic; + break; + case EStyles.backgroundColor: + finalMsg = finalMsg.bgHex(chunk.stylingParams[index]); + break; + case EStyles.textColor: + finalMsg = finalMsg.hex(chunk.stylingParams[index]); + break; + case EStyles.specialSubLine: + special = true; + break; + case EStyles.reset: + finalMsg = finalMsg.reset; + break; + default: + break; + } + }); + let finalMessage = ''; + const fullLineTxt = chunk.content.padEnd(process.stdout.columns - (subLine && !special ? 3 : 0)); + if (subLine && !special) { + finalMessage += (customFGColor ? (backgroundColor ? chalk.bgHex(backgroundColor) : chalk).hex(customFGColor)('| ') : finalMsg('| ')); + finalMessage += (customFGColor ? finalMsg.hex(customFGColor)(fullLineTxt) : finalMsg(fullLineTxt)); + } else if (subLine && special) { + finalMessage += finalMsg(fullLineTxt); + } else { + finalMessage += (customFGColor ? chalk.hex(customFGColor)(finalMsg(chunk.content)) : finalMsg(chunk.content)); + } + return finalMessage; + } + + private parsePrefix(prefixes: IPrefix[], defaultBg?: string): (string | undefined)[] { + return prefixes.map((prefix) => { + if (this.prefixes.has(prefix.content)) return this.prefixes.get(prefix.content); + + let bgColor = ''; + let bgColorArray: string[] = []; + if (prefix.backgroundColor && !Array.isArray(prefix.backgroundColor)) { + if (typeof prefix.backgroundColor === 'function') { + const result = prefix.backgroundColor(prefix.content); + if (!Array.isArray(result)) bgColor = result; + else bgColorArray = result; + } else { + bgColor = prefix.backgroundColor; + } + } else if (prefix.backgroundColor && Array.isArray(prefix.backgroundColor)) { + bgColorArray = prefix.backgroundColor; + } + + let fgColor = ''; + let fgArray: string[] = []; + if (!Array.isArray(prefix.color)) { + if (typeof prefix.color === 'function') { + const result = prefix.color(prefix.content); + if (!Array.isArray(result)) fgColor = result; + else fgArray = result; + } else { + fgColor = prefix.color; + } + } else { + fgArray = prefix.color; + } + + // static colors + if (bgColor && fgColor) { + const result = chalk.bgHex(bgColor).hex(fgColor)(prefix.content); + this.prefixes.set(prefix.content, result); + return result; + } + if (!bgColor && bgColorArray.length <= 0 && fgColor) { + const result = (defaultBg ? chalk.bgHex(defaultBg) : chalk).hex(fgColor)(prefix.content); + this.prefixes.set(prefix.content, result); + return result; + } + + // Gradients + let finalMsg = ''; + + // repeat the last color so that fgArray size matches prefix.content size + if (fgArray.length > 0 && fgArray.length < prefix.content.length) fgArray.push(...Array(prefix.content.length - fgArray.length).fill(fgArray[0])); + + // Has background color gradient + if (bgColorArray.length > 0) { + // repeat the last color so that bgColorArray size matches prefix.content size + if (bgColorArray.length < prefix.content.length) bgColorArray.push(...Array(prefix.content.length - bgColorArray.length).fill(bgColorArray[0])); + bgColorArray.forEach((color, index) => { + if (fgArray.length > 0) finalMsg += chalk.bgHex(color).hex(fgArray[index])(prefix.content[index]); + else finalMsg += chalk.bgHex(color).hex(fgColor)(prefix.content[index]); + }); + + // Doesn't have background color or it is a static color + } else { + fgArray.forEach((color, index) => { + if (bgColor) finalMsg += chalk.bgHex(bgColor).hex(color)(prefix.content[index]); + else finalMsg += (defaultBg ? chalk.bgHex(defaultBg) : chalk).hex(color)(prefix.content[index]); + }); + } + this.prefixes.set(prefix.content, finalMsg); + return finalMsg; + }); + } + + log(message: ILogMessage): void { + if (!this.debug && message.logLevel === ELoggerLevel.DEBUG) return; + + const defaultSettings = message.settings.default; + const shouldColorBg = message.settings.coloredBackground || message.logLevel === ELoggerLevel.FATAL; + + if (shouldColorBg) this.prefixes.clear(); + + let formatter: chalk.Chalk = chalk.reset; + if (shouldColorBg) formatter = formatter.bgHex(defaultSettings.logLevelMainColors[message.logLevel]); + + if (shouldColorBg && defaultSettings.logLevelAccentColors[message.logLevel]) formatter = formatter.hex(defaultSettings.logLevelAccentColors[message.logLevel]); + + if (!message.settings.coloredBackground && message.logLevel !== ELoggerLevel.FATAL) formatter = formatter.hex(defaultSettings.logLevelMainColors[message.logLevel]); + const timestamp = formatter(this.getTime(message.timestamp)); + + const prefixes = this.parsePrefix(message.prefixes, shouldColorBg ? defaultSettings.logLevelMainColors[message.logLevel] : undefined); + + if (message.logLevel === ELoggerLevel.FATAL) this.prefixes.clear(); + + let prefixTxt = ''; + prefixes.forEach((prefix) => { + prefixTxt += formatter(' ['); + prefixTxt += prefix; + prefixTxt += formatter(']'); + }); + const level = formatter(` ${ELoggerLevelNames[message.logLevel]}:`); + + // adds a space before the first chunk to separate the message from the : in the log without coloring the background if allLineColored is false + const firstChunk = message.messageChunks[0]; + message.messageChunks.unshift({ + content: ' ', + styling: firstChunk.styling, + stylingParams: firstChunk.stylingParams, + subLine: false, + }); + + const txt = message.messageChunks.map((chunk): string => this.parseTextStyles(chunk, false, shouldColorBg ? defaultSettings.logLevelMainColors[message.logLevel] : undefined)); + + this.consoleLoggers[message.logLevel](`${timestamp}${prefixTxt}${level}${txt.join('')}`); + + if (!message.subLines || message.subLines.length <= 0) return; + + message.subLines.forEach((line) => + this.consoleLoggers[message.logLevel](this.parseTextStyles( + line, + true, + shouldColorBg ? defaultSettings.logLevelMainColors[message.logLevel] : undefined, + shouldColorBg ? defaultSettings.logLevelAccentColors[message.logLevel] : undefined, + )), + ); + + this.consoleLoggers[message.logLevel]( + this.parseTextStyles( + { + content: '#'.padEnd(process.stdout.columns, '-'), + styling: [EStyles.specialSubLine, EStyles.textColor], + stylingParams: ['', defaultSettings.logLevelAccentColors[message.logLevel] || '#ffffff'], + subLine: true, + }, + true, + shouldColorBg ? defaultSettings.logLevelMainColors[message.logLevel] : undefined, + ), + ); + } +} diff --git a/src/main/outputEngines/engine.ts b/src/main/outputEngines/engine.ts new file mode 100755 index 0000000..351a258 --- /dev/null +++ b/src/main/outputEngines/engine.ts @@ -0,0 +1,42 @@ +import { ILogMessage, IEngineSettings } from '../interfaces'; +import { Logger } from '../logger'; + +export abstract class Engine { + debug: boolean; + private loggers: Logger[] = []; + + constructor(settings?: IEngineSettings, ...loggers: Logger[]) { + if (Array.isArray(settings)) { + loggers = settings; + settings = undefined; + } + + this.debug = settings?.debug || false; + this.loggers = loggers; + + this.loggers.forEach((logger) => { + logger.registerListener(this); + }); + } + + destroy(): void { + this.loggers.forEach((logger) => { + logger.unRegisterListener(this); + }); + } + + getTime(time: Date, fullDate?: boolean): string { + const day = `0${time.getDate()}`.slice(-2); + const month = `0${time.getMonth()}`.slice(-2); + const year = `0${time.getFullYear()}`.slice(-2); + const seconds = `0${time.getSeconds()}`.slice(-2); + const minutes = `0${time.getMinutes()}`.slice(-2); + const hours = `0${time.getHours()}`.slice(-2); + + return `[${fullDate ? `${day}:${month}:${year}-` : ''}${hours}:${minutes}:${seconds}]`; + } + + log(message: ILogMessage): void { + throw new Error('Method not implemented.', { cause: message }); + } +} diff --git a/src/main/outputEngines/fileStorageEngine.ts b/src/main/outputEngines/fileStorageEngine.ts new file mode 100755 index 0000000..c38f977 --- /dev/null +++ b/src/main/outputEngines/fileStorageEngine.ts @@ -0,0 +1,60 @@ +import { ELoggerLevel, ELoggerLevelNames, EStyles, IFileStorageSettings, ILogMessage, IMessageChunk } from '../interfaces'; +import { Logger } from '../logger'; +import { Engine } from './'; + +export default class FileStorage extends Engine { + constructor(settings?: IFileStorageSettings, ...loggers: Logger[]) { + super(settings, ...loggers); + let a; + } + + private parseTextStyles(chunk: IMessageChunk, subLine?: boolean): string { + let special = false; + chunk.styling.forEach((style) => { + switch (style) { + case EStyles.specialSubLine: + special = true; + break; + default: + break; + } + }); + return (subLine && !special ? '| ' : '') + chunk.content; + } + + log(message: ILogMessage): void { + if (!this.debug && message.logLevel === ELoggerLevel.DEBUG) return; + + const defaultSettings = message.settings.default; + + const timestamp = this.getTime(message.timestamp); + + const prefixes = message.prefixes; + + const prefixTxt = prefixes.map((prefix) => ` [${prefix}]`); + const level = ` ${ELoggerLevelNames[message.logLevel]}: `; + + const txt = message.messageChunks.map((chunk): string => this.parseTextStyles(chunk, false)); + + // this.consoleLoggers[message.logLevel](`${timestamp}${prefixTxt}${level}${txt.join('')}`); + + if (!message.subLines || message.subLines.length <= 0) return; + + let biggestLine = 0; + message.subLines.forEach((line) => { + if (line.content.length > biggestLine) biggestLine = line.content.length; + // this.consoleLoggers[message.logLevel](this.parseTextStyles(line, true)); + }); + + this.consoleLoggers[message.logLevel]( + this.parseTextStyles({ + content: '#'.padEnd(biggestLine, '-'), + styling: [EStyles.specialSubLine], + stylingParams: [''], + subLine: true, + }, + true, + ), + ); + } +} diff --git a/src/main/outputEngines/index.ts b/src/main/outputEngines/index.ts new file mode 100755 index 0000000..cf38c86 --- /dev/null +++ b/src/main/outputEngines/index.ts @@ -0,0 +1,3 @@ +export * from './engine'; +export * from './consoleEngine'; +export * from './fileStorageEngine'; From 41cf13f95019cce22078a0ed4567a924e677e27d Mon Sep 17 00:00:00 2001 From: Space_Fox <44732812+emanuelfranklyn@users.noreply.github.com> Date: Mon, 10 Jun 2024 17:13:40 -0300 Subject: [PATCH 02/10] (feat): FileSystemEngine, AutoLogEnd Also changes ConsoleEngine styling --- package-lock.json | 26 +- package.json | 4 +- src/main/autoLogEnd.ts | 159 +++++++---- src/main/defaults/standard.ts | 9 +- src/main/index.ts | 3 +- src/main/interfaces/IDefault.ts | 9 +- src/main/interfaces/IFileStorageSettings.ts | 1 - src/main/interfaces/ILogMessage.ts | 1 + src/main/logger.ts | 288 ++++++++++++++++---- src/main/outputEngines/consoleEngine.ts | 126 +++++---- src/main/outputEngines/engine.ts | 32 ++- src/main/outputEngines/fileStorageEngine.ts | 279 ++++++++++++++++--- src/tests/tester.js | 124 +++++++-- 13 files changed, 802 insertions(+), 259 deletions(-) mode change 100644 => 100755 package-lock.json mode change 100644 => 100755 package.json mode change 100644 => 100755 src/main/index.ts mode change 100644 => 100755 src/main/interfaces/ILogMessage.ts mode change 100644 => 100755 src/tests/tester.js diff --git a/package-lock.json b/package-lock.json old mode 100644 new mode 100755 index 78dda03..71abc26 --- a/package-lock.json +++ b/package-lock.json @@ -10,12 +10,10 @@ "license": "MIT", "dependencies": { "adm-zip": "^0.5.10", - "chalk": "^4.1.2", - "escape-html": "^1.0.3" + "chalk": "^4.1.2" }, "devDependencies": { "@types/adm-zip": "^0.5.0", - "@types/escape-html": "^1.0.2", "@types/node": "^18.15.3", "@typescript-eslint/eslint-plugin": "^5.48.2", "@typescript-eslint/parser": "^5.48.2", @@ -163,12 +161,6 @@ "@types/node": "*" } }, - "node_modules/@types/escape-html": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/escape-html/-/escape-html-1.0.2.tgz", - "integrity": "sha512-gaBLT8pdcexFztLSPRtriHeXY/Kn4907uOCZ4Q3lncFBkheAWOuNt53ypsF8szgxbEJ513UeBzcf4utN0EzEwA==", - "dev": true - }, "node_modules/@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", @@ -806,11 +798,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -3018,12 +3005,6 @@ "@types/node": "*" } }, - "@types/escape-html": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/escape-html/-/escape-html-1.0.2.tgz", - "integrity": "sha512-gaBLT8pdcexFztLSPRtriHeXY/Kn4907uOCZ4Q3lncFBkheAWOuNt53ypsF8szgxbEJ513UeBzcf4utN0EzEwA==", - "dev": true - }, "@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", @@ -3462,11 +3443,6 @@ "is-symbol": "^1.0.2" } }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", diff --git a/package.json b/package.json old mode 100644 new mode 100755 index 64a57d3..591ac8d --- a/package.json +++ b/package.json @@ -26,12 +26,10 @@ "homepage": "https://github.com/PromisePending/logger.js#readme", "dependencies": { "adm-zip": "^0.5.10", - "chalk": "^4.1.2", - "escape-html": "^1.0.3" + "chalk": "^4.1.2" }, "devDependencies": { "@types/adm-zip": "^0.5.0", - "@types/escape-html": "^1.0.2", "@types/node": "^18.15.3", "@typescript-eslint/eslint-plugin": "^5.48.2", "@typescript-eslint/parser": "^5.48.2", diff --git a/src/main/autoLogEnd.ts b/src/main/autoLogEnd.ts index dcd4943..f1c32b5 100755 --- a/src/main/autoLogEnd.ts +++ b/src/main/autoLogEnd.ts @@ -1,60 +1,113 @@ import { Logger } from './logger'; -import util from 'util'; - -var exited = false; -var logger: Logger | null = null; - -function exitHandler({ err, options, exitCode }: {err?: {stack: any, message: any, name: any}, options?: {uncaughtException: boolean}, exitCode?: number | string}): void { - if (!exited) { - process.stdin.resume(); - exited = true; - if (typeof exitCode === 'string') { - logger?.warn('Manually Finished!'); - } else { - if (exitCode !== 123654) logger?.info('Program finished, code: ' + exitCode); - if (exitCode === 123654 && options?.uncaughtException) { - logger?.fatal(util.format(typeof err === 'string' ? err : err?.stack)); - exitCode = 1; - } else if (exitCode && exitCode === 123654) { - logger?.error(util.format(typeof err === 'string' ? err : err?.stack)); - logger?.warn('#===========================================================#'); - logger?.warn('| # AutoLogEnd prevent program exit!'); - logger?.warn('| # Code that is not async or would be runned after the line that generated the error cannot run as per nodejs default behavior.'); - logger?.warn('| # But promises, async code and event based functions will still be executed.'); - logger?.warn('| # In order to prevent sync code to stop, use an try-catch or a promise.'); - logger?.warn('#===========================================================#'); - logger?.warn('If you want to manually exit, you can still use control-c in the process.'); - exited = false; - return; +import { ConsoleEngine } from './outputEngines'; + +/** + * Singleton class that handles the end of the program + */ +export class AutoLogEnd { + private active = false; + private exited = false; + private logger!: Logger; + // eslint-disable-next-line no-use-before-define + public static _instance?: AutoLogEnd; + private deconstructors: Map Promise> = new Map(); + + // callbacks + private exitCallback: (exitCode: number) => Promise = async (exitCode) => { await this.exitHandler({ exitCode }); }; + private sigintCallback: (error: Error) => Promise = async (error) => { await this.exitHandler({ err: error, exitCode: 'SIGINT' }); }; + private sigusr1Callback: (error: Error) => Promise = async (error) => { await this.exitHandler({ err: error, exitCode: 'SIGUSR1' }); }; + private sigusr2Callback: (error: Error) => Promise = async (error) => { await this.exitHandler({ err: error, exitCode: 1 }); }; + private sigtermCallback: (error: Error) => Promise = async (error) => { await this.exitHandler({ err: error, exitCode: 'SIGTERM' }); }; + private uncaughtExceptionCallback: (error: Error) => Promise = async (error: Error) => { await this.exitHandler({ err: error, exitCode: 123654 }); }; + private beforeExitCallback: (code: number) => Promise = async (code: number) => { await this.exitHandler({ exitCode: code }); }; + + /** + * @constructor + * @param logger (optional) custom logger to be used + * @returns new instance of AutoLogEnd or the existing one + */ + constructor(logger?: Logger) { + if (AutoLogEnd._instance) return AutoLogEnd._instance; + + if (logger) this.logger = logger; + else { + this.logger = new Logger({ prefixes: [{ content: 'SYSTEM', color: '#ffaa00', backgroundColor: null }] }); + this.logger.registerListener(new ConsoleEngine({ debug: true })); + } + + this.activate(); + + AutoLogEnd._instance = this; + } + + private async exitHandler({ err, exitCode }: {err?: Error | string, exitCode?: number | string}): Promise { + if (!this.exited) { + process.stdin.resume(); + this.exited = true; + if (typeof exitCode === 'string') this.logger.warn('Manually Finished!'); + else { + if (exitCode !== 123654 && exitCode !== 647412) this.logger.info('Program finished, code: ' + exitCode ?? '?'); + else if (exitCode && exitCode === 123654 && err) this.logger.error(err); } + const promises: Promise[] = []; + this.deconstructors.forEach((deconstructor) => promises.push(deconstructor())); + Promise.all(promises).then(() => { + process.exit(typeof exitCode === 'string' ? 0 : exitCode); + }); } - process.exit(typeof exitCode === 'string' ? 0 : exitCode); } -} -export function activate(uncaughtException?: boolean, logger?: Logger): void { - logger = logger ?? new Logger({ prefixes: ['SYSTEM'] }); - logger?.debug('AutoLogEnd activated!'); - process.on('exit', (exitCode) => exitHandler({ exitCode, options: { uncaughtException: false } })); - process.on('SIGINT', (error) => { exitHandler({ err: { message: error, name: null, stack: null }, options: { uncaughtException: false }, exitCode: 'SIGINT' }); }); - process.on('SIGUSR1', (error) => { exitHandler({ err: { message: error, name: null, stack: null }, options: { uncaughtException: false }, exitCode: 'SIGUSR1' }); }); - process.on('SIGUSR2', (error) => { exitHandler({ err: { message: error, name: null, stack: null }, options: { uncaughtException: false }, exitCode: 1 }); }); - process.on('SIGTERM', (error) => { exitHandler({ err: { message: error, name: null, stack: null }, options: { uncaughtException: false }, exitCode: 'SIGTERM' }); }); - process.on('uncaughtException', (error) => { - exitHandler({ - err: { message: error.message, name: error.name, stack: error.stack }, - options: { uncaughtException: uncaughtException ?? false }, - exitCode: 123654, - }); - }); -} + /** + * Adds a deconstructor function to be runned before the program exits + * NOTE: It is uncertain that node.js will execute desconstructor functions that are async. + * @param id Identifier for the deconstructor + * @param deconstructor Function to be runned before the program exits + */ + appendDeconstructor(id: string, deconstructor: () => Promise): void { + if (this.deconstructors.has(id)) this.logger.warn(`Deconstructor with id ${id} has overwritten!`); + this.deconstructors.set(id, deconstructor); + } + + /** + * Removes a deconstructor function + * @param id Identifier for the deconstructor + */ + removeDeconstructor(id: string): void { + if (!this.deconstructors.has(id)) return this.logger.warn(`Deconstructor with id ${id} not found!`); + this.deconstructors.delete(id); + } + + /** + * Activates the AutoLogEnd + * @returns void + **/ + activate(): void { + if (this.active) return; + process.on('exit', this.exitCallback); + process.on('SIGINT', this.sigintCallback); + process.on('SIGUSR1', this.sigusr1Callback); + process.on('SIGUSR2', this.sigusr2Callback); + process.on('SIGTERM', this.sigtermCallback); + process.on('uncaughtException', this.uncaughtExceptionCallback); + process.on('beforeExit', this.beforeExitCallback); + this.active = true; + this.logger.debug('AutoLogEnd activated!'); + } -export function deactivate(): void { - process.removeListener('exit', exitHandler); - process.removeListener('SIGINT', exitHandler); - process.removeListener('SIGUSR1', exitHandler); - process.removeListener('SIGUSR2', exitHandler); - process.removeListener('SIGTERM', exitHandler); - process.removeListener('uncaughtException', exitHandler); - logger?.debug('AutoLogEnd deactivated!'); + /** + * Deactivates the AutoLogEnd + * @returns void + **/ + deactivate(): void { + if (!this.activate) return; + process.removeListener('exit', this.exitCallback); + process.removeListener('SIGINT', this.sigintCallback); + process.removeListener('SIGUSR1', this.sigusr1Callback); + process.removeListener('SIGUSR2', this.sigusr2Callback); + process.removeListener('SIGTERM', this.sigtermCallback); + process.removeListener('uncaughtException', this.uncaughtExceptionCallback); + process.removeListener('beforeExit', this.beforeExitCallback); + this.active = false; + this.logger.debug('AutoLogEnd deactivated!'); + } } diff --git a/src/main/defaults/standard.ts b/src/main/defaults/standard.ts index 1133e86..d64d6c9 100755 --- a/src/main/defaults/standard.ts +++ b/src/main/defaults/standard.ts @@ -19,9 +19,16 @@ export default { prefixMainColor: '#777777', prefixAccentColor: '#000000', redactionText: '[REDACTED]', - undefinedColor: '#5555aa', causedByTextColor: '#ffffff', causedByBackgroundColor: '#ff0000', variableStyling: [EStyles.bold, EStyles.textColor], variableStylingParams: ['', '#55ff55'], + primitiveColors: { + string: '#ff5555', + number: '#55ff55', + boolean: '#5555ff', + null: '#555555', + undefined: '#005500', + circular: '#ff5555', + }, } as IDefault; diff --git a/src/main/index.ts b/src/main/index.ts old mode 100644 new mode 100755 index 69f8767..06624be --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1,3 +1,4 @@ -export * as autoLogEnd from './autoLogEnd'; +export * from './autoLogEnd'; export * from './interfaces'; export * from './logger'; +export * from './outputEngines'; diff --git a/src/main/interfaces/IDefault.ts b/src/main/interfaces/IDefault.ts index 5a1239c..4ca9c5a 100755 --- a/src/main/interfaces/IDefault.ts +++ b/src/main/interfaces/IDefault.ts @@ -10,9 +10,16 @@ export interface IDefault { prefixMainColor: string, prefixAccentColor: string, redactionText: string, - undefinedColor: string, causedByTextColor?: string, causedByBackgroundColor?: string, variableStyling: EStyles[], variableStylingParams: string[], + primitiveColors: { + string: string, + number: string, + boolean: string, + null: string, + undefined: string, + circular: string, + }, } diff --git a/src/main/interfaces/IFileStorageSettings.ts b/src/main/interfaces/IFileStorageSettings.ts index ebacf50..5c5dbcf 100755 --- a/src/main/interfaces/IFileStorageSettings.ts +++ b/src/main/interfaces/IFileStorageSettings.ts @@ -2,7 +2,6 @@ import { IEngineSettings } from './'; export interface IFileStorageSettings extends IEngineSettings { logFolderPath: string; - enableLatestLog?: boolean; enableDebugLog?: boolean; enableErrorLog?: boolean; enableFatalLog?: boolean; diff --git a/src/main/interfaces/ILogMessage.ts b/src/main/interfaces/ILogMessage.ts old mode 100644 new mode 100755 index 5c741de..e31230a --- a/src/main/interfaces/ILogMessage.ts +++ b/src/main/interfaces/ILogMessage.ts @@ -32,6 +32,7 @@ export interface IMessageChunk { styling: EStyles[]; stylingParams: string[]; subLine: boolean; + breaksLine: boolean; } export interface ILogMessage { diff --git a/src/main/logger.ts b/src/main/logger.ts index 8c2529c..2e15a63 100755 --- a/src/main/logger.ts +++ b/src/main/logger.ts @@ -5,6 +5,9 @@ import utils from 'util'; import { IDefault } from './interfaces/IDefault'; import Standard from './defaults/standard'; +/** + * Main class that will process logs before automaticly sending then to registered Engines + */ export class Logger { private defaultLevel: ELoggerLevel = ELoggerLevel.INFO; private prefixes: IPrefix[]; @@ -15,6 +18,25 @@ export class Logger { private allLineColored: boolean; private defaultSettings: IDefault; + /** + * @constructor + * @param param0 ILoggerOptions object: + * - prefixes: array of strings or IPrefix objects (can be empty list) + * - - IPrefix: object containing `content` field for the text of the prefix, a `color` field that can be a function that receives the text as input and returns a hex color string array for each letter, a array with hex codes for each letter, or a simple hex color string for the whole text, and a `backgroundColor` field that behaves like the color param + * - defaultLevel?: optional value from ELoggerLevel enum, determines what kind of log the .log method will execute (default: info) + * - disableFatalCrash?: optional value that when set true disables exiting the process when a fatal log happens (default: false) + * - redactedContent?: optional list of regex strings that when any match will replace the text with the redacted message + * - allLineColored?: optional boolean that sets if the content of the message should be colored the same as the log level color (default: false) + * - coloredBackground?: optional boolean that sets if the log level color will be applied to the background instead of the text (default: false) + * - defaultSettings?: optional IDefault object containing the colors and redacted text to be used, see /defaults/standard.ts file (default: /defaults/standard.ts file) + * @example + * const logger = new Logger({ + * prefix: ['example'], + * allLineColored: true, + * }); + * new ConsoleEngine(logger); + * logger.info('Hi!'); + */ constructor({ prefixes, defaultLevel, disableFatalCrash, redactedContent, allLineColored, coloredBackground, defaultSettings }: ILoggerOptions) { this.defaultLevel = defaultLevel ?? ELoggerLevel.INFO; this.disableFatalCrash = disableFatalCrash ?? false; @@ -55,6 +77,47 @@ export class Logger { return modifiedString; } + private colorPrimitiveValue(text: string): { text: string, colorStyles: EStyles[], colorStylesValues: string[] } { + let color = null; + if (!isNaN(Number(text))) color = this.defaultSettings.primitiveColors.number; + else if (text === 'null') color = this.defaultSettings.primitiveColors.null; + else if (text === 'undefined') color = this.defaultSettings.primitiveColors.undefined; + else if (text === 'true' || text === 'false') color = this.defaultSettings.primitiveColors.boolean; + else if ( + (text.startsWith('"') && text.endsWith('"')) || (text.startsWith('\'') && text.endsWith('\'')) || (text.startsWith('`') && text.endsWith('`')) + ) color = this.defaultSettings.primitiveColors.string; + else if (text.includes('Circular') || text.includes('ref')) color = this.defaultSettings.primitiveColors.circular; + else if (text.toLowerCase().includes('info')) color = this.defaultSettings.logLevelMainColors[ELoggerLevel.INFO]; + else if (text.toLowerCase().includes('warn')) color = this.defaultSettings.logLevelMainColors[ELoggerLevel.WARN]; + else if (text.toLowerCase().includes('error')) color = this.defaultSettings.logLevelMainColors[ELoggerLevel.ERROR]; + else if (text.toLowerCase().includes('debug')) color = this.defaultSettings.logLevelMainColors[ELoggerLevel.DEBUG]; + return { + text, + colorStyles: color ? [EStyles.textColor] : [], + colorStylesValues: color ? [color] : [], + }; + } + + private colorPrimitive(text: string): { text: string, colorStyles: EStyles[], colorStylesValues: string[] }[] { + // split text by certain characters + const splitCharsNonScape = [' ', ',', ':', '<', '>']; + const splitCharsScape = ['*', '(', ')', '[', ']']; + const result: { text: string, colorStyles: EStyles[], colorStylesValues: string[] }[] = []; + let elementGroupBuffer = ''; + text.split(RegExp(`(\\${splitCharsScape.join('|\\')}|${splitCharsNonScape.join('|')})`, 'gu')).forEach((element) => { + if ([...splitCharsNonScape, ...splitCharsScape].includes(element)) elementGroupBuffer += element; + else { + if (elementGroupBuffer !== '') { + result.push({ text: elementGroupBuffer, colorStyles: [], colorStylesValues: [] }); + elementGroupBuffer = ''; + } + const { text: coloredText, colorStyles, colorStylesValues } = this.colorPrimitiveValue(element); + result.push({ text: coloredText, colorStyles, colorStylesValues }); + } + }); + return result; + } + /** * Parses the message and returns an array of IMessageChunk objects * the first IMessageChunk object is the main message, the rest are subLines @@ -62,55 +125,71 @@ export class Logger { * @param args - The arguments to be passed to the content * @returns IMessageChunk[] */ - private processMessage(text: string | string[] | Error, forceSubline: boolean, ...args: any[]): IMessageChunk[] { - if (!text) { - return [{ - content: 'undefined', - styling: [EStyles.textColor], - stylingParams: [this.defaultSettings.undefinedColor], - subLine: forceSubline, - }]; - } + private processMessage(text: any, forceSubline: boolean, ...args: any[]): IMessageChunk[] { + if (!text) text = 'undefined'; // String handling if (typeof text !== 'object') { - return [...text.toString().split('\n').map((line) => { - return { - content: this.redactText(utils.format(line, ...args)), - styling: [], - stylingParams: [], - subLine: forceSubline, - }; - })]; + const texts: string[] = []; + const otherKinds: any[] = []; + args.map((arg) => typeof arg === 'string' ? texts.push(arg) : otherKinds.push(arg)); + const processedOtherKinds: IMessageChunk[] = []; + otherKinds.map((otherElement) => this.processMessage(otherElement, true)).forEach((otherPElement) => { + otherPElement.map((chunk) => processedOtherKinds.push(chunk)); + }); + const processedTexts: IMessageChunk[] = []; + (text.toString() as string).split('\n').forEach((line: string, index: number) => { + if (!Array.isArray(args)) args = [args]; + const processedColors = this.colorPrimitive(utils.format(line, ...texts)); + processedColors.forEach((color, colorIndex) => { + processedTexts.push({ + content: this.redactText(color.text), + styling: color.colorStyles, + stylingParams: color.colorStylesValues, + subLine: index === 0 ? forceSubline : true, + breaksLine: (index === 0 ? forceSubline : true) && colorIndex === 0, + }); + }); + }); + return [...processedTexts, ...processedOtherKinds]; // Error handling } else if (text instanceof Error) { - const finalMessage = []; - finalMessage.push({ - content: (forceSubline ? 'Error: ' : '') + this.redactText(utils.format(text.message, ...args)), - styling: [], - stylingParams: [], - subLine: forceSubline, + const finalMessage: IMessageChunk[] = []; + const processedColors = this.colorPrimitive(utils.format((forceSubline ? 'Error: ' : '') + text.message.trim(), ...args)); + processedColors.forEach((color, colorIndex) => { + finalMessage.push({ + content: this.redactText(color.text), + styling: color.colorStyles, + stylingParams: color.colorStylesValues, + subLine: forceSubline, + breaksLine: colorIndex === 0 && forceSubline, + }); }); const stack = text.stack?.split('\n'); stack?.shift(); stack?.forEach((line) => { - finalMessage.push({ - content: this.redactText(line.trim()), - styling: [], - stylingParams: [], - subLine: true, + const processedColors = this.colorPrimitive(utils.format(line.trim())); + processedColors.forEach((color, colorIndex) => { + finalMessage.push({ + content: this.redactText(color.text), + styling: color.colorStyles, + stylingParams: color.colorStylesValues, + subLine: true, + breaksLine: colorIndex === 0, + }); }); }); if (text.cause) { - const causedBy = { + const causedBy: IMessageChunk = { content: '# Caused by:', styling: [EStyles.specialSubLine], stylingParams: [''], subLine: true, + breaksLine: true, }; if (this.defaultSettings.causedByBackgroundColor) { @@ -123,26 +202,17 @@ export class Logger { } finalMessage.push(causedBy); - - if (typeof text.cause === 'string' || Array.isArray(text.cause) || text.cause instanceof Error) { - finalMessage.push(...this.processMessage(text.cause, true, ...args)); - } else { - finalMessage.push({ - content: this.redactText(JSON.stringify(text.cause)), - styling: [], - stylingParams: [], - subLine: true, - }); - } + finalMessage.push(...this.processMessage(text.cause, true, ...args)); } return finalMessage; } else if (!Array.isArray(text) || (Array.isArray(text) && (!args || args.length === 0))) { - return [{ - content: this.redactText(utils.format(text, ...args)), - styling: [EStyles.specialSubLine, EStyles.reset], - stylingParams: ['', ''], - subLine: true, - }]; + const processedArgs: IMessageChunk[] = []; + if (args.length > 0) { + args.map((arg) => this.processMessage(arg, true)).forEach((processedArg) => { + processedArg.map((chunk) => processedArgs.push(chunk)); + }); + } + return [...this.processMessage(utils.format(text), forceSubline), ...processedArgs]; } const finalMessage: (IMessageChunk & {subLine: boolean})[] = []; @@ -156,6 +226,7 @@ export class Logger { styling: [EStyles.specialSubLine], stylingParams: [''], subLine: switchedToSublines, + breaksLine: false, }); } if (variable) { @@ -170,7 +241,7 @@ export class Logger { return finalMessage; } - private handleMessage(text: string | string[] | Error, level: ELoggerLevel, ...args: any[]): void { + private handleMessage(text: any, level: ELoggerLevel, ...args: any[]): void { const chunks = this.processMessage(text, false, ...args); const messageChunks: IMessageChunk[] = []; const subLines: IMessageChunk[] = []; @@ -184,7 +255,7 @@ export class Logger { } if (this.allLineColored) { const txtColor = this.coloredBackground ? this.defaultSettings.logLevelAccentColors[level] : this.defaultSettings.logLevelMainColors[level]; - const bgColor = this.coloredBackground ? this.defaultSettings.logLevelMainColors[level] : this.defaultSettings.logLevelAccentColors[level]; + const bgColor = this.coloredBackground ? this.defaultSettings.logLevelMainColors[level] : undefined; if (txtColor) { chunk.styling.unshift(EStyles.textColor); chunk.stylingParams.unshift(txtColor); @@ -198,6 +269,10 @@ export class Logger { } }); + // prevents errors where a message would have no content, only sublines + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + if (messageChunks.length === 0 && subLines.length > 0) messageChunks.push(subLines.shift()!); + const message: ILogMessage = { messageChunks, subLines, @@ -215,54 +290,153 @@ export class Logger { }); } - log(text: string | string[], ...args: any[]): void { + /** + * Logs a message using the default level + * @param text A string, list of strings or Error object to be logged + * @param args A list of arguments to be passed to the text + * @example + * logger.log('Hello, world!'); // Logs 'Hello, world!' with the default level + * logger.log`Hello, ${name}!`; // Logs 'Hello, !' where name will be styled as a variable + * logger.log`Hello, ${errorObject}`; // logs 'Hello, ' followed with the stacktrace + * logger.log(errorObject); // logs '' followed with the stacktrace + */ + log(text: any, ...args: any[]): void { this.handleMessage(text, this.defaultLevel, ...args); } - info(text: string | string[], ...args: any[]): void { + /** + * Logs a message using the info level + * @param text A string, list of strings or Error object to be logged + * @param args A list of arguments to be passed to the text + * @example + * logger.info('Hello, world!'); // Logs 'Hello, world!' with the info level + * logger.info`Hello, ${name}!`; // Logs 'Hello, !' where name will be styled as a variable + * logger.info`Hello, ${errorObject}`; // logs 'Hello, ' followed with the stacktrace + * logger.info(errorObject); // logs '' followed with the stacktrace + */ + info(text: any, ...args: any[]): void { this.handleMessage(text, ELoggerLevel.INFO, ...args); } - warn(text: string | string[], ...args: any[]): void { + /** + * Logs a message using the warn level + * @param text A string, list of strings or Error object to be logged + * @param args A list of arguments to be passed to the text + * @example + * logger.warn('Hello, world!'); // Logs 'Hello, world!' with the warn level + * logger.warn`Hello, ${name}!`; // Logs 'Hello, !' where name will be styled as a variable + * logger.warn`Hello, ${errorObject}`; // logs 'Hello, ' followed with the stacktrace + * logger.warn(errorObject); // logs '' followed with the stacktrace + */ + warn(text: any, ...args: any[]): void { this.handleMessage(text, ELoggerLevel.WARN, ...args); } - error(text: string | string[] | Error, ...args: any[]): void { + /** + * Logs a message using the error level + * @param text A string, list of strings or Error object to be logged + * @param args A list of arguments to be passed to the text + * @example + * logger.error('Hello, world!'); // Logs 'Hello, world!' with the error level + * logger.error`Hello, ${name}!`; // Logs 'Hello, !' where name will be styled as a variable + * logger.error`Hello, ${errorObject}`; // logs 'Hello, ' followed with the stacktrace + * logger.error(errorObject); // logs '' followed with the stacktrace + */ + error(text: any, ...args: any[]): void { this.handleMessage(text, ELoggerLevel.ERROR, ...args); } - debug(text: string | string[], ...args: any[]): void { + /** + * Logs a message using the debug level, this level is only logged if the debug mode is enabled + * @param text A string or list of strings to be logged + * @param args A list of arguments to be passed to the text + * @example + * logger.debug('Hello, world!'); // Logs 'Hello, world!' with the debug level + * logger.debug`Hello, ${name}!`; // Logs 'Hello, !' where name will be styled as a variable + * logger.debug`Hello, ${errorObject}`; // logs 'Hello, ' followed with the stacktrace + * logger.debug(errorObject); // logs '' followed with the stacktrace + */ + debug(text: any, ...args: any[]): void { this.handleMessage(text, ELoggerLevel.DEBUG, ...args); } - fatal(text: string | string[] | Error, ...args: any[]): void { + /** + * Logs a message using the fatal level, will stop the execution of the program unless disableFatalCrash is set to true + * @param text A string or list of strings to be logged + * @param args A list of arguments to be passed to the text + * @example + * logger.fatal('Hello, world!'); // Logs 'Hello, world!' with the fatal level + * logger.fatal`Hello, ${name}!`; // Logs 'Hello, !' where name will be styled as a variable + * logger.fatal`Hello, ${errorObject}`; // logs 'Hello, ' followed with the stacktrace + * logger.fatal(errorObject); // logs '' followed with the stacktrace + */ + fatal(text: any, ...args: any[]): void { this.handleMessage(text, ELoggerLevel.FATAL, ...args); + if (!this.disableFatalCrash) process.exit(647412); } + /** + * Logs a message using the Warning level + * @param text A string or list of strings to be logged + * @param args A list of arguments to be passed to the text + * @example + * logger.alert('Hello, world!'); // Logs 'Hello, world!' with the warning level + * logger.alert`Hello, ${name}!`; // Logs 'Hello, !' where name will be styled as a variable + * logger.alert`Hello, ${errorObject}`; // logs 'Hello, ' followed with the stacktrace + * logger.alert(errorObject); // logs '' followed with the stacktrace + */ alert(text: string | string[], ...args: any[]): void { this.handleMessage(text, ELoggerLevel.ALERT, ...args); } - severe(text: string | string[] | Error, ...args: any[]): void { + /** + * Logs a message using the Error level + * @param text A string or list of strings to be logged + * @param args A list of arguments to be passed to the text + * @example + * logger.severe('Hello, world!'); // Logs 'Hello, world!' with the Error level + * logger.severe`Hello, ${name}!`; // Logs 'Hello, !' where name will be styled as a variable + * logger.severe`Hello, ${errorObject}`; // logs 'Hello, ' followed with the stacktrace + * logger.severe(errorObject); // logs '' followed with the stacktrace + */ + severe(text: any, ...args: any[]): void { this.handleMessage(text, ELoggerLevel.SEVERE, ...args); } /** - * Allows the assignment of a listener callback that will be called every log made - * @param listenerCallback void function with the actions to be executed every log. Receives ILogMessage object. + * Registers an engine listener to this logger + * @param listenerEngine The engine to be registered */ registerListener(listenerEngine: Engine): void { this.logListeners.push(listenerEngine); } + /** + * Unregisters an engine listener from this logger + * @param listenerEngine The engine to be unregistered + */ unRegisterListener(listenerEngine: Engine): void { this.logListeners = this.logListeners.filter((listener) => listener !== listenerEngine); } + /** + * Sets the colored background state for this logger + * @param coloredBackground The new state for colored background + * @example + * logger.setColoredBackground(true); // All logs will have colored background from now on + * logger.setColoredBackground(false); // All logs will not have a background from now on + */ setColoredBackground(coloredBackground: boolean): void { this.coloredBackground = coloredBackground; } + /** + * Sets the all line colored state for this logger + * @param allLineColored The new state for all line colored + * @example + * logger.setAllLineColored(true); // The content of the logs will be colored from now on + * logger.setAllLineColored(false); // Only the information of the logs will be colored while the actual content will stay unchanged from now on + */ setAllLineColored(allLineColored: boolean): void { this.allLineColored = allLineColored; } diff --git a/src/main/outputEngines/consoleEngine.ts b/src/main/outputEngines/consoleEngine.ts index 983368e..6341bc9 100755 --- a/src/main/outputEngines/consoleEngine.ts +++ b/src/main/outputEngines/consoleEngine.ts @@ -14,51 +14,40 @@ export class ConsoleEngine extends Engine { }; private parseTextStyles(chunk: IMessageChunk, subLine?: boolean, backgroundColor?: string, customFGColor?: string): string { - let finalMsg = subLine ? (backgroundColor ? chalk.bgHex(backgroundColor).gray : chalk.gray) : chalk.reset; - let special = false; + let textStyler = subLine ? (backgroundColor ? chalk.bgHex(backgroundColor).gray : chalk.gray) : chalk.reset; chunk.styling.forEach((style, index) => { switch (style) { case EStyles.bold: - finalMsg = finalMsg.bold; + textStyler = textStyler.bold; break; case EStyles.italic: - finalMsg = finalMsg.italic; + textStyler = textStyler.italic; break; case EStyles.backgroundColor: - finalMsg = finalMsg.bgHex(chunk.stylingParams[index]); + textStyler = textStyler.bgHex(chunk.stylingParams[index]); break; case EStyles.textColor: - finalMsg = finalMsg.hex(chunk.stylingParams[index]); - break; - case EStyles.specialSubLine: - special = true; + textStyler = textStyler.hex(chunk.stylingParams[index]); break; case EStyles.reset: - finalMsg = finalMsg.reset; + textStyler = textStyler.reset; break; default: break; } }); - let finalMessage = ''; - const fullLineTxt = chunk.content.padEnd(process.stdout.columns - (subLine && !special ? 3 : 0)); - if (subLine && !special) { - finalMessage += (customFGColor ? (backgroundColor ? chalk.bgHex(backgroundColor) : chalk).hex(customFGColor)('| ') : finalMsg('| ')); - finalMessage += (customFGColor ? finalMsg.hex(customFGColor)(fullLineTxt) : finalMsg(fullLineTxt)); - } else if (subLine && special) { - finalMessage += finalMsg(fullLineTxt); - } else { - finalMessage += (customFGColor ? chalk.hex(customFGColor)(finalMsg(chunk.content)) : finalMsg(chunk.content)); - } - return finalMessage; + const txt = subLine ? (`${!chunk.styling.includes(EStyles.specialSubLine) && chunk.breaksLine ? '| ' : ''}${chunk.content}`) : chunk.content; + return (customFGColor ? textStyler.hex(customFGColor)(txt) : textStyler(txt)); } - private parsePrefix(prefixes: IPrefix[], defaultBg?: string): (string | undefined)[] { + private parsePrefix(prefixes: IPrefix[], defaultBg?: string, dontSaveCache?: boolean): (string | undefined)[] { return prefixes.map((prefix) => { + // if theres cache for this prefix return it if (this.prefixes.has(prefix.content)) return this.prefixes.get(prefix.content); - let bgColor = ''; - let bgColorArray: string[] = []; + // calculates the backgroundColor for the prefix + let bgColor = ''; // used if single color background color + let bgColorArray: string[] = []; // used if multiple background colors if (prefix.backgroundColor && !Array.isArray(prefix.backgroundColor)) { if (typeof prefix.backgroundColor === 'function') { const result = prefix.backgroundColor(prefix.content); @@ -71,8 +60,9 @@ export class ConsoleEngine extends Engine { bgColorArray = prefix.backgroundColor; } - let fgColor = ''; - let fgArray: string[] = []; + // calculates the text color for the prefix + let fgColor = ''; // used if single color + let fgArray: string[] = []; // used if different colors for different characters if (!Array.isArray(prefix.color)) { if (typeof prefix.color === 'function') { const result = prefix.color(prefix.content); @@ -88,12 +78,12 @@ export class ConsoleEngine extends Engine { // static colors if (bgColor && fgColor) { const result = chalk.bgHex(bgColor).hex(fgColor)(prefix.content); - this.prefixes.set(prefix.content, result); + if (!dontSaveCache) this.prefixes.set(prefix.content, result); return result; } if (!bgColor && bgColorArray.length <= 0 && fgColor) { const result = (defaultBg ? chalk.bgHex(defaultBg) : chalk).hex(fgColor)(prefix.content); - this.prefixes.set(prefix.content, result); + if (!dontSaveCache) this.prefixes.set(prefix.content, result); return result; } @@ -119,38 +109,37 @@ export class ConsoleEngine extends Engine { else finalMsg += (defaultBg ? chalk.bgHex(defaultBg) : chalk).hex(color)(prefix.content[index]); }); } - this.prefixes.set(prefix.content, finalMsg); + + // saves to cache + if (!dontSaveCache) this.prefixes.set(prefix.content, finalMsg); return finalMsg; }); } + /** + * Logs a message to the console + * @param message The message to be logged + * @returns void + */ log(message: ILogMessage): void { if (!this.debug && message.logLevel === ELoggerLevel.DEBUG) return; const defaultSettings = message.settings.default; - const shouldColorBg = message.settings.coloredBackground || message.logLevel === ELoggerLevel.FATAL; + const isFatal = message.logLevel === ELoggerLevel.FATAL; + const shouldColorBg = message.settings.coloredBackground || isFatal; + const currentMainColor = shouldColorBg ? defaultSettings.logLevelMainColors[message.logLevel] : undefined; + const currentAccentColor = shouldColorBg ? defaultSettings.logLevelAccentColors[message.logLevel] : undefined; + // clears prefixes cache in order to apply correct background color if (shouldColorBg) this.prefixes.clear(); - let formatter: chalk.Chalk = chalk.reset; - if (shouldColorBg) formatter = formatter.bgHex(defaultSettings.logLevelMainColors[message.logLevel]); - - if (shouldColorBg && defaultSettings.logLevelAccentColors[message.logLevel]) formatter = formatter.hex(defaultSettings.logLevelAccentColors[message.logLevel]); + let styleText = currentMainColor ? chalk.bgHex(currentMainColor) : chalk.reset; + styleText = !shouldColorBg ? styleText.hex(defaultSettings.logLevelMainColors[message.logLevel]) : (currentAccentColor ? styleText.hex(currentAccentColor) : styleText); - if (!message.settings.coloredBackground && message.logLevel !== ELoggerLevel.FATAL) formatter = formatter.hex(defaultSettings.logLevelMainColors[message.logLevel]); - const timestamp = formatter(this.getTime(message.timestamp)); + const timestamp = styleText(this.getTime(message.timestamp)); - const prefixes = this.parsePrefix(message.prefixes, shouldColorBg ? defaultSettings.logLevelMainColors[message.logLevel] : undefined); - - if (message.logLevel === ELoggerLevel.FATAL) this.prefixes.clear(); - - let prefixTxt = ''; - prefixes.forEach((prefix) => { - prefixTxt += formatter(' ['); - prefixTxt += prefix; - prefixTxt += formatter(']'); - }); - const level = formatter(` ${ELoggerLevelNames[message.logLevel]}:`); + const prefixes = this.parsePrefix(message.prefixes, currentMainColor, isFatal).map((prefix) => `${styleText(' [')}${prefix}${styleText(']')}`).join(''); + const logKind = styleText(` ${ELoggerLevelNames[message.logLevel]}:`); // adds a space before the first chunk to separate the message from the : in the log without coloring the background if allLineColored is false const firstChunk = message.messageChunks[0]; @@ -159,33 +148,50 @@ export class ConsoleEngine extends Engine { styling: firstChunk.styling, stylingParams: firstChunk.stylingParams, subLine: false, + breaksLine: false, }); - const txt = message.messageChunks.map((chunk): string => this.parseTextStyles(chunk, false, shouldColorBg ? defaultSettings.logLevelMainColors[message.logLevel] : undefined)); + const parsedText = message.messageChunks.map((chunk): string => this.parseTextStyles(chunk, false, currentMainColor)).join(''); - this.consoleLoggers[message.logLevel](`${timestamp}${prefixTxt}${level}${txt.join('')}`); + // writes the final log into the console + this.consoleLoggers[message.logLevel](`${timestamp}${prefixes}${logKind}${parsedText}`); if (!message.subLines || message.subLines.length <= 0) return; - message.subLines.forEach((line) => - this.consoleLoggers[message.logLevel](this.parseTextStyles( - line, - true, - shouldColorBg ? defaultSettings.logLevelMainColors[message.logLevel] : undefined, - shouldColorBg ? defaultSettings.logLevelAccentColors[message.logLevel] : undefined, - )), - ); + const subLinesBuffer: string[] = []; + let lineBuffer = ''; + let lineSizeBuffer = 0; + message.subLines.forEach((line, index, arr) => { + lineBuffer += this.parseTextStyles(line, true, currentMainColor, currentAccentColor); + lineSizeBuffer += line.content.length; + if (arr[index + 1]?.breaksLine || index === arr.length - 1) { + const spaceFill = ''.padEnd(process.stdout.columns - lineSizeBuffer - 3); + subLinesBuffer.push(lineBuffer + this.parseTextStyles({ + content: spaceFill, + styling: line.styling, + stylingParams: line.stylingParams, + subLine: true, + breaksLine: false, + }, true, currentMainColor, currentAccentColor)); + lineBuffer = ''; + lineSizeBuffer = 0; + } + }); + this.consoleLoggers[message.logLevel](subLinesBuffer.join('\n')); + // prints an indication at the end of the sublines this.consoleLoggers[message.logLevel]( this.parseTextStyles( { content: '#'.padEnd(process.stdout.columns, '-'), - styling: [EStyles.specialSubLine, EStyles.textColor], - stylingParams: ['', defaultSettings.logLevelAccentColors[message.logLevel] || '#ffffff'], + styling: [EStyles.specialSubLine], + stylingParams: [''], subLine: true, + breaksLine: false, }, true, - shouldColorBg ? defaultSettings.logLevelMainColors[message.logLevel] : undefined, + currentMainColor, + currentAccentColor, ), ); } diff --git a/src/main/outputEngines/engine.ts b/src/main/outputEngines/engine.ts index 351a258..3af90a4 100755 --- a/src/main/outputEngines/engine.ts +++ b/src/main/outputEngines/engine.ts @@ -1,15 +1,27 @@ import { ILogMessage, IEngineSettings } from '../interfaces'; import { Logger } from '../logger'; +/** + * Engine + * @description Abstract class that all engines should extend + * @abstract + * @class Engine + **/ export abstract class Engine { + // debug mode debug: boolean; - private loggers: Logger[] = []; + // list of loggers that this engine is listening to + loggers: Logger[] = []; constructor(settings?: IEngineSettings, ...loggers: Logger[]) { if (Array.isArray(settings)) { loggers = settings; settings = undefined; } + if (settings instanceof Logger) { + loggers = [settings]; + settings = undefined; + } this.debug = settings?.debug || false; this.loggers = loggers; @@ -19,12 +31,24 @@ export abstract class Engine { }); } + /** + * Deconstructs the engine + */ destroy(): void { this.loggers.forEach((logger) => { logger.unRegisterListener(this); }); } + /** + * Converts a Date object to a string that can be used on logs + * @param time Date object with the time to be converted + * @param fullDate Boolean to indicate if result string should include days, months and years + * @returns {string} The formatted time + * @example + * getTime(new Date(), true); // [2024:07:01-12:00:00] + * getTime(new Date(), false); // [12:00:00] + */ getTime(time: Date, fullDate?: boolean): string { const day = `0${time.getDate()}`.slice(-2); const month = `0${time.getMonth()}`.slice(-2); @@ -33,9 +57,13 @@ export abstract class Engine { const minutes = `0${time.getMinutes()}`.slice(-2); const hours = `0${time.getHours()}`.slice(-2); - return `[${fullDate ? `${day}:${month}:${year}-` : ''}${hours}:${minutes}:${seconds}]`; + return `[${fullDate ? `${year}:${month}:${day}-` : ''}${hours}:${minutes}:${seconds}]`; } + /** + * logs a message + * @param message The message to be logged + */ log(message: ILogMessage): void { throw new Error('Method not implemented.', { cause: message }); } diff --git a/src/main/outputEngines/fileStorageEngine.ts b/src/main/outputEngines/fileStorageEngine.ts index c38f977..2373ece 100755 --- a/src/main/outputEngines/fileStorageEngine.ts +++ b/src/main/outputEngines/fileStorageEngine.ts @@ -1,60 +1,269 @@ import { ELoggerLevel, ELoggerLevelNames, EStyles, IFileStorageSettings, ILogMessage, IMessageChunk } from '../interfaces'; import { Logger } from '../logger'; import { Engine } from './'; +import path from 'path'; +import fs from 'fs'; +import AdmZip from 'adm-zip'; +import { AutoLogEnd } from '../autoLogEnd'; -export default class FileStorage extends Engine { - constructor(settings?: IFileStorageSettings, ...loggers: Logger[]) { +/** + * FileStorageEngine + * @description Engine that allows logs to be saved to files on the disk + * @extends Engine + */ +export class FileStorageEngine extends Engine { + private uuid: string; + private engineSettings: IFileStorageSettings; + private latestLogStream: fs.WriteStream | null = null; + private debugLogStream: fs.WriteStream | null = null; + private errorLogStream: fs.WriteStream | null = null; + private fatalLogStream: fs.WriteStream | null = null; + private debugLogFolderPath: string; + private errorLogFolderPath: string; + private fatalLogFolderPath: string; + private logQueue: {txt: string, level: ELoggerLevel}[] = []; + private logQueueRunning = false; + + constructor(settings: IFileStorageSettings, ...loggers: Logger[]) { super(settings, ...loggers); - let a; + if (!settings) throw new Error('settings is required'); + this.engineSettings = settings; + this.engineSettings.logFolderPath = path.resolve(this.engineSettings.logFolderPath); // resolve path to absolute path + this.debugLogFolderPath = path.resolve(this.engineSettings.logFolderPath, 'debug'); + this.errorLogFolderPath = path.resolve(this.engineSettings.logFolderPath, 'error'); + this.fatalLogFolderPath = path.resolve(this.engineSettings.logFolderPath, 'fatal'); + + // generate a uuid for this instance + this.uuid = 'FSEngine-' + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); + AutoLogEnd._instance?.appendDeconstructor(this.uuid, async () => { await this.destroy(); }); + + // check if logFolderPath exists + if (!this.engineSettings.logFolderPath) throw new Error('logFolderPath is required'); + if (fs.existsSync(this.engineSettings.logFolderPath)) { + if (!fs.lstatSync(this.engineSettings.logFolderPath).isDirectory()) throw new Error('logFolderPath is not a directory'); + // create subfolder if it doesnt exist + if (!fs.existsSync(this.debugLogFolderPath)) fs.mkdirSync(this.debugLogFolderPath, { recursive: true }); + if (!fs.existsSync(this.errorLogFolderPath)) fs.mkdirSync(this.errorLogFolderPath, { recursive: true }); + if (!fs.existsSync(this.fatalLogFolderPath)) fs.mkdirSync(this.fatalLogFolderPath, { recursive: true }); + + // check if theres a latest.log file and rename it to a timestamp + const date = new Date(); + const timestamp = date.toISOString().replace(/:/g, '-').replace(/\./g, '-').replace('T', '-').replace('Z', ''); + if (fs.existsSync(path.resolve(this.engineSettings.logFolderPath, 'latest.log'))) { + fs.renameSync(path.resolve(this.engineSettings.logFolderPath, 'latest.log'), path.resolve(this.engineSettings.logFolderPath, `${timestamp}.log`)); + } + if (fs.existsSync(path.resolve(this.debugLogFolderPath, 'latest.log'))) { + fs.renameSync(path.resolve(this.debugLogFolderPath, 'latest.log'), path.resolve(this.debugLogFolderPath, `${timestamp}.log`)); + } + if (fs.existsSync(path.resolve(this.errorLogFolderPath, 'latest.log'))) { + fs.renameSync(path.resolve(this.errorLogFolderPath, 'latest.log'), path.resolve(this.errorLogFolderPath, `${timestamp}.log`)); + } + if (fs.existsSync(path.resolve(this.fatalLogFolderPath, 'latest.log'))) { + fs.renameSync(path.resolve(this.fatalLogFolderPath, 'latest.log'), path.resolve(this.fatalLogFolderPath, `${timestamp}.log`)); + } + + if (this.engineSettings.compressLogFilesAfterNewExecution) { + // compress log files + const zipperInstance = new AdmZip(); + const files = fs.readdirSync(this.engineSettings.logFolderPath); + // get the only .log file + const logFile = files.filter((file) => file.endsWith('.log'))[0]; + if (logFile) { + const logTimestamp = logFile.split('.')[0]; + // add all files and folders to the zip + zipperInstance.addLocalFolder(this.engineSettings.logFolderPath, '', (filename) => !filename.endsWith('.zip')); + // save the zip file + zipperInstance.writeZip(`${this.engineSettings.logFolderPath}/${logTimestamp}.zip`); + // remove all .log files recursively + const removeLogFiles = (folderPath: string): void => { + const files = fs.readdirSync(folderPath); + files.forEach((file) => { + const filePath = path.resolve(folderPath, file); + if (fs.lstatSync(filePath).isDirectory()) { + removeLogFiles(filePath); + } else if (file.endsWith('.log')) { + fs.unlinkSync(filePath); + } + }); + }; + removeLogFiles(this.engineSettings.logFolderPath); + } + } + } else { + fs.mkdirSync(this.engineSettings.logFolderPath, { recursive: true }); + fs.mkdirSync(this.debugLogFolderPath, { recursive: true }); + fs.mkdirSync(this.errorLogFolderPath, { recursive: true }); + fs.mkdirSync(this.fatalLogFolderPath, { recursive: true }); + } + + this.latestLogStream = fs.createWriteStream(path.resolve(this.engineSettings.logFolderPath, 'latest.log'), { flags: 'a' }); + if (this.engineSettings.enableDebugLog) this.debugLogStream = fs.createWriteStream(path.resolve(this.debugLogFolderPath, 'latest.log'), { flags: 'a' }); + if (this.engineSettings.enableErrorLog) this.errorLogStream = fs.createWriteStream(path.resolve(this.errorLogFolderPath, 'latest.log'), { flags: 'a' }); + if (this.engineSettings.enableFatalLog) this.fatalLogStream = fs.createWriteStream(path.resolve(this.fatalLogFolderPath, 'latest.log'), { flags: 'a' }); + } + + /** + * Deconstructs the FileStorageEngine + * @returns void + */ + async destroy(): Promise { + this.loggers.forEach((logger) => { + logger.unRegisterListener(this); + }); + await this.closeStreams(); } private parseTextStyles(chunk: IMessageChunk, subLine?: boolean): string { - let special = false; - chunk.styling.forEach((style) => { - switch (style) { - case EStyles.specialSubLine: - special = true; - break; - default: - break; - } + return `${subLine && (!chunk.styling.includes(EStyles.specialSubLine) && chunk.breaksLine) ? '| ' : ''}${chunk.content}`; + } + + /** + * Closes all files streams + * NOTE: Only call this method when you are done with the logger, and you're not using autoLogEnd! + * @returns void + */ + async closeStreams(): Promise { + return new Promise((_resolve) => { + const promises: Promise[] = []; + const date = new Date(); + const timestamp = date.toISOString().replace(/:/g, '-').replace(/\./g, '-').replace('T', '-').replace('Z', ''); + promises.push(new Promise((resolve) => { + if (this.latestLogStream) { + this.latestLogStream.close(() => { + if (fs.existsSync(path.resolve(this.engineSettings.logFolderPath, 'latest.log'))) { + fs.renameSync(path.resolve(this.engineSettings.logFolderPath, 'latest.log'), path.resolve(this.engineSettings.logFolderPath, `${timestamp}.log`)); + } + resolve(); + }); + } + })); + promises.push(new Promise((resolve) => { + if (this.debugLogStream) { + this.debugLogStream.close(() => { + if (fs.existsSync(path.resolve(this.debugLogFolderPath, 'latest.log'))) { + fs.renameSync(path.resolve(this.debugLogFolderPath, 'latest.log'), path.resolve(this.debugLogFolderPath, `${timestamp}.log`)); + } + resolve(); + }); + } + })); + promises.push(new Promise((resolve) => { + if (this.errorLogStream) { + this.errorLogStream.close(() => { + if (fs.existsSync(path.resolve(this.errorLogFolderPath, 'latest.log'))) { + fs.renameSync(path.resolve(this.errorLogFolderPath, 'latest.log'), path.resolve(this.errorLogFolderPath, `${timestamp}.log`)); + } + resolve(); + }); + } + })); + promises.push(new Promise((resolve) => { + if (this.fatalLogStream) { + this.fatalLogStream.close(() => { + if (fs.existsSync(path.resolve(this.fatalLogFolderPath, 'latest.log'))) { + fs.renameSync(path.resolve(this.fatalLogFolderPath, 'latest.log'), path.resolve(this.fatalLogFolderPath, `${timestamp}.log`)); + } + resolve(); + }); + } + })); + Promise.all(promises).then(() => { + _resolve(); + }); }); - return (subLine && !special ? '| ' : '') + chunk.content; } - log(message: ILogMessage): void { - if (!this.debug && message.logLevel === ELoggerLevel.DEBUG) return; + private async logTextToFile(txt: string, logLevel: ELoggerLevel): Promise { + const promises: Promise[] = []; + promises.push((new Promise((resolve) => { + if (this.latestLogStream) this.latestLogStream.write(txt, () => { resolve(); }); + else resolve(); + }))); + switch (logLevel) { + case ELoggerLevel.DEBUG: + promises.push((new Promise((resolve) => { + if (this.debugLogStream) this.debugLogStream.write(txt, () => { resolve(); }); + else resolve(); + }))); + break; + case ELoggerLevel.ERROR: + promises.push((new Promise((resolve) => { + if (this.errorLogStream) this.errorLogStream.write(txt, () => { resolve(); }); + else resolve(); + }))); + break; + case ELoggerLevel.FATAL: + promises.push((new Promise((resolve) => { + if (this.fatalLogStream) this.fatalLogStream.write(txt, () => { resolve(); }); + else resolve(); + }))); + break; + default: + break; + } + await Promise.all(promises); + } - const defaultSettings = message.settings.default; + private async runLogQueue(): Promise { + if (this.logQueueRunning) return; + if (this.logQueue.length <= 0) { + this.logQueueRunning = false; + return; + } + this.logQueueRunning = true; + const log = this.logQueue.shift(); + if (!log) { + this.logQueueRunning = false; + return; + } + await this.logTextToFile(log.txt, log.level); + this.logQueueRunning = false; + this.runLogQueue(); + } - const timestamp = this.getTime(message.timestamp); + private logToFile(txt: string, logLevel: ELoggerLevel): void { + this.logQueue.push({ txt, level: logLevel }); + if (!this.logQueueRunning) this.runLogQueue(); + } - const prefixes = message.prefixes; + /** + * Logs a message to the file + * @param message The message to be logged + * @returns void + */ + log(message: ILogMessage): void { + if (!this.debug && message.logLevel === ELoggerLevel.DEBUG) return; + const timestamp = this.getTime(message.timestamp, true); - const prefixTxt = prefixes.map((prefix) => ` [${prefix}]`); - const level = ` ${ELoggerLevelNames[message.logLevel]}: `; + const prefixes = message.prefixes.map((prefix) => `[${prefix.content}]`).join(' '); + const level = ELoggerLevelNames[message.logLevel]; - const txt = message.messageChunks.map((chunk): string => this.parseTextStyles(chunk, false)); + const textContent = message.messageChunks.map((chunk): string => this.parseTextStyles(chunk, false)).join(''); - // this.consoleLoggers[message.logLevel](`${timestamp}${prefixTxt}${level}${txt.join('')}`); + this.logToFile(`${timestamp} ${prefixes} ${level}: ${textContent}\n`, message.logLevel); if (!message.subLines || message.subLines.length <= 0) return; let biggestLine = 0; - message.subLines.forEach((line) => { - if (line.content.length > biggestLine) biggestLine = line.content.length; - // this.consoleLoggers[message.logLevel](this.parseTextStyles(line, true)); + let lineBuffer = ''; + const lines: string[] = []; + message.subLines.forEach((line, index, arr) => { + lineBuffer += this.parseTextStyles(line, true); + if (arr[index + 1]?.breaksLine || index === arr.length - 1) { + if (lineBuffer.length > biggestLine) biggestLine = lineBuffer.length; + lines.push(lineBuffer); + lineBuffer = ''; + } }); + this.logToFile(lines.join('\n') + '\n', message.logLevel); - this.consoleLoggers[message.logLevel]( - this.parseTextStyles({ - content: '#'.padEnd(biggestLine, '-'), - styling: [EStyles.specialSubLine], - stylingParams: [''], - subLine: true, - }, - true, - ), - ); + this.logToFile(this.parseTextStyles({ + content: '#'.padEnd(biggestLine, '-'), + styling: [EStyles.specialSubLine], + stylingParams: [''], + subLine: true, + breaksLine: false, + }, true) + '\n', + message.logLevel); } } diff --git a/src/tests/tester.js b/src/tests/tester.js old mode 100644 new mode 100755 index cf11316..67d03d3 --- a/src/tests/tester.js +++ b/src/tests/tester.js @@ -1,25 +1,109 @@ -const { Logger } = require('../../build'); +const { Logger, FileStorageEngine, ConsoleEngine, AutoLogEnd } = require('../../build/src'); +const path = require('path'); +console.time('Test execution time'); + +// Creates a logger instance const logger = new Logger({ - prefix: 'Logger.JS', // This will be the prefix of all logs (default: null) - disableFatalCrash: true, // If true, the logger will not crash the process when a fatal error occurs (default: false) - allLineColored: true, // If true, the whole line will be colored instead of only the prefix (default: false) - coloredBackground: false, // If true, the background of the lines will be colored instead of the text (default: false) - debug: false, // If true, the logger will log debug messages (default: false) - fileProperties: { // This is the configuration of the log files - enable: true, // If true, the logger will log to files (default: false) [NOTE: If false all below options will be ignored] - logFolderPath: './logs', // This is the path of the folder where the log files will be saved (default: './logs') - enableLatestLog: true, // If true, the logger will save the latest log in a file (default: true) - enableDebugLog: true, // If true, the logger will save the debug logs in a file (default: false) - enableErrorLog: true, // If true, the logger will save the error logs in a file (default: false) - enableFatalLog: true, // If true, the logger will save the fatal logs in a file (default: true) - generateHTMLLog: true, // If true, the logger will generate a HTML file with the logs otherwise a .log file (default: false) - compressLogFilesAfterNewExecution: true, // If true, the logger will compress the log files to zip after a new execution (default: true) + // adds a basic string prefix + prefixes: ['Logger.JS', + // and a complex long prefix + { + // prefix text + content: 'This is a stupidly long prefix :)', + // this function sets the color of the prefix text, the txt parameter is the content value + // and it must return a array whos size is equal to the amount of letters in the content value + // NOTE: color doesn't need to be a function, it can be a array, or a string! + // if it is an array then its size must match the amount of letters of the content value, however + // if it is a string then its hex code is used to paint the whole text + color: (txt) => { + // in this example we set a list of hex colors and repeat it to match the amount of letters + const colors = ['#ff5555', '#55ff55', '#5555ff']; + return txt.split('').map((t, i) => { + return colors[i % colors.length]; + }); + }, + // background color followes the same logic as color, it can be a function, an array or a string + backgroundColor: '#553311', + } + ], + // disables fatal crash so that fatal logs won't immediatly end the process + disableFatalCrash: true, + // makes the message of the log also be colored + allLineColored: true, + redactedContent: ['true'], +}); + +// Creates and registers a ConsoleEngine, all logs will now be displayed on the terminal +logger.registerListener(new ConsoleEngine({ + debug: true, +})); + +// Iniciates the AutoLogEnd singleton, this allows us to set custom routines to be executed before +// our program exits, but also will automaticly be used by the FileStorageEngines to close and +// rename the log files at the exit of the program. +// We are giving it our instance of logger, however this is optional and it could be instanciated +// without any parameter, where it would create its own instance of a logger and Console engine +// by giving it our instance however this means any log done by it will have our prefixes and will +// trigger the registered engines +new AutoLogEnd(logger); + +// NOTE: it is always recommended to create AutoLogEnd before any FileStorageEngine +// as FileStorageEngine automaticly registers it deconstructor if AutoLogEnd already exists + +// Creates and registers a FileStorageEngine, all logs from now on will be saved on disk! +logger.registerListener(new FileStorageEngine({ + debug: true, + logFolderPath: path.resolve(__dirname, 'logs'), + enableDebugLog: true, + enableErrorLog: true, + enableFatalLog: true, + compressLogFilesAfterNewExecution: true, +})); + +// Regular usage +logger.info('Hello, World!'); +logger.warn('Hello, World!'); +logger.error('Hello, World!'); +logger.fatal('Hello, World!'); +logger.debug('Hello, World!'); + +// Using template literals +logger.info`Hello, ${'World'}`; +logger.warn`Hello, ${'World'}`; +logger.error`Hello, ${'World'}`; +logger.fatal`Hello, ${'World'}`; +logger.debug`Hello, ${'World'}`; + +// Logging different data types +const myObj = { + kind: 'example', + bool: true, + number: 1, + nested: { + result: 'yes', + happy: true, }, +} + +const myArray = [1,2,3,4,5,6,7,8,9,10]; +const myErr = new Error('Example Error', { + cause: new Error('Another Error', { + cause: myObj + }), }); -logger.info('This is an info message'); -logger.warn('This is a warning message'); -logger.error('This is an error message'); -logger.debug('This is a debug message'); -logger.fatal('This is a fatal message'); +logger.info(myObj); +logger.warn('The object ->', myObj); +logger.error`Yes an object -> ${myObj}`; +logger.info(myArray); +logger.warn('The array ->', myArray); +logger.error`Yes an array -> ${myArray}`; +logger.error(myErr); +logger.error('The error ->', myErr); +logger.error`Yes an error -> ${myErr}`; +logger.error(myObj, myArray, myErr); +logger.warn`${myObj}, ${myErr}, ${myArray}`; +logger.info('And last\nBut not least\nMultiline Example!'); + +console.timeEnd('Test execution time'); From 9cc681ef01cca7a2bcafd78a129b90fc12f30d79 Mon Sep 17 00:00:00 2001 From: Space_Fox <44732812+emanuelfranklyn@users.noreply.github.com> Date: Mon, 10 Jun 2024 20:37:12 -0300 Subject: [PATCH 03/10] (fix): small bug fixes & documentation Fix some small bugs, makes the code more legible and updates markdown files and images --- .github/assets/LoggerExample.png | Bin 25970 -> 57898 bytes CHANGELOG.md | 29 +++ README.md | 73 ++++--- src/main/autoLogEnd.ts | 22 ++- src/main/interfaces/ILoggerOption.ts | 2 - src/main/logger.ts | 201 +++++++++++--------- src/main/outputEngines/consoleEngine.ts | 17 +- src/main/outputEngines/engine.ts | 8 + src/main/outputEngines/fileStorageEngine.ts | 54 +++--- src/tests/readmeExample.js | 37 ++++ src/tests/tester.js | 15 +- 11 files changed, 298 insertions(+), 160 deletions(-) mode change 100644 => 100755 CHANGELOG.md mode change 100644 => 100755 README.md create mode 100644 src/tests/readmeExample.js diff --git a/.github/assets/LoggerExample.png b/.github/assets/LoggerExample.png index b4b65be9f6562974bdd4cfc9249f0cb75c41ea7c..f230eb2845af71cced957ec287302329690967f8 100644 GIT binary patch literal 57898 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

-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📖 About -    This is a simple logger for NodeJS, made in TypeScript, with the objective of make beautiful and easy to read logs. +    A simple to use but powerful logger library for NodeJS, made with TypeScript, capable of making beautiful and well organized logs automagically.
-    Originally made for [twitch.js](https://github.com/PromisePending/twitch.js), we decided to make it in a separate package, so that it can be used in other projects without the need to install the entire twitch.js package or copy and maintain the code. +    Originally a small util for [twitch.js](https://github.com/PromisePending/twitch.js), Logger.js quickly expanded to other projects and started gaining more features, and now it stands as a standalone package to be used by anyone.

📦 Installing

-    To install Logger.JS in your project, you need first to have NodeJS installed, then run the following command in your terminal: +    To install Logger.JS in your project, you need first to have NodeJS installed (version 20 is recommended), then use the following command to install Logger.js as a dependency on your project:
@@ -45,38 +45,61 @@ yarn add @promisepending/logger.js
-

⌨ Use example

-    To use Logger.JS in your project, you need to import the logger class, then create an instance of that class, passing as parameter your logger configurations as an object, or nothing if you want to use the default configurations. +

⌨ Usage example

+    To use Logger.JS in your project, first import the Logger Class as well as the Engines that you will be using, then create instances of those classes, passing as parameter your configurations as an object. + +
+ +The instanciation order doesn't matter since both the Logger class as well as the Engine classes provide methods to dynamically add or remove connections.
```js -const { Logger } = require('@promisepending/logger.js'); -// or -import { Logger } from '@promisepending/logger.js'; +import { Logger, ConsoleEngine } from '@promisepending/logger.js'; const logger = new Logger({ - prefix: 'Logger.JS', // This will be the prefix of all logs (default: null) - disableFatalCrash: true, // If true, the logger will not crash the process when a fatal error occurs (default: false) - allLineColored: true, // If true, the whole line will be colored instead of only the prefix (default: false) - coloredBackground: false, // If true, the background of the lines will be colored instead of the text (default: false) - debug: false, // If true, the logger will log debug messages (default: false) - fileProperties: { // This is the configuration of the log files - enable: true, // If true, the logger will log to files (default: false) [NOTE: If false all below options will be ignored] - logFolderPath: './logs', // This is the path of the folder where the log files will be saved (default: './logs') - enableLatestLog: true, // If true, the logger will save the latest log in a file (default: true) - enableDebugLog: true, // If true, the logger will save the debug logs in a file (default: false) - enableErrorLog: true, // If true, the logger will save the error logs in a file (default: false) - enableFatalLog: true, // If true, the logger will save the fatal logs in a file (default: true) - generateHTMLLog: true, // If true, the logger will generate a HTML file with the logs otherwise a .log file (default: false) - compressLogFilesAfterNewExecution: true, // If true, the logger will compress the log files to zip after a new execution (default: true) - }, + // Adds a basic string prefix + prefixes: ['Logger.JS', + // And a complex prefix + { + // Prefix text + content: 'This prefix has complex colors', + /* This function sets the color of the prefix text, the txt parameter is the content value and it must return a array whos size is equal to the amount of letters in the content value. + NOTE: color doesn't need to be a function, it can be a array, or a string! If it is an array then its size must match the amount of letters of the content value, however, if it is a string then the hex code will be used to paint the whole text */ + color: (txt) => { + // In this example we set a list of hex colors and repeat it to match the amount of letters + const colors = ['#ff5555', '#55ff55', '#5555ff']; + return txt.split('').map((_, i) => { + return colors[i % colors.length]; + }); + }, + // Background color follows the same logic as color, it can be a function, an array or a string + backgroundColor: '#000033', + } + ], + // Disables fatal crashing, so that fatal logs won't immediatly end the process + disableFatalCrash: true, + // Makes the message of the log also be colored + allLineColored: true, }); ```
-    After creating the logger instance, you can use the methods to log your messages, as shown below: +Then either before or after the Logger instanciation, instaciate the Engine(s). + +```js +// Creates and registers a ConsoleEngine, all logs will now be displayed on the terminal +logger.registerListener(new ConsoleEngine({ + debug: true, +})); +``` + +Note that we are using `logger.registerListener` however it is possible to just pass `logger` as a second parameter in the constructor of `ConsoleEngine`, but also call the `registerLogger` method of the Engine allowing you to create the Engine before the logger, or even dynamically add loggers to the Engine. + +
+ +You can use the methods of the `logger` object we just create to log your messages, as shown below:
@@ -90,7 +113,7 @@ logger.fatal('This is a fatal message'); ### Results: -The result of the above logs in a windows command prompt +The result of the above logs in a Konsole terminal
diff --git a/src/main/autoLogEnd.ts b/src/main/autoLogEnd.ts index f1c32b5..bb2729d 100755 --- a/src/main/autoLogEnd.ts +++ b/src/main/autoLogEnd.ts @@ -11,6 +11,8 @@ export class AutoLogEnd { // eslint-disable-next-line no-use-before-define public static _instance?: AutoLogEnd; private deconstructors: Map Promise> = new Map(); + private deconstructorCallbacks: (() => void)[] = []; + private runningDeconstructors = false; // callbacks private exitCallback: (exitCode: number) => Promise = async (exitCode) => { await this.exitHandler({ exitCode }); }; @@ -40,6 +42,22 @@ export class AutoLogEnd { AutoLogEnd._instance = this; } + async callDeconstructors(): Promise { + return new Promise((resolve) => { + if (this.runningDeconstructors) return this.deconstructorCallbacks.push(() => resolve); + if (this.deconstructors.size === 0) return resolve(); + this.runningDeconstructors = true; + const promises: Promise[] = []; + this.deconstructors.forEach((deconstructor) => promises.push(deconstructor())); + this.deconstructors.clear(); + Promise.all(promises).then(() => { + this.runningDeconstructors = false; + this.deconstructorCallbacks.forEach((callback) => callback()); + resolve(); + }); + }); + } + private async exitHandler({ err, exitCode }: {err?: Error | string, exitCode?: number | string}): Promise { if (!this.exited) { process.stdin.resume(); @@ -49,9 +67,7 @@ export class AutoLogEnd { if (exitCode !== 123654 && exitCode !== 647412) this.logger.info('Program finished, code: ' + exitCode ?? '?'); else if (exitCode && exitCode === 123654 && err) this.logger.error(err); } - const promises: Promise[] = []; - this.deconstructors.forEach((deconstructor) => promises.push(deconstructor())); - Promise.all(promises).then(() => { + this.callDeconstructors().then(() => { process.exit(typeof exitCode === 'string' ? 0 : exitCode); }); } diff --git a/src/main/interfaces/ILoggerOption.ts b/src/main/interfaces/ILoggerOption.ts index 264fc68..23dfc07 100755 --- a/src/main/interfaces/ILoggerOption.ts +++ b/src/main/interfaces/ILoggerOption.ts @@ -1,5 +1,3 @@ -/* eslint-disable no-unused-vars */ - import { IDefault } from './IDefault'; import { ELoggerLevel } from './ILogMessage'; diff --git a/src/main/logger.ts b/src/main/logger.ts index 2e15a63..6bed796 100755 --- a/src/main/logger.ts +++ b/src/main/logger.ts @@ -4,11 +4,18 @@ import { Engine } from './outputEngines/engine'; import utils from 'util'; import { IDefault } from './interfaces/IDefault'; import Standard from './defaults/standard'; +import { AutoLogEnd } from './autoLogEnd'; /** * Main class that will process logs before automaticly sending then to registered Engines */ export class Logger { + // constants + private static splitCharsNonScape = [' ', ',', ':', '<', '>']; + private static splitCharsScape = ['*', '(', ')', '[', ']']; + private static splitChars = [...Logger.splitCharsNonScape, ...Logger.splitCharsScape]; + + // private fields private defaultLevel: ELoggerLevel = ELoggerLevel.INFO; private prefixes: IPrefix[]; private disableFatalCrash: boolean; @@ -17,6 +24,7 @@ export class Logger { private coloredBackground: boolean; private allLineColored: boolean; private defaultSettings: IDefault; + private exited = false; /** * @constructor @@ -79,13 +87,13 @@ export class Logger { private colorPrimitiveValue(text: string): { text: string, colorStyles: EStyles[], colorStylesValues: string[] } { let color = null; - if (!isNaN(Number(text))) color = this.defaultSettings.primitiveColors.number; - else if (text === 'null') color = this.defaultSettings.primitiveColors.null; + if (text === 'null') color = this.defaultSettings.primitiveColors.null; else if (text === 'undefined') color = this.defaultSettings.primitiveColors.undefined; else if (text === 'true' || text === 'false') color = this.defaultSettings.primitiveColors.boolean; else if ( (text.startsWith('"') && text.endsWith('"')) || (text.startsWith('\'') && text.endsWith('\'')) || (text.startsWith('`') && text.endsWith('`')) ) color = this.defaultSettings.primitiveColors.string; + else if (!isNaN(Number(text))) color = this.defaultSettings.primitiveColors.number; else if (text.includes('Circular') || text.includes('ref')) color = this.defaultSettings.primitiveColors.circular; else if (text.toLowerCase().includes('info')) color = this.defaultSettings.logLevelMainColors[ELoggerLevel.INFO]; else if (text.toLowerCase().includes('warn')) color = this.defaultSettings.logLevelMainColors[ELoggerLevel.WARN]; @@ -99,13 +107,10 @@ export class Logger { } private colorPrimitive(text: string): { text: string, colorStyles: EStyles[], colorStylesValues: string[] }[] { - // split text by certain characters - const splitCharsNonScape = [' ', ',', ':', '<', '>']; - const splitCharsScape = ['*', '(', ')', '[', ']']; const result: { text: string, colorStyles: EStyles[], colorStylesValues: string[] }[] = []; let elementGroupBuffer = ''; - text.split(RegExp(`(\\${splitCharsScape.join('|\\')}|${splitCharsNonScape.join('|')})`, 'gu')).forEach((element) => { - if ([...splitCharsNonScape, ...splitCharsScape].includes(element)) elementGroupBuffer += element; + text.split(RegExp(`(\\${Logger.splitCharsScape.join('|\\')}|${Logger.splitCharsNonScape.join('|')})`, 'gu')).forEach((element) => { + if (Logger.splitChars.includes(element)) elementGroupBuffer += element; else { if (elementGroupBuffer !== '') { result.push({ text: elementGroupBuffer, colorStyles: [], colorStylesValues: [] }); @@ -118,103 +123,96 @@ export class Logger { return result; } - /** - * Parses the message and returns an array of IMessageChunk objects - * the first IMessageChunk object is the main message, the rest are subLines - * @param text - The content to be parsed - * @param args - The arguments to be passed to the content - * @returns IMessageChunk[] - */ - private processMessage(text: any, forceSubline: boolean, ...args: any[]): IMessageChunk[] { - if (!text) text = 'undefined'; - - // String handling - if (typeof text !== 'object') { - const texts: string[] = []; - const otherKinds: any[] = []; - args.map((arg) => typeof arg === 'string' ? texts.push(arg) : otherKinds.push(arg)); - const processedOtherKinds: IMessageChunk[] = []; - otherKinds.map((otherElement) => this.processMessage(otherElement, true)).forEach((otherPElement) => { - otherPElement.map((chunk) => processedOtherKinds.push(chunk)); - }); - const processedTexts: IMessageChunk[] = []; - (text.toString() as string).split('\n').forEach((line: string, index: number) => { - if (!Array.isArray(args)) args = [args]; - const processedColors = this.colorPrimitive(utils.format(line, ...texts)); - processedColors.forEach((color, colorIndex) => { - processedTexts.push({ - content: this.redactText(color.text), - styling: color.colorStyles, - stylingParams: color.colorStylesValues, - subLine: index === 0 ? forceSubline : true, - breaksLine: (index === 0 ? forceSubline : true) && colorIndex === 0, - }); - }); - }); - return [...processedTexts, ...processedOtherKinds]; - - // Error handling - } else if (text instanceof Error) { - const finalMessage: IMessageChunk[] = []; - const processedColors = this.colorPrimitive(utils.format((forceSubline ? 'Error: ' : '') + text.message.trim(), ...args)); + private processStrings(text: any, forceSubline: boolean, ...args: any[]): IMessageChunk[] { + const texts: string[] = []; + const otherKinds: any[] = []; + args.map((arg) => typeof arg === 'string' ? texts.push(arg) : otherKinds.push(arg)); + const processedOtherKinds: IMessageChunk[] = []; + otherKinds.map((otherElement) => this.processMessage(otherElement, true)).forEach((otherPElement) => { + otherPElement.map((chunk) => processedOtherKinds.push(chunk)); + }); + const processedTexts: IMessageChunk[] = []; + (text.toString() as string).split('\n').forEach((line: string, index: number, arr: string[]) => { + const processedColors = this.colorPrimitive(utils.format( + this.redactText(line), ...((index === arr.length - 1) ? texts : [(line.includes('%s') ? texts.shift() : '')]), + )); processedColors.forEach((color, colorIndex) => { - finalMessage.push({ - content: this.redactText(color.text), + processedTexts.push({ + content: color.text, styling: color.colorStyles, stylingParams: color.colorStylesValues, - subLine: forceSubline, - breaksLine: colorIndex === 0 && forceSubline, + subLine: index === 0 ? forceSubline : true, + breaksLine: (index === 0 ? forceSubline : true) && colorIndex === 0, }); }); + }); + return [...processedTexts, ...processedOtherKinds]; + } - const stack = text.stack?.split('\n'); - stack?.shift(); - - stack?.forEach((line) => { - const processedColors = this.colorPrimitive(utils.format(line.trim())); - processedColors.forEach((color, colorIndex) => { - finalMessage.push({ - content: this.redactText(color.text), - styling: color.colorStyles, - stylingParams: color.colorStylesValues, - subLine: true, - breaksLine: colorIndex === 0, - }); - }); + private processErrors(text: Error, forceSubline: boolean, ...args: any[]): IMessageChunk[] { + const finalMessage: IMessageChunk[] = []; + const processedColors = this.colorPrimitive(utils.format((forceSubline ? 'Error: ' : '') + this.redactText(text.message).trim(), ...args)); + processedColors.forEach((color, colorIndex) => { + finalMessage.push({ + content: color.text, + styling: color.colorStyles, + stylingParams: color.colorStylesValues, + subLine: forceSubline, + breaksLine: colorIndex === 0 && forceSubline, }); + }); - if (text.cause) { - const causedBy: IMessageChunk = { - content: '# Caused by:', - styling: [EStyles.specialSubLine], - stylingParams: [''], + const stack = text.stack?.split('\n'); + stack?.shift(); + + stack?.forEach((line) => { + const processedColors = this.colorPrimitive(utils.format(this.redactText(line).trim())); + processedColors.forEach((color, colorIndex) => { + finalMessage.push({ + content: color.text, + styling: color.colorStyles, + stylingParams: color.colorStylesValues, subLine: true, - breaksLine: true, - }; + breaksLine: colorIndex === 0, + }); + }); + }); - if (this.defaultSettings.causedByBackgroundColor) { - causedBy.styling.push(EStyles.backgroundColor); - causedBy.stylingParams.push(this.defaultSettings.causedByBackgroundColor); - } - if (this.defaultSettings.causedByTextColor) { - causedBy.styling.push(EStyles.textColor); - causedBy.stylingParams.push(this.defaultSettings.causedByTextColor); - } + if (text.cause) { + const causedBy: IMessageChunk = { + content: '# Caused by:', + styling: [EStyles.specialSubLine], + stylingParams: [''], + subLine: true, + breaksLine: true, + }; - finalMessage.push(causedBy); - finalMessage.push(...this.processMessage(text.cause, true, ...args)); + if (this.defaultSettings.causedByBackgroundColor) { + causedBy.styling.push(EStyles.backgroundColor); + causedBy.stylingParams.push(this.defaultSettings.causedByBackgroundColor); } - return finalMessage; - } else if (!Array.isArray(text) || (Array.isArray(text) && (!args || args.length === 0))) { - const processedArgs: IMessageChunk[] = []; - if (args.length > 0) { - args.map((arg) => this.processMessage(arg, true)).forEach((processedArg) => { - processedArg.map((chunk) => processedArgs.push(chunk)); - }); + if (this.defaultSettings.causedByTextColor) { + causedBy.styling.push(EStyles.textColor); + causedBy.stylingParams.push(this.defaultSettings.causedByTextColor); } - return [...this.processMessage(utils.format(text), forceSubline), ...processedArgs]; + + finalMessage.push(causedBy); + finalMessage.push(...this.processMessage(text.cause, true, ...args)); } + return finalMessage; + } + + private processObjects(text: any, forceSubline: boolean, ...args: any[]): IMessageChunk[] { + const processedArgs: IMessageChunk[] = []; + if (args.length > 0) { + args.map((arg) => this.processMessage(arg, true)).forEach((processedArg) => { + processedArg.map((chunk) => processedArgs.push(chunk)); + }); + } + return [...this.processMessage(utils.format(text), forceSubline), ...processedArgs]; + } + private processStringLiterals(text: string[], forceSubline: boolean, ...args: any[]): IMessageChunk[] { const finalMessage: (IMessageChunk & {subLine: boolean})[] = []; let switchedToSublines = forceSubline; @@ -241,7 +239,24 @@ export class Logger { return finalMessage; } + /** + * Parses the message and returns an array of IMessageChunk objects + * the first IMessageChunk object is the main message, the rest are subLines + * @param text - The content to be parsed + * @param args - The arguments to be passed to the content + * @returns IMessageChunk[] + */ + private processMessage(text: any, forceSubline: boolean, ...args: any[]): IMessageChunk[] { + if (!text) text = 'undefined'; + + if (typeof text !== 'object') return this.processStrings(text, forceSubline, ...args); + else if (text instanceof Error) return this.processErrors(text, forceSubline, ...args); + else if (!Array.isArray(text) || (Array.isArray(text) && (!args || args.length === 0))) return this.processObjects(text, forceSubline, ...args); + return this.processStringLiterals(text, forceSubline, ...args); + } + private handleMessage(text: any, level: ELoggerLevel, ...args: any[]): void { + if (this.exited) return; const chunks = this.processMessage(text, false, ...args); const messageChunks: IMessageChunk[] = []; const subLines: IMessageChunk[] = []; @@ -270,8 +285,7 @@ export class Logger { }); // prevents errors where a message would have no content, only sublines - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - if (messageChunks.length === 0 && subLines.length > 0) messageChunks.push(subLines.shift()!); + if (messageChunks.length === 0) messageChunks.push({ content: '', styling: [], stylingParams: [], subLine: false, breaksLine: false }); const message: ILogMessage = { messageChunks, @@ -372,7 +386,10 @@ export class Logger { */ fatal(text: any, ...args: any[]): void { this.handleMessage(text, ELoggerLevel.FATAL, ...args); - if (!this.disableFatalCrash) process.exit(647412); + if (!this.disableFatalCrash && !this.exited) { + this.exited = true; + AutoLogEnd._instance?.callDeconstructors().then(() => { process.exit(647412); }); + } } /** diff --git a/src/main/outputEngines/consoleEngine.ts b/src/main/outputEngines/consoleEngine.ts index 6341bc9..987041b 100755 --- a/src/main/outputEngines/consoleEngine.ts +++ b/src/main/outputEngines/consoleEngine.ts @@ -166,13 +166,16 @@ export class ConsoleEngine extends Engine { lineSizeBuffer += line.content.length; if (arr[index + 1]?.breaksLine || index === arr.length - 1) { const spaceFill = ''.padEnd(process.stdout.columns - lineSizeBuffer - 3); - subLinesBuffer.push(lineBuffer + this.parseTextStyles({ - content: spaceFill, - styling: line.styling, - stylingParams: line.stylingParams, - subLine: true, - breaksLine: false, - }, true, currentMainColor, currentAccentColor)); + const spacePadding = currentMainColor + ? this.parseTextStyles({ + content: spaceFill, + styling: line.styling, + stylingParams: line.stylingParams, + subLine: true, + breaksLine: false, + }, true, currentMainColor, currentAccentColor) + : ''; + subLinesBuffer.push(lineBuffer + spacePadding); lineBuffer = ''; lineSizeBuffer = 0; } diff --git a/src/main/outputEngines/engine.ts b/src/main/outputEngines/engine.ts index 3af90a4..fc342de 100755 --- a/src/main/outputEngines/engine.ts +++ b/src/main/outputEngines/engine.ts @@ -40,6 +40,14 @@ export abstract class Engine { }); } + /** + * Register this Engine to an logger + * @param logger the logger instance to register this Engine + */ + registerLogger(logger: Logger): void { + logger.registerListener(this); + } + /** * Converts a Date object to a string that can be used on logs * @param time Date object with the time to be converted diff --git a/src/main/outputEngines/fileStorageEngine.ts b/src/main/outputEngines/fileStorageEngine.ts index 2373ece..9834168 100755 --- a/src/main/outputEngines/fileStorageEngine.ts +++ b/src/main/outputEngines/fileStorageEngine.ts @@ -22,12 +22,14 @@ export class FileStorageEngine extends Engine { private errorLogFolderPath: string; private fatalLogFolderPath: string; private logQueue: {txt: string, level: ELoggerLevel}[] = []; + private logCallbackQueue: (() => void)[] = []; private logQueueRunning = false; constructor(settings: IFileStorageSettings, ...loggers: Logger[]) { super(settings, ...loggers); if (!settings) throw new Error('settings is required'); this.engineSettings = settings; + if (!this.engineSettings.logFolderPath) throw new Error('logFolderPath is required'); this.engineSettings.logFolderPath = path.resolve(this.engineSettings.logFolderPath); // resolve path to absolute path this.debugLogFolderPath = path.resolve(this.engineSettings.logFolderPath, 'debug'); this.errorLogFolderPath = path.resolve(this.engineSettings.logFolderPath, 'error'); @@ -38,11 +40,10 @@ export class FileStorageEngine extends Engine { AutoLogEnd._instance?.appendDeconstructor(this.uuid, async () => { await this.destroy(); }); // check if logFolderPath exists - if (!this.engineSettings.logFolderPath) throw new Error('logFolderPath is required'); if (fs.existsSync(this.engineSettings.logFolderPath)) { if (!fs.lstatSync(this.engineSettings.logFolderPath).isDirectory()) throw new Error('logFolderPath is not a directory'); // create subfolder if it doesnt exist - if (!fs.existsSync(this.debugLogFolderPath)) fs.mkdirSync(this.debugLogFolderPath, { recursive: true }); + if (this.debug && !fs.existsSync(this.debugLogFolderPath)) fs.mkdirSync(this.debugLogFolderPath, { recursive: true }); if (!fs.existsSync(this.errorLogFolderPath)) fs.mkdirSync(this.errorLogFolderPath, { recursive: true }); if (!fs.existsSync(this.fatalLogFolderPath)) fs.mkdirSync(this.fatalLogFolderPath, { recursive: true }); @@ -52,7 +53,7 @@ export class FileStorageEngine extends Engine { if (fs.existsSync(path.resolve(this.engineSettings.logFolderPath, 'latest.log'))) { fs.renameSync(path.resolve(this.engineSettings.logFolderPath, 'latest.log'), path.resolve(this.engineSettings.logFolderPath, `${timestamp}.log`)); } - if (fs.existsSync(path.resolve(this.debugLogFolderPath, 'latest.log'))) { + if (this.debug && fs.existsSync(path.resolve(this.debugLogFolderPath, 'latest.log'))) { fs.renameSync(path.resolve(this.debugLogFolderPath, 'latest.log'), path.resolve(this.debugLogFolderPath, `${timestamp}.log`)); } if (fs.existsSync(path.resolve(this.errorLogFolderPath, 'latest.log'))) { @@ -91,13 +92,13 @@ export class FileStorageEngine extends Engine { } } else { fs.mkdirSync(this.engineSettings.logFolderPath, { recursive: true }); - fs.mkdirSync(this.debugLogFolderPath, { recursive: true }); + if (this.debug) fs.mkdirSync(this.debugLogFolderPath, { recursive: true }); fs.mkdirSync(this.errorLogFolderPath, { recursive: true }); fs.mkdirSync(this.fatalLogFolderPath, { recursive: true }); } this.latestLogStream = fs.createWriteStream(path.resolve(this.engineSettings.logFolderPath, 'latest.log'), { flags: 'a' }); - if (this.engineSettings.enableDebugLog) this.debugLogStream = fs.createWriteStream(path.resolve(this.debugLogFolderPath, 'latest.log'), { flags: 'a' }); + if (this.debug && this.engineSettings.enableDebugLog) this.debugLogStream = fs.createWriteStream(path.resolve(this.debugLogFolderPath, 'latest.log'), { flags: 'a' }); if (this.engineSettings.enableErrorLog) this.errorLogStream = fs.createWriteStream(path.resolve(this.errorLogFolderPath, 'latest.log'), { flags: 'a' }); if (this.engineSettings.enableFatalLog) this.fatalLogStream = fs.createWriteStream(path.resolve(this.fatalLogFolderPath, 'latest.log'), { flags: 'a' }); } @@ -107,10 +108,12 @@ export class FileStorageEngine extends Engine { * @returns void */ async destroy(): Promise { - this.loggers.forEach((logger) => { - logger.unRegisterListener(this); + return new Promise((resolve) => { + this.runLogQueue(() => { + this.loggers.forEach((logger) => logger.unRegisterListener(this)); + this.closeStreams().then(() => { resolve(); }); + }); }); - await this.closeStreams(); } private parseTextStyles(chunk: IMessageChunk, subLine?: boolean): string { @@ -135,18 +138,20 @@ export class FileStorageEngine extends Engine { } resolve(); }); - } - })); - promises.push(new Promise((resolve) => { - if (this.debugLogStream) { - this.debugLogStream.close(() => { - if (fs.existsSync(path.resolve(this.debugLogFolderPath, 'latest.log'))) { - fs.renameSync(path.resolve(this.debugLogFolderPath, 'latest.log'), path.resolve(this.debugLogFolderPath, `${timestamp}.log`)); - } - resolve(); - }); - } + } else resolve(); })); + if (this.debug) { + promises.push(new Promise((resolve) => { + if (this.debugLogStream) { + this.debugLogStream.close(() => { + if (fs.existsSync(path.resolve(this.debugLogFolderPath, 'latest.log'))) { + fs.renameSync(path.resolve(this.debugLogFolderPath, 'latest.log'), path.resolve(this.debugLogFolderPath, `${timestamp}.log`)); + } + resolve(); + }); + } else resolve(); + })); + } promises.push(new Promise((resolve) => { if (this.errorLogStream) { this.errorLogStream.close(() => { @@ -155,7 +160,7 @@ export class FileStorageEngine extends Engine { } resolve(); }); - } + } else resolve(); })); promises.push(new Promise((resolve) => { if (this.fatalLogStream) { @@ -165,7 +170,7 @@ export class FileStorageEngine extends Engine { } resolve(); }); - } + } else resolve(); })); Promise.all(promises).then(() => { _resolve(); @@ -204,12 +209,15 @@ export class FileStorageEngine extends Engine { await Promise.all(promises); } - private async runLogQueue(): Promise { - if (this.logQueueRunning) return; + private async runLogQueue(finishCallback?: () => void): Promise { if (this.logQueue.length <= 0) { this.logQueueRunning = false; + this.logCallbackQueue.forEach((callback) => callback()); + if (finishCallback) finishCallback(); return; } + if (finishCallback) this.logCallbackQueue.push(finishCallback); + if (this.logQueueRunning) return; this.logQueueRunning = true; const log = this.logQueue.shift(); if (!log) { diff --git a/src/tests/readmeExample.js b/src/tests/readmeExample.js new file mode 100644 index 0000000..98f6d83 --- /dev/null +++ b/src/tests/readmeExample.js @@ -0,0 +1,37 @@ +const { Logger, ConsoleEngine } = require('../../build/src'); + +const logger = new Logger({ + // Adds a basic string prefix + prefixes: ['Logger.JS', + // And a complex prefix + { + // Prefix text + content: 'This prefix has complex colors', + /* This function sets the color of the prefix text, the txt parameter is the content value and it must return a array whos size is equal to the amount of letters in the content value. + NOTE: color doesn't need to be a function, it can be a array, or a string! If it is an array then its size must match the amount of letters of the content value, however, if it is a string then the hex code will be used to paint the whole text */ + color: (txt) => { + // In this example we set a list of hex colors and repeat it to match the amount of letters + const colors = ['#ff5555', '#55ff55', '#5555ff']; + return txt.split('').map((_, i) => { + return colors[i % colors.length]; + }); + }, + // Background color follows the same logic as color, it can be a function, an array or a string + backgroundColor: '#000033', + } + ], + // Disables fatal crashing, so that fatal logs won't immediatly end the process + disableFatalCrash: true, + // Makes the message of the log also be colored + allLineColored: true, +}); + +logger.registerListener(new ConsoleEngine({ + debug: true, +})); + +logger.info('This is an info message'); +logger.warn('This is a warning message'); +logger.error('This is an error message'); +logger.debug('This is a debug message'); +logger.fatal('This is a fatal message'); diff --git a/src/tests/tester.js b/src/tests/tester.js index 67d03d3..8370808 100755 --- a/src/tests/tester.js +++ b/src/tests/tester.js @@ -23,7 +23,7 @@ const logger = new Logger({ return colors[i % colors.length]; }); }, - // background color followes the same logic as color, it can be a function, an array or a string + // background color follows the same logic as color, it can be a function, an array or a string backgroundColor: '#553311', } ], @@ -31,7 +31,6 @@ const logger = new Logger({ disableFatalCrash: true, // makes the message of the log also be colored allLineColored: true, - redactedContent: ['true'], }); // Creates and registers a ConsoleEngine, all logs will now be displayed on the terminal @@ -62,18 +61,18 @@ logger.registerListener(new FileStorageEngine({ })); // Regular usage +logger.debug('Hello, World!'); logger.info('Hello, World!'); logger.warn('Hello, World!'); logger.error('Hello, World!'); logger.fatal('Hello, World!'); -logger.debug('Hello, World!'); // Using template literals -logger.info`Hello, ${'World'}`; -logger.warn`Hello, ${'World'}`; -logger.error`Hello, ${'World'}`; -logger.fatal`Hello, ${'World'}`; -logger.debug`Hello, ${'World'}`; +logger.info`Hello, ${'World'}!`; +logger.warn`Hello, ${'World'}!`; +logger.error`Hello, ${'World'}!`; +logger.fatal`Hello, ${'World'}!`; +logger.debug`Hello, ${'World'}!`; // Logging different data types const myObj = { From e2e62f14bc6e059d98006c324e3d3d2c6efbc2f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lobo=20Metal=C3=BArgico?= <43734867+LoboMetalurgico@users.noreply.github.com> Date: Fri, 14 Jun 2024 18:47:42 -0300 Subject: [PATCH 04/10] (chore): update dependencies --- .eslintrc | 25 +- .prettierignore | 7 - .prettierrc.json | 6 - package-lock.json | 2730 ++++++++++++++++++++++++++------------------- package.json | 27 +- 5 files changed, 1603 insertions(+), 1192 deletions(-) delete mode 100644 .prettierignore delete mode 100644 .prettierrc.json diff --git a/.eslintrc b/.eslintrc index 8e0adb9..34307ab 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,16 +1,19 @@ { "rules": { "@typescript-eslint/ban-ts-ignore": ["off"], - "@typescript-eslint/explicit-function-return-type": ["error"], + "@typescript-eslint/explicit-function-return-type": "error", "@typescript-eslint/interface-name-prefix": ["off"], - "@typescript-eslint/no-explicit-any": ["off"], - "@typescript-eslint/no-unused-expressions": ["error"], + "@typescript-eslint/no-explicit-any": ["off", { "fixToUnknown": true, "ignoreRestArgs": true }], + "@typescript-eslint/no-unused-vars": "warn", + "@typescript-eslint/no-unused-expressions": "error", "@typescript-eslint/no-var-requires": ["off"], - "@typescript-eslint/no-use-before-define": ["error"], + "@typescript-eslint/no-use-before-define": "error", + "@typescript-eslint/no-non-null-assertion": ["off"], "array-bracket-spacing": ["warn", "never"], "capIsNew": ["off"], "comma-dangle": ["error", "always-multiline"], "computed-property-spacing": "warn", + "deprecation/deprecation": "warn", "default-case": ["error", { "commentPattern": "^no default$" }], "eol-last": ["error", "always"], "indent": ["warn", 2, {"SwitchCase": 1}], @@ -25,7 +28,7 @@ "max-len": [ "warn", { - "code": 180, + "code": 250, "ignoreComments": true, "ignoreUrls": true } @@ -40,7 +43,8 @@ "no-template-curly-in-string": "error", "no-unsafe-negation": "error", "no-undef": ["error"], - "no-unused-vars": 1, + "no-unused-vars": "off", + "no-unused-expressions": "off", "no-empty": [ "error", { @@ -50,7 +54,7 @@ "no-console": "off", "no-multi-spaces": "warn", "no-use-before-define": [ - 2, + "off", { "functions": false, "classes": false, @@ -88,8 +92,9 @@ "globals": {}, "parser": "@typescript-eslint/parser", "parserOptions": { - "ecmaVersion": 2020, - "sourceType": "module" + "ecmaVersion": "latest", + "sourceType": "module", + "project": "./tsconfig.json" // <-- Point to your project's "tsconfig.json" or create a new one. }, - "plugins": ["prettier", "@typescript-eslint"] + "plugins": ["deprecation", "@typescript-eslint"] } diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 0c54fa1..0000000 --- a/.prettierignore +++ /dev/null @@ -1,7 +0,0 @@ -# Ignore artifacts: -node_modules/ -package-lock.json -package.json -.eslintrc.json -.eslintignore -.github/ \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index 6a5e10e..0000000 --- a/.prettierrc.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "tabWidth": 2, - "useTabs": false, - "trailingComma": "all", - "printWidth": 100 -} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 71abc26..6ab57c9 100755 --- a/package-lock.json +++ b/package-lock.json @@ -1,31 +1,28 @@ { "name": "@promisepending/logger.js", - "version": "1.1.1", + "version": "2.0.0-ALPHA.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@promisepending/logger.js", - "version": "1.1.1", + "version": "2.0.0-ALPHA.0", "license": "MIT", "dependencies": { - "adm-zip": "^0.5.10", - "chalk": "^4.1.2" + "adm-zip": "^0.5.14", + "chalk": "^5.3.0" }, "devDependencies": { - "@types/adm-zip": "^0.5.0", - "@types/node": "^18.15.3", - "@typescript-eslint/eslint-plugin": "^5.48.2", - "@typescript-eslint/parser": "^5.48.2", - "eslint": "^8.32.0", - "eslint-config-prettier": "^8.6.0", - "eslint-config-standard": "^17.0.0", - "eslint-plugin-import": "^2.27.5", + "@types/adm-zip": "^0.5.5", + "@types/node": "^20.14.2", + "@typescript-eslint/eslint-plugin": "^7.13.0", + "@typescript-eslint/parser": "^7.13.0", + "eslint": "^8.57.0", + "eslint-config-standard": "^17.1.0", + "eslint-plugin-import": "^2.29.1", "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-promise": "^6.1.1", - "prettier": "^2.8.3", - "typescript": "^5.0.2" + "eslint-plugin-promise": "^6.2.0", + "typescript": "^5.4.5" } }, "node_modules/@eslint-community/eslint-utils": { @@ -44,23 +41,23 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", + "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "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.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "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", @@ -76,22 +73,23 @@ } }, "node_modules/@eslint/js": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz", - "integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { @@ -112,9 +110,10 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", "dev": true }, "node_modules/@nodelib/fs.scandir": { @@ -153,20 +152,14 @@ } }, "node_modules/@types/adm-zip": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.0.tgz", - "integrity": "sha512-FCJBJq9ODsQZUNURo5ILAQueuA8WJhRvuihS3ke2iI25mJlfV2LK8jG2Qj2z2AWg8U0FtWWqBHVRetceLskSaw==", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.5.tgz", + "integrity": "sha512-YCGstVMjc4LTY5uK9/obvxBya93axZOVOyf2GSUulADzmLhYE45u2nAssCs/fWBs1Ifq5Vat75JTPwd5XZoPJw==", "dev": true, "dependencies": { "@types/node": "*" } }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -174,44 +167,40 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.16.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.5.tgz", - "integrity": "sha512-seOA34WMo9KB+UA78qaJoCO20RJzZGVXQ5Sh6FWu0g/hfT44nKXnej3/tCQl7FL97idFpBhisLYCTB50S0EirA==", - "dev": true - }, - "node_modules/@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", - "dev": true - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.2.tgz", - "integrity": "sha512-yVrXupeHjRxLDcPKL10sGQ/QlVrA8J5IYOEWVqk0lJaSZP7X5DfnP7Ns3cc74/blmbipQ1htFNVGsHX6wsYm0A==", + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", "dev": true, "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.2", - "@typescript-eslint/type-utils": "5.59.2", - "@typescript-eslint/utils": "5.59.2", - "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "undici-types": "~5.26.4" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.0.tgz", + "integrity": "sha512-FX1X6AF0w8MdVFLSdqwqN/me2hyhuQg4ykN6ZpVhh1ij/80pTvDKclX1sZB9iqex8SjQfVhwMKs3JtnnMLzG9w==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/type-utils": "7.13.0", + "@typescript-eslint/utils": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -220,25 +209,26 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.2.tgz", - "integrity": "sha512-uq0sKyw6ao1iFOZZGk9F8Nro/8+gfB5ezl1cA06SrqbgJAt0SRoFhb9pXaHvkrxUpZaoLxt8KlovHNk8Gp6/HQ==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.0.tgz", + "integrity": "sha512-EjMfl69KOS9awXXe83iRN7oIEXy9yYdqWfqdrFAYAAr6syP8eLEFI7ZE4939antx2mNgPRW/o1ybm2SFYkbTVA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.59.2", - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/typescript-estree": "5.59.2", + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/typescript-estree": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", "debug": "^4.3.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -247,16 +237,16 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.2.tgz", - "integrity": "sha512-dB1v7ROySwQWKqQ8rEWcdbTsFjh2G0vn8KUyvTXdPoyzSL6lLGkiXEV5CvpJsEe9xIdKV+8Zqb7wif2issoOFA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.0.tgz", + "integrity": "sha512-ZrMCe1R6a01T94ilV13egvcnvVJ1pxShkE0+NDjDzH4nvG1wXpwsVI5bZCvE7AEDH1mXEx5tJSVR68bLgG7Dng==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/visitor-keys": "5.59.2" + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -264,25 +254,25 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.2.tgz", - "integrity": "sha512-b1LS2phBOsEy/T381bxkkywfQXkV1dWda/z0PhnIy3bC5+rQWQDS7fk9CSpcXBccPY27Z6vBEuaPBCKCgYezyQ==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.0.tgz", + "integrity": "sha512-xMEtMzxq9eRkZy48XuxlBFzpVMDurUAfDu5Rz16GouAtXm0TaAoTFzqWUFPPuQYXI/CDaH/Bgx/fk/84t/Bc9A==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.59.2", - "@typescript-eslint/utils": "5.59.2", + "@typescript-eslint/typescript-estree": "7.13.0", + "@typescript-eslint/utils": "7.13.0", "debug": "^4.3.4", - "tsutils": "^3.21.0" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "*" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -291,12 +281,12 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.2.tgz", - "integrity": "sha512-LbJ/HqoVs2XTGq5shkiKaNTuVv5tTejdHgfdjqRUGdYhjW1crm/M7og2jhVskMt8/4wS3T1+PfFvL1K3wqYj4w==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.0.tgz", + "integrity": "sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -304,21 +294,22 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.2.tgz", - "integrity": "sha512-+j4SmbwVmZsQ9jEyBMgpuBD0rKwi9RxRpjX71Brr73RsYnEr3Lt5QZ624Bxphp8HUkSKfqGnPJp1kA5nl0Sh7Q==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.0.tgz", + "integrity": "sha512-cAvBvUoobaoIcoqox1YatXOnSl3gx92rCZoMRPzMNisDiM12siGilSM4+dJAekuuHTibI2hVC2fYK79iSFvWjw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/visitor-keys": "5.59.2", + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -330,53 +321,79 @@ } } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@typescript-eslint/utils": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.2.tgz", - "integrity": "sha512-kSuF6/77TZzyGPhGO4uVp+f0SBoYxCDf+lW3GKhtKru/L8k/Hd7NFQxyWUeY7Z/KGB2C6Fe3yf2vVi4V9TsCSQ==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.0.tgz", + "integrity": "sha512-jceD8RgdKORVnB4Y6BqasfIkFhl4pajB1wVxrF4akxD2QPM8GNYjgGwEzYS+437ewlqqrg7Dw+6dhdpjMpeBFQ==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.2", - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/typescript-estree": "5.59.2", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/typescript-estree": "7.13.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.2.tgz", - "integrity": "sha512-EEpsO8m3RASrKAHI9jpavNv9NlEUebV4qmF1OWxSTtKSFBpC1NCmWazDQHFivRf0O1DV11BA645yrLEVQ0/Lig==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.0.tgz", + "integrity": "sha512-nxn+dozQx+MK61nn/JP+M4eCkHDSxSLDpgE3WcQo0+fkjEolnaB5jswvIKC4K56By8MMgIho7f1PVxERHEo8rw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.2", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/types": "7.13.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "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.12.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", + "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -395,11 +412,11 @@ } }, "node_modules/adm-zip": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", - "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", + "version": "0.5.14", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.14.tgz", + "integrity": "sha512-DnyqqifT4Jrcvb8USYjp6FHtBpEIz1mnXu6pTRHZ0RL69LbQYiO+0lDFg5+OKA7U29oWSs3a/i8fhn8ZcceIWg==", "engines": { - "node": ">=6.0" + "node": ">=12.0" } }, "node_modules/ajv": { @@ -431,6 +448,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -448,28 +466,32 @@ "dev": true }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" }, "engines": { @@ -488,15 +510,35 @@ "node": ">=8" } }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -507,14 +549,14 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -524,11 +566,36 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -553,12 +620,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -575,13 +642,19 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -597,15 +670,11 @@ } }, "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "engines": { - "node": ">=10" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" @@ -615,6 +684,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -625,7 +695,8 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/concat-map": { "version": "0.0.1", @@ -647,10 +718,61 @@ "node": ">= 8" } }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -670,12 +792,30 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -711,45 +851,57 @@ } }, "node_modules/es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -758,27 +910,60 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "node_modules/es-to-primitive": { @@ -811,27 +996,28 @@ } }, "node_modules/eslint": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz", - "integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.40.0", - "@humanwhocodes/config-array": "^0.11.8", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.5.2", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -839,22 +1025,19 @@ "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", + "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "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" }, "bin": { @@ -867,22 +1050,10 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-config-prettier": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", - "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, "node_modules/eslint-config-standard": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz", - "integrity": "sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==", + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", + "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", "dev": true, "funding": [ { @@ -898,22 +1069,25 @@ "url": "https://feross.org/support" } ], + "engines": { + "node": ">=12.0.0" + }, "peerDependencies": { "eslint": "^8.0.1", "eslint-plugin-import": "^2.25.2", - "eslint-plugin-n": "^15.0.0", + "eslint-plugin-n": "^15.0.0 || ^16.0.0 ", "eslint-plugin-promise": "^6.0.0" } }, "node_modules/eslint-import-resolver-node": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, "dependencies": { "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, "node_modules/eslint-import-resolver-node/node_modules/debug": { @@ -998,26 +1172,28 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.27.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", - "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "dev": true, "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.7.4", - "has": "^1.0.3", - "is-core-module": "^2.11.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.values": "^1.1.6", - "resolve": "^1.22.1", - "semver": "^6.3.0", - "tsconfig-paths": "^3.14.1" + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" @@ -1048,9 +1224,9 @@ } }, "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -1146,58 +1322,43 @@ } }, "node_modules/eslint-plugin-node/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" } }, - "node_modules/eslint-plugin-prettier": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", - "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", - "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.0" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "eslint": ">=7.28.0", - "prettier": ">=2.0.0" - }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } - } - }, "node_modules/eslint-plugin-promise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", - "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.2.0.tgz", + "integrity": "sha512-QmAqwizauvnKOlifxyDj2ObfULpHQawlg/zQdgEixur9vl0CvZGv/LCJV2rtj3210QCoeGBzVMfMXqGAOr/4fA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=8.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-utils": { @@ -1230,9 +1391,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1241,38 +1402,29 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=10" }, "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, "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.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "dependencies": { - "acorn": "^8.8.0", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" }, @@ -1295,15 +1447,6 @@ "node": ">=0.10" } }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -1316,7 +1459,7 @@ "node": ">=4.0" } }, - "node_modules/esrecurse/node_modules/estraverse": { + "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", @@ -1325,15 +1468,6 @@ "node": ">=4.0" } }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -1349,16 +1483,10 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -1417,9 +1545,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -1479,21 +1607,24 @@ "dev": true }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" }, "engines": { "node": ">= 0.4" @@ -1512,27 +1643,33 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -1574,9 +1711,9 @@ } }, "node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -1589,12 +1726,13 @@ } }, "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, "dependencies": { - "define-properties": "^1.1.3" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -1635,24 +1773,12 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -1666,26 +1792,27 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true, "engines": { "node": ">= 0.4" @@ -1707,12 +1834,12 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -1721,10 +1848,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" @@ -1772,13 +1911,13 @@ "dev": true }, "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { @@ -1786,14 +1925,16 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1840,12 +1981,27 @@ } }, "node_modules/is-core-module": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", - "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", "dev": true, "dependencies": { - "has": "^1.0.3" + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1888,9 +2044,9 @@ } }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "engines": { "node": ">= 0.4" @@ -1949,12 +2105,15 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1991,16 +2150,12 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -2021,22 +2176,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, - "node_modules/js-sdsl": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", - "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2107,18 +2258,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -2129,12 +2268,12 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -2174,16 +2313,10 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2199,13 +2332,13 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -2216,15 +2349,47 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -2243,9 +2408,9 @@ } }, "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.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "dependencies": { "deep-is": "^0.1.3", @@ -2253,7 +2418,7 @@ "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -2355,6 +2520,15 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -2364,37 +2538,10 @@ "node": ">= 0.8.0" } }, - "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" @@ -2421,14 +2568,15 @@ ] }, "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -2450,12 +2598,12 @@ } }, "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { - "is-core-module": "^2.11.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -2523,28 +2671,46 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -2552,6 +2718,38 @@ "node": ">=10" } }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -2574,14 +2772,18 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2597,14 +2799,15 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -2614,28 +2817,31 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2678,6 +2884,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -2715,10 +2922,22 @@ "node": ">=8.0" } }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "dependencies": { "@types/json5": "^0.0.29", @@ -2727,27 +2946,6 @@ "strip-bom": "^3.0.0" } }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -2772,31 +2970,90 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=12.20" + "node": ">=14.17" } }, "node_modules/unbox-primitive": { @@ -2814,6 +3071,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -2855,17 +3118,16 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -2875,9 +3137,9 @@ } }, "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==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -2889,12 +3151,6 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -2919,20 +3175,20 @@ } }, "@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", + "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", "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.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "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", @@ -2942,19 +3198,19 @@ } }, "@eslint/js": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz", - "integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true }, "@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" } }, @@ -2965,9 +3221,9 @@ "dev": true }, "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, "@nodelib/fs.scandir": { @@ -2997,20 +3253,14 @@ } }, "@types/adm-zip": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.0.tgz", - "integrity": "sha512-FCJBJq9ODsQZUNURo5ILAQueuA8WJhRvuihS3ke2iI25mJlfV2LK8jG2Qj2z2AWg8U0FtWWqBHVRetceLskSaw==", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.5.tgz", + "integrity": "sha512-YCGstVMjc4LTY5uK9/obvxBya93axZOVOyf2GSUulADzmLhYE45u2nAssCs/fWBs1Ifq5Vat75JTPwd5XZoPJw==", "dev": true, "requires": { "@types/node": "*" } }, - "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -3018,120 +3268,140 @@ "dev": true }, "@types/node": { - "version": "18.16.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.5.tgz", - "integrity": "sha512-seOA34WMo9KB+UA78qaJoCO20RJzZGVXQ5Sh6FWu0g/hfT44nKXnej3/tCQl7FL97idFpBhisLYCTB50S0EirA==", - "dev": true - }, - "@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", - "dev": true + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "dev": true, + "requires": { + "undici-types": "~5.26.4" + } }, "@typescript-eslint/eslint-plugin": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.2.tgz", - "integrity": "sha512-yVrXupeHjRxLDcPKL10sGQ/QlVrA8J5IYOEWVqk0lJaSZP7X5DfnP7Ns3cc74/blmbipQ1htFNVGsHX6wsYm0A==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.0.tgz", + "integrity": "sha512-FX1X6AF0w8MdVFLSdqwqN/me2hyhuQg4ykN6ZpVhh1ij/80pTvDKclX1sZB9iqex8SjQfVhwMKs3JtnnMLzG9w==", "dev": true, "requires": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.2", - "@typescript-eslint/type-utils": "5.59.2", - "@typescript-eslint/utils": "5.59.2", - "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/type-utils": "7.13.0", + "@typescript-eslint/utils": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/parser": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.2.tgz", - "integrity": "sha512-uq0sKyw6ao1iFOZZGk9F8Nro/8+gfB5ezl1cA06SrqbgJAt0SRoFhb9pXaHvkrxUpZaoLxt8KlovHNk8Gp6/HQ==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.0.tgz", + "integrity": "sha512-EjMfl69KOS9awXXe83iRN7oIEXy9yYdqWfqdrFAYAAr6syP8eLEFI7ZE4939antx2mNgPRW/o1ybm2SFYkbTVA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.59.2", - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/typescript-estree": "5.59.2", + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/typescript-estree": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.2.tgz", - "integrity": "sha512-dB1v7ROySwQWKqQ8rEWcdbTsFjh2G0vn8KUyvTXdPoyzSL6lLGkiXEV5CvpJsEe9xIdKV+8Zqb7wif2issoOFA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.0.tgz", + "integrity": "sha512-ZrMCe1R6a01T94ilV13egvcnvVJ1pxShkE0+NDjDzH4nvG1wXpwsVI5bZCvE7AEDH1mXEx5tJSVR68bLgG7Dng==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/visitor-keys": "5.59.2" + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0" } }, "@typescript-eslint/type-utils": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.2.tgz", - "integrity": "sha512-b1LS2phBOsEy/T381bxkkywfQXkV1dWda/z0PhnIy3bC5+rQWQDS7fk9CSpcXBccPY27Z6vBEuaPBCKCgYezyQ==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.0.tgz", + "integrity": "sha512-xMEtMzxq9eRkZy48XuxlBFzpVMDurUAfDu5Rz16GouAtXm0TaAoTFzqWUFPPuQYXI/CDaH/Bgx/fk/84t/Bc9A==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.59.2", - "@typescript-eslint/utils": "5.59.2", + "@typescript-eslint/typescript-estree": "7.13.0", + "@typescript-eslint/utils": "7.13.0", "debug": "^4.3.4", - "tsutils": "^3.21.0" + "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.2.tgz", - "integrity": "sha512-LbJ/HqoVs2XTGq5shkiKaNTuVv5tTejdHgfdjqRUGdYhjW1crm/M7og2jhVskMt8/4wS3T1+PfFvL1K3wqYj4w==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.0.tgz", + "integrity": "sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.2.tgz", - "integrity": "sha512-+j4SmbwVmZsQ9jEyBMgpuBD0rKwi9RxRpjX71Brr73RsYnEr3Lt5QZ624Bxphp8HUkSKfqGnPJp1kA5nl0Sh7Q==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.0.tgz", + "integrity": "sha512-cAvBvUoobaoIcoqox1YatXOnSl3gx92rCZoMRPzMNisDiM12siGilSM4+dJAekuuHTibI2hVC2fYK79iSFvWjw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/visitor-keys": "5.59.2", + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/visitor-keys": "7.13.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } } }, "@typescript-eslint/utils": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.2.tgz", - "integrity": "sha512-kSuF6/77TZzyGPhGO4uVp+f0SBoYxCDf+lW3GKhtKru/L8k/Hd7NFQxyWUeY7Z/KGB2C6Fe3yf2vVi4V9TsCSQ==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.0.tgz", + "integrity": "sha512-jceD8RgdKORVnB4Y6BqasfIkFhl4pajB1wVxrF4akxD2QPM8GNYjgGwEzYS+437ewlqqrg7Dw+6dhdpjMpeBFQ==", "dev": true, "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.2", - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/typescript-estree": "5.59.2", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.13.0", + "@typescript-eslint/types": "7.13.0", + "@typescript-eslint/typescript-estree": "7.13.0" } }, "@typescript-eslint/visitor-keys": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.2.tgz", - "integrity": "sha512-EEpsO8m3RASrKAHI9jpavNv9NlEUebV4qmF1OWxSTtKSFBpC1NCmWazDQHFivRf0O1DV11BA645yrLEVQ0/Lig==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.0.tgz", + "integrity": "sha512-nxn+dozQx+MK61nn/JP+M4eCkHDSxSLDpgE3WcQo0+fkjEolnaB5jswvIKC4K56By8MMgIho7f1PVxERHEo8rw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.2", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/types": "7.13.0", + "eslint-visitor-keys": "^3.4.3" } }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "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.12.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", + "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", "dev": true }, "acorn-jsx": { @@ -3142,9 +3412,9 @@ "requires": {} }, "adm-zip": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", - "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==" + "version": "0.5.14", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.14.tgz", + "integrity": "sha512-DnyqqifT4Jrcvb8USYjp6FHtBpEIz1mnXu6pTRHZ0RL69LbQYiO+0lDFg5+OKA7U29oWSs3a/i8fhn8ZcceIWg==" }, "ajv": { "version": "6.12.6", @@ -3168,6 +3438,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "requires": { "color-convert": "^2.0.1" } @@ -3179,25 +3450,26 @@ "dev": true }, "array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" } }, "array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" } }, @@ -3207,35 +3479,68 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, + "array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + } + }, "array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" } }, "array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" } }, + "arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + } + }, "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "requires": { + "possible-typed-array-names": "^1.0.0" + } }, "balanced-match": { "version": "1.0.2", @@ -3254,12 +3559,12 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "builtins": { @@ -3273,13 +3578,16 @@ } }, "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" } }, "callsites": { @@ -3289,18 +3597,15 @@ "dev": true }, "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==" }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { "color-name": "~1.1.4" } @@ -3308,7 +3613,8 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "concat-map": { "version": "0.0.1", @@ -3327,10 +3633,43 @@ "which": "^2.0.1" } }, + "data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "requires": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "requires": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dev": true, "requires": { "ms": "2.1.2" @@ -3342,12 +3681,24 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + } + }, "define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "requires": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } @@ -3371,65 +3722,101 @@ } }, "es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dev": true, "requires": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" + "which-typed-array": "^1.1.15" + } + }, + "es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.4" + } + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true + }, + "es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "requires": { + "es-errors": "^1.3.0" } }, "es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, "requires": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" } }, "es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, "requires": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "es-to-primitive": { @@ -3450,27 +3837,28 @@ "dev": true }, "eslint": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz", - "integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.40.0", - "@humanwhocodes/config-array": "^0.11.8", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.5.2", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -3478,66 +3866,50 @@ "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", + "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "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" }, "dependencies": { - "eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true } } }, - "eslint-config-prettier": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", - "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", - "dev": true, - "requires": {} - }, "eslint-config-standard": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz", - "integrity": "sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==", + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", + "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", "dev": true, "requires": {} }, "eslint-import-resolver-node": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, "requires": { "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" }, "dependencies": { "debug": { @@ -3602,26 +3974,28 @@ } }, "eslint-plugin-import": { - "version": "2.27.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", - "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "dev": true, "requires": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.7.4", - "has": "^1.0.3", - "is-core-module": "^2.11.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.values": "^1.1.6", - "resolve": "^1.22.1", - "semver": "^6.3.0", - "tsconfig-paths": "^3.14.1" + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" }, "dependencies": { "debug": { @@ -3643,9 +4017,9 @@ } }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -3707,37 +4081,28 @@ "dev": true }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } }, - "eslint-plugin-prettier": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", - "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, "eslint-plugin-promise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", - "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.2.0.tgz", + "integrity": "sha512-QmAqwizauvnKOlifxyDj2ObfULpHQawlg/zQdgEixur9vl0CvZGv/LCJV2rtj3210QCoeGBzVMfMXqGAOr/4fA==", "dev": true, "requires": {} }, "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "requires": { "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "estraverse": "^5.2.0" } }, "eslint-utils": { @@ -3760,18 +4125,18 @@ } }, "eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "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.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "requires": { - "acorn": "^8.8.0", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } @@ -3783,14 +4148,6 @@ "dev": true, "requires": { "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } } }, "esrecurse": { @@ -3800,20 +4157,12 @@ "dev": true, "requires": { "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } } }, "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true }, "esutils": { @@ -3828,16 +4177,10 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -3889,9 +4232,9 @@ } }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "requires": { "to-regex-range": "^5.0.1" @@ -3939,21 +4282,21 @@ "dev": true }, "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true }, "function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" } }, "functions-have-names": { @@ -3963,24 +4306,27 @@ "dev": true }, "get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" } }, "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" } }, "glob": { @@ -4007,21 +4353,22 @@ } }, "globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "requires": { "type-fest": "^0.20.2" } }, "globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, "requires": { - "define-properties": "^1.1.3" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" } }, "globby": { @@ -4047,21 +4394,12 @@ "get-intrinsic": "^1.1.3" } }, - "grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, "has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -4071,21 +4409,22 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "requires": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" } }, "has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true }, "has-symbols": { @@ -4095,18 +4434,27 @@ "dev": true }, "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "requires": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" + } + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" } }, "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true }, "import-fresh": { @@ -4142,25 +4490,24 @@ "dev": true }, "internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "requires": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "hasown": "^2.0.0", "side-channel": "^1.0.4" } }, "is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "requires": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" } }, "is-bigint": { @@ -4189,12 +4536,21 @@ "dev": true }, "is-core-module": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", - "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "requires": { + "hasown": "^2.0.0" + } + }, + "is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", "dev": true, "requires": { - "has": "^1.0.3" + "is-typed-array": "^1.1.13" } }, "is-date-object": { @@ -4222,9 +4578,9 @@ } }, "is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true }, "is-number": { @@ -4259,12 +4615,12 @@ } }, "is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "requires": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" } }, "is-string": { @@ -4286,16 +4642,12 @@ } }, "is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "which-typed-array": "^1.1.14" } }, "is-weakref": { @@ -4307,18 +4659,18 @@ "call-bind": "^1.0.2" } }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, - "js-sdsl": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", - "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", - "dev": true - }, "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -4374,15 +4726,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -4390,12 +4733,12 @@ "dev": true }, "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dev": true, "requires": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" } }, @@ -4426,16 +4769,10 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, "object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true }, "object-keys": { @@ -4445,26 +4782,49 @@ "dev": true }, "object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" } }, + "object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + } + }, + "object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + } + }, "object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "once": { @@ -4477,9 +4837,9 @@ } }, "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "requires": { "deep-is": "^0.1.3", @@ -4487,7 +4847,7 @@ "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "word-wrap": "^1.2.5" } }, "p-limit": { @@ -4553,31 +4913,22 @@ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, + "possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, - "prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true }, "queue-microtask": { @@ -4587,14 +4938,15 @@ "dev": true }, "regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" } }, "regexpp": { @@ -4604,12 +4956,12 @@ "dev": true }, "resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "requires": { - "is-core-module": "^2.11.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } @@ -4644,24 +4996,59 @@ "queue-microtask": "^1.2.2" } }, + "safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + } + }, "safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" } }, "semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true + }, + "set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + } + }, + "set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" } }, "shebang-command": { @@ -4680,14 +5067,15 @@ "dev": true }, "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" } }, "slash": { @@ -4697,36 +5085,37 @@ "dev": true }, "string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" } }, "string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "strip-ansi": { @@ -4754,6 +5143,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "requires": { "has-flag": "^4.0.0" } @@ -4779,10 +5169,17 @@ "is-number": "^7.0.0" } }, + "ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "requires": {} + }, "tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "requires": { "@types/json5": "^0.0.29", @@ -4791,21 +5188,6 @@ "strip-bom": "^3.0.0" } }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -4821,21 +5203,62 @@ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true }, + "typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + } + }, + "typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + } + }, + "typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + } + }, "typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, "requires": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" } }, "typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true }, "unbox-primitive": { @@ -4850,6 +5273,12 @@ "which-boxed-primitive": "^1.0.2" } }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -4882,23 +5311,22 @@ } }, "which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.2" } }, "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==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true }, "wrappy": { @@ -4907,12 +5335,6 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 591ac8d..024e780 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@promisepending/logger.js", - "version": "1.1.1", + "version": "2.0.0-ALPHA.0", "description": "A better logger", "main": "build/index.js", "types": "src/main/index.ts", @@ -25,22 +25,19 @@ }, "homepage": "https://github.com/PromisePending/logger.js#readme", "dependencies": { - "adm-zip": "^0.5.10", - "chalk": "^4.1.2" + "adm-zip": "^0.5.14", + "chalk": "^5.3.0" }, "devDependencies": { - "@types/adm-zip": "^0.5.0", - "@types/node": "^18.15.3", - "@typescript-eslint/eslint-plugin": "^5.48.2", - "@typescript-eslint/parser": "^5.48.2", - "eslint": "^8.32.0", - "eslint-config-prettier": "^8.6.0", - "eslint-config-standard": "^17.0.0", - "eslint-plugin-import": "^2.27.5", + "@types/adm-zip": "^0.5.5", + "@types/node": "^20.14.2", + "@typescript-eslint/eslint-plugin": "^7.13.0", + "@typescript-eslint/parser": "^7.13.0", + "eslint": "^8.57.0", + "eslint-config-standard": "^17.1.0", + "eslint-plugin-import": "^2.29.1", "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-promise": "^6.1.1", - "prettier": "^2.8.3", - "typescript": "^5.0.2" + "eslint-plugin-promise": "^6.2.0", + "typescript": "^5.4.5" } } From be9abcc804507de6500293f68ef6bdfaf81745be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lobo=20Metal=C3=BArgico?= <43734867+LoboMetalurgico@users.noreply.github.com> Date: Fri, 14 Jun 2024 18:57:22 -0300 Subject: [PATCH 05/10] (chore): fix eslint errors --- .eslintrc | 1 + package-lock.json | 39 ++++++++++++++++++++++++++++++ package.json | 5 +++- src/main/interfaces/ILogMessage.ts | 2 +- 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/.eslintrc b/.eslintrc index 34307ab..816edbb 100644 --- a/.eslintrc +++ b/.eslintrc @@ -9,6 +9,7 @@ "@typescript-eslint/no-var-requires": ["off"], "@typescript-eslint/no-use-before-define": "error", "@typescript-eslint/no-non-null-assertion": ["off"], + "@typescript-eslint/no-duplicate-enum-values": "off", "array-bracket-spacing": ["warn", "never"], "capIsNew": ["off"], "comma-dangle": ["error", "always-multiline"], diff --git a/package-lock.json b/package-lock.json index 6ab57c9..43ad707 100755 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@typescript-eslint/parser": "^7.13.0", "eslint": "^8.57.0", "eslint-config-standard": "^17.1.0", + "eslint-plugin-deprecation": "^3.0.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^6.2.0", @@ -1125,6 +1126,21 @@ "ms": "^2.1.1" } }, + "node_modules/eslint-plugin-deprecation": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-deprecation/-/eslint-plugin-deprecation-3.0.0.tgz", + "integrity": "sha512-JuVLdNg/uf0Adjg2tpTyYoYaMbwQNn/c78P1HcccokvhtRphgnRjZDKmhlxbxYptppex03zO76f97DD/yQHv7A==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^7.0.0", + "ts-api-utils": "^1.3.0", + "tslib": "^2.3.1" + }, + "peerDependencies": { + "eslint": "^8.0.0", + "typescript": "^4.2.4 || ^5.0.0" + } + }, "node_modules/eslint-plugin-es": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", @@ -2946,6 +2962,12 @@ "strip-bom": "^3.0.0" } }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -3943,6 +3965,17 @@ } } }, + "eslint-plugin-deprecation": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-deprecation/-/eslint-plugin-deprecation-3.0.0.tgz", + "integrity": "sha512-JuVLdNg/uf0Adjg2tpTyYoYaMbwQNn/c78P1HcccokvhtRphgnRjZDKmhlxbxYptppex03zO76f97DD/yQHv7A==", + "dev": true, + "requires": { + "@typescript-eslint/utils": "^7.0.0", + "ts-api-utils": "^1.3.0", + "tslib": "^2.3.1" + } + }, "eslint-plugin-es": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", @@ -5188,6 +5221,12 @@ "strip-bom": "^3.0.0" } }, + "tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index 024e780..d28d3d3 100755 --- a/package.json +++ b/package.json @@ -7,8 +7,10 @@ "scripts": { "build": "npx tsc -p .", "pdeploy": "node scripts/prepareDeploy.js", + "pretest": "npm run build", "test": "node src/tests/tester.js", - "pretest": "npm run build" + "eslint": "eslint ./src", + "eslint:fix": "eslint ./src --fix" }, "repository": { "type": "git", @@ -35,6 +37,7 @@ "@typescript-eslint/parser": "^7.13.0", "eslint": "^8.57.0", "eslint-config-standard": "^17.1.0", + "eslint-plugin-deprecation": "^3.0.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^6.2.0", diff --git a/src/main/interfaces/ILogMessage.ts b/src/main/interfaces/ILogMessage.ts index e31230a..8a6d36d 100755 --- a/src/main/interfaces/ILogMessage.ts +++ b/src/main/interfaces/ILogMessage.ts @@ -1,4 +1,4 @@ -import { ILogSettings, IPrefix } from "./ILoggerOption"; +import { ILogSettings, IPrefix } from './ILoggerOption'; export enum EStyles { bold = 1, From 2a7f01e9fa1bf653943e9eac572c62ccd38cc980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lobo=20Metal=C3=BArgico?= <43734867+LoboMetalurgico@users.noreply.github.com> Date: Fri, 14 Jun 2024 18:58:21 -0300 Subject: [PATCH 06/10] (fix): downgrade chalk, semver --- package-lock.json | 68 +++++++++++++---------------------------------- package.json | 4 +-- 2 files changed, 21 insertions(+), 51 deletions(-) diff --git a/package-lock.json b/package-lock.json index 43ad707..8b8e384 100755 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "MIT", "dependencies": { "adm-zip": "^0.5.14", - "chalk": "^5.3.0" + "chalk": "^4.1.2" }, "devDependencies": { "@types/adm-zip": "^0.5.5", @@ -449,7 +449,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -671,11 +670,15 @@ } }, "node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "node": ">=10" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" @@ -685,7 +688,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -696,8 +698,7 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/concat-map": { "version": "0.0.1", @@ -1418,22 +1419,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -1808,7 +1793,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -2900,7 +2884,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -3460,7 +3443,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { "color-convert": "^2.0.1" } @@ -3619,15 +3601,18 @@ "dev": true }, "chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==" + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "requires": { "color-name": "~1.1.4" } @@ -3635,8 +3620,7 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "concat-map": { "version": "0.0.1", @@ -3902,18 +3886,6 @@ "optionator": "^0.9.3", "strip-ansi": "^6.0.1", "text-table": "^0.2.0" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - } } }, "eslint-config-standard": { @@ -4442,8 +4414,7 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "has-property-descriptors": { "version": "1.0.2", @@ -5176,7 +5147,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "requires": { "has-flag": "^4.0.0" } diff --git a/package.json b/package.json index d28d3d3..5ba68f7 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@promisepending/logger.js", - "version": "2.0.0-ALPHA.0", + "version": "2.0.0-alpha.0", "description": "A better logger", "main": "build/index.js", "types": "src/main/index.ts", @@ -28,7 +28,7 @@ "homepage": "https://github.com/PromisePending/logger.js#readme", "dependencies": { "adm-zip": "^0.5.14", - "chalk": "^5.3.0" + "chalk": "^4.1.2" }, "devDependencies": { "@types/adm-zip": "^0.5.5", From 9e43b2a42f35f4cc3567c16ff0a793caab69b0dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lobo=20Metal=C3=BArgico?= <43734867+LoboMetalurgico@users.noreply.github.com> Date: Fri, 14 Jun 2024 20:03:03 -0300 Subject: [PATCH 07/10] (chore): update keywords --- package.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/package.json b/package.json index 5ba68f7..17651fe 100755 --- a/package.json +++ b/package.json @@ -17,7 +17,19 @@ "url": "git+https://github.com/PromisePending/logger.js.git" }, "keywords": [ + "console", "logger", + "error", + "stacktrace", + "warn", + "info", + "debug", + "elegant", + "format", + "formatter", + "color", + "colors", + "error-handling", "typescript" ], "author": "PromisePending", From 3084db1527006b0dae2e2ad9444f518637443355 Mon Sep 17 00:00:00 2001 From: Space_Fox <44732812+emanuelfranklyn@users.noreply.github.com> Date: Thu, 27 Jun 2024 00:28:51 -0300 Subject: [PATCH 08/10] (feat): Publish to NPM (alpha), (beta), and (latest) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit updates the packagePublish.yml workflow to include separate steps for publishing to NPM based on the version tag. It introduces three new steps: Publish to npm (alpha), Publish to npm (beta), and Publish to npm (latest). The step Publish to npm (alpha) is triggered when the version contains '-alpha', and it publishes the package with the 'alpha' tag. Similarly, the step Publish to npm (beta) is triggered when the version contains '-beta', and it publishes the package with the 'beta' tag. Finally, the step Publish to npm (latest) is triggered when the version does not contain '-alpha' or '-beta', and it publishes the package without any tag. This change improves the release process by allowing different versions of the package to be published with appropriate tags. Co-authored-by: Lobo Metalúrgico <43734867+LoboMetalurgico@users.noreply.github.com> --- .github/workflows/packagePublish.yml | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/.github/workflows/packagePublish.yml b/.github/workflows/packagePublish.yml index 62906c1..a775a05 100644 --- a/.github/workflows/packagePublish.yml +++ b/.github/workflows/packagePublish.yml @@ -1,4 +1,4 @@ -name: Publish API to NPM +name: Publish to NPM on: push: @@ -45,8 +45,23 @@ jobs: - name: Prepare to publish run: npm run pdeploy - - name: Publish to npm + - name: Publish to npm (alpha) + if: ${{ contains(steps.current_version.outputs.version, '-alpha') }} working-directory: ./build - run: npm publish --access=public + run: npm publish --provenance --access=public --tag alpha + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Publish to npm (beta) + if: ${{ contains(steps.current_version.outputs.version, '-beta') }} + working-directory: ./build + run: npm publish --provenance --access=public --tag beta + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Publish to npm (latest) + if: ${{ !contains(steps.current_version.outputs.version, '-alpha') && !contains(steps.current_version.outputs.version, '-beta') }} + working-directory: ./build + run: npm publish --provenance --access=public env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} From b8c6fd6abba3213a868b12bbb2f33366693303fa Mon Sep 17 00:00:00 2001 From: Space_Fox <44732812+emanuelfranklyn@users.noreply.github.com> Date: Thu, 27 Jun 2024 00:35:28 -0300 Subject: [PATCH 09/10] (feat): backwards compatibility, improve highligh matching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Lobo Metalúrgico <43734867+LoboMetalurgico@users.noreply.github.com> --- src/main/logger.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/logger.ts b/src/main/logger.ts index 6bed796..4e02ab0 100755 --- a/src/main/logger.ts +++ b/src/main/logger.ts @@ -5,6 +5,7 @@ import utils from 'util'; import { IDefault } from './interfaces/IDefault'; import Standard from './defaults/standard'; import { AutoLogEnd } from './autoLogEnd'; +import { ConsoleEngine } from './outputEngines'; /** * Main class that will process logs before automaticly sending then to registered Engines @@ -12,7 +13,7 @@ import { AutoLogEnd } from './autoLogEnd'; export class Logger { // constants private static splitCharsNonScape = [' ', ',', ':', '<', '>']; - private static splitCharsScape = ['*', '(', ')', '[', ']']; + private static splitCharsScape = ['*', '(', ')', '[', ']', '/', '\\']; private static splitChars = [...Logger.splitCharsNonScape, ...Logger.splitCharsScape]; // private fields @@ -257,6 +258,12 @@ export class Logger { private handleMessage(text: any, level: ELoggerLevel, ...args: any[]): void { if (this.exited) return; + + if (this.logListeners.length === 0) { + this.registerListener(new ConsoleEngine({ debug: process.env.NODE_ENV !== 'production' })); + this.warn('No log listeners were registered, a ConsoleEngine was registered automatically.\nThis is a backard compatibility feature and should be avoided.'); + } + const chunks = this.processMessage(text, false, ...args); const messageChunks: IMessageChunk[] = []; const subLines: IMessageChunk[] = []; From 690bc6b27dbf3b879d8d26f5d380af580d96bb40 Mon Sep 17 00:00:00 2001 From: Space_Fox <44732812+emanuelfranklyn@users.noreply.github.com> Date: Thu, 27 Jun 2024 00:36:03 -0300 Subject: [PATCH 10/10] (chore): prepare release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Lobo Metalúrgico <43734867+LoboMetalurgico@users.noreply.github.com> --- CHANGELOG.md | 9 +++++++-- package.json | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fbbbce..cfc6ca4 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,9 @@ -# v2.0.0 +# v2.0.0-ALPHA.1: Customize Everything (patch) + - [BACKWARDS COMPATIBILITY] Automatically register the console engine if no engine is provided and you try to log something. + + - [NEW] Strings with highlightable words separated by `/` and `\` will be highlighted. + +# v2.0.0-ALPHA.0: Customize Everything - [BREAKING] Full rewrite of the constructor and the way the logger works, logging methods however remain the same. - [BREAKING] Removed the `fileProperties` parameter from the constructor, use instead new FileStorageEngine class for file logging. @@ -65,7 +70,7 @@ - [NEW] Added support to log objects, arrays and etc. Like the default `console.log` function. - - [BREAKING] Changed the export of AutoLogEnd now importing the package will return the `Logger` class and a object named `AutoLogEnd` with the `activate` and `deactivate` functions. + - [BREAKING] Changed the export of AutoLogEnd. Now, importing the package will return the `Logger` class and a object named `AutoLogEnd` with the `activate` and `deactivate` functions. - [NEW] AutoLogEnd `activate` function now accepts a `Logger` instance as 2º parameter. If not passed it will create a new instance of `Logger` with the default parameters. otherwise it will use the passed instance. diff --git a/package.json b/package.json index 17651fe..ee26a29 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@promisepending/logger.js", - "version": "2.0.0-alpha.0", + "version": "2.0.0-alpha.1", "description": "A better logger", "main": "build/index.js", "types": "src/main/index.ts",