From 0e711d281c604d6b9b4c3c4e2f02500d560708b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Mon, 27 Jul 2026 19:25:19 +0000 Subject: [PATCH] music: index + serve loose folder images (band photos, booklet scans) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Analog of the videos feature — exposes per-folder images (excluding the album cover files) under /api/music so the app can show an "Images" section. Indexer: IMAGE_EXT + isImage; collect loose images (minus COVER_FILES); add them to the version signature (img: parts, so v changes when one is added/removed — no re-sync hack needed, source files); write meta.images: [{ file }] and a manifest images count. Folders with only images now index too. Serving: GET /image?path=&file= streams the ORIGINAL image bytes from the library folder (image/*, ETag=, 304), basename + prefix-guarded against traversal. Documented in the contract comment. Verified: meta.images lists loose images with the cover excluded, manifest count correct, /image path resolution + traversal guard. App side (music-api, Images section) is the app's to add. No CACHE_VERSION bump — the sig change reindexes exactly the folders that have images. Co-Authored-By: Claude Opus 4.8 --- src/servers/sidecar/music/index.ts | 21 +++++++++++- src/servers/sidecar/music/indexer.ts | 48 ++++++++++++++++++++++++---- 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/src/servers/sidecar/music/index.ts b/src/servers/sidecar/music/index.ts index ac6fb13b..7342b3fa 100644 --- a/src/servers/sidecar/music/index.ts +++ b/src/servers/sidecar/music/index.ts @@ -1,5 +1,5 @@ import { mkdirSync, writeFileSync } from 'node:fs'; -import { join } from 'node:path'; +import { join, basename } from 'node:path'; import type { SidecarCommand, SidecarEvent } from '../protocol'; import { createSidecarConnector } from '../connect'; import { streamAudioFile } from './stream-audio'; @@ -8,6 +8,7 @@ import { startMusicWatcher, stopMusicWatcher } from './watcher'; import { reindexNow, ensureCacheSetup, + MUSIC_ROOT, getIndexStatus, getManifest, albumVersion, @@ -42,6 +43,7 @@ const DATA_PATH = process.env.DATA_PATH ?? join(process.cwd(), 'data'); // GET /cover?path= compressed cover.jpg. ETag: ; If-None-Match → 304. // GET /poster?path=&file=