CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-nuxt

Nuxt is a free and open-source framework with an intuitive and extendable way to create type-safe, performant and production-grade full-stack web applications and websites with Vue.js.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

data-fetching.mddocs/

Data Fetching

Comprehensive data fetching system with server-side rendering support, caching, loading states, and error handling. Nuxt provides powerful composables for fetching data with automatic SSR hydration, request deduplication, and reactive updates.

Note: Examples use $fetch, which is Nuxt's built-in fetch utility available globally in Nuxt applications. For external usage, import it from 'ofetch'.

Capabilities

Async Data

Handle asynchronous data fetching with caching, loading states, and error handling.

/**
 * Handle asynchronous data fetching with caching and loading states
 * @param key - Unique key for caching the data
 * @param handler - Function that returns a Promise resolving to the data
 * @param options - Configuration options for the async data
 * @returns AsyncData object with data, pending, error, and refresh properties
 */
function useAsyncData<DataT, ErrorT = Error>(
  key: string,
  handler: () => Promise<DataT>,
  options?: AsyncDataOptions<DataT>
): AsyncData<DataT, ErrorT>;

/**
 * Lazy version of useAsyncData that doesn't block navigation
 * @param key - Unique key for caching the data
 * @param handler - Function that returns a Promise resolving to the data
 * @param options - Configuration options for the async data
 * @returns AsyncData object with data, pending, error, and refresh properties
 */
function useLazyAsyncData<DataT, ErrorT = Error>(
  key: string,
  handler: () => Promise<DataT>,
  options?: AsyncDataOptions<DataT>
): AsyncData<DataT, ErrorT>;

interface AsyncData<DataT, ErrorT> {
  /** The fetched data */
  data: Ref<DataT | null>;
  /** Whether the data is being fetched */
  pending: Ref<boolean>;
  /** Any error that occurred during fetching */
  error: Ref<ErrorT | null>;
  /** Function to refresh the data */
  refresh: () => Promise<void>;
  /** Function to execute the handler */
  execute: () => Promise<void>;
  /** Current request status */
  status: Ref<AsyncDataRequestStatus>;
}

interface AsyncDataOptions<ResT, DataT = ResT, PickKeys extends KeysOf<DataT> = KeysOf<DataT>, DefaultT = null> {
  /** Whether to fetch on server-side */
  server?: boolean;
  /** Whether to fetch on client-side */  
  client?: boolean;
  /** Whether to use lazy loading (non-blocking) */
  lazy?: boolean;
  /** Whether to fetch immediately */
  immediate?: boolean;
  /** Default value factory */
  default?: () => DefaultT | Ref<DefaultT>;
  /** Transform function for the data */
  transform?: (input: ResT) => DataT;
  /** Keys to pick from the result */
  pick?: PickKeys[];
  /** Reactive sources to watch for changes */
  watch?: MultiWatchSources;
  /** Whether to perform deep watching */
  deep?: boolean;
  /** Whether to dedupe identical requests */
  dedupe?: "cancel" | "defer";
}

type AsyncDataRequestStatus = "idle" | "pending" | "success" | "error";

Usage Examples:

// Basic async data
const { data: users, pending, error } = await useAsyncData("users", () => 
  $fetch("/api/users")
);

// With options
const { data: posts, refresh } = await useAsyncData(
  "posts", 
  () => $fetch("/api/posts"),
  {
    server: true,
    client: false,
    default: () => [],
    transform: (data: any[]) => data.slice(0, 10)
  }
);

// Lazy loading (non-blocking)
const { data: comments } = await useLazyAsyncData(
  "comments",
  () => $fetch(`/api/posts/${route.params.id}/comments`)
);

// With reactive dependencies
const route = useRoute();
const { data: product } = await useAsyncData(
  `product-${route.params.id}`,
  () => $fetch(`/api/products/${route.params.id}`),
  {
    watch: [() => route.params.id]
  }
);

// Transform and pick data
const { data: userProfile } = await useAsyncData(
  "profile",
  () => $fetch("/api/user/profile"),
  {
    pick: ["id", "name", "email"],
    transform: (user: any) => ({
      ...user,
      displayName: `${user.firstName} ${user.lastName}`
    })
  }
);

Fetch Utilities

