Framework
Build Salesforce SOQL with a Kysely-inspired, type-safe TypeScript query builder.
Kysoql gives Salesforce SOQL a fluent, type-safe TypeScript API. You write queries with familiar builder methods, while the generated schema keeps object names, fields, relationships, and supported operations tied to your Salesforce org.
If you know Kysely, the shape of the API should feel familiar. Kysoql is still its own query builder. It targets SOQL directly and follows Salesforce rules whenever SQL and SOQL behave differently.
Start here
The getting started guide takes you from installation to a real REST query. If you only want to see the builder first, this is the basic idea:
import { Kysoql } from "@kysoql/core";
import type { SalesforceSchema } from "./kysoql/salesforce.generated";
const db = new Kysoql<SalesforceSchema>();
const query = db
.selectFrom("Account")
.select(["Id", "Name"])
.where("Name", "like", "Acme%")
.orderBy("Name")
.limit(25);
console.log(query.compile().soql);
// SELECT Id, Name FROM Account WHERE Name LIKE 'Acme%' ORDER BY Name LIMIT 25Compilation does not need a Salesforce connection. Add an executor when you want .execute() and related methods to send the query to Salesforce.
What feels familiar from Kysely?
Methods such as select, where, and orderBy return a new builder. You can reuse a base query without one branch changing another.
$if and $call make it easier to share query logic while preserving useful TypeScript inference.
The result type follows what you select, including aliases, nullable relationships, conditional selections, aggregates, and TYPEOF branches.
The important difference is the target language. SOQL uses relationship paths, parent-to-child subqueries, and semi-joins instead of arbitrary SQL joins. Ordinary API values become escaped SOQL literals rather than SQL placeholder parameters. Mutations and transactions live outside this package because they are not part of SOQL.
Packages
| Package | What it does |
|---|---|
@kysoql/core | Builds and compiles typed SOQL queries. |
@kysoql/rest | Executes queries with Salesforce REST and native fetch. |
@kysoql/auth | Handles supported Salesforce OAuth flows and refresh-token storage. |
@kysoql/codegen | Generates org-specific TypeScript schema metadata. |
@kysoql/jsforce | Connects Kysoql to an existing JSforce connection. |
Install only the pieces your application needs, but keep all @kysoql/* packages on aligned versions.
Find the right guide
| I want to... | Read |
|---|---|
| Understand how builders and result types work | Mental model |
| Choose fields and shape a result | Selecting fields |
Build WHERE conditions | Filtering records |
| Query parent or child relationships | Relationships |
| Build grouped reports | Counts and aggregate reports |
| Sort or paginate results | Ordering and pagination |
| Run queries through Salesforce REST | Native REST execution |
| Compile SOQL for Apex | Compile for Apex |
| Check a platform-specific restriction | Support boundaries and limits |
| Diagnose an error | Troubleshooting |
| Look up a public API | Core API reference |
Types help, Salesforce still decides
Generated metadata catches a lot before runtime, including invalid names, unsupported operators, and many incompatible query shapes. It cannot replace Salesforce itself.
Permissions, enabled org features, API-version behaviour, query selectivity, current metadata, and runtime limits still apply when Salesforce receives the query.
Beta and Pilot features live under Beta and pilot features so they do not blend into the normal production API. soql.raw() remains the explicit escape hatch for trusted syntax Kysoql does not model.
For a direct map from builder concepts to Salesforce documentation, use the Salesforce reference map.