import { SubscriptionStatusType, AllSubscriptionStatusType, Ref, IPage, IUser, ISubscription, } from '@growi/core'; import { Types, Document, Model, Schema, } from 'mongoose'; import { AllSupportedTargetModels } from '~/interfaces/activity'; import { getOrCreateModel } from '../util/mongoose-utils'; export interface SubscriptionDocument extends ISubscription, Document {} export interface SubscriptionModel extends Model { findByUserIdAndTargetId(userId: Types.ObjectId | string, targetId: Types.ObjectId | string): any upsertSubscription(user: Ref, targetModel: string, target: Ref, status: string): any subscribeByPageId(userId: Types.ObjectId, pageId: Types.ObjectId, status: string): any getSubscription(target: Ref): Promise[]> getUnsubscription(target: Ref): Promise[]> getSubscriptions(targets: Ref[]): Promise[]> } const subscriptionSchema = new Schema({ user: { type: Schema.Types.ObjectId, ref: 'User', index: true, required: true, }, targetModel: { type: String, required: true, enum: AllSupportedTargetModels, }, target: { type: Schema.Types.ObjectId, ref: 'Page', refPath: 'targetModel', required: true, }, status: { type: String, required: true, enum: AllSubscriptionStatusType, }, }, { timestamps: true, }); subscriptionSchema.methods.isSubscribing = function() { return this.status === SubscriptionStatusType.SUBSCRIBE; }; subscriptionSchema.methods.isUnsubscribing = function() { return this.status === SubscriptionStatusType.UNSUBSCRIBE; }; subscriptionSchema.statics.findByUserIdAndTargetId = function(userId, targetId) { return this.findOne({ user: userId, target: targetId }); }; subscriptionSchema.statics.upsertSubscription = function(user, targetModel, target, status) { const query = { user, targetModel, target }; const doc = { ...query, status }; const options = { upsert: true, new: true, setDefaultsOnInsert: true, runValidators: true, }; return this.findOneAndUpdate(query, doc, options); }; subscriptionSchema.statics.subscribeByPageId = function(userId, pageId, status) { return this.upsertSubscription(userId, 'Page', pageId, status); }; subscriptionSchema.statics.getSubscription = async function(target: Ref) { return this.find({ target, status: SubscriptionStatusType.SUBSCRIBE }).distinct('user'); }; subscriptionSchema.statics.getUnsubscription = async function(target: Ref) { return this.find({ target, status: SubscriptionStatusType.UNSUBSCRIBE }).distinct('user'); }; subscriptionSchema.statics.getSubscriptions = async function(targets: Ref[]) { return this.find({ target: { $in: targets }, status: SubscriptionStatusType.SUBSCRIBE }).distinct('user'); }; export default getOrCreateModel('Subscription', subscriptionSchema);