diff --git a/package.json b/package.json index 08f096f7..5b3088a1 100644 --- a/package.json +++ b/package.json @@ -42,8 +42,6 @@ "@vanilla-extract/css": "^1.14.2", "@vanilla-extract/dynamic": "^2.1.1", "@vanilla-extract/recipes": "^0.5.2", - "adm-zip": "^0.5.16", - "archiver": "^7.0.1", "auto-launch": "^5.0.6", "axios": "^1.7.7", "better-sqlite3": "^11.2.1", @@ -74,6 +72,7 @@ "react-redux": "^9.1.1", "react-router-dom": "^6.22.3", "sudo-prompt": "^9.2.1", + "tar": "^7.4.3", "typeorm": "^0.3.20", "user-agents": "^1.1.193", "yaml": "^2.4.1", @@ -88,8 +87,6 @@ "@electron-toolkit/tsconfig": "^1.0.1", "@sentry/vite-plugin": "^2.20.1", "@swc/core": "^1.4.16", - "@types/adm-zip": "^0.5.5", - "@types/archiver": "^6.0.2", "@types/auto-launch": "^5.0.5", "@types/color": "^3.0.6", "@types/folder-hash": "^4.0.4", diff --git a/src/main/events/catalogue/get-catalogue.ts b/src/main/events/catalogue/get-catalogue.ts index 4fdb95bd..145f3166 100644 --- a/src/main/events/catalogue/get-catalogue.ts +++ b/src/main/events/catalogue/get-catalogue.ts @@ -30,7 +30,7 @@ const getCatalogue = async ( title: steamGame.name, shop: game.shop, cover: steamUrlBuilder.library(game.objectId), - objectID: game.objectId, + objectId: game.objectId, }; }) ); diff --git a/src/main/events/catalogue/get-game-shop-details.ts b/src/main/events/catalogue/get-game-shop-details.ts index 3a435013..08366abc 100644 --- a/src/main/events/catalogue/get-game-shop-details.ts +++ b/src/main/events/catalogue/get-game-shop-details.ts @@ -7,16 +7,16 @@ import { registerEvent } from "../register-event"; import { steamGamesWorker } from "@main/workers"; const getLocalizedSteamAppDetails = async ( - objectID: string, + objectId: string, language: string ): Promise => { if (language === "english") { - return getSteamAppDetails(objectID, language); + return getSteamAppDetails(objectId, language); } - return getSteamAppDetails(objectID, language).then( + return getSteamAppDetails(objectId, language).then( async (localizedAppDetails) => { - const steamGame = await steamGamesWorker.run(Number(objectID), { + const steamGame = await steamGamesWorker.run(Number(objectId), { name: "getById", }); @@ -34,21 +34,21 @@ const getLocalizedSteamAppDetails = async ( const getGameShopDetails = async ( _event: Electron.IpcMainInvokeEvent, - objectID: string, + objectId: string, shop: GameShop, language: string ): Promise => { if (shop === "steam") { const cachedData = await gameShopCacheRepository.findOne({ - where: { objectID, language }, + where: { objectID: objectId, language }, }); - const appDetails = getLocalizedSteamAppDetails(objectID, language).then( + const appDetails = getLocalizedSteamAppDetails(objectId, language).then( (result) => { if (result) { gameShopCacheRepository.upsert( { - objectID, + objectID: objectId, shop: "steam", language, serializedData: JSON.stringify(result), @@ -68,7 +68,7 @@ const getGameShopDetails = async ( if (cachedGame) { return { ...cachedGame, - objectID, + objectId, } as ShopDetails; } diff --git a/src/main/events/catalogue/get-games.ts b/src/main/events/catalogue/get-games.ts index 81717806..3eb1f135 100644 --- a/src/main/events/catalogue/get-games.ts +++ b/src/main/events/catalogue/get-games.ts @@ -1,28 +1,29 @@ import type { CatalogueEntry } from "@types"; import { registerEvent } from "../register-event"; -import { steamGamesWorker } from "@main/workers"; +import { HydraApi } from "@main/services"; import { steamUrlBuilder } from "@shared"; const getGames = async ( _event: Electron.IpcMainInvokeEvent, take = 12, - cursor = 0 -): Promise<{ results: CatalogueEntry[]; cursor: number }> => { - const steamGames = await steamGamesWorker.run( - { limit: take, offset: cursor }, - { name: "list" } + skip = 0 +): Promise => { + const searchParams = new URLSearchParams({ + take: take.toString(), + skip: skip.toString(), + }); + + const games = await HydraApi.get( + `/games/catalogue?${searchParams.toString()}`, + undefined, + { needsAuth: false } ); - return { - results: steamGames.map((steamGame) => ({ - title: steamGame.name, - shop: "steam", - cover: steamUrlBuilder.library(steamGame.id), - objectID: steamGame.id, - })), - cursor: cursor + steamGames.length, - }; + return games.map((game) => ({ + ...game, + cover: steamUrlBuilder.library(game.objectId), + })); }; registerEvent("getGames", getGames); diff --git a/src/main/events/catalogue/get-how-long-to-beat.ts b/src/main/events/catalogue/get-how-long-to-beat.ts index 642dd9a3..f489f804 100644 --- a/src/main/events/catalogue/get-how-long-to-beat.ts +++ b/src/main/events/catalogue/get-how-long-to-beat.ts @@ -6,14 +6,14 @@ import { gameShopCacheRepository } from "@main/repository"; const getHowLongToBeat = async ( _event: Electron.IpcMainInvokeEvent, - objectID: string, + objectId: string, shop: GameShop, title: string ): Promise => { const searchHowLongToBeatPromise = searchHowLongToBeat(title); const gameShopCache = await gameShopCacheRepository.findOne({ - where: { objectID, shop }, + where: { objectID: objectId, shop }, }); const howLongToBeatCachedData = gameShopCache?.howLongToBeatSerializedData @@ -23,7 +23,7 @@ const getHowLongToBeat = async ( return searchHowLongToBeatPromise.then(async (response) => { const game = response.data.find( - (game) => game.profile_steam === Number(objectID) + (game) => game.profile_steam === Number(objectId) ); if (!game) return null; @@ -31,7 +31,7 @@ const getHowLongToBeat = async ( gameShopCacheRepository.upsert( { - objectID, + objectID: objectId, shop, howLongToBeatSerializedData: JSON.stringify(howLongToBeat), }, diff --git a/src/main/events/cloud-save/delete-game-artifact.ts b/src/main/events/cloud-save/delete-game-artifact.ts index fa869896..e293bc56 100644 --- a/src/main/events/cloud-save/delete-game-artifact.ts +++ b/src/main/events/cloud-save/delete-game-artifact.ts @@ -4,6 +4,9 @@ import { registerEvent } from "../register-event"; const deleteGameArtifact = async ( _event: Electron.IpcMainInvokeEvent, gameArtifactId: string -) => HydraApi.delete<{ ok: boolean }>(`/games/artifacts/${gameArtifactId}`); +) => + HydraApi.delete<{ ok: boolean }>( + `/profile/games/artifacts/${gameArtifactId}` + ); registerEvent("deleteGameArtifact", deleteGameArtifact); diff --git a/src/main/events/cloud-save/download-game-artifact.ts b/src/main/events/cloud-save/download-game-artifact.ts index 94bc8edf..d587daaa 100644 --- a/src/main/events/cloud-save/download-game-artifact.ts +++ b/src/main/events/cloud-save/download-game-artifact.ts @@ -1,6 +1,6 @@ import { HydraApi, logger, Ludusavi, WindowManager } from "@main/services"; import fs from "node:fs"; -import AdmZip from "adm-zip"; +import * as tar from "tar"; import { registerEvent } from "../register-event"; import axios from "axios"; import { app } from "electron"; @@ -8,16 +8,54 @@ import path from "node:path"; import { backupsPath } from "@main/constants"; import type { GameShop } from "@types"; +import YAML from "yaml"; + +export interface LudusaviBackup { + files: { + [key: string]: { + hash: string; + size: number; + }; + }; +} + +const replaceLudusaviBackupWithCurrentUser = ( + mappingPath: string, + backupHomeDir: string +) => { + const data = fs.readFileSync(mappingPath, "utf8"); + const manifest = YAML.parse(data); + + const currentHomeDir = app.getPath("home"); + + const backups = manifest.backups.map((backup: LudusaviBackup) => { + const files = Object.entries(backup.files).reduce((prev, [key, value]) => { + return { + ...prev, + [key.replace(backupHomeDir, currentHomeDir)]: value, + }; + }, {}); + + return { + ...backup, + files, + }; + }); + + fs.writeFileSync(mappingPath, YAML.stringify({ ...manifest, backups })); +}; + const downloadGameArtifact = async ( _event: Electron.IpcMainInvokeEvent, objectId: string, shop: GameShop, gameArtifactId: string ) => { - const { downloadUrl, objectKey } = await HydraApi.post<{ + const { downloadUrl, objectKey, homeDir } = await HydraApi.post<{ downloadUrl: string; objectKey: string; - }>(`/games/artifacts/${gameArtifactId}/download`); + homeDir: string; + }>(`/profile/games/artifacts/${gameArtifactId}/download`); const zipLocation = path.join(app.getPath("userData"), objectKey); const backupPath = path.join(backupsPath, `${shop}-${objectId}`); @@ -42,20 +80,31 @@ const downloadGameArtifact = async ( }); writer.on("close", () => { - const zip = new AdmZip(zipLocation); - zip.extractAllToAsync(backupPath, true, true, (err) => { - if (err) { - logger.error("Failed to extract zip", err); - throw err; - } + tar + .x({ + file: zipLocation, + cwd: backupPath, + }) + .then(async () => { + const [game] = await Ludusavi.findGames(shop, objectId); + if (!game) throw new Error("Game not found in Ludusavi manifest"); - Ludusavi.restoreBackup(backupPath).then(() => { - WindowManager.mainWindow?.webContents.send( - `on-backup-download-complete-${objectId}-${shop}`, - true + const mappingPath = path.join( + backupsPath, + `${shop}-${objectId}`, + game, + "mapping.yaml" ); + + replaceLudusaviBackupWithCurrentUser(mappingPath, homeDir); + + Ludusavi.restoreBackup(backupPath).then(() => { + WindowManager.mainWindow?.webContents.send( + `on-backup-download-complete-${objectId}-${shop}`, + true + ); + }); }); - }); }); }; diff --git a/src/main/events/cloud-save/get-game-artifacts.ts b/src/main/events/cloud-save/get-game-artifacts.ts index b32dfd79..fc47076a 100644 --- a/src/main/events/cloud-save/get-game-artifacts.ts +++ b/src/main/events/cloud-save/get-game-artifacts.ts @@ -12,7 +12,9 @@ const getGameArtifacts = async ( shop, }); - return HydraApi.get(`/games/artifacts?${params.toString()}`); + return HydraApi.get( + `/profile/games/artifacts?${params.toString()}` + ); }; registerEvent("getGameArtifacts", getGameArtifacts); diff --git a/src/main/events/cloud-save/upload-save-game.ts b/src/main/events/cloud-save/upload-save-game.ts index efa7cd22..9948da31 100644 --- a/src/main/events/cloud-save/upload-save-game.ts +++ b/src/main/events/cloud-save/upload-save-game.ts @@ -2,47 +2,31 @@ import { HydraApi, logger, Ludusavi, WindowManager } from "@main/services"; import { registerEvent } from "../register-event"; import fs from "node:fs"; import path from "node:path"; -import archiver from "archiver"; +import * as tar from "tar"; import crypto from "node:crypto"; import { GameShop } from "@types"; import axios from "axios"; import os from "node:os"; -import { app } from "electron"; import { backupsPath } from "@main/constants"; +import { app } from "electron"; -const compressBackupToArtifact = async ( - shop: GameShop, - objectId: string, - cb: (zipLocation: string) => void -) => { +const bundleBackup = async (shop: GameShop, objectId: string) => { const backupPath = path.join(backupsPath, `${shop}-${objectId}`); await Ludusavi.backupGame(shop, objectId, backupPath); - const archive = archiver("zip", { - zlib: { level: 9 }, - }); + const tarLocation = path.join(backupsPath, `${crypto.randomUUID()}.zip`); - const zipLocation = path.join( - app.getPath("userData"), - `${crypto.randomUUID()}.zip` + await tar.create( + { + gzip: false, + file: tarLocation, + cwd: backupPath, + }, + ["."] ); - const output = fs.createWriteStream(zipLocation); - - output.on("close", () => { - cb(zipLocation); - }); - - output.on("error", (err) => { - logger.error("Failed to compress folder", err); - throw err; - }); - - archive.pipe(output); - - archive.directory(backupPath, false); - archive.finalize(); + return tarLocation; }; const uploadSaveGame = async ( @@ -50,49 +34,51 @@ const uploadSaveGame = async ( objectId: string, shop: GameShop ) => { - compressBackupToArtifact(shop, objectId, (zipLocation) => { - fs.stat(zipLocation, async (err, stat) => { + const bundleLocation = await bundleBackup(shop, objectId); + + fs.stat(bundleLocation, async (err, stat) => { + if (err) { + logger.error("Failed to get zip file stats", err); + throw err; + } + + const { uploadUrl } = await HydraApi.post<{ + id: string; + uploadUrl: string; + }>("/profile/games/artifacts", { + artifactLengthInBytes: stat.size, + shop, + objectId, + hostname: os.hostname(), + homeDir: app.getPath("home"), + platform: os.platform(), + }); + + fs.readFile(bundleLocation, async (err, fileBuffer) => { if (err) { - logger.error("Failed to get zip file stats", err); + logger.error("Failed to read zip file", err); throw err; } - const { uploadUrl } = await HydraApi.post<{ - id: string; - uploadUrl: string; - }>("/games/artifacts", { - artifactLengthInBytes: stat.size, - shop, - objectId, - hostname: os.hostname(), + await axios.put(uploadUrl, fileBuffer, { + headers: { + "Content-Type": "application/tar", + }, + onUploadProgress: (progressEvent) => { + console.log(progressEvent); + }, }); - fs.readFile(zipLocation, async (err, fileBuffer) => { + WindowManager.mainWindow?.webContents.send( + `on-upload-complete-${objectId}-${shop}`, + true + ); + + fs.rm(bundleLocation, (err) => { if (err) { - logger.error("Failed to read zip file", err); + logger.error("Failed to remove tar file", err); throw err; } - - await axios.put(uploadUrl, fileBuffer, { - headers: { - "Content-Type": "application/zip", - }, - onUploadProgress: (progressEvent) => { - console.log(progressEvent); - }, - }); - - WindowManager.mainWindow?.webContents.send( - `on-upload-complete-${objectId}-${shop}`, - true - ); - - fs.rm(zipLocation, (err) => { - if (err) { - logger.error("Failed to remove zip file", err); - throw err; - } - }); }); }); }); diff --git a/src/main/events/helpers/search-games.ts b/src/main/events/helpers/search-games.ts index 1f1fc756..74e0b6a8 100644 --- a/src/main/events/helpers/search-games.ts +++ b/src/main/events/helpers/search-games.ts @@ -12,7 +12,7 @@ export interface SearchGamesArgs { export const convertSteamGameToCatalogueEntry = ( game: SteamGame ): CatalogueEntry => ({ - objectID: String(game.id), + objectId: String(game.id), title: game.name, shop: "steam" as GameShop, cover: steamUrlBuilder.library(String(game.id)), diff --git a/src/main/events/library/add-game-to-library.ts b/src/main/events/library/add-game-to-library.ts index b5c9a5d0..789241f0 100644 --- a/src/main/events/library/add-game-to-library.ts +++ b/src/main/events/library/add-game-to-library.ts @@ -10,14 +10,14 @@ import { steamUrlBuilder } from "@shared"; const addGameToLibrary = async ( _event: Electron.IpcMainInvokeEvent, - objectID: string, + objectId: string, title: string, shop: GameShop ) => { return gameRepository .update( { - objectID, + objectID: objectId, }, { shop, @@ -27,23 +27,25 @@ const addGameToLibrary = async ( ) .then(async ({ affected }) => { if (!affected) { - const steamGame = await steamGamesWorker.run(Number(objectID), { + const steamGame = await steamGamesWorker.run(Number(objectId), { name: "getById", }); const iconUrl = steamGame?.clientIcon - ? steamUrlBuilder.icon(objectID, steamGame.clientIcon) + ? steamUrlBuilder.icon(objectId, steamGame.clientIcon) : null; await gameRepository.insert({ title, iconUrl, - objectID, + objectID: objectId, shop, }); } - const game = await gameRepository.findOne({ where: { objectID } }); + const game = await gameRepository.findOne({ + where: { objectID: objectId }, + }); createGame(game!).catch(() => {}); }); diff --git a/src/main/events/library/get-game-by-object-id.ts b/src/main/events/library/get-game-by-object-id.ts index 91cc1b5a..d68aac69 100644 --- a/src/main/events/library/get-game-by-object-id.ts +++ b/src/main/events/library/get-game-by-object-id.ts @@ -2,15 +2,15 @@ import { gameRepository } from "@main/repository"; import { registerEvent } from "../register-event"; -const getGameByObjectID = async ( +const getGameByObjectId = async ( _event: Electron.IpcMainInvokeEvent, - objectID: string + objectId: string ) => gameRepository.findOne({ where: { - objectID, + objectID: objectId, isDeleted: false, }, }); -registerEvent("getGameByObjectID", getGameByObjectID); +registerEvent("getGameByObjectId", getGameByObjectId); diff --git a/src/main/events/torrenting/start-game-download.ts b/src/main/events/torrenting/start-game-download.ts index a2c51a01..deac1d2c 100644 --- a/src/main/events/torrenting/start-game-download.ts +++ b/src/main/events/torrenting/start-game-download.ts @@ -14,7 +14,7 @@ const startGameDownload = async ( _event: Electron.IpcMainInvokeEvent, payload: StartGameDownloadPayload ) => { - const { objectID, title, shop, downloadPath, downloader, uri } = payload; + const { objectId, title, shop, downloadPath, downloader, uri } = payload; return dataSource.transaction(async (transactionalEntityManager) => { const gameRepository = transactionalEntityManager.getRepository(Game); @@ -23,7 +23,7 @@ const startGameDownload = async ( const game = await gameRepository.findOne({ where: { - objectID, + objectID: objectId, shop, }, }); @@ -51,18 +51,18 @@ const startGameDownload = async ( } ); } else { - const steamGame = await steamGamesWorker.run(Number(objectID), { + const steamGame = await steamGamesWorker.run(Number(objectId), { name: "getById", }); const iconUrl = steamGame?.clientIcon - ? steamUrlBuilder.icon(objectID, steamGame.clientIcon) + ? steamUrlBuilder.icon(objectId, steamGame.clientIcon) : null; await gameRepository.insert({ title, iconUrl, - objectID, + objectID: objectId, downloader, shop, status: "active", @@ -73,7 +73,7 @@ const startGameDownload = async ( const updatedGame = await gameRepository.findOne({ where: { - objectID, + objectID: objectId, }, }); diff --git a/src/main/services/process-watcher.ts b/src/main/services/process-watcher.ts index 2a194bf2..f4b550b3 100644 --- a/src/main/services/process-watcher.ts +++ b/src/main/services/process-watcher.ts @@ -2,7 +2,7 @@ import { IsNull, Not } from "typeorm"; import { gameRepository } from "@main/repository"; import { WindowManager } from "./window-manager"; import { createGame, updateGamePlaytime } from "./library-sync"; -import { GameRunning } from "@types"; +import type { GameRunning } from "@types"; import { PythonInstance } from "./download"; import { Game } from "@main/entity"; diff --git a/src/main/services/steam-250.ts b/src/main/services/steam-250.ts index 9833c278..0abc2f14 100644 --- a/src/main/services/steam-250.ts +++ b/src/main/services/steam-250.ts @@ -17,7 +17,7 @@ export const requestSteam250 = async (path: string) => { return { title: $title.textContent, - objectID: steamGameUrl.split("/").pop(), + objectId: steamGameUrl.split("/").pop(), } as Steam250Game; }) .filter((game) => game != null); @@ -38,7 +38,7 @@ export const getSteam250List = async () => { ).flat(); const gamesMap: Map = gamesList.reduce((map, item) => { - if (item) map.set(item.objectID, item); + if (item) map.set(item.objectId, item); return map; }, new Map()); diff --git a/src/main/services/steam-grid.ts b/src/main/services/steam-grid.ts index 2bdee28d..540e5857 100644 --- a/src/main/services/steam-grid.ts +++ b/src/main/services/steam-grid.ts @@ -21,7 +21,7 @@ export interface SteamGridGameResponse { } export const getSteamGridData = async ( - objectID: string, + objectId: string, path: string, shop: GameShop, params: Record = {} @@ -33,7 +33,7 @@ export const getSteamGridData = async ( } const response = await axios.get( - `https://www.steamgriddb.com/api/v2/${path}/${shop}/${objectID}?${searchParams.toString()}`, + `https://www.steamgriddb.com/api/v2/${path}/${shop}/${objectId}?${searchParams.toString()}`, { headers: { Authorization: `Bearer ${import.meta.env.MAIN_VITE_STEAMGRIDDB_API_KEY}`, @@ -59,10 +59,10 @@ export const getSteamGridGameById = async ( return response.data; }; -export const getSteamGameClientIcon = async (objectID: string) => { +export const getSteamGameClientIcon = async (objectId: string) => { const { data: { id: steamGridGameId }, - } = await getSteamGridData(objectID, "games", "steam"); + } = await getSteamGridData(objectId, "games", "steam"); const steamGridGame = await getSteamGridGameById(steamGridGameId); return steamGridGame.data.platforms.steam.metadata.clienticon; diff --git a/src/main/services/steam.ts b/src/main/services/steam.ts index 53e243f3..1d8ed2d9 100644 --- a/src/main/services/steam.ts +++ b/src/main/services/steam.ts @@ -12,11 +12,11 @@ export interface SteamAppDetailsResponse { } export const getSteamAppDetails = async ( - objectID: string, + objectId: string, language: string ) => { const searchParams = new URLSearchParams({ - appids: objectID, + appids: objectId, l: language, }); @@ -25,7 +25,7 @@ export const getSteamAppDetails = async ( `http://store.steampowered.com/api/appdetails?${searchParams.toString()}` ) .then((response) => { - if (response.data[objectID].success) return response.data[objectID].data; + if (response.data[objectId].success) return response.data[objectId].data; return null; }) .catch((err) => { diff --git a/src/main/workers/ludusavi.worker.ts b/src/main/workers/ludusavi.worker.ts index 2a1d266c..e6ccdaad 100644 --- a/src/main/workers/ludusavi.worker.ts +++ b/src/main/workers/ludusavi.worker.ts @@ -28,20 +28,18 @@ export const backupGame = ({ title, backupPath, preview = false, + winePrefix, }: { title: string; backupPath: string; preview?: boolean; + winePrefix?: string; }) => { const args = ["backup", title, "--api", "--force"]; - if (preview) { - args.push("--preview"); - } - - if (backupPath) { - args.push("--path", backupPath); - } + if (preview) args.push("--preview"); + if (backupPath) args.push("--path", backupPath); + if (winePrefix) args.push("--wine-prefix", winePrefix); const result = cp.execFileSync(binaryPath, args); @@ -59,3 +57,5 @@ export const restoreBackup = (backupPath: string) => { return JSON.parse(result.toString("utf-8")) as LudusaviBackup; }; + +// --wine-prefix diff --git a/src/preload/index.ts b/src/preload/index.ts index f5dd0ba7..f2600fdc 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -38,13 +38,13 @@ contextBridge.exposeInMainWorld("electron", { searchGames: (query: string) => ipcRenderer.invoke("searchGames", query), getCatalogue: (category: CatalogueCategory) => ipcRenderer.invoke("getCatalogue", category), - getGameShopDetails: (objectID: string, shop: GameShop, language: string) => - ipcRenderer.invoke("getGameShopDetails", objectID, shop, language), + getGameShopDetails: (objectId: string, shop: GameShop, language: string) => + ipcRenderer.invoke("getGameShopDetails", objectId, shop, language), getRandomGame: () => ipcRenderer.invoke("getRandomGame"), - getHowLongToBeat: (objectID: string, shop: GameShop, title: string) => - ipcRenderer.invoke("getHowLongToBeat", objectID, shop, title), - getGames: (take?: number, prevCursor?: number) => - ipcRenderer.invoke("getGames", take, prevCursor), + getHowLongToBeat: (objectId: string, shop: GameShop, title: string) => + ipcRenderer.invoke("getHowLongToBeat", objectId, shop, title), + getGames: (take?: number, skip?: number) => + ipcRenderer.invoke("getGames", take, skip), searchGameRepacks: (query: string) => ipcRenderer.invoke("searchGameRepacks", query), getGameStats: (objectId: string, shop: GameShop) => @@ -65,8 +65,8 @@ contextBridge.exposeInMainWorld("electron", { ipcRenderer.invoke("deleteDownloadSource", id), /* Library */ - addGameToLibrary: (objectID: string, title: string, shop: GameShop) => - ipcRenderer.invoke("addGameToLibrary", objectID, title, shop), + addGameToLibrary: (objectId: string, title: string, shop: GameShop) => + ipcRenderer.invoke("addGameToLibrary", objectId, title, shop), createGameShortcut: (id: number) => ipcRenderer.invoke("createGameShortcut", id), updateExecutablePath: (id: number, executablePath: string) => @@ -88,8 +88,8 @@ contextBridge.exposeInMainWorld("electron", { removeGame: (gameId: number) => ipcRenderer.invoke("removeGame", gameId), deleteGameFolder: (gameId: number) => ipcRenderer.invoke("deleteGameFolder", gameId), - getGameByObjectID: (objectID: string) => - ipcRenderer.invoke("getGameByObjectID", objectID), + getGameByObjectId: (objectId: string) => + ipcRenderer.invoke("getGameByObjectId", objectId), onGamesRunning: ( cb: ( gamesRunning: Pick[] diff --git a/src/renderer/src/app.css.ts b/src/renderer/src/app.css.ts index 4e0cf7a0..871f2220 100644 --- a/src/renderer/src/app.css.ts +++ b/src/renderer/src/app.css.ts @@ -26,6 +26,10 @@ globalStyle("::-webkit-scrollbar-thumb", { borderRadius: "24px", }); +globalStyle("::-webkit-scrollbar-thumb:hover", { + backgroundColor: "rgba(255, 255, 255, 0.16)", +}); + globalStyle("html, body, #root, main", { height: "100%", }); diff --git a/src/renderer/src/components/game-card/game-card.tsx b/src/renderer/src/components/game-card/game-card.tsx index 9d54bad8..c548be52 100644 --- a/src/renderer/src/components/game-card/game-card.tsx +++ b/src/renderer/src/components/game-card/game-card.tsx @@ -44,7 +44,7 @@ export function GameCard({ game, ...props }: GameCardProps) { const handleHover = useCallback(() => { if (!stats) { - window.electron.getGameStats(game.objectID, game.shop).then((stats) => { + window.electron.getGameStats(game.objectId, game.shop).then((stats) => { setStats(stats); }); } diff --git a/src/renderer/src/components/sidebar/sidebar.tsx b/src/renderer/src/components/sidebar/sidebar.tsx index 383d2197..c509e489 100644 --- a/src/renderer/src/components/sidebar/sidebar.tsx +++ b/src/renderer/src/components/sidebar/sidebar.tsx @@ -140,7 +140,10 @@ export function Sidebar() { event: React.MouseEvent, game: LibraryGame ) => { - const path = buildGameDetailsPath(game); + const path = buildGameDetailsPath({ + ...game, + objectId: game.objectID, + }); if (path !== location.pathname) { navigate(path); } diff --git a/src/renderer/src/context/game-details/game-details.context.tsx b/src/renderer/src/context/game-details/game-details.context.tsx index 82984d9a..39771623 100644 --- a/src/renderer/src/context/game-details/game-details.context.tsx +++ b/src/renderer/src/context/game-details/game-details.context.tsx @@ -31,7 +31,7 @@ export const gameDetailsContext = createContext({ gameTitle: "", isGameRunning: false, isLoading: false, - objectID: undefined, + objectId: undefined, gameColor: "", showRepacksModal: false, showGameOptionsModal: false, @@ -97,7 +97,7 @@ export function GameDetailsContextProvider({ const updateGame = useCallback(async () => { return window.electron - .getGameByObjectID(objectId!) + .getGameByObjectId(objectId!) .then((result) => setGame(result)); }, [setGame, objectId]); @@ -199,7 +199,7 @@ export function GameDetailsContextProvider({ gameTitle, isGameRunning, isLoading, - objectID: objectId, + objectId, gameColor, showGameOptionsModal, showRepacksModal, diff --git a/src/renderer/src/context/game-details/game-details.context.types.ts b/src/renderer/src/context/game-details/game-details.context.types.ts index 7c3bd20b..9a09f74e 100644 --- a/src/renderer/src/context/game-details/game-details.context.types.ts +++ b/src/renderer/src/context/game-details/game-details.context.types.ts @@ -14,7 +14,7 @@ export interface GameDetailsContext { gameTitle: string; isGameRunning: boolean; isLoading: boolean; - objectID: string | undefined; + objectId: string | undefined; gameColor: string; showRepacksModal: boolean; showGameOptionsModal: boolean; diff --git a/src/renderer/src/context/repacks/repacks.context.tsx b/src/renderer/src/context/repacks/repacks.context.tsx index cddbb209..054df60b 100644 --- a/src/renderer/src/context/repacks/repacks.context.tsx +++ b/src/renderer/src/context/repacks/repacks.context.tsx @@ -50,6 +50,7 @@ export function RepacksContextProvider({ children }: RepacksContextProps) { }, []); useEffect(() => { + console.log("CALLED"); indexRepacks(); }, [indexRepacks]); diff --git a/src/renderer/src/declaration.d.ts b/src/renderer/src/declaration.d.ts index 870b592a..57a7db6d 100644 --- a/src/renderer/src/declaration.d.ts +++ b/src/renderer/src/declaration.d.ts @@ -51,27 +51,24 @@ declare global { searchGames: (query: string) => Promise; getCatalogue: (category: CatalogueCategory) => Promise; getGameShopDetails: ( - objectID: string, + objectId: string, shop: GameShop, language: string ) => Promise; getRandomGame: () => Promise; getHowLongToBeat: ( - objectID: string, + objectId: string, shop: GameShop, title: string ) => Promise; - getGames: ( - take?: number, - prevCursor?: number - ) => Promise<{ results: CatalogueEntry[]; cursor: number }>; + getGames: (take?: number, skip?: number) => Promise; searchGameRepacks: (query: string) => Promise; getGameStats: (objectId: string, shop: GameShop) => Promise; getTrendingGames: () => Promise; /* Library */ addGameToLibrary: ( - objectID: string, + objectId: string, title: string, shop: GameShop ) => Promise; @@ -87,7 +84,7 @@ declare global { removeGameFromLibrary: (gameId: number) => Promise; removeGame: (gameId: number) => Promise; deleteGameFolder: (gameId: number) => Promise; - getGameByObjectID: (objectID: string) => Promise; + getGameByObjectId: (objectId: string) => Promise; onGamesRunning: ( cb: ( gamesRunning: Pick[] diff --git a/src/renderer/src/helpers.ts b/src/renderer/src/helpers.ts index 3dea26d3..a9fc3cdd 100644 --- a/src/renderer/src/helpers.ts +++ b/src/renderer/src/helpers.ts @@ -27,11 +27,11 @@ export const getSteamLanguage = (language: string) => { }; export const buildGameDetailsPath = ( - game: { shop: GameShop; objectID: string; title: string }, + game: { shop: GameShop; objectId: string; title: string }, params: Record = {} ) => { const searchParams = new URLSearchParams({ title: game.title, ...params }); - return `/game/${game.shop}/${game.objectID}?${searchParams.toString()}`; + return `/game/${game.shop}/${game.objectId}?${searchParams.toString()}`; }; export const darkenColor = (color: string, amount: number, alpha: number = 1) => diff --git a/src/renderer/src/main.tsx b/src/renderer/src/main.tsx index d845e028..5b72264a 100644 --- a/src/renderer/src/main.tsx +++ b/src/renderer/src/main.tsx @@ -64,7 +64,7 @@ ReactDOM.createRoot(document.getElementById("root")!).render( - + diff --git a/src/renderer/src/pages/catalogue/catalogue.tsx b/src/renderer/src/pages/catalogue/catalogue.tsx index ee1f5395..0ce77fa6 100644 --- a/src/renderer/src/pages/catalogue/catalogue.tsx +++ b/src/renderer/src/pages/catalogue/catalogue.tsx @@ -24,12 +24,10 @@ export function Catalogue() { const contentRef = useRef(null); - const cursorRef = useRef(0); - const navigate = useNavigate(); const [searchParams] = useSearchParams(); - const cursor = Number(searchParams.get("cursor") ?? 0); + const skip = Number(searchParams.get("skip") ?? 0); const handleGameClick = (game: CatalogueEntry) => { dispatch(clearSearch()); @@ -42,11 +40,10 @@ export function Catalogue() { setSearchResults([]); window.electron - .getGames(24, cursor) - .then(({ results, cursor }) => { + .getGames(24, skip) + .then((results) => { return new Promise((resolve) => { setTimeout(() => { - cursorRef.current = cursor; setSearchResults(results); resolve(null); }, 500); @@ -55,11 +52,11 @@ export function Catalogue() { .finally(() => { setIsLoading(false); }); - }, [dispatch, cursor, searchParams]); + }, [dispatch, skip, searchParams]); const handleNextPage = () => { const params = new URLSearchParams({ - cursor: cursorRef.current.toString(), + skip: String(skip + 24), }); navigate(`/catalogue?${params.toString()}`); @@ -80,7 +77,7 @@ export function Catalogue() { diff --git a/src/renderer/src/pages/game-details/cloud-sync-files-modal/cloud-sync-files-modal.tsx b/src/renderer/src/pages/game-details/cloud-sync-files-modal/cloud-sync-files-modal.tsx index db36a285..f8a31223 100644 --- a/src/renderer/src/pages/game-details/cloud-sync-files-modal/cloud-sync-files-modal.tsx +++ b/src/renderer/src/pages/game-details/cloud-sync-files-modal/cloud-sync-files-modal.tsx @@ -1,4 +1,4 @@ -import { Modal, ModalProps, TextField } from "@renderer/components"; +import { Modal, ModalProps } from "@renderer/components"; import { useContext, useMemo } from "react"; import { cloudSyncContext } from "@renderer/context"; @@ -11,6 +11,8 @@ export function CloudSyncFilesModal({ }: CloudSyncFilesModalProps) { const { backupPreview } = useContext(cloudSyncContext); + console.log(backupPreview); + const files = useMemo(() => { if (!backupPreview) { return []; @@ -51,22 +53,24 @@ export function CloudSyncFilesModal({ ))} */} -
    - {files.map((file) => ( -
  • - -
  • - ))} -
+ + + + + + + + + + {files.map((file) => ( + + + + + + ))} + +
ArquivoHashTamanho
{file.path}{file.change}{file.path}
); } diff --git a/src/renderer/src/pages/game-details/cloud-sync-modal/cloud-sync-modal.tsx b/src/renderer/src/pages/game-details/cloud-sync-modal/cloud-sync-modal.tsx index ef57d1be..27ac7d80 100644 --- a/src/renderer/src/pages/game-details/cloud-sync-modal/cloud-sync-modal.tsx +++ b/src/renderer/src/pages/game-details/cloud-sync-modal/cloud-sync-modal.tsx @@ -43,7 +43,7 @@ export function CloudSyncModal({ visible, onClose }: CloudSyncModalProps) { setShowCloudSyncFilesModal, } = useContext(cloudSyncContext); - const { objectID, shop, gameTitle } = useContext(gameDetailsContext); + const { objectId, shop, gameTitle } = useContext(gameDetailsContext); const { showSuccessToast, showErrorToast } = useToast(); @@ -63,13 +63,13 @@ export function CloudSyncModal({ visible, onClose }: CloudSyncModalProps) { useEffect(() => { gameBackupsTable - .where({ shop: shop, objectId: objectID }) + .where({ shop: shop, objectId }) .last() .then((lastBackup) => setLastBackup(lastBackup || null)); const removeBackupDownloadProgressListener = window.electron.onBackupDownloadProgress( - objectID!, + objectId!, shop, (progressEvent) => { setBackupDownloadProgress(progressEvent); @@ -79,7 +79,7 @@ export function CloudSyncModal({ visible, onClose }: CloudSyncModalProps) { return () => { removeBackupDownloadProgressListener(); }; - }, [backupPreview, objectID, shop]); + }, [backupPreview, objectId, shop]); const handleBackupInstallClick = async (artifactId: string) => { setBackupDownloadProgress(null); diff --git a/src/renderer/src/pages/game-details/game-details-content.tsx b/src/renderer/src/pages/game-details/game-details-content.tsx index 7350ccfd..fab6a49b 100644 --- a/src/renderer/src/pages/game-details/game-details-content.tsx +++ b/src/renderer/src/pages/game-details/game-details-content.tsx @@ -26,7 +26,7 @@ export function GameDetailsContent() { const { t } = useTranslation("game_details"); const { - objectID, + objectId, shopDetails, game, gameColor, @@ -42,7 +42,7 @@ export function GameDetailsContent() { const [backdropOpactiy, setBackdropOpacity] = useState(1); const handleHeroLoad = async () => { - const output = await average(steamUrlBuilder.libraryHero(objectID!), { + const output = await average(steamUrlBuilder.libraryHero(objectId!), { amount: 1, format: "hex", }); @@ -56,7 +56,7 @@ export function GameDetailsContent() { useEffect(() => { setBackdropOpacity(1); - }, [objectID]); + }, [objectId]); const onScroll: React.UIEventHandler = (event) => { const heroHeight = heroRef.current?.clientHeight ?? styles.HERO_HEIGHT; @@ -90,7 +90,7 @@ export function GameDetailsContent() { return (
{game?.title}
{game?.title} diff --git a/src/renderer/src/pages/game-details/game-details.tsx b/src/renderer/src/pages/game-details/game-details.tsx index 89a34fff..f2b928b5 100644 --- a/src/renderer/src/pages/game-details/game-details.tsx +++ b/src/renderer/src/pages/game-details/game-details.tsx @@ -33,7 +33,7 @@ export function GameDetails() { const [randomGame, setRandomGame] = useState(null); const [randomizerLocked, setRandomizerLocked] = useState(false); - const { objectID, shop } = useParams(); + const { objectId, shop } = useParams(); const [searchParams] = useSearchParams(); const fromRandomizer = searchParams.get("fromRandomizer"); @@ -50,7 +50,7 @@ export function GameDetails() { window.electron.getRandomGame().then((randomGame) => { setRandomGame(randomGame); }); - }, [objectID]); + }, [objectId]); const handleRandomizerClick = () => { if (randomGame) { @@ -82,7 +82,7 @@ export function GameDetails() { {({ @@ -105,7 +105,7 @@ export function GameDetails() { ) => { await startDownload({ repackId: repack.id, - objectID: objectID!, + objectId: objectId!, title: gameTitle, downloader, shop: shop as GameShop, @@ -125,7 +125,7 @@ export function GameDetails() { return ( diff --git a/src/renderer/src/pages/game-details/hero/hero-panel-actions.tsx b/src/renderer/src/pages/game-details/hero/hero-panel-actions.tsx index 323b3c8f..88eb7c63 100644 --- a/src/renderer/src/pages/game-details/hero/hero-panel-actions.tsx +++ b/src/renderer/src/pages/game-details/hero/hero-panel-actions.tsx @@ -18,7 +18,7 @@ export function HeroPanelActions() { game, repacks, isGameRunning, - objectID, + objectId, gameTitle, setShowGameOptionsModal, setShowRepacksModal, @@ -39,7 +39,7 @@ export function HeroPanelActions() { setToggleLibraryGameDisabled(true); try { - await window.electron.addGameToLibrary(objectID!, gameTitle, "steam"); + await window.electron.addGameToLibrary(objectId!, gameTitle, "steam"); updateLibrary(); updateGame(); diff --git a/src/renderer/src/pages/game-details/sidebar/sidebar.tsx b/src/renderer/src/pages/game-details/sidebar/sidebar.tsx index e56f0764..5d7e2d56 100644 --- a/src/renderer/src/pages/game-details/sidebar/sidebar.tsx +++ b/src/renderer/src/pages/game-details/sidebar/sidebar.tsx @@ -24,11 +24,11 @@ export function Sidebar() { const { numberFormatter } = useFormat(); // useEffect(() => { - // if (objectID) { + // if (objectId) { // setHowLongToBeat({ isLoading: true, data: null }); // window.electron - // .getHowLongToBeat(objectID, "steam", gameTitle) + // .getHowLongToBeat(objectId, "steam", gameTitle) // .then((howLongToBeat) => { // setHowLongToBeat({ isLoading: false, data: howLongToBeat }); // }) @@ -36,7 +36,7 @@ export function Sidebar() { // setHowLongToBeat({ isLoading: false, data: null }); // }); // } - // }, [objectID, gameTitle]); + // }, [objectId, gameTitle]); return (
{ uris: string; } +const state = { + repacks: [] as SerializedGameRepack[], +}; + self.onmessage = async ( event: MessageEvent<[string, string] | "INDEX_REPACKS"> ) => { diff --git a/src/shared/index.ts b/src/shared/index.ts index 556000f2..ec3fe9d9 100644 --- a/src/shared/index.ts +++ b/src/shared/index.ts @@ -91,14 +91,14 @@ export const getDownloadersForUris = (uris: string[]) => { }; export const steamUrlBuilder = { - library: (objectID: string) => - `https://steamcdn-a.akamaihd.net/steam/apps/${objectID}/header.jpg`, - libraryHero: (objectID: string) => - `https://steamcdn-a.akamaihd.net/steam/apps/${objectID}/library_hero.jpg`, - logo: (objectID: string) => - `https://cdn.cloudflare.steamstatic.com/steam/apps/${objectID}/logo.png`, - cover: (objectID: string) => - `https://cdn.cloudflare.steamstatic.com/steam/apps/${objectID}/library_600x900.jpg`, - icon: (objectID: string, clientIcon: string) => - `https://cdn.cloudflare.steamstatic.com/steamcommunity/public/images/apps/${objectID}/${clientIcon}.ico`, + library: (objectId: string) => + `https://steamcdn-a.akamaihd.net/steam/apps/${objectId}/header.jpg`, + libraryHero: (objectId: string) => + `https://steamcdn-a.akamaihd.net/steam/apps/${objectId}/library_hero.jpg`, + logo: (objectId: string) => + `https://cdn.cloudflare.steamstatic.com/steam/apps/${objectId}/logo.png`, + cover: (objectId: string) => + `https://cdn.cloudflare.steamstatic.com/steam/apps/${objectId}/library_600x900.jpg`, + icon: (objectId: string, clientIcon: string) => + `https://cdn.cloudflare.steamstatic.com/steamcommunity/public/images/apps/${objectId}/${clientIcon}.ico`, }; diff --git a/src/types/index.ts b/src/types/index.ts index cd06cfcc..0ab1c8b9 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -29,7 +29,7 @@ export interface GameRepack { } export type ShopDetails = SteamAppDetails & { - objectID: string; + objectId: string; }; export interface TorrentFile { @@ -39,7 +39,7 @@ export interface TorrentFile { /* Used by the catalogue */ export interface CatalogueEntry { - objectID: string; + objectId: string; shop: GameShop; title: string; /* Epic Games covers cannot be guessed with objectID */ @@ -54,6 +54,8 @@ export interface UserGame { cover: string; playTimeInSeconds: number; lastTimePlayed: Date | null; + unlockedAchievementCount: number; + achievementCount: number; } export interface DownloadQueue { @@ -126,7 +128,7 @@ export interface HowLongToBeatCategory { export interface Steam250Game { title: string; - objectID: string; + objectId: string; } export interface SteamGame { @@ -142,7 +144,7 @@ export type AppUpdaterEvent = /* Events */ export interface StartGameDownloadPayload { repackId: number; - objectID: string; + objectId: string; title: string; shop: GameShop; uri: string; @@ -187,7 +189,7 @@ export interface UserRelation { updatedAt: string; } -export interface UserProfileCurrentGame extends Omit { +export interface UserProfileCurrentGame extends Omit { objectId: string; sessionDurationInSeconds: number; } diff --git a/yarn.lock b/yarn.lock index 75b9a7d8..8af7c20f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -991,6 +991,13 @@ wrap-ansi "^8.1.0" wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" +"@isaacs/fs-minipass@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz#2d59ae3ab4b38fb4270bfa23d30f8e2e86c7fe32" + integrity sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w== + dependencies: + minipass "^7.0.4" + "@jimp/bmp@^0.22.10": version "0.22.12" resolved "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.22.12.tgz" @@ -1923,20 +1930,6 @@ dependencies: "@types/node" "*" -"@types/adm-zip@^0.5.5": - version "0.5.5" - resolved "https://registry.yarnpkg.com/@types/adm-zip/-/adm-zip-0.5.5.tgz#4588042726aa5f351d7ea88232e4a952f60e7c1a" - integrity sha512-YCGstVMjc4LTY5uK9/obvxBya93axZOVOyf2GSUulADzmLhYE45u2nAssCs/fWBs1Ifq5Vat75JTPwd5XZoPJw== - dependencies: - "@types/node" "*" - -"@types/archiver@^6.0.2": - version "6.0.2" - resolved "https://registry.yarnpkg.com/@types/archiver/-/archiver-6.0.2.tgz#0daf8c83359cbde69de1e4b33dcade6a48a929e2" - integrity sha512-KmROQqbQzKGuaAbmK+ZcytkJ51+YqDa7NmbXjmtC5YBLSyQYo21YaUnQ3HbaPFKL1ooo6RQ6OPYPIDyxfpDDXw== - dependencies: - "@types/readdir-glob" "*" - "@types/auto-launch@^5.0.5": version "5.0.5" resolved "https://registry.npmjs.org/@types/auto-launch/-/auto-launch-5.0.5.tgz" @@ -2311,13 +2304,6 @@ "@types/prop-types" "*" csstype "^3.0.2" -"@types/readdir-glob@*": - version "1.1.5" - resolved "https://registry.yarnpkg.com/@types/readdir-glob/-/readdir-glob-1.1.5.tgz#21a4a98898fc606cb568ad815f2a0eedc24d412a" - integrity sha512-raiuEPUYqXu+nvtY2Pe8s8FEmZ3x5yAH4VkLdihcPdalvsHltomrRC9BzuStrJ9yk06470hS0Crw0f1pXqD+Hg== - dependencies: - "@types/node" "*" - "@types/responselike@^1.0.0": version "1.0.3" resolved "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz" @@ -2609,11 +2595,6 @@ acorn@^8.8.1, acorn@^8.8.2: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.0.tgz#1627bfa2e058148036133b8d9b51a700663c294c" integrity sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw== -adm-zip@^0.5.16: - version "0.5.16" - resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.5.16.tgz#0b5e4c779f07dedea5805cdccb1147071d94a909" - integrity sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ== - agent-base@6: version "6.0.2" resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" @@ -2743,32 +2724,6 @@ applescript@^1.0.0: resolved "https://registry.npmjs.org/applescript/-/applescript-1.0.0.tgz" integrity sha512-yvtNHdWvtbYEiIazXAdp/NY+BBb65/DAseqlNiJQjOx9DynuzOYDbVLBJvuc0ve0VL9x6B3OHF6eH52y9hCBtQ== -archiver-utils@^5.0.0, archiver-utils@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-5.0.2.tgz#63bc719d951803efc72cf961a56ef810760dd14d" - integrity sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA== - dependencies: - glob "^10.0.0" - graceful-fs "^4.2.0" - is-stream "^2.0.1" - lazystream "^1.0.0" - lodash "^4.17.15" - normalize-path "^3.0.0" - readable-stream "^4.0.0" - -archiver@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/archiver/-/archiver-7.0.1.tgz#c9d91c350362040b8927379c7aa69c0655122f61" - integrity sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ== - dependencies: - archiver-utils "^5.0.2" - async "^3.2.4" - buffer-crc32 "^1.0.0" - readable-stream "^4.0.0" - readdir-glob "^1.1.2" - tar-stream "^3.0.0" - zip-stream "^6.0.1" - arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" @@ -2908,11 +2863,6 @@ async@^3.2.3: resolved "https://registry.npmjs.org/async/-/async-3.2.5.tgz" integrity sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg== -async@^3.2.4: - version "3.2.6" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" - integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" @@ -2962,21 +2912,11 @@ axobject-query@^3.2.1: dependencies: dequal "^2.0.3" -b4a@^1.6.4: - version "1.6.6" - resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.6.6.tgz#a4cc349a3851987c3c4ac2d7785c18744f6da9ba" - integrity sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg== - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -bare-events@^2.2.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.5.0.tgz#305b511e262ffd8b9d5616b056464f8e1b3329cc" - integrity sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A== - base64-arraybuffer@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz" @@ -3089,11 +3029,6 @@ browserslist@^4.22.2: node-releases "^2.0.14" update-browserslist-db "^1.0.13" -buffer-crc32@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-1.0.0.tgz#a10993b9055081d55304bd9feb4a072de179f405" - integrity sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w== - buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz" @@ -3269,6 +3204,11 @@ chownr@^2.0.0: resolved "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== +chownr@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-3.0.0.tgz#9855e64ecd240a9cc4267ce8a4aa5d24a1da15e4" + integrity sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g== + chromium-pickle-js@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz" @@ -3414,17 +3354,6 @@ compare-version@^0.1.2: resolved "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz" integrity sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A== -compress-commons@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-6.0.2.tgz#26d31251a66b9d6ba23a84064ecd3a6a71d2609e" - integrity sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg== - dependencies: - crc-32 "^1.2.0" - crc32-stream "^6.0.0" - is-stream "^2.0.1" - normalize-path "^3.0.0" - readable-stream "^4.0.0" - concat-map@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" @@ -3477,11 +3406,6 @@ core-util-is@1.0.2: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - cosmiconfig-typescript-loader@^5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.0.0.tgz" @@ -3509,19 +3433,6 @@ cosmiconfig@^9.0.0: js-yaml "^4.1.0" parse-json "^5.2.0" -crc-32@^1.2.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" - integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== - -crc32-stream@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-6.0.0.tgz#8529a3868f8b27abb915f6c3617c0fadedbf9430" - integrity sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g== - dependencies: - crc-32 "^1.2.0" - readable-stream "^4.0.0" - crc@^3.8.0: version "3.8.0" resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6" @@ -4345,11 +4256,6 @@ event-target-shim@^5.0.0: resolved "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz" integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== -events@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - execa@^8.0.1: version "8.0.1" resolved "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz" @@ -4396,11 +4302,6 @@ fast-diff@^1.1.2: resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz" integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== -fast-fifo@^1.2.0, fast-fifo@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" - integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== - fast-glob@^3.2.9: version "3.3.2" resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz" @@ -4721,18 +4622,6 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@^10.0.0: - version "10.4.5" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" - integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== - dependencies: - foreground-child "^3.1.0" - jackspeak "^3.1.2" - minimatch "^9.0.4" - minipass "^7.1.2" - package-json-from-dist "^1.0.0" - path-scurry "^1.11.1" - glob@^10.3.10: version "10.3.15" resolved "https://registry.npmjs.org/glob/-/glob-10.3.15.tgz" @@ -4744,6 +4633,18 @@ glob@^10.3.10: minipass "^7.0.4" path-scurry "^1.11.0" +glob@^10.3.7: + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + glob@^7.1.3, glob@^7.1.6: version "7.2.3" resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" @@ -5101,7 +5002,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4: version "2.0.4" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -5298,11 +5199,6 @@ is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: dependencies: call-bind "^1.0.7" -is-stream@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - is-stream@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz" @@ -5361,11 +5257,6 @@ isarray@^2.0.5: resolved "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz" integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - isbinaryfile@^4.0.8: version "4.0.10" resolved "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz" @@ -5622,13 +5513,6 @@ lazy-val@^1.0.4, lazy-val@^1.0.5: resolved "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz" integrity sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q== -lazystream@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.1.tgz#494c831062f1f9408251ec44db1cba29242a2638" - integrity sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw== - dependencies: - readable-stream "^2.0.5" - levn@^0.4.1: version "0.4.1" resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" @@ -5917,7 +5801,7 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" -minimatch@^5.0.1, minimatch@^5.1.0, minimatch@^5.1.1: +minimatch@^5.0.1, minimatch@^5.1.1: version "5.1.6" resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz" integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== @@ -5985,6 +5869,14 @@ minizlib@^2.1.1: minipass "^3.0.0" yallist "^4.0.0" +minizlib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-3.0.1.tgz#46d5329d1eb3c83924eff1d3b858ca0a31581012" + integrity sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg== + dependencies: + minipass "^7.0.4" + rimraf "^5.0.5" + mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: version "0.5.3" resolved "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz" @@ -6007,6 +5899,11 @@ mkdirp@^2.1.3: resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz" integrity sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A== +mkdirp@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" + integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== + mlly@^1.4.2, mlly@^1.7.0: version "1.7.0" resolved "https://registry.npmjs.org/mlly/-/mlly-1.7.0.tgz" @@ -6580,16 +6477,6 @@ prettier@^3.2.4: resolved "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz" integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== - progress@^2.0.3: version "2.0.3" resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz" @@ -6650,11 +6537,6 @@ queue-microtask@^1.2.2, queue-microtask@^1.2.3: resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== -queue-tick@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/queue-tick/-/queue-tick-1.0.1.tgz#f6f07ac82c1fd60f82e098b417a80e52f1f4c142" - integrity sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag== - quick-lru@^5.1.1: version "5.1.1" resolved "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz" @@ -6748,19 +6630,6 @@ read-config-file@6.3.2: json5 "^2.2.0" lazy-val "^1.0.4" -readable-stream@^2.0.5: - version "2.3.8" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" - integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.2" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" @@ -6770,17 +6639,6 @@ readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^4.0.0: - version "4.5.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.5.2.tgz#9e7fc4c45099baeed934bff6eb97ba6cf2729e09" - integrity sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g== - dependencies: - abort-controller "^3.0.0" - buffer "^6.0.3" - events "^3.3.0" - process "^0.11.10" - string_decoder "^1.3.0" - readable-web-to-node-stream@^3.0.2: version "3.0.2" resolved "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz" @@ -6788,13 +6646,6 @@ readable-web-to-node-stream@^3.0.2: dependencies: readable-stream "^3.6.0" -readdir-glob@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/readdir-glob/-/readdir-glob-1.1.3.tgz#c3d831f51f5e7bfa62fa2ffbe4b508c640f09584" - integrity sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA== - dependencies: - minimatch "^5.1.0" - readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -6948,6 +6799,13 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +rimraf@^5.0.5: + version "5.0.10" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.10.tgz#23b9843d3dc92db71f96e1a2ce92e39fd2a8221c" + integrity sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ== + dependencies: + glob "^10.3.7" + roarr@^2.15.3: version "2.15.4" resolved "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz" @@ -7012,11 +6870,6 @@ safe-buffer@^5.0.1, safe-buffer@~5.2.0: resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - safe-regex-test@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz" @@ -7234,17 +7087,6 @@ stat-mode@^1.0.0: resolved "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz" integrity sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg== -streamx@^2.15.0: - version "2.20.1" - resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.20.1.tgz#471c4f8b860f7b696feb83d5b125caab2fdbb93c" - integrity sha512-uTa0mU6WUC65iUvzKH4X9hEdvSW7rbPxPtwfWiLMSj3qTdQbAiUboZTxauKfpFuGIGa1C2BYijZ7wgdUXICJhA== - dependencies: - fast-fifo "^1.3.2" - queue-tick "^1.0.1" - text-decoder "^1.1.0" - optionalDependencies: - bare-events "^2.2.0" - "string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" @@ -7318,20 +7160,13 @@ string.prototype.trimstart@^1.0.8: define-properties "^1.2.1" es-object-atoms "^1.0.0" -string_decoder@^1.1.1, string_decoder@^1.3.0: +string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: safe-buffer "~5.2.0" -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - "strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" @@ -7446,15 +7281,6 @@ tar-stream@^2.1.4: inherits "^2.0.3" readable-stream "^3.1.1" -tar-stream@^3.0.0: - version "3.1.7" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-3.1.7.tgz#24b3fb5eabada19fe7338ed6d26e5f7c482e792b" - integrity sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ== - dependencies: - b4a "^1.6.4" - fast-fifo "^1.2.0" - streamx "^2.15.0" - tar@^6.1.12: version "6.2.1" resolved "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz" @@ -7467,6 +7293,18 @@ tar@^6.1.12: mkdirp "^1.0.3" yallist "^4.0.0" +tar@^7.4.3: + version "7.4.3" + resolved "https://registry.yarnpkg.com/tar/-/tar-7.4.3.tgz#88bbe9286a3fcd900e94592cda7a22b192e80571" + integrity sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw== + dependencies: + "@isaacs/fs-minipass" "^4.0.0" + chownr "^3.0.0" + minipass "^7.1.2" + minizlib "^3.0.1" + mkdirp "^3.0.1" + yallist "^5.0.0" + tarn@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/tarn/-/tarn-3.0.2.tgz#73b6140fbb881b71559c4f8bfde3d9a4b3d27693" @@ -7480,13 +7318,6 @@ temp-file@^3.4.0: async-exit-hook "^2.0.1" fs-extra "^10.0.0" -text-decoder@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.2.0.tgz#85f19d4d5088e0b45cd841bdfaeac458dbffeefc" - integrity sha512-n1yg1mOj9DNpk3NeZOx7T6jchTbyJS3i3cucbNN6FcdPriMZx7NsgrGpWWdWZZGxD7ES1XB+3uoqHMgOKaN+fg== - dependencies: - b4a "^1.6.4" - text-extensions@^2.0.0: version "2.4.0" resolved "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz" @@ -7837,7 +7668,7 @@ utf8-byte-length@^1.0.1: resolved "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz" integrity sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA== -util-deprecate@^1.0.1, util-deprecate@~1.0.1: +util-deprecate@^1.0.1: version "1.0.2" resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== @@ -8096,6 +7927,11 @@ yallist@^4.0.0: resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yallist@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-5.0.0.tgz#00e2de443639ed0d78fd87de0d27469fbcffb533" + integrity sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw== + yaml@^2.4.1: version "2.4.2" resolved "https://registry.npmjs.org/yaml/-/yaml-2.4.2.tgz" @@ -8170,15 +8006,6 @@ yup@^1.4.0: toposort "^2.0.2" type-fest "^2.19.0" -zip-stream@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-6.0.1.tgz#e141b930ed60ccaf5d7fa9c8260e0d1748a2bbfb" - integrity sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA== - dependencies: - archiver-utils "^5.0.0" - compress-commons "^6.0.2" - readable-stream "^4.0.0" - zod@^3.23.8: version "3.23.8" resolved "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz"