Skip to content

Commit bef296b

Browse files
committed
feat: enhance error handling by implementing fetchAllowNotFound for expected 404 responses
1 parent b83c059 commit bef296b

1 file changed

Lines changed: 31 additions & 16 deletions

File tree

src/storage/repo/repo-client.ts

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ export class RepoStorageBackend implements StorageBackend {
7878

7979
public async exists(): Promise<boolean> {
8080
try {
81-
const res = await this.fetch(`/contents/${SYNC_DIR}/manifest.json`);
82-
return res.ok;
81+
const res = await this.fetchAllowNotFound(`/contents/${SYNC_DIR}/manifest.json`);
82+
return res?.ok ?? false;
8383
} catch (error) {
8484
// 404 means file doesn't exist, which is expected for new repos
8585
if (error instanceof RepoApiError && error.status === 404) {
@@ -99,8 +99,8 @@ export class RepoStorageBackend implements StorageBackend {
9999

100100
public async getFile(path: string): Promise<string | null> {
101101
const fullPath = `${SYNC_DIR}/${path}`;
102-
const res = await this.fetch(`/contents/${fullPath}`);
103-
if (!res.ok) return null;
102+
const res = await this.fetchAllowNotFound(`/contents/${fullPath}`);
103+
if (!res?.ok) return null;
104104

105105
const data = (await res.json()) as ContentFile;
106106

@@ -148,8 +148,8 @@ export class RepoStorageBackend implements StorageBackend {
148148
}
149149

150150
public async listFiles(): Promise<StorageFile[]> {
151-
const res = await this.fetch(`/contents/${SYNC_DIR}`);
152-
if (!res.ok) return [];
151+
const res = await this.fetchAllowNotFound(`/contents/${SYNC_DIR}`);
152+
if (!res?.ok) return [];
153153

154154
const data = (await res.json()) as ContentFile[];
155155
return data.map((f) => ({
@@ -177,6 +177,21 @@ export class RepoStorageBackend implements StorageBackend {
177177
return fetchWithRetry(url, opts, this.maxRetries, this.retryDelayMs);
178178
}
179179

180+
/**
181+
* Fetch that returns null for 404 instead of throwing.
182+
* Use this for operations where "not found" is an expected valid result.
183+
*/
184+
private async fetchAllowNotFound(path: string, options?: RequestInit): Promise<Response | null> {
185+
try {
186+
return await this.fetch(path, options);
187+
} catch (error) {
188+
if (error instanceof RepoApiError && error.status === 404) {
189+
return null;
190+
}
191+
throw error;
192+
}
193+
}
194+
180195
private async createOrUpdateFile(path: string, content: string, message: string): Promise<void> {
181196
// Get current file SHA if exists (404 means file doesn't exist yet)
182197
let sha: string | undefined;
@@ -223,14 +238,14 @@ export class RepoStorageBackend implements StorageBackend {
223238
}
224239

225240
// Auto-detect: try main first, then master
226-
const res = await this.fetch('/git/ref/heads/main');
227-
if (res.ok) {
241+
const res = await this.fetchAllowNotFound('/git/ref/heads/main');
242+
if (res?.ok) {
228243
this.detectedBranch = 'main';
229244
return 'main';
230245
}
231246

232-
const masterRes = await this.fetch('/git/ref/heads/master');
233-
if (masterRes.ok) {
247+
const masterRes = await this.fetchAllowNotFound('/git/ref/heads/master');
248+
if (masterRes?.ok) {
234249
this.detectedBranch = 'master';
235250
return 'master';
236251
}
@@ -240,8 +255,8 @@ export class RepoStorageBackend implements StorageBackend {
240255
}
241256

242257
private async branchExists(branch: string): Promise<boolean> {
243-
const res = await this.fetch(`/git/ref/heads/${branch}`);
244-
return res.ok;
258+
const res = await this.fetchAllowNotFound(`/git/ref/heads/${branch}`);
259+
return res?.ok ?? false;
245260
}
246261

247262
private async createBranch(branch: string): Promise<void> {
@@ -276,11 +291,11 @@ export class RepoStorageBackend implements StorageBackend {
276291

277292
/** Detect default branch without creating - used as base for new branches */
278293
private async detectDefaultBranch(): Promise<'main' | 'master'> {
279-
const res = await this.fetch('/git/ref/heads/main');
280-
if (res.ok) return 'main';
294+
const res = await this.fetchAllowNotFound('/git/ref/heads/main');
295+
if (res?.ok) return 'main';
281296

282-
const masterRes = await this.fetch('/git/ref/heads/master');
283-
if (masterRes.ok) return 'master';
297+
const masterRes = await this.fetchAllowNotFound('/git/ref/heads/master');
298+
if (masterRes?.ok) return 'master';
284299

285300
return 'main';
286301
}

0 commit comments

Comments
 (0)