@jsreport/jsreport-core 3.0.0 → 3.1.2-test.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 (80) hide show
  1. package/LICENSE +166 -166
  2. package/README.md +298 -284
  3. package/index.js +29 -27
  4. package/lib/main/blobStorage/blobStorage.js +52 -47
  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 -265
  11. package/lib/main/extensions/fileUtils.js +56 -55
  12. package/lib/main/extensions/findVersion.js +49 -53
  13. package/lib/main/extensions/locationCache.js +103 -97
  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 +244 -244
  23. package/lib/main/migration/resourcesToAssets.js +230 -210
  24. package/lib/main/migration/xlsxTemplatesToAssets.js +128 -118
  25. package/lib/main/monitoring.js +91 -91
  26. package/lib/main/optionsLoad.js +237 -237
  27. package/lib/main/optionsSchema.js +237 -237
  28. package/lib/main/profiler.js +2 -1
  29. package/lib/main/reporter.js +575 -578
  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 -0
  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 +227 -190
  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 +158 -158
  71. package/lib/worker/render/render.js +213 -209
  72. package/lib/worker/render/resolveReferences.js +60 -60
  73. package/lib/worker/reporter.js +192 -187
  74. package/lib/worker/sandbox/runInSandbox.js +13 -4
  75. package/lib/worker/sandbox/safeSandbox.js +828 -822
  76. package/lib/worker/templates.js +78 -78
  77. package/lib/worker/workerHandler.js +54 -54
  78. package/package.json +92 -92
  79. package/test/blobStorage/common.js +21 -21
  80. package/test/store/common.js +1449 -1449
