@things-factory/shell 5.0.0-alpha.5 → 5.0.0-alpha.50

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.
@@ -1,6 +1,9 @@
1
- import { Brackets } from 'typeorm'
1
+ import { Brackets, Repository, SelectQueryBuilder } from 'typeorm'
2
+ import { ColumnMetadata } from 'typeorm/metadata/ColumnMetadata'
2
3
 
4
+ import { Domain } from '../service/domain/domain'
3
5
  import { buildCondition } from './condition-builder'
6
+ import { buildWhereClause } from './where-clause-builder'
4
7
 
5
8
  export const buildQuery = function (queryBuilder: any, params: any, context: any, domainRef: Boolean = true) {
6
9
  const columnFilters = params.filters?.filter(filter => filter.operator !== 'search') || []
@@ -58,3 +61,92 @@ export const buildQuery = function (queryBuilder: any, params: any, context: any
58
61
  })
59
62
  }
60
63
  }
64
+
65
+ export function getQueryBuilderFromListParams<Type>(options: {
66
+ repository: Repository<Type>
67
+ params: any
68
+ domain?: Domain
69
+ alias?: string
70
+ }): SelectQueryBuilder<Type> {
71
+ var { repository, params, domain, alias } = options
72
+ const selectQueryBuilder = repository.createQueryBuilder(alias)
73
+ alias = selectQueryBuilder.alias
74
+
75
+ const columnFilters = params.filters?.filter(filter => filter.operator !== 'search') || []
76
+ const searchFilters = params.filters?.filter(filter => filter.operator === 'search') || []
77
+ const pagination = params.pagination
78
+ const sortings = params.sortings
79
+
80
+ const metadata = repository.metadata
81
+ const columnMetas = params.filters
82
+ .map(filter => filter.name)
83
+ .reduce((sum, name) => {
84
+ sum[name] = metadata.columns.find(column => column.propertyName === name)
85
+ return sum
86
+ }, {} as { [name: string]: ColumnMetadata })
87
+
88
+ if (columnFilters && columnFilters.length > 0) {
89
+ columnFilters.forEach(filter => {
90
+ const { name, operator, value } = filter
91
+
92
+ const condition = buildWhereClause({
93
+ alias,
94
+ columnMeta: columnMetas[name],
95
+ operator,
96
+ value,
97
+ seq: Object.keys(selectQueryBuilder.getParameters()).length + 1,
98
+ domain,
99
+ selectQueryBuilder
100
+ })
101
+
102
+ if (condition?.clause) selectQueryBuilder.andWhere(condition.clause)
103
+ if (condition?.parameters) selectQueryBuilder.setParameters(condition.parameters)
104
+ })
105
+ }
106
+
107
+ if (searchFilters.length > 0) {
108
+ selectQueryBuilder.andWhere(
109
+ new Brackets(qb => {
110
+ searchFilters.forEach(filter => {
111
+ const { name, operator, value } = filter
112
+
113
+ const condition = buildWhereClause({
114
+ alias,
115
+ columnMeta: columnMetas[name],
116
+ operator /* has to be 'search' */,
117
+ value,
118
+ seq: Object.keys(selectQueryBuilder.getParameters()).length + 1,
119
+ domain,
120
+ selectQueryBuilder
121
+ })
122
+
123
+ if (condition?.clause) qb.orWhere(condition.clause)
124
+ if (condition?.parameters) selectQueryBuilder.setParameters(condition.parameters)
125
+ })
126
+ })
127
+ )
128
+ }
129
+
130
+ if (domain) {
131
+ selectQueryBuilder.andWhere(`${selectQueryBuilder.alias}.domain = :domain`, { domain: domain.id })
132
+ }
133
+
134
+ if (pagination && pagination.page > 0 && pagination.limit > 0) {
135
+ selectQueryBuilder.skip(pagination.limit * (pagination.page - 1))
136
+ selectQueryBuilder.take(pagination.limit)
137
+ }
138
+
139
+ if (sortings && sortings.length > 0) {
140
+ sortings.forEach((sorting, index) => {
141
+ const sortField =
142
+ sorting.name.split('.').length > 1 ? sorting.name : `${selectQueryBuilder.alias}.${sorting.name}`
143
+ if (index === 0) {
144
+ selectQueryBuilder.orderBy(sortField, sorting.desc ? 'DESC' : 'ASC')
145
+ } else {
146
+ selectQueryBuilder.addOrderBy(sortField, sorting.desc ? 'DESC' : 'ASC')
147
+ }
148
+ })
149
+ }
150
+
151
+ return selectQueryBuilder
152
+ }
@@ -0,0 +1,200 @@
1
+ import { SelectQueryBuilder } from 'typeorm'
2
+ import { ColumnMetadata } from 'typeorm/metadata/ColumnMetadata'
3
+
4
+ import { Domain } from '../service/domain/domain'
5
+
6
+ function getClause(
7
+ selectQueryBuilder: SelectQueryBuilder<any>,
8
+ columnMeta: ColumnMetadata,
9
+ operator: string,
10
+ field: string,
11
+ pname: string
12
+ ): string {
13
+ const relation = columnMeta.relationMetadata
14
+
15
+ if (!relation) {
16
+ switch (operator) {
17
+ case 'like':
18
+ return `${field} LIKE :${pname}`
19
+
20
+ case 'search':
21
+ case 'i_like':
22
+ return `LOWER(${field}) LIKE :${pname}`
23
+
24
+ case 'nlike':
25
+ return `${field} NOT LIKE :${pname}`
26
+
27
+ case 'i_nlike':
28
+ return `LOWER(${field}) NOT LIKE :${pname}`
29
+ }
30
+ }
31
+
32
+ const inverseEntityMetadata = relation.inverseEntityMetadata
33
+ const { target, tableName, ownColumns } = inverseEntityMetadata
34
+ var subquery = selectQueryBuilder.subQuery().select('id').from(target, tableName)
35
+
36
+ switch (operator) {
37
+ case 'like':
38
+ subquery = subquery.where(`${tableName}.name LIKE :${pname}`)
39
+ break
40
+
41
+ case 'search':
42
+ case 'i_like':
43
+ subquery = subquery.where(`LOWER(${tableName}.name) LIKE :${pname}`)
44
+ break
45
+
46
+ case 'nlike':
47
+ subquery = subquery.where(`${tableName}.name NOT LIKE :${pname}`)
48
+ break
49
+
50
+ case 'i_nlike':
51
+ subquery = subquery.where(`LOWER(${tableName}.name) NOT LIKE :${pname}`)
52
+ break
53
+ }
54
+
55
+ if (ownColumns.find(column => column.propertyName === 'domain')) {
56
+ subquery.andWhere(`${tableName}.domain_id = :domain`)
57
+ }
58
+
59
+ return `${field} IN ${subquery.getQuery()}`
60
+ }
61
+
62
+ export const buildWhereClause = function (options: {
63
+ alias: string
64
+ columnMeta: ColumnMetadata
65
+ operator: string
66
+ value: any
67
+ seq: number
68
+ domain: Domain
69
+ selectQueryBuilder: SelectQueryBuilder<any>
70
+ }) {
71
+ const { alias, columnMeta, operator, value, seq, selectQueryBuilder, domain } = options
72
+ const values = value instanceof Array ? value : [value]
73
+ const { propertyName: name, propertyAliasName, propertyPath: path, databaseName } = columnMeta
74
+ const field = `${alias}.${databaseName}`
75
+ const pname = `args${seq}`
76
+
77
+ switch (operator) {
78
+ case 'eq':
79
+ return {
80
+ clause: `${field} = :${pname}`,
81
+ parameters: { [pname]: value }
82
+ }
83
+
84
+ case 'like':
85
+ return {
86
+ clause: getClause(selectQueryBuilder, columnMeta, operator, field, pname),
87
+ parameters: { [pname]: `%${value}%` }
88
+ }
89
+
90
+ case 'search':
91
+ case 'i_like':
92
+ return {
93
+ clause: getClause(selectQueryBuilder, columnMeta, operator, field, pname),
94
+ parameters: { [pname]: `%${String(value).toLowerCase()}%` }
95
+ }
96
+
97
+ case 'nlike':
98
+ return {
99
+ clause: getClause(selectQueryBuilder, columnMeta, operator, field, pname),
100
+ value: { [pname]: `%${value}%` }
101
+ }
102
+
103
+ case 'i_nlike':
104
+ return {
105
+ clause: getClause(selectQueryBuilder, columnMeta, operator, field, pname),
106
+ value: { [pname]: `%${String(value).toLowerCase()}%` }
107
+ }
108
+
109
+ case 'lt':
110
+ return {
111
+ clause: `${field} < :${pname}`,
112
+ parameters: { [pname]: value }
113
+ }
114
+
115
+ case 'gt':
116
+ return {
117
+ clause: `${field} > :${pname}`,
118
+ parameters: { [pname]: value }
119
+ }
120
+
121
+ case 'lte':
122
+ return {
123
+ clause: `${field} <= :${pname}`,
124
+ parameters: { [pname]: value }
125
+ }
126
+
127
+ case 'gte':
128
+ return {
129
+ clause: `${field} >= :${pname}`,
130
+ parameters: { [pname]: value }
131
+ }
132
+
133
+ case 'noteq':
134
+ return {
135
+ clause: `${field} != :${pname}`,
136
+ parameters: { [pname]: value }
137
+ }
138
+
139
+ case 'in':
140
+ return {
141
+ clause: `${field} IN (:...${pname})`,
142
+ parameters: { [pname]: values }
143
+ }
144
+
145
+ case 'notin':
146
+ return {
147
+ clause: `${field} NOT IN (:...${pname})`,
148
+ parameters: { [pname]: values }
149
+ }
150
+
151
+ case 'notin_with_null':
152
+ return {
153
+ clause: `${field} IS NULL OR ${field} NOT IN (:...${pname}))`,
154
+ parameters: { [pname]: values }
155
+ }
156
+
157
+ case 'is_null':
158
+ return {
159
+ clause: `${field} IS NULL`
160
+ }
161
+ case 'is_not_null':
162
+ return {
163
+ clause: `${field} IS NOT NULL`
164
+ }
165
+ case 'is_false':
166
+ return {
167
+ clause: `${field} IS FALSE`
168
+ }
169
+ case 'is_true':
170
+ return {
171
+ clause: `${field} IS TRUE`
172
+ }
173
+ case 'is_not_false':
174
+ return {
175
+ clause: `${field} IS NOT FALSE`
176
+ }
177
+ case 'is_not_true':
178
+ return {
179
+ clause: `${field} IS NOT TRUE`
180
+ }
181
+ case 'is_present':
182
+ return {
183
+ clause: `${field} IS PRESENT`
184
+ }
185
+ case 'is_blank':
186
+ return {
187
+ clause: `${field} IS BLANK`
188
+ }
189
+ case 'is_empty_num_id':
190
+ return {
191
+ clause: `${field} IS EMPTY NUMERIC ID`
192
+ }
193
+
194
+ case 'between':
195
+ return {
196
+ clause: `${field} BETWEEN :${pname}_1 AND :${pname}_2`,
197
+ parameters: { [`args${seq}_1`]: values[0], [`args${seq}_2`]: values[1] }
198
+ }
199
+ }
200
+ }