@starbemtech/star-db-query-builder 1.0.13 → 1.0.15
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/coverage/clover.xml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<coverage generated="
|
|
3
|
-
<project timestamp="
|
|
2
|
+
<coverage generated="1713917118420" clover="3.2.0">
|
|
3
|
+
<project timestamp="1713917118420" name="All files">
|
|
4
4
|
<metrics statements="0" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0" elements="0" coveredelements="0" complexity="0" loc="0" ncloc="0" packages="0" files="0" classes="0"/>
|
|
5
5
|
</project>
|
|
6
6
|
</coverage>
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
87
87
|
Code coverage generated by
|
|
88
88
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
89
|
-
at 2024-04-
|
|
89
|
+
at 2024-04-24T00:05:18.412Z
|
|
90
90
|
</div>
|
|
91
91
|
<script src="prettify.js"></script>
|
|
92
92
|
<script>
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { v4 as uuid } from 'uuid'
|
|
2
|
-
import { QueryParams } from './types'
|
|
2
|
+
import { QueryParams, QueryBuilder } from './types'
|
|
3
3
|
import {
|
|
4
4
|
createGroupByClause,
|
|
5
5
|
createLimitClause,
|
|
@@ -145,7 +145,7 @@ export const update = async <P, R>({
|
|
|
145
145
|
const values: any[] = Object.values(data)
|
|
146
146
|
|
|
147
147
|
const setClause = generateSetClause(keys, dbClient.clientType)
|
|
148
|
-
let query = `UPDATE ${tableName} SET ${setClause} WHERE ${id}`
|
|
148
|
+
let query = `UPDATE ${tableName} SET ${setClause} WHERE id = '${id}'`
|
|
149
149
|
|
|
150
150
|
if (dbClient.clientType === 'pg') {
|
|
151
151
|
if (returning && returning.length > 0) {
|
|
@@ -195,3 +195,47 @@ export const deleteOne = async <T>({
|
|
|
195
195
|
[id]
|
|
196
196
|
)
|
|
197
197
|
}
|
|
198
|
+
|
|
199
|
+
export const joins = async <T>({
|
|
200
|
+
tableName,
|
|
201
|
+
dbClient,
|
|
202
|
+
select,
|
|
203
|
+
joins,
|
|
204
|
+
where,
|
|
205
|
+
}: QueryParams<T>): Promise<T[]> => {
|
|
206
|
+
if (!tableName) throw new Error('Table name is required')
|
|
207
|
+
if (!dbClient) throw new Error('DB client is required')
|
|
208
|
+
|
|
209
|
+
const fields = Array.isArray(select) ? select : []
|
|
210
|
+
const selectFields = createSelectFields(fields, dbClient.clientType)
|
|
211
|
+
const [whereClause, params] = createWhereClause(where, 1, dbClient.clientType)
|
|
212
|
+
|
|
213
|
+
const queryBuilder: QueryBuilder = {
|
|
214
|
+
select: [selectFields],
|
|
215
|
+
from: tableName,
|
|
216
|
+
joins: joins,
|
|
217
|
+
where: whereClause,
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const queryString = await buildQuery(queryBuilder)
|
|
221
|
+
|
|
222
|
+
const rows = await dbClient.query<T[]>(queryString, params)
|
|
223
|
+
|
|
224
|
+
return rows
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async function buildQuery(params: QueryBuilder): Promise<string> {
|
|
228
|
+
let queryString = `SELECT ${params.select.join(', ')} FROM ${params.from}`
|
|
229
|
+
|
|
230
|
+
if (params.joins) {
|
|
231
|
+
for (const join of params.joins) {
|
|
232
|
+
queryString += ` ${join.type} JOIN ${join.table} ON ${join.on}`
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (params.where) {
|
|
237
|
+
queryString += `${params.where}`
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return queryString
|
|
241
|
+
}
|
package/src/default/types.ts
CHANGED
|
@@ -31,6 +31,7 @@ export type Condition<T> = OperatorCondition | LogicalCondition<T>
|
|
|
31
31
|
interface LogicalCondition<T> {
|
|
32
32
|
OR?: Conditions<T>[]
|
|
33
33
|
AND?: Conditions<T>[]
|
|
34
|
+
JOINS?: Conditions<object>
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
export type Conditions<T> = {
|
|
@@ -41,6 +42,7 @@ export type DBClients = 'pg' | 'mysql'
|
|
|
41
42
|
|
|
42
43
|
export type OrderBy = { field: string; direction: 'ASC' | 'DESC' }[]
|
|
43
44
|
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
44
46
|
export interface QueryParams<T> {
|
|
45
47
|
tableName: string
|
|
46
48
|
dbClient: IDatabaseClient
|
|
@@ -50,4 +52,18 @@ export interface QueryParams<T> {
|
|
|
50
52
|
orderBy?: OrderBy
|
|
51
53
|
groupBy?: string[]
|
|
52
54
|
limit?: number
|
|
55
|
+
joins?: JoinClause[]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface JoinClause {
|
|
59
|
+
type: 'INNER' | 'LEFT' | 'RIGHT' | 'FULL'
|
|
60
|
+
table: string
|
|
61
|
+
on: string
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface QueryBuilder {
|
|
65
|
+
select: string[]
|
|
66
|
+
from?: string
|
|
67
|
+
joins?: JoinClause[]
|
|
68
|
+
where?: string
|
|
53
69
|
}
|
package/src/default/utils.ts
CHANGED
|
@@ -63,12 +63,19 @@ export const createWhereClause = <T>(
|
|
|
63
63
|
: mysqlPlaceholderGenerator()
|
|
64
64
|
)
|
|
65
65
|
.join(', ')
|
|
66
|
+
|
|
66
67
|
if (operator === 'BETWEEN') {
|
|
67
68
|
whereParts.push(
|
|
68
69
|
clientType === 'pg'
|
|
69
70
|
? `"${key}" ${operator} ${placeholders.replace(', ', ' AND ')}`
|
|
70
71
|
: `${key} ${operator} ${placeholders.replace(', ', ' AND ')}`
|
|
71
72
|
)
|
|
73
|
+
} else if (operator === 'IN') {
|
|
74
|
+
whereParts.push(
|
|
75
|
+
clientType === 'pg'
|
|
76
|
+
? `"${key}" ${operator} ${placeholders.replace(', ', ' AND ')}`
|
|
77
|
+
: `${key} ${operator} (${placeholders})`
|
|
78
|
+
)
|
|
72
79
|
} else {
|
|
73
80
|
whereParts.push(
|
|
74
81
|
clientType === 'pg'
|
|
@@ -83,14 +90,48 @@ export const createWhereClause = <T>(
|
|
|
83
90
|
? `"${key}" ${operator} ${pgPlaceholderGenerator(index++)}`
|
|
84
91
|
: `${key} ${operator} ${mysqlPlaceholderGenerator()}`
|
|
85
92
|
)
|
|
93
|
+
|
|
86
94
|
values.push(value)
|
|
87
95
|
}
|
|
88
|
-
} else {
|
|
89
|
-
console.error('Unsupported condition format: ', condition)
|
|
90
96
|
}
|
|
91
97
|
}
|
|
92
98
|
}
|
|
93
99
|
|
|
100
|
+
if ('JOINS' in conditions) {
|
|
101
|
+
const logicalOperator = conditions.JOINS ? 'AND' : 'OR'
|
|
102
|
+
const compositeConditions = conditions.JOINS
|
|
103
|
+
|
|
104
|
+
if (Array.isArray(compositeConditions)) {
|
|
105
|
+
const subWhereParts = compositeConditions
|
|
106
|
+
.map((subCondition: any) => {
|
|
107
|
+
if (
|
|
108
|
+
typeof subCondition === 'object' &&
|
|
109
|
+
!Array.isArray(subCondition) &&
|
|
110
|
+
subCondition !== null
|
|
111
|
+
) {
|
|
112
|
+
const key = Object.keys(subCondition)[0]
|
|
113
|
+
const condition = subCondition[key]
|
|
114
|
+
|
|
115
|
+
processCondition(key, condition)
|
|
116
|
+
return whereParts.pop()
|
|
117
|
+
}
|
|
118
|
+
return ''
|
|
119
|
+
})
|
|
120
|
+
.filter((part) => part)
|
|
121
|
+
whereParts.push(
|
|
122
|
+
clientType === 'pg'
|
|
123
|
+
? `(${subWhereParts.join(` ${logicalOperator} `)})`
|
|
124
|
+
: `${subWhereParts.join(` ${logicalOperator} `)}`
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
Object.entries(conditions).forEach(([key, value]) => {
|
|
129
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
130
|
+
// @ts-expect-error
|
|
131
|
+
processCondition(key, value)
|
|
132
|
+
})
|
|
133
|
+
}
|
|
134
|
+
|
|
94
135
|
if ('OR' in conditions || 'AND' in conditions) {
|
|
95
136
|
const logicalOperator = conditions.OR ? 'OR' : 'AND'
|
|
96
137
|
const compositeConditions = conditions.OR || conditions.AND
|
|
@@ -21,7 +21,7 @@ export const getByUserAndSubscription = async <T>({
|
|
|
21
21
|
`SELECT
|
|
22
22
|
${fields}
|
|
23
23
|
FROM payments.plan_association_users pa
|
|
24
|
-
|
|
24
|
+
LEFT JOIN payments.plans ON pa.plan_id = plans.id
|
|
25
25
|
${whereClause}
|
|
26
26
|
AND pa.status IN ('active', 'cancelation_requested', 'blocked')`,
|
|
27
27
|
params
|