@@ -1,187 +1,192 @@
1
- const ExtensionsManager = require('./extensionsManager')
2
- const DocumentStore = require('./documentStore')
3
- const Templates = require('./templates')
4
- const createLogger = require('./logger')
5
- const runInSandbox = require('./sandbox/runInSandbox')
6
- const createNoneEngine = require('./render/noneEngine')
7
- const htmlRecipe = require('./render/htmlRecipe')
8
- const defaultProxyExtend = require('./defaultProxyExtend')
9
- const Reporter = require('../shared/reporter')
10
- const BlobStorage = require('./blobStorage.js')
11
- const Render = require('./render/render')
12
- const Profiler = require('./render/profiler.js')
13
-
14
- class WorkerReporter extends Reporter {
15
- constructor (workerData, executeMain) {
16
- const { options, documentStore, extensionsDefs } = workerData
17
-
18
- super(options)
19
-
20
- this._executeMain = executeMain
21
- this._initialized = false
22
- this._documentStoreData = documentStore
23
- this._requestContextMetaConfigCollection = new Map()
24
- this._proxyRegistrationFns = []
25
- this.requestModulesCache = new Map()
26
- this._workerActions = new Map()
27
- this._registerRenderAction()
28
-
29
- this.afterTemplatingEnginesExecutedListeners = this.createListenerCollection()
30
- this.validateRenderListeners = this.createListenerCollection()
31
-
32
- this.extensionsManager = ExtensionsManager(this, extensionsDefs)
33
-
34
- this.extendProxy((proxy, req) => defaultProxyExtend(this)(proxy, req))
35
- this.beforeMainActionListeners = this.createListenerCollection()
36
- }
37
-
38
- async init () {
39
- if (this._initialized === true) {
40
- throw new Error('jsreport already initialized. Make sure init is called only once')
41
- }
42
-
43
- super.init()
44
-
45
- Templates(this)
46
-
47
- this.profiler = Profiler(this)
48
- this.logger = createLogger(this.profiler)
49
-
50
- this._render = Render(this)
51
- await this.extensionsManager.init()
52
-
53
- this.documentStore = DocumentStore(this._documentStoreData, this.executeMainAction.bind(this))
54
- this.blobStorage = BlobStorage(this.executeMainAction.bind(this))
55
-
56
- this.addRequestContextMetaConfig('rootId', { sandboxReadOnly: true })
57
- this.addRequestContextMetaConfig('id', { sandboxReadOnly: true })
58
- this.addRequestContextMetaConfig('reportCounter', { sandboxReadOnly: true })
59
- this.addRequestContextMetaConfig('startTimestamp', { sandboxReadOnly: true })
60
- this.addRequestContextMetaConfig('logs', { sandboxReadOnly: true })
61
- this.addRequestContextMetaConfig('isChildRequest', { sandboxReadOnly: true })
62
- this.addRequestContextMetaConfig('originalInputDataIsEmpty', { sandboxReadOnly: true })
63
- this.addRequestContextMetaConfig('skipModificationDateUpdate', { sandboxHidden: true })
64
-
65
- this._runInSandbox = runInSandbox(this)
66
-
67
- const { compile: compileNone, execute: executeNone } = createNoneEngine()
68
-
69
- this.extensionsManager.engines.push({
70
- name: 'none',
71
- compile: compileNone,
72
- execute: executeNone
73
- })
74
-
75
- this.extensionsManager.recipes.push({
76
- name: 'html',
77
- execute: htmlRecipe
78
- })
79
-
80
- await this.initializeListeners.fire()
81
-
82
- this._initialized = true
83
- }
84
-
85
- /**
86
- * @public
87
- */
88
- addRequestContextMetaConfig (property, options) {
89
- this._requestContextMetaConfigCollection.set(property, options)
90
- }
91
-
92
- /**
93
- * @public
94
- */
95
- getRequestContextMetaConfig (property) {
96
- if (property === undefined) {
97
- const all = {}
98
-
99
- for (const [key, value] of this._requestContextMetaConfigCollection.entries()) {
100
- all[key] = value
101
- }
102
-
103
- return all
104
- }
105
-
106
- return this._requestContextMetaConfigCollection.get(property)
107
- }
108
-
109
- extendProxy (registrationFn) {
110
- this._proxyRegistrationFns.push(registrationFn)
111
- }
112
-
113
- createProxy ({ req, runInSandbox, context, getTopLevelFunctions, safeRequire }) {
114
- const proxyInstance = {}
115
- for (const fn of this._proxyRegistrationFns) {
116
- fn(proxyInstance, req, {
117
- runInSandbox,
118
- context,
119
- getTopLevelFunctions,
120
- safeRequire
121
- })
122
- }
123
- return proxyInstance
124
- }
125
-
126
- render (req, parentReq) {
127
- return this._render(req, parentReq)
128
- }
129
-
130
- async executeMainAction (actionName, data, req) {
131
- await this.beforeMainActionListeners.fire(actionName, data, req)
132
- return this._executeMain(actionName, data, req)
133
- }
134
-
135
- async runInSandbox ({
136
- context,
137
- userCode,
138
- executionFn,
139
- onRequire,
140
- propertiesConfig,
141
- errorLineNumberOffset
142
- }, req) {
143
- return this._runInSandbox({
144
- context,
145
- userCode,
146
- executionFn,
147
- onRequire,
148
- propertiesConfig,
149
- errorLineNumberOffset
150
- }, req)
151
- }
152
-
153
- registerWorkerAction (actionName, fn) {
154
- this._workerActions.set(actionName, fn)
155
- }
156
-
157
- async executeWorkerAction (actionName, data, req) {
158
- const action = this._workerActions.get(actionName)
159
- if (!action) {
160
- throw new Error(`Worker action ${actionName} not registered`)
161
- }
162
- return action(data, req)
163
- }
164
-
165
- _registerRenderAction () {
166
- this.registerWorkerAction('render', async (data, req) => {
167
- const res = await this.render(req)
168
-
169
- const sharedBuf = new SharedArrayBuffer(res.content.byteLength)
170
- const buf = Buffer.from(sharedBuf)
171
-
172
- res.content.copy(buf)
173
-
174
- return {
175
- meta: res.meta,
176
- content: buf
177
- }
178
- })
179
- }
180
-
181
- async close () {
182
- this.logger.debug('Closing jsreport worker')
183
- return this.closeListeners.fire()
184
- }
185
- }
186
-
187
- module.exports = WorkerReporter
1
+ const ExtensionsManager = require('./extensionsManager')
2
+ const DocumentStore = require('./documentStore')
3
+ const Templates = require('./templates')
4
+ const createLogger = require('./logger')
5
+ const runInSandbox = require('./sandbox/runInSandbox')
6
+ const createNoneEngine = require('./render/noneEngine')
7
+ const htmlRecipe = require('./render/htmlRecipe')
8
+ const defaultProxyExtend = require('./defaultProxyExtend')
9
+ const Reporter = require('../shared/reporter')
10
+ const BlobStorage = require('./blobStorage.js')
11
+ const Render = require('./render/render')
12
+ const Profiler = require('./render/profiler.js')
13
+
14
+ class WorkerReporter extends Reporter {
15
+ constructor (workerData, executeMain) {
16
+ const { options, documentStore, extensionsDefs } = workerData
17
+
18
+ super(options)
19
+
20
+ this._executeMain = executeMain
21
+ this._initialized = false
22
+ this._documentStoreData = documentStore
23
+ this._requestContextMetaConfigCollection = new Map()
24
+ this._proxyRegistrationFns = []
25
+ this.requestModulesCache = new Map()
26
+ this._workerActions = new Map()
27
+ this._registerRenderAction()
28
+
29
+ this.registerHelpersListeners = this.createListenerCollection('registerHelpers')
30
+ this.afterTemplatingEnginesExecutedListeners = this.createListenerCollection('afterTemplatingEnginesExecuted')
31
+ this.validateRenderListeners = this.createListenerCollection('validateRender')
32
+
33
+ this.extensionsManager = ExtensionsManager(this, extensionsDefs)
34
+
35
+ this.extendProxy((proxy, req) => defaultProxyExtend(this)(proxy, req))
36
+ this.beforeMainActionListeners = this.createListenerCollection('beforeMainAction')
37
+ }
38
+
39
+ async init () {
40
+ if (this._initialized === true) {
41
+ throw new Error('jsreport already initialized. Make sure init is called only once')
42
+ }
43
+
44
+ super.init()
45
+
46
+ Templates(this)
47
+
48
+ this.profiler = Profiler(this)
49
+ this.logger = createLogger(this.profiler)
50
+
51
+ this._render = Render(this)
52
+ await this.extensionsManager.init()
53
+
54
+ this.documentStore = DocumentStore(this._documentStoreData, this.executeMainAction.bind(this))
55
+ this.blobStorage = BlobStorage(this.executeMainAction.bind(this))
56
+
57
+ this.addRequestContextMetaConfig('rootId', { sandboxReadOnly: true })
58
+ this.addRequestContextMetaConfig('id', { sandboxReadOnly: true })
59
+ this.addRequestContextMetaConfig('reportCounter', { sandboxReadOnly: true })
60
+ this.addRequestContextMetaConfig('startTimestamp', { sandboxReadOnly: true })
61
+ this.addRequestContextMetaConfig('logs', { sandboxReadOnly: true })
62
+ this.addRequestContextMetaConfig('isChildRequest', { sandboxReadOnly: true })
63
+ this.addRequestContextMetaConfig('originalInputDataIsEmpty', { sandboxReadOnly: true })
64
+ this.addRequestContextMetaConfig('skipModificationDateUpdate', { sandboxHidden: true })
65
+
66
+ this._runInSandbox = runInSandbox(this)
67
+
68
+ const { compile: compileNone, execute: executeNone } = createNoneEngine()
69
+
70
+ this.extensionsManager.engines.push({
71
+ name: 'none',
72
+ compile: compileNone,
73
+ execute: executeNone
74
+ })
75
+
76
+ this.extensionsManager.recipes.push({
77
+ name: 'html',
78
+ execute: htmlRecipe
79
+ })
80
+
81
+ await this.initializeListeners.fire()
82
+
83
+ this._initialized = true
84
+ }
85
+
86
+ /**
87
+ * @public
88
+ */
89
+ addRequestContextMetaConfig (property, options) {
90
+ this._requestContextMetaConfigCollection.set(property, options)
91
+ }
92
+
93
+ /**
94
+ * @public
95
+ */
96
+ getRequestContextMetaConfig (property) {
97
+ if (property === undefined) {
98
+ const all = {}
99
+
100
+ for (const [key, value] of this._requestContextMetaConfigCollection.entries()) {
101
+ all[key] = value
102
+ }
103
+
104
+ return all
105
+ }
106
+
107
+ return this._requestContextMetaConfigCollection.get(property)
108
+ }
109
+
110
+ extendProxy (registrationFn) {
111
+ this._proxyRegistrationFns.push(registrationFn)
112
+ }
113
+
114
+ createProxy ({ req, runInSandbox, context, getTopLevelFunctions, safeRequire }) {
115
+ const proxyInstance = {}
116
+ for (const fn of this._proxyRegistrationFns) {
117
+ fn(proxyInstance, req, {
118
+ runInSandbox,
119
+ context,
120
+ getTopLevelFunctions,
121
+ safeRequire
122
+ })
123
+ }
124
+ return proxyInstance
125
+ }
126
+
127
+ render (req, parentReq) {
128
+ return this._render(req, parentReq)
129
+ }
130
+
131
+ async executeMainAction (actionName, data, req) {
132
+ await this.beforeMainActionListeners.fire(actionName, data, req)
133
+ return this._executeMain(actionName, data, req)
134
+ }
135
+
136
+ async runInSandbox ({
137
+ manager,
138
+ context,
139
+ userCode,
140
+ executionFn,
141
+ onRequire,
142
+ propertiesConfig,
143
+ currentPath,
144
+ errorLineNumberOffset
145
+ }, req) {
146
+ return this._runInSandbox({
147
+ manager,
148
+ context,
149
+ userCode,
150
+ executionFn,
151
+ onRequire,
152
+ propertiesConfig,
153
+ currentPath,
154
+ errorLineNumberOffset
155
+ }, req)
156
+ }
157
+
158
+ registerWorkerAction (actionName, fn) {
159
+ this._workerActions.set(actionName, fn)
160
+ }
161
+
162
+ async executeWorkerAction (actionName, data, req) {
163
+ const action = this._workerActions.get(actionName)
164
+ if (!action) {
165
+ throw new Error(`Worker action ${actionName} not registered`)
166
+ }
167
+ return action(data, req)
168
+ }
169
+
170
+ _registerRenderAction () {
171
+ this.registerWorkerAction('render', async (data, req) => {
172
+ const res = await this.render(req)
173
+
174
+ const sharedBuf = new SharedArrayBuffer(res.content.byteLength)
175
+ const buf = Buffer.from(sharedBuf)
176
+
177
+ res.content.copy(buf)
178
+
179
+ return {
180
+ meta: res.meta,
181
+ content: buf
182
+ }
183
+ })
184
+ }
185
+
186
+ async close () {
187
+ this.logger.debug('Closing jsreport worker')
188
+ return this.closeListeners.fire()
189
+ }
190
+ }
191
+
192
+ module.exports = WorkerReporter
@@ -5,9 +5,11 @@ const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz', 10)
5
5
 
