diff --git a/.eslintrc.json b/.eslintrc.json
deleted file mode 100644
index 7db8224..0000000
--- a/.eslintrc.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "$schema": "https://json.schemastore.org/eslintrc.json",
- "root": true,
- "extends": ["neon/common", "neon/node", "neon/typescript", "neon/prettier"],
- "parserOptions": {
- "project": ["./tsconfig.eslint.json"]
- },
- "ignorePatterns": ["**/dist/*"],
- "rules": {
- "import/extensions": 0
- }
-}
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..b1a62b4
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,15 @@
+# These are supported funding model platforms
+
+github: duck-organization
+patreon: # Replace with a single Patreon username
+open_collective: # Replace with a single Open Collective username
+ko_fi: # Replace with a single Ko-fi username
+tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+liberapay: # Replace with a single Liberapay username
+issuehunt: # Replace with a single IssueHunt username
+lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
+polar: # Replace with a single Polar username
+buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
+thanks_dev: # Replace with a single thanks.dev username
+custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
diff --git a/.github/assets/LargeDuckBanner.png b/.github/assets/LargeDuckBanner.png
new file mode 100644
index 0000000..120cd5a
Binary files /dev/null and b/.github/assets/LargeDuckBanner.png differ
diff --git a/.github/assets/LargeDuckBannerWhite.png b/.github/assets/LargeDuckBannerWhite.png
deleted file mode 100644
index 9c4be3c..0000000
Binary files a/.github/assets/LargeDuckBannerWhite.png and /dev/null differ
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..def5cdf
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,11 @@
+version: 2
+updates:
+ - package-ecosystem: "npm"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ groups:
+ dependencies:
+ update-types:
+ - "minor"
+ - "patch"
diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml
index d267227..25d87a8 100644
--- a/.github/workflows/deploy.yaml
+++ b/.github/workflows/deploy.yaml
@@ -17,6 +17,7 @@ jobs:
if: >
(github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') ||
(github.event.workflow_run.conclusion == 'success' &&
+ github.event.workflow_run.event == 'push' &&
github.event.workflow_run.head_branch == 'main')
steps:
- name: Check out repository
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e5673ee..a88986e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,20 +1,20 @@
# Contributing to Quest Bot
-Contributing to Quest Bot requires basic knowledge of Typescript, Discord.JS and prisma.
+Contributing to Quest Bot requires basic knowledge of TypeScript, Discord.JS and Prisma.
## AI Rules
-Please refrain from using AI to create new features. Using AI to help you *understand* how to make something is fine but you can't have it vibecode or make features for you. This is especially important for HackClub events. You can use AI to help *draft* a feature.
+Please refrain from using AI to create new features. Using AI to help you *understand* how to make something is fine but you can't have it write code or make features for you. This is especially important for HackClub events. You can use AI to help *draft* a feature.
-When commiting code you take *full* responsibility for what you are commiting.
+When committing code you take *full* responsibility for what you are committing.
## Pull requests
-Please submit pull requests to the `dev` branch, unless this is a feature which requires a seperate branch.
+Please submit pull requests to the `dev` branch, unless this is a feature which requires a separate branch.
Make sure to test the code you have made before creating a pull request.
-Format for commit messages, fix|upd|chore|dockerfile: (change made).
+Use conventional commit messages for all commits.
> [!NOTE]
-> When contributing to this project you agree that you have all rights to the content you have contributed and that these align with the projects license.
+> When contributing to this project you agree that you have all rights to the content you have contributed and that these align with the project's license.
## Thanks for your interest! ❤️
diff --git a/Dockerfile b/Dockerfile
index 6bb318a..297e73a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -10,7 +10,7 @@ COPY apps/bot/prisma ./apps/bot/prisma/
RUN pnpm install --frozen-lockfile
COPY . .
-RUN pnpm --filter @quest/bot build
+RUN pnpm --filter @duckorganization/questbot build
FROM node:24-alpine
WORKDIR /app
@@ -22,8 +22,8 @@ COPY pnpm-workspace.yaml ./
COPY apps/bot/package.json ./apps/bot/package.json
COPY apps/bot/prisma.config.ts ./apps/bot/prisma.config.ts
COPY apps/bot/prisma ./apps/bot/prisma/
-RUN pnpm install --prod --frozen-lockfile --filter @quest/bot
+RUN pnpm install --prod --frozen-lockfile --filter @duckorganization/questbot
COPY --from=builder /app/apps/bot/dist ./apps/bot/dist
-CMD ["sh", "-c", "pnpm --filter @quest/bot db:push && pnpm --filter @quest/bot start"]
+CMD ["sh", "-c", "pnpm --filter @duckorganization/questbot db:push && pnpm --filter @duckorganization/questbot start"]
diff --git a/README.md b/README.md
index f4d91d6..bfb3a81 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-

+

---
@@ -38,6 +38,12 @@ Feel free to open a pull request! Just make sure to follow the guidelines at [CO
5. Run the development server with `pnpm dev`
6. The bot will register commands automatically on startup.
+# Security
+
+Quest Bot undergoes frequent security audits that help it stay safe!
+
+If you ever find a security vulnerabitity, do not hesitate to make a report! We are more than happy to review it.
+
# License
This project is licensed under the Affero GNU General Public License v3.0 (AGPL-3.0). See LICENSE for more details.
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..cd70be7
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,28 @@
+# Security Policy
+
+## Supported Versions
+
+| Version | Supported |
+| ------------ | ------------------ |
+| Latest Tag | :white_check_mark: |
+
+## Unsupported types of vulnerabilities
+
+| Type | Supported |
+| ------------- | ------------------ |
+| Rate limits | :x: |
+| Limits | :x: |
+| DDOS/DOS | :x: |
+
+If it is *critical* please submit it.
+
+## Reporting a Vulnerability
+
+Please report vulnerabilties through Github Advisories.
+
+Don't be afraid to report a vulnerability! If we have to close it there are no consequences!
+
+If a vulnerability is of high severity it will be looked into reasonably fast.
+Vulnerabilties get accepted and denied all the time, if your vulnerability is denied
+and you believe it was denied falsely than you can either reopen it or create a new one
+if it is of high priority.
diff --git a/apps/bot/.prettierignore b/apps/bot/.prettierignore
new file mode 100644
index 0000000..849ddff
--- /dev/null
+++ b/apps/bot/.prettierignore
@@ -0,0 +1 @@
+dist/
diff --git a/apps/bot/LICENSE b/apps/bot/LICENSE
new file mode 120000
index 0000000..30cff74
--- /dev/null
+++ b/apps/bot/LICENSE
@@ -0,0 +1 @@
+../../LICENSE
\ No newline at end of file
diff --git a/apps/bot/README.md b/apps/bot/README.md
new file mode 120000
index 0000000..fe84005
--- /dev/null
+++ b/apps/bot/README.md
@@ -0,0 +1 @@
+../../README.md
\ No newline at end of file
diff --git a/apps/bot/package.json b/apps/bot/package.json
index 8eb2857..67e3578 100644
--- a/apps/bot/package.json
+++ b/apps/bot/package.json
@@ -1,42 +1,59 @@
{
"$schema": "https://json.schemastore.org/package.json",
- "name": "@quest/bot",
- "version": "0.1.0",
+ "name": "@duckorganization/questbot",
+ "version": "0.1.5",
"private": true,
"type": "module",
+ "description": "A Discord bot built with Sapphire framework",
+ "license": "AGPL-3.0-or-later",
+ "author": "Duck Organization",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/duck-organization/quest-bot.git"
+ },
+ "main": "./dist/index.js",
+ "bin": {
+ "questbot": "./dist/sharder.js"
+ },
+ "files": [
+ "dist",
+ "prisma/schema.prisma",
+ "README.md",
+ "LICENSE"
+ ],
"scripts": {
"build": "rimraf dist && prisma generate && tsc",
- "lint": "prettier --check . && eslint --ext .ts --format=pretty src",
- "format": "prettier --write . && eslint --ext .ts --fix --format=pretty src",
+ "lint": "prettier --check .",
+ "format": "prettier --write .",
"predev": "pnpm build",
"start": "node --env-file-if-exists=../../.env dist/sharder.js",
"dev": "concurrently \"tsc --watch --preserveWatchOutput\" \"node --watch --watch-preserve-output --env-file-if-exists=../../.env dist/index.js\"",
"db:push": "prisma db push",
- "db:generate": "prisma generate"
+ "db:generate": "prisma generate",
+ "postinstall": "prisma generate",
+ "prepublishOnly": "pnpm build"
},
"dependencies": {
- "@discordjs/core": "^2.3.0",
- "@prisma/adapter-pg": "^7.7.0",
- "@prisma/client": "^7.7.0",
+ "@discordjs/core": "^2.4.0",
+ "@prisma/adapter-pg": "^7.8.0",
+ "@prisma/client": "^7.8.0",
"@sapphire/framework": "^5.5.0",
"@types/ms": "^2.1.0",
"discord.js": "^14.26.4",
- "dotenv": "^17.4.2",
+ "ipaddr.js": "^2.4.0",
"ms": "^2.1.3",
- "prisma": "^7.7.0",
- "zod": "^4.3.6"
+ "prisma": "^7.8.0",
+ "sharp": "^0.34.5",
+
+ "zod": "^4.4.3"
},
"devDependencies": {
- "@sapphire/ts-config": "^5.0.1",
- "@types/node": "^22.18.8",
+ "@sapphire/ts-config": "^5.0.3",
+ "@types/node": "^25.8.0",
"concurrently": "^9.2.1",
- "eslint": "^9.39.4",
- "eslint-config-neon": "^0.2.7",
- "eslint-formatter-compact": "^8.40.0",
- "eslint-formatter-pretty": "^7.0.0",
- "prettier": "^3.6.2",
+ "prettier": "^3.8.3",
"rimraf": "^6.1.3",
- "typescript": "~5.9.3"
+ "typescript": "~6.0.3"
},
"engines": {
"node": ">=22.12.0"
@@ -46,4 +63,4 @@
"#lib/*": "./dist/lib/*",
"#prisma/*": "./dist/generated/prisma/*"
}
-}
+}
\ No newline at end of file
diff --git a/apps/bot/prisma.config.ts b/apps/bot/prisma.config.ts
index 831a20f..cdf363d 100644
--- a/apps/bot/prisma.config.ts
+++ b/apps/bot/prisma.config.ts
@@ -1,14 +1,12 @@
-// This file was generated by Prisma, and assumes you have installed the following:
-// npm install --save-dev prisma dotenv
-import "dotenv/config";
-import { defineConfig } from "prisma/config";
+///
+import { defineConfig } from 'prisma/config';
export default defineConfig({
- schema: "prisma/schema.prisma",
- migrations: {
- path: "prisma/migrations",
- },
- datasource: {
- url: process.env["DATABASE_URL"],
- },
+ schema: 'prisma/schema.prisma',
+ migrations: {
+ path: 'prisma/migrations',
+ },
+ datasource: {
+ url: process.env['DATABASE_URL'] ?? '',
+ },
});
diff --git a/apps/bot/src/commands/globalModeration/confessionBlacklist.ts b/apps/bot/src/commands/globalModeration/confessionBlacklist.ts
index 21141d5..ae74503 100644
--- a/apps/bot/src/commands/globalModeration/confessionBlacklist.ts
+++ b/apps/bot/src/commands/globalModeration/confessionBlacklist.ts
@@ -1,91 +1,79 @@
import { Command } from '@sapphire/framework';
import { MessageFlags } from 'discord.js';
-import {
- addConfessionBlacklist,
- removeConfessionBlacklist,
- isConfessionBlacklisted,
-} from '#lib/confessions.js';
+import { addConfessionBlacklist, removeConfessionBlacklist, isConfessionBlacklisted } from '#lib/confessions.js';
import { emojis } from '#utils/emoji.js';
export class ConfessionBlacklistCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['globalModerator'] });
- }
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['globalModerator'] });
+ }
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder
- .setName('confessionblacklist')
- .setDescription('Manage the confession blacklist')
- .setDefaultMemberPermissions(0n)
- .setDMPermission(false)
- .addSubcommand((sub: any) =>
- sub
- .setName('add')
- .setDescription('Blacklist a user from making confessions')
- .addUserOption((opt: any) =>
- opt.setName('user').setDescription('User to blacklist').setRequired(true)
- )
- .addStringOption((opt: any) =>
- opt.setName('reason').setDescription('Reason').setRequired(false)
- )
- )
- .addSubcommand((sub: any) =>
- sub
- .setName('remove')
- .setDescription('Remove a user from the confession blacklist')
- .addUserOption((opt: any) =>
- opt.setName('user').setDescription('User to unblacklist').setRequired(true)
- )
- )
- .addSubcommand((sub: any) =>
- sub
- .setName('check')
- .setDescription('Check if a user is blacklisted from confessions')
- .addUserOption((opt: any) =>
- opt.setName('user').setDescription('User to check').setRequired(true)
- )
- )
- );
- }
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder
+ .setName('confessionblacklist')
+ .setDescription('Manage the confession blacklist')
+ .setDefaultMemberPermissions(0n)
+ .setDMPermission(false)
+ .addSubcommand((sub: any) =>
+ sub
+ .setName('add')
+ .setDescription('Blacklist a user from making confessions')
+ .addUserOption((opt: any) => opt.setName('user').setDescription('User to blacklist').setRequired(true))
+ .addStringOption((opt: any) => opt.setName('reason').setDescription('Reason').setMaxLength(512).setRequired(false)),
+ )
+ .addSubcommand((sub: any) =>
+ sub
+ .setName('remove')
+ .setDescription('Remove a user from the confession blacklist')
+ .addUserOption((opt: any) => opt.setName('user').setDescription('User to unblacklist').setRequired(true)),
+ )
+ .addSubcommand((sub: any) =>
+ sub
+ .setName('check')
+ .setDescription('Check if a user is blacklisted from confessions')
+ .addUserOption((opt: any) => opt.setName('user').setDescription('User to check').setRequired(true)),
+ ),
+ );
+ }
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- const subcommand = interaction.options.getSubcommand();
- const user = interaction.options.getUser('user', true);
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ const subcommand = interaction.options.getSubcommand();
+ const user = interaction.options.getUser('user', true);
- if (subcommand === 'add') {
- const reason = interaction.options.getString('reason') ?? undefined;
- try {
- await addConfessionBlacklist(user.id, interaction.user.id, reason);
- await interaction.reply({
- content: `${emojis.rightArrow2} Blacklisted ${user} from confessions${reason ? ` (reason: ${reason})` : ''}.`,
- flags: MessageFlags.Ephemeral
- });
- } catch (err) {
- console.error(err);
- await interaction.reply({
- content: `${emojis.rightArrow2} Failed to blacklist that user.`,
- flags: MessageFlags.Ephemeral
- });
- }
- }
+ if (subcommand === 'add') {
+ const reason = interaction.options.getString('reason') ?? undefined;
+ try {
+ await addConfessionBlacklist(user.id, interaction.user.id, reason);
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Blacklisted ${user} from confessions${reason ? ` (reason: ${reason})` : ''}.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ } catch (err) {
+ console.error(err);
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Failed to blacklist that user.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ }
+ }
- if (subcommand === 'remove') {
- await removeConfessionBlacklist(user.id);
- await interaction.reply({
- content: `${emojis.rightArrow2} Removed ${user} from the confession blacklist.`,
- flags: MessageFlags.Ephemeral
- });
- }
+ if (subcommand === 'remove') {
+ await removeConfessionBlacklist(user.id);
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Removed ${user} from the confession blacklist.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ }
- if (subcommand === 'check') {
- const blacklisted = await isConfessionBlacklisted(user.id);
- await interaction.reply({
- content: blacklisted
- ? `${emojis.rightArrow2} ${user} is blacklisted from confessions.`
- : `${emojis.rightArrow2} ${user} is not blacklisted.`,
- flags: MessageFlags.Ephemeral
- });
- }
- }
-}
\ No newline at end of file
+ if (subcommand === 'check') {
+ const blacklisted = await isConfessionBlacklisted(user.id);
+ await interaction.reply({
+ content: blacklisted
+ ? `${emojis.rightArrow2} ${user} is blacklisted from confessions.`
+ : `${emojis.rightArrow2} ${user} is not blacklisted.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ }
+ }
+}
diff --git a/apps/bot/src/commands/moderation/automod.ts b/apps/bot/src/commands/moderation/automod.ts
index 0156e1d..cb04600 100644
--- a/apps/bot/src/commands/moderation/automod.ts
+++ b/apps/bot/src/commands/moderation/automod.ts
@@ -1,162 +1,226 @@
import { Command } from '@sapphire/framework';
-import { MessageFlags } from 'discord.js';
+import { ActionRowBuilder, ButtonBuilder, ButtonStyle, MessageFlags, PermissionsBitField } from 'discord.js';
import { createAutoMod, DuplicateAutoModError, getAutoMod, getAutoMods, removeAutoMod } from '#lib/automod.js';
import { getQuestUnlimitedPurchaseComponents, LimitError } from '#lib/limits.js';
import { emojis } from '#utils/emoji.js';
+import { awaitMessageComponentSafe } from '#utils/collectors.js';
export class AutoModCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
-
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder
- .setName('automod')
- .setDescription('Block words from being said!')
- .addSubcommand((sub: any) =>
- sub
- .setName('add')
- .setDescription('Create a new automod rule.')
- .addStringOption((option: any) =>
- option.setName('word').setDescription('The word to block').setRequired(true)
- )
- )
- .addSubcommand((sub: any) =>
- sub
- .setName('remove')
- .setDescription('Remove words from the automod list.')
- .addStringOption((option: any) =>
- option
- .setName('word')
- .setDescription('The word to remove')
- .setAutocomplete(true)
- .setRequired(true)
- )
- )
- .addSubcommand((sub: any) =>
- sub
- .setName('list')
- .setDescription('List all blocked words.')
- )
- );
- }
-
- public override async autocompleteRun(interaction: Command.AutocompleteInteraction) {
- if (!interaction.guildId) {
- await interaction.respond([]);
- return;
- }
-
- const focusedOption = interaction.options.getFocused(true);
-
- if (interaction.options.getSubcommand() !== 'remove' || focusedOption.name !== 'word') {
- await interaction.respond([]);
- return;
- }
-
- const autoMods = await getAutoMods(interaction.guildId);
- const choices = autoMods.slice(0, 25).map((autoMod) => ({
- name: autoMod.word,
- value: autoMod.id
- }));
-
- await interaction.respond(choices);
- }
-
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- if (!interaction.inCachedGuild()) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This command can only be used in a server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const subcommand = interaction.options.getSubcommand();
-
- if (subcommand === 'add') {
- const word = interaction.options.getString('word', true).trim().toLowerCase();
- try {
- await createAutoMod(
- interaction.guildId,
- interaction.guild.name,
- word,
- interaction.client.application.entitlements
- );
- await interaction.reply({
- content: `${emojis.rightArrow2} The word '${word}' has been added to the automod list.`,
- flags: MessageFlags.Ephemeral
- });
- } catch (err) {
- if (err instanceof LimitError) {
- if (err.showQuestUnlimitedPrompt) {
- await interaction.reply({
- content: `${emojis.questUnlimited2} ${err.message} Unlock unlimited automod rules with QuestUnlimited.`,
- components: getQuestUnlimitedPurchaseComponents(interaction.client.application.id),
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- await interaction.reply({
- content: `${emojis.rightArrow2} ${err.message}`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (err instanceof DuplicateAutoModError) {
- await interaction.reply({
- content: `${emojis.rightArrow2} ${err.message}`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- console.error(err);
-
- await interaction.reply({
- content: `${emojis.rightArrow2} That word is already blocked in this server.`,
- flags: MessageFlags.Ephemeral
- });
- }
- }
-
- if (subcommand === 'list') {
- const autoMods = await getAutoMods(interaction.guildId);
- if (autoMods.length === 0) {
- await interaction.reply({
- content: `${emojis.rightArrow2} There are no words in the automod list.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const wordList = autoMods.map((autoMod) => `${emojis.rightArrow1} ${autoMod.word}`).join('\n');
- await interaction.reply({
- content: `**Blocked Words:**\n${wordList}`,
- flags: MessageFlags.Ephemeral
- });
- }
-
- if (subcommand === 'remove') {
- const autoModId = interaction.options.getString('word', true);
- const autoMod = await getAutoMod(autoModId);
-
- if (!autoMod) {
- await interaction.reply({
- content: `${emojis.rightArrow2} That blocked word doesn't exist.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- await removeAutoMod(autoMod.id);
- await interaction.reply({
- content: `${emojis.rightArrow2} The word '${autoMod.word}' has been removed from the automod list.`,
- flags: MessageFlags.Ephemeral
- });
- }
- }
-}
\ No newline at end of file
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
+
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder
+ .setName('automod')
+ .setDescription('Block words from being said!')
+ .addSubcommand((sub: any) =>
+ sub
+ .setName('add')
+ .setDescription('Create a new automod rule.')
+ .addStringOption((option: any) =>
+ option.setName('word').setDescription('The word to block').setRequired(true).setMaxLength(100),
+ ),
+ )
+ .addSubcommand((sub: any) =>
+ sub
+ .setName('remove')
+ .setDescription('Remove words from the automod list.')
+ .addStringOption((option: any) =>
+ option.setName('word').setDescription('The word to remove').setAutocomplete(true).setRequired(true).setMaxLength(36),
+ ),
+ )
+ .addSubcommand((sub: any) => sub.setName('list').setDescription('List all blocked words.')),
+ );
+ }
+
+ public override async autocompleteRun(interaction: Command.AutocompleteInteraction) {
+ if (!interaction.guildId) {
+ await interaction.respond([]);
+ return;
+ }
+
+ const focusedOption = interaction.options.getFocused(true);
+
+ if (interaction.options.getSubcommand() !== 'remove' || focusedOption.name !== 'word') {
+ await interaction.respond([]);
+ return;
+ }
+
+ const autoMods = await getAutoMods(interaction.guildId);
+ const choices = autoMods.slice(0, 25).map((autoMod) => ({
+ name: autoMod.word,
+ value: autoMod.id,
+ }));
+
+ await interaction.respond(choices);
+ }
+
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ if (!interaction.inCachedGuild()) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This command can only be used in a server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (!interaction.member.permissions.has(PermissionsBitField.Flags.ManageGuild)) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You do not have permission to manage automod.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const subcommand = interaction.options.getSubcommand();
+
+ if (subcommand === 'add') {
+ const word = interaction.options.getString('word', true).trim().toLowerCase();
+
+ if (!word) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} The word cannot be empty or contain only whitespace.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ try {
+ await createAutoMod(
+ interaction.guildId,
+ interaction.guild.name,
+ word,
+ interaction.client.application.entitlements,
+ );
+ await interaction.reply({
+ content: `${emojis.rightArrow2} The word '${word}' has been added to the automod list.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ } catch (err) {
+ if (err instanceof LimitError) {
+ if (err.showQuestUnlimitedPrompt) {
+ await interaction.reply({
+ content: `${emojis.questUnlimited2} ${err.message} Unlock unlimited automod rules with QuestUnlimited.`,
+ components: getQuestUnlimitedPurchaseComponents(interaction.client.application.id),
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ await interaction.reply({
+ content: `${emojis.rightArrow2} ${err.message}`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (err instanceof DuplicateAutoModError) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} ${err.message}`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ console.error(err);
+
+ await interaction.reply({
+ content: `${emojis.rightArrow2} That word is already blocked in this server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ }
+ }
+
+ if (subcommand === 'list') {
+ const autoMods = await getAutoMods(interaction.guildId);
+ if (autoMods.length === 0) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} There are no words in the automod list.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const totalPages = Math.ceil(autoMods.length / 10);
+ let page = 0;
+
+ const buildContent = (page: number) => {
+ const slice = autoMods.slice(page * 10, (page + 1) * 10);
+ const wordList = slice.map((autoMod) => `${emojis.rightArrow1} ${autoMod.word}`).join('\n');
+ return `**Blocked Words** (Page ${page + 1}/${totalPages}):\n${wordList}`;
+ };
+
+ const buildRow = (page: number) =>
+ new ActionRowBuilder
().addComponents(
+ new ButtonBuilder()
+ .setCustomId('prev')
+ .setLabel('<')
+ .setStyle(ButtonStyle.Primary)
+ .setDisabled(page === 0),
+ new ButtonBuilder()
+ .setCustomId('next')
+ .setLabel('>')
+ .setStyle(ButtonStyle.Primary)
+ .setDisabled(page >= totalPages - 1),
+ );
+
+ if (totalPages === 1) {
+ await interaction.reply({
+ content: buildContent(0),
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const response = await interaction.reply({
+ content: buildContent(page),
+ components: [buildRow(page)],
+ flags: MessageFlags.Ephemeral,
+ withResponse: true,
+ });
+
+ const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
+
+ while (true) {
+ const btn = await awaitMessageComponentSafe(response.resource!.message!, {
+ filter: collectorFilter,
+ time: 60_000,
+ });
+
+ if (!btn) {
+ await interaction.editReply({ components: [] });
+ break;
+ }
+
+ if (btn.customId === 'prev') page = Math.max(0, page - 1);
+ if (btn.customId === 'next') page = Math.min(totalPages - 1, page + 1);
+
+ await btn.update({
+ content: buildContent(page),
+ components: [buildRow(page)],
+ });
+ }
+ }
+
+ if (subcommand === 'remove') {
+ const autoModId = interaction.options.getString('word', true);
+ const autoMod = await getAutoMod(autoModId);
+
+ if (!autoMod || autoMod.guildId !== interaction.guildId) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} That blocked word doesn't exist.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ await removeAutoMod(autoMod.id);
+ await interaction.reply({
+ content: `${emojis.rightArrow2} The word '${autoMod.word}' has been removed from the automod list.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ }
+ }
+}
diff --git a/apps/bot/src/commands/moderation/autorole/autorole.ts b/apps/bot/src/commands/moderation/autorole/autorole.ts
index bd204d4..cd6c733 100644
--- a/apps/bot/src/commands/moderation/autorole/autorole.ts
+++ b/apps/bot/src/commands/moderation/autorole/autorole.ts
@@ -1,183 +1,234 @@
import { Command } from '@sapphire/framework';
-import { MessageFlags, PermissionFlagsBits } from 'discord.js';
+import { ActionRowBuilder, ButtonBuilder, ButtonStyle, MessageFlags, PermissionFlagsBits } from 'discord.js';
import { createAutoRole, getAutoRole, getAutoRoles, removeAutoRole } from '#lib/autorole.js';
import { getQuestUnlimitedPurchaseComponents, LimitError } from '#lib/limits.js';
import { emojis } from '#utils/emoji.js';
+import { awaitMessageComponentSafe } from '#utils/collectors.js';
export class AutoRoleCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
-
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder
- .setName('autorole')
- .setDescription('Automatically assign roles to new members!')
- .setDefaultMemberPermissions(PermissionFlagsBits.ManageRoles)
- .addSubcommand((sub: any) =>
- sub
- .setName('add')
- .setDescription('Create a new auto role.')
- .addRoleOption((option: any) =>
- option.setName('role').setDescription('The role to assign to new members').setRequired(true)
- )
- .addBooleanOption((option: any) =>
- option.setName('bot_role').setDescription('Whether this role should be assigned to bots').setRequired(true)
- )
- )
- .addSubcommand((sub: any) =>
- sub
- .setName('remove')
- .setDescription('Remove an auto role.')
- .addStringOption((option: any) =>
- option
- .setName('role')
- .setDescription('The auto role to remove')
- .setAutocomplete(true)
- .setRequired(true)
- )
- )
- .addSubcommand((sub: any) =>
- sub
- .setName('list')
- .setDescription('List all auto roles.')
- )
- );
- }
-
- public override async autocompleteRun(interaction: Command.AutocompleteInteraction) {
- if (!interaction.guildId) {
- await interaction.respond([]);
- return;
- }
-
- const focusedOption = interaction.options.getFocused(true);
-
- if (interaction.options.getSubcommand() !== 'remove' || focusedOption.name !== 'role') {
- await interaction.respond([]);
- return;
- }
-
- const autoRoles = await getAutoRoles(interaction.guildId);
- const choices = autoRoles.slice(0, 25).map((autoRole) => ({
- name: interaction.guild?.roles.cache.get(autoRole.roleId)?.name ?? autoRole.roleId,
- value: autoRole.id
- }));
-
- await interaction.respond(choices);
- }
-
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- if (!interaction.inCachedGuild()) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This command can only be used in a server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const subcommand = interaction.options.getSubcommand();
-
- if (subcommand === 'add') {
- const role = interaction.options.getRole('role', true);
- const botRole = interaction.options.getBoolean('bot_role', true);
-
- if (!interaction.member.permissions.has(PermissionFlagsBits.ManageRoles)) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You do not have permission to configure auto roles.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (interaction.member.roles.highest.position <= role.position) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You can only configure auto roles for roles below your highest role.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- try {
- await createAutoRole(
- interaction.guildId,
- interaction.guild.name,
- role.id,
- botRole,
- interaction.client.application.entitlements
- );
- await interaction.reply({
- content: `${emojis.rightArrow2} Added auto role ${role} (Bot Role: ${botRole}).`,
- flags: MessageFlags.Ephemeral
- });
- } catch (err) {
- if (err instanceof LimitError) {
- if (err.showQuestUnlimitedPrompt) {
- await interaction.reply({
- content: `${emojis.questUnlimited2} ${err.message} Unlock unlimited auto roles with QuestUnlimited.`,
- components: getQuestUnlimitedPurchaseComponents(interaction.client.application.id),
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- await interaction.reply({
- content: `${emojis.rightArrow2} ${err.message}`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- console.error(err);
-
- await interaction.reply({
- content: `${emojis.rightArrow2} That role is already an auto role in this server.`,
- flags: MessageFlags.Ephemeral
- });
- }
- }
-
- if (subcommand === 'remove') {
- const autoRoleId = interaction.options.getString('role', true);
- const autoRole = await getAutoRole(autoRoleId);
-
- if (!autoRole || autoRole.guildId !== interaction.guildId) {
- await interaction.reply({
- content: `${emojis.rightArrow2} That auto role no longer exists.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- await removeAutoRole(autoRole.id);
- await interaction.reply({
- content: `${emojis.rightArrow2} Removed auto role for <@&${autoRole.roleId}>.`,
- flags: MessageFlags.Ephemeral
- });
- }
-
- if (subcommand === 'list') {
- const autoRoles = await getAutoRoles(interaction.guildId);
- if (autoRoles.length === 0) {
- await interaction.reply({
- content: `${emojis.rightArrow2} There are no auto roles set up in this server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const autoRoleList = autoRoles.map(autoRole => {
- const role = interaction.guild?.roles.cache.get(autoRole.roleId);
- const roleName = role ? `<@&${role.id}>` : `Unknown Role (${autoRole.roleId})`;
- const botRoleText = autoRole.botRole ? ' (Bot Role)' : '';
- return `${emojis.rightArrow1} ${roleName}${botRoleText}`;
- }).join('\n');
-
- await interaction.reply({
- content: `**Auto Roles:**\n${autoRoleList}`,
- flags: MessageFlags.Ephemeral
- });
- }
- }
-}
\ No newline at end of file
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
+
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder
+ .setName('autorole')
+ .setDescription('Automatically assign roles to new members!')
+ .setDefaultMemberPermissions(PermissionFlagsBits.ManageRoles)
+ .addSubcommand((sub: any) =>
+ sub
+ .setName('add')
+ .setDescription('Create a new auto role.')
+ .addRoleOption((option: any) =>
+ option.setName('role').setDescription('The role to assign to new members').setRequired(true),
+ )
+ .addBooleanOption((option: any) =>
+ option
+ .setName('bot_role')
+ .setDescription('Whether this role should be assigned to bots')
+ .setRequired(true),
+ ),
+ )
+ .addSubcommand((sub: any) =>
+ sub
+ .setName('remove')
+ .setDescription('Remove an auto role.')
+ .addStringOption((option: any) =>
+ option.setName('role').setDescription('The auto role to remove').setAutocomplete(true).setRequired(true).setMaxLength(36),
+ ),
+ )
+ .addSubcommand((sub: any) => sub.setName('list').setDescription('List all auto roles.')),
+ );
+ }
+
+ public override async autocompleteRun(interaction: Command.AutocompleteInteraction) {
+ if (!interaction.guildId) {
+ await interaction.respond([]);
+ return;
+ }
+
+ const focusedOption = interaction.options.getFocused(true);
+
+ if (interaction.options.getSubcommand() !== 'remove' || focusedOption.name !== 'role') {
+ await interaction.respond([]);
+ return;
+ }
+
+ const autoRoles = await getAutoRoles(interaction.guildId);
+ const choices = autoRoles.slice(0, 25).map((autoRole) => ({
+ name: interaction.guild?.roles.cache.get(autoRole.roleId)?.name ?? autoRole.roleId,
+ value: autoRole.id,
+ }));
+
+ await interaction.respond(choices);
+ }
+
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ if (!interaction.inCachedGuild()) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This command can only be used in a server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const subcommand = interaction.options.getSubcommand();
+
+ if (subcommand === 'add') {
+ const role = interaction.options.getRole('role', true);
+ const botRole = interaction.options.getBoolean('bot_role', true);
+
+ if (!interaction.member.permissions.has(PermissionFlagsBits.ManageRoles)) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You do not have permission to configure auto roles.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (interaction.member.roles.highest.position <= role.position) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You can only configure auto roles for roles below your highest role.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ try {
+ await createAutoRole(
+ interaction.guildId,
+ interaction.guild.name,
+ role.id,
+ botRole,
+ interaction.client.application.entitlements,
+ );
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Added auto role ${role} (Bot Role: ${botRole}).`,
+ flags: MessageFlags.Ephemeral,
+ });
+ } catch (err) {
+ if (err instanceof LimitError) {
+ if (err.showQuestUnlimitedPrompt) {
+ await interaction.reply({
+ content: `${emojis.questUnlimited2} ${err.message} Unlock unlimited auto roles with QuestUnlimited.`,
+ components: getQuestUnlimitedPurchaseComponents(interaction.client.application.id),
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ await interaction.reply({
+ content: `${emojis.rightArrow2} ${err.message}`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ console.error(err);
+
+ await interaction.reply({
+ content: `${emojis.rightArrow2} That role is already an auto role in this server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ }
+ }
+
+ if (subcommand === 'remove') {
+ const autoRoleId = interaction.options.getString('role', true);
+ const autoRole = await getAutoRole(autoRoleId);
+
+ if (!autoRole || autoRole.guildId !== interaction.guildId) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} That auto role no longer exists.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ await removeAutoRole(autoRole.id);
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Removed auto role for <@&${autoRole.roleId}>.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ }
+
+ if (subcommand === 'list') {
+ const autoRoles = await getAutoRoles(interaction.guildId);
+ if (autoRoles.length === 0) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} There are no auto roles set up in this server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const totalPages = Math.ceil(autoRoles.length / 10);
+ let page = 0;
+
+ const buildContent = (page: number) => {
+ const slice = autoRoles.slice(page * 10, (page + 1) * 10);
+ const roleList = slice
+ .map((autoRole) => {
+ const role = interaction.guild?.roles.cache.get(autoRole.roleId);
+ const roleName = role ? `<@&${role.id}>` : `Unknown Role (${autoRole.roleId})`;
+ const botRoleText = autoRole.botRole ? ' (Bot Role)' : '';
+ return `${emojis.rightArrow1} ${roleName}${botRoleText}`;
+ })
+ .join('\n');
+ return `**Auto Roles** (Page ${page + 1}/${totalPages}):\n${roleList}`;
+ };
+
+ const buildRow = (page: number) =>
+ new ActionRowBuilder().addComponents(
+ new ButtonBuilder()
+ .setCustomId('prev')
+ .setLabel('<')
+ .setStyle(ButtonStyle.Primary)
+ .setDisabled(page === 0),
+ new ButtonBuilder()
+ .setCustomId('next')
+ .setLabel('>')
+ .setStyle(ButtonStyle.Primary)
+ .setDisabled(page >= totalPages - 1),
+ );
+
+ if (totalPages === 1) {
+ await interaction.reply({
+ content: buildContent(0),
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const response = await interaction.reply({
+ content: buildContent(page),
+ components: [buildRow(page)],
+ flags: MessageFlags.Ephemeral,
+ withResponse: true,
+ });
+
+ const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
+
+ while (true) {
+ const btn = await awaitMessageComponentSafe(response.resource!.message!, {
+ filter: collectorFilter,
+ time: 60_000,
+ });
+
+ if (!btn) {
+ await interaction.editReply({ components: [] });
+ break;
+ }
+
+ if (btn.customId === 'prev') page = Math.max(0, page - 1);
+ if (btn.customId === 'next') page = Math.min(totalPages - 1, page + 1);
+
+ await btn.update({
+ content: buildContent(page),
+ components: [buildRow(page)],
+ });
+ }
+ }
+ }
+}
diff --git a/apps/bot/src/commands/moderation/ban/ban.ts b/apps/bot/src/commands/moderation/ban/ban.ts
index b70ecf0..5a871d0 100644
--- a/apps/bot/src/commands/moderation/ban/ban.ts
+++ b/apps/bot/src/commands/moderation/ban/ban.ts
@@ -1,169 +1,166 @@
import { Command } from '@sapphire/framework';
import {
- ActionRowBuilder,
- ButtonBuilder,
- ButtonStyle,
- GuildMember,
- MessageFlags,
- PermissionsBitField
+ ActionRowBuilder,
+ ButtonBuilder,
+ ButtonStyle,
+ GuildMember,
+ MessageFlags,
+ PermissionsBitField,
} from 'discord.js';
import ms, { type StringValue } from 'ms';
import { applyBan, createBan } from '#lib/bans.js';
import { emojis } from '#utils/emoji.js';
export class BanCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
-
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder
- .setName('ban')
- .setDescription('Ban someone from the discord server.')
- .addUserOption((option: any) =>
- option.setName('member').setDescription('Select a member to ban').setRequired(true)
- )
- .addStringOption((option: any) =>
- option.setName('reason').setDescription('Provide a reason for their ban')
- )
- .addStringOption((option: any) =>
- option.setName('duration').setDescription('Provide a duration for their ban (if needed)')
- )
- );
- }
-
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- if (!interaction.inCachedGuild()) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This command can only be used in a server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const member = interaction.member as GuildMember;
-
- if (!member.permissions.has(PermissionsBitField.Flags.BanMembers)) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You do not have permission to ban members.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const targetMember = interaction.options.getMember('member') as GuildMember;
- const reason = interaction.options.getString('reason') ?? 'No reason provided';
-
- const durationStr = interaction.options.getString('duration') as StringValue;
- const duration = durationStr ? ms(durationStr) : null;
- const expiresAt = duration ? new Date(Date.now() + duration) : null;
-
- if (!targetMember) {
- await interaction.reply({
- content: `${emojis.rightArrow2} That user is not in this server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (targetMember.id === interaction.user.id) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You cannot ban yourself.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (targetMember.id === interaction.guild.ownerId) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You cannot ban the server owner.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (!targetMember.bannable) {
- await interaction.reply({
- content: `${emojis.rightArrow2} I cannot ban this user.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const confirm = new ButtonBuilder()
- .setCustomId('confirm')
- .setLabel('Confirm Ban')
- .setStyle(ButtonStyle.Danger);
-
- const cancel = new ButtonBuilder()
- .setCustomId('cancel')
- .setLabel('Cancel')
- .setStyle(ButtonStyle.Secondary);
-
- const row = new ActionRowBuilder().addComponents(cancel, confirm);
-
- const response = await interaction.reply({
- content: `${emojis.rightArrow1} Are you sure you want to ban <@${targetMember.id}> for reason: ${reason}?`,
- components: [row],
- withResponse: true
- });
-
- const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
-
- try {
- const confirmation = await import('#utils/collectors.js').then((m) =>
- m.awaitMessageComponentSafe(response.resource!.message!, { filter: collectorFilter, time: 60_000 })
- );
-
- if (!confirmation) {
- await interaction.editReply({
- content: `${emojis.rightArrow2} No response within a minute or errored.`,
- components: []
- });
- return;
- }
-
- if (confirmation.customId === 'confirm') {
- try {
- await createBan(
- interaction.guild.id,
- interaction.guild.name,
- targetMember.id,
- expiresAt,
- reason
- );
- await applyBan(interaction.guild, targetMember.id, reason);
- await targetMember
- .send(
- `You have been banned from **${interaction.guild.name}**.\nReason: ${reason}${
- expiresAt ? `\nExpires: ` : ''
- }`
- )
- .catch(() => {});
- await confirmation.update({
- content: `${emojis.rightArrow2} <@${targetMember.user.id}> has been banned with reason: ${reason}`,
- components: []
- });
- } catch (err) {
- console.error(err);
- await confirmation.update({
- content: `${emojis.rightArrow2} Failed to ban <@${targetMember.user.id}> with reason: ${reason}`,
- components: []
- });
- }
- } else if (confirmation.customId === 'cancel') {
- await confirmation.update({
- content: `${emojis.rightArrow2} Cancelled.`,
- components: []
- });
- }
- } catch (err) {
- console.error(err);
- await interaction.editReply({
- content: `${emojis.rightArrow2} No response within a minute or errored.`,
- components: []
- });
- }
- }
-}
\ No newline at end of file
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
+
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder
+ .setName('ban')
+ .setDescription('Ban someone from the discord server.')
+ .addUserOption((option: any) =>
+ option.setName('member').setDescription('Select a member to ban').setRequired(true),
+ )
+ .addStringOption((option: any) => option.setName('reason').setDescription('Provide a reason for their ban').setMaxLength(512))
+ .addStringOption((option: any) =>
+ option.setName('duration').setDescription('Provide a duration for their ban (if needed)').setMaxLength(20),
+ ),
+ );
+ }
+
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ if (!interaction.inCachedGuild()) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This command can only be used in a server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const member = interaction.member as GuildMember;
+
+ if (!member.permissions.has(PermissionsBitField.Flags.BanMembers)) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You do not have permission to ban members.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const targetMember = interaction.options.getMember('member') as GuildMember;
+ const reason = interaction.options.getString('reason') ?? 'No reason provided';
+
+ const durationStr = interaction.options.getString('duration') as StringValue;
+ const duration = durationStr ? ms(durationStr) : null;
+ const expiresAt = duration ? new Date(Date.now() + duration) : null;
+
+ if (!targetMember) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} That user is not in this server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (targetMember.id === interaction.user.id) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You cannot ban yourself.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (targetMember.id === interaction.guild.ownerId) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You cannot ban the server owner.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (member.roles.highest.position <= targetMember.roles.highest.position) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You cannot moderate someone with a higher or equal role.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (!targetMember.bannable) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} I cannot ban this user.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const confirm = new ButtonBuilder().setCustomId('confirm').setLabel('Confirm Ban').setStyle(ButtonStyle.Danger);
+
+ const cancel = new ButtonBuilder().setCustomId('cancel').setLabel('Cancel').setStyle(ButtonStyle.Secondary);
+
+ const row = new ActionRowBuilder().addComponents(cancel, confirm);
+
+ const response = await interaction.reply({
+ content: `${emojis.rightArrow1} Are you sure you want to ban <@${targetMember.id}> for reason: ${reason}?`,
+ allowedMentions: { parse: [], users: [targetMember.user.id] },
+ components: [row],
+ withResponse: true,
+ });
+
+ const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
+
+ try {
+ const confirmation = await import('#utils/collectors.js').then((m) =>
+ m.awaitMessageComponentSafe(response.resource!.message!, { filter: collectorFilter, time: 60_000 }),
+ );
+
+ if (!confirmation) {
+ await interaction.editReply({
+ content: `${emojis.rightArrow2} No response within a minute or errored.`,
+ components: [],
+ });
+ return;
+ }
+
+ if (confirmation.customId === 'confirm') {
+ try {
+ await createBan(interaction.guild.id, interaction.guild.name, targetMember.id, expiresAt, reason);
+ await applyBan(interaction.guild, targetMember.id, reason);
+ await targetMember
+ .send(
+ `You have been banned from **${interaction.guild.name}**.\nReason: ${reason}${
+ expiresAt ? `\nExpires: ` : ''
+ }`,
+ )
+ .catch(() => {});
+ await confirmation.update({
+ content: `${emojis.rightArrow2} <@${targetMember.user.id}> has been banned with reason: ${reason}`,
+ allowedMentions: { parse: [], users: [targetMember.user.id] },
+ components: [],
+ });
+ } catch (err) {
+ console.error(err);
+ await confirmation.update({
+ content: `${emojis.rightArrow2} Failed to ban <@${targetMember.user.id}> with reason: ${reason}`,
+ allowedMentions: { parse: [], users: [targetMember.user.id] },
+ components: [],
+ });
+ }
+ } else if (confirmation.customId === 'cancel') {
+ await confirmation.update({
+ content: `${emojis.rightArrow2} Cancelled.`,
+ components: [],
+ });
+ }
+ } catch (err) {
+ console.error(err);
+ await interaction.editReply({
+ content: `${emojis.rightArrow2} No response within a minute or errored.`,
+ components: [],
+ });
+ }
+ }
+}
diff --git a/apps/bot/src/commands/moderation/ban/unban.ts b/apps/bot/src/commands/moderation/ban/unban.ts
index 933f998..512c6db 100644
--- a/apps/bot/src/commands/moderation/ban/unban.ts
+++ b/apps/bot/src/commands/moderation/ban/unban.ts
@@ -1,129 +1,124 @@
import { Command } from '@sapphire/framework';
import {
- ActionRowBuilder,
- ButtonBuilder,
- ButtonStyle,
- GuildMember,
- MessageFlags,
- PermissionsBitField
+ ActionRowBuilder,
+ ButtonBuilder,
+ ButtonStyle,
+ GuildMember,
+ MessageFlags,
+ PermissionsBitField,
} from 'discord.js';
import { getBan, removeBan } from '#lib/bans.js';
import { emojis } from '#utils/emoji.js';
export class UnbanCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
-
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder
- .setName('unban')
- .setDescription('Unban someone from the discord server.')
- .addUserOption((option: any) =>
- option.setName('member').setDescription('The member to unban').setRequired(true)
- )
- .addStringOption((option: any) =>
- option.setName('reason').setDescription('Provide a reason for their unban')
- )
- );
- }
-
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- if (!interaction.inCachedGuild()) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This command can only be used in a server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const member = interaction.member as GuildMember;
-
- if (!member.permissions.has(PermissionsBitField.Flags.BanMembers)) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You do not have permission to unban members.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const targetMember = interaction.options.getUser('member', true);
- const reason = interaction.options.getString('reason') ?? 'No reason provided';
-
- const discordBan = await interaction.guild.bans.fetch(targetMember.id).catch(() => null);
- const dbBan = await getBan(interaction.guild.id, targetMember.id);
-
- if (!discordBan && !dbBan) {
- await interaction.reply({
- content: `${emojis.rightArrow2} That user isn't banned.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const confirm = new ButtonBuilder()
- .setCustomId('confirm')
- .setLabel('Confirm Unban')
- .setStyle(ButtonStyle.Danger);
-
- const cancel = new ButtonBuilder()
- .setCustomId('cancel')
- .setLabel('Cancel')
- .setStyle(ButtonStyle.Secondary);
-
- const row = new ActionRowBuilder().addComponents(cancel, confirm);
-
- const response = await interaction.reply({
- content: `${emojis.rightArrow1} Are you sure you want to unban <@${targetMember.id}> for reason: ${reason}?`,
- components: [row],
- withResponse: true
- });
-
- const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
-
- try {
- const confirmation = await import('#utils/collectors.js').then((m) =>
- m.awaitMessageComponentSafe(response.resource!.message!, { filter: collectorFilter, time: 60_000 })
- );
-
- if (!confirmation) {
- await interaction.editReply({
- content: `${emojis.rightArrow2} No response within a minute or errored.`,
- components: []
- });
- return;
- }
-
- if (confirmation.customId === 'confirm') {
- try {
- await removeBan(interaction.guild, targetMember.id);
- await targetMember
- .send(`You have been unbanned in **${interaction.guild.name}**.\nReason: ${reason}`)
- .catch(() => {});
- await confirmation.update({
- content: `${emojis.rightArrow2} <@${targetMember.id}> has been unbanned with reason: ${reason}`,
- components: []
- });
- } catch (err) {
- console.error(err);
- await confirmation.update({
- content: `${emojis.rightArrow2} Failed to unban <@${targetMember.id}> with reason: ${reason}`,
- components: []
- });
- }
- } else if (confirmation.customId === 'cancel') {
- await confirmation.update({
- content: `${emojis.rightArrow2} Cancelled.`,
- components: []
- });
- }
- } catch (err) {
- console.error(err);
- await interaction.editReply({
- content: `${emojis.rightArrow2} No response within a minute or errored.`,
- components: []
- });
- }
- }
-}
\ No newline at end of file
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
+
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder
+ .setName('unban')
+ .setDescription('Unban someone from the discord server.')
+ .addUserOption((option: any) =>
+ option.setName('member').setDescription('The member to unban').setRequired(true),
+ )
+ .addStringOption((option: any) => option.setName('reason').setDescription('Provide a reason for their unban').setMaxLength(512)),
+ );
+ }
+
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ if (!interaction.inCachedGuild()) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This command can only be used in a server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const member = interaction.member as GuildMember;
+
+ if (!member.permissions.has(PermissionsBitField.Flags.BanMembers)) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You do not have permission to unban members.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const targetMember = interaction.options.getUser('member', true);
+ const reason = interaction.options.getString('reason') ?? 'No reason provided';
+
+ const discordBan = await interaction.guild.bans.fetch(targetMember.id).catch(() => null);
+ const dbBan = await getBan(interaction.guild.id, targetMember.id);
+
+ if (!discordBan && !dbBan) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} That user isn't banned.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const confirm = new ButtonBuilder().setCustomId('confirm').setLabel('Confirm Unban').setStyle(ButtonStyle.Danger);
+
+ const cancel = new ButtonBuilder().setCustomId('cancel').setLabel('Cancel').setStyle(ButtonStyle.Secondary);
+
+ const row = new ActionRowBuilder().addComponents(cancel, confirm);
+
+ const response = await interaction.reply({
+ content: `${emojis.rightArrow1} Are you sure you want to unban <@${targetMember.id}> for reason: ${reason}?`,
+ allowedMentions: { parse: [], users: [targetMember.id] },
+ components: [row],
+ withResponse: true,
+ });
+
+ const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
+
+ try {
+ const confirmation = await import('#utils/collectors.js').then((m) =>
+ m.awaitMessageComponentSafe(response.resource!.message!, { filter: collectorFilter, time: 60_000 }),
+ );
+
+ if (!confirmation) {
+ await interaction.editReply({
+ content: `${emojis.rightArrow2} No response within a minute or errored.`,
+ components: [],
+ });
+ return;
+ }
+
+ if (confirmation.customId === 'confirm') {
+ try {
+ await removeBan(interaction.guild, targetMember.id);
+ await targetMember
+ .send(`You have been unbanned in **${interaction.guild.name}**.\nReason: ${reason}`)
+ .catch(() => {});
+ await confirmation.update({
+ content: `${emojis.rightArrow2} <@${targetMember.id}> has been unbanned with reason: ${reason}`,
+ allowedMentions: { parse: [], users: [targetMember.id] },
+ components: [],
+ });
+ } catch (err) {
+ console.error(err);
+ await confirmation.update({
+ content: `${emojis.rightArrow2} Failed to unban <@${targetMember.id}> with reason: ${reason}`,
+ allowedMentions: { parse: [], users: [targetMember.id] },
+ components: [],
+ });
+ }
+ } else if (confirmation.customId === 'cancel') {
+ await confirmation.update({
+ content: `${emojis.rightArrow2} Cancelled.`,
+ components: [],
+ });
+ }
+ } catch (err) {
+ console.error(err);
+ await interaction.editReply({
+ content: `${emojis.rightArrow2} No response within a minute or errored.`,
+ components: [],
+ });
+ }
+ }
+}
diff --git a/apps/bot/src/commands/moderation/kick.ts b/apps/bot/src/commands/moderation/kick.ts
index 4fd3c28..fd4b841 100644
--- a/apps/bot/src/commands/moderation/kick.ts
+++ b/apps/bot/src/commands/moderation/kick.ts
@@ -1,149 +1,152 @@
import { Command } from '@sapphire/framework';
import {
- ActionRowBuilder,
- ButtonBuilder,
- ButtonStyle,
- GuildMember,
- MessageFlags,
- PermissionsBitField
+ ActionRowBuilder,
+ ButtonBuilder,
+ ButtonStyle,
+ GuildMember,
+ MessageFlags,
+ PermissionsBitField,
} from 'discord.js';
import { emojis } from '#utils/emoji.js';
export class KickCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
-
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder
- .setName('kick')
- .setDescription('Kick someone from the discord server.')
- .addUserOption((option: any) =>
- option.setName('member').setDescription('Select a member to kick').setRequired(true)
- )
- .addStringOption((option: any) =>
- option.setName('reason').setDescription('Provide a reason for their kick')
- )
- );
- }
-
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- if (!interaction.inCachedGuild()) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This command can only be used in a server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const member = interaction.member as GuildMember;
-
- if (!member.permissions.has(PermissionsBitField.Flags.KickMembers)) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You do not have permission to kick members.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const targetMember = interaction.options.getMember('member');
- const reason = interaction.options.getString('reason') ?? 'No reason provided';
-
- if (!targetMember) {
- await interaction.reply({
- content: `${emojis.rightArrow2} That user is not in this server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (targetMember.id === interaction.user.id) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You cannot kick yourself.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (targetMember.id === interaction.guild.ownerId) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You cannot kick the server owner.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (!targetMember.kickable) {
- await interaction.reply({
- content: `${emojis.rightArrow2} I cannot kick this user.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const confirm = new ButtonBuilder()
- .setCustomId('confirm')
- .setLabel('Confirm Kick')
- .setStyle(ButtonStyle.Danger);
-
- const cancel = new ButtonBuilder()
- .setCustomId('cancel')
- .setLabel('Cancel')
- .setStyle(ButtonStyle.Secondary);
-
- const row = new ActionRowBuilder().addComponents(cancel, confirm);
-
- const response = await interaction.reply({
- content: `${emojis.rightArrow1} Are you sure you want to kick <@${targetMember.user.id}> with reason: ${reason}?`,
- components: [row],
- withResponse: true
- });
-
- const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
-
- try {
- const confirmation = await import('#utils/collectors.js').then((m) =>
- m.awaitMessageComponentSafe(response.resource!.message!, { filter: collectorFilter, time: 60_000 })
- );
-
- if (!confirmation) {
- await interaction.editReply({
- content: `${emojis.rightArrow2} No response within a minute or errored.`,
- components: []
- });
- return;
- }
-
- if (confirmation.customId === 'confirm') {
- try {
- await interaction.guild.members.kick(targetMember);
- await targetMember
- .send(`You have been kicked from **${interaction.guild.name}**.\nReason: ${reason}`)
- .catch(() => {});
- await confirmation.update({
- content: `${emojis.rightArrow2} <@${targetMember.user.id}> has been kicked with reason: ${reason}\nYou must have had a real ick towards that person.`,
- components: []
- });
- } catch (err) {
- console.error(err);
- await confirmation.update({
- content: `${emojis.rightArrow2} Failed to kick <@${targetMember.user.id}> with reason: ${reason}\nYou must have had a real ick towards that person.`,
- components: []
- });
- }
- } else if (confirmation.customId === 'cancel') {
- await confirmation.update({
- content: `${emojis.rightArrow2} Cancelled.`,
- components: []
- });
- }
- } catch (err) {
- console.error(err);
- await interaction.editReply({
- content: `${emojis.rightArrow2} No response within a minute or errored.`,
- components: []
- });
- }
- }
-}
\ No newline at end of file
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
+
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder
+ .setName('kick')
+ .setDescription('Kick someone from the discord server.')
+ .addUserOption((option: any) =>
+ option.setName('member').setDescription('Select a member to kick').setRequired(true),
+ )
+ .addStringOption((option: any) => option.setName('reason').setDescription('Provide a reason for their kick').setMaxLength(512)),
+ );
+ }
+
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ if (!interaction.inCachedGuild()) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This command can only be used in a server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const member = interaction.member as GuildMember;
+
+ if (!member.permissions.has(PermissionsBitField.Flags.KickMembers)) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You do not have permission to kick members.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const targetMember = interaction.options.getMember('member');
+ const reason = interaction.options.getString('reason') ?? 'No reason provided';
+
+ if (!targetMember) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} That user is not in this server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (targetMember.id === interaction.user.id) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You cannot kick yourself.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (targetMember.id === interaction.guild.ownerId) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You cannot kick the server owner.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (member.roles.highest.position <= targetMember.roles.highest.position) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You cannot moderate someone with a higher or equal role.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (!targetMember.kickable) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} I cannot kick this user.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const confirm = new ButtonBuilder().setCustomId('confirm').setLabel('Confirm Kick').setStyle(ButtonStyle.Danger);
+
+ const cancel = new ButtonBuilder().setCustomId('cancel').setLabel('Cancel').setStyle(ButtonStyle.Secondary);
+
+ const row = new ActionRowBuilder().addComponents(cancel, confirm);
+
+ const response = await interaction.reply({
+ content: `${emojis.rightArrow1} Are you sure you want to kick <@${targetMember.user.id}> with reason: ${reason}?`,
+ allowedMentions: { parse: [], users: [targetMember.user.id] },
+ components: [row],
+ withResponse: true,
+ });
+
+ const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
+
+ try {
+ const confirmation = await import('#utils/collectors.js').then((m) =>
+ m.awaitMessageComponentSafe(response.resource!.message!, { filter: collectorFilter, time: 60_000 }),
+ );
+
+ if (!confirmation) {
+ await interaction.editReply({
+ content: `${emojis.rightArrow2} No response within a minute or errored.`,
+ components: [],
+ });
+ return;
+ }
+
+ if (confirmation.customId === 'confirm') {
+ try {
+ await interaction.guild.members.kick(targetMember);
+ await targetMember
+ .send(`You have been kicked from **${interaction.guild.name}**.\nReason: ${reason}`)
+ .catch(() => {});
+ await confirmation.update({
+ content: `${emojis.rightArrow2} <@${targetMember.user.id}> has been kicked with reason: ${reason}\nYou must have had a real ick towards that person.`,
+ allowedMentions: { parse: [], users: [targetMember.user.id] },
+ components: [],
+ });
+ } catch (err) {
+ console.error(err);
+ await confirmation.update({
+ content: `${emojis.rightArrow2} Failed to kick <@${targetMember.user.id}> with reason: ${reason}\nYou must have had a real ick towards that person.`,
+ allowedMentions: { parse: [], users: [targetMember.user.id] },
+ components: [],
+ });
+ }
+ } else if (confirmation.customId === 'cancel') {
+ await confirmation.update({
+ content: `${emojis.rightArrow2} Cancelled.`,
+ components: [],
+ });
+ }
+ } catch (err) {
+ console.error(err);
+ await interaction.editReply({
+ content: `${emojis.rightArrow2} No response within a minute or errored.`,
+ components: [],
+ });
+ }
+ }
+}
diff --git a/apps/bot/src/commands/moderation/mute/mute.ts b/apps/bot/src/commands/moderation/mute/mute.ts
index 101a264..638febd 100644
--- a/apps/bot/src/commands/moderation/mute/mute.ts
+++ b/apps/bot/src/commands/moderation/mute/mute.ts
@@ -1,172 +1,166 @@
import { Command } from '@sapphire/framework';
import {
- ActionRowBuilder,
- ButtonBuilder,
- ButtonStyle,
- GuildMember,
- MessageFlags,
- PermissionsBitField
+ ActionRowBuilder,
+ ButtonBuilder,
+ ButtonStyle,
+ GuildMember,
+ MessageFlags,
+ PermissionsBitField,
} from 'discord.js';
import ms, { type StringValue } from 'ms';
import { createMute, enforceMute } from '#lib/mutes.js';
import { emojis } from '#utils/emoji.js';
export class MuteCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
-
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder
- .setName('mute')
- .setDescription('Mute someone in the discord server.')
- .addUserOption((option: any) =>
- option.setName('member').setDescription('Select a member to mute').setRequired(true)
- )
- .addStringOption((option: any) =>
- option.setName('duration').setDescription('Specify a duration for the mute')
- )
- .addStringOption((option: any) =>
- option.setName('reason').setDescription('Provide a reason for their mute')
- )
- );
- }
-
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- if (!interaction.inCachedGuild()) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This command can only be used in a server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const member = interaction.member as GuildMember;
-
- if (!member.permissions.has(PermissionsBitField.Flags.ModerateMembers)) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You do not have permission to mute members.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const targetMember = interaction.options.getMember('member') as GuildMember;
- const reason = interaction.options.getString('reason') ?? 'No reason provided';
- const durationStr = interaction.options.getString('duration') as StringValue;
- const duration = durationStr ? ms(durationStr) : null;
- const expiresAt = duration ? new Date(Date.now() + duration) : null;
-
- if (!targetMember) {
- await interaction.reply({
- content: `${emojis.rightArrow2} That user is not in this server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (durationStr && (typeof duration !== 'number' || isNaN(duration))) {
- await interaction.reply({
- content: `${emojis.rightArrow2} Invalid duration format.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (targetMember.id === interaction.user.id) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You cannot mute yourself.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (targetMember.id === interaction.guild.ownerId) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You cannot mute the server owner.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (!targetMember.moderatable) {
- await interaction.reply({
- content: `${emojis.rightArrow2} I cannot mute this user.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const confirm = new ButtonBuilder()
- .setCustomId('confirm')
- .setLabel('Confirm Mute')
- .setStyle(ButtonStyle.Danger);
-
- const cancel = new ButtonBuilder()
- .setCustomId('cancel')
- .setLabel('Cancel')
- .setStyle(ButtonStyle.Secondary);
-
- const row = new ActionRowBuilder().addComponents(cancel, confirm);
-
- const response = await interaction.reply({
- content: `${emojis.rightArrow1} Are you sure you want to mute <@${targetMember.user.id}> with reason: ${reason}?`,
- components: [row],
- withResponse: true
- });
-
- const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
-
- try {
- const confirmation = await import('#utils/collectors.js').then((m) =>
- m.awaitMessageComponentSafe(response.resource!.message!, { filter: collectorFilter, time: 60_000 })
- );
-
- if (!confirmation) {
- await interaction.editReply({
- content: `${emojis.rightArrow2} No response within a minute or errored.`,
- components: []
- });
- return;
- }
-
- if (confirmation.customId === 'confirm') {
- await createMute(
- interaction.guild.id,
- interaction.guild.name,
- targetMember.id,
- expiresAt,
- reason
- );
-
- await targetMember
- .send(
- `You have been muted in **${interaction.guild.name}**.\nReason: ${reason}${
- expiresAt ? `\nExpires: ` : ''
- }`
- )
- .catch(() => {});
-
- await enforceMute(interaction.guild, targetMember.id);
- await confirmation.update({
- content: `${emojis.rightArrow2} <@${targetMember.user.id}> has been muted with reason: ${reason}${
- expiresAt ? `\nExpires: ` : ''
- }`,
- components: []
- });
- } else if (confirmation.customId === 'cancel') {
- await confirmation.update({
- content: `${emojis.rightArrow2} Cancelled.`,
- components: []
- });
- }
- } catch (err) {
- console.error(err);
- await interaction.editReply({
- content: `${emojis.rightArrow2} No response within a minute or errored.`,
- components: []
- });
- }
- }
-}
\ No newline at end of file
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
+
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder
+ .setName('mute')
+ .setDescription('Mute someone in the discord server.')
+ .addUserOption((option: any) =>
+ option.setName('member').setDescription('Select a member to mute').setRequired(true),
+ )
+ .addStringOption((option: any) => option.setName('duration').setDescription('Specify a duration for the mute').setMaxLength(20))
+ .addStringOption((option: any) => option.setName('reason').setDescription('Provide a reason for their mute').setMaxLength(512)),
+ );
+ }
+
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ if (!interaction.inCachedGuild()) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This command can only be used in a server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const member = interaction.member as GuildMember;
+
+ if (!member.permissions.has(PermissionsBitField.Flags.ModerateMembers)) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You do not have permission to mute members.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const targetMember = interaction.options.getMember('member') as GuildMember;
+ const reason = interaction.options.getString('reason') ?? 'No reason provided';
+ const durationStr = interaction.options.getString('duration') as StringValue;
+ const duration = durationStr ? ms(durationStr) : null;
+ const expiresAt = duration ? new Date(Date.now() + duration) : null;
+
+ if (!targetMember) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} That user is not in this server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (durationStr && (typeof duration !== 'number' || isNaN(duration))) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Invalid duration format.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (targetMember.id === interaction.user.id) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You cannot mute yourself.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (targetMember.id === interaction.guild.ownerId) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You cannot mute the server owner.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (member.roles.highest.position <= targetMember.roles.highest.position) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You cannot moderate someone with a higher or equal role.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (!targetMember.moderatable) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} I cannot mute this user.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const confirm = new ButtonBuilder().setCustomId('confirm').setLabel('Confirm Mute').setStyle(ButtonStyle.Danger);
+
+ const cancel = new ButtonBuilder().setCustomId('cancel').setLabel('Cancel').setStyle(ButtonStyle.Secondary);
+
+ const row = new ActionRowBuilder().addComponents(cancel, confirm);
+
+ const response = await interaction.reply({
+ content: `${emojis.rightArrow1} Are you sure you want to mute <@${targetMember.user.id}> with reason: ${reason}?`,
+ allowedMentions: { parse: [], users: [targetMember.user.id] },
+ components: [row],
+ withResponse: true,
+ });
+
+ const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
+
+ try {
+ const confirmation = await import('#utils/collectors.js').then((m) =>
+ m.awaitMessageComponentSafe(response.resource!.message!, { filter: collectorFilter, time: 60_000 }),
+ );
+
+ if (!confirmation) {
+ await interaction.editReply({
+ content: `${emojis.rightArrow2} No response within a minute or errored.`,
+ components: [],
+ });
+ return;
+ }
+
+ if (confirmation.customId === 'confirm') {
+ await createMute(interaction.guild.id, interaction.guild.name, targetMember.id, expiresAt, reason);
+
+ await targetMember
+ .send(
+ `You have been muted in **${interaction.guild.name}**.\nReason: ${reason}${
+ expiresAt ? `\nExpires: ` : ''
+ }`,
+ )
+ .catch(() => {});
+
+ await enforceMute(interaction.guild, targetMember.id);
+ await confirmation.update({
+ content: `${emojis.rightArrow2} <@${targetMember.user.id}> has been muted with reason: ${reason}${
+ expiresAt ? `\nExpires: ` : ''
+ }`,
+ allowedMentions: { parse: [], users: [targetMember.user.id] },
+ components: [],
+ });
+ } else if (confirmation.customId === 'cancel') {
+ await confirmation.update({
+ content: `${emojis.rightArrow2} Cancelled.`,
+ components: [],
+ });
+ }
+ } catch (err) {
+ console.error(err);
+ await interaction.editReply({
+ content: `${emojis.rightArrow2} No response within a minute or errored.`,
+ components: [],
+ });
+ }
+ }
+}
diff --git a/apps/bot/src/commands/moderation/mute/unmute.ts b/apps/bot/src/commands/moderation/mute/unmute.ts
index 2a79b6a..5e2548f 100644
--- a/apps/bot/src/commands/moderation/mute/unmute.ts
+++ b/apps/bot/src/commands/moderation/mute/unmute.ts
@@ -1,136 +1,136 @@
import { Command } from '@sapphire/framework';
import {
- ActionRowBuilder,
- ButtonBuilder,
- ButtonStyle,
- GuildMember,
- MessageFlags,
- PermissionsBitField
+ ActionRowBuilder,
+ ButtonBuilder,
+ ButtonStyle,
+ GuildMember,
+ MessageFlags,
+ PermissionsBitField,
} from 'discord.js';
import { removeMute } from '#lib/mutes.js';
import { emojis } from '#utils/emoji.js';
export class UnmuteCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
-
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder
- .setName('unmute')
- .setDescription('Unmute someone in the discord server.')
- .addUserOption((option: any) =>
- option.setName('member').setDescription('Select a member to unmute').setRequired(true)
- )
- .addStringOption((option: any) =>
- option.setName('reason').setDescription('Provide a reason for their unmute')
- )
- );
- }
-
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- if (!interaction.inCachedGuild()) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This command can only be used in a server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const member = interaction.member as GuildMember;
-
- if (!member.permissions.has(PermissionsBitField.Flags.ModerateMembers)) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You do not have permission to unmute members.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const targetMember = interaction.options.getMember('member') as GuildMember;
- const reason = interaction.options.getString('reason') ?? 'No reason provided';
-
- if (!targetMember) {
- await interaction.reply({
- content: `${emojis.rightArrow2} That user is not in this server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (!targetMember.moderatable) {
- await interaction.reply({
- content: `${emojis.rightArrow2} I cannot unmute this user.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const confirm = new ButtonBuilder()
- .setCustomId('confirm')
- .setLabel('Confirm Unmute')
- .setStyle(ButtonStyle.Danger);
-
- const cancel = new ButtonBuilder()
- .setCustomId('cancel')
- .setLabel('Cancel')
- .setStyle(ButtonStyle.Secondary);
-
- const row = new ActionRowBuilder().addComponents(cancel, confirm);
-
- const response = await interaction.reply({
- content: `${emojis.rightArrow1} Are you sure you want to unmute <@${targetMember.user.id}> with reason: ${reason}?`,
- components: [row],
- withResponse: true
- });
-
- const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
-
- try {
- const confirmation = await import('#utils/collectors.js').then((m) =>
- m.awaitMessageComponentSafe(response.resource!.message!, { filter: collectorFilter, time: 60_000 })
- );
-
- if (!confirmation) {
- await interaction.editReply({
- content: `${emojis.rightArrow2} No response within a minute or errored.`,
- components: []
- });
- return;
- }
-
- if (confirmation.customId === 'confirm') {
- try {
- await Promise.all([
- removeMute(interaction.guild.id, targetMember.id),
- targetMember.timeout(null, reason)
- ]);
- await targetMember
- .send(`You have been unmuted in **${interaction.guild.name}**.\nReason: ${reason}`)
- .catch(() => {});
- await confirmation.update({
- content: `${emojis.rightArrow2} <@${targetMember.id}> has been unmuted. Reason: ${reason}`,
- components: []
- });
- } catch (err) {
- console.error(err);
- await confirmation.update({
- content: `${emojis.rightArrow2} Failed to unmute <@${targetMember.id}> with reason: ${reason}`,
- components: []
- });
- }
- } else if (confirmation.customId === 'cancel') {
- await confirmation.update({
- content: `${emojis.rightArrow2} Cancelled.`,
- components: []
- });
- }
- } catch {
- await interaction.editReply({
- content: `${emojis.rightArrow2} No response within a minute or errored.`,
- components: []
- });
- }
- }
-}
\ No newline at end of file
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
+
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder
+ .setName('unmute')
+ .setDescription('Unmute someone in the discord server.')
+ .addUserOption((option: any) =>
+ option.setName('member').setDescription('Select a member to unmute').setRequired(true),
+ )
+ .addStringOption((option: any) => option.setName('reason').setDescription('Provide a reason for their unmute').setMaxLength(512)),
+ );
+ }
+
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ if (!interaction.inCachedGuild()) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This command can only be used in a server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const member = interaction.member as GuildMember;
+
+ if (!member.permissions.has(PermissionsBitField.Flags.ModerateMembers)) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You do not have permission to unmute members.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const targetMember = interaction.options.getMember('member') as GuildMember;
+ const reason = interaction.options.getString('reason') ?? 'No reason provided';
+
+ if (!targetMember) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} That user is not in this server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (member.roles.highest.position <= targetMember.roles.highest.position) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You cannot moderate someone with a higher or equal role.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (!targetMember.moderatable) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} I cannot unmute this user.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const confirm = new ButtonBuilder().setCustomId('confirm').setLabel('Confirm Unmute').setStyle(ButtonStyle.Danger);
+
+ const cancel = new ButtonBuilder().setCustomId('cancel').setLabel('Cancel').setStyle(ButtonStyle.Secondary);
+
+ const row = new ActionRowBuilder().addComponents(cancel, confirm);
+
+ const response = await interaction.reply({
+ content: `${emojis.rightArrow1} Are you sure you want to unmute <@${targetMember.user.id}> with reason: ${reason}?`,
+ allowedMentions: { parse: [], users: [targetMember.user.id] },
+ components: [row],
+ withResponse: true,
+ });
+
+ const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
+
+ try {
+ const confirmation = await import('#utils/collectors.js').then((m) =>
+ m.awaitMessageComponentSafe(response.resource!.message!, { filter: collectorFilter, time: 60_000 }),
+ );
+
+ if (!confirmation) {
+ await interaction.editReply({
+ content: `${emojis.rightArrow2} No response within a minute or errored.`,
+ components: [],
+ });
+ return;
+ }
+
+ if (confirmation.customId === 'confirm') {
+ try {
+ await Promise.all([removeMute(interaction.guild.id, targetMember.id), targetMember.timeout(null, reason)]);
+ await targetMember
+ .send(`You have been unmuted in **${interaction.guild.name}**.\nReason: ${reason}`)
+ .catch(() => {});
+ await confirmation.update({
+ content: `${emojis.rightArrow2} <@${targetMember.id}> has been unmuted. Reason: ${reason}`,
+ allowedMentions: { parse: [], users: [targetMember.user.id] },
+ components: [],
+ });
+ } catch (err) {
+ console.error(err);
+ await confirmation.update({
+ content: `${emojis.rightArrow2} Failed to unmute <@${targetMember.id}> with reason: ${reason}`,
+ allowedMentions: { parse: [], users: [targetMember.user.id] },
+ components: [],
+ });
+ }
+ } else if (confirmation.customId === 'cancel') {
+ await confirmation.update({
+ content: `${emojis.rightArrow2} Cancelled.`,
+ components: [],
+ });
+ }
+ } catch {
+ await interaction.editReply({
+ content: `${emojis.rightArrow2} No response within a minute or errored.`,
+ components: [],
+ });
+ }
+ }
+}
diff --git a/apps/bot/src/commands/moderation/nick.ts b/apps/bot/src/commands/moderation/nick.ts
index 3c8e1f1..c5030d7 100644
--- a/apps/bot/src/commands/moderation/nick.ts
+++ b/apps/bot/src/commands/moderation/nick.ts
@@ -3,83 +3,89 @@ import { GuildMember, MessageFlags, PermissionsBitField } from 'discord.js';
import { emojis } from '#utils/emoji.js';
export class NickCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder
- .setName('nick')
- .setDescription("Change a member's nickname.")
- .addUserOption((option: any) =>
- option.setName('member').setDescription('Select a member to change their nickname').setRequired(true)
- )
- .addStringOption((option: any) =>
- option.setName('nickname').setDescription('Nickname (leave empty to reset)')
- )
- );
- }
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder
+ .setName('nick')
+ .setDescription("Change a member's nickname.")
+ .addUserOption((option: any) =>
+ option.setName('member').setDescription('Select a member to change their nickname').setRequired(true),
+ )
+ .addStringOption((option: any) => option.setName('nickname').setDescription('Nickname (leave empty to reset)').setMaxLength(32)),
+ );
+ }
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- if (!interaction.inCachedGuild()) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This command can only be used in a server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ if (!interaction.inCachedGuild()) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This command can only be used in a server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
- const member = interaction.member as GuildMember;
+ const member = interaction.member as GuildMember;
- if (!member.permissions.has(PermissionsBitField.Flags.ManageNicknames)) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You do not have permission to manage nicknames.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
+ if (!member.permissions.has(PermissionsBitField.Flags.ManageNicknames)) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You do not have permission to manage nicknames.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
- const targetMember = interaction.options.getMember('member');
- const nickname = interaction.options.getString('nickname') ?? null;
+ const targetMember = interaction.options.getMember('member');
+ const nickname = interaction.options.getString('nickname') ?? null;
- if (!targetMember) {
- await interaction.reply({
- content: `${emojis.rightArrow2} That user is not in this server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
+ if (!targetMember) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} That user is not in this server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
- if (targetMember.id === interaction.guild.ownerId) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You cannot change the server owner's nickname.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
+ if (targetMember.id === interaction.guild.ownerId) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You cannot change the server owner's nickname.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
- if (!targetMember.manageable) {
- await interaction.reply({
- content: `${emojis.rightArrow2} I cannot manage this member's nickname.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
+ if (member.roles.highest.position <= targetMember.roles.highest.position) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You cannot moderate someone with a higher or equal role.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
- try {
- await targetMember.setNickname(nickname);
- await interaction.reply({
- content: nickname
- ? `${emojis.rightArrow2} Set <@${targetMember.user.id}>'s nickname to **${nickname}**.`
- : `${emojis.rightArrow2} Reseted <@${targetMember.user.id}>'s nickname.`,
- flags: MessageFlags.Ephemeral
- });
- } catch {
- await interaction.reply({
- content: `${emojis.rightArrow2} Failed to update <@${targetMember.user.id}>'s nickname.`,
- flags: MessageFlags.Ephemeral
- });
- }
- }
+ if (!targetMember.manageable) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} I cannot manage this member's nickname.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ try {
+ await targetMember.setNickname(nickname);
+ await interaction.reply({
+ content: nickname
+ ? `${emojis.rightArrow2} Set <@${targetMember.user.id}>'s nickname to **${nickname}**.`
+ : `${emojis.rightArrow2} Reseted <@${targetMember.user.id}>'s nickname.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ } catch {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Failed to update <@${targetMember.user.id}>'s nickname.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ }
+ }
}
diff --git a/apps/bot/src/commands/moderation/purge.ts b/apps/bot/src/commands/moderation/purge.ts
index cb5220c..f723f53 100644
--- a/apps/bot/src/commands/moderation/purge.ts
+++ b/apps/bot/src/commands/moderation/purge.ts
@@ -5,114 +5,112 @@ import { MessageFlags, PermissionsBitField } from 'discord.js';
const FOURTEEN_DAYS = 14 * 24 * 60 * 60 * 1000;
export class PurgeCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
-
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder
- .setName('purge')
- .setDescription('Purge messages from a channel.')
- .addIntegerOption((option: any) =>
- option
- .setName('amount')
- .setDescription('The number of messages to purge')
- .setRequired(true)
- .setMinValue(1)
- .setMaxValue(1000)
- )
- );
- }
-
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- if (!interaction.inCachedGuild()) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This command can only be used in a server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const member = interaction.member;
-
- if (!member || !('permissions' in member) || !member.permissions.has(PermissionsBitField.Flags.ManageMessages)) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You do not have permission to manage messages.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const amount = interaction.options.getInteger('amount') ?? 0;
- if (amount <= 0) {
- await interaction.reply({
- content: `${emojis.rightArrow2} Please provide a valid number of messages to purge.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const channel = interaction.channel;
- if (!channel || !('messages' in channel)) {
- await interaction.reply({
- content: `${emojis.rightArrow2} Unable to access channel messages.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- await interaction.deferReply({ ephemeral: true });
- await interaction.editReply(`${emojis.rightArrow2} Purging ${amount} messages...`);
-
- let remaining = amount;
- let deletedTotal = 0;
-
- try {
- while (remaining > 0) {
- const fetchLimit = Math.min(remaining, 100);
- const fetched = await channel.messages.fetch({ limit: fetchLimit as number });
- if (!fetched.size) break;
-
- const now = Date.now();
- const recentMessages = fetched.filter((message: any) => now - message.createdTimestamp < FOURTEEN_DAYS);
- const oldMessages = fetched.filter((message: any) => now - message.createdTimestamp >= FOURTEEN_DAYS);
-
- if (recentMessages.size) {
- const deleted = await channel.bulkDelete(recentMessages, true);
- deletedTotal += deleted.size;
- remaining -= deleted.size;
- }
-
- if (oldMessages.size && remaining > 0) {
- const messagesToDelete = oldMessages.first(Math.min(oldMessages.size, remaining));
-
- for (const message of messagesToDelete) {
- try {
- await channel.messages.delete(message.id);
- deletedTotal += 1;
- remaining -= 1;
- } catch (err) {
- console.error('Failed to delete old message', err);
- }
-
- if (remaining <= 0) break;
- }
- }
-
- await interaction.editReply(
- `${emojis.rightArrow2} Purging messages... deleted ${deletedTotal}/${amount}`
- );
-
- if (recentMessages.size === 0 && oldMessages.size === 0) break;
- }
-
- await interaction.editReply(`${emojis.rightArrow1} Successfully purged ${deletedTotal} messages.`);
- } catch (err) {
- console.error(err);
- await interaction.editReply({
- content: `${emojis.rightArrow2} An error occurred while trying to purge messages.`,
- });
- }
- }
-}
\ No newline at end of file
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
+
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder
+ .setName('purge')
+ .setDescription('Purge messages from a channel.')
+ .addIntegerOption((option: any) =>
+ option
+ .setName('amount')
+ .setDescription('The number of messages to purge')
+ .setRequired(true)
+ .setMinValue(1)
+ .setMaxValue(1000),
+ ),
+ );
+ }
+
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ if (!interaction.inCachedGuild()) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This command can only be used in a server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const member = interaction.member;
+ const channel = interaction.channel;
+
+ if (!channel || !('messages' in channel)) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Unable to access channel messages.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (!member || !('permissions' in member) || !channel.permissionsFor(member)?.has(PermissionsBitField.Flags.ManageMessages)) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You do not have permission to manage messages.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const amount = interaction.options.getInteger('amount') ?? 0;
+ if (amount <= 0) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Please provide a valid number of messages to purge.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ await interaction.deferReply({ ephemeral: true });
+ await interaction.editReply(`${emojis.rightArrow2} Purging ${amount} messages...`);
+
+ let remaining = amount;
+ let deletedTotal = 0;
+
+ try {
+ while (remaining > 0) {
+ const fetchLimit = Math.min(remaining, 100);
+ const fetched = await channel.messages.fetch({ limit: fetchLimit as number });
+ if (!fetched.size) break;
+
+ const now = Date.now();
+ const recentMessages = fetched.filter((message: any) => now - message.createdTimestamp < FOURTEEN_DAYS);
+ const oldMessages = fetched.filter((message: any) => now - message.createdTimestamp >= FOURTEEN_DAYS);
+
+ if (recentMessages.size) {
+ const deleted = await channel.bulkDelete(recentMessages, true);
+ deletedTotal += deleted.size;
+ remaining -= deleted.size;
+ }
+
+ if (oldMessages.size && remaining > 0) {
+ const messagesToDelete = oldMessages.first(Math.min(oldMessages.size, remaining));
+
+ for (const message of messagesToDelete) {
+ try {
+ await channel.messages.delete(message.id);
+ deletedTotal += 1;
+ remaining -= 1;
+ } catch (err) {
+ console.error('Failed to delete old message', err);
+ }
+
+ if (remaining <= 0) break;
+ }
+ }
+
+ await interaction.editReply(`${emojis.rightArrow2} Purging messages... deleted ${deletedTotal}/${amount}`);
+
+ if (recentMessages.size === 0 && oldMessages.size === 0) break;
+ }
+
+ await interaction.editReply(`${emojis.rightArrow1} Successfully purged ${deletedTotal} messages.`);
+ } catch (err) {
+ console.error(err);
+ await interaction.editReply({
+ content: `${emojis.rightArrow2} An error occurred while trying to purge messages.`,
+ });
+ }
+ }
+}
diff --git a/apps/bot/src/commands/moderation/slowmode.ts b/apps/bot/src/commands/moderation/slowmode.ts
index c0be7ba..b161d3e 100644
--- a/apps/bot/src/commands/moderation/slowmode.ts
+++ b/apps/bot/src/commands/moderation/slowmode.ts
@@ -6,87 +6,86 @@ import { emojis } from '#utils/emoji.js';
const MAX_SLOWMODE_SECONDS = 21_600;
export class SlowmodeCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder
- .setName('slowmode')
- .setDescription('Set or clear the slowmode for the current channel.')
- .addStringOption((option: any) =>
- option.setName('duration').setDescription('Provide a duration for slowmode, or leave blank to remove it')
- )
- );
- }
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder
+ .setName('slowmode')
+ .setDescription('Set or clear the slowmode for the current channel.')
+ .addStringOption((option: any) =>
+ option.setName('duration').setDescription('Provide a duration for slowmode, or leave blank to remove it').setMaxLength(20),
+ ),
+ );
+ }
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- if (!interaction.inCachedGuild()) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This command can only be used in a server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ if (!interaction.inCachedGuild()) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This command can only be used in a server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
- const member = interaction.member;
+ const member = interaction.member;
+ const channel = interaction.channel;
- if (!member || !('permissions' in member) || !member.permissions.has(PermissionsBitField.Flags.ManageChannels)) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You do not have permission to manage channels.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
+ if (!channel || !('setRateLimitPerUser' in channel)) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This channel does not support slowmode.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
- const channel = interaction.channel;
+ if (!member || !('permissions' in member) || !channel.permissionsFor(member)?.has(PermissionsBitField.Flags.ManageChannels)) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You do not have permission to manage channels.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
- if (!channel || !('setRateLimitPerUser' in channel)) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This channel does not support slowmode.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
+ const durationStr = interaction.options.getString('duration') as StringValue;
+ const durationMs = durationStr ? ms(durationStr) : null;
- const durationStr = interaction.options.getString('duration') as StringValue;
- const durationMs = durationStr ? ms(durationStr) : null;
+ if (durationStr && (typeof durationMs !== 'number' || Number.isNaN(durationMs))) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Invalid duration format.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
- if (durationStr && (typeof durationMs !== 'number' || Number.isNaN(durationMs))) {
- await interaction.reply({
- content: `${emojis.rightArrow2} Invalid duration format.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
+ const slowmodeSeconds = durationStr ? Math.floor((durationMs ?? 0) / 1000) : 0;
- const slowmodeSeconds = durationStr ? Math.floor((durationMs ?? 0) / 1000) : 0;
+ if (slowmodeSeconds < 0 || slowmodeSeconds > MAX_SLOWMODE_SECONDS) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Slowmode must be between 0 seconds and 6 hours.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
- if (slowmodeSeconds < 0 || slowmodeSeconds > MAX_SLOWMODE_SECONDS) {
- await interaction.reply({
- content: `${emojis.rightArrow2} Slowmode must be between 0 seconds and 6 hours.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
+ try {
+ await channel.setRateLimitPerUser(slowmodeSeconds);
- try {
- await channel.setRateLimitPerUser(slowmodeSeconds);
-
- await interaction.reply({
- content:
- slowmodeSeconds === 0
- ? `${emojis.rightArrow1} Slowmode cleared in <#${channel.id}>.`
- : `${emojis.rightArrow1} Slowmode set to ${slowmodeSeconds} second${slowmodeSeconds === 1 ? '' : 's'} in <#${channel.id}>.`,
- flags: MessageFlags.Ephemeral
- });
- } catch (error) {
- console.error(error);
- await interaction.reply({
- content: `${emojis.rightArrow2} Failed to update slowmode for this channel.`,
- flags: MessageFlags.Ephemeral
- });
- }
- }
-}
\ No newline at end of file
+ await interaction.reply({
+ content:
+ slowmodeSeconds === 0
+ ? `${emojis.rightArrow1} Slowmode cleared in <#${channel.id}>.`
+ : `${emojis.rightArrow1} Slowmode set to ${slowmodeSeconds} second${slowmodeSeconds === 1 ? '' : 's'} in <#${channel.id}>.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ } catch (error) {
+ console.error(error);
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Failed to update slowmode for this channel.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ }
+ }
+}
diff --git a/apps/bot/src/commands/moderation/warn/unwarn.ts b/apps/bot/src/commands/moderation/warn/unwarn.ts
index f3ec394..28ae75b 100644
--- a/apps/bot/src/commands/moderation/warn/unwarn.ts
+++ b/apps/bot/src/commands/moderation/warn/unwarn.ts
@@ -1,130 +1,125 @@
import { Command } from '@sapphire/framework';
import {
- ActionRowBuilder,
- ButtonBuilder,
- ButtonStyle,
- GuildMember,
- MessageFlags,
- PermissionsBitField
+ ActionRowBuilder,
+ ButtonBuilder,
+ ButtonStyle,
+ GuildMember,
+ MessageFlags,
+ PermissionsBitField,
} from 'discord.js';
import { getWarn, removeWarn } from '#lib/warns.js';
import { emojis } from '#utils/emoji.js';
export class UnwarnCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
-
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder
- .setName('unwarn')
- .setDescription('Unwarn someone in the discord server.')
- .addStringOption((option: any) =>
- option.setName('id').setDescription('The ID of the warn to remove').setRequired(true)
- )
- .addStringOption((option: any) =>
- option.setName('reason').setDescription('Provide a reason for removing the warn')
- )
- );
- }
-
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- if (!interaction.inCachedGuild()) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This command can only be used in a server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const member = interaction.member as GuildMember;
-
- if (!member.permissions.has(PermissionsBitField.Flags.ModerateMembers)) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You do not have permission to remove warns.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const warnId = interaction.options.getString('id', true);
- const reason = interaction.options.getString('reason') ?? 'No reason provided';
-
- const warn = await getWarn(warnId, interaction.guild.id);
-
- if (!warn) {
- await interaction.reply({
- content: `${emojis.rightArrow2} No warn found with that ID in this server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const confirm = new ButtonBuilder()
- .setCustomId('confirm')
- .setLabel('Confirm Unwarn')
- .setStyle(ButtonStyle.Danger);
-
- const cancel = new ButtonBuilder()
- .setCustomId('cancel')
- .setLabel('Cancel')
- .setStyle(ButtonStyle.Secondary);
-
- const row = new ActionRowBuilder().addComponents(cancel, confirm);
-
- const response = await interaction.reply({
- content: `${emojis.rightArrow1} Are you sure you want to unwarn <@${warn.userId}> with reason: ${reason}?\n${emojis.rightArrow2} They were warned for: ${warn.reason} `,
- components: [row],
- withResponse: true
- });
-
- const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
-
- try {
- const confirmation = await import('#utils/collectors.js').then((m) =>
- m.awaitMessageComponentSafe(response.resource!.message!, { filter: collectorFilter, time: 60_000 })
- );
-
- if (!confirmation) {
- await interaction.editReply({
- content: `${emojis.rightArrow2} No response within a minute or errored.`,
- components: []
- });
- return;
- }
-
- if (confirmation.customId === 'confirm') {
- try {
- await removeWarn(warn.id);
- const user = await interaction.client.users.fetch(warn.userId);
- await user
- .send(
- `Your warn for ${warn.reason} in **${interaction.guild.name}** has been removed.\nReason: ${reason}`
- )
- .catch(() => {});
- await confirmation.update({
- content: `${emojis.rightArrow2} \`${warn.id}\` has been removed from <@${warn.userId}>. Reason: ${reason}`,
- components: []
- });
- } catch (err) {
- console.error(`Failed to remove warn ${warn.id}:`, err);
- await confirmation.update({
- content: `${emojis.rightArrow2} Failed to remove warn \`${warn.id}\` from <@${warn.userId}>.`,
- components: []
- });
- }
- } else if (confirmation.customId === 'cancel') {
- await confirmation.update({
- content: `${emojis.rightArrow2} Cancelled.`,
- components: []
- });
- }
- } catch {
- await interaction.editReply({
- content: `${emojis.rightArrow2} No response within a minute or errored.`,
- components: []
- });
- }
- }
-}
\ No newline at end of file
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
+
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder
+ .setName('unwarn')
+ .setDescription('Unwarn someone in the discord server.')
+ .addStringOption((option: any) =>
+ option.setName('id').setDescription('The ID of the warn to remove').setRequired(true).setMaxLength(36),
+ )
+ .addStringOption((option: any) =>
+ option.setName('reason').setDescription('Provide a reason for removing the warn').setMaxLength(512),
+ ),
+ );
+ }
+
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ if (!interaction.inCachedGuild()) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This command can only be used in a server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const member = interaction.member as GuildMember;
+
+ if (!member.permissions.has(PermissionsBitField.Flags.ModerateMembers)) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You do not have permission to remove warns.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const warnId = interaction.options.getString('id', true);
+ const reason = interaction.options.getString('reason') ?? 'No reason provided';
+
+ const warn = await getWarn(warnId, interaction.guild.id);
+
+ if (!warn) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} No warn found with that ID in this server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const confirm = new ButtonBuilder().setCustomId('confirm').setLabel('Confirm Unwarn').setStyle(ButtonStyle.Danger);
+
+ const cancel = new ButtonBuilder().setCustomId('cancel').setLabel('Cancel').setStyle(ButtonStyle.Secondary);
+
+ const row = new ActionRowBuilder().addComponents(cancel, confirm);
+
+ const response = await interaction.reply({
+ content: `${emojis.rightArrow1} Are you sure you want to unwarn <@${warn.userId}> with reason: ${reason}?\n${emojis.rightArrow2} They were warned for: ${warn.reason} `,
+ allowedMentions: { parse: [], users: [warn.userId] },
+ components: [row],
+ withResponse: true,
+ });
+
+ const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
+
+ try {
+ const confirmation = await import('#utils/collectors.js').then((m) =>
+ m.awaitMessageComponentSafe(response.resource!.message!, { filter: collectorFilter, time: 60_000 }),
+ );
+
+ if (!confirmation) {
+ await interaction.editReply({
+ content: `${emojis.rightArrow2} No response within a minute or errored.`,
+ components: [],
+ });
+ return;
+ }
+
+ if (confirmation.customId === 'confirm') {
+ try {
+ await removeWarn(warn.id);
+ const user = await interaction.client.users.fetch(warn.userId);
+ await user
+ .send(`Your warn for ${warn.reason} in **${interaction.guild.name}** has been removed.\nReason: ${reason}`)
+ .catch(() => {});
+ await confirmation.update({
+ content: `${emojis.rightArrow2} \`${warn.id}\` has been removed from <@${warn.userId}>. Reason: ${reason}`,
+ allowedMentions: { parse: [], users: [warn.userId] },
+ components: [],
+ });
+ } catch (err) {
+ console.error(`Failed to remove warn ${warn.id}:`, err);
+ await confirmation.update({
+ content: `${emojis.rightArrow2} Failed to remove warn \`${warn.id}\` from <@${warn.userId}>.`,
+ allowedMentions: { parse: [], users: [warn.userId] },
+ components: [],
+ });
+ }
+ } else if (confirmation.customId === 'cancel') {
+ await confirmation.update({
+ content: `${emojis.rightArrow2} Cancelled.`,
+ components: [],
+ });
+ }
+ } catch {
+ await interaction.editReply({
+ content: `${emojis.rightArrow2} No response within a minute or errored.`,
+ components: [],
+ });
+ }
+ }
+}
diff --git a/apps/bot/src/commands/moderation/warn/warn.ts b/apps/bot/src/commands/moderation/warn/warn.ts
index 5886066..f55b189 100644
--- a/apps/bot/src/commands/moderation/warn/warn.ts
+++ b/apps/bot/src/commands/moderation/warn/warn.ts
@@ -1,13 +1,13 @@
import { Command } from '@sapphire/framework';
import {
- ActionRowBuilder,
- Colors,
- ButtonBuilder,
- ButtonStyle,
- EmbedBuilder,
- GuildMember,
- MessageFlags,
- PermissionsBitField
+ ActionRowBuilder,
+ Colors,
+ ButtonBuilder,
+ ButtonStyle,
+ EmbedBuilder,
+ GuildMember,
+ MessageFlags,
+ PermissionsBitField,
} from 'discord.js';
import ms, { type StringValue } from 'ms';
import { createWarn } from '#lib/warns.js';
@@ -15,185 +15,186 @@ import { logEmbed, truncate } from '#lib/logging.js';
import { emojis } from '#utils/emoji.js';
export class WarnCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
-
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder
- .setName('warn')
- .setDescription('Warn someone in the discord server.')
- .addUserOption((option: any) =>
- option.setName('member').setDescription('Select a member to warn').setRequired(true)
- )
- .addStringOption((option: any) =>
- option.setName('reason').setDescription('Provide a reason for their warn')
- )
- .addStringOption((option: any) =>
- option.setName('duration').setDescription('Specify a duration for the warn')
- )
- );
- }
-
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- if (!interaction.inCachedGuild()) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This command can only be used in a server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const member = interaction.member as GuildMember;
-
- if (!member.permissions.has(PermissionsBitField.Flags.ModerateMembers)) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You do not have permission to warn members.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const targetMember = interaction.options.getMember('member') as GuildMember;
- const reason = interaction.options.getString('reason') ?? 'No reason provided';
- const durationStr = interaction.options.getString('duration') as StringValue;
- const duration = durationStr ? ms(durationStr) : null;
- const expiresAt = duration ? new Date(Date.now() + duration) : null;
-
- if (durationStr && (typeof duration !== 'number' || isNaN(duration))) {
- await interaction.reply({
- content: `${emojis.rightArrow2} Invalid duration format.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (!targetMember) {
- await interaction.reply({
- content: `${emojis.rightArrow2} That user is not in this server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (targetMember.id === interaction.user.id) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You cannot warn yourself.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (targetMember.id === interaction.guild.ownerId) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You cannot warn the server owner.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (!targetMember.moderatable) {
- await interaction.reply({
- content: `${emojis.rightArrow2} I cannot warn this user.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const confirm = new ButtonBuilder()
- .setCustomId('confirm')
- .setLabel('Confirm Warn')
- .setStyle(ButtonStyle.Danger);
-
- const cancel = new ButtonBuilder()
- .setCustomId('cancel')
- .setLabel('Cancel')
- .setStyle(ButtonStyle.Secondary);
-
- const row = new ActionRowBuilder().addComponents(cancel, confirm);
-
- const response = await interaction.reply({
- content: `${emojis.rightArrow1} Are you sure you want to warn <@${targetMember.user.id}> with reason: ${reason}?`,
- components: [row],
- withResponse: true
- });
-
- const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
-
- try {
- const confirmation = await import('#utils/collectors.js').then((m) =>
- m.awaitMessageComponentSafe(response.resource!.message!, { filter: collectorFilter, time: 60_000 })
- );
-
- if (!confirmation) {
- await interaction.editReply({
- content: `${emojis.rightArrow2} No response within a minute or errored.`,
- components: []
- });
- return;
- }
-
- if (confirmation.customId === 'confirm') {
- try {
- await createWarn(
- interaction.guild.id,
- interaction.guild.name,
- targetMember.id,
- interaction.user.id,
- reason,
- expiresAt
- );
- await targetMember
- .send(
- `You have been warned in **${interaction.guild.name}**.\nReason: ${reason}${
- expiresAt ? `\nExpires: ` : ''
- }`
- )
- .catch(() => {});
-
- const embed = new EmbedBuilder()
- .setTitle('Member Warned')
- .setColor(Colors.Orange)
- .addFields(
- { name: 'Member', value: `<@${targetMember.id}>`, inline: true },
- { name: 'Moderator', value: `<@${interaction.user.id}>`, inline: true },
- { name: 'Reason', value: truncate(reason) || '-', inline: false }
- )
- .setTimestamp();
-
- if (expiresAt) {
- embed.addFields({
- name: 'Expires',
- value: ``,
- inline: true
- });
- }
-
- await logEmbed(interaction.guild, embed);
- await confirmation.update({
- content: `${emojis.rightArrow2} <@${targetMember.id}> has been warned with reason: ${reason}`,
- components: []
- });
- } catch (err) {
- console.error(err);
- await confirmation.update({
- content: `${emojis.rightArrow2} Failed to warn <@${targetMember.id}>`,
- components: []
- });
- }
- } else if (confirmation.customId === 'cancel') {
- await confirmation.update({
- content: `${emojis.rightArrow2} Cancelled.`,
- components: []
- });
- }
- } catch (err) {
- console.error(err);
- await interaction.editReply({
- content: `${emojis.rightArrow2} No response within a minute or errored.`,
- components: []
- });
- }
- }
-}
\ No newline at end of file
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
+
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder
+ .setName('warn')
+ .setDescription('Warn someone in the discord server.')
+ .addUserOption((option: any) =>
+ option.setName('member').setDescription('Select a member to warn').setRequired(true),
+ )
+ .addStringOption((option: any) => option.setName('reason').setDescription('Provide a reason for their warn').setMaxLength(512))
+ .addStringOption((option: any) => option.setName('duration').setDescription('Specify a duration for the warn').setMaxLength(20)),
+ );
+ }
+
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ if (!interaction.inCachedGuild()) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This command can only be used in a server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const member = interaction.member as GuildMember;
+
+ if (!member.permissions.has(PermissionsBitField.Flags.ModerateMembers)) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You do not have permission to warn members.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const targetMember = interaction.options.getMember('member') as GuildMember;
+ const reason = interaction.options.getString('reason') ?? 'No reason provided';
+ const durationStr = interaction.options.getString('duration') as StringValue;
+ const duration = durationStr ? ms(durationStr) : null;
+ const expiresAt = duration ? new Date(Date.now() + duration) : null;
+
+ if (durationStr && (typeof duration !== 'number' || isNaN(duration))) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Invalid duration format.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (!targetMember) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} That user is not in this server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (targetMember.id === interaction.user.id) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You cannot warn yourself.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (targetMember.id === interaction.guild.ownerId) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You cannot warn the server owner.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (member.roles.highest.position <= targetMember.roles.highest.position) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You cannot moderate someone with a higher or equal role.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (!targetMember.moderatable) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} I cannot warn this user.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const confirm = new ButtonBuilder().setCustomId('confirm').setLabel('Confirm Warn').setStyle(ButtonStyle.Danger);
+
+ const cancel = new ButtonBuilder().setCustomId('cancel').setLabel('Cancel').setStyle(ButtonStyle.Secondary);
+
+ const row = new ActionRowBuilder().addComponents(cancel, confirm);
+
+ const response = await interaction.reply({
+ content: `${emojis.rightArrow1} Are you sure you want to warn <@${targetMember.user.id}> with reason: ${reason}?`,
+ allowedMentions: { parse: [], users: [targetMember.user.id] },
+ components: [row],
+ withResponse: true,
+ });
+
+ const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
+
+ try {
+ const confirmation = await import('#utils/collectors.js').then((m) =>
+ m.awaitMessageComponentSafe(response.resource!.message!, { filter: collectorFilter, time: 60_000 }),
+ );
+
+ if (!confirmation) {
+ await interaction.editReply({
+ content: `${emojis.rightArrow2} No response within a minute or errored.`,
+ components: [],
+ });
+ return;
+ }
+
+ if (confirmation.customId === 'confirm') {
+ try {
+ await createWarn(
+ interaction.guild.id,
+ interaction.guild.name,
+ targetMember.id,
+ interaction.user.id,
+ reason,
+ expiresAt,
+ );
+ await targetMember
+ .send(
+ `You have been warned in **${interaction.guild.name}**.\nReason: ${reason}${
+ expiresAt ? `\nExpires: ` : ''
+ }`,
+ )
+ .catch(() => {});
+
+ const embed = new EmbedBuilder()
+ .setTitle('Member Warned')
+ .setColor(Colors.Orange)
+ .addFields(
+ { name: 'Member', value: `<@${targetMember.id}>`, inline: true },
+ { name: 'Moderator', value: `<@${interaction.user.id}>`, inline: true },
+ { name: 'Reason', value: truncate(reason) || '-', inline: false },
+ )
+ .setTimestamp();
+
+ if (expiresAt) {
+ embed.addFields({
+ name: 'Expires',
+ value: ``,
+ inline: true,
+ });
+ }
+
+ await logEmbed(interaction.guild, embed);
+ await confirmation.update({
+ content: `${emojis.rightArrow2} <@${targetMember.id}> has been warned with reason: ${reason}`,
+ allowedMentions: { parse: [], users: [targetMember.user.id] },
+ components: [],
+ });
+ } catch (err) {
+ console.error(err);
+ await confirmation.update({
+ content: `${emojis.rightArrow2} Failed to warn <@${targetMember.id}>`,
+ allowedMentions: { parse: [], users: [targetMember.user.id] },
+ components: [],
+ });
+ }
+ } else if (confirmation.customId === 'cancel') {
+ await confirmation.update({
+ content: `${emojis.rightArrow2} Cancelled.`,
+ components: [],
+ });
+ }
+ } catch (err) {
+ console.error(err);
+ await interaction.editReply({
+ content: `${emojis.rightArrow2} No response within a minute or errored.`,
+ components: [],
+ });
+ }
+ }
+}
diff --git a/apps/bot/src/commands/moderation/warn/warns.ts b/apps/bot/src/commands/moderation/warn/warns.ts
index aa66846..e5fbd24 100644
--- a/apps/bot/src/commands/moderation/warn/warns.ts
+++ b/apps/bot/src/commands/moderation/warn/warns.ts
@@ -4,63 +4,59 @@ import { getWarns } from '#lib/warns.js';
import { emojis } from '#utils/emoji.js';
export class WarnsCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
-
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder
- .setName('warns')
- .setDescription('View (someones) warns.')
- .addUserOption((option: any) =>
- option.setName('member').setDescription('Member to view warns of')
- )
- );
- }
-
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- if (!interaction.inCachedGuild()) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This command can only be used in a server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const member = interaction.member as GuildMember;
- const targetOption = interaction.options.getMember('member') as GuildMember;
-
- if (targetOption && targetOption.id !== interaction.user.id) {
- if (!member.permissions.has(PermissionsBitField.Flags.ModerateMembers)) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You do not have permission to view other members' warns.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
- }
-
- const targetMember = targetOption ?? member;
- const active = await getWarns(interaction.guild.id, targetMember.id);
-
- if (active.length === 0) {
- await interaction.reply({
- content: `${emojis.rightArrow2} <@${targetMember.user.id}> has no active warns.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const lines = active.slice(0, 10).map((warn) => {
- const expires = warn.expiresAt
- ? ``
- : 'Never';
- return `${emojis.rightArrow2} **${warn.reason ?? 'No reason provided'}** by <@${warn.moderatorId}>\n Expires: ${expires} \`${warn.id}\``;
- });
-
- const content = `${emojis.rightArrow1} ${active.length} active warn(s) for <@${targetMember.user.id}>:\n${lines.join('\n')}`;
-
- await interaction.reply({ content });
- }
-}
\ No newline at end of file
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
+
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder
+ .setName('warns')
+ .setDescription('View (someones) warns.')
+ .addUserOption((option: any) => option.setName('member').setDescription('Member to view warns of')),
+ );
+ }
+
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ if (!interaction.inCachedGuild()) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This command can only be used in a server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const member = interaction.member as GuildMember;
+ const targetOption = interaction.options.getMember('member') as GuildMember;
+
+ if (targetOption && targetOption.id !== interaction.user.id) {
+ if (!member.permissions.has(PermissionsBitField.Flags.ModerateMembers)) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You do not have permission to view other members' warns.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+ }
+
+ const targetMember = targetOption ?? member;
+ const active = await getWarns(interaction.guild.id, targetMember.id);
+
+ if (active.length === 0) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} <@${targetMember.user.id}> has no active warns.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const lines = active.slice(0, 10).map((warn) => {
+ const expires = warn.expiresAt ? `` : 'Never';
+ return `${emojis.rightArrow2} **${warn.reason ?? 'No reason provided'}** by <@${warn.moderatorId}>\n Expires: ${expires} \`${warn.id}\``;
+ });
+
+ const content = `${emojis.rightArrow1} ${active.length} active warn(s) for <@${targetMember.user.id}>:\n${lines.join('\n')}`;
+
+ await interaction.reply({ content, flags: MessageFlags.Ephemeral });
+ }
+}
diff --git a/apps/bot/src/commands/ping.ts b/apps/bot/src/commands/ping.ts
index 8c060ee..8143fb2 100644
--- a/apps/bot/src/commands/ping.ts
+++ b/apps/bot/src/commands/ping.ts
@@ -2,26 +2,26 @@ import { Command } from '@sapphire/framework';
import { emojis } from '#utils/emoji.js';
export class PingCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder.setName('ping').setDescription("Return the bot's latency.")
- );
- }
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder.setName('ping').setDescription("Return the bot's latency."),
+ );
+ }
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- await interaction.deferReply();
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ await interaction.deferReply();
- const reply = await interaction.fetchReply();
+ const reply = await interaction.fetchReply();
- const ping = reply.createdTimestamp - interaction.createdTimestamp;
- const shardId = interaction.client.shard?.ids?.[0];
+ const ping = reply.createdTimestamp - interaction.createdTimestamp;
+ const shardId = interaction.client.shard?.ids?.[0];
- await interaction.editReply(
- `${emojis.rightArrow1} Client: ${ping}ms\n${emojis.rightArrow1} Websocket: ${interaction.client.ws.ping}ms\n${emojis.rightArrow2} Shard: #${typeof shardId === 'number' ? shardId : 'N/A'}`
- );
- }
-}
\ No newline at end of file
+ await interaction.editReply(
+ `${emojis.rightArrow1} Client: ${ping}ms\n${emojis.rightArrow1} Websocket: ${interaction.client.ws.ping}ms\n${emojis.rightArrow2} Shard: #${typeof shardId === 'number' ? shardId : 'N/A'}`,
+ );
+ }
+}
diff --git a/apps/bot/src/commands/promotion/bot.ts b/apps/bot/src/commands/promotion/bot.ts
index 4e91ec0..95086ee 100644
--- a/apps/bot/src/commands/promotion/bot.ts
+++ b/apps/bot/src/commands/promotion/bot.ts
@@ -2,17 +2,17 @@ import { Command } from '@sapphire/framework';
import { emojis } from '#utils/emoji.js';
export class BotCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder.setName('bot').setDescription('Get a link to add the bot to your server!')
- );
- }
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder.setName('bot').setDescription('Get a link to add the bot to your server!'),
+ );
+ }
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- await interaction.reply(`${emojis.rightArrow1} https://duckorg.com/bot/invite`);
- }
-}
\ No newline at end of file
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ await interaction.reply(`${emojis.rightArrow1} https://duckorg.com/bot/invite`);
+ }
+}
diff --git a/apps/bot/src/commands/promotion/discord.ts b/apps/bot/src/commands/promotion/discord.ts
index 593c26c..d3eb143 100644
--- a/apps/bot/src/commands/promotion/discord.ts
+++ b/apps/bot/src/commands/promotion/discord.ts
@@ -2,17 +2,17 @@ import { Command } from '@sapphire/framework';
import { emojis } from '#utils/emoji.js';
export class DiscordCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder.setName('discord').setDescription('Get a link to the official Discord server!')
- );
- }
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder.setName('discord').setDescription('Get a link to the official Discord server!'),
+ );
+ }
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- await interaction.reply(`${emojis.rightArrow1} https://duckorg.com/discord`);
- }
-}
\ No newline at end of file
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ await interaction.reply(`${emojis.rightArrow1} https://duckorg.com/discord`);
+ }
+}
diff --git a/apps/bot/src/commands/promotion/invite.ts b/apps/bot/src/commands/promotion/invite.ts
index a4a1253..fbc22f7 100644
--- a/apps/bot/src/commands/promotion/invite.ts
+++ b/apps/bot/src/commands/promotion/invite.ts
@@ -2,17 +2,17 @@ import { Command } from '@sapphire/framework';
import { emojis } from '#utils/emoji.js';
export class InviteCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder.setName('invite').setDescription('Get a link to add the bot to your server!')
- );
- }
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder.setName('invite').setDescription('Get a link to add the bot to your server!'),
+ );
+ }
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- await interaction.reply(`${emojis.rightArrow1} https://duckorg.com/bot/invite`);
- }
-}
\ No newline at end of file
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ await interaction.reply(`${emojis.rightArrow1} https://duckorg.com/bot/invite`);
+ }
+}
diff --git a/apps/bot/src/commands/promotion/unlimited.ts b/apps/bot/src/commands/promotion/unlimited.ts
index 524467a..14c3865 100644
--- a/apps/bot/src/commands/promotion/unlimited.ts
+++ b/apps/bot/src/commands/promotion/unlimited.ts
@@ -4,21 +4,21 @@ import { MessageFlags } from 'discord.js';
import { emojis } from '#utils/emoji.js';
export class QuestUnlimitedCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder.setName('unlimited').setDescription('Purchase Quest Unlimited!')
- );
- }
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder.setName('unlimited').setDescription('Purchase Quest Unlimited!'),
+ );
+ }
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- await interaction.reply({
- content: `${emojis.questUnlimited2} Purchase Quest Unlimited below:`,
- components: getQuestUnlimitedPurchaseComponents(interaction.client.application.id),
- flags: MessageFlags.Ephemeral
- });
- }
-}
\ No newline at end of file
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ await interaction.reply({
+ content: `${emojis.questUnlimited2} Purchase Quest Unlimited below:`,
+ components: getQuestUnlimitedPurchaseComponents(interaction.client.application.id),
+ flags: MessageFlags.Ephemeral,
+ });
+ }
+}
diff --git a/apps/bot/src/commands/utility/confess.ts b/apps/bot/src/commands/utility/confess.ts
deleted file mode 100644
index 108aeb4..0000000
--- a/apps/bot/src/commands/utility/confess.ts
+++ /dev/null
@@ -1,121 +0,0 @@
-import { Command } from '@sapphire/framework';
-import {
- ActionRowBuilder,
- ButtonBuilder,
- ButtonStyle,
- EmbedBuilder,
- LabelBuilder,
- MessageFlags,
- ModalBuilder,
- TextInputBuilder,
- TextInputStyle,
- TextChannel
-} from 'discord.js';
-import { getSettings } from '#lib/settings.js';
-import { storeConfessionContext, isConfessionBlacklisted } from '#lib/confessions.js';
-import { emojis } from '#utils/emoji.js';
-
-export class ConfessCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
-
- public override registerApplicationCommands(_registry: Command.Registry) {
- _registry.registerChatInputCommand((builder: any) =>
- builder.setName('confess').setDescription('Create a confession')
- );
- }
-
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- if (!interaction.inGuild() || !interaction.guild) {
- await interaction.reply({ content: `${emojis.rightArrow2} This command can only be used in a server.`, flags: MessageFlags.Ephemeral });
- return;
- }
-
- const settings = await getSettings(interaction.guild.id, interaction.guild.name);
-
- if (settings.confessionEnabled === false) {
- await interaction.reply({ content: `${emojis.rightArrow2} Confessions are disabled in this server.`, flags: MessageFlags.Ephemeral });
- return;
- }
-
- if (!settings.confessionChannelId) {
- await interaction.reply({ content: `${emojis.rightArrow2} Confessions are not configured in this server.`, flags: MessageFlags.Ephemeral });
- return;
- }
-
- const blacklistEntry = await isConfessionBlacklisted(interaction.user.id);
- if (blacklistEntry) {
- await interaction.reply({ content: `${emojis.rightArrow2} You are blacklisted from confessions${blacklistEntry.reason ? ` reason: ${blacklistEntry.reason}` : ''}.`, flags: MessageFlags.Ephemeral });
- return;
- }
-
- const confessionInput = new TextInputBuilder()
- .setCustomId('confession-text')
- .setStyle(TextInputStyle.Paragraph)
- .setRequired(true)
- .setMaxLength(1_000);
-
- const confessionLabel = new LabelBuilder().setLabel('Confession').setTextInputComponent(confessionInput);
-
- const modal = new ModalBuilder().setCustomId('create-confession-modal').setTitle('Create Confession').addLabelComponents(confessionLabel);
-
- await interaction.showModal(modal);
-
- let modalSubmit;
-
- try {
- modalSubmit = await interaction.awaitModalSubmit({
- filter: (m: any) => m.customId === 'create-confession-modal' && m.user.id === interaction.user.id,
- time: 60_000
- });
- await modalSubmit.deferReply({ flags: MessageFlags.Ephemeral });
- } catch {
- return;
- }
-
- const confession = modalSubmit.fields.getTextInputValue('confession-text');
-
- const confessionChannel = await interaction.guild.channels.fetch(settings.confessionChannelId).catch(() => null);
-
- if (!(confessionChannel instanceof TextChannel)) {
- await modalSubmit.editReply({ content: `${emojis.rightArrow2} The configured confession channel is unavailable.` });
- return;
- }
-
- const embed = new EmbedBuilder().setTitle('Confession').setDescription(confession).setTimestamp();
-
- const message = await confessionChannel.send({ embeds: [embed] });
-
- let thread;
-
- try {
- const threadName = confession.replace(/\s+/g, ' ').slice(0, 10).toLowerCase() || 'confession';
- thread = await message.startThread({ name: `confession-${threadName}` });
- } catch (error) {
- await message.delete().catch(() => null);
- throw error;
- }
-
- const reportButton = new ButtonBuilder().setCustomId(`report-confession:${message.id}`).setLabel('Report').setStyle(ButtonStyle.Danger);
- const row = new ActionRowBuilder().addComponents(reportButton);
-
- await message.edit({ components: [row] });
-
- try {
- await storeConfessionContext({
- guildId: interaction.guild.id,
- channelId: confessionChannel.id,
- messageId: message.id,
- threadId: thread.id,
- creatorId: modalSubmit.user.id
- });
- } catch (error) {
- await thread.delete().catch(() => null);
- await message.delete().catch(() => null);
- throw error;
- }
-
- await modalSubmit.editReply({ content: `${emojis.rightArrow2} Confession sent.` });
- }
-}
\ No newline at end of file
diff --git a/apps/bot/src/commands/utility/fun/confess.ts b/apps/bot/src/commands/utility/fun/confess.ts
new file mode 100644
index 0000000..0f10954
--- /dev/null
+++ b/apps/bot/src/commands/utility/fun/confess.ts
@@ -0,0 +1,141 @@
+import { Command } from '@sapphire/framework';
+import {
+ ActionRowBuilder,
+ ButtonBuilder,
+ ButtonStyle,
+ EmbedBuilder,
+ LabelBuilder,
+ MessageFlags,
+ ModalBuilder,
+ TextInputBuilder,
+ TextInputStyle,
+ TextChannel,
+} from 'discord.js';
+import { getSettings } from '#lib/settings.js';
+import { storeConfessionContext, isConfessionBlacklisted } from '#lib/confessions.js';
+import { emojis } from '#utils/emoji.js';
+
+export class ConfessCommand extends Command {
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
+
+ public override registerApplicationCommands(_registry: Command.Registry) {
+ _registry.registerChatInputCommand((builder: any) =>
+ builder.setName('confess').setDescription('Create a confession'),
+ );
+ }
+
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ if (!interaction.inGuild() || !interaction.guild) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This command can only be used in a server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const settings = await getSettings(interaction.guild.id, interaction.guild.name);
+
+ if (settings.confessionEnabled === false) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Confessions are disabled in this server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (!settings.confessionChannelId) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Confessions are not configured in this server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const blacklistEntry = await isConfessionBlacklisted(interaction.user.id);
+ if (blacklistEntry) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You are blacklisted from confessions${blacklistEntry.reason ? ` reason: ${blacklistEntry.reason}` : ''}.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const confessionInput = new TextInputBuilder()
+ .setCustomId('confession-text')
+ .setStyle(TextInputStyle.Paragraph)
+ .setRequired(true)
+ .setMaxLength(1_000);
+
+ const confessionLabel = new LabelBuilder().setLabel('Confession').setTextInputComponent(confessionInput);
+
+ const modal = new ModalBuilder()
+ .setCustomId('create-confession-modal')
+ .setTitle('Create Confession')
+ .addLabelComponents(confessionLabel);
+
+ await interaction.showModal(modal);
+
+ let modalSubmit;
+
+ try {
+ modalSubmit = await interaction.awaitModalSubmit({
+ filter: (m: any) => m.customId === 'create-confession-modal' && m.user.id === interaction.user.id,
+ time: 60_000,
+ });
+ await modalSubmit.deferReply({ flags: MessageFlags.Ephemeral });
+ } catch {
+ return;
+ }
+
+ const confession = modalSubmit.fields.getTextInputValue('confession-text');
+
+ const confessionChannel = await interaction.guild.channels.fetch(settings.confessionChannelId).catch(() => null);
+
+ if (!(confessionChannel instanceof TextChannel)) {
+ await modalSubmit.editReply({
+ content: `${emojis.rightArrow2} The configured confession channel is unavailable.`,
+ });
+ return;
+ }
+
+ const embed = new EmbedBuilder().setTitle('Confession').setDescription(confession).setTimestamp();
+
+ const message = await confessionChannel.send({ embeds: [embed] });
+
+ let thread;
+
+ try {
+ const threadName = confession.replace(/\s+/g, ' ').slice(0, 10).toLowerCase() || 'confession';
+ thread = await message.startThread({ name: `confession-${threadName}` });
+ } catch (error) {
+ await message.delete().catch(() => null);
+ throw error;
+ }
+
+ const reportButton = new ButtonBuilder()
+ .setCustomId(`report-confession:${message.id}`)
+ .setLabel('Report')
+ .setStyle(ButtonStyle.Danger);
+ const row = new ActionRowBuilder().addComponents(reportButton);
+
+ await message.edit({ components: [row] });
+
+ try {
+ await storeConfessionContext({
+ guildId: interaction.guild.id,
+ channelId: confessionChannel.id,
+ messageId: message.id,
+ threadId: thread.id,
+ creatorId: modalSubmit.user.id,
+ });
+ } catch (error) {
+ await thread.delete().catch(() => null);
+ await message.delete().catch(() => null);
+ throw error;
+ }
+
+ await modalSubmit.editReply({ content: `${emojis.rightArrow2} Confession sent.` });
+ }
+}
diff --git a/apps/bot/src/commands/utility/fun/toGif.ts b/apps/bot/src/commands/utility/fun/toGif.ts
new file mode 100644
index 0000000..ae53fc2
--- /dev/null
+++ b/apps/bot/src/commands/utility/fun/toGif.ts
@@ -0,0 +1,75 @@
+import { Command } from '@sapphire/framework';
+import { AttachmentBuilder } from 'discord.js';
+import sharp from 'sharp';
+import { emojis } from '#utils/emoji.js';
+import { safeFetch, SafeFetchError } from '#lib/safeFetch.js';
+
+const ALLOWED_TYPES = new Set(['image/png', 'image/jpeg', 'image/webp']);
+const MAX_SIZE = 20 * 1024 * 1024;
+
+export class ToGifCommand extends Command {
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
+
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder
+ .setName('togif')
+ .setDescription('Convert a PNG, JPEG, or WEBP image URL to a GIF.')
+ .addStringOption((option: any) =>
+ option.setName('url').setDescription('The image URL to convert.').setRequired(true).setMaxLength(512),
+ ),
+ );
+ }
+
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ const url = interaction.options.getString('url', true);
+
+ await interaction.deferReply();
+
+ let response;
+ try {
+ response = await safeFetch(url);
+ } catch (err) {
+ const msg = err instanceof SafeFetchError ? err.message : 'Failed to fetch the URL.';
+ await interaction.editReply(`${emojis.rightArrow1} ${msg}`);
+ return;
+ }
+
+ if (!response.ok) {
+ await interaction.editReply(`${emojis.rightArrow1} Could not retrieve the image (HTTP ${response.status}).`);
+ return;
+ }
+
+ const contentType = response.headers.get('content-type')?.split(';')[0].trim() ?? '';
+ if (!ALLOWED_TYPES.has(contentType)) {
+ await interaction.editReply(`${emojis.rightArrow1} Only PNG, JPEG, and WEBP images are supported.`);
+ return;
+ }
+
+ const contentLength = response.headers.get('content-length');
+ if (contentLength && parseInt(contentLength, 10) > MAX_SIZE) {
+ await interaction.editReply(`${emojis.rightArrow1} Image exceeds the 20 MB size limit.`);
+ return;
+ }
+
+ const arrayBuffer = await response.arrayBuffer();
+ if (arrayBuffer.byteLength > MAX_SIZE) {
+ await interaction.editReply(`${emojis.rightArrow1} Image exceeds the 20 MB size limit.`);
+ return;
+ }
+ const inputBuffer = Buffer.from(arrayBuffer);
+
+ let gifBuffer: Buffer;
+ try {
+ gifBuffer = await sharp(inputBuffer, { failOn: 'error' }).gif().toBuffer();
+ } catch {
+ await interaction.editReply(`${emojis.rightArrow1} Failed to convert the image to GIF.`);
+ return;
+ }
+
+ const attachment = new AttachmentBuilder(gifBuffer, { name: 'toGif.gif' });
+ await interaction.editReply({ files: [attachment] });
+ }
+}
\ No newline at end of file
diff --git a/apps/bot/src/commands/utility/help.ts b/apps/bot/src/commands/utility/help.ts
index 3981bb4..16009a2 100644
--- a/apps/bot/src/commands/utility/help.ts
+++ b/apps/bot/src/commands/utility/help.ts
@@ -3,37 +3,38 @@ import { emojis } from '#utils/emoji.js';
import { EmbedBuilder, MessageFlags } from 'discord.js';
export class HelpCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder.setName('help').setDescription("Show what the bot is capable of.")
- );
- }
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder.setName('help').setDescription('Show what the bot is capable of.'),
+ );
+ }
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- const commands = this.container.stores.get('commands');
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ const commands = this.container.stores.get('commands');
- const commandList = Array.from(commands.values())
- .sort((a, b) => (a.name ?? '').localeCompare(b.name ?? ''))
- .map((cmd) => {
- const description = cmd.applicationCommandRegistry['apiCalls'][0]?.builtData.description ?? cmd.description;
- const commandName = cmd.applicationCommandRegistry['apiCalls'][0]?.builtData.name ?? cmd.name;
+ const commandList = Array.from(commands.values())
+ .sort((a, b) => (a.name ?? '').localeCompare(b.name ?? ''))
+ .map((cmd) => {
+ const description = cmd.applicationCommandRegistry['apiCalls'][0]?.builtData.description ?? cmd.description;
+ const commandName = cmd.applicationCommandRegistry['apiCalls'][0]?.builtData.name ?? cmd.name;
- return `${emojis.rightArrow1} **/${commandName}** - ${description}`;
- })
- .join('\n');
+ return `${emojis.rightArrow1} **/${commandName}** - ${description}`;
+ })
+ .join('\n');
- const embed = new EmbedBuilder()
- .setTitle('Commands')
- .setDescription(commandList)
- .addFields({ name: 'Links', value: '**Status:** https://status.duckorg.com/\n**Official Discord Server:** https://discord.gg/F4HYE8frK2\n**Documentation:** https://docs.duckorg.com/' });
+ const embed = new EmbedBuilder().setTitle('Commands').setDescription(commandList).addFields({
+ name: 'Links',
+ value:
+ '**Status:** https://status.duckorg.com/\n**Official Discord Server:** https://discord.gg/F4HYE8frK2\n**Documentation:** https://docs.duckorg.com/',
+ });
- await interaction.reply({
- embeds: [embed],
- flags: MessageFlags.Ephemeral
- });
- }
-}
\ No newline at end of file
+ await interaction.reply({
+ embeds: [embed],
+ flags: MessageFlags.Ephemeral,
+ });
+ }
+}
diff --git a/apps/bot/src/commands/utility/reminder/reminder.ts b/apps/bot/src/commands/utility/reminder/reminder.ts
index 89f5b0b..315e693 100644
--- a/apps/bot/src/commands/utility/reminder/reminder.ts
+++ b/apps/bot/src/commands/utility/reminder/reminder.ts
@@ -1,134 +1,132 @@
import { Command } from '@sapphire/framework';
-import { MessageFlags } from 'discord.js';
+import { MessageFlags, SlashCommandBuilder } from 'discord.js';
import ms, { type StringValue } from 'ms';
import { createReminder, getReminder, removeReminder } from '#lib/reminders.js';
import { LimitError } from '#lib/limits.js';
import { emojis } from '#utils/emoji.js';
export class ReminderCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
-
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder
- .setName('reminder')
- .setDescription('Set reminders!')
- .addSubcommand((sub: any) =>
- sub
- .setName('add')
- .setDescription('Set a new reminder.')
- .addStringOption((option: any) =>
- option.setName('duration').setDescription('When to remind you').setRequired(true)
- )
- .addStringOption((option: any) =>
- option.setName('message').setDescription('What to remind you about').setRequired(true)
- )
- )
- .addSubcommand((sub: any) =>
- sub
- .setName('remove')
- .setDescription('Cancel a reminder.')
- .addStringOption((option: any) =>
- option.setName('id').setDescription('The reminder ID').setRequired(true)
- )
- )
- );
- }
-
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- const subcommand = interaction.options.getSubcommand();
-
- if (subcommand === 'add') {
- const durationStr = interaction.options.getString('duration', true);
- const message = interaction.options.getString('message', true);
-
- const duration = ms(durationStr as StringValue);
- if (typeof duration !== 'number' || isNaN(duration) || duration <= 0) {
- await interaction.reply({
- content: `${emojis.rightArrow2} Invalid duration.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (duration > 31_536_000_000) {
- await interaction.reply({
- content: `${emojis.rightArrow2} Reminder cannot be longer than 1 year.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const remindAt = new Date(Date.now() + duration);
-
- try {
- const reminder = interaction.inCachedGuild()
- ? await createReminder(
- interaction.user.id,
- message,
- remindAt,
- interaction.guild.id,
- interaction.guild.name,
- interaction.channelId
- )
- : await createReminder(interaction.user.id, message, remindAt);
-
- const unix = Math.floor(remindAt.getTime() / 1000);
- await interaction.reply({
- content: `${emojis.rightArrow2} Reminder set to go off in message: ${message}\nID: \`${reminder.id}\``,
- allowedMentions: { parse: [] },
- });
-
- setTimeout(() => {
- interaction.deleteReply().catch(() => {});
- }, 5000);
- return;
- } catch (err) {
- console.error(err);
- if (err instanceof LimitError) {
- await interaction.reply({
- content: `${emojis.rightArrow2} ${err.message}`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- throw err;
- }
- }
-
- if (subcommand === 'remove') {
- const id = interaction.options.getString('id', true);
- const reminder = await getReminder(id);
-
- if (!reminder) {
- await interaction.reply({
- content: `${emojis.rightArrow2} No reminder found.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (reminder.userId !== interaction.user.id) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You can't remove other's reminders.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- await removeReminder(id);
- await interaction.reply({
- content: `${emojis.rightArrow2} Reminder removed.`,
- flags: MessageFlags.Ephemeral
- });
-
- setTimeout(() => {
- interaction.deleteReply().catch(() => {});
- }, 5000);
- return;
- }
- }
-}
\ No newline at end of file
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
+
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: SlashCommandBuilder) =>
+ builder
+ .setName('reminder')
+ .setDescription('Set reminders!')
+ .addSubcommand((sub: any) =>
+ sub
+ .setName('add')
+ .setDescription('Set a new reminder.')
+ .addStringOption((option: any) =>
+ option.setName('duration').setDescription('When to remind you').setRequired(true).setMaxLength(20),
+ )
+ .addStringOption((option: any) =>
+ option.setName('message').setDescription('What to remind you about').setRequired(true).setMaxLength(1000),
+ ),
+ )
+ .addSubcommand((sub: any) =>
+ sub
+ .setName('remove')
+ .setDescription('Cancel a reminder.')
+ .addStringOption((option: any) => option.setName('id').setDescription('The reminder ID').setRequired(true).setMaxLength(36)),
+ ),
+ );
+ }
+
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ const subcommand = interaction.options.getSubcommand();
+
+ if (subcommand === 'add') {
+ const durationStr = interaction.options.getString('duration', true);
+ const message = interaction.options.getString('message', true);
+
+ const duration = ms(durationStr as StringValue);
+ if (typeof duration !== 'number' || isNaN(duration) || duration <= 0) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Invalid duration.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (duration > 31_536_000_000) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Reminder cannot be longer than 1 year.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const remindAt = new Date(Date.now() + duration);
+
+ try {
+ const reminder = interaction.inCachedGuild()
+ ? await createReminder(
+ interaction.user.id,
+ message,
+ remindAt,
+ interaction.guild.id,
+ interaction.guild.name,
+ interaction.channelId,
+ )
+ : await createReminder(interaction.user.id, message, remindAt);
+
+ const unix = Math.floor(remindAt.getTime() / 1000);
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Reminder set to go off in . Message: ${message}\nID: \`${reminder.id}\``,
+ allowedMentions: { parse: [] },
+ });
+
+ setTimeout(() => {
+ interaction.deleteReply().catch(() => {});
+ }, 5000);
+ return;
+ } catch (err) {
+ console.error(err);
+ if (err instanceof LimitError) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} ${err.message}`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ throw err;
+ }
+ }
+
+ if (subcommand === 'remove') {
+ const id = interaction.options.getString('id', true);
+ const reminder = await getReminder(id);
+
+ if (!reminder) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} No reminder found.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (reminder.userId !== interaction.user.id) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You can't remove others' reminders.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ await removeReminder(id);
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Reminder removed.`,
+ flags: MessageFlags.Ephemeral,
+ });
+
+ setTimeout(() => {
+ interaction.deleteReply().catch(() => {});
+ }, 5000);
+ return;
+ }
+ }
+}
diff --git a/apps/bot/src/commands/utility/reminder/reminders.ts b/apps/bot/src/commands/utility/reminder/reminders.ts
index b18d610..22a1c7d 100644
--- a/apps/bot/src/commands/utility/reminder/reminders.ts
+++ b/apps/bot/src/commands/utility/reminder/reminders.ts
@@ -4,37 +4,37 @@ import { getReminders } from '#lib/reminders.js';
import { emojis } from '#utils/emoji.js';
export class RemindersCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder.setName('reminders').setDescription('List your current reminders.')
- );
- }
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder.setName('reminders').setDescription('List your current reminders.'),
+ );
+ }
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- const reminders = interaction.inCachedGuild()
- ? await getReminders(interaction.user.id, interaction.guild.id)
- : await getReminders(interaction.user.id);
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ const reminders = interaction.inCachedGuild()
+ ? await getReminders(interaction.user.id, interaction.guild.id)
+ : await getReminders(interaction.user.id);
- if (reminders.length === 0) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You have no active reminders${interaction.inCachedGuild() ? ' in this server' : ''}.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
+ if (reminders.length === 0) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You have no active reminders${interaction.inCachedGuild() ? ' in this server' : ''}.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
- const lines = reminders.map((r) => {
- const unix = Math.floor(r.remindAt.getTime() / 1000);
- return ` | ${r.message}\n \`${r.id}\``;
- });
+ const lines = reminders.map((r) => {
+ const unix = Math.floor(r.remindAt.getTime() / 1000);
+ return ` | ${r.message}\n \`${r.id}\``;
+ });
- await interaction.reply({
- content: `${emojis.rightArrow2} Your reminders:\n${lines.join('\n')}`,
- flags: MessageFlags.Ephemeral
- });
- }
-}
\ No newline at end of file
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Your reminders:\n${lines.join('\n')}`,
+ flags: MessageFlags.Ephemeral,
+ });
+ }
+}
diff --git a/apps/bot/src/commands/utility/settings.ts b/apps/bot/src/commands/utility/settings.ts
index ba93d9a..febd4b5 100644
--- a/apps/bot/src/commands/utility/settings.ts
+++ b/apps/bot/src/commands/utility/settings.ts
@@ -1,17 +1,17 @@
import { Command } from '@sapphire/framework';
import {
- ActionRowBuilder,
- ButtonBuilder,
- ButtonStyle,
- ChannelSelectMenuBuilder,
- ChannelType,
- type Guild,
- InteractionContextType,
- MessageFlags,
- PermissionFlagsBits,
- RoleSelectMenuBuilder,
- StringSelectMenuBuilder,
- StringSelectMenuOptionBuilder
+ ActionRowBuilder,
+ ButtonBuilder,
+ ButtonStyle,
+ ChannelSelectMenuBuilder,
+ ChannelType,
+ type Guild,
+ InteractionContextType,
+ MessageFlags,
+ PermissionFlagsBits,
+ RoleSelectMenuBuilder,
+ StringSelectMenuBuilder,
+ StringSelectMenuOptionBuilder,
} from 'discord.js';
import { getSettings, type ServerSettings, updateSettings } from '#lib/settings.js';
import { emojis } from '#utils/emoji.js';
@@ -19,379 +19,368 @@ import { emojis } from '#utils/emoji.js';
const staleInteractionErrorCodes = new Set([10_015, 50_027, 10062]);
function isStaleInteractionError(error: unknown): error is { code: number } {
- return (
- typeof error === 'object' &&
- error !== null &&
- 'code' in error &&
- typeof error.code === 'number' &&
- staleInteractionErrorCodes.has(error.code)
- );
+ return (
+ typeof error === 'object' &&
+ error !== null &&
+ 'code' in error &&
+ typeof error.code === 'number' &&
+ staleInteractionErrorCodes.has(error.code)
+ );
}
function buildWelcomePanel(settings: ServerSettings, guild: Guild, status?: string) {
- const currentChannelName = settings.welcomeChannelId
- ? guild.channels.cache.get(settings.welcomeChannelId)?.name
- : null;
-
- const toggleMenu = new StringSelectMenuBuilder()
- .setCustomId('welcomeToggle')
- .setPlaceholder(`${settings.welcomePeople ? 'Enabled' : 'Disabled'}`)
- .addOptions(
- new StringSelectMenuOptionBuilder()
- .setLabel('Enable')
- .setDescription('Send a message when a user joins the server.')
- .setValue('enable'),
- new StringSelectMenuOptionBuilder()
- .setLabel('Disable')
- .setDescription("Don't send a message when a user joins the server.")
- .setValue('disable')
- );
-
- const channelMenu = new ChannelSelectMenuBuilder()
- .setCustomId('welcomeChannel')
- .setPlaceholder(
- currentChannelName ? `#${currentChannelName}` : 'Select a channel for welcome messages'
- )
- .setChannelTypes(ChannelType.GuildText);
-
- return {
- content: status
- ? `${emojis.rightArrow1} **Welcome** module:\n${emojis.rightArrow2} ${status}`
- : `${emojis.rightArrow1} **Welcome** module:`,
- components: [
- new ActionRowBuilder().addComponents(toggleMenu),
- new ActionRowBuilder().addComponents(channelMenu)
- ]
- };
+ const currentChannelName = settings.welcomeChannelId
+ ? guild.channels.cache.get(settings.welcomeChannelId)?.name
+ : null;
+
+ const toggleMenu = new StringSelectMenuBuilder()
+ .setCustomId('welcomeToggle')
+ .setPlaceholder(`${settings.welcomePeople ? 'Enabled' : 'Disabled'}`)
+ .addOptions(
+ new StringSelectMenuOptionBuilder()
+ .setLabel('Enable')
+ .setDescription('Send a message when a user joins the server.')
+ .setValue('enable'),
+ new StringSelectMenuOptionBuilder()
+ .setLabel('Disable')
+ .setDescription("Don't send a message when a user joins the server.")
+ .setValue('disable'),
+ );
+
+ const channelMenu = new ChannelSelectMenuBuilder()
+ .setCustomId('welcomeChannel')
+ .setPlaceholder(currentChannelName ? `#${currentChannelName}` : 'Select a channel for welcome messages')
+ .setChannelTypes(ChannelType.GuildText);
+
+ return {
+ content: status
+ ? `${emojis.rightArrow1} **Welcome** module:\n${emojis.rightArrow2} ${status}`
+ : `${emojis.rightArrow1} **Welcome** module:`,
+ components: [
+ new ActionRowBuilder().addComponents(toggleMenu),
+ new ActionRowBuilder().addComponents(channelMenu),
+ ],
+ };
}
function buildTicketPanel(settings: ServerSettings, guild: Guild, status?: string) {
- const currentCategoryName = settings.ticketCategoryId
- ? guild.channels.cache.get(settings.ticketCategoryId)?.name
- : null;
-
- const categoryMenu = new ChannelSelectMenuBuilder()
- .setCustomId('ticketCategory')
- .setPlaceholder(currentCategoryName ?? 'Select a category for tickets')
- .setChannelTypes(ChannelType.GuildCategory);
-
- const removeButton = new ButtonBuilder()
- .setCustomId('ticketCategoryRemove')
- .setLabel('Remove Category')
- .setStyle(ButtonStyle.Danger)
- .setDisabled(!settings.ticketCategoryId);
-
- const currentStaffRole = settings.staffRole
- ? guild.roles.cache.get(settings.staffRole)?.name
- : null;
-
- const staffRole = new RoleSelectMenuBuilder()
- .setCustomId('staffRole')
- .setPlaceholder(currentStaffRole ?? 'Select a ticket staff role');
-
- const removeStaffRoleButton = new ButtonBuilder()
- .setCustomId('removeStaffRole')
- .setLabel('Remove Staff Role')
- .setStyle(ButtonStyle.Danger)
- .setDisabled(!settings.staffRole);
-
- const currentTranscriptChannelName = settings.ticketTranscriptChannelId
- ? guild.channels.cache.get(settings.ticketTranscriptChannelId)?.name
- : null;
-
- const ticketTranscriptChannel = new ChannelSelectMenuBuilder()
- .setCustomId('ticketTranscriptChannel')
- .setPlaceholder(currentTranscriptChannelName ? `#${currentTranscriptChannelName}` : 'Select a channel for ticket transcripts')
- .setChannelTypes(ChannelType.GuildText);
-
- const removeTranscriptChannelButton = new ButtonBuilder()
- .setCustomId('removeTranscriptChannel')
- .setLabel('Remove Transcript Channel')
- .setStyle(ButtonStyle.Danger)
- .setDisabled(!settings.ticketTranscriptChannelId);
-
- return {
- content: status
- ? `${emojis.rightArrow1} **Tickets** module:\n${emojis.rightArrow2} ${status}`
- : `${emojis.rightArrow1} **Tickets** module:`,
- components: [
- new ActionRowBuilder().addComponents(categoryMenu),
- new ActionRowBuilder().addComponents(staffRole),
- new ActionRowBuilder().addComponents(ticketTranscriptChannel),
- new ActionRowBuilder().addComponents(removeButton, removeStaffRoleButton, removeTranscriptChannelButton)
- ]
- };
+ const currentCategoryName = settings.ticketCategoryId
+ ? guild.channels.cache.get(settings.ticketCategoryId)?.name
+ : null;
+
+ const categoryMenu = new ChannelSelectMenuBuilder()
+ .setCustomId('ticketCategory')
+ .setPlaceholder(currentCategoryName ?? 'Select a category for tickets')
+ .setChannelTypes(ChannelType.GuildCategory);
+
+ const removeButton = new ButtonBuilder()
+ .setCustomId('ticketCategoryRemove')
+ .setLabel('Remove Category')
+ .setStyle(ButtonStyle.Danger)
+ .setDisabled(!settings.ticketCategoryId);
+
+ const currentStaffRole = settings.staffRole ? guild.roles.cache.get(settings.staffRole)?.name : null;
+
+ const staffRole = new RoleSelectMenuBuilder()
+ .setCustomId('staffRole')
+ .setPlaceholder(currentStaffRole ?? 'Select a ticket staff role');
+
+ const removeStaffRoleButton = new ButtonBuilder()
+ .setCustomId('removeStaffRole')
+ .setLabel('Remove Staff Role')
+ .setStyle(ButtonStyle.Danger)
+ .setDisabled(!settings.staffRole);
+
+ const currentTranscriptChannelName = settings.ticketTranscriptChannelId
+ ? guild.channels.cache.get(settings.ticketTranscriptChannelId)?.name
+ : null;
+
+ const ticketTranscriptChannel = new ChannelSelectMenuBuilder()
+ .setCustomId('ticketTranscriptChannel')
+ .setPlaceholder(
+ currentTranscriptChannelName ? `#${currentTranscriptChannelName}` : 'Select a channel for ticket transcripts',
+ )
+ .setChannelTypes(ChannelType.GuildText);
+
+ const removeTranscriptChannelButton = new ButtonBuilder()
+ .setCustomId('removeTranscriptChannel')
+ .setLabel('Remove Transcript Channel')
+ .setStyle(ButtonStyle.Danger)
+ .setDisabled(!settings.ticketTranscriptChannelId);
+
+ return {
+ content: status
+ ? `${emojis.rightArrow1} **Tickets** module:\n${emojis.rightArrow2} ${status}`
+ : `${emojis.rightArrow1} **Tickets** module:`,
+ components: [
+ new ActionRowBuilder().addComponents(categoryMenu),
+ new ActionRowBuilder().addComponents(staffRole),
+ new ActionRowBuilder().addComponents(ticketTranscriptChannel),
+ new ActionRowBuilder().addComponents(
+ removeButton,
+ removeStaffRoleButton,
+ removeTranscriptChannelButton,
+ ),
+ ],
+ };
}
function buildLoggingPanel(settings: ServerSettings, guild: Guild, status?: string) {
- const currentChannelName = settings.loggingChannelId
- ? guild.channels.cache.get(settings.loggingChannelId)?.name
- : null;
-
- const toggleMenu = new StringSelectMenuBuilder()
- .setCustomId('loggingToggle')
- .setPlaceholder(`${settings.loggingEnabled ? 'Enabled' : 'Disabled'}`)
- .addOptions(
- new StringSelectMenuOptionBuilder()
- .setLabel('Enable')
- .setDescription('Log all server events.')
- .setValue('enable'),
- new StringSelectMenuOptionBuilder()
- .setLabel('Disable')
- .setDescription("Don't log any server events.")
- .setValue('disable')
- );
-
- const channelMenu = new ChannelSelectMenuBuilder()
- .setCustomId('loggingChannel')
- .setPlaceholder(
- currentChannelName ? `#${currentChannelName}` : 'Select a channel for logging messages'
- )
- .setChannelTypes(ChannelType.GuildText);
-
- return {
- content: status
- ? `${emojis.rightArrow1} **Logging** module:\n${emojis.rightArrow2} ${status}`
- : `${emojis.rightArrow1} **Logging** module:`,
- components: [
- new ActionRowBuilder().addComponents(toggleMenu),
- new ActionRowBuilder().addComponents(channelMenu)
- ]
- };
+ const currentChannelName = settings.loggingChannelId
+ ? guild.channels.cache.get(settings.loggingChannelId)?.name
+ : null;
+
+ const toggleMenu = new StringSelectMenuBuilder()
+ .setCustomId('loggingToggle')
+ .setPlaceholder(`${settings.loggingEnabled ? 'Enabled' : 'Disabled'}`)
+ .addOptions(
+ new StringSelectMenuOptionBuilder()
+ .setLabel('Enable')
+ .setDescription('Log all server events.')
+ .setValue('enable'),
+ new StringSelectMenuOptionBuilder()
+ .setLabel('Disable')
+ .setDescription("Don't log any server events.")
+ .setValue('disable'),
+ );
+
+ const channelMenu = new ChannelSelectMenuBuilder()
+ .setCustomId('loggingChannel')
+ .setPlaceholder(currentChannelName ? `#${currentChannelName}` : 'Select a channel for logging messages')
+ .setChannelTypes(ChannelType.GuildText);
+
+ return {
+ content: status
+ ? `${emojis.rightArrow1} **Logging** module:\n${emojis.rightArrow2} ${status}`
+ : `${emojis.rightArrow1} **Logging** module:`,
+ components: [
+ new ActionRowBuilder().addComponents(toggleMenu),
+ new ActionRowBuilder().addComponents(channelMenu),
+ ],
+ };
}
function buildConfessionPanel(settings: ServerSettings, guild: Guild, status?: string) {
- const currentChannelName = settings.confessionChannelId
- ? guild.channels.cache.get(settings.confessionChannelId)?.name
- : null;
-
- const toggleMenu = new StringSelectMenuBuilder()
- .setCustomId('confessionToggle')
- .setPlaceholder(`${settings.confessionEnabled ? 'Enabled' : 'Disabled'}`)
- .addOptions(
- new StringSelectMenuOptionBuilder()
- .setLabel('Enable')
- .setDescription('Enable confessions for this server.')
- .setValue('enable'),
- new StringSelectMenuOptionBuilder()
- .setLabel('Disable')
- .setDescription('Disable confessions for this server.')
- .setValue('disable')
- );
-
- const channelMenu = new ChannelSelectMenuBuilder()
- .setCustomId('confessionChannel')
- .setPlaceholder(currentChannelName ? `#${currentChannelName}` : 'Select a channel for confessions')
- .setChannelTypes(ChannelType.GuildText);
-
- return {
- content: status
- ? `${emojis.rightArrow1} **Confessions** module:
+ const currentChannelName = settings.confessionChannelId
+ ? guild.channels.cache.get(settings.confessionChannelId)?.name
+ : null;
+
+ const toggleMenu = new StringSelectMenuBuilder()
+ .setCustomId('confessionToggle')
+ .setPlaceholder(`${settings.confessionEnabled ? 'Enabled' : 'Disabled'}`)
+ .addOptions(
+ new StringSelectMenuOptionBuilder()
+ .setLabel('Enable')
+ .setDescription('Enable confessions for this server.')
+ .setValue('enable'),
+ new StringSelectMenuOptionBuilder()
+ .setLabel('Disable')
+ .setDescription('Disable confessions for this server.')
+ .setValue('disable'),
+ );
+
+ const channelMenu = new ChannelSelectMenuBuilder()
+ .setCustomId('confessionChannel')
+ .setPlaceholder(currentChannelName ? `#${currentChannelName}` : 'Select a channel for confessions')
+ .setChannelTypes(ChannelType.GuildText);
+
+ return {
+ content: status
+ ? `${emojis.rightArrow1} **Confessions** module:
${emojis.rightArrow2} ${status}`
- : `${emojis.rightArrow1} **Confessions** module:`,
- components: [
- new ActionRowBuilder().addComponents(toggleMenu),
- new ActionRowBuilder().addComponents(channelMenu)
- ]
- };
+ : `${emojis.rightArrow1} **Confessions** module:`,
+ components: [
+ new ActionRowBuilder().addComponents(toggleMenu),
+ new ActionRowBuilder().addComponents(channelMenu),
+ ],
+ };
}
async function normalizeTicketSettings(guildId: string, guild: Guild, settings: ServerSettings) {
- if (!settings.ticketCategoryId) return settings;
+ if (!settings.ticketCategoryId) return settings;
- const ticketCategory =
- guild.channels.cache.get(settings.ticketCategoryId) ??
- (await guild.channels.fetch(settings.ticketCategoryId).catch(() => null));
+ const ticketCategory =
+ guild.channels.cache.get(settings.ticketCategoryId) ??
+ (await guild.channels.fetch(settings.ticketCategoryId).catch(() => null));
- if (ticketCategory?.type === ChannelType.GuildCategory) return settings;
+ if (ticketCategory?.type === ChannelType.GuildCategory) return settings;
- return updateSettings(guildId, guild.name, { ticketCategoryId: null });
+ return updateSettings(guildId, guild.name, { ticketCategoryId: null });
}
export class SettingsCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
-
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder
- .setName('settings')
- .setDescription("Configure the bot's settings for this server.")
- .setDefaultMemberPermissions(PermissionFlagsBits.ManageGuild)
- .setContexts(InteractionContextType.Guild)
- );
- }
-
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- const safeEditReply = async (
- options: Parameters[0]
- ) => {
- try {
- await interaction.editReply(options);
- } catch (error) {
- if (isStaleInteractionError(error)) return;
- throw error;
- }
- };
-
- const settingMenu = new StringSelectMenuBuilder()
- .setCustomId('settingOption')
- .setPlaceholder('Select a setting to modify')
- .addOptions(
- new StringSelectMenuOptionBuilder()
- .setLabel('Welcome Message')
- .setDescription('Send a message when a user joins the server.')
- .setValue('welcome'),
- new StringSelectMenuOptionBuilder()
- .setLabel('Tickets')
- .setDescription('Configure where tickets are created.')
- .setValue('tickets'),
- new StringSelectMenuOptionBuilder()
- .setLabel('Logging')
- .setDescription('Configure server channel logging.')
- .setValue('logging')
- ,
- new StringSelectMenuOptionBuilder()
- .setLabel('Confessions')
- .setDescription('Configure where confessions are posted and whether they are enabled.')
- .setValue('confessions')
- );
-
- const response = await interaction.reply({
- components: [new ActionRowBuilder().addComponents(settingMenu)],
- flags: MessageFlags.Ephemeral,
- withResponse: true
- });
-
- const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
-
- try {
- const settingChoice = await import('#utils/collectors.js').then((m) =>
- m.awaitMessageComponentSafe(response.resource!.message!, { filter: collectorFilter, time: 60_000 })
- );
-
- if (!settingChoice) {
- await safeEditReply({
- content: `${emojis.rightArrow2} No response within a minute or errored.`,
- components: []
- });
- return;
- }
-
- if (!settingChoice.isStringSelectMenu()) return;
-
- const guildId = interaction.guildId;
- const guild = interaction.guild;
-
- if (!guildId || !guild) {
- await settingChoice.update({
- content: `${emojis.rightArrow2} This command can only be used in a server.`,
- components: []
- });
- return;
- }
-
- const settings = await normalizeTicketSettings(
- guildId,
- guild,
- await getSettings(guildId, guild.name)
- );
-
- if (settingChoice.values[0] === 'welcome') {
- await settingChoice.update(buildWelcomePanel(settings, guild));
- } else if (settingChoice.values[0] === 'tickets') {
- await settingChoice.update(buildTicketPanel(settings, guild));
- } else if (settingChoice.values[0] === 'logging') {
- await settingChoice.update(buildLoggingPanel(settings, guild));
- } else if (settingChoice.values[0] === 'confessions') {
- await settingChoice.update(buildConfessionPanel(settings, guild));
- } else {
- return;
- }
-
- const collector = settingChoice.message.createMessageComponentCollector({
- filter: collectorFilter,
- time: 60_000
- });
-
- collector.on('collect', async (i) => {
- if (i.customId === 'welcomeToggle' && i.isStringSelectMenu()) {
- const enable = i.values[0] === 'enable';
- const next = await updateSettings(guildId, guild.name, { welcomePeople: enable });
-
- await i.update(
- buildWelcomePanel(next, guild, `Welcome module **${enable ? 'enabled' : 'disabled'}**.`)
- );
- } else if (i.customId === 'welcomeChannel' && i.isChannelSelectMenu()) {
- const channelId = i.values[0];
- const next = await updateSettings(guildId, guild.name, { welcomeChannelId: channelId });
-
- await i.update(buildWelcomePanel(next, guild, `Welcome channel set to <#${channelId}>.`));
- } else if (i.customId === 'ticketCategory' && i.isChannelSelectMenu()) {
- const categoryId = i.values[0];
- const next = await updateSettings(guildId, guild.name, { ticketCategoryId: categoryId });
-
- await i.update(buildTicketPanel(next, guild, `Ticket category set to <#${categoryId}>.`));
- } else if (i.customId === 'ticketCategoryRemove' && i.isButton()) {
- const next = await updateSettings(guildId, guild.name, { ticketCategoryId: null });
-
- await i.update(buildTicketPanel(next, guild, 'Ticket category removed.'));
- } else if (i.customId === 'staffRole' && i.isRoleSelectMenu()) {
- const roleId = i.values[0];
- const next = await updateSettings(guildId, guild.name, { staffRole: roleId });
-
- await i.update(buildTicketPanel(next, guild, `Ticket staff role set to <@&${roleId}>.`));
- } else if (i.customId === 'removeStaffRole' && i.isButton()) {
- const next = await updateSettings(guildId, guild.name, { staffRole: null });
-
- await i.update(buildTicketPanel(next, guild, 'Ticket staff role removed.'));
- } else if (i.customId === 'ticketTranscriptChannel' && i.isChannelSelectMenu()) {
- const channelId = i.values[0];
- const next = await updateSettings(guildId, guild.name, { ticketTranscriptChannelId: channelId });
-
- await i.update(buildTicketPanel(next, guild, `Ticket transcript channel set to <#${channelId}>.`));
- } else if (i.customId === 'removeTranscriptChannel' && i.isButton()) {
- const next = await updateSettings(guildId, guild.name, { ticketTranscriptChannelId: null });
-
- await i.update(buildTicketPanel(next, guild, 'Ticket transcript channel removed.'));
- } else if (i.customId === 'loggingToggle' && i.isStringSelectMenu()) {
- const enable = i.values[0] === 'enable';
- const next = await updateSettings(guildId, guild.name, { loggingEnabled: enable });
-
- await i.update(
- buildLoggingPanel(next, guild, `Logging module **${enable ? 'enabled' : 'disabled'}**.`)
- );
- } else if (i.customId === 'loggingChannel' && i.isChannelSelectMenu()) {
- const channelId = i.values[0];
- const next = await updateSettings(guildId, guild.name, { loggingChannelId: channelId });
-
- await i.update(buildLoggingPanel(next, guild, `Logging channel set to <#${channelId}>.`));
- } else if (i.customId === 'confessionToggle' && i.isStringSelectMenu()) {
- const enable = i.values[0] === 'enable';
- const next = await updateSettings(guildId, guild.name, { confessionEnabled: enable });
-
- await i.update(buildConfessionPanel(next, guild, `Confessions **${enable ? 'enabled' : 'disabled'}**.`));
- } else if (i.customId === 'confessionChannel' && i.isChannelSelectMenu()) {
- const channelId = i.values[0];
- const next = await updateSettings(guildId, guild.name, { confessionChannelId: channelId });
-
- await i.update(buildConfessionPanel(next, guild, `Confession channel set to <#${channelId}>.`));
- }
- });
-
- collector.on('end', async () => {
- await safeEditReply({
- content: `${emojis.rightArrow2} Closed.`,
- components: []
- });
- });
- } catch (err) {
- console.error(err);
- await safeEditReply({
- content: `${emojis.rightArrow2} No response within a minute or errored.`,
- components: []
- });
- }
- }
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
+
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder
+ .setName('settings')
+ .setDescription("Configure the bot's settings for this server.")
+ .setDefaultMemberPermissions(PermissionFlagsBits.Administrator)
+ .setContexts(InteractionContextType.Guild),
+ );
+ }
+
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ const safeEditReply = async (options: Parameters[0]) => {
+ try {
+ await interaction.editReply(options);
+ } catch (error) {
+ if (isStaleInteractionError(error)) return;
+ throw error;
+ }
+ };
+
+ const settingMenu = new StringSelectMenuBuilder()
+ .setCustomId('settingOption')
+ .setPlaceholder('Select a setting to modify')
+ .addOptions(
+ new StringSelectMenuOptionBuilder()
+ .setLabel('Welcome Message')
+ .setDescription('Send a message when a user joins the server.')
+ .setValue('welcome'),
+ new StringSelectMenuOptionBuilder()
+ .setLabel('Tickets')
+ .setDescription('Configure where tickets are created.')
+ .setValue('tickets'),
+ new StringSelectMenuOptionBuilder()
+ .setLabel('Logging')
+ .setDescription('Configure server channel logging.')
+ .setValue('logging'),
+ new StringSelectMenuOptionBuilder()
+ .setLabel('Confessions')
+ .setDescription('Configure where confessions are posted and whether they are enabled.')
+ .setValue('confessions'),
+ );
+
+ const response = await interaction.reply({
+ components: [new ActionRowBuilder().addComponents(settingMenu)],
+ flags: MessageFlags.Ephemeral,
+ withResponse: true,
+ });
+
+ const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
+
+ try {
+ const settingChoice = await import('#utils/collectors.js').then((m) =>
+ m.awaitMessageComponentSafe(response.resource!.message!, { filter: collectorFilter, time: 60_000 }),
+ );
+
+ if (!settingChoice) {
+ await safeEditReply({
+ content: `${emojis.rightArrow2} No response within a minute or errored.`,
+ components: [],
+ });
+ return;
+ }
+
+ if (!settingChoice.isStringSelectMenu()) return;
+
+ const guildId = interaction.guildId;
+ const guild = interaction.guild;
+
+ if (!guildId || !guild) {
+ await settingChoice.update({
+ content: `${emojis.rightArrow2} This command can only be used in a server.`,
+ components: [],
+ });
+ return;
+ }
+
+ const settings = await normalizeTicketSettings(guildId, guild, await getSettings(guildId, guild.name));
+
+ if (settingChoice.values[0] === 'welcome') {
+ await settingChoice.update(buildWelcomePanel(settings, guild));
+ } else if (settingChoice.values[0] === 'tickets') {
+ await settingChoice.update(buildTicketPanel(settings, guild));
+ } else if (settingChoice.values[0] === 'logging') {
+ await settingChoice.update(buildLoggingPanel(settings, guild));
+ } else if (settingChoice.values[0] === 'confessions') {
+ await settingChoice.update(buildConfessionPanel(settings, guild));
+ } else {
+ return;
+ }
+
+ const collector = settingChoice.message.createMessageComponentCollector({
+ filter: collectorFilter,
+ time: 60_000,
+ });
+
+ collector.on('collect', async (i) => {
+ if (i.customId === 'welcomeToggle' && i.isStringSelectMenu()) {
+ const enable = i.values[0] === 'enable';
+ const next = await updateSettings(guildId, guild.name, { welcomePeople: enable });
+
+ await i.update(buildWelcomePanel(next, guild, `Welcome module **${enable ? 'enabled' : 'disabled'}**.`));
+ } else if (i.customId === 'welcomeChannel' && i.isChannelSelectMenu()) {
+ const channelId = i.values[0];
+ const next = await updateSettings(guildId, guild.name, { welcomeChannelId: channelId });
+
+ await i.update(buildWelcomePanel(next, guild, `Welcome channel set to <#${channelId}>.`));
+ } else if (i.customId === 'ticketCategory' && i.isChannelSelectMenu()) {
+ const categoryId = i.values[0];
+ const next = await updateSettings(guildId, guild.name, { ticketCategoryId: categoryId });
+
+ await i.update(buildTicketPanel(next, guild, `Ticket category set to <#${categoryId}>.`));
+ } else if (i.customId === 'ticketCategoryRemove' && i.isButton()) {
+ const next = await updateSettings(guildId, guild.name, { ticketCategoryId: null });
+
+ await i.update(buildTicketPanel(next, guild, 'Ticket category removed.'));
+ } else if (i.customId === 'staffRole' && i.isRoleSelectMenu()) {
+ const roleId = i.values[0];
+ const next = await updateSettings(guildId, guild.name, { staffRole: roleId });
+
+ await i.update(buildTicketPanel(next, guild, `Ticket staff role set to <@&${roleId}>.`));
+ } else if (i.customId === 'removeStaffRole' && i.isButton()) {
+ const next = await updateSettings(guildId, guild.name, { staffRole: null });
+
+ await i.update(buildTicketPanel(next, guild, 'Ticket staff role removed.'));
+ } else if (i.customId === 'ticketTranscriptChannel' && i.isChannelSelectMenu()) {
+ const channelId = i.values[0];
+ const next = await updateSettings(guildId, guild.name, { ticketTranscriptChannelId: channelId });
+
+ await i.update(buildTicketPanel(next, guild, `Ticket transcript channel set to <#${channelId}>.`));
+ } else if (i.customId === 'removeTranscriptChannel' && i.isButton()) {
+ const next = await updateSettings(guildId, guild.name, { ticketTranscriptChannelId: null });
+
+ await i.update(buildTicketPanel(next, guild, 'Ticket transcript channel removed.'));
+ } else if (i.customId === 'loggingToggle' && i.isStringSelectMenu()) {
+ const enable = i.values[0] === 'enable';
+ const next = await updateSettings(guildId, guild.name, { loggingEnabled: enable });
+
+ await i.update(buildLoggingPanel(next, guild, `Logging module **${enable ? 'enabled' : 'disabled'}**.`));
+ } else if (i.customId === 'loggingChannel' && i.isChannelSelectMenu()) {
+ const channelId = i.values[0];
+ const next = await updateSettings(guildId, guild.name, { loggingChannelId: channelId });
+
+ await i.update(buildLoggingPanel(next, guild, `Logging channel set to <#${channelId}>.`));
+ } else if (i.customId === 'confessionToggle' && i.isStringSelectMenu()) {
+ const enable = i.values[0] === 'enable';
+ const next = await updateSettings(guildId, guild.name, { confessionEnabled: enable });
+
+ await i.update(buildConfessionPanel(next, guild, `Confessions **${enable ? 'enabled' : 'disabled'}**.`));
+ } else if (i.customId === 'confessionChannel' && i.isChannelSelectMenu()) {
+ const channelId = i.values[0];
+ const next = await updateSettings(guildId, guild.name, { confessionChannelId: channelId });
+
+ await i.update(buildConfessionPanel(next, guild, `Confession channel set to <#${channelId}>.`));
+ }
+ });
+
+ collector.on('end', async () => {
+ await safeEditReply({
+ content: `${emojis.rightArrow2} Closed.`,
+ components: [],
+ });
+ });
+ } catch (err) {
+ console.error(err);
+ await safeEditReply({
+ content: `${emojis.rightArrow2} No response within a minute or errored.`,
+ components: [],
+ });
+ }
+ }
}
diff --git a/apps/bot/src/commands/utility/setup.ts b/apps/bot/src/commands/utility/setup.ts
index 90c7a25..0909133 100644
--- a/apps/bot/src/commands/utility/setup.ts
+++ b/apps/bot/src/commands/utility/setup.ts
@@ -1,16 +1,16 @@
import { Command } from '@sapphire/framework';
import {
- ActionRowBuilder,
- ButtonBuilder,
- ButtonStyle,
- ChannelSelectMenuBuilder,
- ChannelType,
- InteractionContextType,
- type Message,
- MessageFlags,
- type MessageComponentInteraction,
- PermissionFlagsBits,
- RoleSelectMenuBuilder
+ ActionRowBuilder,
+ ButtonBuilder,
+ ButtonStyle,
+ ChannelSelectMenuBuilder,
+ ChannelType,
+ InteractionContextType,
+ type Message,
+ MessageFlags,
+ type MessageComponentInteraction,
+ PermissionFlagsBits,
+ RoleSelectMenuBuilder,
} from 'discord.js';
import { getSettings, updateSettings } from '#lib/settings.js';
import { emojis } from '#utils/emoji.js';
@@ -19,610 +19,573 @@ import { awaitMessageComponentSafe } from '#utils/collectors.js';
const staleInteractionErrorCodes = new Set([10_015, 50_027, 10062]);
function isStaleInteractionError(error: unknown): error is { code: number } {
- return (
- typeof error === 'object' &&
- error !== null &&
- 'code' in error &&
- typeof error.code === 'number' &&
- staleInteractionErrorCodes.has(error.code)
- );
+ return (
+ typeof error === 'object' &&
+ error !== null &&
+ 'code' in error &&
+ typeof error.code === 'number' &&
+ staleInteractionErrorCodes.has(error.code)
+ );
}
const STEP_TIMEOUT = 90_000;
function yesNoRow() {
- return new ActionRowBuilder().addComponents(
- new ButtonBuilder().setCustomId('setup_yes').setLabel('Yes, enable it').setStyle(ButtonStyle.Success),
- new ButtonBuilder().setCustomId('setup_skip').setLabel('Skip').setStyle(ButtonStyle.Secondary)
- );
+ return new ActionRowBuilder().addComponents(
+ new ButtonBuilder().setCustomId('setup_yes').setLabel('Yes, enable it').setStyle(ButtonStyle.Success),
+ new ButtonBuilder().setCustomId('setup_skip').setLabel('Skip').setStyle(ButtonStyle.Secondary),
+ );
}
function nextSkipRow() {
- return new ActionRowBuilder().addComponents(
- new ButtonBuilder().setCustomId('setup_next').setLabel('Next').setStyle(ButtonStyle.Primary),
- new ButtonBuilder().setCustomId('setup_skip').setLabel('Skip this feature').setStyle(ButtonStyle.Secondary)
- );
+ return new ActionRowBuilder().addComponents(
+ new ButtonBuilder().setCustomId('setup_next').setLabel('Next').setStyle(ButtonStyle.Primary),
+ new ButtonBuilder().setCustomId('setup_skip').setLabel('Skip this feature').setStyle(ButtonStyle.Secondary),
+ );
}
async function runCollector(
- message: Message,
- filter: (i: any) => boolean,
- timeout: number,
- handler: (i: MessageComponentInteraction, stop: () => void) => Promise
+ message: Message,
+ filter: (i: any) => boolean,
+ timeout: number,
+ handler: (i: MessageComponentInteraction, stop: () => void) => Promise,
): Promise {
- return new Promise((resolve) => {
- const collector = message.createMessageComponentCollector({ filter, time: timeout });
- let stopped = false;
-
- const stop = () => {
- if (stopped) return;
- stopped = true;
- collector.stop('done');
- };
-
- collector.on('collect', async (i) => {
- await handler(i, stop);
- });
-
- collector.on('end', (_, reason) => {
- resolve(reason === 'done');
- });
- });
+ return new Promise((resolve) => {
+ const collector = message.createMessageComponentCollector({ filter, time: timeout });
+ let stopped = false;
+
+ const stop = () => {
+ if (stopped) return;
+ stopped = true;
+ collector.stop('done');
+ };
+
+ collector.on('collect', async (i) => {
+ await handler(i, stop);
+ });
+
+ collector.on('end', (_, reason) => {
+ resolve(reason === 'done');
+ });
+ });
}
export class SetupCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
-
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder
- .setName('setup')
- .setDescription('Guided setup to configure the bot for this server.')
- .setDefaultMemberPermissions(PermissionFlagsBits.Administrator)
- .setContexts(InteractionContextType.Guild)
- );
- }
-
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- if (!interaction.inCachedGuild()) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This command can only be used in a server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const { guildId, guild } = interaction;
- const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
-
- const safeEditReply = async (
- options: Parameters[0]
- ) => {
- try {
- await interaction.editReply(options);
- } catch (error) {
- if (isStaleInteractionError(error)) return;
- throw error;
- }
- };
-
- // initial menu
- const response = await interaction.reply({
- content: [
- `**Server Setup**`,
- `${emojis.rightArrow1} This wizard will walk you through configuring the bot's features.`,
- `${emojis.rightArrow1} You can adjust anything later with \`/settings\`.`
- ].join('\n'),
- components: [
- new ActionRowBuilder().addComponents(
- new ButtonBuilder()
- .setCustomId('setup_start')
- .setLabel('Get Started')
- .setStyle(ButtonStyle.Success),
- new ButtonBuilder()
- .setCustomId('setup_cancel')
- .setLabel('Cancel')
- .setStyle(ButtonStyle.Secondary)
- )
- ],
- flags: MessageFlags.Ephemeral,
- withResponse: true
- });
-
- const message = response.resource!.message!;
-
- const startChoice = await awaitMessageComponentSafe(message, {
- filter: collectorFilter,
- time: STEP_TIMEOUT
- });
-
- if (!startChoice || startChoice.customId === 'setup_cancel') {
- await safeEditReply({ content: `${emojis.rightArrow2} Setup cancelled.`, components: [] });
- return;
- }
-
- let settings = await getSettings(guildId, guild.name);
- const summary: string[] = [];
-
- // 1. welcome messages
- await startChoice.update({
- content: [
- `**Setup (1/4) Welcome Messages**`,
- `${emojis.rightArrow1} Would you like to send a welcome message when someone joins?`
- ].join('\n'),
- components: [yesNoRow()]
- });
-
- const welcomeFeatureChoice = await awaitMessageComponentSafe(message, {
- filter: collectorFilter,
- time: STEP_TIMEOUT
- });
-
- if (!welcomeFeatureChoice) {
- await safeEditReply({ content: `${emojis.rightArrow2} Setup timed out.`, components: [] });
- return;
- }
-
- if (welcomeFeatureChoice.customId === 'setup_yes') {
- let welcomeChannelId: string | null = null;
-
- const buildWelcomeConfigPanel = (status?: string) => ({
- content: [
- `**Setup (1/4) Welcome Messages**`,
- `${emojis.rightArrow1} Select the channel for welcome messages.`,
- status
- ? `${emojis.rightArrow2} ${status}`
- : `${emojis.rightArrow1} Click **Next** when ready.`
- ].join('\n'),
- components: [
- new ActionRowBuilder().addComponents(
- new ChannelSelectMenuBuilder()
- .setCustomId('setup_welcome_channel')
- .setPlaceholder(
- welcomeChannelId
- ? `${guild.channels.cache.get(welcomeChannelId)?.name ?? 'selected'}`
- : 'Select a channel'
- )
- .setChannelTypes(ChannelType.GuildText)
- ),
- nextSkipRow()
- ]
- });
-
- await welcomeFeatureChoice.update(buildWelcomeConfigPanel());
-
- const completed = await runCollector(message, collectorFilter, STEP_TIMEOUT, async (i, stop) => {
- if (i.customId === 'setup_welcome_channel' && i.isChannelSelectMenu()) {
- welcomeChannelId = i.values[0];
- await i.update(
- buildWelcomeConfigPanel(`Welcome channel set to <#${welcomeChannelId}>. Click **Next** to continue.`)
- );
- } else if (i.customId === 'setup_next' && i.isButton()) {
- await i.deferUpdate();
- stop();
- } else if (i.customId === 'setup_skip' && i.isButton()) {
- welcomeChannelId = null;
- await i.deferUpdate();
- stop();
- }
- });
-
- if (!completed) {
- await safeEditReply({ content: `${emojis.rightArrow2} Setup timed out.`, components: [] });
- return;
- }
-
- if (welcomeChannelId) {
- settings = await updateSettings(guildId, guild.name, {
- welcomePeople: true,
- welcomeChannelId
- });
- summary.push(`${emojis.rightArrow2} **Welcome Messages** enabled in <#${welcomeChannelId}>`);
- } else {
- summary.push(`${emojis.rightArrow1} **Welcome Messages** skipped`);
- }
- } else {
- await welcomeFeatureChoice.deferUpdate();
- summary.push(`${emojis.rightArrow1} **Welcome Messages** skipped`);
- }
-
- // 2: tickets
- await safeEditReply({
- content: [
- `**Setup (2/4) Tickets**`,
- `${emojis.rightArrow1} Would you like to enable tickets?`
- ].join('\n'),
- components: [yesNoRow()]
- });
-
- const ticketsFeatureChoice = await awaitMessageComponentSafe(message, {
- filter: collectorFilter,
- time: STEP_TIMEOUT
- });
-
- if (!ticketsFeatureChoice) {
- await safeEditReply({ content: `${emojis.rightArrow2} Setup timed out.`, components: [] });
- return;
- }
-
- if (ticketsFeatureChoice.customId === 'setup_yes') {
- let ticketCategoryId: string | null = null;
- let staffRoleId: string | null = null;
- let transcriptChannelId: string | null = null;
-
- const buildTicketConfigPanel = (status?: string) => ({
- content: [
- `**Setup (2/4) Tickets**`,
- `${emojis.rightArrow1} Configure the ticket system below. Staff role and transcript channel are optional.`,
- status
- ? `${emojis.rightArrow2} ${status}`
- : `${emojis.rightArrow1} Click **Next** when ready.`
- ].join('\n'),
- components: [
- new ActionRowBuilder().addComponents(
- new ChannelSelectMenuBuilder()
- .setCustomId('setup_ticket_category')
- .setPlaceholder(
- ticketCategoryId
- ? `#${guild.channels.cache.get(ticketCategoryId)?.name ?? 'selected'}`
- : 'Select a ticket category (required)'
- )
- .setChannelTypes(ChannelType.GuildCategory)
- ),
- new ActionRowBuilder().addComponents(
- new RoleSelectMenuBuilder()
- .setCustomId('setup_ticket_staff_role')
- .setPlaceholder(
- staffRoleId
- ? guild.roles.cache.get(staffRoleId)?.name ?? 'selected'
- : 'Select a staff role (optional)'
- )
- ),
- new ActionRowBuilder().addComponents(
- new ChannelSelectMenuBuilder()
- .setCustomId('setup_ticket_transcript')
- .setPlaceholder(
- transcriptChannelId
- ? `#${guild.channels.cache.get(transcriptChannelId)?.name ?? 'selected'}`
- : 'Select a transcript channel (optional)'
- )
- .setChannelTypes(ChannelType.GuildText)
- ),
- nextSkipRow()
- ]
- });
-
- await ticketsFeatureChoice.update(buildTicketConfigPanel());
-
- const completed = await runCollector(message, collectorFilter, STEP_TIMEOUT, async (i, stop) => {
- if (i.customId === 'setup_ticket_category' && i.isChannelSelectMenu()) {
- ticketCategoryId = i.values[0];
- await i.update(buildTicketConfigPanel(`Ticket category set to <#${ticketCategoryId}>.`));
- } else if (i.customId === 'setup_ticket_staff_role' && i.isRoleSelectMenu()) {
- staffRoleId = i.values[0];
- await i.update(buildTicketConfigPanel(`Staff role set to <@&${staffRoleId}>.`));
- } else if (i.customId === 'setup_ticket_transcript' && i.isChannelSelectMenu()) {
- transcriptChannelId = i.values[0];
- await i.update(buildTicketConfigPanel(`Transcript channel set to <#${transcriptChannelId}>.`));
- } else if (i.customId === 'setup_next' && i.isButton()) {
- await i.deferUpdate();
- stop();
- } else if (i.customId === 'setup_skip' && i.isButton()) {
- ticketCategoryId = null;
- staffRoleId = null;
- transcriptChannelId = null;
- await i.deferUpdate();
- stop();
- }
- });
-
- if (!completed) {
- await safeEditReply({ content: `${emojis.rightArrow2} Setup timed out.`, components: [] });
- return;
- }
-
- if (ticketCategoryId) {
- settings = await updateSettings(guildId, guild.name, {
- ticketCategoryId,
- staffRole: staffRoleId,
- ticketTranscriptChannelId: transcriptChannelId
- });
- summary.push(`${emojis.rightArrow2} **Tickets** enabled`);
-
- // sub-panel: post ticket panel
- await safeEditReply({
- content: [
- `**Setup (2/4) Ticket Panel**`,
- `${emojis.rightArrow1} Would you like to post the ticket creation panel in a channel?`,
- `${emojis.rightArrow1} Members click a button in that channel to open a ticket.`
- ].join('\n'),
- components: [
- new ActionRowBuilder().addComponents(
- new ButtonBuilder()
- .setCustomId('setup_yes')
- .setLabel('Yes!')
- .setStyle(ButtonStyle.Success),
- new ButtonBuilder()
- .setCustomId('setup_skip')
- .setLabel('Skip')
- .setStyle(ButtonStyle.Secondary)
- )
- ]
- });
-
- const panelChoice = await awaitMessageComponentSafe(message, {
- filter: collectorFilter,
- time: STEP_TIMEOUT
- });
-
- if (!panelChoice) {
- await safeEditReply({ content: `${emojis.rightArrow2} Setup timed out.`, components: [] });
- return;
- }
-
- if (panelChoice.customId === 'setup_yes') {
- let panelChannelId: string | null = null;
-
- const buildPanelChannelPanel = (status?: string) => ({
- content: [
- `**Setup (2/4) Ticket Panel**`,
- `${emojis.rightArrow1} Select the channel to post the ticket creation panel in.`,
- status
- ? `${emojis.rightArrow2} ${status}`
- : `${emojis.rightArrow1} Click **Send Panel** when ready.`
- ].join('\n'),
- components: [
- new ActionRowBuilder().addComponents(
- new ChannelSelectMenuBuilder()
- .setCustomId('setup_panel_channel')
- .setPlaceholder(
- panelChannelId
- ? `#${guild.channels.cache.get(panelChannelId)?.name ?? 'selected'}`
- : 'Select a channel'
- )
- .setChannelTypes(ChannelType.GuildText)
- ),
- new ActionRowBuilder().addComponents(
- new ButtonBuilder()
- .setCustomId('setup_send')
- .setLabel('Send Panel')
- .setStyle(ButtonStyle.Primary),
- new ButtonBuilder()
- .setCustomId('setup_skip')
- .setLabel('Skip')
- .setStyle(ButtonStyle.Secondary)
- )
- ]
- });
-
- await panelChoice.update(buildPanelChannelPanel());
-
- await runCollector(message, collectorFilter, STEP_TIMEOUT, async (i, stop) => {
- if (i.customId === 'setup_panel_channel' && i.isChannelSelectMenu()) {
- panelChannelId = i.values[0];
- await i.update(
- buildPanelChannelPanel(
- `Panel will be sent in <#${panelChannelId}>. Click **Send Panel** to post it.`
- )
- );
- } else if (i.customId === 'setup_send' && i.isButton()) {
- if (panelChannelId) {
- const panelChannel = guild.channels.cache.get(panelChannelId);
- if (panelChannel?.isTextBased()) {
- await panelChannel.send({
- content: '**Create a ticket by clicking the button below!**',
- components: [
- new ActionRowBuilder().addComponents(
- new ButtonBuilder()
- .setCustomId('create-ticket')
- .setLabel('Create Ticket')
- .setStyle(ButtonStyle.Success)
- )
- ]
- });
- }
- }
- await i.deferUpdate();
- stop();
- } else if (i.customId === 'setup_skip' && i.isButton()) {
- await i.deferUpdate();
- stop();
- }
- });
- } else {
- await panelChoice.deferUpdate();
- }
- } else {
- summary.push(`${emojis.rightArrow1} **Tickets** skipped`);
- }
- } else {
- await ticketsFeatureChoice.deferUpdate();
- summary.push(`${emojis.rightArrow2} **Tickets** skipped`);
- }
-
- // 3: logging
- await safeEditReply({
- content: [
- `**Setup (3/4) Logging**`,
- `${emojis.rightArrow1} Would you like to log server events (bans, kicks, message deletions, etc.) in a channel?`
- ].join('\n'),
- components: [yesNoRow()]
- });
-
- const loggingFeatureChoice = await awaitMessageComponentSafe(message, {
- filter: collectorFilter,
- time: STEP_TIMEOUT
- });
-
- if (!loggingFeatureChoice) {
- await safeEditReply({ content: `${emojis.rightArrow2} Setup timed out.`, components: [] });
- return;
- }
-
- if (loggingFeatureChoice.customId === 'setup_yes') {
- let loggingChannelId: string | null = null;
-
- const buildLoggingConfigPanel = (status?: string) => ({
- content: [
- `**Setup (3/4) Logging**`,
- `${emojis.rightArrow1} Select the channel where server events will be logged.`,
- status
- ? `${emojis.rightArrow2} ${status}`
- : `${emojis.rightArrow1} Click **Next** when ready.`
- ].join('\n'),
- components: [
- new ActionRowBuilder().addComponents(
- new ChannelSelectMenuBuilder()
- .setCustomId('setup_logging_channel')
- .setPlaceholder(
- loggingChannelId
- ? `#${guild.channels.cache.get(loggingChannelId)?.name ?? 'selected'}`
- : 'Select a channel'
- )
- .setChannelTypes(ChannelType.GuildText)
- ),
- nextSkipRow()
- ]
- });
-
- await loggingFeatureChoice.update(buildLoggingConfigPanel());
-
- const completed = await runCollector(message, collectorFilter, STEP_TIMEOUT, async (i, stop) => {
- if (i.customId === 'setup_logging_channel' && i.isChannelSelectMenu()) {
- loggingChannelId = i.values[0];
- await i.update(
- buildLoggingConfigPanel(
- `Logging channel set to <#${loggingChannelId}>. Click **Next** to continue.`
- )
- );
- } else if (i.customId === 'setup_next' && i.isButton()) {
- await i.deferUpdate();
- stop();
- } else if (i.customId === 'setup_skip' && i.isButton()) {
- loggingChannelId = null;
- await i.deferUpdate();
- stop();
- }
- });
-
- if (!completed) {
- await safeEditReply({ content: `${emojis.rightArrow2} Setup timed out.`, components: [] });
- return;
- }
-
- if (loggingChannelId) {
- settings = await updateSettings(guildId, guild.name, {
- loggingEnabled: true,
- loggingChannelId
- });
- summary.push(`${emojis.rightArrow2} **Logging** enabled, channel: <#${loggingChannelId}>`);
- } else {
- summary.push(`${emojis.rightArrow1} **Logging** skipped`);
- }
- } else {
- await loggingFeatureChoice.deferUpdate();
- summary.push(`${emojis.rightArrow1} **Logging** skipped`);
- }
-
- // 4: confessions
- await safeEditReply({
- content: [
- `**Setup (4/4) Confessions**`,
- `${emojis.rightArrow1} Would you like to enable confessions?`
- ].join('\n'),
- components: [yesNoRow()]
- });
-
- const confessionsFeatureChoice = await awaitMessageComponentSafe(message, {
- filter: collectorFilter,
- time: STEP_TIMEOUT
- });
-
- if (!confessionsFeatureChoice) {
- await safeEditReply({ content: `${emojis.rightArrow2} Setup timed out.`, components: [] });
- return;
- }
-
- if (confessionsFeatureChoice.customId === 'setup_yes') {
- let confessionChannelId: string | null = null;
-
- const buildConfessionConfigPanel = (status?: string) => ({
- content: [
- `**Setup (4/4) Confessions**`,
- `${emojis.rightArrow1} Select the channel where anonymous confessions will be posted.`,
- status
- ? `${emojis.rightArrow2} ${status}`
- : `${emojis.rightArrow1} Click **Next** when ready.`
- ].join('\n'),
- components: [
- new ActionRowBuilder().addComponents(
- new ChannelSelectMenuBuilder()
- .setCustomId('setup_confession_channel')
- .setPlaceholder(
- confessionChannelId
- ? `#${guild.channels.cache.get(confessionChannelId)?.name ?? 'selected'}`
- : 'Select a channel'
- )
- .setChannelTypes(ChannelType.GuildText)
- ),
- nextSkipRow()
- ]
- });
-
- await confessionsFeatureChoice.update(buildConfessionConfigPanel());
-
- const completed = await runCollector(message, collectorFilter, STEP_TIMEOUT, async (i, stop) => {
- if (i.customId === 'setup_confession_channel' && i.isChannelSelectMenu()) {
- confessionChannelId = i.values[0];
- await i.update(
- buildConfessionConfigPanel(
- `Confession channel set to <#${confessionChannelId}>. Click **Next** to continue.`
- )
- );
- } else if (i.customId === 'setup_next' && i.isButton()) {
- await i.deferUpdate();
- stop();
- } else if (i.customId === 'setup_skip' && i.isButton()) {
- confessionChannelId = null;
- await i.deferUpdate();
- stop();
- }
- });
-
- if (!completed) {
- await safeEditReply({ content: `${emojis.rightArrow2} Setup timed out.`, components: [] });
- return;
- }
-
- if (confessionChannelId) {
- settings = await updateSettings(guildId, guild.name, {
- confessionEnabled: true,
- confessionChannelId
- });
- summary.push(`${emojis.rightArrow2} **Confessions** enabled in <#${confessionChannelId}>`);
- } else {
- summary.push(`${emojis.rightArrow1} **Confessions** skipped`);
- }
- } else {
- await confessionsFeatureChoice.deferUpdate();
- summary.push(`${emojis.rightArrow1} **Confessions** skipped`);
- }
-
- await safeEditReply({
- content: [
- `${emojis.rightArrow1} Here's what was configured:`,
- ...summary,
- '',
- `${emojis.rightArrow1} **What's next?**`,
- `${emojis.rightArrow1} Use \`/automod add\` to block words in your server.`,
- `${emojis.rightArrow1} Use \`/autorole add\` to assign roles to new members automatically.`,
- `${emojis.rightArrow1} Use \`/settings\` to adjust any of these at any time.`
- ].join('\n'),
- components: []
- });
-
- void settings;
- }
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
+
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder
+ .setName('setup')
+ .setDescription('Guided setup to configure the bot for this server.')
+ .setDefaultMemberPermissions(PermissionFlagsBits.Administrator)
+ .setContexts(InteractionContextType.Guild),
+ );
+ }
+
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ if (!interaction.inCachedGuild()) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This command can only be used in a server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const { guildId, guild } = interaction;
+ const collectorFilter = (i: { user: { id: string } }) => i.user.id === interaction.user.id;
+
+ const safeEditReply = async (options: Parameters[0]) => {
+ try {
+ await interaction.editReply(options);
+ } catch (error) {
+ if (isStaleInteractionError(error)) return;
+ throw error;
+ }
+ };
+
+ // initial menu
+ const response = await interaction.reply({
+ content: [
+ `**Server Setup**`,
+ `${emojis.rightArrow1} This wizard will walk you through configuring the bot's features.`,
+ `${emojis.rightArrow1} You can adjust anything later with \`/settings\`.`,
+ `**Please put the newly created Quest role at the top of the role list!**`,
+ ].join('\n'),
+ components: [
+ new ActionRowBuilder().addComponents(
+ new ButtonBuilder().setCustomId('setup_start').setLabel('Get Started').setStyle(ButtonStyle.Success),
+ new ButtonBuilder().setCustomId('setup_cancel').setLabel('Cancel').setStyle(ButtonStyle.Secondary),
+ ),
+ ],
+ flags: MessageFlags.Ephemeral,
+ withResponse: true,
+ });
+
+ const message = response.resource!.message!;
+
+ const startChoice = await awaitMessageComponentSafe(message, {
+ filter: collectorFilter,
+ time: STEP_TIMEOUT,
+ });
+
+ if (!startChoice || startChoice.customId === 'setup_cancel') {
+ await safeEditReply({ content: `${emojis.rightArrow2} Setup cancelled.`, components: [] });
+ return;
+ }
+
+ let settings = await getSettings(guildId, guild.name);
+ const summary: string[] = [];
+
+ // 1. welcome messages
+ await startChoice.update({
+ content: [
+ `**Setup (1/4) Welcome Messages**`,
+ `${emojis.rightArrow1} Would you like to send a welcome message when someone joins?`,
+ ].join('\n'),
+ components: [yesNoRow()],
+ });
+
+ const welcomeFeatureChoice = await awaitMessageComponentSafe(message, {
+ filter: collectorFilter,
+ time: STEP_TIMEOUT,
+ });
+
+ if (!welcomeFeatureChoice) {
+ await safeEditReply({ content: `${emojis.rightArrow2} Setup timed out.`, components: [] });
+ return;
+ }
+
+ if (welcomeFeatureChoice.customId === 'setup_yes') {
+ let welcomeChannelId: string | null = null;
+
+ const buildWelcomeConfigPanel = (status?: string) => ({
+ content: [
+ `**Setup (1/4) Welcome Messages**`,
+ `${emojis.rightArrow1} Select the channel for welcome messages.`,
+ status ? `${emojis.rightArrow2} ${status}` : `${emojis.rightArrow1} Click **Next** when ready.`,
+ ].join('\n'),
+ components: [
+ new ActionRowBuilder().addComponents(
+ new ChannelSelectMenuBuilder()
+ .setCustomId('setup_welcome_channel')
+ .setPlaceholder(
+ welcomeChannelId
+ ? `${guild.channels.cache.get(welcomeChannelId)?.name ?? 'selected'}`
+ : 'Select a channel',
+ )
+ .setChannelTypes(ChannelType.GuildText),
+ ),
+ nextSkipRow(),
+ ],
+ });
+
+ await welcomeFeatureChoice.update(buildWelcomeConfigPanel());
+
+ const completed = await runCollector(message, collectorFilter, STEP_TIMEOUT, async (i, stop) => {
+ if (i.customId === 'setup_welcome_channel' && i.isChannelSelectMenu()) {
+ welcomeChannelId = i.values[0];
+ await i.update(
+ buildWelcomeConfigPanel(`Welcome channel set to <#${welcomeChannelId}>. Click **Next** to continue.`),
+ );
+ } else if (i.customId === 'setup_next' && i.isButton()) {
+ await i.deferUpdate();
+ stop();
+ } else if (i.customId === 'setup_skip' && i.isButton()) {
+ welcomeChannelId = null;
+ await i.deferUpdate();
+ stop();
+ }
+ });
+
+ if (!completed) {
+ await safeEditReply({ content: `${emojis.rightArrow2} Setup timed out.`, components: [] });
+ return;
+ }
+
+ if (welcomeChannelId) {
+ settings = await updateSettings(guildId, guild.name, {
+ welcomePeople: true,
+ welcomeChannelId,
+ });
+ summary.push(`${emojis.rightArrow2} **Welcome Messages** enabled in <#${welcomeChannelId}>`);
+ } else {
+ summary.push(`${emojis.rightArrow2} **Welcome Messages** skipped`);
+ }
+ } else {
+ await welcomeFeatureChoice.deferUpdate();
+ summary.push(`${emojis.rightArrow2} **Welcome Messages** skipped`);
+ }
+
+ // 2: tickets
+ await safeEditReply({
+ content: [`**Setup (2/4) Tickets**`, `${emojis.rightArrow1} Would you like to enable tickets?`].join('\n'),
+ components: [yesNoRow()],
+ });
+
+ const ticketsFeatureChoice = await awaitMessageComponentSafe(message, {
+ filter: collectorFilter,
+ time: STEP_TIMEOUT,
+ });
+
+ if (!ticketsFeatureChoice) {
+ await safeEditReply({ content: `${emojis.rightArrow2} Setup timed out.`, components: [] });
+ return;
+ }
+
+ if (ticketsFeatureChoice.customId === 'setup_yes') {
+ let ticketCategoryId: string | null = null;
+ let staffRoleId: string | null = null;
+ let transcriptChannelId: string | null = null;
+
+ const buildTicketConfigPanel = (status?: string) => ({
+ content: [
+ `**Setup (2/4) Tickets**`,
+ `${emojis.rightArrow1} Configure the ticket system below. Staff role and transcript channel are optional.`,
+ status ? `${emojis.rightArrow2} ${status}` : `${emojis.rightArrow1} Click **Next** when ready.`,
+ ].join('\n'),
+ components: [
+ new ActionRowBuilder().addComponents(
+ new ChannelSelectMenuBuilder()
+ .setCustomId('setup_ticket_category')
+ .setPlaceholder(
+ ticketCategoryId
+ ? `#${guild.channels.cache.get(ticketCategoryId)?.name ?? 'selected'}`
+ : 'Select a ticket category (required)',
+ )
+ .setChannelTypes(ChannelType.GuildCategory),
+ ),
+ new ActionRowBuilder().addComponents(
+ new RoleSelectMenuBuilder()
+ .setCustomId('setup_ticket_staff_role')
+ .setPlaceholder(
+ staffRoleId
+ ? (guild.roles.cache.get(staffRoleId)?.name ?? 'selected')
+ : 'Select a staff role (optional)',
+ ),
+ ),
+ new ActionRowBuilder().addComponents(
+ new ChannelSelectMenuBuilder()
+ .setCustomId('setup_ticket_transcript')
+ .setPlaceholder(
+ transcriptChannelId
+ ? `#${guild.channels.cache.get(transcriptChannelId)?.name ?? 'selected'}`
+ : 'Select a transcript channel (optional)',
+ )
+ .setChannelTypes(ChannelType.GuildText),
+ ),
+ nextSkipRow(),
+ ],
+ });
+
+ await ticketsFeatureChoice.update(buildTicketConfigPanel());
+
+ const completed = await runCollector(message, collectorFilter, STEP_TIMEOUT, async (i, stop) => {
+ if (i.customId === 'setup_ticket_category' && i.isChannelSelectMenu()) {
+ ticketCategoryId = i.values[0];
+ await i.update(buildTicketConfigPanel(`Ticket category set to <#${ticketCategoryId}>.`));
+ } else if (i.customId === 'setup_ticket_staff_role' && i.isRoleSelectMenu()) {
+ staffRoleId = i.values[0];
+ await i.update(buildTicketConfigPanel(`Staff role set to <@&${staffRoleId}>.`));
+ } else if (i.customId === 'setup_ticket_transcript' && i.isChannelSelectMenu()) {
+ transcriptChannelId = i.values[0];
+ await i.update(buildTicketConfigPanel(`Transcript channel set to <#${transcriptChannelId}>.`));
+ } else if (i.customId === 'setup_next' && i.isButton()) {
+ await i.deferUpdate();
+ stop();
+ } else if (i.customId === 'setup_skip' && i.isButton()) {
+ ticketCategoryId = null;
+ staffRoleId = null;
+ transcriptChannelId = null;
+ await i.deferUpdate();
+ stop();
+ }
+ });
+
+ if (!completed) {
+ await safeEditReply({ content: `${emojis.rightArrow2} Setup timed out.`, components: [] });
+ return;
+ }
+
+ if (ticketCategoryId) {
+ settings = await updateSettings(guildId, guild.name, {
+ ticketCategoryId,
+ staffRole: staffRoleId,
+ ticketTranscriptChannelId: transcriptChannelId,
+ });
+ summary.push(`${emojis.rightArrow2} **Tickets** enabled`);
+
+ // sub-panel: post ticket panel
+ await safeEditReply({
+ content: [
+ `**Setup (2/4) Ticket Panel**`,
+ `${emojis.rightArrow1} Would you like to post the ticket creation panel in a channel?`,
+ `${emojis.rightArrow1} Members click a button in that channel to open a ticket.`,
+ ].join('\n'),
+ components: [
+ new ActionRowBuilder().addComponents(
+ new ButtonBuilder().setCustomId('setup_yes').setLabel('Yes!').setStyle(ButtonStyle.Success),
+ new ButtonBuilder().setCustomId('setup_skip').setLabel('Skip').setStyle(ButtonStyle.Secondary),
+ ),
+ ],
+ });
+
+ const panelChoice = await awaitMessageComponentSafe(message, {
+ filter: collectorFilter,
+ time: STEP_TIMEOUT,
+ });
+
+ if (!panelChoice) {
+ await safeEditReply({ content: `${emojis.rightArrow2} Setup timed out.`, components: [] });
+ return;
+ }
+
+ if (panelChoice.customId === 'setup_yes') {
+ let panelChannelId: string | null = null;
+
+ const buildPanelChannelPanel = (status?: string) => ({
+ content: [
+ `**Setup (2/4) Ticket Panel**`,
+ `${emojis.rightArrow1} Select the channel to post the ticket creation panel in.`,
+ status ? `${emojis.rightArrow2} ${status}` : `${emojis.rightArrow1} Click **Send Panel** when ready.`,
+ ].join('\n'),
+ components: [
+ new ActionRowBuilder().addComponents(
+ new ChannelSelectMenuBuilder()
+ .setCustomId('setup_panel_channel')
+ .setPlaceholder(
+ panelChannelId
+ ? `#${guild.channels.cache.get(panelChannelId)?.name ?? 'selected'}`
+ : 'Select a channel',
+ )
+ .setChannelTypes(ChannelType.GuildText),
+ ),
+ new ActionRowBuilder().addComponents(
+ new ButtonBuilder().setCustomId('setup_send').setLabel('Send Panel').setStyle(ButtonStyle.Primary),
+ new ButtonBuilder().setCustomId('setup_skip').setLabel('Skip').setStyle(ButtonStyle.Secondary),
+ ),
+ ],
+ });
+
+ await panelChoice.update(buildPanelChannelPanel());
+
+ await runCollector(message, collectorFilter, STEP_TIMEOUT, async (i, stop) => {
+ if (i.customId === 'setup_panel_channel' && i.isChannelSelectMenu()) {
+ panelChannelId = i.values[0];
+ await i.update(
+ buildPanelChannelPanel(`Panel will be sent in <#${panelChannelId}>. Click **Send Panel** to post it.`),
+ );
+ } else if (i.customId === 'setup_send' && i.isButton()) {
+ if (panelChannelId) {
+ const panelChannel = guild.channels.cache.get(panelChannelId);
+ if (panelChannel?.isTextBased()) {
+ await panelChannel.send({
+ content: '**Create a ticket by clicking the button below!**',
+ components: [
+ new ActionRowBuilder().addComponents(
+ new ButtonBuilder()
+ .setCustomId('create-ticket')
+ .setLabel('Create Ticket')
+ .setStyle(ButtonStyle.Success),
+ ),
+ ],
+ });
+ }
+ }
+ await i.deferUpdate();
+ stop();
+ } else if (i.customId === 'setup_skip' && i.isButton()) {
+ await i.deferUpdate();
+ stop();
+ }
+ });
+ } else {
+ await panelChoice.deferUpdate();
+ }
+ } else {
+ summary.push(`${emojis.rightArrow2} **Tickets** skipped`);
+ }
+ } else {
+ await ticketsFeatureChoice.deferUpdate();
+ summary.push(`${emojis.rightArrow2} **Tickets** skipped`);
+ }
+
+ // 3: logging
+ await safeEditReply({
+ content: [
+ `**Setup (3/4) Logging**`,
+ `${emojis.rightArrow1} Would you like to log server events (bans, kicks, message deletions, etc.) in a channel?`,
+ ].join('\n'),
+ components: [yesNoRow()],
+ });
+
+ const loggingFeatureChoice = await awaitMessageComponentSafe(message, {
+ filter: collectorFilter,
+ time: STEP_TIMEOUT,
+ });
+
+ if (!loggingFeatureChoice) {
+ await safeEditReply({ content: `${emojis.rightArrow2} Setup timed out.`, components: [] });
+ return;
+ }
+
+ if (loggingFeatureChoice.customId === 'setup_yes') {
+ let loggingChannelId: string | null = null;
+
+ const buildLoggingConfigPanel = (status?: string) => ({
+ content: [
+ `**Setup (3/4) Logging**`,
+ `${emojis.rightArrow1} Select the channel where server events will be logged.`,
+ status ? `${emojis.rightArrow2} ${status}` : `${emojis.rightArrow1} Click **Next** when ready.`,
+ ].join('\n'),
+ components: [
+ new ActionRowBuilder().addComponents(
+ new ChannelSelectMenuBuilder()
+ .setCustomId('setup_logging_channel')
+ .setPlaceholder(
+ loggingChannelId
+ ? `#${guild.channels.cache.get(loggingChannelId)?.name ?? 'selected'}`
+ : 'Select a channel',
+ )
+ .setChannelTypes(ChannelType.GuildText),
+ ),
+ nextSkipRow(),
+ ],
+ });
+
+ await loggingFeatureChoice.update(buildLoggingConfigPanel());
+
+ const completed = await runCollector(message, collectorFilter, STEP_TIMEOUT, async (i, stop) => {
+ if (i.customId === 'setup_logging_channel' && i.isChannelSelectMenu()) {
+ loggingChannelId = i.values[0];
+ await i.update(
+ buildLoggingConfigPanel(`Logging channel set to <#${loggingChannelId}>. Click **Next** to continue.`),
+ );
+ } else if (i.customId === 'setup_next' && i.isButton()) {
+ await i.deferUpdate();
+ stop();
+ } else if (i.customId === 'setup_skip' && i.isButton()) {
+ loggingChannelId = null;
+ await i.deferUpdate();
+ stop();
+ }
+ });
+
+ if (!completed) {
+ await safeEditReply({ content: `${emojis.rightArrow2} Setup timed out.`, components: [] });
+ return;
+ }
+
+ if (loggingChannelId) {
+ settings = await updateSettings(guildId, guild.name, {
+ loggingEnabled: true,
+ loggingChannelId,
+ });
+ summary.push(`${emojis.rightArrow2} **Logging** enabled, channel: <#${loggingChannelId}>`);
+ } else {
+ summary.push(`${emojis.rightArrow1} **Logging** skipped`);
+ }
+ } else {
+ await loggingFeatureChoice.deferUpdate();
+ summary.push(`${emojis.rightArrow1} **Logging** skipped`);
+ }
+
+ // 4: confessions
+ await safeEditReply({
+ content: [`**Setup (4/4) Confessions**`, `${emojis.rightArrow1} Would you like to enable confessions?`].join(
+ '\n',
+ ),
+ components: [yesNoRow()],
+ });
+
+ const confessionsFeatureChoice = await awaitMessageComponentSafe(message, {
+ filter: collectorFilter,
+ time: STEP_TIMEOUT,
+ });
+
+ if (!confessionsFeatureChoice) {
+ await safeEditReply({ content: `${emojis.rightArrow2} Setup timed out.`, components: [] });
+ return;
+ }
+
+ if (confessionsFeatureChoice.customId === 'setup_yes') {
+ let confessionChannelId: string | null = null;
+
+ const buildConfessionConfigPanel = (status?: string) => ({
+ content: [
+ `**Setup (4/4) Confessions**`,
+ `${emojis.rightArrow1} Select the channel where anonymous confessions will be posted.`,
+ status ? `${emojis.rightArrow2} ${status}` : `${emojis.rightArrow1} Click **Next** when ready.`,
+ ].join('\n'),
+ components: [
+ new ActionRowBuilder().addComponents(
+ new ChannelSelectMenuBuilder()
+ .setCustomId('setup_confession_channel')
+ .setPlaceholder(
+ confessionChannelId
+ ? `#${guild.channels.cache.get(confessionChannelId)?.name ?? 'selected'}`
+ : 'Select a channel',
+ )
+ .setChannelTypes(ChannelType.GuildText),
+ ),
+ nextSkipRow(),
+ ],
+ });
+
+ await confessionsFeatureChoice.update(buildConfessionConfigPanel());
+
+ const completed = await runCollector(message, collectorFilter, STEP_TIMEOUT, async (i, stop) => {
+ if (i.customId === 'setup_confession_channel' && i.isChannelSelectMenu()) {
+ confessionChannelId = i.values[0];
+ await i.update(
+ buildConfessionConfigPanel(
+ `Confession channel set to <#${confessionChannelId}>. Click **Next** to continue.`,
+ ),
+ );
+ } else if (i.customId === 'setup_next' && i.isButton()) {
+ await i.deferUpdate();
+ stop();
+ } else if (i.customId === 'setup_skip' && i.isButton()) {
+ confessionChannelId = null;
+ await i.deferUpdate();
+ stop();
+ }
+ });
+
+ if (!completed) {
+ await safeEditReply({ content: `${emojis.rightArrow2} Setup timed out.`, components: [] });
+ return;
+ }
+
+ if (confessionChannelId) {
+ settings = await updateSettings(guildId, guild.name, {
+ confessionEnabled: true,
+ confessionChannelId,
+ });
+ summary.push(`${emojis.rightArrow2} **Confessions** enabled in <#${confessionChannelId}>`);
+ } else {
+ summary.push(`${emojis.rightArrow2} **Confessions** skipped`);
+ }
+ } else {
+ await confessionsFeatureChoice.deferUpdate();
+ summary.push(`${emojis.rightArrow2} **Confessions** skipped`);
+ }
+
+ await safeEditReply({
+ content: [
+ `**Here's what was configured:**`,
+ ...summary,
+ '',
+ `**What's next?**`,
+ `${emojis.rightArrow1} Use \`/automod add\` to block words in your server.`,
+ `${emojis.rightArrow1} Use \`/autorole add\` to assign roles to new members automatically.`,
+ `${emojis.rightArrow1} Use \`/settings\` to adjust any of these at any time.`,
+ ].join('\n'),
+ components: [],
+ });
+
+ void settings;
+ }
}
diff --git a/apps/bot/src/commands/utility/setupTickets.ts b/apps/bot/src/commands/utility/setupTickets.ts
index d1b7f91..3d8f30e 100644
--- a/apps/bot/src/commands/utility/setupTickets.ts
+++ b/apps/bot/src/commands/utility/setupTickets.ts
@@ -1,53 +1,53 @@
import { Command } from '@sapphire/framework';
import { emojis } from '#utils/emoji.js';
import {
- ActionRowBuilder,
- ButtonBuilder,
- ButtonStyle,
- ChannelType,
- MessageFlags,
- PermissionFlagsBits
+ ActionRowBuilder,
+ ButtonBuilder,
+ ButtonStyle,
+ ChannelType,
+ MessageFlags,
+ PermissionFlagsBits,
} from 'discord.js';
export class SetupTicketsCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder
- .setName('setup-tickets')
- .setDescription('Post the ticket panel in a channel.')
- .setDefaultMemberPermissions(PermissionFlagsBits.Administrator)
- .addChannelOption((option: any) =>
- option
- .setName('channel')
- .setDescription('The channel where the ticket panel should be posted')
- .addChannelTypes(ChannelType.GuildText)
- .setRequired(true)
- )
- );
- }
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder
+ .setName('setup-tickets')
+ .setDescription('Post the ticket panel in a channel.')
+ .setDefaultMemberPermissions(PermissionFlagsBits.Administrator)
+ .addChannelOption((option: any) =>
+ option
+ .setName('channel')
+ .setDescription('The channel where the ticket panel should be posted')
+ .addChannelTypes(ChannelType.GuildText)
+ .setRequired(true),
+ ),
+ );
+ }
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- const channel = interaction.options.getChannel('channel', true, [ChannelType.GuildText]);
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ const channel = interaction.options.getChannel('channel', true, [ChannelType.GuildText]);
- const button = new ButtonBuilder()
- .setCustomId('create-ticket')
- .setLabel('Create Ticket')
- .setStyle(ButtonStyle.Success);
+ const button = new ButtonBuilder()
+ .setCustomId('create-ticket')
+ .setLabel('Create Ticket')
+ .setStyle(ButtonStyle.Success);
- const row = new ActionRowBuilder().addComponents(button);
+ const row = new ActionRowBuilder().addComponents(button);
- await channel.send({
- content: `**Create a ticket by clicking the button below!**`,
- components: [row]
- });
+ await channel.send({
+ content: `**Create a ticket by clicking the button below!**`,
+ components: [row],
+ });
- await interaction.reply({
- content: `${emojis.rightArrow2} Ticket panel sent in ${channel}.`,
- flags: MessageFlags.Ephemeral
- });
- }
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Ticket panel sent in ${channel}.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ }
}
diff --git a/apps/bot/src/commands/utility/user.ts b/apps/bot/src/commands/utility/user.ts
index f81dbd8..25e6504 100644
--- a/apps/bot/src/commands/utility/user.ts
+++ b/apps/bot/src/commands/utility/user.ts
@@ -2,19 +2,17 @@ import { Command } from '@sapphire/framework';
import { emojis } from '#utils/emoji.js';
export class UserCommand extends Command {
- public constructor(context: Command.LoaderContext, options: Command.Options) {
- super(context, { ...options, preconditions: ['devMode'] });
- }
+ public constructor(context: Command.LoaderContext, options: Command.Options) {
+ super(context, { ...options, preconditions: ['devMode'] });
+ }
- public override registerApplicationCommands(registry: Command.Registry) {
- registry.registerChatInputCommand((builder: any) =>
- builder.setName('user').setDescription('Provides information about the user.')
- );
- }
+ public override registerApplicationCommands(registry: Command.Registry) {
+ registry.registerChatInputCommand((builder: any) =>
+ builder.setName('user').setDescription('Provides information about the user.'),
+ );
+ }
- public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
- await interaction.reply(
- `${emojis.rightArrow2} This command was run by **${interaction.user.username}**.`
- );
- }
-}
\ No newline at end of file
+ public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
+ await interaction.reply(`${emojis.rightArrow2} This command was run by **${interaction.user.username}**.`);
+ }
+}
diff --git a/apps/bot/src/index.ts b/apps/bot/src/index.ts
index 2e89817..4d38b49 100644
--- a/apps/bot/src/index.ts
+++ b/apps/bot/src/index.ts
@@ -1,30 +1,24 @@
import process from 'node:process';
import { fileURLToPath } from 'node:url';
-import {
- ApplicationCommandRegistries,
- RegisterBehavior,
- SapphireClient
-} from '@sapphire/framework';
+import { ApplicationCommandRegistries, RegisterBehavior, SapphireClient } from '@sapphire/framework';
import { GatewayIntentBits, Partials } from 'discord.js';
-ApplicationCommandRegistries.setDefaultBehaviorWhenNotIdentical(
- RegisterBehavior.BulkOverwrite
-);
+ApplicationCommandRegistries.setDefaultBehaviorWhenNotIdentical(RegisterBehavior.BulkOverwrite);
const client = new SapphireClient({
- intents: [
- GatewayIntentBits.Guilds,
- GatewayIntentBits.GuildMembers,
- GatewayIntentBits.GuildMessages,
- GatewayIntentBits.MessageContent,
- GatewayIntentBits.GuildModeration,
- GatewayIntentBits.GuildExpressions
- ],
- partials: [Partials.Message, Partials.Channel],
- presence: {
- status: 'online'
- },
- baseUserDirectory: fileURLToPath(new URL('.', import.meta.url))
+ intents: [
+ GatewayIntentBits.Guilds,
+ GatewayIntentBits.GuildMembers,
+ GatewayIntentBits.GuildMessages,
+ GatewayIntentBits.MessageContent,
+ GatewayIntentBits.GuildModeration,
+ GatewayIntentBits.GuildExpressions,
+ ],
+ partials: [Partials.Message, Partials.Channel],
+ presence: {
+ status: 'online',
+ },
+ baseUserDirectory: fileURLToPath(new URL('.', import.meta.url)),
});
void client.login(process.env.DISCORD_TOKEN);
diff --git a/apps/bot/src/interaction-handlers/confession/confessionHandler.ts b/apps/bot/src/interaction-handlers/confession/confessionHandler.ts
index 9ea77ad..11cfa10 100644
--- a/apps/bot/src/interaction-handlers/confession/confessionHandler.ts
+++ b/apps/bot/src/interaction-handlers/confession/confessionHandler.ts
@@ -1,416 +1,327 @@
import { InteractionHandler, InteractionHandlerTypes } from '@sapphire/framework';
import {
- ActionRowBuilder,
- ButtonBuilder,
- ButtonStyle,
- EmbedBuilder,
- LabelBuilder,
- MessageFlags,
- ModalBuilder,
- TextChannel,
- TextInputBuilder,
- TextInputStyle,
- type ButtonInteraction,
+ ActionRowBuilder,
+ ButtonBuilder,
+ ButtonStyle,
+ EmbedBuilder,
+ LabelBuilder,
+ MessageFlags,
+ ModalBuilder,
+ TextInputBuilder,
+ TextInputStyle,
+ type ButtonInteraction,
} from 'discord.js';
import {
- getModeratorIds,
- buildConfessionLink,
- getConfessionContext,
- removeConfessionContext,
- storeConfessionContext
+ getModeratorIds,
+ buildConfessionLink,
+ getConfessionContext,
+ removeConfessionContext,
} from '#lib/confessions.js';
-import { getSettings } from '#lib/settings.js';
import { emojis } from '#utils/emoji.js';
interface ParsedConfessionButton {
- action: string;
- messageId?: string;
- guildId?: string;
- channelId?: string;
+ action: string;
+ messageId?: string;
+ guildId?: string;
+ channelId?: string;
}
function parseConfessionButton(customId: string): ParsedConfessionButton {
- const [action, ...parts] = customId.split(':');
- const result: ParsedConfessionButton = { action };
+ const [action, ...parts] = customId.split(':');
+ const result: ParsedConfessionButton = { action };
- if (action === 'delete-confession' && parts.length >= 3) {
- [result.guildId, result.channelId, result.messageId] = parts;
- } else if (parts.length > 0) {
- [result.messageId] = parts;
- }
+ if (action === 'delete-confession' && parts.length >= 3) {
+ [result.guildId, result.channelId, result.messageId] = parts;
+ } else if (parts.length > 0) {
+ [result.messageId] = parts;
+ }
- return result;
+ return result;
}
function createTextInputModal(customId: string, title: string, inputId: string, label: string) {
- const input = new TextInputBuilder()
- .setCustomId(inputId)
- .setStyle(TextInputStyle.Paragraph)
- .setRequired(true)
- .setMaxLength(1_000);
-
- return new ModalBuilder()
- .setCustomId(customId)
- .setTitle(title)
- .addLabelComponents(new LabelBuilder().setLabel(label).setTextInputComponent(input));
+ const input = new TextInputBuilder()
+ .setCustomId(inputId)
+ .setStyle(TextInputStyle.Paragraph)
+ .setRequired(true)
+ .setMaxLength(1_000);
+
+ return new ModalBuilder()
+ .setCustomId(customId)
+ .setTitle(title)
+ .addLabelComponents(new LabelBuilder().setLabel(label).setTextInputComponent(input));
}
async function fetchConfessionChannel(interaction: ButtonInteraction, channelId: string, guildId?: string) {
- try {
- let channel = null;
-
- if (guildId) {
- const guild = await interaction.client.guilds.fetch(guildId).catch(() => null);
- if (guild) {
- channel = await guild.channels.fetch(channelId).catch(() => null);
- }
- } else if (interaction.inGuild() && interaction.guild) {
- channel = await interaction.guild.channels.fetch(channelId).catch(() => null);
- }
-
- if (!channel) {
- channel = await interaction.client.channels.fetch(channelId).catch(() => null);
- }
-
- return channel?.isTextBased() ? channel : null;
- } catch {
- return null;
- }
+ try {
+ let channel = null;
+
+ if (guildId) {
+ const guild = await interaction.client.guilds.fetch(guildId).catch(() => null);
+ if (guild) {
+ channel = await guild.channels.fetch(channelId).catch(() => null);
+ }
+ } else if (interaction.inGuild() && interaction.guild) {
+ channel = await interaction.guild.channels.fetch(channelId).catch(() => null);
+ }
+
+ if (!channel) {
+ channel = await interaction.client.channels.fetch(channelId).catch(() => null);
+ }
+
+ return channel?.isTextBased() ? channel : null;
+ } catch {
+ return null;
+ }
}
export class ConfessionButtonHandler extends InteractionHandler {
- public constructor(ctx: InteractionHandler.LoaderContext, options: InteractionHandler.Options) {
- super(ctx, {
- ...options,
- interactionHandlerType: InteractionHandlerTypes.Button
- });
- }
-
- public override parse(interaction: ButtonInteraction) {
- if (
- interaction.customId !== 'create-confession' &&
- !interaction.customId.startsWith('report-confession:') &&
- !interaction.customId.startsWith('delete-confession:')
- ) {
- return this.none();
- }
-
- return this.some();
- }
-
- public async run(interaction: ButtonInteraction) {
- if (interaction.customId === 'create-confession') {
- await this.handleCreateConfession(interaction);
- return;
- }
-
- const parsed = parseConfessionButton(interaction.customId);
-
- if (parsed.action === 'report-confession') {
- await this.handleReportConfession(interaction, parsed);
- return;
- }
-
- if (parsed.action === 'delete-confession') {
- await this.handleDeleteConfession(interaction, parsed);
- }
- }
-
- private async handleCreateConfession(interaction: ButtonInteraction) {
- if (!interaction.inGuild() || !interaction.guild) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This button can only be used in a server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const settings = await getSettings(interaction.guild.id, interaction.guild.name);
-
- if (!settings.confessionChannelId) {
- await interaction.reply({
- content: `${emojis.rightArrow2} Confessions are not configured yet.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const modal = createTextInputModal('create-confession-modal', 'Create Confession', 'confession-text', 'Confession');
- await interaction.showModal(modal);
-
- try {
- const modalSubmit = await interaction.awaitModalSubmit({
- filter: (modal) =>
- modal.customId === 'create-confession-modal' && modal.user.id === interaction.user.id,
- time: 60_000
- });
- await modalSubmit.deferReply({ flags: MessageFlags.Ephemeral });
-
- const confession = modalSubmit.fields.getTextInputValue('confession-text');
- const confessionChannel = await interaction.guild.channels
- .fetch(settings.confessionChannelId)
- .catch(() => null);
-
- if (!(confessionChannel instanceof TextChannel)) {
- await modalSubmit.editReply({
- content: `${emojis.rightArrow2} The configured confession channel is unavailable.`
- });
- return;
- }
-
- const embed = new EmbedBuilder()
- .setTitle('Confession')
- .setDescription(confession)
- .setTimestamp();
-
- const message = await confessionChannel.send({ embeds: [embed] });
-
- try {
- const threadName = confession.replace(/\s+/g, ' ').slice(0, 10).toLowerCase() || 'confession';
- const thread = await message.startThread({ name: `confession-${threadName}` });
-
- const reportButton = new ButtonBuilder()
- .setCustomId(`report-confession:${message.id}`)
- .setLabel('Report')
- .setStyle(ButtonStyle.Danger);
-
- await message.edit({ components: [new ActionRowBuilder().addComponents(reportButton)] });
-
- await storeConfessionContext({
- guildId: interaction.guild.id,
- channelId: confessionChannel.id,
- messageId: message.id,
- threadId: thread.id,
- creatorId: modalSubmit.user.id
- });
-
- await modalSubmit.editReply({
- content: `${emojis.rightArrow1} Confession sent.`
- });
- } catch (error) {
- await message.delete().catch(() => null);
- throw error;
- }
- } catch {
- return;
- }
- }
-
- private async handleReportConfession(interaction: ButtonInteraction, parsed: ParsedConfessionButton) {
- if (!interaction.inGuild() || !interaction.guild || !parsed.messageId) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This confession cannot be reported right now.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const context = await getConfessionContext(parsed.messageId);
-
- if (!context) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This confession is no longer available.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const moderators = getModeratorIds();
-
- if (moderators.length === 0) {
- await interaction.reply({
- content: `${emojis.rightArrow2} No bot moderators are configured.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const modal = createTextInputModal(
- `report-confession-modal:${parsed.messageId}`,
- 'Report Confession',
- 'confession-report-reason',
- 'Reason'
- );
-
- await interaction.showModal(modal);
-
- let modalSubmit;
-
- try {
- modalSubmit = await interaction.awaitModalSubmit({
- filter: (modal) =>
- modal.customId === `report-confession-modal:${parsed.messageId}` && modal.user.id === interaction.user.id,
- time: 60_000
- });
- } catch {
- return;
- }
-
- const reason = modalSubmit.fields.getTextInputValue('confession-report-reason');
- await modalSubmit.deferReply({ flags: MessageFlags.Ephemeral });
-
- const channel = await fetchConfessionChannel(interaction, context.channelId);
-
- if (!channel) {
- console.error('Confession channel fetch failed', { channelId: context.channelId, context });
- await modalSubmit.editReply({
- content: `${emojis.rightArrow2} The confession channel (<#${context.channelId}>) is no longer available.`
- });
- return;
- }
-
- const message = await channel.messages.fetch(context.messageId).catch(() => null);
-
- if (!message) {
- await modalSubmit.editReply({
- content: `${emojis.rightArrow2} That confession no longer exists.`
- });
- return;
- }
-
- const deleteButton = new ButtonBuilder()
- .setCustomId(`delete-confession:${context.guildId}:${context.channelId}:${context.messageId}`)
- .setLabel('Delete Confession')
- .setStyle(ButtonStyle.Danger);
-
- const confessionText = message.embeds[0]?.description ?? 'No confession content was found.';
- const link = buildConfessionLink(context.guildId, context.channelId, context.messageId);
-
- let confessorDisplay = 'Unknown';
- if (context.creatorId) {
- const confessorUser = await interaction.client.users.fetch(context.creatorId).catch(() => null);
- confessorDisplay = confessorUser ? `${confessorUser.tag} (${confessorUser.id})` : context.creatorId;
- }
-
- const reportEmbed = new EmbedBuilder()
- .setTitle('Confession Reported')
- .addFields(
- { name: 'Guild', value: `${interaction.guild.name} (${interaction.guild.id})` },
- { name: 'Channel', value: `<#${context.channelId}>` },
- { name: 'Reported by', value: `${modalSubmit.user.tag} (${modalSubmit.user.id})` },
- { name: 'Confessor', value: confessorDisplay },
- { name: 'Reason', value: reason },
- { name: 'Confession', value: confessionText.slice(0, 1024) },
- { name: 'Link', value: link }
- )
- .setTimestamp();
-
- const deliveries = await Promise.allSettled(
- moderators.map((moderatorId) => this.sendReportToModerator(interaction, moderatorId, reportEmbed, deleteButton))
- );
-
- const delivered = deliveries.some((result) => result.status === 'fulfilled');
-
- if (!delivered) {
- await modalSubmit.editReply({
- content: `${emojis.rightArrow2} I could not contact any configured moderators.`
- });
- return;
- }
-
- await modalSubmit.editReply({
- content: `${emojis.rightArrow1} Your report was sent to the bot moderators.`
- });
- }
-
- private async sendReportToModerator(
- interaction: ButtonInteraction,
- moderatorId: string,
- reportEmbed: EmbedBuilder,
- deleteButton: ButtonBuilder
- ) {
- const user = await interaction.client.users.fetch(moderatorId);
- const row = new ActionRowBuilder().addComponents(deleteButton);
- await user.send({ embeds: [reportEmbed], components: [row] });
- }
-
- private async handleDeleteConfession(interaction: ButtonInteraction, parsed: ParsedConfessionButton) {
- if (interaction.inGuild() || !parsed.messageId) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This action can only be used from a moderator DM.`
- });
- return;
- }
-
- const context =
- parsed.guildId && parsed.channelId && parsed.messageId
- ? { guildId: parsed.guildId, channelId: parsed.channelId, messageId: parsed.messageId, threadId: '' }
- : await getConfessionContext(parsed.messageId);
-
- if (!context) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This confession is no longer available.`
- });
- return;
- }
-
- const moderatorIds = getModeratorIds();
-
- if (!moderatorIds.includes(interaction.user.id)) {
- await interaction.reply({
- content: `${emojis.rightArrow2} You are not configured as a bot moderator.`
- });
- return;
- }
-
- const channel = await fetchConfessionChannel(interaction, context.channelId, context.guildId);
-
- if (!channel) {
- console.error('Confession channel fetch failed (delete flow)', {
- channelId: context.channelId,
- guildId: context.guildId,
- context
- });
-
- await removeConfessionContext(context.messageId);
-
- await interaction.reply({
- content: `${emojis.rightArrow2} The confession channel (<#${context.channelId}>) is no longer available, but the confession has been removed from records.`
- });
- return;
- }
-
- const message = await channel.messages.fetch(context.messageId).catch(() => null);
-
- if (!message) {
- await removeConfessionContext(context.messageId);
-
- await interaction.reply({
- content: `${emojis.rightArrow2} That confession no longer exists, but the record has been cleaned up.`
- });
- return;
- }
-
- const deletedEmbed = new EmbedBuilder()
- .setTitle('Confession')
- .setDescription('This confession was deleted by global moderators.')
- .setColor(0xed4245)
- .setTimestamp();
-
- try {
- await message.edit({ embeds: [deletedEmbed], components: [] });
- } catch {
- await interaction.reply({
- content: `${emojis.rightArrow2} I could not update the confession message.`
- });
- return;
- }
-
- try {
- if (context.threadId) {
- const thread = await interaction.client.channels.fetch(context.threadId).catch(() => null);
- if (thread && typeof (thread as any).setName === 'function') {
- await (thread as any).setName('confession-deleted').catch(() => null);
- }
- }
- } catch (error) {
- console.error('Failed to rename confession thread', { threadId: context.threadId, error });
- }
-
- await removeConfessionContext(context.messageId);
-
- await interaction.reply({
- content: `${emojis.rightArrow1} Confession marked as deleted.`
- });
- }
-}
\ No newline at end of file
+ public constructor(ctx: InteractionHandler.LoaderContext, options: InteractionHandler.Options) {
+ super(ctx, {
+ ...options,
+ interactionHandlerType: InteractionHandlerTypes.Button,
+ });
+ }
+
+ public override parse(interaction: ButtonInteraction) {
+ if (
+ !interaction.customId.startsWith('report-confession:') &&
+ !interaction.customId.startsWith('delete-confession:')
+ ) {
+ return this.none();
+ }
+
+ return this.some();
+ }
+
+ public async run(interaction: ButtonInteraction) {
+ const parsed = parseConfessionButton(interaction.customId);
+
+ if (parsed.action === 'report-confession') {
+ await this.handleReportConfession(interaction, parsed);
+ return;
+ }
+
+ if (parsed.action === 'delete-confession') {
+ await this.handleDeleteConfession(interaction, parsed);
+ }
+ }
+
+ private async handleReportConfession(interaction: ButtonInteraction, parsed: ParsedConfessionButton) {
+ if (!interaction.inGuild() || !interaction.guild || !parsed.messageId) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This confession cannot be reported right now.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const context = await getConfessionContext(parsed.messageId);
+
+ if (!context) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This confession is no longer available.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const moderators = getModeratorIds();
+
+ if (moderators.length === 0) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} No bot moderators are configured.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const modal = createTextInputModal(
+ `report-confession-modal:${parsed.messageId}`,
+ 'Report Confession',
+ 'confession-report-reason',
+ 'Reason',
+ );
+
+ await interaction.showModal(modal);
+
+ let modalSubmit;
+
+ try {
+ modalSubmit = await interaction.awaitModalSubmit({
+ filter: (modal) =>
+ modal.customId === `report-confession-modal:${parsed.messageId}` && modal.user.id === interaction.user.id,
+ time: 60_000,
+ });
+ } catch {
+ return;
+ }
+
+ const reason = modalSubmit.fields.getTextInputValue('confession-report-reason');
+ await modalSubmit.deferReply({ flags: MessageFlags.Ephemeral });
+
+ const channel = await fetchConfessionChannel(interaction, context.channelId);
+
+ if (!channel) {
+ console.error('Confession channel fetch failed', { channelId: context.channelId, context });
+ await modalSubmit.editReply({
+ content: `${emojis.rightArrow2} The confession channel (<#${context.channelId}>) is no longer available.`,
+ });
+ return;
+ }
+
+ const message = await channel.messages.fetch(context.messageId).catch(() => null);
+
+ if (!message) {
+ await modalSubmit.editReply({
+ content: `${emojis.rightArrow2} That confession no longer exists.`,
+ });
+ return;
+ }
+
+ const deleteButton = new ButtonBuilder()
+ .setCustomId(`delete-confession:${context.guildId}:${context.channelId}:${context.messageId}`)
+ .setLabel('Delete Confession')
+ .setStyle(ButtonStyle.Danger);
+
+ const confessionText = message.embeds[0]?.description ?? 'No confession content was found.';
+ const link = buildConfessionLink(context.guildId, context.channelId, context.messageId);
+
+ let confessorDisplay = 'Unknown';
+ if (context.creatorId) {
+ const confessorUser = await interaction.client.users.fetch(context.creatorId).catch(() => null);
+ confessorDisplay = confessorUser ? `${confessorUser.tag} (${confessorUser.id})` : context.creatorId;
+ }
+
+ const reportEmbed = new EmbedBuilder()
+ .setTitle('Confession Reported')
+ .addFields(
+ { name: 'Guild', value: `${interaction.guild.name} (${interaction.guild.id})` },
+ { name: 'Channel', value: `<#${context.channelId}>` },
+ { name: 'Reported by', value: `${modalSubmit.user.tag} (${modalSubmit.user.id})` },
+ { name: 'Confessor', value: confessorDisplay },
+ { name: 'Reason', value: reason },
+ { name: 'Confession', value: confessionText.slice(0, 1024) },
+ { name: 'Link', value: link },
+ )
+ .setTimestamp();
+
+ const deliveries = await Promise.allSettled(
+ moderators.map((moderatorId) => this.sendReportToModerator(interaction, moderatorId, reportEmbed, deleteButton)),
+ );
+
+ const delivered = deliveries.some((result) => result.status === 'fulfilled');
+
+ if (!delivered) {
+ await modalSubmit.editReply({
+ content: `${emojis.rightArrow2} I could not contact any configured moderators.`,
+ });
+ return;
+ }
+
+ await modalSubmit.editReply({
+ content: `${emojis.rightArrow1} Your report was sent to the bot moderators.`,
+ });
+ }
+
+ private async sendReportToModerator(
+ interaction: ButtonInteraction,
+ moderatorId: string,
+ reportEmbed: EmbedBuilder,
+ deleteButton: ButtonBuilder,
+ ) {
+ const user = await interaction.client.users.fetch(moderatorId);
+ const row = new ActionRowBuilder().addComponents(deleteButton);
+ await user.send({ embeds: [reportEmbed], components: [row] });
+ }
+
+ private async handleDeleteConfession(interaction: ButtonInteraction, parsed: ParsedConfessionButton) {
+ if (interaction.inGuild() || !parsed.messageId) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This action can only be used from a moderator DM.`,
+ });
+ return;
+ }
+
+ const context =
+ parsed.guildId && parsed.channelId && parsed.messageId
+ ? { guildId: parsed.guildId, channelId: parsed.channelId, messageId: parsed.messageId, threadId: '' }
+ : await getConfessionContext(parsed.messageId);
+
+ if (!context) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This confession is no longer available.`,
+ });
+ return;
+ }
+
+ const moderatorIds = getModeratorIds();
+
+ if (!moderatorIds.includes(interaction.user.id)) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} You are not configured as a bot moderator.`,
+ });
+ return;
+ }
+
+ const channel = await fetchConfessionChannel(interaction, context.channelId, context.guildId);
+
+ if (!channel) {
+ console.error('Confession channel fetch failed (delete flow)', {
+ channelId: context.channelId,
+ guildId: context.guildId,
+ context,
+ });
+
+ await removeConfessionContext(context.messageId);
+
+ await interaction.reply({
+ content: `${emojis.rightArrow2} The confession channel (<#${context.channelId}>) is no longer available, but the confession has been removed from records.`,
+ });
+ return;
+ }
+
+ const message = await channel.messages.fetch(context.messageId).catch(() => null);
+
+ if (!message) {
+ await removeConfessionContext(context.messageId);
+
+ await interaction.reply({
+ content: `${emojis.rightArrow2} That confession no longer exists, but the record has been cleaned up.`,
+ });
+ return;
+ }
+
+ const deletedEmbed = new EmbedBuilder()
+ .setTitle('Confession')
+ .setDescription('This confession was deleted by global moderators.')
+ .setColor(0xed4245)
+ .setTimestamp();
+
+ try {
+ await message.edit({ embeds: [deletedEmbed], components: [] });
+ } catch {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} I could not update the confession message.`,
+ });
+ return;
+ }
+
+ try {
+ if (context.threadId) {
+ const thread = await interaction.client.channels.fetch(context.threadId).catch(() => null);
+ if (thread && typeof (thread as any).setName === 'function') {
+ await (thread as any).setName('confession-deleted').catch(() => null);
+ }
+ }
+ } catch (error) {
+ console.error('Failed to rename confession thread', { threadId: context.threadId, error });
+ }
+
+ await removeConfessionContext(context.messageId);
+
+ await interaction.reply({
+ content: `${emojis.rightArrow1} Confession marked as deleted.`,
+ });
+ }
+}
diff --git a/apps/bot/src/interaction-handlers/ticket/createTicketHandler.ts b/apps/bot/src/interaction-handlers/ticket/createTicketHandler.ts
index 08fbcb3..c5a8c27 100644
--- a/apps/bot/src/interaction-handlers/ticket/createTicketHandler.ts
+++ b/apps/bot/src/interaction-handlers/ticket/createTicketHandler.ts
@@ -1,13 +1,13 @@
import { InteractionHandler, InteractionHandlerTypes } from '@sapphire/framework';
import {
- ActionRowBuilder,
- ButtonBuilder,
- ButtonStyle,
- ChannelType,
- LabelBuilder,
- MessageFlags,
- ModalBuilder,
- PermissionFlagsBits
+ ActionRowBuilder,
+ ButtonBuilder,
+ ButtonStyle,
+ ChannelType,
+ LabelBuilder,
+ MessageFlags,
+ ModalBuilder,
+ PermissionFlagsBits,
} from 'discord.js';
import { TextInputBuilder, TextInputStyle, type ButtonInteraction } from 'discord.js';
import { getSettings, updateSettings } from '#lib/settings.js';
@@ -15,150 +15,147 @@ import { createTicket, removeTicket, setTicketChannelId } from '#lib/tickets.js'
import { emojis } from '#utils/emoji.js';
export class ButtonHandler extends InteractionHandler {
- public constructor(ctx: InteractionHandler.LoaderContext, options: InteractionHandler.Options) {
- super(ctx, {
- ...options,
- interactionHandlerType: InteractionHandlerTypes.Button
- });
- }
-
- public override parse(interaction: ButtonInteraction) {
- if (interaction.customId !== 'create-ticket') return this.none();
-
- return this.some();
- }
-
- public async run(interaction: ButtonInteraction) {
- if (!interaction.inGuild()) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This button can only be used in a server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (!interaction.guild) {
- await interaction.reply({
- content: `${emojis.rightArrow2} Failed to create ticket.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- const reasonInput = new TextInputBuilder()
- .setCustomId('ticket-reason')
- .setStyle(TextInputStyle.Paragraph)
- .setRequired(true)
- .setMaxLength(1_000);
-
- const reasonLabel = new LabelBuilder()
- .setLabel('Reason')
- .setTextInputComponent(reasonInput);
-
- const modal = new ModalBuilder()
- .setCustomId('create-ticket-modal')
- .setTitle('Create Ticket')
- .addLabelComponents(reasonLabel);
-
- await interaction.showModal(modal);
-
- const modalSubmit = await interaction.awaitModalSubmit({
- filter: (modalInteraction) =>
- modalInteraction.customId === 'create-ticket-modal' &&
- modalInteraction.user.id === interaction.user.id,
- time: 60_000
- });
-
- const reason = modalSubmit.fields.getTextInputValue('ticket-reason');
- const settings = await getSettings(interaction.guild.id, interaction.guild.name);
- let parent: string | undefined;
-
- if (settings.ticketCategoryId) {
- const ticketCategory =
- interaction.guild.channels.cache.get(settings.ticketCategoryId) ??
- (await interaction.guild.channels.fetch(settings.ticketCategoryId).catch(() => null));
-
- if (ticketCategory?.type === ChannelType.GuildCategory) {
- parent = ticketCategory.id;
- } else {
- await updateSettings(interaction.guild.id, interaction.guild.name, { ticketCategoryId: null });
- }
- }
-
- const ticket = await createTicket(interaction.guild.id, interaction.guild.name, interaction.user.id, reason);
-
- const permissionOverwrites = [
- {
- id: interaction.guild.id,
- deny: [PermissionFlagsBits.ViewChannel]
- },
- {
- id: interaction.user.id,
- allow: [
- PermissionFlagsBits.ViewChannel,
- PermissionFlagsBits.SendMessages,
- PermissionFlagsBits.ReadMessageHistory
- ]
- },
- {
- id: interaction.client.user.id,
- allow: [
- PermissionFlagsBits.ViewChannel,
- PermissionFlagsBits.SendMessages,
- PermissionFlagsBits.ReadMessageHistory,
- PermissionFlagsBits.ManageChannels
- ]
- }
- ] as any[];
-
- const staffRoleId = settings.staffRole;
- const staffRoleExists = typeof staffRoleId === 'string' && interaction.guild.roles.cache.has(staffRoleId);
-
- if (staffRoleExists) {
- permissionOverwrites.push({
- id: staffRoleId,
- allow: [
- PermissionFlagsBits.ViewChannel,
- PermissionFlagsBits.SendMessages,
- PermissionFlagsBits.ReadMessageHistory
- ]
- });
- }
-
- const channel = await interaction.guild.channels
- .create({
- name: `${ticket.ticketNumber}-${interaction.user.username}`,
- type: ChannelType.GuildText,
- parent,
- permissionOverwrites
- })
- .catch(async (error) => {
- await removeTicket(ticket.id).catch(() => null);
- throw error;
- });
-
- await setTicketChannelId(ticket.id, channel.id);
-
- await modalSubmit.reply({
- content: `${emojis.rightArrow2} Created ticket <#${channel.id}>!`,
- flags: MessageFlags.Ephemeral
- });
-
- const closeButton = new ButtonBuilder()
- .setCustomId('remove-ticket')
- .setLabel('Close Ticket')
- .setStyle(ButtonStyle.Danger);
-
- const closeRow = new ActionRowBuilder().addComponents(closeButton);
-
- const staffMention = staffRoleExists ? `<@&${staffRoleId}> ` : '';
-
- await channel.send({
- content: `${staffMention}<@${interaction.user.id}>, your ticket has been created!\n**Reason:** ${reason}`,
- components: [closeRow],
- allowedMentions: {
- users: [interaction.user.id]
- },
- });
- }
+ public constructor(ctx: InteractionHandler.LoaderContext, options: InteractionHandler.Options) {
+ super(ctx, {
+ ...options,
+ interactionHandlerType: InteractionHandlerTypes.Button,
+ });
+ }
+
+ public override parse(interaction: ButtonInteraction) {
+ if (interaction.customId !== 'create-ticket') return this.none();
+
+ return this.some();
+ }
+
+ public async run(interaction: ButtonInteraction) {
+ if (!interaction.inGuild()) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This button can only be used in a server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (!interaction.guild) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Failed to create ticket.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ const reasonInput = new TextInputBuilder()
+ .setCustomId('ticket-reason')
+ .setStyle(TextInputStyle.Paragraph)
+ .setRequired(true)
+ .setMaxLength(1_000);
+
+ const reasonLabel = new LabelBuilder().setLabel('Reason').setTextInputComponent(reasonInput);
+
+ const modal = new ModalBuilder()
+ .setCustomId('create-ticket-modal')
+ .setTitle('Create Ticket')
+ .addLabelComponents(reasonLabel);
+
+ await interaction.showModal(modal);
+
+ const modalSubmit = await interaction.awaitModalSubmit({
+ filter: (modalInteraction) =>
+ modalInteraction.customId === 'create-ticket-modal' && modalInteraction.user.id === interaction.user.id,
+ time: 60_000,
+ });
+
+ const reason = modalSubmit.fields.getTextInputValue('ticket-reason');
+ const settings = await getSettings(interaction.guild.id, interaction.guild.name);
+ let parent: string | undefined;
+
+ if (settings.ticketCategoryId) {
+ const ticketCategory =
+ interaction.guild.channels.cache.get(settings.ticketCategoryId) ??
+ (await interaction.guild.channels.fetch(settings.ticketCategoryId).catch(() => null));
+
+ if (ticketCategory?.type === ChannelType.GuildCategory) {
+ parent = ticketCategory.id;
+ } else {
+ await updateSettings(interaction.guild.id, interaction.guild.name, { ticketCategoryId: null });
+ }
+ }
+
+ const ticket = await createTicket(interaction.guild.id, interaction.guild.name, interaction.user.id, reason);
+
+ const permissionOverwrites = [
+ {
+ id: interaction.guild.id,
+ deny: [PermissionFlagsBits.ViewChannel],
+ },
+ {
+ id: interaction.user.id,
+ allow: [
+ PermissionFlagsBits.ViewChannel,
+ PermissionFlagsBits.SendMessages,
+ PermissionFlagsBits.ReadMessageHistory,
+ ],
+ },
+ {
+ id: interaction.client.user.id,
+ allow: [
+ PermissionFlagsBits.ViewChannel,
+ PermissionFlagsBits.SendMessages,
+ PermissionFlagsBits.ReadMessageHistory,
+ PermissionFlagsBits.ManageChannels,
+ ],
+ },
+ ] as any[];
+
+ const staffRoleId = settings.staffRole;
+ const staffRoleExists = typeof staffRoleId === 'string' && interaction.guild.roles.cache.has(staffRoleId);
+
+ if (staffRoleExists) {
+ permissionOverwrites.push({
+ id: staffRoleId,
+ allow: [
+ PermissionFlagsBits.ViewChannel,
+ PermissionFlagsBits.SendMessages,
+ PermissionFlagsBits.ReadMessageHistory,
+ ],
+ });
+ }
+
+ const channel = await interaction.guild.channels
+ .create({
+ name: `${ticket.ticketNumber}-${interaction.user.username}`,
+ type: ChannelType.GuildText,
+ parent,
+ permissionOverwrites,
+ })
+ .catch(async (error) => {
+ await removeTicket(ticket.id).catch(() => null);
+ throw error;
+ });
+
+ await setTicketChannelId(ticket.id, channel.id);
+
+ await modalSubmit.reply({
+ content: `${emojis.rightArrow2} Created ticket <#${channel.id}>!`,
+ flags: MessageFlags.Ephemeral,
+ });
+
+ const closeButton = new ButtonBuilder()
+ .setCustomId('remove-ticket')
+ .setLabel('Close Ticket')
+ .setStyle(ButtonStyle.Danger);
+
+ const closeRow = new ActionRowBuilder().addComponents(closeButton);
+
+ const staffMention = staffRoleExists ? `<@&${staffRoleId}> ` : '';
+
+ await channel.send({
+ content: `${staffMention}<@${interaction.user.id}>, your ticket has been created!\n**Reason:** ${reason}`,
+ components: [closeRow],
+ allowedMentions: {
+ users: [interaction.user.id],
+ },
+ });
+ }
}
diff --git a/apps/bot/src/interaction-handlers/ticket/removeTicketHandler.ts b/apps/bot/src/interaction-handlers/ticket/removeTicketHandler.ts
index 3cbd53f..150e5f2 100644
--- a/apps/bot/src/interaction-handlers/ticket/removeTicketHandler.ts
+++ b/apps/bot/src/interaction-handlers/ticket/removeTicketHandler.ts
@@ -6,155 +6,159 @@ import { getTicketId, removeTicket } from '#lib/tickets.js';
import { getSettings } from '#lib/settings.js';
async function generateTranscript(channel: TextChannel, ticket: any): Promise {
- const messages = new Map();
- let lastId: string | undefined;
-
- while (true) {
- const fetched = await channel.messages.fetch({ limit: 100, before: lastId });
- if (fetched.size === 0) break;
- fetched.forEach(msg => messages.set(msg.id, msg));
- lastId = fetched.last()?.id;
- }
-
- const sortedMessages = Array.from(messages.values()).reverse();
-
- let transcript = `Ticket <${ticket.ticketNumber}>-<@${ticket.userId}> Transcript\n`;
- transcript += `Created: ${ticket.createdAt.toLocaleString()}\n`;
- transcript += `User: <@${ticket.userId}>\n`;
- if (ticket.reason) {
- transcript += `Reason: ${ticket.reason}\n`;
- }
- transcript += `${'='.repeat(50)}\n\n`;
-
- for (const message of sortedMessages) {
- const timestamp = message.createdAt.toLocaleString();
- const author = message.author.tag;
- const content = message.content || '[No text content]';
-
- transcript += `[${timestamp}] ${author}: ${content}\n`;
-
- if (message.attachments.size > 0) {
- transcript += ` Attachments: ${Array.from(message.attachments.values()).map((a: any) => a.url).join(', ')}\n`;
- }
- }
-
- return transcript;
+ const messages = new Map();
+ let lastId: string | undefined;
+
+ while (true) {
+ const fetched = await channel.messages.fetch({ limit: 100, before: lastId });
+ if (fetched.size === 0) break;
+ fetched.forEach((msg) => messages.set(msg.id, msg));
+ lastId = fetched.last()?.id;
+ }
+
+ const sortedMessages = Array.from(messages.values()).reverse();
+
+ let transcript = `Ticket <${ticket.ticketNumber}>-<@${ticket.userId}> Transcript\n`;
+ transcript += `Created: ${ticket.createdAt.toLocaleString()}\n`;
+ transcript += `User: <@${ticket.userId}>\n`;
+ if (ticket.reason) {
+ transcript += `Reason: ${ticket.reason}\n`;
+ }
+ transcript += `${'='.repeat(50)}\n\n`;
+
+ for (const message of sortedMessages) {
+ const timestamp = message.createdAt.toLocaleString();
+ const author = message.author.tag;
+ const content = message.content || '[No text content]';
+
+ transcript += `[${timestamp}] ${author}: ${content}\n`;
+
+ if (message.attachments.size > 0) {
+ transcript += ` Attachments: ${Array.from(message.attachments.values())
+ .map((a: any) => a.url)
+ .join(', ')}\n`;
+ }
+ }
+
+ return transcript;
}
export class ButtonHandler extends InteractionHandler {
- public constructor(ctx: InteractionHandler.LoaderContext, options: InteractionHandler.Options) {
- super(ctx, {
- ...options,
- interactionHandlerType: InteractionHandlerTypes.Button
- });
- }
-
- public override parse(interaction: ButtonInteraction) {
- if (
- interaction.customId !== 'remove-ticket' &&
- interaction.customId !== 'confirm-remove-ticket' &&
- interaction.customId !== 'cancel-remove-ticket'
- ) {
- return this.none();
- }
-
- return this.some();
- }
-
- public async run(interaction: ButtonInteraction) {
- if (!interaction.inGuild()) {
- await interaction.reply({
- content: `${emojis.rightArrow2} This button can only be used in a server.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (!interaction.guild) {
- await interaction.reply({
- content: `${emojis.rightArrow2} Failed to remove ticket.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (interaction.customId === 'cancel-remove-ticket') {
- await interaction.update({
- content: `${emojis.rightArrow2} Ticket closure cancelled.`,
- components: []
- });
- return;
- }
-
- const channel = interaction.channel;
-
- if (!channel || !('deletable' in channel) || !channel.deletable) {
- await interaction.reply({
- content: `${emojis.rightArrow2} I cannot delete this channel.`,
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- if (interaction.customId === 'remove-ticket') {
- const confirmButton = new ButtonBuilder()
- .setCustomId('confirm-remove-ticket')
- .setLabel('Confirm Close')
- .setStyle(ButtonStyle.Danger);
-
- const cancelButton = new ButtonBuilder()
- .setCustomId('cancel-remove-ticket')
- .setLabel('Cancel')
- .setStyle(ButtonStyle.Secondary);
-
- const row = new ActionRowBuilder().addComponents(confirmButton, cancelButton);
-
- await interaction.reply({
- content: `${emojis.rightArrow2} Are you sure you want to close this ticket?`,
- components: [row],
- flags: MessageFlags.Ephemeral
- });
- return;
- }
-
- await interaction.update({
- content: `${emojis.rightArrow2} Closing ticket...`,
- components: []
- });
-
- const ticket = await getTicketId(interaction.guild.id, channel.id);
-
- try {
- if (ticket && channel.isTextBased()) {
- const settings = await getSettings(interaction.guild.id, interaction.guild.name);
-
- // Send transcript if configured
- if (settings.ticketTranscriptChannelId) {
- const transcriptChannel = await interaction.guild.channels.fetch(settings.ticketTranscriptChannelId).catch(() => null);
-
- if (transcriptChannel && transcriptChannel.type === ChannelType.GuildText) {
- try {
- const transcript = await generateTranscript(channel as TextChannel, ticket);
- const attachment = new AttachmentBuilder(Buffer.from(transcript), {
- name: `ticket-${ticket.ticketNumber}-transcript.txt`
- });
-
- await (transcriptChannel as TextChannel).send({
- content: `📋 **Ticket #${ticket.ticketNumber}** transcript - Closed by ${interaction.user.tag}`,
- files: [attachment]
- });
- } catch (transcriptErr) {
- console.error('Failed to send ticket transcript:', transcriptErr);
- }
- }
- }
-
- await removeTicket(ticket.id);
- }
-
- await channel.delete(`Ticket closed by ${interaction.user.tag}.`);
- } catch (err) {
- console.log(err);
- }
- }
+ public constructor(ctx: InteractionHandler.LoaderContext, options: InteractionHandler.Options) {
+ super(ctx, {
+ ...options,
+ interactionHandlerType: InteractionHandlerTypes.Button,
+ });
+ }
+
+ public override parse(interaction: ButtonInteraction) {
+ if (
+ interaction.customId !== 'remove-ticket' &&
+ interaction.customId !== 'confirm-remove-ticket' &&
+ interaction.customId !== 'cancel-remove-ticket'
+ ) {
+ return this.none();
+ }
+
+ return this.some();
+ }
+
+ public async run(interaction: ButtonInteraction) {
+ if (!interaction.inGuild()) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} This button can only be used in a server.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (!interaction.guild) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Failed to remove ticket.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (interaction.customId === 'cancel-remove-ticket') {
+ await interaction.update({
+ content: `${emojis.rightArrow2} Ticket closure cancelled.`,
+ components: [],
+ });
+ return;
+ }
+
+ const channel = interaction.channel;
+
+ if (!channel || !('deletable' in channel) || !channel.deletable) {
+ await interaction.reply({
+ content: `${emojis.rightArrow2} I cannot delete this channel.`,
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ if (interaction.customId === 'remove-ticket') {
+ const confirmButton = new ButtonBuilder()
+ .setCustomId('confirm-remove-ticket')
+ .setLabel('Confirm Close')
+ .setStyle(ButtonStyle.Danger);
+
+ const cancelButton = new ButtonBuilder()
+ .setCustomId('cancel-remove-ticket')
+ .setLabel('Cancel')
+ .setStyle(ButtonStyle.Secondary);
+
+ const row = new ActionRowBuilder().addComponents(confirmButton, cancelButton);
+
+ await interaction.reply({
+ content: `${emojis.rightArrow2} Are you sure you want to close this ticket?`,
+ components: [row],
+ flags: MessageFlags.Ephemeral,
+ });
+ return;
+ }
+
+ await interaction.update({
+ content: `${emojis.rightArrow2} Closing ticket...`,
+ components: [],
+ });
+
+ const ticket = await getTicketId(interaction.guild.id, channel.id);
+
+ try {
+ if (ticket && channel.isTextBased()) {
+ const settings = await getSettings(interaction.guild.id, interaction.guild.name);
+
+ // Send transcript if configured
+ if (settings.ticketTranscriptChannelId) {
+ const transcriptChannel = await interaction.guild.channels
+ .fetch(settings.ticketTranscriptChannelId)
+ .catch(() => null);
+
+ if (transcriptChannel && transcriptChannel.type === ChannelType.GuildText) {
+ try {
+ const transcript = await generateTranscript(channel as TextChannel, ticket);
+ const attachment = new AttachmentBuilder(Buffer.from(transcript), {
+ name: `ticket-${ticket.ticketNumber}-transcript.txt`,
+ });
+
+ await (transcriptChannel as TextChannel).send({
+ content: `📋 **Ticket #${ticket.ticketNumber}** transcript - Closed by ${interaction.user.tag}`,
+ files: [attachment],
+ });
+ } catch (transcriptErr) {
+ console.error('Failed to send ticket transcript:', transcriptErr);
+ }
+ }
+ }
+
+ await removeTicket(ticket.id);
+ }
+
+ await channel.delete(`Ticket closed by ${interaction.user.tag}.`);
+ } catch (err) {
+ console.log(err);
+ }
+ }
}
diff --git a/apps/bot/src/lib/automod.ts b/apps/bot/src/lib/automod.ts
index 9eafb24..9b44058 100644
--- a/apps/bot/src/lib/automod.ts
+++ b/apps/bot/src/lib/automod.ts
@@ -3,76 +3,80 @@ import { hasQuestUnlimitedAccess, LIMITS_ENABLED, LimitError } from './limits.js
import type { EntitlementManager } from 'discord.js';
export class DuplicateAutoModError extends Error {
- public constructor() {
- super('That word is already blocked in this server.');
- this.name = 'DuplicateAutoModError';
- }
+ public constructor() {
+ super('That word is already blocked in this server.');
+ this.name = 'DuplicateAutoModError';
+ }
}
export async function createAutoMod(
- guildId: string,
- guildName: string,
- word: string,
- entitlements?: EntitlementManager
+ guildId: string,
+ guildName: string,
+ word: string,
+ entitlements?: EntitlementManager,
) {
- const hasUnlimitedAccess = entitlements ? await hasQuestUnlimitedAccess(entitlements, guildId) : false;
+ if (!word || !word.trim()) {
+ throw new Error('Automod word cannot be empty.');
+ }
- if (LIMITS_ENABLED && !hasUnlimitedAccess) {
- const autoModCount = await prisma.autoMod.count({ where: { guildId } });
+ const hasUnlimitedAccess = entitlements ? await hasQuestUnlimitedAccess(entitlements, guildId) : false;
- if (autoModCount >= 10) {
- throw new LimitError('A guild can only have up to 10 automod rules.', true);
- }
- }
+ if (LIMITS_ENABLED && !hasUnlimitedAccess) {
+ const autoModCount = await prisma.autoMod.count({ where: { guildId } });
- if (guildId && guildName) {
- await prisma.server.upsert({
- where: { id: guildId },
- create: { id: guildId, name: guildName },
- update: { name: guildName }
- });
+ if (autoModCount >= 10) {
+ throw new LimitError('A guild can only have up to 10 automod rules.', true);
+ }
+ }
- try {
- return await prisma.autoMod.create({
- data: { guildId, word }
- });
- } catch (error) {
- if ((error as { code?: string }).code === 'P2002') {
- throw new DuplicateAutoModError();
- }
+ if (guildId && guildName) {
+ await prisma.server.upsert({
+ where: { id: guildId },
+ create: { id: guildId, name: guildName },
+ update: { name: guildName },
+ });
- throw error;
- }
- }
+ try {
+ return await prisma.autoMod.create({
+ data: { guildId, word },
+ });
+ } catch (error) {
+ if ((error as { code?: string }).code === 'P2002') {
+ throw new DuplicateAutoModError();
+ }
- try {
- return await prisma.autoMod.create({
- data: { guildId, word }
- });
- } catch (error) {
- if ((error as { code?: string }).code === 'P2002') {
- throw new DuplicateAutoModError();
- }
+ throw error;
+ }
+ }
- throw error;
- }
+ try {
+ return await prisma.autoMod.create({
+ data: { guildId, word },
+ });
+ } catch (error) {
+ if ((error as { code?: string }).code === 'P2002') {
+ throw new DuplicateAutoModError();
+ }
+
+ throw error;
+ }
}
export async function getAutoMods(guildId: string) {
- return prisma.autoMod.findMany({
- where: { guildId },
- orderBy: { createdAt: 'asc' }
- });
+ return prisma.autoMod.findMany({
+ where: { guildId },
+ orderBy: { createdAt: 'asc' },
+ });
}
export async function removeAutoMod(autoModId: string) {
- return prisma.autoMod.delete({ where: { id: autoModId } });
+ return prisma.autoMod.delete({ where: { id: autoModId } });
}
export async function clearAutoMods(guildId: string) {
- return prisma.autoMod.deleteMany({ where: { guildId } });
+ return prisma.autoMod.deleteMany({ where: { guildId } });
}
export async function getAutoMod(autoModId: string) {
- return prisma.autoMod.findUnique({ where: { id: autoModId } });
-}
\ No newline at end of file
+ return prisma.autoMod.findUnique({ where: { id: autoModId } });
+}
diff --git a/apps/bot/src/lib/autorole.ts b/apps/bot/src/lib/autorole.ts
index afd4daf..f189726 100644
--- a/apps/bot/src/lib/autorole.ts
+++ b/apps/bot/src/lib/autorole.ts
@@ -3,63 +3,63 @@ import { hasQuestUnlimitedAccess, LIMITS_ENABLED, LimitError } from './limits.js
import type { EntitlementManager } from 'discord.js';
export async function createAutoRole(
- guildId: string,
- guildName: string,
- roleId: string,
- botRole?: boolean,
- entitlements?: EntitlementManager
+ guildId: string,
+ guildName: string,
+ roleId: string,
+ botRole?: boolean,
+ entitlements?: EntitlementManager,
) {
- const hasUnlimitedAccess = entitlements ? await hasQuestUnlimitedAccess(entitlements, guildId) : false;
+ const hasUnlimitedAccess = entitlements ? await hasQuestUnlimitedAccess(entitlements, guildId) : false;
- if (LIMITS_ENABLED && !hasUnlimitedAccess) {
- const autoRoleCount = await prisma.autoRole.count({ where: { guildId } });
+ if (LIMITS_ENABLED && !hasUnlimitedAccess) {
+ const autoRoleCount = await prisma.autoRole.count({ where: { guildId } });
- if (autoRoleCount >= 5) {
- throw new LimitError('A guild can only have up to 5 auto roles.', true);
- }
- }
+ if (autoRoleCount >= 5) {
+ throw new LimitError('A guild can only have up to 5 auto roles.', true);
+ }
+ }
- if (guildId && guildName) {
- await prisma.server.upsert({
- where: { id: guildId },
- create: { id: guildId, name: guildName },
- update: { name: guildName }
- });
- }
+ if (guildId && guildName) {
+ await prisma.server.upsert({
+ where: { id: guildId },
+ create: { id: guildId, name: guildName },
+ update: { name: guildName },
+ });
+ }
- return prisma.autoRole.upsert({
- where: {
- guildId_roleId: {
- guildId,
- roleId
- }
- },
- create: {
- guildId,
- roleId,
- botRole
- },
- update: {
- botRole
- }
- });
+ return prisma.autoRole.upsert({
+ where: {
+ guildId_roleId: {
+ guildId,
+ roleId,
+ },
+ },
+ create: {
+ guildId,
+ roleId,
+ botRole,
+ },
+ update: {
+ botRole,
+ },
+ });
}
export async function getAutoRoles(guildId: string) {
- return prisma.autoRole.findMany({
- where: { guildId },
- orderBy: { createdAt: 'asc' }
- });
+ return prisma.autoRole.findMany({
+ where: { guildId },
+ orderBy: { createdAt: 'asc' },
+ });
}
export async function removeAutoRole(autoRoleId: string) {
- return prisma.autoRole.delete({ where: { id: autoRoleId } });
+ return prisma.autoRole.delete({ where: { id: autoRoleId } });
}
export async function clearAutoRoles(guildId: string) {
- return prisma.autoRole.deleteMany({ where: { guildId } });
+ return prisma.autoRole.deleteMany({ where: { guildId } });
}
export async function getAutoRole(autoRoleId: string) {
- return prisma.autoRole.findUnique({ where: { id: autoRoleId } });
-}
\ No newline at end of file
+ return prisma.autoRole.findUnique({ where: { id: autoRoleId } });
+}
diff --git a/apps/bot/src/lib/bans.ts b/apps/bot/src/lib/bans.ts
index 37d95aa..f2520d6 100644
--- a/apps/bot/src/lib/bans.ts
+++ b/apps/bot/src/lib/bans.ts
@@ -1,85 +1,82 @@
-import { prisma } from "./prisma.js";
+import { prisma } from './prisma.js';
import { Guild, PermissionFlagsBits, Client } from 'discord.js';
export async function createBan(
- guildId: string,
- guildName: string,
- userId: string,
- expiresAt: Date | null,
- reason?: string,
+ guildId: string,
+ guildName: string,
+ userId: string,
+ expiresAt: Date | null,
+ reason?: string,
) {
- await prisma.server.upsert({
- where: { id: guildId },
- create: { id: guildId, name: guildName },
- update: { name: guildName },
- });
- return prisma.ban.upsert({
- where: { guildId_userId: { guildId, userId } },
- create: { guildId, userId, expiresAt, reason },
- update: { expiresAt, reason },
- });
+ await prisma.server.upsert({
+ where: { id: guildId },
+ create: { id: guildId, name: guildName },
+ update: { name: guildName },
+ });
+ return prisma.ban.upsert({
+ where: { guildId_userId: { guildId, userId } },
+ create: { guildId, userId, expiresAt, reason },
+ update: { expiresAt, reason },
+ });
}
export async function clearBans(guildId: string, userId: string) {
- return prisma.ban.deleteMany({
- where: { guildId, userId },
- });
+ return prisma.ban.deleteMany({
+ where: { guildId, userId },
+ });
}
export async function getBan(guildId: string, userId: string) {
- return prisma.ban.findUnique({
- where: { guildId_userId: { guildId, userId } },
- });
+ return prisma.ban.findUnique({
+ where: { guildId_userId: { guildId, userId } },
+ });
}
export async function getBans() {
- return prisma.ban.findMany({
- where: {
- OR: [
- { expiresAt: null },
- { expiresAt: { gt: new Date() } },
- ],
- },
- });
+ return prisma.ban.findMany({
+ where: {
+ OR: [{ expiresAt: null }, { expiresAt: { gt: new Date() } }],
+ },
+ });
}
export async function applyBan(guild: Guild, userId: string, reason?: string): Promise {
- const me = guild.members.me;
- if (!me?.permissions.has(PermissionFlagsBits.BanMembers)) return false;
+ const me = guild.members.me;
+ if (!me?.permissions.has(PermissionFlagsBits.BanMembers)) return false;
- try {
- await guild.bans.create(userId, { reason: reason ?? undefined });
- return true;
- } catch {
- return false;
- }
+ try {
+ await guild.bans.create(userId, { reason: reason ?? undefined });
+ return true;
+ } catch {
+ return false;
+ }
}
export async function removeBan(guild: Guild, userId: string): Promise {
- const me = guild.members.me;
- if (!me?.permissions.has(PermissionFlagsBits.BanMembers)) return false;
+ const me = guild.members.me;
+ if (!me?.permissions.has(PermissionFlagsBits.BanMembers)) return false;
- try {
- await guild.bans.remove(userId);
- } catch {}
-
- await clearBans(guild.id, userId);
- return true;
+ try {
+ await guild.bans.remove(userId);
+ } catch {}
+
+ await clearBans(guild.id, userId);
+ return true;
}
export async function purgeExpiredBans(client: Client) {
- const expired = await prisma.ban.findMany({
- where: {
- expiresAt: { not: null, lte: new Date() },
- },
- });
+ const expired = await prisma.ban.findMany({
+ where: {
+ expiresAt: { not: null, lte: new Date() },
+ },
+ });
- for (const ban of expired) {
- const guild = client.guilds.cache.get(ban.guildId);
- if (guild) {
- await removeBan(guild, ban.userId);
- } else {
- await prisma.ban.delete({ where: { id: ban.id } }).catch(() => {});
- }
- }
+ for (const ban of expired) {
+ const guild = client.guilds.cache.get(ban.guildId);
+ if (guild) {
+ await removeBan(guild, ban.userId);
+ } else {
+ await prisma.ban.delete({ where: { id: ban.id } }).catch(() => {});
+ }
+ }
}
diff --git a/apps/bot/src/lib/confessions.ts b/apps/bot/src/lib/confessions.ts
index 5bc67f2..66d3091 100644
--- a/apps/bot/src/lib/confessions.ts
+++ b/apps/bot/src/lib/confessions.ts
@@ -1,78 +1,85 @@
-import { prisma } from "./prisma.js";
+import { prisma } from './prisma.js';
export type ConfessionContext = {
- guildId: string;
- channelId: string;
- messageId: string;
- threadId: string;
- creatorId?: string;
+ guildId: string;
+ channelId: string;
+ messageId: string;
+ threadId: string;
+ creatorId?: string;
};
export function getModeratorIds() {
- return [...new Set((process.env.MODERATORS ?? '').split(',').map((id) => id.trim()).filter(Boolean))];
+ return [
+ ...new Set(
+ (process.env.MODERATORS ?? '')
+ .split(',')
+ .map((id) => id.trim())
+ .filter(Boolean),
+ ),
+ ];
}
export function buildConfessionLink(guildId: string, channelId: string, messageId: string) {
- return `https://discord.com/channels/${guildId}/${channelId}/${messageId}`;
+ return `https://discord.com/channels/${guildId}/${channelId}/${messageId}`;
}
export async function storeConfessionContext(context: ConfessionContext) {
- await prisma.confession.upsert({
- where: { messageId: context.messageId },
- create: context,
- update: context,
- });
+ await prisma.confession.upsert({
+ where: { messageId: context.messageId },
+ create: context,
+ update: context,
+ });
}
export async function getConfessionContext(messageId: string) {
- return prisma.confession.findUnique({
- where: { messageId },
- select: {
- guildId: true,
- channelId: true,
- messageId: true,
- threadId: true,
- creatorId: true,
- },
- });
+ return prisma.confession.findUnique({
+ where: { messageId },
+ select: {
+ guildId: true,
+ channelId: true,
+ messageId: true,
+ threadId: true,
+ creatorId: true,
+ },
+ });
}
export async function removeConfessionContext(messageId: string) {
- await prisma.confession.deleteMany({
- where: { messageId },
- });
+ await prisma.confession.deleteMany({
+ where: { messageId },
+ });
}
export async function removeConfessionContexts(messageIds: string[]) {
- if (messageIds.length === 0) return;
+ if (messageIds.length === 0) return;
- await prisma.confession.deleteMany({
- where: {
- messageId: {
- in: messageIds,
- },
- },
- });
+ await prisma.confession.deleteMany({
+ where: {
+ messageId: {
+ in: messageIds,
+ },
+ },
+ });
}
export async function removeConfessionContextsByChannel(channelId: string) {
- await prisma.confession.deleteMany({
- where: { channelId },
- });
+ await prisma.confession.deleteMany({
+ where: { channelId },
+ });
}
export async function isConfessionBlacklisted(userId: string) {
- return prisma.confessionBlacklist.findUnique({ where: { userId } });
+ return prisma.confessionBlacklist.findUnique({ where: { userId } });
}
export async function addConfessionBlacklist(userId: string, createdBy: string, reason?: string) {
- return prisma.confessionBlacklist.upsert({
- where: { userId },
- create: { userId, createdBy, reason },
- update: { createdBy, reason },
- });
+ return prisma.confessionBlacklist.upsert({
+ where: { userId },
+ create: { userId, createdBy, reason },
+ update: { createdBy, reason },
+ });
}
export async function removeConfessionBlacklist(userId: string) {
- return prisma.confessionBlacklist.deleteMany({ where: { userId } });
-}
\ No newline at end of file
+ return prisma.confessionBlacklist.deleteMany({ where: { userId } });
+}
diff --git a/apps/bot/src/lib/limits.ts b/apps/bot/src/lib/limits.ts
index a138c60..7c8024a 100644
--- a/apps/bot/src/lib/limits.ts
+++ b/apps/bot/src/lib/limits.ts
@@ -5,36 +5,39 @@ export const LIMITS_ENABLED = process.env.LIMITS === 'true';
export const QUEST_UNLIMITED_SKU_ID = '1502381886025240788';
export class LimitError extends Error {
- public constructor(message: string, public readonly showQuestUnlimitedPrompt = false) {
- super(message);
- this.name = 'LimitError';
- }
+ public constructor(
+ message: string,
+ public readonly showQuestUnlimitedPrompt = false,
+ ) {
+ super(message);
+ this.name = 'LimitError';
+ }
}
export async function hasQuestUnlimitedAccess(entitlements: EntitlementManager, guildId: string) {
- try {
- const guildEntitlements = await entitlements.fetch({
- guild: guildId,
- skus: [QUEST_UNLIMITED_SKU_ID],
- excludeEnded: true,
- excludeDeleted: true
- });
+ try {
+ const guildEntitlements = await entitlements.fetch({
+ guild: guildId,
+ skus: [QUEST_UNLIMITED_SKU_ID],
+ excludeEnded: true,
+ excludeDeleted: true,
+ });
- return guildEntitlements.size > 0;
- } catch {
- return false;
- }
+ return guildEntitlements.size > 0;
+ } catch {
+ return false;
+ }
}
export function getQuestUnlimitedUrl(applicationId: string) {
- return `https://discord.com/application-directory/${applicationId}/store/${QUEST_UNLIMITED_SKU_ID}`;
+ return `https://discord.com/application-directory/${applicationId}/store/${QUEST_UNLIMITED_SKU_ID}`;
}
export function getQuestUnlimitedPurchaseComponents(applicationId: string) {
- const purchaseButton = new ButtonBuilder()
- .setLabel('Upgrade to Quest Unlimited')
- .setStyle(ButtonStyle.Link)
- .setURL(getQuestUnlimitedUrl(applicationId));
+ const purchaseButton = new ButtonBuilder()
+ .setLabel('Upgrade to Quest Unlimited')
+ .setStyle(ButtonStyle.Link)
+ .setURL(getQuestUnlimitedUrl(applicationId));
- return [new ActionRowBuilder().addComponents(purchaseButton)];
-}
\ No newline at end of file
+ return [new ActionRowBuilder().addComponents(purchaseButton)];
+}
diff --git a/apps/bot/src/lib/logging.ts b/apps/bot/src/lib/logging.ts
index a940030..e9a068b 100644
--- a/apps/bot/src/lib/logging.ts
+++ b/apps/bot/src/lib/logging.ts
@@ -2,46 +2,45 @@ import { AuditLogEvent, EmbedBuilder, type Guild } from 'discord.js';
import { getSettings } from '#lib/settings.js';
export async function logEmbed(guild: Guild, embed: EmbedBuilder) {
- const settings = await getSettings(guild.id, guild.name).catch((err) => {
- console.error(err);
- return null;
- });
+ const settings = await getSettings(guild.id, guild.name).catch((err) => {
+ console.error(err);
+ return null;
+ });
- if (!settings || !settings.loggingEnabled || !settings.loggingChannelId) return;
+ if (!settings || !settings.loggingEnabled || !settings.loggingChannelId) return;
- const channel = await guild.channels.fetch(settings.loggingChannelId).catch(() => null);
- if (!channel?.isTextBased() || !channel.isSendable()) return;
+ const channel = await guild.channels.fetch(settings.loggingChannelId).catch(() => null);
+ if (!channel?.isTextBased() || !channel.isSendable()) return;
- await channel.send({ embeds: [embed] }).catch((err) => console.error(err));
+ await channel.send({ embeds: [embed] }).catch((err) => console.error(err));
}
export async function isLoggingChannel(guild: Guild, channelId: string | null | undefined) {
- if (!channelId) return false;
+ if (!channelId) return false;
- const settings = await getSettings(guild.id, guild.name).catch((err) => {
- console.error(err);
- return null;
- });
+ const settings = await getSettings(guild.id, guild.name).catch((err) => {
+ console.error(err);
+ return null;
+ });
- return settings?.loggingEnabled && settings.loggingChannelId === channelId;
+ return settings?.loggingEnabled && settings.loggingChannelId === channelId;
}
export async function getRecentAuditLogEntry(guild: Guild, type: AuditLogEvent, targetId: string) {
- const auditLogs = await guild.fetchAuditLogs({ type, limit: 5 }).catch((err) => {
- if (err?.code !== 10004) console.error(err);
- return null;
- });
-
- if (!auditLogs) return null;
-
- return (
- auditLogs.entries.find(
- (entry) => entry.targetId === targetId && Date.now() - entry.createdTimestamp < 5_000
- ) ?? null
- );
+ const auditLogs = await guild.fetchAuditLogs({ type, limit: 5 }).catch((err) => {
+ if (err?.code !== 10004) console.error(err);
+ return null;
+ });
+
+ if (!auditLogs) return null;
+
+ return (
+ auditLogs.entries.find((entry) => entry.targetId === targetId && Date.now() - entry.createdTimestamp < 5_000) ??
+ null
+ );
}
export function truncate(text: string | null | undefined, length = 1900) {
- if (!text) return '';
- return text.length > length ? `${text.slice(0, length)}…` : text;
+ if (!text) return '';
+ return text.length > length ? `${text.slice(0, length)}…` : text;
}
diff --git a/apps/bot/src/lib/mutes.ts b/apps/bot/src/lib/mutes.ts
index 7f6e49a..e10e9b5 100644
--- a/apps/bot/src/lib/mutes.ts
+++ b/apps/bot/src/lib/mutes.ts
@@ -1,64 +1,59 @@
-import { prisma } from "./prisma.js";
+import { prisma } from './prisma.js';
import { Guild } from 'discord.js';
export async function createMute(
- guildId: string,
- guildName: string,
- userId: string,
- expiresAt: Date | null,
- reason?: string,
+ guildId: string,
+ guildName: string,
+ userId: string,
+ expiresAt: Date | null,
+ reason?: string,
) {
- await prisma.server.upsert({
- where: { id: guildId },
- create: { id: guildId, name: guildName },
- update: { name: guildName },
- });
- return prisma.mute.upsert({
- where: { guildId_userId: { guildId, userId } },
- create: { guildId, userId, expiresAt, reason },
- update: { expiresAt, reason },
- });
+ await prisma.server.upsert({
+ where: { id: guildId },
+ create: { id: guildId, name: guildName },
+ update: { name: guildName },
+ });
+ return prisma.mute.upsert({
+ where: { guildId_userId: { guildId, userId } },
+ create: { guildId, userId, expiresAt, reason },
+ update: { expiresAt, reason },
+ });
}
export async function removeMute(guildId: string, userId: string) {
- return prisma.mute.deleteMany({
- where: { guildId, userId },
- });
+ return prisma.mute.deleteMany({
+ where: { guildId, userId },
+ });
}
export async function getMute(guildId: string, userId: string) {
- return prisma.mute.findUnique({
- where: { guildId_userId: { guildId, userId } },
- });
+ return prisma.mute.findUnique({
+ where: { guildId_userId: { guildId, userId } },
+ });
}
export async function getActiveMutes() {
- return prisma.mute.findMany({
- where: {
- OR: [
- { expiresAt: null },
- { expiresAt: { gt: new Date() } },
- ],
- },
- });
+ return prisma.mute.findMany({
+ where: {
+ OR: [{ expiresAt: null }, { expiresAt: { gt: new Date() } }],
+ },
+ });
}
export async function enforceMute(guild: Guild, userId: string): Promise {
- const mute = await getMute(guild.id, userId);
- if (!mute) return false;
-
- if (mute.expiresAt !== null && mute.expiresAt <= new Date()) {
- await removeMute(guild.id, userId);
- return false;
- }
-
- const member = await guild.members.fetch(userId).catch(() => null);
- if (!member || !member.moderatable) return false;
-
- const remaining = mute.expiresAt
- ? Math.min(mute.expiresAt.getTime() - Date.now(), 2419200000)
- : 2419200000;
+ const mute = await getMute(guild.id, userId);
+ if (!mute) return false;
- await member.timeout(remaining, mute.reason ?? '').catch(() => {});
- return true;
+ if (mute.expiresAt !== null && mute.expiresAt <= new Date()) {
+ await removeMute(guild.id, userId);
+ return false;
+ }
+
+ const member = await guild.members.fetch(userId).catch(() => null);
+ if (!member || !member.moderatable) return false;
+
+ const remaining = mute.expiresAt ? Math.min(mute.expiresAt.getTime() - Date.now(), 2419200000) : 2419200000;
+
+ await member.timeout(remaining, mute.reason ?? '').catch(() => {});
+ return true;
}
diff --git a/apps/bot/src/lib/prisma.ts b/apps/bot/src/lib/prisma.ts
index e913567..fe564d3 100644
--- a/apps/bot/src/lib/prisma.ts
+++ b/apps/bot/src/lib/prisma.ts
@@ -1,16 +1,16 @@
-import { PrismaClient } from "#prisma/client.js";
-import { PrismaPg } from "@prisma/adapter-pg";
+import { PrismaClient } from '#prisma/client.js';
+import { PrismaPg } from '@prisma/adapter-pg';
const globalForPrisma = globalThis as unknown as {
- prisma: PrismaClient | undefined;
+ prisma: PrismaClient | undefined;
};
function createPrismaClient() {
- const adapter = new PrismaPg({
- connectionString: process.env.DATABASE_URL,
- });
- return new PrismaClient({ adapter });
+ const adapter = new PrismaPg({
+ connectionString: process.env.DATABASE_URL,
+ });
+ return new PrismaClient({ adapter });
}
export const prisma = globalForPrisma.prisma ?? createPrismaClient();
-if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
+if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;
diff --git a/apps/bot/src/lib/reminderEvent.ts b/apps/bot/src/lib/reminderEvent.ts
index 7496c17..d07a6cf 100644
--- a/apps/bot/src/lib/reminderEvent.ts
+++ b/apps/bot/src/lib/reminderEvent.ts
@@ -3,56 +3,58 @@ import { emojis } from '#utils/emoji.js';
import { getDueReminders, removeReminder } from './reminders.js';
function ownerShardId(snowflake: string, totalShards: number) {
- return Number((BigInt(snowflake) >> 22n) % BigInt(totalShards));
+ return Number((BigInt(snowflake) >> 22n) % BigInt(totalShards));
}
export function reminderScheduler(client: Client) {
- const checkReminders = async () => {
- try {
- const due = await getDueReminders();
- const totalShards = client.shard?.count ?? 1;
- const shardId = client.shard?.ids[0] ?? 0;
+ const checkReminders = async () => {
+ try {
+ const due = await getDueReminders();
+ const totalShards = client.shard?.count ?? 1;
+ const shardId = client.shard?.ids[0] ?? 0;
- for (const reminder of due) {
- // each shard handles its reminders for its own guild
- const targetShard = ownerShardId(reminder.guildId ?? reminder.userId, totalShards);
- if (targetShard !== shardId) continue;
+ for (const reminder of due) {
+ // each shard handles its reminders for its own guild
+ const targetShard = ownerShardId(reminder.guildId ?? reminder.userId, totalShards);
+ if (targetShard !== shardId) continue;
- try {
- let sent = false;
- if (reminder.channelId) {
- const channel = client.channels.cache.get(reminder.channelId);
- if (channel?.isSendable()) {
- await channel.send({
- content: `${emojis.rightArrow2} <@${reminder.userId}> reminder: ${reminder.message ?? 'No message provided'}`,
- allowedMentions: { users: [reminder.userId] },
- });
- sent = true;
- }
- }
- if (!sent) {
- await dmUser(client, reminder.userId, reminder.message);
- }
+ try {
+ let sent = false;
+ if (reminder.channelId) {
+ const channel = client.channels.cache.get(reminder.channelId);
+ if (channel?.isSendable()) {
+ await channel.send({
+ content: `${emojis.rightArrow2} <@${reminder.userId}> reminder: ${reminder.message ?? 'No message provided'}`,
+ allowedMentions: { users: [reminder.userId] },
+ });
+ sent = true;
+ }
+ }
+ if (!sent) {
+ await dmUser(client, reminder.userId, reminder.message);
+ }
- await removeReminder(reminder.id);
- } catch (err) {
- console.error(err);
- }
- }
- } catch (err) {
- console.error(err);
- }
- };
- checkReminders();
- setInterval(checkReminders, 30_000);
+ await removeReminder(reminder.id);
+ } catch (err) {
+ console.error(err);
+ }
+ }
+ } catch (err) {
+ console.error(err);
+ }
+ };
+ checkReminders();
+ setInterval(checkReminders, 30_000);
}
-async function dmUser(client: Client, userId: string, message: string ){
- const user = await client.users.fetch(userId).catch(() => null);
- if (!user) return;
-
- await user.send({
- content: `${emojis.rightArrow2} <@${userId}> reminder: ${message}`,
- allowedMentions: { users: [userId] },
- }).catch(() => {});
+async function dmUser(client: Client, userId: string, message: string) {
+ const user = await client.users.fetch(userId).catch(() => null);
+ if (!user) return;
+
+ await user
+ .send({
+ content: `${emojis.rightArrow2} <@${userId}> reminder: ${message}`,
+ allowedMentions: { users: [userId] },
+ })
+ .catch(() => {});
}
diff --git a/apps/bot/src/lib/reminders.ts b/apps/bot/src/lib/reminders.ts
index cf8bcaf..6d6da64 100644
--- a/apps/bot/src/lib/reminders.ts
+++ b/apps/bot/src/lib/reminders.ts
@@ -2,57 +2,57 @@ import { prisma } from './prisma.js';
import { LIMITS_ENABLED, LimitError } from './limits.js';
export async function createReminder(
- userId: string,
- message: string,
- remindAt: Date,
- guildId?: string,
- guildName?: string,
- channelId?: string,
+ userId: string,
+ message: string,
+ remindAt: Date,
+ guildId?: string,
+ guildName?: string,
+ channelId?: string,
) {
- if (LIMITS_ENABLED) {
- const reminderCount = await prisma.reminder.count({ where: { userId } });
-
- if (reminderCount >= 5) {
- throw new LimitError('You can only have up to 5 reminders.');
- }
- }
-
- if (guildId && guildName) {
- await prisma.server.upsert({
- where: { id: guildId },
- create: { id: guildId, name: guildName },
- update: { name: guildName },
- });
- return prisma.reminder.create({
- data: { guildId, userId, channelId, message, remindAt },
- });
- }
- return prisma.reminder.create({
- data: { userId, channelId, message, remindAt },
- });
+ if (LIMITS_ENABLED) {
+ const reminderCount = await prisma.reminder.count({ where: { userId } });
+
+ if (reminderCount >= 5) {
+ throw new LimitError('You can only have up to 5 reminders.');
+ }
+ }
+
+ if (guildId && guildName) {
+ await prisma.server.upsert({
+ where: { id: guildId },
+ create: { id: guildId, name: guildName },
+ update: { name: guildName },
+ });
+ return prisma.reminder.create({
+ data: { guildId, userId, channelId, message, remindAt },
+ });
+ }
+ return prisma.reminder.create({
+ data: { userId, channelId, message, remindAt },
+ });
}
-export async function getReminders( userId: string, guildId?: string) {
- return prisma.reminder.findMany({
- where: { userId, guildId },
- orderBy: { remindAt: 'asc' },
- });
+export async function getReminders(userId: string, guildId?: string) {
+ return prisma.reminder.findMany({
+ where: { userId, guildId },
+ orderBy: { remindAt: 'asc' },
+ });
}
export async function removeReminder(reminderId: string) {
- return prisma.reminder.delete({ where: { id: reminderId } });
+ return prisma.reminder.delete({ where: { id: reminderId } });
}
export async function clearReminders(guildId: string, userId: string) {
- return prisma.reminder.deleteMany({ where: { guildId, userId } });
+ return prisma.reminder.deleteMany({ where: { guildId, userId } });
}
export async function getReminder(reminderId: string) {
- return prisma.reminder.findUnique({ where: { id: reminderId } });
+ return prisma.reminder.findUnique({ where: { id: reminderId } });
}
export async function getDueReminders() {
- return prisma.reminder.findMany({
- where: { remindAt: { lte: new Date() } },
- });
+ return prisma.reminder.findMany({
+ where: { remindAt: { lte: new Date() } },
+ });
}
diff --git a/apps/bot/src/lib/safeFetch.ts b/apps/bot/src/lib/safeFetch.ts
new file mode 100644
index 0000000..a363b86
--- /dev/null
+++ b/apps/bot/src/lib/safeFetch.ts
@@ -0,0 +1,53 @@
+import { lookup } from 'node:dns/promises';
+import ipaddr from 'ipaddr.js';
+
+const MAX_REDIRECTS = 3;
+const TIMEOUT_MS = 10_000;
+
+export class SafeFetchError extends Error {}
+
+async function assertSafeHost(hostname: string): Promise {
+ const records = ipaddr.isValid(hostname)
+ ? [{ address: hostname }]
+ : await lookup(hostname, { all: true });
+
+ if (records.length === 0) {
+ throw new SafeFetchError(`No DNS records for ${hostname}`);
+ }
+
+ for (const { address } of records) {
+ if (ipaddr.parse(address).range() !== 'unicast') {
+ throw new SafeFetchError(`Blocked address range for ${hostname}`);
+ }
+ }
+}
+
+function validate(url: URL) {
+ if (url.protocol !== 'https:') throw new SafeFetchError('HTTPS required.');
+ if (url.port && url.port !== '443') throw new SafeFetchError('Port 443 only.');
+}
+
+export async function safeFetch(raw: string, init: RequestInit = {}): Promise {
+ let url: URL;
+ try { url = new URL(raw); } catch { throw new SafeFetchError('Invalid URL.'); }
+
+ for (let i = 0; i <= MAX_REDIRECTS; i++) {
+ validate(url);
+ await assertSafeHost(url.hostname);
+
+ const res = await fetch(url, {
+ ...init,
+ redirect: 'manual',
+ signal: AbortSignal.timeout(TIMEOUT_MS)
+ }).catch(() => {throw new SafeFetchError('Request failed.');});
+
+ if (res.status >= 300 && res.status < 400) {
+ const loc = res.headers.get('location');
+ if (!loc) return res;
+ url = new URL(loc, url);
+ continue;
+ }
+ return res;
+ }
+ throw new SafeFetchError('Too many redirects.');
+}
\ No newline at end of file
diff --git a/apps/bot/src/lib/settings.ts b/apps/bot/src/lib/settings.ts
index ecf10a2..a8af210 100644
--- a/apps/bot/src/lib/settings.ts
+++ b/apps/bot/src/lib/settings.ts
@@ -1,57 +1,57 @@
-import { Prisma } from "#prisma/client.js";
-import { prisma } from "./prisma.js";
+import { Prisma } from '#prisma/client.js';
+import { prisma } from './prisma.js';
export type ServerSettings = {
- welcomePeople: boolean;
- welcomeChannelId: string | null;
- ticketCategoryId: string | null;
- ticketTranscriptChannelId?: string | null;
- staffRole: string | null;
- confessionChannelId: string | null;
- confessionEnabled: boolean;
- loggingEnabled?: boolean;
- loggingChannelId?: string | null;
+ welcomePeople: boolean;
+ welcomeChannelId: string | null;
+ ticketCategoryId: string | null;
+ ticketTranscriptChannelId?: string | null;
+ staffRole: string | null;
+ confessionChannelId: string | null;
+ confessionEnabled: boolean;
+ loggingEnabled?: boolean;
+ loggingChannelId?: string | null;
};
export const DefaultSettings: ServerSettings = {
- welcomePeople: false,
- welcomeChannelId: null,
- ticketCategoryId: null,
- ticketTranscriptChannelId: null,
- staffRole: null,
- confessionChannelId: null,
- confessionEnabled: false,
- loggingEnabled: false,
- loggingChannelId: null,
+ welcomePeople: false,
+ welcomeChannelId: null,
+ ticketCategoryId: null,
+ ticketTranscriptChannelId: null,
+ staffRole: null,
+ confessionChannelId: null,
+ confessionEnabled: false,
+ loggingEnabled: false,
+ loggingChannelId: null,
};
export async function getSettings(guildId: string, guildName: string): Promise {
- const row = await prisma.server.upsert({
- where: { id: guildId },
- create: { id: guildId, name: guildName, settings: DefaultSettings as Prisma.InputJsonValue },
- update: { name: guildName },
- });
- return { ...DefaultSettings, ...(row.settings as Partial) };
+ const row = await prisma.server.upsert({
+ where: { id: guildId },
+ create: { id: guildId, name: guildName, settings: DefaultSettings as Prisma.InputJsonValue },
+ update: { name: guildName },
+ });
+ return { ...DefaultSettings, ...(row.settings as Partial) };
}
export async function updateSettings(
- guildId: string,
- guildName: string,
- patch: Partial,
+ guildId: string,
+ guildName: string,
+ patch: Partial,
): Promise {
- const row = await prisma.server.upsert({
- where: { id: guildId },
- create: { id: guildId, name: guildName, settings: DefaultSettings as Prisma.InputJsonValue },
- update: { name: guildName },
- });
+ const row = await prisma.server.upsert({
+ where: { id: guildId },
+ create: { id: guildId, name: guildName, settings: DefaultSettings as Prisma.InputJsonValue },
+ update: { name: guildName },
+ });
- const current = { ...DefaultSettings, ...(row.settings as Partial) };
- const next = { ...current, ...patch };
+ const current = { ...DefaultSettings, ...(row.settings as Partial) };
+ const next = { ...current, ...patch };
- await prisma.server.update({
- where: { id: guildId },
- data: { name: guildName, settings: next as Prisma.InputJsonValue },
- });
+ await prisma.server.update({
+ where: { id: guildId },
+ data: { name: guildName, settings: next as Prisma.InputJsonValue },
+ });
- return next;
+ return next;
}
diff --git a/apps/bot/src/lib/tickets.ts b/apps/bot/src/lib/tickets.ts
index 823a00e..bbad4f6 100644
--- a/apps/bot/src/lib/tickets.ts
+++ b/apps/bot/src/lib/tickets.ts
@@ -1,71 +1,66 @@
-import { prisma } from "./prisma.js";
+import { prisma } from './prisma.js';
-export async function createTicket(
- guildId: string,
- guildName: string,
- userId: string,
- reason: string,
-) {
- return prisma.$transaction(async (tx) => {
- await tx.server.upsert({
- where: { id: guildId },
- create: { id: guildId, name: guildName },
- update: { name: guildName },
- });
+export async function createTicket(guildId: string, guildName: string, userId: string, reason: string) {
+ return prisma.$transaction(async (tx) => {
+ await tx.server.upsert({
+ where: { id: guildId },
+ create: { id: guildId, name: guildName },
+ update: { name: guildName },
+ });
- const server = await tx.server.update({
- where: { id: guildId },
- data: {
- nextTicketNumber: {
- increment: 1,
- },
- },
- select: {
- nextTicketNumber: true,
- },
- });
+ const server = await tx.server.update({
+ where: { id: guildId },
+ data: {
+ nextTicketNumber: {
+ increment: 1,
+ },
+ },
+ select: {
+ nextTicketNumber: true,
+ },
+ });
- return tx.ticket.create({
- data: {
- guildId,
- ticketNumber: server.nextTicketNumber - 1,
- userId,
- reason,
- },
- });
- });
+ return tx.ticket.create({
+ data: {
+ guildId,
+ ticketNumber: server.nextTicketNumber - 1,
+ userId,
+ reason,
+ },
+ });
+ });
}
export async function setTicketChannelId(ticketId: string, channelId: string) {
- return prisma.ticket.update({
- where: { id: ticketId },
- data: { channelId },
- });
+ return prisma.ticket.update({
+ where: { id: ticketId },
+ data: { channelId },
+ });
}
export async function getTickets(guildId: string, userId: string) {
- return prisma.ticket.findMany({
- where: { guildId, userId },
- orderBy: { createdAt: 'desc' },
- });
+ return prisma.ticket.findMany({
+ where: { guildId, userId },
+ orderBy: { createdAt: 'desc' },
+ });
}
export async function removeTicket(ticketId: string) {
- return prisma.ticket.delete({ where: { id: ticketId } });
+ return prisma.ticket.delete({ where: { id: ticketId } });
}
export async function clearTickets(guildId: string, userId: string) {
- return prisma.ticket.deleteMany({ where: { guildId, userId } });
+ return prisma.ticket.deleteMany({ where: { guildId, userId } });
}
export async function getTicket(ticketId: string, guildId: string) {
- const ticket = await prisma.ticket.findUnique({ where: { id: ticketId } });
- if (!ticket || ticket.guildId !== guildId) return null;
- return ticket;
+ const ticket = await prisma.ticket.findUnique({ where: { id: ticketId } });
+ if (!ticket || ticket.guildId !== guildId) return null;
+ return ticket;
}
export async function getTicketId(guildId: string, channelId: string) {
- return prisma.ticket.findFirst({
- where: { guildId, channelId }
- });
+ return prisma.ticket.findFirst({
+ where: { guildId, channelId },
+ });
}
diff --git a/apps/bot/src/lib/warns.ts b/apps/bot/src/lib/warns.ts
index dcd61fb..110557a 100644
--- a/apps/bot/src/lib/warns.ts
+++ b/apps/bot/src/lib/warns.ts
@@ -1,51 +1,51 @@
-import { prisma } from "./prisma.js";
+import { prisma } from './prisma.js';
export async function createWarn(
- guildId: string,
- guildName: string,
- userId: string,
- moderatorId: string,
- reason: string,
- expiresAt: Date | null = null,
+ guildId: string,
+ guildName: string,
+ userId: string,
+ moderatorId: string,
+ reason: string,
+ expiresAt: Date | null = null,
) {
- return prisma.$transaction(async (tx) => {
- await (tx as any).server.upsert({
- where: { id: guildId },
- create: { id: guildId, name: guildName },
- update: { name: guildName },
- });
- return (tx as any).warn.create({
- data: { guildId, userId, moderatorId, reason, expiresAt },
- });
- });
+ return prisma.$transaction(async (tx) => {
+ await (tx as any).server.upsert({
+ where: { id: guildId },
+ create: { id: guildId, name: guildName },
+ update: { name: guildName },
+ });
+ return (tx as any).warn.create({
+ data: { guildId, userId, moderatorId, reason, expiresAt },
+ });
+ });
}
export async function getWarns(guildId: string, userId: string) {
- return prisma.warn.findMany({
- where: { guildId, userId },
- orderBy: { createdAt: 'desc' },
- });
+ return prisma.warn.findMany({
+ where: { guildId, userId },
+ orderBy: { createdAt: 'desc' },
+ });
}
export async function removeWarn(warnId: string) {
- return prisma.warn.delete({ where: { id: warnId } });
+ return prisma.warn.delete({ where: { id: warnId } });
}
export async function clearWarns(guildId: string, userId: string) {
- return prisma.warn.deleteMany({ where: { guildId, userId } });
+ return prisma.warn.deleteMany({ where: { guildId, userId } });
}
export async function getWarn(warnId: string, guildId: string) {
- const warn = await prisma.warn.findUnique({ where: { id: warnId } });
- if (!warn || warn.guildId !== guildId) return null;
- return warn;
+ const warn = await prisma.warn.findUnique({ where: { id: warnId } });
+ if (!warn || warn.guildId !== guildId) return null;
+ return warn;
}
export async function purgeExpiredWarns(gracePeriodDays = 30) {
- const cutoff = new Date(Date.now() - gracePeriodDays * 24 * 60 * 60 * 1000);
- return prisma.warn.deleteMany({
- where: {
- expiresAt: { not: null, lte: cutoff },
- },
- });
+ const cutoff = new Date(Date.now() - gracePeriodDays * 24 * 60 * 60 * 1000);
+ return prisma.warn.deleteMany({
+ where: {
+ expiresAt: { not: null, lte: cutoff },
+ },
+ });
}
diff --git a/apps/bot/src/lib/welcomeModule.ts b/apps/bot/src/lib/welcomeModule.ts
index b6ef297..c3243a4 100644
--- a/apps/bot/src/lib/welcomeModule.ts
+++ b/apps/bot/src/lib/welcomeModule.ts
@@ -6,39 +6,35 @@ const ownerDmCooldown = new Map();
const DM_COOLDOWN = 24 * 60 * 60 * 1000; // 24h
export async function sendWelcome(member: GuildMember): Promise {
- const settings = await getSettings(member.guild.id, member.guild.name);
- if (!settings.welcomePeople || !settings.welcomeChannelId) return;
+ const settings = await getSettings(member.guild.id, member.guild.name);
+ if (!settings.welcomePeople || !settings.welcomeChannelId) return;
- const channel = await member.guild.channels
- .fetch(settings.welcomeChannelId)
- .catch(() => null);
- if (!channel?.isTextBased() || !channel.isSendable()) return;
+ const channel = await member.guild.channels.fetch(settings.welcomeChannelId).catch(() => null);
+ if (!channel?.isTextBased() || !channel.isSendable()) return;
- try {
- await channel.send(
- `${emojis.rightArrow1} Welcome to **${member.guild.name}**, <@${member.user.id}>!`,
- );
- } catch (err) {
- if (err instanceof DiscordAPIError && err.code === RESTJSONErrorCodes.MissingPermissions) {
- await notifyOwner(member, channel.id);
- return;
- }
- console.error(`[welcomeModule] Failed to send in ${member.guild.id}#${channel.id}:`, err);
- }
+ try {
+ await channel.send(`${emojis.rightArrow1} Welcome to **${member.guild.name}**, <@${member.user.id}>!`);
+ } catch (err) {
+ if (err instanceof DiscordAPIError && err.code === RESTJSONErrorCodes.MissingPermissions) {
+ await notifyOwner(member, channel.id);
+ return;
+ }
+ console.error(`[welcomeModule] Failed to send in ${member.guild.id}#${channel.id}:`, err);
+ }
}
async function notifyOwner(member: GuildMember, channelId: string): Promise {
- const guild = member.guild;
- const last = ownerDmCooldown.get(guild.id) ?? 0;
- if (Date.now() - last < DM_COOLDOWN) return;
- ownerDmCooldown.set(guild.id, Date.now());
+ const guild = member.guild;
+ const last = ownerDmCooldown.get(guild.id) ?? 0;
+ if (Date.now() - last < DM_COOLDOWN) return;
+ ownerDmCooldown.set(guild.id, Date.now());
- try {
- const owner = await guild.fetchOwner();
- await owner.send(
- `${emojis.rightArrow2} I couldn't send a welcome message in **${guild.name}** because I'm missing permissions in <#${channelId}>. Make sure I have permission to send messages there!`
- );
- } catch (err) {
- console.warn(`[welcomeModule] Couldn't DM owner of ${guild.id}:`, err);
- }
-}
\ No newline at end of file
+ try {
+ const owner = await guild.fetchOwner();
+ await owner.send(
+ `${emojis.rightArrow2} I couldn't send a welcome message in **${guild.name}** because I'm missing permissions in <#${channelId}>. Make sure I have permission to send messages there!`,
+ );
+ } catch (err) {
+ console.warn(`[welcomeModule] Couldn't DM owner of ${guild.id}:`, err);
+ }
+}
diff --git a/apps/bot/src/listeners/channelCreate.ts b/apps/bot/src/listeners/channelCreate.ts
index 7d86d60..f67c516 100644
--- a/apps/bot/src/listeners/channelCreate.ts
+++ b/apps/bot/src/listeners/channelCreate.ts
@@ -3,37 +3,37 @@ import { AuditLogEvent, EmbedBuilder, Events, type Channel } from 'discord.js';
import { getRecentAuditLogEntry, isLoggingChannel, logEmbed } from '#lib/logging.js';
export class ChannelCreateListener extends Listener {
- public constructor(context: Listener.LoaderContext, options: Listener.Options) {
- super(context, {
- ...options,
- event: Events.ChannelCreate
- });
- }
-
- public async run(channel: Channel) {
- if (!('guild' in channel) || !channel.guild) return;
-
- if (await isLoggingChannel(channel.guild, channel.id)) return;
-
- const channelId = channel.id;
- const typeLabel = String(channel.type);
-
- const embed = new EmbedBuilder()
- .setTitle('Channel Created')
- .setColor(0x77DD76)
- .addFields(
- { name: 'Channel', value: `<#${channelId}>`, inline: true },
- { name: 'Type', value: typeLabel, inline: true }
- )
- .setTimestamp();
-
- const auditEntry = await getRecentAuditLogEntry(channel.guild, AuditLogEvent.ChannelCreate, channel.id);
-
- if (auditEntry?.executor) {
- const moderatorLabel = auditEntry.executor.tag ?? auditEntry.executor.username ?? auditEntry.executor.id;
- embed.addFields({ name: 'Moderator', value: moderatorLabel, inline: true });
- }
-
- await logEmbed(channel.guild, embed);
- }
-}
\ No newline at end of file
+ public constructor(context: Listener.LoaderContext, options: Listener.Options) {
+ super(context, {
+ ...options,
+ event: Events.ChannelCreate,
+ });
+ }
+
+ public async run(channel: Channel) {
+ if (!('guild' in channel) || !channel.guild) return;
+
+ if (await isLoggingChannel(channel.guild, channel.id)) return;
+
+ const channelId = channel.id;
+ const typeLabel = String(channel.type);
+
+ const embed = new EmbedBuilder()
+ .setTitle('Channel Created')
+ .setColor(0x77dd76)
+ .addFields(
+ { name: 'Channel', value: `<#${channelId}>`, inline: true },
+ { name: 'Type', value: typeLabel, inline: true },
+ )
+ .setTimestamp();
+
+ const auditEntry = await getRecentAuditLogEntry(channel.guild, AuditLogEvent.ChannelCreate, channel.id);
+
+ if (auditEntry?.executor) {
+ const moderatorLabel = auditEntry.executor.tag ?? auditEntry.executor.username ?? auditEntry.executor.id;
+ embed.addFields({ name: 'Moderator', value: moderatorLabel, inline: true });
+ }
+
+ await logEmbed(channel.guild, embed);
+ }
+}
diff --git a/apps/bot/src/listeners/channelDelete.ts b/apps/bot/src/listeners/channelDelete.ts
index bdc21c6..d41ac83 100644
--- a/apps/bot/src/listeners/channelDelete.ts
+++ b/apps/bot/src/listeners/channelDelete.ts
@@ -4,40 +4,36 @@ import { removeConfessionContextsByChannel } from '#lib/confessions.js';
import { getRecentAuditLogEntry, isLoggingChannel, logEmbed } from '#lib/logging.js';
export class ChannelDeleteListener extends Listener {
- public constructor(context: Listener.LoaderContext, options: Listener.Options) {
- super(context, {
- ...options,
- event: Events.ChannelDelete
- });
- }
-
- public async run(channel: Channel) {
- if (!('guild' in channel) || !channel.guild) return;
-
- await removeConfessionContextsByChannel(channel.id).catch(() => null);
-
- if (await isLoggingChannel(channel.guild, channel.id)) return;
-
- const channelLabel = channel.toString() || 'Unknown';
- const typeLabel = String(channel.type);
- const fields: APIEmbedField[] = [
- { name: 'Channel', value: `${channelLabel} (${channel.id})`, inline: true },
- { name: 'Type', value: typeLabel, inline: true }
- ];
-
- const embed = new EmbedBuilder()
- .setTitle('Channel Deleted')
- .setColor(0xFF6962)
- .addFields(fields)
- .setTimestamp();
-
- const auditEntry = await getRecentAuditLogEntry(channel.guild, AuditLogEvent.ChannelDelete, channel.id);
-
- if (auditEntry?.executor) {
- const moderatorLabel = String(auditEntry.executor.tag ?? auditEntry.executor.username ?? auditEntry.executor.id);
- embed.addFields({ name: 'Moderator', value: moderatorLabel, inline: true });
- }
-
- await logEmbed(channel.guild, embed);
- }
-}
\ No newline at end of file
+ public constructor(context: Listener.LoaderContext, options: Listener.Options) {
+ super(context, {
+ ...options,
+ event: Events.ChannelDelete,
+ });
+ }
+
+ public async run(channel: Channel) {
+ if (!('guild' in channel) || !channel.guild) return;
+
+ await removeConfessionContextsByChannel(channel.id).catch(() => null);
+
+ if (await isLoggingChannel(channel.guild, channel.id)) return;
+
+ const channelLabel = channel.toString() || 'Unknown';
+ const typeLabel = String(channel.type);
+ const fields: APIEmbedField[] = [
+ { name: 'Channel', value: `${channelLabel} (${channel.id})`, inline: true },
+ { name: 'Type', value: typeLabel, inline: true },
+ ];
+
+ const embed = new EmbedBuilder().setTitle('Channel Deleted').setColor(0xff6962).addFields(fields).setTimestamp();
+
+ const auditEntry = await getRecentAuditLogEntry(channel.guild, AuditLogEvent.ChannelDelete, channel.id);
+
+ if (auditEntry?.executor) {
+ const moderatorLabel = String(auditEntry.executor.tag ?? auditEntry.executor.username ?? auditEntry.executor.id);
+ embed.addFields({ name: 'Moderator', value: moderatorLabel, inline: true });
+ }
+
+ await logEmbed(channel.guild, embed);
+ }
+}
diff --git a/apps/bot/src/listeners/chatInputDenied.ts b/apps/bot/src/listeners/chatInputDenied.ts
index c1f292f..96017e0 100644
--- a/apps/bot/src/listeners/chatInputDenied.ts
+++ b/apps/bot/src/listeners/chatInputDenied.ts
@@ -2,19 +2,19 @@ import { Listener, type ChatInputCommandDeniedPayload, type UserError } from '@s
import { MessageFlags } from 'discord.js';
export class ChatInputCommandDeniedListener extends Listener {
- public constructor(context: Listener.LoaderContext, options: Listener.Options) {
- super(context, { ...options, event: 'chatInputCommandDenied' });
- }
+ public constructor(context: Listener.LoaderContext, options: Listener.Options) {
+ super(context, { ...options, event: 'chatInputCommandDenied' });
+ }
- public override async run(error: UserError, { interaction }: ChatInputCommandDeniedPayload) {
- if (interaction.deferred || interaction.replied) {
- await interaction.editReply({ content: error.message });
- return;
- }
+ public override async run(error: UserError, { interaction }: ChatInputCommandDeniedPayload) {
+ if (interaction.deferred || interaction.replied) {
+ await interaction.editReply({ content: error.message });
+ return;
+ }
- await interaction.reply({
- content: error.message,
- flags: MessageFlags.Ephemeral,
- });
- }
-}
\ No newline at end of file
+ await interaction.reply({
+ content: error.message,
+ flags: MessageFlags.Ephemeral,
+ });
+ }
+}
diff --git a/apps/bot/src/listeners/contextMenuDenied.ts b/apps/bot/src/listeners/contextMenuDenied.ts
index f0b8e85..0d97620 100644
--- a/apps/bot/src/listeners/contextMenuDenied.ts
+++ b/apps/bot/src/listeners/contextMenuDenied.ts
@@ -2,19 +2,19 @@ import { Listener, type ContextMenuCommandDeniedPayload, type UserError } from '
import { MessageFlags } from 'discord.js';
export class ContextMenuCommandDeniedListener extends Listener {
- public constructor(context: Listener.LoaderContext, options: Listener.Options) {
- super(context, { ...options, event: 'contextMenuCommandDenied' });
- }
+ public constructor(context: Listener.LoaderContext, options: Listener.Options) {
+ super(context, { ...options, event: 'contextMenuCommandDenied' });
+ }
- public override async run(error: UserError, { interaction }: ContextMenuCommandDeniedPayload) {
- if (interaction.deferred || interaction.replied) {
- await interaction.editReply({ content: error.message });
- return;
- }
+ public override async run(error: UserError, { interaction }: ContextMenuCommandDeniedPayload) {
+ if (interaction.deferred || interaction.replied) {
+ await interaction.editReply({ content: error.message });
+ return;
+ }
- await interaction.reply({
- content: error.message,
- flags: MessageFlags.Ephemeral,
- });
- }
-}
\ No newline at end of file
+ await interaction.reply({
+ content: error.message,
+ flags: MessageFlags.Ephemeral,
+ });
+ }
+}
diff --git a/apps/bot/src/listeners/guildBanAdd.ts b/apps/bot/src/listeners/guildBanAdd.ts
index c0020bf..b376760 100644
--- a/apps/bot/src/listeners/guildBanAdd.ts
+++ b/apps/bot/src/listeners/guildBanAdd.ts
@@ -3,33 +3,33 @@ import { AuditLogEvent, Colors, EmbedBuilder, Events, type GuildBan } from 'disc
import { getRecentAuditLogEntry, logEmbed } from '#lib/logging.js';
export class GuildBanAddListener extends Listener {
- public constructor(context: Listener.LoaderContext, options: Listener.Options) {
- super(context, {
- ...options,
- event: Events.GuildBanAdd
- });
- }
+ public constructor(context: Listener.LoaderContext, options: Listener.Options) {
+ super(context, {
+ ...options,
+ event: Events.GuildBanAdd,
+ });
+ }
- public async run(ban: GuildBan) {
- const auditEntry = await getRecentAuditLogEntry(ban.guild, AuditLogEvent.MemberBanAdd, ban.user.id);
+ public async run(ban: GuildBan) {
+ const auditEntry = await getRecentAuditLogEntry(ban.guild, AuditLogEvent.MemberBanAdd, ban.user.id);
- const embed = new EmbedBuilder()
- .setTitle('Member Banned')
- .setColor(Colors.DarkRed)
- .addFields(
- { name: 'Member', value: `${ban.user.tag} (${ban.user.id})`, inline: false },
- { name: 'Username', value: ban.user.toString(), inline: true }
- )
- .setTimestamp();
+ const embed = new EmbedBuilder()
+ .setTitle('Member Banned')
+ .setColor(Colors.DarkRed)
+ .addFields(
+ { name: 'Member', value: `${ban.user.tag} (${ban.user.id})`, inline: false },
+ { name: 'Username', value: ban.user.toString(), inline: true },
+ )
+ .setTimestamp();
- if (auditEntry?.executor) {
- embed.addFields({ name: 'Moderator', value: `${auditEntry.executor.tag}`, inline: true });
- }
+ if (auditEntry?.executor) {
+ embed.addFields({ name: 'Moderator', value: `${auditEntry.executor.tag}`, inline: true });
+ }
- if (auditEntry?.reason) {
- embed.addFields({ name: 'Reason', value: auditEntry.reason, inline: false });
- }
+ if (auditEntry?.reason) {
+ embed.addFields({ name: 'Reason', value: auditEntry.reason, inline: false });
+ }
- await logEmbed(ban.guild, embed);
- }
-}
\ No newline at end of file
+ await logEmbed(ban.guild, embed);
+ }
+}
diff --git a/apps/bot/src/listeners/guildCreate.ts b/apps/bot/src/listeners/guildCreate.ts
index 005141c..83bfa30 100644
--- a/apps/bot/src/listeners/guildCreate.ts
+++ b/apps/bot/src/listeners/guildCreate.ts
@@ -2,24 +2,26 @@ import { Listener } from '@sapphire/framework';
import { AuditLogEvent, EmbedBuilder, Events, PermissionFlagsBits, type Guild } from 'discord.js';
export class GuildCreateListener extends Listener {
- public constructor(context: Listener.LoaderContext, options: Listener.Options) {
- super(context, { ...options, event: Events.GuildCreate });
- }
+ public constructor(context: Listener.LoaderContext, options: Listener.Options) {
+ super(context, { ...options, event: Events.GuildCreate });
+ }
- public async run(guild: Guild) {
- if (!guild.members.me?.permissions.has(PermissionFlagsBits.ViewAuditLog)) return;
+ public async run(guild: Guild) {
+ if (!guild.members.me?.permissions.has(PermissionFlagsBits.ViewAuditLog)) return;
- const logs = await guild.fetchAuditLogs({ type: AuditLogEvent.BotAdd, limit: 5 }).catch(() => null);
- const entry = logs?.entries.find((e) => e.target?.id === guild.client.user.id);
- const adder = entry?.executor;
+ const logs = await guild.fetchAuditLogs({ type: AuditLogEvent.BotAdd, limit: 5 }).catch(() => null);
+ const entry = logs?.entries.find((e) => e.target?.id === guild.client.user.id);
+ const adder = entry?.executor;
- if (!adder) return;
+ if (!adder) return;
- const embed = new EmbedBuilder()
- .setColor(0xffffff)
- .setTitle('Thanks for adding me!')
- .setDescription(`I'm here to replace your other bot's and help improve your server!\n\nTo get started you can use the \`/setup\` command to help configure your server.\nIf you know how I work and want to configure me you can run \`/help\` for a list of all commands.\n\nIf you have any questions or need help, feel free to join the support server by using the \`/discord\` command.`);
+ const embed = new EmbedBuilder()
+ .setColor(0xffffff)
+ .setTitle('Thanks for adding me!')
+ .setDescription(
+ `I'm here to replace your other bot's and help improve your server!\n\nTo get started you can use the \`/setup\` command to help configure your server.\nIf you know how I work and want to configure me you can run \`/help\` for a list of all commands.\n\nIf you have any questions or need help, feel free to join the support server by using the \`/discord\` command.`,
+ );
- await adder.send({ embeds: [embed] }).catch(() => null);
- }
+ await adder.send({ embeds: [embed] }).catch(() => null);
+ }
}
diff --git a/apps/bot/src/listeners/guildDelete.ts b/apps/bot/src/listeners/guildDelete.ts
index 1629eb2..7024be5 100644
--- a/apps/bot/src/listeners/guildDelete.ts
+++ b/apps/bot/src/listeners/guildDelete.ts
@@ -3,21 +3,23 @@ import { EmbedBuilder, Events, type Guild } from 'discord.js';
import { prisma } from '#lib/prisma.js';
export class GuildDeleteListener extends Listener {
- public constructor(context: Listener.LoaderContext, options: Listener.Options) {
- super(context, { ...options, event: Events.GuildDelete });
- }
+ public constructor(context: Listener.LoaderContext, options: Listener.Options) {
+ super(context, { ...options, event: Events.GuildDelete });
+ }
- public async run(guild: Guild) {
- await prisma.server.delete({ where: { id: guild.id } }).catch(() => null);
+ public async run(guild: Guild) {
+ await prisma.server.delete({ where: { id: guild.id } }).catch(() => null);
- const owner = await guild.client.users.fetch(guild.ownerId).catch(() => null);
- if (!owner) return;
+ const owner = await guild.client.users.fetch(guild.ownerId).catch(() => null);
+ if (!owner) return;
- const embed = new EmbedBuilder()
- .setColor(0xffffff)
- .setTitle('Sorry to see you go!')
- .setDescription(`If you had any issues or feedback, feel free to join the support server by using the \`/discord\` command.\n\nWe'd also appreciate it if you could fill out our feedback form at https://duckorg.com/feedback/questbot.`);
+ const embed = new EmbedBuilder()
+ .setColor(0xffffff)
+ .setTitle('Sorry to see you go!')
+ .setDescription(
+ `If you had any issues or feedback, feel free to join the support server by using the \`/discord\` command.\n\nWe'd also appreciate it if you could fill out our feedback form at https://duckorg.com/feedback/questbot.`,
+ );
- await owner.send({ embeds: [embed] }).catch(() => null);
- }
+ await owner.send({ embeds: [embed] }).catch(() => null);
+ }
}
diff --git a/apps/bot/src/listeners/guildEmojisUpdate.ts b/apps/bot/src/listeners/guildEmojisUpdate.ts
index fe316ad..2290e6c 100644
--- a/apps/bot/src/listeners/guildEmojisUpdate.ts
+++ b/apps/bot/src/listeners/guildEmojisUpdate.ts
@@ -3,29 +3,29 @@ import { EmbedBuilder, Colors, type GuildEmoji, type Collection, type Guild } fr
import { logEmbed } from '#lib/logging.js';
export class GuildEmojisUpdateListener extends Listener {
- public constructor(context: Listener.LoaderContext, options: Listener.Options) {
- super(context, { ...options, event: 'guildEmojisUpdate' as any });
- }
+ public constructor(context: Listener.LoaderContext, options: Listener.Options) {
+ super(context, { ...options, event: 'guildEmojisUpdate' as any });
+ }
- public async run(guild: Guild, oldEmojis: Collection, newEmojis: Collection) {
- const created = newEmojis.filter((e) => !oldEmojis.has(e.id));
- const deleted = oldEmojis.filter((e) => !newEmojis.has(e.id));
- const updated = newEmojis.filter((e) => {
- const old = oldEmojis.get(e.id);
- return old && (old.name !== e.name || old.animated !== e.animated);
- });
+ public async run(guild: Guild, oldEmojis: Collection, newEmojis: Collection) {
+ const created = newEmojis.filter((e) => !oldEmojis.has(e.id));
+ const deleted = oldEmojis.filter((e) => !newEmojis.has(e.id));
+ const updated = newEmojis.filter((e) => {
+ const old = oldEmojis.get(e.id);
+ return old && (old.name !== e.name || old.animated !== e.animated);
+ });
- if (created.size === 0 && deleted.size === 0 && updated.size === 0) return;
+ if (created.size === 0 && deleted.size === 0 && updated.size === 0) return;
- const embed = new EmbedBuilder().setTitle('Guild Emojis Updated').setColor(Colors.Blue).setTimestamp();
+ const embed = new EmbedBuilder().setTitle('Guild Emojis Updated').setColor(Colors.Blue).setTimestamp();
- if (created.size > 0)
- embed.addFields({ name: `Created (${created.size})`, value: created.map((e) => `${e}`).join(' ' ) });
- if (deleted.size > 0)
- embed.addFields({ name: `Deleted (${deleted.size})`, value: deleted.map((e) => e.name).join(', ') });
- if (updated.size > 0)
- embed.addFields({ name: `Updated (${updated.size})`, value: updated.map((e) => e.name).join(', ') });
+ if (created.size > 0)
+ embed.addFields({ name: `Created (${created.size})`, value: created.map((e) => `${e}`).join(' ') });
+ if (deleted.size > 0)
+ embed.addFields({ name: `Deleted (${deleted.size})`, value: deleted.map((e) => e.name).join(', ') });
+ if (updated.size > 0)
+ embed.addFields({ name: `Updated (${updated.size})`, value: updated.map((e) => e.name).join(', ') });
- await logEmbed(guild, embed);
- }
+ await logEmbed(guild, embed);
+ }
}
diff --git a/apps/bot/src/listeners/guildMemberAdd.ts b/apps/bot/src/listeners/guildMemberAdd.ts
index 3bd7fa6..55c616e 100644
--- a/apps/bot/src/listeners/guildMemberAdd.ts
+++ b/apps/bot/src/listeners/guildMemberAdd.ts
@@ -5,38 +5,38 @@ import { getAutoRoles } from '#lib/autorole.js';
import { sendWelcome } from '#lib/welcomeModule.js';
export class GuildMemberAddListener extends Listener {
- public constructor(context: Listener.LoaderContext, options: Listener.Options) {
- super(context, {
- ...options,
- event: Events.GuildMemberAdd
- });
- }
+ public constructor(context: Listener.LoaderContext, options: Listener.Options) {
+ super(context, {
+ ...options,
+ event: Events.GuildMemberAdd,
+ });
+ }
- public async run(member: GuildMember) {
- const botMember = member.guild.members.me;
+ public async run(member: GuildMember) {
+ const botMember = member.guild.members.me;
- if (!botMember?.permissions.has(PermissionFlagsBits.ManageRoles)) {
- await enforceMute(member.guild, member.id).catch((err) => console.error(err));
- await sendWelcome(member).catch((err) => console.error(err));
- return;
- }
+ if (!botMember?.permissions.has(PermissionFlagsBits.ManageRoles)) {
+ await enforceMute(member.guild, member.id).catch((err) => console.error(err));
+ await sendWelcome(member).catch((err) => console.error(err));
+ return;
+ }
- const autoRoles = await getAutoRoles(member.guild.id).catch((err) => {
- console.error(err);
- return [];
- });
+ const autoRoles = await getAutoRoles(member.guild.id).catch((err) => {
+ console.error(err);
+ return [];
+ });
- const rolesToAdd = autoRoles
- .filter((autoRole) => Boolean(autoRole.botRole) === member.user.bot)
- .map((autoRole) => member.guild.roles.cache.get(autoRole.roleId))
- .filter((role): role is NonNullable => Boolean(role?.editable))
- .map((role) => role.id);
+ const rolesToAdd = autoRoles
+ .filter((autoRole) => Boolean(autoRole.botRole) === member.user.bot)
+ .map((autoRole) => member.guild.roles.cache.get(autoRole.roleId))
+ .filter((role): role is NonNullable => Boolean(role?.editable))
+ .map((role) => role.id);
- if (rolesToAdd.length > 0) {
- await member.roles.add(rolesToAdd).catch((err) => console.error(err));
- }
+ if (rolesToAdd.length > 0) {
+ await member.roles.add(rolesToAdd).catch((err) => console.error(err));
+ }
- await enforceMute(member.guild, member.id).catch((err) => console.error(err));
- await sendWelcome(member).catch((err) => console.error(err));
- }
-}
\ No newline at end of file
+ await enforceMute(member.guild, member.id).catch((err) => console.error(err));
+ await sendWelcome(member).catch((err) => console.error(err));
+ }
+}
diff --git a/apps/bot/src/listeners/guildMemberRemove.ts b/apps/bot/src/listeners/guildMemberRemove.ts
index 8446411..c91652a 100644
--- a/apps/bot/src/listeners/guildMemberRemove.ts
+++ b/apps/bot/src/listeners/guildMemberRemove.ts
@@ -3,36 +3,36 @@ import { AuditLogEvent, Colors, EmbedBuilder, Events, type GuildMember } from 'd
import { getRecentAuditLogEntry, logEmbed } from '#lib/logging.js';
export class GuildMemberRemoveListener extends Listener {
- public constructor(context: Listener.LoaderContext, options: Listener.Options) {
- super(context, {
- ...options,
- event: Events.GuildMemberRemove
- });
- }
+ public constructor(context: Listener.LoaderContext, options: Listener.Options) {
+ super(context, {
+ ...options,
+ event: Events.GuildMemberRemove,
+ });
+ }
- public async run(member: GuildMember) {
- const banEntry = await getRecentAuditLogEntry(member.guild, AuditLogEvent.MemberBanAdd, member.id);
- if (banEntry) return;
+ public async run(member: GuildMember) {
+ const banEntry = await getRecentAuditLogEntry(member.guild, AuditLogEvent.MemberBanAdd, member.id);
+ if (banEntry) return;
- const kickEntry = await getRecentAuditLogEntry(member.guild, AuditLogEvent.MemberKick, member.id);
+ const kickEntry = await getRecentAuditLogEntry(member.guild, AuditLogEvent.MemberKick, member.id);
- const embed = new EmbedBuilder()
- .setTitle(kickEntry ? 'Member Kicked' : 'Member Left')
- .setColor(kickEntry ? 0xFF6962 : Colors.Grey)
- .addFields(
- { name: 'Member', value: `${member.user.tag} (${member.id})`, inline: false },
- { name: 'Username', value: member.user.toString(), inline: true }
- )
- .setTimestamp();
+ const embed = new EmbedBuilder()
+ .setTitle(kickEntry ? 'Member Kicked' : 'Member Left')
+ .setColor(kickEntry ? 0xff6962 : Colors.Grey)
+ .addFields(
+ { name: 'Member', value: `${member.user.tag} (${member.id})`, inline: false },
+ { name: 'Username', value: member.user.toString(), inline: true },
+ )
+ .setTimestamp();
- if (kickEntry?.executor) {
- embed.addFields({ name: 'Moderator', value: `${kickEntry.executor.tag}`, inline: true });
- }
+ if (kickEntry?.executor) {
+ embed.addFields({ name: 'Moderator', value: `${kickEntry.executor.tag}`, inline: true });
+ }
- if (kickEntry?.reason) {
- embed.addFields({ name: 'Reason', value: kickEntry.reason, inline: false });
- }
+ if (kickEntry?.reason) {
+ embed.addFields({ name: 'Reason', value: kickEntry.reason, inline: false });
+ }
- await logEmbed(member.guild, embed);
- }
-}
\ No newline at end of file
+ await logEmbed(member.guild, embed);
+ }
+}
diff --git a/apps/bot/src/listeners/guildMemberUpdate.ts b/apps/bot/src/listeners/guildMemberUpdate.ts
index a55cfff..8856b61 100644
--- a/apps/bot/src/listeners/guildMemberUpdate.ts
+++ b/apps/bot/src/listeners/guildMemberUpdate.ts
@@ -3,47 +3,47 @@ import { AuditLogEvent, Colors, EmbedBuilder, Events, type GuildMember } from 'd
import { getRecentAuditLogEntry, logEmbed } from '#lib/logging.js';
export class GuildMemberUpdateListener extends Listener {
- public constructor(context: Listener.LoaderContext, options: Listener.Options) {
- super(context, {
- ...options,
- event: Events.GuildMemberUpdate
- });
- }
-
- public async run(oldMember: GuildMember, newMember: GuildMember) {
- const beforeTimeout = oldMember.communicationDisabledUntilTimestamp ?? null;
- const afterTimeout = newMember.communicationDisabledUntilTimestamp ?? null;
-
- if (Boolean(beforeTimeout) === Boolean(afterTimeout)) return;
-
- const auditEntry = await getRecentAuditLogEntry(newMember.guild, AuditLogEvent.MemberUpdate, newMember.id);
-
- const timeoutAdded = !beforeTimeout && afterTimeout;
- const embed = new EmbedBuilder()
- .setTitle(timeoutAdded ? 'Member Timed Out' : 'Timeout Removed')
- .setColor(timeoutAdded ? Colors.Orange : 0x77DD76)
- .addFields(
- { name: 'Member', value: `${newMember.user.tag} (${newMember.id})`, inline: false },
- { name: 'Username', value: newMember.user.toString(), inline: true }
- )
- .setTimestamp();
-
- if (auditEntry?.executor) {
- embed.addFields({ name: 'Moderator', value: `${auditEntry.executor.tag}`, inline: true });
- }
-
- if (auditEntry?.reason) {
- embed.addFields({ name: 'Reason', value: auditEntry.reason, inline: false });
- }
-
- if (afterTimeout) {
- embed.addFields({
- name: 'Expires',
- value: ``,
- inline: true
- });
- }
-
- await logEmbed(newMember.guild, embed);
- }
-}
\ No newline at end of file
+ public constructor(context: Listener.LoaderContext, options: Listener.Options) {
+ super(context, {
+ ...options,
+ event: Events.GuildMemberUpdate,
+ });
+ }
+
+ public async run(oldMember: GuildMember, newMember: GuildMember) {
+ const beforeTimeout = oldMember.communicationDisabledUntilTimestamp ?? null;
+ const afterTimeout = newMember.communicationDisabledUntilTimestamp ?? null;
+
+ if (Boolean(beforeTimeout) === Boolean(afterTimeout)) return;
+
+ const auditEntry = await getRecentAuditLogEntry(newMember.guild, AuditLogEvent.MemberUpdate, newMember.id);
+
+ const timeoutAdded = !beforeTimeout && afterTimeout;
+ const embed = new EmbedBuilder()
+ .setTitle(timeoutAdded ? 'Member Timed Out' : 'Timeout Removed')
+ .setColor(timeoutAdded ? Colors.Orange : 0x77dd76)
+ .addFields(
+ { name: 'Member', value: `${newMember.user.tag} (${newMember.id})`, inline: false },
+ { name: 'Username', value: newMember.user.toString(), inline: true },
+ )
+ .setTimestamp();
+
+ if (auditEntry?.executor) {
+ embed.addFields({ name: 'Moderator', value: `${auditEntry.executor.tag}`, inline: true });
+ }
+
+ if (auditEntry?.reason) {
+ embed.addFields({ name: 'Reason', value: auditEntry.reason, inline: false });
+ }
+
+ if (afterTimeout) {
+ embed.addFields({
+ name: 'Expires',
+ value: ``,
+ inline: true,
+ });
+ }
+
+ await logEmbed(newMember.guild, embed);
+ }
+}
diff --git a/apps/bot/src/listeners/messageCommandDenied.ts b/apps/bot/src/listeners/messageCommandDenied.ts
index f2abcc6..b6e2989 100644
--- a/apps/bot/src/listeners/messageCommandDenied.ts
+++ b/apps/bot/src/listeners/messageCommandDenied.ts
@@ -1,11 +1,11 @@
import { Listener, type MessageCommandDeniedPayload, type UserError } from '@sapphire/framework';
export class MessageCommandDeniedListener extends Listener {
- public constructor(context: Listener.LoaderContext, options: Listener.Options) {
- super(context, { ...options, event: 'messageCommandDenied' });
- }
+ public constructor(context: Listener.LoaderContext, options: Listener.Options) {
+ super(context, { ...options, event: 'messageCommandDenied' });
+ }
- public override async run(error: UserError, { message }: MessageCommandDeniedPayload) {
- await message.reply({ content: error.message });
- }
-}
\ No newline at end of file
+ public override async run(error: UserError, { message }: MessageCommandDeniedPayload) {
+ await message.reply({ content: error.message });
+ }
+}
diff --git a/apps/bot/src/listeners/messageCreate.ts b/apps/bot/src/listeners/messageCreate.ts
index d49fedc..86f5003 100644
--- a/apps/bot/src/listeners/messageCreate.ts
+++ b/apps/bot/src/listeners/messageCreate.ts
@@ -3,42 +3,49 @@ import { Events, type Message } from 'discord.js';
import { getAutoMods } from '#lib/automod.js';
export class MessageCreateListener extends Listener {
- public constructor(context: Listener.LoaderContext, options: Listener.Options) {
- super(context, {
- ...options,
- event: Events.MessageCreate
- });
- }
-
- public async run(message: Message) {
- if (message.author.bot) return;
- if (!message.guild) return;
-
- const autoMods = await getAutoMods(message.guild.id);
- const content = message.content.toLowerCase();
-
- for (const autoMod of autoMods) {
- if (content.includes(autoMod.word.toLowerCase())) {
-
- await message.delete().catch((err) => console.error(err));
-
- const channel = message.channel;
- if (!channel.isTextBased() || !channel.isSendable()) return;
-
- await channel.send(`<@${message.author.id}>, that word is not allowed here!`).catch((err) => {
- console.error(err);
- });
-
- break;
- }
- }
-
- const moderatorIds = [...new Set((process.env.MODERATORS ?? '').split(',').map((id) => id.trim()).filter(Boolean))];
-
- if (moderatorIds.includes(message.author.id)) {
- if (content.includes('<@1494686224508522579>')) {
- await message.reply('Why hello there!').catch((err) => console.error(err));
- }
- }
- }
-}
\ No newline at end of file
+ public constructor(context: Listener.LoaderContext, options: Listener.Options) {
+ super(context, {
+ ...options,
+ event: Events.MessageCreate,
+ });
+ }
+
+ public async run(message: Message) {
+ if (message.author.bot) return;
+ if (!message.guild) return;
+
+ const autoMods = await getAutoMods(message.guild.id);
+ const content = message.content.toLowerCase();
+
+ for (const autoMod of autoMods) {
+ if (!autoMod.word.trim()) continue;
+ if (content.includes(autoMod.word.toLowerCase())) {
+ await message.delete().catch((err) => console.error(err));
+
+ const channel = message.channel;
+ if (!channel.isTextBased() || !channel.isSendable()) return;
+
+ await channel.send(`<@${message.author.id}>, that word is not allowed here!`).catch((err) => {
+ console.error(err);
+ });
+
+ break;
+ }
+ }
+
+ const moderatorIds = [
+ ...new Set(
+ (process.env.MODERATORS ?? '')
+ .split(',')
+ .map((id) => id.trim())
+ .filter(Boolean),
+ ),
+ ];
+
+ if (moderatorIds.includes(message.author.id)) {
+ if (content.includes('<@1494686224508522579>')) {
+ await message.reply('Why hello there!').catch((err) => console.error(err));
+ }
+ }
+ }
+}
diff --git a/apps/bot/src/listeners/messageDelete.ts b/apps/bot/src/listeners/messageDelete.ts
index ee7b355..608650a 100644
--- a/apps/bot/src/listeners/messageDelete.ts
+++ b/apps/bot/src/listeners/messageDelete.ts
@@ -4,27 +4,34 @@ import { removeConfessionContext } from '#lib/confessions.js';
import { isLoggingChannel, logEmbed, truncate } from '#lib/logging.js';
export class MessageDeleteListener extends Listener {
- public constructor(context: Listener.LoaderContext, options: Listener.Options) {
- super(context, { ...options, event: Events.MessageDelete });
- }
+ public constructor(context: Listener.LoaderContext, options: Listener.Options) {
+ super(context, { ...options, event: Events.MessageDelete });
+ }
- public async run(message: Message | PartialMessage) {
- const guild = message.guild;
- if (!guild) return;
- if (await isLoggingChannel(guild, message.channel?.id)) return;
+ public async run(message: Message | PartialMessage) {
+ const guild = message.guild;
+ if (!guild) return;
+ if (await isLoggingChannel(guild, message.channel?.id)) return;
- const embed = new EmbedBuilder()
- .setTitle('Message Deleted')
- .setColor(0xFF6962)
- .addFields(
- { name: 'Channel', value: message.channel?.toString() ?? 'Unknown', inline: true },
- { name: 'Author', value: message.author?.tag ?? 'Unknown', inline: true },
- { name: 'Content', value: truncate(message instanceof Object ? (message as Message).content : undefined, 1024) || '-' }
- )
- .setFooter({ text: `ID: ${message.id}` })
- .setTimestamp();
+ const content = message instanceof Object ? (message as Message).content : undefined;
+ const imageUrls = [...message.attachments.values()]
+ .filter((attachment) => attachment.contentType?.startsWith('image/'))
+ .map((attachment) => attachment.url);
+ const contentParts = [content, ...imageUrls].filter(Boolean) as string[];
+ const contentValue = truncate(contentParts.join('\n'), 1024) || '-';
- await removeConfessionContext(message.id).catch(() => null);
- await logEmbed(guild, embed);
- }
+ const embed = new EmbedBuilder()
+ .setTitle('Message Deleted')
+ .setColor(0xff6962)
+ .addFields(
+ { name: 'Channel', value: message.channel?.toString() ?? 'Unknown', inline: true },
+ { name: 'Author', value: message.author?.tag ?? 'Unknown', inline: true },
+ { name: 'Content', value: contentValue },
+ )
+ .setFooter({ text: `ID: ${message.id}` })
+ .setTimestamp();
+
+ await removeConfessionContext(message.id).catch(() => null);
+ await logEmbed(guild, embed);
+ }
}
diff --git a/apps/bot/src/listeners/messageDeleteBulk.ts b/apps/bot/src/listeners/messageDeleteBulk.ts
index 8547fa2..fb49e5b 100644
--- a/apps/bot/src/listeners/messageDeleteBulk.ts
+++ b/apps/bot/src/listeners/messageDeleteBulk.ts
@@ -4,28 +4,28 @@ import { removeConfessionContexts } from '#lib/confessions.js';
import { isLoggingChannel, logEmbed } from '#lib/logging.js';
export class MessageDeleteBulkListener extends Listener {
- public constructor(context: Listener.LoaderContext, options: Listener.Options) {
- super(context, { ...options, event: 'messageDeleteBulk' as any });
- }
+ public constructor(context: Listener.LoaderContext, options: Listener.Options) {
+ super(context, { ...options, event: 'messageDeleteBulk' as any });
+ }
- public async run(messages: Collection) {
- const first = messages.first();
- const guild = first?.guild;
- if (!guild) return;
- if (await isLoggingChannel(guild, first?.channel?.id)) return;
+ public async run(messages: Collection) {
+ const first = messages.first();
+ const guild = first?.guild;
+ if (!guild) return;
+ if (await isLoggingChannel(guild, first?.channel?.id)) return;
- const channel = first?.channel?.toString() ?? 'Unknown';
+ const channel = first?.channel?.toString() ?? 'Unknown';
- const embed = new EmbedBuilder()
- .setTitle('Bulk Messages Deleted')
- .setColor(0xFF6962)
- .addFields(
- { name: 'Channel', value: channel, inline: true },
- { name: 'Count', value: `${messages.size}`, inline: true }
- )
- .setTimestamp();
+ const embed = new EmbedBuilder()
+ .setTitle('Bulk Messages Deleted')
+ .setColor(0xff6962)
+ .addFields(
+ { name: 'Channel', value: channel, inline: true },
+ { name: 'Count', value: `${messages.size}`, inline: true },
+ )
+ .setTimestamp();
- await removeConfessionContexts([...messages.keys()]).catch(() => null);
- await logEmbed(guild, embed);
- }
+ await removeConfessionContexts([...messages.keys()]).catch(() => null);
+ await logEmbed(guild, embed);
+ }
}
diff --git a/apps/bot/src/listeners/messageUpdate.ts b/apps/bot/src/listeners/messageUpdate.ts
index 8b67e78..ab60dec 100644
--- a/apps/bot/src/listeners/messageUpdate.ts
+++ b/apps/bot/src/listeners/messageUpdate.ts
@@ -3,34 +3,47 @@ import { EmbedBuilder, type Message } from 'discord.js';
import { isLoggingChannel, logEmbed, truncate } from '#lib/logging.js';
export class MessageUpdateListener extends Listener {
- public constructor(context: Listener.LoaderContext, options: Listener.Options) {
- super(context, { ...options, event: 'messageUpdate' as any });
- }
-
- public async run(oldMessage: unknown, newMessage: unknown) {
- const oldMsg = oldMessage as Message | null;
- const newMsg = newMessage as Message;
- const guild = newMsg.guild ?? oldMsg?.guild;
- if (!guild) return;
- if (await isLoggingChannel(guild, newMsg.channel?.id ?? oldMsg?.channel?.id)) return;
-
- const oldContent = oldMsg?.content ?? '';
- const newContent = newMsg.content ?? '';
-
- if (oldContent === newContent) return;
-
- const embed = new EmbedBuilder()
- .setTitle('Message Edited')
- .setColor(0xFAC898)
- .addFields(
- { name: 'Channel', value: newMsg.channel?.toString() ?? 'Unknown', inline: true },
- { name: 'Author', value: newMsg.author?.tag ?? oldMsg?.author?.tag ?? 'Unknown', inline: true },
- { name: 'Before', value: truncate(oldMsg?.content, 1023) || '-' },
- { name: 'After', value: truncate(newMsg.content, 1023) || '-' }
- )
- .setFooter({ text: `ID: ${newMsg.id}` })
- .setTimestamp();
-
- await logEmbed(guild, embed);
- }
+ public constructor(context: Listener.LoaderContext, options: Listener.Options) {
+ super(context, { ...options, event: 'messageUpdate' as any });
+ }
+
+ public async run(oldMessage: unknown, newMessage: unknown) {
+ const oldMsg = oldMessage as Message | null;
+ const newMsg = newMessage as Message;
+ const guild = newMsg.guild ?? oldMsg?.guild;
+ if (!guild) return;
+ if (await isLoggingChannel(guild, newMsg.channel?.id ?? oldMsg?.channel?.id)) return;
+
+ const oldContent = oldMsg?.content ?? '';
+ const newContent = newMsg.content ?? '';
+
+ if (oldContent === newContent) return;
+
+ const oldImageUrls = [...(oldMsg?.attachments.values() ?? [])]
+ .filter((attachment) => attachment.contentType?.startsWith('image/'))
+ .map((attachment) => attachment.url);
+ const newImageUrls = [...newMsg.attachments.values()]
+ .filter((attachment) => attachment.contentType?.startsWith('image/'))
+ .map((attachment) => attachment.url);
+
+ const beforeParts = [oldMsg?.content, ...oldImageUrls].filter(Boolean) as string[];
+ const afterParts = [newMsg.content, ...newImageUrls].filter(Boolean) as string[];
+
+ const beforeValue = truncate(beforeParts.join('\n'), 1024) || '-';
+ const afterValue = truncate(afterParts.join('\n'), 1024) || '-';
+
+ const embed = new EmbedBuilder()
+ .setTitle('Message Edited')
+ .setColor(0xfac898)
+ .addFields(
+ { name: 'Channel', value: newMsg.channel?.toString() ?? 'Unknown', inline: true },
+ { name: 'Author', value: newMsg.author?.tag ?? oldMsg?.author?.tag ?? 'Unknown', inline: true },
+ { name: 'Before', value: beforeValue },
+ { name: 'After', value: afterValue },
+ )
+ .setFooter({ text: `ID: ${newMsg.id}` })
+ .setTimestamp();
+
+ await logEmbed(guild, embed);
+ }
}
diff --git a/apps/bot/src/listeners/ready.ts b/apps/bot/src/listeners/ready.ts
index b1eab8a..4c5d853 100644
--- a/apps/bot/src/listeners/ready.ts
+++ b/apps/bot/src/listeners/ready.ts
@@ -7,44 +7,47 @@ import { reminderScheduler } from '#lib/reminderEvent.js';
import { purgeExpiredWarns } from '#lib/warns.js';
export class ReadyListener extends Listener {
- public constructor(context: Listener.LoaderContext, options: Listener.Options) {
- super(context, {
- ...options,
- once: true,
- event: Events.ClientReady
- });
- }
-
- public async run(client: Client) {
- console.log(`Ready! Logged in as ${client.user.tag}`);
-
- client.user.setActivity({
- name: `/setup! | Shard ${client.shard?.ids?.[0] ?? 0}`,
- type: ActivityType.Custom
- });
-
- heartbeat(client);
- reminderScheduler(client);
-
- const enforceMutes = async () => {
- const mutes = await getActiveMutes();
- for (const mute of mutes) {
- const guild = client.guilds.cache.get(mute.guildId);
- if (guild) await enforceMute(guild, mute.userId).catch((err) => console.error(err));
- }
- };
-
- await enforceMutes().catch((err) => console.error(err));
- purgeExpiredWarns().catch((err) => console.error(err));
- purgeExpiredBans(client).catch((err) => console.error(err));
-
- setInterval(() => {
- purgeExpiredWarns().catch((err) => console.error(err));
- purgeExpiredBans(client).catch((err) => console.error(err));
- }, 60 * 1000); // 1 min
-
- setInterval(() => {
- enforceMutes().catch((err) => console.error(err));
- }, 30 * 60 * 1000); // 30 min
- }
-}
\ No newline at end of file
+ public constructor(context: Listener.LoaderContext, options: Listener.Options) {
+ super(context, {
+ ...options,
+ once: true,
+ event: Events.ClientReady,
+ });
+ }
+
+ public async run(client: Client) {
+ console.log(`Ready! Logged in as ${client.user.tag}`);
+
+ client.user.setActivity({
+ name: `/setup! | Shard ${client.shard?.ids?.[0] ?? 0}`,
+ type: ActivityType.Custom,
+ });
+
+ heartbeat(client);
+ reminderScheduler(client);
+
+ const enforceMutes = async () => {
+ const mutes = await getActiveMutes();
+ for (const mute of mutes) {
+ const guild = client.guilds.cache.get(mute.guildId);
+ if (guild) await enforceMute(guild, mute.userId).catch((err) => console.error(err));
+ }
+ };
+
+ await enforceMutes().catch((err) => console.error(err));
+ purgeExpiredWarns().catch((err) => console.error(err));
+ purgeExpiredBans(client).catch((err) => console.error(err));
+
+ setInterval(() => {
+ purgeExpiredWarns().catch((err) => console.error(err));
+ purgeExpiredBans(client).catch((err) => console.error(err));
+ }, 60 * 1000); // 1 min
+
+ setInterval(
+ () => {
+ enforceMutes().catch((err) => console.error(err));
+ },
+ 30 * 60 * 1000,
+ ); // 30 min
+ }
+}
diff --git a/apps/bot/src/preconditions/devMode.ts b/apps/bot/src/preconditions/devMode.ts
index 55474b2..2d1dea9 100644
--- a/apps/bot/src/preconditions/devMode.ts
+++ b/apps/bot/src/preconditions/devMode.ts
@@ -2,37 +2,37 @@ import { Precondition } from '@sapphire/framework';
import type { CommandInteraction, Message, ContextMenuCommandInteraction } from 'discord.js';
const DEV_IDS = new Set(
- (process.env['DEVIDS'] ?? '')
- .split(',')
- .map((id) => id.trim())
- .filter(Boolean)
+ (process.env['DEVIDS'] ?? '')
+ .split(',')
+ .map((id) => id.trim())
+ .filter(Boolean),
);
const DEV_MODE = process.env['DEV'] === 'true';
export class devModePrecondition extends Precondition {
- public override chatInputRun(interaction: CommandInteraction) {
- return this.check(interaction.user.id);
- }
+ public override chatInputRun(interaction: CommandInteraction) {
+ return this.check(interaction.user.id);
+ }
- public override messageRun(message: Message) {
- return this.check(message.author.id);
- }
+ public override messageRun(message: Message) {
+ return this.check(message.author.id);
+ }
- public override contextMenuRun(interaction: ContextMenuCommandInteraction) {
- return this.check(interaction.user.id);
- }
+ public override contextMenuRun(interaction: ContextMenuCommandInteraction) {
+ return this.check(interaction.user.id);
+ }
- private check(userId: string) {
- if (!DEV_MODE) return this.ok();
- if (DEV_IDS.has(userId)) return this.ok();
- return this.error({
- message: 'Please use the Official Quest Bot.\n\nThis bot is currently undergoing testing by a developer.'
- });
- }
+ private check(userId: string) {
+ if (!DEV_MODE) return this.ok();
+ if (DEV_IDS.has(userId)) return this.ok();
+ return this.error({
+ message: 'Please use the Official Quest Bot.\n\nThis bot is currently undergoing testing by a developer.',
+ });
+ }
}
declare module '@sapphire/framework' {
- interface Preconditions {
- devMode: never;
- }
-}
\ No newline at end of file
+ interface Preconditions {
+ devMode: never;
+ }
+}
diff --git a/apps/bot/src/preconditions/globalModerator.ts b/apps/bot/src/preconditions/globalModerator.ts
index 7c7c883..a54cc0d 100644
--- a/apps/bot/src/preconditions/globalModerator.ts
+++ b/apps/bot/src/preconditions/globalModerator.ts
@@ -3,27 +3,27 @@ import type { ChatInputCommandInteraction, ContextMenuCommandInteraction, Messag
import { getModeratorIds } from '#lib/confessions.js';
export class globalModeratorPrecondition extends AllFlowsPrecondition {
- public override chatInputRun(interaction: ChatInputCommandInteraction) {
- return this.check(interaction.user.id);
- }
+ public override chatInputRun(interaction: ChatInputCommandInteraction) {
+ return this.check(interaction.user.id);
+ }
- public override contextMenuRun(interaction: ContextMenuCommandInteraction) {
- return this.check(interaction.user.id);
- }
+ public override contextMenuRun(interaction: ContextMenuCommandInteraction) {
+ return this.check(interaction.user.id);
+ }
- public override messageRun(message: Message) {
- return this.check(message.author.id);
- }
+ public override messageRun(message: Message) {
+ return this.check(message.author.id);
+ }
- private check(userId: string) {
- return getModeratorIds().includes(userId)
- ? this.ok()
- : this.error({ message: 'This command is restricted to bot moderators.' });
- }
+ private check(userId: string) {
+ return getModeratorIds().includes(userId)
+ ? this.ok()
+ : this.error({ message: 'This command is restricted to bot moderators.' });
+ }
}
declare module '@sapphire/framework' {
- interface Preconditions {
- globalModerator: never;
- }
-}
\ No newline at end of file
+ interface Preconditions {
+ globalModerator: never;
+ }
+}
diff --git a/apps/bot/src/sharder.ts b/apps/bot/src/sharder.ts
index e81f67f..4a8d8c0 100644
--- a/apps/bot/src/sharder.ts
+++ b/apps/bot/src/sharder.ts
@@ -1,5 +1,11 @@
+#!/usr/bin/env node
import process from 'node:process';
import { ShardingManager } from 'discord.js';
+import { dirname, join } from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const __dirname = dirname(fileURLToPath(import.meta.url));
+const shardFile = join(__dirname, 'index.js');
const shardCountEnv = process.env.SHARD_COUNT;
let totalShards: number | 'auto' | undefined;
@@ -17,9 +23,9 @@ if (totalShards !== undefined) {
console.log('No shard count provided using what Discord recommends.');
}
-const manager = new ShardingManager('./dist/index.js', {
+const manager = new ShardingManager(shardFile, {
token: process.env.DISCORD_TOKEN,
- ...(totalShards ? { totalShards } : {})
+ ...(totalShards ? { totalShards } : {}),
});
manager.on('shardCreate', (shard) => {
diff --git a/apps/bot/src/util/collectors.ts b/apps/bot/src/util/collectors.ts
index cc27871..75a9793 100644
--- a/apps/bot/src/util/collectors.ts
+++ b/apps/bot/src/util/collectors.ts
@@ -1,30 +1,30 @@
import type { Message, MessageComponentInteraction } from 'discord.js';
export async function awaitMessageComponentSafe(
- message: Message,
- options: { filter?: (i: any) => boolean; time?: number }
+ message: Message,
+ options: { filter?: (i: any) => boolean; time?: number },
): Promise {
- return new Promise((resolve) => {
- const collector = message.createMessageComponentCollector({
- filter: options.filter ?? (() => true),
- time: options.time ?? 60_000
- } as any);
- collector.on('error', (err: unknown) => {
- console.debug('[awaitMessageComponentSafe] collector error', err);
- resolve(null);
- });
+ return new Promise((resolve) => {
+ const collector = message.createMessageComponentCollector({
+ filter: options.filter ?? (() => true),
+ time: options.time ?? 60_000,
+ } as any);
+ collector.on('error', (err: unknown) => {
+ console.debug('[awaitMessageComponentSafe] collector error', err);
+ resolve(null);
+ });
- collector.on('collect', (i: MessageComponentInteraction) => {
- collector.stop('collected');
- resolve(i);
- });
+ collector.on('collect', (i: MessageComponentInteraction) => {
+ collector.stop('collected');
+ resolve(i);
+ });
- collector.on('end', (collected: any, reason: string) => {
- if (reason === 'time' || collected.size === 0) {
- resolve(null);
- }
- });
- });
+ collector.on('end', (collected: any, reason: string) => {
+ if (reason === 'time' || collected.size === 0) {
+ resolve(null);
+ }
+ });
+ });
}
export default awaitMessageComponentSafe;
diff --git a/apps/bot/src/util/emoji.ts b/apps/bot/src/util/emoji.ts
index 163b725..31e0287 100644
--- a/apps/bot/src/util/emoji.ts
+++ b/apps/bot/src/util/emoji.ts
@@ -1,7 +1,7 @@
export const emojis = {
- // formatting emojis
- upArrow1: '<:UpArrow1:1494777244386721992>',
- rightArrow1: '<:RightArrow2:1494777243359117382>',
- rightArrow2: '<:RightArrow:1494777242075529266>',
- questUnlimited2: '<:QuestUnlimited2:1501690572870647888>'
-}
+ // formatting emojis
+ upArrow1: '<:UpArrow1:1494777244386721992>',
+ rightArrow1: '<:RightArrow2:1494777243359117382>',
+ rightArrow2: '<:RightArrow:1494777242075529266>',
+ questUnlimited2: '<:QuestUnlimited2:1501690572870647888>',
+};
diff --git a/apps/bot/src/util/heartbeat.ts b/apps/bot/src/util/heartbeat.ts
index b4150cc..7a7798b 100644
--- a/apps/bot/src/util/heartbeat.ts
+++ b/apps/bot/src/util/heartbeat.ts
@@ -1,24 +1,33 @@
import type { Client } from 'discord.js';
export function heartbeat(client: Client) {
- const pushURLs = process.env['KUMA_PUSH_URL']?.split(',').map((url) => url.trim()).filter(Boolean) ?? [];
- const shardId = client.shard?.ids?.[0] ?? 0;
- const pushURL = pushURLs[shardId] ?? pushURLs[0];
+ const pushURLs =
+ process.env.KUMA_PUSH_URL?.split(',')
+ .map((u) => u.trim())
+ .filter(Boolean) ?? [];
+ const shardId = client.shard?.ids?.[0] ?? 0;
+ const pushURL = pushURLs[shardId];
- if (!pushURL) return;
+ const push = async () => {
+ if (!pushURL || !client.isReady()) return;
- const push = async () => {
- if (!client.isReady()) return;
+ try {
+ const url = new URL(pushURL);
+ url.searchParams.set('ping', String(Math.max(0, client.ws.ping)));
+ url.searchParams.set('status', 'up');
- try {
- const url = new URL(pushURL);
- url.searchParams.set('ping', String(client.ws.ping));
- await fetch(url);
- } catch (err) {
- console.error('Push failed:', err);
- }
- };
+ const response = await fetch(url, { signal: AbortSignal.timeout(10_000) });
+ if (!response.ok) {
+ console.error(`[heartbeat] Shard ${shardId} push failed: ${response.status}`);
+ }
+ } catch (err) {
+ console.error(`[heartbeat] Shard ${shardId} push error:`, err);
+ }
+ };
- void push();
- setInterval(push, 60_000);
+ const loop = async () => {
+ await push();
+ setTimeout(loop, 60_000);
+ };
+ void loop();
}
diff --git a/apps/bot/tsconfig.eslint.json b/apps/bot/tsconfig.eslint.json
deleted file mode 100644
index ae192e2..0000000
--- a/apps/bot/tsconfig.eslint.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "$schema": "https://json.schemastore.org/tsconfig.json",
- "extends": "./tsconfig.json",
- "compilerOptions": {
- "allowJs": true
- },
- "include": ["*.ts", "*.tsx", "*.js", "*.cjs", "*.mjs", "src", "bin"]
-}
diff --git a/package.json b/package.json
index 71db1a0..8156e2e 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
"name": "quest-bot-workspace",
"version": "0.1.0",
"private": true,
- "packageManager": "pnpm@11.1.1+sha512.d1fdf5f73c617b64fa1a56a81c3c8dfe0e966e33a6010aa256b517ae77be21d93e05affc0de1a83b0e4f29d569f68b446ae8f068cd7247c0bb3df0fb4d7bdf9a",
+ "packageManager": "pnpm@11.2.2+sha512.36e6621fad506178936455e70247b8808ef4ec25797a9f437a93281a020484e2607f6a469a22e982987c3dbb8866e3071514ab10a4a1749e06edcd1ec118436f",
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev",
@@ -15,6 +15,9 @@
"prisma": "pnpm --filter @quest/bot prisma",
"clean": "turbo run build --force && rm -rf node_modules apps/*/node_modules dist .turbo"
},
+ "dependencies": {
+ "discord.js": "^14.26.4"
+ },
"engines": {
"node": ">=22.12.0"
},
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 956b28f..8133dc7 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -7,6 +7,10 @@ settings:
importers:
.:
+ dependencies:
+ discord.js:
+ specifier: ^14.26.4
+ version: 14.26.4
devDependencies:
turbo:
specifier: ^2.9.14
@@ -15,14 +19,14 @@ importers:
apps/bot:
dependencies:
'@discordjs/core':
- specifier: ^2.3.0
+ specifier: ^2.4.0
version: 2.4.0
'@prisma/adapter-pg':
- specifier: ^7.7.0
- version: 7.7.0
+ specifier: ^7.8.0
+ version: 7.8.0
'@prisma/client':
- specifier: ^7.7.0
- version: 7.7.0(prisma@7.7.0(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(typescript@5.9.3))(typescript@5.9.3)
+ specifier: ^7.8.0
+ version: 7.8.0(prisma@7.8.0(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(typescript@6.0.3))(typescript@6.0.3)
'@sapphire/framework':
specifier: ^5.5.0
version: 5.5.0
@@ -32,49 +36,40 @@ importers:
discord.js:
specifier: ^14.26.4
version: 14.26.4
- dotenv:
- specifier: ^17.4.2
- version: 17.4.2
+ ipaddr.js:
+ specifier: ^2.4.0
+ version: 2.4.0
ms:
specifier: ^2.1.3
version: 2.1.3
prisma:
- specifier: ^7.7.0
- version: 7.7.0(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(typescript@5.9.3)
+ specifier: ^7.8.0
+ version: 7.8.0(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(typescript@6.0.3)
+ sharp:
+ specifier: ^0.34.5
+ version: 0.34.5
zod:
- specifier: ^4.3.6
- version: 4.3.6
+ specifier: ^4.4.3
+ version: 4.4.3
devDependencies:
'@sapphire/ts-config':
- specifier: ^5.0.1
+ specifier: ^5.0.3
version: 5.0.3
'@types/node':
- specifier: ^22.18.8
- version: 22.19.17
+ specifier: ^25.8.0
+ version: 25.8.0
concurrently:
specifier: ^9.2.1
version: 9.2.1
- eslint:
- specifier: ^9.39.4
- version: 9.39.4(jiti@2.6.1)
- eslint-config-neon:
- specifier: ^0.2.7
- version: 0.2.9(@typescript-eslint/types@8.58.2)(@typescript-eslint/utils@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(svelte@3.59.2)(typescript@5.9.3)
- eslint-formatter-compact:
- specifier: ^8.40.0
- version: 8.40.0
- eslint-formatter-pretty:
- specifier: ^7.0.0
- version: 7.1.0
prettier:
- specifier: ^3.6.2
+ specifier: ^3.8.3
version: 3.8.3
rimraf:
specifier: ^6.1.3
version: 6.1.3
typescript:
- specifier: ~5.9.3
- version: 5.9.3
+ specifier: ~6.0.3
+ version: 6.0.3
apps/dash:
dependencies:
@@ -124,170 +119,6 @@ importers:
packages:
- '@angular-eslint/bundled-angular-compiler@20.7.0':
- resolution: {integrity: sha512-9KPz24YoiL0SvTtTX6sd1zmysU5cKOCcmpEiXkCoO3L2oYZGlVxmMT4hfSaHMt8qmfvV2KzQMoR6DZM84BwRzQ==}
-
- '@angular-eslint/eslint-plugin-template@20.7.0':
- resolution: {integrity: sha512-WFmvW2vBR6ExsSKEaActQTteyw6ikWyuJau9XmWEPFd+2eusEt/+wO21ybjDn3uc5FTp1IcdhfYy+U5OdDjH5w==}
- peerDependencies:
- '@angular-eslint/template-parser': 20.7.0
- '@typescript-eslint/types': ^7.11.0 || ^8.0.0
- '@typescript-eslint/utils': ^7.11.0 || ^8.0.0
- eslint: ^8.57.0 || ^9.0.0
- typescript: '*'
-
- '@angular-eslint/eslint-plugin@20.7.0':
- resolution: {integrity: sha512-aHH2YTiaonojsKN+y2z4IMugCwdsH/dYIjYBig6kfoSPyf9rGK4zx+gnNGq/pGRjF3bOYrmFgIviYpQVb80inQ==}
- peerDependencies:
- '@typescript-eslint/utils': ^7.11.0 || ^8.0.0
- eslint: ^8.57.0 || ^9.0.0
- typescript: '*'
-
- '@angular-eslint/template-parser@20.7.0':
- resolution: {integrity: sha512-CVskZnF38IIxVVlKWi1VCz7YH/gHMJu2IY9bD1AVoBBGIe0xA4FRXJkW2Y+EDs9vQqZTkZZljhK5gL65Ro1PeQ==}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0
- typescript: '*'
-
- '@angular-eslint/utils@20.7.0':
- resolution: {integrity: sha512-B6EJHbsk2W/lnS3kS/gm56VGvX735419z/DzgbRDcOvqMGMLwD1ILzv5OTEcL1rzpnB0AHW+IxOu6y/aCzSNUA==}
- peerDependencies:
- '@typescript-eslint/utils': ^7.11.0 || ^8.0.0
- eslint: ^8.57.0 || ^9.0.0
- typescript: '*'
-
- '@astrojs/compiler@3.0.1':
- resolution: {integrity: sha512-z97oYbdebO5aoWzuJ/8q5hLK232+17KcLZ7cJ8BCWk6+qNzVxn/gftC0KzMBUTD8WAaBkPpNSQK6PXLnNrZ0CA==}
-
- '@babel/code-frame@7.29.0':
- resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==}
- engines: {node: '>=6.9.0'}
-
- '@babel/compat-data@7.29.0':
- resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==}
- engines: {node: '>=6.9.0'}
-
- '@babel/core@7.29.0':
- resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==}
- engines: {node: '>=6.9.0'}
-
- '@babel/generator@7.29.1':
- resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-annotate-as-pure@7.27.3':
- resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-compilation-targets@7.28.6':
- resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-create-class-features-plugin@7.29.3':
- resolution: {integrity: sha512-RpLYy2sb51oNLjuu1iD3bwBqCBWUzjO0ocp+iaCP/lJtb2CPLcnC2Fftw+4sAzaMELGeWTgExSKADbdo0GFVzA==}
- engines: {node: '>=6.9.0'}
- peerDependencies:
- '@babel/core': ^7.0.0
-
- '@babel/helper-globals@7.28.0':
- resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-member-expression-to-functions@7.28.5':
- resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-module-imports@7.28.6':
- resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-module-transforms@7.28.6':
- resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==}
- engines: {node: '>=6.9.0'}
- peerDependencies:
- '@babel/core': ^7.0.0
-
- '@babel/helper-optimise-call-expression@7.27.1':
- resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-plugin-utils@7.28.6':
- resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-replace-supers@7.28.6':
- resolution: {integrity: sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==}
- engines: {node: '>=6.9.0'}
- peerDependencies:
- '@babel/core': ^7.0.0
-
- '@babel/helper-skip-transparent-expression-wrappers@7.27.1':
- resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-string-parser@7.27.1':
- resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-validator-identifier@7.28.5':
- resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-validator-option@7.27.1':
- resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helpers@7.29.2':
- resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==}
- engines: {node: '>=6.9.0'}
-
- '@babel/parser@7.29.2':
- resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==}
- engines: {node: '>=6.0.0'}
- hasBin: true
-
- '@babel/plugin-syntax-jsx@7.28.6':
- resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==}
- engines: {node: '>=6.9.0'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
- '@babel/plugin-syntax-typescript@7.28.6':
- resolution: {integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==}
- engines: {node: '>=6.9.0'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
- '@babel/plugin-transform-modules-commonjs@7.28.6':
- resolution: {integrity: sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==}
- engines: {node: '>=6.9.0'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
- '@babel/plugin-transform-typescript@7.28.6':
- resolution: {integrity: sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==}
- engines: {node: '>=6.9.0'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
- '@babel/preset-typescript@7.28.5':
- resolution: {integrity: sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==}
- engines: {node: '>=6.9.0'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
- '@babel/template@7.28.6':
- resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==}
- engines: {node: '>=6.9.0'}
-
- '@babel/traverse@7.29.0':
- resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==}
- engines: {node: '>=6.9.0'}
-
- '@babel/types@7.29.0':
- resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==}
- engines: {node: '>=6.9.0'}
-
'@discordjs/builders@1.14.1':
resolution: {integrity: sha512-gSKkhXLqs96TCzk66VZuHHl8z2bQMJFGwrXC0f33ngK+FLNau4hU1PYny3DNJfNdSH+gVMzE85/d5FQ2BpcNwQ==}
engines: {node: '>=16.11.0'}
@@ -338,366 +169,179 @@ packages:
'@electric-sql/pglite@0.4.1':
resolution: {integrity: sha512-mZ9NzzUSYPOCnxHH1oAHPRzoMFJHY472raDKwXl/+6oPbpdJ7g8LsCN4FSaIIfkiCKHhb3iF/Zqo3NYxaIhU7Q==}
- '@emnapi/core@1.10.0':
- resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==}
-
'@emnapi/runtime@1.10.0':
resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==}
- '@emnapi/wasi-threads@1.2.1':
- resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==}
-
- '@es-joy/jsdoccomment@0.78.0':
- resolution: {integrity: sha512-rQkU5u8hNAq2NVRzHnIUUvR6arbO0b6AOlvpTNS48CkiKSn/xtNfOzBK23JE4SiW89DgvU7GtxLVgV4Vn2HBAw==}
- engines: {node: '>=20.11.0'}
-
- '@es-joy/resolve.exports@1.2.0':
- resolution: {integrity: sha512-Q9hjxWI5xBM+qW2enxfe8wDKdFWMfd0Z29k5ZJnuBqD/CasY5Zryj09aCA6owbGATWz+39p5uIdaHXpopOcG8g==}
- engines: {node: '>=10'}
-
- '@esbuild/aix-ppc64@0.27.7':
- resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==}
- engines: {node: '>=18'}
- cpu: [ppc64]
- os: [aix]
-
- '@esbuild/android-arm64@0.27.7':
- resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [android]
-
- '@esbuild/android-arm@0.27.7':
- resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==}
- engines: {node: '>=18'}
- cpu: [arm]
- os: [android]
+ '@hono/node-server@1.19.11':
+ resolution: {integrity: sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g==}
+ engines: {node: '>=18.14.1'}
+ peerDependencies:
+ hono: ^4
- '@esbuild/android-x64@0.27.7':
- resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==}
+ '@img/colour@1.1.0':
+ resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
engines: {node: '>=18'}
- cpu: [x64]
- os: [android]
- '@esbuild/darwin-arm64@0.27.7':
- resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==}
- engines: {node: '>=18'}
+ '@img/sharp-darwin-arm64@0.34.5':
+ resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [darwin]
- '@esbuild/darwin-x64@0.27.7':
- resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==}
- engines: {node: '>=18'}
+ '@img/sharp-darwin-x64@0.34.5':
+ resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [darwin]
- '@esbuild/freebsd-arm64@0.27.7':
- resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==}
- engines: {node: '>=18'}
+ '@img/sharp-libvips-darwin-arm64@1.2.4':
+ resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==}
cpu: [arm64]
- os: [freebsd]
+ os: [darwin]
- '@esbuild/freebsd-x64@0.27.7':
- resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==}
- engines: {node: '>=18'}
+ '@img/sharp-libvips-darwin-x64@1.2.4':
+ resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==}
cpu: [x64]
- os: [freebsd]
+ os: [darwin]
- '@esbuild/linux-arm64@0.27.7':
- resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==}
- engines: {node: '>=18'}
+ '@img/sharp-libvips-linux-arm64@1.2.4':
+ resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
- '@esbuild/linux-arm@0.27.7':
- resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==}
- engines: {node: '>=18'}
+ '@img/sharp-libvips-linux-arm@1.2.4':
+ resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==}
cpu: [arm]
os: [linux]
+ libc: [glibc]
- '@esbuild/linux-ia32@0.27.7':
- resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==}
- engines: {node: '>=18'}
- cpu: [ia32]
- os: [linux]
-
- '@esbuild/linux-loong64@0.27.7':
- resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==}
- engines: {node: '>=18'}
- cpu: [loong64]
- os: [linux]
-
- '@esbuild/linux-mips64el@0.27.7':
- resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==}
- engines: {node: '>=18'}
- cpu: [mips64el]
- os: [linux]
-
- '@esbuild/linux-ppc64@0.27.7':
- resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==}
- engines: {node: '>=18'}
+ '@img/sharp-libvips-linux-ppc64@1.2.4':
+ resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==}
cpu: [ppc64]
os: [linux]
+ libc: [glibc]
- '@esbuild/linux-riscv64@0.27.7':
- resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==}
- engines: {node: '>=18'}
+ '@img/sharp-libvips-linux-riscv64@1.2.4':
+ resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==}
cpu: [riscv64]
os: [linux]
+ libc: [glibc]
- '@esbuild/linux-s390x@0.27.7':
- resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==}
- engines: {node: '>=18'}
+ '@img/sharp-libvips-linux-s390x@1.2.4':
+ resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==}
cpu: [s390x]
os: [linux]
+ libc: [glibc]
- '@esbuild/linux-x64@0.27.7':
- resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==}
- engines: {node: '>=18'}
+ '@img/sharp-libvips-linux-x64@1.2.4':
+ resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==}
cpu: [x64]
os: [linux]
+ libc: [glibc]
- '@esbuild/netbsd-arm64@0.27.7':
- resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==}
- engines: {node: '>=18'}
+ '@img/sharp-libvips-linuxmusl-arm64@1.2.4':
+ resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==}
cpu: [arm64]
- os: [netbsd]
+ os: [linux]
+ libc: [musl]
- '@esbuild/netbsd-x64@0.27.7':
- resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==}
- engines: {node: '>=18'}
+ '@img/sharp-libvips-linuxmusl-x64@1.2.4':
+ resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==}
cpu: [x64]
- os: [netbsd]
+ os: [linux]
+ libc: [musl]
- '@esbuild/openbsd-arm64@0.27.7':
- resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==}
- engines: {node: '>=18'}
+ '@img/sharp-linux-arm64@0.34.5':
+ resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
- os: [openbsd]
+ os: [linux]
+ libc: [glibc]
- '@esbuild/openbsd-x64@0.27.7':
- resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==}
- engines: {node: '>=18'}
+ '@img/sharp-linux-arm@0.34.5':
+ resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [arm]
+ os: [linux]
+ libc: [glibc]
+
+ '@img/sharp-linux-ppc64@0.34.5':
+ resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [glibc]
+
+ '@img/sharp-linux-riscv64@0.34.5':
+ resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [glibc]
+
+ '@img/sharp-linux-s390x@0.34.5':
+ resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [s390x]
+ os: [linux]
+ libc: [glibc]
+
+ '@img/sharp-linux-x64@0.34.5':
+ resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
- os: [openbsd]
+ os: [linux]
+ libc: [glibc]
- '@esbuild/openharmony-arm64@0.27.7':
- resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==}
- engines: {node: '>=18'}
+ '@img/sharp-linuxmusl-arm64@0.34.5':
+ resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
- os: [openharmony]
+ os: [linux]
+ libc: [musl]
- '@esbuild/sunos-x64@0.27.7':
- resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==}
- engines: {node: '>=18'}
+ '@img/sharp-linuxmusl-x64@0.34.5':
+ resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
- os: [sunos]
+ os: [linux]
+ libc: [musl]
- '@esbuild/win32-arm64@0.27.7':
- resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==}
- engines: {node: '>=18'}
+ '@img/sharp-wasm32@0.34.5':
+ resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [wasm32]
+
+ '@img/sharp-win32-arm64@0.34.5':
+ resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [win32]
- '@esbuild/win32-ia32@0.27.7':
- resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==}
- engines: {node: '>=18'}
+ '@img/sharp-win32-ia32@0.34.5':
+ resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [ia32]
os: [win32]
- '@esbuild/win32-x64@0.27.7':
- resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==}
- engines: {node: '>=18'}
+ '@img/sharp-win32-x64@0.34.5':
+ resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [win32]
- '@eslint-community/eslint-utils@4.9.1':
- resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- peerDependencies:
- eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
-
- '@eslint-community/regexpp@4.12.2':
- resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==}
- engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
-
- '@eslint/compat@1.4.1':
- resolution: {integrity: sha512-cfO82V9zxxGBxcQDr1lfaYB7wykTa0b00mGa36FrJl7iTFd0Z2cHfEYuxcBRP/iNijCsWsEkA+jzT8hGYmv33w==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.40 || 9
- peerDependenciesMeta:
- eslint:
- optional: true
-
- '@eslint/config-array@0.21.2':
- resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/config-helpers@0.4.2':
- resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/core@0.15.2':
- resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/core@0.17.0':
- resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/eslintrc@3.3.5':
- resolution: {integrity: sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/js@9.39.4':
- resolution: {integrity: sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/object-schema@2.1.7':
- resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/plugin-kit@0.3.5':
- resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/plugin-kit@0.4.1':
- resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@hono/node-server@1.19.11':
- resolution: {integrity: sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g==}
- engines: {node: '>=18.14.1'}
- peerDependencies:
- hono: ^4
-
- '@humanfs/core@0.19.1':
- resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
- engines: {node: '>=18.18.0'}
-
- '@humanfs/node@0.16.7':
- resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==}
- engines: {node: '>=18.18.0'}
-
- '@humanwhocodes/module-importer@1.0.1':
- resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
- engines: {node: '>=12.22'}
-
- '@humanwhocodes/retry@0.4.3':
- resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
- engines: {node: '>=18.18'}
-
- '@isaacs/balanced-match@4.0.1':
- resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==}
- engines: {node: 20 || >=22}
-
- '@isaacs/brace-expansion@5.0.1':
- resolution: {integrity: sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==}
- engines: {node: 20 || >=22}
-
- '@isaacs/cliui@8.0.2':
- resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
- engines: {node: '>=12'}
-
- '@jridgewell/gen-mapping@0.3.13':
- resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
-
- '@jridgewell/remapping@2.3.5':
- resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
-
- '@jridgewell/resolve-uri@3.1.2':
- resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
- engines: {node: '>=6.0.0'}
-
- '@jridgewell/sourcemap-codec@1.5.5':
- resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
-
- '@jridgewell/trace-mapping@0.3.31':
- resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
-
'@kurkle/color@0.3.4':
resolution: {integrity: sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==}
- '@microsoft/tsdoc-config@0.17.1':
- resolution: {integrity: sha512-UtjIFe0C6oYgTnad4q1QP4qXwLhe6tIpNTRStJ2RZEPIkqQPREAwE5spzVxsdn9UaEMUqhh0AqSx3X4nWAKXWw==}
-
- '@microsoft/tsdoc@0.15.1':
- resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==}
-
- '@mjackson/node-fetch-server@0.2.0':
- resolution: {integrity: sha512-EMlH1e30yzmTpGLQjlFmaDAjyOeZhng1/XCd7DExR8PNAnG/G1tyruZxEoUe11ClnwGhGrtsdnyyUx1frSzjng==}
-
- '@napi-rs/wasm-runtime@0.2.12':
- resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
-
- '@napi-rs/wasm-runtime@1.1.4':
- resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==}
- peerDependencies:
- '@emnapi/core': ^1.7.1
- '@emnapi/runtime': ^1.7.1
-
- '@next/eslint-plugin-next@15.5.15':
- resolution: {integrity: sha512-ExQoBfyKMjAUQ2nuF39ryQsG26H374ZfH13dlOZqf6TaE9ycRbIm+qUbUFCliU4BtQhiqtS7cnGA1yWfPMQ+jA==}
-
- '@nodelib/fs.scandir@2.1.5':
- resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
- engines: {node: '>= 8'}
-
- '@nodelib/fs.stat@2.0.5':
- resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
- engines: {node: '>= 8'}
-
- '@nodelib/fs.walk@1.2.8':
- resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
- engines: {node: '>= 8'}
-
- '@npmcli/config@8.3.4':
- resolution: {integrity: sha512-01rtHedemDNhUXdicU7s+QYz/3JyV5Naj84cvdXGH4mgCdL+agmSYaLF4LUG4vMCLzhBO8YtS0gPpH1FGvbgAw==}
- engines: {node: ^16.14.0 || >=18.0.0}
-
- '@npmcli/git@5.0.8':
- resolution: {integrity: sha512-liASfw5cqhjNW9UFd+ruwwdEf/lbOAQjLL2XY2dFW/bkJheXDYZgOyul/4gVvEV4BWkTXjYGmDqMw9uegdbJNQ==}
- engines: {node: ^16.14.0 || >=18.0.0}
-
- '@npmcli/map-workspaces@3.0.6':
- resolution: {integrity: sha512-tkYs0OYnzQm6iIRdfy+LcLBjcKuQCeE5YLb8KnrIlutJfheNaPvPpgoFEyEFgbjzl5PLZ3IA/BWAwRU0eHuQDA==}
- engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
-
- '@npmcli/name-from-folder@2.0.0':
- resolution: {integrity: sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==}
- engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
-
- '@npmcli/package-json@5.2.1':
- resolution: {integrity: sha512-f7zYC6kQautXHvNbLEWgD/uGu1+xCn9izgqBfgItWSx22U0ZDekxN08A1vM8cTxj/cRVe0Q94Ode+tdoYmIOOQ==}
- engines: {node: ^16.14.0 || >=18.0.0}
-
- '@npmcli/promise-spawn@7.0.2':
- resolution: {integrity: sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==}
- engines: {node: ^16.14.0 || >=18.0.0}
-
- '@oxc-project/types@0.128.0':
- resolution: {integrity: sha512-huv1Y/LzBJkBVHt3OlC7u0zHBW9qXf1FdD7sGmc1rXc2P1mTwHssYv7jyGx5KAACSCH+9B3Bhn6Z9luHRvf7pQ==}
-
- '@package-json/types@0.0.12':
- resolution: {integrity: sha512-uu43FGU34B5VM9mCNjXCwLaGHYjXdNincqKLaraaCW+7S2+SmiBg1Nv8bPnmschrIfZmfKNY9f3fC376MRrObw==}
-
- '@pkgjs/parseargs@0.11.0':
- resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
- engines: {node: '>=14'}
-
- '@pkgr/core@0.2.9':
- resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==}
- engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
+ '@prisma/adapter-pg@7.8.0':
+ resolution: {integrity: sha512-ygb3UkerK3v8MDpXVgCISdRNDozpxh6+JVJgiIGbSr5KBgz10LLf5ejUskPGoXlsIjxsOu6nuy1JVQr2EKGSlg==}
- '@prisma/adapter-pg@7.7.0':
- resolution: {integrity: sha512-q33Ta8sKbgzEpAy0lx45tAq//yMv0qcb+8nj+TCA3P4wiAY+OBFEFk/NDkZncAfHaNJeGo5WJpJdpbL+ijYx8g==}
+ '@prisma/client-runtime-utils@7.8.0':
+ resolution: {integrity: sha512-5NQZztQ0oY/ADFkmd9gPuweH5A1/CCY8YQPorLLO0Mu6a87mY5gsnDkzmFmIHs9NFaLnZojzgddFVN4RpKYrdw==}
- '@prisma/client-runtime-utils@7.7.0':
- resolution: {integrity: sha512-BLyd0UpFYOtyJFTHm7jS9vesHW7P83abibodQMiIofqjBKzDHQ1VAsQkdfvXyYDkPlONPfOTz7/rv3x/+CQqvQ==}
-
- '@prisma/client@7.7.0':
- resolution: {integrity: sha512-5Ar4OsZpJ54s21sy5oDNNW9gQtd4NuxCaiM7+JDTOU07D6VvlpLjYzAVCMB1+JzokN+08dAVomlx+b7bhJd3ww==}
+ '@prisma/client@7.8.0':
+ resolution: {integrity: sha512-HFp3Dawv/3sU3JtlPha90IB+48lS7zHiH4LKZPjmcE8YH5P9DOXGPvo8dqOtO7MqLDd1p2hOWMcFlRT1DMblHw==}
engines: {node: ^20.19 || ^22.12 || >=24.0}
peerDependencies:
prisma: '*'
@@ -708,35 +352,35 @@ packages:
typescript:
optional: true
- '@prisma/config@7.7.0':
- resolution: {integrity: sha512-hmPI3tKLO2aP0Y5vugbjcnA9qqlfJndiT6ds4tw28U5hNHLWg+mHJEWAhjsSPgxjtmxhJ/EDIeIlyh+3Us0OPg==}
+ '@prisma/config@7.8.0':
+ resolution: {integrity: sha512-HFESzd9rx2ZQxlK+TL7tu1HPvCqrHiL6LCxYykI2c34mvaUuIVVl3lYuicJD/MNnzgPnyeBEMlK4WTomJCV5jw==}
'@prisma/debug@7.2.0':
resolution: {integrity: sha512-YSGTiSlBAVJPzX4ONZmMotL+ozJwQjRmZweQNIq/ER0tQJKJynNkRB3kyvt37eOfsbMCXk3gnLF6J9OJ4QWftw==}
- '@prisma/debug@7.7.0':
- resolution: {integrity: sha512-12J62XdqCmpiwJHhHdQxZeY3ckVCWIFmcJP8hg5dPTceeiQ0wiojXGFYTluKqFQfu46fRLgb/rLALZMAx3+dTA==}
+ '@prisma/debug@7.8.0':
+ resolution: {integrity: sha512-p+QZReysDUqXC+mk17q9a+Y/qzh4c2KYliDK30buYUyfrGeTGSyfmc0AIrJRhZJrLHhRiJa9Au/J72h3C+szvA==}
'@prisma/dev@0.24.3':
resolution: {integrity: sha512-ffHlQuKXZiaDt9Go0OnCTdJZrHxK0k7omJKNV86/VjpsXu5EIHZLK0T7JSWgvNlJwh56kW9JFu9v0qJciFzepg==}
- '@prisma/driver-adapter-utils@7.7.0':
- resolution: {integrity: sha512-gZXREeu6mOk7zXfGFJgh86p7Vhj0sXNKp+4Cg1tWYo7V2dfncP2qxS2BiTmbIIha8xPqItkl0WSw38RuSq1HoQ==}
+ '@prisma/driver-adapter-utils@7.8.0':
+ resolution: {integrity: sha512-/Q13o0ZT0rjc1Xk0Q9KhZYwuq2EW/vSbWUBKfgEKkaCuB/Sg6bqnjmTZqC5cD4d6y1vfFAEwBRzfzoSMIVJ55A==}
- '@prisma/engines-version@7.6.0-1.75cbdc1eb7150937890ad5465d861175c6624711':
- resolution: {integrity: sha512-r51DLcJ8bDRSrBEJF3J4cinoWyGA7rfP2mG6lD90VqIbGNOkbfcLcXalSVjq5Y6brQS3vcjrq4GbyUb1Cb7vkw==}
+ '@prisma/engines-version@7.8.0-6.3c6e192761c0362d496ed980de936e2f3cebcd3a':
+ resolution: {integrity: sha512-fJPQxCkLgA5EayWaW8eArgCvjJ+N+Kz3VyeNKMEeYiQC4alNkxRKFVAGxv/ZUzuJISKqdw+zGeDbS6mn6RCPOA==}
- '@prisma/engines@7.7.0':
- resolution: {integrity: sha512-7fmcbT7HHXBq/b+3h/dO1JI3fd8l8q7erf7xP7pRprh58hmSSnG8mg9K3yjW3h9WaHWUwngVFpSxxxivaitQ2w==}
+ '@prisma/engines@7.8.0':
+ resolution: {integrity: sha512-jx3rCnNNrt5uzbkKlegtQ2GZHxSlihMCzutgT/BP6UIDF1r9tDI39hV/0T/cHZgzJ3ELbuQPXlVZy+Y1n0pcgw==}
- '@prisma/fetch-engine@7.7.0':
- resolution: {integrity: sha512-TfyzveBQoK4xALzsTpVhB/0KG1N8zOK0ap+RnBMkzGUu3f98fnQ4QtXa2wlKPhsO2X8a3N5ugFQgcKNoHGmDfw==}
+ '@prisma/fetch-engine@7.8.0':
+ resolution: {integrity: sha512-gwB0Euiz/DDRyxFRpLXYlK3RfaZUj1c5dAYMuhZYfApg7arknJlcb9bIsOHDppJmbqYaVA+yBIiFMDBfprsNPQ==}
'@prisma/get-platform@7.2.0':
resolution: {integrity: sha512-k1V0l0Td1732EHpAfi2eySTezyllok9dXb6UQanajkJQzPUGi3vO2z7jdkz67SypFTdmbnyGYxvEvYZdZsMAVA==}
- '@prisma/get-platform@7.7.0':
- resolution: {integrity: sha512-MEUNzvKxvYnJ7kgvd6oNRnMmmiGNS9TYLB2weMeIXplnHdL/UWEGnvavYGnN7KLJ2n0iI4dDAyzSkHI3c7AscQ==}
+ '@prisma/get-platform@7.8.0':
+ resolution: {integrity: sha512-WlxgRGnolL8VH2EmkH1R/DkKNr/mVdS3G2h42IZFFZ3eUrH9OT6t73kIOSlkkrv50wG123Iq8d96ufv5LlZktw==}
'@prisma/query-plan-executor@7.2.0':
resolution: {integrity: sha512-EOZmNzcV8uJ0mae3DhTsiHgoNCuu1J9mULQpGCh62zN3PxPTd+qI9tJvk5jOst8WHKQNwJWR3b39t0XvfBB0WQ==}
@@ -1182,199 +826,44 @@ packages:
resolution: {integrity: sha512-QGLdC9+pT74Zd7aaObqn0EUfq40c4dyTL65pFnkM6WO1QYN7Yg/s4CdH+CXmx0Zcu6wcfCWILSftXPMosJHP5A==}
engines: {node: '>=v14.0.0'}
- '@sindresorhus/base62@1.0.0':
- resolution: {integrity: sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA==}
- engines: {node: '>=18'}
-
'@standard-schema/spec@1.1.0':
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
- '@stylistic/eslint-plugin-jsx@4.4.1':
- resolution: {integrity: sha512-83SInq4u7z71vWwGG+6ViOtlOmZ6tSrDkMPhrvdBBTGMLA0gs22WSdhQ4vZP3oJ5Xg4ythvqeUiFSedvVxzhyA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: '>=9.0.0'
-
- '@stylistic/eslint-plugin-ts@4.4.1':
- resolution: {integrity: sha512-2r6cLcmdF6til66lx8esBYvBvsn7xCmLT50gw/n1rGGlTq/OxeNjBIh4c3VEaDGMa/5TybrZTia6sQUHdIWx1w==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: '>=9.0.0'
-
- '@stylistic/eslint-plugin@5.10.0':
- resolution: {integrity: sha512-nPK52ZHvot8Ju/0A4ucSX1dcPV2/1clx0kLcH5wDmrE4naKso7TUC/voUyU1O9OTKTrR6MYip6LP0ogEMQ9jPQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^9.0.0 || ^10.0.0
-
- '@tailwindcss/node@4.3.0':
- resolution: {integrity: sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==}
-
- '@tailwindcss/oxide-android-arm64@4.3.0':
- resolution: {integrity: sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng==}
- engines: {node: '>= 20'}
- cpu: [arm64]
- os: [android]
-
- '@tailwindcss/oxide-darwin-arm64@4.3.0':
- resolution: {integrity: sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ==}
- engines: {node: '>= 20'}
- cpu: [arm64]
+ '@turbo/darwin-64@2.9.14':
+ resolution: {integrity: sha512-t7QiPflaEyBE4oayeZtSmu4mEfjgIrcNlNNl1z1dmIVPqEdtA7+CfTf8d7KXsOGPh6aNgWjKxyvQg9uGfDQF+A==}
+ cpu: [x64]
os: [darwin]
- '@tailwindcss/oxide-darwin-x64@4.3.0':
- resolution: {integrity: sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA==}
- engines: {node: '>= 20'}
- cpu: [x64]
+ '@turbo/darwin-arm64@2.9.14':
+ resolution: {integrity: sha512-d23147mC9BsCPA9mJ0h/ubcpbRgcJBXbcG3+Vq7YLhjz3IXuvQsJ1UXH8f4MD76ZjJ4m/E4aRdJV+MW88CDfbw==}
+ cpu: [arm64]
os: [darwin]
- '@tailwindcss/oxide-freebsd-x64@4.3.0':
- resolution: {integrity: sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ==}
- engines: {node: '>= 20'}
+ '@turbo/linux-64@2.9.14':
+ resolution: {integrity: sha512-P3ZKB5tuUDdDQWuAsACGUR1qv9W7BNWxdxqVJ0kZNuNNPRaVYTPPikLcp79+GiEcW3npsR+KyP38lnQiBc5aSA==}
cpu: [x64]
- os: [freebsd]
-
- '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.0':
- resolution: {integrity: sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA==}
- engines: {node: '>= 20'}
- cpu: [arm]
- os: [linux]
-
- '@tailwindcss/oxide-linux-arm64-gnu@4.3.0':
- resolution: {integrity: sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg==}
- engines: {node: '>= 20'}
- cpu: [arm64]
os: [linux]
- libc: [glibc]
- '@tailwindcss/oxide-linux-arm64-musl@4.3.0':
- resolution: {integrity: sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ==}
- engines: {node: '>= 20'}
+ '@turbo/linux-arm64@2.9.14':
+ resolution: {integrity: sha512-ZRTlzcUMrrPv9ZuDzRF9n60Ym13bKeG9jDB8WjxyLhWNzV+AJQN+zdpIk3NJYf2zQsGUm1mNar2P0elRzLw25g==}
cpu: [arm64]
os: [linux]
- libc: [musl]
-
- '@tailwindcss/oxide-linux-x64-gnu@4.3.0':
- resolution: {integrity: sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==}
- engines: {node: '>= 20'}
- cpu: [x64]
- os: [linux]
- libc: [glibc]
- '@tailwindcss/oxide-linux-x64-musl@4.3.0':
- resolution: {integrity: sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==}
- engines: {node: '>= 20'}
+ '@turbo/windows-64@2.9.14':
+ resolution: {integrity: sha512-exanwN6sIduZwykYeiTQj8kCmOhazP5WOz3bvXMcYtjhL6Z3iRWLewKrXCBq0bqwSP3iBMb/AerRCnHI4lx46A==}
cpu: [x64]
- os: [linux]
- libc: [musl]
-
- '@tailwindcss/oxide-wasm32-wasi@4.3.0':
- resolution: {integrity: sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==}
- engines: {node: '>=14.0.0'}
- cpu: [wasm32]
- bundledDependencies:
- - '@napi-rs/wasm-runtime'
- - '@emnapi/core'
- - '@emnapi/runtime'
- - '@tybys/wasm-util'
- - '@emnapi/wasi-threads'
- - tslib
-
- '@tailwindcss/oxide-win32-arm64-msvc@4.3.0':
- resolution: {integrity: sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ==}
- engines: {node: '>= 20'}
- cpu: [arm64]
os: [win32]
- '@tailwindcss/oxide-win32-x64-msvc@4.3.0':
- resolution: {integrity: sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==}
- engines: {node: '>= 20'}
- cpu: [x64]
+ '@turbo/windows-arm64@2.9.14':
+ resolution: {integrity: sha512-fVdCsnmYoKICsycbWuuGp6Jvi51/3G/UluFWuAUCvR8PIW5IJkAk5BM9UF8PSm0Q2IphWHFZjYEgjHsh3B9y/g==}
+ cpu: [arm64]
os: [win32]
- '@tailwindcss/oxide@4.3.0':
- resolution: {integrity: sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==}
- engines: {node: '>= 20'}
-
- '@tailwindcss/vite@4.3.0':
- resolution: {integrity: sha512-t6J3OrB5Fc0ExuhohouH0fWUGMYL6PTLhW+E7zIk/pdbnJARZDCwjBznFnkh5ynRnIRSI4YjtTH0t6USjJISrw==}
- peerDependencies:
- vite: ^5.2.0 || ^6 || ^7 || ^8
-
- '@turbo/darwin-64@2.9.14':
- resolution: {integrity: sha512-t7QiPflaEyBE4oayeZtSmu4mEfjgIrcNlNNl1z1dmIVPqEdtA7+CfTf8d7KXsOGPh6aNgWjKxyvQg9uGfDQF+A==}
- cpu: [x64]
- os: [darwin]
-
- '@turbo/darwin-arm64@2.9.14':
- resolution: {integrity: sha512-d23147mC9BsCPA9mJ0h/ubcpbRgcJBXbcG3+Vq7YLhjz3IXuvQsJ1UXH8f4MD76ZjJ4m/E4aRdJV+MW88CDfbw==}
- cpu: [arm64]
- os: [darwin]
-
- '@turbo/linux-64@2.9.14':
- resolution: {integrity: sha512-P3ZKB5tuUDdDQWuAsACGUR1qv9W7BNWxdxqVJ0kZNuNNPRaVYTPPikLcp79+GiEcW3npsR+KyP38lnQiBc5aSA==}
- cpu: [x64]
- os: [linux]
-
- '@turbo/linux-arm64@2.9.14':
- resolution: {integrity: sha512-ZRTlzcUMrrPv9ZuDzRF9n60Ym13bKeG9jDB8WjxyLhWNzV+AJQN+zdpIk3NJYf2zQsGUm1mNar2P0elRzLw25g==}
- cpu: [arm64]
- os: [linux]
-
- '@turbo/windows-64@2.9.14':
- resolution: {integrity: sha512-exanwN6sIduZwykYeiTQj8kCmOhazP5WOz3bvXMcYtjhL6Z3iRWLewKrXCBq0bqwSP3iBMb/AerRCnHI4lx46A==}
- cpu: [x64]
- os: [win32]
-
- '@turbo/windows-arm64@2.9.14':
- resolution: {integrity: sha512-fVdCsnmYoKICsycbWuuGp6Jvi51/3G/UluFWuAUCvR8PIW5IJkAk5BM9UF8PSm0Q2IphWHFZjYEgjHsh3B9y/g==}
- cpu: [arm64]
- os: [win32]
-
- '@tybys/wasm-util@0.10.1':
- resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
-
- '@types/concat-stream@2.0.3':
- resolution: {integrity: sha512-3qe4oQAPNwVNwK4C9c8u+VJqv9kez+2MR4qJpoPFfXtgxxif1QbFusvXzK0/Wra2VX07smostI2VMmJNSpZjuQ==}
-
- '@types/debug@4.1.13':
- resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==}
-
- '@types/eslint@9.6.1':
- resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==}
-
- '@types/esrecurse@4.3.1':
- resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==}
-
- '@types/estree-jsx@1.0.5':
- resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==}
-
- '@types/estree@1.0.8':
- resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
-
- '@types/hast@3.0.4':
- resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
-
- '@types/is-empty@1.2.3':
- resolution: {integrity: sha512-4J1l5d79hoIvsrKh5VUKVRA1aIdsOb10Hu5j3J2VfP/msDnfTdGPmNp2E1Wg+vs97Bktzo+MZePFFXSGoykYJw==}
-
- '@types/json-schema@7.0.15':
- resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
-
- '@types/lodash.merge@4.6.9':
- resolution: {integrity: sha512-23sHDPmzd59kUgWyKGiOMO2Qb9YtqRO/x4IhkgNUiPQ1+5MUVqi6bCZeq9nBJ17msjIMbEIO5u+XW4Kz6aGUhQ==}
-
- '@types/lodash@4.17.24':
- resolution: {integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==}
-
- '@types/mdast@4.0.4':
- resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
-
'@types/ms@2.1.0':
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
- '@types/node@22.19.17':
- resolution: {integrity: sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==}
+ '@types/node@25.8.0':
+ resolution: {integrity: sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ==}
'@types/pg@8.20.0':
resolution: {integrity: sha512-bEPFOaMAHTEP1EzpvHTbmwR8UsFyHSKsRisLIHVMXnpNefSbGA1bD6CVy+qKjGSqmZqNqBDV2azOBo8TgkcVow==}
@@ -1387,7025 +876,1245 @@ packages:
'@types/react@19.2.14':
resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==}
- '@types/semver@7.7.1':
- resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==}
-
- '@types/supports-color@8.1.3':
- resolution: {integrity: sha512-Hy6UMpxhE3j1tLpl27exp1XqHD7n8chAiNPzWfz16LPZoMMoSc4dzLl6w9qijkEb/r5O1ozdu1CWGA2L83ZeZg==}
-
- '@types/unist@2.0.11':
- resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
-
- '@types/unist@3.0.3':
- resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
-
'@types/ws@8.18.1':
resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==}
- '@types/yargs-parser@21.0.3':
- resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==}
-
- '@types/yargs@17.0.35':
- resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==}
+ '@vladfrangu/async_event_emitter@2.4.7':
+ resolution: {integrity: sha512-Xfe6rpCTxSxfbswi/W/Pz7zp1WWSNn4A0eW4mLkQUewCrXXtMj31lCg+iQyTkh/CkusZSq9eDflu7tjEDXUY6g==}
+ engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
- '@typescript-eslint/eslint-plugin@8.58.2':
- resolution: {integrity: sha512-aC2qc5thQahutKjP+cl8cgN9DWe3ZUqVko30CMSZHnFEHyhOYoZSzkGtAI2mcwZ38xeImDucI4dnqsHiOYuuCw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- '@typescript-eslint/parser': ^8.58.2
- eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
- typescript: '>=4.8.4 <6.1.0'
+ ajv@8.20.0:
+ resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==}
- '@typescript-eslint/experimental-utils@5.62.0':
- resolution: {integrity: sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- peerDependencies:
- eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
+ ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
- '@typescript-eslint/parser@8.58.2':
- resolution: {integrity: sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
- typescript: '>=4.8.4 <6.1.0'
+ ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
- '@typescript-eslint/project-service@8.58.2':
- resolution: {integrity: sha512-Cq6UfpZZk15+r87BkIh5rDpi38W4b+Sjnb8wQCPPDDweS/LRCFjCyViEbzHk5Ck3f2QDfgmlxqSa7S7clDtlfg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- typescript: '>=4.8.4 <6.1.0'
+ aws-ssl-profiles@1.1.2:
+ resolution: {integrity: sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==}
+ engines: {node: '>= 6.0.0'}
- '@typescript-eslint/scope-manager@5.62.0':
- resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ balanced-match@4.0.4:
+ resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
+ engines: {node: 18 || 20 || >=22}
- '@typescript-eslint/scope-manager@8.58.2':
- resolution: {integrity: sha512-SgmyvDPexWETQek+qzZnrG6844IaO02UVyOLhI4wpo82dpZJY9+6YZCKAMFzXb7qhx37mFK1QcPQ18tud+vo6Q==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ better-result@2.9.2:
+ resolution: {integrity: sha512-WIFoBPCdnTOdk9inkE1ZRvCZ4P0CpSkAiLlchC65N7n9DcjZ3NhqkBOlafzpOVnO8ixyi37kicmSJ3ENhPZl7Q==}
- '@typescript-eslint/tsconfig-utils@8.58.2':
- resolution: {integrity: sha512-3SR+RukipDvkkKp/d0jP0dyzuls3DbGmwDpVEc5wqk5f38KFThakqAAO0XMirWAE+kT00oTauTbzMFGPoAzB0A==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- typescript: '>=4.8.4 <6.1.0'
+ brace-expansion@5.0.6:
+ resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==}
+ engines: {node: 18 || 20 || >=22}
- '@typescript-eslint/type-utils@8.58.2':
- resolution: {integrity: sha512-Z7EloNR/B389FvabdGeTo2XMs4W9TjtPiO9DAsmT0yom0bwlPyRjkJ1uCdW1DvrrrYP50AJZ9Xc3sByZA9+dcg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ c12@3.3.4:
+ resolution: {integrity: sha512-cM0ApFQSBXuourJejzwv/AuPRvAxordTyParRVcHjjtXirtkzM0uK2L9TTn9s0cXZbG7E55jCivRQzoxYmRAlA==}
peerDependencies:
- eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
- typescript: '>=4.8.4 <6.1.0'
+ magicast: '*'
+ peerDependenciesMeta:
+ magicast:
+ optional: true
- '@typescript-eslint/types@5.62.0':
- resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ chalk@4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
- '@typescript-eslint/types@8.58.2':
- resolution: {integrity: sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ chart.js@4.5.1:
+ resolution: {integrity: sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==}
+ engines: {pnpm: '>=8'}
- '@typescript-eslint/typescript-estree@5.62.0':
- resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- peerDependencies:
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
+ chokidar@5.0.0:
+ resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==}
+ engines: {node: '>= 20.19.0'}
- '@typescript-eslint/typescript-estree@8.58.2':
- resolution: {integrity: sha512-ELGuoofuhhoCvNbQjFFiobFcGgcDCEm0ThWdmO4Z0UzLqPXS3KFvnEZ+SHewwOYHjM09tkzOWXNTv9u6Gqtyuw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- typescript: '>=4.8.4 <6.1.0'
+ cliui@8.0.1:
+ resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
+ engines: {node: '>=12'}
- '@typescript-eslint/utils@5.62.0':
- resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- peerDependencies:
- eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
+ color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
- '@typescript-eslint/utils@8.58.2':
- resolution: {integrity: sha512-QZfjHNEzPY8+l0+fIXMvuQ2sJlplB4zgDZvA+NmvZsZv3EQwOcc1DuIU1VJUTWZ/RKouBMhDyNaBMx4sWvrzRA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
- typescript: '>=4.8.4 <6.1.0'
+ color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
- '@typescript-eslint/visitor-keys@5.62.0':
- resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ concurrently@9.2.1:
+ resolution: {integrity: sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==}
+ engines: {node: '>=18'}
+ hasBin: true
- '@typescript-eslint/visitor-keys@8.58.2':
- resolution: {integrity: sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ confbox@0.2.4:
+ resolution: {integrity: sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==}
- '@unrs/resolver-binding-android-arm-eabi@1.11.1':
- resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==}
- cpu: [arm]
- os: [android]
+ cross-spawn@7.0.6:
+ resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
+ engines: {node: '>= 8'}
- '@unrs/resolver-binding-android-arm64@1.11.1':
- resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==}
- cpu: [arm64]
- os: [android]
+ csstype@3.2.3:
+ resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
- '@unrs/resolver-binding-darwin-arm64@1.11.1':
- resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==}
- cpu: [arm64]
- os: [darwin]
+ deepmerge-ts@7.1.5:
+ resolution: {integrity: sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==}
+ engines: {node: '>=16.0.0'}
- '@unrs/resolver-binding-darwin-x64@1.11.1':
- resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==}
- cpu: [x64]
- os: [darwin]
+ defu@6.1.7:
+ resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==}
- '@unrs/resolver-binding-freebsd-x64@1.11.1':
- resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==}
- cpu: [x64]
- os: [freebsd]
+ denque@2.1.0:
+ resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
+ engines: {node: '>=0.10'}
- '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1':
- resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==}
- cpu: [arm]
- os: [linux]
+ destr@2.0.5:
+ resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==}
- '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1':
- resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==}
- cpu: [arm]
- os: [linux]
+ detect-libc@2.1.2:
+ resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
+ engines: {node: '>=8'}
- '@unrs/resolver-binding-linux-arm64-gnu@1.11.1':
- resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==}
- cpu: [arm64]
- os: [linux]
- libc: [glibc]
+ discord-api-types@0.38.47:
+ resolution: {integrity: sha512-XgXQodHQBAE6kfD7kMvVo30863iHX1LHSqNq6MGUTDwIFCCvHva13+rwxyxVXDqudyApMNAd32PGjgVETi5rjA==}
- '@unrs/resolver-binding-linux-arm64-musl@1.11.1':
- resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==}
- cpu: [arm64]
- os: [linux]
- libc: [musl]
+ discord.js@14.26.4:
+ resolution: {integrity: sha512-4oBp8tc6Kf8IDBwAHhbsMaAqx1b5fob9SNasZT7V6yyyUydoO5i5fGuX7TmvRtR+q/WgKRnRViRoAWnG7fNyvA==}
+ engines: {node: '>=18'}
- '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
- resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==}
- cpu: [ppc64]
- os: [linux]
- libc: [glibc]
+ dotenv@17.4.2:
+ resolution: {integrity: sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==}
+ engines: {node: '>=12'}
- '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
- resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==}
- cpu: [riscv64]
- os: [linux]
- libc: [glibc]
+ effect@3.20.0:
+ resolution: {integrity: sha512-qMLfDJscrNG8p/aw+IkT9W7fgj50Z4wG5bLBy0Txsxz8iUHjDIkOgO3SV0WZfnQbNG2VJYb0b+rDLMrhM4+Krw==}
- '@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
- resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==}
- cpu: [riscv64]
- os: [linux]
- libc: [musl]
+ emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
- '@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
- resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==}
- cpu: [s390x]
- os: [linux]
- libc: [glibc]
+ empathic@2.0.0:
+ resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==}
+ engines: {node: '>=14'}
- '@unrs/resolver-binding-linux-x64-gnu@1.11.1':
- resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==}
- cpu: [x64]
- os: [linux]
- libc: [glibc]
+ env-paths@3.0.0:
+ resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
- '@unrs/resolver-binding-linux-x64-musl@1.11.1':
- resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==}
- cpu: [x64]
- os: [linux]
- libc: [musl]
+ escalade@3.2.0:
+ resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
+ engines: {node: '>=6'}
- '@unrs/resolver-binding-wasm32-wasi@1.11.1':
- resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==}
- engines: {node: '>=14.0.0'}
- cpu: [wasm32]
+ exsolve@1.0.8:
+ resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==}
- '@unrs/resolver-binding-win32-arm64-msvc@1.11.1':
- resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==}
- cpu: [arm64]
- os: [win32]
+ fast-check@3.23.2:
+ resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==}
+ engines: {node: '>=8.0.0'}
- '@unrs/resolver-binding-win32-ia32-msvc@1.11.1':
- resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==}
- cpu: [ia32]
- os: [win32]
+ fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
- '@unrs/resolver-binding-win32-x64-msvc@1.11.1':
- resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==}
- cpu: [x64]
- os: [win32]
+ fast-uri@3.1.2:
+ resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==}
- '@vladfrangu/async_event_emitter@2.4.7':
- resolution: {integrity: sha512-Xfe6rpCTxSxfbswi/W/Pz7zp1WWSNn4A0eW4mLkQUewCrXXtMj31lCg+iQyTkh/CkusZSq9eDflu7tjEDXUY6g==}
- engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
+ foreground-child@3.3.1:
+ resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
+ engines: {node: '>=14'}
- abbrev@2.0.0:
- resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==}
- engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+ generate-function@2.3.1:
+ resolution: {integrity: sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==}
- accepts@1.3.8:
- resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
- engines: {node: '>= 0.6'}
+ get-caller-file@2.0.5:
+ resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+ engines: {node: 6.* || 8.* || >= 10.*}
- acorn-jsx@5.3.2:
- resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
- peerDependencies:
- acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+ get-port-please@3.2.0:
+ resolution: {integrity: sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A==}
- acorn@8.16.0:
- resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==}
- engines: {node: '>=0.4.0'}
+ giget@3.2.0:
+ resolution: {integrity: sha512-GvHTWcykIR/fP8cj8dMpuMMkvaeJfPvYnhq0oW+chSeIr+ldX21ifU2Ms6KBoyKZQZmVaUAAhQ2EZ68KJF8a7A==}
hasBin: true
- ajv@6.14.0:
- resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==}
-
- ajv@8.12.0:
- resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==}
+ glob@13.0.6:
+ resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==}
+ engines: {node: 18 || 20 || >=22}
- ansi-escapes@7.3.0:
- resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==}
- engines: {node: '>=18'}
+ graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
- ansi-regex@5.0.1:
- resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
- engines: {node: '>=8'}
+ grammex@3.1.12:
+ resolution: {integrity: sha512-6ufJOsSA7LcQehIJNCO7HIBykfM7DXQual0Ny780/DEcJIpBlHRvcqEBWGPYd7hrXL2GJ3oJI1MIhaXjWmLQOQ==}
- ansi-regex@6.2.2:
- resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==}
- engines: {node: '>=12'}
+ graphmatch@1.1.1:
+ resolution: {integrity: sha512-5ykVn/EXM1hF0XCaWh05VbYvEiOL2lY1kBxZtaYsyvjp7cmWOU1XsAdfQBwClraEofXDT197lFbXOEVMHpvQOg==}
- ansi-styles@4.3.0:
- resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
- ansi-styles@6.2.3:
- resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
- engines: {node: '>=12'}
+ hono@4.12.19:
+ resolution: {integrity: sha512-xa3eYXYXx68XTT4hZ7dRzsXBhaq85ToSrlUJNoR0gwz/1Ap/CNwX47wfvV7pc/xWhjKVVkLT7zBJy8chhNguqQ==}
+ engines: {node: '>=16.9.0'}
- are-docs-informative@0.0.2:
- resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==}
- engines: {node: '>=14'}
+ http-status-codes@2.3.0:
+ resolution: {integrity: sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==}
- arg@5.0.2:
- resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
+ iconv-lite@0.7.2:
+ resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==}
+ engines: {node: '>=0.10.0'}
- argparse@2.0.1:
- resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+ ipaddr.js@2.4.0:
+ resolution: {integrity: sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==}
+ engines: {node: '>= 10'}
- aria-query@5.3.2:
- resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
- engines: {node: '>= 0.4'}
+ is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
- array-buffer-byte-length@1.0.2:
- resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==}
- engines: {node: '>= 0.4'}
+ is-property@1.0.2:
+ resolution: {integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==}
- array-flatten@1.1.1:
- resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
+ isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
- array-includes@3.1.9:
- resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==}
- engines: {node: '>= 0.4'}
+ jiti@2.7.0:
+ resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==}
+ hasBin: true
- array-union@2.1.0:
- resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
- engines: {node: '>=8'}
+ json-schema-traverse@1.0.0:
+ resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
- array.prototype.findlast@1.2.5:
- resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==}
- engines: {node: '>= 0.4'}
+ lodash.snakecase@4.1.1:
+ resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==}
- array.prototype.flat@1.3.3:
- resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==}
- engines: {node: '>= 0.4'}
+ lodash@4.18.1:
+ resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==}
- array.prototype.flatmap@1.3.3:
- resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==}
- engines: {node: '>= 0.4'}
+ long@5.3.2:
+ resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==}
- array.prototype.tosorted@1.1.4:
- resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==}
- engines: {node: '>= 0.4'}
+ lru-cache@11.3.6:
+ resolution: {integrity: sha512-Gf/KoL3C/MlI7Bt0PGI9I+TeTC/I6r/csU58N4BSNc4lppLBeKsOdFYkK+dX0ABDUMJNfCHTyPpzwwO21Awd3A==}
+ engines: {node: 20 || >=22}
- arraybuffer.prototype.slice@1.0.4:
- resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==}
- engines: {node: '>= 0.4'}
+ lru.min@1.1.4:
+ resolution: {integrity: sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==}
+ engines: {bun: '>=1.0.0', deno: '>=1.30.0', node: '>=8.0.0'}
- ast-types-flow@0.0.8:
- resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==}
+ magic-bytes.js@1.13.0:
+ resolution: {integrity: sha512-afO2mnxW7GDTXMm5/AoN1WuOcdoKhtgXjIvHmobqTD1grNplhGdv3PFOyjCVmrnOZBIT/gD/koDKpYG+0mvHcg==}
- astro-eslint-parser@1.4.0:
- resolution: {integrity: sha512-+QDcgc7e+au6EZ0YjMmRRjNoQo5bDMlaR45aWDoFsuxQTCM9qmCHRoiKJPELgckJ8Wmr7vcfpa9eCDHBFh6G4w==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ minimatch@10.2.5:
+ resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==}
+ engines: {node: 18 || 20 || >=22}
- astrojs-compiler-sync@1.1.1:
- resolution: {integrity: sha512-0mKvB9sDQRIZPsEJadw6OaFbGJ92cJPPR++ICca9XEyiUAZqgVuk25jNmzHPT0KF80rI94trSZrUR5iHFXGGOQ==}
- engines: {node: ^18.18.0 || >=20.9.0}
- peerDependencies:
- '@astrojs/compiler': '>=0.27.0'
+ minipass@7.1.3:
+ resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==}
+ engines: {node: '>=16 || 14 >=14.17'}
- async-function@1.0.0:
- resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
- engines: {node: '>= 0.4'}
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
- available-typed-arrays@1.0.7:
- resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
- engines: {node: '>= 0.4'}
+ mysql2@3.15.3:
+ resolution: {integrity: sha512-FBrGau0IXmuqg4haEZRBfHNWB5mUARw6hNwPDXXGg0XzVJ50mr/9hb267lvpVMnhZ1FON3qNd4Xfcez1rbFwSg==}
+ engines: {node: '>= 8.0'}
- aws-ssl-profiles@1.1.2:
- resolution: {integrity: sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==}
- engines: {node: '>= 6.0.0'}
+ named-placeholders@1.1.6:
+ resolution: {integrity: sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==}
+ engines: {node: '>=8.0.0'}
- axe-core@4.11.3:
- resolution: {integrity: sha512-zBQouZixDTbo3jMGqHKyePxYxr1e5W8UdTmBQ7sNtaA9M2bE32daxxPLS/jojhKOHxQ7LWwPjfiwf/fhaJWzlg==}
- engines: {node: '>=4'}
+ ohash@2.0.11:
+ resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==}
- axobject-query@4.1.0:
- resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
- engines: {node: '>= 0.4'}
+ package-json-from-dist@1.0.1:
+ resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
- babel-dead-code-elimination@1.0.12:
- resolution: {integrity: sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig==}
+ path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
- bail@2.0.2:
- resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
+ path-scurry@2.0.2:
+ resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==}
+ engines: {node: 18 || 20 || >=22}
- balanced-match@1.0.2:
- resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+ pathe@2.0.3:
+ resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
- balanced-match@4.0.4:
- resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
- engines: {node: 18 || 20 || >=22}
+ perfect-debounce@2.1.0:
+ resolution: {integrity: sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==}
- baseline-browser-mapping@2.10.19:
- resolution: {integrity: sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g==}
- engines: {node: '>=6.0.0'}
- hasBin: true
+ pg-cloudflare@1.3.0:
+ resolution: {integrity: sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==}
- basic-auth@2.0.1:
- resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==}
- engines: {node: '>= 0.8'}
+ pg-connection-string@2.12.0:
+ resolution: {integrity: sha512-U7qg+bpswf3Cs5xLzRqbXbQl85ng0mfSV/J0nnA31MCLgvEaAo7CIhmeyrmJpOr7o+zm0rXK+hNnT5l9RHkCkQ==}
- bent@7.3.12:
- resolution: {integrity: sha512-T3yrKnVGB63zRuoco/7Ybl7BwwGZR0lceoVG5XmQyMIH9s19SV5m+a8qam4if0zQuAmOQTyPTPmsQBdAorGK3w==}
+ pg-int8@1.0.1:
+ resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
+ engines: {node: '>=4.0.0'}
- better-result@2.8.2:
- resolution: {integrity: sha512-YOf0VSj5nUPI27doTtXF+BBnsiRq3qY7avHqfIWnppxTLGyvkLq1QV2RTxkwoZwJ60ywLfZ0raFF4J/G886i7A==}
+ pg-pool@3.13.0:
+ resolution: {integrity: sha512-gB+R+Xud1gLFuRD/QgOIgGOBE2KCQPaPwkzBBGC9oG69pHTkhQeIuejVIk3/cnDyX39av2AxomQiyPT13WKHQA==}
+ peerDependencies:
+ pg: '>=8.0'
- body-parser@1.20.5:
- resolution: {integrity: sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==}
- engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
+ pg-protocol@1.13.0:
+ resolution: {integrity: sha512-zzdvXfS6v89r6v7OcFCHfHlyG/wvry1ALxZo4LqgUoy7W9xhBDMaqOuMiF3qEV45VqsN6rdlcehHrfDtlCPc8w==}
- boolbase@1.0.0:
- resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
+ pg-types@2.2.0:
+ resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
+ engines: {node: '>=4'}
- brace-expansion@1.1.14:
- resolution: {integrity: sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==}
+ pg@8.20.0:
+ resolution: {integrity: sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA==}
+ engines: {node: '>= 16.0.0'}
+ peerDependencies:
+ pg-native: '>=3.0.1'
+ peerDependenciesMeta:
+ pg-native:
+ optional: true
- brace-expansion@2.1.0:
- resolution: {integrity: sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==}
+ pgpass@1.0.5:
+ resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==}
- brace-expansion@5.0.5:
- resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==}
- engines: {node: 18 || 20 || >=22}
+ pkg-types@2.3.1:
+ resolution: {integrity: sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==}
- braces@3.0.3:
- resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
- engines: {node: '>=8'}
+ postgres-array@2.0.0:
+ resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
+ engines: {node: '>=4'}
- browserslist@4.28.2:
- resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==}
- engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
- hasBin: true
+ postgres-array@3.0.4:
+ resolution: {integrity: sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ==}
+ engines: {node: '>=12'}
- buffer-from@1.1.2:
- resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
+ postgres-bytea@1.0.1:
+ resolution: {integrity: sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==}
+ engines: {node: '>=0.10.0'}
- builtin-modules@3.3.0:
- resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==}
- engines: {node: '>=6'}
+ postgres-date@1.0.7:
+ resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
+ engines: {node: '>=0.10.0'}
- builtin-modules@5.1.0:
- resolution: {integrity: sha512-c5JxaDrzwRjq3WyJkI1AGR5xy6Gr6udlt7sQPbl09+3ckB+Zo2qqQ2KhCTBr7Q8dHB43bENGYEk4xddrFH/b7A==}
- engines: {node: '>=18.20'}
+ postgres-interval@1.2.0:
+ resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
+ engines: {node: '>=0.10.0'}
- bytes@3.1.2:
- resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
- engines: {node: '>= 0.8'}
+ postgres@3.4.7:
+ resolution: {integrity: sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==}
+ engines: {node: '>=12'}
- bytesish@0.4.4:
- resolution: {integrity: sha512-i4uu6M4zuMUiyfZN4RU2+i9+peJh//pXhd9x1oSe1LBkZ3LEbCoygu8W0bXTukU1Jme2txKuotpCZRaC3FLxcQ==}
+ prettier@3.8.3:
+ resolution: {integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==}
+ engines: {node: '>=14'}
+ hasBin: true
- c12@3.1.0:
- resolution: {integrity: sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==}
+ prisma@7.8.0:
+ resolution: {integrity: sha512-yfN4yrw7HV9kEJhoy1+jgah0jafEIQsf7uWouSsM8MvJtlubsk+kM7AIBWZ8+GJl74Yj3c+nbYqBkMOxtsZ3Lw==}
+ engines: {node: ^20.19 || ^22.12 || >=24.0}
+ hasBin: true
peerDependencies:
- magicast: ^0.3.5
+ better-sqlite3: '>=9.0.0'
+ typescript: '>=5.4.0'
peerDependenciesMeta:
- magicast:
+ better-sqlite3:
+ optional: true
+ typescript:
optional: true
- cac@6.7.14:
- resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
- engines: {node: '>=8'}
+ proper-lockfile@4.1.2:
+ resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==}
- call-bind-apply-helpers@1.0.2:
- resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
- engines: {node: '>= 0.4'}
+ pure-rand@6.1.0:
+ resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==}
- call-bind@1.0.9:
- resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==}
- engines: {node: '>= 0.4'}
+ rc9@3.0.1:
+ resolution: {integrity: sha512-gMDyleLWVE+i6Sgtc0QbbY6pEKqYs97NGi6isHQPqYlLemPoO8dxQ3uGi0f4NiP98c+jMW6cG1Kx9dDwfvqARQ==}
- call-bound@1.0.4:
- resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
- engines: {node: '>= 0.4'}
+ react-dom@19.2.5:
+ resolution: {integrity: sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==}
+ peerDependencies:
+ react: ^19.2.5
- callsites@3.1.0:
- resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
- engines: {node: '>=6'}
+ react@19.2.5:
+ resolution: {integrity: sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==}
+ engines: {node: '>=0.10.0'}
- caniuse-lite@1.0.30001788:
- resolution: {integrity: sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==}
+ readdirp@5.0.0:
+ resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==}
+ engines: {node: '>= 20.19.0'}
- caseless@0.12.0:
- resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==}
+ remeda@2.33.4:
+ resolution: {integrity: sha512-ygHswjlc/opg2VrtiYvUOPLjxjtdKvjGz1/plDhkG66hjNjFr1xmfrs2ClNFo/E6TyUFiwYNh53bKV26oBoMGQ==}
- ccount@2.0.1:
- resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
+ require-directory@2.1.1:
+ resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+ engines: {node: '>=0.10.0'}
- chalk@4.1.2:
- resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
- engines: {node: '>=10'}
+ require-from-string@2.0.2:
+ resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
+ engines: {node: '>=0.10.0'}
- chalk@5.6.2:
- resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==}
- engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
+ retry@0.12.0:
+ resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==}
+ engines: {node: '>= 4'}
- change-case@5.4.4:
- resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==}
+ rimraf@6.1.3:
+ resolution: {integrity: sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==}
+ engines: {node: 20 || >=22}
+ hasBin: true
- character-entities-html4@2.1.0:
- resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
+ rxjs@7.8.2:
+ resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==}
- character-entities-legacy@3.0.0:
- resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
+ safer-buffer@2.1.2:
+ resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
- character-entities@2.0.2:
- resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
+ scheduler@0.27.0:
+ resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
- character-reference-invalid@2.0.1:
- resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
+ semver@7.8.0:
+ resolution: {integrity: sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==}
+ engines: {node: '>=10'}
+ hasBin: true
- chart.js@4.5.1:
- resolution: {integrity: sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==}
- engines: {pnpm: '>=8'}
+ seq-queue@0.0.5:
+ resolution: {integrity: sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==}
- chokidar@4.0.3:
- resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
- engines: {node: '>= 14.16.0'}
+ sharp@0.34.5:
+ resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- ci-info@4.4.0:
- resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==}
+ shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
engines: {node: '>=8'}
- citty@0.1.6:
- resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==}
-
- citty@0.2.2:
- resolution: {integrity: sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==}
-
- clean-regexp@1.0.0:
- resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==}
- engines: {node: '>=4'}
-
- cliui@8.0.1:
- resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
- engines: {node: '>=12'}
-
- color-convert@2.0.1:
- resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
- engines: {node: '>=7.0.0'}
+ shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
- color-name@1.1.4:
- resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+ shell-quote@1.8.3:
+ resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==}
+ engines: {node: '>= 0.4'}
- comment-parser@1.4.1:
- resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==}
- engines: {node: '>= 12.0.0'}
+ signal-exit@3.0.7:
+ resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
- comment-parser@1.4.6:
- resolution: {integrity: sha512-ObxuY6vnbWTN6Od72xfwN9DbzC7Y2vv8u1Soi9ahRKL37gb6y1qk6/dgjs+3JWuXJHWvsg3BXIwzd/rkmAwavg==}
- engines: {node: '>= 12.0.0'}
+ signal-exit@4.1.0:
+ resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+ engines: {node: '>=14'}
- common-tags@1.8.2:
- resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==}
- engines: {node: '>=4.0.0'}
+ split2@4.2.0:
+ resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
+ engines: {node: '>= 10.x'}
- compressible@2.0.18:
- resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==}
+ sqlstring@2.3.3:
+ resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==}
engines: {node: '>= 0.6'}
- compression@1.8.1:
- resolution: {integrity: sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==}
- engines: {node: '>= 0.8.0'}
-
- concat-map@0.0.1:
- resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
-
- concat-stream@2.0.0:
- resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==}
- engines: {'0': node >= 6.0}
-
- concurrently@9.2.1:
- resolution: {integrity: sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==}
- engines: {node: '>=18'}
- hasBin: true
-
- confbox@0.2.4:
- resolution: {integrity: sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==}
-
- consola@3.4.2:
- resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==}
- engines: {node: ^14.18.0 || >=16.10.0}
-
- content-disposition@0.5.4:
- resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
- engines: {node: '>= 0.6'}
+ std-env@3.10.0:
+ resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
- content-type@1.0.5:
- resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
- engines: {node: '>= 0.6'}
+ string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
- convert-source-map@2.0.0:
- resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+ strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
- cookie-signature@1.0.7:
- resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==}
+ supports-color@7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
- cookie@0.7.2:
- resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
- engines: {node: '>= 0.6'}
+ supports-color@8.1.1:
+ resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
+ engines: {node: '>=10'}
- cookie@1.1.1:
- resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==}
- engines: {node: '>=18'}
+ tree-kill@1.2.2:
+ resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
+ hasBin: true
- core-js-compat@3.49.0:
- resolution: {integrity: sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==}
+ ts-mixer@6.0.4:
+ resolution: {integrity: sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==}
- cross-spawn@7.0.6:
- resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
- engines: {node: '>= 8'}
+ tslib@2.8.1:
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
- cssesc@3.0.0:
- resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
- engines: {node: '>=4'}
+ turbo@2.9.14:
+ resolution: {integrity: sha512-BQqXRr4UoWI3UPFrtznCLykYHxwxWh53iCB57x092jPMjIlW1wnm3N895g5irpiXmnxUhREBB0n6+y8BHhs4nw==}
hasBin: true
- csstype@3.2.3:
- resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
-
- damerau-levenshtein@1.0.8:
- resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
+ typescript@5.4.5:
+ resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==}
+ engines: {node: '>=14.17'}
+ hasBin: true
- data-view-buffer@1.0.2:
- resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==}
- engines: {node: '>= 0.4'}
+ typescript@6.0.3:
+ resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==}
+ engines: {node: '>=14.17'}
+ hasBin: true
- data-view-byte-length@1.0.2:
- resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==}
- engines: {node: '>= 0.4'}
+ undici-types@7.24.6:
+ resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==}
- data-view-byte-offset@1.0.1:
- resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==}
- engines: {node: '>= 0.4'}
+ undici@6.24.1:
+ resolution: {integrity: sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==}
+ engines: {node: '>=18.17'}
- debug@2.6.9:
- resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
+ valibot@1.2.0:
+ resolution: {integrity: sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==}
peerDependencies:
- supports-color: '*'
+ typescript: '>=5'
peerDependenciesMeta:
- supports-color:
+ typescript:
optional: true
- debug@4.4.3:
- resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
- engines: {node: '>=6.0'}
- peerDependencies:
- supports-color: '*'
- peerDependenciesMeta:
- supports-color:
- optional: true
+ which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
- decamelize@5.0.1:
- resolution: {integrity: sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==}
+ wrap-ansi@7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}
- decode-named-character-reference@1.3.0:
- resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==}
-
- dedent@1.7.2:
- resolution: {integrity: sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==}
- peerDependencies:
- babel-plugin-macros: ^3.1.0
- peerDependenciesMeta:
- babel-plugin-macros:
- optional: true
-
- deep-is@0.1.4:
- resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
-
- deepmerge-ts@7.1.5:
- resolution: {integrity: sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==}
- engines: {node: '>=16.0.0'}
-
- define-data-property@1.1.4:
- resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
- engines: {node: '>= 0.4'}
-
- define-properties@1.2.1:
- resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
- engines: {node: '>= 0.4'}
-
- defu@6.1.7:
- resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==}
-
- denque@2.1.0:
- resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
- engines: {node: '>=0.10'}
-
- depd@2.0.0:
- resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
- engines: {node: '>= 0.8'}
-
- dequal@2.0.3:
- resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
- engines: {node: '>=6'}
-
- destr@2.0.5:
- resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==}
-
- destroy@1.2.0:
- resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
- engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
-
- detect-libc@2.1.2:
- resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
- engines: {node: '>=8'}
-
- devlop@1.1.0:
- resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
-
- dir-glob@3.0.1:
- resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
- engines: {node: '>=8'}
-
- discord-api-types@0.38.47:
- resolution: {integrity: sha512-XgXQodHQBAE6kfD7kMvVo30863iHX1LHSqNq6MGUTDwIFCCvHva13+rwxyxVXDqudyApMNAd32PGjgVETi5rjA==}
-
- discord.js@14.26.4:
- resolution: {integrity: sha512-4oBp8tc6Kf8IDBwAHhbsMaAqx1b5fob9SNasZT7V6yyyUydoO5i5fGuX7TmvRtR+q/WgKRnRViRoAWnG7fNyvA==}
- engines: {node: '>=18'}
-
- doctrine@2.1.0:
- resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
- engines: {node: '>=0.10.0'}
-
- dotenv@16.6.1:
- resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==}
- engines: {node: '>=12'}
-
- dotenv@17.4.2:
- resolution: {integrity: sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==}
- engines: {node: '>=12'}
-
- dunder-proto@1.0.1:
- resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
- engines: {node: '>= 0.4'}
-
- eastasianwidth@0.2.0:
- resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
-
- ee-first@1.1.1:
- resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
-
- effect@3.20.0:
- resolution: {integrity: sha512-qMLfDJscrNG8p/aw+IkT9W7fgj50Z4wG5bLBy0Txsxz8iUHjDIkOgO3SV0WZfnQbNG2VJYb0b+rDLMrhM4+Krw==}
-
- electron-to-chromium@1.5.340:
- resolution: {integrity: sha512-908qahOGocRMinT2nM3ajCEM99H4iPdv84eagPP3FfZy/1ZGeOy2CZYzjhms81ckOPCXPlW7LkY4XpxD8r1DrA==}
-
- emoji-regex@10.6.0:
- resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==}
-
- emoji-regex@8.0.0:
- resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
-
- emoji-regex@9.2.2:
- resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
-
- empathic@2.0.0:
- resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==}
- engines: {node: '>=14'}
-
- encodeurl@2.0.0:
- resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
- engines: {node: '>= 0.8'}
-
- enhanced-resolve@5.20.1:
- resolution: {integrity: sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==}
- engines: {node: '>=10.13.0'}
-
- enhanced-resolve@5.21.2:
- resolution: {integrity: sha512-xe9vQb5kReirPUxgQrXA3ihgbCqssmTiM7cOZ+Gzu+VeGWgpV98lLZvp0dl4yriyAePcewxGUs9UpKD8PET9KQ==}
- engines: {node: '>=10.13.0'}
-
- entities@7.0.1:
- resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==}
- engines: {node: '>=0.12'}
-
- env-paths@3.0.0:
- resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
- environment@1.1.0:
- resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==}
- engines: {node: '>=18'}
-
- err-code@2.0.3:
- resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==}
-
- error-ex@1.3.4:
- resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==}
-
- es-abstract@1.24.2:
- resolution: {integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==}
- engines: {node: '>= 0.4'}
-
- es-define-property@1.0.1:
- resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
- engines: {node: '>= 0.4'}
-
- es-errors@1.3.0:
- resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
- engines: {node: '>= 0.4'}
-
- es-iterator-helpers@1.3.2:
- resolution: {integrity: sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw==}
- engines: {node: '>= 0.4'}
-
- es-module-lexer@1.7.0:
- resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
-
- es-object-atoms@1.1.1:
- resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
- engines: {node: '>= 0.4'}
-
- es-set-tostringtag@2.1.0:
- resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
- engines: {node: '>= 0.4'}
-
- es-shim-unscopables@1.1.0:
- resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==}
- engines: {node: '>= 0.4'}
-
- es-to-primitive@1.3.0:
- resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
- engines: {node: '>= 0.4'}
-
- esbuild@0.27.7:
- resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==}
- engines: {node: '>=18'}
- hasBin: true
-
- escalade@3.2.0:
- resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
- engines: {node: '>=6'}
-
- escape-html@1.0.3:
- resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
-
- escape-string-regexp@1.0.5:
- resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
- engines: {node: '>=0.8.0'}
-
- escape-string-regexp@4.0.0:
- resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
- engines: {node: '>=10'}
-
- eslint-compat-utils@0.5.1:
- resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==}
- engines: {node: '>=12'}
- peerDependencies:
- eslint: '>=6.0.0'
-
- eslint-compat-utils@0.6.5:
- resolution: {integrity: sha512-vAUHYzue4YAa2hNACjB8HvUQj5yehAZgiClyFVVom9cP8z5NSFq3PwB/TtJslN2zAMgRX6FCFCjYBbQh71g5RQ==}
- engines: {node: '>=12'}
- peerDependencies:
- eslint: '>=6.0.0'
-
- eslint-config-neon@0.2.9:
- resolution: {integrity: sha512-1+l4fSVkc9KAJtQMl4hxPLlOODt4auKNBGAkDzSSnUr4sQExp48zGjExSH+lW5Y3obpAvLLUhsHbofGjvpD9yA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- eslint-config-prettier@10.1.8:
- resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==}
- hasBin: true
- peerDependencies:
- eslint: '>=7.0.0'
-
- eslint-etc@5.2.1:
- resolution: {integrity: sha512-lFJBSiIURdqQKq9xJhvSJFyPA+VeTh5xvk24e8pxVL7bwLBtGF60C/KRkLTMrvCZ6DA3kbPuYhLWY0TZMlqTsg==}
- peerDependencies:
- eslint: ^8.0.0
- typescript: '>=4.0.0'
-
- eslint-formatter-compact@8.40.0:
- resolution: {integrity: sha512-cwGUs113TgmTQXecx5kfRjB7m0y2wkDLSadPTE2pK6M/wO4N8PjmUaoWOFNCP9MHgsiZwgqd5bZFnDCnszC56Q==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
-
- eslint-formatter-pretty@7.1.0:
- resolution: {integrity: sha512-iyPrgpwKC3MMM75Wxn0VouD89HolpG+BL95NOxgwOWO0R+Omapo7gFX2xcGVsUDS7KiXLtDuynLbNbOARSE7YA==}
- engines: {node: '>=18'}
-
- eslint-import-context@0.1.9:
- resolution: {integrity: sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg==}
- engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
- peerDependencies:
- unrs-resolver: ^1.0.0
- peerDependenciesMeta:
- unrs-resolver:
- optional: true
-
- eslint-import-resolver-typescript@4.4.4:
- resolution: {integrity: sha512-1iM2zeBvrYmUNTj2vSC/90JTHDth+dfOfiNKkxApWRsTJYNrc8rOdxxIf5vazX+BiAXTeOT0UvWpGI/7qIWQOw==}
- engines: {node: ^16.17.0 || >=18.6.0}
- peerDependencies:
- eslint: '*'
- eslint-plugin-import: '*'
- eslint-plugin-import-x: '*'
- peerDependenciesMeta:
- eslint-plugin-import:
- optional: true
- eslint-plugin-import-x:
- optional: true
-
- eslint-mdx@3.7.0:
- resolution: {integrity: sha512-QpPdJ6EeFthHuIrfgnWneZgwwFNOLFj/nf2jg/tOTBoiUnqNTxUUpTGAn0ZFHYEh5htVVoe5kjvD02oKtxZGeA==}
- engines: {node: '>=18.0.0'}
- peerDependencies:
- eslint: '>=8.0.0'
- remark-lint-file-extension: '*'
- peerDependenciesMeta:
- remark-lint-file-extension:
- optional: true
-
- eslint-plugin-astro@1.7.0:
- resolution: {integrity: sha512-89xpAn528UKCdmyysbg0AHHqi6sqcK89wXnJIpu4F0mFBN03zATEBNK7pRtMfl6gwtMOm5ECXs+Wz5qDHhwTFw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: '>=8.57.0'
-
- eslint-plugin-cypress@5.3.0:
- resolution: {integrity: sha512-qjHF2Sdi3VkXSMnfQeUqsbYnessgc6T2dus/Q1U+e5102GpPy9eLd8MWW2Xp2SS9bMpPNLnSHwktMhCKr0dIBg==}
- peerDependencies:
- eslint: '>=9'
-
- eslint-plugin-es-x@7.8.0:
- resolution: {integrity: sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==}
- engines: {node: ^14.18.0 || >=16.0.0}
- peerDependencies:
- eslint: '>=8'
-
- eslint-plugin-import-x@4.16.2:
- resolution: {integrity: sha512-rM9K8UBHcWKpzQzStn1YRN2T5NvdeIfSVoKu/lKF41znQXHAUcBbYXe5wd6GNjZjTrP7viQ49n1D83x/2gYgIw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ ws@8.20.0:
+ resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==}
+ engines: {node: '>=10.0.0'}
peerDependencies:
- '@typescript-eslint/utils': ^8.56.0
- eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
- eslint-import-resolver-node: '*'
+ bufferutil: ^4.0.1
+ utf-8-validate: '>=5.0.2'
peerDependenciesMeta:
- '@typescript-eslint/utils':
+ bufferutil:
optional: true
- eslint-import-resolver-node:
+ utf-8-validate:
optional: true
- eslint-plugin-jsdoc@61.7.1:
- resolution: {integrity: sha512-36DpldF95MlTX//n3/naULFVt8d1cV4jmSkx7ZKrE9ikkKHAgMLesuWp1SmwpVwAs5ndIM6abKd6PeOYZUgdWg==}
- engines: {node: '>=20.11.0'}
- peerDependencies:
- eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
-
- eslint-plugin-jsx-a11y@6.10.2:
- resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==}
- engines: {node: '>=4.0'}
- peerDependencies:
- eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9
-
- eslint-plugin-mdx@3.7.0:
- resolution: {integrity: sha512-JXaaQPnKqyti/QSOSQDThLV1EemHm/Fe2l/nMKH0vmhvmABtN/yV/9+GtKgh8UTZwrwuTfQq1HW5eR8HXneNLA==}
- engines: {node: '>=18.0.0'}
- peerDependencies:
- eslint: '>=8.0.0'
-
- eslint-plugin-n@17.24.0:
- resolution: {integrity: sha512-/gC7/KAYmfNnPNOb3eu8vw+TdVnV0zhdQwexsw6FLXbhzroVj20vRn2qL8lDWDGnAQ2J8DhdfvXxX9EoxvERvw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: '>=8.23.0'
-
- eslint-plugin-promise@7.2.1:
- resolution: {integrity: sha512-SWKjd+EuvWkYaS+uN2csvj0KoP43YTu7+phKQ5v+xw6+A0gutVX2yqCeCkC3uLCJFiPfR2dD8Es5L7yUsmvEaA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
-
- eslint-plugin-react-hooks@7.1.0:
- resolution: {integrity: sha512-LDicyhrRFrIaheDYryeM2W8gWyZXnAs4zIr2WVPiOSeTmIu2RjR4x/9N0xLaRWZ+9hssBDGo3AadcohuzAvSvg==}
- engines: {node: '>=18'}
- peerDependencies:
- eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0
-
- eslint-plugin-react-refresh@0.4.26:
- resolution: {integrity: sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==}
- peerDependencies:
- eslint: '>=8.40'
-
- eslint-plugin-react@7.37.5:
- resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==}
- engines: {node: '>=4'}
- peerDependencies:
- eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7
-
- eslint-plugin-rxjs-angular@2.0.1:
- resolution: {integrity: sha512-HJ/JHhjDJKyFUmM8o7rS91WNkNv7W7Z/okR5X3hqG7tKVMLOJi4T63Aa74ECuCdowmdfW75p2RrW4R8WeoZIKQ==}
- peerDependencies:
- eslint: ^8.0.0
- typescript: '>=4.0.0'
-
- eslint-plugin-rxjs@5.0.3:
- resolution: {integrity: sha512-fcVkqLmYLRfRp+ShafjpUKuaZ+cw/sXAvM5dfSxiEr7M28QZ/NY7vaOr09FB4rSaZsQyLBnNPh5SL+4EgKjh8Q==}
- peerDependencies:
- eslint: ^8.0.0
- typescript: '>=4.0.0'
-
- eslint-plugin-sonarjs@3.0.7:
- resolution: {integrity: sha512-62jB20krIPvcwBLAyG3VVKa2ce2j2lL1yCb8Y0ylMRR/dLvCCTiQx8gQbXb+G81k1alPZ2/I3muZinqWQdBbzw==}
- peerDependencies:
- eslint: ^8.0.0 || ^9.0.0
-
- eslint-plugin-svelte3@4.0.0:
- resolution: {integrity: sha512-OIx9lgaNzD02+MDFNLw0GEUbuovNcglg+wnd/UY0fbZmlQSz7GlQiQ1f+yX0XvC07XPcDOnFcichqI3xCwp71g==}
- peerDependencies:
- eslint: '>=8.0.0'
- svelte: ^3.2.0
-
- eslint-plugin-tsdoc@0.4.0:
- resolution: {integrity: sha512-MT/8b4aKLdDClnS8mP3R/JNjg29i0Oyqd/0ym6NnQf+gfKbJJ4ZcSh2Bs1H0YiUMTBwww5JwXGTWot/RwyJ7aQ==}
-
- eslint-plugin-typescript-sort-keys@3.3.0:
- resolution: {integrity: sha512-bRW3Rc/VNdrSP9OoY5wgjjaXCOOkZKpzvl/Mk6l8Sg8CMehVIcg9K4y33l+ZcZiknpl0aR6rKusxuCJNGZWmVw==}
- engines: {node: '>= 16'}
- peerDependencies:
- '@typescript-eslint/parser': '>=6'
- eslint: ^7 || ^8
- typescript: ^3 || ^4 || ^5
-
- eslint-plugin-unicorn@61.0.2:
- resolution: {integrity: sha512-zLihukvneYT7f74GNbVJXfWIiNQmkc/a9vYBTE4qPkQZswolWNdu+Wsp9sIXno1JOzdn6OUwLPd19ekXVkahRA==}
- engines: {node: ^20.10.0 || >=21.0.0}
- peerDependencies:
- eslint: '>=9.29.0'
-
- eslint-plugin-vue@10.8.0:
- resolution: {integrity: sha512-f1J/tcbnrpgC8suPN5AtdJ5MQjuXbSU9pGRSSYAuF3SHoiYCOdEX6O22pLaRyLHXvDcOe+O5ENgc1owQ587agA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ ws@8.20.1:
+ resolution: {integrity: sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==}
+ engines: {node: '>=10.0.0'}
peerDependencies:
- '@stylistic/eslint-plugin': ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0
- '@typescript-eslint/parser': ^7.0.0 || ^8.0.0
- eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
- vue-eslint-parser: ^10.0.0
+ bufferutil: ^4.0.1
+ utf-8-validate: '>=5.0.2'
peerDependenciesMeta:
- '@stylistic/eslint-plugin':
- optional: true
- '@typescript-eslint/parser':
+ bufferutil:
optional: true
-
- eslint-rule-docs@1.1.235:
- resolution: {integrity: sha512-+TQ+x4JdTnDoFEXXb3fDvfGOwnyNV7duH8fXWTPD1ieaBmB8omj7Gw/pMBBu4uI2uJCCU8APDaQJzWuXnTsH4A==}
-
- eslint-scope@5.1.1:
- resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==}
- engines: {node: '>=8.0.0'}
-
- eslint-scope@8.4.0:
- resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- eslint-scope@9.1.2:
- resolution: {integrity: sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==}
- engines: {node: ^20.19.0 || ^22.13.0 || >=24}
-
- eslint-visitor-keys@3.4.3:
- resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
-
- eslint-visitor-keys@4.2.1:
- resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- eslint-visitor-keys@5.0.1:
- resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==}
- engines: {node: ^20.19.0 || ^22.13.0 || >=24}
-
- eslint@9.39.4:
- resolution: {integrity: sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- hasBin: true
- peerDependencies:
- jiti: '*'
- peerDependenciesMeta:
- jiti:
+ utf-8-validate:
optional: true
- espree@10.4.0:
- resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- espree@11.2.0:
- resolution: {integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==}
- engines: {node: ^20.19.0 || ^22.13.0 || >=24}
-
- esquery@1.7.0:
- resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==}
- engines: {node: '>=0.10'}
-
- esrecurse@4.3.0:
- resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
- engines: {node: '>=4.0'}
-
- estraverse@4.3.0:
- resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==}
- engines: {node: '>=4.0'}
-
- estraverse@5.3.0:
- resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
- engines: {node: '>=4.0'}
-
- estree-util-is-identifier-name@3.0.0:
- resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==}
-
- estree-util-visit@2.0.0:
- resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==}
-
- esutils@2.0.3:
- resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
- engines: {node: '>=0.10.0'}
-
- etag@1.8.1:
- resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
- engines: {node: '>= 0.6'}
+ xtend@4.0.2:
+ resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
+ engines: {node: '>=0.4'}
- exit-hook@2.2.1:
- resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==}
- engines: {node: '>=6'}
+ y18n@5.0.8:
+ resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+ engines: {node: '>=10'}
- express@4.22.1:
- resolution: {integrity: sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==}
- engines: {node: '>= 0.10.0'}
+ yargs-parser@21.1.1:
+ resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+ engines: {node: '>=12'}
- exsolve@1.0.8:
- resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==}
+ yargs@17.7.2:
+ resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
+ engines: {node: '>=12'}
- extend@3.0.2:
- resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
+ zeptomatch@2.1.0:
+ resolution: {integrity: sha512-KiGErG2J0G82LSpniV0CtIzjlJ10E04j02VOudJsPyPwNZgGnRKQy7I1R7GMyg/QswnE4l7ohSGrQbQbjXPPDA==}
- fast-check@3.23.2:
- resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==}
- engines: {node: '>=8.0.0'}
+ zod@4.4.3:
+ resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==}
- fast-deep-equal@3.1.3:
- resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+snapshots:
- fast-glob@3.3.1:
- resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==}
- engines: {node: '>=8.6.0'}
+ '@discordjs/builders@1.14.1':
+ dependencies:
+ '@discordjs/formatters': 0.6.2
+ '@discordjs/util': 1.2.0
+ '@sapphire/shapeshift': 4.0.0
+ discord-api-types: 0.38.47
+ fast-deep-equal: 3.1.3
+ ts-mixer: 6.0.4
+ tslib: 2.8.1
- fast-glob@3.3.3:
- resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
- engines: {node: '>=8.6.0'}
+ '@discordjs/collection@1.5.3': {}
- fast-json-stable-stringify@2.1.0:
- resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+ '@discordjs/collection@2.1.1': {}
- fast-levenshtein@2.0.6:
- resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+ '@discordjs/core@2.4.0':
+ dependencies:
+ '@discordjs/rest': 2.6.1
+ '@discordjs/util': 1.2.0
+ '@discordjs/ws': 2.0.4
+ '@sapphire/snowflake': 3.5.5
+ '@vladfrangu/async_event_emitter': 2.4.7
+ discord-api-types: 0.38.47
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
- fastq@1.20.1:
- resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==}
+ '@discordjs/formatters@0.6.2':
+ dependencies:
+ discord-api-types: 0.38.47
- fdir@6.5.0:
- resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
- engines: {node: '>=12.0.0'}
- peerDependencies:
- picomatch: ^3 || ^4
- peerDependenciesMeta:
- picomatch:
- optional: true
-
- file-entry-cache@8.0.0:
- resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
- engines: {node: '>=16.0.0'}
-
- fill-range@7.1.1:
- resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
- engines: {node: '>=8'}
-
- finalhandler@1.3.2:
- resolution: {integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==}
- engines: {node: '>= 0.8'}
-
- find-up-simple@1.0.1:
- resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==}
- engines: {node: '>=18'}
-
- find-up@5.0.0:
- resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
- engines: {node: '>=10'}
-
- flat-cache@4.0.1:
- resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
- engines: {node: '>=16'}
-
- flatted@3.4.2:
- resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==}
-
- for-each@0.3.5:
- resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
- engines: {node: '>= 0.4'}
-
- foreground-child@3.3.1:
- resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
- engines: {node: '>=14'}
-
- forwarded@0.2.0:
- resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
- engines: {node: '>= 0.6'}
-
- fresh@0.5.2:
- resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
- engines: {node: '>= 0.6'}
-
- fs.realpath@1.0.0:
- resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
-
- fsevents@2.3.3:
- resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
- engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
- os: [darwin]
-
- function-bind@1.1.2:
- resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
-
- function.prototype.name@1.1.8:
- resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==}
- engines: {node: '>= 0.4'}
-
- functional-red-black-tree@1.0.1:
- resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==}
-
- functions-have-names@1.2.3:
- resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
-
- generate-function@2.3.1:
- resolution: {integrity: sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==}
-
- generator-function@2.0.1:
- resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==}
- engines: {node: '>= 0.4'}
-
- gensync@1.0.0-beta.2:
- resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
- engines: {node: '>=6.9.0'}
-
- get-caller-file@2.0.5:
- resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
- engines: {node: 6.* || 8.* || >= 10.*}
-
- get-east-asian-width@1.5.0:
- resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==}
- engines: {node: '>=18'}
-
- get-intrinsic@1.3.0:
- resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
- engines: {node: '>= 0.4'}
-
- get-port-please@3.2.0:
- resolution: {integrity: sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A==}
-
- get-port@5.1.1:
- resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==}
- engines: {node: '>=8'}
-
- get-proto@1.0.1:
- resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
- engines: {node: '>= 0.4'}
-
- get-symbol-description@1.1.0:
- resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
- engines: {node: '>= 0.4'}
-
- get-tsconfig@4.14.0:
- resolution: {integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==}
-
- giget@2.0.0:
- resolution: {integrity: sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==}
- hasBin: true
-
- glob-parent@5.1.2:
- resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
- engines: {node: '>= 6'}
-
- glob-parent@6.0.2:
- resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
- engines: {node: '>=10.13.0'}
-
- glob@10.5.0:
- resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==}
- deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
- hasBin: true
-
- glob@13.0.6:
- resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==}
- engines: {node: 18 || 20 || >=22}
-
- glob@7.2.3:
- resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
- deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
-
- globals@14.0.0:
- resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
- engines: {node: '>=18'}
-
- globals@15.15.0:
- resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==}
- engines: {node: '>=18'}
-
- globals@16.5.0:
- resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==}
- engines: {node: '>=18'}
-
- globalthis@1.0.4:
- resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
- engines: {node: '>= 0.4'}
-
- globby@11.1.0:
- resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
- engines: {node: '>=10'}
-
- globrex@0.1.2:
- resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==}
-
- gopd@1.2.0:
- resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
- engines: {node: '>= 0.4'}
-
- graceful-fs@4.2.11:
- resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
-
- grammex@3.1.12:
- resolution: {integrity: sha512-6ufJOsSA7LcQehIJNCO7HIBykfM7DXQual0Ny780/DEcJIpBlHRvcqEBWGPYd7hrXL2GJ3oJI1MIhaXjWmLQOQ==}
-
- graphmatch@1.1.1:
- resolution: {integrity: sha512-5ykVn/EXM1hF0XCaWh05VbYvEiOL2lY1kBxZtaYsyvjp7cmWOU1XsAdfQBwClraEofXDT197lFbXOEVMHpvQOg==}
-
- has-bigints@1.1.0:
- resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
- engines: {node: '>= 0.4'}
-
- has-flag@4.0.0:
- resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
- engines: {node: '>=8'}
-
- has-flag@5.0.1:
- resolution: {integrity: sha512-CsNUt5x9LUdx6hnk/E2SZLsDyvfqANZSUq4+D3D8RzDJ2M+HDTIkF60ibS1vHaK55vzgiZw1bEPFG9yH7l33wA==}
- engines: {node: '>=12'}
-
- has-property-descriptors@1.0.2:
- resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
-
- has-proto@1.2.0:
- resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==}
- engines: {node: '>= 0.4'}
-
- has-symbols@1.1.0:
- resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
- engines: {node: '>= 0.4'}
-
- has-tostringtag@1.0.2:
- resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
- engines: {node: '>= 0.4'}
-
- hasown@2.0.2:
- resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
- engines: {node: '>= 0.4'}
-
- hermes-estree@0.25.1:
- resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==}
-
- hermes-parser@0.25.1:
- resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==}
-
- hono@4.12.14:
- resolution: {integrity: sha512-am5zfg3yu6sqn5yjKBNqhnTX7Cv+m00ox+7jbaKkrLMRJ4rAdldd1xPd/JzbBWspqaQv6RSTrgFN95EsfhC+7w==}
- engines: {node: '>=16.9.0'}
-
- hosted-git-info@7.0.2:
- resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==}
- engines: {node: ^16.14.0 || >=18.0.0}
-
- html-entities@2.6.0:
- resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==}
-
- http-errors@2.0.1:
- resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==}
- engines: {node: '>= 0.8'}
-
- http-status-codes@2.3.0:
- resolution: {integrity: sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==}
-
- iconv-lite@0.4.24:
- resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
- engines: {node: '>=0.10.0'}
-
- iconv-lite@0.7.2:
- resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==}
- engines: {node: '>=0.10.0'}
-
- ignore@5.3.2:
- resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
- engines: {node: '>= 4'}
-
- ignore@6.0.2:
- resolution: {integrity: sha512-InwqeHHN2XpumIkMvpl/DCJVrAHgCsG5+cn1XlnLWGwtZBm8QJfSusItfrwx81CTp5agNZqpKU2J/ccC5nGT4A==}
- engines: {node: '>= 4'}
-
- ignore@7.0.5:
- resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
- engines: {node: '>= 4'}
-
- import-fresh@3.3.1:
- resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
- engines: {node: '>=6'}
-
- import-meta-resolve@4.2.0:
- resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==}
-
- imurmurhash@0.1.4:
- resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
- engines: {node: '>=0.8.19'}
-
- indent-string@5.0.0:
- resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==}
- engines: {node: '>=12'}
-
- inflight@1.0.6:
- resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
- deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
-
- inherits@2.0.4:
- resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
-
- ini@4.1.3:
- resolution: {integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==}
- engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
-
- internal-slot@1.1.0:
- resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
- engines: {node: '>= 0.4'}
-
- ipaddr.js@1.9.1:
- resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
- engines: {node: '>= 0.10'}
-
- irregular-plurals@3.5.0:
- resolution: {integrity: sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==}
- engines: {node: '>=8'}
-
- is-alphabetical@2.0.1:
- resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==}
-
- is-alphanumerical@2.0.1:
- resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==}
-
- is-array-buffer@3.0.5:
- resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
- engines: {node: '>= 0.4'}
-
- is-arrayish@0.2.1:
- resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
-
- is-async-function@2.1.1:
- resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==}
- engines: {node: '>= 0.4'}
-
- is-bigint@1.1.0:
- resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==}
- engines: {node: '>= 0.4'}
-
- is-boolean-object@1.2.2:
- resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==}
- engines: {node: '>= 0.4'}
-
- is-builtin-module@5.0.0:
- resolution: {integrity: sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA==}
- engines: {node: '>=18.20'}
-
- is-bun-module@2.0.0:
- resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==}
-
- is-callable@1.2.7:
- resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
- engines: {node: '>= 0.4'}
-
- is-core-module@2.16.1:
- resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
- engines: {node: '>= 0.4'}
-
- is-data-view@1.0.2:
- resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==}
- engines: {node: '>= 0.4'}
-
- is-date-object@1.1.0:
- resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==}
- engines: {node: '>= 0.4'}
-
- is-decimal@2.0.1:
- resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
-
- is-empty@1.2.0:
- resolution: {integrity: sha512-F2FnH/otLNJv0J6wc73A5Xo7oHLNnqplYqZhUu01tD54DIPvxIRSTSLkrUB/M0nHO4vo1O9PDfN4KoTxCzLh/w==}
-
- is-extglob@2.1.1:
- resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
- engines: {node: '>=0.10.0'}
-
- is-finalizationregistry@1.1.1:
- resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==}
- engines: {node: '>= 0.4'}
-
- is-fullwidth-code-point@3.0.0:
- resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
- engines: {node: '>=8'}
-
- is-generator-function@1.1.2:
- resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==}
- engines: {node: '>= 0.4'}
-
- is-glob@4.0.3:
- resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
- engines: {node: '>=0.10.0'}
-
- is-hexadecimal@2.0.1:
- resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
-
- is-map@2.0.3:
- resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==}
- engines: {node: '>= 0.4'}
-
- is-negative-zero@2.0.3:
- resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==}
- engines: {node: '>= 0.4'}
-
- is-number-object@1.1.1:
- resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==}
- engines: {node: '>= 0.4'}
-
- is-number@7.0.0:
- resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
- engines: {node: '>=0.12.0'}
-
- is-plain-obj@4.1.0:
- resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
- engines: {node: '>=12'}
-
- is-property@1.0.2:
- resolution: {integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==}
-
- is-regex@1.2.1:
- resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==}
- engines: {node: '>= 0.4'}
-
- is-set@2.0.3:
- resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==}
- engines: {node: '>= 0.4'}
-
- is-shared-array-buffer@1.0.4:
- resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==}
- engines: {node: '>= 0.4'}
-
- is-stream@2.0.1:
- resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
- engines: {node: '>=8'}
-
- is-string@1.1.1:
- resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==}
- engines: {node: '>= 0.4'}
-
- is-symbol@1.1.1:
- resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==}
- engines: {node: '>= 0.4'}
-
- is-typed-array@1.1.15:
- resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==}
- engines: {node: '>= 0.4'}
-
- is-unicode-supported@2.1.0:
- resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==}
- engines: {node: '>=18'}
-
- is-weakmap@2.0.2:
- resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==}
- engines: {node: '>= 0.4'}
-
- is-weakref@1.1.1:
- resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==}
- engines: {node: '>= 0.4'}
-
- is-weakset@2.0.4:
- resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
- engines: {node: '>= 0.4'}
-
- isarray@2.0.5:
- resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
-
- isbot@5.1.40:
- resolution: {integrity: sha512-yNeeynhhtIVRBk12tBV4eHNxwB42HzR4Q3Ea7vCOiJhImGaAIdIMrbJtacQlBizGLjUPw+akkFI5Dn9T70XoVQ==}
- engines: {node: '>=18'}
-
- isexe@2.0.0:
- resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
-
- isexe@3.1.5:
- resolution: {integrity: sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==}
- engines: {node: '>=18'}
-
- iterator.prototype@1.1.5:
- resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==}
- engines: {node: '>= 0.4'}
-
- jackspeak@3.4.3:
- resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
-
- jiti@2.6.1:
- resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
- hasBin: true
-
- jju@1.4.0:
- resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==}
-
- js-tokens@4.0.0:
- resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
-
- js-yaml@4.1.1:
- resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
- hasBin: true
-
- jsdoc-type-pratt-parser@7.0.0:
- resolution: {integrity: sha512-c7YbokssPOSHmqTbSAmTtnVgAVa/7lumWNYqomgd5KOMyPrRve2anx6lonfOsXEQacqF9FKVUj7bLg4vRSvdYA==}
- engines: {node: '>=20.0.0'}
-
- jsesc@3.0.2:
- resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==}
- engines: {node: '>=6'}
- hasBin: true
-
- jsesc@3.1.0:
- resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
- engines: {node: '>=6'}
- hasBin: true
-
- json-buffer@3.0.1:
- resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
-
- json-parse-even-better-errors@3.0.2:
- resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==}
- engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
-
- json-schema-traverse@0.4.1:
- resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
-
- json-schema-traverse@1.0.0:
- resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
-
- json-schema@0.4.0:
- resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==}
-
- json-stable-stringify-without-jsonify@1.0.1:
- resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
-
- json5@2.2.3:
- resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
- engines: {node: '>=6'}
- hasBin: true
-
- jsx-ast-utils-x@0.1.0:
- resolution: {integrity: sha512-eQQBjBnsVtGacsG9uJNB8qOr3yA8rga4wAaGG1qRcBzSIvfhERLrWxMAM1hp5fcS6Abo8M4+bUBTekYR0qTPQw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- jsx-ast-utils@3.3.5:
- resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
- engines: {node: '>=4.0'}
-
- keyv@4.5.4:
- resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
-
- kleur@3.0.3:
- resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
- engines: {node: '>=6'}
-
- language-subtag-registry@0.3.23:
- resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==}
-
- language-tags@1.0.9:
- resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==}
- engines: {node: '>=0.10'}
-
- levn@0.4.1:
- resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
- engines: {node: '>= 0.8.0'}
-
- lightningcss-android-arm64@1.32.0:
- resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==}
- engines: {node: '>= 12.0.0'}
- cpu: [arm64]
- os: [android]
-
- lightningcss-darwin-arm64@1.32.0:
- resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==}
- engines: {node: '>= 12.0.0'}
- cpu: [arm64]
- os: [darwin]
-
- lightningcss-darwin-x64@1.32.0:
- resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==}
- engines: {node: '>= 12.0.0'}
- cpu: [x64]
- os: [darwin]
-
- lightningcss-freebsd-x64@1.32.0:
- resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==}
- engines: {node: '>= 12.0.0'}
- cpu: [x64]
- os: [freebsd]
-
- lightningcss-linux-arm-gnueabihf@1.32.0:
- resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==}
- engines: {node: '>= 12.0.0'}
- cpu: [arm]
- os: [linux]
-
- lightningcss-linux-arm64-gnu@1.32.0:
- resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==}
- engines: {node: '>= 12.0.0'}
- cpu: [arm64]
- os: [linux]
- libc: [glibc]
-
- lightningcss-linux-arm64-musl@1.32.0:
- resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==}
- engines: {node: '>= 12.0.0'}
- cpu: [arm64]
- os: [linux]
- libc: [musl]
-
- lightningcss-linux-x64-gnu@1.32.0:
- resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==}
- engines: {node: '>= 12.0.0'}
- cpu: [x64]
- os: [linux]
- libc: [glibc]
-
- lightningcss-linux-x64-musl@1.32.0:
- resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==}
- engines: {node: '>= 12.0.0'}
- cpu: [x64]
- os: [linux]
- libc: [musl]
-
- lightningcss-win32-arm64-msvc@1.32.0:
- resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==}
- engines: {node: '>= 12.0.0'}
- cpu: [arm64]
- os: [win32]
-
- lightningcss-win32-x64-msvc@1.32.0:
- resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==}
- engines: {node: '>= 12.0.0'}
- cpu: [x64]
- os: [win32]
-
- lightningcss@1.32.0:
- resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==}
- engines: {node: '>= 12.0.0'}
-
- lines-and-columns@2.0.4:
- resolution: {integrity: sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
- load-plugin@6.0.3:
- resolution: {integrity: sha512-kc0X2FEUZr145odl68frm+lMJuQ23+rTXYmR6TImqPtbpmXC4vVXbWKDQ9IzndA0HfyQamWfKLhzsqGSTxE63w==}
-
- locate-path@6.0.0:
- resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
- engines: {node: '>=10'}
-
- lodash.merge@4.6.2:
- resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
-
- lodash.snakecase@4.1.1:
- resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==}
-
- lodash@4.18.1:
- resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==}
-
- log-symbols@7.0.1:
- resolution: {integrity: sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==}
- engines: {node: '>=18'}
-
- long@5.3.2:
- resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==}
-
- longest-streak@3.1.0:
- resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
-
- loose-envify@1.4.0:
- resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
- hasBin: true
-
- lru-cache@10.4.3:
- resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
-
- lru-cache@11.3.5:
- resolution: {integrity: sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==}
- engines: {node: 20 || >=22}
-
- lru-cache@5.1.1:
- resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
-
- lru.min@1.1.4:
- resolution: {integrity: sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==}
- engines: {bun: '>=1.0.0', deno: '>=1.30.0', node: '>=8.0.0'}
-
- magic-bytes.js@1.13.0:
- resolution: {integrity: sha512-afO2mnxW7GDTXMm5/AoN1WuOcdoKhtgXjIvHmobqTD1grNplhGdv3PFOyjCVmrnOZBIT/gD/koDKpYG+0mvHcg==}
-
- magic-string@0.30.21:
- resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
-
- math-intrinsics@1.1.0:
- resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
- engines: {node: '>= 0.4'}
-
- mdast-util-from-markdown@2.0.3:
- resolution: {integrity: sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==}
-
- mdast-util-mdx-expression@2.0.1:
- resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==}
-
- mdast-util-mdx-jsx@3.2.0:
- resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==}
-
- mdast-util-mdx@3.0.0:
- resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==}
-
- mdast-util-mdxjs-esm@2.0.1:
- resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==}
-
- mdast-util-phrasing@4.1.0:
- resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==}
-
- mdast-util-to-markdown@2.1.2:
- resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==}
-
- mdast-util-to-string@4.0.0:
- resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
-
- media-typer@0.3.0:
- resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
- engines: {node: '>= 0.6'}
-
- merge-descriptors@1.0.3:
- resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==}
-
- merge2@1.4.1:
- resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
- engines: {node: '>= 8'}
-
- methods@1.1.2:
- resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==}
- engines: {node: '>= 0.6'}
-
- micromark-core-commonmark@2.0.3:
- resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}
-
- micromark-extension-mdx-expression@3.0.1:
- resolution: {integrity: sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==}
-
- micromark-extension-mdx-jsx@3.0.2:
- resolution: {integrity: sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==}
-
- micromark-extension-mdx-md@2.0.0:
- resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==}
-
- micromark-extension-mdxjs-esm@3.0.0:
- resolution: {integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==}
-
- micromark-extension-mdxjs@3.0.0:
- resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==}
-
- micromark-factory-destination@2.0.1:
- resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==}
-
- micromark-factory-label@2.0.1:
- resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==}
-
- micromark-factory-mdx-expression@2.0.3:
- resolution: {integrity: sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==}
-
- micromark-factory-space@2.0.1:
- resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==}
-
- micromark-factory-title@2.0.1:
- resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==}
-
- micromark-factory-whitespace@2.0.1:
- resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==}
-
- micromark-util-character@2.1.1:
- resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==}
-
- micromark-util-chunked@2.0.1:
- resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==}
-
- micromark-util-classify-character@2.0.1:
- resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==}
-
- micromark-util-combine-extensions@2.0.1:
- resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==}
-
- micromark-util-decode-numeric-character-reference@2.0.2:
- resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==}
-
- micromark-util-decode-string@2.0.1:
- resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==}
-
- micromark-util-encode@2.0.1:
- resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}
-
- micromark-util-events-to-acorn@2.0.3:
- resolution: {integrity: sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==}
-
- micromark-util-html-tag-name@2.0.1:
- resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==}
-
- micromark-util-normalize-identifier@2.0.1:
- resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==}
-
- micromark-util-resolve-all@2.0.1:
- resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==}
-
- micromark-util-sanitize-uri@2.0.1:
- resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==}
-
- micromark-util-subtokenize@2.1.0:
- resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==}
-
- micromark-util-symbol@2.0.1:
- resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==}
-
- micromark-util-types@2.0.2:
- resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==}
-
- micromark@4.0.2:
- resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==}
-
- micromatch@4.0.8:
- resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
- engines: {node: '>=8.6'}
-
- mime-db@1.52.0:
- resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
- engines: {node: '>= 0.6'}
-
- mime-db@1.54.0:
- resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
- engines: {node: '>= 0.6'}
-
- mime-types@2.1.35:
- resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
- engines: {node: '>= 0.6'}
-
- mime@1.6.0:
- resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
- engines: {node: '>=4'}
- hasBin: true
-
- minimatch@10.1.2:
- resolution: {integrity: sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==}
- engines: {node: 20 || >=22}
-
- minimatch@10.2.5:
- resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==}
- engines: {node: 18 || 20 || >=22}
-
- minimatch@3.1.5:
- resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==}
-
- minimatch@9.0.9:
- resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==}
- engines: {node: '>=16 || 14 >=14.17'}
-
- minipass@7.1.3:
- resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==}
- engines: {node: '>=16 || 14 >=14.17'}
-
- morgan@1.10.1:
- resolution: {integrity: sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==}
- engines: {node: '>= 0.8.0'}
-
- ms@2.0.0:
- resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
-
- ms@2.1.3:
- resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
-
- mysql2@3.15.3:
- resolution: {integrity: sha512-FBrGau0IXmuqg4haEZRBfHNWB5mUARw6hNwPDXXGg0XzVJ50mr/9hb267lvpVMnhZ1FON3qNd4Xfcez1rbFwSg==}
- engines: {node: '>= 8.0'}
-
- named-placeholders@1.1.6:
- resolution: {integrity: sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==}
- engines: {node: '>=8.0.0'}
-
- nanoid@3.3.11:
- resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
- engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
- hasBin: true
-
- napi-postinstall@0.3.4:
- resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==}
- engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
- hasBin: true
-
- natural-compare-lite@1.4.0:
- resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}
-
- natural-compare@1.4.0:
- resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
-
- negotiator@0.6.3:
- resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
- engines: {node: '>= 0.6'}
-
- negotiator@0.6.4:
- resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==}
- engines: {node: '>= 0.6'}
-
- node-exports-info@1.6.0:
- resolution: {integrity: sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==}
- engines: {node: '>= 0.4'}
-
- node-fetch-native@1.6.7:
- resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==}
-
- node-releases@2.0.37:
- resolution: {integrity: sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==}
-
- nopt@7.2.1:
- resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==}
- engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
- hasBin: true
-
- normalize-package-data@6.0.2:
- resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==}
- engines: {node: ^16.14.0 || >=18.0.0}
-
- npm-install-checks@6.3.0:
- resolution: {integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==}
- engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
-
- npm-normalize-package-bin@3.0.1:
- resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==}
- engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
-
- npm-package-arg@11.0.3:
- resolution: {integrity: sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==}
- engines: {node: ^16.14.0 || >=18.0.0}
-
- npm-pick-manifest@9.1.0:
- resolution: {integrity: sha512-nkc+3pIIhqHVQr085X9d2JzPzLyjzQS96zbruppqC9aZRm/x8xx6xhI98gHtsfELP2bE+loHq8ZaHFHhe+NauA==}
- engines: {node: ^16.14.0 || >=18.0.0}
-
- nth-check@2.1.1:
- resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
-
- nypm@0.6.5:
- resolution: {integrity: sha512-K6AJy1GMVyfyMXRVB88700BJqNUkByijGJM8kEHpLdcAt+vSQAVfkWWHYzuRXHSY6xA2sNc5RjTj0p9rE2izVQ==}
- engines: {node: '>=18'}
- hasBin: true
-
- object-assign@4.1.1:
- resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
- engines: {node: '>=0.10.0'}
-
- object-deep-merge@2.0.0:
- resolution: {integrity: sha512-3DC3UMpeffLTHiuXSy/UG4NOIYTLlY9u3V82+djSCLYClWobZiS4ivYzpIUWrRY/nfsJ8cWsKyG3QfyLePmhvg==}
-
- object-inspect@1.13.4:
- resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
- engines: {node: '>= 0.4'}
-
- object-keys@1.1.1:
- resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
- engines: {node: '>= 0.4'}
-
- object.assign@4.1.7:
- resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==}
- engines: {node: '>= 0.4'}
-
- object.entries@1.1.9:
- resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==}
- engines: {node: '>= 0.4'}
-
- object.fromentries@2.0.8:
- resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==}
- engines: {node: '>= 0.4'}
-
- object.values@1.2.1:
- resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
- engines: {node: '>= 0.4'}
-
- ohash@2.0.11:
- resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==}
-
- on-finished@2.3.0:
- resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==}
- engines: {node: '>= 0.8'}
-
- on-finished@2.4.1:
- resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
- engines: {node: '>= 0.8'}
-
- on-headers@1.1.0:
- resolution: {integrity: sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==}
- engines: {node: '>= 0.8'}
-
- once@1.4.0:
- resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
-
- optionator@0.9.4:
- resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
- engines: {node: '>= 0.8.0'}
-
- own-keys@1.0.1:
- resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==}
- engines: {node: '>= 0.4'}
-
- p-limit@3.1.0:
- resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
- engines: {node: '>=10'}
-
- p-locate@5.0.0:
- resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
- engines: {node: '>=10'}
-
- p-map@7.0.4:
- resolution: {integrity: sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==}
- engines: {node: '>=18'}
-
- package-json-from-dist@1.0.1:
- resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
-
- parent-module@1.0.1:
- resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
- engines: {node: '>=6'}
-
- parse-entities@4.0.2:
- resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
-
- parse-imports-exports@0.2.4:
- resolution: {integrity: sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==}
-
- parse-json@7.1.1:
- resolution: {integrity: sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==}
- engines: {node: '>=16'}
-
- parse-statements@1.0.11:
- resolution: {integrity: sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==}
-
- parseurl@1.3.3:
- resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
- engines: {node: '>= 0.8'}
-
- path-exists@4.0.0:
- resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
- engines: {node: '>=8'}
-
- path-is-absolute@1.0.1:
- resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
- engines: {node: '>=0.10.0'}
-
- path-key@3.1.1:
- resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
- engines: {node: '>=8'}
-
- path-parse@1.0.7:
- resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
-
- path-scurry@1.11.1:
- resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
- engines: {node: '>=16 || 14 >=14.18'}
-
- path-scurry@2.0.2:
- resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==}
- engines: {node: 18 || 20 || >=22}
-
- path-to-regexp@0.1.13:
- resolution: {integrity: sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==}
-
- path-type@4.0.0:
- resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
- engines: {node: '>=8'}
-
- pathe@1.1.2:
- resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
-
- pathe@2.0.3:
- resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
-
- perfect-debounce@1.0.0:
- resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
-
- pg-cloudflare@1.3.0:
- resolution: {integrity: sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==}
-
- pg-connection-string@2.12.0:
- resolution: {integrity: sha512-U7qg+bpswf3Cs5xLzRqbXbQl85ng0mfSV/J0nnA31MCLgvEaAo7CIhmeyrmJpOr7o+zm0rXK+hNnT5l9RHkCkQ==}
-
- pg-int8@1.0.1:
- resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
- engines: {node: '>=4.0.0'}
-
- pg-pool@3.13.0:
- resolution: {integrity: sha512-gB+R+Xud1gLFuRD/QgOIgGOBE2KCQPaPwkzBBGC9oG69pHTkhQeIuejVIk3/cnDyX39av2AxomQiyPT13WKHQA==}
- peerDependencies:
- pg: '>=8.0'
-
- pg-protocol@1.13.0:
- resolution: {integrity: sha512-zzdvXfS6v89r6v7OcFCHfHlyG/wvry1ALxZo4LqgUoy7W9xhBDMaqOuMiF3qEV45VqsN6rdlcehHrfDtlCPc8w==}
-
- pg-types@2.2.0:
- resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
- engines: {node: '>=4'}
-
- pg@8.20.0:
- resolution: {integrity: sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA==}
- engines: {node: '>= 16.0.0'}
- peerDependencies:
- pg-native: '>=3.0.1'
- peerDependenciesMeta:
- pg-native:
- optional: true
-
- pgpass@1.0.5:
- resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==}
-
- picocolors@1.1.1:
- resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
-
- picomatch@2.3.2:
- resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==}
- engines: {node: '>=8.6'}
-
- picomatch@4.0.4:
- resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==}
- engines: {node: '>=12'}
-
- pkg-types@2.3.0:
- resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==}
-
- plur@5.1.0:
- resolution: {integrity: sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
- pluralize@8.0.0:
- resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
- engines: {node: '>=4'}
-
- possible-typed-array-names@1.1.0:
- resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
- engines: {node: '>= 0.4'}
-
- postcss-selector-parser@7.1.1:
- resolution: {integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==}
- engines: {node: '>=4'}
-
- postcss@8.5.10:
- resolution: {integrity: sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==}
- engines: {node: ^10 || ^12 || >=14}
-
- postcss@8.5.14:
- resolution: {integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==}
- engines: {node: ^10 || ^12 || >=14}
-
- postgres-array@2.0.0:
- resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
- engines: {node: '>=4'}
-
- postgres-array@3.0.4:
- resolution: {integrity: sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ==}
- engines: {node: '>=12'}
-
- postgres-bytea@1.0.1:
- resolution: {integrity: sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==}
- engines: {node: '>=0.10.0'}
-
- postgres-date@1.0.7:
- resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
- engines: {node: '>=0.10.0'}
-
- postgres-interval@1.2.0:
- resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
- engines: {node: '>=0.10.0'}
-
- postgres@3.4.7:
- resolution: {integrity: sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==}
- engines: {node: '>=12'}
-
- prelude-ls@1.2.1:
- resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
- engines: {node: '>= 0.8.0'}
-
- prettier@3.8.3:
- resolution: {integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==}
- engines: {node: '>=14'}
- hasBin: true
-
- prisma@7.7.0:
- resolution: {integrity: sha512-HlgwRBt1uEFB9LStHL4HLYDvoi4BNu1rYA0hPG0zCAEyK9SaZBqp7E5Rjpc3Qh8Lex/ye/svoHZ0OWoFNhWxuQ==}
- engines: {node: ^20.19 || ^22.12 || >=24.0}
- hasBin: true
- peerDependencies:
- better-sqlite3: '>=9.0.0'
- typescript: '>=5.4.0'
- peerDependenciesMeta:
- better-sqlite3:
- optional: true
- typescript:
- optional: true
-
- proc-log@4.2.0:
- resolution: {integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==}
- engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
-
- promise-inflight@1.0.1:
- resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==}
- peerDependencies:
- bluebird: '*'
- peerDependenciesMeta:
- bluebird:
- optional: true
-
- promise-retry@2.0.1:
- resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==}
- engines: {node: '>=10'}
-
- prompts@2.4.2:
- resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
- engines: {node: '>= 6'}
-
- prop-types@15.8.1:
- resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
-
- proper-lockfile@4.1.2:
- resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==}
-
- proxy-addr@2.0.7:
- resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
- engines: {node: '>= 0.10'}
-
- punycode@2.3.1:
- resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
- engines: {node: '>=6'}
-
- pure-rand@6.1.0:
- resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==}
-
- qs@6.14.2:
- resolution: {integrity: sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==}
- engines: {node: '>=0.6'}
-
- qs@6.15.1:
- resolution: {integrity: sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==}
- engines: {node: '>=0.6'}
-
- queue-microtask@1.2.3:
- resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
-
- range-parser@1.2.1:
- resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
- engines: {node: '>= 0.6'}
-
- raw-body@2.5.3:
- resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==}
- engines: {node: '>= 0.8'}
-
- rc9@2.1.2:
- resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==}
-
- react-dom@19.2.6:
- resolution: {integrity: sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==}
- peerDependencies:
- react: ^19.2.6
-
- react-is@16.13.1:
- resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
-
- react-refresh@0.14.2:
- resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
- engines: {node: '>=0.10.0'}
-
- react-router@7.15.0:
- resolution: {integrity: sha512-HW9vYwuM8f4yx66Izy8xfrzCM+SBJluoZcCbww9A1TySax11S5Vgw6fi3ZjMONw9J4gQwngL7PzkyIpJJpJ7RQ==}
- engines: {node: '>=20.0.0'}
- peerDependencies:
- react: '>=18'
- react-dom: '>=18'
- peerDependenciesMeta:
- react-dom:
- optional: true
-
- react@19.2.6:
- resolution: {integrity: sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==}
- engines: {node: '>=0.10.0'}
-
- read-package-json-fast@3.0.2:
- resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==}
- engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
-
- readable-stream@3.6.2:
- resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
- engines: {node: '>= 6'}
-
- readdirp@4.1.2:
- resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
- engines: {node: '>= 14.18.0'}
-
- refa@0.12.1:
- resolution: {integrity: sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==}
- engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
-
- reflect.getprototypeof@1.0.10:
- resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
- engines: {node: '>= 0.4'}
-
- regexp-ast-analysis@0.7.1:
- resolution: {integrity: sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==}
- engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
-
- regexp-tree@0.1.27:
- resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==}
- hasBin: true
-
- regexp.prototype.flags@1.5.4:
- resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
- engines: {node: '>= 0.4'}
-
- regjsparser@0.12.0:
- resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==}
- hasBin: true
-
- remark-mdx@3.1.1:
- resolution: {integrity: sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==}
-
- remark-parse@11.0.0:
- resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
-
- remark-stringify@11.0.0:
- resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
-
- remeda@2.33.4:
- resolution: {integrity: sha512-ygHswjlc/opg2VrtiYvUOPLjxjtdKvjGz1/plDhkG66hjNjFr1xmfrs2ClNFo/E6TyUFiwYNh53bKV26oBoMGQ==}
-
- require-directory@2.1.1:
- resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
- engines: {node: '>=0.10.0'}
-
- require-from-string@2.0.2:
- resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
- engines: {node: '>=0.10.0'}
-
- requireindex@1.2.0:
- resolution: {integrity: sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==}
- engines: {node: '>=0.10.5'}
-
- reserved-identifiers@1.2.0:
- resolution: {integrity: sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw==}
- engines: {node: '>=18'}
-
- resolve-from@4.0.0:
- resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
- engines: {node: '>=4'}
-
- resolve-pkg-maps@1.0.0:
- resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
-
- resolve@1.22.12:
- resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==}
- engines: {node: '>= 0.4'}
- hasBin: true
-
- resolve@2.0.0-next.6:
- resolution: {integrity: sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==}
- engines: {node: '>= 0.4'}
- hasBin: true
-
- retry@0.12.0:
- resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==}
- engines: {node: '>= 4'}
-
- reusify@1.1.0:
- resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
- engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
-
- rimraf@6.1.3:
- resolution: {integrity: sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==}
- engines: {node: 20 || >=22}
- hasBin: true
-
- rolldown@1.0.0-rc.18:
- resolution: {integrity: sha512-phmyKBpuBdRYDf4hgyynGAYn/rDDe+iZXKVJ7WX5b1zQzpLkP5oJRPGsfJuHdzPMlyyEO/4sPW6yfSx2gf7lVg==}
- engines: {node: ^20.19.0 || >=22.12.0}
- hasBin: true
-
- rollup@4.60.3:
- resolution: {integrity: sha512-pAQK9HalE84QSm4Po3EmWIZPd3FnjkShVkiMlz1iligWYkWQ7wHYd1PF/T7QZ5TVSD6uSTon5gBVMSM4JfBV+A==}
- engines: {node: '>=18.0.0', npm: '>=8.0.0'}
- hasBin: true
-
- run-parallel@1.2.0:
- resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
-
- rxjs-report-usage@1.0.6:
- resolution: {integrity: sha512-omv1DIv5z1kV+zDAEjaDjWSkx8w5TbFp5NZoPwUipwzYVcor/4So9ZU3bUyQ1c8lxY5Q0Es/ztWW7PGjY7to0Q==}
- hasBin: true
-
- rxjs@7.8.2:
- resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==}
-
- safe-array-concat@1.1.3:
- resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
- engines: {node: '>=0.4'}
-
- safe-buffer@5.1.2:
- resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
-
- safe-buffer@5.2.1:
- resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
-
- safe-push-apply@1.0.0:
- resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
- engines: {node: '>= 0.4'}
-
- safe-regex-test@1.1.0:
- resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
- engines: {node: '>= 0.4'}
-
- safer-buffer@2.1.2:
- resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
-
- scheduler@0.27.0:
- resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
-
- scslre@0.3.0:
- resolution: {integrity: sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ==}
- engines: {node: ^14.0.0 || >=16.0.0}
-
- semver@6.3.1:
- resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
- hasBin: true
-
- semver@7.7.4:
- resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==}
- engines: {node: '>=10'}
- hasBin: true
-
- send@0.19.2:
- resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==}
- engines: {node: '>= 0.8.0'}
-
- seq-queue@0.0.5:
- resolution: {integrity: sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==}
-
- serve-static@1.16.3:
- resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==}
- engines: {node: '>= 0.8.0'}
-
- set-cookie-parser@2.7.2:
- resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==}
-
- set-function-length@1.2.2:
- resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
- engines: {node: '>= 0.4'}
-
- set-function-name@2.0.2:
- resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==}
- engines: {node: '>= 0.4'}
-
- set-proto@1.0.0:
- resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==}
- engines: {node: '>= 0.4'}
-
- setprototypeof@1.2.0:
- resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
-
- shebang-command@2.0.0:
- resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
- engines: {node: '>=8'}
-
- shebang-regex@3.0.0:
- resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
- engines: {node: '>=8'}
-
- shell-quote@1.8.3:
- resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==}
- engines: {node: '>= 0.4'}
-
- side-channel-list@1.0.1:
- resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==}
- engines: {node: '>= 0.4'}
-
- side-channel-map@1.0.1:
- resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
- engines: {node: '>= 0.4'}
-
- side-channel-weakmap@1.0.2:
- resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
- engines: {node: '>= 0.4'}
-
- side-channel@1.1.0:
- resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
- engines: {node: '>= 0.4'}
-
- signal-exit@3.0.7:
- resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
-
- signal-exit@4.1.0:
- resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
- engines: {node: '>=14'}
-
- sisteransi@1.0.5:
- resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
-
- slash@3.0.0:
- resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
- engines: {node: '>=8'}
-
- source-map-js@1.2.1:
- resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
- engines: {node: '>=0.10.0'}
-
- source-map-support@0.5.21:
- resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
-
- source-map@0.6.1:
- resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
- engines: {node: '>=0.10.0'}
-
- spdx-correct@3.2.0:
- resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==}
-
- spdx-exceptions@2.5.0:
- resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==}
-
- spdx-expression-parse@3.0.1:
- resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==}
-
- spdx-expression-parse@4.0.0:
- resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==}
-
- spdx-license-ids@3.0.23:
- resolution: {integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==}
-
- split2@4.2.0:
- resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
- engines: {node: '>= 10.x'}
-
- sqlstring@2.3.3:
- resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==}
- engines: {node: '>= 0.6'}
-
- stable-hash-x@0.2.0:
- resolution: {integrity: sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==}
- engines: {node: '>=12.0.0'}
-
- statuses@2.0.2:
- resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
- engines: {node: '>= 0.8'}
-
- std-env@3.10.0:
- resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
-
- stop-iteration-iterator@1.1.0:
- resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
- engines: {node: '>= 0.4'}
-
- string-width@4.2.3:
- resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
- engines: {node: '>=8'}
-
- string-width@5.1.2:
- resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
- engines: {node: '>=12'}
-
- string-width@6.1.0:
- resolution: {integrity: sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==}
- engines: {node: '>=16'}
-
- string-width@8.2.0:
- resolution: {integrity: sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==}
- engines: {node: '>=20'}
-
- string.prototype.includes@2.0.1:
- resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==}
- engines: {node: '>= 0.4'}
-
- string.prototype.matchall@4.0.12:
- resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==}
- engines: {node: '>= 0.4'}
-
- string.prototype.repeat@1.0.0:
- resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==}
-
- string.prototype.trim@1.2.10:
- resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==}
- engines: {node: '>= 0.4'}
-
- string.prototype.trimend@1.0.9:
- resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==}
- engines: {node: '>= 0.4'}
-
- string.prototype.trimstart@1.0.8:
- resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
- engines: {node: '>= 0.4'}
-
- string_decoder@1.3.0:
- resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
-
- stringify-entities@4.0.4:
- resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
-
- strip-ansi@6.0.1:
- resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
- engines: {node: '>=8'}
-
- strip-ansi@7.2.0:
- resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==}
- engines: {node: '>=12'}
-
- strip-indent@4.1.1:
- resolution: {integrity: sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==}
- engines: {node: '>=12'}
-
- strip-json-comments@3.1.1:
- resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
- engines: {node: '>=8'}
-
- supports-color@10.2.2:
- resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==}
- engines: {node: '>=18'}
-
- supports-color@7.2.0:
- resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
- engines: {node: '>=8'}
-
- supports-color@8.1.1:
- resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
- engines: {node: '>=10'}
-
- supports-color@9.4.0:
- resolution: {integrity: sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==}
- engines: {node: '>=12'}
-
- supports-hyperlinks@4.4.0:
- resolution: {integrity: sha512-UKbpT93hN5Nr9go5UY7bopIB9YQlMz9nm/ct4IXt/irb5YRkn9WaqrOBJGZ5Pwvsd5FQzSVeYlGdXoCAPQZrPg==}
- engines: {node: '>=20'}
-
- supports-preserve-symlinks-flag@1.0.0:
- resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
- engines: {node: '>= 0.4'}
-
- svelte@3.59.2:
- resolution: {integrity: sha512-vzSyuGr3eEoAtT/A6bmajosJZIUWySzY2CzB3w2pgPvnkUjGqlDnsNnA0PMO+mMAhuyMul6C2uuZzY6ELSkzyA==}
- engines: {node: '>= 8'}
-
- synckit@0.11.12:
- resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==}
- engines: {node: ^14.18.0 || >=16.0.0}
-
- tailwindcss@4.3.0:
- resolution: {integrity: sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==}
-
- tapable@2.3.2:
- resolution: {integrity: sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==}
- engines: {node: '>=6'}
-
- tapable@2.3.3:
- resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==}
- engines: {node: '>=6'}
-
- tinyexec@1.1.1:
- resolution: {integrity: sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==}
- engines: {node: '>=18'}
-
- tinyglobby@0.2.16:
- resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==}
- engines: {node: '>=12.0.0'}
-
- to-regex-range@5.0.1:
- resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
- engines: {node: '>=8.0'}
-
- to-valid-identifier@1.0.0:
- resolution: {integrity: sha512-41wJyvKep3yT2tyPqX/4blcfybknGB4D+oETKLs7Q76UiPqRpUJK3hr1nxelyYO0PHKVzJwlu0aCeEAsGI6rpw==}
- engines: {node: '>=20'}
-
- toidentifier@1.0.1:
- resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
- engines: {node: '>=0.6'}
-
- tree-kill@1.2.2:
- resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
- hasBin: true
-
- trough@2.2.0:
- resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==}
-
- ts-api-utils@2.5.0:
- resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==}
- engines: {node: '>=18.12'}
- peerDependencies:
- typescript: '>=4.8.4'
-
- ts-declaration-location@1.0.7:
- resolution: {integrity: sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA==}
- peerDependencies:
- typescript: '>=4.0.0'
-
- ts-mixer@6.0.4:
- resolution: {integrity: sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==}
-
- tslib@1.14.1:
- resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
-
- tslib@2.8.1:
- resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
-
- tsutils-etc@1.4.2:
- resolution: {integrity: sha512-2Dn5SxTDOu6YWDNKcx1xu2YUy6PUeKrWZB/x2cQ8vY2+iz3JRembKn/iZ0JLT1ZudGNwQQvtFX9AwvRHbXuPUg==}
- hasBin: true
- peerDependencies:
- tsutils: ^3.0.0
- typescript: '>=4.0.0'
-
- tsutils@3.21.0:
- resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
- engines: {node: '>= 6'}
- peerDependencies:
- typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta'
-
- turbo@2.9.14:
- resolution: {integrity: sha512-BQqXRr4UoWI3UPFrtznCLykYHxwxWh53iCB57x092jPMjIlW1wnm3N895g5irpiXmnxUhREBB0n6+y8BHhs4nw==}
- hasBin: true
-
- type-check@0.4.0:
- resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
- engines: {node: '>= 0.8.0'}
-
- type-fest@3.13.1:
- resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==}
- engines: {node: '>=14.16'}
-
- type-is@1.6.18:
- resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
- engines: {node: '>= 0.6'}
-
- typed-array-buffer@1.0.3:
- resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
- engines: {node: '>= 0.4'}
-
- typed-array-byte-length@1.0.3:
- resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==}
- engines: {node: '>= 0.4'}
-
- typed-array-byte-offset@1.0.4:
- resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==}
- engines: {node: '>= 0.4'}
-
- typed-array-length@1.0.7:
- resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==}
- engines: {node: '>= 0.4'}
-
- typedarray@0.0.6:
- resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==}
-
- typescript-eslint@8.58.2:
- resolution: {integrity: sha512-V8iSng9mRbdZjl54VJ9NKr6ZB+dW0J3TzRXRGcSbLIej9jV86ZRtlYeTKDR/QLxXykocJ5icNzbsl2+5TzIvcQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
- typescript: '>=4.8.4 <6.1.0'
-
- typescript@5.4.5:
- resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==}
- engines: {node: '>=14.17'}
- hasBin: true
-
- typescript@5.9.3:
- resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
- engines: {node: '>=14.17'}
- hasBin: true
-
- unbox-primitive@1.1.0:
- resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==}
- engines: {node: '>= 0.4'}
-
- undici-types@6.21.0:
- resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
-
- undici@6.24.1:
- resolution: {integrity: sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==}
- engines: {node: '>=18.17'}
-
- unified-engine@11.2.2:
- resolution: {integrity: sha512-15g/gWE7qQl9tQ3nAEbMd5h9HV1EACtFs6N9xaRBZICoCwnNGbal1kOs++ICf4aiTdItZxU2s/kYWhW7htlqJg==}
-
- unified@11.0.5:
- resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
-
- unist-util-inspect@8.1.0:
- resolution: {integrity: sha512-mOlg8Mp33pR0eeFpo5d2902ojqFFOKMMG2hF8bmH7ZlhnmjFgh0NI3/ZDwdaBJNbvrS7LZFVrBVtIE9KZ9s7vQ==}
-
- unist-util-is@6.0.1:
- resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
-
- unist-util-position-from-estree@2.0.0:
- resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==}
-
- unist-util-stringify-position@4.0.0:
- resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
-
- unist-util-visit-parents@6.0.2:
- resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==}
-
- unist-util-visit@5.1.0:
- resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==}
-
- unpipe@1.0.0:
- resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
- engines: {node: '>= 0.8'}
-
- unrs-resolver@1.11.1:
- resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==}
-
- update-browserslist-db@1.2.3:
- resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
- hasBin: true
- peerDependencies:
- browserslist: '>= 4.21.0'
-
- uri-js@4.4.1:
- resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
-
- util-deprecate@1.0.2:
- resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
-
- utils-merge@1.0.1:
- resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
- engines: {node: '>= 0.4.0'}
-
- valibot@1.2.0:
- resolution: {integrity: sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==}
- peerDependencies:
- typescript: '>=5'
- peerDependenciesMeta:
- typescript:
- optional: true
-
- validate-npm-package-license@3.0.4:
- resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
-
- validate-npm-package-name@5.0.1:
- resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==}
- engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
-
- vary@1.1.2:
- resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
- engines: {node: '>= 0.8'}
-
- vfile-message@4.0.3:
- resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==}
-
- vfile-reporter@8.1.1:
- resolution: {integrity: sha512-qxRZcnFSQt6pWKn3PAk81yLK2rO2i7CDXpy8v8ZquiEOMLSnPw6BMSi9Y1sUCwGGl7a9b3CJT1CKpnRF7pp66g==}
-
- vfile-sort@4.0.0:
- resolution: {integrity: sha512-lffPI1JrbHDTToJwcq0rl6rBmkjQmMuXkAxsZPRS9DXbaJQvc642eCg6EGxcX2i1L+esbuhq+2l9tBll5v8AeQ==}
-
- vfile-statistics@3.0.0:
- resolution: {integrity: sha512-/qlwqwWBWFOmpXujL/20P+Iuydil0rZZNglR+VNm6J0gpLHwuVM5s7g2TfVoswbXjZ4HuIhLMySEyIw5i7/D8w==}
-
- vfile@6.0.3:
- resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
-
- vite-node@3.2.4:
- resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==}
- engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
- hasBin: true
-
- vite@7.3.3:
- resolution: {integrity: sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==}
- engines: {node: ^20.19.0 || >=22.12.0}
- hasBin: true
- peerDependencies:
- '@types/node': ^20.19.0 || >=22.12.0
- jiti: '>=1.21.0'
- less: ^4.0.0
- lightningcss: ^1.21.0
- sass: ^1.70.0
- sass-embedded: ^1.70.0
- stylus: '>=0.54.8'
- sugarss: ^5.0.0
- terser: ^5.16.0
- tsx: ^4.8.1
- yaml: ^2.4.2
- peerDependenciesMeta:
- '@types/node':
- optional: true
- jiti:
- optional: true
- less:
- optional: true
- lightningcss:
- optional: true
- sass:
- optional: true
- sass-embedded:
- optional: true
- stylus:
- optional: true
- sugarss:
- optional: true
- terser:
- optional: true
- tsx:
- optional: true
- yaml:
- optional: true
-
- vite@8.0.11:
- resolution: {integrity: sha512-Jz1mxtUBR5xTT65VOdJZUUeoyLtqljmFkiUXhPTLZka3RDc9vpi/xXkyrnsdRcm2lIi3l3GPMnAidTsEGIj3Ow==}
- engines: {node: ^20.19.0 || >=22.12.0}
- hasBin: true
- peerDependencies:
- '@types/node': ^20.19.0 || >=22.12.0
- '@vitejs/devtools': ^0.1.18
- esbuild: ^0.27.0 || ^0.28.0
- jiti: '>=1.21.0'
- less: ^4.0.0
- sass: ^1.70.0
- sass-embedded: ^1.70.0
- stylus: '>=0.54.8'
- sugarss: ^5.0.0
- terser: ^5.16.0
- tsx: ^4.8.1
- yaml: ^2.4.2
- peerDependenciesMeta:
- '@types/node':
- optional: true
- '@vitejs/devtools':
- optional: true
- esbuild:
- optional: true
- jiti:
- optional: true
- less:
- optional: true
- sass:
- optional: true
- sass-embedded:
- optional: true
- stylus:
- optional: true
- sugarss:
- optional: true
- terser:
- optional: true
- tsx:
- optional: true
- yaml:
- optional: true
-
- vue-eslint-parser@10.4.0:
- resolution: {integrity: sha512-Vxi9pJdbN3ZnVGLODVtZ7y4Y2kzAAE2Cm0CZ3ZDRvydVYxZ6VrnBhLikBsRS+dpwj4Jv4UCv21PTEwF5rQ9WXg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
-
- walk-up-path@3.0.1:
- resolution: {integrity: sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==}
-
- which-boxed-primitive@1.1.1:
- resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
- engines: {node: '>= 0.4'}
-
- which-builtin-type@1.2.1:
- resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==}
- engines: {node: '>= 0.4'}
-
- which-collection@1.0.2:
- resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==}
- engines: {node: '>= 0.4'}
-
- which-typed-array@1.1.20:
- resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==}
- engines: {node: '>= 0.4'}
-
- which@2.0.2:
- resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
- engines: {node: '>= 8'}
- hasBin: true
-
- which@4.0.0:
- resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==}
- engines: {node: ^16.13.0 || >=18.0.0}
- hasBin: true
-
- word-wrap@1.2.5:
- resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
- engines: {node: '>=0.10.0'}
-
- wrap-ansi@7.0.0:
- resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
- engines: {node: '>=10'}
-
- wrap-ansi@8.1.0:
- resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
- engines: {node: '>=12'}
-
- wrappy@1.0.2:
- resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
-
- ws@8.20.0:
- resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==}
- engines: {node: '>=10.0.0'}
- peerDependencies:
- bufferutil: ^4.0.1
- utf-8-validate: '>=5.0.2'
- peerDependenciesMeta:
- bufferutil:
- optional: true
- utf-8-validate:
- optional: true
-
- xml-name-validator@4.0.0:
- resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
- engines: {node: '>=12'}
-
- xtend@4.0.2:
- resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
- engines: {node: '>=0.4'}
-
- y18n@5.0.8:
- resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
- engines: {node: '>=10'}
-
- yallist@3.1.1:
- resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
-
- yaml@2.8.3:
- resolution: {integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==}
- engines: {node: '>= 14.6'}
- hasBin: true
-
- yargs-parser@21.1.1:
- resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
- engines: {node: '>=12'}
-
- yargs@17.7.2:
- resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
- engines: {node: '>=12'}
-
- yocto-queue@0.1.0:
- resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
- engines: {node: '>=10'}
-
- yoctocolors@2.1.2:
- resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==}
- engines: {node: '>=18'}
-
- zeptomatch@2.1.0:
- resolution: {integrity: sha512-KiGErG2J0G82LSpniV0CtIzjlJ10E04j02VOudJsPyPwNZgGnRKQy7I1R7GMyg/QswnE4l7ohSGrQbQbjXPPDA==}
-
- zod-validation-error@4.0.2:
- resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==}
- engines: {node: '>=18.0.0'}
- peerDependencies:
- zod: ^3.25.0 || ^4.0.0
-
- zod@4.3.6:
- resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==}
-
- zwitch@2.0.4:
- resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
-
-snapshots:
-
- '@angular-eslint/bundled-angular-compiler@20.7.0': {}
-
- '@angular-eslint/eslint-plugin-template@20.7.0(@angular-eslint/template-parser@20.7.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(@typescript-eslint/types@8.58.2)(@typescript-eslint/utils@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
- dependencies:
- '@angular-eslint/bundled-angular-compiler': 20.7.0
- '@angular-eslint/template-parser': 20.7.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- '@angular-eslint/utils': 20.7.0(@typescript-eslint/utils@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/types': 8.58.2
- '@typescript-eslint/utils': 8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- aria-query: 5.3.2
- axobject-query: 4.1.0
- eslint: 9.39.4(jiti@2.6.1)
- typescript: 5.9.3
-
- '@angular-eslint/eslint-plugin@20.7.0(@typescript-eslint/utils@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
- dependencies:
- '@angular-eslint/bundled-angular-compiler': 20.7.0
- '@angular-eslint/utils': 20.7.0(@typescript-eslint/utils@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/utils': 8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- eslint: 9.39.4(jiti@2.6.1)
- ts-api-utils: 2.5.0(typescript@5.9.3)
- typescript: 5.9.3
-
- '@angular-eslint/template-parser@20.7.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
- dependencies:
- '@angular-eslint/bundled-angular-compiler': 20.7.0
- eslint: 9.39.4(jiti@2.6.1)
- eslint-scope: 9.1.2
- typescript: 5.9.3
-
- '@angular-eslint/utils@20.7.0(@typescript-eslint/utils@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
- dependencies:
- '@angular-eslint/bundled-angular-compiler': 20.7.0
- '@typescript-eslint/utils': 8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- eslint: 9.39.4(jiti@2.6.1)
- typescript: 5.9.3
-
- '@astrojs/compiler@3.0.1': {}
-
- '@babel/code-frame@7.29.0':
- dependencies:
- '@babel/helper-validator-identifier': 7.28.5
- js-tokens: 4.0.0
- picocolors: 1.1.1
-
- '@babel/compat-data@7.29.0': {}
-
- '@babel/core@7.29.0':
- dependencies:
- '@babel/code-frame': 7.29.0
- '@babel/generator': 7.29.1
- '@babel/helper-compilation-targets': 7.28.6
- '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0)
- '@babel/helpers': 7.29.2
- '@babel/parser': 7.29.2
- '@babel/template': 7.28.6
- '@babel/traverse': 7.29.0
- '@babel/types': 7.29.0
- '@jridgewell/remapping': 2.3.5
- convert-source-map: 2.0.0
- debug: 4.4.3
- gensync: 1.0.0-beta.2
- json5: 2.2.3
- semver: 6.3.1
- transitivePeerDependencies:
- - supports-color
-
- '@babel/generator@7.29.1':
- dependencies:
- '@babel/parser': 7.29.2
- '@babel/types': 7.29.0
- '@jridgewell/gen-mapping': 0.3.13
- '@jridgewell/trace-mapping': 0.3.31
- jsesc: 3.1.0
-
- '@babel/helper-annotate-as-pure@7.27.3':
- dependencies:
- '@babel/types': 7.29.0
-
- '@babel/helper-compilation-targets@7.28.6':
- dependencies:
- '@babel/compat-data': 7.29.0
- '@babel/helper-validator-option': 7.27.1
- browserslist: 4.28.2
- lru-cache: 5.1.1
- semver: 6.3.1
-
- '@babel/helper-create-class-features-plugin@7.29.3(@babel/core@7.29.0)':
- dependencies:
- '@babel/core': 7.29.0
- '@babel/helper-annotate-as-pure': 7.27.3
- '@babel/helper-member-expression-to-functions': 7.28.5
- '@babel/helper-optimise-call-expression': 7.27.1
- '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0)
- '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
- '@babel/traverse': 7.29.0
- semver: 6.3.1
- transitivePeerDependencies:
- - supports-color
-
- '@babel/helper-globals@7.28.0': {}
-
- '@babel/helper-member-expression-to-functions@7.28.5':
- dependencies:
- '@babel/traverse': 7.29.0
- '@babel/types': 7.29.0
- transitivePeerDependencies:
- - supports-color
-
- '@babel/helper-module-imports@7.28.6':
- dependencies:
- '@babel/traverse': 7.29.0
- '@babel/types': 7.29.0
- transitivePeerDependencies:
- - supports-color
-
- '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)':
- dependencies:
- '@babel/core': 7.29.0
- '@babel/helper-module-imports': 7.28.6
- '@babel/helper-validator-identifier': 7.28.5
- '@babel/traverse': 7.29.0
- transitivePeerDependencies:
- - supports-color
-
- '@babel/helper-optimise-call-expression@7.27.1':
- dependencies:
- '@babel/types': 7.29.0
-
- '@babel/helper-plugin-utils@7.28.6': {}
-
- '@babel/helper-replace-supers@7.28.6(@babel/core@7.29.0)':
- dependencies:
- '@babel/core': 7.29.0
- '@babel/helper-member-expression-to-functions': 7.28.5
- '@babel/helper-optimise-call-expression': 7.27.1
- '@babel/traverse': 7.29.0
- transitivePeerDependencies:
- - supports-color
-
- '@babel/helper-skip-transparent-expression-wrappers@7.27.1':
- dependencies:
- '@babel/traverse': 7.29.0
- '@babel/types': 7.29.0
- transitivePeerDependencies:
- - supports-color
-
- '@babel/helper-string-parser@7.27.1': {}
-
- '@babel/helper-validator-identifier@7.28.5': {}
-
- '@babel/helper-validator-option@7.27.1': {}
-
- '@babel/helpers@7.29.2':
- dependencies:
- '@babel/template': 7.28.6
- '@babel/types': 7.29.0
-
- '@babel/parser@7.29.2':
- dependencies:
- '@babel/types': 7.29.0
-
- '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)':
- dependencies:
- '@babel/core': 7.29.0
- '@babel/helper-plugin-utils': 7.28.6
-
- '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)':
- dependencies:
- '@babel/core': 7.29.0
- '@babel/helper-plugin-utils': 7.28.6
-
- '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.29.0)':
- dependencies:
- '@babel/core': 7.29.0
- '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0)
- '@babel/helper-plugin-utils': 7.28.6
- transitivePeerDependencies:
- - supports-color
-
- '@babel/plugin-transform-typescript@7.28.6(@babel/core@7.29.0)':
- dependencies:
- '@babel/core': 7.29.0
- '@babel/helper-annotate-as-pure': 7.27.3
- '@babel/helper-create-class-features-plugin': 7.29.3(@babel/core@7.29.0)
- '@babel/helper-plugin-utils': 7.28.6
- '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
- '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0)
- transitivePeerDependencies:
- - supports-color
-
- '@babel/preset-typescript@7.28.5(@babel/core@7.29.0)':
- dependencies:
- '@babel/core': 7.29.0
- '@babel/helper-plugin-utils': 7.28.6
- '@babel/helper-validator-option': 7.27.1
- '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0)
- '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0)
- '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0)
- transitivePeerDependencies:
- - supports-color
-
- '@babel/template@7.28.6':
- dependencies:
- '@babel/code-frame': 7.29.0
- '@babel/parser': 7.29.2
- '@babel/types': 7.29.0
-
- '@babel/traverse@7.29.0':
- dependencies:
- '@babel/code-frame': 7.29.0
- '@babel/generator': 7.29.1
- '@babel/helper-globals': 7.28.0
- '@babel/parser': 7.29.2
- '@babel/template': 7.28.6
- '@babel/types': 7.29.0
- debug: 4.4.3
- transitivePeerDependencies:
- - supports-color
-
- '@babel/types@7.29.0':
- dependencies:
- '@babel/helper-string-parser': 7.27.1
- '@babel/helper-validator-identifier': 7.28.5
-
- '@discordjs/builders@1.14.1':
- dependencies:
- '@discordjs/formatters': 0.6.2
- '@discordjs/util': 1.2.0
- '@sapphire/shapeshift': 4.0.0
- discord-api-types: 0.38.47
- fast-deep-equal: 3.1.3
- ts-mixer: 6.0.4
- tslib: 2.8.1
-
- '@discordjs/collection@1.5.3': {}
-
- '@discordjs/collection@2.1.1': {}
-
- '@discordjs/core@2.4.0':
- dependencies:
- '@discordjs/rest': 2.6.1
- '@discordjs/util': 1.2.0
- '@discordjs/ws': 2.0.4
- '@sapphire/snowflake': 3.5.5
- '@vladfrangu/async_event_emitter': 2.4.7
- discord-api-types: 0.38.47
- transitivePeerDependencies:
- - bufferutil
- - utf-8-validate
-
- '@discordjs/formatters@0.6.2':
- dependencies:
- discord-api-types: 0.38.47
-
- '@discordjs/rest@2.6.1':
- dependencies:
- '@discordjs/collection': 2.1.1
- '@discordjs/util': 1.2.0
- '@sapphire/async-queue': 1.5.5
- '@sapphire/snowflake': 3.5.5
- '@vladfrangu/async_event_emitter': 2.4.7
- discord-api-types: 0.38.47
- magic-bytes.js: 1.13.0
- tslib: 2.8.1
- undici: 6.24.1
-
- '@discordjs/util@1.2.0':
- dependencies:
- discord-api-types: 0.38.47
-
- '@discordjs/ws@1.2.3':
- dependencies:
- '@discordjs/collection': 2.1.1
- '@discordjs/rest': 2.6.1
- '@discordjs/util': 1.2.0
- '@sapphire/async-queue': 1.5.5
- '@types/ws': 8.18.1
- '@vladfrangu/async_event_emitter': 2.4.7
- discord-api-types: 0.38.47
- tslib: 2.8.1
- ws: 8.20.0
- transitivePeerDependencies:
- - bufferutil
- - utf-8-validate
-
- '@discordjs/ws@2.0.4':
- dependencies:
- '@discordjs/collection': 2.1.1
- '@discordjs/rest': 2.6.1
- '@discordjs/util': 1.2.0
- '@sapphire/async-queue': 1.5.5
- '@types/ws': 8.18.1
- '@vladfrangu/async_event_emitter': 2.4.7
- discord-api-types: 0.38.47
- tslib: 2.8.1
- ws: 8.20.0
- transitivePeerDependencies:
- - bufferutil
- - utf-8-validate
-
- '@electric-sql/pglite-socket@0.1.1(@electric-sql/pglite@0.4.1)':
- dependencies:
- '@electric-sql/pglite': 0.4.1
-
- '@electric-sql/pglite-tools@0.3.1(@electric-sql/pglite@0.4.1)':
- dependencies:
- '@electric-sql/pglite': 0.4.1
-
- '@electric-sql/pglite@0.4.1': {}
-
- '@emnapi/core@1.10.0':
- dependencies:
- '@emnapi/wasi-threads': 1.2.1
- tslib: 2.8.1
- optional: true
-
- '@emnapi/runtime@1.10.0':
- dependencies:
- tslib: 2.8.1
- optional: true
-
- '@emnapi/wasi-threads@1.2.1':
- dependencies:
- tslib: 2.8.1
- optional: true
-
- '@es-joy/jsdoccomment@0.78.0':
- dependencies:
- '@types/estree': 1.0.8
- '@typescript-eslint/types': 8.58.2
- comment-parser: 1.4.1
- esquery: 1.7.0
- jsdoc-type-pratt-parser: 7.0.0
-
- '@es-joy/resolve.exports@1.2.0': {}
-
- '@esbuild/aix-ppc64@0.27.7':
- optional: true
-
- '@esbuild/android-arm64@0.27.7':
- optional: true
-
- '@esbuild/android-arm@0.27.7':
- optional: true
-
- '@esbuild/android-x64@0.27.7':
- optional: true
-
- '@esbuild/darwin-arm64@0.27.7':
- optional: true
-
- '@esbuild/darwin-x64@0.27.7':
- optional: true
-
- '@esbuild/freebsd-arm64@0.27.7':
- optional: true
-
- '@esbuild/freebsd-x64@0.27.7':
- optional: true
-
- '@esbuild/linux-arm64@0.27.7':
- optional: true
-
- '@esbuild/linux-arm@0.27.7':
- optional: true
-
- '@esbuild/linux-ia32@0.27.7':
- optional: true
-
- '@esbuild/linux-loong64@0.27.7':
- optional: true
-
- '@esbuild/linux-mips64el@0.27.7':
- optional: true
-
- '@esbuild/linux-ppc64@0.27.7':
- optional: true
-
- '@esbuild/linux-riscv64@0.27.7':
- optional: true
-
- '@esbuild/linux-s390x@0.27.7':
- optional: true
-
- '@esbuild/linux-x64@0.27.7':
- optional: true
-
- '@esbuild/netbsd-arm64@0.27.7':
- optional: true
-
- '@esbuild/netbsd-x64@0.27.7':
- optional: true
-
- '@esbuild/openbsd-arm64@0.27.7':
- optional: true
-
- '@esbuild/openbsd-x64@0.27.7':
- optional: true
-
- '@esbuild/openharmony-arm64@0.27.7':
- optional: true
-
- '@esbuild/sunos-x64@0.27.7':
- optional: true
-
- '@esbuild/win32-arm64@0.27.7':
- optional: true
-
- '@esbuild/win32-ia32@0.27.7':
- optional: true
-
- '@esbuild/win32-x64@0.27.7':
- optional: true
-
- '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.6.1))':
- dependencies:
- eslint: 9.39.4(jiti@2.6.1)
- eslint-visitor-keys: 3.4.3
-
- '@eslint-community/regexpp@4.12.2': {}
-
- '@eslint/compat@1.4.1(eslint@9.39.4(jiti@2.6.1))':
- dependencies:
- '@eslint/core': 0.17.0
- optionalDependencies:
- eslint: 9.39.4(jiti@2.6.1)
-
- '@eslint/config-array@0.21.2':
- dependencies:
- '@eslint/object-schema': 2.1.7
- debug: 4.4.3
- minimatch: 3.1.5
- transitivePeerDependencies:
- - supports-color
-
- '@eslint/config-helpers@0.4.2':
- dependencies:
- '@eslint/core': 0.17.0
-
- '@eslint/core@0.15.2':
- dependencies:
- '@types/json-schema': 7.0.15
-
- '@eslint/core@0.17.0':
- dependencies:
- '@types/json-schema': 7.0.15
-
- '@eslint/eslintrc@3.3.5':
- dependencies:
- ajv: 6.14.0
- debug: 4.4.3
- espree: 10.4.0
- globals: 14.0.0
- ignore: 5.3.2
- import-fresh: 3.3.1
- js-yaml: 4.1.1
- minimatch: 3.1.5
- strip-json-comments: 3.1.1
- transitivePeerDependencies:
- - supports-color
-
- '@eslint/js@9.39.4': {}
-
- '@eslint/object-schema@2.1.7': {}
-
- '@eslint/plugin-kit@0.3.5':
- dependencies:
- '@eslint/core': 0.15.2
- levn: 0.4.1
-
- '@eslint/plugin-kit@0.4.1':
- dependencies:
- '@eslint/core': 0.17.0
- levn: 0.4.1
-
- '@hono/node-server@1.19.11(hono@4.12.14)':
- dependencies:
- hono: 4.12.14
-
- '@humanfs/core@0.19.1': {}
-
- '@humanfs/node@0.16.7':
- dependencies:
- '@humanfs/core': 0.19.1
- '@humanwhocodes/retry': 0.4.3
-
- '@humanwhocodes/module-importer@1.0.1': {}
-
- '@humanwhocodes/retry@0.4.3': {}
-
- '@isaacs/balanced-match@4.0.1': {}
-
- '@isaacs/brace-expansion@5.0.1':
- dependencies:
- '@isaacs/balanced-match': 4.0.1
-
- '@isaacs/cliui@8.0.2':
- dependencies:
- string-width: 5.1.2
- string-width-cjs: string-width@4.2.3
- strip-ansi: 7.2.0
- strip-ansi-cjs: strip-ansi@6.0.1
- wrap-ansi: 8.1.0
- wrap-ansi-cjs: wrap-ansi@7.0.0
-
- '@jridgewell/gen-mapping@0.3.13':
- dependencies:
- '@jridgewell/sourcemap-codec': 1.5.5
- '@jridgewell/trace-mapping': 0.3.31
-
- '@jridgewell/remapping@2.3.5':
- dependencies:
- '@jridgewell/gen-mapping': 0.3.13
- '@jridgewell/trace-mapping': 0.3.31
-
- '@jridgewell/resolve-uri@3.1.2': {}
-
- '@jridgewell/sourcemap-codec@1.5.5': {}
-
- '@jridgewell/trace-mapping@0.3.31':
- dependencies:
- '@jridgewell/resolve-uri': 3.1.2
- '@jridgewell/sourcemap-codec': 1.5.5
-
- '@kurkle/color@0.3.4': {}
-
- '@microsoft/tsdoc-config@0.17.1':
- dependencies:
- '@microsoft/tsdoc': 0.15.1
- ajv: 8.12.0
- jju: 1.4.0
- resolve: 1.22.12
-
- '@microsoft/tsdoc@0.15.1': {}
-
- '@mjackson/node-fetch-server@0.2.0': {}
-
- '@napi-rs/wasm-runtime@0.2.12':
- dependencies:
- '@emnapi/core': 1.10.0
- '@emnapi/runtime': 1.10.0
- '@tybys/wasm-util': 0.10.1
- optional: true
-
- '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)':
- dependencies:
- '@emnapi/core': 1.10.0
- '@emnapi/runtime': 1.10.0
- '@tybys/wasm-util': 0.10.1
- optional: true
-
- '@next/eslint-plugin-next@15.5.15':
- dependencies:
- fast-glob: 3.3.1
-
- '@nodelib/fs.scandir@2.1.5':
- dependencies:
- '@nodelib/fs.stat': 2.0.5
- run-parallel: 1.2.0
-
- '@nodelib/fs.stat@2.0.5': {}
-
- '@nodelib/fs.walk@1.2.8':
- dependencies:
- '@nodelib/fs.scandir': 2.1.5
- fastq: 1.20.1
-
- '@npmcli/config@8.3.4':
- dependencies:
- '@npmcli/map-workspaces': 3.0.6
- '@npmcli/package-json': 5.2.1
- ci-info: 4.4.0
- ini: 4.1.3
- nopt: 7.2.1
- proc-log: 4.2.0
- semver: 7.7.4
- walk-up-path: 3.0.1
- transitivePeerDependencies:
- - bluebird
-
- '@npmcli/git@5.0.8':
- dependencies:
- '@npmcli/promise-spawn': 7.0.2
- ini: 4.1.3
- lru-cache: 10.4.3
- npm-pick-manifest: 9.1.0
- proc-log: 4.2.0
- promise-inflight: 1.0.1
- promise-retry: 2.0.1
- semver: 7.7.4
- which: 4.0.0
- transitivePeerDependencies:
- - bluebird
-
- '@npmcli/map-workspaces@3.0.6':
- dependencies:
- '@npmcli/name-from-folder': 2.0.0
- glob: 10.5.0
- minimatch: 9.0.9
- read-package-json-fast: 3.0.2
-
- '@npmcli/name-from-folder@2.0.0': {}
-
- '@npmcli/package-json@5.2.1':
- dependencies:
- '@npmcli/git': 5.0.8
- glob: 10.5.0
- hosted-git-info: 7.0.2
- json-parse-even-better-errors: 3.0.2
- normalize-package-data: 6.0.2
- proc-log: 4.2.0
- semver: 7.7.4
- transitivePeerDependencies:
- - bluebird
-
- '@npmcli/promise-spawn@7.0.2':
- dependencies:
- which: 4.0.0
-
- '@oxc-project/types@0.128.0': {}
-
- '@package-json/types@0.0.12': {}
-
- '@pkgjs/parseargs@0.11.0':
- optional: true
-
- '@pkgr/core@0.2.9': {}
-
- '@prisma/adapter-pg@7.7.0':
- dependencies:
- '@prisma/driver-adapter-utils': 7.7.0
- '@types/pg': 8.20.0
- pg: 8.20.0
- postgres-array: 3.0.4
- transitivePeerDependencies:
- - pg-native
-
- '@prisma/client-runtime-utils@7.7.0': {}
-
- '@prisma/client@7.7.0(prisma@7.7.0(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(typescript@5.9.3))(typescript@5.9.3)':
- dependencies:
- '@prisma/client-runtime-utils': 7.7.0
- optionalDependencies:
- prisma: 7.7.0(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(typescript@5.9.3)
- typescript: 5.9.3
-
- '@prisma/config@7.7.0':
- dependencies:
- c12: 3.1.0
- deepmerge-ts: 7.1.5
- effect: 3.20.0
- empathic: 2.0.0
- transitivePeerDependencies:
- - magicast
-
- '@prisma/debug@7.2.0': {}
-
- '@prisma/debug@7.7.0': {}
-
- '@prisma/dev@0.24.3(typescript@5.9.3)':
- dependencies:
- '@electric-sql/pglite': 0.4.1
- '@electric-sql/pglite-socket': 0.1.1(@electric-sql/pglite@0.4.1)
- '@electric-sql/pglite-tools': 0.3.1(@electric-sql/pglite@0.4.1)
- '@hono/node-server': 1.19.11(hono@4.12.14)
- '@prisma/get-platform': 7.2.0
- '@prisma/query-plan-executor': 7.2.0
- '@prisma/streams-local': 0.1.2
- foreground-child: 3.3.1
- get-port-please: 3.2.0
- hono: 4.12.14
- http-status-codes: 2.3.0
- pathe: 2.0.3
- proper-lockfile: 4.1.2
- remeda: 2.33.4
- std-env: 3.10.0
- valibot: 1.2.0(typescript@5.9.3)
- zeptomatch: 2.1.0
- transitivePeerDependencies:
- - typescript
-
- '@prisma/driver-adapter-utils@7.7.0':
- dependencies:
- '@prisma/debug': 7.7.0
-
- '@prisma/engines-version@7.6.0-1.75cbdc1eb7150937890ad5465d861175c6624711': {}
-
- '@prisma/engines@7.7.0':
- dependencies:
- '@prisma/debug': 7.7.0
- '@prisma/engines-version': 7.6.0-1.75cbdc1eb7150937890ad5465d861175c6624711
- '@prisma/fetch-engine': 7.7.0
- '@prisma/get-platform': 7.7.0
-
- '@prisma/fetch-engine@7.7.0':
- dependencies:
- '@prisma/debug': 7.7.0
- '@prisma/engines-version': 7.6.0-1.75cbdc1eb7150937890ad5465d861175c6624711
- '@prisma/get-platform': 7.7.0
-
- '@prisma/get-platform@7.2.0':
- dependencies:
- '@prisma/debug': 7.2.0
-
- '@prisma/get-platform@7.7.0':
- dependencies:
- '@prisma/debug': 7.7.0
-
- '@prisma/query-plan-executor@7.2.0': {}
-
- '@prisma/streams-local@0.1.2':
- dependencies:
- ajv: 8.12.0
- better-result: 2.8.2
- env-paths: 3.0.0
- proper-lockfile: 4.1.2
-
- '@prisma/studio-core@0.27.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)':
- dependencies:
- '@radix-ui/react-toggle': 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
- '@types/react': 19.2.14
- chart.js: 4.5.1
- react: 19.2.6
- react-dom: 19.2.6(react@19.2.6)
- transitivePeerDependencies:
- - '@types/react-dom'
-
- '@radix-ui/primitive@1.1.3': {}
-
- '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.14)(react@19.2.6)':
- dependencies:
- react: 19.2.6
- optionalDependencies:
- '@types/react': 19.2.14
-
- '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)':
- dependencies:
- '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.6)
- react: 19.2.6
- react-dom: 19.2.6(react@19.2.6)
- optionalDependencies:
- '@types/react': 19.2.14
- '@types/react-dom': 19.2.3(@types/react@19.2.14)
-
- '@radix-ui/react-slot@1.2.3(@types/react@19.2.14)(react@19.2.6)':
- dependencies:
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.6)
- react: 19.2.6
- optionalDependencies:
- '@types/react': 19.2.14
-
- '@radix-ui/react-toggle@1.1.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)':
- dependencies:
- '@radix-ui/primitive': 1.1.3
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
- '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.6)
- react: 19.2.6
- react-dom: 19.2.6(react@19.2.6)
- optionalDependencies:
- '@types/react': 19.2.14
- '@types/react-dom': 19.2.3(@types/react@19.2.14)
-
- '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.2.14)(react@19.2.6)':
- dependencies:
- '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.14)(react@19.2.6)
- '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.6)
- react: 19.2.6
- optionalDependencies:
- '@types/react': 19.2.14
-
- '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.2.14)(react@19.2.6)':
- dependencies:
- '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.6)
- react: 19.2.6
- optionalDependencies:
- '@types/react': 19.2.14
-
- '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.14)(react@19.2.6)':
- dependencies:
- react: 19.2.6
- optionalDependencies:
- '@types/react': 19.2.14
-
- '@react-router/dev@7.15.0(@react-router/serve@7.15.0(react-router@7.15.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(typescript@5.9.3))(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(react-router@7.15.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(typescript@5.9.3)(vite@8.0.11(@types/node@22.19.17)(esbuild@0.27.7)(jiti@2.6.1)(yaml@2.8.3))(yaml@2.8.3)':
- dependencies:
- '@babel/core': 7.29.0
- '@babel/generator': 7.29.1
- '@babel/parser': 7.29.2
- '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0)
- '@babel/preset-typescript': 7.28.5(@babel/core@7.29.0)
- '@babel/traverse': 7.29.0
- '@babel/types': 7.29.0
- '@react-router/node': 7.15.0(react-router@7.15.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(typescript@5.9.3)
- '@remix-run/node-fetch-server': 0.13.1
- arg: 5.0.2
- babel-dead-code-elimination: 1.0.12
- chokidar: 4.0.3
- dedent: 1.7.2
- es-module-lexer: 1.7.0
- exit-hook: 2.2.1
- isbot: 5.1.40
- jsesc: 3.0.2
- lodash: 4.18.1
- p-map: 7.0.4
- pathe: 1.1.2
- picocolors: 1.1.1
- pkg-types: 2.3.0
- prettier: 3.8.3
- react-refresh: 0.14.2
- react-router: 7.15.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
- semver: 7.7.4
- tinyglobby: 0.2.16
- valibot: 1.2.0(typescript@5.9.3)
- vite: 8.0.11(@types/node@22.19.17)(esbuild@0.27.7)(jiti@2.6.1)(yaml@2.8.3)
- vite-node: 3.2.4(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
- optionalDependencies:
- '@react-router/serve': 7.15.0(react-router@7.15.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(typescript@5.9.3)
- typescript: 5.9.3
- transitivePeerDependencies:
- - '@types/node'
- - babel-plugin-macros
- - jiti
- - less
- - lightningcss
- - sass
- - sass-embedded
- - stylus
- - sugarss
- - supports-color
- - terser
- - tsx
- - yaml
-
- '@react-router/express@7.15.0(express@4.22.1)(react-router@7.15.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(typescript@5.9.3)':
- dependencies:
- '@react-router/node': 7.15.0(react-router@7.15.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(typescript@5.9.3)
- express: 4.22.1
- react-router: 7.15.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
- optionalDependencies:
- typescript: 5.9.3
-
- '@react-router/node@7.15.0(react-router@7.15.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(typescript@5.9.3)':
- dependencies:
- '@mjackson/node-fetch-server': 0.2.0
- react-router: 7.15.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
- optionalDependencies:
- typescript: 5.9.3
-
- '@react-router/serve@7.15.0(react-router@7.15.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(typescript@5.9.3)':
- dependencies:
- '@mjackson/node-fetch-server': 0.2.0
- '@react-router/express': 7.15.0(express@4.22.1)(react-router@7.15.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(typescript@5.9.3)
- '@react-router/node': 7.15.0(react-router@7.15.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(typescript@5.9.3)
- compression: 1.8.1
- express: 4.22.1
- get-port: 5.1.1
- morgan: 1.10.1
- react-router: 7.15.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
- source-map-support: 0.5.21
- transitivePeerDependencies:
- - supports-color
- - typescript
-
- '@remix-run/node-fetch-server@0.13.1': {}
-
- '@rolldown/binding-android-arm64@1.0.0-rc.18':
- optional: true
-
- '@rolldown/binding-darwin-arm64@1.0.0-rc.18':
- optional: true
-
- '@rolldown/binding-darwin-x64@1.0.0-rc.18':
- optional: true
-
- '@rolldown/binding-freebsd-x64@1.0.0-rc.18':
- optional: true
-
- '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.18':
- optional: true
-
- '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.18':
- optional: true
-
- '@rolldown/binding-linux-arm64-musl@1.0.0-rc.18':
- optional: true
-
- '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.18':
- optional: true
-
- '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.18':
- optional: true
-
- '@rolldown/binding-linux-x64-gnu@1.0.0-rc.18':
- optional: true
-
- '@rolldown/binding-linux-x64-musl@1.0.0-rc.18':
- optional: true
-
- '@rolldown/binding-openharmony-arm64@1.0.0-rc.18':
- optional: true
-
- '@rolldown/binding-wasm32-wasi@1.0.0-rc.18':
- dependencies:
- '@emnapi/core': 1.10.0
- '@emnapi/runtime': 1.10.0
- '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)
- optional: true
-
- '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.18':
- optional: true
-
- '@rolldown/binding-win32-x64-msvc@1.0.0-rc.18':
- optional: true
-
- '@rolldown/pluginutils@1.0.0-rc.18': {}
-
- '@rollup/rollup-android-arm-eabi@4.60.3':
- optional: true
-
- '@rollup/rollup-android-arm64@4.60.3':
- optional: true
-
- '@rollup/rollup-darwin-arm64@4.60.3':
- optional: true
-
- '@rollup/rollup-darwin-x64@4.60.3':
- optional: true
-
- '@rollup/rollup-freebsd-arm64@4.60.3':
- optional: true
-
- '@rollup/rollup-freebsd-x64@4.60.3':
- optional: true
-
- '@rollup/rollup-linux-arm-gnueabihf@4.60.3':
- optional: true
-
- '@rollup/rollup-linux-arm-musleabihf@4.60.3':
- optional: true
-
- '@rollup/rollup-linux-arm64-gnu@4.60.3':
- optional: true
-
- '@rollup/rollup-linux-arm64-musl@4.60.3':
- optional: true
-
- '@rollup/rollup-linux-loong64-gnu@4.60.3':
- optional: true
-
- '@rollup/rollup-linux-loong64-musl@4.60.3':
- optional: true
-
- '@rollup/rollup-linux-ppc64-gnu@4.60.3':
- optional: true
-
- '@rollup/rollup-linux-ppc64-musl@4.60.3':
- optional: true
-
- '@rollup/rollup-linux-riscv64-gnu@4.60.3':
- optional: true
-
- '@rollup/rollup-linux-riscv64-musl@4.60.3':
- optional: true
-
- '@rollup/rollup-linux-s390x-gnu@4.60.3':
- optional: true
-
- '@rollup/rollup-linux-x64-gnu@4.60.3':
- optional: true
-
- '@rollup/rollup-linux-x64-musl@4.60.3':
- optional: true
-
- '@rollup/rollup-openbsd-x64@4.60.3':
- optional: true
-
- '@rollup/rollup-openharmony-arm64@4.60.3':
- optional: true
-
- '@rollup/rollup-win32-arm64-msvc@4.60.3':
- optional: true
-
- '@rollup/rollup-win32-ia32-msvc@4.60.3':
- optional: true
-
- '@rollup/rollup-win32-x64-gnu@4.60.3':
- optional: true
-
- '@rollup/rollup-win32-x64-msvc@4.60.3':
- optional: true
-
- '@sapphire/async-queue@1.5.5': {}
-
- '@sapphire/discord-utilities@3.5.0':
- dependencies:
- discord-api-types: 0.38.47
-
- '@sapphire/discord-utilities@4.0.0':
- dependencies:
- discord-api-types: 0.38.47
-
- '@sapphire/discord.js-utilities@7.3.3':
- dependencies:
- '@sapphire/discord-utilities': 3.5.0
- '@sapphire/duration': 1.2.0
- '@sapphire/utilities': 3.18.2
- tslib: 2.8.1
-
- '@sapphire/duration@1.2.0': {}
-
- '@sapphire/framework@5.5.0':
- dependencies:
- '@discordjs/builders': 1.14.1
- '@sapphire/discord-utilities': 4.0.0
- '@sapphire/discord.js-utilities': 7.3.3
- '@sapphire/lexure': 1.1.12
- '@sapphire/pieces': 4.4.1
- '@sapphire/ratelimits': 2.4.11
- '@sapphire/result': 2.8.0
- '@sapphire/stopwatch': 1.5.4
- '@sapphire/utilities': 3.18.2
-
- '@sapphire/lexure@1.1.12':
- dependencies:
- '@sapphire/result': 2.8.0
-
- '@sapphire/pieces@4.4.1':
- dependencies:
- '@discordjs/collection': 2.1.1
- '@sapphire/utilities': 3.18.2
- tslib: 2.8.1
-
- '@sapphire/ratelimits@2.4.11': {}
-
- '@sapphire/result@2.8.0': {}
-
- '@sapphire/shapeshift@4.0.0':
- dependencies:
- fast-deep-equal: 3.1.3
- lodash: 4.18.1
-
- '@sapphire/snowflake@3.5.3': {}
-
- '@sapphire/snowflake@3.5.5': {}
-
- '@sapphire/stopwatch@1.5.4':
- dependencies:
- tslib: 2.8.1
-
- '@sapphire/ts-config@5.0.3':
- dependencies:
- tslib: 2.8.1
- typescript: 5.4.5
-
- '@sapphire/utilities@3.18.2': {}
-
- '@sindresorhus/base62@1.0.0': {}
-
- '@standard-schema/spec@1.1.0': {}
-
- '@stylistic/eslint-plugin-jsx@4.4.1(eslint@9.39.4(jiti@2.6.1))':
- dependencies:
- eslint: 9.39.4(jiti@2.6.1)
- eslint-visitor-keys: 4.2.1
- espree: 10.4.0
- estraverse: 5.3.0
- picomatch: 4.0.4
-
- '@stylistic/eslint-plugin-ts@4.4.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
- dependencies:
- '@typescript-eslint/utils': 8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- eslint: 9.39.4(jiti@2.6.1)
- eslint-visitor-keys: 4.2.1
- espree: 10.4.0
- transitivePeerDependencies:
- - supports-color
- - typescript
-
- '@stylistic/eslint-plugin@5.10.0(eslint@9.39.4(jiti@2.6.1))':
- dependencies:
- '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1))
- '@typescript-eslint/types': 8.58.2
- eslint: 9.39.4(jiti@2.6.1)
- eslint-visitor-keys: 4.2.1
- espree: 10.4.0
- estraverse: 5.3.0
- picomatch: 4.0.4
-
- '@tailwindcss/node@4.3.0':
- dependencies:
- '@jridgewell/remapping': 2.3.5
- enhanced-resolve: 5.21.2
- jiti: 2.6.1
- lightningcss: 1.32.0
- magic-string: 0.30.21
- source-map-js: 1.2.1
- tailwindcss: 4.3.0
-
- '@tailwindcss/oxide-android-arm64@4.3.0':
- optional: true
-
- '@tailwindcss/oxide-darwin-arm64@4.3.0':
- optional: true
-
- '@tailwindcss/oxide-darwin-x64@4.3.0':
- optional: true
-
- '@tailwindcss/oxide-freebsd-x64@4.3.0':
- optional: true
-
- '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.0':
- optional: true
-
- '@tailwindcss/oxide-linux-arm64-gnu@4.3.0':
- optional: true
-
- '@tailwindcss/oxide-linux-arm64-musl@4.3.0':
- optional: true
-
- '@tailwindcss/oxide-linux-x64-gnu@4.3.0':
- optional: true
-
- '@tailwindcss/oxide-linux-x64-musl@4.3.0':
- optional: true
-
- '@tailwindcss/oxide-wasm32-wasi@4.3.0':
- optional: true
-
- '@tailwindcss/oxide-win32-arm64-msvc@4.3.0':
- optional: true
-
- '@tailwindcss/oxide-win32-x64-msvc@4.3.0':
- optional: true
-
- '@tailwindcss/oxide@4.3.0':
- optionalDependencies:
- '@tailwindcss/oxide-android-arm64': 4.3.0
- '@tailwindcss/oxide-darwin-arm64': 4.3.0
- '@tailwindcss/oxide-darwin-x64': 4.3.0
- '@tailwindcss/oxide-freebsd-x64': 4.3.0
- '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.0
- '@tailwindcss/oxide-linux-arm64-gnu': 4.3.0
- '@tailwindcss/oxide-linux-arm64-musl': 4.3.0
- '@tailwindcss/oxide-linux-x64-gnu': 4.3.0
- '@tailwindcss/oxide-linux-x64-musl': 4.3.0
- '@tailwindcss/oxide-wasm32-wasi': 4.3.0
- '@tailwindcss/oxide-win32-arm64-msvc': 4.3.0
- '@tailwindcss/oxide-win32-x64-msvc': 4.3.0
-
- '@tailwindcss/vite@4.3.0(vite@8.0.11(@types/node@22.19.17)(esbuild@0.27.7)(jiti@2.6.1)(yaml@2.8.3))':
- dependencies:
- '@tailwindcss/node': 4.3.0
- '@tailwindcss/oxide': 4.3.0
- tailwindcss: 4.3.0
- vite: 8.0.11(@types/node@22.19.17)(esbuild@0.27.7)(jiti@2.6.1)(yaml@2.8.3)
-
- '@turbo/darwin-64@2.9.14':
- optional: true
-
- '@turbo/darwin-arm64@2.9.14':
- optional: true
-
- '@turbo/linux-64@2.9.14':
- optional: true
-
- '@turbo/linux-arm64@2.9.14':
- optional: true
-
- '@turbo/windows-64@2.9.14':
- optional: true
-
- '@turbo/windows-arm64@2.9.14':
- optional: true
-
- '@tybys/wasm-util@0.10.1':
- dependencies:
- tslib: 2.8.1
- optional: true
-
- '@types/concat-stream@2.0.3':
- dependencies:
- '@types/node': 22.19.17
-
- '@types/debug@4.1.13':
- dependencies:
- '@types/ms': 2.1.0
-
- '@types/eslint@9.6.1':
- dependencies:
- '@types/estree': 1.0.8
- '@types/json-schema': 7.0.15
-
- '@types/esrecurse@4.3.1': {}
-
- '@types/estree-jsx@1.0.5':
- dependencies:
- '@types/estree': 1.0.8
-
- '@types/estree@1.0.8': {}
-
- '@types/hast@3.0.4':
- dependencies:
- '@types/unist': 3.0.3
-
- '@types/is-empty@1.2.3': {}
-
- '@types/json-schema@7.0.15': {}
-
- '@types/lodash.merge@4.6.9':
- dependencies:
- '@types/lodash': 4.17.24
-
- '@types/lodash@4.17.24': {}
-
- '@types/mdast@4.0.4':
- dependencies:
- '@types/unist': 3.0.3
-
- '@types/ms@2.1.0': {}
-
- '@types/node@22.19.17':
- dependencies:
- undici-types: 6.21.0
-
- '@types/pg@8.20.0':
- dependencies:
- '@types/node': 22.19.17
- pg-protocol: 1.13.0
- pg-types: 2.2.0
-
- '@types/react-dom@19.2.3(@types/react@19.2.14)':
- dependencies:
- '@types/react': 19.2.14
-
- '@types/react@19.2.14':
- dependencies:
- csstype: 3.2.3
-
- '@types/semver@7.7.1': {}
-
- '@types/supports-color@8.1.3': {}
-
- '@types/unist@2.0.11': {}
-
- '@types/unist@3.0.3': {}
-
- '@types/ws@8.18.1':
- dependencies:
- '@types/node': 22.19.17
-
- '@types/yargs-parser@21.0.3': {}
-
- '@types/yargs@17.0.35':
- dependencies:
- '@types/yargs-parser': 21.0.3
-
- '@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
- dependencies:
- '@eslint-community/regexpp': 4.12.2
- '@typescript-eslint/parser': 8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/scope-manager': 8.58.2
- '@typescript-eslint/type-utils': 8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/utils': 8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/visitor-keys': 8.58.2
- eslint: 9.39.4(jiti@2.6.1)
- ignore: 7.0.5
- natural-compare: 1.4.0
- ts-api-utils: 2.5.0(typescript@5.9.3)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/experimental-utils@5.62.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
- dependencies:
- '@typescript-eslint/utils': 5.62.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- eslint: 9.39.4(jiti@2.6.1)
- transitivePeerDependencies:
- - supports-color
- - typescript
-
- '@typescript-eslint/parser@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
- dependencies:
- '@typescript-eslint/scope-manager': 8.58.2
- '@typescript-eslint/types': 8.58.2
- '@typescript-eslint/typescript-estree': 8.58.2(typescript@5.9.3)
- '@typescript-eslint/visitor-keys': 8.58.2
- debug: 4.4.3
- eslint: 9.39.4(jiti@2.6.1)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/project-service@8.58.2(typescript@5.9.3)':
- dependencies:
- '@typescript-eslint/tsconfig-utils': 8.58.2(typescript@5.9.3)
- '@typescript-eslint/types': 8.58.2
- debug: 4.4.3
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/scope-manager@5.62.0':
- dependencies:
- '@typescript-eslint/types': 5.62.0
- '@typescript-eslint/visitor-keys': 5.62.0
-
- '@typescript-eslint/scope-manager@8.58.2':
- dependencies:
- '@typescript-eslint/types': 8.58.2
- '@typescript-eslint/visitor-keys': 8.58.2
-
- '@typescript-eslint/tsconfig-utils@8.58.2(typescript@5.9.3)':
- dependencies:
- typescript: 5.9.3
-
- '@typescript-eslint/type-utils@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
- dependencies:
- '@typescript-eslint/types': 8.58.2
- '@typescript-eslint/typescript-estree': 8.58.2(typescript@5.9.3)
- '@typescript-eslint/utils': 8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- debug: 4.4.3
- eslint: 9.39.4(jiti@2.6.1)
- ts-api-utils: 2.5.0(typescript@5.9.3)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/types@5.62.0': {}
-
- '@typescript-eslint/types@8.58.2': {}
-
- '@typescript-eslint/typescript-estree@5.62.0(typescript@5.9.3)':
- dependencies:
- '@typescript-eslint/types': 5.62.0
- '@typescript-eslint/visitor-keys': 5.62.0
- debug: 4.4.3
- globby: 11.1.0
- is-glob: 4.0.3
- semver: 7.7.4
- tsutils: 3.21.0(typescript@5.9.3)
- optionalDependencies:
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/typescript-estree@8.58.2(typescript@5.9.3)':
- dependencies:
- '@typescript-eslint/project-service': 8.58.2(typescript@5.9.3)
- '@typescript-eslint/tsconfig-utils': 8.58.2(typescript@5.9.3)
- '@typescript-eslint/types': 8.58.2
- '@typescript-eslint/visitor-keys': 8.58.2
- debug: 4.4.3
- minimatch: 10.2.5
- semver: 7.7.4
- tinyglobby: 0.2.16
- ts-api-utils: 2.5.0(typescript@5.9.3)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/utils@5.62.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
- dependencies:
- '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1))
- '@types/json-schema': 7.0.15
- '@types/semver': 7.7.1
- '@typescript-eslint/scope-manager': 5.62.0
- '@typescript-eslint/types': 5.62.0
- '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.9.3)
- eslint: 9.39.4(jiti@2.6.1)
- eslint-scope: 5.1.1
- semver: 7.7.4
- transitivePeerDependencies:
- - supports-color
- - typescript
-
- '@typescript-eslint/utils@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
- dependencies:
- '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1))
- '@typescript-eslint/scope-manager': 8.58.2
- '@typescript-eslint/types': 8.58.2
- '@typescript-eslint/typescript-estree': 8.58.2(typescript@5.9.3)
- eslint: 9.39.4(jiti@2.6.1)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/visitor-keys@5.62.0':
- dependencies:
- '@typescript-eslint/types': 5.62.0
- eslint-visitor-keys: 3.4.3
-
- '@typescript-eslint/visitor-keys@8.58.2':
- dependencies:
- '@typescript-eslint/types': 8.58.2
- eslint-visitor-keys: 5.0.1
-
- '@unrs/resolver-binding-android-arm-eabi@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-android-arm64@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-darwin-arm64@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-darwin-x64@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-freebsd-x64@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-arm64-gnu@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-arm64-musl@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-x64-gnu@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-x64-musl@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-wasm32-wasi@1.11.1':
- dependencies:
- '@napi-rs/wasm-runtime': 0.2.12
- optional: true
-
- '@unrs/resolver-binding-win32-arm64-msvc@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-win32-ia32-msvc@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-win32-x64-msvc@1.11.1':
- optional: true
-
- '@vladfrangu/async_event_emitter@2.4.7': {}
-
- abbrev@2.0.0: {}
-
- accepts@1.3.8:
- dependencies:
- mime-types: 2.1.35
- negotiator: 0.6.3
-
- acorn-jsx@5.3.2(acorn@8.16.0):
- dependencies:
- acorn: 8.16.0
-
- acorn@8.16.0: {}
-
- ajv@6.14.0:
- dependencies:
- fast-deep-equal: 3.1.3
- fast-json-stable-stringify: 2.1.0
- json-schema-traverse: 0.4.1
- uri-js: 4.4.1
-
- ajv@8.12.0:
- dependencies:
- fast-deep-equal: 3.1.3
- json-schema-traverse: 1.0.0
- require-from-string: 2.0.2
- uri-js: 4.4.1
-
- ansi-escapes@7.3.0:
- dependencies:
- environment: 1.1.0
-
- ansi-regex@5.0.1: {}
-
- ansi-regex@6.2.2: {}
-
- ansi-styles@4.3.0:
- dependencies:
- color-convert: 2.0.1
-
- ansi-styles@6.2.3: {}
-
- are-docs-informative@0.0.2: {}
-
- arg@5.0.2: {}
-
- argparse@2.0.1: {}
-
- aria-query@5.3.2: {}
-
- array-buffer-byte-length@1.0.2:
- dependencies:
- call-bound: 1.0.4
- is-array-buffer: 3.0.5
-
- array-flatten@1.1.1: {}
-
- array-includes@3.1.9:
- dependencies:
- call-bind: 1.0.9
- call-bound: 1.0.4
- define-properties: 1.2.1
- es-abstract: 1.24.2
- es-object-atoms: 1.1.1
- get-intrinsic: 1.3.0
- is-string: 1.1.1
- math-intrinsics: 1.1.0
-
- array-union@2.1.0: {}
-
- array.prototype.findlast@1.2.5:
- dependencies:
- call-bind: 1.0.9
- define-properties: 1.2.1
- es-abstract: 1.24.2
- es-errors: 1.3.0
- es-object-atoms: 1.1.1
- es-shim-unscopables: 1.1.0
-
- array.prototype.flat@1.3.3:
- dependencies:
- call-bind: 1.0.9
- define-properties: 1.2.1
- es-abstract: 1.24.2
- es-shim-unscopables: 1.1.0
-
- array.prototype.flatmap@1.3.3:
- dependencies:
- call-bind: 1.0.9
- define-properties: 1.2.1
- es-abstract: 1.24.2
- es-shim-unscopables: 1.1.0
-
- array.prototype.tosorted@1.1.4:
- dependencies:
- call-bind: 1.0.9
- define-properties: 1.2.1
- es-abstract: 1.24.2
- es-errors: 1.3.0
- es-shim-unscopables: 1.1.0
-
- arraybuffer.prototype.slice@1.0.4:
- dependencies:
- array-buffer-byte-length: 1.0.2
- call-bind: 1.0.9
- define-properties: 1.2.1
- es-abstract: 1.24.2
- es-errors: 1.3.0
- get-intrinsic: 1.3.0
- is-array-buffer: 3.0.5
-
- ast-types-flow@0.0.8: {}
-
- astro-eslint-parser@1.4.0:
- dependencies:
- '@astrojs/compiler': 3.0.1
- '@typescript-eslint/scope-manager': 8.58.2
- '@typescript-eslint/types': 8.58.2
- astrojs-compiler-sync: 1.1.1(@astrojs/compiler@3.0.1)
- debug: 4.4.3
- entities: 7.0.1
- eslint-scope: 8.4.0
- eslint-visitor-keys: 4.2.1
- espree: 10.4.0
- fast-glob: 3.3.3
- is-glob: 4.0.3
- semver: 7.7.4
- transitivePeerDependencies:
- - supports-color
-
- astrojs-compiler-sync@1.1.1(@astrojs/compiler@3.0.1):
- dependencies:
- '@astrojs/compiler': 3.0.1
- synckit: 0.11.12
-
- async-function@1.0.0: {}
-
- available-typed-arrays@1.0.7:
- dependencies:
- possible-typed-array-names: 1.1.0
-
- aws-ssl-profiles@1.1.2: {}
-
- axe-core@4.11.3: {}
-
- axobject-query@4.1.0: {}
-
- babel-dead-code-elimination@1.0.12:
- dependencies:
- '@babel/core': 7.29.0
- '@babel/parser': 7.29.2
- '@babel/traverse': 7.29.0
- '@babel/types': 7.29.0
- transitivePeerDependencies:
- - supports-color
-
- bail@2.0.2: {}
-
- balanced-match@1.0.2: {}
-
- balanced-match@4.0.4: {}
-
- baseline-browser-mapping@2.10.19: {}
-
- basic-auth@2.0.1:
- dependencies:
- safe-buffer: 5.1.2
-
- bent@7.3.12:
- dependencies:
- bytesish: 0.4.4
- caseless: 0.12.0
- is-stream: 2.0.1
-
- better-result@2.8.2: {}
-
- body-parser@1.20.5:
- dependencies:
- bytes: 3.1.2
- content-type: 1.0.5
- debug: 2.6.9
- depd: 2.0.0
- destroy: 1.2.0
- http-errors: 2.0.1
- iconv-lite: 0.4.24
- on-finished: 2.4.1
- qs: 6.15.1
- raw-body: 2.5.3
- type-is: 1.6.18
- unpipe: 1.0.0
- transitivePeerDependencies:
- - supports-color
-
- boolbase@1.0.0: {}
-
- brace-expansion@1.1.14:
- dependencies:
- balanced-match: 1.0.2
- concat-map: 0.0.1
-
- brace-expansion@2.1.0:
- dependencies:
- balanced-match: 1.0.2
-
- brace-expansion@5.0.5:
- dependencies:
- balanced-match: 4.0.4
-
- braces@3.0.3:
- dependencies:
- fill-range: 7.1.1
-
- browserslist@4.28.2:
- dependencies:
- baseline-browser-mapping: 2.10.19
- caniuse-lite: 1.0.30001788
- electron-to-chromium: 1.5.340
- node-releases: 2.0.37
- update-browserslist-db: 1.2.3(browserslist@4.28.2)
-
- buffer-from@1.1.2: {}
-
- builtin-modules@3.3.0: {}
-
- builtin-modules@5.1.0: {}
-
- bytes@3.1.2: {}
-
- bytesish@0.4.4: {}
-
- c12@3.1.0:
- dependencies:
- chokidar: 4.0.3
- confbox: 0.2.4
- defu: 6.1.7
- dotenv: 16.6.1
- exsolve: 1.0.8
- giget: 2.0.0
- jiti: 2.6.1
- ohash: 2.0.11
- pathe: 2.0.3
- perfect-debounce: 1.0.0
- pkg-types: 2.3.0
- rc9: 2.1.2
-
- cac@6.7.14: {}
-
- call-bind-apply-helpers@1.0.2:
- dependencies:
- es-errors: 1.3.0
- function-bind: 1.1.2
-
- call-bind@1.0.9:
- dependencies:
- call-bind-apply-helpers: 1.0.2
- es-define-property: 1.0.1
- get-intrinsic: 1.3.0
- set-function-length: 1.2.2
-
- call-bound@1.0.4:
- dependencies:
- call-bind-apply-helpers: 1.0.2
- get-intrinsic: 1.3.0
-
- callsites@3.1.0: {}
-
- caniuse-lite@1.0.30001788: {}
-
- caseless@0.12.0: {}
-
- ccount@2.0.1: {}
-
- chalk@4.1.2:
- dependencies:
- ansi-styles: 4.3.0
- supports-color: 7.2.0
-
- chalk@5.6.2: {}
-
- change-case@5.4.4: {}
-
- character-entities-html4@2.1.0: {}
-
- character-entities-legacy@3.0.0: {}
-
- character-entities@2.0.2: {}
-
- character-reference-invalid@2.0.1: {}
-
- chart.js@4.5.1:
- dependencies:
- '@kurkle/color': 0.3.4
-
- chokidar@4.0.3:
- dependencies:
- readdirp: 4.1.2
-
- ci-info@4.4.0: {}
-
- citty@0.1.6:
- dependencies:
- consola: 3.4.2
-
- citty@0.2.2: {}
-
- clean-regexp@1.0.0:
- dependencies:
- escape-string-regexp: 1.0.5
-
- cliui@8.0.1:
- dependencies:
- string-width: 4.2.3
- strip-ansi: 6.0.1
- wrap-ansi: 7.0.0
-
- color-convert@2.0.1:
- dependencies:
- color-name: 1.1.4
-
- color-name@1.1.4: {}
-
- comment-parser@1.4.1: {}
-
- comment-parser@1.4.6: {}
-
- common-tags@1.8.2: {}
-
- compressible@2.0.18:
- dependencies:
- mime-db: 1.54.0
-
- compression@1.8.1:
- dependencies:
- bytes: 3.1.2
- compressible: 2.0.18
- debug: 2.6.9
- negotiator: 0.6.4
- on-headers: 1.1.0
- safe-buffer: 5.2.1
- vary: 1.1.2
- transitivePeerDependencies:
- - supports-color
-
- concat-map@0.0.1: {}
-
- concat-stream@2.0.0:
- dependencies:
- buffer-from: 1.1.2
- inherits: 2.0.4
- readable-stream: 3.6.2
- typedarray: 0.0.6
-
- concurrently@9.2.1:
- dependencies:
- chalk: 4.1.2
- rxjs: 7.8.2
- shell-quote: 1.8.3
- supports-color: 8.1.1
- tree-kill: 1.2.2
- yargs: 17.7.2
-
- confbox@0.2.4: {}
-
- consola@3.4.2: {}
-
- content-disposition@0.5.4:
- dependencies:
- safe-buffer: 5.2.1
-
- content-type@1.0.5: {}
-
- convert-source-map@2.0.0: {}
-
- cookie-signature@1.0.7: {}
-
- cookie@0.7.2: {}
-
- cookie@1.1.1: {}
-
- core-js-compat@3.49.0:
- dependencies:
- browserslist: 4.28.2
-
- cross-spawn@7.0.6:
- dependencies:
- path-key: 3.1.1
- shebang-command: 2.0.0
- which: 2.0.2
-
- cssesc@3.0.0: {}
-
- csstype@3.2.3: {}
-
- damerau-levenshtein@1.0.8: {}
-
- data-view-buffer@1.0.2:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- is-data-view: 1.0.2
-
- data-view-byte-length@1.0.2:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- is-data-view: 1.0.2
-
- data-view-byte-offset@1.0.1:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- is-data-view: 1.0.2
-
- debug@2.6.9:
- dependencies:
- ms: 2.0.0
-
- debug@4.4.3:
- dependencies:
- ms: 2.1.3
-
- decamelize@5.0.1: {}
-
- decode-named-character-reference@1.3.0:
- dependencies:
- character-entities: 2.0.2
-
- dedent@1.7.2: {}
-
- deep-is@0.1.4: {}
-
- deepmerge-ts@7.1.5: {}
-
- define-data-property@1.1.4:
- dependencies:
- es-define-property: 1.0.1
- es-errors: 1.3.0
- gopd: 1.2.0
-
- define-properties@1.2.1:
- dependencies:
- define-data-property: 1.1.4
- has-property-descriptors: 1.0.2
- object-keys: 1.1.1
-
- defu@6.1.7: {}
-
- denque@2.1.0: {}
-
- depd@2.0.0: {}
-
- dequal@2.0.3: {}
-
- destr@2.0.5: {}
-
- destroy@1.2.0: {}
-
- detect-libc@2.1.2: {}
-
- devlop@1.1.0:
- dependencies:
- dequal: 2.0.3
-
- dir-glob@3.0.1:
- dependencies:
- path-type: 4.0.0
-
- discord-api-types@0.38.47: {}
-
- discord.js@14.26.4:
- dependencies:
- '@discordjs/builders': 1.14.1
- '@discordjs/collection': 1.5.3
- '@discordjs/formatters': 0.6.2
- '@discordjs/rest': 2.6.1
- '@discordjs/util': 1.2.0
- '@discordjs/ws': 1.2.3
- '@sapphire/snowflake': 3.5.3
- discord-api-types: 0.38.47
- fast-deep-equal: 3.1.3
- lodash.snakecase: 4.1.1
- magic-bytes.js: 1.13.0
- tslib: 2.8.1
- undici: 6.24.1
- transitivePeerDependencies:
- - bufferutil
- - utf-8-validate
-
- doctrine@2.1.0:
- dependencies:
- esutils: 2.0.3
-
- dotenv@16.6.1: {}
-
- dotenv@17.4.2: {}
-
- dunder-proto@1.0.1:
- dependencies:
- call-bind-apply-helpers: 1.0.2
- es-errors: 1.3.0
- gopd: 1.2.0
-
- eastasianwidth@0.2.0: {}
-
- ee-first@1.1.1: {}
-
- effect@3.20.0:
- dependencies:
- '@standard-schema/spec': 1.1.0
- fast-check: 3.23.2
-
- electron-to-chromium@1.5.340: {}
-
- emoji-regex@10.6.0: {}
-
- emoji-regex@8.0.0: {}
-
- emoji-regex@9.2.2: {}
-
- empathic@2.0.0: {}
-
- encodeurl@2.0.0: {}
-
- enhanced-resolve@5.20.1:
- dependencies:
- graceful-fs: 4.2.11
- tapable: 2.3.2
-
- enhanced-resolve@5.21.2:
- dependencies:
- graceful-fs: 4.2.11
- tapable: 2.3.3
-
- entities@7.0.1: {}
-
- env-paths@3.0.0: {}
-
- environment@1.1.0: {}
-
- err-code@2.0.3: {}
-
- error-ex@1.3.4:
- dependencies:
- is-arrayish: 0.2.1
-
- es-abstract@1.24.2:
- dependencies:
- array-buffer-byte-length: 1.0.2
- arraybuffer.prototype.slice: 1.0.4
- available-typed-arrays: 1.0.7
- call-bind: 1.0.9
- call-bound: 1.0.4
- data-view-buffer: 1.0.2
- data-view-byte-length: 1.0.2
- data-view-byte-offset: 1.0.1
- es-define-property: 1.0.1
- es-errors: 1.3.0
- es-object-atoms: 1.1.1
- es-set-tostringtag: 2.1.0
- es-to-primitive: 1.3.0
- function.prototype.name: 1.1.8
- get-intrinsic: 1.3.0
- get-proto: 1.0.1
- get-symbol-description: 1.1.0
- globalthis: 1.0.4
- gopd: 1.2.0
- has-property-descriptors: 1.0.2
- has-proto: 1.2.0
- has-symbols: 1.1.0
- hasown: 2.0.2
- internal-slot: 1.1.0
- is-array-buffer: 3.0.5
- is-callable: 1.2.7
- is-data-view: 1.0.2
- is-negative-zero: 2.0.3
- is-regex: 1.2.1
- is-set: 2.0.3
- is-shared-array-buffer: 1.0.4
- is-string: 1.1.1
- is-typed-array: 1.1.15
- is-weakref: 1.1.1
- math-intrinsics: 1.1.0
- object-inspect: 1.13.4
- object-keys: 1.1.1
- object.assign: 4.1.7
- own-keys: 1.0.1
- regexp.prototype.flags: 1.5.4
- safe-array-concat: 1.1.3
- safe-push-apply: 1.0.0
- safe-regex-test: 1.1.0
- set-proto: 1.0.0
- stop-iteration-iterator: 1.1.0
- string.prototype.trim: 1.2.10
- string.prototype.trimend: 1.0.9
- string.prototype.trimstart: 1.0.8
- typed-array-buffer: 1.0.3
- typed-array-byte-length: 1.0.3
- typed-array-byte-offset: 1.0.4
- typed-array-length: 1.0.7
- unbox-primitive: 1.1.0
- which-typed-array: 1.1.20
-
- es-define-property@1.0.1: {}
-
- es-errors@1.3.0: {}
-
- es-iterator-helpers@1.3.2:
- dependencies:
- call-bind: 1.0.9
- call-bound: 1.0.4
- define-properties: 1.2.1
- es-abstract: 1.24.2
- es-errors: 1.3.0
- es-set-tostringtag: 2.1.0
- function-bind: 1.1.2
- get-intrinsic: 1.3.0
- globalthis: 1.0.4
- gopd: 1.2.0
- has-property-descriptors: 1.0.2
- has-proto: 1.2.0
- has-symbols: 1.1.0
- internal-slot: 1.1.0
- iterator.prototype: 1.1.5
- math-intrinsics: 1.1.0
-
- es-module-lexer@1.7.0: {}
-
- es-object-atoms@1.1.1:
- dependencies:
- es-errors: 1.3.0
-
- es-set-tostringtag@2.1.0:
- dependencies:
- es-errors: 1.3.0
- get-intrinsic: 1.3.0
- has-tostringtag: 1.0.2
- hasown: 2.0.2
-
- es-shim-unscopables@1.1.0:
- dependencies:
- hasown: 2.0.2
-
- es-to-primitive@1.3.0:
- dependencies:
- is-callable: 1.2.7
- is-date-object: 1.1.0
- is-symbol: 1.1.1
-
- esbuild@0.27.7:
- optionalDependencies:
- '@esbuild/aix-ppc64': 0.27.7
- '@esbuild/android-arm': 0.27.7
- '@esbuild/android-arm64': 0.27.7
- '@esbuild/android-x64': 0.27.7
- '@esbuild/darwin-arm64': 0.27.7
- '@esbuild/darwin-x64': 0.27.7
- '@esbuild/freebsd-arm64': 0.27.7
- '@esbuild/freebsd-x64': 0.27.7
- '@esbuild/linux-arm': 0.27.7
- '@esbuild/linux-arm64': 0.27.7
- '@esbuild/linux-ia32': 0.27.7
- '@esbuild/linux-loong64': 0.27.7
- '@esbuild/linux-mips64el': 0.27.7
- '@esbuild/linux-ppc64': 0.27.7
- '@esbuild/linux-riscv64': 0.27.7
- '@esbuild/linux-s390x': 0.27.7
- '@esbuild/linux-x64': 0.27.7
- '@esbuild/netbsd-arm64': 0.27.7
- '@esbuild/netbsd-x64': 0.27.7
- '@esbuild/openbsd-arm64': 0.27.7
- '@esbuild/openbsd-x64': 0.27.7
- '@esbuild/openharmony-arm64': 0.27.7
- '@esbuild/sunos-x64': 0.27.7
- '@esbuild/win32-arm64': 0.27.7
- '@esbuild/win32-ia32': 0.27.7
- '@esbuild/win32-x64': 0.27.7
-
- escalade@3.2.0: {}
-
- escape-html@1.0.3: {}
-
- escape-string-regexp@1.0.5: {}
-
- escape-string-regexp@4.0.0: {}
-
- eslint-compat-utils@0.5.1(eslint@9.39.4(jiti@2.6.1)):
- dependencies:
- eslint: 9.39.4(jiti@2.6.1)
- semver: 7.7.4
-
- eslint-compat-utils@0.6.5(eslint@9.39.4(jiti@2.6.1)):
- dependencies:
- eslint: 9.39.4(jiti@2.6.1)
- semver: 7.7.4
-
- eslint-config-neon@0.2.9(@typescript-eslint/types@8.58.2)(@typescript-eslint/utils@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(svelte@3.59.2)(typescript@5.9.3):
- dependencies:
- '@angular-eslint/eslint-plugin': 20.7.0(@typescript-eslint/utils@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- '@angular-eslint/eslint-plugin-template': 20.7.0(@angular-eslint/template-parser@20.7.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(@typescript-eslint/types@8.58.2)(@typescript-eslint/utils@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- '@angular-eslint/template-parser': 20.7.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- '@eslint/compat': 1.4.1(eslint@9.39.4(jiti@2.6.1))
- '@next/eslint-plugin-next': 15.5.15
- '@stylistic/eslint-plugin': 5.10.0(eslint@9.39.4(jiti@2.6.1))
- '@stylistic/eslint-plugin-jsx': 4.4.1(eslint@9.39.4(jiti@2.6.1))
- '@stylistic/eslint-plugin-ts': 4.4.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- '@types/lodash.merge': 4.6.9
- '@typescript-eslint/eslint-plugin': 8.58.2(@typescript-eslint/parser@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/parser': 8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- astro-eslint-parser: 1.4.0
- eslint-config-prettier: 10.1.8(eslint@9.39.4(jiti@2.6.1))
- eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import-x@4.16.2(@typescript-eslint/utils@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1))
- eslint-mdx: 3.7.0(eslint@9.39.4(jiti@2.6.1))
- eslint-plugin-astro: 1.7.0(eslint@9.39.4(jiti@2.6.1))
- eslint-plugin-cypress: 5.3.0(eslint@9.39.4(jiti@2.6.1))
- eslint-plugin-import-x: 4.16.2(@typescript-eslint/utils@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))
- eslint-plugin-jsdoc: 61.7.1(eslint@9.39.4(jiti@2.6.1))
- eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.4(jiti@2.6.1))
- eslint-plugin-mdx: 3.7.0(eslint@9.39.4(jiti@2.6.1))
- eslint-plugin-n: 17.24.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- eslint-plugin-promise: 7.2.1(eslint@9.39.4(jiti@2.6.1))
- eslint-plugin-react: 7.37.5(eslint@9.39.4(jiti@2.6.1))
- eslint-plugin-react-hooks: 7.1.0(eslint@9.39.4(jiti@2.6.1))
- eslint-plugin-react-refresh: 0.4.26(eslint@9.39.4(jiti@2.6.1))
- eslint-plugin-rxjs: 5.0.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- eslint-plugin-rxjs-angular: 2.0.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- eslint-plugin-sonarjs: 3.0.7(eslint@9.39.4(jiti@2.6.1))
- eslint-plugin-svelte3: 4.0.0(eslint@9.39.4(jiti@2.6.1))(svelte@3.59.2)
- eslint-plugin-tsdoc: 0.4.0
- eslint-plugin-typescript-sort-keys: 3.3.0(@typescript-eslint/parser@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- eslint-plugin-unicorn: 61.0.2(eslint@9.39.4(jiti@2.6.1))
- eslint-plugin-vue: 10.8.0(@stylistic/eslint-plugin@5.10.0(eslint@9.39.4(jiti@2.6.1)))(@typescript-eslint/parser@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(vue-eslint-parser@10.4.0(eslint@9.39.4(jiti@2.6.1)))
- globals: 16.5.0
- lodash.merge: 4.6.2
- typescript-eslint: 8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- vue-eslint-parser: 10.4.0(eslint@9.39.4(jiti@2.6.1))
- transitivePeerDependencies:
- - '@typescript-eslint/types'
- - '@typescript-eslint/utils'
- - bluebird
- - eslint
- - eslint-import-resolver-node
- - eslint-plugin-import
- - remark-lint-file-extension
- - supports-color
- - svelte
- - typescript
-
- eslint-config-prettier@10.1.8(eslint@9.39.4(jiti@2.6.1)):
- dependencies:
- eslint: 9.39.4(jiti@2.6.1)
-
- eslint-etc@5.2.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3):
- dependencies:
- '@typescript-eslint/experimental-utils': 5.62.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- eslint: 9.39.4(jiti@2.6.1)
- tsutils: 3.21.0(typescript@5.9.3)
- tsutils-etc: 1.4.2(tsutils@3.21.0(typescript@5.9.3))(typescript@5.9.3)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
- eslint-formatter-compact@8.40.0: {}
-
- eslint-formatter-pretty@7.1.0:
- dependencies:
- '@types/eslint': 9.6.1
- ansi-escapes: 7.3.0
- chalk: 5.6.2
- eslint-rule-docs: 1.1.235
- log-symbols: 7.0.1
- plur: 5.1.0
- string-width: 8.2.0
- supports-hyperlinks: 4.4.0
-
- eslint-import-context@0.1.9(unrs-resolver@1.11.1):
- dependencies:
- get-tsconfig: 4.14.0
- stable-hash-x: 0.2.0
- optionalDependencies:
- unrs-resolver: 1.11.1
-
- eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.2(@typescript-eslint/utils@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)):
- dependencies:
- debug: 4.4.3
- eslint: 9.39.4(jiti@2.6.1)
- eslint-import-context: 0.1.9(unrs-resolver@1.11.1)
- get-tsconfig: 4.14.0
- is-bun-module: 2.0.0
- stable-hash-x: 0.2.0
- tinyglobby: 0.2.16
- unrs-resolver: 1.11.1
- optionalDependencies:
- eslint-plugin-import-x: 4.16.2(@typescript-eslint/utils@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))
- transitivePeerDependencies:
- - supports-color
-
- eslint-mdx@3.7.0(eslint@9.39.4(jiti@2.6.1)):
- dependencies:
- acorn: 8.16.0
- acorn-jsx: 5.3.2(acorn@8.16.0)
- eslint: 9.39.4(jiti@2.6.1)
- espree: 10.4.0
- estree-util-visit: 2.0.0
- remark-mdx: 3.1.1
- remark-parse: 11.0.0
- remark-stringify: 11.0.0
- synckit: 0.11.12
- unified: 11.0.5
- unified-engine: 11.2.2
- unist-util-visit: 5.1.0
- vfile: 6.0.3
- transitivePeerDependencies:
- - bluebird
- - supports-color
-
- eslint-plugin-astro@1.7.0(eslint@9.39.4(jiti@2.6.1)):
- dependencies:
- '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1))
- '@jridgewell/sourcemap-codec': 1.5.5
- '@typescript-eslint/types': 8.58.2
- astro-eslint-parser: 1.4.0
- eslint: 9.39.4(jiti@2.6.1)
- eslint-compat-utils: 0.6.5(eslint@9.39.4(jiti@2.6.1))
- globals: 16.5.0
- postcss: 8.5.10
- postcss-selector-parser: 7.1.1
- transitivePeerDependencies:
- - supports-color
-
- eslint-plugin-cypress@5.3.0(eslint@9.39.4(jiti@2.6.1)):
- dependencies:
- eslint: 9.39.4(jiti@2.6.1)
- globals: 16.5.0
-
- eslint-plugin-es-x@7.8.0(eslint@9.39.4(jiti@2.6.1)):
- dependencies:
- '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1))
- '@eslint-community/regexpp': 4.12.2
- eslint: 9.39.4(jiti@2.6.1)
- eslint-compat-utils: 0.5.1(eslint@9.39.4(jiti@2.6.1))
-
- eslint-plugin-import-x@4.16.2(@typescript-eslint/utils@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)):
- dependencies:
- '@package-json/types': 0.0.12
- '@typescript-eslint/types': 8.58.2
- comment-parser: 1.4.6
- debug: 4.4.3
- eslint: 9.39.4(jiti@2.6.1)
- eslint-import-context: 0.1.9(unrs-resolver@1.11.1)
- is-glob: 4.0.3
- minimatch: 10.2.5
- semver: 7.7.4
- stable-hash-x: 0.2.0
- unrs-resolver: 1.11.1
- optionalDependencies:
- '@typescript-eslint/utils': 8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- transitivePeerDependencies:
- - supports-color
-
- eslint-plugin-jsdoc@61.7.1(eslint@9.39.4(jiti@2.6.1)):
- dependencies:
- '@es-joy/jsdoccomment': 0.78.0
- '@es-joy/resolve.exports': 1.2.0
- are-docs-informative: 0.0.2
- comment-parser: 1.4.1
- debug: 4.4.3
- escape-string-regexp: 4.0.0
- eslint: 9.39.4(jiti@2.6.1)
- espree: 11.2.0
- esquery: 1.7.0
- html-entities: 2.6.0
- object-deep-merge: 2.0.0
- parse-imports-exports: 0.2.4
- semver: 7.7.4
- spdx-expression-parse: 4.0.0
- to-valid-identifier: 1.0.0
- transitivePeerDependencies:
- - supports-color
-
- eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.4(jiti@2.6.1)):
- dependencies:
- aria-query: 5.3.2
- array-includes: 3.1.9
- array.prototype.flatmap: 1.3.3
- ast-types-flow: 0.0.8
- axe-core: 4.11.3
- axobject-query: 4.1.0
- damerau-levenshtein: 1.0.8
- emoji-regex: 9.2.2
- eslint: 9.39.4(jiti@2.6.1)
- hasown: 2.0.2
- jsx-ast-utils: 3.3.5
- language-tags: 1.0.9
- minimatch: 3.1.5
- object.fromentries: 2.0.8
- safe-regex-test: 1.1.0
- string.prototype.includes: 2.0.1
-
- eslint-plugin-mdx@3.7.0(eslint@9.39.4(jiti@2.6.1)):
- dependencies:
- eslint: 9.39.4(jiti@2.6.1)
- eslint-mdx: 3.7.0(eslint@9.39.4(jiti@2.6.1))
- mdast-util-from-markdown: 2.0.3
- mdast-util-mdx: 3.0.0
- micromark-extension-mdxjs: 3.0.0
- remark-mdx: 3.1.1
- remark-parse: 11.0.0
- remark-stringify: 11.0.0
- synckit: 0.11.12
- unified: 11.0.5
- vfile: 6.0.3
- transitivePeerDependencies:
- - bluebird
- - remark-lint-file-extension
- - supports-color
-
- eslint-plugin-n@17.24.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3):
- dependencies:
- '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1))
- enhanced-resolve: 5.20.1
- eslint: 9.39.4(jiti@2.6.1)
- eslint-plugin-es-x: 7.8.0(eslint@9.39.4(jiti@2.6.1))
- get-tsconfig: 4.14.0
- globals: 15.15.0
- globrex: 0.1.2
- ignore: 5.3.2
- semver: 7.7.4
- ts-declaration-location: 1.0.7(typescript@5.9.3)
- transitivePeerDependencies:
- - typescript
-
- eslint-plugin-promise@7.2.1(eslint@9.39.4(jiti@2.6.1)):
- dependencies:
- '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1))
- eslint: 9.39.4(jiti@2.6.1)
-
- eslint-plugin-react-hooks@7.1.0(eslint@9.39.4(jiti@2.6.1)):
- dependencies:
- '@babel/core': 7.29.0
- '@babel/parser': 7.29.2
- eslint: 9.39.4(jiti@2.6.1)
- hermes-parser: 0.25.1
- zod: 4.3.6
- zod-validation-error: 4.0.2(zod@4.3.6)
- transitivePeerDependencies:
- - supports-color
-
- eslint-plugin-react-refresh@0.4.26(eslint@9.39.4(jiti@2.6.1)):
- dependencies:
- eslint: 9.39.4(jiti@2.6.1)
-
- eslint-plugin-react@7.37.5(eslint@9.39.4(jiti@2.6.1)):
- dependencies:
- array-includes: 3.1.9
- array.prototype.findlast: 1.2.5
- array.prototype.flatmap: 1.3.3
- array.prototype.tosorted: 1.1.4
- doctrine: 2.1.0
- es-iterator-helpers: 1.3.2
- eslint: 9.39.4(jiti@2.6.1)
- estraverse: 5.3.0
- hasown: 2.0.2
- jsx-ast-utils: 3.3.5
- minimatch: 3.1.5
- object.entries: 1.1.9
- object.fromentries: 2.0.8
- object.values: 1.2.1
- prop-types: 15.8.1
- resolve: 2.0.0-next.6
- semver: 6.3.1
- string.prototype.matchall: 4.0.12
- string.prototype.repeat: 1.0.0
-
- eslint-plugin-rxjs-angular@2.0.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3):
- dependencies:
- '@typescript-eslint/experimental-utils': 5.62.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- common-tags: 1.8.2
- eslint: 9.39.4(jiti@2.6.1)
- eslint-etc: 5.2.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- requireindex: 1.2.0
- tslib: 2.8.1
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
- eslint-plugin-rxjs@5.0.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3):
- dependencies:
- '@typescript-eslint/experimental-utils': 5.62.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- common-tags: 1.8.2
- decamelize: 5.0.1
- eslint: 9.39.4(jiti@2.6.1)
- eslint-etc: 5.2.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- requireindex: 1.2.0
- rxjs-report-usage: 1.0.6
- tslib: 2.8.1
- tsutils: 3.21.0(typescript@5.9.3)
- tsutils-etc: 1.4.2(tsutils@3.21.0(typescript@5.9.3))(typescript@5.9.3)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
- eslint-plugin-sonarjs@3.0.7(eslint@9.39.4(jiti@2.6.1)):
- dependencies:
- '@eslint-community/regexpp': 4.12.2
- builtin-modules: 3.3.0
- bytes: 3.1.2
- eslint: 9.39.4(jiti@2.6.1)
- functional-red-black-tree: 1.0.1
- jsx-ast-utils-x: 0.1.0
- lodash.merge: 4.6.2
- minimatch: 10.1.2
- scslre: 0.3.0
- semver: 7.7.4
- typescript: 5.9.3
-
- eslint-plugin-svelte3@4.0.0(eslint@9.39.4(jiti@2.6.1))(svelte@3.59.2):
- dependencies:
- eslint: 9.39.4(jiti@2.6.1)
- svelte: 3.59.2
-
- eslint-plugin-tsdoc@0.4.0:
- dependencies:
- '@microsoft/tsdoc': 0.15.1
- '@microsoft/tsdoc-config': 0.17.1
-
- eslint-plugin-typescript-sort-keys@3.3.0(@typescript-eslint/parser@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3):
- dependencies:
- '@typescript-eslint/experimental-utils': 5.62.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/parser': 8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- eslint: 9.39.4(jiti@2.6.1)
- json-schema: 0.4.0
- natural-compare-lite: 1.4.0
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
- eslint-plugin-unicorn@61.0.2(eslint@9.39.4(jiti@2.6.1)):
- dependencies:
- '@babel/helper-validator-identifier': 7.28.5
- '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1))
- '@eslint/plugin-kit': 0.3.5
- change-case: 5.4.4
- ci-info: 4.4.0
- clean-regexp: 1.0.0
- core-js-compat: 3.49.0
- eslint: 9.39.4(jiti@2.6.1)
- esquery: 1.7.0
- find-up-simple: 1.0.1
- globals: 16.5.0
- indent-string: 5.0.0
- is-builtin-module: 5.0.0
- jsesc: 3.1.0
- pluralize: 8.0.0
- regexp-tree: 0.1.27
- regjsparser: 0.12.0
- semver: 7.7.4
- strip-indent: 4.1.1
-
- eslint-plugin-vue@10.8.0(@stylistic/eslint-plugin@5.10.0(eslint@9.39.4(jiti@2.6.1)))(@typescript-eslint/parser@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(vue-eslint-parser@10.4.0(eslint@9.39.4(jiti@2.6.1))):
- dependencies:
- '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1))
- eslint: 9.39.4(jiti@2.6.1)
- natural-compare: 1.4.0
- nth-check: 2.1.1
- postcss-selector-parser: 7.1.1
- semver: 7.7.4
- vue-eslint-parser: 10.4.0(eslint@9.39.4(jiti@2.6.1))
- xml-name-validator: 4.0.0
- optionalDependencies:
- '@stylistic/eslint-plugin': 5.10.0(eslint@9.39.4(jiti@2.6.1))
- '@typescript-eslint/parser': 8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
-
- eslint-rule-docs@1.1.235: {}
-
- eslint-scope@5.1.1:
- dependencies:
- esrecurse: 4.3.0
- estraverse: 4.3.0
-
- eslint-scope@8.4.0:
- dependencies:
- esrecurse: 4.3.0
- estraverse: 5.3.0
-
- eslint-scope@9.1.2:
- dependencies:
- '@types/esrecurse': 4.3.1
- '@types/estree': 1.0.8
- esrecurse: 4.3.0
- estraverse: 5.3.0
-
- eslint-visitor-keys@3.4.3: {}
-
- eslint-visitor-keys@4.2.1: {}
-
- eslint-visitor-keys@5.0.1: {}
-
- eslint@9.39.4(jiti@2.6.1):
- dependencies:
- '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1))
- '@eslint-community/regexpp': 4.12.2
- '@eslint/config-array': 0.21.2
- '@eslint/config-helpers': 0.4.2
- '@eslint/core': 0.17.0
- '@eslint/eslintrc': 3.3.5
- '@eslint/js': 9.39.4
- '@eslint/plugin-kit': 0.4.1
- '@humanfs/node': 0.16.7
- '@humanwhocodes/module-importer': 1.0.1
- '@humanwhocodes/retry': 0.4.3
- '@types/estree': 1.0.8
- ajv: 6.14.0
- chalk: 4.1.2
- cross-spawn: 7.0.6
- debug: 4.4.3
- escape-string-regexp: 4.0.0
- eslint-scope: 8.4.0
- eslint-visitor-keys: 4.2.1
- espree: 10.4.0
- esquery: 1.7.0
- esutils: 2.0.3
- fast-deep-equal: 3.1.3
- file-entry-cache: 8.0.0
- find-up: 5.0.0
- glob-parent: 6.0.2
- ignore: 5.3.2
- imurmurhash: 0.1.4
- is-glob: 4.0.3
- json-stable-stringify-without-jsonify: 1.0.1
- lodash.merge: 4.6.2
- minimatch: 3.1.5
- natural-compare: 1.4.0
- optionator: 0.9.4
- optionalDependencies:
- jiti: 2.6.1
- transitivePeerDependencies:
- - supports-color
-
- espree@10.4.0:
- dependencies:
- acorn: 8.16.0
- acorn-jsx: 5.3.2(acorn@8.16.0)
- eslint-visitor-keys: 4.2.1
-
- espree@11.2.0:
- dependencies:
- acorn: 8.16.0
- acorn-jsx: 5.3.2(acorn@8.16.0)
- eslint-visitor-keys: 5.0.1
-
- esquery@1.7.0:
- dependencies:
- estraverse: 5.3.0
-
- esrecurse@4.3.0:
- dependencies:
- estraverse: 5.3.0
-
- estraverse@4.3.0: {}
-
- estraverse@5.3.0: {}
-
- estree-util-is-identifier-name@3.0.0: {}
-
- estree-util-visit@2.0.0:
- dependencies:
- '@types/estree-jsx': 1.0.5
- '@types/unist': 3.0.3
-
- esutils@2.0.3: {}
-
- etag@1.8.1: {}
-
- exit-hook@2.2.1: {}
-
- express@4.22.1:
- dependencies:
- accepts: 1.3.8
- array-flatten: 1.1.1
- body-parser: 1.20.5
- content-disposition: 0.5.4
- content-type: 1.0.5
- cookie: 0.7.2
- cookie-signature: 1.0.7
- debug: 2.6.9
- depd: 2.0.0
- encodeurl: 2.0.0
- escape-html: 1.0.3
- etag: 1.8.1
- finalhandler: 1.3.2
- fresh: 0.5.2
- http-errors: 2.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.13
- proxy-addr: 2.0.7
- qs: 6.14.2
- range-parser: 1.2.1
- safe-buffer: 5.2.1
- send: 0.19.2
- serve-static: 1.16.3
- setprototypeof: 1.2.0
- statuses: 2.0.2
- type-is: 1.6.18
- utils-merge: 1.0.1
- vary: 1.1.2
- transitivePeerDependencies:
- - supports-color
-
- exsolve@1.0.8: {}
-
- extend@3.0.2: {}
-
- fast-check@3.23.2:
- dependencies:
- pure-rand: 6.1.0
-
- fast-deep-equal@3.1.3: {}
-
- fast-glob@3.3.1:
- dependencies:
- '@nodelib/fs.stat': 2.0.5
- '@nodelib/fs.walk': 1.2.8
- glob-parent: 5.1.2
- merge2: 1.4.1
- micromatch: 4.0.8
-
- fast-glob@3.3.3:
- dependencies:
- '@nodelib/fs.stat': 2.0.5
- '@nodelib/fs.walk': 1.2.8
- glob-parent: 5.1.2
- merge2: 1.4.1
- micromatch: 4.0.8
-
- fast-json-stable-stringify@2.1.0: {}
-
- fast-levenshtein@2.0.6: {}
-
- fastq@1.20.1:
- dependencies:
- reusify: 1.1.0
-
- fdir@6.5.0(picomatch@4.0.4):
- optionalDependencies:
- picomatch: 4.0.4
-
- file-entry-cache@8.0.0:
- dependencies:
- flat-cache: 4.0.1
-
- fill-range@7.1.1:
- dependencies:
- to-regex-range: 5.0.1
-
- finalhandler@1.3.2:
- dependencies:
- debug: 2.6.9
- encodeurl: 2.0.0
- escape-html: 1.0.3
- on-finished: 2.4.1
- parseurl: 1.3.3
- statuses: 2.0.2
- unpipe: 1.0.0
- transitivePeerDependencies:
- - supports-color
-
- find-up-simple@1.0.1: {}
-
- find-up@5.0.0:
- dependencies:
- locate-path: 6.0.0
- path-exists: 4.0.0
-
- flat-cache@4.0.1:
- dependencies:
- flatted: 3.4.2
- keyv: 4.5.4
-
- flatted@3.4.2: {}
-
- for-each@0.3.5:
- dependencies:
- is-callable: 1.2.7
-
- foreground-child@3.3.1:
- dependencies:
- cross-spawn: 7.0.6
- signal-exit: 4.1.0
-
- forwarded@0.2.0: {}
-
- fresh@0.5.2: {}
-
- fs.realpath@1.0.0: {}
-
- fsevents@2.3.3:
- optional: true
-
- function-bind@1.1.2: {}
-
- function.prototype.name@1.1.8:
- dependencies:
- call-bind: 1.0.9
- call-bound: 1.0.4
- define-properties: 1.2.1
- functions-have-names: 1.2.3
- hasown: 2.0.2
- is-callable: 1.2.7
-
- functional-red-black-tree@1.0.1: {}
-
- functions-have-names@1.2.3: {}
-
- generate-function@2.3.1:
- dependencies:
- is-property: 1.0.2
-
- generator-function@2.0.1: {}
-
- gensync@1.0.0-beta.2: {}
-
- get-caller-file@2.0.5: {}
-
- get-east-asian-width@1.5.0: {}
-
- get-intrinsic@1.3.0:
- dependencies:
- call-bind-apply-helpers: 1.0.2
- es-define-property: 1.0.1
- es-errors: 1.3.0
- es-object-atoms: 1.1.1
- function-bind: 1.1.2
- get-proto: 1.0.1
- gopd: 1.2.0
- has-symbols: 1.1.0
- hasown: 2.0.2
- math-intrinsics: 1.1.0
-
- get-port-please@3.2.0: {}
-
- get-port@5.1.1: {}
-
- get-proto@1.0.1:
- dependencies:
- dunder-proto: 1.0.1
- es-object-atoms: 1.1.1
-
- get-symbol-description@1.1.0:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- get-intrinsic: 1.3.0
-
- get-tsconfig@4.14.0:
- dependencies:
- resolve-pkg-maps: 1.0.0
-
- giget@2.0.0:
- dependencies:
- citty: 0.1.6
- consola: 3.4.2
- defu: 6.1.7
- node-fetch-native: 1.6.7
- nypm: 0.6.5
- pathe: 2.0.3
-
- glob-parent@5.1.2:
- dependencies:
- is-glob: 4.0.3
-
- glob-parent@6.0.2:
- dependencies:
- is-glob: 4.0.3
-
- glob@10.5.0:
- dependencies:
- foreground-child: 3.3.1
- jackspeak: 3.4.3
- minimatch: 9.0.9
- minipass: 7.1.3
- package-json-from-dist: 1.0.1
- path-scurry: 1.11.1
-
- glob@13.0.6:
- dependencies:
- minimatch: 10.2.5
- minipass: 7.1.3
- path-scurry: 2.0.2
-
- glob@7.2.3:
- dependencies:
- fs.realpath: 1.0.0
- inflight: 1.0.6
- inherits: 2.0.4
- minimatch: 3.1.5
- once: 1.4.0
- path-is-absolute: 1.0.1
-
- globals@14.0.0: {}
-
- globals@15.15.0: {}
-
- globals@16.5.0: {}
-
- globalthis@1.0.4:
- dependencies:
- define-properties: 1.2.1
- gopd: 1.2.0
-
- globby@11.1.0:
- dependencies:
- array-union: 2.1.0
- dir-glob: 3.0.1
- fast-glob: 3.3.3
- ignore: 5.3.2
- merge2: 1.4.1
- slash: 3.0.0
-
- globrex@0.1.2: {}
-
- gopd@1.2.0: {}
-
- graceful-fs@4.2.11: {}
-
- grammex@3.1.12: {}
-
- graphmatch@1.1.1: {}
-
- has-bigints@1.1.0: {}
-
- has-flag@4.0.0: {}
-
- has-flag@5.0.1: {}
-
- has-property-descriptors@1.0.2:
- dependencies:
- es-define-property: 1.0.1
-
- has-proto@1.2.0:
- dependencies:
- dunder-proto: 1.0.1
-
- has-symbols@1.1.0: {}
-
- has-tostringtag@1.0.2:
- dependencies:
- has-symbols: 1.1.0
-
- hasown@2.0.2:
- dependencies:
- function-bind: 1.1.2
-
- hermes-estree@0.25.1: {}
-
- hermes-parser@0.25.1:
- dependencies:
- hermes-estree: 0.25.1
-
- hono@4.12.14: {}
-
- hosted-git-info@7.0.2:
- dependencies:
- lru-cache: 10.4.3
-
- html-entities@2.6.0: {}
-
- http-errors@2.0.1:
- dependencies:
- depd: 2.0.0
- inherits: 2.0.4
- setprototypeof: 1.2.0
- statuses: 2.0.2
- toidentifier: 1.0.1
-
- http-status-codes@2.3.0: {}
-
- iconv-lite@0.4.24:
- dependencies:
- safer-buffer: 2.1.2
-
- iconv-lite@0.7.2:
- dependencies:
- safer-buffer: 2.1.2
-
- ignore@5.3.2: {}
-
- ignore@6.0.2: {}
-
- ignore@7.0.5: {}
-
- import-fresh@3.3.1:
- dependencies:
- parent-module: 1.0.1
- resolve-from: 4.0.0
-
- import-meta-resolve@4.2.0: {}
-
- imurmurhash@0.1.4: {}
-
- indent-string@5.0.0: {}
-
- inflight@1.0.6:
- dependencies:
- once: 1.4.0
- wrappy: 1.0.2
-
- inherits@2.0.4: {}
-
- ini@4.1.3: {}
-
- internal-slot@1.1.0:
- dependencies:
- es-errors: 1.3.0
- hasown: 2.0.2
- side-channel: 1.1.0
-
- ipaddr.js@1.9.1: {}
-
- irregular-plurals@3.5.0: {}
-
- is-alphabetical@2.0.1: {}
-
- is-alphanumerical@2.0.1:
- dependencies:
- is-alphabetical: 2.0.1
- is-decimal: 2.0.1
-
- is-array-buffer@3.0.5:
- dependencies:
- call-bind: 1.0.9
- call-bound: 1.0.4
- get-intrinsic: 1.3.0
-
- is-arrayish@0.2.1: {}
-
- is-async-function@2.1.1:
- dependencies:
- async-function: 1.0.0
- call-bound: 1.0.4
- get-proto: 1.0.1
- has-tostringtag: 1.0.2
- safe-regex-test: 1.1.0
-
- is-bigint@1.1.0:
- dependencies:
- has-bigints: 1.1.0
-
- is-boolean-object@1.2.2:
- dependencies:
- call-bound: 1.0.4
- has-tostringtag: 1.0.2
-
- is-builtin-module@5.0.0:
- dependencies:
- builtin-modules: 5.1.0
-
- is-bun-module@2.0.0:
- dependencies:
- semver: 7.7.4
-
- is-callable@1.2.7: {}
-
- is-core-module@2.16.1:
- dependencies:
- hasown: 2.0.2
-
- is-data-view@1.0.2:
- dependencies:
- call-bound: 1.0.4
- get-intrinsic: 1.3.0
- is-typed-array: 1.1.15
-
- is-date-object@1.1.0:
- dependencies:
- call-bound: 1.0.4
- has-tostringtag: 1.0.2
-
- is-decimal@2.0.1: {}
-
- is-empty@1.2.0: {}
-
- is-extglob@2.1.1: {}
-
- is-finalizationregistry@1.1.1:
- dependencies:
- call-bound: 1.0.4
-
- is-fullwidth-code-point@3.0.0: {}
-
- is-generator-function@1.1.2:
- dependencies:
- call-bound: 1.0.4
- generator-function: 2.0.1
- get-proto: 1.0.1
- has-tostringtag: 1.0.2
- safe-regex-test: 1.1.0
-
- is-glob@4.0.3:
- dependencies:
- is-extglob: 2.1.1
-
- is-hexadecimal@2.0.1: {}
-
- is-map@2.0.3: {}
-
- is-negative-zero@2.0.3: {}
-
- is-number-object@1.1.1:
+ '@discordjs/rest@2.6.1':
dependencies:
- call-bound: 1.0.4
- has-tostringtag: 1.0.2
-
- is-number@7.0.0: {}
-
- is-plain-obj@4.1.0: {}
-
- is-property@1.0.2: {}
+ '@discordjs/collection': 2.1.1
+ '@discordjs/util': 1.2.0
+ '@sapphire/async-queue': 1.5.5
+ '@sapphire/snowflake': 3.5.5
+ '@vladfrangu/async_event_emitter': 2.4.7
+ discord-api-types: 0.38.47
+ magic-bytes.js: 1.13.0
+ tslib: 2.8.1
+ undici: 6.24.1
- is-regex@1.2.1:
+ '@discordjs/util@1.2.0':
dependencies:
- call-bound: 1.0.4
- gopd: 1.2.0
- has-tostringtag: 1.0.2
- hasown: 2.0.2
-
- is-set@2.0.3: {}
+ discord-api-types: 0.38.47
- is-shared-array-buffer@1.0.4:
+ '@discordjs/ws@1.2.3':
dependencies:
- call-bound: 1.0.4
-
- is-stream@2.0.1: {}
+ '@discordjs/collection': 2.1.1
+ '@discordjs/rest': 2.6.1
+ '@discordjs/util': 1.2.0
+ '@sapphire/async-queue': 1.5.5
+ '@types/ws': 8.18.1
+ '@vladfrangu/async_event_emitter': 2.4.7
+ discord-api-types: 0.38.47
+ tslib: 2.8.1
+ ws: 8.20.0
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
- is-string@1.1.1:
+ '@discordjs/ws@2.0.4':
dependencies:
- call-bound: 1.0.4
- has-tostringtag: 1.0.2
+ '@discordjs/collection': 2.1.1
+ '@discordjs/rest': 2.6.1
+ '@discordjs/util': 1.2.0
+ '@sapphire/async-queue': 1.5.5
+ '@types/ws': 8.18.1
+ '@vladfrangu/async_event_emitter': 2.4.7
+ discord-api-types: 0.38.47
+ tslib: 2.8.1
+ ws: 8.20.1
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
- is-symbol@1.1.1:
+ '@electric-sql/pglite-socket@0.1.1(@electric-sql/pglite@0.4.1)':
dependencies:
- call-bound: 1.0.4
- has-symbols: 1.1.0
- safe-regex-test: 1.1.0
+ '@electric-sql/pglite': 0.4.1
- is-typed-array@1.1.15:
+ '@electric-sql/pglite-tools@0.3.1(@electric-sql/pglite@0.4.1)':
dependencies:
- which-typed-array: 1.1.20
-
- is-unicode-supported@2.1.0: {}
+ '@electric-sql/pglite': 0.4.1
- is-weakmap@2.0.2: {}
+ '@electric-sql/pglite@0.4.1': {}
- is-weakref@1.1.1:
+ '@emnapi/runtime@1.10.0':
dependencies:
- call-bound: 1.0.4
+ tslib: 2.8.1
+ optional: true
- is-weakset@2.0.4:
+ '@hono/node-server@1.19.11(hono@4.12.19)':
dependencies:
- call-bound: 1.0.4
- get-intrinsic: 1.3.0
-
- isarray@2.0.5: {}
+ hono: 4.12.19
- isbot@5.1.40: {}
+ '@img/colour@1.1.0': {}
- isexe@2.0.0: {}
-
- isexe@3.1.5: {}
-
- iterator.prototype@1.1.5:
- dependencies:
- define-data-property: 1.1.4
- es-object-atoms: 1.1.1
- get-intrinsic: 1.3.0
- get-proto: 1.0.1
- has-symbols: 1.1.0
- set-function-name: 2.0.2
-
- jackspeak@3.4.3:
- dependencies:
- '@isaacs/cliui': 8.0.2
+ '@img/sharp-darwin-arm64@0.34.5':
optionalDependencies:
- '@pkgjs/parseargs': 0.11.0
-
- jiti@2.6.1: {}
-
- jju@1.4.0: {}
-
- js-tokens@4.0.0: {}
-
- js-yaml@4.1.1:
- dependencies:
- argparse: 2.0.1
-
- jsdoc-type-pratt-parser@7.0.0: {}
-
- jsesc@3.0.2: {}
-
- jsesc@3.1.0: {}
-
- json-buffer@3.0.1: {}
-
- json-parse-even-better-errors@3.0.2: {}
+ '@img/sharp-libvips-darwin-arm64': 1.2.4
+ optional: true
- json-schema-traverse@0.4.1: {}
+ '@img/sharp-darwin-x64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-darwin-x64': 1.2.4
+ optional: true
- json-schema-traverse@1.0.0: {}
+ '@img/sharp-libvips-darwin-arm64@1.2.4':
+ optional: true
- json-schema@0.4.0: {}
+ '@img/sharp-libvips-darwin-x64@1.2.4':
+ optional: true
- json-stable-stringify-without-jsonify@1.0.1: {}
+ '@img/sharp-libvips-linux-arm64@1.2.4':
+ optional: true
- json5@2.2.3: {}
+ '@img/sharp-libvips-linux-arm@1.2.4':
+ optional: true
- jsx-ast-utils-x@0.1.0: {}
+ '@img/sharp-libvips-linux-ppc64@1.2.4':
+ optional: true
- jsx-ast-utils@3.3.5:
- dependencies:
- array-includes: 3.1.9
- array.prototype.flat: 1.3.3
- object.assign: 4.1.7
- object.values: 1.2.1
+ '@img/sharp-libvips-linux-riscv64@1.2.4':
+ optional: true
- keyv@4.5.4:
- dependencies:
- json-buffer: 3.0.1
+ '@img/sharp-libvips-linux-s390x@1.2.4':
+ optional: true
- kleur@3.0.3: {}
+ '@img/sharp-libvips-linux-x64@1.2.4':
+ optional: true
- language-subtag-registry@0.3.23: {}
+ '@img/sharp-libvips-linuxmusl-arm64@1.2.4':
+ optional: true
- language-tags@1.0.9:
- dependencies:
- language-subtag-registry: 0.3.23
+ '@img/sharp-libvips-linuxmusl-x64@1.2.4':
+ optional: true
- levn@0.4.1:
- dependencies:
- prelude-ls: 1.2.1
- type-check: 0.4.0
+ '@img/sharp-linux-arm64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-arm64': 1.2.4
+ optional: true
- lightningcss-android-arm64@1.32.0:
+ '@img/sharp-linux-arm@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-arm': 1.2.4
optional: true
- lightningcss-darwin-arm64@1.32.0:
+ '@img/sharp-linux-ppc64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-ppc64': 1.2.4
optional: true
- lightningcss-darwin-x64@1.32.0:
+ '@img/sharp-linux-riscv64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-riscv64': 1.2.4
optional: true
- lightningcss-freebsd-x64@1.32.0:
+ '@img/sharp-linux-s390x@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-s390x': 1.2.4
optional: true
- lightningcss-linux-arm-gnueabihf@1.32.0:
+ '@img/sharp-linux-x64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-x64': 1.2.4
optional: true
- lightningcss-linux-arm64-gnu@1.32.0:
+ '@img/sharp-linuxmusl-arm64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linuxmusl-arm64': 1.2.4
optional: true
- lightningcss-linux-arm64-musl@1.32.0:
+ '@img/sharp-linuxmusl-x64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linuxmusl-x64': 1.2.4
optional: true
- lightningcss-linux-x64-gnu@1.32.0:
+ '@img/sharp-wasm32@0.34.5':
+ dependencies:
+ '@emnapi/runtime': 1.10.0
optional: true
- lightningcss-linux-x64-musl@1.32.0:
+ '@img/sharp-win32-arm64@0.34.5':
optional: true
- lightningcss-win32-arm64-msvc@1.32.0:
+ '@img/sharp-win32-ia32@0.34.5':
optional: true
- lightningcss-win32-x64-msvc@1.32.0:
+ '@img/sharp-win32-x64@0.34.5':
optional: true
- lightningcss@1.32.0:
- dependencies:
- detect-libc: 2.1.2
- optionalDependencies:
- lightningcss-android-arm64: 1.32.0
- lightningcss-darwin-arm64: 1.32.0
- lightningcss-darwin-x64: 1.32.0
- lightningcss-freebsd-x64: 1.32.0
- lightningcss-linux-arm-gnueabihf: 1.32.0
- lightningcss-linux-arm64-gnu: 1.32.0
- lightningcss-linux-arm64-musl: 1.32.0
- lightningcss-linux-x64-gnu: 1.32.0
- lightningcss-linux-x64-musl: 1.32.0
- lightningcss-win32-arm64-msvc: 1.32.0
- lightningcss-win32-x64-msvc: 1.32.0
-
- lines-and-columns@2.0.4: {}
-
- load-plugin@6.0.3:
- dependencies:
- '@npmcli/config': 8.3.4
- import-meta-resolve: 4.2.0
- transitivePeerDependencies:
- - bluebird
+ '@kurkle/color@0.3.4': {}
- locate-path@6.0.0:
+ '@prisma/adapter-pg@7.8.0':
dependencies:
- p-locate: 5.0.0
-
- lodash.merge@4.6.2: {}
+ '@prisma/driver-adapter-utils': 7.8.0
+ '@types/pg': 8.20.0
+ pg: 8.20.0
+ postgres-array: 3.0.4
+ transitivePeerDependencies:
+ - pg-native
- lodash.snakecase@4.1.1: {}
+ '@prisma/client-runtime-utils@7.8.0': {}
- lodash@4.18.1: {}
+ '@prisma/client@7.8.0(prisma@7.8.0(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(typescript@6.0.3))(typescript@6.0.3)':
+ dependencies:
+ '@prisma/client-runtime-utils': 7.8.0
+ optionalDependencies:
+ prisma: 7.8.0(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(typescript@6.0.3)
+ typescript: 6.0.3
- log-symbols@7.0.1:
+ '@prisma/config@7.8.0':
dependencies:
- is-unicode-supported: 2.1.0
- yoctocolors: 2.1.2
+ c12: 3.3.4
+ deepmerge-ts: 7.1.5
+ effect: 3.20.0
+ empathic: 2.0.0
+ transitivePeerDependencies:
+ - magicast
- long@5.3.2: {}
+ '@prisma/debug@7.2.0': {}
- longest-streak@3.1.0: {}
+ '@prisma/debug@7.8.0': {}
- loose-envify@1.4.0:
+ '@prisma/dev@0.24.3(typescript@6.0.3)':
dependencies:
- js-tokens: 4.0.0
+ '@electric-sql/pglite': 0.4.1
+ '@electric-sql/pglite-socket': 0.1.1(@electric-sql/pglite@0.4.1)
+ '@electric-sql/pglite-tools': 0.3.1(@electric-sql/pglite@0.4.1)
+ '@hono/node-server': 1.19.11(hono@4.12.19)
+ '@prisma/get-platform': 7.2.0
+ '@prisma/query-plan-executor': 7.2.0
+ '@prisma/streams-local': 0.1.2
+ foreground-child: 3.3.1
+ get-port-please: 3.2.0
+ hono: 4.12.19
+ http-status-codes: 2.3.0
+ pathe: 2.0.3
+ proper-lockfile: 4.1.2
+ remeda: 2.33.4
+ std-env: 3.10.0
+ valibot: 1.2.0(typescript@6.0.3)
+ zeptomatch: 2.1.0
+ transitivePeerDependencies:
+ - typescript
- lru-cache@10.4.3: {}
+ '@prisma/driver-adapter-utils@7.8.0':
+ dependencies:
+ '@prisma/debug': 7.8.0
- lru-cache@11.3.5: {}
+ '@prisma/engines-version@7.8.0-6.3c6e192761c0362d496ed980de936e2f3cebcd3a': {}
- lru-cache@5.1.1:
+ '@prisma/engines@7.8.0':
dependencies:
- yallist: 3.1.1
+ '@prisma/debug': 7.8.0
+ '@prisma/engines-version': 7.8.0-6.3c6e192761c0362d496ed980de936e2f3cebcd3a
+ '@prisma/fetch-engine': 7.8.0
+ '@prisma/get-platform': 7.8.0
- lru.min@1.1.4: {}
+ '@prisma/fetch-engine@7.8.0':
+ dependencies:
+ '@prisma/debug': 7.8.0
+ '@prisma/engines-version': 7.8.0-6.3c6e192761c0362d496ed980de936e2f3cebcd3a
+ '@prisma/get-platform': 7.8.0
- magic-bytes.js@1.13.0: {}
+ '@prisma/get-platform@7.2.0':
+ dependencies:
+ '@prisma/debug': 7.2.0
- magic-string@0.30.21:
+ '@prisma/get-platform@7.8.0':
dependencies:
- '@jridgewell/sourcemap-codec': 1.5.5
+ '@prisma/debug': 7.8.0
- math-intrinsics@1.1.0: {}
+ '@prisma/query-plan-executor@7.2.0': {}
- mdast-util-from-markdown@2.0.3:
+ '@prisma/streams-local@0.1.2':
dependencies:
- '@types/mdast': 4.0.4
- '@types/unist': 3.0.3
- decode-named-character-reference: 1.3.0
- devlop: 1.1.0
- mdast-util-to-string: 4.0.0
- micromark: 4.0.2
- micromark-util-decode-numeric-character-reference: 2.0.2
- micromark-util-decode-string: 2.0.1
- micromark-util-normalize-identifier: 2.0.1
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
- unist-util-stringify-position: 4.0.0
- transitivePeerDependencies:
- - supports-color
+ ajv: 8.20.0
+ better-result: 2.9.2
+ env-paths: 3.0.0
+ proper-lockfile: 4.1.2
- mdast-util-mdx-expression@2.0.1:
+ '@prisma/studio-core@0.27.3(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
dependencies:
- '@types/estree-jsx': 1.0.5
- '@types/hast': 3.0.4
- '@types/mdast': 4.0.4
- devlop: 1.1.0
- mdast-util-from-markdown: 2.0.3
- mdast-util-to-markdown: 2.1.2
+ '@radix-ui/react-toggle': 1.1.10(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
+ '@types/react': 19.2.14
+ chart.js: 4.5.1
+ react: 19.2.5
+ react-dom: 19.2.5(react@19.2.5)
transitivePeerDependencies:
- - supports-color
+ - '@types/react-dom'
- mdast-util-mdx-jsx@3.2.0:
- dependencies:
- '@types/estree-jsx': 1.0.5
- '@types/hast': 3.0.4
- '@types/mdast': 4.0.4
- '@types/unist': 3.0.3
- ccount: 2.0.1
- devlop: 1.1.0
- mdast-util-from-markdown: 2.0.3
- mdast-util-to-markdown: 2.1.2
- parse-entities: 4.0.2
- stringify-entities: 4.0.4
- unist-util-stringify-position: 4.0.0
- vfile-message: 4.0.3
- transitivePeerDependencies:
- - supports-color
+ '@radix-ui/primitive@1.1.3': {}
- mdast-util-mdx@3.0.0:
+ '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.14)(react@19.2.5)':
dependencies:
- mdast-util-from-markdown: 2.0.3
- mdast-util-mdx-expression: 2.0.1
- mdast-util-mdx-jsx: 3.2.0
- mdast-util-mdxjs-esm: 2.0.1
- mdast-util-to-markdown: 2.1.2
- transitivePeerDependencies:
- - supports-color
+ react: 19.2.5
+ optionalDependencies:
+ '@types/react': 19.2.14
- mdast-util-mdxjs-esm@2.0.1:
+ '@radix-ui/react-primitive@2.1.3(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
dependencies:
- '@types/estree-jsx': 1.0.5
- '@types/hast': 3.0.4
- '@types/mdast': 4.0.4
- devlop: 1.1.0
- mdast-util-from-markdown: 2.0.3
- mdast-util-to-markdown: 2.1.2
- transitivePeerDependencies:
- - supports-color
+ '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.5)
+ react: 19.2.5
+ react-dom: 19.2.5(react@19.2.5)
+ optionalDependencies:
+ '@types/react': 19.2.14
- mdast-util-phrasing@4.1.0:
+ '@radix-ui/react-slot@1.2.3(@types/react@19.2.14)(react@19.2.5)':
dependencies:
- '@types/mdast': 4.0.4
- unist-util-is: 6.0.1
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5)
+ react: 19.2.5
+ optionalDependencies:
+ '@types/react': 19.2.14
- mdast-util-to-markdown@2.1.2:
+ '@radix-ui/react-toggle@1.1.10(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
dependencies:
- '@types/mdast': 4.0.4
- '@types/unist': 3.0.3
- longest-streak: 3.1.0
- mdast-util-phrasing: 4.1.0
- mdast-util-to-string: 4.0.0
- micromark-util-classify-character: 2.0.1
- micromark-util-decode-string: 2.0.1
- unist-util-visit: 5.1.0
- zwitch: 2.0.4
-
- mdast-util-to-string@4.0.0:
- dependencies:
- '@types/mdast': 4.0.4
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-primitive': 2.1.3(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.5)
+ react: 19.2.5
+ react-dom: 19.2.5(react@19.2.5)
+ optionalDependencies:
+ '@types/react': 19.2.14
- media-typer@0.3.0: {}
+ '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.2.14)(react@19.2.5)':
+ dependencies:
+ '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.14)(react@19.2.5)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.5)
+ react: 19.2.5
+ optionalDependencies:
+ '@types/react': 19.2.14
- merge-descriptors@1.0.3: {}
+ '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.2.14)(react@19.2.5)':
+ dependencies:
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.5)
+ react: 19.2.5
+ optionalDependencies:
+ '@types/react': 19.2.14
- merge2@1.4.1: {}
+ '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.14)(react@19.2.5)':
+ dependencies:
+ react: 19.2.5
+ optionalDependencies:
+ '@types/react': 19.2.14
- methods@1.1.2: {}
+ '@sapphire/async-queue@1.5.5': {}
- micromark-core-commonmark@2.0.3:
+ '@sapphire/discord-utilities@3.5.0':
dependencies:
- decode-named-character-reference: 1.3.0
- devlop: 1.1.0
- micromark-factory-destination: 2.0.1
- micromark-factory-label: 2.0.1
- micromark-factory-space: 2.0.1
- micromark-factory-title: 2.0.1
- micromark-factory-whitespace: 2.0.1
- micromark-util-character: 2.1.1
- micromark-util-chunked: 2.0.1
- micromark-util-classify-character: 2.0.1
- micromark-util-html-tag-name: 2.0.1
- micromark-util-normalize-identifier: 2.0.1
- micromark-util-resolve-all: 2.0.1
- micromark-util-subtokenize: 2.1.0
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
-
- micromark-extension-mdx-expression@3.0.1:
+ discord-api-types: 0.38.47
+
+ '@sapphire/discord-utilities@4.0.0':
dependencies:
- '@types/estree': 1.0.8
- devlop: 1.1.0
- micromark-factory-mdx-expression: 2.0.3
- micromark-factory-space: 2.0.1
- micromark-util-character: 2.1.1
- micromark-util-events-to-acorn: 2.0.3
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
-
- micromark-extension-mdx-jsx@3.0.2:
+ discord-api-types: 0.38.47
+
+ '@sapphire/discord.js-utilities@7.3.3':
dependencies:
- '@types/estree': 1.0.8
- devlop: 1.1.0
- estree-util-is-identifier-name: 3.0.0
- micromark-factory-mdx-expression: 2.0.3
- micromark-factory-space: 2.0.1
- micromark-util-character: 2.1.1
- micromark-util-events-to-acorn: 2.0.3
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
- vfile-message: 4.0.3
-
- micromark-extension-mdx-md@2.0.0:
+ '@sapphire/discord-utilities': 3.5.0
+ '@sapphire/duration': 1.2.0
+ '@sapphire/utilities': 3.18.2
+ tslib: 2.8.1
+
+ '@sapphire/duration@1.2.0': {}
+
+ '@sapphire/framework@5.5.0':
dependencies:
- micromark-util-types: 2.0.2
+ '@discordjs/builders': 1.14.1
+ '@sapphire/discord-utilities': 4.0.0
+ '@sapphire/discord.js-utilities': 7.3.3
+ '@sapphire/lexure': 1.1.12
+ '@sapphire/pieces': 4.4.1
+ '@sapphire/ratelimits': 2.4.11
+ '@sapphire/result': 2.8.0
+ '@sapphire/stopwatch': 1.5.4
+ '@sapphire/utilities': 3.18.2
- micromark-extension-mdxjs-esm@3.0.0:
+ '@sapphire/lexure@1.1.12':
dependencies:
- '@types/estree': 1.0.8
- devlop: 1.1.0
- micromark-core-commonmark: 2.0.3
- micromark-util-character: 2.1.1
- micromark-util-events-to-acorn: 2.0.3
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
- unist-util-position-from-estree: 2.0.0
- vfile-message: 4.0.3
-
- micromark-extension-mdxjs@3.0.0:
+ '@sapphire/result': 2.8.0
+
+ '@sapphire/pieces@4.4.1':
dependencies:
- acorn: 8.16.0
- acorn-jsx: 5.3.2(acorn@8.16.0)
- micromark-extension-mdx-expression: 3.0.1
- micromark-extension-mdx-jsx: 3.0.2
- micromark-extension-mdx-md: 2.0.0
- micromark-extension-mdxjs-esm: 3.0.0
- micromark-util-combine-extensions: 2.0.1
- micromark-util-types: 2.0.2
-
- micromark-factory-destination@2.0.1:
+ '@discordjs/collection': 2.1.1
+ '@sapphire/utilities': 3.18.2
+ tslib: 2.8.1
+
+ '@sapphire/ratelimits@2.4.11': {}
+
+ '@sapphire/result@2.8.0': {}
+
+ '@sapphire/shapeshift@4.0.0':
dependencies:
- micromark-util-character: 2.1.1
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
+ fast-deep-equal: 3.1.3
+ lodash: 4.18.1
+
+ '@sapphire/snowflake@3.5.3': {}
+
+ '@sapphire/snowflake@3.5.5': {}
- micromark-factory-label@2.0.1:
+ '@sapphire/stopwatch@1.5.4':
dependencies:
- devlop: 1.1.0
- micromark-util-character: 2.1.1
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
+ tslib: 2.8.1
- micromark-factory-mdx-expression@2.0.3:
+ '@sapphire/ts-config@5.0.3':
dependencies:
- '@types/estree': 1.0.8
- devlop: 1.1.0
- micromark-factory-space: 2.0.1
- micromark-util-character: 2.1.1
- micromark-util-events-to-acorn: 2.0.3
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
- unist-util-position-from-estree: 2.0.0
- vfile-message: 4.0.3
-
- micromark-factory-space@2.0.1:
+ tslib: 2.8.1
+ typescript: 5.4.5
+
+ '@sapphire/utilities@3.18.2': {}
+
+ '@standard-schema/spec@1.1.0': {}
+
+ '@turbo/darwin-64@2.9.14':
+ optional: true
+
+ '@turbo/darwin-arm64@2.9.14':
+ optional: true
+
+ '@turbo/linux-64@2.9.14':
+ optional: true
+
+ '@turbo/linux-arm64@2.9.14':
+ optional: true
+
+ '@turbo/windows-64@2.9.14':
+ optional: true
+
+ '@turbo/windows-arm64@2.9.14':
+ optional: true
+
+ '@types/ms@2.1.0': {}
+
+ '@types/node@25.8.0':
dependencies:
- micromark-util-character: 2.1.1
- micromark-util-types: 2.0.2
+ undici-types: 7.24.6
- micromark-factory-title@2.0.1:
+ '@types/pg@8.20.0':
dependencies:
- micromark-factory-space: 2.0.1
- micromark-util-character: 2.1.1
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
+ '@types/node': 25.8.0
+ pg-protocol: 1.13.0
+ pg-types: 2.2.0
- micromark-factory-whitespace@2.0.1:
+ '@types/react@19.2.14':
dependencies:
- micromark-factory-space: 2.0.1
- micromark-util-character: 2.1.1
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
+ csstype: 3.2.3
- micromark-util-character@2.1.1:
+ '@types/ws@8.18.1':
dependencies:
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
+ '@types/node': 25.8.0
+
+ '@vladfrangu/async_event_emitter@2.4.7': {}
- micromark-util-chunked@2.0.1:
+ ajv@8.20.0:
dependencies:
- micromark-util-symbol: 2.0.1
+ fast-deep-equal: 3.1.3
+ fast-uri: 3.1.2
+ json-schema-traverse: 1.0.0
+ require-from-string: 2.0.2
- micromark-util-classify-character@2.0.1:
- dependencies:
- micromark-util-character: 2.1.1
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
+ ansi-regex@5.0.1: {}
- micromark-util-combine-extensions@2.0.1:
+ ansi-styles@4.3.0:
dependencies:
- micromark-util-chunked: 2.0.1
- micromark-util-types: 2.0.2
+ color-convert: 2.0.1
- micromark-util-decode-numeric-character-reference@2.0.2:
- dependencies:
- micromark-util-symbol: 2.0.1
+ aws-ssl-profiles@1.1.2: {}
- micromark-util-decode-string@2.0.1:
- dependencies:
- decode-named-character-reference: 1.3.0
- micromark-util-character: 2.1.1
- micromark-util-decode-numeric-character-reference: 2.0.2
- micromark-util-symbol: 2.0.1
+ balanced-match@4.0.4: {}
- micromark-util-encode@2.0.1: {}
+ better-result@2.9.2: {}
- micromark-util-events-to-acorn@2.0.3:
+ brace-expansion@5.0.6:
dependencies:
- '@types/estree': 1.0.8
- '@types/unist': 3.0.3
- devlop: 1.1.0
- estree-util-visit: 2.0.0
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
- vfile-message: 4.0.3
-
- micromark-util-html-tag-name@2.0.1: {}
+ balanced-match: 4.0.4
- micromark-util-normalize-identifier@2.0.1:
+ c12@3.3.4:
dependencies:
- micromark-util-symbol: 2.0.1
+ chokidar: 5.0.0
+ confbox: 0.2.4
+ defu: 6.1.7
+ dotenv: 17.4.2
+ exsolve: 1.0.8
+ giget: 3.2.0
+ jiti: 2.7.0
+ ohash: 2.0.11
+ pathe: 2.0.3
+ perfect-debounce: 2.1.0
+ pkg-types: 2.3.1
+ rc9: 3.0.1
- micromark-util-resolve-all@2.0.1:
+ chalk@4.1.2:
dependencies:
- micromark-util-types: 2.0.2
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
- micromark-util-sanitize-uri@2.0.1:
+ chart.js@4.5.1:
dependencies:
- micromark-util-character: 2.1.1
- micromark-util-encode: 2.0.1
- micromark-util-symbol: 2.0.1
+ '@kurkle/color': 0.3.4
- micromark-util-subtokenize@2.1.0:
+ chokidar@5.0.0:
dependencies:
- devlop: 1.1.0
- micromark-util-chunked: 2.0.1
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
+ readdirp: 5.0.0
- micromark-util-symbol@2.0.1: {}
-
- micromark-util-types@2.0.2: {}
-
- micromark@4.0.2:
+ cliui@8.0.1:
dependencies:
- '@types/debug': 4.1.13
- debug: 4.4.3
- decode-named-character-reference: 1.3.0
- devlop: 1.1.0
- micromark-core-commonmark: 2.0.3
- micromark-factory-space: 2.0.1
- micromark-util-character: 2.1.1
- micromark-util-chunked: 2.0.1
- micromark-util-combine-extensions: 2.0.1
- micromark-util-decode-numeric-character-reference: 2.0.2
- micromark-util-encode: 2.0.1
- micromark-util-normalize-identifier: 2.0.1
- micromark-util-resolve-all: 2.0.1
- micromark-util-sanitize-uri: 2.0.1
- micromark-util-subtokenize: 2.1.0
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
- transitivePeerDependencies:
- - supports-color
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 7.0.0
- micromatch@4.0.8:
+ color-convert@2.0.1:
dependencies:
- braces: 3.0.3
- picomatch: 2.3.2
-
- mime-db@1.52.0: {}
+ color-name: 1.1.4
- mime-db@1.54.0: {}
+ color-name@1.1.4: {}
- mime-types@2.1.35:
+ concurrently@9.2.1:
dependencies:
- mime-db: 1.52.0
+ chalk: 4.1.2
+ rxjs: 7.8.2
+ shell-quote: 1.8.3
+ supports-color: 8.1.1
+ tree-kill: 1.2.2
+ yargs: 17.7.2
- mime@1.6.0: {}
+ confbox@0.2.4: {}
- minimatch@10.1.2:
+ cross-spawn@7.0.6:
dependencies:
- '@isaacs/brace-expansion': 5.0.1
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
- minimatch@10.2.5:
- dependencies:
- brace-expansion: 5.0.5
+ csstype@3.2.3: {}
- minimatch@3.1.5:
- dependencies:
- brace-expansion: 1.1.14
+ deepmerge-ts@7.1.5: {}
- minimatch@9.0.9:
- dependencies:
- brace-expansion: 2.1.0
+ defu@6.1.7: {}
- minipass@7.1.3: {}
+ denque@2.1.0: {}
- morgan@1.10.1:
- dependencies:
- basic-auth: 2.0.1
- debug: 2.6.9
- depd: 2.0.0
- on-finished: 2.3.0
- on-headers: 1.1.0
- transitivePeerDependencies:
- - supports-color
+ destr@2.0.5: {}
- ms@2.0.0: {}
+ detect-libc@2.1.2: {}
- ms@2.1.3: {}
+ discord-api-types@0.38.47: {}
- mysql2@3.15.3:
+ discord.js@14.26.4:
dependencies:
- aws-ssl-profiles: 1.1.2
- denque: 2.1.0
- generate-function: 2.3.1
- iconv-lite: 0.7.2
- long: 5.3.2
- lru.min: 1.1.4
- named-placeholders: 1.1.6
- seq-queue: 0.0.5
- sqlstring: 2.3.3
+ '@discordjs/builders': 1.14.1
+ '@discordjs/collection': 1.5.3
+ '@discordjs/formatters': 0.6.2
+ '@discordjs/rest': 2.6.1
+ '@discordjs/util': 1.2.0
+ '@discordjs/ws': 1.2.3
+ '@sapphire/snowflake': 3.5.3
+ discord-api-types: 0.38.47
+ fast-deep-equal: 3.1.3
+ lodash.snakecase: 4.1.1
+ magic-bytes.js: 1.13.0
+ tslib: 2.8.1
+ undici: 6.24.1
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
- named-placeholders@1.1.6:
- dependencies:
- lru.min: 1.1.4
+ dotenv@17.4.2: {}
- nanoid@3.3.11: {}
+ effect@3.20.0:
+ dependencies:
+ '@standard-schema/spec': 1.1.0
+ fast-check: 3.23.2
- napi-postinstall@0.3.4: {}
+ emoji-regex@8.0.0: {}
- natural-compare-lite@1.4.0: {}
+ empathic@2.0.0: {}
- natural-compare@1.4.0: {}
+ env-paths@3.0.0: {}
- negotiator@0.6.3: {}
+ escalade@3.2.0: {}
- negotiator@0.6.4: {}
+ exsolve@1.0.8: {}
- node-exports-info@1.6.0:
+ fast-check@3.23.2:
dependencies:
- array.prototype.flatmap: 1.3.3
- es-errors: 1.3.0
- object.entries: 1.1.9
- semver: 6.3.1
+ pure-rand: 6.1.0
- node-fetch-native@1.6.7: {}
+ fast-deep-equal@3.1.3: {}
- node-releases@2.0.37: {}
+ fast-uri@3.1.2: {}
- nopt@7.2.1:
+ foreground-child@3.3.1:
dependencies:
- abbrev: 2.0.0
+ cross-spawn: 7.0.6
+ signal-exit: 4.1.0
- normalize-package-data@6.0.2:
+ generate-function@2.3.1:
dependencies:
- hosted-git-info: 7.0.2
- semver: 7.7.4
- validate-npm-package-license: 3.0.4
+ is-property: 1.0.2
- npm-install-checks@6.3.0:
- dependencies:
- semver: 7.7.4
+ get-caller-file@2.0.5: {}
- npm-normalize-package-bin@3.0.1: {}
+ get-port-please@3.2.0: {}
- npm-package-arg@11.0.3:
- dependencies:
- hosted-git-info: 7.0.2
- proc-log: 4.2.0
- semver: 7.7.4
- validate-npm-package-name: 5.0.1
+ giget@3.2.0: {}
- npm-pick-manifest@9.1.0:
+ glob@13.0.6:
dependencies:
- npm-install-checks: 6.3.0
- npm-normalize-package-bin: 3.0.1
- npm-package-arg: 11.0.3
- semver: 7.7.4
+ minimatch: 10.2.5
+ minipass: 7.1.3
+ path-scurry: 2.0.2
- nth-check@2.1.1:
- dependencies:
- boolbase: 1.0.0
+ graceful-fs@4.2.11: {}
- nypm@0.6.5:
- dependencies:
- citty: 0.2.2
- pathe: 2.0.3
- tinyexec: 1.1.1
+ grammex@3.1.12: {}
- object-assign@4.1.1: {}
+ graphmatch@1.1.1: {}
- object-deep-merge@2.0.0: {}
+ has-flag@4.0.0: {}
- object-inspect@1.13.4: {}
+ hono@4.12.19: {}
- object-keys@1.1.1: {}
+ http-status-codes@2.3.0: {}
- object.assign@4.1.7:
- dependencies:
- call-bind: 1.0.9
- call-bound: 1.0.4
- define-properties: 1.2.1
- es-object-atoms: 1.1.1
- has-symbols: 1.1.0
- object-keys: 1.1.1
-
- object.entries@1.1.9:
+ iconv-lite@0.7.2:
dependencies:
- call-bind: 1.0.9
- call-bound: 1.0.4
- define-properties: 1.2.1
- es-object-atoms: 1.1.1
+ safer-buffer: 2.1.2
- object.fromentries@2.0.8:
- dependencies:
- call-bind: 1.0.9
- define-properties: 1.2.1
- es-abstract: 1.24.2
- es-object-atoms: 1.1.1
+ ipaddr.js@2.4.0: {}
- object.values@1.2.1:
- dependencies:
- call-bind: 1.0.9
- call-bound: 1.0.4
- define-properties: 1.2.1
- es-object-atoms: 1.1.1
+ is-fullwidth-code-point@3.0.0: {}
- ohash@2.0.11: {}
+ is-property@1.0.2: {}
- on-finished@2.3.0:
- dependencies:
- ee-first: 1.1.1
+ isexe@2.0.0: {}
- on-finished@2.4.1:
- dependencies:
- ee-first: 1.1.1
+ jiti@2.7.0: {}
- on-headers@1.1.0: {}
+ json-schema-traverse@1.0.0: {}
- once@1.4.0:
- dependencies:
- wrappy: 1.0.2
+ lodash.snakecase@4.1.1: {}
- optionator@0.9.4:
- dependencies:
- deep-is: 0.1.4
- fast-levenshtein: 2.0.6
- levn: 0.4.1
- prelude-ls: 1.2.1
- type-check: 0.4.0
- word-wrap: 1.2.5
-
- own-keys@1.0.1:
- dependencies:
- get-intrinsic: 1.3.0
- object-keys: 1.1.1
- safe-push-apply: 1.0.0
+ lodash@4.18.1: {}
- p-limit@3.1.0:
- dependencies:
- yocto-queue: 0.1.0
+ long@5.3.2: {}
- p-locate@5.0.0:
- dependencies:
- p-limit: 3.1.0
+ lru-cache@11.3.6: {}
- p-map@7.0.4: {}
+ lru.min@1.1.4: {}
- package-json-from-dist@1.0.1: {}
+ magic-bytes.js@1.13.0: {}
- parent-module@1.0.1:
+ minimatch@10.2.5:
dependencies:
- callsites: 3.1.0
+ brace-expansion: 5.0.6
- parse-entities@4.0.2:
- dependencies:
- '@types/unist': 2.0.11
- character-entities-legacy: 3.0.0
- character-reference-invalid: 2.0.1
- decode-named-character-reference: 1.3.0
- is-alphanumerical: 2.0.1
- is-decimal: 2.0.1
- is-hexadecimal: 2.0.1
-
- parse-imports-exports@0.2.4:
- dependencies:
- parse-statements: 1.0.11
+ minipass@7.1.3: {}
- parse-json@7.1.1:
- dependencies:
- '@babel/code-frame': 7.29.0
- error-ex: 1.3.4
- json-parse-even-better-errors: 3.0.2
- lines-and-columns: 2.0.4
- type-fest: 3.13.1
+ ms@2.1.3: {}
- parse-statements@1.0.11: {}
+ mysql2@3.15.3:
+ dependencies:
+ aws-ssl-profiles: 1.1.2
+ denque: 2.1.0
+ generate-function: 2.3.1
+ iconv-lite: 0.7.2
+ long: 5.3.2
+ lru.min: 1.1.4
+ named-placeholders: 1.1.6
+ seq-queue: 0.0.5
+ sqlstring: 2.3.3
- parseurl@1.3.3: {}
+ named-placeholders@1.1.6:
+ dependencies:
+ lru.min: 1.1.4
- path-exists@4.0.0: {}
+ ohash@2.0.11: {}
- path-is-absolute@1.0.1: {}
+ package-json-from-dist@1.0.1: {}
path-key@3.1.1: {}
- path-parse@1.0.7: {}
-
- path-scurry@1.11.1:
- dependencies:
- lru-cache: 10.4.3
- minipass: 7.1.3
-
path-scurry@2.0.2:
dependencies:
- lru-cache: 11.3.5
+ lru-cache: 11.3.6
minipass: 7.1.3
- path-to-regexp@0.1.13: {}
-
- path-type@4.0.0: {}
-
- pathe@1.1.2: {}
-
pathe@2.0.3: {}
- perfect-debounce@1.0.0: {}
+ perfect-debounce@2.1.0: {}
pg-cloudflare@1.3.0:
optional: true
@@ -8442,225 +2151,66 @@ snapshots:
dependencies:
split2: 4.2.0
- picocolors@1.1.1: {}
-
- picomatch@2.3.2: {}
-
- picomatch@4.0.4: {}
-
- pkg-types@2.3.0:
+ pkg-types@2.3.1:
dependencies:
confbox: 0.2.4
exsolve: 1.0.8
pathe: 2.0.3
- plur@5.1.0:
- dependencies:
- irregular-plurals: 3.5.0
-
- pluralize@8.0.0: {}
-
- possible-typed-array-names@1.1.0: {}
-
- postcss-selector-parser@7.1.1:
- dependencies:
- cssesc: 3.0.0
- util-deprecate: 1.0.2
-
- postcss@8.5.10:
- dependencies:
- nanoid: 3.3.11
- picocolors: 1.1.1
- source-map-js: 1.2.1
-
- postcss@8.5.14:
- dependencies:
- nanoid: 3.3.11
- picocolors: 1.1.1
- source-map-js: 1.2.1
-
postgres-array@2.0.0: {}
- postgres-array@3.0.4: {}
-
- postgres-bytea@1.0.1: {}
-
- postgres-date@1.0.7: {}
-
- postgres-interval@1.2.0:
- dependencies:
- xtend: 4.0.2
-
- postgres@3.4.7: {}
-
- prelude-ls@1.2.1: {}
-
- prettier@3.8.3: {}
-
- prisma@7.7.0(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(typescript@5.9.3):
- dependencies:
- '@prisma/config': 7.7.0
- '@prisma/dev': 0.24.3(typescript@5.9.3)
- '@prisma/engines': 7.7.0
- '@prisma/studio-core': 0.27.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
- mysql2: 3.15.3
- postgres: 3.4.7
- optionalDependencies:
- typescript: 5.9.3
- transitivePeerDependencies:
- - '@types/react'
- - '@types/react-dom'
- - magicast
- - react
- - react-dom
-
- proc-log@4.2.0: {}
-
- promise-inflight@1.0.1: {}
-
- promise-retry@2.0.1:
- dependencies:
- err-code: 2.0.3
- retry: 0.12.0
-
- prompts@2.4.2:
- dependencies:
- kleur: 3.0.3
- sisteransi: 1.0.5
-
- prop-types@15.8.1:
- dependencies:
- loose-envify: 1.4.0
- object-assign: 4.1.1
- react-is: 16.13.1
-
- proper-lockfile@4.1.2:
- dependencies:
- graceful-fs: 4.2.11
- retry: 0.12.0
- signal-exit: 3.0.7
-
- proxy-addr@2.0.7:
- dependencies:
- forwarded: 0.2.0
- ipaddr.js: 1.9.1
-
- punycode@2.3.1: {}
-
- pure-rand@6.1.0: {}
-
- qs@6.14.2:
- dependencies:
- side-channel: 1.1.0
-
- qs@6.15.1:
- dependencies:
- side-channel: 1.1.0
-
- queue-microtask@1.2.3: {}
-
- range-parser@1.2.1: {}
-
- raw-body@2.5.3:
- dependencies:
- bytes: 3.1.2
- http-errors: 2.0.1
- iconv-lite: 0.4.24
- unpipe: 1.0.0
-
- rc9@2.1.2:
- dependencies:
- defu: 6.1.7
- destr: 2.0.5
-
- react-dom@19.2.6(react@19.2.6):
- dependencies:
- react: 19.2.6
- scheduler: 0.27.0
-
- react-is@16.13.1: {}
-
- react-refresh@0.14.2: {}
+ postgres-array@3.0.4: {}
- react-router@7.15.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6):
- dependencies:
- cookie: 1.1.1
- react: 19.2.6
- set-cookie-parser: 2.7.2
- optionalDependencies:
- react-dom: 19.2.6(react@19.2.6)
+ postgres-bytea@1.0.1: {}
- react@19.2.6: {}
+ postgres-date@1.0.7: {}
- read-package-json-fast@3.0.2:
+ postgres-interval@1.2.0:
dependencies:
- json-parse-even-better-errors: 3.0.2
- npm-normalize-package-bin: 3.0.1
+ xtend: 4.0.2
- readable-stream@3.6.2:
- dependencies:
- inherits: 2.0.4
- string_decoder: 1.3.0
- util-deprecate: 1.0.2
+ postgres@3.4.7: {}
- readdirp@4.1.2: {}
+ prettier@3.8.3: {}
- refa@0.12.1:
+ prisma@7.8.0(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(typescript@6.0.3):
dependencies:
- '@eslint-community/regexpp': 4.12.2
+ '@prisma/config': 7.8.0
+ '@prisma/dev': 0.24.3(typescript@6.0.3)
+ '@prisma/engines': 7.8.0
+ '@prisma/studio-core': 0.27.3(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
+ mysql2: 3.15.3
+ postgres: 3.4.7
+ optionalDependencies:
+ typescript: 6.0.3
+ transitivePeerDependencies:
+ - '@types/react'
+ - '@types/react-dom'
+ - magicast
+ - react
+ - react-dom
- reflect.getprototypeof@1.0.10:
- dependencies:
- call-bind: 1.0.9
- define-properties: 1.2.1
- es-abstract: 1.24.2
- es-errors: 1.3.0
- es-object-atoms: 1.1.1
- get-intrinsic: 1.3.0
- get-proto: 1.0.1
- which-builtin-type: 1.2.1
-
- regexp-ast-analysis@0.7.1:
+ proper-lockfile@4.1.2:
dependencies:
- '@eslint-community/regexpp': 4.12.2
- refa: 0.12.1
+ graceful-fs: 4.2.11
+ retry: 0.12.0
+ signal-exit: 3.0.7
- regexp-tree@0.1.27: {}
+ pure-rand@6.1.0: {}
- regexp.prototype.flags@1.5.4:
+ rc9@3.0.1:
dependencies:
- call-bind: 1.0.9
- define-properties: 1.2.1
- es-errors: 1.3.0
- get-proto: 1.0.1
- gopd: 1.2.0
- set-function-name: 2.0.2
-
- regjsparser@0.12.0:
- dependencies:
- jsesc: 3.0.2
+ defu: 6.1.7
+ destr: 2.0.5
- remark-mdx@3.1.1:
+ react-dom@19.2.6(react@19.2.6):
dependencies:
- mdast-util-mdx: 3.0.0
- micromark-extension-mdxjs: 3.0.0
- transitivePeerDependencies:
- - supports-color
+ react: 19.2.6
+ scheduler: 0.27.0
- remark-parse@11.0.0:
- dependencies:
- '@types/mdast': 4.0.4
- mdast-util-from-markdown: 2.0.3
- micromark-util-types: 2.0.2
- unified: 11.0.5
- transitivePeerDependencies:
- - supports-color
+ react@19.2.5: {}
- remark-stringify@11.0.0:
- dependencies:
- '@types/mdast': 4.0.4
- mdast-util-to-markdown: 2.1.2
- unified: 11.0.5
+ readdirp@5.0.0: {}
remeda@2.33.4: {}
@@ -8668,147 +2218,22 @@ snapshots:
require-from-string@2.0.2: {}
- requireindex@1.2.0: {}
-
- reserved-identifiers@1.2.0: {}
-
- resolve-from@4.0.0: {}
-
- resolve-pkg-maps@1.0.0: {}
-
- resolve@1.22.12:
- dependencies:
- es-errors: 1.3.0
- is-core-module: 2.16.1
- path-parse: 1.0.7
- supports-preserve-symlinks-flag: 1.0.0
-
- resolve@2.0.0-next.6:
- dependencies:
- es-errors: 1.3.0
- is-core-module: 2.16.1
- node-exports-info: 1.6.0
- object-keys: 1.1.1
- path-parse: 1.0.7
- supports-preserve-symlinks-flag: 1.0.0
-
retry@0.12.0: {}
- reusify@1.1.0: {}
-
rimraf@6.1.3:
dependencies:
glob: 13.0.6
package-json-from-dist: 1.0.1
- rolldown@1.0.0-rc.18:
- dependencies:
- '@oxc-project/types': 0.128.0
- '@rolldown/pluginutils': 1.0.0-rc.18
- optionalDependencies:
- '@rolldown/binding-android-arm64': 1.0.0-rc.18
- '@rolldown/binding-darwin-arm64': 1.0.0-rc.18
- '@rolldown/binding-darwin-x64': 1.0.0-rc.18
- '@rolldown/binding-freebsd-x64': 1.0.0-rc.18
- '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.18
- '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.18
- '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.18
- '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.18
- '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.18
- '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.18
- '@rolldown/binding-linux-x64-musl': 1.0.0-rc.18
- '@rolldown/binding-openharmony-arm64': 1.0.0-rc.18
- '@rolldown/binding-wasm32-wasi': 1.0.0-rc.18
- '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.18
- '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.18
-
- rollup@4.60.3:
- dependencies:
- '@types/estree': 1.0.8
- optionalDependencies:
- '@rollup/rollup-android-arm-eabi': 4.60.3
- '@rollup/rollup-android-arm64': 4.60.3
- '@rollup/rollup-darwin-arm64': 4.60.3
- '@rollup/rollup-darwin-x64': 4.60.3
- '@rollup/rollup-freebsd-arm64': 4.60.3
- '@rollup/rollup-freebsd-x64': 4.60.3
- '@rollup/rollup-linux-arm-gnueabihf': 4.60.3
- '@rollup/rollup-linux-arm-musleabihf': 4.60.3
- '@rollup/rollup-linux-arm64-gnu': 4.60.3
- '@rollup/rollup-linux-arm64-musl': 4.60.3
- '@rollup/rollup-linux-loong64-gnu': 4.60.3
- '@rollup/rollup-linux-loong64-musl': 4.60.3
- '@rollup/rollup-linux-ppc64-gnu': 4.60.3
- '@rollup/rollup-linux-ppc64-musl': 4.60.3
- '@rollup/rollup-linux-riscv64-gnu': 4.60.3
- '@rollup/rollup-linux-riscv64-musl': 4.60.3
- '@rollup/rollup-linux-s390x-gnu': 4.60.3
- '@rollup/rollup-linux-x64-gnu': 4.60.3
- '@rollup/rollup-linux-x64-musl': 4.60.3
- '@rollup/rollup-openbsd-x64': 4.60.3
- '@rollup/rollup-openharmony-arm64': 4.60.3
- '@rollup/rollup-win32-arm64-msvc': 4.60.3
- '@rollup/rollup-win32-ia32-msvc': 4.60.3
- '@rollup/rollup-win32-x64-gnu': 4.60.3
- '@rollup/rollup-win32-x64-msvc': 4.60.3
- fsevents: 2.3.3
-
- run-parallel@1.2.0:
- dependencies:
- queue-microtask: 1.2.3
-
- rxjs-report-usage@1.0.6:
- dependencies:
- '@babel/parser': 7.29.2
- '@babel/traverse': 7.29.0
- '@babel/types': 7.29.0
- bent: 7.3.12
- chalk: 4.1.2
- glob: 7.2.3
- prompts: 2.4.2
- transitivePeerDependencies:
- - supports-color
-
rxjs@7.8.2:
dependencies:
tslib: 2.8.1
- safe-array-concat@1.1.3:
- dependencies:
- call-bind: 1.0.9
- call-bound: 1.0.4
- get-intrinsic: 1.3.0
- has-symbols: 1.1.0
- isarray: 2.0.5
-
- safe-buffer@5.1.2: {}
-
- safe-buffer@5.2.1: {}
-
- safe-push-apply@1.0.0:
- dependencies:
- es-errors: 1.3.0
- isarray: 2.0.5
-
- safe-regex-test@1.1.0:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- is-regex: 1.2.1
-
safer-buffer@2.1.2: {}
scheduler@0.27.0: {}
- scslre@0.3.0:
- dependencies:
- '@eslint-community/regexpp': 4.12.2
- refa: 0.12.1
- regexp-ast-analysis: 0.7.1
-
- semver@6.3.1: {}
-
- semver@7.7.4: {}
+ semver@7.8.0: {}
send@0.19.2:
dependencies:
@@ -8830,38 +2255,36 @@ snapshots:
seq-queue@0.0.5: {}
- serve-static@1.16.3:
- dependencies:
- encodeurl: 2.0.0
- escape-html: 1.0.3
- parseurl: 1.3.3
- send: 0.19.2
- transitivePeerDependencies:
- - supports-color
-
- set-cookie-parser@2.7.2: {}
-
- set-function-length@1.2.2:
+ sharp@0.34.5:
dependencies:
- define-data-property: 1.1.4
- es-errors: 1.3.0
- function-bind: 1.1.2
- get-intrinsic: 1.3.0
- gopd: 1.2.0
- has-property-descriptors: 1.0.2
-
- set-function-name@2.0.2:
- dependencies:
- define-data-property: 1.1.4
- es-errors: 1.3.0
- functions-have-names: 1.2.3
- has-property-descriptors: 1.0.2
-
- set-proto@1.0.0:
- dependencies:
- dunder-proto: 1.0.1
- es-errors: 1.3.0
- es-object-atoms: 1.1.1
+ '@img/colour': 1.1.0
+ detect-libc: 2.1.2
+ semver: 7.8.0
+ optionalDependencies:
+ '@img/sharp-darwin-arm64': 0.34.5
+ '@img/sharp-darwin-x64': 0.34.5
+ '@img/sharp-libvips-darwin-arm64': 1.2.4
+ '@img/sharp-libvips-darwin-x64': 1.2.4
+ '@img/sharp-libvips-linux-arm': 1.2.4
+ '@img/sharp-libvips-linux-arm64': 1.2.4
+ '@img/sharp-libvips-linux-ppc64': 1.2.4
+ '@img/sharp-libvips-linux-riscv64': 1.2.4
+ '@img/sharp-libvips-linux-s390x': 1.2.4
+ '@img/sharp-libvips-linux-x64': 1.2.4
+ '@img/sharp-libvips-linuxmusl-arm64': 1.2.4
+ '@img/sharp-libvips-linuxmusl-x64': 1.2.4
+ '@img/sharp-linux-arm': 0.34.5
+ '@img/sharp-linux-arm64': 0.34.5
+ '@img/sharp-linux-ppc64': 0.34.5
+ '@img/sharp-linux-riscv64': 0.34.5
+ '@img/sharp-linux-s390x': 0.34.5
+ '@img/sharp-linux-x64': 0.34.5
+ '@img/sharp-linuxmusl-arm64': 0.34.5
+ '@img/sharp-linuxmusl-x64': 0.34.5
+ '@img/sharp-wasm32': 0.34.5
+ '@img/sharp-win32-arm64': 0.34.5
+ '@img/sharp-win32-ia32': 0.34.5
+ '@img/sharp-win32-x64': 0.34.5
setprototypeof@1.2.0: {}
@@ -8873,181 +2296,26 @@ snapshots:
shell-quote@1.8.3: {}
- side-channel-list@1.0.1:
- dependencies:
- es-errors: 1.3.0
- object-inspect: 1.13.4
-
- side-channel-map@1.0.1:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- get-intrinsic: 1.3.0
- object-inspect: 1.13.4
-
- side-channel-weakmap@1.0.2:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- get-intrinsic: 1.3.0
- object-inspect: 1.13.4
- side-channel-map: 1.0.1
-
- side-channel@1.1.0:
- dependencies:
- es-errors: 1.3.0
- object-inspect: 1.13.4
- side-channel-list: 1.0.1
- side-channel-map: 1.0.1
- side-channel-weakmap: 1.0.2
-
signal-exit@3.0.7: {}
signal-exit@4.1.0: {}
- sisteransi@1.0.5: {}
-
- slash@3.0.0: {}
-
- source-map-js@1.2.1: {}
-
- source-map-support@0.5.21:
- dependencies:
- buffer-from: 1.1.2
- source-map: 0.6.1
-
- source-map@0.6.1: {}
-
- spdx-correct@3.2.0:
- dependencies:
- spdx-expression-parse: 3.0.1
- spdx-license-ids: 3.0.23
-
- spdx-exceptions@2.5.0: {}
-
- spdx-expression-parse@3.0.1:
- dependencies:
- spdx-exceptions: 2.5.0
- spdx-license-ids: 3.0.23
-
- spdx-expression-parse@4.0.0:
- dependencies:
- spdx-exceptions: 2.5.0
- spdx-license-ids: 3.0.23
-
- spdx-license-ids@3.0.23: {}
-
split2@4.2.0: {}
sqlstring@2.3.3: {}
- stable-hash-x@0.2.0: {}
-
- statuses@2.0.2: {}
-
std-env@3.10.0: {}
- stop-iteration-iterator@1.1.0:
- dependencies:
- es-errors: 1.3.0
- internal-slot: 1.1.0
-
string-width@4.2.3:
dependencies:
emoji-regex: 8.0.0
is-fullwidth-code-point: 3.0.0
strip-ansi: 6.0.1
- string-width@5.1.2:
- dependencies:
- eastasianwidth: 0.2.0
- emoji-regex: 9.2.2
- strip-ansi: 7.2.0
-
- string-width@6.1.0:
- dependencies:
- eastasianwidth: 0.2.0
- emoji-regex: 10.6.0
- strip-ansi: 7.2.0
-
- string-width@8.2.0:
- dependencies:
- get-east-asian-width: 1.5.0
- strip-ansi: 7.2.0
-
- string.prototype.includes@2.0.1:
- dependencies:
- call-bind: 1.0.9
- define-properties: 1.2.1
- es-abstract: 1.24.2
-
- string.prototype.matchall@4.0.12:
- dependencies:
- call-bind: 1.0.9
- call-bound: 1.0.4
- define-properties: 1.2.1
- es-abstract: 1.24.2
- es-errors: 1.3.0
- es-object-atoms: 1.1.1
- get-intrinsic: 1.3.0
- gopd: 1.2.0
- has-symbols: 1.1.0
- internal-slot: 1.1.0
- regexp.prototype.flags: 1.5.4
- set-function-name: 2.0.2
- side-channel: 1.1.0
-
- string.prototype.repeat@1.0.0:
- dependencies:
- define-properties: 1.2.1
- es-abstract: 1.24.2
-
- string.prototype.trim@1.2.10:
- dependencies:
- call-bind: 1.0.9
- call-bound: 1.0.4
- define-data-property: 1.1.4
- define-properties: 1.2.1
- es-abstract: 1.24.2
- es-object-atoms: 1.1.1
- has-property-descriptors: 1.0.2
-
- string.prototype.trimend@1.0.9:
- dependencies:
- call-bind: 1.0.9
- call-bound: 1.0.4
- define-properties: 1.2.1
- es-object-atoms: 1.1.1
-
- string.prototype.trimstart@1.0.8:
- dependencies:
- call-bind: 1.0.9
- define-properties: 1.2.1
- es-object-atoms: 1.1.1
-
- string_decoder@1.3.0:
- dependencies:
- safe-buffer: 5.2.1
-
- stringify-entities@4.0.4:
- dependencies:
- character-entities-html4: 2.1.0
- character-entities-legacy: 3.0.0
-
strip-ansi@6.0.1:
dependencies:
ansi-regex: 5.0.1
- strip-ansi@7.2.0:
- dependencies:
- ansi-regex: 6.2.2
-
- strip-indent@4.1.1: {}
-
- strip-json-comments@3.1.1: {}
-
- supports-color@10.2.2: {}
-
supports-color@7.2.0:
dependencies:
has-flag: 4.0.0
@@ -9056,76 +2324,12 @@ snapshots:
dependencies:
has-flag: 4.0.0
- supports-color@9.4.0: {}
-
- supports-hyperlinks@4.4.0:
- dependencies:
- has-flag: 5.0.1
- supports-color: 10.2.2
-
- supports-preserve-symlinks-flag@1.0.0: {}
-
- svelte@3.59.2: {}
-
- synckit@0.11.12:
- dependencies:
- '@pkgr/core': 0.2.9
-
- tailwindcss@4.3.0: {}
-
- tapable@2.3.2: {}
-
- tapable@2.3.3: {}
-
- tinyexec@1.1.1: {}
-
- tinyglobby@0.2.16:
- dependencies:
- fdir: 6.5.0(picomatch@4.0.4)
- picomatch: 4.0.4
-
- to-regex-range@5.0.1:
- dependencies:
- is-number: 7.0.0
-
- to-valid-identifier@1.0.0:
- dependencies:
- '@sindresorhus/base62': 1.0.0
- reserved-identifiers: 1.2.0
-
- toidentifier@1.0.1: {}
-
tree-kill@1.2.2: {}
- trough@2.2.0: {}
-
- ts-api-utils@2.5.0(typescript@5.9.3):
- dependencies:
- typescript: 5.9.3
-
- ts-declaration-location@1.0.7(typescript@5.9.3):
- dependencies:
- picomatch: 4.0.4
- typescript: 5.9.3
-
ts-mixer@6.0.4: {}
- tslib@1.14.1: {}
-
tslib@2.8.1: {}
- tsutils-etc@1.4.2(tsutils@3.21.0(typescript@5.9.3))(typescript@5.9.3):
- dependencies:
- '@types/yargs': 17.0.35
- tsutils: 3.21.0(typescript@5.9.3)
- typescript: 5.9.3
- yargs: 17.7.2
-
- tsutils@3.21.0(typescript@5.9.3):
- dependencies:
- tslib: 1.14.1
- typescript: 5.9.3
-
turbo@2.9.14:
optionalDependencies:
'@turbo/darwin-64': 2.9.14
@@ -9135,367 +2339,36 @@ snapshots:
'@turbo/windows-64': 2.9.14
'@turbo/windows-arm64': 2.9.14
- type-check@0.4.0:
- dependencies:
- prelude-ls: 1.2.1
-
- type-fest@3.13.1: {}
-
- type-is@1.6.18:
- dependencies:
- media-typer: 0.3.0
- mime-types: 2.1.35
-
- typed-array-buffer@1.0.3:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- is-typed-array: 1.1.15
-
- typed-array-byte-length@1.0.3:
- dependencies:
- call-bind: 1.0.9
- for-each: 0.3.5
- gopd: 1.2.0
- has-proto: 1.2.0
- is-typed-array: 1.1.15
-
- typed-array-byte-offset@1.0.4:
- dependencies:
- available-typed-arrays: 1.0.7
- call-bind: 1.0.9
- for-each: 0.3.5
- gopd: 1.2.0
- has-proto: 1.2.0
- is-typed-array: 1.1.15
- reflect.getprototypeof: 1.0.10
-
- typed-array-length@1.0.7:
- dependencies:
- call-bind: 1.0.9
- for-each: 0.3.5
- gopd: 1.2.0
- is-typed-array: 1.1.15
- possible-typed-array-names: 1.1.0
- reflect.getprototypeof: 1.0.10
-
- typedarray@0.0.6: {}
-
- typescript-eslint@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3):
- dependencies:
- '@typescript-eslint/eslint-plugin': 8.58.2(@typescript-eslint/parser@8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/parser': 8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/typescript-estree': 8.58.2(typescript@5.9.3)
- '@typescript-eslint/utils': 8.58.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- eslint: 9.39.4(jiti@2.6.1)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
typescript@5.4.5: {}
- typescript@5.9.3: {}
-
- unbox-primitive@1.1.0:
- dependencies:
- call-bound: 1.0.4
- has-bigints: 1.1.0
- has-symbols: 1.1.0
- which-boxed-primitive: 1.1.1
+ typescript@6.0.3: {}
- undici-types@6.21.0: {}
+ undici-types@7.24.6: {}
undici@6.24.1: {}
- unified-engine@11.2.2:
- dependencies:
- '@types/concat-stream': 2.0.3
- '@types/debug': 4.1.13
- '@types/is-empty': 1.2.3
- '@types/node': 22.19.17
- '@types/unist': 3.0.3
- concat-stream: 2.0.0
- debug: 4.4.3
- extend: 3.0.2
- glob: 10.5.0
- ignore: 6.0.2
- is-empty: 1.2.0
- is-plain-obj: 4.1.0
- load-plugin: 6.0.3
- parse-json: 7.1.1
- trough: 2.2.0
- unist-util-inspect: 8.1.0
- vfile: 6.0.3
- vfile-message: 4.0.3
- vfile-reporter: 8.1.1
- vfile-statistics: 3.0.0
- yaml: 2.8.3
- transitivePeerDependencies:
- - bluebird
- - supports-color
-
- unified@11.0.5:
- dependencies:
- '@types/unist': 3.0.3
- bail: 2.0.2
- devlop: 1.1.0
- extend: 3.0.2
- is-plain-obj: 4.1.0
- trough: 2.2.0
- vfile: 6.0.3
-
- unist-util-inspect@8.1.0:
- dependencies:
- '@types/unist': 3.0.3
-
- unist-util-is@6.0.1:
- dependencies:
- '@types/unist': 3.0.3
-
- unist-util-position-from-estree@2.0.0:
- dependencies:
- '@types/unist': 3.0.3
-
- unist-util-stringify-position@4.0.0:
- dependencies:
- '@types/unist': 3.0.3
-
- unist-util-visit-parents@6.0.2:
- dependencies:
- '@types/unist': 3.0.3
- unist-util-is: 6.0.1
-
- unist-util-visit@5.1.0:
- dependencies:
- '@types/unist': 3.0.3
- unist-util-is: 6.0.1
- unist-util-visit-parents: 6.0.2
-
- unpipe@1.0.0: {}
-
- unrs-resolver@1.11.1:
- dependencies:
- napi-postinstall: 0.3.4
- optionalDependencies:
- '@unrs/resolver-binding-android-arm-eabi': 1.11.1
- '@unrs/resolver-binding-android-arm64': 1.11.1
- '@unrs/resolver-binding-darwin-arm64': 1.11.1
- '@unrs/resolver-binding-darwin-x64': 1.11.1
- '@unrs/resolver-binding-freebsd-x64': 1.11.1
- '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1
- '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1
- '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1
- '@unrs/resolver-binding-linux-arm64-musl': 1.11.1
- '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1
- '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1
- '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1
- '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1
- '@unrs/resolver-binding-linux-x64-gnu': 1.11.1
- '@unrs/resolver-binding-linux-x64-musl': 1.11.1
- '@unrs/resolver-binding-wasm32-wasi': 1.11.1
- '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1
- '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1
- '@unrs/resolver-binding-win32-x64-msvc': 1.11.1
-
- update-browserslist-db@1.2.3(browserslist@4.28.2):
- dependencies:
- browserslist: 4.28.2
- escalade: 3.2.0
- picocolors: 1.1.1
-
- uri-js@4.4.1:
- dependencies:
- punycode: 2.3.1
-
- util-deprecate@1.0.2: {}
-
- utils-merge@1.0.1: {}
-
- valibot@1.2.0(typescript@5.9.3):
- optionalDependencies:
- typescript: 5.9.3
-
- validate-npm-package-license@3.0.4:
- dependencies:
- spdx-correct: 3.2.0
- spdx-expression-parse: 3.0.1
-
- validate-npm-package-name@5.0.1: {}
-
- vary@1.1.2: {}
-
- vfile-message@4.0.3:
- dependencies:
- '@types/unist': 3.0.3
- unist-util-stringify-position: 4.0.0
-
- vfile-reporter@8.1.1:
- dependencies:
- '@types/supports-color': 8.1.3
- string-width: 6.1.0
- supports-color: 9.4.0
- unist-util-stringify-position: 4.0.0
- vfile: 6.0.3
- vfile-message: 4.0.3
- vfile-sort: 4.0.0
- vfile-statistics: 3.0.0
-
- vfile-sort@4.0.0:
- dependencies:
- vfile: 6.0.3
- vfile-message: 4.0.3
-
- vfile-statistics@3.0.0:
- dependencies:
- vfile: 6.0.3
- vfile-message: 4.0.3
-
- vfile@6.0.3:
- dependencies:
- '@types/unist': 3.0.3
- vfile-message: 4.0.3
-
- vite-node@3.2.4(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3):
- dependencies:
- cac: 6.7.14
- debug: 4.4.3
- es-module-lexer: 1.7.0
- pathe: 2.0.3
- vite: 7.3.3(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
- transitivePeerDependencies:
- - '@types/node'
- - jiti
- - less
- - lightningcss
- - sass
- - sass-embedded
- - stylus
- - sugarss
- - supports-color
- - terser
- - tsx
- - yaml
-
- vite@7.3.3(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3):
- dependencies:
- esbuild: 0.27.7
- fdir: 6.5.0(picomatch@4.0.4)
- picomatch: 4.0.4
- postcss: 8.5.10
- rollup: 4.60.3
- tinyglobby: 0.2.16
- optionalDependencies:
- '@types/node': 22.19.17
- fsevents: 2.3.3
- jiti: 2.6.1
- lightningcss: 1.32.0
- yaml: 2.8.3
-
- vite@8.0.11(@types/node@22.19.17)(esbuild@0.27.7)(jiti@2.6.1)(yaml@2.8.3):
- dependencies:
- lightningcss: 1.32.0
- picomatch: 4.0.4
- postcss: 8.5.14
- rolldown: 1.0.0-rc.18
- tinyglobby: 0.2.16
+ valibot@1.2.0(typescript@6.0.3):
optionalDependencies:
- '@types/node': 22.19.17
- esbuild: 0.27.7
- fsevents: 2.3.3
- jiti: 2.6.1
- yaml: 2.8.3
-
- vue-eslint-parser@10.4.0(eslint@9.39.4(jiti@2.6.1)):
- dependencies:
- debug: 4.4.3
- eslint: 9.39.4(jiti@2.6.1)
- eslint-scope: 9.1.2
- eslint-visitor-keys: 5.0.1
- espree: 11.2.0
- esquery: 1.7.0
- semver: 7.7.4
- transitivePeerDependencies:
- - supports-color
-
- walk-up-path@3.0.1: {}
-
- which-boxed-primitive@1.1.1:
- dependencies:
- is-bigint: 1.1.0
- is-boolean-object: 1.2.2
- is-number-object: 1.1.1
- is-string: 1.1.1
- is-symbol: 1.1.1
-
- which-builtin-type@1.2.1:
- dependencies:
- call-bound: 1.0.4
- function.prototype.name: 1.1.8
- has-tostringtag: 1.0.2
- is-async-function: 2.1.1
- is-date-object: 1.1.0
- is-finalizationregistry: 1.1.1
- is-generator-function: 1.1.2
- is-regex: 1.2.1
- is-weakref: 1.1.1
- isarray: 2.0.5
- which-boxed-primitive: 1.1.1
- which-collection: 1.0.2
- which-typed-array: 1.1.20
-
- which-collection@1.0.2:
- dependencies:
- is-map: 2.0.3
- is-set: 2.0.3
- is-weakmap: 2.0.2
- is-weakset: 2.0.4
-
- which-typed-array@1.1.20:
- dependencies:
- available-typed-arrays: 1.0.7
- call-bind: 1.0.9
- call-bound: 1.0.4
- for-each: 0.3.5
- get-proto: 1.0.1
- gopd: 1.2.0
- has-tostringtag: 1.0.2
+ typescript: 6.0.3
which@2.0.2:
dependencies:
isexe: 2.0.0
- which@4.0.0:
- dependencies:
- isexe: 3.1.5
-
- word-wrap@1.2.5: {}
-
wrap-ansi@7.0.0:
dependencies:
ansi-styles: 4.3.0
string-width: 4.2.3
strip-ansi: 6.0.1
- wrap-ansi@8.1.0:
- dependencies:
- ansi-styles: 6.2.3
- string-width: 5.1.2
- strip-ansi: 7.2.0
-
- wrappy@1.0.2: {}
-
ws@8.20.0: {}
- xml-name-validator@4.0.0: {}
+ ws@8.20.1: {}
xtend@4.0.2: {}
y18n@5.0.8: {}
- yallist@3.1.1: {}
-
- yaml@2.8.3: {}
-
yargs-parser@21.1.1: {}
yargs@17.7.2:
@@ -9508,19 +2381,9 @@ snapshots:
y18n: 5.0.8
yargs-parser: 21.1.1
- yocto-queue@0.1.0: {}
-
- yoctocolors@2.1.2: {}
-
zeptomatch@2.1.0:
dependencies:
grammex: 3.1.12
graphmatch: 1.1.1
- zod-validation-error@4.0.2(zod@4.3.6):
- dependencies:
- zod: 4.3.6
-
- zod@4.3.6: {}
-
- zwitch@2.0.4: {}
+ zod@4.4.3: {}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index cc85114..6c8a7a9 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -11,4 +11,5 @@ allowBuilds:
'@prisma/engines': true
esbuild: true
prisma: true
+ sharp: true
unrs-resolver: true