@bob-kit/client 0.0.29 → 0.0.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +208 -0
- package/package.json +3 -2
package/README.md
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# @bob-kit/client
|
|
2
|
+
|
|
3
|
+
> **Disclaimer:**
|
|
4
|
+
> Bob is under development! Use at your own risk.
|
|
5
|
+
|
|
6
|
+
Official **Bob** client for consuming the `bob` DSL from **JavaScript/TypeScript**.
|
|
7
|
+
|
|
8
|
+
This package loads Bob’s runtime (WASM) and exposes a small API to:
|
|
9
|
+
|
|
10
|
+
- Transpile your `bob` input into SQL for a given engine (SQLite, MariaDB/MySQL, PostgreSQL).
|
|
11
|
+
- Automatically execute the generated SQL using a `Driver` you provide.
|
|
12
|
+
- Optionally cache transpilation results.
|
|
13
|
+
|
|
14
|
+
## What is Bob?
|
|
15
|
+
|
|
16
|
+
**Bob** is a lightweight, declarative transpiler that lets you define database **schemas** and **queries** using a simple, human‑readable DSL called `bob`.
|
|
17
|
+
Bob then converts those definitions into SQL for multiple engines such as **SQLite**, **MariaDB/MySQL**, and **PostgreSQL**.
|
|
18
|
+
|
|
19
|
+
Instead of writing verbose SQL by hand, you describe tables, relationships, and queries concisely, and Bob generates the corresponding SQL.
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
With pnpm:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pnpm add @bob-kit/client
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
With npm:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm i @bob-kit/client
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
With yarn:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
yarn add @bob-kit/client
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Environment requirements
|
|
42
|
+
|
|
43
|
+
Right now, `@bob-kit/client` loads the WASM using Node APIs (`fs`, `vm`).
|
|
44
|
+
That means it’s currently **Node.js-oriented** (not browser) as implemented today.
|
|
45
|
+
|
|
46
|
+
## Concepts: Driver and cache
|
|
47
|
+
|
|
48
|
+
The client needs a `Driver` (from `@bob-kit/types`) to execute the generated SQL:
|
|
49
|
+
|
|
50
|
+
- **driver**: target engine (`"sqlite" | "mariadb" | "mysql" | "postgres"`).
|
|
51
|
+
- **querier(query, ...params)**: async function that executes SQL (and returns rows for `SELECT`).
|
|
52
|
+
- **cache**: optional implementation to cache transpilation results (memory, redis, etc.).
|
|
53
|
+
|
|
54
|
+
This package also exports a ready-to-use in-memory cache: `MemoryCache`.
|
|
55
|
+
|
|
56
|
+
## Quick start (Node + SQLite)
|
|
57
|
+
|
|
58
|
+
Complete example using `@bob-kit/sqlite` as the `querier`:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import bob from "@bob-kit/client";
|
|
62
|
+
import { MemoryCache } from "@bob-kit/client/cache";
|
|
63
|
+
import { sqlite } from "@bob-kit/sqlite";
|
|
64
|
+
|
|
65
|
+
const querier = sqlite(":memory:");
|
|
66
|
+
|
|
67
|
+
const client = bob({
|
|
68
|
+
driver: "sqlite",
|
|
69
|
+
querier,
|
|
70
|
+
cache: new MemoryCache(),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// 1) Define multiple tables in a single query
|
|
74
|
+
await client.query`
|
|
75
|
+
table Profile {
|
|
76
|
+
id id
|
|
77
|
+
avatar string
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
table Users {
|
|
81
|
+
id id
|
|
82
|
+
name string
|
|
83
|
+
lastName string
|
|
84
|
+
Profile
|
|
85
|
+
}
|
|
86
|
+
`;
|
|
87
|
+
|
|
88
|
+
// 2) Insert one entity
|
|
89
|
+
await client.query`
|
|
90
|
+
new Profile {
|
|
91
|
+
avatar "bear"
|
|
92
|
+
}
|
|
93
|
+
`;
|
|
94
|
+
|
|
95
|
+
// 3) Bulk insert with multiple rows and columns
|
|
96
|
+
await client.query`
|
|
97
|
+
new Users name lastName Profile.id {
|
|
98
|
+
"John" "Doe" 1
|
|
99
|
+
"Mary" "Jane" 3
|
|
100
|
+
"Robert" "Smith" 3
|
|
101
|
+
}
|
|
102
|
+
`;
|
|
103
|
+
|
|
104
|
+
// 4) Create reusable query functions with types
|
|
105
|
+
const getUserByName = (name: string) => client.query`
|
|
106
|
+
get Users {
|
|
107
|
+
name
|
|
108
|
+
profile_id
|
|
109
|
+
|
|
110
|
+
-> Profile {
|
|
111
|
+
avatar
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
desc Profile.id
|
|
115
|
+
}
|
|
116
|
+
`;
|
|
117
|
+
|
|
118
|
+
const users = await getUserByName("John");
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Advanced examples
|
|
122
|
+
|
|
123
|
+
#### Joins and relationships
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
// Join with related table
|
|
127
|
+
const usersWithProfiles = await client.query`
|
|
128
|
+
get Users {
|
|
129
|
+
id
|
|
130
|
+
name
|
|
131
|
+
lastName
|
|
132
|
+
|
|
133
|
+
-> Profile {
|
|
134
|
+
avatar
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
`;
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
#### Filtering and sorting
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
const filteredUsers = await client.query`
|
|
144
|
+
get Users {
|
|
145
|
+
id
|
|
146
|
+
name
|
|
147
|
+
if name = "John" || "Mary"
|
|
148
|
+
}
|
|
149
|
+
`;
|
|
150
|
+
|
|
151
|
+
const sortedUsers = await client.query`
|
|
152
|
+
get Users {
|
|
153
|
+
id
|
|
154
|
+
name
|
|
155
|
+
desc id
|
|
156
|
+
}
|
|
157
|
+
`;
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Parameters
|
|
161
|
+
|
|
162
|
+
The API accepts parameters as arguments to `query(...)`. Internally, the template literal is converted to a string using `?` as the placeholder.
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
const byEmail = await client.query`
|
|
166
|
+
get Users {
|
|
167
|
+
id
|
|
168
|
+
name
|
|
169
|
+
email
|
|
170
|
+
if email == ?
|
|
171
|
+
}
|
|
172
|
+
`("ada@lovelace.dev");
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## API
|
|
176
|
+
|
|
177
|
+
### `default export function bob(driver: Driver)`
|
|
178
|
+
|
|
179
|
+
Creates a client instance.
|
|
180
|
+
|
|
181
|
+
Returns an object with:
|
|
182
|
+
|
|
183
|
+
- **`query<A>(input, ...params): Promise<A[]>`**: executes a `bob` input. You can destructure it for convenience: `const { query: b } = bob(...)`.
|
|
184
|
+
- **`cache(id)(input, ...params): Promise<A[]>`**: same as `query`, but caches the transpilation result under a fixed `id`.
|
|
185
|
+
- **`factory.<id>(input, ...params): Promise<A[]>`**: shortcut for `cache("<id>")(...)`.
|
|
186
|
+
|
|
187
|
+
### `bobQuery({ driver, input, id? })`
|
|
188
|
+
|
|
189
|
+
Low-level function that only performs transpilation (and applies cache if present). You usually won’t need it.
|
|
190
|
+
|
|
191
|
+
### `@bob-kit/client/cache`
|
|
192
|
+
|
|
193
|
+
Includes:
|
|
194
|
+
|
|
195
|
+
- **`MemoryCache`**: in-memory (Map) cache for `BobQueryResult`.
|
|
196
|
+
|
|
197
|
+
## Errors
|
|
198
|
+
|
|
199
|
+
When Bob returns a parsing/validation/transpilation error, the client throws `BobError` with:
|
|
200
|
+
|
|
201
|
+
- **`name`**: a value from `BobErrors` (from `@bob-kit/types/errors`)
|
|
202
|
+
- **`message`**: error details
|
|
203
|
+
|
|
204
|
+
## Important notes
|
|
205
|
+
|
|
206
|
+
- **Multiple actions**: if your input generates more than 1 SQL action, the client throws (`MultipleActions`).
|
|
207
|
+
The current flow assumes **0 or 1 action** per execution.
|
|
208
|
+
- **Table execution**: if the output includes `tables`, all of them are executed (in order) before the action/query.
|
package/package.json
CHANGED