@things-factory/shell 5.0.0-alpha.7 → 5.0.0-y.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.
- package/client/themes/tooltip-theme.css +4 -3
- package/config/config.production.js +13 -0
- package/dist-server/middlewares/index.js +2 -2
- package/dist-server/middlewares/index.js.map +1 -1
- package/dist-server/pubsub.js +2 -2
- package/dist-server/pubsub.js.map +1 -1
- package/dist-server/server-dev.js +18 -16
- package/dist-server/server-dev.js.map +1 -1
- package/dist-server/server.js +15 -14
- package/dist-server/server.js.map +1 -1
- package/dist-server/service/domain/domain-resolver.js +4 -1
- package/dist-server/service/domain/domain-resolver.js.map +1 -1
- package/dist-server/service/domain/domain.js +34 -1
- package/dist-server/service/domain/domain.js.map +1 -1
- package/dist-server/utils/condition-builder.js +10 -11
- package/dist-server/utils/condition-builder.js.map +1 -1
- package/dist-server/utils/get-query-builder-from-list-params.js +249 -0
- package/dist-server/utils/get-query-builder-from-list-params.js.map +1 -0
- package/dist-server/utils/index.js +1 -0
- package/dist-server/utils/index.js.map +1 -1
- package/dist-server/utils/list-params-converter.js +48 -18
- package/dist-server/utils/list-params-converter.js.map +1 -1
- package/dist-server/utils/list-query-builder.js +33 -3
- package/dist-server/utils/list-query-builder.js.map +1 -1
- package/package.json +19 -18
- package/server/middlewares/index.ts +3 -2
- package/server/pubsub.ts +3 -3
- package/server/server-dev.ts +20 -17
- package/server/server.ts +17 -15
- package/server/service/domain/domain-resolver.ts +5 -1
- package/server/service/domain/domain.ts +37 -2
- package/server/utils/condition-builder.ts +12 -12
- package/server/utils/get-query-builder-from-list-params.ts +304 -0
- package/server/utils/index.ts +1 -0
- package/server/utils/list-params-converter.ts +83 -26
- package/server/utils/list-query-builder.ts +50 -3
package/server/server-dev.ts
CHANGED
@@ -1,33 +1,36 @@
|
|
1
|
+
/* following lines should be located in top of the file */
|
1
2
|
// @prettier-ignore
|
2
3
|
process.env.NODE_ENV = 'development'
|
3
4
|
process.setMaxListeners(0)
|
4
|
-
/** Never move following lines */
|
5
5
|
|
6
|
-
|
7
|
-
import { config, loader, logger, orderedModuleNames } from '@things-factory/env'
|
8
|
-
import { domainPrivateRouter, domainPublicRouter, globalPrivateRouter, globalPublicRouter } from './routers'
|
9
|
-
import { execute, subscribe } from 'graphql'
|
10
|
-
|
11
|
-
import { ApolloServer } from 'apollo-server-koa'
|
6
|
+
/* following lines should be located in top of the file */
|
12
7
|
import { ApolloServerPluginLandingPageGraphQLPlayground } from 'apollo-server-core'
|
13
|
-
import {
|
14
|
-
import
|
8
|
+
import { ApolloServer } from 'apollo-server-koa'
|
9
|
+
import bytesFormat from 'bytes'
|
15
10
|
import co from 'co'
|
16
|
-
import
|
17
|
-
import cors from '@koa/cors'
|
18
|
-
import { createServer } from 'http'
|
19
|
-
import { databaseInitializer } from './initializers/database'
|
11
|
+
import { execute, subscribe } from 'graphql'
|
20
12
|
import { graphqlUploadKoa } from 'graphql-upload'
|
21
|
-
import {
|
22
|
-
import
|
13
|
+
import { createServer } from 'http'
|
14
|
+
import Koa from 'koa'
|
23
15
|
import koaBodyParser from 'koa-bodyparser'
|
16
|
+
import compose from 'koa-compose'
|
17
|
+
import ip from 'koa-ip'
|
24
18
|
import koaStatic from 'koa-static'
|
19
|
+
import { historyApiFallback } from 'koa2-connect-history-api-fallback'
|
20
|
+
/** Never move following lines */
|
21
|
+
import { ConnectionContext, SubscriptionServer } from 'subscriptions-transport-ws'
|
22
|
+
|
25
23
|
import koaWebpack from '@hatiolab/koa-webpack'
|
24
|
+
import cors from '@koa/cors'
|
25
|
+
import { config, loader, logger, orderedModuleNames } from '@things-factory/env'
|
26
|
+
|
27
|
+
import { GraphqlLocalClient } from './graphql-local-client'
|
28
|
+
import { databaseInitializer } from './initializers/database'
|
29
|
+
import { domainPrivateRouter, domainPublicRouter, globalPrivateRouter, globalPublicRouter } from './routers'
|
26
30
|
import { schema } from './schema'
|
27
|
-
import bytesFormat from 'bytes'
|
28
31
|
|
29
32
|
process.on('uncaughtException', error => {
|
30
|
-
|
33
|
+
logger.error(error)
|
31
34
|
|
32
35
|
process.exit(1)
|
33
36
|
})
|
package/server/server.ts
CHANGED
@@ -1,29 +1,31 @@
|
|
1
|
+
// @prettier-ignore
|
1
2
|
process.env.NODE_ENV = 'production'
|
2
3
|
process.setMaxListeners(0)
|
3
4
|
|
4
|
-
import { ConnectionContext, SubscriptionServer } from 'subscriptions-transport-ws'
|
5
|
-
import { config, loader, logger, orderedModuleNames } from '@things-factory/env'
|
6
|
-
import { domainPrivateRouter, domainPublicRouter, globalPrivateRouter, globalPublicRouter } from './routers'
|
7
|
-
import { execute, subscribe } from 'graphql'
|
8
|
-
|
9
5
|
import { ApolloServer } from 'apollo-server-koa'
|
10
|
-
import
|
11
|
-
import Koa from 'koa'
|
6
|
+
import bytesFormat from 'bytes'
|
12
7
|
import co from 'co'
|
13
|
-
import
|
14
|
-
import cors from '@koa/cors'
|
15
|
-
import { createServer } from 'http'
|
16
|
-
import { databaseInitializer } from './initializers/database'
|
8
|
+
import { execute, subscribe } from 'graphql'
|
17
9
|
import { graphqlUploadKoa } from 'graphql-upload'
|
18
|
-
import {
|
19
|
-
import
|
10
|
+
import { createServer } from 'http'
|
11
|
+
import Koa from 'koa'
|
20
12
|
import koaBodyParser from 'koa-bodyparser'
|
13
|
+
import compose from 'koa-compose'
|
14
|
+
import ip from 'koa-ip'
|
21
15
|
import koaStatic from 'koa-static'
|
16
|
+
import { historyApiFallback } from 'koa2-connect-history-api-fallback'
|
17
|
+
import { ConnectionContext, SubscriptionServer } from 'subscriptions-transport-ws'
|
18
|
+
|
19
|
+
import cors from '@koa/cors'
|
20
|
+
import { config, loader, logger, orderedModuleNames } from '@things-factory/env'
|
21
|
+
|
22
|
+
import { GraphqlLocalClient } from './graphql-local-client'
|
23
|
+
import { databaseInitializer } from './initializers/database'
|
24
|
+
import { domainPrivateRouter, domainPublicRouter, globalPrivateRouter, globalPublicRouter } from './routers'
|
22
25
|
import { schema } from './schema'
|
23
|
-
import bytesFormat from 'bytes'
|
24
26
|
|
25
27
|
process.on('uncaughtException', error => {
|
26
|
-
|
28
|
+
logger.error(error)
|
27
29
|
|
28
30
|
process.exit(1)
|
29
31
|
})
|
@@ -22,7 +22,11 @@ export class DomainResolver {
|
|
22
22
|
@Query(returns => DomainList, { description: 'To fetch multiple domain' })
|
23
23
|
async domains(@Args() params: ListParam, @Ctx() context): Promise<DomainList> {
|
24
24
|
const queryBuilder = getRepository(Domain).createQueryBuilder()
|
25
|
-
|
25
|
+
|
26
|
+
buildQuery(queryBuilder, params || {}, context, {
|
27
|
+
domainRef: false,
|
28
|
+
searchables: ['name', 'description', 'subdomain']
|
29
|
+
})
|
26
30
|
const [items, total] = await queryBuilder.getManyAndCount()
|
27
31
|
|
28
32
|
return { items, total }
|
@@ -1,12 +1,47 @@
|
|
1
|
-
import { Column, CreateDateColumn, Entity, Index,
|
1
|
+
import { Column, CreateDateColumn, Entity, Index, UpdateDateColumn } from 'typeorm'
|
2
2
|
import { ObjectType, Field, ID } from 'type-graphql'
|
3
|
+
import { config } from '@things-factory/env'
|
4
|
+
|
5
|
+
const numericTypes = ["int","int2","int4","int8","integer","tinyint","smallint","mediumint","bigint"]
|
6
|
+
const generatedStrategy = ['uuid','rowid',"increment","identity"]
|
7
|
+
const domainPrimaryOption =config.get('domainPrimaryOption')
|
8
|
+
const domainPrimaryType = domainPrimaryOption?.type
|
9
|
+
const domainPrimaryStrategy = domainPrimaryOption?.strategy
|
3
10
|
|
4
11
|
@Entity()
|
5
12
|
@Index('ix_domain_0', (domain: Domain) => [domain.subdomain], { unique: true })
|
6
13
|
@ObjectType()
|
7
14
|
export class Domain {
|
8
15
|
@Field(type => ID)
|
9
|
-
@
|
16
|
+
@Column(
|
17
|
+
domainPrimaryOption?
|
18
|
+
{
|
19
|
+
type: domainPrimaryType,
|
20
|
+
primary:true,
|
21
|
+
transformer: {
|
22
|
+
//from(value: DatabaseType): EntityType
|
23
|
+
from: (value) => {
|
24
|
+
return value
|
25
|
+
},
|
26
|
+
//to(value: EntityType): DatabaseType
|
27
|
+
to: (value) => {
|
28
|
+
if(!value){
|
29
|
+
value = 0
|
30
|
+
}
|
31
|
+
if(numericTypes.indexOf(domainPrimaryType)>=0){
|
32
|
+
return parseInt(value)
|
33
|
+
}else{
|
34
|
+
return value
|
35
|
+
}
|
36
|
+
}
|
37
|
+
},
|
38
|
+
generated:generatedStrategy.indexOf(domainPrimaryStrategy)>=0?domainPrimaryStrategy:false
|
39
|
+
}:{
|
40
|
+
type: 'uuid',
|
41
|
+
primary:true,
|
42
|
+
generated:'uuid'
|
43
|
+
}
|
44
|
+
)
|
10
45
|
readonly id: string
|
11
46
|
|
12
47
|
@Field()
|
@@ -5,12 +5,13 @@ export const buildCondition = function (
|
|
5
5
|
fieldName: string,
|
6
6
|
operator: string,
|
7
7
|
value: any,
|
8
|
-
relation: boolean,
|
8
|
+
relation: boolean | string,
|
9
9
|
seq: number
|
10
10
|
) {
|
11
11
|
seq++
|
12
12
|
|
13
13
|
fieldName = _.snakeCase(fieldName)
|
14
|
+
const values = value instanceof Array ? value : [value]
|
14
15
|
|
15
16
|
switch (operator) {
|
16
17
|
case 'eq':
|
@@ -75,24 +76,23 @@ export const buildCondition = function (
|
|
75
76
|
}
|
76
77
|
|
77
78
|
case 'in':
|
78
|
-
const clause = relation ? `${fieldName}.id IN (:...args${seq})` : `${alias}.${fieldName} IN (:...args${seq})`
|
79
|
-
value = value?.length ? value : [value]
|
80
79
|
return {
|
81
|
-
clause
|
82
|
-
parameters: { [`args${seq}`]:
|
80
|
+
clause: relation ? `${fieldName}.id IN (:...args${seq})` : `${alias}.${fieldName} IN (:...args${seq})`,
|
81
|
+
parameters: { [`args${seq}`]: values }
|
83
82
|
}
|
83
|
+
|
84
84
|
case 'notin':
|
85
|
-
value = value?.length ? value : [value]
|
86
85
|
return {
|
87
|
-
clause: `${alias}.${fieldName} NOT IN (:...args${seq})`,
|
88
|
-
parameters: { [`args${seq}`]:
|
86
|
+
clause: relation ? `${fieldName}.id NOT IN (:...args${seq})` : `${alias}.${fieldName} NOT IN (:...args${seq})`,
|
87
|
+
parameters: { [`args${seq}`]: values }
|
89
88
|
}
|
90
89
|
|
91
90
|
case 'notin_with_null':
|
92
|
-
value = value?.length ? value : [value]
|
93
91
|
return {
|
94
|
-
clause:
|
95
|
-
|
92
|
+
clause: relation
|
93
|
+
? `(${fieldName}.id IS NULL OR ${fieldName}.id NOT IN (:...args${seq})`
|
94
|
+
: `${alias}.${fieldName} IS NULL OR ${alias}.${fieldName} NOT IN (:...args${seq}))`,
|
95
|
+
parameters: { [`args${seq}`]: values }
|
96
96
|
}
|
97
97
|
|
98
98
|
case 'is_null':
|
@@ -135,7 +135,7 @@ export const buildCondition = function (
|
|
135
135
|
case 'between':
|
136
136
|
return {
|
137
137
|
clause: `${alias}.${fieldName} BETWEEN :args${seq}_1 AND :args${seq}_2`,
|
138
|
-
parameters: { [`args${seq}_1`]:
|
138
|
+
parameters: { [`args${seq}_1`]: values[0], [`args${seq}_2`]: values[1] }
|
139
139
|
}
|
140
140
|
}
|
141
141
|
}
|
@@ -0,0 +1,304 @@
|
|
1
|
+
import { Filter, ListParam } from 'server/service'
|
2
|
+
import { Brackets, EntityMetadata, Repository, SelectQueryBuilder, WhereExpressionBuilder } from 'typeorm'
|
3
|
+
|
4
|
+
import { Domain } from '../service/domain/domain'
|
5
|
+
|
6
|
+
const debug = require('debug')('things-factory:shell:get-query-builder-from-list-params')
|
7
|
+
|
8
|
+
/**
|
9
|
+
*
|
10
|
+
* @param options
|
11
|
+
* @returns
|
12
|
+
*/
|
13
|
+
export function getQueryBuilderFromListParams<Type>(options: {
|
14
|
+
repository: Repository<Type>
|
15
|
+
params: ListParam
|
16
|
+
domain?: Domain
|
17
|
+
alias?: string
|
18
|
+
searchables?: string[]
|
19
|
+
filtersMap?: { [name: string]: { columnName: string; relationColumn?: string } }
|
20
|
+
}): SelectQueryBuilder<Type> {
|
21
|
+
var { repository, params, domain, alias, searchables, filtersMap = {} } = options
|
22
|
+
|
23
|
+
const selectQueryBuilder = repository.createQueryBuilder(alias)
|
24
|
+
const entityAlias = selectQueryBuilder.alias
|
25
|
+
|
26
|
+
const columnFilters =
|
27
|
+
params.filters?.filter(filter => {
|
28
|
+
if (filter.operator === 'search') {
|
29
|
+
return false
|
30
|
+
}
|
31
|
+
if (filter.operator.toLowerCase().includes('like') && (!searchables || !searchables.includes(filter.name))) {
|
32
|
+
debug('"searchables" setting is required for like searches with a heavy database query load', filter.name)
|
33
|
+
return false
|
34
|
+
}
|
35
|
+
return true
|
36
|
+
}) || []
|
37
|
+
const searchFilters =
|
38
|
+
searchables instanceof Array
|
39
|
+
? params.filters?.filter(filter => {
|
40
|
+
if (filter.operator !== 'search') {
|
41
|
+
return false
|
42
|
+
}
|
43
|
+
if (!searchables.includes(filter.name)) {
|
44
|
+
debug('"searchables" setting is required for like searches with a heavy database query load', filter.name)
|
45
|
+
return false
|
46
|
+
}
|
47
|
+
return true
|
48
|
+
}) || []
|
49
|
+
: []
|
50
|
+
const pagination = params.pagination
|
51
|
+
const sortings = params.sortings
|
52
|
+
|
53
|
+
const metadata = repository.metadata
|
54
|
+
|
55
|
+
if (columnFilters && columnFilters.length > 0) {
|
56
|
+
columnFilters.forEach(filter => {
|
57
|
+
addCondition(metadata, selectQueryBuilder, selectQueryBuilder, filter, filtersMap, true)
|
58
|
+
})
|
59
|
+
}
|
60
|
+
|
61
|
+
if (searchFilters.length > 0) {
|
62
|
+
selectQueryBuilder.andWhere(
|
63
|
+
new Brackets(qb => {
|
64
|
+
searchFilters.forEach(filter => {
|
65
|
+
addCondition(metadata, selectQueryBuilder, qb, filter, filtersMap, false)
|
66
|
+
})
|
67
|
+
})
|
68
|
+
)
|
69
|
+
}
|
70
|
+
|
71
|
+
if (domain) {
|
72
|
+
selectQueryBuilder.andWhere(`${entityAlias}.domain = :domain`, { domain: domain.id })
|
73
|
+
}
|
74
|
+
|
75
|
+
if (pagination && pagination.page > 0 && pagination.limit > 0) {
|
76
|
+
selectQueryBuilder.skip(pagination.limit * (pagination.page - 1))
|
77
|
+
selectQueryBuilder.take(pagination.limit)
|
78
|
+
}
|
79
|
+
|
80
|
+
if (sortings && sortings.length > 0) {
|
81
|
+
sortings.forEach((sorting, index) => {
|
82
|
+
const sortField = sorting.name.split('.').length > 1 ? sorting.name : `${entityAlias}.${sorting.name}`
|
83
|
+
if (index === 0) {
|
84
|
+
selectQueryBuilder.orderBy(sortField, sorting.desc ? 'DESC' : 'ASC')
|
85
|
+
} else {
|
86
|
+
selectQueryBuilder.addOrderBy(sortField, sorting.desc ? 'DESC' : 'ASC')
|
87
|
+
}
|
88
|
+
})
|
89
|
+
}
|
90
|
+
|
91
|
+
return selectQueryBuilder
|
92
|
+
}
|
93
|
+
|
94
|
+
function addCondition<T>(
|
95
|
+
metadata: EntityMetadata,
|
96
|
+
selectQueryBuilder: SelectQueryBuilder<T>,
|
97
|
+
whereExpressionBuilder: WhereExpressionBuilder,
|
98
|
+
filter: Filter,
|
99
|
+
filtersMap: { [name: string]: { columnName: string; relationColumn?: string } } = {},
|
100
|
+
andCondition: boolean
|
101
|
+
): void {
|
102
|
+
const { name, operator, value } = filter
|
103
|
+
const values = value instanceof Array ? value : [value]
|
104
|
+
const entityAlias = selectQueryBuilder.alias
|
105
|
+
|
106
|
+
var { relationColumn, columnName } = filtersMap[name] || {}
|
107
|
+
/*
|
108
|
+
1. relationColumn과 columnName이 지정된 경우
|
109
|
+
- relation inverse 테이블에서, columnName을 찾는다.
|
110
|
+
2. relationColumn만 지정된 경우는 없어야 한다.
|
111
|
+
- 이 경우 columnName 은 'name' 이라고 판단한다.
|
112
|
+
3. columnName이 지정된 경우.
|
113
|
+
- 이 경우는 columnName 만 적용한다.
|
114
|
+
*/
|
115
|
+
if (relationColumn) {
|
116
|
+
var relationColumnMeta = metadata.columns.find(column => column.propertyName === relationColumn)
|
117
|
+
if (!relationColumnMeta) {
|
118
|
+
debug(`relationColumn "${relationColumn}" in filtersMap for "${name}" is not a relation column`)
|
119
|
+
return
|
120
|
+
}
|
121
|
+
|
122
|
+
var relation = relationColumnMeta.relationMetadata
|
123
|
+
var entityMetadata = relation.inverseEntityMetadata
|
124
|
+
var columnMeta = entityMetadata.columns.find(column => column.propertyName === (columnName || 'name'))
|
125
|
+
if (!columnMeta) {
|
126
|
+
debug(`columnName "${columnName}" in filtersMap for "${name}" is not a column`)
|
127
|
+
return
|
128
|
+
}
|
129
|
+
} else {
|
130
|
+
var columnMeta = metadata.columns.find(column => column.propertyName === (columnName || name))
|
131
|
+
if (!columnMeta) {
|
132
|
+
/* relationId 에 대한 필터링은 해당 컬럼값 자체의 비교로 한다. */
|
133
|
+
var relationIdMeta = metadata.relationIds.find(relationId => relationId.propertyName === (columnName || name))
|
134
|
+
if (relationIdMeta) {
|
135
|
+
columnMeta = relationIdMeta.relation.joinColumns[0]
|
136
|
+
} else {
|
137
|
+
columnName
|
138
|
+
? debug(`columnName "${columnName}" in filtersMap for "${name}" is not a column`)
|
139
|
+
: debug(`name "${name}" is not a column`)
|
140
|
+
}
|
141
|
+
} else {
|
142
|
+
var relation = columnMeta.relationMetadata
|
143
|
+
}
|
144
|
+
|
145
|
+
if (relation) {
|
146
|
+
/* filterMap에 의해서 relationColumn 이 지정되지 않았더라도, name 또는 columnName의 column이 relation인 경우에는
|
147
|
+
- 조건절 구성을 위한 타겟필드명은 'name' 으로만 한정된다.
|
148
|
+
*/
|
149
|
+
var relationColumnMeta = columnMeta
|
150
|
+
var entityMetadata = relation.inverseEntityMetadata
|
151
|
+
columnMeta = entityMetadata.columns.find(column => column.propertyName === 'name')
|
152
|
+
if (!columnMeta) {
|
153
|
+
debug(`relation column "${columnName || name}" does not have "name" column`)
|
154
|
+
return
|
155
|
+
}
|
156
|
+
}
|
157
|
+
}
|
158
|
+
|
159
|
+
const dbNameForColumn = columnMeta.databaseName
|
160
|
+
const alias = relationColumnMeta ? `${name}-filter` : entityAlias
|
161
|
+
|
162
|
+
/* relation columne인 경우 name을 alias로 사용한다. */
|
163
|
+
const field = `${alias}.${dbNameForColumn}`
|
164
|
+
|
165
|
+
var clause = ''
|
166
|
+
var parameters = {}
|
167
|
+
|
168
|
+
switch (operator) {
|
169
|
+
case 'eq':
|
170
|
+
clause = `${field} = :${name}`
|
171
|
+
parameters = { [name]: value }
|
172
|
+
break
|
173
|
+
|
174
|
+
case 'like':
|
175
|
+
clause = `${field} LIKE :${name}`
|
176
|
+
parameters = { [name]: `%${value}%` }
|
177
|
+
break
|
178
|
+
|
179
|
+
case 'search':
|
180
|
+
case 'i_like':
|
181
|
+
clause = `LOWER(${field}) LIKE :${name}`
|
182
|
+
parameters = { [name]: `%${String(value).toLowerCase()}%` }
|
183
|
+
break
|
184
|
+
|
185
|
+
case 'nlike':
|
186
|
+
clause = `${field} NOT LIKE :${name}`
|
187
|
+
parameters = { [name]: `%${value}%` }
|
188
|
+
break
|
189
|
+
|
190
|
+
case 'i_nlike':
|
191
|
+
clause = `LOWER(${field}) NOT LIKE :${name}`
|
192
|
+
parameters = { [name]: `%${String(value).toLowerCase()}%` }
|
193
|
+
break
|
194
|
+
|
195
|
+
case 'lt':
|
196
|
+
clause = `${field} < :${name}`
|
197
|
+
parameters = { [name]: value }
|
198
|
+
break
|
199
|
+
|
200
|
+
case 'gt':
|
201
|
+
clause = `${field} > :${name}`
|
202
|
+
parameters = { [name]: value }
|
203
|
+
break
|
204
|
+
|
205
|
+
case 'lte':
|
206
|
+
clause = `${field} <= :${name}`
|
207
|
+
parameters = { [name]: value }
|
208
|
+
break
|
209
|
+
|
210
|
+
case 'gte':
|
211
|
+
clause = `${field} >= :${name}`
|
212
|
+
parameters = { [name]: value }
|
213
|
+
break
|
214
|
+
|
215
|
+
case 'noteq':
|
216
|
+
clause = `${field} != :${name}`
|
217
|
+
parameters = { [name]: value }
|
218
|
+
break
|
219
|
+
|
220
|
+
case 'in':
|
221
|
+
clause = `${field} IN (:...${name})`
|
222
|
+
parameters = { [name]: values }
|
223
|
+
break
|
224
|
+
|
225
|
+
case 'notin':
|
226
|
+
clause = `${field} NOT IN (:...${name})`
|
227
|
+
parameters = { [name]: values }
|
228
|
+
break
|
229
|
+
|
230
|
+
case 'notin_with_null':
|
231
|
+
clause = `${field} IS NULL OR ${field} NOT IN (:...${name}))`
|
232
|
+
parameters = { [name]: values }
|
233
|
+
break
|
234
|
+
|
235
|
+
case 'is_null':
|
236
|
+
clause = `${field} IS NULL`
|
237
|
+
break
|
238
|
+
|
239
|
+
case 'is_not_null':
|
240
|
+
clause = `${field} IS NOT NULL`
|
241
|
+
break
|
242
|
+
|
243
|
+
case 'is_false':
|
244
|
+
clause = `${field} IS FALSE`
|
245
|
+
break
|
246
|
+
|
247
|
+
case 'is_true':
|
248
|
+
clause = `${field} IS TRUE`
|
249
|
+
break
|
250
|
+
|
251
|
+
case 'is_not_false':
|
252
|
+
clause = `${field} IS NOT FALSE`
|
253
|
+
break
|
254
|
+
|
255
|
+
case 'is_not_true':
|
256
|
+
clause = `${field} IS NOT TRUE`
|
257
|
+
break
|
258
|
+
|
259
|
+
case 'is_present':
|
260
|
+
clause = `${field} IS PRESENT`
|
261
|
+
break
|
262
|
+
|
263
|
+
case 'is_blank':
|
264
|
+
clause = `${field} IS BLANK`
|
265
|
+
break
|
266
|
+
|
267
|
+
case 'is_empty_num_id':
|
268
|
+
clause = `${field} IS EMPTY NUMERIC ID`
|
269
|
+
break
|
270
|
+
|
271
|
+
case 'between':
|
272
|
+
clause = `${field} BETWEEN :${name}_1 AND :${name}_2`
|
273
|
+
parameters = { [`${name}_1`]: values[0], [`${name}_2`]: values[1] }
|
274
|
+
break
|
275
|
+
}
|
276
|
+
|
277
|
+
if (relationColumnMeta) {
|
278
|
+
const { propertyName } = relationColumnMeta
|
279
|
+
const property = `${entityAlias}.${propertyName}`
|
280
|
+
if (andCondition) {
|
281
|
+
selectQueryBuilder.innerJoin(property, alias, clause, parameters)
|
282
|
+
} else {
|
283
|
+
selectQueryBuilder.leftJoin(property, alias)
|
284
|
+
whereExpressionBuilder.orWhere(clause, parameters)
|
285
|
+
}
|
286
|
+
} else {
|
287
|
+
andCondition
|
288
|
+
? whereExpressionBuilder.andWhere(clause, parameters)
|
289
|
+
: whereExpressionBuilder.orWhere(clause, parameters)
|
290
|
+
}
|
291
|
+
}
|
292
|
+
|
293
|
+
// export function adjustFiltersFromListParam(params: ListParam, filtersChange: Filter[]): ListParam {
|
294
|
+
// const { filters = [] } = params
|
295
|
+
|
296
|
+
// var filtersNew = [...filters]
|
297
|
+
|
298
|
+
// filtersChange.forEach(change => {
|
299
|
+
// const idx = (filtersNew || []).findIndex(f => f.name === change.name)
|
300
|
+
// idx !== -1 ? filtersNew.splice(idx, 1, change) : filtersNew.push(change)
|
301
|
+
// })
|
302
|
+
|
303
|
+
// return { ...params, filters: filtersNew }
|
304
|
+
// }
|
package/server/utils/index.ts
CHANGED