diff --git a/.github/workflows/desktop.yml b/.github/workflows/desktop.yml new file mode 100644 index 00000000..b9378bc1 --- /dev/null +++ b/.github/workflows/desktop.yml @@ -0,0 +1,64 @@ +name: Build Desktop App + +on: + workflow_dispatch: + release: + types: [published, prereleased] + +jobs: + build: + name: Build on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 9 + + - name: Install Dependencies + run: pnpm install --frozen-lockfile + + - name: Build and Bundle + run: | + pnpm --filter clipcc-desktop run fetch-library + pnpm --filter clipcc-desktop run bundle:dist + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload to Release + uses: softprops/action-gh-release@v2 + if: github.event_name == 'release' + with: + files: | + app/desktop/dist/*.exe + app/desktop/dist/*.zip + app/desktop/dist/*.dmg + app/desktop/dist/*.AppImage + app/desktop/dist/*.deb + app/desktop/dist/*.rpm + + - name: Upload to Aurora Release + uses: softprops/action-gh-release@v2 + if: github.event_name == 'workflow_dispatch' + with: + tag_name: aurora + files: | + app/desktop/dist/*.exe + app/desktop/dist/*.zip + app/desktop/dist/*.dmg + app/desktop/dist/*.AppImage + app/desktop/dist/*.deb + app/desktop/dist/*.rpm diff --git a/app/desktop/.env.example b/app/desktop/.env.example new file mode 100644 index 00000000..5e0ff27a --- /dev/null +++ b/app/desktop/.env.example @@ -0,0 +1,15 @@ +# electron-builder signing placeholders for distribution builds (`--mode=dist`) +# Fill these in CI/local secret store as needed. + +# Windows/macOS code signing certificate +CSC_LINK= +CSC_KEY_PASSWORD= + +# Optional Windows-specific override certificate (when different from CSC_*) +WIN_CSC_LINK= +WIN_CSC_KEY_PASSWORD= + +# Optional macOS notarization (recommended App Store Connect API key method) +APPLE_API_KEY= +APPLE_API_KEY_ID= +APPLE_API_ISSUER= diff --git a/app/desktop/.gitignore b/app/desktop/.gitignore new file mode 100644 index 00000000..501cf485 --- /dev/null +++ b/app/desktop/.gitignore @@ -0,0 +1,30 @@ +# Mac OS +.DS_Store + +# Windows +thumbs.db + +# NPM +/node_modules +npm-* + +# Testing +/.nyc_output +/coverage +.eslintcache + +# Build +/build +/dist +/.opt-in +/*.provisionprofile + +# don't store the assets downloaded with the `fetch` script +/static/assets/ + +# generated translation files +/translations +/locale + +# Environment +.env diff --git a/app/desktop/LICENSE b/app/desktop/LICENSE new file mode 100644 index 00000000..8af18b59 --- /dev/null +++ b/app/desktop/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Clipteam + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/app/desktop/README.md b/app/desktop/README.md new file mode 100644 index 00000000..1932038e --- /dev/null +++ b/app/desktop/README.md @@ -0,0 +1,61 @@ +# clipcc-desktop +ClipCC as a standalone desktop application. + +## Installation + +### From GitHub + +See [Releases](https://github.com/Clipteam/clipcc/releases). +We always release the latest version on GitHub, please download it from there if you want to be up-to-date. + +### From Package Managers + +### WinGet (Windows users) + +> The WinGet package is maintained by the community and may not be up-to-date. + +On Windows, you can use winget to install ClipCC. + +```powershell +winget install ClipTeam.ClipCC +``` +### AUR (Arch Linux users) + +> The WinGet package is maintained by the community and may not be up-to-date. + +For Arch Linux users, you can install the AUR package [clipcc](https://aur.archlinux.org/packages/clipcc) or [clipcc-beta-bin](https://aur.archlinux.org/packages/clipcc-beta-bin): +```bash +yay -S clipcc +``` +Or +```bash +yay -S clipcc-beta-bin +``` +_Note that these two packages conflict with each other._ + +## Development + +> Since desktop is placed in the monorepo, you need to set up the monorepo first. Please refer to the [contributing guide](/CONTRIBUTING.md) for instructions. +> All commands below are run in the root directory. + +You need to fetch library assets from server for the first time and need to update them: +```bash +pnpm desktop fetch-library +``` +If you need to start the development server, run: +```bash +pnpm desktop start +``` +It will use webpack-dev-server to serve the renderer process and use regular webpack to build and electron to serve the main process. The renderer process will automatically reload when you make changes, and restart the electron process when you make changes to the main or preload part. + +To build the application for development purposes, run: +```bash +pnpm desktop bundle:dev # or pnpm desktop bundle:dir +``` +The build artifacts will be placed in `dist/win32-unpacked`. +For production build, run: +```bash +pnpm desktop bundle:dist +``` + +You may need a code signing certificate and modify `.env` to build the application for production. Please refer to the [code signing guide](https://www.electron.build/code-signing) for more details. diff --git a/app/desktop/buildResources/.gitignore b/app/desktop/buildResources/.gitignore new file mode 100644 index 00000000..75adfab8 --- /dev/null +++ b/app/desktop/buildResources/.gitignore @@ -0,0 +1,6 @@ +/ClipCC.iconset +/tmp +/app.icns +/app.ico +/icon/ +/appx/*.png diff --git a/app/desktop/buildResources/entitlements.mac.plist b/app/desktop/buildResources/entitlements.mac.plist new file mode 100644 index 00000000..a8e622f3 --- /dev/null +++ b/app/desktop/buildResources/entitlements.mac.plist @@ -0,0 +1,24 @@ + + + + +com.apple.security.cs.allow-dyld-environment-variables + +com.apple.security.cs.allow-jit + +com.apple.security.cs.allow-unsigned-executable-memory + +com.apple.security.device.audio-input + +com.apple.security.device.camera + +com.apple.security.device.microphone + +com.apple.security.files.user-selected.read-only + +com.apple.security.files.user-selected.read-write + +com.apple.security.network.client + + + diff --git a/app/desktop/buildResources/entitlements.mas.inherit.plist b/app/desktop/buildResources/entitlements.mas.inherit.plist new file mode 100644 index 00000000..8c3993fc --- /dev/null +++ b/app/desktop/buildResources/entitlements.mas.inherit.plist @@ -0,0 +1,10 @@ + + + + +com.apple.security.app-sandbox + +com.apple.security.inherit + + + diff --git a/app/desktop/buildResources/entitlements.mas.plist b/app/desktop/buildResources/entitlements.mas.plist new file mode 100644 index 00000000..58351e70 --- /dev/null +++ b/app/desktop/buildResources/entitlements.mas.plist @@ -0,0 +1,26 @@ + + + + +com.apple.security.app-sandbox + +com.apple.security.cs.allow-dyld-environment-variables + +com.apple.security.cs.allow-jit + +com.apple.security.cs.allow-unsigned-executable-memory + +com.apple.security.device.audio-input + +com.apple.security.device.camera + +com.apple.security.device.microphone + +com.apple.security.files.user-selected.read-only + +com.apple.security.files.user-selected.read-write + +com.apple.security.network.client + + + diff --git a/app/desktop/buildResources/install.nsh b/app/desktop/buildResources/install.nsh new file mode 100644 index 00000000..159a1f4d --- /dev/null +++ b/app/desktop/buildResources/install.nsh @@ -0,0 +1,40 @@ +!macro customInstall + #WriteRegStr HKCR "clipcc" "" "URL:clipcc" + #WriteRegStr HKCR "clipcc" "URL Protocol" "" + #WriteRegStr HKCR "clipcc\shell\open\command" "" '"$INSTDIR\ClipCC 3.exe"' + + WriteRegStr HKCR ".sb2" "" "clipcc.sb2" + WriteRegStr HKCR ".sb2" "Content Type" "application/x-zip-compressed" + WriteRegStr HKCR ".sb2" "PerceivedType" "compressed" + WriteRegStr HKCR ".sb2\OpenWithProgIds" "clipcc.sb2" "" + + WriteRegStr HKCR ".sb3" "" "clipcc.sb3" + WriteRegStr HKCR ".sb3" "Content Type" "application/x-zip-compressed" + WriteRegStr HKCR ".sb3" "PerceivedType" "compressed" + WriteRegStr HKCR ".sb3\OpenWithProgIds" "clipcc.sb3" "" + + WriteRegStr HKCR ".cc3" "" "clipcc.cc3" + WriteRegStr HKCR ".cc3" "Content Type" "application/x-zip-compressed" + WriteRegStr HKCR ".cc3" "PerceivedType" "compressed" + WriteRegStr HKCR ".cc3\OpenWithProgIds" "clipcc.cc3" "" + + WriteRegStr HKCR ".ccx" "" "clipcc.ccx" + WriteRegStr HKCR ".ccx" "Content Type" "application/x-zip-compressed" + WriteRegStr HKCR ".ccx" "PerceivedType" "compressed" + WriteRegStr HKCR ".cc3\OpenWithProgIds" "clipcc.ccx" "" + + WriteRegStr HKCR "clipcc.sb2" "" "Scratch 2 File" + WriteRegStr HKCR "clipcc.sb2\DefaultIcon" "" '"$INSTDIR\resources\icon\cc3.ico"' + WriteRegStr HKCR "clipcc.sb2\shell\open\command" "" '"$INSTDIR\ClipCC 3.exe" "%1"' + + WriteRegStr HKCR "clipcc.sb3" "" "Scratch 3 File" + WriteRegStr HKCR "clipcc.sb3\DefaultIcon" "" '"$INSTDIR\resources\icon\cc3.ico"' + WriteRegStr HKCR "clipcc.sb3\shell\open\command" "" '"$INSTDIR\ClipCC 3.exe" "%1"' + + WriteRegStr HKCR "clipcc.cc3" "" "ClipCC 3 File" + WriteRegStr HKCR "clipcc.cc3\DefaultIcon" "" '"$INSTDIR\resources\icon\cc3.ico"' + WriteRegStr HKCR "clipcc.cc3\shell\open\command" "" '"$INSTDIR\ClipCC 3.exe" "%1"' + + WriteRegStr HKCR "clipcc.ccx" "" "ClipCC 3 Extension" + WriteRegStr HKCR "clipcc.ccx\DefaultIcon" "" '"$INSTDIR\resources\icon\ccx.ico"' +!macroend diff --git a/app/desktop/electron-builder.yaml b/app/desktop/electron-builder.yaml new file mode 100644 index 00000000..e78c6104 --- /dev/null +++ b/app/desktop/electron-builder.yaml @@ -0,0 +1,64 @@ +appId: com.codingclip.clipcc3 +productName: ClipCC +electronVersion: 41.2.0 +artifactName: clipcc-${version}-${os}-${arch}.${ext} +copyright: Copyright © 2019-2026 Clip Team. +compression: maximum +publish: null + +directories: + buildResources: buildResources + output: dist + +files: + - dist/main/**/* + - dist/renderer/**/* + - package.json + +extraResources: + - from: buildResources/icon + to: icon + +mac: + category: public.app-category.education + icon: buildResources/app.icns + entitlements: buildResources/entitlements.mac.plist + entitlementsInherit: buildResources/entitlements.mas.inherit.plist + hardenedRuntime: true + target: + - target: dmg + extendInfo: + NSCameraUsageDescription: >- + This app requires camera access when using the video sensing blocks. + NSMicrophoneUsageDescription: >- + This app requires microphone access when recording sounds or detecting loudness. + +dmg: + title: ClipCC ${version} + +win: + icon: buildResources/app.ico + target: + - target: nsis + arch: + - x64 + - ia32 + - target: zip + arch: + - x64 + +nsis: + oneClick: false + allowElevation: true + allowToChangeInstallationDirectory: true + createDesktopShortcut: true + createStartMenuShortcut: true + license: ../../LICENSE + include: buildResources/install.nsh + +linux: + category: Education + target: + - target: AppImage + - target: deb + - target: rpm diff --git a/app/desktop/eslint.config.mjs b/app/desktop/eslint.config.mjs new file mode 100644 index 00000000..ce98401c --- /dev/null +++ b/app/desktop/eslint.config.mjs @@ -0,0 +1,41 @@ +import clipccConfig from 'eslint-config-clipcc'; +import clipccNode from 'eslint-config-clipcc/node.js'; +import clipccES6 from 'eslint-config-clipcc/es6.js'; +import clipccReact from 'eslint-config-clipcc/react.js'; +import clipccTS from 'eslint-config-clipcc/ts.js'; +import globals from 'globals'; + +export default [ + ...clipccConfig, + ...clipccNode, + ...clipccES6, + ...clipccReact.map(config => ({ + ...config, + files: ['src/**/*.{js,jsx}'] + })), + ...clipccTS.map(config => ({ + ...config, + files: ['src/**/*.{ts,tsx}'] + })), + { + files: ['scripts/**/*.{js,ts,mjs}'], + rules: { + 'no-console': 'off' + } + }, + { + files: ['src/renderer/**/*.{js,jsx,ts,tsx}'], + languageOptions: { + globals: { + ...globals.browser + } + } + }, + { + ignores: [ + 'node_modules/**', + 'dist/**', + 'static/**' + ] + } +]; diff --git a/app/desktop/package.json b/app/desktop/package.json new file mode 100644 index 00000000..f213d0b7 --- /dev/null +++ b/app/desktop/package.json @@ -0,0 +1,70 @@ +{ + "name": "clipcc-desktop", + "displayName": "ClipCC", + "private": true, + "productName": "ClipCC", + "version": "3.2.0", + "description": "ClipCC as a self-contained desktop application.", + "author": { + "name": "Clip Team", + "email": "support@codingclip.com" + }, + "license": "MIT", + "homepage": "https://github.com/Clipteam/clipcc", + "repository": { + "type": "git", + "url": "https://github.com/Clipteam/clipcc.git" + }, + "main": "dist/main/index.js", + "scripts": { + "fetch-library": "rimraf ./static/assets/ && mkdirp ./static/assets/ && node ./scripts/fetchMediaLibraryAssets.js", + "build:resources": "node ./scripts/generate-build-resources.mjs", + "lint": "eslint .", + "clean": "rimraf dist", + "build:main": "webpack --env target=main", + "build:preload": "webpack --env target=preload", + "build:renderer": "webpack --env target=renderer", + "build": "pnpm run build:resources && pnpm run build:main && pnpm run build:preload && pnpm run build:renderer", + "bundle:dir": "pnpm run clean && pnpm run build && node ./scripts/electron-builder-wrapper.mjs --mode=dir", + "bundle:dev": "pnpm run clean && pnpm run build && node ./scripts/electron-builder-wrapper.mjs --mode=dev", + "bundle:dist": "pnpm run clean && cross-env NODE_ENV=production pnpm run build && node ./scripts/electron-builder-wrapper.mjs --mode=dist", + "start": "node ./scripts/dev.mjs" + }, + "devDependencies": { + "@types/lodash.bindall": "^4.4.9", + "@types/lodash.omit": "^4.5.9", + "@types/node": "^22.15.30", + "@types/react": "16.1.0", + "@types/react-dom": "16.0.11", + "clipcc-gui": "workspace:~", + "clipcc-storage": "workspace:~", + "clipcc-vm": "workspace:~", + "copy-webpack-plugin": "^14.0.0", + "cross-env": "^10.1.0", + "css-loader": "6.7.3", + "electron": "^41.2.0", + "electron-builder": "^26.8.1", + "esbuild-loader": "^4.4.3", + "eslint": "^9.39.2", + "eslint-config-clipcc": "workspace:~", + "globals": "^16.5.0", + "lodash.bindall": "4.4.0", + "node-polyfill-webpack-plugin": "^3.0.0", + "png2icons": "^2.0.1", + "postcss-import": "^12.0.0", + "postcss-loader": "7.0.2", + "react": "catalog:", + "react-dom": "16.2.1", + "react-redux": "5.0.7", + "redux": "3.7.2", + "rimraf": "^6.1.3", + "rule-inheritance-webpack-plugin": "^0.4.0", + "sharp": "^0.34.4", + "style-loader": "^4.0.0", + "ts-loader": "^9.5.4", + "typescript": "catalog:", + "webpack": "catalog:", + "webpack-cli": "^6.0.1", + "webpack-dev-server": "^5.2.3" + } +} diff --git a/app/desktop/scripts/dev.mjs b/app/desktop/scripts/dev.mjs new file mode 100644 index 00000000..e63e0d26 --- /dev/null +++ b/app/desktop/scripts/dev.mjs @@ -0,0 +1,425 @@ +import {spawn} from 'node:child_process'; +import path from 'node:path'; +import process from 'node:process'; +import electronPath from 'electron'; +import webpack from 'webpack'; +import WebpackDevServer from 'webpack-dev-server'; +import configFactory from '../webpack.config.mjs'; + +/** @typedef {'main' | 'preload' | 'renderer'} Target */ +/** @typedef {'main' | 'preload'} NodeTarget */ +/** @typedef {import('node:child_process').ChildProcess} ChildProcess */ +/** @typedef {import('webpack').Compiler} Compiler */ +/** @typedef {import('webpack').Configuration} WebpackConfiguration */ +/** @typedef {import('webpack').Stats} Stats */ +/** @typedef {import('webpack').Watching} Watching */ +/** @typedef {import('webpack-dev-server').Configuration} DevServerConfiguration */ + +const scriptsDir = path.dirname(import.meta.filename); +const desktopDir = path.resolve(scriptsDir, '..'); +const nodeTargets = /** @type {const} */ (['main', 'preload']); + +/** @type {ChildProcess | null} */ +let electronProcess = null; +/** @type {WebpackDevServer | null} */ +let rendererServer = null; +/** @type {Compiler | null} */ +let rendererCompiler = null; +/** @type {Watching[]} */ +const nodeWatchers = []; +/** @type {Compiler[]} */ +const nodeCompilers = []; +/** @type {Set} */ +const readyNodeTargets = new Set(); +/** @type {ReturnType | null} */ +let restartTimer = null; +let rendererReady = false; +let isRestartingElectron = false; +let isShuttingDown = false; + +if (process.cwd() !== desktopDir) { + process.chdir(desktopDir); +} + +/** + * Print a simple scoped log message. + * @param {string} scope - Short log prefix. + * @param {string} message - Message to print. + */ +const log = (scope, message) => { + console.log(`[${scope}] ${message}`); +}; + +/** + * Normalize a config from the shared webpack factory. + * @param {Target} target - Requested webpack target. + * @returns {WebpackConfiguration} Normalized single-target config. + */ +const getConfig = target => { + const config = configFactory({target}); + if (!config || Array.isArray(config)) { + throw new Error(`Expected a single webpack config for ${target}`); + } + + return { + ...config, + context: config.context ?? desktopDir + }; +}; + +/** + * Print warnings and errors from a webpack build. + * @param {NodeTarget} target - Node-side target that finished building. + * @param {Stats} stats - Webpack stats for that build. + * @returns {boolean} True when the build succeeded. + */ +const handleNodeBuildResult = (target, stats) => { + const output = stats.toString({ + colors: true, + preset: 'errors-warnings', + timings: true + }); + + if (output) { + console.log(output); + } + + if (stats.hasErrors()) { + log(target, 'build failed; keeping the current Electron process running'); + return false; + } + + const buildTime = typeof stats.endTime === 'number' && typeof stats.startTime === 'number' ? + ` in ${stats.endTime - stats.startTime} ms` : + ''; + + log(target, `built successfully${buildTime}`); + return true; +}; + +/** + * Print warnings and errors from renderer builds. + * @param {Stats} stats - Webpack stats for the renderer build. + * @returns {boolean} True when the build succeeded. + */ +const handleRendererBuildResult = stats => { + const output = stats.toString({ + colors: true, + preset: 'errors-warnings', + timings: true + }); + + if (output) { + console.log(output); + } + + if (stats.hasErrors()) { + log('renderer', 'build failed; waiting for a successful rebuild before launching Electron'); + return false; + } + + const buildTime = typeof stats.endTime === 'number' && typeof stats.startTime === 'number' ? + ` in ${stats.endTime - stats.startTime} ms` : + ''; + + log('renderer', `built successfully${buildTime}`); + return true; +}; + +/** + * Launch the Electron app against the renderer dev server. + * @param {string} reason - Why Electron is being launched. + */ +const startElectron = reason => { + if (electronProcess || isShuttingDown) { + return; + } + + const port = getConfig('renderer').devServer?.port; + if (!port) { + throw new Error('Renderer webpack config is missing devServer.port setting'); + } + + log('electron', reason); + electronProcess = spawn(electronPath, [desktopDir], { + cwd: desktopDir, + env: { + ...process.env, + ELECTRON_WEBPACK_WDS_PORT: port + }, + stdio: 'inherit' + }); + + electronProcess.once('error', error => { + console.error(error); + electronProcess = null; + shutdown(1); + }); + + electronProcess.once('exit', (code, signal) => { + const wasRestarting = isRestartingElectron; + electronProcess = null; + + if (isShuttingDown || wasRestarting) { + return; + } + + const detail = signal ? `signal ${signal}` : `code ${code ?? 0}`; + log('electron', `exited with ${detail}`); + shutdown(code ?? 0); + }); +}; + +/** + * Stop the running Electron process, if any. + * @returns {Promise} + */ +const stopElectron = async () => { + if (!electronProcess) { + return; + } + + const processToStop = electronProcess; + electronProcess = null; + + await new Promise(resolve => { + const killTimer = setTimeout(() => { + if (processToStop.exitCode === null && processToStop.signalCode === null) { + processToStop.kill('SIGKILL'); + } + }, 5000); + + killTimer.unref(); + + processToStop.once('exit', () => { + clearTimeout(killTimer); + resolve(); + }); + + processToStop.kill(); + }); +}; + +/** + * Start Electron after the first successful main + preload builds. + */ +const maybeStartElectron = () => { + if (!rendererReady || electronProcess || isShuttingDown) { + return; + } + + if (readyNodeTargets.size !== nodeTargets.length) { + return; + } + + startElectron('launching Electron'); +}; + +/** + * Debounce restarts so a main+preload change only restarts Electron once. + * @param {NodeTarget} target - Target that triggered the restart. + */ +const scheduleElectronRestart = target => { + if (!rendererReady || isShuttingDown) { + return; + } + + if (restartTimer) { + clearTimeout(restartTimer); + } + + restartTimer = setTimeout(() => { + restartTimer = null; + restartElectron(`${target} changed; restarting Electron`); + }, 150); +}; + +/** + * Restart Electron after a successful node-side rebuild. + * @param {string} reason - Why Electron is being restarted. + * @returns {Promise} Resolves after the restart completes. + */ +const restartElectron = async reason => { + if (isShuttingDown) { + return; + } + + isRestartingElectron = true; + try { + await stopElectron(); + startElectron(reason); + } finally { + isRestartingElectron = false; + } +}; + +/** + * Watch one node-side webpack target and restart Electron after successful rebuilds. + * @param {NodeTarget} target - Node-side webpack target to watch. + */ +const watchNodeTarget = target => { + const compiler = webpack(getConfig(target)); + nodeCompilers.push(compiler); + + const watching = compiler.watch({}, (error, stats) => { + if (error) { + console.error(error); + log(target, 'build failed before stats were available'); + return; + } + + if (!stats) { + log(target, 'build finished without stats output'); + return; + } + + const succeeded = handleNodeBuildResult(target, stats); + if (!succeeded) { + return; + } + + const isFirstSuccessfulBuild = !readyNodeTargets.has(target); + readyNodeTargets.add(target); + + if (isFirstSuccessfulBuild) { + maybeStartElectron(); + return; + } + + scheduleElectronRestart(target); + }); + + nodeWatchers.push(watching); + log(target, 'watching for changes'); +}; + +/** + * Start the renderer dev server so BrowserWindow can use live reload. + * @returns {Promise} + */ +const startRendererServer = async () => { + const rendererConfig = getConfig('renderer'); + if (!rendererConfig.devServer) { + throw new Error('Renderer webpack config is missing devServer settings'); + } + + rendererCompiler = webpack(rendererConfig); + rendererCompiler.hooks.done.tap('clipcc-desktop-dev-runner-renderer', stats => { + const succeeded = handleRendererBuildResult(stats); + if (!succeeded) { + return; + } + + const isFirstSuccessfulBuild = !rendererReady; + rendererReady = true; + + if (isFirstSuccessfulBuild) { + maybeStartElectron(); + } + }); + + rendererServer = new WebpackDevServer( + /** @type {DevServerConfiguration} */ (rendererConfig.devServer), + rendererCompiler + ); + + await rendererServer.start(); +}; + +/** + * Close webpack's watch handle. + * @param {Watching} watching - Active webpack watch handle. + * @returns {Promise} Resolves once the watcher closes. + */ +const closeWatching = watching => new Promise((resolve, reject) => { + watching.close(error => { + if (error) { + reject(error); + return; + } + resolve(); + }); +}); + +/** + * Close a webpack compiler after its watcher is stopped. + * @param {Compiler} compiler - Compiler to dispose. + * @returns {Promise} Resolves once the compiler closes. + */ +const closeCompiler = compiler => new Promise((resolve, reject) => { + compiler.close(error => { + if (error) { + reject(error); + return; + } + resolve(); + }); +}); + +/** + * Shut the dev runner down in a controlled order. + * @param {number} exitCode - Process exit code to keep. + * @returns {Promise} Resolves after shutdown work finishes. + */ +const shutdown = async exitCode => { + if (isShuttingDown) { + process.exitCode = exitCode; + return; + } + + isShuttingDown = true; + process.exitCode = exitCode; + + if (restartTimer) { + clearTimeout(restartTimer); + restartTimer = null; + } + + await stopElectron(); + + const watcherResults = await Promise.allSettled(nodeWatchers.map(closeWatching)); + watcherResults.forEach(result => { + if (result.status === 'rejected') { + console.error(result.reason); + } + }); + + const compilerResults = await Promise.allSettled(nodeCompilers.map(closeCompiler)); + compilerResults.forEach(result => { + if (result.status === 'rejected') { + console.error(result.reason); + } + }); + + if (rendererServer) { + await rendererServer.stop(); + } + + if (rendererCompiler) { + await closeCompiler(rendererCompiler); + } +}; + +/** + * Surface fatal runner errors and stop everything. + * @param {unknown} error - Fatal error thrown by the dev runner. + */ +const handleFatalError = error => { + console.error(error); + shutdown(1); +}; + +process.once('SIGINT', () => { + shutdown(0); +}); + +process.once('SIGTERM', () => { + shutdown(0); +}); + +process.once('uncaughtException', handleFatalError); +process.once('unhandledRejection', handleFatalError); + +await startRendererServer(); +watchNodeTarget('main'); +watchNodeTarget('preload'); diff --git a/app/desktop/scripts/electron-builder-wrapper.mjs b/app/desktop/scripts/electron-builder-wrapper.mjs new file mode 100644 index 00000000..f45abe6a --- /dev/null +++ b/app/desktop/scripts/electron-builder-wrapper.mjs @@ -0,0 +1,173 @@ +// @ts-check + +import {spawnSync} from 'node:child_process'; +import path from 'node:path'; +import fs from 'node:fs'; +import {createRequire} from 'node:module'; + +const require = createRequire(import.meta.url); +const projectDir = path.resolve(import.meta.filename, '..'); +const configPath = path.resolve(projectDir, 'electron-builder.yaml'); + +/** + * @typedef {'dir' | 'dev' | 'dist'} BuildMode + */ + +/** + * @typedef ParsedArgs + * @property {BuildMode} mode Selected build mode for packaging. + * @property {string[]} passthroughArgs Forwarded electron-builder CLI arguments. + */ + +/** + * Parse wrapper arguments and extract mode. + * + * Supported forms: + * --mode=dir + * --mode dir + * + * Unknown args are forwarded to electron-builder. + * @param {string[]} argv Wrapper script command-line arguments. + * @returns {ParsedArgs} Parsed mode and forwarded argument list. + */ +const parseArgs = argv => { + /** @type {BuildMode} */ + let mode = 'dev'; + /** @type {string[]} */ + const passthroughArgs = []; + + for (let i = 0; i < argv.length; i++) { + const arg = argv[i]; + if (arg.startsWith('--mode=')) { + const value = arg.slice('--mode='.length); + if (value === 'dir' || value === 'dev' || value === 'dist') { + mode = value; + continue; + } + throw new Error(`Invalid --mode value: ${value}`); + } + + if (arg === '--mode') { + const value = argv[i + 1]; + if (value === 'dir' || value === 'dev' || value === 'dist') { + mode = value; + i++; + continue; + } + throw new Error(`Invalid --mode value: ${String(value)}`); + } + + passthroughArgs.push(arg); + } + + return {mode, passthroughArgs}; +}; + +/** + * Resolve platform selector for electron-builder CLI. + * @returns {'--win' | '--mac' | '--linux'} Platform flag matching current OS. + */ +const getCurrentPlatformFlag = () => { + switch (process.platform) { + case 'win32': + return '--win'; + case 'darwin': + return '--mac'; + case 'linux': + return '--linux'; + default: + throw new Error(`Unsupported platform: ${process.platform}`); + } +}; + +/** + * Check if rpmbuild is available in PATH. + * @returns {boolean} True when rpm toolchain is available or platform is non-Linux. + */ +const hasRpmBuild = () => { + if (process.platform !== 'linux') return true; + const check = spawnSync('rpmbuild', ['--version'], { + stdio: 'ignore' + }); + return check.status === 0; +}; + +/** + * Build argument list for electron-builder. + * @param {BuildMode} mode Requested build mode. + * @param {string[]} passthroughArgs Additional CLI arguments to pass through. + * @returns {string[]} Fully expanded electron-builder arguments. + */ +const createBuilderArgs = (mode, passthroughArgs) => { + /** @type {string[]} */ + const args = [ + 'build', + '--config', + configPath, + '--projectDir', + projectDir, + getCurrentPlatformFlag() + ]; + + if (mode === 'dir') { + args.push('--dir', '--config.compression=store'); + } + + if (mode === 'dist') { + // Distribution artifacts should fail if signing is expected but missing. + args.push('--config.forceCodeSigning=true'); + } else { + // Keep local and CI dev/dir builds unsigned by default. + args.push('--config.forceCodeSigning=false'); + + if (process.platform === 'darwin') { + // Explicitly disable mac signing when producing unsigned artifacts. + args.push('--config.mac.identity=null'); + } + } + + if (process.platform === 'linux' && !hasRpmBuild()) { + // rpm target requires rpmbuild/fpm toolchain. + args.push('--linux', 'AppImage', 'deb'); + console.warn('[electron-builder-wrapper] rpmbuild not found; skipping rpm target.'); + } + + return args.concat(passthroughArgs); +}; + +/** + * Run electron-builder CLI with the given arguments. + * @param {string[]} args Final argument list for electron-builder. + */ +const runElectronBuilder = args => { + const cliPath = require.resolve('electron-builder/out/cli/cli.js'); + console.log(`[electron-builder-wrapper] mode args: ${args.join(' ')}`); + + const result = spawnSync(process.execPath, [cliPath, ...args], { + cwd: projectDir, + stdio: 'inherit', + env: process.env + }); + + if (result.error) { + throw result.error; + } + if (result.signal) { + throw new Error(`electron-builder terminated by signal: ${result.signal}`); + } + if (typeof result.status === 'number' && result.status !== 0) { + throw new Error(`electron-builder exited with code ${result.status}`); + } +}; + +const main = () => { + if (!fs.existsSync(configPath)) { + throw new Error(`Missing config: ${configPath}`); + } + + const {mode, passthroughArgs} = parseArgs(process.argv.slice(2)); + const args = createBuilderArgs(mode, passthroughArgs); + runElectronBuilder(args); +}; + +main(); diff --git a/app/desktop/scripts/fetchMediaLibraryAssets.js b/app/desktop/scripts/fetchMediaLibraryAssets.js new file mode 100644 index 00000000..89ef7fb1 --- /dev/null +++ b/app/desktop/scripts/fetchMediaLibraryAssets.js @@ -0,0 +1,106 @@ +const fs = require('fs'); +const https = require('https'); +const path = require('path'); +const util = require('util'); + +const async = require('async'); + +const libraries = require('./lib/libraries'); + +const ASSET_HOST = 'cdn.assets.scratch.mit.edu'; +const NUM_SIMULTANEOUS_DOWNLOADS = 5; +const OUT_PATH = path.resolve('static', 'assets'); + +const describe = function (object) { + return util.inspect(object, false, Infinity, true); +}; + +const collectSimple = function (library, dest, debugLabel = 'Item') { + library.forEach(item => { + let md5Count = 0; + if (item.md5) { + ++md5Count; + dest.add(item.md5); + } + if (item.baseLayerMD5) { // 2.0 library syntax for costumes + ++md5Count; + dest.add(item.baseLayerMD5); + } + if (item.md5ext) { // 3.0 library syntax for costumes + ++md5Count; + dest.add(item.md5ext); + } + if (md5Count < 1) { + console.warn(`${debugLabel} has no MD5 property:\n${describe(item)}`); + } else if (md5Count > 1) { + // is this actually bad? + console.warn(`${debugLabel} has multiple MD5 properties:\n${describe(item)}`); + } + }); + return dest; +}; + +const collectAssets = function (dest) { + collectSimple(libraries.backdrops, dest, 'Backdrop'); + collectSimple(libraries.costumes, dest, 'Costume'); + collectSimple(libraries.sounds, dest, 'Sound'); + libraries.sprites.forEach(sprite => { + if (sprite.costumes) { + collectSimple(sprite.costumes, dest, `Costume for sprite ${sprite.name}`); + } + if (sprite.sounds) { + collectSimple(sprite.sounds, dest, `Sound for sprite ${sprite.name}`); + } + }); + return dest; +}; + +const connectionPool = []; + +const fetchAsset = function (md5, callback) { + const myAgent = connectionPool.pop() || new https.Agent({keepAlive: true}); + const getOptions = { + host: ASSET_HOST, + path: `/internalapi/asset/${md5}/get/`, + agent: myAgent + }; + const urlHuman = `//${getOptions.host}${getOptions.path}`; + https.get(getOptions, response => { + if (response.statusCode !== 200) { + callback(new Error(`Request failed: status code ${response.statusCode} for ${urlHuman}`)); + return; + } + + const stream = fs.createWriteStream(path.resolve(OUT_PATH, md5), {encoding: 'binary'}); + stream.on('error', callback); + response.on('data', chunk => { + stream.write(chunk); + }); + response.on('end', () => { + connectionPool.push(myAgent); + stream.end(); + console.log(`Fetched ${urlHuman}`); + callback(); + }); + }); +}; + +const fetchAllAssets = function () { + const allAssets = collectAssets(new Set()); + console.log(`Total library assets: ${allAssets.size}`); + + async.forEachLimit(allAssets, NUM_SIMULTANEOUS_DOWNLOADS, fetchAsset, err => { + if (err) { + console.error(`Fetch failed:\n${describe(err)}`); + } else { + console.log('Fetch succeeded.'); + } + + console.log(`Shutting down ${connectionPool.length} agents.`); + while (connectionPool.length > 0) { + connectionPool.pop().destroy(); + } + }); +}; + +fetchAllAssets(); diff --git a/app/desktop/scripts/generate-build-resources.mjs b/app/desktop/scripts/generate-build-resources.mjs new file mode 100644 index 00000000..c1253651 --- /dev/null +++ b/app/desktop/scripts/generate-build-resources.mjs @@ -0,0 +1,95 @@ +import {mkdir, writeFile} from 'node:fs/promises'; +import path from 'node:path'; + +import png2icons from 'png2icons'; +import sharp from 'sharp'; + +const desktopRoot = path.resolve(import.meta.dirname, '..'); +const sourceIconDir = path.resolve(desktopRoot, 'src/common/icon'); +const buildResourcesDir = path.resolve(desktopRoot, 'buildResources'); + +const appSourceSvg = path.resolve(sourceIconDir, 'app.svg'); +const cc3SourceSvg = path.resolve(sourceIconDir, 'cc3.svg'); +const ccxSourceSvg = path.resolve(sourceIconDir, 'ccx.svg'); + +const appIcoPath = path.resolve(buildResourcesDir, 'app.ico'); +const appIcnsPath = path.resolve(buildResourcesDir, 'app.icns'); +const cc3IcoPath = path.resolve(buildResourcesDir, 'icon/cc3.ico'); +const ccxIcoPath = path.resolve(buildResourcesDir, 'icon/ccx.ico'); + +const appxLogoSizes = [ + {name: 'Square44x44Logo.png', width: 44, height: 44}, + {name: 'StoreLogo.png', width: 50, height: 50}, + {name: 'Square150x150Logo.png', width: 150, height: 150}, + {name: 'Wide310x150Logo.png', width: 310, height: 150} +]; + +/** + * Render an SVG source to PNG. + * @param {string} sourcePath Source SVG path. + * @param {number} width Target width. + * @param {number} height Target height. + * @returns {Promise} PNG bytes. + */ +const renderPng = (sourcePath, width, height) => sharp(sourcePath) + .resize(width, height, { + fit: 'contain', + background: {r: 0, g: 0, b: 0, alpha: 0} + }) + .png() + .toBuffer(); + +/** + * Assert non-empty icon data from png2icons. + * @param {Uint8Array | Buffer | false} iconBuffer Output buffer from png2icons. + * @param {string} label Icon label for error text. + * @returns {Buffer} Normalized Node buffer. + */ +const requireIconBuffer = (iconBuffer, label) => { + if (!iconBuffer || iconBuffer.length === 0) { + throw new Error(`Failed to generate ${label}`); + } + return Buffer.from(iconBuffer); +}; + +const generate = async () => { + await mkdir(path.resolve(buildResourcesDir, 'appx'), {recursive: true}); + await mkdir(path.resolve(buildResourcesDir, 'icon'), {recursive: true}); + + const appMasterPng = await renderPng(appSourceSvg, 1024, 1024); + const cc3MasterPng = await renderPng(cc3SourceSvg, 1024, 1024); + const ccxMasterPng = await renderPng(ccxSourceSvg, 1024, 1024); + + const appIcoData = requireIconBuffer( + png2icons.createICO(appMasterPng, png2icons.BILINEAR, 0, true), + 'app.ico' + ); + const appIcnsData = requireIconBuffer( + png2icons.createICNS(appMasterPng, png2icons.BILINEAR, 0), + 'app.icns' + ); + const cc3IcoData = requireIconBuffer( + png2icons.createICO(cc3MasterPng, png2icons.BILINEAR, 0, true), + 'icon/cc3.ico' + ); + + const ccxIcoData = requireIconBuffer( + png2icons.createICO(ccxMasterPng, png2icons.BILINEAR, 0, true), + 'icon/ccx.ico' + ); + + await Promise.all([ + writeFile(appIcoPath, appIcoData), + writeFile(appIcnsPath, appIcnsData), + writeFile(cc3IcoPath, cc3IcoData), + writeFile(ccxIcoPath, ccxIcoData) + ]); + + await Promise.all(appxLogoSizes.map(async logo => { + const outputPath = path.resolve(buildResourcesDir, 'appx', logo.name); + const png = await renderPng(appSourceSvg, logo.width, logo.height); + await writeFile(outputPath, png); + })); +}; + +generate(); diff --git a/app/desktop/scripts/lib/libraries.js b/app/desktop/scripts/lib/libraries.js new file mode 100644 index 00000000..10313559 --- /dev/null +++ b/app/desktop/scripts/lib/libraries.js @@ -0,0 +1,13 @@ +const backdrops = require('clipcc-gui/libraries/backdrops.json'); +const costumes = require('clipcc-gui/libraries/costumes.json'); +const sounds = require('clipcc-gui/libraries/sounds.json'); +const sprites = require('clipcc-gui/libraries/sprites.json'); + +const libraries = { + backdrops, + costumes, + sounds, + sprites +}; + +module.exports = libraries; diff --git a/app/desktop/src/common/icon/app.svg b/app/desktop/src/common/icon/app.svg new file mode 100644 index 00000000..5e6b4b52 --- /dev/null +++ b/app/desktop/src/common/icon/app.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/desktop/src/common/icon/cc3.svg b/app/desktop/src/common/icon/cc3.svg new file mode 100644 index 00000000..cfb7a99a --- /dev/null +++ b/app/desktop/src/common/icon/cc3.svg @@ -0,0 +1 @@ +clipcc file soil \ No newline at end of file diff --git a/app/desktop/src/common/icon/ccx.svg b/app/desktop/src/common/icon/ccx.svg new file mode 100644 index 00000000..c54b10cc --- /dev/null +++ b/app/desktop/src/common/icon/ccx.svg @@ -0,0 +1 @@ +clipcc extension soil \ No newline at end of file diff --git a/app/desktop/src/main/index.ts b/app/desktop/src/main/index.ts new file mode 100644 index 00000000..025aac11 --- /dev/null +++ b/app/desktop/src/main/index.ts @@ -0,0 +1,35 @@ +import {app, Menu, session} from 'electron'; + +import {registerIpcListeners} from './ipc'; +import MacOSMenu from './macos-menu'; +import {initializeWindows} from './window-manager'; + +app.commandLine.appendSwitch('enable-features', 'FluentScrollbar,OverlayScrollbar'); +app.whenReady().then(() => { + session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => { + const existingHeader = details.requestHeaders['User-Agent']; + const baseUserAgent = (typeof existingHeader === 'string' && existingHeader.trim()) ? + existingHeader : + app.userAgentFallback; + + details.requestHeaders['User-Agent'] = `${baseUserAgent} ClipCCDesktop/${app.getVersion()}`; + callback({requestHeaders: details.requestHeaders}); + }); + + initializeWindows(); + registerIpcListeners(); +}); + +if (process.platform === 'darwin') { + const osxMenu = Menu.buildFromTemplate(MacOSMenu(app)); + Menu.setApplicationMenu(osxMenu); +} else { + // disable menu for other platforms + Menu.setApplicationMenu(null); +} + +app.on('window-all-closed', () => { + if (process.platform !== 'darwin') { + app.quit(); + } +}); diff --git a/app/desktop/src/main/ipc.ts b/app/desktop/src/main/ipc.ts new file mode 100644 index 00000000..bd1b345e --- /dev/null +++ b/app/desktop/src/main/ipc.ts @@ -0,0 +1,7 @@ +import {ipcMain} from 'electron'; + +import {openAboutWindow} from './window-manager'; + +export const registerIpcListeners = () => { + ipcMain.on('open-about-window', openAboutWindow); +}; diff --git a/app/desktop/src/main/macos-menu.ts b/app/desktop/src/main/macos-menu.ts new file mode 100644 index 00000000..0b270600 --- /dev/null +++ b/app/desktop/src/main/macos-menu.ts @@ -0,0 +1,52 @@ +import type {App, MenuItemConstructorOptions} from 'electron'; + +// Include the standard keyboard shortcuts in the edit menu +// so they can be used within the app. Only needed on Mac. +export default (app: App): MenuItemConstructorOptions[] => ([ + { + label: 'App', // Always overridden by app name + submenu: [{ + label: 'Quit', + accelerator: 'CmdOrCtrl+Q', + click: () => app.quit() + }] + }, + { + label: 'Edit', + submenu: [ + { + label: 'Undo', + accelerator: 'CmdOrCtrl+Z', + role: 'undo' + }, + { + label: 'Redo', + accelerator: 'Shift+CmdOrCtrl+Z', + role: 'redo' + }, + { + type: 'separator' + }, + { + label: 'Cut', + accelerator: 'CmdOrCtrl+X', + role: 'cut' + }, + { + label: 'Copy', + accelerator: 'CmdOrCtrl+C', + role: 'copy' + }, + { + label: 'Paste', + accelerator: 'CmdOrCtrl+V', + role: 'paste' + }, + { + label: 'Select All', + accelerator: 'CmdOrCtrl+A', + role: 'selectAll' + } + ] + } +]); diff --git a/app/desktop/src/main/window-manager.ts b/app/desktop/src/main/window-manager.ts new file mode 100644 index 00000000..206b1c17 --- /dev/null +++ b/app/desktop/src/main/window-manager.ts @@ -0,0 +1,330 @@ +import { + BrowserWindow, + type BrowserWindowConstructorOptions, + dialog, + shell, + systemPreferences +} from 'electron'; +import path from 'path'; +import {pathToFileURL} from 'url'; + +type WindowName = 'main' | 'about' | 'loading'; + +const windows: Partial> = {}; + +const defaultWebPreferences: BrowserWindowConstructorOptions['webPreferences'] = { + preload: path.resolve(__dirname, 'preload.js'), + contextIsolation: true, + nodeIntegration: false, + sandbox: false +}; + +const devToolKey = ((process.platform === 'darwin') ? + { // macOS: command+option+i + alt: true, // option + control: false, + meta: true, // command + shift: false, + code: 'KeyI' + } : { // Windows: control+shift+i + alt: false, + control: true, + meta: false, // Windows key + shift: true, + code: 'KeyI' + } +); + +const displayPermissionDeniedWarning = (window: BrowserWindow, permissionType: 'camera' | 'microphone') => { + let title = 'Permission Denied'; + let message = 'A permission has been denied.'; + + if (permissionType === 'camera') { + title = 'Camera Permission Denied'; + message = 'Permission to use the camera has been denied. ClipCC will not be able to use video sensing.'; + } else if (permissionType === 'microphone') { + title = 'Microphone Permission Denied'; + message = ( + 'Permission to use the microphone has been denied. ClipCC will not be able to record sounds ' + + 'or detect loudness.' + ); + } + + const instructions = (process.platform === 'darwin') ? + 'To change ClipCC permissions, please check "Privacy & Security" in System Settings.' : + 'To change ClipCC permissions, please check your system settings and restart ClipCC.'; + + void dialog.showMessageBox(window, { + type: 'warning', + title, + message: `${message}\n\n${instructions}` + }); +}; + +const askForMediaAccess = (mediaType: 'microphone' | 'camera') => { + if (systemPreferences.askForMediaAccess) { + return systemPreferences.askForMediaAccess(mediaType); + } + return true; +}; + +const getAllowedRequestingUrlBase = () => { + if (process.env.ELECTRON_WEBPACK_WDS_PORT) { + return `http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}/`; + } + + const rendererDirPath = `${path.resolve(__dirname, '..', 'renderer')}${path.sep}`; + return pathToFileURL(rendererDirPath).toString(); +}; + +const handlePermissionRequest = async ( + webContents: Electron.WebContents, + permission: string, + callback: (isAllowed: boolean) => void, + details: Electron.PermissionRequest +) => { + if (webContents !== windows.main?.webContents) { + callback(false); + return; + } + + if (!details.isMainFrame) { + callback(false); + return; + } + + if (permission !== 'media') { + callback(false); + return; + } + + const requiredBase = getAllowedRequestingUrlBase(); + if (!details.requestingUrl.startsWith(requiredBase)) { + callback(false); + return; + } + + let askForMicrophone = false; + let askForCamera = false; + const mediaTypes = (details as Electron.PermissionRequest & {mediaTypes?: string[]}).mediaTypes ?? []; + + for (const mediaType of mediaTypes) { + if (mediaType === 'audio') { + askForMicrophone = true; + continue; + } + if (mediaType === 'video') { + askForCamera = true; + continue; + } + + callback(false); + return; + } + + const parentWindow = windows.main; + + if (askForMicrophone) { + const microphoneResult = await askForMediaAccess('microphone'); + if (!microphoneResult) { + if (parentWindow) { + displayPermissionDeniedWarning(parentWindow, 'microphone'); + } + callback(false); + return; + } + } + + if (askForCamera) { + const cameraResult = await askForMediaAccess('camera'); + if (!cameraResult) { + if (parentWindow) { + displayPermissionDeniedWarning(parentWindow, 'camera'); + } + callback(false); + return; + } + } + + callback(true); +}; + +export const createWindow = ({ + webPreferences, + ...options +}: BrowserWindowConstructorOptions) => { + const window = new BrowserWindow({ + autoHideMenuBar: true, + ...options, + webPreferences: { + ...defaultWebPreferences, + ...webPreferences + } + }); + + window.webContents.setWindowOpenHandler(({url}) => { + shell.openExternal(url); + return {action: 'deny'}; + }); + + window.webContents.session.setPermissionRequestHandler(handlePermissionRequest); + + window.webContents.on('before-input-event', (event, input) => { + if (input.code === devToolKey.code && + input.alt === devToolKey.alt && + input.control === devToolKey.control && + input.meta === devToolKey.meta && + input.shift === devToolKey.shift && + input.type === 'keyDown' && + !input.isAutoRepeat && + !input.isComposing) { + event.preventDefault(); + window.webContents.openDevTools({mode: 'detach', activate: true}); + } + }); + + window.once('ready-to-show', () => { + window.webContents.send('ready-to-show'); + }); + + return window; +}; + +const loadRendererRoute = (window: BrowserWindow, route = 'app') => { + if (!process.env.ELECTRON_WEBPACK_WDS_PORT) { + return window.loadFile(path.resolve(__dirname, '..', 'renderer', 'index.html'), { + query: { + route + } + }); + } + const devServerUrl = `http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}/`; + + const rendererUrl = new URL(devServerUrl); + rendererUrl.searchParams.set('route', route); + + return window.loadURL(rendererUrl.toString()); +}; + +const createMainWindow = () => { + const window = createWindow({ + title: 'ClipCC', + width: 1280, + height: 820, + minWidth: 960, + minHeight: 600, + show: false + }); + + loadRendererRoute(window, 'app'); + + window.once('ready-to-show', () => { + windows.loading?.show(); + }); + + window.webContents.once('did-finish-load', () => { + windows.loading?.close(); + window.show(); + }); + + window.webContents.on('will-prevent-unload', ev => { + const choice = dialog.showMessageBoxSync(window, { + type: 'question', + message: 'Leave ClipCC?', + detail: 'Any unsaved changes will be lost.', + buttons: ['Stay', 'Leave'], + cancelId: 0, // closing the dialog means "stay" + defaultId: 0 // pressing enter or space without explicitly selecting something means "stay" + }); + const shouldQuit = (choice === 1); + if (shouldQuit) { + ev.preventDefault(); + } + }); + + window.on('closed', () => { + if (windows.main === window) { + delete windows.main; + } + + windows.about?.close(); + windows.loading?.close(); + }); + + return window; +}; + +const createAboutWindow = () => { + const window = createWindow({ + title: 'About ClipCC', + width: 400, + height: 400, + parent: windows.main, + show: false, + useContentSize: true + }); + + loadRendererRoute(window, 'about'); + + window.on('closed', () => { + if (windows.about === window) { + delete windows.about; + } + }); + + return window; +}; + +const createLoadingWindow = () => { + const window = createWindow({ + width: 300, + height: 300, + frame: false, + resizable: false, + show: false, + titleBarStyle: 'hiddenInset' + }); + + if (process.env.ELECTRON_WEBPACK_WDS_PORT) { + const loadingUrl = new URL(`http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}/loading.html`); + window.loadURL(loadingUrl.toString()); + } else { + const loadingFilePath = path.resolve(__dirname, '..', 'renderer', 'loading.html'); + window.loadFile(loadingFilePath); + } + + window.on('closed', () => { + if (windows.loading === window) { + delete windows.loading; + } + }); + + return window; +}; + +const ensureWindow = (name: WindowName) => { + if (!windows[name]) { + switch (name) { + case 'main': + windows.main = createMainWindow(); + break; + case 'about': + windows.about = createAboutWindow(); + break; + case 'loading': + windows.loading = createLoadingWindow(); + break; + } + } + + return windows[name]!; +}; + +export const initializeWindows = () => { + ensureWindow('loading'); + ensureWindow('main'); +}; + +export const openAboutWindow = () => { + ensureWindow('about').show(); +}; diff --git a/app/desktop/src/preload/index.ts b/app/desktop/src/preload/index.ts new file mode 100644 index 00000000..8bdde3f8 --- /dev/null +++ b/app/desktop/src/preload/index.ts @@ -0,0 +1,21 @@ +import {contextBridge, ipcRenderer} from 'electron'; + +const runtimeVersions = { + electron: process.versions.electron, + chrome: process.versions.chrome, + node: process.versions.node +}; + +const desktopApi = { + onReadyToShow (listener: () => void) { + ipcRenderer.once('ready-to-show', listener); + }, + openAboutWindow () { + ipcRenderer.send('open-about-window'); + }, + getRuntimeVersions () { + return runtimeVersions; + } +}; + +contextBridge.exposeInMainWorld('desktop', desktopApi); diff --git a/app/desktop/src/renderer/index.css b/app/desktop/src/renderer/index.css new file mode 100644 index 00000000..8424bb5c --- /dev/null +++ b/app/desktop/src/renderer/index.css @@ -0,0 +1,11 @@ +html, +body { + /* probably unecessary, transitional until layout is refactored */ + width: 100%; + height: 100%; + margin: 0; +} + +/* @todo: move globally? Safe / side FX, for blocks particularly? */ +* { box-sizing: border-box; } + diff --git a/app/desktop/src/renderer/index.html b/app/desktop/src/renderer/index.html new file mode 100644 index 00000000..4a8bf2cb --- /dev/null +++ b/app/desktop/src/renderer/index.html @@ -0,0 +1,11 @@ + + + + + + + +
+ + + diff --git a/app/desktop/src/renderer/index.ts b/app/desktop/src/renderer/index.ts new file mode 100644 index 00000000..22189222 --- /dev/null +++ b/app/desktop/src/renderer/index.ts @@ -0,0 +1,28 @@ +// This file does async imports of the heavy JSX, especially app.jsx, to avoid blocking the first render. +// The main index.html just contains a loading/splash screen which will display while this import loads. + +import ReactDOM from 'react-dom'; + +window.desktop?.onReadyToShow(() => { + // Start without any element in focus, otherwise the first link starts with focus and shows an orange box. + // We shouldn't disable that box or the focus behavior in case someone wants or needs to navigate that way. + // This seems like a hack... maybe there's some better way to do avoid any element starting with focus? + (document.activeElement as HTMLElement | null)?.blur(); +}); + +const route = new URLSearchParams(window.location.search).get('route') || 'app'; +let routeModulePromise; +switch (route) { +case 'app': + routeModulePromise = import('./routes/app/app'); + break; +case 'about': + routeModulePromise = import('./routes/about/about'); + break; +} + +routeModulePromise?.then(routeModule => { + const appTarget = document.getElementById('app'); + const routeElement = routeModule.default; + ReactDOM.render(routeElement, appTarget); +}); diff --git a/app/desktop/src/renderer/lib/ElectronStorageHelper.ts b/app/desktop/src/renderer/lib/ElectronStorageHelper.ts new file mode 100644 index 00000000..dd6e8504 --- /dev/null +++ b/app/desktop/src/renderer/lib/ElectronStorageHelper.ts @@ -0,0 +1,41 @@ +import type {Asset, DataFormat, IAssetType, ScratchStorage} from 'clipcc-storage'; + +const staticAssets = new URL('./static/assets/', window.location.href); + +const basename = (value: string): string => { + const normalized = value.replace(/\\/g, '/'); + return normalized.split('/').pop() || ''; +}; + +/** + * Allow the storage module to load files bundled in the Electron application. + */ +class ElectronStorageHelper { + constructor ( + public parent: ScratchStorage + ) {} + + /** + * Fetch an asset but don't process dependencies. + * @param assetType - The type of asset to fetch. + * @param assetId - The ID of the asset to fetch: a project ID, MD5, etc. + * @param dataFormat - The file format / file extension of the asset to fetch: PNG, JPG, etc. + * @returns A promise for the contents of the asset. + */ + load (assetType: IAssetType, assetId: string, dataFormat: DataFormat): Promise { + assetId = basename(assetId); + dataFormat = basename(dataFormat) as DataFormat; + + const assetUrl = new URL(`${assetId}.${dataFormat}`, staticAssets); + return fetch(assetUrl.toString()) + .then(response => { + if (!response.ok) { + throw new Error(`Failed to load asset ${assetId}.${dataFormat}: ${response.status}`); + } + return response.arrayBuffer(); + }) + .then(data => new this.parent.Asset(assetType, assetId, dataFormat, new Uint8Array(data))); + } +} + +export default ElectronStorageHelper; diff --git a/app/desktop/src/renderer/loading.html b/app/desktop/src/renderer/loading.html new file mode 100644 index 00000000..b4dea393 --- /dev/null +++ b/app/desktop/src/renderer/loading.html @@ -0,0 +1,275 @@ + + + + + + + + + + +
+ + + +
+ + + +
+
+ + + + + diff --git a/app/desktop/src/renderer/routes/about/about.css b/app/desktop/src/renderer/routes/about/about.css new file mode 100644 index 00000000..43f9ce7b --- /dev/null +++ b/app/desktop/src/renderer/routes/about/about.css @@ -0,0 +1,39 @@ +html, body { + background-color: #4D97FF; + color: white; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: bolder; +} + +a:active, a:hover, a:link, a:visited { + color: currentColor; +} + +a:active, a:hover { + filter: brightness(0.9); +} + +.aboutBox { + margin: 0; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.aboutLogo { + max-width: 10rem; + max-height: 10rem; +} + +.aboutText { + margin: 1.5rem; +} + +.aboutDetails { + font-size: x-small; +} + +.aboutFooter { + font-size: small; +} diff --git a/app/desktop/src/renderer/routes/about/about.tsx b/app/desktop/src/renderer/routes/about/about.tsx new file mode 100644 index 00000000..823dff75 --- /dev/null +++ b/app/desktop/src/renderer/routes/about/about.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import packageJSON from '../../../../package.json'; + +import logo from '../../../common/icon/app.svg'; +import styles from './about.css'; + +const runtimeVersions = window.desktop?.getRuntimeVersions() ?? {}; + +const AboutElement = () => ( +
+
{`${packageJSON.productName}
+
+

{packageJSON.productName}

+ Version {packageJSON.version} + + { + ['Electron', 'Chrome', 'Node'].map(component => { + const versionKey = component.toLowerCase() as keyof typeof runtimeVersions; + const componentVersion = runtimeVersions[versionKey] ?? 'Unknown'; + return ; + }) + } +
{component}{componentVersion}
+
+
+); + +export default ; diff --git a/app/desktop/src/renderer/routes/app/DesktopAppStateHOC.tsx b/app/desktop/src/renderer/routes/app/DesktopAppStateHOC.tsx new file mode 100644 index 00000000..406ecf73 --- /dev/null +++ b/app/desktop/src/renderer/routes/app/DesktopAppStateHOC.tsx @@ -0,0 +1,51 @@ +import bindAll from 'lodash.bindall'; +import React from 'react'; +import type {AppStateHOC} from 'clipcc-gui'; + +type PropsOf = C extends React.ComponentType ? P : never; + +/** + * Higher-order component to add desktop logic to AppStateHOC. + * @param WrappedComponent an AppStateHOC-like component to wrap. + * @returns a component similar to AppStateHOC with desktop-specific logic added. + */ +const ScratchDesktopAppStateHOC = function

> ( + WrappedComponent: React.ComponentType

+) { + class ScratchDesktopAppStateComponent extends React.Component { + constructor (props: P) { + super(props); + bindAll(this, [ + 'handleTelemetryModalOptIn', + 'handleTelemetryModalOptOut' + ]); + this.state = { + // use `sendSync` because this should be set before first render + telemetryDidOptIn: false + }; + } + handleTelemetryModalOptIn () { + } + handleTelemetryModalOptOut () { + } + render () { + const shouldShowTelemetryModal = false; + + return ( + + ); + } + } + + return ScratchDesktopAppStateComponent; +}; + +export default ScratchDesktopAppStateHOC; diff --git a/app/desktop/src/renderer/routes/app/DesktopGUIHOC.tsx b/app/desktop/src/renderer/routes/app/DesktopGUIHOC.tsx new file mode 100644 index 00000000..c500d81b --- /dev/null +++ b/app/desktop/src/renderer/routes/app/DesktopGUIHOC.tsx @@ -0,0 +1,219 @@ +import {connect} from 'react-redux'; +import type {AnyAction, Dispatch} from 'redux'; +import ElectronStorageHelper from '../../lib/ElectronStorageHelper'; +import React from 'react'; +import type VM from 'clipcc-vm'; +import type {ScratchStorage} from 'clipcc-storage'; + +import { + type AppStateHOC, + type LoadingState, + closeLoadingProject, + defaultProjectId, + openLoadingProject, + openTelemetryModal, + onLoadedProject, + requestNewProject, + requestProjectUpload, + setProjectId +} from 'clipcc-gui'; + +type PropsOf = C extends React.ComponentType ? P : never; +type LoadingStateValue = typeof LoadingState[keyof typeof LoadingState]; +type RootState = { + scratchGui: { + projectState: { + loadingState: LoadingStateValue; + }; + vm: VM; + }; +}; + +type InitialProjectData = Parameters[0]; + +const getInitialProjectData = (): Promise => Promise.resolve(null); + +const hasInitialProjectData = (projectData: InitialProjectData | null): projectData is InitialProjectData => { + if (projectData === null) { + return false; + } + if (typeof projectData === 'string') { + return projectData.length > 0; + } + if (ArrayBuffer.isView(projectData)) { + return projectData.byteLength > 0; + } + if (projectData instanceof ArrayBuffer) { + return projectData.byteLength > 0; + } + return true; +}; + +const getErrorMessage = (error: Error | string): string => (error instanceof Error ? error.message : error); + +const mapStateToProps = (state: RootState) => { + const loadingState = state.scratchGui.projectState.loadingState; + return { + loadingState, + vm: state.scratchGui.vm + }; +}; + +const mapDispatchToProps = (dispatch: Dispatch) => ({ + onLoadingStarted: () => { + dispatch(openLoadingProject()); + }, + onLoadingCompleted: () => { + dispatch(closeLoadingProject()); + }, + onHasInitialProject: (hasInitialProject: boolean, loadingState: LoadingStateValue) => { + if (hasInitialProject) { + // emulate sb-file-uploader + const action = requestProjectUpload(loadingState); + if (action) { + dispatch(action); + } + return; + } + + // `createProject()` might seem more appropriate but it's not a valid state transition here + // setting the default project ID is a valid transition from NOT_LOADED and acts like "create new" + dispatch(setProjectId(defaultProjectId)); + }, + onLoadedProject: (loadingState: LoadingStateValue, loadSuccess: boolean) => { + const canSaveToServer = false; + const action = onLoadedProject(loadingState, canSaveToServer, loadSuccess); + if (action) { + dispatch(action); + } + }, + onRequestNewProject: () => { + dispatch(requestNewProject(false)); + }, + onTelemetrySettingsClicked: () => { + dispatch(openTelemetryModal()); + } +}); + +type StatedGUILikeProps = PropsOf>; +type StateProps = ReturnType; +type DispatchProps = ReturnType; +type DesktopGUIComponentProps = StatedGUILikeProps & StateProps & DispatchProps; +type WrappedComponentProps = Omit; + +/** + * Higher-order component to add desktop logic to the GUI. + * @param WrappedComponent - a GUI-like component to wrap. + * @returns A component similar to GUI with desktop-specific logic added. + */ +const ScratchDesktopGUIHOC = function ( + WrappedComponent: React.ComponentType +): React.ComponentType { + interface State { + projectTitle: string; + }; + + class ScratchDesktopGUIComponent extends React.Component { + state = { + projectTitle: '' + }; + + override componentDidMount () { + this.props.onLoadingStarted(); + getInitialProjectData().then(initialProjectData => { + const hasInitialProject = hasInitialProjectData(initialProjectData); + this.props.onHasInitialProject(hasInitialProject, this.props.loadingState); + if (!hasInitialProject) { + this.props.onLoadingCompleted(); + return; + } + this.props.vm.loadProject(initialProjectData).then( + () => { + this.props.onLoadingCompleted(); + this.props.onLoadedProject(this.props.loadingState, true); + }, + (e: Error | string) => { + this.props.onLoadingCompleted(); + this.props.onLoadedProject(this.props.loadingState, false); + console.error( + `Failed to load project: Invalid or corrupt project file. ${getErrorMessage(e)}`, + e + ); + + // this effectively sets the default project ID + // TODO: maybe setting the default project ID should be implicit in `requestNewProject` + this.props.onHasInitialProject(false, this.props.loadingState); + + // restart as if we didn't have an initial project to load + this.props.onRequestNewProject(); + } + ); + }); + } + + handleClickAbout = () => { + window.desktop?.openAboutWindow(); + }; + + handleProjectTelemetryEvent = () => { + // ipcRenderer.send(event, metadata); + }; + + handleStorageInit = (storageInstance: ScratchStorage) => { + storageInstance.addHelper(new ElectronStorageHelper(storageInstance), 50); + }; + + handleUpdateProjectTitle = (newTitle: string) => { + this.setState({projectTitle: newTitle}); + }; + + override render () { + const { + /* eslint-disable @typescript-eslint/no-unused-vars */ + loadingState: _loadingState, + vm: _vm, + onLoadingStarted: _onLoadingStarted, + onLoadingCompleted: _onLoadingCompleted, + onHasInitialProject: _onHasInitialProject, + onLoadedProject: _onLoadedProject, + onRequestNewProject: _onRequestNewProject, + onTelemetrySettingsClicked: _onTelemetrySettingsClicked, + /* eslint-enable @typescript-eslint/no-unused-vars */ + ...componentProps + } = this.props; + + const desktopProps = { + canEditTitle: true, + canModifyCloudData: false, + canSave: false, + isScratchDesktop: true, + onClickAbout: [ + { + title: 'About', + onClick: () => this.handleClickAbout() + }, + { + title: 'Data Settings', + onClick: () => this.props.onTelemetrySettingsClicked() + } + ], + onProjectTelemetryEvent: this.handleProjectTelemetryEvent, + onStorageInit: this.handleStorageInit, + onUpdateProjectTitle: this.handleUpdateProjectTitle + }; + + const wrappedComponentProps = { + ...componentProps, + ...desktopProps + }; + + return (); + } + } + + return connect(mapStateToProps, mapDispatchToProps)(ScratchDesktopGUIComponent); +}; + +export default ScratchDesktopGUIHOC; diff --git a/app/desktop/src/renderer/routes/app/app.css b/app/desktop/src/renderer/routes/app/app.css new file mode 100644 index 00000000..d551673e --- /dev/null +++ b/app/desktop/src/renderer/routes/app/app.css @@ -0,0 +1,17 @@ +.app { + /* probably unecessary, transitional until layout is refactored */ + width: 100%; + height: 100%; + margin: 0; +} + +html, +body { + /* Setting min height/width makes the UI scroll below those sizes */ + min-width: 1024px; + min-height: 640px; /* Min height to fit sprite/backdrop button */ +} + +[theme='dark'] body { + background-color: var(--clipcc-ui-white); +} diff --git a/app/desktop/src/renderer/routes/app/app.tsx b/app/desktop/src/renderer/routes/app/app.tsx new file mode 100644 index 00000000..2ad11b9a --- /dev/null +++ b/app/desktop/src/renderer/routes/app/app.tsx @@ -0,0 +1,24 @@ +import {compose} from 'redux'; + +import GUI, {AppStateHOC, setAppElement} from 'clipcc-gui'; + +import ScratchDesktopAppStateHOC from './DesktopAppStateHOC'; +import ScratchDesktopGUIHOC from './DesktopGUIHOC'; +import React from 'react'; +import styles from './app.css'; + +const appTarget = document.getElementById('app')!; +appTarget.classList.add(styles.app); + +setAppElement(appTarget); + +// note that redux's 'compose' function is just being used as a general utility to make +// the hierarchy of HOC constructor calls clearer here; it has nothing to do with redux's +// ability to compose reducers. +const WrappedGui = compose( + ScratchDesktopAppStateHOC, + AppStateHOC, + ScratchDesktopGUIHOC +)(GUI); + +export default ; diff --git a/app/desktop/src/types.d.ts b/app/desktop/src/types.d.ts new file mode 100644 index 00000000..656902d9 --- /dev/null +++ b/app/desktop/src/types.d.ts @@ -0,0 +1,56 @@ +declare module '*.svg' { + declare const value: string; + export default value; +} + +declare module '*.css' { + declare const value: { [className: string]: string }; + export default value; +} + +declare module 'react-intl' { + import type React from 'react'; + + interface InjectIntlOptions { + intlPropName?: string; + withRef?: boolean; + } + + export interface MessageDescriptor { + id: string; + defaultMessage?: string; + description?: string; + } + + export interface IntlShape { + formatMessage( + descriptor: MessageDescriptor, + values?: Record + ): string; + } + + export function addLocaleData(localeData: unknown): void; + export function defineMessages>(messages: T): T; + export const FormattedMessage: React.ComponentType< + MessageDescriptor & { values?: Record } + >; + export const intlShape: { isRequired: unknown }; + export function injectIntl

( + component: React.ComponentType

, + options?: InjectIntlOptions + ): React.ComponentType>; +} + +interface ClipCCDesktopApi { + onReadyToShow(listener: () => void): void; + openAboutWindow(): void; + getRuntimeVersions(): { + electron?: string; + chrome?: string; + node?: string; + }; +} + +interface Window { + desktop?: ClipCCDesktopApi; +} diff --git a/app/desktop/tsconfig.json b/app/desktop/tsconfig.json new file mode 100644 index 00000000..e278f3b2 --- /dev/null +++ b/app/desktop/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Bundler", + "strict": true, + "jsx": "react", + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "types": [ + "node", + "electron" + ], + "lib": [ + "ES2022", + "DOM" + ] + }, + "include": [ + "src/**/*" + ] +} \ No newline at end of file diff --git a/app/desktop/webpack.config.mjs b/app/desktop/webpack.config.mjs new file mode 100644 index 00000000..93094539 --- /dev/null +++ b/app/desktop/webpack.config.mjs @@ -0,0 +1,25 @@ +// @ts-check + +import mainConfig from './webpack.main.mjs'; +import preloadConfig from './webpack.preload.mjs'; +import rendererConfig from './webpack.renderer.mjs'; + +/** + * Select configs by target. + * @param {{target?: string}} env Build environment flags. + * @returns {import('webpack').Configuration | import('webpack').Configuration[]} Target-specific config or all configs. + */ +export default env => { + const target = env?.target; + + switch (target) { + case 'main': + return mainConfig; + case 'preload': + return preloadConfig; + case 'renderer': + return rendererConfig; + default: + return [mainConfig, preloadConfig, rendererConfig]; + } +}; diff --git a/app/desktop/webpack.main.mjs b/app/desktop/webpack.main.mjs new file mode 100644 index 00000000..879c7859 --- /dev/null +++ b/app/desktop/webpack.main.mjs @@ -0,0 +1,45 @@ +// @ts-check + +import path from 'path'; +import {createRequire} from 'module'; + +const require = createRequire(import.meta.url); + +/** @type {import('webpack').Configuration} */ +export default { + name: 'main', + mode: process.env.NODE_ENV === 'production' ? 'production' : 'development', + target: 'electron-main', + entry: { + index: './src/main/index.ts' + }, + output: { + path: path.resolve(import.meta.dirname, 'dist', 'main'), + filename: '[name].js' + }, + resolve: { + extensions: ['.ts', '.js', '.json'] + }, + devtool: process.env.NODE_ENV === 'production' ? false : 'cheap-module-source-map', + module: { + rules: [ + { + test: /\.tsx?$/, + loader: 'esbuild-loader', + include: path.resolve(import.meta.dirname, 'src', 'main'), + options: { + loader: 'tsx', + tsconfigRaw: require('./tsconfig.json') + } + }, + { + test: /\.jsx?$/, + loader: 'esbuild-loader', + include: path.resolve(import.meta.dirname, 'src', 'main'), + options: { + loader: 'jsx' + } + } + ] + } +}; diff --git a/app/desktop/webpack.preload.mjs b/app/desktop/webpack.preload.mjs new file mode 100644 index 00000000..a0da9623 --- /dev/null +++ b/app/desktop/webpack.preload.mjs @@ -0,0 +1,45 @@ +// @ts-check + +import path from 'path'; +import {createRequire} from 'module'; + +const require = createRequire(import.meta.url); + +/** @type {import('webpack').Configuration} */ +export default { + name: 'preload', + mode: process.env.NODE_ENV === 'production' ? 'production' : 'development', + target: 'electron-preload', + entry: { + preload: './src/preload/index.ts' + }, + output: { + path: path.resolve(import.meta.dirname, 'dist', 'main'), + filename: '[name].js' + }, + resolve: { + extensions: ['.ts', '.js', '.json'] + }, + devtool: process.env.NODE_ENV === 'production' ? false : 'cheap-module-source-map', + module: { + rules: [ + { + test: /\.tsx?$/, + loader: 'esbuild-loader', + include: path.resolve(import.meta.dirname, 'src', 'preload'), + options: { + loader: 'tsx', + tsconfigRaw: require('./tsconfig.json') + } + }, + { + test: /\.jsx?$/, + loader: 'esbuild-loader', + include: path.resolve(import.meta.dirname, 'src', 'preload'), + options: { + loader: 'jsx' + } + } + ] + } +}; diff --git a/app/desktop/webpack.renderer.mjs b/app/desktop/webpack.renderer.mjs new file mode 100644 index 00000000..47af2802 --- /dev/null +++ b/app/desktop/webpack.renderer.mjs @@ -0,0 +1,220 @@ +// @ts-check + +import path from 'path'; + +import CopyWebpackPlugin from 'copy-webpack-plugin'; +import NodePolyfillPlugin from 'node-polyfill-webpack-plugin'; +import {createRequire} from 'module'; +import RuleInheritancePlugin from 'rule-inheritance-webpack-plugin'; +import webpack from 'webpack'; +const require = createRequire(import.meta.url); + +const IS_PRODUCTION = process.env.NODE_ENV === 'production'; +const {version} = require('../../package.json'); + +/** + * @typedef {import('webpack-dev-server').Configuration} ConfigurationWithDevServer + */ + + +/** @satisfies {webpack.Configuration} */ +const rendererConfig = { + name: 'renderer', + mode: IS_PRODUCTION ? 'production' : 'development', + target: 'web', + entry: { + index: './src/renderer/index.ts' + }, + output: { + path: path.resolve(import.meta.dirname, 'dist', 'renderer'), + filename: '[name].js' + }, + resolve: { + extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'] + }, + devtool: IS_PRODUCTION ? false : 'cheap-module-source-map', + devServer: { + host: 'localhost', + port: 8386, + hot: false, + liveReload: true, + static: [ + { + directory: path.resolve(import.meta.dirname, 'static'), + publicPath: '/static' + }, + { + directory: path.resolve(import.meta.dirname, '../../packages/gui/static'), + publicPath: '/static' + }, + { + directory: path.resolve(import.meta.dirname, '../../packages/block/media'), + publicPath: '/static/blocks-media/default' + }, + { + directory: path.resolve(import.meta.dirname, '../../packages/block/media'), + publicPath: '/static/blocks-media/high-contrast' + }, + { + directory: path.resolve( + import.meta.dirname, + '../../packages/gui/src/lib/themes/high-contrast/blocks-media' + ), + publicPath: '/static/blocks-media/high-contrast' + } + ], + compress: true + }, + module: { + rules: [ + { + test: /\.tsx?$/, + loader: 'esbuild-loader', + include: path.resolve(import.meta.dirname, 'src', 'renderer'), + options: { + loader: 'tsx', + tsconfigRaw: require('./tsconfig.json') + } + }, + { + test: /\.jsx?$/, + loader: 'esbuild-loader', + include: path.resolve(import.meta.dirname, 'src', 'renderer'), + options: { + loader: 'jsx' + } + }, + { + test: /\.css$/, + include: [ + path.resolve(import.meta.dirname, 'src', 'renderer'), + require.resolve('react-tabs/style/react-tabs.css', { + paths: [path.resolve(import.meta.dirname, '../../packages/gui')] + }) + ], + use: [{ + loader: 'style-loader' + }, { + loader: 'css-loader', + options: { + modules: { + localIdentName: '[name]_[local]_[hash:base64:5]', + exportLocalsConvention: 'camelCase' + }, + importLoaders: 1 + } + }, { + loader: 'postcss-loader', + options: { + postcssOptions: { + plugins: [ + 'postcss-import' + ] + } + } + }] + }, + { + test: /\.(svg|png|wav|gif|jpg)$/, + include: path.resolve(import.meta.dirname, 'src'), + type: 'asset/resource', + generator: { + filename: 'static/assets/[hash][ext][query]' + } + } + ] + }, + plugins: [ + new RuleInheritancePlugin({ + packages: [ + path.resolve(import.meta.dirname, '../../packages/gui') + ], + callbacks: { + 'babel-loader': (rule, loader, packagePath) => { + if (!rule.options) { + rule.options = {}; + } else if (typeof rule.options === 'string') { + console.warn(`We don't support string options for babel-loader in ${packagePath}. Ignoring.`); + return; + } + + if (typeof rule.use === 'string') { + rule.use = { + loader: rule.use, + options: {} + }; + } + + // See https://babeljs.io/docs/options#cwd + if (!rule.options.cwd) { + rule.options.cwd = packagePath; + } + } + } + }), + new CopyWebpackPlugin({ + patterns: [ + { + from: path.resolve(import.meta.dirname, 'static'), + to: './static', + noErrorOnMissing: true + }, + { + from: path.resolve(import.meta.dirname, '../../packages/gui/static'), + to: './static' + }, + { + from: path.resolve(import.meta.dirname, 'src', 'renderer', 'index.html'), + to: '.' + }, + { + from: path.resolve(import.meta.dirname, 'src', 'renderer', 'index.css'), + to: '.' + }, + { + from: path.resolve(import.meta.dirname, 'src', 'renderer', 'loading.html'), + to: '.' + }, + { + from: path.resolve(import.meta.dirname, '../../packages/block/media'), + to: 'static/blocks-media/default' + }, + { + from: path.resolve(import.meta.dirname, '../../packages/block/media'), + to: 'static/blocks-media/high-contrast' + }, + { + from: path.resolve( + import.meta.dirname, + '../../packages/gui/src/lib/themes/high-contrast/blocks-media' + ), + to: 'static/blocks-media/high-contrast', + force: true + } + ] + }), + new webpack.DefinePlugin({ + 'process.env.DEBUG': Boolean(process.env.DEBUG), + 'process.env.GA_ID': `"${process.env.GA_ID || 'UA-000000-01'}"`, + 'clipcc.VERSION': version, + 'clipcc.BUILD_TIME': Date.now() + }), + new NodePolyfillPlugin({ + includeAliases: ['buffer', 'Buffer', 'events'] + }) + ] +}; + +if (!IS_PRODUCTION) { + rendererConfig.module.rules.push({ + test: /blocks-msgs\.js$/, + include: [ + path.resolve(import.meta.dirname, '../../packages/l10n/locales') + ], + use: [{ + loader: path.resolve(import.meta.dirname, '../../packages/gui/scripts/block-message-loader.js') + }] + }); +} + +export default rendererConfig; diff --git a/package.json b/package.json index 91e79372..e32e8396 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "start": "pnpm run gui start", "prepare": "husky", "build:dist": "cross-env NODE_ENV=production pnpm run build:full", - "build:full": "pnpm l10n build && pnpm audio build && pnpm storage build && pnpm svg-renderer build && pnpm render build && pnpm block build && pnpm vm build && pnpm paint build && node packages/gui/scripts/prepublish.mjs && pnpm gui build", + "build:full": "pnpm l10n build && pnpm audio build && pnpm storage build && pnpm svg-renderer build && pnpm render build && pnpm block build && pnpm vm build && pnpm paint build && node packages/gui/scripts/prepublish.mjs && pnpm gui build && cross-env LIBRARY_ONLY=1 pnpm gui build", "build": "pnpm block build && pnpm gui build", "test": "pnpm gui test:unit && pnpm block test && pnpm vm test", "performance": "pnpm vm performance", @@ -23,6 +23,7 @@ "bump": "pnpm changeset version", "release-all": "pnpm changeset publish", "patch:convert": "node ./scripts/convert-patch.mjs", + "desktop": "pnpm --filter clipcc-desktop", "gui": "pnpm --filter clipcc-gui", "vm": "pnpm --filter clipcc-vm", "block": "pnpm --filter clipcc-block", diff --git a/packages/block/webpack.config.js b/packages/block/webpack.config.js index d62572d7..4aab7f70 100644 --- a/packages/block/webpack.config.js +++ b/packages/block/webpack.config.js @@ -20,7 +20,8 @@ const baseConfig = { }, { test: /\.ts$/, exclude: /node_modules/, - use: 'ts-loader' + use: 'ts-loader', + include: path.resolve(__dirname, 'src') }, { test: /_compressed\.js$/, enforce: 'pre', diff --git a/packages/gui/package.json b/packages/gui/package.json index 17c6764e..83305030 100644 --- a/packages/gui/package.json +++ b/packages/gui/package.json @@ -10,8 +10,15 @@ "url": "https://github.com/Clipteam/clipcc.git" }, "exports": { - "types": "./dist/types/index.d.ts", - "default": "./dist/scratch-gui.js" + ".": { + "types": "./dist/types/index.d.ts", + "webpack": "./src/index.js", + "default": "./dist/scratch-gui.js" + }, + "./libraries/backdrops.json": "./dist/libraries/backdrops.json", + "./libraries/costumes.json": "./dist/libraries/costumes.json", + "./libraries/sounds.json": "./dist/libraries/sounds.json", + "./libraries/sprites.json": "./dist/libraries/sprites.json" }, "scripts": { "build:types": "tsc --project ./tsconfig.dts.json", diff --git a/packages/gui/src/index.js b/packages/gui/src/index.js index b94d3985..eaa7a667 100644 --- a/packages/gui/src/index.js +++ b/packages/gui/src/index.js @@ -2,9 +2,22 @@ import GUI from './containers/gui.tsx'; import AppStateHOC from './lib/app-state-hoc.tsx'; import GuiReducer, {guiInitialState, guiMiddleware, initEmbedded, initFullScreen, initPlayer} from './reducers/gui'; import LocalesReducer, {localesInitialState, initLocale} from './reducers/locales'; +import { + defaultProjectId, + LoadingState, + onLoadedProject, + requestNewProject, + requestProjectUpload, + setProjectId, + remixProject +} from './reducers/project-state'; +import { + openLoadingProject, + closeLoadingProject, + openTelemetryModal +} from './reducers/modals'; import {ScratchPaintReducer} from 'clipcc-paint'; import {setFullScreen, setPlayer} from './reducers/mode'; -import {remixProject} from './reducers/project-state'; import {setAppElement} from 'react-modal'; import totallyNormalStrings from './lib/l10n.js'; @@ -25,6 +38,15 @@ export { initPlayer, initFullScreen, initLocale, + defaultProjectId, + LoadingState, + onLoadedProject, + requestNewProject, + requestProjectUpload, + setProjectId, + openLoadingProject, + closeLoadingProject, + openTelemetryModal, localesInitialState, remixProject, setFullScreen, diff --git a/packages/gui/webpack.config.js b/packages/gui/webpack.config.js index 87fc87a9..efbf6d5b 100644 --- a/packages/gui/webpack.config.js +++ b/packages/gui/webpack.config.js @@ -14,6 +14,7 @@ const STATIC_PATH = process.env.STATIC_PATH || '/static'; const IS_PRODUCTION = process.env.NODE_ENV === 'production'; const BUILD_DIST = IS_PRODUCTION || process.env.BUILD_MODE === 'dist'; const IS_CI = process.env.CI; +const LIBRARY_ONLY = process.env.LIBRARY_ONLY; const base = { mode: IS_PRODUCTION ? 'production' : 'development', @@ -78,10 +79,7 @@ const base = { }] }, { test: /\.hex$/, - type: 'asset/inline', - generator: { - dataUrl: content => `data:text/plain;base64,${content.toString('base64')}` - } + type: 'asset' }, { resourceQuery: '?arrayBuffer', type: 'javascript/auto', @@ -151,7 +149,7 @@ if (!IS_PRODUCTION) { }); } -module.exports = [ +module.exports = (BUILD_DIST ? [] : [ // to run editor examples defaultsDeep({}, base, { entry: { @@ -243,8 +241,8 @@ module.exports = [ }) ]) }) -].concat( - BUILD_DIST ? ( +]).concat( + (BUILD_DIST || LIBRARY_ONLY) ? ( // export as library defaultsDeep({}, base, { target: 'web', diff --git a/packages/render/webpack.config.js b/packages/render/webpack.config.js index d198dba6..61770cd3 100644 --- a/packages/render/webpack.config.js +++ b/packages/render/webpack.config.js @@ -44,7 +44,9 @@ const base = { path.resolve(__dirname, '../svg-renderer') ] }), - new NodePolyfillPlugin() + new NodePolyfillPlugin({ + includeAliases: ['Buffer', 'events'] + }) ] }; diff --git a/packages/storage/package.json b/packages/storage/package.json index 41aceace..4fd553e9 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -56,7 +56,9 @@ "jest": "catalog:", "json": "^9.0.6", "node-fetch": "^3.3.2", + "node-polyfill-webpack-plugin": "^3.0.0", "rimraf": "6.0.1", + "terser-webpack-plugin": "^5.3.17", "ts-jest": "^29.4.5", "ts-jest-mock-import-meta": "1.2.1", "typescript": "catalog:", diff --git a/packages/svg-renderer/package.json b/packages/svg-renderer/package.json index e8824d70..7b4107d3 100644 --- a/packages/svg-renderer/package.json +++ b/packages/svg-renderer/package.json @@ -32,6 +32,7 @@ "css-tree": "^1.1.3", "fastestsmallesttextencoderdecoder": "^1.0.22", "isomorphic-dompurify": "^2.14.0", + "lodash.defaultsdeep": "^4.6.1", "transformation-matrix": "^2.16.1" }, "devDependencies": { @@ -42,6 +43,7 @@ "@babel/preset-typescript": "^7.28.5", "@types/css-tree": "^2.3.8", "@types/jsdom": "^28.0.0", + "@xmldom/xmldom": "0.8.11", "babel-core": "7.0.0-bridge.0", "babel-loader": "^10.1.1", "copy-webpack-plugin": "^14.0.0", @@ -59,8 +61,7 @@ "typescript": "catalog:", "webpack": "catalog:", "webpack-cli": "6.0.1", - "webpack-dev-server": "5.2.3", - "@xmldom/xmldom": "0.8.11" + "webpack-dev-server": "5.2.3" }, "browserslist": [ "Chrome >= 63", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 513508c4..cb65d462 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -56,6 +56,114 @@ importers: specifier: ^9.1.7 version: 9.1.7 + app/desktop: + devDependencies: + '@types/lodash.bindall': + specifier: ^4.4.9 + version: 4.4.9 + '@types/lodash.omit': + specifier: ^4.5.9 + version: 4.5.9 + '@types/node': + specifier: ^22.15.30 + version: 22.19.17 + '@types/react': + specifier: 16.1.0 + version: 16.1.0 + '@types/react-dom': + specifier: 16.0.11 + version: 16.0.11 + clipcc-gui: + specifier: workspace:~ + version: link:../../packages/gui + clipcc-storage: + specifier: workspace:~ + version: link:../../packages/storage + clipcc-vm: + specifier: workspace:~ + version: link:../../packages/vm + copy-webpack-plugin: + specifier: ^14.0.0 + version: 14.0.0(webpack@5.105.4) + cross-env: + specifier: ^10.1.0 + version: 10.1.0 + css-loader: + specifier: 6.7.3 + version: 6.7.3(webpack@5.105.4) + electron: + specifier: ^41.2.0 + version: 41.2.0 + electron-builder: + specifier: ^26.8.1 + version: 26.8.1(electron-builder-squirrel-windows@26.8.1) + esbuild-loader: + specifier: ^4.4.3 + version: 4.4.3(webpack@5.105.4) + eslint: + specifier: ^9.39.2 + version: 9.39.2(jiti@2.6.1) + eslint-config-clipcc: + specifier: workspace:~ + version: link:../../packages/lint-config + globals: + specifier: ^16.5.0 + version: 16.5.0 + lodash.bindall: + specifier: 4.4.0 + version: 4.4.0 + node-polyfill-webpack-plugin: + specifier: ^3.0.0 + version: 3.0.0(webpack@5.105.4) + png2icons: + specifier: ^2.0.1 + version: 2.0.1 + postcss-import: + specifier: ^12.0.0 + version: 12.0.1 + postcss-loader: + specifier: 7.0.2 + version: 7.0.2(postcss@8.5.8)(webpack@5.105.4) + react: + specifier: 'catalog:' + version: 16.2.0 + react-dom: + specifier: 16.2.1 + version: 16.2.1(react@16.2.0) + react-redux: + specifier: 5.0.7 + version: 5.0.7(react@16.2.0)(redux@3.7.2) + redux: + specifier: 3.7.2 + version: 3.7.2 + rimraf: + specifier: ^6.1.3 + version: 6.1.3 + rule-inheritance-webpack-plugin: + specifier: ^0.4.0 + version: 0.4.0(webpack@5.105.4) + sharp: + specifier: ^0.34.4 + version: 0.34.5 + style-loader: + specifier: ^4.0.0 + version: 4.0.0(webpack@5.105.4) + ts-loader: + specifier: ^9.5.4 + version: 9.5.4(typescript@5.9.3)(webpack@5.105.4) + typescript: + specifier: 'catalog:' + version: 5.9.3 + webpack: + specifier: 'catalog:' + version: 5.105.4(webpack-cli@6.0.1) + webpack-cli: + specifier: ^6.0.1 + version: 6.0.1(webpack-dev-server@5.2.3)(webpack@5.105.4) + webpack-dev-server: + specifier: ^5.2.3 + version: 5.2.3(tslib@2.8.1)(webpack-cli@6.0.1)(webpack@5.105.4) + packages/audio: dependencies: '@turbowarp/nanolog': @@ -1045,9 +1153,15 @@ importers: node-fetch: specifier: ^3.3.2 version: 3.3.2 + node-polyfill-webpack-plugin: + specifier: ^3.0.0 + version: 3.0.0(webpack@5.105.4) rimraf: specifier: 6.0.1 version: 6.0.1 + terser-webpack-plugin: + specifier: ^5.3.17 + version: 5.3.17(webpack@5.105.4) ts-jest: specifier: ^29.4.5 version: 29.4.6(@babel/core@7.29.0)(@jest/transform@30.3.0)(@jest/types@30.3.0)(babel-jest@30.3.0(@babel/core@7.29.0))(jest-util@30.3.0)(jest@30.3.0(@types/node@25.5.2))(typescript@5.9.3) @@ -1084,6 +1198,9 @@ importers: isomorphic-dompurify: specifier: ^2.14.0 version: 2.36.0 + lodash.defaultsdeep: + specifier: ^4.6.1 + version: 4.6.1 transformation-matrix: specifier: ^2.16.1 version: 2.16.1 @@ -1338,6 +1455,9 @@ importers: packages: + 7zip-bin@5.2.0: + resolution: {integrity: sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==} + '@acemir/cssom@0.9.31': resolution: {integrity: sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==} @@ -2257,10 +2377,54 @@ packages: resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} engines: {node: '>=20.19.0'} + '@develar/schema-utils@2.6.5': + resolution: {integrity: sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==} + engines: {node: '>= 8.9.0'} + '@discoveryjs/json-ext@0.6.3': resolution: {integrity: sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==} engines: {node: '>=14.17.0'} + '@electron/asar@3.4.1': + resolution: {integrity: sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==} + engines: {node: '>=10.12.0'} + hasBin: true + + '@electron/fuses@1.8.0': + resolution: {integrity: sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw==} + hasBin: true + + '@electron/get@2.0.3': + resolution: {integrity: sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==} + engines: {node: '>=12'} + + '@electron/get@3.1.0': + resolution: {integrity: sha512-F+nKc0xW+kVbBRhFzaMgPy3KwmuNTYX1fx6+FxxoSnNgwYX6LD7AKBTWkU0MQ6IBoe7dz069CNkR673sPAgkCQ==} + engines: {node: '>=14'} + + '@electron/notarize@2.5.0': + resolution: {integrity: sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A==} + engines: {node: '>= 10.0.0'} + + '@electron/osx-sign@1.3.3': + resolution: {integrity: sha512-KZ8mhXvWv2rIEgMbWZ4y33bDHyUKMXnx4M0sTyPNK/vcB81ImdeY9Ggdqy0SWbMDgmbqyQ+phgejh6V3R2QuSg==} + engines: {node: '>=12.0.0'} + hasBin: true + + '@electron/rebuild@4.0.3': + resolution: {integrity: sha512-u9vpTHRMkOYCs/1FLiSVAFZ7FbjsXK+bQuzviJZa+lG7BHZl1nz52/IcGvwa3sk80/fc3llutBkbCq10Vh8WQA==} + engines: {node: '>=22.12.0'} + hasBin: true + + '@electron/universal@2.0.3': + resolution: {integrity: sha512-Wn9sPYIVFRFl5HmwMJkARCCf7rqK/EurkfQ/rJZ14mHP3iYTjZSIOSVonEAnhWeAXwtw7zOekGRlc6yTtZ0t+g==} + engines: {node: '>=16.4'} + + '@electron/windows-sign@1.2.2': + resolution: {integrity: sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ==} + engines: {node: '>=14.14'} + hasBin: true + '@emnapi/core@1.8.1': resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} @@ -2285,6 +2449,162 @@ packages: resolution: {integrity: sha512-Q9hjxWI5xBM+qW2enxfe8wDKdFWMfd0Z29k5ZJnuBqD/CasY5Zryj09aCA6owbGATWz+39p5uIdaHXpopOcG8g==} engines: {node: '>=10'} + '@esbuild/aix-ppc64@0.27.7': + resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.27.7': + resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.7': + resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.7': + resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.27.7': + resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.7': + resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.7': + resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.7': + resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.27.7': + resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.7': + resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.27.7': + resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.27.7': + resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.27.7': + resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.7': + resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.7': + resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.7': + resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.27.7': + resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.7': + resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.7': + resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.7': + resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.7': + resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.7': + resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.7': + resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.27.7': + resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.27.7': + resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.27.7': + resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.9.1': resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2372,6 +2692,143 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} + '@img/colour@1.1.0': + resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.34.5': + resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.34.5': + resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.2.4': + resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.2.4': + resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.2.4': + resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.2.4': + resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-ppc64@1.2.4': + resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} + cpu: [ppc64] + os: [linux] + + '@img/sharp-libvips-linux-riscv64@1.2.4': + resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} + cpu: [riscv64] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.2.4': + resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.2.4': + resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.34.5': + resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.34.5': + resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-ppc64@0.34.5': + resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ppc64] + os: [linux] + + '@img/sharp-linux-riscv64@0.34.5': + resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [riscv64] + os: [linux] + + '@img/sharp-linux-s390x@0.34.5': + resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.34.5': + resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.34.5': + resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.34.5': + resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.34.5': + resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.34.5': + resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.34.5': + resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.34.5': + resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + '@inquirer/external-editor@1.0.3': resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} engines: {node: '>=18'} @@ -2668,6 +3125,14 @@ packages: '@leichtgewicht/ip-codec@2.0.5': resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==} + '@malept/cross-spawn-promise@2.0.0': + resolution: {integrity: sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==} + engines: {node: '>= 12.13.0'} + + '@malept/flatpak-bundler@0.4.0': + resolution: {integrity: sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==} + engines: {node: '>= 10.0.0'} + '@manypkg/find-root@1.1.0': resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} @@ -2709,10 +3174,18 @@ packages: resolution: {integrity: sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==} engines: {node: ^16.14.0 || >=18.0.0} + '@npmcli/agent@3.0.0': + resolution: {integrity: sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q==} + engines: {node: ^18.17.0 || >=20.5.0} + '@npmcli/fs@3.1.1': resolution: {integrity: sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + '@npmcli/fs@4.0.0': + resolution: {integrity: sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==} + engines: {node: ^18.17.0 || >=20.5.0} + '@npmcli/git@5.0.8': resolution: {integrity: sha512-liASfw5cqhjNW9UFd+ruwwdEf/lbOAQjLL2XY2dFW/bkJheXDYZgOyul/4gVvEV4BWkTXjYGmDqMw9uegdbJNQ==} engines: {node: ^16.14.0 || >=18.0.0} @@ -2833,12 +3306,20 @@ packages: resolution: {integrity: sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA==} engines: {node: '>=18'} + '@sindresorhus/is@4.6.0': + resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} + engines: {node: '>=10'} + '@sinonjs/commons@3.0.1': resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} '@sinonjs/fake-timers@15.1.1': resolution: {integrity: sha512-cO5W33JgAPbOh07tvZjUOJ7oWhtaqGHiZw+11DPbyqh2kHTBc3eF/CjJDeQ4205RLQsX6rxCuYOroFQwl7JDRw==} + '@szmarczak/http-timer@4.0.6': + resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} + engines: {node: '>=10'} + '@tapjs/after-each@4.0.0': resolution: {integrity: sha512-RrkYMB3SpXKFJAijbgNkOexiClX5aygkCIHKHPIfnfqsPozkwjYbtVQs6d1/tG8ytiJtH5rvybuNJMRRNDcfBQ==} engines: {node: 20 || >=22} @@ -3028,6 +3509,9 @@ packages: '@types/bonjour@3.5.13': resolution: {integrity: sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==} + '@types/cacheable-request@6.0.3': + resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} + '@types/connect-history-api-fallback@1.5.4': resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==} @@ -3037,6 +3521,9 @@ packages: '@types/css-tree@2.3.11': resolution: {integrity: sha512-aEokibJOI77uIlqoBOkVbaQGC9zII0A+JH1kcTNKW2CwyYWD8KM6qdo+4c77wD3wZOQfJuNWAr9M4hdk+YhDIg==} + '@types/debug@4.1.13': + resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} + '@types/eslint-scope@3.7.7': resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} @@ -3055,9 +3542,15 @@ packages: '@types/fastestsmallesttextencoderdecoder@1.0.2': resolution: {integrity: sha512-0Md9qUxGnQ9uJ0NjsA70Y0NHIl3NwfBO1d8CGXK0zhczRL85CXJ3M0JZsmCNQ0WcAbt08FuT4U1G1mWQqgOsUg==} + '@types/fs-extra@9.0.13': + resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} + '@types/html-minifier-terser@6.1.0': resolution: {integrity: sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==} + '@types/http-cache-semantics@4.2.0': + resolution: {integrity: sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==} + '@types/http-errors@2.0.5': resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} @@ -3097,6 +3590,9 @@ packages: '@types/keymirror@0.1.4': resolution: {integrity: sha512-EPlgLrh8Z9OLtGmJRqRIar19Apg7a7xLckaOs16WGraEUuEM4sVdoKBA9MOIQsSbrW+yH1F4QD7WpIlCIy0V0A==} + '@types/keyv@3.1.4': + resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} + '@types/lodash.bindall@4.4.9': resolution: {integrity: sha512-sG6V5+T3JcB39nXfORM+kHRH6DiCB+95DfGrH2YpPMXRpt6q3rn7VrW3dItiOLasJYeHq1jxc+tOW1ijT+d1wg==} @@ -3109,12 +3605,21 @@ packages: '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + '@types/node-hid@1.3.4': resolution: {integrity: sha512-0ootpsYetN9vjqkDSwm/cA4fk/9yGM/PO0X8SLPE/BzXlUaBelImMWMymtF9QEoEzxY0pnhcROIJM0CNSUqO8w==} '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + '@types/node@22.19.17': + resolution: {integrity: sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==} + + '@types/node@24.12.2': + resolution: {integrity: sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==} + '@types/node@25.5.0': resolution: {integrity: sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==} @@ -3124,6 +3629,9 @@ packages: '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + '@types/plist@3.0.5': + resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==} + '@types/prop-types@15.5.9': resolution: {integrity: sha512-Nha5b+jmBI271jdTMwrHiNXM+DvThjHOfyZtMX9kj/c/LUj2xiLHsG/1L3tJ8DjAoQN48cHwUwtqBotjyXaSdQ==} @@ -3145,6 +3653,9 @@ packages: '@types/react@16.1.0': resolution: {integrity: sha512-gXrB20mWBLrYGtkdf5fA6wL3FEXpY2Nz8OOgVn1qonp66JE4mqFXUigKD8CVDofQu+EsSy8G4UFRJAshFWMOvA==} + '@types/responselike@1.0.3': + resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} + '@types/retry@0.12.2': resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} @@ -3182,6 +3693,9 @@ packages: '@types/usb@1.5.4': resolution: {integrity: sha512-NOUza/8yuswu6RoECQyPHEjA34qpDaeONQ72fm+bCnnN2DJjDePAY+NsmV17H88oIlq4JlJ2mD5Kh5d6R2MwTQ==} + '@types/verror@1.10.11': + resolution: {integrity: sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==} + '@types/w3c-web-usb@1.0.13': resolution: {integrity: sha512-N2nSl3Xsx8mRHZBvMSdNGtzMyeleTvtlEw+ujujgXalPqOjIA6UtrqcB6OzyUjkTbDm3J7P1RNK1lgoO7jxtsw==} @@ -3569,6 +4083,10 @@ packages: resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + abbrev@3.0.1: + resolution: {integrity: sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==} + engines: {node: ^18.17.0 || >=20.5.0} + abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -3712,6 +4230,16 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + app-builder-bin@5.0.0-alpha.12: + resolution: {integrity: sha512-j87o0j6LqPL3QRr8yid6c+Tt5gC7xNfYo6uQIQkorAC6MpeayVMZrEDzKmJJ/Hlv7EnOQpaRm53k6ktDYZyB6w==} + + app-builder-lib@26.8.1: + resolution: {integrity: sha512-p0Im/Dx5C4tmz8QEE1Yn4MkuPC8PrnlRneMhWJj7BBXQfNTJUshM/bp3lusdEsDbvvfJZpXWnYesgSLvwtM2Zw==} + engines: {node: '>=14.0.0'} + peerDependencies: + dmg-builder: 26.8.1 + electron-builder-squirrel-windows: 26.8.1 + are-docs-informative@0.0.2: resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} engines: {node: '>=14'} @@ -3809,6 +4337,10 @@ packages: resolution: {integrity: sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ==} engines: {node: '>=12.0.0'} + assert-plus@1.0.0: + resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} + engines: {node: '>=0.8'} + assert@2.1.0: resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==} @@ -3820,6 +4352,14 @@ packages: resolution: {integrity: sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==} engines: {node: '>=4'} + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + + async-exit-hook@2.0.1: + resolution: {integrity: sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==} + engines: {node: '>=0.12.0'} + async-function@1.0.0: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} @@ -3831,9 +4371,16 @@ packages: async@3.2.3: resolution: {integrity: sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==} + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + at-least-node@1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + atob@2.1.2: resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} engines: {node: '>= 4.5.0'} @@ -4065,6 +4612,9 @@ packages: bl@1.2.3: resolution: {integrity: sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==} + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + blockly@12.5.1: resolution: {integrity: sha512-etXLpUtEkcRibHGwIJ4BsvnIzMJJs0C0yPIjE/W0NCtj8ACha/a7Q9n7Ib6+j7N4EzQ0p28YPZMnypi5pNIj1g==} engines: {node: '>=18'} @@ -4085,6 +4635,10 @@ packages: boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + boolean@3.2.0: + resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + bowser@1.9.4: resolution: {integrity: sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==} @@ -4163,9 +4717,19 @@ packages: buffer-xor@1.0.3: resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + builder-util-runtime@9.5.1: + resolution: {integrity: sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ==} + engines: {node: '>=12.0.0'} + + builder-util@26.8.1: + resolution: {integrity: sha512-pm1lTYbGyc90DHgCDO7eo8Rl4EqKLciayNbZqGziqnH9jrlKe8ZANGdityLZU+pJh16dfzjAx2xQq9McuIPEtw==} + builtin-status-codes@3.0.0: resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==} @@ -4195,6 +4759,18 @@ packages: resolution: {integrity: sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==} engines: {node: ^16.14.0 || >=18.0.0} + cacache@19.0.1: + resolution: {integrity: sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + cacheable-lookup@5.0.4: + resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} + engines: {node: '>=10.6.0'} + + cacheable-request@7.0.4: + resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==} + engines: {node: '>=8'} + call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -4289,10 +4865,17 @@ packages: engines: {node: '>=20'} hasBin: true + chromium-pickle-js@0.2.0: + resolution: {integrity: sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==} + ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} + ci-info@4.3.1: + resolution: {integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==} + engines: {node: '>=8'} + ci-info@4.4.0: resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} engines: {node: '>=8'} @@ -4327,6 +4910,14 @@ packages: resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-truncate@2.1.0: + resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} + engines: {node: '>=8'} + cli-truncate@4.0.0: resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} engines: {node: '>=18'} @@ -4347,6 +4938,13 @@ packages: resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} engines: {node: '>=6'} + clone-response@1.0.3: + resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} + + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + co@4.6.0: resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} @@ -4406,6 +5004,10 @@ packages: commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + commander@5.1.0: + resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} + engines: {node: '>= 6'} + commander@6.2.1: resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} engines: {node: '>= 6'} @@ -4414,6 +5016,10 @@ packages: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} + commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + comment-parser@1.4.1: resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} engines: {node: '>= 12.0.0'} @@ -4430,6 +5036,10 @@ packages: compare-func@2.0.0: resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + compare-version@0.1.2: + resolution: {integrity: sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==} + engines: {node: '>=0.10.0'} + compare-versions@6.1.1: resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} @@ -4522,6 +5132,9 @@ packages: core-js@3.48.0: resolution: {integrity: sha512-zpEHTy1fjTMZCKLHUZoVeylt9XrzaIN2rbPXEt0k+q7JE5CkCZdo6bNq55bn24a69CH7ErAVLKijxJja4fw+UQ==} + core-util-is@1.0.2: + resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} + core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -4551,6 +5164,9 @@ packages: engines: {node: '>= 0.4.0'} hasBin: true + crc@3.8.0: + resolution: {integrity: sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==} + create-ecdh@4.0.4: resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} @@ -4560,6 +5176,9 @@ packages: create-hmac@1.1.7: resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + cross-dirname@0.1.0: + resolution: {integrity: sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==} + cross-env@10.1.0: resolution: {integrity: sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==} engines: {node: '>=20'} @@ -4708,6 +5327,10 @@ packages: resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} engines: {node: '>=0.10'} + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + dedent@1.7.2: resolution: {integrity: sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==} peerDependencies: @@ -4731,6 +5354,13 @@ packages: resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} engines: {node: '>=18'} + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + + defer-to-connect@2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} + define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} @@ -4774,6 +5404,10 @@ packages: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + detect-newline@3.1.0: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} @@ -4799,6 +5433,9 @@ packages: diffie-hellman@5.0.3: resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} + dir-compare@4.2.0: + resolution: {integrity: sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==} + dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -4806,6 +5443,15 @@ packages: discontinuous-range@1.0.0: resolution: {integrity: sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==} + dmg-builder@26.8.1: + resolution: {integrity: sha512-glMJgnTreo8CFINujtAhCgN96QAqApDMZ8Vl1r8f0QT8QprvC1UCltV4CcWj20YoIyLZx6IUskaJZ0NV8fokcg==} + + dmg-license@1.0.11: + resolution: {integrity: sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==} + engines: {node: '>=8'} + os: [darwin] + hasBin: true + dns-packet@5.6.1: resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} engines: {node: '>=6'} @@ -4883,6 +5529,14 @@ packages: resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} engines: {node: '>=8'} + dotenv-expand@11.0.7: + resolution: {integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==} + engines: {node: '>=12'} + + dotenv@16.6.1: + resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} + engines: {node: '>=12'} + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -4896,9 +5550,34 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + + electron-builder-squirrel-windows@26.8.1: + resolution: {integrity: sha512-o288fIdgPLHA76eDrFADHPoo7VyGkDCYbLV1GzndaMSAVBoZrGvM9m2IehdcVMzdAZJ2eV9bgyissQXHv5tGzA==} + + electron-builder@26.8.1: + resolution: {integrity: sha512-uWhx1r74NGpCagG0ULs/P9Nqv2nsoo+7eo4fLUOB8L8MdWltq9odW/uuLXMFCDGnPafknYLZgjNX0ZIFRzOQAw==} + engines: {node: '>=14.0.0'} + hasBin: true + + electron-publish@26.8.1: + resolution: {integrity: sha512-q+jrSTIh/Cv4eGZa7oVR+grEJo/FoLMYBAnSL5GCtqwUpr1T+VgKB/dn1pnzxIxqD8S/jP1yilT9VrwCqINR4w==} + electron-to-chromium@1.5.307: resolution: {integrity: sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==} + electron-winstaller@5.4.0: + resolution: {integrity: sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==} + engines: {node: '>=8.0.0'} + + electron@41.2.0: + resolution: {integrity: sha512-0OKLiymqfV0WK68RBXqAm3Myad2TpI5wwxLCBEUcH5Nugo3YfSk7p1Js/AL9266qTz5xZioUnxt9hG8FFwax0g==} + engines: {node: '>= 12.20.55'} + hasBin: true + elliptic@6.6.1: resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} @@ -5050,9 +5729,22 @@ packages: es-toolkit@1.45.1: resolution: {integrity: sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==} + es6-error@4.1.1: + resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} + es6-object-assign@1.1.0: resolution: {integrity: sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==} + esbuild-loader@4.4.3: + resolution: {integrity: sha512-Wpui03EzqC151xFteKlgJQhbyZl5CgnBpUHXVuao02nItULlkaTeiLdEMPTmR2zdwpEBWkXVNoT5dDOYJluUzg==} + peerDependencies: + webpack: ^4.40.0 || ^5.0.0 + + esbuild@0.27.7: + resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -5369,6 +6061,10 @@ packages: engines: {node: '>= 10.17.0'} hasBin: true + extsprintf@1.4.1: + resolution: {integrity: sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==} + engines: {'0': node >=0.6.0} + falafel@2.2.5: resolution: {integrity: sha512-HuC1qF9iTnHDnML9YZAdCDQwT0yKl/U55K4XSUXqGAA2GLoafFgWRqdAbhWJxXaYD4pyoVxAJ8wH670jMpI9DQ==} engines: {node: '>=0.4.0'} @@ -5440,6 +6136,9 @@ packages: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} + filelist@1.0.6: + resolution: {integrity: sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==} + filename-regex@2.0.1: resolution: {integrity: sha512-BTCqyBaWBTsauvnHiE8i562+EdJj+oUpkqWp2R1iCoR8f6oo8STRu3of7WJJ0TqWtxN50a5YFpzYK4Jj9esYfQ==} engines: {node: '>=0.10.0'} @@ -5591,6 +6290,14 @@ packages: fromentries@1.3.2: resolution: {integrity: sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==} + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + fs-extra@11.3.4: + resolution: {integrity: sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==} + engines: {node: '>=14.14'} + fs-extra@7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} engines: {node: '>=6 <7 || >=8'} @@ -5599,6 +6306,10 @@ packages: resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} engines: {node: '>=6 <7 || >=8'} + fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + fs-minipass@2.1.0: resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} engines: {node: '>= 8'} @@ -5677,6 +6388,9 @@ packages: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} + get-tsconfig@4.13.7: + resolution: {integrity: sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==} + get-uri@6.0.5: resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==} engines: {node: '>= 14'} @@ -5739,6 +6453,10 @@ packages: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + global-agent@3.0.0: + resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==} + engines: {node: '>=10.0'} + global-directory@4.0.1: resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} engines: {node: '>=18'} @@ -5774,6 +6492,10 @@ packages: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} + got@11.8.6: + resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} + engines: {node: '>=10.19.0'} + graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -5861,6 +6583,10 @@ packages: hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + hosted-git-info@4.1.0: + resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} + engines: {node: '>=10'} + hosted-git-info@7.0.2: resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} engines: {node: ^16.14.0 || >=18.0.0} @@ -5952,6 +6678,10 @@ packages: resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} engines: {node: '>=8.0.0'} + http2-wrapper@1.0.3: + resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} + engines: {node: '>=10.19.0'} + https-browserify@1.0.0: resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==} @@ -5987,6 +6717,11 @@ packages: hyphenate-style-name@1.1.0: resolution: {integrity: sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==} + iconv-corefoundation@1.1.7: + resolution: {integrity: sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==} + engines: {node: ^8.11.2 || >=10} + os: [darwin] + iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -6279,6 +7014,10 @@ packages: engines: {node: '>=14.16'} hasBin: true + is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + is-lambda@1.0.1: resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} @@ -6384,6 +7123,10 @@ packages: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + is-url@1.2.4: resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==} @@ -6423,6 +7166,14 @@ packages: isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + isbinaryfile@4.0.10: + resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==} + engines: {node: '>= 8.0.0'} + + isbinaryfile@5.0.7: + resolution: {integrity: sha512-gnWD14Jh3FzS3CPhF0AxNOJ8CxqeblPTADzI38r0wt8ZyQl5edpy75myt08EG2oKvpyiqSqsx+Wkz9vtkbTqYQ==} + engines: {node: '>= 18.0.0'} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -6482,6 +7233,11 @@ packages: resolution: {integrity: sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==} engines: {node: 20 || >=22} + jake@10.9.4: + resolution: {integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==} + engines: {node: '>=10'} + hasBin: true + jest-canvas-mock@2.3.1: resolution: {integrity: sha512-5FnSZPrX3Q2ZfsbYNE3wqKR3+XorN8qFzDzB5o0golWgt6EOX1+emBnpOc9IAQ+NXFj8Nzm3h7ZdE/9H0ylBcg==} @@ -6760,6 +7516,9 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + json5@1.0.2: resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} hasBin: true @@ -6780,6 +7539,9 @@ packages: jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + jsonfile@6.2.0: + resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} + jsonparse@1.3.1: resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} engines: {'0': node >= 0.2.0} @@ -6812,6 +7574,9 @@ packages: launch-editor@2.13.1: resolution: {integrity: sha512-lPSddlAAluRKJ7/cjRFoXUFzaX7q/YKI7yPHuEvSJVqoXvFnJov1/Ud87Aa4zULIbA9Nja4mSPK8l0z/7eV2wA==} + lazy-val@1.0.5: + resolution: {integrity: sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==} + leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -6936,6 +7701,10 @@ packages: lodash@4.17.23: resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + lookup-closest-locale@6.2.0: resolution: {integrity: sha512-/c2kL+Vnp1jnV6K6RpDTHK3dgg0Tu2VVp+elEiJpjfS1UyY7AjOYHohRug6wT0OpoX2qFgNORndE9RqesfVxWQ==} @@ -6946,6 +7715,10 @@ packages: lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + lowercase-keys@2.0.0: + resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} + engines: {node: '>=8'} + lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -6956,6 +7729,10 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + lru-cache@7.18.3: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} @@ -6981,12 +7758,20 @@ packages: resolution: {integrity: sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==} engines: {node: ^16.14.0 || >=18.0.0} + make-fetch-happen@14.0.3: + resolution: {integrity: sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==} + engines: {node: ^18.17.0 || >=20.5.0} + makeerror@1.0.12: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} map-limit@0.0.1: resolution: {integrity: sha512-pJpcfLPnIF/Sk3taPW21G/RQsEEirGaFpCW3oXRwH9dnFHPHNGjNyvh++rdmC2fNqEaTw2MhYJraoJWAHx8kEg==} + matcher@3.0.0: + resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==} + engines: {node: '>=10'} + matchmediaquery@0.3.1: resolution: {integrity: sha512-Hlk20WQHRIm9EE9luN1kjRjYXAQToHOIAHPJn9buxBwuhfTHoKUcX+lXBbxc85DVQfXYbEQ4HcwQdd128E3qHQ==} @@ -7084,6 +7869,14 @@ packages: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} + mimic-response@1.0.1: + resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} + engines: {node: '>=4'} + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + min-document@2.19.2: resolution: {integrity: sha512-8S5I8db/uZN8r9HSLFVWPdJCvYOejMcEC82VIzNUc6Zkklf/d1gg2psfE79/vyhWOj4+J8MtwmoOz3TmvaGu5A==} @@ -7106,6 +7899,10 @@ packages: minimatch@3.1.5: resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + minimatch@5.1.9: + resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==} + engines: {node: '>=10'} + minimatch@9.0.9: resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} engines: {node: '>=16 || 14 >=14.17'} @@ -7121,6 +7918,10 @@ packages: resolution: {integrity: sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + minipass-fetch@4.0.1: + resolution: {integrity: sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ==} + engines: {node: ^18.17.0 || >=20.5.0} + minipass-flush@1.0.5: resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} engines: {node: '>= 8'} @@ -7221,6 +8022,10 @@ packages: resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} engines: {node: '>= 0.6'} + negotiator@1.0.0: + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} + engines: {node: '>= 0.6'} + neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} @@ -7234,6 +8039,16 @@ packages: no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + node-abi@4.28.0: + resolution: {integrity: sha512-Qfp5XZL1cJDOabOT8H5gnqMTmM4NjvYzHp4I/Kt/Sl76OVkOBBHRFlPspGV0hYvMoqQsypFjT/Yp7Km0beXW9g==} + engines: {node: '>=22.12.0'} + + node-addon-api@1.7.2: + resolution: {integrity: sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==} + + node-api-version@0.2.1: + resolution: {integrity: sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==} + node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} @@ -7267,6 +8082,11 @@ packages: engines: {node: ^16.14.0 || >=18.0.0} hasBin: true + node-gyp@11.5.0: + resolution: {integrity: sha512-ra7Kvlhxn5V9Slyus0ygMa2h+UqExPqUIkfk7Pc8QTLT956JLSy51uWFwHtIYy0vI8cB4BDhc/S03+880My/LQ==} + engines: {node: ^18.17.0 || >=20.5.0} + hasBin: true + node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} @@ -7287,6 +8107,11 @@ packages: engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} hasBin: true + nopt@8.1.0: + resolution: {integrity: sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==} + engines: {node: ^18.17.0 || >=20.5.0} + hasBin: true + normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} @@ -7306,6 +8131,10 @@ packages: resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} engines: {node: '>=0.10.0'} + normalize-url@6.1.0: + resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} + engines: {node: '>=10'} + npm-bundled@3.0.1: resolution: {integrity: sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -7440,6 +8269,10 @@ packages: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} + ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + os-browserify@0.3.0: resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==} @@ -7454,6 +8287,10 @@ packages: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} + p-cancelable@2.1.1: + resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} + engines: {node: '>=8'} + p-filter@2.1.0: resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} engines: {node: '>=8'} @@ -7498,6 +8335,10 @@ packages: resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} engines: {node: '>=10'} + p-map@7.0.4: + resolution: {integrity: sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==} + engines: {node: '>=18'} + p-queue@3.0.0: resolution: {integrity: sha512-2tv/MRmPXfmfnjLLJAHl+DdU8p2DhZafAnlpm/C/T5BpF5L9wKz5tMin4A4N2zVpJL2YMhPlRmtO7s5EtNrjfA==} engines: {node: '>=6'} @@ -7654,6 +8495,10 @@ packages: resolution: {integrity: sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==} engines: {node: '>= 0.10'} + pe-library@0.4.1: + resolution: {integrity: sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw==} + engines: {node: '>=12', npm: '>=6'} + pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} @@ -7714,6 +8559,14 @@ packages: engines: {node: '>=12'} hasBin: true + plist@3.1.0: + resolution: {integrity: sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==} + engines: {node: '>=10.4.0'} + + png2icons@2.0.1: + resolution: {integrity: sha512-GDEQJr8OG4e6JMp7mABtXFSEpgJa1CCpbQiAR+EjhkHJHnUL9zPPtbOrjsMD8gUbikgv3j7x404b0YJsV3aVFA==} + hasBin: true + pngjs@5.0.0: resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} engines: {node: '>=10.13.0'} @@ -7783,6 +8636,11 @@ packages: resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} engines: {node: ^10 || ^12 || >=14} + postject@1.0.0-alpha.6: + resolution: {integrity: sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==} + engines: {node: '>=14.0.0'} + hasBin: true + prelude-ls@1.1.2: resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} engines: {node: '>= 0.8.0'} @@ -7827,6 +8685,10 @@ packages: resolution: {integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + proc-log@5.0.0: + resolution: {integrity: sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==} + engines: {node: ^18.17.0 || >=20.5.0} + process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} @@ -7930,6 +8792,10 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + quote-stream@1.0.2: resolution: {integrity: sha512-kKr2uQ2AokadPjvTyKJQad9xELbZwYzWlNfI3Uz2j/ib5u6H9lDP7fUUR//rMycd0gv4Z5P1qXMfXR8YpIxrjQ==} hasBin: true @@ -8101,6 +8967,10 @@ packages: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} + read-binary-file-arch@1.0.6: + resolution: {integrity: sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==} + hasBin: true + read-cache@1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} @@ -8246,10 +9116,17 @@ packages: requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + resedit@1.7.2: + resolution: {integrity: sha512-vHjcY2MlAITJhC0eRD/Vv8Vlgmu9Sd3LX9zZvtGzU5ZImdTN3+d6e/4mnTyV8vEbyf1sgNIrWxhWlrys52OkEA==} + engines: {node: '>=12', npm: '>=6'} + reserved-identifiers@1.2.0: resolution: {integrity: sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw==} engines: {node: '>=18'} + resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + resolve-cwd@3.0.0: resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} engines: {node: '>=8'} @@ -8266,6 +9143,9 @@ packages: resolution: {integrity: sha512-gLWKdA5tiv5j/D7ipR47u3ovbVfzFPrctTdw2Ulnpmr6PPVVSvPKGNWu09jXVNlOSLLAeD6CA13bjIelpWttSw==} engines: {node: 20 || >=22} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve@1.22.11: resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} engines: {node: '>= 0.4'} @@ -8276,6 +9156,9 @@ packages: engines: {node: '>= 0.4'} hasBin: true + responselike@2.0.1: + resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} + restore-cursor@3.1.0: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} @@ -8329,6 +9212,10 @@ packages: resolution: {integrity: sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==} engines: {node: '>= 0.8'} + roarr@2.15.4: + resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==} + engines: {node: '>=8.0'} + rrweb-cssom@0.8.0: resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} @@ -8376,6 +9263,9 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + sanitize-filename@1.6.4: + resolution: {integrity: sha512-9ZyI08PsvdQl2r/bBIGubpVdR3RR9sY6RDiWFPreA21C/EFlQhmgo20UZlNjZMMZNubusLhAQozkA0Od5J21Eg==} + sanitize-html-react@1.13.0: resolution: {integrity: sha512-EDoOqPd2wrJEV6px8XvWEx7b+JNIoka3mI4fdBVa6S/de9b+UnmzKsVqBkj93s+FwIaBv1fBuXiXkoVxmAU3MQ==} @@ -8424,6 +9314,9 @@ packages: resolution: {integrity: sha512-ftnu3TW4+3eBfLRFnDEkzGxSF/10BJBkaLJuBHZX0kiPS7bRdlpZGu6YGt4KngMkdTwJE6MbjavFpqHvqVt+Ew==} engines: {node: '>=18'} + semver-compare@1.0.0: + resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} + semver@5.5.0: resolution: {integrity: sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==} hasBin: true @@ -8445,6 +9338,10 @@ packages: resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} engines: {node: '>= 0.8.0'} + serialize-error@7.0.1: + resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==} + engines: {node: '>=10'} + serialize-javascript@7.0.4: resolution: {integrity: sha512-DuGdB+Po43Q5Jxwpzt1lhyFSYKryqoNjQSA9M92tyw0lyHIOur+XCalOUe0KTJpyqzT8+fQ5A0Jf7vCx/NKmIg==} engines: {node: '>=20.0.0'} @@ -8487,6 +9384,10 @@ packages: shallow-copy@0.0.1: resolution: {integrity: sha512-b6i4ZpVuUxB9h5gfCxPiusKYkqTMOjEbBs4wMaFbkfia4yFv92UKZ6Df8WXcKbn08JNL/abvg3FnMAOfakDvUw==} + sharp@0.34.5: + resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + shebang-command@1.2.0: resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} engines: {node: '>=0.10.0'} @@ -8543,6 +9444,10 @@ packages: resolution: {integrity: sha512-8G+/XDU8wNsJOQS5ysDVO0Etg9/2uA5gR9l4ZwijjlwxBcrU6RPfwi2+jJmbP+Ap1Hlp/nVAaEO4Fj22/SL2gQ==} engines: {node: ^16.14.0 || >=18.0.0} + simple-update-notifier@2.0.0: + resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} + engines: {node: '>=10'} + slash@2.0.0: resolution: {integrity: sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==} engines: {node: '>=6'} @@ -8555,6 +9460,10 @@ packages: resolution: {integrity: sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==} engines: {node: '>=6'} + slice-ansi@3.0.0: + resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} + engines: {node: '>=8'} + slice-ansi@5.0.0: resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} engines: {node: '>=12'} @@ -8634,10 +9543,17 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + ssri@10.0.6: resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + ssri@12.0.0: + resolution: {integrity: sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==} + engines: {node: ^18.17.0 || >=20.5.0} + stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} @@ -8645,6 +9561,10 @@ packages: startaudiocontext@1.2.1: resolution: {integrity: sha512-ooOQhOAoCwzMIRwWd9j7xF8kAMo1Wv7Zfw+q6dWDW5gxJUKx15HJXWDg89GMDqfdle9xsqPv+uioneX+bI643g==} + stat-mode@1.0.0: + resolution: {integrity: sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==} + engines: {node: '>= 6'} + static-eval@2.1.1: resolution: {integrity: sha512-MgWpQ/ZjGieSVB3eOJVs4OA2LT/q1vx98KPCTTQPzq/aLr0YUXTsgryTXr4SLfR0ZfUUCiedM9n/ABeDIyy4mA==} @@ -8779,6 +9699,10 @@ packages: peerDependencies: webpack: ^5.27.0 + sumchecker@3.0.1: + resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==} + engines: {node: '>= 8.0'} + supports-color@2.0.0: resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} engines: {node: '>=0.8.0'} @@ -8857,6 +9781,13 @@ packages: tcp-port-used@1.0.2: resolution: {integrity: sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==} + temp-file@3.4.0: + resolution: {integrity: sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==} + + temp@0.9.4: + resolution: {integrity: sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==} + engines: {node: '>=6.0.0'} + term-size@2.2.1: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} @@ -8919,6 +9850,9 @@ packages: resolution: {integrity: sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==} engines: {node: '>=0.6.0'} + tiny-async-pool@1.3.0: + resolution: {integrity: sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA==} + tiny-inflate@1.0.3: resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} @@ -8947,6 +9881,9 @@ packages: resolution: {integrity: sha512-keinCnPbwXEUG3ilrWQZU+CqcTTzHq9m2HhoUP2l7Xmi8l1LuijAXLpAJ5zRW+ifKTNscs4NdCkfkDCBYm352w==} hasBin: true + tmp-promise@3.0.3: + resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==} + tmp@0.0.30: resolution: {integrity: sha512-HXdTB7lvMwcb55XFfrTM8CPr/IYREk4hVBFaQ4b/6nInrluSL86hfHm7vu0luYKCfyBZp2trCjpc8caC3vVM3w==} engines: {node: '>=0.4.0'} @@ -8955,6 +9892,10 @@ packages: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} + tmp@0.2.5: + resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} + engines: {node: '>=14.14'} + tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} @@ -9022,6 +9963,9 @@ packages: resolution: {integrity: sha512-iGbM7X2slv9ORDVj2y2FFUq3cP/ypbtu2nQ8S38ufjL0glBABvmR9pTdsib1XtS2LUhhLMbelaBUaf/s5J3dSw==} engines: {node: '>= 8'} + truncate-utf8-bytes@1.0.2: + resolution: {integrity: sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==} + ts-api-utils@1.4.3: resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==} engines: {node: '>=16'} @@ -9119,6 +10063,10 @@ packages: resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} engines: {node: '>=4'} + type-fest@0.13.1: + resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} + engines: {node: '>=10'} + type-fest@0.21.3: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} @@ -9189,6 +10137,12 @@ packages: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + undici-types@7.18.2: resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} @@ -9222,14 +10176,26 @@ packages: resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + unique-filename@4.0.0: + resolution: {integrity: sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==} + engines: {node: ^18.17.0 || >=20.5.0} + unique-slug@4.0.0: resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + unique-slug@5.0.0: + resolution: {integrity: sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==} + engines: {node: ^18.17.0 || >=20.5.0} + universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} @@ -9250,6 +10216,9 @@ packages: resolution: {integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==} engines: {node: '>= 0.4'} + utf8-byte-length@1.0.5: + resolution: {integrity: sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==} + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -9292,6 +10261,10 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} + verror@1.10.1: + resolution: {integrity: sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==} + engines: {node: '>=0.6.0'} + vlq@0.2.3: resolution: {integrity: sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==} @@ -9322,6 +10295,9 @@ packages: wbuf@1.7.3: resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==} + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + web-audio-test-api@0.5.2: resolution: {integrity: sha512-RevLfVjp+wwe/dBPe361IpmNpeXXW6JVmlp8dk0YIxLwAh7evn6JpEQQalVgX4PH/jA8tpLpjD/8tFNUYTf88w==} @@ -9459,6 +10435,11 @@ packages: engines: {node: ^16.13.0 || >=18.0.0} hasBin: true + which@5.0.0: + resolution: {integrity: sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==} + engines: {node: ^18.17.0 || >=20.5.0} + hasBin: true + widest-line@5.0.0: resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} engines: {node: '>=18'} @@ -9542,6 +10523,10 @@ packages: resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} engines: {node: '>=4.0'} + xmlbuilder@15.1.1: + resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} + engines: {node: '>=8.0'} + xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} @@ -9605,6 +10590,8 @@ packages: snapshots: + 7zip-bin@5.2.0: {} + '@acemir/cssom@0.9.31': {} '@alcalzone/ansi-tokenize@0.1.3': @@ -10847,53 +11834,236 @@ snapshots: dependencies: '@csstools/css-tokenizer': 3.0.4 - '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)': - dependencies: - '@csstools/css-tokenizer': 4.0.0 + '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-syntax-patches-for-csstree@1.1.0': {} + + '@csstools/css-tokenizer@3.0.4': {} + + '@csstools/css-tokenizer@4.0.0': {} + + '@develar/schema-utils@2.6.5': + dependencies: + ajv: 6.14.0 + ajv-keywords: 3.5.2(ajv@6.14.0) + + '@discoveryjs/json-ext@0.6.3': {} + + '@electron/asar@3.4.1': + dependencies: + commander: 5.1.0 + glob: 7.2.3 + minimatch: 3.1.5 + + '@electron/fuses@1.8.0': + dependencies: + chalk: 4.1.2 + fs-extra: 9.1.0 + minimist: 1.2.8 + + '@electron/get@2.0.3': + dependencies: + debug: 4.4.3 + env-paths: 2.2.1 + fs-extra: 8.1.0 + got: 11.8.6 + progress: 2.0.3 + semver: 6.3.1 + sumchecker: 3.0.1 + optionalDependencies: + global-agent: 3.0.0 + transitivePeerDependencies: + - supports-color + + '@electron/get@3.1.0': + dependencies: + debug: 4.4.3 + env-paths: 2.2.1 + fs-extra: 8.1.0 + got: 11.8.6 + progress: 2.0.3 + semver: 6.3.1 + sumchecker: 3.0.1 + optionalDependencies: + global-agent: 3.0.0 + transitivePeerDependencies: + - supports-color + + '@electron/notarize@2.5.0': + dependencies: + debug: 4.4.3 + fs-extra: 9.1.0 + promise-retry: 2.0.1 + transitivePeerDependencies: + - supports-color + + '@electron/osx-sign@1.3.3': + dependencies: + compare-version: 0.1.2 + debug: 4.4.3 + fs-extra: 10.1.0 + isbinaryfile: 4.0.10 + minimist: 1.2.8 + plist: 3.1.0 + transitivePeerDependencies: + - supports-color + + '@electron/rebuild@4.0.3': + dependencies: + '@malept/cross-spawn-promise': 2.0.0 + debug: 4.4.3 + detect-libc: 2.1.2 + got: 11.8.6 + graceful-fs: 4.2.11 + node-abi: 4.28.0 + node-api-version: 0.2.1 + node-gyp: 11.5.0 + ora: 5.4.1 + read-binary-file-arch: 1.0.6 + semver: 7.7.4 + tar: 7.5.10 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + + '@electron/universal@2.0.3': + dependencies: + '@electron/asar': 3.4.1 + '@malept/cross-spawn-promise': 2.0.0 + debug: 4.4.3 + dir-compare: 4.2.0 + fs-extra: 11.3.4 + minimatch: 9.0.9 + plist: 3.1.0 + transitivePeerDependencies: + - supports-color + + '@electron/windows-sign@1.2.2': + dependencies: + cross-dirname: 0.1.0 + debug: 4.4.3 + fs-extra: 11.3.4 + minimist: 1.2.8 + postject: 1.0.0-alpha.6 + transitivePeerDependencies: + - supports-color + optional: true + + '@emnapi/core@1.8.1': + dependencies: + '@emnapi/wasi-threads': 1.1.0 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.8.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.1.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@epic-web/invariant@1.0.0': {} + + '@es-joy/jsdoccomment@0.50.2': + dependencies: + '@types/estree': 1.0.8 + '@typescript-eslint/types': 8.57.0 + comment-parser: 1.4.1 + esquery: 1.7.0 + jsdoc-type-pratt-parser: 4.1.0 + + '@es-joy/jsdoccomment@0.78.0': + dependencies: + '@types/estree': 1.0.8 + '@typescript-eslint/types': 8.57.0 + comment-parser: 1.4.1 + esquery: 1.7.0 + jsdoc-type-pratt-parser: 7.0.0 + + '@es-joy/resolve.exports@1.2.0': {} + + '@esbuild/aix-ppc64@0.27.7': + optional: true + + '@esbuild/android-arm64@0.27.7': + optional: true + + '@esbuild/android-arm@0.27.7': + optional: true + + '@esbuild/android-x64@0.27.7': + optional: true + + '@esbuild/darwin-arm64@0.27.7': + optional: true + + '@esbuild/darwin-x64@0.27.7': + optional: true + + '@esbuild/freebsd-arm64@0.27.7': + optional: true + + '@esbuild/freebsd-x64@0.27.7': + optional: true + + '@esbuild/linux-arm64@0.27.7': + optional: true + + '@esbuild/linux-arm@0.27.7': + optional: true + + '@esbuild/linux-ia32@0.27.7': + optional: true + + '@esbuild/linux-loong64@0.27.7': + optional: true + + '@esbuild/linux-mips64el@0.27.7': + optional: true + + '@esbuild/linux-ppc64@0.27.7': + optional: true - '@csstools/css-syntax-patches-for-csstree@1.1.0': {} + '@esbuild/linux-riscv64@0.27.7': + optional: true - '@csstools/css-tokenizer@3.0.4': {} + '@esbuild/linux-s390x@0.27.7': + optional: true - '@csstools/css-tokenizer@4.0.0': {} + '@esbuild/linux-x64@0.27.7': + optional: true - '@discoveryjs/json-ext@0.6.3': {} + '@esbuild/netbsd-arm64@0.27.7': + optional: true - '@emnapi/core@1.8.1': - dependencies: - '@emnapi/wasi-threads': 1.1.0 - tslib: 2.8.1 + '@esbuild/netbsd-x64@0.27.7': optional: true - '@emnapi/runtime@1.8.1': - dependencies: - tslib: 2.8.1 + '@esbuild/openbsd-arm64@0.27.7': optional: true - '@emnapi/wasi-threads@1.1.0': - dependencies: - tslib: 2.8.1 + '@esbuild/openbsd-x64@0.27.7': optional: true - '@epic-web/invariant@1.0.0': {} + '@esbuild/openharmony-arm64@0.27.7': + optional: true - '@es-joy/jsdoccomment@0.50.2': - dependencies: - '@types/estree': 1.0.8 - '@typescript-eslint/types': 8.57.0 - comment-parser: 1.4.1 - esquery: 1.7.0 - jsdoc-type-pratt-parser: 4.1.0 + '@esbuild/sunos-x64@0.27.7': + optional: true - '@es-joy/jsdoccomment@0.78.0': - dependencies: - '@types/estree': 1.0.8 - '@typescript-eslint/types': 8.57.0 - comment-parser: 1.4.1 - esquery: 1.7.0 - jsdoc-type-pratt-parser: 7.0.0 + '@esbuild/win32-arm64@0.27.7': + optional: true - '@es-joy/resolve.exports@1.2.0': {} + '@esbuild/win32-ia32@0.27.7': + optional: true + + '@esbuild/win32-x64@0.27.7': + optional: true '@eslint-community/eslint-utils@4.9.1(eslint@9.39.2(jiti@2.6.1))': dependencies: @@ -10977,6 +12147,102 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} + '@img/colour@1.1.0': {} + + '@img/sharp-darwin-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.2.4 + optional: true + + '@img/sharp-darwin-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.2.4 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.2.4': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-riscv64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-s390x@1.2.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + optional: true + + '@img/sharp-linux-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.2.4 + optional: true + + '@img/sharp-linux-arm@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.2.4 + optional: true + + '@img/sharp-linux-ppc64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.2.4 + optional: true + + '@img/sharp-linux-riscv64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-riscv64': 1.2.4 + optional: true + + '@img/sharp-linux-s390x@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.2.4 + optional: true + + '@img/sharp-linux-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + optional: true + + '@img/sharp-wasm32@0.34.5': + dependencies: + '@emnapi/runtime': 1.8.1 + optional: true + + '@img/sharp-win32-arm64@0.34.5': + optional: true + + '@img/sharp-win32-ia32@0.34.5': + optional: true + + '@img/sharp-win32-x64@0.34.5': + optional: true + '@inquirer/external-editor@1.0.3(@types/node@25.5.2)': dependencies: chardet: 2.1.1 @@ -11093,7 +12359,7 @@ snapshots: '@jest/fake-timers': 30.3.0 '@jest/types': 30.3.0 '@types/jsdom': 21.1.7 - '@types/node': 25.5.0 + '@types/node': 25.5.2 jest-mock: 30.3.0 jest-util: 30.3.0 jsdom: 26.1.0(patch_hash=4725214219761e272bac827780047d8a6effa8b02b2c8516a14e1363bb08948b) @@ -11104,7 +12370,7 @@ snapshots: '@jest/fake-timers': 30.3.0 '@jest/types': 30.3.0 '@types/jsdom': 21.1.7 - '@types/node': 25.5.0 + '@types/node': 25.5.2 jest-mock: 30.3.0 jest-util: 30.3.0 jsdom: 28.1.0 @@ -11113,7 +12379,7 @@ snapshots: dependencies: '@jest/fake-timers': 30.3.0 '@jest/types': 30.3.0 - '@types/node': 25.5.0 + '@types/node': 25.5.2 jest-mock: 30.3.0 '@jest/expect-utils@29.7.0': @@ -11421,6 +12687,19 @@ snapshots: '@leichtgewicht/ip-codec@2.0.5': {} + '@malept/cross-spawn-promise@2.0.0': + dependencies: + cross-spawn: 7.0.6 + + '@malept/flatpak-bundler@0.4.0': + dependencies: + debug: 4.4.3 + fs-extra: 9.1.0 + lodash: 4.17.23 + tmp-promise: 3.0.3 + transitivePeerDependencies: + - supports-color + '@manypkg/find-root@1.1.0': dependencies: '@babel/runtime': 7.28.6 @@ -11479,10 +12758,24 @@ snapshots: transitivePeerDependencies: - supports-color + '@npmcli/agent@3.0.0': + dependencies: + agent-base: 7.1.4 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + lru-cache: 10.4.3 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + '@npmcli/fs@3.1.1': dependencies: semver: 7.7.4 + '@npmcli/fs@4.0.0': + dependencies: + semver: 7.7.4 + '@npmcli/git@5.0.8': dependencies: '@npmcli/promise-spawn': 7.0.2 @@ -11677,6 +12970,8 @@ snapshots: '@sindresorhus/base62@1.0.0': {} + '@sindresorhus/is@4.6.0': {} + '@sinonjs/commons@3.0.1': dependencies: type-detect: 4.0.8 @@ -11685,6 +12980,10 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 + '@szmarczak/http-timer@4.0.6': + dependencies: + defer-to-connect: 2.0.1 + '@tapjs/after-each@4.0.0(@tapjs/core@4.0.0(@types/node@25.5.2)(react-dom@16.4.0(react@18.3.1))(react@18.3.1))': dependencies: '@tapjs/core': 4.0.0(@types/node@25.5.2)(react-dom@16.4.0(react@18.3.1))(react@18.3.1) @@ -12000,6 +13299,13 @@ snapshots: dependencies: '@types/node': 25.5.2 + '@types/cacheable-request@6.0.3': + dependencies: + '@types/http-cache-semantics': 4.2.0 + '@types/keyv': 3.1.4 + '@types/node': 25.5.2 + '@types/responselike': 1.0.3 + '@types/connect-history-api-fallback@1.5.4': dependencies: '@types/express-serve-static-core': 4.19.8 @@ -12011,6 +13317,10 @@ snapshots: '@types/css-tree@2.3.11': {} + '@types/debug@4.1.13': + dependencies: + '@types/ms': 2.1.0 + '@types/eslint-scope@3.7.7': dependencies: '@types/eslint': 9.6.1 @@ -12039,8 +13349,14 @@ snapshots: '@types/fastestsmallesttextencoderdecoder@1.0.2': {} + '@types/fs-extra@9.0.13': + dependencies: + '@types/node': 25.5.2 + '@types/html-minifier-terser@6.1.0': {} + '@types/http-cache-semantics@4.2.0': {} + '@types/http-errors@2.0.5': {} '@types/http-proxy@1.17.17': @@ -12077,7 +13393,7 @@ snapshots: '@types/jsdom@28.0.0': dependencies: - '@types/node': 12.20.55 + '@types/node': 25.5.2 '@types/tough-cookie': 4.0.5 parse5: 7.3.0 undici-types: 7.22.0 @@ -12088,6 +13404,10 @@ snapshots: '@types/keymirror@0.1.4': {} + '@types/keyv@3.1.4': + dependencies: + '@types/node': 25.5.2 + '@types/lodash.bindall@4.4.9': dependencies: '@types/lodash': 4.17.24 @@ -12100,12 +13420,22 @@ snapshots: '@types/mime@1.3.5': {} + '@types/ms@2.1.0': {} + '@types/node-hid@1.3.4': dependencies: '@types/node': 25.5.2 '@types/node@12.20.55': {} + '@types/node@22.19.17': + dependencies: + undici-types: 6.21.0 + + '@types/node@24.12.2': + dependencies: + undici-types: 7.16.0 + '@types/node@25.5.0': dependencies: undici-types: 7.18.2 @@ -12116,6 +13446,12 @@ snapshots: '@types/parse-json@4.0.2': {} + '@types/plist@3.0.5': + dependencies: + '@types/node': 25.5.2 + xmlbuilder: 15.1.1 + optional: true + '@types/prop-types@15.5.9': {} '@types/qs@6.15.0': {} @@ -12137,6 +13473,10 @@ snapshots: '@types/react@16.1.0': {} + '@types/responselike@1.0.3': + dependencies: + '@types/node': 25.5.2 + '@types/retry@0.12.2': {} '@types/schema-utils@2.4.0': @@ -12179,6 +13519,9 @@ snapshots: dependencies: '@types/node': 25.5.2 + '@types/verror@1.10.11': + optional: true + '@types/w3c-web-usb@1.0.13': {} '@types/ws@8.18.1': @@ -12585,12 +13928,12 @@ snapshots: '@webpack-cli/configtest@3.0.1(webpack-cli@6.0.1)(webpack@5.105.4)': dependencies: webpack: 5.105.4(webpack-cli@6.0.1) - webpack-cli: 6.0.1(webpack@5.105.4) + webpack-cli: 6.0.1(webpack-dev-server@5.2.3)(webpack@5.105.4) '@webpack-cli/info@3.0.1(webpack-cli@6.0.1)(webpack@5.105.4)': dependencies: webpack: 5.105.4(webpack-cli@6.0.1) - webpack-cli: 6.0.1(webpack@5.105.4) + webpack-cli: 6.0.1(webpack-dev-server@5.2.3)(webpack@5.105.4) '@webpack-cli/serve@3.0.1(webpack-cli@6.0.1)(webpack-dev-server@5.2.3)(webpack@5.105.4)': dependencies: @@ -12612,6 +13955,8 @@ snapshots: abbrev@2.0.0: {} + abbrev@3.0.1: {} + abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 @@ -12743,6 +14088,51 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.1 + app-builder-bin@5.0.0-alpha.12: {} + + app-builder-lib@26.8.1(dmg-builder@26.8.1)(electron-builder-squirrel-windows@26.8.1): + dependencies: + '@develar/schema-utils': 2.6.5 + '@electron/asar': 3.4.1 + '@electron/fuses': 1.8.0 + '@electron/get': 3.1.0 + '@electron/notarize': 2.5.0 + '@electron/osx-sign': 1.3.3 + '@electron/rebuild': 4.0.3 + '@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.8.1 + builder-util-runtime: 9.5.1 + chromium-pickle-js: 0.2.0 + ci-info: 4.3.1 + debug: 4.4.3 + dmg-builder: 26.8.1(electron-builder-squirrel-windows@26.8.1) + dotenv: 16.6.1 + dotenv-expand: 11.0.7 + ejs: 3.1.10 + electron-builder-squirrel-windows: 26.8.1(dmg-builder@26.8.1) + electron-publish: 26.8.1 + fs-extra: 10.1.0 + hosted-git-info: 4.1.0 + isbinaryfile: 5.0.7 + jiti: 2.6.1 + js-yaml: 4.1.1 + json5: 2.2.3 + lazy-val: 1.0.5 + minimatch: 10.2.4 + plist: 3.1.0 + proper-lockfile: 4.1.2 + resedit: 1.7.2 + semver: 7.7.4 + tar: 7.5.10 + temp-file: 3.4.0 + tiny-async-pool: 1.3.0 + which: 5.0.0 + transitivePeerDependencies: + - supports-color + are-docs-informative@0.0.2: {} arg@4.1.3: {} @@ -12882,6 +14272,9 @@ snapshots: pvutils: 1.1.5 tslib: 2.8.1 + assert-plus@1.0.0: + optional: true + assert@2.1.0: dependencies: call-bind: 1.0.8 @@ -12896,14 +14289,23 @@ snapshots: astral-regex@1.0.0: {} + astral-regex@2.0.0: + optional: true + + async-exit-hook@2.0.1: {} + async-function@1.0.0: {} async-hook-domain@4.0.1: {} async@3.2.3: {} + async@3.2.6: {} + asynckit@0.4.0: {} + at-least-node@1.0.0: {} + atob@2.1.2: {} audio-context@1.0.3: {} @@ -13247,6 +14649,12 @@ snapshots: readable-stream: 2.3.8 safe-buffer: 5.2.1 + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + blockly@12.5.1: dependencies: jsdom: 26.1.0(patch_hash=4725214219761e272bac827780047d8a6effa8b02b2c8516a14e1363bb08948b) @@ -13284,6 +14692,9 @@ snapshots: boolbase@1.0.0: {} + boolean@3.2.0: + optional: true + bowser@1.9.4: {} brace-expansion@1.1.12: @@ -13388,11 +14799,44 @@ snapshots: buffer-xor@1.0.3: {} + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + buffer@6.0.3: dependencies: base64-js: 1.5.1 ieee754: 1.2.1 + builder-util-runtime@9.5.1: + dependencies: + debug: 4.4.3 + sax: 1.5.0 + transitivePeerDependencies: + - supports-color + + builder-util@26.8.1: + dependencies: + 7zip-bin: 5.2.0 + '@types/debug': 4.1.13 + app-builder-bin: 5.0.0-alpha.12 + builder-util-runtime: 9.5.1 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + fs-extra: 10.1.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + js-yaml: 4.1.1 + sanitize-filename: 1.6.4 + source-map-support: 0.5.21 + stat-mode: 1.0.0 + temp-file: 3.4.0 + tiny-async-pool: 1.3.0 + transitivePeerDependencies: + - supports-color + builtin-status-codes@3.0.0: {} bundle-name@4.1.0: @@ -13432,6 +14876,33 @@ snapshots: tar: 6.2.1 unique-filename: 3.0.0 + cacache@19.0.1: + dependencies: + '@npmcli/fs': 4.0.0 + fs-minipass: 3.0.3 + glob: 10.5.0 + lru-cache: 10.4.3 + minipass: 7.1.3 + minipass-collect: 2.0.1 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + p-map: 7.0.4 + ssri: 12.0.0 + tar: 7.5.10 + unique-filename: 4.0.0 + + cacheable-lookup@5.0.4: {} + + cacheable-request@7.0.4: + dependencies: + clone-response: 1.0.3 + get-stream: 5.2.0 + http-cache-semantics: 4.2.0 + keyv: 4.5.4 + lowercase-keys: 2.0.0 + normalize-url: 6.1.0 + responselike: 2.0.1 + call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -13547,8 +15018,12 @@ snapshots: - debug - supports-color + chromium-pickle-js@0.2.0: {} + ci-info@3.9.0: {} + ci-info@4.3.1: {} + ci-info@4.4.0: {} cipher-base@1.0.7: @@ -13577,6 +15052,14 @@ snapshots: dependencies: restore-cursor: 4.0.0 + cli-spinners@2.9.2: {} + + cli-truncate@2.1.0: + dependencies: + slice-ansi: 3.0.0 + string-width: 4.2.3 + optional: true + cli-truncate@4.0.0: dependencies: slice-ansi: 5.0.0 @@ -13601,6 +15084,12 @@ snapshots: kind-of: 6.0.3 shallow-clone: 3.0.1 + clone-response@1.0.3: + dependencies: + mimic-response: 1.0.1 + + clone@1.0.4: {} + co@4.6.0: {} code-excerpt@4.0.0: @@ -13645,10 +15134,15 @@ snapshots: commander@2.20.3: {} + commander@5.1.0: {} + commander@6.2.1: {} commander@8.3.0: {} + commander@9.5.0: + optional: true + comment-parser@1.4.1: {} commitlint-config-gitmoji@2.3.1: @@ -13671,6 +15165,8 @@ snapshots: array-ify: 1.0.0 dot-prop: 5.3.0 + compare-version@0.1.2: {} + compare-versions@6.1.1: {} compressible@2.0.18: @@ -13756,6 +15252,9 @@ snapshots: core-js@3.48.0: {} + core-util-is@1.0.2: + optional: true + core-util-is@1.0.3: {} cosmiconfig-typescript-loader@6.2.0(@types/node@25.5.2)(cosmiconfig@9.0.1(typescript@5.9.3))(typescript@5.9.3): @@ -13784,6 +15283,11 @@ snapshots: crc32@0.2.2: {} + crc@3.8.0: + dependencies: + buffer: 5.7.1 + optional: true + create-ecdh@4.0.4: dependencies: bn.js: 4.12.3 @@ -13806,6 +15310,9 @@ snapshots: safe-buffer: 5.2.1 sha.js: 2.4.12 + cross-dirname@0.1.0: + optional: true + cross-env@10.1.0: dependencies: '@epic-web/invariant': 1.0.0 @@ -13978,6 +15485,10 @@ snapshots: decode-uri-component@0.2.2: {} + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + dedent@1.7.2: {} deep-is@0.1.4: {} @@ -13991,6 +15502,12 @@ snapshots: bundle-name: 4.1.0 default-browser-id: 5.0.1 + defaults@1.0.4: + dependencies: + clone: 1.0.4 + + defer-to-connect@2.0.1: {} + define-data-property@1.1.4: dependencies: es-define-property: 1.0.1 @@ -14030,6 +15547,8 @@ snapshots: detect-indent@6.1.0: {} + detect-libc@2.1.2: {} + detect-newline@3.1.0: {} detect-node@2.1.0: {} @@ -14048,12 +15567,42 @@ snapshots: miller-rabin: 4.0.1 randombytes: 2.1.0 + dir-compare@4.2.0: + dependencies: + minimatch: 3.1.5 + p-limit: 3.1.0 + dir-glob@3.0.1: dependencies: path-type: 4.0.0 discontinuous-range@1.0.0: {} + dmg-builder@26.8.1(electron-builder-squirrel-windows@26.8.1): + dependencies: + app-builder-lib: 26.8.1(dmg-builder@26.8.1)(electron-builder-squirrel-windows@26.8.1) + builder-util: 26.8.1 + fs-extra: 10.1.0 + iconv-lite: 0.6.3 + js-yaml: 4.1.1 + optionalDependencies: + dmg-license: 1.0.11 + transitivePeerDependencies: + - electron-builder-squirrel-windows + - supports-color + + dmg-license@1.0.11: + dependencies: + '@types/plist': 3.0.5 + '@types/verror': 1.10.11 + ajv: 6.14.0 + crc: 3.8.0 + iconv-corefoundation: 1.1.7 + plist: 3.1.0 + smart-buffer: 4.2.0 + verror: 1.10.1 + optional: true + dns-packet@5.6.1: dependencies: '@leichtgewicht/ip-codec': 2.0.5 @@ -14150,6 +15699,12 @@ snapshots: dependencies: is-obj: 2.0.0 + dotenv-expand@11.0.7: + dependencies: + dotenv: 16.6.1 + + dotenv@16.6.1: {} + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -14164,8 +15719,70 @@ snapshots: ee-first@1.1.1: {} + ejs@3.1.10: + dependencies: + jake: 10.9.4 + + electron-builder-squirrel-windows@26.8.1(dmg-builder@26.8.1): + dependencies: + app-builder-lib: 26.8.1(dmg-builder@26.8.1)(electron-builder-squirrel-windows@26.8.1) + builder-util: 26.8.1 + electron-winstaller: 5.4.0 + transitivePeerDependencies: + - dmg-builder + - supports-color + + electron-builder@26.8.1(electron-builder-squirrel-windows@26.8.1): + dependencies: + app-builder-lib: 26.8.1(dmg-builder@26.8.1)(electron-builder-squirrel-windows@26.8.1) + builder-util: 26.8.1 + builder-util-runtime: 9.5.1 + chalk: 4.1.2 + ci-info: 4.4.0 + dmg-builder: 26.8.1(electron-builder-squirrel-windows@26.8.1) + fs-extra: 10.1.0 + lazy-val: 1.0.5 + simple-update-notifier: 2.0.0 + yargs: 17.7.2 + transitivePeerDependencies: + - electron-builder-squirrel-windows + - supports-color + + electron-publish@26.8.1: + dependencies: + '@types/fs-extra': 9.0.13 + builder-util: 26.8.1 + builder-util-runtime: 9.5.1 + chalk: 4.1.2 + form-data: 4.0.5 + fs-extra: 10.1.0 + lazy-val: 1.0.5 + mime: 2.6.0 + transitivePeerDependencies: + - supports-color + electron-to-chromium@1.5.307: {} + electron-winstaller@5.4.0: + dependencies: + '@electron/asar': 3.4.1 + debug: 4.4.3 + fs-extra: 7.0.1 + lodash: 4.17.23 + temp: 0.9.4 + optionalDependencies: + '@electron/windows-sign': 1.2.2 + transitivePeerDependencies: + - supports-color + + electron@41.2.0: + dependencies: + '@electron/get': 2.0.3 + '@types/node': 24.12.2 + extract-zip: 2.0.1 + transitivePeerDependencies: + - supports-color + elliptic@6.6.1: dependencies: bn.js: 4.12.3 @@ -14416,8 +16033,48 @@ snapshots: es-toolkit@1.45.1: {} + es6-error@4.1.1: + optional: true + es6-object-assign@1.1.0: {} + esbuild-loader@4.4.3(webpack@5.105.4): + dependencies: + esbuild: 0.27.7 + get-tsconfig: 4.13.7 + loader-utils: 2.0.4 + webpack: 5.105.4(webpack-cli@6.0.1) + webpack-sources: 3.3.4 + + esbuild@0.27.7: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.7 + '@esbuild/android-arm': 0.27.7 + '@esbuild/android-arm64': 0.27.7 + '@esbuild/android-x64': 0.27.7 + '@esbuild/darwin-arm64': 0.27.7 + '@esbuild/darwin-x64': 0.27.7 + '@esbuild/freebsd-arm64': 0.27.7 + '@esbuild/freebsd-x64': 0.27.7 + '@esbuild/linux-arm': 0.27.7 + '@esbuild/linux-arm64': 0.27.7 + '@esbuild/linux-ia32': 0.27.7 + '@esbuild/linux-loong64': 0.27.7 + '@esbuild/linux-mips64el': 0.27.7 + '@esbuild/linux-ppc64': 0.27.7 + '@esbuild/linux-riscv64': 0.27.7 + '@esbuild/linux-s390x': 0.27.7 + '@esbuild/linux-x64': 0.27.7 + '@esbuild/netbsd-arm64': 0.27.7 + '@esbuild/netbsd-x64': 0.27.7 + '@esbuild/openbsd-arm64': 0.27.7 + '@esbuild/openbsd-x64': 0.27.7 + '@esbuild/openharmony-arm64': 0.27.7 + '@esbuild/sunos-x64': 0.27.7 + '@esbuild/win32-arm64': 0.27.7 + '@esbuild/win32-ia32': 0.27.7 + '@esbuild/win32-x64': 0.27.7 + escalade@3.2.0: {} escape-html@1.0.3: {} @@ -14913,6 +16570,9 @@ snapshots: transitivePeerDependencies: - supports-color + extsprintf@1.4.1: + optional: true + falafel@2.2.5: dependencies: acorn: 7.4.1 @@ -14987,6 +16647,10 @@ snapshots: dependencies: flat-cache: 4.0.1 + filelist@1.0.6: + dependencies: + minimatch: 5.1.9 + filename-regex@2.0.1: {} fill-range@2.2.4: @@ -15165,6 +16829,18 @@ snapshots: fromentries@1.3.2: {} + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + + fs-extra@11.3.4: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + fs-extra@7.0.1: dependencies: graceful-fs: 4.2.11 @@ -15177,6 +16853,13 @@ snapshots: jsonfile: 4.0.0 universalify: 0.1.2 + fs-extra@9.1.0: + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + fs-minipass@2.1.0: dependencies: minipass: 3.3.6 @@ -15251,6 +16934,10 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.3.0 + get-tsconfig@4.13.7: + dependencies: + resolve-pkg-maps: 1.0.0 + get-uri@6.0.5: dependencies: basic-ftp: 5.2.0 @@ -15335,6 +17022,16 @@ snapshots: once: 1.4.0 path-is-absolute: 1.0.1 + global-agent@3.0.0: + dependencies: + boolean: 3.2.0 + es6-error: 4.1.1 + matcher: 3.0.0 + roarr: 2.15.4 + semver: 7.7.4 + serialize-error: 7.0.1 + optional: true + global-directory@4.0.1: dependencies: ini: 4.1.1 @@ -15370,6 +17067,20 @@ snapshots: gopd@1.2.0: {} + got@11.8.6: + dependencies: + '@sindresorhus/is': 4.6.0 + '@szmarczak/http-timer': 4.0.6 + '@types/cacheable-request': 6.0.3 + '@types/responselike': 1.0.3 + cacheable-lookup: 5.0.4 + cacheable-request: 7.0.4 + decompress-response: 6.0.0 + http2-wrapper: 1.0.3 + lowercase-keys: 2.0.0 + p-cancelable: 2.1.1 + responselike: 2.0.1 + graceful-fs@4.2.11: {} grapheme-breaker@0.3.2: @@ -15457,6 +17168,10 @@ snapshots: hosted-git-info@2.8.9: {} + hosted-git-info@4.1.0: + dependencies: + lru-cache: 6.0.0 + hosted-git-info@7.0.2: dependencies: lru-cache: 10.4.3 @@ -15594,6 +17309,11 @@ snapshots: transitivePeerDependencies: - debug + http2-wrapper@1.0.3: + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + https-browserify@1.0.0: {} https-proxy-agent@5.0.1: @@ -15622,6 +17342,12 @@ snapshots: hyphenate-style-name@1.1.0: {} + iconv-corefoundation@1.1.7: + dependencies: + cli-truncate: 2.1.0 + node-addon-api: 1.7.2 + optional: true + iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 @@ -15898,6 +17624,8 @@ snapshots: dependencies: is-docker: 3.0.0 + is-interactive@1.0.0: {} + is-lambda@1.0.1: {} is-map@2.0.3: {} @@ -15980,6 +17708,8 @@ snapshots: dependencies: which-typed-array: 1.1.20 + is-unicode-supported@0.1.0: {} + is-url@1.2.4: {} is-utf8@0.2.1: {} @@ -16013,6 +17743,10 @@ snapshots: isarray@2.0.5: {} + isbinaryfile@4.0.10: {} + + isbinaryfile@5.0.7: {} + isexe@2.0.0: {} isexe@3.1.5: {} @@ -16101,6 +17835,12 @@ snapshots: dependencies: '@isaacs/cliui': 9.0.0 + jake@10.9.4: + dependencies: + async: 3.2.6 + filelist: 1.0.6 + picocolors: 1.1.1 + jest-canvas-mock@2.3.1: dependencies: cssfontparser: 1.2.1 @@ -16674,6 +18414,9 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} + json-stringify-safe@5.0.1: + optional: true + json5@1.0.2: dependencies: minimist: 1.2.8 @@ -16690,6 +18433,12 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 + jsonfile@6.2.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + jsonparse@1.3.1: {} jsx-ast-utils@3.3.5: @@ -16725,6 +18474,8 @@ snapshots: picocolors: 1.1.1 shell-quote: 1.8.3 + lazy-val@1.0.5: {} + leven@3.1.0: {} levn@0.3.0: @@ -16841,6 +18592,11 @@ snapshots: lodash@4.17.23: {} + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + lookup-closest-locale@6.2.0: {} loose-envify@1.4.0: @@ -16851,6 +18607,8 @@ snapshots: dependencies: tslib: 2.8.1 + lowercase-keys@2.0.0: {} + lru-cache@10.4.3: {} lru-cache@11.2.6: {} @@ -16859,6 +18617,10 @@ snapshots: dependencies: yallist: 3.1.1 + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + lru-cache@7.18.3: {} lumen5-web-audio-test-api@0.5.2: {} @@ -16895,6 +18657,22 @@ snapshots: transitivePeerDependencies: - supports-color + make-fetch-happen@14.0.3: + dependencies: + '@npmcli/agent': 3.0.0 + cacache: 19.0.1 + http-cache-semantics: 4.2.0 + minipass: 7.1.3 + minipass-fetch: 4.0.1 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + negotiator: 1.0.0 + proc-log: 5.0.0 + promise-retry: 2.0.1 + ssri: 12.0.0 + transitivePeerDependencies: + - supports-color + makeerror@1.0.12: dependencies: tmpl: 1.0.5 @@ -16903,6 +18681,11 @@ snapshots: dependencies: once: 1.3.3 + matcher@3.0.0: + dependencies: + escape-string-regexp: 4.0.0 + optional: true + matchmediaquery@0.3.1: dependencies: css-mediaquery: 0.1.2 @@ -17002,6 +18785,10 @@ snapshots: mimic-fn@2.1.0: {} + mimic-response@1.0.1: {} + + mimic-response@3.1.0: {} + min-document@2.19.2: dependencies: dom-walk: 0.1.2 @@ -17026,6 +18813,10 @@ snapshots: dependencies: brace-expansion: 1.1.12 + minimatch@5.1.9: + dependencies: + brace-expansion: 2.0.2 + minimatch@9.0.9: dependencies: brace-expansion: 2.0.2 @@ -17044,6 +18835,14 @@ snapshots: optionalDependencies: encoding: 0.1.13 + minipass-fetch@4.0.1: + dependencies: + minipass: 7.1.3 + minipass-sized: 1.0.3 + minizlib: 3.1.0 + optionalDependencies: + encoding: 0.1.13 + minipass-flush@1.0.5: dependencies: minipass: 3.3.6 @@ -17123,6 +18922,8 @@ snapshots: negotiator@0.6.4: {} + negotiator@1.0.0: {} + neo-async@2.6.2: {} netmask@2.0.2: {} @@ -17134,6 +18935,17 @@ snapshots: lower-case: 2.0.2 tslib: 2.8.1 + node-abi@4.28.0: + dependencies: + semver: 7.7.4 + + node-addon-api@1.7.2: + optional: true + + node-api-version@0.2.1: + dependencies: + semver: 7.7.4 + node-domexception@1.0.0: {} node-environment-flags@1.0.6: @@ -17180,6 +18992,21 @@ snapshots: transitivePeerDependencies: - supports-color + node-gyp@11.5.0: + dependencies: + env-paths: 2.2.1 + exponential-backoff: 3.1.3 + graceful-fs: 4.2.11 + make-fetch-happen: 14.0.3 + nopt: 8.1.0 + proc-log: 5.0.0 + semver: 7.7.4 + tar: 7.5.10 + tinyglobby: 0.2.15 + which: 5.0.0 + transitivePeerDependencies: + - supports-color + node-int64@0.4.0: {} node-options-to-argv@1.0.0: {} @@ -17218,6 +19045,10 @@ snapshots: dependencies: abbrev: 2.0.0 + nopt@8.1.0: + dependencies: + abbrev: 3.0.1 + normalize-package-data@2.5.0: dependencies: hosted-git-info: 2.8.9 @@ -17239,6 +19070,8 @@ snapshots: normalize-range@0.1.2: {} + normalize-url@6.1.0: {} + npm-bundled@3.0.1: dependencies: npm-normalize-package-bin: 3.0.1 @@ -17409,6 +19242,18 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 + ora@5.4.1: + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.2 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + os-browserify@0.3.0: {} os-tmpdir@1.0.2: {} @@ -17421,6 +19266,8 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 + p-cancelable@2.1.1: {} + p-filter@2.1.0: dependencies: p-map: 2.1.0 @@ -17463,6 +19310,8 @@ snapshots: dependencies: aggregate-error: 3.1.0 + p-map@7.0.4: {} + p-queue@3.0.0: {} p-retry@6.2.1: @@ -17646,6 +19495,8 @@ snapshots: sha.js: 2.4.12 to-buffer: 1.2.2 + pe-library@0.4.1: {} + pend@1.2.0: {} performance-now@2.1.0: {} @@ -17710,6 +19561,14 @@ snapshots: - supports-color - utf-8-validate + plist@3.1.0: + dependencies: + '@xmldom/xmldom': 0.8.11 + base64-js: 1.5.1 + xmlbuilder: 15.1.1 + + png2icons@2.0.1: {} + pngjs@5.0.0: {} pngjs@7.0.0: {} @@ -17774,6 +19633,11 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + postject@1.0.0-alpha.6: + dependencies: + commander: 9.5.0 + optional: true + prelude-ls@1.1.2: {} prelude-ls@1.2.1: {} @@ -17816,6 +19680,8 @@ snapshots: proc-log@4.2.0: {} + proc-log@5.0.0: {} + process-nextick-args@2.0.1: {} process-on-spawn@1.1.0: @@ -17928,6 +19794,8 @@ snapshots: queue-microtask@1.2.3: {} + quick-lru@5.1.1: {} + quote-stream@1.0.2: dependencies: buffer-equal: 0.0.1 @@ -18163,6 +20031,12 @@ snapshots: dependencies: loose-envify: 1.4.0 + read-binary-file-arch@1.0.6: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + read-cache@1.0.0: dependencies: pify: 2.3.0 @@ -18339,8 +20213,14 @@ snapshots: requires-port@1.0.0: {} + resedit@1.7.2: + dependencies: + pe-library: 0.4.1 + reserved-identifiers@1.2.0: {} + resolve-alpn@1.2.1: {} + resolve-cwd@3.0.0: dependencies: resolve-from: 5.0.0 @@ -18354,6 +20234,8 @@ snapshots: glob: 13.0.6 walk-up-path: 4.0.0 + resolve-pkg-maps@1.0.0: {} + resolve@1.22.11: dependencies: is-core-module: 2.16.1 @@ -18369,6 +20251,10 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + responselike@2.0.1: + dependencies: + lowercase-keys: 2.0.0 + restore-cursor@3.1.0: dependencies: onetime: 5.1.2 @@ -18414,6 +20300,16 @@ snapshots: hash-base: 3.1.2 inherits: 2.0.4 + roarr@2.15.4: + dependencies: + boolean: 3.2.0 + detect-node: 2.1.0 + globalthis: 1.0.4 + json-stringify-safe: 5.0.1 + semver-compare: 1.0.0 + sprintf-js: 1.1.3 + optional: true + rrweb-cssom@0.8.0: {} rst-selector-parser@2.2.3: @@ -18462,6 +20358,10 @@ snapshots: safer-buffer@2.1.2: {} + sanitize-filename@1.6.4: + dependencies: + truncate-utf8-bytes: 1.0.2 + sanitize-html-react@1.13.0: dependencies: htmlparser2: 3.10.1 @@ -18525,6 +20425,9 @@ snapshots: '@peculiar/x509': 1.14.3 pkijs: 3.3.3 + semver-compare@1.0.0: + optional: true + semver@5.5.0: {} semver@5.7.2: {} @@ -18551,6 +20454,11 @@ snapshots: transitivePeerDependencies: - supports-color + serialize-error@7.0.1: + dependencies: + type-fest: 0.13.1 + optional: true + serialize-javascript@7.0.4: {} serve-index@1.9.2: @@ -18612,6 +20520,37 @@ snapshots: shallow-copy@0.0.1: {} + sharp@0.34.5: + dependencies: + '@img/colour': 1.1.0 + detect-libc: 2.1.2 + semver: 7.7.4 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.34.5 + '@img/sharp-darwin-x64': 0.34.5 + '@img/sharp-libvips-darwin-arm64': 1.2.4 + '@img/sharp-libvips-darwin-x64': 1.2.4 + '@img/sharp-libvips-linux-arm': 1.2.4 + '@img/sharp-libvips-linux-arm64': 1.2.4 + '@img/sharp-libvips-linux-ppc64': 1.2.4 + '@img/sharp-libvips-linux-riscv64': 1.2.4 + '@img/sharp-libvips-linux-s390x': 1.2.4 + '@img/sharp-libvips-linux-x64': 1.2.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + '@img/sharp-linux-arm': 0.34.5 + '@img/sharp-linux-arm64': 0.34.5 + '@img/sharp-linux-ppc64': 0.34.5 + '@img/sharp-linux-riscv64': 0.34.5 + '@img/sharp-linux-s390x': 0.34.5 + '@img/sharp-linux-x64': 0.34.5 + '@img/sharp-linuxmusl-arm64': 0.34.5 + '@img/sharp-linuxmusl-x64': 0.34.5 + '@img/sharp-wasm32': 0.34.5 + '@img/sharp-win32-arm64': 0.34.5 + '@img/sharp-win32-ia32': 0.34.5 + '@img/sharp-win32-x64': 0.34.5 + shebang-command@1.2.0: dependencies: shebang-regex: 1.0.0 @@ -18676,6 +20615,10 @@ snapshots: transitivePeerDependencies: - supports-color + simple-update-notifier@2.0.0: + dependencies: + semver: 7.7.4 + slash@2.0.0: {} slash@3.0.0: {} @@ -18686,6 +20629,13 @@ snapshots: astral-regex: 1.0.0 is-fullwidth-code-point: 2.0.0 + slice-ansi@3.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + optional: true + slice-ansi@5.0.0: dependencies: ansi-styles: 6.2.3 @@ -18788,16 +20738,25 @@ snapshots: sprintf-js@1.0.3: {} + sprintf-js@1.1.3: + optional: true + ssri@10.0.6: dependencies: minipass: 7.1.3 + ssri@12.0.0: + dependencies: + minipass: 7.1.3 + stack-utils@2.0.6: dependencies: escape-string-regexp: 2.0.0 startaudiocontext@1.2.1: {} + stat-mode@1.0.0: {} + static-eval@2.1.1: dependencies: escodegen: 2.1.0 @@ -18969,6 +20928,12 @@ snapshots: dependencies: webpack: 5.105.4(webpack-cli@6.0.1) + sumchecker@3.0.1: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + supports-color@2.0.0: {} supports-color@5.5.0: @@ -19090,6 +21055,16 @@ snapshots: transitivePeerDependencies: - supports-color + temp-file@3.4.0: + dependencies: + async-exit-hook: 2.0.1 + fs-extra: 10.1.0 + + temp@0.9.4: + dependencies: + mkdirp: 0.5.6 + rimraf: 2.6.3 + term-size@2.2.1: {} terser-webpack-plugin@5.3.17(webpack@5.105.4): @@ -19148,6 +21123,10 @@ snapshots: dependencies: setimmediate: 1.0.5 + tiny-async-pool@1.3.0: + dependencies: + semver: 5.7.2 + tiny-inflate@1.0.3: {} tiny-worker@2.3.0: @@ -19173,6 +21152,10 @@ snapshots: dependencies: tldts-core: 7.0.25 + tmp-promise@3.0.3: + dependencies: + tmp: 0.2.5 + tmp@0.0.30: dependencies: os-tmpdir: 1.0.2 @@ -19181,6 +21164,8 @@ snapshots: dependencies: os-tmpdir: 1.0.2 + tmp@0.2.5: {} + tmpl@1.0.5: {} to-buffer@1.2.2: @@ -19234,6 +21219,10 @@ snapshots: trivial-deferred@2.0.0: {} + truncate-utf8-bytes@1.0.2: + dependencies: + utf8-byte-length: 1.0.5 + ts-api-utils@1.4.3(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -19354,6 +21343,9 @@ snapshots: type-detect@4.0.8: {} + type-fest@0.13.1: + optional: true + type-fest@0.21.3: {} type-fest@0.8.1: {} @@ -19429,6 +21421,10 @@ snapshots: has-symbols: 1.1.0 which-boxed-primitive: 1.1.1 + undici-types@6.21.0: {} + + undici-types@7.16.0: {} + undici-types@7.18.2: {} undici-types@7.22.0: {} @@ -19455,12 +21451,22 @@ snapshots: dependencies: unique-slug: 4.0.0 + unique-filename@4.0.0: + dependencies: + unique-slug: 5.0.0 + unique-slug@4.0.0: dependencies: imurmurhash: 0.1.4 + unique-slug@5.0.0: + dependencies: + imurmurhash: 0.1.4 + universalify@0.1.2: {} + universalify@2.0.1: {} + unpipe@1.0.0: {} unrs-resolver@1.11.1: @@ -19502,6 +21508,8 @@ snapshots: punycode: 1.4.1 qs: 6.15.0 + utf8-byte-length@1.0.5: {} + util-deprecate@1.0.2: {} util@0.12.5: @@ -19541,6 +21549,13 @@ snapshots: vary@1.1.2: {} + verror@1.10.1: + dependencies: + assert-plus: 1.0.0 + core-util-is: 1.0.2 + extsprintf: 1.4.1 + optional: true + vlq@0.2.3: {} vm-browserify@1.1.2: {} @@ -19570,6 +21585,10 @@ snapshots: dependencies: minimalistic-assert: 1.0.1 + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + web-audio-test-api@0.5.2: {} web-streams-polyfill@3.3.3: {} @@ -19705,7 +21724,7 @@ snapshots: watchpack: 2.5.1 webpack-sources: 3.3.4 optionalDependencies: - webpack-cli: 6.0.1(webpack@5.105.4) + webpack-cli: 6.0.1(webpack-dev-server@5.2.3)(webpack@5.105.4) transitivePeerDependencies: - '@swc/core' - esbuild @@ -19800,6 +21819,10 @@ snapshots: dependencies: isexe: 3.1.5 + which@5.0.0: + dependencies: + isexe: 3.1.5 + widest-line@5.0.0: dependencies: string-width: 7.2.0 @@ -19865,6 +21888,8 @@ snapshots: xmlbuilder@11.0.1: {} + xmlbuilder@15.1.1: {} + xmlchars@2.2.0: {} xtend@4.0.2: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 0d0546ca..950aede5 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,5 +1,6 @@ packages: - packages/* + - app/* catalog: jest: ^30.3.0 @@ -10,6 +11,8 @@ catalog: onlyBuiltDependencies: - chromedriver - core-js + - electron + - electron-winstaller - playwright-chromium - unrs-resolver