Fetch data from API endpoints with SSR support and request optimization.

/**
 * Fetch data from an API endpoint with SSR support
 * @param request - URL string, Request object, or reactive reference
 * @param opts - Fetch and async data options
 * @returns AsyncData with fetched data
 */
function useFetch<ResT = any, ErrorT = FetchError>(
  request: string | Request | Ref<string | Request> | (() => string | Request),
  opts?: UseFetchOptions<ResT>
): AsyncData<ResT, ErrorT>;

/**
 * Lazy version of useFetch that doesn't block navigation
 * @param request - URL string, Request object, or reactive reference
 * @param opts - Fetch and async data options
 * @returns AsyncData with fetched data
 */
function useLazyFetch<ResT = any, ErrorT = FetchError>(
  request: string | Request | Ref<string | Request> | (() => string | Request),
  opts?: UseFetchOptions<ResT>
): AsyncData<ResT, ErrorT>;

interface UseFetchOptions<ResT = any, DataT = ResT, PickKeys extends KeysOf<DataT> = KeysOf<DataT>, DefaultT = null, R extends NitroFetchRequest = string, M extends AvailableRouterMethod<R> = AvailableRouterMethod<R>> extends AsyncDataOptions<ResT, DataT, PickKeys, DefaultT>, FetchOptions<R, M> {
  /** Request method */
  method?: M;
  /** Request body */
  body?: RequestInit["body"] | Record<string, any>;
  /** Request headers */
  headers?: Record<string, string> | [key: string, value: string][] | Headers;
  /** Query parameters */
  query?: SearchParams;
  /** Request parameters */
  params?: SearchParams;
  /** Base URL for the request */
  baseURL?: string;
  /** Request timeout in milliseconds */
  timeout?: number;
  /** Request retry configuration */
  retry?: number | false;
  /** Whether to retry on status codes */
  retryStatusCodes?: number[];
  /** Delay between retries */
  retryDelay?: number;
  /** Request interceptors */
  onRequest?: (context: FetchContext) => Promise<void> | void;
  /** Request error handlers */
  onRequestError?: (context: FetchContext & { error: FetchError }) => Promise<void> | void;
  /** Response interceptors */
  onResponse?: (context: FetchContext & { response: FetchResponse<ResT> }) => Promise<void> | void;
  /** Response error handlers */
  onResponseError?: (context: FetchContext & { response: FetchResponse<ResT> }) => Promise<void> | void;
}

Usage Examples:

// Basic fetch
const { data: users } = await useFetch("/api/users");

// With method and body
const { data: newUser } = await useFetch("/api/users", {
  method: "POST",
  body: { name: "John", email: "john@example.com" }
});

// With query parameters
const { data: products } = await useFetch("/api/products", {
  query: { category: "electronics", limit: 20 }
});

// Reactive URL
const route = useRoute();
const { data: user } = await useFetch(() => `/api/users/${route.params.id}`);

// With headers and interceptors
const { data, error } = await useFetch("/api/protected", {
  headers: {
    Authorization: `Bearer ${token}`
  },
  onRequest({ request, options }) {
    console.log("Making request to:", request);
  },
  onResponse({ response }) {
    console.log("Response status:", response.status);
  },
  onResponseError({ response }) {
    console.error("Request failed:", response.status);
  }
});

// Lazy fetch with transform
const { data: processedData } = await useLazyFetch("/api/raw-data", {
  transform: (data: any[]) => data.map(item => ({
    id: item.id,
    title: item.title.toUpperCase(),
    createdAt: new Date(item.created_at)
  }))
});

Data Management

Manage and refresh cached async data.

/**
 * Get existing async data by key
 * @param key - The key used when calling useAsyncData
 * @returns Object with data reference
 */
function useNuxtData<DataT = any>(key: string): {
  data: Ref<DataT | null>;
};

/**
 * Refresh cached async data by key(s)
 * @param keys - Optional key or keys to refresh, refreshes all if not provided
 * @returns Promise resolving when refresh is complete
 */
function refreshNuxtData(keys?: string | string[]): Promise<void>;

/**
 * Clear cached async data
 * @param keys - Keys to clear or filter function
 */
function clearNuxtData(keys?: string | string[] | ((key: string) => boolean)): void;

