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 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bunql",
3
- "version": "1.0.0",
3
+ "version": "1.0.1-dev.1",
4
4
  "description": "A fluent SQL query builder for Bun with transaction support",
5
5
  "module": "src/index.ts",
6
6
  "type": "module",
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,