Connecting
tsql keeps query building and query execution separate.
You provide:
schema: output ofdefineDatabase(...)dialect: SQL placeholder and identifier behaviorconnection: your adapter withexecute(sql, params)
import { connect, sqliteDialect, type SqlConnection } from "@bms/tsql";
import { schema } from "./schema";
const connection: SqlConnection = {
execute: async (sql, params) => {
// Call your runtime driver here.
return { rows: [] };
},
};
const db = connect({
schema,
dialect: sqliteDialect(),
connection,
});
SqlConnection
type SqlConnection = {
execute(
sql: string,
params: readonly unknown[],
): Promise<{
rows: readonly unknown[];
}>;
};
execute always receives compiled SQL and bound parameters.
Effect integration
Use @bms/tsql/effect when running queries inside Effect programs. It is a separate export so applications use their own effect package version.
import { Effect } from "effect";
import { connect } from "@bms/tsql/effect";
const db = connect({ schema, dialect: sqliteDialect(), connection });
const users = await Effect.runPromise(
db.run(db.from("users").select(({ users }) => ({ id: users.id }))),
);
See Effect for Effect-native connections and transaction helpers.
Database object
connect(...) returns Database<TSchema>. Main methods:
from(...)forselectinsert(...),update(...),delete(...)rawandexprtemplate helpers- aggregate helpers:
count,max,min,avg,sum - transaction methods:
begin, and on transactionscommit/rollback - migration runner:
migrate