@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,237 +1,231 @@
1
- const path = require('path')
2
- const fs = require('fs')
3
- const extend = require('node.extend.without.arrays')
4
- const decamelize = require('decamelize')
5
- const nconf = require('nconf')
6
- const appRoot = require('app-root-path')
7
- const { ignoreInitialSchemaProperties } = require('./optionsSchema')
8
-
9
- const {
10
- getDefaultLoadConfig,
11
- getDefaultTempDirectory,
12
- getDefaultRootDirectory
13
- } = require('./defaults')
14
-
15
- /**
16
- * Initialize configuration options. This includes loading config files or initializing default config values
17
- */
18
- async function optionsLoad ({
19
- defaults,
20
- options,
21
- validator,
22
- onConfigLoaded
23
- }) {
24
- let shouldLoadExternalConfig = defaults.loadConfig
25
-
26
- if (options.loadConfig != null) {
27
- shouldLoadExternalConfig = options.loadConfig
28
- }
29
-
30
- if (shouldLoadExternalConfig == null) {
31
- shouldLoadExternalConfig = getDefaultLoadConfig()
32
- }
33
-
34
- let loadConfigResult
35
-
36
- if (shouldLoadExternalConfig) {
37
- loadConfigResult = await loadConfig(defaults, options)
38
- } else {
39
- loadConfigResult = await loadConfig(defaults, options, false)
40
- }
41
-
42
- const appliedConfigFile = loadConfigResult[1]
43
-
44
- options.loadConfig = shouldLoadExternalConfig
45
-
46
- // validating initial options at very first to ensure basic options are right
47
- // this makes afterConfigLoaded function be able to see sanitized values and let us
48
- // apply defaults later doing checks that expects the right value type
49
- const rootOptionsValidation = validator.validateRoot(options, {
50
- rootPrefix: 'rootOptions',
51
- ignore: ignoreInitialSchemaProperties
52
- })
53
-
54
- if (!rootOptionsValidation.valid) {
55
- throw new Error(`options contain values that does not match the defined base root schema. ${rootOptionsValidation.fullErrorMessage}`)
56
- }
57
-
58
- options.appDirectory = options.appDirectory || appRoot.toString()
59
-
60
- // if parentModuleDirectory is empty or null here we proceed with the fallback value to rootDirectory
61
- if (!options.parentModuleDirectory) {
62
- options.parentModuleDirectory = options.rootDirectory
63
- }
64
-
65
- options.extensions = options.extensions || {}
66
- options.logger = options.logger || {}
67
-
68
- if (onConfigLoaded != null) {
69
- await onConfigLoaded()
70
- }
71
-
72
- if (options.tempDirectory && !path.isAbsolute(options.tempDirectory)) {
73
- options.tempDirectory = path.join(options.rootDirectory, options.tempDirectory)
74
- }
75
-
76
- options.tempDirectory = options.tempDirectory || getDefaultTempDirectory()
77
- options.tempAutoCleanupDirectory = path.join(options.tempDirectory, 'autocleanup')
78
- options.tempCoreDirectory = path.join(options.tempDirectory, 'core')
79
- options.store = options.store || { provider: 'memory' }
80
-
81
- options.sandbox = options.sandbox || {}
82
- if (options.allowLocalFilesAccess === true) {
83
- options.sandbox.allowedModules = '*'
84
- }
85
- options.sandbox.nativeModules = options.sandbox.nativeModules || []
86
- options.sandbox.modules = options.sandbox.modules || []
87
- options.sandbox.allowedModules = options.sandbox.allowedModules || []
88
-
89
- if (!fs.existsSync(options.tempDirectory)) {
90
- fs.mkdirSync(options.tempDirectory, { recursive: true })
91
- }
92
-
93
- if (!fs.existsSync(options.tempAutoCleanupDirectory)) {
94
- fs.mkdirSync(options.tempAutoCleanupDirectory, { recursive: true })
95
- }
96
-
97
- if (!fs.existsSync(options.tempCoreDirectory)) {
98
- fs.mkdirSync(options.tempCoreDirectory, { recursive: true })
99
- }
100
-
101
- return appliedConfigFile
102
- }
103
-
104
- /**
105
- * Merge config values from arguments, environment variables, default passed to the constructor and configuration file
106
- */
107
- async function loadConfig (defaults, options, loadExternal = true) {
108
- let loadedOptions = {}
109
- // using clean instance of nconf, avoids sharing values between multiple instances of jsreport
110
- const nconfInstance = new nconf.Provider()
111
-
112
- let rootDirectory = options.rootDirectory || defaults.rootDirectory || getDefaultRootDirectory()
113
-
114
- if (options.rootDirectory) {
115
- loadedOptions.rootDirectory = options.rootDirectory
116
- }
117
-
118
- // we use `.defaults({ store: <value> }` because nconf has problems reading objects with `store`
119
- // property, nconf always take the value of `.store` instead of whole options object in that case
120
- // so we need to pass our object inside store property in order to be loaded correctly
121
- let nfn = nconfInstance.overrides({ store: options })
122
-
123
- let appliedConfigFile = null
124
-
125
- const makeTransform = ({ normalize, separator }) => (obj) => {
126
- let separators = !Array.isArray(separator) ? [separator] : separator
127
-
128
- separators = separators.join('')
129
-
130
- if (normalize === true && obj.key === 'extensions' && typeof obj.value === 'object') {
131
- Object.keys(obj.value).forEach((extensionKey) => {
132
- const realExtensionName = decamelize(extensionKey, '-')
133
- const currentValue = obj.value[extensionKey]
134
- delete obj.value[extensionKey]
135
-
136
- if (realExtensionName !== extensionKey && obj.value[realExtensionName]) {
137
- obj.value[realExtensionName] = extend(
138
- true,
139
- obj.value[realExtensionName],
140
- currentValue
141
- )
142
- } else {
143
- obj.value[realExtensionName] = currentValue
144
- }
145
- })
146
- } else if (!normalize && obj.key.startsWith('extensions')) {
147
- // the transform ensures that camelCase alias keys of extensions
148
- // are being loaded as decamelized keys, this is needed
149
- // in order to respect the order of configuration loading
150
- // for args and env config values
151
- const match = new RegExp(`extensions[${separators}](.[^${separators}]*)[${separators}]*.*`).exec(obj.key)
152
-
153
- if (!match) {
154
- return obj
155
- }
156
-
157
- if (match.length < 2) {
158
- throw new Error(`Wrong configuration value ${obj.key}`)
159
- }
160
-
161
- const realExtensionName = decamelize(match[1], '-')
162
- obj.key = obj.key.replace(match[1], realExtensionName)
163
- }
164
-
165
- return obj
166
- }
167
-
168
- if (loadExternal) {
169
- const separators = ['_', ':']
170
-
171
- nfn = nfn.argv({
172
- // we make a transform that just normalize keys,
173
- // because the transform for args receives single key "extensions" with
174
- // already parsed values of nested args
175
- // "--extensions.something.value = true", "--extensions.something2.value = true".
176
- // unlike the transform for env store which receives raw keys
177
- transform: makeTransform({ normalize: true })
178
- }).env({
179
- separator: ':',
180
- transform: makeTransform({ separator: separators })
181
- }).env({
182
- separator: '_',
183
- transform: makeTransform({ separator: separators })
184
- })
185
- }
186
-
187
- if (nfn.get('rootDirectory') != null) {
188
- rootDirectory = nfn.get('rootDirectory')
189
- }
190
-
191
- // the highest priority for applied config file has file specified using configFile option
192
- const configFileParam = nfn.get('configFile')
193
-
194
- if (configFileParam) {
195
- const configFilePath = path.isAbsolute(configFileParam) ? configFileParam : path.join(rootDirectory, configFileParam)
196
-
197
- if (!fs.existsSync(configFilePath)) {
198
- throw new Error('Config file ' + configFileParam + ' was not found.')
199
- }
200
-
201
- appliedConfigFile = configFileParam
202
-
203
- nfn.file({ file: configFilePath })
204
-
205
- if (nfn.get('rootDirectory') != null) {
206
- rootDirectory = nfn.get('rootDirectory')
207
- }
208
- }
209
-
210
- if (loadExternal) {
211
- // no config file applied so far, lets try to apply the default jsreport.config.json
212
- if (!appliedConfigFile) {
213
- if (fs.existsSync(path.join(rootDirectory, 'jsreport.config.json'))) {
214
- appliedConfigFile = 'jsreport.config.json'
215
- nfn.file({ file: path.join(rootDirectory, 'jsreport.config.json') })
216
-
217
- if (nfn.get('rootDirectory') != null) {
218
- rootDirectory = nfn.get('rootDirectory')
219
- }
220
- }
221
- }
222
- }
223
-
224
- // we pass a copy of defaults to avoid loosing the original
225
- // object values
226
- nfn.defaults({ store: extend(true, {}, defaults) })
227
-
228
- Object.assign(options, nconfInstance.get())
229
-
230
- loadedOptions = extend(true, {}, options, loadedOptions)
231
-
232
- options.rootDirectory = rootDirectory
233
-
234
- return [loadedOptions, appliedConfigFile]
235
- }
236
-
237
- module.exports = optionsLoad
1
+ const path = require('path')
2
+ const fs = require('fs')
3
+ const extend = require('node.extend.without.arrays')
4
+ const decamelize = require('decamelize')
5
+ const nconf = require('nconf')
6
+ const appRoot = require('app-root-path')
7
+ const { ignoreInitialSchemaProperties } = require('./optionsSchema')
8
+
9
+ const {
10
+ getDefaultLoadConfig,
11
+ getDefaultTempDirectory,
12
+ getDefaultRootDirectory
13
+ } = require('./defaults')
14
+
15
+ /**
16
+ * Initialize configuration options. This includes loading config files or initializing default config values
17
+ */
18
+ async function optionsLoad ({
19
+ defaults,
20
+ options,
21
+ validator,
22
+ onConfigLoaded
23
+ }) {
24
+ let shouldLoadExternalConfig = defaults.loadConfig
25
+
26
+ if (options.loadConfig != null) {
27
+ shouldLoadExternalConfig = options.loadConfig
28
+ }
29
+
30
+ if (shouldLoadExternalConfig == null) {
31
+ shouldLoadExternalConfig = getDefaultLoadConfig()
32
+ }
33
+
34
+ let loadConfigResult
35
+
36
+ if (shouldLoadExternalConfig) {
37
+ loadConfigResult = await loadConfig(defaults, options)
38
+ } else {
39
+ loadConfigResult = await loadConfig(defaults, options, false)
40
+ }
41
+
42
+ const appliedConfigFile = loadConfigResult[1]
43
+
44
+ options.loadConfig = shouldLoadExternalConfig
45
+
46
+ // validating initial options at very first to ensure basic options are right
47
+ // this makes afterConfigLoaded function be able to see sanitized values and let us
48
+ // apply defaults later doing checks that expects the right value type
49
+ const rootOptionsValidation = validator.validateRoot(options, {
50
+ rootPrefix: 'rootOptions',
51
+ ignore: ignoreInitialSchemaProperties
52
+ })
53
+
54
+ if (!rootOptionsValidation.valid) {
55
+ throw new Error(`options contain values that does not match the defined base root schema. ${rootOptionsValidation.fullErrorMessage}`)
56
+ }
57
+
58
+ options.appDirectory = options.appDirectory || appRoot.toString()
59
+
60
+ // if parentModuleDirectory is empty or null here we proceed with the fallback value to rootDirectory
61
+ if (!options.parentModuleDirectory) {
62
+ options.parentModuleDirectory = options.rootDirectory
63
+ }
64
+
65
+ options.extensions = options.extensions || {}
66
+ options.logger = options.logger || {}
67
+
68
+ if (onConfigLoaded != null) {
69
+ await onConfigLoaded()
70
+ }
71
+
72
+ if (options.tempDirectory && !path.isAbsolute(options.tempDirectory)) {
73
+ options.tempDirectory = path.join(options.rootDirectory, options.tempDirectory)
74
+ }
75
+
76
+ options.tempDirectory = options.tempDirectory || getDefaultTempDirectory()
77
+ options.tempAutoCleanupDirectory = path.join(options.tempDirectory, 'autocleanup')
78
+ options.tempCoreDirectory = path.join(options.tempDirectory, 'core')
79
+ options.store = options.store || { provider: 'memory' }
80
+
81
+ options.sandbox = options.sandbox || {}
82
+ if (options.allowLocalFilesAccess === true) {
83
+ options.sandbox.allowedModules = '*'
84
+ }
85
+ options.sandbox.nativeModules = options.sandbox.nativeModules || []
86
+ options.sandbox.modules = options.sandbox.modules || []
87
+ options.sandbox.allowedModules = options.sandbox.allowedModules || []
88
+
89
+ if (!fs.existsSync(options.tempDirectory)) {
90
+ fs.mkdirSync(options.tempDirectory, { recursive: true })
91
+ }
92
+
93
+ if (!fs.existsSync(options.tempAutoCleanupDirectory)) {
94
+ fs.mkdirSync(options.tempAutoCleanupDirectory, { recursive: true })
95
+ }
96
+
97
+ if (!fs.existsSync(options.tempCoreDirectory)) {
98
+ fs.mkdirSync(options.tempCoreDirectory, { recursive: true })
99
+ }
100
+
101
+ return appliedConfigFile
102
+ }
103
+
104
+ /**
105
+ * Merge config values from arguments, environment variables, default passed to the constructor and configuration file
106
+ */
107
+ async function loadConfig (defaults, options, loadExternal = true) {
108
+ let loadedOptions = {}
109
+ // using clean instance of nconf, avoids sharing values between multiple instances of jsreport
110
+ const nconfInstance = new nconf.Provider()
111
+
112
+ let rootDirectory = options.rootDirectory || defaults.rootDirectory || getDefaultRootDirectory()
113
+
114
+ if (options.rootDirectory) {
115
+ loadedOptions.rootDirectory = options.rootDirectory
116
+ }
117
+
118
+ // we use `.defaults({ store: <value> }` because nconf has problems reading objects with `store`
119
+ // property, nconf always take the value of `.store` instead of whole options object in that case
120
+ // so we need to pass our object inside store property in order to be loaded correctly
121
+ let nfn = nconfInstance.overrides({ store: options })
122
+
123
+ let appliedConfigFile = null
124
+
125
+ const makeTransform = ({ normalize, separator }) => (obj) => {
126
+ let separators = !Array.isArray(separator) ? [separator] : separator
127
+
128
+ separators = separators.join('')
129
+
130
+ if (normalize === true && obj.key === 'extensions' && typeof obj.value === 'object') {
131
+ Object.keys(obj.value).forEach((extensionKey) => {
132
+ const realExtensionName = decamelize(extensionKey, '-')
133
+ const currentValue = obj.value[extensionKey]
134
+ delete obj.value[extensionKey]
135
+
136
+ // the camelCase key version should already contain all merged values
137
+ // (from both the real extension name with "-" and camel case)
138
+ obj.value[realExtensionName] = currentValue
139
+ })
140
+ } else if (!normalize && obj.key.startsWith('extensions')) {
141
+ // the transform ensures that camelCase alias keys of extensions
142
+ // are being loaded as decamelized keys, this is needed
143
+ // in order to respect the order of configuration loading
144
+ // for args and env config values
145
+ const match = new RegExp(`extensions[${separators}](.[^${separators}]*)[${separators}]*.*`).exec(obj.key)
146
+
147
+ if (!match) {
148
+ return obj
149
+ }
150
+
151
+ if (match.length < 2) {
152
+ throw new Error(`Wrong configuration value ${obj.key}`)
153
+ }
154
+
155
+ const realExtensionName = decamelize(match[1], '-')
156
+ obj.key = obj.key.replace(match[1], realExtensionName)
157
+ }
158
+
159
+ return obj
160
+ }
161
+
162
+ if (loadExternal) {
163
+ const separators = ['_', ':']
164
+
165
+ nfn = nfn.argv({
166
+ // we make a transform that just normalize keys,
167
+ // because the transform for args receives single key "extensions" with
168
+ // already parsed values of nested args
169
+ // "--extensions.something.value = true", "--extensions.something2.value = true".
170
+ // unlike the transform for env store which receives raw keys
171
+ transform: makeTransform({ normalize: true })
172
+ }).env({
173
+ separator: ':',
174
+ transform: makeTransform({ separator: separators })
175
+ }).env({
176
+ separator: '_',
177
+ transform: makeTransform({ separator: separators })
178
+ })
179
+ }
180
+
181
+ if (nfn.get('rootDirectory') != null) {
182
+ rootDirectory = nfn.get('rootDirectory')
183
+ }
184
+
185
+ // the highest priority for applied config file has file specified using configFile option
186
+ const configFileParam = nfn.get('configFile')
187
+
188
+ if (configFileParam) {
189
+ const configFilePath = path.isAbsolute(configFileParam) ? configFileParam : path.join(rootDirectory, configFileParam)
190
+
191
+ if (!fs.existsSync(configFilePath)) {
192
+ throw new Error('Config file ' + configFileParam + ' was not found.')
193
+ }
194
+
195
+ appliedConfigFile = configFileParam
196
+
197
+ nfn.file({ file: configFilePath })
198
+
199
+ if (nfn.get('rootDirectory') != null) {
200
+ rootDirectory = nfn.get('rootDirectory')
201
+ }
202
+ }
203
+
204
+ if (loadExternal) {
205
+ // no config file applied so far, lets try to apply the default jsreport.config.json
206
+ if (!appliedConfigFile) {
207
+ if (fs.existsSync(path.join(rootDirectory, 'jsreport.config.json'))) {
208
+ appliedConfigFile = 'jsreport.config.json'
209
+ nfn.file({ file: path.join(rootDirectory, 'jsreport.config.json') })
210
+
211
+ if (nfn.get('rootDirectory') != null) {
212
+ rootDirectory = nfn.get('rootDirectory')
213
+ }
214
+ }
215
+ }
216
+ }
217
+
218
+ // we pass a copy of defaults to avoid loosing the original
219
+ // object values
220
+ nfn.defaults({ store: extend(true, {}, defaults) })
221
+
222
+ Object.assign(options, nconfInstance.get())
223
+
224
+ loadedOptions = extend(true, {}, options, loadedOptions)
225
+
226
+ options.rootDirectory = rootDirectory
227
+
228
+ return [loadedOptions, appliedConfigFile]
229
+ }
230
+
231
+ module.exports = optionsLoad