Compare commits
1 Commits
t3chguy/be
...
t3chguy/cf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37f7885d13 |
@@ -1,33 +0,0 @@
|
||||
name: Upload release assets
|
||||
description: Uploads assets to an existing release and optionally signs them
|
||||
inputs:
|
||||
tag:
|
||||
description: GitHub release tag to fetch assets from.
|
||||
required: true
|
||||
out-file-path:
|
||||
description: Path to where the webapp should be extracted to.
|
||||
required: true
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Download current version for its old bundles
|
||||
id: current_download
|
||||
uses: robinraju/release-downloader@a96f54c1b5f5e09e47d9504526e96febd949d4c2 # v1
|
||||
with:
|
||||
tag: steps.current_version.outputs.version
|
||||
fileName: element-*.tar.gz*
|
||||
out-file-path: ${{ runner.temp }}/download-verify-element-tarball
|
||||
|
||||
- name: Verify tarball
|
||||
run: gpg --verify element-*.tar.gz.asc element-*.tar.gz
|
||||
working-directory: ${{ runner.temp }}/download-verify-element-tarball
|
||||
|
||||
- name: Extract tarball
|
||||
run: tar xvzf element-*.tar.gz -C webapp --strip-components=1
|
||||
working-directory: ${{ runner.temp }}/download-verify-element-tarball
|
||||
|
||||
- name: Move webapp to out-file-path
|
||||
run: mv ${{ runner.temp }}/download-verify-element-tarball/webapp ${{ inputs.out-file-path }}
|
||||
|
||||
- name: Clean up temp directory
|
||||
run: rm -R ${{ runner.temp }}/download-verify-element-tarball
|
||||
88
.github/workflows/deploy.yml
vendored
88
.github/workflows/deploy.yml
vendored
@@ -1,88 +0,0 @@
|
||||
# Manual deploy workflow for deploying to app.element.io & staging.element.io
|
||||
# Runs automatically for staging.element.io when an RC or Release is published
|
||||
# Note: Does *NOT* run automatically for app.element.io so that it gets tested on staging.element.io beforehand
|
||||
name: Build and Deploy ${{ inputs.site || 'staging.element.io' }}
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
site:
|
||||
description: Which site to deploy to
|
||||
required: true
|
||||
default: staging.element.io
|
||||
type: choice
|
||||
options:
|
||||
- staging.element.io
|
||||
- app.element.io
|
||||
concurrency: ${{ inputs.site || 'staging.element.io' }}
|
||||
permissions: {}
|
||||
jobs:
|
||||
deploy:
|
||||
name: "Deploy to Cloudflare Pages"
|
||||
runs-on: ubuntu-24.04
|
||||
environment: ${{ inputs.site || 'staging.element.io' }}
|
||||
permissions:
|
||||
checks: read
|
||||
deployments: write
|
||||
env:
|
||||
SITE: ${{ inputs.site || 'staging.element.io' }}
|
||||
steps:
|
||||
- name: Load GPG key
|
||||
run: |
|
||||
curl https://packages.element.io/element-release-key.gpg | gpg --import
|
||||
gpg -k "$GPG_FINGERPRINT"
|
||||
env:
|
||||
GPG_FINGERPRINT: ${{ secrets.GPG_FINGERPRINT }}
|
||||
|
||||
- name: Check current version on deployment
|
||||
id: current_version
|
||||
run: |
|
||||
echo "version=$(curl -s https://$SITE/version)" >> $GITHUB_OUTPUT
|
||||
|
||||
# The current version bundle melding dance is skipped if the version we're deploying is the same
|
||||
# as then we're just doing a re-deploy of the same version with potentially different configs.
|
||||
- name: Download current version for its old bundles
|
||||
id: current_download
|
||||
if: steps.current_version.outputs.version != github.ref_name
|
||||
uses: element-hq/element-web/.github/actions/download-verify-element-tarball@${{ github.ref_name }}
|
||||
with:
|
||||
tag: steps.current_version.outputs.version
|
||||
out-file-path: current_version
|
||||
|
||||
- name: Download target version
|
||||
uses: element-hq/element-web/.github/actions/download-verify-element-tarball@${{ github.ref_name }}
|
||||
with:
|
||||
tag: ${{ github.ref_name }}
|
||||
out-file-path: _deploy
|
||||
|
||||
- name: Merge current bundles into target
|
||||
if: steps.current_download.outcome == 'success'
|
||||
run: cp -vnpr current_version/bundles/* _deploy/bundles/
|
||||
|
||||
- name: Copy config
|
||||
run: cp element.io/app/config.json _deploy/config.json
|
||||
|
||||
- name: Populate 404.html
|
||||
run: echo "404 Not Found" > _deploy/404.html
|
||||
|
||||
- name: Populate _headers
|
||||
run: cp .github/cfp_headers _deploy/_headers
|
||||
|
||||
- name: Wait for other steps to succeed
|
||||
uses: t3chguy/wait-on-check-action@18541021811b56544d90e0f073401c2b99e249d6 # fork
|
||||
with:
|
||||
ref: ${{ github.sha }}
|
||||
running-workflow-name: "Build and Deploy ${{ env.SITE }}"
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
wait-interval: 10
|
||||
check-regexp: ^((?!SonarCloud|SonarQube|issue|board|label|Release|prepare|GitHub Pages).)*$
|
||||
|
||||
- name: Deploy to Cloudflare Pages
|
||||
uses: cloudflare/pages-action@f0a1cd58cd66095dee69bfa18fa5efd1dde93bca # v1
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_PAGES_TOKEN }}
|
||||
accountId: ${{ secrets.CF_PAGES_ACCOUNT_ID }}
|
||||
projectName: ${{ env.SITE == 'staging.element.io' && 'element-web-staging' || 'element-web' }}
|
||||
directory: _deploy
|
||||
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -19,7 +19,6 @@ jobs:
|
||||
environment: develop
|
||||
permissions:
|
||||
checks: read
|
||||
pages: write
|
||||
deployments: write
|
||||
env:
|
||||
R2_BUCKET: "element-web-develop"
|
||||
@@ -119,13 +118,9 @@ jobs:
|
||||
|
||||
- name: Deploy to Cloudflare Pages
|
||||
id: cfp
|
||||
uses: cloudflare/pages-action@f0a1cd58cd66095dee69bfa18fa5efd1dde93bca # v1
|
||||
uses: cloudflare/wrangler-action@b19342b08c7c7f6855c1adfbf6f626acd085896d # v3
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_PAGES_TOKEN }}
|
||||
accountId: ${{ secrets.CF_PAGES_ACCOUNT_ID }}
|
||||
projectName: element-web-develop
|
||||
directory: _deploy
|
||||
command: pages deploy _deploy --project-name=element-web-develop
|
||||
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- run: |
|
||||
echo "Deployed to ${{ steps.cfp.outputs.url }}" >> $GITHUB_STEP_SUMMARY
|
||||
2
.github/workflows/docs.yml
vendored
2
.github/workflows/docs.yml
vendored
@@ -43,7 +43,7 @@ jobs:
|
||||
working-directory: element-web
|
||||
run: |
|
||||
yarn install --frozen-lockfile
|
||||
tsx ./scripts/gen-workflow-mermaid.ts ../element-desktop ../element-web ../matrix-js-sdk > docs/automations.md
|
||||
yarn ts-node ./scripts/gen-workflow-mermaid.ts ../element-desktop ../element-web ../matrix-js-sdk > docs/automations.md
|
||||
echo "- [Automations](automations.md)" >> docs/SUMMARY.md
|
||||
|
||||
- name: Setup mdBook
|
||||
|
||||
57
.github/workflows/end-to-end-tests-netlify.yaml
vendored
57
.github/workflows/end-to-end-tests-netlify.yaml
vendored
@@ -23,7 +23,6 @@ jobs:
|
||||
statuses: write
|
||||
deployments: write
|
||||
actions: read
|
||||
contents: write
|
||||
steps:
|
||||
- name: Download HTML report
|
||||
uses: actions/download-artifact@v4
|
||||
@@ -45,59 +44,3 @@ jobs:
|
||||
desc: Playwright Report
|
||||
deployment_env: EndToEndTests
|
||||
prefix: "e2e-"
|
||||
|
||||
benchmark:
|
||||
if: github.event.workflow_run.conclusion != 'cancelled'
|
||||
name: Benchmarks
|
||||
runs-on: ubuntu-24.04
|
||||
environment: Netlify
|
||||
permissions:
|
||||
statuses: write
|
||||
deployments: write
|
||||
actions: read
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: "yarn"
|
||||
node-version-file: package.json
|
||||
|
||||
- name: Install Deps
|
||||
run: "yarn install --frozen-lockfile"
|
||||
|
||||
- name: Download webapp
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: webapp
|
||||
path: webapp
|
||||
|
||||
- name: Generate benchmark result
|
||||
run: ./scripts/benchmark-bundle.ts > benchmarks.json
|
||||
|
||||
- name: Evaluate benchmark result
|
||||
uses: benchmark-action/github-action-benchmark@d48d326b4ca9ba73ca0cd0d59f108f9e02a381c7 # v1
|
||||
with:
|
||||
tool: "customSmallerIsBetter"
|
||||
output-file-path: "benchmarks.json"
|
||||
gh-pages-branch: benchmarks
|
||||
auto-push: false
|
||||
|
||||
- name: Push latest develop results
|
||||
if: github.event.workflow_run.head_branch == 'develop' && github.event.workflow_run.head_repository.owner.login == 'element-hq'
|
||||
run: git push origin benchmarks
|
||||
|
||||
- name: 📤 Deploy to Netlify
|
||||
uses: matrix-org/netlify-pr-preview@v3
|
||||
if: github.event.workflow_run.head_branch == 'develop' && github.event.workflow_run.head_repository.owner.login == 'element-hq'
|
||||
with:
|
||||
path: .
|
||||
owner: ${{ github.event.workflow_run.head_repository.owner.login }}
|
||||
branch: ${{ github.event.workflow_run.head_branch }}
|
||||
revision: ${{ github.event.workflow_run.head_sha }}
|
||||
token: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||
site_id: ${{ vars.NETLIFY_SITE_ID }}
|
||||
desc: Bundle Size Benchmark
|
||||
deployment_env: BundleSize
|
||||
prefix: "benchmark-"
|
||||
|
||||
1
.github/workflows/release.yml
vendored
1
.github/workflows/release.yml
vendored
@@ -18,7 +18,6 @@ jobs:
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: read
|
||||
secrets:
|
||||
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||
|
||||
6
__mocks__/FontManager.js
Normal file
6
__mocks__/FontManager.js
Normal file
@@ -0,0 +1,6 @@
|
||||
// Stub out FontManager for tests as it doesn't validate anything we don't already know given
|
||||
// our fixed test environment and it requires the installation of node-canvas.
|
||||
|
||||
module.exports = {
|
||||
fixupColorFonts: () => Promise.resolve(),
|
||||
};
|
||||
@@ -32,6 +32,7 @@ const config: Config = {
|
||||
"decoderWorker\\.min\\.wasm": "<rootDir>/__mocks__/empty.js",
|
||||
"waveWorker\\.min\\.js": "<rootDir>/__mocks__/empty.js",
|
||||
"context-filter-polyfill": "<rootDir>/__mocks__/empty.js",
|
||||
"FontManager.ts": "<rootDir>/__mocks__/FontManager.js",
|
||||
"workers/(.+)Factory": "<rootDir>/__mocks__/workerFactoryMock.js",
|
||||
"^!!raw-loader!.*": "jest-raw-loader",
|
||||
"recorderWorkletFactory": "<rootDir>/__mocks__/empty.js",
|
||||
|
||||
10
package.json
10
package.json
@@ -39,16 +39,16 @@
|
||||
"clean": "rimraf lib webapp",
|
||||
"build": "yarn clean && yarn build:genfiles && yarn build:bundle",
|
||||
"build-stats": "yarn clean && yarn build:genfiles && yarn build:bundle-stats",
|
||||
"build:res": "tsx scripts/copy-res.ts",
|
||||
"build:res": "ts-node scripts/copy-res.ts",
|
||||
"build:genfiles": "yarn build:res && yarn build:module_system",
|
||||
"build:modernizr": "modernizr -c .modernizr.json -d src/vector/modernizr.js",
|
||||
"build:bundle": "webpack --progress --mode production",
|
||||
"build:bundle-stats": "webpack --progress --mode production --json > webpack-stats.json",
|
||||
"build:module_system": "tsx --project ./tsconfig.module_system.json module_system/scripts/install.ts",
|
||||
"build:module_system": "ts-node --project ./tsconfig.module_system.json module_system/scripts/install.ts",
|
||||
"dist": "./scripts/package.sh",
|
||||
"start": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n modules,res \"yarn build:module_system\" \"yarn build:res\" && concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n res,element-js \"yarn start:res\" \"yarn start:js\"",
|
||||
"start:https": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n res,element-js \"yarn start:res\" \"yarn start:js --server-type https\"",
|
||||
"start:res": "tsx scripts/copy-res.ts -w",
|
||||
"start:res": "ts-node scripts/copy-res.ts -w",
|
||||
"start:js": "webpack serve --output-path webapp --output-filename=bundles/_dev_/[name].js --output-chunk-filename=bundles/_dev_/[name].js --mode development",
|
||||
"lint": "yarn lint:types && yarn lint:js && yarn lint:style && yarn lint:workflows",
|
||||
"lint:js": "eslint --max-warnings 0 src test playwright module_system && prettier --check .",
|
||||
@@ -66,7 +66,7 @@
|
||||
"test:playwright:screenshots:build": "docker build playwright -t element-web-playwright",
|
||||
"test:playwright:screenshots:run": "docker run --rm --network host -e BASE_URL -e CI -v $(pwd):/work/ -v $(node -e 'console.log(require(`path`).dirname(require.resolve(`matrix-js-sdk/package.json`)))'):/work/node_modules/matrix-js-sdk -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/:/tmp/ -it element-web-playwright",
|
||||
"coverage": "yarn test --coverage",
|
||||
"analyse:unused-exports": "tsx ./scripts/analyse_unused_exports.ts",
|
||||
"analyse:unused-exports": "ts-node ./scripts/analyse_unused_exports.ts",
|
||||
"analyse:webpack-bundles": "webpack-bundle-analyzer webpack-stats.json webapp",
|
||||
"update:jitsi": "curl -s https://meet.element.io/libs/external_api.min.js > ./res/jitsi_external_api.min.js"
|
||||
},
|
||||
@@ -278,8 +278,8 @@
|
||||
"stylelint-scss": "^6.0.0",
|
||||
"stylelint-value-no-unknown-custom-properties": "^6.0.1",
|
||||
"terser-webpack-plugin": "^5.3.9",
|
||||
"ts-node": "^10.9.1",
|
||||
"ts-prune": "^0.10.3",
|
||||
"tsx": "^4.19.2",
|
||||
"typescript": "5.6.3",
|
||||
"util": "^0.12.5",
|
||||
"web-streams-polyfill": "^4.0.0",
|
||||
|
||||
@@ -20,7 +20,7 @@ import { randB64Bytes } from "../../utils/rand";
|
||||
// Docker tag to use for synapse docker image.
|
||||
// We target a specific digest as every now and then a Synapse update will break our CI.
|
||||
// This digest is updated by the playwright-image-updates.yaml workflow periodically.
|
||||
const DOCKER_TAG = "develop@sha256:e163b15bf4905e4067dece856cca00e6ac8d1d655f4f1307978eee256b3ea775";
|
||||
const DOCKER_TAG = "develop@sha256:127c68d4468019ce363c8b2fd7a42a3ef50710eb3aaf288a2295dd4623ce9f54";
|
||||
|
||||
async function cfgDirFromTemplate(opts: StartHomeserverOpts): Promise<Omit<HomeserverConfig, "dockerUrl">> {
|
||||
const templateDir = path.join(__dirname, "templates", opts.template);
|
||||
|
||||
BIN
res/fonts/Twemoji_Mozilla/TwemojiMozilla-sbix.woff2
Normal file
BIN
res/fonts/Twemoji_Mozilla/TwemojiMozilla-sbix.woff2
Normal file
Binary file not shown.
@@ -143,21 +143,3 @@ $inter-unicode-range: U+0000-20e2, U+20e4-23ce, U+23d0-24c1, U+24c3-259f, U+25c2
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC,
|
||||
U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* Twemoji COLR */
|
||||
@font-face {
|
||||
font-family: "Twemoji";
|
||||
font-weight: 400;
|
||||
src: url("$(res)/fonts/Twemoji_Mozilla/TwemojiMozilla-colr.woff2") format("woff2");
|
||||
}
|
||||
/* For at least Chrome on Windows 10, we have to explictly add extra weights for the emoji to appear in bold messages, etc. */
|
||||
@font-face {
|
||||
font-family: "Twemoji";
|
||||
font-weight: 600;
|
||||
src: url("$(res)/fonts/Twemoji_Mozilla/TwemojiMozilla-colr.woff2") format("woff2");
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Twemoji";
|
||||
font-weight: 700;
|
||||
src: url("$(res)/fonts/Twemoji_Mozilla/TwemojiMozilla-colr.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
#!/usr/bin/env -S yarn --silent tsx
|
||||
|
||||
import { glob } from "glob";
|
||||
import path from "node:path";
|
||||
import { stat } from "node:fs/promises";
|
||||
|
||||
async function main() {
|
||||
const cwd = path.join(__dirname, "..", "webapp");
|
||||
const jsfiles = await glob("**/*.js", { cwd });
|
||||
const sizes = await Promise.all(
|
||||
jsfiles.map(async (file) => {
|
||||
const data = await stat(path.join(cwd, file));
|
||||
return data.size;
|
||||
}),
|
||||
);
|
||||
|
||||
const totalBytes = sizes.reduce((acc, size) => acc + size, 0);
|
||||
|
||||
console.log([
|
||||
{
|
||||
name: "Total JS bundle size",
|
||||
unit: "Megabytes",
|
||||
value: totalBytes / 1024 / 1024,
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env -S yarn --silent tsx
|
||||
#!/usr/bin/env -S npx ts-node
|
||||
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
7
src/@types/matrix-js-sdk.d.ts
vendored
7
src/@types/matrix-js-sdk.d.ts
vendored
@@ -22,13 +22,6 @@ declare module "matrix-js-sdk/src/types" {
|
||||
[BLURHASH_FIELD]?: string;
|
||||
}
|
||||
|
||||
export interface ImageInfo {
|
||||
/**
|
||||
* @see https://github.com/matrix-org/matrix-spec-proposals/pull/4230
|
||||
*/
|
||||
"org.matrix.msc4230.is_animated"?: boolean;
|
||||
}
|
||||
|
||||
export interface StateEvents {
|
||||
// Jitsi-backed video room state events
|
||||
[JitsiCallMemberEventType]: JitsiCallMemberContent;
|
||||
|
||||
@@ -56,7 +56,6 @@ import { createThumbnail } from "./utils/image-media";
|
||||
import { attachMentions, attachRelation } from "./components/views/rooms/SendMessageComposer";
|
||||
import { doMaybeLocalRoomAction } from "./utils/local-room";
|
||||
import { SdkContextClass } from "./contexts/SDKContext";
|
||||
import { blobIsAnimated } from "./utils/Image.ts";
|
||||
|
||||
// scraped out of a macOS hidpi (5660ppm) screenshot png
|
||||
// 5669 px (x-axis) , 5669 px (y-axis) , per metre
|
||||
@@ -151,20 +150,15 @@ async function infoForImageFile(matrixClient: MatrixClient, roomId: string, imag
|
||||
thumbnailType = "image/jpeg";
|
||||
}
|
||||
|
||||
// We don't await this immediately so it can happen in the background
|
||||
const isAnimatedPromise = blobIsAnimated(imageFile.type, imageFile);
|
||||
|
||||
const imageElement = await loadImageElement(imageFile);
|
||||
|
||||
const result = await createThumbnail(imageElement.img, imageElement.width, imageElement.height, thumbnailType);
|
||||
const imageInfo = result.info;
|
||||
|
||||
imageInfo["org.matrix.msc4230.is_animated"] = await isAnimatedPromise;
|
||||
|
||||
// For lesser supported image types, always include the thumbnail even if it is larger
|
||||
if (!ALWAYS_INCLUDE_THUMBNAIL.includes(imageFile.type)) {
|
||||
// we do all sizing checks here because we still rely on thumbnail generation for making a blurhash from.
|
||||
const sizeDifference = imageFile.size - imageInfo.thumbnail_info!.size!;
|
||||
const sizeDifference = imageFile.size - imageInfo.thumbnail_info!.size;
|
||||
if (
|
||||
// image is small enough already
|
||||
imageFile.size <= IMAGE_SIZE_THRESHOLD_THUMBNAIL ||
|
||||
|
||||
@@ -230,15 +230,12 @@ export default class DeviceListener {
|
||||
private async getKeyBackupInfo(): Promise<KeyBackupInfo | null> {
|
||||
if (!this.client) return null;
|
||||
const now = new Date().getTime();
|
||||
const crypto = this.client.getCrypto();
|
||||
if (!crypto) return null;
|
||||
|
||||
if (
|
||||
!this.keyBackupInfo ||
|
||||
!this.keyBackupFetchedAt ||
|
||||
this.keyBackupFetchedAt < now - KEY_BACKUP_POLL_INTERVAL
|
||||
) {
|
||||
this.keyBackupInfo = await crypto.getKeyBackupInfo();
|
||||
this.keyBackupInfo = await this.client.getKeyBackupVersion();
|
||||
this.keyBackupFetchedAt = now;
|
||||
}
|
||||
return this.keyBackupInfo;
|
||||
|
||||
@@ -279,7 +279,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent<IProp
|
||||
if (!forceReset) {
|
||||
try {
|
||||
this.setState({ phase: Phase.Loading });
|
||||
backupInfo = await crypto.getKeyBackupInfo();
|
||||
backupInfo = await cli.getKeyBackupVersion();
|
||||
} catch (e) {
|
||||
logger.error("Error fetching backup data from server", e);
|
||||
this.setState({ phase: Phase.LoadError });
|
||||
|
||||
@@ -23,6 +23,7 @@ import classNames from "classnames";
|
||||
import { isOnlyCtrlOrCmdKeyEvent, Key } from "../../Keyboard";
|
||||
import PageTypes from "../../PageTypes";
|
||||
import MediaDeviceHandler from "../../MediaDeviceHandler";
|
||||
import { fixupColorFonts } from "../../utils/FontManager";
|
||||
import dis from "../../dispatcher/dispatcher";
|
||||
import { IMatrixClientCreds } from "../../MatrixClientPeg";
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
@@ -148,6 +149,8 @@ class LoggedInView extends React.Component<IProps, IState> {
|
||||
|
||||
MediaDeviceHandler.loadDevices();
|
||||
|
||||
fixupColorFonts();
|
||||
|
||||
this._roomView = React.createRef();
|
||||
this._resizeContainer = React.createRef();
|
||||
this.resizeHandler = React.createRef();
|
||||
|
||||
@@ -1638,7 +1638,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||
} else {
|
||||
// otherwise check the server to see if there's a new one
|
||||
try {
|
||||
newVersionInfo = (await cli.getCrypto()?.getKeyBackupInfo()) ?? null;
|
||||
newVersionInfo = await cli.getKeyBackupVersion();
|
||||
if (newVersionInfo !== null) haveNewVersion = true;
|
||||
} catch (e) {
|
||||
logger.error("Saw key backup error but failed to check backup version!", e);
|
||||
|
||||
@@ -109,7 +109,7 @@ export default class LogoutDialog extends React.Component<IProps, IState> {
|
||||
}
|
||||
|
||||
// backup is not active. see if there is a backup version on the server we ought to back up to.
|
||||
const backupInfo = await crypto.getKeyBackupInfo();
|
||||
const backupInfo = await client.getKeyBackupVersion();
|
||||
this.setState({ backupStatus: backupInfo ? BackupStatus.SERVER_BACKUP_BUT_DISABLED : BackupStatus.NO_BACKUP });
|
||||
}
|
||||
|
||||
|
||||
@@ -258,7 +258,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent<IProps,
|
||||
});
|
||||
try {
|
||||
const cli = MatrixClientPeg.safeGet();
|
||||
const backupInfo = (await cli.getCrypto()?.getKeyBackupInfo()) ?? null;
|
||||
const backupInfo = await cli.getKeyBackupVersion();
|
||||
const has4S = await cli.secretStorage.hasKey();
|
||||
const backupKeyStored = has4S ? await cli.isKeyBackupKeyStored() : null;
|
||||
this.setState({
|
||||
|
||||
@@ -275,7 +275,7 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
|
||||
}
|
||||
|
||||
const content = this.props.mxEvent.getContent<ImageContent>();
|
||||
let isAnimated = content.info?.["org.matrix.msc4230.is_animated"] ?? mayBeAnimated(content.info?.mimetype);
|
||||
let isAnimated = mayBeAnimated(content.info?.mimetype);
|
||||
|
||||
// If there is no included non-animated thumbnail then we will generate our own, we can't depend on the server
|
||||
// because 1. encryption and 2. we can't ask the server specifically for a non-animated thumbnail.
|
||||
@@ -298,15 +298,8 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
|
||||
}
|
||||
|
||||
try {
|
||||
// If we didn't receive the MSC4230 is_animated flag
|
||||
// then we need to check if the image is animated by downloading it.
|
||||
if (
|
||||
content.info?.["org.matrix.msc4230.is_animated"] === false ||
|
||||
!(await blobIsAnimated(
|
||||
content.info?.mimetype,
|
||||
await this.props.mediaEventHelper!.sourceBlob.value,
|
||||
))
|
||||
) {
|
||||
const blob = await this.props.mediaEventHelper!.sourceBlob.value;
|
||||
if (!(await blobIsAnimated(content.info?.mimetype, blob))) {
|
||||
isAnimated = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -757,9 +757,6 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
||||
case EventShieldReason.MISMATCHED_SENDER_KEY:
|
||||
shieldReasonMessage = _t("encryption|event_shield_reason_mismatched_sender_key");
|
||||
break;
|
||||
|
||||
default:
|
||||
shieldReasonMessage = _t("error|unknown");
|
||||
}
|
||||
|
||||
if (this.state.shieldColour === EventShieldColour.GREY) {
|
||||
|
||||
@@ -118,7 +118,7 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
|
||||
this.getUpdatedDiagnostics();
|
||||
try {
|
||||
const cli = MatrixClientPeg.safeGet();
|
||||
const backupInfo = (await cli.getCrypto()?.getKeyBackupInfo()) ?? null;
|
||||
const backupInfo = await cli.getKeyBackupVersion();
|
||||
const backupTrustInfo = backupInfo ? await cli.getCrypto()?.isKeyBackupTrusted(backupInfo) : undefined;
|
||||
|
||||
const activeBackupVersion = (await cli.getCrypto()?.getActiveSessionBackupVersion()) ?? null;
|
||||
@@ -192,9 +192,12 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
|
||||
if (!proceed) return;
|
||||
this.setState({ loading: true });
|
||||
const versionToDelete = this.state.backupInfo!.version!;
|
||||
// deleteKeyBackupVersion fires a key backup status event
|
||||
// which will update the UI
|
||||
MatrixClientPeg.safeGet().getCrypto()?.deleteKeyBackupVersion(versionToDelete);
|
||||
MatrixClientPeg.safeGet()
|
||||
.getCrypto()
|
||||
?.deleteKeyBackupVersion(versionToDelete)
|
||||
.then(() => {
|
||||
this.loadBackupStatus();
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -17,7 +17,6 @@ import {
|
||||
EventType,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { InlineSpinner } from "@vector-im/compound-web";
|
||||
|
||||
import { Icon as WarningIcon } from "../../../../../../res/img/warning.svg";
|
||||
import { _t } from "../../../../../languageHandler";
|
||||
@@ -54,7 +53,7 @@ interface IState {
|
||||
guestAccess: GuestAccess;
|
||||
history: HistoryVisibility;
|
||||
hasAliases: boolean;
|
||||
encrypted: boolean | null;
|
||||
encrypted: boolean;
|
||||
showAdvancedSection: boolean;
|
||||
}
|
||||
|
||||
@@ -79,7 +78,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
||||
HistoryVisibility.Shared,
|
||||
),
|
||||
hasAliases: false, // async loaded in componentDidMount
|
||||
encrypted: null, // async loaded in componentDidMount
|
||||
encrypted: false, // async loaded in componentDidMount
|
||||
showAdvancedSection: false,
|
||||
};
|
||||
}
|
||||
@@ -420,7 +419,6 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
||||
const client = this.context;
|
||||
const room = this.props.room;
|
||||
const isEncrypted = this.state.encrypted;
|
||||
const isEncryptionLoading = isEncrypted === null;
|
||||
const hasEncryptionPermission = room.currentState.mayClientSendStateEvent(EventType.RoomEncryption, client);
|
||||
const isEncryptionForceDisabled = shouldForceDisableEncryption(client);
|
||||
const canEnableEncryption = !isEncrypted && !isEncryptionForceDisabled && hasEncryptionPermission;
|
||||
@@ -453,23 +451,18 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
||||
: _t("room_settings|security|encryption_permanent")
|
||||
}
|
||||
>
|
||||
{isEncryptionLoading ? (
|
||||
<InlineSpinner />
|
||||
) : (
|
||||
<>
|
||||
<LabelledToggleSwitch
|
||||
value={isEncrypted}
|
||||
onChange={this.onEncryptionChange}
|
||||
label={_t("common|encrypted")}
|
||||
disabled={!canEnableEncryption}
|
||||
/>
|
||||
{isEncryptionForceDisabled && !isEncrypted && (
|
||||
<Caption>{_t("room_settings|security|encryption_forced")}</Caption>
|
||||
)}
|
||||
{encryptionSettings}
|
||||
</>
|
||||
<LabelledToggleSwitch
|
||||
value={isEncrypted}
|
||||
onChange={this.onEncryptionChange}
|
||||
label={_t("common|encrypted")}
|
||||
disabled={!canEnableEncryption}
|
||||
/>
|
||||
{isEncryptionForceDisabled && !isEncrypted && (
|
||||
<Caption>{_t("room_settings|security|encryption_forced")}</Caption>
|
||||
)}
|
||||
{encryptionSettings}
|
||||
</SettingsFieldset>
|
||||
|
||||
{this.renderJoinRule()}
|
||||
{historySection}
|
||||
</SettingsSection>
|
||||
|
||||
@@ -14,6 +14,7 @@ import SasEmoji from "@matrix-org/spec/sas-emoji.json";
|
||||
import { _t, getNormalizedLanguageKeys, getUserLanguage } from "../../../languageHandler";
|
||||
import { PendingActionSpinner } from "../right_panel/EncryptionInfo";
|
||||
import AccessibleButton from "../elements/AccessibleButton";
|
||||
import { fixupColorFonts } from "../../../utils/FontManager";
|
||||
|
||||
interface IProps {
|
||||
pending?: boolean;
|
||||
@@ -87,6 +88,11 @@ export default class VerificationShowSas extends React.Component<IProps, IState>
|
||||
this.state = {
|
||||
pending: false,
|
||||
};
|
||||
|
||||
// As this component is also used before login (during complete security),
|
||||
// also make sure we have a working emoji font to display the SAS emojis here.
|
||||
// This is also done from LoggedInView.
|
||||
fixupColorFonts();
|
||||
}
|
||||
|
||||
private onMatchClick = (): void => {
|
||||
|
||||
@@ -125,7 +125,7 @@ export class SetupEncryptionStore extends EventEmitter {
|
||||
this.emit("update");
|
||||
try {
|
||||
const cli = MatrixClientPeg.safeGet();
|
||||
const backupInfo = (await cli.getCrypto()?.getKeyBackupInfo()) ?? null;
|
||||
const backupInfo = await cli.getKeyBackupVersion();
|
||||
this.backupInfo = backupInfo;
|
||||
this.emit("update");
|
||||
|
||||
|
||||
124
src/utils/FontManager.ts
Normal file
124
src/utils/FontManager.ts
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2019-2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Based on...
|
||||
* ChromaCheck 1.16
|
||||
* author Roel Nieskens, https://pixelambacht.nl
|
||||
* MIT license
|
||||
*/
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
function safariVersionCheck(ua: string): boolean {
|
||||
logger.log("Browser is Safari - checking version for COLR support");
|
||||
try {
|
||||
const safariVersionMatch = ua.match(/Mac OS X ([\d|_]+).*Version\/([\d|.]+).*Safari/);
|
||||
if (safariVersionMatch) {
|
||||
const macOSVersionStr = safariVersionMatch[1];
|
||||
const safariVersionStr = safariVersionMatch[2];
|
||||
const macOSVersion = macOSVersionStr.split("_").map((n) => parseInt(n, 10));
|
||||
const safariVersion = safariVersionStr.split(".").map((n) => parseInt(n, 10));
|
||||
const colrFontSupported =
|
||||
macOSVersion[0] >= 10 && macOSVersion[1] >= 14 && safariVersion[0] >= 12 && safariVersion[0] < 17;
|
||||
// https://www.colorfonts.wtf/ states Safari supports COLR fonts from this version on but Safari 17 breaks it
|
||||
logger.log(
|
||||
`COLR support on Safari requires macOS 10.14 and Safari 12-16, ` +
|
||||
`detected Safari ${safariVersionStr} on macOS ${macOSVersionStr}, ` +
|
||||
`COLR supported: ${colrFontSupported}`,
|
||||
);
|
||||
return colrFontSupported;
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error("Error in Safari COLR version check", err);
|
||||
}
|
||||
logger.warn("Couldn't determine Safari version to check COLR font support, assuming no.");
|
||||
return false;
|
||||
}
|
||||
|
||||
async function isColrFontSupported(): Promise<boolean> {
|
||||
logger.log("Checking for COLR support");
|
||||
|
||||
const { userAgent } = navigator;
|
||||
// Firefox has supported COLR fonts since version 26
|
||||
// but doesn't support the check below without
|
||||
// "Extract canvas data" permissions
|
||||
// when content blocking is enabled.
|
||||
if (userAgent.includes("Firefox")) {
|
||||
logger.log("Browser is Firefox - assuming COLR is supported");
|
||||
return true;
|
||||
}
|
||||
// Safari doesn't wait for the font to load (if it doesn't have it in cache)
|
||||
// to emit the load event on the image, so there is no way to not make the check
|
||||
// reliable. Instead sniff the version.
|
||||
// Excluding "Chrome", as it's user agent unhelpfully also contains Safari...
|
||||
if (!userAgent.includes("Chrome") && userAgent.includes("Safari")) {
|
||||
return safariVersionCheck(userAgent);
|
||||
}
|
||||
|
||||
try {
|
||||
const canvas = document.createElement("canvas");
|
||||
const context = canvas.getContext("2d")!;
|
||||
const img = new Image();
|
||||
// eslint-disable-next-line
|
||||
const fontCOLR =
|
||||
"d09GRgABAAAAAAKAAAwAAAAAAowAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABDT0xSAAACVAAAABYAAAAYAAIAJUNQQUwAAAJsAAAAEgAAABLJAAAQT1MvMgAAAYAAAAA6AAAAYBfxJ0pjbWFwAAABxAAAACcAAAAsAAzpM2dseWYAAAH0AAAAGgAAABoNIh0kaGVhZAAAARwAAAAvAAAANgxLumdoaGVhAAABTAAAABUAAAAkCAEEAmhtdHgAAAG8AAAABgAAAAYEAAAAbG9jYQAAAewAAAAGAAAABgANAABtYXhwAAABZAAAABsAAAAgAg4AHW5hbWUAAAIQAAAAOAAAAD4C5wsecG9zdAAAAkgAAAAMAAAAIAADAAB4AWNgZGAAYQ5+qdB4fpuvDNIsDCBwaQGTAIi+VlscBaJZGMDiHAxMIAoAtjIF/QB4AWNgZGBgYQACOAkUQQWMAAGRABAAAAB4AWNgZGBgYGJgAdMMUJILJMQgAWICAAH3AC4AeAFjYGFhYJzAwMrAwDST6QwDA0M/hGZ8zWDMyMmAChgFkDgKQMBw4CXDSwYWEBdIYgAFBgYA/8sIdAAABAAAAAAAAAB4AWNgYGBkYAZiBgYeBhYGBSDNAoRA/kuG//8hpDgjWJ4BAFVMBiYAAAAAAAANAAAAAQAAAAAEAAQAAAMAABEhESEEAPwABAD8AAAAeAEtxgUNgAAAAMHHIQTShTlOAty9/4bf7AARCwlBNhBw4L/43qXjYGUmf19TMuLcj/BJL3XfBg54AWNgZsALAAB9AAR4AWNgYGAEYj4gFgGygGwICQACOwAoAAAAAAABAAEAAQAAAA4AAAAAyP8AAA==";
|
||||
const svg = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="100" style="background:#fff;fill:#000;">
|
||||
<style type="text/css">
|
||||
@font-face {
|
||||
font-family: "chromacheck-colr";
|
||||
src: url(data:application/x-font-woff;base64,${fontCOLR}) format("woff");
|
||||
}
|
||||
</style>
|
||||
<text x="0" y="0" font-size="20">
|
||||
<tspan font-family="chromacheck-colr" x="0" dy="20"></tspan>
|
||||
</text>
|
||||
</svg>`;
|
||||
canvas.width = 20;
|
||||
canvas.height = 100;
|
||||
|
||||
img.src = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svg);
|
||||
|
||||
logger.log("Waiting for COLR SVG to load");
|
||||
await new Promise((resolve) => (img.onload = resolve));
|
||||
logger.log("Drawing canvas to detect COLR support");
|
||||
context.drawImage(img, 0, 0);
|
||||
const colrFontSupported = context.getImageData(10, 10, 1, 1).data[0] === 200;
|
||||
logger.log("Canvas check revealed COLR is supported? " + colrFontSupported);
|
||||
return colrFontSupported;
|
||||
} catch (e) {
|
||||
logger.error("Couldn't load COLR font", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
let colrFontCheckStarted = false;
|
||||
export async function fixupColorFonts(): Promise<void> {
|
||||
if (colrFontCheckStarted) {
|
||||
return;
|
||||
}
|
||||
colrFontCheckStarted = true;
|
||||
|
||||
if (await isColrFontSupported()) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const path = `url('${require("../../res/fonts/Twemoji_Mozilla/TwemojiMozilla-colr.woff2")}')`;
|
||||
document.fonts.add(new FontFace("Twemoji", path, {}));
|
||||
// For at least Chrome on Windows 10, we have to explictly add extra
|
||||
// weights for the emoji to appear in bold messages, etc.
|
||||
document.fonts.add(new FontFace("Twemoji", path, { weight: "600" }));
|
||||
document.fonts.add(new FontFace("Twemoji", path, { weight: "700" }));
|
||||
} else {
|
||||
// fall back to SBIX, generated via https://github.com/matrix-org/twemoji-colr/tree/matthew/sbix
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const path = `url('${require("../../res/fonts/Twemoji_Mozilla/TwemojiMozilla-sbix.woff2")}')`;
|
||||
document.fonts.add(new FontFace("Twemoji", path, {}));
|
||||
document.fonts.add(new FontFace("Twemoji", path, { weight: "600" }));
|
||||
document.fonts.add(new FontFace("Twemoji", path, { weight: "700" }));
|
||||
}
|
||||
// ...and if SBIX is not supported, the browser will fall back to one of the native fonts specified.
|
||||
}
|
||||
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { ImageInfo } from "matrix-js-sdk/src/types";
|
||||
import { EncryptedFile } from "matrix-js-sdk/src/types";
|
||||
|
||||
import { BlurhashEncoder } from "../BlurhashEncoder";
|
||||
|
||||
@@ -15,7 +15,19 @@ type ThumbnailableElement = HTMLImageElement | HTMLVideoElement;
|
||||
export const BLURHASH_FIELD = "xyz.amorgan.blurhash"; // MSC2448
|
||||
|
||||
interface IThumbnail {
|
||||
info: ImageInfo;
|
||||
info: {
|
||||
thumbnail_info?: {
|
||||
w: number;
|
||||
h: number;
|
||||
mimetype: string;
|
||||
size: number;
|
||||
};
|
||||
w: number;
|
||||
h: number;
|
||||
[BLURHASH_FIELD]?: string;
|
||||
thumbnail_url?: string;
|
||||
thumbnail_file?: EncryptedFile;
|
||||
};
|
||||
thumbnail: Blob;
|
||||
}
|
||||
|
||||
|
||||
@@ -143,6 +143,7 @@ export const mockClientMethodsCrypto = (): Partial<
|
||||
> => ({
|
||||
isKeyBackupKeyStored: jest.fn(),
|
||||
getCrossSigningCacheCallbacks: jest.fn().mockReturnValue({ getCrossSigningKeyCache: jest.fn() }),
|
||||
getKeyBackupVersion: jest.fn().mockResolvedValue(null),
|
||||
secretStorage: { hasKey: jest.fn() },
|
||||
getCrypto: jest.fn().mockReturnValue({
|
||||
getUserDeviceInfo: jest.fn(),
|
||||
@@ -162,7 +163,6 @@ export const mockClientMethodsCrypto = (): Partial<
|
||||
getOwnDeviceKeys: jest.fn().mockReturnValue(new Promise(() => {})),
|
||||
getCrossSigningKeyId: jest.fn(),
|
||||
isEncryptionEnabledInRoom: jest.fn().mockResolvedValue(false),
|
||||
getKeyBackupInfo: jest.fn().mockResolvedValue(null),
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@ export function createTestClient(): MatrixClient {
|
||||
getDevices: jest.fn().mockResolvedValue({ devices: [{ device_id: "ABCDEFGHI" }] }),
|
||||
getSessionId: jest.fn().mockReturnValue("iaszphgvfku"),
|
||||
credentials: { userId: "@userId:matrix.org" },
|
||||
getKeyBackupVersion: jest.fn(),
|
||||
|
||||
secretStorage: {
|
||||
get: jest.fn(),
|
||||
@@ -134,7 +135,6 @@ export function createTestClient(): MatrixClient {
|
||||
restoreKeyBackupWithPassphrase: jest.fn(),
|
||||
loadSessionBackupPrivateKeyFromSecretStorage: jest.fn(),
|
||||
storeSessionBackupPrivateKey: jest.fn(),
|
||||
getKeyBackupInfo: jest.fn().mockResolvedValue(null),
|
||||
}),
|
||||
|
||||
getPushActionsForEvent: jest.fn(),
|
||||
|
||||
@@ -96,12 +96,12 @@ describe("DeviceListener", () => {
|
||||
}),
|
||||
getSessionBackupPrivateKey: jest.fn(),
|
||||
isEncryptionEnabledInRoom: jest.fn(),
|
||||
getKeyBackupInfo: jest.fn().mockResolvedValue(null),
|
||||
} as unknown as Mocked<CryptoApi>;
|
||||
mockClient = getMockClientWithEventEmitter({
|
||||
isGuest: jest.fn(),
|
||||
getUserId: jest.fn().mockReturnValue(userId),
|
||||
getSafeUserId: jest.fn().mockReturnValue(userId),
|
||||
getKeyBackupVersion: jest.fn().mockResolvedValue(undefined),
|
||||
getRooms: jest.fn().mockReturnValue([]),
|
||||
isVersionSupported: jest.fn().mockResolvedValue(true),
|
||||
isInitialSyncComplete: jest.fn().mockReturnValue(true),
|
||||
@@ -354,7 +354,7 @@ describe("DeviceListener", () => {
|
||||
|
||||
it("shows set up encryption toast when user has a key backup available", async () => {
|
||||
// non falsy response
|
||||
mockCrypto.getKeyBackupInfo.mockResolvedValue({} as unknown as KeyBackupInfo);
|
||||
mockClient!.getKeyBackupVersion.mockResolvedValue({} as unknown as KeyBackupInfo);
|
||||
await createAndStart();
|
||||
|
||||
expect(SetupEncryptionToast.showToast).toHaveBeenCalledWith(
|
||||
@@ -673,7 +673,7 @@ describe("DeviceListener", () => {
|
||||
describe("When Room Key Backup is not enabled", () => {
|
||||
beforeEach(() => {
|
||||
// no backup
|
||||
mockCrypto.getKeyBackupInfo.mockResolvedValue(null);
|
||||
mockClient.getKeyBackupVersion.mockResolvedValue(null);
|
||||
});
|
||||
|
||||
it("Should report recovery state as Enabled", async () => {
|
||||
@@ -722,7 +722,7 @@ describe("DeviceListener", () => {
|
||||
});
|
||||
|
||||
// no backup
|
||||
mockCrypto.getKeyBackupInfo.mockResolvedValue(null);
|
||||
mockClient.getKeyBackupVersion.mockResolvedValue(null);
|
||||
|
||||
await createAndStart();
|
||||
|
||||
@@ -872,7 +872,7 @@ describe("DeviceListener", () => {
|
||||
describe("When Room Key Backup is enabled", () => {
|
||||
beforeEach(() => {
|
||||
// backup enabled - just need a mock object
|
||||
mockCrypto.getKeyBackupInfo.mockResolvedValue({} as KeyBackupInfo);
|
||||
mockClient.getKeyBackupVersion.mockResolvedValue({} as KeyBackupInfo);
|
||||
});
|
||||
|
||||
const testCases = [
|
||||
|
||||
@@ -139,7 +139,6 @@ describe("<MatrixChat />", () => {
|
||||
globalBlacklistUnverifiedDevices: false,
|
||||
// This needs to not finish immediately because we need to test the screen appears
|
||||
bootstrapCrossSigning: jest.fn().mockImplementation(() => bootstrapDeferred.promise),
|
||||
getKeyBackupInfo: jest.fn().mockResolvedValue(null),
|
||||
}),
|
||||
secretStorage: {
|
||||
isStored: jest.fn().mockReturnValue(null),
|
||||
@@ -149,6 +148,7 @@ describe("<MatrixChat />", () => {
|
||||
whoami: jest.fn(),
|
||||
logout: jest.fn(),
|
||||
getDeviceId: jest.fn(),
|
||||
getKeyBackupVersion: jest.fn().mockResolvedValue(null),
|
||||
});
|
||||
let mockClient: Mocked<MatrixClient>;
|
||||
const serverConfig = {
|
||||
|
||||
@@ -22,6 +22,7 @@ describe("LogoutDialog", () => {
|
||||
beforeEach(() => {
|
||||
mockClient = getMockClientWithEventEmitter({
|
||||
...mockClientMethodsCrypto(),
|
||||
getKeyBackupVersion: jest.fn(),
|
||||
});
|
||||
|
||||
mockCrypto = mocked(mockClient.getCrypto()!);
|
||||
@@ -49,14 +50,14 @@ describe("LogoutDialog", () => {
|
||||
});
|
||||
|
||||
it("Prompts user to connect backup if there is a backup on the server", async () => {
|
||||
mockCrypto.getKeyBackupInfo.mockResolvedValue({} as KeyBackupInfo);
|
||||
mockClient.getKeyBackupVersion.mockResolvedValue({} as KeyBackupInfo);
|
||||
const rendered = renderComponent();
|
||||
await rendered.findByText("Connect this session to Key Backup");
|
||||
expect(rendered.container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("Prompts user to set up backup if there is no backup on the server", async () => {
|
||||
mockCrypto.getKeyBackupInfo.mockResolvedValue(null);
|
||||
mockClient.getKeyBackupVersion.mockResolvedValue(null);
|
||||
const rendered = renderComponent();
|
||||
await rendered.findByText("Start using Key Backup");
|
||||
expect(rendered.container).toMatchSnapshot();
|
||||
@@ -68,7 +69,7 @@ describe("LogoutDialog", () => {
|
||||
describe("when there is an error fetching backups", () => {
|
||||
filterConsole("Unable to fetch key backup status");
|
||||
it("prompts user to set up backup", async () => {
|
||||
mockCrypto.getKeyBackupInfo.mockImplementation(async () => {
|
||||
mockClient.getKeyBackupVersion.mockImplementation(async () => {
|
||||
throw new Error("beep");
|
||||
});
|
||||
const rendered = renderComponent();
|
||||
|
||||
@@ -77,7 +77,7 @@ describe("CreateSecretStorageDialog", () => {
|
||||
filterConsole("Error fetching backup data from server");
|
||||
|
||||
it("shows an error", async () => {
|
||||
jest.spyOn(mockClient.getCrypto()!, "getKeyBackupInfo").mockImplementation(async () => {
|
||||
mockClient.getKeyBackupVersion.mockImplementation(async () => {
|
||||
throw new Error("bleh bleh");
|
||||
});
|
||||
|
||||
@@ -92,7 +92,7 @@ describe("CreateSecretStorageDialog", () => {
|
||||
expect(result.container).toMatchSnapshot();
|
||||
|
||||
// Now we can get the backup and we retry
|
||||
jest.spyOn(mockClient.getCrypto()!, "getKeyBackupInfo").mockRestore();
|
||||
mockClient.getKeyBackupVersion.mockRestore();
|
||||
await userEvent.click(screen.getByRole("button", { name: "Retry" }));
|
||||
await screen.findByText("Your keys are now being backed up from this device.");
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@ describe("<RestoreKeyBackupDialog />", () => {
|
||||
beforeEach(() => {
|
||||
matrixClient = stubClient();
|
||||
jest.spyOn(recoveryKeyModule, "decodeRecoveryKey").mockReturnValue(new Uint8Array(32));
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getKeyBackupInfo").mockResolvedValue({ version: "1" } as KeyBackupInfo);
|
||||
jest.spyOn(matrixClient, "getKeyBackupVersion").mockResolvedValue({ version: "1" } as KeyBackupInfo);
|
||||
});
|
||||
|
||||
it("should render", async () => {
|
||||
@@ -99,7 +99,7 @@ describe("<RestoreKeyBackupDialog />", () => {
|
||||
|
||||
test("should restore key backup when passphrase is filled", async () => {
|
||||
// Determine that the passphrase is required
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getKeyBackupInfo").mockResolvedValue({
|
||||
jest.spyOn(matrixClient, "getKeyBackupVersion").mockResolvedValue({
|
||||
version: "1",
|
||||
auth_data: {
|
||||
private_key_salt: "salt",
|
||||
|
||||
@@ -28,13 +28,14 @@ describe("<SecureBackupPanel />", () => {
|
||||
const client = getMockClientWithEventEmitter({
|
||||
...mockClientMethodsUser(userId),
|
||||
...mockClientMethodsCrypto(),
|
||||
getKeyBackupVersion: jest.fn().mockReturnValue("1"),
|
||||
getClientWellKnown: jest.fn(),
|
||||
});
|
||||
|
||||
const getComponent = () => render(<SecureBackupPanel />);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.spyOn(client.getCrypto()!, "getKeyBackupInfo").mockResolvedValue({
|
||||
client.getKeyBackupVersion.mockResolvedValue({
|
||||
version: "1",
|
||||
algorithm: "test",
|
||||
auth_data: {
|
||||
@@ -51,6 +52,7 @@ describe("<SecureBackupPanel />", () => {
|
||||
});
|
||||
|
||||
mocked(client.secretStorage.hasKey).mockClear().mockResolvedValue(false);
|
||||
client.getKeyBackupVersion.mockClear();
|
||||
|
||||
mocked(accessSecretStorage).mockClear().mockResolvedValue();
|
||||
});
|
||||
@@ -63,8 +65,8 @@ describe("<SecureBackupPanel />", () => {
|
||||
});
|
||||
|
||||
it("handles error fetching backup", async () => {
|
||||
// getKeyBackupInfo can fail for various reasons
|
||||
jest.spyOn(client.getCrypto()!, "getKeyBackupInfo").mockImplementation(async () => {
|
||||
// getKeyBackupVersion can fail for various reasons
|
||||
client.getKeyBackupVersion.mockImplementation(async () => {
|
||||
throw new Error("beep beep");
|
||||
});
|
||||
const renderResult = getComponent();
|
||||
@@ -73,9 +75,9 @@ describe("<SecureBackupPanel />", () => {
|
||||
});
|
||||
|
||||
it("handles absence of backup", async () => {
|
||||
jest.spyOn(client.getCrypto()!, "getKeyBackupInfo").mockResolvedValue(null);
|
||||
client.getKeyBackupVersion.mockResolvedValue(null);
|
||||
getComponent();
|
||||
// flush getKeyBackupInfo promise
|
||||
// flush getKeyBackupVersion promise
|
||||
await flushPromises();
|
||||
expect(screen.getByText("Back up your keys before signing out to avoid losing them.")).toBeInTheDocument();
|
||||
});
|
||||
@@ -118,7 +120,7 @@ describe("<SecureBackupPanel />", () => {
|
||||
});
|
||||
|
||||
it("deletes backup after confirmation", async () => {
|
||||
jest.spyOn(client.getCrypto()!, "getKeyBackupInfo")
|
||||
client.getKeyBackupVersion
|
||||
.mockResolvedValueOnce({
|
||||
version: "1",
|
||||
algorithm: "test",
|
||||
@@ -155,7 +157,7 @@ describe("<SecureBackupPanel />", () => {
|
||||
// flush checkKeyBackup promise
|
||||
await flushPromises();
|
||||
|
||||
jest.spyOn(client.getCrypto()!, "getKeyBackupInfo").mockClear();
|
||||
client.getKeyBackupVersion.mockClear();
|
||||
mocked(client.getCrypto()!).isKeyBackupTrusted.mockClear();
|
||||
|
||||
fireEvent.click(screen.getByText("Reset"));
|
||||
@@ -165,7 +167,7 @@ describe("<SecureBackupPanel />", () => {
|
||||
await flushPromises();
|
||||
|
||||
// backup status refreshed
|
||||
expect(client.getCrypto()!.getKeyBackupInfo).toHaveBeenCalled();
|
||||
expect(client.getKeyBackupVersion).toHaveBeenCalled();
|
||||
expect(client.getCrypto()!.isKeyBackupTrusted).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -75,7 +75,7 @@ describe("<SecurityRoomSettingsTab />", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
client.sendStateEvent.mockReset().mockResolvedValue({ event_id: "test" });
|
||||
jest.spyOn(client.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(false);
|
||||
client.isRoomEncrypted.mockReturnValue(false);
|
||||
client.getClientWellKnown.mockReturnValue(undefined);
|
||||
jest.spyOn(SettingsStore, "getValue").mockRestore();
|
||||
|
||||
@@ -313,7 +313,7 @@ describe("<SecurityRoomSettingsTab />", () => {
|
||||
setRoomStateEvents(room);
|
||||
getComponent(room);
|
||||
|
||||
await waitFor(() => expect(screen.getByLabelText("Encrypted")).not.toBeChecked());
|
||||
expect(screen.getByLabelText("Encrypted")).not.toBeChecked();
|
||||
|
||||
fireEvent.click(screen.getByLabelText("Encrypted"));
|
||||
|
||||
@@ -330,7 +330,7 @@ describe("<SecurityRoomSettingsTab />", () => {
|
||||
setRoomStateEvents(room);
|
||||
getComponent(room);
|
||||
|
||||
await waitFor(() => expect(screen.getByLabelText("Encrypted")).not.toBeChecked());
|
||||
expect(screen.getByLabelText("Encrypted")).not.toBeChecked();
|
||||
|
||||
fireEvent.click(screen.getByLabelText("Encrypted"));
|
||||
|
||||
@@ -416,12 +416,12 @@ describe("<SecurityRoomSettingsTab />", () => {
|
||||
expect(screen.getByText("Once enabled, encryption cannot be disabled.")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("displays unencrypted rooms with toggle disabled", async () => {
|
||||
it("displays unencrypted rooms with toggle disabled", () => {
|
||||
const room = new Room(roomId, client, userId);
|
||||
setRoomStateEvents(room);
|
||||
getComponent(room);
|
||||
|
||||
await waitFor(() => expect(screen.getByLabelText("Encrypted")).not.toBeChecked());
|
||||
expect(screen.getByLabelText("Encrypted")).not.toBeChecked();
|
||||
expect(screen.getByLabelText("Encrypted").getAttribute("aria-disabled")).toEqual("true");
|
||||
expect(screen.queryByText("Once enabled, encryption cannot be disabled.")).not.toBeInTheDocument();
|
||||
expect(screen.getByText("Your server requires encryption to be disabled.")).toBeInTheDocument();
|
||||
|
||||
@@ -34,6 +34,7 @@ describe("<SecurityUserSettingsTab />", () => {
|
||||
...mockClientMethodsCrypto(),
|
||||
getRooms: jest.fn().mockReturnValue([]),
|
||||
getIgnoredUsers: jest.fn(),
|
||||
getKeyBackupVersion: jest.fn(),
|
||||
});
|
||||
|
||||
const sdkContext = new SdkContextClass();
|
||||
|
||||
@@ -37,7 +37,6 @@ describe("SetupEncryptionStore", () => {
|
||||
getDeviceVerificationStatus: jest.fn(),
|
||||
isDehydrationSupported: jest.fn().mockResolvedValue(false),
|
||||
startDehydration: jest.fn(),
|
||||
getKeyBackupInfo: jest.fn().mockResolvedValue(null),
|
||||
} as unknown as Mocked<CryptoApi>;
|
||||
client.getCrypto.mockReturnValue(mockCrypto);
|
||||
|
||||
|
||||
@@ -27,5 +27,11 @@
|
||||
"./test/**/*.ts",
|
||||
"./test/**/*.tsx",
|
||||
"./scripts/*.ts"
|
||||
]
|
||||
],
|
||||
"ts-node": {
|
||||
"files": true,
|
||||
"moduleTypes": {
|
||||
"*": "cjs"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
264
yarn.lock
264
yarn.lock
@@ -1164,6 +1164,13 @@
|
||||
uuid "8.3.2"
|
||||
xml "1.0.1"
|
||||
|
||||
"@cspotcode/source-map-support@^0.8.0":
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1"
|
||||
integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==
|
||||
dependencies:
|
||||
"@jridgewell/trace-mapping" "0.3.9"
|
||||
|
||||
"@csstools/cascade-layer-name-parser@^2.0.2":
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-2.0.2.tgz#a71bd7ab4325fbbdd41e55645c2c958896b24fb1"
|
||||
@@ -1483,126 +1490,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz#519c1549b0e147759e7825701ecffd25e5819f7b"
|
||||
integrity sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==
|
||||
|
||||
"@esbuild/aix-ppc64@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz#51299374de171dbd80bb7d838e1cfce9af36f353"
|
||||
integrity sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==
|
||||
|
||||
"@esbuild/android-arm64@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz#58565291a1fe548638adb9c584237449e5e14018"
|
||||
integrity sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==
|
||||
|
||||
"@esbuild/android-arm@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.23.1.tgz#5eb8c652d4c82a2421e3395b808e6d9c42c862ee"
|
||||
integrity sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==
|
||||
|
||||
"@esbuild/android-x64@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.23.1.tgz#ae19d665d2f06f0f48a6ac9a224b3f672e65d517"
|
||||
integrity sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==
|
||||
|
||||
"@esbuild/darwin-arm64@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz#05b17f91a87e557b468a9c75e9d85ab10c121b16"
|
||||
integrity sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==
|
||||
|
||||
"@esbuild/darwin-x64@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz#c58353b982f4e04f0d022284b8ba2733f5ff0931"
|
||||
integrity sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz#f9220dc65f80f03635e1ef96cfad5da1f446f3bc"
|
||||
integrity sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==
|
||||
|
||||
"@esbuild/freebsd-x64@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz#69bd8511fa013b59f0226d1609ac43f7ce489730"
|
||||
integrity sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==
|
||||
|
||||
"@esbuild/linux-arm64@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz#8050af6d51ddb388c75653ef9871f5ccd8f12383"
|
||||
integrity sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==
|
||||
|
||||
"@esbuild/linux-arm@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz#ecaabd1c23b701070484990db9a82f382f99e771"
|
||||
integrity sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==
|
||||
|
||||
"@esbuild/linux-ia32@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz#3ed2273214178109741c09bd0687098a0243b333"
|
||||
integrity sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==
|
||||
|
||||
"@esbuild/linux-loong64@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz#a0fdf440b5485c81b0fbb316b08933d217f5d3ac"
|
||||
integrity sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==
|
||||
|
||||
"@esbuild/linux-mips64el@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz#e11a2806346db8375b18f5e104c5a9d4e81807f6"
|
||||
integrity sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==
|
||||
|
||||
"@esbuild/linux-ppc64@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz#06a2744c5eaf562b1a90937855b4d6cf7c75ec96"
|
||||
integrity sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==
|
||||
|
||||
"@esbuild/linux-riscv64@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz#65b46a2892fc0d1af4ba342af3fe0fa4a8fe08e7"
|
||||
integrity sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==
|
||||
|
||||
"@esbuild/linux-s390x@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz#e71ea18c70c3f604e241d16e4e5ab193a9785d6f"
|
||||
integrity sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==
|
||||
|
||||
"@esbuild/linux-x64@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz#d47f97391e80690d4dfe811a2e7d6927ad9eed24"
|
||||
integrity sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==
|
||||
|
||||
"@esbuild/netbsd-x64@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz#44e743c9778d57a8ace4b72f3c6b839a3b74a653"
|
||||
integrity sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==
|
||||
|
||||
"@esbuild/openbsd-arm64@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz#05c5a1faf67b9881834758c69f3e51b7dee015d7"
|
||||
integrity sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==
|
||||
|
||||
"@esbuild/openbsd-x64@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz#2e58ae511bacf67d19f9f2dcd9e8c5a93f00c273"
|
||||
integrity sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==
|
||||
|
||||
"@esbuild/sunos-x64@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz#adb022b959d18d3389ac70769cef5a03d3abd403"
|
||||
integrity sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==
|
||||
|
||||
"@esbuild/win32-arm64@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz#84906f50c212b72ec360f48461d43202f4c8b9a2"
|
||||
integrity sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==
|
||||
|
||||
"@esbuild/win32-ia32@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz#5e3eacc515820ff729e90d0cb463183128e82fac"
|
||||
integrity sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==
|
||||
|
||||
"@esbuild/win32-x64@0.23.1":
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz#81fd50d11e2c32b2d6241470e3185b70c7b30699"
|
||||
integrity sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==
|
||||
|
||||
"@eslint-community/eslint-utils@^4.2.0":
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
|
||||
@@ -1978,7 +1865,7 @@
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
"@jridgewell/trace-mapping" "^0.3.24"
|
||||
|
||||
"@jridgewell/resolve-uri@^3.1.0":
|
||||
"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0":
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6"
|
||||
integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
|
||||
@@ -2001,6 +1888,14 @@
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a"
|
||||
integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==
|
||||
|
||||
"@jridgewell/trace-mapping@0.3.9":
|
||||
version "0.3.9"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9"
|
||||
integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==
|
||||
dependencies:
|
||||
"@jridgewell/resolve-uri" "^3.0.3"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
|
||||
"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25":
|
||||
version "0.3.25"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0"
|
||||
@@ -2842,6 +2737,26 @@
|
||||
mkdirp "^1.0.4"
|
||||
path-browserify "^1.0.1"
|
||||
|
||||
"@tsconfig/node10@^1.0.7":
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2"
|
||||
integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==
|
||||
|
||||
"@tsconfig/node12@^1.0.7":
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d"
|
||||
integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==
|
||||
|
||||
"@tsconfig/node14@^1.0.0":
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1"
|
||||
integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==
|
||||
|
||||
"@tsconfig/node16@^1.0.2":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9"
|
||||
integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==
|
||||
|
||||
"@types/aria-query@^5.0.1":
|
||||
version "5.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708"
|
||||
@@ -3721,14 +3636,14 @@ acorn-jsx@^5.3.2:
|
||||
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
|
||||
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
||||
|
||||
acorn-walk@^8.0.0, acorn-walk@^8.0.2:
|
||||
acorn-walk@^8.0.0, acorn-walk@^8.0.2, acorn-walk@^8.1.1:
|
||||
version "8.3.4"
|
||||
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7"
|
||||
integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==
|
||||
dependencies:
|
||||
acorn "^8.11.0"
|
||||
|
||||
acorn@^8.0.4, acorn@^8.1.0, acorn@^8.11.0, acorn@^8.12.0, acorn@^8.7.1, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0:
|
||||
acorn@^8.0.4, acorn@^8.1.0, acorn@^8.11.0, acorn@^8.12.0, acorn@^8.4.1, acorn@^8.7.1, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0:
|
||||
version "8.13.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.13.0.tgz#2a30d670818ad16ddd6a35d3842dacec9e5d7ca3"
|
||||
integrity sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==
|
||||
@@ -3858,6 +3773,11 @@ anymatch@^3.0.3, anymatch@~3.1.2:
|
||||
normalize-path "^3.0.0"
|
||||
picomatch "^2.0.4"
|
||||
|
||||
arg@^4.1.0:
|
||||
version "4.1.3"
|
||||
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
|
||||
integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
|
||||
|
||||
argparse@^1.0.7:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
|
||||
@@ -4819,6 +4739,11 @@ create-jest@^29.7.0:
|
||||
jest-util "^29.7.0"
|
||||
prompts "^2.0.1"
|
||||
|
||||
create-require@^1.1.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
|
||||
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
|
||||
|
||||
cronstrue@^2.41.0:
|
||||
version "2.50.0"
|
||||
resolved "https://registry.yarnpkg.com/cronstrue/-/cronstrue-2.50.0.tgz#eabba0f915f186765258b707b7a3950c663b5573"
|
||||
@@ -5278,6 +5203,11 @@ diff-sequences@^29.6.3:
|
||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921"
|
||||
integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==
|
||||
|
||||
diff@^4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
|
||||
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
|
||||
|
||||
dijkstrajs@^1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz#4c8dbdea1f0f6478bff94d9c49c784d623e4fc23"
|
||||
@@ -5683,36 +5613,6 @@ es-to-primitive@^1.2.1:
|
||||
is-date-object "^1.0.1"
|
||||
is-symbol "^1.0.2"
|
||||
|
||||
esbuild@~0.23.0:
|
||||
version "0.23.1"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.23.1.tgz#40fdc3f9265ec0beae6f59824ade1bd3d3d2dab8"
|
||||
integrity sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==
|
||||
optionalDependencies:
|
||||
"@esbuild/aix-ppc64" "0.23.1"
|
||||
"@esbuild/android-arm" "0.23.1"
|
||||
"@esbuild/android-arm64" "0.23.1"
|
||||
"@esbuild/android-x64" "0.23.1"
|
||||
"@esbuild/darwin-arm64" "0.23.1"
|
||||
"@esbuild/darwin-x64" "0.23.1"
|
||||
"@esbuild/freebsd-arm64" "0.23.1"
|
||||
"@esbuild/freebsd-x64" "0.23.1"
|
||||
"@esbuild/linux-arm" "0.23.1"
|
||||
"@esbuild/linux-arm64" "0.23.1"
|
||||
"@esbuild/linux-ia32" "0.23.1"
|
||||
"@esbuild/linux-loong64" "0.23.1"
|
||||
"@esbuild/linux-mips64el" "0.23.1"
|
||||
"@esbuild/linux-ppc64" "0.23.1"
|
||||
"@esbuild/linux-riscv64" "0.23.1"
|
||||
"@esbuild/linux-s390x" "0.23.1"
|
||||
"@esbuild/linux-x64" "0.23.1"
|
||||
"@esbuild/netbsd-x64" "0.23.1"
|
||||
"@esbuild/openbsd-arm64" "0.23.1"
|
||||
"@esbuild/openbsd-x64" "0.23.1"
|
||||
"@esbuild/sunos-x64" "0.23.1"
|
||||
"@esbuild/win32-arm64" "0.23.1"
|
||||
"@esbuild/win32-ia32" "0.23.1"
|
||||
"@esbuild/win32-x64" "0.23.1"
|
||||
|
||||
escalade@^3.1.1, escalade@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
|
||||
@@ -6471,7 +6371,7 @@ fsevents@2.3.2:
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
||||
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
|
||||
|
||||
fsevents@^2.3.2, fsevents@~2.3.2, fsevents@~2.3.3:
|
||||
fsevents@^2.3.2, fsevents@~2.3.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
||||
@@ -6556,13 +6456,6 @@ get-symbol-description@^1.0.2:
|
||||
es-errors "^1.3.0"
|
||||
get-intrinsic "^1.2.4"
|
||||
|
||||
get-tsconfig@^4.7.5:
|
||||
version "4.8.1"
|
||||
resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.8.1.tgz#8995eb391ae6e1638d251118c7b56de7eb425471"
|
||||
integrity sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==
|
||||
dependencies:
|
||||
resolve-pkg-maps "^1.0.0"
|
||||
|
||||
github-markdown-css@^5.5.1:
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/github-markdown-css/-/github-markdown-css-5.7.0.tgz#40fa19a8b9826a22874f305c40a5260d4d57e90a"
|
||||
@@ -8389,6 +8282,11 @@ make-dir@^4.0.0:
|
||||
dependencies:
|
||||
semver "^7.5.3"
|
||||
|
||||
make-error@^1.1.1:
|
||||
version "1.3.6"
|
||||
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
|
||||
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
|
||||
|
||||
makeerror@1.0.12:
|
||||
version "1.0.12"
|
||||
resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a"
|
||||
@@ -10475,11 +10373,6 @@ resolve-from@^5.0.0:
|
||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
|
||||
integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
|
||||
|
||||
resolve-pkg-maps@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f"
|
||||
integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==
|
||||
|
||||
resolve-protobuf-schema@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz#9ca9a9e69cf192bbdaf1006ec1973948aa4a3758"
|
||||
@@ -11557,6 +11450,25 @@ ts-morph@^13.0.1:
|
||||
"@ts-morph/common" "~0.12.3"
|
||||
code-block-writer "^11.0.0"
|
||||
|
||||
ts-node@^10.9.1:
|
||||
version "10.9.2"
|
||||
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f"
|
||||
integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==
|
||||
dependencies:
|
||||
"@cspotcode/source-map-support" "^0.8.0"
|
||||
"@tsconfig/node10" "^1.0.7"
|
||||
"@tsconfig/node12" "^1.0.7"
|
||||
"@tsconfig/node14" "^1.0.0"
|
||||
"@tsconfig/node16" "^1.0.2"
|
||||
acorn "^8.4.1"
|
||||
acorn-walk "^8.1.1"
|
||||
arg "^4.1.0"
|
||||
create-require "^1.1.0"
|
||||
diff "^4.0.1"
|
||||
make-error "^1.1.1"
|
||||
v8-compile-cache-lib "^3.0.1"
|
||||
yn "3.1.1"
|
||||
|
||||
ts-prune@^0.10.3:
|
||||
version "0.10.3"
|
||||
resolved "https://registry.yarnpkg.com/ts-prune/-/ts-prune-0.10.3.tgz#b6c71a525543b38dcf947a7d3adfb7f9e8b91f38"
|
||||
@@ -11594,16 +11506,6 @@ tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.6.1, tslib@^2.6
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.0.tgz#d124c86c3c05a40a91e6fdea4021bd31d377971b"
|
||||
integrity sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==
|
||||
|
||||
tsx@^4.19.2:
|
||||
version "4.19.2"
|
||||
resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.19.2.tgz#2d7814783440e0ae42354d0417d9c2989a2ae92c"
|
||||
integrity sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==
|
||||
dependencies:
|
||||
esbuild "~0.23.0"
|
||||
get-tsconfig "^4.7.5"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.3"
|
||||
|
||||
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"
|
||||
@@ -11875,6 +11777,11 @@ uuid@^9.0.0:
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30"
|
||||
integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==
|
||||
|
||||
v8-compile-cache-lib@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
|
||||
integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==
|
||||
|
||||
v8-to-istanbul@^9.0.1:
|
||||
version "9.3.0"
|
||||
resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175"
|
||||
@@ -12418,6 +12325,11 @@ yargs@^17.3.1, yargs@^17.7.2:
|
||||
y18n "^5.0.5"
|
||||
yargs-parser "^21.1.1"
|
||||
|
||||
yn@3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
|
||||
integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==
|
||||
|
||||
yocto-queue@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||
|
||||
Reference in New Issue
Block a user