Share the one HTTP envelope and the one byte formatter

Both stores carried their own ~28-line request<T>, and formatBytes existed
twice – the second copy had lost the "B" branch, so a small sprite would have
read as 0 KB had its caller ever passed one under a kilobyte.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
rootandClaude Opus 5 committed 2026-09-10 07:14:23 +02:00
1 parent 787a19d525
commit b13b130da7
11 files changed
+80 -78

No files matched your search

+2 -22
View File
@@ -1,7 +1,6 @@
import { statusMessage } from './http';
import { apiRequest } from './http';
import type { StoredTexture, TextureStore, UploadedTexture } from './TextureStore';
/** Routing goes through the `r` query parameter because nginx does not pass PATH_INFO to PHP. */
export class HttpTextureStore implements TextureStore {
constructor(private readonly endpoint: string) {}
@@ -22,28 +21,9 @@ export class HttpTextureStore implements TextureStore {
route: string,
payload?: { bytes: Blob | ArrayBuffer; type: string },
): Promise<T> {
const url = `${this.endpoint}?r=${encodeURIComponent(route)}`;
const response = await fetch(url, {
method,
return apiRequest<T>(this.endpoint, method, route, {
headers: payload ? { 'Content-Type': payload.type } : {},
body: payload?.bytes,
});
if (response.status === 204) return undefined as T;
const text = await response.text();
let data: unknown;
try {
data = text ? JSON.parse(text) : null;
} catch {
// An upload is the request nginx refuses before PHP sees it, answering with an HTML page,
// so a failure is explained from the status instead.
if (response.ok) throw new Error(`API ${method} ${route}: invalid JSON (${response.status})`);
data = null;
}
if (!response.ok) {
const message =
(data as { error?: string } | null)?.error ?? statusMessage(response.status, response.statusText);
throw new Error(`API ${method} ${route}: ${message} (${response.status})`);
}
return data as T;
}
}