@jsreport/jsreport-core 3.1.2-test.2 → 3.4.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.
Files changed (81) hide show
  1. package/LICENSE +166 -166
  2. package/README.md +310 -298
  3. package/index.js +29 -29
  4. package/lib/main/blobStorage/blobStorage.js +53 -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 +231 -237
  27. package/lib/main/optionsSchema.js +237 -237
  28. package/lib/main/profiler.js +13 -1
  29. package/lib/main/reporter.js +589 -579
  30. package/lib/main/request.js +21 -0
  31. package/lib/main/schemaValidator.js +252 -252
  32. package/lib/main/settings.js +154 -154
  33. package/lib/main/store/checkDuplicatedId.js +27 -27
  34. package/lib/main/store/collection.js +329 -329
  35. package/lib/main/store/documentStore.js +469 -469
  36. package/lib/main/store/mainActions.js +28 -28
  37. package/lib/main/store/memoryStoreProvider.js +99 -99
  38. package/lib/main/store/queue.js +48 -48
  39. package/lib/main/store/referenceUtils.js +251 -251
  40. package/lib/main/store/setupValidateId.js +43 -43
  41. package/lib/main/store/setupValidateShortid.js +71 -71
  42. package/lib/main/store/transaction.js +69 -69
  43. package/lib/main/store/typeUtils.js +180 -180
  44. package/lib/main/templates.js +34 -34
  45. package/lib/main/validateEntityName.js +62 -62
  46. package/lib/shared/createError.js +36 -36
  47. package/lib/shared/encryption.js +114 -114
  48. package/lib/shared/folders/index.js +11 -11
  49. package/lib/shared/folders/normalizeEntityPath.js +15 -15
  50. package/lib/shared/folders/resolveEntityFromPath.js +88 -88
  51. package/lib/shared/folders/resolveEntityPath.js +46 -46
  52. package/lib/shared/folders/resolveFolderFromPath.js +38 -38
  53. package/lib/shared/generateRequestId.js +4 -4
  54. package/lib/shared/listenerCollection.js +169 -169
  55. package/lib/shared/normalizeMetaFromLogs.js +30 -30
  56. package/lib/shared/reporter.js +128 -123
  57. package/lib/shared/request.js +64 -64
  58. package/lib/shared/tempFilesHandler.js +81 -81
  59. package/lib/shared/templates.js +82 -82
  60. package/lib/static/helpers.js +33 -33
  61. package/lib/worker/blobStorage.js +34 -34
  62. package/lib/worker/defaultProxyExtend.js +46 -46
  63. package/lib/worker/documentStore.js +49 -49
  64. package/lib/worker/extensionsManager.js +17 -17
  65. package/lib/worker/logger.js +48 -48
  66. package/lib/worker/render/diff.js +138 -138
  67. package/lib/worker/render/executeEngine.js +232 -207
  68. package/lib/worker/render/htmlRecipe.js +10 -10
  69. package/lib/worker/render/moduleHelper.js +45 -43
  70. package/lib/worker/render/noneEngine.js +12 -12
  71. package/lib/worker/render/profiler.js +162 -158
  72. package/lib/worker/render/render.js +202 -205
  73. package/lib/worker/render/resolveReferences.js +60 -60
  74. package/lib/worker/reporter.js +197 -191
  75. package/lib/worker/sandbox/runInSandbox.js +64 -12
  76. package/lib/worker/sandbox/safeSandbox.js +829 -828
  77. package/lib/worker/templates.js +80 -78
  78. package/lib/worker/workerHandler.js +55 -54
  79. package/package.json +91 -92
  80. package/test/blobStorage/common.js +25 -21
  81. package/test/store/common.js +1449 -1449
