import { getOrCreateModel } from '@growi/core'; import { Types, Document, Model, Schema, } from 'mongoose'; import { AllSupportedTargetModelType } from '~/interfaces/activity'; import { SubscriptionStatusType, AllSubscriptionStatusType } from '~/interfaces/subscription'; export interface ISubscription { user: Types.ObjectId targetModel: string target: Types.ObjectId status: string createdAt: Date isSubscribing(): boolean isUnsubscribing(): boolean } export interface SubscriptionDocument extends ISubscription, Document {} export interface SubscriptionModel extends Model { findByUserIdAndTargetId(userId: Types.ObjectId | string, targetId: Types.ObjectId | string): any upsertSubscription(user: Types.ObjectId, targetModel: string, target: Types.ObjectId, status: string): any subscribeByPageId(user: Types.ObjectId, pageId: Types.ObjectId, status: string): any getSubscription(target: Types.ObjectId): Promise getUnsubscription(target: Types.ObjectId): Promise getSubscriptions(targets: Types.ObjectId[]): Promise } const subscriptionSchema = new Schema({ user: { type: Schema.Types.ObjectId, ref: 'User', index: true, required: true, }, targetModel: { type: String, require: true, enum: AllSupportedTargetModelType, }, target: { type: Schema.Types.ObjectId, refPath: 'targetModel', require: true, }, status: { type: String, require: 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(user, pageId, status) { return this.upsertSubscription(user, 'Page', pageId, status); }; subscriptionSchema.statics.getSubscription = async function(target) { return this.find({ target, status: SubscriptionStatusType.SUBSCRIBE }).distinct('user'); }; subscriptionSchema.statics.getUnsubscription = async function(target) { return this.find({ target, status: SubscriptionStatusType.UNSUBSCRIBE }).distinct('user'); }; subscriptionSchema.statics.getSubscriptions = async function(targets) { return this.find({ $in: targets, status: SubscriptionStatusType.SUBSCRIBE }).distinct('user'); }; export default getOrCreateModel('Subscription', subscriptionSchema);