diff --git a/examples/encryption_bot.ts b/examples/encryption_bot.ts index 18d5dee7..91038983 100644 --- a/examples/encryption_bot.ts +++ b/examples/encryption_bot.ts @@ -34,73 +34,82 @@ const worksImage = fs.readFileSync("./examples/static/it-works.png"); const client = new MatrixClient(homeserverUrl, accessToken, storage, crypto); (async function() { - let encryptedRoomId: string; - const joinedRooms = await client.getJoinedRooms(); - await client.crypto.prepare(joinedRooms); // init crypto because we're doing things before the client is started - for (const roomId of joinedRooms) { - if (await client.crypto.isRoomEncrypted(roomId)) { - encryptedRoomId = roomId; - break; - } - } - if (!encryptedRoomId) { - encryptedRoomId = await client.createRoom({ - invite: [dmTarget], - is_direct: true, - visibility: "private", - preset: "trusted_private_chat", - initial_state: [ - { type: "m.room.encryption", state_key: "", content: { algorithm: EncryptionAlgorithm.MegolmV1AesSha2 } }, - { type: "m.room.guest_access", state_key: "", content: { guest_access: "can_join" } }, - ], - }); - } - - client.on("room.failed_decryption", async (roomId: string, event: any, e: Error) => { - LogService.error("index", `Failed to decrypt ${roomId} ${event['event_id']} because `, e); - }); - - client.on("room.message", async (roomId: string, event: any) => { - if (roomId !== encryptedRoomId) return; - - const message = new MessageEvent(event); - - if (message.sender === (await client.getUserId()) && message.messageType === "m.notice") { - // yay, we decrypted our own message. Communicate that back for testing purposes. - const encrypted = await client.crypto.encryptMedia(Buffer.from(worksImage)); - const mxc = await client.uploadContent(encrypted.buffer); - await client.sendMessage(roomId, { - msgtype: "m.image", - body: "it-works.png", - info: { - // XXX: We know these details, so have hardcoded them. - w: 256, - h: 256, - mimetype: "image/png", - size: worksImage.length, - }, - file: { - url: mxc, - ...encrypted.file, - }, - }); - return; - } - - if (message.messageType === "m.image") { - const fileEvent = new MessageEvent(message.raw); - const decrypted = await client.crypto.decryptMedia(fileEvent.content.file); - fs.writeFileSync('./examples/storage/decrypted.png', decrypted); - await client.unstableApis.addReactionToEvent(roomId, fileEvent.eventId, 'Decrypted'); - return; - } - - if (message.messageType !== "m.text") return; - if (message.textBody.startsWith("!ping")) { - await client.replyNotice(roomId, event, "Pong"); - } - }); + // let encryptedRoomId: string; + // const joinedRooms = await client.getJoinedRooms(); + // await client.crypto.prepare(joinedRooms); // init crypto because we're doing things before the client is started + // for (const roomId of joinedRooms) { + // if (await client.crypto.isRoomEncrypted(roomId)) { + // encryptedRoomId = roomId; + // break; + // } + // } + // if (!encryptedRoomId) { + // encryptedRoomId = await client.createRoom({ + // invite: [dmTarget], + // is_direct: true, + // visibility: "private", + // preset: "trusted_private_chat", + // initial_state: [ + // {type: "m.room.encryption", state_key: "", content: {algorithm: EncryptionAlgorithm.MegolmV1AesSha2}}, + // {type: "m.room.guest_access", state_key: "", content: {guest_access: "can_join"}}, + // ], + // }); + // } + // + // client.on("room.failed_decryption", async (roomId: string, event: any, e: Error) => { + // LogService.error("index", `Failed to decrypt ${roomId} ${event['event_id']} because `, e); + // }); + // + // client.on("room.message", async (roomId: string, event: any) => { + // if (roomId !== encryptedRoomId) return; + // + // const message = new MessageEvent(event); + // + // if (message.sender === (await client.getUserId()) && message.messageType === "m.notice") { + // // yay, we decrypted our own message. Communicate that back for testing purposes. + // const encrypted = await client.crypto.encryptMedia(Buffer.from(worksImage)); + // const mxc = await client.uploadContent(encrypted.buffer); + // await client.sendMessage(roomId, { + // msgtype: "m.image", + // body: "it-works.png", + // info: { + // // XXX: We know these details, so have hardcoded them. + // w: 256, + // h: 256, + // mimetype: "image/png", + // size: worksImage.length, + // }, + // file: { + // url: mxc, + // ...encrypted.file, + // }, + // }); + // return; + // } + // + // if (message.messageType === "m.image") { + // const fileEvent = new MessageEvent(message.raw); + // const decrypted = await client.crypto.decryptMedia(fileEvent.content.file); + // fs.writeFileSync('./examples/storage/decrypted.png', decrypted); + // await client.unstableApis.addReactionToEvent(roomId, fileEvent.eventId, 'Decrypted'); + // return; + // } + // + // if (message.messageType !== "m.text") return; + // if (message.textBody.startsWith("!ping")) { + // await client.replyNotice(roomId, event, "Pong"); + // } + // }); LogService.info("index", "Starting bot..."); await client.start(); + + const callRoomId = await client.joinRoom("#test-call-1:localhost"); + const calls = await client.unstableApis.getCallsInRoom(callRoomId); + const activeCall = calls.find(c => !c.callEvent.isTerminated); + if (!activeCall) { + throw new Error("A call is not in progress"); + } + + await activeCall.join(); })(); diff --git a/package.json b/package.json index cfae6a7d..4ab9166c 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,8 @@ "morgan": "^1.10.0", "request": "^2.88.2", "request-promise": "^4.2.6", - "sanitize-html": "^2.7.0" + "sanitize-html": "^2.7.0", + "wrtc": "^0.4.7" }, "devDependencies": { "@babel/core": "^7.18.2", diff --git a/src/MatrixClient.ts b/src/MatrixClient.ts index 6a04dd8e..8b41be70 100644 --- a/src/MatrixClient.ts +++ b/src/MatrixClient.ts @@ -957,12 +957,12 @@ export class MatrixClient extends EventEmitter { * @returns {Promise} resolves to the state event */ @timedMatrixClientFunctionCall() - public getRoomStateEvent(roomId, type, stateKey): Promise { + public getRoomStateEvent(roomId, type, stateKey, format = "content"): Promise { const path = "/_matrix/client/v3/rooms/" + encodeURIComponent(roomId) + "/state/" + encodeURIComponent(type) + "/" + encodeURIComponent(stateKey ? stateKey : ''); - return this.doRequest("GET", path) + return this.doRequest("GET", path, { format }) .then(ev => this.processEvent(ev)); } diff --git a/src/UnstableApis.ts b/src/UnstableApis.ts index 93284db6..8a1ccb43 100644 --- a/src/UnstableApis.ts +++ b/src/UnstableApis.ts @@ -1,5 +1,7 @@ import { MatrixClient } from "./MatrixClient"; import { MSC2380MediaInfo } from "./models/unstable/MediaInfo"; +import { MSC3401Call } from "./voip/MSC3401Call"; +import { MSC3401CallEvent } from "./models/events/MSC3401CallEvent"; /** * Unstable APIs that shouldn't be used in most circumstances. @@ -71,4 +73,67 @@ export class UnstableApis { } return this.client.doRequest("GET", `/_matrix/media/unstable/info/${encodeURIComponent(domain)}/${encodeURIComponent(mediaId)}`); } + + /** + * Creates an MSC3401 call room (public). This is essentially a proxy to the createRoom + * function with a special template. + * @param {string} name The name of the call. + * @returns {Promise} Resolves to the room ID. + */ + public async createCallRoom(name: string): Promise { + return this.client.createRoom({ + // Template borrowed from Element Call + name: name, + preset: "public_chat", + room_alias_name: name, + visibility: "private", + power_level_content_override: { + users_default: 0, + events_default: 0, + state_default: 0, + invite: 100, + kick: 100, + redact: 50, + ban: 100, + events: { + "m.room.encrypted": 50, + "m.room.encryption": 100, + "m.room.history_visibility": 100, + "m.room.message": 0, + "m.room.name": 50, + "m.room.power_levels": 100, + "m.room.tombstone": 100, + "m.sticker": 50, + "org.matrix.msc3401.call.member": 0, + }, + users: { + [await this.client.getUserId()]: 100, + }, + }, + }); + } + + /** + * Starts a call in the room. + * @param {string} roomId The room ID to start a call in. + * @returns {Promise} Resolves to the call object. + */ + public async startCallInRoom(roomId: string): Promise { + const roomName = await this.client.getRoomStateEvent(roomId, "m.room.name", ""); + const call = new MSC3401Call(this.client, roomId, roomName["name"]); + await this.client.sendStateEvent(roomId, call.callEvent.type, call.callEvent.stateKey, call.callEvent.content); + return call; + } + + /** + * Get all the calls in a room. + * @param {string} roomId The room ID. + * @returns {Promise} Resolves to an array of all known calls. + */ + public async getCallsInRoom(roomId: string): Promise { + const state = await this.client.getRoomState(roomId); + return state + .filter(s => s.type === 'org.matrix.msc3401.call') + .map(s => new MSC3401Call(this.client, roomId, new MSC3401CallEvent(s))); + } } diff --git a/src/models/events/MSC3401CallEvent.ts b/src/models/events/MSC3401CallEvent.ts new file mode 100644 index 00000000..b7a2a0b3 --- /dev/null +++ b/src/models/events/MSC3401CallEvent.ts @@ -0,0 +1,48 @@ +import { StateEvent } from "./RoomEvent"; + +/** + * The content definition for m.call state events + * @category Matrix event contents + * @see MSC3401CallEvent + */ +export interface MSC3401CallEventContent { + "m.intent": "m.room" | "m.ring" | "m.prompt" | string; + "m.type": "m.voice" | "m.video" | string; + "m.terminated": boolean; // TODO: Check type + "m.name": string; // TODO: Check if used + "m.foci"?: string[]; // Not currently supported +} + +/** + * Represents an m.call state event + * @category Matrix events + */ +export class MSC3401CallEvent extends StateEvent { + constructor(event: any) { + super(event); + } + + public get callId(): string { + return this.stateKey; + } + + public get startTime(): number { + return this.timestamp; + } + + public get intent(): MSC3401CallEventContent["m.intent"] { + return this.content["m.intent"]; + } + + public get callType(): MSC3401CallEventContent["m.type"] { + return this.content["m.type"]; + } + + public get isTerminated(): boolean { + return !!this.content["m.terminated"]; + } + + public get name(): string { + return this.content["m.name"]; + } +} diff --git a/src/models/events/MSC3401CallMemberEvent.ts b/src/models/events/MSC3401CallMemberEvent.ts new file mode 100644 index 00000000..f9b69e29 --- /dev/null +++ b/src/models/events/MSC3401CallMemberEvent.ts @@ -0,0 +1,58 @@ +import { StateEvent } from "./RoomEvent"; + +/** + * The definition of a member's device in an m.call.member event content. + * @category Matrix event contents + * @see MSC3401CallMemberEventContent + */ +export interface MSC3401CallMemberEventDevice { + device_id: string; + session_id: string; + feeds: { + purpose: "m.usermedia" | "m.screenshare" | string; + }[]; +} + +/** + * The content definition for m.call.member state events + * @category Matrix event contents + * @see MSC3401CallMemberEvent + */ +export interface MSC3401CallMemberEventContent { + "m.calls": { + "m.call_id": string; + "m.foci"?: string[]; // not currently used + "m.devices": MSC3401CallMemberEventDevice[]; + }[]; +} + +/** + * Represents an m.call.member state event + * @category Matrix events + */ +export class MSC3401CallMemberEvent extends StateEvent { + constructor(event: any) { + super(event); + } + + public get forUserId(): string { + return this.stateKey; + } + + public get isInCall(): boolean { + return this.content["m.calls"]?.length > 0; + } + + public get callId(): string { + return this.content["m.calls"]?.[0]?.["m.call_id"]; + } + + public get deviceIdSessions(): Record { + return this.content["m.calls"]?.[0]?.["m.devices"]?.reduce((p, c) => { + if (c.feeds?.filter(f => f.purpose === "m.usermedia" || f.purpose === "m.screenshare").length === 0) { + return p; + } + return { ...p, [c.device_id]: c.session_id }; + }, {}); + } +} diff --git a/src/voip/MSC3401Call.ts b/src/voip/MSC3401Call.ts new file mode 100644 index 00000000..5d14c25e --- /dev/null +++ b/src/voip/MSC3401Call.ts @@ -0,0 +1,214 @@ +import { MSC3401CallEvent, MSC3401CallEventContent } from "../models/events/MSC3401CallEvent"; +import { randomUUID } from "crypto"; +import { MatrixClient } from "../MatrixClient"; +import { MSC3401CallMemberEvent, MSC3401CallMemberEventContent } from "../models/events/MSC3401CallMemberEvent"; +import { RTCPeerConnection, RTCSessionDescription, RTCIceCandidate, nonstandard, MediaStream } from "wrtc"; +import { LogService } from "../logging/LogService"; + +// TODO: Wire this up to sync + demo +// TODO: Wire up to appservices +// TODO: Support to-device channel for communications +// TODO: Support defining (external) media streams. Media is not anticipated to be handled in JS. +// TODO: Support negotiating a write-only mode +// TODO: Test against Element Call + +/** + * An experimental implementation of MSC3401 for calls over Matrix. + * + * The API surface offered by this class can break at any point without warning. + * + * @category VoIP + */ +export class MSC3401Call { + public readonly callEvent: MSC3401CallEvent; + + private members: MSC3401CallMemberEvent[]; + private inCall = false; + private rtc = new RTCPeerConnection({ + iceServers: [{ + urls: ['stun:stun1.l.google.com:19302', 'stun:stun2.l.google.com:19302'], + }], + iceCandidatePoolSize: 10, + }); + private rtcCallId: string; + + public constructor(client: MatrixClient, roomId: string, callName: string); + public constructor(client: MatrixClient, roomId: string, callEvent: MSC3401CallEvent); + public constructor(private client: MatrixClient, private roomId: string, nameOrEvent: string | MSC3401CallEvent) { + if (typeof nameOrEvent === 'string') { + this.callEvent = new MSC3401CallEvent({ + type: "org.matrix.msc3401.call", + state_key: randomUUID(), + content: { + "m.intent": "m.prompt", // TODO: Expose as option + "m.name": nameOrEvent, + "m.terminated": false, + "m.type": "m.voice", // TODO: Expose as option + }, + }); + } else { + this.callEvent = nameOrEvent; + } + + if (!this.client.crypto) { + throw new Error("Crypto is required for VoIP"); + } + + const source = new nonstandard.RTCAudioSource(); + const track = source.createTrack(); + const sink = new nonstandard.RTCAudioSink(track); + const sampleRate = 8000; + const samples = new Int16Array(sampleRate / 100); // 10ms of 16 bit mono audio + const data = {samples, sampleRate}; + setInterval(() => source.onData(data)); + this.rtc.addTrack(track, new MediaStream([track])); + + this.client.on("to_device.decrypted", async (edu) => { + if (edu["type"] === "m.call.invite" && edu["content"]?.["conf_id"] === this.callEvent.callId) { + LogService.info("MSC3401Call", `${this.callEvent.callId} offer received`); + this.rtcCallId = edu["content"]["call_id"]; + this.rtc.setRemoteDescription(new RTCSessionDescription(edu.content.offer)); + } else if (edu["type"] === "m.call.candidates" && edu["content"]?.["conf_id"] === this.callEvent.callId) { + for (const candidate of edu["content"]["candidates"]) { + if (!candidate.candidate) continue; + this.rtc.addIceCandidate(new RTCIceCandidate(candidate)); + } + if (this.rtc.signalingState === "have-remote-offer") { + await this.broadcastCallAnswer(); + } + } + }); + + let queuedCandidates: RTCIceCandidate[] = []; + this.rtc.onicecandidate = async (ev) => { + if (!ev.candidate) { + await this.broadcastCandidates(queuedCandidates); + queuedCandidates = []; + } else { + queuedCandidates.push(ev.candidate); + } + }; + } + + private async getSelfMember(): Promise { + const userId = await this.client.getUserId(); + return this.members.find(m => m.forUserId === userId); + } + + public async join() { + const ev = new MSC3401CallMemberEvent({ + type: "org.matrix.msc3401.call.member", + state_key: await this.client.getUserId(), + content: { + "m.calls": [{ + "m.call_id": this.callEvent.callId, + "m.devices": [{ + device_id: this.client.crypto.clientDeviceId, + session_id: randomUUID(), + feeds: [{ + purpose: "m.usermedia", + }], + }], + }], + }, + }); + await this.client.sendStateEvent(this.roomId, ev.type, ev.stateKey, ev.content); + await this.scanMembers(); + } + + private async scanMembers() { + this.members = []; + const members = await this.client.getJoinedRoomMembers(this.roomId); + for (const member of members) { + try { + const callMember = await this.client.getRoomStateEvent(this.roomId, "org.matrix.msc3401.call.member", member, 'event'); + if (callMember) { + await this.handleMember(new MSC3401CallMemberEvent(callMember)); + } + } catch (e) { + // ignore error - not joined to call + } + } + } + + private async handleMember(member: MSC3401CallMemberEvent) { + this.members = [ + ...this.members.filter(m => m.forUserId !== member.forUserId), + member, + ]; + + const myUserId = await this.client.getUserId(); + this.inCall = this.members.some(m => m.forUserId === myUserId); + + if (this.inCall) { + this.establishSessions(); + } + } + + private establishSessions() { + // TODO: Establish call sessions with whoever we haven't yet + // TODO: Establish olm sessions too + } + + private async doBroadcast(type: string, message: object) { + const selfUserId = await this.client.getUserId(); + const joinedMembers = this.members.filter(m => m.isInCall && m.forUserId !== selfUserId); + + const messages = {}; + for (const target of joinedMembers) { + if (!messages[target.forUserId]) messages[target.forUserId] = {}; + + const userMap = messages[target.forUserId]; + for (const [deviceId, sessionId] of Object.entries(target.deviceIdSessions)) { + userMap[deviceId] = { + ...message, + party_id: deviceId, + device_id: deviceId, + dest_session_id: sessionId, + }; + } + + await this.client.sendToDevices(type, messages); + } + } + + private async broadcastCallAnswer() { + const selfUserId = await this.client.getUserId(); + const selfDeviceId = this.client.crypto.clientDeviceId; + const selfMember = this.members.find(m => m.isInCall && m.forUserId === selfUserId); + + const answer = await this.rtc.createAnswer(); + await this.rtc.setLocalDescription(answer); + + await this.doBroadcast("m.call.answer", { + answer: { + sdp: answer.sdp, + type: answer.type, + }, + conf_id: this.callEvent.callId, + seq: 0, + version: 1, + capabilities: { + "m.call.transferee": false, + "m.call.dtmf": false, + }, + sender_session_id: selfMember.deviceIdSessions[selfDeviceId], + call_id: this.rtcCallId, + }); + } + + private async broadcastCandidates(candidates: RTCIceCandidate[]) { + const selfUserId = await this.client.getUserId(); + const selfDeviceId = this.client.crypto.clientDeviceId; + const selfMember = this.members.find(m => m.isInCall && m.forUserId === selfUserId); + + await this.doBroadcast("m.call.candidates", { + candidates: candidates.map(c => ({ candidate: c.candidate, sdpMid: c.sdpMid, sdpMLineIndex: c.sdpMLineIndex })), + conf_id: this.callEvent.callId, + seq: 1, + version: 1, + sender_session_id: selfMember.deviceIdSessions[selfDeviceId], + call_id: this.rtcCallId, + }); + } +} diff --git a/yarn.lock b/yarn.lock index 0e205339..29302f0b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -932,6 +932,11 @@ "@typescript-eslint/types" "5.26.0" eslint-visitor-keys "^3.3.0" +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -1003,6 +1008,11 @@ ansi-escapes@^4.2.1: dependencies: type-fest "^0.21.3" +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -1035,6 +1045,19 @@ anymatch@^3.0.3: normalize-path "^3.0.0" picomatch "^2.0.4" +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +are-we-there-yet@~1.1.2: + version "1.1.7" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146" + integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -1421,6 +1444,11 @@ character-parser@^2.1.1: dependencies: is-regex "^1.0.3" +chownr@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + ci-info@^3.2.0: version "3.3.1" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.1.tgz#58331f6f472a25fe3a50a351ae3052936c2c7f32" @@ -1461,6 +1489,11 @@ co@^4.6.0: resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== + collect-v8-coverage@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" @@ -1507,6 +1540,11 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + constantinople@^3.0.1, constantinople@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/constantinople/-/constantinople-3.1.2.tgz#d45ed724f57d3d10500017a7d3a889c1381ae647" @@ -1556,6 +1594,11 @@ core-util-is@1.0.2: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -1584,7 +1627,7 @@ debug@2.6.9, debug@^2.6.9: dependencies: ms "2.0.0" -debug@^3.2.7: +debug@^3.2.6, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -1608,6 +1651,11 @@ dedent@^0.7.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -1631,6 +1679,11 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + depd@2.0.0, depd@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" @@ -1641,6 +1694,11 @@ destroy@1.2.0: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== + detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -1706,6 +1764,13 @@ domelementtype@^2.0.1, domelementtype@^2.2.0: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== +domexception@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" + integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug== + dependencies: + webidl-conversions "^4.0.2" + domhandler@^4.0.0, domhandler@^4.2.0: version "4.3.1" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" @@ -2241,6 +2306,13 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== +fs-minipass@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== + dependencies: + minipass "^2.6.0" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -2276,6 +2348,20 @@ functions-have-names@^1.2.2: resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -2432,6 +2518,11 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -2514,13 +2605,20 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -iconv-lite@0.4.24: +iconv-lite@0.4.24, iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" +ignore-walk@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.4.tgz#c9a09f69b7c7b479a5d74ac1a3c0d4236d2a6335" + integrity sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ== + dependencies: + minimatch "^3.0.4" + ignore@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" @@ -2555,11 +2653,16 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" @@ -2631,6 +2734,13 @@ is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== + dependencies: + number-is-nan "^1.0.0" + is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -2721,6 +2831,11 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -3539,6 +3654,28 @@ minimist@^1.2.0, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== +minipass@^2.6.0, minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== + dependencies: + minipass "^2.9.0" + +mkdirp@^0.5.1, mkdirp@^0.5.5: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" @@ -3595,6 +3732,15 @@ nearley@^2.20.1: railroad-diagrams "^1.0.0" randexp "0.4.6" +needle@^2.2.1: + version "2.9.1" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.9.1.tgz#22d1dffbe3490c2b83e301f7709b6736cd8f2684" + integrity sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ== + dependencies: + debug "^3.2.6" + iconv-lite "^0.4.4" + sax "^1.2.4" + negotiator@0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" @@ -3622,16 +3768,61 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= +node-pre-gyp@^0.13.0: + version "0.13.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.13.0.tgz#df9ab7b68dd6498137717838e4f92a33fc9daa42" + integrity sha512-Md1D3xnEne8b/HGVQkZZwV27WUi1ZRuZBij24TNaZwUPU3ZAFtvT6xxJGaUVillfmMKnn5oD1HoGsp2Ftik7SQ== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + node-releases@^2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.5.tgz#280ed5bc3eba0d96ce44897d8aee478bfb3d9666" integrity sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q== +nopt@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" + integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== + dependencies: + abbrev "1" + osenv "^0.1.4" + normalize-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +npm-bundled@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1" + integrity sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ== + dependencies: + npm-normalize-package-bin "^1.0.1" + +npm-normalize-package-bin@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" + integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== + +npm-packlist@^1.1.6: + version "1.4.8" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" + integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + npm-normalize-package-bin "^1.0.1" + npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" @@ -3639,6 +3830,21 @@ npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== + oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" @@ -3723,6 +3929,24 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== + +os-tmpdir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + +osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" @@ -3915,6 +4139,11 @@ private@^0.1.8: resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + promise@^7.0.1: version "7.3.1" resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" @@ -4112,6 +4341,16 @@ raw-body@2.5.1: iconv-lite "0.4.24" unpipe "1.0.0" +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + react-ace@^9.5.0: version "9.5.0" resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-9.5.0.tgz#b6c32b70d404dd821a7e01accc2d76da667ff1f7" @@ -4159,6 +4398,19 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.1.0.tgz#61aaed3096d30eacf2a2127118b5b41387d32a67" integrity sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg== +readable-stream@^2.0.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + recast@^0.17.3: version "0.17.6" resolved "https://registry.yarnpkg.com/recast/-/recast-0.17.6.tgz#64ae98d0d2dfb10ff92ff5fb9ffb7371823b69fa" @@ -4301,6 +4553,13 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" +rimraf@^2.6.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -4315,12 +4574,12 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -safe-buffer@5.1.2, safe-buffer@~5.1.1: +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.2: +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -4342,6 +4601,11 @@ sanitize-html@^2.7.0: parse-srcset "^1.0.2" postcss "^8.3.11" +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + selderee@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/selderee/-/selderee-0.6.0.tgz#f3bee66cfebcb6f33df98e4a1df77388b42a96f7" @@ -4356,6 +4620,11 @@ semver@7.x, semver@^7.3.5, semver@^7.3.7: dependencies: lru-cache "^6.0.0" +semver@^5.3.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + semver@^6.0.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" @@ -4390,6 +4659,11 @@ serve-static@1.15.0: parseurl "~1.3.3" send "0.18.0" +set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + setprototypeof@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" @@ -4416,7 +4690,7 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: +signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== @@ -4511,7 +4785,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -4538,6 +4821,20 @@ string.prototype.trimstart@^1.0.5: define-properties "^1.1.4" es-abstract "^1.19.5" +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -4572,6 +4869,11 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -4611,6 +4913,19 @@ taffydb@2.6.2: resolved "https://registry.yarnpkg.com/taffydb/-/taffydb-2.6.2.tgz#7cbcb64b5a141b6a2efc2c5d2c67b4e150b2a268" integrity sha1-fLy2S1oUG2ou/CxdLGe04VCyomg= +tar@^4: + version "4.4.19" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" + integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== + dependencies: + chownr "^1.1.4" + fs-minipass "^1.2.7" + minipass "^2.9.0" + minizlib "^1.3.3" + mkdirp "^0.5.5" + safe-buffer "^5.2.1" + yallist "^3.1.1" + terminal-link@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" @@ -4830,6 +5145,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" @@ -4911,6 +5231,11 @@ walker@^1.0.7: dependencies: makeerror "1.0.12" +webidl-conversions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" + integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" @@ -4929,6 +5254,13 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +wide-align@^1.1.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" @@ -4974,6 +5306,15 @@ write-file-atomic@^4.0.1: imurmurhash "^0.1.4" signal-exit "^3.0.7" +wrtc@^0.4.7: + version "0.4.7" + resolved "https://registry.yarnpkg.com/wrtc/-/wrtc-0.4.7.tgz#c61530cd662713e50bffe64b7a78673ce070426c" + integrity sha512-P6Hn7VT4lfSH49HxLHcHhDq+aFf/jd9dPY7lDHeFhZ22N3858EKuwm2jmnlPzpsRGEPaoF6XwkcxY5SYnt4f/g== + dependencies: + node-pre-gyp "^0.13.0" + optionalDependencies: + domexception "^1.0.1" + xmlcreate@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/xmlcreate/-/xmlcreate-2.0.4.tgz#0c5ab0f99cdd02a81065fa9cd8f8ae87624889be" @@ -4989,6 +5330,11 @@ yallist@^2.1.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= +yallist@^3.0.0, yallist@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"