subscription.ts 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import type {
  2. Ref, IPage, IUser, ISubscription,
  3. } from '@growi/core';
  4. import {
  5. SubscriptionStatusType, AllSubscriptionStatusType,
  6. } from '@growi/core';
  7. import {
  8. type Types, type Document, type Model, Schema,
  9. } from 'mongoose';
  10. import { AllSupportedTargetModels } from '~/interfaces/activity';
  11. import { getOrCreateModel } from '../util/mongoose-utils';
  12. export interface SubscriptionDocument extends ISubscription, Document {}
  13. export interface SubscriptionModel extends Model<SubscriptionDocument> {
  14. findByUserIdAndTargetId(userId: Types.ObjectId | string, targetId: Types.ObjectId | string): any
  15. upsertSubscription(user: Ref<IUser>, targetModel: string, target: Ref<IPage>, status: string): any
  16. subscribeByPageId(userId: Types.ObjectId, pageId: Types.ObjectId, status: string): any
  17. getSubscription(target: Ref<IPage>): Promise<Ref<IUser>[]>
  18. getUnsubscription(target: Ref<IPage>): Promise<Ref<IUser>[]>
  19. getSubscriptions(targets: Ref<IPage>[]): Promise<Ref<IUser>[]>
  20. }
  21. const subscriptionSchema = new Schema<SubscriptionDocument, SubscriptionModel>({
  22. user: {
  23. type: Schema.Types.ObjectId,
  24. ref: 'User',
  25. index: true,
  26. required: true,
  27. },
  28. targetModel: {
  29. type: String,
  30. required: true,
  31. enum: AllSupportedTargetModels,
  32. },
  33. target: {
  34. type: Schema.Types.ObjectId,
  35. ref: 'Page',
  36. refPath: 'targetModel',
  37. required: true,
  38. },
  39. status: {
  40. type: String,
  41. required: true,
  42. enum: AllSubscriptionStatusType,
  43. },
  44. }, {
  45. timestamps: true,
  46. });
  47. subscriptionSchema.methods.isSubscribing = function() {
  48. return this.status === SubscriptionStatusType.SUBSCRIBE;
  49. };
  50. subscriptionSchema.methods.isUnsubscribing = function() {
  51. return this.status === SubscriptionStatusType.UNSUBSCRIBE;
  52. };
  53. subscriptionSchema.statics.findByUserIdAndTargetId = function(userId, targetId) {
  54. return this.findOne({ user: userId, target: targetId });
  55. };
  56. subscriptionSchema.statics.upsertSubscription = function(user, targetModel, target, status) {
  57. const query = { user, targetModel, target };
  58. const doc = { ...query, status };
  59. const options = {
  60. upsert: true, new: true, setDefaultsOnInsert: true, runValidators: true,
  61. };
  62. return this.findOneAndUpdate(query, doc, options);
  63. };
  64. subscriptionSchema.statics.subscribeByPageId = function(userId, pageId, status) {
  65. return this.upsertSubscription(userId, 'Page', pageId, status);
  66. };
  67. subscriptionSchema.statics.getSubscription = async function(target: Ref<IPage>) {
  68. return this.find({ target, status: SubscriptionStatusType.SUBSCRIBE }).distinct('user');
  69. };
  70. subscriptionSchema.statics.getUnsubscription = async function(target: Ref<IPage>) {
  71. return this.find({ target, status: SubscriptionStatusType.UNSUBSCRIBE }).distinct('user');
  72. };
  73. subscriptionSchema.statics.getSubscriptions = async function(targets: Ref<IPage>[]) {
  74. return this.find({ target: { $in: targets }, status: SubscriptionStatusType.SUBSCRIBE }).distinct('user');
  75. };
  76. export default getOrCreateModel<SubscriptionDocument, SubscriptionModel>('Subscription', subscriptionSchema);