diff --git a/.cargo/config.toml b/.cargo/config.toml deleted file mode 100644 index 46adaad..0000000 --- a/.cargo/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[env] -MTP_TYPE_MAPS = { value = "mtp-type-maps/type-maps.yaml", relative = true } diff --git a/.fallowrc.json b/.fallowrc.json index ba50fb5..022e0cc 100644 --- a/.fallowrc.json +++ b/.fallowrc.json @@ -3,7 +3,6 @@ "entry": [ "src/index.{ts,tsx,js,jsx}", "src/main.{ts,tsx,js,jsx}", - "apps/pwa/src/serviceWorker.ts", "apps/tauri/render-version.ts", "packages/**/*.test.ts" ], diff --git a/.forgejo/workflows/dependency-builds.yml b/.forgejo/workflows/dependency-builds.yml index 2ae48fe..95dacb7 100644 --- a/.forgejo/workflows/dependency-builds.yml +++ b/.forgejo/workflows/dependency-builds.yml @@ -4,6 +4,7 @@ on: pull_request: env: + NIX_CONFIG: experimental-features = nix-command flakes FORGEJO_TOKEN: "" GITHUB_TOKEN: "" @@ -13,10 +14,10 @@ jobs: name: Build web runs-on: nixos steps: + - run: nix profile add nixpkgs#nodejs_24 - uses: https://data.forgejo.org/actions/checkout@v4 with: persist-credentials: false - - run: git submodule update --init --recursive - run: nix develop .#electron --command pnpm install --frozen-lockfile - run: nix develop .#electron --command pnpm run build:packages - run: nix develop .#electron --command pnpm run build:web @@ -25,36 +26,24 @@ jobs: if: ${{ github.actor == 'rasensprenger' }} name: Build desktop runs-on: nixos - steps: - - uses: https://data.forgejo.org/actions/checkout@v4 - with: - persist-credentials: false - - run: git submodule update --init --recursive - - run: nix develop .#electron --command pnpm install --frozen-lockfile - - run: nix develop .#electron --command pnpm run build:packages - - run: nix develop .#electron --command pnpm run build:desktop - - native-mtp: - if: ${{ github.actor == 'rasensprenger' }} - name: Test native MTP - runs-on: nixos steps: - run: nix profile add nixpkgs#nodejs_24 - uses: https://data.forgejo.org/actions/checkout@v4 with: persist-credentials: false - - run: git submodule update --init --recursive - - run: nix develop .#electron --command bash -lc 'cd apps/tauri/src-tauri && cargo test' + - run: nix develop .#electron --command pnpm install --frozen-lockfile + - run: nix develop .#electron --command pnpm run build:packages + - run: nix develop .#electron --command pnpm run build:desktop mobile: if: ${{ github.actor == 'rasensprenger' }} name: Build mobile runs-on: nixos steps: + - run: nix profile add nixpkgs#nodejs_24 - uses: https://data.forgejo.org/actions/checkout@v4 with: persist-credentials: false - - run: git submodule update --init --recursive - run: nix develop .#tauri --command pnpm install --frozen-lockfile - run: nix develop .#tauri --command pnpm run build:packages - run: nix develop .#tauri --command pnpm --dir apps/tauri run build:mobile:ci diff --git a/.forgejo/workflows/deploy-dev.yml b/.forgejo/workflows/deploy-dev.yml index 7f59ec1..0d5be50 100644 --- a/.forgejo/workflows/deploy-dev.yml +++ b/.forgejo/workflows/deploy-dev.yml @@ -1,15 +1,20 @@ on: - workflow_dispatch: push: branches: - dev paths-ignore: - flake.nix +env: + NIX_CONFIG: experimental-features = nix-command flakes + jobs: build-web: runs-on: nixos steps: + - name: Install node + run: nix profile add nixpkgs#nodejs_24 + - name: Check out repo uses: https://data.forgejo.org/actions/checkout@v4 @@ -34,6 +39,9 @@ jobs: build-mobile: runs-on: nixos steps: + - name: Install node + run: nix profile add nixpkgs#nodejs_24 + - name: Check out repo uses: https://data.forgejo.org/actions/checkout@v4 @@ -54,6 +62,8 @@ jobs: KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} KEYSTORE_PROPERTIES: ${{ secrets.ANDROID_KEYSTORE_PROPERTIES }} run: | + nix profile add nixpkgs#gnused + set -euo pipefail if [ -z "$KEYSTORE_BASE64" ]; then @@ -118,6 +128,9 @@ jobs: matrix: target: [linux] steps: + - name: Install node + run: nix profile add nixpkgs#nodejs_24 + - name: Check out repo uses: https://data.forgejo.org/actions/checkout@v4 @@ -168,6 +181,9 @@ jobs: runs-on: nixos needs: [build-web, build-mobile, build-desktop] steps: + - name: Install node + run: nix profile add nixpkgs#nodejs_24 + - name: Check out repo uses: https://data.forgejo.org/actions/checkout@v4 with: diff --git a/.forgejo/workflows/deploy-prod.yml b/.forgejo/workflows/deploy-prod.yml index 621a0cd..d85ce27 100644 --- a/.forgejo/workflows/deploy-prod.yml +++ b/.forgejo/workflows/deploy-prod.yml @@ -6,10 +6,16 @@ on: paths-ignore: - flake.nix +env: + NIX_CONFIG: experimental-features = nix-command flakes + jobs: build-web: runs-on: nixos steps: + - name: Install node + run: nix profile add nixpkgs#nodejs_24 + - name: Check out repo uses: https://data.forgejo.org/actions/checkout@v4 @@ -34,6 +40,9 @@ jobs: build-mobile: runs-on: nixos steps: + - name: Install node + run: nix profile add nixpkgs#nodejs_24 + - name: Check out repo uses: https://data.forgejo.org/actions/checkout@v4 @@ -54,6 +63,8 @@ jobs: KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} KEYSTORE_PROPERTIES: ${{ secrets.ANDROID_KEYSTORE_PROPERTIES }} run: | + nix profile add nixpkgs#gnused + set -euo pipefail if [ -z "$KEYSTORE_BASE64" ]; then @@ -118,6 +129,9 @@ jobs: matrix: target: [linux] steps: + - name: Install node + run: nix profile add nixpkgs#nodejs_24 + - name: Check out repo uses: https://data.forgejo.org/actions/checkout@v4 @@ -166,6 +180,9 @@ jobs: runs-on: nixos needs: [build-web, build-mobile, build-desktop] steps: + - name: Install node + run: nix profile add nixpkgs#nodejs_24 + - name: Check out repo uses: https://data.forgejo.org/actions/checkout@v4 @@ -311,3 +328,58 @@ jobs: "$API/repos/$REPO/releases/$release_id" done < "$DELETE_RELEASES" EOF + + - name: Update root flake release hash + env: + TAG: ${{ steps.version.outputs.tag }} + run: | + nix develop .#electron --command bash <<'EOF' + set -eu + + DEB="$(find releases -maxdepth 1 -type f -name 'Tensamin-*-linux-amd64.deb' -print -quit)" + test -n "$DEB" + + HASH="$(node -e 'const fs = require("fs"); const crypto = require("crypto"); const file = process.argv[1]; console.log("sha256-" + crypto.createHash("sha256").update(fs.readFileSync(file)).digest("base64"));' "$DEB")" + export HASH + + node -e ' + const fs = require("fs"); + const version = process.env.TAG; + const hash = process.env.HASH; + let content = fs.readFileSync("flake.nix", "utf8"); + content = content.replace(/version = "[^"]+";/, `version = "${version}";`); + content = content.replace(/x86_64DebHash = "sha256-[^"]+";/, `x86_64DebHash = "${hash}";`); + fs.writeFileSync("flake.nix", content); + ' + + if git diff --quiet -- flake.nix; then + echo "flake.nix already has the current release hash on main." + else + git add flake.nix + git -c user.name="forgejo-actions" -c user.email="forgejo-actions@localhost" commit -m "(qol): update release flake hash" + git push + fi + + git fetch origin dev + git worktree add ../dev-flake-update origin/dev + cd ../dev-flake-update + + node -e ' + const fs = require("fs"); + const version = process.env.TAG; + const hash = process.env.HASH; + let content = fs.readFileSync("flake.nix", "utf8"); + content = content.replace(/version = "[^"]+";/, `version = "${version}";`); + content = content.replace(/x86_64DebHash = "sha256-[^"]+";/, `x86_64DebHash = "${hash}";`); + fs.writeFileSync("flake.nix", content); + ' + + if git diff --quiet -- flake.nix; then + echo "flake.nix already has the current release hash on dev." + exit 0 + fi + + git add flake.nix + git -c user.name="forgejo-actions" -c user.email="forgejo-actions@localhost" commit -m "(qol): update release flake hash" + git push origin HEAD:dev + EOF diff --git a/apps/electron/build/icons/128x128.png b/apps/electron/build/icons/128x128.png new file mode 100644 index 0000000..357e1c2 Binary files /dev/null and b/apps/electron/build/icons/128x128.png differ diff --git a/apps/electron/build/icons/128x128@2x.png b/apps/electron/build/icons/128x128@2x.png new file mode 100644 index 0000000..be55e24 Binary files /dev/null and b/apps/electron/build/icons/128x128@2x.png differ diff --git a/apps/electron/build/icons/32x32.png b/apps/electron/build/icons/32x32.png new file mode 100644 index 0000000..bc4fba4 Binary files /dev/null and b/apps/electron/build/icons/32x32.png differ diff --git a/apps/electron/build/icons/64x64.png b/apps/electron/build/icons/64x64.png new file mode 100644 index 0000000..567f4ad Binary files /dev/null and b/apps/electron/build/icons/64x64.png differ diff --git a/apps/electron/build/icons/icon.icns b/apps/electron/build/icons/icon.icns new file mode 100644 index 0000000..a7f0a1e Binary files /dev/null and b/apps/electron/build/icons/icon.icns differ diff --git a/apps/electron/build/icons/icon.ico b/apps/electron/build/icons/icon.ico new file mode 100644 index 0000000..c5c68f8 Binary files /dev/null and b/apps/electron/build/icons/icon.ico differ diff --git a/apps/electron/build/icons/icon.png b/apps/electron/build/icons/icon.png new file mode 100644 index 0000000..dad3edb Binary files /dev/null and b/apps/electron/build/icons/icon.png differ diff --git a/apps/pwa/package.json b/apps/pwa/package.json deleted file mode 100644 index 39c4ec5..0000000 --- a/apps/pwa/package.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "@tensamin/pwa", - "private": true, - "version": "0.0.0", - "type": "module", - "exports": { - "./vite": "./src/vite.ts", - "./runtime": "./src/runtime.tsx" - }, - "scripts": { - "format": "pnpm exec prettier --write .", - "lint": "eslint src", - "build": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.worker.json --noEmit" - }, - "dependencies": { - "@methanium/ui": "*", - "@tauri-apps/api": "^2.11.1", - "@tensamin/crypto": "workspace:*", - "@tensamin/shared": "workspace:*", - "@tensamin/storage": "workspace:*", - "mtp": "*", - "react": "^19.2.8", - "sonner": "^2.0.7", - "vite-plugin-pwa": "^1.1.0", - "workbox-core": "^7.3.0", - "workbox-precaching": "^7.3.0", - "workbox-routing": "^7.3.0", - "workbox-strategies": "^7.3.0" - }, - "devDependencies": { - "@types/node": "^26.1.2", - "@types/react": "^19.2.18", - "typescript": "~6.0.3", - "vite": "^8.2.1" - } -} diff --git a/apps/pwa/src/runtime.tsx b/apps/pwa/src/runtime.tsx deleted file mode 100644 index a1947eb..0000000 --- a/apps/pwa/src/runtime.tsx +++ /dev/null @@ -1,189 +0,0 @@ -import { useEffect } from "react"; -import { toast } from "sonner"; - -import { setDatabaseEntry } from "@tensamin/shared/indexedDb"; -import { isTauri } from "@tauri-apps/api/core"; - -import "./style.css"; - -const launchedFiles: File[] = []; -const fileListeners = new Set<(file: File) => void>(); - -function emitLaunchedFile(file: File) { - if (fileListeners.size === 0) launchedFiles.push(file); - else for (const listener of fileListeners) listener(file); -} - -export function subscribeTuFileLaunch(listener: (file: File) => void) { - fileListeners.add(listener); - for (const file of launchedFiles.splice(0)) listener(file); - return () => { - fileListeners.delete(listener); - }; -} - -function isInstalledPwa() { - return ( - window.matchMedia("(display-mode: standalone)").matches || - window.matchMedia("(display-mode: window-controls-overlay)").matches || - (navigator as Navigator & { standalone?: boolean }).standalone === true - ); -} - -function applicationServerKey(value: string) { - const normalized = value.replace(/-/g, "+").replace(/_/g, "/"); - const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "="); - return Uint8Array.from(atob(padded), (character) => character.charCodeAt(0)); -} - -async function enablePush() { - if (!("Notification" in window)) - throw new Error("Notifications are not supported by this browser."); - const permission = await Notification.requestPermission(); - if (permission !== "granted") - throw new Error("Notification permission was not granted."); - - const publicKey = import.meta.env.VITE_WEB_PUSH_PUBLIC_KEY; - if ( - !publicKey || - !("serviceWorker" in navigator) || - !("PushManager" in window) - ) { - return; - } - const registration = await navigator.serviceWorker.ready; - const subscription = - (await registration.pushManager.getSubscription()) ?? - (await registration.pushManager.subscribe({ - userVisibleOnly: true, - applicationServerKey: applicationServerKey(publicKey), - })); - await setDatabaseEntry("keys", "push-subscription", subscription.toJSON()); -} - -function InstalledPwaRuntime() { - useEffect(() => { - if ( - !("serviceWorker" in navigator) || - !["http:", "https:"].includes(window.location.protocol) - ) { - return; - } - let reloading = false; - const handleControllerChange = () => { - if (reloading) return; - reloading = true; - // A newly activated service worker must reload the document it controls. - // eslint-disable-next-line tensamin/no-window-location-reload - window.location.reload(); - }; - navigator.serviceWorker.addEventListener( - "controllerchange", - handleControllerChange, - ); - void navigator.serviceWorker - .register( - import.meta.env.DEV ? "/dev-sw.js?dev-sw" : "/serviceWorker.js", - { - type: "module", - }, - ) - .then((registration) => { - const watchWorker = (worker: ServiceWorker) => { - worker.addEventListener("statechange", () => { - if (worker.state !== "installed") return; - if (!navigator.serviceWorker.controller) { - toast.success("Tensamin is ready for offline startup"); - return; - } - toast("A Tensamin update is ready", { - duration: Infinity, - action: { - label: "Update", - onClick: () => worker.postMessage({ type: "SKIP_WAITING" }), - }, - }); - }); - }; - if (registration.installing) watchWorker(registration.installing); - registration.addEventListener("updatefound", () => { - if (registration.installing) watchWorker(registration.installing); - }); - }) - .catch((error: unknown) => { - console.error("Failed to register the Tensamin service worker", error); - }); - return () => { - navigator.serviceWorker.removeEventListener( - "controllerchange", - handleControllerChange, - ); - }; - }, []); - - useEffect(() => { - const launchQueue = ( - window as Window & { - launchQueue?: { - setConsumer: ( - consumer: (params: { - files?: Array<{ getFile: () => Promise }>; - }) => void, - ) => void; - }; - } - ).launchQueue; - launchQueue?.setConsumer((params) => { - for (const handle of params.files ?? []) { - void handle.getFile().then(emitLaunchedFile); - } - }); - }, []); - - useEffect(() => { - if ( - !("Notification" in window) || - Notification.permission !== "default" || - localStorage.getItem("pwa-push-hint") - ) { - return; - } - localStorage.setItem("pwa-push-hint", "shown"); - toast("Enable message notifications", { - duration: Infinity, - action: { - label: "Enable", - onClick: () => { - void enablePush() - .then(() => toast.success("Notifications enabled")) - .catch((error: unknown) => - toast.error( - error instanceof Error - ? error.message - : "Could not enable notifications", - ), - ); - }, - }, - }); - }, []); - - useEffect(() => { - if ( - "Notification" in window && - Notification.permission === "granted" && - import.meta.env.VITE_WEB_PUSH_PUBLIC_KEY - ) { - void enablePush().catch((error: unknown) => { - console.error("Failed to refresh the Web Push subscription", error); - }); - } - }, []); - - return null; -} - -export default function PwaRuntime() { - if (isTauri() || !isInstalledPwa()) return null; - return ; -} diff --git a/apps/pwa/src/serviceWorker.ts b/apps/pwa/src/serviceWorker.ts deleted file mode 100644 index 554ceeb..0000000 --- a/apps/pwa/src/serviceWorker.ts +++ /dev/null @@ -1,161 +0,0 @@ -/// - -import { base64ToBytes } from "mtp"; -import { clientsClaim } from "workbox-core"; -import { cleanupOutdatedCaches, precacheAndRoute } from "workbox-precaching"; -import { NavigationRoute, registerRoute } from "workbox-routing"; -import { createHandlerBoundToURL } from "workbox-precaching"; -import { CacheFirst } from "workbox-strategies"; - -import { decryptChatText, unwrapChatSecret } from "@tensamin/crypto/chatSecret"; -import { loadSecureBrowserValue } from "@tensamin/storage/browserSecure"; - -declare let self: ServiceWorkerGlobalScope; - -type PushPayload = { - version: 1; - senderId: number; - sender: string; - avatar?: string; - message: { content: string }; - secret: { - chatId: string; - secretId: string; - version: number; - encryptedSecret: string; - kemCiphertext: string; - wrappingScheme: string; - }; -}; - -function isPushPayload(value: unknown): value is PushPayload { - if (!value || typeof value !== "object") return false; - const payload = value as Partial; - const message = payload.message as - Partial | undefined; - const secret = payload.secret as Partial | undefined; - const stringValues = [ - payload.sender, - message?.content, - secret?.chatId, - secret?.secretId, - secret?.encryptedSecret, - secret?.kemCiphertext, - secret?.wrappingScheme, - ]; - return ( - payload.version === 1 && - typeof payload.senderId === "number" && - Number.isSafeInteger(payload.senderId) && - payload.senderId > 0 && - typeof secret?.version === "number" && - stringValues.every((item) => typeof item === "string") - ); -} - -async function decryptPush(payload: PushPayload) { - const keyring = await loadSecureBrowserValue("mtp_keyring"); - if (!keyring) throw new Error("MTP credentials are unavailable."); - const chatSecret = await unwrapChatSecret({ - encryptedSecret: base64ToBytes(payload.secret.encryptedSecret), - kemCiphertext: base64ToBytes(payload.secret.kemCiphertext), - keyring, - chatId: payload.secret.chatId, - secretId: payload.secret.secretId, - version: payload.secret.version, - wrappingScheme: payload.secret.wrappingScheme, - }); - try { - return await decryptChatText(chatSecret, payload.message.content); - } finally { - chatSecret.fill(0); - } -} - -clientsClaim(); -cleanupOutdatedCaches(); -const precacheManifest = self.__WB_MANIFEST; -precacheAndRoute(precacheManifest); - -if ( - precacheManifest.some((entry) => - (typeof entry === "string" ? entry : entry.url).endsWith("index.html"), - ) -) { - registerRoute( - new NavigationRoute(createHandlerBoundToURL("index.html"), { - denylist: [/^\/api\//], - }), - ); -} -registerRoute( - ({ request, url }) => - url.origin === self.location.origin && - ["font", "image", "style"].includes(request.destination), - new CacheFirst({ cacheName: "tensamin-static-v1" }), -); - -self.addEventListener("push", (event) => { - event.waitUntil( - (async () => { - let payload: PushPayload | undefined; - try { - const value = event.data?.json() as unknown; - if (isPushPayload(value)) payload = value; - } catch { - // The generic notification below is safe for malformed payloads. - } - - let body = "Open Tensamin to view the encrypted message."; - if (payload) { - try { - body = await decryptPush(payload); - } catch { - // Do not leak credential or decryption failures in the notification. - } - } - - await self.registration.showNotification(payload?.sender ?? "Tensamin", { - body, - icon: payload?.avatar || "./icons/icon-192.png", - badge: "./icons/notification-badge.png", - tag: payload ? `message-${payload.senderId}` : "message", - data: { url: payload ? `/chat?id=${payload.senderId}` : "/" }, - }); - - const navigatorWithBadge = self.navigator as WorkerNavigator & { - setAppBadge?: (contents?: number) => Promise; - }; - await navigatorWithBadge.setAppBadge?.().catch(() => undefined); - })(), - ); -}); - -self.addEventListener("notificationclick", (event) => { - event.notification.close(); - event.waitUntil( - (async () => { - const target = new URL( - String( - (event.notification.data as { url?: string } | undefined)?.url ?? "/", - ), - self.location.origin, - ); - const windows = await self.clients.matchAll({ - type: "window", - includeUncontrolled: true, - }); - for (const client of windows) { - if ("navigate" in client) await client.navigate(target.href); - return client.focus(); - } - return self.clients.openWindow(target.href); - })(), - ); -}); - -self.addEventListener("message", (event) => { - if ((event.data as { type?: string } | undefined)?.type === "SKIP_WAITING") { - void self.skipWaiting(); - } -}); diff --git a/apps/pwa/src/style.css b/apps/pwa/src/style.css deleted file mode 100644 index 213d773..0000000 --- a/apps/pwa/src/style.css +++ /dev/null @@ -1,18 +0,0 @@ -@media (display-mode: standalone), (display-mode: fullscreen) { - [data-pwa-root] { - padding-top: env(safe-area-inset-top, 0px); - padding-right: env(safe-area-inset-right, 0px); - padding-left: env(safe-area-inset-left, 0px); - } -} - -@media (display-mode: window-controls-overlay) and (min-width: 768px) { - [data-pwa-navbar] { - min-height: env(titlebar-area-height, 3.375rem); - padding-left: max(1px, env(titlebar-area-x, 0px)); - padding-right: max( - 0px, - calc(100vw - env(titlebar-area-x, 0px) - env(titlebar-area-width, 100vw)) - ); - } -} diff --git a/apps/pwa/src/vite.ts b/apps/pwa/src/vite.ts deleted file mode 100644 index 962dce1..0000000 --- a/apps/pwa/src/vite.ts +++ /dev/null @@ -1,218 +0,0 @@ -import { readFileSync } from "node:fs"; -import { dirname, resolve } from "node:path"; -import { fileURLToPath } from "node:url"; - -import type { Plugin } from "vite"; -import { VitePWA } from "vite-plugin-pwa"; - -const pwaDirectory = resolve(dirname(fileURLToPath(import.meta.url)), ".."); -const tauriIcons = resolve(pwaDirectory, "../tauri/src-tauri/icons"); -const androidResources = resolve( - pwaDirectory, - "../tauri/src-tauri/gen/android/app/src/main/res", -); - -function emitIcons(): Plugin { - const icons = [ - { - fileName: "icons/icon-180.png", - source: resolve(tauriIcons, "ios/AppIcon-60x60@3x.png"), - }, - { - fileName: "icons/icon-192.png", - source: resolve(androidResources, "mipmap-xxxhdpi/ic_launcher.png"), - }, - { - fileName: "icons/icon-96.png", - source: resolve(androidResources, "mipmap-xhdpi/ic_launcher.png"), - }, - { - fileName: "icons/icon-512.png", - source: resolve(tauriIcons, "icon.png"), - }, - { - fileName: "icons/icon-maskable-512.png", - source: resolve(tauriIcons, "icon.png"), - }, - { - fileName: "icons/icon-monochrome-432.png", - source: resolve( - androidResources, - "mipmap-xxxhdpi/ic_launcher_monochrome.png", - ), - }, - { - fileName: "icons/notification-badge.png", - source: resolve(androidResources, "drawable/ic_notification_small.png"), - }, - ]; - - return { - name: "tensamin-pwa-icons", - configureServer(server) { - server.middlewares.use((request, response, next) => { - const pathname = request.url - ? new URL(request.url, "http://localhost").pathname.slice(1) - : ""; - const icon = icons.find(({ fileName }) => fileName === pathname); - if (!icon) { - next(); - return; - } - response.statusCode = 200; - response.setHeader("Content-Type", "image/png"); - response.setHeader("Cache-Control", "no-cache"); - response.end(readFileSync(icon.source)); - }); - }, - generateBundle() { - for (const icon of icons) { - this.emitFile({ - type: "asset", - fileName: icon.fileName, - source: readFileSync(icon.source), - }); - } - }, - transformIndexHtml: { - order: "post", - handler() { - return [ - { - tag: "link", - attrs: { - rel: "apple-touch-icon", - sizes: "180x180", - href: "./icons/icon-180.png", - }, - injectTo: "head", - }, - { - tag: "meta", - attrs: { name: "apple-mobile-web-app-capable", content: "yes" }, - injectTo: "head", - }, - { - tag: "meta", - attrs: { - name: "apple-mobile-web-app-status-bar-style", - content: "black-translucent", - }, - injectTo: "head", - }, - { - tag: "meta", - attrs: { - name: "apple-mobile-web-app-title", - content: "Tensamin", - }, - injectTo: "head", - }, - { - tag: "meta", - attrs: { name: "theme-color", content: "#006a67" }, - injectTo: "head", - }, - ]; - }, - }, - }; -} - -export function tensaminPwa(): Plugin[] { - return [ - emitIcons(), - ...VitePWA({ - strategies: "injectManifest", - srcDir: resolve(pwaDirectory, "src"), - filename: "serviceWorker.ts", - injectRegister: null, - registerType: "prompt", - buildBase: "/", - manifestFilename: "manifest.json", - includeAssets: ["favicon.ico", "icons/*.png"], - manifest: { - id: "/", - name: "Tensamin", - short_name: "Tensamin", - description: "Private messaging and calls with Tensamin.", - start_url: "/", - scope: "/", - display: "standalone", - display_override: ["window-controls-overlay", "standalone"], - background_color: "#001f1e", - theme_color: "#006a67", - categories: ["social", "communication"], - orientation: "any", - launch_handler: { client_mode: "focus-existing" }, - icons: [ - { - src: "icons/icon-192.png", - sizes: "192x192", - type: "image/png", - purpose: "any", - }, - { - src: "icons/icon-512.png", - sizes: "512x512", - type: "image/png", - purpose: "any", - }, - { - src: "icons/icon-maskable-512.png", - sizes: "512x512", - type: "image/png", - purpose: "maskable", - }, - { - src: "icons/icon-monochrome-432.png", - sizes: "432x432", - type: "image/png", - purpose: "monochrome", - }, - ], - shortcuts: [ - { - name: "Chats", - short_name: "Chats", - url: "/", - icons: [ - { - src: "icons/icon-96.png", - sizes: "96x96", - type: "image/png", - }, - ], - }, - { - name: "Settings", - short_name: "Settings", - url: "/settings", - icons: [ - { - src: "icons/icon-96.png", - sizes: "96x96", - type: "image/png", - }, - ], - }, - ], - file_handlers: [ - { - action: "/login", - accept: { "application/x-tensamin-user": [".tu"] }, - }, - ], - }, - injectManifest: { - globPatterns: ["**/*.{js,css,html,ico,png,svg,woff2,wasm,mp3,wav}"], - globIgnores: ["assets/v2/**"], - maximumFileSizeToCacheInBytes: 15 * 1024 * 1024, - }, - devOptions: { - enabled: true, - type: "module", - }, - }), - ]; -} diff --git a/apps/pwa/todo.md b/apps/pwa/todo.md deleted file mode 100644 index b5b2055..0000000 --- a/apps/pwa/todo.md +++ /dev/null @@ -1,33 +0,0 @@ -# Web Push Backend TODO - -The client can subscribe and decrypt version 1 push payloads, but reliable delivery requires backend support. - -- Generate and securely store a VAPID key pair. Expose only the public key to the web build as `VITE_WEB_PUSH_PUBLIC_KEY`. -- Add authenticated MTP requests for registering, replacing, and deleting a browser `PushSubscription` per user and installation. -- Persist the endpoint, `p256dh`, `auth`, expiration time, stable installation ID, and last-seen time. -- Remove subscriptions when a push service returns HTTP 404 or 410 and rate-limit registrations per user. -- Send pushes when an encrypted live message cannot be delivered to an active browser client. Define duplicate suppression for clients that receive both MTP and Web Push. -- Keep the JSON payload within push-provider limits and use this version 1 shape: - -```json -{ - "version": 1, - "senderId": 123, - "sender": "Display name", - "avatar": "https://optional.example/avatar", - "message": { "content": "base64 encrypted message content" }, - "secret": { - "chatId": "123:456", - "secretId": "chat:123:456:main", - "version": 1, - "encryptedSecret": "base64 wrapped chat secret", - "kemCiphertext": "base64 KEM ciphertext", - "wrappingScheme": "mtp-chat-secret-kem-chacha20poly1305-hkdf-sha256-v1" - } -} -``` - -- Ensure the wrapped secret is intended for the receiving user's MTP keyring. The server must never receive plaintext message content or plaintext chat secrets. -- Decide how edits, deletions, reactions, calls, read states, and per-chat notification cancellation map to push events. -- Add subscription rotation handling and unregister subscriptions when a user logs out or clears application data. -- Configure production HTTPS, SPA route fallback, `application/manifest+json` for `manifest.json`, and `Cache-Control: no-cache` for the service worker. diff --git a/apps/pwa/tsconfig.json b/apps/pwa/tsconfig.json deleted file mode 100644 index 1e7cfde..0000000 --- a/apps/pwa/tsconfig.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ES2022", "DOM", "DOM.Iterable"], - "types": ["vite/client", "vite-plugin-pwa/client", "node"], - "skipLibCheck": true, - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "moduleDetection": "force", - "noEmit": true, - "jsx": "react-jsx", - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "erasableSyntaxOnly": true, - "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true - }, - "include": ["src/runtime.tsx", "src/vite.ts"] -} diff --git a/apps/pwa/tsconfig.worker.json b/apps/pwa/tsconfig.worker.json deleted file mode 100644 index a478894..0000000 --- a/apps/pwa/tsconfig.worker.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "lib": ["ES2022", "WebWorker"], - "types": ["vite-plugin-pwa/client"], - "skipLibCheck": true, - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "moduleDetection": "force", - "noEmit": true, - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "erasableSyntaxOnly": true, - "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true - }, - "include": ["src/serviceWorker.ts"] -} diff --git a/apps/tauri/.cargo/config.toml b/apps/tauri/.cargo/config.toml new file mode 100644 index 0000000..161678f --- /dev/null +++ b/apps/tauri/.cargo/config.toml @@ -0,0 +1,2 @@ +[env] +MTP_TYPE_MAPS = { value = "../../mtp-type-maps/type-maps.yaml", relative = true } diff --git a/apps/tauri/package.json b/apps/tauri/package.json index 36937be..7b7e5a7 100644 --- a/apps/tauri/package.json +++ b/apps/tauri/package.json @@ -7,10 +7,14 @@ "./deeplinkHandler": { "types": "./src/deeplinkHandler.tsx", "default": "./src/deeplinkHandler.tsx" + }, + "./qrCodeScanner": { + "types": "./src/qrCodeScanner.tsx", + "default": "./src/qrCodeScanner.tsx" } }, "scripts": { - "dev:mobile:raw": "adb reverse tcp:3000 tcp:3000 && tauri android dev --host ${TAURI_DEV_HOST:-127.0.0.1}", + "dev:mobile:raw": "tauri android dev --host ${TAURI_DEV_HOST:-127.0.0.1}", "start-adb:mobile:raw": "adb devices", "build:mobile:raw": "tauri android build", "build:mobile:ci": "node render-version.ts && trap 'node render-version.ts --unrender' EXIT && tauri android build --debug", @@ -24,6 +28,7 @@ "dependencies": { "@methanium/ui": "*", "@tauri-apps/api": "^2.11.1", + "@tauri-apps/plugin-barcode-scanner": "~2.4.5", "@tauri-apps/plugin-deep-link": "~2.4.9", "@tensamin/shared": "workspace:*", "react": "^19.2.8", diff --git a/apps/tauri/src-tauri/Cargo.lock b/apps/tauri/src-tauri/Cargo.lock index d404d61..9171fc5 100644 --- a/apps/tauri/src-tauri/Cargo.lock +++ b/apps/tauri/src-tauri/Cargo.lock @@ -560,6 +560,17 @@ dependencies = [ "uuid", ] +[[package]] +name = "cfb" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a347dcabdae9c31b0825fd6a8bed285ec9c2acb89c47827126d52fa4f59cece3" +dependencies = [ + "fnv", + "uuid", + "web-time", +] + [[package]] name = "cfg-expr" version = "0.15.8" @@ -674,6 +685,12 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "const-oid" version = "0.10.2" @@ -826,7 +843,20 @@ version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dae61cf9c0abb83bd659dab65b7e4e38d8236824c85f0f804f173567bda257d2" dependencies = [ - "cssparser-macros", + "cssparser-macros 0.6.1", + "dtoa-short", + "itoa", + "phf", + "smallvec", +] + +[[package]] +name = "cssparser" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9cdaae01d5ed7882b04d795e7f752f46ff52d2fa3b50a20d28c464510bba98" +dependencies = [ + "cssparser-macros 0.7.0", "dtoa-short", "itoa", "phf", @@ -843,6 +873,16 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "cssparser-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a2a99df6e410a8ff4245aa2006499ea662245f967cc7c0a38c83ef8eb44dbf" +dependencies = [ + "quote", + "syn 2.0.119", +] + [[package]] name = "ctor" version = "0.8.0" @@ -883,6 +923,7 @@ dependencies = [ "cfg-if", "cpufeatures 0.2.17", "curve25519-dalek-derive", + "digest 0.10.7", "fiat-crypto 0.2.9", "rustc_version", "subtle", @@ -967,14 +1008,25 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid 0.9.6", + "pem-rfc7468 0.7.0", + "zeroize", +] + [[package]] name = "der" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a69dedd701da44b0536442edf09c81a64b0ab97a7a4a5e3d1971f00027cbc63d" dependencies = [ - "const-oid", - "pem-rfc7468", + "const-oid 0.10.2", + "pem-rfc7468 1.0.0", "zeroize", ] @@ -1039,7 +1091,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ "block-buffer 0.12.1", - "const-oid", + "const-oid 0.10.2", "crypto-common 0.2.2", "ctutils", ] @@ -1127,11 +1179,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521e380c0c8afb8d9a1e83a1822ee03556fc3e3e7dbc1fd30be14e37f9cb3f89" dependencies = [ "bit-set", - "cssparser", + "cssparser 0.36.0", "foldhash", - "html5ever", + "html5ever 0.38.0", "precomputed-hash", - "selectors", + "selectors 0.36.1", + "tendril", +] + +[[package]] +name = "dom_query" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fac5fca71e65e94cc718a6e2af65d6e0f9c6027751c2aa562fbb5087fda639bc" +dependencies = [ + "bit-set", + "cssparser 0.37.0", + "foldhash", + "html5ever 0.39.0", + "precomputed-hash", + "selectors 0.38.0", "tendril", ] @@ -1186,14 +1253,38 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8 0.10.2", + "signature 2.2.0", +] + [[package]] name = "ed25519" version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29fcf32e6c73d1079f83ab4d782de2d81620346a5f38c6237a86a22f8368980a" dependencies = [ - "pkcs8", - "signature", + "pkcs8 0.11.0", + "signature 3.0.0", +] + +[[package]] +name = "ed25519-dalek" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" +dependencies = [ + "curve25519-dalek 4.1.3", + "ed25519 2.2.3", + "serde", + "sha2 0.10.9", + "subtle", + "zeroize", ] [[package]] @@ -1203,10 +1294,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ebaa1a2bf1290ab3bfe5a7b771d050ebffab2711c19a81691c683a5144a25de" dependencies = [ "curve25519-dalek 5.0.0", - "ed25519", + "ed25519 3.0.0", "serde", "sha2 0.11.0", - "signature", + "signature 3.0.0", "subtle", "zeroize", ] @@ -1292,7 +1383,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -1982,7 +2073,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1054432bae2f14e0061e33d23402fbaa67a921d319d56adc6bcf887ddad1cbc2" dependencies = [ "log", - "markup5ever", + "markup5ever 0.38.0", +] + +[[package]] +name = "html5ever" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a1761807faccc9a19e86944bbf40610014066306f96edcdedc2fb714bcb7b8" +dependencies = [ + "log", + "markup5ever 0.39.0", ] [[package]] @@ -2081,6 +2182,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", + "webpki-roots", ] [[package]] @@ -2118,7 +2220,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core", + "windows-core 0.62.2", ] [[package]] @@ -2278,7 +2380,16 @@ version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" dependencies = [ - "cfb", + "cfb 0.7.3", +] + +[[package]] +name = "infer" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4200d433cbd5178df7797c9c2e75b348b728e39631cf14520d1e2fc424201f4" +dependencies = [ + "cfb 0.14.0", ] [[package]] @@ -2641,6 +2752,17 @@ dependencies = [ "web_atoms", ] +[[package]] +name = "markup5ever" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7122d987ec5f704ee56f6e5b41a7d93722e9aae27ae07cafa4036c4d3f9757de" +dependencies = [ + "log", + "tendril", + "web_atoms", +] + [[package]] name = "memchr" version = "2.8.3" @@ -2695,14 +2817,14 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "add6b9d92e496f16f4526d68ff29da1483aba4b119baeab8bed3b9e3544a6f3d" dependencies = [ - "const-oid", + "const-oid 0.10.2", "crypto-common 0.2.2", "ctutils", "hybrid-array", "module-lattice", - "pkcs8", + "pkcs8 0.11.0", "shake", - "signature", + "signature 3.0.0", ] [[package]] @@ -2744,50 +2866,72 @@ dependencies = [ [[package]] name = "mtp" -version = "0.3.0" -source = "git+https://git.methanium.net/Methanium/mtp.git?rev=a5c8d4f0c898c78351e9d54124886c86e789a22a#a5c8d4f0c898c78351e9d54124886c86e789a22a" +version = "0.2.0" +source = "git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22#7182272e3edb0079d7b74b45b2f62a298d2fee22" dependencies = [ "mtp-client", - "mtp-codec", - "mtp-common", - "mtp-crypto", + "mtp-codec 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", + "mtp-common 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", + "mtp-crypto 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", "mtp-host", - "mtp-transport", - "mtp-type-map", + "mtp-transport 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", + "mtp-type-map 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", "mtp-webserver", ] [[package]] name = "mtp-client" -version = "0.3.0" -source = "git+https://git.methanium.net/Methanium/mtp.git?rev=a5c8d4f0c898c78351e9d54124886c86e789a22a#a5c8d4f0c898c78351e9d54124886c86e789a22a" +version = "0.2.0" +source = "git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22#7182272e3edb0079d7b74b45b2f62a298d2fee22" dependencies = [ - "mtp-codec", - "mtp-common", - "mtp-crypto", - "mtp-transport", + "mtp-codec 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", + "mtp-common 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", + "mtp-crypto 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", + "mtp-transport 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", "rand 0.10.2", "tokio", ] [[package]] name = "mtp-codec" -version = "0.3.0" -source = "git+https://git.methanium.net/Methanium/mtp.git?rev=a5c8d4f0c898c78351e9d54124886c86e789a22a#a5c8d4f0c898c78351e9d54124886c86e789a22a" +version = "0.2.0" +source = "git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22#7182272e3edb0079d7b74b45b2f62a298d2fee22" dependencies = [ "base64 0.23.1", "byteorder", - "mtp-common", - "mtp-crypto", - "mtp-type-map", + "mtp-common 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", + "mtp-crypto 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", + "mtp-type-map 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", + "rand 0.10.2", +] + +[[package]] +name = "mtp-codec" +version = "0.2.0" +source = "git+https://git.methanium.net/methanium/mtp.git?rev=b067614a684eb1856bc5db7b3fd82148c036ce6b#b067614a684eb1856bc5db7b3fd82148c036ce6b" +dependencies = [ + "base64 0.23.1", + "byteorder", + "mtp-common 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=b067614a684eb1856bc5db7b3fd82148c036ce6b)", + "mtp-type-map 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=b067614a684eb1856bc5db7b3fd82148c036ce6b)", "rand 0.10.2", - "thiserror 2.0.19", ] [[package]] name = "mtp-common" -version = "0.3.0" -source = "git+https://git.methanium.net/Methanium/mtp.git?rev=a5c8d4f0c898c78351e9d54124886c86e789a22a#a5c8d4f0c898c78351e9d54124886c86e789a22a" +version = "0.2.0" +source = "git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22#7182272e3edb0079d7b74b45b2f62a298d2fee22" +dependencies = [ + "quinn", + "rustls", + "thiserror 2.0.19", + "wtransport", +] + +[[package]] +name = "mtp-common" +version = "0.2.0" +source = "git+https://git.methanium.net/methanium/mtp.git?rev=b067614a684eb1856bc5db7b3fd82148c036ce6b#b067614a684eb1856bc5db7b3fd82148c036ce6b" dependencies = [ "quinn", "rustls", @@ -2797,18 +2941,18 @@ dependencies = [ [[package]] name = "mtp-crypto" -version = "0.3.0" -source = "git+https://git.methanium.net/Methanium/mtp.git?rev=a5c8d4f0c898c78351e9d54124886c86e789a22a#a5c8d4f0c898c78351e9d54124886c86e789a22a" +version = "0.2.0" +source = "git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22#7182272e3edb0079d7b74b45b2f62a298d2fee22" dependencies = [ - "base64 0.22.1", + "base64 0.23.1", "chacha20poly1305", - "ed25519-dalek", + "ed25519-dalek 2.2.0", "getrandom 0.4.3", "hkdf", "ml-dsa", "mlkem-tls", "rand 0.10.2", - "rand_core 0.6.4", + "rand_core 0.10.1", "rustls", "serde", "sha2 0.11.0", @@ -2818,31 +2962,67 @@ dependencies = [ ] [[package]] -name = "mtp-host" -version = "0.3.0" -source = "git+https://git.methanium.net/Methanium/mtp.git?rev=a5c8d4f0c898c78351e9d54124886c86e789a22a#a5c8d4f0c898c78351e9d54124886c86e789a22a" +name = "mtp-crypto" +version = "0.2.0" +source = "git+https://git.methanium.net/methanium/mtp.git?rev=b067614a684eb1856bc5db7b3fd82148c036ce6b#b067614a684eb1856bc5db7b3fd82148c036ce6b" dependencies = [ - "mtp-codec", - "mtp-common", - "mtp-crypto", - "mtp-transport", + "base64 0.23.1", + "chacha20poly1305", + "ed25519-dalek 3.0.0", + "getrandom 0.4.3", + "hkdf", + "ml-dsa", "rand 0.10.2", + "rand_core 0.10.1", + "rustls", + "sha2 0.11.0", "thiserror 2.0.19", "tokio", + "zeroize", +] + +[[package]] +name = "mtp-host" +version = "0.2.0" +source = "git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22#7182272e3edb0079d7b74b45b2f62a298d2fee22" +dependencies = [ + "mtp-codec 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", + "mtp-common 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", + "mtp-crypto 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", + "mtp-transport 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", + "rand 0.10.2", + "tokio", "tracing", "wtransport", ] [[package]] name = "mtp-transport" -version = "0.3.0" -source = "git+https://git.methanium.net/Methanium/mtp.git?rev=a5c8d4f0c898c78351e9d54124886c86e789a22a#a5c8d4f0c898c78351e9d54124886c86e789a22a" +version = "0.2.0" +source = "git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22#7182272e3edb0079d7b74b45b2f62a298d2fee22" dependencies = [ "async-trait", - "mtp-codec", - "mtp-common", - "mtp-crypto", - "rand 0.10.2", + "mtp-codec 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", + "mtp-common 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", + "mtp-crypto 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", + "rcgen", + "rustls", + "rustls-native-certs", + "sha2 0.11.0", + "tokio", + "tracing", + "wtransport", +] + +[[package]] +name = "mtp-transport" +version = "0.2.0" +source = "git+https://git.methanium.net/methanium/mtp.git?rev=b067614a684eb1856bc5db7b3fd82148c036ce6b#b067614a684eb1856bc5db7b3fd82148c036ce6b" +dependencies = [ + "async-trait", + "mtp-codec 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=b067614a684eb1856bc5db7b3fd82148c036ce6b)", + "mtp-common 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=b067614a684eb1856bc5db7b3fd82148c036ce6b)", + "mtp-crypto 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=b067614a684eb1856bc5db7b3fd82148c036ce6b)", "rcgen", "rustls", "rustls-native-certs", @@ -2850,13 +3030,21 @@ dependencies = [ "tokio", "tracing", "wtransport", - "zeroize", ] [[package]] name = "mtp-type-map" -version = "0.3.0" -source = "git+https://git.methanium.net/Methanium/mtp.git?rev=a5c8d4f0c898c78351e9d54124886c86e789a22a#a5c8d4f0c898c78351e9d54124886c86e789a22a" +version = "0.2.0" +source = "git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22#7182272e3edb0079d7b74b45b2f62a298d2fee22" +dependencies = [ + "serde", + "serde_yaml", +] + +[[package]] +name = "mtp-type-map" +version = "0.2.0" +source = "git+https://git.methanium.net/methanium/mtp.git?rev=b067614a684eb1856bc5db7b3fd82148c036ce6b#b067614a684eb1856bc5db7b3fd82148c036ce6b" dependencies = [ "serde", "serde_yaml", @@ -2864,8 +3052,8 @@ dependencies = [ [[package]] name = "mtp-webserver" -version = "0.3.0" -source = "git+https://git.methanium.net/Methanium/mtp.git?rev=a5c8d4f0c898c78351e9d54124886c86e789a22a#a5c8d4f0c898c78351e9d54124886c86e789a22a" +version = "0.2.0" +source = "git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22#7182272e3edb0079d7b74b45b2f62a298d2fee22" dependencies = [ "async-trait", "bytes", @@ -2876,12 +3064,13 @@ dependencies = [ "http-body-util", "hyper", "hyper-util", - "mtp-codec", - "mtp-common", - "mtp-crypto", + "mtp-codec 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", + "mtp-common 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", + "mtp-crypto 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", "mtp-host", - "mtp-transport", + "mtp-transport 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=7182272e3edb0079d7b74b45b2f62a298d2fee22)", "quinn", + "rand 0.10.2", "rustls", "thiserror 2.0.19", "tokio", @@ -3383,6 +3572,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "pem-rfc7468" version = "1.0.0" @@ -3468,14 +3666,24 @@ dependencies = [ "futures-io", ] +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der 0.7.10", + "spki 0.7.3", +] + [[package]] name = "pkcs8" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7" dependencies = [ - "der", - "spki", + "der 0.8.1", + "spki 0.8.0", ] [[package]] @@ -3712,7 +3920,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3892,14 +4100,13 @@ checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "reqwest" -version = "0.13.4" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64 0.22.1", "bytes", "futures-core", - "futures-util", "http", "http-body", "http-body-util", @@ -3913,12 +4120,45 @@ dependencies = [ "quinn", "rustls", "rustls-pki-types", - "rustls-platform-verifier", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", +] + +[[package]] +name = "reqwest" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", "serde", "serde_json", "sync_wrapper", "tokio", - "tokio-rustls", "tokio-util", "tower", "tower-http", @@ -3988,7 +4228,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -4047,7 +4287,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -4200,7 +4440,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c" dependencies = [ "bitflags 2.13.1", - "cssparser", + "cssparser 0.36.0", + "derive_more", + "log", + "new_debug_unreachable", + "phf", + "phf_codegen", + "precomputed-hash", + "rustc-hash", + "servo_arc", + "smallvec", +] + +[[package]] +name = "selectors" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8adfa1c298912827b8a28b223b3b874357397ae706e6190acd9bf28cee99114d" +dependencies = [ + "bitflags 2.13.1", + "cssparser 0.37.0", "derive_more", "log", "new_debug_unreachable", @@ -4329,6 +4588,18 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "serde_with" version = "3.21.0" @@ -4464,6 +4735,15 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "rand_core 0.6.4", +] + [[package]] name = "signature" version = "3.0.0" @@ -4572,6 +4852,16 @@ dependencies = [ "system-deps", ] +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der 0.7.10", +] + [[package]] name = "spki" version = "0.8.0" @@ -4579,7 +4869,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d9efca8738c78ee9484207732f728b1ef517bbb1833d6fc0879ca898a522f6f" dependencies = [ "base64ct", - "der", + "der 0.8.1", ] [[package]] @@ -4741,7 +5031,7 @@ dependencies = [ "unicode-segmentation", "url", "windows", - "windows-core", + "windows-core 0.61.2", "windows-version", "x11-dl", ] @@ -4792,13 +5082,13 @@ dependencies = [ "percent-encoding", "plist", "raw-window-handle", - "reqwest", + "reqwest 0.13.4", "serde", "serde_json", "serde_repr", "serialize-to-javascript", "swift-rs", - "tauri-build", + "tauri-build 2.6.3 (git+https://github.com/tauri-apps/tauri?rev=4af26a3f7f8b692d62cca549bbacd93f5ce90b41)", "tauri-macros", "tauri-runtime", "tauri-runtime-wry", @@ -4833,6 +5123,26 @@ dependencies = [ "walkdir", ] +[[package]] +name = "tauri-build" +version = "2.6.3" +source = "git+https://github.com/tauri-apps/tauri?rev=c0bd0d5a61eedba5c4783add24455c5028c6f390#c0bd0d5a61eedba5c4783add24455c5028c6f390" +dependencies = [ + "anyhow", + "cargo_toml", + "dirs", + "glob", + "heck 0.5.0", + "json-patch 4.2.0", + "schemars 0.8.22", + "semver", + "serde", + "serde_json", + "tauri-utils 2.9.3 (git+https://github.com/tauri-apps/tauri?rev=c0bd0d5a61eedba5c4783add24455c5028c6f390)", + "tauri-winres", + "walkdir", +] + [[package]] name = "tauri-codegen" version = "2.6.3" @@ -4888,6 +5198,20 @@ dependencies = [ "walkdir", ] +[[package]] +name = "tauri-plugin-barcode-scanner" +version = "2.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b68f0e3782b61a6e16a67380be40226e2b7233f3e36dadf6e5d03f07d2e7b3" +dependencies = [ + "log", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror 2.0.19", +] + [[package]] name = "tauri-plugin-deep-link" version = "2.4.9" @@ -4906,7 +5230,7 @@ dependencies = [ "tracing", "url", "windows-registry", - "windows-result", + "windows-result 0.3.4", ] [[package]] @@ -5027,11 +5351,11 @@ dependencies = [ "anyhow", "cargo_metadata", "ctor 0.8.0", - "dom_query", + "dom_query 0.27.0", "dunce", "glob", "http", - "infer", + "infer 0.19.0", "json-patch 3.0.1", "log", "memchr", @@ -5063,11 +5387,11 @@ dependencies = [ "brotli", "cargo_metadata", "ctor 1.0.12", - "dom_query", + "dom_query 0.27.0", "dunce", "glob", "http", - "infer", + "infer 0.19.0", "json-patch 4.2.0", "log", "memchr", @@ -5091,6 +5415,42 @@ dependencies = [ "walkdir", ] +[[package]] +name = "tauri-utils" +version = "2.9.3" +source = "git+https://github.com/tauri-apps/tauri?rev=c0bd0d5a61eedba5c4783add24455c5028c6f390#c0bd0d5a61eedba5c4783add24455c5028c6f390" +dependencies = [ + "anyhow", + "cargo_metadata", + "ctor 1.0.12", + "dom_query 0.28.0", + "dunce", + "glob", + "http", + "infer 0.22.0", + "json-patch 4.2.0", + "log", + "memchr", + "phf", + "plist", + "proc-macro2", + "quote", + "regex", + "schemars 0.8.22", + "semver", + "serde", + "serde-untagged", + "serde_json", + "serde_with", + "swift-rs", + "thiserror 2.0.19", + "toml 1.1.4+spec-1.1.0", + "url", + "urlpattern 0.6.0", + "uuid", + "walkdir", +] + [[package]] name = "tauri-winres" version = "0.3.6" @@ -5120,10 +5480,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -5142,11 +5502,13 @@ dependencies = [ "base64 0.22.1", "jni 0.22.4", "mtp", - "reqwest", + "mtp-transport 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=b067614a684eb1856bc5db7b3fd82148c036ce6b)", + "reqwest 0.12.28", "serde", "serde_json", "tauri", - "tauri-build", + "tauri-build 2.6.3 (git+https://github.com/tauri-apps/tauri?rev=c0bd0d5a61eedba5c4783add24455c5028c6f390)", + "tauri-plugin-barcode-scanner", "tauri-plugin-deep-link", "tauri-plugin-log", "tauri-plugin-notification", @@ -5903,6 +6265,15 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "webpki-roots" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "webview2-com" version = "0.38.2" @@ -5912,7 +6283,7 @@ dependencies = [ "webview2-com-macros", "webview2-com-sys", "windows", - "windows-core", + "windows-core 0.61.2", "windows-implement", "windows-interface", ] @@ -5936,7 +6307,7 @@ checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c" dependencies = [ "thiserror 2.0.19", "windows", - "windows-core", + "windows-core 0.61.2", ] [[package]] @@ -5961,7 +6332,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -5992,7 +6363,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" dependencies = [ "windows-collections", - "windows-core", + "windows-core 0.61.2", "windows-future", "windows-link 0.1.3", "windows-numerics", @@ -6004,7 +6375,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" dependencies = [ - "windows-core", + "windows-core 0.61.2", ] [[package]] @@ -6016,8 +6387,21 @@ dependencies = [ "windows-implement", "windows-interface", "windows-link 0.1.3", - "windows-result", - "windows-strings", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", ] [[package]] @@ -6026,7 +6410,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ - "windows-core", + "windows-core 0.61.2", "windows-link 0.1.3", "windows-threading", ] @@ -6071,7 +6455,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ - "windows-core", + "windows-core 0.61.2", "windows-link 0.1.3", ] @@ -6082,8 +6466,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" dependencies = [ "windows-link 0.1.3", - "windows-result", - "windows-strings", + "windows-result 0.3.4", + "windows-strings 0.4.2", ] [[package]] @@ -6095,6 +6479,15 @@ dependencies = [ "windows-link 0.1.3", ] +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows-strings" version = "0.4.2" @@ -6104,6 +6497,15 @@ dependencies = [ "windows-link 0.1.3", ] +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -6330,7 +6732,7 @@ dependencies = [ "cookie", "crossbeam-channel", "dirs", - "dom_query", + "dom_query 0.27.0", "dpi", "dunce", "gdkx11", @@ -6358,7 +6760,7 @@ dependencies = [ "webkit2gtk-sys", "webview2-com", "windows", - "windows-core", + "windows-core 0.61.2", "windows-version", "x11-dl", ] diff --git a/apps/tauri/src-tauri/Cargo.toml b/apps/tauri/src-tauri/Cargo.toml index 2a68e95..19fe954 100644 --- a/apps/tauri/src-tauri/Cargo.toml +++ b/apps/tauri/src-tauri/Cargo.toml @@ -15,16 +15,17 @@ name = "mobile_lib" crate-type = ["staticlib", "cdylib", "rlib"] [build-dependencies] -tauri-build = { git = "https://github.com/tauri-apps/tauri", rev = "4af26a3f7f8b692d62cca549bbacd93f5ce90b41", features = [] } +tauri-build = { git = "https://github.com/tauri-apps/tauri", rev = "c0bd0d5a61eedba5c4783add24455c5028c6f390", features = [] } [dependencies] tauri-plugin-opener = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" base64 = "0.22" -reqwest = { version = "0.13", default-features = false, features = ["json", "rustls"] } +reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] } tokio = { version = "1", features = ["rt-multi-thread", "sync", "time"] } -mtp = { git = "https://git.methanium.net/Methanium/mtp.git", rev = "a5c8d4f0c898c78351e9d54124886c86e789a22a", features = ["client", "crypto"] } +mtp = { git = "https://git.methanium.net/methanium/mtp.git", rev = "7182272e3edb0079d7b74b45b2f62a298d2fee22", features = ["client", "crypto"] } +mtp-transport = { git = "https://git.methanium.net/methanium/mtp.git", rev = "b067614a684eb1856bc5db7b3fd82148c036ce6b" } webpki-root-certs = "1" tauri-plugin-deep-link = "2" tauri-plugin-notification = "2" @@ -35,14 +36,12 @@ version = "2" features = [] default-features = true -[target.'cfg(not(target_os = "android"))'.dependencies.tauri] -version = "2" -features = [] -default-features = true - [target.'cfg(target_os = "android")'.dependencies] jni = "0.22" +[target.'cfg(any(target_os = "android", target_os = "ios"))'.dependencies] +tauri-plugin-barcode-scanner = "2" + [patch.crates-io.tauri] git = "https://github.com/tauri-apps/tauri" rev = "4af26a3f7f8b692d62cca549bbacd93f5ce90b41" diff --git a/apps/tauri/src-tauri/capabilities/mobile.json b/apps/tauri/src-tauri/capabilities/mobile.json index 91f1d4e..447a06f 100644 --- a/apps/tauri/src-tauri/capabilities/mobile.json +++ b/apps/tauri/src-tauri/capabilities/mobile.json @@ -1,10 +1,17 @@ { "identifier": "mobile-capability", - "platforms": ["android", "iOS"], - "windows": ["main"], + "platforms": [ + "android", + "iOS" + ], + "windows": [ + "main" + ], "permissions": [ - "core:event:default", "deep-link:default", + "barcode-scanner:default", + "barcode-scanner:allow-scan", + "barcode-scanner:allow-cancel", "notification:default", "log:default" ] diff --git a/apps/tauri/src-tauri/gen/android/app/build.gradle.kts b/apps/tauri/src-tauri/gen/android/app/build.gradle.kts index 66d6289..e7120ba 100644 --- a/apps/tauri/src-tauri/gen/android/app/build.gradle.kts +++ b/apps/tauri/src-tauri/gen/android/app/build.gradle.kts @@ -1,4 +1,3 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import java.util.Properties import java.io.FileInputStream @@ -62,17 +61,14 @@ android { ) } } + kotlinOptions { + jvmTarget = "1.8" + } buildFeatures { buildConfig = true } } -kotlin { - compilerOptions { - jvmTarget = JvmTarget.JVM_1_8 - } -} - rust { rootDirRel = "../../../" } diff --git a/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MainActivity.kt b/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MainActivity.kt index 66df13a..bd10948 100644 --- a/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MainActivity.kt +++ b/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MainActivity.kt @@ -3,9 +3,10 @@ package net.tensamin.client import android.Manifest import android.app.Activity import android.content.pm.PackageManager +import android.graphics.Rect import android.media.projection.MediaProjectionManager import android.os.Bundle -import android.view.MotionEvent +import android.view.ViewGroup import android.view.ViewTreeObserver import android.view.WindowManager import android.webkit.JavascriptInterface @@ -55,33 +56,7 @@ class MainActivity : TauriActivity() { } override fun onWebViewCreate(webView: WebView) { - webView.settings.apply { - setSupportZoom(false) - builtInZoomControls = false - displayZoomControls = false - } - - var blockingMultiTouch = false - webView.setOnTouchListener { _, event -> - val shouldBlock = blockingMultiTouch || event.pointerCount > 1 - - when (event.actionMasked) { - MotionEvent.ACTION_POINTER_DOWN -> { - // Cancel the one-finger gesture before consuming the rest of the pinch. - MotionEvent.obtain(event).let { cancelEvent -> - cancelEvent.action = MotionEvent.ACTION_CANCEL - webView.onTouchEvent(cancelEvent) - cancelEvent.recycle() - } - blockingMultiTouch = true - } - MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> blockingMultiTouch = false - } - - shouldBlock - } - - NativeAccessibilityBridge.attach(webView) + webView.setInitialScale(290) mediaWebView = webView MobileMediaEvents.attach(webView) webView.addJavascriptInterface(MobileMediaJavascriptInterface(), "tensaminMobileMedia") @@ -90,12 +65,11 @@ class MainActivity : TauriActivity() { override fun onCreate(savedInstanceState: Bundle?) { WindowCompat.setDecorFitsSystemWindows(window, true) window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING) - super.onCreate(savedInstanceState) - NativeMtpBridge.nativeAttach(applicationContext) if (MtpSecureStore.isEnabled(this) && MtpSecureStore.hasConfig(this)) { NativeMtpBridge.startService(this) } - NativeAccessibilityBridge.nativeAttach(applicationContext) + super.onCreate(savedInstanceState) + NativeMtpBridge.nativeAttach(applicationContext) installKeyboardResizeWorkaround() } @@ -116,10 +90,7 @@ class MainActivity : TauriActivity() { attachLayoutListener = null contentRoot = null contentChild = null - mediaWebView?.let { - NativeAccessibilityBridge.detach(it) - it.removeJavascriptInterface("tensaminMobileMedia") - } + mediaWebView?.removeJavascriptInterface("tensaminMobileMedia") mediaWebView = null MobileMediaEvents.detach() super.onDestroy() @@ -232,20 +203,16 @@ class MainActivity : TauriActivity() { child: android.view.View, insets: WindowInsetsCompat? = ViewCompat.getRootWindowInsets(child), ) { + val visibleFrame = Rect() + child.getWindowVisibleDisplayFrame(visibleFrame) + val rootHeight = child.rootView.height if (rootHeight <= 0) return - val imeVisible = insets?.isVisible(WindowInsetsCompat.Type.ime()) == true - val imeHeight = if (imeVisible) { - insets.getInsets(WindowInsetsCompat.Type.ime()).bottom - } else { - 0 - } - val usableHeight = if (imeHeight in 1 until rootHeight) { - rootHeight - imeHeight - } else { - WindowManager.LayoutParams.MATCH_PARENT - } + val imeHeight = insets?.getInsets(WindowInsetsCompat.Type.ime())?.bottom ?: 0 + val keyboardHeight = maxOf(imeHeight, rootHeight - visibleFrame.bottom) + val keyboardVisible = keyboardHeight > rootHeight * 0.15 + val usableHeight = if (keyboardVisible) rootHeight - keyboardHeight else ViewGroup.LayoutParams.MATCH_PARENT if (previousUsableHeight == usableHeight) return diff --git a/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MediaProjectionService.kt b/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MediaProjectionService.kt index 3e961df..0afa75a 100644 --- a/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MediaProjectionService.kt +++ b/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MediaProjectionService.kt @@ -26,7 +26,6 @@ import android.os.HandlerThread import android.os.IBinder import android.util.Base64 import android.util.DisplayMetrics -import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat import java.io.ByteArrayOutputStream import java.util.concurrent.atomic.AtomicBoolean @@ -108,12 +107,16 @@ class MediaProjectionService : Service() { stopIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, ) - val notification = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID) + val notification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + android.app.Notification.Builder(this, NOTIFICATION_CHANNEL_ID) + } else { + android.app.Notification.Builder(this) + } .setSmallIcon(android.R.drawable.ic_menu_share) .setContentTitle("Tensamin is sharing your screen") .setContentText("Tap Stop to end screen sharing") .setOngoing(true) - .setCategory(NotificationCompat.CATEGORY_SERVICE) + .setCategory(android.app.Notification.CATEGORY_SERVICE) .addAction(android.R.drawable.ic_media_pause, "Stop", stopPendingIntent) .build() diff --git a/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MtpForegroundService.kt b/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MtpForegroundService.kt index 56cca97..8b41c78 100644 --- a/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MtpForegroundService.kt +++ b/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MtpForegroundService.kt @@ -13,8 +13,6 @@ import android.net.Network import android.net.NetworkCapabilities import android.os.Build import android.os.IBinder -import android.os.Process -import android.os.SystemClock import androidx.core.app.NotificationCompat class MtpForegroundService : Service() { @@ -76,19 +74,10 @@ class MtpForegroundService : Service() { } override fun onTaskRemoved(rootIntent: Intent?) { - val preferences = getSharedPreferences(SERVICE_PREFERENCES, Context.MODE_PRIVATE) - val now = SystemClock.elapsedRealtime() - if (now - preferences.getLong(LAST_TASK_RESTART, 0) < TASK_RESTART_COOLDOWN_MS) { - super.onTaskRemoved(rootIntent) - return - } - preferences.edit().putLong(LAST_TASK_RESTART, now).commit() if (MtpSecureStore.isEnabled(this) && MtpSecureStore.hasConfig(this)) { startService(Intent(this, MtpForegroundService::class.java)) } super.onTaskRemoved(rootIntent) - // Tauri cannot recreate its WebView after the UI task is removed while this process survives. - Process.killProcess(Process.myPid()) } override fun onDestroy() { @@ -105,9 +94,6 @@ class MtpForegroundService : Service() { private const val CHANNEL_ID = "tensamin-connection" private const val NOTIFICATION_ID = 2201 private const val ACTION_STOP = "net.tensamin.client.STOP_MTP" - private const val SERVICE_PREFERENCES = "tensamin-service" - private const val LAST_TASK_RESTART = "last-task-restart" - private const val TASK_RESTART_COOLDOWN_MS = 15_000L @Volatile private var connectionStatus = "Connecting" fun updateNotification(context: Context, status: String) { diff --git a/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/NativeAccessibilityBridge.kt b/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/NativeAccessibilityBridge.kt deleted file mode 100644 index e04365a..0000000 --- a/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/NativeAccessibilityBridge.kt +++ /dev/null @@ -1,51 +0,0 @@ -package net.tensamin.client - -import android.content.Context -import android.webkit.WebView -import androidx.annotation.Keep -import java.lang.ref.WeakReference - -@Keep -object NativeAccessibilityBridge { - const val DEFAULT_INITIAL_SCALE = 290 - private const val MIN_INITIAL_SCALE = 210 - private const val MAX_INITIAL_SCALE = 500 - private const val PREFERENCES = "tensamin-accessibility" - private const val INITIAL_SCALE = "initial-scale" - - private var webView = WeakReference(null) - - init { - System.loadLibrary("mobile_lib") - } - - @JvmStatic external fun nativeAttach(context: Context) - - fun attach(webView: WebView) { - this.webView = WeakReference(webView) - webView.setInitialScale(getInitialScale(webView.context)) - } - - fun detach(webView: WebView) { - if (this.webView.get() === webView) this.webView.clear() - } - - fun getInitialScale(context: Context): Int { - val preferences = context.getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE) - val storedScale = preferences.getInt(INITIAL_SCALE, DEFAULT_INITIAL_SCALE) - val scale = storedScale.coerceIn(MIN_INITIAL_SCALE, MAX_INITIAL_SCALE) - if (scale != storedScale) preferences.edit().putInt(INITIAL_SCALE, scale).apply() - return scale - } - - fun setInitialScale(context: Context, initialScale: Int) { - val nextScale = initialScale.coerceIn(MIN_INITIAL_SCALE, MAX_INITIAL_SCALE) - context.getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE) - .edit() - .putInt(INITIAL_SCALE, nextScale) - .apply() - webView.get()?.let { currentWebView -> - currentWebView.post { currentWebView.setInitialScale(nextScale) } - } - } -} diff --git a/apps/tauri/src-tauri/gen/android/build.gradle.kts b/apps/tauri/src-tauri/gen/android/build.gradle.kts index 1488b27..00024b5 100644 --- a/apps/tauri/src-tauri/gen/android/build.gradle.kts +++ b/apps/tauri/src-tauri/gen/android/build.gradle.kts @@ -1,4 +1,4 @@ -import com.android.build.api.dsl.LibraryExtension +import com.android.build.gradle.LibraryExtension buildscript { repositories { @@ -6,7 +6,7 @@ buildscript { mavenCentral() } dependencies { - classpath("com.android.tools.build:gradle:8.11.0") + classpath("com.android.tools.build:gradle:8.13.2") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.20") } } diff --git a/apps/tauri/src-tauri/gen/android/buildSrc/build.gradle.kts b/apps/tauri/src-tauri/gen/android/buildSrc/build.gradle.kts index 09776c6..9edb463 100644 --- a/apps/tauri/src-tauri/gen/android/buildSrc/build.gradle.kts +++ b/apps/tauri/src-tauri/gen/android/buildSrc/build.gradle.kts @@ -18,5 +18,6 @@ repositories { dependencies { compileOnly(gradleApi()) - implementation("com.android.tools.build:gradle:8.11.0") + implementation("com.android.tools.build:gradle:8.13.2") } + diff --git a/apps/tauri/src-tauri/gen/android/buildSrc/src/main/java/net/tensamin/client/kotlin/BuildTask.kt b/apps/tauri/src-tauri/gen/android/buildSrc/src/main/java/net/tensamin/client/kotlin/BuildTask.kt index e2be2d1..a7e39eb 100644 --- a/apps/tauri/src-tauri/gen/android/buildSrc/src/main/java/net/tensamin/client/kotlin/BuildTask.kt +++ b/apps/tauri/src-tauri/gen/android/buildSrc/src/main/java/net/tensamin/client/kotlin/BuildTask.kt @@ -5,12 +5,8 @@ import org.gradle.api.GradleException import org.gradle.api.logging.LogLevel import org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskAction -import org.gradle.process.ExecOperations -import javax.inject.Inject -open class BuildTask @Inject constructor( - private val execOperations: ExecOperations, -) : DefaultTask() { +open class BuildTask : DefaultTask() { @Input var rootDirRel: String? = null @Input @@ -54,7 +50,7 @@ open class BuildTask @Inject constructor( val release = release ?: throw GradleException("release cannot be null") val args = listOf("tauri", "android", "android-studio-script"); - execOperations.exec { + project.exec { workingDir(File(project.projectDir, rootDirRel)) executable(executable) args(args) @@ -69,4 +65,4 @@ open class BuildTask @Inject constructor( args(listOf("--target", target)) }.assertNormalExitValue() } -} +} \ No newline at end of file diff --git a/apps/tauri/src-tauri/src/accessibility_backend.rs b/apps/tauri/src-tauri/src/accessibility_backend.rs deleted file mode 100644 index 692b42e..0000000 --- a/apps/tauri/src-tauri/src/accessibility_backend.rs +++ /dev/null @@ -1,135 +0,0 @@ -#[cfg(not(target_os = "android"))] -const DEFAULT_INITIAL_SCALE: i32 = 290; -const MIN_INITIAL_SCALE: i32 = 210; -const MAX_INITIAL_SCALE: i32 = 500; - -#[tauri::command] -pub fn accessibility_get_initial_scale() -> Result { - android_get_initial_scale() -} - -#[tauri::command] -pub fn accessibility_set_initial_scale(initial_scale: i32) -> Result<(), String> { - if !(MIN_INITIAL_SCALE..=MAX_INITIAL_SCALE).contains(&initial_scale) { - return Err(format!( - "Initial scale must be between {MIN_INITIAL_SCALE} and {MAX_INITIAL_SCALE}" - )); - } - - android_set_initial_scale(initial_scale) -} - -#[cfg(not(target_os = "android"))] -fn android_get_initial_scale() -> Result { - Ok(DEFAULT_INITIAL_SCALE) -} - -#[cfg(not(target_os = "android"))] -fn android_set_initial_scale(_: i32) -> Result<(), String> { - Ok(()) -} - -#[cfg(target_os = "android")] -mod android { - use std::sync::OnceLock; - - use jni::{ - jni_sig, jni_str, - objects::{Global, JClass, JObject, JValue}, - Env, EnvUnowned, JavaVM, - }; - - struct Host { - vm: JavaVM, - context: Global>, - bridge: Global>, - } - - static HOST: OnceLock = OnceLock::new(); - - fn attach(env: &mut Env, context: JObject) -> Result<(), String> { - if HOST.get().is_some() { - return Ok(()); - } - - let class = env - .find_class(jni_str!("net/tensamin/client/NativeAccessibilityBridge")) - .map_err(|error| error.to_string())?; - let bridge = env - .get_static_field( - class, - jni_str!("INSTANCE"), - jni_sig!("Lnet/tensamin/client/NativeAccessibilityBridge;"), - ) - .and_then(|value| value.l()) - .map_err(|error| error.to_string())?; - - HOST.set(Host { - vm: env.get_java_vm().map_err(|error| error.to_string())?, - context: env - .new_global_ref(context) - .map_err(|error| error.to_string())?, - bridge: env - .new_global_ref(bridge) - .map_err(|error| error.to_string())?, - }) - .map_err(|_| "Android accessibility host is already attached".to_string()) - } - - fn with_env(call: impl FnOnce(&mut Env, &Host) -> Result) -> Result { - let host = HOST - .get() - .ok_or("Android accessibility host is not attached")?; - host.vm - .attach_current_thread(|env| Ok::<_, jni::errors::Error>(call(env, host))) - .map_err(|error| error.to_string())? - } - - pub fn get_initial_scale() -> Result { - with_env(|env, host| { - env.call_method( - host.bridge.as_obj(), - jni_str!("getInitialScale"), - jni_sig!("(Landroid/content/Context;)I"), - &[JValue::Object(host.context.as_obj())], - ) - .and_then(|value| value.i()) - .map_err(|error| error.to_string()) - }) - } - - pub fn set_initial_scale(initial_scale: i32) -> Result<(), String> { - with_env(|env, host| { - env.call_method( - host.bridge.as_obj(), - jni_str!("setInitialScale"), - jni_sig!("(Landroid/content/Context;I)V"), - &[ - JValue::Object(host.context.as_obj()), - JValue::Int(initial_scale), - ], - ) - .map_err(|error| error.to_string())?; - Ok(()) - }) - } - - #[no_mangle] - pub extern "system" fn Java_net_tensamin_client_NativeAccessibilityBridge_nativeAttach< - 'caller, - >( - mut env: EnvUnowned<'caller>, - _class: JClass, - context: JObject<'caller>, - ) { - let _ = env.with_env(|env| { - let _ = attach(env, context); - Ok::<_, jni::errors::Error>(()) - }); - } -} - -#[cfg(target_os = "android")] -use android::{ - get_initial_scale as android_get_initial_scale, set_initial_scale as android_set_initial_scale, -}; diff --git a/apps/tauri/src-tauri/src/lib.rs b/apps/tauri/src-tauri/src/lib.rs index 6636682..8131b57 100644 --- a/apps/tauri/src-tauri/src/lib.rs +++ b/apps/tauri/src-tauri/src/lib.rs @@ -1,4 +1,3 @@ -mod accessibility_backend; mod mtp_backend; #[cfg_attr(mobile, tauri::mobile_entry_point)] @@ -15,10 +14,11 @@ pub fn run() { .plugin(tauri_plugin_deep_link::init()) .plugin(tauri_plugin_opener::init()); + #[cfg(any(target_os = "ios", target_os = "android"))] + let builder = builder.plugin(tauri_plugin_barcode_scanner::init()); + let app = builder .invoke_handler(tauri::generate_handler![ - accessibility_backend::accessibility_get_initial_scale, - accessibility_backend::accessibility_set_initial_scale, mtp_backend::mtp_request, mtp_backend::mtp_status, mtp_backend::mtp_store_credentials, diff --git a/apps/tauri/src-tauri/src/main.rs b/apps/tauri/src-tauri/src/main.rs index 272583a..e78a26a 100644 --- a/apps/tauri/src-tauri/src/main.rs +++ b/apps/tauri/src-tauri/src/main.rs @@ -1,6 +1,9 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] +use lib::log; + fn main() { mobile_lib::run(); + log("Test test 123") } diff --git a/apps/tauri/src-tauri/src/mtp_backend.rs b/apps/tauri/src-tauri/src/mtp_backend.rs index fa28597..09fa249 100644 --- a/apps/tauri/src-tauri/src/mtp_backend.rs +++ b/apps/tauri/src-tauri/src/mtp_backend.rs @@ -2,7 +2,7 @@ use std::sync::{ atomic::{AtomicBool, AtomicU64, Ordering}, Arc, Mutex, OnceLock, RwLock, }; -use std::time::{Duration, SystemTime, UNIX_EPOCH}; +use std::time::Duration; use base64::{ engine::general_purpose::{STANDARD, STANDARD_NO_PAD}, @@ -16,7 +16,6 @@ use mtp::crypto::{ use serde::{Deserialize, Serialize}; use serde_json::{Map, Value}; use tauri::{AppHandle, Emitter}; -use tokio::sync::mpsc; const EVENT_NAME: &str = "mtp://event"; const DISCONNECTED: u8 = 0; @@ -25,9 +24,6 @@ const CONNECTED: u8 = 2; const CHAT_SECRET_SALT: &[u8] = b"tensamin-chat-secret-v1"; const CHAT_MESSAGE_SALT: &[u8] = b"tensamin-chat-message-v1"; const CHAT_SECRET_SCHEME: &str = "mtp-chat-secret-kem-chacha20poly1305-hkdf-sha256-v1"; -const INITIAL_SYNC_TIMEOUT: Duration = Duration::from_secs(30); -const MAX_BUFFERED_INITIAL_FRAMES: usize = 1_000; -const NOTIFICATION_QUEUE_CAPACITY: usize = 32; #[cfg(target_os = "android")] const ROOT_YE_PEM: &[u8] = b"-----BEGIN CERTIFICATE-----\n\ MIIB2TCCAWCgAwIBAgIRAKQCa6LvbHwg1AR+XmWmk4AwCgYIKoZIzj0EAwMwLjEL\n\ @@ -99,7 +95,7 @@ enum MtpEvent { pub struct MtpManager { runtime: tokio::runtime::Runtime, config: RwLock>, - connection: RwLock>>, + connection: RwLock>>, snapshot: RwLock, generation: AtomicU64, enabled: AtomicBool, @@ -108,46 +104,6 @@ pub struct MtpManager { start_lock: Mutex<()>, } -struct RequestIdAllocator { - next: AtomicU64, -} - -impl RequestIdAllocator { - fn new() -> Self { - Self { - next: AtomicU64::new(1), - } - } - - fn next(&self) -> Result { - let value = self.next.fetch_add(1, Ordering::Relaxed); - u32::try_from(value) - .map_err(|_| "MTP request ID space exhausted for this connection".to_string()) - } -} - -struct ManagedConnection { - mtp: Arc, - request_ids: RequestIdAllocator, -} - -impl ManagedConnection { - async fn next_request_id(&self) -> Result { - let id = self.request_ids.next(); - if id.is_err() { - self.mtp.sender.close().await; - } - id - } -} - -struct PreparedConnection { - connection: MTPConnection, - request_ids: RequestIdAllocator, - initial_state: Value, - buffered_frames: Vec, -} - static MANAGER: OnceLock = OnceLock::new(); pub fn manager() -> &'static MtpManager { @@ -193,7 +149,7 @@ impl MtpManager { .take() { self.runtime - .spawn(async move { connection.mtp.sender.close().await }); + .spawn(async move { connection.sender.close().await }); } self.set_snapshot(MtpSnapshot { generation, @@ -215,7 +171,7 @@ impl MtpManager { .take() { self.runtime - .spawn(async move { connection.mtp.sender.close().await }); + .spawn(async move { connection.sender.close().await }); } self.set_snapshot(MtpSnapshot { generation: self.generation.load(Ordering::SeqCst), @@ -275,16 +231,20 @@ impl MtpManager { self.enabled.load(Ordering::SeqCst) && self.generation.load(Ordering::SeqCst) == generation } - async fn request(&self, type_name: &str, data: Value) -> Result { + async fn request( + &self, + type_name: &str, + data: Value, + id: Option, + ) -> Result { let connection = self .connection .read() .map_err(|_| "MTP connection lock is unavailable")? .clone() .ok_or_else(|| "MTP is not connected".to_string())?; - let request = json_to_frame(type_name, data, connection.next_request_id().await?)?; + let request = json_to_frame(type_name, data, id)?; let response = connection - .mtp .request(&request, None) .await .map_err(|error| error.to_string())?; @@ -301,12 +261,9 @@ async fn supervise(generation: u64) { manager.log(2, "Starting native MTP connection", None); android_status("Connecting"); match connect(&config).await { - Ok(prepared) => { + Ok((connection, state)) => { delay = Duration::from_secs(1); - let connection = Arc::new(ManagedConnection { - mtp: Arc::new(prepared.connection), - request_ids: prepared.request_ids, - }); + let connection = Arc::new(connection); let stale = { let _guard = manager.start_lock.lock().expect("start lock poisoned"); let mut current = manager @@ -322,47 +279,22 @@ async fn supervise(generation: u64) { generation, ready_state: CONNECTED, identified: true, - state: Some(prepared.initial_state), + state: Some(state), error: None, }); false } }; if stale { - connection.mtp.sender.close().await; + connection.sender.close().await; break; } android_status("Connected"); manager.log(2, "Native MTP connection established", None); - let (notification_tx, mut notification_rx) = - mpsc::channel(NOTIFICATION_QUEUE_CAPACITY); - let notification_connection = connection.clone(); - let notification_config = config.clone(); - let notification_worker = tokio::spawn(async move { - while let Some(frame) = notification_rx.recv().await { - if !manager.is_current(generation) { - break; - } - if let Err(error) = notify_message( - ¬ification_config, - notification_connection.clone(), - &frame, - ) - .await - { - eprintln!("failed to create background message notification: {error}"); - } - } - }); - - for frame in prepared.buffered_frames { - handle_push(generation, ¬ification_tx, frame).await; - } - while manager.is_current(generation) { - match connection.mtp.receive().await { - Ok(frame) => handle_push(generation, ¬ification_tx, frame).await, + match connection.receive().await { + Ok(frame) => handle_push(generation, connection.clone(), frame).await, Err(error) => { let _guard = manager.start_lock.lock().expect("start lock poisoned"); if manager.is_current(generation) { @@ -378,13 +310,6 @@ async fn supervise(generation: u64) { } } } - drop(notification_tx); - notification_worker.abort(); - if let Err(error) = notification_worker.await { - if !error.is_cancelled() { - eprintln!("background notification worker failed: {error}"); - } - } let mut current = manager .connection .write() @@ -414,21 +339,12 @@ async fn supervise(generation: u64) { break; } android_status("Reconnecting"); - tokio::time::sleep(jittered_retry_delay(delay)).await; + tokio::time::sleep(delay).await; delay = (delay * 2).min(Duration::from_secs(60)); } } -fn jittered_retry_delay(delay: Duration) -> Duration { - let entropy = SystemTime::now() - .duration_since(UNIX_EPOCH) - .map(|duration| duration.subsec_nanos()) - .unwrap_or_default(); - let percent = 80 + entropy % 41; - delay.mul_f64(percent as f64 / 100.0) -} - -async fn connect(config: &MtpConfig) -> Result { +async fn connect(config: &MtpConfig) -> Result<(MTPConnection, Value), String> { let (url, public_key) = resolve_endpoint(config) .await .map_err(|error| format!("endpoint discovery failed: {error}"))?; @@ -456,21 +372,43 @@ async fn connect(config: &MtpConfig) -> Result { .with_max_missed_pings(3); #[cfg(target_os = "android")] let client_config = client_config.with_pinned_pem(android_root_certificates().clone()); - let connection = tokio::time::timeout( - Duration::from_secs(30), - MTPClient::auth_connect(client_config, &keyring, &host_key), - ) - .await - .map_err(|_| "transport authentication timed out".to_string())? - .map_err(|error| format!("transport authentication failed: {error}"))?; + let connection = MTPClient::auth_connect(client_config, &keyring, &host_key) + .await + .map_err(|error| format!("transport authentication failed: {error}"))?; manager().log(2, "Native MTP authentication completed", None); - let (state, buffered_frames) = await_initial_state(&connection).await?; - let request_ids = RequestIdAllocator::new(); - let (initial_state, ack) = prepare_initial_state_ack(&state, &request_ids)?; - let response = tokio::time::timeout(INITIAL_SYNC_TIMEOUT, connection.request(&ack, None)) + let connected = CommunicationValue::new(CommunicationType::ClientConnected) + .add_typed_default( + DataType::SessionId, + DataValue::UnsignedNumber(current_millis() as u128), + ) + .add_typed_default(DataType::VersionNumber, DataValue::UnsignedNumber(0)) + .add_typed_default(DataType::CacheValid, DataValue::BoolFalse) + .add_typed_default(DataType::CacheSchemaVersion, DataValue::UnsignedNumber(0)); + let state = connection + .request(&connected, None) + .await + .map_err(|error| format!("initial state synchronization failed: {error}"))?; + if !state.is_type(CommunicationType::ClientStateSync) { + return Err(format!( + "expected ClientStateSync, received {}", + state.get_type_name().unwrap_or("unknown") + )); + } + let session_id = state + .get_data(DataType::SessionId) + .as_number() + .ok_or("ClientStateSync omitted SessionId")?; + let version = state + .get_data(DataType::VersionNumber) + .as_number() + .ok_or("ClientStateSync omitted VersionNumber")?; + let ack = CommunicationValue::new(CommunicationType::ClientStateAck) + .add_typed_default(DataType::SessionId, number_to_data(session_id)) + .add_typed_default(DataType::VersionNumber, number_to_data(version)); + let response = connection + .request(&ack, None) .await - .map_err(|_| "state acknowledgement timed out".to_string())? .map_err(|error| format!("state acknowledgement failed: {error}"))?; if response .get_type_name() @@ -478,182 +416,7 @@ async fn connect(config: &MtpConfig) -> Result { { return Err(format!("ClientStateAck failed: {response}")); } - Ok(PreparedConnection { - connection, - request_ids, - initial_state, - buffered_frames, - }) -} - -fn prepare_initial_state_ack( - state: &CommunicationValue, - request_ids: &RequestIdAllocator, -) -> Result<(Value, CommunicationValue), String> { - let initial_state = frame_data_to_json(state)?; - validate_client_state_sync(&initial_state)?; - let data = initial_state - .as_object() - .ok_or("ClientStateSync payload is not an object")?; - let session_id = required_integer(data, "SessionId")?; - let version = required_integer(data, "VersionNumber")?; - let ack = CommunicationValue::new(communication_type("ClientStateAck")?) - .with_id(request_ids.next()?) - .add_typed_default(DataType::SessionId, number_to_data(session_id)) - .add_typed_default(DataType::VersionNumber, number_to_data(version)); - Ok((initial_state, ack)) -} - -fn validate_client_state_sync(state: &Value) -> Result<(), String> { - let data = state - .as_object() - .ok_or("ClientStateSync payload is not an object")?; - if required_integer(data, "SessionId")? <= 0 { - return Err("ClientStateSync SessionId must be a positive integer".into()); - } - for field in ["VersionNumber", "CacheSchemaVersion"] { - if required_integer(data, field)? < 0 { - return Err(format!("ClientStateSync {field} must be nonnegative")); - } - } - match data.get("SyncMode").and_then(Value::as_str) { - Some("full" | "delta") => {} - _ => return Err("ClientStateSync SyncMode must be 'full' or 'delta'".into()), - } - for field in ["Contacts", "Communities", "Calls", "Messages"] { - if !data.get(field).is_some_and(Value::is_array) { - return Err(format!("ClientStateSync {field} must be an array")); - } - } - for field in ["DeletedMessageIds", "DeletedContactIds"] { - if let Some(value) = data.get(field) { - let values = value - .as_array() - .ok_or_else(|| format!("ClientStateSync {field} must be an array"))?; - if values.iter().any(|value| !value.is_number()) { - return Err(format!("ClientStateSync {field} must contain numbers")); - } - } - } - validate_object_array(data, "Communities", |_| Ok(()))?; - validate_object_array(data, "Contacts", validate_contact)?; - validate_object_array(data, "Calls", validate_call)?; - validate_object_array(data, "Messages", validate_message)?; - Ok(()) -} - -fn validate_object_array( - data: &Map, - field: &str, - validate: impl Fn(&Map) -> Result<(), String>, -) -> Result<(), String> { - let values = data - .get(field) - .and_then(Value::as_array) - .ok_or_else(|| format!("ClientStateSync {field} must be an array"))?; - for value in values { - let object = value - .as_object() - .ok_or_else(|| format!("ClientStateSync {field} entries must be objects"))?; - validate(object)?; - } - Ok(()) -} - -fn validate_contact(contact: &Map) -> Result<(), String> { - if !contact.get("UserId").is_some_and(Value::is_number) { - return Err("ClientStateSync contact omitted numeric UserId".into()); - } - if let Some(messages) = contact.get("Messages") { - let messages = messages - .as_array() - .ok_or("ClientStateSync contact Messages must be an array")?; - for message in messages { - validate_message( - message - .as_object() - .ok_or("ClientStateSync contact message must be an object")?, - )?; - } - } - Ok(()) -} - -fn validate_call(call: &Map) -> Result<(), String> { - if !call.get("CallId").is_some_and(Value::is_string) { - return Err("ClientStateSync call omitted string CallId".into()); - } - let members = call - .get("CallMembers") - .and_then(Value::as_array) - .ok_or("ClientStateSync call omitted CallMembers array")?; - if members.iter().any(|member| !member.is_number()) { - return Err("ClientStateSync CallMembers must contain numbers".into()); - } - Ok(()) -} - -fn validate_message(message: &Map) -> Result<(), String> { - for field in ["SenderId", "SendTime"] { - if !message.get(field).is_some_and(Value::is_number) { - return Err(format!("ClientStateSync message omitted numeric {field}")); - } - } - let content = message - .get("Content") - .and_then(Value::as_str) - .ok_or("ClientStateSync message omitted string Content")?; - STANDARD - .decode(content) - .or_else(|_| STANDARD_NO_PAD.decode(content)) - .map_err(|_| "ClientStateSync message Content must be base64".to_string())?; - if let Some(state) = message.get("MessageState") { - match state.as_str() { - Some("read" | "received" | "sent" | "sending" | "awaiting") => {} - _ => return Err("ClientStateSync message has invalid MessageState".into()), - } - } - Ok(()) -} - -fn required_integer(data: &Map, field: &str) -> Result { - let value = data - .get(field) - .ok_or_else(|| format!("ClientStateSync omitted {field}"))?; - if let Some(value) = value.as_i64() { - return Ok(value as i128); - } - value - .as_u64() - .map(|value| value as i128) - .ok_or_else(|| format!("ClientStateSync {field} must be an integer")) -} - -async fn await_initial_state( - connection: &MTPConnection, -) -> Result<(CommunicationValue, Vec), String> { - let mut buffered = Vec::new(); - let deadline = tokio::time::Instant::now() + INITIAL_SYNC_TIMEOUT; - - loop { - let frame = tokio::time::timeout_at(deadline, connection.receive()) - .await - .map_err(|_| "initial state synchronization timed out".to_string())? - .map_err(|error| format!("initial state synchronization failed: {error}"))?; - - if frame.is_type(CommunicationType::ErrorNoIota) { - return Err("No Iota is currently connected".into()); - } - - if frame.get_type_name() == Some("ClientStateSync") { - return Ok((frame, buffered)); - } - - if buffered.len() == MAX_BUFFERED_INITIAL_FRAMES { - return Err("initial state synchronization buffered too many frames".into()); - } - buffered.push(frame); - } + Ok((connection, frame_data_to_json(&state)?)) } async fn resolve_endpoint(config: &MtpConfig) -> Result<(String, String), String> { @@ -670,19 +433,7 @@ async fn resolve_endpoint(config: &MtpConfig) -> Result<(String, String), String public_key: String, } let root = config.omega_url.trim_end_matches('/'); - let client = reqwest::Client::builder() - .connect_timeout(Duration::from_secs(10)) - .timeout(Duration::from_secs(20)); - #[cfg(target_os = "android")] - let client = client.tls_certs_only( - reqwest::Certificate::from_pem_bundle(android_root_certificates()) - .map_err(|error| format!("invalid bundled root certificates: {error}"))?, - ); - let response = client - .build() - .map_err(|error| error.to_string())? - .get(format!("{root}/api/get/omikron/{}", config.user_id)) - .send() + let response = reqwest::get(format!("{root}/api/get/omikron/{}", config.user_id)) .await .map_err(|error| error.to_string())?; if !response.status().is_success() { @@ -695,11 +446,7 @@ async fn resolve_endpoint(config: &MtpConfig) -> Result<(String, String), String )) } -async fn handle_push( - generation: u64, - notification_tx: &mpsc::Sender, - frame: CommunicationValue, -) { +async fn handle_push(generation: u64, connection: Arc, frame: CommunicationValue) { let manager = manager(); if let Ok(message) = frame_to_json(&frame) { manager.emit(MtpEvent::Message { @@ -712,7 +459,7 @@ async fn handle_push( { if let Some(partner_id) = frame .get_data(DataType::ChatPartnerId) - .and_then(DataValue::as_number) + .as_number() .and_then(|value| u64::try_from(value).ok()) { if let Err(error) = android_cancel_notification(partner_id) { @@ -721,39 +468,40 @@ async fn handle_push( } } if frame.is_type(CommunicationType::MessageLive) && !manager.ui_visible.load(Ordering::SeqCst) { - if notification_tx.try_send(frame).is_err() { - eprintln!("background message notification queue is full"); + if let Err(error) = notify_message(connection, &frame).await { + eprintln!("failed to create background message notification: {error}"); } } } async fn notify_message( - config: &MtpConfig, - connection: Arc, + connection: Arc, frame: &CommunicationValue, ) -> Result<(), String> { let sender_id = frame .get_data(DataType::SenderId) - .and_then(DataValue::as_number) + .as_number() .and_then(|value| u64::try_from(value).ok()) .ok_or("MessageLive omitted SenderId")?; - let message = frame - .get_data(DataType::Message) - .ok_or("MessageLive omitted Message")?; - let content = container_value_by_name(message, "Content") + let message = frame.get_data(DataType::Message); + let content = container_value(message, DataType::Content) .and_then(DataValue::as_str) .ok_or("MessageLive omitted Content")?; + let config = manager() + .config + .read() + .expect("config lock poisoned") + .clone() + .ok_or("missing config")?; let keyring_bytes = decode_browser_base64(&config.keyring)?; let keyring = Keyring::from_bytes(&keyring_bytes).map_err(|error| error.to_string())?; let chat_id = derive_chat_id(config.user_id, sender_id); let secret_id = format!("chat:{chat_id}:main"); let secret_request = CommunicationValue::new(CommunicationType::GetChatSecret) - .with_id(connection.next_request_id().await?) .add_typed_default(DataType::UserId, DataValue::Str(config.user_id.to_string())) .add_typed_default(DataType::ChatId, DataValue::Str(chat_id.clone())) .add_typed_default(DataType::SecretId, DataValue::Str(secret_id.clone())); let secret = connection - .mtp .request(&secret_request, None) .await .map_err(|error| error.to_string())?; @@ -765,7 +513,7 @@ async fn notify_message( } let version = secret .get_data(DataType::VersionNumber) - .and_then(DataValue::as_number) + .as_number() .ok_or("missing secret version")?; let encrypted_secret = secret .get_bytes(DataType::EncryptedSecret) @@ -793,14 +541,11 @@ async fn notify_message( .decrypt(&ciphertext, b"") .map_err(|error| error.to_string())?; - let user_request = CommunicationValue::new(CommunicationType::GetUserData) - .with_id(connection.next_request_id().await?) - .add_typed_default( - DataType::UserId, - DataValue::UnsignedNumber(sender_id as u128), - ); + let user_request = CommunicationValue::new(CommunicationType::GetUserData).add_typed_default( + DataType::UserId, + DataValue::UnsignedNumber(sender_id as u128), + ); let user = connection - .mtp .request(&user_request, None) .await .map_err(|error| error.to_string())?; @@ -888,17 +633,17 @@ fn container_value(value: &DataValue, field: DataType) -> Option<&DataValue> { value.get_field(id) } -fn container_value_by_name<'a>(value: &'a DataValue, field: &str) -> Option<&'a DataValue> { - container_value(value, DataType::from_name(field)?) -} - -fn communication_type(name: &str) -> Result { - CommunicationType::from_name(name).ok_or_else(|| format!("unknown communication type: {name}")) -} - -fn json_to_frame(type_name: &str, data: Value, id: u32) -> Result { - let comm_type = communication_type(type_name)?; - let mut frame = CommunicationValue::new(comm_type).with_id(id); +fn json_to_frame( + type_name: &str, + data: Value, + id: Option, +) -> Result { + let comm_type = CommunicationType::from_name(type_name) + .ok_or_else(|| format!("unknown communication type: {type_name}"))?; + let mut frame = CommunicationValue::new(comm_type); + if let Some(id) = id { + frame = frame.with_id(id); + } let Value::Object(fields) = data else { return Err("MTP request data must be an object".into()); }; @@ -973,8 +718,8 @@ fn is_bytes_field(field: &str) -> bool { fn frame_to_json(frame: &CommunicationValue) -> Result { let mut result = Map::new(); - if let Some(id) = frame.id() { - result.insert("id".into(), Value::from(id)); + if frame.get_id() != 0 { + result.insert("id".into(), Value::from(frame.get_id())); } result.insert( "type".into(), @@ -987,10 +732,7 @@ fn frame_to_json(frame: &CommunicationValue) -> Result { fn frame_data_to_json(frame: &CommunicationValue) -> Result { let map = frame.type_map().cloned().unwrap_or_else(TypeMap::latest); let mut result = Map::new(); - let entries = frame - .data() - .ok_or("MTP frame payload is not a data container")?; - for (id, value) in entries { + for (id, value) in frame.data() { let name = map .data_type_name(id.0) .ok_or_else(|| format!("unknown data type id: {}", id.0))?; @@ -1040,15 +782,16 @@ fn number_to_json(value: i128) -> Result { .map_err(|_| "number exceeds JSON range".into()) } +fn current_millis() -> u64 { + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default() + .as_millis() as u64 +} + #[cfg(test)] mod tests { - use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue}; - use serde_json::json; - - use super::{ - container_value_by_name, decode_browser_base64, decode_sdk_bytes, frame_to_json, - jittered_retry_delay, json_to_frame, prepare_initial_state_ack, RequestIdAllocator, - }; + use super::{decode_browser_base64, decode_sdk_bytes}; #[test] fn browser_base64_accepts_file_whitespace_and_missing_padding() { @@ -1061,137 +804,11 @@ mod tests { assert_eq!(decode_sdk_bytes("0x01:02-ff").unwrap(), [1, 2, 255]); assert_eq!(decode_sdk_bytes("AQI=").unwrap(), [1, 2]); } - - #[test] - fn request_ids_are_nonzero_and_monotonic() { - let ids = RequestIdAllocator::new(); - - assert_eq!(ids.next().unwrap(), 1); - assert_eq!(ids.next().unwrap(), 2); - } - - #[test] - fn retry_jitter_stays_within_policy_bounds() { - let delay = jittered_retry_delay(std::time::Duration::from_secs(10)); - - assert!(delay >= std::time::Duration::from_secs(8)); - assert!(delay <= std::time::Duration::from_secs(12)); - } - - #[test] - fn json_content_uses_content_wire_type() { - let frame = json_to_frame( - "MessageEdit", - json!({ - "Content": "ciphertext", - "ChatPartnerId": 42, - "SendTime": 10, - }), - 1, - ) - .unwrap(); - - assert_eq!( - frame - .get_data(DataType::Content) - .and_then(DataValue::as_str), - Some("ciphertext") - ); - } - - #[test] - fn nested_json_content_uses_content_wire_type() { - let frame = json_to_frame( - "MessageEdit", - json!({ - "Message": { "Content": "ciphertext" }, - }), - 1, - ) - .unwrap(); - let message = frame.get_data(DataType::Message).unwrap(); - - assert_eq!( - container_value_by_name(message, "Content").and_then(DataValue::as_str), - Some("ciphertext") - ); - } - - #[test] - fn content_is_exposed_to_frontend() { - let frame = CommunicationValue::new(CommunicationType::MessageEditLive) - .with_id(1) - .add_typed_default(DataType::Content, DataValue::Str("ciphertext".into())); - - let json = frame_to_json(&frame).unwrap(); - - assert_eq!(json["data"]["Content"], "ciphertext"); - } - - fn valid_initial_state() -> CommunicationValue { - CommunicationValue::new(communication_type("ClientStateSync").unwrap()) - .add_typed_default(DataType::SessionId, DataValue::UnsignedNumber(1)) - .add_typed_default(DataType::VersionNumber, DataValue::UnsignedNumber(0)) - .add_typed_default(DataType::CacheSchemaVersion, DataValue::UnsignedNumber(0)) - .add_typed_default(DataType::SyncMode, DataValue::Str("full".into())) - .add_typed_default(DataType::Contacts, DataValue::Array(vec![])) - .add_typed_default(DataType::Communities, DataValue::Array(vec![])) - .add_typed_default(DataType::Calls, DataValue::Array(vec![])) - .add_typed_default(DataType::Messages, DataValue::Array(vec![])) - } - - #[test] - fn valid_initial_state_is_prepared_before_ack() { - let ids = RequestIdAllocator::new(); - let (state, ack) = prepare_initial_state_ack(&valid_initial_state(), &ids).unwrap(); - - assert_eq!(state["SyncMode"], "full"); - assert_eq!(ack.get_type_name(), Some("ClientStateAck")); - assert_eq!(ack.id(), Some(1)); - } - - #[test] - fn malformed_initial_state_does_not_prepare_ack() { - let ids = RequestIdAllocator::new(); - let malformed = valid_initial_state() - .add_typed_default(DataType::SyncMode, DataValue::Str("invalid".into())); - - assert!(prepare_initial_state_ack(&malformed, &ids).is_err()); - assert_eq!( - ids.next().unwrap(), - 1, - "no acknowledgement ID was allocated" - ); - } - - #[test] - fn malformed_nested_initial_state_does_not_prepare_ack() { - let ids = RequestIdAllocator::new(); - let malformed = CommunicationValue::new(communication_type("ClientStateSync").unwrap()) - .add_typed_default(DataType::SessionId, DataValue::UnsignedNumber(1)) - .add_typed_default(DataType::VersionNumber, DataValue::UnsignedNumber(0)) - .add_typed_default(DataType::CacheSchemaVersion, DataValue::UnsignedNumber(0)) - .add_typed_default(DataType::SyncMode, DataValue::Str("full".into())) - .add_typed_default( - DataType::Contacts, - DataValue::Array(vec![DataValue::Container(vec![])]), - ) - .add_typed_default(DataType::Communities, DataValue::Array(vec![])) - .add_typed_default(DataType::Calls, DataValue::Array(vec![])) - .add_typed_default(DataType::Messages, DataValue::Array(vec![])); - - assert!(prepare_initial_state_ack(&malformed, &ids).is_err()); - assert_eq!( - ids.next().unwrap(), - 1, - "no acknowledgement ID was allocated" - ); - } } #[tauri::command] -pub async fn mtp_request(type_name: String, data: Value) -> Result { - manager().request(&type_name, data).await +pub async fn mtp_request(type_name: String, data: Value, id: Option) -> Result { + manager().request(&type_name, data, id).await } #[tauri::command] diff --git a/apps/tauri/src/qrCodeScanner.tsx b/apps/tauri/src/qrCodeScanner.tsx new file mode 100644 index 0000000..fa3f3c7 --- /dev/null +++ b/apps/tauri/src/qrCodeScanner.tsx @@ -0,0 +1,38 @@ +import { + scan, + Format, + requestPermissions, +} from "@tauri-apps/plugin-barcode-scanner"; +import { Button } from "@methanium/ui"; + +import { toast } from "@tensamin/shared/log"; + +export default function QrCodeScanner({ + onData, +}: { + onData: (data: string) => void; +}) { + return ( + + ); +} diff --git a/apps/web/index.html b/apps/web/index.html index 0c0644f..eef61d9 100644 --- a/apps/web/index.html +++ b/apps/web/index.html @@ -2,11 +2,8 @@ - - + + Tensamin diff --git a/apps/web/package.json b/apps/web/package.json index a6b3951..107c6f7 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -6,9 +6,9 @@ "scripts": { "format": "pnpm exec prettier --write .", "lint": "eslint src", - "dev": "vite", + "dev": "vite --port 3000 --host 0.0.0.0", "test": "vitest run --passWithNoTests", - "build": "pnpm --filter @tensamin/pwa build && pnpm run test && tsc -b && vite build", + "build": "pnpm run test && tsc -b && vite build", "preview": "cd dist && nix-shell -p python3 --run 'python3 -m http.server 3000' && cd .." }, "dependencies": { @@ -18,7 +18,6 @@ "@tanstack/react-router": "^1.170.21", "@tanstack/react-virtual": "^3.14.9", "@tauri-apps/api": "^2.11.1", - "@tensamin/pwa": "workspace:*", "@tensamin/cache": "workspace:*", "@tensamin/call": "workspace:*", "@tensamin/chat": "workspace:*", @@ -55,7 +54,6 @@ "esbuild": "^0.28.1", "eslint": "^10.8.0", "globals": "^17.9.0", - "mtp": "*", "typescript": "~6.0.3", "typescript-eslint": "^8.66.0", "vite": "^8.2.1" diff --git a/apps/web/src/components/modals/basic.tsx b/apps/web/src/components/modals/basic.tsx index dc4e48a..46eaa45 100644 --- a/apps/web/src/components/modals/basic.tsx +++ b/apps/web/src/components/modals/basic.tsx @@ -15,10 +15,7 @@ export function Basic({ user, extra, }: { - user: Pick< - User, - "Display" | "Username" | "Avatar" | "OnlineStatus" | "Status" - >; + user: User; extra?: React.ReactNode; }) { const display = user.Display || user.Username || "Unknown"; @@ -60,9 +57,8 @@ export function Basic({ -
+

{display}

-

{user.Status}

{extra}
diff --git a/apps/web/src/components/modals/profile.tsx b/apps/web/src/components/modals/profile.tsx index a4bddb2..6324ab5 100644 --- a/apps/web/src/components/modals/profile.tsx +++ b/apps/web/src/components/modals/profile.tsx @@ -4,20 +4,7 @@ import { Text } from "@methanium/ui/markdown"; import { ChevronDown, ChevronUp } from "lucide-react"; import { useState } from "react"; -export default function Profile({ - user, -}: { - user: Pick< - User, - | "UserId" - | "Display" - | "Username" - | "Avatar" - | "About" - | "IotaId" - | "PublicKey" - >; -}) { +export default function Profile({ user }: { user: User }) { const [showAdvancedInformation, setShowAdvancedInformation] = useState(false); return ( diff --git a/apps/web/src/components/navbar.tsx b/apps/web/src/components/navbar.tsx index 122f188..6c86f96 100644 --- a/apps/web/src/components/navbar.tsx +++ b/apps/web/src/components/navbar.tsx @@ -52,7 +52,6 @@ export default function Navbar({ forMobile }: { forMobile: boolean }) { return (
@@ -92,15 +91,6 @@ export default function Navbar({ forMobile }: { forMobile: boolean }) { {pathname === "/chat" && id && ( isMobile ? (

{user?.Display}

diff --git a/apps/web/src/components/screens/login/form.tsx b/apps/web/src/components/screens/login/form.tsx index c9fa041..0bbb850 100644 --- a/apps/web/src/components/screens/login/form.tsx +++ b/apps/web/src/components/screens/login/form.tsx @@ -13,11 +13,8 @@ import { useState, } from "react"; import { z } from "zod"; -import { subscribeTuFileLaunch } from "@tensamin/pwa/runtime"; -import { - parseTuFileContent, - persistMtpCredentials, -} from "@tensamin/storage/credentials"; +import { invoke, isTauri } from "@tauri-apps/api/core"; +import QrCodeScanner from "@tensamin/tauri/qrCodeScanner"; import { useNavigate } from "@tanstack/react-router"; const fetchedUser = z.object({ @@ -38,6 +35,55 @@ const formSchema = z.object({ mtp_keyring: z.string().min(1).max(92), }); +/** + * Parses a .tu file payload into credentials. + * @param rawFileContent UTF-8 file content from an uploaded .tu file. + * @returns Parsed user id and private key credentials. + */ +function parseTuFileContent(rawFileContent: string): { + userId: number; + privateKey: string; + domain: string | null; +} { + if (rawFileContent.trim().length === 0) { + throw new Error("File is empty"); + } else if (!rawFileContent.includes("::")) { + throw new Error("Invalid file"); + } else if (rawFileContent.split("::").length !== 2) { + throw new Error("Invalid file"); + } + + const left = rawFileContent.split("::")[0]; + const right = rawFileContent.split("::")[1]; + + if (left.length === 0) { + throw new Error("Invalid file"); + } else if (right.length === 0) { + throw new Error("Invalid file"); + } else if (isNaN(Number(left)) && !left.includes("@")) { + throw new Error("Invalid file"); + } + + const [userIdString, privateKeyValue] = rawFileContent.split("::"); + const privateKey = privateKeyValue.trim(); + const userId = isNaN(Number(userIdString)) + ? Number(userIdString.split("@")[0]) + : Number(userIdString); + + const domain = userIdString.includes("@") ? userIdString.split("@")[1] : null; + + if (!userId || !privateKey) { + throw new Error("Invalid file"); + } + + console.log({ + domain, + userId, + }); + + return { userId, privateKey, domain }; +} + export default function Form() { const isMobile = useIsMobile(); const uploadRef = useRef(null); @@ -51,12 +97,27 @@ export default function Form() { if (loginPendingRef.current) return false; loginPendingRef.current = true; try { - await persistMtpCredentials({ - storage: { load, save }, - userId, - keyring: privateKey, - domain, - }); + if (domain) await save("omega_url", `https://${domain}/`); + if (isTauri()) { + const [omegaUrl, forcedOmikronUrl, forcedOmikronPublicKey] = + await Promise.all([ + domain ? `https://${domain}/` : load("omega_url"), + load("forced_omikron_url"), + load("forced_omikron_public_key"), + ]); + await invoke("mtp_store_credentials", { + config: { + userId, + keyring: privateKey, + omegaUrl, + forcedOmikronUrl, + forcedOmikronPublicKey, + }, + }); + } + await save("mtp_keyring", privateKey, { secure: true }); + await save("session_id", Date.now()); + await save("user_id", userId); await navigate({ to: "/", replace: true }); return true; } finally { @@ -87,11 +148,6 @@ export default function Form() { [persistLogin], ); - useEffect( - () => subscribeTuFileLaunch(processDroppedFile), - [processDroppedFile], - ); - // Handle .tu files const handleFileInputChange = useCallback( async (event: ChangeEvent): Promise => { @@ -230,10 +286,32 @@ export default function Form() { return (
- {isMobile ? ( - + {isTauri() && isMobile ? ( + <> + { + if (!data.startsWith("tensamin://tu::")) { + toast("error", "Invalid QR code"); + return; + } + + const decoded = data.replace("tensamin://tu::", ""); + + try { + const { userId, privateKey, domain } = + parseTuFileContent(decoded); + + await persistLogin(userId, privateKey, domain); + } catch (error) { + log(0, "login", "red", error); + toast("error", "Failed to parse QR code data"); + } + }} + /> + + ) : (
uploadRef.current?.click()} diff --git a/apps/web/src/components/sidebar.tsx b/apps/web/src/components/sidebar.tsx index d56a4f1..7a7c58b 100644 --- a/apps/web/src/components/sidebar.tsx +++ b/apps/web/src/components/sidebar.tsx @@ -27,6 +27,7 @@ import { SelectContent, SelectItem, } from "@methanium/ui"; +import { isTauri } from "@tauri-apps/api/core"; import { useIsMobile } from "@methanium/ui"; import { MobileNavbar } from "./navbar"; @@ -34,7 +35,7 @@ import SidebarBox from "@tensamin/call/sidebarBox"; import { useShowMobileNavbar } from "@/routes/app/useShowMobileNavbar"; import { Ellipsis, Check } from "lucide-react"; import { useState } from "react"; -import { useUser, type User } from "@tensamin/user/context"; +import type { User } from "@tensamin/user/context"; import { mtp, userPresencePreferenceSchema } from "@tensamin/shared/data"; import { useMTP } from "@tensamin/mtp"; import { @@ -63,7 +64,7 @@ function StatusDialog({ saveSucceeded, setSaveSucceeded, }: { - user: Pick; + user: User; open: boolean; onOpenChange: (open: boolean) => void; send: ReturnType["send"]; @@ -76,8 +77,6 @@ function StatusDialog({ saveSucceeded: boolean; setSaveSucceeded: (value: boolean) => void; }) { - const { updateProfile, updateState } = useUser(); - return ( Cancel} /> - {selectedGroup.name} -
- ) : groups.length > 0 ? ( -
- {sortedGroups.map((group) => ( - - ))} -
- ) : null} - - {visibleUrls.length === 0 ? ( -
- {selectedGroup ? "This group is empty." : "No ungrouped media."} -
- ) : null} -
{columns.map((column, columnIndex) => (
@@ -563,7 +504,6 @@ function SavedPanel({ ariaLabel="Unsave media" defaultSaved onSavedMediaChange={onSavedMediaChange} - onSavedMediaGroupsChange={onSavedMediaGroupsChange} url={url} />
@@ -590,9 +530,6 @@ export default function GifPicker({ const [searchString, setSearchString] = useState(""); const [debouncedSearchString, setDebouncedSearchString] = useState(""); const [savedMedia, setSavedMedia] = useState([]); - const [savedMediaGroups, setSavedMediaGroups] = useState< - ChatPickerMediaGroup[] - >([]); const didLoadLastTabRef = useRef(false); const searchDebouncerRef = useRef void> | null>( null, @@ -618,13 +555,7 @@ export default function GifPicker({ useEffect(() => { if (tab !== "saved") return; - void Promise.all([ - load("chat_picker_saved_media"), - load("chat_picker_saved_media_groups"), - ]).then(([nextSavedMedia, nextGroups]) => { - setSavedMedia(nextSavedMedia); - setSavedMediaGroups(nextGroups); - }); + void load("chat_picker_saved_media").then(setSavedMedia); }, [load, tab]); useEffect(() => { @@ -696,10 +627,8 @@ export default function GifPicker({ className="flex min-h-0 w-full flex-col overflow-hidden" > diff --git a/packages/chat/src/components/input.tsx b/packages/chat/src/components/input.tsx index 469c28a..28752f0 100644 --- a/packages/chat/src/components/input.tsx +++ b/packages/chat/src/components/input.tsx @@ -2,9 +2,6 @@ import { Input, type InputController } from "@methanium/ui/markdown"; import { Card, CardHeader, - Drawer, - DrawerContent, - DrawerTrigger, Popover, PopoverContent, PopoverTrigger, @@ -21,9 +18,9 @@ import { cn, useIsMobile } from "@methanium/ui"; import { encryptChatText } from "@tensamin/crypto/chatSecret"; import { useSession } from "@tensamin/storage/session"; -import EmojiPicker from "./emoji/emojiPicker"; -import { useEmojiRanks, useRecordEmojiUse } from "./emoji/emojiRanks"; -import GifPicker from "./media/gifPicker"; +import GifPicker from "./gifPicker"; +import EmojiPicker from "./emojiPicker"; +import { useEmojiRanks, useRecordEmojiUse } from "./emojiRanks"; import ReplyBox from "./replyBox"; import { useHotkey } from "@tensamin/hotkeys"; import { editLastMessageHotkey } from "../hotkeys"; @@ -334,65 +331,42 @@ export default function InputComponent({ /> - {isMobile ? ( - - -
- -
-
- -
- { - void handleSubmit(url, true); - setGifPopoverOpen(false); - }} - /> -
-
-
- ) : ( - - ( - - )} + + ( + + )} + /> + event.stopPropagation()} + onWheelCapture={(event) => event.stopPropagation()} + style={{ + ...gifPopoverSize, + maxHeight: gifPopoverSize?.height, + }} + > +
- event.stopPropagation()} - onWheelCapture={(event) => event.stopPropagation()} - style={{ - ...gifPopoverSize, - maxHeight: gifPopoverSize?.height, + { + void handleSubmit(url, true); + setGifPopoverOpen(false); }} - > -
- { - void handleSubmit(url, true); - setGifPopoverOpen(false); - }} - /> - - - )} + /> + +
diff --git a/packages/chat/src/components/media/media.tsx b/packages/chat/src/components/media.tsx similarity index 94% rename from packages/chat/src/components/media/media.tsx rename to packages/chat/src/components/media.tsx index 1072308..a37f444 100644 --- a/packages/chat/src/components/media/media.tsx +++ b/packages/chat/src/components/media.tsx @@ -24,7 +24,7 @@ import { } from "lucide-react"; import { useState, useMemo, useEffect, useRef, type WheelEvent } from "react"; import MediaSaveButton from "./mediaSaveButton"; -import { useUserFields } from "@tensamin/user/context"; +import { type User, useUser } from "@tensamin/user/context"; const zoomLevels = [1, 1.5, 2, 3]; @@ -46,7 +46,12 @@ export default function Media({ const wheelDelta = useRef(0); const hostname = useMemo(() => new URL(link).hostname, [link]); - const { data: user } = useUserFields(senderId, ["Avatar", "Display"]); + // Get user's + const { get } = useUser(); + const [user, setUser] = useState(undefined); + useEffect(() => { + get(senderId).then(setUser); + }, [senderId, get]); const avatar = user?.Avatar ? `data:image/webp;base64,${user.Avatar}` : undefined; @@ -166,9 +171,9 @@ export default function Media({ -
+
({ - ...group, - media: group.media.filter((item) => item !== url), - })) - .filter((group) => group.id === keepGroupId || group.media.length > 0); -} - -export function assignMediaToGroup( - groups: ChatPickerMediaGroup[], - groupId: string | null, - url: string, -) { - const nextGroups = withoutMedia(groups, url, groupId ?? undefined); - - if (groupId === null) return nextGroups; - - return nextGroups.map((group) => - group.id === groupId ? { ...group, media: [url, ...group.media] } : group, - ); -} - -export function createMediaGroup( - groups: ChatPickerMediaGroup[], - id: string, - name: string, - url: string, -) { - const trimmedName = name.trim(); - - if ( - !trimmedName || - groups.some( - (group) => - group.name.toLocaleLowerCase() === trimmedName.toLocaleLowerCase(), - ) - ) { - return groups; - } - - return [ - ...withoutMedia(groups, url), - { id, name: trimmedName, media: [url] }, - ]; -} - -export function getMediaGroupId(groups: ChatPickerMediaGroup[], url: string) { - return groups.find((group) => group.media.includes(url))?.id ?? null; -} - -export function getUngroupedMedia( - savedMedia: string[], - groups: ChatPickerMediaGroup[], -) { - const groupedMedia = new Set(groups.flatMap((group) => group.media)); - - return savedMedia.filter((url) => !groupedMedia.has(url)); -} diff --git a/packages/chat/src/components/media/mediaSaveButton.tsx b/packages/chat/src/components/media/mediaSaveButton.tsx deleted file mode 100644 index e585eae..0000000 --- a/packages/chat/src/components/media/mediaSaveButton.tsx +++ /dev/null @@ -1,238 +0,0 @@ -import { - Button, - cn, - Dialog, - DialogContent, - DialogFooter, - DialogHeader, - DialogTitle, - Input, - Label, - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, - useIsMobile, -} from "@methanium/ui"; -import type { ChatPickerMediaGroup } from "@tensamin/shared/data"; -import { useStorage } from "@tensamin/storage/context"; -import { Ellipsis, Star } from "lucide-react"; -import { useEffect, useState } from "react"; -import { - assignMediaToGroup, - createMediaGroup, - getMediaGroupId, -} from "./mediaGroups"; - -export default function MediaSaveButton({ - ariaLabel, - className, - defaultSaved = false, - onSavedMediaChange, - onSavedMediaGroupsChange, - url, -}: { - ariaLabel?: string; - className?: string; - defaultSaved?: boolean; - onSavedMediaChange?: (savedMedia: string[]) => void; - onSavedMediaGroupsChange?: (groups: ChatPickerMediaGroup[]) => void; - url: string; -}) { - const { load, save } = useStorage(); - const isMobile = useIsMobile(); - const [savedMedia, setSavedMedia] = useState(null); - const [groups, setGroups] = useState(null); - const [dialogOpen, setDialogOpen] = useState(false); - const [selectedGroupId, setSelectedGroupId] = useState(null); - const [newGroupName, setNewGroupName] = useState(""); - const isSaved = savedMedia ? savedMedia.includes(url) : defaultSaved; - const sortedGroups = [...(groups ?? [])].sort((left, right) => - left.name.localeCompare(right.name), - ); - const normalizedNewGroupName = newGroupName.trim().toLocaleLowerCase(); - const canCreateGroup = - normalizedNewGroupName.length > 0 && - !(groups ?? []).some( - (group) => group.name.toLocaleLowerCase() === normalizedNewGroupName, - ); - - useEffect(() => { - void Promise.all([ - load("chat_picker_saved_media"), - load("chat_picker_saved_media_groups"), - ]).then(([nextSavedMedia, nextGroups]) => { - setSavedMedia(nextSavedMedia); - setGroups(nextGroups); - }); - }, [load]); - - async function handleSaveClick(event: React.MouseEvent) { - event.stopPropagation(); - - const [currentSavedMedia, currentGroups] = await Promise.all([ - load("chat_picker_saved_media"), - load("chat_picker_saved_media_groups"), - ]); - const willUnsave = currentSavedMedia.includes(url); - const nextSavedMedia = willUnsave - ? currentSavedMedia.filter((item) => item !== url) - : [url, ...currentSavedMedia]; - - setSavedMedia(nextSavedMedia); - onSavedMediaChange?.(nextSavedMedia); - if (willUnsave) { - const nextGroups = assignMediaToGroup(currentGroups, null, url); - setGroups(nextGroups); - onSavedMediaGroupsChange?.(nextGroups); - await Promise.all([ - save("chat_picker_saved_media", nextSavedMedia), - save("chat_picker_saved_media_groups", nextGroups), - ]); - return; - } - - await save("chat_picker_saved_media", nextSavedMedia); - } - - async function handleGroupClick(event: React.MouseEvent) { - event.stopPropagation(); - - const currentGroups = await load("chat_picker_saved_media_groups"); - setGroups(currentGroups); - setSelectedGroupId(getMediaGroupId(currentGroups, url)); - setNewGroupName(""); - setDialogOpen(true); - } - - async function handleGroupSave() { - const currentGroups = await load("chat_picker_saved_media_groups"); - const nextGroups = assignMediaToGroup(currentGroups, selectedGroupId, url); - - setGroups(nextGroups); - onSavedMediaGroupsChange?.(nextGroups); - await save("chat_picker_saved_media_groups", nextGroups); - setDialogOpen(false); - } - - async function handleCreateGroup() { - if (!canCreateGroup) return; - - const currentGroups = await load("chat_picker_saved_media_groups"); - const groupId = crypto.randomUUID(); - const nextGroups = createMediaGroup( - currentGroups, - groupId, - newGroupName, - url, - ); - - setGroups(nextGroups); - setSelectedGroupId(groupId); - setNewGroupName(""); - onSavedMediaGroupsChange?.(nextGroups); - await save("chat_picker_saved_media_groups", nextGroups); - setDialogOpen(false); - } - - return ( - <> -
- - {isSaved ? ( - - ) : null} -
- - - event.stopPropagation()}> - - Organize saved media - - -
-
- - -
- -
- -
- setNewGroupName(event.target.value)} - onKeyDown={(event) => { - if (event.key === "Enter") void handleCreateGroup(); - }} - /> - -
-
-
- - - - - -
-
- - ); -} diff --git a/packages/chat/src/components/mediaSaveButton.tsx b/packages/chat/src/components/mediaSaveButton.tsx new file mode 100644 index 0000000..99fbcec --- /dev/null +++ b/packages/chat/src/components/mediaSaveButton.tsx @@ -0,0 +1,63 @@ +import { Button, cn, useIsMobile } from "@methanium/ui"; +import { useStorage } from "@tensamin/storage/context"; +import { Star } from "lucide-react"; +import { useEffect, useState } from "react"; + +export default function MediaSaveButton({ + ariaLabel, + className, + defaultSaved = false, + onSavedMediaChange, + url, +}: { + ariaLabel?: string; + className?: string; + defaultSaved?: boolean; + onSavedMediaChange?: (savedMedia: string[]) => void; + url: string; +}) { + const { load, save } = useStorage(); + const isMobile = useIsMobile(); + const [savedMedia, setSavedMedia] = useState(null); + const isSaved = savedMedia ? savedMedia.includes(url) : defaultSaved; + + useEffect(() => { + void load("chat_picker_saved_media").then(setSavedMedia); + }, [load]); + + async function handleClick(event: React.MouseEvent) { + event.stopPropagation(); + + const currentSavedMedia = + savedMedia ?? (await load("chat_picker_saved_media")); + const nextSavedMedia = currentSavedMedia.includes(url) + ? currentSavedMedia.filter((item) => item !== url) + : [url, ...currentSavedMedia]; + + setSavedMedia(nextSavedMedia); + onSavedMediaChange?.(nextSavedMedia); + void save("chat_picker_saved_media", nextSavedMedia); + } + + return ( + + ); +} diff --git a/packages/chat/src/components/message.tsx b/packages/chat/src/components/message.tsx index cbcd37e..515b39d 100644 --- a/packages/chat/src/components/message.tsx +++ b/packages/chat/src/components/message.tsx @@ -1,7 +1,7 @@ import type { RawMessage } from "../values"; import { AlertTriangle, Check, CheckLine, RefreshCw } from "lucide-react"; import { memo, useCallback, useEffect, useRef, useState } from "react"; -import { type SelectedUser, useUserFields } from "@tensamin/user/context"; +import type { User } from "@tensamin/user/context"; import { Avatar, @@ -13,14 +13,15 @@ import { Skeleton, } from "@methanium/ui"; import MessageContextMenu from "./messageContextMenu"; -import Media from "./media/media"; +import Media from "./media"; import { useStorage } from "@tensamin/storage/context"; import { useMTP } from "@tensamin/mtp"; import { getMessage, useChat } from "../context"; import { decryptChatText, encryptChatText } from "@tensamin/crypto/chatSecret"; import { log, toast } from "@tensamin/shared/log"; import { Emoji, Input, normalizeShortcode, Text } from "@methanium/ui/markdown"; -import { useRecordEmojiUse } from "./emoji/emojiRanks"; +import { useRecordEmojiUse } from "./emojiRanks"; +import { useUser } from "@tensamin/user/context"; import ReplyBox from "./replyBox"; import { useHotkey } from "@tensamin/hotkeys"; import { cancelMessageEditHotkey } from "../hotkeys"; @@ -39,7 +40,7 @@ function MessageComponent({ decryptionFailed?: boolean; }; onSetEditing: (editing: boolean) => void; - user: SelectedUser | null; + user: User | null; }) { const actuallyFailed = (message.failed && message.MessageState === "awaiting") || @@ -149,14 +150,13 @@ function MessageComponent({ removeReaction, replyTo, } = useChat(); + const { get: getUser } = useUser(); const [replyMessage, setReplyMessage] = useState(null); - const { data: replyUser } = useUserFields(replyMessage?.SenderId ?? null, [ - "Avatar", - "Display", - ]); + const [replyUser, setReplyUser] = useState(null); useEffect(() => { if (!message.ReplyId || !ownId || !chatSecret) { setReplyMessage(null); + setReplyUser(null); return; } @@ -168,20 +168,25 @@ function MessageComponent({ send, }) .then(async (reply) => { - const Content = await decryptChatText(chatSecret, reply.Content); + const [Content, author] = await Promise.all([ + decryptChatText(chatSecret, reply.Content), + getUser(reply.SenderId), + ]); if (!active) return; setReplyMessage({ ...reply, Content }); + setReplyUser(author); }) .catch((err) => { if (!active) return; setReplyMessage(null); + setReplyUser(null); log(1, "chat", "red", "Failed to get replied-to message", err); }); return () => { active = false; }; - }, [chatSecret, message.ReplyId, ownId, send, userId]); + }, [chatSecret, getUser, message.ReplyId, ownId, send, userId]); const recordUse = useRecordEmojiUse(); const editingRef = useRef(editing); const onSetEditingRef = useRef(onSetEditing); @@ -381,8 +386,8 @@ function MessageComponent({
)} {editing ? ( -
- +
+ + ))} +
+ ))} +
+ +
+
+ ); +} diff --git a/packages/settings/src/manifest.ts b/packages/settings/src/manifest.ts index 1afdd5a..2daf8ff 100644 --- a/packages/settings/src/manifest.ts +++ b/packages/settings/src/manifest.ts @@ -1,4 +1,3 @@ -import Accessibility from "./pages/accessibility"; import Cache from "./pages/cache"; import Call from "./pages/call"; import Chat from "./pages/chat"; @@ -8,24 +7,40 @@ import Profile from "./pages/profile"; import Security from "./pages/security"; import Theme from "./pages/theme"; import Hotkeys from "./pages/hotkeys"; -import { settingsNavigation } from "./navigation"; - -const pageComponents = { - profile: Profile, - security: Security, - chat: Chat, - call: Call, - cache: Cache, - theme: Theme, - accessibility: Accessibility, - hotkeys: Hotkeys, - licenses: Licenses, -} as const; export const settingsPages = [ { path: "/", component: Index }, - ...settingsNavigation.map((page) => ({ - ...page, - component: pageComponents[page.path], - })), + { + category: "account", + path: "profile", + label: "Profile", + component: Profile, + }, + { + category: "account", + path: "security", + label: "Security", + component: Security, + }, + { category: "general", path: "chat", label: "Chat", component: Chat }, + { category: "general", path: "call", label: "Call", component: Call }, + { category: "application", path: "cache", label: "Cache", component: Cache }, + { category: "application", path: "theme", label: "Theme", component: Theme }, + { + category: "application", + path: "hotkeys", + label: "Hotkeys", + component: Hotkeys, + }, + { + category: "application", + path: "licenses", + label: "Licenses", + component: Licenses, + }, ] as const; + +export const settingsNavigation = settingsPages.filter( + (page): page is Exclude<(typeof settingsPages)[number], { path: "/" }> => + page.path !== "/", +); diff --git a/packages/settings/src/navigation.ts b/packages/settings/src/navigation.ts deleted file mode 100644 index b47fae9..0000000 --- a/packages/settings/src/navigation.ts +++ /dev/null @@ -1,31 +0,0 @@ -export const settingsNavigation = [ - { - category: "account", - path: "profile", - label: "Profile", - }, - { - category: "account", - path: "security", - label: "Security", - }, - { category: "general", path: "chat", label: "Chat" }, - { category: "general", path: "call", label: "Call" }, - { category: "application", path: "cache", label: "Cache" }, - { category: "application", path: "theme", label: "Theme" }, - { - category: "application", - path: "accessibility", - label: "Accessibility", - }, - { - category: "application", - path: "hotkeys", - label: "Hotkeys", - }, - { - category: "application", - path: "licenses", - label: "Licenses", - }, -] as const; diff --git a/packages/settings/src/pages/accessibility.tsx b/packages/settings/src/pages/accessibility.tsx deleted file mode 100644 index 026c3b1..0000000 --- a/packages/settings/src/pages/accessibility.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { Button, Label, Slider } from "@methanium/ui"; -import { invoke, isTauri } from "@tauri-apps/api/core"; -import { RotateCcw } from "lucide-react"; -import { useEffect, useState } from "react"; - -const DEFAULT_INITIAL_SCALE = 290; -const MIN_INITIAL_SCALE = 210; -const isAndroid = isTauri() && /Android/.test(navigator.userAgent); - -export default function Page() { - const [initialScale, setInitialScale] = useState(DEFAULT_INITIAL_SCALE); - const [loading, setLoading] = useState(isAndroid); - - useEffect(() => { - if (!isAndroid) return; - - let active = true; - void invoke("accessibility_get_initial_scale") - .then((scale) => { - if (active) setInitialScale(scale); - }) - .catch((error: unknown) => { - console.error("Failed to load the Android initial scale", error); - }) - .finally(() => { - if (active) setLoading(false); - }); - - return () => { - active = false; - }; - }, []); - - if (!isAndroid) return null; - - function updateInitialScale(nextScale: number) { - setInitialScale(nextScale); - void invoke("accessibility_set_initial_scale", { - initialScale: nextScale, - }).catch((error: unknown) => { - console.error("Failed to update the Android initial scale", error); - }); - } - - return ( -
-
- - - {initialScale}% - -
-
- { - const nextScale = Array.isArray(value) ? value[0] : value; - if (nextScale !== undefined) updateInitialScale(nextScale); - }} - /> - -
-
- ); -} diff --git a/packages/settings/src/pages/index.tsx b/packages/settings/src/pages/index.tsx index b5d04e3..803a0c1 100644 --- a/packages/settings/src/pages/index.tsx +++ b/packages/settings/src/pages/index.tsx @@ -1,4 +1,4 @@ -import { SettingsSidebar } from "../sidebar"; +import { SettingsSidebar } from "../layout"; export default function Page() { return ( diff --git a/packages/settings/src/pages/profile.tsx b/packages/settings/src/pages/profile.tsx index dc8de3c..7f8cd5a 100644 --- a/packages/settings/src/pages/profile.tsx +++ b/packages/settings/src/pages/profile.tsx @@ -11,25 +11,10 @@ import { Input, useIsMobile, } from "@methanium/ui"; -import { - useUser, - useUserFields, - type SelectedUser, -} from "@tensamin/user/context"; +import { useUser, type User } from "@tensamin/user/context"; import { Check } from "lucide-react"; import { useEffect, useRef, useState } from "react"; -const PROFILE_FIELDS = [ - "Avatar", - "Display", - "Username", - "About", - "UserId", -] as const; -type ProfileDraft = Partial< - Omit, "UserId"> ->; - async function prepImage( file: File, size = 300, @@ -59,13 +44,12 @@ async function prepImage( } export default function Page() { - const { updateProfile } = useUser(); + const { get, update } = useUser(); const { load } = useStorage(); const { send } = useMTP(); const isMobile = useIsMobile(); - const [userId, setUserId] = useState(null); - const { data: currentUser } = useUserFields(userId, PROFILE_FIELDS); - const [draftUser, setDraftUser] = useState({}); + const [currentUser, setCurrentUser] = useState(null); + const [draftUser, setDraftUser] = useState>({}); const [errorMessage, setErrorMessage] = useState(""); const [saveSucceeded, setSaveSucceeded] = useState(false); const avatarUploadRef = useRef(null); @@ -73,23 +57,18 @@ export default function Page() { const effectiveAvatar = draftUser.Avatar === "none" ? undefined : draftUser.Avatar; const updateDraftUser = ( - updater: (previous: ProfileDraft) => ProfileDraft, + updater: (previous: Partial) => Partial, ) => { setSaveSucceeded(false); setErrorMessage(""); setDraftUser(updater); }; useEffect(() => { - void load("user_id").then(setUserId); - }, [load]); + void (async () => setCurrentUser(await get(await load("user_id"))))(); + }, [get, load]); useEffect(() => { if (!currentUser || draftInitializedRef.current) return; - setDraftUser({ - Avatar: currentUser.Avatar, - Display: currentUser.Display, - Username: currentUser.Username, - About: currentUser.About, - }); + setDraftUser(currentUser); draftInitializedRef.current = true; }, [currentUser]); async function handleAvatarUpload(file: File) { @@ -148,7 +127,7 @@ export default function Page() { onChange={(event) => updateDraftUser((previous) => ({ ...previous, - Display: event.target.value, + display: event.target.value, })) } placeholder="Display Name" @@ -159,7 +138,7 @@ export default function Page() { onChange={(event) => updateDraftUser((previous) => ({ ...previous, - Username: event.target.value, + username: event.target.value, })) } placeholder="Username" @@ -171,7 +150,7 @@ export default function Page() { fontSize=".875rem" placeholder="About Me" setValue={(value) => - updateDraftUser((previous) => ({ ...previous, About: value })) + updateDraftUser((previous) => ({ ...previous, about: value })) } value={draftUser.About || ""} /> @@ -201,7 +180,13 @@ export default function Page() { if (response.type.startsWith("Error")) { throw new Error(response.type); } - await updateProfile(currentUser.UserId, validation.data); + const updatedUser = mtp.GetUserData.response.parse({ + ...currentUser, + ...draftUser, + }); + await update(updatedUser); + setCurrentUser(updatedUser); + setDraftUser(updatedUser); setSaveSucceeded(true); setErrorMessage(""); } catch (error) { diff --git a/packages/settings/src/sidebar.tsx b/packages/settings/src/sidebar.tsx deleted file mode 100644 index 3a2155e..0000000 --- a/packages/settings/src/sidebar.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { Button, ClearStorageButton, cn } from "@methanium/ui"; -import { useNavigate } from "@tanstack/react-router"; - -import { settingsNavigation } from "./navigation"; - -export function SettingsSidebar({ - mobile = false, - className, -}: { - mobile?: boolean; - className?: string; -}) { - const navigate = useNavigate(); - const categories = [ - ...new Set(settingsNavigation.map((page) => page.category)), - ]; - - return ( -
- {categories.map((category) => ( -
-

{category}

- {settingsNavigation - .filter((page) => page.category === category) - .map((page) => ( - - ))} -
- ))} -
- -
-
- ); -} diff --git a/packages/shared/src/data.ts b/packages/shared/src/data.ts index eed6e7e..9f16723 100644 --- a/packages/shared/src/data.ts +++ b/packages/shared/src/data.ts @@ -260,13 +260,20 @@ export const mtp = { UserState: clientUserStateSchema, }), }, + SetUserState: { + request: z.object({ + UserState: userPresencePreferenceSchema, + }), + response: z.object({ + UserState: userPresencePreferenceSchema, + }), + }, ChangeUserData: { request: z .object({ About: userFields.About, Avatar: userFields.Avatar, Display: userFields.Display, - OnlineStatus: userPresencePreferenceSchema, PublicKey: userFields.PublicKey, Status: userFields.Status, Username: userFields.Username, @@ -497,12 +504,6 @@ export const mtp = { export type MTP = typeof mtp; // Storage -export type ChatPickerMediaGroup = { - id: string; - name: string; - media: string[]; -}; - export interface Storage extends SettingsStorageDefaults { session_id: number; user_id: number; @@ -555,7 +556,6 @@ export interface Storage extends SettingsStorageDefaults { theme_design: ThemeDesign; chat_trusted_domains: string[]; chat_picker_saved_media: string[]; - chat_picker_saved_media_groups: ChatPickerMediaGroup[]; chat_picker_last_tab: "gif" | "meme" | "saved"; chat_picker_size: { width: number; @@ -580,11 +580,20 @@ export const storageDefaults: Storage = { analytics_done: false, ...settingsStorageDefaults, legal_docs: { + eula: { + version: "0.0", + hash: "000000000000", + unix: 0, + }, tos: { - hash: "0000000000000000000000000000000000000000000000000000000000000000", + version: "0.0", + hash: "000000000000", + unix: 0, }, pp: { - hash: "0000000000000000000000000000000000000000000000000000000000000000", + version: "0.0", + hash: "000000000000", + unix: 0, }, }, cached_contacts: [], @@ -638,7 +647,6 @@ export const storageDefaults: Storage = { "media4.giphy.com", ], chat_picker_saved_media: [], - chat_picker_saved_media_groups: [], chat_picker_last_tab: "gif", chat_picker_size: null, reactions: { diff --git a/packages/shared/src/features/legal/schema.ts b/packages/shared/src/features/legal/schema.ts index 26d35b1..cbdbf4e 100644 --- a/packages/shared/src/features/legal/schema.ts +++ b/packages/shared/src/features/legal/schema.ts @@ -1,10 +1,13 @@ import { z } from "zod"; const legalDocSchema = z.object({ - hash: z.string().regex(/^[a-f0-9]{64}$/), + version: z.string().regex(/^\d+\.\d+$/), + hash: z.string().regex(/^[a-f0-9]{12}$/), + unix: z.number().int().positive(), }); export const legalDocsSchema = z.object({ + eula: legalDocSchema, tos: legalDocSchema, pp: legalDocSchema, }); diff --git a/packages/storage/package.json b/packages/storage/package.json index dce1554..9e19759 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -6,9 +6,7 @@ "exports": { "./session": "./src/session.tsx", "./context": "./src/context.tsx", - "./secure": "./src/secure.ts", - "./browserSecure": "./src/browserSecure.ts", - "./credentials": "./src/credentials.ts" + "./secure": "./src/secure.ts" }, "scripts": { "format": "pnpm exec prettier --write .", diff --git a/packages/storage/src/browserSecure.ts b/packages/storage/src/browserSecure.ts deleted file mode 100644 index 494b5f0..0000000 --- a/packages/storage/src/browserSecure.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { getDatabaseEntry } from "@tensamin/shared/indexedDb"; - -type SecureEnvelope = { - __tensaminSecure: 1; - version: 1; - iv: string; - data: string; -}; - -function base64ToBytes(value: string) { - const binary = atob(value); - return Uint8Array.from(binary, (character) => character.charCodeAt(0)); -} - -function isSecureEnvelope(value: unknown): value is SecureEnvelope { - if (!value || typeof value !== "object") return false; - const envelope = value as Partial; - return ( - envelope.__tensaminSecure === 1 && - envelope.version === 1 && - typeof envelope.iv === "string" && - typeof envelope.data === "string" - ); -} - -export async function loadSecureBrowserValue(key: string) { - const stored = await getDatabaseEntry("storage", key); - if (stored === undefined || !isSecureEnvelope(stored)) { - return stored as T | undefined; - } - - const masterKey = await getDatabaseEntry("keys", "master-v1"); - if (!masterKey) throw new Error("Secure storage key is unavailable."); - const plaintext = await crypto.subtle.decrypt( - { name: "AES-GCM", iv: base64ToBytes(stored.iv) }, - masterKey, - base64ToBytes(stored.data), - ); - return JSON.parse(new TextDecoder().decode(plaintext)) as T; -} diff --git a/packages/storage/src/context.tsx b/packages/storage/src/context.tsx index 407adfe..27d8759 100644 --- a/packages/storage/src/context.tsx +++ b/packages/storage/src/context.tsx @@ -30,7 +30,7 @@ import { export type SaveOptions = { secure?: boolean }; -export interface StorageContextValue { +interface StorageContextValue { load(key: K): Promise; save( key: K, diff --git a/packages/storage/src/credentials.ts b/packages/storage/src/credentials.ts deleted file mode 100644 index 7562992..0000000 --- a/packages/storage/src/credentials.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { invoke, isTauri } from "@tauri-apps/api/core"; - -import type { StorageContextValue } from "./context"; - -export function parseTuFileContent(rawFileContent: string): { - userId: number; - privateKey: string; - domain: string | null; -} { - const content = rawFileContent.trim(); - const separator = content.indexOf("::"); - if (separator <= 0 || separator !== content.lastIndexOf("::")) { - throw new Error("Invalid file"); - } - - const identity = content.slice(0, separator); - const privateKey = content.slice(separator + 2).trim(); - const [userIdValue, domain, ...extraDomainParts] = identity.split("@"); - const userId = Number(userIdValue); - if ( - !Number.isSafeInteger(userId) || - userId <= 0 || - !privateKey || - extraDomainParts.length > 0 || - (identity.includes("@") && !domain) - ) { - throw new Error("Invalid file"); - } - - return { userId, privateKey, domain: domain ?? null }; -} - -export async function persistMtpCredentials({ - storage, - userId, - keyring, - domain, -}: { - storage: Pick; - userId: number; - keyring: string; - domain?: string | null; -}) { - const omegaUrl = domain - ? `https://${domain}/` - : await storage.load("omega_url"); - if (domain) await storage.save("omega_url", omegaUrl); - - if (isTauri()) { - const [forcedOmikronUrl, forcedOmikronPublicKey] = await Promise.all([ - storage.load("forced_omikron_url"), - storage.load("forced_omikron_public_key"), - ]); - await invoke("mtp_store_credentials", { - config: { - userId, - keyring, - omegaUrl, - forcedOmikronUrl, - forcedOmikronPublicKey, - }, - }); - } - - await storage.save("mtp_keyring", keyring, { secure: true }); - await storage.save("session_id", Date.now()); - await storage.save("user_id", userId); -} diff --git a/packages/storage/src/secure.ts b/packages/storage/src/secure.ts index 367c494..283d5c0 100644 --- a/packages/storage/src/secure.ts +++ b/packages/storage/src/secure.ts @@ -4,7 +4,10 @@ import { getDatabaseEntry, setDatabaseEntry } from "@tensamin/shared/indexedDb"; export type SecureStorageStatus = { backend: - "electron-keyring" | "application-storage" | "webcrypto" | "indexeddb"; + | "electron-keyring" + | "application-storage" + | "webcrypto" + | "indexeddb"; secure: boolean; reason?: string; }; @@ -68,12 +71,7 @@ async function getKey() { if (!globalThis.crypto?.subtle || typeof indexedDB === "undefined") { return null; } - if ( - typeof window !== "undefined" && - window.tensaminDesktop?.secureStorage - ) { - return loadElectronKey(); - } + if (window.tensaminDesktop?.secureStorage) return loadElectronKey(); return loadBrowserKey(); })().catch(() => null); return keyPromise; @@ -122,10 +120,7 @@ export async function decodeSecureValue(value: unknown): Promise { } export async function getSecureStorageStatus(): Promise { - const desktop = - typeof window === "undefined" - ? undefined - : window.tensaminDesktop?.secureStorage; + const desktop = window.tensaminDesktop?.secureStorage; if (desktop?.getStatus) { const status = await desktop.getStatus(); if (status.available) return { backend: "electron-keyring", secure: true }; diff --git a/packages/storage/todo.md b/packages/storage/todo.md index 244fc2c..761fd8e 100644 --- a/packages/storage/todo.md +++ b/packages/storage/todo.md @@ -1 +1,2 @@ - Add `notifications: number` to contacts +- Store private key in a device bound session diff --git a/packages/user/package.json b/packages/user/package.json index 956cd0d..6c6a9b5 100644 --- a/packages/user/package.json +++ b/packages/user/package.json @@ -11,7 +11,6 @@ "scripts": { "format": "pnpm exec prettier --write .", "lint": "eslint src", - "test": "vitest run", "build": "tsc -p tsconfig.json --noEmit" }, "dependencies": { diff --git a/packages/user/src/context.tsx b/packages/user/src/context.tsx index 8c41aa4..be741f4 100644 --- a/packages/user/src/context.tsx +++ b/packages/user/src/context.tsx @@ -4,37 +4,24 @@ import { useCallback, useContext, useEffect, - useMemo, useRef, useState, - useSyncExternalStore, } from "react"; -import { useMTP } from "@tensamin/mtp"; +import { useMTP, type ProtocolMessage } from "@tensamin/mtp"; import { clientUserStateSchema, mtp as schemas, publicUserStateSchema, + userStateEntrySchema, } from "@tensamin/shared/data"; import type z from "zod"; import { createCache } from "@tensamin/cache"; import { useStorage } from "@tensamin/storage/context"; import { useSession } from "@tensamin/storage/session"; -import { getChangedUserFields, selectUserFields } from "./selection"; - -export { getChangedUserFields, selectUserFields } from "./selection"; export type User = z.infer; type ClientUserState = z.infer; -export type UserField = keyof User; -export type UserFields = readonly [UserField, ...UserField[]]; -export type SelectedUser = Readonly< - Pick ->; -export type UserProfilePatch = Omit< - z.infer, - "OnlineStatus" ->; export function mergeTransientPresence( user: T, @@ -47,22 +34,8 @@ export function mergeTransientPresence( const USER_CACHE_MAX_AGE = 5 * 60 * 1000; interface contextValue { - get( - userId: number, - fields: Fields, - ): Promise>; - peek( - userId: number, - fields: Fields, - ): SelectedUser | undefined; - subscribe( - userId: number, - fields: readonly UserField[], - listener: () => void, - ): () => void; - getVersion(userId: number, fields: readonly UserField[]): string; - updateProfile(userId: number, patch: UserProfilePatch): Promise; - updateState(userId: number, state: ClientUserState): void; + get(userId: number): Promise; + update(user: User): Promise; } const UserContext = createContext(undefined); @@ -75,24 +48,16 @@ const UserContext = createContext(undefined); export default function UserProvider(props: { children: ReactNode }) { const storageRef = useRef>({}); const pendingRef = useRef | undefined>>({}); - const profileUpdateQueuesRef = useRef(new Map>()); - const profileGenerationsRef = useRef(new Map()); const checkedAtRef = useRef>({}); const presenceRef = useRef(new Map()); const durableProfileRef = useRef>({}); - const listenersRef = useRef( - new Map< - number, - Set<{ fields: ReadonlySet; listener: () => void }> - >(), - ); - const revisionsRef = useRef(new Map>()); - const { send, subscribe: subscribeMTP } = useMTP(); + const { send, subscribePush } = useMTP(); const { load } = useStorage(); const { contacts } = useSession(); const [accountId, setAccountId] = useState(null); - const accountIdRef = useRef(null); + const [cacheVersion, setCacheVersion] = useState(0); + const [sessionId, setSessionId] = useState(null); const contactsRef = useRef(contacts); const initialStatesRef = useRef( new Map>(), @@ -106,110 +71,91 @@ export default function UserProvider(props: { children: ReactNode }) { return mergeTransientPresence(user, presenceRef.current); }, []); - const publishUser = useCallback((userId: number, user?: User) => { - const previous = storageRef.current[userId]; - if (user) storageRef.current[userId] = user; - else delete storageRef.current[userId]; - - const changedFields = getChangedUserFields(previous, user); - if (changedFields.length === 0) return; - - let revisions = revisionsRef.current.get(userId); - if (!revisions) { - revisions = new Map(); - revisionsRef.current.set(userId, revisions); - } - for (const field of changedFields) { - revisions.set(field, (revisions.get(field) ?? 0) + 1); - } - - const changed = new Set(changedFields); - for (const entry of listenersRef.current.get(userId) ?? []) { - if ([...entry.fields].some((field) => changed.has(field))) { - entry.listener(); - } - } - }, []); - - const installProfile = useCallback( - (profile: User) => { - durableProfileRef.current[profile.UserId] = profile; - publishUser(profile.UserId, mergeUserPresence(profile)); - }, - [mergeUserPresence, publishUser], - ); - const applyUserState = useCallback( (userId: number, state: ClientUserState, privateState = false) => { - const currentAccountId = accountIdRef.current; const known = - userId === currentAccountId || - durableProfileRef.current[userId] !== undefined || + userId === accountId || contactsRef.current.some((contact) => contact.UserId === userId); if (!known) return false; - if (state === "user_invisible" && userId !== currentAccountId) - return false; - if (userId === currentAccountId && !privateState) return false; - if (presenceRef.current.get(userId) === state) return true; + if (state === "user_invisible" && userId !== accountId) return false; + if (userId === accountId && !privateState) return false; presenceRef.current.set(userId, state); - const profile = durableProfileRef.current[userId]; - if (profile) publishUser(userId, mergeUserPresence(profile)); + const current = storageRef.current[userId]; + if (current) storageRef.current[userId] = mergeUserPresence(current); + setCacheVersion((version) => version + 1); return true; }, - [mergeUserPresence, publishUser], + [accountId, mergeUserPresence], ); - const removePresence = useCallback( - (userId: number) => { - const removed = presenceRef.current.delete(userId); - initialStatesRef.current.delete(userId); - delete checkedAtRef.current[userId]; - if (!removed) return; - const profile = durableProfileRef.current[userId]; - if (profile) publishUser(userId, profile); + const removePresence = useCallback((userId: number) => { + presenceRef.current.delete(userId); + initialStatesRef.current.delete(userId); + delete checkedAtRef.current[userId]; + setCacheVersion((version) => version + 1); + }, []); + + const handleStatePush = useCallback( + async (message: ProtocolMessage) => { + if (!accountId || !sessionId) return; + const data = message.data as Record; + if (message.type === "GetStates") { + if (Number(data.SessionId) !== sessionId) { + return; + } + if (Array.isArray(data.MissingUserIds)) { + for (const userId of data.MissingUserIds) { + if (typeof userId === "number") removePresence(userId); + } + } + if (!Array.isArray(data.UserStates)) return; + for (const entry of data.UserStates) { + const parsed = userStateEntrySchema.safeParse(entry); + if (!parsed.success) continue; + if (parsed.data.UserId === accountId) continue; + initialStatesRef.current.set( + parsed.data.UserId, + parsed.data.UserState, + ); + if (applyUserState(parsed.data.UserId, parsed.data.UserState)) { + initialStatesRef.current.delete(parsed.data.UserId); + } + } + return; + } + if (message.type !== "ClientChanged") return; + if (Number(data.SessionId) !== sessionId) return; + const parsed = schemas.ClientChanged.response.safeParse(data); + if (!parsed.success) return; + applyUserState(parsed.data.UserId, parsed.data.UserState, true); }, - [publishUser], + [accountId, applyUserState, removePresence, sessionId], ); useEffect(() => { void load("user_id").then((accountId) => { - accountIdRef.current = accountId; setAccountId(accountId); }); - }, [load]); - - const getAccountId = useCallback(async () => { - if (accountIdRef.current !== null) return accountIdRef.current; - const value = await load("user_id"); - accountIdRef.current = value; - return value; + void load("session_id").then((value) => { + setSessionId(value); + }); }, [load]); useEffect(() => { - if (!accountId) return; - const unsubscribeStates = subscribeMTP("GetStates", ({ data }) => { - for (const userId of data.MissingUserIds ?? []) removePresence(userId); - for (const entry of data.UserStates) { - if (!entry || entry.UserId === accountId) continue; - initialStatesRef.current.set(entry.UserId, entry.UserState); - if (applyUserState(entry.UserId, entry.UserState)) { - initialStatesRef.current.delete(entry.UserId); - } - } - }); - const unsubscribeChanged = subscribeMTP("ClientChanged", ({ data }) => { - applyUserState(data.UserId, data.UserState, true); - }); - return () => { - unsubscribeStates(); - unsubscribeChanged(); - }; - }, [accountId, applyUserState, removePresence, subscribeMTP]); + if (!accountId || !sessionId) return; + return subscribePush(handleStatePush); + }, [accountId, handleStatePush, sessionId, subscribePush]); - const loadUser = useCallback( + /** + * Executes get. + * @param userId Parameter userId. + * @returns Promise. + */ + const get = useCallback( async (userId: number): Promise => { + void cacheVersion; if (userId == null) { throw new Error("userId is required"); } @@ -220,45 +166,39 @@ export default function UserProvider(props: { children: ReactNode }) { } const request = (async () => { - const cache = createCache(String(await getAccountId())); + const cache = createCache(String(accountId ?? userId)); const cachedValue = - durableProfileRef.current[userId] ?? - (await cache.profiles.get(userId)); + storageRef.current[userId] ?? (await cache.profiles.get(userId)); const cachedResult = schemas.GetUserData.response.safeParse(cachedValue); const cached = cachedResult.success ? cachedResult.data : undefined; if (cached) { - installProfile(cached); + durableProfileRef.current[userId] = cached; + const merged = mergeUserPresence(cached); + storageRef.current[userId] = merged; const checkedAt = checkedAtRef.current[userId]; if (!checkedAt || Date.now() - checkedAt < USER_CACHE_MAX_AGE) { checkedAtRef.current[userId] = Date.now(); - return storageRef.current[userId]; + return merged; } } try { - const profileGeneration = - profileGenerationsRef.current.get(userId) ?? 0; const userData = await send("GetUserData", { UserId: userId }); if (userData.type === "ErrorNotFound" || userData.data.UserId === 0) { + delete storageRef.current[userId]; delete durableProfileRef.current[userId]; delete checkedAtRef.current[userId]; - publishUser(userId); await cache.profiles.delete(userId); throw new Error("GetUserData failed: user not found"); } if (userData.type.startsWith("Error")) { throw new Error(`GetUserData failed: ${userData.type}`); } - if ( - profileGeneration !== - (profileGenerationsRef.current.get(userId) ?? 0) && - storageRef.current[userId] - ) { - return storageRef.current[userId]; - } - installProfile(userData.data); + const user = mergeUserPresence(userData.data); + durableProfileRef.current[userId] = userData.data; + storageRef.current[userId] = user; checkedAtRef.current[userId] = Date.now(); - return storageRef.current[userId]; + return user; } catch (error) { if (cached && storageRef.current[userId]) { checkedAtRef.current[userId] = Date.now(); @@ -276,91 +216,26 @@ export default function UserProvider(props: { children: ReactNode }) { delete pendingRef.current[userId]; } }, - [getAccountId, installProfile, publishUser, send], + [accountId, cacheVersion, mergeUserPresence, send], ); - const get = useCallback( - async ( - userId: number, - fields: Fields, - ): Promise> => { - return selectUserFields(await loadUser(userId), fields); + const update = useCallback( + async (user: User) => { + const durableProfile = { + ...user, + OnlineStatus: + durableProfileRef.current[user.UserId]?.OnlineStatus ?? + user.OnlineStatus, + } as User; + await createCache(String(accountId ?? user.UserId)).profiles.put( + durableProfile, + ); + durableProfileRef.current[user.UserId] = durableProfile; + storageRef.current[user.UserId] = mergeUserPresence(durableProfile); + checkedAtRef.current[user.UserId] = Date.now(); + setCacheVersion((version) => version + 1); }, - [loadUser], - ); - - const peek = useCallback( - (userId: number, fields: Fields) => { - const user = storageRef.current[userId]; - return user ? selectUserFields(user, fields) : undefined; - }, - [], - ); - - const subscribe = useCallback( - (userId: number, fields: readonly UserField[], listener: () => void) => { - let listeners = listenersRef.current.get(userId); - if (!listeners) { - listeners = new Set(); - listenersRef.current.set(userId, listeners); - } - const entry = { fields: new Set(fields), listener }; - listeners.add(entry); - return () => { - listeners.delete(entry); - if (listeners.size === 0) listenersRef.current.delete(userId); - }; - }, - [], - ); - - const getVersion = useCallback( - (userId: number, fields: readonly UserField[]) => { - const revisions = revisionsRef.current.get(userId); - return fields - .map((field) => `${field}:${revisions?.get(field) ?? 0}`) - .join("|"); - }, - [], - ); - - const updateProfile = useCallback( - async (userId: number, patch: UserProfilePatch) => { - const previousUpdate = profileUpdateQueuesRef.current.get(userId); - const update = ( - previousUpdate?.catch(() => undefined) ?? Promise.resolve() - ).then(async () => { - const current = durableProfileRef.current[userId]; - if (!current) throw new Error(`User ${userId} is not loaded`); - profileGenerationsRef.current.set( - userId, - (profileGenerationsRef.current.get(userId) ?? 0) + 1, - ); - const profile = schemas.GetUserData.response.parse({ - ...current, - ...patch, - }); - installProfile(profile); - checkedAtRef.current[userId] = Date.now(); - await createCache(String(await getAccountId())).profiles.put(profile); - }); - profileUpdateQueuesRef.current.set(userId, update); - try { - await update; - } finally { - if (profileUpdateQueuesRef.current.get(userId) === update) { - profileUpdateQueuesRef.current.delete(userId); - } - } - }, - [getAccountId, installProfile], - ); - - const updateState = useCallback( - (userId: number, state: ClientUserState) => { - applyUserState(userId, state, true); - }, - [applyUserState], + [accountId, mergeUserPresence], ); useEffect(() => { @@ -372,7 +247,7 @@ export default function UserProvider(props: { children: ReactNode }) { ].filter((userId, index, all) => all.indexOf(userId) === index); for (const userId of userIds) { try { - await loadUser(userId); + await get(userId); const state = initialStatesRef.current.get(userId); if (state && applyUserState(userId, state)) { initialStatesRef.current.delete(userId); @@ -382,22 +257,12 @@ export default function UserProvider(props: { children: ReactNode }) { } } })(); - }, [accountId, applyUserState, contacts, loadUser]); - - const value = useMemo( - () => ({ - get, - peek, - subscribe, - getVersion, - updateProfile, - updateState, - }), - [get, getVersion, peek, subscribe, updateProfile, updateState], - ); + }, [accountId, applyUserState, contacts, get]); return ( - {props.children} + + {props.children} + ); } @@ -413,63 +278,3 @@ export function useUser(): contextValue { } return context; } - -export type UserLoadState = - | { data: undefined; error: undefined; loading: true } - | { data: undefined; error: unknown; loading: false } - | { data: SelectedUser; error: undefined; loading: false }; - -export function useUserFields( - userId: number | null, - fields: Fields, -): UserLoadState { - const { get, getVersion, peek, subscribe } = useUser(); - const fieldKey = fields.join("|"); - const selectedFields = useMemo( - () => fieldKey.split("|") as unknown as Fields, - [fieldKey], - ); - const requestKey = `${userId ?? "unresolved"}:${fieldKey}`; - const [failure, setFailure] = useState<{ - error: unknown; - requestKey: string; - }>(); - - const version = useSyncExternalStore( - useCallback( - (listener) => - userId === null - ? () => undefined - : subscribe(userId, selectedFields, listener), - [selectedFields, subscribe, userId], - ), - useCallback( - () => - userId === null ? "unresolved" : getVersion(userId, selectedFields), - [getVersion, selectedFields, userId], - ), - () => "server", - ); - - useEffect(() => { - if (userId === null) return; - let active = true; - void get(userId, selectedFields).catch((nextError: unknown) => { - if (active) setFailure({ error: nextError, requestKey }); - }); - return () => { - active = false; - }; - }, [get, requestKey, selectedFields, userId]); - - const data = useMemo(() => { - void version; - return userId === null ? undefined : peek(userId, selectedFields); - }, [peek, selectedFields, userId, version]); - - if (data) return { data, error: undefined, loading: false }; - if (failure?.requestKey === requestKey) { - return { data: undefined, error: failure.error, loading: false }; - } - return { data: undefined, error: undefined, loading: true }; -} diff --git a/packages/user/src/selection.test.ts b/packages/user/src/selection.test.ts deleted file mode 100644 index 4235945..0000000 --- a/packages/user/src/selection.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { describe, expect, it } from "vitest"; - -import type { User } from "./context"; -import { getChangedUserFields, selectUserFields } from "./selection"; - -const user = { - Avatar: undefined, - Display: "Alice", - IotaId: 1, - OmikronConnections: [], - OnlineStatus: "user_online", - PublicKey: "AA==", - SubEnd: 0, - SubLevel: 0, - UserId: 1, - Username: "alice", -} satisfies User; - -describe("presence selection", () => { - it("notifies OnlineStatus selections when presence changes", () => { - const next = { ...user, OnlineStatus: "user_dnd" as const }; - - expect(getChangedUserFields(user, next)).toEqual(["OnlineStatus"]); - expect(selectUserFields(next, ["OnlineStatus"])).toEqual({ - OnlineStatus: "user_dnd", - }); - }); -}); diff --git a/packages/user/src/selection.ts b/packages/user/src/selection.ts deleted file mode 100644 index 57b0fe3..0000000 --- a/packages/user/src/selection.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { User, UserField, UserFields, SelectedUser } from "./context"; - -const USER_FIELD_MAP = { - About: true, - Avatar: true, - Display: true, - IotaId: true, - OmikronConnections: true, - OmikronId: true, - OnlineStatus: true, - PublicKey: true, - Status: true, - SubEnd: true, - SubLevel: true, - UserId: true, - Username: true, -} satisfies Record; - -const USER_FIELDS = Object.keys(USER_FIELD_MAP) as UserField[]; - -export function selectUserFields( - user: User, - fields: Fields, -): SelectedUser { - return Object.fromEntries( - fields.map((field) => [field, user[field]]), - ) as SelectedUser; -} - -export function getChangedUserFields( - previous: User | undefined, - next: User | undefined, -): UserField[] { - if ((previous === undefined) !== (next === undefined)) { - return [...USER_FIELDS]; - } - return USER_FIELDS.filter( - (field) => !Object.is(previous?.[field], next?.[field]), - ); -} diff --git a/packages/user/src/wrapper.tsx b/packages/user/src/wrapper.tsx index 2a8752f..5f13e54 100644 --- a/packages/user/src/wrapper.tsx +++ b/packages/user/src/wrapper.tsx @@ -1,47 +1,48 @@ import { useEffect, useState } from "react"; -import { type SelectedUser, type UserFields, useUserFields } from "./context"; +import { useUser, type User } from "./context"; import { failedUser } from "@tensamin/shared/data"; import { useStorage } from "@tensamin/storage/context"; // Wrapper function to pass user data to some component -export default function Wrapper(props: { +export default function Wrapper(props: { userId: number | "own"; - fields: Fields; loading: React.ReactNode; - component: (user: SelectedUser) => React.ReactNode; + component: (user: User) => React.ReactNode; }) { + const { get } = useUser(); const { load } = useStorage(); - const [ownUserId, setOwnUserId] = useState(null); - const [ownUserError, setOwnUserError] = useState(false); + const [user, setUser] = useState(null); useEffect(() => { - if (props.userId !== "own") return; + if (props.userId == null) return; + let active = true; - void load("user_id").then( - (value) => { + + void (async () => { + try { + const userId = + props.userId === "own" ? await load("user_id") : props.userId; + const value = await get(userId); + if (active) { - setOwnUserId(value); - setOwnUserError(false); + setUser(value); } - }, - () => { - if (active) setOwnUserError(true); - }, - ); + } catch { + if (active) { + setUser(failedUser); + } + } + })(); + return () => { active = false; }; - }, [load, props.userId]); + }, [load, get, props.userId]); - const userId = props.userId === "own" ? ownUserId : props.userId; - const result = useUserFields(userId, props.fields); - if ( - (props.userId === "own" && ownUserError) || - (!result.loading && !result.data) - ) { - return <>{props.component(failedUser as SelectedUser)}; + if (props.userId == null) { + return <>{props.component(failedUser)}; } - return <>{result.data ? props.component(result.data) : props.loading}; + return <>{user ? props.component(user) : props.loading}; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 83d88ff..bbfb6de 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,28 +5,28 @@ settings: excludeLinksFromLockfile: false overrides: - '@methanium/ui': https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz - mtp: https://git.methanium.net/methanium/mtp/releases/download/0.3.0-dev-c7c7afe/mtp-0.3.0.tgz + '@methanium/ui': https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz + mtp: https://git.methanium.net/methanium/mtp/releases/download/0.2.0-dev-a692bed/mtp-0.2.0.tgz importers: .: dependencies: '@methanium/ui': - specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz - version: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) + specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz + version: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) mtp: - specifier: https://git.methanium.net/methanium/mtp/releases/download/0.3.0-dev-c7c7afe/mtp-0.3.0.tgz - version: https://git.methanium.net/methanium/mtp/releases/download/0.3.0-dev-c7c7afe/mtp-0.3.0.tgz + specifier: https://git.methanium.net/methanium/mtp/releases/download/0.2.0-dev-a692bed/mtp-0.2.0.tgz + version: https://git.methanium.net/methanium/mtp/releases/download/0.2.0-dev-a692bed/mtp-0.2.0.tgz sonner: - specifier: ^2.0.8 - version: 2.0.8(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + specifier: ^2.0.7 + version: 2.0.7(react-dom@19.2.8(react@19.2.8))(react@19.2.8) devDependencies: '@eslint/js': specifier: ^10.0.1 version: 10.0.1(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0)) '@types/node': - specifier: ^26.2.0 + specifier: ^26.1.2 version: 26.2.0 '@types/react': specifier: ^19.2.18 @@ -35,20 +35,20 @@ importers: specifier: ^19.2.4 version: 19.2.4(@types/react@19.2.18) '@typescript-eslint/parser': - specifier: ^8.67.0 - version: 8.67.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + specifier: ^8.66.0 + version: 8.66.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) eslint: - specifier: ^10.8.1 + specifier: ^10.8.0 version: 10.8.1(jiti@2.7.0)(supports-color@7.2.0) eslint-plugin-react-hooks: specifier: ^7.1.1 version: 7.1.1(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0) fallow: - specifier: ^3.17.0 - version: 3.17.0 + specifier: ^3.14.0 + version: 3.14.0 globals: - specifier: ^17.11.0 - version: 17.11.0 + specifier: ^17.9.0 + version: 17.9.0 prettier: specifier: ^3.9.6 version: 3.9.6 @@ -56,11 +56,11 @@ importers: specifier: ^6.0.3 version: 6.0.3 typescript-eslint: - specifier: ^8.67.0 - version: 8.67.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + specifier: ^8.66.0 + version: 8.66.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) vitest: - specifier: ^4.1.11 - version: 4.1.11(@types/node@26.2.0)(vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0)) + specifier: ^4.1.10 + version: 4.1.10(@types/node@26.2.0)(vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)) apps/electron: devDependencies: @@ -80,69 +80,17 @@ importers: specifier: ~6.0.3 version: 6.0.3 - apps/pwa: - dependencies: - '@methanium/ui': - specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz - version: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) - '@tauri-apps/api': - specifier: ^2.11.1 - version: 2.11.1 - '@tensamin/crypto': - specifier: workspace:* - version: link:../../packages/crypto - '@tensamin/shared': - specifier: workspace:* - version: link:../../packages/shared - '@tensamin/storage': - specifier: workspace:* - version: link:../../packages/storage - mtp: - specifier: https://git.methanium.net/methanium/mtp/releases/download/0.3.0-dev-c7c7afe/mtp-0.3.0.tgz - version: https://git.methanium.net/methanium/mtp/releases/download/0.3.0-dev-c7c7afe/mtp-0.3.0.tgz - react: - specifier: ^19.2.8 - version: 19.2.8 - sonner: - specifier: ^2.0.7 - version: 2.0.8(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) - vite-plugin-pwa: - specifier: ^1.1.0 - version: 1.3.0(supports-color@7.2.0)(vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0))(workbox-build@7.4.1(supports-color@7.2.0))(workbox-window@7.4.1) - workbox-core: - specifier: ^7.3.0 - version: 7.4.1 - workbox-precaching: - specifier: ^7.3.0 - version: 7.4.1 - workbox-routing: - specifier: ^7.3.0 - version: 7.4.1 - workbox-strategies: - specifier: ^7.3.0 - version: 7.4.1 - devDependencies: - '@types/node': - specifier: ^26.1.2 - version: 26.2.0 - '@types/react': - specifier: ^19.2.18 - version: 19.2.18 - typescript: - specifier: ~6.0.3 - version: 6.0.3 - vite: - specifier: ^8.2.1 - version: 8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0) - apps/tauri: dependencies: '@methanium/ui': - specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz - version: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) + specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz + version: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) '@tauri-apps/api': specifier: ^2.11.1 version: 2.11.1 + '@tauri-apps/plugin-barcode-scanner': + specifier: ~2.4.5 + version: 2.4.5 '@tauri-apps/plugin-deep-link': specifier: ~2.4.9 version: 2.4.9 @@ -169,11 +117,11 @@ importers: specifier: ^5.3.0 version: 5.3.0 '@methanium/ui': - specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz - version: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) + specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz + version: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) '@tailwindcss/vite': specifier: ^4.3.3 - version: 4.3.3(vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0)) + version: 4.3.3(vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)) '@tanstack/react-router': specifier: ^1.170.21 version: 1.170.23(react-dom@19.2.8(react@19.2.8))(react@19.2.8) @@ -207,9 +155,6 @@ importers: '@tensamin/onboarding': specifier: workspace:* version: link:../../packages/onboarding - '@tensamin/pwa': - specifier: workspace:* - version: link:../pwa '@tensamin/settings': specifier: workspace:* version: link:../../packages/settings @@ -279,7 +224,7 @@ importers: version: 19.2.4(@types/react@19.2.18) '@vitejs/plugin-react': specifier: ^6.0.5 - version: 6.0.5(vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0)) + version: 6.0.5(vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)) esbuild: specifier: ^0.28.1 version: 0.28.1 @@ -289,9 +234,6 @@ importers: globals: specifier: ^17.9.0 version: 17.9.0 - mtp: - specifier: https://git.methanium.net/methanium/mtp/releases/download/0.3.0-dev-c7c7afe/mtp-0.3.0.tgz - version: https://git.methanium.net/methanium/mtp/releases/download/0.3.0-dev-c7c7afe/mtp-0.3.0.tgz typescript: specifier: ~6.0.3 version: 6.0.3 @@ -300,7 +242,7 @@ importers: version: 8.66.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) vite: specifier: ^8.2.1 - version: 8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0) + version: 8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0) packages/cache: dependencies: @@ -326,8 +268,8 @@ importers: specifier: ^2.9.23 version: 2.9.23(livekit-client@2.21.0(@types/dom-mediacapture-record@1.0.22))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(tslib@2.8.1) '@methanium/ui': - specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz - version: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) + specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz + version: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) '@tanstack/react-router': specifier: ^1.170.21 version: 1.170.23(react-dom@19.2.8(react@19.2.8))(react@19.2.8) @@ -355,9 +297,6 @@ importers: lucide-react: specifier: ^1.29.0 version: 1.30.0(react@19.2.8) - mtp: - specifier: https://git.methanium.net/methanium/mtp/releases/download/0.3.0-dev-c7c7afe/mtp-0.3.0.tgz - version: https://git.methanium.net/methanium/mtp/releases/download/0.3.0-dev-c7c7afe/mtp-0.3.0.tgz react: specifier: ^19.2.8 version: 19.2.8 @@ -377,8 +316,8 @@ importers: packages/chat: dependencies: '@methanium/ui': - specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz - version: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) + specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz + version: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) '@tanstack/pacer': specifier: ^0.21.1 version: 0.21.1 @@ -430,9 +369,6 @@ importers: packages/crypto: dependencies: - mtp: - specifier: https://git.methanium.net/methanium/mtp/releases/download/0.3.0-dev-c7c7afe/mtp-0.3.0.tgz - version: https://git.methanium.net/methanium/mtp/releases/download/0.3.0-dev-c7c7afe/mtp-0.3.0.tgz react: specifier: ^19.2.8 version: 19.2.8 @@ -457,55 +393,19 @@ importers: devDependencies: vite: specifier: ^8.2.1 - version: 8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0) - - packages/markdown: - dependencies: - '@codemirror/autocomplete': - specifier: ^6.20.3 - version: 6.20.3 - '@codemirror/commands': - specifier: ^6.10.4 - version: 6.11.0 - '@codemirror/lang-markdown': - specifier: ^6.5.2 - version: 6.5.2 - '@codemirror/language': - specifier: ^6.12.4 - version: 6.12.4 - '@codemirror/state': - specifier: ^6.7.1 - version: 6.7.1 - '@codemirror/view': - specifier: ^6.43.8 - version: 6.43.9 - '@methanium/ui': - specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz - version: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) - '@twemoji/api': - specifier: ^17.0.3 - version: 17.0.3 - emojibase-data: - specifier: ^17.0.0 - version: 17.0.0(emojibase@17.0.0) - lucide-react: - specifier: ^1.30.0 - version: 1.32.0(react@19.2.8) - react: - specifier: ^19.2.8 - version: 19.2.8 - react-dom: - specifier: ^19.2.8 - version: 19.2.8(react@19.2.8) + version: 8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0) packages/mtp: dependencies: '@methanium/ui': - specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz - version: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) + specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz + version: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) '@tauri-apps/api': specifier: ^2.11.1 version: 2.11.1 + '@tensamin/crypto': + specifier: workspace:* + version: link:../crypto '@tensamin/shared': specifier: workspace:* version: link:../shared @@ -513,11 +413,17 @@ importers: specifier: workspace:* version: link:../storage mtp: - specifier: https://git.methanium.net/methanium/mtp/releases/download/0.3.0-dev-c7c7afe/mtp-0.3.0.tgz - version: https://git.methanium.net/methanium/mtp/releases/download/0.3.0-dev-c7c7afe/mtp-0.3.0.tgz + specifier: https://git.methanium.net/methanium/mtp/releases/download/0.2.0-dev-a692bed/mtp-0.2.0.tgz + version: https://git.methanium.net/methanium/mtp/releases/download/0.2.0-dev-a692bed/mtp-0.2.0.tgz react: specifier: ^19.2.8 version: 19.2.8 + react-dom: + specifier: ^19.2.8 + version: 19.2.8(react@19.2.8) + zod: + specifier: ^4.4.3 + version: 4.4.3 devDependencies: eslint: specifier: ^10.8.0 @@ -526,8 +432,8 @@ importers: packages/notifications: dependencies: '@methanium/ui': - specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz - version: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) + specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz + version: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) '@tanstack/react-router': specifier: ^1.170.21 version: 1.170.23(react-dom@19.2.8(react@19.2.8))(react@19.2.8) @@ -568,8 +474,8 @@ importers: packages/onboarding: dependencies: '@methanium/ui': - specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz - version: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) + specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz + version: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) '@tauri-apps/api': specifier: ^2.11.1 version: 2.11.1 @@ -598,14 +504,11 @@ importers: packages/settings: dependencies: '@methanium/ui': - specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz - version: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) + specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz + version: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) '@tanstack/react-router': specifier: ^1.170.21 version: 1.170.23(react-dom@19.2.8(react@19.2.8))(react@19.2.8) - '@tauri-apps/api': - specifier: ^2.11.1 - version: 2.11.1 '@tensamin/cache': specifier: workspace:* version: link:../cache @@ -636,13 +539,13 @@ importers: devDependencies: vite: specifier: ^8.2.1 - version: 8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0) + version: 8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0) packages/shared: dependencies: '@methanium/ui': - specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz - version: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) + specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz + version: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) lucide-react: specifier: ^1.29.0 version: 1.30.0(react@19.2.8) @@ -659,8 +562,8 @@ importers: packages/storage: dependencies: '@methanium/ui': - specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz - version: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) + specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz + version: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) '@tauri-apps/api': specifier: ^2.11.1 version: 2.11.1 @@ -683,8 +586,8 @@ importers: packages/tauth: dependencies: '@methanium/ui': - specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz - version: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) + specifier: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz + version: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3) '@tanstack/react-router': specifier: ^1.170.21 version: 1.170.23(react-dom@19.2.8(react@19.2.8))(react@19.2.8) @@ -739,12 +642,6 @@ importers: packages: - '@apideck/better-ajv-errors@0.3.7': - resolution: {integrity: sha512-TajUJwGWbDwkCx/CZi7tRE8PVB7simCvKJfHUsSdvps+aTM/PDPP4gkLmKnc+x3CE//y9i/nj74GqdL/hwk7Iw==} - engines: {node: '>=10'} - peerDependencies: - ajv: '>=8' - '@babel/code-frame@7.29.7': resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} @@ -775,17 +672,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-create-regexp-features-plugin@7.29.7': - resolution: {integrity: sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/helper-define-polyfill-provider@0.6.8': - resolution: {integrity: sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - '@babel/helper-globals@7.29.7': resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} engines: {node: '>=6.9.0'} @@ -812,12 +698,6 @@ packages: resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==} engines: {node: '>=6.9.0'} - '@babel/helper-remap-async-to-generator@7.29.7': - resolution: {integrity: sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - '@babel/helper-replace-supers@7.29.7': resolution: {integrity: sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==} engines: {node: '>=6.9.0'} @@ -840,10 +720,6 @@ packages: resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} engines: {node: '>=6.9.0'} - '@babel/helper-wrap-function@7.29.7': - resolution: {integrity: sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==} - engines: {node: '>=6.9.0'} - '@babel/helpers@7.29.7': resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==} engines: {node: '>=6.9.0'} @@ -853,60 +729,6 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.29.7': - resolution: {integrity: sha512-j8SrR0zLZrRsC09DlszEx8FpMiwukKffYXMK0d5LmOglO7vGG6sz/BR/20yHqWH+Lnn31JTt2PE3hIWNgM2J6w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.29.7': - resolution: {integrity: sha512-r8j8escF+U2FUHo0KOhPUdMzUO+jp9fInva6+ACVAF3Y97Ev+5iNZwiqTghmzNeWwDkOPlYuTcfb1vDaoZKmAQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.29.7': - resolution: {integrity: sha512-GE1TFSiuFeGsCxmYXZl8HwoPrVlwe4rHPFE8weieGKZqnDORK+Ar3vgWMgW+AOxQ6/2TgLSKx9p6W7O4rC6qgQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@7.29.7': - resolution: {integrity: sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.29.7': - resolution: {integrity: sha512-QQt9qKHZ2sg/kivaLr7lnQr8HVrQDdBNSfCsTjiDxRuX/K5ORyKq+Bu8Xr0cDE3Dfkv0cw28Ve0EKyKMvulkOw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.13.0 - - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.29.7': - resolution: {integrity: sha512-pn6QacGLgvCcwc+syUhKE/qSjV2D1IHDB84RNxWYSt1mW3K/SCtjinZ2p0cETJxAWBjPy3K/1lHwG5BjjPxNlw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': - resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-import-assertions@7.29.7': - resolution: {integrity: sha512-/An1OCBN93thpBAGyfsK2pcf0jvju1SAtKkL2Ny++B5Sy6sqgzXDQH1cZxWbF96Wuk+bn41MDA9bLd4VVAw6rw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-import-attributes@7.29.7': - resolution: {integrity: sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-jsx@7.29.7': resolution: {integrity: sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==} engines: {node: '>=6.9.0'} @@ -919,335 +741,18 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-unicode-sets-regex@7.18.6': - resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/plugin-transform-arrow-functions@7.29.7': - resolution: {integrity: sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-async-generator-functions@7.29.7': - resolution: {integrity: sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-async-to-generator@7.29.7': - resolution: {integrity: sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-block-scoped-functions@7.29.7': - resolution: {integrity: sha512-cUSmjh72N+rN4PrkFlN1dJwNCwjVp5d38/CQrEsFggkD10UiFlBFgdH3tv5dNsLuHY+3S8db2xCHjhZcv5WgvA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-block-scoping@7.29.7': - resolution: {integrity: sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-class-properties@7.29.7': - resolution: {integrity: sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-class-static-block@7.29.7': - resolution: {integrity: sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.12.0 - - '@babel/plugin-transform-classes@7.29.7': - resolution: {integrity: sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-computed-properties@7.29.7': - resolution: {integrity: sha512-RK7/IyU5phpuCdBAuig5VkzG/EnbDaui5SQGdU9BFrHdV+mV4cUjLMQ9lJDjLNtWHsqtiefpGZUXQP2BiTYMsA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-destructuring@7.29.7': - resolution: {integrity: sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-dotall-regex@7.29.7': - resolution: {integrity: sha512-3qc18hsD2RdZiyJNDNc7HQpv6xbncwh8FYtxNFFzclSyh/trPD9KkVR9BDECUjDLvb7yJVF15GfYUuC+LMkkiQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-duplicate-keys@7.29.7': - resolution: {integrity: sha512-6IvRRriEMqnBwD6chtxdLpMYCHWEzN+oL5cyQtjykya19UgzbmKhxmhZgKC/LHxS2nYr9Q/qYPZ5Lr6jOL9+yQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.7': - resolution: {integrity: sha512-2wiIyo2BjtgU7HufSeDnL9L2O7zr8jmhFKuSr65VpRkUiRKRNpb0mdlk56+XPPKoIrfHqzbMuglDvZun0RISsA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/plugin-transform-dynamic-import@7.29.7': - resolution: {integrity: sha512-giOlEm/EFjfjr+te9NsdjkUo2v4f8rS/SXPumRVHAtbNcyNlvtREkU1dZzaIDclNpnaVhlCqRdFKhJBjBikzLg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-explicit-resource-management@7.29.7': - resolution: {integrity: sha512-Rstj7coNz8sE+7Ju7ihpHLI564lsK5pUpNNlvptCIC/16E/S5hbl6n3kESPKdNRmqEWlpn5xpS5Q2dvXBsySLw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-exponentiation-operator@7.29.7': - resolution: {integrity: sha512-zFpMOTLZBdW5LfObqcSbL6kefg4R4eLdmvS0wbN9M6D5Mym/sKm9toOoWyVOa+xDjvCnuWcHls2YonXwHvH3CQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-export-namespace-from@7.29.7': - resolution: {integrity: sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-for-of@7.29.7': - resolution: {integrity: sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-function-name@7.29.7': - resolution: {integrity: sha512-otRWaHXE6fbAGkePvaj/kvs3HsqXfPhlnzwSOlnFgbqCPMd975dW+4wZ00WFBt+/YlBGcJwNrARQTOJOb4ZrIg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-json-strings@7.29.7': - resolution: {integrity: sha512-RRnE2+eon1rJAq8MnoF1b5kTpY1vU88twHcvcKMrsqP/jxIRqDVs9iJB5fqPuqyeFAW0wJo4MlUIPpQCq/aRsg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-literals@7.29.7': - resolution: {integrity: sha512-DZ/oLP21ZuWx1vKqnoNv6/tvEK48AQOBRai40CX9dTjGluvT/YZCyY3rryDtyUqCEoyNroy5KKPwX2iQCiRvyw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-logical-assignment-operators@7.29.7': - resolution: {integrity: sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-member-expression-literals@7.29.7': - resolution: {integrity: sha512-hl1kwFZCCiDyfH25Xmco9jTrkPgnS9pmOzSG7W5I4SaGbLeqKv417hcU2RKmaxoPEgsoJh7ZPOrnPGq99bHoUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-modules-amd@7.29.7': - resolution: {integrity: sha512-fxtQoH3m5ywUSIfaH0FGCzWu4McsYon5bD3K4XnskC7f+OyQMj7rsOMi4NvvmJ83WwBAg4UCe+ov4VZlqEvyew==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-commonjs@7.29.7': resolution: {integrity: sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-systemjs@7.29.8': - resolution: {integrity: sha512-6iSnEK0zlkLKU4heofK/AdmRD4e2SHVpJMtrwnTCzhnaM98ria4rTrOXBBi45BTTYnJtO8txnPsX4fChYXkmeA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-modules-umd@7.29.7': - resolution: {integrity: sha512-B4UkaTK3QpgCwJnrxKfMPKdo92CN7OKXAlpAAnM3UPu0Q0lCCk57ylA9AJbRy2v8dDKOPAAWcoR6CMyeoHwRCA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-named-capturing-groups-regex@7.29.7': - resolution: {integrity: sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/plugin-transform-new-target@7.29.7': - resolution: {integrity: sha512-fEo41GmsOUhOBlw8ioo6zvjX5Xc2Lqkzlyfqbpsk3eB6TReV18uhxZ0esfEokVbY2+PVJAQHNKxER6lGrzNd3A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-nullish-coalescing-operator@7.29.7': - resolution: {integrity: sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-numeric-separator@7.29.7': - resolution: {integrity: sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-object-rest-spread@7.29.7': - resolution: {integrity: sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-object-super@7.29.7': - resolution: {integrity: sha512-Ea/diGcw0twB5IlZPO5sgET6fJsLJqPABqTuFWIR+iMPGPZJkATEIWx0wa+aEQ5UY1CBQyP/gkAiLEqn1vBiQA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-optional-catch-binding@7.29.7': - resolution: {integrity: sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-optional-chaining@7.29.7': - resolution: {integrity: sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-parameters@7.29.7': - resolution: {integrity: sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-private-methods@7.29.7': - resolution: {integrity: sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-private-property-in-object@7.29.7': - resolution: {integrity: sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-property-literals@7.29.7': - resolution: {integrity: sha512-bOMRLQuI0A5ZqHq3OWJ89/rXpJ/NJrbVhXiP4zwPGMs6kpcVsuTUNjwoE30K0Qm3mf48a/TnRYYD6vPNqcg6jA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-regenerator@7.29.8': - resolution: {integrity: sha512-0UpIXPtdDtMXfnV2OJAVMLpj3H/92vmkA6lpSRakmycJvj3VUy6Xs1dM8tXRugupykr5WB+LpiVl0J8LMVg2mg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-regexp-modifiers@7.29.7': - resolution: {integrity: sha512-mB5Fs0VWrJ42ZCmc8114v60qetdaUVNkj9PmSZRmanCZM3S9hm0CFRLjRmYIsuXav14l2jvZ+4T8iiCGnhj3nQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/plugin-transform-reserved-words@7.29.7': - resolution: {integrity: sha512-5+YhdpVgmfSmwZyLMftfaiffLRMHjzIRHFHHLdibcSyJm2pasMrKHrO3Ptrt2DRshjvpgjEJJ1zVW14WPq/6QA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-shorthand-properties@7.29.7': - resolution: {integrity: sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-spread@7.29.8': - resolution: {integrity: sha512-4S9ksMGVWUshvgK0mKfvZky7leuG5/uoFVwMpAomJ8bMoDJiNHRVmc1EglwW/CmGVSqqWpEbXm9FmbRit22qoA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-sticky-regex@7.29.7': - resolution: {integrity: sha512-BCHzNYJGe9l7EpwwDBN/ztlL2NYFFq8hp9ddjtUEM9f2O7S7kKV/lL6Fwo7IF7NSkYhPK2vO+86nIGltA90MsA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-template-literals@7.29.7': - resolution: {integrity: sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-typeof-symbol@7.29.7': - resolution: {integrity: sha512-223mNGoTkBiTEWFoK+Q6Go3tueMRclO8vxxxxquNCYuNI4jWOofFKJRRDu6SDrB8Sgo1UEGW9T4GAQ8ZyRso1A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-typescript@7.29.7': resolution: {integrity: sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-escapes@7.29.7': - resolution: {integrity: sha512-jCfXxSjf94lf4E0hKE0AByxF6F3/pVFqRdUUNkDJhsY0m1ZKjnN6ZYyMeHNpzflxb/0q5b7t3p+BE+SLF1WOtA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-unicode-property-regex@7.29.7': - resolution: {integrity: sha512-OgZ+zoAJgZLUCunsTRQ5LAjOywDv5zzZ2/hQ5aMw1pGXyY2rtE8/chXYUmu3AlVHKpm10KEdG9aMwbI/K76ZGw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-unicode-regex@7.29.7': - resolution: {integrity: sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-unicode-sets-regex@7.29.7': - resolution: {integrity: sha512-BLOhLht9DOJwIxlmp91wHvkXv1lguuHS3/FwUO8HL1H0u8s4hR1gASVFyilu9iGtcTRYqjTZmlsFFeQletntEg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/preset-env@7.29.7': - resolution: {integrity: sha512-GYzX36n1nsciIb0uyH0GHwxwtNwPQIcpxSeiVLDtG/B7jB5xXgchnmL1f/jCX5o+pwnaDBtO60ONSJhEBJfxYA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/preset-modules@0.1.6-no-external-plugins': - resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} - peerDependencies: - '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 - '@babel/preset-typescript@7.29.7': resolution: {integrity: sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ==} engines: {node: '>=6.9.0'} @@ -1303,8 +808,8 @@ packages: '@codemirror/autocomplete@6.20.3': resolution: {integrity: sha512-tlosUqb+3BbxCxZdu4tKeRghPFC+QM7q4X5YhKV2eCmPG+1r2F3f4AaSz5sCrFqUtX4Jh20VFTKecl16MgiV9g==} - '@codemirror/commands@6.11.0': - resolution: {integrity: sha512-/K4Rl5BN0OtTiPWmJCdqODu38XnDMsDxKY5rgrPnCkutPTJf2wVbkoixLfealF5Kwse/s8P8M5jAiURiwSwnFA==} + '@codemirror/commands@6.10.4': + resolution: {integrity: sha512-Ryk9y9T0FFVF0cUGhAknveAyUOl/A1qReTFi+qPKtOh2Z9F4AUBz3XOrYD4ZEgZirdugVzHvd/2/Wcwy5OliTg==} '@codemirror/lang-css@6.3.1': resolution: {integrity: sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==} @@ -1327,8 +832,8 @@ packages: '@codemirror/state@6.7.1': resolution: {integrity: sha512-9QzNDgE4EYDnAHfrTlR2lwiPciiOymLtwKK+8yHQzCc7GXhAP9xdEbEJFy2IWB1j9UGUl9BsgMmTo/ImA02T7A==} - '@codemirror/view@6.43.9': - resolution: {integrity: sha512-sTuUzTpPMFebRhg6dawChoKKgndIwfjmJgKVxBefPElcU2NwQ6AFroupk0SFqEerQyZOGRfDNnSN8Dw/lMAsXw==} + '@codemirror/view@6.43.8': + resolution: {integrity: sha512-qtItTDssZ/5GFfi94hrILu9j/VUeFPDPkhovEfmWFj2ipTxnzPB8DdHgfbb8HYTzLTYhrndKmyQxXUz/PDLenw==} '@dotenvx/dotenvx@1.75.1': resolution: {integrity: sha512-/BITOC9dmS/edY2zQwZNicQ059O6RKabtQfyEafV0nGtfYRNHYy1DIPiYVcov40+tob9hfmBnbR963dS+EQ1DQ==} @@ -1576,43 +1081,43 @@ packages: resolution: {integrity: sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@fallow-cli/darwin-arm64@3.17.0': - resolution: {integrity: sha512-u9O4aQaTSdaZaa4MAVEZEiwOx6QQzChymyQPrxV6KvDcVbcl0oYSekJKdvN4gEqUY8ClMze9gWS1tbn/W3N4dQ==} + '@fallow-cli/darwin-arm64@3.14.0': + resolution: {integrity: sha512-seaix3OqADcq90PkPOOPrN8Jl7QZDGjFziHA85Ikp+lGSHVjJ2IMyGh/QKLhvi9Q6Ha3Y//F0+PFFGNd0Gi4mw==} cpu: [arm64] os: [darwin] - '@fallow-cli/darwin-x64@3.17.0': - resolution: {integrity: sha512-l3tZJovnCa8j+im4qTl4GVSfrx4gisJYeHDwb5TbcdTGaWYz42gHriAaz5MhOR8S24q3xRegX8QrI8PA4XXU4g==} + '@fallow-cli/darwin-x64@3.14.0': + resolution: {integrity: sha512-qgYZHHTFobuJCtON7aVe/tXCUjiF/9nKT4tNLVfUPH4Qe9KwieO4rAuknDOnxkjzsWPO4MfHyCbcVdslf4JMnw==} cpu: [x64] os: [darwin] - '@fallow-cli/linux-arm64-gnu@3.17.0': - resolution: {integrity: sha512-IAjS6qR4tHcRo1y5lzYT6mktN/ATPyPNrJ6yjwTORwwQV1YfMO58A5zGBfJlPBY+lUmaMZ9w37ftvH9a2AS4dQ==} + '@fallow-cli/linux-arm64-gnu@3.14.0': + resolution: {integrity: sha512-FwmIG391lMViBXh1cAvOcwQxbI2sLjEYkugFauVbmntjuJt6xVxQXAxjybdFXSL/jjfFnbAzPKy9oHlhq3sA6A==} cpu: [arm64] os: [linux] - '@fallow-cli/linux-arm64-musl@3.17.0': - resolution: {integrity: sha512-Oe1dvk5Wt5Bmnxfc6HufJTaFY9SEwDVrZpnSdVQlv+nvz7DzrTK1r91cR3Ip477ANSLa9XD/MHPMpfqqo0dlZg==} + '@fallow-cli/linux-arm64-musl@3.14.0': + resolution: {integrity: sha512-x4R9aNT2kIoSHRIZ5s2MZ+swyb3uutV6SSYCwWhPSE5UI/oCEYWNWiYS7uKMLM0cTuMPVcsm2qMTd4iYA3ACLw==} cpu: [arm64] os: [linux] - '@fallow-cli/linux-x64-gnu@3.17.0': - resolution: {integrity: sha512-XgLU2a51zuky7gifjVDHuiJGToAReDsVCDcyDF84TQz/h3bqO0iRkpDL8dh7+HODku84+EffpK5ZHY19n6Ij0w==} + '@fallow-cli/linux-x64-gnu@3.14.0': + resolution: {integrity: sha512-8kBxy9FkwKjiH1C19T0nSkmbtldwVyWLQWajIqvyHE0x4rurHhve7RQrwEDPzNMFu7OgYCMU1nXr/AMIJ6Kg9w==} cpu: [x64] os: [linux] - '@fallow-cli/linux-x64-musl@3.17.0': - resolution: {integrity: sha512-GnDZx2kbLKKdYAp05NSKv6CZHgzEKvhRd0btCKFMMpUEhdzmr4uh2Qb4UzKDBg/q2r1EhkzN4b/qC+tbFCmtwA==} + '@fallow-cli/linux-x64-musl@3.14.0': + resolution: {integrity: sha512-9TAdXSpYvk9WkKy2GR8T/PHbq7QCTO/SYUmiZ+EAJUMzXBvSfnpj8cCGQpeAD000Nb+o7rL94lIAPJMAqMKO3Q==} cpu: [x64] os: [linux] - '@fallow-cli/win32-arm64-msvc@3.17.0': - resolution: {integrity: sha512-u9n5WzPuKuC1PKegKQknWtngAUJ2szQaRXsbY54s7UMqeFNyC+W04LV5D+sEZywU7L0kzL+Kck9LxFLXBQcgvA==} + '@fallow-cli/win32-arm64-msvc@3.14.0': + resolution: {integrity: sha512-xc495cracyJL+0UKwcqNhofIz2K5XiJbb+YFhxrbSrrbm+EVDnQKpCOzzOJYbm7RPxF6XOxJpATn7ciBy7Rqrw==} cpu: [arm64] os: [win32] - '@fallow-cli/win32-x64-msvc@3.17.0': - resolution: {integrity: sha512-/OcyxHuCKabzQ9hKIjM/CFJ9fr30n0Mw5MK6nzi5rn26mbYUgh073UZq4FONOpPJ/FqHtC726rxpgBtR4qS+gg==} + '@fallow-cli/win32-x64-msvc@3.14.0': + resolution: {integrity: sha512-ihyCZ5GMoYGnzlPP6b5pZBBcGZhDHDW2u1YEGkZEuf3pbW6E45U7Hhf213cE2CCheScXOirK6AKWnLM/Qj4c2A==} cpu: [x64] os: [win32] @@ -1637,8 +1142,8 @@ packages: '@fontsource-variable/public-sans@5.3.0': resolution: {integrity: sha512-AVfkmAt50BMXWpOO21FAntiJFKGX6xTc2dSL8dxtDteONe9IuRXJWGbs0EbG955vAMCq23ENeuopuW87cGWDSQ==} - '@hono/node-server@2.1.1': - resolution: {integrity: sha512-ELuehkj5VCBdgEw9zs+ivkKwyzzUCSQuE96YmiPvn1ECBoZCczbFXJLeEGMTYjphP6gydh4pHMqEYPVMYUVgQg==} + '@hono/node-server@2.1.0': + resolution: {integrity: sha512-XovyyCCnBzW+zKu+z/zq8hwNs4KOR5rEMAOxo2f40Q5xoOI37IMm6MIg2COOUtUApo0i6850MTBKH2u4QLGIqg==} engines: {node: '>=20'} peerDependencies: hono: ^4 @@ -1663,10 +1168,6 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@isaacs/cliui@9.0.0': - resolution: {integrity: sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==} - engines: {node: '>=18'} - '@isaacs/fs-minipass@4.0.1': resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} engines: {node: '>=18.0.0'} @@ -1681,9 +1182,6 @@ packages: resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - '@jridgewell/source-map@0.3.11': - resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} - '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} @@ -1748,9 +1246,9 @@ packages: '@marijn/find-cluster-break@1.0.3': resolution: {integrity: sha512-FY+MKLBoTsLNJF/eLWaOsXGdz6uh3Iu1axjPf6TUq92IYumcTcXWHoS747JARLkcdlJ/Waiaxc5wQfFO8jC6NA==} - '@methanium/ui@https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz': - resolution: {integrity: sha512-ij9zo/PdP5l/F/70t7a1o+OFZbMFRNNseNc1dlqddUFqIkAy+71VL6ptrXNpeVtzKFq8LuycwzXGsGihuViVig==, tarball: https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz} - version: 0.0.29 + '@methanium/ui@https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz': + resolution: {integrity: sha512-I0uTA21w9iHM1UQAtRTVJCMB93QgwB//PKTrnvwe5WjgU/EZ4H3wsC+zIfiQn4lpNCfoPtHhMjISWjxYLIUgsA==, tarball: https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz} + version: 0.0.28 peerDependencies: react: ^19.2.7 react-dom: ^19.2.7 @@ -1765,13 +1263,6 @@ packages: '@cfworker/json-schema': optional: true - '@napi-rs/lzma-linux-x64-gnu@1.5.1': - resolution: {integrity: sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==} - engines: {node: ^22.20 || ^24.12 || >=25} - cpu: [x64] - os: [linux] - libc: [glibc] - '@noble/hashes@1.4.0': resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} engines: {node: '>= 16'} @@ -2075,222 +1566,35 @@ packages: '@rolldown/pluginutils@1.0.1': resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} - '@rollup/plugin-babel@6.1.0': - resolution: {integrity: sha512-dFZNuFD2YRcoomP4oYf+DvQNSUA9ih+A3vUqopQx5EdtPGo3WBnQcI/S8pwpz91UsGfL0HsMSOlaMld8HrbubA==} - engines: {node: '>=14.0.0'} - peerDependencies: - '@babel/core': ^7.0.0 - '@types/babel__core': ^7.1.9 - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - '@types/babel__core': - optional: true - rollup: - optional: true - - '@rollup/plugin-node-resolve@16.0.3': - resolution: {integrity: sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.78.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-replace@6.0.3': - resolution: {integrity: sha512-J4RZarRvQAm5IF0/LwUUg+obsm+xZhYnbMXmXROyoSE1ATJe3oXSb9L5MMppdxP2ylNSjv6zFBwKYjcKMucVfA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-terser@1.0.0': - resolution: {integrity: sha512-FnCxhTBx6bMOYQrar6C8h3scPt8/JwIzw3+AJ2K++6guogH5fYaIFia+zZuhqv0eo1RN7W1Pz630SyvLbDjhtQ==} - engines: {node: '>=20.0.0'} - peerDependencies: - rollup: ^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/pluginutils@5.4.0': - resolution: {integrity: sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/rollup-android-arm-eabi@4.62.4': - resolution: {integrity: sha512-RrPokAb7dmbxFoeO3TloqHyOjgye8RkBhSqmp4aJMIex4c9r46ZstPnleDQOq1t46VOVjwIuwNogIqbodV1Vvg==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.62.4': - resolution: {integrity: sha512-JKuJc+pnpks2pjy7L/N3v/cAkZxYlnmuZoD840ldbMI5KDbC4iO9NKwPKYdjYFCMAIIlBzYSFHxIJVYzRo2/8A==} - cpu: [arm64] - os: [android] - - '@rollup/rollup-darwin-arm64@4.62.4': - resolution: {integrity: sha512-krw5uS2STmvJ02x0uTXHbqQNuz+9eZ1iw+qXk9dmW2gvV4jV7O2hEoOnuhFrpOPiel1mBFtqbxYZZtC46hXLOw==} - cpu: [arm64] - os: [darwin] - - '@rollup/rollup-darwin-x64@4.62.4': - resolution: {integrity: sha512-wsTxtgApb4PrOsNJIm0FZ1h3WvCC+k9uxLJ4ad75hgoS4NiRes2SoJFlDAyMwiUY8IssDqGcHbXuN0sx1tfF1A==} - cpu: [x64] - os: [darwin] - - '@rollup/rollup-freebsd-arm64@4.62.4': - resolution: {integrity: sha512-GUOnQlyZe3yAXhWOtOMsn5Qkrv5E5mZXa0thbARWi5Ei2szlVXJFQhddZ4HbAzh8q92w5twp+CQvs/eFanz9YQ==} - cpu: [arm64] - os: [freebsd] - - '@rollup/rollup-freebsd-x64@4.62.4': - resolution: {integrity: sha512-/Y7f3QuxjzPKsjA/rfEDa3+0vXqyjmJ50Ln8dPpCmWkKTrUoWHG1cWhTqaAMLob2m2nESWuC7yGrREz019Ztqg==} - cpu: [x64] - os: [freebsd] - - '@rollup/rollup-linux-arm-gnueabihf@4.62.4': - resolution: {integrity: sha512-81wiiX3v7aqy+T+bT61TJ78yJjRquqFFTTbAPt08imfQQzkPIW8t6aJbkTagtCCrXMNc9D66+geqlK7ydLPNqA==} - cpu: [arm] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-arm-musleabihf@4.62.4': - resolution: {integrity: sha512-9kmDIvNZqdoHOBZgNtpTBeLWYO/LVipM3H/j62P8848/l/VPEQL6N3uxU9pvP1oZAsXyC2MEnFP3ovRjo7WYNQ==} - cpu: [arm] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-arm64-gnu@4.62.4': - resolution: {integrity: sha512-CcnXHWnXg69g+DX5VWL3FHts3qMRN2uVEHX+BZvGLdd07/gXkn3ePjYtO1LDJvxkGKVHMclKBRa1QUTH+6toYQ==} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-arm64-musl@4.62.4': - resolution: {integrity: sha512-iFOibiHnTRuhrWLlRsOQFdZJJIa7S8OwkneJr4ocALP16u5yk6lWLINFwhHaEqBFMsKDUZofLkGos7+CPzGB3g==} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-loong64-gnu@4.62.4': - resolution: {integrity: sha512-XnWYMI7euHlb5a871xPja+Gm7DRCFU+FGRrtS2sMq9N8FvqtpagUy6gD4YOemC5MRk9xbh8+jYMEJbigFQwsgA==} - cpu: [loong64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-loong64-musl@4.62.4': - resolution: {integrity: sha512-qGDAlO0U8xedCcsdRm9oaoQY8DAx/QT7uIxJWhCdx0ceIWX783UC9QSYkdpzAe29wNiVfp24+bZdQmn49o45SQ==} - cpu: [loong64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-ppc64-gnu@4.62.4': - resolution: {integrity: sha512-ru4H6ezD7ysA5EiEK6qkkaEb4modH8CTej6kUy/gQi20u3kB3G7Zn8snXXkeJSCOFKG/rbPPtM/+9Wgas1961w==} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-ppc64-musl@4.62.4': - resolution: {integrity: sha512-2W4MO5WQVJnbJaZdvDb9rhBDuFU1nKIepPFpJUBsTh2k1YY2g+ODViaWuyOAjQ5cOP7NvrvLzt3wvHOoiAvc7w==} - cpu: [ppc64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-riscv64-gnu@4.62.4': - resolution: {integrity: sha512-+fxjfuoAmVMCYV5QyjoIpu0cp5DOiOTeqYFk1AVaxGr+/ravWLX89XfQmptsoWcaVy/TGf2hexzbUOrCQIL1CQ==} - cpu: [riscv64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-riscv64-musl@4.62.4': - resolution: {integrity: sha512-jTn8JfHGL4djjFxPuM06LmNUJDsst2jeVlsd9OmIH6zc5sC9K6rIuO4YajXatLUpBmBKl6b35ro1QZocLi+tcA==} - cpu: [riscv64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-s390x-gnu@4.62.4': - resolution: {integrity: sha512-oCJCJL4pXsoDcP2QZ+JVlPTIRc6266zsIaeJJsWImmF7HO0W8nb6HuSgZlMWxJwaPf8ehbSw8yo0EUw925hKsA==} - cpu: [s390x] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-x64-gnu@4.62.4': - resolution: {integrity: sha512-W69hukhZ3KKNRCaMIEzKvcFye42hh0FE1+YoYaf5+Ikacuftoco6yO/xouz0hc5d5W/s3yBro5jRiuEE/Q5vUw==} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-x64-musl@4.62.4': - resolution: {integrity: sha512-qiXbGG2jkjXhzXpsFZSR2Xpb8DN/UaxYsbb/STbuR/6fpaDgRmmaq1B/LmtF2wQFOFOSsK2jdE0RZ3a0zHn4QA==} - cpu: [x64] - os: [linux] - libc: [musl] - - '@rollup/rollup-openbsd-x64@4.62.4': - resolution: {integrity: sha512-nWeM//hxv8mIo6jD7Hu4o48DVmV9pbV6gsKaWU+4NFyqHoPKwrkRiZGLKUhOBk8qNmDmpwFtPKg80Bo/Tn4xiQ==} - cpu: [x64] - os: [openbsd] - - '@rollup/rollup-openharmony-arm64@4.62.4': - resolution: {integrity: sha512-s62SQ/vgsRSvMwDkOEfTqfgASF0f26ZNaQuTA6Aok5lrikf89yI2W0gFHvZb2Jpgc6N8JnOKZgCK2iciO3CsxQ==} - cpu: [arm64] - os: [openharmony] - - '@rollup/rollup-win32-arm64-msvc@4.62.4': - resolution: {integrity: sha512-J6wGf8TVGbXJq+HH+ttTvrcfNKPbuZecV6KT1B8I18BC5IURUh5kl4Yl5OEP5eFIUoI5BWxCsyYMhFsDx8kekw==} - cpu: [arm64] - os: [win32] - - '@rollup/rollup-win32-ia32-msvc@4.62.4': - resolution: {integrity: sha512-zmfrQd/0wu6oJs8Vq8KwY/YtsKSsLtKe/HwAP4Wqy8LhWjeT55fHRAkOhYQ12wI3ayS4Tt12d5CDRD7N96SAYQ==} - cpu: [ia32] - os: [win32] - - '@rollup/rollup-win32-x64-gnu@4.62.4': - resolution: {integrity: sha512-qPzHqdj9rfUD+w79dtE07zi/kFwKyCJqplp5K5ygeLTp7jLpAoc16OAH39HSmRC9UpozaecsleI8uAdEj6v2yw==} - cpu: [x64] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.62.4': - resolution: {integrity: sha512-zD6NdeWEByGE9QF9vCrlJ5YQB4oq9q91kPZS37Jwj5hOkvR1lTBSpsKhKDw4IJtbQ35LsTS1HD9DZYGKIshU1Q==} - cpu: [x64] - os: [win32] - '@sec-ant/readable-stream@0.4.1': resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} - '@shikijs/core@4.4.3': - resolution: {integrity: sha512-QCR4q2ZO/ILJEuwiBMel4wdcTDb1JGwfjKTxPDF6x8ixOaluPrVqIn06C99AcRPhmYlBR56d/Fb+GN58GzExpg==} + '@shikijs/core@4.4.2': + resolution: {integrity: sha512-StyzbAyxg2/tBGf78gwbBkGyeQ73lf8UiJArFaQhTQIDqQOCKPCQFanvrs4/Yv3Yfyc+ONInJM6K+FMIf+P+kA==} engines: {node: '>=20'} - '@shikijs/engine-javascript@4.4.3': - resolution: {integrity: sha512-FbOjFJp9VLdo1Wevs10BBtVxiTWwNLqZh5Gkhjgda/ioL15YOgeSl9n+6XMa3qRlPQzfhFNe641SrynFHYG0nQ==} + '@shikijs/engine-javascript@4.4.2': + resolution: {integrity: sha512-MnIkeqWdVPUWsxlx8gKLVCJFTsqrQJgpTPBPpQwaFeJ56lOnJxj5aN2LUFnfxUEcvOQuNocmbaMnVrCEln6rkw==} engines: {node: '>=20'} - '@shikijs/engine-oniguruma@4.4.3': - resolution: {integrity: sha512-EcOQkxdxGQrc1Row/cC2c96/v1dbZqGnEVu1qTuT/MJmp6+cXCvQussowVmCv5Tqr3KuY3c7IbM6HTW3LJ1k9w==} + '@shikijs/engine-oniguruma@4.4.2': + resolution: {integrity: sha512-GLhowz1+jixjz+wiZ3wMnOn1jTxiFCGl2PkXufivbnwPHKuyw1AYqu5/hbWhZZ2oAb0NP05WUJhYeigY14drnw==} engines: {node: '>=20'} - '@shikijs/langs@4.4.3': - resolution: {integrity: sha512-ePic0yfAJGOF83D5wBHK/00EjK65oahBYxFk5epgq33WRv7X9UuxLEV8PtR0szC0z8dl7INIpIodB99JRFlR+A==} + '@shikijs/langs@4.4.2': + resolution: {integrity: sha512-8DfeusD+Zdv/eYIDdXyJTUnSMHt+aAWjAOCXV20HNGAHRlInXpG8wh421v6B91WOm9TFwRLN+b/LG5F2NAIojg==} engines: {node: '>=20'} - '@shikijs/primitive@4.4.3': - resolution: {integrity: sha512-m0wBeLDQDeIxRdUmrCPdQqfuUamDwRL5isCfYbguKD6NiaKpVbsv+3J81DyIKgNW5h4WAIIr8T4EkgQrBBxvaQ==} + '@shikijs/primitive@4.4.2': + resolution: {integrity: sha512-l6fQQKsOMlz72n38fztmSgZ76MO6KSWuw8o+GJ+FhmqrpC9pIOJNQNXGgbb5yX2AwpzlEHwsaLPnk/8o4Fm+rA==} engines: {node: '>=20'} - '@shikijs/themes@4.4.3': - resolution: {integrity: sha512-w8UHjeUnIR965KMWJHUPXOc2mNJUnK3vpVLYLvw5IYU2mnTTJ89E24OrJDBNiJDQ0qzb0tc4l7mrIXx5cFeIyw==} + '@shikijs/themes@4.4.2': + resolution: {integrity: sha512-H0CFoL07ddDC2Dd6EdrPYNkRhUR6YCkJlnuYFceYYUJJA5TIm2b5B33qqiDYryBExgbKMndFJPb2u1gTuqO37g==} engines: {node: '>=20'} - '@shikijs/types@4.4.3': - resolution: {integrity: sha512-UEJxmRR++MAGR6hugn0vgVS2W/6lWAts84FFSrnlH9sP0LNol7E5+NQ792pH8liWUhyMyjhTgSUH3k7iD7tc5g==} + '@shikijs/types@4.4.2': + resolution: {integrity: sha512-PFYitV4vpDr/iPCIhnHp+Q4ftic5N5VeNJ3KQ1O8gn3h2ar8qgwMAXF7tq4m1CWaMS60fV4VqF6vfnWH4F7vqQ==} engines: {node: '>=20'} '@shikijs/vscode-textmate@10.0.2': @@ -2557,25 +1861,18 @@ packages: engines: {node: '>= 10'} hasBin: true + '@tauri-apps/plugin-barcode-scanner@2.4.5': + resolution: {integrity: sha512-sIPRYEfxww8/y8skZ2LcAp/h5bwvlHkQiq+3w6QEl+2BHs13xnpn7hP+pv4fkBs8DyDfpUbOBIYS5YBwP7x1QQ==} + '@tauri-apps/plugin-deep-link@2.4.9': resolution: {integrity: sha512-u0SKOUHnJ1wqeqXsDFq2+kASCBj9xxbG0g9XZWPy9SOmU4wXtp6b/wiYpm6oH6/5fBTQsLqnLhIvqLBRpgHJlA==} '@tauri-apps/plugin-notification@2.3.3': resolution: {integrity: sha512-Zw+ZH18RJb41G4NrfHgIuofJiymusqN+q8fGUIIV7vyCH+5sSn5coqRv/MWB9qETsUs97vmU045q7OyseCV3Qg==} - '@trickfilm400/rollup-plugin-off-main-thread@3.0.0-pre1': - resolution: {integrity: sha512-/67zpWDBLV+oYAEL682s1ktXL0HgqX76f6gaVGkGnVZlBbm1zd0v4Bz8MFF2GGhoX9rvfq3KSQHubFHwa6w6/Q==} - engines: {node: '>=12'} - '@ts-morph/common@0.27.0': resolution: {integrity: sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ==} - '@twemoji/api@17.0.3': - resolution: {integrity: sha512-iwERjxY0QgPGVwT6b1OKG0Oa9nIfHhJw+Ij1TapTBMKTvVCU6qdXPXX/XKwxKx5QZIJW5GwELUCtw8wlaIQ2ug==} - - '@twemoji/parser@17.0.2': - resolution: {integrity: sha512-X/P7pHsGOxnrupQYUVetIeuxBGgffFu8CLwoPMMjH9CWmQvlXiCpbTW/BXxMOCWXQojgHdmgdvm6IsCqAQ5nxA==} - '@types/cacheable-request@6.0.3': resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} @@ -2668,15 +1965,9 @@ packages: '@types/react@19.2.18': resolution: {integrity: sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==} - '@types/resolve@1.20.2': - resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} - '@types/responselike@1.0.3': resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} - '@types/trusted-types@2.0.7': - resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} - '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -2697,14 +1988,6 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/eslint-plugin@8.67.0': - resolution: {integrity: sha512-Un7Heoyj65NREbKAyIrFxeM143NZpExWmy1Nep4DLeQOeLlTeumPjoNKnBrU5D5moWXbPJgRa5Uwcdu0faVNGQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/parser': ^8.67.0 - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.66.0': resolution: {integrity: sha512-X6ypGChaWYk6PBtUg2BwuTZEFFcHJAtGTVJ9/lCTOufhZ4i9fNolQNnktq+kkMCwMj7V8Svsq7+TxSDslmhE0g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2712,45 +1995,22 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.67.0': - resolution: {integrity: sha512-fUBfTuuEulWqX6V8+O3PtScV01tzYYRUDTAirHFKoRAt7nOzoGiPt0M/bB47wWNy0coOOcgEwAMUtBpykMxl6w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.66.0': resolution: {integrity: sha512-7MthGPTt4BP69lSryqpqq8HQqxuzynssckL/jyDyk3+TNMQ3y2jFWkptCrktWvBrP+EH787Nl5N5Qpw7WZg+5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.67.0': - resolution: {integrity: sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.66.0': resolution: {integrity: sha512-8TGcH25j9zqJ/IULB/ppyhRvxA8QYfFEZ7nfbg6/BN9spDgb8fPWQXlE5l8TWBL50EtUx007uZ1o9VOwrq2/9g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/scope-manager@8.67.0': - resolution: {integrity: sha512-EgvsleTwS4E+WzzSvem8fAUubLwatMNF1B5hHSLQxcvs7q2dtRhGyujHwLJSYlG41niJ7GP24Aha2+0mb1b2kg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.66.0': resolution: {integrity: sha512-9D5gLYZG4rOjcoag8MQ/fWI8WqA9wcPDyOGyWtWFhvM1lHRbliqUSPIY5J3zqCU1tvSwzXxnnjhQhz5Ne7mJ4g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/tsconfig-utils@8.67.0': - resolution: {integrity: sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.66.0': resolution: {integrity: sha512-LG2dWfjZQQp0ADtAu/EWJVayefGL2UEZ3CDeI44D9v3rXB/WYUqE/jpO28KrEKul5AySrmI+Zh1v6v+xW2U9+g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2758,33 +2018,16 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.67.0': - resolution: {integrity: sha512-aVWDXbRmdXO9siTfX4ditQI1T9+zVcNazT48EJCD0v40/9RIFoUgZ05CmGEq9H2gixRpjUn/iplwvlcvutJW/Q==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.66.0': resolution: {integrity: sha512-H6gcYaSDOyvL3AD/jHUtUFo2jqGgn/F6nuyuZSu0QTesxL+cP4dQoIMrODRofuJC09g64+WgZ6tE19Y1N2YIFQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.67.0': - resolution: {integrity: sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.66.0': resolution: {integrity: sha512-8/x4INiiQb10jGgXYD7116/zQ+OL84ZIFn0za68wwFHCanT/VLbBEroWht8RV8fn0/ZCAoazHLQgwUC0UQcDfg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/typescript-estree@8.67.0': - resolution: {integrity: sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.66.0': resolution: {integrity: sha512-jasearZPolBw5NJNYGMwxzHMF83niVWmMU1VdHzG1CyfI2VS7f7nZltnKtHcg20hW+7Uo5GfK4MeDPoU3qI8EA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2792,21 +2035,10 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.67.0': - resolution: {integrity: sha512-U9D1FdwEWBwok3hxxSdhclMb0twvt9QnjIQ0VfQ1AiX2epnpSgv2ubVDsayOFyY8K6FX+AQ7E0FKWVG3iKsj1A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.66.0': resolution: {integrity: sha512-dkKR8q+lKciskj1Y3vthHktl+3cMLWGyVUP23bRiPZ5O9BRT++4EqDDV+TVeIKBL1VXVEqrJlz8MYbcnvJcAlg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/visitor-keys@8.67.0': - resolution: {integrity: sha512-fkv8dHRDqfGtTHuJeebdrQ7cX6Ad4WAS00rgHh9UGvMycF1mjBfsxry1XsLIFhWZ6Judlh6UdzK+TYlbpCXgnA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript/typescript-aix-ppc64@7.0.2': resolution: {integrity: sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==} engines: {node: '>=16.20.0'} @@ -2943,11 +2175,11 @@ packages: babel-plugin-react-compiler: optional: true - '@vitest/expect@4.1.11': - resolution: {integrity: sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==} + '@vitest/expect@4.1.10': + resolution: {integrity: sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==} - '@vitest/mocker@4.1.11': - resolution: {integrity: sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==} + '@vitest/mocker@4.1.10': + resolution: {integrity: sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==} peerDependencies: msw: ^2.4.9 vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -2957,25 +2189,24 @@ packages: vite: optional: true - '@vitest/pretty-format@4.1.11': - resolution: {integrity: sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==} + '@vitest/pretty-format@4.1.10': + resolution: {integrity: sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==} - '@vitest/runner@4.1.11': - resolution: {integrity: sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==} + '@vitest/runner@4.1.10': + resolution: {integrity: sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==} - '@vitest/snapshot@4.1.11': - resolution: {integrity: sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==} + '@vitest/snapshot@4.1.10': + resolution: {integrity: sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==} - '@vitest/spy@4.1.11': - resolution: {integrity: sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==} + '@vitest/spy@4.1.10': + resolution: {integrity: sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==} - '@vitest/utils@4.1.11': - resolution: {integrity: sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==} + '@vitest/utils@4.1.10': + resolution: {integrity: sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==} '@xmldom/xmldom@0.8.13': resolution: {integrity: sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==} engines: {node: '>=10.0.0'} - deprecated: this version has critical issues, please update to the latest version abbrev@4.0.0: resolution: {integrity: sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==} @@ -3029,8 +2260,8 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.3.0: - resolution: {integrity: sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==} + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} engines: {node: '>=12'} ansi-styles@4.3.0: @@ -3051,14 +2282,6 @@ packages: resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} engines: {node: '>=10'} - array-buffer-byte-length@1.0.2: - resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} - engines: {node: '>= 0.4'} - - arraybuffer.prototype.slice@1.0.4: - resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} - engines: {node: '>= 0.4'} - asn1js@3.0.10: resolution: {integrity: sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg==} engines: {node: '>=12.0.0'} @@ -3075,10 +2298,6 @@ packages: resolution: {integrity: sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==} engines: {node: '>=0.12.0'} - async-function@1.0.0: - resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} - engines: {node: '>= 0.4'} - async@3.2.6: resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} @@ -3093,28 +2312,9 @@ packages: resolution: {integrity: sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==} engines: {node: '>=10.12.0'} - available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - aws4@1.13.2: resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==} - babel-plugin-polyfill-corejs2@0.4.17: - resolution: {integrity: sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - - babel-plugin-polyfill-corejs3@0.14.2: - resolution: {integrity: sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - - babel-plugin-polyfill-regenerator@0.6.8: - resolution: {integrity: sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} @@ -3128,8 +2328,8 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.11.15: - resolution: {integrity: sha512-FwMjJJ7HnyZpWe+oWxegG0fezZyBZUagI5LZEoO3GCbtbKNwRfMH9Ue5d5v01PNePBy1QSfPSDTTeVL0Hb9EzA==} + baseline-browser-mapping@2.11.12: + resolution: {integrity: sha512-r7WnVImvVCeFpf2DOXfy41aPWzeNg3H/A2X4dKmy1QL0MSyyk/e7z8ihJ3N6Nn2PsdhkVlqnEfnUE4a05P2aTA==} engines: {node: '>=6.0.0'} hasBin: true @@ -3158,8 +2358,8 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.28.8: - resolution: {integrity: sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==} + browserslist@4.28.7: + resolution: {integrity: sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -3198,10 +2398,6 @@ packages: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} - call-bind@1.0.9: - resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} - engines: {node: '>= 0.4'} - call-bound@1.0.4: resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} engines: {node: '>= 0.4'} @@ -3308,9 +2504,6 @@ packages: resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} engines: {node: '>=20'} - 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'} @@ -3323,10 +2516,6 @@ packages: resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} engines: {node: ^12.20.0 || >=14} - common-tags@1.8.2: - resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} - engines: {node: '>=4.0.0'} - compare-version@0.1.2: resolution: {integrity: sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==} engines: {node: '>=0.10.0'} @@ -3346,8 +2535,8 @@ packages: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} - content-type@2.1.0: - resolution: {integrity: sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==} + content-type@2.0.0: + resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==} engines: {node: '>=18'} convert-source-map@2.0.0: @@ -3364,10 +2553,6 @@ packages: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} - core-js-compat@3.50.0: - resolution: {integrity: sha512-XGpFGbMLHwSt74YLTKho7Ib242qi6O8MSX+sRokV4oz7iKXvQWGYZthjIhjRGMxjzVkAubBO512dKGYcefmX3Q==} - engines: {node: '>=6.4.0'} - core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -3394,10 +2579,6 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} - crypto-random-string@2.0.0: - resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} - engines: {node: '>=8'} - cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -3450,18 +2631,6 @@ packages: resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} engines: {node: '>=12'} - data-view-buffer@1.0.2: - resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} - engines: {node: '>= 0.4'} - - data-view-byte-length@1.0.2: - resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} - engines: {node: '>= 0.4'} - - data-view-byte-offset@1.0.1: - resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} - engines: {node: '>= 0.4'} - debounce-fn@4.0.0: resolution: {integrity: sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==} engines: {node: '>=10'} @@ -3510,8 +2679,8 @@ packages: resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} engines: {node: '>=18'} - default-browser@5.5.1: - resolution: {integrity: sha512-m1pAzaJgZ/gssEqlOhJkPJp8Xly7QyW6xcrkUa2KKcDeDSEMP7X8xipU3snUcfisTQx0w1AGae+9UtJSfVnXGw==} + default-browser@5.5.0: + resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} engines: {node: '>=18'} defer-to-connect@2.0.1: @@ -3611,8 +2780,8 @@ packages: electron-publish@26.15.3: resolution: {integrity: sha512-g/2bn8YTavY4cuS5F+jOS7zmZbXXBV8KZ8yHKfJjFPoKtzBqrpCdNPxBd3tqdBwP7BVd0lGzf7Bk2s0KesWZ4Q==} - electron-to-chromium@1.5.411: - resolution: {integrity: sha512-gglkxzokjHfawpGxq75XdBV2/l3BAPzrsMs70qgaZdTW5rpV1tC4MdgJVP9fN126bODA4ZJQkn1wryEzJyQXIg==} + electron-to-chromium@1.5.402: + resolution: {integrity: sha512-/oOpMaPT6Yg+6/1XQhyIPlzgj7Ye9zf+nNM2Uh6OcE2G2oNptWazFa+qB2Pdqqbsc9KnIDzgAntoYN0dbwOXwA==} electron-winstaller@5.4.0: resolution: {integrity: sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==} @@ -3684,14 +2853,6 @@ packages: error-ex@1.3.4: resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} - es-abstract-get@1.0.0: - resolution: {integrity: sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==} - engines: {node: '>= 0.4'} - - es-abstract@1.24.2: - resolution: {integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==} - engines: {node: '>= 0.4'} - es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -3700,8 +2861,8 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-module-lexer@2.3.2: - resolution: {integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==} + es-module-lexer@2.3.1: + resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==} es-object-atoms@1.1.2: resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} @@ -3711,10 +2872,6 @@ packages: resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} engines: {node: '>= 0.4'} - es-to-primitive@1.3.4: - resolution: {integrity: sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==} - engines: {node: '>= 0.4'} - es-toolkit@1.50.0: resolution: {integrity: sha512-OyZKhUVvEep9ITEiwHn8GKnMRQIVqoSIX7WnRbkWgJkllCujilqP2rD0u979tkl8wqyc8ICwlc1UBVv/Sl1G6w==} @@ -3793,9 +2950,6 @@ packages: estree-util-is-identifier-name@3.0.0: resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} - estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -3803,10 +2957,6 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - eta@4.6.0: - resolution: {integrity: sha512-lW6is4T1NFOYnmqGZIfvixqj7A7sSvScF+DN8EK6K58xI5MZ5UvYe0GjopxOXQtZvUn4eDdVuZ8XSoYWTMEKwA==} - engines: {node: '>=20'} - etag@1.8.1: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} @@ -3818,8 +2968,8 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - eventsource-parser@3.1.1: - resolution: {integrity: sha512-EKN1vKAMcZ8MlYMpaNuxN6R9yakzH6uajHcHVTqWJzvu5pWw9DyhbP35HH8MVBQ+dZjAfDxk+A8NiR9KWaXiyQ==} + eventsource-parser@3.1.0: + resolution: {integrity: sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==} engines: {node: '>=18.0.0'} eventsource@3.0.7: @@ -3854,13 +3004,13 @@ packages: extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - fallow-type-aware@3.17.0: - resolution: {integrity: sha512-DFtZUK5oqP56tSsrBWPzjrTIwPPxwlBV8QoSaGghMru347Nqj8ZBY6u9HFa/TIPcxvFU/zIZMRF8xS/XAWQTzg==} + fallow-type-aware@3.14.0: + resolution: {integrity: sha512-D8+bNELjmoVV2dKpmHplQ1YzuheHltmZKaOVJ//hx7h8vFNyp5H3hcJV8rR26ofBU51z9K5eyA7FpgP3hebjwg==} engines: {node: '>=20'} hasBin: true - fallow@3.17.0: - resolution: {integrity: sha512-tbLuvsPq3I2CzpoF/9MgSQ7hWzOqlj3avFUAmCr1J9OERE6z714SlDmA38NVvNy/zuK/70utXB3/b33xC9z29g==} + fallow@3.14.0: + resolution: {integrity: sha512-hse+sChmWkrffLiZDPGdNSyiLybVEhgoiYCIYgqLwdYhfTCO+f2PS1g+gMhGAJdLlYpZ75tFwRoMBFmZjN3Q6g==} engines: {node: '>=22'} hasBin: true @@ -3926,14 +3076,6 @@ packages: flatted@3.4.4: resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==} - for-each@0.3.5: - resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} - engines: {node: '>= 0.4'} - - foreground-child@3.3.1: - resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} - engines: {node: '>=14'} - form-data@4.0.6: resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} engines: {node: '>= 6'} @@ -3992,20 +3134,9 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - function.prototype.name@1.2.0: - resolution: {integrity: sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==} - engines: {node: '>= 0.4'} - - functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - fuzzysort@3.1.0: resolution: {integrity: sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ==} - generator-function@2.0.1: - resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} - engines: {node: '>= 0.4'} - gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -4030,9 +3161,6 @@ packages: resolution: {integrity: sha512-PKsK2FSrQCyxcGHsGrLDcK0lx+0Ke+6e8KFFozA9/fIQLhQzPaRvJFdcz7+Axg3jUH/Mq+NI4xa5u/UT2tQskA==} engines: {node: '>=14.16'} - get-own-enumerable-property-symbols@3.0.2: - resolution: {integrity: sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==} - get-proto@1.0.1: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} @@ -4049,10 +3177,6 @@ packages: resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} engines: {node: '>=18'} - get-symbol-description@1.1.0: - resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} - engines: {node: '>= 0.4'} - github-slugger@2.0.0: resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} @@ -4064,12 +3188,6 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob@11.1.0: - resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} - engines: {node: 20 || >=22} - 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 - hasBin: true - glob@7.2.3: 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 @@ -4078,10 +3196,6 @@ packages: resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==} engines: {node: '>=10.0'} - globals@17.11.0: - resolution: {integrity: sha512-Z2I8hM+PbJDXQDq3Icgpzv+mPdwr68iZUU9d5WW4FuXfDUQfkZaZuvjMv42/5crNyw154+9+VWXbYrUgDXbxNw==} - engines: {node: '>=18'} - globals@17.9.0: resolution: {integrity: sha512-m/MvAW61QVU5VDNF1Vj8axt016h8w7L5TU1e9zlab7XIttAT2YAlCwl75K1fOqvMM9apmD7lbCIRhpfkhmxhCg==} engines: {node: '>=18'} @@ -4101,10 +3215,6 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - has-bigints@1.1.0: - resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} - engines: {node: '>= 0.4'} - has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -4112,10 +3222,6 @@ packages: has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - has-proto@1.2.0: - resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} - engines: {node: '>= 0.4'} - has-symbols@1.1.0: resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} @@ -4173,8 +3279,8 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} - hono@4.13.3: - resolution: {integrity: sha512-r8AO2mYHoLxSHkgafNeC/BXyb2vWRxD3jem4Ts+ptav8oTG5FIRifAjuJEmZI4bSvvc2ns0GxmIYiZnHqN3mMw==} + hono@4.13.1: + resolution: {integrity: sha512-kdJoFVv2xmayw6cY09H7AbMJMt8Jn5jdlEdXsP7AGBdF2DIptVlKlOLKXP41yPip4/a3yQPv9gVcJYI8YY04dw==} engines: {node: '>=16.9.0'} hosted-git-info@4.1.0: @@ -4218,9 +3324,6 @@ packages: resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==} engines: {node: '>=0.10.0'} - idb@7.1.1: - resolution: {integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==} - ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -4250,22 +3353,18 @@ packages: inline-style-parser@0.2.7: resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==} - input-otp@1.5.0: - resolution: {integrity: sha512-3AcfdW1sNG0FmSA5hHMBXG7jNW5CdcdKs8ln8JOmn6S2SRkoXoJx+2UwC+ZvjflfnOdHJx0SfQ9/YjlxVYLtGQ==} + input-otp@1.4.2: + resolution: {integrity: sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA==} peerDependencies: react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc - internal-slot@1.1.0: - resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} - engines: {node: '>= 0.4'} - internmap@2.0.3: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} - ip-address@10.5.0: - resolution: {integrity: sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g==} + ip-address@10.4.0: + resolution: {integrity: sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==} engines: {node: '>= 12'} ipaddr.js@1.9.1: @@ -4278,41 +3377,9 @@ packages: is-alphanumerical@2.0.1: resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} - is-array-buffer@3.0.5: - resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} - engines: {node: '>= 0.4'} - is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - is-async-function@2.1.1: - resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} - engines: {node: '>= 0.4'} - - is-bigint@1.1.0: - resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} - engines: {node: '>= 0.4'} - - is-boolean-object@1.2.2: - resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} - engines: {node: '>= 0.4'} - - is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - - is-core-module@2.16.2: - resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==} - engines: {node: '>= 0.4'} - - is-data-view@1.0.2: - resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} - engines: {node: '>= 0.4'} - - is-date-object@1.1.0: - resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} - engines: {node: '>= 0.4'} - is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} @@ -4326,26 +3393,14 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} hasBin: true - is-document.all@1.0.0: - resolution: {integrity: sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==} - engines: {node: '>= 0.4'} - is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - is-finalizationregistry@1.1.1: - resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} - engines: {node: '>= 0.4'} - is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-generator-function@1.1.2: - resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} - engines: {node: '>= 0.4'} - is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -4366,29 +3421,10 @@ packages: resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} engines: {node: '>=12'} - is-map@2.0.3: - resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} - engines: {node: '>= 0.4'} - - is-module@1.0.0: - resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} - - is-negative-zero@2.0.3: - resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} - engines: {node: '>= 0.4'} - - is-number-object@1.1.1: - resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} - engines: {node: '>= 0.4'} - is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - is-obj@1.0.1: - resolution: {integrity: sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==} - engines: {node: '>=0.10.0'} - is-obj@2.0.0: resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} engines: {node: '>=8'} @@ -4404,26 +3440,10 @@ packages: is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} - is-regex@1.2.1: - resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} - engines: {node: '>= 0.4'} - - is-regexp@1.0.0: - resolution: {integrity: sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==} - engines: {node: '>=0.10.0'} - is-regexp@3.1.0: resolution: {integrity: sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==} engines: {node: '>=12'} - is-set@2.0.3: - resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} - engines: {node: '>= 0.4'} - - is-shared-array-buffer@1.0.4: - resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} - engines: {node: '>= 0.4'} - is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} @@ -4432,18 +3452,6 @@ packages: resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} engines: {node: '>=18'} - is-string@1.1.1: - resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} - engines: {node: '>= 0.4'} - - is-symbol@1.1.1: - resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} - engines: {node: '>= 0.4'} - - is-typed-array@1.1.15: - resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} - engines: {node: '>= 0.4'} - is-unicode-supported@1.3.0: resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} engines: {node: '>=12'} @@ -4452,18 +3460,6 @@ packages: resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} engines: {node: '>=18'} - is-weakmap@2.0.2: - resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} - engines: {node: '>= 0.4'} - - is-weakref@1.1.1: - resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} - engines: {node: '>= 0.4'} - - is-weakset@2.0.4: - resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} - engines: {node: '>= 0.4'} - is-wsl@2.2.0: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} engines: {node: '>=8'} @@ -4475,9 +3471,6 @@ packages: isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - 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'} @@ -4501,10 +3494,6 @@ packages: resolution: {integrity: sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==} engines: {node: '>=20'} - jackspeak@4.2.3: - resolution: {integrity: sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==} - engines: {node: 20 || >=22} - jake@10.9.4: resolution: {integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==} engines: {node: '>=10'} @@ -4517,9 +3506,6 @@ packages: jose@6.2.8: resolution: {integrity: sha512-Bsdjwm3Qsd/P0jR+BHDe3LytDfY7WBq2HmCCLIwuVRHMuEC9ae7/R474GIUdF1NgCyZjzVo/A9DOiOBtXq8ZoQ==} - jose@6.2.9: - resolution: {integrity: sha512-XrchZOFZUl/T3vTwRe8XK+cJrGtMF4th1ARnDfwbBXFKThGhlsxEE4Zu03AD/bjJSt/9jT/mxrOCkJWOg77aPA==} - js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -4564,22 +3550,15 @@ packages: jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} - jsonfile@5.0.0: - resolution: {integrity: sha512-NQRZ5CRo74MhMMC3/3r5g2k4fjodJ/wh8MxjFbCViWKFjxrnudWSY5vomh+23ZaXzAS7J3fBZIR2dV6WbmfM0w==} - jsonfile@6.2.1: resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==} - jsonpointer@5.0.1: - resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} - engines: {node: '>=0.10.0'} - katex@0.16.47: resolution: {integrity: sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==} hasBin: true - katex@0.18.4: - resolution: {integrity: sha512-IMPntbRLOU+eu88XDiFKqQ8Akhr9Tv7jDMXqPhjG9SI1JMA4DIgXk4x9k4skJz2NZJXBRbC+2pYBLj9olqcZow==} + katex@0.18.2: + resolution: {integrity: sha512-3snve4y0SXTMequLim1FMiPvLGElySam0blN5xQZBqEY3lOJz1TnuaaiugnBZBqHzlSAGmFTYL7MCQkORuLKCA==} hasBin: true keyv@4.5.4: @@ -4596,10 +3575,6 @@ packages: 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'} - levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -4793,10 +3768,6 @@ packages: resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} engines: {node: '>=8'} - lru-cache@11.5.2: - resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} - engines: {node: 20 || >=22} - lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -4809,11 +3780,6 @@ packages: peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 - lucide-react@1.32.0: - resolution: {integrity: sha512-txX56hMFnRxPi1f9/nH69YN8uvAO6a7Y1KSWKjCDAtdD9+soEgmWuCt6iRm1pkxUZo2+YntSdsE1L6bIuKoY8Q==} - peerDependencies: - react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 - magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} @@ -5076,9 +4042,9 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - mtp@https://git.methanium.net/methanium/mtp/releases/download/0.3.0-dev-c7c7afe/mtp-0.3.0.tgz: - resolution: {integrity: sha512-MzqeWSaS2lVoiK0coNfY8EPgGNk7QYFS3eRqVYeYBCT0NNm2lQ7T8lLjBuIuMZ6Zh2KAVWhwI2xQIkMdZ7QThA==, tarball: https://git.methanium.net/methanium/mtp/releases/download/0.3.0-dev-c7c7afe/mtp-0.3.0.tgz} - version: 0.3.0 + mtp@https://git.methanium.net/methanium/mtp/releases/download/0.2.0-dev-a692bed/mtp-0.2.0.tgz: + resolution: {integrity: sha512-WcXHd53aDM0zQfO8eaUnK5tpnRP73GlWjwAMMcstcVAIWrvyFGuINkCRNEkb2RsNk9h57UMhxElCZeBkFrVmCg==, tarball: https://git.methanium.net/methanium/mtp/releases/download/0.2.0-dev-a692bed/mtp-0.2.0.tgz} + version: 0.2.0 nanoid@3.3.18: resolution: {integrity: sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==} @@ -5150,10 +4116,6 @@ packages: resolution: {integrity: sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==} engines: {node: '>= 10'} - object.assign@4.1.7: - resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} - engines: {node: '>= 0.4'} - obug@2.1.4: resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==} engines: {node: '>=12.20.0'} @@ -5179,8 +4141,8 @@ packages: oniguruma-to-es@4.3.6: resolution: {integrity: sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==} - open@11.0.1: - resolution: {integrity: sha512-NzwMUB6C1D0+Kd+9iMS/H4k+Ck3cTX6Ckyfr/gAGlmvSE1LUQZnEZvWBi4PYmMwH/S5SMeTXnE+9uAz8uF+pWw==} + open@11.0.0: + resolution: {integrity: sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==} engines: {node: '>=20'} open@8.4.2: @@ -5195,10 +4157,6 @@ packages: resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} engines: {node: '>=18'} - own-keys@1.0.2: - resolution: {integrity: sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==} - engines: {node: '>= 0.4'} - p-cancelable@2.1.1: resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} engines: {node: '>=8'} @@ -5223,9 +4181,6 @@ packages: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} - package-json-from-dist@1.0.1: - resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -5271,13 +4226,6 @@ packages: resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} engines: {node: '>=12'} - path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - - path-scurry@2.0.2: - resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} - engines: {node: 18 || 20 || >=22} - path-to-regexp@8.4.2: resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} @@ -5315,10 +4263,6 @@ packages: resolution: {integrity: sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==} engines: {node: '>=10.4.0'} - possible-typed-array-names@1.1.0: - resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} - engines: {node: '>= 0.4'} - postcss-selector-parser@7.1.5: resolution: {integrity: sha512-KvvtD7SrlBP7dlgkBghEE3r84CABm5SmV2aNcG4oCA+qDnJ/tvKonFVvwWAyyWUEwxuNawdfEAZKP9zM3oZ2Uw==} engines: {node: '>=4'} @@ -5336,10 +4280,6 @@ packages: resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==} engines: {node: '>=20'} - powershell-utils@0.2.0: - resolution: {integrity: sha512-ZlsFlG7MtSFCoc5xreOvBAozCJ6Pf06opgJjh9ONEv418xpZSAzNjstD36C6+JwOnfSqOW/9uDkqKjezTdxZhw==} - engines: {node: '>=20'} - prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -5349,14 +4289,6 @@ packages: engines: {node: '>=14'} hasBin: true - pretty-bytes@5.6.0: - resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} - engines: {node: '>=6'} - - pretty-bytes@6.1.1: - resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==} - engines: {node: ^14.13.1 || >=16.0.0} - pretty-ms@9.3.0: resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==} engines: {node: '>=18'} @@ -5469,8 +4401,8 @@ packages: '@types/react': optional: true - react-resizable-panels@4.12.3: - resolution: {integrity: sha512-GHMJWnDXui/3RX4bT+cgBP+N3N2nkwcoZATr/2xLFpqQQe7TlBrE0cGM0dUa9ceT7A90tUrSRsiqgRG+g0/2AA==} + react-resizable-panels@4.12.2: + resolution: {integrity: sha512-NwY5LCo4WrxVvDh0xoMML6EMLPONP/8ckKcIdpnojxexoatZdjLiRqLJQjQK5CPkd4SYiB/2M5BVrjZBQtOO7Q==} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 @@ -5496,8 +4428,8 @@ packages: readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - recast@0.23.21: - resolution: {integrity: sha512-mFAyJq9vUbSTARLZUvAEf1z3YxlvAwswbmxMx2mPA/MSm4KmpwvwvhsH/NIrZhyOuwD60Lzyw2qh83uCbgTPYw==} + recast@0.23.19: + resolution: {integrity: sha512-T98lym7kH+pnZmRaD8yDRdaNqyUbwnbEBx0MuchrzMFOEMray4AO3ZJoTUZ5r78Ao78X/OhzW0DL8GB85w/I2w==} engines: {node: '>= 4'} recharts@3.10.1: @@ -5516,17 +4448,6 @@ packages: redux@5.0.1: resolution: {integrity: sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==} - reflect.getprototypeof@1.0.10: - resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} - engines: {node: '>= 0.4'} - - regenerate-unicode-properties@10.2.2: - resolution: {integrity: sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==} - engines: {node: '>=4'} - - regenerate@1.4.2: - resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} - regex-recursion@6.0.2: resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==} @@ -5536,21 +4457,6 @@ packages: regex@6.1.0: resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==} - regexp.prototype.flags@1.5.4: - resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} - engines: {node: '>= 0.4'} - - regexpu-core@6.4.0: - resolution: {integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==} - engines: {node: '>=4'} - - regjsgen@0.8.0: - resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} - - regjsparser@0.13.2: - resolution: {integrity: sha512-NgRBy2Nx/bE+9F27nVHnqcN5HjyLmecqsqx2PJHu3/IEtADD4WuxuXIVExD5PoSDFVrl78dOonfcOe5O+5nbzQ==} - hasBin: true - rehype-autolink-headings@7.1.0: resolution: {integrity: sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw==} @@ -5600,11 +4506,6 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - resolve@1.22.12: - resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==} - engines: {node: '>= 0.4'} - hasBin: true - responselike@2.0.1: resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} @@ -5634,11 +4535,6 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true - rollup@4.62.4: - resolution: {integrity: sha512-RXOqwaPsBGjMNMa4sQjDjHieHEZDFoj/Rdr46l2MU5DfEs16wHJPC2RPTPHWhNl+M3aI472LLqFkFKut4SblOg==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - router@2.2.0: resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} engines: {node: '>= 18'} @@ -5653,21 +4549,9 @@ packages: rxjs@7.8.2: resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} - safe-array-concat@1.1.4: - resolution: {integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==} - engines: {node: '>=0.4'} - safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - safe-push-apply@1.0.0: - resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} - engines: {node: '>= 0.4'} - - safe-regex-test@1.1.0: - resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} - engines: {node: '>= 0.4'} - safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -5717,10 +4601,6 @@ packages: resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==} engines: {node: '>=10'} - serialize-javascript@7.1.0: - resolution: {integrity: sha512-RNEqWOyhhUQYN9V1GfHwu9AR/g+NTciH6Z5u3/no6X3/w+04J2lVDL+svFQVXgXrEGBMG2puMVN3gq2SNGuTGw==} - engines: {node: '>=20.0.0'} - seroval-plugins@1.6.2: resolution: {integrity: sha512-TfxuUjlbBESzUOWdTkTKqvSmav0ABym+itetDXLK6mDz8SmrpdI30aF8RTXE8Bvq+tH/1yIDkvy3W0lfQb1ipQ==} engines: {node: '>=10'} @@ -5735,23 +4615,11 @@ packages: resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} engines: {node: '>= 18'} - set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - - set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} - - set-proto@1.0.0: - resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} - engines: {node: '>= 0.4'} - setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - shadcn@4.18.0: - resolution: {integrity: sha512-tUFZgkYmfVNQVm3xX7lhSzOvDsp+O14ac5dwgXIr5mIsr79ISueb/Mu+ZtWMz0DH6v77u4eYyvbQ9TTMpSn3aw==} + shadcn@4.16.2: + resolution: {integrity: sha512-M1AvZKFWcCzWRDoyApIqJMSLIpY8Ev4uBGuiPLSFmiTbixXhPmzotSTvLzFmBrfoIxG9aIg2dZOETblEaXGUnQ==} engines: {node: '>=20.18.1'} hasBin: true @@ -5763,8 +4631,8 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - shiki@4.4.3: - resolution: {integrity: sha512-Mb/GvXPHBAXdgGIcnfU5L3ldpn1XcxrGkPHwqgRx17/I2XRfqlFKk2vGkHWINn1kdXvzJZeuO3is6I9KLPFm0g==} + shiki@4.4.2: + resolution: {integrity: sha512-P8F/dFhRevaw2uSdeIYlq/5SXZNY85DPtmXQ947gD1Zj2JqO5AkNvVVBar0Me9JkFx3uzVud/qOtP5ek9NEQGA==} engines: {node: '>=20'} side-channel-list@1.0.1: @@ -5800,34 +4668,12 @@ packages: sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - smart-buffer@4.2.0: - resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - - smob@1.6.2: - resolution: {integrity: sha512-RQsvleCbF8cVHEv+xuDGaA4pOizFqJ0GgjtMSRo6oP8pnN7WsigHgVGey6aILRBKv4W2YOMHLqbKdnB6hpB9fw==} - engines: {node: '>=20.0.0'} - - socks@2.8.9: - resolution: {integrity: sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==} - engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} - sonner@2.0.7: resolution: {integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==} peerDependencies: react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc - sonner@2.0.8: - resolution: {integrity: sha512-UM/ByIoFra8yzV75n1o0Puu0bw5U/9UNnDacrJNspekBewIfsQ3D6ez1nvlWpt7aTsO6rujQtifBpycwIivqlg==} - peerDependencies: - '@types/react': ^18.0.0 || ^19.0.0 - react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc - react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -5839,10 +4685,6 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - source-map@0.8.0: - resolution: {integrity: sha512-d8EqvL+k/SOXCreS/SUzg2ciyHqBBLcN/yuRjFsbvVhHTE2pgei7oAhmPM7kWFbkX6OSMQfUq4KbkF3au9lhYQ==} - engines: {node: '>= 12'} - space-separated-tokens@2.0.2: resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} @@ -5867,10 +4709,6 @@ packages: resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} engines: {node: '>=18'} - stop-iteration-iterator@1.1.0: - resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} - engines: {node: '>= 0.4'} - string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -5879,32 +4717,12 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} - string.prototype.matchall@4.0.12: - resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} - engines: {node: '>= 0.4'} - - string.prototype.trim@1.2.11: - resolution: {integrity: sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==} - engines: {node: '>= 0.4'} - - string.prototype.trimend@1.0.10: - resolution: {integrity: sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==} - engines: {node: '>= 0.4'} - - string.prototype.trimstart@1.0.8: - resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} - engines: {node: '>= 0.4'} - string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} stringify-entities@4.0.4: resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} - stringify-object@3.3.0: - resolution: {integrity: sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==} - engines: {node: '>=4'} - stringify-object@5.0.0: resolution: {integrity: sha512-zaJYxz2FtcMb4f+g60KsRNFOpVMUyuJgA51Zi5Z1DOTC3S59+OQiVOzE9GZt0x72uBGWKsQIuBKeF9iusmKFsg==} engines: {node: '>=14.16'} @@ -5921,10 +4739,6 @@ packages: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} - strip-comments@2.0.1: - resolution: {integrity: sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==} - engines: {node: '>=10'} - strip-final-newline@2.0.0: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} @@ -5950,10 +4764,6 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - systeminformation@5.33.1: resolution: {integrity: sha512-DEN6ICHk3Tk0Uf/hrAHh7xlt7iL5CJFBtPZinA0H62DrGG/KPKqq/Nzj6lCXPS4Ay/sf/14zNnk9LpqKzBIc+w==} engines: {node: '>=10.0.0'} @@ -5979,10 +4789,6 @@ packages: resolution: {integrity: sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==} engines: {node: '>=18'} - temp-dir@2.0.0: - resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} - engines: {node: '>=8'} - temp-file@3.4.0: resolution: {integrity: sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==} @@ -5990,15 +4796,6 @@ packages: resolution: {integrity: sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==} engines: {node: '>=6.0.0'} - tempy@0.6.0: - resolution: {integrity: sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==} - engines: {node: '>=10'} - - terser@5.50.0: - resolution: {integrity: sha512-CN9BVxWhgS/hRxtUMjtC2uRWSTcSfQFHMDWma6sKKfIivCD91sM+FOPfvwoaRMqCSrUpe1nv3jDamd9eEQ4y+w==} - engines: {node: '>=10'} - hasBin: true - tiny-async-pool@1.3.0: resolution: {integrity: sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA==} @@ -6071,30 +4868,10 @@ packages: resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} engines: {node: '>=10'} - type-fest@0.16.0: - resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==} - engines: {node: '>=10'} - type-is@2.1.0: resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==} engines: {node: '>= 18'} - typed-array-buffer@1.0.3: - resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} - engines: {node: '>= 0.4'} - - typed-array-byte-length@1.0.3: - resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} - engines: {node: '>= 0.4'} - - typed-array-byte-offset@1.0.4: - resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} - engines: {node: '>= 0.4'} - - typed-array-length@1.0.8: - resolution: {integrity: sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==} - engines: {node: '>= 0.4'} - typed-emitter@2.1.0: resolution: {integrity: sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==} @@ -6105,13 +4882,6 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - typescript-eslint@8.67.0: - resolution: {integrity: sha512-S2udFs8tCKEKffuJ4TB1idGUZiXdCPGi3IPBGWXarbLQ5UPXORV8QEVzJ4gCRduURMb5EkpNCdjbk0eDIuI8Yg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - typescript@6.0.3: resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} engines: {node: '>=14.17'} @@ -6122,10 +4892,6 @@ packages: engines: {node: '>=16.20.0'} hasBin: true - unbox-primitive@1.1.0: - resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} - engines: {node: '>= 0.4'} - undici-types@7.18.2: resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} @@ -6140,22 +4906,6 @@ packages: resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==} engines: {node: '>=20.18.1'} - unicode-canonical-property-names-ecmascript@2.0.1: - resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} - engines: {node: '>=4'} - - unicode-match-property-ecmascript@2.0.0: - resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} - engines: {node: '>=4'} - - unicode-match-property-value-ecmascript@2.2.1: - resolution: {integrity: sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==} - engines: {node: '>=4'} - - unicode-property-aliases-ecmascript@2.2.0: - resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} - engines: {node: '>=4'} - unicorn-magic@0.3.0: resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} engines: {node: '>=18'} @@ -6163,10 +4913,6 @@ packages: unified@11.0.5: resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} - unique-string@2.0.0: - resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} - engines: {node: '>=8'} - unist-util-find-after@5.0.0: resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==} @@ -6203,12 +4949,8 @@ packages: unzipper@0.12.5: resolution: {integrity: sha512-tXYOi9R57Uj/2Z25SOs5RRSzq886MBQj2gY8dPL+xl/kv6s6SvByoKfAtvfVeEuhntWDgjd2o9p2lb4TVPAz0A==} - upath@1.2.0: - resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} - engines: {node: '>=4'} - - update-browserslist-db@1.3.1: - resolution: {integrity: sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==} + update-browserslist-db@1.3.0: + resolution: {integrity: sha512-x/M6q3w4Ybp91CNaS4S69UnliqR3BzRpOT6LWbksjth0S/+jhfaPJsWjt/TewpT8j9eLIojUf5jr29WextHroA==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -6279,18 +5021,6 @@ packages: victory-vendor@37.3.6: resolution: {integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==} - vite-plugin-pwa@1.3.0: - resolution: {integrity: sha512-c5kMgN+ITrOtHXp8PAtk2uOIEea6XjP/unCGxOWWBzQ6qa65qj/awHg0wf+QF9E/2u9vh86LqxPwzEPNbM2r5A==} - engines: {node: '>=16.0.0'} - peerDependencies: - '@vite-pwa/assets-generator': ^1.0.0 - vite: ^3.1.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 - workbox-build: ^7.4.1 - workbox-window: ^7.4.1 - peerDependenciesMeta: - '@vite-pwa/assets-generator': - optional: true - vite@8.2.1: resolution: {integrity: sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -6334,20 +5064,20 @@ packages: yaml: optional: true - vitest@4.1.11: - resolution: {integrity: sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==} + vitest@4.1.10: + resolution: {integrity: sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@opentelemetry/api': ^1.9.0 '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.1.11 - '@vitest/browser-preview': 4.1.11 - '@vitest/browser-webdriverio': 4.1.11 - '@vitest/coverage-istanbul': 4.1.11 - '@vitest/coverage-v8': 4.1.11 - '@vitest/ui': 4.1.11 + '@vitest/browser-playwright': 4.1.10 + '@vitest/browser-preview': 4.1.10 + '@vitest/browser-webdriverio': 4.1.10 + '@vitest/coverage-istanbul': 4.1.10 + '@vitest/coverage-v8': 4.1.10 + '@vitest/ui': 4.1.10 happy-dom: '*' jsdom: '*' vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -6388,22 +5118,6 @@ packages: resolution: {integrity: sha512-CHbl2ZQbxx164IgWRgzJno4hWtM4tFbRam1QfI3Yxhs3w/DvqluVxVWeXs3oL5/fbGkSNLKo0Ty5MgUWceNhog==} engines: {node: '>=6.0.0', npm: '>=3.10.0'} - which-boxed-primitive@1.1.1: - resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} - engines: {node: '>= 0.4'} - - which-builtin-type@1.2.1: - resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} - engines: {node: '>= 0.4'} - - which-collection@1.0.2: - resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} - engines: {node: '>= 0.4'} - - which-typed-array@1.1.22: - resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==} - engines: {node: '>= 0.4'} - which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -6433,55 +5147,6 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} - workbox-background-sync@7.4.1: - resolution: {integrity: sha512-HhT7KE8tOWDm02wRNshXUnUPofMlhenF2DBdUnDPOubhizzPeItkYTmAB6td1Z2cjYPa98vzEiPLEuzn5hN66g==} - - workbox-broadcast-update@7.4.1: - resolution: {integrity: sha512-uAlgslKLvbQY+suirIdnBCSYrcgBhjp81Nj4l1lj/Jmj0MJO2CJERnCJjT0GFVwmReV0N+zs78K6gqd5gr9/+A==} - - workbox-build@7.4.1: - resolution: {integrity: sha512-SDhxIvEAde9Gy/5w4Yo1Jh/M49Z0qE3q0oteyE8zGq0DScxFqVBcCtIXFuLtmtxRQZCMbf0prco4VyEu3KBQuw==} - engines: {node: '>=20.0.0'} - - workbox-cacheable-response@7.4.1: - resolution: {integrity: sha512-8xaFoJdDc2OjrlbbL3gEeBO1WKcMwRqwLRupgqahYXu75yXajPLuwrbXMrIGZuWYXrQwk0xDjOxZ/ujCy/oJYw==} - - workbox-core@7.4.1: - resolution: {integrity: sha512-DT+vu46eh/2vRsSHTY4Xmc32Z1rr9PRlQUXr1Dx30ZuXRWwOsvZgGgcwxcasubQLQmbTNYZjv44LkBAQ4tT5tQ==} - - workbox-expiration@7.4.1: - resolution: {integrity: sha512-lRKUF7b+OGbeXkQk1s6MHXOa3d7Xxf7Of31W6c6hCfipfIyrtdWZ89stq21AHZMaoG7VNFoHply4Ox+rU31TWg==} - - workbox-google-analytics@7.4.1: - resolution: {integrity: sha512-Mks1JwLEt++ZAkF6sS1OpSh9RtAMIsiDgRpK+codiHGIPXeaUOgi4cPc3GFadUl8V5QPeypEk8Oxgl3HlwVzHw==} - - workbox-navigation-preload@7.4.1: - resolution: {integrity: sha512-C4KVsjPcYKJOhr631AxR9XoG2rLF3QiTk5aMv36MXOjtWvm8axwNFAtKUPGsWUwLXXAMgYM1En7fsvndaXeXRQ==} - - workbox-precaching@7.4.1: - resolution: {integrity: sha512-cdr/9qByww7yzEp7zg/qI4ukUrrNjQLgN+ONQRpjy/VqGQXwkgHwr00KksGJK8v0VifwDXBb8a4cWNZH71jn3Q==} - - workbox-range-requests@7.4.1: - resolution: {integrity: sha512-7i2oxAUE82gHdAJBCAQ04JzNOdRPqzuOzGfoUyJpFSmeqBNYGPrAH8GPoPjUQTfp+NycwrD2H68VtuF8qxv0vQ==} - - workbox-recipes@7.4.1: - resolution: {integrity: sha512-gnbVfmV4/TtmQaM4x9AtuXhcdstJsep3XMVeztOrQVPT+R6+6DeBjGTCQ7fFCXm+4GEHUA5VEBTyi5+4gWGeog==} - - workbox-routing@7.4.1: - resolution: {integrity: sha512-yubJGErZOusuidAenaL5ypfhQOa7urxP/f8E0ws7FPb4039RiWXUWBAyUkmUoOL/BcQGen3h0J8872d51IYxtA==} - - workbox-strategies@7.4.1: - resolution: {integrity: sha512-GZxpaw9NbmOelj7667uZ2kpk5BFpOGbO4X0qjwh5ls8XQ8C+Lha5LQchTiUzsTFSS+NlUpftYAyOVXvQUrcqOQ==} - - workbox-streams@7.4.1: - resolution: {integrity: sha512-HWWtraKUbJknd9kgqGcpQ3G114HOPYvqs8HaJMDs2ebLNAimDkVDaWfAXE6Ybl+m8U6KsCE6pWyLYuigWmnAXw==} - - workbox-sw@7.4.1: - resolution: {integrity: sha512-fez5f2DUlDJWTFYkCWQpY10N8gtztd849NswCbVFk0QlcSM4HT5A8x4g4ii650yem4I8tHY0R7JZahwp3ltIPw==} - - workbox-window@7.4.1: - resolution: {integrity: sha512-notZDH2u8VXaqyuD7xaqIfEFi6SRM4SUSd7ewe9PDsVqADuepxX2ZMY3uvuZGxzY5ZOsGC/vD3A/3smFtJt4/A==} - wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -6489,8 +5154,8 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - wsl-utils@1.0.0: - resolution: {integrity: sha512-Hl0ZOAs672vg+06kfujwRhoS6/jehvULrlFkuF2dRu6pHgA8U06h3xqNIqNNU1LTXPcedxByAR4GS6pwQK0mgA==} + wsl-utils@0.3.1: + resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==} engines: {node: '>=20'} xmlbuilder@15.1.1: @@ -6576,12 +5241,6 @@ packages: snapshots: - '@apideck/better-ajv-errors@0.3.7(ajv@8.20.0)': - dependencies: - ajv: 8.20.0 - jsonpointer: 5.0.1 - leven: 3.1.0 - '@babel/code-frame@7.29.7': dependencies: '@babel/helper-validator-identifier': 7.29.7 @@ -6626,7 +5285,7 @@ snapshots: dependencies: '@babel/compat-data': 7.29.7 '@babel/helper-validator-option': 7.29.7 - browserslist: 4.28.8 + browserslist: 4.28.7 lru-cache: 5.1.1 semver: 6.3.1 @@ -6643,24 +5302,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-create-regexp-features-plugin@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-annotate-as-pure': 7.29.7 - regexpu-core: 6.4.0 - semver: 6.3.1 - - '@babel/helper-define-polyfill-provider@0.6.8(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-compilation-targets': 7.29.7 - '@babel/helper-plugin-utils': 7.29.7 - debug: 4.4.3(supports-color@7.2.0) - lodash.debounce: 4.0.8 - resolve: 1.22.12 - transitivePeerDependencies: - - supports-color - '@babel/helper-globals@7.29.7': {} '@babel/helper-member-expression-to-functions@7.29.7(supports-color@7.2.0)': @@ -6692,15 +5333,6 @@ snapshots: '@babel/helper-plugin-utils@7.29.7': {} - '@babel/helper-remap-async-to-generator@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-annotate-as-pure': 7.29.7 - '@babel/helper-wrap-function': 7.29.7(supports-color@7.2.0) - '@babel/traverse': 7.29.8(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - '@babel/helper-replace-supers@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': dependencies: '@babel/core': 7.29.7(supports-color@7.2.0) @@ -6723,14 +5355,6 @@ snapshots: '@babel/helper-validator-option@7.29.7': {} - '@babel/helper-wrap-function@7.29.7(supports-color@7.2.0)': - dependencies: - '@babel/template': 7.29.7 - '@babel/traverse': 7.29.8(supports-color@7.2.0) - '@babel/types': 7.29.8 - transitivePeerDependencies: - - supports-color - '@babel/helpers@7.29.7': dependencies: '@babel/template': 7.29.7 @@ -6740,63 +5364,6 @@ snapshots: dependencies: '@babel/types': 7.29.8 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/traverse': 7.29.8(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@7.2.0) - '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/traverse': 7.29.8(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - - '@babel/plugin-syntax-import-assertions@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-syntax-import-attributes@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': dependencies: '@babel/core': 7.29.7(supports-color@7.2.0) @@ -6807,172 +5374,6 @@ snapshots: '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-arrow-functions@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-async-generator-functions@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-remap-async-to-generator': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/traverse': 7.29.8(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-async-to-generator@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-module-imports': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-remap-async-to-generator': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-block-scoped-functions@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-block-scoping@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-class-properties@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-class-static-block@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-classes@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-annotate-as-pure': 7.29.7 - '@babel/helper-compilation-targets': 7.29.7 - '@babel/helper-globals': 7.29.7 - '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/traverse': 7.29.8(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-computed-properties@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/template': 7.29.7 - - '@babel/plugin-transform-destructuring@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/traverse': 7.29.8(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-dotall-regex@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-duplicate-keys@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-dynamic-import@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-explicit-resource-management@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-exponentiation-operator@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-export-namespace-from@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-for-of@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-function-name@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-compilation-targets': 7.29.7 - '@babel/helper-plugin-utils': 7.29.7 - '@babel/traverse': 7.29.8(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-json-strings@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-literals@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-logical-assignment-operators@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-member-expression-literals@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-modules-amd@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - transitivePeerDependencies: - - supports-color - '@babel/plugin-transform-modules-commonjs@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': dependencies: '@babel/core': 7.29.7(supports-color@7.2.0) @@ -6981,148 +5382,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-systemjs@7.29.8(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-validator-identifier': 7.29.7 - '@babel/traverse': 7.29.8(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-modules-umd@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-named-capturing-groups-regex@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-new-target@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-nullish-coalescing-operator@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-numeric-separator@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-object-rest-spread@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-compilation-targets': 7.29.7 - '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-parameters': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/traverse': 7.29.8(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-object-super@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-optional-catch-binding@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-optional-chaining@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-parameters@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-private-methods@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-private-property-in-object@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-annotate-as-pure': 7.29.7 - '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-property-literals@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-regenerator@7.29.8(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-regexp-modifiers@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-reserved-words@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-shorthand-properties@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-spread@7.29.8(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-sticky-regex@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-template-literals@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-typeof-symbol@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-typescript@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': dependencies: '@babel/core': 7.29.7(supports-color@7.2.0) @@ -7134,113 +5393,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-unicode-escapes@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-unicode-property-regex@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-unicode-regex@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-unicode-sets-regex@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/preset-env@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': - dependencies: - '@babel/compat-data': 7.29.7 - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-compilation-targets': 7.29.7 - '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-validator-option': 7.29.7 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-bugfix-safari-rest-destructuring-rhs-array': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-syntax-import-assertions': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-syntax-import-attributes': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-arrow-functions': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-async-generator-functions': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-async-to-generator': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-block-scoped-functions': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-block-scoping': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-class-properties': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-class-static-block': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-classes': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-computed-properties': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-dotall-regex': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-duplicate-keys': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-dynamic-import': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-explicit-resource-management': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-exponentiation-operator': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-export-namespace-from': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-for-of': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-function-name': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-json-strings': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-literals': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-logical-assignment-operators': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-member-expression-literals': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-modules-amd': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-modules-systemjs': 7.29.8(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-modules-umd': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-named-capturing-groups-regex': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-new-target': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-nullish-coalescing-operator': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-numeric-separator': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-object-rest-spread': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-object-super': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-optional-catch-binding': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-parameters': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-private-methods': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-private-property-in-object': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-property-literals': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-regenerator': 7.29.8(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-regexp-modifiers': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-reserved-words': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-shorthand-properties': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-spread': 7.29.8(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/plugin-transform-sticky-regex': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-template-literals': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-typeof-symbol': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-unicode-escapes': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-unicode-property-regex': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-unicode-regex': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/plugin-transform-unicode-sets-regex': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.29.7(supports-color@7.2.0)) - babel-plugin-polyfill-corejs2: 0.4.17(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - babel-plugin-polyfill-corejs3: 0.14.2(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - babel-plugin-polyfill-regenerator: 0.6.8(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - core-js-compat: 3.50.0 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.29.7(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/types': 7.29.8 - esutils: 2.0.3 - '@babel/preset-typescript@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': dependencies: '@babel/core': 7.29.7(supports-color@7.2.0) @@ -7306,14 +5458,14 @@ snapshots: dependencies: '@codemirror/language': 6.12.4 '@codemirror/state': 6.7.1 - '@codemirror/view': 6.43.9 + '@codemirror/view': 6.43.8 '@lezer/common': 1.5.2 - '@codemirror/commands@6.11.0': + '@codemirror/commands@6.10.4': dependencies: '@codemirror/language': 6.12.4 '@codemirror/state': 6.7.1 - '@codemirror/view': 6.43.9 + '@codemirror/view': 6.43.8 '@lezer/common': 1.5.2 '@codemirror/lang-css@6.3.1': @@ -7331,7 +5483,7 @@ snapshots: '@codemirror/lang-javascript': 6.2.5 '@codemirror/language': 6.12.4 '@codemirror/state': 6.7.1 - '@codemirror/view': 6.43.9 + '@codemirror/view': 6.43.8 '@lezer/common': 1.5.2 '@lezer/css': 1.3.6 '@lezer/html': 1.3.13 @@ -7342,7 +5494,7 @@ snapshots: '@codemirror/language': 6.12.4 '@codemirror/lint': 6.9.7 '@codemirror/state': 6.7.1 - '@codemirror/view': 6.43.9 + '@codemirror/view': 6.43.8 '@lezer/common': 1.5.2 '@lezer/javascript': 1.5.4 @@ -7352,14 +5504,14 @@ snapshots: '@codemirror/lang-html': 6.4.12 '@codemirror/language': 6.12.4 '@codemirror/state': 6.7.1 - '@codemirror/view': 6.43.9 + '@codemirror/view': 6.43.8 '@lezer/common': 1.5.2 '@lezer/markdown': 1.7.2 '@codemirror/language@6.12.4': dependencies: '@codemirror/state': 6.7.1 - '@codemirror/view': 6.43.9 + '@codemirror/view': 6.43.8 '@lezer/common': 1.5.2 '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.10 @@ -7368,14 +5520,14 @@ snapshots: '@codemirror/lint@6.9.7': dependencies: '@codemirror/state': 6.7.1 - '@codemirror/view': 6.43.9 + '@codemirror/view': 6.43.8 crelt: 1.0.7 '@codemirror/state@6.7.1': dependencies: '@marijn/find-cluster-break': 1.0.3 - '@codemirror/view@6.43.9': + '@codemirror/view@6.43.8': dependencies: '@codemirror/state': 6.7.1 crelt: 1.0.7 @@ -7609,28 +5761,28 @@ snapshots: '@eslint/core': 1.2.1 levn: 0.4.1 - '@fallow-cli/darwin-arm64@3.17.0': + '@fallow-cli/darwin-arm64@3.14.0': optional: true - '@fallow-cli/darwin-x64@3.17.0': + '@fallow-cli/darwin-x64@3.14.0': optional: true - '@fallow-cli/linux-arm64-gnu@3.17.0': + '@fallow-cli/linux-arm64-gnu@3.14.0': optional: true - '@fallow-cli/linux-arm64-musl@3.17.0': + '@fallow-cli/linux-arm64-musl@3.14.0': optional: true - '@fallow-cli/linux-x64-gnu@3.17.0': + '@fallow-cli/linux-x64-gnu@3.14.0': optional: true - '@fallow-cli/linux-x64-musl@3.17.0': + '@fallow-cli/linux-x64-musl@3.14.0': optional: true - '@fallow-cli/win32-arm64-msvc@3.17.0': + '@fallow-cli/win32-arm64-msvc@3.14.0': optional: true - '@fallow-cli/win32-x64-msvc@3.17.0': + '@fallow-cli/win32-x64-msvc@3.14.0': optional: true '@floating-ui/core@1.8.0': @@ -7657,9 +5809,9 @@ snapshots: '@fontsource-variable/public-sans@5.3.0': {} - '@hono/node-server@2.1.1(hono@4.13.3)': + '@hono/node-server@2.1.0(hono@4.13.1)': dependencies: - hono: 4.13.3 + hono: 4.13.1 '@humanfs/core@0.19.2': dependencies: @@ -7677,8 +5829,6 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} - '@isaacs/cliui@9.0.0': {} - '@isaacs/fs-minipass@4.0.1': dependencies: minipass: 7.1.3 @@ -7695,11 +5845,6 @@ snapshots: '@jridgewell/resolve-uri@3.1.2': {} - '@jridgewell/source-map@0.3.11': - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - '@jridgewell/sourcemap-codec@1.5.5': {} '@jridgewell/trace-mapping@0.3.31': @@ -7781,16 +5926,16 @@ snapshots: '@marijn/find-cluster-break@1.0.3': {} - '@methanium/ui@https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3)': + '@methanium/ui@https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(emojibase@17.0.0)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1)(supports-color@7.2.0)(typescript@6.0.3)': dependencies: '@base-ui/react': 1.7.0(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@codemirror/autocomplete': 6.20.3 - '@codemirror/commands': 6.11.0 + '@codemirror/commands': 6.10.4 '@codemirror/lang-markdown': 6.5.2 '@codemirror/language': 6.12.4 '@codemirror/state': 6.7.1 - '@codemirror/view': 6.43.9 - '@shikijs/langs': 4.4.3 + '@codemirror/view': 6.43.8 + '@shikijs/langs': 4.4.2 '@tauri-apps/api': 2.11.1 class-variance-authority: 0.7.1 clsx: 2.1.1 @@ -7798,14 +5943,14 @@ snapshots: embla-carousel-react: 8.6.0(react@19.2.8) emojibase-data: 17.0.0(emojibase@17.0.0) hast-util-to-jsx-runtime: 2.3.6(supports-color@7.2.0) - input-otp: 1.5.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8) - katex: 0.18.4 - lucide-react: 1.32.0(react@19.2.8) + input-otp: 1.4.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + katex: 0.18.2 + lucide-react: 1.30.0(react@19.2.8) next-themes: 0.4.6(react-dom@19.2.8(react@19.2.8))(react@19.2.8) react: 19.2.8 react-dom: 19.2.8(react@19.2.8) react-markdown: 10.1.0(@types/react@19.2.18)(react@19.2.8)(supports-color@7.2.0) - react-resizable-panels: 4.12.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + react-resizable-panels: 4.12.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8) recharts: 3.10.1(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react-is@19.2.8)(react@19.2.8)(redux@5.0.1) rehype-autolink-headings: 7.1.0 rehype-katex: 7.0.1 @@ -7813,9 +5958,9 @@ snapshots: remark-breaks: 4.0.0 remark-gfm: 4.0.1(supports-color@7.2.0) remark-math: 6.0.0(supports-color@7.2.0) - shadcn: 4.18.0(supports-color@7.2.0)(typescript@6.0.3) - shiki: 4.4.3 - sonner: 2.0.8(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + shadcn: 4.16.2(supports-color@7.2.0)(typescript@6.0.3) + shiki: 4.4.2 + sonner: 2.0.7(react-dom@19.2.8(react@19.2.8))(react@19.2.8) tailwind-merge: 3.6.0 tw-animate-css: 1.4.0 unist-util-visit: 5.1.0 @@ -7835,18 +5980,18 @@ snapshots: '@modelcontextprotocol/sdk@1.30.0(supports-color@7.2.0)(zod@3.25.76)': dependencies: - '@hono/node-server': 2.1.1(hono@4.13.3) + '@hono/node-server': 2.1.0(hono@4.13.1) ajv: 8.20.0 ajv-formats: 3.0.1(ajv@8.20.0) content-type: 1.0.5 cors: 2.8.6 cross-spawn: 7.0.6 eventsource: 3.0.7 - eventsource-parser: 3.1.1 + eventsource-parser: 3.1.0 express: 5.2.1(supports-color@7.2.0) express-rate-limit: 8.6.2(express@5.2.1(supports-color@7.2.0))(supports-color@7.2.0) - hono: 4.13.3 - jose: 6.2.9 + hono: 4.13.1 + jose: 6.2.8 json-schema-typed: 8.0.2 pkce-challenge: 5.0.1 raw-body: 3.0.2 @@ -7855,9 +6000,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@napi-rs/lzma-linux-x64-gnu@1.5.1': - optional: true - '@noble/hashes@1.4.0': {} '@noble/hashes@2.3.0': {} @@ -8091,160 +6233,42 @@ snapshots: '@rolldown/pluginutils@1.0.1': {} - '@rollup/plugin-babel@6.1.0(@babel/core@7.29.7(supports-color@7.2.0))(rollup@4.62.4)(supports-color@7.2.0)': - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-module-imports': 7.29.7(supports-color@7.2.0) - '@rollup/pluginutils': 5.4.0(rollup@4.62.4) - optionalDependencies: - rollup: 4.62.4 - transitivePeerDependencies: - - supports-color - - '@rollup/plugin-node-resolve@16.0.3(rollup@4.62.4)': - dependencies: - '@rollup/pluginutils': 5.4.0(rollup@4.62.4) - '@types/resolve': 1.20.2 - deepmerge: 4.3.1 - is-module: 1.0.0 - resolve: 1.22.12 - optionalDependencies: - rollup: 4.62.4 - - '@rollup/plugin-replace@6.0.3(rollup@4.62.4)': - dependencies: - '@rollup/pluginutils': 5.4.0(rollup@4.62.4) - magic-string: 0.30.21 - optionalDependencies: - rollup: 4.62.4 - - '@rollup/plugin-terser@1.0.0(rollup@4.62.4)': - dependencies: - serialize-javascript: 7.1.0 - smob: 1.6.2 - terser: 5.50.0 - optionalDependencies: - rollup: 4.62.4 - - '@rollup/pluginutils@5.4.0(rollup@4.62.4)': - dependencies: - '@types/estree': 1.0.9 - estree-walker: 2.0.2 - picomatch: 4.0.5 - optionalDependencies: - rollup: 4.62.4 - - '@rollup/rollup-android-arm-eabi@4.62.4': - optional: true - - '@rollup/rollup-android-arm64@4.62.4': - optional: true - - '@rollup/rollup-darwin-arm64@4.62.4': - optional: true - - '@rollup/rollup-darwin-x64@4.62.4': - optional: true - - '@rollup/rollup-freebsd-arm64@4.62.4': - optional: true - - '@rollup/rollup-freebsd-x64@4.62.4': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.62.4': - optional: true - - '@rollup/rollup-linux-arm-musleabihf@4.62.4': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.62.4': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.62.4': - optional: true - - '@rollup/rollup-linux-loong64-gnu@4.62.4': - optional: true - - '@rollup/rollup-linux-loong64-musl@4.62.4': - optional: true - - '@rollup/rollup-linux-ppc64-gnu@4.62.4': - optional: true - - '@rollup/rollup-linux-ppc64-musl@4.62.4': - optional: true - - '@rollup/rollup-linux-riscv64-gnu@4.62.4': - optional: true - - '@rollup/rollup-linux-riscv64-musl@4.62.4': - optional: true - - '@rollup/rollup-linux-s390x-gnu@4.62.4': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.62.4': - optional: true - - '@rollup/rollup-linux-x64-musl@4.62.4': - optional: true - - '@rollup/rollup-openbsd-x64@4.62.4': - optional: true - - '@rollup/rollup-openharmony-arm64@4.62.4': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.62.4': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.62.4': - optional: true - - '@rollup/rollup-win32-x64-gnu@4.62.4': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.62.4': - optional: true - '@sec-ant/readable-stream@0.4.1': {} - '@shikijs/core@4.4.3': + '@shikijs/core@4.4.2': dependencies: - '@shikijs/primitive': 4.4.3 - '@shikijs/types': 4.4.3 + '@shikijs/primitive': 4.4.2 + '@shikijs/types': 4.4.2 '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.5 hast-util-to-html: 9.0.5 - '@shikijs/engine-javascript@4.4.3': + '@shikijs/engine-javascript@4.4.2': dependencies: - '@shikijs/types': 4.4.3 + '@shikijs/types': 4.4.2 '@shikijs/vscode-textmate': 10.0.2 oniguruma-to-es: 4.3.6 - '@shikijs/engine-oniguruma@4.4.3': + '@shikijs/engine-oniguruma@4.4.2': dependencies: - '@shikijs/types': 4.4.3 + '@shikijs/types': 4.4.2 '@shikijs/vscode-textmate': 10.0.2 - '@shikijs/langs@4.4.3': + '@shikijs/langs@4.4.2': dependencies: - '@shikijs/types': 4.4.3 + '@shikijs/types': 4.4.2 - '@shikijs/primitive@4.4.3': + '@shikijs/primitive@4.4.2': dependencies: - '@shikijs/types': 4.4.3 + '@shikijs/types': 4.4.2 '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.5 - '@shikijs/themes@4.4.3': + '@shikijs/themes@4.4.2': dependencies: - '@shikijs/types': 4.4.3 + '@shikijs/types': 4.4.2 - '@shikijs/types@4.4.3': + '@shikijs/types@4.4.2': dependencies: '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.5 @@ -8324,12 +6348,12 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.3.3 '@tailwindcss/oxide-win32-x64-msvc': 4.3.3 - '@tailwindcss/vite@4.3.3(vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0))': + '@tailwindcss/vite@4.3.3(vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))': dependencies: '@tailwindcss/node': 4.3.3 '@tailwindcss/oxide': 4.3.3 tailwindcss: 4.3.3 - vite: 8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0) '@tanstack/devtools-event-client@0.4.4': {} @@ -8449,6 +6473,10 @@ snapshots: '@tauri-apps/cli-win32-ia32-msvc': 2.11.4 '@tauri-apps/cli-win32-x64-msvc': 2.11.4 + '@tauri-apps/plugin-barcode-scanner@2.4.5': + dependencies: + '@tauri-apps/api': 2.11.1 + '@tauri-apps/plugin-deep-link@2.4.9': dependencies: '@tauri-apps/api': 2.11.1 @@ -8457,28 +6485,12 @@ snapshots: dependencies: '@tauri-apps/api': 2.11.1 - '@trickfilm400/rollup-plugin-off-main-thread@3.0.0-pre1': - dependencies: - ejs: 3.1.10 - json5: 2.2.3 - magic-string: 0.30.21 - string.prototype.matchall: 4.0.12 - '@ts-morph/common@0.27.0': dependencies: fast-glob: 3.3.3 minimatch: 10.2.6 path-browserify: 1.0.1 - '@twemoji/api@17.0.3': - dependencies: - '@twemoji/parser': 17.0.2 - fs-extra: 8.1.0 - jsonfile: 5.0.0 - universalify: 0.1.2 - - '@twemoji/parser@17.0.2': {} - '@types/cacheable-request@6.0.3': dependencies: '@types/http-cache-semantics': 4.2.0 @@ -8575,14 +6587,10 @@ snapshots: dependencies: csstype: 3.2.3 - '@types/resolve@1.20.2': {} - '@types/responselike@1.0.3': dependencies: '@types/node': 26.2.0 - '@types/trusted-types@2.0.7': {} - '@types/unist@2.0.11': {} '@types/unist@3.0.3': {} @@ -8607,22 +6615,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/eslint-plugin@8.67.0(@typescript-eslint/parser@8.67.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': - dependencies: - '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.67.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.67.0 - '@typescript-eslint/type-utils': 8.67.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/utils': 8.67.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.67.0 - eslint: 10.8.1(jiti@2.7.0)(supports-color@7.2.0) - ignore: 7.0.6 - natural-compare: 1.4.0 - ts-api-utils: 2.5.0(typescript@6.0.3) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/parser@8.66.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': dependencies: '@typescript-eslint/scope-manager': 8.66.0 @@ -8635,18 +6627,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.67.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': - dependencies: - '@typescript-eslint/scope-manager': 8.67.0 - '@typescript-eslint/types': 8.67.0 - '@typescript-eslint/typescript-estree': 8.67.0(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.67.0 - debug: 4.4.3(supports-color@7.2.0) - eslint: 10.8.1(jiti@2.7.0)(supports-color@7.2.0) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/project-service@8.66.0(supports-color@7.2.0)(typescript@6.0.3)': dependencies: '@typescript-eslint/tsconfig-utils': 8.66.0(typescript@6.0.3) @@ -8656,33 +6636,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.67.0(supports-color@7.2.0)(typescript@6.0.3)': - dependencies: - '@typescript-eslint/tsconfig-utils': 8.67.0(typescript@6.0.3) - '@typescript-eslint/types': 8.67.0 - debug: 4.4.3(supports-color@7.2.0) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/scope-manager@8.66.0': dependencies: '@typescript-eslint/types': 8.66.0 '@typescript-eslint/visitor-keys': 8.66.0 - '@typescript-eslint/scope-manager@8.67.0': - dependencies: - '@typescript-eslint/types': 8.67.0 - '@typescript-eslint/visitor-keys': 8.67.0 - '@typescript-eslint/tsconfig-utils@8.66.0(typescript@6.0.3)': dependencies: typescript: 6.0.3 - '@typescript-eslint/tsconfig-utils@8.67.0(typescript@6.0.3)': - dependencies: - typescript: 6.0.3 - '@typescript-eslint/type-utils@8.66.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': dependencies: '@typescript-eslint/types': 8.66.0 @@ -8695,22 +6657,8 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/type-utils@8.67.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': - dependencies: - '@typescript-eslint/types': 8.67.0 - '@typescript-eslint/typescript-estree': 8.67.0(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/utils': 8.67.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - debug: 4.4.3(supports-color@7.2.0) - eslint: 10.8.1(jiti@2.7.0)(supports-color@7.2.0) - ts-api-utils: 2.5.0(typescript@6.0.3) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/types@8.66.0': {} - '@typescript-eslint/types@8.67.0': {} - '@typescript-eslint/typescript-estree@8.66.0(supports-color@7.2.0)(typescript@6.0.3)': dependencies: '@typescript-eslint/project-service': 8.66.0(supports-color@7.2.0)(typescript@6.0.3) @@ -8726,21 +6674,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@8.67.0(supports-color@7.2.0)(typescript@6.0.3)': - dependencies: - '@typescript-eslint/project-service': 8.67.0(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/tsconfig-utils': 8.67.0(typescript@6.0.3) - '@typescript-eslint/types': 8.67.0 - '@typescript-eslint/visitor-keys': 8.67.0 - debug: 4.4.3(supports-color@7.2.0) - minimatch: 10.2.6 - semver: 7.8.5 - tinyglobby: 0.2.17 - ts-api-utils: 2.5.0(typescript@6.0.3) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/utils@8.66.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': dependencies: '@eslint-community/eslint-utils': 4.10.1(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0)) @@ -8752,27 +6685,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.67.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': - dependencies: - '@eslint-community/eslint-utils': 4.10.1(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0)) - '@typescript-eslint/scope-manager': 8.67.0 - '@typescript-eslint/types': 8.67.0 - '@typescript-eslint/typescript-estree': 8.67.0(supports-color@7.2.0)(typescript@6.0.3) - eslint: 10.8.1(jiti@2.7.0)(supports-color@7.2.0) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/visitor-keys@8.66.0': dependencies: '@typescript-eslint/types': 8.66.0 eslint-visitor-keys: 5.0.1 - '@typescript-eslint/visitor-keys@8.67.0': - dependencies: - '@typescript-eslint/types': 8.67.0 - eslint-visitor-keys: 5.0.1 - '@typescript/typescript-aix-ppc64@7.0.2': optional: true @@ -8835,49 +6752,49 @@ snapshots: '@ungap/structured-clone@1.3.3': {} - '@vitejs/plugin-react@6.0.5(vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0))': + '@vitejs/plugin-react@6.0.5(vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))': dependencies: '@rolldown/pluginutils': 1.0.1 - vite: 8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0) - '@vitest/expect@4.1.11': + '@vitest/expect@4.1.10': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 4.1.11 - '@vitest/utils': 4.1.11 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 chai: 6.2.2 tinyrainbow: 3.1.1 - '@vitest/mocker@4.1.11(vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0))': + '@vitest/mocker@4.1.10(vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))': dependencies: - '@vitest/spy': 4.1.11 + '@vitest/spy': 4.1.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0) - '@vitest/pretty-format@4.1.11': + '@vitest/pretty-format@4.1.10': dependencies: tinyrainbow: 3.1.1 - '@vitest/runner@4.1.11': + '@vitest/runner@4.1.10': dependencies: - '@vitest/utils': 4.1.11 + '@vitest/utils': 4.1.10 pathe: 2.0.3 - '@vitest/snapshot@4.1.11': + '@vitest/snapshot@4.1.10': dependencies: - '@vitest/pretty-format': 4.1.11 - '@vitest/utils': 4.1.11 + '@vitest/pretty-format': 4.1.10 + '@vitest/utils': 4.1.10 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@4.1.11': {} + '@vitest/spy@4.1.10': {} - '@vitest/utils@4.1.11': + '@vitest/utils@4.1.10': dependencies: - '@vitest/pretty-format': 4.1.11 + '@vitest/pretty-format': 4.1.10 convert-source-map: 2.0.0 tinyrainbow: 3.1.1 @@ -8924,7 +6841,7 @@ snapshots: ansi-regex@5.0.1: {} - ansi-regex@6.3.0: {} + ansi-regex@6.2.2: {} ansi-styles@4.3.0: dependencies: @@ -8984,21 +6901,6 @@ snapshots: dependencies: tslib: 2.8.1 - array-buffer-byte-length@1.0.2: - dependencies: - call-bound: 1.0.4 - is-array-buffer: 3.0.5 - - arraybuffer.prototype.slice@1.0.4: - dependencies: - array-buffer-byte-length: 1.0.2 - call-bind: 1.0.9 - define-properties: 1.2.1 - es-abstract: 1.24.2 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - is-array-buffer: 3.0.5 - asn1js@3.0.10: dependencies: pvtsutils: 1.3.6 @@ -9013,8 +6915,6 @@ snapshots: async-exit-hook@2.0.1: {} - async-function@1.0.0: {} - async@3.2.6: {} asynckit@0.4.0: {} @@ -9023,36 +6923,8 @@ snapshots: atomically@1.7.0: {} - available-typed-arrays@1.0.7: - dependencies: - possible-typed-array-names: 1.1.0 - aws4@1.13.2: {} - babel-plugin-polyfill-corejs2@0.4.17(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0): - dependencies: - '@babel/compat-data': 7.29.7 - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - babel-plugin-polyfill-corejs3@0.14.2(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0): - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - core-js-compat: 3.50.0 - transitivePeerDependencies: - - supports-color - - babel-plugin-polyfill-regenerator@0.6.8(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0): - dependencies: - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - transitivePeerDependencies: - - supports-color - bail@2.0.2: {} balanced-match@1.0.2: {} @@ -9061,14 +6933,14 @@ snapshots: base64-js@1.5.1: {} - baseline-browser-mapping@2.11.15: {} + baseline-browser-mapping@2.11.12: {} bluebird@3.7.2: {} body-parser@2.3.0(supports-color@7.2.0): dependencies: bytes: 3.1.2 - content-type: 2.1.0 + content-type: 2.0.0 debug: 4.4.3(supports-color@7.2.0) http-errors: 2.0.1 iconv-lite: 0.7.3 @@ -9099,13 +6971,13 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.28.8: + browserslist@4.28.7: dependencies: - baseline-browser-mapping: 2.11.15 + baseline-browser-mapping: 2.11.12 caniuse-lite: 1.0.30001809 - electron-to-chromium: 1.5.411 + electron-to-chromium: 1.5.402 node-releases: 2.0.53 - update-browserslist-db: 1.3.1(browserslist@4.28.8) + update-browserslist-db: 1.3.0(browserslist@4.28.7) buffer-from@1.1.2: {} @@ -9160,13 +7032,6 @@ snapshots: es-errors: 1.3.0 function-bind: 1.1.2 - call-bind@1.0.9: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - get-intrinsic: 1.3.0 - set-function-length: 1.2.2 - call-bound@1.0.4: dependencies: call-bind-apply-helpers: 1.0.2 @@ -9255,8 +7120,6 @@ snapshots: commander@14.0.3: {} - commander@2.20.3: {} - commander@5.1.0: {} commander@8.3.0: {} @@ -9264,8 +7127,6 @@ snapshots: commander@9.5.0: optional: true - common-tags@1.8.2: {} - compare-version@0.1.2: {} concat-map@0.0.1: {} @@ -9287,7 +7148,7 @@ snapshots: content-type@1.0.5: {} - content-type@2.1.0: {} + content-type@2.0.0: {} convert-source-map@2.0.0: {} @@ -9297,10 +7158,6 @@ snapshots: cookie@0.7.2: {} - core-js-compat@3.50.0: - dependencies: - browserslist: 4.28.8 - core-util-is@1.0.3: {} cors@2.8.6: @@ -9328,8 +7185,6 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - crypto-random-string@2.0.0: {} - cssesc@3.0.0: {} csstype@3.2.3: {} @@ -9372,24 +7227,6 @@ snapshots: d3-timer@3.0.1: {} - data-view-buffer@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - data-view-byte-length@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - data-view-byte-offset@1.0.1: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-data-view: 1.0.2 - debounce-fn@4.0.0: dependencies: mimic-fn: 3.1.0 @@ -9422,7 +7259,7 @@ snapshots: default-browser-id@5.0.1: {} - default-browser@5.5.1: + default-browser@5.5.0: dependencies: bundle-name: 4.1.0 default-browser-id: 5.0.1 @@ -9434,6 +7271,7 @@ snapshots: es-define-property: 1.0.1 es-errors: 1.3.0 gopd: 1.2.0 + optional: true define-lazy-prop@2.0.0: {} @@ -9444,6 +7282,7 @@ snapshots: define-data-property: 1.1.4 has-property-descriptors: 1.0.2 object-keys: 1.1.1 + optional: true delayed-stream@1.0.0: {} @@ -9546,7 +7385,7 @@ snapshots: transitivePeerDependencies: - supports-color - electron-to-chromium@1.5.411: {} + electron-to-chromium@1.5.402: {} electron-winstaller@5.4.0(supports-color@7.2.0): dependencies: @@ -9618,75 +7457,11 @@ snapshots: dependencies: is-arrayish: 0.2.1 - es-abstract-get@1.0.0: - dependencies: - es-errors: 1.3.0 - es-object-atoms: 1.1.2 - is-callable: 1.2.7 - object-inspect: 1.13.4 - - es-abstract@1.24.2: - dependencies: - array-buffer-byte-length: 1.0.2 - arraybuffer.prototype.slice: 1.0.4 - available-typed-arrays: 1.0.7 - call-bind: 1.0.9 - call-bound: 1.0.4 - data-view-buffer: 1.0.2 - data-view-byte-length: 1.0.2 - data-view-byte-offset: 1.0.1 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.2 - es-set-tostringtag: 2.1.0 - es-to-primitive: 1.3.4 - function.prototype.name: 1.2.0 - get-intrinsic: 1.3.0 - get-proto: 1.0.1 - get-symbol-description: 1.1.0 - globalthis: 1.0.4 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - has-proto: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.4 - internal-slot: 1.1.0 - is-array-buffer: 3.0.5 - is-callable: 1.2.7 - is-data-view: 1.0.2 - is-negative-zero: 2.0.3 - is-regex: 1.2.1 - is-set: 2.0.3 - is-shared-array-buffer: 1.0.4 - is-string: 1.1.1 - is-typed-array: 1.1.15 - is-weakref: 1.1.1 - math-intrinsics: 1.1.0 - object-inspect: 1.13.4 - object-keys: 1.1.1 - object.assign: 4.1.7 - own-keys: 1.0.2 - regexp.prototype.flags: 1.5.4 - safe-array-concat: 1.1.4 - safe-push-apply: 1.0.0 - safe-regex-test: 1.1.0 - set-proto: 1.0.0 - stop-iteration-iterator: 1.1.0 - string.prototype.trim: 1.2.11 - string.prototype.trimend: 1.0.10 - string.prototype.trimstart: 1.0.8 - typed-array-buffer: 1.0.3 - typed-array-byte-length: 1.0.3 - typed-array-byte-offset: 1.0.4 - typed-array-length: 1.0.8 - unbox-primitive: 1.1.0 - which-typed-array: 1.1.22 - es-define-property@1.0.1: {} es-errors@1.3.0: {} - es-module-lexer@2.3.2: {} + es-module-lexer@2.3.1: {} es-object-atoms@1.1.2: dependencies: @@ -9699,15 +7474,6 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.4 - es-to-primitive@1.3.4: - dependencies: - es-abstract-get: 1.0.0 - es-define-property: 1.0.1 - es-errors: 1.3.0 - is-callable: 1.2.7 - is-date-object: 1.1.0 - is-symbol: 1.1.1 - es-toolkit@1.50.0: {} es6-error@4.1.1: @@ -9829,27 +7595,23 @@ snapshots: estree-util-is-identifier-name@3.0.0: {} - estree-walker@2.0.2: {} - estree-walker@3.0.3: dependencies: '@types/estree': 1.0.9 esutils@2.0.3: {} - eta@4.6.0: {} - etag@1.8.1: {} eventemitter3@5.0.4: {} events@3.3.0: {} - eventsource-parser@3.1.1: {} + eventsource-parser@3.1.0: {} eventsource@3.0.7: dependencies: - eventsource-parser: 3.1.1 + eventsource-parser: 3.1.0 execa@5.1.1: dependencies: @@ -9886,7 +7648,7 @@ snapshots: dependencies: debug: 4.4.3(supports-color@7.2.0) express: 5.2.1(supports-color@7.2.0) - ip-address: 10.5.0 + ip-address: 10.4.0 transitivePeerDependencies: - supports-color @@ -9925,24 +7687,24 @@ snapshots: extend@3.0.2: {} - fallow-type-aware@3.17.0: + fallow-type-aware@3.14.0: dependencies: typescript: 7.0.2 optional: true - fallow@3.17.0: + fallow@3.14.0: dependencies: detect-libc: 2.1.2 optionalDependencies: - '@fallow-cli/darwin-arm64': 3.17.0 - '@fallow-cli/darwin-x64': 3.17.0 - '@fallow-cli/linux-arm64-gnu': 3.17.0 - '@fallow-cli/linux-arm64-musl': 3.17.0 - '@fallow-cli/linux-x64-gnu': 3.17.0 - '@fallow-cli/linux-x64-musl': 3.17.0 - '@fallow-cli/win32-arm64-msvc': 3.17.0 - '@fallow-cli/win32-x64-msvc': 3.17.0 - fallow-type-aware: 3.17.0 + '@fallow-cli/darwin-arm64': 3.14.0 + '@fallow-cli/darwin-x64': 3.14.0 + '@fallow-cli/linux-arm64-gnu': 3.14.0 + '@fallow-cli/linux-arm64-musl': 3.14.0 + '@fallow-cli/linux-x64-gnu': 3.14.0 + '@fallow-cli/linux-x64-musl': 3.14.0 + '@fallow-cli/win32-arm64-msvc': 3.14.0 + '@fallow-cli/win32-x64-msvc': 3.14.0 + fallow-type-aware: 3.14.0 fast-deep-equal@3.1.3: {} @@ -10011,15 +7773,6 @@ snapshots: flatted@3.4.4: {} - for-each@0.3.5: - dependencies: - is-callable: 1.2.7 - - foreground-child@3.3.1: - dependencies: - cross-spawn: 7.0.6 - signal-exit: 4.1.0 - form-data@4.0.6: dependencies: asynckit: 0.4.0 @@ -10085,24 +7838,8 @@ snapshots: function-bind@1.1.2: {} - function.prototype.name@1.2.0: - dependencies: - call-bind: 1.0.9 - call-bound: 1.0.4 - es-define-property: 1.0.1 - es-errors: 1.3.0 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - hasown: 2.0.4 - is-callable: 1.2.7 - is-document.all: 1.0.0 - - functions-have-names@1.2.3: {} - fuzzysort@3.1.0: {} - generator-function@2.0.1: {} - gensync@1.0.0-beta.2: {} get-caller-file@2.0.5: {} @@ -10126,8 +7863,6 @@ snapshots: get-own-enumerable-keys@1.0.0: {} - get-own-enumerable-property-symbols@3.0.2: {} - get-proto@1.0.1: dependencies: dunder-proto: 1.0.1 @@ -10144,12 +7879,6 @@ snapshots: '@sec-ant/readable-stream': 0.4.1 is-stream: 4.0.1 - get-symbol-description@1.1.0: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - github-slugger@2.0.0: {} glob-parent@5.1.2: @@ -10160,15 +7889,6 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@11.1.0: - dependencies: - foreground-child: 3.3.1 - jackspeak: 4.2.3 - minimatch: 10.2.6 - minipass: 7.1.3 - package-json-from-dist: 1.0.1 - path-scurry: 2.0.2 - glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -10188,14 +7908,13 @@ snapshots: serialize-error: 7.0.1 optional: true - globals@17.11.0: {} - globals@17.9.0: {} globalthis@1.0.4: dependencies: define-properties: 1.2.1 gopd: 1.2.0 + optional: true gopd@1.2.0: {} @@ -10215,17 +7934,12 @@ snapshots: graceful-fs@4.2.11: {} - has-bigints@1.1.0: {} - has-flag@4.0.0: {} has-property-descriptors@1.0.2: dependencies: es-define-property: 1.0.1 - - has-proto@1.2.0: - dependencies: - dunder-proto: 1.0.1 + optional: true has-symbols@1.1.0: {} @@ -10345,7 +8059,7 @@ snapshots: dependencies: hermes-estree: 0.25.1 - hono@4.13.3: {} + hono@4.13.1: {} hosted-git-info@4.1.0: dependencies: @@ -10392,8 +8106,6 @@ snapshots: dependencies: safer-buffer: 2.1.2 - idb@7.1.1: {} - ignore@5.3.2: {} ignore@7.0.6: {} @@ -10416,20 +8128,14 @@ snapshots: inline-style-parser@0.2.7: {} - input-otp@1.5.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8): + input-otp@1.4.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8): dependencies: react: 19.2.8 react-dom: 19.2.8(react@19.2.8) - internal-slot@1.1.0: - dependencies: - es-errors: 1.3.0 - hasown: 2.0.4 - side-channel: 1.1.1 - internmap@2.0.3: {} - ip-address@10.5.0: {} + ip-address@10.4.0: {} ipaddr.js@1.9.1: {} @@ -10440,74 +8146,18 @@ snapshots: is-alphabetical: 2.0.1 is-decimal: 2.0.1 - is-array-buffer@3.0.5: - dependencies: - call-bind: 1.0.9 - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - is-arrayish@0.2.1: {} - is-async-function@2.1.1: - dependencies: - async-function: 1.0.0 - call-bound: 1.0.4 - get-proto: 1.0.1 - has-tostringtag: 1.0.2 - safe-regex-test: 1.1.0 - - is-bigint@1.1.0: - dependencies: - has-bigints: 1.1.0 - - is-boolean-object@1.2.2: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - - is-callable@1.2.7: {} - - is-core-module@2.16.2: - dependencies: - hasown: 2.0.4 - - is-data-view@1.0.2: - dependencies: - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - is-typed-array: 1.1.15 - - is-date-object@1.1.0: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - is-decimal@2.0.1: {} is-docker@2.2.1: {} is-docker@3.0.0: {} - is-document.all@1.0.0: - dependencies: - call-bound: 1.0.4 - is-extglob@2.1.1: {} - is-finalizationregistry@1.1.1: - dependencies: - call-bound: 1.0.4 - is-fullwidth-code-point@3.0.0: {} - is-generator-function@1.1.2: - dependencies: - call-bound: 1.0.4 - generator-function: 2.0.1 - get-proto: 1.0.1 - has-tostringtag: 1.0.2 - safe-regex-test: 1.1.0 - is-glob@4.0.3: dependencies: is-extglob: 2.1.1 @@ -10522,21 +8172,8 @@ snapshots: is-interactive@2.0.0: {} - is-map@2.0.3: {} - - is-module@1.0.0: {} - - is-negative-zero@2.0.3: {} - - is-number-object@1.1.1: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - is-number@7.0.0: {} - is-obj@1.0.1: {} - is-obj@2.0.0: {} is-obj@3.0.0: {} @@ -10545,57 +8182,16 @@ snapshots: is-promise@4.0.0: {} - is-regex@1.2.1: - dependencies: - call-bound: 1.0.4 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - hasown: 2.0.4 - - is-regexp@1.0.0: {} - is-regexp@3.1.0: {} - is-set@2.0.3: {} - - is-shared-array-buffer@1.0.4: - dependencies: - call-bound: 1.0.4 - is-stream@2.0.1: {} is-stream@4.0.1: {} - is-string@1.1.1: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - - is-symbol@1.1.1: - dependencies: - call-bound: 1.0.4 - has-symbols: 1.1.0 - safe-regex-test: 1.1.0 - - is-typed-array@1.1.15: - dependencies: - which-typed-array: 1.1.22 - is-unicode-supported@1.3.0: {} is-unicode-supported@2.1.0: {} - is-weakmap@2.0.2: {} - - is-weakref@1.1.1: - dependencies: - call-bound: 1.0.4 - - is-weakset@2.0.4: - dependencies: - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - is-wsl@2.2.0: dependencies: is-docker: 2.2.1 @@ -10606,8 +8202,6 @@ snapshots: isarray@1.0.0: {} - isarray@2.0.5: {} - isbinaryfile@4.0.10: {} isbinaryfile@5.0.7: {} @@ -10620,10 +8214,6 @@ snapshots: isexe@4.0.0: {} - jackspeak@4.2.3: - dependencies: - '@isaacs/cliui': 9.0.0 - jake@10.9.4: dependencies: async: 3.2.6 @@ -10634,8 +8224,6 @@ snapshots: jose@6.2.8: {} - jose@6.2.9: {} - js-tokens@4.0.0: {} js-yaml@4.3.1: @@ -10667,25 +8255,17 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 - jsonfile@5.0.0: - dependencies: - universalify: 0.1.2 - optionalDependencies: - graceful-fs: 4.2.11 - jsonfile@6.2.1: dependencies: universalify: 2.0.1 optionalDependencies: graceful-fs: 4.2.11 - jsonpointer@5.0.1: {} - katex@0.16.47: dependencies: commander: 8.3.0 - katex@0.18.4: + katex@0.18.2: dependencies: commander: 8.3.0 @@ -10699,8 +8279,6 @@ snapshots: lazy-val@1.0.5: {} - leven@3.1.0: {} - levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -10845,8 +8423,6 @@ snapshots: lowercase-keys@2.0.0: {} - lru-cache@11.5.2: {} - lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -10859,10 +8435,6 @@ snapshots: dependencies: react: 19.2.8 - lucide-react@1.32.0(react@19.2.8): - dependencies: - react: 19.2.8 - magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -11328,7 +8900,7 @@ snapshots: ms@2.1.3: {} - mtp@https://git.methanium.net/methanium/mtp/releases/download/0.3.0-dev-c7c7afe/mtp-0.3.0.tgz: + mtp@https://git.methanium.net/methanium/mtp/releases/download/0.2.0-dev-a692bed/mtp-0.2.0.tgz: dependencies: yaml: 2.9.0 @@ -11387,19 +8959,11 @@ snapshots: object-inspect@1.13.4: {} - object-keys@1.1.1: {} + object-keys@1.1.1: + optional: true object-treeify@1.1.33: {} - object.assign@4.1.7: - dependencies: - call-bind: 1.0.9 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-object-atoms: 1.1.2 - has-symbols: 1.1.0 - object-keys: 1.1.1 - obug@2.1.4: {} on-finished@2.4.1: @@ -11426,14 +8990,14 @@ snapshots: regex: 6.1.0 regex-recursion: 6.0.2 - open@11.0.1: + open@11.0.0: dependencies: - default-browser: 5.5.1 + default-browser: 5.5.0 define-lazy-prop: 3.0.0 is-in-ssh: 1.0.0 is-inside-container: 1.0.0 - powershell-utils: 0.2.0 - wsl-utils: 1.0.0 + powershell-utils: 0.1.0 + wsl-utils: 0.3.1 open@8.4.2: dependencies: @@ -11462,13 +9026,6 @@ snapshots: string-width: 7.2.0 strip-ansi: 7.2.0 - own-keys@1.0.2: - dependencies: - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - object-keys: 1.1.1 - safe-push-apply: 1.0.0 - p-cancelable@2.1.1: {} p-limit@2.3.0: @@ -11489,8 +9046,6 @@ snapshots: p-try@2.2.0: {} - package-json-from-dist@1.0.1: {} - parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -11532,13 +9087,6 @@ snapshots: path-key@4.0.0: {} - path-parse@1.0.7: {} - - path-scurry@2.0.2: - dependencies: - lru-cache: 11.5.2 - minipass: 7.1.3 - path-to-regexp@8.4.2: {} pathe@2.0.3: {} @@ -11572,8 +9120,6 @@ snapshots: base64-js: 1.5.1 xmlbuilder: 15.1.1 - possible-typed-array-names@1.1.0: {} - postcss-selector-parser@7.1.5: dependencies: cssesc: 3.0.0 @@ -11592,16 +9138,10 @@ snapshots: powershell-utils@0.1.0: {} - powershell-utils@0.2.0: {} - prelude-ls@1.2.1: {} prettier@3.9.6: {} - pretty-bytes@5.6.0: {} - - pretty-bytes@6.1.1: {} - pretty-ms@9.3.0: dependencies: parse-ms: 4.0.0 @@ -11719,7 +9259,7 @@ snapshots: optionalDependencies: '@types/react': 19.2.18 - react-resizable-panels@4.12.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8): + react-resizable-panels@4.12.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8): dependencies: react: 19.2.8 react-dom: 19.2.8(react@19.2.8) @@ -11750,7 +9290,7 @@ snapshots: string_decoder: 1.1.1 util-deprecate: 1.0.2 - recast@0.23.21: + recast@0.23.19: dependencies: ast-types: 0.16.1 esprima: 4.0.1 @@ -11784,23 +9324,6 @@ snapshots: redux@5.0.1: {} - reflect.getprototypeof@1.0.10: - dependencies: - call-bind: 1.0.9 - define-properties: 1.2.1 - es-abstract: 1.24.2 - es-errors: 1.3.0 - es-object-atoms: 1.1.2 - get-intrinsic: 1.3.0 - get-proto: 1.0.1 - which-builtin-type: 1.2.1 - - regenerate-unicode-properties@10.2.2: - dependencies: - regenerate: 1.4.2 - - regenerate@1.4.2: {} - regex-recursion@6.0.2: dependencies: regex-utilities: 2.3.0 @@ -11811,30 +9334,6 @@ snapshots: dependencies: regex-utilities: 2.3.0 - regexp.prototype.flags@1.5.4: - dependencies: - call-bind: 1.0.9 - define-properties: 1.2.1 - es-errors: 1.3.0 - get-proto: 1.0.1 - gopd: 1.2.0 - set-function-name: 2.0.2 - - regexpu-core@6.4.0: - dependencies: - regenerate: 1.4.2 - regenerate-unicode-properties: 10.2.2 - regjsgen: 0.8.0 - regjsparser: 0.13.2 - unicode-match-property-ecmascript: 2.0.0 - unicode-match-property-value-ecmascript: 2.2.1 - - regjsgen@0.8.0: {} - - regjsparser@0.13.2: - dependencies: - jsesc: 3.1.0 - rehype-autolink-headings@7.1.0: dependencies: '@types/hast': 3.0.5 @@ -11925,13 +9424,6 @@ snapshots: resolve-from@4.0.0: {} - resolve@1.22.12: - dependencies: - es-errors: 1.3.0 - is-core-module: 2.16.2 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - responselike@2.0.1: dependencies: lowercase-keys: 2.0.0 @@ -11979,38 +9471,6 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.2.3 '@rolldown/binding-win32-x64-msvc': 1.2.3 - rollup@4.62.4: - dependencies: - '@types/estree': 1.0.9 - optionalDependencies: - '@napi-rs/lzma-linux-x64-gnu': 1.5.1 - '@rollup/rollup-android-arm-eabi': 4.62.4 - '@rollup/rollup-android-arm64': 4.62.4 - '@rollup/rollup-darwin-arm64': 4.62.4 - '@rollup/rollup-darwin-x64': 4.62.4 - '@rollup/rollup-freebsd-arm64': 4.62.4 - '@rollup/rollup-freebsd-x64': 4.62.4 - '@rollup/rollup-linux-arm-gnueabihf': 4.62.4 - '@rollup/rollup-linux-arm-musleabihf': 4.62.4 - '@rollup/rollup-linux-arm64-gnu': 4.62.4 - '@rollup/rollup-linux-arm64-musl': 4.62.4 - '@rollup/rollup-linux-loong64-gnu': 4.62.4 - '@rollup/rollup-linux-loong64-musl': 4.62.4 - '@rollup/rollup-linux-ppc64-gnu': 4.62.4 - '@rollup/rollup-linux-ppc64-musl': 4.62.4 - '@rollup/rollup-linux-riscv64-gnu': 4.62.4 - '@rollup/rollup-linux-riscv64-musl': 4.62.4 - '@rollup/rollup-linux-s390x-gnu': 4.62.4 - '@rollup/rollup-linux-x64-gnu': 4.62.4 - '@rollup/rollup-linux-x64-musl': 4.62.4 - '@rollup/rollup-openbsd-x64': 4.62.4 - '@rollup/rollup-openharmony-arm64': 4.62.4 - '@rollup/rollup-win32-arm64-msvc': 4.62.4 - '@rollup/rollup-win32-ia32-msvc': 4.62.4 - '@rollup/rollup-win32-x64-gnu': 4.62.4 - '@rollup/rollup-win32-x64-msvc': 4.62.4 - fsevents: 2.3.3 - router@2.2.0(supports-color@7.2.0): dependencies: debug: 4.4.3(supports-color@7.2.0) @@ -12031,27 +9491,8 @@ snapshots: dependencies: tslib: 2.8.1 - safe-array-concat@1.1.4: - dependencies: - call-bind: 1.0.9 - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - has-symbols: 1.1.0 - isarray: 2.0.5 - safe-buffer@5.1.2: {} - safe-push-apply@1.0.0: - dependencies: - es-errors: 1.3.0 - isarray: 2.0.5 - - safe-regex-test@1.1.0: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-regex: 1.2.1 - safer-buffer@2.1.2: {} sanitize-filename@1.6.4: @@ -12098,8 +9539,6 @@ snapshots: type-fest: 0.13.1 optional: true - serialize-javascript@7.1.0: {} - seroval-plugins@1.6.2(seroval@1.6.2): dependencies: seroval: 1.6.2 @@ -12115,31 +9554,9 @@ snapshots: transitivePeerDependencies: - supports-color - set-function-length@1.2.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.3.0 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - - set-function-name@2.0.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - - set-proto@1.0.0: - dependencies: - dunder-proto: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.2 - setprototypeof@1.2.0: {} - shadcn@4.18.0(supports-color@7.2.0)(typescript@6.0.3): + shadcn@4.16.2(supports-color@7.2.0)(typescript@6.0.3): dependencies: '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/parser': 7.29.8 @@ -12148,7 +9565,7 @@ snapshots: '@dotenvx/dotenvx': 1.75.1 '@modelcontextprotocol/sdk': 1.30.0(supports-color@7.2.0)(zod@3.25.76) '@types/validate-npm-package-name': 4.0.2 - browserslist: 4.28.8 + browserslist: 4.28.7 commander: 14.0.3 cosmiconfig: 9.0.2(typescript@6.0.3) dedent: 1.7.2 @@ -12159,13 +9576,12 @@ snapshots: fs-extra: 11.4.0 fuzzysort: 3.1.0 kleur: 4.1.5 - open: 11.0.1 + open: 11.0.0 ora: 8.2.0 postcss: 8.5.26 postcss-selector-parser: 7.1.5 prompts: 2.4.2 - recast: 0.23.21 - socks: 2.8.9 + recast: 0.23.19 stringify-object: 5.0.0 tailwind-merge: 3.6.0 ts-morph: 26.0.0 @@ -12186,14 +9602,14 @@ snapshots: shebang-regex@3.0.0: {} - shiki@4.4.3: + shiki@4.4.2: dependencies: - '@shikijs/core': 4.4.3 - '@shikijs/engine-javascript': 4.4.3 - '@shikijs/engine-oniguruma': 4.4.3 - '@shikijs/langs': 4.4.3 - '@shikijs/themes': 4.4.3 - '@shikijs/types': 4.4.3 + '@shikijs/core': 4.4.2 + '@shikijs/engine-javascript': 4.4.2 + '@shikijs/engine-oniguruma': 4.4.2 + '@shikijs/langs': 4.4.2 + '@shikijs/themes': 4.4.2 + '@shikijs/types': 4.4.2 '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.5 @@ -12237,27 +9653,11 @@ snapshots: sisteransi@1.0.5: {} - smart-buffer@4.2.0: {} - - smob@1.6.2: {} - - socks@2.8.9: - dependencies: - ip-address: 10.5.0 - smart-buffer: 4.2.0 - sonner@2.0.7(react-dom@19.2.8(react@19.2.8))(react@19.2.8): dependencies: react: 19.2.8 react-dom: 19.2.8(react@19.2.8) - sonner@2.0.8(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8): - dependencies: - react: 19.2.8 - react-dom: 19.2.8(react@19.2.8) - optionalDependencies: - '@types/react': 19.2.18 - source-map-js@1.2.1: {} source-map-support@0.5.21: @@ -12267,8 +9667,6 @@ snapshots: source-map@0.6.1: {} - source-map@0.8.0: {} - space-separated-tokens@2.0.2: {} sprintf-js@1.1.3: @@ -12284,11 +9682,6 @@ snapshots: stdin-discarder@0.2.2: {} - stop-iteration-iterator@1.1.0: - dependencies: - es-errors: 1.3.0 - internal-slot: 1.1.0 - string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -12301,46 +9694,6 @@ snapshots: get-east-asian-width: 1.6.0 strip-ansi: 7.2.0 - string.prototype.matchall@4.0.12: - dependencies: - call-bind: 1.0.9 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-abstract: 1.24.2 - es-errors: 1.3.0 - es-object-atoms: 1.1.2 - get-intrinsic: 1.3.0 - gopd: 1.2.0 - has-symbols: 1.1.0 - internal-slot: 1.1.0 - regexp.prototype.flags: 1.5.4 - set-function-name: 2.0.2 - side-channel: 1.1.1 - - string.prototype.trim@1.2.11: - dependencies: - call-bind: 1.0.9 - call-bound: 1.0.4 - define-data-property: 1.1.4 - define-properties: 1.2.1 - es-abstract: 1.24.2 - es-object-atoms: 1.1.2 - has-property-descriptors: 1.0.2 - safe-regex-test: 1.1.0 - - string.prototype.trimend@1.0.10: - dependencies: - call-bind: 1.0.9 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-object-atoms: 1.1.2 - - string.prototype.trimstart@1.0.8: - dependencies: - call-bind: 1.0.9 - define-properties: 1.2.1 - es-object-atoms: 1.1.2 - string_decoder@1.1.1: dependencies: safe-buffer: 5.1.2 @@ -12350,12 +9703,6 @@ snapshots: character-entities-html4: 2.1.0 character-entities-legacy: 3.0.0 - stringify-object@3.3.0: - dependencies: - get-own-enumerable-property-symbols: 3.0.2 - is-obj: 1.0.1 - is-regexp: 1.0.0 - stringify-object@5.0.0: dependencies: get-own-enumerable-keys: 1.0.0 @@ -12368,12 +9715,10 @@ snapshots: strip-ansi@7.2.0: dependencies: - ansi-regex: 6.3.0 + ansi-regex: 6.2.2 strip-bom@3.0.0: {} - strip-comments@2.0.1: {} - strip-final-newline@2.0.0: {} strip-final-newline@4.0.0: {} @@ -12398,8 +9743,6 @@ snapshots: dependencies: has-flag: 4.0.0 - supports-preserve-symlinks-flag@1.0.0: {} - systeminformation@5.33.1: {} tailwind-merge@3.6.0: {} @@ -12420,8 +9763,6 @@ snapshots: minizlib: 3.1.0 yallist: 5.0.0 - temp-dir@2.0.0: {} - temp-file@3.4.0: dependencies: async-exit-hook: 2.0.1 @@ -12432,20 +9773,6 @@ snapshots: mkdirp: 0.5.6 rimraf: 2.6.3 - tempy@0.6.0: - dependencies: - is-stream: 2.0.1 - temp-dir: 2.0.0 - type-fest: 0.16.0 - unique-string: 2.0.0 - - terser@5.50.0: - dependencies: - '@jridgewell/source-map': 0.3.11 - acorn: 8.18.0 - commander: 2.20.3 - source-map-support: 0.5.21 - tiny-async-pool@1.3.0: dependencies: semver: 5.7.2 @@ -12509,47 +9836,12 @@ snapshots: type-fest@0.13.1: optional: true - type-fest@0.16.0: {} - type-is@2.1.0: dependencies: - content-type: 2.1.0 + content-type: 2.0.0 media-typer: 1.1.1 mime-types: 3.0.2 - typed-array-buffer@1.0.3: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-typed-array: 1.1.15 - - typed-array-byte-length@1.0.3: - dependencies: - call-bind: 1.0.9 - for-each: 0.3.5 - gopd: 1.2.0 - has-proto: 1.2.0 - is-typed-array: 1.1.15 - - typed-array-byte-offset@1.0.4: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.9 - for-each: 0.3.5 - gopd: 1.2.0 - has-proto: 1.2.0 - is-typed-array: 1.1.15 - reflect.getprototypeof: 1.0.10 - - typed-array-length@1.0.8: - dependencies: - call-bind: 1.0.9 - for-each: 0.3.5 - gopd: 1.2.0 - is-typed-array: 1.1.15 - possible-typed-array-names: 1.1.0 - reflect.getprototypeof: 1.0.10 - typed-emitter@2.1.0: optionalDependencies: rxjs: 7.8.2 @@ -12565,17 +9857,6 @@ snapshots: transitivePeerDependencies: - supports-color - typescript-eslint@8.67.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3): - dependencies: - '@typescript-eslint/eslint-plugin': 8.67.0(@typescript-eslint/parser@8.67.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/parser': 8.67.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/typescript-estree': 8.67.0(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/utils': 8.67.0(eslint@10.8.1(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint: 10.8.1(jiti@2.7.0)(supports-color@7.2.0) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - typescript@6.0.3: {} typescript@7.0.2: @@ -12602,13 +9883,6 @@ snapshots: '@typescript/typescript-win32-x64': 7.0.2 optional: true - unbox-primitive@1.1.0: - dependencies: - call-bound: 1.0.4 - has-bigints: 1.1.0 - has-symbols: 1.1.0 - which-boxed-primitive: 1.1.1 - undici-types@7.18.2: {} undici-types@8.3.0: {} @@ -12617,17 +9891,6 @@ snapshots: undici@7.29.0: {} - unicode-canonical-property-names-ecmascript@2.0.1: {} - - unicode-match-property-ecmascript@2.0.0: - dependencies: - unicode-canonical-property-names-ecmascript: 2.0.1 - unicode-property-aliases-ecmascript: 2.2.0 - - unicode-match-property-value-ecmascript@2.2.1: {} - - unicode-property-aliases-ecmascript@2.2.0: {} - unicorn-magic@0.3.0: {} unified@11.0.5: @@ -12640,10 +9903,6 @@ snapshots: trough: 2.2.0 vfile: 6.0.3 - unique-string@2.0.0: - dependencies: - crypto-random-string: 2.0.0 - unist-util-find-after@5.0.0: dependencies: '@types/unist': 3.0.3 @@ -12691,11 +9950,9 @@ snapshots: graceful-fs: 4.2.11 node-int64: 0.4.0 - upath@1.2.0: {} - - update-browserslist-db@1.3.1(browserslist@4.28.8): + update-browserslist-db@1.3.0(browserslist@4.28.7): dependencies: - browserslist: 4.28.8 + browserslist: 4.28.7 escalade: 3.2.0 picocolors: 1.1.1 @@ -12776,18 +10033,7 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite-plugin-pwa@1.3.0(supports-color@7.2.0)(vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0))(workbox-build@7.4.1(supports-color@7.2.0))(workbox-window@7.4.1): - dependencies: - debug: 4.4.3(supports-color@7.2.0) - pretty-bytes: 6.1.1 - tinyglobby: 0.2.17 - vite: 8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0) - workbox-build: 7.4.1(supports-color@7.2.0) - workbox-window: 7.4.1 - transitivePeerDependencies: - - supports-color - - vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0): + vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0): dependencies: lightningcss: 1.33.0 picomatch: 4.0.5 @@ -12799,19 +10045,18 @@ snapshots: esbuild: 0.28.1 fsevents: 2.3.3 jiti: 2.7.0 - terser: 5.50.0 yaml: 2.9.0 - vitest@4.1.11(@types/node@26.2.0)(vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0)): + vitest@4.1.10(@types/node@26.2.0)(vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)): dependencies: - '@vitest/expect': 4.1.11 - '@vitest/mocker': 4.1.11(vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0)) - '@vitest/pretty-format': 4.1.11 - '@vitest/runner': 4.1.11 - '@vitest/snapshot': 4.1.11 - '@vitest/spy': 4.1.11 - '@vitest/utils': 4.1.11 - es-module-lexer: 2.3.2 + '@vitest/expect': 4.1.10 + '@vitest/mocker': 4.1.10(vite@8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)) + '@vitest/pretty-format': 4.1.10 + '@vitest/runner': 4.1.10 + '@vitest/snapshot': 4.1.10 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 + es-module-lexer: 2.3.1 expect-type: 1.4.0 magic-string: 0.30.21 obug: 2.1.4 @@ -12822,7 +10067,7 @@ snapshots: tinyexec: 1.3.0 tinyglobby: 0.2.17 tinyrainbow: 3.1.1 - vite: 8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.50.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@26.2.0)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 26.2.0 @@ -12845,47 +10090,6 @@ snapshots: dependencies: sdp: 3.2.2 - which-boxed-primitive@1.1.1: - dependencies: - is-bigint: 1.1.0 - is-boolean-object: 1.2.2 - is-number-object: 1.1.1 - is-string: 1.1.1 - is-symbol: 1.1.1 - - which-builtin-type@1.2.1: - dependencies: - call-bound: 1.0.4 - function.prototype.name: 1.2.0 - has-tostringtag: 1.0.2 - is-async-function: 2.1.1 - is-date-object: 1.1.0 - is-finalizationregistry: 1.1.1 - is-generator-function: 1.1.2 - is-regex: 1.2.1 - is-weakref: 1.1.1 - isarray: 2.0.5 - which-boxed-primitive: 1.1.1 - which-collection: 1.0.2 - which-typed-array: 1.1.22 - - which-collection@1.0.2: - dependencies: - is-map: 2.0.3 - is-set: 2.0.3 - is-weakmap: 2.0.2 - is-weakset: 2.0.4 - - which-typed-array@1.1.22: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.9 - call-bound: 1.0.4 - for-each: 0.3.5 - get-proto: 1.0.1 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - which@2.0.2: dependencies: isexe: 2.0.0 @@ -12909,119 +10113,6 @@ snapshots: word-wrap@1.2.5: {} - workbox-background-sync@7.4.1: - dependencies: - idb: 7.1.1 - workbox-core: 7.4.1 - - workbox-broadcast-update@7.4.1: - dependencies: - workbox-core: 7.4.1 - - workbox-build@7.4.1(supports-color@7.2.0): - dependencies: - '@apideck/better-ajv-errors': 0.3.7(ajv@8.20.0) - '@babel/core': 7.29.7(supports-color@7.2.0) - '@babel/preset-env': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) - '@babel/runtime': 7.29.7 - '@rollup/plugin-babel': 6.1.0(@babel/core@7.29.7(supports-color@7.2.0))(rollup@4.62.4)(supports-color@7.2.0) - '@rollup/plugin-node-resolve': 16.0.3(rollup@4.62.4) - '@rollup/plugin-replace': 6.0.3(rollup@4.62.4) - '@rollup/plugin-terser': 1.0.0(rollup@4.62.4) - '@trickfilm400/rollup-plugin-off-main-thread': 3.0.0-pre1 - ajv: 8.20.0 - common-tags: 1.8.2 - eta: 4.6.0 - fast-json-stable-stringify: 2.1.0 - fs-extra: 9.1.0 - glob: 11.1.0 - pretty-bytes: 5.6.0 - rollup: 4.62.4 - source-map: 0.8.0 - stringify-object: 3.3.0 - strip-comments: 2.0.1 - tempy: 0.6.0 - upath: 1.2.0 - workbox-background-sync: 7.4.1 - workbox-broadcast-update: 7.4.1 - workbox-cacheable-response: 7.4.1 - workbox-core: 7.4.1 - workbox-expiration: 7.4.1 - workbox-google-analytics: 7.4.1 - workbox-navigation-preload: 7.4.1 - workbox-precaching: 7.4.1 - workbox-range-requests: 7.4.1 - workbox-recipes: 7.4.1 - workbox-routing: 7.4.1 - workbox-strategies: 7.4.1 - workbox-streams: 7.4.1 - workbox-sw: 7.4.1 - workbox-window: 7.4.1 - transitivePeerDependencies: - - '@types/babel__core' - - supports-color - - workbox-cacheable-response@7.4.1: - dependencies: - workbox-core: 7.4.1 - - workbox-core@7.4.1: {} - - workbox-expiration@7.4.1: - dependencies: - idb: 7.1.1 - workbox-core: 7.4.1 - - workbox-google-analytics@7.4.1: - dependencies: - workbox-background-sync: 7.4.1 - workbox-core: 7.4.1 - workbox-routing: 7.4.1 - workbox-strategies: 7.4.1 - - workbox-navigation-preload@7.4.1: - dependencies: - workbox-core: 7.4.1 - - workbox-precaching@7.4.1: - dependencies: - workbox-core: 7.4.1 - workbox-routing: 7.4.1 - workbox-strategies: 7.4.1 - - workbox-range-requests@7.4.1: - dependencies: - workbox-core: 7.4.1 - - workbox-recipes@7.4.1: - dependencies: - workbox-cacheable-response: 7.4.1 - workbox-core: 7.4.1 - workbox-expiration: 7.4.1 - workbox-precaching: 7.4.1 - workbox-routing: 7.4.1 - workbox-strategies: 7.4.1 - - workbox-routing@7.4.1: - dependencies: - workbox-core: 7.4.1 - - workbox-strategies@7.4.1: - dependencies: - workbox-core: 7.4.1 - - workbox-streams@7.4.1: - dependencies: - workbox-core: 7.4.1 - workbox-routing: 7.4.1 - - workbox-sw@7.4.1: {} - - workbox-window@7.4.1: - dependencies: - '@types/trusted-types': 2.0.7 - workbox-core: 7.4.1 - wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 @@ -13030,7 +10121,7 @@ snapshots: wrappy@1.0.2: {} - wsl-utils@1.0.0: + wsl-utils@0.3.1: dependencies: is-wsl: 3.1.1 powershell-utils: 0.1.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 6ec3531..2bcade5 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -6,5 +6,5 @@ allowBuilds: electron-winstaller: true esbuild: true overrides: - "@methanium/ui": "https://git.methanium.net/methanium/ui/releases/download/0.0.29/methanium-ui.tgz" - mtp: "https://git.methanium.net/methanium/mtp/releases/download/0.3.0-dev-c7c7afe/mtp-0.3.0.tgz" + "@methanium/ui": "https://git.methanium.net/methanium/ui/releases/download/0.0.28/methanium-ui.tgz" + mtp: "https://git.methanium.net/methanium/mtp/releases/download/0.2.0-dev-a692bed/mtp-0.2.0.tgz" diff --git a/utils/scripts/build-packages.ts b/utils/scripts/build-packages.ts index 1f1f4fd..9518c49 100644 --- a/utils/scripts/build-packages.ts +++ b/utils/scripts/build-packages.ts @@ -15,14 +15,7 @@ function getPackageDirs(dir: string): string[] { for (const entry of entries) { const fullPath = join(dir, entry); - if (entry === "node_modules" || entry.startsWith(".")) continue; - let stats; - try { - stats = statSync(fullPath); - } catch { - continue; - } - if (!stats.isDirectory()) continue; + if (!statSync(fullPath).isDirectory()) continue; if (existsSync(join(fullPath, "package.json"))) { dirs.push(fullPath); diff --git a/utils/scripts/lint-packages.ts b/utils/scripts/lint-packages.ts index c84e0e0..0aea8c3 100644 --- a/utils/scripts/lint-packages.ts +++ b/utils/scripts/lint-packages.ts @@ -16,14 +16,7 @@ function getPackageDirs(dir: string): string[] { for (const entry of entries) { const fullPath = join(dir, entry); - if (entry === "node_modules" || entry.startsWith(".")) continue; - let stats; - try { - stats = statSync(fullPath); - } catch { - continue; - } - if (!stats.isDirectory()) continue; + if (!statSync(fullPath).isDirectory()) continue; if (existsSync(join(fullPath, "package.json"))) { dirs.push(fullPath); diff --git a/utils/scripts/update-packages.ts b/utils/scripts/update-packages.ts index 90b3b0c..22b258f 100644 --- a/utils/scripts/update-packages.ts +++ b/utils/scripts/update-packages.ts @@ -15,14 +15,7 @@ function getPackageDirs(dir: string): string[] { for (const entry of entries) { const fullPath = join(dir, entry); - if (entry === "node_modules" || entry.startsWith(".")) continue; - let stats; - try { - stats = statSync(fullPath); - } catch { - continue; - } - if (!stats.isDirectory()) continue; + if (!statSync(fullPath).isDirectory()) continue; if (existsSync(join(fullPath, "package.json"))) { dirs.push(fullPath);