@bob-kit/client
v0.0.33
Published
> **Disclaimer:** > Bob is under development! Use at your own risk.
Readme
@bob-kit/client
Disclaimer:
Bob is under development! Use at your own risk.
Official Bob client for consuming the bob DSL from JavaScript/TypeScript.
This package loads Bob’s runtime (WASM) and exposes a small API to:
- Transpile your
bobinput into SQL for a given engine (SQLite, MariaDB/MySQL, PostgreSQL). - Automatically execute the generated SQL using a
Driveryou provide. - Optionally cache transpilation results.
What is Bob?
Bob is a lightweight, declarative transpiler that lets you define database schemas and queries using a simple, human‑readable DSL called bob.
Bob then converts those definitions into SQL for multiple engines such as SQLite, MariaDB/MySQL, and PostgreSQL.
Instead of writing verbose SQL by hand, you describe tables, relationships, and queries concisely, and Bob generates the corresponding SQL.
Installation
With pnpm:
pnpm add @bob-kit/clientWith npm:
npm i @bob-kit/clientWith yarn:
yarn add @bob-kit/clientEnvironment requirements
Right now, @bob-kit/client loads the WASM using Node APIs (fs, vm).
That means it’s currently Node.js-oriented (not browser) as implemented today.
Concepts: Driver and cache
The client needs a Driver (from @bob-kit/types) to execute the generated SQL:
- driver: target engine (
"sqlite" | "mariadb" | "mysql" | "postgres"). - querier(query, ...params): async function that executes SQL (and returns rows for
SELECT). - cache: optional implementation to cache transpilation results (memory, redis, etc.).
This package also exports a ready-to-use in-memory cache: MemoryCache.
Quick start (Node + SQLite)
Complete example using @bob-kit/sqlite as the querier:
import bob from "@bob-kit/client";
import { MemoryCache } from "@bob-kit/client/cache";
import { sqlite } from "@bob-kit/sqlite";
const querier = sqlite(":memory:");
const client = bob({
driver: "sqlite",
querier,
cache: new MemoryCache(),
});
// 1) Define multiple tables in a single query
await client.query`
table Profile {
id id
avatar string
}
table Users {
id id
name string
lastName string
Profile
}
`;
// 2) Insert one entity
await client.query`
new Profile {
avatar "bear"
}
`;
// 3) Bulk insert with multiple rows and columns
await client.query`
new Users name lastName Profile.id {
"John" "Doe" 1
"Mary" "Jane" 3
"Robert" "Smith" 3
}
`;
// 4) Create reusable query functions with types
const getUserByName = (name: string) => client.query`
get Users {
name
profile_id
-> Profile {
avatar
}
desc Profile.id
}
`;
const users = await getUserByName("John");Advanced examples
Joins and relationships
// Join with related table
const usersWithProfiles = await client.query`
get Users {
id
name
lastName
-> Profile {
avatar
}
}
`;Filtering and sorting
const filteredUsers = await client.query`
get Users {
id
name
if name = "John" || "Mary"
}
`;
const sortedUsers = await client.query`
get Users {
id
name
desc id
}
`;Parameters
The API accepts parameters as arguments to query(...). Internally, the template literal is converted to a string using ? as the placeholder.
const byEmail = await client.query`
get Users {
id
name
email
if email == ?
}
`("[email protected]");API
default export function bob(driver: Driver)
Creates a client instance.
Returns an object with:
query<A>(input, ...params): Promise<A[]>: executes abobinput. You can destructure it for convenience:const { query: b } = bob(...).cache(id)(input, ...params): Promise<A[]>: same asquery, but caches the transpilation result under a fixedid.factory.<id>(input, ...params): Promise<A[]>: shortcut forcache("<id>")(...).
bobQuery({ driver, input, id? })
Low-level function that only performs transpilation (and applies cache if present). You usually won’t need it.
@bob-kit/client/cache
Includes:
MemoryCache: in-memory (Map) cache forBobQueryResult.
Errors
When Bob returns a parsing/validation/transpilation error, the client throws BobError with:
name: a value fromBobErrors(from@bob-kit/types/errors)message: error details
Important notes
- Multiple actions: if your input generates more than 1 SQL action, the client throws (
MultipleActions).
The current flow assumes 0 or 1 action per execution. - Table execution: if the output includes
tables, all of them are executed (in order) before the action/query.
