Compare commits
40 Commits
v34.0.0
...
v34.1.0-rc.3
| Author | SHA1 | Date | |
|---|---|---|---|
| 6520e0f54f | |||
| ed7b314e6a | |||
| 24eff501e4 | |||
| a0d73dfaca | |||
| 5d2500b7a7 | |||
| eff52b82e8 | |||
| 2868308079 | |||
| a5ef569717 | |||
| c06b22ae7c | |||
| 712ba617de | |||
| 957329b218 | |||
| 1733ec7b7f | |||
| 03ed4f5dd7 | |||
| 6e641a28c0 | |||
| b36682cb99 | |||
| ccc2fb5663 | |||
| 0a7f7efd9d | |||
| ae58d0c8eb | |||
| 20a6704497 | |||
| 3337bda752 | |||
| d90292bff5 | |||
| 3de0c02757 | |||
| 65b9c31f9b | |||
| d629a685c2 | |||
| 0210106be2 | |||
| 3e05a71068 | |||
| c755810d9c | |||
| 2d492f60a0 | |||
| 16db2c5f9a | |||
| 29c02d8c37 | |||
| 0f98df158c | |||
| 2ea4ce0bb6 | |||
| 3e0017fecf | |||
| a0073ddaaf | |||
| c29e116c0c | |||
| d9f372ca79 | |||
| 6417f4fac7 | |||
| 4bae83f59f | |||
| b8c68eb102 | |||
| 8790cde6d4 |
@@ -0,0 +1,43 @@
|
||||
- name: "A-Element-R"
|
||||
description: "Issues affecting the port of Element's crypto layer to Rust"
|
||||
color: "bfd4f2"
|
||||
- name: "A-Packaging"
|
||||
description: "Packaging, signing, releasing"
|
||||
color: "bfd4f2"
|
||||
- name: "A-Technical-Debt"
|
||||
color: "bfd4f2"
|
||||
- name: "A-Testing"
|
||||
description: "Testing, code coverage, etc."
|
||||
color: "bfd4f2"
|
||||
- name: "backport staging"
|
||||
description: "Label to automatically backport PR to staging branch"
|
||||
color: "B60205"
|
||||
- name: "Dependencies"
|
||||
description: "Pull requests that update a dependency file"
|
||||
color: "0366d6"
|
||||
- name: "Easy"
|
||||
color: "5dc9f7"
|
||||
- name: "Sponsored"
|
||||
color: "ffc8f4"
|
||||
- name: "T-Deprecation"
|
||||
description: "A pull request that makes something deprecated"
|
||||
color: "98e6ae"
|
||||
- name: "T-Other"
|
||||
description: "Questions, user support, anything else"
|
||||
color: "98e6ae"
|
||||
- name: "X-Blocked"
|
||||
color: "ff7979"
|
||||
- name: "X-Breaking-Change"
|
||||
color: "ff7979"
|
||||
- name: "X-Reverted"
|
||||
description: "PR has been reverted"
|
||||
color: "F68AA3"
|
||||
- name: "X-Upcoming-Release-Blocker"
|
||||
description: "This does not affect the current release cycle but will affect the next one"
|
||||
color: "e99695"
|
||||
- name: "Z-Community-PR"
|
||||
description: "Issue is solved by a community member's PR"
|
||||
color: "ededed"
|
||||
- name: "Z-Flaky-Test"
|
||||
description: "A test is raising false alarms"
|
||||
color: "ededed"
|
||||
@@ -24,10 +24,6 @@ on:
|
||||
description: List of github projects (owner/repo) which should have their dependency bumped to the newly released version (in JSON string array string syntax)
|
||||
type: string
|
||||
required: false
|
||||
include-changes:
|
||||
description: Project to include changelog entries from in this release.
|
||||
type: string
|
||||
required: false
|
||||
gpg-fingerprint:
|
||||
description: Fingerprint of the GPG key to use for signing the git tag and assets, if any.
|
||||
type: string
|
||||
@@ -120,6 +116,7 @@ jobs:
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: "yarn"
|
||||
node-version-file: package.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: "yarn install --frozen-lockfile"
|
||||
@@ -319,6 +316,11 @@ jobs:
|
||||
ref: staging
|
||||
token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: "yarn"
|
||||
node-version: "lts/*"
|
||||
|
||||
- name: Bump dependency
|
||||
env:
|
||||
DEPENDENCY: ${{ needs.npm.outputs.id }}
|
||||
|
||||
@@ -25,6 +25,7 @@ jobs:
|
||||
with:
|
||||
cache: "yarn"
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
node-version-file: package.json
|
||||
|
||||
- name: 🔨 Install dependencies
|
||||
run: "yarn install --frozen-lockfile"
|
||||
|
||||
@@ -43,6 +43,7 @@ jobs:
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: "yarn"
|
||||
node-version-file: package.json
|
||||
|
||||
- name: 🔨 Install dependencies
|
||||
run: "yarn install --frozen-lockfile"
|
||||
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
target_url: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
|
||||
- name: "🧮 Checkout code"
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
|
||||
with:
|
||||
repository: ${{ github.event.workflow_run.head_repository.full_name }}
|
||||
ref: ${{ github.event.workflow_run.head_branch }} # checkout commit that triggered this workflow
|
||||
|
||||
@@ -18,6 +18,7 @@ jobs:
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: "yarn"
|
||||
node-version-file: package.json
|
||||
|
||||
- name: Install Deps
|
||||
run: "yarn install"
|
||||
@@ -44,6 +45,7 @@ jobs:
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: "yarn"
|
||||
node-version-file: package.json
|
||||
|
||||
- name: Install Deps
|
||||
run: "yarn install"
|
||||
@@ -60,6 +62,7 @@ jobs:
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: "yarn"
|
||||
node-version-file: package.json
|
||||
|
||||
- name: Install Deps
|
||||
run: "yarn install --frozen-lockfile"
|
||||
@@ -76,12 +79,13 @@ jobs:
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: "yarn"
|
||||
node-version-file: package.json
|
||||
|
||||
- name: Install Deps
|
||||
run: "yarn install"
|
||||
|
||||
- name: Generate Docs
|
||||
run: "yarn run gendoc --treatWarningsAsErrors"
|
||||
run: "yarn run gendoc --treatWarningsAsErrors --suppressCommentWarningsInDeclarationFiles"
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -100,6 +104,7 @@ jobs:
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: "yarn"
|
||||
node-version-file: package.json
|
||||
|
||||
- name: Install Deps
|
||||
run: "yarn install --frozen-lockfile"
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
name: Sync labels
|
||||
on:
|
||||
workflow_dispatch: {}
|
||||
schedule:
|
||||
- cron: "0 1 * * *" # 1am every day
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
paths:
|
||||
- .github/labels.yml
|
||||
jobs:
|
||||
sync-labels:
|
||||
uses: element-hq/element-meta/.github/workflows/sync-labels.yml@develop
|
||||
with:
|
||||
LABELS: |
|
||||
element-hq/element-meta
|
||||
.github/labels.yml
|
||||
DELETE: true
|
||||
WET: true
|
||||
secrets:
|
||||
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
specs: [integ, unit]
|
||||
node: [18, "lts/*", 21]
|
||||
node: ["lts/*", 21, 22]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
@@ -3,12 +3,10 @@
|
||||
"version": "0.0.0",
|
||||
"description": "",
|
||||
"main": "app.js",
|
||||
"scripts": {
|
||||
"preinstall": "npm install ../.."
|
||||
},
|
||||
"author": "",
|
||||
"license": "Apache 2.0",
|
||||
"dependencies": {
|
||||
"cli-color": "^1.0.0"
|
||||
"cli-color": "^1.0.0",
|
||||
"matrix-js-sdk": "^32.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
+9
-9
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "matrix-js-sdk",
|
||||
"version": "34.0.0",
|
||||
"version": "34.1.0-rc.3",
|
||||
"description": "Matrix Client-Server SDK for Javascript",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"prepack": "yarn build",
|
||||
@@ -54,8 +54,9 @@
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@matrix-org/matrix-sdk-crypto-wasm": "^6.0.0",
|
||||
"@matrix-org/olm": "3.2.15",
|
||||
"another-json": "^0.2.0",
|
||||
"bs58": "^5.0.0",
|
||||
"bs58": "^6.0.0",
|
||||
"content-type": "^1.0.4",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"loglevel": "^1.7.1",
|
||||
@@ -82,7 +83,6 @@
|
||||
"@babel/preset-env": "^7.12.11",
|
||||
"@babel/preset-typescript": "^7.12.7",
|
||||
"@casualbot/jest-sonar-reporter": "2.2.7",
|
||||
"@matrix-org/olm": "3.2.15",
|
||||
"@peculiar/webcrypto": "^1.4.5",
|
||||
"@types/bs58": "^4.0.1",
|
||||
"@types/content-type": "^1.1.5",
|
||||
@@ -90,7 +90,7 @@
|
||||
"@types/jest": "^29.0.0",
|
||||
"@types/node": "18",
|
||||
"@types/sdp-transform": "^2.4.5",
|
||||
"@types/uuid": "9",
|
||||
"@types/uuid": "10",
|
||||
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
||||
"@typescript-eslint/parser": "^7.0.0",
|
||||
"babel-jest": "^29.0.0",
|
||||
@@ -104,9 +104,9 @@
|
||||
"eslint-plugin-jsdoc": "^48.0.0",
|
||||
"eslint-plugin-matrix-org": "^1.0.0",
|
||||
"eslint-plugin-tsdoc": "^0.3.0",
|
||||
"eslint-plugin-unicorn": "^53.0.0",
|
||||
"eslint-plugin-unicorn": "^54.0.0",
|
||||
"fake-indexeddb": "^5.0.2",
|
||||
"fetch-mock": "9.11.0",
|
||||
"fetch-mock": "10.0.7",
|
||||
"fetch-mock-jest": "^1.5.1",
|
||||
"husky": "^9.0.0",
|
||||
"jest": "^29.0.0",
|
||||
@@ -120,10 +120,10 @@
|
||||
"prettier": "3.3.2",
|
||||
"rimraf": "^5.0.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"typedoc": "^0.25.10",
|
||||
"typedoc": "^0.26.0",
|
||||
"typedoc-plugin-coverage": "^3.0.0",
|
||||
"typedoc-plugin-mdn-links": "^3.0.3",
|
||||
"typedoc-plugin-missing-exports": "^2.0.0",
|
||||
"typedoc-plugin-missing-exports": "^3.0.0",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"@casualbot/jest-sonar-reporter": {
|
||||
|
||||
@@ -112,7 +112,14 @@ const main = async ({ github, releaseId, dependencies }) => {
|
||||
const { GITHUB_REPOSITORY } = process.env;
|
||||
const [owner, repo] = GITHUB_REPOSITORY.split("/");
|
||||
|
||||
const { data: release } = await github.rest.repos.getRelease({
|
||||
owner,
|
||||
repo,
|
||||
release_id: releaseId,
|
||||
});
|
||||
|
||||
const sections = Object.fromEntries(categories.map((cat) => [cat, []]));
|
||||
parseReleaseNotes(release.body, sections);
|
||||
for (const dependency of dependencies) {
|
||||
const releases = await getReleases(github, dependency);
|
||||
for (const release of releases) {
|
||||
@@ -120,12 +127,6 @@ const main = async ({ github, releaseId, dependencies }) => {
|
||||
}
|
||||
}
|
||||
|
||||
const { data: release } = await github.rest.repos.getRelease({
|
||||
owner,
|
||||
repo,
|
||||
release_id: releaseId,
|
||||
});
|
||||
|
||||
const intro = release.body.split(HEADING_PREFIX, 2)[0].trim();
|
||||
|
||||
let output = "";
|
||||
|
||||
@@ -11,6 +11,11 @@ async function main() {
|
||||
pkgJson[field] = pkgJson["matrix_lib_" + field];
|
||||
}
|
||||
}
|
||||
|
||||
// matrix-js-sdk is built into ECMAScript modules. Make sure we declare it as such.
|
||||
// See https://nodejs.org/api/packages.html#type.
|
||||
pkgJson["type"] = "module";
|
||||
|
||||
await fsProm.writeFile(PKGJSON, JSON.stringify(pkgJson, null, 2));
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import anotherjson from "another-json";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import "fake-indexeddb/auto";
|
||||
import { IDBFactory } from "fake-indexeddb";
|
||||
import { MockResponse, MockResponseFunction } from "fetch-mock";
|
||||
import FetchMock from "fetch-mock";
|
||||
import Olm from "@matrix-org/olm";
|
||||
|
||||
import * as testUtils from "../../test-utils/test-utils";
|
||||
@@ -157,7 +157,7 @@ async function expectSendRoomKey(
|
||||
return await new Promise<Olm.InboundGroupSession>((resolve) => {
|
||||
fetchMock.putOnce(
|
||||
new RegExp("/sendToDevice/m.room.encrypted/"),
|
||||
(url: string, opts: RequestInit): MockResponse => {
|
||||
(url: string, opts: RequestInit): FetchMock.MockResponse => {
|
||||
const content = JSON.parse(opts.body as string);
|
||||
resolve(onSendRoomKey(content));
|
||||
return {};
|
||||
@@ -291,7 +291,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
|
||||
* @param response - the response to return from the request. Normally an {@link IClaimOTKsResult}
|
||||
* (or a function that returns one).
|
||||
*/
|
||||
function expectAliceKeyClaim(response: MockResponse | MockResponseFunction) {
|
||||
function expectAliceKeyClaim(response: FetchMock.MockResponse | FetchMock.MockResponseFunction) {
|
||||
const rootRegexp = escapeRegExp(new URL("/_matrix/client/", aliceClient.getHomeserverUrl()).toString());
|
||||
fetchMock.postOnce(new RegExp(rootRegexp + "(r0|v3)/keys/claim"), response);
|
||||
}
|
||||
@@ -1419,7 +1419,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
|
||||
|
||||
fetchMock.putOnce(
|
||||
{ url: new RegExp("/send/"), name: "send-event" },
|
||||
(url: string, opts: RequestInit): MockResponse => {
|
||||
(url: string, opts: RequestInit): FetchMock.MockResponse => {
|
||||
const content = JSON.parse(opts.body as string);
|
||||
logger.log("/send:", content);
|
||||
// make sure that a new session is used
|
||||
@@ -1484,7 +1484,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
|
||||
|
||||
// mark the device as known, and resend.
|
||||
aliceClient.setDeviceKnown(aliceClient.getUserId()!, "DEVICE_ID");
|
||||
expectAliceKeyClaim((url: string, opts: RequestInit): MockResponse => {
|
||||
expectAliceKeyClaim((url: string, opts: RequestInit): FetchMock.MockResponse => {
|
||||
const content = JSON.parse(opts.body as string);
|
||||
expect(content.one_time_keys[aliceClient.getUserId()!].DEVICE_ID).toEqual("signed_curve25519");
|
||||
return getTestKeysClaimResponse(aliceClient.getUserId()!);
|
||||
@@ -2180,11 +2180,11 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
|
||||
const inboundGroupSessionPromise = expectSendRoomKey("@bob:xyz", testOlmAccount);
|
||||
|
||||
// ... and finally, send the room key. We block the response until `sendRoomMessageDefer` completes.
|
||||
const sendRoomMessageDefer = defer<MockResponse>();
|
||||
const sendRoomMessageDefer = defer<FetchMock.MockResponse>();
|
||||
const reqProm = new Promise<IContent>((resolve) => {
|
||||
fetchMock.putOnce(
|
||||
new RegExp("/send/m.room.encrypted/"),
|
||||
async (url: string, opts: RequestInit): Promise<MockResponse> => {
|
||||
async (url: string, opts: RequestInit): Promise<FetchMock.MockResponse> => {
|
||||
resolve(JSON.parse(opts.body as string));
|
||||
return await sendRoomMessageDefer.promise;
|
||||
},
|
||||
|
||||
@@ -66,26 +66,6 @@ describe("MatrixClient.initRustCrypto", () => {
|
||||
expect(databaseNames).toEqual(expect.arrayContaining(["matrix-js-sdk::matrix-sdk-crypto"]));
|
||||
});
|
||||
|
||||
it("should create the meta db if given a pickleKey", async () => {
|
||||
const matrixClient = createClient({
|
||||
baseUrl: "http://test.server",
|
||||
userId: "@alice:localhost",
|
||||
deviceId: "aliceDevice",
|
||||
pickleKey: "testKey",
|
||||
});
|
||||
|
||||
// No databases.
|
||||
expect(await indexedDB.databases()).toHaveLength(0);
|
||||
|
||||
await matrixClient.initRustCrypto();
|
||||
|
||||
// should have two indexed dbs now
|
||||
const databaseNames = (await indexedDB.databases()).map((db) => db.name);
|
||||
expect(databaseNames).toEqual(
|
||||
expect.arrayContaining(["matrix-js-sdk::matrix-sdk-crypto", "matrix-js-sdk::matrix-sdk-crypto-meta"]),
|
||||
);
|
||||
});
|
||||
|
||||
it("should create the meta db if given a storageKey", async () => {
|
||||
const matrixClient = createClient({
|
||||
baseUrl: "http://test.server",
|
||||
@@ -470,10 +450,9 @@ describe("MatrixClient.clearStores", () => {
|
||||
baseUrl: "http://test.server",
|
||||
userId: "@alice:localhost",
|
||||
deviceId: "aliceDevice",
|
||||
pickleKey: "testKey",
|
||||
});
|
||||
|
||||
await matrixClient.initRustCrypto();
|
||||
await matrixClient.initRustCrypto({ storagePassword: "testKey" });
|
||||
expect(await indexedDB.databases()).toHaveLength(2);
|
||||
await matrixClient.stopClient();
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ limitations under the License.
|
||||
import "fake-indexeddb/auto";
|
||||
|
||||
import anotherjson from "another-json";
|
||||
import { MockResponse } from "fetch-mock";
|
||||
import FetchMock from "fetch-mock";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import { IDBFactory } from "fake-indexeddb";
|
||||
import { createHash } from "crypto";
|
||||
@@ -1511,7 +1511,7 @@ function expectSendToDeviceMessage(msgtype: string): Promise<{ messages: any }>
|
||||
return new Promise((resolve) => {
|
||||
fetchMock.putOnce(
|
||||
new RegExp(`/_matrix/client/(r0|v3)/sendToDevice/${escapeRegExp(msgtype)}`),
|
||||
(url: string, opts: RequestInit): MockResponse => {
|
||||
(url: string, opts: RequestInit): FetchMock.MockResponse => {
|
||||
resolve(JSON.parse(opts.body as string));
|
||||
return {};
|
||||
},
|
||||
@@ -1535,7 +1535,7 @@ function mockSecretRequestAndGetPromises(): Map<string, Promise<string>> {
|
||||
|
||||
fetchMock.put(
|
||||
new RegExp(`/_matrix/client/(r0|v3)/sendToDevice/m.secret.request`),
|
||||
(url: string, opts: RequestInit): MockResponse => {
|
||||
(url: string, opts: RequestInit): FetchMock.MockResponse => {
|
||||
const messages = JSON.parse(opts.body as string).messages[TEST_USER_ID];
|
||||
// rust crypto broadcasts to all devices, old crypto to a specific device, take the first one
|
||||
const content = Object.values(messages)[0] as any;
|
||||
|
||||
@@ -2281,67 +2281,70 @@ describe("MatrixClient syncing", () => {
|
||||
httpBackend!.expectedRequests = [];
|
||||
});
|
||||
|
||||
it("should return a room based on the room initialSync API", async () => {
|
||||
httpBackend!.when("GET", `/rooms/${encodeURIComponent(roomOne)}/initialSync`).respond(200, {
|
||||
room_id: roomOne,
|
||||
membership: KnownMembership.Leave,
|
||||
messages: {
|
||||
start: "start",
|
||||
end: "end",
|
||||
chunk: [
|
||||
it.each([undefined, 100])(
|
||||
"should return a room based on the room initialSync API with limit %s",
|
||||
async (limit) => {
|
||||
httpBackend!.when("GET", `/rooms/${encodeURIComponent(roomOne)}/initialSync`).respond(200, {
|
||||
room_id: roomOne,
|
||||
membership: KnownMembership.Leave,
|
||||
messages: {
|
||||
start: "start",
|
||||
end: "end",
|
||||
chunk: [
|
||||
{
|
||||
content: { body: "Message 1" },
|
||||
type: "m.room.message",
|
||||
event_id: "$eventId1",
|
||||
sender: userA,
|
||||
origin_server_ts: 12313525,
|
||||
room_id: roomOne,
|
||||
},
|
||||
{
|
||||
content: { body: "Message 2" },
|
||||
type: "m.room.message",
|
||||
event_id: "$eventId2",
|
||||
sender: userB,
|
||||
origin_server_ts: 12315625,
|
||||
room_id: roomOne,
|
||||
},
|
||||
],
|
||||
},
|
||||
state: [
|
||||
{
|
||||
content: { body: "Message 1" },
|
||||
type: "m.room.message",
|
||||
event_id: "$eventId1",
|
||||
content: { name: "Room Name" },
|
||||
type: "m.room.name",
|
||||
event_id: "$eventId",
|
||||
sender: userA,
|
||||
origin_server_ts: 12313525,
|
||||
room_id: roomOne,
|
||||
},
|
||||
{
|
||||
content: { body: "Message 2" },
|
||||
type: "m.room.message",
|
||||
event_id: "$eventId2",
|
||||
sender: userB,
|
||||
origin_server_ts: 12315625,
|
||||
origin_server_ts: 12314525,
|
||||
state_key: "",
|
||||
room_id: roomOne,
|
||||
},
|
||||
],
|
||||
},
|
||||
state: [
|
||||
{
|
||||
content: { name: "Room Name" },
|
||||
type: "m.room.name",
|
||||
event_id: "$eventId",
|
||||
sender: userA,
|
||||
origin_server_ts: 12314525,
|
||||
state_key: "",
|
||||
room_id: roomOne,
|
||||
},
|
||||
],
|
||||
presence: [
|
||||
{
|
||||
content: {},
|
||||
type: "m.presence",
|
||||
sender: userA,
|
||||
},
|
||||
],
|
||||
});
|
||||
httpBackend!.when("GET", "/events").respond(200, { chunk: [] });
|
||||
presence: [
|
||||
{
|
||||
content: {},
|
||||
type: "m.presence",
|
||||
sender: userA,
|
||||
},
|
||||
],
|
||||
});
|
||||
httpBackend!.when("GET", "/events").respond(200, { chunk: [] });
|
||||
|
||||
const prom = client!.peekInRoom(roomOne);
|
||||
await httpBackend!.flushAllExpected();
|
||||
const room = await prom;
|
||||
const prom = client!.peekInRoom(roomOne, limit);
|
||||
await httpBackend!.flushAllExpected();
|
||||
const room = await prom;
|
||||
|
||||
expect(room.roomId).toBe(roomOne);
|
||||
expect(room.getMyMembership()).toBe(KnownMembership.Leave);
|
||||
expect(room.name).toBe("Room Name");
|
||||
expect(room.currentState.getStateEvents("m.room.name", "")?.getId()).toBe("$eventId");
|
||||
expect(room.timeline[0].getContent().body).toBe("Message 1");
|
||||
expect(room.timeline[1].getContent().body).toBe("Message 2");
|
||||
client?.stopPeeking();
|
||||
httpBackend!.when("GET", "/events").respond(200, { chunk: [] });
|
||||
await httpBackend!.flushAllExpected();
|
||||
});
|
||||
expect(room.roomId).toBe(roomOne);
|
||||
expect(room.getMyMembership()).toBe(KnownMembership.Leave);
|
||||
expect(room.name).toBe("Room Name");
|
||||
expect(room.currentState.getStateEvents("m.room.name", "")?.getId()).toBe("$eventId");
|
||||
expect(room.timeline[0].getContent().body).toBe("Message 1");
|
||||
expect(room.timeline[1].getContent().body).toBe("Message 2");
|
||||
client?.stopPeeking();
|
||||
httpBackend!.when("GET", "/events").respond(200, { chunk: [] });
|
||||
await httpBackend!.flushAllExpected();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe("user account data", () => {
|
||||
|
||||
@@ -15,7 +15,6 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import { MockOptionsMethodPut } from "fetch-mock";
|
||||
|
||||
import { ISyncResponder } from "./SyncResponder";
|
||||
|
||||
@@ -40,7 +39,10 @@ export class AccountDataAccumulator {
|
||||
* @param opts - options to pass to fetchMock
|
||||
* @returns a Promise which will resolve (with the content of the account data) once it is set.
|
||||
*/
|
||||
public interceptSetAccountData(accountDataType: string, opts?: MockOptionsMethodPut): Promise<any> {
|
||||
public interceptSetAccountData(
|
||||
accountDataType: string,
|
||||
opts?: Parameters<(typeof fetchMock)["put"]>[2],
|
||||
): Promise<any> {
|
||||
return new Promise((resolve) => {
|
||||
// Called when the cross signing key is uploaded
|
||||
fetchMock.put(
|
||||
|
||||
@@ -17,7 +17,7 @@ limitations under the License.
|
||||
import debugFunc from "debug";
|
||||
import { Debugger } from "debug";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import { MockResponse } from "fetch-mock";
|
||||
import FetchMock from "fetch-mock";
|
||||
|
||||
/** Interface implemented by classes that intercept `/sync` requests from test clients
|
||||
*
|
||||
@@ -80,7 +80,7 @@ export class SyncResponder implements ISyncResponder {
|
||||
);
|
||||
}
|
||||
|
||||
private async onSyncRequest(): Promise<MockResponse> {
|
||||
private async onSyncRequest(): Promise<FetchMock.MockResponse> {
|
||||
switch (this.state) {
|
||||
case SyncResponderState.IDLE: {
|
||||
this.debug("Got /sync request: waiting for response to be ready");
|
||||
|
||||
@@ -26,7 +26,6 @@ import { getRandomValues } from "node:crypto";
|
||||
import { TextEncoder } from "node:util";
|
||||
|
||||
import { Method } from "../../../src";
|
||||
import * as crypto from "../../../src/crypto/crypto";
|
||||
import { logger } from "../../../src/logger";
|
||||
import {
|
||||
completeAuthorizationCodeGrant,
|
||||
@@ -39,11 +38,6 @@ import { makeDelegatedAuthConfig, mockOpenIdConfiguration } from "../../test-uti
|
||||
|
||||
jest.mock("jwt-decode");
|
||||
|
||||
const webCrypto = new Crypto();
|
||||
|
||||
// save for resetting mocks
|
||||
const realSubtleCrypto = crypto.subtleCrypto;
|
||||
|
||||
describe("oidc authorization", () => {
|
||||
const delegatedAuthConfig = makeDelegatedAuthConfig();
|
||||
const authorizationEndpoint = delegatedAuthConfig.authorizationEndpoint;
|
||||
@@ -62,7 +56,11 @@ describe("oidc authorization", () => {
|
||||
delegatedAuthConfig.metadata.issuer + ".well-known/openid-configuration",
|
||||
mockOpenIdConfiguration(),
|
||||
);
|
||||
global.TextEncoder = TextEncoder;
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
const webCrypto = new Crypto();
|
||||
Object.defineProperty(window, "crypto", {
|
||||
value: {
|
||||
getRandomValues,
|
||||
@@ -70,12 +68,6 @@ describe("oidc authorization", () => {
|
||||
subtle: webCrypto.subtle,
|
||||
},
|
||||
});
|
||||
global.TextEncoder = TextEncoder;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// @ts-ignore reset any ugly mocking we did
|
||||
crypto.subtleCrypto = realSubtleCrypto;
|
||||
});
|
||||
|
||||
it("should generate authorization params", () => {
|
||||
@@ -99,7 +91,7 @@ describe("oidc authorization", () => {
|
||||
it("should generate url with correct parameters", async () => {
|
||||
// test the no crypto case here
|
||||
// @ts-ignore mocking
|
||||
crypto.subtleCrypto = undefined;
|
||||
globalThis.crypto.subtle = undefined;
|
||||
|
||||
const authorizationParams = generateAuthorizationParams({ redirectUri: baseUrl });
|
||||
const authUrl = new URL(
|
||||
|
||||
@@ -1122,4 +1122,59 @@ describe("RoomState", function () {
|
||||
).toBeFalsy();
|
||||
});
|
||||
});
|
||||
describe("skipWrongOrderRoomStateInserts", () => {
|
||||
const idNow = "now";
|
||||
const idBefore = "before";
|
||||
const endState = new RoomState(roomId);
|
||||
const startState = new RoomState(roomId, undefined, true);
|
||||
|
||||
let onRoomStateEvent: (event: MatrixEvent, state: RoomState, lastStateEvent: MatrixEvent | null) => void;
|
||||
const evNow = new MatrixEvent({
|
||||
type: "m.call.member",
|
||||
room_id: roomId,
|
||||
state_key: "@user:example.org",
|
||||
content: {},
|
||||
});
|
||||
evNow.event.unsigned = { replaces_state: idBefore };
|
||||
evNow.event.event_id = idNow;
|
||||
|
||||
const evBefore = new MatrixEvent({
|
||||
type: "m.call.member",
|
||||
room_id: roomId,
|
||||
state_key: "@user:example.org",
|
||||
content: {},
|
||||
});
|
||||
|
||||
const updatedStateWithBefore = jest.fn();
|
||||
const updatedStateWithNow = jest.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
evBefore.event.event_id = idBefore;
|
||||
onRoomStateEvent = (event, _state, _lastState) => {
|
||||
if (event.event.event_id === idNow) {
|
||||
updatedStateWithNow();
|
||||
} else if (event.event.event_id === idBefore) {
|
||||
updatedStateWithBefore();
|
||||
}
|
||||
};
|
||||
endState.on(RoomStateEvent.Events, onRoomStateEvent);
|
||||
startState.on(RoomStateEvent.Events, onRoomStateEvent);
|
||||
});
|
||||
afterEach(() => {
|
||||
endState.off(RoomStateEvent.Events, onRoomStateEvent);
|
||||
startState.off(RoomStateEvent.Events, onRoomStateEvent);
|
||||
updatedStateWithNow.mockReset();
|
||||
updatedStateWithBefore.mockReset();
|
||||
});
|
||||
it("should skip inserting state to the end of the timeline if the current endState events replaces_state id is the same as the inserted events id", () => {
|
||||
endState.setStateEvents([evNow, evBefore]);
|
||||
expect(updatedStateWithBefore).not.toHaveBeenCalled();
|
||||
expect(updatedStateWithNow).toHaveBeenCalled();
|
||||
});
|
||||
it("should skip inserting state at the beginning of the timeline if the inserted events replaces_state is the event id of the current startState", () => {
|
||||
startState.setStateEvents([evBefore, evNow]);
|
||||
expect(updatedStateWithBefore).toHaveBeenCalled();
|
||||
expect(updatedStateWithNow).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+6
-7
@@ -1075,7 +1075,7 @@ export type ClientEventHandlerMap = {
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
[ClientEvent.Sync]: (state: SyncState, lastState: SyncState | null, data?: ISyncStateData) => void;
|
||||
[ClientEvent.Sync]: (state: SyncState, prevState: SyncState | null, data?: ISyncStateData) => void;
|
||||
/**
|
||||
* Fires whenever the SDK receives a new event.
|
||||
* <p>
|
||||
@@ -2232,9 +2232,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
cryptoCallbacks: this.cryptoCallbacks,
|
||||
storePrefix: args.useIndexedDB === false ? null : RUST_SDK_STORE_PREFIX,
|
||||
storeKey: args.storageKey,
|
||||
|
||||
// temporary compatibility hack: if there is no storageKey nor storagePassword, fall back to the pickleKey
|
||||
storePassphrase: args.storagePassword ?? this.pickleKey,
|
||||
storePassphrase: args.storagePassword,
|
||||
|
||||
legacyCryptoStore: this.cryptoStore,
|
||||
legacyPickleKey: this.pickleKey ?? "DEFAULT_KEY",
|
||||
@@ -6605,13 +6603,14 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
* Peek into a room and receive updates about the room. This only works if the
|
||||
* history visibility for the room is world_readable.
|
||||
* @param roomId - The room to attempt to peek into.
|
||||
* @param limit - The number of timeline events to initially retrieve.
|
||||
* @returns Promise which resolves: Room object
|
||||
* @returns Rejects: with an error response.
|
||||
*/
|
||||
public peekInRoom(roomId: string): Promise<Room> {
|
||||
public peekInRoom(roomId: string, limit: number = 20): Promise<Room> {
|
||||
this.peekSync?.stopPeeking();
|
||||
this.peekSync = new SyncApi(this, this.clientOpts, this.buildSyncApiOptions());
|
||||
return this.peekSync.peek(roomId);
|
||||
return this.peekSync.peek(roomId, limit);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -7410,7 +7409,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
return this.http.authedRequest(Method.Post, path, undefined, undefined, { prefix: "" });
|
||||
}
|
||||
|
||||
private async fetchClientWellKnown(): Promise<void> {
|
||||
protected async fetchClientWellKnown(): Promise<void> {
|
||||
// `getRawClientConfig` does not throw or reject on network errors, instead
|
||||
// it absorbs errors and returns `{}`.
|
||||
this.clientWellKnownPromise = AutoDiscovery.getRawClientConfig(this.getDomain() ?? undefined);
|
||||
|
||||
@@ -15,15 +15,15 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import type { SecretsBundle } from "@matrix-org/matrix-sdk-crypto-wasm";
|
||||
import type { IMegolmSessionData } from "./@types/crypto";
|
||||
import { Room } from "./models/room";
|
||||
import { DeviceMap } from "./models/device";
|
||||
import { UIAuthCallback } from "./interactive-auth";
|
||||
import { PassphraseInfo, SecretStorageCallbacks, SecretStorageKeyDescription } from "./secret-storage";
|
||||
import { VerificationRequest } from "./crypto-api/verification";
|
||||
import { BackupTrustInfo, KeyBackupCheck, KeyBackupInfo } from "./crypto-api/keybackup";
|
||||
import { ISignatures } from "./@types/signed";
|
||||
import { MatrixEvent } from "./models/event";
|
||||
import type { IMegolmSessionData } from "../@types/crypto";
|
||||
import { Room } from "../models/room";
|
||||
import { DeviceMap } from "../models/device";
|
||||
import { UIAuthCallback } from "../interactive-auth";
|
||||
import { PassphraseInfo, SecretStorageCallbacks, SecretStorageKeyDescription } from "../secret-storage";
|
||||
import { VerificationRequest } from "./verification";
|
||||
import { BackupTrustInfo, KeyBackupCheck, KeyBackupInfo } from "./keybackup";
|
||||
import { ISignatures } from "../@types/signed";
|
||||
import { MatrixEvent } from "../models/event";
|
||||
|
||||
/**
|
||||
* Public interface to the cryptography parts of the js-sdk
|
||||
@@ -949,5 +949,5 @@ export interface OwnDeviceKeys {
|
||||
curve25519: string;
|
||||
}
|
||||
|
||||
export * from "./crypto-api/verification";
|
||||
export * from "./crypto-api/keybackup";
|
||||
export * from "./verification";
|
||||
export * from "./keybackup";
|
||||
+12
-10
@@ -15,7 +15,6 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import { decodeBase64, encodeBase64 } from "../base64";
|
||||
import { subtleCrypto, crypto, TextEncoder } from "./crypto";
|
||||
|
||||
// salt for HKDF, with 8 bytes of zeros
|
||||
const zeroSalt = new Uint8Array(8);
|
||||
@@ -49,7 +48,7 @@ export async function encryptAES(
|
||||
iv = decodeBase64(ivStr);
|
||||
} else {
|
||||
iv = new Uint8Array(16);
|
||||
crypto.getRandomValues(iv);
|
||||
globalThis.crypto.getRandomValues(iv);
|
||||
|
||||
// clear bit 63 of the IV to stop us hitting the 64-bit counter boundary
|
||||
// (which would mean we wouldn't be able to decrypt on Android). The loss
|
||||
@@ -60,7 +59,7 @@ export async function encryptAES(
|
||||
const [aesKey, hmacKey] = await deriveKeys(key, name);
|
||||
const encodedData = new TextEncoder().encode(data);
|
||||
|
||||
const ciphertext = await subtleCrypto.encrypt(
|
||||
const ciphertext = await globalThis.crypto.subtle.encrypt(
|
||||
{
|
||||
name: "AES-CTR",
|
||||
counter: iv,
|
||||
@@ -70,7 +69,7 @@ export async function encryptAES(
|
||||
encodedData,
|
||||
);
|
||||
|
||||
const hmac = await subtleCrypto.sign({ name: "HMAC" }, hmacKey, ciphertext);
|
||||
const hmac = await globalThis.crypto.subtle.sign({ name: "HMAC" }, hmacKey, ciphertext);
|
||||
|
||||
return {
|
||||
iv: encodeBase64(iv),
|
||||
@@ -91,11 +90,11 @@ export async function decryptAES(data: IEncryptedPayload, key: Uint8Array, name:
|
||||
|
||||
const ciphertext = decodeBase64(data.ciphertext);
|
||||
|
||||
if (!(await subtleCrypto.verify({ name: "HMAC" }, hmacKey, decodeBase64(data.mac), ciphertext))) {
|
||||
if (!(await globalThis.crypto.subtle.verify({ name: "HMAC" }, hmacKey, decodeBase64(data.mac), ciphertext))) {
|
||||
throw new Error(`Error decrypting secret ${name}: bad MAC`);
|
||||
}
|
||||
|
||||
const plaintext = await subtleCrypto.decrypt(
|
||||
const plaintext = await globalThis.crypto.subtle.decrypt(
|
||||
{
|
||||
name: "AES-CTR",
|
||||
counter: decodeBase64(data.iv),
|
||||
@@ -109,8 +108,8 @@ export async function decryptAES(data: IEncryptedPayload, key: Uint8Array, name:
|
||||
}
|
||||
|
||||
async function deriveKeys(key: Uint8Array, name: string): Promise<[CryptoKey, CryptoKey]> {
|
||||
const hkdfkey = await subtleCrypto.importKey("raw", key, { name: "HKDF" }, false, ["deriveBits"]);
|
||||
const keybits = await subtleCrypto.deriveBits(
|
||||
const hkdfkey = await globalThis.crypto.subtle.importKey("raw", key, { name: "HKDF" }, false, ["deriveBits"]);
|
||||
const keybits = await globalThis.crypto.subtle.deriveBits(
|
||||
{
|
||||
name: "HKDF",
|
||||
salt: zeroSalt,
|
||||
@@ -126,9 +125,12 @@ async function deriveKeys(key: Uint8Array, name: string): Promise<[CryptoKey, Cr
|
||||
const aesKey = keybits.slice(0, 32);
|
||||
const hmacKey = keybits.slice(32);
|
||||
|
||||
const aesProm = subtleCrypto.importKey("raw", aesKey, { name: "AES-CTR" }, false, ["encrypt", "decrypt"]);
|
||||
const aesProm = globalThis.crypto.subtle.importKey("raw", aesKey, { name: "AES-CTR" }, false, [
|
||||
"encrypt",
|
||||
"decrypt",
|
||||
]);
|
||||
|
||||
const hmacProm = subtleCrypto.importKey(
|
||||
const hmacProm = globalThis.crypto.subtle.importKey(
|
||||
"raw",
|
||||
hmacKey,
|
||||
{
|
||||
|
||||
@@ -38,7 +38,6 @@ import {
|
||||
} from "./keybackup";
|
||||
import { UnstableValue } from "../NamespacedValue";
|
||||
import { CryptoEvent } from "./index";
|
||||
import { crypto } from "./crypto";
|
||||
import { ClientPrefix, HTTPError, MatrixError, Method } from "../http-api";
|
||||
import { BackupTrustInfo } from "../crypto-api/keybackup";
|
||||
import { BackupDecryptor } from "../common-crypto/CryptoBackend";
|
||||
@@ -764,7 +763,7 @@ export class Curve25519 implements BackupAlgorithm {
|
||||
|
||||
function randomBytes(size: number): Uint8Array {
|
||||
const buf = new Uint8Array(size);
|
||||
crypto.getRandomValues(buf);
|
||||
globalThis.crypto.getRandomValues(buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
+2
-34
@@ -14,37 +14,5 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { logger } from "../logger";
|
||||
|
||||
export let crypto = globalThis.crypto;
|
||||
export let subtleCrypto = crypto?.subtle ?? crypto?.webkitSubtle; // TODO: Stop using webkitSubtle fallback
|
||||
export let TextEncoder = globalThis.TextEncoder;
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
if (!crypto) {
|
||||
try {
|
||||
crypto = require("crypto").webcrypto;
|
||||
} catch (e) {
|
||||
logger.error("Failed to load webcrypto", e);
|
||||
}
|
||||
}
|
||||
if (!subtleCrypto) {
|
||||
subtleCrypto = crypto?.subtle;
|
||||
}
|
||||
if (!TextEncoder) {
|
||||
try {
|
||||
TextEncoder = require("util").TextEncoder;
|
||||
} catch (e) {
|
||||
logger.error("Failed to load TextEncoder util", e);
|
||||
}
|
||||
}
|
||||
/* eslint-enable @typescript-eslint/no-var-requires */
|
||||
|
||||
export function setCrypto(_crypto: Crypto): void {
|
||||
crypto = _crypto;
|
||||
subtleCrypto = _crypto.subtle ?? _crypto.webkitSubtle;
|
||||
}
|
||||
|
||||
export function setTextEncoder(_TextEncoder: typeof TextEncoder): void {
|
||||
TextEncoder = _TextEncoder;
|
||||
}
|
||||
/** @deprecated this is a no-op and should no longer be called. */
|
||||
export function setCrypto(_crypto: Crypto): void {}
|
||||
|
||||
+2
-2
@@ -276,7 +276,7 @@ export type CryptoEventHandlerMap = {
|
||||
* @param deviceId - the id of the verified device
|
||||
* @param deviceInfo - updated device information
|
||||
*/
|
||||
[CryptoEvent.DeviceVerificationChanged]: (userId: string, deviceId: string, device: DeviceInfo) => void;
|
||||
[CryptoEvent.DeviceVerificationChanged]: (userId: string, deviceId: string, deviceInfo: DeviceInfo) => void;
|
||||
/**
|
||||
* Fires when the trust status of a user changes
|
||||
* If userId is the userId of the logged-in user, this indicated a change
|
||||
@@ -292,7 +292,7 @@ export type CryptoEventHandlerMap = {
|
||||
/**
|
||||
* Fires when we receive a room key request
|
||||
*
|
||||
* @param req - request details
|
||||
* @param request - request details
|
||||
*/
|
||||
[CryptoEvent.RoomKeyRequest]: (request: IncomingRoomKeyRequest) => void;
|
||||
/**
|
||||
|
||||
@@ -15,7 +15,6 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import { randomString } from "../randomstring";
|
||||
import { subtleCrypto, TextEncoder } from "./crypto";
|
||||
|
||||
const DEFAULT_ITERATIONS = 500000;
|
||||
|
||||
@@ -36,10 +35,6 @@ interface IKey {
|
||||
}
|
||||
|
||||
export function keyFromAuthData(authData: IAuthData, password: string): Promise<Uint8Array> {
|
||||
if (!global.Olm) {
|
||||
throw new Error("Olm is not available");
|
||||
}
|
||||
|
||||
if (!authData.private_key_salt || !authData.private_key_iterations) {
|
||||
throw new Error("Salt and/or iterations not found: " + "this backup cannot be restored with a passphrase");
|
||||
}
|
||||
@@ -53,10 +48,6 @@ export function keyFromAuthData(authData: IAuthData, password: string): Promise<
|
||||
}
|
||||
|
||||
export async function keyFromPassphrase(password: string): Promise<IKey> {
|
||||
if (!global.Olm) {
|
||||
throw new Error("Olm is not available");
|
||||
}
|
||||
|
||||
const salt = randomString(32);
|
||||
|
||||
const key = await deriveKey(password, salt, DEFAULT_ITERATIONS, DEFAULT_BITSIZE);
|
||||
@@ -70,15 +61,19 @@ export async function deriveKey(
|
||||
iterations: number,
|
||||
numBits = DEFAULT_BITSIZE,
|
||||
): Promise<Uint8Array> {
|
||||
if (!subtleCrypto || !TextEncoder) {
|
||||
if (!globalThis.crypto.subtle || !TextEncoder) {
|
||||
throw new Error("Password-based backup is not available on this platform");
|
||||
}
|
||||
|
||||
const key = await subtleCrypto.importKey("raw", new TextEncoder().encode(password), { name: "PBKDF2" }, false, [
|
||||
"deriveBits",
|
||||
]);
|
||||
const key = await globalThis.crypto.subtle.importKey(
|
||||
"raw",
|
||||
new TextEncoder().encode(password),
|
||||
{ name: "PBKDF2" },
|
||||
false,
|
||||
["deriveBits"],
|
||||
);
|
||||
|
||||
const keybits = await subtleCrypto.deriveBits(
|
||||
const keybits = await globalThis.crypto.subtle.deriveBits(
|
||||
{
|
||||
name: "PBKDF2",
|
||||
salt: new TextEncoder().encode(salt),
|
||||
|
||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import * as bs58 from "bs58";
|
||||
import bs58 from "bs58";
|
||||
|
||||
// picked arbitrarily but to try & avoid clashing with any bitcoin ones
|
||||
// (which are also base58 encoded, but bitcoin's involve a lot more hashing)
|
||||
|
||||
@@ -18,7 +18,6 @@ limitations under the License.
|
||||
* QR code key verification.
|
||||
*/
|
||||
|
||||
import { crypto } from "../crypto";
|
||||
import { VerificationBase as Base } from "./Base";
|
||||
import { newKeyMismatchError, newUserCancelledError } from "./Error";
|
||||
import { decodeBase64, encodeUnpaddedBase64 } from "../../base64";
|
||||
@@ -202,7 +201,7 @@ export class QRCodeData {
|
||||
|
||||
private static generateSharedSecret(): string {
|
||||
const secretBytes = new Uint8Array(11);
|
||||
crypto.getRandomValues(secretBytes);
|
||||
globalThis.crypto.getRandomValues(secretBytes);
|
||||
return encodeUnpaddedBase64(secretBytes);
|
||||
}
|
||||
|
||||
|
||||
@@ -218,6 +218,14 @@ export class RoomWidgetClient extends MatrixClient {
|
||||
});
|
||||
}) ?? [],
|
||||
);
|
||||
|
||||
if (opts.clientWellKnownPollPeriod !== undefined) {
|
||||
this.clientWellKnownIntervalID = setInterval(() => {
|
||||
this.fetchClientWellKnown();
|
||||
}, 1000 * opts.clientWellKnownPollPeriod);
|
||||
this.fetchClientWellKnown();
|
||||
}
|
||||
|
||||
this.setSyncState(SyncState.Syncing);
|
||||
logger.info("Finished backfilling events");
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ export type EventTimelineSetHandlerMap = {
|
||||
*/
|
||||
[RoomEvent.TimelineReset]: (
|
||||
room: Room | undefined,
|
||||
eventTimelineSet: EventTimelineSet,
|
||||
timelineSet: EventTimelineSet,
|
||||
resetAllTimelines: boolean,
|
||||
) => void;
|
||||
};
|
||||
|
||||
@@ -127,7 +127,7 @@ export class EventTimeline {
|
||||
public constructor(private readonly eventTimelineSet: EventTimelineSet) {
|
||||
this.roomId = eventTimelineSet.room?.roomId ?? null;
|
||||
if (this.roomId) {
|
||||
this.startState = new RoomState(this.roomId);
|
||||
this.startState = new RoomState(this.roomId, undefined, true);
|
||||
this.endState = new RoomState(this.roomId);
|
||||
}
|
||||
|
||||
@@ -267,7 +267,7 @@ export class EventTimeline {
|
||||
/**
|
||||
* Get a pagination token
|
||||
*
|
||||
* @param direction - EventTimeline.BACKWARDS to get the pagination
|
||||
* @param direction - EventTimeline.BACKWARDS to get the pagination
|
||||
* token for going backwards in time; EventTimeline.FORWARDS to get the
|
||||
* pagination token for going forwards in time.
|
||||
*
|
||||
|
||||
@@ -95,7 +95,7 @@ export type RoomStateEventHandlerMap = {
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
[RoomStateEvent.Events]: (event: MatrixEvent, state: RoomState, lastStateEvent: MatrixEvent | null) => void;
|
||||
[RoomStateEvent.Events]: (event: MatrixEvent, state: RoomState, prevEvent: MatrixEvent | null) => void;
|
||||
/**
|
||||
* Fires whenever a member in the members dictionary is updated in any way.
|
||||
* @param event - The matrix event which caused this event to fire.
|
||||
@@ -194,10 +194,22 @@ export class RoomState extends TypedEventEmitter<EmittedEvents, EventHandlerMap>
|
||||
* As the timeline might get reset while they are loading, this state needs to be inherited
|
||||
* and shared when the room state is cloned for the new timeline.
|
||||
* This should only be passed from clone.
|
||||
* @param isStartTimelineState - Optional. This state is marked as a start state.
|
||||
* This is used to skip state insertions that are
|
||||
* in the wrong order. The order is determined by the `replaces_state` id.
|
||||
*
|
||||
* Example:
|
||||
* A current state events `replaces_state` value is `1`.
|
||||
* Trying to insert a state event with `event_id` `1` in its place would fail if isStartTimelineState = false.
|
||||
*
|
||||
* A current state events `event_id` is `2`.
|
||||
* Trying to insert a state event where its `replaces_state` value is `2` would fail if isStartTimelineState = true.
|
||||
*/
|
||||
|
||||
public constructor(
|
||||
public readonly roomId: string,
|
||||
private oobMemberFlags = { status: OobStatus.NotStarted },
|
||||
public readonly isStartTimelineState = false,
|
||||
) {
|
||||
super();
|
||||
this.updateModifiedTime();
|
||||
@@ -408,7 +420,7 @@ export class RoomState extends TypedEventEmitter<EmittedEvents, EventHandlerMap>
|
||||
* Fires {@link RoomStateEvent.Events}
|
||||
* Fires {@link RoomStateEvent.Marker}
|
||||
*/
|
||||
public setStateEvents(stateEvents: MatrixEvent[], markerFoundOptions?: IMarkerFoundOptions): void {
|
||||
public setStateEvents(stateEvents: MatrixEvent[], options?: IMarkerFoundOptions): void {
|
||||
this.updateModifiedTime();
|
||||
|
||||
// update the core event dict
|
||||
@@ -420,6 +432,22 @@ export class RoomState extends TypedEventEmitter<EmittedEvents, EventHandlerMap>
|
||||
}
|
||||
|
||||
const lastStateEvent = this.getStateEventMatching(event);
|
||||
|
||||
// Safety measure to not update the room (and emit the update) with older state.
|
||||
// The sync loop really should not send old events but it does very regularly.
|
||||
// Logging on return in those two conditions results in a large amount of logging. (on startup and when running element)
|
||||
const lastReplaceId = lastStateEvent?.event.unsigned?.replaces_state;
|
||||
const lastId = lastStateEvent?.event.event_id;
|
||||
const newReplaceId = event.event.unsigned?.replaces_state;
|
||||
const newId = event.event.event_id;
|
||||
if (this.isStartTimelineState) {
|
||||
// Add an event to the start of the timeline. Its replace id should not be the same as the one of the current/last start state event.
|
||||
if (newReplaceId && lastId && newReplaceId === lastId) return;
|
||||
} else {
|
||||
// Add an event to the end of the timeline. It should not be the same as the one replaced by the current/last end state event.
|
||||
if (lastReplaceId && newId && lastReplaceId === newId) return;
|
||||
}
|
||||
|
||||
this.setStateEvent(event);
|
||||
if (event.getType() === EventType.RoomMember) {
|
||||
this.updateDisplayNameCache(event.getStateKey()!, event.getContent().displayname ?? "");
|
||||
@@ -476,7 +504,7 @@ export class RoomState extends TypedEventEmitter<EmittedEvents, EventHandlerMap>
|
||||
// assume all our sentinels are now out-of-date
|
||||
this.sentinels = {};
|
||||
} else if (UNSTABLE_MSC2716_MARKER.matches(event.getType())) {
|
||||
this.emit(RoomStateEvent.Marker, event, markerFoundOptions);
|
||||
this.emit(RoomStateEvent.Marker, event, options);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
+1
-1
@@ -209,7 +209,7 @@ export type RoomEventHandlerMap = {
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
[RoomEvent.AccountData]: (event: MatrixEvent, room: Room, lastEvent?: MatrixEvent) => void;
|
||||
[RoomEvent.AccountData]: (event: MatrixEvent, room: Room, prevEvent?: MatrixEvent) => void;
|
||||
/**
|
||||
* Fires whenever a receipt is received for a room
|
||||
* @param event - The receipt event
|
||||
|
||||
@@ -16,17 +16,16 @@ limitations under the License.
|
||||
|
||||
import { IdTokenClaims, Log, OidcClient, SigninResponse, SigninState, WebStorageStateStore } from "oidc-client-ts";
|
||||
|
||||
import { subtleCrypto, TextEncoder } from "../crypto/crypto";
|
||||
import { logger } from "../logger";
|
||||
import { randomString } from "../randomstring";
|
||||
import { OidcError } from "./error";
|
||||
import {
|
||||
validateIdToken,
|
||||
ValidatedIssuerMetadata,
|
||||
validateStoredUserState,
|
||||
UserState,
|
||||
BearerTokenResponse,
|
||||
UserState,
|
||||
validateBearerTokenResponse,
|
||||
ValidatedIssuerMetadata,
|
||||
validateIdToken,
|
||||
validateStoredUserState,
|
||||
} from "./validate";
|
||||
|
||||
// reexport for backwards compatibility
|
||||
@@ -57,14 +56,14 @@ export const generateScope = (deviceId?: string): string => {
|
||||
|
||||
// https://www.rfc-editor.org/rfc/rfc7636
|
||||
const generateCodeChallenge = async (codeVerifier: string): Promise<string> => {
|
||||
if (!subtleCrypto) {
|
||||
if (!globalThis.crypto.subtle) {
|
||||
// @TODO(kerrya) should this be allowed? configurable?
|
||||
logger.warn("A secure context is required to generate code challenge. Using plain text code challenge");
|
||||
return codeVerifier;
|
||||
}
|
||||
const utf8 = new TextEncoder().encode(codeVerifier);
|
||||
|
||||
const digest = await subtleCrypto.digest("SHA-256", utf8);
|
||||
const digest = await globalThis.crypto.subtle.digest("SHA-256", utf8);
|
||||
|
||||
return btoa(String.fromCharCode(...new Uint8Array(digest)))
|
||||
.replace(/=/g, "")
|
||||
|
||||
+1
-2
@@ -16,7 +16,6 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import { encodeUnpaddedBase64Url } from "./base64";
|
||||
import { crypto } from "./crypto/crypto";
|
||||
|
||||
const LOWERCASE = "abcdefghijklmnopqrstuvwxyz";
|
||||
const UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
@@ -24,7 +23,7 @@ const DIGITS = "0123456789";
|
||||
|
||||
export function secureRandomBase64Url(len: number): string {
|
||||
const key = new Uint8Array(len);
|
||||
crypto.getRandomValues(key);
|
||||
globalThis.crypto.getRandomValues(key);
|
||||
|
||||
return encodeUnpaddedBase64Url(key);
|
||||
}
|
||||
|
||||
@@ -17,16 +17,15 @@ limitations under the License.
|
||||
import { SAS } from "@matrix-org/olm";
|
||||
|
||||
import {
|
||||
RendezvousError,
|
||||
RendezvousCode,
|
||||
RendezvousIntent,
|
||||
RendezvousChannel,
|
||||
RendezvousTransportDetails,
|
||||
RendezvousTransport,
|
||||
LegacyRendezvousFailureReason as RendezvousFailureReason,
|
||||
RendezvousChannel,
|
||||
RendezvousCode,
|
||||
RendezvousError,
|
||||
RendezvousIntent,
|
||||
RendezvousTransport,
|
||||
RendezvousTransportDetails,
|
||||
} from "..";
|
||||
import { encodeUnpaddedBase64, decodeBase64 } from "../../base64";
|
||||
import { crypto, subtleCrypto, TextEncoder } from "../../crypto/crypto";
|
||||
import { decodeBase64, encodeUnpaddedBase64 } from "../../base64";
|
||||
import { generateDecimalSas } from "../../crypto/verification/SASDecimal";
|
||||
import { UnstableValue } from "../../NamespacedValue";
|
||||
|
||||
@@ -56,11 +55,11 @@ export interface EncryptedPayload {
|
||||
}
|
||||
|
||||
async function importKey(key: Uint8Array): Promise<CryptoKey> {
|
||||
if (!subtleCrypto) {
|
||||
if (!globalThis.crypto.subtle) {
|
||||
throw new Error("Web Crypto is not available");
|
||||
}
|
||||
|
||||
const imported = subtleCrypto.importKey("raw", key, { name: "AES-GCM" }, false, ["encrypt", "decrypt"]);
|
||||
const imported = globalThis.crypto.subtle.importKey("raw", key, { name: "AES-GCM" }, false, ["encrypt", "decrypt"]);
|
||||
|
||||
return imported;
|
||||
}
|
||||
@@ -164,16 +163,16 @@ export class MSC3903ECDHv2RendezvousChannel<T> implements RendezvousChannel<T> {
|
||||
}
|
||||
|
||||
private async encrypt(data: T): Promise<MSC3903ECDHPayload> {
|
||||
if (!subtleCrypto) {
|
||||
if (!globalThis.crypto.subtle) {
|
||||
throw new Error("Web Crypto is not available");
|
||||
}
|
||||
|
||||
const iv = new Uint8Array(32);
|
||||
crypto.getRandomValues(iv);
|
||||
globalThis.crypto.getRandomValues(iv);
|
||||
|
||||
const encodedData = new TextEncoder().encode(JSON.stringify(data));
|
||||
|
||||
const ciphertext = await subtleCrypto.encrypt(
|
||||
const ciphertext = await globalThis.crypto.subtle.encrypt(
|
||||
{
|
||||
name: "AES-GCM",
|
||||
iv,
|
||||
@@ -208,11 +207,11 @@ export class MSC3903ECDHv2RendezvousChannel<T> implements RendezvousChannel<T> {
|
||||
|
||||
const ciphertextBytes = decodeBase64(ciphertext);
|
||||
|
||||
if (!subtleCrypto) {
|
||||
if (!globalThis.crypto.subtle) {
|
||||
throw new Error("Web Crypto is not available");
|
||||
}
|
||||
|
||||
const plaintext = await subtleCrypto.decrypt(
|
||||
const plaintext = await globalThis.crypto.subtle.decrypt(
|
||||
{
|
||||
name: "AES-GCM",
|
||||
iv: decodeBase64(iv),
|
||||
|
||||
@@ -21,7 +21,6 @@ import { encodeUri } from "../utils";
|
||||
import { IHttpOpts, MatrixError, MatrixHttpApi, Method } from "../http-api";
|
||||
import { IToDeviceEvent } from "../sync-accumulator";
|
||||
import { ServerSideSecretStorage } from "../secret-storage";
|
||||
import { crypto } from "../crypto/crypto";
|
||||
import { decodeBase64, encodeUnpaddedBase64 } from "../base64";
|
||||
import { Logger } from "../logger";
|
||||
|
||||
@@ -155,7 +154,7 @@ export class DehydratedDeviceManager {
|
||||
*/
|
||||
public async resetKey(): Promise<void> {
|
||||
const key = new Uint8Array(32);
|
||||
crypto.getRandomValues(key);
|
||||
globalThis.crypto.getRandomValues(key);
|
||||
await this.secretStorage.store(SECRET_STORAGE_NAME, encodeUnpaddedBase64(key));
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@@ -105,10 +105,8 @@ export class RoomEncryptor {
|
||||
(member.membership == KnownMembership.Invite && this.room.shouldEncryptForInvitedMembers())
|
||||
) {
|
||||
// make sure we are tracking the deviceList for this user
|
||||
logDuration(this.prefixedLogger, "updateTrackedUsers", async () => {
|
||||
this.olmMachine.updateTrackedUsers([new UserId(member.userId)]).catch((e) => {
|
||||
this.prefixedLogger.error("Unable to update tracked users", e);
|
||||
});
|
||||
this.olmMachine.updateTrackedUsers([new UserId(member.userId)]).catch((e) => {
|
||||
this.prefixedLogger.error("Unable to update tracked users", e);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import type { IEventDecryptionResult, IMegolmSessionData } from "../@types/crypt
|
||||
import { KnownMembership } from "../@types/membership";
|
||||
import type { IDeviceLists, IToDeviceEvent } from "../sync-accumulator";
|
||||
import type { IEncryptedEventInfo } from "../crypto/api";
|
||||
import { IContent, MatrixEvent, MatrixEventEvent } from "../models/event";
|
||||
import { MatrixEvent, MatrixEventEvent } from "../models/event";
|
||||
import { Room } from "../models/room";
|
||||
import { RoomMember } from "../models/room-member";
|
||||
import { BackupDecryptor, CryptoBackend, DecryptionError, OnSyncCompletedData } from "../common-crypto/CryptoBackend";
|
||||
@@ -62,7 +62,6 @@ import { CrossSigningIdentity } from "./CrossSigningIdentity";
|
||||
import { secretStorageCanAccessSecrets, secretStorageContainsCrossSigningKeys } from "./secret-storage";
|
||||
import { keyFromPassphrase } from "../crypto/key_passphrase";
|
||||
import { encodeRecoveryKey } from "../crypto/recoverykey";
|
||||
import { crypto } from "../crypto/crypto";
|
||||
import { isVerificationEvent, RustVerificationRequest, verificationMethodIdentifierToMethod } from "./verification";
|
||||
import { EventType, MsgType } from "../@types/event";
|
||||
import { CryptoEvent } from "../crypto";
|
||||
@@ -891,7 +890,7 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
||||
} else {
|
||||
// Using the navigator crypto API to generate the private key
|
||||
const key = new Uint8Array(32);
|
||||
crypto.getRandomValues(key);
|
||||
globalThis.crypto.getRandomValues(key);
|
||||
return {
|
||||
privateKey: key,
|
||||
encodedPrivateKey: encodeRecoveryKey(key),
|
||||
@@ -1315,7 +1314,11 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
||||
// look for interesting to-device messages
|
||||
for (const message of processed) {
|
||||
if (message.type === EventType.KeyVerificationRequest) {
|
||||
this.onIncomingKeyVerificationRequest(message.sender, message.content);
|
||||
const sender = message.sender;
|
||||
const transactionId = message.content.transaction_id;
|
||||
if (transactionId && sender) {
|
||||
this.onIncomingKeyVerificationRequest(sender, transactionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
return processed;
|
||||
@@ -1411,18 +1414,13 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming m.key.verification request event
|
||||
* Handle an incoming m.key.verification.request event, received either in-room or in a to-device message.
|
||||
*
|
||||
* @param sender - the sender of the event
|
||||
* @param content - the content of the event
|
||||
* @param transactionId - the transaction ID for the verification. For to-device messages, this comes from the
|
||||
* content of the message; for in-room messages it is the event ID.
|
||||
*/
|
||||
private onIncomingKeyVerificationRequest(sender: string, content: IContent): void {
|
||||
const transactionId = content.transaction_id;
|
||||
if (!transactionId || !sender) {
|
||||
// not a valid request: ignore
|
||||
return;
|
||||
}
|
||||
|
||||
private onIncomingKeyVerificationRequest(sender: string, transactionId: string): void {
|
||||
const request: RustSdkCryptoJs.VerificationRequest | undefined = this.olmMachine.getVerificationRequest(
|
||||
new RustSdkCryptoJs.UserId(sender),
|
||||
transactionId,
|
||||
@@ -1438,6 +1436,12 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
||||
this._supportedVerificationMethods,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// There are multiple reasons this can happen; probably the most likely is that the event is an
|
||||
// in-room event which is too old.
|
||||
this.logger.info(
|
||||
`Ignoring just-received verification request ${transactionId} which did not start a rust-side verification`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1597,7 +1601,7 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
||||
const processEvent = async (evt: MatrixEvent): Promise<void> => {
|
||||
// Process only verification event
|
||||
if (isVerificationEvent(event)) {
|
||||
await this.onKeyVerificationRequest(evt);
|
||||
await this.onKeyVerificationEvent(evt);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1624,11 +1628,11 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle key verification request.
|
||||
* Handle an in-room key verification event.
|
||||
*
|
||||
* @param event - a key validation request event.
|
||||
*/
|
||||
private async onKeyVerificationRequest(event: MatrixEvent): Promise<void> {
|
||||
private async onKeyVerificationEvent(event: MatrixEvent): Promise<void> {
|
||||
const roomId = event.getRoomId();
|
||||
|
||||
if (!roomId) {
|
||||
@@ -1655,27 +1659,7 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
||||
event.getType() === EventType.RoomMessage &&
|
||||
event.getContent().msgtype === MsgType.KeyVerificationRequest
|
||||
) {
|
||||
const request: RustSdkCryptoJs.VerificationRequest | undefined = this.olmMachine.getVerificationRequest(
|
||||
new RustSdkCryptoJs.UserId(event.getSender()!),
|
||||
event.getId()!,
|
||||
);
|
||||
|
||||
if (!request) {
|
||||
// There are multiple reasons this can happen; probably the most likely is that the event is too old.
|
||||
this.logger.info(
|
||||
`Ignoring just-received verification request ${event.getId()} which did not start a rust-side verification`,
|
||||
);
|
||||
} else {
|
||||
this.emit(
|
||||
CryptoEvent.VerificationRequestReceived,
|
||||
new RustVerificationRequest(
|
||||
this.olmMachine,
|
||||
request,
|
||||
this.outgoingRequestProcessor,
|
||||
this._supportedVerificationMethods,
|
||||
),
|
||||
);
|
||||
}
|
||||
this.onIncomingKeyVerificationRequest(event.getSender()!, event.getId()!);
|
||||
}
|
||||
|
||||
// that may have caused us to queue up outgoing requests, so make sure we send them.
|
||||
|
||||
+3
-2
@@ -401,17 +401,18 @@ export class SyncApi {
|
||||
* Peek into a room. This will result in the room in question being synced so it
|
||||
* is accessible via getRooms(). Live updates for the room will be provided.
|
||||
* @param roomId - The room ID to peek into.
|
||||
* @param limit - The number of timeline events to initially retrieve.
|
||||
* @returns A promise which resolves once the room has been added to the
|
||||
* store.
|
||||
*/
|
||||
public peek(roomId: string): Promise<Room> {
|
||||
public peek(roomId: string, limit: number = 20): Promise<Room> {
|
||||
if (this._peekRoom?.roomId === roomId) {
|
||||
return Promise.resolve(this._peekRoom);
|
||||
}
|
||||
|
||||
const client = this.client;
|
||||
this._peekRoom = this.createRoom(roomId);
|
||||
return this.client.roomInitialSync(roomId, 20).then((response) => {
|
||||
return this.client.roomInitialSync(roomId, limit).then((response) => {
|
||||
if (this._peekRoom?.roomId !== roomId) {
|
||||
throw new Error("Peeking aborted");
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ export type GroupCallEventHandlerMap = {
|
||||
* `MatrixCall.ERR_NO_USER_MEDIA`. `ERR_LOCAL_OFFER_FAILED` is emitted when the local client
|
||||
* fails to create an offer. `ERR_NO_USER_MEDIA` is emitted when the user has denied access
|
||||
* to their audio/video hardware.
|
||||
* @param err - The error raised by MatrixCall.
|
||||
* @param error - The error raised by MatrixCall.
|
||||
* @example
|
||||
* ```
|
||||
* matrixCall.on("error", function(err){
|
||||
|
||||
@@ -1912,6 +1912,16 @@
|
||||
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
|
||||
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
|
||||
|
||||
"@pkgr/core@^0.1.0":
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31"
|
||||
integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==
|
||||
|
||||
"@shikijs/core@1.9.1":
|
||||
version "1.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-1.9.1.tgz#f8c61fb19dbec510fa27f892c441d99b53093e49"
|
||||
integrity sha512-EmUful2MQtY8KgCF1OkBtOuMcvaZEvmdubhW0UHCGXi21O9dRLeADVCj+k6ZS+de7Mz9d2qixOXJ+GLhcK3pXg==
|
||||
|
||||
"@sinclair/typebox@^0.24.1":
|
||||
version "0.24.51"
|
||||
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.51.tgz#645f33fe4e02defe26f2f5c0410e1c094eac7f5f"
|
||||
@@ -2112,9 +2122,9 @@
|
||||
undici-types "~5.26.4"
|
||||
|
||||
"@types/node@18":
|
||||
version "18.19.34"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.34.tgz#c3fae2bbbdb94b4a52fe2d229d0dccce02ef3d27"
|
||||
integrity sha512-eXF4pfBNV5DAMKGbI02NnDtWrQ40hAN558/2vvS4gMpMIxaf6JmD7YjnZbq0Q9TDSSkKBamime8ewRoomHdt4g==
|
||||
version "18.19.39"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.39.tgz#c316340a5b4adca3aee9dcbf05de385978590593"
|
||||
integrity sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==
|
||||
dependencies:
|
||||
undici-types "~5.26.4"
|
||||
|
||||
@@ -2143,10 +2153,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304"
|
||||
integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==
|
||||
|
||||
"@types/uuid@9":
|
||||
version "9.0.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba"
|
||||
integrity sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==
|
||||
"@types/uuid@10":
|
||||
version "10.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-10.0.0.tgz#e9c07fe50da0f53dc24970cca94d619ff03f6f6d"
|
||||
integrity sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==
|
||||
|
||||
"@types/yargs-parser@*":
|
||||
version "21.0.3"
|
||||
@@ -2223,9 +2233,9 @@
|
||||
integrity sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==
|
||||
|
||||
"@typescript-eslint/types@^7.2.0":
|
||||
version "7.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.13.1.tgz#787db283bd0b58751094c90d5b58bbf5e9fc9bd8"
|
||||
integrity sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==
|
||||
version "7.14.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.14.1.tgz#a43a540dbe5df7f2a11269683d777fc50b4350aa"
|
||||
integrity sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==
|
||||
|
||||
"@typescript-eslint/typescript-estree@7.12.0":
|
||||
version "7.12.0"
|
||||
@@ -2401,11 +2411,6 @@ ansi-regex@^6.0.1:
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a"
|
||||
integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==
|
||||
|
||||
ansi-sequence-parser@^1.1.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz#e0aa1cdcbc8f8bb0b5bca625aac41f5f056973cf"
|
||||
integrity sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==
|
||||
|
||||
ansi-styles@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
|
||||
@@ -2660,10 +2665,10 @@ base-x@^3.0.6:
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
base-x@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.0.tgz#d0e3b7753450c73f8ad2389b5c018a4af7b2224a"
|
||||
integrity sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==
|
||||
base-x@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/base-x/-/base-x-5.0.0.tgz#6d835ceae379130e1a4cb846a70ac4746f28ea9b"
|
||||
integrity sha512-sMW3VGSX1QWVFA6l8U62MLKz29rRfpTlYdCqLdpLo1/Yd4zZwSbnUaDfciIAowAqvq7YFnWq9hrhdg1KYgc1lQ==
|
||||
|
||||
binary-extensions@^2.0.0:
|
||||
version "2.3.0"
|
||||
@@ -2702,12 +2707,12 @@ browserslist@^4.22.2, browserslist@^4.23.0:
|
||||
node-releases "^2.0.14"
|
||||
update-browserslist-db "^1.0.16"
|
||||
|
||||
bs58@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/bs58/-/bs58-5.0.0.tgz#865575b4d13c09ea2a84622df6c8cbeb54ffc279"
|
||||
integrity sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==
|
||||
bs58@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/bs58/-/bs58-6.0.0.tgz#a2cda0130558535dd281a2f8697df79caaf425d8"
|
||||
integrity sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==
|
||||
dependencies:
|
||||
base-x "^4.0.0"
|
||||
base-x "^5.0.0"
|
||||
|
||||
bser@2.1.1:
|
||||
version "2.1.1"
|
||||
@@ -3232,6 +3237,11 @@ es-abstract@^1.22.1:
|
||||
unbox-primitive "^1.0.2"
|
||||
which-typed-array "^1.1.13"
|
||||
|
||||
es-module-lexer@^1.5.3:
|
||||
version "1.5.4"
|
||||
resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.4.tgz#a8efec3a3da991e60efa6b633a7cad6ab8d26b78"
|
||||
integrity sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==
|
||||
|
||||
es-set-tostringtag@^2.0.1:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz#11f7cc9f63376930a5f20be4915834f4bc74f9c9"
|
||||
@@ -3358,9 +3368,9 @@ eslint-plugin-jest@^28.0.0:
|
||||
"@typescript-eslint/utils" "^6.0.0 || ^7.0.0"
|
||||
|
||||
eslint-plugin-jsdoc@^48.0.0:
|
||||
version "48.2.12"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.12.tgz#e8411c87e55db3f21a288e04bf7e1fb5fa62dfa9"
|
||||
integrity sha512-sO9sKkJx5ovWoRk9hV0YiNzXQ4Z6j27CqE/po2E3wddZVuy9wvKPSTiIhpxMTrP/qURvKayJIDB2+o9kyCW1Fw==
|
||||
version "48.4.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.4.0.tgz#746a30b8d01a9aa7894e52f8a273a49ca681ef78"
|
||||
integrity sha512-xBUxuAx03cKoEA7y+MYSUdwyN8AJyZHbAJ257sOFXgVgCScm574S4zEYJpBoARwaCu4chhCbvA+gdm+00whlxA==
|
||||
dependencies:
|
||||
"@es-joy/jsdoccomment" "~0.43.1"
|
||||
are-docs-informative "^0.0.2"
|
||||
@@ -3368,8 +3378,10 @@ eslint-plugin-jsdoc@^48.0.0:
|
||||
debug "^4.3.4"
|
||||
escape-string-regexp "^4.0.0"
|
||||
esquery "^1.5.0"
|
||||
parse-imports "^2.1.0"
|
||||
semver "^7.6.2"
|
||||
spdx-expression-parse "^4.0.0"
|
||||
synckit "^0.9.0"
|
||||
|
||||
eslint-plugin-matrix-org@^1.0.0:
|
||||
version "1.2.1"
|
||||
@@ -3384,10 +3396,10 @@ eslint-plugin-tsdoc@^0.3.0:
|
||||
"@microsoft/tsdoc" "0.15.0"
|
||||
"@microsoft/tsdoc-config" "0.17.0"
|
||||
|
||||
eslint-plugin-unicorn@^53.0.0:
|
||||
version "53.0.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-53.0.0.tgz#df3a5c9ecabeb759e6fd867b2d84198466ac8c4d"
|
||||
integrity sha512-kuTcNo9IwwUCfyHGwQFOK/HjJAYzbODHN3wP0PgqbW+jbXqpNWxNVpVhj2tO9SixBwuAdmal8rVcWKBxwFnGuw==
|
||||
eslint-plugin-unicorn@^54.0.0:
|
||||
version "54.0.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-54.0.0.tgz#ce3ea853e8fd7ca2bda2fd6065bf065adb5d8b6d"
|
||||
integrity sha512-XxYLRiYtAWiAjPv6z4JREby1TAE2byBC7wlh0V4vWDCpccOSU1KovWV//jqPXF6bq3WKxqX9rdjoRQ1EhdmNdQ==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.24.5"
|
||||
"@eslint-community/eslint-utils" "^4.4.0"
|
||||
@@ -3668,7 +3680,19 @@ fetch-mock-jest@^1.5.1:
|
||||
dependencies:
|
||||
fetch-mock "^9.11.0"
|
||||
|
||||
fetch-mock@9.11.0, fetch-mock@^9.11.0:
|
||||
fetch-mock@10.0.7:
|
||||
version "10.0.7"
|
||||
resolved "https://registry.yarnpkg.com/fetch-mock/-/fetch-mock-10.0.7.tgz#b274aaebe5b59c641f02d836b579bbe9b063f8db"
|
||||
integrity sha512-TFG42kMRJ6dZpUDeVTdXNjh5O4TchHU/UNk41a050TwKzRr5RJQbtckXDjXiQFHPKgXGUG5l2TY3ZZ2gokiXaQ==
|
||||
dependencies:
|
||||
debug "^4.1.1"
|
||||
glob-to-regexp "^0.4.0"
|
||||
is-subset "^0.1.1"
|
||||
lodash.isequal "^4.5.0"
|
||||
path-to-regexp "^2.2.1"
|
||||
querystring "^0.2.1"
|
||||
|
||||
fetch-mock@^9.11.0:
|
||||
version "9.11.0"
|
||||
resolved "https://registry.yarnpkg.com/fetch-mock/-/fetch-mock-9.11.0.tgz#371c6fb7d45584d2ae4a18ee6824e7ad4b637a3f"
|
||||
integrity sha512-PG1XUv+x7iag5p/iNHD4/jdpxL9FtVSqRMUQhPab4hVDt80T1MH5ehzVrL2IdXO9Q2iBggArFvPqjUbHFuI58Q==
|
||||
@@ -3684,13 +3708,6 @@ fetch-mock@9.11.0, fetch-mock@^9.11.0:
|
||||
querystring "^0.2.0"
|
||||
whatwg-url "^6.5.0"
|
||||
|
||||
file-entry-cache@8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f"
|
||||
integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==
|
||||
dependencies:
|
||||
flat-cache "^4.0.0"
|
||||
|
||||
file-entry-cache@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
|
||||
@@ -3734,24 +3751,11 @@ flat-cache@^3.0.4:
|
||||
flatted "^3.1.0"
|
||||
rimraf "^3.0.2"
|
||||
|
||||
flat-cache@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c"
|
||||
integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==
|
||||
dependencies:
|
||||
flatted "^3.2.9"
|
||||
keyv "^4.5.4"
|
||||
|
||||
flatted@^3.1.0:
|
||||
version "3.2.7"
|
||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
|
||||
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
|
||||
|
||||
flatted@^3.2.9:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a"
|
||||
integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==
|
||||
|
||||
for-each@^0.3.3:
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
|
||||
@@ -4010,7 +4014,7 @@ has@^1.0.3:
|
||||
resolved "https://registry.yarnpkg.com/has/-/has-1.0.4.tgz#2eb2860e000011dae4f1406a86fe80e530fb2ec6"
|
||||
integrity sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==
|
||||
|
||||
hasown@^2.0.0:
|
||||
hasown@^2.0.0, hasown@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
|
||||
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
|
||||
@@ -4186,7 +4190,14 @@ is-core-module@^2.11.0:
|
||||
dependencies:
|
||||
has "^1.0.3"
|
||||
|
||||
is-core-module@^2.13.0, is-core-module@^2.13.1:
|
||||
is-core-module@^2.13.0:
|
||||
version "2.14.0"
|
||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.14.0.tgz#43b8ef9f46a6a08888db67b1ffd4ec9e3dfd59d1"
|
||||
integrity sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==
|
||||
dependencies:
|
||||
hasown "^2.0.2"
|
||||
|
||||
is-core-module@^2.13.1:
|
||||
version "2.13.1"
|
||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384"
|
||||
integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==
|
||||
@@ -4917,11 +4928,6 @@ jsesc@~0.5.0:
|
||||
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
|
||||
integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==
|
||||
|
||||
json-buffer@3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
|
||||
integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
|
||||
|
||||
json-parse-even-better-errors@^2.3.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
|
||||
@@ -4954,39 +4960,26 @@ json5@^2.2.2, json5@^2.2.3:
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
|
||||
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
|
||||
|
||||
jsonc-parser@^3.2.0:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.1.tgz#031904571ccf929d7670ee8c547545081cb37f1a"
|
||||
integrity sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==
|
||||
|
||||
jwt-decode@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-4.0.0.tgz#2270352425fd413785b2faf11f6e755c5151bd4b"
|
||||
integrity sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==
|
||||
|
||||
keyv@^4.5.4:
|
||||
version "4.5.4"
|
||||
resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93"
|
||||
integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==
|
||||
dependencies:
|
||||
json-buffer "3.0.1"
|
||||
|
||||
kleur@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
|
||||
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
|
||||
|
||||
knip@^5.0.0:
|
||||
version "5.21.2"
|
||||
resolved "https://registry.yarnpkg.com/knip/-/knip-5.21.2.tgz#0b25001ee645882784c652cd14c3a3e7ff50ec37"
|
||||
integrity sha512-V8bzHWjQyhkN0cxajxyHqaD8CPOkNtSwo4+Zue3z//4fbWO79xXLVp61fuaaTcT9O7I7E2ZjuHENtRkBrjSzCg==
|
||||
version "5.23.0"
|
||||
resolved "https://registry.yarnpkg.com/knip/-/knip-5.23.0.tgz#655bec539375571baa8cebe059d64ae9ceb4fd41"
|
||||
integrity sha512-kHXcxmbbpTa+ZPx29KfAbBGP6TK81wXjvHyUPTCbGNFwOVnVUminesaO/of+9KleCzw3pUPiK/k4UsEu+aFK4Q==
|
||||
dependencies:
|
||||
"@ericcornelissen/bash-parser" "0.5.3"
|
||||
"@nodelib/fs.walk" "2.0.0"
|
||||
"@snyk/github-codeowners" "1.1.0"
|
||||
easy-table "1.2.0"
|
||||
fast-glob "^3.3.2"
|
||||
file-entry-cache "8.0.0"
|
||||
jiti "^1.21.0"
|
||||
js-yaml "^4.1.0"
|
||||
minimist "^1.2.8"
|
||||
@@ -5024,6 +5017,13 @@ lines-and-columns@^1.1.6:
|
||||
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
|
||||
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
|
||||
|
||||
linkify-it@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-5.0.0.tgz#9ef238bfa6dc70bd8e7f9572b52d369af569b421"
|
||||
integrity sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==
|
||||
dependencies:
|
||||
uc.micro "^2.0.0"
|
||||
|
||||
lint-staged@^15.0.2:
|
||||
version "15.2.7"
|
||||
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-15.2.7.tgz#97867e29ed632820c0fb90be06cd9ed384025649"
|
||||
@@ -5170,10 +5170,17 @@ map-obj@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9"
|
||||
integrity sha512-TzQSV2DiMYgoF5RycneKVUzIa9bQsj/B3tTgsE3dOGqlzHnGIDaC7XBE7grnA+8kZPnfqSGFe95VHc2oc0VFUQ==
|
||||
|
||||
marked@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3"
|
||||
integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==
|
||||
markdown-it@^14.1.0:
|
||||
version "14.1.0"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-14.1.0.tgz#3c3c5992883c633db4714ccb4d7b5935d98b7d45"
|
||||
integrity sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
entities "^4.4.0"
|
||||
linkify-it "^5.0.0"
|
||||
mdurl "^2.0.0"
|
||||
punycode.js "^2.3.1"
|
||||
uc.micro "^2.1.0"
|
||||
|
||||
matrix-events-sdk@0.0.1:
|
||||
version "0.0.1"
|
||||
@@ -5195,6 +5202,11 @@ matrix-widget-api@^1.6.0:
|
||||
"@types/events" "^3.0.0"
|
||||
events "^3.2.0"
|
||||
|
||||
mdurl@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0"
|
||||
integrity sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==
|
||||
|
||||
merge-stream@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
|
||||
@@ -5247,7 +5259,7 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimatch@^9.0.1, minimatch@^9.0.3, minimatch@^9.0.4:
|
||||
minimatch@^9.0.1, minimatch@^9.0.4:
|
||||
version "9.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51"
|
||||
integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==
|
||||
@@ -5488,6 +5500,14 @@ parent-module@^1.0.0:
|
||||
dependencies:
|
||||
callsites "^3.0.0"
|
||||
|
||||
parse-imports@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/parse-imports/-/parse-imports-2.1.0.tgz#22a152f4503da34e8fb89c902383895f59e93d2d"
|
||||
integrity sha512-JQWgmK2o4w8leUkZeZPatWdAny6vXGU/3siIUvMF6J2rDCud9aTt8h/px9oZJ6U3EcfhngBJ635uPFI0q0VAeA==
|
||||
dependencies:
|
||||
es-module-lexer "^1.5.3"
|
||||
slashes "^3.0.12"
|
||||
|
||||
parse-json@^5.0.0, parse-json@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
|
||||
@@ -5644,6 +5664,11 @@ psl@^1.1.33:
|
||||
resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7"
|
||||
integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==
|
||||
|
||||
punycode.js@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7"
|
||||
integrity sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==
|
||||
|
||||
punycode@^2.1.0, punycode@^2.1.1:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
|
||||
@@ -5666,7 +5691,7 @@ pvutils@^1.1.3:
|
||||
resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.3.tgz#f35fc1d27e7cd3dfbd39c0826d173e806a03f5a3"
|
||||
integrity sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==
|
||||
|
||||
querystring@^0.2.0:
|
||||
querystring@^0.2.0, querystring@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.1.tgz#40d77615bb09d16902a85c3e38aa8b5ed761c2dd"
|
||||
integrity sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==
|
||||
@@ -5991,15 +6016,12 @@ shell-quote-word@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/shell-quote-word/-/shell-quote-word-1.0.1.tgz#e2bdfd22d599fd68886491677e38f560f9d469c9"
|
||||
integrity sha512-lT297f1WLAdq0A4O+AknIFRP6kkiI3s8C913eJ0XqBxJbZPGWUNkRQk2u8zk4bEAjUJ5i+fSLwB6z1HzeT+DEg==
|
||||
|
||||
shiki@^0.14.7:
|
||||
version "0.14.7"
|
||||
resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.14.7.tgz#c3c9e1853e9737845f1d2ef81b31bcfb07056d4e"
|
||||
integrity sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==
|
||||
shiki@^1.9.0:
|
||||
version "1.9.1"
|
||||
resolved "https://registry.yarnpkg.com/shiki/-/shiki-1.9.1.tgz#9d9f553b06e70a9e71b5457622d6f4a5aaf1db27"
|
||||
integrity sha512-8PDkgb5ja3nfujTjvC4VytL6wGOGCtFAClUb2r3QROevYXxcq+/shVJK5s6gy0HZnjaJgFxd6BpPqpRfqne5rA==
|
||||
dependencies:
|
||||
ansi-sequence-parser "^1.1.0"
|
||||
jsonc-parser "^3.2.0"
|
||||
vscode-oniguruma "^1.7.0"
|
||||
vscode-textmate "^8.0.0"
|
||||
"@shikijs/core" "1.9.1"
|
||||
|
||||
side-channel@^1.0.4:
|
||||
version "1.0.4"
|
||||
@@ -6035,6 +6057,11 @@ slash@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
|
||||
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
|
||||
|
||||
slashes@^3.0.12:
|
||||
version "3.0.12"
|
||||
resolved "https://registry.yarnpkg.com/slashes/-/slashes-3.0.12.tgz#3d664c877ad542dc1509eaf2c50f38d483a6435a"
|
||||
integrity sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==
|
||||
|
||||
slice-ansi@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a"
|
||||
@@ -6052,9 +6079,9 @@ slice-ansi@^7.0.0:
|
||||
is-fullwidth-code-point "^5.0.0"
|
||||
|
||||
smol-toml@^1.1.4:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/smol-toml/-/smol-toml-1.2.1.tgz#6216334548763d4aac76cafff19f8914937ee13a"
|
||||
integrity sha512-OtZKrVrGIT+m++lxyF0z5n68nkwdgZotPhy89bfA4T7nSWe0xeQtfbjM1z5VLTilJdWXH46g8i0oAcpQNkzZTg==
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/smol-toml/-/smol-toml-1.2.2.tgz#e0eb86dd8dab307b5345b0daff32a79a39f19175"
|
||||
integrity sha512-fVEjX2ybKdJKzFL46VshQbj9PuA4IUKivalgp48/3zwS9vXzyykzQ6AX92UxHSvWJagziMRLeHMgEzoGO7A8hQ==
|
||||
|
||||
source-map-support@0.5.13:
|
||||
version "0.5.13"
|
||||
@@ -6290,6 +6317,14 @@ symbol-tree@^3.2.4:
|
||||
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
|
||||
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
|
||||
|
||||
synckit@^0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.9.0.tgz#5b33b458b3775e4466a5b377fba69c63572ae449"
|
||||
integrity sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==
|
||||
dependencies:
|
||||
"@pkgr/core" "^0.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
tapable@^2.2.0:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
|
||||
@@ -6417,11 +6452,16 @@ tsconfig-paths@^4.2.0:
|
||||
minimist "^1.2.6"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
tslib@^2.0.0, tslib@^2.4.0, tslib@^2.6.1, tslib@^2.6.2:
|
||||
tslib@^2.0.0, tslib@^2.4.0, tslib@^2.6.1:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
|
||||
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
|
||||
|
||||
tslib@^2.6.2:
|
||||
version "2.6.3"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0"
|
||||
integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==
|
||||
|
||||
type-check@^0.4.0, type-check@~0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
|
||||
@@ -6494,34 +6534,40 @@ typed-array-length@^1.0.4:
|
||||
is-typed-array "^1.1.9"
|
||||
|
||||
typedoc-plugin-coverage@^3.0.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/typedoc-plugin-coverage/-/typedoc-plugin-coverage-3.2.0.tgz#c3d09fd5f42fb8fa3de0ed72344c406afe7e994b"
|
||||
integrity sha512-jY6bEl/zNezRTAg0V4+FkJAtPlzSszK3QzcXSyGYcKjzzT8C6qw0xdh2KIJkxAtzYtgxT/4idiAYqZ1WRAieTA==
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/typedoc-plugin-coverage/-/typedoc-plugin-coverage-3.3.0.tgz#2b00830f32129e7433708f6893729d6770b96276"
|
||||
integrity sha512-wpywQ95tqGSD6IbYUPMXSKiwnSWboSKdx2y9X6SJQKzQvBqZoz5iiUyDJFixtW8v7+xmrqXFR/B6Wy37FNhVqA==
|
||||
|
||||
typedoc-plugin-mdn-links@^3.0.3:
|
||||
version "3.1.30"
|
||||
resolved "https://registry.yarnpkg.com/typedoc-plugin-mdn-links/-/typedoc-plugin-mdn-links-3.1.30.tgz#bea289518cb393b07ee65fabc8ced393810dce9a"
|
||||
integrity sha512-aB3UqyRGdxYziOHKzE7AQPh+9xpqqHHrp23F+T6yshHeuSiauCL+zzgTRhi4Ad1x30/7rTkCtyQ5dfO/+1FDKA==
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/typedoc-plugin-mdn-links/-/typedoc-plugin-mdn-links-3.2.1.tgz#7388fb62b034d3d1df5bb2c8296683139d4a19f2"
|
||||
integrity sha512-l76VJKKhOxCYXnb16aV6nAQG5JCsuStqviNFmgzhS9dW73nqm3/1MO9497+0KlDTOPO3o+R2uVXq87d2cDy/hg==
|
||||
|
||||
typedoc-plugin-missing-exports@^2.0.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/typedoc-plugin-missing-exports/-/typedoc-plugin-missing-exports-2.3.0.tgz#ae0858bf383a08345cc09a99d428234cf6b85ecf"
|
||||
integrity sha512-iI9ITNNLlbsLCBBeYDyu0Qqp3GN/9AGyWNKg8bctRXuZEPT7G1L+0+MNWG9MsHcf/BFmNbXL0nQ8mC/tXRicog==
|
||||
typedoc-plugin-missing-exports@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/typedoc-plugin-missing-exports/-/typedoc-plugin-missing-exports-3.0.0.tgz#47ab7cf9b91967f50550b7f07549ed1b743f3726"
|
||||
integrity sha512-R7D8fYrK34mBFZSlF1EqJxfqiUSlQSmyrCiQgTQD52nNm6+kUtqwiaqaNkuJ2rA2wBgWFecUA8JzHT7x2r7ePg==
|
||||
|
||||
typedoc@^0.25.10:
|
||||
version "0.25.13"
|
||||
resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.25.13.tgz#9a98819e3b2d155a6d78589b46fa4c03768f0922"
|
||||
integrity sha512-pQqiwiJ+Z4pigfOnnysObszLiU3mVLWAExSPf+Mu06G/qsc3wzbuM56SZQvONhHLncLUhYzOVkjFFpFfL5AzhQ==
|
||||
typedoc@^0.26.0:
|
||||
version "0.26.2"
|
||||
resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.26.2.tgz#f9538e6e9a081fda1f2416d0ee0d7dfab480cbec"
|
||||
integrity sha512-q/t+M+PZqhN9gPWLBZ3CCvP+KT8O1tyYkSzEYbcQ6mo89avdIrMlBEl3vfo5BgSzwC6Lbmq0W64E8RkY+eVsLA==
|
||||
dependencies:
|
||||
lunr "^2.3.9"
|
||||
marked "^4.3.0"
|
||||
minimatch "^9.0.3"
|
||||
shiki "^0.14.7"
|
||||
markdown-it "^14.1.0"
|
||||
minimatch "^9.0.4"
|
||||
shiki "^1.9.0"
|
||||
yaml "^2.4.5"
|
||||
|
||||
typescript@^5.3.3:
|
||||
version "5.4.5"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611"
|
||||
integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==
|
||||
version "5.5.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.2.tgz#c26f023cb0054e657ce04f72583ea2d85f8d0507"
|
||||
integrity sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==
|
||||
|
||||
uc.micro@^2.0.0, uc.micro@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee"
|
||||
integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==
|
||||
|
||||
unbox-primitive@^1.0.2:
|
||||
version "1.0.2"
|
||||
@@ -6638,16 +6684,6 @@ vlq@^0.2.1:
|
||||
resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26"
|
||||
integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==
|
||||
|
||||
vscode-oniguruma@^1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz#439bfad8fe71abd7798338d1cd3dc53a8beea94b"
|
||||
integrity sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==
|
||||
|
||||
vscode-textmate@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-8.0.0.tgz#2c7a3b1163ef0441097e0b5d6389cd5504b59e5d"
|
||||
integrity sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==
|
||||
|
||||
w3c-xmlserializer@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz#aebdc84920d806222936e3cdce408e32488a3073"
|
||||
@@ -6845,7 +6881,7 @@ yallist@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||
|
||||
yaml@~2.4.2:
|
||||
yaml@^2.4.5, yaml@~2.4.2:
|
||||
version "2.4.5"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.5.tgz#60630b206dd6d84df97003d33fc1ddf6296cca5e"
|
||||
integrity sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==
|
||||
|
||||
Reference in New Issue
Block a user