Once you’ve defined several fragments, you can start defining your queries.

Query definition.

import { collectFragments } from "@adrocodes/pigeon";
import { HeroBannerFragment } from "@modules/hero-banner/hero-banner.pigeon";
import { z } from "zod";

const query = `
  ${collectFragments([HeroBannerFragment])}

  query GetPageData {
    page {
      heroBanner {
        ...${HeroBannerFragment.fragmentName}
      }
    }
  }
`
Nothing is stopping you from using createDependency for the page above. In the example above, the more dependencies you have, the more items you’ll need to add to collectFragments. Abstracting page into a createDependency means you’ll only need to update the dependencies key and the fragments will automatically be collected.

What does collectFragments do?

collectFragments is a helper function that will collect all the fragments required for a query. This ensures that only the fragments you need are included and de-duped.

This will produce a string that looks like this:

fragment HeroBannerFragment on HeroBanner {
  title
  description
  image {
    ...ImageFragment
  }
}

fragment ImageFragment on Asset {
  url
  alt
  size { width height }
}

Notice how you didn’t have to include ImageFragment in the collectFragment method, while traversing the HeroBannerFragment it found that ImageFragment was a dependency and included it.

Query Schema.

const schema = z.object({
  page: z.object({
    heroBanner: HeroBannerFragment.schema
  })
})

Query Execution.

const { data, error } = await client.query({ query })

const parsed = await schema.parseAsync(data)

return parsed
Be better than me and handle your errors, please.

Pigeon isn’t opinionate on how you fetch the data so replace client with your GraphQL client of choice. Some clients may require the query method to be wrapped in a gql call, so be sure to check the documentation for your client.

Once you get your data back, you’ll need to parse your data with the schema you defined. This will validate the data and transform it into the shape you need. I am using the parseAsync method to handle any async transforms however, if you don’t have any async transforms you can use the parse method.

At this point, you can be confident that the data you are working with is valid and in the shape you need. If your data is invalid, zod will provide error details that you can debug further.