@jsreport/jsreport-core 3.0.1 → 3.1.2-test.2

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 (79) 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/reporter.js +579 -578
  29. package/lib/main/schemaValidator.js +252 -252
  30. package/lib/main/settings.js +154 -154
  31. package/lib/main/store/checkDuplicatedId.js +27 -27
  32. package/lib/main/store/collection.js +329 -329
  33. package/lib/main/store/documentStore.js +469 -469
  34. package/lib/main/store/mainActions.js +28 -28
  35. package/lib/main/store/memoryStoreProvider.js +99 -99
  36. package/lib/main/store/queue.js +48 -48
  37. package/lib/main/store/referenceUtils.js +251 -251
  38. package/lib/main/store/setupValidateId.js +43 -43
  39. package/lib/main/store/setupValidateShortid.js +71 -71
  40. package/lib/main/store/transaction.js +69 -69
  41. package/lib/main/store/typeUtils.js +180 -180
  42. package/lib/main/templates.js +34 -34
  43. package/lib/main/validateEntityName.js +62 -62
  44. package/lib/shared/createError.js +36 -36
  45. package/lib/shared/encryption.js +114 -114
  46. package/lib/shared/folders/index.js +11 -11
  47. package/lib/shared/folders/normalizeEntityPath.js +15 -15
  48. package/lib/shared/folders/resolveEntityFromPath.js +88 -88
  49. package/lib/shared/folders/resolveEntityPath.js +46 -46
  50. package/lib/shared/folders/resolveFolderFromPath.js +38 -38
  51. package/lib/shared/generateRequestId.js +4 -4
  52. package/lib/shared/listenerCollection.js +169 -0
  53. package/lib/shared/normalizeMetaFromLogs.js +30 -30
  54. package/lib/shared/reporter.js +123 -123
  55. package/lib/shared/request.js +64 -64
  56. package/lib/shared/tempFilesHandler.js +81 -81
  57. package/lib/shared/templates.js +82 -82
  58. package/lib/static/helpers.js +33 -33
  59. package/lib/worker/blobStorage.js +34 -34
  60. package/lib/worker/defaultProxyExtend.js +46 -46
  61. package/lib/worker/documentStore.js +49 -49
  62. package/lib/worker/extensionsManager.js +17 -17
  63. package/lib/worker/logger.js +48 -48
  64. package/lib/worker/render/diff.js +138 -138
  65. package/lib/worker/render/executeEngine.js +207 -200
  66. package/lib/worker/render/htmlRecipe.js +10 -10
  67. package/lib/worker/render/moduleHelper.js +43 -43
  68. package/lib/worker/render/noneEngine.js +12 -12
  69. package/lib/worker/render/profiler.js +158 -158
  70. package/lib/worker/render/render.js +205 -209
  71. package/lib/worker/render/resolveReferences.js +60 -60
  72. package/lib/worker/reporter.js +191 -187
  73. package/lib/worker/sandbox/runInSandbox.js +13 -4
  74. package/lib/worker/sandbox/safeSandbox.js +828 -822
  75. package/lib/worker/templates.js +78 -78
  76. package/lib/worker/workerHandler.js +54 -54
  77. package/package.json +92 -92
  78. package/test/blobStorage/common.js +21 -21
  79. package/test/store/common.js +1449 -1449
@@ -1,187 +1,191 @@
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.afterTemplatingEnginesExecutedListeners = this.createListenerCollection('afterTemplatingEnginesExecuted')
30
+ this.validateRenderListeners = this.createListenerCollection('validateRender')
31
+
32
+ this.extensionsManager = ExtensionsManager(this, extensionsDefs)
33
+
34
+ this.extendProxy((proxy, req) => defaultProxyExtend(this)(proxy, req))
35
+ this.beforeMainActionListeners = this.createListenerCollection('beforeMainAction')
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
+ manager,
137
+ context,
138
+ userCode,
139
+ executionFn,
140
+ onRequire,
141
+ propertiesConfig,
142
+ currentPath,
143
+ errorLineNumberOffset
144
+ }, req) {
145
+ return this._runInSandbox({
146
+ manager,
147
+ context,
148
+ userCode,
149
+ executionFn,
150
+ onRequire,
151
+ propertiesConfig,
152
+ currentPath,
153
+ errorLineNumberOffset
154
+ }, req)
155
+ }
156
+
157
+ registerWorkerAction (actionName, fn) {
158
+ this._workerActions.set(actionName, fn)
159
+ }
160
+
161
+ async executeWorkerAction (actionName, data, req) {
162
+ const action = this._workerActions.get(actionName)
163
+ if (!action) {
164
+ throw new Error(`Worker action ${actionName} not registered`)
165
+ }
166
+ return action(data, req)
167
+ }
168
+
169
+ _registerRenderAction () {
170
+ this.registerWorkerAction('render', async (data, req) => {
171
+ const res = await this.render(req)
172
+
173
+ const sharedBuf = new SharedArrayBuffer(res.content.byteLength)
174
+ const buf = Buffer.from(sharedBuf)
175
+
176
+ res.content.copy(buf)
177
+
178
+ return {
179
+ meta: res.meta,
180
+ content: buf
181
+ }
182
+ })
183
+ }
184
+
185
+ async close () {
186
+ this.logger.debug('Closing jsreport worker')
187
+ return this.closeListeners.fire()
188
+ }
189
+ }
190
+
191
+ 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