@things-factory/shell 8.0.0-beta.0 → 8.0.0-beta.2

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 (55) hide show
  1. package/package.json +6 -6
  2. package/server/graphql-local-client.ts +0 -59
  3. package/server/index.ts +0 -13
  4. package/server/initializers/database.ts +0 -96
  5. package/server/initializers/naming-strategy.ts +0 -14
  6. package/server/middlewares/domain-middleware.ts +0 -60
  7. package/server/middlewares/index.ts +0 -43
  8. package/server/migrations/1000000000000-SeedDomain.ts +0 -37
  9. package/server/migrations/index.ts +0 -9
  10. package/server/pubsub-log-transport.ts +0 -59
  11. package/server/pubsub.ts +0 -84
  12. package/server/routers/domain-router.ts +0 -13
  13. package/server/routers/global-router.ts +0 -76
  14. package/server/routers/graphql-router.ts +0 -3
  15. package/server/routers/index.ts +0 -3
  16. package/server/schema.ts +0 -163
  17. package/server/server-dev.ts +0 -305
  18. package/server/server.ts +0 -296
  19. package/server/service/attribute-set/attribute-set-item-type.ts +0 -65
  20. package/server/service/attribute-set/attribute-set-mutation.ts +0 -125
  21. package/server/service/attribute-set/attribute-set-query.ts +0 -36
  22. package/server/service/attribute-set/attribute-set-type.ts +0 -46
  23. package/server/service/attribute-set/attribute-set.ts +0 -35
  24. package/server/service/attribute-set/index.ts +0 -6
  25. package/server/service/common-types/index.ts +0 -6
  26. package/server/service/common-types/list-param.ts +0 -61
  27. package/server/service/common-types/log.ts +0 -17
  28. package/server/service/common-types/object-ref.ts +0 -13
  29. package/server/service/common-types/scalar-any.ts +0 -44
  30. package/server/service/common-types/scalar-date.ts +0 -22
  31. package/server/service/common-types/scalar-object.ts +0 -15
  32. package/server/service/directive-transaction/index.ts +0 -1
  33. package/server/service/directive-transaction/transaction.ts +0 -40
  34. package/server/service/domain/domain-mutation.ts +0 -120
  35. package/server/service/domain/domain-query.ts +0 -48
  36. package/server/service/domain/domain-types.ts +0 -63
  37. package/server/service/domain/domain.ts +0 -147
  38. package/server/service/domain/index.ts +0 -6
  39. package/server/service/index.ts +0 -32
  40. package/server/service/subscription-data/data-resolver.ts +0 -37
  41. package/server/service/subscription-data/data-types.ts +0 -16
  42. package/server/service/subscription-data/index.ts +0 -4
  43. package/server/typeorm/encrypt-transform.ts +0 -70
  44. package/server/typeorm/get-data-encryption-key.ts +0 -13
  45. package/server/typeorm/json5-transform.ts +0 -26
  46. package/server/typeorm/round-transform.ts +0 -20
  47. package/server/utils/condition-builder.ts +0 -145
  48. package/server/utils/get-domain.ts +0 -226
  49. package/server/utils/get-query-builder-from-list-params.ts +0 -469
  50. package/server/utils/get-times-for-period.ts +0 -60
  51. package/server/utils/index.ts +0 -8
  52. package/server/utils/list-param-adjuster.ts +0 -21
  53. package/server/utils/list-params-converter.ts +0 -200
  54. package/server/utils/list-query-builder.ts +0 -120
  55. package/server/utils/publish-progress.ts +0 -23
