@things-factory/integration-base 7.0.7 → 7.0.13

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 (65) hide show
  1. package/assets/images/mssql-procedure-example1.png +0 -0
  2. package/dist-server/controllers/index.d.ts +1 -0
  3. package/dist-server/controllers/index.js +1 -0
  4. package/dist-server/controllers/index.js.map +1 -1
  5. package/dist-server/controllers/publish-data.d.ts +6 -0
  6. package/dist-server/controllers/publish-data.js +22 -0
  7. package/dist-server/controllers/publish-data.js.map +1 -0
  8. package/dist-server/engine/connector/mssql-connector.d.ts +10 -0
  9. package/dist-server/engine/connector/mssql-connector.js +42 -11
  10. package/dist-server/engine/connector/mssql-connector.js.map +1 -1
  11. package/dist-server/engine/task/index.d.ts +2 -0
  12. package/dist-server/engine/task/index.js +2 -0
  13. package/dist-server/engine/task/index.js.map +1 -1
  14. package/dist-server/engine/task/mssql-procedure.d.ts +1 -0
  15. package/dist-server/engine/task/mssql-procedure.js +94 -0
  16. package/dist-server/engine/task/mssql-procedure.js.map +1 -0
  17. package/dist-server/engine/task/oracle-procedure.js +4 -1
  18. package/dist-server/engine/task/oracle-procedure.js.map +1 -1
  19. package/dist-server/engine/task/state-group-read.d.ts +1 -0
  20. package/dist-server/engine/task/state-group-read.js +62 -0
  21. package/dist-server/engine/task/state-group-read.js.map +1 -0
  22. package/dist-server/service/index.d.ts +1 -1
  23. package/dist-server/service/scenario-instance/scenario-instance-type.js +6 -9
  24. package/dist-server/service/scenario-instance/scenario-instance-type.js.map +1 -1
  25. package/dist-server/service/state-register/data-resolver.d.ts +6 -0
  26. package/dist-server/service/state-register/data-resolver.js +61 -0
  27. package/dist-server/service/state-register/data-resolver.js.map +1 -0
  28. package/dist-server/service/state-register/index.d.ts +2 -1
  29. package/dist-server/service/state-register/index.js +2 -1
  30. package/dist-server/service/state-register/index.js.map +1 -1
  31. package/dist-server/service/state-register/state-register-query.js +1 -1
  32. package/dist-server/service/state-register/state-register-query.js.map +1 -1
  33. package/dist-server/service/state-register/state-register-type.d.ts +6 -0
  34. package/dist-server/service/state-register/state-register-type.js +40 -16
  35. package/dist-server/service/state-register/state-register-type.js.map +1 -1
  36. package/dist-server/service/state-register/state-register.d.ts +3 -0
  37. package/dist-server/service/state-register/state-register.js +36 -13
  38. package/dist-server/service/state-register/state-register.js.map +1 -1
  39. package/dist-server/tsconfig.tsbuildinfo +1 -1
  40. package/helps/integration/task/mqtt-subscribe.ms.md +127 -11
  41. package/helps/integration/task/mssql-procedure.ja.md +105 -0
  42. package/helps/integration/task/mssql-procedure.ko.md +89 -0
  43. package/helps/integration/task/mssql-procedure.md +89 -0
  44. package/helps/integration/task/mssql-procedure.ms.md +89 -0
  45. package/helps/integration/task/mssql-procedure.zh.md +103 -0
  46. package/helps/integration/task/oracle-procedure.ko.md +0 -2
  47. package/helps/integration/task/state-group-read.ja.md +8 -0
  48. package/helps/integration/task/state-group-read.ko.md +8 -0
  49. package/helps/integration/task/state-group-read.md +10 -0
  50. package/helps/integration/task/state-group-read.ms.md +8 -0
  51. package/helps/integration/task/state-group-read.zh.md +8 -0
  52. package/package.json +8 -8
  53. package/server/controllers/index.ts +1 -0
  54. package/server/controllers/publish-data.ts +29 -0
  55. package/server/engine/connector/mssql-connector.ts +43 -12
  56. package/server/engine/task/index.ts +2 -0
  57. package/server/engine/task/mssql-procedure.ts +128 -0
  58. package/server/engine/task/oracle-procedure.ts +4 -1
  59. package/server/engine/task/state-group-read.ts +69 -0
  60. package/server/service/scenario-instance/scenario-instance-type.ts +6 -9
  61. package/server/service/state-register/data-resolver.ts +56 -0
  62. package/server/service/state-register/index.ts +2 -1
  63. package/server/service/state-register/state-register-query.ts +1 -1
  64. package/server/service/state-register/state-register-type.ts +36 -20
  65. package/server/service/state-register/state-register.ts +39 -17
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/integration-base",
3
- "version": "7.0.7",
3
+ "version": "7.0.13",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "client/index.js",
6
6
  "things-factory": true,
