Waddler is a database client wrapper that unifies database communication and enables all* supported database clients to use an SQL template tag with consistent syntax, value escaping, helping prevent SQL injection and supporting common query-building scenarios.
* supported clients by waddler
You don't need to learn each driver's API, hunt for the features you need to build queries, or constantly write your own small utilities for parameterization, escaping, and so on. All of that is handled by the sql`` template tag from Waddler
SQL template
sql.identifier
sql.values
sql.raw
Types
Stream
Chunked
// Import from any driver subpackage to wrap it with waddler
import { waddler } from 'waddler/...';
const sql = waddler({ dbUrl: "" })
await sql`select * from "users" where "id" = ${10}`;// Example wrapping "duckdb-neo" driver with waddler
import { waddler } from 'waddler/duckdb-neo';
const sql = waddler({ dbUrl: ":memory:" })
await sql`select * from "users" where "id" = ${10}`;select * from "users" where "id" = $1;
-- 10 will be passed as a param [10]await sql`select * from ${sql.identifier('users')}`;
await sql`select ${sql.identifier('id')} from ${sql.identifier('users')}`;
await sql`select ${sql.identifier(['id', 'name', 'email'])} from ${sql.identifier('users')}`;select * from "users";
select "id" from "users";
select "id", "name", "email" from "users";// Just add an array of arrays for insert values
await sql`insert into "users" ("name") values ${sql.values([["Dan"]])}`;
const values = sql.values([["Dan", "[email protected]", 25]]);
await sql`insert into "users" ("name", "email", "age") values ${values}`;insert into "users" ("name") values ('Dan');
insert into "users" ("name", "email", "age") values ('Dan', '[email protected]', 25);const listUsers = async (filter: string | undefined) => {
const whereClause = filter ? sql.raw(` where ${filter}`) : sql.raw("");
return sql`select * from "users"${whereClause}`;
}
await listUsers(`"id" = 10`);
await listUsers(`"name" = 'Dan'`);
await listUsers();select * from "users" where "id" = 10;
select * from "users" where "name" = 'Dan';
select * from "users";const result = await sql<{ id: number, name: string }>`select * from "users"`;
// or
type User = { id: number, name: string };
const result: User[] = await sql<User>`select * from "users"`;
result[0].id; // ✓ works
result[0].name; // ✓ works
result[0].unknown;
// ^ TS errorconst result = sql`select * from users`.stream();
for await (const row of result) {
console.log(row);
}{
id: 1,
name: "Alex",
}
{
id: 2,
name: "Oleksii",
}const result = sql`select * from users`.chunked(2);
for await (const chunk of result) {
console.log(chunk);
}[
{
id: 1,
name: "Alex",
},
{
id: 2,
name: "Oleksii",
}
]
…