@starbemtech/star-db-query-builder 1.3.0 → 1.4.0

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 (75) hide show
  1. package/.claude/skills/star-db-query-builder/SKILL.md +104 -0
  2. package/CHANGELOG.md +81 -46
  3. package/LICENSE +21 -0
  4. package/README.md +194 -94
  5. package/bin/install-skill.js +53 -0
  6. package/dist/src/core/repository.d.ts +92 -9
  7. package/dist/src/core/repository.js +275 -27
  8. package/dist/src/core/repository.js.map +1 -1
  9. package/dist/src/core/types.d.ts +17 -2
  10. package/dist/src/core/utils.d.ts +102 -0
  11. package/dist/src/core/utils.js +287 -70
  12. package/dist/src/core/utils.js.map +1 -1
  13. package/dist/src/db/initDb.d.ts +60 -50
  14. package/dist/src/db/initDb.js +96 -64
  15. package/dist/src/db/initDb.js.map +1 -1
  16. package/dist/src/db/mysqlClient.d.ts +3 -8
  17. package/dist/src/db/mysqlClient.js +9 -11
  18. package/dist/src/db/mysqlClient.js.map +1 -1
  19. package/dist/src/db/pgClient.js +0 -2
  20. package/dist/src/db/pgClient.js.map +1 -1
  21. package/dist/src/monitor/monitor.js +7 -0
  22. package/dist/src/monitor/monitor.js.map +1 -1
  23. package/package.json +28 -20
  24. package/.github/workflows/publish.yml +0 -118
  25. package/.prettierignore +0 -3
  26. package/.prettierrc +0 -5
  27. package/ARCHITECTURE.md +0 -313
  28. package/coverage/base.css +0 -224
  29. package/coverage/block-navigation.js +0 -87
  30. package/coverage/favicon.png +0 -0
  31. package/coverage/index.html +0 -131
  32. package/coverage/lcov-report/base.css +0 -224
  33. package/coverage/lcov-report/block-navigation.js +0 -87
  34. package/coverage/lcov-report/favicon.png +0 -0
  35. package/coverage/lcov-report/index.html +0 -131
  36. package/coverage/lcov-report/mysqlClient.ts.html +0 -685
  37. package/coverage/lcov-report/pgClient.ts.html +0 -823
  38. package/coverage/lcov-report/prettify.css +0 -1
  39. package/coverage/lcov-report/prettify.js +0 -2
  40. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  41. package/coverage/lcov-report/sorter.js +0 -210
  42. package/coverage/lcov.info +0 -533
  43. package/coverage/mysqlClient.ts.html +0 -685
  44. package/coverage/pgClient.ts.html +0 -823
  45. package/coverage/prettify.css +0 -1
  46. package/coverage/prettify.js +0 -2
  47. package/coverage/sort-arrow-sprite.png +0 -0
  48. package/coverage/sorter.js +0 -210
  49. package/dist/src/setupTests.d.ts +0 -26
  50. package/dist/src/setupTests.js +0 -43
  51. package/dist/src/setupTests.js.map +0 -1
  52. package/docs/INDEX.md +0 -145
  53. package/docs/methods/findFirst.md +0 -394
  54. package/docs/methods/findMany.md +0 -587
  55. package/docs/methods/insert.md +0 -536
  56. package/docs/methods/insertMany.md +0 -627
  57. package/docs/methods/joins.md +0 -781
  58. package/docs/methods/rawQuery.md +0 -284
  59. package/docs/methods/transactions.md +0 -737
  60. package/eslint.config.mjs +0 -77
  61. package/index.ts +0 -16
  62. package/jest.config.ts +0 -194
  63. package/scripts/release.sh +0 -123
  64. package/src/core/repository.ts +0 -865
  65. package/src/core/types.ts +0 -97
  66. package/src/core/utils.ts +0 -357
  67. package/src/db/IDatabaseClient.ts +0 -16
  68. package/src/db/__tests__/mysqlClient.test.ts +0 -262
  69. package/src/db/__tests__/pgClient.test.ts +0 -260
  70. package/src/db/initDb.ts +0 -181
  71. package/src/db/mysqlClient.ts +0 -200
  72. package/src/db/pgClient.ts +0 -246
  73. package/src/monitor/monitor.ts +0 -16
  74. package/src/setupTests.ts +0 -45
  75. package/tsconfig.test.json +0 -21
