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 }[]
Parameter Type Required Description
select SelectInput Yes Fields and relations to include in the result
where Entity filters No Filter conditions
orderBy Entity orderBy No Ordering specification
limit number No Maximum number of results
offset number No Number 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:

Quantifier Matches when
some At least one related row matches
every All related rows match
none No 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.