diff --git a/.dockerignore b/.dockerignore index 6b1cd91..ba77e8f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,10 +1,7 @@ .git -.nodemon -.vscode dev dist node_modules -scripts .dockerignore .env .env.example diff --git a/.swcrc b/.swcrc deleted file mode 100644 index a2c9065..0000000 --- a/.swcrc +++ /dev/null @@ -1,33 +0,0 @@ -{ - "$schema": "https://swc.rs/schema.json", - "jsc": { - "parser": { - "syntax": "typescript", - "tsx": false, - "dynamicImport": true, - "decorators": false - }, - "target": "es2022", - "loose": false, - "externalHelpers": false, - "keepClassNames": false, - "preserveAllComments": false, - "baseUrl": "./", - "paths": { - "~/utils/*": ["src/utils/*"], - "~/config/*": ["src/config/*"], - "~/typings": ["src/typings/index"] - } - }, - "module": { - "type": "es6", - "strict": true, - "strictMode": true, - "noInterop": false, - "lazy": false, - "ignoreDynamic": true, - "resolveFully": true - }, - "minify": false, - "sourceMaps": false -} diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index bd0b3e4..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Attach to process (nvim)", - "type": "pwa-node", - "request": "attach", - "port": 9229, - "skipFiles": [ - "/**", - "${workspaceFolder}/node_modules/**" - ] - }, - { - "name": "Attach to process (vscode)", - "type": "node", - "request": "attach", - "port": 9229, - "skipFiles": [ - "/**", - "${workspaceFolder}/node_modules/**" - ] - } - ] -} diff --git a/Dockerfile b/Dockerfile index 358aca5..829dbf8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,17 @@ -FROM oven/bun +FROM oven/bun AS build WORKDIR /app COPY package.json bun.lock . -RUN bun install --production --frozen-lockfile +RUN bun install --frozen-lockfile COPY . . -ENV NODE_ENV prod +ENV NODE_ENV=prod +RUN bun bundle -CMD ["bun", "run", "start"] +FROM oven/bun + +WORKDIR /app +COPY --from=build /app/dist /app + +CMD ["bun", "run", "index.js"] diff --git a/docker-compose.yml b/docker-compose.yml index 74dfefb..f49f861 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,9 +10,13 @@ services: - HYPIXELAPIKEY=${HYPIXELAPIKEY} - REDISURI=${REDISURI} - POSTGRESURI=${POSTGRESURI} + - PG_USER=${PG_USER} + - PG_PASSWORD=${PG_PASSWORD} + - PG_HOST=${PG_HOST} + - PG_PORT=${PG_PORT} + - PG_DATABASE=${PG_DATABASE} depends_on: - db - pull_policy: always db: container_name: illegitimate-postgres image: postgres:16.4 @@ -22,6 +26,6 @@ services: ports: - 127.0.0.1:5432:5432 environment: - - POSTGRES_PASSWORD=${PG_PASSWD} + - POSTGRES_PASSWORD=${PG_PASSWORD} - POSTGRES_USER=${PG_USER} - - POSTGRES_DB=illegitimate + - POSTGRES_DB=${PG_DATABASE} diff --git a/package.json b/package.json index 0fdf28a..d91db80 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "homepage": "https://gitlab.com/illegitimate/illegitimate-bot", "scripts": { "start": "bun run --bun src/index.ts", + "bundle": "bun run scripts/build.ts", "dev": "bun run --bun --watch src/index.ts", "fmt": "dprint fmt \"**/*.ts\"", "check": "bun tscheck && bun lint", diff --git a/scripts/build.ts b/scripts/build.ts new file mode 100644 index 0000000..1b6f181 --- /dev/null +++ b/scripts/build.ts @@ -0,0 +1,37 @@ +import fs from "node:fs/promises" + +const normalFiles = await Promise.all([ + fs.readdir("src/commands"), + fs.readdir("src/commands-contextmenu"), + fs.readdir("src/components/autocomplete"), + fs.readdir("src/components/buttons"), + fs.readdir("src/components/modals"), + fs.readdir("src/events/cron") +]) + +const eventFiles = (await fs.readdir("src/events", { recursive: true })).filter(f => f.endsWith(".ts")) + +const files = [ + normalFiles[0].map(f => `src/commands/${f}`), + normalFiles[1].map(f => `src/commands-contextmenu/${f}`), + normalFiles[2].map(f => `src/components/autocomplete/${f}`), + normalFiles[3].map(f => `src/components/buttons/${f}`), + normalFiles[4].map(f => `src/components/modals/${f}`), + normalFiles[5].map(f => `src/events/cron/${f}`), + eventFiles.map(f => `src/events/${f}`) +].flat() + +await Bun.build({ + entrypoints: ["src/index.ts", ...files], + outdir: "dist", + target: "bun", + splitting: true, + sourcemap: "external", + naming: { + entry: "[dir]/[name].[ext]", + chunk: "chunk/[name]-[hash].[ext]", + asset: "asset/[name]-[hash].[ext]" + }, + root: "src", + banner: "process.env.BUILD = 'true'" +}) diff --git a/src/utils/Events/autocomplete.ts b/src/utils/Events/autocomplete.ts index 4162de7..9120dac 100644 --- a/src/utils/Events/autocomplete.ts +++ b/src/utils/Events/autocomplete.ts @@ -8,9 +8,9 @@ import logToChannel from "~/utils/Functions/logtochannel" import tryCatch from "../Functions/trycatch" import { log } from "../Logger" -export default async function loadAutocompleteEvents(client: Client) { - const autocompletePath = path.join(import.meta.dirname, "..", "..", "components", "autocomplete") - const autocompleteFiles = fs.readdirSync(autocompletePath).filter(file => file.endsWith(".ts")) +export default async function loadAutocompleteEvents(client: Client, ft: "ts" | "js", folder: "src" | "dist") { + const autocompletePath = path.join(process.cwd(), folder, "components", "autocomplete") + const autocompleteFiles = fs.readdirSync(autocompletePath).filter(file => file.endsWith(`.${ft}`)) for (const file of autocompleteFiles) { const filePath = path.join(autocompletePath, file) diff --git a/src/utils/Events/button.ts b/src/utils/Events/button.ts index af1388d..a8d3971 100644 --- a/src/utils/Events/button.ts +++ b/src/utils/Events/button.ts @@ -8,9 +8,9 @@ import logToChannel from "~/utils/Functions/logtochannel" import tryCatch from "../Functions/trycatch" import { log } from "../Logger" -export default async function loadButtonEvents(client: Client) { - const btnPath = path.join(import.meta.dirname, "..", "..", "components", "buttons") - const btnFiles = fs.readdirSync(btnPath).filter(file => file.endsWith(".ts")) +export default async function loadButtonEvents(client: Client, ft: "ts" | "js", folder: "src" | "dist") { + const btnPath = path.join(process.cwd(), folder, "components", "buttons") + const btnFiles = fs.readdirSync(btnPath).filter(file => file.endsWith(`.${ft}`)) for (const file of btnFiles) { const filePath = path.join(btnPath, file) diff --git a/src/utils/Events/command.ts b/src/utils/Events/command.ts index dd2d717..eb0fbb7 100644 --- a/src/utils/Events/command.ts +++ b/src/utils/Events/command.ts @@ -8,9 +8,9 @@ import logToChannel from "~/utils/Functions/logtochannel" import tryCatch from "../Functions/trycatch" import { log } from "../Logger" -export default async function loadSlashCommandsEvents(client: Client) { - const cmdPath = path.join(import.meta.dirname, "..", "..", "commands") - const cmdFiles = fs.readdirSync(cmdPath).filter(file => file.endsWith(".ts")) +export default async function loadSlashCommandsEvents(client: Client, ft: "ts" | "js", folder: "src" | "dist") { + const cmdPath = path.join(process.cwd(), folder, "commands") + const cmdFiles = fs.readdirSync(cmdPath).filter(file => file.endsWith(`.${ft}`)) for (const file of cmdFiles) { const filePath = path.join(cmdPath, file) diff --git a/src/utils/Events/contextmenu.ts b/src/utils/Events/contextmenu.ts index 21079f6..6066459 100644 --- a/src/utils/Events/contextmenu.ts +++ b/src/utils/Events/contextmenu.ts @@ -8,9 +8,9 @@ import logToChannel from "~/utils/Functions/logtochannel" import tryCatch from "../Functions/trycatch" import { log } from "../Logger" -export default async function loadContextMenuEvents(client: Client) { - const contextMenuPath = path.join(import.meta.dirname, "..", "..", "commands-contextmenu") - const contextMenuFiles = fs.readdirSync(contextMenuPath).filter(file => file.endsWith(".ts")) +export default async function loadContextMenuEvents(client: Client, ft: "ts" | "js", folder: "src" | "dist") { + const contextMenuPath = path.join(process.cwd(), folder, "commands-contextmenu") + const contextMenuFiles = fs.readdirSync(contextMenuPath).filter(file => file.endsWith(`.${ft}`)) for (const file of contextMenuFiles) { const filePath = path.join(contextMenuPath, file) diff --git a/src/utils/Events/cron.ts b/src/utils/Events/cron.ts index 572f3a2..5ee1407 100644 --- a/src/utils/Events/cron.ts +++ b/src/utils/Events/cron.ts @@ -3,9 +3,9 @@ import fs from "fs" import path from "path" import { ICron } from "~/typings" -export default async function loadCronEvents() { - const cronPath = path.join(import.meta.dirname, "..", "..", "events", "cron") - const cronFiles = fs.readdirSync(cronPath).filter(file => file.endsWith(".ts")) +export default async function loadCronEvents(ft: "ts" | "js", folder: "src" | "dist") { + const cronPath = path.join(process.cwd(), folder, "events", "cron") + const cronFiles = fs.readdirSync(cronPath).filter(file => file.endsWith(`.${ft}`)) for (const file of cronFiles) { const filePath = path.join(cronPath, file) diff --git a/src/utils/Events/events.ts b/src/utils/Events/events.ts index 6cf04d7..14cba96 100644 --- a/src/utils/Events/events.ts +++ b/src/utils/Events/events.ts @@ -2,11 +2,11 @@ import fs from "fs" import path from "path" import { ExtendedClient as Client } from "~/utils/Client" -export default async function loadEvents(client: Client) { - const serverDir = path.join(import.meta.dirname, "..", "..", "events", "server") +export default async function loadEvents(client: Client, ft: "ts" | "js", folder: "src" | "dist") { + const serverDir = path.join(process.cwd(), folder, "events", "server") const eventDirs = fs.readdirSync(serverDir) for (const eventDir of eventDirs) { - const eventFiles = fs.readdirSync(path.join(serverDir, eventDir)).filter(file => file.endsWith(".ts")) + const eventFiles = fs.readdirSync(path.join(serverDir, eventDir)).filter(file => file.endsWith(`.${ft}`)) const eventName = eventDir for (const eventFile of eventFiles) { const eventPath = path.join(serverDir, eventDir, eventFile) diff --git a/src/utils/Events/loadevents.ts b/src/utils/Events/loadevents.ts index 51dcd45..86edb6f 100644 --- a/src/utils/Events/loadevents.ts +++ b/src/utils/Events/loadevents.ts @@ -8,12 +8,12 @@ import loadCronEvents from "./cron" import loadEvents from "./events" import loadModalEvents from "./modal" -export default async function loadAllEvents(client: ExtendedClient) { - await loadEvents(client).then(() => log.info("Events loaded")) - await loadButtonEvents(client).then(() => log.info("Button events loaded")) - await loadSlashCommandsEvents(client).then(() => log.info("Slash commands loaded")) - await loadContextMenuEvents(client).then(() => log.info("Context menu events loaded")) - await loadModalEvents(client).then(() => log.info("Modal events loaded")) - await loadAutocompleteEvents(client).then(() => log.info("Autocomplete events loaded")) - await loadCronEvents().then(() => log.info("Cron events loaded")) +export default async function loadAllEvents(client: ExtendedClient, ft: "js" | "ts", folder: "dist" | "src") { + await loadEvents(client, ft, folder).then(() => log.info("Events loaded")) + await loadButtonEvents(client, ft, folder).then(() => log.info("Button events loaded")) + await loadSlashCommandsEvents(client, ft, folder).then(() => log.info("Slash commands loaded")) + await loadContextMenuEvents(client, ft, folder).then(() => log.info("Context menu events loaded")) + await loadModalEvents(client, ft, folder).then(() => log.info("Modal events loaded")) + await loadAutocompleteEvents(client, ft, folder).then(() => log.info("Autocomplete events loaded")) + await loadCronEvents(ft, folder).then(() => log.info("Cron events loaded")) } diff --git a/src/utils/Events/modal.ts b/src/utils/Events/modal.ts index f124d93..804197b 100644 --- a/src/utils/Events/modal.ts +++ b/src/utils/Events/modal.ts @@ -8,9 +8,9 @@ import logToChannel from "~/utils/Functions/logtochannel" import tryCatch from "../Functions/trycatch" import { log } from "../Logger" -export default async function loadModalEvents(client: Client) { - const modalPath = path.join(import.meta.dirname, "..", "..", "components", "modals") - const modalFiles = fs.readdirSync(modalPath).filter(file => file.endsWith(".ts")) +export default async function loadModalEvents(client: Client, ft: "ts" | "js", folder: "src" | "dist") { + const modalPath = path.join(process.cwd(), folder, "components", "modals") + const modalFiles = fs.readdirSync(modalPath).filter(file => file.endsWith(`.${ft}`)) for (const file of modalFiles) { const filePath = path.join(modalPath, file) diff --git a/src/utils/Illegitimate.ts b/src/utils/Illegitimate.ts index a1b00cf..5dbdb04 100644 --- a/src/utils/Illegitimate.ts +++ b/src/utils/Illegitimate.ts @@ -7,9 +7,12 @@ import { log } from "./Logger" const client = new Client() const redis = new RedisClient(env.prod.REDISURI) +const ft = process.env.BUILD !== "true" ? "ts" : "js" +const folder = process.env.BUILD !== "true" ? "src" : "dist" + class Illegitimate { async start() { - await loadAllEvents(client) + await loadAllEvents(client, ft, folder) await client.start() await this.databases() this.loadMethods()