bun-query-builder 0.1.10 → 0.1.11
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/LICENSE.md +21 -0
- package/README.md +489 -0
- package/dist/actions/migrate.d.ts +17 -7
- package/dist/browser.d.ts +290 -0
- package/dist/client.d.ts +5 -3
- package/dist/config.d.ts +19 -1
- package/dist/db.d.ts +20 -1
- package/dist/drivers/dynamodb.d.ts +338 -0
- package/dist/drivers/index.d.ts +27 -1
- package/dist/dynamodb/client.d.ts +178 -0
- package/dist/dynamodb/index.d.ts +156 -0
- package/dist/dynamodb/migration-driver.d.ts +55 -0
- package/dist/dynamodb/migration-tracker.d.ts +22 -0
- package/dist/dynamodb/migrations.d.ts +113 -0
- package/dist/dynamodb/model.d.ts +114 -0
- package/dist/dynamodb-client.d.ts +134 -0
- package/dist/dynamodb-single-table.d.ts +140 -0
- package/dist/dynamodb-tooling-adapter.d.ts +228 -0
- package/dist/index.d.ts +11 -1
- package/dist/index.js +9799 -826
- package/dist/model.d.ts +27 -0
- package/dist/orm.d.ts +172 -0
- package/dist/types.d.ts +18 -1
- package/package.json +18 -5
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Open Web Foundation
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
<p align="center"><img src=".github/art/cover.jpg" alt="Social Card of this repo"></p>
|
|
2
|
+
|
|
3
|
+
[![npm version][npm-version-src]][npm-version-href]
|
|
4
|
+
[![GitHub Actions][github-actions-src]][github-actions-href]
|
|
5
|
+
[](http://commitizen.github.io/cz-cli/)
|
|
6
|
+
<!-- [![npm downloads][npm-downloads-src]][npm-downloads-href] -->
|
|
7
|
+
<!-- [![Codecov][codecov-src]][codecov-href] -->
|
|
8
|
+
|
|
9
|
+
# bun-query-builder
|
|
10
|
+
|
|
11
|
+
Fully-typed, model-driven Query Builder for Bun’s native `sql`.
|
|
12
|
+
|
|
13
|
+
Define your data model once and get a type-safe query experience _(a la Kysely/Laravel)_, powered by Bun’s tagged templates for safety and performance.
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
### Core Query Building
|
|
18
|
+
|
|
19
|
+
- **Typed from Models**: Infer tables/columns/PKs from your model files; `selectFrom('users')` and `where({ active: true })` are typed.
|
|
20
|
+
- **Fluent Builder**: `select/insert/update/delete`, `where/andWhere/orWhere`, `join/leftJoin/rightJoin/crossJoin`, `groupBy/having`, `union/unionAll`.
|
|
21
|
+
- **Aggregations**: `count()`, `avg()`, `sum()`, `max()`, `min()` with full type safety.
|
|
22
|
+
- **Batch Operations**: `insertMany()`, `updateMany()`, `deleteMany()` for efficient bulk operations.
|
|
23
|
+
|
|
24
|
+
### Advanced Features
|
|
25
|
+
|
|
26
|
+
- **Relations**: `with(...)`, `withCount(...)`, `whereHas(...)`, `has()`, `doesntHave()`, `selectAllRelations()` with configurable aliasing and constraint callbacks.
|
|
27
|
+
- **Query Scopes**: Define reusable query constraints on models for cleaner, more maintainable code.
|
|
28
|
+
- **Query Caching**: Built-in LRU cache with TTL support via `cache(ttlMs)`, `clearQueryCache()`, `setQueryCacheMaxSize()`.
|
|
29
|
+
- **Model Hooks**: Lifecycle events - `beforeCreate`, `afterCreate`, `beforeUpdate`, `afterUpdate`, `beforeDelete`, `afterDelete`.
|
|
30
|
+
|
|
31
|
+
### Utilities & Helpers
|
|
32
|
+
|
|
33
|
+
- **Utilities**: `distinct/distinctOn`, `orderByDesc/latest/oldest/inRandomOrder`, `whereColumn/whereRaw/groupByRaw/havingRaw`, JSON/date helpers.
|
|
34
|
+
- **Pagination**: `paginate`, `simplePaginate`, `cursorPaginate`, plus `chunk/chunkById/eachById`.
|
|
35
|
+
- **Soft Deletes**: `withTrashed()`, `onlyTrashed()` for logical deletion support.
|
|
36
|
+
|
|
37
|
+
### Database Operations
|
|
38
|
+
|
|
39
|
+
- **Transactions**: `transaction` with retries/backoff/isolation/onRetry/afterCommit; `savepoint`; distributed tx helpers.
|
|
40
|
+
- **Migrations**: Generate and execute migrations from models with full diff support.
|
|
41
|
+
- **Seeders**: Database seeding with fake data generation via `ts-mocker` (faker alternative).
|
|
42
|
+
- **Raw Queries**: Tagged templates and parameterized queries with `raw()` and `unsafe()`.
|
|
43
|
+
|
|
44
|
+
### Configuration & Integration
|
|
45
|
+
|
|
46
|
+
- **Configurable**: Dialect hints, timestamps, alias strategies, relation FK formats, JSON mode, random function, shared lock syntax.
|
|
47
|
+
- **Bun API passthroughs**: `unsafe`, `file`, `simple`, pool `reserve/release`, `close`, `ping/waitForReady`.
|
|
48
|
+
- **CLI**: Introspection, query printing, connectivity checks, file/unsafe execution, explain.
|
|
49
|
+
|
|
50
|
+
> Note: LISTEN/NOTIFY and COPY helpers are scaffolded and will be wired as Bun exposes native APIs.
|
|
51
|
+
|
|
52
|
+
## Get Started
|
|
53
|
+
|
|
54
|
+
### Installation
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
bun add bun-query-builder
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Usage
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
import { buildDatabaseSchema, buildSchemaMeta, createQueryBuilder } from 'bun-query-builder'
|
|
64
|
+
|
|
65
|
+
// Load or define your model files (see docs for model shape)
|
|
66
|
+
const models = {
|
|
67
|
+
User: { name: 'User', table: 'users', primaryKey: 'id', attributes: { id: { validation: { rule: {} } }, name: { validation: { rule: {} } }, active: { validation: { rule: {} } } } },
|
|
68
|
+
} as const
|
|
69
|
+
|
|
70
|
+
const schema = buildDatabaseSchema(models as any)
|
|
71
|
+
const meta = buildSchemaMeta(models as any)
|
|
72
|
+
const db = createQueryBuilder<typeof schema>({ schema, meta })
|
|
73
|
+
|
|
74
|
+
// Fully-typed query
|
|
75
|
+
const q = db
|
|
76
|
+
.selectFrom('users')
|
|
77
|
+
.where({ active: true })
|
|
78
|
+
.orderBy('created_at', 'desc')
|
|
79
|
+
.limit(10)
|
|
80
|
+
|
|
81
|
+
const rows = await q.execute()
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Aggregations
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
// Get average age of active users
|
|
88
|
+
const avgAge = await db.selectFrom('users')
|
|
89
|
+
.where({ active: true })
|
|
90
|
+
.avg('age')
|
|
91
|
+
|
|
92
|
+
// Count total posts
|
|
93
|
+
const totalPosts = await db.selectFrom('posts').count()
|
|
94
|
+
|
|
95
|
+
// Get max and min scores
|
|
96
|
+
const maxScore = await db.selectFrom('users').max('score')
|
|
97
|
+
const minScore = await db.selectFrom('users').min('score')
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Batch Operations
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
// Insert multiple records at once
|
|
104
|
+
await db.insertMany('users', [
|
|
105
|
+
{ name: 'Alice', email: 'alice@example.com' },
|
|
106
|
+
{ name: 'Bob', email: 'bob@example.com' },
|
|
107
|
+
{ name: 'Charlie', email: 'charlie@example.com' },
|
|
108
|
+
])
|
|
109
|
+
|
|
110
|
+
// Update multiple records matching conditions
|
|
111
|
+
await db.updateMany('users', { verified: false }, { status: 'pending' })
|
|
112
|
+
|
|
113
|
+
// Delete multiple records by IDs
|
|
114
|
+
await db.deleteMany('users', [1, 2, 3, 4, 5])
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Query Caching
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
// Cache query results for 60 seconds (default)
|
|
121
|
+
const users = await db.selectFrom('users')
|
|
122
|
+
.where({ active: true })
|
|
123
|
+
.cache()
|
|
124
|
+
.get()
|
|
125
|
+
|
|
126
|
+
// Custom cache TTL (5 seconds)
|
|
127
|
+
const posts = await db.selectFrom('posts')
|
|
128
|
+
.orderBy('created_at', 'desc')
|
|
129
|
+
.limit(10)
|
|
130
|
+
.cache(5000)
|
|
131
|
+
.get()
|
|
132
|
+
|
|
133
|
+
// Clear all cached queries
|
|
134
|
+
clearQueryCache()
|
|
135
|
+
|
|
136
|
+
// Configure cache size
|
|
137
|
+
setQueryCacheMaxSize(500)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Model Hooks
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
const db = createQueryBuilder<typeof schema>({
|
|
144
|
+
schema,
|
|
145
|
+
meta,
|
|
146
|
+
hooks: {
|
|
147
|
+
beforeCreate: async ({ table, data }) => {
|
|
148
|
+
console.log(`Creating ${table}:`, data)
|
|
149
|
+
// Modify data, validate, or throw to prevent creation
|
|
150
|
+
},
|
|
151
|
+
afterCreate: async ({ table, data, result }) => {
|
|
152
|
+
console.log(`Created ${table}:`, result)
|
|
153
|
+
// Trigger notifications, update caches, etc.
|
|
154
|
+
},
|
|
155
|
+
beforeUpdate: async ({ table, data, where }) => {
|
|
156
|
+
// Audit logging, validation, etc.
|
|
157
|
+
},
|
|
158
|
+
afterUpdate: async ({ table, data, where, result }) => {
|
|
159
|
+
// Clear related caches, send webhooks, etc.
|
|
160
|
+
},
|
|
161
|
+
beforeDelete: async ({ table, where }) => {
|
|
162
|
+
// Prevent deletion, check constraints, etc.
|
|
163
|
+
},
|
|
164
|
+
afterDelete: async ({ table, where, result }) => {
|
|
165
|
+
// Clean up related data, update aggregates, etc.
|
|
166
|
+
},
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Query Scopes
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
// Define scopes on your models
|
|
175
|
+
const User = {
|
|
176
|
+
name: 'User',
|
|
177
|
+
table: 'users',
|
|
178
|
+
scopes: {
|
|
179
|
+
active: (qb) => qb.where({ status: 'active' }),
|
|
180
|
+
verified: (qb) => qb.where({ email_verified_at: ['IS NOT', null] }),
|
|
181
|
+
premium: (qb) => qb.where({ subscription: 'premium' }),
|
|
182
|
+
},
|
|
183
|
+
// ... other model properties
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Use scopes in queries
|
|
187
|
+
const activeUsers = await db.selectFrom('users')
|
|
188
|
+
.scope('active')
|
|
189
|
+
.scope('verified')
|
|
190
|
+
.get()
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Relations with Constraints
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
// Eager load with constraints
|
|
197
|
+
const users = await db.selectFrom('users')
|
|
198
|
+
.with({
|
|
199
|
+
posts: (qb) => qb.where('published', '=', true).orderBy('created_at', 'desc')
|
|
200
|
+
})
|
|
201
|
+
.get()
|
|
202
|
+
|
|
203
|
+
// Check for related records
|
|
204
|
+
const usersWithPosts = await db.selectFrom('users')
|
|
205
|
+
.has('posts')
|
|
206
|
+
.get()
|
|
207
|
+
|
|
208
|
+
// Query by relationship existence
|
|
209
|
+
const activeAuthors = await db.selectFrom('users')
|
|
210
|
+
.whereHas('posts', (qb) => qb.where('published', '=', true))
|
|
211
|
+
.get()
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Migrations
|
|
215
|
+
|
|
216
|
+
Generate and execute migrations from your models:
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
import { generateMigration, executeMigration } from 'bun-query-builder'
|
|
220
|
+
|
|
221
|
+
// Generate migration from models directory
|
|
222
|
+
const migration = await generateMigration('./models', {
|
|
223
|
+
dialect: 'postgres',
|
|
224
|
+
apply: true,
|
|
225
|
+
full: true
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
// Execute the migration
|
|
229
|
+
await executeMigration(migration)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Database Seeding
|
|
233
|
+
|
|
234
|
+
Populate your database with test data using seeders powered by [ts-mocker](https://github.com/stacksjs/ts-mocker):
|
|
235
|
+
|
|
236
|
+
### Creating a Seeder
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
# Generate a new seeder
|
|
240
|
+
bun qb make:seeder User
|
|
241
|
+
|
|
242
|
+
# This creates database/seeders/UserSeeder.ts
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Writing a Seeder
|
|
246
|
+
|
|
247
|
+
```ts
|
|
248
|
+
import { Seeder } from 'bun-query-builder'
|
|
249
|
+
import { faker } from 'ts-mocker'
|
|
250
|
+
|
|
251
|
+
export default class UserSeeder extends Seeder {
|
|
252
|
+
async run(qb: any): Promise<void> {
|
|
253
|
+
// Generate 50 users with realistic fake data
|
|
254
|
+
const users = Array.from({ length: 50 }, () => ({
|
|
255
|
+
name: faker.person.fullName(),
|
|
256
|
+
email: faker.internet.email(),
|
|
257
|
+
age: faker.number.int(18, 80),
|
|
258
|
+
role: faker.helpers.arrayElement(['admin', 'user', 'moderator']),
|
|
259
|
+
created_at: new Date(),
|
|
260
|
+
updated_at: new Date(),
|
|
261
|
+
}))
|
|
262
|
+
|
|
263
|
+
await qb.table('users').insert(users).execute()
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Control execution order (lower runs first)
|
|
267
|
+
get order(): number {
|
|
268
|
+
return 10 // Default is 100
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Running Seeders
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
# Run all seeders
|
|
277
|
+
bun qb seed
|
|
278
|
+
bun qb db:seed
|
|
279
|
+
|
|
280
|
+
# Run a specific seeder
|
|
281
|
+
bun qb seed --class UserSeeder
|
|
282
|
+
|
|
283
|
+
# Drop all tables, re-run migrations and seed
|
|
284
|
+
bun qb db:fresh
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Programmatic Usage
|
|
288
|
+
|
|
289
|
+
```ts
|
|
290
|
+
import { runSeeders, runSeeder } from 'bun-query-builder'
|
|
291
|
+
|
|
292
|
+
// Run all seeders
|
|
293
|
+
await runSeeders({
|
|
294
|
+
seedersDir: './database/seeders',
|
|
295
|
+
verbose: true
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
// Run specific seeder
|
|
299
|
+
await runSeeder('UserSeeder', { verbose: true })
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### CLI
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
# Model Generation
|
|
306
|
+
query-builder make:model User
|
|
307
|
+
query-builder make:model Post --table=blog_posts
|
|
308
|
+
query-builder model:show User # Show detailed model info
|
|
309
|
+
|
|
310
|
+
# Schema Introspection
|
|
311
|
+
query-builder introspect ./app/Models --verbose
|
|
312
|
+
query-builder sql ./app/Models users --limit 5
|
|
313
|
+
|
|
314
|
+
# Migrations
|
|
315
|
+
query-builder migrate ./app/Models --dialect postgres
|
|
316
|
+
query-builder migrate:generate # Generate migration from drift
|
|
317
|
+
query-builder migrate:status # Show migration status
|
|
318
|
+
query-builder migrate:list # List all migrations
|
|
319
|
+
query-builder migrate:rollback --steps 2 # Rollback migrations
|
|
320
|
+
query-builder migrate:fresh ./app/Models
|
|
321
|
+
query-builder reset ./app/Models
|
|
322
|
+
|
|
323
|
+
# Database Info
|
|
324
|
+
query-builder db:info # Show database statistics
|
|
325
|
+
query-builder db:stats # Alias for db:info
|
|
326
|
+
query-builder inspect users # Inspect table structure
|
|
327
|
+
query-builder table:info users # Alias for inspect
|
|
328
|
+
query-builder db:wipe --force # Drop all tables
|
|
329
|
+
query-builder db:optimize # Optimize database (VACUUM, ANALYZE)
|
|
330
|
+
query-builder db:optimize --aggressive # Aggressive optimization
|
|
331
|
+
|
|
332
|
+
# Interactive Console
|
|
333
|
+
query-builder console # Start REPL
|
|
334
|
+
query-builder tinker # Alias for console
|
|
335
|
+
|
|
336
|
+
# Seeders
|
|
337
|
+
query-builder make:seeder User
|
|
338
|
+
query-builder seed
|
|
339
|
+
query-builder db:seed --class UserSeeder
|
|
340
|
+
query-builder db:fresh
|
|
341
|
+
|
|
342
|
+
# Data Management
|
|
343
|
+
query-builder export users --format json
|
|
344
|
+
query-builder export users --format csv --output users.csv
|
|
345
|
+
query-builder import users users.json --truncate
|
|
346
|
+
query-builder dump --tables users,posts
|
|
347
|
+
|
|
348
|
+
# Cache Management
|
|
349
|
+
query-builder cache:clear
|
|
350
|
+
query-builder cache:stats
|
|
351
|
+
query-builder cache:config --size 500
|
|
352
|
+
|
|
353
|
+
# Performance
|
|
354
|
+
query-builder benchmark --iterations 1000
|
|
355
|
+
query-builder benchmark --operations select,insert
|
|
356
|
+
query-builder query:explain-all ./queries # Batch EXPLAIN analysis
|
|
357
|
+
|
|
358
|
+
# Schema Validation
|
|
359
|
+
query-builder validate:schema ./app/Models
|
|
360
|
+
query-builder check # Alias for validate:schema
|
|
361
|
+
|
|
362
|
+
# Connectivity
|
|
363
|
+
query-builder ping
|
|
364
|
+
query-builder wait-ready --attempts 30 --delay 250
|
|
365
|
+
|
|
366
|
+
# Execute SQL
|
|
367
|
+
query-builder file ./migrations/seed.sql
|
|
368
|
+
query-builder unsafe "SELECT * FROM users WHERE id = $1" --params "[1]"
|
|
369
|
+
query-builder explain "SELECT * FROM users WHERE active = true"
|
|
370
|
+
|
|
371
|
+
# Diagrams & Visualization
|
|
372
|
+
query-builder relation:diagram # Generate Mermaid ER diagram
|
|
373
|
+
query-builder relation:diagram --format dot # Generate Graphviz DOT
|
|
374
|
+
query-builder relation:diagram --output schema.mmd
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
## Performance
|
|
378
|
+
|
|
379
|
+
**🏆 bun-query-builder wins 13 out of 16 benchmarks (81.25%)**
|
|
380
|
+
|
|
381
|
+
### Summary
|
|
382
|
+
|
|
383
|
+
| Category | Win Rate | Performance vs Best |
|
|
384
|
+
|----------|----------|-------------------|
|
|
385
|
+
| Basic Queries | 7/7 (100%) 🎯 | 1.36x-29.29x faster |
|
|
386
|
+
| Advanced Queries | 4/5 (80%) | 1.01x-3.96x faster |
|
|
387
|
+
| Batch Operations | 2/4 (50%) | 1.45x-4.83x faster |
|
|
388
|
+
|
|
389
|
+
### Key Performance Wins
|
|
390
|
+
|
|
391
|
+
🚀 **Dominant in Basic Queries:**
|
|
392
|
+
|
|
393
|
+
- **29.29x faster** than Prisma in DELETE operations
|
|
394
|
+
- **16.45x faster** than Prisma in SELECT with LIMIT
|
|
395
|
+
- **14.86x faster** than Prisma in SELECT active users
|
|
396
|
+
- **13.8x faster** than Prisma in SELECT by ID
|
|
397
|
+
- **12.65x faster** than Prisma in COUNT queries
|
|
398
|
+
|
|
399
|
+
⚡ **Strong in Advanced Queries:**
|
|
400
|
+
|
|
401
|
+
- **3.96x faster** than Drizzle in AGGREGATE queries
|
|
402
|
+
- **2.99x faster** than Prisma in GROUP BY + HAVING
|
|
403
|
+
- **1.28x faster** than Prisma in JOIN operations
|
|
404
|
+
- **1.03x faster** than Kysely in JOIN operations
|
|
405
|
+
- **1.02x faster** than Kysely in AGGREGATE queries
|
|
406
|
+
|
|
407
|
+
💪 **Competitive in Batch Operations:**
|
|
408
|
+
|
|
409
|
+
- **4.83x faster** than Prisma in DELETE MANY
|
|
410
|
+
- **1.45x faster** than Kysely in DELETE MANY
|
|
411
|
+
- Within 14% of Kysely on INSERT MANY
|
|
412
|
+
|
|
413
|
+
### Perfect Category
|
|
414
|
+
|
|
415
|
+
- **100% wins** in basic CRUD operations (7/7) 🎯 - Beating Kysely, Drizzle, and Prisma in every single basic query
|
|
416
|
+
|
|
417
|
+
### The Trade-offs (3 out of 16)
|
|
418
|
+
|
|
419
|
+
- **WHERE: Complex conditions** - Kysely 1.05x faster
|
|
420
|
+
- **ORDER BY + LIMIT** - Kysely 1.07x faster
|
|
421
|
+
- **SELECT: Large result set (1000 rows)**
|
|
422
|
+
|
|
423
|
+
**Note:** Two additional benchmarks where we're competitive but not winning:
|
|
424
|
+
|
|
425
|
+
- **INSERT MANY: 100 users** - Kysely 1.14x faster
|
|
426
|
+
- **UPDATE MANY** - Prisma 1.10x faster
|
|
427
|
+
|
|
428
|
+
### Why Fast?
|
|
429
|
+
|
|
430
|
+
bun-query-builder leverages Bun's native SQLite driver with:
|
|
431
|
+
|
|
432
|
+
- **Direct BunDatabase access** - No abstraction layers
|
|
433
|
+
- **Statement caching** - Prepared statements reused across queries
|
|
434
|
+
- **Ultra-fast path** - Optimized execution for queries without hooks/soft-deletes
|
|
435
|
+
- **Smart optimizations** - For-loop template processing, minimal allocations
|
|
436
|
+
|
|
437
|
+
**[View Full Benchmark Results →](./packages/benchmark/README.md)**
|
|
438
|
+
|
|
439
|
+
## Testing
|
|
440
|
+
|
|
441
|
+
```bash
|
|
442
|
+
bun test
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
## Changelog
|
|
446
|
+
|
|
447
|
+
Please see our [releases](https://github.com/stackjs/bun-query-builder/releases) page for more information on what has changed recently.
|
|
448
|
+
|
|
449
|
+
## Contributing
|
|
450
|
+
|
|
451
|
+
Please see [CONTRIBUTING](.github/CONTRIBUTING.md) for details.
|
|
452
|
+
|
|
453
|
+
## Community
|
|
454
|
+
|
|
455
|
+
For help, discussion about best practices, or any other conversation that would benefit from being searchable:
|
|
456
|
+
|
|
457
|
+
[Discussions on GitHub](https://github.com/stacksjs/ts-starter/discussions)
|
|
458
|
+
|
|
459
|
+
For casual chit-chat with others using this package:
|
|
460
|
+
|
|
461
|
+
[Join the Stacks Discord Server](https://discord.gg/stacksjs)
|
|
462
|
+
|
|
463
|
+
## Postcardware
|
|
464
|
+
|
|
465
|
+
“Software that is free, but hopes for a postcard.” We love receiving postcards from around the world showing where Stacks is being used! We showcase them on our website too.
|
|
466
|
+
|
|
467
|
+
Our address: Stacks.js, 12665 Village Ln #2306, Playa Vista, CA 90094, United States 🌎
|
|
468
|
+
|
|
469
|
+
## Sponsors
|
|
470
|
+
|
|
471
|
+
We would like to extend our thanks to the following sponsors for funding Stacks development. If you are interested in becoming a sponsor, please reach out to us.
|
|
472
|
+
|
|
473
|
+
- [JetBrains](https://www.jetbrains.com/)
|
|
474
|
+
- [The Solana Foundation](https://solana.com/)
|
|
475
|
+
|
|
476
|
+
## License
|
|
477
|
+
|
|
478
|
+
The MIT License (MIT). Please see [LICENSE](LICENSE.md) for more information.
|
|
479
|
+
|
|
480
|
+
Made with 💙
|
|
481
|
+
|
|
482
|
+
<!-- Badges -->
|
|
483
|
+
[npm-version-src]: https://img.shields.io/npm/v/bun-query-builder?style=flat-square
|
|
484
|
+
[npm-version-href]: https://npmjs.com/package/bun-query-builder
|
|
485
|
+
[github-actions-src]: https://img.shields.io/github/actions/workflow/status/stacksjs/ts-starter/ci.yml?style=flat-square&branch=main
|
|
486
|
+
[github-actions-href]: https://github.com/stacksjs/ts-starter/actions?query=workflow%3Aci
|
|
487
|
+
|
|
488
|
+
<!-- [codecov-src]: https://img.shields.io/codecov/c/gh/stacksjs/ts-starter/main?style=flat-square
|
|
489
|
+
[codecov-href]: https://codecov.io/gh/stacksjs/ts-starter -->
|
|
@@ -1,21 +1,31 @@
|
|
|
1
1
|
import type { GenerateMigrationResult, MigrateOptions } from '@/types';
|
|
2
2
|
/**
|
|
3
|
-
* Generate migration files by comparing
|
|
3
|
+
* Generate migration files by comparing the stored model snapshot with current models.
|
|
4
4
|
*
|
|
5
5
|
* Workflow:
|
|
6
|
-
* 1. Loads previous
|
|
7
|
-
* 2. Loads current models from the source directory
|
|
8
|
-
* 3. Compares both to detect all changes:
|
|
6
|
+
* 1. Loads the previous migration plan from `.qb/model-snapshot.{dialect}.json`
|
|
7
|
+
* 2. Loads current models from the source directory and builds a new migration plan
|
|
8
|
+
* 3. Compares both plans to detect all changes:
|
|
9
9
|
* - Dropped tables, columns, indexes
|
|
10
10
|
* - New tables, columns, indexes
|
|
11
11
|
* - Modified columns (type changes, etc.)
|
|
12
|
-
* 4. Generates SQL migration files for
|
|
13
|
-
* 5.
|
|
12
|
+
* 4. Generates SQL migration files for only the detected differences
|
|
13
|
+
* 5. Saves the current plan as the new snapshot for future comparisons
|
|
14
14
|
*
|
|
15
15
|
* This follows Laravel's migration philosophy where model changes drive schema changes.
|
|
16
|
+
* Simply update your models and run migrations - the system automatically figures out what changed.
|
|
16
17
|
*/
|
|
17
18
|
export declare function generateMigration(dir?: string, opts?: MigrateOptions): Promise<GenerateMigrationResult>;
|
|
18
19
|
export declare function executeMigration(dir?: string): Promise<boolean>;
|
|
19
20
|
export declare function resetDatabase(dir?: string, opts?: MigrateOptions): Promise<boolean>;
|
|
20
21
|
export declare function deleteMigrationFiles(dir?: string, workspaceRoot?: string, opts?: MigrateOptions): Promise<void>;
|
|
21
|
-
|
|
22
|
+
/**
|
|
23
|
+
* @deprecated This function is no longer needed. Model snapshots are now stored as JSON migration plans.
|
|
24
|
+
* Keeping for backward compatibility but this is now a no-op.
|
|
25
|
+
*/
|
|
26
|
+
export declare function copyModelsToGenerated(_dir?: string, _workspaceRoot?: string): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Clear the generated directory to force fresh migration generation
|
|
29
|
+
* This is called during migrate:fresh to ensure all models are treated as new
|
|
30
|
+
*/
|
|
31
|
+
export declare function clearGeneratedDirectory(workspaceRoot?: string): Promise<void>;
|