Awesome-omni-skill MongoDB with Mongoose
Database patterns for user data and credentials storage
install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/development/mongodb-with-mongoose" ~/.claude/skills/diegosouzapw-awesome-omni-skill-mongodb-with-mongoose && rm -rf "$T"
manifest:
skills/development/mongodb-with-mongoose/SKILL.mdsource content
MongoDB with Mongoose Skill
This skill covers MongoDB database operations for the autoclaim bot.
Connection Setup
// src/database.ts import mongoose from "mongoose"; export async function connectDatabase() { const uri = process.env.MONGODB_URI; if (!uri) throw new Error("MONGODB_URI not set"); await mongoose.connect(uri); console.log("Connected to MongoDB"); }
User Schema Pattern
// src/models/user.ts import { Schema, model, Document } from "mongoose"; interface IHoyolabCredentials { ltoken: string; ltuid: string; cookieToken?: string; games: string[]; } interface IEndfieldCredentials { skOauthCredKey: string; gameId: string; server: string; } interface IUser extends Document { discordId: string; hoyolab?: IHoyolabCredentials; endfield?: IEndfieldCredentials; settings: { notifications: boolean; autoClaimEnabled: boolean; }; lastClaim?: Date; createdAt: Date; updatedAt: Date; } const userSchema = new Schema<IUser>( { discordId: { type: String, required: true, unique: true, index: true }, hoyolab: { ltoken: { type: String }, ltuid: { type: String }, cookieToken: { type: String }, games: [{ type: String }] }, endfield: { skOauthCredKey: { type: String }, gameId: { type: String }, server: { type: String } }, settings: { notifications: { type: Boolean, default: true }, autoClaimEnabled: { type: Boolean, default: true } }, lastClaim: { type: Date } }, { timestamps: true } ); export const User = model<IUser>("User", userSchema);
Common Operations
Find or Create User
async function findOrCreateUser(discordId: string) { let user = await User.findOne({ discordId }); if (!user) { user = await User.create({ discordId }); } return user; }
Update Credentials
async function updateHoyolabCredentials(discordId: string, credentials: IHoyolabCredentials) { return User.findOneAndUpdate({ discordId }, { $set: { hoyolab: credentials } }, { new: true, upsert: true }); }
Get All Active Users
async function getActiveUsers() { return User.find({ "settings.autoClaimEnabled": true, $or: [{ "hoyolab.ltoken": { $exists: true } }, { "endfield.skOauthCredKey": { $exists: true } }] }); }
Delete User Data
async function deleteUserData(discordId: string) { return User.deleteOne({ discordId }); }
Update Last Claim Time
async function updateLastClaim(discordId: string) { return User.findOneAndUpdate({ discordId }, { $set: { lastClaim: new Date() } }, { new: true }); }
Claim History Schema
const claimHistorySchema = new Schema({ discordId: { type: String, required: true, index: true }, game: { type: String, required: true }, success: { type: Boolean, required: true }, message: { type: String }, rewards: [ { name: String, count: Number, icon: String } ], claimedAt: { type: Date, default: Date.now } }); // Index for efficient queries claimHistorySchema.index({ discordId: 1, claimedAt: -1 }); export const ClaimHistory = model("ClaimHistory", claimHistorySchema);
Best Practices
- Always use indexes for frequently queried fields
- Use
for read-only querieslean() - Handle connection errors gracefully
- Use transactions for multi-document updates
- Never log or expose raw credentials
Security Considerations
// Encrypt sensitive data before storing import crypto from "crypto"; const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY!; function encrypt(text: string): string { const iv = crypto.randomBytes(16); const cipher = crypto.createCipheriv("aes-256-cbc", Buffer.from(ENCRYPTION_KEY, "hex"), iv); let encrypted = cipher.update(text); encrypted = Buffer.concat([encrypted, cipher.final()]); return iv.toString("hex") + ":" + encrypted.toString("hex"); } function decrypt(text: string): string { const parts = text.split(":"); const iv = Buffer.from(parts[0], "hex"); const encrypted = Buffer.from(parts[1], "hex"); const decipher = crypto.createDecipheriv("aes-256-cbc", Buffer.from(ENCRYPTION_KEY, "hex"), iv); let decrypted = decipher.update(encrypted); decrypted = Buffer.concat([decrypted, decipher.final()]); return decrypted.toString(); }