@jsreport/jsreport-core 3.4.2 → 3.6.1
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/README.md +18 -0
- package/lib/main/blobStorage/blobStorage.js +8 -0
- package/lib/main/logger.js +3 -0
- package/lib/main/optionsLoad.js +10 -2
- package/lib/main/optionsSchema.js +21 -3
- package/lib/main/profiler.js +166 -75
- package/lib/main/reporter.js +113 -78
- package/lib/main/schemaValidator.js +30 -0
- package/lib/main/settings.js +1 -2
- package/lib/main/store/collection.js +10 -8
- package/lib/main/store/documentStore.js +19 -0
- package/lib/main/store/setupValidateId.js +7 -1
- package/lib/main/store/setupValidateShortid.js +4 -0
- package/lib/shared/normalizeMetaFromLogs.js +1 -1
- package/lib/shared/reporter.js +16 -0
- package/lib/worker/render/executeEngine.js +108 -27
- package/lib/worker/render/moduleHelper.js +4 -4
- package/lib/worker/render/profiler.js +20 -13
- package/lib/worker/render/render.js +0 -4
- package/lib/worker/reporter.js +6 -4
- package/lib/worker/sandbox/{safeSandbox.js → createSandbox.js} +90 -35
- package/lib/worker/sandbox/runInSandbox.js +38 -13
- package/package.json +9 -9
- package/lib/main/monitoring.js +0 -92
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
const LRU = require('lru-cache')
|
|
2
2
|
const stackTrace = require('stack-trace')
|
|
3
3
|
const { customAlphabet } = require('nanoid')
|
|
4
|
-
const
|
|
4
|
+
const createSandbox = require('./createSandbox')
|
|
5
5
|
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz', 10)
|
|
6
6
|
|
|
7
7
|
module.exports = (reporter) => {
|
|
8
|
-
|
|
8
|
+
const functionsCache = LRU(reporter.options.sandbox.cache)
|
|
9
|
+
|
|
10
|
+
return async ({
|
|
9
11
|
manager = {},
|
|
10
12
|
context,
|
|
11
13
|
userCode,
|
|
14
|
+
initFn,
|
|
12
15
|
executionFn,
|
|
13
16
|
currentPath,
|
|
14
17
|
onRequire,
|
|
@@ -19,7 +22,8 @@ module.exports = (reporter) => {
|
|
|
19
22
|
|
|
20
23
|
// we use dynamic name because of the potential nested vm2 execution in the jsreportProxy.assets.require
|
|
21
24
|
// it may turn out it is a bad approach in assets so we gonna delete it here
|
|
22
|
-
const executionFnName = nanoid()
|
|
25
|
+
const executionFnName = `${nanoid()}_executionFn`
|
|
26
|
+
|
|
23
27
|
context[executionFnName] = executionFn
|
|
24
28
|
context.__appDirectory = reporter.options.appDirectory
|
|
25
29
|
context.__rootDirectory = reporter.options.rootDirectory
|
|
@@ -28,13 +32,14 @@ module.exports = (reporter) => {
|
|
|
28
32
|
context.__topLevelFunctions = {}
|
|
29
33
|
context.__handleError = (err) => handleError(reporter, err)
|
|
30
34
|
|
|
31
|
-
const { sourceFilesInfo, run, restore, sandbox,
|
|
35
|
+
const { sourceFilesInfo, run, compileScript, restore, sandbox, sandboxRequire } = createSandbox(context, {
|
|
32
36
|
onLog: (log) => {
|
|
33
37
|
reporter.logger[log.level](log.message, { ...req, timestamp: log.timestamp })
|
|
34
38
|
},
|
|
35
39
|
formatError: (error, moduleName) => {
|
|
36
|
-
error.message += ` To be able to require custom modules you need to add to configuration { "
|
|
40
|
+
error.message += ` To be able to require custom modules you need to add to configuration { "trustUserCode": true } or enable just specific module using { sandbox: { allowedModules": ["${moduleName}"] }`
|
|
37
41
|
},
|
|
42
|
+
safeExecution: reporter.options.trustUserCode === false,
|
|
38
43
|
modulesCache: reporter.requestModulesCache.get(req.context.rootId),
|
|
39
44
|
globalModules: reporter.options.sandbox.nativeModules || [],
|
|
40
45
|
allowedModules: reporter.options.sandbox.allowedModules,
|
|
@@ -61,7 +66,17 @@ module.exports = (reporter) => {
|
|
|
61
66
|
}
|
|
62
67
|
})
|
|
63
68
|
|
|
64
|
-
|
|
69
|
+
const _getTopLevelFunctions = (code) => {
|
|
70
|
+
return getTopLevelFunctions(functionsCache, code)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
jsreportProxy = reporter.createProxy({
|
|
74
|
+
req,
|
|
75
|
+
runInSandbox: run,
|
|
76
|
+
context: sandbox,
|
|
77
|
+
getTopLevelFunctions: _getTopLevelFunctions,
|
|
78
|
+
sandboxRequire
|
|
79
|
+
})
|
|
65
80
|
|
|
66
81
|
jsreportProxy.currentPath = async () => {
|
|
67
82
|
// we get the current path by throwing an error, which give us a stack trace
|
|
@@ -114,9 +129,20 @@ module.exports = (reporter) => {
|
|
|
114
129
|
// be passed in options
|
|
115
130
|
manager.restore = restore
|
|
116
131
|
|
|
117
|
-
|
|
132
|
+
if (typeof initFn === 'function') {
|
|
133
|
+
const initScriptInfo = await initFn(_getTopLevelFunctions, compileScript)
|
|
134
|
+
|
|
135
|
+
if (initScriptInfo) {
|
|
136
|
+
await run(initScriptInfo.script, {
|
|
137
|
+
filename: initScriptInfo.filename || 'sandbox-init.js',
|
|
138
|
+
source: initScriptInfo.source
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const functionNames = getTopLevelFunctions(functionsCache, userCode)
|
|
118
144
|
const functionsCode = `return {${functionNames.map(h => `"${h}": ${h}`).join(',')}}`
|
|
119
|
-
const executionCode = `;(async () => { ${userCode}
|
|
145
|
+
const executionCode = `;(async () => { ${userCode} \n\n;${functionsCode} })()
|
|
120
146
|
.then((topLevelFunctions) => {
|
|
121
147
|
const mergedTopLevelFunctions = { ...topLevelFunctions, ...__topLevelFunctions }
|
|
122
148
|
|
|
@@ -180,12 +206,11 @@ function handleError (reporter, errValue) {
|
|
|
180
206
|
})
|
|
181
207
|
}
|
|
182
208
|
|
|
183
|
-
|
|
184
|
-
function getTopLevelFunctions (code) {
|
|
209
|
+
function getTopLevelFunctions (cache, code) {
|
|
185
210
|
const key = `functions:${code}`
|
|
186
211
|
|
|
187
|
-
if (
|
|
188
|
-
return
|
|
212
|
+
if (cache.has(key)) {
|
|
213
|
+
return cache.get(key)
|
|
189
214
|
}
|
|
190
215
|
|
|
191
216
|
// lazy load to speed up boot
|
|
@@ -223,6 +248,6 @@ function getTopLevelFunctions (code) {
|
|
|
223
248
|
return []
|
|
224
249
|
}
|
|
225
250
|
|
|
226
|
-
|
|
251
|
+
cache.set(key, names)
|
|
227
252
|
return names
|
|
228
253
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsreport/jsreport-core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.1",
|
|
4
4
|
"description": "javascript based business reporting",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"report",
|
|
@@ -32,11 +32,11 @@
|
|
|
32
32
|
"@babel/code-frame": "7.12.13",
|
|
33
33
|
"@babel/parser": "7.14.4",
|
|
34
34
|
"@babel/traverse": "7.12.9",
|
|
35
|
-
"@jsreport/advanced-workers": "1.2.
|
|
35
|
+
"@jsreport/advanced-workers": "1.2.3",
|
|
36
36
|
"@jsreport/mingo": "2.4.1",
|
|
37
37
|
"ajv": "6.12.6",
|
|
38
|
-
"app-root-path": "
|
|
39
|
-
"
|
|
38
|
+
"app-root-path": "3.0.0",
|
|
39
|
+
"bytes": "3.1.2",
|
|
40
40
|
"camelcase": "5.0.0",
|
|
41
41
|
"debug": "4.3.2",
|
|
42
42
|
"decamelize": "2.0.0",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"enhanced-resolve": "5.8.3",
|
|
47
47
|
"has-own-deep": "1.1.0",
|
|
48
48
|
"isbinaryfile": "4.0.0",
|
|
49
|
-
"listener-collection": "
|
|
49
|
+
"listener-collection": "2.0.0",
|
|
50
50
|
"lodash.get": "4.4.2",
|
|
51
51
|
"lodash.groupby": "4.6.0",
|
|
52
52
|
"lodash.omit": "4.5.0",
|
|
@@ -54,21 +54,21 @@
|
|
|
54
54
|
"lru-cache": "4.1.1",
|
|
55
55
|
"ms": "2.1.3",
|
|
56
56
|
"nanoid": "3.2.0",
|
|
57
|
-
"nconf": "0.
|
|
57
|
+
"nconf": "0.12.0",
|
|
58
58
|
"node.extend.without.arrays": "1.1.6",
|
|
59
|
-
"
|
|
59
|
+
"@jsreport/reap": "0.1.0",
|
|
60
60
|
"semver": "7.3.5",
|
|
61
61
|
"serializator": "1.0.2",
|
|
62
62
|
"stack-trace": "0.0.10",
|
|
63
63
|
"triple-beam": "1.3.0",
|
|
64
64
|
"unset-value": "1.0.0",
|
|
65
65
|
"uuid": "8.3.2",
|
|
66
|
-
"vm2": "3.9.
|
|
66
|
+
"vm2": "3.9.9",
|
|
67
67
|
"winston": "3.3.3",
|
|
68
68
|
"winston-transport": "4.4.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
-
"mocha": "
|
|
71
|
+
"mocha": "9.2.2",
|
|
72
72
|
"should": "13.2.3",
|
|
73
73
|
"standard": "16.0.4",
|
|
74
74
|
"std-mocks": "1.0.1",
|
package/lib/main/monitoring.js
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
const os = require('os')
|
|
2
|
-
|
|
3
|
-
function cpu () {
|
|
4
|
-
// Create function to get CPU information
|
|
5
|
-
function cpuAverage () {
|
|
6
|
-
// Initialise sum of idle and time of cores and fetch CPU info
|
|
7
|
-
let totalIdle = 0; let totalTick = 0
|
|
8
|
-
const cpus = os.cpus()
|
|
9
|
-
|
|
10
|
-
// Loop through CPU cores
|
|
11
|
-
for (let i = 0, len = cpus.length; i < len; i++) {
|
|
12
|
-
// Select CPU core
|
|
13
|
-
const cpu = cpus[i]
|
|
14
|
-
|
|
15
|
-
// Total up the time in the cores tick
|
|
16
|
-
for (const type in cpu.times) {
|
|
17
|
-
totalTick += cpu.times[type]
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Total up the idle time of the core
|
|
21
|
-
totalIdle += cpu.times.idle
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Return the average Idle and Tick times
|
|
25
|
-
return { idle: totalIdle / cpus.length, total: totalTick / cpus.length }
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Grab first CPU Measure
|
|
29
|
-
const startMeasure = cpuAverage()
|
|
30
|
-
|
|
31
|
-
return new Promise((resolve) => {
|
|
32
|
-
// Set delay for second Measure
|
|
33
|
-
setTimeout(function () {
|
|
34
|
-
// Grab second Measure
|
|
35
|
-
const endMeasure = cpuAverage()
|
|
36
|
-
|
|
37
|
-
// Calculate the difference in idle and total time between the measures
|
|
38
|
-
const idleDifference = endMeasure.idle - startMeasure.idle
|
|
39
|
-
const totalDifference = endMeasure.total - startMeasure.total
|
|
40
|
-
|
|
41
|
-
// Calculate the average percentage CPU usage
|
|
42
|
-
const percentageCPU = 100 - ~~(100 * idleDifference / totalDifference)
|
|
43
|
-
|
|
44
|
-
// Output result to console
|
|
45
|
-
resolve(percentageCPU)
|
|
46
|
-
}, 1000)
|
|
47
|
-
})
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
class Monitoring {
|
|
51
|
-
constructor (reporter) {
|
|
52
|
-
this.reporter = reporter
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
async execute () {
|
|
56
|
-
const monitoring = {
|
|
57
|
-
cpu: await cpu(),
|
|
58
|
-
freemem: Math.round(os.freemem() / 1024 / 1024),
|
|
59
|
-
timestamp: new Date(),
|
|
60
|
-
hostname: os.hostname()
|
|
61
|
-
}
|
|
62
|
-
return this.reporter.documentStore.collection('monitoring').insert(monitoring)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
init () {
|
|
66
|
-
this._interval = setInterval(() => {
|
|
67
|
-
this.execute().catch((e) => this.reporter.logger.warn('unable to persist monitoring info, but no need to worry, we will retry, details:' + e.stack))
|
|
68
|
-
}, 60000)
|
|
69
|
-
this._interval.unref()
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
close () {
|
|
73
|
-
clearInterval(this._interval)
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
module.exports = (reporter) => {
|
|
78
|
-
reporter.documentStore.registerEntityType('MonitoringType', {
|
|
79
|
-
cpu: { type: 'Edm.Int32' },
|
|
80
|
-
freemem: { type: 'Edm.Int32' },
|
|
81
|
-
timestamp: { type: 'Edm.DateTimeOffset', schema: { type: 'null' } },
|
|
82
|
-
hostname: { type: 'Edm.String' }
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
reporter.documentStore.registerEntitySet('monitoring', {
|
|
86
|
-
entityType: 'jsreport.MonitoringType',
|
|
87
|
-
exportable: false,
|
|
88
|
-
shared: true
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
reporter.monitoring = new Monitoring(reporter)
|
|
92
|
-
}
|