@things-factory/board-service 6.2.15 → 6.2.19
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/dist-server/routers/standalone-board-service-router.js +22 -0
- package/dist-server/routers/standalone-board-service-router.js.map +1 -1
- package/dist-server/service/board/board-mutation.js +3 -2
- package/dist-server/service/board/board-mutation.js.map +1 -1
- package/dist-server/service/board-template/board-template-mutation.js +56 -4
- package/dist-server/service/board-template/board-template-mutation.js.map +1 -1
- package/dist-server/service/board-template/board-template-query.js +51 -39
- package/dist-server/service/board-template/board-template-query.js.map +1 -1
- package/dist-server/service/board-template/board-template-type.js +8 -8
- package/dist-server/service/board-template/board-template-type.js.map +1 -1
- package/dist-server/service/board-template/board-template.js +7 -10
- package/dist-server/service/board-template/board-template.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/server/routers/standalone-board-service-router.ts +27 -0
- package/server/service/board/board-mutation.ts +5 -3
- package/server/service/board-template/board-template-mutation.ts +69 -4
- package/server/service/board-template/board-template-query.ts +56 -33
- package/server/service/board-template/board-template-type.ts +12 -17
- package/server/service/board-template/board-template.ts +8 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/board-service",
|
|
3
|
-
"version": "6.2.
|
|
3
|
+
"version": "6.2.19",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "client/index.js",
|
|
6
6
|
"things-factory": true,
|
|
@@ -24,11 +24,11 @@
|
|
|
24
24
|
"migration:create": "node ../../node_modules/typeorm/cli.js migration:create -d ./server/migrations"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@things-factory/auth-base": "^6.2.
|
|
27
|
+
"@things-factory/auth-base": "^6.2.19",
|
|
28
28
|
"@things-factory/env": "^6.2.0",
|
|
29
|
-
"@things-factory/fav-base": "^6.2.
|
|
30
|
-
"@things-factory/font-base": "^6.2.
|
|
31
|
-
"@things-factory/integration-base": "^6.2.
|
|
29
|
+
"@things-factory/fav-base": "^6.2.19",
|
|
30
|
+
"@things-factory/font-base": "^6.2.19",
|
|
31
|
+
"@things-factory/integration-base": "^6.2.19",
|
|
32
32
|
"@things-factory/operato-license-checker": "^3.1.0",
|
|
33
33
|
"content-disposition": "^0.5.3",
|
|
34
34
|
"generic-pool": "^3.8.2"
|
|
@@ -37,5 +37,5 @@
|
|
|
37
37
|
"@thiagoelg/node-printer": "0.6.2",
|
|
38
38
|
"puppeteer": "^20.7.3"
|
|
39
39
|
},
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "5b5f3c02adca0ecb6344310bfeaf27b04c5dc657"
|
|
41
41
|
}
|
|
@@ -11,6 +11,7 @@ import { labelcommand } from '../controllers/label-command'
|
|
|
11
11
|
import { pdf } from '../controllers/pdf'
|
|
12
12
|
import { screenshot } from '../controllers/screenshot'
|
|
13
13
|
import { Board } from '../service/board/board'
|
|
14
|
+
import { BoardTemplate } from '../service/board-template/board-template'
|
|
14
15
|
|
|
15
16
|
export const standaloneBoardServiceRouter = new Router()
|
|
16
17
|
|
|
@@ -216,6 +217,32 @@ standaloneBoardServiceRouter.get('/thumbnail/:id', async (context, next) => {
|
|
|
216
217
|
}
|
|
217
218
|
})
|
|
218
219
|
|
|
220
|
+
// for board-template thumbnail
|
|
221
|
+
standaloneBoardServiceRouter.get('/board-template-thumbnail/:id', async (context, next) => {
|
|
222
|
+
const { domain, user } = context.state
|
|
223
|
+
|
|
224
|
+
if (!(await User.hasPrivilege('query', 'board-template', domain, user))) {
|
|
225
|
+
context.status = 403
|
|
226
|
+
return
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const { id } = context.params
|
|
230
|
+
|
|
231
|
+
const { name, thumbnail } = (await getRepository(BoardTemplate).findOneBy({ domain: { id: domain.id }, id })) || {}
|
|
232
|
+
|
|
233
|
+
if (thumbnail) {
|
|
234
|
+
const index = thumbnail.indexOf(';base64,')
|
|
235
|
+
const base64 = thumbnail.substring(index + 8)
|
|
236
|
+
const buffer = Buffer.from(base64, 'base64')
|
|
237
|
+
|
|
238
|
+
context.type = 'image/png'
|
|
239
|
+
context.set('Content-Disposition', contentDisposition(`thumbnail-${name}.png`))
|
|
240
|
+
context.body = buffer
|
|
241
|
+
} else {
|
|
242
|
+
context.throw(404, 'thumbnail not found')
|
|
243
|
+
}
|
|
244
|
+
})
|
|
245
|
+
|
|
219
246
|
// for webpage scrap
|
|
220
247
|
standaloneBoardServiceRouter.get('/screenshot/:id', async (context, next) => {
|
|
221
248
|
const { domain, user } = context.state
|
|
@@ -55,10 +55,12 @@ export class BoardMutation {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
const newBoard: Board = {
|
|
58
|
-
...board
|
|
59
|
-
thumbnail: 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==' /* empty thumbnail */
|
|
58
|
+
...board
|
|
60
59
|
}
|
|
61
60
|
|
|
61
|
+
newBoard.thumbnail ||=
|
|
62
|
+
'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==' /* empty thumbnail */
|
|
63
|
+
|
|
62
64
|
if (board.groupId) {
|
|
63
65
|
newBoard.group = await groupRepository.findOneBy({
|
|
64
66
|
id: board.groupId
|
|
@@ -239,7 +241,7 @@ export class BoardMutation {
|
|
|
239
241
|
|
|
240
242
|
@Directive('@transaction')
|
|
241
243
|
@Directive('@privilege(category: "board", privilege: "mutation", domainOwnerGranted: true)')
|
|
242
|
-
@Mutation(returns => Board, { description: 'To release Board
|
|
244
|
+
@Mutation(returns => Board, { description: 'To release a Board' })
|
|
243
245
|
async releaseBoard(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Board> {
|
|
244
246
|
const { domain, user, notify, tx } = context.state
|
|
245
247
|
const repository = tx.getRepository(Board)
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { Resolver, Mutation, Arg, Ctx, Directive } from 'type-graphql'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { getRedirectSubdomainPath } from '@things-factory/shell'
|
|
4
4
|
import { BoardTemplate } from './board-template'
|
|
5
|
+
import { Board } from '../board/board'
|
|
5
6
|
import { NewBoardTemplate, BoardTemplatePatch } from './board-template-type'
|
|
7
|
+
import { thumbnail } from '../../controllers/thumbnail'
|
|
6
8
|
|
|
7
9
|
@Resolver(BoardTemplate)
|
|
8
10
|
export class BoardTemplateMutation {
|
|
9
11
|
@Directive('@transaction')
|
|
10
|
-
@Directive('@privilege(category: "board", privilege: "mutation", domainOwnerGranted: true)')
|
|
12
|
+
@Directive('@privilege(category: "board-template", privilege: "mutation", domainOwnerGranted: true)')
|
|
11
13
|
@Mutation(returns => BoardTemplate, { description: 'To create new BoardTemplate' })
|
|
12
14
|
async createBoardTemplate(
|
|
13
15
|
@Arg('boardTemplate') boardTemplate: NewBoardTemplate,
|
|
@@ -49,7 +51,7 @@ export class BoardTemplateMutation {
|
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
@Directive('@transaction')
|
|
52
|
-
@Directive('@privilege(category: "board", privilege: "mutation", domainOwnerGranted: true)')
|
|
54
|
+
@Directive('@privilege(category: "board-template", privilege: "mutation", domainOwnerGranted: true)')
|
|
53
55
|
@Mutation(returns => BoardTemplate, { description: 'To modify BoardTemplate information' })
|
|
54
56
|
async updateBoardTemplate(
|
|
55
57
|
@Arg('id') id: string,
|
|
@@ -84,7 +86,7 @@ export class BoardTemplateMutation {
|
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
@Directive('@transaction')
|
|
87
|
-
@Directive('@privilege(category: "board", privilege: "mutation", domainOwnerGranted: true)')
|
|
89
|
+
@Directive('@privilege(category: "board-template", privilege: "mutation", domainOwnerGranted: true)')
|
|
88
90
|
@Mutation(returns => Boolean, { description: 'To delete BoardTemplate' })
|
|
89
91
|
async deleteBoardTemplate(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {
|
|
90
92
|
const { domain, tx } = context.state
|
|
@@ -93,4 +95,67 @@ export class BoardTemplateMutation {
|
|
|
93
95
|
|
|
94
96
|
return true
|
|
95
97
|
}
|
|
98
|
+
|
|
99
|
+
@Directive('@transaction')
|
|
100
|
+
@Directive('@privilege(category: "board-template", privilege: "mutation", domainOwnerGranted: true)')
|
|
101
|
+
@Mutation(returns => BoardTemplate, { description: 'To register a board as a board template with the given ID' })
|
|
102
|
+
async registerBoardAsTemplate(
|
|
103
|
+
@Arg('id', { description: 'board Id to be regiestered' }) id: string,
|
|
104
|
+
@Arg('name', { description: 'name of board template to be regiestered' }) name: string,
|
|
105
|
+
@Arg('description', { description: 'description of board template to be regiestered' }) description: string,
|
|
106
|
+
@Arg('visibility', { description: 'visibility of board template to be regiestered' }) visibility: string,
|
|
107
|
+
@Ctx() context: ResolverContext
|
|
108
|
+
): Promise<BoardTemplate> {
|
|
109
|
+
const { domain, user, notify, tx } = context.state
|
|
110
|
+
|
|
111
|
+
const boardTemplateRepository = tx.getRepository(BoardTemplate)
|
|
112
|
+
|
|
113
|
+
const board = await tx.getRepository(Board).findOne({
|
|
114
|
+
where: { domain: { id: domain.id }, id }
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
if (!board) {
|
|
118
|
+
throw `Board given id(${id}) is not found`
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
name ||= board.name
|
|
122
|
+
|
|
123
|
+
const { model, thumbnail } = board
|
|
124
|
+
|
|
125
|
+
const boardTemplate = await boardTemplateRepository.findOne({
|
|
126
|
+
where: { domain: { id: domain.id }, name }
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
const registered = boardTemplate
|
|
130
|
+
? await boardTemplateRepository.save({
|
|
131
|
+
...boardTemplate,
|
|
132
|
+
name,
|
|
133
|
+
description: description || boardTemplate.description,
|
|
134
|
+
visibility: visibility || boardTemplate.visibility,
|
|
135
|
+
model,
|
|
136
|
+
thumbnail,
|
|
137
|
+
updater: user
|
|
138
|
+
})
|
|
139
|
+
: await boardTemplateRepository.save({
|
|
140
|
+
domain: { id: domain.id },
|
|
141
|
+
name,
|
|
142
|
+
description: description || board.description,
|
|
143
|
+
model,
|
|
144
|
+
thumbnail,
|
|
145
|
+
visibility: visibility || 'private',
|
|
146
|
+
updater: user,
|
|
147
|
+
creator: user
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
notify &&
|
|
151
|
+
notify({
|
|
152
|
+
mode: 'in-app',
|
|
153
|
+
title: `BoardTemplate '${registered.name}' registered`,
|
|
154
|
+
body: `BoardTemplate '${registered.name}' registered by ${user.name}\n${registered.description}`,
|
|
155
|
+
image: getRedirectSubdomainPath(context, domain.subdomain, `/board-template-thumbnail/${registered.id}`),
|
|
156
|
+
url: getRedirectSubdomainPath(context, domain.subdomain, `/board-template-viewer/${registered.id}`)
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
return registered
|
|
160
|
+
}
|
|
96
161
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { In } from 'typeorm'
|
|
1
|
+
import { Brackets, In } from 'typeorm'
|
|
2
2
|
import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx, Directive } from 'type-graphql'
|
|
3
3
|
import { Attachment } from '@things-factory/attachment-base'
|
|
4
4
|
import { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'
|
|
@@ -9,23 +9,35 @@ import { BoardTemplateList } from './board-template-type'
|
|
|
9
9
|
@Resolver(BoardTemplate)
|
|
10
10
|
export class BoardTemplateQuery {
|
|
11
11
|
@Query(returns => BoardTemplate!, { nullable: true, description: 'To fetch a BoardTemplate' })
|
|
12
|
-
@Directive('@privilege(category: "board", privilege: "query", domainOwnerGranted: true)')
|
|
12
|
+
@Directive('@privilege(category: "board-template", privilege: "query", domainOwnerGranted: true)')
|
|
13
13
|
async boardTemplate(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<BoardTemplate> {
|
|
14
|
-
const { domain } = context.state
|
|
15
|
-
|
|
16
|
-
return await getRepository(BoardTemplate).findOne({
|
|
17
|
-
where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id }
|
|
18
|
-
})
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
@Query(returns => BoardTemplate, { nullable: true, description: 'To fetch a BoardTemplate by name' })
|
|
22
|
-
@Directive('@privilege(category: "board", privilege: "query", domainOwnerGranted: true)')
|
|
23
|
-
async boardTemplateByName(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<BoardTemplate> {
|
|
24
|
-
const { domain } = context.state
|
|
14
|
+
const { domain, user } = context.state
|
|
25
15
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
16
|
+
const qb = await getRepository(BoardTemplate)
|
|
17
|
+
.createQueryBuilder('BoardTemplate')
|
|
18
|
+
.where('id=:id', { id })
|
|
19
|
+
.andWhere(
|
|
20
|
+
new Brackets(qb => {
|
|
21
|
+
qb.where({ visibility: 'public' })
|
|
22
|
+
.orWhere({
|
|
23
|
+
visibility: 'domain',
|
|
24
|
+
domain: { id: In([domain.id, domain.parentId]) }
|
|
25
|
+
})
|
|
26
|
+
.orWhere({
|
|
27
|
+
visibility: 'private',
|
|
28
|
+
creator: { id: user.id }
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
return qb.getOne()
|
|
34
|
+
|
|
35
|
+
// return await getRepository(BoardTemplate).findOne({
|
|
36
|
+
// where: {
|
|
37
|
+
// domain: { id: In([domain.id, domain.parentId].filter(Boolean)) },
|
|
38
|
+
// id
|
|
39
|
+
// }
|
|
40
|
+
// })
|
|
29
41
|
}
|
|
30
42
|
|
|
31
43
|
@Query(returns => BoardTemplateList, { description: 'To fetch BoardTemplates created by me' })
|
|
@@ -33,12 +45,11 @@ export class BoardTemplateQuery {
|
|
|
33
45
|
@Args() params: ListParam,
|
|
34
46
|
@Ctx() context: ResolverContext
|
|
35
47
|
): Promise<BoardTemplateList> {
|
|
36
|
-
const {
|
|
48
|
+
const { user } = context.state
|
|
37
49
|
|
|
38
50
|
const queryBuilder = getQueryBuilderFromListParams({
|
|
39
51
|
repository: getRepository(BoardTemplate),
|
|
40
52
|
params,
|
|
41
|
-
domain,
|
|
42
53
|
alias: 'template',
|
|
43
54
|
searchables: ['name', 'description']
|
|
44
55
|
}).andWhere('template.creator = :user', { user: user.id })
|
|
@@ -49,33 +60,45 @@ export class BoardTemplateQuery {
|
|
|
49
60
|
}
|
|
50
61
|
|
|
51
62
|
@Query(returns => BoardTemplateList, { description: 'To fetch multiple BoardTemplates' })
|
|
52
|
-
@Directive('@privilege(category: "board", privilege: "query", domainOwnerGranted: true)')
|
|
63
|
+
@Directive('@privilege(category: "board-template", privilege: "query", domainOwnerGranted: true)')
|
|
53
64
|
async boardTemplates(@Args() params: ListParam, @Ctx() context: ResolverContext): Promise<BoardTemplateList> {
|
|
54
|
-
const { domain } = context.state
|
|
65
|
+
const { domain, user } = context.state
|
|
66
|
+
/*
|
|
67
|
+
리스트에 포함되는 보드템플릿들
|
|
68
|
+
- visibility가 public 인 경우
|
|
69
|
+
- visibility가 domain이며 컨텍스트의 도메인과 같은 경우
|
|
70
|
+
- visibility가 private 이며, creator가 나인 경우
|
|
71
|
+
*/
|
|
55
72
|
|
|
56
73
|
const queryBuilder = getQueryBuilderFromListParams({
|
|
57
|
-
domain,
|
|
58
74
|
params,
|
|
59
75
|
repository: await getRepository(BoardTemplate),
|
|
60
76
|
searchables: ['name', 'description']
|
|
61
|
-
})
|
|
77
|
+
}).andWhere(
|
|
78
|
+
new Brackets(qb => {
|
|
79
|
+
qb.where({ visibility: 'public' })
|
|
80
|
+
.orWhere({
|
|
81
|
+
visibility: 'domain',
|
|
82
|
+
domain: { id: In([domain.id, domain.parentId]) }
|
|
83
|
+
})
|
|
84
|
+
.orWhere({
|
|
85
|
+
visibility: 'private',
|
|
86
|
+
creator: { id: user.id }
|
|
87
|
+
})
|
|
88
|
+
})
|
|
89
|
+
)
|
|
62
90
|
|
|
63
91
|
const [items, total] = await queryBuilder.getManyAndCount()
|
|
64
92
|
|
|
65
93
|
return { items, total }
|
|
66
94
|
}
|
|
67
95
|
|
|
68
|
-
@FieldResolver(type =>
|
|
69
|
-
async
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
refBy: boardTemplate.id
|
|
75
|
-
}
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
return attachment?.fullpath
|
|
96
|
+
@FieldResolver(type => Boolean)
|
|
97
|
+
async mine(@Root() boardTemplate: BoardTemplate, @Ctx() context: ResolverContext): Promise<boolean> {
|
|
98
|
+
const { creatorId } = boardTemplate
|
|
99
|
+
const { user } = context.state
|
|
100
|
+
|
|
101
|
+
return creatorId == user.id
|
|
79
102
|
}
|
|
80
103
|
|
|
81
104
|
@FieldResolver(type => Domain)
|
|
@@ -1,27 +1,22 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { ObjectType, Field, InputType, Int, ID, registerEnumType } from 'type-graphql'
|
|
4
|
-
|
|
5
|
-
import { ObjectRef, ScalarObject } from '@things-factory/shell'
|
|
6
|
-
|
|
7
|
-
import { BoardTemplate, BoardTemplateStatus } from './board-template'
|
|
1
|
+
import { ObjectType, Field, InputType, Int, ID } from 'type-graphql'
|
|
2
|
+
import { BoardTemplate } from './board-template'
|
|
8
3
|
|
|
9
4
|
@InputType()
|
|
10
5
|
export class NewBoardTemplate {
|
|
11
6
|
@Field()
|
|
12
7
|
name: string
|
|
13
8
|
|
|
14
|
-
@Field(
|
|
15
|
-
description
|
|
16
|
-
|
|
17
|
-
@Field(type => BoardTemplateStatus, { nullable: true })
|
|
18
|
-
state?: BoardTemplateStatus
|
|
9
|
+
@Field()
|
|
10
|
+
description: string
|
|
19
11
|
|
|
20
12
|
@Field()
|
|
21
13
|
model: string
|
|
22
14
|
|
|
15
|
+
@Field()
|
|
16
|
+
visibility: 'private' | 'public'
|
|
17
|
+
|
|
23
18
|
@Field({ nullable: true })
|
|
24
|
-
thumbnail
|
|
19
|
+
thumbnail: string
|
|
25
20
|
}
|
|
26
21
|
|
|
27
22
|
@InputType()
|
|
@@ -35,12 +30,12 @@ export class BoardTemplatePatch {
|
|
|
35
30
|
@Field({ nullable: true })
|
|
36
31
|
description?: string
|
|
37
32
|
|
|
38
|
-
@Field(
|
|
39
|
-
state?: BoardTemplateStatus
|
|
40
|
-
|
|
41
|
-
@Field()
|
|
33
|
+
@Field({ nullable: true })
|
|
42
34
|
model: string
|
|
43
35
|
|
|
36
|
+
@Field({ nullable: true })
|
|
37
|
+
visibility?: 'private' | 'public'
|
|
38
|
+
|
|
44
39
|
@Field({ nullable: true })
|
|
45
40
|
thumbnail?: string
|
|
46
41
|
|
|
@@ -6,12 +6,11 @@ import {
|
|
|
6
6
|
Column,
|
|
7
7
|
RelationId,
|
|
8
8
|
ManyToOne,
|
|
9
|
-
PrimaryGeneratedColumn
|
|
10
|
-
VersionColumn
|
|
9
|
+
PrimaryGeneratedColumn
|
|
11
10
|
} from 'typeorm'
|
|
12
11
|
import { ObjectType, Field, Int, ID, registerEnumType } from 'type-graphql'
|
|
13
12
|
|
|
14
|
-
import { Domain } from '@things-factory/shell'
|
|
13
|
+
import { Domain, ScalarObject } from '@things-factory/shell'
|
|
15
14
|
import { User } from '@things-factory/auth-base'
|
|
16
15
|
import { config } from '@things-factory/env'
|
|
17
16
|
|
|
@@ -38,10 +37,6 @@ export class BoardTemplate {
|
|
|
38
37
|
@Field(type => ID)
|
|
39
38
|
readonly id: string
|
|
40
39
|
|
|
41
|
-
@VersionColumn()
|
|
42
|
-
@Field({ nullable: true })
|
|
43
|
-
version?: number = 1
|
|
44
|
-
|
|
45
40
|
@ManyToOne(type => Domain)
|
|
46
41
|
@Field({ nullable: true })
|
|
47
42
|
domain?: Domain
|
|
@@ -57,9 +52,13 @@ export class BoardTemplate {
|
|
|
57
52
|
@Field({ nullable: true })
|
|
58
53
|
description?: string
|
|
59
54
|
|
|
60
|
-
@Column({ nullable: true })
|
|
55
|
+
@Column('simple-json', { nullable: true, default: null })
|
|
56
|
+
@Field(type => ScalarObject, { nullable: true })
|
|
57
|
+
tags?: string[]
|
|
58
|
+
|
|
59
|
+
@Column({ nullable: true, default: 'private' })
|
|
61
60
|
@Field({ nullable: true })
|
|
62
|
-
|
|
61
|
+
visibility?: string // 'private' | 'public' | 'domain'
|
|
63
62
|
|
|
64
63
|
@Column({
|
|
65
64
|
nullable: true,
|