@@ -1,394 +0,0 @@
1
- # findFirst
2
-
3
- Finds the first record that matches the specified conditions from a database table.
4
-
5
- ## Signature
6
-
7
- ```typescript
8
- findFirst<T>({
9
- tableName: string,
10
- dbClient: IDatabaseClient,
11
- select?: string[],
12
- where?: Conditions<T>,
13
- groupBy?: string[],
14
- orderBy?: OrderBy
15
- }): Promise<T | null>
16
- ```
17
-
18
- ## Parameters
19
-
20
- | Parameter | Type | Required | Description |
21
- | ----------- | ----------------- | -------- | ---------------------------------------------------- |
22
- | `tableName` | `string` | ✅ | Name of the database table |
23
- | `dbClient` | `IDatabaseClient` | ✅ | Database client instance |
24
- | `select` | `string[]` | ❌ | Array of field names to select (default: all fields) |
25
- | `where` | `Conditions<T>` | ❌ | Conditions to filter records |
26
- | `groupBy` | `string[]` | ❌ | Fields to group by |
27
- | `orderBy` | `OrderBy` | ❌ | Sort order specification |
28
-
29
- ## Return Value
30
-
31
- - **Type**: `Promise<T | null>`
32
- - **Description**: Returns the first matching record or `null` if no record is found
33
-
34
- ## Examples
35
-
36
- ### Basic Usage
37
-
38
- ```typescript
39
- import { findFirst } from '@starbemtech/star-db-query-builder'
40
-
41
- // Find user by email
42
- const user = await findFirst({
43
- tableName: 'users',
44
- dbClient,
45
- where: {
46
- email: { operator: '=', value: 'user@example.com' },
47
- },
48
- })
49
-
50
- console.log(user) // { id: 'user-123', name: 'John Doe', email: 'user@example.com', ... }
51
- ```
52
-
53
- ### With Specific Fields
54
-
55
- ```typescript
56
- // Select only specific fields
57
- const user = await findFirst({
58
- tableName: 'users',
59
- dbClient,
60
- select: ['id', 'name', 'email'],
61
- where: {
62
- status: { operator: '=', value: 'active' },
63
- },
64
- })
65
-
66
- console.log(user) // { id: 'user-123', name: 'John Doe', email: 'user@example.com' }
67
- ```
68
-
69
- ### With Complex Conditions
70
-
71
- ```typescript
72
- // Multiple conditions with AND
73
- const user = await findFirst({
74
- tableName: 'users',
75
- dbClient,
76
- where: {
77
- AND: [
78
- { email: { operator: '=', value: 'user@example.com' } },
79
- { status: { operator: '=', value: 'active' } },
80
- { verified: { operator: '=', value: true } },
81
- ],
82
- },
83
- })
84
-
85
- // Multiple conditions with OR
86
- const user = await findFirst({
87
- tableName: 'users',
88
- dbClient,
89
- where: {
90
- OR: [
91
- { email: { operator: '=', value: 'user@example.com' } },
92
- { phone: { operator: '=', value: '+1234567890' } },
93
- ],
94
- },
95
- })
96
- ```
97
-
98
- ### With Ordering
99
-
100
- ```typescript
101
- // Find the most recent user
102
- const latestUser = await findFirst({
103
- tableName: 'users',
104
- dbClient,
105
- orderBy: [{ field: 'created_at', direction: 'DESC' }],
106
- })
107
-
108
- // Find the oldest active user
109
- const oldestUser = await findFirst({
110
- tableName: 'users',
111
- dbClient,
112
- where: { status: { operator: '=', value: 'active' } },
113
- orderBy: [{ field: 'created_at', direction: 'ASC' }],
114
- })
115
- ```
116
-
117
- ### With Grouping
118
-
119
- ```typescript
120
- // Find the first user in each status group
121
- const userByStatus = await findFirst({
122
- tableName: 'users',
123
- dbClient,
124
- select: ['status', 'name', 'created_at'],
125
- groupBy: ['status'],
126
- orderBy: [{ field: 'created_at', direction: 'ASC' }],
127
- })
128
- ```
129
-
130
- ### Advanced Conditions
131
-
132
- ```typescript
133
- // Using different operators
134
- const user = await findFirst({
135
- tableName: 'users',
136
- dbClient,
137
- where: {
138
- age: { operator: '>=', value: 18 },
139
- name: { operator: 'LIKE', value: '%John%' },
140
- email: { operator: 'IS NOT NULL', value: null },
141
- status: { operator: 'IN', value: ['active', 'pending'] },
142
- },
143
- })
144
-
145
- // Using BETWEEN
146
- const user = await findFirst({
147
- tableName: 'users',
148
- dbClient,
149
- where: {
150
- created_at: {
151
- operator: 'BETWEEN',
152
- value: [new Date('2023-01-01'), new Date('2023-12-31')],
153
- },
154
- },
155
- })
156
- ```
157
-
158
- ### TypeScript Usage
159
-
160
- ```typescript
161
- interface User {
162
- id: string
163
- name: string
164
- email: string
165
- age: number
166
- status: 'active' | 'inactive' | 'pending'
167
- created_at: Date
168
- updated_at: Date
169
- }
170
-
171
- // Typed usage
172
- const user: User | null = await findFirst<User>({
173
- tableName: 'users',
174
- dbClient,
175
- where: {
176
- email: { operator: '=', value: 'user@example.com' },
177
- },
178
- })
179
-
180
- if (user) {
181
- console.log(`Found user: ${user.name}`)
182
- } else {
183
- console.log('User not found')
184
- }
185
- ```
186
-
187
- ### Error Handling
188
-
189
- ```typescript
190
- try {
191
- const user = await findFirst({
192
- tableName: 'users',
193
- dbClient,
194
- where: { email: { operator: '=', value: 'user@example.com' } },
195
- })
196
-
197
- if (user) {
198
- console.log('User found:', user.name)
199
- } else {
200
- console.log('No user found with this email')
201
- }
202
- } catch (error) {
203
- console.error('Database error:', error.message)
204
- // Handle error appropriately
205
- }
206
- ```
207
-
208
- ## Generated SQL Examples
209
-
210
- ### Simple Query
211
-
212
- ```sql
213
- SELECT * FROM users WHERE email = $1 LIMIT 1
214
- ```
215
-
216
- ### With Specific Fields
217
-
218
- ```sql
219
- SELECT id, name, email FROM users WHERE status = $1 LIMIT 1
220
- ```
221
-
222
- ### With Complex Conditions
223
-
224
- ```sql
225
- SELECT * FROM users
226
- WHERE (email = $1 AND status = $2 AND verified = $3)
227
- LIMIT 1
228
- ```
229
-
230
- ### With Ordering
231
-
232
- ```sql
233
- SELECT * FROM users
234
- ORDER BY created_at DESC
235
- LIMIT 1
236
- ```
237
-
238
- ### With Grouping
239
-
240
- ```sql
241
- SELECT status, name, created_at
242
- FROM users
243
- GROUP BY status
244
- ORDER BY created_at ASC
245
- LIMIT 1
246
- ```
247
-
248
- ## Best Practices
249
-
250
- ### 1. Use Specific Field Selection
251
-
252
- ```typescript
253
- // Good: Select only needed fields
254
- const user = await findFirst({
255
- tableName: 'users',
256
- dbClient,
257
- select: ['id', 'name', 'email'],
258
- where: { id: { operator: '=', value: 'user-123' } },
259
- })
260
-
261
- // Avoid: Selecting all fields when not needed
262
- const user = await findFirst({
263
- tableName: 'users',
264
- dbClient,
265
- where: { id: { operator: '=', value: 'user-123' } },
266
- })
267
- ```
268
-
269
- ### 2. Use Appropriate Indexes
270
-
271
- Ensure your database has indexes on fields used in WHERE clauses for better performance:
272
-
273
- ```sql
274
- -- Example indexes for common queries
275
- CREATE INDEX idx_users_email ON users(email);
276
- CREATE INDEX idx_users_status ON users(status);
277
- CREATE INDEX idx_users_created_at ON users(created_at);
278
- ```
279
-
280
- ### 3. Handle Null Results
281
-
282
- ```typescript
283
- const user = await findFirst({
284
- tableName: 'users',
285
- dbClient,
286
- where: { email: { operator: '=', value: 'nonexistent@example.com' } },
287
- })
288
-
289
- if (!user) {
290
- // Handle case when no user is found
291
- throw new Error('User not found')
292
- }
293
- ```
294
-
295
- ### 4. Use TypeScript for Type Safety
296
-
297
- ```typescript
298
- interface UserSearchParams {
299
- email?: string
300
- status?: string
301
- age?: number
302
- }
303
-
304
- const findUserByParams = async (
305
- params: UserSearchParams
306
- ): Promise<User | null> => {
307
- const where: Conditions<User> = {}
308
-
309
- if (params.email) {
310
- where.email = { operator: '=', value: params.email }
311
- }
312
-
313
- if (params.status) {
314
- where.status = { operator: '=', value: params.status }
315
- }
316
-
317
- if (params.age) {
318
- where.age = { operator: '>=', value: params.age }
319
- }
320
-
321
- return findFirst<User>({
322
- tableName: 'users',
323
- dbClient,
324
- where,
325
- })
326
- }
327
- ```
328
-
329
- ## Common Use Cases
330
-
331
- ### 1. User Authentication
332
-
333
- ```typescript
334
- const authenticateUser = async (email: string, password: string) => {
335
- const user = await findFirst({
336
- tableName: 'users',
337
- dbClient,
338
- where: {
339
- AND: [
340
- { email: { operator: '=', value: email } },
341
- { password: { operator: '=', value: password } },
342
- { status: { operator: '=', value: 'active' } },
343
- ],
344
- },
345
- })
346
-
347
- return user
348
- }
349
- ```
350
-
351
- ### 2. Finding Latest Record
352
-
353
- ```typescript
354
- const getLatestOrder = async (userId: string) => {
355
- const order = await findFirst({
356
- tableName: 'orders',
357
- dbClient,
358
- where: { user_id: { operator: '=', value: userId } },
359
- orderBy: [{ field: 'created_at', direction: 'DESC' }],
360
- })
361
-
362
- return order
363
- }
364
- ```
365
-
366
- ### 3. Checking Existence
367
-
368
- ```typescript
369
- const userExists = async (email: string): Promise<boolean> => {
370
- const user = await findFirst({
371
- tableName: 'users',
372
- dbClient,
373
- select: ['id'],
374
- where: { email: { operator: '=', value: email } },
375
- })
376
-
377
- return user !== null
378
- }
379
- ```
380
-
381
- ## Performance Considerations
382
-
383
- - **Indexes**: Ensure proper indexes exist on fields used in WHERE clauses
384
- - **Field Selection**: Use `select` to limit returned fields when possible
385
- - **Limit Results**: `findFirst` automatically limits to 1 result, which is optimal
386
- - **Connection Pooling**: Use connection pooling for better performance in high-traffic applications
387
-
388
- ## Error Messages
389
-
390
- Common error messages you might encounter:
391
-
392
- - `Table name is required` - The `tableName` parameter is missing
393
- - `DB client is required` - The `dbClient` parameter is missing
394
- - Database-specific errors from the underlying database driver