supabase-local #15

Merged
erman merged 20 commits from supabase-local into main 2025-07-08 17:34:14 +02:00
4 changed files with 66 additions and 52 deletions
Showing only changes of commit c248e4e074 - Show all commits

View File

@@ -26,7 +26,6 @@ export function getOAuthClient() {
* @returns Auth URL for Google OAuth * @returns Auth URL for Google OAuth
*/ */
export function createAuthUrl() { export function createAuthUrl() {
console.warn("CREATE AUTH URL");
return getOAuthClient().generateAuthUrl({ return getOAuthClient().generateAuthUrl({
access_type: 'offline', access_type: 'offline',
prompt: 'consent', prompt: 'consent',

View File

@@ -64,34 +64,29 @@ export const GET: RequestHandler = async ({ url }) => {
<script> <script>
(function() { (function() {
try { try {
// Store tokens in the parent window's localStorage // Store tokens in localStorage (same origin)
if (window.opener && !window.opener.closed) { localStorage.setItem('google_access_token', '${tokens.access_token}');
window.opener.localStorage.setItem('google_access_token', '${tokens.access_token}'); localStorage.setItem('google_refresh_token', '${tokens.refresh_token}');
window.opener.localStorage.setItem('google_refresh_token', '${tokens.refresh_token}'); // Set timestamp that the main application will detect
localStorage.setItem('google_auth_timestamp', Date.now().toString());
// Send success message to parent
window.opener.postMessage({ // Update UI to show success
type: 'GOOGLE_AUTH_SUCCESS', document.querySelector('.loading').textContent = 'Authentication complete! This window will close automatically.';
tokens: {
accessToken: '${tokens.access_token}', // Close window after a short delay
refreshToken: '${tokens.refresh_token}' setTimeout(() => {
} try {
}, '*');
// Close the popup after a short delay to ensure message is received
setTimeout(() => {
window.close(); window.close();
}, 500); } catch (e) {
} else { // If we can't close automatically, update message
// If no opener, close immediately document.querySelector('.loading').textContent = 'Authentication complete! You can close this window now.';
window.close(); }
} }, 1500);
} catch (error) { } catch (error) {
console.error('Error in auth callback:', error); console.error('Error in auth callback:', error);
// Try to close the window anyway // Update UI to show error
setTimeout(() => { document.querySelector('.success').textContent = '✗ Authentication error';
window.close(); document.querySelector('.loading').textContent = 'Please close this window and try again.';
}, 1000);
} }
})(); })();
</script> </script>

View File

@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { isTokenValid, getUserInfo, revokeToken } from '$lib/google/auth/client.js'; import { isTokenValid, getUserInfo, revokeToken } from '$lib/google/auth/client.js';
import type { GoogleSheet } from '$lib/google/sheets/client.js'; import type { GoogleSheet } from '$lib/google/sheets/types.ts';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
// Import Components // Import Components
@@ -124,35 +124,49 @@
let popupTimer: number | null = null; let popupTimer: number | null = null;
let cancelTimeout: number | null = null; let cancelTimeout: number | null = null;
// Listen for messages from the popup // Store current timestamp to detect changes in localStorage
const messageHandler = (event: MessageEvent) => { const startTimestamp = localStorage.getItem('google_auth_timestamp') || '0';
if (event.data?.type === 'GOOGLE_AUTH_SUCCESS') {
authCompleted = true; // Poll localStorage for auth completion
authData.connecting = false; const pollInterval = setInterval(() => {
authData.showCancelOption = false; try {
window.removeEventListener('message', messageHandler); const currentTimestamp = localStorage.getItem('google_auth_timestamp');
// Clean up timers // If timestamp has changed, auth is complete
if (popupTimer) clearTimeout(popupTimer); if (currentTimestamp && currentTimestamp !== startTimestamp) {
if (cancelTimeout) clearTimeout(cancelTimeout); handleAuthSuccess();
}
// Check auth status again after success } catch (e) {
setTimeout(checkGoogleAuth, 100); console.error('Error checking auth timestamp:', e);
} }
}; }, 500); // Poll every 500ms
// Common handler for authentication success
function handleAuthSuccess() {
if (authCompleted) return; // Prevent duplicate handling
authCompleted = true;
authData.connecting = false;
authData.showCancelOption = false;
// Clean up timers
clearInterval(pollInterval);
if (popupTimer) clearTimeout(popupTimer);
if (cancelTimeout) clearTimeout(cancelTimeout);
// Update auth state
setTimeout(checkGoogleAuth, 100);
}
// Clean up function to handle all cleanup in one place // Clean up function to handle all cleanup in one place
const cleanUp = () => { const cleanUp = () => {
window.removeEventListener('message', messageHandler); clearInterval(pollInterval);
if (popupTimer) clearTimeout(popupTimer); if (popupTimer) clearTimeout(popupTimer);
if (cancelTimeout) clearTimeout(cancelTimeout); if (cancelTimeout) clearTimeout(cancelTimeout);
authData.connecting = false; authData.connecting = false;
}; };
window.addEventListener('message', messageHandler); // Set a timeout for initial auth check
// Set a timeout to check auth status regardless of popup state
// This is a workaround for Cross-Origin-Opener-Policy restrictions
popupTimer = setTimeout(() => { popupTimer = setTimeout(() => {
// Only check if auth isn't already completed // Only check if auth isn't already completed
if (!authCompleted) { if (!authCompleted) {
@@ -160,21 +174,21 @@
// Check if tokens were stored by the popup before it was closed // Check if tokens were stored by the popup before it was closed
setTimeout(checkGoogleAuth, 100); setTimeout(checkGoogleAuth, 100);
} }
}, 60 * 1000) as unknown as number; }, 30 * 1000) as unknown as number; // Reduced from 60s to 30s
// After 20 seconds with no response, show cancel option // Show cancel option sooner
cancelTimeout = setTimeout(() => { cancelTimeout = setTimeout(() => {
if (!authCompleted) { if (!authCompleted) {
authData.showCancelOption = true; authData.showCancelOption = true;
} }
}, 20 * 1000) as unknown as number; }, 10 * 1000) as unknown as number; // Reduced from 20s to 10s
// Set a final timeout to clean up everything if nothing else worked // Final cleanup timeout
setTimeout(() => { setTimeout(() => {
if (!authCompleted) { if (!authCompleted) {
cleanUp(); cleanUp();
} }
}, 3 * 60 * 1000); // 3 minute max timeout }, 60 * 1000); // Reduced from 3min to 1min
} catch (error) { } catch (error) {
console.error('Error connecting to Google:', error); console.error('Error connecting to Google:', error);

View File

@@ -36,6 +36,12 @@ self.addEventListener('fetch', (event) => {
async function respond() { async function respond() {
const url = new URL(event.request.url); const url = new URL(event.request.url);
// Skip caching for auth routes
if (url.pathname.startsWith('/auth/')) {
return fetch(event.request);
}
const cache = await caches.open(CACHE); const cache = await caches.open(CACHE);
// `build`/`files` can always be served from the cache // `build`/`files` can always be served from the cache