@@ -27,13 +27,13 @@
27
27
  "dependencies": {
28
28
  "@apollo/client": "^3.6.9",
29
29
  "@operato/moment-timezone-es": "^7.0.0",
30
- "@things-factory/api": "^7.0.6",
31
- "@things-factory/auth-base": "^7.0.6",
32
- "@things-factory/cache-service": "^7.0.6",
30
+ "@things-factory/api": "^7.0.10",
31
+ "@things-factory/auth-base": "^7.0.10",
32
+ "@things-factory/cache-service": "^7.0.10",
33
33
  "@things-factory/env": "^7.0.0",
34
- "@things-factory/oauth2-client": "^7.0.7",
35
- "@things-factory/scheduler-client": "^7.0.6",
36
- "@things-factory/shell": "^7.0.6",
34
+ "@things-factory/oauth2-client": "^7.0.10",
35
+ "@things-factory/scheduler-client": "^7.0.10",
36
+ "@things-factory/shell": "^7.0.10",
37
37
  "@things-factory/utils": "^7.0.0",
38
38
  "async-mqtt": "^2.5.0",
39
39
  "chance": "^1.1.11",
@@ -44,5 +44,5 @@
44
44
  "readline": "^1.3.0",
45
45
  "ses": "^1.5.0"
46
46
  },
47
- "gitHead": "6c9d22d79abfb199bd741f6504b29add846b46a9"
47
+ "gitHead": "2bcab979adf08e9561cb6ba2506afa4770b90bbc"
48
48
  }
@@ -1 +1,2 @@
1
1
  export * from './scenario-controller'
2
+ export * from './publish-data'
@@ -0,0 +1,29 @@
1
+ import { Domain, getRepository, pubsub } from '@things-factory/shell'
2
+ import { User } from '@things-factory/auth-base'
3
+
4
+ import { StateRegister } from '../service/state-register/state-register'
5
+
6
+ export async function publishData(tag: string, data: any, { domain, user }: { domain: Domain; user: User }) {
7
+ const repository = getRepository(StateRegister)
8
+
9
+ const stateRegister = await repository.findOne({
10
+ where: { domain: { id: domain?.id }, name: tag }
11
+ })
12
+
13
+ if (stateRegister) {
14
+ await repository.save({
15
+ ...stateRegister,
16
+ state: data,
17
+ writer: user,
18
+ wroteAt: new Date()
19
+ })
20
+ }
21
+
22
+ pubsub.publish('data', {
23
+ data: {
24
+ domain,
25
+ tag,
26
+ data
27
+ }
28
+ })
29
+ }
@@ -5,7 +5,7 @@ import { Connector } from '../types'
5
5
  import { InputConnection } from '../../service/connection/connection-type'
6
6
 
7
7
  try {
8
- var Client = require('mssql')
8
+ var mssql = require('mssql')
9
9
  } catch (err) {
10
10
  logger.error('mssql module loading failed', err)
11
11
  }
