mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
feat(voice)!: add new encryption methods, remove old methods (#10451)
BREAKING CHANGE: This library no longer supports using `tweetnacl` as an encryption library due to Discord deprecating the algorithms that `tweetnacl` helped us support (read more [here](https://discord.com/developers/docs/change-log#voice-encryption-modes)). Please migrate to one of: `sodium-native`, `sodium`, `@stablelib/xchacha20poly1305`, `@noble/ciphers` or `libsodium-wrappers` unless your system supports `aes-256-gcm` (verify by running `require('node:crypto').getCiphers().includes('aes-256-gcm')`). --------- Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com> Co-authored-by: Vlad Frangu <me@vladfrangu.dev>
This commit is contained in:
@@ -53,7 +53,8 @@ try installing another.
|
|||||||
|
|
||||||
- `sodium-native`: ^3.3.0
|
- `sodium-native`: ^3.3.0
|
||||||
- `sodium`: ^3.0.2
|
- `sodium`: ^3.0.2
|
||||||
- `tweetnacl`: ^1.0.3
|
- `@stablelib/xchacha20poly1305`: ^2.0.0
|
||||||
|
- `@noble/ciphers`: ^1.0.0
|
||||||
- `libsodium-wrappers`: ^0.7.9
|
- `libsodium-wrappers`: ^0.7.9
|
||||||
|
|
||||||
**Opus Libraries (npm install):**
|
**Opus Libraries (npm install):**
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
import { Buffer } from 'node:buffer';
|
import { Buffer } from 'node:buffer';
|
||||||
|
|
||||||
|
// The following constants are silence packets collected from various platforms because Discord did not previously send header extensions
|
||||||
|
// The header extension (extra data in decrypted vs opusFrame) can be detected in the position of {encrypted.subarray(12,14)} if it is equal to 0xbe,0xde
|
||||||
|
// The header extension length will then follow as an integer and can be removed from the decrypted data (see ../src/receive/VoiceReceiver.ts:parsePacket)
|
||||||
|
|
||||||
export const RTP_PACKET_DESKTOP = {
|
export const RTP_PACKET_DESKTOP = {
|
||||||
ssrc: 341_124,
|
ssrc: 341_124,
|
||||||
packet: Buffer.from([
|
packet: Buffer.from([
|
||||||
0x90, 0x78, 0x27, 0xe9, 0xf7, 0xcb, 0xbc, 0xd1, 0x0, 0x5, 0x34, 0x84, 0x8a, 0xbb, 0xe2, 0x97, 0x21, 0x9f, 0x1f,
|
0x90, 0x78, 0x27, 0xe9, 0xf7, 0xcb, 0xbc, 0xd1, 0x0, 0x5, 0x34, 0x84, 0xbe, 0xde, 0x0, 0x1, 0x8a, 0xbb, 0xe2, 0x97,
|
||||||
0x67, 0xcd, 0x17, 0x91, 0x56, 0x43, 0xa0, 0x98, 0xfd, 0xa9, 0x25, 0x81, 0x63, 0x13, 0xb4, 0x1e, 0xae, 0x88, 0xe4,
|
0x21, 0x9f, 0x1f, 0x67, 0xcd, 0x17, 0x91, 0x56, 0x43, 0xa0, 0x98, 0xfd, 0xa9, 0x25, 0x81, 0x63, 0x13, 0xb4, 0x1e,
|
||||||
0x0, 0xed, 0x0, 0x0, 0x0,
|
0xae, 0x88, 0xe4, 0x0, 0xed, 0x0, 0x0, 0x0,
|
||||||
]),
|
]),
|
||||||
decrypted: Buffer.from([0xbe, 0xde, 0x0, 0x1, 0x10, 0xff, 0x90, 0x0, 0xf8, 0xff, 0xfe]),
|
decrypted: Buffer.from([0x10, 0xff, 0x90, 0x0, 0xf8, 0xff, 0xfe]),
|
||||||
opusFrame: Buffer.from([0xf8, 0xff, 0xfe]),
|
opusFrame: Buffer.from([0xf8, 0xff, 0xfe]),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -24,10 +28,43 @@ export const RTP_PACKET_CHROME = {
|
|||||||
export const RTP_PACKET_ANDROID = {
|
export const RTP_PACKET_ANDROID = {
|
||||||
ssrc: 172_596,
|
ssrc: 172_596,
|
||||||
packet: Buffer.from([
|
packet: Buffer.from([
|
||||||
0x90, 0x78, 0x39, 0xd0, 0xe0, 0x59, 0xf5, 0x47, 0x0, 0x2, 0xa2, 0x34, 0x12, 0x6d, 0x87, 0x56, 0x25, 0xc8, 0x3e,
|
0x90, 0x78, 0x39, 0xd0, 0xe0, 0x59, 0xf5, 0x47, 0x0, 0x2, 0xa2, 0x34, 0xbe, 0xde, 0x0, 0x1, 0x12, 0x6d, 0x87, 0x56,
|
||||||
0x96, 0xc0, 0x71, 0x9a, 0x1, 0x83, 0xe, 0x1, 0x62, 0x91, 0x95, 0x1f, 0x76, 0x57, 0x15, 0x41, 0xab, 0xee, 0x5b, 0xac,
|
0x25, 0xc8, 0x3e, 0x96, 0xc0, 0x71, 0x9a, 0x1, 0x83, 0xe, 0x1, 0x62, 0x91, 0x95, 0x1f, 0x76, 0x57, 0x15, 0x41, 0xab,
|
||||||
0x8b, 0x0, 0x0, 0x0,
|
0xee, 0x5b, 0xac, 0x8b, 0x0, 0x0, 0x0,
|
||||||
]),
|
]),
|
||||||
decrypted: Buffer.from([0xbe, 0xde, 0x0, 0x1, 0x10, 0xff, 0x90, 0x0, 0xf8, 0xff, 0xfe]),
|
decrypted: Buffer.from([0x10, 0xff, 0x90, 0x0, 0xf8, 0xff, 0xfe]),
|
||||||
opusFrame: Buffer.from([0xf8, 0xff, 0xfe]),
|
opusFrame: Buffer.from([0xf8, 0xff, 0xfe]),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const XCHACHA20_SAMPLE = {
|
||||||
|
encrypted: Buffer.from([
|
||||||
|
144, 120, 86, 102, 191, 243, 52, 48, 0, 0, 191, 25, 190, 222, 0, 2, 211, 29, 103, 76, 73, 102, 37, 162, 65, 41, 39,
|
||||||
|
252, 26, 85, 90, 228, 241, 169, 112, 65, 95, 183, 236, 4, 87, 207, 215, 195, 180, 39, 60, 224, 221, 89, 32, 187,
|
||||||
|
208, 228, 145, 252, 132, 189, 103, 208, 180, 183, 217, 50, 70, 86, 20, 28, 142, 66, 251, 122, 214, 17, 7, 173, 203,
|
||||||
|
117, 148, 232, 118, 103, 8, 136, 227, 136, 249, 243, 135, 41, 31, 103, 146, 15, 1, 0, 0,
|
||||||
|
]),
|
||||||
|
key: new Uint8Array([
|
||||||
|
105, 217, 109, 27, 247, 101, 71, 49, 71, 151, 172, 85, 91, 11, 201, 23, 43, 242, 147, 81, 96, 60, 157, 50, 63, 200,
|
||||||
|
133, 174, 108, 144, 251, 110,
|
||||||
|
]),
|
||||||
|
|
||||||
|
decrypted: Buffer.from([
|
||||||
|
0x32, 0x64, 0xe6, 0x62, 0x10, 0xe3, 0x90, 0x02, 0x78, 0x07, 0xd6, 0x2f, 0x52, 0x23, 0x20, 0x9a, 0xab, 0x2c, 0xcc,
|
||||||
|
0x1c, 0x88, 0x8e, 0xcb, 0xd9, 0x4d, 0xe5, 0x33, 0x7a, 0x4b, 0x2b, 0xed, 0xa7, 0xaf, 0x5f, 0x8d, 0xb2, 0x59, 0x99,
|
||||||
|
0x75, 0x36, 0xf2, 0x88, 0xf5, 0xc7, 0x9f, 0x47, 0xaf, 0x92, 0x5a, 0x96, 0x3b, 0xd8, 0x9f, 0x3a, 0xb4, 0x13, 0xce,
|
||||||
|
0x2f, 0xae, 0x0a, 0x37,
|
||||||
|
]),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AES256GCM_SAMPLE = {
|
||||||
|
encrypted: Buffer.from([
|
||||||
|
128, 120, 163, 156, 159, 11, 131, 240, 0, 0, 197, 183, 175, 91, 102, 101, 195, 6, 200, 143, 117, 72, 108, 44, 165,
|
||||||
|
123, 121, 49, 111, 38, 3, 0, 0, 0, 90,
|
||||||
|
]),
|
||||||
|
key: Buffer.from([
|
||||||
|
109, 77, 195, 27, 111, 50, 231, 84, 179, 255, 217, 217, 34, 227, 19, 106, 195, 20, 150, 237, 38, 4, 101, 210, 5, 90,
|
||||||
|
8, 241, 58, 223, 24, 24,
|
||||||
|
]),
|
||||||
|
|
||||||
|
decrypted: Buffer.from([0xf8, 0xff, 0xfe]),
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
import { test, expect, vitest } from 'vitest';
|
import { test, expect, vitest } from 'vitest';
|
||||||
import { methods } from '../src/util/Secretbox';
|
import { methods, secretboxLoadPromise } from '../src/util/Secretbox';
|
||||||
|
|
||||||
vitest.mock('tweetnacl');
|
vitest.mock('@noble/ciphers/chacha');
|
||||||
|
|
||||||
test('Does not throw error with a package installed', () => {
|
// TODO: what is this even testing exactly?
|
||||||
// @ts-expect-error We are testing
|
test.skip('Does not throw error with a package installed', async () => {
|
||||||
expect(() => methods.open()).toThrow(TypeError);
|
// The async loop in Secretbox will not have finished importing unless we wait
|
||||||
|
await secretboxLoadPromise;
|
||||||
|
|
||||||
|
expect(() => methods.crypto_aead_xchacha20poly1305_ietf_decrypt()).not.toThrowError();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,7 +6,13 @@ import { once } from 'node:events';
|
|||||||
import process from 'node:process';
|
import process from 'node:process';
|
||||||
import { VoiceOpcodes } from 'discord-api-types/voice/v4';
|
import { VoiceOpcodes } from 'discord-api-types/voice/v4';
|
||||||
import { describe, test, expect, vitest, beforeEach } from 'vitest';
|
import { describe, test, expect, vitest, beforeEach } from 'vitest';
|
||||||
import { RTP_PACKET_DESKTOP, RTP_PACKET_CHROME, RTP_PACKET_ANDROID } from '../__mocks__/rtp';
|
import {
|
||||||
|
RTP_PACKET_DESKTOP,
|
||||||
|
RTP_PACKET_CHROME,
|
||||||
|
RTP_PACKET_ANDROID,
|
||||||
|
XCHACHA20_SAMPLE,
|
||||||
|
AES256GCM_SAMPLE,
|
||||||
|
} from '../__mocks__/rtp';
|
||||||
import { VoiceConnection, VoiceConnectionStatus } from '../src/VoiceConnection';
|
import { VoiceConnection, VoiceConnectionStatus } from '../src/VoiceConnection';
|
||||||
import { VoiceReceiver } from '../src/receive/VoiceReceiver';
|
import { VoiceReceiver } from '../src/receive/VoiceReceiver';
|
||||||
import { methods } from '../src/util/Secretbox';
|
import { methods } from '../src/util/Secretbox';
|
||||||
@@ -22,10 +28,6 @@ vitest.mock('../src/VoiceConnection', async (importOriginal) => {
|
|||||||
|
|
||||||
vitest.mock('../src/receive/SSRCMap');
|
vitest.mock('../src/receive/SSRCMap');
|
||||||
|
|
||||||
const openSpy = vitest.spyOn(methods, 'open');
|
|
||||||
|
|
||||||
openSpy.mockImplementation((buffer) => buffer);
|
|
||||||
|
|
||||||
async function nextTick() {
|
async function nextTick() {
|
||||||
// eslint-disable-next-line no-promise-executor-return
|
// eslint-disable-next-line no-promise-executor-return
|
||||||
return new Promise((resolve) => process.nextTick(resolve));
|
return new Promise((resolve) => process.nextTick(resolve));
|
||||||
@@ -62,7 +64,7 @@ describe('VoiceReceiver', () => {
|
|||||||
['RTP Packet Desktop', RTP_PACKET_DESKTOP],
|
['RTP Packet Desktop', RTP_PACKET_DESKTOP],
|
||||||
['RTP Packet Chrome', RTP_PACKET_CHROME],
|
['RTP Packet Chrome', RTP_PACKET_CHROME],
|
||||||
['RTP Packet Android', RTP_PACKET_ANDROID],
|
['RTP Packet Android', RTP_PACKET_ANDROID],
|
||||||
])('onUdpMessage: %s', async (testName, RTP_PACKET) => {
|
])('onUdpMessage: decrypt from %s', async (testName, RTP_PACKET) => {
|
||||||
receiver['decrypt'] = vitest.fn().mockImplementationOnce(() => RTP_PACKET.decrypted);
|
receiver['decrypt'] = vitest.fn().mockImplementationOnce(() => RTP_PACKET.decrypted);
|
||||||
|
|
||||||
const spy = vitest.spyOn(receiver.ssrcMap, 'get');
|
const spy = vitest.spyOn(receiver.ssrcMap, 'get');
|
||||||
@@ -174,47 +176,42 @@ describe('VoiceReceiver', () => {
|
|||||||
describe('decrypt', () => {
|
describe('decrypt', () => {
|
||||||
const secretKey = new Uint8Array([1, 2, 3, 4]);
|
const secretKey = new Uint8Array([1, 2, 3, 4]);
|
||||||
|
|
||||||
beforeEach(() => {
|
test('decrypt: aead_xchacha20_poly1305_rtpsize', () => {
|
||||||
openSpy.mockClear();
|
const nonceSpace = Buffer.alloc(24);
|
||||||
|
|
||||||
|
const decrypted = receiver['decrypt'](
|
||||||
|
XCHACHA20_SAMPLE.encrypted,
|
||||||
|
'aead_xchacha20_poly1305_rtpsize',
|
||||||
|
nonceSpace,
|
||||||
|
XCHACHA20_SAMPLE.key,
|
||||||
|
);
|
||||||
|
|
||||||
|
const expectedNonce = Buffer.concat([
|
||||||
|
XCHACHA20_SAMPLE.encrypted.slice(XCHACHA20_SAMPLE.encrypted.length - 4),
|
||||||
|
Buffer.alloc(20),
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(nonceSpace.equals(expectedNonce)).toEqual(true);
|
||||||
|
expect(decrypted.equals(XCHACHA20_SAMPLE.decrypted)).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('decrypt: xsalsa20_poly1305_lite', () => {
|
test('decrypt: aead_aes256gcm_rtpsize', () => {
|
||||||
// Arrange
|
const nonceSpace = Buffer.alloc(12);
|
||||||
const buffer = range(1, 32);
|
|
||||||
const nonce = Buffer.alloc(4);
|
|
||||||
|
|
||||||
// Act
|
const decrypted = receiver['decrypt'](
|
||||||
const decrypted = receiver['decrypt'](buffer, 'xsalsa20_poly1305_lite', nonce, secretKey);
|
AES256GCM_SAMPLE.encrypted,
|
||||||
|
'aead_aes256_gcm_rtpsize',
|
||||||
|
nonceSpace,
|
||||||
|
AES256GCM_SAMPLE.key,
|
||||||
|
);
|
||||||
|
|
||||||
// Assert
|
const expectedNonce = Buffer.concat([
|
||||||
expect(nonce.equals(range(29, 32))).toEqual(true);
|
AES256GCM_SAMPLE.encrypted.subarray(AES256GCM_SAMPLE.encrypted.length - 4),
|
||||||
expect(decrypted!.equals(range(13, 28))).toEqual(true);
|
Buffer.alloc(8),
|
||||||
});
|
]);
|
||||||
|
|
||||||
test('decrypt: xsalsa20_poly1305_suffix', () => {
|
expect(nonceSpace.equals(expectedNonce)).toEqual(true);
|
||||||
// Arrange
|
expect(decrypted.equals(AES256GCM_SAMPLE.decrypted)).toEqual(true);
|
||||||
const buffer = range(1, 64);
|
|
||||||
const nonce = Buffer.alloc(24);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
const decrypted = receiver['decrypt'](buffer, 'xsalsa20_poly1305_suffix', nonce, secretKey);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
expect(nonce.equals(range(41, 64))).toEqual(true);
|
|
||||||
expect(decrypted!.equals(range(13, 40))).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('decrypt: xsalsa20_poly1305', () => {
|
|
||||||
// Arrange
|
|
||||||
const buffer = range(1, 64);
|
|
||||||
const nonce = Buffer.alloc(12);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
const decrypted = receiver['decrypt'](buffer, 'xsalsa20_poly1305', nonce, secretKey);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
expect(nonce.equals(range(1, 12))).toEqual(true);
|
|
||||||
expect(decrypted!.equals(range(13, 64))).toEqual(true);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -74,6 +74,7 @@
|
|||||||
"@discordjs/opus": "^0.9.0",
|
"@discordjs/opus": "^0.9.0",
|
||||||
"@discordjs/scripts": "workspace:^",
|
"@discordjs/scripts": "workspace:^",
|
||||||
"@favware/cliff-jumper": "^4.1.0",
|
"@favware/cliff-jumper": "^4.1.0",
|
||||||
|
"@noble/ciphers": "^1.0.0",
|
||||||
"@types/node": "18.19.45",
|
"@types/node": "18.19.45",
|
||||||
"@vitest/coverage-v8": "2.0.5",
|
"@vitest/coverage-v8": "2.0.5",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
@@ -84,7 +85,6 @@
|
|||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"tsup": "^8.2.4",
|
"tsup": "^8.2.4",
|
||||||
"turbo": "^2.0.14",
|
"turbo": "^2.0.14",
|
||||||
"tweetnacl": "^1.0.3",
|
|
||||||
"typescript": "~5.5.4",
|
"typescript": "~5.5.4",
|
||||||
"vitest": "^2.0.5",
|
"vitest": "^2.0.5",
|
||||||
"vitest-websocket-mock": "^0.3.0"
|
"vitest-websocket-mock": "^0.3.0"
|
||||||
|
|||||||
@@ -3,5 +3,7 @@ import { readFile, writeFile } from 'node:fs/promises';
|
|||||||
const data = await readFile('./dist/index.mjs', 'utf8');
|
const data = await readFile('./dist/index.mjs', 'utf8');
|
||||||
await writeFile(
|
await writeFile(
|
||||||
'./dist/index.mjs',
|
'./dist/index.mjs',
|
||||||
`import{createRequire as topLevelCreateRequire}from"module";const require=topLevelCreateRequire(import.meta.url);${data}`,
|
`import { createRequire as topLevelCreateRequire } from "module";
|
||||||
|
const require = topLevelCreateRequire(import.meta.url);
|
||||||
|
${data}`,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
/* eslint-disable id-length */
|
/* eslint-disable id-length */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
import { Buffer } from 'node:buffer';
|
import { Buffer } from 'node:buffer';
|
||||||
|
import crypto from 'node:crypto';
|
||||||
import { EventEmitter } from 'node:events';
|
import { EventEmitter } from 'node:events';
|
||||||
import { VoiceOpcodes } from 'discord-api-types/voice/v4';
|
import { VoiceOpcodes } from 'discord-api-types/voice/v4';
|
||||||
import type { CloseEvent } from 'ws';
|
import type { CloseEvent } from 'ws';
|
||||||
@@ -15,7 +16,12 @@ const CHANNELS = 2;
|
|||||||
const TIMESTAMP_INC = (48_000 / 100) * CHANNELS;
|
const TIMESTAMP_INC = (48_000 / 100) * CHANNELS;
|
||||||
const MAX_NONCE_SIZE = 2 ** 32 - 1;
|
const MAX_NONCE_SIZE = 2 ** 32 - 1;
|
||||||
|
|
||||||
export const SUPPORTED_ENCRYPTION_MODES = ['xsalsa20_poly1305_lite', 'xsalsa20_poly1305_suffix', 'xsalsa20_poly1305'];
|
export const SUPPORTED_ENCRYPTION_MODES = ['aead_xchacha20_poly1305_rtpsize'];
|
||||||
|
|
||||||
|
// Just in case there's some system that doesn't come with aes-256-gcm, conditionally add it as supported
|
||||||
|
if (crypto.getCiphers().includes('aes-256-gcm')) {
|
||||||
|
SUPPORTED_ENCRYPTION_MODES.unshift('aead_aes256_gcm_rtpsize');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The different statuses that a networking instance can hold. The order
|
* The different statuses that a networking instance can hold. The order
|
||||||
@@ -187,6 +193,7 @@ function stringifyState(state: NetworkingState) {
|
|||||||
function chooseEncryptionMode(options: string[]): string {
|
function chooseEncryptionMode(options: string[]): string {
|
||||||
const option = options.find((option) => SUPPORTED_ENCRYPTION_MODES.includes(option));
|
const option = options.find((option) => SUPPORTED_ENCRYPTION_MODES.includes(option));
|
||||||
if (!option) {
|
if (!option) {
|
||||||
|
// This should only ever happen if the gateway does not give us any encryption modes we support.
|
||||||
throw new Error(`No compatible encryption modes. Available include: ${options.join(', ')}`);
|
throw new Error(`No compatible encryption modes. Available include: ${options.join(', ')}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,7 +449,7 @@ export class Networking extends EventEmitter {
|
|||||||
sequence: randomNBit(16),
|
sequence: randomNBit(16),
|
||||||
timestamp: randomNBit(32),
|
timestamp: randomNBit(32),
|
||||||
nonce: 0,
|
nonce: 0,
|
||||||
nonceBuffer: Buffer.alloc(24),
|
nonceBuffer: encryptionMode === 'aead_aes256_gcm_rtpsize' ? Buffer.alloc(12) : Buffer.alloc(24),
|
||||||
speaking: false,
|
speaking: false,
|
||||||
packetsPlayed: 0,
|
packetsPlayed: 0,
|
||||||
},
|
},
|
||||||
@@ -554,18 +561,18 @@ export class Networking extends EventEmitter {
|
|||||||
* @param connectionData - The current connection data of the instance
|
* @param connectionData - The current connection data of the instance
|
||||||
*/
|
*/
|
||||||
private createAudioPacket(opusPacket: Buffer, connectionData: ConnectionData) {
|
private createAudioPacket(opusPacket: Buffer, connectionData: ConnectionData) {
|
||||||
const packetBuffer = Buffer.alloc(12);
|
const rtpHeader = Buffer.alloc(12);
|
||||||
packetBuffer[0] = 0x80;
|
rtpHeader[0] = 0x80;
|
||||||
packetBuffer[1] = 0x78;
|
rtpHeader[1] = 0x78;
|
||||||
|
|
||||||
const { sequence, timestamp, ssrc } = connectionData;
|
const { sequence, timestamp, ssrc } = connectionData;
|
||||||
|
|
||||||
packetBuffer.writeUIntBE(sequence, 2, 2);
|
rtpHeader.writeUIntBE(sequence, 2, 2);
|
||||||
packetBuffer.writeUIntBE(timestamp, 4, 4);
|
rtpHeader.writeUIntBE(timestamp, 4, 4);
|
||||||
packetBuffer.writeUIntBE(ssrc, 8, 4);
|
rtpHeader.writeUIntBE(ssrc, 8, 4);
|
||||||
|
|
||||||
packetBuffer.copy(nonce, 0, 0, 12);
|
rtpHeader.copy(nonce, 0, 0, 12);
|
||||||
return Buffer.concat([packetBuffer, ...this.encryptOpusPacket(opusPacket, connectionData)]);
|
return Buffer.concat([rtpHeader, ...this.encryptOpusPacket(opusPacket, connectionData, rtpHeader)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -574,22 +581,43 @@ export class Networking extends EventEmitter {
|
|||||||
* @param opusPacket - The Opus packet to encrypt
|
* @param opusPacket - The Opus packet to encrypt
|
||||||
* @param connectionData - The current connection data of the instance
|
* @param connectionData - The current connection data of the instance
|
||||||
*/
|
*/
|
||||||
private encryptOpusPacket(opusPacket: Buffer, connectionData: ConnectionData) {
|
private encryptOpusPacket(opusPacket: Buffer, connectionData: ConnectionData, additionalData: Buffer) {
|
||||||
const { secretKey, encryptionMode } = connectionData;
|
const { secretKey, encryptionMode } = connectionData;
|
||||||
|
|
||||||
if (encryptionMode === 'xsalsa20_poly1305_lite') {
|
// Both supported encryption methods want the nonce to be an incremental integer
|
||||||
connectionData.nonce++;
|
connectionData.nonce++;
|
||||||
if (connectionData.nonce > MAX_NONCE_SIZE) connectionData.nonce = 0;
|
if (connectionData.nonce > MAX_NONCE_SIZE) connectionData.nonce = 0;
|
||||||
connectionData.nonceBuffer.writeUInt32BE(connectionData.nonce, 0);
|
connectionData.nonceBuffer.writeUInt32BE(connectionData.nonce, 0);
|
||||||
return [
|
|
||||||
secretbox.methods.close(opusPacket, connectionData.nonceBuffer, secretKey),
|
|
||||||
connectionData.nonceBuffer.slice(0, 4),
|
|
||||||
];
|
|
||||||
} else if (encryptionMode === 'xsalsa20_poly1305_suffix') {
|
|
||||||
const random = secretbox.methods.random(24, connectionData.nonceBuffer);
|
|
||||||
return [secretbox.methods.close(opusPacket, random, secretKey), random];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [secretbox.methods.close(opusPacket, nonce, secretKey)];
|
// 4 extra bytes of padding on the end of the encrypted packet
|
||||||
|
const noncePadding = connectionData.nonceBuffer.subarray(0, 4);
|
||||||
|
|
||||||
|
let encrypted;
|
||||||
|
switch (encryptionMode) {
|
||||||
|
case 'aead_aes256_gcm_rtpsize': {
|
||||||
|
const cipher = crypto.createCipheriv('aes-256-gcm', secretKey, connectionData.nonceBuffer);
|
||||||
|
cipher.setAAD(additionalData);
|
||||||
|
|
||||||
|
encrypted = Buffer.concat([cipher.update(opusPacket), cipher.final(), cipher.getAuthTag()]);
|
||||||
|
|
||||||
|
return [encrypted, noncePadding];
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'aead_xchacha20_poly1305_rtpsize': {
|
||||||
|
encrypted = secretbox.methods.crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||||
|
opusPacket,
|
||||||
|
additionalData,
|
||||||
|
connectionData.nonceBuffer,
|
||||||
|
secretKey,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [encrypted, noncePadding];
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
// This should never happen. Our encryption mode is chosen from a list given to us by the gateway and checked with the ones we support.
|
||||||
|
throw new RangeError(`Unsupported encryption method: ${encryptionMode}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/* eslint-disable jsdoc/check-param-names */
|
/* eslint-disable jsdoc/check-param-names */
|
||||||
|
|
||||||
import { Buffer } from 'node:buffer';
|
import { Buffer } from 'node:buffer';
|
||||||
|
import crypto from 'node:crypto';
|
||||||
import { VoiceOpcodes } from 'discord-api-types/voice/v4';
|
import { VoiceOpcodes } from 'discord-api-types/voice/v4';
|
||||||
import type { VoiceConnection } from '../VoiceConnection';
|
import type { VoiceConnection } from '../VoiceConnection';
|
||||||
import type { ConnectionData } from '../networking/Networking';
|
import type { ConnectionData } from '../networking/Networking';
|
||||||
@@ -13,6 +14,10 @@ import {
|
|||||||
import { SSRCMap } from './SSRCMap';
|
import { SSRCMap } from './SSRCMap';
|
||||||
import { SpeakingMap } from './SpeakingMap';
|
import { SpeakingMap } from './SpeakingMap';
|
||||||
|
|
||||||
|
const HEADER_EXTENSION_BYTE = Buffer.from([0xbe, 0xde]);
|
||||||
|
const UNPADDED_NONCE_LENGTH = 4;
|
||||||
|
const AUTH_TAG_LENGTH = 16;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaches to a VoiceConnection, allowing you to receive audio packets from other
|
* Attaches to a VoiceConnection, allowing you to receive audio packets from other
|
||||||
* users that are speaking.
|
* users that are speaking.
|
||||||
@@ -87,22 +92,48 @@ export class VoiceReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private decrypt(buffer: Buffer, mode: string, nonce: Buffer, secretKey: Uint8Array) {
|
private decrypt(buffer: Buffer, mode: string, nonce: Buffer, secretKey: Uint8Array) {
|
||||||
// Choose correct nonce depending on encryption
|
// Copy the last 4 bytes of unpadded nonce to the padding of (12 - 4) or (24 - 4) bytes
|
||||||
let end;
|
buffer.copy(nonce, 0, buffer.length - UNPADDED_NONCE_LENGTH);
|
||||||
if (mode === 'xsalsa20_poly1305_lite') {
|
|
||||||
buffer.copy(nonce, 0, buffer.length - 4);
|
|
||||||
end = buffer.length - 4;
|
|
||||||
} else if (mode === 'xsalsa20_poly1305_suffix') {
|
|
||||||
buffer.copy(nonce, 0, buffer.length - 24);
|
|
||||||
end = buffer.length - 24;
|
|
||||||
} else {
|
|
||||||
buffer.copy(nonce, 0, 0, 12);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open packet
|
let headerSize = 12;
|
||||||
const decrypted = methods.open(buffer.slice(12, end), nonce, secretKey);
|
const first = buffer.readUint8();
|
||||||
if (!decrypted) return;
|
if ((first >> 4) & 0x01) headerSize += 4;
|
||||||
return Buffer.from(decrypted);
|
|
||||||
|
// The unencrypted RTP header contains 12 bytes, HEADER_EXTENSION and the extension size
|
||||||
|
const header = buffer.subarray(0, headerSize);
|
||||||
|
|
||||||
|
// Encrypted contains the extension, if any, the opus packet, and the auth tag
|
||||||
|
const encrypted = buffer.subarray(headerSize, buffer.length - AUTH_TAG_LENGTH - UNPADDED_NONCE_LENGTH);
|
||||||
|
const authTag = buffer.subarray(
|
||||||
|
buffer.length - AUTH_TAG_LENGTH - UNPADDED_NONCE_LENGTH,
|
||||||
|
buffer.length - UNPADDED_NONCE_LENGTH,
|
||||||
|
);
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case 'aead_aes256_gcm_rtpsize': {
|
||||||
|
const decipheriv = crypto.createDecipheriv('aes-256-gcm', secretKey, nonce);
|
||||||
|
decipheriv.setAAD(header);
|
||||||
|
decipheriv.setAuthTag(authTag);
|
||||||
|
|
||||||
|
return Buffer.concat([decipheriv.update(encrypted), decipheriv.final()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'aead_xchacha20_poly1305_rtpsize': {
|
||||||
|
// Combined mode expects authtag in the encrypted message
|
||||||
|
return Buffer.from(
|
||||||
|
methods.crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||||
|
Buffer.concat([encrypted, authTag]),
|
||||||
|
header,
|
||||||
|
nonce,
|
||||||
|
secretKey,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
throw new RangeError(`Unsupported decryption method: ${mode}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -118,10 +149,11 @@ export class VoiceReceiver {
|
|||||||
let packet = this.decrypt(buffer, mode, nonce, secretKey);
|
let packet = this.decrypt(buffer, mode, nonce, secretKey);
|
||||||
if (!packet) return;
|
if (!packet) return;
|
||||||
|
|
||||||
// Strip RTP Header Extensions (one-byte only)
|
// Strip decrypted RTP Header Extension if present
|
||||||
if (packet[0] === 0xbe && packet[1] === 0xde) {
|
// The header is only indicated in the original data, so compare with buffer first
|
||||||
const headerExtensionLength = packet.readUInt16BE(2);
|
if (buffer.subarray(12, 14).compare(HEADER_EXTENSION_BYTE) === 0) {
|
||||||
packet = packet.subarray(4 + 4 * headerExtensionLength);
|
const headerExtensionLength = buffer.subarray(14).readUInt16BE();
|
||||||
|
packet = packet.subarray(4 * headerExtensionLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
return packet;
|
return packet;
|
||||||
|
|||||||
@@ -1,75 +1,135 @@
|
|||||||
import { Buffer } from 'node:buffer';
|
import { Buffer } from 'node:buffer';
|
||||||
|
|
||||||
interface Methods {
|
interface Methods {
|
||||||
close(opusPacket: Buffer, nonce: Buffer, secretKey: Uint8Array): Buffer;
|
crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||||
open(buffer: Buffer, nonce: Buffer, secretKey: Uint8Array): Buffer | null;
|
cipherText: Buffer,
|
||||||
random(bytes: number, nonce: Buffer): Buffer;
|
additionalData: Buffer,
|
||||||
|
nonce: Buffer,
|
||||||
|
key: ArrayBufferLike,
|
||||||
|
): Buffer;
|
||||||
|
crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||||
|
plaintext: Buffer,
|
||||||
|
additionalData: Buffer,
|
||||||
|
nonce: Buffer,
|
||||||
|
key: ArrayBufferLike,
|
||||||
|
): Buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
const libs = {
|
const libs = {
|
||||||
'sodium-native': (sodium: any): Methods => ({
|
'sodium-native': (sodium: any): Methods => ({
|
||||||
open: (buffer: Buffer, nonce: Buffer, secretKey: Uint8Array) => {
|
crypto_aead_xchacha20poly1305_ietf_decrypt: (
|
||||||
if (buffer) {
|
cipherText: Buffer,
|
||||||
const output = Buffer.allocUnsafe(buffer.length - sodium.crypto_box_MACBYTES);
|
additionalData: Buffer,
|
||||||
if (sodium.crypto_secretbox_open_easy(output, buffer, nonce, secretKey)) return output;
|
nonce: Buffer,
|
||||||
}
|
key: ArrayBufferLike,
|
||||||
|
) => {
|
||||||
return null;
|
const message = Buffer.alloc(cipherText.length - sodium.crypto_aead_xchacha20poly1305_ietf_ABYTES);
|
||||||
|
sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(message, null, cipherText, additionalData, nonce, key);
|
||||||
|
return message;
|
||||||
},
|
},
|
||||||
close: (opusPacket: Buffer, nonce: Buffer, secretKey: Uint8Array) => {
|
crypto_aead_xchacha20poly1305_ietf_encrypt: (
|
||||||
const output = Buffer.allocUnsafe(opusPacket.length + sodium.crypto_box_MACBYTES);
|
plaintext: Buffer,
|
||||||
sodium.crypto_secretbox_easy(output, opusPacket, nonce, secretKey);
|
additionalData: Buffer,
|
||||||
return output;
|
nonce: Buffer,
|
||||||
},
|
key: ArrayBufferLike,
|
||||||
random: (num: number, buffer: Buffer = Buffer.allocUnsafe(num)) => {
|
) => {
|
||||||
sodium.randombytes_buf(buffer);
|
const cipherText = Buffer.alloc(plaintext.length + sodium.crypto_aead_xchacha20poly1305_ietf_ABYTES);
|
||||||
return buffer;
|
sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(cipherText, plaintext, additionalData, null, nonce, key);
|
||||||
|
return cipherText;
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
sodium: (sodium: any): Methods => ({
|
sodium: (sodium: any): Methods => ({
|
||||||
open: sodium.api.crypto_secretbox_open_easy,
|
crypto_aead_xchacha20poly1305_ietf_decrypt: (
|
||||||
close: sodium.api.crypto_secretbox_easy,
|
cipherText: Buffer,
|
||||||
random: (num: number, buffer: Buffer = Buffer.allocUnsafe(num)) => {
|
additionalData: Buffer,
|
||||||
sodium.api.randombytes_buf(buffer);
|
nonce: Buffer,
|
||||||
return buffer;
|
key: ArrayBufferLike,
|
||||||
|
) => {
|
||||||
|
return sodium.api.crypto_aead_xchacha20poly1305_ietf_decrypt(cipherText, additionalData, null, nonce, key);
|
||||||
|
},
|
||||||
|
crypto_aead_xchacha20poly1305_ietf_encrypt: (
|
||||||
|
plaintext: Buffer,
|
||||||
|
additionalData: Buffer,
|
||||||
|
nonce: Buffer,
|
||||||
|
key: ArrayBufferLike,
|
||||||
|
) => {
|
||||||
|
return sodium.api.crypto_aead_xchacha20poly1305_ietf_encrypt(plaintext, additionalData, null, nonce, key);
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
'libsodium-wrappers': (sodium: any): Methods => ({
|
'libsodium-wrappers': (sodium: any): Methods => ({
|
||||||
open: sodium.crypto_secretbox_open_easy,
|
crypto_aead_xchacha20poly1305_ietf_decrypt: (
|
||||||
close: sodium.crypto_secretbox_easy,
|
cipherText: Buffer,
|
||||||
random: sodium.randombytes_buf,
|
additionalData: Buffer,
|
||||||
|
nonce: Buffer,
|
||||||
|
key: ArrayBufferLike,
|
||||||
|
) => {
|
||||||
|
return sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(null, cipherText, additionalData, nonce, key);
|
||||||
|
},
|
||||||
|
crypto_aead_xchacha20poly1305_ietf_encrypt: (
|
||||||
|
plaintext: Buffer,
|
||||||
|
additionalData: Buffer,
|
||||||
|
nonce: Buffer,
|
||||||
|
key: ArrayBufferLike,
|
||||||
|
) => {
|
||||||
|
return sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(plaintext, additionalData, null, nonce, key);
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
tweetnacl: (tweetnacl: any): Methods => ({
|
'@stablelib/xchacha20poly1305': (stablelib: any): Methods => ({
|
||||||
open: tweetnacl.secretbox.open,
|
crypto_aead_xchacha20poly1305_ietf_decrypt(plaintext, additionalData, nonce, key) {
|
||||||
close: tweetnacl.secretbox,
|
const crypto = new stablelib.XChaCha20Poly1305(key);
|
||||||
random: tweetnacl.randomBytes,
|
return crypto.open(nonce, plaintext, additionalData);
|
||||||
|
},
|
||||||
|
crypto_aead_xchacha20poly1305_ietf_encrypt(cipherText, additionalData, nonce, key) {
|
||||||
|
const crypto = new stablelib.XChaCha20Poly1305(key);
|
||||||
|
return crypto.seal(nonce, cipherText, additionalData);
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
'@noble/ciphers/chacha': (noble: any): Methods => ({
|
||||||
|
crypto_aead_xchacha20poly1305_ietf_decrypt(cipherText, additionalData, nonce, key) {
|
||||||
|
const chacha = noble.xchacha20poly1305(key, nonce, additionalData);
|
||||||
|
return chacha.decrypt(cipherText);
|
||||||
|
},
|
||||||
|
crypto_aead_xchacha20poly1305_ietf_encrypt(plaintext, additionalData, nonce, key) {
|
||||||
|
const chacha = noble.xchacha20poly1305(key, nonce, additionalData);
|
||||||
|
return chacha.encrypt(plaintext);
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const fallbackError = () => {
|
const fallbackError = () => {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Cannot play audio as no valid encryption package is installed.
|
`Cannot play audio as no valid encryption package is installed.
|
||||||
- Install sodium, libsodium-wrappers, or tweetnacl.
|
- Install one of:
|
||||||
|
- sodium
|
||||||
|
- libsodium-wrappers
|
||||||
|
- @stablelib/xchacha20poly1305
|
||||||
|
- @noble/ciphers.
|
||||||
- Use the generateDependencyReport() function for more information.\n`,
|
- Use the generateDependencyReport() function for more information.\n`,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const methods: Methods = {
|
const methods: Methods = {
|
||||||
open: fallbackError,
|
crypto_aead_xchacha20poly1305_ietf_encrypt: fallbackError,
|
||||||
close: fallbackError,
|
crypto_aead_xchacha20poly1305_ietf_decrypt: fallbackError,
|
||||||
random: fallbackError,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void (async () => {
|
// eslint-disable-next-line no-async-promise-executor
|
||||||
|
export const secretboxLoadPromise = new Promise<void>(async (resolve) => {
|
||||||
for (const libName of Object.keys(libs) as (keyof typeof libs)[]) {
|
for (const libName of Object.keys(libs) as (keyof typeof libs)[]) {
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
|
const lib = await import(libName);
|
||||||
const lib = require(libName);
|
|
||||||
if (libName === 'libsodium-wrappers' && lib.ready) await lib.ready;
|
if (libName === 'libsodium-wrappers' && lib.ready) {
|
||||||
|
await lib.ready;
|
||||||
|
}
|
||||||
|
|
||||||
Object.assign(methods, libs[libName](lib));
|
Object.assign(methods, libs[libName](lib));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
})();
|
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
|
||||||
export { methods };
|
export { methods };
|
||||||
|
|||||||
@@ -68,7 +68,8 @@ export function generateDependencyReport() {
|
|||||||
addVersion('sodium-native');
|
addVersion('sodium-native');
|
||||||
addVersion('sodium');
|
addVersion('sodium');
|
||||||
addVersion('libsodium-wrappers');
|
addVersion('libsodium-wrappers');
|
||||||
addVersion('tweetnacl');
|
addVersion('@stablelib/xchacha20poly1305');
|
||||||
|
addVersion('@noble/ciphers');
|
||||||
report.push('');
|
report.push('');
|
||||||
|
|
||||||
// ffmpeg
|
// ffmpeg
|
||||||
|
|||||||
118
pnpm-lock.yaml
generated
118
pnpm-lock.yaml
generated
@@ -1625,6 +1625,9 @@ importers:
|
|||||||
'@favware/cliff-jumper':
|
'@favware/cliff-jumper':
|
||||||
specifier: ^4.1.0
|
specifier: ^4.1.0
|
||||||
version: 4.1.0
|
version: 4.1.0
|
||||||
|
'@noble/ciphers':
|
||||||
|
specifier: ^1.0.0
|
||||||
|
version: 1.0.0
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: 18.19.45
|
specifier: 18.19.45
|
||||||
version: 18.19.45
|
version: 18.19.45
|
||||||
@@ -1655,9 +1658,6 @@ importers:
|
|||||||
turbo:
|
turbo:
|
||||||
specifier: ^2.0.14
|
specifier: ^2.0.14
|
||||||
version: 2.0.14
|
version: 2.0.14
|
||||||
tweetnacl:
|
|
||||||
specifier: ^1.0.3
|
|
||||||
version: 1.0.3
|
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ~5.5.4
|
specifier: ~5.5.4
|
||||||
version: 5.5.4
|
version: 5.5.4
|
||||||
@@ -2589,12 +2589,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
|
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
'@definitelytyped/header-parser@0.2.13':
|
'@definitelytyped/header-parser@0.2.15':
|
||||||
resolution: {integrity: sha512-m7YEtGhwAjmQyJQFQ7q8+hTGTiC/WrdRATvw8fyTwgW+RiWUt8MAeehuFj4txnCYXDcLO0ozuW5gNrLoYR4Ubg==}
|
resolution: {integrity: sha512-SRUpmhQ7QZpsjLiA9SlwaD2Ct1xOc5Vt8cpZAqQ+P/puu4nNIsibCW87NKkyjCXG+MCUVFWEK7rVCTd12m2hTw==}
|
||||||
engines: {node: '>=18.18.0'}
|
engines: {node: '>=18.18.0'}
|
||||||
|
|
||||||
'@definitelytyped/typescript-versions@0.1.4':
|
'@definitelytyped/typescript-versions@0.1.5':
|
||||||
resolution: {integrity: sha512-4Rz5kCpyxofwXCtBQaNfmWYXZcH0sMJxpbIgJzS+PAxgFCAa9W+2Jil7rrkpzsjx9E7+zOPukbXBXjyXohcyuQ==}
|
resolution: {integrity: sha512-XdLx3+S6zZCcG4jnG6Kqv/PlKBRTkz5M/xZUEEN9R2g6BlzbxyE+z5EzlezJqkUls53zjuOzgbkNNP4HQIfbJQ==}
|
||||||
engines: {node: '>=18.18.0'}
|
engines: {node: '>=18.18.0'}
|
||||||
|
|
||||||
'@definitelytyped/utils@0.1.8':
|
'@definitelytyped/utils@0.1.8':
|
||||||
@@ -3616,6 +3616,10 @@ packages:
|
|||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
|
'@noble/ciphers@1.0.0':
|
||||||
|
resolution: {integrity: sha512-wH5EHOmLi0rEazphPbecAzmjd12I6/Yv/SiHdkA9LSycsQk7RuuTp7am5/o62qYr0RScE7Pc9icXGBbsr6cesA==}
|
||||||
|
engines: {node: ^14.21.3 || >=16}
|
||||||
|
|
||||||
'@nodelib/fs.scandir@2.1.5':
|
'@nodelib/fs.scandir@2.1.5':
|
||||||
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
@@ -5680,9 +5684,6 @@ packages:
|
|||||||
'@types/node@18.19.45':
|
'@types/node@18.19.45':
|
||||||
resolution: {integrity: sha512-VZxPKNNhjKmaC1SUYowuXSRSMGyQGmQjvvA1xE4QZ0xce2kLtEhPDS+kqpCPBZYgqblCLQ2DAjSzmgCM5auvhA==}
|
resolution: {integrity: sha512-VZxPKNNhjKmaC1SUYowuXSRSMGyQGmQjvvA1xE4QZ0xce2kLtEhPDS+kqpCPBZYgqblCLQ2DAjSzmgCM5auvhA==}
|
||||||
|
|
||||||
'@types/node@18.19.59':
|
|
||||||
resolution: {integrity: sha512-vizm2EqwV/7Zay+A6J3tGl9Lhr7CjZe2HmWS988sefiEmsyP9CeXEleho6i4hJk/8UtZAo0bWN4QPZZr83RxvQ==}
|
|
||||||
|
|
||||||
'@types/node@20.16.1':
|
'@types/node@20.16.1':
|
||||||
resolution: {integrity: sha512-zJDo7wEadFtSyNz5QITDfRcrhqDvQI1xQNQ0VoizPjM/dVAODqqIUWbJPkvsxmTI0MYRGRikcdjMPhOssnPejQ==}
|
resolution: {integrity: sha512-zJDo7wEadFtSyNz5QITDfRcrhqDvQI1xQNQ0VoizPjM/dVAODqqIUWbJPkvsxmTI0MYRGRikcdjMPhOssnPejQ==}
|
||||||
|
|
||||||
@@ -12892,9 +12893,6 @@ packages:
|
|||||||
tweetnacl@0.14.5:
|
tweetnacl@0.14.5:
|
||||||
resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==}
|
resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==}
|
||||||
|
|
||||||
tweetnacl@1.0.3:
|
|
||||||
resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==}
|
|
||||||
|
|
||||||
typanion@3.14.0:
|
typanion@3.14.0:
|
||||||
resolution: {integrity: sha512-ZW/lVMRabETuYCd9O9ZvMhAh8GslSqaUjxmK/JLPCh6l73CvLBiuXswj/+7LdnWOgYsQ130FqLzFz5aGT4I3Ug==}
|
resolution: {integrity: sha512-ZW/lVMRabETuYCd9O9ZvMhAh8GslSqaUjxmK/JLPCh6l73CvLBiuXswj/+7LdnWOgYsQ130FqLzFz5aGT4I3Ug==}
|
||||||
|
|
||||||
@@ -14604,7 +14602,7 @@ snapshots:
|
|||||||
'@babel/parser': 7.25.4
|
'@babel/parser': 7.25.4
|
||||||
'@babel/template': 7.25.0
|
'@babel/template': 7.25.0
|
||||||
'@babel/types': 7.25.4
|
'@babel/types': 7.25.4
|
||||||
debug: 4.3.6
|
debug: 4.3.7
|
||||||
globals: 11.12.0
|
globals: 11.12.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -14841,18 +14839,18 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/trace-mapping': 0.3.9
|
'@jridgewell/trace-mapping': 0.3.9
|
||||||
|
|
||||||
'@definitelytyped/header-parser@0.2.13':
|
'@definitelytyped/header-parser@0.2.15':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@definitelytyped/typescript-versions': 0.1.4
|
'@definitelytyped/typescript-versions': 0.1.5
|
||||||
'@definitelytyped/utils': 0.1.8
|
'@definitelytyped/utils': 0.1.8
|
||||||
semver: 7.6.3
|
semver: 7.6.3
|
||||||
|
|
||||||
'@definitelytyped/typescript-versions@0.1.4': {}
|
'@definitelytyped/typescript-versions@0.1.5': {}
|
||||||
|
|
||||||
'@definitelytyped/utils@0.1.8':
|
'@definitelytyped/utils@0.1.8':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@qiwi/npm-registry-client': 8.9.1
|
'@qiwi/npm-registry-client': 8.9.1
|
||||||
'@types/node': 18.19.59
|
'@types/node': 18.19.45
|
||||||
cachedir: 2.4.0
|
cachedir: 2.4.0
|
||||||
charm: 1.0.2
|
charm: 1.0.2
|
||||||
minimatch: 9.0.5
|
minimatch: 9.0.5
|
||||||
@@ -15312,7 +15310,7 @@ snapshots:
|
|||||||
'@antfu/install-pkg': 0.4.0
|
'@antfu/install-pkg': 0.4.0
|
||||||
'@antfu/utils': 0.7.10
|
'@antfu/utils': 0.7.10
|
||||||
'@iconify/types': 2.0.0
|
'@iconify/types': 2.0.0
|
||||||
debug: 4.3.6
|
debug: 4.3.7
|
||||||
kolorist: 1.8.0
|
kolorist: 1.8.0
|
||||||
local-pkg: 0.5.0
|
local-pkg: 0.5.0
|
||||||
mlly: 1.7.1
|
mlly: 1.7.1
|
||||||
@@ -15694,7 +15692,7 @@ snapshots:
|
|||||||
nopt: 5.0.0
|
nopt: 5.0.0
|
||||||
npmlog: 5.0.1
|
npmlog: 5.0.1
|
||||||
rimraf: 3.0.2
|
rimraf: 3.0.2
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
tar: 6.2.1
|
tar: 6.2.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
@@ -15958,6 +15956,8 @@ snapshots:
|
|||||||
'@next/swc-win32-x64-msvc@15.0.0-rc.0':
|
'@next/swc-win32-x64-msvc@15.0.0-rc.0':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@noble/ciphers@1.0.0': {}
|
||||||
|
|
||||||
'@nodelib/fs.scandir@2.1.5':
|
'@nodelib/fs.scandir@2.1.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nodelib/fs.stat': 2.0.5
|
'@nodelib/fs.stat': 2.0.5
|
||||||
@@ -15978,14 +15978,14 @@ snapshots:
|
|||||||
ini: 4.1.3
|
ini: 4.1.3
|
||||||
nopt: 7.2.1
|
nopt: 7.2.1
|
||||||
proc-log: 4.2.0
|
proc-log: 4.2.0
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
walk-up-path: 3.0.1
|
walk-up-path: 3.0.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- bluebird
|
- bluebird
|
||||||
|
|
||||||
'@npmcli/fs@3.1.1':
|
'@npmcli/fs@3.1.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
|
|
||||||
'@npmcli/git@5.0.8':
|
'@npmcli/git@5.0.8':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -15996,7 +15996,7 @@ snapshots:
|
|||||||
proc-log: 4.2.0
|
proc-log: 4.2.0
|
||||||
promise-inflight: 1.0.1
|
promise-inflight: 1.0.1
|
||||||
promise-retry: 2.0.1
|
promise-retry: 2.0.1
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
which: 4.0.0
|
which: 4.0.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- bluebird
|
- bluebird
|
||||||
@@ -16018,7 +16018,7 @@ snapshots:
|
|||||||
json-parse-even-better-errors: 3.0.2
|
json-parse-even-better-errors: 3.0.2
|
||||||
normalize-package-data: 6.0.2
|
normalize-package-data: 6.0.2
|
||||||
proc-log: 4.2.0
|
proc-log: 4.2.0
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- bluebird
|
- bluebird
|
||||||
|
|
||||||
@@ -16184,7 +16184,7 @@ snapshots:
|
|||||||
'@opentelemetry/propagator-b3': 1.25.1(@opentelemetry/api@1.9.0)
|
'@opentelemetry/propagator-b3': 1.25.1(@opentelemetry/api@1.9.0)
|
||||||
'@opentelemetry/propagator-jaeger': 1.25.1(@opentelemetry/api@1.9.0)
|
'@opentelemetry/propagator-jaeger': 1.25.1(@opentelemetry/api@1.9.0)
|
||||||
'@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0)
|
'@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0)
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
|
|
||||||
'@opentelemetry/semantic-conventions@1.15.2': {}
|
'@opentelemetry/semantic-conventions@1.15.2': {}
|
||||||
|
|
||||||
@@ -16230,7 +16230,7 @@ snapshots:
|
|||||||
request: 2.88.2
|
request: 2.88.2
|
||||||
retry: 0.12.0
|
retry: 0.12.0
|
||||||
safe-buffer: 5.2.1
|
safe-buffer: 5.2.1
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
slide: 1.1.6
|
slide: 1.1.6
|
||||||
ssri: 8.0.1
|
ssri: 8.0.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
@@ -19088,10 +19088,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 5.26.5
|
undici-types: 5.26.5
|
||||||
|
|
||||||
'@types/node@18.19.59':
|
|
||||||
dependencies:
|
|
||||||
undici-types: 5.26.5
|
|
||||||
|
|
||||||
'@types/node@20.16.1':
|
'@types/node@20.16.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 6.19.8
|
undici-types: 6.19.8
|
||||||
@@ -19281,7 +19277,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/typescript-estree': 7.11.0(typescript@5.5.4)
|
'@typescript-eslint/typescript-estree': 7.11.0(typescript@5.5.4)
|
||||||
'@typescript-eslint/utils': 7.11.0(eslint@8.57.0)(typescript@5.5.4)
|
'@typescript-eslint/utils': 7.11.0(eslint@8.57.0)(typescript@5.5.4)
|
||||||
debug: 4.3.6
|
debug: 4.3.7
|
||||||
eslint: 8.57.0
|
eslint: 8.57.0
|
||||||
ts-api-utils: 1.3.0(typescript@5.5.4)
|
ts-api-utils: 1.3.0(typescript@5.5.4)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
@@ -19293,7 +19289,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/typescript-estree': 7.18.0(typescript@5.5.4)
|
'@typescript-eslint/typescript-estree': 7.18.0(typescript@5.5.4)
|
||||||
'@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.5.4)
|
'@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.5.4)
|
||||||
debug: 4.3.6
|
debug: 4.3.7
|
||||||
eslint: 8.57.0
|
eslint: 8.57.0
|
||||||
ts-api-utils: 1.3.0(typescript@5.5.4)
|
ts-api-utils: 1.3.0(typescript@5.5.4)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
@@ -19328,7 +19324,7 @@ snapshots:
|
|||||||
debug: 4.3.7
|
debug: 4.3.7
|
||||||
globby: 11.1.0
|
globby: 11.1.0
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
tsutils: 3.21.0(typescript@5.5.4)
|
tsutils: 3.21.0(typescript@5.5.4)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
typescript: 5.5.4
|
typescript: 5.5.4
|
||||||
@@ -19354,7 +19350,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 7.18.0
|
'@typescript-eslint/types': 7.18.0
|
||||||
'@typescript-eslint/visitor-keys': 7.18.0
|
'@typescript-eslint/visitor-keys': 7.18.0
|
||||||
debug: 4.3.6
|
debug: 4.3.7
|
||||||
globby: 11.1.0
|
globby: 11.1.0
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
minimatch: 9.0.5
|
minimatch: 9.0.5
|
||||||
@@ -19390,7 +19386,7 @@ snapshots:
|
|||||||
'@typescript-eslint/typescript-estree': 5.62.0(typescript@5.5.4)
|
'@typescript-eslint/typescript-estree': 5.62.0(typescript@5.5.4)
|
||||||
eslint: 8.57.0
|
eslint: 8.57.0
|
||||||
eslint-scope: 5.1.1
|
eslint-scope: 5.1.1
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
- typescript
|
- typescript
|
||||||
@@ -20090,7 +20086,7 @@ snapshots:
|
|||||||
|
|
||||||
agent-base@7.1.1:
|
agent-base@7.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.3.6
|
debug: 4.3.7
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -21125,7 +21121,7 @@ snapshots:
|
|||||||
handlebars: 4.7.8
|
handlebars: 4.7.8
|
||||||
json-stringify-safe: 5.0.1
|
json-stringify-safe: 5.0.1
|
||||||
meow: 12.1.1
|
meow: 12.1.1
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
split2: 4.2.0
|
split2: 4.2.0
|
||||||
|
|
||||||
conventional-changelog@5.1.0:
|
conventional-changelog@5.1.0:
|
||||||
@@ -21561,7 +21557,7 @@ snapshots:
|
|||||||
|
|
||||||
dts-critic@3.3.11(typescript@5.5.4):
|
dts-critic@3.3.11(typescript@5.5.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@definitelytyped/header-parser': 0.2.13
|
'@definitelytyped/header-parser': 0.2.15
|
||||||
command-exists: 1.2.9
|
command-exists: 1.2.9
|
||||||
rimraf: 3.0.2
|
rimraf: 3.0.2
|
||||||
semver: 6.3.1
|
semver: 6.3.1
|
||||||
@@ -21571,8 +21567,8 @@ snapshots:
|
|||||||
|
|
||||||
dtslint@4.2.1(typescript@5.5.4):
|
dtslint@4.2.1(typescript@5.5.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@definitelytyped/header-parser': 0.2.13
|
'@definitelytyped/header-parser': 0.2.15
|
||||||
'@definitelytyped/typescript-versions': 0.1.4
|
'@definitelytyped/typescript-versions': 0.1.5
|
||||||
'@definitelytyped/utils': 0.1.8
|
'@definitelytyped/utils': 0.1.8
|
||||||
dts-critic: 3.3.11(typescript@5.5.4)
|
dts-critic: 3.3.11(typescript@5.5.4)
|
||||||
fs-extra: 6.0.1
|
fs-extra: 6.0.1
|
||||||
@@ -22072,7 +22068,7 @@ snapshots:
|
|||||||
debug: 4.3.6
|
debug: 4.3.6
|
||||||
enhanced-resolve: 5.17.1
|
enhanced-resolve: 5.17.1
|
||||||
eslint: 8.57.0
|
eslint: 8.57.0
|
||||||
eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-i@2.29.1)(eslint@8.57.0))(eslint@8.57.0)
|
||||||
eslint-plugin-import: eslint-plugin-i@2.29.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
eslint-plugin-import: eslint-plugin-i@2.29.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||||
fast-glob: 3.3.2
|
fast-glob: 3.3.2
|
||||||
get-tsconfig: 4.7.6
|
get-tsconfig: 4.7.6
|
||||||
@@ -22105,7 +22101,7 @@ snapshots:
|
|||||||
- bluebird
|
- bluebird
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-module-utils@2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0):
|
eslint-module-utils@2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-i@2.29.1)(eslint@8.57.0))(eslint@8.57.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 3.2.7
|
debug: 3.2.7
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
@@ -22116,7 +22112,7 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-module-utils@2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0):
|
eslint-module-utils@2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-i@2.29.1)(eslint@8.57.0))(eslint@8.57.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 3.2.7
|
debug: 3.2.7
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
@@ -22158,11 +22154,11 @@ snapshots:
|
|||||||
doctrine: 3.0.0
|
doctrine: 3.0.0
|
||||||
eslint: 8.57.0
|
eslint: 8.57.0
|
||||||
eslint-import-resolver-node: 0.3.9
|
eslint-import-resolver-node: 0.3.9
|
||||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-i@2.29.1)(eslint@8.57.0))(eslint@8.57.0)
|
||||||
get-tsconfig: 4.8.1
|
get-tsconfig: 4.8.1
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
minimatch: 3.1.2
|
minimatch: 3.1.2
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@typescript-eslint/parser'
|
- '@typescript-eslint/parser'
|
||||||
- eslint-import-resolver-typescript
|
- eslint-import-resolver-typescript
|
||||||
@@ -22967,7 +22963,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
basic-ftp: 5.0.5
|
basic-ftp: 5.0.5
|
||||||
data-uri-to-buffer: 6.0.2
|
data-uri-to-buffer: 6.0.2
|
||||||
debug: 4.3.6
|
debug: 4.3.7
|
||||||
fs-extra: 11.2.0
|
fs-extra: 11.2.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -23025,7 +23021,7 @@ snapshots:
|
|||||||
git-semver-tags@7.0.1:
|
git-semver-tags@7.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
meow: 12.1.1
|
meow: 12.1.1
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
|
|
||||||
github-slugger@2.0.0: {}
|
github-slugger@2.0.0: {}
|
||||||
|
|
||||||
@@ -23434,7 +23430,7 @@ snapshots:
|
|||||||
http-proxy-agent@7.0.2:
|
http-proxy-agent@7.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base: 7.1.1
|
agent-base: 7.1.1
|
||||||
debug: 4.3.6
|
debug: 4.3.7
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -23454,7 +23450,7 @@ snapshots:
|
|||||||
https-proxy-agent@7.0.5:
|
https-proxy-agent@7.0.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base: 7.1.1
|
agent-base: 7.1.1
|
||||||
debug: 4.3.6
|
debug: 4.3.7
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -23849,7 +23845,7 @@ snapshots:
|
|||||||
'@babel/parser': 7.25.4
|
'@babel/parser': 7.25.4
|
||||||
'@istanbuljs/schema': 0.1.3
|
'@istanbuljs/schema': 0.1.3
|
||||||
istanbul-lib-coverage: 3.2.2
|
istanbul-lib-coverage: 3.2.2
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -24238,7 +24234,7 @@ snapshots:
|
|||||||
jest-util: 29.7.0
|
jest-util: 29.7.0
|
||||||
natural-compare: 1.4.0
|
natural-compare: 1.4.0
|
||||||
pretty-format: 29.7.0
|
pretty-format: 29.7.0
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -26062,13 +26058,13 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
hosted-git-info: 4.1.0
|
hosted-git-info: 4.1.0
|
||||||
is-core-module: 2.15.1
|
is-core-module: 2.15.1
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
validate-npm-package-license: 3.0.4
|
validate-npm-package-license: 3.0.4
|
||||||
|
|
||||||
normalize-package-data@6.0.2:
|
normalize-package-data@6.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
hosted-git-info: 7.0.2
|
hosted-git-info: 7.0.2
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
validate-npm-package-license: 3.0.4
|
validate-npm-package-license: 3.0.4
|
||||||
|
|
||||||
normalize-path@3.0.0: {}
|
normalize-path@3.0.0: {}
|
||||||
@@ -26077,7 +26073,7 @@ snapshots:
|
|||||||
|
|
||||||
npm-install-checks@6.3.0:
|
npm-install-checks@6.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
|
|
||||||
npm-normalize-package-bin@3.0.1: {}
|
npm-normalize-package-bin@3.0.1: {}
|
||||||
|
|
||||||
@@ -26092,13 +26088,13 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
hosted-git-info: 7.0.2
|
hosted-git-info: 7.0.2
|
||||||
proc-log: 4.2.0
|
proc-log: 4.2.0
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
validate-npm-package-name: 5.0.1
|
validate-npm-package-name: 5.0.1
|
||||||
|
|
||||||
npm-package-arg@8.1.5:
|
npm-package-arg@8.1.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
hosted-git-info: 4.1.0
|
hosted-git-info: 4.1.0
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
validate-npm-package-name: 3.0.0
|
validate-npm-package-name: 3.0.0
|
||||||
|
|
||||||
npm-pick-manifest@9.1.0:
|
npm-pick-manifest@9.1.0:
|
||||||
@@ -26106,7 +26102,7 @@ snapshots:
|
|||||||
npm-install-checks: 6.3.0
|
npm-install-checks: 6.3.0
|
||||||
npm-normalize-package-bin: 3.0.1
|
npm-normalize-package-bin: 3.0.1
|
||||||
npm-package-arg: 11.0.3
|
npm-package-arg: 11.0.3
|
||||||
semver: 7.6.3
|
semver: 7.5.4
|
||||||
|
|
||||||
npm-registry-fetch@14.0.5:
|
npm-registry-fetch@14.0.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -26347,7 +26343,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@tootallnate/quickjs-emscripten': 0.23.0
|
'@tootallnate/quickjs-emscripten': 0.23.0
|
||||||
agent-base: 7.1.1
|
agent-base: 7.1.1
|
||||||
debug: 4.3.6
|
debug: 4.3.7
|
||||||
get-uri: 6.0.3
|
get-uri: 6.0.3
|
||||||
http-proxy-agent: 7.0.2
|
http-proxy-agent: 7.0.2
|
||||||
https-proxy-agent: 7.0.5
|
https-proxy-agent: 7.0.5
|
||||||
@@ -27745,7 +27741,7 @@ snapshots:
|
|||||||
socks-proxy-agent@8.0.4:
|
socks-proxy-agent@8.0.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base: 7.1.1
|
agent-base: 7.1.1
|
||||||
debug: 4.3.6
|
debug: 4.3.7
|
||||||
socks: 2.8.3
|
socks: 2.8.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -28650,8 +28646,6 @@ snapshots:
|
|||||||
|
|
||||||
tweetnacl@0.14.5: {}
|
tweetnacl@0.14.5: {}
|
||||||
|
|
||||||
tweetnacl@1.0.3: {}
|
|
||||||
|
|
||||||
typanion@3.14.0: {}
|
typanion@3.14.0: {}
|
||||||
|
|
||||||
type-check@0.4.0:
|
type-check@0.4.0:
|
||||||
@@ -28821,7 +28815,7 @@ snapshots:
|
|||||||
'@types/node': 20.16.1
|
'@types/node': 20.16.1
|
||||||
'@types/unist': 3.0.3
|
'@types/unist': 3.0.3
|
||||||
concat-stream: 2.0.0
|
concat-stream: 2.0.0
|
||||||
debug: 4.3.6
|
debug: 4.3.7
|
||||||
extend: 3.0.2
|
extend: 3.0.2
|
||||||
glob: 10.4.5
|
glob: 10.4.5
|
||||||
ignore: 5.3.2
|
ignore: 5.3.2
|
||||||
|
|||||||
Reference in New Issue
Block a user