mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-07-12 12:21:34 +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
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -29,9 +29,10 @@ class Collection extends Model {
|
|||
* @param {import('./User')} user
|
||||
* @param {string} [libraryId]
|
||||
* @param {string[]} [include]
|
||||
* @param {boolean} [minified=false]
|
||||
* @async
|
||||
*/
|
||||
static async getOldCollectionsJsonExpanded(user, libraryId, include) {
|
||||
static async getOldCollectionsJsonExpanded(user, libraryId, include, minified = false) {
|
||||
let collectionWhere = null
|
||||
if (libraryId) {
|
||||
collectionWhere = {
|
||||
|
|
@ -98,7 +99,7 @@ class Collection extends Model {
|
|||
|
||||
this.books = books
|
||||
|
||||
const collectionExpanded = c.toOldJSONExpanded()
|
||||
const collectionExpanded = c.toOldJSONExpanded(minified)
|
||||
|
||||
// Map feed if found
|
||||
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) {
|
||||
throw new Error('Books are required to expand Collection')
|
||||
}
|
||||
|
|
@ -282,7 +287,7 @@ class Collection extends Model {
|
|||
const libraryItem = book.libraryItem
|
||||
delete book.libraryItem
|
||||
libraryItem.media = book
|
||||
return libraryItem.toOldJSONExpanded()
|
||||
return minified ? libraryItem.toOldJSONMinified() : libraryItem.toOldJSONExpanded()
|
||||
})
|
||||
|
||||
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