mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 00:11:37 -06:00
feat(types): expose the book file id on audiobook manifest assets
Clients that download an audiobook get its files from the book detail and its playback order from the manifest, and had to pair the two by position. The two lists are ordered differently, so an index pairing can attach the wrong file to an asset. Add the book_files id to each manifest asset so the pairing can be made by id. The field is additive and the server always sends it. The manifest revision is hashed from file and chapter data, not from the response, so existing revisions do not change and clients holding one do not see a 412 from this deploy. The iOS app consumes this field to pair downloaded files with manifest assets; the web client does not read it yet, so a grep of the client alone will show it as unused.
This commit is contained in:
@@ -102,8 +102,8 @@ describe('AudiobookService', () => {
|
||||
expect(manifest.schemaVersion).toBe(AUDIOBOOK_MANIFEST_VERSION);
|
||||
expect(manifest.revision).toMatch(/^[0-9a-f]{64}$/);
|
||||
expect(manifest.assets).toEqual([
|
||||
expect.objectContaining({ assetId: `aud_${FIRST_PUBLIC_ID}`, sequence: 0, durationMs: 10_125 }),
|
||||
expect.objectContaining({ assetId: `aud_${SECOND_PUBLIC_ID}`, sequence: 1, durationMs: 20_000 }),
|
||||
expect.objectContaining({ assetId: `aud_${FIRST_PUBLIC_ID}`, fileId: 11, sequence: 0, durationMs: 10_125 }),
|
||||
expect.objectContaining({ assetId: `aud_${SECOND_PUBLIC_ID}`, fileId: 12, sequence: 1, durationMs: 20_000 }),
|
||||
]);
|
||||
expect(manifest.chapters).toEqual([
|
||||
expect.objectContaining({ sequence: 0, startMs: 0, endMs: 10_125, assetId: `aud_${FIRST_PUBLIC_ID}`, assetOffsetMs: 0 }),
|
||||
@@ -111,6 +111,18 @@ describe('AudiobookService', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('keeps the manifest revision independent of the file ids it exposes', async () => {
|
||||
const { service, repo } = makeFixture();
|
||||
const before = await service.getManifest(30, makeUser());
|
||||
const files = await repo.findAudioFiles();
|
||||
repo.findAudioFiles.mockResolvedValue(files.map((file) => ({ ...file, id: file.id + 900 })));
|
||||
|
||||
const after = await service.getManifest(30, makeUser());
|
||||
|
||||
expect(after.assets.map((asset) => asset.fileId)).toEqual([911, 912]);
|
||||
expect(after.revision).toBe(before.revision);
|
||||
});
|
||||
|
||||
it('derives percentage and creates revision one from a matching manifest write', async () => {
|
||||
const { service, repo, bookService } = makeFixture();
|
||||
const manifest = await service.getManifest(30, makeUser());
|
||||
|
||||
@@ -212,6 +212,7 @@ export class AudiobookService {
|
||||
.digest('hex');
|
||||
const assets = files.map<AudiobookManifestAsset>((file, sequence) => ({
|
||||
assetId: this.assetId(file.publicId),
|
||||
fileId: file.id,
|
||||
sequence,
|
||||
format: file.format!,
|
||||
durationMs: file.durationSeconds === null ? null : Math.round(file.durationSeconds * 1000),
|
||||
|
||||
Reference in New Issue
Block a user