build: preparing for publish, day 6

i am slowly descending to madness

bugs fixed, stuff exported, and maybe something else
This commit is contained in:
teidesu 2021-06-10 02:31:48 +03:00
parent c46f113f1f
commit 079d65b38d
20 changed files with 152 additions and 88 deletions

View file

@ -21,6 +21,7 @@
"@types/mocha": "^8.2.0", "@types/mocha": "^8.2.0",
"@types/node": "^14.14.22", "@types/node": "^14.14.22",
"@types/node-forge": "^0.9.7", "@types/node-forge": "^0.9.7",
"@types/node-fetch": "^2.5.10",
"@types/pako": "^1.0.1", "@types/pako": "^1.0.1",
"@types/ws": "^7.4.0", "@types/ws": "^7.4.0",
"@typescript-eslint/eslint-plugin": "^4.15.0", "@typescript-eslint/eslint-plugin": "^4.15.0",

View file

@ -155,6 +155,7 @@ import { updateUsername } from './methods/users/update-username'
import { IMessageEntityParser } from './parser' import { IMessageEntityParser } from './parser'
import { Readable } from 'stream' import { Readable } from 'stream'
import { import {
ArrayWithTotal,
Chat, Chat,
ChatEvent, ChatEvent,
ChatInviteLink, ChatInviteLink,
@ -523,7 +524,6 @@ export interface TelegramClient extends BaseTelegramClient {
* @param queryId Inline query ID * @param queryId Inline query ID
* @param results Results of the query * @param results Results of the query
* @param params Additional parameters * @param params Additional parameters
*/ */
answerInlineQuery( answerInlineQuery(
queryId: tl.Long, queryId: tl.Long,
@ -984,7 +984,7 @@ export interface TelegramClient extends BaseTelegramClient {
| 'contacts' | 'contacts'
| 'mention' | 'mention'
} }
): Promise<ChatMember[]> ): Promise<ArrayWithTotal<ChatMember>>
/** /**
* Get preview information about a private chat. * Get preview information about a private chat.
* *
@ -1286,7 +1286,6 @@ export interface TelegramClient extends BaseTelegramClient {
* *
* @param folder Parameters for the folder * @param folder Parameters for the folder
* @returns Newly created folder * @returns Newly created folder
*/ */
createFolder( createFolder(
folder: PartialExcept<tl.RawDialogFilter, 'title'> folder: PartialExcept<tl.RawDialogFilter, 'title'>
@ -1443,7 +1442,6 @@ export interface TelegramClient extends BaseTelegramClient {
* > into memory at once. This might cause an issue, so use wisely! * > into memory at once. This might cause an issue, so use wisely!
* *
* @param params File download parameters * @param params File download parameters
*/ */
downloadAsBuffer(params: FileDownloadParameters): Promise<Buffer> downloadAsBuffer(params: FileDownloadParameters): Promise<Buffer>
/** /**
@ -1452,7 +1450,6 @@ export interface TelegramClient extends BaseTelegramClient {
* *
* @param filename Local file name to which the remote file will be downloaded * @param filename Local file name to which the remote file will be downloaded
* @param params File download parameters * @param params File download parameters
*/ */
downloadToFile( downloadToFile(
filename: string, filename: string,
@ -1464,7 +1461,6 @@ export interface TelegramClient extends BaseTelegramClient {
* consecutive. * consecutive.
* *
* @param params Download parameters * @param params Download parameters
*/ */
downloadAsIterable( downloadAsIterable(
params: FileDownloadParameters params: FileDownloadParameters
@ -1474,7 +1470,6 @@ export interface TelegramClient extends BaseTelegramClient {
* streaming file contents. * streaming file contents.
* *
* @param params File download parameters * @param params File download parameters
*/ */
downloadAsStream(params: FileDownloadParameters): Readable downloadAsStream(params: FileDownloadParameters): Readable
/** /**
@ -1983,7 +1978,6 @@ export interface TelegramClient extends BaseTelegramClient {
* *
* @param chatId Chat ID * @param chatId Chat ID
* @param message ID of one of the messages in the group * @param message ID of one of the messages in the group
*/ */
getMessageGroup(chatId: InputPeerLike, message: number): Promise<Message[]> getMessageGroup(chatId: InputPeerLike, message: number): Promise<Message[]>
/** /**
@ -2275,6 +2269,9 @@ export interface TelegramClient extends BaseTelegramClient {
/** /**
* Send a group of media. * Send a group of media.
* *
* To add a caption to the group, add caption to the first
* media in the group and don't add caption for any other.
*
* @param chatId ID of the chat, its username, phone or `"me"` or `"self"` * @param chatId ID of the chat, its username, phone or `"me"` or `"self"`
* @param medias Medias contained in the message. * @param medias Medias contained in the message.
* @param params Additional sending parameters * @param params Additional sending parameters
@ -2282,7 +2279,7 @@ export interface TelegramClient extends BaseTelegramClient {
*/ */
sendMediaGroup( sendMediaGroup(
chatId: InputPeerLike, chatId: InputPeerLike,
medias: InputMediaLike[], medias: (InputMediaLike | string)[],
params?: { params?: {
/** /**
* Message to reply to. Either a message object or message ID. * Message to reply to. Either a message object or message ID.

View file

@ -10,3 +10,4 @@ export * from './parser'
export * from './types' export * from './types'
export * from './client' export * from './client'
export * from './utils/peer-utils' export * from './utils/peer-utils'
export { createDummyUpdate } from './utils/updates-utils'

View file

@ -38,6 +38,7 @@ import {
UsersIndex, UsersIndex,
ChatsIndex, ChatsIndex,
GameHighScore, GameHighScore,
ArrayWithTotal,
} from '../types' } from '../types'
// @copy // @copy

View file

@ -12,6 +12,7 @@ import {
} from '../../utils/peer-utils' } from '../../utils/peer-utils'
import { assertTypeIs } from '../../utils/type-assertion' import { assertTypeIs } from '../../utils/type-assertion'
import { tl } from '@mtcute/tl' import { tl } from '@mtcute/tl'
import { ArrayWithTotal } from '../../types'
/** /**
* Get a chunk of members of some chat. * Get a chunk of members of some chat.
@ -68,7 +69,7 @@ export async function getChatMembers(
| 'contacts' | 'contacts'
| 'mention' | 'mention'
} }
): Promise<ChatMember[]> { ): Promise<ArrayWithTotal<ChatMember>> {
if (!params) params = {} if (!params) params = {}
const chat = await this.resolvePeer(chatId) const chat = await this.resolvePeer(chatId)
@ -95,7 +96,10 @@ export async function getChatMembers(
const { users } = createUsersChatsIndex(res) const { users } = createUsersChatsIndex(res)
return members.map((m) => new ChatMember(this, m, users)) const ret = members.map((m) => new ChatMember(this, m, users)) as ArrayWithTotal<ChatMember>
ret.total = ret.length
return ret
} }
if (isInputPeerChannel(chat)) { if (isInputPeerChannel(chat)) {
@ -146,7 +150,10 @@ export async function getChatMembers(
) )
const { users } = createUsersChatsIndex(res) const { users } = createUsersChatsIndex(res)
return res.participants.map((i) => new ChatMember(this, i, users))
const ret = res.participants.map((i) => new ChatMember(this, i, users)) as ArrayWithTotal<ChatMember>
ret.total = res.count
return ret
} }
throw new MtCuteInvalidPeerTypeError(chatId, 'chat or channel') throw new MtCuteInvalidPeerTypeError(chatId, 'chat or channel')

View file

@ -136,6 +136,45 @@ export async function uploadFile(
file = convertWebStreamToNodeReadable(file) file = convertWebStreamToNodeReadable(file)
} }
if (typeof file === 'object' && 'headers' in file && 'body' in file && 'url' in file) {
// fetch() response
const length = parseInt(file.headers.get('content-length') || '0')
if (!isNaN(length) && length) fileSize = length
fileMime = file.headers.get('content-type')?.split(';')[0]
const disposition = file.headers.get('content-disposition')
if (disposition) {
const idx = disposition.indexOf('filename=')
if (idx > -1) {
const raw = disposition.slice(idx + 9).split(';')[0]
fileName = JSON.parse(raw)
}
}
if (fileName === 'unnamed') {
// try to infer from url
const url = new URL(file.url)
const name = url.pathname.split('/').pop()
if (name && name.indexOf('.') > -1) {
fileName = name
}
}
if (!file.body)
throw new MtCuteArgumentError('Fetch response contains `null` body')
if (
typeof ReadableStream !== 'undefined' &&
file.body instanceof ReadableStream
) {
file = convertWebStreamToNodeReadable(file.body)
} else {
file = file.body
}
}
// override file name and mime (if any) // override file name and mime (if any)
if (params.fileName) fileName = params.fileName if (params.fileName) fileName = params.fileName

View file

@ -82,7 +82,9 @@ export async function getHistory(
const { users, chats } = createUsersChatsIndex(res) const { users, chats } = createUsersChatsIndex(res)
const msgs = res.messages.map((msg) => new Message(this, msg, users, chats)) const msgs = res.messages
.filter((msg) => msg._ !== 'messageEmpty')
.map((msg) => new Message(this, msg, users, chats))
if (params.reverse) msgs.reverse() if (params.reverse) msgs.reverse()

View file

@ -85,7 +85,9 @@ export async function getMessages(
const { users, chats } = createUsersChatsIndex(res) const { users, chats } = createUsersChatsIndex(res)
const ret = res.messages.map((msg) => new Message(this, msg, users, chats)) const ret = res.messages
.filter((msg) => msg._ !== 'messageEmpty')
.map((msg) => new Message(this, msg, users, chats))
return isSingle ? ret[0] : ret return isSingle ? ret[0] : ret
} }

View file

@ -79,9 +79,9 @@ export async function* searchGlobal(
const { users, chats } = createUsersChatsIndex(res) const { users, chats } = createUsersChatsIndex(res)
const msgs = res.messages.map( const msgs = res.messages
(msg) => new Message(this, msg, users, chats) .filter((msg) => msg._ !== 'messageEmpty')
) .map((msg) => new Message(this, msg, users, chats))
if (!msgs.length) break if (!msgs.length) break

View file

@ -100,9 +100,9 @@ export async function* searchMessages(
const { users, chats } = createUsersChatsIndex(res) const { users, chats } = createUsersChatsIndex(res)
const msgs = res.messages.map( const msgs = res.messages
(msg) => new Message(this, msg, users, chats) .filter((msg) => msg._ !== 'messageEmpty')
) .map((msg) => new Message(this, msg, users, chats))
if (!msgs.length) break if (!msgs.length) break

View file

@ -1,6 +1,6 @@
import { TelegramClient } from '../../client' import { TelegramClient } from '../../client'
import { import {
BotKeyboard, BotKeyboard, InputFileLike,
InputMediaLike, InputMediaLike,
InputPeerLike, InputPeerLike,
Message, Message,
@ -18,6 +18,9 @@ import { createUsersChatsIndex } from '../../utils/peer-utils'
/** /**
* Send a group of media. * Send a group of media.
* *
* To add a caption to the group, add caption to the first
* media in the group and don't add caption for any other.
*
* @param chatId ID of the chat, its username, phone or `"me"` or `"self"` * @param chatId ID of the chat, its username, phone or `"me"` or `"self"`
* @param medias Medias contained in the message. * @param medias Medias contained in the message.
* @param params Additional sending parameters * @param params Additional sending parameters
@ -27,7 +30,7 @@ import { createUsersChatsIndex } from '../../utils/peer-utils'
export async function sendMediaGroup( export async function sendMediaGroup(
this: TelegramClient, this: TelegramClient,
chatId: InputPeerLike, chatId: InputPeerLike,
medias: InputMediaLike[], medias: (InputMediaLike | string)[],
params?: { params?: {
/** /**
* Message to reply to. Either a message object or message ID. * Message to reply to. Either a message object or message ID.
@ -108,7 +111,15 @@ export async function sendMediaGroup(
const multiMedia: tl.RawInputSingleMedia[] = [] const multiMedia: tl.RawInputSingleMedia[] = []
for (let i = 0; i < medias.length; i++) { for (let i = 0; i < medias.length; i++) {
const media = medias[i] let media = medias[i]
if (typeof media === 'string') {
media = {
type: 'auto',
file: media,
}
}
const inputMedia = await this._normalizeInputMedia(media, { const inputMedia = await this._normalizeInputMedia(media, {
progressCallback: params.progressCallback?.bind(null, i), progressCallback: params.progressCallback?.bind(null, i),
}) })

View file

@ -14,6 +14,7 @@ import { tdFileId } from '@mtcute/file-id'
* - `ReadStream` (for NodeJS, from the `fs` module) * - `ReadStream` (for NodeJS, from the `fs` module)
* - `ReadableStream` (from the Web API, base readable stream) * - `ReadableStream` (from the Web API, base readable stream)
* - `Readable` (for NodeJS, base readable stream) * - `Readable` (for NodeJS, base readable stream)
* - `Response` (from `window.fetch` or `node-fetch`)
*/ */
export type UploadFileLike = export type UploadFileLike =
| Buffer | Buffer
@ -21,7 +22,14 @@ export type UploadFileLike =
| string | string
| ReadStream | ReadStream
| ReadableStream | ReadableStream
| NodeJS.ReadableStream
| Readable | Readable
// fetch() response
| {
headers: any
url: string
body: ReadableStream<Uint8Array> | NodeJS.ReadableStream | null
}
/** /**
* Describes types that can be used as an input * Describes types that can be used as an input

View file

@ -7,5 +7,5 @@ export * from './peers'
export * from './misc' export * from './misc'
export * from './errors' export * from './errors'
export { MaybeDynamic } from './utils' export { MaybeDynamic, ArrayWithTotal } from './utils'
export { MaybeAsync, PartialExcept, PartialOnly } from '@mtcute/core' export { MaybeAsync, PartialExcept, PartialOnly } from '@mtcute/core'

View file

@ -101,16 +101,6 @@ export class Message {
/** /**
* Raw TL object. * Raw TL object.
*
* > **Note**: In fact, `raw` can also be {@link tl.RawMessageEmpty}.
* > But since it is quite rare, for the simplicity sake
* > we don't bother thinking about it (and you shouldn't too).
* >
* > When the {@link Message} is in fact `messageEmpty`,
* > `.empty` will be true and trying to access properties
* > that are not available will result in {@link MtCuteEmptyError}.
* >
* > The only property that is available on an "empty" message is `.id`
*/ */
readonly raw: tl.RawMessage | tl.RawMessageService readonly raw: tl.RawMessage | tl.RawMessageService
@ -119,8 +109,6 @@ export class Message {
/** Map of chats in this message. Mainly for internal use */ /** Map of chats in this message. Mainly for internal use */
readonly _chats: ChatsIndex readonly _chats: ChatsIndex
private _emptyError?: MtCuteEmptyError
constructor( constructor(
client: TelegramClient, client: TelegramClient,
raw: tl.TypeMessage, raw: tl.TypeMessage,
@ -128,33 +116,18 @@ export class Message {
chats: ChatsIndex, chats: ChatsIndex,
isScheduled = false isScheduled = false
) { ) {
if (raw._ === 'messageEmpty')
throw new MtCuteTypeAssertionError('Message#ctor', 'not messageEmpty', 'messageEmpty')
this.client = client this.client = client
this._users = users this._users = users
this._chats = chats this._chats = chats
// a bit of cheating in terms of types but whatever :shrug: this.raw = raw
//
// using exclude instead of `typeof this.raw` because
// TypeMessage might have some other types added, and we'll detect
// that at compile time
this.raw = raw as Exclude<tl.TypeMessage, tl.RawMessageEmpty>
this.empty = raw._ === 'messageEmpty'
if (this.empty) {
this._emptyError = new MtCuteEmptyError()
}
this.isScheduled = isScheduled this.isScheduled = isScheduled
} }
/**
* Whether the message is empty.
*
* Note that if the message is empty,
* accessing any other property except `id` and `raw`
* will result in {@link MtCuteEmptyError}
*/
readonly empty: boolean
/** /**
* Whether the message is scheduled. * Whether the message is scheduled.
* If it is, then its {@link date} is set to future. * If it is, then its {@link date} is set to future.
@ -172,8 +145,6 @@ export class Message {
* `null` for service messages and non-post messages. * `null` for service messages and non-post messages.
*/ */
get views(): number | null { get views(): number | null {
if (this._emptyError) throw this._emptyError
return this.raw._ === 'message' ? this.raw.views ?? null : null return this.raw._ === 'message' ? this.raw.views ?? null : null
} }
@ -184,8 +155,6 @@ export class Message {
* - Messages to yourself (i.e. *Saved Messages*) are incoming (`outgoing = false`) * - Messages to yourself (i.e. *Saved Messages*) are incoming (`outgoing = false`)
*/ */
get isOutgoing(): boolean { get isOutgoing(): boolean {
if (this._emptyError) throw this._emptyError
return this.raw.out! return this.raw.out!
} }
@ -203,8 +172,6 @@ export class Message {
* `null` for service messages and non-grouped messages * `null` for service messages and non-grouped messages
*/ */
get groupedId(): tl.Long | null { get groupedId(): tl.Long | null {
if (this._emptyError) throw this._emptyError
return this.raw._ === 'message' ? this.raw.groupedId ?? null : null return this.raw._ === 'message' ? this.raw.groupedId ?? null : null
} }
@ -224,8 +191,6 @@ export class Message {
* sender is the channel itself. * sender is the channel itself.
*/ */
get sender(): User | Chat { get sender(): User | Chat {
if (this._emptyError) throw this._emptyError
if (this._sender === undefined) { if (this._sender === undefined) {
const from = this.raw.fromId const from = this.raw.fromId
if (!from) { if (!from) {
@ -270,8 +235,6 @@ export class Message {
* Conversation the message belongs to * Conversation the message belongs to
*/ */
get chat(): Chat { get chat(): Chat {
if (this._emptyError) throw this._emptyError
if (this._chat === undefined) { if (this._chat === undefined) {
this._chat = Chat._parseFromMessage( this._chat = Chat._parseFromMessage(
this.client, this.client,
@ -288,8 +251,6 @@ export class Message {
* Date the message was sent * Date the message was sent
*/ */
get date(): Date { get date(): Date {
if (this._emptyError) throw this._emptyError
return new Date(this.raw.date * 1000) return new Date(this.raw.date * 1000)
} }
@ -299,8 +260,6 @@ export class Message {
* If this message is a forward, contains info about it. * If this message is a forward, contains info about it.
*/ */
get forward(): Message.MessageForwardInfo | null { get forward(): Message.MessageForwardInfo | null {
if (this._emptyError) throw this._emptyError
if (!this._forward) { if (!this._forward) {
if (this.raw._ !== 'message' || !this.raw.fwdFrom) { if (this.raw._ !== 'message' || !this.raw.fwdFrom) {
this._forward = null this._forward = null
@ -386,8 +345,6 @@ export class Message {
* replies to. * replies to.
*/ */
get replyToMessageId(): number | null { get replyToMessageId(): number | null {
if (this._emptyError) throw this._emptyError
return this.raw.replyTo?.replyToMsgId ?? null return this.raw.replyTo?.replyToMsgId ?? null
} }
@ -395,8 +352,6 @@ export class Message {
* Whether this message contains mention of the current user * Whether this message contains mention of the current user
*/ */
get isMention(): boolean { get isMention(): boolean {
if (this._emptyError) throw this._emptyError
return this.raw.mentioned! return this.raw.mentioned!
} }
@ -406,8 +361,6 @@ export class Message {
* information about the bot which generated it * information about the bot which generated it
*/ */
get viaBot(): User | null { get viaBot(): User | null {
if (this._emptyError) throw this._emptyError
if (this._viaBot === undefined) { if (this._viaBot === undefined) {
if (this.raw._ === 'messageService' || !this.raw.viaBotId) { if (this.raw._ === 'messageService' || !this.raw.viaBotId) {
this._viaBot = null this._viaBot = null
@ -429,8 +382,6 @@ export class Message {
* (you should handle i18n yourself) * (you should handle i18n yourself)
*/ */
get text(): string { get text(): string {
if (this._emptyError) throw this._emptyError
return this.raw._ === 'messageService' ? '' : this.raw.message return this.raw._ === 'messageService' ? '' : this.raw.message
} }
@ -439,8 +390,6 @@ export class Message {
* Message text/caption entities (may be empty) * Message text/caption entities (may be empty)
*/ */
get entities(): ReadonlyArray<MessageEntity> { get entities(): ReadonlyArray<MessageEntity> {
if (this._emptyError) throw this._emptyError
if (!this._entities) { if (!this._entities) {
this._entities = [] this._entities = []
if (this.raw._ === 'message' && this.raw.entities?.length) { if (this.raw._ === 'message' && this.raw.entities?.length) {

View file

@ -2,6 +2,8 @@ import { MaybeAsync } from '@mtcute/core'
export type MaybeDynamic<T> = MaybeAsync<T> | (() => MaybeAsync<T>) export type MaybeDynamic<T> = MaybeAsync<T> | (() => MaybeAsync<T>)
export type ArrayWithTotal<T> = T[] & { total: number }
let util: any | null = null let util: any | null = null
try { try {
util = require('util') util = require('util')

View file

@ -62,6 +62,8 @@ export function normalizeToInputUser(
if (tl.isAnyInputUser(res)) return res if (tl.isAnyInputUser(res)) return res
switch (res._) { switch (res._) {
case 'inputPeerSelf':
return { _: 'inputUserSelf' }
case 'inputPeerUser': case 'inputPeerUser':
return { return {
_: 'inputUser', _: 'inputUser',

View file

@ -72,8 +72,18 @@ export function convertWebStreamToNodeReadable(
export async function readStreamUntilEnd(stream: Readable): Promise<Buffer> { export async function readStreamUntilEnd(stream: Readable): Promise<Buffer> {
const chunks = [] const chunks = []
let length = 0
while (stream.readable) { while (stream.readable) {
chunks.push(await stream.read()) const c = await stream.read()
if (c === null) break
length += c.length
if (length > 2097152000) {
throw new Error('File is too big')
}
chunks.push(c)
} }
return Buffer.concat(chunks) return Buffer.concat(chunks)

View file

@ -4,7 +4,13 @@ import { MtCuteTypeAssertionError } from '../types'
// dummy updates which are used for methods that return messages.affectedHistory. // dummy updates which are used for methods that return messages.affectedHistory.
// that is not an update, but it carries info about pts, and we need to handle it // that is not an update, but it carries info about pts, and we need to handle it
/** @internal */ /**
* Create a dummy update from PTS and PTS count.
*
* @param pts PTS
* @param ptsCount PTS count
* @param channelId Channel ID (bare), if applicable
*/
export function createDummyUpdate( export function createDummyUpdate(
pts: number, pts: number,
ptsCount: number, ptsCount: number,

View file

@ -4,6 +4,8 @@ import { parseFileId } from './parse'
import { getBasicPeerType, markedPeerIdToBare } from '@mtcute/core' import { getBasicPeerType, markedPeerIdToBare } from '@mtcute/core'
import FileType = tdFileId.FileType import FileType = tdFileId.FileType
const EMPTY_BUFFER = Buffer.alloc(0)
type FileId = td.RawFullRemoteFileLocation type FileId = td.RawFullRemoteFileLocation
function dialogPhotoToInputPeer( function dialogPhotoToInputPeer(
@ -182,14 +184,21 @@ export function fileIdToInputDocument(
) )
throw new td.ConversionError('inputDocument') throw new td.ConversionError('inputDocument')
if (!fileId.fileReference) let fileRef = fileId.fileReference
if (!fileId.fileReference) {
if (fileId.type === FileType.Sticker) {
// older stickers' file IDs don't have file ref
fileRef = EMPTY_BUFFER
} else {
throw new td.InvalidFileIdError( throw new td.InvalidFileIdError(
'Expected document to have file reference' 'Expected document to have file reference'
) )
}
}
return { return {
_: 'inputDocument', _: 'inputDocument',
fileReference: fileId.fileReference, fileReference: fileRef!,
id: fileId.location.id, id: fileId.location.id,
accessHash: fileId.location.accessHash, accessHash: fileId.location.accessHash,
} }

View file

@ -1145,6 +1145,14 @@
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.0.tgz#3eb56d13a1de1d347ecb1957c6860c911704bc44" resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.0.tgz#3eb56d13a1de1d347ecb1957c6860c911704bc44"
integrity sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ== integrity sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ==
"@types/node-fetch@^2.5.10":
version "2.5.10"
resolved "http://localhost:4873/@types%2fnode-fetch/-/node-fetch-2.5.10.tgz#9b4d4a0425562f9fcea70b12cb3fcdd946ca8132"
integrity sha512-IpkX0AasN44hgEad0gEF/V6EgR5n69VEqPEgnmoM8GsIGro3PowbWs4tR6IhxUTyPLpOn+fiGG6nrQhcmoCuIQ==
dependencies:
"@types/node" "*"
form-data "^3.0.0"
"@types/node-forge@^0.9.7": "@types/node-forge@^0.9.7":
version "0.9.7" version "0.9.7"
resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-0.9.7.tgz#948f7b52d352a6c4ab22d3328c206f0870672db5" resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-0.9.7.tgz#948f7b52d352a6c4ab22d3328c206f0870672db5"
@ -1953,9 +1961,9 @@ columnify@^1.5.4:
strip-ansi "^3.0.0" strip-ansi "^3.0.0"
wcwidth "^1.0.0" wcwidth "^1.0.0"
combined-stream@^1.0.6, combined-stream@~1.0.6: combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
version "1.0.8" version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" resolved "http://localhost:4873/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
dependencies: dependencies:
delayed-stream "~1.0.0" delayed-stream "~1.0.0"
@ -2869,6 +2877,15 @@ forever-agent@~0.6.1:
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
form-data@^3.0.0:
version "3.0.1"
resolved "http://localhost:4873/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f"
integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"
form-data@~2.3.2: form-data@~2.3.2:
version "2.3.3" version "2.3.3"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"