LakeQL
Introduction
  • Overview
  • Key Concepts
  • Package Map
Getting Started
  • Prerequisites
  • Quickstart
  • Environment Configuration
  • First Run
Architecture
  • System Overview
  • Data Flow
  • Request Lifecycle
Configuration
  • Environment Variables
  • Authentication
  • Trino Connection
create-app
  • Usage
  • Template Structure
  • Post Creation
Contributing
  • Local Development
  • Contribution Guide
Guides
  • Custom Resolvers
  • Extending Schema
  • Deploying
  • Mutations
  • Load Strategies
GitHub
LakeQL
  1. LakeQL
  2. Getting Started
  3. First Run

On this page

  1. Pulling a Table Schema
    1. Generated Files
  2. Starting the API Server
  3. Executing a Query
    1. Example Response
  4. What Happens Under the Hood

First Run

Walk through pulling your first schema, understanding the generated files, and executing a GraphQL query.

Pulling a Table Schema #

After configuring your environment variables, pull a schema from Trino:

npm run cli pull --catalog hive --schema sales

This 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 dev

The 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
    }
  }
}
If 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 #

  1. GraphQL Yoga receives the query and resolves the orders field
  2. The resolver extracts selected fields from the GraphQL resolve info
  3. @lakeql/query-builder generates a Trino SQL query with two CTEs ( total_count and records )
  4. @lakeql/trino-client executes the SQL against your Trino instance
  5. @lakeql/response-transformer converts Trino's array response into typed objects using the JSON schema
  6. Pagination metadata is calculated and the connection response is returned

Previous page

Environment Configuration

Next page

Architecture

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
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