UNPKG

@replyke/express

Version:

Replyke: Build interactive apps with social features like comments, votes, feeds, user lists, notifications, and more.

195 lines (194 loc) 7.03 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const sequelize_1 = require("sequelize"); const Entity_1 = __importDefault(require("./Entity")); const User_1 = __importDefault(require("./User")); const Report_1 = __importDefault(require("./Report")); class Comment extends sequelize_1.Model { static initModel(sequelize) { Comment.init({ id: { type: sequelize_1.DataTypes.UUID, defaultValue: sequelize_1.DataTypes.UUIDV4, primaryKey: true, allowNull: false, }, projectId: { type: sequelize_1.DataTypes.UUID, allowNull: false, }, userId: { type: sequelize_1.DataTypes.UUID, allowNull: false, }, referenceId: { type: sequelize_1.DataTypes.STRING, allowNull: true, }, foreignId: { type: sequelize_1.DataTypes.STRING, allowNull: true, }, entityId: { type: sequelize_1.DataTypes.UUID, allowNull: false, }, parentId: { type: sequelize_1.DataTypes.UUID, allowNull: true, }, content: { type: sequelize_1.DataTypes.TEXT, allowNull: true, }, gif: { type: sequelize_1.DataTypes.JSON, allowNull: true, }, mentions: { type: sequelize_1.DataTypes.ARRAY(sequelize_1.DataTypes.JSONB), allowNull: false, defaultValue: [], }, upvotes: { type: sequelize_1.DataTypes.ARRAY(sequelize_1.DataTypes.UUID), allowNull: false, defaultValue: [], }, downvotes: { type: sequelize_1.DataTypes.ARRAY(sequelize_1.DataTypes.UUID), allowNull: false, defaultValue: [], }, parentDeletedAt: { type: sequelize_1.DataTypes.DATE, allowNull: true, }, referencedCommentId: { type: sequelize_1.DataTypes.UUID, allowNull: true, }, attachments: { type: sequelize_1.DataTypes.ARRAY(sequelize_1.DataTypes.JSONB), allowNull: false, defaultValue: [], }, metadata: { type: sequelize_1.DataTypes.JSONB, allowNull: false, defaultValue: {}, validate: { notTooLarge(value) { const MAX_SIZE = 10240; // 10 KB if (value !== null) { const size = Buffer.byteLength(JSON.stringify(value), "utf8"); if (size > MAX_SIZE) { throw new Error(`Metadata exceeds the size limit of ${MAX_SIZE} bytes.`); } } }, }, }, createdAt: { type: sequelize_1.DataTypes.DATE, allowNull: false, defaultValue: sequelize_1.DataTypes.NOW, }, updatedAt: { type: sequelize_1.DataTypes.DATE, allowNull: false, defaultValue: sequelize_1.DataTypes.NOW, }, deletedAt: { type: sequelize_1.DataTypes.DATE, allowNull: true, }, }, { sequelize, modelName: "Comment", tableName: "Comments", timestamps: false, paranoid: true, indexes: [ { fields: ["projectId"], }, { fields: ["entityId"], }, { fields: ["parentId"], }, // make the comment‐count scan index‐only { name: "idx_comments_active", fields: ["entityId"], where: { deletedAt: null, parentDeletedAt: null, }, }, { name: "idx_comments_active_parent", fields: ["parentId"], where: { deletedAt: null, parentDeletedAt: null, }, }, { name: "idx_comments_list", fields: [ { name: "projectId" }, { name: "entityId" }, { name: "createdAt", order: "DESC" }, ], where: { deletedAt: null, }, }, ], }); // On update: only overwrite updatedAt *if* the user didn’t explicitly set it. Comment.beforeUpdate((inst) => { if (!inst.changed("updatedAt")) { inst.setDataValue("updatedAt", new Date()); } }); } /** * Define associations to other models */ static associate() { Comment.belongsTo(Entity_1.default, { foreignKey: "entityId", onDelete: "CASCADE", // Ensures each Comment belongs to an Entity as: "entity", // Define the alias here }); // We don't cascade delete comments when users are remove to keep conversation integrity. We will just not show the user if there is no one Comment.belongsTo(User_1.default, { foreignKey: "userId", as: "user", // Define the alias here }); // Self-referential relationship between Comment and itself // We don't cascade deletion. Currently, if a comment is deleted, the replies are not deleted. Comment.hasMany(Comment, { foreignKey: "parentId", // This field refers to the parent comment as: "replies", // Alias for the relation }); Comment.belongsTo(Comment, { foreignKey: "parentId", // Reference to the parent comment as: "parentComment", // Alias for the parent folder relation }); Comment.hasMany(Report_1.default, { foreignKey: "targetId", constraints: false, onDelete: "CASCADE", scope: { targetType: "Comment" }, // Ensures this association only applies to Reports for Comments }); } } exports.default = Comment;