const { DataTypes, Model } = require('sequelize') /** * @typedef MediaItemShareObject * @property {UUIDV4} id * @property {UUIDV4} mediaItemId * @property {string} mediaItemType * @property {string} slug * @property {string} pash * @property {UUIDV4} userId * @property {Date} expiresAt * @property {Object} extraData * @property {Date} createdAt * @property {Date} updatedAt * * @typedef {MediaItemShareObject & MediaItemShare} MediaItemShareModel */ /** * @typedef MediaItemShareForClient * @property {UUIDV4} id * @property {UUIDV4} mediaItemId * @property {string} mediaItemType * @property {string} slug * @property {Date} expiresAt * @property {Date} createdAt * @property {Date} updatedAt */ class MediaItemShare extends Model { constructor(values, options) { super(values, options) } toJSONForClient() { return { id: this.id, mediaItemId: this.mediaItemId, mediaItemType: this.mediaItemType, slug: this.slug, expiresAt: this.expiresAt, createdAt: this.createdAt, updatedAt: this.updatedAt } } /** * * @param {import('sequelize').FindOptions} options * @returns {Promise} */ getMediaItem(options) { if (!this.mediaItemType) return Promise.resolve(null) const mixinMethodName = `get${this.sequelize.uppercaseFirst(this.mediaItemType)}` return this[mixinMethodName](options) } /** * Initialize model * * @param {import('../Database').sequelize} sequelize */ static init(sequelize) { super.init( { id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true }, mediaItemId: DataTypes.UUIDV4, mediaItemType: DataTypes.STRING, slug: DataTypes.STRING, pash: DataTypes.STRING, expiresAt: DataTypes.DATE, extraData: DataTypes.JSON }, { sequelize, modelName: 'mediaItemShare' } ) const { user, book, podcastEpisode } = sequelize.models user.hasMany(MediaItemShare) MediaItemShare.belongsTo(user) book.hasMany(MediaItemShare, { foreignKey: 'mediaItemId', constraints: false, scope: { mediaItemType: 'book' } }) MediaItemShare.belongsTo(book, { foreignKey: 'mediaItemId', constraints: false }) podcastEpisode.hasOne(MediaItemShare, { foreignKey: 'mediaItemId', constraints: false, scope: { mediaItemType: 'podcastEpisode' } }) MediaItemShare.belongsTo(podcastEpisode, { foreignKey: 'mediaItemId', constraints: false }) MediaItemShare.addHook('afterFind', (findResult) => { if (!findResult) return if (!Array.isArray(findResult)) findResult = [findResult] for (const instance of findResult) { if (instance.mediaItemType === 'book' && instance.book !== undefined) { instance.mediaItem = instance.book instance.dataValues.mediaItem = instance.dataValues.book } else if (instance.mediaItemType === 'podcastEpisode' && instance.podcastEpisode !== undefined) { instance.mediaItem = instance.podcastEpisode instance.dataValues.mediaItem = instance.dataValues.podcastEpisode } // To prevent mistakes: delete instance.book delete instance.dataValues.book delete instance.podcastEpisode delete instance.dataValues.podcastEpisode } }) } } module.exports = MediaItemShare