@things-factory/integration-base 7.0.7 → 7.0.10

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 (46) hide show
  1. package/dist-server/controllers/index.d.ts +1 -0
  2. package/dist-server/controllers/index.js +1 -0
  3. package/dist-server/controllers/index.js.map +1 -1
  4. package/dist-server/controllers/publish-data.d.ts +6 -0
  5. package/dist-server/controllers/publish-data.js +22 -0
  6. package/dist-server/controllers/publish-data.js.map +1 -0
  7. package/dist-server/engine/task/index.d.ts +1 -0
  8. package/dist-server/engine/task/index.js +1 -0
  9. package/dist-server/engine/task/index.js.map +1 -1
  10. package/dist-server/engine/task/state-group-read.d.ts +1 -0
  11. package/dist-server/engine/task/state-group-read.js +62 -0
  12. package/dist-server/engine/task/state-group-read.js.map +1 -0
  13. package/dist-server/service/index.d.ts +1 -1
  14. package/dist-server/service/scenario-instance/scenario-instance-type.js +6 -9
  15. package/dist-server/service/scenario-instance/scenario-instance-type.js.map +1 -1
  16. package/dist-server/service/state-register/data-resolver.d.ts +6 -0
  17. package/dist-server/service/state-register/data-resolver.js +61 -0
  18. package/dist-server/service/state-register/data-resolver.js.map +1 -0
  19. package/dist-server/service/state-register/index.d.ts +2 -1
  20. package/dist-server/service/state-register/index.js +2 -1
  21. package/dist-server/service/state-register/index.js.map +1 -1
  22. package/dist-server/service/state-register/state-register-query.js +1 -1
  23. package/dist-server/service/state-register/state-register-query.js.map +1 -1
  24. package/dist-server/service/state-register/state-register-type.d.ts +6 -0
  25. package/dist-server/service/state-register/state-register-type.js +40 -16
  26. package/dist-server/service/state-register/state-register-type.js.map +1 -1
  27. package/dist-server/service/state-register/state-register.d.ts +3 -0
  28. package/dist-server/service/state-register/state-register.js +36 -13
  29. package/dist-server/service/state-register/state-register.js.map +1 -1
  30. package/dist-server/tsconfig.tsbuildinfo +1 -1
  31. package/helps/integration/task/state-group-read.ja.md +8 -0
  32. package/helps/integration/task/state-group-read.ko.md +8 -0
  33. package/helps/integration/task/state-group-read.md +10 -0
  34. package/helps/integration/task/state-group-read.ms.md +8 -0
  35. package/helps/integration/task/state-group-read.zh.md +8 -0
  36. package/package.json +8 -8
  37. package/server/controllers/index.ts +1 -0
  38. package/server/controllers/publish-data.ts +29 -0
  39. package/server/engine/task/index.ts +1 -0
  40. package/server/engine/task/state-group-read.ts +69 -0
  41. package/server/service/scenario-instance/scenario-instance-type.ts +6 -9
  42. package/server/service/state-register/data-resolver.ts +56 -0
  43. package/server/service/state-register/index.ts +2 -1
  44. package/server/service/state-register/state-register-query.ts +1 -1
  45. package/server/service/state-register/state-register-type.ts +36 -20
  46. package/server/service/state-register/state-register.ts +39 -17
@@ -0,0 +1,8 @@
1
+ # state-group-read
2
+
3
+ このタスクは、[状態レジスター](../concept/state-register.md)内の特定のグループに属するすべての状態の値を読み取ります。
4
+
5
+ ## パラメータ
6
+
7
+ - group
8
+ - 取得する状態「グループ」の名称を指定します。
@@ -0,0 +1,8 @@
1
+ # state-group-read
2
+
3
+ [상태등록부(state-register)](../concept/state-register.md)에 특정 그룹에 속하는 모든 상태의 값을 읽어오는 태스크이다.
4
+
5
+ ## parameters
6
+
7
+ - group
8
+ - 가져올 상태 "그룹"의 명칭을 지정한다
@@ -0,0 +1,10 @@
1
+ ### English Translation
2
+
3
+ # state-group-read
4
+
5
+ This task reads the values of all states belonging to a specific group in the [state-register](../concept/state-register.md).
6
+
7
+ ## parameters
8
+
9
+ - group
10
+ - Specifies the name of the "group" of states to be fetched.
@@ -0,0 +1,8 @@
1
+ # state-group-read
2
+
3
+ Tugas ini membaca nilai semua keadaan yang tergolong dalam kumpulan tertentu di [daftar keadaan](../concept/state-register.md).
4
+
5
+ ## parameter
6
+
7
+ - group
8
+ - Menentukan nama "kumpulan" keadaan yang hendak diambil.
@@ -0,0 +1,8 @@
1
+ # state-group-read
2
+
3
+ 该任务从[状态注册表](../concept/state-register.md)中读取属于特定组的所有状态的值。
4
+
5
+ ## 参数
6
+
7
+ - group
8
+ - 指定要获取的状态“组”的名称。
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.10",
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": "9da4e145880a6d637db60f03116d5bbfdb6f4cfc"
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
+ }
@@ -41,3 +41,4 @@ import './oracle-procedure'
41
41
  import './jsonata'
42
42
  import './state-read'
43
43
  import './state-write'
44
+ import './state-group-read'
@@ -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
  }
