Only report undecryptable events once (#12501)
* persist previously-reported event IDs as a bloom filter * Pin to older `@types/seedrandom` ... to work around https://github.com/Callidon/bloom-filters/issues/72 * Inline `DecryptionFailureTracker.addDecryptionFailure` * Remove redundant TRACK_INTERVAL There really doesn't seem to be much point to this batching up of decryption failure reports. We still call the analytics callback the same number of times. * Rename `trackedEvents` to `reportedEvents` * Fix incorrect documentation on `visibleEvents` This *does* overlap with `failures`. * Combine `addFailure` and `reportFailure` * Calculate client properties before starting reporting * Clear localstorage after each test ... otherwise they interfere * Remove redundant comment * Ensure that reports are cleared on a logout/login cycle * make private const private and const --------- Co-authored-by: Richard van der Hoff <richard@matrix.org>
This commit is contained in:
parent
3e103941d6
commit
1bb70c5b3b
5 changed files with 197 additions and 73 deletions
|
@ -81,6 +81,7 @@
|
||||||
"@zxcvbn-ts/language-common": "^3.0.4",
|
"@zxcvbn-ts/language-common": "^3.0.4",
|
||||||
"@zxcvbn-ts/language-en": "^3.0.2",
|
"@zxcvbn-ts/language-en": "^3.0.2",
|
||||||
"await-lock": "^2.1.0",
|
"await-lock": "^2.1.0",
|
||||||
|
"bloom-filters": "^3.0.1",
|
||||||
"blurhash": "^2.0.3",
|
"blurhash": "^2.0.3",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"commonmark": "^0.31.0",
|
"commonmark": "^0.31.0",
|
||||||
|
@ -182,6 +183,7 @@
|
||||||
"@types/react-transition-group": "^4.4.0",
|
"@types/react-transition-group": "^4.4.0",
|
||||||
"@types/sanitize-html": "2.11.0",
|
"@types/sanitize-html": "2.11.0",
|
||||||
"@types/sdp-transform": "^2.4.6",
|
"@types/sdp-transform": "^2.4.6",
|
||||||
|
"@types/seedrandom": "<3.0.5",
|
||||||
"@types/tar-js": "^0.3.2",
|
"@types/tar-js": "^0.3.2",
|
||||||
"@types/ua-parser-js": "^0.7.36",
|
"@types/ua-parser-js": "^0.7.36",
|
||||||
"@types/uuid": "^9.0.2",
|
"@types/uuid": "^9.0.2",
|
||||||
|
|
|
@ -14,12 +14,16 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { ScalableBloomFilter } from "bloom-filters";
|
||||||
import { CryptoEvent, HttpApiEvent, MatrixClient, MatrixEventEvent, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
import { CryptoEvent, HttpApiEvent, MatrixClient, MatrixEventEvent, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||||
import { Error as ErrorEvent } from "@matrix-org/analytics-events/types/typescript/Error";
|
import { Error as ErrorEvent } from "@matrix-org/analytics-events/types/typescript/Error";
|
||||||
import { DecryptionFailureCode } from "matrix-js-sdk/src/crypto-api";
|
import { DecryptionFailureCode } from "matrix-js-sdk/src/crypto-api";
|
||||||
|
|
||||||
import { PosthogAnalytics } from "./PosthogAnalytics";
|
import { PosthogAnalytics } from "./PosthogAnalytics";
|
||||||
|
|
||||||
|
/** The key that we use to store the `reportedEvents` bloom filter in localstorage */
|
||||||
|
const DECRYPTION_FAILURE_STORAGE_KEY = "mx_decryption_failure_event_ids";
|
||||||
|
|
||||||
export class DecryptionFailure {
|
export class DecryptionFailure {
|
||||||
/**
|
/**
|
||||||
* The time between our initial failure to decrypt and our successful
|
* The time between our initial failure to decrypt and our successful
|
||||||
|
@ -104,8 +108,8 @@ export class DecryptionFailureTracker {
|
||||||
*/
|
*/
|
||||||
public visibleEvents: Set<string> = new Set();
|
public visibleEvents: Set<string> = new Set();
|
||||||
|
|
||||||
/** Event IDs of failures that were reported previously */
|
/** Bloom filter tracking event IDs of failures that were reported previously */
|
||||||
private reportedEvents: Set<string> = new Set();
|
private reportedEvents: ScalableBloomFilter = new ScalableBloomFilter();
|
||||||
|
|
||||||
/** Set to an interval ID when `start` is called */
|
/** Set to an interval ID when `start` is called */
|
||||||
public checkInterval: number | null = null;
|
public checkInterval: number | null = null;
|
||||||
|
@ -172,13 +176,18 @@ export class DecryptionFailureTracker {
|
||||||
return DecryptionFailureTracker.internalInstance;
|
return DecryptionFailureTracker.internalInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadReportedEvents() {
|
private loadReportedEvents(): void {
|
||||||
// this.reportedEvents = new Set(JSON.parse(localStorage.getItem('mx-decryption-failure-event-ids')) || []);
|
const storedFailures = localStorage.getItem(DECRYPTION_FAILURE_STORAGE_KEY);
|
||||||
// }
|
if (storedFailures) {
|
||||||
|
this.reportedEvents = ScalableBloomFilter.fromJSON(JSON.parse(storedFailures));
|
||||||
|
} else {
|
||||||
|
this.reportedEvents = new ScalableBloomFilter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// saveReportedEvents() {
|
private saveReportedEvents(): void {
|
||||||
// localStorage.setItem('mx-decryption-failure-event-ids', JSON.stringify([...this.reportedEvents]));
|
localStorage.setItem(DECRYPTION_FAILURE_STORAGE_KEY, JSON.stringify(this.reportedEvents.saveAsJSON()));
|
||||||
// }
|
}
|
||||||
|
|
||||||
/** Callback for when an event is decrypted.
|
/** Callback for when an event is decrypted.
|
||||||
*
|
*
|
||||||
|
@ -290,6 +299,7 @@ export class DecryptionFailureTracker {
|
||||||
* Start checking for and tracking failures.
|
* Start checking for and tracking failures.
|
||||||
*/
|
*/
|
||||||
public async start(client: MatrixClient): Promise<void> {
|
public async start(client: MatrixClient): Promise<void> {
|
||||||
|
this.loadReportedEvents();
|
||||||
await this.calculateClientProperties(client);
|
await this.calculateClientProperties(client);
|
||||||
this.registerHandlers(client);
|
this.registerHandlers(client);
|
||||||
this.checkInterval = window.setInterval(
|
this.checkInterval = window.setInterval(
|
||||||
|
@ -385,9 +395,7 @@ export class DecryptionFailureTracker {
|
||||||
}
|
}
|
||||||
this.failures = failuresNotReady;
|
this.failures = failuresNotReady;
|
||||||
|
|
||||||
// Commented out for now for expediency, we need to consider unbound nature of storing
|
this.saveReportedEvents();
|
||||||
// this in localStorage
|
|
||||||
// this.saveReportedEvents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -23,8 +23,8 @@ import {
|
||||||
MatrixClient,
|
MatrixClient,
|
||||||
MatrixEvent,
|
MatrixEvent,
|
||||||
RoomType,
|
RoomType,
|
||||||
SyncStateData,
|
|
||||||
SyncState,
|
SyncState,
|
||||||
|
SyncStateData,
|
||||||
TimelineEvents,
|
TimelineEvents,
|
||||||
} from "matrix-js-sdk/src/matrix";
|
} from "matrix-js-sdk/src/matrix";
|
||||||
import { defer, IDeferred, QueryDict } from "matrix-js-sdk/src/utils";
|
import { defer, IDeferred, QueryDict } from "matrix-js-sdk/src/utils";
|
||||||
|
@ -128,7 +128,7 @@ import { TimelineRenderingType } from "../../contexts/RoomContext";
|
||||||
import { UseCaseSelection } from "../views/elements/UseCaseSelection";
|
import { UseCaseSelection } from "../views/elements/UseCaseSelection";
|
||||||
import { ValidatedServerConfig } from "../../utils/ValidatedServerConfig";
|
import { ValidatedServerConfig } from "../../utils/ValidatedServerConfig";
|
||||||
import { isLocalRoom } from "../../utils/localRoom/isLocalRoom";
|
import { isLocalRoom } from "../../utils/localRoom/isLocalRoom";
|
||||||
import { SdkContextClass, SDKContext } from "../../contexts/SDKContext";
|
import { SDKContext, SdkContextClass } from "../../contexts/SDKContext";
|
||||||
import { viewUserDeviceSettings } from "../../actions/handlers/viewUserDeviceSettings";
|
import { viewUserDeviceSettings } from "../../actions/handlers/viewUserDeviceSettings";
|
||||||
import { cleanUpBroadcasts, VoiceBroadcastResumer } from "../../voice-broadcast";
|
import { cleanUpBroadcasts, VoiceBroadcastResumer } from "../../voice-broadcast";
|
||||||
import GenericToast from "../views/toasts/GenericToast";
|
import GenericToast from "../views/toasts/GenericToast";
|
||||||
|
@ -1585,13 +1585,9 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const dft = DecryptionFailureTracker.instance;
|
DecryptionFailureTracker.instance
|
||||||
|
.start(cli)
|
||||||
// Shelved for later date when we have time to think about persisting history of
|
.catch((e) => logger.error("Unable to start DecryptionFailureTracker", e));
|
||||||
// tracked events across sessions.
|
|
||||||
// dft.loadTrackedEventHashMap();
|
|
||||||
|
|
||||||
dft.start(cli).catch((e) => logger.error("Unable to start DecryptionFailureTracker", e));
|
|
||||||
|
|
||||||
cli.on(ClientEvent.Room, (room) => {
|
cli.on(ClientEvent.Room, (room) => {
|
||||||
if (cli.isCryptoEnabled()) {
|
if (cli.isCryptoEnabled()) {
|
||||||
|
|
|
@ -14,14 +14,15 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { mocked, Mocked } from "jest-mock";
|
import { mocked, Mocked, MockedObject } from "jest-mock";
|
||||||
import { CryptoEvent, HttpApiEvent, MatrixEvent, MatrixEventEvent } from "matrix-js-sdk/src/matrix";
|
import { CryptoEvent, HttpApiEvent, MatrixClient, MatrixEvent, MatrixEventEvent } from "matrix-js-sdk/src/matrix";
|
||||||
import { decryptExistingEvent, mkDecryptionFailureMatrixEvent } from "matrix-js-sdk/src/testing";
|
import { decryptExistingEvent, mkDecryptionFailureMatrixEvent } from "matrix-js-sdk/src/testing";
|
||||||
import { CryptoApi, DecryptionFailureCode, UserVerificationStatus } from "matrix-js-sdk/src/crypto-api";
|
import { CryptoApi, DecryptionFailureCode, UserVerificationStatus } from "matrix-js-sdk/src/crypto-api";
|
||||||
import { sleep } from "matrix-js-sdk/src/utils";
|
import { sleep } from "matrix-js-sdk/src/utils";
|
||||||
|
|
||||||
import { DecryptionFailureTracker, ErrorProperties } from "../src/DecryptionFailureTracker";
|
import { DecryptionFailureTracker, ErrorProperties } from "../src/DecryptionFailureTracker";
|
||||||
import { stubClient } from "./test-utils";
|
import { stubClient } from "./test-utils";
|
||||||
|
import * as Lifecycle from "../src/Lifecycle";
|
||||||
|
|
||||||
async function createFailedDecryptionEvent(opts: { sender?: string; code?: DecryptionFailureCode } = {}) {
|
async function createFailedDecryptionEvent(opts: { sender?: string; code?: DecryptionFailureCode } = {}) {
|
||||||
return await mkDecryptionFailureMatrixEvent({
|
return await mkDecryptionFailureMatrixEvent({
|
||||||
|
@ -39,6 +40,10 @@ function eventDecrypted(tracker: DecryptionFailureTracker, e: MatrixEvent, nowTs
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("DecryptionFailureTracker", function () {
|
describe("DecryptionFailureTracker", function () {
|
||||||
|
afterEach(() => {
|
||||||
|
localStorage.clear();
|
||||||
|
});
|
||||||
|
|
||||||
it("tracks a failed decryption for a visible event", async function () {
|
it("tracks a failed decryption for a visible event", async function () {
|
||||||
const failedDecryptionEvent = await createFailedDecryptionEvent();
|
const failedDecryptionEvent = await createFailedDecryptionEvent();
|
||||||
|
|
||||||
|
@ -247,6 +252,7 @@ describe("DecryptionFailureTracker", function () {
|
||||||
() => count++,
|
() => count++,
|
||||||
() => "UnknownError",
|
() => "UnknownError",
|
||||||
);
|
);
|
||||||
|
await tracker.start(mockClient());
|
||||||
|
|
||||||
tracker.addVisibleEvent(decryptedEvent);
|
tracker.addVisibleEvent(decryptedEvent);
|
||||||
|
|
||||||
|
@ -264,10 +270,7 @@ describe("DecryptionFailureTracker", function () {
|
||||||
expect(count).toBe(1);
|
expect(count).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip("should not track a failure for an event that was tracked in a previous session", async () => {
|
it("should not report a failure for an event that was reported in a previous session", async () => {
|
||||||
// This test uses localStorage, clear it beforehand
|
|
||||||
localStorage.clear();
|
|
||||||
|
|
||||||
const decryptedEvent = await createFailedDecryptionEvent();
|
const decryptedEvent = await createFailedDecryptionEvent();
|
||||||
|
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
@ -276,6 +279,7 @@ describe("DecryptionFailureTracker", function () {
|
||||||
() => count++,
|
() => count++,
|
||||||
() => "UnknownError",
|
() => "UnknownError",
|
||||||
);
|
);
|
||||||
|
await tracker.start(mockClient());
|
||||||
|
|
||||||
tracker.addVisibleEvent(decryptedEvent);
|
tracker.addVisibleEvent(decryptedEvent);
|
||||||
|
|
||||||
|
@ -289,14 +293,13 @@ describe("DecryptionFailureTracker", function () {
|
||||||
// Simulate the browser refreshing by destroying tracker and creating a new tracker
|
// Simulate the browser refreshing by destroying tracker and creating a new tracker
|
||||||
// @ts-ignore access to private constructor
|
// @ts-ignore access to private constructor
|
||||||
const secondTracker = new DecryptionFailureTracker(
|
const secondTracker = new DecryptionFailureTracker(
|
||||||
(total: number) => (count += total),
|
() => count++,
|
||||||
() => "UnknownError",
|
() => "UnknownError",
|
||||||
);
|
);
|
||||||
|
await secondTracker.start(mockClient());
|
||||||
|
|
||||||
secondTracker.addVisibleEvent(decryptedEvent);
|
secondTracker.addVisibleEvent(decryptedEvent);
|
||||||
|
|
||||||
//secondTracker.loadTrackedEvents();
|
|
||||||
|
|
||||||
eventDecrypted(secondTracker, decryptedEvent, Date.now());
|
eventDecrypted(secondTracker, decryptedEvent, Date.now());
|
||||||
secondTracker.checkFailures(Infinity);
|
secondTracker.checkFailures(Infinity);
|
||||||
|
|
||||||
|
@ -304,6 +307,70 @@ describe("DecryptionFailureTracker", function () {
|
||||||
expect(count).toBe(1);
|
expect(count).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should report a failure for an event that was tracked but not reported in a previous session", async () => {
|
||||||
|
const decryptedEvent = await createFailedDecryptionEvent();
|
||||||
|
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
// @ts-ignore access to private constructor
|
||||||
|
const tracker = new DecryptionFailureTracker(
|
||||||
|
() => count++,
|
||||||
|
() => "UnknownError",
|
||||||
|
);
|
||||||
|
await tracker.start(mockClient());
|
||||||
|
|
||||||
|
tracker.addVisibleEvent(decryptedEvent);
|
||||||
|
|
||||||
|
// Indicate decryption
|
||||||
|
eventDecrypted(tracker, decryptedEvent, Date.now());
|
||||||
|
|
||||||
|
// we do *not* call `checkFailures` here
|
||||||
|
expect(count).toBe(0);
|
||||||
|
|
||||||
|
// Simulate the browser refreshing by destroying tracker and creating a new tracker
|
||||||
|
// @ts-ignore access to private constructor
|
||||||
|
const secondTracker = new DecryptionFailureTracker(
|
||||||
|
() => count++,
|
||||||
|
() => "UnknownError",
|
||||||
|
);
|
||||||
|
await secondTracker.start(mockClient());
|
||||||
|
|
||||||
|
secondTracker.addVisibleEvent(decryptedEvent);
|
||||||
|
|
||||||
|
eventDecrypted(secondTracker, decryptedEvent, Date.now());
|
||||||
|
secondTracker.checkFailures(Infinity);
|
||||||
|
expect(count).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should report a failure for an event that was reported before a logout/login cycle", async () => {
|
||||||
|
const decryptedEvent = await createFailedDecryptionEvent();
|
||||||
|
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
// @ts-ignore access to private constructor
|
||||||
|
const tracker = new DecryptionFailureTracker(
|
||||||
|
() => count++,
|
||||||
|
() => "UnknownError",
|
||||||
|
);
|
||||||
|
await tracker.start(mockClient());
|
||||||
|
|
||||||
|
tracker.addVisibleEvent(decryptedEvent);
|
||||||
|
|
||||||
|
// Indicate decryption
|
||||||
|
eventDecrypted(tracker, decryptedEvent, Date.now());
|
||||||
|
tracker.checkFailures(Infinity);
|
||||||
|
expect(count).toBe(1);
|
||||||
|
|
||||||
|
// Simulate a logout/login cycle
|
||||||
|
await Lifecycle.onLoggedOut();
|
||||||
|
await tracker.start(mockClient());
|
||||||
|
|
||||||
|
tracker.addVisibleEvent(decryptedEvent);
|
||||||
|
eventDecrypted(tracker, decryptedEvent, Date.now());
|
||||||
|
tracker.checkFailures(Infinity);
|
||||||
|
expect(count).toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
it("should count different error codes separately for multiple failures with different error codes", async () => {
|
it("should count different error codes separately for multiple failures with different error codes", async () => {
|
||||||
const counts: Record<string, number> = {};
|
const counts: Record<string, number> = {};
|
||||||
|
|
||||||
|
@ -521,12 +588,7 @@ describe("DecryptionFailureTracker", function () {
|
||||||
it("listens for client events", async () => {
|
it("listens for client events", async () => {
|
||||||
// Test that the decryption failure tracker registers the right event
|
// Test that the decryption failure tracker registers the right event
|
||||||
// handlers on start, and unregisters them when the client logs out.
|
// handlers on start, and unregisters them when the client logs out.
|
||||||
const client = mocked(stubClient());
|
const client = mockClient();
|
||||||
const mockCrypto = {
|
|
||||||
getVersion: jest.fn().mockReturnValue("Rust SDK 0.7.0 (61b175b), Vodozemac 0.5.1"),
|
|
||||||
getUserVerificationStatus: jest.fn().mockResolvedValue(new UserVerificationStatus(false, false, false)),
|
|
||||||
} as unknown as Mocked<CryptoApi>;
|
|
||||||
client.getCrypto.mockReturnValue(mockCrypto);
|
|
||||||
|
|
||||||
let errorCount: number = 0;
|
let errorCount: number = 0;
|
||||||
// @ts-ignore access to private constructor
|
// @ts-ignore access to private constructor
|
||||||
|
@ -568,13 +630,7 @@ describe("DecryptionFailureTracker", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("tracks client information", async () => {
|
it("tracks client information", async () => {
|
||||||
const client = mocked(stubClient());
|
const client = mockClient();
|
||||||
const mockCrypto = {
|
|
||||||
getVersion: jest.fn().mockReturnValue("Rust SDK 0.7.0 (61b175b), Vodozemac 0.5.1"),
|
|
||||||
getUserVerificationStatus: jest.fn().mockResolvedValue(new UserVerificationStatus(false, false, false)),
|
|
||||||
} as unknown as Mocked<CryptoApi>;
|
|
||||||
client.getCrypto.mockReturnValue(mockCrypto);
|
|
||||||
|
|
||||||
const propertiesByErrorCode: Record<string, ErrorProperties> = {};
|
const propertiesByErrorCode: Record<string, ErrorProperties> = {};
|
||||||
// @ts-ignore access to private constructor
|
// @ts-ignore access to private constructor
|
||||||
const tracker = new DecryptionFailureTracker(
|
const tracker = new DecryptionFailureTracker(
|
||||||
|
@ -610,7 +666,9 @@ describe("DecryptionFailureTracker", function () {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
eventDecrypted(tracker, federatedDecryption, now);
|
eventDecrypted(tracker, federatedDecryption, now);
|
||||||
|
|
||||||
mockCrypto.getUserVerificationStatus.mockResolvedValue(new UserVerificationStatus(true, true, false));
|
mocked(client.getCrypto()!.getUserVerificationStatus).mockResolvedValue(
|
||||||
|
new UserVerificationStatus(true, true, false),
|
||||||
|
);
|
||||||
client.emit(CryptoEvent.KeysChanged, {});
|
client.emit(CryptoEvent.KeysChanged, {});
|
||||||
await sleep(100);
|
await sleep(100);
|
||||||
eventDecrypted(tracker, localDecryption, now);
|
eventDecrypted(tracker, localDecryption, now);
|
||||||
|
@ -628,7 +686,7 @@ describe("DecryptionFailureTracker", function () {
|
||||||
|
|
||||||
// change client params, and make sure the reports the right values
|
// change client params, and make sure the reports the right values
|
||||||
client.getDomain.mockReturnValue("example.com");
|
client.getDomain.mockReturnValue("example.com");
|
||||||
mockCrypto.getVersion.mockReturnValue("Olm 0.0.0");
|
mocked(client.getCrypto()!.getVersion).mockReturnValue("Olm 0.0.0");
|
||||||
// @ts-ignore access to private method
|
// @ts-ignore access to private method
|
||||||
await tracker.calculateClientProperties(client);
|
await tracker.calculateClientProperties(client);
|
||||||
|
|
||||||
|
@ -673,3 +731,21 @@ describe("DecryptionFailureTracker", function () {
|
||||||
expect(failure?.timeToDecryptMillis).toEqual(50000);
|
expect(failure?.timeToDecryptMillis).toEqual(50000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function mockClient(): MockedObject<MatrixClient> {
|
||||||
|
const client = mocked(stubClient());
|
||||||
|
const mockCrypto = {
|
||||||
|
getVersion: jest.fn().mockReturnValue("Rust SDK 0.7.0 (61b175b), Vodozemac 0.5.1"),
|
||||||
|
getUserVerificationStatus: jest.fn().mockResolvedValue(new UserVerificationStatus(false, false, false)),
|
||||||
|
} as unknown as Mocked<CryptoApi>;
|
||||||
|
client.getCrypto.mockReturnValue(mockCrypto);
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
client.stopClient = jest.fn(() => {});
|
||||||
|
// @ts-ignore
|
||||||
|
client.removeAllListeners = jest.fn(() => {});
|
||||||
|
|
||||||
|
client.store = { destroy: jest.fn(() => {}) } as any;
|
||||||
|
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
100
yarn.lock
100
yarn.lock
|
@ -2907,6 +2907,11 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/sdp-transform/-/sdp-transform-2.4.9.tgz#26ef39f487a6909b0512f580b80920a366b27f52"
|
resolved "https://registry.yarnpkg.com/@types/sdp-transform/-/sdp-transform-2.4.9.tgz#26ef39f487a6909b0512f580b80920a366b27f52"
|
||||||
integrity sha512-bVr+/OoZZy7wrHlNcEAAa6PAgKA4BoXPYVN2EijMC5WnGgQ4ZEuixmKnVs2roiAvr7RhIFVH17QD27cojgIZCg==
|
integrity sha512-bVr+/OoZZy7wrHlNcEAAa6PAgKA4BoXPYVN2EijMC5WnGgQ4ZEuixmKnVs2roiAvr7RhIFVH17QD27cojgIZCg==
|
||||||
|
|
||||||
|
"@types/seedrandom@<3.0.5":
|
||||||
|
version "3.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-3.0.4.tgz#e4a8d0fca0168cacc7dba2af0e4a4ea645d3a190"
|
||||||
|
integrity sha512-/rWdxeiuZenlawrHU+XV6ZHMTKOqrC2hMfeDfLTIWJhDZP5aVqXRysduYHBbhD7CeJO6FJr/D2uBVXB7GT6v7w==
|
||||||
|
|
||||||
"@types/semver@^7.5.8":
|
"@types/semver@^7.5.8":
|
||||||
version "7.5.8"
|
version "7.5.8"
|
||||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e"
|
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e"
|
||||||
|
@ -3594,6 +3599,11 @@ base-x@^4.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.0.tgz#d0e3b7753450c73f8ad2389b5c018a4af7b2224a"
|
resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.0.tgz#d0e3b7753450c73f8ad2389b5c018a4af7b2224a"
|
||||||
integrity sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==
|
integrity sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==
|
||||||
|
|
||||||
|
base64-arraybuffer@^1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#1c37589a7c4b0746e34bd1feb951da2df01c1bdc"
|
||||||
|
integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==
|
||||||
|
|
||||||
big-integer@^1.6.48:
|
big-integer@^1.6.48:
|
||||||
version "1.6.51"
|
version "1.6.51"
|
||||||
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686"
|
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686"
|
||||||
|
@ -3614,6 +3624,21 @@ blob-polyfill@^7.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/blob-polyfill/-/blob-polyfill-7.0.20220408.tgz#38bf5e046c41a21bb13654d9d19f303233b8218c"
|
resolved "https://registry.yarnpkg.com/blob-polyfill/-/blob-polyfill-7.0.20220408.tgz#38bf5e046c41a21bb13654d9d19f303233b8218c"
|
||||||
integrity sha512-oD8Ydw+5lNoqq+en24iuPt1QixdPpe/nUF8azTHnviCZYu9zUC+TwdzIp5orpblJosNlgNbVmmAb//c6d6ImUQ==
|
integrity sha512-oD8Ydw+5lNoqq+en24iuPt1QixdPpe/nUF8azTHnviCZYu9zUC+TwdzIp5orpblJosNlgNbVmmAb//c6d6ImUQ==
|
||||||
|
|
||||||
|
bloom-filters@^3.0.1:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/bloom-filters/-/bloom-filters-3.0.1.tgz#13e28ed22febe2489cd00ba5bd98fdc90e820180"
|
||||||
|
integrity sha512-rU9IU6bgZ1jmqcLWhlKSidrFjbIGjB89CJBsQqUj1+3/11tAJDwn+f7iRu4bbQ2srTjGgNeoWNwcnelumqdi0g==
|
||||||
|
dependencies:
|
||||||
|
base64-arraybuffer "^1.0.2"
|
||||||
|
is-buffer "^2.0.5"
|
||||||
|
lodash "^4.17.15"
|
||||||
|
lodash.eq "^4.0.0"
|
||||||
|
lodash.indexof "^4.0.5"
|
||||||
|
long "^5.2.0"
|
||||||
|
reflect-metadata "^0.1.13"
|
||||||
|
seedrandom "^3.0.5"
|
||||||
|
xxhashjs "^0.2.2"
|
||||||
|
|
||||||
blurhash@^2.0.3:
|
blurhash@^2.0.3:
|
||||||
version "2.0.5"
|
version "2.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/blurhash/-/blurhash-2.0.5.tgz#efde729fc14a2f03571a6aa91b49cba80d1abe4b"
|
resolved "https://registry.yarnpkg.com/blurhash/-/blurhash-2.0.5.tgz#efde729fc14a2f03571a6aa91b49cba80d1abe4b"
|
||||||
|
@ -4155,6 +4180,11 @@ csstype@^3.0.2:
|
||||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
|
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
|
||||||
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
|
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
|
||||||
|
|
||||||
|
cuint@^0.2.2:
|
||||||
|
version "0.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/cuint/-/cuint-0.2.2.tgz#408086d409550c2631155619e9fa7bcadc3b991b"
|
||||||
|
integrity sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==
|
||||||
|
|
||||||
damerau-levenshtein@^1.0.8:
|
damerau-levenshtein@^1.0.8:
|
||||||
version "1.0.8"
|
version "1.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7"
|
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7"
|
||||||
|
@ -5976,6 +6006,11 @@ is-boolean-object@^1.1.0:
|
||||||
call-bind "^1.0.2"
|
call-bind "^1.0.2"
|
||||||
has-tostringtag "^1.0.0"
|
has-tostringtag "^1.0.0"
|
||||||
|
|
||||||
|
is-buffer@^2.0.5:
|
||||||
|
version "2.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191"
|
||||||
|
integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==
|
||||||
|
|
||||||
is-buffer@~1.1.6:
|
is-buffer@~1.1.6:
|
||||||
version "1.1.6"
|
version "1.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
||||||
|
@ -6961,6 +6996,16 @@ lodash.debounce@^4.0.8:
|
||||||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||||
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
|
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
|
||||||
|
|
||||||
|
lodash.eq@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.eq/-/lodash.eq-4.0.0.tgz#a39f06779e72f9c0d1f310c90cd292c1661d5035"
|
||||||
|
integrity sha512-vbrJpXL6kQNG6TkInxX12DZRfuYVllSxhwYqjYB78g2zF3UI15nFO/0AgmZnZRnaQ38sZtjCiVjGr2rnKt4v0g==
|
||||||
|
|
||||||
|
lodash.indexof@^4.0.5:
|
||||||
|
version "4.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.indexof/-/lodash.indexof-4.0.5.tgz#53714adc2cddd6ed87638f893aa9b6c24e31ef3c"
|
||||||
|
integrity sha512-t9wLWMQsawdVmf6/IcAgVGqAJkNzYVcn4BHYZKTPW//l7N5Oq7Bq138BaVk19agcsPZePcidSgTTw4NqS1nUAw==
|
||||||
|
|
||||||
lodash.isequal@^4.5.0:
|
lodash.isequal@^4.5.0:
|
||||||
version "4.5.0"
|
version "4.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
||||||
|
@ -6981,7 +7026,7 @@ lodash.truncate@^4.4.2:
|
||||||
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
||||||
integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==
|
integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==
|
||||||
|
|
||||||
lodash@^4.17.20, lodash@^4.17.21:
|
lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21:
|
||||||
version "4.17.21"
|
version "4.17.21"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||||
|
@ -6991,6 +7036,11 @@ loglevel@^1.7.1:
|
||||||
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.1.tgz#5c621f83d5b48c54ae93b6156353f555963377b4"
|
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.1.tgz#5c621f83d5b48c54ae93b6156353f555963377b4"
|
||||||
integrity sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg==
|
integrity sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg==
|
||||||
|
|
||||||
|
long@^5.2.0:
|
||||||
|
version "5.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1"
|
||||||
|
integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==
|
||||||
|
|
||||||
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
|
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||||
|
@ -8172,6 +8222,11 @@ redux@^4.0.0, redux@^4.0.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.9.2"
|
"@babel/runtime" "^7.9.2"
|
||||||
|
|
||||||
|
reflect-metadata@^0.1.13:
|
||||||
|
version "0.1.14"
|
||||||
|
resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.14.tgz#24cf721fe60677146bb77eeb0e1f9dece3d65859"
|
||||||
|
integrity sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==
|
||||||
|
|
||||||
reflect.getprototypeof@^1.0.4:
|
reflect.getprototypeof@^1.0.4:
|
||||||
version "1.0.6"
|
version "1.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859"
|
resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859"
|
||||||
|
@ -8472,6 +8527,11 @@ sdp-transform@^2.14.1:
|
||||||
resolved "https://registry.yarnpkg.com/sdp-transform/-/sdp-transform-2.14.1.tgz#2bb443583d478dee217df4caa284c46b870d5827"
|
resolved "https://registry.yarnpkg.com/sdp-transform/-/sdp-transform-2.14.1.tgz#2bb443583d478dee217df4caa284c46b870d5827"
|
||||||
integrity sha512-RjZyX3nVwJyCuTo5tGPx+PZWkDMCg7oOLpSlhjDdZfwUoNqG1mM8nyj31IGHyaPWXhjbP7cdK3qZ2bmkJ1GzRw==
|
integrity sha512-RjZyX3nVwJyCuTo5tGPx+PZWkDMCg7oOLpSlhjDdZfwUoNqG1mM8nyj31IGHyaPWXhjbP7cdK3qZ2bmkJ1GzRw==
|
||||||
|
|
||||||
|
seedrandom@^3.0.5:
|
||||||
|
version "3.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7"
|
||||||
|
integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==
|
||||||
|
|
||||||
"semver@2 || 3 || 4 || 5", semver@^5.6.0:
|
"semver@2 || 3 || 4 || 5", semver@^5.6.0:
|
||||||
version "5.7.2"
|
version "5.7.2"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
|
||||||
|
@ -8729,16 +8789,7 @@ string-length@^4.0.1:
|
||||||
char-regex "^1.0.2"
|
char-regex "^1.0.2"
|
||||||
strip-ansi "^6.0.0"
|
strip-ansi "^6.0.0"
|
||||||
|
|
||||||
"string-width-cjs@npm:string-width@^4.2.0":
|
"string-width-cjs@npm:string-width@^4.2.0", 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==
|
|
||||||
dependencies:
|
|
||||||
emoji-regex "^8.0.0"
|
|
||||||
is-fullwidth-code-point "^3.0.0"
|
|
||||||
strip-ansi "^6.0.1"
|
|
||||||
|
|
||||||
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
|
||||||
version "4.2.3"
|
version "4.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||||
|
@ -8832,14 +8883,7 @@ string_decoder@~1.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer "~5.1.0"
|
safe-buffer "~5.1.0"
|
||||||
|
|
||||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", 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"
|
|
||||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
|
||||||
dependencies:
|
|
||||||
ansi-regex "^5.0.1"
|
|
||||||
|
|
||||||
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||||
|
@ -9632,7 +9676,7 @@ which@^2.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
isexe "^2.0.0"
|
isexe "^2.0.0"
|
||||||
|
|
||||||
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
|
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||||
|
@ -9650,15 +9694,6 @@ wrap-ansi@^6.2.0:
|
||||||
string-width "^4.1.0"
|
string-width "^4.1.0"
|
||||||
strip-ansi "^6.0.0"
|
strip-ansi "^6.0.0"
|
||||||
|
|
||||||
wrap-ansi@^7.0.0:
|
|
||||||
version "7.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
|
||||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
|
||||||
dependencies:
|
|
||||||
ansi-styles "^4.0.0"
|
|
||||||
string-width "^4.1.0"
|
|
||||||
strip-ansi "^6.0.0"
|
|
||||||
|
|
||||||
wrap-ansi@^8.1.0:
|
wrap-ansi@^8.1.0:
|
||||||
version "8.1.0"
|
version "8.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
|
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
|
||||||
|
@ -9709,6 +9744,13 @@ xmlchars@^2.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
|
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
|
||||||
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
|
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
|
||||||
|
|
||||||
|
xxhashjs@^0.2.2:
|
||||||
|
version "0.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/xxhashjs/-/xxhashjs-0.2.2.tgz#8a6251567621a1c46a5ae204da0249c7f8caa9d8"
|
||||||
|
integrity sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==
|
||||||
|
dependencies:
|
||||||
|
cuint "^0.2.2"
|
||||||
|
|
||||||
y18n@^4.0.0:
|
y18n@^4.0.0:
|
||||||
version "4.0.3"
|
version "4.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
|
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
|
||||||
|
|
Loading…
Reference in a new issue