Styled Query Component
Like StyledComponents, but for SQL.
`${template literal}` your way to database queries!
User by ID
Fetch a single user and review the query metadata.
Lookup User
Run a single query for user #1.
type UserByIdParams = { id: number };type UserByIdRow = { id: number; name: string }; const UserById = sqc.Select< UserByIdParams, UserByIdRow>({ from: "users", columns: ["id", "name"], where: { id: sqc.param("id") },}); <UserById await={false} id={1} fulfilled={(rows, meta) => /* render output + meta */} reject={(error) => /* handle error */}/>Rows
| id | name |
|---|---|
| 1 | Sophie Lovelace |
Meta
| SQL | SELECT id, name FROM users WHERE id = :id |
| Params | {"id":1} |
| Rows | 1 |
| Duration | 2.06ms |
Create a Client
Connect createClient to better-sqlite3 with a lightweight adapter.
import { createClient } from "@lib";import db from "@lib/db"; const sqc = createClient({ adapter: async (sql, params) => { const stmt = db.prepare(sql); const rows = stmt.all(params) as Record<string, unknown>[]; const columns = rows.length > 0 ? Object.keys(rows[0]) : []; return { rows, columns }; },});Tagged Template (Await Mode)
Use sqc.sql with sqc.param for dynamic values and render results as a table.
User List
Fetch a range of users with a dynamic limit.
type UserListParams = { id: number; limit: number };type UserListRow = { id: number; name: string }; const UserList = sqc.sql<UserListParams, UserListRow>` select id, name from users where id >= ${sqc.param("id")} limit ${sqc.param("limit")}`; <UserList await id={1} limit={5} as="table" />Rows
| id | name |
|---|---|
| 1 | Sophie Lovelace |
| 2 | Larry Thompson |
| 3 | Donald Turing |
| 4 | Susan Hopper |
| 5 | Ryan Turing |
Meta
| SQL | select id, name from users where id >= :id limit :limit |
| Params | {"id":1,"limit":5} |
| Rows | 5 |
| Duration | 1.50ms |
Select API (Promise Mode)
Use sqc.Select and custom fulfilled/reject handlers for full control.
Products by Category
Handle results manually and inspect query metadata.
type ProductsByCategoryParams = { category: string; limit: number };type ProductsByCategoryRow = { id: number; title: string; price: number; category: string }; const ProductsByCategory = sqc.Select< ProductsByCategoryParams, ProductsByCategoryRow>({ from: "products", columns: ["id", "title", "price", "category"], where: { category: sqc.param("category") }, orderBy: { field: "price", direction: "desc" }, limit: sqc.param("limit"),}); <ProductsByCategory await={false} category="electronics" limit={3} fulfilled={(rows, meta) => /* custom render */} reject={(error) => /* custom render */}/>Rows
| id | title | price | category |
|---|---|---|---|
| 502 | Pro Chair 502 | 993.68 | electronics |
| 16 | Essential Headphones 16 | 985.69 | electronics |
| 536 | Ergonomic Tablet 536 | 982.28 | electronics |
Meta
| SQL | SELECT id, title, price, category FROM products WHERE category = :category ORDER BY price DESC LIMIT :limit |
| Params | {"category":"electronics","limit":3} |
| Rows | 3 |
| Duration | 1.13ms |
Render Modes
Switch output formats with the as prop.
<UserList await id={1} limit={3} as="json" /><UserList await id={1} limit={3} as="table" />Rows
| id | name |
|---|---|
| 1 | Sophie Lovelace |
| 2 | Larry Thompson |
| 3 | Donald Turing |
Meta
| SQL | select id, name from users where id >= :id limit :limit |
| Params | {"id":1,"limit":3} |
| Rows | 3 |
| Duration | 0.71ms |
Playground
Experiment with Styled Query Component examples, params, and output formats.
Interactive Query Builder
Pick an example, tweak params, and inspect the generated SQL.
User by ID
Tagged template with a single param.
type UserByIdParams = { id: number };type UserByIdRow = { id: number; name: string; email: string; role: string; status: string;}; const UserById = sqc.sql<UserByIdParams, UserByIdRow>` select id, name, email, role, status from users where id = ${sqc.param("id")}`; <UserById await id={1} as="table" />Execution
Render As
Parameters
Result
Meta
Run a query to see SQL and execution metadata.