Skip to content

Commit 2ee6696

Browse files
committed
docs: remove old QueryBuilder section, replace with new generators API examples
- Remove standalone QueryBuilder example (old API) - Add 'Nested Relations' section showing buildSelect with fieldSelection.include - Show automatic hasMany Connection wrapping vs direct belongsTo nesting - Update Field Selection section with proper presets (minimal/all/full) and custom selection
1 parent 9ab56d1 commit 2ee6696

1 file changed

Lines changed: 45 additions & 85 deletions

File tree

graphql/query/README.md

Lines changed: 45 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ This package is the **canonical source** for PostGraphile query generation logic
2727
- **Query generators**`buildSelect`, `buildFindOne`, `buildCount` for read operations
2828
- **Mutation generators**`buildPostGraphileCreate`, `buildPostGraphileUpdate`, `buildPostGraphileDelete`
2929
- **Introspection pipeline**`inferTablesFromIntrospection` to convert a GraphQL schema into `CleanTable` metadata
30-
- **QueryBuilder** — fluent API for composing nested queries with filters and pagination
3130
- **AST builders** — low-level `getAll`, `getMany`, `getOne`, `createOne`, `patchOne`, `deleteOne`
3231
- **Client utilities**`TypedDocumentString`, `execute`, `DataError` for type-safe execution and error handling
3332
- **Naming helpers** — server-aware inflection functions that respect PostGraphile's schema naming
@@ -168,105 +167,55 @@ mutation deleteUserMutation($input: DeleteUserInput!) {
168167

169168
---
170169

171-
## QueryBuilder (Fluent API)
170+
## Nested Relations
172171

173-
For more control over nested queries, filters, and pagination, use the `QueryBuilder` class:
172+
Include related tables in your query with automatic Connection wrapping for hasMany relations:
174173

175174
```ts
176-
import { QueryBuilder } from '@constructive-io/graphql-query';
175+
import { buildSelect } from '@constructive-io/graphql-query';
177176

178-
const builder = new QueryBuilder({
179-
introspection: { ...queries, ...mutations } // provide your GraphQL schema metadata
180-
});
177+
const actionTable = tables.find(t => t.name === 'Action')!;
181178

182-
const result = builder
183-
.query('Action')
184-
.edges(true)
185-
.getMany({
186-
select: {
187-
id: true,
188-
name: true,
189-
photo: true,
190-
title: true,
191-
actionResults: {
192-
select: {
193-
id: true,
194-
actionId: true
195-
},
196-
variables: {
197-
first: 10,
198-
before: null,
199-
filter: {
200-
name: {
201-
in: ['abc', 'def']
202-
},
203-
actionId: {
204-
equalTo: 'dc310161-7a42-4b93-6a56-9fa48adcad7e'
205-
}
206-
}
207-
}
208-
}
209-
}
210-
})
211-
.print();
179+
const query = buildSelect(actionTable, tables, {
180+
fieldSelection: {
181+
select: ['id', 'name', 'photo', 'title'],
182+
include: {
183+
actionResults: ['id', 'actionId'], // hasMany → wrapped in nodes { ... }
184+
category: true, // belongsTo → direct nesting
185+
},
186+
},
187+
});
212188
```
213189

214190
**Generated GraphQL:**
215191

216192
```graphql
217-
query getActionsQuery(
218-
$first: Int
219-
$last: Int
220-
$after: Cursor
221-
$before: Cursor
222-
$offset: Int
223-
$condition: ActionCondition
224-
$filter: ActionFilter
225-
$orderBy: [ActionsOrderBy!]
226-
) {
227-
actions(
228-
first: $first
229-
last: $last
230-
offset: $offset
231-
after: $after
232-
before: $before
233-
condition: $condition
234-
filter: $filter
235-
orderBy: $orderBy
236-
) {
193+
query actionsQuery {
194+
actions {
237195
totalCount
238-
pageInfo {
239-
hasNextPage
240-
hasPreviousPage
241-
endCursor
242-
startCursor
243-
}
244-
edges {
245-
cursor
246-
node {
196+
nodes {
197+
id
198+
name
199+
photo
200+
title
201+
actionResults(first: 20) {
202+
nodes {
203+
id
204+
actionId
205+
}
206+
}
207+
category {
247208
id
248209
name
249-
photo
250-
title
251-
actionResults(
252-
first: 10
253-
before: null
254-
filter: {
255-
name: { in: ["abc", "def"] }
256-
actionId: { equalTo: "dc310161-7a42-4b93-6a56-9fa48adcad7e" }
257-
}
258-
) {
259-
nodes {
260-
id
261-
actionId
262-
}
263-
}
264210
}
265211
}
266212
}
267213
}
268214
```
269215

216+
> **hasMany** relations are automatically wrapped in the PostGraphile Connection pattern (`nodes { ... }` with a default `first: 20` limit).
217+
> **belongsTo** relations are nested directly.
218+
270219
---
271220

272221
## FindOne Query
@@ -319,15 +268,26 @@ query getUsersCountQuery(
319268

320269
## Field Selection
321270

322-
Control which fields and relations are included in the query:
271+
Control which fields and relations are included using presets or custom selection:
323272

324273
```ts
325274
import { buildSelect } from '@constructive-io/graphql-query';
326275

327-
const query = buildSelect(userTable, tables, {
276+
// Preset: just id + a few display fields
277+
const minimal = buildSelect(userTable, tables, { fieldSelection: 'minimal' });
278+
279+
// Preset: all scalar fields (no relations)
280+
const allFields = buildSelect(userTable, tables, { fieldSelection: 'all' });
281+
282+
// Preset: everything including relations
283+
const full = buildSelect(userTable, tables, { fieldSelection: 'full' });
284+
285+
// Custom: pick specific fields + exclude some + include specific relations
286+
const custom = buildSelect(userTable, tables, {
328287
fieldSelection: {
329-
preset: 'all', // 'all' | 'scalar' | 'custom'
330-
includeRelations: true, // include related tables
288+
select: ['id', 'name', 'email'],
289+
exclude: ['internalNotes'],
290+
include: { posts: ['id', 'title'] },
331291
},
332292
});
333293
```

0 commit comments

Comments
 (0)