Add jsdoc types to remaining models

This commit is contained in:
advplyr 2023-08-16 16:38:48 -05:00
parent 0bc89cd40f
commit a98942a361
11 changed files with 2302 additions and 1939 deletions

View File

@ -92,27 +92,27 @@ class Database {
} }
buildModels(force = false) { buildModels(force = false) {
require('./models/User')(this.sequelize) require('./models/User').init(this.sequelize)
require('./models/Library').init(this.sequelize) require('./models/Library').init(this.sequelize)
require('./models/LibraryFolder').init(this.sequelize) require('./models/LibraryFolder').init(this.sequelize)
require('./models/Book').init(this.sequelize) require('./models/Book').init(this.sequelize)
require('./models/Podcast')(this.sequelize) require('./models/Podcast').init(this.sequelize)
require('./models/PodcastEpisode')(this.sequelize) require('./models/PodcastEpisode').init(this.sequelize)
require('./models/LibraryItem')(this.sequelize) require('./models/LibraryItem').init(this.sequelize)
require('./models/MediaProgress')(this.sequelize) require('./models/MediaProgress').init(this.sequelize)
require('./models/Series')(this.sequelize) require('./models/Series').init(this.sequelize)
require('./models/BookSeries').init(this.sequelize) require('./models/BookSeries').init(this.sequelize)
require('./models/Author').init(this.sequelize) require('./models/Author').init(this.sequelize)
require('./models/BookAuthor').init(this.sequelize) require('./models/BookAuthor').init(this.sequelize)
require('./models/Collection').init(this.sequelize) require('./models/Collection').init(this.sequelize)
require('./models/CollectionBook').init(this.sequelize) require('./models/CollectionBook').init(this.sequelize)
require('./models/Playlist')(this.sequelize) require('./models/Playlist').init(this.sequelize)
require('./models/PlaylistMediaItem')(this.sequelize) require('./models/PlaylistMediaItem').init(this.sequelize)
require('./models/Device').init(this.sequelize) require('./models/Device').init(this.sequelize)
require('./models/PlaybackSession')(this.sequelize) require('./models/PlaybackSession').init(this.sequelize)
require('./models/Feed').init(this.sequelize) require('./models/Feed').init(this.sequelize)
require('./models/FeedEpisode').init(this.sequelize) require('./models/FeedEpisode').init(this.sequelize)
require('./models/Setting')(this.sequelize) require('./models/Setting').init(this.sequelize)
return this.sequelize.sync({ force, alter: false }) return this.sequelize.sync({ force, alter: false })
} }

View File

