@flowblade/source-kysely
v0.17.0
Published
Kysely datasource
Readme
@flowblade/source-kysely
A source adapter for Kysely.
Install
yarn add @flowblade/core @flowblade/source-kysely kysely
# Install optional drivers
# 01. for Ms SqlServer or Azure Sql Edge
yarn add tedious tarnKysely supports
Quick start
// Your db configuration, see Utils section for more details
import { db } from "@/config/db.config.ts";
import { KyselyDatasource, isQueryResultError } from "@flowblade/source-kysely";
import { sql } from "kysely";
import { KyselyDatasource, isQueryResultError } from "@flowblade/source-kysely";
const ds = new KyselyDatasource({ db });
const query = ds.queryBuilder // This gives access to Kysely expression builder
.selectFrom("brand as b")
.select(["b.id", "b.name"])
.leftJoin("product as p", "p.brand_id", "b.id")
.select(["p.id as product_id", "p.name as product_name"])
.where("b.created_at", "<", new Date())
.orderBy("b.name", "desc");
const result = await ds.query(query);
// Or with query information (will be sent in the metadata)
// const result = await ds.query(query, {
// name: 'getBrands'
// });
// Option 1: the QResult object contains the data, metadata and error
// - data: the result rows (TData or undefined if error)
// - error: the error (QError or undefined if success)
// - meta: the metadata (always present)
const { data, meta, error } = result;
// Option 2: You operate over the result, ie: mapping the data
const { data: data2 } = result.map((row) => {
return {
...data,
key: `key-${row.productId}`,
};
});Streaming
import { KyselyDatasource } from "@flowblade/source-kysely";
const ds = new KyselyDatasource({ db });
const query = ds.queryBuilder // This gives access to Kysely expression builder
.selectFrom("brand as b")
.select(["b.id", "b.name"]);
const stream = ds.stream(query, {
// Chunksize used when reading the database
// @default undefined
chunkSize: undefined,
});
for await (const brand of stream) {
console.log(brand.name);
if (brand.name === "Something") {
// Breaking or returning before the stream has ended will release
// the database connection and invalidate the stream.
break;
}
}Utils
createKyselyMssqlDialect
Create a Kysely dialect for Ms SqlServer or Azure Sql Edge.
import * as Tedious from "tedious";
import {
TediousConnUtils,
createKyselyMssqlDialect,
} from "@flowblade/source-kysely";
const jdbcDsn =
"sqlserver://localhost:1433;database=db;user=sa;password=pwd;trustServerCertificate=true;encrypt=false";
const tediousConfig = TediousConnUtils.fromJdbcDsn(jdbcDsn);
const dialect = createKyselyMssqlDialect({
tediousConfig,
// 👉 Optional tarn pool options
poolOptions: {
min: 0, // 👉 Minimum number of connections, default 0
max: 10, // 👉 Maximum number of connections, default 10
propagateCreateError: true, // 👉 Propagate connection creation errors, default false
},
dialectConfig: {
/**
* When true, connections are validated before being acquired from the pool,
* resulting in additional requests to the database.
*
* In safe scenarios, this can be set to false to improve performance.
*
* Defaults to `true`.
*/
validateConnections: true,
/**
* When true, connections are reset to their initial states when released back to the pool,
* resulting in additional requests to the database.
*
* Defaults to `false`.
*/
resetConnectionsOnRelease: false,
// 👉 Override Tedious types to enhance compatibility and modern support
tediousTypes: {
...Tedious.TYPES,
// see https://github.com/kysely-org/kysely/issues/1161#issuecomment-2384539764
NVarChar: Tedious.TYPES.VarChar,
// see https://github.com/kysely-org/kysely/issues/1596#issuecomment-3341591075
DateTime: Tedious.TYPES.DateTime2,
},
},
});
const db = new Kysely<DB>({
dialect,
});Note: For performance you can avoid connection roundtrips by setting
validateConnectionstofalseandresetConnectionOnReleasetofalse.
TediousConnUtils
fromJdbcDsn
Parse and validate a JDBC connection string and return a Tedious connection configuration.
import * as Tedious from "tedious";
import { TediousConnUtils } from "@flowblade/source-kysely";
// In your .env file
// DB_JDBC_DSN="sqlserver://localhost:1433;database=db;user=sa;password=pwd;trustServerCertificate=true;encrypt=false";
const tediousConfig = TediousConnUtils.fromJdbcDsn(process.env.DB_JDBC_DSN);
const tediousConnection = new Tedious.Connection(tediousConfig);Compatibility
| Level | CI | Description | | ------------ | --- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Node | ✅ | CI for 20.x, 22.x. & 24.x | | Cloudflare | ✅ | Ensured with @cloudflare/vitest-pool-workers (see wrangler.toml | | Browserslist | ✅ | > 95% on 01/2025. Chrome 96+, Firefox 90+, Edge 19+, ios 15+, Safari 15+ and Opera 77+ | | Typescript | ✅ | TS 5.0 + / are-the-type-wrong checks on CI. | | ES2022 | ✅ | Dist files checked with es-check | | Performance | ✅ | Monitored with codspeed.io |
Contributors
Contributions are welcome. Have a look to the CONTRIBUTING document.
Sponsors
Sponsor, coffee, or star – All is spent for quality time with loved ones. Thanks ! 🙏❤️
Special thanks to
License
MIT © Sébastien Vanvelthem and contributors.
