@jsreport/jsreport-core 3.1.1 → 3.3.0

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 (80) hide show
  1. package/LICENSE +166 -166
  2. package/README.md +298 -298
  3. package/index.js +29 -29
  4. package/lib/main/blobStorage/blobStorage.js +52 -52
  5. package/lib/main/blobStorage/inMemoryProvider.js +27 -27
  6. package/lib/main/blobStorage/mainActions.js +24 -24
  7. package/lib/main/createDefaultLoggerFormat.js +17 -17
  8. package/lib/main/defaults.js +14 -14
  9. package/lib/main/extensions/discover.js +20 -20
  10. package/lib/main/extensions/extensionsManager.js +264 -264
  11. package/lib/main/extensions/fileUtils.js +56 -56
  12. package/lib/main/extensions/findVersion.js +49 -49
  13. package/lib/main/extensions/locationCache.js +103 -103
  14. package/lib/main/extensions/sorter.js +10 -10
  15. package/lib/main/extensions/validateMinimalVersion.js +50 -50
  16. package/lib/main/folders/cascadeFolderRemove.js +25 -25
  17. package/lib/main/folders/getEntitiesInFolder.js +53 -53
  18. package/lib/main/folders/index.js +42 -42
  19. package/lib/main/folders/moveBetweenFolders.js +354 -354
  20. package/lib/main/folders/validateDuplicatedName.js +107 -107
  21. package/lib/main/folders/validateReservedName.js +53 -53
  22. package/lib/main/logger.js +254 -244
  23. package/lib/main/migration/resourcesToAssets.js +230 -230
  24. package/lib/main/migration/xlsxTemplatesToAssets.js +128 -128
  25. package/lib/main/monitoring.js +92 -91
  26. package/lib/main/optionsLoad.js +237 -237
  27. package/lib/main/optionsSchema.js +237 -237
  28. package/lib/main/profiler.js +13 -1
  29. package/lib/main/reporter.js +593 -579
  30. package/lib/main/schemaValidator.js +252 -252
  31. package/lib/main/settings.js +154 -154
  32. package/lib/main/store/checkDuplicatedId.js +27 -27
  33. package/lib/main/store/collection.js +329 -329
  34. package/lib/main/store/documentStore.js +469 -469
  35. package/lib/main/store/mainActions.js +28 -28
  36. package/lib/main/store/memoryStoreProvider.js +99 -99
  37. package/lib/main/store/queue.js +48 -48
  38. package/lib/main/store/referenceUtils.js +251 -251
  39. package/lib/main/store/setupValidateId.js +43 -43
  40. package/lib/main/store/setupValidateShortid.js +71 -71
  41. package/lib/main/store/transaction.js +69 -69
  42. package/lib/main/store/typeUtils.js +180 -180
  43. package/lib/main/templates.js +34 -34
  44. package/lib/main/validateEntityName.js +62 -62
  45. package/lib/shared/createError.js +36 -36
  46. package/lib/shared/encryption.js +114 -114
  47. package/lib/shared/folders/index.js +11 -11
  48. package/lib/shared/folders/normalizeEntityPath.js +15 -15
  49. package/lib/shared/folders/resolveEntityFromPath.js +88 -88
  50. package/lib/shared/folders/resolveEntityPath.js +46 -46
  51. package/lib/shared/folders/resolveFolderFromPath.js +38 -38
  52. package/lib/shared/generateRequestId.js +4 -4
  53. package/lib/shared/listenerCollection.js +169 -169
  54. package/lib/shared/normalizeMetaFromLogs.js +30 -30
  55. package/lib/shared/reporter.js +128 -123
  56. package/lib/shared/request.js +64 -64
  57. package/lib/shared/tempFilesHandler.js +81 -81
  58. package/lib/shared/templates.js +82 -82
  59. package/lib/static/helpers.js +33 -33
  60. package/lib/worker/blobStorage.js +34 -34
  61. package/lib/worker/defaultProxyExtend.js +46 -46
  62. package/lib/worker/documentStore.js +49 -49
  63. package/lib/worker/extensionsManager.js +17 -17
  64. package/lib/worker/logger.js +48 -48
  65. package/lib/worker/render/diff.js +138 -138
  66. package/lib/worker/render/executeEngine.js +232 -207
  67. package/lib/worker/render/htmlRecipe.js +10 -10
  68. package/lib/worker/render/moduleHelper.js +45 -43
  69. package/lib/worker/render/noneEngine.js +12 -12
  70. package/lib/worker/render/profiler.js +162 -158
  71. package/lib/worker/render/render.js +202 -201
  72. package/lib/worker/render/resolveReferences.js +60 -60
  73. package/lib/worker/reporter.js +197 -191
  74. package/lib/worker/sandbox/runInSandbox.js +65 -13
  75. package/lib/worker/sandbox/safeSandbox.js +829 -828
  76. package/lib/worker/templates.js +80 -78
  77. package/lib/worker/workerHandler.js +54 -54
  78. package/package.json +91 -92
  79. package/test/blobStorage/common.js +21 -21
  80. package/test/store/common.js +1449 -1449
