Skip to content

Combining Sources

Make additional $fetch calls inside a transformer to enrich the backend response with data from other endpoints before it reaches the client.

Basic example

The transformer receives event: H3Event, so you can call useRuntimeConfig() and $fetch just like in a route:

typescript
// server/bff/transformers/pet.ts
import type { H3Event } from 'h3'
import type { AuthContext } from '~/server/auth/types'

export async function transformPet<T = any>(
  data: T,
  event: H3Event,
  auth: AuthContext | null
): Promise<T> {
  const pet = data as any
  const config = useRuntimeConfig()

  // Fetch owner info from another endpoint
  const owner = await $fetch(`${config.apiBaseUrl}/owners/${pet.ownerId}`, {
    headers: { Authorization: `Bearer ${config.apiSecret}` },
  }).catch(() => null)

  return {
    ...pet,
    ownerName: owner?.name ?? null,
  } as T
}

Parallel fetches

Use Promise.all to avoid sequential waterfall:

typescript
export async function transformPet<T = any>(
  data: T,
  event: H3Event,
  auth: AuthContext | null
): Promise<T> {
  const pet = data as any
  const config = useRuntimeConfig()

  const [owner, medicalRecord] = await Promise.all([
    $fetch(`${config.apiBaseUrl}/owners/${pet.ownerId}`).catch(() => null),
    $fetch(`${config.apiBaseUrl}/medical-records?petId=${pet.id}`).catch(() => null),
  ])

  return {
    ...pet,
    ownerName: owner?.name ?? null,
    hasVaccinations: Array.isArray(medicalRecord) && medicalRecord.length > 0,
  } as T
}

Only enrich when needed

Skip the extra fetch for unauthenticated requests to keep public endpoints fast:

typescript
export async function transformPet<T = any>(
  data: T,
  event: H3Event,
  auth: AuthContext | null
): Promise<T> {
  const pet = data as any

  // Skip enrichment for unauthenticated users
  if (!auth?.isAuthenticated) return data

  const config = useRuntimeConfig()
  const owner = await $fetch(`${config.apiBaseUrl}/owners/${pet.ownerId}`).catch(() => null)

  return {
    ...pet,
    ownerName: owner?.name ?? null,
  } as T
}

WARNING

Extra fetches inside a transformer add latency to every call of that route. Always catch errors so a failure in an enrichment source does not crash the main response.

Released under the Apache-2.0 License.