Pulling a Table Schema #
After configuring your environment variables, pull a schema from Trino:
npm run cli pull --catalog hive --schema salesThis command introspects every table in hive.sales and generates five files per table.
Generated Files #
For a table called orders, the CLI creates:
1
2
3
4
5
6
7
src/schemas/generated/hive/sales/orders/
├── config.ts # Table metadata and docs settings
├── interface.ts # TypeScript interface for the table
├── query-schema.ts # Pothos query schema with resolvers
├── json-schema.json # JSON Schema for response transformation
└── endpoint.json # Endpoint definition (for re-generation)
config.ts — Contains the table's catalog, schema, table name, and docs settings:
1
2
3
4
5
6
7
8
9
10
11
12
13
export const hiveConfig = {
catalog: "hive",
schema: "sales",
tableName: "orders",
} as const
export const docsConfig = {
query: true,
mutation: false,
queryName: "orders",
mutationName: null,
} as const
interface.ts — A TypeScript interface matching the table's column types:
1
2
3
4
5
6
7
8
export interface Orders {
id: number
customer_id: number
status: string
total: number
created_at: Date
}
query-schema.ts — A Pothos query schema defining the GraphQL type, comparison inputs, and resolver with filtering, sorting, and pagination:
1
2
3
4
5
6
import { builder } from "@lakeql/api"
import { hiveConfig } from "./config"
// Defines: OrdersType, OrdersFilter, OrdersSort, OrdersConnection
// Registers: Query.orders(filter, sorting, paging) → OrdersConnection
json-schema.json — Used at runtime by @lakeql/response-transformer to map Trino's array responses into typed objects:
1
2
3
4
5
6
7
8
9
10
11
{
"type": "object",
"properties": {
"id": { "type": "integer" },
"customer_id": { "type": "integer" },
"status": { "type": "string" },
"total": { "type": "number" },
"created_at": { "type": "string" }
}
}
Starting the API Server #
With schemas generated, start the server:
npm run devThe server loads all query schemas from the configured schemaPath directory and registers them with the Pothos builder. On startup you'll see:
1
2
3
* Server URL: http://localhost:4000/
* GraphQL Endpoint: http://localhost:4000/graphql
Executing a Query #
Open GraphiQL at http://localhost:4000/graphql and run:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24query {
orders(
filter: { and: [{ status: { eq: "shipped" } }] }
paging: { limit: 10, offset: 0 }
sorting: [{ field: "created_at", direction: "DESC" }]
) {
totalCount
pageInfo {
hasNext
hasPrevious
currentPage
maxPages
nextPage
previousPage
}
nodes {
id
customer_id
status
total
}
}
}
AUTH_MOCK=true, include the Authorization header with your
AUTH_MOCK_TOKEN value. You can also set x-username to simulate different
users.Example Response #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30{
"data": {
"orders": {
"totalCount": 142,
"pageInfo": {
"hasNext": true,
"hasPrevious": false,
"currentPage": 1,
"maxPages": 15,
"nextPage": 2,
"previousPage": null
},
"nodes": [
{
"id": 1001,
"customer_id": 42,
"status": "shipped",
"total": 249.99
},
{
"id": 998,
"customer_id": 17,
"status": "shipped",
"total": 89.5
}
]
}
}
}
What Happens Under the Hood #
-
GraphQL Yoga receives the query and resolves the
ordersfield - The resolver extracts selected fields from the GraphQL resolve info
-
@lakeql/query-buildergenerates a Trino SQL query with two CTEs (total_countandrecords) -
@lakeql/trino-clientexecutes the SQL against your Trino instance -
@lakeql/response-transformerconverts Trino's array response into typed objects using the JSON schema - Pagination metadata is calculated and the connection response is returned