From 8141bd624ba872acec7bce47e1bc0d20d5185ac0 Mon Sep 17 00:00:00 2001 From: Josh Creek <8179928+jcreek@users.noreply.github.com> Date: Sat, 24 Jan 2026 17:18:57 +0000 Subject: [PATCH] refactor(#89): Address PR comments --- .../export-integrations/[provider]/+server.ts | 3 +++ .../integrations/dropbox/connect/+server.ts | 5 +++- .../google-drive/callback/+server.ts | 25 ++++++++++------- .../google-drive/connect/+server.ts | 5 +++- src/routes/backup-settings/+page.svelte | 2 ++ src/routes/pokedex/[id]/+page.svelte | 27 ++++++++++++++++++- 6 files changed, 54 insertions(+), 13 deletions(-) diff --git a/src/routes/api/export-integrations/[provider]/+server.ts b/src/routes/api/export-integrations/[provider]/+server.ts index d6316a9..5afeeee 100644 --- a/src/routes/api/export-integrations/[provider]/+server.ts +++ b/src/routes/api/export-integrations/[provider]/+server.ts @@ -26,6 +26,9 @@ export const PUT = async (event: RequestEvent) => { const patch: Record = {}; if (body.folderId !== undefined) patch.folderId = body.folderId; if (body.path !== undefined) patch.path = body.path; + if (Object.keys(patch).length === 0) { + return json({ error: 'No fields to update' }, { status: 400 }); + } const { data, error } = await event.locals.supabase .from('pokedex_export_integrations') diff --git a/src/routes/api/integrations/dropbox/connect/+server.ts b/src/routes/api/integrations/dropbox/connect/+server.ts index 83e7065..904fbb6 100644 --- a/src/routes/api/integrations/dropbox/connect/+server.ts +++ b/src/routes/api/integrations/dropbox/connect/+server.ts @@ -31,7 +31,10 @@ export const GET = async (event: RequestEvent) => { const env = getEnv(); const clientId = env.DROPBOX_OAUTH_CLIENT_ID; if (!clientId) { - throw redirect(302, `/pokedex/${pokedexId}?export=dropbox-missing-client`); + const missingClientRedirect = pokedexId + ? `/pokedex/${pokedexId}?export=dropbox-missing-client` + : '/pokedex?export=dropbox-missing-client'; + throw redirect(302, missingClientRedirect); } const state = createOAuthState(); diff --git a/src/routes/api/integrations/google-drive/callback/+server.ts b/src/routes/api/integrations/google-drive/callback/+server.ts index 2e8ad24..d22dba0 100644 --- a/src/routes/api/integrations/google-drive/callback/+server.ts +++ b/src/routes/api/integrations/google-drive/callback/+server.ts @@ -89,16 +89,21 @@ export const GET = async (event: RequestEvent) => { const fileName = oauthState.fileName?.trim() ? oauthState.fileName : null; const folderId = oauthState.folderId?.trim() ? oauthState.folderId : null; - await repo.upsert({ - provider: 'google_drive', - enabled: true, - fileName, - folderId, - accessToken: tokenData.access_token, - refreshToken: tokenData.refresh_token ?? null, - accessTokenExpiresAt: expiresAt, - metadata: tokenData.scope ? { scope: tokenData.scope } : null - }); + try { + await repo.upsert({ + provider: 'google_drive', + enabled: true, + fileName, + folderId, + accessToken: tokenData.access_token, + refreshToken: tokenData.refresh_token ?? null, + accessTokenExpiresAt: expiresAt, + metadata: tokenData.scope ? { scope: tokenData.scope } : null + }); + } catch (saveError) { + console.error('Google Drive integration save failed:', saveError); + throw redirect(302, `${returnTo}-error`); + } throw redirect(302, `${returnTo}-connected`); } catch (err) { diff --git a/src/routes/api/integrations/google-drive/connect/+server.ts b/src/routes/api/integrations/google-drive/connect/+server.ts index e245949..2098752 100644 --- a/src/routes/api/integrations/google-drive/connect/+server.ts +++ b/src/routes/api/integrations/google-drive/connect/+server.ts @@ -31,7 +31,10 @@ export const GET = async (event: RequestEvent) => { const env = getEnv(); const clientId = env.GOOGLE_OAUTH_CLIENT_ID; if (!clientId) { - throw redirect(302, `/pokedex/${pokedexId}?export=google-missing-client`); + const missingClientRedirect = pokedexId + ? `/pokedex/${pokedexId}?export=google-missing-client` + : '/pokedex?export=google-missing-client'; + throw redirect(302, missingClientRedirect); } const state = createOAuthState(); diff --git a/src/routes/backup-settings/+page.svelte b/src/routes/backup-settings/+page.svelte index 23a0a19..3268345 100644 --- a/src/routes/backup-settings/+page.svelte +++ b/src/routes/backup-settings/+page.svelte @@ -121,6 +121,7 @@ Open Drive folder @@ -156,6 +157,7 @@ Open Dropbox folder diff --git a/src/routes/pokedex/[id]/+page.svelte b/src/routes/pokedex/[id]/+page.svelte index d6767cf..90d1f68 100644 --- a/src/routes/pokedex/[id]/+page.svelte +++ b/src/routes/pokedex/[id]/+page.svelte @@ -64,6 +64,21 @@ let exportInFlightGeneration = 0; let toggleFlushTimer: ReturnType | null = null; + function resetExportState() { + if (exportTimer) { + clearTimeout(exportTimer); + exportTimer = null; + } + if (toggleFlushTimer) { + clearTimeout(toggleFlushTimer); + toggleFlushTimer = null; + } + exportAfterFlush = false; + exportInFlight = false; + exportGeneration = 0; + exportInFlightGeneration = 0; + } + function scheduleExportIfIdle() { if (!browser) return; if (!pokedexId) return; @@ -77,10 +92,15 @@ exportInFlight = true; exportInFlightGeneration = exportGeneration; try { - await fetch(`/api/pokedexes/${pokedexId}/export`, { + const response = await fetch(`/api/pokedexes/${pokedexId}/export`, { method: 'POST', credentials: 'include' }); + if (!response.ok) { + const body = await response.text().catch(() => ''); + console.error('Auto-export failed:', response.status, body); + return; + } if (exportGeneration === exportInFlightGeneration) { exportAfterFlush = false; } @@ -121,6 +141,9 @@ catchWriteQueueUnsubscribe?.(); catchWriteQueueUnsubscribe = null; }); + onDestroy(() => { + resetExportState(); + }); function openPokemonModal(pokemon: CombinedData) { selectedPokemon = pokemon; @@ -139,6 +162,8 @@ const desiredKey = `${localUser.id}:${pokedexId}`; if (catchWriteQueue && catchWriteQueueKey === desiredKey) return; + resetExportState(); + // Unsubscribe from the previous queue's status store before replacing the queue. catchWriteQueueUnsubscribe?.(); catchWriteQueueUnsubscribe = null;