diff --git a/.eslintrc.js b/.eslintrc.js index e69646071b..ed761bb558 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -88,7 +88,7 @@ const eslintConfig = { 'no-undef': 2, 'no-unmodified-loop-condition': 2, 'no-unreachable': 2, - 'no-unused-vars': [1, { vars: 'all', args: 'after-used' }], + 'no-unused-vars': [2, { vars: 'all', args: 'after-used' }], 'no-use-before-define': 0, 'no-useless-call': 2, 'no-useless-computed-key': 2, diff --git a/CHANGELOG.md b/CHANGELOG.md index e937d97a5f..a77548bb59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### NEXT - CI: Support Node 22 ([PR #1434](https://github.com/versatica/mediasoup/pull/1434)). +- Update ESLint to version 9 ([PR #1435](https://github.com/versatica/mediasoup/pull/1435)). ### 3.14.9 @@ -864,7 +865,7 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi ### 3.6.6 - Update `usrsctp` library. -- Update ESlint and TypeScript related dependencies. +- Update ESLint and TypeScript related dependencies. ### 3.6.5 diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000000..c49dcb532f --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,185 @@ +import eslint from '@eslint/js'; +import tsEslint from 'typescript-eslint'; +import jestEslint from 'eslint-plugin-jest'; +import prettierRecommendedEslint from 'eslint-plugin-prettier/recommended'; +import globals from 'globals'; + +const config = tsEslint.config( + { + languageOptions: { + sourceType: 'module', + globals: { ...globals.node }, + }, + linterOptions: { + noInlineConfig: false, + reportUnusedDisableDirectives: 'error', + }, + }, + eslint.configs.recommended, + { + rules: { + 'constructor-super': 2, + curly: [2, 'all'], + // Unfortunatelly `curly` does not apply to blocks in `switch` cases so + // this is needed. + 'no-restricted-syntax': [ + 2, + { + selector: 'SwitchCase > *.consequent[type!="BlockStatement"]', + message: 'Switch cases without blocks are disallowed', + }, + ], + 'guard-for-in': 2, + 'newline-after-var': 2, + 'newline-before-return': 2, + 'no-alert': 2, + 'no-caller': 2, + 'no-case-declarations': 2, + 'no-catch-shadow': 2, + 'no-class-assign': 2, + 'no-console': 2, + 'no-const-assign': 2, + 'no-debugger': 2, + 'no-dupe-args': 2, + 'no-dupe-keys': 2, + 'no-duplicate-case': 2, + 'no-div-regex': 2, + 'no-empty': [2, { allowEmptyCatch: true }], + 'no-empty-pattern': 2, + 'no-eval': 2, + 'no-extend-native': 2, + 'no-ex-assign': 2, + 'no-extra-bind': 2, + 'no-extra-boolean-cast': 2, + 'no-extra-label': 2, + 'no-fallthrough': 2, + 'no-func-assign': 2, + 'no-global-assign': 2, + 'no-implicit-coercion': 2, + 'no-implicit-globals': 2, + 'no-inner-declarations': 2, + 'no-invalid-regexp': 2, + 'no-invalid-this': 2, + 'no-irregular-whitespace': 2, + 'no-lonely-if': 2, + 'no-multi-str': 2, + 'no-native-reassign': 2, + 'no-negated-in-lhs': 2, + 'no-new': 2, + 'no-new-func': 2, + 'no-new-wrappers': 2, + 'no-obj-calls': 2, + 'no-proto': 2, + 'no-prototype-builtins': 0, + 'no-redeclare': 2, + 'no-regex-spaces': 2, + 'no-restricted-imports': 2, + 'no-return-assign': 2, + 'no-self-assign': 2, + 'no-self-compare': 2, + 'no-sequences': 2, + 'no-shadow': 2, + 'no-shadow-restricted-names': 2, + 'no-sparse-arrays': 2, + 'no-this-before-super': 2, + 'no-throw-literal': 2, + 'no-undef': 2, + 'no-unmodified-loop-condition': 2, + 'no-unreachable': 2, + 'no-unused-vars': [ + 2, + { vars: 'all', args: 'after-used', caughtErrors: 'none' }, + ], + 'no-use-before-define': 0, + 'no-useless-call': 2, + 'no-useless-computed-key': 2, + 'no-useless-concat': 2, + 'no-useless-rename': 2, + 'no-var': 2, + 'object-curly-newline': 0, + 'prefer-const': 2, + 'prefer-rest-params': 2, + 'prefer-spread': 2, + 'prefer-template': 2, + 'spaced-comment': [2, 'always'], + strict: 2, + 'valid-typeof': 2, + yoda: 2, + }, + }, + // NOTE: We need to apply this only to .ts files (and not to .mjs files). + ...tsEslint.configs.recommendedTypeChecked.map(item => ({ + ...item, + files: ['node/src/**/*.ts'], + })), + // NOTE: We need to apply this only to .ts files (and not to .mjs files). + ...tsEslint.configs.stylisticTypeChecked.map(item => ({ + ...item, + files: ['node/src/**/*.ts'], + })), + { + name: 'mediasoup .ts files', + files: ['node/src/**/*.ts'], + languageOptions: { + parserOptions: { + projectService: true, + project: 'tsconfig.json', + }, + }, + rules: { + '@typescript-eslint/consistent-generic-constructors': [ + 2, + 'type-annotation', + ], + '@typescript-eslint/dot-notation': 0, + '@typescript-eslint/no-unused-vars': [ + 2, + { + vars: 'all', + args: 'after-used', + caughtErrors: 'none', + ignoreRestSiblings: false, + }, + ], + // We want to use `type` instead of `interface`. + '@typescript-eslint/consistent-type-definitions': 0, + // Sorry, we need many `any` usage. + '@typescript-eslint/no-explicit-any': 0, + '@typescript-eslint/no-unsafe-member-access': 0, + '@typescript-eslint/no-unsafe-assignment': 0, + '@typescript-eslint/no-unsafe-call': 0, + '@typescript-eslint/no-unsafe-return': 0, + '@typescript-eslint/no-unsafe-argument': 0, + '@typescript-eslint/consistent-indexed-object-style': 0, + '@typescript-eslint/no-empty-function': 0, + '@typescript-eslint/restrict-template-expressions': 0, + '@typescript-eslint/no-duplicate-type-constituents': [ + 2, + { ignoreUnions: true }, + ], + }, + }, + { + name: 'mediasoup .ts test files', + ...jestEslint.configs['flat/recommended'], + files: ['node/src/test/**/*.ts'], + rules: { + ...jestEslint.configs['flat/recommended'].rules, + 'jest/no-disabled-tests': 2, + 'jest/prefer-expect-assertions': 0, + '@typescript-eslint/no-unnecessary-type-assertion': 0, + }, + }, + prettierRecommendedEslint +); + +// console.log('*** config:***\n', config); + +// console.log( +// '---tsEslint.configs.strictTypeChecked: %o', +// tsEslint.configs.strictTypeChecked +// ); + +// process.exit(1); + +export default config; diff --git a/node/src/Channel.ts b/node/src/Channel.ts index a2fa6b3a6c..97ec868bdb 100644 --- a/node/src/Channel.ts +++ b/node/src/Channel.ts @@ -94,7 +94,6 @@ export class Channel extends EnhancedEventEmitter { let msgStart = 0; - // eslint-disable-next-line no-constant-condition while (true) { const readLen = this.#recvBuffer.length - msgStart; @@ -320,7 +319,11 @@ export class Channel extends EnhancedEventEmitter { ); } - this.#nextId < 4294967295 ? ++this.#nextId : (this.#nextId = 1); + if (this.#nextId < 4294967295) { + ++this.#nextId; + } else { + this.#nextId = 1; + } const id = this.#nextId; @@ -408,7 +411,7 @@ export class Channel extends EnhancedEventEmitter { if (!sent) { logger.error( - `received response does not match any sent request [id:${response.id}]` + `received response does not match any sent request [id:${response.id()}]` ); return; diff --git a/node/src/Consumer.ts b/node/src/Consumer.ts index 8de9fc4cff..cb6314eea2 100644 --- a/node/src/Consumer.ts +++ b/node/src/Consumer.ts @@ -356,7 +356,7 @@ export class Consumer< this.#producerPaused = producerPaused; this.#score = score; this.#preferredLayers = preferredLayers; - this.#appData = appData || ({} as ConsumerAppData); + this.#appData = appData ?? ({} as ConsumerAppData); this.handleWorkerNotifications(); } @@ -556,7 +556,7 @@ export class Consumer< /** * Get Consumer stats. */ - async getStats(): Promise> { + async getStats(): Promise<(ConsumerStat | ProducerStat)[]> { logger.debug('getStats()'); const response = await this.#channel.request( @@ -642,7 +642,7 @@ export class Consumer< FbsConsumer.ConsumerLayers.createConsumerLayers( builder, spatialLayer, - temporalLayer !== undefined ? temporalLayer : null + temporalLayer ?? null ); const requestOffset = FbsConsumer.SetPreferredLayersRequest.createSetPreferredLayersRequest( @@ -669,10 +669,7 @@ export class Consumer< if (status.preferredLayers) { preferredLayers = { spatialLayer: status.preferredLayers.spatialLayer, - temporalLayer: - status.preferredLayers.temporalLayer !== null - ? status.preferredLayers.temporalLayer - : undefined, + temporalLayer: status.preferredLayers.temporalLayer ?? undefined, }; } } @@ -835,7 +832,7 @@ export class Consumer< data!.body(notification); - const score: ConsumerScore = notification!.score()!.unpack(); + const score: ConsumerScore = notification.score()!.unpack(); this.#score = score; @@ -848,7 +845,7 @@ export class Consumer< } case Event.CONSUMER_LAYERS_CHANGE: { - const notification = new FbsConsumer.LayersChangeNotification()!; + const notification = new FbsConsumer.LayersChangeNotification(); data!.body(notification); @@ -1194,6 +1191,6 @@ function parseConsumerDumpResponse( function parseConsumerStats( binary: FbsConsumer.GetStatsResponse -): Array { +): (ConsumerStat | ProducerStat)[] { return utils.parseVector(binary, 'stats', parseRtpStreamStats); } diff --git a/node/src/DataConsumer.ts b/node/src/DataConsumer.ts index 8a987f143d..19e66b5267 100644 --- a/node/src/DataConsumer.ts +++ b/node/src/DataConsumer.ts @@ -184,7 +184,7 @@ export class DataConsumer< this.#paused = paused; this.#dataProducerPaused = dataProducerPaused; this.#subchannels = subchannels; - this.#appData = appData || ({} as DataConsumerAppData); + this.#appData = appData ?? ({} as DataConsumerAppData); this.handleWorkerNotifications(); } diff --git a/node/src/DataProducer.ts b/node/src/DataProducer.ts index 5a6ced5aa0..e4ac42884e 100644 --- a/node/src/DataProducer.ts +++ b/node/src/DataProducer.ts @@ -143,7 +143,7 @@ export class DataProducer< this.#data = data; this.#channel = channel; this.#paused = paused; - this.#appData = appData || ({} as DataProducerAppData); + this.#appData = appData ?? ({} as DataProducerAppData); this.handleWorkerNotifications(); } diff --git a/node/src/DirectTransport.ts b/node/src/DirectTransport.ts index 3417e0bb46..ea5f2b8684 100644 --- a/node/src/DirectTransport.ts +++ b/node/src/DirectTransport.ts @@ -71,6 +71,7 @@ export class DirectTransport< DirectTransportObserver > { // DirectTransport data. + // eslint-disable-next-line no-unused-private-class-members readonly #data: DirectTransportData; /** @@ -178,6 +179,7 @@ export class DirectTransport< * * @override */ + // eslint-disable-next-line @typescript-eslint/require-await async connect(): Promise { logger.debug('connect()'); } @@ -185,7 +187,7 @@ export class DirectTransport< /** * @override */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars + // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/require-await async setMaxIncomingBitrate(bitrate: number): Promise { throw new UnsupportedError( 'setMaxIncomingBitrate() not implemented in DirectTransport' @@ -195,7 +197,7 @@ export class DirectTransport< /** * @override */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars + // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/require-await async setMaxOutgoingBitrate(bitrate: number): Promise { throw new UnsupportedError( 'setMaxOutgoingBitrate() not implemented in DirectTransport' @@ -205,7 +207,7 @@ export class DirectTransport< /** * @override */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars + // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/require-await async setMinOutgoingBitrate(bitrate: number): Promise { throw new UnsupportedError( 'setMinOutgoingBitrate() not implemented in DirectTransport' diff --git a/node/src/PipeTransport.ts b/node/src/PipeTransport.ts index 6fea0d56ad..61a30bbf07 100644 --- a/node/src/PipeTransport.ts +++ b/node/src/PipeTransport.ts @@ -390,7 +390,7 @@ export class PipeTransport< type: 'pipe' as ConsumerType, }; - const consumer = new Consumer({ + const consumer: Consumer = new Consumer({ internal: { ...this.internal, consumerId, diff --git a/node/src/Producer.ts b/node/src/Producer.ts index 317091e0d8..4ab4b64620 100644 --- a/node/src/Producer.ts +++ b/node/src/Producer.ts @@ -227,7 +227,7 @@ export class Producer< this.#data = data; this.#channel = channel; this.#paused = paused; - this.#appData = appData || ({} as ProducerAppData); + this.#appData = appData ?? ({} as ProducerAppData); this.handleWorkerNotifications(); } @@ -627,6 +627,10 @@ export function producerTypeToFbs(type: ProducerType): FbsRtpParameters.Type { case 'svc': { return FbsRtpParameters.Type.SVC; } + + default: { + throw new TypeError(`invalid ProducerType: ${type}`); + } } } diff --git a/node/src/Router.ts b/node/src/Router.ts index fb05298187..70fc9ffb27 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -278,7 +278,7 @@ export class Router< this.#internal = internal; this.#data = data; this.#channel = channel; - this.#appData = appData || ({} as RouterAppData); + this.#appData = appData ?? ({} as RouterAppData); } /** @@ -627,21 +627,23 @@ export class Router< const webRtcTransportData = parseWebRtcTransportDumpResponse(data); - const transport = new WebRtcTransport({ - internal: { - ...this.#internal, - transportId: transportId, - }, - data: webRtcTransportData, - channel: this.#channel, - appData, - getRouterRtpCapabilities: (): RtpCapabilities => - this.#data.rtpCapabilities, - getProducerById: (producerId: string): Producer | undefined => - this.#producers.get(producerId), - getDataProducerById: (dataProducerId: string): DataProducer | undefined => - this.#dataProducers.get(dataProducerId), - }); + const transport: WebRtcTransport = + new WebRtcTransport({ + internal: { + ...this.#internal, + transportId: transportId, + }, + data: webRtcTransportData, + channel: this.#channel, + appData, + getRouterRtpCapabilities: (): RtpCapabilities => + this.#data.rtpCapabilities, + getProducerById: (producerId: string): Producer | undefined => + this.#producers.get(producerId), + getDataProducerById: ( + dataProducerId: string + ): DataProducer | undefined => this.#dataProducers.get(dataProducerId), + }); this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); @@ -797,21 +799,24 @@ export class Router< const plainTransportData = parsePlainTransportDumpResponse(data); - const transport = new PlainTransport({ - internal: { - ...this.#internal, - transportId: transportId, - }, - data: plainTransportData, - channel: this.#channel, - appData, - getRouterRtpCapabilities: (): RtpCapabilities => - this.#data.rtpCapabilities, - getProducerById: (producerId: string): Producer | undefined => - this.#producers.get(producerId), - getDataProducerById: (dataProducerId: string): DataProducer | undefined => - this.#dataProducers.get(dataProducerId), - }); + const transport: PlainTransport = new PlainTransport( + { + internal: { + ...this.#internal, + transportId: transportId, + }, + data: plainTransportData, + channel: this.#channel, + appData, + getRouterRtpCapabilities: (): RtpCapabilities => + this.#data.rtpCapabilities, + getProducerById: (producerId: string): Producer | undefined => + this.#producers.get(producerId), + getDataProducerById: ( + dataProducerId: string + ): DataProducer | undefined => this.#dataProducers.get(dataProducerId), + } + ); this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); @@ -935,7 +940,7 @@ export class Router< const plainTransportData = parsePipeTransportDumpResponse(data); - const transport = new PipeTransport({ + const transport: PipeTransport = new PipeTransport({ internal: { ...this.#internal, transportId, @@ -1030,21 +1035,23 @@ export class Router< const directTransportData = parseDirectTransportDumpResponse(data); - const transport = new DirectTransport({ - internal: { - ...this.#internal, - transportId: transportId, - }, - data: directTransportData, - channel: this.#channel, - appData, - getRouterRtpCapabilities: (): RtpCapabilities => - this.#data.rtpCapabilities, - getProducerById: (producerId: string): Producer | undefined => - this.#producers.get(producerId), - getDataProducerById: (dataProducerId: string): DataProducer | undefined => - this.#dataProducers.get(dataProducerId), - }); + const transport: DirectTransport = + new DirectTransport({ + internal: { + ...this.#internal, + transportId: transportId, + }, + data: directTransportData, + channel: this.#channel, + appData, + getRouterRtpCapabilities: (): RtpCapabilities => + this.#data.rtpCapabilities, + getProducerById: (producerId: string): Producer | undefined => + this.#producers.get(producerId), + getDataProducerById: ( + dataProducerId: string + ): DataProducer | undefined => this.#dataProducers.get(dataProducerId), + }); this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); @@ -1217,7 +1224,7 @@ export class Router< remotePipeTransport.close(); } - reject(error); + reject(error instanceof Error ? error : new Error(String(error))); }); }); @@ -1242,9 +1249,9 @@ export class Router< pipeProducer = await remotePipeTransport!.produce({ id: producer.id, - kind: pipeConsumer!.kind, - rtpParameters: pipeConsumer!.rtpParameters, - paused: pipeConsumer!.producerPaused, + kind: pipeConsumer.kind, + rtpParameters: pipeConsumer.rtpParameters, + paused: pipeConsumer.producerPaused, appData: producer.appData, }); @@ -1264,9 +1271,9 @@ export class Router< } // Pipe events from the pipe Consumer to the pipe Producer. - pipeConsumer!.observer.on('close', () => pipeProducer!.close()); - pipeConsumer!.observer.on('pause', () => pipeProducer!.pause()); - pipeConsumer!.observer.on('resume', () => pipeProducer!.resume()); + pipeConsumer.observer.on('close', () => pipeProducer!.close()); + pipeConsumer.observer.on('pause', () => void pipeProducer!.pause()); + pipeConsumer.observer.on('resume', () => void pipeProducer!.resume()); // Pipe events from the pipe Producer to the pipe Consumer. pipeProducer.observer.on('close', () => pipeConsumer!.close()); @@ -1299,9 +1306,9 @@ export class Router< pipeDataProducer = await remotePipeTransport!.produceData({ id: dataProducer.id, - sctpStreamParameters: pipeDataConsumer!.sctpStreamParameters, - label: pipeDataConsumer!.label, - protocol: pipeDataConsumer!.protocol, + sctpStreamParameters: pipeDataConsumer.sctpStreamParameters, + label: pipeDataConsumer.label, + protocol: pipeDataConsumer.protocol, appData: dataProducer.appData, }); @@ -1311,7 +1318,7 @@ export class Router< } // Pipe events from the pipe DataConsumer to the pipe DataProducer. - pipeDataConsumer!.observer.on('close', () => pipeDataProducer!.close()); + pipeDataConsumer.observer.on('close', () => pipeDataProducer!.close()); // Pipe events from the pipe DataProducer to the pipe DataConsumer. pipeDataProducer.observer.on('close', () => pipeDataConsumer!.close()); @@ -1323,13 +1330,8 @@ export class Router< error ); - if (pipeDataConsumer) { - pipeDataConsumer.close(); - } - - if (pipeDataProducer) { - pipeDataProducer.close(); - } + pipeDataConsumer?.close(); + pipeDataProducer?.close(); throw error; } @@ -1412,8 +1414,8 @@ export class Router< this.#internal.routerId ); - const activeSpeakerObserver = - new ActiveSpeakerObserver({ + const activeSpeakerObserver: ActiveSpeakerObserver = + new ActiveSpeakerObserver({ internal: { ...this.#internal, rtpObserverId: rtpObserverId, @@ -1488,8 +1490,8 @@ export class Router< this.#internal.routerId ); - const audioLevelObserver = - new AudioLevelObserver({ + const audioLevelObserver: AudioLevelObserver = + new AudioLevelObserver({ internal: { ...this.#internal, rtpObserverId: rtpObserverId, diff --git a/node/src/RtpObserver.ts b/node/src/RtpObserver.ts index 9bc808e5ce..a64abc3747 100644 --- a/node/src/RtpObserver.ts +++ b/node/src/RtpObserver.ts @@ -93,7 +93,7 @@ export abstract class RtpObserver< this.internal = internal; this.channel = channel; - this.#appData = appData || ({} as RtpObserverAppData); + this.#appData = appData ?? ({} as RtpObserverAppData); this.getProducerById = getProducerById; this.#observer = observer; } diff --git a/node/src/RtpParameters.ts b/node/src/RtpParameters.ts index 08d02cf3e6..4c1e7631dc 100644 --- a/node/src/RtpParameters.ts +++ b/node/src/RtpParameters.ts @@ -640,8 +640,7 @@ export function parseParameters(data: any): any { const value = new FbsBoolean(); fbsParameter.value(value); - - parameters[String(fbsParameter.name()!)] = value.value(); + parameters[String(fbsParameter.name())] = value.value(); break; } @@ -650,8 +649,7 @@ export function parseParameters(data: any): any { const value = new FbsInteger32(); fbsParameter.value(value); - - parameters[String(fbsParameter.name()!)] = value.value(); + parameters[String(fbsParameter.name())] = value.value(); break; } @@ -660,8 +658,7 @@ export function parseParameters(data: any): any { const value = new FbsDouble(); fbsParameter.value(value); - - parameters[String(fbsParameter.name()!)] = value.value(); + parameters[String(fbsParameter.name())] = value.value(); break; } @@ -670,8 +667,7 @@ export function parseParameters(data: any): any { const value = new FbsString(); fbsParameter.value(value); - - parameters[String(fbsParameter.name()!)] = value.value(); + parameters[String(fbsParameter.name())] = value.value(); break; } @@ -680,8 +676,7 @@ export function parseParameters(data: any): any { const value = new FbsInteger32Array(); fbsParameter.value(value); - - parameters[String(fbsParameter.name()!)] = value.valueArray(); + parameters[String(fbsParameter.name())] = value.valueArray(); break; } @@ -843,7 +838,7 @@ export function parseRtpEncodingParameters( rid: data.rid() ?? undefined, codecPayloadType: data.codecPayloadType() !== null ? data.codecPayloadType()! : undefined, - rtx: data.rtx() ? { ssrc: data.rtx()!.ssrc()! } : undefined, + rtx: data.rtx() ? { ssrc: data.rtx()!.ssrc() } : undefined, dtx: data.dtx(), scalabilityMode: data.scalabilityMode() ?? undefined, maxBitrate: data.maxBitrate() !== null ? data.maxBitrate()! : undefined, diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 2b6bced94d..8559b5961e 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -402,7 +402,7 @@ export abstract class Transport< this.internal = internal; this.#data = data; this.channel = channel; - this.#appData = appData || ({} as TransportAppData); + this.#appData = appData ?? ({} as TransportAppData); this.#getRouterRtpCapabilities = getRouterRtpCapabilities; this.getProducerById = getProducerById; this.getDataProducerById = getDataProducerById; @@ -635,6 +635,7 @@ export abstract class Transport< * * @abstract */ + // eslint-disable-next-line @typescript-eslint/require-await async dump(): Promise { // Should not happen. throw new Error('method implemented in the subclass'); @@ -645,6 +646,7 @@ export abstract class Transport< * * @abstract */ + // eslint-disable-next-line @typescript-eslint/require-await async getStats(): Promise { // Should not happen. throw new Error('method implemented in the subclass'); @@ -655,7 +657,7 @@ export abstract class Transport< * * @abstract */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars + // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/require-await async connect(params: any): Promise { // Should not happen. throw new Error('method implemented in the subclass'); @@ -761,11 +763,7 @@ export abstract class Transport< if (this.constructor.name !== 'PipeTransport') { // If CNAME is given and we don't have yet a CNAME for Producers in this // Transport, take it. - if ( - !this.#cnameForProducers && - clonedRtpParameters.rtcp && - clonedRtpParameters.rtcp.cname - ) { + if (!this.#cnameForProducers && clonedRtpParameters.rtcp?.cname) { this.#cnameForProducers = clonedRtpParameters.rtcp.cname; } // Otherwise if we don't have yet a CNAME for Producers and the RTP @@ -795,7 +793,7 @@ export abstract class Transport< rtpMapping ); - const producerId = id || utils.generateUUIDv4(); + const producerId = id ?? utils.generateUUIDv4(); const requestOffset = createProduceRequest({ builder: this.channel.bufferBuilder, producerId, @@ -827,7 +825,7 @@ export abstract class Transport< consumableRtpParameters, }; - const producer = new Producer({ + const producer: Producer = new Producer({ internal: { ...this.internal, producerId, @@ -954,7 +952,7 @@ export abstract class Transport< type: pipe ? 'pipe' : (producer.type as ConsumerType), }; - const consumer = new Consumer({ + const consumer: Consumer = new Consumer({ internal: { ...this.internal, consumerId, @@ -968,10 +966,7 @@ export abstract class Transport< preferredLayers: status.preferredLayers ? { spatialLayer: status.preferredLayers.spatialLayer, - temporalLayer: - status.preferredLayers.temporalLayer !== null - ? status.preferredLayers.temporalLayer - : undefined, + temporalLayer: status.preferredLayers.temporalLayer ?? undefined, } : undefined, }); @@ -1034,7 +1029,7 @@ export abstract class Transport< } } - const dataProducerId = id || utils.generateUUIDv4(); + const dataProducerId = id ?? utils.generateUUIDv4(); const requestOffset = createProduceDataRequest({ builder: this.channel.bufferBuilder, dataProducerId, @@ -1059,7 +1054,7 @@ export abstract class Transport< const dump = parseDataProducerDumpResponse(produceDataResponse); - const dataProducer = new DataProducer({ + const dataProducer: DataProducer = new DataProducer({ internal: { ...this.internal, dataProducerId, @@ -1194,7 +1189,7 @@ export abstract class Transport< const dump = parseDataConsumerDumpResponse(consumeDataResponse); - const dataConsumer = new DataConsumer({ + const dataConsumer: DataConsumer = new DataConsumer({ internal: { ...this.internal, dataConsumerId, @@ -1339,10 +1334,6 @@ export function parseSctpState(fbsSctpState: FbsSctpState): SctpState { case FbsSctpState.CLOSED: { return 'closed'; } - - default: { - throw new TypeError(`invalid SctpState: ${fbsSctpState}`); - } } } @@ -1530,7 +1521,7 @@ export function parseTransportTraceEventData( timestamp: Number(trace.timestamp()), direction: trace.direction() === FbsTraceDirection.DIRECTION_IN ? 'in' : 'out', - info: parseBweTraceInfo(info!), + info: parseBweTraceInfo(info), }; } @@ -1573,10 +1564,6 @@ function transportTraceEventTypeToFbs( case 'bwe': { return FbsTransport.TraceEventType.BWE; } - - default: { - throw new TypeError(`invalid TransportTraceEventType: ${eventType}`); - } } } diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index 29082d80c8..385a49e638 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -113,7 +113,7 @@ export class WebRtcServer< this.#internal = internal; this.#channel = channel; - this.#appData = appData || ({} as WebRtcServerAppData); + this.#appData = appData ?? ({} as WebRtcServerAppData); } /** @@ -280,7 +280,7 @@ function parseIceUserNameFragment( function parseTupleHash(binary: FbsWebRtcServer.TupleHash): TupleHash { return { - tupleHash: Number(binary.tupleHash()!), + tupleHash: Number(binary.tupleHash()), webRtcTransportId: binary.webRtcTransportId()!, }; } diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index 11977b6cfd..34ca5014a3 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -925,7 +925,7 @@ function parseDtlsParameters( return { fingerprints: fingerprints, - role: binary.role() === null ? undefined : dtlsRoleFromFbs(binary.role()!), + role: binary.role() === null ? undefined : dtlsRoleFromFbs(binary.role()), }; } diff --git a/node/src/Worker.ts b/node/src/Worker.ts index 151211fa61..e86206d98b 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -101,8 +101,6 @@ export type WorkerUpdateableSettings = Pick< * - https://linux.die.net/man/2/getrusage */ export type WorkerResourceUsage = { - /* eslint-disable camelcase */ - /** * User CPU time used (in ms). */ @@ -182,8 +180,6 @@ export type WorkerResourceUsage = { * Involuntary context switches. */ ru_nivcsw: number; - - /* eslint-enable camelcase */ }; export type WorkerDump = { @@ -301,7 +297,7 @@ export class Worker< let spawnArgs: string[] = []; if (process.env.MEDIASOUP_USE_VALGRIND === 'true') { - spawnBin = process.env.MEDIASOUP_VALGRIND_BIN || 'valgrind'; + spawnBin = process.env.MEDIASOUP_VALGRIND_BIN ?? 'valgrind'; if (process.env.MEDIASOUP_VALGRIND_OPTIONS) { spawnArgs = spawnArgs.concat( @@ -383,7 +379,7 @@ export class Worker< pid: this.#pid, }); - this.#appData = appData || ({} as WorkerAppData); + this.#appData = appData ?? ({} as WorkerAppData); let spawnDone = false; @@ -636,7 +632,6 @@ export class Worker< const ru = resourceUsage.unpack(); - /* eslint-disable camelcase */ return { ru_utime: Number(ru.ruUtime), ru_stime: Number(ru.ruStime), @@ -655,7 +650,6 @@ export class Worker< ru_nvcsw: Number(ru.ruNvcsw), ru_nivcsw: Number(ru.ruNivcsw), }; - /* eslint-enable camelcase */ } /** @@ -729,7 +723,7 @@ export class Worker< createWebRtcServerRequestOffset ); - const webRtcServer = new WebRtcServer({ + const webRtcServer: WebRtcServer = new WebRtcServer({ internal: { webRtcServerId }, channel: this.#channel, appData, @@ -780,7 +774,7 @@ export class Worker< ); const data = { rtpCapabilities }; - const router = new Router({ + const router: Router = new Router({ internal: { routerId, }, @@ -803,7 +797,7 @@ export class Worker< return; } - logger.debug(`died() [error:${error}]`); + logger.debug(`died() [error:${error.toString()}]`); this.#closed = true; this.#died = true; @@ -834,7 +828,7 @@ export function parseWorkerDumpResponse( binary: FbsWorker.DumpResponse ): WorkerDump { const dump: WorkerDump = { - pid: binary.pid()!, + pid: binary.pid(), webRtcServerIds: utils.parseVector(binary, 'webRtcServerIds'), routerIds: utils.parseVector(binary, 'routerIds'), channelMessageHandlers: { diff --git a/node/src/enhancedEvents.ts b/node/src/enhancedEvents.ts index a5458d3a08..e2ef6a34fb 100644 --- a/node/src/enhancedEvents.ts +++ b/node/src/enhancedEvents.ts @@ -113,10 +113,12 @@ export class EnhancedEventEmitter< return super.listenerCount(eventName); } + // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type listeners(eventName: K): Function[] { return super.listeners(eventName); } + // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type rawListeners(eventName: K): Function[] { return super.rawListeners(eventName); } diff --git a/node/src/index.ts b/node/src/index.ts index 38410c419a..eeff81c0fa 100644 --- a/node/src/index.ts +++ b/node/src/index.ts @@ -4,6 +4,7 @@ import { workerBin, Worker, WorkerSettings } from './Worker'; import * as utils from './utils'; import { supportedRtpCapabilities } from './supportedRtpCapabilities'; import { RtpCapabilities } from './RtpParameters'; + import * as types from './types'; /** @@ -14,7 +15,7 @@ export { types }; /** * Expose mediasoup version. */ -// eslint-disable-next-line @typescript-eslint/no-var-requires +// eslint-disable-next-line @typescript-eslint/no-require-imports export const version: string = require('../../package.json').version; /** @@ -63,7 +64,7 @@ export async function createWorker< throw new TypeError('if given, appData must be an object'); } - const worker = new Worker({ + const worker: Worker = new Worker({ logLevel, logTags, rtcMinPort, diff --git a/node/src/scalabilityModes.ts b/node/src/scalabilityModes.ts index 2804e29b2e..291255092a 100644 --- a/node/src/scalabilityModes.ts +++ b/node/src/scalabilityModes.ts @@ -9,7 +9,7 @@ export type ScalabilityMode = { }; export function parse(scalabilityMode?: string): ScalabilityMode { - const match = ScalabilityModeRegex.exec(scalabilityMode || ''); + const match = ScalabilityModeRegex.exec(scalabilityMode ?? ''); if (match) { return { diff --git a/node/src/test/test-ActiveSpeakerObserver.ts b/node/src/test/test-ActiveSpeakerObserver.ts index f957a727c2..aaa922390d 100644 --- a/node/src/test/test-ActiveSpeakerObserver.ts +++ b/node/src/test/test-ActiveSpeakerObserver.ts @@ -59,14 +59,14 @@ test('router.createActiveSpeakerObserver() succeeds', async () => { test('router.createActiveSpeakerObserver() with wrong arguments rejects with TypeError', async () => { await expect( ctx.router!.createActiveSpeakerObserver( - // @ts-ignore + // @ts-expect-error --- Testing purposes. { interval: false } ) ).rejects.toThrow(TypeError); await expect( ctx.router!.createActiveSpeakerObserver( - // @ts-ignore + // @ts-expect-error --- Testing purposes. { appData: 'NOT-AN-OBJECT' } ) ).rejects.toThrow(TypeError); diff --git a/node/src/test/test-AudioLevelObserver.ts b/node/src/test/test-AudioLevelObserver.ts index f6d6f61723..f1a1a5fb17 100644 --- a/node/src/test/test-AudioLevelObserver.ts +++ b/node/src/test/test-AudioLevelObserver.ts @@ -66,17 +66,17 @@ test('router.createAudioLevelObserver() with wrong arguments rejects with TypeEr ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.router!.createAudioLevelObserver({ threshold: 'foo' }) ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.router!.createAudioLevelObserver({ interval: false }) ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.router!.createAudioLevelObserver({ appData: 'NOT-AN-OBJECT' }) ).rejects.toThrow(TypeError); }, 2000); diff --git a/node/src/test/test-Consumer.ts b/node/src/test/test-Consumer.ts index 436145fbc2..aad102f089 100644 --- a/node/src/test/test-Consumer.ts +++ b/node/src/test/test-Consumer.ts @@ -195,13 +195,13 @@ const ctx: TestContext = { }, { kind: 'audio', - uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', preferredId: 4, preferredEncrypt: false, }, { kind: 'video', - uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', preferredId: 4, preferredEncrypt: false, }, @@ -454,7 +454,7 @@ test('transport.consume() succeeds', async () => { }); expect(videoPipeConsumer.preferredLayers).toBeUndefined(); expect(videoPipeConsumer.currentLayers).toBeUndefined(); - expect(videoPipeConsumer.appData).toBeUndefined; + expect(videoPipeConsumer.appData).toEqual({}); const dump2 = await ctx.router!.dump(); @@ -818,11 +818,11 @@ test('consumer.pause() and resume() succeed', async () => { // Even if we don't await for pause()/resume() completion, the observer must // fire 'pause' and 'resume' events if state was the opposite. - audioConsumer.pause(); - audioConsumer.resume(); - audioConsumer.pause(); - audioConsumer.pause(); - audioConsumer.pause(); + void audioConsumer.pause(); + void audioConsumer.resume(); + void audioConsumer.pause(); + void audioConsumer.pause(); + void audioConsumer.pause(); await audioConsumer.resume(); expect(onObserverPause).toHaveBeenCalledTimes(3); @@ -909,22 +909,22 @@ test('consumer.setPreferredLayers() with wrong arguments rejects with TypeError' rtpCapabilities: ctx.consumerDeviceCapabilities, }); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(videoConsumer.setPreferredLayers({})).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. videoConsumer.setPreferredLayers({ foo: '123' }) ).rejects.toThrow(TypeError); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(videoConsumer.setPreferredLayers('foo')).rejects.toThrow( TypeError ); // Missing spatialLayer. await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. videoConsumer.setPreferredLayers({ temporalLayer: 2 }) ).rejects.toThrow(TypeError); }, 2000); @@ -945,12 +945,12 @@ test('consumer.setPriority() with wrong arguments rejects with TypeError', async rtpCapabilities: ctx.consumerDeviceCapabilities, }); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(videoConsumer.setPriority()).rejects.toThrow(TypeError); await expect(videoConsumer.setPriority(0)).rejects.toThrow(TypeError); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(videoConsumer.setPriority('foo')).rejects.toThrow(TypeError); }, 2000); @@ -981,7 +981,7 @@ test('consumer.enableTraceEvent() succeed', async () => { expect(dump2.traceEventTypes).toEqual(expect.arrayContaining([])); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await audioConsumer.enableTraceEvent(['nack', 'FOO', 'fir']); const dump3 = await audioConsumer.dump(); @@ -1003,16 +1003,16 @@ test('consumer.enableTraceEvent() with wrong arguments rejects with TypeError', rtpCapabilities: ctx.consumerDeviceCapabilities, }); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(audioConsumer.enableTraceEvent(123)).rejects.toThrow(TypeError); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(audioConsumer.enableTraceEvent('rtp')).rejects.toThrow( TypeError ); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. audioConsumer.enableTraceEvent(['fir', 123.123]) ).rejects.toThrow(TypeError); }, 2000); @@ -1144,7 +1144,7 @@ test('Consumer methods reject if closed', async () => { await expect(audioConsumer.resume()).rejects.toThrow(Error); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(audioConsumer.setPreferredLayers({})).rejects.toThrow(Error); await expect(audioConsumer.setPriority(2)).rejects.toThrow(Error); diff --git a/node/src/test/test-DataConsumer.ts b/node/src/test/test-DataConsumer.ts index e51a718095..f61bb8291c 100644 --- a/node/src/test/test-DataConsumer.ts +++ b/node/src/test/test-DataConsumer.ts @@ -289,11 +289,11 @@ test('dataConsumer.pause() and resume() succeed', async () => { // Even if we don't await for pause()/resume() completion, the observer must // fire 'pause' and 'resume' events if state was the opposite. - dataConsumer.pause(); - dataConsumer.resume(); - dataConsumer.pause(); - dataConsumer.pause(); - dataConsumer.pause(); + void dataConsumer.pause(); + void dataConsumer.resume(); + void dataConsumer.pause(); + void dataConsumer.pause(); + void dataConsumer.pause(); await dataConsumer.resume(); expect(onObserverPause).toHaveBeenCalledTimes(3); diff --git a/node/src/test/test-DataProducer.ts b/node/src/test/test-DataProducer.ts index ad1457caea..4f490792ce 100644 --- a/node/src/test/test-DataProducer.ts +++ b/node/src/test/test-DataProducer.ts @@ -146,7 +146,7 @@ test('webRtcTransport1.produceData() with wrong arguments rejects with TypeError // Missing or empty sctpStreamParameters.streamId. await expect( ctx.webRtcTransport1!.produceData({ - // @ts-ignore + // @ts-expect-error --- Testing purposes. sctpStreamParameters: { foo: 'foo' }, }) ).rejects.toThrow(TypeError); @@ -271,11 +271,11 @@ test('dataProducer.pause() and resume() succeed', async () => { // Even if we don't await for pause()/resume() completion, the observer must // fire 'pause' and 'resume' events if state was the opposite. - dataProducer1.pause(); - dataProducer1.resume(); - dataProducer1.pause(); - dataProducer1.pause(); - dataProducer1.pause(); + void dataProducer1.pause(); + void dataProducer1.resume(); + void dataProducer1.pause(); + void dataProducer1.pause(); + void dataProducer1.pause(); await dataProducer1.resume(); expect(onObserverPause).toHaveBeenCalledTimes(3); diff --git a/node/src/test/test-DirectTransport.ts b/node/src/test/test-DirectTransport.ts index 3b7689acc1..e8812257b4 100644 --- a/node/src/test/test-DirectTransport.ts +++ b/node/src/test/test-DirectTransport.ts @@ -59,7 +59,7 @@ test('router.createDirectTransport() succeeds', async () => { test('router.createDirectTransport() with wrong arguments rejects with TypeError', async () => { await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.router!.createDirectTransport({ maxMessageSize: 'foo' }) ).rejects.toThrow(TypeError); @@ -168,7 +168,7 @@ test('dataProducer.send() succeeds', async () => { dataProducer.on('listenererror', (eventName, error) => { reject( new Error( - `dataProducer 'listenererror' [eventName:${eventName}]: ${error}` + `dataProducer 'listenererror' [eventName:${eventName}]: ${error.toString()}` ) ); }); @@ -176,7 +176,7 @@ test('dataProducer.send() succeeds', async () => { dataConsumer.on('listenererror', (eventName, error) => { reject( new Error( - `dataConsumer 'listenererror' [eventName:${eventName}]: ${error}` + `dataConsumer 'listenererror' [eventName:${eventName}]: ${error.toString()}` ) ); }); diff --git a/node/src/test/test-PipeTransport.ts b/node/src/test/test-PipeTransport.ts index 4f2c24363d..854636ffa4 100644 --- a/node/src/test/test-PipeTransport.ts +++ b/node/src/test/test-PipeTransport.ts @@ -477,7 +477,7 @@ test('router.pipeToRouter() succeeds with video', async () => { }, 2000); test('router.createPipeTransport() with wrong arguments rejects with TypeError', async () => { - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(ctx.router1!.createPipeTransport({})).rejects.toThrow(TypeError); await expect( @@ -495,7 +495,7 @@ test('router.createPipeTransport() with wrong arguments rejects with TypeError', ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.router1!.createPipeTransport({ listenIp: ['127.0.0.1'] }) ).rejects.toThrow(TypeError); @@ -508,7 +508,7 @@ test('router.createPipeTransport() with wrong arguments rejects with TypeError', await expect( ctx.router1!.createPipeTransport({ listenInfo: { protocol: 'udp', ip: '127.0.0.1' }, - // @ts-ignore + // @ts-expect-error --- Testing purposes. appData: 'NOT-AN-OBJECT', }) ).rejects.toThrow(TypeError); @@ -658,7 +658,7 @@ test('pipeTransport.connect() with srtpParameters fails if enableSrtp is unset', pipeTransport.connect({ ip: '127.0.0.2', port: 9999, - // @ts-ignore + // @ts-expect-error --- Testing purposes. srtpParameters: 'invalid', }) ).rejects.toThrow(TypeError); @@ -688,7 +688,7 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { pipeTransport.connect({ ip: '127.0.0.2', port: 9999, - // @ts-ignore + // @ts-expect-error --- Testing purposes. srtpParameters: 1, }) ).rejects.toThrow(TypeError); @@ -698,7 +698,7 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { pipeTransport.connect({ ip: '127.0.0.2', port: 9999, - // @ts-ignore + // @ts-expect-error --- Testing purposes. srtpParameters: { keyBase64: 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=', @@ -711,7 +711,7 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { pipeTransport.connect({ ip: '127.0.0.2', port: 9999, - // @ts-ignore + // @ts-expect-error --- Testing purposes. srtpParameters: { cryptoSuite: 'AEAD_AES_256_GCM', }, @@ -724,7 +724,7 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { ip: '127.0.0.2', port: 9999, srtpParameters: { - // @ts-ignore + // @ts-expect-error --- Testing purposes. cryptoSuite: 'FOO', keyBase64: 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=', @@ -738,7 +738,7 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { ip: '127.0.0.2', port: 9999, srtpParameters: { - // @ts-ignore + // @ts-expect-error --- Testing purposes. cryptoSuite: 123, keyBase64: 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=', @@ -753,7 +753,7 @@ test('pipeTransport.connect() with invalid srtpParameters fails', async () => { port: 9999, srtpParameters: { cryptoSuite: 'AEAD_AES_256_GCM', - // @ts-ignore + // @ts-expect-error --- Testing purposes. keyBase64: [], }, }) @@ -907,7 +907,7 @@ test('producer.close() is transmitted to pipe Consumer', async () => { rtpCapabilities: ctx.consumerDeviceCapabilities, }); - await ctx.videoProducer!.close(); + ctx.videoProducer!.close(); expect(ctx.videoProducer!.closed).toBe(true); @@ -1010,7 +1010,7 @@ test('dataProducer.close() is transmitted to pipe DataConsumer', async () => { dataProducerId: ctx.dataProducer!.id, }); - await ctx.dataProducer!.close(); + ctx.dataProducer!.close(); expect(ctx.dataProducer!.closed).toBe(true); diff --git a/node/src/test/test-PlainTransport.ts b/node/src/test/test-PlainTransport.ts index 31508bbddf..abd7c326b9 100644 --- a/node/src/test/test-PlainTransport.ts +++ b/node/src/test/test-PlainTransport.ts @@ -173,7 +173,7 @@ test('router.createPlainTransport() succeeds', async () => { }, 2000); test('router.createPlainTransport() with wrong arguments rejects with TypeError', async () => { - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(ctx.router!.createPlainTransport({})).rejects.toThrow(TypeError); await expect( @@ -191,7 +191,7 @@ test('router.createPlainTransport() with wrong arguments rejects with TypeError' ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.router!.createPlainTransport({ listenIp: ['127.0.0.1'] }) ).rejects.toThrow(TypeError); @@ -204,7 +204,7 @@ test('router.createPlainTransport() with wrong arguments rejects with TypeError' await expect( ctx.router!.createPlainTransport({ listenInfo: { protocol: 'udp', ip: '127.0.0.1' }, - // @ts-ignore + // @ts-expect-error --- Testing purposes. appData: 'NOT-AN-OBJECT', }) ).rejects.toThrow(TypeError); @@ -237,7 +237,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { plainTransport.connect({ ip: '127.0.0.2', port: 9999, - // @ts-ignore + // @ts-expect-error --- Testing purposes. srtpParameters: 1, }) ).rejects.toThrow(TypeError); @@ -247,7 +247,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { plainTransport.connect({ ip: '127.0.0.2', port: 9999, - // @ts-ignore + // @ts-expect-error --- Testing purposes. srtpParameters: { keyBase64: 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv', }, @@ -259,7 +259,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { plainTransport.connect({ ip: '127.0.0.2', port: 9999, - // @ts-ignore + // @ts-expect-error --- Testing purposes. srtpParameters: { cryptoSuite: 'AES_CM_128_HMAC_SHA1_80', }, @@ -272,7 +272,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { ip: '127.0.0.2', port: 9999, srtpParameters: { - // @ts-ignore + // @ts-expect-error --- Testing purposes. cryptoSuite: 'FOO', keyBase64: 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv', }, @@ -285,7 +285,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { ip: '127.0.0.2', port: 9999, srtpParameters: { - // @ts-ignore + // @ts-expect-error --- Testing purposes. cryptoSuite: 123, keyBase64: 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv', }, @@ -299,7 +299,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { port: 9999, srtpParameters: { cryptoSuite: 'AES_CM_128_HMAC_SHA1_80', - // @ts-ignore + // @ts-expect-error --- Testing purposes. keyBase64: [], }, }) @@ -482,7 +482,7 @@ test('plainTransport.connect() with wrong arguments rejects with TypeError', asy plainTransport.connect({ ip: '127.0.0.1', port: 1234, - // @ts-ignore + // @ts-expect-error --- Testing purposes. __rtcpPort: 1235, }) ).rejects.toThrow(TypeError); @@ -490,7 +490,7 @@ test('plainTransport.connect() with wrong arguments rejects with TypeError', asy await expect( plainTransport.connect({ ip: '127.0.0.1', - // @ts-ignore + // @ts-expect-error --- Testing purposes. __port: 'chicken', rtcpPort: 1235, }) diff --git a/node/src/test/test-Producer.ts b/node/src/test/test-Producer.ts index fbf2cef5c1..661c60faf1 100644 --- a/node/src/test/test-Producer.ts +++ b/node/src/test/test-Producer.ts @@ -271,9 +271,9 @@ test('webRtcTransport1.produce() without header extensions and rtcp succeeds', a test('webRtcTransport1.produce() with wrong arguments rejects with TypeError', async () => { await expect( ctx.webRtcTransport1!.produce({ - // @ts-ignore + // @ts-expect-error --- Testing purposes. kind: 'chicken', - // @ts-ignore + // @ts-expect-error --- Testing purposes. rtpParameters: {}, }) ).rejects.toThrow(TypeError); @@ -281,7 +281,7 @@ test('webRtcTransport1.produce() with wrong arguments rejects with TypeError', a await expect( ctx.webRtcTransport1!.produce({ kind: 'audio', - // @ts-ignore + // @ts-expect-error --- Testing purposes. rtpParameters: {}, }) ).rejects.toThrow(TypeError); @@ -293,7 +293,7 @@ test('webRtcTransport1.produce() with wrong arguments rejects with TypeError', a rtpParameters: { codecs: [], headerExtensions: [], - // @ts-ignore + // @ts-expect-error --- Testing purposes. encodings: [{ ssrc: '1111' }], rtcp: { cname: 'qwerty' }, }, @@ -633,11 +633,11 @@ test('producer.pause() and resume() succeed', async () => { // Even if we don't await for pause()/resume() completion, the observer must // fire 'pause' and 'resume' events if state was the opposite. - audioProducer.pause(); - audioProducer.resume(); - audioProducer.pause(); - audioProducer.pause(); - audioProducer.pause(); + void audioProducer.pause(); + void audioProducer.resume(); + void audioProducer.pause(); + void audioProducer.pause(); + void audioProducer.pause(); await audioProducer.resume(); expect(onObserverPause).toHaveBeenCalledTimes(3); @@ -686,7 +686,7 @@ test('producer.enableTraceEvent() succeed', async () => { expect(dump2.traceEventTypes).toEqual(expect.arrayContaining([])); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await audioProducer.enableTraceEvent(['nack', 'FOO', 'fir']); const dump3 = await audioProducer.dump(); @@ -707,16 +707,16 @@ test('producer.enableTraceEvent() with wrong arguments rejects with TypeError', ctx.audioProducerOptions ); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(audioProducer.enableTraceEvent(123)).rejects.toThrow(TypeError); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(audioProducer.enableTraceEvent('rtp')).rejects.toThrow( TypeError ); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. audioProducer.enableTraceEvent(['fir', 123.123]) ).rejects.toThrow(TypeError); }, 2000); @@ -806,11 +806,8 @@ test('Producer methods reject if closed', async () => { audioProducer.close(); await expect(audioProducer.dump()).rejects.toThrow(Error); - await expect(audioProducer.getStats()).rejects.toThrow(Error); - await expect(audioProducer.pause()).rejects.toThrow(Error); - await expect(audioProducer.resume()).rejects.toThrow(Error); }, 2000); diff --git a/node/src/test/test-Router.ts b/node/src/test/test-Router.ts index 50602aec32..615ff4176c 100644 --- a/node/src/test/test-Router.ts +++ b/node/src/test/test-Router.ts @@ -106,13 +106,13 @@ test('worker.createRouter() succeeds', async () => { }, 2000); test('worker.createRouter() with wrong arguments rejects with TypeError', async () => { - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(ctx.worker!.createRouter({ mediaCodecs: {} })).rejects.toThrow( TypeError ); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.worker!.createRouter({ appData: 'NOT-AN-OBJECT' }) ).rejects.toThrow(TypeError); }, 2000); diff --git a/node/src/test/test-WebRtcServer.ts b/node/src/test/test-WebRtcServer.ts index 8297941723..a6c5e8bec0 100644 --- a/node/src/test/test-WebRtcServer.ts +++ b/node/src/test/test-WebRtcServer.ts @@ -217,16 +217,16 @@ test('worker.createWebRtcServer() without specifying port/portRange succeeds', a }, 2000); test('worker.createWebRtcServer() with wrong arguments rejects with TypeError', async () => { - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(ctx.worker!.createWebRtcServer({})).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.worker!.createWebRtcServer({ listenInfos: 'NOT-AN-ARRAY' }) ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.worker!.createWebRtcServer({ listenInfos: ['NOT-AN-OBJECT'] }) ).rejects.toThrow(Error); diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index 601073d209..400f25c11e 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -279,7 +279,7 @@ test('router.createWebRtcTransport() with portRange succeeds', async () => { }, 2000); test('router.createWebRtcTransport() with wrong arguments rejects with TypeError', async () => { - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(ctx.router!.createWebRtcTransport({})).rejects.toThrow( TypeError ); @@ -297,24 +297,24 @@ test('router.createWebRtcTransport() with wrong arguments rejects with TypeError ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.router!.createWebRtcTransport({ listenIps: [123] }) ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.router!.createWebRtcTransport({ listenInfos: '127.0.0.1' }) ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. ctx.router!.createWebRtcTransport({ listenIps: '127.0.0.1' }) ).rejects.toThrow(TypeError); await expect( ctx.router!.createWebRtcTransport({ listenIps: ['127.0.0.1'], - // @ts-ignore + // @ts-expect-error --- Testing purposes. appData: 'NOT-AN-OBJECT', }) ).rejects.toThrow(TypeError); @@ -323,7 +323,7 @@ test('router.createWebRtcTransport() with wrong arguments rejects with TypeError ctx.router!.createWebRtcTransport({ listenIps: ['127.0.0.1'], enableSctp: true, - // @ts-ignore + // @ts-expect-error --- Testing purposes. numSctpStreams: 'foo', }) ).rejects.toThrow(TypeError); @@ -433,13 +433,13 @@ test('webRtcTransport.connect() with wrong arguments rejects with TypeError', as let dtlsRemoteParameters: mediasoup.types.DtlsParameters; - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(webRtcTransport.connect({})).rejects.toThrow(TypeError); dtlsRemoteParameters = { fingerprints: [ { - // @ts-ignore. + // @ts-expect-error --- Testing purposes.. algorithm: 'sha-256000', value: '82:5A:68:3D:36:C3:0A:DE:AF:E7:32:43:D2:88:83:57:AC:2D:65:E5:80:C4:B6:FB:AF:1A:A0:21:9F:6D:0C:AD', @@ -460,7 +460,7 @@ test('webRtcTransport.connect() with wrong arguments rejects with TypeError', as '82:5A:68:3D:36:C3:0A:DE:AF:E7:32:43:D2:88:83:57:AC:2D:65:E5:80:C4:B6:FB:AF:1A:A0:21:9F:6D:0C:AD', }, ], - // @ts-ignore + // @ts-expect-error --- Testing purposes. role: 'chicken', }; @@ -614,7 +614,7 @@ test('transport.enableTraceEvent() succeed', async () => { ], }); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await webRtcTransport.enableTraceEvent(['foo', 'probation']); await expect(webRtcTransport.dump()).resolves.toMatchObject({ traceEventTypes: ['probation'], @@ -625,7 +625,7 @@ test('transport.enableTraceEvent() succeed', async () => { traceEventTypes: [], }); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await webRtcTransport.enableTraceEvent(['probation', 'FOO', 'bwe', 'BAR']); await expect(webRtcTransport.dump()).resolves.toMatchObject({ traceEventTypes: ['probation', 'bwe'], @@ -644,18 +644,18 @@ test('transport.enableTraceEvent() with wrong arguments rejects with TypeError', ], }); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(webRtcTransport.enableTraceEvent(123)).rejects.toThrow( TypeError ); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(webRtcTransport.enableTraceEvent('probation')).rejects.toThrow( TypeError ); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. webRtcTransport.enableTraceEvent(['probation', 123.123]) ).rejects.toThrow(TypeError); }, 2000); @@ -816,7 +816,7 @@ test('WebRtcTransport methods reject if closed', async () => { await expect(webRtcTransport.getStats()).rejects.toThrow(Error); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(webRtcTransport.connect({})).rejects.toThrow(Error); await expect(webRtcTransport.setMaxIncomingBitrate(200000)).rejects.toThrow( diff --git a/node/src/test/test-Worker.ts b/node/src/test/test-Worker.ts index 6f1b28dedc..78fa5740a6 100644 --- a/node/src/test/test-Worker.ts +++ b/node/src/test/test-Worker.ts @@ -81,7 +81,7 @@ test('createWorker() succeeds', async () => { }, 2000); test('createWorker() with wrong settings rejects with TypeError', async () => { - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(mediasoup.createWorker({ logLevel: 'chicken' })).rejects.toThrow( TypeError ); @@ -104,7 +104,7 @@ test('createWorker() with wrong settings rejects with TypeError', async () => { ).rejects.toThrow(TypeError); await expect( - // @ts-ignore + // @ts-expect-error --- Testing purposes. mediasoup.createWorker({ appData: 'NOT-AN-OBJECT' }) ).rejects.toThrow(TypeError); }, 2000); @@ -124,7 +124,7 @@ test('worker.updateSettings() succeeds', async () => { test('worker.updateSettings() with wrong settings rejects with TypeError', async () => { const worker = await mediasoup.createWorker(); - // @ts-ignore + // @ts-expect-error --- Testing purposes. await expect(worker.updateSettings({ logLevel: 'chicken' })).rejects.toThrow( TypeError ); diff --git a/node/src/test/test-mediasoup.ts b/node/src/test/test-mediasoup.ts index 455d6472eb..4fa6db110a 100644 --- a/node/src/test/test-mediasoup.ts +++ b/node/src/test/test-mediasoup.ts @@ -22,7 +22,7 @@ test('mediasoup.getSupportedRtpCapabilities() returns the mediasoup RTP capabili // Mangle retrieved codecs to check that, if called again, // getSupportedRtpCapabilities() returns a cloned object. - // @ts-ignore + // @ts-expect-error --- Testing purposes. rtpCapabilities.codecs = 'bar'; const rtpCapabilities2 = getSupportedRtpCapabilities(); diff --git a/node/src/test/test-multiopus.ts b/node/src/test/test-multiopus.ts index d6542fb391..4b8ab50450 100644 --- a/node/src/test/test-multiopus.ts +++ b/node/src/test/test-multiopus.ts @@ -84,7 +84,7 @@ const ctx: TestContext = { }, { kind: 'audio', - uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', preferredId: 4, preferredEncrypt: false, }, diff --git a/node/src/test/test-node-sctp.ts b/node/src/test/test-node-sctp.ts index 46b2f93036..7e944661ea 100644 --- a/node/src/test/test-node-sctp.ts +++ b/node/src/test/test-node-sctp.ts @@ -1,5 +1,5 @@ import * as dgram from 'node:dgram'; -// @ts-ignore +// @ts-expect-error -- sctp library doesn't have TS types. import * as sctp from 'sctp'; import * as mediasoup from '../'; import { enhancedOnce } from '../enhancedEvents'; @@ -46,14 +46,11 @@ beforeEach(async () => { const { OS, MIS } = ctx.plainTransport.sctpParameters!; await new Promise((resolve, reject) => { - // @ts-ignore - ctx.udpSocket.connect(remoteUdpPort, remoteUdpIp, (error: Error) => { - if (error) { - reject(error); - - return; - } + ctx.udpSocket?.on('error', error => { + reject(error); + }); + ctx.udpSocket?.connect(remoteUdpPort, remoteUdpIp, () => { ctx.sctpSocket = sctp.connect({ localPort: 5000, // Required for SCTP over UDP in mediasoup. port: 5000, // Required for SCTP over UDP in mediasoup. @@ -125,18 +122,18 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn await new Promise((resolve, reject) => { sendNextMessage(); - async function sendNextMessage(): Promise { + function sendNextMessage(): void { const id = ++numSentMessages; const data = Buffer.from(String(id)); // Set ppid of type WebRTC DataChannel string. if (id < numMessages / 2) { - // @ts-ignore + // @ts-expect-errors --- sctp library needs `ppid` field.` data.ppid = sctp.PPID.WEBRTC_STRING; } // Set ppid of type WebRTC DataChannel binary. else { - // @ts-ignore + // @ts-expect-errors --- sctp library needs `ppid` field. data.ppid = sctp.PPID.WEBRTC_BINARY; } @@ -151,7 +148,7 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn ctx.sctpSocket!.on('stream', onStream); // Handle the generated SCTP incoming stream and SCTP messages receives on it. - // @ts-ignore + // @ts-expect-error --- Custom event of sctp library. ctx.sctpSocket.on('stream', (stream, streamId) => { // It must be zero because it's the first SCTP incoming stream (so first // DataConsumer). @@ -161,13 +158,12 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn return; } - // @ts-ignore stream.on('data', (data: Buffer) => { ++numReceivedMessages; recvMessageBytes += data.byteLength; const id = Number(data.toString('utf8')); - // @ts-ignore + // @ts-expect-errors --- sctp library uses `ppid` field. const ppid = data.ppid; if (id !== numReceivedMessages) { diff --git a/node/src/utils.ts b/node/src/utils.ts index eef0a53663..f7c8e8c8b9 100644 --- a/node/src/utils.ts +++ b/node/src/utils.ts @@ -72,7 +72,7 @@ export function parseVector( if (parseFn) { array.push(parseFn(binary[methodName](i))); } else { - array.push(binary[methodName](i)); + array.push(binary[methodName](i) as Type); } } @@ -165,7 +165,7 @@ export function parseStringStringArrayVector( const values: string[] = []; for (let i2 = 0; i2 < kv.valuesLength(); ++i2) { - values.push(kv.values(i2)!); + values.push(kv.values(i2)! as string); } array.push({ key: kv.key(), values }); diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 2bb7081e84..1612a46229 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -26,9 +26,12 @@ const GH_OWNER = 'versatica'; const GH_REPO = 'mediasoup'; // Paths for ESLint to check. Converted to string for convenience. -const ESLINT_PATHS = ['node/src', 'npm-scripts.mjs', 'worker/scripts'].join( - ' ' -); +const ESLINT_PATHS = [ + 'eslint.config.mjs', + 'node/src', + 'npm-scripts.mjs', + 'worker/scripts', +].join(' '); // Paths for ESLint to ignore. Converted to string argument for convenience. const ESLINT_IGNORE_PATTERN_ARGS = ['node/src/fbs'] .map(entry => `--ignore-pattern ${entry}`) @@ -42,9 +45,9 @@ const PRETTIER_PATHS = [ 'README.md', 'doc', 'node/src', - 'node/tsconfig.json', 'npm-scripts.mjs', 'package.json', + 'tsconfig.json', 'worker/scripts', ].join(' '); @@ -140,7 +143,7 @@ async function run() { case 'typescript:watch': { deleteNodeLib(); - executeCmd(`tsc --project node --watch ${args}`); + executeCmd(`tsc --watch ${args}`); break; } @@ -327,7 +330,7 @@ function buildTypescript({ force = false } = { force: false }) { logInfo('buildTypescript()'); deleteNodeLib(); - executeCmd('tsc --project node'); + executeCmd('tsc'); } function buildWorker() { @@ -356,10 +359,10 @@ function lintNode() { // Ensure there are no rules that are unnecessary or conflict with Prettier // rules. - executeCmd('eslint-config-prettier .eslintrc.js'); + executeCmd('eslint-config-prettier eslint.config.mjs'); executeCmd( - `eslint -c .eslintrc.js --ext=ts,js,mjs --max-warnings 0 ${ESLINT_IGNORE_PATTERN_ARGS} ${ESLINT_PATHS}` + `eslint -c eslint.config.mjs --max-warnings 0 ${ESLINT_IGNORE_PATTERN_ARGS} ${ESLINT_PATHS}` ); executeCmd(`prettier --check ${PRETTIER_PATHS}`); diff --git a/package-lock.json b/package-lock.json index 6e37d19f61..af31120ab7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,16 +20,16 @@ "tar": "^7.4.3" }, "devDependencies": { + "@eslint/js": "^9.8.0", "@octokit/rest": "^21.0.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^22.1.0", - "@typescript-eslint/eslint-plugin": "^7.17.0", - "@typescript-eslint/parser": "^7.17.0", - "eslint": "^8.57.0", + "eslint": "^9.8.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.7.0", "eslint-plugin-prettier": "^5.2.1", + "globals": "^15.9.0", "jest": "^29.7.0", "marked": "^13.0.3", "open-cli": "^8.0.0", @@ -37,7 +37,8 @@ "prettier": "^3.3.3", "sctp": "^1.0.0", "ts-jest": "^29.2.4", - "typescript": "^5.5.4" + "typescript": "^5.5.4", + "typescript-eslint": "^8.0.0" }, "engines": { "node": ">=18" @@ -738,24 +739,38 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", + "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -763,33 +778,40 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", + "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, "engines": { - "node": ">=10.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@humanwhocodes/module-importer": { @@ -805,11 +827,18 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "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 + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@isaacs/cliui": { "version": "8.0.2", @@ -1749,6 +1778,26 @@ "@types/ms": "*" } }, + "node_modules/@types/eslint": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/@types/graceful-fs": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", @@ -1797,6 +1846,14 @@ "pretty-format": "^29.0.0" } }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", @@ -1834,31 +1891,31 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.17.0.tgz", - "integrity": "sha512-pyiDhEuLM3PuANxH7uNYan1AaFs5XE0zw1hq69JBvGvE7gSuEoQl1ydtEe/XQeoC3GQxLXyOVa5kNOATgM638A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.0.0.tgz", + "integrity": "sha512-STIZdwEQRXAHvNUS6ILDf5z3u95Gc8jzywunxSNqX00OooIemaaNIA0vEgynJlycL5AjabYLLrIyHd4iazyvtg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.17.0", - "@typescript-eslint/type-utils": "7.17.0", - "@typescript-eslint/utils": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0", + "@typescript-eslint/scope-manager": "8.0.0", + "@typescript-eslint/type-utils": "8.0.0", + "@typescript-eslint/utils": "8.0.0", + "@typescript-eslint/visitor-keys": "8.0.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -1867,26 +1924,26 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.17.0.tgz", - "integrity": "sha512-puiYfGeg5Ydop8eusb/Hy1k7QmOU6X3nvsqCgzrB2K4qMavK//21+PzNE8qeECgNOIoertJPUC1SpegHDI515A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.0.0.tgz", + "integrity": "sha512-pS1hdZ+vnrpDIxuFXYQpLTILglTjSYJ9MbetZctrUawogUsPdz31DIIRZ9+rab0LhYNTsk88w4fIzVheiTbWOQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.17.0", - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/typescript-estree": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0", + "@typescript-eslint/scope-manager": "8.0.0", + "@typescript-eslint/types": "8.0.0", + "@typescript-eslint/typescript-estree": "8.0.0", + "@typescript-eslint/visitor-keys": "8.0.0", "debug": "^4.3.4" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -1895,16 +1952,16 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.17.0.tgz", - "integrity": "sha512-0P2jTTqyxWp9HiKLu/Vemr2Rg1Xb5B7uHItdVZ6iAenXmPo4SZ86yOPCJwMqpCyaMiEHTNqizHfsbmCFT1x9SA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.0.tgz", + "integrity": "sha512-V0aa9Csx/ZWWv2IPgTfY7T4agYwJyILESu/PVqFtTFz9RIS823mAze+NbnBI8xiwdX3iqeQbcTYlvB04G9wyQw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0" + "@typescript-eslint/types": "8.0.0", + "@typescript-eslint/visitor-keys": "8.0.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -1912,26 +1969,23 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.17.0.tgz", - "integrity": "sha512-XD3aaBt+orgkM/7Cei0XNEm1vwUxQ958AOLALzPlbPqb8C1G8PZK85tND7Jpe69Wualri81PLU+Zc48GVKIMMA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.0.0.tgz", + "integrity": "sha512-mJAFP2mZLTBwAn5WI4PMakpywfWFH5nQZezUQdSKV23Pqo6o9iShQg1hP2+0hJJXP2LnZkWPphdIq4juYYwCeg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.17.0", - "@typescript-eslint/utils": "7.17.0", + "@typescript-eslint/typescript-estree": "8.0.0", + "@typescript-eslint/utils": "8.0.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependencies": { - "eslint": "^8.56.0" - }, "peerDependenciesMeta": { "typescript": { "optional": true @@ -1939,12 +1993,12 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.17.0.tgz", - "integrity": "sha512-a29Ir0EbyKTKHnZWbNsrc/gqfIBqYPwj3F2M+jWE/9bqfEHg0AMtXzkbUkOG6QgEScxh2+Pz9OXe11jHDnHR7A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.0.tgz", + "integrity": "sha512-wgdSGs9BTMWQ7ooeHtu5quddKKs5Z5dS+fHLbrQI+ID0XWJLODGMHRfhwImiHoeO2S5Wir2yXuadJN6/l4JRxw==", "dev": true, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -1952,13 +2006,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.17.0.tgz", - "integrity": "sha512-72I3TGq93t2GoSBWI093wmKo0n6/b7O4j9o8U+f65TVD0FS6bI2180X5eGEr8MA8PhKMvYe9myZJquUT2JkCZw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.0.tgz", + "integrity": "sha512-5b97WpKMX+Y43YKi4zVcCVLtK5F98dFls3Oxui8LbnmRsseKenbbDinmvxrWegKDMmlkIq/XHuyy0UGLtpCDKg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0", + "@typescript-eslint/types": "8.0.0", + "@typescript-eslint/visitor-keys": "8.0.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1967,7 +2021,7 @@ "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2004,54 +2058,48 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.17.0.tgz", - "integrity": "sha512-r+JFlm5NdB+JXc7aWWZ3fKSm1gn0pkswEwIYsrGPdsT2GjsRATAKXiNtp3vgAAO1xZhX8alIOEQnNMl3kbTgJw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.0.0.tgz", + "integrity": "sha512-k/oS/A/3QeGLRvOWCg6/9rATJL5rec7/5s1YmdS0ZU6LHveJyGFwBvLhSRBv6i9xaj7etmosp+l+ViN1I9Aj/Q==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.17.0", - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/typescript-estree": "7.17.0" + "@typescript-eslint/scope-manager": "8.0.0", + "@typescript-eslint/types": "8.0.0", + "@typescript-eslint/typescript-estree": "8.0.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.17.0.tgz", - "integrity": "sha512-RVGC9UhPOCsfCdI9pU++K4nD7to+jTcMIbXTSOcrLqUEW6gF2pU1UUbYJKc9cvcRSK1UDeMJ7pdMxf4bhMpV/A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.0.tgz", + "integrity": "sha512-oN0K4nkHuOyF3PVMyETbpP5zp6wfyOvm7tWhTMfoqxSSsPmJIh6JNASuZDlODE8eE+0EB9uar+6+vxr9DBTYOA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.17.0", + "@typescript-eslint/types": "8.0.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.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.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -2715,18 +2763,6 @@ "node": ">=8" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -2801,41 +2837,37 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz", + "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.17.1", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.8.0", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", - "@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.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", @@ -2849,10 +2881,10 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" } }, "node_modules/eslint-config-prettier": { @@ -2923,16 +2955,16 @@ } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2950,18 +2982,42 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", "dev": true, "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -3163,15 +3219,15 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/file-type": { @@ -3250,17 +3306,16 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatbuffers": { @@ -3421,15 +3476,12 @@ } }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", + "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5450,21 +5502,6 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/run-applescript": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", @@ -6019,18 +6056,6 @@ "node": ">=4" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typescript": { "version": "5.5.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", @@ -6044,6 +6069,29 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.0.0.tgz", + "integrity": "sha512-yQWBJutWL1PmpmDddIOl9/Mi6vZjqNCjqSGBMQ4vsc2Aiodk0SnbQQWPXbSy0HNuKCuGkw1+u4aQ2mO40TdhDQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.0.0", + "@typescript-eslint/parser": "8.0.0", + "@typescript-eslint/utils": "8.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/undici-types": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", @@ -6802,44 +6850,58 @@ } }, "@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", "dev": true }, + "@eslint/config-array": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", + "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", + "dev": true, + "requires": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + } + }, "@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true + } } }, "@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", + "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", "dev": true }, - "@humanwhocodes/config-array": { - "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": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - } + "@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true }, "@humanwhocodes/module-importer": { "version": "1.0.1", @@ -6847,10 +6909,10 @@ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true }, - "@humanwhocodes/object-schema": { - "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==", + "@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", "dev": true }, "@isaacs/cliui": { @@ -7592,6 +7654,26 @@ "@types/ms": "*" } }, + "@types/eslint": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true, + "optional": true, + "peer": true + }, "@types/graceful-fs": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", @@ -7640,6 +7722,14 @@ "pretty-format": "^29.0.0" } }, + "@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "optional": true, + "peer": true + }, "@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", @@ -7676,16 +7766,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.17.0.tgz", - "integrity": "sha512-pyiDhEuLM3PuANxH7uNYan1AaFs5XE0zw1hq69JBvGvE7gSuEoQl1ydtEe/XQeoC3GQxLXyOVa5kNOATgM638A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.0.0.tgz", + "integrity": "sha512-STIZdwEQRXAHvNUS6ILDf5z3u95Gc8jzywunxSNqX00OooIemaaNIA0vEgynJlycL5AjabYLLrIyHd4iazyvtg==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.17.0", - "@typescript-eslint/type-utils": "7.17.0", - "@typescript-eslint/utils": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0", + "@typescript-eslint/scope-manager": "8.0.0", + "@typescript-eslint/type-utils": "8.0.0", + "@typescript-eslint/utils": "8.0.0", + "@typescript-eslint/visitor-keys": "8.0.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7693,54 +7783,54 @@ } }, "@typescript-eslint/parser": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.17.0.tgz", - "integrity": "sha512-puiYfGeg5Ydop8eusb/Hy1k7QmOU6X3nvsqCgzrB2K4qMavK//21+PzNE8qeECgNOIoertJPUC1SpegHDI515A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.0.0.tgz", + "integrity": "sha512-pS1hdZ+vnrpDIxuFXYQpLTILglTjSYJ9MbetZctrUawogUsPdz31DIIRZ9+rab0LhYNTsk88w4fIzVheiTbWOQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.17.0", - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/typescript-estree": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0", + "@typescript-eslint/scope-manager": "8.0.0", + "@typescript-eslint/types": "8.0.0", + "@typescript-eslint/typescript-estree": "8.0.0", + "@typescript-eslint/visitor-keys": "8.0.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.17.0.tgz", - "integrity": "sha512-0P2jTTqyxWp9HiKLu/Vemr2Rg1Xb5B7uHItdVZ6iAenXmPo4SZ86yOPCJwMqpCyaMiEHTNqizHfsbmCFT1x9SA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.0.tgz", + "integrity": "sha512-V0aa9Csx/ZWWv2IPgTfY7T4agYwJyILESu/PVqFtTFz9RIS823mAze+NbnBI8xiwdX3iqeQbcTYlvB04G9wyQw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0" + "@typescript-eslint/types": "8.0.0", + "@typescript-eslint/visitor-keys": "8.0.0" } }, "@typescript-eslint/type-utils": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.17.0.tgz", - "integrity": "sha512-XD3aaBt+orgkM/7Cei0XNEm1vwUxQ958AOLALzPlbPqb8C1G8PZK85tND7Jpe69Wualri81PLU+Zc48GVKIMMA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.0.0.tgz", + "integrity": "sha512-mJAFP2mZLTBwAn5WI4PMakpywfWFH5nQZezUQdSKV23Pqo6o9iShQg1hP2+0hJJXP2LnZkWPphdIq4juYYwCeg==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.17.0", - "@typescript-eslint/utils": "7.17.0", + "@typescript-eslint/typescript-estree": "8.0.0", + "@typescript-eslint/utils": "8.0.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.17.0.tgz", - "integrity": "sha512-a29Ir0EbyKTKHnZWbNsrc/gqfIBqYPwj3F2M+jWE/9bqfEHg0AMtXzkbUkOG6QgEScxh2+Pz9OXe11jHDnHR7A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.0.tgz", + "integrity": "sha512-wgdSGs9BTMWQ7ooeHtu5quddKKs5Z5dS+fHLbrQI+ID0XWJLODGMHRfhwImiHoeO2S5Wir2yXuadJN6/l4JRxw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.17.0.tgz", - "integrity": "sha512-72I3TGq93t2GoSBWI093wmKo0n6/b7O4j9o8U+f65TVD0FS6bI2180X5eGEr8MA8PhKMvYe9myZJquUT2JkCZw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.0.tgz", + "integrity": "sha512-5b97WpKMX+Y43YKi4zVcCVLtK5F98dFls3Oxui8LbnmRsseKenbbDinmvxrWegKDMmlkIq/XHuyy0UGLtpCDKg==", "dev": true, "requires": { - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0", + "@typescript-eslint/types": "8.0.0", + "@typescript-eslint/visitor-keys": "8.0.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7770,37 +7860,31 @@ } }, "@typescript-eslint/utils": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.17.0.tgz", - "integrity": "sha512-r+JFlm5NdB+JXc7aWWZ3fKSm1gn0pkswEwIYsrGPdsT2GjsRATAKXiNtp3vgAAO1xZhX8alIOEQnNMl3kbTgJw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.0.0.tgz", + "integrity": "sha512-k/oS/A/3QeGLRvOWCg6/9rATJL5rec7/5s1YmdS0ZU6LHveJyGFwBvLhSRBv6i9xaj7etmosp+l+ViN1I9Aj/Q==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.17.0", - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/typescript-estree": "7.17.0" + "@typescript-eslint/scope-manager": "8.0.0", + "@typescript-eslint/types": "8.0.0", + "@typescript-eslint/typescript-estree": "8.0.0" } }, "@typescript-eslint/visitor-keys": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.17.0.tgz", - "integrity": "sha512-RVGC9UhPOCsfCdI9pU++K4nD7to+jTcMIbXTSOcrLqUEW6gF2pU1UUbYJKc9cvcRSK1UDeMJ7pdMxf4bhMpV/A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.0.tgz", + "integrity": "sha512-oN0K4nkHuOyF3PVMyETbpP5zp6wfyOvm7tWhTMfoqxSSsPmJIh6JNASuZDlODE8eE+0EB9uar+6+vxr9DBTYOA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.17.0", + "@typescript-eslint/types": "8.0.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.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true }, "acorn-jsx": { @@ -8266,15 +8350,6 @@ "path-type": "^4.0.0" } }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, "eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -8328,41 +8403,37 @@ "dev": true }, "eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz", + "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.17.1", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.8.0", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", - "@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.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", @@ -8371,6 +8442,14 @@ "optionator": "^0.9.3", "strip-ansi": "^6.0.1", "text-table": "^0.2.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true + } } }, "eslint-config-prettier": { @@ -8400,9 +8479,9 @@ } }, "eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, "requires": { "esrecurse": "^4.3.0", @@ -8416,14 +8495,22 @@ "dev": true }, "espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", "dev": true, "requires": { - "acorn": "^8.9.0", + "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true + } } }, "esprima": { @@ -8574,12 +8661,12 @@ } }, "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "requires": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" } }, "file-type": { @@ -8642,14 +8729,13 @@ } }, "flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "requires": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" } }, "flatbuffers": { @@ -8760,13 +8846,10 @@ } }, "globals": { - "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" - } + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", + "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", + "dev": true }, "globby": { "version": "11.1.0", @@ -10193,15 +10276,6 @@ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, "run-applescript": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", @@ -10562,18 +10636,23 @@ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, "typescript": { "version": "5.5.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true }, + "typescript-eslint": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.0.0.tgz", + "integrity": "sha512-yQWBJutWL1PmpmDddIOl9/Mi6vZjqNCjqSGBMQ4vsc2Aiodk0SnbQQWPXbSy0HNuKCuGkw1+u4aQ2mO40TdhDQ==", + "dev": true, + "requires": { + "@typescript-eslint/eslint-plugin": "8.0.0", + "@typescript-eslint/parser": "8.0.0", + "@typescript-eslint/utils": "8.0.0" + } + }, "undici-types": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", diff --git a/package.json b/package.json index 35437050aa..ad23116f00 100644 --- a/package.json +++ b/package.json @@ -109,16 +109,16 @@ "tar": "^7.4.3" }, "devDependencies": { + "@eslint/js": "^9.8.0", "@octokit/rest": "^21.0.1", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^22.1.0", - "@typescript-eslint/eslint-plugin": "^7.17.0", - "@typescript-eslint/parser": "^7.17.0", - "eslint": "^8.57.0", + "eslint": "^9.8.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.7.0", "eslint-plugin-prettier": "^5.2.1", + "globals": "^15.9.0", "jest": "^29.7.0", "marked": "^13.0.3", "open-cli": "^8.0.0", @@ -126,6 +126,7 @@ "prettier": "^3.3.3", "sctp": "^1.0.0", "ts-jest": "^29.2.4", - "typescript": "^5.5.4" + "typescript": "^5.5.4", + "typescript-eslint": "^8.0.0" } } diff --git a/node/tsconfig.json b/tsconfig.json similarity index 83% rename from node/tsconfig.json rename to tsconfig.json index 87394576c7..1ea8a48622 100644 --- a/node/tsconfig.json +++ b/tsconfig.json @@ -1,16 +1,16 @@ { "compileOnSave": true, "compilerOptions": { - "lib": ["es2021"], + "lib": ["es2022"], "target": "esnext", "module": "commonjs", "moduleResolution": "node", "strict": true, - "outDir": "lib", + "outDir": "node/lib", "declaration": true, "declarationMap": true }, - "include": ["src"], + "include": ["node/src"], "watchOptions": { "watchFile": "useFsEvents", "watchDirectory": "useFsEvents", diff --git a/worker/scripts/clang-format.mjs b/worker/scripts/clang-format.mjs index c17152998a..c6665493b8 100644 --- a/worker/scripts/clang-format.mjs +++ b/worker/scripts/clang-format.mjs @@ -4,7 +4,7 @@ import clangFormat from 'clang-format'; const task = process.argv.slice(2).join(' '); -run(); +void run(); async function run() { const clangFormatNativeBinary = clangFormat.getNativeBinary();