@truto/sqlite-builder 2.0.2-canary.13 → 2.0.2-canary.20

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.
Files changed (2) hide show
  1. package/README.md +23 -220
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,225 +1,28 @@
1
-
2
- // Dynamic column selection (simplified with array support)
3
- const columns = ['id', 'name', 'email']
4
- const selectQuery = sql`SELECT ${sql.ident(columns)} FROM users`
5
-
6
- // Alternative approach for more complex column expressions
7
- const complexColumns = [
8
- sql.ident('id'),
9
- sql.ident('name'),
10
- sql.raw('UPPER(email) as email_upper'),
11
- ]
12
- const complexQuery = sql`SELECT ${sql.join(complexColumns)} FROM users`
13
- ```
14
-
15
- ### Dynamic Queries with JSON Filters
16
-
17
- ```typescript
18
- import { sql, compileFilter } from '@truto/sqlite-builder'
19
-
20
- // API endpoint that accepts JSON filter
21
- app.get('/api/users', (req, res) => {
22
- // User sends filter as JSON
23
- const filter = req.body.filter || {}
24
-
25
- // Safely compile to SQL and interpolate directly. Filter values and the
26
- // LIMIT value are collected in order into query.values.
27
- const query = sql`
28
- SELECT id, name, email, created_at
29
- FROM users
30
- WHERE ${compileFilter(filter)}
31
- ORDER BY created_at DESC
32
- LIMIT ${req.query.limit || 20}
33
- `
34
-
35
- const users = db.prepare(query.text).all(...query.values)
36
- res.json(users)
37
- })
38
-
39
- // Example API calls:
40
- // POST /api/users { "filter": { "status": "ACTIVE", "age": { "gte": 18 } } }
41
- // POST /api/users { "filter": { "or": [{ "role": "ADMIN" }, { "verified": true }] } }
42
- ```
43
-
44
- ### Array Identifiers & Qualified Identifiers
45
-
46
- The `sql.ident()` function supports simple identifiers, qualified identifiers (table.column), arrays, and mixed arrays with SQL fragments:
47
-
48
- ```typescript
49
- // ✅ Simple identifiers
50
- const table = 'users'
51
- const column = 'name'
52
- const simpleQuery = sql`SELECT ${sql.ident(column)} FROM ${sql.ident(table)}`
53
- // Result: SELECT "name" FROM "users"
54
-
55
- // ✅ Qualified identifiers (table.column)
56
- const qualifiedQuery = sql`SELECT ${sql.ident('u.name')}, ${sql.ident('p.title')} FROM users u JOIN posts p ON u.id = p.user_id`
57
- // Result: SELECT "u"."name", "p"."title" FROM users u JOIN posts p ON u.id = p.user_id
58
-
59
- // ✅ Pure identifier arrays (clean and concise)
60
- const columns = ['id', 'name', 'email', 'created_at']
61
- const arrayQuery = sql`SELECT ${sql.ident(columns)} FROM users`
62
- // Result: SELECT "id", "name", "email", "created_at" FROM users
63
-
64
- // ✅ Mixed qualified and simple identifiers in arrays
65
- const mixedColumns = ['u.id', 'name', 'u.email', 'p.title', 'created_at']
66
- const mixedQuery = sql`SELECT ${sql.ident(mixedColumns)} FROM users u LEFT JOIN posts p ON u.id = p.user_id`
67
- // Result: SELECT "u"."id", "name", "u"."email", "p"."title", "created_at" FROM users u LEFT JOIN posts p ON u.id = p.user_id
68
-
69
- // ✅ NEW: Mixed arrays with identifiers and SQL fragments
70
- const mixedColumns = [
71
- 'id',
72
- 'name',
73
- sql.raw('UPPER(email) as email_upper'),
74
- sql.raw('COUNT(*) as total'),
75
- ]
76
- const mixedQuery = sql`SELECT ${sql.ident(mixedColumns)} FROM users GROUP BY id, name, email`
77
- // Result: SELECT "id", "name", UPPER(email) as email_upper, COUNT(*) as total FROM users GROUP BY id, name, email
78
-
79
- // ✅ Mixed arrays with parameterized fragments
80
- const status = 'premium'
81
- const dynamicColumns = [
82
- 'id',
83
- 'name',
84
- sql`CASE WHEN status = ${status} THEN 'Premium User' ELSE 'Regular User' END as user_type`,
85
- sql.raw('created_at'),
86
- ]
87
- const parameterizedQuery = sql`SELECT ${sql.ident(dynamicColumns)} FROM users WHERE active = ${true}`
88
- // Combines identifiers, raw SQL, and parameterized values seamlessly
89
-
90
- // ✅ Works great for INSERT statements
91
- const insertData = { name: 'John', email: 'john@example.com', age: 30 }
92
- const insertColumns = Object.keys(insertData)
93
- const insertValues = Object.values(insertData)
94
- const insertQuery = sql`
95
- INSERT INTO users (${sql.ident(insertColumns)})
96
- VALUES (${insertValues[0]}, ${insertValues[1]}, ${insertValues[2]})
97
- `
98
-
99
- // ✅ Dynamic column selection
100
- const userFields = ['name', 'email']
101
- const includeTimestamps = true
102
- if (includeTimestamps) {
103
- userFields.push('created_at', 'updated_at')
1
+ verified_at: { exists: true },
2
+ },
3
+
4
+ // Recent orders
5
+ $recent_orders: {
6
+ created_at: { gte: '2024-01-01' },
7
+ status: { in: ['completed', 'shipped'] },
8
+ total: { gt: 50 },
9
+ },
104
10
  }
