How do I get the type definition for my schema before transformation?

Zod will dynamically define the type as you define your schema. As soon as you use the transform method, Zod will infer the type from the return value of the transform method. If you need the type definition before transformation, you’ll need to define your schema outside of createRegistration or createDependency.

import { z } from "zod"

const schema = z.object({})
type Schema = z.infer<typeof schema>

const transformer = (value: Schema) => value

const registration = createRegistration({
  schema: schema.transform(transformer),
})

How do I handle multiple fragments for the same __typename?

If you have multiple fragments for the same __typename, you’ll need to define a fragmentName for each fragment. This is to avoid conflicts when collecting fragments for a query.

How do I define a union using multiple fragments?

Unfortunatly, zod doesn’t like defining a union “dynamically”. You’ll need to define the union manually.

import { z } from "zod"

const union = z.union([
  HeroBannerFragment.schema,
  ImageFragment.schema,
])

How do I make my query smaller?

Some APIs can have a byte limit on your fetch body. You can use gqlmin to minify your query.

I would also recommend creating a function to generate smaller fragment names, since pigeon just appends Fragment to the __typename, that can add quite a bit of bytes to your query.

How do I ensure anything pigeon doesn’t make it to the frontend?

If you’re in the React space, use the server-only package. At the top of any function you define a fragment import this package.

import "server-only"

import { createDependency } from "@adrocodes/pigeon"

// ...

How can my transform functions have access to server context?

Sometime there might be information about your request that you’ll need access to in your transform functions. For this you’ll need to set up a “store” to hold this information.

In the below example is for Next.js utilising the React cache function.

store.ts
import { cache } from "react"

type Store = {
  pathname?: string
}

function getStoreImpl() {
  const value: Store = {
    pathname: undefined,
  };
  return value;
}

const getStore = cache(getStoreImpl);

export function setRequestPathname(pathname: string) {
  getStore().pathname = pathname;
}

export function getRequestPathname() {
  return getStore().pathname;
}

Now in your page.tsx or layout.tsx you can set the pathname and access it in your transform functions.

page.tsx
export default function Page({ params }) {
  setRequestPathname(params.pathname);

  //...
}
Remember to do this before your fetches or anything that uses pigeon. You should do this anywhere that params are available.
hero-banner.pigeon.ts
export const HeroBannerFragment = createDependency({
  schema: z.object({...}).transform(() => {
    const pathname = getRequestPathname();
    //...
  })
})