A worktree's own samples, in a page on a dev server that serves another checkout: for the headless tools (tools/measure, tools/check-songs), which play songs on the main dev server while a review may have re-rendered or added samples in its worktree.
The dev server's sample map (pages/jev-samples/strudel.json.js) lists each
file as @fs/<its checkout>/samples/<sound>/<file>, so the map says which
checkout it serves. When that is not this one, route(page) answers the
page's request for the map with one built from this checkout's samples/
(sampleMap.mjs, the site's own builder), and its requests for sample files
under either checkout's samples/ from this checkout's files, so a sample
only this worktree has plays too, and one it deleted does not.
17const FS_ENTRY = /^@fs(\/.*?)\/samples\/[^/]+\/[^/]+$/;
The checkout whose samples/ the dev server at url serves.
20async function servedRoot(url) { 21 const res = await fetch(`${url}/jev-samples/strudel.json`); 22 if (!res.ok) throw new Error(`${url}/jev-samples/strudel.json answered ${res.status}`); 23 const map = await res.json(); 24 for (const [sound, files] of Object.entries(map)) { 25 if (sound === '_base') continue; 26 const root = [files].flat()[0]?.match(FS_ENTRY)?.[1]; 27 if (root) return root; 28 } 29 throw new Error(`${url}'s sample map names no /@fs/…/samples/ file, so which checkout it serves is unknown`); 30}
[samples/<sound>/<file>, absolute path] for every sample file in root.
33function samplesIn(root) { 34 const dir = join(root, 'samples'); 35 const isDir = (p) => statSync(p).isDirectory(); 36 return readdirSync(dir) 37 .filter((sound) => isDir(join(dir, sound))) 38 .flatMap((sound) => 39 readdirSync(join(dir, sound)) 40 .filter((file) => SAMPLE_EXTENSIONS.includes(extname(file).slice(1))) 41 .map((file) => [`samples/${sound}/${file}`, join(dir, sound, file)]), 42 ); 43}
null when the dev server at url serves root itself; otherwise
{ served, root, sounds, route(page) }, served being the checkout the
server has, and route making a page hear root's samples instead.
48export async function worktreeSamples({ url, root }) { 49 const served = realpathSync(await servedRoot(url)); 50 root = realpathSync(root); 51 if (served === root) return null; 52 const files = samplesIn(root); 53 const map = sampleMap(files.map(([rel]) => [rel, `/@fs${root}/${rel}`])); 54 const prefixes = [served, root].map((r) => `/@fs${r}/`); 55 const local = (requestUrl) => { 56 const path = decodeURIComponent(new URL(requestUrl).pathname); 57 const prefix = prefixes.find((p) => path.startsWith(`${p}samples/`)); 58 return prefix && join(root, path.slice(prefix.length)); 59 }; 60 return { 61 served, 62 root, 63 sounds: Object.keys(map).length - 1, 64 async route(page) { 65 await page.route('**/jev-samples/strudel.json', (route) => route.fulfill({ json: map })); 66 await page.route( 67 (u) => Boolean(local(u.href)), 68 (route) => { 69 const file = local(route.request().url()); 70 if (!existsSync(file)) return route.fulfill({ status: 404, body: `not in ${root}/samples` }); 71 return route.fulfill({ path: file }); 72 }, 73 ); 74 }, 75 }; 76}