@ -4,8 +4,55 @@ const oldLibraryItem = require('../objects/LibraryItem')
const libraryFilters = require('../utils/queries/libraryFilters') const libraryFilters = require('../utils/queries/libraryFilters')
const { areEquivalent } = require('../utils/index') const { areEquivalent } = require('../utils/index')
module.exports = (sequelize) => {
class LibraryItem extends Model { class LibraryItem extends Model {
constructor(values, options) {
super(values, options)
/** @type {UUIDV4} */
this.id
/** @type {string} */
this.ino
/** @type {string} */
this.path
/** @type {string} */
this.relPath
/** @type {UUIDV4} */
this.mediaId
/** @type {string} */
this.mediaType
/** @type {boolean} */
this.isFile
/** @type {boolean} */
this.isMissing
/** @type {boolean} */
this.isInvalid
/** @type {Date} */
this.mtime
/** @type {Date} */
this.ctime
/** @type {Date} */
this.birthtime
/** @type {BigInt} */
this.size
/** @type {Date} */
this.lastScan
/** @type {string} */
this.lastScanVersion
/** @type {Object} */
this.libraryFiles
/** @type {Object} */
this.extraData
/** @type {UUIDV4} */
this.libraryId
/** @type {UUIDV4} */
this.libraryFolderId
/** @type {Date} */
this.createdAt
/** @type {Date} */
this.updatedAt
}
/** /**
* Loads all podcast episodes, all library items in chunks of 500, then maps them to old library items * Loads all podcast episodes, all library items in chunks of 500, then maps them to old library items
* @todo this is a temporary solution until we can use the sqlite without loading all the library items on init * @todo this is a temporary solution until we can use the sqlite without loading all the library items on init
@ -15,7 +62,7 @@ module.exports = (sequelize) => {
static async loadAllLibraryItems() { static async loadAllLibraryItems() {
let start = Date.now() let start = Date.now()
Logger.info(`[LibraryItem] Loading podcast episodes...`) Logger.info(`[LibraryItem] Loading podcast episodes...`)
const podcastEpisodes = await sequelize.models.podcastEpisode.findAll() const podcastEpisodes = await this.sequelize.models.podcastEpisode.findAll()
Logger.info(`[LibraryItem] Finished loading ${podcastEpisodes.length} podcast episodes in ${((Date.now() - start) / 1000).toFixed(2)}s`) Logger.info(`[LibraryItem] Finished loading ${podcastEpisodes.length} podcast episodes in ${((Date.now() - start) / 1000).toFixed(2)}s`)
start = Date.now() start = Date.now()
@ -69,16 +116,16 @@ module.exports = (sequelize) => {
}, },
include: [ include: [
{ {
model: sequelize.models.book, model: this.sequelize.models.book,
include: [ include: [
{ {
model: sequelize.models.author, model: this.sequelize.models.author,
through: { through: {
attributes: ['createdAt'] attributes: ['createdAt']
} }
}, },
{ {
model: sequelize.models.series, model: this.sequelize.models.series,
through: { through: {
attributes: ['sequence', 'createdAt'] attributes: ['sequence', 'createdAt']
} }
@ -86,14 +133,14 @@ module.exports = (sequelize) => {
] ]
}, },
{ {
model: sequelize.models.podcast model: this.sequelize.models.podcast
} }
], ],
order: [ order: [
['createdAt', 'ASC'], ['createdAt', 'ASC'],
// Ensure author & series stay in the same order // Ensure author & series stay in the same order
[sequelize.models.book, sequelize.models.author, sequelize.models.bookAuthor, 'createdAt', 'ASC'], [this.sequelize.models.book, this.sequelize.models.author, this.sequelize.models.bookAuthor, 'createdAt', 'ASC'],
[sequelize.models.book, sequelize.models.series, 'bookSeries', 'createdAt', 'ASC'] [this.sequelize.models.book, this.sequelize.models.series, 'bookSeries', 'createdAt', 'ASC']
], ],
offset, offset,
limit limit
@ -110,16 +157,16 @@ module.exports = (sequelize) => {
where, where,
include: [ include: [
{ {
model: sequelize.models.book, model: this.sequelize.models.book,
include: [ include: [
{ {
model: sequelize.models.author, model: this.sequelize.models.author,
through: { through: {
attributes: [] attributes: []
} }
}, },
{ {
model: sequelize.models.series, model: this.sequelize.models.series,
through: { through: {
attributes: ['sequence'] attributes: ['sequence']
} }
@ -127,10 +174,10 @@ module.exports = (sequelize) => {
] ]
}, },
{ {
model: sequelize.models.podcast, model: this.sequelize.models.podcast,
include: [ include: [
{ {
model: sequelize.models.podcastEpisode model: this.sequelize.models.podcastEpisode
} }
] ]
} }
@ -148,9 +195,9 @@ module.exports = (sequelize) => {
static getOldLibraryItem(libraryItemExpanded) { static getOldLibraryItem(libraryItemExpanded) {
let media = null let media = null
if (libraryItemExpanded.mediaType === 'book') { if (libraryItemExpanded.mediaType === 'book') {
media = sequelize.models.book.getOldBook(libraryItemExpanded) media = this.sequelize.models.book.getOldBook(libraryItemExpanded)
} else if (libraryItemExpanded.mediaType === 'podcast') { } else if (libraryItemExpanded.mediaType === 'podcast') {
media = sequelize.models.podcast.getOldPodcast(libraryItemExpanded) media = this.sequelize.models.podcast.getOldPodcast(libraryItemExpanded)
} }
return new oldLibraryItem({ return new oldLibraryItem({
@ -181,30 +228,30 @@ module.exports = (sequelize) => {
const newLibraryItem = await this.create(this.getFromOld(oldLibraryItem)) const newLibraryItem = await this.create(this.getFromOld(oldLibraryItem))
if (oldLibraryItem.mediaType === 'book') { if (oldLibraryItem.mediaType === 'book') {
const bookObj = sequelize.models.book.getFromOld(oldLibraryItem.media) const bookObj = this.sequelize.models.book.getFromOld(oldLibraryItem.media)
bookObj.libraryItemId = newLibraryItem.id bookObj.libraryItemId = newLibraryItem.id
const newBook = await sequelize.models.book.create(bookObj) const newBook = await this.sequelize.models.book.create(bookObj)
const oldBookAuthors = oldLibraryItem.media.metadata.authors || [] const oldBookAuthors = oldLibraryItem.media.metadata.authors || []
const oldBookSeriesAll = oldLibraryItem.media.metadata.series || [] const oldBookSeriesAll = oldLibraryItem.media.metadata.series || []
for (const oldBookAuthor of oldBookAuthors) { for (const oldBookAuthor of oldBookAuthors) {
await sequelize.models.bookAuthor.create({ authorId: oldBookAuthor.id, bookId: newBook.id }) await this.sequelize.models.bookAuthor.create({ authorId: oldBookAuthor.id, bookId: newBook.id })
} }
for (const oldSeries of oldBookSeriesAll) { for (const oldSeries of oldBookSeriesAll) {
await sequelize.models.bookSeries.create({ seriesId: oldSeries.id, bookId: newBook.id, sequence: oldSeries.sequence }) await this.sequelize.models.bookSeries.create({ seriesId: oldSeries.id, bookId: newBook.id, sequence: oldSeries.sequence })
} }
} else if (oldLibraryItem.mediaType === 'podcast') { } else if (oldLibraryItem.mediaType === 'podcast') {
const podcastObj = sequelize.models.podcast.getFromOld(oldLibraryItem.media) const podcastObj = this.sequelize.models.podcast.getFromOld(oldLibraryItem.media)
podcastObj.libraryItemId = newLibraryItem.id podcastObj.libraryItemId = newLibraryItem.id
const newPodcast = await sequelize.models.podcast.create(podcastObj) const newPodcast = await this.sequelize.models.podcast.create(podcastObj)
const oldEpisodes = oldLibraryItem.media.episodes || [] const oldEpisodes = oldLibraryItem.media.episodes || []
for (const oldEpisode of oldEpisodes) { for (const oldEpisode of oldEpisodes) {
const episodeObj = sequelize.models.podcastEpisode.getFromOld(oldEpisode) const episodeObj = this.sequelize.models.podcastEpisode.getFromOld(oldEpisode)
episodeObj.libraryItemId = newLibraryItem.id episodeObj.libraryItemId = newLibraryItem.id
episodeObj.podcastId = newPodcast.id episodeObj.podcastId = newPodcast.id
await sequelize.models.podcastEpisode.create(episodeObj) await this.sequelize.models.podcastEpisode.create(episodeObj)
} }
} }
@ -215,16 +262,16 @@ module.exports = (sequelize) => {
const libraryItemExpanded = await this.findByPk(oldLibraryItem.id, { const libraryItemExpanded = await this.findByPk(oldLibraryItem.id, {
include: [ include: [
{ {
model: sequelize.models.book, model: this.sequelize.models.book,
include: [ include: [
{ {
model: sequelize.models.author, model: this.sequelize.models.author,
through: { through: {
attributes: [] attributes: []
} }
}, },
{ {
model: sequelize.models.series, model: this.sequelize.models.series,
through: { through: {
attributes: ['id', 'sequence'] attributes: ['id', 'sequence']
} }
@ -232,10 +279,10 @@ module.exports = (sequelize) => {
] ]
}, },
{ {
model: sequelize.models.podcast, model: this.sequelize.models.podcast,
include: [ include: [
{ {
model: sequelize.models.podcastEpisode model: this.sequelize.models.podcastEpisode
} }
] ]
} }
@ -249,7 +296,7 @@ module.exports = (sequelize) => {
if (libraryItemExpanded.media) { if (libraryItemExpanded.media) {
let updatedMedia = null let updatedMedia = null
if (libraryItemExpanded.mediaType === 'podcast') { if (libraryItemExpanded.mediaType === 'podcast') {
updatedMedia = sequelize.models.podcast.getFromOld(oldLibraryItem.media) updatedMedia = this.sequelize.models.podcast.getFromOld(oldLibraryItem.media)
const existingPodcastEpisodes = libraryItemExpanded.media.podcastEpisodes || [] const existingPodcastEpisodes = libraryItemExpanded.media.podcastEpisodes || []
const updatedPodcastEpisodes = oldLibraryItem.media.episodes || [] const updatedPodcastEpisodes = oldLibraryItem.media.episodes || []
@ -266,10 +313,10 @@ module.exports = (sequelize) => {
const existingEpisodeMatch = existingPodcastEpisodes.find(ep => ep.id === updatedPodcastEpisode.id) const existingEpisodeMatch = existingPodcastEpisodes.find(ep => ep.id === updatedPodcastEpisode.id)
if (!existingEpisodeMatch) { if (!existingEpisodeMatch) {
Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" episode "${updatedPodcastEpisode.title}" was added`) Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" episode "${updatedPodcastEpisode.title}" was added`)
await sequelize.models.podcastEpisode.createFromOld(updatedPodcastEpisode) await this.sequelize.models.podcastEpisode.createFromOld(updatedPodcastEpisode)
hasUpdates = true hasUpdates = true
} else { } else {
const updatedEpisodeCleaned = sequelize.models.podcastEpisode.getFromOld(updatedPodcastEpisode) const updatedEpisodeCleaned = this.sequelize.models.podcastEpisode.getFromOld(updatedPodcastEpisode)
let episodeHasUpdates = false let episodeHasUpdates = false
for (const key in updatedEpisodeCleaned) { for (const key in updatedEpisodeCleaned) {
let existingValue = existingEpisodeMatch[key] let existingValue = existingEpisodeMatch[key]
@ -287,7 +334,7 @@ module.exports = (sequelize) => {
} }
} }
} else if (libraryItemExpanded.mediaType === 'book') { } else if (libraryItemExpanded.mediaType === 'book') {
updatedMedia = sequelize.models.book.getFromOld(oldLibraryItem.media) updatedMedia = this.sequelize.models.book.getFromOld(oldLibraryItem.media)
const existingAuthors = libraryItemExpanded.media.authors || [] const existingAuthors = libraryItemExpanded.media.authors || []
const existingSeriesAll = libraryItemExpanded.media.series || [] const existingSeriesAll = libraryItemExpanded.media.series || []
@ -298,7 +345,7 @@ module.exports = (sequelize) => {
// Author was removed from Book // Author was removed from Book
if (!updatedAuthors.some(au => au.id === existingAuthor.id)) { if (!updatedAuthors.some(au => au.id === existingAuthor.id)) {
Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" author "${existingAuthor.name}" was removed`) Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" author "${existingAuthor.name}" was removed`)
await sequelize.models.bookAuthor.removeByIds(existingAuthor.id, libraryItemExpanded.media.id) await this.sequelize.models.bookAuthor.removeByIds(existingAuthor.id, libraryItemExpanded.media.id)
hasUpdates = true hasUpdates = true
} }
} }
@ -306,7 +353,7 @@ module.exports = (sequelize) => {
// Author was added // Author was added
if (!existingAuthors.some(au => au.id === updatedAuthor.id)) { if (!existingAuthors.some(au => au.id === updatedAuthor.id)) {
Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" author "${updatedAuthor.name}" was added`) Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" author "${updatedAuthor.name}" was added`)
await sequelize.models.bookAuthor.create({ authorId: updatedAuthor.id, bookId: libraryItemExpanded.media.id }) await this.sequelize.models.bookAuthor.create({ authorId: updatedAuthor.id, bookId: libraryItemExpanded.media.id })
hasUpdates = true hasUpdates = true
} }
} }
@ -314,7 +361,7 @@ module.exports = (sequelize) => {
// Series was removed // Series was removed
if (!updatedSeriesAll.some(se => se.id === existingSeries.id)) { if (!updatedSeriesAll.some(se => se.id === existingSeries.id)) {
Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" series "${existingSeries.name}" was removed`) Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" series "${existingSeries.name}" was removed`)
await sequelize.models.bookSeries.removeByIds(existingSeries.id, libraryItemExpanded.media.id) await this.sequelize.models.bookSeries.removeByIds(existingSeries.id, libraryItemExpanded.media.id)
hasUpdates = true hasUpdates = true
} }
} }
@ -323,7 +370,7 @@ module.exports = (sequelize) => {
const existingSeriesMatch = existingSeriesAll.find(se => se.id === updatedSeries.id) const existingSeriesMatch = existingSeriesAll.find(se => se.id === updatedSeries.id)
if (!existingSeriesMatch) { if (!existingSeriesMatch) {
Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" series "${updatedSeries.name}" was added`) Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" series "${updatedSeries.name}" was added`)
await sequelize.models.bookSeries.create({ seriesId: updatedSeries.id, bookId: libraryItemExpanded.media.id, sequence: updatedSeries.sequence }) await this.sequelize.models.bookSeries.create({ seriesId: updatedSeries.id, bookId: libraryItemExpanded.media.id, sequence: updatedSeries.sequence })
hasUpdates = true hasUpdates = true
} else if (existingSeriesMatch.bookSeries.sequence !== updatedSeries.sequence) { } else if (existingSeriesMatch.bookSeries.sequence !== updatedSeries.sequence) {
Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" series "${updatedSeries.name}" sequence was updated from "${existingSeriesMatch.bookSeries.sequence}" to "${updatedSeries.sequence}"`) Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" series "${updatedSeries.name}" sequence was updated from "${existingSeriesMatch.bookSeries.sequence}" to "${updatedSeries.sequence}"`)
@ -415,16 +462,16 @@ module.exports = (sequelize) => {
const libraryItem = await this.findByPk(libraryItemId, { const libraryItem = await this.findByPk(libraryItemId, {
include: [ include: [
{ {
model: sequelize.models.book, model: this.sequelize.models.book,
include: [ include: [
{ {
model: sequelize.models.author, model: this.sequelize.models.author,
through: { through: {
attributes: [] attributes: []
} }
}, },
{ {
model: sequelize.models.series, model: this.sequelize.models.series,
through: { through: {
attributes: ['sequence'] attributes: ['sequence']
} }
@ -432,10 +479,10 @@ module.exports = (sequelize) => {
] ]
}, },
{ {
model: sequelize.models.podcast, model: this.sequelize.models.podcast,
include: [ include: [
{ {
model: sequelize.models.podcastEpisode model: this.sequelize.models.podcastEpisode
} }
] ]
} }
@ -467,7 +514,7 @@ module.exports = (sequelize) => {
oldLibraryItem.media.metadata.series = li.series oldLibraryItem.media.metadata.series = li.series
} }
if (li.rssFeed) { if (li.rssFeed) {
oldLibraryItem.rssFeed = sequelize.models.feed.getOldFeed(li.rssFeed).toJSONMinified() oldLibraryItem.rssFeed = this.sequelize.models.feed.getOldFeed(li.rssFeed).toJSONMinified()
} }
if (li.media.numEpisodes) { if (li.media.numEpisodes) {
oldLibraryItem.media.numEpisodes = li.media.numEpisodes oldLibraryItem.media.numEpisodes = li.media.numEpisodes
@ -690,12 +737,16 @@ module.exports = (sequelize) => {
getMedia(options) { getMedia(options) {
if (!this.mediaType) return Promise.resolve(null) if (!this.mediaType) return Promise.resolve(null)
const mixinMethodName = `get${sequelize.uppercaseFirst(this.mediaType)}` const mixinMethodName = `get${this.sequelize.uppercaseFirst(this.mediaType)}`
return this[mixinMethodName](options) return this[mixinMethodName](options)
} }
}
LibraryItem.init({ /**
* Initialize model
* @param {import('../Database').sequelize} sequelize
*/
static init(sequelize) {
super.init({
id: { id: {
type: DataTypes.UUID, type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4, defaultValue: DataTypes.UUIDV4,
@ -791,6 +842,7 @@ module.exports = (sequelize) => {
media.destroy() media.destroy()
} }
}) })
return LibraryItem
} }
}
module.exports = LibraryItem

