diff --git a/config.js b/config.ts similarity index 67% rename from config.js rename to config.ts index d87004d..1fb5779 100644 --- a/config.js +++ b/config.ts @@ -1,8 +1,11 @@ +import type { ColorResolvable } from "discord.js"; + export const defaultConfig = { channel: process.env.CHANNEL_ID, // Channel ID token: process.env.TOKEN, // Discord bot token - owners: [...process.env.OWNERS_IDS.split(",")], // Array of owners IDs (separated by commas) - embedColor: "#5865f2", // Discord's blurple + cwd: process.env.CUSTOM_CWD || process.cwd(), // Custom working directory + owners: [...(process.env.OWNERS_IDS?.split(",") ?? [])], // Array of owners IDs (separated by commas) + embedColor: [88, 101, 242] as ColorResolvable, // Discord's blurple emojis: { loading: "", // https://cdn.discordapp.com/emojis/895227261752582154.gif?v=1 output: "📤", diff --git a/events/client/ready.js b/events/client/ready.js deleted file mode 100644 index fe5ce1b..0000000 --- a/events/client/ready.js +++ /dev/null @@ -1,29 +0,0 @@ -import { ActivityType } from "discord.js"; -import { defaultConfig } from "../../config.js"; -import { logger } from "../../utils/logger.js"; - -/** - * Handles the ready event. - * - * @param {object} client The Discord client. - * @returns {Promise} - */ -export async function ready(client) { - try { - defaultConfig.channel = client.channels.cache.get(defaultConfig.channel); - if (!defaultConfig.channel) return logger("error", "Channel not found! Please check your CHANNEL_ID .env variable."); - - if (!(await defaultConfig.channel.fetchWebhooks()).size) { - await defaultConfig.channel.createWebhook({ - name: "SSH", - avatar: client.user.displayAvatarURL(), - reason: "SSH Webhook", - }); - } - - logger("ready", `Logged in as ${client.user.tag}! (ID: ${client.user.id})`); - client.user.setActivity("all ports!", { type: ActivityType.Watching }); - } catch (error) { - logger("error", error); - } -} diff --git a/events/client/ready.ts b/events/client/ready.ts new file mode 100644 index 0000000..5c8b53e --- /dev/null +++ b/events/client/ready.ts @@ -0,0 +1,15 @@ +import { ActivityType, Client, TextChannel } from "discord.js"; +import { logger } from "../../utils/logger.js"; +import { defaultConfig } from "../../config.js"; + +export async function ready(client: Client): Promise { + try { + logger("ready", `Logged in as ${client.user?.tag}! (ID: ${client.user?.id})`); + if (!defaultConfig.channel) return logger("error", "Channel not found! Please check your CHANNEL_ID .env variable."); + const channel = client.channels.cache.get(defaultConfig.channel) as TextChannel; + logger("ready", `Watching for commands in ${channel.guild.name}#${channel.name}`); + client.user?.setActivity("👀 Watching all ports!", { type: ActivityType.Custom }); + } catch (error) { + logger("error", `Error setting activity: ${error}`); + } +} diff --git a/events/guild/messageCreate.js b/events/guild/messageCreate.js deleted file mode 100644 index 56f1eea..0000000 --- a/events/guild/messageCreate.js +++ /dev/null @@ -1,70 +0,0 @@ -import fs from "node:fs"; -import path from "node:path"; -import { EmbedBuilder } from "discord.js"; -import { defaultConfig } from "../../config.js"; -import { execCommand } from "../../utils/execCommand.js"; -import { logger } from "../../utils/logger.js"; - -/** - * Creates an embed. - * - * @param {string} description The embed description. - * @param {string} color The embed color. - * @returns {EmbedBuilder} The embed. - */ -function createEmbed(description, color) { - return new EmbedBuilder() // prettier - .setDescription(description) - .setColor(color); -} - -/** - * Handles the messageCreate event. - * - * @param {object} client The Discord client. - * @param {object} message The message object. - * @returns {Promise} - */ -export async function messageCreate(client, message) { - try { - if (message.author.bot) return; - if (message.channel !== defaultConfig.channel && !defaultConfig.owners.includes(message.author.id)) return; - if (!message.content) return; - - const [command, ...args] = message.content.split(" "); - - if (command === "cd") { - const newCWD = args.join(" "); - if (!newCWD) return; - - const resolvedPath = path.resolve(client.customCWD, newCWD); - if (!fs.existsSync(resolvedPath)) { - const error = createEmbed(`${defaultConfig.emojis.error} **Directory does not exist**`, defaultConfig.embedColor); - return message.reply({ embeds: [error] }); - } - - try { - process.chdir(resolvedPath); - defaultConfig.debugger.changeDir && logger("event", `Changed directory from ${client.customCWD} to ${resolvedPath}`); - - const changedDirectory = createEmbed(`${defaultConfig.emojis.change} **Changed directory from \`${client.customCWD}\` to \`${resolvedPath}\`**`, defaultConfig.embedColor); - - client.customCWD = resolvedPath; - return message.reply({ embeds: [changedDirectory] }); - } catch (err) { - defaultConfig.debugger.changeDir && logger("error", err); - const error = createEmbed(`${defaultConfig.emojis.error} **${err.message}**`, defaultConfig.embedColor); - - return message.reply({ embeds: [error] }); - } - } - - const wait = createEmbed(`${defaultConfig.emojis.loading} **Waiting for server response...**`, defaultConfig.embedColor); - - await message.reply({ embeds: [wait] }); - - await execCommand(client, message.content); - } catch (error) { - logger("error", error); - } -} diff --git a/events/guild/messageCreate.ts b/events/guild/messageCreate.ts new file mode 100644 index 0000000..7ca78df --- /dev/null +++ b/events/guild/messageCreate.ts @@ -0,0 +1,59 @@ +import fs from "node:fs"; +import path from "node:path"; +import { Client, EmbedBuilder, Message, TextChannel } from "discord.js"; +import { defaultConfig } from "../../config.js"; +import { execCommand } from "../../utils/execCommand.ts"; +import { logger } from "../../utils/logger.js"; + +export async function messageCreate(client: Client, message: Message): Promise> { + try { + if (message.author.bot) return; + if (!(message.channel instanceof TextChannel)) return; + if (message.channel.id !== defaultConfig.channel && !defaultConfig.owners.includes(message.author.id)) return; + if (!message.content) return; + + const [command, ...args] = message.content.split(" "); + + if (command === "cd") { + const newCWD = args.join(" "); + if (!newCWD) return; + + const resolvedPath = path.resolve(defaultConfig.cwd, newCWD); + if (!fs.existsSync(resolvedPath)) { + const error = new EmbedBuilder() // prettier + .setDescription(`${defaultConfig.emojis.error} **Directory does not exist**`) + .setColor(defaultConfig.embedColor); + return message.reply({ embeds: [error] }); + } + + try { + process.chdir(resolvedPath); + defaultConfig.debugger.changeDir && logger("event", `Changed directory from ${defaultConfig.cwd} to ${resolvedPath}`); + + const changedDirectory = new EmbedBuilder() // prettier + .setDescription(`${defaultConfig.emojis.change} **Changed directory from \`${defaultConfig.cwd}\` to \`${resolvedPath}\`**`) + .setColor(defaultConfig.embedColor); + + defaultConfig.cwd = resolvedPath; + return message.reply({ embeds: [changedDirectory] }); + } catch (error) { + defaultConfig.debugger.changeDir && logger("error", `Error changing directory: ${error}`); + const errorEmbed = new EmbedBuilder() // prettier + .setDescription(`${defaultConfig.emojis.error} **Error changing directory**`) + .setColor(defaultConfig.embedColor); + + return message.reply({ embeds: [errorEmbed] }); + } + } + + const wait = new EmbedBuilder() // prettier + .setDescription(`${defaultConfig.emojis.loading} **Waiting for server response...**`) + .setColor(defaultConfig.embedColor); + + await message.reply({ embeds: [wait] }); + + await execCommand(client, message.content); + } catch (error) { + logger("error", `Error executing command: ${error}`); + } +} diff --git a/index.js b/index.ts similarity index 72% rename from index.js rename to index.ts index e4f1eb9..d92690f 100644 --- a/index.js +++ b/index.ts @@ -1,7 +1,7 @@ import "dotenv/config"; import { Client, GatewayIntentBits } from "discord.js"; -import loadEvents from "./utils/loadEvents.js"; -import { logger } from "./utils/logger.js"; +import loadEvents from "./utils/loadEvents"; +import { logger } from "./utils/logger"; logger("event", "Starting SSH Bot session..."); logger("info", `Running version v${process.env.npm_package_version} on Node.js ${process.version} on ${process.platform} ${process.arch}`); @@ -14,25 +14,24 @@ try { parse: ["users", "roles"], repliedUser: false, }, - intents: GatewayIntentBits.Guilds | GatewayIntentBits.GuildMembers | GatewayIntentBits.GuildPresences | GatewayIntentBits.GuildMessages | GatewayIntentBits.MessageContent, + intents: GatewayIntentBits.Guilds | GatewayIntentBits.GuildMembers | GatewayIntentBits.GuildMessages | GatewayIntentBits.MessageContent, }); - client.customCWD = process.env.CUSTOM_CWD || process.cwd(); - logger("info", "Loading events..."); await loadEvents(client); logger("info", "Logging in..."); + await client.login(process.env.TOKEN); } catch (error) { - logger("error", error); + logger("error", `Error starting the bot: ${error}`); process.exit(1); } process.on("unhandledRejection", async (reason) => { - return logger("error", reason); + return logger("error", `Unhandled Rejection: ${reason}`); }); process.on("uncaughtException", async (err) => { - return logger("error", err); + return logger("error", `Uncaught Exception: ${err}`); }); diff --git a/package.json b/package.json index 165566d..6e04a72 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,11 @@ { "name": "discord-ssh", - "version": "3.0.0", + "version": "4.0.0", "description": "Discord bot for using shell commands remotely through Discord", - "exports": null, "type": "module", "scripts": { - "start": "node index.js", - "dev": "nodemon index.js", + "start": "tsx ./index.ts", + "dev": "tsx watch ./index.ts", "format": "prettier . --write --ignore-unknown --cache", "format:check": "prettier . --check --cache", "lint": "eslint .", @@ -22,9 +21,11 @@ "devDependencies": { "@igorkowalczyk/eslint-config": "2.2.0", "@igorkowalczyk/prettier-config": "2.2.0", - "eslint": "9.9.0", - "nodemon": "3.1.4", - "prettier": "3.3.3" + "@types/node": "22.3.0", + "eslint": "9.7.0", + "prettier": "3.3.3", + "tsx": "4.17.0", + "typescript": "5.5.4" }, "engines": { "node": ">=18" @@ -47,5 +48,5 @@ "ssh", "remote-connection" ], - "packageManager": "pnpm@9.7.1" + "packageManager": "pnpm@9.6.0" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 35c16f0..d8a4837 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,19 +26,25 @@ importers: devDependencies: '@igorkowalczyk/eslint-config': specifier: 2.2.0 - version: 2.2.0(eslint@9.9.0)(prettier@3.3.3) + version: 2.2.0(eslint@9.7.0)(prettier@3.3.3) '@igorkowalczyk/prettier-config': specifier: 2.2.0 version: 2.2.0(prettier@3.3.3) + '@types/node': + specifier: 22.3.0 + version: 22.3.0 eslint: - specifier: 9.9.0 - version: 9.9.0 - nodemon: - specifier: 3.1.4 - version: 3.1.4 + specifier: 9.7.0 + version: 9.7.0 prettier: specifier: 3.3.3 version: 3.3.3 + tsx: + specifier: 4.17.0 + version: 4.17.0 + typescript: + specifier: 5.5.4 + version: 5.5.4 packages: @@ -74,6 +80,150 @@ packages: resolution: {integrity: sha512-PZ+vLpxGCRtmr2RMkqh8Zp+BenUaJqlS6xhgWKEZcgC/vfHLEzpHtKkB0sl3nZWpwtcKk6YWy+pU3okL2I97FA==} engines: {node: '>=16.11.0'} + '@esbuild/aix-ppc64@0.23.0': + resolution: {integrity: sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.23.0': + resolution: {integrity: sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.23.0': + resolution: {integrity: sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.23.0': + resolution: {integrity: sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.23.0': + resolution: {integrity: sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.23.0': + resolution: {integrity: sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.23.0': + resolution: {integrity: sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.23.0': + resolution: {integrity: sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.23.0': + resolution: {integrity: sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.23.0': + resolution: {integrity: sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.23.0': + resolution: {integrity: sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.23.0': + resolution: {integrity: sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.23.0': + resolution: {integrity: sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.23.0': + resolution: {integrity: sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.23.0': + resolution: {integrity: sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.23.0': + resolution: {integrity: sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.23.0': + resolution: {integrity: sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.23.0': + resolution: {integrity: sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.23.0': + resolution: {integrity: sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.23.0': + resolution: {integrity: sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.23.0': + resolution: {integrity: sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.23.0': + resolution: {integrity: sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.23.0': + resolution: {integrity: sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.23.0': + resolution: {integrity: sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.2.0': resolution: {integrity: sha512-gB8T4H4DEfX2IV9zGDJPOBgP1e/DbfCPDTtEqUMckpvzS1OYtva8JdFYBqMwYk7xAQ429WGF/UPqn8uQ//h2vQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -84,8 +234,8 @@ packages: resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.17.1': - resolution: {integrity: sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==} + '@eslint/config-array@0.17.0': + resolution: {integrity: sha512-A68TBu6/1mHHuc5YJL0U0VVeGNiklLAL6rRmhTCP2B5XjWLMnrX+HkO+IAXyHvks5cyyY1jjK5ITPQ1HGS2EVA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/eslintrc@3.1.0': @@ -96,8 +246,8 @@ packages: resolution: {integrity: sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@eslint/js@9.9.0': - resolution: {integrity: sha512-hhetes6ZHP3BlXLxmd8K2SNgkhNSi+UcecbnwWKwpP7kyi/uC75DJ1lOOBO3xrC4jyojtGE3YxKZPHfk4yrgug==} + '@eslint/js@9.7.0': + resolution: {integrity: sha512-ChuWDQenef8OSFnvuxv0TCVxEwmu3+hPNKvM9B34qpM0rDRbjL8t5QkQeHHeAfsKQjuH9wS82WeCi1J/owatng==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.4': @@ -153,8 +303,8 @@ packages: '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - '@types/node@18.11.13': - resolution: {integrity: sha512-IASpMGVcWpUsx5xBOrxMj7Bl8lqfuTY7FKAnPmu5cHkfQVWF8GulWS1jbRqA934qZL35xh5xN/+Xe/i26Bod4w==} + '@types/node@22.3.0': + resolution: {integrity: sha512-nrWpWVaDZuaVc5X84xJ0vNrLvomM205oQyLsRt7OHNZbSHslcWsvgFR7O7hire2ZonjLrWBbedmotmIlJDVd6g==} '@types/ws@8.5.10': resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} @@ -163,9 +313,6 @@ packages: resolution: {integrity: sha512-ButUPz9E9cXMLgvAW8aLAKKJJsPu1dY1/l/E8xzLFuysowXygs6GBcyunK9rnGC4zTsnIc2mQo71rGw9U+Ykug==} engines: {node: '>=v14.0.0', npm: '>=7.0.0'} - abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -191,10 +338,6 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -232,10 +375,6 @@ packages: resolution: {integrity: sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==} engines: {node: '>=0.6'} - binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} - engines: {node: '>=8'} - bplist-parser@0.2.0: resolution: {integrity: sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==} engines: {node: '>= 5.10.0'} @@ -266,10 +405,6 @@ packages: resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - chokidar@3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} - color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -350,6 +485,11 @@ packages: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} + esbuild@0.23.0: + resolution: {integrity: sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==} + engines: {node: '>=18'} + hasBin: true + escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -414,15 +554,10 @@ packages: resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.9.0: - resolution: {integrity: sha512-JfiKJrbx0506OEerjK2Y1QlldtBxkAlLxT5OEcRF8uaQ86noDe2k31Vw9rnSWv+MXZHj7OOUV/dA0AhdLFcyvA==} + eslint@9.7.0: + resolution: {integrity: sha512-FzJ9D/0nGiCGBf8UXO/IGLTgLVzIxze1zpfA8Ton2mjLovXdAPlYDv+MQDcqj3TmrhAGYfOpz9RfR+ent0AgAw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true - peerDependencies: - jiti: '*' - peerDependenciesMeta: - jiti: - optional: true espree@10.1.0: resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==} @@ -519,6 +654,9 @@ packages: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} engines: {node: '>= 0.4'} + get-tsconfig@4.7.6: + resolution: {integrity: sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -545,10 +683,6 @@ packages: has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -584,9 +718,6 @@ packages: resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} engines: {node: '>=14.18.0'} - ignore-by-default@1.0.1: - resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} - ignore@5.2.4: resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} engines: {node: '>= 4'} @@ -609,10 +740,6 @@ packages: is-bigint@1.0.4: resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - is-boolean-object@1.1.2: resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} engines: {node: '>= 0.4'} @@ -744,10 +871,6 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - magic-bytes.js@1.10.0: resolution: {integrity: sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==} @@ -782,19 +905,6 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - nodemon@3.1.4: - resolution: {integrity: sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==} - engines: {node: '>=10'} - hasBin: true - - nopt@1.0.10: - resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==} - hasBin: true - - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - npm-run-path@4.0.1: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} @@ -888,9 +998,6 @@ packages: engines: {node: '>=14'} hasBin: true - pstree.remy@1.1.8: - resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} - punycode@2.3.0: resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} engines: {node: '>=6'} @@ -898,10 +1005,6 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - regexp.prototype.flags@1.5.0: resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==} engines: {node: '>= 0.4'} @@ -910,6 +1013,9 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve@1.22.8: resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} hasBin: true @@ -936,11 +1042,6 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} - engines: {node: '>=10'} - hasBin: true - shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -955,10 +1056,6 @@ packages: signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - simple-update-notifier@2.0.0: - resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} - engines: {node: '>=10'} - string.prototype.trim@1.2.7: resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} engines: {node: '>= 0.4'} @@ -993,10 +1090,6 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -1026,10 +1119,6 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - touch@3.1.0: - resolution: {integrity: sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==} - hasBin: true - ts-mixer@6.0.4: resolution: {integrity: sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==} @@ -1039,6 +1128,11 @@ packages: tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + tsx@4.17.0: + resolution: {integrity: sha512-eN4mnDA5UMKDt4YZixo9tBioibaMBpoxBkD+rIPAjVmYERSG0/dWEY1CEFuV89CgASlKL499q8AhmkMnnjtOJg==} + engines: {node: '>=18.0.0'} + hasBin: true + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -1062,11 +1156,16 @@ packages: typed-array-length@1.0.4: resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + typescript@5.5.4: + resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} + engines: {node: '>=14.17'} + hasBin: true + unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - undefsafe@2.0.5: - resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} + undici-types@6.18.2: + resolution: {integrity: sha512-5ruQbENj95yDYJNS3TvcaxPMshV7aizdv/hWYjGIKoANWKjhWNBsr2YEuYZKodQulB1b8l7ILOuDQep3afowQQ==} undici@6.13.0: resolution: {integrity: sha512-Q2rtqmZWrbP8nePMq7mOJIN98M0fYvSgV89vwl/BQRT4mDOeY2GXZngfGpcBBhtky3woM7G24wZV3Q304Bv6cw==} @@ -1103,9 +1202,6 @@ packages: utf-8-validate: optional: true - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -1161,17 +1257,89 @@ snapshots: - bufferutil - utf-8-validate - '@eslint-community/eslint-utils@4.2.0(eslint@9.9.0)': + '@esbuild/aix-ppc64@0.23.0': + optional: true + + '@esbuild/android-arm64@0.23.0': + optional: true + + '@esbuild/android-arm@0.23.0': + optional: true + + '@esbuild/android-x64@0.23.0': + optional: true + + '@esbuild/darwin-arm64@0.23.0': + optional: true + + '@esbuild/darwin-x64@0.23.0': + optional: true + + '@esbuild/freebsd-arm64@0.23.0': + optional: true + + '@esbuild/freebsd-x64@0.23.0': + optional: true + + '@esbuild/linux-arm64@0.23.0': + optional: true + + '@esbuild/linux-arm@0.23.0': + optional: true + + '@esbuild/linux-ia32@0.23.0': + optional: true + + '@esbuild/linux-loong64@0.23.0': + optional: true + + '@esbuild/linux-mips64el@0.23.0': + optional: true + + '@esbuild/linux-ppc64@0.23.0': + optional: true + + '@esbuild/linux-riscv64@0.23.0': + optional: true + + '@esbuild/linux-s390x@0.23.0': + optional: true + + '@esbuild/linux-x64@0.23.0': + optional: true + + '@esbuild/netbsd-x64@0.23.0': + optional: true + + '@esbuild/openbsd-arm64@0.23.0': + optional: true + + '@esbuild/openbsd-x64@0.23.0': + optional: true + + '@esbuild/sunos-x64@0.23.0': + optional: true + + '@esbuild/win32-arm64@0.23.0': + optional: true + + '@esbuild/win32-ia32@0.23.0': + optional: true + + '@esbuild/win32-x64@0.23.0': + optional: true + + '@eslint-community/eslint-utils@4.2.0(eslint@9.7.0)': dependencies: - eslint: 9.9.0 + eslint: 9.7.0 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.11.0': {} - '@eslint/config-array@0.17.1': + '@eslint/config-array@0.17.0': dependencies: '@eslint/object-schema': 2.1.4 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -1179,7 +1347,7 @@ snapshots: '@eslint/eslintrc@3.1.0': dependencies: ajv: 6.12.6 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4 espree: 10.1.0 globals: 14.0.0 ignore: 5.2.4 @@ -1192,7 +1360,7 @@ snapshots: '@eslint/js@8.55.0': {} - '@eslint/js@9.9.0': {} + '@eslint/js@9.7.0': {} '@eslint/object-schema@2.1.4': {} @@ -1200,12 +1368,12 @@ snapshots: '@humanwhocodes/retry@0.3.0': {} - '@igorkowalczyk/eslint-config@2.2.0(eslint@9.9.0)(prettier@3.3.3)': + '@igorkowalczyk/eslint-config@2.2.0(eslint@9.7.0)(prettier@3.3.3)': dependencies: '@eslint/js': 8.55.0 - eslint: 9.9.0 - eslint-plugin-import: 2.29.0(eslint@9.9.0) - eslint-plugin-prettier: 5.0.1(eslint@9.9.0)(prettier@3.3.3) + eslint: 9.7.0 + eslint-plugin-import: 2.29.0(eslint@9.7.0) + eslint-plugin-prettier: 5.0.1(eslint@9.7.0)(prettier@3.3.3) globals: 13.23.0 transitivePeerDependencies: - '@types/eslint' @@ -1252,16 +1420,16 @@ snapshots: '@types/json5@0.0.29': {} - '@types/node@18.11.13': {} + '@types/node@22.3.0': + dependencies: + undici-types: 6.18.2 '@types/ws@8.5.10': dependencies: - '@types/node': 18.11.13 + '@types/node': 22.3.0 '@vladfrangu/async_event_emitter@2.2.4': {} - abbrev@1.1.1: {} - acorn-jsx@5.3.2(acorn@8.12.0): dependencies: acorn: 8.12.0 @@ -1283,11 +1451,6 @@ snapshots: dependencies: color-convert: 2.0.1 - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - argparse@2.0.1: {} array-buffer-byte-length@1.0.0: @@ -1340,8 +1503,6 @@ snapshots: big-integer@1.6.51: {} - binary-extensions@2.2.0: {} - bplist-parser@0.2.0: dependencies: big-integer: 1.6.51 @@ -1373,18 +1534,6 @@ snapshots: chalk@5.3.0: {} - chokidar@3.5.3: - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -1403,11 +1552,9 @@ snapshots: dependencies: ms: 2.1.2 - debug@4.3.4(supports-color@5.5.0): + debug@4.3.4: dependencies: ms: 2.1.2 - optionalDependencies: - supports-color: 5.5.0 deep-is@0.1.4: {} @@ -1514,6 +1661,33 @@ snapshots: is-date-object: 1.0.5 is-symbol: 1.0.4 + esbuild@0.23.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.23.0 + '@esbuild/android-arm': 0.23.0 + '@esbuild/android-arm64': 0.23.0 + '@esbuild/android-x64': 0.23.0 + '@esbuild/darwin-arm64': 0.23.0 + '@esbuild/darwin-x64': 0.23.0 + '@esbuild/freebsd-arm64': 0.23.0 + '@esbuild/freebsd-x64': 0.23.0 + '@esbuild/linux-arm': 0.23.0 + '@esbuild/linux-arm64': 0.23.0 + '@esbuild/linux-ia32': 0.23.0 + '@esbuild/linux-loong64': 0.23.0 + '@esbuild/linux-mips64el': 0.23.0 + '@esbuild/linux-ppc64': 0.23.0 + '@esbuild/linux-riscv64': 0.23.0 + '@esbuild/linux-s390x': 0.23.0 + '@esbuild/linux-x64': 0.23.0 + '@esbuild/netbsd-x64': 0.23.0 + '@esbuild/openbsd-arm64': 0.23.0 + '@esbuild/openbsd-x64': 0.23.0 + '@esbuild/sunos-x64': 0.23.0 + '@esbuild/win32-arm64': 0.23.0 + '@esbuild/win32-ia32': 0.23.0 + '@esbuild/win32-x64': 0.23.0 + escape-string-regexp@4.0.0: {} eslint-import-resolver-node@0.3.9: @@ -1524,16 +1698,16 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.8.0(eslint-import-resolver-node@0.3.9)(eslint@9.9.0): + eslint-module-utils@2.8.0(eslint-import-resolver-node@0.3.9)(eslint@9.7.0): dependencies: debug: 3.2.7 optionalDependencies: - eslint: 9.9.0 + eslint: 9.7.0 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-import@2.29.0(eslint@9.9.0): + eslint-plugin-import@2.29.0(eslint@9.7.0): dependencies: array-includes: 3.1.7 array.prototype.findlastindex: 1.2.3 @@ -1541,9 +1715,9 @@ snapshots: array.prototype.flatmap: 1.3.2 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.9.0 + eslint: 9.7.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(eslint-import-resolver-node@0.3.9)(eslint@9.9.0) + eslint-module-utils: 2.8.0(eslint-import-resolver-node@0.3.9)(eslint@9.7.0) hasown: 2.0.0 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -1558,9 +1732,9 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-prettier@5.0.1(eslint@9.9.0)(prettier@3.3.3): + eslint-plugin-prettier@5.0.1(eslint@9.7.0)(prettier@3.3.3): dependencies: - eslint: 9.9.0 + eslint: 9.7.0 prettier: 3.3.3 prettier-linter-helpers: 1.0.0 synckit: 0.8.5 @@ -1574,20 +1748,20 @@ snapshots: eslint-visitor-keys@4.0.0: {} - eslint@9.9.0: + eslint@9.7.0: dependencies: - '@eslint-community/eslint-utils': 4.2.0(eslint@9.9.0) + '@eslint-community/eslint-utils': 4.2.0(eslint@9.7.0) '@eslint-community/regexpp': 4.11.0 - '@eslint/config-array': 0.17.1 + '@eslint/config-array': 0.17.0 '@eslint/eslintrc': 3.1.0 - '@eslint/js': 9.9.0 + '@eslint/js': 9.7.0 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.3.0 '@nodelib/fs.walk': 1.2.8 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4 escape-string-regexp: 4.0.0 eslint-scope: 8.0.2 eslint-visitor-keys: 4.0.0 @@ -1727,6 +1901,10 @@ snapshots: call-bind: 1.0.2 get-intrinsic: 1.2.1 + get-tsconfig@4.7.6: + dependencies: + resolve-pkg-maps: 1.0.0 + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -1751,8 +1929,6 @@ snapshots: has-bigints@1.0.2: {} - has-flag@3.0.0: {} - has-flag@4.0.0: {} has-property-descriptors@1.0.0: @@ -1779,8 +1955,6 @@ snapshots: human-signals@4.3.1: {} - ignore-by-default@1.0.1: {} - ignore@5.2.4: {} import-fresh@3.3.0: @@ -1806,10 +1980,6 @@ snapshots: dependencies: has-bigints: 1.0.2 - is-binary-path@2.1.0: - dependencies: - binary-extensions: 2.2.0 - is-boolean-object@1.1.2: dependencies: call-bind: 1.0.2 @@ -1923,10 +2093,6 @@ snapshots: lodash@4.17.21: {} - lru-cache@6.0.0: - dependencies: - yallist: 4.0.0 - magic-bytes.js@1.10.0: {} merge-stream@2.0.0: {} @@ -1952,25 +2118,6 @@ snapshots: natural-compare@1.4.0: {} - nodemon@3.1.4: - dependencies: - chokidar: 3.5.3 - debug: 4.3.4(supports-color@5.5.0) - ignore-by-default: 1.0.1 - minimatch: 3.1.2 - pstree.remy: 1.1.8 - semver: 7.5.4 - simple-update-notifier: 2.0.0 - supports-color: 5.5.0 - touch: 3.1.0 - undefsafe: 2.0.5 - - nopt@1.0.10: - dependencies: - abbrev: 1.1.1 - - normalize-path@3.0.0: {} - npm-run-path@4.0.1: dependencies: path-key: 3.1.1 @@ -2065,16 +2212,10 @@ snapshots: prettier@3.3.3: {} - pstree.remy@1.1.8: {} - punycode@2.3.0: {} queue-microtask@1.2.3: {} - readdirp@3.6.0: - dependencies: - picomatch: 2.3.1 - regexp.prototype.flags@1.5.0: dependencies: call-bind: 1.0.2 @@ -2083,6 +2224,8 @@ snapshots: resolve-from@4.0.0: {} + resolve-pkg-maps@1.0.0: {} + resolve@1.22.8: dependencies: is-core-module: 2.13.1 @@ -2114,10 +2257,6 @@ snapshots: semver@6.3.1: {} - semver@7.5.4: - dependencies: - lru-cache: 6.0.0 - shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -2132,10 +2271,6 @@ snapshots: signal-exit@3.0.7: {} - simple-update-notifier@2.0.0: - dependencies: - semver: 7.5.4 - string.prototype.trim@1.2.7: dependencies: call-bind: 1.0.2 @@ -2170,10 +2305,6 @@ snapshots: strip-json-comments@3.1.1: {} - supports-color@5.5.0: - dependencies: - has-flag: 3.0.0 - supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -2195,10 +2326,6 @@ snapshots: dependencies: is-number: 7.0.0 - touch@3.1.0: - dependencies: - nopt: 1.0.10 - ts-mixer@6.0.4: {} tsconfig-paths@3.14.2: @@ -2210,6 +2337,13 @@ snapshots: tslib@2.6.2: {} + tsx@4.17.0: + dependencies: + esbuild: 0.23.0 + get-tsconfig: 4.7.6 + optionalDependencies: + fsevents: 2.3.3 + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -2243,6 +2377,8 @@ snapshots: for-each: 0.3.3 is-typed-array: 1.1.10 + typescript@5.5.4: {} + unbox-primitive@1.0.2: dependencies: call-bind: 1.0.2 @@ -2250,7 +2386,7 @@ snapshots: has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 - undefsafe@2.0.5: {} + undici-types@6.18.2: {} undici@6.13.0: {} @@ -2282,6 +2418,4 @@ snapshots: ws@8.17.0: {} - yallist@4.0.0: {} - yocto-queue@0.1.0: {} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..4c73bee --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "lib": ["ESNext", "DOM"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false + } +} diff --git a/utils/chunkString.js b/utils/chunkString.js deleted file mode 100644 index cf89d9a..0000000 --- a/utils/chunkString.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Divide a string into chunks of n characters - * - * @param {string} str String to divide - * @param {number} n Number of characters per chunk - * @param {string[]} acc Array to store the chunks - * @returns {string[]} Array of chunks - */ -export function chunkString(str, n, acc) { - if (str.length === 0) return acc; - - acc.push(str.substring(0, n)); - return chunkString(str.substring(n), n, acc); -} diff --git a/utils/chunkString.ts b/utils/chunkString.ts new file mode 100644 index 0000000..921cde6 --- /dev/null +++ b/utils/chunkString.ts @@ -0,0 +1,6 @@ +export function chunkString(str: string, n: number, acc: string[]): string[] { + if (str.length === 0) return acc; + + acc.push(str.substring(0, n)); + return chunkString(str.substring(n), n, acc); +} diff --git a/utils/execCommand.js b/utils/execCommand.js deleted file mode 100644 index ba929a8..0000000 --- a/utils/execCommand.js +++ /dev/null @@ -1,63 +0,0 @@ -import { once } from "events"; -import { spawn } from "node:child_process"; -import { EmbedBuilder, codeBlock } from "discord.js"; -import stripAnsi from "strip-ansi"; -import { cpuTemperature as checkCpuTemperature, currentLoad, mem } from "systeminformation"; -import { defaultConfig } from "../config.js"; -import { chunkString } from "./chunkString.js"; -import { logger } from "./logger.js"; - -/** - * Executes a command in the terminal. - * - * @param {object} client The Discord client. - * @param {string} input The command to execute. - * @returns {Promise} - */ -export async function execCommand(client, input) { - try { - defaultConfig.debugger.showCommand && logger("event", `Executing command: ${input} in ${client.customCWD}`); - const output = []; - - const { main: cpuTemperature } = await checkCpuTemperature(); - const { currentLoad: cpuUsage } = await currentLoad(); - const memoryTest = await mem(); - const memoryPercentage = ((memoryTest.used / 1048576 / (memoryTest.total / 1048576)) * 100).toFixed(2); - - const args = input.split(" "); - const command = args.shift(); - - const cmd = spawn(`${command}`, args, { - shell: true, - env: { COLUMNS: 128 }, - cwd: client.customCWD, - }); - - cmd.stdout.on("data", (data) => output.push(data)); - cmd.stderr.on("data", (data) => output.push(data)); - - await once(cmd, "exit"); - - const outputDiscord = chunkString(output.join("") || "", 3000, []); - - outputDiscord.forEach((item, index) => { - const index2 = index + 1; - - const embed = new EmbedBuilder() // prettier - .setColor("#4f545c") - .setTitle(`${defaultConfig.emojis.output} Output`) - .setTimestamp() - .setFooter({ text: `Page ${index2}/${outputDiscord.length}`, icon: client.user.displayAvatarURL() }) - .setDescription(codeBlock(stripAnsi(item, true) || "No output!")); - - if (index2 == outputDiscord.length) embed.setDescription(`${embed.data.description}\n${codeBlock(`CWD: ${client.customCWD}\nCPU: ${Math.round(cpuUsage)}% | RAM: ${Math.round(memoryPercentage)}% | Temp: ${Math.round(cpuTemperature)}°C`)}`); - - const finalMessage = defaultConfig.channel.messages.cache.first(); - if (index2 !== 1) defaultConfig.channel.send({ embeds: [embed] }); - - finalMessage.reply({ embeds: [embed] }); - }); - } catch (error) { - console.error(error); - } -} diff --git a/utils/execCommand.ts b/utils/execCommand.ts new file mode 100644 index 0000000..0d4bb28 --- /dev/null +++ b/utils/execCommand.ts @@ -0,0 +1,67 @@ +import { exec } from "node:child_process"; +import { Client, EmbedBuilder, TextChannel, codeBlock } from "discord.js"; +import stripAnsi from "strip-ansi"; +import { cpuTemperature as checkCpuTemperature, currentLoad, mem } from "systeminformation"; +import { defaultConfig } from "../config"; +import { chunkString } from "./chunkString"; +import { logger } from "./logger"; +import { promisify } from "util"; + +const execPromise = promisify(exec); + +async function getSystemInfo() { + const { main: cpuTemperature } = await checkCpuTemperature(); + const { currentLoad: cpuUsage } = await currentLoad(); + const memoryTest = await mem(); + const memoryPercentage = Number(((memoryTest.used / 1048576 / (memoryTest.total / 1048576)) * 100).toFixed(2)); + return { cpuTemperature, cpuUsage, memoryPercentage }; +} + +async function executeCommand(command: string) { + try { + const { stdout, stderr } = await execPromise(command, { + cwd: defaultConfig.cwd, + env: { COLUMNS: "128" }, + }); + return stdout + stderr; + } catch (error) { + return error; + } +} + +export async function execCommand(client: Client, input: string): Promise { + try { + defaultConfig.debugger.showCommand && logger("event", `Executing command: ${input} in ${defaultConfig.cwd}`); + + const { cpuTemperature, cpuUsage, memoryPercentage } = await getSystemInfo(); + const output = (await executeCommand(input)) || "No output!"; + const outputDiscord = chunkString(output.toString() || "", 3000, []); + + outputDiscord.forEach((item, index) => { + const index2 = index + 1; + + const embed = new EmbedBuilder() + .setColor("#4f545c") + .setTitle(`${defaultConfig.emojis.output} Output`) + .setTimestamp() + .setFooter({ text: `Page ${index2}/${outputDiscord.length}`, iconURL: client.user?.displayAvatarURL() }) + .setDescription(codeBlock(stripAnsi(item) || "No output!")); + + if (index2 == outputDiscord.length) { + embed.setDescription(`${embed.data.description}\n${codeBlock(`CWD: ${defaultConfig.cwd}\nCPU: ${Math.round(cpuUsage)}% | RAM: ${Math.round(memoryPercentage)}% | Temp: ${Math.round(cpuTemperature)}°C`)}`); + } + + if (!defaultConfig.channel) return logger("error", "Channel not found! Please check your CHANNEL_ID .env variable."); + const channel = client.channels.cache.get(defaultConfig.channel) as TextChannel; + if (!channel) return logger("error", "Channel not found! Please check your CHANNEL_ID .env variable."); + + const finalMessage = channel.messages.cache.first(); + if (index2 !== 1) channel.send({ embeds: [embed] }); + + if (!finalMessage) return channel.send({ embeds: [embed] }); + finalMessage.reply({ embeds: [embed] }); + }); + } catch (error) { + console.error(error); + } +} diff --git a/utils/loadEvents.js b/utils/loadEvents.ts similarity index 60% rename from utils/loadEvents.js rename to utils/loadEvents.ts index e93dec0..3a17422 100644 --- a/utils/loadEvents.js +++ b/utils/loadEvents.ts @@ -2,24 +2,19 @@ import { readdirSync } from "node:fs"; import { basename } from "node:path"; import { performance } from "node:perf_hooks"; import { pathToFileURL } from "node:url"; -import { defaultConfig } from "../config.js"; -import { logger } from "./logger.js"; +import { defaultConfig } from "../config"; +import { logger } from "./logger"; +import { Client } from "discord.js"; -/** - * Loads all events from the /events folder - * - * @param {object} client - The Discord client - * @returns {Promise} Promise that resolves when all events are loaded - * @throws {Error} Error that is thrown if an event could not be loaded - */ -export default async function loadEvents(client) { +export default async function loadEvents(client: Client): Promise { try { const loadTime = performance.now(); const directories = readdirSync(`${process.cwd()}/events/`); - const events = []; + const events: string[] = []; + for (const directory of directories) { - const files = readdirSync(`${process.cwd()}/events/${directory}`).filter((file) => file.endsWith(".js")); + const files = readdirSync(`${process.cwd()}/events/${directory}`).filter((file) => file.endsWith(".ts")); for (const file of files) { events.push(`${process.cwd()}/events/${directory}/${file}`); } @@ -27,8 +22,8 @@ export default async function loadEvents(client) { for (const file of events) { const fileURL = pathToFileURL(file); - await import(fileURL).then((e) => { - const eventName = basename(file, ".js"); + await import(fileURL.toString()).then((e) => { + const eventName = basename(file, ".ts"); defaultConfig.debugger.displayEventList && logger("event", `Loaded event ${eventName} from ${file.replace(process.cwd(), "")}`); client.on(eventName, e[eventName].bind(null, client)); }); @@ -36,6 +31,6 @@ export default async function loadEvents(client) { logger("event", `Loaded ${events.length} events from /events in ${Math.round(performance.now() - loadTime)}ms`); } catch (error) { - logger("error", `Error loading events: ${error.message}`); + logger("error", `Error loading events: ${error}`); } } diff --git a/utils/logger.js b/utils/logger.js deleted file mode 100644 index 1b86a9f..0000000 --- a/utils/logger.js +++ /dev/null @@ -1,23 +0,0 @@ -import chalk from "chalk"; - -const colors = { - info: "cyan", - event: "magenta", - error: "red", - warn: "yellow", - ready: "green", - cron: "blue", -}; - -const types = ["info", "event", "error", "warn", "ready", "cron"]; -const longest = types.reduce((long, str) => Math.max(long, str.length), 0); - -/** - * Logs a message to the console with a colored log type. - * - * @param {"info" | "event" | "error" | "warn" | "ready" | "cron" } type - The type of log. - * @param {...string} args - The message to log. - */ -export function logger(type, ...args) { - console.log(chalk[colors[type] || "white"](type + " ".repeat(longest - type.length)) + chalk.white(" - " + args.join(" "))); -} diff --git a/utils/logger.ts b/utils/logger.ts new file mode 100644 index 0000000..dc662bf --- /dev/null +++ b/utils/logger.ts @@ -0,0 +1,18 @@ +import chalk from "chalk"; + +type LogType = "info" | "event" | "error" | "warn" | "ready" | "cron"; + +const colors: Record = { + info: "cyan", + event: "magenta", + error: "red", + warn: "yellow", + ready: "green", + cron: "blue", +}; + +const longest = Math.max(...Object.keys(colors).map((type) => type.length)); + +export function logger(type: LogType, ...args: string[]): void { + console.log(`${(chalk[colors[type]] as Function)(type.padEnd(longest))} - ${chalk.white(args.join(" "))}`); +}