@@ -20,24 +20,23 @@ export class MssqlConnector implements Connector {
20
20
  async connect(connection: InputConnection) {
21
21
  const {
22
22
  endpoint,
23
- params: { user, password, database, encrypt = 'Y', trustServerCertificate }
23
+ params: { user, password, database, poolMin = 0, poolMax = 4, encrypt = 'Y', trustServerCertificate }
24
24
  } = connection
25
25
 
26
26
  const [host, port = 1433] = endpoint.split(':')
27
27
 
28
- if (!Client) {
28
+ if (!mssql) {
29
29
  throw new Error('mssql module loading failed')
30
30
  }
31
31
 
32
- const client = await Client.connect({
33
- // client is pool
32
+ const pool = await mssql.connect({
34
33
  user,
35
34
  password,
36
35
  server: host,
37
36
  database,
38
37
  pool: {
39
- max: 10,
40
- min: 0,
38
+ max: Math.max(2, poolMax),
39
+ min: Math.max(0, poolMin),
41
40
  idleTimeoutMillis: 30000
42
41
  },
43
42
  options: {
@@ -48,12 +47,30 @@ export class MssqlConnector implements Connector {
48
47
 
49
48
  ConnectionManager.addConnectionInstance(connection, {
50
49
  query: async (query, params) => {
51
- var result = await client.query(query)
50
+ var result = await pool.request().query(query)
52
51
  return result.recordset
53
-
54
- // return (await client.query(query))
55
52
  },
56
- close: client.close.bind(client)
53
+ execute: async (procedure, params) => {
54
+ let request = pool.request()
55
+
56
+ Object.keys(params).forEach(key => {
57
+ let { dir, type, val } = params[key]
58
+
59
+ if (dir === 'in' || dir === 'inout') {
60
+ request.input(key, type, val)
61
+ } else if (dir === 'out') {
62
+ request.output(key, type)
63
+ } else {
64
+ console.error(`Invalid parameter direction(${dir}) for mssql stored procedure`)
65
+ }
66
+ })
67
+
68
+ var result = await request.execute(procedure)
69
+ return result
70
+ },
71
+ close: () => {
72
+ pool.close()
73
+ }
57
74
  })
58
75
 
59
76
  ConnectionManager.logger.info(`MSSql Database(${connection.name}:${database}) at ${endpoint} connected.`)
@@ -97,6 +114,20 @@ export class MssqlConnector implements Connector {
97
114
  options: ['Y', 'N']
98
115
  }
99
116
  },
117
+ {
118
+ type: 'number',
119
+ name: 'poolMin',
120
+ placeholder: 'minimum connection-pool size',
121
+ label: 'pool-min',
122
+ value: 0
123
+ },
124
+ {
125
+ type: 'number',
126
+ name: 'poolMax',
127
+ placeholder: 'maximum connection-pool size',
128
+ label: 'pool-max',
129
+ value: 4
130
+ },
100
131
  {
101
132
  type: 'select',
102
133
  name: 'trustServerCertificate',
@@ -109,7 +140,7 @@ export class MssqlConnector implements Connector {
109
140
  }
110
141
 
111
142
  get taskPrefixes() {
112
- return ['database']
143
+ return ['database', 'mssql']
113
144
  }
114
145
 
115
146
  get help() {
@@ -37,7 +37,9 @@ import './data-mapper'
37
37
  import './headless-post'
38
38
  import './headless-scrap'
39
39
  import './set-domain'
40
+ import './mssql-procedure'
40
41
  import './oracle-procedure'
41
42
  import './jsonata'
42
43
  import './state-read'
43
44
  import './state-write'
45
+ import './state-group-read'
@@ -0,0 +1,128 @@
1
+ import { logger } from '@things-factory/env'
2
+ import { access } from '@things-factory/utils'
3
+ import { ConnectionManager } from '../connection-manager'
4
+ import { TaskRegistry } from '../task-registry'
5
+ import { InputStep } from '../../service/step/step-type'
6
+ import { Context } from '../types'
7
+ import 'ses'
8
+
9
+ try {
10
+ var mssql = require('mssql')
11
+ } catch (err) {
12
+ logger.error('mssql module loading failed', err)
13
+ }
14
+
15
+ type ProcedureParameterType = {
16
+ name: string
17
+ dir: string
18
+ type: string
19
+ val?: any
20
+ accessor?: string
21
+ maxSize?: number
22
+ }
23
+
24
+ type ValueType = {
25
+ code?: string
26
+ procedure?: string
27
+ parameters?: ProcedureParameterType[]
28
+ }
29
+
30
+ const DIR = {
31
+ In: 'in',
32
+ Out: 'out',
33
+ Inout: 'inout' /* 초기값이 있는 out 파라미터 */
34
+ }
35
+
36
+ const NUMBER_TYPES = [
37
+ 'TINYINT',
38
+ 'SMALLINT',
39
+ 'INT',
40
+ 'BIGINT',
41
+ 'FLOAT',
42
+ 'READ',
43
+ 'DECIMAL',
44
+ 'NUMERIC',
45
+ 'MONEY',
46
+ 'SMALLMONEY'
47
+ ]
48
+
49
+ const DATE_TYPES = ['DATE', 'TIME', 'DATETIME', 'SMALLDATETIME', 'DATETIME2']
50
+ const PARAMETERIZED_STRINGS = ['NCHAR', 'NVARCHAR', 'NTEXT', 'DECIMAL', 'NUMERIC']
51
+
52
+ async function MssqlProcedure(step: InputStep, context: Context) {
53
+ var { domain, user, data, variables, lng } = context
54
+ var { connection: connectionName, params } = step
55
+
56
+ var { code = '', procedure = '', parameters = [] } = params.parameters as ValueType
57
+
58
+ var dbconnection = ConnectionManager.getConnectionInstanceByName(domain, connectionName)
59
+
60
+ if (!code) {
61
+ throw 'procedure code not defined'
62
+ }
63
+
64
+ const compartment = new Compartment({
65
+ domain,
66
+ user,
67
+ lng,
68
+ data,
69
+ variables,
70
+ console
71
+ })
72
+
73
+ let evalCode
74
+ try {
75
+ evalCode = compartment.evaluate('`' + code + '`')
76
+ } catch (err) {
77
+ throw new Error(`Failed to evaluate code: ${err.message}`)
78
+ }
79
+
80
+ code = evalCode
81
+
82
+ const procedureParameters =
83
+ parameters &&
84
+ parameters.reduce((sum, { name, val, dir, type, accessor, maxSize }) => {
85
+ sum[name] = {
86
+ dir: DIR[dir],
87
+ type
88
+ }
89
+
90
+ const calculated = accessor ? access(accessor, data) || val : val
91
+
92
+ if (calculated !== undefined) {
93
+ sum[name].val = NUMBER_TYPES.includes(type)
94
+ ? Number(calculated)
95
+ : DATE_TYPES.includes(type)
96
+ ? new Date(calculated)
97
+ : String(calculated)
98
+ }
99
+
100
+ if ((dir == DIR.In || dir == DIR.Inout) && maxSize > 0 && type == 'String') {
101
+ sum[name].type = mssql?.VarChar(maxSize)
102
+ sum[name].maxSize = maxSize
103
+ }
104
+
105
+ return sum
106
+ }, {})
107
+
108
+ const result = await dbconnection.execute(procedure, procedureParameters)
109
+
110
+ return {
111
+ data: result
112
+ }
113
+ }
114
+
115
+ MssqlProcedure.parameterSpec = [
116
+ {
117
+ type: 'procedure-parameters',
118
+ name: 'parameters',
119
+ label: '',
120
+ property: {
121
+ dbtype: 'mssql'
122
+ }
123
+ }
124
+ ]
125
+
126
+ MssqlProcedure.help = 'integration/task/mssql-procedure'
127
+
128
+ TaskRegistry.registerTaskHandler('mssql-procedure', MssqlProcedure)
@@ -112,7 +112,10 @@ OracleProcedure.parameterSpec = [
112
112
  {
113
113
  type: 'procedure-parameters',
114
114
  name: 'parameters',
115
- label: ''
115
+ label: '',
116
+ property: {
117
+ dbtype: 'oracle'
118
+ }
116
119
  }
117
120
  ]
118
121
 
@@ -0,0 +1,69 @@
1
+ import gql from 'graphql-tag'
2
+ import { TaskRegistry } from '../task-registry'
3
+ import { InputStep } from '../../service/step/step-type'
4
+ import { Context } from '../types'
5
+
6
+ async function StateGroupRead(step: InputStep, { logger, publish, data, domain, user, client }: Context) {
7
+ var {
8
+ params: { group }
9
+ } = step
10
+
11
+ if (!group) {
12
+ throw Error(`group should be defined: group - '${group}'`)
13
+ }
14
+
15
+ var { data: queryResult, errors } = await client.query({
16
+ query: gql`
17
+ query ($filters: [Filter!]) {
18
+ stateRegisters(filters: $filters) {
19
+ items {
20
+ name
21
+ state
22
+ }
23
+ }
24
+ }
25
+ `,
26
+ variables: {
27
+ filters: [
28
+ {
29
+ name: 'group',
30
+ operator: 'eq',
31
+ value: group
32
+ }
33
+ ]
34
+ },
35
+ context: {
36
+ state: {
37
+ domain,
38
+ user
39
+ }
40
+ }
41
+ })
42
+
43
+ if (errors) {
44
+ errors.forEach(error => {
45
+ logger.error('GraphQL Error: %s', error)
46
+ })
47
+ }
48
+
49
+ return {
50
+ data: queryResult?.stateRegisters?.items.reduce((status, item) => {
51
+ const { name, state } = item
52
+ status[name] = state
53
+ return status
54
+ }, {})
55
+ }
56
+ }
57
+
58
+ StateGroupRead.parameterSpec = [
59
+ {
60
+ type: 'string',
61
+ name: 'group',
62
+ label: 'group'
63
+ }
64
+ ]
65
+
66
+ StateGroupRead.connectorFree = true
67
+ StateGroupRead.help = 'integration/task/state-group-read'
68
+
69
+ TaskRegistry.registerTaskHandler('state-group-read', StateGroupRead)
@@ -11,6 +11,7 @@ import { cacheService } from '@things-factory/cache-service'
11
11
  import { User } from '@things-factory/auth-base'
12
12
  import { sleep } from '@things-factory/utils'
13
13
 
14
+ import { publishData } from '../../controllers/publish-data'
14
15
  import { ConnectionManager } from '../../engine/connection-manager'
15
16
  import { TaskRegistry } from '../../engine'
16
17
  import { Context } from '../../engine/types'
@@ -390,13 +391,7 @@ export class ScenarioInstance {
390
391
  }
391
392
 
392
393
  publishData(tag, data) {
393
- pubsub.publish('data', {
394
- data: {
395
- domain: this.context.domain,
396
- tag,
397
- data
398
- }
399
- })
394
+ publishData(tag, data, this.context)
400
395
  }
401
396
 
402
397
  publishState() {
@@ -498,9 +493,11 @@ export class ScenarioInstance {
498
493
  await this.disposer.call(this)
499
494
  }
500
495
 
501
- // {{ CHECKPOINT 본 인스턴스를 위해서 생성된 logger를 닫는다.
496
+ // {{ CHECKPOINT 본 인스턴스를 위해서 생성된 logger를 닫는다. 사용을 완료하고 닫기위해서 지연해서 수행한다.
502
497
  if (this.context?.logger) {
503
- this.context.logger.close()
498
+ setTimeout(() => {
499
+ this.context.logger.close()
500
+ }, 300)
504
501
  }
505
502
  // }}
506
503
  }
@@ -0,0 +1,56 @@
1
+ import { filter, pipe } from 'graphql-yoga'
2
+ import { Arg, Resolver, Root, Subscription } from 'type-graphql'
3
+
4
+ import { pubsub, Data, getRepository } from '@things-factory/shell'
5
+ import { StateRegister } from './state-register'
6
+
7
+ /* 이 Resolver는 @things-factory/shell에서 등록한 DataResolver를 Overide 한 것이다. */
8
+ @Resolver()
9
+ export class DataResolver {
10
+ @Subscription({
11
+ subscribe: ({ args, context, info }) => {
12
+ const { domain, user } = context.state
13
+ const { tag } = args
14
+ const subdomain = domain?.subdomain
15
+
16
+ if (!domain || !tag) {
17
+ throw new Error('domain and tag required')
18
+ }
19
+
20
+ //@ts-ignore
21
+ if (!user.domains?.find(d => d.subdomain === subdomain) && !process.superUserGranted(domain, user)) {
22
+ throw new Error(`domain(${subdomain}) is not working for user(${user.email}).`)
23
+ }
24
+
25
+ process.nextTick(async () => {
26
+ /* state-register에 등록된 태그라면, 현재 상태값을 publish 한다. */
27
+ const { domain } = context.state
28
+
29
+ const state = await getRepository(StateRegister).findOne({
30
+ where: { domain: { id: domain.id }, name: tag }
31
+ })
32
+
33
+ if (state) {
34
+ pubsub.publish('data', {
35
+ data: {
36
+ domain,
37
+ tag,
38
+ data: state.state
39
+ }
40
+ })
41
+ }
42
+ })
43
+
44
+ return pipe(
45
+ pubsub.subscribe('data'),
46
+ filter((payload: { data: Data }) => {
47
+ const { domain: pdomain, tag: ptag, data } = payload.data
48
+ return tag === ptag && subdomain === pdomain?.subdomain
49
+ })
50
+ )
51
+ }
52
+ })
53
+ data(@Root() payload: { data: Data }, @Arg('tag') tag: string): Data {
54
+ return payload.data
55
+ }
56
+ }
@@ -1,7 +1,8 @@
1
1
  import { StateRegister } from './state-register'
2
2
  import { StateRegisterQuery } from './state-register-query'
3
3
  import { StateRegisterMutation } from './state-register-mutation'
4
+ import { DataResolver } from './data-resolver'
4
5
 
5
6
  export const entities = [StateRegister]
6
- export const resolvers = [StateRegisterQuery, StateRegisterMutation]
7
+ export const resolvers = [StateRegisterQuery, StateRegisterMutation, DataResolver]
7
8
  export const subscribers = []
@@ -38,7 +38,7 @@ export class StateRegisterQuery {
38
38
  domain,
39
39
  params,
40
40
  repository: await getRepository(StateRegister),
41
- searchables: ['name', 'description']
41
+ searchables: ['name', 'description', 'group']
42
42
  })
43
43
 
44
44
  const [items, total] = await queryBuilder.getManyAndCount()
@@ -1,64 +1,80 @@
1
- import type { FileUpload } from 'graphql-upload/GraphQLUpload.js'
2
- import GraphQLUpload from 'graphql-upload/GraphQLUpload.js'
3
- import { ObjectType, Field, InputType, Int, ID, registerEnumType } from 'type-graphql'
1
+ import { ObjectType, Field, InputType, Int, ID } from 'type-graphql'
4
2
 
5
- import { ObjectRef, ScalarObject } from '@things-factory/shell'
3
+ import { ScalarObject } from '@things-factory/shell'
6
4
 
7
5
  import { StateRegister } from './state-register'
8
6
 
9
7
  @InputType()
10
8
  export class NewStateRegister {
11
- @Field()
9
+ @Field({ description: 'Name of the state register' })
12
10
  name: string
13
11
 
14
- @Field({ nullable: true })
12
+ @Field({ nullable: true, description: 'Description of the state register' })
15
13
  description?: string
16
14
 
17
- @Field({ nullable: true })
15
+ @Field({ nullable: true, description: 'Group name for the state register' })
16
+ group?: string
17
+
18
+ @Field({ nullable: true, description: 'Type of the state' })
18
19
  type?: string
19
20
 
20
- @Field(type => ScalarObject, { nullable: true })
21
+ @Field({ nullable: true, description: 'Number of decimal places if the state is a number type' })
22
+ place?: string
23
+
24
+ @Field({ nullable: true, description: 'Unit of the state value' })
25
+ unit?: string
26
+
27
+ @Field(type => ScalarObject, { nullable: true, description: 'Current state value' })
21
28
  state?: any
22
29
 
23
- @Field(type => Int, { nullable: true })
30
+ @Field(type => Int, { nullable: true, description: 'Time to live for the state value in seconds' })
24
31
  ttl?: number
25
32
 
26
- @Field({ nullable: true })
33
+ @Field({ nullable: true, description: 'Reference to an external entity or data, used as a flexible foreign key' })
27
34
  refBy?: string
28
35
  }
29
36
 
30
37
  @InputType()
31
38
  export class StateRegisterPatch {
32
- @Field(type => ID, { nullable: true })
39
+ @Field(type => ID, { nullable: true, description: 'ID of the state register' })
33
40
  id?: string
34
41
 
35
- @Field({ nullable: true })
42
+ @Field({ nullable: true, description: 'Name of the state register' })
36
43
  name?: string
37
44
 
38
- @Field({ nullable: true })
45
+ @Field({ nullable: true, description: 'Description of the state register' })
39
46
  description?: string
40
47
 
41
- @Field({ nullable: true })
48
+ @Field({ nullable: true, description: 'Group name for the state register' })
49
+ group?: string
50
+
51
+ @Field({ nullable: true, description: 'Type of the state' })
42
52
  type?: string
43
53
 
44
- @Field(type => ScalarObject, { nullable: true })
54
+ @Field({ nullable: true, description: 'Number of decimal places if the state is a number type' })
55
+ place?: string
56
+
57
+ @Field({ nullable: true, description: 'Unit of the state value' })
58
+ unit?: string
59
+
60
+ @Field(type => ScalarObject, { nullable: true, description: 'Current state value' })
45
61
  state?: any
46
62
 
47
- @Field(type => Int, { nullable: true })
63
+ @Field(type => Int, { nullable: true, description: 'Time to live for the state value in seconds' })
48
64
  ttl?: number
49
65
 
50
- @Field({ nullable: true })
66
+ @Field({ nullable: true, description: 'Reference to an external entity or data, used as a flexible foreign key' })
51
67
  refBy?: string
52
68
 
53
- @Field({ nullable: true })
69
+ @Field({ nullable: true, description: 'Flag indicating create/update operations' })
54
70
  cuFlag?: string
55
71
  }
56
72
 
57
73
  @ObjectType()
58
74
  export class StateRegisterList {
59
- @Field(type => [StateRegister])
75
+ @Field(type => [StateRegister], { description: 'List of state registers' })
60
76
  items: StateRegister[]
61
77
 
62
- @Field(type => Int)
78
+ @Field(type => Int, { description: 'Total number of state registers' })
63
79
  total: number
64
80
  }