Getting Started #
Fork and clone
Fork the repository on GitHub, then clone your fork:
1
2
3
git clone https://github.com/<your-username>/lakeql.git
cd lakeql
Set up the environment
Follow the Local Development guide to install dependencies and start the local Trino cluster.
Create a feature branch
Always branch from main:
1
2
git checkout -b feat/my-feature main
Project Structure #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22lakeql/
├── apps/
│ └── docs/ # Documentation site (Next.js)
├── packages/
│ ├── adapter-fabric/ # Fabric adapter
│ ├── adapter-trino/ # Trino adapter
│ ├── api/ # GraphQL API server (Pothos + Yoga)
│ ├── cli/ # CLI tool
│ ├── config/ # Shared configuration utilities
│ ├── create-app/ # Project scaffolding tool
│ ├── datasource/ # Data source abstraction
│ ├── fabric-client/ # Microsoft Fabric client
│ ├── query-builder/ # SQL query builder
│ ├── storage/ # Storage write operations
│ ├── trino-client/ # Trino REST API client
│ └── ... # Internal packages (helpers, logger, etc.)
├── tooling/
│ ├── test-data/ # Test data generation and seed tooling
│ └── typescript/ # Shared TypeScript config
├── templates/ # App scaffolding templates
└── .minitrino/ # Local Trino cluster configuration
Development Workflow #
Building #
The monorepo builds packages with tsdown and orchestrates tasks with Turbo:
1
2
3
4
5
6
# Build all packages
pnpm build:pkg
# Build everything (packages + apps)
pnpm build
Running Tests #
Tests are written with vitest:
1
2
3
4
5
6
7
8
9
10
11
12
# Run all tests
pnpm test
# Run tests for a specific package
pnpm -F @lakeql/trino-client test
# Run with coverage
pnpm test -- --coverage
# Interactive UI
pnpm test:ui
Type Checking #
1
2
pnpm typecheck
Linting and Formatting #
The project lints with oxlint and formats with oxfmt. The shared rule presets come from Ultracite:
1
2
3
4
5
6
7
8
9
10
11
12
# Lint all files
pnpm lint
# Lint and auto-fix
pnpm lint:fix
# Check formatting
pnpm format
# Format all files
pnpm format:fix
pnpm lint and pnpm format before committing to catch issues early.Commits #
Write clear, descriptive commit messages. Prefer the conventional commit format:
1
2
3
4
feat(api): add cursor-based pagination
fix(trino-client): handle empty result sets
docs: update quickstart guide
Keep each commit focused on a single logical change.
Changelogs #
LakeQL uses Tegami for versioning and changelogs. When your change affects a published @lakeql/* package, add a changelog file under .tegami/.
The fastest way is the interactive TUI. It prompts you for the affected packages and bump level, then writes the file for you:
1
2
pnpm tegami
To write the file by hand, create it under .tegami/ following the naming convention:
1
2
# File: .tegami/YYYY-MM-DD-<short-description>.md
Either way, the file declares affected packages in YAML frontmatter and carries user-facing release notes in a markdown body:
1
2
3
4
5
6
7
8
9
---
packages:
"npm:@lakeql/trino-client":
type: patch
---
### Fix empty result handling
Return an empty array instead of throwing when Trino returns zero rows.
When a changelog is needed:
-
Any change to a published
@lakeql/*package — including bug fixes, features, and refactors
When a changelog is not needed:
-
Changes to
tooling/, docs, or dev infrastructure -
Changes to
private: truepackages
.tegami/publish-lock.yaml or CHANGELOG.md files in packages.
These are managed by Tegami during releases.Testing create-app on a Feature Branch #
When a pull request touches packages/**, CI publishes a pkg.pr.new preview build of every package, including @lakeql/create-app. That preview build of create-app is self-consistent. It downloads the starter template from the PR's own branch and resolves @lakeql/* dependencies to that same commit's pkg.pr.new preview versions, instead of the main template and npm latest packages.
create-app end to end against a feature
branch — scaffold a project with the preview build and it pulls in the
branch's own template and packages — rather than only being able to test
against main + npm latest.This behavior is CI-only infrastructure, driven by build-time environment variables the pipeline sets. The released create-lakeql-app is unaffected and keeps resolving the template from main and dependencies from npm latest.
Running a preview build #
The PR comment from pkg.pr.new lists an install URL for each package. To scaffold with the create-app preview, run its URL as a one-off with pnpm dlx or npx. Don't use pnpm create, which expects a package specifier rather than a URL:
1
2
3
pnpm dlx --config.block-exotic-subdeps=false \
https://pkg.pr.new/noxify/lakeql/@lakeql/create-app@<sha> my-app
The --config.block-exotic-subdeps=false flag is required with pnpm. The preview build of create-app carries its own @lakeql/scaffold dependency as a pkg.pr.new URL, and recent pnpm versions block URL dependencies nested inside a package by default (ERR_PNPM_EXOTIC_SUBDEP). npx does not need the flag.
To confirm the self-consistency, check the generated project's package.json. Every @lakeql/* dependency should point at https://pkg.pr.new/noxify/lakeql/<package>@<sha> (the same commit), while non-@lakeql/* dependencies keep their normal npm versions.
Pull Requests #
Workflow #
Ensure all checks pass
Before opening a PR, verify your changes locally:
1
2
3
4
5
pnpm typecheck
pnpm lint
pnpm format
pnpm test
Push and open a PR
Push your branch and open a pull request against main. Reference any related issues in the PR description.
Address review feedback
Respond to review comments and push additional commits. Avoid force-pushing unless asked — it makes review harder to follow.
PR Guidelines #
- Keep PRs focused on a single feature or fix
- Include a brief summary of what changed and why
- Add a Tegami changelog file if the change affects published packages
- Make sure CI passes before requesting review
Workspace Validation #
The project validates workspace constraints with sherif, checking for consistent dependency versions and proper workspace references:
1
2
pnpm lint:ws
Run this if you add or update dependencies to verify the workspace stays consistent.