bunql 1.0.0 → 1.0.1-dev.1
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 +33 -0
- package/package.json +1 -1
- package/src/index.test.ts +27 -0
- package/src/index.ts +63 -0
package/README.md
CHANGED
|
@@ -49,6 +49,35 @@ const users = await db.select('*').from('users').execute();
|
|
|
49
49
|
|
|
50
50
|
This makes the API more concise and intuitive while maintaining backward compatibility.
|
|
51
51
|
|
|
52
|
+
## Count Functionality
|
|
53
|
+
|
|
54
|
+
BunQL provides `.count()` methods on all query types to get the number of records:
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
// Count all records in a table
|
|
58
|
+
const totalUsers = await db.select('*').from('users').count();
|
|
59
|
+
|
|
60
|
+
// Count with WHERE conditions
|
|
61
|
+
const activeUsers = await db.select('*')
|
|
62
|
+
.from('users')
|
|
63
|
+
.where('active', '=', true)
|
|
64
|
+
.count();
|
|
65
|
+
|
|
66
|
+
// Count records that would be affected by an update
|
|
67
|
+
const usersToUpdate = await db.update('users')
|
|
68
|
+
.set({ active: false })
|
|
69
|
+
.where('last_login', '<', new Date('2023-01-01'))
|
|
70
|
+
.count();
|
|
71
|
+
|
|
72
|
+
// Count records that would be deleted
|
|
73
|
+
const usersToDelete = await db.delete('users')
|
|
74
|
+
.where('active', '=', false)
|
|
75
|
+
.count();
|
|
76
|
+
|
|
77
|
+
// Count total records in table (for insert queries)
|
|
78
|
+
const totalRecords = await db.insert('users').values({ name: 'Test' }).count();
|
|
79
|
+
```
|
|
80
|
+
|
|
52
81
|
## Usage Examples
|
|
53
82
|
|
|
54
83
|
### Select Queries
|
|
@@ -410,6 +439,7 @@ Methods for building SELECT queries.
|
|
|
410
439
|
- `execute()`: Execute the query and return results
|
|
411
440
|
- `first()`: Execute the query and return first result
|
|
412
441
|
- `all()`: Alias for `execute()`
|
|
442
|
+
- `count()`: Execute and return count of matching records
|
|
413
443
|
|
|
414
444
|
### InsertQuery
|
|
415
445
|
|
|
@@ -419,6 +449,7 @@ Methods for building INSERT queries.
|
|
|
419
449
|
|
|
420
450
|
- `values(data)`: Specify values to insert (object or array)
|
|
421
451
|
- `execute()`: Execute the insert query
|
|
452
|
+
- `count()`: Return count of total records in table
|
|
422
453
|
|
|
423
454
|
### UpdateQuery
|
|
424
455
|
|
|
@@ -429,6 +460,7 @@ Methods for building UPDATE queries.
|
|
|
429
460
|
- `set(data)`: Specify values to update
|
|
430
461
|
- `where(column, operator, value)`: Add WHERE condition
|
|
431
462
|
- `execute()`: Execute the update query
|
|
463
|
+
- `count()`: Return count of records that would be affected
|
|
432
464
|
|
|
433
465
|
### DeleteQuery
|
|
434
466
|
|
|
@@ -438,6 +470,7 @@ Methods for building DELETE queries.
|
|
|
438
470
|
|
|
439
471
|
- `where(column, operator, value)`: Add WHERE condition
|
|
440
472
|
- `execute()`: Execute the delete query
|
|
473
|
+
- `count()`: Return count of records that would be deleted
|
|
441
474
|
|
|
442
475
|
## Error Handling
|
|
443
476
|
|
package/package.json
CHANGED
package/src/index.test.ts
CHANGED
|
@@ -243,6 +243,33 @@ describe('BunQL', () => {
|
|
|
243
243
|
});
|
|
244
244
|
});
|
|
245
245
|
|
|
246
|
+
describe('Count Functionality', () => {
|
|
247
|
+
it('should have count method on select queries', () => {
|
|
248
|
+
const query = db.select('*').from('users');
|
|
249
|
+
expect(typeof query.count).toBe('function');
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it('should have count method on update queries', () => {
|
|
253
|
+
const query = db.update('users').set({ name: 'Test' });
|
|
254
|
+
expect(typeof query.count).toBe('function');
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('should have count method on insert queries', () => {
|
|
258
|
+
const query = db.insert('users').values({ name: 'Test' });
|
|
259
|
+
expect(typeof query.count).toBe('function');
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it('should have count method on delete queries', () => {
|
|
263
|
+
const query = db.delete('users').where('id', '=', 1);
|
|
264
|
+
expect(typeof query.count).toBe('function');
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('should throw error when calling count on select without table', async () => {
|
|
268
|
+
const query = db.select('*');
|
|
269
|
+
await expect(query.count()).rejects.toThrow('Table name is required. Use .from() method.');
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
|
|
246
273
|
describe('Method Availability', () => {
|
|
247
274
|
it('should have run method', () => {
|
|
248
275
|
expect(typeof db.run).toBe('function');
|
package/src/index.ts
CHANGED
|
@@ -198,6 +198,26 @@ export class SelectQuery<T = any> {
|
|
|
198
198
|
return this.execute();
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
+
async count(): Promise<number> {
|
|
202
|
+
if (!this.table) {
|
|
203
|
+
throw new Error('Table name is required. Use .from() method.');
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
let query = `SELECT COUNT(*) as count FROM "${this.table}"`;
|
|
207
|
+
|
|
208
|
+
if (this.whereClauses.length > 0) {
|
|
209
|
+
query += ` WHERE ${this.whereClauses.join(' AND ')}`;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const executor = this.transaction || this.sql;
|
|
213
|
+
const result = await executeSql(executor, query, this.whereParams);
|
|
214
|
+
// Handle different result formats
|
|
215
|
+
if (Array.isArray(result)) {
|
|
216
|
+
return result[0]?.count || 0;
|
|
217
|
+
}
|
|
218
|
+
return result.count || 0;
|
|
219
|
+
}
|
|
220
|
+
|
|
201
221
|
// Make the query awaitable by implementing then method
|
|
202
222
|
then<TResult1 = T[], TResult2 = never>(
|
|
203
223
|
onfulfilled?: ((value: T[]) => TResult1 | PromiseLike<TResult1>) | undefined | null,
|
|
@@ -252,6 +272,22 @@ export class UpdateQuery {
|
|
|
252
272
|
return await executeSql(executor, query, allParams);
|
|
253
273
|
}
|
|
254
274
|
|
|
275
|
+
async count(): Promise<number> {
|
|
276
|
+
let query = `SELECT COUNT(*) as count FROM "${this.table}"`;
|
|
277
|
+
|
|
278
|
+
if (this.whereClauses.length > 0) {
|
|
279
|
+
query += ` WHERE ${this.whereClauses.join(' AND ')}`;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const executor = this.transaction || this.sql;
|
|
283
|
+
const result = await executeSql(executor, query, this.whereParams);
|
|
284
|
+
// Handle different result formats
|
|
285
|
+
if (Array.isArray(result)) {
|
|
286
|
+
return result[0]?.count || 0;
|
|
287
|
+
}
|
|
288
|
+
return result.count || 0;
|
|
289
|
+
}
|
|
290
|
+
|
|
255
291
|
// Make the query awaitable by implementing then method
|
|
256
292
|
then<TResult1 = any, TResult2 = never>(
|
|
257
293
|
onfulfilled?: ((value: any) => TResult1 | PromiseLike<TResult1>) | undefined | null,
|
|
@@ -315,6 +351,17 @@ export class InsertQuery {
|
|
|
315
351
|
return await executeSql(executor, query, this.valuesArray);
|
|
316
352
|
}
|
|
317
353
|
|
|
354
|
+
async count(): Promise<number> {
|
|
355
|
+
let query = `SELECT COUNT(*) as count FROM "${this.table}"`;
|
|
356
|
+
const executor = this.transaction || this.sql;
|
|
357
|
+
const result = await executeSql(executor, query, []);
|
|
358
|
+
// Handle different result formats
|
|
359
|
+
if (Array.isArray(result)) {
|
|
360
|
+
return result[0]?.count || 0;
|
|
361
|
+
}
|
|
362
|
+
return result.count || 0;
|
|
363
|
+
}
|
|
364
|
+
|
|
318
365
|
// Make the query awaitable by implementing then method
|
|
319
366
|
then<TResult1 = any, TResult2 = never>(
|
|
320
367
|
onfulfilled?: ((value: any) => TResult1 | PromiseLike<TResult1>) | undefined | null,
|
|
@@ -354,6 +401,22 @@ export class DeleteQuery {
|
|
|
354
401
|
return await executeSql(executor, query, this.whereParams);
|
|
355
402
|
}
|
|
356
403
|
|
|
404
|
+
async count(): Promise<number> {
|
|
405
|
+
let query = `SELECT COUNT(*) as count FROM "${this.table}"`;
|
|
406
|
+
|
|
407
|
+
if (this.whereClauses.length > 0) {
|
|
408
|
+
query += ` WHERE ${this.whereClauses.join(' AND ')}`;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const executor = this.transaction || this.sql;
|
|
412
|
+
const result = await executeSql(executor, query, this.whereParams);
|
|
413
|
+
// Handle different result formats
|
|
414
|
+
if (Array.isArray(result)) {
|
|
415
|
+
return result[0]?.count || 0;
|
|
416
|
+
}
|
|
417
|
+
return result.count || 0;
|
|
418
|
+
}
|
|
419
|
+
|
|
357
420
|
// Make the query awaitable by implementing then method
|
|
358
421
|
then<TResult1 = any, TResult2 = never>(
|
|
359
422
|
onfulfilled?: ((value: any) => TResult1 | PromiseLike<TResult1>) | undefined | null,
|