@live-change/print-service 0.8.113 → 0.8.114
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/authentication.js +25 -0
- package/browser.js +5 -5
- package/config.js +2 -1
- package/index.js +6 -1
- package/package.json +5 -5
- package/printPdf.js +82 -0
- package/screenshot.js +138 -0
- package/print.js +0 -88
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import config from './config.js'
|
|
2
|
+
import definition from './definition.js'
|
|
3
|
+
|
|
4
|
+
import { ObservableValue } from '@live-change/dao'
|
|
5
|
+
|
|
6
|
+
const authenticationKey = new ObservableValue(
|
|
7
|
+
config.printAuthenticationKey
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
definition.authenticator({
|
|
11
|
+
async prepareCredentials(credentials) {
|
|
12
|
+
//console.log("PRINT AUTHENTICATOR", credentials, authenticationKey.getValue())
|
|
13
|
+
if(credentials.sessionKey === authenticationKey.getValue()) {
|
|
14
|
+
credentials.roles.push('admin')
|
|
15
|
+
credentials.internal = true
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const baseUrl = `http://${config.ssrHost}`+`:${config.ssrPort}`
|
|
21
|
+
|
|
22
|
+
export async function getAuthenticatedUrl(path, data) {
|
|
23
|
+
const encodedData = data && encodeURIComponent(JSON.stringify(data))
|
|
24
|
+
return baseUrl + path + (data ? '/' + encodedData : '') +`?sessionKey=${await authenticationKey.getValue()}`
|
|
25
|
+
}
|
package/browser.js
CHANGED
|
@@ -4,7 +4,7 @@ const app = App.app()
|
|
|
4
4
|
import definition from './definition.js'
|
|
5
5
|
import config from './config.js'
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { chromium } from 'playwright'
|
|
8
8
|
|
|
9
9
|
import PQueue from 'p-queue'
|
|
10
10
|
import got from "got"
|
|
@@ -13,20 +13,20 @@ const browserQueue = new PQueue({ concurrency: config.concurrency })
|
|
|
13
13
|
|
|
14
14
|
async function newBrowser() {
|
|
15
15
|
if(config.browserWebSocketDebuggerUrl) {
|
|
16
|
-
const browser = await
|
|
16
|
+
const browser = await chromium.connect({ wsEndpoint: config.browserWebSocketDebuggerUrl })
|
|
17
17
|
return browser
|
|
18
18
|
} else if(config.browserUrl) {
|
|
19
19
|
const browserInfo = await got.post(config.browserUrl + '/json/version').json()
|
|
20
|
-
const browser = await
|
|
20
|
+
const browser = await chromium.connect({ wsEndpoint: browserInfo.webSocketDebuggerUrl })
|
|
21
21
|
} else {
|
|
22
|
-
const browser = await
|
|
22
|
+
const browser = await chromium.launch()
|
|
23
23
|
return browser
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
export async function runWithBrowser(func) {
|
|
28
28
|
return await browserQueue.add(async () => {
|
|
29
|
-
const browser = newBrowser()
|
|
29
|
+
const browser = await newBrowser()
|
|
30
30
|
const result = await func(browser)
|
|
31
31
|
await browser.close()
|
|
32
32
|
return result
|
package/config.js
CHANGED
package/index.js
CHANGED
|
@@ -3,6 +3,11 @@ const app = App.app()
|
|
|
3
3
|
|
|
4
4
|
import definition from './definition.js'
|
|
5
5
|
|
|
6
|
-
import "./
|
|
6
|
+
import "./authentication.js"
|
|
7
|
+
import { printToPdfFileTask } from "./printPdf.js"
|
|
8
|
+
import { screenshotToFileTask } from "./screenshot.js"
|
|
9
|
+
|
|
10
|
+
export { printToPdfFileTask, screenshotToFileTask }
|
|
11
|
+
|
|
7
12
|
|
|
8
13
|
export default definition
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@live-change/print-service",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.114",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -21,13 +21,13 @@
|
|
|
21
21
|
"url": "https://www.viamage.com/"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@live-change/framework": "^0.8.
|
|
25
|
-
"@live-change/relations-plugin": "^0.8.
|
|
26
|
-
"@live-change/user-service": "^0.8.
|
|
24
|
+
"@live-change/framework": "^0.8.114",
|
|
25
|
+
"@live-change/relations-plugin": "^0.8.114",
|
|
26
|
+
"@live-change/user-service": "^0.8.114",
|
|
27
27
|
"got": "^11.8.6",
|
|
28
28
|
"p-queue": "^8.0.1",
|
|
29
29
|
"playwright": "^1.41.2"
|
|
30
30
|
},
|
|
31
|
-
"gitHead": "
|
|
31
|
+
"gitHead": "1a5a437aae382d766c2806a11f805370ee8cc40a",
|
|
32
32
|
"type": "module"
|
|
33
33
|
}
|
package/printPdf.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import App from '@live-change/framework'
|
|
2
|
+
const app = App.app()
|
|
3
|
+
|
|
4
|
+
import definition from './definition.js'
|
|
5
|
+
import config from './config.js'
|
|
6
|
+
|
|
7
|
+
import { task } from '@live-change/task-service'
|
|
8
|
+
|
|
9
|
+
import { runWithBrowser } from './browser.js'
|
|
10
|
+
|
|
11
|
+
import { getAuthenticatedUrl } from './authentication.js'
|
|
12
|
+
|
|
13
|
+
async function sleep(time) {
|
|
14
|
+
return new Promise(resolve => setTimeout(resolve, time))
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const printToPdfFileTask = task({
|
|
18
|
+
name: "printToPdfFile",
|
|
19
|
+
properties: {
|
|
20
|
+
path: {
|
|
21
|
+
type: String
|
|
22
|
+
},
|
|
23
|
+
data: {
|
|
24
|
+
type: Object
|
|
25
|
+
},
|
|
26
|
+
timeout: {
|
|
27
|
+
type: Number
|
|
28
|
+
},
|
|
29
|
+
media: {
|
|
30
|
+
type: Object
|
|
31
|
+
},
|
|
32
|
+
options: {
|
|
33
|
+
type: Object
|
|
34
|
+
},
|
|
35
|
+
waitForSelector: {
|
|
36
|
+
type: String
|
|
37
|
+
},
|
|
38
|
+
outputPath: {
|
|
39
|
+
type: String
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
async execute({ path, data, timeout, media, options, waitForSelector, outputPath }, { task, trigger, triggerService }, emit) {
|
|
43
|
+
const all = 10
|
|
44
|
+
let at = 0
|
|
45
|
+
const url = await getAuthenticatedUrl(path, data)
|
|
46
|
+
let pdf
|
|
47
|
+
task.progress(at++, all, 'gettingBrowserReady')
|
|
48
|
+
await runWithBrowser(async browser => {
|
|
49
|
+
task.progress(at++, all, 'creatingPage')
|
|
50
|
+
const page = await browser.newPage()
|
|
51
|
+
task.progress(at++, all, 'enteringPage')
|
|
52
|
+
await page.goto(url)
|
|
53
|
+
task.progress(at++, all, 'waitingForLoading')
|
|
54
|
+
while(true) {
|
|
55
|
+
const loadingTasksCount = await page.evaluate(() => api.globals.$allLoadingTasks?.length)
|
|
56
|
+
if(loadingTasksCount === 0) break
|
|
57
|
+
await sleep(100)
|
|
58
|
+
}
|
|
59
|
+
if(waitForSelector) {
|
|
60
|
+
task.progress(at++, all, 'waitingForSelector')
|
|
61
|
+
await page.waitForSelector(waitForSelector)
|
|
62
|
+
} else {
|
|
63
|
+
task.progress(at++, all, 'waitingForNetworkIdle')
|
|
64
|
+
await page.waitForLoadState('networkidle')
|
|
65
|
+
}
|
|
66
|
+
task.progress(at++, all, 'waitingForRendering')
|
|
67
|
+
await sleep(100) // wait for some time to give browser time to render
|
|
68
|
+
task.progress(at++, all, 'printing')
|
|
69
|
+
page.emulateMedia(media ?? { media: 'print' })
|
|
70
|
+
pdf = await page.pdf( options ?? { format: 'A4', printBackground: true })
|
|
71
|
+
task.progress(at++, all, 'closingPage')
|
|
72
|
+
})
|
|
73
|
+
task.progress(at++, all, 'writingPdfToFile')
|
|
74
|
+
await fs.promises.writeFile(outputPath, pdf)
|
|
75
|
+
task.progress(at++, all, 'done')
|
|
76
|
+
return outputPath
|
|
77
|
+
}
|
|
78
|
+
}, definition)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
package/screenshot.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import App from '@live-change/framework'
|
|
2
|
+
const app = App.app()
|
|
3
|
+
|
|
4
|
+
import definition from './definition.js'
|
|
5
|
+
import config from './config.js'
|
|
6
|
+
|
|
7
|
+
import fs from "fs/promises"
|
|
8
|
+
|
|
9
|
+
import { task } from '@live-change/task-service'
|
|
10
|
+
|
|
11
|
+
import { runWithBrowser } from './browser.js'
|
|
12
|
+
|
|
13
|
+
import { getAuthenticatedUrl } from './authentication.js'
|
|
14
|
+
|
|
15
|
+
async function sleep(time) {
|
|
16
|
+
return new Promise(resolve => setTimeout(resolve, time))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const screenshotToFileTask = task({
|
|
20
|
+
name: "screenshotToFile",
|
|
21
|
+
properties: {
|
|
22
|
+
path: {
|
|
23
|
+
type: String
|
|
24
|
+
},
|
|
25
|
+
data: {
|
|
26
|
+
type: Object
|
|
27
|
+
},
|
|
28
|
+
timeout: {
|
|
29
|
+
type: Number
|
|
30
|
+
},
|
|
31
|
+
viewport: {
|
|
32
|
+
type: Object,
|
|
33
|
+
properties: {
|
|
34
|
+
width: {
|
|
35
|
+
type: Number
|
|
36
|
+
},
|
|
37
|
+
height: {
|
|
38
|
+
type: Number
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
media: {
|
|
43
|
+
type: Object
|
|
44
|
+
},
|
|
45
|
+
options: {
|
|
46
|
+
type: Object
|
|
47
|
+
},
|
|
48
|
+
waitForSelector: {
|
|
49
|
+
type: String
|
|
50
|
+
},
|
|
51
|
+
clipSelector: {
|
|
52
|
+
type: String
|
|
53
|
+
},
|
|
54
|
+
outputPath: {
|
|
55
|
+
type: String
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
async execute({ path, data, timeout, media, options, waitForSelector, viewport, outputPath, clipSelector },
|
|
59
|
+
{ task, trigger, triggerService }, emit) {
|
|
60
|
+
const all = 10
|
|
61
|
+
let at = 0
|
|
62
|
+
const url = await getAuthenticatedUrl(path, data)
|
|
63
|
+
let imageData
|
|
64
|
+
let size
|
|
65
|
+
task.progress(at++, all, 'gettingBrowserReady')
|
|
66
|
+
await runWithBrowser(async browser => {
|
|
67
|
+
console.log("BROWSER", browser)
|
|
68
|
+
task.progress(at++, all, 'creatingPage')
|
|
69
|
+
const page = await browser.newPage()
|
|
70
|
+
if(viewport) page.setViewport(viewport)
|
|
71
|
+
task.progress(at++, all, 'enteringPage')
|
|
72
|
+
await page.goto(url)
|
|
73
|
+
task.progress(at++, all, 'waitingForLoading')
|
|
74
|
+
while(true) {
|
|
75
|
+
const loadingTasksCount = await page.evaluate(() => api.globals.$allLoadingTasks?.length)
|
|
76
|
+
if(loadingTasksCount === 0) break
|
|
77
|
+
await sleep(100)
|
|
78
|
+
}
|
|
79
|
+
if(waitForSelector) {
|
|
80
|
+
task.progress(at++, all, 'waitingForSelector')
|
|
81
|
+
console.log("WAITING FOR SELECTOR", waitForSelector, "AT URL", url)
|
|
82
|
+
const locator = page.locator(waitForSelector)
|
|
83
|
+
await locator.waitFor({ state: 'attached', timeout })
|
|
84
|
+
} else {
|
|
85
|
+
task.progress(at++, all, 'waitingForNetworkIdle')
|
|
86
|
+
await page.waitForLoadState('networkidle')
|
|
87
|
+
}
|
|
88
|
+
task.progress(at++, all, 'waitingForRendering')
|
|
89
|
+
await sleep(100) // wait for some time to give browser time to render
|
|
90
|
+
task.progress(at++, all, 'printing')
|
|
91
|
+
if(media) page.emulateMedia(media)
|
|
92
|
+
const screenshotOptions = {
|
|
93
|
+
type: 'png',
|
|
94
|
+
...options
|
|
95
|
+
}
|
|
96
|
+
if(clipSelector) {
|
|
97
|
+
const clip = await page.evaluate(selector => {
|
|
98
|
+
const element = document.querySelector(selector)
|
|
99
|
+
if(!element) return null
|
|
100
|
+
const { x, y, width, height } = element.getBoundingClientRect()
|
|
101
|
+
return { x, y, width, height }
|
|
102
|
+
}, clipSelector)
|
|
103
|
+
if(clip) {
|
|
104
|
+
screenshotOptions.clip = clip
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
size = screenshotOptions.clip
|
|
108
|
+
if(!size) {
|
|
109
|
+
if(screenshotOptions.fullPage) {
|
|
110
|
+
const bodyHandle = await page.$('body')
|
|
111
|
+
const { width, height } = await bodyHandle.boundingBox()
|
|
112
|
+
await bodyHandle.dispose()
|
|
113
|
+
size = { width, height }
|
|
114
|
+
} else {
|
|
115
|
+
size = await page.evaluate(() => {
|
|
116
|
+
return {
|
|
117
|
+
width: document.documentElement.clientWidth,
|
|
118
|
+
height: document.documentElement.clientHeight
|
|
119
|
+
}
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
imageData = await page.screenshot(screenshotOptions)
|
|
124
|
+
task.progress(at++, all, 'closingPage')
|
|
125
|
+
})
|
|
126
|
+
task.progress(at++, all, 'writingScreenshotToFile')
|
|
127
|
+
await fs.writeFile(outputPath, imageData)
|
|
128
|
+
task.progress(at++, all, 'done')
|
|
129
|
+
return {
|
|
130
|
+
path: outputPath,
|
|
131
|
+
size
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}, definition)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
package/print.js
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import App from '@live-change/framework'
|
|
2
|
-
const app = App.app()
|
|
3
|
-
|
|
4
|
-
import definition from './definition.js'
|
|
5
|
-
import config from './config.js'
|
|
6
|
-
|
|
7
|
-
import { task } from '@live-change/task-service'
|
|
8
|
-
|
|
9
|
-
import { runWithBrowser } from './browser.js'
|
|
10
|
-
|
|
11
|
-
const authenticationKey = new ObservableValue(
|
|
12
|
-
config.printAuthenticationKey
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
definition.authenticator({
|
|
16
|
-
async prepareCredentials(credentials) {
|
|
17
|
-
//console.log("PRINT AUTHENTICATOR", credentials, authenticationKey.getValue())
|
|
18
|
-
if(credentials.sessionKey === authenticationKey.getValue()) {
|
|
19
|
-
credentials.roles.push('admin')
|
|
20
|
-
credentials.internal = true
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
const baseUrl = `http://${config.ssrHost}`+`:${config.ssrPort}`
|
|
26
|
-
|
|
27
|
-
export async function getPrintUrl(path, data) {
|
|
28
|
-
const encodedData = encodeURIComponent(JSON.stringify(data))
|
|
29
|
-
return baseUrl + path+'/' + encodedData +`?sessionKey=${await authenticationKey.getValue()}`
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async function sleep(time) {
|
|
33
|
-
return new Promise(resolve => setTimeout(resolve, time))
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const printToPdfFile = task({
|
|
37
|
-
name: "printToPdfFile",
|
|
38
|
-
properties: {
|
|
39
|
-
path: {
|
|
40
|
-
type: String
|
|
41
|
-
},
|
|
42
|
-
data: {
|
|
43
|
-
type: Object
|
|
44
|
-
},
|
|
45
|
-
timeout: {
|
|
46
|
-
type: Number
|
|
47
|
-
},
|
|
48
|
-
media: {
|
|
49
|
-
type: Object
|
|
50
|
-
},
|
|
51
|
-
options: {
|
|
52
|
-
type: Object
|
|
53
|
-
},
|
|
54
|
-
outputPath: {
|
|
55
|
-
type: String
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
async execute({ path, data, timeout, media, options, outputPath }, { task, trigger, triggerService }, emit) {
|
|
59
|
-
const all = 8
|
|
60
|
-
const url = await getPrintUrl(path, data)
|
|
61
|
-
task.progress(0, all, 'gettingBrowserReady')
|
|
62
|
-
await runWithBrowser(async browser => {
|
|
63
|
-
task.progress(1, all, 'creatingPage')
|
|
64
|
-
const page = await browser.newPage()
|
|
65
|
-
task.progress(2, all, 'enteringPage')
|
|
66
|
-
await page.goto(url)
|
|
67
|
-
task.progress(3, all, 'waitingForLoading')
|
|
68
|
-
while(true) {
|
|
69
|
-
const loadingTasksCount = await page.evaluate(() => api.globals.$allLoadingTasks?.length)
|
|
70
|
-
if(loadingTasksCount === 0) break
|
|
71
|
-
await sleep(100)
|
|
72
|
-
}
|
|
73
|
-
task.progress(4, all, 'waitingForNetworkIdle')
|
|
74
|
-
await page.waitForLoadState('networkidle')
|
|
75
|
-
task.progress(5, all, 'waitingForRendering')
|
|
76
|
-
await sleep(100) // wait for some time to give browser time to render
|
|
77
|
-
task.progress(6, all, 'printing')
|
|
78
|
-
page.emulateMedia(media ?? { media: 'print' })
|
|
79
|
-
const pdf = await page.pdf( options ?? { format: 'A4', printBackground: true })
|
|
80
|
-
task.progress(7, all, 'closingPage')
|
|
81
|
-
})
|
|
82
|
-
task.progress(9, all, 'writingPdfToFile')
|
|
83
|
-
await fs.promises.writeFile(outputPath, pdf)
|
|
84
|
-
task.progress(10, all, 'done')
|
|
85
|
-
return outputPath
|
|
86
|
-
}
|
|
87
|
-
})
|
|
88
|
-
|