or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

examples

edge-cases.mdreal-world-scenarios.md
index.md
tile.json

edge-cases.mddocs/examples/

Edge Cases and Advanced Scenarios

Advanced patterns and edge cases for SvelteKit applications.

Load Function Edge Cases

Handling Race Conditions

// Prevent race conditions with AbortController
export async function load({ fetch, url }) {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), 5000);
  
  try {
    const response = await fetch(`/api/data?q=${url.searchParams.get('q')}`, {
      signal: controller.signal
    });
    return { data: await response.json() };
  } catch (e) {
    if (e.name === 'AbortError') {
      return { data: null, timeout: true };
    }
    throw e;
  } finally {
    clearTimeout(timeoutId);
  }
}

Conditional Data Loading

// Only load data if certain conditions are met
export async function load({ url, depends }) {
  const shouldLoad = url.searchParams.get('load') === 'true';
  
  if (!shouldLoad) {
    depends('app:data');
    return {};
  }
  
  const data = await fetchData();
  return { data };
}

Untracking Dependencies

// Prevent specific reads from triggering reruns
export async function load({ url, untrack }) => {
  const filter = url.searchParams.get('filter');
  
  // This won't trigger rerun when stable param changes
  const stable = untrack(() => url.searchParams.get('stable'));
  
  return { filter, stable };
}

Form Action Edge Cases

Handling Large File Uploads

// src/routes/upload/+page.server.ts
import { fail } from '@sveltejs/kit';

export const actions = {
  upload: async ({ request }) => {
    const data = await request.formData();
    const file = data.get('file') as File;
    
    // Stream large files
    if (file.size > 100 * 1024 * 1024) {
      const stream = file.stream();
      const url = await streamToStorage(stream);
      return { url };
    }
    
    // Handle smaller files in memory
    const buffer = await file.arrayBuffer();
    const url = await uploadBuffer(buffer);
    return { url };
  }
};

Form Validation with Custom Rules

// Complex validation logic
export const actions = {
  register: async ({ request }) => {
    const data = await request.formData();
    const email = data.get('email');
    const password = data.get('password');
    const confirmPassword = data.get('confirmPassword');
    
    const issues = [];
    
    if (!email || !isValidEmail(email)) {
      issues.push({ path: ['email'], message: 'Invalid email' });
    }
    
    if (password !== confirmPassword) {
      issues.push({ path: ['password'], message: 'Passwords do not match' });
      issues.push({ path: ['confirmPassword'], message: 'Passwords do not match' });
    }
    
    if (issues.length > 0) {
      invalid(...issues);
    }
    
    // Continue with registration
  }
};

Navigation Edge Cases

Handling Navigation Cancellation

import { beforeNavigate } from '$app/navigation';

let hasUnsavedChanges = false;

beforeNavigate(({ cancel }) => {
  if (hasUnsavedChanges) {
    if (!confirm('You have unsaved changes. Leave anyway?')) {
      cancel();
    }
  }
});

Deep Linking with State

// Restore application state from URL
export async function load({ url, parent }) {
  const stateParam = url.searchParams.get('state');
  
  if (stateParam) {
    const state = JSON.parse(decodeURIComponent(stateParam));
    return { restoredState: state };
  }
  
  return {};
}

Error Handling Edge Cases

Retry Logic

// Retry failed requests
async function loadWithRetry(fetch: typeof fetch, url: string, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch(url);
      if (response.ok) return await response.json();
      throw new Error(`HTTP ${response.status}`);
    } catch (e) {
      if (i === maxRetries - 1) throw e;
      await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
    }
  }
}

export async function load({ fetch }) {
  const data = await loadWithRetry(fetch, '/api/unreliable');
  return { data };
}

Graceful Degradation

// Fallback when primary data source fails
export async function load({ fetch }) {
  try {
    const data = await fetch('/api/primary').then(r => r.json());
    return { data, source: 'primary' };
  } catch (e) {
    const fallback = await fetch('/api/fallback').then(r => r.json());
    return { data: fallback, source: 'fallback' };
  }
}

Server Hooks Edge Cases

Conditional Hook Execution

// src/hooks.server.ts
import { sequence } from '@sveltejs/kit/hooks';
import type { Handle } from '@sveltejs/kit';

const auth: Handle = async ({ event, resolve }) => {
  if (event.url.pathname.startsWith('/api')) {
    // Skip auth for public API routes
    if (event.url.pathname.startsWith('/api/public')) {
      return resolve(event);
    }
  }
  
  // Apply auth for protected routes
  const token = event.cookies.get('token');
  if (!token) {
    return new Response('Unauthorized', { status: 401 });
  }
  
  return resolve(event);
};

export const handle = sequence(auth);

Request Transformation

// Transform requests before processing
export const handle: Handle = async ({ event, resolve }) => {
  // Rewrite old API paths
  if (event.url.pathname.startsWith('/api/v1')) {
    event.url.pathname = event.url.pathname.replace('/api/v1', '/api/v2');
  }
  
  return resolve(event);
};

Environment Variable Edge Cases

Runtime Environment Detection

// Handle different environments
import { env } from '$env/dynamic/private';
import { dev } from '$app/environment';

const config = {
  apiUrl: dev 
    ? 'http://localhost:3000'
    : env.PRODUCTION_API_URL || 'https://api.example.com',
  features: {
    analytics: env.ENABLE_ANALYTICS === 'true',
    debug: dev
  }
};

Remote Functions Edge Cases

Optimistic Updates

// Server: src/lib/server/commands.ts
import { command } from '$app/server';
import { getPost } from './queries';

export const updatePost = command('unchecked', async (data: { id: string; title: string }) => {
  await db.posts.update(data.id, { title: data.title });
  return { success: true };
});

// Client: Use with optimistic update
import { updatePost } from '$lib/server/commands';
import { getPost } from '$lib/server/queries';

const post = getPost('post-123');

await updatePost({ id: 'post-123', title: 'New Title' })
  .updates(post.withOverride((current) => ({ ...current, title: 'New Title' })));

Batch Operations

// Batch multiple operations
import { query } from '$app/server';

export const getUsers = query.batch('unchecked', async (userIds: string[]) => {
  const users = await db.users.findMany(userIds);
  return (userId, idx) => users[idx];
});

// Client automatically batches concurrent calls
const [user1, user2, user3] = await Promise.all([
  getUsers('id-1'),
  getUsers('id-2'),
  getUsers('id-3')
]);
// Only one server request is made!

Performance Optimization

Code Splitting

// Lazy load heavy components
<script>
  import { onMount } from 'svelte';
  
  let HeavyComponent;
  
  onMount(async () => {
    HeavyComponent = (await import('./HeavyComponent.svelte')).default;
  });
</script>

{#if HeavyComponent}
  <svelte:component this={HeavyComponent} />
{/if}

Data Prefetching

// Prefetch data on hover
import { preloadData } from '$app/navigation';

function handleMouseEnter(href: string) {
  preloadData(href);
}

See Also

  • Real-World Scenarios - Common patterns
  • Load Functions Reference
  • Forms Reference
  • Remote Functions Reference