View File

@ -1,11 +1,39 @@
const { DataTypes, Model } = require('sequelize') const { DataTypes, Model } = require('sequelize')
/*
* Polymorphic association: https://sequelize.org/docs/v6/advanced-association-concepts/polymorphic-associations/
* Book has many MediaProgress. PodcastEpisode has many MediaProgress.
*/
module.exports = (sequelize) => {
class MediaProgress extends Model { class MediaProgress extends Model {
constructor(values, options) {
super(values, options)
/** @type {UUIDV4} */
this.id
/** @type {UUIDV4} */
this.mediaItemId
/** @type {string} */
this.mediaItemType
/** @type {number} */
this.duration
/** @type {number} */
this.currentTime
/** @type {boolean} */
this.isFinished
/** @type {boolean} */
this.hideFromContinueListening
/** @type {string} */
this.ebookLocation
/** @type {number} */
this.ebookProgress
/** @type {Date} */
this.finishedAt
/** @type {Object} */
this.extraData
/** @type {UUIDV4} */
this.userId
/** @type {Date} */
this.updatedAt
/** @type {Date} */
this.createdAt
}
getOldMediaProgress() { getOldMediaProgress() {
const isPodcastEpisode = this.mediaItemType === 'podcastEpisode' const isPodcastEpisode = this.mediaItemType === 'podcastEpisode'
@ -66,13 +94,20 @@ module.exports = (sequelize) => {
getMediaItem(options) { getMediaItem(options) {
if (!this.mediaItemType) return Promise.resolve(null) if (!this.mediaItemType) return Promise.resolve(null)
const mixinMethodName = `get${sequelize.uppercaseFirst(this.mediaItemType)}` const mixinMethodName = `get${this.sequelize.uppercaseFirst(this.mediaItemType)}`
return this[mixinMethodName](options) return this[mixinMethodName](options)
} }
}
/**
MediaProgress.init({ * Initialize model
*
* Polymorphic association: Book has many MediaProgress. PodcastEpisode has many MediaProgress.
* @see https://sequelize.org/docs/v6/advanced-association-concepts/polymorphic-associations/
*
* @param {import('../Database').sequelize} sequelize
*/
static init(sequelize) {
super.init({
id: { id: {
type: DataTypes.UUID, type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4, defaultValue: DataTypes.UUIDV4,
@ -143,6 +178,7 @@ module.exports = (sequelize) => {
onDelete: 'CASCADE' onDelete: 'CASCADE'
}) })
MediaProgress.belongsTo(user) MediaProgress.belongsTo(user)
return MediaProgress
} }
}
module.exports = MediaProgress

View File

@ -2,14 +2,63 @@ const { DataTypes, Model } = require('sequelize')
const oldPlaybackSession = require('../objects/PlaybackSession') const oldPlaybackSession = require('../objects/PlaybackSession')
module.exports = (sequelize) => {
class PlaybackSession extends Model { class PlaybackSession extends Model {
constructor(values, options) {
super(values, options)
/** @type {UUIDV4} */
this.id
/** @type {UUIDV4} */
this.mediaItemId
/** @type {string} */
this.mediaItemType
/** @type {string} */
this.displayTitle
/** @type {string} */
this.displayAuthor
/** @type {number} */
this.duration
/** @type {number} */
this.playMethod
/** @type {string} */
this.mediaPlayer
/** @type {number} */
this.startTime
/** @type {number} */
this.currentTime
/** @type {string} */
this.serverVersion
/** @type {string} */
this.coverPath
/** @type {number} */
this.timeListening
/** @type {Object} */
this.mediaMetadata
/** @type {string} */
this.date
/** @type {string} */
this.dayOfWeek
/** @type {Object} */
this.extraData
/** @type {UUIDV4} */
this.userId
/** @type {UUIDV4} */
this.deviceId
/** @type {UUIDV4} */
this.libraryId
/** @type {Date} */
this.updatedAt
/** @type {Date} */
this.createdAt
}
static async getOldPlaybackSessions(where = null) { static async getOldPlaybackSessions(where = null) {
const playbackSessions = await this.findAll({ const playbackSessions = await this.findAll({
where, where,
include: [ include: [
{ {
model: sequelize.models.device model: this.sequelize.models.device
} }
] ]
}) })
@ -20,7 +69,7 @@ module.exports = (sequelize) => {
const playbackSession = await this.findByPk(sessionId, { const playbackSession = await this.findByPk(sessionId, {
include: [ include: [
{ {
model: sequelize.models.device model: this.sequelize.models.device
} }
] ]
}) })
@ -112,12 +161,16 @@ module.exports = (sequelize) => {
getMediaItem(options) { getMediaItem(options) {
if (!this.mediaItemType) return Promise.resolve(null) if (!this.mediaItemType) return Promise.resolve(null)
const mixinMethodName = `get${sequelize.uppercaseFirst(this.mediaItemType)}` const mixinMethodName = `get${this.sequelize.uppercaseFirst(this.mediaItemType)}`
return this[mixinMethodName](options) return this[mixinMethodName](options)
} }
}
PlaybackSession.init({ /**
* Initialize model
* @param {import('../Database').sequelize} sequelize
*/
static init(sequelize) {
super.init({
id: { id: {
type: DataTypes.UUID, type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4, defaultValue: DataTypes.UUIDV4,
@ -193,6 +246,7 @@ module.exports = (sequelize) => {
delete instance.dataValues.podcastEpisode delete instance.dataValues.podcastEpisode
} }
}) })
return PlaybackSession
} }
}
module.exports = PlaybackSession

View File

@ -3,22 +3,40 @@ const Logger = require('../Logger')
const oldPlaylist = require('../objects/Playlist') const oldPlaylist = require('../objects/Playlist')
module.exports = (sequelize) => {
class Playlist extends Model { class Playlist extends Model {
constructor(values, options) {
super(values, options)
/** @type {UUIDV4} */
this.id
/** @type {string} */
this.name
/** @type {string} */
this.description
/** @type {UUIDV4} */
this.libraryId
/** @type {UUIDV4} */
this.userId
/** @type {Date} */
this.createdAt
/** @type {Date} */
this.updatedAt
}
static async getOldPlaylists() { static async getOldPlaylists() {
const playlists = await this.findAll({ const playlists = await this.findAll({
include: { include: {
model: sequelize.models.playlistMediaItem, model: this.sequelize.models.playlistMediaItem,
include: [ include: [
{ {
model: sequelize.models.book, model: this.sequelize.models.book,
include: sequelize.models.libraryItem include: this.sequelize.models.libraryItem
}, },
{ {
model: sequelize.models.podcastEpisode, model: this.sequelize.models.podcastEpisode,
include: { include: {
model: sequelize.models.podcast, model: this.sequelize.models.podcast,
include: sequelize.models.libraryItem include: this.sequelize.models.libraryItem
} }
} }
] ]
@ -62,24 +80,24 @@ module.exports = (sequelize) => {
this.playlistMediaItems = await this.getPlaylistMediaItems({ this.playlistMediaItems = await this.getPlaylistMediaItems({
include: [ include: [
{ {
model: sequelize.models.book, model: this.sequelize.models.book,
include: sequelize.models.libraryItem include: this.sequelize.models.libraryItem
}, },
{ {
model: sequelize.models.podcastEpisode, model: this.sequelize.models.podcastEpisode,
include: { include: {
model: sequelize.models.podcast, model: this.sequelize.models.podcast,
include: sequelize.models.libraryItem include: this.sequelize.models.libraryItem
} }
} }
], ],
order: [['order', 'ASC']] order: [['order', 'ASC']]
}) || [] }) || []
const oldPlaylist = sequelize.models.playlist.getOldPlaylist(this) const oldPlaylist = this.sequelize.models.playlist.getOldPlaylist(this)
const libraryItemIds = oldPlaylist.items.map(i => i.libraryItemId) const libraryItemIds = oldPlaylist.items.map(i => i.libraryItemId)
let libraryItems = await sequelize.models.libraryItem.getAllOldLibraryItems({ let libraryItems = await this.sequelize.models.libraryItem.getAllOldLibraryItems({
id: libraryItemIds id: libraryItemIds
}) })
@ -88,7 +106,7 @@ module.exports = (sequelize) => {
if (include?.includes('rssfeed')) { if (include?.includes('rssfeed')) {
const feeds = await this.getFeeds() const feeds = await this.getFeeds()
if (feeds?.length) { if (feeds?.length) {
playlistExpanded.rssFeed = sequelize.models.feed.getOldFeed(feeds[0]) playlistExpanded.rssFeed = this.sequelize.models.feed.getOldFeed(feeds[0])
} }
} }
@ -127,17 +145,17 @@ module.exports = (sequelize) => {
if (!playlistId) return null if (!playlistId) return null
const playlist = await this.findByPk(playlistId, { const playlist = await this.findByPk(playlistId, {
include: { include: {
model: sequelize.models.playlistMediaItem, model: this.sequelize.models.playlistMediaItem,
include: [ include: [
{ {
model: sequelize.models.book, model: this.sequelize.models.book,
include: sequelize.models.libraryItem include: this.sequelize.models.libraryItem
}, },
{ {
model: sequelize.models.podcastEpisode, model: this.sequelize.models.podcastEpisode,
include: { include: {
model: sequelize.models.podcast, model: this.sequelize.models.podcast,
include: sequelize.models.libraryItem include: this.sequelize.models.libraryItem
} }
} }
] ]
@ -166,17 +184,17 @@ module.exports = (sequelize) => {
const playlists = await this.findAll({ const playlists = await this.findAll({
where: whereQuery, where: whereQuery,
include: { include: {
model: sequelize.models.playlistMediaItem, model: this.sequelize.models.playlistMediaItem,
include: [ include: [
{ {
model: sequelize.models.book, model: this.sequelize.models.book,
include: sequelize.models.libraryItem include: this.sequelize.models.libraryItem
}, },
{ {
model: sequelize.models.podcastEpisode, model: this.sequelize.models.podcastEpisode,
include: { include: {
model: sequelize.models.podcast, model: this.sequelize.models.podcast,
include: sequelize.models.libraryItem include: this.sequelize.models.libraryItem
} }
} }
] ]
@ -212,7 +230,7 @@ module.exports = (sequelize) => {
static async getPlaylistsForMediaItemIds(mediaItemIds) { static async getPlaylistsForMediaItemIds(mediaItemIds) {
if (!mediaItemIds?.length) return [] if (!mediaItemIds?.length) return []
const playlistMediaItemsExpanded = await sequelize.models.playlistMediaItem.findAll({ const playlistMediaItemsExpanded = await this.sequelize.models.playlistMediaItem.findAll({
where: { where: {
mediaItemId: { mediaItemId: {
[Op.in]: mediaItemIds [Op.in]: mediaItemIds
@ -220,19 +238,19 @@ module.exports = (sequelize) => {
}, },
include: [ include: [
{ {
model: sequelize.models.playlist, model: this.sequelize.models.playlist,
include: { include: {
model: sequelize.models.playlistMediaItem, model: this.sequelize.models.playlistMediaItem,
include: [ include: [
{ {
model: sequelize.models.book, model: this.sequelize.models.book,
include: sequelize.models.libraryItem include: this.sequelize.models.libraryItem
}, },
{ {
model: sequelize.models.podcastEpisode, model: this.sequelize.models.podcastEpisode,
include: { include: {
model: sequelize.models.podcast, model: this.sequelize.models.podcast,
include: sequelize.models.libraryItem include: this.sequelize.models.libraryItem
} }
} }
] ]
@ -265,9 +283,13 @@ module.exports = (sequelize) => {
} }
return playlists return playlists
} }
}
Playlist.init({ /**
* Initialize model
* @param {import('../Database').sequelize} sequelize
*/
static init(sequelize) {
super.init({
id: { id: {
type: DataTypes.UUID, type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4, defaultValue: DataTypes.UUIDV4,
@ -315,6 +337,7 @@ module.exports = (sequelize) => {
} }
}) })
return Playlist
} }
}
module.exports = Playlist

View File

@ -1,7 +1,23 @@
const { DataTypes, Model } = require('sequelize') const { DataTypes, Model } = require('sequelize')
module.exports = (sequelize) => {
class PlaylistMediaItem extends Model { class PlaylistMediaItem extends Model {
constructor(values, options) {
super(values, options)
/** @type {UUIDV4} */
this.id
/** @type {UUIDV4} */
this.mediaItemId
/** @type {string} */
this.mediaItemType
/** @type {number} */
this.order
/** @type {UUIDV4} */
this.playlistId
/** @type {Date} */
this.createdAt
}
static removeByIds(playlistId, mediaItemId) { static removeByIds(playlistId, mediaItemId) {
return this.destroy({ return this.destroy({
where: { where: {
@ -13,12 +29,16 @@ module.exports = (sequelize) => {
getMediaItem(options) { getMediaItem(options) {
if (!this.mediaItemType) return Promise.resolve(null) if (!this.mediaItemType) return Promise.resolve(null)
const mixinMethodName = `get${sequelize.uppercaseFirst(this.mediaItemType)}` const mixinMethodName = `get${this.sequelize.uppercaseFirst(this.mediaItemType)}`
return this[mixinMethodName](options) return this[mixinMethodName](options)
} }
}
PlaylistMediaItem.init({ /**
* Initialize model
* @param {import('../Database').sequelize} sequelize
*/
static init(sequelize) {
super.init({
id: { id: {
type: DataTypes.UUID, type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4, defaultValue: DataTypes.UUIDV4,
@ -79,6 +99,7 @@ module.exports = (sequelize) => {
onDelete: 'CASCADE' onDelete: 'CASCADE'
}) })
PlaylistMediaItem.belongsTo(playlist) PlaylistMediaItem.belongsTo(playlist)
return PlaylistMediaItem
} }
}
module.exports = PlaylistMediaItem

View File

@ -1,7 +1,57 @@
const { DataTypes, Model } = require('sequelize') const { DataTypes, Model } = require('sequelize')
module.exports = (sequelize) => {
class Podcast extends Model { class Podcast extends Model {
constructor(values, options) {
super(values, options)
/** @type {UUIDV4} */
this.id
/** @type {string} */
this.title
/** @type {string} */
this.titleIgnorePrefix
/** @type {string} */
this.author
/** @type {string} */
this.releaseDate
/** @type {string} */
this.feedURL
/** @type {string} */
this.imageURL
/** @type {string} */
this.description
/** @type {string} */
this.itunesPageURL
/** @type {string} */
this.itunesId
/** @type {string} */
this.itunesArtistId
/** @type {string} */
this.language
/** @type {string} */
this.podcastType
/** @type {boolean} */
this.explicit
/** @type {boolean} */
this.autoDownloadEpisodes
/** @type {string} */
this.autoDownloadSchedule
/** @type {Date} */
this.lastEpisodeCheck
/** @type {number} */
this.maxEpisodesToKeep
/** @type {string} */
this.coverPath
/** @type {Object} */
this.tags
/** @type {Object} */
this.genres
/** @type {Date} */
this.createdAt
/** @type {Date} */
this.updatedAt
}
static getOldPodcast(libraryItemExpanded) { static getOldPodcast(libraryItemExpanded) {
const podcastExpanded = libraryItemExpanded.media const podcastExpanded = libraryItemExpanded.media
const podcastEpisodes = podcastExpanded.podcastEpisodes?.map(ep => ep.getOldPodcastEpisode(libraryItemExpanded.id)).sort((a, b) => a.index - b.index) const podcastEpisodes = podcastExpanded.podcastEpisodes?.map(ep => ep.getOldPodcastEpisode(libraryItemExpanded.id)).sort((a, b) => a.index - b.index)
@ -61,9 +111,13 @@ module.exports = (sequelize) => {
genres: oldPodcastMetadata.genres genres: oldPodcastMetadata.genres
} }
} }
}
Podcast.init({ /**
* Initialize model
* @param {import('../Database').sequelize} sequelize
*/
static init(sequelize) {
super.init({
id: { id: {
type: DataTypes.UUID, type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4, defaultValue: DataTypes.UUIDV4,
@ -95,6 +149,7 @@ module.exports = (sequelize) => {
sequelize, sequelize,
modelName: 'podcast' modelName: 'podcast'
}) })
return Podcast
} }
}
module.exports = Podcast

View File

@ -1,7 +1,49 @@
const { DataTypes, Model } = require('sequelize') const { DataTypes, Model } = require('sequelize')
module.exports = (sequelize) => {
class PodcastEpisode extends Model { class PodcastEpisode extends Model {
constructor(values, options) {
super(values, options)
/** @type {UUIDV4} */
this.id
/** @type {number} */
this.index
/** @type {string} */
this.season
/** @type {string} */
this.episode
/** @type {string} */
this.episodeType
/** @type {string} */
this.title
/** @type {string} */
this.subtitle
/** @type {string} */
this.description
/** @type {string} */
this.pubDate
/** @type {string} */
this.enclosureURL
/** @type {BigInt} */
this.enclosureSize
/** @type {string} */
this.enclosureType
/** @type {Date} */
this.publishedAt
/** @type {Object} */
this.audioFile
/** @type {Object} */
this.chapters
/** @type {Object} */
this.extraData
/** @type {UUIDV4} */
this.podcastId
/** @type {Date} */
this.createdAt
/** @type {Date} */
this.updatedAt
}
getOldPodcastEpisode(libraryItemId = null) { getOldPodcastEpisode(libraryItemId = null) {
let enclosure = null let enclosure = null
if (this.enclosureURL) { if (this.enclosureURL) {
@ -63,9 +105,13 @@ module.exports = (sequelize) => {
extraData extraData
} }
} }
}
PodcastEpisode.init({ /**
* Initialize model
* @param {import('../Database').sequelize} sequelize
*/
static init(sequelize) {
super.init({
id: { id: {
type: DataTypes.UUID, type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4, defaultValue: DataTypes.UUIDV4,
@ -97,6 +143,7 @@ module.exports = (sequelize) => {
onDelete: 'CASCADE' onDelete: 'CASCADE'
}) })
PodcastEpisode.belongsTo(podcast) PodcastEpisode.belongsTo(podcast)
return PodcastEpisode
} }
}
module.exports = PodcastEpisode

View File

@ -2,8 +2,26 @@ const { DataTypes, Model } = require('sequelize')
const oldSeries = require('../objects/entities/Series') const oldSeries = require('../objects/entities/Series')
module.exports = (sequelize) => {
class Series extends Model { class Series extends Model {
constructor(values, options) {
super(values, options)
/** @type {UUIDV4} */
this.id
/** @type {string} */
this.name
/** @type {string} */
this.nameIgnorePrefix
/** @type {string} */
this.description
/** @type {UUIDV4} */
this.libraryId
/** @type {Date} */
this.createdAt
/** @type {Date} */
this.updatedAt
}
static async getAllOldSeries() { static async getAllOldSeries() {
const series = await this.findAll() const series = await this.findAll()
return series.map(se => se.getOldSeries()) return series.map(se => se.getOldSeries())
@ -56,9 +74,13 @@ module.exports = (sequelize) => {
} }
}) })
} }
}
Series.init({ /**
* Initialize model
* @param {import('../Database').sequelize} sequelize
*/
static init(sequelize) {
super.init({
id: { id: {
type: DataTypes.UUID, type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4, defaultValue: DataTypes.UUIDV4,
@ -77,6 +99,7 @@ module.exports = (sequelize) => {
onDelete: 'CASCADE' onDelete: 'CASCADE'
}) })
Series.belongsTo(library) Series.belongsTo(library)
return Series
} }
}
module.exports = Series

View File

@ -4,8 +4,20 @@ const oldEmailSettings = require('../objects/settings/EmailSettings')
const oldServerSettings = require('../objects/settings/ServerSettings') const oldServerSettings = require('../objects/settings/ServerSettings')
const oldNotificationSettings = require('../objects/settings/NotificationSettings') const oldNotificationSettings = require('../objects/settings/NotificationSettings')
module.exports = (sequelize) => {
class Setting extends Model { class Setting extends Model {
constructor(values, options) {
super(values, options)
/** @type {string} */
this.key
/** @type {Object} */
this.value
/** @type {Date} */
this.createdAt
/** @type {Date} */
this.updatedAt
}
static async getOldSettings() { static async getOldSettings() {
const settings = (await this.findAll()).map(se => se.value) const settings = (await this.findAll()).map(se => se.value)
@ -28,9 +40,13 @@ module.exports = (sequelize) => {
value: setting value: setting
}) })
} }
}
Setting.init({ /**
* Initialize model
* @param {import('../Database').sequelize} sequelize
*/
static init(sequelize) {
super.init({
key: { key: {
type: DataTypes.STRING, type: DataTypes.STRING,
primaryKey: true primaryKey: true
@ -40,6 +56,7 @@ module.exports = (sequelize) => {
sequelize, sequelize,
modelName: 'setting' modelName: 'setting'
}) })
return Setting
} }
}
module.exports = Setting

View File

@ -3,15 +3,45 @@ const { DataTypes, Model, Op } = require('sequelize')
const Logger = require('../Logger') const Logger = require('../Logger')
const oldUser = require('../objects/user/User') const oldUser = require('../objects/user/User')
module.exports = (sequelize) => {
class User extends Model { class User extends Model {
constructor(values, options) {
super(values, options)
/** @type {UUIDV4} */
this.id
/** @type {string} */
this.username
/** @type {string} */
this.email
/** @type {string} */
this.pash
/** @type {string} */
this.type
/** @type {boolean} */
this.isActive
/** @type {boolean} */
this.isLocked
/** @type {Date} */
this.lastSeen
/** @type {Object} */
this.permissions
/** @type {Object} */
this.bookmarks
/** @type {Object} */
this.extraData
/** @type {Date} */
this.createdAt
/** @type {Date} */
this.updatedAt
}
/** /**
* Get all oldUsers * Get all oldUsers
* @returns {Promise<oldUser>} * @returns {Promise<oldUser>}
*/ */
static async getOldUsers() { static async getOldUsers() {
const users = await this.findAll({ const users = await this.findAll({
include: sequelize.models.mediaProgress include: this.sequelize.models.mediaProgress
}) })
return users.map(u => this.getOldUser(u)) return users.map(u => this.getOldUser(u))
} }
@ -139,7 +169,7 @@ module.exports = (sequelize) => {
} }
] ]
}, },
include: sequelize.models.mediaProgress include: this.sequelize.models.mediaProgress
}) })
if (!user) return null if (!user) return null
return this.getOldUser(user) return this.getOldUser(user)
@ -158,7 +188,7 @@ module.exports = (sequelize) => {
[Op.like]: username [Op.like]: username
} }
}, },
include: sequelize.models.mediaProgress include: this.sequelize.models.mediaProgress
}) })
if (!user) return null if (!user) return null
return this.getOldUser(user) return this.getOldUser(user)
@ -172,7 +202,7 @@ module.exports = (sequelize) => {
static async getUserById(userId) { static async getUserById(userId) {
if (!userId) return null if (!userId) return null
const user = await this.findByPk(userId, { const user = await this.findByPk(userId, {
include: sequelize.models.mediaProgress include: this.sequelize.models.mediaProgress
}) })
if (!user) return null if (!user) return null
return this.getOldUser(user) return this.getOldUser(user)
@ -206,9 +236,13 @@ module.exports = (sequelize) => {
}) })
return count > 0 return count > 0
} }
}
User.init({ /**
* Initialize model
* @param {import('../Database').sequelize} sequelize
*/
static init(sequelize) {
super.init({
id: { id: {
type: DataTypes.UUID, type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4, defaultValue: DataTypes.UUIDV4,
@ -235,6 +269,7 @@ module.exports = (sequelize) => {
sequelize, sequelize,
modelName: 'user' modelName: 'user'
}) })
return User
} }
}
module.exports = User