Usage Examples:

// Access existing data
const { data: users } = useNuxtData("users");

// Refresh specific data
await refreshNuxtData("users");

// Refresh multiple keys
await refreshNuxtData(["users", "posts"]);

// Refresh all data
await refreshNuxtData();

// Clear specific data
clearNuxtData("users");

// Clear multiple keys
clearNuxtData(["users", "posts"]);

// Clear with filter
clearNuxtData((key) => key.startsWith("user-"));

// Manual refresh with useAsyncData
const { data: posts, refresh } = await useAsyncData("posts", () => 
  $fetch("/api/posts")
);

// Refresh this specific data
await refresh();

Advanced Data Fetching Patterns

// Dependent data fetching
const { data: user } = await useAsyncData("user", () => 
  $fetch("/api/user")
);

const { data: userPosts } = await useAsyncData(
  "user-posts",
  () => $fetch(`/api/users/${user.value?.id}/posts`),
  {
    // Only fetch when user is available
    server: false,
    watch: [user],
    immediate: false
  }
);

// Conditional fetching
const route = useRoute();
const shouldFetch = computed(() => route.name === "dashboard");

const { data: analytics } = await useAsyncData(
  "analytics",
  () => $fetch("/api/analytics"),
  {
    server: shouldFetch.value,
    client: shouldFetch.value
  }
);

// Polling data
const { data: liveData, refresh } = await useAsyncData(
  "live-data",
  () => $fetch("/api/live-data")
);

// Set up polling
const { pause, resume } = useIntervalFn(async () => {
  await refresh();
}, 5000);

// Optimistic updates
const { data: todos, refresh } = await useAsyncData("todos", () => 
  $fetch("/api/todos")
);

async function addTodo(newTodo: Todo) {
  // Optimistically update
  todos.value = [...(todos.value || []), { ...newTodo, id: Date.now() }];
  
  try {
    await $fetch("/api/todos", {
      method: "POST",
      body: newTodo
    });
    // Refresh to get server state
    await refresh();
  } catch (error) {
    // Revert on error
    await refresh();
    throw error;
  }
}

Error Handling

// Basic error handling
const { data, error, pending } = await useAsyncData("users", async () => {
  try {
    return await $fetch("/api/users");
  } catch (err) {
    throw createError({
      statusCode: 500,
      statusMessage: "Failed to fetch users"
    });
  }
});

// Global error handling
const { data: posts } = await useFetch("/api/posts", {
  onResponseError({ response }) {
    if (response.status === 401) {
      throw createError({
        statusCode: 401,
        statusMessage: "Unauthorized"
      });
    }
  }
});

// Retry logic
const { data: unreliableData } = await useFetch("/api/unreliable", {
  retry: 3,
  retryDelay: 1000,
  retryStatusCodes: [408, 409, 425, 429, 500, 502, 503, 504]
});

Types

interface FetchError extends Error {
  request?: RequestInfo;
  options?: RequestInit;
  response?: Response;
  data?: any;
  status?: number;
  statusText?: string;
}

interface FetchContext<T = any, R extends NitroFetchRequest = NitroFetchRequest> {
  request: R;
  options: FetchOptions<R>;
  response?: FetchResponse<T>;
  error?: FetchError;
}

interface FetchResponse<T> extends Response {
  _data?: T;
}

type SearchParams = Record<string, any> | [key: string, value: string][] | string | URLSearchParams;

type MultiWatchSources = (WatchSource<unknown> | object)[];

type KeysOf<T> = Array<
  T extends T 
    ? keyof T extends string
      ? keyof T
      : string
    : never
>;

type AvailableRouterMethod<R extends NitroFetchRequest> = 
  R extends string 
    ? "GET" | "HEAD" | "PATCH" | "POST" | "PUT" | "DELETE" | "OPTIONS"
    : "GET" | "HEAD" | "PATCH" | "POST" | "PUT" | "DELETE" | "OPTIONS";

type NitroFetchRequest = string | Request;

Install with Tessl CLI

npx tessl i tessl/npm-nuxt

docs

app-lifecycle.md

configuration.md

core.md

data-fetching.md

head.md

index.md

module-dev.md

navigation.md

performance.md

ssr.md

state.md

tile.json