diff --git a/package-lock.json b/package-lock.json index 0e721c0c..902566ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ }, "devDependencies": { "@types/jsonwebtoken": "^8.5.0", + "@types/mongoose-lean-virtuals": "^0.5.1", "@types/node": "^14.14.25", "typescript": "^4.1.3" } @@ -47,6 +48,25 @@ "@types/node": "*" } }, + "node_modules/@types/mongoose": { + "version": "5.10.4", + "resolved": "https://registry.npmjs.org/@types/mongoose/-/mongoose-5.10.4.tgz", + "integrity": "sha512-U7fNDcTcdaSGzQ3+mlSBeebiYr6eaacJi330LTLOEh8Sm6mXfuec70ag/UXkL+alFm7pfAjFqfc7jEaJEJvAHQ==", + "dev": true, + "dependencies": { + "@types/mongodb": "*", + "@types/node": "*" + } + }, + "node_modules/@types/mongoose-lean-virtuals": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@types/mongoose-lean-virtuals/-/mongoose-lean-virtuals-0.5.1.tgz", + "integrity": "sha512-bNk+QLjP5VZU4EsJag4xQsjLAa8CEm/SKZDyiC2kM208wIrGum6daD7j45Oqs50bWNGfqZYRuEhh8xZ17D7aEw==", + "dev": true, + "dependencies": { + "@types/mongoose": "*" + } + }, "node_modules/@types/node": { "version": "14.14.25", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.25.tgz", @@ -1164,6 +1184,25 @@ "@types/node": "*" } }, + "@types/mongoose": { + "version": "5.10.4", + "resolved": "https://registry.npmjs.org/@types/mongoose/-/mongoose-5.10.4.tgz", + "integrity": "sha512-U7fNDcTcdaSGzQ3+mlSBeebiYr6eaacJi330LTLOEh8Sm6mXfuec70ag/UXkL+alFm7pfAjFqfc7jEaJEJvAHQ==", + "dev": true, + "requires": { + "@types/mongodb": "*", + "@types/node": "*" + } + }, + "@types/mongoose-lean-virtuals": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@types/mongoose-lean-virtuals/-/mongoose-lean-virtuals-0.5.1.tgz", + "integrity": "sha512-bNk+QLjP5VZU4EsJag4xQsjLAa8CEm/SKZDyiC2kM208wIrGum6daD7j45Oqs50bWNGfqZYRuEhh8xZ17D7aEw==", + "dev": true, + "requires": { + "@types/mongoose": "*" + } + }, "@types/node": { "version": "14.14.25", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.25.tgz", diff --git a/package.json b/package.json index 7900d301..b92228ff 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ }, "devDependencies": { "@types/jsonwebtoken": "^8.5.0", + "@types/mongoose-lean-virtuals": "^0.5.1", "@types/node": "^14.14.25", "typescript": "^4.1.3" } diff --git a/src/index.ts b/src/index.ts index 914431d8..343a7496 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,6 @@ export * from "./models/index"; export * from "./util/index"; import Config, { DefaultOptions } from "./util/Config"; -import db, { MongooseCache } from "./util/Database"; +import db, { MongooseCache, toObject } from "./util/Database"; -export { Config, db, DefaultOptions, MongooseCache }; +export { Config, db, DefaultOptions, MongooseCache, toObject }; diff --git a/src/models/Message.ts b/src/models/Message.ts index 15f00cf4..ee038f97 100644 --- a/src/models/Message.ts +++ b/src/models/Message.ts @@ -1,8 +1,9 @@ import { Schema, Types, Document } from "mongoose"; import db from "../util/Database"; -import { UserModel } from "./User"; -import { MemberModel } from "./Member"; -import { RoleModel } from "./Role"; +import { PublicUser, UserModel } from "./User"; +import { MemberModel, PublicMember } from "./Member"; +import { Role, RoleModel } from "./Role"; +import { Channel } from "./Channel"; export interface Message { id: string; @@ -36,6 +37,12 @@ export interface Message { channel_id?: string; guild_id?: string; }; + // mongoose virtuals: + author?: PublicUser; + member?: PublicMember; + mentions?: PublicUser[]; + mention_roles?: Role[]; + mention_channels?: Channel[]; } export interface MessageDocument extends Document, Message { @@ -190,50 +197,39 @@ export const Embed = { ], }; -export const MessageSchema = new Schema( - { - id: String, - channel_id: String, - author_id: String, - webhook_id: String, - guild_id: String, - application_id: String, - content: String, - timestamp: Date, - edited_timestamp: Date, - tts: Boolean, - mention_everyone: Boolean, - mention_user_ids: [String], - mention_role_ids: [String], - mention_channel_ids: [String], - attachments: [Attachment], - embeds: [Embed], - reactions: [Reaction], - nonce: Schema.Types.Mixed, // can be a long or a string - pinned: Boolean, - type: { type: Number }, - activity: { - type: Number, - party_id: String, - }, - flags: Types.Long, - stickers: [], - message_reference: { - message_id: String, - channel_id: String, - guild_id: String, - }, +export const MessageSchema = new Schema({ + id: String, + channel_id: String, + author_id: String, + webhook_id: String, + guild_id: String, + application_id: String, + content: String, + timestamp: Date, + edited_timestamp: Date, + tts: Boolean, + mention_everyone: Boolean, + mention_user_ids: [String], + mention_role_ids: [String], + mention_channel_ids: [String], + attachments: [Attachment], + embeds: [Embed], + reactions: [Reaction], + nonce: Schema.Types.Mixed, // can be a long or a string + pinned: Boolean, + type: { type: Number }, + activity: { + type: Number, + party_id: String, }, - { - toJSON: { - transform: function (doc, ret) { - delete ret.mention_channel_ids; - delete ret.mention_user_ids; - delete ret.mention_role_ids; - }, - }, - } -); + flags: Types.Long, + stickers: [], + message_reference: { + message_id: String, + channel_id: String, + guild_id: String, + }, +}); MessageSchema.virtual("author", { ref: UserModel, @@ -270,6 +266,8 @@ MessageSchema.virtual("mention_channels", { justOne: false, }); +MessageSchema.set("removeResponse", ["mention_channel_ids", "mention_role_ids", "mention_user_ids", "author_id"]); + // TODO: missing Application Model // MessageSchema.virtual("application", { // ref: Application, diff --git a/src/models/index.ts b/src/models/index.ts index bb6024fe..03b9fe70 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -1,4 +1,20 @@ import mongoose from "mongoose"; +import { Schema } from "mongoose"; + +mongoose.plugin((schema: Schema, opts: any) => { + schema.set("toObject", { + virtuals: true, + versionKey: false, + transform(doc: any, ret: any) { + delete ret._id; + delete ret.__v; + const props = schema.get("removeResponse") || []; + props.forEach((prop: string) => { + delete ret[prop]; + }); + }, + }); +}); export * from "./Ban"; export * from "./Channel"; @@ -15,14 +31,3 @@ export * from "./Message"; export * from "./Status"; export * from "./VoiceState"; export * from "./Event"; - -mongoose.plugin((schema: any) => { - schema.options.toJSON = { - virtuals: true, - versionKey: false, - transform(doc: any, ret: any) { - delete ret._id; - delete ret.__v; - }, - }; -}); diff --git a/src/util/Database.ts b/src/util/Database.ts index 883c8dcd..e17eeccb 100644 --- a/src/util/Database.ts +++ b/src/util/Database.ts @@ -2,6 +2,7 @@ import "./MongoBigInt"; import mongoose, { Collection, Connection } from "mongoose"; import { ChangeStream, ChangeEvent, Long } from "mongodb"; import EventEmitter from "events"; +import { Document } from "mongoose"; const uri = process.env.MONGO_URL || "mongodb://localhost:27017/fosscord?readPreference=secondaryPreferred"; console.log(`[DB] connect: ${uri}`); @@ -10,6 +11,14 @@ const connection = mongoose.createConnection(uri, { autoIndex: true, useNewUrlPa export default connection; +function transform(document: T) { + return document.toObject({ virtuals: true }); +} + +export function toObject(document: T | T[]) { + return Array.isArray(document) ? document.map((x) => transform(x)) : transform(document); +} + export interface MongooseCache { on(event: "delete", listener: (id: string) => void): this; on(event: "change", listener: (data: any) => void): this;