(bookId: string)
| 264 | } |
| 265 | |
| 266 | async loadChapterIndex(bookId: string): Promise<ReadonlyArray<ChapterMeta>> { |
| 267 | const indexPath = join(this.bookDir(bookId), "chapters", "index.json"); |
| 268 | try { |
| 269 | const raw = await readFile(indexPath, "utf-8"); |
| 270 | const parsed = JSON.parse(raw) as unknown; |
| 271 | if (Array.isArray(parsed) && parsed.length > 0) return parsed as ReadonlyArray<ChapterMeta>; |
| 272 | if (Array.isArray(parsed)) { |
| 273 | const rebuilt = await this.rebuildChapterIndexFromFiles(bookId); |
| 274 | return rebuilt.length > 0 ? rebuilt : parsed as ReadonlyArray<ChapterMeta>; |
| 275 | } |
| 276 | } catch { |
| 277 | const rebuilt = await this.rebuildChapterIndexFromFiles(bookId); |
| 278 | if (rebuilt.length > 0) return rebuilt; |
| 279 | } |
| 280 | return []; |
| 281 | } |
| 282 | |
| 283 | private async rebuildChapterIndexFromFiles(bookId: string): Promise<ReadonlyArray<ChapterMeta>> { |
| 284 | return this.rebuildChapterIndexFromFilesAt(this.bookDir(bookId)); |
no test coverage detected