@things-factory/board-service 8.0.5 → 9.0.0-beta.12
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/controllers/headless-pdf-to-image.js +7 -2
- package/dist-server/controllers/headless-pdf-to-image.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/views/internal-board-full-feature-view.html +1 -2
- package/views/internal-board-player-view.html +0 -1
- package/views/internal-board-service-view.html +0 -1
- package/server/constants/error-code.ts +0 -2
- package/server/controllers/analyzer/analyze-integration.ts +0 -142
- package/server/controllers/fonts.ts +0 -83
- package/server/controllers/headless-model.ts +0 -53
- package/server/controllers/headless-pdf-to-image.ts +0 -103
- package/server/controllers/headless-playlist.ts +0 -71
- package/server/controllers/headless-pool-for-board.ts +0 -71
- package/server/controllers/headless-pool-for-label.ts +0 -141
- package/server/controllers/index.ts +0 -11
- package/server/controllers/label-command.ts +0 -62
- package/server/controllers/pdf.ts +0 -132
- package/server/controllers/screenshot.ts +0 -127
- package/server/controllers/thumbnail.ts +0 -18
- package/server/errors/index.ts +0 -1
- package/server/errors/license-error.ts +0 -21
- package/server/index.ts +0 -36
- package/server/migrations/1556862253000-SeedGroup.ts +0 -51
- package/server/migrations/index.ts +0 -9
- package/server/routers/internal-board-view-router.ts +0 -33
- package/server/routers/standalone-board-service-router.ts +0 -326
- package/server/routes.ts +0 -25
- package/server/service/analysis/analysis-query.ts +0 -13
- package/server/service/analysis/index.ts +0 -3
- package/server/service/board/board-history.ts +0 -137
- package/server/service/board/board-mutation.ts +0 -446
- package/server/service/board/board-query.ts +0 -180
- package/server/service/board/board-subscription.ts +0 -43
- package/server/service/board/board-type.ts +0 -58
- package/server/service/board/board.ts +0 -125
- package/server/service/board/event-subscriber.ts +0 -68
- package/server/service/board/index.ts +0 -10
- package/server/service/board-favorite/board-favorite-query.ts +0 -53
- package/server/service/board-favorite/board-favorite-type.ts +0 -18
- package/server/service/board-favorite/index.ts +0 -4
- package/server/service/board-template/board-template-mutation.ts +0 -161
- package/server/service/board-template/board-template-query.ts +0 -121
- package/server/service/board-template/board-template-type.ts +0 -53
- package/server/service/board-template/board-template.ts +0 -114
- package/server/service/board-template/index.ts +0 -7
- package/server/service/group/group-mutation.ts +0 -82
- package/server/service/group/group-query.ts +0 -58
- package/server/service/group/group-type.ts +0 -30
- package/server/service/group/group.ts +0 -69
- package/server/service/group/index.ts +0 -6
- package/server/service/index.ts +0 -56
- package/server/service/permission/domain-permission-subscriber.ts +0 -27
- package/server/service/permission/index.ts +0 -3
- package/server/service/play-group/event-subscriber.ts +0 -58
- package/server/service/play-group/index.ts +0 -9
- package/server/service/play-group/play-group-mutation.ts +0 -148
- package/server/service/play-group/play-group-query.ts +0 -92
- package/server/service/play-group/play-group-subscription.ts +0 -43
- package/server/service/play-group/play-group-type.ts +0 -30
- package/server/service/play-group/play-group.ts +0 -74
- package/server/service/theme/index.ts +0 -7
- package/server/service/theme/theme-mutation.ts +0 -128
- package/server/service/theme/theme-query.ts +0 -48
- package/server/service/theme/theme-type.ts +0 -55
- package/server/service/theme/theme.ts +0 -97
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
import * as genericPool from 'generic-pool'
|
|
2
|
-
|
|
3
|
-
import { config, logger } from '@things-factory/env'
|
|
4
|
-
import { pubsub } from '@things-factory/shell'
|
|
5
|
-
|
|
6
|
-
import { fonts } from './fonts'
|
|
7
|
-
|
|
8
|
-
try {
|
|
9
|
-
var puppeteer = require('puppeteer')
|
|
10
|
-
} catch (err) {
|
|
11
|
-
logger.error(err)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
var headlessPool
|
|
15
|
-
|
|
16
|
-
export function getHeadlessPool() {
|
|
17
|
-
if (!headlessPool) {
|
|
18
|
-
headlessPool = genericPool.createPool(
|
|
19
|
-
{
|
|
20
|
-
create() {
|
|
21
|
-
console.log('headless instance in headless-pool-for-label about to create')
|
|
22
|
-
return initializeScenePage()
|
|
23
|
-
},
|
|
24
|
-
validate({ browser, page }) {
|
|
25
|
-
return Promise.race([
|
|
26
|
-
new Promise(res => setTimeout(() => res(false), 1500)),
|
|
27
|
-
browser
|
|
28
|
-
//@ts-ignore
|
|
29
|
-
.version()
|
|
30
|
-
.then(_ => true)
|
|
31
|
-
.catch(_ => false)
|
|
32
|
-
])
|
|
33
|
-
},
|
|
34
|
-
destroy({ browser, page }) {
|
|
35
|
-
//@ts-ignore
|
|
36
|
-
return browser.close()
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
min: 2,
|
|
41
|
-
max: 10,
|
|
42
|
-
testOnBorrow: true,
|
|
43
|
-
acquireTimeoutMillis: 15000
|
|
44
|
-
}
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
setTimeout(async () => {
|
|
48
|
-
const eventSource = pubsub.subscribe('notify-font-changed')
|
|
49
|
-
for await (const data of eventSource) {
|
|
50
|
-
headlessPool.clear()
|
|
51
|
-
}
|
|
52
|
-
})
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return headlessPool
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const CHROMIUM_PATH = config.get('CHROMIUM_PATH')
|
|
59
|
-
|
|
60
|
-
async function initializeChromium() {
|
|
61
|
-
try {
|
|
62
|
-
if (!puppeteer) {
|
|
63
|
-
return
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
var launchSetting = {
|
|
67
|
-
args: ['--hide-scrollbars', '--mute-audio', '--no-sandbox', '--use-gl=egl'],
|
|
68
|
-
headless: 'shell'
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (CHROMIUM_PATH) {
|
|
72
|
-
launchSetting['executablePath'] = CHROMIUM_PATH
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const browser = await puppeteer.launch(launchSetting)
|
|
76
|
-
|
|
77
|
-
return browser
|
|
78
|
-
} catch (err) {
|
|
79
|
-
logger.error(err)
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async function initializeScenePage() {
|
|
84
|
-
/* get brand new browser for every request */
|
|
85
|
-
const browser = await initializeChromium()
|
|
86
|
-
|
|
87
|
-
if (!browser) {
|
|
88
|
-
return
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const protocol = 'http'
|
|
92
|
-
const host = 'localhost'
|
|
93
|
-
const path = '/internal-label-command-view'
|
|
94
|
-
|
|
95
|
-
const port = process.env.PORT
|
|
96
|
-
const url = `${protocol}://${host}:${port}${path}`
|
|
97
|
-
|
|
98
|
-
const page = await browser.newPage()
|
|
99
|
-
const [fontsToUse, fontStyles] = await fonts()
|
|
100
|
-
|
|
101
|
-
await page.setRequestInterception(true)
|
|
102
|
-
|
|
103
|
-
page.on('console', async msg => {
|
|
104
|
-
console.log(`[headless ${msg.type()}] ${msg.text()}`)
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
page.on('pageerror', error => {
|
|
108
|
-
console.log(`[headless pageerror] ${error.message}`)
|
|
109
|
-
console.log(error.stack)
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
page.on('error', error => {
|
|
113
|
-
console.log(`[headless fault] ${error}`)
|
|
114
|
-
console.log(error.stack)
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
page.on('requestfailed', request => {
|
|
118
|
-
console.log('Request failed:', request.url())
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
page.on('request', request => {
|
|
122
|
-
if (request.url() === url) {
|
|
123
|
-
request.continue({
|
|
124
|
-
method: 'POST',
|
|
125
|
-
headers: {
|
|
126
|
-
'Content-Type': 'application/json'
|
|
127
|
-
},
|
|
128
|
-
postData: JSON.stringify({
|
|
129
|
-
fonts: fontsToUse,
|
|
130
|
-
fontStyles
|
|
131
|
-
})
|
|
132
|
-
})
|
|
133
|
-
} else {
|
|
134
|
-
request.continue()
|
|
135
|
-
}
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
await page.goto(url, { timeout: 0, waitUntil: 'load' })
|
|
139
|
-
|
|
140
|
-
return { browser, page }
|
|
141
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { labelcommand as boardToZpl } from './label-command'
|
|
2
|
-
import { pdf as boardToPdf } from './pdf'
|
|
3
|
-
import { headlessModel } from './headless-model'
|
|
4
|
-
import { fonts } from './fonts'
|
|
5
|
-
|
|
6
|
-
export const BoardFunc = {
|
|
7
|
-
boardToZpl,
|
|
8
|
-
boardToPdf,
|
|
9
|
-
headlessModel,
|
|
10
|
-
fonts
|
|
11
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright © HatioLab Inc. All rights reserved.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { getHeadlessPool } from './headless-pool-for-label'
|
|
6
|
-
import { headlessModel } from './headless-model'
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* 라벨 출력
|
|
10
|
-
*
|
|
11
|
-
* @param {String} id 모델 ID
|
|
12
|
-
* @param {Object} data 매핑할 데이터
|
|
13
|
-
* @param {String} orientation (시계방향) N: 0, R: 90, I: 180, B: 270
|
|
14
|
-
* @param {boolean} mirror 좌우반전
|
|
15
|
-
* @param {boolean} upsideDown 상하반전
|
|
16
|
-
*/
|
|
17
|
-
export const labelcommand = async ({ id, model, data, orientation, mirror = false, upsideDown = false, context, draft = false }) => {
|
|
18
|
-
const { domain } = context.state
|
|
19
|
-
|
|
20
|
-
const browser = (await getHeadlessPool().acquire()) as any
|
|
21
|
-
if (!browser) {
|
|
22
|
-
return
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const { page } = browser
|
|
26
|
-
|
|
27
|
-
var { model } = await headlessModel({ domain, model, id }, draft)
|
|
28
|
-
|
|
29
|
-
const grf = await page.evaluate(
|
|
30
|
-
async (model, data, orientation, mirror, upsideDown) => {
|
|
31
|
-
//@ts-ignore
|
|
32
|
-
let s = createScene(model)
|
|
33
|
-
if (data) {
|
|
34
|
-
s.data = data
|
|
35
|
-
}
|
|
36
|
-
return new Promise(resolve => {
|
|
37
|
-
// @ts-ignore
|
|
38
|
-
requestAnimationFrame(() => {
|
|
39
|
-
// @ts-ignore
|
|
40
|
-
let grf = imageDataToGrf(s, model, orientation, mirror, upsideDown)
|
|
41
|
-
resolve(grf)
|
|
42
|
-
// @ts-ignore
|
|
43
|
-
sceneContainer.removeChild(s.target)
|
|
44
|
-
s.dispose()
|
|
45
|
-
})
|
|
46
|
-
})
|
|
47
|
-
},
|
|
48
|
-
model,
|
|
49
|
-
data,
|
|
50
|
-
orientation,
|
|
51
|
-
mirror,
|
|
52
|
-
upsideDown
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
getHeadlessPool().release(browser)
|
|
56
|
-
|
|
57
|
-
return `
|
|
58
|
-
^XA
|
|
59
|
-
^GFA,${grf}
|
|
60
|
-
^FS
|
|
61
|
-
^XZ`
|
|
62
|
-
}
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import { fonts } from './fonts'
|
|
2
|
-
import { getHeadlessPool } from './headless-pool-for-board'
|
|
3
|
-
import { headlessModel } from './headless-model'
|
|
4
|
-
|
|
5
|
-
const protocol = 'http'
|
|
6
|
-
const host = 'localhost'
|
|
7
|
-
const path = '/internal-board-service-view'
|
|
8
|
-
|
|
9
|
-
export const pdf = async ({
|
|
10
|
-
id = '',
|
|
11
|
-
model = null,
|
|
12
|
-
data = null,
|
|
13
|
-
width: w = 0,
|
|
14
|
-
height: h = 0,
|
|
15
|
-
options = {} as any,
|
|
16
|
-
context = {} as any
|
|
17
|
-
} = {}) => {
|
|
18
|
-
const browser = (await getHeadlessPool().acquire()) as any
|
|
19
|
-
|
|
20
|
-
if (!browser) {
|
|
21
|
-
return
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const { domain, user } = context.state
|
|
25
|
-
|
|
26
|
-
var { model, base } = await headlessModel({ domain, id, model })
|
|
27
|
-
const [fontsToUse, fontStyles] = await fonts(domain)
|
|
28
|
-
|
|
29
|
-
model.fonts = fontsToUse
|
|
30
|
-
model.fontStyles = fontStyles
|
|
31
|
-
|
|
32
|
-
let { width, height } = model
|
|
33
|
-
|
|
34
|
-
width = Number(width)
|
|
35
|
-
height = Number(height)
|
|
36
|
-
|
|
37
|
-
if (!w) {
|
|
38
|
-
w = width
|
|
39
|
-
}
|
|
40
|
-
if (!h) {
|
|
41
|
-
h = height
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
let ratio = Math.min(w / width, h / height)
|
|
45
|
-
|
|
46
|
-
width = Math.floor(width * ratio)
|
|
47
|
-
height = Math.floor(height * ratio)
|
|
48
|
-
|
|
49
|
-
const port = process.env.PORT ? `:${process.env.PORT}` : ''
|
|
50
|
-
const url = `${protocol}://${host}${port}${path}`
|
|
51
|
-
const page = await browser.newPage()
|
|
52
|
-
|
|
53
|
-
try {
|
|
54
|
-
/* @remember-me width, height should be a integer */
|
|
55
|
-
await page.setViewport({ width, height })
|
|
56
|
-
await page.setRequestInterception(true)
|
|
57
|
-
|
|
58
|
-
page.on('console', async msg => {
|
|
59
|
-
console.log(`[headless ${msg.type()}] ${msg.text()}`)
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
page.on('pageerror', error => {
|
|
63
|
-
console.log(`[headless pageerror] ${error.message}`)
|
|
64
|
-
console.log(error.stack)
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
page.on('error', error => {
|
|
68
|
-
console.log(`[headless fault] ${error}`)
|
|
69
|
-
console.log(error.stack)
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
page.on('requestfailed', request => {
|
|
73
|
-
console.log('Request failed:', request.url())
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
const token = await user?.sign() // TODO improve performance
|
|
77
|
-
|
|
78
|
-
page.on('request', request => {
|
|
79
|
-
if (request.url() === url) {
|
|
80
|
-
request.continue({
|
|
81
|
-
method: 'POST',
|
|
82
|
-
headers: {
|
|
83
|
-
'Content-Type': 'application/json',
|
|
84
|
-
'x-things-factory-domain': domain?.subdomain,
|
|
85
|
-
Authorization: 'Bearer ' + token
|
|
86
|
-
},
|
|
87
|
-
postData: JSON.stringify({
|
|
88
|
-
model,
|
|
89
|
-
base
|
|
90
|
-
})
|
|
91
|
-
})
|
|
92
|
-
} else if (request.url().startsWith(`${protocol}://${host}${port}`)) {
|
|
93
|
-
request.continue({
|
|
94
|
-
headers: {
|
|
95
|
-
...request.headers(),
|
|
96
|
-
'x-things-factory-domain': domain?.subdomain,
|
|
97
|
-
Authorization: 'Bearer ' + token
|
|
98
|
-
}
|
|
99
|
-
})
|
|
100
|
-
} else {
|
|
101
|
-
request.continue()
|
|
102
|
-
}
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
await page.goto(url)
|
|
106
|
-
|
|
107
|
-
await page.evaluate(async data => {
|
|
108
|
-
if (data) {
|
|
109
|
-
// @ts-ignore
|
|
110
|
-
s.data = data
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// data 주입 후 강제 지연시킴.
|
|
114
|
-
return new Promise(resolve => {
|
|
115
|
-
// @ts-ignore
|
|
116
|
-
requestAnimationFrame(() => resolve())
|
|
117
|
-
})
|
|
118
|
-
}, data)
|
|
119
|
-
|
|
120
|
-
const pdf = await page.pdf({
|
|
121
|
-
format: 'A4',
|
|
122
|
-
...options
|
|
123
|
-
})
|
|
124
|
-
} catch (error) {
|
|
125
|
-
console.log(error)
|
|
126
|
-
} finally {
|
|
127
|
-
page.close()
|
|
128
|
-
getHeadlessPool().release(browser)
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return pdf
|
|
132
|
-
}
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { fonts } from './fonts'
|
|
2
|
-
import { getHeadlessPool } from './headless-pool-for-board'
|
|
3
|
-
import { headlessModel } from './headless-model'
|
|
4
|
-
|
|
5
|
-
const protocol = 'http'
|
|
6
|
-
const host = 'localhost'
|
|
7
|
-
const path = '/internal-board-service-view'
|
|
8
|
-
|
|
9
|
-
export const screenshot = async ({
|
|
10
|
-
id = '',
|
|
11
|
-
model = null,
|
|
12
|
-
data = null,
|
|
13
|
-
width: w = 0,
|
|
14
|
-
height: h = 0,
|
|
15
|
-
options = { encoding: 'base64' } as any,
|
|
16
|
-
isThumbnail = false,
|
|
17
|
-
context = {} as any,
|
|
18
|
-
draft = false
|
|
19
|
-
} = {}) => {
|
|
20
|
-
const browser = (await getHeadlessPool().acquire()) as any
|
|
21
|
-
var screenshot = null
|
|
22
|
-
|
|
23
|
-
if (!browser) {
|
|
24
|
-
return
|
|
25
|
-
}
|
|
26
|
-
const { domain, user } = context.state
|
|
27
|
-
|
|
28
|
-
var { model, base } = await headlessModel({ domain, id, model }, draft)
|
|
29
|
-
const [fontsToUse, fontStyles] = await fonts(domain)
|
|
30
|
-
|
|
31
|
-
model.fonts = fontsToUse
|
|
32
|
-
model.fontStyles = fontStyles
|
|
33
|
-
|
|
34
|
-
var { width, height } = model
|
|
35
|
-
|
|
36
|
-
if (isThumbnail) {
|
|
37
|
-
var widthRatio = 400 / width,
|
|
38
|
-
heightRatio = 300 / height
|
|
39
|
-
var ratio = widthRatio < heightRatio ? widthRatio : heightRatio
|
|
40
|
-
width = width * ratio
|
|
41
|
-
height = height * ratio
|
|
42
|
-
}
|
|
43
|
-
width = Math.floor(w || Number(width))
|
|
44
|
-
height = Math.floor(h || Number(height))
|
|
45
|
-
|
|
46
|
-
const port = process.env.PORT ? `:${process.env.PORT}` : ''
|
|
47
|
-
const url = `${protocol}://${host}${port}${path}`
|
|
48
|
-
|
|
49
|
-
var page = await browser.newPage()
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
/* @remember-me width, height should be a integer */
|
|
53
|
-
await page.setViewport({ width, height })
|
|
54
|
-
await page.setRequestInterception(true)
|
|
55
|
-
await page.setDefaultTimeout(10000)
|
|
56
|
-
|
|
57
|
-
page.on('console', async msg => {
|
|
58
|
-
console.log(`[headless ${msg.type()}] ${msg.text()}`)
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
page.on('pageerror', error => {
|
|
62
|
-
console.log(`[headless pageerror] ${error.message}`)
|
|
63
|
-
console.log(error.stack)
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
page.on('error', error => {
|
|
67
|
-
console.log(`[headless fault] ${error}`)
|
|
68
|
-
console.log(error.stack)
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
page.on('requestfailed', request => {
|
|
72
|
-
console.log('Request failed:', request.url())
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
const token = await user?.sign() // TODO improve performance
|
|
76
|
-
|
|
77
|
-
page.on('request', request => {
|
|
78
|
-
if (request.url() === url) {
|
|
79
|
-
request.continue({
|
|
80
|
-
method: 'POST',
|
|
81
|
-
headers: {
|
|
82
|
-
'Content-Type': 'application/json',
|
|
83
|
-
'x-things-factory-domain': domain?.subdomain,
|
|
84
|
-
Authorization: 'Bearer ' + token
|
|
85
|
-
},
|
|
86
|
-
postData: JSON.stringify({
|
|
87
|
-
model,
|
|
88
|
-
base
|
|
89
|
-
})
|
|
90
|
-
})
|
|
91
|
-
} else if (request.url().startsWith(`${protocol}://${host}${port}`)) {
|
|
92
|
-
request.continue({
|
|
93
|
-
headers: {
|
|
94
|
-
...request.headers(),
|
|
95
|
-
'x-things-factory-domain': domain?.subdomain,
|
|
96
|
-
Authorization: 'Bearer ' + token
|
|
97
|
-
}
|
|
98
|
-
})
|
|
99
|
-
} else {
|
|
100
|
-
request.continue()
|
|
101
|
-
}
|
|
102
|
-
})
|
|
103
|
-
await page.goto(url)
|
|
104
|
-
|
|
105
|
-
await page.evaluate(async data => {
|
|
106
|
-
if (data) {
|
|
107
|
-
// @ts-ignore
|
|
108
|
-
s.data = data
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// data 주입 후 강제 지연시킴.
|
|
112
|
-
return new Promise(resolve => {
|
|
113
|
-
// @ts-ignore
|
|
114
|
-
requestAnimationFrame(() => resolve())
|
|
115
|
-
})
|
|
116
|
-
}, data)
|
|
117
|
-
|
|
118
|
-
screenshot = await page.screenshot(options)
|
|
119
|
-
} catch (error) {
|
|
120
|
-
console.log(error)
|
|
121
|
-
} finally {
|
|
122
|
-
page.close()
|
|
123
|
-
getHeadlessPool().release(browser)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return screenshot
|
|
127
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { screenshot } from './screenshot'
|
|
2
|
-
|
|
3
|
-
export const thumbnail = async ({
|
|
4
|
-
id = '',
|
|
5
|
-
model = null,
|
|
6
|
-
data = null,
|
|
7
|
-
options = { encoding: 'base64', type: 'png' } as any,
|
|
8
|
-
context = {}
|
|
9
|
-
} = {}) => {
|
|
10
|
-
return await screenshot({
|
|
11
|
-
id,
|
|
12
|
-
model,
|
|
13
|
-
data,
|
|
14
|
-
options,
|
|
15
|
-
isThumbnail: true,
|
|
16
|
-
context
|
|
17
|
-
})
|
|
18
|
-
}
|
package/server/errors/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './license-error'
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import * as ERROR_CODES from '../constants/error-code'
|
|
2
|
-
|
|
3
|
-
type LicenseErrorArgument = {
|
|
4
|
-
errorCode: string
|
|
5
|
-
detail?: Object
|
|
6
|
-
}
|
|
7
|
-
export class LicenseError extends Error {
|
|
8
|
-
static get ERROR_CODES(): any {
|
|
9
|
-
return {
|
|
10
|
-
...ERROR_CODES
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
errorCode: any
|
|
14
|
-
detail: Object
|
|
15
|
-
constructor({ errorCode, detail }: LicenseErrorArgument) {
|
|
16
|
-
super(errorCode)
|
|
17
|
-
this.name = 'license-error'
|
|
18
|
-
this.errorCode = errorCode
|
|
19
|
-
this.detail = detail
|
|
20
|
-
}
|
|
21
|
-
}
|
package/server/index.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
export * from './service'
|
|
2
|
-
export * from './migrations'
|
|
3
|
-
export * from './controllers'
|
|
4
|
-
|
|
5
|
-
import './routes'
|
|
6
|
-
|
|
7
|
-
import { getPermission } from '@things-factory/operato-license-checker'
|
|
8
|
-
|
|
9
|
-
export function initMiddlewares(app) {
|
|
10
|
-
const licensedPermissions = (getPermission('Permissions For Board Usage') || 'Modeller, Viewer')
|
|
11
|
-
.split(',')
|
|
12
|
-
.map(p => p.trim())
|
|
13
|
-
|
|
14
|
-
const prohibited = !licensedPermissions.includes('Modeller') && [
|
|
15
|
-
{
|
|
16
|
-
privilege: 'mutation',
|
|
17
|
-
category: 'board'
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
privilege: 'mutation',
|
|
21
|
-
category: 'board-template'
|
|
22
|
-
}
|
|
23
|
-
]
|
|
24
|
-
|
|
25
|
-
/*
|
|
26
|
-
* board-permission을 prohibitedPrivileges에 반영한다.
|
|
27
|
-
*/
|
|
28
|
-
app.use(async (context, next) => {
|
|
29
|
-
if (prohibited) {
|
|
30
|
-
const { prohibitedPrivileges } = context.state
|
|
31
|
-
|
|
32
|
-
context.state.prohibitedPrivileges = [...(prohibitedPrivileges || []), ...prohibited]
|
|
33
|
-
}
|
|
34
|
-
await next()
|
|
35
|
-
})
|
|
36
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { MigrationInterface, QueryRunner } from 'typeorm'
|
|
2
|
-
|
|
3
|
-
import { logger } from '@things-factory/env'
|
|
4
|
-
import { Domain, getRepository } from '@things-factory/shell'
|
|
5
|
-
|
|
6
|
-
import { Group } from '../service/group/group'
|
|
7
|
-
|
|
8
|
-
const SEED_GROUP = [
|
|
9
|
-
{
|
|
10
|
-
name: 'DASHBOARD',
|
|
11
|
-
description: 'Dashboard'
|
|
12
|
-
}
|
|
13
|
-
]
|
|
14
|
-
|
|
15
|
-
export class SeedGroup1556862253000 implements MigrationInterface {
|
|
16
|
-
public async up(queryRunner: QueryRunner): Promise<any> {
|
|
17
|
-
const repository = getRepository(Group)
|
|
18
|
-
const domainRepository = getRepository(Domain)
|
|
19
|
-
const domain = await domainRepository.findOneBy({ name: 'SYSTEM' })
|
|
20
|
-
|
|
21
|
-
try {
|
|
22
|
-
return await Promise.all(
|
|
23
|
-
SEED_GROUP.map(async group => {
|
|
24
|
-
await repository.save({
|
|
25
|
-
...group,
|
|
26
|
-
domain
|
|
27
|
-
})
|
|
28
|
-
})
|
|
29
|
-
)
|
|
30
|
-
} catch (e) {
|
|
31
|
-
logger.error(e)
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
public async down(queryRunner: QueryRunner): Promise<any> {
|
|
36
|
-
const repository = getRepository(Group)
|
|
37
|
-
const domainRepository = getRepository(Domain)
|
|
38
|
-
const domain = await domainRepository.findOneBy({ name: 'SYSTEM' })
|
|
39
|
-
|
|
40
|
-
SEED_GROUP.reverse().forEach(async group => {
|
|
41
|
-
let record = await repository.findOne({
|
|
42
|
-
where: {
|
|
43
|
-
domain: { id: domain.id },
|
|
44
|
-
name: group.name
|
|
45
|
-
}
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
await repository.remove(record)
|
|
49
|
-
})
|
|
50
|
-
}
|
|
51
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
const glob = require('glob')
|
|
2
|
-
const path = require('path')
|
|
3
|
-
|
|
4
|
-
export var migrations = []
|
|
5
|
-
|
|
6
|
-
glob.sync(path.resolve(__dirname, '.', '**', '*.js')).forEach(function(file) {
|
|
7
|
-
if (file.indexOf('index.js') !== -1) return
|
|
8
|
-
migrations = migrations.concat(Object.values(require(path.resolve(file))) || [])
|
|
9
|
-
})
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import Router from 'koa-router'
|
|
2
|
-
|
|
3
|
-
export const internalBoardViewRouter = new Router()
|
|
4
|
-
|
|
5
|
-
function parseQuery(query) {
|
|
6
|
-
for (const key in query) {
|
|
7
|
-
if (query.hasOwnProperty(key)) {
|
|
8
|
-
try {
|
|
9
|
-
query[key] = JSON.parse(query[key])
|
|
10
|
-
} catch (error) {
|
|
11
|
-
// do nothing
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
return query
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// should be used only for building label command by headless chrome internally
|
|
20
|
-
internalBoardViewRouter.post('/internal-label-command-view', async (context, next) => {
|
|
21
|
-
let model = context.request.body
|
|
22
|
-
let data = context.query
|
|
23
|
-
|
|
24
|
-
await context.render('internal-label-command-view', { model, data })
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
// should be used only for building board service by headless chrome internally
|
|
28
|
-
internalBoardViewRouter.post('/internal-board-service-view', async (context, next) => {
|
|
29
|
-
let { id, model, base } = context.request.body
|
|
30
|
-
const data = parseQuery({ ...context.query })
|
|
31
|
-
|
|
32
|
-
await context.render('internal-board-service-view', { id, model, data, base })
|
|
33
|
-
})
|