@@ -1,158 +1,162 @@
1
- const extend = require('node.extend.without.arrays')
2
- const isbinaryfile = require('isbinaryfile').isBinaryFileSync
3
- const omit = require('lodash.omit')
4
- const { createPatch } = require('./diff')
5
- const generateRequestId = require('../../shared/generateRequestId')
6
-
7
- class Profiler {
8
- constructor (reporter) {
9
- this.reporter = reporter
10
-
11
- this.reporter.addRequestContextMetaConfig('profiling', { sandboxReadOnly: true })
12
- this.reporter.addRequestContextMetaConfig('resolvedTemplate', { sandboxHidden: true })
13
-
14
- this.reporter.beforeMainActionListeners.add('profiler', (actionName, data, req) => {
15
- if (actionName === 'log' && req.context.profiling) {
16
- data.previousOperationId = req.context.profiling.lastOperationId
17
- }
18
- })
19
-
20
- this.profiledRequestsMap = new Map()
21
- const profileEventsFlushInterval = setInterval(async () => {
22
- for (const id of [...this.profiledRequestsMap.keys()]) {
23
- const profilingInfo = this.profiledRequestsMap.get(id)
24
- if (profilingInfo) {
25
- const batch = profilingInfo.batch
26
- profilingInfo.batch = []
27
- await this.reporter.executeMainAction('profile', batch, profilingInfo.req).catch((e) => this.reporter.logger.error(e, profilingInfo.req))
28
- }
29
- }
30
- }, 100)
31
- profileEventsFlushInterval.unref()
32
-
33
- this.reporter.closeListeners.add('profiler', this, () => {
34
- if (profileEventsFlushInterval) {
35
- clearInterval(profileEventsFlushInterval)
36
- }
37
- })
38
- }
39
-
40
- emit (m, req, res) {
41
- m.timestamp = m.timestamp || new Date().getTime()
42
-
43
- if (m.type === 'log' && !req.context.profiling) {
44
- // this means there is an action running, but not the render, and it is logging...
45
- return this.reporter.executeMainAction('log', m, req)
46
- }
47
-
48
- m.id = generateRequestId()
49
-
50
- if (m.previousEventId == null && req.context.profiling.lastEventId && m.type !== 'log') {
51
- m.previousEventId = req.context.profiling.lastEventId
52
- }
53
-
54
- if (m.type !== 'log') {
55
- req.context.profiling.lastEventId = m.id
56
- }
57
-
58
- m.operationId = m.operationId || generateRequestId()
59
- if (m.previousOperationId == null && req.context.profiling.lastOperationId) {
60
- m.previousOperationId = req.context.profiling.lastOperationId
61
- }
62
-
63
- if (m.type === 'operationStart') {
64
- req.context.profiling.lastOperationId = m.operationId
65
- }
66
-
67
- if (m.doDiffs !== false && req.context.profiling.mode === 'full' && (m.type === 'operationStart' || m.type === 'operationEnd')) {
68
- let content = res.content
69
-
70
- if (content != null) {
71
- if (isbinaryfile(content)) {
72
- content = {
73
- content: res.content.toString('base64'),
74
- encoding: 'base64'
75
- }
76
- } else {
77
- content = {
78
- content: createPatch('res', req.context.profiling.resLastVal ? req.context.profiling.resLastVal.toString() : '', res.content.toString(), 0),
79
- encoding: 'diff'
80
- }
81
- }
82
- }
83
-
84
- const stringifiedResMeta = JSON.stringify(omit(res.meta, ['logs']))
85
-
86
- m.res = { content, meta: { diff: createPatch('resMeta', req.context.profiling.resMetaLastVal || '', stringifiedResMeta, 0) } }
87
-
88
- const stringifiedReq = JSON.stringify({ template: req.template, data: req.data }, null, 2)
89
-
90
- m.req = { diff: createPatch('req', req.context.profiling.reqLastVal || '', stringifiedReq, 0) }
91
-
92
- req.context.profiling.resLastVal = res.content
93
- req.context.profiling.resMetaLastVal = stringifiedResMeta
94
- req.context.profiling.reqLastVal = stringifiedReq
95
- }
96
-
97
- if (!this.profiledRequestsMap.has(req.context.rootId)) {
98
- this.profiledRequestsMap.set(req.context.rootId, { req, batch: [] })
99
- }
100
-
101
- this.profiledRequestsMap.get(req.context.rootId).batch.push(m)
102
- return m
103
- }
104
-
105
- async renderStart (req, parentReq, res) {
106
- let templateName = 'anonymous'
107
- let template = req.context.resolvedTemplate
108
-
109
- if (parentReq) {
110
- template = await this.reporter.templates.resolveTemplate(req)
111
- // store a copy to prevent side-effects
112
- req.context.resolvedTemplate = extend(true, {}, template)
113
- } else {
114
- template = req.context.resolvedTemplate
115
- }
116
-
117
- if (template != null && template.name != null) {
118
- templateName = template.name
119
- }
120
-
121
- const profilerEvent = {
122
- type: 'operationStart',
123
- subtype: 'render',
124
- name: templateName,
125
- previousOperationId: parentReq ? parentReq.context.profiling.lastOperationId : null
126
- }
127
-
128
- if (!req.context.isChildRequest) {
129
- profilerEvent.profileId = req.context.profiling.entity._id
130
- }
131
-
132
- return this.emit(profilerEvent, req, res)
133
- }
134
-
135
- async renderEnd (operationId, req, res, err) {
136
- if (err) {
137
- err.previousOperationId = err.previousOperationId || req.context.profiling.lastOperationId
138
- } else {
139
- await this.emit({
140
- type: 'operationEnd',
141
- subtype: 'render',
142
- operationId
143
- }, req, res)
144
- }
145
-
146
- if (!req.context.isChildRequest) {
147
- const profilingInfo = this.profiledRequestsMap.get(req.context.rootId)
148
- if (profilingInfo) {
149
- this.profiledRequestsMap.delete(req.context.rootId)
150
- await this.reporter.executeMainAction('profile', profilingInfo.batch, req)
151
- }
152
- }
153
- }
154
- }
155
-
156
- module.exports = (reporter) => {
157
- return new Profiler(reporter)
158
- }
1
+ const extend = require('node.extend.without.arrays')
2
+ const isbinaryfile = require('isbinaryfile').isBinaryFileSync
3
+ const omit = require('lodash.omit')
4
+ const { createPatch } = require('./diff')
5
+ const generateRequestId = require('../../shared/generateRequestId')
6
+
7
+ class Profiler {
8
+ constructor (reporter) {
9
+ this.reporter = reporter
10
+
11
+ this.reporter.addRequestContextMetaConfig('profiling', { sandboxReadOnly: true })
12
+ this.reporter.addRequestContextMetaConfig('resolvedTemplate', { sandboxHidden: true })
13
+
14
+ this.reporter.beforeMainActionListeners.add('profiler', (actionName, data, req) => {
15
+ if (actionName === 'log' && req.context.profiling) {
16
+ data.previousOperationId = req.context.profiling.lastOperationId
17
+ }
18
+ })
19
+
20
+ this.profiledRequestsMap = new Map()
21
+ const profileEventsFlushInterval = setInterval(() => this.flush(), 100)
22
+ profileEventsFlushInterval.unref()
23
+
24
+ this.reporter.closeListeners.add('profiler', this, () => {
25
+ if (profileEventsFlushInterval) {
26
+ clearInterval(profileEventsFlushInterval)
27
+ }
28
+ })
29
+ }
30
+
31
+ async flush (id) {
32
+ const toProcess = id == null ? [...this.profiledRequestsMap.keys()] : [id]
33
+
34
+ for (const id of toProcess) {
35
+ const profilingInfo = this.profiledRequestsMap.get(id)
36
+ if (profilingInfo) {
37
+ const batch = profilingInfo.batch
38
+ profilingInfo.batch = []
39
+ await this.reporter.executeMainAction('profile', batch, profilingInfo.req).catch((e) => this.reporter.logger.error(e, profilingInfo.req))
40
+ }
41
+ }
42
+ }
43
+
44
+ emit (m, req, res) {
45
+ m.timestamp = m.timestamp || new Date().getTime()
46
+
47
+ if (m.type === 'log' && !req.context.profiling) {
48
+ // this means there is an action running, but not the render, and it is logging...
49
+ return this.reporter.executeMainAction('log', m, req)
50
+ }
51
+
52
+ m.id = generateRequestId()
53
+
54
+ if (m.previousEventId == null && req.context.profiling.lastEventId && m.type !== 'log') {
55
+ m.previousEventId = req.context.profiling.lastEventId
56
+ }
57
+
58
+ if (m.type !== 'log') {
59
+ req.context.profiling.lastEventId = m.id
60
+ }
61
+
62
+ m.operationId = m.operationId || generateRequestId()
63
+ if (m.previousOperationId == null && req.context.profiling.lastOperationId) {
64
+ m.previousOperationId = req.context.profiling.lastOperationId
65
+ }
66
+
67
+ if (m.type === 'operationStart') {
68
+ req.context.profiling.lastOperationId = m.operationId
69
+ }
70
+
71
+ if (m.doDiffs !== false && req.context.profiling.mode === 'full' && (m.type === 'operationStart' || m.type === 'operationEnd')) {
72
+ let content = res.content
73
+
74
+ if (content != null) {
75
+ if (isbinaryfile(content)) {
76
+ content = {
77
+ content: res.content.toString('base64'),
78
+ encoding: 'base64'
79
+ }
80
+ } else {
81
+ content = {
82
+ content: createPatch('res', req.context.profiling.resLastVal ? req.context.profiling.resLastVal.toString() : '', res.content.toString(), 0),
83
+ encoding: 'diff'
84
+ }
85
+ }
86
+ }
87
+
88
+ const stringifiedResMeta = JSON.stringify(omit(res.meta, ['logs']))
89
+
90
+ m.res = { content, meta: { diff: createPatch('resMeta', req.context.profiling.resMetaLastVal || '', stringifiedResMeta, 0) } }
91
+
92
+ const stringifiedReq = JSON.stringify({ template: req.template, data: req.data }, null, 2)
93
+
94
+ m.req = { diff: createPatch('req', req.context.profiling.reqLastVal || '', stringifiedReq, 0) }
95
+
96
+ req.context.profiling.resLastVal = res.content
97
+ req.context.profiling.resMetaLastVal = stringifiedResMeta
98
+ req.context.profiling.reqLastVal = stringifiedReq
99
+ }
100
+
101
+ if (!this.profiledRequestsMap.has(req.context.rootId)) {
102
+ this.profiledRequestsMap.set(req.context.rootId, { req, batch: [] })
103
+ }
104
+
105
+ this.profiledRequestsMap.get(req.context.rootId).batch.push(m)
106
+ return m
107
+ }
108
+
109
+ async renderStart (req, parentReq, res) {
110
+ let templateName = 'anonymous'
111
+ let template = req.context.resolvedTemplate
112
+
113
+ if (parentReq) {
114
+ template = await this.reporter.templates.resolveTemplate(req)
115
+ // store a copy to prevent side-effects
116
+ req.context.resolvedTemplate = extend(true, {}, template)
117
+ } else {
118
+ template = req.context.resolvedTemplate
119
+ }
120
+
121
+ if (template != null && template.name != null) {
122
+ templateName = template.name
123
+ }
124
+
125
+ const profilerEvent = {
126
+ type: 'operationStart',
127
+ subtype: 'render',
128
+ name: templateName,
129
+ previousOperationId: parentReq ? parentReq.context.profiling.lastOperationId : null
130
+ }
131
+
132
+ if (!req.context.isChildRequest) {
133
+ profilerEvent.profileId = req.context.profiling.entity._id
134
+ }
135
+
136
+ return this.emit(profilerEvent, req, res)
137
+ }
138
+
139
+ async renderEnd (operationId, req, res, err) {
140
+ if (err) {
141
+ err.previousOperationId = err.previousOperationId || req.context.profiling.lastOperationId
142
+ } else {
143
+ await this.emit({
144
+ type: 'operationEnd',
145
+ subtype: 'render',
146
+ operationId
147
+ }, req, res)
148
+ }
149
+
150
+ if (!req.context.isChildRequest) {
151
+ const profilingInfo = this.profiledRequestsMap.get(req.context.rootId)
152
+ if (profilingInfo) {
153
+ this.profiledRequestsMap.delete(req.context.rootId)
154
+ await this.reporter.executeMainAction('profile', profilingInfo.batch, req)
155
+ }
156
+ }
157
+ }
158
+ }
159
+
160
+ module.exports = (reporter) => {
161
+ return new Profiler(reporter)
162
+ }