@@ -1,70 +0,0 @@
1
- import { ValueTransformer } from 'typeorm'
2
- import { createCipheriv, createDecipheriv, randomBytes, scryptSync } from 'crypto'
3
-
4
- import { dataEncryptionKey } from './get-data-encryption-key'
5
-
6
- const ALGORITHM = 'aes-256-cbc'
7
- const KEY_LENGTH = 32
8
- const SALT_LENGTH = 16
9
- const IV_LENGTH = 16
10
-
11
- /**
12
- * ValueTransformer object for encrypting and decrypting database entity field values.
13
- * Used in TypeORM entities to encrypt field values before storing them in the database
14
- * and decrypt values when retrieving them from the database.
15
- */
16
- export const encryptTransformer: ValueTransformer = {
17
- /**
18
- * Encrypts the entity field value before storing it in the database.
19
- * @param {string} entityValue - Unencrypted entity field value
20
- * @returns {string} - Encrypted string
21
- */
22
- to: (entityValue: string) => encrypt(entityValue), // DB에 저장하기 전에 암호화
23
-
24
- /**
25
- * Decrypts the encrypted database value when retrieving it from the database.
26
- * @param {string} databaseValue - Encrypted database field value
27
- * @returns {string} - Decrypted string
28
- */
29
- from: (databaseValue: string) => decrypt(databaseValue) // DB에서 값을 가져올 때 복호화
30
- }
31
-
32
- /**
33
- * Encrypts the given text using the AES-256-CBC algorithm.
34
- * @param {string} text - Text to encrypt
35
- * @returns {string} - Encrypted string
36
- */
37
- function encrypt(text: string): string {
38
- if (!text) {
39
- return null
40
- }
41
-
42
- const iv = randomBytes(IV_LENGTH)
43
- const cipher = createCipheriv(ALGORITHM, dataEncryptionKey, iv)
44
- const encrypted = Buffer.concat([cipher.update(text, 'utf8'), cipher.final()])
45
-
46
- return `${iv.toString('hex')}:${encrypted.toString('hex')}`
47
- }
48
-
49
- /**
50
- * Decrypts the given encrypted text.
51
- * @param {string} text - Encrypted text to decrypt
52
- * @returns {string} - Decrypted string
53
- */
54
- function decrypt(text: string): string {
55
- if (!text) {
56
- return null
57
- }
58
-
59
- try {
60
- const parts = text.split(':')
61
- const iv = Buffer.from(parts.shift(), 'hex')
62
- const encryptedText = Buffer.from(parts.join(':'), 'hex')
63
- const decipher = createDecipheriv(ALGORITHM, dataEncryptionKey, iv)
64
-
65
- return Buffer.concat([decipher.update(encryptedText), decipher.final()]).toString('utf8')
66
- } catch (err) {
67
- console.error(`decryption for encrypted field failed in encryptTransformer`)
68
- return null
69
- }
70
- }
@@ -1,13 +0,0 @@
1
- import { config } from '@things-factory/env'
2
-
3
- var _DATA_ENCRYPTION_KEY = config.get('dataEncryptionKey')
4
-
5
- if (!_DATA_ENCRYPTION_KEY) {
6
- if (process.env.NODE_ENV == 'production') {
7
- throw new TypeError('dataEncryptionKey not configured.')
8
- } else {
9
- _DATA_ENCRYPTION_KEY = 'V6g5oHJZb7KcYzIyL6cM95XvIDouon5b'
10
- }
11
- }
12
-
13
- export const dataEncryptionKey = _DATA_ENCRYPTION_KEY
@@ -1,26 +0,0 @@
1
- import { ValueTransformer } from 'typeorm'
2
- import json5 from 'json5'
3
-
4
- export const json5Transformer: ValueTransformer = {
5
- /**
6
- * Converts the entity's value to a JSON5 string before storing it in the database.
7
- * @param {any} entityValue - The unencrypted entity field value.
8
- * @returns {string} - The stringified JSON5 representation of the entityValue.
9
- */
10
- to(entityValue: any) {
11
- return json5.stringify(entityValue)
12
- },
13
-
14
- /**
15
- * Converts a JSON5 string from the database back into its original type when retrieving it.
16
- * @param {string} databaseValue - The JSON5 string stored in the database.
17
- * @returns {any} - The original type of the entityValue, parsed from the JSON5 string.
18
- */
19
- from(databaseValue: string) {
20
- try {
21
- return json5.parse(databaseValue)
22
- } finally {
23
- return databaseValue
24
- }
25
- }
26
- }
@@ -1,20 +0,0 @@
1
- import { ValueTransformer } from 'typeorm'
2
-
3
- /**
4
- * ValueTransformer object for rounding floating point values.
5
- */
6
- export const roundTransformer: ValueTransformer = {
7
- /**
8
- * Rounds the entity field value before storing it in the database.
9
- * @param {number | null} value - Floating point value to round or null
10
- * @returns {number | null} - Rounded number or null
11
- */
12
- to: (value: number | null) => (value !== null && !isNaN(value) ? Math.round(value * 10000) / 10000 : undefined),
13
-
14
- /**
15
- * Returns the entity field value as it is without any transformation when reading from the database.
16
- * @param {number} value - Number value read from the database
17
- * @returns {number} - The number value as is
18
- */
19
- from: (value: number) => value
20
- }
@@ -1,145 +0,0 @@
1
- import _ from 'lodash'
2
-
3
- /**
4
- * Generates and returns a condition clause based on the provided parameters.
5
- *
6
- * @param alias {string} Alias or table name of the entity.
7
- * @param fieldName {string} Field or column name.
8
- * @param operator {string} Comparison operator.
9
- * @param value {any} Value or an array of values to compare.
10
- * @param relation {boolean | string} Indicates if it's a related field or the name of the relation (optional).
11
- * @param seq {number} Integer representing the order of condition generation (internal use).
12
- * @returns {Object} An object containing the generated condition clause and parameters.
13
- */
14
- export const buildCondition = function (alias: string, fieldName: string, operator: string, value: any, relation: boolean | string, seq: number) {
15
- seq++
16
-
17
- fieldName = _.snakeCase(fieldName)
18
- const values = value instanceof Array ? value : [value]
19
-
20
- switch (operator) {
21
- case 'eq':
22
- return {
23
- clause: `${alias}.${fieldName} = :args${seq}`,
24
- parameters: { [`args${seq}`]: value }
25
- }
26
-
27
- case 'like':
28
- return {
29
- clause: `${alias}.${fieldName} LIKE :args${seq}`,
30
- parameters: { [`args${seq}`]: `${value}` }
31
- }
32
-
33
- case 'search':
34
- case 'i_like':
35
- return {
36
- clause: `LOWER(${alias}.${fieldName}) LIKE :args${seq}`,
37
- parameters: { [`args${seq}`]: `${String(value).toLowerCase()}` }
38
- }
39
-
40
- case 'nlike':
41
- return {
42
- clause: `${alias}.${fieldName} NOT LIKE :args${seq}`,
43
- value: { [`args${seq}`]: `${value}` }
44
- }
45
-
46
- case 'i_nlike':
47
- return {
48
- clause: `LOWER(${alias}.${fieldName}) NOT LIKE :args${seq}`,
49
- value: { [`args${seq}`]: `${String(value).toLowerCase()}` }
50
- }
51
-
52
- case 'lt':
53
- return {
54
- clause: `${alias}.${fieldName} < :args${seq}`,
55
- parameters: { [`args${seq}`]: value }
56
- }
57
-
58
- case 'gt':
59
- return {
60
- clause: `${alias}.${fieldName} > :args${seq}`,
61
- parameters: { [`args${seq}`]: value }
62
- }
63
-
64
- case 'lte':
65
- return {
66
- clause: `${alias}.${fieldName} <= :args${seq}`,
67
- parameters: { [`args${seq}`]: value }
68
- }
69
-
70
- case 'gte':
71
- return {
72
- clause: `${alias}.${fieldName} >= :args${seq}`,
73
- parameters: { [`args${seq}`]: value }
74
- }
75
-
76
- case 'noteq':
77
- return {
78
- clause: `${alias}.${fieldName} != :args${seq}`,
79
- parameters: { [`args${seq}`]: value }
80
- }
81
-
82
- case 'in':
83
- return {
84
- clause: relation ? `${fieldName}.id IN (:...args${seq})` : `${alias}.${fieldName} IN (:...args${seq})`,
85
- parameters: { [`args${seq}`]: values }
86
- }
87
-
88
- case 'notin':
89
- return {
90
- clause: relation ? `${fieldName}.id NOT IN (:...args${seq})` : `${alias}.${fieldName} NOT IN (:...args${seq})`,
91
- parameters: { [`args${seq}`]: values }
92
- }
93
-
94
- case 'notin_with_null':
95
- return {
96
- clause: relation
97
- ? `(${fieldName}.id IS NULL OR ${fieldName}.id NOT IN (:...args${seq})`
98
- : `${alias}.${fieldName} IS NULL OR ${alias}.${fieldName} NOT IN (:...args${seq}))`,
99
- parameters: { [`args${seq}`]: values }
100
- }
101
-
102
- case 'is_null':
103
- return {
104
- clause: `${alias}.${fieldName} IS NULL`
105
- }
106
- case 'is_not_null':
107
- return {
108
- clause: `${alias}.${fieldName} IS NOT NULL`
109
- }
110
- case 'is_false':
111
- return {
112
- clause: `${alias}.${fieldName} IS FALSE`
113
- }
114
- case 'is_true':
115
- return {
116
- clause: `${alias}.${fieldName} IS TRUE`
117
- }
118
- case 'is_not_false':
119
- return {
120
- clause: `${alias}.${fieldName} IS NOT FALSE`
121
- }
122
- case 'is_not_true':
123
- return {
124
- clause: `${alias}.${fieldName} IS NOT TRUE`
125
- }
126
- case 'is_present':
127
- return {
128
- clause: `${alias}.${fieldName} IS PRESENT`
129
- }
130
- case 'is_blank':
131
- return {
132
- clause: `${alias}.${fieldName} IS BLANK`
133
- }
134
- case 'is_empty_num_id':
135
- return {
136
- clause: `${alias}.${fieldName} IS EMPTY NUMERIC ID`
137
- }
138
-
139
- case 'between':
140
- return {
141
- clause: `${alias}.${fieldName} BETWEEN :args${seq}_1 AND :args${seq}_2`,
142
- parameters: { [`args${seq}_1`]: values[0], [`args${seq}_2`]: values[1] }
143
- }
144
- }
145
- }
@@ -1,226 +0,0 @@
1
- import { URL } from 'url'
2
-
3
- import { config } from '@things-factory/env'
4
- import { getPathInfo } from '@things-factory/utils'
5
-
6
- import { getRepository } from '../initializers/database'
7
- import { Domain } from '../service/domain/domain'
8
-
9
- const useVirtualHostBasedDomain = !!config.get('useVirtualHostBasedDomain')
10
- const protocol: string = config.get('protocol')
11
- const fixed = config.get('subdomain')
12
- const subdomainOffset = config.getNumber('subdomainOffset', 2)
13
-
14
- /**
15
- * Creates a URL based on the given context and path.
16
- *
17
- * @param context {Object} An object containing the current request context information.
18
- * @param path {string} The path to be added to the created URL (optional).
19
- * @returns {URL} The generated URL object.
20
- */
21
- export function getUrlFromContext(context, path = '') {
22
- const { method, href, host, header } = context
23
- const { referer } = header || {}
24
-
25
- var base = href
26
-
27
- if (method !== 'GET' && referer) {
28
- var { host: refererHost } = new URL(referer)
29
- if (refererHost === host) {
30
- base = referer
31
- }
32
- }
33
-
34
- let url: URL = new URL(path, base)
35
-
36
- const originalProtocol = context.headers['x-forwarded-proto']
37
- const originalHost = context.headers['x-forwarded-host']
38
- const originalPort = context.headers['x-forwarded-port']
39
-
40
- if (protocol || originalProtocol) {
41
- url.protocol = protocol || originalProtocol
42
- }
43
-
44
- if (originalHost) {
45
- url.host = originalHost
46
- if (originalPort) {
47
- url.port = originalPort
48
- }
49
- }
50
-
51
- return url
52
- }
53
-
54
- /**
55
- * Extracts subdomains from the Host header.
56
- *
57
- * @param context {Object} An object containing the current request context information.
58
- * @returns {string[]} An array of extracted subdomains.
59
- */
60
- function getSubdomainsFromHost(context: any) {
61
- const { request } = context
62
- var subdomains = request.headers.host.split('.').reverse()
63
- return subdomains.slice(subdomainOffset)
64
- }
65
-
66
- /**
67
- * Extracts a subdomain from the path.
68
- *
69
- * @param context {Object} An object containing the current request context information.
70
- * @returns {string} The extracted subdomain.
71
- */
72
- function getSubdomainFromPath(context: any) {
73
- var { path } = context
74
-
75
- var domain = getPathInfo(path || '')?.domain
76
- if (domain) {
77
- return domain
78
- }
79
-
80
- var {
81
- header: { referer }
82
- } = context
83
-
84
- if (referer) {
85
- var { pathname } = new URL(referer)
86
- return getPathInfo(pathname || '')?.domain
87
- }
88
- }
89
-
90
- /**
91
- * Extracts a subdomain based on virtual host.
92
- *
93
- * @param context {Object} An object containing the current request context information.
94
- * @returns {string} The extracted subdomain.
95
- */
96
- function getSubdomainFromVhost(context: any) {
97
- const subdomain = (context.subdomains || getSubdomainsFromHost(context)).slice(-1)[0]
98
-
99
- return subdomain
100
- }
101
-
102
- /**
103
- * Extracts a subdomain from the URL context.
104
- *
105
- * @param context {Object} An object containing the current request context information.
106
- * @returns {string} The extracted subdomain.
107
- */
108
- function getSubdomainFromURL(context) {
109
- return fixed || (useVirtualHostBasedDomain ? getSubdomainFromVhost(context) : getSubdomainFromPath(context))
110
- }
111
-
112
- /**
113
- * Asynchronously searches for a domain object based on the URL context.
114
- *
115
- * @param context {Object} An object containing the current request context information.
116
- * @returns {Promise<Domain>} A promise that resolves to the domain object.
117
- */
118
- export async function getDomainFromURL(context: any): Promise<Domain> {
119
- const { header } = context
120
-
121
- const subdomain = header['x-things-factory-domain'] || getSubdomainFromURL(context)
122
-
123
- if (subdomain) {
124
- return await getRepository(Domain).findOne({ where: { subdomain }, cache: true })
125
- }
126
- }
127
-
128
- /**
129
- * Extracts the cookie domain from the hostname.
130
- *
131
- * @param hostname {string} The hostname.
132
- * @returns {string} The extracted cookie domain.
133
- */
134
- export function getCookieDomainFromHostname(hostname) {
135
- if (useVirtualHostBasedDomain) {
136
- return hostname.split('.').slice(-subdomainOffset).join('.')
137
- }
138
- }
139
-
140
- /**
141
- * Generates a context path based on the subdomain.
142
- *
143
- * @param subdomain {string} The subdomain.
144
- * @returns {string} The generated context path.
145
- */
146
- export function getContextPath(subdomain) {
147
- return fixed || useVirtualHostBasedDomain ? '' : '/domain/' + subdomain
148
- }
149
-
150
- /**
151
- * Generates a redirection path considering the subdomain.
152
- *
153
- * @param context {Object} An object containing the current request context information.
154
- * @param subdomain {string} The subdomain.
155
- * @param redirectTo {string} The path to redirect to (optional).
156
- * @returns {string} The generated redirection path.
157
- */
158
- export function getRedirectSubdomainPath(context, subdomain, redirectTo = '/') {
159
- if (fixed) {
160
- return redirectTo || '/'
161
- }
162
-
163
- var parsed = getUrlFromContext(context, redirectTo)
164
- var { hostname, pathname } = parsed
165
-
166
- if (useVirtualHostBasedDomain) {
167
- const splitHost = hostname.split('.').reverse()
168
- splitHost[subdomainOffset] = subdomain
169
- parsed.hostname = splitHost
170
- .reverse()
171
- .filter(a => a)
172
- .join('.')
173
- } else {
174
- const contextPath = `/domain/${subdomain}`
175
- const match = pathname.match(/^\/domain\/([^\/]+)/)
176
-
177
- if (match) {
178
- parsed.pathname = pathname.replace(match[0], contextPath)
179
- } else {
180
- parsed.pathname = `${contextPath}${pathname}`
181
- }
182
- }
183
-
184
- return parsed.toString()
185
- }
186
-
187
- /**
188
- * Finds a subdomain from the given path.
189
- *
190
- * @param context {Object} An object containing the current request context information.
191
- * @param path {string} The path to search in.
192
- * @returns {string} The found subdomain.
193
- */
194
- export function findSubdomainFromPath(context, path) {
195
- if (fixed) {
196
- return fixed
197
- }
198
-
199
- var parsed = getUrlFromContext(context, path)
200
- var { hostname, pathname } = parsed
201
-
202
- if (useVirtualHostBasedDomain) {
203
- return hostname.split('.').reverse()[subdomainOffset]
204
- }
205
-
206
- const match = pathname.match(/^\/domain\/([^\/]+)/)
207
- return match && match[1]
208
- }
209
-
210
- /**
211
- * Generates a site root path based on the current environment.
212
- *
213
- * @param context {Object} An object containing the current request context information.
214
- * @returns {string} The generated site root path.
215
- */
216
- export function getSiteRootPath(context) {
217
- if (useVirtualHostBasedDomain) {
218
- var { protocol, host } = context
219
- protocol = protocol.replace(':', '')
220
-
221
- let domainname = host.split('.').slice(-subdomainOffset).join('.')
222
- return protocol + '://' + domainname + '/'
223
- } else {
224
- return '/'
225
- }
226
- }