@@ -1,205 +1,202 @@
1
- /*!
2
- * Copyright(c) 2018 Jan Blaha
3
- *
4
- * Orchestration of the rendering process
5
- */
6
- const { Readable } = require('stream')
7
- const extend = require('node.extend.without.arrays')
8
- const ExecuteEngine = require('./executeEngine')
9
- const Request = require('../../shared/request')
10
- const generateRequestId = require('../../shared/generateRequestId')
11
- const resolveReferences = require('./resolveReferences.js')
12
- const moduleHelper = require('./moduleHelper')
13
- let reportCounter = 0
14
-
15
- module.exports = (reporter) => {
16
- reporter.addRequestContextMetaConfig('systemHelpers', { sandboxHidden: true })
17
-
18
- moduleHelper(reporter)
19
-
20
- const executeEngine = ExecuteEngine(reporter)
21
- async function beforeRender (reporter, request, response) {
22
- if (!request.template) {
23
- throw reporter.createError('template property must be defined', {
24
- statusCode: 400
25
- })
26
- }
27
-
28
- await reporter.beforeRenderListeners.fire(request, response)
29
- await reporter.validateRenderListeners.fire(request, response)
30
- }
31
-
32
- async function invokeRender (reporter, request, response) {
33
- if (!request.template.engine) {
34
- throw reporter.createError('Engine must be specified', {
35
- statusCode: 400
36
- })
37
- }
38
-
39
- const engine = reporter.extensionsManager.engines.find((e) => e.name === request.template.engine)
40
-
41
- if (!engine) {
42
- throw reporter.createError(`Engine '${request.template.engine}' not found. If this is a custom engine make sure it's properly installed from npm`, {
43
- statusCode: 400
44
- })
45
- }
46
-
47
- if (
48
- request.data != null &&
49
- typeof request.data === 'object' &&
50
- Array.isArray(request.data)
51
- ) {
52
- throw reporter.createError('Request data can not be an array. you should pass an object in request.data input', {
53
- statusCode: 400
54
- })
55
- }
56
-
57
- const engineProfilerEvent = reporter.profiler.emit({
58
- type: 'operationStart',
59
- subtype: 'engine',
60
- name: request.template.engine
61
- }, request, response)
62
-
63
- reporter.logger.debug(`Rendering engine ${engine.name}`, request)
64
-
65
- const engineRes = await executeEngine(engine, request)
66
-
67
- response.content = Buffer.from(engineRes.content != null ? engineRes.content : '')
68
-
69
- reporter.profiler.emit({
70
- type: 'operationEnd',
71
- operationId: engineProfilerEvent.operationId
72
- }, request, response)
73
-
74
- await reporter.afterTemplatingEnginesExecutedListeners.fire(request, response)
75
-
76
- if (!request.template.recipe) {
77
- throw reporter.createError('Recipe must be specified', {
78
- statusCode: 400
79
- })
80
- }
81
-
82
- const recipe = reporter.extensionsManager.recipes.find((r) => r.name === request.template.recipe)
83
-
84
- if (!recipe) {
85
- throw reporter.createError(`Recipe '${request.template.recipe}' not found. If this is a custom recipe make sure it's properly installed from npm.`, {
86
- statusCode: 400
87
- })
88
- }
89
-
90
- const recipeProfilerEvent = reporter.profiler.emit({
91
- type: 'operationStart',
92
- subtype: 'recipe',
93
- name: request.template.recipe
94
- }, request, response)
95
-
96
- reporter.logger.debug('Executing recipe ' + request.template.recipe, request)
97
-
98
- await recipe.execute(request, response)
99
- reporter.profiler.emit({
100
- type: 'operationEnd',
101
- operationId: recipeProfilerEvent.operationId
102
- }, request, response)
103
- }
104
-
105
- async function afterRender (reporter, request, response) {
106
- await reporter.afterRenderListeners.fire(request, response)
107
-
108
- response.stream = Readable.from(response.content)
109
- response.result = response.stream
110
-
111
- return response
112
- }
113
-
114
- return async (req, parentReq) => {
115
- const request = Request(req, parentReq)
116
- request.context.systemHelpers = ''
117
- const response = { meta: {} }
118
- let renderStartProfilerEvent
119
- try {
120
- if (request.context.id == null) {
121
- request.context.id = generateRequestId()
122
- }
123
-
124
- renderStartProfilerEvent = await reporter.profiler.renderStart(request, parentReq, response)
125
- request.data = resolveReferences(request.data) || {}
126
-
127
- if (request.options.reportName) {
128
- response.meta.reportName = String(request.options.reportName)
129
- } else {
130
- response.meta.reportName = 'report'
131
- }
132
-
133
- request.context.reportCounter = ++reportCounter
134
- request.context.startTimestamp = new Date().getTime()
135
-
136
- if (parentReq == null) {
137
- reporter.requestModulesCache.set(request.context.rootId, Object.create(null))
138
- }
139
-
140
- reporter.logger.info(`Starting rendering request ${request.context.reportCounter} (user: ${(request.context.user ? request.context.user.username : 'null')})`, request)
141
-
142
- // TODO
143
- /* if (reporter.entityTypeValidator.getSchema('TemplateType') != null) {
144
- const templateValidationResult = reporter.entityTypeValidator.validate('TemplateType', request.template, { rootPrefix: 'template' })
145
-
146
- if (!templateValidationResult.valid) {
147
- throw reporter.createError(`template input in request contain values that does not match the defined schema. ${templateValidationResult.fullErrorMessage}`, {
148
- statusCode: 400
149
- })
150
- }
151
- } */
152
-
153
- await beforeRender(reporter, request, response)
154
- await invokeRender(reporter, request, response)
155
- await afterRender(reporter, request, response)
156
-
157
- reporter.logger.info(`Rendering request ${request.context.reportCounter} finished in ${(new Date().getTime() - request.context.startTimestamp)} ms`, request)
158
-
159
- response.meta.logs = request.context.logs
160
-
161
- if (parentReq) {
162
- parentReq.context.logs = parentReq.context.logs.concat(request.context.logs)
163
- parentReq.context.shared = extend(true, parentReq.context.shared, request.context.shared)
164
- }
165
-
166
- await reporter.profiler.renderEnd(renderStartProfilerEvent.operationId, request, response)
167
-
168
- return response
169
- } catch (e) {
170
- await reporter.renderErrorListeners.fire(request, response, e)
171
-
172
- const logFn = e.weak ? reporter.logger.warn : reporter.logger.error
173
-
174
- logFn(`Error when processing render request ${request.context.reportCounter} ${e.message}${e.stack != null ? ' ' + e.stack : ''}`, request)
175
-
176
- logFn(`Rendering request ${request.context.reportCounter} finished with error in ${(new Date().getTime() - request.context.startTimestamp)} ms`, request)
177
-
178
- if (
179
- parentReq &&
180
- parentReq.context &&
181
- parentReq.context.logs &&
182
- request.context &&
183
- request.context.logs
184
- ) {
185
- parentReq.context.logs = parentReq.context.logs.concat(request.context.logs)
186
- }
187
-
188
- if (parentReq) {
189
- parentReq.context.shared = extend(true, parentReq.context.shared, request.context.shared)
190
- }
191
-
192
- e.logged = true
193
-
194
- if (renderStartProfilerEvent) {
195
- await reporter.profiler.renderEnd(renderStartProfilerEvent.operationId, request, response, e)
196
- }
197
-
198
- throw e
199
- } finally {
200
- if (parentReq == null) {
201
- reporter.requestModulesCache.delete(request.context.rootId)
202
- }
203
- }
204
- }
205
- }
1
+ /*!
2
+ * Copyright(c) 2018 Jan Blaha
3
+ *
4
+ * Orchestration of the rendering process
5
+ */
6
+ const { Readable } = require('stream')
7
+ const extend = require('node.extend.without.arrays')
8
+ const ExecuteEngine = require('./executeEngine')
9
+ const Request = require('../../shared/request')
10
+ const generateRequestId = require('../../shared/generateRequestId')
11
+ const resolveReferences = require('./resolveReferences.js')
12
+ const moduleHelper = require('./moduleHelper')
13
+ let reportCounter = 0
14
+
15
+ module.exports = (reporter) => {
16
+ moduleHelper(reporter)
17
+
18
+ const executeEngine = ExecuteEngine(reporter)
19
+ async function beforeRender (reporter, request, response) {
20
+ if (!request.template) {
21
+ throw reporter.createError('template property must be defined', {
22
+ statusCode: 400
23
+ })
24
+ }
25
+
26
+ await reporter.beforeRenderListeners.fire(request, response)
27
+ await reporter.validateRenderListeners.fire(request, response)
28
+ }
29
+
30
+ async function invokeRender (reporter, request, response) {
31
+ if (!request.template.engine) {
32
+ throw reporter.createError('Engine must be specified', {
33
+ statusCode: 400
34
+ })
35
+ }
36
+
37
+ const engine = reporter.extensionsManager.engines.find((e) => e.name === request.template.engine)
38
+
39
+ if (!engine) {
40
+ throw reporter.createError(`Engine '${request.template.engine}' not found. If this is a custom engine make sure it's properly installed from npm`, {
41
+ statusCode: 400
42
+ })
43
+ }
44
+
45
+ if (
46
+ request.data != null &&
47
+ typeof request.data === 'object' &&
48
+ Array.isArray(request.data)
49
+ ) {
50
+ throw reporter.createError('Request data can not be an array. you should pass an object in request.data input', {
51
+ statusCode: 400
52
+ })
53
+ }
54
+
55
+ const engineProfilerEvent = reporter.profiler.emit({
56
+ type: 'operationStart',
57
+ subtype: 'engine',
58
+ name: request.template.engine
59
+ }, request, response)
60
+
61
+ reporter.logger.debug(`Rendering engine ${engine.name}`, request)
62
+
63
+ const engineRes = await executeEngine(engine, request)
64
+
65
+ response.content = Buffer.from(engineRes.content != null ? engineRes.content : '')
66
+
67
+ reporter.profiler.emit({
68
+ type: 'operationEnd',
69
+ operationId: engineProfilerEvent.operationId
70
+ }, request, response)
71
+
72
+ await reporter.afterTemplatingEnginesExecutedListeners.fire(request, response)
73
+
74
+ if (!request.template.recipe) {
75
+ throw reporter.createError('Recipe must be specified', {
76
+ statusCode: 400
77
+ })
78
+ }
79
+
80
+ const recipe = reporter.extensionsManager.recipes.find((r) => r.name === request.template.recipe)
81
+
82
+ if (!recipe) {
83
+ throw reporter.createError(`Recipe '${request.template.recipe}' not found. If this is a custom recipe make sure it's properly installed from npm.`, {
84
+ statusCode: 400
85
+ })
86
+ }
87
+
88
+ const recipeProfilerEvent = reporter.profiler.emit({
89
+ type: 'operationStart',
90
+ subtype: 'recipe',
91
+ name: request.template.recipe
92
+ }, request, response)
93
+
94
+ reporter.logger.debug('Executing recipe ' + request.template.recipe, request)
95
+
96
+ await recipe.execute(request, response)
97
+ reporter.profiler.emit({
98
+ type: 'operationEnd',
99
+ operationId: recipeProfilerEvent.operationId
100
+ }, request, response)
101
+ }
102
+
103
+ async function afterRender (reporter, request, response) {
104
+ await reporter.afterRenderListeners.fire(request, response)
105
+
106
+ response.stream = Readable.from(response.content)
107
+ response.result = response.stream
108
+
109
+ return response
110
+ }
111
+
112
+ return async (req, parentReq) => {
113
+ const request = Request(req, parentReq)
114
+ const response = { meta: {} }
115
+ let renderStartProfilerEvent
116
+ try {
117
+ if (request.context.id == null) {
118
+ request.context.id = generateRequestId()
119
+ }
120
+
121
+ renderStartProfilerEvent = await reporter.profiler.renderStart(request, parentReq, response)
122
+ request.data = resolveReferences(request.data) || {}
123
+
124
+ if (request.options.reportName) {
125
+ response.meta.reportName = String(request.options.reportName)
126
+ } else {
127
+ response.meta.reportName = 'report'
128
+ }
129
+
130
+ request.context.reportCounter = ++reportCounter
131
+ request.context.startTimestamp = new Date().getTime()
132
+
133
+ if (parentReq == null) {
134
+ reporter.requestModulesCache.set(request.context.rootId, Object.create(null))
135
+ }
136
+
137
+ reporter.logger.info(`Starting rendering request ${request.context.reportCounter} (user: ${(request.context.user ? request.context.user.username : 'null')})`, request)
138
+
139
+ // TODO
140
+ /* if (reporter.entityTypeValidator.getSchema('TemplateType') != null) {
141
+ const templateValidationResult = reporter.entityTypeValidator.validate('TemplateType', request.template, { rootPrefix: 'template' })
142
+
143
+ if (!templateValidationResult.valid) {
144
+ throw reporter.createError(`template input in request contain values that does not match the defined schema. ${templateValidationResult.fullErrorMessage}`, {
145
+ statusCode: 400
146
+ })
147
+ }
148
+ } */
149
+
150
+ await beforeRender(reporter, request, response)
151
+ await invokeRender(reporter, request, response)
152
+ await afterRender(reporter, request, response)
153
+
154
+ reporter.logger.info(`Rendering request ${request.context.reportCounter} finished in ${(new Date().getTime() - request.context.startTimestamp)} ms`, request)
155
+
156
+ response.meta.logs = request.context.logs
157
+
158
+ if (parentReq) {
159
+ parentReq.context.logs = parentReq.context.logs.concat(request.context.logs)
160
+ parentReq.context.shared = extend(true, parentReq.context.shared, request.context.shared)
161
+ }
162
+
163
+ await reporter.profiler.renderEnd(renderStartProfilerEvent.operationId, request, response)
164
+
165
+ return response
166
+ } catch (e) {
167
+ await reporter.renderErrorListeners.fire(request, response, e)
168
+
169
+ const logFn = e.weak ? reporter.logger.warn : reporter.logger.error
170
+
171
+ logFn(`Error when processing render request ${request.context.reportCounter} ${e.message}${e.stack != null ? ' ' + e.stack : ''}`, request)
172
+
173
+ logFn(`Rendering request ${request.context.reportCounter} finished with error in ${(new Date().getTime() - request.context.startTimestamp)} ms`, request)
174
+
175
+ if (
176
+ parentReq &&
177
+ parentReq.context &&
178
+ parentReq.context.logs &&
179
+ request.context &&
180
+ request.context.logs
181
+ ) {
182
+ parentReq.context.logs = parentReq.context.logs.concat(request.context.logs)
183
+ }
184
+
185
+ if (parentReq) {
186
+ parentReq.context.shared = extend(true, parentReq.context.shared, request.context.shared)
187
+ }
188
+
189
+ e.logged = true
190
+
191
+ if (renderStartProfilerEvent) {
192
+ await reporter.profiler.renderEnd(renderStartProfilerEvent.operationId, request, response, e)
193
+ }
194
+
195
+ throw e
196
+ } finally {
197
+ if (parentReq == null) {
198
+ reporter.requestModulesCache.delete(request.context.rootId)
199
+ }
200
+ }
201
+ }
202
+ }
@@ -1,60 +1,60 @@
1
- // resolve references in json specified by $ref and $id attribute, this is handy when user send cycles in json
2
- module.exports = function (json) {
3
- if (typeof json === 'string') {
4
- json = JSON.parse(json)
5
- }
6
-
7
- const byid = {} // all objects by id
8
- const refs = [] // references to objects that could not be resolved
9
- json = (function recurse (obj, prop, parent) {
10
- if (typeof obj !== 'object' || !obj) { // a primitive value
11
- return obj
12
- }
13
- if (Object.prototype.toString.call(obj) === '[object Array]') {
14
- for (let i = 0; i < obj.length; i++) {
15
- if (obj[i] === null) {
16
- continue
17
- }
18
-
19
- if (Object.prototype.hasOwnProperty.call(obj[i], '$ref')) {
20
- obj[i] = recurse(obj[i], i, obj)
21
- } else {
22
- obj[i] = recurse(obj[i], prop, obj)
23
- }
24
- }
25
- return obj
26
- }
27
-
28
- if ('$ref' in obj) { // a reference
29
- const ref = obj.$ref
30
- if (ref in byid) {
31
- return byid[ref]
32
- }
33
- // else we have to make it lazy:
34
- refs.push([parent, prop, ref])
35
- return
36
- } else if ('$id' in obj) {
37
- const id = obj.$id
38
- delete obj.$id
39
- if ('$values' in obj) { // an array
40
- obj = obj.$values.map(recurse)
41
- } else { // a plain object
42
- for (const p in obj) {
43
- if (Object.prototype.hasOwnProperty.call(obj, p)) {
44
- obj[p] = recurse(obj[p], p, obj)
45
- }
46
- }
47
- }
48
- byid[id] = obj
49
- }
50
-
51
- return obj
52
- })(json) // run it!
53
-
54
- for (let i = 0; i < refs.length; i++) { // resolve previously unknown references
55
- const ref = refs[i]
56
- ref[0][ref[1]] = byid[ref[2]]
57
- // Notice that this throws if you put in a reference at top-level
58
- }
59
- return json
60
- }
1
+ // resolve references in json specified by $ref and $id attribute, this is handy when user send cycles in json
2
+ module.exports = function (json) {
3
+ if (typeof json === 'string') {
4
+ json = JSON.parse(json)
5
+ }
6
+
7
+ const byid = {} // all objects by id
8
+ const refs = [] // references to objects that could not be resolved
9
+ json = (function recurse (obj, prop, parent) {
10
+ if (typeof obj !== 'object' || !obj) { // a primitive value
11
+ return obj
12
+ }
13
+ if (Object.prototype.toString.call(obj) === '[object Array]') {
14
+ for (let i = 0; i < obj.length; i++) {
15
+ if (obj[i] === null) {
16
+ continue
17
+ }
18
+
19
+ if (Object.prototype.hasOwnProperty.call(obj[i], '$ref')) {
20
+ obj[i] = recurse(obj[i], i, obj)
21
+ } else {
22
+ obj[i] = recurse(obj[i], prop, obj)
23
+ }
24
+ }
25
+ return obj
26
+ }
27
+
28
+ if ('$ref' in obj) { // a reference
29
+ const ref = obj.$ref
30
+ if (ref in byid) {
31
+ return byid[ref]
32
+ }
33
+ // else we have to make it lazy:
34
+ refs.push([parent, prop, ref])
35
+ return
36
+ } else if ('$id' in obj) {
37
+ const id = obj.$id
38
+ delete obj.$id
39
+ if ('$values' in obj) { // an array
40
+ obj = obj.$values.map(recurse)
41
+ } else { // a plain object
42
+ for (const p in obj) {
43
+ if (Object.prototype.hasOwnProperty.call(obj, p)) {
44
+ obj[p] = recurse(obj[p], p, obj)
45
+ }
46
+ }
47
+ }
48
+ byid[id] = obj
49
+ }
50
+
51
+ return obj
52
+ })(json) // run it!
53
+
54
+ for (let i = 0; i < refs.length; i++) { // resolve previously unknown references
55
+ const ref = refs[i]
56
+ ref[0][ref[1]] = byid[ref[2]]
57
+ // Notice that this throws if you put in a reference at top-level
58
+ }
59
+ return json
60
+ }