npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@kysoql/core

v0.1.0

Published

Kysely-inspired, type-safe Salesforce SOQL query builder and compiler

Readme

@kysoql/core

@kysoql/core is the type-safe SOQL query builder at the heart of Kysoql. It gives you immutable, Kysely-inspired builders while following Salesforce query rules rather than SQL rules.

The package does not connect to Salesforce on its own. You can compile queries without a transport, or add @kysoql/rest, @kysoql/jsforce, or your own executor when you are ready to run them.

Install

pnpm add @kysoql/core

Generate an org-specific schema with @kysoql/codegen, then pass it to Kysoql:

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 25

Type-safe Salesforce queries

The generated schema gives Kysoql more than field names. It also carries Salesforce metadata such as nullability, filterability, sortability, grouping support, relationship targets, and active picklist values where available.

That lets the builder catch many mistakes before a query reaches Salesforce:

const accounts = db
  .selectFrom("Account")
  .select(["Id", "Name", "Owner.Name"])
  .where("Name", "like", "Acme%")
  .limit(25);

Result types follow the fields you actually select. Parent relationships retain their nested shape unless you give a field an alias.

const accounts = db
  .selectFrom("Account")
  .select(["Id as id", "Owner.Name as ownerName"]);

Salesforce does not provide ordinary field aliases for record queries, so Kysoql requests the source fields and projects the aliases onto the returned JavaScript rows.

Compose queries without mutation

Builders are immutable. You can safely start with one query and derive several versions from it.

const base = db.selectFrom("Account").select(["Id", "Name"]);

const firstPage = base.orderBy("Name").limit(25);
const search = base.where("Name", "like", "Acme%").limit(10);

$if and $call help keep reusable query logic readable:

const query = db
  .selectFrom("Account")
  .select(["Id", "Name"])
  .$if(includeRevenue, (qb) => qb.select("AnnualRevenue"))
  .$call((qb) => addAccountFilters(qb));

Fields selected inside $if become optional in the inferred result because the condition is only known at runtime.

Salesforce-specific features

Kysoql models Salesforce concepts directly instead of forcing them into SQL-shaped APIs. Core includes typed support for features such as:

  • parent and child relationship queries
  • semi-joins and anti-joins
  • TYPEOF polymorphic selections
  • aggregate queries, HAVING, ROLLUP, and CUBE
  • Salesforce date and datetime literals
  • FIELDS() selectors with Salesforce's bounding rules
  • multipicklist INCLUDES and EXCLUDES
  • translated labels, formatting, currency conversion, and geolocation functions
  • QueryAll execution mode through capable executors
  • Apex-only compilation with typed binds and access modes

Some Salesforce features are Beta or Pilot APIs. Kysoql keeps those APIs explicitly namespaced so experimental syntax is easy to spot in application code.

Apex compilation

Use .apex() when the query is meant to be embedded in Apex and needs Apex-only syntax:

import { apexBind } from "@kysoql/core";

const query = db
  .selectFrom("Account")
  .select(["Id", "Name"])
  .apex()
  .where("Id", "=", apexBind<string>("accountId"))
  .forUpdate()
  .compile();

Apex builders are compile-only. Kysoql does not execute Apex or create the runtime bind values for you.

Use .dynamicApex() for the separate managed-package dynamic SOQL surface, including typed Database.QueryOptions binds.

Execute queries

Pass a QueryExecutor to Kysoql to enable .execute(), .executeTakeFirst(), and related helpers.

For most applications, use @kysoql/rest. If you already have a JSforce connection, use @kysoql/jsforce.

const db = new Kysoql<SalesforceSchema>({ executor });

const accounts = await db
  .selectFrom("Account")
  .select(["Id", "Name"])
  .execute();

Documentation