6
6
  module.exports = (reporter) => {
7
7
  return ({
8
+ manager = {},
8
9
  context,
9
10
  userCode,
10
11
  executionFn,
12
+ currentPath,
11
13
  onRequire,
12
14
  propertiesConfig,
13
15
  errorLineNumberOffset = 0
@@ -25,14 +27,14 @@ module.exports = (reporter) => {
25
27
  context.__topLevelFunctions = {}
26
28
  context.__handleError = (err) => handleError(reporter, err)
27
29
 
28
- const { run, restore, sandbox, safeRequire } = safeSandbox(context, {
30
+ const { run, restore, contextifyValue, decontextifyValue, unproxyValue, sandbox, safeRequire } = safeSandbox(context, {
29
31
  onLog: (log) => {
30
32
  reporter.logger[log.level](log.message, { ...req, timestamp: log.timestamp })
31
33
  },
32
34
  formatError: (error, moduleName) => {
33
35
  error.message += ` To be able to require custom modules you need to add to configuration { "allowLocalFilesAccess": true } or enable just specific module using { sandbox: { allowedModules": ["${moduleName}"] }`
34
36
  },
35
- modulesCache: reporter.requestModulesCache.get(req.context.id),
37
+ modulesCache: reporter.requestModulesCache.get(req.context.rootId),
36
38
  globalModules: reporter.options.sandbox.nativeModules || [],
37
39
  allowedModules: reporter.options.sandbox.allowedModules,
38
40
  propertiesConfig,
@@ -59,8 +61,16 @@ module.exports = (reporter) => {
59
61
  })
60
62
 
61
63
  jsreportProxy = reporter.createProxy({ req, runInSandbox: run, context: sandbox, getTopLevelFunctions, safeRequire })
64
+ jsreportProxy.currentPath = currentPath
62
65
 
63
- sandbox.__restore = restore
66
+ // NOTE: it is important that cleanup, restore methods are not called from a function attached to the
67
+ // sandbox, because the arguments and return value of such function call will be sandboxed again, to solve this
68
+ // we don't attach these methods to the sandbox, and instead share them through a "manager" object that should
69
+ // be passed in options
70
+ manager.restore = restore
71
+ manager.contextifyValue = contextifyValue
72
+ manager.decontextifyValue = decontextifyValue
73
+ manager.unproxyValue = unproxyValue
64
74
 
65
75
  const functionNames = getTopLevelFunctions(userCode)
66
76
  const functionsCode = `return {${functionNames.map(h => `"${h}": ${h}`).join(',')}}`
@@ -72,7 +82,6 @@ module.exports = (reporter) => {
72
82
  },
73
83
  require,
74
84
  console,
75
- restore: __restore,
76
85
  context: this
77
86
  })).catch(__handleError);`
78
87