mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-07-13 21:01:39 +00:00
Merge 42c6798981 into 82aec5f60c
This commit is contained in:
commit
1aee2a1a1b
3 changed files with 117 additions and 5 deletions
|
|
@ -830,7 +830,7 @@ class LibraryController {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Create paginated queries
|
// TODO: Create paginated queries
|
||||||
let collections = await Database.collectionModel.getOldCollectionsJsonExpanded(req.user, req.library.id, include)
|
let collections = await Database.collectionModel.getOldCollectionsJsonExpanded(req.user, req.library.id, include, payload.minified)
|
||||||
|
|
||||||
payload.total = collections.length
|
payload.total = collections.length
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,10 @@ class Collection extends Model {
|
||||||
* @param {import('./User')} user
|
* @param {import('./User')} user
|
||||||
* @param {string} [libraryId]
|
* @param {string} [libraryId]
|
||||||
* @param {string[]} [include]
|
* @param {string[]} [include]
|
||||||
|
* @param {boolean} [minified=false]
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
static async getOldCollectionsJsonExpanded(user, libraryId, include) {
|
static async getOldCollectionsJsonExpanded(user, libraryId, include, minified = false) {
|
||||||
let collectionWhere = null
|
let collectionWhere = null
|
||||||
if (libraryId) {
|
if (libraryId) {
|
||||||
collectionWhere = {
|
collectionWhere = {
|
||||||
|
|
@ -98,7 +99,7 @@ class Collection extends Model {
|
||||||
|
|
||||||
this.books = books
|
this.books = books
|
||||||
|
|
||||||
const collectionExpanded = c.toOldJSONExpanded()
|
const collectionExpanded = c.toOldJSONExpanded(minified)
|
||||||
|
|
||||||
// Map feed if found
|
// Map feed if found
|
||||||
if (c.feeds?.length) {
|
if (c.feeds?.length) {
|
||||||
|
|
@ -272,7 +273,11 @@ class Collection extends Model {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toOldJSONExpanded() {
|
/**
|
||||||
|
* @param {boolean} [minified=false] When true, books use the minified library item serialization
|
||||||
|
* (omits libraryFiles and heavy media fields like chapters/tracks/audioFiles)
|
||||||
|
*/
|
||||||
|
toOldJSONExpanded(minified = false) {
|
||||||
if (!this.books) {
|
if (!this.books) {
|
||||||
throw new Error('Books are required to expand Collection')
|
throw new Error('Books are required to expand Collection')
|
||||||
}
|
}
|
||||||
|
|
@ -282,7 +287,7 @@ class Collection extends Model {
|
||||||
const libraryItem = book.libraryItem
|
const libraryItem = book.libraryItem
|
||||||
delete book.libraryItem
|
delete book.libraryItem
|
||||||
libraryItem.media = book
|
libraryItem.media = book
|
||||||
return libraryItem.toOldJSONExpanded()
|
return minified ? libraryItem.toOldJSONMinified() : libraryItem.toOldJSONExpanded()
|
||||||
})
|
})
|
||||||
|
|
||||||
return json
|
return json
|
||||||
|
|
|
||||||
107
test/server/models/Collection.test.js
Normal file
107
test/server/models/Collection.test.js
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
const { expect } = require('chai')
|
||||||
|
const { Sequelize } = require('sequelize')
|
||||||
|
|
||||||
|
const Database = require('../../../server/Database')
|
||||||
|
|
||||||
|
describe('Collection', () => {
|
||||||
|
/** @type {string} */
|
||||||
|
let libraryId
|
||||||
|
/** @type {string} */
|
||||||
|
let collectionId
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
global.ServerSettings = {}
|
||||||
|
Database.sequelize = new Sequelize({ dialect: 'sqlite', storage: ':memory:', logging: false })
|
||||||
|
Database.sequelize.uppercaseFirst = (str) => (str ? `${str[0].toUpperCase()}${str.substr(1)}` : '')
|
||||||
|
await Database.buildModels()
|
||||||
|
|
||||||
|
const library = await Database.libraryModel.create({ name: 'Test Library', mediaType: 'book' })
|
||||||
|
libraryId = library.id
|
||||||
|
const libraryFolder = await Database.libraryFolderModel.create({ path: '/test', libraryId: library.id })
|
||||||
|
|
||||||
|
// Build a book with heavy media: many audio files + chapters
|
||||||
|
const audioFiles = []
|
||||||
|
const chapters = []
|
||||||
|
for (let i = 0; i < 30; i++) {
|
||||||
|
audioFiles.push({
|
||||||
|
index: i + 1,
|
||||||
|
ino: `ino-${i}`,
|
||||||
|
duration: 600,
|
||||||
|
exclude: false,
|
||||||
|
mimeType: 'audio/mpeg',
|
||||||
|
metadata: { filename: `track-${i}.mp3`, ext: '.mp3', path: `/test/book/track-${i}.mp3`, relPath: `track-${i}.mp3`, size: 12345678 }
|
||||||
|
})
|
||||||
|
chapters.push({ id: i, start: i * 600, end: (i + 1) * 600, title: `Chapter ${i + 1}` })
|
||||||
|
}
|
||||||
|
|
||||||
|
const book = await Database.bookModel.create({ title: 'Heavy Book', audioFiles, tags: [], narrators: [], genres: [], chapters })
|
||||||
|
|
||||||
|
// libraryItem carries a large libraryFiles array (dropped by the minified form)
|
||||||
|
const libraryFiles = []
|
||||||
|
for (let i = 0; i < 30; i++) {
|
||||||
|
libraryFiles.push({
|
||||||
|
ino: `lf-${i}`,
|
||||||
|
metadata: { filename: `track-${i}.mp3`, ext: '.mp3', path: `/test/book/track-${i}.mp3`, relPath: `track-${i}.mp3`, size: 12345678, mtimeMs: 0, ctimeMs: 0, birthtimeMs: 0 }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await Database.libraryItemModel.create({ libraryFiles, mediaId: book.id, mediaType: 'book', libraryId: library.id, libraryFolderId: libraryFolder.id })
|
||||||
|
|
||||||
|
const collection = await Database.collectionModel.create({ name: 'Test Collection', libraryId: library.id })
|
||||||
|
collectionId = collection.id
|
||||||
|
await Database.collectionBookModel.create({ collectionId: collection.id, bookId: book.id, order: 1 })
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await Database.sequelize.close()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('getOldCollectionsJsonExpanded', () => {
|
||||||
|
it('returns fully expanded book objects when minified is not requested', async () => {
|
||||||
|
const collections = await Database.collectionModel.getOldCollectionsJsonExpanded(null, libraryId, [], false)
|
||||||
|
expect(collections).to.have.lengthOf(1)
|
||||||
|
const book = collections[0].books[0]
|
||||||
|
|
||||||
|
// Library item keeps the full libraryFiles array
|
||||||
|
expect(book).to.have.property('libraryFiles')
|
||||||
|
expect(book.libraryFiles).to.be.an('array').with.lengthOf(30)
|
||||||
|
|
||||||
|
// Media keeps the heavy arrays
|
||||||
|
expect(book.media).to.have.property('audioFiles').that.is.an('array').with.lengthOf(30)
|
||||||
|
expect(book.media).to.have.property('chapters').that.is.an('array').with.lengthOf(30)
|
||||||
|
expect(book.media).to.have.property('tracks').that.is.an('array').with.lengthOf(30)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns minified book objects that omit libraryFiles and heavy media when minified is requested', async () => {
|
||||||
|
const collections = await Database.collectionModel.getOldCollectionsJsonExpanded(null, libraryId, [], true)
|
||||||
|
expect(collections).to.have.lengthOf(1)
|
||||||
|
const book = collections[0].books[0]
|
||||||
|
|
||||||
|
// Library item drops libraryFiles in favor of a numFiles count
|
||||||
|
expect(book).to.not.have.property('libraryFiles')
|
||||||
|
expect(book).to.have.property('numFiles', 30)
|
||||||
|
|
||||||
|
// Media drops the heavy arrays in favor of counts
|
||||||
|
expect(book.media).to.not.have.property('audioFiles')
|
||||||
|
expect(book.media).to.not.have.property('chapters')
|
||||||
|
expect(book.media).to.not.have.property('tracks')
|
||||||
|
expect(book.media).to.have.property('numAudioFiles', 30)
|
||||||
|
expect(book.media).to.have.property('numChapters', 30)
|
||||||
|
expect(book.media).to.have.property('numTracks', 30)
|
||||||
|
|
||||||
|
// Essential display fields survive minification
|
||||||
|
expect(book.media).to.have.property('coverPath')
|
||||||
|
expect(book.media).to.have.property('duration')
|
||||||
|
expect(book.media.metadata).to.have.property('title', 'Heavy Book')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('produces a materially smaller payload when minified', async () => {
|
||||||
|
const expanded = await Database.collectionModel.getOldCollectionsJsonExpanded(null, libraryId, [], false)
|
||||||
|
const minified = await Database.collectionModel.getOldCollectionsJsonExpanded(null, libraryId, [], true)
|
||||||
|
|
||||||
|
const expandedSize = JSON.stringify(expanded).length
|
||||||
|
const minifiedSize = JSON.stringify(minified).length
|
||||||
|
|
||||||
|
expect(minifiedSize).to.be.lessThan(expandedSize * 0.5)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
Loading…
Add table
Add a link
Reference in a new issue