Skip to content

Entity Client

The EntityClient is accessed via client.entity('tableName') and provides type-safe methods for querying data. All methods return promises and build GraphQL queries automatically from the parameters you provide.

Returns an array of results matching the given parameters.

const articles = await client.entity('article').query({
select: { id: true, title: true, author: { name: true } },
where: { status: { eq: 'published' } },
orderBy: { createdAt: { direction: 'desc', priority: 1 } },
limit: 10,
offset: 0,
})
// Type: { id: string; title: string; author: { name: string } | null }[]
ParameterTypeRequiredDescription
selectSelectInputYesFields and relations to include in the result
whereEntity filtersNoFilter conditions
orderByEntity orderByNoOrdering specification
limitnumberNoMaximum number of results
offsetnumberNoNumber of results to skip

Returns a single result or null. Accepts the same parameters as query except limit.

const article = await client.entity('article').querySingle({
select: { id: true, title: true, content: true },
where: { id: { eq: articleId } },
})
// Type: { id: string; title: string; content: string } | null

Returns the number of matching rows. Accepts an optional where filter.

const total = await client.entity('article').count({
where: { status: { eq: 'published' } },
})
// Type: number

The select parameter determines both the GraphQL query fields and the TypeScript return type. Only selected fields appear in the response type.

Use true to include a scalar field:

const articles = await client.entity('article').query({
select: { id: true, title: true },
})
// Type: { id: string; title: string }[]

Use a nested object to include relation fields:

const articles = await client.entity('article').query({
select: {
id: true,
title: true,
author: { id: true, name: true }, // one-to-one: { ... } | null
comments: { id: true, body: true }, // one-to-many: { ... }[]
},
})

One-to-one relations are always typed as nullable (T | null) because a matching row may not exist. One-to-many relations are typed as arrays.

Filter conditions use per-column operator objects:

const articles = await client.entity('article').query({
select: { id: true },
where: {
status: { eq: 'published' },
createdAt: { gte: '2024-01-01' },
title: { ilike: '%graphql%' },
OR: [
{ authorId: { eq: 'user-1' } },
{ authorId: { eq: 'user-2' } },
],
},
})

Available operators: eq, ne, lt, lte, gt, gte, like, notLike, ilike, notIlike, inArray, notInArray, isNull, isNotNull.

For one-to-many relations, you can filter using quantifiers:

QuantifierMatches when
someAt least one related row matches
everyAll related rows match
noneNo related rows match
const articles = await client.entity('article').query({
select: { id: true, title: true },
where: {
comments: {
some: { approved: { eq: true } }, // has at least one approved comment
},
},
})

You can combine multiple quantifiers on the same relation:

where: {
comments: {
some: { body: { ilike: '%bug%' } }, // at least one comment mentions "bug"
none: { spam: { eq: true } }, // no comments flagged as spam
},
}

One-to-one / many-to-one relations use a direct nested filter object without any quantifier:

where: {
author: {
role: { eq: 'admin' },
},
}

Ordering uses column names with direction and priority:

const articles = await client.entity('article').query({
select: { id: true, title: true },
orderBy: {
createdAt: { direction: 'desc', priority: 2 },
title: { direction: 'asc', priority: 1 },
},
})

The priority field determines sort order when multiple columns are specified — higher values are applied first. In the example above, createdAt (priority 2) is the primary sort column, and title (priority 1) is used as a tiebreaker.