diff --git a/.env.example b/.env.example index dc7d96e..d25e432 100644 --- a/.env.example +++ b/.env.example @@ -32,9 +32,8 @@ DB_AUTH_PASS= DB_SYNC= DB_LOGGING= DB_DATA_LOCATION=./.temp/database - -DB_CARD_FILE=:memory: +DB_ROOT_HOST=0.0.0.0 EXPRESS_PORT=3302 -GDRIVESYNC_AUTO=true +GDRIVESYNC_AUTO=false diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 29f04b8..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "env": { - "browser": true, - "es2021": true - }, - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": "latest", - "sourceType": "module" - }, - "plugins": [ - "@typescript-eslint" - ], - "rules": { - "indent": [ - "error", - 4 - ], - "linebreak-style": [ - "error", - "unix" - ], - "quotes": [ - "error", - "double" - ], - "semi": [ - "error", - "always" - ] - }, - "globals": { - "jest": true, - "require": true, - "exports": true, - "process": true - }, - "ignorePatterns": [ - "dist/**/*" - ] -} diff --git a/.forgejo/workflows/production.yml b/.forgejo/workflows/production.yml index 110f5e8..cb4ed46 100644 --- a/.forgejo/workflows/production.yml +++ b/.forgejo/workflows/production.yml @@ -30,7 +30,7 @@ jobs: needs: build runs-on: node steps: - - uses: https://github.com/appleboy/ssh-action@v1.0.3 + - uses: https://github.com/appleboy/ssh-action@v1.1.0 env: DB_NAME: ${{ secrets.PROD_DB_NAME }} DB_AUTH_USER: ${{ secrets.PROD_DB_AUTH_USER }} diff --git a/.forgejo/workflows/stage.yml b/.forgejo/workflows/stage.yml index 149a78e..b6c27da 100644 --- a/.forgejo/workflows/stage.yml +++ b/.forgejo/workflows/stage.yml @@ -30,7 +30,7 @@ jobs: needs: build runs-on: node steps: - - uses: https://github.com/appleboy/ssh-action@v1.0.3 + - uses: https://github.com/appleboy/ssh-action@v1.1.0 env: DB_NAME: ${{ secrets.STAGE_DB_NAME }} DB_AUTH_USER: ${{ secrets.STAGE_DB_AUTH_USER }} diff --git a/database/0.9/1729962056556-createUserEffect/Down/01-table-userEffect.sql b/database/0.9/1729962056556-createUserEffect/Down/01-table-userEffect.sql new file mode 100644 index 0000000..ca2a800 --- /dev/null +++ b/database/0.9/1729962056556-createUserEffect/Down/01-table-userEffect.sql @@ -0,0 +1 @@ +DROP TABLE `user_effect`; diff --git a/database/0.9/1729962056556-createUserEffect/Up/01-table-userEffect.sql b/database/0.9/1729962056556-createUserEffect/Up/01-table-userEffect.sql new file mode 100644 index 0000000..17c1811 --- /dev/null +++ b/database/0.9/1729962056556-createUserEffect/Up/01-table-userEffect.sql @@ -0,0 +1,10 @@ +CREATE TABLE `user_effect` ( + `Id` varchar(255) NOT NULL, + `WhenCreated` datetime NOT NULL, + `WhenUpdated` datetime NOT NULL, + `Name` varchar(255) NOT NULL, + `UserId` varchar(255) NOT NULL, + `Unused` int NOT NULL DEFAULT 0, + `WhenExpires` datetime NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; diff --git a/docs/google-drive-sync.md b/docs/google-drive-sync.md new file mode 100644 index 0000000..1847f70 --- /dev/null +++ b/docs/google-drive-sync.md @@ -0,0 +1,35 @@ +# Google Drive Sync + +The bot relies on an external sync between the local file system and Google +Drive in order to get newer cards to the bot. This is done using +[Rclone](https://rclone.org/). + +The process for this is done by once the `/gdrivesync` command is executed by +an admin user of the bot, which calls the system shell to run rclone to the +card folder. + +- The admins who can run the command is specifed in `$BOT_ADMINS`, which are +discord user ids separated by commas. +- The card folder is located at `$DATA_DIR/cards`. +- The source requires rclone's remote to be setup as `card-drop-gdrive`. + +The exact command it runs is: `rclone sync card-drop-gdrive: $DATA_DIR/cards`. + +Once it syncs the database will reread all the cards for updates and then load +them into the bot to be given. + +## Safe Mode +Safe mode is a function of the bot which disables the `/drop` command function +and any other functions which rely on the card metadata. Safe mode is activated +upon failure to sync properly. It is disabled once errors are resolved. + +The reason for safe mode is to ensure that the bot stays online for admins to +be able to resync the bot in case there's an error without it crashing. + +## Google Drive +Please see the Rclone documentation on how to setup a remote using Google +Drive. You will need to make an app password for this. + +- scope: `drive.readonly` +- root\_folder\_id: The folder id where the cards are located, this can be found + by looking at the url when viewing the folder in the browser in google drive. diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..64bf3e2 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,55 @@ +import js from "@eslint/js"; +import ts from "typescript-eslint"; + +export default [ + { + ignores: [ + "**/dist/", + "eslint.config.mjs", + "jest.config.cjs", + "jest.setup.js", + "**/.temp/**/*" + ], + }, + js.configs.recommended, + ...ts.configs.recommended, + { + languageOptions: { + globals: { + exports: "writable", + module: "writable", + require: "writable", + process: "writable", + console: "writable", + jest: "writable", + }, + + ecmaVersion: 6, + sourceType: "script", + }, + + files: [ + "./src", + "./tests" + ], + + rules: { + camelcase: "error", + "brace-style": ["error", "1tbs"], + "comma-dangle": ["error", "never"], + + "comma-spacing": ["error", { + before: false, + after: true, + }], + + "comma-style": ["error", "last"], + "arrow-body-style": ["error", "as-needed"], + "arrow-parens": ["error", "as-needed"], + "arrow-spacing": "error", + "no-var": "error", + "prefer-template": "error", + "prefer-const": "error", + }, + } +]; diff --git a/jest.setup.js b/jest.setup.js index d583d1a..8e9ae9a 100644 --- a/jest.setup.js +++ b/jest.setup.js @@ -1,3 +1,4 @@ jest.setTimeout(1 * 1000); // 1 second jest.resetModules(); -jest.resetAllMocks(); \ No newline at end of file +jest.resetAllMocks(); +jest.useFakeTimers(); \ No newline at end of file diff --git a/package.json b/package.json index 0e0ce30..137ca15 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "clean": "rm -rf node_modules/ dist/", "build": "tsc", "start": "node ./dist/bot.js", - "test": "echo true", + "test": "jest", "lint": "eslint .", "lint:fix": "eslint . --fix", "db:up": "typeorm migration:run -d dist/database/dataSources/appDataSource.js", @@ -27,18 +27,19 @@ "dependencies": { "@discordjs/rest": "^2.0.0", "@types/clone-deep": "^4.0.4", - "@types/express": "^4.17.20", - "@types/jest": "^29.0.0", - "@types/uuid": "^9.0.0", + "@types/express": "^5.0.0", + "@types/jest": "^29.5.14", + "@types/uuid": "^10.0.0", "axios": "^1.8.4", "body-parser": "^1.20.2", "canvas": "^2.11.2", "clone-deep": "^4.0.1", "cron": "^3.1.7", - "discord.js": "^14.15.3", + "discord.js": "^14.16.3", "dotenv": "^16.0.0", "express": "^4.18.2", - "glob": "^10.3.10", + "fuse.js": "^7.0.0", + "glob": "^11.0.0", "jest": "^29.0.0", "jest-mock-extended": "^3.0.0", "jimp": "^1.6.0", @@ -46,19 +47,18 @@ "mysql": "^2.18.1", "ts-jest": "^29.0.0", "typeorm": "0.3.20", - "winston": "^3.11.0", + "winston": "^3.15.0", "winston-daily-rotate-file": "^5.0.0", "winston-discord-transport": "^1.3.0" }, - "resolutions": { - "**/ws": "^8.17.1" - }, + "resolutions": {}, "devDependencies": { - "@types/node": "^20.0.0", - "@typescript-eslint/eslint-plugin": "^7.0.0", - "@typescript-eslint/parser": "^6.16.0", - "eslint": "^8.56.0", - "np": "^9.0.0", - "typescript": "^5.0.0" + "@types/node": "^22.8.1", + "@typescript-eslint/eslint-plugin": "^8.11.0", + "@typescript-eslint/parser": "^8.11.0", + "eslint": "^9.13.0", + "np": "^10.0.7", + "typescript": "^5.0.0", + "typescript-eslint": "^8.11.0" } } diff --git a/src/bot.ts b/src/bot.ts index e5e25a3..871b927 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -38,6 +38,7 @@ const client = new CoreClient([ Registry.RegisterCommands(); Registry.RegisterButtonEvents(); +Registry.RegisterStringDropdownEvents(); if (!existsSync(`${process.env.DATA_DIR}/cards`) && process.env.GDRIVESYNC_AUTO && process.env.GDRIVESYNC_AUTO == "true") { console.log("Card directory not found, syncing..."); diff --git a/src/buttonEvents/Claim.ts b/src/buttonEvents/Claim.ts index 4d5d97a..d139f42 100644 --- a/src/buttonEvents/Claim.ts +++ b/src/buttonEvents/Claim.ts @@ -1,17 +1,18 @@ import { ButtonInteraction } from "discord.js"; import { ButtonEvent } from "../type/buttonEvent"; import Inventory from "../database/entities/app/Inventory"; -import { CoreClient } from "../client/client"; import { default as eClaim } from "../database/entities/app/Claim"; import AppLogger from "../client/appLogger"; -import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata"; import User from "../database/entities/app/User"; import CardConstants from "../constants/CardConstants"; +import GetCardsHelper from "../helpers/DropHelpers/GetCardsHelper"; +import DropEmbedHelper from "../helpers/DropHelpers/DropEmbedHelper"; export default class Claim extends ButtonEvent { public override async execute(interaction: ButtonInteraction) { if (!interaction.guild || !interaction.guildId) return; if (!interaction.channel) return; + if (!interaction.channel.isSendable()) return; await interaction.deferUpdate(); @@ -21,10 +22,10 @@ export default class Claim extends ButtonEvent { const userId = interaction.user.id; const whenDropped = interaction.message.createdAt; - const lastClaimableDate = new Date(Date.now() - (1000 * 60 * 5)); // 5 minutes ago + const lastClaimableDate = new Date(Date.now() - (1000 * 60 * 2)); // 2 minutes ago if (whenDropped < lastClaimableDate) { - await interaction.channel.send(`${interaction.user}, Cards can only be claimed within 5 minutes of it being dropped!`); + await interaction.channel.send(`${interaction.user}, Cards can only be claimed within 2 minutes of it being dropped!`); return; } @@ -34,11 +35,6 @@ export default class Claim extends ButtonEvent { AppLogger.LogSilly("Button/Claim", `${user.Id} has ${user.Currency} currency`); - if (!user.RemoveCurrency(CardConstants.ClaimCost)) { - await interaction.channel.send(`${interaction.user}, Not enough currency! You need ${CardConstants.ClaimCost} currency, you have ${user.Currency}!`); - return; - } - const claimed = await eClaim.FetchOneByClaimId(claimId); if (claimed) { @@ -46,19 +42,12 @@ export default class Claim extends ButtonEvent { return; } - if (claimId == CoreClient.ClaimId && userId != droppedBy) { - await interaction.channel.send(`${interaction.user}, The latest dropped card can only be claimed by the user who dropped it!`); - return; - } - - await user.Save(User, user); - let inventory = await Inventory.FetchOneByCardNumberAndUserId(userId, cardNumber); if (!inventory) { inventory = new Inventory(userId, cardNumber, 1); } else { - inventory.SetQuantity(inventory.Quantity + 1); + inventory.AddQuantity(1); } await inventory.Save(Inventory, inventory); @@ -68,16 +57,18 @@ export default class Claim extends ButtonEvent { await claim.Save(eClaim, claim); - const card = CardDropHelperMetadata.GetCardByCardNumber(cardNumber); + const card = GetCardsHelper.GetCardByCardNumber(cardNumber); if (!card) { + AppLogger.LogError("Button/Claim", `Unable to find card, ${cardNumber}`); + return; } const imageFileName = card.card.path.split("/").pop()!; - const embed = CardDropHelperMetadata.GenerateDropEmbed(card, inventory.Quantity, imageFileName, interaction.user.username, user.Currency); - const row = CardDropHelperMetadata.GenerateDropButtons(card, claimId, interaction.user.id, true); + const embed = DropEmbedHelper.GenerateDropEmbed(card, inventory.Quantity, imageFileName, interaction.user.username, user.Currency); + const row = DropEmbedHelper.GenerateDropButtons(card, claimId, interaction.user.id, true); await interaction.editReply({ embeds: [ embed ], diff --git a/src/buttonEvents/Effects.ts b/src/buttonEvents/Effects.ts new file mode 100644 index 0000000..cd1a765 --- /dev/null +++ b/src/buttonEvents/Effects.ts @@ -0,0 +1,26 @@ +import { ButtonInteraction } from "discord.js"; +import { ButtonEvent } from "../type/buttonEvent"; +import List from "./Effects/List"; +import Use from "./Effects/Use"; +import AppLogger from "../client/appLogger"; +import Buy from "./Effects/Buy"; + +export default class Effects extends ButtonEvent { + public override async execute(interaction: ButtonInteraction) { + const action = interaction.customId.split(" ")[1]; + + switch (action) { + case "list": + await List(interaction); + break; + case "use": + await Use.Execute(interaction); + break; + case "buy": + await Buy.Execute(interaction); + break; + default: + AppLogger.LogError("Buttons/Effects", `Unknown action, ${action}`); + } + } +} diff --git a/src/buttonEvents/Effects/Buy.ts b/src/buttonEvents/Effects/Buy.ts new file mode 100644 index 0000000..49cc75f --- /dev/null +++ b/src/buttonEvents/Effects/Buy.ts @@ -0,0 +1,120 @@ +import {ButtonInteraction} from "discord.js"; +import AppLogger from "../../client/appLogger"; +import EffectHelper from "../../helpers/EffectHelper"; +import EmbedColours from "../../constants/EmbedColours"; +import User from "../../database/entities/app/User"; +import {EffectDetails} from "../../constants/EffectDetails"; + +export default class Buy { + public static async Execute(interaction: ButtonInteraction) { + const subaction = interaction.customId.split(" ")[2]; + + switch (subaction) { + case "confirm": + await this.Confirm(interaction); + break; + case "cancel": + await this.Cancel(interaction); + break; + default: + AppLogger.LogError("Buy", `Unknown subaction, effects ${subaction}`); + } + } + + private static async Confirm(interaction: ButtonInteraction) { + const id = interaction.customId.split(" ")[3]; + const quantity = interaction.customId.split(" ")[4]; + + if (!id || !quantity) { + AppLogger.LogError("Buy Confirm", "Not enough parameters"); + return; + } + + const effectDetail = EffectDetails.get(id); + + if (!effectDetail) { + AppLogger.LogError("Buy Confirm", "Effect detail not found!"); + return; + } + + const quantityNumber = Number(quantity); + + if (!quantityNumber || quantityNumber < 1) { + AppLogger.LogError("Buy Confirm", "Invalid number"); + return; + } + + const totalCost = effectDetail.cost * quantityNumber; + + const user = await User.FetchOneById(User, interaction.user.id); + + if (!user) { + AppLogger.LogError("Buy Confirm", "Unable to find user"); + return; + } + + if (user.Currency < totalCost) { + interaction.reply(`You don't have enough currency to buy this! You have \`${user.Currency} Currency\` and need \`${totalCost} Currency\`!`); + return; + } + + user.RemoveCurrency(totalCost); + await user.Save(User, user); + + await EffectHelper.AddEffectToUserInventory(interaction.user.id, id, quantityNumber); + + const generatedEmbed = await EffectHelper.GenerateEffectBuyEmbed(interaction.user.id, id, quantityNumber, true); + + if (typeof generatedEmbed == "string") { + await interaction.reply(generatedEmbed); + return; + } + + generatedEmbed.embed.setColor(EmbedColours.Success); + generatedEmbed.embed.setFooter({ text: "Purchased" }); + + await interaction.update({ + embeds: [ generatedEmbed.embed ], + components: [ generatedEmbed.row ], + }); + } + + private static async Cancel(interaction: ButtonInteraction) { + const id = interaction.customId.split(" ")[3]; + const quantity = interaction.customId.split(" ")[4]; + + if (!id || !quantity) { + AppLogger.LogError("Buy Cancel", "Not enough parameters"); + return; + } + + const effectDetail = EffectDetails.get(id); + + if (!effectDetail) { + AppLogger.LogError("Buy Cancel", "Effect detail not found!"); + return; + } + + const quantityNumber = Number(quantity); + + if (!quantityNumber || quantityNumber < 1) { + AppLogger.LogError("Buy Cancel", "Invalid number"); + return; + } + + const generatedEmbed = await EffectHelper.GenerateEffectBuyEmbed(interaction.user.id, id, quantityNumber, true); + + if (typeof generatedEmbed == "string") { + await interaction.reply(generatedEmbed); + return; + } + + generatedEmbed.embed.setColor(EmbedColours.Error); + generatedEmbed.embed.setFooter({ text: "Cancelled" }); + + await interaction.update({ + embeds: [ generatedEmbed.embed ], + components: [ generatedEmbed.row ], + }); + } +} diff --git a/src/buttonEvents/Effects/List.ts b/src/buttonEvents/Effects/List.ts new file mode 100644 index 0000000..d86dfce --- /dev/null +++ b/src/buttonEvents/Effects/List.ts @@ -0,0 +1,20 @@ +import { ButtonInteraction } from "discord.js"; +import EffectHelper from "../../helpers/EffectHelper"; + +export default async function List(interaction: ButtonInteraction) { + const pageOption = interaction.customId.split(" ")[2]; + + const page = Number(pageOption); + + if (!page) { + await interaction.reply("Page option is not a valid number"); + return; + } + + const result = await EffectHelper.GenerateEffectListEmbed(interaction.user.id, page); + + await interaction.update({ + embeds: [ result.embed ], + components: [ result.row ], + }); +} \ No newline at end of file diff --git a/src/buttonEvents/Effects/Use.ts b/src/buttonEvents/Effects/Use.ts new file mode 100644 index 0000000..5bfe2fd --- /dev/null +++ b/src/buttonEvents/Effects/Use.ts @@ -0,0 +1,132 @@ +import { ActionRowBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, EmbedBuilder } from "discord.js"; +import { EffectDetails } from "../../constants/EffectDetails"; +import EffectHelper from "../../helpers/EffectHelper"; +import EmbedColours from "../../constants/EmbedColours"; +import TimeLengthInput from "../../helpers/TimeLengthInput"; +import AppLogger from "../../client/appLogger"; + +export default class Use { + public static async Execute(interaction: ButtonInteraction) { + const subaction = interaction.customId.split(" ")[2]; + + switch (subaction) { + case "confirm": + await this.UseConfirm(interaction); + break; + case "cancel": + await this.UseCancel(interaction); + break; + } + } + + private static async UseConfirm(interaction: ButtonInteraction) { + const id = interaction.customId.split(" ")[3]; + + const effectDetail = EffectDetails.get(id); + + if (!effectDetail) { + AppLogger.LogError("Button/Effects/Use", `Effect not found, ${id}`); + + await interaction.reply("Effect not found in system!"); + return; + } + + const now = new Date(); + + const whenExpires = new Date(now.getTime() + effectDetail.duration); + + const result = await EffectHelper.UseEffect(interaction.user.id, id, whenExpires); + + if (!result) { + await interaction.reply("Unable to use effect! Please make sure you have it in your inventory and is not on cooldown"); + return; + } + + const embed = new EmbedBuilder() + .setTitle("Effect Used") + .setDescription("You now have an active effect!") + .setColor(EmbedColours.Green) + .addFields([ + { + name: "Effect", + value: effectDetail.friendlyName, + inline: true, + }, + { + name: "Expires", + value: ``, + inline: true, + }, + ]); + + const row = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setLabel("Confirm") + .setCustomId(`effects use confirm ${effectDetail.id}`) + .setStyle(ButtonStyle.Primary) + .setDisabled(true), + new ButtonBuilder() + .setLabel("Cancel") + .setCustomId(`effects use cancel ${effectDetail.id}`) + .setStyle(ButtonStyle.Danger) + .setDisabled(true), + ]); + + await interaction.update({ + embeds: [ embed ], + components: [ row ], + }); + } + + private static async UseCancel(interaction: ButtonInteraction) { + const id = interaction.customId.split(" ")[3]; + + const effectDetail = EffectDetails.get(id); + + if (!effectDetail) { + AppLogger.LogError("Button/Effects/Cancel", `Effect not found, ${id}`); + + await interaction.reply("Effect not found in system!"); + return; + } + + const timeLengthInput = TimeLengthInput.ConvertFromMilliseconds(effectDetail.duration); + + const embed = new EmbedBuilder() + .setTitle("Effect Use Cancelled") + .setDescription("The effect from your inventory has not been used") + .setColor(EmbedColours.Grey) + .addFields([ + { + name: "Effect", + value: effectDetail.friendlyName, + inline: true, + }, + { + name: "Expires", + value: timeLengthInput.GetLengthShort(), + inline: true, + }, + ]); + + const row = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setLabel("Confirm") + .setCustomId(`effects use confirm ${effectDetail.id}`) + .setStyle(ButtonStyle.Primary) + .setDisabled(true), + new ButtonBuilder() + .setLabel("Cancel") + .setCustomId(`effects use cancel ${effectDetail.id}`) + .setStyle(ButtonStyle.Danger) + .setDisabled(true), + ]); + + await interaction.update({ + embeds: [ embed ], + components: [ row ], + }); + } +} diff --git a/src/buttonEvents/Inventory.ts b/src/buttonEvents/Inventory.ts index 8356305..73c7019 100644 --- a/src/buttonEvents/Inventory.ts +++ b/src/buttonEvents/Inventory.ts @@ -11,7 +11,7 @@ export default class Inventory extends ButtonEvent { const page = interaction.customId.split(" ")[2]; AppLogger.LogSilly("Button/Inventory", `Parameters: userid=${userid}, page=${page}`); - + await interaction.deferUpdate(); const member = interaction.guild.members.cache.find(x => x.id == userid) || await interaction.guild.members.fetch(userid); @@ -34,7 +34,7 @@ export default class Inventory extends ButtonEvent { await interaction.editReply({ files: [ embed.image ], embeds: [ embed.embed ], - components: [ embed.row ], + components: [ embed.row1, embed.row2 ], }); } catch (e) { AppLogger.LogError("Button/Inventory", `Error generating inventory page for ${member.user.username} with id ${member.user.id}: ${e}`); diff --git a/src/buttonEvents/Multidrop.ts b/src/buttonEvents/Multidrop.ts new file mode 100644 index 0000000..e6ea7c2 --- /dev/null +++ b/src/buttonEvents/Multidrop.ts @@ -0,0 +1,214 @@ +import { AttachmentBuilder, ButtonInteraction, EmbedBuilder } from "discord.js"; +import { ButtonEvent } from "../type/buttonEvent"; +import AppLogger from "../client/appLogger"; +import Inventory from "../database/entities/app/Inventory"; +import EmbedColours from "../constants/EmbedColours"; +import { readFileSync } from "fs"; +import path from "path"; +import ErrorMessages from "../constants/ErrorMessages"; +import User from "../database/entities/app/User"; +import { GetSacrificeAmount } from "../constants/CardRarity"; +import GetCardsHelper from "../helpers/DropHelpers/GetCardsHelper"; +import MultidropEmbedHelper from "../helpers/DropHelpers/MultidropEmbedHelper"; + +export default class Multidrop extends ButtonEvent { + public override async execute(interaction: ButtonInteraction) { + const action = interaction.customId.split(" ")[1]; + + switch (action) { + case "keep": + await this.Keep(interaction); + break; + case "sacrifice": + await this.Sacrifice(interaction); + break; + default: + await interaction.reply("Invalid action"); + AppLogger.LogError("Button/Multidrop", `Invalid action, ${action}`); + } + } + + private async Keep(interaction: ButtonInteraction) { + const cardNumber = interaction.customId.split(" ")[2]; + let cardsRemaining = Number(interaction.customId.split(" ")[3]) || 0; + const userId = interaction.customId.split(" ")[4]; + + if (interaction.user.id != userId) { + await interaction.reply("You're not the user this drop was made for!"); + return; + } + + const card = GetCardsHelper.GetCardByCardNumber(cardNumber); + + if (!card) { + await interaction.reply("Unable to find card."); + AppLogger.LogWarn("Button/Multidrop/Keep", `Card not found, ${cardNumber}`); + return; + } + + if (cardsRemaining < 0) { + await interaction.reply("Your multidrop has ran out! Please buy a new one!"); + return; + } + + const user = await User.FetchOneById(User, interaction.user.id); + + if (!user) { + AppLogger.LogWarn("Button/Multidrop/Keep", ErrorMessages.UnableToFetchUser); + await interaction.reply(ErrorMessages.UnableToFetchUser); + return; + } + + // Claim + let inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, cardNumber); + + if (!inventory) { + inventory = new Inventory(interaction.user.id, cardNumber, 1); + } else { + inventory.AddQuantity(1); + } + + await inventory.Save(Inventory, inventory); + + // Pack has ran out + if (cardsRemaining == 0) { + const embed = new EmbedBuilder() + .setDescription("Your multidrop has ran out! Please buy a new one!") + .setColor(EmbedColours.Ok); + + await interaction.update({ + embeds: [ embed ], + attachments: [], + components: [], + }); + + return; + } + + // Drop next card + const randomCard = GetCardsHelper.GetRandomCard(); + cardsRemaining -= 1; + + if (!randomCard) { + AppLogger.LogWarn("Button/Multidrop/Keep", ErrorMessages.UnableToFetchCard); + await interaction.reply(ErrorMessages.UnableToFetchCard); + return; + } + + await interaction.deferUpdate(); + + try { + const image = readFileSync(path.join(process.env.DATA_DIR!, "cards", randomCard.card.path)); + const imageFileName = randomCard.card.path.split("/").pop()!; + + const attachment = new AttachmentBuilder(image, { name: imageFileName }); + + const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, randomCard.card.id); + const quantityClaimed = inventory ? inventory.Quantity : 0; + + const embed = MultidropEmbedHelper.GenerateMultidropEmbed(randomCard, quantityClaimed, imageFileName, cardsRemaining, undefined, user.Currency); + + const row = MultidropEmbedHelper.GenerateMultidropButtons(randomCard, cardsRemaining, interaction.user.id, cardsRemaining < 0); + + await interaction.editReply({ + embeds: [ embed ], + files: [ attachment ], + components: [ row ], + }); + } catch (e) { + AppLogger.LogError("Button/Multidrop/Keep", `Error sending next drop for card ${randomCard.card.id}: ${e}`); + + await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. (${randomCard.card.id})`); + } + } + + private async Sacrifice(interaction: ButtonInteraction) { + const cardNumber = interaction.customId.split(" ")[2]; + let cardsRemaining = Number(interaction.customId.split(" ")[3]) || 0; + const userId = interaction.customId.split(" ")[4]; + + if (interaction.user.id != userId) { + await interaction.reply("You're not the user this drop was made for!"); + return; + } + + const card = GetCardsHelper.GetCardByCardNumber(cardNumber); + + if (!card) { + await interaction.reply("Unable to find card."); + AppLogger.LogWarn("Button/Multidrop/Sacrifice", `Card not found, ${cardNumber}`); + return; + } + + if (cardsRemaining < 0) { + await interaction.reply("Your multidrop has ran out! Please buy a new one!"); + return; + } + + const user = await User.FetchOneById(User, interaction.user.id); + + if (!user) { + AppLogger.LogWarn("Button/Multidrop/Sacrifice", ErrorMessages.UnableToFetchUser); + await interaction.reply(ErrorMessages.UnableToFetchUser); + return; + } + + // Sacrifice + const sacrificeAmount = GetSacrificeAmount(card.card.type); + + user.AddCurrency(sacrificeAmount); + + await user.Save(User, user); + + // Pack has ran out + if (cardsRemaining == 0) { + const embed = new EmbedBuilder() + .setDescription("Your multidrop has ran out! Please buy a new one!") + .setColor(EmbedColours.Ok); + + await interaction.update({ + embeds: [ embed ], + attachments: [], + components: [], + }); + + return; + } + + // Drop next card + const randomCard = GetCardsHelper.GetRandomCard(); + cardsRemaining -= 1; + + if (!randomCard) { + AppLogger.LogWarn("Button/Multidrop/Sacrifice", ErrorMessages.UnableToFetchCard); + await interaction.reply(ErrorMessages.UnableToFetchCard); + return; + } + + await interaction.deferUpdate(); + + try { + const image = readFileSync(path.join(process.env.DATA_DIR!, "cards", randomCard.card.path)); + const imageFileName = randomCard.card.path.split("/").pop()!; + + const attachment = new AttachmentBuilder(image, { name: imageFileName }); + + const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, randomCard.card.id); + const quantityClaimed = inventory ? inventory.Quantity : 0; + + const embed = MultidropEmbedHelper.GenerateMultidropEmbed(randomCard, quantityClaimed, imageFileName, cardsRemaining, undefined, user.Currency); + + const row = MultidropEmbedHelper.GenerateMultidropButtons(randomCard, cardsRemaining, interaction.user.id, cardsRemaining < 0); + + await interaction.editReply({ + embeds: [ embed ], + files: [ attachment ], + components: [ row ], + }); + } catch (e) { + AppLogger.LogError("Button/Multidrop/Sacrifice", `Error sending next drop for card ${randomCard.card.id}: ${e}`); + + await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. (${randomCard.card.id})`); + } + } +} \ No newline at end of file diff --git a/src/buttonEvents/Reroll.ts b/src/buttonEvents/Reroll.ts index dc9622a..6d97024 100644 --- a/src/buttonEvents/Reroll.ts +++ b/src/buttonEvents/Reroll.ts @@ -5,11 +5,12 @@ import { v4 } from "uuid"; import { CoreClient } from "../client/client"; import Inventory from "../database/entities/app/Inventory"; import Config from "../database/entities/app/Config"; -import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata"; import path from "path"; import AppLogger from "../client/appLogger"; import User from "../database/entities/app/User"; import CardConstants from "../constants/CardConstants"; +import GetCardsHelper from "../helpers/DropHelpers/GetCardsHelper"; +import DropEmbedHelper from "../helpers/DropHelpers/DropEmbedHelper"; export default class Reroll extends ButtonEvent { public override async execute(interaction: ButtonInteraction) { @@ -34,12 +35,14 @@ export default class Reroll extends ButtonEvent { AppLogger.LogInfo("Commands/Drop", `New user (${interaction.user.id}) saved to the database`); } - if (user.Currency < CardConstants.ClaimCost) { + if (!user.RemoveCurrency(CardConstants.ClaimCost)) { await interaction.reply(`Not enough currency! You need ${CardConstants.ClaimCost} currency, you have ${user.Currency}!`); return; } - const randomCard = CardDropHelperMetadata.GetRandomCard(); + await user.Save(User, user); + + const randomCard = await GetCardsHelper.FetchCard(interaction.user.id); if (!randomCard) { await interaction.reply("Unable to fetch card, please try again."); @@ -66,19 +69,17 @@ export default class Reroll extends ButtonEvent { const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, randomCard.card.id); const quantityClaimed = inventory ? inventory.Quantity : 0; - const embed = CardDropHelperMetadata.GenerateDropEmbed(randomCard, quantityClaimed, imageFileName, undefined, user.Currency); + const embed = DropEmbedHelper.GenerateDropEmbed(randomCard, quantityClaimed, imageFileName, undefined, user.Currency); const claimId = v4(); - const row = CardDropHelperMetadata.GenerateDropButtons(randomCard, claimId, interaction.user.id); + const row = DropEmbedHelper.GenerateDropButtons(randomCard, claimId, interaction.user.id); await interaction.editReply({ embeds: [ embed ], files: files, components: [ row ], }); - - CoreClient.ClaimId = claimId; } catch (e) { AppLogger.LogError("Button/Reroll", `Error sending next drop for card ${randomCard.card.id}: ${e}`); diff --git a/src/buttonEvents/Sacrifice.ts b/src/buttonEvents/Sacrifice.ts index a82ba81..de0bb77 100644 --- a/src/buttonEvents/Sacrifice.ts +++ b/src/buttonEvents/Sacrifice.ts @@ -1,10 +1,10 @@ import { ActionRowBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, EmbedBuilder } from "discord.js"; import { ButtonEvent } from "../type/buttonEvent"; import Inventory from "../database/entities/app/Inventory"; -import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata"; import { CardRarityToString, GetSacrificeAmount } from "../constants/CardRarity"; import EmbedColours from "../constants/EmbedColours"; import User from "../database/entities/app/User"; +import GetCardsHelper from "../helpers/DropHelpers/GetCardsHelper"; export default class Sacrifice extends ButtonEvent { public override async execute(interaction: ButtonInteraction) { @@ -23,6 +23,7 @@ export default class Sacrifice extends ButtonEvent { private async confirm(interaction: ButtonInteraction) { const userId = interaction.customId.split(" ")[2]; const cardNumber = interaction.customId.split(" ")[3]; + const quantity = Number(interaction.customId.split(" ")[4]) || 1; if (userId != interaction.user.id) { await interaction.reply("Only the user who created this sacrifice can confirm it."); @@ -31,12 +32,17 @@ export default class Sacrifice extends ButtonEvent { const cardInInventory = await Inventory.FetchOneByCardNumberAndUserId(userId, cardNumber); - if (!cardInInventory) { + if (!cardInInventory || cardInInventory.Quantity == 0) { await interaction.reply("Unable to find card in inventory."); return; } - const cardData = CardDropHelperMetadata.GetCardByCardNumber(cardNumber); + if (cardInInventory.Quantity < quantity) { + await interaction.reply("You can only sacrifice what you own."); + return; + } + + const cardData = GetCardsHelper.GetCardByCardNumber(cardNumber); if (!cardData) { await interaction.reply("Unable to find card in the database."); @@ -50,11 +56,11 @@ export default class Sacrifice extends ButtonEvent { return; } - cardInInventory.RemoveQuantity(1); + cardInInventory.RemoveQuantity(quantity); await cardInInventory.Save(Inventory, cardInInventory); - const cardValue = GetSacrificeAmount(cardData.card.type); + const cardValue = GetSacrificeAmount(cardData.card.type) * quantity; const cardRarityString = CardRarityToString(cardData.card.type); user.AddCurrency(cardValue); @@ -66,6 +72,7 @@ export default class Sacrifice extends ButtonEvent { `Series: ${cardData.series.name}`, `Rarity: ${cardRarityString}`, `Quantity Owned: ${cardInInventory.Quantity}`, + `Quantity To Sacrifice: ${quantity}`, `Sacrifice Amount: ${cardValue}`, ]; @@ -98,6 +105,7 @@ export default class Sacrifice extends ButtonEvent { private async cancel(interaction: ButtonInteraction) { const userId = interaction.customId.split(" ")[2]; const cardNumber = interaction.customId.split(" ")[3]; + const quantity = Number(interaction.customId.split(" ")[4]) || 1; if (userId != interaction.user.id) { await interaction.reply("Only the user who created this sacrifice can cancel it."); @@ -106,19 +114,24 @@ export default class Sacrifice extends ButtonEvent { const cardInInventory = await Inventory.FetchOneByCardNumberAndUserId(userId, cardNumber); - if (!cardInInventory) { + if (!cardInInventory || cardInInventory.Quantity == 0) { await interaction.reply("Unable to find card in inventory."); return; } - const cardData = CardDropHelperMetadata.GetCardByCardNumber(cardNumber); + if (cardInInventory.Quantity < quantity) { + await interaction.reply("You can only sacrifice what you own."); + return; + } + + const cardData = GetCardsHelper.GetCardByCardNumber(cardNumber); if (!cardData) { await interaction.reply("Unable to find card in the database."); return; } - const cardValue = GetSacrificeAmount(cardData.card.type); + const cardValue = GetSacrificeAmount(cardData.card.type) * quantity; const cardRarityString = CardRarityToString(cardData.card.type); const description = [ @@ -126,6 +139,7 @@ export default class Sacrifice extends ButtonEvent { `Series: ${cardData.series.name}`, `Rarity: ${cardRarityString}`, `Quantity Owned: ${cardInInventory.Quantity}`, + `Quantity To Sacrifice: ${quantity}`, `Sacrifice Amount: ${cardValue}`, ]; diff --git a/src/buttonEvents/Trade.ts b/src/buttonEvents/Trade.ts index ef0d1c5..fb8449d 100644 --- a/src/buttonEvents/Trade.ts +++ b/src/buttonEvents/Trade.ts @@ -28,8 +28,10 @@ export default class Trade extends ButtonEvent { const user2CardNumber = interaction.customId.split(" ")[5]; const expiry = interaction.customId.split(" ")[6]; const timeoutId = interaction.customId.split(" ")[7]; + const user1Quantity = Number(interaction.customId.split(" ")[8]) || 1; + const user2Quantity = Number(interaction.customId.split(" ")[9]) || 1; - AppLogger.LogSilly("Button/Trade/AcceptTrade", `Parameters: user1UserId=${user1UserId}, user2UserId=${user2UserId}, user1CardNumber=${user1CardNumber}, user2CardNumber=${user2CardNumber}, expiry=${expiry}, timeoutId=${timeoutId}`); + AppLogger.LogSilly("Button/Trade/AcceptTrade", `Parameters: user1UserId=${user1UserId}, user2UserId=${user2UserId}, user1CardNumber=${user1CardNumber}, user2CardNumber=${user2CardNumber}, expiry=${expiry}, timeoutId=${timeoutId} user1Quantity=${user1Quantity} user2Quantity=${user2Quantity}`); const expiryDate = new Date(expiry); @@ -67,13 +69,13 @@ export default class Trade extends ButtonEvent { return; } - if (user1UserInventory1.Quantity < 1 || user2UserInventory1.Quantity < 1) { + if (user1UserInventory1.Quantity < user1Quantity || user2UserInventory1.Quantity < user2Quantity) { await interaction.reply("One or more of the items you are trying to trade does not exist."); return; } - user1UserInventory1.RemoveQuantity(1); - user2UserInventory1.RemoveQuantity(1); + user1UserInventory1.RemoveQuantity(user1Quantity); + user2UserInventory1.RemoveQuantity(user2Quantity); await user1UserInventory1.Save(Inventory, user1UserInventory1); await user2UserInventory1.Save(Inventory, user2UserInventory1); @@ -82,15 +84,15 @@ export default class Trade extends ButtonEvent { let user2UserInventory2 = await Inventory.FetchOneByCardNumberAndUserId(user2UserId, user1CardNumber); if (!user1UserInventory2) { - user1UserInventory2 = new Inventory(user1UserId, user2CardNumber, 1); + user1UserInventory2 = new Inventory(user1UserId, user2CardNumber, user2Quantity); } else { - user1UserInventory2.AddQuantity(1); + user1UserInventory2.AddQuantity(user2Quantity); } if (!user2UserInventory2) { - user2UserInventory2 = new Inventory(user2UserId, user1CardNumber, 1); + user2UserInventory2 = new Inventory(user2UserId, user1CardNumber, user1Quantity); } else { - user2UserInventory2.AddQuantity(1); + user2UserInventory2.AddQuantity(user1Quantity); } await user1UserInventory2.Save(Inventory, user1UserInventory2); @@ -106,12 +108,12 @@ export default class Trade extends ButtonEvent { .addFields([ { name: `${user1User.username} Receives`, - value: `${user2Item.id}: ${user2Item.name}`, + value: `${user2Item.id}: ${user2Item.name} x${user2Quantity}`, inline: true, }, { name: `${user2User.username} Receives`, - value: `${user1Item.id}: ${user1Item.name}`, + value: `${user1Item.id}: ${user1Item.name} x${user1Quantity}`, inline: true, }, { @@ -144,6 +146,8 @@ export default class Trade extends ButtonEvent { const user2CardNumber = interaction.customId.split(" ")[5]; // No need to get expiry date const timeoutId = interaction.customId.split(" ")[7]; + const user1Quantity = Number(interaction.customId.split(" ")[8]) || 1; + const user2Quantity = Number(interaction.customId.split(" ")[9]) || 1; AppLogger.LogSilly("Button/Trade/DeclineTrade", `Parameters: user1UserId=${user1UserId}, user2UserId=${user2UserId}, user1CardNumber=${user1CardNumber}, user2CardNumber=${user2CardNumber}, timeoutId=${timeoutId}`); @@ -178,12 +182,12 @@ export default class Trade extends ButtonEvent { .addFields([ { name: `${user1User.username} Receives`, - value: `${user2Item.id}: ${user2Item.name}`, + value: `${user2Item.id}: ${user2Item.name} x${user2Quantity}`, inline: true, }, { name: `${user2User.username} Receives`, - value: `${user1Item.id}: ${user1Item.name}`, + value: `${user1Item.id}: ${user1Item.name} x${user1Quantity}`, inline: true, }, { diff --git a/src/buttonEvents/View.ts b/src/buttonEvents/View.ts new file mode 100644 index 0000000..007a911 --- /dev/null +++ b/src/buttonEvents/View.ts @@ -0,0 +1,25 @@ +import {ButtonInteraction} from "discord.js"; +import {ButtonEvent} from "../type/buttonEvent.js"; +import CardSearchHelper from "../helpers/CardSearchHelper.js"; + +export default class View extends ButtonEvent { + public override async execute(interaction: ButtonInteraction) { + const page = interaction.customId.split(" ")[1]; + const results = interaction.customId.split(" ").splice(2); + + await interaction.deferUpdate(); + + const searchResult = await CardSearchHelper.GenerateSearchPageFromQuery(results, interaction.user.id, Number(page)); + + if (!searchResult) { + await interaction.followUp("No results found"); + return; + } + + await interaction.editReply({ + embeds: [ searchResult.embed ], + components: [ searchResult.row ], + files: searchResult.attachments, + }); + } +} diff --git a/src/client/client.ts b/src/client/client.ts index 117bdb9..57551fb 100644 --- a/src/client/client.ts +++ b/src/client/client.ts @@ -17,18 +17,20 @@ import AppLogger from "./appLogger"; import TimerHelper from "../helpers/TimerHelper"; import GiveCurrency from "../timers/GiveCurrency"; import PurgeClaims from "../timers/PurgeClaims"; +import StringDropdownEventItem from "../contracts/StringDropdownEventItem"; +import {StringDropdownEvent} from "../type/stringDropdownEvent"; export class CoreClient extends Client { private static _commandItems: ICommandItem[]; private static _eventExecutors: EventExecutors; private static _buttonEvents: IButtonEventItem[]; + private static _stringDropdowns: StringDropdownEventItem[]; private _events: Events; private _util: Util; private _webhooks: Webhooks; private _timerHelper: TimerHelper; - public static ClaimId: string; public static Environment: Environment; public static AllowDrops: boolean; public static Cards: SeriesMetadata[]; @@ -45,6 +47,10 @@ export class CoreClient extends Client { return this._buttonEvents; } + public static get stringDropdowns(): StringDropdownEventItem[] { + return this._stringDropdowns; + } + constructor(intents: number[]) { super({ intents: intents }); dotenv.config(); @@ -59,6 +65,7 @@ export class CoreClient extends Client { CoreClient._commandItems = []; CoreClient._buttonEvents = []; + CoreClient._stringDropdowns = []; this._events = new Events(); this._util = new Util(); @@ -408,4 +415,19 @@ export class CoreClient extends Client { AppLogger.LogVerbose("Client", `Registered Button Event: ${buttonId}`); } } + + public static RegisterStringDropdownEvent(dropdownId: string, event: StringDropdownEvent, environment: Environment = Environment.All) { + const item: StringDropdownEventItem = { + DropdownId: dropdownId, + Event: event, + Environment: environment, + }; + + if ((environment & CoreClient.Environment) == CoreClient.Environment) { + CoreClient._stringDropdowns.push(item); + + AppLogger.LogVerbose("Client", `Registered String Dropdown Event: ${dropdownId}`); + } + } } + diff --git a/src/client/events.ts b/src/client/events.ts index f02fb9c..5f61da5 100644 --- a/src/client/events.ts +++ b/src/client/events.ts @@ -3,6 +3,7 @@ import ChatInputCommand from "./interactionCreate/ChatInputCommand"; import Button from "./interactionCreate/Button"; import AppLogger from "./appLogger"; import NewUserDiscovery from "./interactionCreate/middleware/NewUserDiscovery"; +import StringDropdown from "./interactionCreate/StringDropdown"; export class Events { public async onInteractionCreate(interaction: Interaction) { @@ -19,6 +20,11 @@ export class Events { AppLogger.LogVerbose("Client", `Button: ${interaction.customId}`); Button.onButtonClicked(interaction); } + + if (interaction.isStringSelectMenu()) { + AppLogger.LogVerbose("Client", `StringDropdown: ${interaction.customId}`); + StringDropdown.onStringDropdownSelected(interaction); + } } // Emit when bot is logged in and ready to use diff --git a/src/client/interactionCreate/StringDropdown.ts b/src/client/interactionCreate/StringDropdown.ts new file mode 100644 index 0000000..608b81b --- /dev/null +++ b/src/client/interactionCreate/StringDropdown.ts @@ -0,0 +1,29 @@ +import {StringSelectMenuInteraction} from "discord.js"; +import {CoreClient} from "../client"; +import AppLogger from "../appLogger"; + +export default class StringDropdown { + public static async onStringDropdownSelected(interaction: StringSelectMenuInteraction) { + if (!interaction.isStringSelectMenu()) return; + + const item = CoreClient.stringDropdowns.find(x => x.DropdownId == interaction.customId.split(" ")[0]); + + if (!item) { + AppLogger.LogVerbose("StringDropdown", `Event not found: ${interaction.customId}`); + + await interaction.reply("Event not found"); + return; + } + + try { + AppLogger.LogDebug("StringDropdown", `Executing ${interaction.customId}`); + + item.Event.execute(interaction); + } catch (e) { + AppLogger.LogError("StringDropdown", `Error occurred while executing event: ${interaction.customId}`); + AppLogger.LogError("StringDropdown", e as string); + + await interaction.reply("An error occurred while executing the event"); + } + } +} diff --git a/src/commands/drop.ts b/src/commands/drop.ts index 66558e3..ac8008c 100644 --- a/src/commands/drop.ts +++ b/src/commands/drop.ts @@ -5,11 +5,13 @@ import { CoreClient } from "../client/client"; import { v4 } from "uuid"; import Inventory from "../database/entities/app/Inventory"; import Config from "../database/entities/app/Config"; -import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata"; import path from "path"; import AppLogger from "../client/appLogger"; import User from "../database/entities/app/User"; import CardConstants from "../constants/CardConstants"; +import ErrorMessages from "../constants/ErrorMessages"; +import GetCardsHelper from "../helpers/DropHelpers/GetCardsHelper"; +import DropEmbedHelper from "../helpers/DropHelpers/DropEmbedHelper"; export default class Drop extends Command { constructor() { @@ -22,14 +24,13 @@ export default class Drop extends Command { public override async execute(interaction: CommandInteraction) { if (!CoreClient.AllowDrops) { - await interaction.reply("Bot is currently syncing, please wait until its done."); + await interaction.reply(ErrorMessages.BotSyncing); return; } if (await Config.GetValue("safemode") == "true") { - AppLogger.LogWarn("Commands/Drop", "Safe Mode is active, refusing to send next drop."); - - await interaction.reply("Safe Mode has been activated, please resync to continue."); + AppLogger.LogWarn("Commands/Drop", ErrorMessages.SafeMode); + await interaction.reply(ErrorMessages.SafeMode); return; } @@ -42,17 +43,18 @@ export default class Drop extends Command { AppLogger.LogInfo("Commands/Drop", `New user (${interaction.user.id}) saved to the database`); } - if (user.Currency < CardConstants.ClaimCost) { - await interaction.reply(`Not enough currency! You need ${CardConstants.ClaimCost} currency, you have ${user.Currency}!`); + if (!user.RemoveCurrency(CardConstants.ClaimCost)) { + await interaction.reply(ErrorMessages.NotEnoughCurrency(CardConstants.ClaimCost, user.Currency)); return; } - const randomCard = CardDropHelperMetadata.GetRandomCard(); + await user.Save(User, user); + + const randomCard = await GetCardsHelper.FetchCard(interaction.user.id); if (!randomCard) { - AppLogger.LogWarn("Commands/Drop", "Unable to fetch card, please try again. (randomCard is null)"); - - await interaction.reply("Unable to fetch card, please try again."); + AppLogger.LogWarn("Commands/Drop", ErrorMessages.UnableToFetchCard); + await interaction.reply(ErrorMessages.UnableToFetchCard); return; } @@ -74,11 +76,11 @@ export default class Drop extends Command { const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, randomCard.card.id); const quantityClaimed = inventory ? inventory.Quantity : 0; - const embed = CardDropHelperMetadata.GenerateDropEmbed(randomCard, quantityClaimed, imageFileName, undefined, user.Currency); + const embed = DropEmbedHelper.GenerateDropEmbed(randomCard, quantityClaimed, imageFileName, undefined, user.Currency); const claimId = v4(); - const row = CardDropHelperMetadata.GenerateDropButtons(randomCard, claimId, interaction.user.id); + const row = DropEmbedHelper.GenerateDropButtons(randomCard, claimId, interaction.user.id); await interaction.editReply({ embeds: [ embed ], @@ -86,8 +88,6 @@ export default class Drop extends Command { components: [ row ], }); - CoreClient.ClaimId = claimId; - } catch (e) { AppLogger.LogError("Commands/Drop", `Error sending next drop for card ${randomCard.card.id}: ${e}`); diff --git a/src/commands/effects.ts b/src/commands/effects.ts new file mode 100644 index 0000000..cd6d1d4 --- /dev/null +++ b/src/commands/effects.ts @@ -0,0 +1,64 @@ +import { CommandInteraction, SlashCommandBuilder } from "discord.js"; +import { Command } from "../type/command"; +import { EffectChoices } from "../constants/EffectDetails"; +import AppLogger from "../client/appLogger"; +import List from "./effects/List"; +import Use from "./effects/Use"; +import Buy from "./effects/Buy"; + +export default class Effects extends Command { + constructor() { + super(); + + this.CommandBuilder = new SlashCommandBuilder() + .setName("effects") + .setDescription("Effects") + .addSubcommand(x => x + .setName("list") + .setDescription("List all effects I have") + .addNumberOption(x => x + .setName("page") + .setDescription("The page number") + .setMinValue(1))) + .addSubcommand(x => x + .setName("use") + .setDescription("Use an effect in your inventory") + .addStringOption(y => y + .setName("id") + .setDescription("The effect id to use") + .setRequired(true) + .setChoices(EffectChoices))) + .addSubcommand(x => x + .setName("buy") + .setDescription("Buy more effects") + .addStringOption(y => y + .setName("id") + .setDescription("The effect id to buy") + .setRequired(true) + .setChoices(EffectChoices)) + .addNumberOption(y => y + .setName("quantity") + .setDescription("The amount to buy") + .setMinValue(1))); + } + + public override async execute(interaction: CommandInteraction) { + if (!interaction.isChatInputCommand()) return; + + const subcommand = interaction.options.getSubcommand(); + + switch (subcommand) { + case "list": + await List(interaction); + break; + case "use": + await Use(interaction); + break; + case "buy": + await Buy(interaction); + break; + default: + AppLogger.LogError("Commands/Effects", `Invalid subcommand: ${subcommand}`); + } + } +} diff --git a/src/commands/effects/Buy.ts b/src/commands/effects/Buy.ts new file mode 100644 index 0000000..3ebf587 --- /dev/null +++ b/src/commands/effects/Buy.ts @@ -0,0 +1,22 @@ +import { CommandInteraction } from "discord.js"; +import EffectHelper from "../../helpers/EffectHelper"; + +export default async function Buy(interaction: CommandInteraction) { + const id = interaction.options.get("id", true).value!; + const quantity = interaction.options.get("quantity")?.value ?? 1; + + const idValue = id.toString(); + const quantityValue = Number(quantity); + + const result = await EffectHelper.GenerateEffectBuyEmbed(interaction.user.id, idValue, quantityValue, false); + + if (typeof result == "string") { + await interaction.reply(result); + return; + } + + await interaction.reply({ + embeds: [ result.embed ], + components: [ result.row ], + }); +} \ No newline at end of file diff --git a/src/commands/effects/List.ts b/src/commands/effects/List.ts new file mode 100644 index 0000000..14e6085 --- /dev/null +++ b/src/commands/effects/List.ts @@ -0,0 +1,15 @@ +import { CommandInteraction } from "discord.js"; +import EffectHelper from "../../helpers/EffectHelper"; + +export default async function List(interaction: CommandInteraction) { + const pageOption = interaction.options.get("page"); + + const page = !isNaN(Number(pageOption?.value)) ? Number(pageOption?.value) : 1; + + const result = await EffectHelper.GenerateEffectListEmbed(interaction.user.id, page); + + await interaction.reply({ + embeds: [ result.embed ], + components: [ result.row ], + }); +} \ No newline at end of file diff --git a/src/commands/effects/Use.ts b/src/commands/effects/Use.ts new file mode 100644 index 0000000..9f72ae0 --- /dev/null +++ b/src/commands/effects/Use.ts @@ -0,0 +1,62 @@ +import { ActionRowBuilder, ButtonBuilder, ButtonStyle, CommandInteraction, EmbedBuilder } from "discord.js"; +import { EffectDetails } from "../../constants/EffectDetails"; +import AppLogger from "../../client/appLogger"; +import EffectHelper from "../../helpers/EffectHelper"; +import TimeLengthInput from "../../helpers/TimeLengthInput"; +import EmbedColours from "../../constants/EmbedColours"; + +export default async function Use(interaction: CommandInteraction) { + const id = interaction.options.get("id", true).value!.toString(); + + const effectDetail = EffectDetails.get(id); + + if (!effectDetail) { + AppLogger.LogWarn("Commands/Effects", `Unable to find effect details for ${id}`); + + await interaction.reply("Unable to find effect!"); + return; + } + + const canUseEffect = await EffectHelper.CanUseEffect(interaction.user.id, id); + + if (!canUseEffect) { + await interaction.reply("Unable to use effect! Please make sure you have it in your inventory and is not on cooldown"); + return; + } + + const timeLengthInput = TimeLengthInput.ConvertFromMilliseconds(effectDetail.duration); + + const embed = new EmbedBuilder() + .setTitle("Effect Confirmation") + .setDescription("Would you like to use this effect?") + .setColor(EmbedColours.Ok) + .addFields([ + { + name: "Effect", + value: effectDetail.friendlyName, + inline: true, + }, + { + name: "Length", + value: timeLengthInput.GetLengthShort(), + inline: true, + }, + ]); + + const row = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setLabel("Confirm") + .setCustomId(`effects use confirm ${effectDetail.id}`) + .setStyle(ButtonStyle.Primary), + new ButtonBuilder() + .setLabel("Cancel") + .setCustomId(`effects use cancel ${effectDetail.id}`) + .setStyle(ButtonStyle.Danger), + ]); + + await interaction.reply({ + embeds: [ embed ], + components: [ row ], + }); +} \ No newline at end of file diff --git a/src/commands/give.ts b/src/commands/give.ts index 3ffbe8f..35dfa04 100644 --- a/src/commands/give.ts +++ b/src/commands/give.ts @@ -2,10 +2,10 @@ import { CacheType, CommandInteraction, PermissionsBitField, SlashCommandBuilder import { Command } from "../type/command"; import { CoreClient } from "../client/client"; import Config from "../database/entities/app/Config"; -import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata"; import Inventory from "../database/entities/app/Inventory"; import AppLogger from "../client/appLogger"; import User from "../database/entities/app/User"; +import GetCardsHelper from "../helpers/DropHelpers/GetCardsHelper"; export default class Give extends Command { constructor() { @@ -81,7 +81,7 @@ export default class Give extends Command { AppLogger.LogSilly("Commands/Give/GiveCard", `Parameters: cardNumber=${cardNumber.value}, user=${user.id}`); - const card = CardDropHelperMetadata.GetCardByCardNumber(cardNumber.value!.toString()); + const card = GetCardsHelper.GetCardByCardNumber(cardNumber.value!.toString()); if (!card) { await interaction.reply("Unable to fetch card, please try again."); diff --git a/src/commands/id.ts b/src/commands/id.ts new file mode 100644 index 0000000..0f11aaa --- /dev/null +++ b/src/commands/id.ts @@ -0,0 +1,80 @@ +import { AttachmentBuilder, CommandInteraction, DiscordAPIError, SlashCommandBuilder } from "discord.js"; +import { Command } from "../type/command"; +import { CoreClient } from "../client/client"; +import { readFileSync } from "fs"; +import path from "path"; +import Inventory from "../database/entities/app/Inventory"; +import AppLogger from "../client/appLogger"; +import DropEmbedHelper from "../helpers/DropHelpers/DropEmbedHelper"; + +export default class Id extends Command { + constructor() { + super(); + + this.CommandBuilder = new SlashCommandBuilder() + .setName("id") + .setDescription("View a specific command by its id") + .addStringOption(x => + x + .setName("cardnumber") + .setDescription("The card number to view") + .setRequired(true)); + } + + public override async execute(interaction: CommandInteraction) { + const cardNumber = interaction.options.get("cardnumber"); + + AppLogger.LogSilly("Commands/View", `Parameters: cardNumber=${cardNumber?.value}`); + + if (!cardNumber || !cardNumber.value) { + await interaction.reply("Card number is required."); + return; + } + + const card = CoreClient.Cards + .flatMap(x => x.cards) + .find(x => x.id == cardNumber.value); + + if (!card) { + await interaction.reply("Card not found."); + return; + } + + const series = CoreClient.Cards + .find(x => x.cards.includes(card))!; + + const files = []; + let imageFileName = ""; + + if (!(card.path.startsWith("http://") || card.path.startsWith("https://"))) { + const image = readFileSync(path.join(process.env.DATA_DIR!, "cards", card.path)); + imageFileName = card.path.split("/").pop()!; + + const attachment = new AttachmentBuilder(image, { name: imageFileName }); + + files.push(attachment); + } + + await interaction.deferReply(); + + const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, card.id); + const quantityClaimed = inventory ? inventory.Quantity : 0; + + const embed = DropEmbedHelper.GenerateDropEmbed({ card, series }, quantityClaimed, imageFileName); + + try { + await interaction.editReply({ + embeds: [ embed ], + files: files, + }); + } catch (e) { + AppLogger.LogError("Commands/View", `Error sending view for card ${card.id}: ${e}`); + + if (e instanceof DiscordAPIError) { + await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. Code: ${e.code}.`); + } else { + await interaction.editReply("Unable to send next drop. Please try again, and report this if it keeps happening. Code: UNKNOWN."); + } + } + } +} diff --git a/src/commands/inventory.ts b/src/commands/inventory.ts index 8d2ef2c..deb4735 100644 --- a/src/commands/inventory.ts +++ b/src/commands/inventory.ts @@ -47,7 +47,7 @@ export default class Inventory extends Command { await interaction.followUp({ files: [ embed.image ], embeds: [ embed.embed ], - components: [ embed.row ], + components: [ embed.row1, embed.row2 ], }); } catch (e) { AppLogger.LogError("Commands/Inventory", e as string); diff --git a/src/commands/multidrop.ts b/src/commands/multidrop.ts new file mode 100644 index 0000000..aa42686 --- /dev/null +++ b/src/commands/multidrop.ts @@ -0,0 +1,88 @@ +import { AttachmentBuilder, CommandInteraction, SlashCommandBuilder } from "discord.js"; +import { Command } from "../type/command"; +import { CoreClient } from "../client/client"; +import ErrorMessages from "../constants/ErrorMessages"; +import Config from "../database/entities/app/Config"; +import AppLogger from "../client/appLogger"; +import User from "../database/entities/app/User"; +import CardConstants from "../constants/CardConstants"; +import { readFileSync } from "fs"; +import path from "path"; +import Inventory from "../database/entities/app/Inventory"; +import GetCardsHelper from "../helpers/DropHelpers/GetCardsHelper"; +import MultidropEmbedHelper from "../helpers/DropHelpers/MultidropEmbedHelper"; + +export default class Multidrop extends Command { + constructor() { + super(); + + this.CommandBuilder = new SlashCommandBuilder() + .setName("multidrop") + .setDescription("Drop 11 cards for the price of 10!"); + } + + public override async execute(interaction: CommandInteraction) { + if (!CoreClient.AllowDrops) { + await interaction.reply(ErrorMessages.BotSyncing); + return; + } + + if (await Config.GetValue("safemode") == "true") { + AppLogger.LogWarn("Commands/Multidrop", ErrorMessages.SafeMode); + await interaction.reply(ErrorMessages.SafeMode); + return; + } + + let user = await User.FetchOneById(User, interaction.user.id); + + if (!user) { + user = new User(interaction.user.id, CardConstants.StartingCurrency); + await user.Save(User, user); + + AppLogger.LogInfo("Commands/Multidrop", `New user (${interaction.user.id}) saved to the database`); + } + + if (user.Currency < CardConstants.MultidropCost) { + await interaction.reply(ErrorMessages.NotEnoughCurrency(CardConstants.MultidropCost, user.Currency)); + return; + } + + user.RemoveCurrency(CardConstants.MultidropCost); + await user.Save(User, user); + + const randomCard = GetCardsHelper.GetRandomCard(); + const cardsRemaining = CardConstants.MultidropQuantity - 1; + + if (!randomCard) { + AppLogger.LogWarn("Commands/Multidrop", ErrorMessages.UnableToFetchCard); + await interaction.reply(ErrorMessages.UnableToFetchCard); + return; + } + + await interaction.deferReply(); + + try { + const image = readFileSync(path.join(process.env.DATA_DIR!, "cards", randomCard.card.path)); + const imageFileName = randomCard.card.path.split("/").pop()!; + + const attachment = new AttachmentBuilder(image, { name: imageFileName }); + + const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, randomCard.card.id); + const quantityClaimed = inventory ? inventory.Quantity : 0; + + const embed = MultidropEmbedHelper.GenerateMultidropEmbed(randomCard, quantityClaimed, imageFileName, cardsRemaining, undefined, user.Currency); + + const row = MultidropEmbedHelper.GenerateMultidropButtons(randomCard, cardsRemaining, interaction.user.id); + + await interaction.editReply({ + embeds: [ embed ], + files: [ attachment ], + components: [ row ], + }); + } catch (e) { + AppLogger.LogError("Commands/Multidrop", `Error sending next drop for card ${randomCard.card.id}: ${e}`); + + await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. (${randomCard.card.id})`); + } + } +} \ No newline at end of file diff --git a/src/commands/sacrifice.ts b/src/commands/sacrifice.ts index 4d1c51a..a44a69e 100644 --- a/src/commands/sacrifice.ts +++ b/src/commands/sacrifice.ts @@ -2,8 +2,8 @@ import { ActionRowBuilder, ButtonBuilder, ButtonStyle, CacheType, CommandInterac import { Command } from "../type/command"; import Inventory from "../database/entities/app/Inventory"; import { CardRarityToString, GetSacrificeAmount } from "../constants/CardRarity"; -import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata"; import EmbedColours from "../constants/EmbedColours"; +import GetCardsHelper from "../helpers/DropHelpers/GetCardsHelper"; export default class Sacrifice extends Command { constructor() { @@ -16,11 +16,18 @@ export default class Sacrifice extends Command { x .setName("cardnumber") .setDescription("The card to sacrifice from your inventory") - .setRequired(true)); + .setRequired(true)) + .addNumberOption(x => + x + .setName("quantity") + .setDescription("The amount to sacrifice (default 1)")); } public override async execute(interaction: CommandInteraction): Promise { const cardnumber = interaction.options.get("cardnumber", true); + const quantityInput = interaction.options.get("quantity")?.value ?? 1; + + const quantity = Number(quantityInput) || 1; const cardInInventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, cardnumber.value! as string); @@ -29,14 +36,19 @@ export default class Sacrifice extends Command { return; } - const cardData = CardDropHelperMetadata.GetCardByCardNumber(cardnumber.value! as string); + if (cardInInventory.Quantity < quantity) { + await interaction.reply(`You can only sacrifice what you own! You have ${cardInInventory.Quantity} of this card`); + return; + } + + const cardData = GetCardsHelper.GetCardByCardNumber(cardnumber.value! as string); if (!cardData) { await interaction.reply("Unable to find card in the database."); return; } - const cardValue = GetSacrificeAmount(cardData.card.type); + const cardValue = GetSacrificeAmount(cardData.card.type) * quantity; const cardRarityString = CardRarityToString(cardData.card.type); const description = [ @@ -44,6 +56,7 @@ export default class Sacrifice extends Command { `Series: ${cardData.series.name}`, `Rarity: ${cardRarityString}`, `Quantity Owned: ${cardInInventory.Quantity}`, + `Quantity To Sacrifice: ${quantity}`, `Sacrifice Amount: ${cardValue}`, ]; @@ -56,11 +69,11 @@ export default class Sacrifice extends Command { const row = new ActionRowBuilder() .addComponents([ new ButtonBuilder() - .setCustomId(`sacrifice confirm ${interaction.user.id} ${cardnumber.value!}`) + .setCustomId(`sacrifice confirm ${interaction.user.id} ${cardnumber.value!} ${quantity}`) .setLabel("Confirm") .setStyle(ButtonStyle.Success), new ButtonBuilder() - .setCustomId(`sacrifice cancel ${interaction.user.id} ${cardnumber.value!}`) + .setCustomId(`sacrifice cancel ${interaction.user.id} ${cardnumber.value!} ${quantity}`) .setLabel("Cancel") .setStyle(ButtonStyle.Secondary), ]); diff --git a/src/commands/stage/dropnumber.ts b/src/commands/stage/dropnumber.ts index caeccd0..c61ed43 100644 --- a/src/commands/stage/dropnumber.ts +++ b/src/commands/stage/dropnumber.ts @@ -5,7 +5,7 @@ import Inventory from "../../database/entities/app/Inventory"; import { v4 } from "uuid"; import { CoreClient } from "../../client/client"; import path from "path"; -import CardDropHelperMetadata from "../../helpers/CardDropHelperMetadata"; +import DropEmbedHelper from "../../helpers/DropHelpers/DropEmbedHelper"; import AppLogger from "../../client/appLogger"; export default class Dropnumber extends Command { @@ -41,44 +41,40 @@ export default class Dropnumber extends Command { return; } + const claimId = v4(); + await interaction.deferReply(); + + try { + const files = []; + let imageFileName = ""; + + if (!(card.path.startsWith("http://") || card.path.startsWith("https://"))) { + const image = readFileSync(path.join(process.env.DATA_DIR!, "cards", card.path)); + imageFileName = card.path.split("/").pop()!; + + const attachment = new AttachmentBuilder(image, { name: imageFileName }); + + files.push(attachment); + } + const series = CoreClient.Cards .find(x => x.cards.includes(card))!; - const claimId = v4(); + const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, card.id); + const quantityClaimed = inventory ? inventory.Quantity : 0; + const embed = DropEmbedHelper.GenerateDropEmbed({ card, series }, quantityClaimed, imageFileName); - await interaction.deferReply(); + const row = DropEmbedHelper.GenerateDropButtons({ card, series }, claimId, interaction.user.id); - try { - const files = []; - let imageFileName = ""; - - if (!(card.path.startsWith("http://") || card.path.startsWith("https://"))) { - const image = readFileSync(path.join(process.env.DATA_DIR!, "cards", card.path)); - imageFileName = card.path.split("/").pop()!; - - const attachment = new AttachmentBuilder(image, { name: imageFileName }); - - files.push(attachment); - } - - const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, card.id); - const quantityClaimed = inventory ? inventory.Quantity : 0; - - const embed = CardDropHelperMetadata.GenerateDropEmbed({ card, series }, quantityClaimed, imageFileName); - - const row = CardDropHelperMetadata.GenerateDropButtons({ card, series }, claimId, interaction.user.id); - - await interaction.editReply({ - embeds: [ embed ], - files: files, - components: [ row ], - }); + await interaction.editReply({ + embeds: [ embed ], + files: files, + components: [ row ], + }); } catch (e) { AppLogger.CatchError("Dropnumber", e); await interaction.editReply("Unable to send next drop. Please try again, and report this if it keeps happening"); } - - CoreClient.ClaimId = claimId; } } \ No newline at end of file diff --git a/src/commands/stage/droprarity.ts b/src/commands/stage/droprarity.ts index cf2eded..f776930 100644 --- a/src/commands/stage/droprarity.ts +++ b/src/commands/stage/droprarity.ts @@ -4,9 +4,9 @@ import { CardRarity, CardRarityChoices, CardRarityParse } from "../../constants/ import { readFileSync } from "fs"; import Inventory from "../../database/entities/app/Inventory"; import { v4 } from "uuid"; -import { CoreClient } from "../../client/client"; -import CardDropHelperMetadata from "../../helpers/CardDropHelperMetadata"; import path from "path"; +import GetCardsHelper from "../../helpers/DropHelpers/GetCardsHelper"; +import DropEmbedHelper from "../../helpers/DropHelpers/DropEmbedHelper"; import AppLogger from "../../client/appLogger"; export default class Droprarity extends Command { @@ -41,7 +41,7 @@ export default class Droprarity extends Command { return; } - const card = CardDropHelperMetadata.GetRandomCardByRarity(rarityType); + const card = GetCardsHelper.GetRandomCardByRarity(rarityType); if (!card) { await interaction.reply("Card not found"); @@ -49,7 +49,6 @@ export default class Droprarity extends Command { } const claimId = v4(); - await interaction.deferReply(); try { @@ -68,9 +67,9 @@ export default class Droprarity extends Command { const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, card.card.id); const quantityClaimed = inventory ? inventory.Quantity : 0; - const embed = CardDropHelperMetadata.GenerateDropEmbed(card, quantityClaimed, imageFileName); + const embed = DropEmbedHelper.GenerateDropEmbed(card, quantityClaimed, imageFileName); - const row = CardDropHelperMetadata.GenerateDropButtons(card, claimId, interaction.user.id); + const row = DropEmbedHelper.GenerateDropButtons(card, claimId, interaction.user.id); await interaction.editReply({ embeds: [ embed ], @@ -81,7 +80,5 @@ export default class Droprarity extends Command { AppLogger.CatchError("Droprarity", e); await interaction.editReply("Unable to send next drop. Please try again, and report this if it keeps happening"); } - - CoreClient.ClaimId = claimId; } } \ No newline at end of file diff --git a/src/commands/trade.ts b/src/commands/trade.ts index 569e88f..fcd312a 100644 --- a/src/commands/trade.ts +++ b/src/commands/trade.ts @@ -26,13 +26,26 @@ export default class Trade extends Command { x .setName("receive") .setDescription("Item to receive") - .setRequired(true)); + .setRequired(true)) + .addNumberOption(x => + x + .setName("givequantity") + .setDescription("Amount to give")) + .addNumberOption(x => + x + .setName("receivequantity") + .setDescription("Amount to receive")); } public override async execute(interaction: CommandInteraction) { const user = interaction.options.get("user", true).user!; const give = interaction.options.get("give", true); const receive = interaction.options.get("receive", true); + const givequantityInput = interaction.options.get("givequantity")?.value ?? 1; + const receivequantityInput = interaction.options.get("receivequantity")?.value ?? 1; + + const givequantity = Number(givequantityInput) || 1; + const receivequantity = Number(receivequantityInput) || 1; AppLogger.LogSilly("Commands/Trade", `Parameters: user=${user.id}, give=${give.value}, receive=${receive.value}`); @@ -44,12 +57,12 @@ export default class Trade extends Command { const user1ItemEntity = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, give.value!.toString()); const user2ItemEntity = await Inventory.FetchOneByCardNumberAndUserId(user.id, receive.value!.toString()); - if (!user1ItemEntity) { + if (!user1ItemEntity || user1ItemEntity.Quantity < givequantity) { await interaction.reply("You do not have the item you are trying to trade."); return; } - if (!user2ItemEntity) { + if (!user2ItemEntity || user2ItemEntity.Quantity < receivequantity) { await interaction.reply("The user you are trying to trade with does not have the item you are trying to trade for."); return; } @@ -78,12 +91,12 @@ export default class Trade extends Command { .addFields([ { name: `${interaction.user.username} Receives`, - value: `${user2Item.id}: ${user2Item.name}`, + value: `${user2Item.id}: ${user2Item.name} x${receivequantity}`, inline: true, }, { name: `${user.username} Receives`, - value: `${user1Item.id}: ${user1Item.name}`, + value: `${user1Item.id}: ${user1Item.name} x${givequantity}`, inline: true, }, { @@ -92,16 +105,16 @@ export default class Trade extends Command { } ]); - const timeoutId = setTimeout(async () => this.autoDecline(interaction, interaction.user.username, user.username, user1Item.id, user2Item.id, user1Item.name, user2Item.name), 1000 * 60 * 15); // 15 minutes + const timeoutId = setTimeout(async () => this.autoDecline(interaction, interaction.user.username, user.username, user1Item.id, user2Item.id, user1Item.name, user2Item.name, givequantity, receivequantity), 1000 * 60 * 15); // 15 minutes const row = new ActionRowBuilder() .addComponents([ new ButtonBuilder() - .setCustomId(`trade accept ${interaction.user.id} ${user.id} ${user1Item.id} ${user2Item.id} ${expiry} ${timeoutId}`) + .setCustomId(`trade accept ${interaction.user.id} ${user.id} ${user1Item.id} ${user2Item.id} ${expiry} ${timeoutId} ${givequantity} ${receivequantity}`) .setLabel("Accept") .setStyle(ButtonStyle.Success), new ButtonBuilder() - .setCustomId(`trade decline ${interaction.user.id} ${user.id} ${user1Item.id} ${user2Item.id} ${expiry} ${timeoutId}`) + .setCustomId(`trade decline ${interaction.user.id} ${user.id} ${user1Item.id} ${user2Item.id} ${expiry} ${timeoutId} ${givequantity} ${receivequantity}`) .setLabel("Decline") .setStyle(ButtonStyle.Danger), ]); @@ -109,7 +122,7 @@ export default class Trade extends Command { await interaction.reply({ content: `${user}`, embeds: [ tradeEmbed ], components: [ row ] }); } - private async autoDecline(interaction: CommandInteraction, user1Username: string, user2Username: string, user1CardNumber: string, user2CardNumber: string, user1CardName: string, user2CardName: string) { + private async autoDecline(interaction: CommandInteraction, user1Username: string, user2Username: string, user1CardNumber: string, user2CardNumber: string, user1CardName: string, user2CardName: string, user1Quantity: number, user2Quantity: number) { AppLogger.LogSilly("Commands/Trade/AutoDecline", `Auto declining trade between ${user1Username} and ${user2Username}`); const tradeEmbed = new EmbedBuilder() @@ -120,12 +133,12 @@ export default class Trade extends Command { .addFields([ { name: `${user1Username} Receives`, - value: `${user2CardNumber}: ${user2CardName}`, + value: `${user2CardNumber}: ${user2CardName} x${user2Quantity}`, inline: true, }, { name: `${user2Username} Receives`, - value: `${user1CardNumber}: ${user1CardName}`, + value: `${user1CardNumber}: ${user1CardName} x${user1Quantity}`, inline: true, }, { diff --git a/src/commands/view.ts b/src/commands/view.ts index 0e29db5..9a1d447 100644 --- a/src/commands/view.ts +++ b/src/commands/view.ts @@ -1,11 +1,7 @@ -import { AttachmentBuilder, CommandInteraction, DiscordAPIError, SlashCommandBuilder } from "discord.js"; +import { CommandInteraction, SlashCommandBuilder } from "discord.js"; import { Command } from "../type/command"; -import { CoreClient } from "../client/client"; -import { readFileSync } from "fs"; -import path from "path"; -import Inventory from "../database/entities/app/Inventory"; -import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata"; import AppLogger from "../client/appLogger"; +import CardSearchHelper from "../helpers/CardSearchHelper"; export default class View extends Command { constructor() { @@ -13,68 +9,32 @@ export default class View extends Command { this.CommandBuilder = new SlashCommandBuilder() .setName("view") - .setDescription("View a specific command") + .setDescription("Search for a card by its name") .addStringOption(x => x - .setName("cardnumber") - .setDescription("The card number to view") + .setName("name") + .setDescription("The card name to search for") .setRequired(true)); } public override async execute(interaction: CommandInteraction) { - const cardNumber = interaction.options.get("cardnumber"); + const name = interaction.options.get("name", true); - AppLogger.LogSilly("Commands/View", `Parameters: cardNumber=${cardNumber?.value}`); - - if (!cardNumber || !cardNumber.value) { - await interaction.reply("Card number is required."); - return; - } - - const card = CoreClient.Cards - .flatMap(x => x.cards) - .find(x => x.id == cardNumber.value); - - if (!card) { - await interaction.reply("Card not found."); - return; - } - - const series = CoreClient.Cards - .find(x => x.cards.includes(card))!; - - const files = []; - let imageFileName = ""; - - if (!(card.path.startsWith("http://") || card.path.startsWith("https://"))) { - const image = readFileSync(path.join(process.env.DATA_DIR!, "cards", card.path)); - imageFileName = card.path.split("/").pop()!; - - const attachment = new AttachmentBuilder(image, { name: imageFileName }); - - files.push(attachment); - } + AppLogger.LogSilly("Commands/View", `Parameters: name=${name.value}`); await interaction.deferReply(); - const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, card.id); - const quantityClaimed = inventory ? inventory.Quantity : 0; + const searchResult = await CardSearchHelper.GenerateSearchQuery(name.value!.toString(), interaction.user.id, 7); - const embed = CardDropHelperMetadata.GenerateDropEmbed({ card, series }, quantityClaimed, imageFileName); - - try { - await interaction.editReply({ - embeds: [ embed ], - files: files, - }); - } catch (e) { - AppLogger.LogError("Commands/View", `Error sending view for card ${card.id}: ${e}`); - - if (e instanceof DiscordAPIError) { - await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. Code: ${e.code}.`); - } else { - await interaction.editReply("Unable to send next drop. Please try again, and report this if it keeps happening. Code: UNKNOWN."); - } + if (!searchResult) { + await interaction.editReply("No results found"); + return; } + + await interaction.editReply({ + embeds: [ searchResult.embed ], + components: [ searchResult.row ], + files: searchResult.attachments, + }); } } \ No newline at end of file diff --git a/src/constants/CardConstants.ts b/src/constants/CardConstants.ts index 0a87e22..60a7f59 100644 --- a/src/constants/CardConstants.ts +++ b/src/constants/CardConstants.ts @@ -3,4 +3,11 @@ export default class CardConstants { public static readonly TimerGiveAmount = 10; public static readonly DailyCurrency = 100; public static readonly StartingCurrency = 300; + + // Multidrop + public static readonly MultidropCost = this.ClaimCost * 10; + public static readonly MultidropQuantity = 11; + + // Effects + public static readonly UnusedChanceUpChance = 0.5; } \ No newline at end of file diff --git a/src/constants/EffectDetails.ts b/src/constants/EffectDetails.ts new file mode 100644 index 0000000..9d1f2b6 --- /dev/null +++ b/src/constants/EffectDetails.ts @@ -0,0 +1,23 @@ +class EffectDetail { + public readonly id: string; + public readonly friendlyName: string; + public readonly duration: number; + public readonly cost: number; + public readonly cooldown: number; + + constructor(id: string, friendlyName: string, duration: number, cost: number, cooldown: number) { + this.id = id; + this.friendlyName = friendlyName; + this.duration = duration; + this.cost = cost; + this.cooldown = cooldown; + } +}; + +export const EffectDetails = new Map([ + [ "unclaimed", new EffectDetail("unclaimed", "Unclaimed Chance Up", 10 * 60 * 1000, 100, 3 * 60 * 60 * 1000) ], +]); + +export const EffectChoices = [ + { name: "Unclaimed Chance Up", value: "unclaimed" }, +]; diff --git a/src/constants/ErrorMessages.ts b/src/constants/ErrorMessages.ts new file mode 100644 index 0000000..c8749ec --- /dev/null +++ b/src/constants/ErrorMessages.ts @@ -0,0 +1,8 @@ +export default class ErrorMessages { + public static readonly BotSyncing = "Bot is currently syncing, please wait until its done."; + public static readonly SafeMode = "Safe Mode has been activated, please resync to continue."; + public static readonly UnableToFetchCard = "Unable to fetch card, please try again."; + public static readonly UnableToFetchUser = "Unable to fetch user, please try again."; + + public static readonly NotEnoughCurrency = (need: number, have: number) => `Not enough currency! You need ${need} currency, you have ${have}!`; +} \ No newline at end of file diff --git a/src/contracts/StringDropdownEventItem.ts b/src/contracts/StringDropdownEventItem.ts new file mode 100644 index 0000000..1a7b0aa --- /dev/null +++ b/src/contracts/StringDropdownEventItem.ts @@ -0,0 +1,10 @@ +import {Environment} from "../constants/Environment"; +import {StringDropdownEvent} from "../type/stringDropdownEvent"; + +interface StringDropdownEventItem { + DropdownId: string, + Event: StringDropdownEvent, + Environment: Environment, +} + +export default StringDropdownEventItem; diff --git a/src/database/entities/app/Inventory.ts b/src/database/entities/app/Inventory.ts index 469cbdc..c780dad 100644 --- a/src/database/entities/app/Inventory.ts +++ b/src/database/entities/app/Inventory.ts @@ -29,16 +29,16 @@ export default class Inventory extends AppBaseEntity { this.Quantity = quantity; } - public AddQuantity(amount: number) { - this.Quantity += amount; - } - public RemoveQuantity(amount: number) { if (this.Quantity < amount) return; this.Quantity -= amount; } + public AddQuantity(amount: number) { + this.Quantity += amount; + } + public AddClaim(claim: Claim) { this.Claims.push(claim); } diff --git a/src/database/entities/app/User.ts b/src/database/entities/app/User.ts index c3d8437..3a9018d 100644 --- a/src/database/entities/app/User.ts +++ b/src/database/entities/app/User.ts @@ -13,7 +13,7 @@ export default class User extends AppBaseEntity { @Column() Currency: number; - @Column() + @Column({ nullable: true }) LastUsedDaily?: Date; public AddCurrency(amount: number) { diff --git a/src/database/entities/app/UserEffect.ts b/src/database/entities/app/UserEffect.ts new file mode 100644 index 0000000..447b9c5 --- /dev/null +++ b/src/database/entities/app/UserEffect.ts @@ -0,0 +1,86 @@ +import {Column, Entity} from "typeorm"; +import AppBaseEntity from "../../../contracts/AppBaseEntity"; +import AppDataSource from "../../dataSources/appDataSource"; + +@Entity() +export default class UserEffect extends AppBaseEntity { + constructor(name: string, userId: string, unused: number, WhenExpires?: Date) { + super(); + + this.Name = name; + this.UserId = userId; + this.Unused = unused; + this.WhenExpires = WhenExpires; + } + + @Column() + Name: string; + + @Column() + UserId: string; + + @Column() + Unused: number; + + @Column({ nullable: true }) + WhenExpires?: Date; + + public AddUnused(amount: number) { + this.Unused += amount; + } + + public UseEffect(whenExpires: Date): boolean { + if (this.Unused == 0) { + return false; + } + + this.Unused -= 1; + this.WhenExpires = whenExpires; + + return true; + } + + public IsEffectActive(): boolean { + const now = new Date(); + + if (this.WhenExpires && now < this.WhenExpires) { + return true; + } + + return false; + } + + public static async FetchOneByUserIdAndName(userId: string, name: string): Promise { + const repository = AppDataSource.getRepository(UserEffect); + + const single = await repository.findOne({ where: { UserId: userId, Name: name } }); + + return single; + } + + public static async FetchAllByUserIdPaginated(userId: string, page: number = 0, itemsPerPage: number = 10): Promise<[UserEffect[], number]> { + const repository = AppDataSource.getRepository(UserEffect); + + const query = await repository.createQueryBuilder("effect") + .where("effect.UserId = :userId", { userId }) + .andWhere("effect.Unused > 0") + .orderBy("effect.Name", "ASC") + .skip(page * itemsPerPage) + .take(itemsPerPage) + .getManyAndCount(); + + return query; + } + + public static async FetchActiveEffectByUserId(userId: string): Promise { + const repository = AppDataSource.getRepository(UserEffect); + + const query = await repository.createQueryBuilder("effect") + .where("effect.UserId = :userId", { userId }) + .andWhere("effect.WhenExpires IS NOT NULL") + .andWhere("effect.WhenExpires > :now", { now: new Date() }) + .getOne(); + + return query; + } +} diff --git a/src/database/migrations/app/0.9/1729962056556-createUserEffect.ts b/src/database/migrations/app/0.9/1729962056556-createUserEffect.ts new file mode 100644 index 0000000..f59b7d4 --- /dev/null +++ b/src/database/migrations/app/0.9/1729962056556-createUserEffect.ts @@ -0,0 +1,18 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; +import MigrationHelper from "../../../../helpers/MigrationHelper"; + +export class CreateUserEffect1729962056556 implements MigrationInterface { + + public async up(queryRunner: QueryRunner): Promise { + MigrationHelper.Up("1729962056556-createUserEffect", "0.9", [ + "01-table-userEffect", + ], queryRunner); + } + + public async down(queryRunner: QueryRunner): Promise { + MigrationHelper.Down("1729962056556-createUserEffect", "0.9", [ + "01-table-userEffect", + ], queryRunner); + } + +} diff --git a/src/helpers/CardDropHelperMetadata.ts b/src/helpers/CardDropHelperMetadata.ts deleted file mode 100644 index 342f347..0000000 --- a/src/helpers/CardDropHelperMetadata.ts +++ /dev/null @@ -1,158 +0,0 @@ -import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js"; -import { CardRarity, CardRarityToColour, CardRarityToString } from "../constants/CardRarity"; -import CardRarityChances from "../constants/CardRarityChances"; -import { DropResult } from "../contracts/SeriesMetadata"; -import { CoreClient } from "../client/client"; -import AppLogger from "../client/appLogger"; -import CardConstants from "../constants/CardConstants"; -import StringTools from "./StringTools"; - -export default class CardDropHelperMetadata { - public static GetRandomCard(): DropResult | undefined { - const randomRarity = Math.random() * 100; - - let cardRarity: CardRarity; - - const bronzeChance = CardRarityChances.Bronze; - const silverChance = bronzeChance + CardRarityChances.Silver; - const goldChance = silverChance + CardRarityChances.Gold; - const mangaChance = goldChance + CardRarityChances.Manga; - - if (randomRarity < bronzeChance) cardRarity = CardRarity.Bronze; - else if (randomRarity < silverChance) cardRarity = CardRarity.Silver; - else if (randomRarity < goldChance) cardRarity = CardRarity.Gold; - else if (randomRarity < mangaChance) cardRarity = CardRarity.Manga; - else cardRarity = CardRarity.Legendary; - - const randomCard = this.GetRandomCardByRarity(cardRarity); - - AppLogger.LogSilly("CardDropHelperMetadata/GetRandomCard", `Random card: ${randomCard?.card.id} ${randomCard?.card.name}`); - - return randomCard; - } - - public static GetRandomCardByRarity(rarity: CardRarity): DropResult | undefined { - AppLogger.LogSilly("CardDropHelperMetadata/GetRandomCardByRarity", `Parameters: rarity=${rarity}`); - - const allCards = CoreClient.Cards - .flatMap(x => x.cards) - .filter(x => x.type == rarity); - - const randomCardIndex = Math.floor(Math.random() * allCards.length); - - const card = allCards[randomCardIndex]; - const series = CoreClient.Cards - .find(x => x.cards.includes(card)); - - if (!series) { - AppLogger.LogWarn("CardDropHelperMetadata/GetRandomCardByRarity", `Series not found for card ${card.id}`); - - return undefined; - } - - AppLogger.LogSilly("CardDropHelperMetadata/GetRandomCardByRarity", `Random card: ${card.id} ${card.name}`); - - return { - series: series, - card: card, - }; - } - - public static GetCardByCardNumber(cardNumber: string): DropResult | undefined { - AppLogger.LogSilly("CardDropHelperMetadata/GetCardByCardNumber", `Parameters: cardNumber=${cardNumber}`); - - const card = CoreClient.Cards - .flatMap(x => x.cards) - .find(x => x.id == cardNumber); - - const series = CoreClient.Cards - .find(x => x.cards.find(y => y.id == card?.id)); - - AppLogger.LogSilly("CardDropHelperMetadata/GetCardByCardNumber", `Card: ${card?.id} ${card?.name}`); - AppLogger.LogSilly("CardDropHelperMetadata/GetCardByCardNumber", `Series: ${series?.id} ${series?.name}`); - - if (!card || !series) { - AppLogger.LogVerbose("CardDropHelperMetadata/GetCardByCardNumber", `Unable to find card metadata: ${cardNumber}`); - return undefined; - } - - return { card, series }; - } - - public static GenerateDropEmbed(drop: DropResult, quantityClaimed: number, imageFileName: string, claimedBy?: string, currency?: number): EmbedBuilder { - AppLogger.LogSilly("CardDropHelperMetadata/GenerateDropEmbed", `Parameters: drop=${drop.card.id}, quantityClaimed=${quantityClaimed}, imageFileName=${imageFileName}`); - - const description = drop.card.subseries ?? drop.series.name; - let colour = CardRarityToColour(drop.card.type); - - if (drop.card.colour && StringTools.IsHexCode(drop.card.colour)) { - const hexCode = Number("0x" + drop.card.colour); - - if (hexCode) { - colour = hexCode; - } else { - AppLogger.LogWarn("CardDropHelperMetadata/GenerateDropEmbed", `Card's colour override is invalid: ${drop.card.id}, ${drop.card.colour}`); - } - } else if (drop.card.colour) { - AppLogger.LogWarn("CardDropHelperMetadata/GenerateDropEmbed", `Card's colour override is invalid: ${drop.card.id}, ${drop.card.colour}`); - } - - let imageUrl = `attachment://${imageFileName}`; - - if (drop.card.path.startsWith("http://") || drop.card.path.startsWith("https://")) { - imageUrl = drop.card.path; - } - - const embed = new EmbedBuilder() - .setTitle(drop.card.name) - .setDescription(description) - .setFooter({ text: `${CardRarityToString(drop.card.type)} · ${drop.card.id}` }) - .setColor(colour) - .setImage(imageUrl) - .addFields([ - { - name: "Claimed", - value: `${quantityClaimed}`, - inline: true, - } - ]); - - if (claimedBy != null) { - embed.addFields([ - { - name: "Claimed by", - value: claimedBy, - inline: true, - } - ]); - } - - if (currency != null) { - embed.addFields([ - { - name: "Currency", - value: `${currency}`, - inline: true, - } - ]); - } - - return embed; - } - - public static GenerateDropButtons(drop: DropResult, claimId: string, userId: string, disabled: boolean = false): ActionRowBuilder { - AppLogger.LogSilly("CardDropHelperMetadata/GenerateDropButtons", `Parameters: drop=${drop.card.id}, claimId=${claimId}, userId=${userId}`); - - return new ActionRowBuilder() - .addComponents( - new ButtonBuilder() - .setCustomId(`claim ${drop.card.id} ${claimId} ${userId}`) - .setLabel(`Claim (${CardConstants.ClaimCost} 🪙)`) - .setStyle(ButtonStyle.Primary) - .setDisabled(disabled), - new ButtonBuilder() - .setCustomId("reroll") - .setLabel("Reroll") - .setStyle(ButtonStyle.Secondary)); - } -} diff --git a/src/helpers/CardSearchHelper.ts b/src/helpers/CardSearchHelper.ts new file mode 100644 index 0000000..df0265c --- /dev/null +++ b/src/helpers/CardSearchHelper.ts @@ -0,0 +1,116 @@ +import {ActionRowBuilder, AttachmentBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder} from "discord.js"; +import Fuse from "fuse.js"; +import {CoreClient} from "../client/client.js"; +import Inventory from "../database/entities/app/Inventory.js"; +import {readFileSync} from "fs"; +import path from "path"; +import AppLogger from "../client/appLogger.js"; +import GetCardsHelper from "./DropHelpers/GetCardsHelper.js"; +import DropEmbedHelper from "./DropHelpers/DropEmbedHelper.js"; + +interface ReturnedPage { + embed: EmbedBuilder, + row: ActionRowBuilder, + attachments: AttachmentBuilder[], + results: string[], +} + +export default class CardSearchHelper { + public static async GenerateSearchQuery(query: string, userid: string, pages: number): Promise { + AppLogger.LogSilly("CardSearchHelper/GenerateSearchQuery", `Parameters: query=${query}, userid=${userid}, pages=${pages}`); + + const fzf = new Fuse(CoreClient.Cards.flatMap(x => x.cards), { keys: ["name"] }); + const entries = fzf.search(query) + .splice(0, pages); + + const entry = entries[0]; + const results = entries + .flatMap(x => x.item.id); + + if (!entry) { + AppLogger.LogVerbose("CardSearchHelper/GenerateSearchQuery", `Unable to find entry: ${query}`); + + return undefined; + } + + const card = GetCardsHelper.GetCardByCardNumber(entry.item.id); + + if (!card) return undefined; + + const attachments = []; + let imageFileName = ""; + + if (!(card.card.path.startsWith("http://") || card.card.path.startsWith("https://"))) { + const image = readFileSync(path.join(process.env.DATA_DIR!, "cards", card.card.path)); + imageFileName = card.card.path.split("/").pop()!; + + const attachment = new AttachmentBuilder(image, { name: imageFileName }); + + attachments.push(attachment); + } + + const inventory = await Inventory.FetchOneByCardNumberAndUserId(userid, card.card.id); + const quantityClaimed = inventory?.Quantity ?? 0; + + const embed = DropEmbedHelper.GenerateDropEmbed(card, quantityClaimed, imageFileName); + + const row = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setCustomId(`view 0 ${results.join(" ")}`) + .setLabel("Previous") + .setStyle(ButtonStyle.Primary) + .setDisabled(true), + new ButtonBuilder() + .setCustomId(`view 2 ${results.join(" ")}`) + .setLabel("Next") + .setStyle(ButtonStyle.Primary) + .setDisabled(pages == 1)); + + return { embed, row, attachments, results }; + } + + public static async GenerateSearchPageFromQuery(results: string[], userid: string, page: number): Promise { + const currentPageId = results[page - 1]; + + const card = GetCardsHelper.GetCardByCardNumber(currentPageId); + + if (!card) { + AppLogger.LogError("CardSearchHelper/GenerateSearchPageFromQuery", `Unable to find card by id: ${currentPageId}.`); + + return undefined; + } + + const attachments = []; + let imageFileName = ""; + + if (!(card.card.path.startsWith("http://") || card.card.path.startsWith("https://"))) { + const image = readFileSync(path.join(process.env.DATA_DIR!, "cards", card.card.path)); + imageFileName = card.card.path.split("/").pop()!; + + const attachment = new AttachmentBuilder(image, { name: imageFileName }); + + attachments.push(attachment); + } + + const inventory = await Inventory.FetchOneByCardNumberAndUserId(userid, card.card.id); + const quantityClaimed = inventory?.Quantity ?? 0; + + const embed = DropEmbedHelper.GenerateDropEmbed(card, quantityClaimed, imageFileName); + + const row = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setCustomId(`view ${page - 1} ${results.join(" ")}`) + .setLabel("Previous") + .setStyle(ButtonStyle.Primary) + .setDisabled(page - 1 == 0), + new ButtonBuilder() + .setCustomId(`view ${page + 1} ${results.join(" ")}`) + .setLabel("Next") + .setStyle(ButtonStyle.Primary) + .setDisabled(page == results.length)); + + return { embed, row, attachments, results }; + } +} diff --git a/src/helpers/DropHelpers/DropEmbedHelper.ts b/src/helpers/DropHelpers/DropEmbedHelper.ts new file mode 100644 index 0000000..08b5813 --- /dev/null +++ b/src/helpers/DropHelpers/DropEmbedHelper.ts @@ -0,0 +1,88 @@ +import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js"; +import { DropResult } from "../../contracts/SeriesMetadata"; +import AppLogger from "../../client/appLogger"; +import { CardRarityToColour, CardRarityToString } from "../../constants/CardRarity"; +import StringTools from "../StringTools"; + +export default class DropEmbedHelper { + public static GenerateDropEmbed(drop: DropResult, quantityClaimed: number, imageFileName: string, claimedBy?: string, currency?: number): EmbedBuilder { + AppLogger.LogSilly("CardDropHelperMetadata/GenerateDropEmbed", `Parameters: drop=${drop.card.id}, quantityClaimed=${quantityClaimed}, imageFileName=${imageFileName}`); + + const description = drop.card.subseries ?? drop.series.name; + let colour = CardRarityToColour(drop.card.type); + + if (drop.card.colour && StringTools.IsHexCode(drop.card.colour)) { + const hexCode = Number("0x" + drop.card.colour); + + if (hexCode) { + colour = hexCode; + } else { + AppLogger.LogWarn("CardDropHelperMetadata/GenerateDropEmbed", `Card's colour override is invalid: ${drop.card.id}, ${drop.card.colour}`); + } + } else if (drop.card.colour) { + AppLogger.LogWarn("CardDropHelperMetadata/GenerateDropEmbed", `Card's colour override is invalid: ${drop.card.id}, ${drop.card.colour}`); + } + + let imageUrl = `attachment://${imageFileName}`; + + if (drop.card.path.startsWith("http://") || drop.card.path.startsWith("https://")) { + imageUrl = drop.card.path; + } + + const embed = new EmbedBuilder() + .setTitle(drop.card.name) + .setDescription(description) + .setFooter({ text: `${CardRarityToString(drop.card.type)} · ${drop.card.id}` }) + .setColor(colour) + .setImage(imageUrl) + .addFields([ + { + name: "Claimed", + value: `${quantityClaimed}`, + inline: true, + } + ]); + + if (claimedBy != null) { + embed.addFields([ + { + name: "Claimed by", + value: claimedBy, + inline: true, + } + ]); + } + + if (currency != null) { + embed.addFields([ + { + name: "Currency", + value: `${currency}`, + inline: true, + } + ]); + } + + return embed; + } + + public static GenerateDropButtons(drop: DropResult, claimId: string, userId: string, disabled: boolean = false): ActionRowBuilder { + AppLogger.LogSilly("CardDropHelperMetadata/GenerateDropButtons", `Parameters: drop=${drop.card.id}, claimId=${claimId}, userId=${userId}`); + + return new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setCustomId(`claim ${drop.card.id} ${claimId} ${userId}`) + .setLabel("Claim") + .setStyle(ButtonStyle.Success) + .setDisabled(disabled), + new ButtonBuilder() + .setCustomId(`sacrifice confirm ${userId} ${drop.card.id} 1`) + .setLabel(`Sacrifice`) + .setStyle(ButtonStyle.Danger), + new ButtonBuilder() + .setCustomId("reroll") + .setEmoji("🔁") + .setStyle(ButtonStyle.Primary),); + } +} \ No newline at end of file diff --git a/src/helpers/DropHelpers/GetCardsHelper.ts b/src/helpers/DropHelpers/GetCardsHelper.ts new file mode 100644 index 0000000..8bc4fe7 --- /dev/null +++ b/src/helpers/DropHelpers/GetCardsHelper.ts @@ -0,0 +1,91 @@ +import AppLogger from "../../client/appLogger"; +import { CoreClient } from "../../client/client"; +import CardConstants from "../../constants/CardConstants"; +import { CardRarity } from "../../constants/CardRarity"; +import CardRarityChances from "../../constants/CardRarityChances"; +import { DropResult } from "../../contracts/SeriesMetadata"; +import EffectHelper from "../EffectHelper"; +import GetUnclaimedCardsHelper from "./GetUnclaimedCardsHelper"; + +export default class GetCardsHelper { + public static async FetchCard(userId: string): Promise { + const hasChanceUpEffect = await EffectHelper.HasEffect(userId, "unclaimed"); + + if (hasChanceUpEffect && Math.random() <= CardConstants.UnusedChanceUpChance) { + return await GetUnclaimedCardsHelper.GetRandomCardUnclaimed(userId); + } + + return this.GetRandomCard(); + } + + public static GetRandomCard(): DropResult | undefined { + const randomRarity = Math.random() * 100; + + let cardRarity: CardRarity; + + const bronzeChance = CardRarityChances.Bronze; + const silverChance = bronzeChance + CardRarityChances.Silver; + const goldChance = silverChance + CardRarityChances.Gold; + const mangaChance = goldChance + CardRarityChances.Manga; + + if (randomRarity < bronzeChance) cardRarity = CardRarity.Bronze; + else if (randomRarity < silverChance) cardRarity = CardRarity.Silver; + else if (randomRarity < goldChance) cardRarity = CardRarity.Gold; + else if (randomRarity < mangaChance) cardRarity = CardRarity.Manga; + else cardRarity = CardRarity.Legendary; + + const randomCard = this.GetRandomCardByRarity(cardRarity); + + AppLogger.LogSilly("CardDropHelperMetadata/GetRandomCard", `Random card: ${randomCard?.card.id} ${randomCard?.card.name}`); + + return randomCard; + } + + public static GetRandomCardByRarity(rarity: CardRarity): DropResult | undefined { + AppLogger.LogSilly("CardDropHelperMetadata/GetRandomCardByRarity", `Parameters: rarity=${rarity}`); + + const allCards = CoreClient.Cards + .flatMap(x => x.cards) + .filter(x => x.type == rarity); + + const randomCardIndex = Math.floor(Math.random() * allCards.length); + + const card = allCards[randomCardIndex]; + const series = CoreClient.Cards + .find(x => x.cards.includes(card)); + + if (!series) { + AppLogger.LogWarn("CardDropHelperMetadata/GetRandomCardByRarity", `Series not found for card ${card.id}`); + + return undefined; + } + + AppLogger.LogSilly("CardDropHelperMetadata/GetRandomCardByRarity", `Random card: ${card.id} ${card.name}`); + + return { + series: series, + card: card, + }; + } + + public static GetCardByCardNumber(cardNumber: string): DropResult | undefined { + AppLogger.LogSilly("CardDropHelperMetadata/GetCardByCardNumber", `Parameters: cardNumber=${cardNumber}`); + + const card = CoreClient.Cards + .flatMap(x => x.cards) + .find(x => x.id == cardNumber); + + const series = CoreClient.Cards + .find(x => x.cards.find(y => y.id == card?.id)); + + AppLogger.LogSilly("CardDropHelperMetadata/GetCardByCardNumber", `Card: ${card?.id} ${card?.name}`); + AppLogger.LogSilly("CardDropHelperMetadata/GetCardByCardNumber", `Series: ${series?.id} ${series?.name}`); + + if (!card || !series) { + AppLogger.LogVerbose("CardDropHelperMetadata/GetCardByCardNumber", `Unable to find card metadata: ${cardNumber}`); + return undefined; + } + + return { card, series }; + } +} diff --git a/src/helpers/DropHelpers/GetUnclaimedCardsHelper.ts b/src/helpers/DropHelpers/GetUnclaimedCardsHelper.ts new file mode 100644 index 0000000..87fafea --- /dev/null +++ b/src/helpers/DropHelpers/GetUnclaimedCardsHelper.ts @@ -0,0 +1,63 @@ +import AppLogger from "../../client/appLogger"; +import { CoreClient } from "../../client/client"; +import { CardRarity } from "../../constants/CardRarity"; +import CardRarityChances from "../../constants/CardRarityChances"; +import { DropResult } from "../../contracts/SeriesMetadata"; +import Inventory from "../../database/entities/app/Inventory"; +import GetCardsHelper from "./GetCardsHelper"; + +export default class GetUnclaimedCardsHelper { + public static async GetRandomCardUnclaimed(userId: string): Promise { + const randomRarity = Math.random() * 100; + + let cardRarity: CardRarity; + + const bronzeChance = CardRarityChances.Bronze; + const silverChance = bronzeChance + CardRarityChances.Silver; + const goldChance = silverChance + CardRarityChances.Gold; + const mangaChance = goldChance + CardRarityChances.Manga; + + if (randomRarity < bronzeChance) cardRarity = CardRarity.Bronze; + else if (randomRarity < silverChance) cardRarity = CardRarity.Silver; + else if (randomRarity < goldChance) cardRarity = CardRarity.Gold; + else if (randomRarity < mangaChance) cardRarity = CardRarity.Manga; + else cardRarity = CardRarity.Legendary; + + const randomCard = await this.GetRandomCardByRarityUnclaimed(cardRarity, userId); + + return randomCard; + } + + public static async GetRandomCardByRarityUnclaimed(rarity: CardRarity, userId: string): Promise { + const claimedCards = await Inventory.FetchAllByUserId(userId); + + if (!claimedCards) { + // They don't have any cards, so safe to get any random card + return GetCardsHelper.GetRandomCardByRarity(rarity); + } + + const allCards = CoreClient.Cards + .flatMap(x => x.cards) + .filter(x => x.type == rarity) + .filter(x => !claimedCards.find(y => y.CardNumber == x.id)); + + if (!allCards) return undefined; + + const randomCardIndex = Math.floor(Math.random() * allCards.length); + + const card = allCards[randomCardIndex]; + const series = CoreClient.Cards + .find(x => x.cards.includes(card)); + + if (!series) { + AppLogger.LogWarn("CardDropHelperMetadata/GetRandomCardByRarityUnclaimed", `Series not found for card ${card.id}`); + + return undefined; + } + + return { + series: series, + card: card, + }; + } +} diff --git a/src/helpers/DropHelpers/MultidropEmbedHelper.ts b/src/helpers/DropHelpers/MultidropEmbedHelper.ts new file mode 100644 index 0000000..526993e --- /dev/null +++ b/src/helpers/DropHelpers/MultidropEmbedHelper.ts @@ -0,0 +1,28 @@ +import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js"; +import { DropResult } from "../../contracts/SeriesMetadata"; +import { GetSacrificeAmount } from "../../constants/CardRarity"; +import DropEmbedHelper from "./DropEmbedHelper"; + +export default class MultidropEmbedHelper { + public static GenerateMultidropEmbed(drop: DropResult, quantityClaimed: number, imageFileName: string, cardsRemaining: number, claimedBy?: string, currency?: number): EmbedBuilder { + const dropEmbed = DropEmbedHelper.GenerateDropEmbed(drop, quantityClaimed, imageFileName, claimedBy, currency); + + dropEmbed.setFooter({ text: `${dropEmbed.data.footer?.text} · ${cardsRemaining} Remaining`}); + + return dropEmbed; + } + + public static GenerateMultidropButtons(drop: DropResult, cardsRemaining: number, userId: string, disabled = false): ActionRowBuilder { + return new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setCustomId(`multidrop keep ${drop.card.id} ${cardsRemaining} ${userId}`) + .setLabel("Keep") + .setStyle(ButtonStyle.Primary) + .setDisabled(disabled), + new ButtonBuilder() + .setCustomId(`multidrop sacrifice ${drop.card.id} ${cardsRemaining} ${userId}`) + .setLabel(`Sacrifice (+${GetSacrificeAmount(drop.card.type)} 🪙)`) + .setStyle(ButtonStyle.Secondary)); + } +} diff --git a/src/helpers/EffectHelper.ts b/src/helpers/EffectHelper.ts new file mode 100644 index 0000000..235ea08 --- /dev/null +++ b/src/helpers/EffectHelper.ts @@ -0,0 +1,194 @@ +import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js"; +import UserEffect from "../database/entities/app/UserEffect"; +import EmbedColours from "../constants/EmbedColours"; +import { EffectDetails } from "../constants/EffectDetails"; +import User from "../database/entities/app/User"; +import CardConstants from "../constants/CardConstants"; +import AppLogger from "../client/appLogger"; + +export default class EffectHelper { + public static async AddEffectToUserInventory(userId: string, name: string, quantity: number = 1) { + let effect = await UserEffect.FetchOneByUserIdAndName(userId, name); + + if (!effect) { + effect = new UserEffect(name, userId, quantity); + } else { + effect.AddUnused(quantity); + } + + await effect.Save(UserEffect, effect); + } + + public static async UseEffect(userId: string, name: string, whenExpires: Date): Promise { + const canUseEffect = await this.CanUseEffect(userId, name); + + if (!canUseEffect) return false; + + const effect = await UserEffect.FetchOneByUserIdAndName(userId, name); + + effect!.UseEffect(whenExpires); + + await effect!.Save(UserEffect, effect!); + + return true; + } + + public static async CanUseEffect(userId: string, name: string): Promise { + const effect = await UserEffect.FetchOneByUserIdAndName(userId, name); + const now = new Date(); + + if (!effect || effect.Unused == 0) { + return false; + } + + const effectDetail = EffectDetails.get(effect.Name); + + if (!effectDetail) { + return false; + } + + if (effect.WhenExpires && now < new Date(effect.WhenExpires.getTime() + effectDetail.cooldown)) { + return false; + } + + return true; + } + + public static async HasEffect(userId: string, name: string): Promise { + const effect = await UserEffect.FetchOneByUserIdAndName(userId, name); + const now = new Date(); + + if (!effect || !effect.WhenExpires) { + return false; + } + + if (now > effect.WhenExpires) { + return false; + } + + return true; + } + + public static async GenerateEffectListEmbed(userId: string, page: number): Promise<{ + embed: EmbedBuilder, + row: ActionRowBuilder, + }> { + const itemsPerPage = 10; + + const query = await UserEffect.FetchAllByUserIdPaginated(userId, page - 1, itemsPerPage); + const activeEffect = await UserEffect.FetchActiveEffectByUserId(userId); + + const effects = query[0]; + const count = query[1]; + + const totalPages = count > 0 ? Math.ceil(count / itemsPerPage) : 1; + + let description = "*none*"; + + if (effects.length > 0) { + description = effects.map(x => `${EffectDetails.get(x.Name)?.friendlyName} x${x.Unused}`).join("\n"); + } + + const embed = new EmbedBuilder() + .setTitle("Effects") + .setDescription(description) + .setColor(EmbedColours.Ok) + .setFooter({ text: `Page ${page} of ${totalPages}` }); + + if (activeEffect) { + embed.addFields([ + { + name: "Active", + value: `${EffectDetails.get(activeEffect.Name)?.friendlyName}`, + inline: true, + }, + { + name: "Expires", + value: ``, + inline: true, + }, + ]); + } + + const row = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setCustomId(`effects list ${page - 1}`) + .setLabel("Previous") + .setStyle(ButtonStyle.Primary) + .setDisabled(page == 1), + new ButtonBuilder() + .setCustomId(`effects list ${page + 1}`) + .setLabel("Next") + .setStyle(ButtonStyle.Primary) + .setDisabled(page == totalPages), + ); + + return { + embed, + row, + }; + } + + public static async GenerateEffectBuyEmbed(userId: string, id: string, quantity: number, disabled: boolean): Promise<{ + embed: EmbedBuilder, + row: ActionRowBuilder, + } | string> { + const effectDetail = EffectDetails.get(id); + + if (!effectDetail) { + return "Effect detail not found!"; + } + + const totalCost = effectDetail.cost * quantity; + + let user = await User.FetchOneById(User, userId); + + if (!user) { + user = new User(userId, CardConstants.StartingCurrency); + await user.Save(User, user); + + AppLogger.LogInfo("EffectHelper", `Created initial user entity for : ${userId}`); + } + + if (user.Currency < totalCost) { + return `You don't have enough currency to buy this! You have \`${user.Currency} Currency\` and need \`${totalCost} Currency\`!`; + } + + const embed = new EmbedBuilder() + .setTitle("Buy Effect") + .setDescription(effectDetail.friendlyName) + .setColor(EmbedColours.Ok) + .addFields([ + { + name: "Cost", + value: `${totalCost}`, + inline: true, + }, + { + name: "Quantity", + value: `${quantity}`, + inline: true, + }, + ]); + + const row = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setCustomId(`effects buy confirm ${id} ${quantity}`) + .setLabel("Confirm") + .setStyle(ButtonStyle.Success) + .setDisabled(disabled), + new ButtonBuilder() + .setCustomId(`effects buy cancel ${id} ${quantity}`) + .setLabel("Cancel") + .setStyle(ButtonStyle.Danger) + .setDisabled(disabled), + ]); + + return { + embed, + row, + } + } +} diff --git a/src/helpers/ImageHelper.ts b/src/helpers/ImageHelper.ts index 1b0c856..6156938 100644 --- a/src/helpers/ImageHelper.ts +++ b/src/helpers/ImageHelper.ts @@ -68,7 +68,7 @@ export default class ImageHelper { ctx.drawImage(image, imageX, imageY); } - catch (e) { + catch { // TODO: Enable once we've investigated a fix //AppLogger.CatchError("ImageHelper", e); } diff --git a/src/helpers/InventoryHelper.ts b/src/helpers/InventoryHelper.ts index 8b8ffa1..3a7fbff 100644 --- a/src/helpers/InventoryHelper.ts +++ b/src/helpers/InventoryHelper.ts @@ -1,4 +1,4 @@ -import { ActionRowBuilder, AttachmentBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js"; +import { ActionRowBuilder, AttachmentBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder, StringSelectMenuBuilder, StringSelectMenuOptionBuilder } from "discord.js"; import Inventory from "../database/entities/app/Inventory"; import { CoreClient } from "../client/client"; import EmbedColours from "../constants/EmbedColours"; @@ -24,7 +24,8 @@ interface InventoryPageCards { interface ReturnedInventoryPage { embed: EmbedBuilder, - row: ActionRowBuilder, + row1: ActionRowBuilder, + row2: ActionRowBuilder, image: AttachmentBuilder, } @@ -99,7 +100,7 @@ export default class InventoryHelper { .setColor(EmbedColours.Ok) .setImage("attachment://page.png"); - const row = new ActionRowBuilder() + const row1 = new ActionRowBuilder() .addComponents( new ButtonBuilder() .setCustomId(`inventory ${userid} ${page - 1}`) @@ -112,9 +113,23 @@ export default class InventoryHelper { .setStyle(ButtonStyle.Primary) .setDisabled(page + 1 == pages.length)); + let pageNum = 0; + + const row2 = new ActionRowBuilder() + .addComponents( + new StringSelectMenuBuilder() + .setCustomId("inventory") + .setPlaceholder(`${currentPage.name} (${currentPage.seriesSubpage + 1})`) + .addOptions(...pages.map(x => + new StringSelectMenuOptionBuilder() + .setLabel(`${x.name} (${x.seriesSubpage + 1})`.substring(0, 100)) + .setDescription(`Page ${pageNum + 1}`) + .setDefault(currentPage.id == x.id) + .setValue(`${userid} ${pageNum++}`)))); + const buffer = await ImageHelper.GenerateCardImageGrid(currentPage.cards.map(x => ({ id: x.id, path: x.path }))); const image = new AttachmentBuilder(buffer, { name: "page.png" }); - return { embed, row, image }; + return { embed, row1, row2, image }; } } diff --git a/src/helpers/TimeLengthInput.ts b/src/helpers/TimeLengthInput.ts index d1d8734..aef58ba 100644 --- a/src/helpers/TimeLengthInput.ts +++ b/src/helpers/TimeLengthInput.ts @@ -118,4 +118,19 @@ export default class TimeLengthInput { return desNumber; } + + public static ConvertFromMilliseconds(ms: number): TimeLengthInput { + const seconds = Math.floor(ms / 1000); + const minutes = Math.floor(seconds / 60); + const hours = Math.floor(minutes / 60); + const days = Math.floor(hours / 24); + + const remainingSeconds = seconds % 60; + const remainingMinutes = minutes % 60; + const remainingHours = hours % 24; + + const timeString = `${days}d ${remainingHours}h ${remainingMinutes}m ${remainingSeconds}s`; + + return new TimeLengthInput(timeString); + } } \ No newline at end of file diff --git a/src/registry.ts b/src/registry.ts index 5ba3af6..3ae885d 100644 --- a/src/registry.ts +++ b/src/registry.ts @@ -7,9 +7,12 @@ import AllBalance from "./commands/allbalance"; import Balance from "./commands/balance"; import Daily from "./commands/daily"; import Drop from "./commands/drop"; +import Effects from "./commands/effects"; import Gdrivesync from "./commands/gdrivesync"; import Give from "./commands/give"; +import Id from "./commands/id"; import Inventory from "./commands/inventory"; +import Multidrop from "./commands/multidrop"; import Resync from "./commands/resync"; import Sacrifice from "./commands/sacrifice"; import Series from "./commands/series"; @@ -23,11 +26,17 @@ import Droprarity from "./commands/stage/droprarity"; // Button Event Imports import Claim from "./buttonEvents/Claim"; +import EffectsButtonEvent from "./buttonEvents/Effects"; import InventoryButtonEvent from "./buttonEvents/Inventory"; +import MultidropButtonEvent from "./buttonEvents/Multidrop"; import Reroll from "./buttonEvents/Reroll"; import SacrificeButtonEvent from "./buttonEvents/Sacrifice"; import SeriesEvent from "./buttonEvents/Series"; import TradeButtonEvent from "./buttonEvents/Trade"; +import ViewButtonEvent from "./buttonEvents/View"; + +// String Dropdown Event Imports +import InventoryStringDropdown from "./stringDropdowns/Inventory"; export default class Registry { public static RegisterCommands() { @@ -37,9 +46,12 @@ export default class Registry { CoreClient.RegisterCommand("balance", new Balance()); CoreClient.RegisterCommand("daily", new Daily()); CoreClient.RegisterCommand("drop", new Drop()); + CoreClient.RegisterCommand("effects", new Effects()); CoreClient.RegisterCommand("gdrivesync", new Gdrivesync()); CoreClient.RegisterCommand("give", new Give()); + CoreClient.RegisterCommand("id", new Id()); CoreClient.RegisterCommand("inventory", new Inventory()); + CoreClient.RegisterCommand("multidrop", new Multidrop()); CoreClient.RegisterCommand("resync", new Resync()); CoreClient.RegisterCommand("sacrifice", new Sacrifice()); CoreClient.RegisterCommand("series", new Series()); @@ -54,10 +66,17 @@ export default class Registry { public static RegisterButtonEvents() { CoreClient.RegisterButtonEvent("claim", new Claim()); + CoreClient.RegisterButtonEvent("effects", new EffectsButtonEvent()); CoreClient.RegisterButtonEvent("inventory", new InventoryButtonEvent()); + CoreClient.RegisterButtonEvent("multidrop", new MultidropButtonEvent()); CoreClient.RegisterButtonEvent("reroll", new Reroll()); CoreClient.RegisterButtonEvent("sacrifice", new SacrificeButtonEvent()); CoreClient.RegisterButtonEvent("series", new SeriesEvent()); CoreClient.RegisterButtonEvent("trade", new TradeButtonEvent()); + CoreClient.RegisterButtonEvent("view", new ViewButtonEvent()); + } + + public static RegisterStringDropdownEvents() { + CoreClient.RegisterStringDropdownEvent("inventory", new InventoryStringDropdown()); } } \ No newline at end of file diff --git a/src/stringDropdowns/Inventory.ts b/src/stringDropdowns/Inventory.ts new file mode 100644 index 0000000..2a218ea --- /dev/null +++ b/src/stringDropdowns/Inventory.ts @@ -0,0 +1,43 @@ +import {StringSelectMenuInteraction} from "discord.js"; +import {StringDropdownEvent} from "../type/stringDropdownEvent"; +import AppLogger from "../client/appLogger"; +import InventoryHelper from "../helpers/InventoryHelper"; + +export default class Inventory extends StringDropdownEvent { + public override async execute(interaction: StringSelectMenuInteraction) { + if (!interaction.guild) return; + + const userid = interaction.values[0].split(" ")[0]; + const page = interaction.values[0].split(" ")[1]; + + AppLogger.LogDebug("StringDropdown/Inventory", `Parameters: userid=${userid}, page=${page}`); + + await interaction.deferUpdate(); + + const member = interaction.guild.members.cache.find(x => x.id == userid) || await interaction.guild.members.fetch(userid); + + if (!member) { + await interaction.reply("Unable to find user."); + return; + } + + try { + const embed = await InventoryHelper.GenerateInventoryPage(member.user.username, member.user.id, Number(page)); + + if (!embed) { + await interaction.followUp("No page for user found."); + return; + } + + await interaction.editReply({ + files: [ embed.image ], + embeds: [ embed.embed ], + components: [ embed.row1, embed.row2 ], + }); + } catch (e) { + AppLogger.LogError("StringDropdown/Inventory", `Error generating inventory page for ${member.user.username} with id ${member.user.id}: ${e}`); + + await interaction.followUp("An error has occurred running this command."); + } + } +} diff --git a/src/timers/PurgeClaims.ts b/src/timers/PurgeClaims.ts index a0ed9d0..4ca8902 100644 --- a/src/timers/PurgeClaims.ts +++ b/src/timers/PurgeClaims.ts @@ -4,7 +4,7 @@ import Claim from "../database/entities/app/Claim"; export default async function PurgeClaims() { const claims = await Claim.FetchAll(Claim); - const whenLastClaimable = new Date(Date.now() - (1000 * 60 * 5)); // 5 minutes ago + const whenLastClaimable = new Date(Date.now() - (1000 * 60 * 2)); // 2 minutes ago const expiredClaims = claims.filter(x => x.WhenCreated < whenLastClaimable); diff --git a/src/type/stringDropdownEvent.ts b/src/type/stringDropdownEvent.ts new file mode 100644 index 0000000..c097cda --- /dev/null +++ b/src/type/stringDropdownEvent.ts @@ -0,0 +1,5 @@ +import {StringSelectMenuInteraction} from "discord.js"; + +export abstract class StringDropdownEvent { + abstract execute(interaction: StringSelectMenuInteraction): Promise; +} diff --git a/tests/.gitkeep b/tests/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/tests/__functions__/discord.js/GenerateButtonInteractionMock.ts b/tests/__functions__/discord.js/GenerateButtonInteractionMock.ts new file mode 100644 index 0000000..2199477 --- /dev/null +++ b/tests/__functions__/discord.js/GenerateButtonInteractionMock.ts @@ -0,0 +1,23 @@ +import { ButtonInteraction } from "../../__types__/discord.js"; + +export default function GenerateButtonInteractionMock(): ButtonInteraction { + return { + guild: {}, + guildId: "guildId", + channel: { + isSendable: jest.fn().mockReturnValue(true), + send: jest.fn(), + }, + deferUpdate: jest.fn(), + editReply: jest.fn(), + message: { + createdAt: new Date(1000 * 60 * 27), + }, + user: { + id: "userId", + }, + customId: "customId", + update: jest.fn(), + reply: jest.fn(), + }; +} \ No newline at end of file diff --git a/tests/__functions__/discord.js/GenerateCommandInteractionMock.ts b/tests/__functions__/discord.js/GenerateCommandInteractionMock.ts new file mode 100644 index 0000000..128c25b --- /dev/null +++ b/tests/__functions__/discord.js/GenerateCommandInteractionMock.ts @@ -0,0 +1,17 @@ +import { CommandInteraction } from "../../__types__/discord.js"; + +export default function GenerateCommandInteractionMock(options?: { + subcommand?: string, +}): CommandInteraction { + return { + deferReply: jest.fn(), + editReply: jest.fn(), + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue(options?.subcommand), + }, + user: { + id: "userId", + }, + }; +} \ No newline at end of file diff --git a/tests/__types__/discord.js.ts b/tests/__types__/discord.js.ts new file mode 100644 index 0000000..3304af4 --- /dev/null +++ b/tests/__types__/discord.js.ts @@ -0,0 +1,31 @@ +export type ButtonInteraction = { + guild: object | null, + guildId: string | null, + channel: { + isSendable: jest.Func, + send: jest.Func, + } | null, + deferUpdate: jest.Func, + editReply: jest.Func, + message: { + createdAt: Date, + } | null, + user: { + id: string, + } | null, + customId: string, + update: jest.Func, + reply: jest.Func, +} + +export type CommandInteraction = { + deferReply: jest.Func, + editReply: jest.Func, + isChatInputCommand: jest.Func, + options: { + getSubcommand: jest.Func, + }, + user: { + id: string, + }, +} \ No newline at end of file diff --git a/tests/buttonEvents/Claim.test.ts b/tests/buttonEvents/Claim.test.ts new file mode 100644 index 0000000..1e7027c --- /dev/null +++ b/tests/buttonEvents/Claim.test.ts @@ -0,0 +1,90 @@ +import { ButtonInteraction, TextChannel } from "discord.js"; +import Claim from "../../src/buttonEvents/Claim"; +import { ButtonInteraction as ButtonInteractionType } from "../__types__/discord.js"; +import GenerateButtonInteractionMock from "../__functions__/discord.js/GenerateButtonInteractionMock"; + +jest.mock("../../src/client/appLogger"); + +let interaction: ButtonInteractionType; + +beforeEach(() => { + jest.useFakeTimers(); + jest.setSystemTime(1000 * 60 * 30); + + interaction = GenerateButtonInteractionMock(); + interaction.customId = "claim cardNumber claimId droppedBy userId"; +}); + +afterAll(() => { + jest.useRealTimers(); +}); + +test("GIVEN interaction.guild is null, EXPECT nothing to happen", async () => { + // Arrange + interaction.guild = null; + + // Act + const claim = new Claim(); + await claim.execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(interaction.deferUpdate).not.toHaveBeenCalled(); + expect(interaction.editReply).not.toHaveBeenCalled(); + expect((interaction.channel as TextChannel).send).not.toHaveBeenCalled(); +}); + +test("GIVEN interaction.guildId is null, EXPECT nothing to happen", async () => { + // Arrange + interaction.guildId = null; + + // Act + const claim = new Claim(); + await claim.execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(interaction.deferUpdate).not.toHaveBeenCalled(); + expect(interaction.editReply).not.toHaveBeenCalled(); + expect((interaction.channel as TextChannel).send).not.toHaveBeenCalled(); +}); + +test("GIVEN interaction.channel is null, EXPECT nothing to happen", async () => { + // Arrange + interaction.channel = null; + + // Act + const claim = new Claim(); + await claim.execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(interaction.deferUpdate).not.toHaveBeenCalled(); + expect(interaction.editReply).not.toHaveBeenCalled(); +}); + +test("GIVEN channel is not sendable, EXPECT nothing to happen", async () => { + // Arrange + interaction.channel!.isSendable = jest.fn().mockReturnValue(false); + + // Act + const claim = new Claim(); + await claim.execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(interaction.deferUpdate).not.toHaveBeenCalled(); + expect(interaction.editReply).not.toHaveBeenCalled(); + expect((interaction.channel as TextChannel).send).not.toHaveBeenCalled(); +}); + +test("GIVEN interaction.message was created more than 5 minutes ago, EXPECT error", async () => { + // Arrange + interaction.message!.createdAt = new Date(0); + + // Act + const claim = new Claim(); + await claim.execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(interaction.channel!.send).toHaveBeenCalledTimes(1); + expect(interaction.channel!.send).toHaveBeenCalledWith("[object Object], Cards can only be claimed within 2 minutes of it being dropped!"); + + expect(interaction.editReply).not.toHaveBeenCalled(); +}); \ No newline at end of file diff --git a/tests/buttonEvents/Effects.test.ts b/tests/buttonEvents/Effects.test.ts new file mode 100644 index 0000000..8fb1023 --- /dev/null +++ b/tests/buttonEvents/Effects.test.ts @@ -0,0 +1,68 @@ +import { ButtonInteraction } from "discord.js"; +import Effects from "../../src/buttonEvents/Effects"; +import GenerateButtonInteractionMock from "../__functions__/discord.js/GenerateButtonInteractionMock"; +import { ButtonInteraction as ButtonInteractionType } from "../__types__/discord.js"; +import List from "../../src/buttonEvents/Effects/List"; +import Use from "../../src/buttonEvents/Effects/Use"; +import AppLogger from "../../src/client/appLogger"; + +jest.mock("../../src/client/appLogger"); +jest.mock("../../src/buttonEvents/Effects/List"); +jest.mock("../../src/buttonEvents/Effects/Use"); + +let interaction: ButtonInteractionType; + +beforeEach(() => { + jest.resetAllMocks(); + + interaction = GenerateButtonInteractionMock(); + interaction.customId = "effects"; +}); + +test("GIVEN action is list, EXPECT list function to be called", async () => { + // Arrange + interaction.customId = "effects list"; + + // Act + const effects = new Effects(); + await effects.execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(List).toHaveBeenCalledTimes(1); + expect(List).toHaveBeenCalledWith(interaction); + + expect(Use.Execute).not.toHaveBeenCalled(); +}); + +test("GIVEN action is use, EXPECT use function to be called", async () => { + // Arrange + interaction.customId = "effects use"; + + // Act + const effects = new Effects(); + await effects.execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(Use.Execute).toHaveBeenCalledTimes(1); + expect(Use.Execute).toHaveBeenCalledWith(interaction); + + expect(List).not.toHaveBeenCalled(); +}); + +test.todo("GIVEN action is buy, EXPECT buy function to be called"); + +test("GIVEN action is invalid, EXPECT nothing to be called", async () => { + // Arrange + interaction.customId = "effects invalid"; + + // Act + const effects = new Effects(); + await effects.execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(List).not.toHaveBeenCalled(); + expect(Use.Execute).not.toHaveBeenCalled(); + + expect(AppLogger.LogError).toHaveBeenCalledTimes(1); + expect(AppLogger.LogError).toHaveBeenCalledWith("Buttons/Effects", "Unknown action, invalid"); +}); diff --git a/tests/buttonEvents/Effects/Buy.test.ts b/tests/buttonEvents/Effects/Buy.test.ts new file mode 100644 index 0000000..3898504 --- /dev/null +++ b/tests/buttonEvents/Effects/Buy.test.ts @@ -0,0 +1,350 @@ +import {ButtonInteraction} from "discord.js"; +import Buy from "../../../src/buttonEvents/Effects/Buy"; +import GenerateButtonInteractionMock from "../../__functions__/discord.js/GenerateButtonInteractionMock"; +import { ButtonInteraction as ButtonInteractionType } from "../../__types__/discord.js"; +import AppLogger from "../../../src/client/appLogger"; +import EffectHelper from "../../../src/helpers/EffectHelper"; +import EmbedColours from "../../../src/constants/EmbedColours"; +import User from "../../../src/database/entities/app/User"; + +jest.mock("../../../src/client/appLogger"); +jest.mock("../../../src/helpers/EffectHelper"); +jest.mock("../../../src/database/entities/app/User"); + +let interaction: ButtonInteractionType; + +beforeEach(() => { + jest.resetAllMocks(); + + interaction = GenerateButtonInteractionMock(); + interaction.customId = "effects buy"; + +}); + +describe("Execute", () => { + test("GIVEN subaction is invalid, EXPECT error logged", async () => { + // Arrange + interaction.customId += " invalid"; + + // Act + await Buy.Execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(AppLogger.LogError).toHaveBeenCalledTimes(1); + expect(AppLogger.LogError).toHaveBeenCalledWith("Buy", "Unknown subaction, effects invalid"); + }); +}); + +describe("Confirm", () => { + let user: User; + + beforeEach(() => { + interaction.customId += " confirm"; + + user = { + Currency: 1000, + Save: jest.fn(), + RemoveCurrency: jest.fn(), + } as unknown as User; + + (User.FetchOneById as jest.Mock).mockResolvedValue(user); + }); + + test("EXPECT success embed generated", async () => { + // Assert + interaction.customId += " unclaimed 1"; + + const embed = { + id: "embed", + setColor: jest.fn(), + setFooter: jest.fn(), + }; + const row = { + id: "row", + }; + + (EffectHelper.GenerateEffectBuyEmbed as jest.Mock).mockResolvedValue({ + embed, + row, + }); + + // Act + await Buy.Execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(interaction.update).toHaveBeenCalledTimes(1); + expect(interaction.update).toHaveBeenCalledWith({ + embeds: [ embed ], + components: [ row ], + }); + + expect(EffectHelper.GenerateEffectBuyEmbed).toHaveBeenCalledTimes(1); + expect(EffectHelper.GenerateEffectBuyEmbed).toHaveBeenCalledWith("userId", "unclaimed", 1, true); + + expect(embed.setColor).toHaveBeenCalledTimes(1); + expect(embed.setColor).toHaveBeenCalledWith(EmbedColours.Success); + + expect(embed.setFooter).toHaveBeenCalledTimes(1); + expect(embed.setFooter).toHaveBeenCalledWith({ text: "Purchased" }); + + expect(interaction.reply).not.toHaveBeenCalled(); + expect(AppLogger.LogError).not.toHaveBeenCalled(); + + expect(User.FetchOneById).toHaveBeenCalledTimes(1); + expect(User.FetchOneById).toHaveBeenCalledWith(User, "userId"); + + expect(user.RemoveCurrency).toHaveBeenCalledTimes(1); + expect(user.RemoveCurrency).toHaveBeenCalledWith(100); + + expect(user.Save).toHaveBeenCalledTimes(1); + expect(user.Save).toHaveBeenCalledWith(User, user); + + expect(EffectHelper.AddEffectToUserInventory).toHaveBeenCalledTimes(1); + expect(EffectHelper.AddEffectToUserInventory).toHaveBeenCalledWith("userId", "unclaimed", 1); + }); + + test("GIVEN id is not supplied, EXPECT error", async () => { + // Act + await Buy.Execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(AppLogger.LogError).toHaveBeenCalledTimes(1); + expect(AppLogger.LogError).toHaveBeenCalledWith("Buy Confirm", "Not enough parameters"); + + expect(EffectHelper.GenerateEffectBuyEmbed).not.toHaveBeenCalled(); + expect(interaction.reply).not.toHaveBeenCalled(); + expect(interaction.update).not.toHaveBeenCalled(); + }); + + test("GIVEN quantity is not supplied, EXPECT error", async () => { + // Assert + interaction.customId += " unclaimed"; + + // Act + await Buy.Execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(AppLogger.LogError).toHaveBeenCalledTimes(1); + expect(AppLogger.LogError).toHaveBeenCalledWith("Buy Confirm", "Not enough parameters"); + + expect(EffectHelper.GenerateEffectBuyEmbed).not.toHaveBeenCalled(); + expect(interaction.reply).not.toHaveBeenCalled(); + expect(interaction.update).not.toHaveBeenCalled(); + }); + + test("GIVEN quantity is not a number, EXPECT error", async () => { + // Assert + interaction.customId += " unclaimed invalid"; + + // Act + await Buy.Execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(AppLogger.LogError).toHaveBeenCalledTimes(1); + expect(AppLogger.LogError).toHaveBeenCalledWith("Buy Confirm", "Invalid number"); + + expect(EffectHelper.GenerateEffectBuyEmbed).not.toHaveBeenCalled(); + expect(interaction.reply).not.toHaveBeenCalled(); + expect(interaction.update).not.toHaveBeenCalled(); + }); + + test("GIVEN quantity is 0, EXPECT error", async () => { + // Assert + interaction.customId += " unclaimed 0"; + + // Act + await Buy.Execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(AppLogger.LogError).toHaveBeenCalledTimes(1); + expect(AppLogger.LogError).toHaveBeenCalledWith("Buy Confirm", "Invalid number"); + + expect(EffectHelper.GenerateEffectBuyEmbed).not.toHaveBeenCalled(); + expect(interaction.reply).not.toHaveBeenCalled(); + expect(interaction.update).not.toHaveBeenCalled(); + }); + + test("GIVEN user is not found, EXPECT error", async () => { + // Assert + interaction.customId += " unclaimed 1"; + + (User.FetchOneById as jest.Mock).mockResolvedValue(undefined); + + // Act + await Buy.Execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(AppLogger.LogError).toHaveBeenCalledTimes(1); + expect(AppLogger.LogError).toHaveBeenCalledWith("Buy Confirm", "Unable to find user"); + + expect(EffectHelper.AddEffectToUserInventory).not.toHaveBeenCalled(); + + expect(interaction.update).not.toHaveBeenCalled(); + expect(interaction.reply).not.toHaveBeenCalled(); + }); + + test("GIVEN user does not have enough currency, EXPECT error", async () => { + // Assert + interaction.customId += " unclaimed 1"; + + user.Currency = 0; + + // Act + await Buy.Execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("You don't have enough currency to buy this! You have `0 Currency` and need `100 Currency`!"); + + expect(EffectHelper.AddEffectToUserInventory).not.toHaveBeenCalled(); + + expect(interaction.update).not.toHaveBeenCalled(); + + expect(AppLogger.LogError).not.toHaveBeenCalled(); + }); + + test("GIVEN GenerateEffectBuyEmbed returns with a string, EXPECT error replied", async () => { + // Assert + interaction.customId += " unclaimed 1"; + + (EffectHelper.GenerateEffectBuyEmbed as jest.Mock).mockResolvedValue("Test error"); + + // Act + await Buy.Execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("Test error"); + + expect(EffectHelper.GenerateEffectBuyEmbed).toHaveBeenCalledTimes(1); + + expect(interaction.update).not.toHaveBeenCalled(); + expect(AppLogger.LogError).not.toHaveBeenCalled(); + }); +}); + +describe("Cancel", () => { + beforeEach(() => { + interaction.customId += " cancel"; + }); + + test("EXPECT embed generated", async () => { + // Assert + interaction.customId += " unclaimed 1"; + + const embed = { + id: "embed", + setColor: jest.fn(), + setFooter: jest.fn(), + }; + const row = { + id: "row", + }; + + (EffectHelper.GenerateEffectBuyEmbed as jest.Mock).mockResolvedValue({ + embed, + row, + }); + + // Act + await Buy.Execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(interaction.update).toHaveBeenCalledTimes(1); + expect(interaction.update).toHaveBeenCalledWith({ + embeds: [ embed ], + components: [ row ], + }); + + expect(EffectHelper.GenerateEffectBuyEmbed).toHaveBeenCalledTimes(1); + expect(EffectHelper.GenerateEffectBuyEmbed).toHaveBeenCalledWith("userId", "unclaimed", 1, true); + + expect(embed.setColor).toHaveBeenCalledTimes(1); + expect(embed.setColor).toHaveBeenCalledWith(EmbedColours.Error); + + expect(embed.setFooter).toHaveBeenCalledTimes(1); + expect(embed.setFooter).toHaveBeenCalledWith({ text: "Cancelled" }); + + expect(interaction.reply).not.toHaveBeenCalled(); + expect(AppLogger.LogError).not.toHaveBeenCalled(); + }); + + test("GIVEN id is not supplied, EXPECT error", async () => { + // Act + await Buy.Execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(AppLogger.LogError).toHaveBeenCalledTimes(1); + expect(AppLogger.LogError).toHaveBeenCalledWith("Buy Cancel", "Not enough parameters"); + + expect(interaction.reply).not.toHaveBeenCalled(); + expect(interaction.update).not.toHaveBeenCalled(); + }); + + test("GIVEN quantity is not supplied, EXPECT error", async () => { + // Assert + interaction.customId += " unclaimed"; + + // Act + await Buy.Execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(AppLogger.LogError).toHaveBeenCalledTimes(1); + expect(AppLogger.LogError).toHaveBeenCalledWith("Buy Cancel", "Not enough parameters"); + + expect(EffectHelper.GenerateEffectBuyEmbed).not.toHaveBeenCalled(); + expect(interaction.reply).not.toHaveBeenCalled(); + expect(interaction.update).not.toHaveBeenCalled(); + }); + + test("GIVEN quantity is not a number, EXPECT error", async () => { + // Assert + interaction.customId += " unclaimed invalid"; + + // Act + await Buy.Execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(AppLogger.LogError).toHaveBeenCalledTimes(1); + expect(AppLogger.LogError).toHaveBeenCalledWith("Buy Cancel", "Invalid number"); + + expect(EffectHelper.GenerateEffectBuyEmbed).not.toHaveBeenCalled(); + expect(interaction.reply).not.toHaveBeenCalled(); + expect(interaction.update).not.toHaveBeenCalled(); + }); + + test("GIVEN quantity is 0, EXPECT error", async () => { + // Assert + interaction.customId += " unclaimed 0"; + + // Act + await Buy.Execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(AppLogger.LogError).toHaveBeenCalledTimes(1); + expect(AppLogger.LogError).toHaveBeenCalledWith("Buy Cancel", "Invalid number"); + + expect(EffectHelper.GenerateEffectBuyEmbed).not.toHaveBeenCalled(); + expect(interaction.reply).not.toHaveBeenCalled(); + expect(interaction.update).not.toHaveBeenCalled(); + }); + + test("GIVEN GenerateEffectBuyEmbed returns with a string, EXPECT error replied", async () => { + // Assert + interaction.customId += " unclaimed 1"; + + (EffectHelper.GenerateEffectBuyEmbed as jest.Mock).mockResolvedValue("Test error"); + + // Act + await Buy.Execute(interaction as unknown as ButtonInteraction); + + // Assert + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("Test error"); + + expect(EffectHelper.GenerateEffectBuyEmbed).toHaveBeenCalledTimes(1); + + expect(interaction.update).not.toHaveBeenCalled(); + expect(AppLogger.LogError).not.toHaveBeenCalled(); + }); +}); diff --git a/tests/buttonEvents/Effects/List.test.ts b/tests/buttonEvents/Effects/List.test.ts new file mode 100644 index 0000000..5b42c61 --- /dev/null +++ b/tests/buttonEvents/Effects/List.test.ts @@ -0,0 +1,50 @@ +import { ActionRowBuilder, ButtonBuilder, ButtonInteraction, EmbedBuilder } from "discord.js"; +import List from "../../../src/buttonEvents/Effects/List"; +import EffectHelper from "../../../src/helpers/EffectHelper"; +import { mock } from "jest-mock-extended"; + +jest.mock("../../../src/helpers/EffectHelper"); + +let interaction: ReturnType>; + +beforeEach(() => { + jest.resetAllMocks(); + + (EffectHelper.GenerateEffectListEmbed as jest.Mock).mockResolvedValue({ + embed: mock(), + row: mock>(), + }); + + interaction = mock(); + interaction.user.id = "userId"; + interaction.customId = "effects list 1"; +}); + +test("GIVEN pageOption is NOT a number, EXPECT error", async () => { + // Arrange + interaction.customId = "effects list invalid"; + + // Act + await List(interaction); + + // Assert + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("Page option is not a valid number") + + expect(EffectHelper.GenerateEffectListEmbed).not.toHaveBeenCalled(); + expect(interaction.update).not.toHaveBeenCalled(); +}); + +test("GIVEN pageOption is a number, EXPECT interaction updated", async () => { + // Arrange + interaction.customId = "effects list 1"; + + // Act + await List(interaction); + + // Assert + expect(EffectHelper.GenerateEffectListEmbed).toHaveBeenCalledTimes(1); + expect(EffectHelper.GenerateEffectListEmbed).toHaveBeenCalledWith("userId", 1); + + expect(interaction.update).toHaveBeenCalledTimes(1); +}); \ No newline at end of file diff --git a/tests/buttonEvents/Effects/Use.test.ts b/tests/buttonEvents/Effects/Use.test.ts new file mode 100644 index 0000000..86391cc --- /dev/null +++ b/tests/buttonEvents/Effects/Use.test.ts @@ -0,0 +1,148 @@ +import { ButtonInteraction, InteractionResponse, InteractionUpdateOptions, MessagePayload } from "discord.js"; +import Use from "../../../src/buttonEvents/Effects/Use"; +import { mock } from "jest-mock-extended"; +import AppLogger from "../../../src/client/appLogger"; +import EffectHelper from "../../../src/helpers/EffectHelper"; + +jest.mock("../../../src/client/appLogger"); +jest.mock("../../../src/helpers/EffectHelper"); + +beforeEach(() => { + jest.resetAllMocks(); + + jest.useFakeTimers(); + jest.setSystemTime(0); +}); + +afterAll(() => { + jest.useRealTimers(); +}); + +describe("Execute", () => { + test("GIVEN subaction is unknown, EXPECT nothing to be called", async () => { + // Arrange + const interaction = mock(); + interaction.customId = "effects use invalud"; + + // Act + await Use.Execute(interaction); + + // Assert + expect(interaction.reply).not.toHaveBeenCalled(); + expect(interaction.update).not.toHaveBeenCalled(); + }); +}); + +describe("UseConfirm", () => { + let interaction = mock(); + + beforeEach(() => { + interaction = mock(); + interaction.customId = "effects use confirm"; + }); + + test("GIVEN effectDetail is not found, EXPECT error", async () => { + // Arrange + interaction.customId += " invalid"; + + // Act + await Use.Execute(interaction); + + // Assert + expect(AppLogger.LogError).toHaveBeenCalledTimes(1); + expect(AppLogger.LogError).toHaveBeenCalledWith("Button/Effects/Use", "Effect not found, invalid"); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("Effect not found in system!"); + }); + + test("GIVEN EffectHelper.UseEffect failed, EXPECT error", async () => { + // Arrange + interaction.customId += " unclaimed"; + interaction.user.id = "userId"; + + (EffectHelper.UseEffect as jest.Mock).mockResolvedValue(false); + + const whenExpires = new Date(Date.now() + 10 * 60 * 1000); + + // Act + await Use.Execute(interaction); + + // Assert + expect(EffectHelper.UseEffect).toHaveBeenCalledTimes(1); + expect(EffectHelper.UseEffect).toHaveBeenCalledWith("userId", "unclaimed", whenExpires); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("Unable to use effect! Please make sure you have it in your inventory and is not on cooldown"); + }); + + test("GIVEN EffectHelper.UseEffect succeeded, EXPECT interaction updated", async () => { + let updatedWith; + + // Arrange + interaction.customId += " unclaimed"; + interaction.user.id = "userId"; + interaction.update.mockImplementation(async (opts: string | MessagePayload | InteractionUpdateOptions) => { + updatedWith = opts; + + return mock>(); + }); + + (EffectHelper.UseEffect as jest.Mock).mockResolvedValue(true); + + const whenExpires = new Date(Date.now() + 10 * 60 * 1000); + + // Act + await Use.Execute(interaction); + + // Assert + expect(EffectHelper.UseEffect).toHaveBeenCalledTimes(1); + expect(EffectHelper.UseEffect).toHaveBeenCalledWith("userId", "unclaimed", whenExpires); + + expect(interaction.update).toHaveBeenCalledTimes(1); + expect(updatedWith).toMatchSnapshot(); + }); +}); + +describe("UseCancel", () => { + let interaction = mock(); + + beforeEach(() => { + interaction = mock(); + interaction.customId = "effects use cancel"; + }); + + test("GIVEN effectDetail is not found, EXPECT error", async () => { + // Arrange + interaction.customId += " invalid"; + + // Act + await Use.Execute(interaction); + + // Assert + expect(AppLogger.LogError).toHaveBeenCalledTimes(1); + expect(AppLogger.LogError).toHaveBeenCalledWith("Button/Effects/Cancel", "Effect not found, invalid"); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("Effect not found in system!"); + }); + + test("GIVEN effectDetail is found, EXPECT interaction updated", async () => { + let updatedWith; + + // Arrange + interaction.customId += " unclaimed"; + interaction.user.id = "userId"; + interaction.update.mockImplementation(async (opts: string | MessagePayload | InteractionUpdateOptions) => { + updatedWith = opts; + + return mock>(); + }); + // Act + await Use.Execute(interaction); + + // Assert + expect(interaction.update).toHaveBeenCalledTimes(1); + expect(updatedWith).toMatchSnapshot(); + }); +}); \ No newline at end of file diff --git a/tests/buttonEvents/Effects/__snapshots__/Use.test.ts.snap b/tests/buttonEvents/Effects/__snapshots__/Use.test.ts.snap new file mode 100644 index 0000000..6cec0f4 --- /dev/null +++ b/tests/buttonEvents/Effects/__snapshots__/Use.test.ts.snap @@ -0,0 +1,95 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`UseCancel GIVEN effectDetail is found, EXPECT interaction updated 1`] = ` +{ + "components": [ + { + "components": [ + { + "custom_id": "effects use confirm unclaimed", + "disabled": true, + "emoji": undefined, + "label": "Confirm", + "style": 1, + "type": 2, + }, + { + "custom_id": "effects use cancel unclaimed", + "disabled": true, + "emoji": undefined, + "label": "Cancel", + "style": 4, + "type": 2, + }, + ], + "type": 1, + }, + ], + "embeds": [ + { + "color": 13882323, + "description": "The effect from your inventory has not been used", + "fields": [ + { + "inline": true, + "name": "Effect", + "value": "Unclaimed Chance Up", + }, + { + "inline": true, + "name": "Expires", + "value": "10m", + }, + ], + "title": "Effect Use Cancelled", + }, + ], +} +`; + +exports[`UseConfirm GIVEN EffectHelper.UseEffect succeeded, EXPECT interaction updated 1`] = ` +{ + "components": [ + { + "components": [ + { + "custom_id": "effects use confirm unclaimed", + "disabled": true, + "emoji": undefined, + "label": "Confirm", + "style": 1, + "type": 2, + }, + { + "custom_id": "effects use cancel unclaimed", + "disabled": true, + "emoji": undefined, + "label": "Cancel", + "style": 4, + "type": 2, + }, + ], + "type": 1, + }, + ], + "embeds": [ + { + "color": 2263842, + "description": "You now have an active effect!", + "fields": [ + { + "inline": true, + "name": "Effect", + "value": "Unclaimed Chance Up", + }, + { + "inline": true, + "name": "Expires", + "value": "", + }, + ], + "title": "Effect Used", + }, + ], +} +`; diff --git a/tests/buttonEvents/Reroll.test.ts b/tests/buttonEvents/Reroll.test.ts new file mode 100644 index 0000000..2021aac --- /dev/null +++ b/tests/buttonEvents/Reroll.test.ts @@ -0,0 +1,7 @@ +describe("GIVEN valid conditions", () => { + test.todo("EXPECT user.RemoveCurrency to be called"); + + test.todo("GIVEN user is saved"); +}); + +test.todo("GIVEN user.RemoveCurrency fails, EXPECT error replied"); \ No newline at end of file diff --git a/tests/commands/__snapshots__/effects.test.ts.snap b/tests/commands/__snapshots__/effects.test.ts.snap new file mode 100644 index 0000000..474b505 --- /dev/null +++ b/tests/commands/__snapshots__/effects.test.ts.snap @@ -0,0 +1,106 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`EXPECT CommandBuilder to be defined 1`] = ` +{ + "contexts": undefined, + "default_member_permissions": undefined, + "default_permission": undefined, + "description": "Effects", + "description_localizations": undefined, + "dm_permission": undefined, + "integration_types": undefined, + "name": "effects", + "name_localizations": undefined, + "nsfw": undefined, + "options": [ + { + "description": "List all effects I have", + "description_localizations": undefined, + "name": "list", + "name_localizations": undefined, + "options": [ + { + "autocomplete": undefined, + "choices": undefined, + "description": "The page number", + "description_localizations": undefined, + "max_value": undefined, + "min_value": 1, + "name": "page", + "name_localizations": undefined, + "required": false, + "type": 10, + }, + ], + "type": 1, + }, + { + "description": "Use an effect in your inventory", + "description_localizations": undefined, + "name": "use", + "name_localizations": undefined, + "options": [ + { + "autocomplete": undefined, + "choices": [ + { + "name": "Unclaimed Chance Up", + "name_localizations": undefined, + "value": "unclaimed", + }, + ], + "description": "The effect id to use", + "description_localizations": undefined, + "max_length": undefined, + "min_length": undefined, + "name": "id", + "name_localizations": undefined, + "required": true, + "type": 3, + }, + ], + "type": 1, + }, + { + "description": "Buy more effects", + "description_localizations": undefined, + "name": "buy", + "name_localizations": undefined, + "options": [ + { + "autocomplete": undefined, + "choices": [ + { + "name": "Unclaimed Chance Up", + "name_localizations": undefined, + "value": "unclaimed", + }, + ], + "description": "The effect id to buy", + "description_localizations": undefined, + "max_length": undefined, + "min_length": undefined, + "name": "id", + "name_localizations": undefined, + "required": true, + "type": 3, + }, + { + "autocomplete": undefined, + "choices": undefined, + "description": "The amount to buy", + "description_localizations": undefined, + "max_value": undefined, + "min_value": 1, + "name": "quantity", + "name_localizations": undefined, + "required": false, + "type": 10, + }, + ], + "type": 1, + }, + ], + "type": 1, +} +`; diff --git a/tests/commands/drop.test.ts b/tests/commands/drop.test.ts new file mode 100644 index 0000000..81b5f4a --- /dev/null +++ b/tests/commands/drop.test.ts @@ -0,0 +1,142 @@ +import { CommandInteraction } from "discord.js"; +import Drop from "../../src/commands/drop"; +import GenerateCommandInteractionMock from "../__functions__/discord.js/GenerateCommandInteractionMock"; +import { CommandInteraction as CommandInteractionMock } from "../__types__/discord.js"; +import { CoreClient } from "../../src/client/client"; +import Config from "../../src/database/entities/app/Config"; +import User from "../../src/database/entities/app/User"; +import GetCardsHelper from "../../src/helpers/DropHelpers/GetCardsHelper"; +import Inventory from "../../src/database/entities/app/Inventory"; +import DropEmbedHelper from "../../src/helpers/DropHelpers/DropEmbedHelper"; +import CardConstants from "../../src/constants/CardConstants"; +import * as uuid from "uuid"; + +jest.mock("../../src/database/entities/app/Config"); +jest.mock("../../src/database/entities/app/User"); +jest.mock("../../src/helpers/DropHelpers/GetCardsHelper"); +jest.mock("../../src/database/entities/app/Inventory"); +jest.mock("../../src/helpers/DropHelpers/DropEmbedHelper"); + +jest.mock("uuid"); + +beforeEach(() => { + (Config.GetValue as jest.Mock).mockResolvedValue("false"); +}); + +describe("execute", () => { + describe("GIVEN user is in the database", () => { + let interaction: CommandInteractionMock; + let user: User; + const randomCard = { + card: { + id: "cardId", + path: "https://google.com/", + } + }; + + beforeAll(async () => { + // Arrange + CoreClient.AllowDrops = true; + + interaction = GenerateCommandInteractionMock(); + + user = { + Currency: 500, + RemoveCurrency: jest.fn().mockReturnValue(true), + Save: jest.fn(), + } as unknown as User; + + (User.FetchOneById as jest.Mock).mockResolvedValue(user); + (GetCardsHelper.FetchCard as jest.Mock).mockResolvedValue(randomCard); + (Inventory.FetchOneByCardNumberAndUserId as jest.Mock).mockResolvedValue({ + Quantity: 1, + }); + (DropEmbedHelper.GenerateDropEmbed as jest.Mock).mockReturnValue({ + type: "Embed", + }); + (DropEmbedHelper.GenerateDropButtons as jest.Mock).mockReturnValue({ + type: "Button", + }); + + (uuid.v4 as jest.Mock).mockReturnValue("uuid"); + + // Act + const drop = new Drop(); + await drop.execute(interaction as unknown as CommandInteraction); + }); + + test("EXPECT user to be fetched", () => { + expect(User.FetchOneById).toHaveBeenCalledTimes(1); + expect(User.FetchOneById).toHaveBeenCalledWith(User, "userId"); + }); + + test("EXPECT user.RemoveCurrency to be called", () => { + expect(user.RemoveCurrency).toHaveBeenCalledTimes(1); + expect(user.RemoveCurrency).toHaveBeenCalledWith(CardConstants.ClaimCost); + }); + + test("EXPECT user to be saved", () => { + expect(user.Save).toHaveBeenCalledTimes(1); + expect(user.Save).toHaveBeenCalledWith(User, user); + }); + + test("EXPECT random card to be fetched", () => { + expect(GetCardsHelper.FetchCard).toHaveBeenCalledTimes(1); + expect(GetCardsHelper.FetchCard).toHaveBeenCalledWith("userId"); + }); + + test("EXPECT interaction to be deferred", () => { + expect(interaction.deferReply).toHaveBeenCalledTimes(1); + }); + + test("EXPECT Inventory.FetchOneByCardNumberAndUserId to be called", () => { + expect(Inventory.FetchOneByCardNumberAndUserId).toHaveBeenCalledTimes(1); + expect(Inventory.FetchOneByCardNumberAndUserId).toHaveBeenCalledWith("userId", "cardId"); + }); + + test("EXPECT DropEmbedHelper.GenerateDropEmbed to be called", () => { + expect(DropEmbedHelper.GenerateDropEmbed).toHaveBeenCalledTimes(1); + expect(DropEmbedHelper.GenerateDropEmbed).toHaveBeenCalledWith(randomCard, 1, "", undefined, 500); + }); + + test("EXPECT DropEmbedHelper.GenerateDropButtons to be called", () => { + expect(DropEmbedHelper.GenerateDropButtons).toHaveBeenCalledTimes(1); + expect(DropEmbedHelper.GenerateDropButtons).toHaveBeenCalledWith(randomCard, "uuid", "userId"); + }); + + test("EXPECT interaction to be edited", () => { + expect(interaction.editReply).toHaveBeenCalledTimes(1); + expect(interaction.editReply).toHaveBeenCalledWith({ + embeds: [ { type: "Embed" } ], + files: [], + components: [ { type: "Button" } ], + }); + }); + + describe("AND randomCard path is not a url", () => { + test.todo("EXPECT image read from file system"); + + test.todo("EXPECT files on the embed to contain the image as an attachment"); + }); + }); + + describe("GIVEN user is not in the database", () => { + test.todo("EXPECT new user to be created"); + }); + + describe("GIVEN user.RemoveCurrency fails", () => { + test.todo("EXPECT error replied"); + }); + + describe("GIVEN randomCard returns null", () => { + test.todo("EXPECT error logged"); + + test.todo("EXPECT error replied"); + }); + + describe("GIVEN the code throws an error", () => { + test.todo("EXPECT error logged"); + + test.todo("EXPECT interaction edited with error"); + }); +}); \ No newline at end of file diff --git a/tests/commands/effects.test.ts b/tests/commands/effects.test.ts new file mode 100644 index 0000000..33f612d --- /dev/null +++ b/tests/commands/effects.test.ts @@ -0,0 +1,105 @@ +import Effects from "../../src/commands/effects"; +import List from "../../src/commands/effects/List"; +import Use from "../../src/commands/effects/Use"; +import Buy from "../../src/commands/effects/Buy"; +import AppLogger from "../../src/client/appLogger"; +import GenerateCommandInteractionMock from "../__functions__/discord.js/GenerateCommandInteractionMock"; +import { CommandInteraction } from "discord.js"; + +jest.mock("../../src/commands/effects/List"); +jest.mock("../../src/commands/effects/Use"); +jest.mock("../../src/commands/effects/Buy"); +jest.mock("../../src/client/appLogger"); + +beforeEach(() => { + jest.resetAllMocks(); +}); + +test("EXPECT CommandBuilder to be defined", async () => { + // Act + const effects = new Effects(); + + // Assert + expect(effects.CommandBuilder).toMatchSnapshot(); +}); + +describe("execute", () => { + test("GIVEN interaction subcommand is list, EXPECT buy function called", async () => { + // Arrange + const interaction = GenerateCommandInteractionMock({ + subcommand: "list", + }); + + // Act + const effects = new Effects(); + await effects.execute(interaction as unknown as CommandInteraction); + + // Assert + expect(List).toHaveBeenCalledTimes(1); + expect(List).toHaveBeenCalledWith(interaction); + + expect(Use).not.toHaveBeenCalled(); + expect(Buy).not.toHaveBeenCalled(); + + expect(AppLogger.LogError).not.toHaveBeenCalled(); + }); + + test("GIVEN interaction subcommand is use, EXPECT buy function called", async () => { + // Arrange + const interaction = GenerateCommandInteractionMock({ + subcommand: "use", + }); + + // Act + const effects = new Effects(); + await effects.execute(interaction as unknown as CommandInteraction); + + // Assert + expect(Use).toHaveBeenCalledTimes(1); + expect(Use).toHaveBeenCalledWith(interaction); + + expect(List).not.toHaveBeenCalled(); + expect(Buy).not.toHaveBeenCalled(); + + expect(AppLogger.LogError).not.toHaveBeenCalled(); + }); + + test("GIVEN interaction subcommand is buy, EXPECT buy function called", async () => { + // Arrange + const interaction = GenerateCommandInteractionMock({ + subcommand: "buy", + }); + + // Act + const effects = new Effects(); + await effects.execute(interaction as unknown as CommandInteraction); + + // Assert + expect(Buy).toHaveBeenCalledTimes(1); + expect(Buy).toHaveBeenCalledWith(interaction); + + expect(List).not.toHaveBeenCalled(); + expect(Use).not.toHaveBeenCalled(); + + expect(AppLogger.LogError).not.toHaveBeenCalled(); + }); + + test("GIVEN interaction subcommand is invalid, EXPECT error logged", async () => { + // Arrange + const interaction = GenerateCommandInteractionMock({ + subcommand: "invalid", + }); + + // Act + const effects = new Effects(); + await effects.execute(interaction as unknown as CommandInteraction); + + // Assert + expect(AppLogger.LogError).toHaveBeenCalledTimes(1); + expect(AppLogger.LogError).toHaveBeenCalledWith("Commands/Effects", "Invalid subcommand: invalid"); + + expect(List).not.toHaveBeenCalled(); + expect(Use).not.toHaveBeenCalled(); + expect(Buy).not.toHaveBeenCalled(); + }); +}); \ No newline at end of file diff --git a/tests/commands/effects/Buy.test.ts b/tests/commands/effects/Buy.test.ts new file mode 100644 index 0000000..87e4219 --- /dev/null +++ b/tests/commands/effects/Buy.test.ts @@ -0,0 +1,9 @@ +jest.mock("../../../src/helpers/EffectHelper"); + +describe("Buy", () => { + test.todo("GIVEN result returns a string, EXPECT interaction replied with string"); + + test.todo("GIVEN result returns an embed, EXPECT interaction replied with embed and row"); + + test.todo("GIVEN quantity option is not supplied, EXPECT quantity to default to 1"); +}); diff --git a/tests/helpers/DropHelpers/DropEmbedHelper.test.ts b/tests/helpers/DropHelpers/DropEmbedHelper.test.ts new file mode 100644 index 0000000..743f6c7 --- /dev/null +++ b/tests/helpers/DropHelpers/DropEmbedHelper.test.ts @@ -0,0 +1,3 @@ +describe("GenerateDropButtons", () => { + test.todo("EXPECT row to be returned"); +}); \ No newline at end of file diff --git a/tests/helpers/DropHelpers/GetCardsHelper.test.ts b/tests/helpers/DropHelpers/GetCardsHelper.test.ts new file mode 100644 index 0000000..421d4ef --- /dev/null +++ b/tests/helpers/DropHelpers/GetCardsHelper.test.ts @@ -0,0 +1,68 @@ +import GetCardsHelper from "../../../src/helpers/DropHelpers/GetCardsHelper"; +import EffectHelper from "../../../src/helpers/EffectHelper"; +import GetUnclaimedCardsHelper from "../../../src/helpers/DropHelpers/GetUnclaimedCardsHelper"; +import CardConstants from "../../../src/constants/CardConstants"; + +jest.mock("../../../src/helpers/EffectHelper"); +jest.mock("../../../src/helpers/DropHelpers/GetUnclaimedCardsHelper"); + +beforeEach(() => { + jest.resetAllMocks(); +}); + +describe("FetchCard", () => { + test("GIVEN user has the unclaimed effect AND unused chance is within constraint, EXPECT unclaimed card returned", async () => { + // Arrange + (EffectHelper.HasEffect as jest.Mock).mockResolvedValue(true); + GetCardsHelper.GetRandomCard = jest.fn(); + Math.random = jest.fn().mockReturnValue(CardConstants.UnusedChanceUpChance - 0.1); + + // Act + await GetCardsHelper.FetchCard("userId"); + + // Assert + expect(EffectHelper.HasEffect).toHaveBeenCalledTimes(1); + expect(EffectHelper.HasEffect).toHaveBeenCalledWith("userId", "unclaimed"); + + expect(GetUnclaimedCardsHelper.GetRandomCardUnclaimed).toHaveBeenCalledTimes(1); + expect(GetUnclaimedCardsHelper.GetRandomCardUnclaimed).toHaveBeenCalledWith("userId"); + + expect(GetCardsHelper.GetRandomCard).not.toHaveBeenCalled(); + }); + + test("GIVEN user has unclaimed effect AND unused chance is NOT within constraint, EXPECT random card returned", async () => { + // Arrange + (EffectHelper.HasEffect as jest.Mock).mockResolvedValue(true); + GetCardsHelper.GetRandomCard = jest.fn(); + Math.random = jest.fn().mockReturnValue(CardConstants.UnusedChanceUpChance + 0.1); + + // Act + await GetCardsHelper.FetchCard("userId"); + + // Assert + expect(EffectHelper.HasEffect).toHaveBeenCalledTimes(1); + expect(EffectHelper.HasEffect).toHaveBeenCalledWith("userId", "unclaimed"); + + expect(GetCardsHelper.GetRandomCard).toHaveBeenCalledTimes(1); + + expect(GetUnclaimedCardsHelper.GetRandomCardUnclaimed).not.toHaveBeenCalled(); + }); + + test("GIVEN user does NOT have unclaimed effect, EXPECT random card returned", async () => { + // Arrange + (EffectHelper.HasEffect as jest.Mock).mockResolvedValue(false); + GetCardsHelper.GetRandomCard = jest.fn(); + Math.random = jest.fn().mockReturnValue(CardConstants.UnusedChanceUpChance + 0.1); + + // Act + await GetCardsHelper.FetchCard("userId"); + + // Assert + expect(EffectHelper.HasEffect).toHaveBeenCalledTimes(1); + expect(EffectHelper.HasEffect).toHaveBeenCalledWith("userId", "unclaimed"); + + expect(GetCardsHelper.GetRandomCard).toHaveBeenCalledTimes(1); + + expect(GetUnclaimedCardsHelper.GetRandomCardUnclaimed).not.toHaveBeenCalled(); + }); +}); \ No newline at end of file diff --git a/tests/helpers/EffectHelper.test.ts b/tests/helpers/EffectHelper.test.ts new file mode 100644 index 0000000..dcab744 --- /dev/null +++ b/tests/helpers/EffectHelper.test.ts @@ -0,0 +1,127 @@ +import EffectHelper from "../../src/helpers/EffectHelper"; +import UserEffect from "../../src/database/entities/app/UserEffect"; + +jest.mock("../../src/database/entities/app/UserEffect"); + +describe("GenerateEffectListEmbed", () => { + test("GIVEN user has an effect, EXPECT detailed embed to be returned", async () => { + // Arrange + (UserEffect.FetchAllByUserIdPaginated as jest.Mock).mockResolvedValue([ + [ + { + Name: "unclaimed", + Unused: 1, + } + ], + 1, + ]); + + // Act + const result = await EffectHelper.GenerateEffectListEmbed("userId", 1); + + // Assert + expect(result).toMatchSnapshot(); + }); + + test("GIVEN user has more than 1 page of effects, EXPECT pagination enabled", async () => { + const effects: { + Name: string, + Unused: number, + }[] = []; + + for (let i = 0; i < 15; i++) { + effects.push({ + Name: "unclaimed", + Unused: 1, + }); + } + + // Arrange + (UserEffect.FetchAllByUserIdPaginated as jest.Mock).mockResolvedValue([ + effects, + 15, + ]); + + // Act + const result = await EffectHelper.GenerateEffectListEmbed("userId", 1); + + // Assert + expect(result).toMatchSnapshot(); + }); + + test("GIVEN user is on a page other than 1, EXPECT pagination enabled", async () => { + const effects: { + Name: string, + Unused: number, + }[] = []; + + for (let i = 0; i < 15; i++) { + effects.push({ + Name: "unclaimed", + Unused: 1, + }); + } + + // Arrange + (UserEffect.FetchAllByUserIdPaginated as jest.Mock).mockResolvedValue([ + effects, + 15, + ]); + + // Act + const result = await EffectHelper.GenerateEffectListEmbed("userId", 2); + + // Assert + expect(result).toMatchSnapshot(); + }); + + test("GIVEN user does NOT have an effect, EXPECT empty embed to be returned", async () => { + // Arrange + (UserEffect.FetchAllByUserIdPaginated as jest.Mock).mockResolvedValue([ + [], + 0, + ]); + + // Act + const result = await EffectHelper.GenerateEffectListEmbed("userId", 1); + + // Assert + expect(result).toMatchSnapshot(); + }); + + test("GIVEN there is an active effect, EXPECT field added", async () => { + // Arrange + (UserEffect.FetchAllByUserIdPaginated as jest.Mock).mockResolvedValue([ + [ + { + Name: "unclaimed", + Unused: 1, + } + ], + 1, + ]); + + (UserEffect.FetchActiveEffectByUserId as jest.Mock).mockResolvedValue({ + Name: "unclaimed", + WhenExpires: new Date(1738174052), + }); + + // Act + const result = await EffectHelper.GenerateEffectListEmbed("userId", 1); + + // Assert + expect(result).toMatchSnapshot(); + }); +}); + +describe("GenerateEffectBuyEmbed", () => { + test.todo("GIVEN Effect Details are not found, EXPECT error"); + + test.todo("GIVEN user is not in database, EXPECT blank user created"); + + test.todo("GIVEN user does not have enough currency, EXPECT error"); + + test.todo("GIVEN user does have enough currency, EXPECT embed returned"); + + test.todo("GIVEN disabled boolean is true, EXPECT buttons to be disabled"); +}); \ No newline at end of file diff --git a/tests/helpers/TimeLengthInput.test.ts b/tests/helpers/TimeLengthInput.test.ts new file mode 100644 index 0000000..6a23d67 --- /dev/null +++ b/tests/helpers/TimeLengthInput.test.ts @@ -0,0 +1,38 @@ +import TimeLengthInput from "../../src/helpers/TimeLengthInput"; + +describe("ConvertFromMilliseconds", () => { + test("EXPECT 1000ms to be outputted as a second", () => { + const timeLength = TimeLengthInput.ConvertFromMilliseconds(1000); + expect(timeLength.GetLengthShort()).toBe("1s"); + }); + + test("EXPECT 60000ms to be outputted as a minute", () => { + const timeLength = TimeLengthInput.ConvertFromMilliseconds(60000); + expect(timeLength.GetLengthShort()).toBe("1m"); + }); + + test("EXPECT 3600000ms to be outputted as an hour", () => { + const timeLength = TimeLengthInput.ConvertFromMilliseconds(3600000); + expect(timeLength.GetLengthShort()).toBe("1h"); + }); + + test("EXPECT 86400000ms to be outputted as a day", () => { + const timeLength = TimeLengthInput.ConvertFromMilliseconds(86400000); + expect(timeLength.GetLengthShort()).toBe("1d"); + }); + + test("EXPECT a combination to be outputted correctly", () => { + const timeLength = TimeLengthInput.ConvertFromMilliseconds(90061000); + expect(timeLength.GetLengthShort()).toBe("1d 1h 1m 1s"); + }); + + test("EXPECT 0ms to be outputted as empty", () => { + const timeLength = TimeLengthInput.ConvertFromMilliseconds(0); + expect(timeLength.GetLengthShort()).toBe(""); + }); + + test("EXPECT 123456789ms to be outputted correctly", () => { + const timeLength = TimeLengthInput.ConvertFromMilliseconds(123456789); + expect(timeLength.GetLengthShort()).toBe("1d 10h 17m 36s"); + }); +}); \ No newline at end of file diff --git a/tests/helpers/__snapshots__/EffectHelper.test.ts.snap b/tests/helpers/__snapshots__/EffectHelper.test.ts.snap new file mode 100644 index 0000000..fc3317e --- /dev/null +++ b/tests/helpers/__snapshots__/EffectHelper.test.ts.snap @@ -0,0 +1,216 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GenerateEffectListEmbed GIVEN there is an active effect, EXPECT field added 1`] = ` +{ + "embed": { + "color": 3166394, + "description": "Unclaimed Chance Up x1", + "fields": [ + { + "inline": true, + "name": "Active", + "value": "Unclaimed Chance Up", + }, + { + "inline": true, + "name": "Expires", + "value": "", + }, + ], + "footer": { + "icon_url": undefined, + "text": "Page 1 of 1", + }, + "title": "Effects", + }, + "row": { + "components": [ + { + "custom_id": "effects list 0", + "disabled": true, + "emoji": undefined, + "label": "Previous", + "style": 1, + "type": 2, + }, + { + "custom_id": "effects list 2", + "disabled": true, + "emoji": undefined, + "label": "Next", + "style": 1, + "type": 2, + }, + ], + "type": 1, + }, +} +`; + +exports[`GenerateEffectListEmbed GIVEN user does NOT have an effect, EXPECT empty embed to be returned 1`] = ` +{ + "embed": { + "color": 3166394, + "description": "*none*", + "footer": { + "icon_url": undefined, + "text": "Page 1 of 1", + }, + "title": "Effects", + }, + "row": { + "components": [ + { + "custom_id": "effects list 0", + "disabled": true, + "emoji": undefined, + "label": "Previous", + "style": 1, + "type": 2, + }, + { + "custom_id": "effects list 2", + "disabled": true, + "emoji": undefined, + "label": "Next", + "style": 1, + "type": 2, + }, + ], + "type": 1, + }, +} +`; + +exports[`GenerateEffectListEmbed GIVEN user has an effect, EXPECT detailed embed to be returned 1`] = ` +{ + "embed": { + "color": 3166394, + "description": "Unclaimed Chance Up x1", + "footer": { + "icon_url": undefined, + "text": "Page 1 of 1", + }, + "title": "Effects", + }, + "row": { + "components": [ + { + "custom_id": "effects list 0", + "disabled": true, + "emoji": undefined, + "label": "Previous", + "style": 1, + "type": 2, + }, + { + "custom_id": "effects list 2", + "disabled": true, + "emoji": undefined, + "label": "Next", + "style": 1, + "type": 2, + }, + ], + "type": 1, + }, +} +`; + +exports[`GenerateEffectListEmbed GIVEN user has more than 1 page of effects, EXPECT pagination enabled 1`] = ` +{ + "embed": { + "color": 3166394, + "description": "Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1", + "footer": { + "icon_url": undefined, + "text": "Page 1 of 2", + }, + "title": "Effects", + }, + "row": { + "components": [ + { + "custom_id": "effects list 0", + "disabled": true, + "emoji": undefined, + "label": "Previous", + "style": 1, + "type": 2, + }, + { + "custom_id": "effects list 2", + "disabled": false, + "emoji": undefined, + "label": "Next", + "style": 1, + "type": 2, + }, + ], + "type": 1, + }, +} +`; + +exports[`GenerateEffectListEmbed GIVEN user is on a page other than 1, EXPECT pagination enabled 1`] = ` +{ + "embed": { + "color": 3166394, + "description": "Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1 +Unclaimed Chance Up x1", + "footer": { + "icon_url": undefined, + "text": "Page 2 of 2", + }, + "title": "Effects", + }, + "row": { + "components": [ + { + "custom_id": "effects list 1", + "disabled": false, + "emoji": undefined, + "label": "Previous", + "style": 1, + "type": 2, + }, + { + "custom_id": "effects list 3", + "disabled": true, + "emoji": undefined, + "label": "Next", + "style": 1, + "type": 2, + }, + ], + "type": 1, + }, +} +`; diff --git a/tests/registry.test.ts b/tests/registry.test.ts deleted file mode 100644 index 71d80db..0000000 --- a/tests/registry.test.ts +++ /dev/null @@ -1,66 +0,0 @@ -import {CoreClient} from "../src/client/client"; -import Registry from "../src/registry"; -import fs from "fs"; -import path from "path"; - -describe("RegisterCommands", () => { - test("EXPECT every command in the commands folder to be registered", () => { - const registeredCommands: string[] = []; - - CoreClient.RegisterCommand = jest.fn().mockImplementation((name: string) => { - registeredCommands.push(name); - }); - - Registry.RegisterCommands(); - - const commandFiles = getFilesInDirectory(path.join(process.cwd(), "src", "commands")) - .filter(x => x.endsWith(".ts")); - - for (const file of commandFiles) { - expect(registeredCommands).toContain(file.split("/").pop()!.split(".")[0]); - } - - expect(commandFiles.length).toBe(registeredCommands.length); - }); -}); - -describe("RegisterButtonEvents", () => { - test("EXEPCT every button event in the button events folder to be registered", () => { - const registeredButtonEvents: string[] = []; - - CoreClient.RegisterButtonEvent = jest.fn().mockImplementation((name: string) => { - registeredButtonEvents.push(name); - }); - - Registry.RegisterButtonEvents(); - - const eventFiles = getFilesInDirectory(path.join(process.cwd(), "src", "buttonEvents")) - .filter(x => x.endsWith(".ts")); - - for (const file of eventFiles) { - expect(registeredButtonEvents).toContain(file.split("/").pop()!.split(".")[0].toLowerCase()); - } - - expect(eventFiles.length).toBe(registeredButtonEvents.length); - }); -}); - -function getFilesInDirectory(dir: string): string[] { - let results: string[] = []; - const list = fs.readdirSync(dir); - - list.forEach(file => { - file = path.join(dir, file); - const stat = fs.statSync(file); - - if (stat && stat.isDirectory()) { - /* recurse into a subdirectory */ - results = results.concat(getFilesInDirectory(file)); - } else { - /* is a file */ - results.push(file); - } - }); - - return results; -} diff --git a/tests/timers/PurgeClaims.test.ts b/tests/timers/PurgeClaims.test.ts new file mode 100644 index 0000000..6d0d09b --- /dev/null +++ b/tests/timers/PurgeClaims.test.ts @@ -0,0 +1,7 @@ +describe("PurgeClaims", () => { + test.todo("EXPECT claims to be fetched"); + + test.todo("EXPECT Claim.RemoveMany to remove the claims older than 2 minutes"); + + test.todo("EXPECT info logged"); +}); \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 23f0771..c63e681 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,155 +10,114 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.6.tgz#ab88da19344445c3d8889af2216606d3329f3ef2" - integrity sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.0.tgz#9374b5cd068d128dac0b94ff482594273b1c2815" + integrity sha512-INCKxTtbXtcNbUZ3YXutwMpEleqttcswhAdee7dhuoVrD2cnuc3PqtERBtxkX5nziX9vnBL8WXmSGwv8CuPV6g== dependencies: - "@babel/highlight" "^7.24.6" + "@babel/helper-validator-identifier" "^7.25.9" + js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/compat-data@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.6.tgz#b3600217688cabb26e25f8e467019e66d71b7ae2" - integrity sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ== +"@babel/compat-data@^7.25.9": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.0.tgz#f02ba6d34e88fadd5e8861e8b38902f43cc1c819" + integrity sha512-qETICbZSLe7uXv9VE8T/RWOdIE5qqyTucOt4zLYMafj2MRO271VGgLd4RACJMeBO37UPWhXiKMBk7YlJ0fOzQA== "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.6.tgz#8650e0e4b03589ebe886c4e4a60398db0a7ec787" - integrity sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ== + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.0.tgz#d78b6023cc8f3114ccf049eb219613f74a747b40" + integrity sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.24.6" - "@babel/generator" "^7.24.6" - "@babel/helper-compilation-targets" "^7.24.6" - "@babel/helper-module-transforms" "^7.24.6" - "@babel/helpers" "^7.24.6" - "@babel/parser" "^7.24.6" - "@babel/template" "^7.24.6" - "@babel/traverse" "^7.24.6" - "@babel/types" "^7.24.6" + "@babel/code-frame" "^7.26.0" + "@babel/generator" "^7.26.0" + "@babel/helper-compilation-targets" "^7.25.9" + "@babel/helper-module-transforms" "^7.26.0" + "@babel/helpers" "^7.26.0" + "@babel/parser" "^7.26.0" + "@babel/template" "^7.25.9" + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.26.0" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.24.6", "@babel/generator@^7.7.2": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.6.tgz#dfac82a228582a9d30c959fe50ad28951d4737a7" - integrity sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg== +"@babel/generator@^7.25.9", "@babel/generator@^7.26.0", "@babel/generator@^7.7.2": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.0.tgz#505cc7c90d92513f458a477e5ef0703e7c91b8d7" + integrity sha512-/AIkAmInnWwgEAJGQr9vY0c66Mj6kjkE2ZPB1PurTRaRAh3U+J45sAQMjQDJdh4WbR3l0x5xkimXBKyBXXAu2w== dependencies: - "@babel/types" "^7.24.6" + "@babel/parser" "^7.26.0" + "@babel/types" "^7.26.0" "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^2.5.1" + jsesc "^3.0.2" -"@babel/helper-compilation-targets@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz#4a51d681f7680043d38e212715e2a7b1ad29cb51" - integrity sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg== +"@babel/helper-compilation-targets@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz#55af025ce365be3cdc0c1c1e56c6af617ce88875" + integrity sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ== dependencies: - "@babel/compat-data" "^7.24.6" - "@babel/helper-validator-option" "^7.24.6" - browserslist "^4.22.2" + "@babel/compat-data" "^7.25.9" + "@babel/helper-validator-option" "^7.25.9" + browserslist "^4.24.0" lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-environment-visitor@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz#ac7ad5517821641550f6698dd5468f8cef78620d" - integrity sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g== - -"@babel/helper-function-name@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz#cebdd063386fdb95d511d84b117e51fc68fec0c8" - integrity sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w== +"@babel/helper-module-imports@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715" + integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== dependencies: - "@babel/template" "^7.24.6" - "@babel/types" "^7.24.6" + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" -"@babel/helper-hoist-variables@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz#8a7ece8c26756826b6ffcdd0e3cf65de275af7f9" - integrity sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA== +"@babel/helper-module-transforms@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" + integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== dependencies: - "@babel/types" "^7.24.6" + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@babel/traverse" "^7.25.9" -"@babel/helper-module-imports@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz#65e54ffceed6a268dc4ce11f0433b82cfff57852" - integrity sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g== +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.8.0": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz#9cbdd63a9443a2c92a725cca7ebca12cc8dd9f46" + integrity sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw== + +"@babel/helper-string-parser@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" + integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== + +"@babel/helper-validator-identifier@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" + integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== + +"@babel/helper-validator-option@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" + integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== + +"@babel/helpers@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.0.tgz#30e621f1eba5aa45fe6f4868d2e9154d884119a4" + integrity sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw== dependencies: - "@babel/types" "^7.24.6" + "@babel/template" "^7.25.9" + "@babel/types" "^7.26.0" -"@babel/helper-module-transforms@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz#22346ed9df44ce84dee850d7433c5b73fab1fe4e" - integrity sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA== +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.25.9", "@babel/parser@^7.26.0": + version "7.26.1" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.1.tgz#44e02499960df2cdce2c456372a3e8e0c3c5c975" + integrity sha512-reoQYNiAJreZNsJzyrDNzFQ+IQ5JFiIzAHJg9bn94S3l+4++J7RsIhNMoB+lgP/9tpmiAQqspv+xfdxTSzREOw== dependencies: - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-module-imports" "^7.24.6" - "@babel/helper-simple-access" "^7.24.6" - "@babel/helper-split-export-declaration" "^7.24.6" - "@babel/helper-validator-identifier" "^7.24.6" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.24.6", "@babel/helper-plugin-utils@^7.8.0": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.6.tgz#fa02a32410a15a6e8f8185bcbf608f10528d2a24" - integrity sha512-MZG/JcWfxybKwsA9N9PmtF2lOSFSEMVCpIRrbxccZFLJPrJciJdG/UhSh5W96GEteJI2ARqm5UAHxISwRDLSNg== - -"@babel/helper-simple-access@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz#1d6e04d468bba4fc963b4906f6dac6286cfedff1" - integrity sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-split-export-declaration@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz#e830068f7ba8861c53b7421c284da30ae656d7a3" - integrity sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-string-parser@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz#28583c28b15f2a3339cfafafeaad42f9a0e828df" - integrity sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q== - -"@babel/helper-validator-identifier@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz#08bb6612b11bdec78f3feed3db196da682454a5e" - integrity sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw== - -"@babel/helper-validator-option@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz#59d8e81c40b7d9109ab7e74457393442177f460a" - integrity sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ== - -"@babel/helpers@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.6.tgz#cd124245299e494bd4e00edda0e4ea3545c2c176" - integrity sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA== - dependencies: - "@babel/template" "^7.24.6" - "@babel/types" "^7.24.6" - -"@babel/highlight@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.6.tgz#6d610c1ebd2c6e061cade0153bf69b0590b7b3df" - integrity sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ== - dependencies: - "@babel/helper-validator-identifier" "^7.24.6" - chalk "^2.4.2" - js-tokens "^4.0.0" - picocolors "^1.0.0" - -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.6.tgz#5e030f440c3c6c78d195528c3b688b101a365328" - integrity sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q== + "@babel/types" "^7.26.0" "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -174,14 +133,28 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-class-properties@^7.8.3": +"@babel/plugin-syntax-class-properties@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-syntax-import-meta@^7.8.3": +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-import-attributes@^7.24.7": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz#3b1412847699eea739b4f2602c74ce36f6b0b0f7" + integrity sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-syntax-import-meta@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== @@ -196,13 +169,13 @@ "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-jsx@^7.7.2": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.6.tgz#bcca2964150437f88f65e3679e3d68762287b9c8" - integrity sha512-lWfvAIFNWMlCsU0DRUun2GpFwZdGTukLaHJqRh1JRb80NdAP5Sb1HDHB5X9P9OtgZHQl089UzQkpYlBq2VTPRw== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz#a34313a178ea56f1951599b929c1ceacee719290" + integrity sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== @@ -216,7 +189,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.8.3": +"@babel/plugin-syntax-numeric-separator@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== @@ -244,7 +217,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.8.3": +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== @@ -252,60 +232,47 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.7.2": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.6.tgz#769daf2982d60308bc83d8936eaecb7582463c87" - integrity sha512-TzCtxGgVTEJWWwcYwQhCIQ6WaKlo80/B+Onsk4RRCcYqpYGFcG9etPW94VToGte5AAcxRrhjPUFvUS3Y2qKi4A== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz#67dda2b74da43727cf21d46cf9afef23f4365399" + integrity sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/template@^7.24.6", "@babel/template@^7.3.3": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.6.tgz#048c347b2787a6072b24c723664c8d02b67a44f9" - integrity sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw== +"@babel/template@^7.25.9", "@babel/template@^7.3.3": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.9.tgz#ecb62d81a8a6f5dc5fe8abfc3901fc52ddf15016" + integrity sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg== dependencies: - "@babel/code-frame" "^7.24.6" - "@babel/parser" "^7.24.6" - "@babel/types" "^7.24.6" + "@babel/code-frame" "^7.25.9" + "@babel/parser" "^7.25.9" + "@babel/types" "^7.25.9" -"@babel/traverse@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.6.tgz#0941ec50cdeaeacad0911eb67ae227a4f8424edc" - integrity sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw== +"@babel/traverse@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.9.tgz#a50f8fe49e7f69f53de5bea7e413cd35c5e13c84" + integrity sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw== dependencies: - "@babel/code-frame" "^7.24.6" - "@babel/generator" "^7.24.6" - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-function-name" "^7.24.6" - "@babel/helper-hoist-variables" "^7.24.6" - "@babel/helper-split-export-declaration" "^7.24.6" - "@babel/parser" "^7.24.6" - "@babel/types" "^7.24.6" + "@babel/code-frame" "^7.25.9" + "@babel/generator" "^7.25.9" + "@babel/parser" "^7.25.9" + "@babel/template" "^7.25.9" + "@babel/types" "^7.25.9" debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.24.6", "@babel/types@^7.3.3": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.6.tgz#ba4e1f59870c10dc2fa95a274ac4feec23b21912" - integrity sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ== +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.25.9", "@babel/types@^7.26.0", "@babel/types@^7.3.3": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.0.tgz#deabd08d6b753bc8e0f198f8709fb575e31774ff" + integrity sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA== dependencies: - "@babel/helper-string-parser" "^7.24.6" - "@babel/helper-validator-identifier" "^7.24.6" - to-fast-properties "^2.0.0" + "@babel/helper-string-parser" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@bconnorwhite/module@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@bconnorwhite/module/-/module-2.0.2.tgz#557846110bb89412e9689ac778358bc2b1af0c4a" - integrity sha512-ck1me5WMgZKp06gnJrVKEkytpehTTQbvsAMbF1nGPeHri/AZNhj87++PSE2LOxmZqM0EtGMaqeLdx7Lw7SUnTA== - dependencies: - find-up "^5.0.0" - read-json-safe "^1.0.5" - types-pkg-json "^1.1.0" - "@colors/colors@1.6.0", "@colors/colors@^1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0" @@ -320,57 +287,57 @@ enabled "2.0.x" kuler "^2.0.0" -"@discordjs/builders@^1.8.2": - version "1.8.2" - resolved "https://registry.yarnpkg.com/@discordjs/builders/-/builders-1.8.2.tgz#535d970331ee40f20dec9ef8079e43092f323ce9" - integrity sha512-6wvG3QaCjtMu0xnle4SoOIeFB4y6fKMN6WZfy3BMKJdQQtPLik8KGzDwBVL/+wTtcE/ZlFjgEk74GublyEVZ7g== +"@discordjs/builders@^1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@discordjs/builders/-/builders-1.9.0.tgz#71fa6de91132bd1deaff2a9daea7aa5d5c9f124a" + integrity sha512-0zx8DePNVvQibh5ly5kCEei5wtPBIUbSoE9n+91Rlladz4tgtFbJ36PZMxxZrTEOQ7AHMZ/b0crT/0fCy6FTKg== dependencies: - "@discordjs/formatters" "^0.4.0" - "@discordjs/util" "^1.1.0" - "@sapphire/shapeshift" "^3.9.7" - discord-api-types "0.37.83" + "@discordjs/formatters" "^0.5.0" + "@discordjs/util" "^1.1.1" + "@sapphire/shapeshift" "^4.0.0" + discord-api-types "0.37.97" fast-deep-equal "^3.1.3" ts-mixer "^6.0.4" - tslib "^2.6.2" + tslib "^2.6.3" "@discordjs/collection@1.5.3": version "1.5.3" resolved "https://registry.yarnpkg.com/@discordjs/collection/-/collection-1.5.3.tgz#5a1250159ebfff9efa4f963cfa7e97f1b291be18" integrity sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ== -"@discordjs/collection@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@discordjs/collection/-/collection-2.1.0.tgz#f327d944ab2dcf9a1f674470a481f78a120a5e3b" - integrity sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw== +"@discordjs/collection@^2.1.0", "@discordjs/collection@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@discordjs/collection/-/collection-2.1.1.tgz#901917bc538c12b9c3613036d317847baee08cae" + integrity sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg== -"@discordjs/formatters@^0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@discordjs/formatters/-/formatters-0.4.0.tgz#066a2c2163b26ac066e6f621f17445be9690c6a9" - integrity sha512-fJ06TLC1NiruF35470q3Nr1bi95BdvKFAF+T5bNfZJ4bNdqZ3VZ+Ttg6SThqTxm6qumSG3choxLBHMC69WXNXQ== +"@discordjs/formatters@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@discordjs/formatters/-/formatters-0.5.0.tgz#2d284c4271bc41984339936df1d0164e470f3b7a" + integrity sha512-98b3i+Y19RFq1Xke4NkVY46x8KjJQjldHUuEbCqMvp1F5Iq9HgnGpu91jOi/Ufazhty32eRsKnnzS8n4c+L93g== dependencies: - discord-api-types "0.37.83" + discord-api-types "0.37.97" -"@discordjs/rest@^2.0.0", "@discordjs/rest@^2.3.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@discordjs/rest/-/rest-2.3.0.tgz#06d37c7fb54a9be61134b5bbb201abd760343472" - integrity sha512-C1kAJK8aSYRv3ZwMG8cvrrW4GN0g5eMdP8AuN8ODH5DyOCbHgJspze1my3xHOAgwLJdKUbWNVyAeJ9cEdduqIg== +"@discordjs/rest@^2.0.0", "@discordjs/rest@^2.3.0", "@discordjs/rest@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@discordjs/rest/-/rest-2.4.0.tgz#63bfc816af58af844914e3589d7eae609cd199b5" + integrity sha512-Xb2irDqNcq+O8F0/k/NaDp7+t091p+acb51iA4bCKfIn+WFWd6HrNvcsSbMMxIR9NjcMZS6NReTKygqiQN+ntw== dependencies: - "@discordjs/collection" "^2.1.0" - "@discordjs/util" "^1.1.0" - "@sapphire/async-queue" "^1.5.2" + "@discordjs/collection" "^2.1.1" + "@discordjs/util" "^1.1.1" + "@sapphire/async-queue" "^1.5.3" "@sapphire/snowflake" "^3.5.3" - "@vladfrangu/async_event_emitter" "^2.2.4" - discord-api-types "0.37.83" + "@vladfrangu/async_event_emitter" "^2.4.6" + discord-api-types "0.37.97" magic-bytes.js "^1.10.0" - tslib "^2.6.2" - undici "6.13.0" + tslib "^2.6.3" + undici "6.19.8" -"@discordjs/util@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@discordjs/util/-/util-1.1.0.tgz#dcffd2b61aab8eadd66bea67811bc34fc769bb2a" - integrity sha512-IndcI5hzlNZ7GS96RV3Xw1R2kaDuXEp7tRIy/KlhidpN/BQ1qh1NZt3377dMLTa44xDUNKT7hnXkA/oUAzD/lg== +"@discordjs/util@^1.1.0", "@discordjs/util@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@discordjs/util/-/util-1.1.1.tgz#bafcde0faa116c834da1258d78ec237080bbab29" + integrity sha512-eddz6UnOBEB1oITPinyrB2Pttej49M9FZQY8NxgEvc3tq6ZICZ19m70RsmzRdDHk80O9NoYN/25AqJl8vPVf/g== -"@discordjs/ws@^1.1.1": +"@discordjs/ws@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@discordjs/ws/-/ws-1.1.1.tgz#bffbfd46838258ab09054ed98ddef1a36f6507a3" integrity sha512-PZ+vLpxGCRtmr2RMkqh8Zp+BenUaJqlS6xhgWKEZcgC/vfHLEzpHtKkB0sl3nZWpwtcKk6YWy+pU3okL2I97FA== @@ -386,65 +353,90 @@ ws "^8.16.0" "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" - integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + version "4.4.1" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56" + integrity sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA== dependencies: - eslint-visitor-keys "^3.3.0" + eslint-visitor-keys "^3.4.3" -"@eslint-community/regexpp@^4.10.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.0.tgz#b0ffd0312b4a3fd2d6f77237e7248a5ad3a680ae" - integrity sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A== +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.11.0": + version "4.12.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" + integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== -"@eslint-community/regexpp@^4.6.1": - version "4.10.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.1.tgz#361461e5cb3845d874e61731c11cfedd664d83a0" - integrity sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA== +"@eslint/config-array@^0.18.0": + version "0.18.0" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.18.0.tgz#37d8fe656e0d5e3dbaea7758ea56540867fd074d" + integrity sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw== + dependencies: + "@eslint/object-schema" "^2.1.4" + debug "^4.3.1" + minimatch "^3.1.2" -"@eslint/eslintrc@^2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" - integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== +"@eslint/core@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.7.0.tgz#a1bb4b6a4e742a5ff1894b7ee76fbf884ec72bd3" + integrity sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw== + +"@eslint/eslintrc@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.1.0.tgz#dbd3482bfd91efa663cbe7aa1f506839868207b6" + integrity sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.6.0" - globals "^13.19.0" + espree "^10.0.1" + globals "^14.0.0" ignore "^5.2.0" import-fresh "^3.2.1" js-yaml "^4.1.0" minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.57.0": - version "8.57.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" - integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== +"@eslint/js@9.13.0": + version "9.13.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.13.0.tgz#c5f89bcd57eb54d5d4fa8b77693e9c28dc97e547" + integrity sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA== -"@humanwhocodes/config-array@^0.11.14": - version "0.11.14" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" - integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== +"@eslint/object-schema@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.4.tgz#9e69f8bb4031e11df79e03db09f9dbbae1740843" + integrity sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ== + +"@eslint/plugin-kit@^0.2.0": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.1.tgz#cd14fe2db79fa639839dfef4105e83bad1814482" + integrity sha512-HFZ4Mp26nbWk9d/BpvP0YNL6W4UoZF0VFcTw/aPPA8RpOxeFQgK+ClABGgAUXs9Y/RGX/l1vOmrqz1MQt9MNuw== dependencies: - "@humanwhocodes/object-schema" "^2.0.2" - debug "^4.3.1" - minimatch "^3.0.5" + levn "^0.4.1" + +"@humanfs/core@^0.19.0": + version "0.19.0" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.0.tgz#08db7a8c73bb07673d9ebd925f2dad746411fcec" + integrity sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw== + +"@humanfs/node@^0.16.5": + version "0.16.5" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.5.tgz#a9febb7e7ad2aff65890fdc630938f8d20aa84ba" + integrity sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg== + dependencies: + "@humanfs/core" "^0.19.0" + "@humanwhocodes/retry" "^0.3.0" "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/object-schema@^2.0.2": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" - integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== +"@humanwhocodes/retry@^0.3.0", "@humanwhocodes/retry@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" + integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== "@inquirer/figures@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.3.tgz#1227cc980f88e6d6ab85abadbf164f5038041edd" - integrity sha512-ErXXzENMH5pJt5/ssXV0DfWUZqly8nGzf0UcBV9xTnP+KyffE2mqyxIMBrZ8ijQck2nU0TQm40EQB53YreyWHw== + version "1.0.7" + resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.7.tgz#d050ccc0eabfacc0248c4ff647a9dfba1b01594b" + integrity sha512-m+Trk77mp54Zma6xLkLuY+mvanPxlE4A7yNKs2HBiyZ4UkVs28Mv5c/pgWrHeInx+USHeX/WEPzjrWrcJiQgjw== "@isaacs/cliui@^8.0.2": version "8.0.2" @@ -959,9 +951,9 @@ integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": version "0.3.25" @@ -971,13 +963,6 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@ljharb/through@^2.3.13": - version "2.3.13" - resolved "https://registry.yarnpkg.com/@ljharb/through/-/through-2.3.13.tgz#b7e4766e0b65aa82e529be945ab078de79874edc" - integrity sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ== - dependencies: - call-bind "^1.0.7" - "@mapbox/node-pre-gyp@^1.0.0": version "1.0.11" resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa" @@ -1006,7 +991,7 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": +"@nodelib/fs.walk@^1.2.3": version "1.2.8" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== @@ -1032,9 +1017,9 @@ graceful-fs "4.2.10" "@pnpm/npm-conf@^2.1.0": - version "2.2.2" - resolved "https://registry.yarnpkg.com/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz#0058baf1c26cbb63a828f0193795401684ac86f0" - integrity sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA== + version "2.3.1" + resolved "https://registry.yarnpkg.com/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz#bb375a571a0bd63ab0a23bece33033c683e9b6b0" + integrity sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw== dependencies: "@pnpm/config.env-replace" "^1.1.0" "@pnpm/network.ca-file" "^1.0.1" @@ -1047,15 +1032,15 @@ dependencies: any-observable "^0.3.0" -"@sapphire/async-queue@^1.5.2": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@sapphire/async-queue/-/async-queue-1.5.2.tgz#2982dce16e5b8b1ea792604d20c23c0585877b97" - integrity sha512-7X7FFAA4DngXUl95+hYbUF19bp1LGiffjJtu7ygrZrbdCSsdDDBaSjB7Akw0ZbOu6k0xpXyljnJ6/RZUvLfRdg== +"@sapphire/async-queue@^1.5.2", "@sapphire/async-queue@^1.5.3": + version "1.5.3" + resolved "https://registry.yarnpkg.com/@sapphire/async-queue/-/async-queue-1.5.3.tgz#03cd2a2f3665068f314736bdc56eee2025352422" + integrity sha512-x7zadcfJGxFka1Q3f8gCts1F0xMwCKbZweM85xECGI0hBTeIZJGGCrHgLggihBoprlQ/hBmDR5LKfIPqnmHM3w== -"@sapphire/shapeshift@^3.9.7": - version "3.9.7" - resolved "https://registry.yarnpkg.com/@sapphire/shapeshift/-/shapeshift-3.9.7.tgz#43e23243cac8a0c046bf1e73baf3dbf407d33a0c" - integrity sha512-4It2mxPSr4OGn4HSQWGmhFMsNFGfFVhWeRPCRwbH972Ek2pzfGRZtb0pJ4Ze6oIzcyh2jw7nUDa6qGlWofgd9g== +"@sapphire/shapeshift@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@sapphire/shapeshift/-/shapeshift-4.0.0.tgz#86c1b41002ff5d0b2ad21cbc3418b06834b89040" + integrity sha512-d9dUmWVA7MMiKobL3VpLF8P2aeanRTu6ypG2OIaEv/ZHH/SUQ2iHOVyi5wAPjQ+HmnMuL0whK9ez8I/raWbtIg== dependencies: fast-deep-equal "^3.1.3" lodash "^4.17.21" @@ -1070,16 +1055,6 @@ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== -"@sindresorhus/is@^4.0.0": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" - integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== - -"@sindresorhus/is@^5.2.0", "@sindresorhus/is@^5.3.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-5.6.0.tgz#41dd6093d34652cddb5d5bdeee04eafc33826668" - integrity sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g== - "@sinonjs/commons@^3.0.0": version "3.0.1" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" @@ -1099,20 +1074,6 @@ resolved "https://registry.yarnpkg.com/@sqltools/formatter/-/formatter-1.2.5.tgz#3abc203c79b8c3e90fd6c156a0c62d5403520e12" integrity sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw== -"@szmarczak/http-timer@^4.0.5": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" - integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w== - dependencies: - defer-to-connect "^2.0.0" - -"@szmarczak/http-timer@^5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-5.0.1.tgz#c7c1bf1141cdd4751b0399c8fc7b8b664cd5be3a" - integrity sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw== - dependencies: - defer-to-connect "^2.0.1" - "@tokenizer/token@^0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276" @@ -1159,16 +1120,6 @@ "@types/connect" "*" "@types/node" "*" -"@types/cacheable-request@^6.0.1": - version "6.0.3" - resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" - integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw== - dependencies: - "@types/http-cache-semantics" "*" - "@types/keyv" "^3.1.4" - "@types/node" "*" - "@types/responselike" "^1.0.0" - "@types/clone-deep@^4.0.4": version "4.0.4" resolved "https://registry.yarnpkg.com/@types/clone-deep/-/clone-deep-4.0.4.tgz#6932f2d0a4b4ef337d97cb72e6ecdf091c05145d" @@ -1181,23 +1132,28 @@ dependencies: "@types/node" "*" -"@types/express-serve-static-core@^4.17.33": - version "4.19.3" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.3.tgz#e469a13e4186c9e1c0418fb17be8bc8ff1b19a7a" - integrity sha512-KOzM7MhcBFlmnlr/fzISFF5vGWVSvN6fTd4T+ExOt08bA/dA5kpSzY52nMsI1KDFmUREpJelPYyuslLRSjjgCg== +"@types/estree@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" + integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== + +"@types/express-serve-static-core@^5.0.0": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-5.0.1.tgz#3c9997ae9d00bc236e45c6374e84f2596458d9db" + integrity sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA== dependencies: "@types/node" "*" "@types/qs" "*" "@types/range-parser" "*" "@types/send" "*" -"@types/express@^4.17.20": - version "4.17.21" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" - integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== +"@types/express@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@types/express/-/express-5.0.0.tgz#13a7d1f75295e90d19ed6e74cab3678488eaa96c" + integrity sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ== dependencies: "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.33" + "@types/express-serve-static-core" "^5.0.0" "@types/qs" "*" "@types/serve-static" "*" @@ -1208,11 +1164,6 @@ dependencies: "@types/node" "*" -"@types/http-cache-semantics@*", "@types/http-cache-semantics@^4.0.2": - version "4.0.4" - resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz#b979ebad3919799c979b17c72621c0bc0a31c6c4" - integrity sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA== - "@types/http-errors@*": version "2.0.4" resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" @@ -1237,20 +1188,18 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@^29.0.0": - version "29.5.12" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.12.tgz#7f7dc6eb4cf246d2474ed78744b05d06ce025544" - integrity sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw== +"@types/jest@^29.5.14": + version "29.5.14" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.14.tgz#2b910912fa1d6856cadcd0c1f95af7df1d6049e5" + integrity sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ== dependencies: expect "^29.0.0" pretty-format "^29.0.0" -"@types/keyv@^3.1.4": - version "3.1.4" - resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" - integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg== - dependencies: - "@types/node" "*" +"@types/json-schema@^7.0.15": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== "@types/luxon@~3.4.0": version "3.4.2" @@ -1262,47 +1211,33 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== -"@types/node@*": - version "20.14.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.9.tgz#12e8e765ab27f8c421a1820c99f5f313a933b420" - integrity sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg== +"@types/node@*", "@types/node@^22.8.1": + version "22.8.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.8.1.tgz#b39d4b98165e2ae792ce213f610c7c6108ccfa16" + integrity sha512-k6Gi8Yyo8EtrNtkHXutUu2corfDf9su95VYVP10aGYMMROM6SAItZi0w1XszA6RtWTHSVp5OeFof37w0IEqCQg== dependencies: - undici-types "~5.26.4" + undici-types "~6.19.8" "@types/node@16.9.1": version "16.9.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-16.9.1.tgz#0611b37db4246c937feef529ddcc018cf8e35708" integrity sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g== -"@types/node@^20.0.0": - version "20.14.11" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.11.tgz#09b300423343460455043ddd4d0ded6ac579b74b" - integrity sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA== - dependencies: - undici-types "~5.26.4" - "@types/normalize-package-data@^2.4.3": version "2.4.4" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== "@types/qs@*": - version "6.9.15" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.15.tgz#adde8a060ec9c305a82de1babc1056e73bd64dce" - integrity sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg== + version "6.9.16" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.16.tgz#52bba125a07c0482d26747d5d4947a64daf8f794" + integrity sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A== "@types/range-parser@*": version "1.2.7" resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== -"@types/responselike@^1.0.0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.3.tgz#cc29706f0a397cfe6df89debfe4bf5cea159db50" - integrity sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw== - dependencies: - "@types/node" "*" - "@types/send@*": version "0.17.4" resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" @@ -1330,15 +1265,15 @@ resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.5.tgz#74fef9ffbaa198eb8b588be029f38b00299caa2c" integrity sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw== -"@types/uuid@^9.0.0": - version "9.0.8" - resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba" - integrity sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA== +"@types/uuid@^10.0.0": + version "10.0.0" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-10.0.0.tgz#e9c07fe50da0f53dc24970cca94d619ff03f6f6d" + integrity sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ== "@types/ws@^8.5.10": - version "8.5.10" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.10.tgz#4acfb517970853fa6574a3a6886791d04a396787" - integrity sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A== + version "8.5.12" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.12.tgz#619475fe98f35ccca2a2f6c137702d85ec247b7e" + integrity sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ== dependencies: "@types/node" "*" @@ -1348,143 +1283,110 @@ integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== "@types/yargs@^17.0.8": - version "17.0.32" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" - integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== + version "17.0.33" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.33.tgz#8c32303da83eec050a84b3c7ae7b9f922d13e32d" + integrity sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA== dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^7.0.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.15.0.tgz#8eaf396ac2992d2b8f874b68eb3fcd6b179cb7f3" - integrity sha512-uiNHpyjZtFrLwLDpHnzaDlP3Tt6sGMqTCiqmxaN4n4RP0EfYZDODJyddiFDF44Hjwxr5xAcaYxVKm9QKQFJFLA== +"@typescript-eslint/eslint-plugin@8.11.0", "@typescript-eslint/eslint-plugin@^8.11.0": + version "8.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.11.0.tgz#c3f087d20715fa94310b30666c08b3349e0ab084" + integrity sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA== dependencies: "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "7.15.0" - "@typescript-eslint/type-utils" "7.15.0" - "@typescript-eslint/utils" "7.15.0" - "@typescript-eslint/visitor-keys" "7.15.0" + "@typescript-eslint/scope-manager" "8.11.0" + "@typescript-eslint/type-utils" "8.11.0" + "@typescript-eslint/utils" "8.11.0" + "@typescript-eslint/visitor-keys" "8.11.0" graphemer "^1.4.0" ignore "^5.3.1" natural-compare "^1.4.0" ts-api-utils "^1.3.0" -"@typescript-eslint/parser@^6.16.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b" - integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ== +"@typescript-eslint/parser@8.11.0", "@typescript-eslint/parser@^8.11.0": + version "8.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.11.0.tgz#2ad1481388dc1c937f50b2d138c9ca57cc6c5cce" + integrity sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg== dependencies: - "@typescript-eslint/scope-manager" "6.21.0" - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/typescript-estree" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" + "@typescript-eslint/scope-manager" "8.11.0" + "@typescript-eslint/types" "8.11.0" + "@typescript-eslint/typescript-estree" "8.11.0" + "@typescript-eslint/visitor-keys" "8.11.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1" - integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg== +"@typescript-eslint/scope-manager@8.11.0": + version "8.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.11.0.tgz#9d399ce624118966732824878bc9a83593a30405" + integrity sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ== dependencies: - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" + "@typescript-eslint/types" "8.11.0" + "@typescript-eslint/visitor-keys" "8.11.0" -"@typescript-eslint/scope-manager@7.15.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.15.0.tgz#201b34b0720be8b1447df17b963941bf044999b2" - integrity sha512-Q/1yrF/XbxOTvttNVPihxh1b9fxamjEoz2Os/Pe38OHwxC24CyCqXxGTOdpb4lt6HYtqw9HetA/Rf6gDGaMPlw== +"@typescript-eslint/type-utils@8.11.0": + version "8.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.11.0.tgz#b7f9e6120c1ddee8a1a07615646642ad85fc91b5" + integrity sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg== dependencies: - "@typescript-eslint/types" "7.15.0" - "@typescript-eslint/visitor-keys" "7.15.0" - -"@typescript-eslint/type-utils@7.15.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.15.0.tgz#5b83c904c6de91802fb399305a50a56d10472c39" - integrity sha512-SkgriaeV6PDvpA6253PDVep0qCqgbO1IOBiycjnXsszNTVQe5flN5wR5jiczoEoDEnAqYFSFFc9al9BSGVltkg== - dependencies: - "@typescript-eslint/typescript-estree" "7.15.0" - "@typescript-eslint/utils" "7.15.0" + "@typescript-eslint/typescript-estree" "8.11.0" + "@typescript-eslint/utils" "8.11.0" debug "^4.3.4" ts-api-utils "^1.3.0" -"@typescript-eslint/types@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d" - integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg== +"@typescript-eslint/types@8.11.0": + version "8.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.11.0.tgz#7c766250502097f49bbc2e651132e6bf489e20b8" + integrity sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw== -"@typescript-eslint/types@7.15.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.15.0.tgz#fb894373a6e3882cbb37671ffddce44f934f62fc" - integrity sha512-aV1+B1+ySXbQH0pLK0rx66I3IkiZNidYobyfn0WFsdGhSXw+P3YOqeTq5GED458SfB24tg+ux3S+9g118hjlTw== - -"@typescript-eslint/typescript-estree@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46" - integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ== +"@typescript-eslint/typescript-estree@8.11.0": + version "8.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz#35fe5d3636fc5727c52429393415412e552e222b" + integrity sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg== dependencies: - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" + "@typescript-eslint/types" "8.11.0" + "@typescript-eslint/visitor-keys" "8.11.0" debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "9.0.3" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/typescript-estree@7.15.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.15.0.tgz#e323bfa3966e1485b638ce751f219fc1f31eba37" - integrity sha512-gjyB/rHAopL/XxfmYThQbXbzRMGhZzGw6KpcMbfe8Q3nNQKStpxnUKeXb0KiN/fFDR42Z43szs6rY7eHk0zdGQ== - dependencies: - "@typescript-eslint/types" "7.15.0" - "@typescript-eslint/visitor-keys" "7.15.0" - debug "^4.3.4" - globby "^11.1.0" + fast-glob "^3.3.2" is-glob "^4.0.3" minimatch "^9.0.4" semver "^7.6.0" ts-api-utils "^1.3.0" -"@typescript-eslint/utils@7.15.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.15.0.tgz#9e6253c4599b6e7da2fb64ba3f549c73eb8c1960" - integrity sha512-hfDMDqaqOqsUVGiEPSMLR/AjTSCsmJwjpKkYQRo1FNbmW4tBwBspYDwO9eh7sKSTwMQgBw9/T4DHudPaqshRWA== +"@typescript-eslint/utils@8.11.0": + version "8.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.11.0.tgz#4480d1e9f2bb18ea3510c79f870a1aefc118103d" + integrity sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g== dependencies: "@eslint-community/eslint-utils" "^4.4.0" - "@typescript-eslint/scope-manager" "7.15.0" - "@typescript-eslint/types" "7.15.0" - "@typescript-eslint/typescript-estree" "7.15.0" + "@typescript-eslint/scope-manager" "8.11.0" + "@typescript-eslint/types" "8.11.0" + "@typescript-eslint/typescript-estree" "8.11.0" -"@typescript-eslint/visitor-keys@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47" - integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A== +"@typescript-eslint/visitor-keys@8.11.0": + version "8.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.11.0.tgz#273de1cbffe63d9f9cd7dfc20b5a5af66310cb92" + integrity sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw== dependencies: - "@typescript-eslint/types" "6.21.0" - eslint-visitor-keys "^3.4.1" - -"@typescript-eslint/visitor-keys@7.15.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.15.0.tgz#1da0726201a859343fe6a05742a7c1792fff5b66" - integrity sha512-Hqgy/ETgpt2L5xueA/zHHIl4fJI2O4XUE9l4+OIfbJIRSnTJb/QscncdqqZzofQegIJugRIF57OJea1khw2SDw== - dependencies: - "@typescript-eslint/types" "7.15.0" + "@typescript-eslint/types" "8.11.0" eslint-visitor-keys "^3.4.3" -"@ungap/structured-clone@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" - integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== - -"@vladfrangu/async_event_emitter@^2.2.4": - version "2.2.4" - resolved "https://registry.yarnpkg.com/@vladfrangu/async_event_emitter/-/async_event_emitter-2.2.4.tgz#d3537432c6db6444680a596271dff8ea407343b3" - integrity sha512-ButUPz9E9cXMLgvAW8aLAKKJJsPu1dY1/l/E8xzLFuysowXygs6GBcyunK9rnGC4zTsnIc2mQo71rGw9U+Ykug== +"@vladfrangu/async_event_emitter@^2.2.4", "@vladfrangu/async_event_emitter@^2.4.6": + version "2.4.6" + resolved "https://registry.yarnpkg.com/@vladfrangu/async_event_emitter/-/async_event_emitter-2.4.6.tgz#508b6c45b03f917112a9008180b308ba0e4d1805" + integrity sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA== abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -1498,10 +1400,10 @@ acorn-jsx@^5.3.2: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.9.0: - version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== +acorn@^8.12.0: + version "8.14.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" + integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== agent-base@6: version "6.0.2" @@ -1528,17 +1430,6 @@ ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -all-package-names@^2.0.2: - version "2.0.897" - resolved "https://registry.yarnpkg.com/all-package-names/-/all-package-names-2.0.897.tgz#d672ca5d9566eef046b996523dec84b21512e20c" - integrity sha512-ZWd7bk4fK2Doei5nLP28ytHa5hTD+qr8bWuJQh1Bbi36Ij4RVXSL6tM0zEni85usEhX0iQ32IuYlyoYM0sKFyQ== - dependencies: - commander-version "^1.1.0" - p-lock "^2.0.0" - parse-json-object "^2.0.1" - progress "^2.0.3" - types-json "^1.2.2" - ansi-align@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" @@ -1586,9 +1477,9 @@ ansi-regex@^5.0.1: integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + version "6.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" + integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== ansi-styles@^2.2.1: version "2.2.1" @@ -1614,7 +1505,7 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -ansi-styles@^6.1.0: +ansi-styles@^6.1.0, ansi-styles@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== @@ -1677,21 +1568,24 @@ array-flatten@1.1.1: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - async@^3.2.3: - version "3.2.5" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.5.tgz#ebd52a8fdaf7a2289a24df399f8d8485c8a46b66" - integrity sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg== + 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.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== +atomically@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/atomically/-/atomically-2.0.3.tgz#27e47bbe39994d324918491ba7c0edb7783e56cb" + integrity sha512-kU6FmrwZ3Lx7/7y3hPS5QnbJfaohcIul5fGqf7ok+4KklIEk9tJ0C2IQPdacSbVUWv6zVHXEBWoWd6NrVMT7Cw== + dependencies: + stubborn-fs "^1.2.5" + when-exit "^2.1.1" + await-to-js@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/await-to-js/-/await-to-js-3.0.0.tgz#70929994185616f4675a91af6167eb61cc92868f" @@ -1741,22 +1635,25 @@ babel-plugin-jest-hoist@^29.6.3: "@types/babel__traverse" "^7.0.6" babel-preset-current-node-syntax@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" - integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + version "1.1.0" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz#9a929eafece419612ef4ae4f60b1862ebad8ef30" + integrity sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw== dependencies: "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.8.3" - "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-import-attributes" "^7.24.7" + "@babel/plugin-syntax-import-meta" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-top-level-await" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" babel-preset-jest@^29.6.3: version "29.6.3" @@ -1776,11 +1673,6 @@ base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -big-integer@^1.6.44: - version "1.6.52" - resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" - integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg== - bignumber.js@9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075" @@ -1800,10 +1692,10 @@ bmp-ts@^1.0.9: resolved "https://registry.yarnpkg.com/bmp-ts/-/bmp-ts-1.0.9.tgz#0fd124ba812be9b786b29e5b186ee76d74ff5538" integrity sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw== -body-parser@1.20.2, body-parser@^1.20.2: - version "1.20.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" - integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== +body-parser@1.20.3, body-parser@^1.20.2: + version "1.20.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" + integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g== dependencies: bytes "3.1.2" content-type "~1.0.5" @@ -1813,31 +1705,24 @@ body-parser@1.20.2, body-parser@^1.20.2: http-errors "2.0.0" iconv-lite "0.4.24" on-finished "2.4.1" - qs "6.11.0" + qs "6.13.0" raw-body "2.5.2" type-is "~1.6.18" unpipe "1.0.0" -boxen@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-7.1.1.tgz#f9ba525413c2fec9cdb88987d835c4f7cad9c8f4" - integrity sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog== +boxen@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-8.0.1.tgz#7e9fcbb45e11a2d7e6daa8fdcebfc3242fc19fe3" + integrity sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw== dependencies: ansi-align "^3.0.1" - camelcase "^7.0.1" - chalk "^5.2.0" + camelcase "^8.0.0" + chalk "^5.3.0" cli-boxes "^3.0.0" - string-width "^5.1.2" - type-fest "^2.13.0" - widest-line "^4.0.1" - wrap-ansi "^8.1.0" - -bplist-parser@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.2.0.tgz#43a9d183e5bf9d545200ceac3e712f79ebbe8d0e" - integrity sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw== - dependencies: - big-integer "^1.6.44" + string-width "^7.2.0" + type-fest "^4.21.0" + widest-line "^5.0.0" + wrap-ansi "^9.0.0" brace-expansion@^1.1.7: version "1.1.11" @@ -1861,17 +1746,17 @@ braces@^3.0.3: dependencies: fill-range "^7.1.1" -browserslist@^4.22.2: - version "4.23.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" - integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== +browserslist@^4.24.0: + version "4.24.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.2.tgz#f5845bc91069dbd55ee89faf9822e1d885d16580" + integrity sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg== dependencies: - caniuse-lite "^1.0.30001587" - electron-to-chromium "^1.4.668" - node-releases "^2.0.14" - update-browserslist-db "^1.0.13" + caniuse-lite "^1.0.30001669" + electron-to-chromium "^1.5.41" + node-releases "^2.0.18" + update-browserslist-db "^1.1.1" -bs-logger@0.x: +bs-logger@^0.2.6: version "0.2.6" resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== @@ -1906,59 +1791,18 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -builtins@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" - integrity sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ== - -bundle-name@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-3.0.0.tgz#ba59bcc9ac785fb67ccdbf104a2bf60c099f0e1a" - integrity sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw== +bundle-name@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-4.1.0.tgz#f3b96b34160d6431a19d7688135af7cfb8797889" + integrity sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q== dependencies: - run-applescript "^5.0.0" + run-applescript "^7.0.0" bytes@3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -cacheable-lookup@^5.0.3: - version "5.0.4" - resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" - integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== - -cacheable-lookup@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz#3476a8215d046e5a3202a9209dd13fec1f933a27" - integrity sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w== - -cacheable-request@^10.2.8: - version "10.2.14" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-10.2.14.tgz#eb915b665fda41b79652782df3f553449c406b9d" - integrity sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ== - dependencies: - "@types/http-cache-semantics" "^4.0.2" - get-stream "^6.0.1" - http-cache-semantics "^4.1.1" - keyv "^4.5.3" - mimic-response "^4.0.0" - normalize-url "^8.0.0" - responselike "^3.0.0" - -cacheable-request@^7.0.2: - version "7.0.4" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.4.tgz#7a33ebf08613178b403635be7b899d3e69bbe817" - integrity sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^4.0.0" - lowercase-keys "^2.0.0" - normalize-url "^6.0.1" - responselike "^2.0.0" - call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" @@ -1983,11 +1827,6 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -callsites@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-4.1.0.tgz#de72b98612eed4e1e2564c952498677faa9d86c2" - integrity sha512-aBMbD1Xxay75ViYezwT40aQONfr+pSXTHwNKvIXhXD6+LY3F1dLIcceoC5OZKBVHbXcysz1hL9D2w0JJIMXpUw== - camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" @@ -1998,15 +1837,15 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -camelcase@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-7.0.1.tgz#f02e50af9fd7782bc8b88a3558c32fd3a388f048" - integrity sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw== +camelcase@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-8.0.0.tgz#c0d36d418753fb6ad9c5e0437579745c1c14a534" + integrity sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA== -caniuse-lite@^1.0.30001587: - version "1.0.30001627" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001627.tgz#8071c42d468e06ed2fb2c545efe79a663fd326ab" - integrity sha512-4zgNiB8nTyV/tHhwZrFs88ryjls/lHiqFhrxCW4qSTeuRByBVnPYpDInchOIySWknznucaf31Z4KYqjfbrecVw== +caniuse-lite@^1.0.30001669: + version "1.0.30001673" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001673.tgz#5aa291557af1c71340e809987367410aab7a5a9e" + integrity sha512-WTrjUCSMp3LYX0nE12ECkV0a+e6LC85E0Auz75555/qr78Oc8YWhEPNfDd6SHdtlCMSzqtuXY0uyEMNRcsKpKw== canvas@^2.11.2: version "2.11.2" @@ -2044,7 +1883,7 @@ chalk@^2.4.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: +chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -2078,9 +1917,9 @@ ci-info@^3.2.0: integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== cjs-module-lexer@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz#c485341ae8fd999ca4ee5af2d7a1c9ae01e0099c" - integrity sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q== + version "1.4.1" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz#707413784dbb3a72aa11c2f2b042a0bef4004170" + integrity sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA== clean-stack@^4.0.0: version "4.2.0" @@ -2175,13 +2014,6 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" -clone-response@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" - integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== - dependencies: - mimic-response "^1.0.0" - clone@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" @@ -2267,19 +2099,6 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" -commander-version@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/commander-version/-/commander-version-1.1.0.tgz#fbfaea4632921a42f8f855f96bcaa3d9920a6296" - integrity sha512-9aNW4N6q6EPDUszLRH6k9IwO6OoGYh3HRgUF/fA7Zs+Mz1v1x5akSqT7QGB8JsGY7AG7qMA7oRRB/4yyn33FYA== - dependencies: - "@bconnorwhite/module" "^2.0.2" - commander "^6.1.0" - -commander@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" - integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== - component-emitter@^1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.1.tgz#ef1d5796f7d93f135ee6fb684340b26403c97d17" @@ -2298,16 +2117,15 @@ config-chain@^1.1.11: ini "^1.3.4" proto-list "~1.2.1" -configstore@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-6.0.0.tgz#49eca2ebc80983f77e09394a1a56e0aca8235566" - integrity sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA== +configstore@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-7.0.0.tgz#4461561fc51cb40e5ee1161230bc0337e069cc6b" + integrity sha512-yk7/5PN5im4qwz0WFZW3PXnzHgPu9mX29Y8uZ3aefe2lBPC1FYttWZRcaW9fKkT0pBCJyuQ2HfbmPVaODi9jcQ== dependencies: - dot-prop "^6.0.1" - graceful-fs "^4.2.6" - unique-string "^3.0.0" - write-file-atomic "^3.0.3" - xdg-basedir "^5.0.1" + atomically "^2.0.3" + dot-prop "^9.0.0" + graceful-fs "^4.2.11" + xdg-basedir "^5.1.0" console-control-strings@^1.0.0, console-control-strings@^1.1.0: version "1.1.0" @@ -2336,10 +2154,10 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookie@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" - integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== +cookie@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9" + integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w== cookiejar@^2.1.2: version "2.1.4" @@ -2391,22 +2209,15 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -crypto-random-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-4.0.0.tgz#5a3cc53d7dd86183df5da0312816ceeeb5bb1fc2" - integrity sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA== - dependencies: - type-fest "^1.0.1" - date-fns@^1.27.2: version "1.30.1" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== dayjs@^1.11.9: - version "1.11.11" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.11.tgz#dfe0e9d54c5f8b68ccf8ca5f72ac603e7e5ed59e" - integrity sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg== + version "1.11.13" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" + integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== debug@2.6.9: version "2.6.9" @@ -2416,11 +2227,11 @@ debug@2.6.9: ms "2.0.0" debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: - version "4.3.5" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" - integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== dependencies: - ms "2.1.2" + ms "^2.1.3" decompress-response@^4.2.0: version "4.2.1" @@ -2429,13 +2240,6 @@ decompress-response@^4.2.0: dependencies: mimic-response "^2.0.0" -decompress-response@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" - integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== - dependencies: - mimic-response "^3.1.0" - dedent@^1.0.0: version "1.5.3" resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.3.tgz#99aee19eb9bae55a67327717b6e848d0bf777e5a" @@ -2456,23 +2260,18 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== -default-browser-id@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-3.0.0.tgz#bee7bbbef1f4e75d31f98f4d3f1556a14cea790c" - integrity sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA== - dependencies: - bplist-parser "^0.2.0" - untildify "^4.0.0" +default-browser-id@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-5.0.0.tgz#a1d98bf960c15082d8a3fa69e83150ccccc3af26" + integrity sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA== -default-browser@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-4.0.0.tgz#53c9894f8810bf86696de117a6ce9085a3cbc7da" - integrity sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA== +default-browser@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-5.2.1.tgz#7b7ba61204ff3e425b556869ae6d3e9d9f1712cf" + integrity sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg== dependencies: - bundle-name "^3.0.0" - default-browser-id "^3.0.0" - execa "^7.1.1" - titleize "^3.0.0" + bundle-name "^4.1.0" + default-browser-id "^5.0.0" defaults@^1.0.3: version "1.0.4" @@ -2481,11 +2280,6 @@ defaults@^1.0.3: dependencies: clone "^1.0.2" -defer-to-connect@^2.0.0, defer-to-connect@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" - integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== - define-data-property@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" @@ -2556,49 +2350,45 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +discord-api-types@0.37.100: + version "0.37.100" + resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.37.100.tgz#5979892d39511bc7f1dbb9660d2d2cad698b3de7" + integrity sha512-a8zvUI0GYYwDtScfRd/TtaNBDTXwP5DiDVX7K5OmE+DRT57gBqKnwtOC5Ol8z0mRW8KQfETIgiB8U0YZ9NXiCA== + discord-api-types@0.37.83: version "0.37.83" resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.37.83.tgz#a22a799729ceded8176ea747157837ddf4708b1f" integrity sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA== -discord.js@^14.15.3: - version "14.15.3" - resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-14.15.3.tgz#b2a67a1a4ef192be498fb8b6784224a42906f1be" - integrity sha512-/UJDQO10VuU6wQPglA4kz2bw2ngeeSbogiIPx/TsnctfzV/tNf+q+i1HlgtX1OGpeOBpJH9erZQNO5oRM2uAtQ== +discord-api-types@0.37.97: + version "0.37.97" + resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.37.97.tgz#d658573f726ad179261d538dbad4e7e8eca48d11" + integrity sha512-No1BXPcVkyVD4ZVmbNgDKaBoqgeQ+FJpzZ8wqHkfmBnTZig1FcH3iPPersiK1TUIAzgClh2IvOuVUYfcWLQAOA== + +discord.js@^14.16.3: + version "14.16.3" + resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-14.16.3.tgz#9553366953c992469f47a55af2a11c2054a9babe" + integrity sha512-EPCWE9OkA9DnFFNrO7Kl1WHHDYFXu3CNVFJg63bfU7hVtjZGyhShwZtSBImINQRWxWP2tgo2XI+QhdXx28r0aA== dependencies: - "@discordjs/builders" "^1.8.2" + "@discordjs/builders" "^1.9.0" "@discordjs/collection" "1.5.3" - "@discordjs/formatters" "^0.4.0" - "@discordjs/rest" "^2.3.0" - "@discordjs/util" "^1.1.0" - "@discordjs/ws" "^1.1.1" + "@discordjs/formatters" "^0.5.0" + "@discordjs/rest" "^2.4.0" + "@discordjs/util" "^1.1.1" + "@discordjs/ws" "1.1.1" "@sapphire/snowflake" "3.5.3" - discord-api-types "0.37.83" + discord-api-types "0.37.100" fast-deep-equal "3.1.3" lodash.snakecase "4.1.1" - tslib "2.6.2" - undici "6.13.0" + tslib "^2.6.3" + undici "6.19.8" -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== +dot-prop@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-9.0.0.tgz#bae5982fe6dc6b8fddb92efef4f2ddff26779e92" + integrity sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ== dependencies: - esutils "^2.0.2" - -dot-prop@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-6.0.1.tgz#fc26b3cf142b9e59b74dbd39ed66ce620c681083" - integrity sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA== - dependencies: - is-obj "^2.0.0" - -dot-prop@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-7.2.0.tgz#468172a3529779814d21a779c1ba2f6d76609809" - integrity sha512-Ol/IPXUARn9CSbkrdV4VJo7uCy1I3VuSiWCaFSg+8BdUOzF9n3jefIpcgAydvUZbTdEBZs2vEiTiS9m61ssiDA== - dependencies: - type-fest "^2.11.2" + type-fest "^4.18.2" dotenv@^16.0.0, dotenv@^16.0.3: version "16.4.5" @@ -2624,10 +2414,17 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.4.668: - version "1.4.788" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.788.tgz#a3545959d5cfa0a266d3e551386c040be34e7e06" - integrity sha512-ubp5+Ev/VV8KuRoWnfP2QF2Bg+O2ZFdb49DiiNbz2VmgkIqrnyYaqIOqj8A6K/3p1xV0QcU5hBQ1+BmB6ot1OA== +ejs@^3.1.10: + version "3.1.10" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b" + integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA== + dependencies: + jake "^10.8.5" + +electron-to-chromium@^1.5.41: + version "1.5.47" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.47.tgz#ef0751bc19b28be8ee44cd8405309de3bf3b20c7" + integrity sha512-zS5Yer0MOYw4rtK2iq43cJagHZ8sXN0jDHDKzB+86gSBSAI4v07S97mcq+Gs2vclAxSh1j7vOAHxSVgduiiuVQ== elegant-spinner@^1.0.1: version "1.0.1" @@ -2639,6 +2436,11 @@ emittery@^0.13.1: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== +emoji-regex@^10.3.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.4.0.tgz#03553afea80b3975749cfcb36f776ca268e413d4" + integrity sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -2659,12 +2461,10 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" +encodeurl@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== error-ex@^1.3.1: version "1.3.2" @@ -2707,11 +2507,16 @@ es-set-tostringtag@^2.1.0: has-tostringtag "^1.0.2" hasown "^2.0.2" -escalade@^3.1.1, escalade@^3.1.2: +escalade@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== +escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + escape-goat@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-4.0.0.tgz#9424820331b510b0666b98f7873fe11ac4aa8081" @@ -2742,81 +2547,83 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -eslint-scope@^7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" - integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== +eslint-scope@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.1.0.tgz#70214a174d4cbffbc3e8a26911d8bf51b9ae9d30" + integrity sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: +eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint@^8.56.0: - version "8.57.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" - integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== +eslint-visitor-keys@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz#1f785cc5e81eb7534523d85922248232077d2f8c" + integrity sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg== + +eslint@^9.13.0: + version "9.13.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.13.0.tgz#7659014b7dda1ff876ecbd990f726e11c61596e6" + integrity sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA== dependencies: "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.57.0" - "@humanwhocodes/config-array" "^0.11.14" + "@eslint-community/regexpp" "^4.11.0" + "@eslint/config-array" "^0.18.0" + "@eslint/core" "^0.7.0" + "@eslint/eslintrc" "^3.1.0" + "@eslint/js" "9.13.0" + "@eslint/plugin-kit" "^0.2.0" + "@humanfs/node" "^0.16.5" "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - "@ungap/structured-clone" "^1.2.0" + "@humanwhocodes/retry" "^0.3.1" + "@types/estree" "^1.0.6" + "@types/json-schema" "^7.0.15" ajv "^6.12.4" chalk "^4.0.0" cross-spawn "^7.0.2" debug "^4.3.2" - doctrine "^3.0.0" escape-string-regexp "^4.0.0" - eslint-scope "^7.2.2" - eslint-visitor-keys "^3.4.3" - espree "^9.6.1" - esquery "^1.4.2" + eslint-scope "^8.1.0" + eslint-visitor-keys "^4.1.0" + espree "^10.2.0" + esquery "^1.5.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" + file-entry-cache "^8.0.0" find-up "^5.0.0" glob-parent "^6.0.2" - globals "^13.19.0" - graphemer "^1.4.0" ignore "^5.2.0" imurmurhash "^0.1.4" is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" lodash.merge "^4.6.2" minimatch "^3.1.2" natural-compare "^1.4.0" optionator "^0.9.3" - strip-ansi "^6.0.1" text-table "^0.2.0" -espree@^9.6.0, espree@^9.6.1: - version "9.6.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" - integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== +espree@^10.0.1, espree@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.2.0.tgz#f4bcead9e05b0615c968e85f83816bc386a45df6" + integrity sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g== dependencies: - acorn "^8.9.0" + acorn "^8.12.0" acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.1" + eslint-visitor-keys "^4.1.0" esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== +esquery@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== dependencies: estraverse "^5.1.0" @@ -2842,6 +2649,16 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + 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@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -2857,21 +2674,6 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -execa@^7.1.1: - version "7.2.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-7.2.0.tgz#657e75ba984f42a70f38928cedc87d6f2d4fe4e9" - integrity sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.1" - human-signals "^4.3.0" - is-stream "^3.0.0" - merge-stream "^2.0.0" - npm-run-path "^5.1.0" - onetime "^6.0.0" - signal-exit "^3.0.7" - strip-final-newline "^3.0.0" - execa@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c" @@ -2914,36 +2716,36 @@ expect@^29.0.0, expect@^29.7.0: jest-util "^29.7.0" express@^4.18.2: - version "4.19.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" - integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== + version "4.21.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.21.1.tgz#9dae5dda832f16b4eec941a4e44aa89ec481b281" + integrity sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ== dependencies: accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.20.2" + body-parser "1.20.3" content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.6.0" + cookie "0.7.1" cookie-signature "1.0.6" debug "2.6.9" depd "2.0.0" - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "1.2.0" + finalhandler "1.3.1" fresh "0.5.2" http-errors "2.0.0" - merge-descriptors "1.0.1" + merge-descriptors "1.0.3" methods "~1.1.2" on-finished "2.4.1" parseurl "~1.3.3" - path-to-regexp "0.1.7" + path-to-regexp "0.1.10" proxy-addr "~2.0.7" - qs "6.11.0" + qs "6.13.0" range-parser "~1.2.1" safe-buffer "5.2.1" - send "0.18.0" - serve-static "1.15.0" + send "0.19.0" + serve-static "1.16.2" setprototypeof "1.2.0" statuses "2.0.1" type-is "~1.6.18" @@ -2964,7 +2766,7 @@ fast-deep-equal@3.1.3, fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.2.9, fast-glob@^3.3.0: +fast-glob@^3.3.0, fast-glob@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== @@ -3036,12 +2838,12 @@ figures@^3.0.0: dependencies: escape-string-regexp "^1.0.5" -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== dependencies: - flat-cache "^3.0.4" + flat-cache "^4.0.0" file-stream-rotator@^0.6.1: version "0.6.1" @@ -3059,6 +2861,13 @@ file-type@^16.0.0: strtok3 "^6.2.4" token-types "^4.1.1" +filelist@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5" + integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q== + dependencies: + minimatch "^5.0.1" + fill-range@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" @@ -3066,13 +2875,13 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" -finalhandler@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== +finalhandler@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019" + integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ== dependencies: debug "2.6.9" - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" on-finished "2.4.1" parseurl "~1.3.3" @@ -3100,14 +2909,13 @@ find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" -flat-cache@^3.0.4: - version "3.2.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" - integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== dependencies: flatted "^3.2.9" - keyv "^4.5.3" - rimraf "^3.0.2" + keyv "^4.5.4" flatted@^3.2.9: version "3.3.1" @@ -3120,27 +2928,22 @@ fn.name@1.x.x: integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== follow-redirects@^1.15.6: - version "1.15.6" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" - integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== + version "1.15.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== foreground-child@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.2.1.tgz#767004ccf3a5b30df39bed90718bab43fe0a59f7" - integrity sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA== + version "3.3.0" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77" + integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg== dependencies: cross-spawn "^7.0.0" signal-exit "^4.0.1" -form-data-encoder@^2.1.2: - version "2.1.4" - resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-2.1.4.tgz#261ea35d2a70d48d30ec7a9603130fa5515e9cd5" - integrity sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw== - form-data@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" - integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + version "3.0.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.2.tgz#83ad9ced7c03feaad97e293d6f6091011e1659c8" + integrity sha512-sJe+TQb2vIaIyO783qN6BlMYWMw3WBOHA1Ay2qxsnjuafEOQFJ2JakedOQirT6D5XPRxDvS7AHYyem9fTpb4LQ== dependencies: asynckit "^0.4.0" combined-stream "^1.0.8" @@ -3193,6 +2996,11 @@ function-bind@^1.1.2: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== +fuse.js@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-7.0.0.tgz#6573c9fcd4c8268e403b4fc7d7131ffcf99a9eb2" + integrity sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q== + gauge@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" @@ -3218,6 +3026,11 @@ get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-east-asian-width@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz#21b4071ee58ed04ee0db653371b55b4299875389" + integrity sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ== + get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" @@ -3258,14 +3071,7 @@ get-proto@^1.0.1: dunder-proto "^1.0.1" es-object-atoms "^1.0.0" -get-stream@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - -get-stream@^6.0.0, get-stream@^6.0.1: +get-stream@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== @@ -3314,6 +3120,18 @@ glob@^10.3.10: package-json-from-dist "^1.0.0" path-scurry "^1.11.1" +glob@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-11.0.0.tgz#6031df0d7b65eaa1ccb9b29b5ced16cea658e77e" + integrity sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g== + dependencies: + foreground-child "^3.1.0" + jackspeak "^4.0.1" + minimatch "^10.0.0" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^2.0.0" + glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -3333,36 +3151,15 @@ global-directory@^4.0.1: dependencies: ini "4.1.1" -global-dirs@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.1.tgz#0c488971f066baceda21447aecb1a8b911d22485" - integrity sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA== - dependencies: - ini "2.0.0" - globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^13.19.0: - version "13.24.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" - integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== - dependencies: - type-fest "^0.20.2" - -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== globby@^13.1.2: version "13.2.2" @@ -3387,46 +3184,12 @@ gopd@^1.2.0: resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== -got@^11.8.5: - version "11.8.6" - resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" - integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g== - dependencies: - "@sindresorhus/is" "^4.0.0" - "@szmarczak/http-timer" "^4.0.5" - "@types/cacheable-request" "^6.0.1" - "@types/responselike" "^1.0.0" - cacheable-lookup "^5.0.3" - cacheable-request "^7.0.2" - decompress-response "^6.0.0" - http2-wrapper "^1.0.0-beta.5.2" - lowercase-keys "^2.0.0" - p-cancelable "^2.0.0" - responselike "^2.0.0" - -got@^12.1.0: - version "12.6.1" - resolved "https://registry.yarnpkg.com/got/-/got-12.6.1.tgz#8869560d1383353204b5a9435f782df9c091f549" - integrity sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ== - dependencies: - "@sindresorhus/is" "^5.2.0" - "@szmarczak/http-timer" "^5.0.1" - cacheable-lookup "^7.0.0" - cacheable-request "^10.2.8" - decompress-response "^6.0.0" - form-data-encoder "^2.1.2" - get-stream "^6.0.1" - http2-wrapper "^2.1.10" - lowercase-keys "^3.0.0" - p-cancelable "^3.0.0" - responselike "^3.0.0" - graceful-fs@4.2.10: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== -graceful-fs@^4.2.10, graceful-fs@^4.2.6, graceful-fs@^4.2.9: +graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -3487,11 +3250,6 @@ has-unicode@^2.0.1: resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== -has-yarn@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-3.0.0.tgz#c3c21e559730d1d3b57e28af1f30d06fac38147d" - integrity sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA== - hasown@^2.0.0, hasown@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" @@ -3516,11 +3274,6 @@ html-escaper@^2.0.0: resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" - integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== - http-errors@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" @@ -3532,22 +3285,6 @@ http-errors@2.0.0: statuses "2.0.1" toidentifier "1.0.1" -http2-wrapper@^1.0.0-beta.5.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" - integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== - dependencies: - quick-lru "^5.1.1" - resolve-alpn "^1.0.0" - -http2-wrapper@^2.1.10: - version "2.2.1" - resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-2.2.1.tgz#310968153dcdedb160d8b72114363ef5fce1f64a" - integrity sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ== - dependencies: - quick-lru "^5.1.1" - resolve-alpn "^1.2.0" - https-proxy-agent@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -3561,11 +3298,6 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -human-signals@^4.3.0: - version "4.3.1" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" - integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== - human-signals@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" @@ -3583,7 +3315,7 @@ ieee754@^1.1.13, ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore-walk@^6.0.3: +ignore-walk@^6.0.4: version "6.0.5" resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-6.0.5.tgz#ef8d61eab7da169078723d1f82833b36e200b0dd" integrity sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A== @@ -3591,9 +3323,9 @@ ignore-walk@^6.0.3: minimatch "^9.0.0" ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" - integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== image-q@^4.0.0: version "4.0.0" @@ -3610,15 +3342,10 @@ import-fresh@^3.2.1, import-fresh@^3.3.0: parent-module "^1.0.0" resolve-from "^4.0.0" -import-lazy@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153" - integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw== - import-local@^3.0.2, import-local@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" - integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + version "3.2.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" + integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== dependencies: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" @@ -3656,11 +3383,6 @@ inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, i resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -ini@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" - integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== - ini@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ini/-/ini-4.1.1.tgz#d95b3d843b1e906e56d6747d5447904ff50ce7a1" @@ -3718,19 +3440,15 @@ inquirer@^7.0.0: strip-ansi "^6.0.0" through "^2.3.6" -inquirer@^9.2.12: - version "9.2.23" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-9.2.23.tgz#cd2fe34edca12315b624fbc3c8cb99b1c4f61f90" - integrity sha512-kod5s+FBPIDM2xiy9fu+6wdU/SkK5le5GS9lh4FEBjBHqiMgD9lLFbCbuqFNAjNL2ZOy9Wd9F694IOzN9pZHBA== +inquirer@^9.2.15: + version "9.3.7" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-9.3.7.tgz#0b562bf843812208844741c9aec9244c939b83d4" + integrity sha512-LJKFHCSeIRq9hanN14IlOtPSTe3lNES7TYDTE2xxdAy1LS5rYphajK1qtwvj3YmQXvvk0U2Vbmcni8P9EIQW9w== dependencies: "@inquirer/figures" "^1.0.3" - "@ljharb/through" "^2.3.13" ansi-escapes "^4.3.2" - chalk "^5.3.0" - cli-cursor "^3.1.0" cli-width "^4.1.0" external-editor "^3.1.0" - lodash "^4.17.21" mute-stream "1.0.0" ora "^5.4.1" run-async "^3.0.0" @@ -3738,6 +3456,7 @@ inquirer@^9.2.12: string-width "^4.2.3" strip-ansi "^6.0.1" wrap-ansi "^6.2.0" + yoctocolors-cjs "^2.1.2" ipaddr.js@1.9.1: version "1.9.1" @@ -3754,17 +3473,12 @@ is-arrayish@^0.3.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== -is-core-module@^2.13.0, is-core-module@^2.8.1: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== +is-core-module@^2.13.0: + version "2.15.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37" + integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ== dependencies: - hasown "^2.0.0" - -is-docker@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + hasown "^2.0.2" is-docker@^3.0.0: version "3.0.0" @@ -3805,10 +3519,10 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: dependencies: is-extglob "^2.1.1" -is-in-ci@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-in-ci/-/is-in-ci-0.1.0.tgz#5e07d6a02ec3a8292d3f590973357efa3fceb0d3" - integrity sha512-d9PXLEY0v1iJ64xLiQMJ51J128EYHAaOR4yZqQi8aHGfw6KgifM3/Viw1oZZ1GCVmb3gBuyhLyHj0HgR2DhSXQ== +is-in-ci@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-in-ci/-/is-in-ci-1.0.0.tgz#9a86bbda7e42c6129902e0574c54b018fbb6ab88" + integrity sha512-eUuAjybVTHMYWm/U+vBO1sY/JOCgoPCXRxzdju0K+K0BiGW0SChEL1MLC0PoCIR1OlPo5YAp8HuQoUlsWEICwg== is-inside-container@^1.0.0: version "1.0.0" @@ -3817,14 +3531,6 @@ is-inside-container@^1.0.0: dependencies: is-docker "^3.0.0" -is-installed-globally@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" - integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ== - dependencies: - global-dirs "^3.0.0" - is-path-inside "^3.0.2" - is-installed-globally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-1.0.0.tgz#08952c43758c33d815692392f7f8437b9e436d5a" @@ -3843,15 +3549,6 @@ is-interactive@^2.0.0: resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-2.0.0.tgz#40c57614593826da1100ade6059778d597f16e90" integrity sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ== -is-name-taken@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-name-taken/-/is-name-taken-2.0.0.tgz#c36e6515e07621dc48cd026b6b015a504942fae1" - integrity sha512-W+FUWF5g7ONVJTx3rldZeVizmPzrMMUdscpSQ96vyYerx+4b2NcqaujLJJDWruGzE0FjzGZO9RFIipOGxx/WIw== - dependencies: - all-package-names "^2.0.2" - package-name-conflict "^1.0.3" - validate-npm-package-name "^3.0.0" - is-npm@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-6.0.0.tgz#b59e75e8915543ca5d881ecff864077cba095261" @@ -3862,11 +3559,6 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" - integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== - is-observable@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e" @@ -3879,11 +3571,6 @@ is-path-cwd@^3.0.0: resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-3.0.0.tgz#889b41e55c8588b1eb2a96a61d05740a674521c7" integrity sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA== -is-path-inside@^3.0.2, is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - is-path-inside@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-4.0.0.tgz#805aeb62c47c1b12fc3fd13bfb3ed1e7430071db" @@ -3923,11 +3610,6 @@ is-stream@^3.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== -is-typedarray@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== - is-unicode-supported@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" @@ -3943,12 +3625,12 @@ is-url-superb@^6.1.0: resolved "https://registry.yarnpkg.com/is-url-superb/-/is-url-superb-6.1.0.tgz#182f0d92b482412afeadfba8e6ea2c76680e3631" integrity sha512-LXdhGlYqUPdvEyIhWPEEwYYK3yrUiPcBjmFGlZNv1u5GtIL5qQRf7ddDyPNAvsMFqdzS923FROpTQU97tLe3JQ== -is-wsl@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== +is-wsl@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-3.1.0.tgz#e1c657e39c10090afcbedec61720f6b924c3cbd2" + integrity sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw== dependencies: - is-docker "^2.0.0" + is-inside-container "^1.0.0" isarray@~1.0.0: version "1.0.0" @@ -3966,9 +3648,9 @@ isobject@^3.0.1: integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== issue-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/issue-regex/-/issue-regex-4.1.0.tgz#e2039123748a48e6711eed7a9eb392f2c17c9341" - integrity sha512-X3HBmm7+Th+l4/kMtqwcHHgELD0Lfl0Ina6S3+grr+mKmTxsrM84NAO1UuRPIxIbGLIl3TCEu45S1kdu21HYbQ== + version "4.3.0" + resolved "https://registry.yarnpkg.com/issue-regex/-/issue-regex-4.3.0.tgz#e73db1b475fa12b93ddc66c36ebd5a5f57d0d838" + integrity sha512-7731a/t2llyrk8Hdwl1x3LkhIFGzxHQGpJA7Ur9cIRViakQF2y25Lwhx8Ziy1B068+kBYUmYPBzw5uo3DdWrdQ== istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: version "3.2.2" @@ -3987,9 +3669,9 @@ istanbul-lib-instrument@^5.0.4: semver "^6.3.0" istanbul-lib-instrument@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz#91655936cf7380e4e473383081e38478b69993b1" - integrity sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw== + version "6.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765" + integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== dependencies: "@babel/core" "^7.23.9" "@babel/parser" "^7.23.9" @@ -4032,6 +3714,23 @@ jackspeak@^3.1.2: optionalDependencies: "@pkgjs/parseargs" "^0.11.0" +jackspeak@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-4.0.2.tgz#11f9468a3730c6ff6f56823a820d7e3be9bef015" + integrity sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw== + dependencies: + "@isaacs/cliui" "^8.0.2" + +jake@^10.8.5: + version "10.9.2" + resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.2.tgz#6ae487e6a69afec3a5e167628996b59f35ae2b7f" + integrity sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA== + dependencies: + async "^3.2.3" + chalk "^4.0.2" + filelist "^1.0.4" + minimatch "^3.1.2" + jest-changed-files@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" @@ -4455,10 +4154,10 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +jsesc@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" + integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== json-buffer@3.0.1: version "3.0.1" @@ -4485,7 +4184,7 @@ json5@^2.2.3: resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== -keyv@^4.0.0, keyv@^4.5.3: +keyv@^4.5.4: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== @@ -4507,12 +4206,17 @@ kuler@^2.0.0: resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== -latest-version@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-7.0.0.tgz#843201591ea81a4d404932eeb61240fe04e9e5da" - integrity sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg== +ky@^1.2.0: + version "1.7.2" + resolved "https://registry.yarnpkg.com/ky/-/ky-1.7.2.tgz#b97d9b997ba51ff1e152f0815d3d27b86513eb1c" + integrity sha512-OzIvbHKKDpi60TnF9t7UUVAF1B4mcqc02z5PIvrm08Wyb+yOcz63GRvEuVxNT18a9E1SrNouhB4W2NNLeD7Ykg== + +latest-version@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-9.0.0.tgz#e91ed216e7a4badc6f73b66c65adb46c58ec6ba1" + integrity sha512-7W0vV3rqv5tokqkBAFV1LbR7HPOWzXQDpDgEuib/aJ1jsZZx6x3c2mBI+TJhJzOhkGeaLbCKEHXEXLfirtG2JA== dependencies: - package-json "^8.1.0" + package-json "^10.0.0" leven@^3.1.0: version "3.1.0" @@ -4600,12 +4304,7 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lodash.isequal@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== - -lodash.memoize@4.x: +lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== @@ -4685,26 +4384,16 @@ logform@^2.6.0, logform@^2.6.1: safe-stable-stringify "^2.3.1" triple-beam "^1.3.0" -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - -lowercase-keys@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" - integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== - -lru-cache@^10.0.1: - version "10.2.2" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878" - integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ== - -lru-cache@^10.2.0: +lru-cache@^10.0.1, lru-cache@^10.2.0: version "10.4.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== +lru-cache@^11.0.0: + version "11.0.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.0.1.tgz#3a732fbfedb82c5ba7bca6564ad3f42afcb6e147" + integrity sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -4736,7 +4425,7 @@ make-dir@^4.0.0: dependencies: semver "^7.5.3" -make-error@1.x: +make-error@^1.3.6: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -4758,15 +4447,15 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== -meow@^12.1.1: - version "12.1.1" - resolved "https://registry.yarnpkg.com/meow/-/meow-12.1.1.tgz#e558dddbab12477b69b2e9a2728c327f191bace6" - integrity sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw== +meow@^13.2.0: + version "13.2.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-13.2.0.tgz#6b7d63f913f984063b3cc261b6e8800c4cd3474f" + integrity sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA== -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== +merge-descriptors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" + integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ== merge-stream@^2.0.0: version "2.0.0" @@ -4784,9 +4473,9 @@ methods@^1.1.2, methods@~1.1.2: integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== micromatch@^4.0.4: - version "4.0.7" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" - integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== dependencies: braces "^3.0.3" picomatch "^2.3.1" @@ -4838,51 +4527,36 @@ mimic-function@^5.0.0: resolved "https://registry.yarnpkg.com/mimic-function/-/mimic-function-5.0.1.tgz#acbe2b3349f99b9deaca7fb70e48b83e94e67076" integrity sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA== -mimic-response@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - mimic-response@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== -mimic-response@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" - integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== - -mimic-response@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-4.0.0.tgz#35468b19e7c75d10f5165ea25e75a5ceea7cf70f" - integrity sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg== - -minimatch@9.0.3: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - -minimatch@9.0.5, minimatch@^9.0.4: +minimatch@9.0.5, minimatch@^9.0.0, minimatch@^9.0.4: version "9.0.5" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== dependencies: brace-expansion "^2.0.1" -minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: +minimatch@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.1.tgz#ce0521856b453c86e25f2c4c0d03e6ff7ddc440b" + integrity sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimatch@^9.0.0: - version "9.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" - integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== dependencies: brace-expansion "^2.0.1" @@ -4936,12 +4610,7 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3, ms@^2.1.1: +ms@2.1.3, ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -4981,9 +4650,9 @@ mz@^2.4.0: thenify-all "^1.0.0" nan@^2.17.0: - version "2.20.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.20.0.tgz#08c5ea813dd54ed16e5bd6505bf42af4f7838ca3" - integrity sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw== + version "2.22.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.22.0.tgz#31bc433fc33213c97bad36404bb68063de604de3" + integrity sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw== natural-compare@^1.4.0: version "1.4.0" @@ -5014,10 +4683,10 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== -node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== +node-releases@^2.0.18: + version "2.0.18" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" + integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== nopt@^5.0.0: version "5.0.0" @@ -5027,12 +4696,11 @@ nopt@^5.0.0: abbrev "1" normalize-package-data@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-6.0.1.tgz#fa69e9452210f0fabf4d79ee08d0c2870c51ed88" - integrity sha512-6rvCfeRW+OEZagAB4lMLSNuTNYZWLVtKccK79VSTf//yTY5VOCgcpH80O+bZK8Neps7pUnd5G+QlMg1yV/2iZQ== + version "6.0.2" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-6.0.2.tgz#a7bc22167fe24025412bcff0a9651eb768b03506" + integrity sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g== dependencies: hosted-git-info "^7.0.0" - is-core-module "^2.8.1" semver "^7.3.5" validate-npm-package-license "^3.0.4" @@ -5041,20 +4709,10 @@ normalize-path@^3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -normalize-url@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" - integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== - -normalize-url@^8.0.0: - version "8.0.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-8.0.1.tgz#9b7d96af9836577c58f5883e939365fa15623a4a" - integrity sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w== - -np@^9.0.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/np/-/np-9.2.0.tgz#93323e1535b47317f02885e726f2aa0f41c14ac8" - integrity sha512-VYA8IKyx5XJqROr2vu8NAstfgBznrnOu3PUByFl3TBwzQVkeGC+gzOPzGbvYKM1QwlX6Gt7kVSPMzDP4qkSs1g== +np@^10.0.7: + version "10.0.7" + resolved "https://registry.yarnpkg.com/np/-/np-10.0.7.tgz#6f0dc3c7440c8ac95d55a2fa5d488c3d0848b7a5" + integrity sha512-vIPKQwOYKpQU40PU5x/vLfN2haj8ObxMvR1QGt7EZnBPWdm4WEbHdumYAnMV7AeR9kACsMqcqAP37sAo5cW5jA== dependencies: chalk "^5.3.0" chalk-template "^1.1.0" @@ -5065,11 +4723,10 @@ np@^9.0.0: execa "^8.0.1" exit-hook "^4.0.0" github-url-from-git "^1.5.0" - has-yarn "^3.0.0" hosted-git-info "^7.0.1" - ignore-walk "^6.0.3" + ignore-walk "^6.0.4" import-local "^3.1.0" - inquirer "^9.2.12" + inquirer "^9.2.15" is-installed-globally "^1.0.0" is-interactive "^2.0.0" is-scoped "^3.0.0" @@ -5077,12 +4734,11 @@ np@^9.0.0: listr "^0.14.3" listr-input "^0.2.1" log-symbols "^6.0.0" - meow "^12.1.1" + meow "^13.2.0" new-github-release-url "^2.0.0" - npm-name "^7.1.1" + npm-name "^8.0.0" onetime "^7.0.0" - open "^9.1.0" - ow "^1.1.1" + open "^10.0.4" p-memoize "^7.1.1" p-timeout "^6.1.2" path-exists "^5.0.0" @@ -5090,26 +4746,25 @@ np@^9.0.0: read-package-up "^11.0.0" read-pkg "^9.0.1" rxjs "^7.8.1" - semver "^7.5.4" + semver "^7.6.0" symbol-observable "^4.0.0" terminal-link "^3.0.0" update-notifier "^7.0.0" -npm-name@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/npm-name/-/npm-name-7.1.1.tgz#373774cc044b4dab7835e1d02c84f60680f7f748" - integrity sha512-lyOwsFndLoozriMEsaqJ5lXvhCATYOEhDvxlom8TNvB9a/htDXuLgpVhMUOBd9zCewUXCyBXAPxrGr2TK2adgQ== +npm-name@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/npm-name/-/npm-name-8.0.0.tgz#05aeda9748706ffad66d9ecec8188b99d6e3908b" + integrity sha512-DIuCGcKYYhASAZW6Xh/tiaGMko8IHOHe0n3zOA7SzTi0Yvy00x8L7sa5yNiZ75Ny58O/KeRtNouy8Ut6gPbKiw== dependencies: - got "^11.8.5" - is-name-taken "^2.0.0" is-scoped "^3.0.0" is-url-superb "^6.1.0" + ky "^1.2.0" lodash.zip "^4.2.0" org-regex "^1.0.0" - p-map "^5.5.0" - registry-auth-token "^4.2.2" + p-map "^7.0.1" + registry-auth-token "^5.0.2" registry-url "^6.0.1" - validate-npm-package-name "^3.0.0" + validate-npm-package-name "^5.0.0" npm-run-path@^4.0.1: version "4.0.1" @@ -5151,9 +4806,9 @@ object-hash@^3.0.0: integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== object-inspect@^1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== + version "1.13.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" + integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== omggif@^1.0.10: version "1.0.10" @@ -5167,7 +4822,7 @@ on-finished@2.4.1: dependencies: ee-first "1.1.1" -once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@^1.3.0, once@^1.3.1: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== @@ -5209,15 +4864,15 @@ onetime@^7.0.0: dependencies: mimic-function "^5.0.0" -open@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/open/-/open-9.1.0.tgz#684934359c90ad25742f5a26151970ff8c6c80b6" - integrity sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg== +open@^10.0.4: + version "10.1.0" + resolved "https://registry.yarnpkg.com/open/-/open-10.1.0.tgz#a7795e6e5d519abe4286d9937bb24b51122598e1" + integrity sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw== dependencies: - default-browser "^4.0.0" + default-browser "^5.2.1" define-lazy-prop "^3.0.0" is-inside-container "^1.0.0" - is-wsl "^2.2.0" + is-wsl "^3.1.0" optionator@^0.9.3: version "0.9.4" @@ -5256,27 +4911,6 @@ os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== -ow@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ow/-/ow-1.1.1.tgz#354a0f7df9d8d0cf961b29116daf972ef6be1632" - integrity sha512-sJBRCbS5vh1Jp9EOgwp1Ws3c16lJrUkJYlvWTYC03oyiYVwS/ns7lKRWow4w4XjDyTrA2pplQv4B2naWSR6yDA== - dependencies: - "@sindresorhus/is" "^5.3.0" - callsites "^4.0.0" - dot-prop "^7.2.0" - lodash.isequal "^4.5.0" - vali-date "^1.0.0" - -p-cancelable@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" - integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== - -p-cancelable@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050" - integrity sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw== - p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -5305,11 +4939,6 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" -p-lock@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-lock/-/p-lock-2.1.0.tgz#6f9dbc55d3aac5b0f75c8ec47f3a6f1b954135f8" - integrity sha512-pi2yT8gNhVrV4LgsUvJWQy58TXH1HG2+NXDby9+UrsS/9fXb0FJH9aCxbdHJ0EAQ6XC7ggSP6GAzuR5puDArUQ== - p-map@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" @@ -5322,6 +4951,11 @@ p-map@^5.5.0: dependencies: aggregate-error "^4.0.0" +p-map@^7.0.1: + version "7.0.2" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-7.0.2.tgz#7c5119fada4755660f70199a66aa3fe2f85a1fe8" + integrity sha512-z4cYYMMdKHzw4O5UkWJImbZynVIo0lSGTXc7bzB1e/rrDqkgGUNysK/o4bTr+0+xKvvLoTyGqYC4Fgljy9qe1Q== + p-memoize@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/p-memoize/-/p-memoize-7.1.1.tgz#53b1d0e6007288f7261cfa11a7603b84c9261bfa" @@ -5331,9 +4965,9 @@ p-memoize@^7.1.1: type-fest "^3.0.0" p-timeout@^6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-6.1.2.tgz#22b8d8a78abf5e103030211c5fc6dee1166a6aa5" - integrity sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ== + version "6.1.3" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-6.1.3.tgz#9635160c4e10c7b4c3db45b7d5d26f911d9fd853" + integrity sha512-UJUyfKbwvr/uZSV6btANfb+0t/mOhKV/KXcCUTp8FcQI+v/0d+wXqH4htrW0E4rR6WiEO/EPvUFiV9D5OI4vlw== p-try@^2.0.0: version "2.2.0" @@ -5341,24 +4975,19 @@ p-try@^2.0.0: integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== package-json-from-dist@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz#e501cd3094b278495eb4258d4c9f6d5ac3019f00" - integrity sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw== + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== -package-json@^8.1.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/package-json/-/package-json-8.1.1.tgz#3e9948e43df40d1e8e78a85485f1070bf8f03dc8" - integrity sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA== +package-json@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-10.0.1.tgz#e49ee07b8de63b638e7f1b5bb353733e428fe7d7" + integrity sha512-ua1L4OgXSBdsu1FPb7F3tYH0F48a6kxvod4pLUlGY9COeJAJQNX/sNH2IiEmsxw7lqYiAwrdHMjz1FctOsyDQg== dependencies: - got "^12.1.0" - registry-auth-token "^5.0.1" - registry-url "^6.0.0" - semver "^7.3.7" - -package-name-conflict@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/package-name-conflict/-/package-name-conflict-1.0.3.tgz#5147d35e8ae7f93401f1b3f9f3763c070463f25c" - integrity sha512-DPBNWSUWC0wPofXeNThao0uP4a93J7r90UyhagmJS0QcacTTkorZwXYsOop70phn1hKdcf/2e9lJIhazS8bx5A== + ky "^1.2.0" + registry-auth-token "^5.0.2" + registry-url "^6.0.1" + semver "^7.6.0" pako@^1.0.11: version "1.0.11" @@ -5390,20 +5019,6 @@ parse-bmfont-xml@^1.1.6: xml-parse-from-string "^1.0.0" xml2js "^0.5.0" -parse-json-object@^1.0.5: - version "1.1.0" - resolved "https://registry.yarnpkg.com/parse-json-object/-/parse-json-object-1.1.0.tgz#eef60211cec368259723d8586ecec7252f8fcdb2" - integrity sha512-4w5s6uJY1tW9REY8UwUOyaZKSKsrbQrMEzlV/Le/g5t4iMWuuyK83pZZ0OZimSOL9iyv2ORvRSgz71Ekd7iD3g== - dependencies: - types-json "^1.0.6" - -parse-json-object@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/parse-json-object/-/parse-json-object-2.0.1.tgz#a441bd8c36d2c33a69516286e7e4138a23607ee0" - integrity sha512-/oF7PUUBjCqHmMEE6xIQeX5ZokQ9+miudACzPt4KBU2qi6CxZYPdisPXx4ad7wpZJYi2ZpcW2PacLTU3De3ebw== - dependencies: - types-json "^1.2.0" - parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" @@ -5483,10 +5098,18 @@ path-scurry@^1.11.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== +path-scurry@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-2.0.0.tgz#9f052289f23ad8bf9397a2a0425e7b8615c58580" + integrity sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg== + dependencies: + lru-cache "^11.0.0" + minipass "^7.1.2" + +path-to-regexp@0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.10.tgz#67e9108c5c0551b9e5326064387de4763c4d5f8b" + integrity sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w== path-type@^4.0.0: version "4.0.0" @@ -5498,11 +5121,16 @@ peek-readable@^4.1.0: resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-4.1.0.tgz#4ece1111bf5c2ad8867c314c81356847e8a62e72" integrity sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg== -picocolors@^1.0.0, picocolors@^1.0.1: +picocolors@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== +picocolors@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" @@ -5563,10 +5191,10 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -progress@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== +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== prompts@^2.0.1: version "2.4.2" @@ -5594,14 +5222,6 @@ proxy-from-env@^1.1.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - punycode@^2.1.0: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" @@ -5619,17 +5239,10 @@ pure-rand@^6.0.0: resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2" integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== -qs@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== - dependencies: - side-channel "^1.0.4" - -qs@^6.9.1: - version "6.12.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.1.tgz#39422111ca7cbdb70425541cba20c7d7b216599a" - integrity sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ== +qs@6.13.0, qs@^6.9.1: + version "6.13.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" + integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== dependencies: side-channel "^1.0.6" @@ -5638,11 +5251,6 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== -quick-lru@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" - integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== - range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -5673,19 +5281,6 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== -read-file-safe@^1.0.5: - version "1.0.10" - resolved "https://registry.yarnpkg.com/read-file-safe/-/read-file-safe-1.0.10.tgz#9ac9118f12cb122614612211f90dad9daf732e39" - integrity sha512-qW25fd2uMX3dV6Ui/R0jYK1MhTpjx8FO/VHaHTXzwWsGnkNwLRcqYfCXd9qDM+NZ273DPUvP2RaimYuLSu1K/g== - -read-json-safe@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/read-json-safe/-/read-json-safe-1.0.5.tgz#c459443b8e6eb3a2672cf68ddc81d2f4ef95c8d7" - integrity sha512-SJyNY/U9+vW35FPus22Qvv1oilnR7PCfN2E70uKQEGaJS313A5/cz9Yhv7ZtWzZ+XIwrtEPxXf10BOyYemHehA== - dependencies: - parse-json-object "^1.0.5" - read-file-safe "^1.0.5" - read-package-up@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/read-package-up/-/read-package-up-11.0.0.tgz#71fb879fdaac0e16891e6e666df22de24a48d5ba" @@ -5732,7 +5327,7 @@ readable-stream@^2.3.6: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.4.0, readable-stream@^3.6.0, readable-stream@^3.6.2: +readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -5741,6 +5336,17 @@ readable-stream@^3.4.0, readable-stream@^3.6.0, readable-stream@^3.6.2: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@^4.5.2: + 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.0: version "3.0.2" resolved "https://registry.yarnpkg.com/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz#5d52bb5df7b54861fd48d015e93a2cb87b3ee0bb" @@ -5753,21 +5359,14 @@ reflect-metadata@^0.2.1: resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.2.2.tgz#400c845b6cba87a21f2c65c4aeb158f4fa4d9c5b" integrity sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q== -registry-auth-token@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.2.tgz#f02d49c3668884612ca031419491a13539e21fac" - integrity sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg== - dependencies: - rc "1.2.8" - -registry-auth-token@^5.0.1: +registry-auth-token@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-5.0.2.tgz#8b026cc507c8552ebbe06724136267e63302f756" integrity sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ== dependencies: "@pnpm/npm-conf" "^2.1.0" -registry-url@^6.0.0, registry-url@^6.0.1: +registry-url@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-6.0.1.tgz#056d9343680f2f64400032b1e199faa692286c58" integrity sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q== @@ -5779,11 +5378,6 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== -resolve-alpn@^1.0.0, resolve-alpn@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" - integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== - resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" @@ -5815,20 +5409,6 @@ resolve@^1.20.0: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -responselike@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc" - integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw== - dependencies: - lowercase-keys "^2.0.0" - -responselike@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-3.0.0.tgz#20decb6c298aff0dbee1c355ca95461d42823626" - integrity sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg== - dependencies: - lowercase-keys "^3.0.0" - restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" @@ -5857,12 +5437,10 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" -run-applescript@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-5.0.0.tgz#e11e1c932e055d5c6b40d98374e0268d9b11899c" - integrity sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg== - dependencies: - execa "^5.0.0" +run-applescript@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-7.0.0.tgz#e5a553c2bffd620e169d276c1cd8f1b64778fbeb" + integrity sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A== run-async@^2.2.0, run-async@^2.4.0: version "2.4.1" @@ -5906,9 +5484,9 @@ safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@~5.2.0: integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== safe-stable-stringify@^2.3.1: - version "2.4.3" - resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" - integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== + version "2.5.0" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" + integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== "safer-buffer@>= 2.1.2 < 3": version "2.1.2" @@ -5925,27 +5503,20 @@ scoped-regex@^3.0.0: resolved "https://registry.yarnpkg.com/scoped-regex/-/scoped-regex-3.0.0.tgz#cd7ede7d942f2ae90da53272102ff2d73129c46f" integrity sha512-yEsN6TuxZhZ1Tl9iB81frTNS292m0I/IG7+w8lTvfcJQP2x3vnpOoevjBoE3Np5A6KnZM2+RtVenihj9t6NiYg== -semver-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-4.0.0.tgz#3afcf5ed6d62259f5c72d0d5d50dffbdc9680df5" - integrity sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA== - dependencies: - semver "^7.3.5" - semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.5, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0: - version "7.6.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" - integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== +semver@^7.3.5, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== +send@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" + integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== dependencies: debug "2.6.9" depd "2.0.0" @@ -5961,15 +5532,15 @@ send@0.18.0: range-parser "~1.2.1" statuses "2.0.1" -serve-static@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== +serve-static@1.16.2: + version "1.16.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" + integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw== dependencies: - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" parseurl "~1.3.3" - send "0.18.0" + send "0.19.0" set-blocking@^2.0.0: version "2.0.0" @@ -6020,7 +5591,7 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -side-channel@^1.0.4, side-channel@^1.0.6: +side-channel@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== @@ -6121,9 +5692,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.18" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz#22aa922dcf2f2885a6494a261f2d8b75345d0326" - integrity sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ== + version "3.0.20" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz#e44ed19ed318dd1e5888f93325cee800f0f51b89" + integrity sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw== sprintf-js@~1.0.2: version "1.0.3" @@ -6204,7 +5775,16 @@ string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" -string_decoder@^1.1.1: +string-width@^7.0.0, string-width@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.2.0.tgz#b5bb8e2165ce275d4d43476dd2700ad9091db6dc" + integrity sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ== + dependencies: + emoji-regex "^10.3.0" + get-east-asian-width "^1.0.0" + strip-ansi "^7.1.0" + +string_decoder@^1.1.1, string_decoder@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -6253,7 +5833,7 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-ansi@^7.0.1: +strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== @@ -6293,6 +5873,11 @@ strtok3@^6.2.4: "@tokenizer/token" "^0.3.0" peek-readable "^4.1.0" +stubborn-fs@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/stubborn-fs/-/stubborn-fs-1.2.5.tgz#e5e244223166921ddf66ed5e062b6b3bf285bfd2" + integrity sha512-H2N9c26eXjzL/S/K+i/RHHcFanE74dptvvjM8iwzwbVcWY/zjBbgRqF3K0DY4+OD+uTTASTBvDoxPDaPN02D7g== + superagent@5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/superagent/-/superagent-5.2.2.tgz#6ff726c5642795b2c27009e92687c8e69a6bb07d" @@ -6422,11 +6007,6 @@ tinycolor2@^1.6.0: resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e" integrity sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw== -titleize@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/titleize/-/titleize-3.0.0.tgz#71c12eb7fdd2558aa8a44b0be83b8a76694acd53" - integrity sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ== - tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -6439,11 +6019,6 @@ tmpl@1.0.5: resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -6474,45 +6049,46 @@ triple-beam@^1.2.0, triple-beam@^1.3.0, triple-beam@^1.4.1: resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984" integrity sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg== -ts-api-utils@^1.0.1, ts-api-utils@^1.3.0: +ts-api-utils@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== ts-essentials@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-10.0.0.tgz#4abb58d4ed9219e313a10cf86758d257470e4d38" - integrity sha512-77FHNJEyysF9+1s4G6eejuA1lxw7uMchT3ZPy3CIbh7GIunffpshtM8pTe5G6N5dpOzNevqRHew859ceLWVBfw== + version "10.0.2" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-10.0.2.tgz#8c7aa74ed79580ffe49df5ca28d06cc6bea0ff3c" + integrity sha512-Xwag0TULqriaugXqVdDiGZ5wuZpqABZlpwQ2Ho4GDyiu/R2Xjkp/9+zcFxL7uzeLl/QCPrflnvpVYyS3ouT7Zw== ts-jest@^29.0.0: - version "29.1.5" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.5.tgz#d6c0471cc78bffa2cb4664a0a6741ef36cfe8f69" - integrity sha512-UuClSYxM7byvvYfyWdFI+/2UxMmwNyJb0NPkZPQE2hew3RurV7l7zURgOHAd/1I1ZdPpe3GUsXNXAcN8TFKSIg== + version "29.2.5" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.2.5.tgz#591a3c108e1f5ebd013d3152142cb5472b399d63" + integrity sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA== dependencies: - bs-logger "0.x" - fast-json-stable-stringify "2.x" + bs-logger "^0.2.6" + ejs "^3.1.10" + fast-json-stable-stringify "^2.1.0" jest-util "^29.0.0" json5 "^2.2.3" - lodash.memoize "4.x" - make-error "1.x" - semver "^7.5.3" - yargs-parser "^21.0.1" + lodash.memoize "^4.1.2" + make-error "^1.3.6" + semver "^7.6.3" + yargs-parser "^21.1.1" ts-mixer@^6.0.4: version "6.0.4" resolved "https://registry.yarnpkg.com/ts-mixer/-/ts-mixer-6.0.4.tgz#1da39ceabc09d947a82140d9f09db0f84919ca28" integrity sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA== -tslib@2.6.2, tslib@^2.1.0, tslib@^2.5.0, tslib@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" - integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== - tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.1.0, tslib@^2.5.0, tslib@^2.6.2, tslib@^2.6.3: + version "2.8.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.0.tgz#d124c86c3c05a40a91e6fdea4021bd31d377971b" + integrity sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -6525,22 +6101,17 @@ type-detect@4.0.8: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - type-fest@^0.21.3: version "0.21.3" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== -type-fest@^1.0.1, type-fest@^1.0.2: +type-fest@^1.0.2: version "1.4.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== -type-fest@^2.11.2, type-fest@^2.13.0, type-fest@^2.5.1: +type-fest@^2.5.1: version "2.19.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== @@ -6550,10 +6121,15 @@ type-fest@^3.0.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-3.13.1.tgz#bb744c1f0678bea7543a2d1ec24e83e68e8c8706" integrity sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g== -type-fest@^4.6.0, type-fest@^4.7.1: - version "4.18.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.18.3.tgz#5249f96e7c2c3f0f1561625f54050e343f1c8f68" - integrity sha512-Q08/0IrpvM+NMY9PA2rti9Jb+JejTddwmwmVQGskAlhtcrw1wsRzoR6ode6mR+OAabNa75w/dxedSUY2mlphaQ== +type-fest@^4.18.2: + version "4.40.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.40.0.tgz#62bc09caccb99a75e1ad6b9b4653e8805e5e1eee" + integrity sha512-ABHZ2/tS2JkvH1PEjxFDTUWC8dB5OsIGZP4IFLhR293GqT5Y5qB1WwL2kMPYhQW9DVgVD8Hd7I8gjwPIf5GFkw== + +type-fest@^4.21.0, type-fest@^4.6.0, type-fest@^4.7.1: + version "4.26.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.26.1.tgz#a4a17fa314f976dd3e6d6675ef6c775c16d7955e" + integrity sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg== type-is@~1.6.18: version "1.6.18" @@ -6563,13 +6139,6 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - typeorm@0.3.20: version "0.3.20" resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.3.20.tgz#4b61d737c6fed4e9f63006f88d58a5e54816b7ab" @@ -6591,87 +6160,62 @@ typeorm@0.3.20: uuid "^9.0.0" yargs "^17.6.2" -types-eslintrc@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/types-eslintrc/-/types-eslintrc-1.0.3.tgz#b277d301caca6c330477cbaa67bf6f79ac3d6fee" - integrity sha512-zKTR6aKHEudQpl+JoZjS3qh0B5IzSpQK/BCpYBECujcnKtqL87DJJ1sJKe5B8k/y8/UJ5sukq42QDvlaJyCO2w== +typescript-eslint@^8.11.0: + version "8.11.0" + resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.11.0.tgz#74a0551972d675b4141672cec3acc5139b7399c0" + integrity sha512-cBRGnW3FSlxaYwU8KfAewxFK5uzeOAp0l2KebIlPDOT5olVi65KDG/yjBooPBG0kGW/HLkoz1c/iuBFehcS3IA== dependencies: - types-json "^1.2.2" - -types-json@^1.0.6, types-json@^1.2.0, types-json@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/types-json/-/types-json-1.2.2.tgz#91ebe6de59e741ab38a98b071708a29494cedfe6" - integrity sha512-VfVLISHypS7ayIHvhacOESOTib4Sm4mAhnsgR8fzQdGp89YoBwMqvGmqENjtYehUQzgclT+7NafpEXkK/MHKwA== - -types-pkg-json@^1.1.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/types-pkg-json/-/types-pkg-json-1.2.1.tgz#890fe4f231000a721299831ef3e17a489b1e635e" - integrity sha512-Wj75lCkPwfj1BhmaJxMPpTQj9YGpihjs3WICigt1IjTAswr7zPXP0iJYPZjU0Rw/IriODhMJjAImkCIxt9KeuQ== - dependencies: - types-eslintrc "^1.0.3" - types-json "^1.2.2" + "@typescript-eslint/eslint-plugin" "8.11.0" + "@typescript-eslint/parser" "8.11.0" + "@typescript-eslint/utils" "8.11.0" typescript@^5.0.0: - version "5.4.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" - integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== + version "5.6.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b" + integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw== -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== +undici-types@~6.19.8: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== -undici@6.13.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/undici/-/undici-6.13.0.tgz#7edbf4b7f3aac5f8a681d515151bf55cb3589d72" - integrity sha512-Q2rtqmZWrbP8nePMq7mOJIN98M0fYvSgV89vwl/BQRT4mDOeY2GXZngfGpcBBhtky3woM7G24wZV3Q304Bv6cw== +undici@6.19.8: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici/-/undici-6.19.8.tgz#002d7c8a28f8cc3a44ff33c3d4be4d85e15d40e1" + integrity sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g== unicorn-magic@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/unicorn-magic/-/unicorn-magic-0.1.0.tgz#1bb9a51c823aaf9d73a8bfcd3d1a23dde94b0ce4" integrity sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ== -unique-string@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-3.0.0.tgz#84a1c377aff5fd7a8bc6b55d8244b2bd90d75b9a" - integrity sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ== - dependencies: - crypto-random-string "^4.0.0" - unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -untildify@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" - integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== - -update-browserslist-db@^1.0.13: - version "1.0.16" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz#f6d489ed90fb2f07d67784eb3f53d7891f736356" - integrity sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ== +update-browserslist-db@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5" + integrity sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A== dependencies: - escalade "^3.1.2" - picocolors "^1.0.1" + escalade "^3.2.0" + picocolors "^1.1.0" update-notifier@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-7.0.0.tgz#295aa782dadab784ed4073f7ffaea1fb2123031c" - integrity sha512-Hv25Bh+eAbOLlsjJreVPOs4vd51rrtCrmhyOJtbpAojro34jS4KQaEp4/EvlHJX7jSO42VvEFpkastVyXyIsdQ== + version "7.3.1" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-7.3.1.tgz#49af1ad6acfa0ea01c0d0f3c04047c154ead7096" + integrity sha512-+dwUY4L35XFYEzE+OAL3sarJdUioVovq+8f7lcIJ7wnmnYQV5UD1Y/lcwaMSyaQ6Bj3JMj1XSTjZbNLHn/19yA== dependencies: - boxen "^7.1.1" + boxen "^8.0.1" chalk "^5.3.0" - configstore "^6.0.0" - import-lazy "^4.0.0" - is-in-ci "^0.1.0" - is-installed-globally "^0.4.0" + configstore "^7.0.0" + is-in-ci "^1.0.0" + is-installed-globally "^1.0.0" is-npm "^6.0.0" - latest-version "^7.0.0" + latest-version "^9.0.0" pupa "^3.1.0" - semver "^7.5.4" - semver-diff "^4.0.0" + semver "^7.6.3" xdg-basedir "^5.1.0" uri-js@^4.2.2: @@ -6704,19 +6248,14 @@ uuid@^9.0.0: integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== v8-to-istanbul@^9.0.1: - version "9.2.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" - integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== + version "9.3.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175" + integrity sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA== dependencies: "@jridgewell/trace-mapping" "^0.3.12" "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^2.0.0" -vali-date@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6" - integrity sha512-sgECfZthyaCKW10N0fm27cg8HYTFK5qMWgypqkXMQ4Wbl/zZKx7xZICgcoxIIE+WFAP/MBL2EFwC/YvLxw3Zeg== - validate-npm-package-license@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -6725,12 +6264,10 @@ validate-npm-package-license@^3.0.4: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -validate-npm-package-name@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" - integrity sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw== - dependencies: - builtins "^1.0.3" +validate-npm-package-name@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz#a316573e9b49f3ccd90dbb6eb52b3f06c6d604e8" + integrity sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ== vary@~1.1.2: version "1.1.2" @@ -6764,6 +6301,11 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" +when-exit@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/when-exit/-/when-exit-2.1.3.tgz#5831cdbed8ad4984645da98c4a00d4ee3a3757e7" + integrity sha512-uVieSTccFIr/SFQdFWN/fFaQYmV37OKtuaGphMAzi4DmmUlrvRBJW5WSLkHyjNQY/ePJMz3LoiX9R3yy1Su6Hw== + which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -6778,12 +6320,12 @@ wide-align@^1.1.2: dependencies: string-width "^1.0.2 || 2 || 3 || 4" -widest-line@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-4.0.1.tgz#a0fc673aaba1ea6f0a0d35b3c2795c9a9cc2ebf2" - integrity sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig== +widest-line@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-5.0.0.tgz#b74826a1e480783345f0cd9061b49753c9da70d0" + integrity sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA== dependencies: - string-width "^5.0.1" + string-width "^7.0.0" winston-daily-rotate-file@^5.0.0: version "5.0.0" @@ -6813,18 +6355,18 @@ winston-transport@4.3.0: triple-beam "^1.2.0" winston-transport@^4.7.0: - version "4.7.1" - resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.7.1.tgz#52ff1bcfe452ad89991a0aaff9c3b18e7f392569" - integrity sha512-wQCXXVgfv/wUPOfb2x0ruxzwkcZfxcktz6JIMUaPLmcNhO4bZTwA/WtDWK74xV3F2dKu8YadrFv0qhwYjVEwhA== + version "4.8.0" + resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.8.0.tgz#a15080deaeb80338455ac52c863418c74fcf38ea" + integrity sha512-qxSTKswC6llEMZKgCQdaWgDuMJQnhuvF5f2Nk3SNXc4byfQ+voo2mX1Px9dkNOuR8p0KAjfPG29PuYUSIb+vSA== dependencies: logform "^2.6.1" - readable-stream "^3.6.2" + readable-stream "^4.5.2" triple-beam "^1.3.0" -winston@^3.11.0: - version "3.13.1" - resolved "https://registry.yarnpkg.com/winston/-/winston-3.13.1.tgz#53ddadb9c2332eb12cff8306413b3480dc82b6c3" - integrity sha512-SvZit7VFNvXRzbqGHsv5KSmgbEYR5EiQfDAL9gxYkRqa934Hnk++zze0wANKtMHcy/gI4W/3xmSDwlhf865WGw== +winston@^3.15.0: + version "3.15.0" + resolved "https://registry.yarnpkg.com/winston/-/winston-3.15.0.tgz#4df7b70be091bc1a38a4f45b969fa79589b73ff5" + integrity sha512-RhruH2Cj0bV0WgNL+lOfoUBI4DVfdUNjVnJGVovWZmrcKtrFTTRzgXYK2O9cymSGjrERCtaAeHwMNnUWXlwZow== dependencies: "@colors/colors" "^1.6.0" "@dabh/diagnostics" "^2.0.2" @@ -6887,21 +6429,20 @@ wrap-ansi@^8.1.0: string-width "^5.0.1" strip-ansi "^7.0.1" +wrap-ansi@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-9.0.0.tgz#1a3dc8b70d85eeb8398ddfb1e4a02cd186e58b3e" + integrity sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q== + dependencies: + ansi-styles "^6.2.1" + string-width "^7.0.0" + strip-ansi "^7.1.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -write-file-atomic@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" - integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== - dependencies: - imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" - write-file-atomic@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" @@ -6910,12 +6451,12 @@ write-file-atomic@^4.0.2: imurmurhash "^0.1.4" signal-exit "^3.0.7" -ws@^8.16.0, ws@^8.17.1: +ws@^8.16.0: version "8.18.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== -xdg-basedir@^5.0.1, xdg-basedir@^5.1.0: +xdg-basedir@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-5.1.0.tgz#1efba19425e73be1bc6f2a6ceb52a3d2c884c0c9" integrity sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ== @@ -6958,7 +6499,7 @@ yargs-parser@^20.2.2: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== -yargs-parser@^21.0.1, yargs-parser@^21.1.1: +yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== @@ -6994,6 +6535,11 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +yoctocolors-cjs@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz#f4b905a840a37506813a7acaa28febe97767a242" + integrity sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA== + zod@^3.23.8: version "3.24.3" resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.3.tgz#1f40f750a05e477396da64438e0e1c0995dafd87"