@@ -1,16 +1,14 @@
1
1
  import {
2
2
  CreateDateColumn,
3
3
  UpdateDateColumn,
4
- DeleteDateColumn,
5
4
  Entity,
6
5
  Index,
7
6
  Column,
8
7
  RelationId,
9
8
  ManyToOne,
10
- PrimaryGeneratedColumn,
11
- VersionColumn
9
+ PrimaryGeneratedColumn
12
10
  } from 'typeorm'
13
- import { ObjectType, Field, Int, ID, registerEnumType } from 'type-graphql'
11
+ import { ObjectType, Field, Int, ID } from 'type-graphql'
14
12
 
15
13
  import { Domain, ScalarObject } from '@things-factory/shell'
16
14
  import { User } from '@things-factory/auth-base'
@@ -19,6 +17,14 @@ import { User } from '@things-factory/auth-base'
19
17
  @Index('ix_state_register_0', (stateRegister: StateRegister) => [stateRegister.domain, stateRegister.name], {
20
18
  unique: true
21
19
  })
20
+ @Index(
21
+ 'ix_state_register_1',
22
+ (stateRegister: StateRegister) => [stateRegister.domain, stateRegister.group, stateRegister.name],
23
+ {
24
+ unique: true,
25
+ where: '"group" IS NOT NULL'
26
+ }
27
+ )
22
28
  @ObjectType({ description: 'Entity for StateRegister' })
23
29
  export class StateRegister {
24
30
  @PrimaryGeneratedColumn('uuid')
@@ -26,66 +32,82 @@ export class StateRegister {
26
32
  readonly id: string
27
33
 
28
34
  @ManyToOne(type => Domain)
29
- @Field(type => Domain)
35
+ @Field(type => Domain, { description: 'Associated domain for the state register' })
30
36
  domain?: Domain
31
37
 
32
38
  @RelationId((stateRegister: StateRegister) => stateRegister.domain)
39
+ @Field({ description: 'ID of the associated domain' })
33
40
  domainId?: string
34
41
 
35
42
  @Column()
36
- @Field({ nullable: true })
43
+ @Field({ nullable: true, description: 'Name of the state register' })
37
44
  name?: string
38
45
 
39
46
  @Column({ nullable: true })
40
- @Field({ nullable: true })
47
+ @Field({ nullable: true, description: 'Description of the state register' })
41
48
  description?: string
42
49
 
43
50
  @Column({ nullable: true })
44
- @Field({ nullable: true })
51
+ @Field({ nullable: true, description: 'Group name for the state register' })
52
+ group?: string
53
+
54
+ @Column({ nullable: true })
55
+ @Field({ nullable: true, description: 'Type of the state' })
45
56
  type?: string
46
57
 
58
+ @Column({ nullable: true })
59
+ @Field({ nullable: true, description: 'Number of decimal places if the state is a number type' })
60
+ place?: string
61
+
62
+ @Column({ nullable: true })
63
+ @Field({ nullable: true, description: 'Unit of the state value' })
64
+ unit?: string
65
+
47
66
  @Column('simple-json', { nullable: true, default: null })
48
- @Field(type => ScalarObject, { nullable: true })
67
+ @Field(type => ScalarObject, { nullable: true, description: 'Current state value' })
49
68
  state?: any
50
69
 
51
70
  @Column({ nullable: true, default: null })
52
- @Field(type => Int, { nullable: true })
71
+ @Field(type => Int, { nullable: true, description: 'Time to live for the state value in seconds' })
53
72
  ttl?: number
54
73
 
55
74
  @Column({ nullable: true })
56
- @Field({ nullable: true })
75
+ @Field({ nullable: true, description: 'Reference to an external entity or data, used as a flexible foreign key' })
57
76
  refBy?: string
58
77
 
59
78
  @Column({ nullable: true })
60
- @Field({ nullable: true })
79
+ @Field({ nullable: true, description: 'Time when the state was recorded' })
61
80
  wroteAt?: Date
62
81
 
63
82
  @CreateDateColumn()
64
- @Field({ nullable: true })
83
+ @Field({ nullable: true, description: 'Creation time of the state register' })
65
84
  createdAt?: Date
66
85
 
67
86
  @UpdateDateColumn()
68
- @Field({ nullable: true })
87
+ @Field({ nullable: true, description: 'Last update time of the state register' })
69
88
  updatedAt?: Date
70
89
 
71
90
  @ManyToOne(type => User, { nullable: true })
72
- @Field(type => User, { nullable: true })
91
+ @Field(type => User, { nullable: true, description: 'User who wrote the state' })
73
92
  writer?: User
74
93
 
75
94
  @RelationId((stateRegister: StateRegister) => stateRegister.writer)
95
+ @Field({ nullable: true, description: 'ID of the user who wrote the state' })
76
96
  writerId?: string
77
97
 
78
98
  @ManyToOne(type => User, { nullable: true })
79
- @Field(type => User, { nullable: true })
99
+ @Field(type => User, { nullable: true, description: 'User who created the state register' })
80
100
  creator?: User
81
101
 
82
102
  @RelationId((stateRegister: StateRegister) => stateRegister.creator)
103
+ @Field({ nullable: true, description: 'ID of the user who created the state register' })
83
104
  creatorId?: string
84
105
 
85
106
  @ManyToOne(type => User, { nullable: true })
86
- @Field(type => User, { nullable: true })
107
+ @Field(type => User, { nullable: true, description: 'User who last updated the state register' })
87
108
  updater?: User
88
109
 
89
110
  @RelationId((stateRegister: StateRegister) => stateRegister.updater)
111
+ @Field({ nullable: true, description: 'ID of the user who last updated the state register' })
90
112
  updaterId?: string
91
113
  }