diff --git a/packages/api/package.json b/packages/api/package.json index 2e96d68b7..6056e18ea 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -12,7 +12,10 @@ "types": "./dist/env.d.ts", "default": "./src/env.ts" }, - "./minio/minio-client": "./src/minio/minio-client.ts", + "./minio/minio-client": { + "types": "./dist/minio/minio-client.d.ts", + "default": "./src/minio/minio-client.ts" + }, "./utils": { "types": "./dist/utils.d.ts", "default": "./src/utils.ts" diff --git a/packages/db/package.json b/packages/db/package.json index 24b4268d1..52cd02434 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -33,7 +33,6 @@ "dependencies": { "@forge/consts": "workspace:*", "@t3-oss/env-core": "^0.13.10", - "drizzle-orm": "^0.45.1", "drizzle-zod": "^0.8.3", "minimatch": "^10.2.4", "pg": "^8.19.0", diff --git a/packages/db/scripts/seed_devdb.ts b/packages/db/scripts/seed_devdb.ts index 56b5566ab..eb54dd4a9 100644 --- a/packages/db/scripts/seed_devdb.ts +++ b/packages/db/scripts/seed_devdb.ts @@ -15,25 +15,21 @@ // I probably messed a lot up :D. See get_prod_db.ts for how to get prod data // into your local db for deving. -// TODO: look into moving into a separate area so we don't have to do the BS -// that we do with `../../api` and `../../utils` - import { exec } from "child_process"; import { unlink } from "fs/promises"; import { promisify } from "util"; import type { NodePgDatabase } from "drizzle-orm/node-postgres"; import type { Client } from "pg"; +import { REST } from "@discordjs/rest"; import { Routes } from "discord-api-types/v10"; import { sql } from "drizzle-orm"; import { drizzle } from "drizzle-orm/node-postgres"; +import { Client as MinioClient } from "minio"; import Pool from "pg-pool"; import { stringify } from "superjson"; import { DISCORD, MINIO } from "@forge/consts"; -// Scripts can use relative imports to avoid circular dependencies -import { minioClient } from "../../api/src/minio/minio-client"; -import * as discord from "../../utils/src/discord"; import { env } from "../src/env"; import * as authSchema from "../src/schemas/auth"; import * as knightHacksSchema from "../src/schemas/knight-hacks"; @@ -41,6 +37,35 @@ import * as knightHacksSchema from "../src/schemas/knight-hacks"; const execAsync = promisify(exec); console.log("Starting seeding script"); +function requireEnvVar(name: string): string { + /* eslint-disable no-restricted-properties */ + const value = process.env[name]; + /* eslint-enable no-restricted-properties */ + if (!value) { + throw new Error(`Missing required env var: ${name}`); + } + return value; +} + +const requiredEnv = { + DISCORD_BOT_TOKEN: requireEnvVar("DISCORD_BOT_TOKEN"), + MINIO_ENDPOINT: requireEnvVar("MINIO_ENDPOINT"), + MINIO_ACCESS_KEY: requireEnvVar("MINIO_ACCESS_KEY"), + MINIO_SECRET_KEY: requireEnvVar("MINIO_SECRET_KEY"), +}; + +const discordApi = new REST({ version: "10" }).setToken( + requiredEnv.DISCORD_BOT_TOKEN, +); + +const minioClient = new MinioClient({ + endPoint: requiredEnv.MINIO_ENDPOINT, + port: 443, + useSSL: true, + accessKey: requiredEnv.MINIO_ACCESS_KEY, + secretKey: requiredEnv.MINIO_SECRET_KEY, +}); + type AuthSchema = typeof authSchema; type KnightHacksSchema = typeof knightHacksSchema; type DatabaseSchema = AuthSchema & KnightHacksSchema; @@ -243,12 +268,12 @@ async function syncRoles() { await backupDb.query.Roles.findMany({ columns: { discordRoleId: true } }) ).map((row) => row.discordRoleId), ); - let prodRoles = (await discord.api.get( + let prodRoles = (await discordApi.get( Routes.guildRoles(DISCORD.PROD_KNIGHTHACKS_GUILD), )) as DiscordRole[]; prodRoles = prodRoles.filter((role) => prodRolesWithPerms.has(role.id)); - const devRolesArr = (await discord.api.get( + const devRolesArr = (await discordApi.get( Routes.guildRoles(DISCORD.DEV_KNIGHTHACKS_GUILD), )) as DiscordRole[]; const devRoles = Object.fromEntries( @@ -261,7 +286,7 @@ async function syncRoles() { roleIdMappings[role.id] = devRoles[hash].id; } else { await new Promise((resolve) => setTimeout(resolve, 100)); - const newRole = (await discord.api.post( + const newRole = (await discordApi.post( Routes.guildRoles(DISCORD.DEV_KNIGHTHACKS_GUILD), { body: { @@ -300,14 +325,46 @@ interface DiscordGuildScheduledEvent { image?: string | null; } +async function logDiscord({ + title, + message, + color, + userId, +}: { + title: string; + message: string; + color: "tk_blue" | "blade_purple" | "uhoh_red" | "success_green"; + userId: string; +}) { + await discordApi.post(Routes.channelMessages(DISCORD.LOG_CHANNEL), { + body: { + embeds: [ + { + title, + description: message + `\n\nUser: <@${userId}>`, + color: { + tk_blue: 0x1a73e8, + blade_purple: 0xcca4f4, + uhoh_red: 0xff0000, + success_green: 0x00ff00, + }[color], + footer: { + text: new Date().toLocaleString(), + }, + }, + ], + }, + }); +} + async function syncEvents() { if (!backupDb) return; - const prodEvents = (await discord.api.get( + const prodEvents = (await discordApi.get( Routes.guildScheduledEvents(DISCORD.PROD_KNIGHTHACKS_GUILD), )) as DiscordGuildScheduledEvent[]; - const devEventsArr = (await discord.api.get( + const devEventsArr = (await discordApi.get( Routes.guildScheduledEvents(DISCORD.DEV_KNIGHTHACKS_GUILD), )) as DiscordGuildScheduledEvent[]; const devEvents = Object.fromEntries( @@ -320,7 +377,7 @@ async function syncEvents() { eventIdMappings[event.id] = devEvents[hash].id; } else { await new Promise((resolve) => setTimeout(resolve, 100)); - const newEvent = (await discord.api.post( + const newEvent = (await discordApi.post( Routes.guildScheduledEvents(DISCORD.DEV_KNIGHTHACKS_GUILD), { body: { @@ -430,7 +487,7 @@ async function main() { console.log("Cleaning up backup db"); await cleanUp(); - await discord.log({ + await logDiscord({ title: `Successfully saved limited prod db to minio`, message: `Successfully saved limited prod db to minio. Run the get_prod_db.ts script to get it into your local dev db.`, color: "success_green", @@ -440,9 +497,9 @@ async function main() { process.exit(0); } catch (error) { console.error("Error during database seeding:", error); - await discord.log({ + await logDiscord({ title: `Failed to save limited prod db to minio`, - message: `Failed to sav limited prod db to minio. Error: ${stringify(error)}`, + message: `Failed to save limited prod db to minio. Error: ${stringify(error)}`, color: "uhoh_red", userId: "Host", }); diff --git a/packages/utils/package.json b/packages/utils/package.json index 1806eb329..e83d6bd5b 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -5,7 +5,10 @@ "type": "module", "exports": { ".": "./src/index.ts", - "./discord": "./src/discord.ts", + "./discord": { + "types": "./dist/discord.d.ts", + "default": "./src/discord.ts" + }, "./forms": "./src/forms.ts", "./forms.client": "./src/forms.client.ts", "./google": "./src/google.ts", diff --git a/packages/utils/src/discord.ts b/packages/utils/src/discord.ts index 0e502280b..487f6b6dd 100644 --- a/packages/utils/src/discord.ts +++ b/packages/utils/src/discord.ts @@ -9,11 +9,10 @@ import { Routes } from "discord-api-types/v10"; import { and, desc, eq } from "drizzle-orm"; import type { Session } from "@forge/auth/server"; -import { DISCORD } from "@forge/consts"; +import { DISCORD, TEAM } from "@forge/consts"; import { db } from "@forge/db/client"; import { Account } from "@forge/db/schemas/auth"; -import { TEAMS } from "../../consts/src/team"; import { env } from "./env"; import { logger } from "./logger"; @@ -29,7 +28,7 @@ export async function sendRecruitingApplication( gradYear: string; }, ) { - const team = TEAMS.find((x) => x.team === teamName); + const team = TEAM.TEAMS.find((x) => x.team === teamName); if (!team) { throw new Error("Team not found"); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4d3256b82..aea295985 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -141,7 +141,7 @@ importers: version: 10.0.2(jiti@2.6.1) eslint-config-next: specifier: ^16.0.0 - version: 16.1.6(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) + version: 16.1.6(@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) postcss: specifier: ^8.5.6 version: 8.5.6 @@ -243,7 +243,7 @@ importers: version: 6.6.0 geist: specifier: ^1.7.0 - version: 1.7.0(next@16.1.6(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)) + version: 1.7.0(next@16.1.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4)) google-auth-library: specifier: ^10.6.1 version: 10.6.1 @@ -370,7 +370,7 @@ importers: version: 12.34.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4) geist: specifier: ^1.7.0 - version: 1.7.0(next@16.1.6(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)) + version: 1.7.0(next@16.1.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4)) gsap: specifier: ^3.14.2 version: 3.14.2 @@ -552,7 +552,7 @@ importers: version: 12.34.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4) geist: specifier: ^1.7.0 - version: 1.7.0(next@16.1.6(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)) + version: 1.7.0(next@16.1.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4)) gsap: specifier: ^3.14.2 version: 3.14.2 @@ -646,7 +646,7 @@ importers: version: 12.34.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4) geist: specifier: ^1.7.0 - version: 1.7.0(next@16.1.6(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)) + version: 1.7.0(next@16.1.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4)) gsap: specifier: ^3.14.2 version: 3.14.2 @@ -958,9 +958,6 @@ importers: '@t3-oss/env-core': specifier: ^0.13.10 version: 0.13.10(typescript@5.9.3)(zod@4.3.6) - drizzle-orm: - specifier: ^0.45.1 - version: 0.45.1(@libsql/client-wasm@0.17.0)(@types/pg@8.16.0)(kysely@0.28.11)(pg@8.19.0)(postgres@3.4.8) drizzle-zod: specifier: ^0.8.3 version: 0.8.3(drizzle-orm@0.45.1(@libsql/client-wasm@0.17.0)(@types/pg@8.16.0)(kysely@0.28.11)(pg@8.19.0)(postgres@3.4.8))(zod@4.3.6) @@ -1271,7 +1268,7 @@ importers: version: 16.1.6 eslint-plugin-import: specifier: ^2.32.0 - version: 2.32.0(@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.2(jiti@2.6.1)) + version: 2.32.0(eslint@10.0.2(jiti@2.6.1)) eslint-plugin-jsx-a11y: specifier: ^6.10.2 version: 6.10.2(eslint@10.0.2(jiti@2.6.1)) @@ -13050,13 +13047,13 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-next@16.1.6(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3): + eslint-config-next@16.1.6(@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3): dependencies: '@next/eslint-plugin-next': 16.1.6 eslint: 10.0.2(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(eslint@10.0.2(jiti@2.6.1)))(eslint@10.0.2(jiti@2.6.1)) - eslint-plugin-import: 2.32.0(eslint-import-resolver-typescript@3.10.1)(eslint@10.0.2(jiti@2.6.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@10.0.2(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@10.0.2(jiti@2.6.1)) eslint-plugin-jsx-a11y: 6.10.2(eslint@10.0.2(jiti@2.6.1)) eslint-plugin-react: 7.37.5(eslint@10.0.2(jiti@2.6.1)) eslint-plugin-react-hooks: 7.0.1(eslint@10.0.2(jiti@2.6.1)) @@ -13078,7 +13075,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@10.0.2(jiti@2.6.1)))(eslint@10.0.2(jiti@2.6.1)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@10.0.2(jiti@2.6.1)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.3 @@ -13089,31 +13086,22 @@ snapshots: tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(eslint-import-resolver-typescript@3.10.1)(eslint@10.0.2(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@10.0.2(jiti@2.6.1)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@10.0.2(jiti@2.6.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@10.0.2(jiti@2.6.1)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) eslint: 10.0.2(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@10.0.2(jiti@2.6.1)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@10.0.2(jiti@2.6.1)))(eslint@10.0.2(jiti@2.6.1)))(eslint@10.0.2(jiti@2.6.1)): - dependencies: - debug: 3.2.7 - optionalDependencies: - eslint: 10.0.2(jiti@2.6.1) - eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(eslint@10.0.2(jiti@2.6.1)))(eslint@10.0.2(jiti@2.6.1)) - transitivePeerDependencies: - - supports-color - - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.2(jiti@2.6.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@10.0.2(jiti@2.6.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -13124,7 +13112,7 @@ snapshots: doctrine: 2.1.0 eslint: 10.0.2(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@10.0.2(jiti@2.6.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@10.0.2(jiti@2.6.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -13142,7 +13130,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.32.0(eslint-import-resolver-typescript@3.10.1)(eslint@10.0.2(jiti@2.6.1)): + eslint-plugin-import@2.32.0(eslint@10.0.2(jiti@2.6.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -13153,7 +13141,7 @@ snapshots: doctrine: 2.1.0 eslint: 10.0.2(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@10.0.2(jiti@2.6.1)))(eslint@10.0.2(jiti@2.6.1)))(eslint@10.0.2(jiti@2.6.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@10.0.2(jiti@2.6.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -13462,7 +13450,7 @@ snapshots: transitivePeerDependencies: - supports-color - geist@1.7.0(next@16.1.6(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)): + geist@1.7.0(next@16.1.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4)): dependencies: next: 16.1.6(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)