Compare commits

..

51 Commits

Author SHA1 Message Date
Michael Telatynski
bba3e07b4d Refactor store and fix bugs with it (#2348)
(cherry picked from commit 9660c4b2be)
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-05-23 14:40:43 +01:00
RiotRobot
827d514628 v1.11.101 2025-05-20 14:01:24 +00:00
RiotRobot
68216568b0 v1.11.101-rc.0 2025-05-13 11:03:12 +00:00
ElementRobot
9cf81e4484 Merge pull request #2313 from element-hq/actions/localazy-download
Localazy Download
2025-05-12 01:23:34 -05:00
t3chguy
bb2435b529 [create-pull-request] automated change 2025-05-12 06:07:37 +00:00
Michael Telatynski
c0efe2334b Rely on @electron/universal for macOS ASAR integrity (#2169) 2025-05-08 08:32:35 +01:00
ElementRobot
0c2c26af75 Merge pull request #2300 from element-hq/actions/localazy-download
Localazy Download
2025-05-07 17:25:20 +02:00
t3chguy
3c9b229664 [create-pull-request] automated change 2025-05-07 14:58:23 +00:00
RiotRobot
e5815f3e3c Merge branch 'master' into develop 2025-05-06 14:20:34 +00:00
RiotRobot
b5febd1a07 v1.11.100 2025-05-06 14:19:52 +00:00
David Baker
747245e63f Merge pull request #2308 from element-hq/dbkr/apply_gtk_workaround_backport
Apply workaround to fix app launching on Linux
2025-05-06 14:20:38 +01:00
David Baker
a1bba6f8d3 Apply workaround to fix app launching on Linux
Manual backport of https://github.com/element-hq/element-desktop/pull/2307
2025-05-06 13:24:49 +01:00
David Baker
3c39998b0a Merge pull request #2307 from element-hq/dbkr/apply_gtk_workaround
Apply workaround to fix app launching on Linux
2025-05-06 12:08:49 +01:00
David Baker
10f09c90c7 Merge pull request #2306 from element-hq/revert-2298-revert-2293-renovate/major-electron
Re-apply "Update dependency electron to v36"
2025-05-06 12:00:08 +01:00
David Baker
cd9b48d87f Prettier 2025-05-06 11:47:45 +01:00
David Baker
10e2c5c1e4 Apply workaround for electron bug
Fixes https://github.com/element-hq/element-desktop/issues/2297
2025-05-06 11:40:32 +01:00
David Baker
0ad720454c Revert "Revert "Update dependency electron to v36"" 2025-05-06 10:44:51 +01:00
David Baker
ccb1c59076 Merge pull request #2298 from element-hq/revert-2293-renovate/major-electron
Revert "Update dependency electron to v36"
2025-05-02 18:14:40 +01:00
David Baker
9e315e9b05 Merge pull request #2299 from element-hq/rav/gdb_docs
Notes on using gdb
2025-05-02 09:59:31 +01:00
Richard van der Hoff
3a8726f953 Notes on using gdb
... because I always forget how to do this, and it takes me ages to remember.
2025-05-01 17:13:49 +01:00
David Baker
abaaadd2eb Revert "Update dependency electron to v36 (#2293)"
This reverts commit 0b167fe278.
2025-05-01 16:24:19 +01:00
Michael Telatynski
2699d04fd1 Update copy for the Electron Linux keyring backend error (#2295) 2025-04-30 12:13:12 +01:00
ElementRobot
00f3777fcf Merge pull request #2294 from element-hq/actions/localazy-download
Localazy Download
2025-04-30 08:23:14 +02:00
t3chguy
2b928c3f50 [create-pull-request] automated change 2025-04-30 06:07:35 +00:00
renovate[bot]
0b167fe278 Update dependency electron to v36 (#2293)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2025-04-29 12:48:23 +01:00
renovate[bot]
8db9c620df Update all non-major dependencies (#2288)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2025-04-29 11:33:31 +00:00
RiotRobot
2c60929139 v1.11.100-rc.0 2025-04-29 11:21:56 +00:00
renovate[bot]
9a8ca9980f Update playwright to v1.52.0 (#2291)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 12:08:03 +01:00
renovate[bot]
451129d468 Update typescript-eslint monorepo to v8.31.0 (#2292)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 11:06:17 +00:00
renovate[bot]
42a3b8b68c Update docker (#2287)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 12:00:38 +01:00
renovate[bot]
56bbea995f Update dependency @types/node to v18.19.87 (#2289)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 10:59:37 +00:00
Michael Telatynski
c72d23f995 Migrate from keytar to safeStorage (#2227) 2025-04-29 10:40:06 +00:00
David Baker
570a8bdefe Merge pull request #2275 from Fusseldieb/develop
Notification fixes for Windows - AppID name was messing up handler
2025-04-28 13:44:53 +01:00
renovate[bot]
1d3408bb37 Update dependency electron to v35.2.0 (#2283)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-24 09:30:12 +01:00
Michael Telatynski
eef66d9795 Improve HTML test report (#2282) 2025-04-23 14:33:20 +01:00
RiotRobot
a70c5e0215 Merge branch 'master' into develop 2025-04-23 11:16:22 +00:00
RiotRobot
d388b1e64a v1.11.99 2025-04-23 11:15:41 +00:00
ElementRobot
216b1c2157 Fix io.element.desktop protocol handler (#2280) (#2281)
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2025-04-23 10:49:47 +00:00
Michael Telatynski
72da1a90db Fix io.element.desktop protocol handler (#2280) 2025-04-23 11:34:44 +01:00
Valentino Stillhart
37bc884d77 Explanation for setAppUserModelId 2025-04-22 12:59:39 -03:00
RiotRobot
a43d087c02 Merge branch 'master' into develop 2025-04-22 13:47:11 +00:00
Valentino Stillhart
41ff61421d AppIDs must match config to properly display notification icon and title 2025-04-18 05:19:41 -03:00
Valentino Stillhart
65cdeaa9de Dashes were breaking notifications 2025-04-18 05:04:59 -03:00
Michael Telatynski
262abf5847 Enable windows arm64 tests using windows-11-arm runner (#2271) 2025-04-16 13:29:19 +01:00
renovate[bot]
4aa0454442 Update dependency windows to v2025 (#2268)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2025-04-15 16:29:42 +01:00
renovate[bot]
681365fd2f Update all non-major dependencies (#2261)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2025-04-15 15:13:34 +00:00
renovate[bot]
f566c83c81 Update dependency ubuntu to v24 (#2267)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 15:11:06 +00:00
renovate[bot]
1aab67e874 Update electron (#2265)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 15:39:16 +01:00
renovate[bot]
4ded16f12e Update dependency typescript to v5.8.3 (#2263)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 15:36:11 +01:00
renovate[bot]
12ea5fa91a Update typescript-eslint monorepo to v8.29.1 (#2264)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 15:35:18 +01:00
renovate[bot]
83775c9104 Update dependency @types/node to v18.19.86 (#2262)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 15:34:52 +01:00
38 changed files with 1358 additions and 456 deletions

View File

@@ -25,6 +25,7 @@ jobs:
arch: [x64, ia32, arm64]
with:
arch: ${{ matrix.arch }}
blob_report: true
linux:
needs: fetch
@@ -37,14 +38,47 @@ jobs:
with:
sqlcipher: ${{ matrix.sqlcipher }}
arch: ${{ matrix.arch }}
blob_report: true
macos:
needs: fetch
name: macOS
uses: ./.github/workflows/build_macos.yaml
with:
blob_report: true
tests-done:
needs: [windows, linux, macos]
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
if: always()
steps:
- run: echo "Tests successful"
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
cache: "yarn"
node-version: "lts/*"
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Download blob reports from GitHub Actions Artifacts
uses: actions/download-artifact@v4
with:
pattern: blob-report-*
path: all-blob-reports
merge-multiple: true
- name: Merge into HTML Report
run: yarn playwright merge-reports -c ./playwright.config.ts --reporter=html ./all-blob-reports
- name: Upload HTML report
if: always()
uses: actions/upload-artifact@v4
with:
name: html-report
path: playwright-report
retention-days: 14
- if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
run: exit 1

View File

@@ -16,6 +16,10 @@ on:
type: string
required: true
description: "How to link sqlcipher, one of 'system' | 'static'"
blob_report:
type: boolean
required: false
description: "Whether to run the blob report"
env:
SQLCIPHER_BUNDLED: ${{ inputs.sqlcipher == 'static' && '1' || '' }}
MAX_GLIBC: 2.31 # bullseye-era glibc, used by glibc-check.sh
@@ -91,7 +95,7 @@ jobs:
# This allows contributors to test changes to the dockerbuild image within a pull request
- name: Build docker image
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6
if: steps.changed_files.outputs.any_modified == 'true'
with:
file: dockerbuild/Dockerfile
@@ -194,3 +198,4 @@ jobs:
prepare_cmd: |
sudo apt-get -qq update
sudo apt install ./dist/*.deb
blob_report: ${{ inputs.blob_report }}

View File

@@ -27,6 +27,10 @@ on:
type: string
required: false
description: "The URL to which the output will be deployed."
blob_report:
type: boolean
required: false
description: "Whether to run the blob report"
permissions: {} # No permissions required
jobs:
build:
@@ -159,3 +163,4 @@ jobs:
hdiutil attach ./dist/*.dmg -mountpoint /Volumes/Element &&
rsync -a /Volumes/Element/Element*.app ~/Applications/ &&
hdiutil detach /Volumes/Element
blob_report: ${{ inputs.blob_report }}

View File

@@ -18,6 +18,10 @@ on:
type: string
required: false
description: "Command to run to prepare the executable or environment for testing"
blob_report:
type: boolean
default: false
description: "Whether to upload a blob report instead of the HTML report"
permissions: {}
jobs:
test:
@@ -63,16 +67,24 @@ jobs:
- name: Run tests
uses: coactions/setup-xvfb@6b00cf1889f4e1d5a48635647013c0508128ee1a
timeout-minutes: 5
timeout-minutes: 20
with:
run: "yarn test ${{ runner.os != 'Linux' && '--ignore-snapshots' || '' }}"
run: yarn test --project=${{ inputs.artifact }} ${{ runner.os != 'Linux' && '--ignore-snapshots' || '' }} ${{ inputs.blob_report == false && '--reporter=html' || '' }}
env:
ELEMENT_DESKTOP_EXECUTABLE: ${{ steps.executable.outputs.path }}
- name: Upload blob report
if: always() && inputs.blob_report
uses: actions/upload-artifact@v4
with:
name: blob-report-${{ inputs.artifact }}
path: blob-report
retention-days: 1
- name: Upload HTML report
if: always()
if: always() && inputs.blob_report == false
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.artifact }}-test
path: playwright/html-report
path: playwright-report
retention-days: 14

View File

@@ -30,13 +30,17 @@ on:
type: string
required: false
description: "Whether to sign & notarise the build, requires 'packages.element.io' environment"
blob_report:
type: boolean
required: false
description: "Whether to run the blob report"
permissions: {} # No permissions required
jobs:
build:
runs-on: windows-2022
runs-on: windows-2025
environment: ${{ inputs.sign && 'packages.element.io' || '' }}
env:
SIGNTOOL_PATH: "C:/Program Files (x86)/Windows Kits/10/bin/10.0.22000.0/x86/signtool.exe"
SIGNTOOL_PATH: "C:/Program Files (x86)/Windows Kits/10/bin/10.0.26100.0/x86/signtool.exe"
steps:
- uses: nbucic/variable-mapper@0673f6891a0619ba7c002ecfed0f9f4f39017b6f
id: config
@@ -220,9 +224,8 @@ jobs:
test:
needs: build
uses: ./.github/workflows/build_test.yaml
# We have no Windows ARM64 runners at this time
if: inputs.arch != 'arm64'
with:
artifact: win-${{ inputs.arch }}
runs-on: windows-2022
runs-on: ${{ inputs.arch == 'arm64' && 'windows-11-arm' || 'windows-2022' }}
executable: ./dist/win*-unpacked/Element*.exe
blob_report: ${{ inputs.blob_report }}

View File

@@ -30,7 +30,7 @@ jobs:
install: true
- name: Build test image
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6
with:
file: dockerbuild/Dockerfile
push: false
@@ -42,7 +42,7 @@ jobs:
run: docker run -v $PWD:/project element-desktop-dockerbuild yarn install
- name: Log in to the Container registry
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772
uses: docker/login-action@6d4b68b490aef8836e8fb5e50ee7b3bdfa5894f0
if: github.event_name != 'pull_request'
with:
registry: ${{ env.REGISTRY }}
@@ -61,7 +61,7 @@ jobs:
- name: Build and push Docker image
if: github.event_name != 'pull_request'
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6
with:
file: dockerbuild/Dockerfile
push: true

View File

@@ -1 +1 @@
v22.14.0
v22.15.0

View File

@@ -1,3 +1,65 @@
Changes in [1.11.101](https://github.com/element-hq/element-desktop/releases/tag/v1.11.101) (2025-05-20)
========================================================================================================
## ✨ Features
* Migrate from keytar to safeStorage ([#2227](https://github.com/element-hq/element-desktop/pull/2227)). Contributed by @t3chguy.
* New room list: add keyboard navigation support ([#29805](https://github.com/element-hq/element-web/pull/29805)). Contributed by @florianduros.
* Use the JoinRuleSettings component for the guest link access prompt. ([#28614](https://github.com/element-hq/element-web/pull/28614)). Contributed by @toger5.
* Add loading state to the new room list view ([#29725](https://github.com/element-hq/element-web/pull/29725)). Contributed by @langleyd.
* Make OIDC identity reset consistent with EX ([#29854](https://github.com/element-hq/element-web/pull/29854)). Contributed by @andybalaam.
* Support error code for email / phone adding unsupported (MSC4178) ([#29855](https://github.com/element-hq/element-web/pull/29855)). Contributed by @dbkr.
* Update identity reset UI (Make consistent with EX) ([#29701](https://github.com/element-hq/element-web/pull/29701)). Contributed by @andybalaam.
* Add secondary filters to the new room list ([#29818](https://github.com/element-hq/element-web/pull/29818)). Contributed by @dbkr.
* Fix battery drain from Web Audio ([#29203](https://github.com/element-hq/element-web/pull/29203)). Contributed by @mbachry.
## 🐛 Bug Fixes
* Fix go home shortcut on macos and change toggle action events shortcut ([#29929](https://github.com/element-hq/element-web/pull/29929)). Contributed by @florianduros.
* New room list: fix outdated message preview when space or filter change ([#29925](https://github.com/element-hq/element-web/pull/29925)). Contributed by @florianduros.
* Stop migrating to MSC4278 if the config exists. ([#29924](https://github.com/element-hq/element-web/pull/29924)). Contributed by @Half-Shot.
* Ensure consistent download file name on download from ImageView ([#29913](https://github.com/element-hq/element-web/pull/29913)). Contributed by @t3chguy.
* Add error toast when service worker registration fails ([#29895](https://github.com/element-hq/element-web/pull/29895)). Contributed by @t3chguy.
* New Room List: Prevent old tombstoned rooms from appearing in the list ([#29881](https://github.com/element-hq/element-web/pull/29881)). Contributed by @MidhunSureshR.
* Remove lag in search field ([#29885](https://github.com/element-hq/element-web/pull/29885)). Contributed by @florianduros.
* Respect UIFeature.Voip ([#29873](https://github.com/element-hq/element-web/pull/29873)). Contributed by @langleyd.
* Allow jumping to message search from spotlight ([#29850](https://github.com/element-hq/element-web/pull/29850)). Contributed by @t3chguy.
Changes in [1.11.100](https://github.com/element-hq/element-desktop/releases/tag/v1.11.100) (2025-05-06)
========================================================================================================
## ✨ Features
* Move rich topics out of labs / stabilise MSC3765 ([#29817](https://github.com/element-hq/element-web/pull/29817)). Contributed by @Johennes.
* Spell out that Element Web does \*not\* work on mobile. ([#29211](https://github.com/element-hq/element-web/pull/29211)). Contributed by @ara4n.
* Add message preview support to the new room list ([#29784](https://github.com/element-hq/element-web/pull/29784)). Contributed by @dbkr.
* Global configuration flag for media previews ([#29582](https://github.com/element-hq/element-web/pull/29582)). Contributed by @Half-Shot.
* New room list: add partial keyboard shortcuts support ([#29783](https://github.com/element-hq/element-web/pull/29783)). Contributed by @florianduros.
* MVVM RoomSummaryCard Topic ([#29710](https://github.com/element-hq/element-web/pull/29710)). Contributed by @MarcWadai.
* Warn on self change from settings > roles ([#28926](https://github.com/element-hq/element-web/pull/28926)). Contributed by @MarcWadai.
* New room list: new visual for invitation ([#29773](https://github.com/element-hq/element-web/pull/29773)). Contributed by @florianduros.
## 🐛 Bug Fixes
* Apply workaround to fix app launching on Linux ([#2308](https://github.com/element-hq/element-desktop/pull/2308)). Contributed by @dbkr.
* Notification fixes for Windows - AppID name was messing up handler ([#2275](https://github.com/element-hq/element-desktop/pull/2275)). Contributed by @Fusseldieb.
* Fix incorrect display of the user info display name ([#29826](https://github.com/element-hq/element-web/pull/29826)). Contributed by @langleyd.
* RoomListStore: Remove invite rooms on decline ([#29804](https://github.com/element-hq/element-web/pull/29804)). Contributed by @MidhunSureshR.
* Fix the buttons not being displayed with long preview text ([#29811](https://github.com/element-hq/element-web/pull/29811)). Contributed by @dbkr.
* New room list: fix missing/incorrect notification decoration ([#29796](https://github.com/element-hq/element-web/pull/29796)). Contributed by @florianduros.
* New Room List: Prevent potential scroll jump/flicker when switching spaces ([#29781](https://github.com/element-hq/element-web/pull/29781)). Contributed by @MidhunSureshR.
* New room list: fix incorrect decoration ([#29770](https://github.com/element-hq/element-web/pull/29770)). Contributed by @florianduros.
Changes in [1.11.99](https://github.com/element-hq/element-desktop/releases/tag/v1.11.99) (2025-04-23)
======================================================================================================
## 🐛 Bug Fixes
* [Backport staging] Fix `io.element.desktop` protocol handler ([#2281](https://github.com/element-hq/element-desktop/pull/2281)). Contributed by @RiotRobot.
Changes in [1.11.98](https://github.com/element-hq/element-desktop/releases/tag/v1.11.98) (2025-04-22)
======================================================================================================
## 🦖 Deprecations

View File

@@ -2,10 +2,11 @@
- [Introduction](../README.md)
# Build
# Build/Debug
- [Native Node modules](native-node-modules.md)
- [Windows requirements](windows-requirements.md)
- [Using gdb](gdb.md)
# Distribution

46
docs/gdb.md Normal file
View File

@@ -0,0 +1,46 @@
# Using gdb against Element-Desktop
Occasionally it is useful to be able to connect to a running Element-Desktop
with [`gdb`](https://sourceware.org/gdb/), or to analayze a coredump. For this,
you will need debug symbols.
1. If you don't already have the right version of Element-Desktop (eg because
you are analyzing someone else's coredump), download and unpack the tarball
from https://packages.element.io/desktop/install/linux/. If it was a
nightly, your best bet may be to download the deb from
https://packages.element.io/debian/pool/main/e/element-nightly/ and unpack
it.
2. Figure out which version of Electron your Element-Desktop is based on. The
best way to do this is to figure out the version of Element-Desktop, then
look at
[`yarn.lock`](https://github.com/element-hq/element-desktop/blob/develop/yarn.lock)
for the corresponding version. There should be an entry starting
`electron@`, and under it a `version` line: this will tell you the version
of Electron that was used for that version of Element-Desktop.
3. Go to [Electron's releases page](https://github.com/electron/electron/releases/)
and find the version you just identified. Under "Assets", download
`electron-v<version>-linux-x64-debug.zip` (or, the -debug zip corresponding to your
architecture).
4. The debug zip has a structure like:
```
.
├── debug
│   ├── chrome_crashpad_handler.debug
│   ├── electron.debug
│   ├── libEGL.so.debug
│   ├── libffmpeg.so.debug
│   ├── libGLESv2.so.debug
│   └── libvk_swiftshader.so.debug
├── LICENSE
├── LICENSES.chromium.html
└── version
```
Take all the contents of `debug`, and copy them into the Element-Desktop directory,
so that `electron.debug` is alongside the `element-desktop-nightly` executable.
5. You now have a thing you can gdb as normal, either as `gdb --args element-desktop-nightly`, or
`gdb element-desktop-nightly core`.

View File

@@ -1,10 +1,6 @@
import * as os from "node:os";
import * as fs from "node:fs";
import * as path from "node:path";
import * as plist from "plist";
import { AfterPackContext, Arch, Configuration as BaseConfiguration, Platform } from "electron-builder";
import { computeData } from "app-builder-lib/out/asar/integrity";
import { readFile, writeFile } from "node:fs/promises";
import { Configuration as BaseConfiguration } from "electron-builder";
/**
* This script has different outputs depending on your os platform.
@@ -46,26 +42,6 @@ interface Configuration extends BaseConfiguration {
} & BaseConfiguration["deb"];
}
async function injectAsarIntegrity(context: AfterPackContext) {
const packager = context.packager;
// We only need to re-generate asar on universal Mac builds, due to https://github.com/electron/universal/issues/116
if (packager.platform !== Platform.MAC || context.arch !== Arch.universal) return;
const resourcesPath = packager.getResourcesDir(context.appOutDir);
const asarIntegrity = await computeData({
resourcesPath,
resourcesRelativePath: "Resources",
resourcesDestinationPath: resourcesPath,
extraResourceMatchers: [],
});
const plistPath = path.join(resourcesPath, "..", "Info.plist");
const data = plist.parse(await readFile(plistPath, "utf8")) as unknown as Writable<plist.PlistObject>;
data["ElectronAsarIntegrity"] = asarIntegrity as unknown as Writable<plist.PlistValue>;
await writeFile(plistPath, plist.build(data));
}
/**
* @type {import('electron-builder').Configuration}
* @see https://www.electron.build/configuration/configuration
@@ -90,9 +66,6 @@ const config: Omit<Writable<Configuration>, "electronFuses"> & {
loadBrowserProcessSpecificV8Snapshot: false,
enableEmbeddedAsarIntegrityValidation: true,
},
afterPack: async (context: AfterPackContext) => {
await injectAsarIntegrity(context);
},
files: [
"package.json",
{
@@ -154,6 +127,7 @@ const config: Omit<Writable<Configuration>, "electronFuses"> & {
entitlements: "./build/entitlements.mac.plist",
icon: "build/icons/icon.icns",
mergeASARs: true,
x64ArchFiles: "**/matrix-seshat/*.node", // hak already runs lipo
},
win: {
target: ["squirrel", "msi"],

View File

@@ -3,7 +3,7 @@
"productName": "Element",
"main": "lib/electron-main.js",
"exports": "./lib/electron-main.js",
"version": "1.11.98",
"version": "1.11.101",
"description": "Element: the future of secure communication",
"author": "Element",
"homepage": "https://element.io",
@@ -75,21 +75,21 @@
"@babel/preset-env": "^7.18.10",
"@babel/preset-typescript": "^7.18.6",
"@electron/asar": "3.4.1",
"@playwright/test": "1.51.1",
"@playwright/test": "1.52.0",
"@stylistic/eslint-plugin": "^4.0.0",
"@types/auto-launch": "^5.0.1",
"@types/counterpart": "^0.18.1",
"@types/minimist": "^1.2.1",
"@types/node": "18.19.84",
"@types/node": "18.19.87",
"@types/pacote": "^11.1.1",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
"app-builder-lib": "26.0.12",
"app-builder-lib": "26.0.15",
"chokidar": "^4.0.0",
"detect-libc": "^2.0.0",
"electron": "35.1.4",
"electron-builder": "26.0.12",
"electron-builder-squirrel-windows": "26.0.12",
"electron": "36.0.0",
"electron-builder": "26.0.15",
"electron-builder-squirrel-windows": "26.0.15",
"electron-devtools-installer": "^4.0.0",
"eslint": "^8.26.0",
"eslint-config-google": "^0.14.0",
@@ -105,18 +105,18 @@
"matrix-web-i18n": "^3.2.1",
"mkdirp": "^3.0.0",
"pacote": "^21.0.0",
"plist": "^3.1.0",
"prettier": "^3.0.0",
"rimraf": "^6.0.0",
"tar": "^7.0.0",
"tsx": "^4.19.2",
"typescript": "5.8.2"
"typescript": "5.8.3"
},
"hakDependencies": {
"matrix-seshat": "^4.0.1"
},
"resolutions": {
"@types/node": "18.19.84",
"config-file-ts": "0.2.8-rc1"
"@types/node": "18.19.87",
"config-file-ts": "0.2.8-rc1",
"node-abi": "4.4.0"
}
}

View File

@@ -8,7 +8,25 @@ Please see LICENSE files in the repository root for full details.
import { defineConfig } from "@playwright/test";
const projects = [
"macos",
"win-x64",
"win-ia32",
"win-arm64",
"linux-amd64-sqlcipher-system",
"linux-amd64-sqlcipher-static",
"linux-arm64-sqlcipher-system",
"linux-arm64-sqlcipher-static",
];
export default defineConfig({
// Allows the GitHub action to specify a project name (OS + arch) for the combined report to make sense
// workaround for https://github.com/microsoft/playwright/issues/33521
projects: process.env.CI
? projects.map((name) => ({
name,
}))
: undefined,
use: {
viewport: { width: 1280, height: 720 },
video: "retain-on-failure",
@@ -18,7 +36,7 @@ export default defineConfig({
outputDir: "playwright/test-results",
workers: 1,
retries: process.env.CI ? 2 : 0,
reporter: [["html", { outputFolder: "playwright/html-report" }]],
reporter: process.env.CI ? [["blob"], ["github"]] : [["html", { outputFolder: "playwright/html-report" }]],
snapshotDir: "playwright/snapshots",
snapshotPathTemplate: "{snapshotDir}/{testFilePath}/{arg}-{platform}{ext}",
timeout: 30 * 1000,

View File

@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/playwright:v1.51.1-jammy
FROM mcr.microsoft.com/playwright:v1.52.0-jammy
WORKDIR /work/element-desktop

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { platform } from "node:os";
import keytar from "keytar-forked";
import { test, expect } from "../../element-desktop-test.js";
@@ -17,6 +17,7 @@ declare global {
supportsEventIndexing(): Promise<boolean>;
}
| undefined;
getPickleKey(userId: string, deviceId: string): Promise<string | null>;
createPickleKey(userId: string, deviceId: string): Promise<string | null>;
}
@@ -48,14 +49,46 @@ test.describe("App launch", () => {
).resolves.toBeTruthy();
});
test("should launch and render the welcome view successfully and support keytar", async ({ page }) => {
test.skip(platform() === "linux", "This test does not yet support Linux");
test.describe("safeStorage", () => {
const userId = "@user:server";
const deviceId = "ABCDEF";
await expect(
page.evaluate<string | null>(async () => {
return await window.mxPlatformPeg.get().createPickleKey("@user:server", "ABCDEF");
}),
).resolves.not.toBeNull();
test("should be supported", async ({ page }) => {
await expect(
page.evaluate(
([userId, deviceId]) => window.mxPlatformPeg.get().createPickleKey(userId, deviceId),
[userId, deviceId],
),
).resolves.not.toBeNull();
});
test.describe("migrate from keytar", () => {
test.skip(
process.env.GITHUB_ACTIONS && ["linux", "darwin"].includes(process.platform),
"GitHub Actions hosted runner are not a compatible environment for this test",
);
const pickleKey = "DEADBEEF1234";
const keytarService = "element.io";
const keytarKey = `${userId}|${deviceId}`;
test.beforeAll(async () => {
await keytar.setPassword(keytarService, keytarKey, pickleKey);
await expect(keytar.getPassword(keytarService, keytarKey)).resolves.toBe(pickleKey);
});
test.afterAll(async () => {
await keytar.deletePassword(keytarService, keytarKey);
});
test("should migrate successfully", async ({ page }) => {
await expect(
page.evaluate(
([userId, deviceId]) => window.mxPlatformPeg.get().getPickleKey(userId, deviceId),
[userId, deviceId],
),
).resolves.toBe(pickleKey);
});
});
});
test.describe("--no-update", () => {

View File

@@ -62,12 +62,21 @@ export const test = base.extend<Fixtures>({
// eslint-disable-next-line no-empty-pattern
tmpDir: async ({}, use) => {
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "element-desktop-tests-"));
console.log("Using temp profile directory: ", tmpDir);
await use(tmpDir);
await fs.rm(tmpDir, { recursive: true });
},
app: async ({ tmpDir, extraEnv, extraArgs, stdout, stderr }, use) => {
const args = ["--profile-dir", tmpDir];
const args = ["--profile-dir", tmpDir, ...extraArgs];
if (process.env.GITHUB_ACTIONS) {
if (process.platform === "linux") {
// GitHub Actions hosted runner lacks dbus and a compatible keyring, so we need to force plaintext storage
args.push("--storage-mode", "force-plaintext");
} else if (process.platform === "darwin") {
// GitHub Actions hosted runner has no working default keychain, so allow plaintext storage
args.push("--storage-mode", "allow-plaintext");
}
}
const executablePath = process.env["ELEMENT_DESKTOP_EXECUTABLE"];
if (!executablePath) {
@@ -75,13 +84,15 @@ export const test = base.extend<Fixtures>({
args.unshift(path.join(__dirname, "..", "lib", "electron-main.js"));
}
console.log(`Launching '${executablePath}' with args ${args.join(" ")}`);
const app = await electron.launch({
env: {
...process.env,
...extraEnv,
},
executablePath,
args: [...args, ...extraArgs],
args,
});
app.process().stdout.pipe(stdout).pipe(process.stdout);

View File

@@ -8,7 +8,7 @@
"module": "node16",
"sourceMap": false,
"strict": true,
"lib": ["es2020"]
"lib": ["es2021"]
},
"include": ["../src/@types", "./**/*.ts"]
}

View File

@@ -7,7 +7,6 @@ Please see LICENSE files in the repository root for full details.
import { type BrowserWindow } from "electron";
import type Store from "electron-store";
import type AutoLaunch from "auto-launch";
import { type AppLocalization } from "../language-helper.js";
@@ -24,13 +23,5 @@ declare global {
icon_path: string;
brand: string;
};
var store: Store<{
warnBeforeExit?: boolean;
minimizeToTray?: boolean;
spellCheckerEnabled?: boolean;
autoHideMenuBar?: boolean;
locale?: string | string[];
disableHardwareAcceleration?: boolean;
}>;
}
/* eslint-enable no-var */

View File

@@ -16,7 +16,6 @@ import * as Sentry from "@sentry/electron/main";
import AutoLaunch from "auto-launch";
import path, { dirname } from "node:path";
import windowStateKeeper from "electron-window-state";
import Store from "electron-store";
import fs, { promises as afs } from "node:fs";
import { URL, fileURLToPath } from "node:url";
import minimist from "minimist";
@@ -25,6 +24,7 @@ import "./ipc.js";
import "./seshat.js";
import "./settings.js";
import * as tray from "./tray.js";
import Store from "./store.js";
import { buildMenuTemplate } from "./vectormenu.js";
import webContentsHandler from "./webcontents-handler.js";
import * as updater from "./updater.js";
@@ -273,8 +273,6 @@ async function moveAutoLauncher(): Promise<void> {
}
}
global.store = new Store({ name: "electron-config" });
global.appQuitting = false;
const exitShortcuts: Array<(input: Input, platform: string) => boolean> = [
@@ -284,32 +282,6 @@ const exitShortcuts: Array<(input: Input, platform: string) => boolean> = [
platform === "darwin" && input.meta && !input.control && input.key.toUpperCase() === "Q",
];
const warnBeforeExit = (event: Event, input: Input): void => {
const shouldWarnBeforeExit = global.store.get("warnBeforeExit", true);
const exitShortcutPressed =
input.type === "keyDown" && exitShortcuts.some((shortcutFn) => shortcutFn(input, process.platform));
if (shouldWarnBeforeExit && exitShortcutPressed && global.mainWindow) {
const shouldCancelCloseRequest =
dialog.showMessageBoxSync(global.mainWindow, {
type: "question",
buttons: [
_t("action|cancel"),
_t("action|close_brand", {
brand: global.vectorConfig.brand || "Element",
}),
],
message: _t("confirm_quit"),
defaultId: 1,
cancelId: 0,
}) === 0;
if (shouldCancelCloseRequest) {
event.preventDefault();
}
}
};
void configureSentry();
// handle uncaught errors otherwise it displays
@@ -326,6 +298,11 @@ app.commandLine.appendSwitch("--enable-usermedia-screen-capturing");
if (!app.commandLine.hasSwitch("enable-features")) {
app.commandLine.appendSwitch("enable-features", "WebRTCPipeWireCapturer");
}
// Workaround bug in electron 36:https://github.com/electron/electron/issues/46538
// Hopefully this will no longer be needed soon and can be removed
if (process.platform === "linux") {
app.commandLine.appendSwitch("gtk-version", "3");
}
const gotLock = app.requestSingleInstanceLock();
if (!gotLock) {
@@ -366,13 +343,17 @@ app.enableSandbox();
// We disable media controls here. We do this because calls use audio and video elements and they sometimes capture the media keys. See https://github.com/vector-im/element-web/issues/15704
app.commandLine.appendSwitch("disable-features", "HardwareMediaKeyHandling,MediaSessionService");
const store = Store.initialize(argv["storage-mode"]); // must be called before any async actions
// Disable hardware acceleration if the setting has been set.
if (global.store.get("disableHardwareAcceleration", false) === true) {
if (store.get("disableHardwareAcceleration")) {
console.log("Disabling hardware acceleration.");
app.disableHardwareAcceleration();
}
app.on("ready", async () => {
console.debug("Reached Electron ready state");
let asarPath: string;
try {
@@ -462,12 +443,27 @@ app.on("ready", async () => {
console.log("No update_base_url is defined: auto update is disabled");
}
// Set up i18n before loading storage as we need translations for dialogs
global.appLocalization = new AppLocalization({
components: [(): void => tray.initApplicationMenu(), (): void => Menu.setApplicationMenu(buildMenuTemplate())],
store,
});
try {
console.debug("Ensuring storage is ready");
await store.safeStorageReady();
} catch (e) {
console.error(e);
app.exit(1);
}
// Load the previous window state with fallback to defaults
const mainWindowState = windowStateKeeper({
defaultWidth: 1024,
defaultHeight: 768,
});
console.debug("Opening main window");
const preloadScript = path.normalize(`${__dirname}/preload.cjs`);
global.mainWindow = new BrowserWindow({
// https://www.electronjs.org/docs/faq#the-font-looks-blurry-what-is-this-and-what-can-i-do
@@ -478,7 +474,7 @@ app.on("ready", async () => {
icon: global.trayConfig.icon_path,
show: false,
autoHideMenuBar: global.store.get("autoHideMenuBar", true),
autoHideMenuBar: store.get("autoHideMenuBar"),
x: mainWindowState.x,
y: mainWindowState.y,
@@ -500,10 +496,10 @@ app.on("ready", async () => {
// Handle spellchecker
// For some reason spellCheckerEnabled isn't persisted, so we have to use the store here
global.mainWindow.webContents.session.setSpellCheckerEnabled(global.store.get("spellCheckerEnabled", true));
global.mainWindow.webContents.session.setSpellCheckerEnabled(store.get("spellCheckerEnabled", true));
// Create trayIcon icon
if (global.store.get("minimizeToTray", true)) tray.create(global.trayConfig);
if (store.get("minimizeToTray")) tray.create(global.trayConfig);
global.mainWindow.once("ready-to-show", () => {
if (!global.mainWindow) return;
@@ -517,7 +513,31 @@ app.on("ready", async () => {
}
});
global.mainWindow.webContents.on("before-input-event", warnBeforeExit);
global.mainWindow.webContents.on("before-input-event", (event: Event, input: Input): void => {
const shouldWarnBeforeExit = store.get("warnBeforeExit", true);
const exitShortcutPressed =
input.type === "keyDown" && exitShortcuts.some((shortcutFn) => shortcutFn(input, process.platform));
if (shouldWarnBeforeExit && exitShortcutPressed && global.mainWindow) {
const shouldCancelCloseRequest =
dialog.showMessageBoxSync(global.mainWindow, {
type: "question",
buttons: [
_t("action|cancel"),
_t("action|close_brand", {
brand: global.vectorConfig.brand || "Element",
}),
],
message: _t("confirm_quit"),
defaultId: 1,
cancelId: 0,
}) === 0;
if (shouldCancelCloseRequest) {
event.preventDefault();
}
}
});
global.mainWindow.on("closed", () => {
global.mainWindow = null;
@@ -555,11 +575,6 @@ app.on("ready", async () => {
webContentsHandler(global.mainWindow.webContents);
global.appLocalization = new AppLocalization({
store: global.store,
components: [(): void => tray.initApplicationMenu(), (): void => Menu.setApplicationMenu(buildMenuTemplate())],
});
session.defaultSession.setDisplayMediaRequestHandler((_, callback) => {
global.mainWindow?.webContents.send("openDesktopCapturerSourcePicker");
setDisplayMediaCallback(callback);
@@ -596,8 +611,9 @@ app.on("second-instance", (ev, commandLine, workingDirectory) => {
}
});
// Set the App User Model ID to match what the squirrel
// installer uses for the shortcut icon.
// This makes notifications work on windows 8.1 (and is
// a noop on other platforms).
app.setAppUserModelId("com.squirrel.element-desktop.Element");
// This is required to make notification handlers work
// on Windows 8.1/10/11 (and is a noop on other platforms);
// It must also match the ID found in 'electron-builder'
// in order to get the title and icon to show up correctly.
// Ref: https://stackoverflow.com/a/77314604/3525780
app.setAppUserModelId("im.riot.app");

View File

@@ -22,7 +22,9 @@
"about": "O",
"brand_help": "%(brand)s nápověda",
"help": "Nápověda",
"preferences": "Předvolby"
"no": "Ne",
"preferences": "Předvolby",
"yes": "Ano"
},
"confirm_quit": "Opravdu chcete ukončit aplikaci?",
"edit_menu": {
@@ -49,6 +51,20 @@
"save_image_as_error_description": "Obrázek se nepodařilo uložit",
"save_image_as_error_title": "Chyba při ukládání obrázku"
},
"store": {
"error": {
"backend_changed": "Vymazat data a znovu načíst?",
"backend_changed_detail": "Nelze získat přístup k tajnému klíči ze systémové klíčenky, zdá se, že se změnil.",
"backend_changed_title": "Nepodařilo se načíst databázi",
"unknown_backend_override": "Váš systém má nepodporovanou klíčenku, což znamená, že databázi nelze otevřít.",
"unknown_backend_override_details": "Další podrobnosti naleznete v protokolech.",
"unknown_backend_override_title": "Nepodařilo se načíst databázi",
"unsupported_keyring": "Váš systém má nepodporovanou klíčenku, což znamená, že databázi nelze otevřít.",
"unsupported_keyring_cta": "Používat slabší šifrování",
"unsupported_keyring_detail": "Detekce klíčenky Electronu nenalezla podporovaný backend. Můžete se pokusit ručně nakonfigurovat backend spuštěním %(brand)s s argumentem příkazového řádku, jednorázovou operací. Viz %(link)s.",
"unsupported_keyring_title": "Systém není podporován"
}
},
"view_menu": {
"actual_size": "Aktuální velikost",
"toggle_developer_tools": "Přepnout zobrazení nástrojů pro vývojáře",

View File

@@ -22,7 +22,9 @@
"about": "Über",
"brand_help": "%(brand)s Hilfe",
"help": "Hilfe",
"preferences": "Präferenzen"
"no": "Nein",
"preferences": "Präferenzen",
"yes": "Ja"
},
"confirm_quit": "Wirklich beenden?",
"edit_menu": {
@@ -49,6 +51,20 @@
"save_image_as_error_description": "Das Bild konnte nicht gespeichert werden",
"save_image_as_error_title": "Bild kann nicht gespeichert werden"
},
"store": {
"error": {
"backend_changed": "Daten löschen und neu laden?",
"backend_changed_detail": "Zugriff auf Schlüssel im Systemschlüsselbund nicht möglich, er scheint sich geändert zu haben.",
"backend_changed_title": "Datenbank konnte nicht geladen werden",
"unknown_backend_override": "Der Schlüsselbund ihres Systems wird nicht unterstützt, wodurch die Datenbank nicht geöffnet werden kann.",
"unknown_backend_override_details": "Weitere Informationen finden Sie in den Protokollen.",
"unknown_backend_override_title": "Die Datenbank konnte nicht geladen werden",
"unsupported_keyring": "Der Schlüsselbund ihres Systems wird nicht unterstützt, wodurch die Datenbank nicht geöffnet werden kann.",
"unsupported_keyring_cta": "Schwächere Verschlüsselung verwenden",
"unsupported_keyring_detail": "Die Schlüsselbunderkennung von Electron hat kein unterstütztes Backend gefunden. Möglicherweise können sie dennoch den ihres Systemes verwenden. Infos unter %(link)s.",
"unsupported_keyring_title": "System nicht unterstützt"
}
},
"view_menu": {
"actual_size": "Tatsächliche Größe",
"toggle_developer_tools": "Developer-Tools an/aus",

View File

@@ -22,7 +22,9 @@
"about": "About",
"brand_help": "%(brand)s Help",
"help": "Help",
"preferences": "Preferences"
"no": "No",
"preferences": "Preferences",
"yes": "Yes"
},
"confirm_quit": "Are you sure you want to quit?",
"edit_menu": {
@@ -49,6 +51,21 @@
"save_image_as_error_description": "The image failed to save",
"save_image_as_error_title": "Failed to save image"
},
"store": {
"error": {
"backend_changed": "Clear data and reload?",
"backend_changed_detail": "Unable to access secret from system keyring, it appears to have changed.",
"backend_changed_title": "Failed to load database",
"backend_no_encryption": "Your system has a supported keyring but encryption is not available.",
"backend_no_encryption_detail": "Electron has detected that encryption is not available on your keyring %(backend)s. Please ensure that you have the keyring installed. If you do have the keyring installed, please reboot and try again. Optionally, you can allow %(brand)s to use a weaker form of encryption.",
"backend_no_encryption_title": "No encryption support",
"unsupported_keyring": "Your system has an unsupported keyring meaning the database cannot be opened.",
"unsupported_keyring_detail": "Electron's keyring detection did not find a supported backend. You can attempt to manually configure the backend by starting %(brand)s with a command-line argument, a one-time operation. See %(link)s.",
"unsupported_keyring_title": "System unsupported",
"unsupported_keyring_use_basic_text": "Use weaker encryption",
"unsupported_keyring_use_plaintext": "Use no encryption"
}
},
"view_menu": {
"actual_size": "Actual Size",
"toggle_developer_tools": "Toggle Developer Tools",

View File

@@ -22,7 +22,9 @@
"about": "Rakenduse teave",
"brand_help": "%(brand)s abiteave",
"help": "Abiteave",
"preferences": "Eelistused"
"no": "Ei",
"preferences": "Eelistused",
"yes": "Jah"
},
"confirm_quit": "Kas sa kindlasti soovid rakendusest väljuda?",
"edit_menu": {
@@ -49,6 +51,20 @@
"save_image_as_error_description": "Seda pilti ei õnnestunud salvestada",
"save_image_as_error_title": "Pildi salvestamine ei õnnestunud"
},
"store": {
"error": {
"backend_changed": "Kas kustutame andmed ja laadime uuesti?",
"backend_changed_detail": "Süsteemsest võtmerõngast ei õnnestu laadida vajalikku saladust, tundub et ta on muutunud.",
"backend_changed_title": "Andmebaasi ei õnnestunud laadida",
"unknown_backend_override": "Sinu süsteemis on kasutusel mittetoetatud võtmerõnga versioon ning see tähendab, et andmebaasi ei saa avada.",
"unknown_backend_override_details": "Lisateavet leiad logidest.",
"unknown_backend_override_title": "Andmebaasi ei õnnestunud laadida",
"unsupported_keyring": "Sinu süsteemis on kasutusel mittetoetatud võtmerõnga versioon ning see tähendab, et andmebaasi ei saa avada.",
"unsupported_keyring_cta": "Kasuta nõrgemat krüptimist",
"unsupported_keyring_detail": "Electroni võtmerõnga tuvastamine ei leidnud toetatud taustateenust. Kui käivitad rakenduse %(brand)s käsurealt õigete argumentidega, siis võib taustateenuse käsitsi seadistamine õnnestuda ning seda tegevust peaksid vaid üks kord tegema. Lisateave: %(link)s.",
"unsupported_keyring_title": "Süsteem pole toetatud"
}
},
"view_menu": {
"actual_size": "Näita tavasuuruses",
"toggle_developer_tools": "Arendaja töövahendid sisse/välja",

View File

@@ -22,7 +22,9 @@
"about": "À propos",
"brand_help": "Aide de %(brand)s",
"help": "Aide",
"preferences": "Préférences"
"no": "Non",
"preferences": "Préférences",
"yes": "Oui"
},
"confirm_quit": "Êtes-vous sûr de vouloir quitter ?",
"edit_menu": {
@@ -49,6 +51,20 @@
"save_image_as_error_description": "Limage na pas pu être sauvegardée",
"save_image_as_error_title": "Échec de la sauvegarde de limage"
},
"store": {
"error": {
"backend_changed": "Effacer les données et recharger ?",
"backend_changed_detail": "Impossible d'accéder aux secrets depuis le trousseau de clés du système, il semble avoir changé.",
"backend_changed_title": "Impossible de charger la base de données",
"unknown_backend_override": "Votre système possède un trousseau de clés non pris en charge, ce qui signifie que la base de données ne peut pas être ouverte.",
"unknown_backend_override_details": "Veuillez consulter les journaux pour plus de détails.",
"unknown_backend_override_title": "Impossible de charger la base de données",
"unsupported_keyring": "Votre système possède un trousseau de clés non pris en charge, la base de données ne peut pas être ouverte.",
"unsupported_keyring_cta": "Utiliser un chiffrement plus faible",
"unsupported_keyring_detail": "La détection du porte-clés par Electron n'a pas permis de trouver de backend compatible. Vous pouvez essayer de configurer manuellement le backend en utilisant %(brand)s avec un argument de ligne de commande. Cette opération doit être effectuer une seule fois. Voir%(link)s.",
"unsupported_keyring_title": "Système non pris en charge"
}
},
"view_menu": {
"actual_size": "Taille réelle",
"toggle_developer_tools": "Basculer les outils de développement",

View File

@@ -22,7 +22,9 @@
"about": "Névjegy",
"brand_help": "%(brand)s Súgó",
"help": "Súgó",
"preferences": "Beállítások"
"no": "Nem",
"preferences": "Beállítások",
"yes": "Igen"
},
"confirm_quit": "Biztos, hogy kilép?",
"edit_menu": {
@@ -49,6 +51,20 @@
"save_image_as_error_description": "A kép mentése sikertelen",
"save_image_as_error_title": "Kép mentése sikertelen"
},
"store": {
"error": {
"backend_changed": "Adatok törlése és újratöltés?",
"backend_changed_detail": "Nem sikerült hozzáférni a rendszerkulcstartó titkos kódjához, úgy tűnik, megváltozott.",
"backend_changed_title": "Nem sikerült betölteni az adatbázist",
"unknown_backend_override": "A rendszer nem támogatott kulcstartóval rendelkezik, ami azt jelenti, hogy az adatbázis nem nyitható meg.",
"unknown_backend_override_details": "További részletekért ellenőrizze a naplókat.",
"unknown_backend_override_title": "Nem sikerült betölteni az adatbázist",
"unsupported_keyring": "A rendszer nem támogatott kulcstartóval rendelkezik, ami azt jelenti, hogy az adatbázis nem nyitható meg.",
"unsupported_keyring_cta": "Gyengébb titkosítás használata",
"unsupported_keyring_detail": "Az Electron kulcstartóészlelése nem talált támogatott háttérrendszert. Megpróbálhatja kézileg beállítani a háttérrendszert az %(brand)s egyszeri, parancssori argumentummal való indításával. Lásd: %(link)s.",
"unsupported_keyring_title": "A rendszer nem támogatott"
}
},
"view_menu": {
"actual_size": "Jelenlegi méret",
"toggle_developer_tools": "Fejlesztői eszközök",

View File

@@ -22,7 +22,9 @@
"about": "Tentang",
"brand_help": "Bantuan %(brand)s",
"help": "Bantuan",
"preferences": "Preferensi"
"no": "Tidak",
"preferences": "Preferensi",
"yes": "Ya"
},
"confirm_quit": "Apakah Anda yakin ingin keluar?",
"edit_menu": {
@@ -49,6 +51,20 @@
"save_image_as_error_description": "Gambar gagal disimpan",
"save_image_as_error_title": "Gagal menyimpan gambar"
},
"store": {
"error": {
"backend_changed": "Hapus data dan muat ulang?",
"backend_changed_detail": "Tidak dapat mengakses rahasia dari keyring sistem, tampaknya telah berubah.",
"backend_changed_title": "Gagal memuat basis data",
"unknown_backend_override": "Sistem Anda memiliki keyring yang tidak didukung yang berarti basis data tidak dapat dibuka.",
"unknown_backend_override_details": "Silakan periksa log untuk detail lebih lanjut.",
"unknown_backend_override_title": "Gagal memuat basis data",
"unsupported_keyring": "Sistem Anda memiliki keyring yang tidak didukung yang berarti basis data tidak dapat dibuka.",
"unsupported_keyring_cta": "Gunakan enkripsi yang lebih lemah",
"unsupported_keyring_detail": "Deteksi keyring Electron tidak menemukan backend yang didukung. Anda dapat mencoba mengonfigurasi backend secara manual dengan memulai %(brand)s dengan argumen baris perintah, operasi satu kali. Lihat %(link)s.",
"unsupported_keyring_title": "Sistem tidak didukung"
}
},
"view_menu": {
"actual_size": "Ukuran Sebenarnya",
"toggle_developer_tools": "Beralih Alat Pengembang",

View File

@@ -22,7 +22,9 @@
"about": "Om",
"brand_help": "%(brand)s Hjelp",
"help": "Hjelp",
"preferences": "Brukervalg"
"no": "Nei",
"preferences": "Brukervalg",
"yes": "Ja"
},
"confirm_quit": "Er du sikker på at du vil slutte?",
"edit_menu": {
@@ -49,6 +51,20 @@
"save_image_as_error_description": "Bildet kunne ikke lagres",
"save_image_as_error_title": "Kunne ikke lagre bildet"
},
"store": {
"error": {
"backend_changed": "Tøm data og last inn på nytt?",
"backend_changed_detail": "Kan ikke få tilgang til hemmeligheten fra systemnøkkelringen, den ser ut til å ha blitt endret.",
"backend_changed_title": "Kunne ikke laste inn databasen",
"unknown_backend_override": "Systemet ditt har en nøkkelring som ikke støttes, noe som betyr at databasen ikke kan åpnes.",
"unknown_backend_override_details": "Vennligst sjekk loggene for mer informasjon.",
"unknown_backend_override_title": "Kunne ikke laste inn databasen",
"unsupported_keyring": "Systemet ditt har en nøkkelring som ikke støttes, noe som betyr at databasen ikke kan åpnes.",
"unsupported_keyring_cta": "Bruk svakere kryptering",
"unsupported_keyring_detail": "Electrons nøkkelringdeteksjon fant ikke en støttet backend. Du kan prøve å konfigurere backend manuelt ved å starte %(brand)s med et kommandolinjeargument, en engangsoperasjon. Se%(link)s.",
"unsupported_keyring_title": "Systemet støttes ikke"
}
},
"view_menu": {
"actual_size": "Faktisk størrelse",
"toggle_developer_tools": "Veksle Utvikleralternativer",

View File

@@ -22,7 +22,9 @@
"about": "Informacje",
"brand_help": "Pomoc %(brand)s",
"help": "Pomoc",
"preferences": "Preferencje"
"no": "Nie",
"preferences": "Preferencje",
"yes": "Tak"
},
"confirm_quit": "Czy na pewno chcesz zamknąć?",
"edit_menu": {
@@ -49,6 +51,20 @@
"save_image_as_error_description": "Obraz nie został zapisany",
"save_image_as_error_title": "Nie udało się zapisać obrazu"
},
"store": {
"error": {
"backend_changed": "Wyczyścić dane i przeładować?",
"backend_changed_detail": "Nie można uzyskać dostępu do sekretnego magazynu, wygląda na to, że uległ zmianie.",
"backend_changed_title": "Nie udało się załadować bazy danych",
"unknown_backend_override": "System zawiera niewspierany keyring, nie można otworzyć bazy danych.",
"unknown_backend_override_details": "Sprawdź dziennik, aby uzyskać więcej informacji.",
"unknown_backend_override_title": "Nie udało się załadować bazy danych",
"unsupported_keyring": "System zawiera niewspierany keyring, nie można otworzyć bazy danych.",
"unsupported_keyring_cta": "Użyj słabszego szyfrowania",
"unsupported_keyring_detail": "Wykrywanie keyringu Electron nie znalazł wspieranego backendu. Możesz spróbować ręcznie ustawić backed, uruchamiając %(brand)s za pomocą wiesza poleceń. Zobacz %(link)s.",
"unsupported_keyring_title": "System niewspierany"
}
},
"view_menu": {
"actual_size": "Rozmiar rzeczywisty",
"toggle_developer_tools": "Przełącz narzędzia deweloperskie",

View File

@@ -22,7 +22,9 @@
"about": "Sobre",
"brand_help": "%(brand)s Ajuda",
"help": "Ajuda",
"preferences": "Preferências"
"no": "Não",
"preferences": "Preferências",
"yes": "Sim"
},
"confirm_quit": "Você tem certeza que você quer sair?",
"edit_menu": {
@@ -49,6 +51,20 @@
"save_image_as_error_description": "A imagem falhou para salvar",
"save_image_as_error_title": "Falha para salvar imagem"
},
"store": {
"error": {
"backend_changed": "Limpar dados e recarregar?",
"backend_changed_detail": "Não foi possível acessar o segredo no cofre do sistema, parece que ele foi alterado.",
"backend_changed_title": "Falha ao carregar o banco de dados",
"unknown_backend_override": "Seu sistema possui um cofre não compatível, o que impede a abertura do banco de dados.",
"unknown_backend_override_details": "Verifique os logs para obter mais detalhes.",
"unknown_backend_override_title": "Falha ao carregar o banco de dados",
"unsupported_keyring": "Seu sistema possui um cofre não compatível, o que impede a abertura do banco de dados.",
"unsupported_keyring_cta": "Use criptografia mais fraca",
"unsupported_keyring_detail": "A detecção de chaveiro do Electron não encontrou um backend compatível. Você pode tentar configurar manualmente o backend iniciando %(brand)s com um argumento de linha de comando, uma operação única. Consulte %(link)s.",
"unsupported_keyring_title": "Sistema não suportado"
}
},
"view_menu": {
"actual_size": "Tamanho de Verdade",
"toggle_developer_tools": "Ativar/Desativar Ferramentas de Desenvolvimento",

View File

@@ -22,7 +22,9 @@
"about": "Informácie",
"brand_help": "%(brand)s Pomoc",
"help": "Pomocník",
"preferences": "Predvoľby"
"no": "Nie",
"preferences": "Predvoľby",
"yes": "Áno"
},
"confirm_quit": "Naozaj chcete zavrieť aplikáciu?",
"edit_menu": {
@@ -49,6 +51,20 @@
"save_image_as_error_description": "Obrázok sa nepodarilo uložiť",
"save_image_as_error_title": "Chyba pri ukladaní obrázka"
},
"store": {
"error": {
"backend_changed": "Vymazať údaje a znova načítať?",
"backend_changed_detail": "Nepodarilo sa získať prístup k tajnému kľúču zo systémového zväzku kľúčov, zdá sa, že sa zmenil.",
"backend_changed_title": "Nepodarilo sa načítať databázu",
"unknown_backend_override": "Váš systém má nepodporovaný zväzok kľúčov, čo znamená, že databázu nemožno otvoriť.",
"unknown_backend_override_details": "Pre viac informácií si pozrite protokoly.",
"unknown_backend_override_title": "Nepodarilo sa načítať databázu",
"unsupported_keyring": "Váš systém má nepodporovaný zväzok kľúčov, čo znamená, že databázu nemožno otvoriť.",
"unsupported_keyring_cta": "Použiť slabšie šifrovanie",
"unsupported_keyring_detail": "Detekcia zväzku kľúčov aplikácie Electron nenašla podporovaný backend. Môžete sa pokúsiť manuálne nastaviť backend spustením aplikácie %(brand)s s argumentom príkazového riadka, je to jednorazová operácia. Pozrite si %(link)s .",
"unsupported_keyring_title": "Systém nie je podporovaný"
}
},
"view_menu": {
"actual_size": "Aktuálna veľkosť",
"toggle_developer_tools": "Nástroje pre vývojárov",

View File

@@ -22,7 +22,9 @@
"about": "Про застосунок",
"brand_help": "Довідка %(brand)s",
"help": "Довідка",
"preferences": "Параметри"
"no": "Ні",
"preferences": "Параметри",
"yes": "Так"
},
"confirm_quit": "Ви впевнені, що хочете вийти?",
"edit_menu": {
@@ -49,6 +51,20 @@
"save_image_as_error_description": "Не вдалося зберегти зображення",
"save_image_as_error_title": "Не вдалося зберегти зображення"
},
"store": {
"error": {
"backend_changed": "Очистити дані та перезавантажити?",
"backend_changed_detail": "Не вдається отримати доступ до таємного ключа з системного набору ключів, видається, він змінився.",
"backend_changed_title": "Не вдалося завантажити базу даних",
"unknown_backend_override": "Ваша система має непідтримуваний ключ, що означає, що базу даних неможливо відкрити.",
"unknown_backend_override_details": "Перегляньте журнал, щоб дізнатися подробиці.",
"unknown_backend_override_title": "Не вдалося завантажити базу даних",
"unsupported_keyring": "Ваша система має непідтримуваний набір ключів. Це означає, що базу даних неможливо відкрити.",
"unsupported_keyring_cta": "Використовувати слабше шифрування",
"unsupported_keyring_detail": "Electron не виявив підтримуваного бекенда для роботи зі сховищем паролів. Ви можете вручну налаштувати його, запустивши %(brand)s з відповідним аргументом у командному рядку. Цю дію потрібно виконати лише один раз. Докладніше %(link)s.",
"unsupported_keyring_title": "Система не підтримується"
}
},
"view_menu": {
"actual_size": "Фактичний розмір",
"toggle_developer_tools": "Перемкнути інструменти розробника",

View File

@@ -6,14 +6,13 @@ Please see LICENSE files in the repository root for full details.
*/
import { app, autoUpdater, desktopCapturer, ipcMain, powerSaveBlocker, TouchBar, nativeImage } from "electron";
import { relaunchApp } from "@standardnotes/electron-clear-data";
import keytar from "keytar-forked";
import IpcMainEvent = Electron.IpcMainEvent;
import { recordSSOSession } from "./protocol.js";
import { randomArray } from "./utils.js";
import { Settings } from "./settings.js";
import { getDisplayMediaCallback, setDisplayMediaCallback } from "./displayMediaCallback.js";
import Store, { clearDataAndRelaunch } from "./store.js";
ipcMain.on("setBadgeCount", function (_ev: IpcMainEvent, count: number): void {
if (process.platform !== "win32") {
@@ -61,7 +60,8 @@ ipcMain.on("app_onAction", function (_ev: IpcMainEvent, payload) {
});
ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) {
if (!global.mainWindow) return;
const store = Store.instance;
if (!global.mainWindow || !store) return;
const args = payload.args || [];
let ret: any;
@@ -113,11 +113,11 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) {
if (typeof args[0] !== "boolean") return;
global.mainWindow.webContents.session.setSpellCheckerEnabled(args[0]);
global.store.set("spellCheckerEnabled", args[0]);
store.set("spellCheckerEnabled", args[0]);
break;
case "getSpellCheckEnabled":
ret = global.store.get("spellCheckerEnabled", true);
ret = store.get("spellCheckerEnabled");
break;
case "setSpellCheckLanguages":
@@ -141,12 +141,7 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) {
case "getPickleKey":
try {
ret = await keytar.getPassword("element.io", `${args[0]}|${args[1]}`);
// migrate from riot.im (remove once we think there will no longer be
// logins from the time of riot.im)
if (ret === null) {
ret = await keytar.getPassword("riot.im", `${args[0]}|${args[1]}`);
}
ret = await store.getSecret(`${args[0]}|${args[1]}`);
} catch {
// if an error is thrown (e.g. keytar can't connect to the keychain),
// then return null, which means the default pickle key will be used
@@ -157,9 +152,7 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) {
case "createPickleKey":
try {
const pickleKey = await randomArray(32);
// We purposefully throw if keytar is not available so the caller can handle it
// rather than sending them a pickle key we did not store on their behalf.
await keytar!.setPassword("element.io", `${args[0]}|${args[1]}`, pickleKey);
await store.setSecret(`${args[0]}|${args[1]}`, pickleKey);
ret = pickleKey;
} catch (e) {
console.error("Failed to create pickle key", e);
@@ -169,11 +162,10 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) {
case "destroyPickleKey":
try {
await keytar.deletePassword("element.io", `${args[0]}|${args[1]}`);
// migrate from riot.im (remove once we think there will no longer be
// logins from the time of riot.im)
await keytar.deletePassword("riot.im", `${args[0]}|${args[1]}`);
} catch {}
await store.deleteSecret(`${args[0]}|${args[1]}`);
} catch (e) {
console.error("Failed to destroy pickle key", e);
}
break;
case "getDesktopCapturerSources":
ret = (await desktopCapturer.getSources(args[0])).map((source) => ({
@@ -189,10 +181,7 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) {
break;
case "clearStorage":
global.store.clear();
global.mainWindow.webContents.session.flushStorageData();
await global.mainWindow.webContents.session.clearStorageData();
relaunchApp();
await clearDataAndRelaunch();
return; // the app is about to stop, we don't need to reply to the IPC
case "breadcrumbs": {

View File

@@ -10,9 +10,9 @@ import { type TranslationKey as TKey } from "matrix-web-i18n";
import { dirname } from "node:path";
import { fileURLToPath } from "node:url";
import type Store from "electron-store";
import type EN from "./i18n/strings/en_EN.json";
import { loadJsonFile } from "./utils.js";
import type Store from "./store.js";
const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -59,26 +59,24 @@ export function _t(text: TranslationKey, variables: Variables = {}): string {
type Component = () => void;
type TypedStore = Store<{ locale?: string | string[] }>;
export class AppLocalization {
private static readonly STORE_KEY = "locale";
private readonly store: TypedStore;
private readonly localizedComponents?: Set<Component>;
private readonly store: Store;
public constructor({ store, components = [] }: { store: TypedStore; components: Component[] }) {
public constructor({ components = [], store }: { components: Component[]; store: Store }) {
counterpart.registerTranslations(FALLBACK_LOCALE, this.fetchTranslationJson("en_EN"));
counterpart.setFallbackLocale(FALLBACK_LOCALE);
counterpart.setSeparator("|");
this.store = store;
if (Array.isArray(components)) {
this.localizedComponents = new Set(components);
}
this.store = store;
if (this.store.has(AppLocalization.STORE_KEY)) {
const locales = this.store.get(AppLocalization.STORE_KEY);
if (store.has(AppLocalization.STORE_KEY)) {
const locales = store.get(AppLocalization.STORE_KEY);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.setAppLocale(locales!);
}

View File

@@ -117,7 +117,7 @@ export function protocolInit(): void {
// Protocol handler for win32/Linux
app.on("second-instance", (ev, commandLine) => {
const url = commandLine[commandLine.length - 1];
if (!url.startsWith(`${PROTOCOL}://`) && !url.startsWith(`${LEGACY_PROTOCOL}://`)) return;
if (!url.startsWith(`${PROTOCOL}:/`) && !url.startsWith(`${LEGACY_PROTOCOL}://`)) return;
processUrl(url);
});
}

View File

@@ -8,7 +8,6 @@ Please see LICENSE files in the repository root for full details.
import { app, ipcMain } from "electron";
import { promises as afs } from "node:fs";
import path from "node:path";
import keytar from "keytar-forked";
import type {
Seshat as SeshatType,
@@ -17,6 +16,7 @@ import type {
} from "matrix-seshat"; // Hak dependency type
import IpcMainEvent = Electron.IpcMainEvent;
import { randomArray } from "./utils.js";
import Store from "./store.js";
let seshatSupported = false;
let Seshat: typeof SeshatType;
@@ -40,21 +40,24 @@ try {
let eventIndex: SeshatType | null = null;
const seshatDefaultPassphrase = "DEFAULT_PASSPHRASE";
async function getOrCreatePassphrase(key: string): Promise<string> {
if (keytar) {
try {
const storedPassphrase = await keytar.getPassword("element.io", key);
if (storedPassphrase !== null) {
return storedPassphrase;
} else {
const newPassphrase = await randomArray(32);
await keytar.setPassword("element.io", key, newPassphrase);
return newPassphrase;
}
} catch (e) {
console.log("Error getting the event index passphrase out of the secret store", e);
async function getOrCreatePassphrase(store: Store, key: string): Promise<string> {
try {
const storedPassphrase = await store.getSecret(key);
if (storedPassphrase !== null) {
return storedPassphrase;
}
} catch (e) {
console.error("Error getting the event index passphrase out of the secret store", e);
}
try {
const newPassphrase = await randomArray(32);
await store.setSecret(key, newPassphrase);
return newPassphrase;
} catch (e) {
console.error("Error creating new event index passphrase, using default", e);
}
return seshatDefaultPassphrase;
}
@@ -74,7 +77,8 @@ const deleteContents = async (p: string): Promise<void> => {
};
ipcMain.on("seshat", async function (_ev: IpcMainEvent, payload): Promise<void> {
if (!global.mainWindow) return;
const store = Store.instance;
if (!global.mainWindow || !store) return;
// We do this here to ensure we get the path after --profile has been resolved
const eventStorePath = path.join(app.getPath("userData"), "EventStore");
@@ -101,7 +105,7 @@ ipcMain.on("seshat", async function (_ev: IpcMainEvent, payload): Promise<void>
const deviceId = args[1];
const passphraseKey = `seshat|${userId}|${deviceId}`;
const passphrase = await getOrCreatePassphrase(passphraseKey);
const passphrase = await getOrCreatePassphrase(store, passphraseKey);
try {
await afs.mkdir(eventStorePath, { recursive: true });

View File

@@ -6,6 +6,7 @@ Please see LICENSE files in the repository root for full details.
*/
import * as tray from "./tray.js";
import Store from "./store.js";
interface Setting {
read(): Promise<any>;
@@ -27,10 +28,10 @@ export const Settings: Record<string, Setting> = {
},
"Electron.warnBeforeExit": {
async read(): Promise<any> {
return global.store.get("warnBeforeExit", true);
return Store.instance?.get("warnBeforeExit");
},
async write(value: any): Promise<void> {
global.store.set("warnBeforeExit", value);
Store.instance?.set("warnBeforeExit", value);
},
},
"Electron.alwaysShowMenuBar": {
@@ -39,7 +40,7 @@ export const Settings: Record<string, Setting> = {
return !global.mainWindow!.autoHideMenuBar;
},
async write(value: any): Promise<void> {
global.store.set("autoHideMenuBar", !value);
Store.instance?.set("autoHideMenuBar", !value);
global.mainWindow!.autoHideMenuBar = !value;
global.mainWindow!.setMenuBarVisibility(value);
},
@@ -56,15 +57,15 @@ export const Settings: Record<string, Setting> = {
} else {
tray.destroy();
}
global.store.set("minimizeToTray", value);
Store.instance?.set("minimizeToTray", value);
},
},
"Electron.enableHardwareAcceleration": {
async read(): Promise<any> {
return !global.store.get("disableHardwareAcceleration", false);
return !Store.instance?.get("disableHardwareAcceleration");
},
async write(value: any): Promise<void> {
global.store.set("disableHardwareAcceleration", !value);
Store.instance?.set("disableHardwareAcceleration", !value);
},
},
};

505
src/store.ts Normal file
View File

@@ -0,0 +1,505 @@
/*
Copyright 2022-2025 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import ElectronStore from "electron-store";
import keytar from "keytar-forked";
import { app, safeStorage, dialog, type SafeStorage } from "electron";
import { clearAllUserData, relaunchApp } from "@standardnotes/electron-clear-data";
import { _t } from "./language-helper.js";
/**
* Legacy keytar service name for storing secrets.
* @deprecated
*/
const KEYTAR_SERVICE = "element.io";
/**
* Super legacy keytar service name for reading secrets.
* @deprecated
*/
const LEGACY_KEYTAR_SERVICE = "riot.im";
/**
* String union type representing all the safeStorage backends.
* + The "unknown" backend shouldn't exist in practice once the app is ready
* + The "plaintext" is the temporarily-unencrypted backend for migration, data is wholly unencrypted - uses PlaintextStorageWriter
* + The "basic_text" backend is the 'plaintext' backend on Linux, data is encrypted but not using the keychain
* + The "system" backend is the encrypted backend on Windows & macOS, data is encrypted using system keychain
* + All other backends are linux-specific and are encrypted using the keychain
*/
type SafeStorageBackend = ReturnType<SafeStorage["getSelectedStorageBackend"]> | "system" | "plaintext";
/**
* The "unknown" backend is not a valid backend, so we exclude it from the type.
*/
type SaneSafeStorageBackend = Exclude<SafeStorageBackend, "unknown">;
/**
* Map of safeStorage backends to their command line arguments.
* kwallet6 cannot be specified via command line
* https://www.electronjs.org/docs/latest/api/safe-storage#safestoragegetselectedstoragebackend-linux
*/
const safeStorageBackendMap: Omit<
Record<SafeStorageBackend, string>,
"unknown" | "kwallet6" | "system" | "plaintext"
> = {
basic_text: "basic",
gnome_libsecret: "gnome-libsecret",
kwallet: "kwallet",
kwallet5: "kwallet5",
};
/**
* Clear all data and relaunch the app.
*/
export async function clearDataAndRelaunch(): Promise<void> {
Store.instance?.clear();
clearAllUserData();
relaunchApp();
}
interface StoreData {
warnBeforeExit: boolean;
minimizeToTray: boolean;
spellCheckerEnabled: boolean;
autoHideMenuBar: boolean;
locale?: string | string[];
disableHardwareAcceleration: boolean;
safeStorage?: Record<string, string>;
/** the safeStorage backend used for the safeStorage data as written */
safeStorageBackend?: SafeStorageBackend;
/** whether to explicitly override the safeStorage backend, used for migration */
safeStorageBackendOverride?: boolean;
/** whether to perform a migration of the safeStorage data */
safeStorageBackendMigrate?: boolean;
}
/**
* Fallback storage writer for secrets, mainly used for automated tests and systems without any safeStorage support.
*/
class StorageWriter {
public constructor(protected readonly store: ElectronStore<StoreData>) {}
public getKey(key: string): `safeStorage.${string}` {
return `safeStorage.${key.replaceAll(".", "-")}`;
}
public set(key: string, secret: string): void {
this.store.set(this.getKey(key), secret);
}
public get(key: string): string | null {
return this.store.get(this.getKey(key));
}
public delete(key: string): void {
this.store.delete(this.getKey(key));
}
}
/**
* Storage writer for secrets using safeStorage.
*/
class SafeStorageWriter extends StorageWriter {
public set(key: string, secret: string): void {
this.store.set(this.getKey(key), safeStorage.encryptString(secret).toString("base64"));
}
public get(key: string): string | null {
const ciphertext = this.store.get<string, string | undefined>(this.getKey(key));
if (ciphertext) {
try {
return safeStorage.decryptString(Buffer.from(ciphertext, "base64"));
} catch (e) {
console.error("Failed to decrypt secret", e);
console.error("...ciphertext:", JSON.stringify(ciphertext));
}
}
return null;
}
}
const enum Mode {
Encrypted = "encrypted", // default
AllowPlaintext = "allow-plaintext",
ForcePlaintext = "force-plaintext",
}
/**
* JSON-backed store for settings which need to be accessible by the main process.
* Secrets are stored within the `safeStorage` object, encrypted with safeStorage.
* Any secrets operations are blocked on Electron app ready emit, and keytar migration if still needed.
*/
class Store extends ElectronStore<StoreData> {
private static internalInstance?: Store;
public static get instance(): Store | undefined {
return Store.internalInstance;
}
/**
* Prepare the store, does not prepare safeStorage, which needs to be done after the app is ready.
* Must be executed in the first tick of the event loop so that it can call Electron APIs before ready state.
*/
public static initialize(mode: Mode | undefined): Store {
if (Store.internalInstance) {
throw new Error("Store already initialized");
}
const store = new Store(mode ?? Mode.Encrypted);
Store.internalInstance = store;
if (
process.platform === "linux" &&
(store.get("safeStorageBackendOverride") || store.get("safeStorageBackendMigrate"))
) {
const backend = store.get("safeStorageBackend")!;
if (backend in safeStorageBackendMap) {
// If the safeStorage backend which was used to write the data is one we can specify via the commandLine
// then do so to ensure we use the same backend for reading the data.
app.commandLine.appendSwitch(
"password-store",
safeStorageBackendMap[backend as keyof typeof safeStorageBackendMap],
);
}
}
return store;
}
// Provides "raw" access to the underlying secrets storage,
// should be avoided in favour of the getSecret/setSecret/deleteSecret methods.
private secrets?: StorageWriter;
private constructor(private mode: Mode) {
super({
name: "electron-config",
clearInvalidConfig: false,
schema: {
warnBeforeExit: {
type: "boolean",
default: true,
},
minimizeToTray: {
type: "boolean",
default: true,
},
spellCheckerEnabled: {
type: "boolean",
default: true,
},
autoHideMenuBar: {
type: "boolean",
default: true,
},
locale: {
anyOf: [{ type: "string" }, { type: "array", items: { type: "string" } }],
},
disableHardwareAcceleration: {
type: "boolean",
default: false,
},
safeStorage: {
type: "object",
},
safeStorageBackend: {
type: "string",
},
safeStorageBackendOverride: {
type: "boolean",
},
safeStorageBackendMigrate: {
type: "boolean",
},
},
});
}
private safeStorageReadyPromise?: Promise<unknown>;
public async safeStorageReady(): Promise<void> {
if (!this.safeStorageReadyPromise) {
this.safeStorageReadyPromise = this.prepareSafeStorage();
}
await this.safeStorageReadyPromise;
}
/**
* Normalise the backend to a sane value (exclude `unknown`), respect forcePlaintext mode,
* and ensure that if an encrypted backend is picked that encryption is available, falling back to plaintext if not.
* @param forcePlaintext - whether to force plaintext mode
* @private
*/
private chooseBackend(forcePlaintext: boolean): SaneSafeStorageBackend {
if (forcePlaintext) {
return "plaintext";
}
if (process.platform === "linux") {
// The following enables plain text encryption if the backend used is basic_text.
// It has no significance for any other backend.
// We do this early so that in case we end up using the basic_text backend (either because that's the only one available
// or as a fallback when the configured backend lacks encryption support), encryption is already turned on.
safeStorage.setUsePlainTextEncryption(true);
// Linux safeStorage support is hellish, the support varies on the Desktop Environment used rather than the store itself.
// https://github.com/electron/electron/issues/39789 https://github.com/microsoft/vscode/issues/185212
const selectedBackend = safeStorage.getSelectedStorageBackend();
if (selectedBackend === "unknown" || !safeStorage.isEncryptionAvailable()) {
return "plaintext";
}
return selectedBackend;
}
return safeStorage.isEncryptionAvailable() ? "system" : "plaintext";
}
/**
* Prepare the safeStorage backend for use.
* We don't eagerly import from keytar as that would bring in data for all Element profiles and not just the current one,
* so we import lazily in getSecret.
*/
private async prepareSafeStorage(): Promise<void> {
await app.whenReady();
// The backend the existing data is written with if any
let existingSafeStorageBackend = this.get("safeStorageBackend");
// The backend and encryption status of the currently loaded backend
const backend = this.chooseBackend(this.mode === Mode.ForcePlaintext);
// Handle migrations
if (existingSafeStorageBackend) {
if (existingSafeStorageBackend === "basic_text" && backend !== "plaintext" && backend !== "basic_text") {
return this.prepareMigrateBasicTextToPlaintext();
}
if (this.get("safeStorageBackendMigrate") && backend === "basic_text") {
return this.migrateBasicTextToPlaintext();
}
if (existingSafeStorageBackend === "plaintext" && backend !== "plaintext") {
this.migratePlaintextToEncrypted();
// Ensure we update existingSafeStorageBackend so we don't fall into the "backend changed" clause below
existingSafeStorageBackend = this.get("safeStorageBackend");
}
}
if (!existingSafeStorageBackend) {
// First launch of the app or first launch since the update
if (this.mode === Mode.Encrypted && (backend === "plaintext" || backend === "basic_text")) {
// Ask the user for consent to use a degraded mode
await this.consultUserConsentDegradedMode(backend);
}
// Store the backend used for the safeStorage data so we can detect if it changes, and we know how the data is encoded
this.recordSafeStorageBackend(backend);
} else if (existingSafeStorageBackend !== backend) {
console.warn(`safeStorage backend changed from ${existingSafeStorageBackend} to ${backend}`);
if (existingSafeStorageBackend in safeStorageBackendMap) {
this.set("safeStorageBackendOverride", true);
return relaunchApp();
} else {
await this.consultUserBackendChangedUnableToMigrate();
}
}
console.info(`Using storage mode '${this.mode}' with backend '${backend}'`);
if (backend !== "plaintext") {
this.secrets = new SafeStorageWriter(this);
} else {
this.secrets = new StorageWriter(this);
}
}
private async consultUserBackendChangedUnableToMigrate(): Promise<void> {
const { response } = await dialog.showMessageBox({
title: _t("store|error|backend_changed_title"),
message: _t("store|error|backend_changed"),
detail: _t("store|error|backend_changed_detail"),
type: "question",
buttons: [_t("common|no"), _t("common|yes")],
defaultId: 0,
cancelId: 0,
});
if (response === 0) {
throw new Error("safeStorage backend changed and cannot migrate");
}
return clearDataAndRelaunch();
}
private async consultUserConsentDegradedMode(backend: "plaintext" | "basic_text"): Promise<void> {
if (backend === "plaintext") {
// Sometimes we may have a working backend that for some reason does not support encryption at the moment.
// This may be because electron reported an incorrect backend or because of some known issues with the keyring itself.
// Or the environment specified `--storage-mode=force-plaintext`.
// In any case, when this happens, we give the user an option to use a weaker form of encryption.
const { response } = await dialog.showMessageBox({
title: _t("store|error|backend_no_encryption_title"),
message: _t("store|error|backend_no_encryption"),
detail: _t("store|error|backend_no_encryption_detail", {
backend: safeStorage.getSelectedStorageBackend(),
brand: global.vectorConfig.brand || "Element",
}),
type: "error",
buttons: [_t("action|cancel"), _t("store|error|unsupported_keyring_use_plaintext")],
defaultId: 0,
cancelId: 0,
});
if (response === 0) {
throw new Error("isEncryptionAvailable=false and user rejected plaintext");
}
} else {
// Electron did not identify a compatible encrypted backend, ask user for consent to degraded mode
const { response } = await dialog.showMessageBox({
title: _t("store|error|unsupported_keyring_title"),
message: _t("store|error|unsupported_keyring"),
detail: _t("store|error|unsupported_keyring_detail", {
brand: global.vectorConfig.brand || "Element",
link: "https://www.electronjs.org/docs/latest/api/safe-storage#safestoragegetselectedstoragebackend-linux",
}),
type: "error",
buttons: [_t("action|cancel"), _t("store|error|unsupported_keyring_use_basic_text")],
defaultId: 0,
cancelId: 0,
});
if (response === 0) {
throw new Error("safeStorage backend basic_text and user rejected it");
}
}
}
private recordSafeStorageBackend(backend: SafeStorageBackend): void {
this.set("safeStorageBackend", backend);
}
/**
* Linux support for upgrading the backend from basic_text to one of the encrypted backends,
* this is quite a tricky process as the backend is not known until the app is ready & cannot be changed once it is.
* 1. We restart the app in safeStorageBackendMigrate mode
* 2. Now that we are in the mode which our data is written in we decrypt the data, write it back in plaintext
* & restart back in default backend mode,
* 3. Finally, we load the plaintext data & encrypt it.
*/
private prepareMigrateBasicTextToPlaintext(): void {
console.info(`Starting safeStorage migration to ${safeStorage.getSelectedStorageBackend()}`);
this.set("safeStorageBackendMigrate", true);
relaunchApp();
}
private migrateBasicTextToPlaintext(): void {
const secrets = new SafeStorageWriter(this);
console.info("Performing safeStorage migration");
const data = this.get("safeStorage");
if (data) {
for (const key in data) {
this.set(secrets.getKey(key), secrets.get(key));
}
this.recordSafeStorageBackend("plaintext");
}
this.delete("safeStorageBackendMigrate");
relaunchApp();
}
private migratePlaintextToEncrypted(): void {
const secrets = new SafeStorageWriter(this);
const selectedSafeStorageBackend = safeStorage.getSelectedStorageBackend();
console.info(`Finishing safeStorage migration to ${selectedSafeStorageBackend}`);
const data = this.get("safeStorage");
if (data) {
for (const key in data) {
secrets.set(key, data[key]);
}
}
this.recordSafeStorageBackend(selectedSafeStorageBackend);
}
/**
* Get the stored secret for the key.
* Lazily migrates keys from keytar if they are not yet in the store.
*
* @param key The string key name.
*
* @returns A promise for the secret string.
*/
public async getSecret(key: string): Promise<string | null> {
await this.safeStorageReady();
let secret = this.secrets!.get(key);
if (secret) return secret;
try {
secret = await this.getSecretKeytar(key);
} catch (e) {
console.warn(`Failed to read data from keytar with key='${key}'`, e);
}
if (secret) {
console.debug("Migrating secret from keytar", key);
this.secrets!.set(key, secret);
}
return secret;
}
/**
* Add the secret for the key to the keychain.
* We write to both safeStorage & keytar to support downgrading the application.
*
* @param key The string key name.
* @param secret The string password.
*
* @returns A promise for the set password completion.
*/
public async setSecret(key: string, secret: string): Promise<void> {
await this.safeStorageReady();
this.secrets!.set(key, secret);
try {
await keytar.setPassword(KEYTAR_SERVICE, key, secret);
} catch (e) {
console.warn(`Failed to write safeStorage backwards-compatibility key='${key}' data to keytar`, e);
}
}
/**
* Delete the stored password for the key.
* Removes from safeStorage, keytar & keytar legacy.
*
* @param key The string key name.
*/
public async deleteSecret(key: string): Promise<void> {
await this.safeStorageReady();
this.secrets!.delete(key);
try {
await this.deleteSecretKeytar(key);
} catch (e) {
console.warn(`Failed to delete secret with key='${key}' from keytar`, e);
}
}
/**
* @deprecated will be removed in the near future
*/
private async getSecretKeytar(key: string): Promise<string | null> {
return (
(await keytar.getPassword(KEYTAR_SERVICE, key)) ?? (await keytar.getPassword(LEGACY_KEYTAR_SERVICE, key))
);
}
/**
* @deprecated will be removed in the near future
*/
private async deleteSecretKeytar(key: string): Promise<void> {
await keytar.deletePassword(LEGACY_KEYTAR_SERVICE, key);
await keytar.deletePassword(KEYTAR_SERVICE, key);
}
}
export default Store;

535
yarn.lock
View File

@@ -1017,16 +1017,7 @@
ajv "^6.12.0"
ajv-keywords "^3.4.1"
"@electron/asar@3.2.18", "@electron/asar@^3.2.7":
version "3.2.18"
resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.2.18.tgz#fa607f829209bab8b9e0ce6658d3fe81b2cba517"
integrity sha512-2XyvMe3N3Nrs8cV39IKELRHTYUWFKrmqqSY1U+GMlc0jvqjIVnoxhNd2H4JolWQncbJi1DCvb5TNxZuI2fEjWg==
dependencies:
commander "^5.0.0"
glob "^7.1.6"
minimatch "^3.0.4"
"@electron/asar@3.4.1":
"@electron/asar@3.4.1", "@electron/asar@^3.3.1":
version "3.4.1"
resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.4.1.tgz#4e9196a4b54fba18c56cd8d5cac67c5bdc588065"
integrity sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==
@@ -1068,9 +1059,9 @@
optionalDependencies:
global-agent "^3.0.0"
"@electron/node-gyp@https://github.com/electron/node-gyp#06b29aafb7708acef8b3669835c8a7857ebc92d2":
"@electron/node-gyp@git+https://github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2":
version "10.2.0-electron.1"
resolved "https://github.com/electron/node-gyp#06b29aafb7708acef8b3669835c8a7857ebc92d2"
resolved "git+https://github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2"
dependencies:
env-paths "^2.2.0"
exponential-backoff "^3.1.1"
@@ -1092,10 +1083,10 @@
fs-extra "^9.0.1"
promise-retry "^2.0.1"
"@electron/osx-sign@1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@electron/osx-sign/-/osx-sign-1.3.1.tgz#faf7eeca7ca004a6be541dc4cf7a1bd59ec59b1c"
integrity sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==
"@electron/osx-sign@1.3.3":
version "1.3.3"
resolved "https://registry.yarnpkg.com/@electron/osx-sign/-/osx-sign-1.3.3.tgz#af751510488318d9f7663694af85819690d75583"
integrity sha512-KZ8mhXvWv2rIEgMbWZ4y33bDHyUKMXnx4M0sTyPNK/vcB81ImdeY9Ggdqy0SWbMDgmbqyQ+phgejh6V3R2QuSg==
dependencies:
compare-version "^0.1.2"
debug "^4.3.4"
@@ -1104,10 +1095,10 @@
minimist "^1.2.6"
plist "^3.0.5"
"@electron/rebuild@3.7.0":
version "3.7.0"
resolved "https://registry.yarnpkg.com/@electron/rebuild/-/rebuild-3.7.0.tgz#82e20c467ddedbb295d7f641592c52e68c141e9f"
integrity sha512-VW++CNSlZwMYP7MyXEbrKjpzEwhB5kDNbzGtiPEjwYysqyTCF+YbNJ210Dj3AjWsGSV4iEEwNkmJN9yGZmVvmw==
"@electron/rebuild@3.7.2":
version "3.7.2"
resolved "https://registry.yarnpkg.com/@electron/rebuild/-/rebuild-3.7.2.tgz#8d808b29159c50086d27a5dec72b40bf16b4b582"
integrity sha512-19/KbIR/DAxbsCkiaGMXIdPnMCJLkcf8AvGnduJtWBs/CBwiAjY1apCqOLVxrXg+rtXFCngbXhBanWjxLUt1Mg==
dependencies:
"@electron/node-gyp" "https://github.com/electron/node-gyp#06b29aafb7708acef8b3669835c8a7857ebc92d2"
"@malept/cross-spawn-promise" "^2.0.0"
@@ -1124,12 +1115,12 @@
tar "^6.0.5"
yargs "^17.0.1"
"@electron/universal@2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@electron/universal/-/universal-2.0.1.tgz#7b070ab355e02957388f3dbd68e2c3cd08c448ae"
integrity sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==
"@electron/universal@2.0.3":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@electron/universal/-/universal-2.0.3.tgz#1680df6ced8f128ca0ff24e29c2165d41d78b3ce"
integrity sha512-Wn9sPYIVFRFl5HmwMJkARCCf7rqK/EurkfQ/rJZ14mHP3iYTjZSIOSVonEAnhWeAXwtw7zOekGRlc6yTtZ0t+g==
dependencies:
"@electron/asar" "^3.2.7"
"@electron/asar" "^3.3.1"
"@malept/cross-spawn-promise" "^2.0.0"
debug "^4.3.1"
dir-compare "^4.2.0"
@@ -1273,7 +1264,7 @@
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz#c8e119a30a7c8d60b9d2e22d2073722dde3b710b"
integrity sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==
"@eslint-community/eslint-utils@^4.1.2", "@eslint-community/eslint-utils@^4.4.0", "@eslint-community/eslint-utils@^4.4.1":
"@eslint-community/eslint-utils@^4.1.2", "@eslint-community/eslint-utils@^4.4.1":
version "4.5.1"
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz#b0fc7e06d0c94f801537fd4237edc2706d3b8e4c"
integrity sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==
@@ -1287,6 +1278,13 @@
dependencies:
eslint-visitor-keys "^3.3.0"
"@eslint-community/eslint-utils@^4.4.0":
version "4.6.1"
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.6.1.tgz#e4c58fdcf0696e7a5f19c30201ed43123ab15abc"
integrity sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==
dependencies:
eslint-visitor-keys "^3.4.3"
"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.11.0":
version "4.12.1"
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0"
@@ -1417,32 +1415,11 @@
"@nodelib/fs.stat" "2.0.5"
run-parallel "^1.1.9"
"@nodelib/fs.scandir@4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-4.0.1.tgz#4b981a1d6e34e2baff9a33c84b57709e30e8ce30"
integrity sha512-vAkI715yhnmiPupY+dq+xenu5Tdf2TBQ66jLvBIcCddtz+5Q8LbMKaf9CIJJreez8fQ8fgaY+RaywQx8RJIWpw==
dependencies:
"@nodelib/fs.stat" "4.0.0"
run-parallel "^1.2.0"
"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
version "2.0.5"
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
"@nodelib/fs.stat@4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-4.0.0.tgz#d609b10d9c17dac012c4d7be93602ed939861e58"
integrity sha512-ctr6bByzksKRCV0bavi8WoQevU6plSp2IkllIsEqaiKe2mwNNnaluhnRhcsgGZHrrHk57B3lf95MkLMO3STYcg==
"@nodelib/fs.walk@3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-3.0.1.tgz#717a03eb1d07c09db32f884a5d0c06ccd9b657f4"
integrity sha512-nIh/M6Kh3ZtOmlY00DaUYB4xeeV6F3/ts1l29iwl3/cfyY/OuCfUx+v08zgx8TKPTifXRcjjqVQ4KB2zOYSbyw==
dependencies:
"@nodelib/fs.scandir" "4.0.1"
fastq "^1.15.0"
"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8":
version "1.2.8"
resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
@@ -1867,9 +1844,9 @@
integrity sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==
"@opentelemetry/semantic-conventions@^1.27.0", "@opentelemetry/semantic-conventions@^1.30.0":
version "1.30.0"
resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.30.0.tgz#3a42c4c475482f2ec87c12aad98832dc0087dc9a"
integrity sha512-4VlGgo32k2EQ2wcCY3vEU28A0O13aOtHz3Xt2/2U5FAh9EfhD6t6DqL5Z6yAnRCntbTFDU4YfbpyzSlHNWycPw==
version "1.32.0"
resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.32.0.tgz#a15e8f78f32388a7e4655e7f539570e40958ca3f"
integrity sha512-s0OpmpQFSfMrmedAn9Lhg4KWJELHCU6uU9dtIJ28N8UGhf9Y55im5X8fEzwhwDwiSqN+ZPSNrDJF7ivf/AuRPQ==
"@opentelemetry/sql-common@^0.40.1":
version "0.40.1"
@@ -1883,12 +1860,12 @@
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
"@playwright/test@1.51.1":
version "1.51.1"
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.51.1.tgz#75357d513221a7be0baad75f01e966baf9c41a2e"
integrity sha512-nM+kEaTSAoVlXmMPH10017vn3FSiFqr/bh4fKg9vmAdMfd9SDqRZNvPSiAHADc/itWak+qPvMPZQOPwCBW7k7Q==
"@playwright/test@1.52.0":
version "1.52.0"
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.52.0.tgz#267ec595b43a8f4fa5e444ea503689629e91a5b8"
integrity sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==
dependencies:
playwright "1.51.1"
playwright "1.52.0"
"@prisma/instrumentation@6.5.0":
version "6.5.0"
@@ -1902,66 +1879,66 @@
resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8"
integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==
"@sentry-internal/browser-utils@9.10.1":
version "9.10.1"
resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-9.10.1.tgz#64daffa273dd50571752d4b5c781892548d12157"
integrity sha512-O/ibpHbKfpG+xtZuEzbLNtLcbanRcDYGxT+QbslVItmcS9GjMSwvMpp1jnD9Y7/LIFtv7O1gJZ9Hrz///lLprw==
"@sentry-internal/browser-utils@9.11.0":
version "9.11.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-9.11.0.tgz#b4d89fbf1a41ee04ddf5a0058433b6b996d39a41"
integrity sha512-XS71kRf7lw5St/Jc9G2Viy1cKgqGoPHqUAykXEtFt38JVXdf1TY/dSbKv/PAgNqMvC1xvdTsN0HF/81o7DNUEA==
dependencies:
"@sentry/core" "9.10.1"
"@sentry/core" "9.11.0"
"@sentry-internal/feedback@9.10.1":
version "9.10.1"
resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-9.10.1.tgz#e151daff4bfa89af7293ce651649448b6abf9794"
integrity sha512-DM32eAzRvXk36iGBWtlLZA88QzOFBODd+kbz55X4Py+1bDNdRc3Vl6214uuAr7iweHcOQy1rIvmAeO8Xusp7tQ==
"@sentry-internal/feedback@9.11.0":
version "9.11.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-9.11.0.tgz#fefbfb318aef251c3dd02540ce524807dbb59bc3"
integrity sha512-50KiRmrF1Ldr+KoRawqcCYVk7TAVP8K/I81Jk9YWwlp1+Pu1ArpYDmTNCLXTgoyiyO38aHefKGZJX6AKFuSsUQ==
dependencies:
"@sentry/core" "9.10.1"
"@sentry/core" "9.11.0"
"@sentry-internal/replay-canvas@9.10.1":
version "9.10.1"
resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-9.10.1.tgz#dc3d04aba6aa08059bfe515505e5f16b1591341c"
integrity sha512-fxrpqElqdsAQrzVly0V/XaljhAlwwMk+iGyf+wZeK6RwEPVxtoxXVfx7fEEtPn+gortqQR09N/zH179hefjuaw==
"@sentry-internal/replay-canvas@9.11.0":
version "9.11.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-9.11.0.tgz#56db491058dc7005291c45f3e1777afc87637db5"
integrity sha512-ZcRg8TWfF0ucjK2i+4TY/blRNJ7YKrgMpx19pFj6eCOJ1K8geSkAFPIfDHcQEwIU1ZTN+HiCwx0JvTI9YZxjfg==
dependencies:
"@sentry-internal/replay" "9.10.1"
"@sentry/core" "9.10.1"
"@sentry-internal/replay" "9.11.0"
"@sentry/core" "9.11.0"
"@sentry-internal/replay@9.10.1":
version "9.10.1"
resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-9.10.1.tgz#8255b0359027bf6ea06f15cbe1271f05720a8a27"
integrity sha512-nqG33NwojtteL8e3Qg/SOu0BsTJ9R7AjpmQIlOpFGL007nzKgcJHOngewd7FEHyB+F3iOI0MoI9iEWhRFEGRLw==
"@sentry-internal/replay@9.11.0":
version "9.11.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-9.11.0.tgz#ef591263b516415a40b0954e17b29c7a1a83b4c0"
integrity sha512-0k24h58O/2VQw1dwT/zQiWvUzLNQxpxbrVN/MYPT7czSEhI+1bX8fxMHXZORl2JqhetImMXzxH3XkuHQPEqQMg==
dependencies:
"@sentry-internal/browser-utils" "9.10.1"
"@sentry/core" "9.10.1"
"@sentry-internal/browser-utils" "9.11.0"
"@sentry/core" "9.11.0"
"@sentry/browser@9.10.1":
version "9.10.1"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-9.10.1.tgz#071908d8e1082c9e6d24024a73d96fa09943f14c"
integrity sha512-9RWjcyskhnDK2Q6LntFR90EqZD5+DXcXNqeTlE+mpVf65y7wz+9SIuVjAMP7qiDBwfxNbmTxiVCXeCuQnnATsQ==
"@sentry/browser@9.11.0":
version "9.11.0"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-9.11.0.tgz#3126223289949d4b63bfad1fc2c0fc2fdc035cbe"
integrity sha512-DSDj8wQJoiLqqOcntl+7phjd8l8KN9A0vaV7mZNHWbrHU3MVwXqTyLyERRLC6wi0t7F5kqczqa3xLmKjK/fMZg==
dependencies:
"@sentry-internal/browser-utils" "9.10.1"
"@sentry-internal/feedback" "9.10.1"
"@sentry-internal/replay" "9.10.1"
"@sentry-internal/replay-canvas" "9.10.1"
"@sentry/core" "9.10.1"
"@sentry-internal/browser-utils" "9.11.0"
"@sentry-internal/feedback" "9.11.0"
"@sentry-internal/replay" "9.11.0"
"@sentry-internal/replay-canvas" "9.11.0"
"@sentry/core" "9.11.0"
"@sentry/core@9.10.1":
version "9.10.1"
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-9.10.1.tgz#c5fff1d45378ea2937f88bd542230232eec89e65"
integrity sha512-TE2zZV3Od4131mZNgFo2Mv4aKU8FXxL0s96yqRvmV+8AU57mJoycMXBnmNSYfWuDICbPJTVAp+3bYMXwX7N5YA==
"@sentry/core@9.11.0":
version "9.11.0"
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-9.11.0.tgz#4cedb0d549e98f4e259f9a48b129e3a46001aba4"
integrity sha512-qfb4ahGZubbrNh1MnbEqyHFp87rIwQIZapyQLCaYpudXrP1biEpLOV3mMDvDJWCdX460hoOwQ3SkwipV3We/7w==
"@sentry/electron@^6.0.0":
version "6.4.0"
resolved "https://registry.yarnpkg.com/@sentry/electron/-/electron-6.4.0.tgz#fd568da779fd8b626c067e50ccf01a7e0d0886da"
integrity sha512-CbOhTwHH1i3jbLr1OTeDrFGajWK8Pr0jcAXUj8zf93ItTJPS09sEi9cd3CRGzHcC7ODX4nHB5RbUD9GYe6ms4w==
version "6.5.0"
resolved "https://registry.yarnpkg.com/@sentry/electron/-/electron-6.5.0.tgz#6b3f7f6f779adb390e288731f3bcad66f33216d1"
integrity sha512-VFwIr8ovbJGWW3rdnWGEVkRHTVLFj9IiTjguzcCKGGDS3Q1oBqhbxPjX6EKaIubVSKjE1G2gtt+Q9CfM/tMDdg==
dependencies:
"@sentry/browser" "9.10.1"
"@sentry/core" "9.10.1"
"@sentry/node" "9.10.1"
"@sentry/browser" "9.11.0"
"@sentry/core" "9.11.0"
"@sentry/node" "9.11.0"
deepmerge "4.3.1"
"@sentry/node@9.10.1":
version "9.10.1"
resolved "https://registry.yarnpkg.com/@sentry/node/-/node-9.10.1.tgz#03029fa0d47f81f4bb989198b2558d0ec88daf54"
integrity sha512-salNc4R0GiZZNNScNpdAB3OI3kz+clmgXL1rl5O2Kh1IW5vftf5I69n+qqZLJ3kaUp0Sm6V+deCHyUOnw9GozA==
"@sentry/node@9.11.0":
version "9.11.0"
resolved "https://registry.yarnpkg.com/@sentry/node/-/node-9.11.0.tgz#5d42d698a7e2a53075288806a2ad1b31c68f89da"
integrity sha512-luDsNDHsHkoXbL2Rf1cEKijh6hBfjzGQe09iP6kdZr+HB0bO+qoLe+nZLzSIQTWgWSt2XYNQyiLAsaMlbJZhJg==
dependencies:
"@opentelemetry/api" "^1.9.0"
"@opentelemetry/context-async-hooks" "^1.30.1"
@@ -1994,16 +1971,16 @@
"@opentelemetry/sdk-trace-base" "^1.30.1"
"@opentelemetry/semantic-conventions" "^1.30.0"
"@prisma/instrumentation" "6.5.0"
"@sentry/core" "9.10.1"
"@sentry/opentelemetry" "9.10.1"
"@sentry/core" "9.11.0"
"@sentry/opentelemetry" "9.11.0"
import-in-the-middle "^1.13.0"
"@sentry/opentelemetry@9.10.1":
version "9.10.1"
resolved "https://registry.yarnpkg.com/@sentry/opentelemetry/-/opentelemetry-9.10.1.tgz#629c10f80b4ca8837c2e0b3b0d58b56d054dcff8"
integrity sha512-qqcsbIyoOPI91Tm6w0oFzsx/mlu+lywRGSVbPRFhk4zCXBOhCCp4Mg7nwKK0wGJ7AZRl6qtELrRSGClAthC55g==
"@sentry/opentelemetry@9.11.0":
version "9.11.0"
resolved "https://registry.yarnpkg.com/@sentry/opentelemetry/-/opentelemetry-9.11.0.tgz#5e3215cc98ee58d458f504d368fd3e15600814a9"
integrity sha512-B6RumUFGb1+Q4MymY7IZbdl1Ayz2srqf46itFr1ohE/IpwY7OWKMntop8fxyccUW3ptmPp9cPkBJOaa9UdJhSg==
dependencies:
"@sentry/core" "9.10.1"
"@sentry/core" "9.11.0"
"@sigstore/bundle@^3.0.0":
version "3.0.0"
@@ -2056,15 +2033,6 @@
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f"
integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==
"@snyk/github-codeowners@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@snyk/github-codeowners/-/github-codeowners-1.1.0.tgz#45b99732c3c38b5f5b47e43d2b0c9db67a6d2bcc"
integrity sha512-lGFf08pbkEac0NYgVf4hdANpAgApRjNByLXB+WBip3qj1iendOIyAwP2GKkKbQMNVy2r1xxDf0ssfWscoiC+Vw==
dependencies:
commander "^4.1.1"
ignore "^5.1.8"
p-map "^4.0.0"
"@standardnotes/electron-clear-data@^1.0.5":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@standardnotes/electron-clear-data/-/electron-clear-data-1.1.1.tgz#45eab118ed5d1ee9369b540d7e62a9ca96778335"
@@ -2189,10 +2157,10 @@
"@types/node" "*"
form-data "^4.0.0"
"@types/node@*", "@types/node@18.19.84", "@types/node@^17.0.36", "@types/node@^22.7.7":
version "18.19.84"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.84.tgz#29a1c36a9241a76351397993635f5b5fdbc2504c"
integrity sha512-ACYy2HGcZPHxEeWTqowTF7dhXN+JU1o7Gr4b41klnn6pj2LD6rsiGqSZojMdk1Jh2ys3m76ap+ae1vvE4+5+vg==
"@types/node@*", "@types/node@18.19.87", "@types/node@^17.0.36", "@types/node@^22.7.7":
version "18.19.87"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.87.tgz#690f000cc51e3c7f48bc00f7e86fac6eb550b709"
integrity sha512-OIAAu6ypnVZHmsHCeJ+7CCSub38QNBS9uceMQeg7K5Ur0Jr+wG9wEOEvvMbhp09pxD5czIUy/jND7s7Tb6Nw7A==
dependencies:
undici-types "~5.26.4"
@@ -2242,9 +2210,9 @@
"@types/pg" "*"
"@types/pg@*":
version "8.11.11"
resolved "https://registry.yarnpkg.com/@types/pg/-/pg-8.11.11.tgz#3bdce0580e521a62a62339a53d110458d9eae6df"
integrity sha512-kGT1qKM8wJQ5qlawUrEkXgvMSXoV213KfMGXcwfDwUIfUHXqXYXOfS1nE1LINRJVVVx5wCm70XnFlMHaIcQAfw==
version "8.11.13"
resolved "https://registry.yarnpkg.com/@types/pg/-/pg-8.11.13.tgz#ab785528b173d9bf8623406d7611ee0c0c715914"
integrity sha512-6kXByGkvRvwXLuyaWzsebs2du6+XuAB2CuMsuzP7uaihQahshVgSmB22Pmh0vQMkQ1h5+PZU0d+Di1o+WpVWJg==
dependencies:
"@types/node" "*"
pg-protocol "*"
@@ -2306,29 +2274,29 @@
"@types/node" "*"
"@typescript-eslint/eslint-plugin@^8.0.0":
version "8.29.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.29.0.tgz#151c4878700a5ad229ce6713d2674d58b626b3d9"
integrity sha512-PAIpk/U7NIS6H7TEtN45SPGLQaHNgB7wSjsQV/8+KYokAb2T/gloOA/Bee2yd4/yKVhPKe5LlaUGhAZk5zmSaQ==
version "8.31.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.1.tgz#62f1befe59647524994e89de4516d8dcba7a850a"
integrity sha512-oUlH4h1ABavI4F0Xnl8/fOtML/eu8nI2A1nYd+f+55XI0BLu+RIqKoCiZKNo6DtqZBEQm5aNKA20G3Z5w3R6GQ==
dependencies:
"@eslint-community/regexpp" "^4.10.0"
"@typescript-eslint/scope-manager" "8.29.0"
"@typescript-eslint/type-utils" "8.29.0"
"@typescript-eslint/utils" "8.29.0"
"@typescript-eslint/visitor-keys" "8.29.0"
"@typescript-eslint/scope-manager" "8.31.1"
"@typescript-eslint/type-utils" "8.31.1"
"@typescript-eslint/utils" "8.31.1"
"@typescript-eslint/visitor-keys" "8.31.1"
graphemer "^1.4.0"
ignore "^5.3.1"
natural-compare "^1.4.0"
ts-api-utils "^2.0.1"
"@typescript-eslint/parser@^8.0.0":
version "8.29.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.29.0.tgz#b98841e0a8099728cb8583da92326fcb7f5be1d2"
integrity sha512-8C0+jlNJOwQso2GapCVWWfW/rzaq7Lbme+vGUFKE31djwNncIpgXD7Cd4weEsDdkoZDjH0lwwr3QDQFuyrMg9g==
version "8.31.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.31.1.tgz#e9b0ccf30d37dde724ee4d15f4dbc195995cce1b"
integrity sha512-oU/OtYVydhXnumd0BobL9rkJg7wFJ9bFFPmSmB/bf/XWN85hlViji59ko6bSKBXyseT9V8l+CN1nwmlbiN0G7Q==
dependencies:
"@typescript-eslint/scope-manager" "8.29.0"
"@typescript-eslint/types" "8.29.0"
"@typescript-eslint/typescript-estree" "8.29.0"
"@typescript-eslint/visitor-keys" "8.29.0"
"@typescript-eslint/scope-manager" "8.31.1"
"@typescript-eslint/types" "8.31.1"
"@typescript-eslint/typescript-estree" "8.31.1"
"@typescript-eslint/visitor-keys" "8.31.1"
debug "^4.3.4"
"@typescript-eslint/scope-manager@8.29.0":
@@ -2339,13 +2307,21 @@
"@typescript-eslint/types" "8.29.0"
"@typescript-eslint/visitor-keys" "8.29.0"
"@typescript-eslint/type-utils@8.29.0":
version "8.29.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.29.0.tgz#98dcfd1193cb4e2b2d0294a8656ce5eb58c443a9"
integrity sha512-ahaWQ42JAOx+NKEf5++WC/ua17q5l+j1GFrbbpVKzFL/tKVc0aYY8rVSYUpUvt2hUP1YBr7mwXzx+E/DfUWI9Q==
"@typescript-eslint/scope-manager@8.31.1":
version "8.31.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.31.1.tgz#1eb52e76878f545e4add142e0d8e3e97e7aa443b"
integrity sha512-BMNLOElPxrtNQMIsFHE+3P0Yf1z0dJqV9zLdDxN/xLlWMlXK/ApEsVEKzpizg9oal8bAT5Sc7+ocal7AC1HCVw==
dependencies:
"@typescript-eslint/typescript-estree" "8.29.0"
"@typescript-eslint/utils" "8.29.0"
"@typescript-eslint/types" "8.31.1"
"@typescript-eslint/visitor-keys" "8.31.1"
"@typescript-eslint/type-utils@8.31.1":
version "8.31.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.31.1.tgz#be0f438fb24b03568e282a0aed85f776409f970c"
integrity sha512-fNaT/m9n0+dpSp8G/iOQ05GoHYXbxw81x+yvr7TArTuZuCA6VVKbqWYVZrV5dVagpDTtj/O8k5HBEE/p/HM5LA==
dependencies:
"@typescript-eslint/typescript-estree" "8.31.1"
"@typescript-eslint/utils" "8.31.1"
debug "^4.3.4"
ts-api-utils "^2.0.1"
@@ -2354,6 +2330,11 @@
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.29.0.tgz#65add70ab4ef66beaa42a5addf87dab2b05b1f33"
integrity sha512-wcJL/+cOXV+RE3gjCyl/V2G877+2faqvlgtso/ZRbTCnZazh0gXhe+7gbAnfubzN2bNsBtZjDvlh7ero8uIbzg==
"@typescript-eslint/types@8.31.1":
version "8.31.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.31.1.tgz#478ed6f7e8aee1be7b63a60212b6bffe1423b5d4"
integrity sha512-SfepaEFUDQYRoA70DD9GtytljBePSj17qPxFHA/h3eg6lPTqGJ5mWOtbXCk1YrVU1cTJRd14nhaXWFu0l2troQ==
"@typescript-eslint/typescript-estree@8.29.0":
version "8.29.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.29.0.tgz#d201a4f115327ec90496307c9958262285065b00"
@@ -2368,7 +2349,31 @@
semver "^7.6.0"
ts-api-utils "^2.0.1"
"@typescript-eslint/utils@8.29.0", "@typescript-eslint/utils@^8.23.0":
"@typescript-eslint/typescript-estree@8.31.1":
version "8.31.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.1.tgz#37792fe7ef4d3021c7580067c8f1ae66daabacdf"
integrity sha512-kaA0ueLe2v7KunYOyWYtlf/QhhZb7+qh4Yw6Ni5kgukMIG+iP773tjgBiLWIXYumWCwEq3nLW+TUywEp8uEeag==
dependencies:
"@typescript-eslint/types" "8.31.1"
"@typescript-eslint/visitor-keys" "8.31.1"
debug "^4.3.4"
fast-glob "^3.3.2"
is-glob "^4.0.3"
minimatch "^9.0.4"
semver "^7.6.0"
ts-api-utils "^2.0.1"
"@typescript-eslint/utils@8.31.1":
version "8.31.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.31.1.tgz#5628ea0393598a0b2f143d0fc6d019f0dee9dd14"
integrity sha512-2DSI4SNfF5T4oRveQ4nUrSjUqjMND0nLq9rEkz0gfGr3tg0S5KB6DhwR+WZPCjzkZl3cH+4x2ce3EsL50FubjQ==
dependencies:
"@eslint-community/eslint-utils" "^4.4.0"
"@typescript-eslint/scope-manager" "8.31.1"
"@typescript-eslint/types" "8.31.1"
"@typescript-eslint/typescript-estree" "8.31.1"
"@typescript-eslint/utils@^8.23.0":
version "8.29.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.29.0.tgz#d6d22b19c8c4812a874f00341f686b45b9fe895f"
integrity sha512-gX/A0Mz9Bskm8avSWFcK0gP7cZpbY4AIo6B0hWYFCaIsz750oaiWR4Jr2CI+PQhfW1CpcQr9OlfPS+kMFegjXA==
@@ -2386,6 +2391,14 @@
"@typescript-eslint/types" "8.29.0"
eslint-visitor-keys "^4.2.0"
"@typescript-eslint/visitor-keys@8.31.1":
version "8.31.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.1.tgz#6742b0e3ba1e0c1e35bdaf78c03e759eb8dd8e75"
integrity sha512-I+/rgqOVBn6f0o7NDTmAPWWC6NuqhV174lfYvAm9fUaWeiefLdux9/YI3/nLugEn9L8fcSi0XmpKi/r5u0nmpw==
dependencies:
"@typescript-eslint/types" "8.31.1"
eslint-visitor-keys "^4.2.0"
"@ungap/structured-clone@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406"
@@ -2533,30 +2546,30 @@ app-builder-bin@5.0.0-alpha.12:
resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-5.0.0-alpha.12.tgz#2daf82f8badc698e0adcc95ba36af4ff0650dc80"
integrity sha512-j87o0j6LqPL3QRr8yid6c+Tt5gC7xNfYo6uQIQkorAC6MpeayVMZrEDzKmJJ/Hlv7EnOQpaRm53k6ktDYZyB6w==
app-builder-lib@26.0.12:
version "26.0.12"
resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-26.0.12.tgz#2e33df936e0f78d4266b058ece90308ea981eefb"
integrity sha512-+/CEPH1fVKf6HowBUs6LcAIoRcjeqgvAeoSE+cl7Y7LndyQ9ViGPYibNk7wmhMHzNgHIuIbw4nWADPO+4mjgWw==
app-builder-lib@26.0.15:
version "26.0.15"
resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-26.0.15.tgz#3b68b71d6d9d75eb6b318bcf0c830fd3fc1147d3"
integrity sha512-KVIsAHkBLaO2fvYVAccGbQPlbGFeGkx7IJXi/nDSBDXaMwHxauIXpAtf/NpopgudG6Ovyixl4QIWeHMPIvx0kg==
dependencies:
"@develar/schema-utils" "~2.6.5"
"@electron/asar" "3.2.18"
"@electron/asar" "3.4.1"
"@electron/fuses" "^1.8.0"
"@electron/notarize" "2.5.0"
"@electron/osx-sign" "1.3.1"
"@electron/rebuild" "3.7.0"
"@electron/universal" "2.0.1"
"@electron/osx-sign" "1.3.3"
"@electron/rebuild" "3.7.2"
"@electron/universal" "2.0.3"
"@malept/flatpak-bundler" "^0.4.0"
"@types/fs-extra" "9.0.13"
async-exit-hook "^2.0.1"
builder-util "26.0.11"
builder-util-runtime "9.3.1"
builder-util "26.0.13"
builder-util-runtime "9.3.2"
chromium-pickle-js "^0.2.0"
config-file-ts "0.2.8-rc1"
debug "^4.3.4"
dotenv "^16.4.5"
dotenv-expand "^11.0.6"
ejs "^3.1.8"
electron-publish "26.0.11"
electron-publish "26.0.13"
fs-extra "^10.1.0"
hosted-git-info "^4.1.0"
is-ci "^3.0.0"
@@ -2802,23 +2815,23 @@ buffer@^5.1.0, buffer@^5.5.0:
base64-js "^1.3.1"
ieee754 "^1.1.13"
builder-util-runtime@9.3.1:
version "9.3.1"
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-9.3.1.tgz#0daedde0f6d381f2a00a50a407b166fe7dca1a67"
integrity sha512-2/egrNDDnRaxVwK3A+cJq6UOlqOdedGA7JPqCeJjN2Zjk1/QB/6QUi3b714ScIGS7HafFXTyzJEOr5b44I3kvQ==
builder-util-runtime@9.3.2:
version "9.3.2"
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-9.3.2.tgz#2a69a239b50e26accf4ed4ea1730406a3117213c"
integrity sha512-7QDXJ1FwT6d9ZhG4kuObUUPY8/ENBS/Ky26O4hR5vbeoRGavgekS2Jxv+8sCn/v23aPGU2DXRWEeJuijN2ooYA==
dependencies:
debug "^4.3.4"
sax "^1.2.4"
builder-util@26.0.11:
version "26.0.11"
resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-26.0.11.tgz#ad85b92c93f2b976b973e1d87337e0c6813fcb8f"
integrity sha512-xNjXfsldUEe153h1DraD0XvDOpqGR0L5eKFkdReB7eFW5HqysDZFfly4rckda6y9dF39N3pkPlOblcfHKGw+uA==
builder-util@26.0.13:
version "26.0.13"
resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-26.0.13.tgz#a2c11f8e89e5392719e540d610d70d8413943d74"
integrity sha512-6b64uHzywaL2KAG+rVcqk/Prta1m3I2Jo1d4d2CrApb6EeSk2V384tmSL0EniH+P8jaNbMp6qhg7cIALw32zRA==
dependencies:
"7zip-bin" "~5.2.0"
"@types/debug" "^4.1.6"
app-builder-bin "5.0.0-alpha.12"
builder-util-runtime "9.3.1"
builder-util-runtime "9.3.2"
chalk "^4.1.2"
cross-spawn "^7.0.6"
debug "^4.3.4"
@@ -3133,11 +3146,6 @@ commander@^13.1.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-13.1.0.tgz#776167db68c78f38dcce1f9b8d7b8b9a488abf46"
integrity sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==
commander@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
commander@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
@@ -3226,7 +3234,7 @@ cross-dirname@^0.1.0:
resolved "https://registry.yarnpkg.com/cross-dirname/-/cross-dirname-0.1.0.tgz#b899599f30a5389f59e78c150e19f957ad16a37c"
integrity sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==
cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3, cross-spawn@^7.0.6:
cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3, cross-spawn@^7.0.6:
version "7.0.6"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
@@ -3353,9 +3361,9 @@ delayed-stream@~1.0.0:
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
detect-libc@^2.0.0, detect-libc@^2.0.1:
version "2.0.3"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700"
integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==
version "2.0.4"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.4.tgz#f04715b8ba815e53b4d8109655b6508a6865a7e8"
integrity sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==
detect-node@^2.0.4:
version "2.1.0"
@@ -3370,14 +3378,14 @@ dir-compare@^4.2.0:
minimatch "^3.0.5"
p-limit "^3.1.0 "
dmg-builder@26.0.12:
version "26.0.12"
resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-26.0.12.tgz#6996ad0bab80a861c9a7b33ee9734d4f60566b46"
integrity sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==
dmg-builder@26.0.15:
version "26.0.15"
resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-26.0.15.tgz#0cc63db379f9713e8726d5f4ac30709b86720506"
integrity sha512-RXbDCcrPw2B0q2HIcPI2H7pIFeQiDsLW+ykRVKkW2ke2H3pTgI36r86xLmQZ6397uFCNUjpegRFv6bB+BCWJIA==
dependencies:
app-builder-lib "26.0.12"
builder-util "26.0.11"
builder-util-runtime "9.3.1"
app-builder-lib "26.0.15"
builder-util "26.0.13"
builder-util-runtime "9.3.2"
fs-extra "^10.1.0"
iconv-lite "^0.6.2"
js-yaml "^4.1.0"
@@ -3461,25 +3469,25 @@ ejs@^3.1.8:
dependencies:
jake "^10.8.5"
electron-builder-squirrel-windows@26.0.12:
version "26.0.12"
resolved "https://registry.yarnpkg.com/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-26.0.12.tgz#21ff5d8b764a4feb73f7c25fabcaab5109d60385"
integrity sha512-kpwXM7c/ayRUbYVErQbsZ0nQZX4aLHQrPEG9C4h9vuJCXylwFH8a7Jgi2VpKIObzCXO7LKHiCw4KdioFLFOgqA==
electron-builder-squirrel-windows@26.0.15:
version "26.0.15"
resolved "https://registry.yarnpkg.com/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-26.0.15.tgz#34458b57db75bbaec9a3263bf678517438a19aea"
integrity sha512-NAPShr9weifHIn2JXdnZ8P4DfQg60NCiYPF42S1yR+S9YQQ/8cG3lSeoZ/LGPFO9Cf3MoXlbwqa+SSpEb3xXYw==
dependencies:
app-builder-lib "26.0.12"
builder-util "26.0.11"
app-builder-lib "26.0.15"
builder-util "26.0.13"
electron-winstaller "5.4.0"
electron-builder@26.0.12:
version "26.0.12"
resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-26.0.12.tgz#797af2e70efdd96c9ea5d8a8164b8728c90d65ff"
integrity sha512-cD1kz5g2sgPTMFHjLxfMjUK5JABq3//J4jPswi93tOPFz6btzXYtK5NrDt717NRbukCUDOrrvmYVOWERlqoiXA==
electron-builder@26.0.15:
version "26.0.15"
resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-26.0.15.tgz#db1cd0569e079686107c0c6315435b57fbcb7bb0"
integrity sha512-1nDY/7bbbORdWPQkIyFPfLfEHR4d22QfI5yec+etFL0y/PdmVz/wcxXc2KRpTQeIt75njm2/ocrtgp7LJvZC3Q==
dependencies:
app-builder-lib "26.0.12"
builder-util "26.0.11"
builder-util-runtime "9.3.1"
app-builder-lib "26.0.15"
builder-util "26.0.13"
builder-util-runtime "9.3.2"
chalk "^4.1.2"
dmg-builder "26.0.12"
dmg-builder "26.0.15"
fs-extra "^10.1.0"
is-ci "^3.0.0"
lazy-val "^1.0.5"
@@ -3493,14 +3501,14 @@ electron-devtools-installer@^4.0.0:
dependencies:
unzip-crx-3 "^0.2.0"
electron-publish@26.0.11:
version "26.0.11"
resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-26.0.11.tgz#92c9329a101af2836d9d228c82966eca1eee9a7b"
integrity sha512-a8QRH0rAPIWH9WyyS5LbNvW9Ark6qe63/LqDB7vu2JXYpi0Gma5Q60Dh4tmTqhOBQt0xsrzD8qE7C+D7j+B24A==
electron-publish@26.0.13:
version "26.0.13"
resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-26.0.13.tgz#04340520e6e9de5262fecfa011658cfcc3fc8917"
integrity sha512-O5hfHSwli5cegQ4JS3Dp0dZcheex6UCRE/qYyRQvhB6DhSwojiwTnAGEuQCJXc8K8Zxz2lku5Du3VwYHf8d5Lw==
dependencies:
"@types/fs-extra" "^9.0.11"
builder-util "26.0.11"
builder-util-runtime "9.3.1"
builder-util "26.0.13"
builder-util-runtime "9.3.2"
chalk "^4.1.2"
form-data "^4.0.0"
fs-extra "^10.1.0"
@@ -3541,10 +3549,10 @@ electron-winstaller@5.4.0:
optionalDependencies:
"@electron/windows-sign" "^1.1.2"
electron@35.1.4:
version "35.1.4"
resolved "https://registry.yarnpkg.com/electron/-/electron-35.1.4.tgz#53f51c3488e2c49828ce9453e60d60d14fb441d5"
integrity sha512-8HjE2wqxY//T09Of8k1eTpK/NeTG2FkTyRD+fyKXmec4wZVscGgZcmWFC0HYN4ktyHAjtplpxdFXjtqRnvzBMg==
electron@36.0.0:
version "36.0.0"
resolved "https://registry.yarnpkg.com/electron/-/electron-36.0.0.tgz#ffbe7ca9edecaee53617f29a088be10bbed9a45f"
integrity sha512-MhBL5tgzqLsiw++YXxzXRvF5s90gelcEZP4Upz/aaRmmoscmCw/EtimxMSH6EPnKt+8KwBY9RVAdlcffFPYkyw==
dependencies:
"@electron/get" "^2.0.0"
"@types/node" "^22.7.7"
@@ -3772,9 +3780,9 @@ eslint-config-google@^0.14.0:
integrity sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==
eslint-config-prettier@^10.0.0:
version "10.1.1"
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-10.1.1.tgz#cf0ff6e5c4e7e15f129f1f1ce2a5ecba92dec132"
integrity sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==
version "10.1.2"
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-10.1.2.tgz#31a4b393c40c4180202c27e829af43323bf85276"
integrity sha512-Epgp/EofAUeEpIdZkW60MHKvPyru1ruQJxPL+WIycnaPApuseK0Zpkrh/FwL9oIpQvIhJwV7ptOy0DWUjTlCiA==
eslint-import-resolver-node@^0.3.9:
version "0.3.9"
@@ -4060,7 +4068,7 @@ fast-uri@^3.0.1:
resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.6.tgz#88f130b77cfaea2378d56bf970dea21257a68748"
integrity sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==
fastq@^1.15.0, fastq@^1.6.0:
fastq@^1.6.0:
version "1.19.1"
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5"
integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==
@@ -4138,11 +4146,11 @@ foreachasync@^3.0.0:
integrity sha512-J+ler7Ta54FwwNcx6wQRDhTIbNeyDcARMkOcguEqnEdtm0jKvN3Li3PDAb2Du3ubJYEWfYL83XMROXdsXAXycw==
foreground-child@^3.1.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77"
integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==
version "3.3.1"
resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f"
integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==
dependencies:
cross-spawn "^7.0.0"
cross-spawn "^7.0.6"
signal-exit "^4.0.1"
form-data@^4.0.0:
@@ -4369,9 +4377,9 @@ glob@^10.2.2, glob@^10.3.10, glob@^10.3.12, glob@^10.3.7:
path-scurry "^1.11.1"
glob@^11.0.0:
version "11.0.1"
resolved "https://registry.yarnpkg.com/glob/-/glob-11.0.1.tgz#1c3aef9a59d680e611b53dcd24bb8639cef064d9"
integrity sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==
version "11.0.2"
resolved "https://registry.yarnpkg.com/glob/-/glob-11.0.2.tgz#3261e3897bbc603030b041fd77ba636022d51ce0"
integrity sha512-YT7U7Vye+t5fZ/QMkBFrTJ7ZQxInIUjwyAjVj84CYXqgBdv30MFUPGnBR6sQaVq6Is15wYJUsnzTuWaGRBhBAQ==
dependencies:
foreground-child "^3.1.0"
jackspeak "^4.0.1"
@@ -4659,7 +4667,7 @@ ignore-walk@^7.0.0:
dependencies:
minimatch "^9.0.0"
ignore@^5.1.8, ignore@^5.2.0, ignore@^5.3.1, ignore@^5.3.2:
ignore@^5.2.0, ignore@^5.3.1, ignore@^5.3.2:
version "5.3.2"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==
@@ -4981,9 +4989,9 @@ jackspeak@^3.1.2:
"@pkgjs/parseargs" "^0.11.0"
jackspeak@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-4.0.2.tgz#11f9468a3730c6ff6f56823a820d7e3be9bef015"
integrity sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==
version "4.1.0"
resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-4.1.0.tgz#c489c079f2b636dc4cbe9b0312a13ff1282e561b"
integrity sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==
dependencies:
"@isaacs/cliui" "^8.0.2"
@@ -5143,12 +5151,11 @@ keyv@^4.0.0, keyv@^4.5.3:
json-buffer "3.0.1"
knip@^5.0.0:
version "5.46.5"
resolved "https://registry.yarnpkg.com/knip/-/knip-5.46.5.tgz#e554a26974f6686a4371f25ea295a67e04ea20be"
integrity sha512-w5t4K/raY8R8nJ9TZZBi/rZNsrJie6qYUJiL+A8l/4/002WQwzBfFMJftEo1opxgsV0ounFPJYy/9AAw3CO4Rg==
version "5.51.0"
resolved "https://registry.yarnpkg.com/knip/-/knip-5.51.0.tgz#b9d477d32811da292c03cd74c55e5ea8862ea4c8"
integrity sha512-gw5TzLt9FikIk1oPWDc7jPRb/+L3Aw1ia25hWUQBb+hXS/Rbdki/0rrzQygjU5/CVYnRWYqc1kgdNi60Jm1lPg==
dependencies:
"@nodelib/fs.walk" "3.0.1"
"@snyk/github-codeowners" "1.1.0"
"@nodelib/fs.walk" "^1.2.3"
easy-table "1.2.0"
enhanced-resolve "^5.18.1"
fast-glob "^3.3.3"
@@ -5160,7 +5167,6 @@ knip@^5.0.0:
pretty-ms "^9.0.0"
smol-toml "^1.3.1"
strip-json-comments "5.0.1"
summary "2.1.0"
zod "^3.22.4"
zod-validation-error "^3.0.3"
@@ -5195,9 +5201,9 @@ lines-and-columns@^1.1.6:
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
lint-staged@^15.2.10:
version "15.5.0"
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-15.5.0.tgz#fa6464cfb06e0faf5bb167f83186e952ff6e569e"
integrity sha512-WyCzSbfYGhK7cU+UuDDkzUiytbfbi0ZdPy2orwtM75P3WTtQBzmG40cCxIa8Ii2+XjfxzLH6Be46tUfWS85Xfg==
version "15.5.1"
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-15.5.1.tgz#6de35298964641b8b6e060d3db0fb6ac866c6e24"
integrity sha512-6m7u8mue4Xn6wK6gZvSCQwBvMBR36xfY24nF5bMTf2MHDYG6S3yhJuOgdYVw99hsjyDt2d4z168b3naI8+NWtQ==
dependencies:
chalk "^5.4.1"
commander "^13.1.0"
@@ -5211,9 +5217,9 @@ lint-staged@^15.2.10:
yaml "^2.7.0"
listr2@^8.2.5:
version "8.2.5"
resolved "https://registry.yarnpkg.com/listr2/-/listr2-8.2.5.tgz#5c9db996e1afeb05db0448196d3d5f64fec2593d"
integrity sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==
version "8.3.2"
resolved "https://registry.yarnpkg.com/listr2/-/listr2-8.3.2.tgz#c252ec9a3334950bfca9238457d0ad2c1a5cc867"
integrity sha512-vsBzcU4oE+v0lj4FhVLzr9dBTv4/fHIa57l+GCwovP8MoFNZJTOhGU8PXd4v2VJCbECAaijBiHntiekFMLvo0g==
dependencies:
cli-truncate "^4.0.0"
colorette "^2.0.20"
@@ -5281,9 +5287,9 @@ lru-cache@^10.0.1, lru-cache@^10.2.0:
integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
lru-cache@^11.0.0:
version "11.0.2"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.0.2.tgz#fbd8e7cf8211f5e7e5d91905c415a3f55755ca39"
integrity sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==
version "11.1.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.1.0.tgz#afafb060607108132dbc1cf8ae661afb69486117"
integrity sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==
lru-cache@^5.1.1:
version "5.1.1"
@@ -5635,12 +5641,12 @@ negotiator@^1.0.0:
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a"
integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==
node-abi@^3.3.0, node-abi@^3.45.0:
version "3.74.0"
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.74.0.tgz#5bfb4424264eaeb91432d2adb9da23c63a301ed0"
integrity sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==
node-abi@4.4.0, node-abi@^3.3.0, node-abi@^3.45.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-4.4.0.tgz#f17a2880a556337030a02b7f92e308946cdbbfc9"
integrity sha512-+sBEWs/HZ3ZDBtPSPKfYndkTF9ebr1BJm/z2TBDJj/upiOx9J6BeGXRtFyOXz1r6vUqzsCRM5pUr+K83i64agg==
dependencies:
semver "^7.3.5"
semver "^7.6.3"
node-addon-api@^1.6.3:
version "1.7.2"
@@ -6149,17 +6155,17 @@ pidtree@^0.6.0:
resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c"
integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==
playwright-core@1.51.1:
version "1.51.1"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.51.1.tgz#d57f0393e02416f32a47cf82b27533656a8acce1"
integrity sha512-/crRMj8+j/Nq5s8QcvegseuyeZPxpQCZb6HNk3Sos3BlZyAknRjoyJPFWkpNn8v0+P3WiwqFF8P+zQo4eqiNuw==
playwright-core@1.52.0:
version "1.52.0"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.52.0.tgz#238f1f0c3edd4ebba0434ce3f4401900319a3dca"
integrity sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==
playwright@1.51.1:
version "1.51.1"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.51.1.tgz#ae1467ee318083968ad28d6990db59f47a55390f"
integrity sha512-kkx+MB2KQRkyxjYPc3a0wLZZoDczmppyGJIvQ43l+aZihkaVvmu/21kiyaHeHjiFxjxNNFnUncKmcGIyOojsaw==
playwright@1.52.0:
version "1.52.0"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.52.0.tgz#26cb9a63346651e1c54c8805acfd85683173d4bd"
integrity sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==
dependencies:
playwright-core "1.51.1"
playwright-core "1.52.0"
optionalDependencies:
fsevents "2.3.2"
@@ -6624,7 +6630,7 @@ roarr@^2.15.3:
semver-compare "^1.0.0"
sprintf-js "^1.1.2"
run-parallel@^1.1.9, run-parallel@^1.2.0:
run-parallel@^1.1.9:
version "1.2.0"
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
@@ -6837,9 +6843,9 @@ smart-buffer@^4.0.2, smart-buffer@^4.2.0:
integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
smol-toml@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/smol-toml/-/smol-toml-1.3.1.tgz#d9084a9e212142e3cab27ef4e2b8e8ba620bfe15"
integrity sha512-tEYNll18pPKHroYSmLLrksq233j021G0giwW7P3D24jC54pQ5W5BXMsQ/Mvw1OJCmEYDgY+lrzT+3nNUtoNfXQ==
version "1.3.4"
resolved "https://registry.yarnpkg.com/smol-toml/-/smol-toml-1.3.4.tgz#4ec76e0e709f586bc50ba30eb79024173c2b2221"
integrity sha512-UOPtVuYkzYGee0Bd2Szz8d2G3RfMfJ2t3qVdZUAozZyAk+a0Sxa+QKix0YCwjL/A1RR0ar44nCxaoN9FxdJGwA==
socks-proxy-agent@^7.0.0:
version "7.0.0"
@@ -7085,11 +7091,6 @@ sumchecker@^3.0.1:
dependencies:
debug "^4.1.0"
summary@2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/summary/-/summary-2.1.0.tgz#be8a49a0aa34eb6ceea56042cae88f8add4b0885"
integrity sha512-nMIjMrd5Z2nuB2RZCKJfFMjgS3fygbeyGk9PxPPaJR1RIcyN9yn4A63Isovzm3ZtQuEkLBVgMdPup8UeLH7aQw==
supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
@@ -7335,10 +7336,10 @@ typed-array-length@^1.0.6:
is-typed-array "^1.1.13"
possible-typed-array-names "^1.0.0"
typescript@5.8.2:
version "5.8.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.2.tgz#8170b3702f74b79db2e5a96207c15e65807999e4"
integrity sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==
typescript@5.8.3:
version "5.8.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e"
integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
typescript@^5.4.3:
version "5.5.4"
@@ -7653,9 +7654,9 @@ yallist@^5.0.0:
integrity sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==
yaml@^2.7.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.7.0.tgz#aef9bb617a64c937a9a748803786ad8d3ffe1e98"
integrity sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==
version "2.7.1"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.7.1.tgz#44a247d1b88523855679ac7fa7cda6ed7e135cf6"
integrity sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==
yargs-parser@^21.1.1:
version "21.1.1"
@@ -7694,6 +7695,6 @@ zod-validation-error@^3.0.3:
integrity sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==
zod@^3.22.4:
version "3.24.2"
resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.2.tgz#8efa74126287c675e92f46871cfc8d15c34372b3"
integrity sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==
version "3.24.3"
resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.3.tgz#1f40f750a05e477396da64438e0e1c0995dafd87"
integrity sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==