Migration to Postgres 18 fgrom Mongoose.#150
Conversation
…ose & mongodb, added getGuild and setGuild methods, same for users. Deleted old MongoDB schemas.
Axodouble
left a comment
There was a problem hiding this comment.
This will be a faily large change, all autoroles have been manually migrated already, all that still has to be done is a manual test of the data.
There was a problem hiding this comment.
Pull request overview
This PR migrates the bot’s persistence layer away from MongoDB/Mongoose to PostgreSQL using Drizzle ORM, updates affected modules to use the new DB API, and removes several deprecated/unused features/modules. It also updates runtime/build configuration (tsconfig, Docker, compose) to support the new DB stack.
Changes:
- Replace Mongoose/MongoDB usage with Drizzle + PostgreSQL, including new schema and migrations.
- Update economy/server modules (and command handlers) to use the new
client.dbAPI and remove module-usage metrics tracking. - Remove deprecated modules/features (support contact threads, birthdays, giveaways, etc.) and update Docker/compose/env examples accordingly.
Reviewed changes
Copilot reviewed 34 out of 36 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| tsconfig.json | Switch TS module + resolution to ESNext/bundler. |
| src/system/modules/manage.ts | Removes support/metrics implementations; leaves module shell and remaining commands. |
| src/system/backend/events/status.ts | Removes birthday-user status rotation logic. |
| src/system/backend/events/commands/handlers/textCommandHandler.ts | Removes module-usage metrics recording. |
| src/system/backend/events/commands/handlers/slashCommandHandler.ts | Removes module-usage metrics recording. |
| src/system/backend/events/commands/handlers/selectMenuCommandHandler.ts | Removes module-usage metrics recording. |
| src/system/backend/events/commands/handlers/modalCommandHandler.ts | Removes module-usage metrics recording. |
| src/system/backend/events/commands/handlers/contextCommandHandler.ts | Removes module-usage metrics recording. |
| src/system/backend/events/commands/handlers/buttonCommandHandler.ts | Removes module-usage metrics recording. |
| src/system/backend/database/schema.ts | Introduces Drizzle PG schema for guild_users and guilds. |
| src/system/backend/database/models/databaseGuildUserSchema.ts | Deletes Mongoose guild-user model. |
| src/system/backend/database/models/databaseGuildSchema.ts | Deletes Mongoose guild model. |
| src/system/backend/database/database.ts | Replaces Mongoose connection with Bun SQL + Drizzle client and CRUD helpers. |
| src/system/backend/classes/gargoyleClient.ts | Removes Mongoose-based module metrics schema/functions. |
| src/modules/utilities/bible.ts | Minor formatting change. |
| src/modules/server/server.ts | Migrates guild autoroles persistence to new DB API and adds permission checks. |
| src/modules/server/crustacean.ts | Removes deprecated module. |
| src/modules/fun/homunculus.ts | Removes module. |
| src/modules/fun/giveaway.ts | Removes deprecated module. |
| src/modules/fun/economy.ts | Migrates economy persistence to guild-scoped DB rows via new DB API. |
| src/modules/fun/birthday.ts | Removes deprecated module. |
| src/modules/cc/ceraia.ts | Removes module. |
| src/modules/bgn/minecraft.ts | Removes module. |
| src/modules/bgn/bgn.ts | Removes stocks + mongoose-backed features from the BGN module. |
| package.json | Adds Drizzle/PG deps + drizzle-kit scripts; removes mongoose dependency. |
| drizzle/meta/0000_snapshot.json | Adds initial Drizzle snapshot metadata. |
| drizzle/meta/0001_snapshot.json | Adds follow-up Drizzle snapshot metadata. |
| drizzle/meta/_journal.json | Adds Drizzle migration journal. |
| drizzle/0000_cloudy_paibok.sql | Adds initial SQL migration for new tables/indexes. |
| drizzle/0001_curvy_microchip.sql | Adds migration for economy fields (lastdaily, dailystreak, balance default). |
| drizzle.config.ts | Adds drizzle-kit configuration. |
| docker/prod/Dockerfile | Runs DB migrations before starting the bot. |
| docker/dev/Dockerfile | Runs DB migrations before starting the bot (watch mode). |
| docker-compose-dev.yml | Swaps Mongo service for Postgres and adds PG env vars/volume. |
| .env.example | Replaces Mongo env vars with Postgres env vars. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
…, fixed incorrect typed return values for non existing guilds.
There was a problem hiding this comment.
Pull request overview
Migrates the bot’s persistence layer from MongoDB/Mongoose to PostgreSQL using Drizzle ORM, updating affected modules and deployment configs accordingly, while removing several deprecated/unused features and modules.
Changes:
- Replace Mongoose-based DB layer with a Drizzle + PostgreSQL implementation (new schema, migrations, and accessors).
- Update modules/handlers to use the new DB access methods and remove module-usage metrics tracking.
- Update Docker + env examples to run Postgres and apply Drizzle migrations on startup; remove multiple deprecated modules/features.
Reviewed changes
Copilot reviewed 35 out of 37 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| tsconfig.json | Switch TS module/moduleResolution for bundler workflow |
| src/system/modules/manage.ts | Removes support/metrics logic; events now empty |
| src/system/modules/help.ts | Make guild prefix lookup null-safe |
| src/system/backend/events/status.ts | Removes birthday-user status rotation logic |
| src/system/backend/events/commands/handlers/textCommandHandler.ts | Removes module usage recording call |
| src/system/backend/events/commands/handlers/slashCommandHandler.ts | Removes module usage recording call |
| src/system/backend/events/commands/handlers/selectMenuCommandHandler.ts | Removes module usage recording call |
| src/system/backend/events/commands/handlers/modalCommandHandler.ts | Removes module usage recording call |
| src/system/backend/events/commands/handlers/contextCommandHandler.ts | Removes module usage recording call |
| src/system/backend/events/commands/handlers/buttonCommandHandler.ts | Removes module usage recording call |
| src/system/backend/database/schema.ts | Introduces Drizzle PG schema for guilds/users |
| src/system/backend/database/models/databaseGuildUserSchema.ts | Deletes Mongoose guild-user model |
| src/system/backend/database/models/databaseGuildSchema.ts | Deletes Mongoose guild model |
| src/system/backend/database/database.ts | New Postgres/Drizzle DB client + CRUD helpers |
| src/system/backend/classes/gargoyleClient.ts | Removes Mongoose metrics schema + tracking util |
| src/modules/utilities/bible.ts | Minor formatting change |
| src/modules/server/server.ts | Update autoroles persistence to new DB layer + permission checks |
| src/modules/server/crustacean.ts | Removes deprecated crustacean module |
| src/modules/fun/homunculus.ts | Removes deprecated homunculus module |
| src/modules/fun/giveaway.ts | Removes deprecated giveaway module |
| src/modules/fun/economy.ts | Port economy persistence to guild-scoped Postgres table |
| src/modules/fun/birthday.ts | Removes deprecated birthday module |
| src/modules/cc/ceraia.ts | Removes ceraia module (Mongoose-backed) |
| src/modules/bgn/minecraft.ts | Removes minecraft module (Mongoose-backed) |
| src/modules/bgn/bgn.ts | Removes BGN stocks feature and related DB usage |
| package.json | Add drizzle/pg tooling; remove mongoose |
| drizzle/meta/0001_snapshot.json | Drizzle snapshot update for schema evolution |
| drizzle/meta/0000_snapshot.json | Initial Drizzle snapshot |
| drizzle/meta/_journal.json | Drizzle migration journal entries |
| drizzle/0001_curvy_microchip.sql | Migration adding daily fields/defaults |
| drizzle/0000_cloudy_paibok.sql | Initial migration creating guilds/guild_users tables |
| drizzle.config.ts | Adds drizzle-kit configuration for PG |
| docker/prod/Dockerfile | Runs db:migrate before starting app |
| docker/dev/Dockerfile | Runs db:migrate before starting app (watch mode) |
| docker-compose-dev.yml | Replace Mongo service with Postgres service |
| .env.example | Replace Mongo env vars with Postgres env vars |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| if (user) { | ||
| await interaction.reply({ content: `User: ${user.tag}\nID: ${user.id}`, flags: [MessageFlags.Ephemeral] }); | ||
| } | ||
| } else if (interaction.options.getSubcommand() === 'contact') { | ||
| if (!client.db) { | ||
| await interaction.reply({ content: 'Database not initialized.', flags: [MessageFlags.Ephemeral] }); | ||
| return; | ||
| } | ||
| const userId = interaction.options.getString('id', true); | ||
| await interaction.deferReply({ flags: [MessageFlags.Ephemeral] }); | ||
|
|
||
| const existingMessage = await hasSupportMessage(client, userId); | ||
| if (existingMessage) { | ||
| await interaction.editReply({ | ||
| content: `There is already an open support message with this user: <https://discord.com/channels/${existingMessage.guildId}/${existingMessage.channelId}/${existingMessage.id}>` | ||
| }); | ||
| return; | ||
| } | ||
|
|
||
| const user = await client.users.fetch(userId).catch(async (err) => { | ||
| await interaction.editReply({ content: `Error trying to find user: \`${err.message}\`` }); | ||
| return; | ||
| }); | ||
|
|
||
| if (!user) return; | ||
|
|
||
| const dm = await user.createDM().catch(async (err) => { | ||
| await interaction.editReply({ content: `Error trying to create DM with user: \`${err.message}\`` }); | ||
| return; | ||
| }); | ||
|
|
||
| if (!dm) return; | ||
|
|
||
| const message = await this.createSupportMessage(client, interaction.channel as TextChannel, user); | ||
|
|
||
| if (!message) { | ||
| await interaction.editReply({ content: 'Failed to create support message.' }); | ||
| return; | ||
| } | ||
|
|
||
| await interaction.editReply({ | ||
| content: `[Support thread](https://discord.com/channels/${message.channelId}/${message.id}) created successfully.` | ||
| }); | ||
| } | ||
| } else if (interaction.options.getSubcommand() === 'metrics') { | ||
| const metrics = await databaseClientMetrics.findOne({ clientId: client.user?.id! }); | ||
| if (!metrics) { | ||
| await interaction.reply({ content: 'No metrics found.', flags: [MessageFlags.Ephemeral] }); | ||
| return; | ||
| } | ||
|
|
||
| let metricsMessage = 'Module Usage Metrics:\n'; | ||
| for (const moduleMetric of metrics.modules) { | ||
| metricsMessage += `Module: ${moduleMetric.moduleName} - Used: ${moduleMetric.used} times\n`; | ||
| } | ||
|
|
||
| if (metricsMessage.length > 2000) { | ||
| const buffer = Buffer.from(metricsMessage, 'utf-8'); | ||
| await interaction.reply({ | ||
| content: 'Metrics are too long, sending as a file.', | ||
| files: [{ attachment: buffer, name: 'metrics.txt' }], | ||
| flags: [MessageFlags.Ephemeral] | ||
| }); | ||
| } else { | ||
| await interaction.reply({ content: metricsMessage, flags: [MessageFlags.Ephemeral] }); | ||
| } | ||
| } |
| public event = Events.ClientReady as const; | ||
| override once = true; | ||
| private birthdayUsers: User[] = []; | ||
| private hasShownBirthdayMessage = false; |
…ique per guild, removed redundant user declaration, and updated user encoding and password encoding
No description provided.