Command Palette

Search for a command to run...

Querying Data

Fetch data in Server Components with the server client or in Client Components with React Query hooks. Both use the same select and filter API.

Server Components

List entities

app/projects/page.tsx
1 2 3 4 5 6 7 import { pylo } from '@/lib/pylo'; const { data, pagination } = await pylo.project.list({ select: { id: true, name: true, created_at: true, }, pagination: { page: 1, per_page: 20 }, }); // data: Array<{ id: string; name: string | null; created_at: string }> // pagination: { total, current_page, per_page, last_page, has_more_pages }

If you omit select, all scalar fields are returned.

Fetch by ID

example.ts
1 2 3 4 5 6 7 8 9 10 11 const project = await pylo.project.byId('project-uuid', { select: { id: true, name: true, customer: { select: { id: true, name: true }, }, }, }); // Returns null if not found

Client Components (React Query Hooks)

usePyloList

components/project-list.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 'use client'; import { pylo } from "@/lib/pylo-hooks"; export function ProjectList() { const { data, pagination, isLoading, error } = pylo.usePyloList('project', { select: { id: true, name: true, created_at: true }, pagination: { page: 1, per_page: 20 }, filter: { sortby: [{ field: 'created_at', order: 'desc' }], }, }); if (isLoading) return <div>Loading...</div>; if (error) return <div>Error: {error.message}</div>; return ( <div> {data?.map((project) => ( <div key={project.id}>{project.name}</div> ))} <p>Page {pagination?.current_page} of {pagination?.last_page}</p> </div> ); }
FieldTypeDescription
dataT[] | undefinedArray of entities matching the select
paginationPaginationData | undefinedPagination metadata
isLoadingbooleanTrue while the initial request is loading
errorError | nullError if the request failed
refetch() => voidManually trigger a refetch

usePyloById

Fetch a single entity by ID. Automatically disabled when id is null or undefined.

components/project-detail.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 'use client'; import { pylo } from "@/lib/pylo-hooks"; export function ProjectDetail({ projectId }: { projectId: string }) { const { data: project, isLoading } = pylo.usePyloById('project', projectId, { select: { id: true, name: true, customer: { select: { id: true, name: true } }, }, }); if (isLoading) return <div>Loading...</div>; if (!project) return <div>Not found</div>; return ( <div> <h1>{project.name}</h1> <p>Customer: {project.customer?.data.name}</p> </div> ); }

usePyloInfiniteList

Infinite scrolling with automatic page management, built on useInfiniteQuery.

components/infinite-list.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 'use client'; import { pylo } from "@/lib/pylo-hooks"; export function InfiniteProjectList() { const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, } = pylo.usePyloInfiniteList('project', { perPage: 20, select: { id: true, name: true }, filter: { sortby: [{ field: 'created_at', order: 'desc' }], }, }); if (isLoading) return <div>Loading...</div>; return ( <div> {data?.data.map((project) => ( <div key={project.id}>{project.name}</div> ))} {hasNextPage && ( <button onClick={() => fetchNextPage()} disabled={isFetchingNextPage}> {isFetchingNextPage ? 'Loading...' : 'Load more'} </button> )} </div> ); }

Select

The select object determines which fields are returned. Only fields set to true are included.

example.ts
1 2 select: { id: true, name: true } // → { id: string; name: string | null }

Omit select entirely to get all scalar fields.

Relations

Include relations by providing a nested select object:

example.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 select: { id: true, // hasOne — pick specific fields customer: { select: { id: true, name: true }, }, // hasMany — with filter and pagination invoices: { select: { id: true, amount_net: true }, pagination: { per_page: 5 }, filter: { sortby: [{ field: 'created_at', order: 'desc' }], }, }, }

Response shapes:

  • hasOne (ManyToOne, OneToOne): { data: { ... } } | null
  • hasMany (OneToMany, ManyToMany): { data: [...], pagination: { ... } }

Error Handling

Server client — throws PyloError:

example.ts
1 2 3 4 import { PyloError } from '@pylo/nextjs'; try { const { data } = await pylo.project.list(); } catch (error) { if (error instanceof PyloError) { console.error(error.message); console.error(error.graphqlErrors); } }

Client hooks — return error state:

example.ts
1 2 const { data, error } = pylo.usePyloList('project', { ... }); if (error) console.error(error.message);