105
- const dynamicQuery = sql`SELECT ${sql.ident(userFields)} FROM users`
106
-
107
- // 🆚 OLD: Manual joining approach (still works, but much more verbose)
108
- const oldWay = sql`SELECT ${sql.join([
109
- sql.ident('id'),
110
- sql.ident('name'),
111
- sql.raw('UPPER(email) as email_upper'),
112
- ])} FROM users`
113
- ```
114
-
115
- ### Complex Joins
116
11
 
117
- ```typescript
118
- const getUsersWithPosts = sql`
12
+ const complexQuery = sql`
119
13
  SELECT
120
- ${sql.ident('u')}.id,
121
- ${sql.ident('u')}.name,
122
- COUNT(${sql.ident('p')}.id) as post_count
123
- FROM ${sql.ident('users')} u
124
- LEFT JOIN ${sql.ident('posts')} p ON u.id = p.user_id
125
- WHERE u.created_at > ${startDate}
126
- AND u.status IN ${sql.in(['active', 'premium'])}
127
- GROUP BY u.id
128
- HAVING post_count > ${minPosts}
129
- ORDER BY post_count DESC
130
- LIMIT ${limit}
14
+ u.id,
15
+ u.name,
16
+ u.email,
17
+ p.verified_at,
18
+ COUNT(ro.id) as recent_order_count,
19
+ SUM(ro.total) as recent_order_total
20
+ FROM users u
21
+ JOIN profiles p ON u.id = p.user_id
22
+ JOIN orders ro ON u.id = ro.user_id
23
+ WHERE ${compileFilter(userOrderFilter)}
24
+ GROUP BY u.id, u.name, u.email, p.verified_at
25
+ HAVING recent_order_count > 0
26
+ ORDER BY recent_order_total DESC
131
27
  `
132
28
 
133
- // For simpler cases, you can use array identifiers directly
134
- const getUsers = sql`
135
- SELECT ${sql.ident(['id', 'name', 'email', 'created_at'])}
136
- FROM ${sql.ident('users')}
137
- WHERE status = ${'active'}
138
- `
139
- ```
140
-
141
- ### Transactions
142
-
143
- ```typescript
144
- // Works great with better-sqlite3 transactions
145
- const insertUsers = db.transaction((users) => {
146
- const stmt = db.prepare(
147
- sql`
148
- INSERT INTO users (name, email)
149
- VALUES (?, ?)
150
- `.text,
151
- )
152
-
153
- for (const user of users) {
154
- const { values } = sql`${user.name}, ${user.email}`
155
- stmt.run(...values)
156
- }
157
- })
158
-
159
- insertUsers([
160
- { name: 'Alice', email: 'alice@example.com' },
161
- { name: 'Bob', email: 'bob@example.com' },
162
- ])
163
- ```
164
-
165
- ## 🧪 Testing
166
-
167
- ```bash
168
- # Run tests
169
- bun run test
170
-
171
- # Run tests in watch mode
172
- bun run dev
173
-
174
- # Run tests with coverage
175
- bun run test:coverage
176
-
177
- # Run tests with UI
178
- bun run test:ui
179
- ```
180
-
181
- ## 🤝 Contributing
182
-
183
- We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
184
-
185
- ### Development Setup
186
-
187
- ```bash
188
- git clone https://github.com/truto/truto-sqlite-builder.git
189
- cd truto-sqlite-builder
190
- bun install
191
- bun run dev # Start tests in watch mode
192
- ```
193
-
194
- ### Release Process
195
-
196
- We use [changesets](https://github.com/changesets/changesets) for version management:
197
-
198
- ```bash
199
- # Add a changeset
200
- bunx changeset
201
-
202
- # Release
203
- bunx changeset version
204
- bun run build
205
- git commit -am "Release"
206
- git push --follow-tags
207
- ```
208
-
209
- ## 🔒 Security Policy
210
-
211
- If you discover a security vulnerability, please email eng@truto.one or create an issue.
212
-
213
- ## 📄 License
214
-
215
- MIT © [Truto](https://github.com/trutohq)
216
-
217
- ## 💡 Inspiration
218
-
219
- This library was inspired by:
220
-
221
- - [sql-template-strings](https://github.com/felixfbecker/sql-template-strings)
222
- - [slonik](https://github.com/gajus/slonik)
223
- - [Postgres.js](https://github.com/porsager/postgres)
224
-
225
- Built with ❤️ for the SQLite community.
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@truto/sqlite-builder","version":"2.0.2-canary.13","description":"debug canary","license":"MIT","main":"index.js"}
1
+ {"name":"@truto/sqlite-builder","version":"2.0.2-canary.20","description":"debug canary","license":"MIT","main":"index.js"}