@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,230 +1,230 @@
1
- const Request = require('../../shared/request')
2
-
3
- module.exports = async (reporter) => {
4
- if (
5
- reporter.options.migrateResourcesToAssets === false ||
6
- reporter.documentStore.collection('scripts') == null ||
7
- reporter.documentStore.collection('data') == null
8
- ) {
9
- return
10
- }
11
-
12
- const migrated = await reporter.settings.findValue('core-migrated-resources')
13
-
14
- if (migrated) {
15
- return
16
- }
17
-
18
- const req = Request({})
19
- await reporter.documentStore.beginTransaction(req)
20
-
21
- try {
22
- const templateIds = await reporter.documentStore.collection('templates').find({}, { _id: 1 }, req)
23
-
24
- if (templateIds.length !== 0) {
25
- reporter.logger.debug('Running migration "resourcesToAssets"')
26
- }
27
-
28
- const templateToAssetResourcesMap = new Map()
29
- const dataToAssetMap = new Map()
30
- const dataEntitiesToRemove = []
31
-
32
- for (const templateId of templateIds) {
33
- const template = await reporter.documentStore.collection('templates').findOne({ _id: templateId._id }, req)
34
-
35
- if (template.resources == null) {
36
- continue
37
- }
38
-
39
- if (Array.isArray(template.resources.items)) {
40
- for (const dataItem of template.resources.items) {
41
- const dataEntity = await reporter.documentStore.collection('data').findOne({ shortid: dataItem.shortid }, req)
42
-
43
- if (dataEntity) {
44
- let newAsset
45
-
46
- if (dataToAssetMap.has(dataEntity._id)) {
47
- newAsset = dataToAssetMap.get(dataEntity._id)
48
- } else {
49
- const assetProps = {
50
- content: Buffer.from(dataEntity.dataJson || ''),
51
- folder: dataEntity.folder || null
52
- }
53
-
54
- if (dataEntity.readPermissions != null) {
55
- assetProps.readPermissions = dataEntity.readPermissions
56
- }
57
-
58
- if (dataEntity.editPermissions != null) {
59
- assetProps.editPermissions = dataEntity.editPermissions
60
- }
61
-
62
- newAsset = await insertUnique(reporter, 'assets', `${dataEntity.name}.json`, assetProps, req)
63
-
64
- dataToAssetMap.set(dataEntity._id, newAsset)
65
- }
66
-
67
- const assetResources = templateToAssetResourcesMap.get(template._id) || []
68
-
69
- assetResources.push({
70
- ...newAsset,
71
- originalName: dataEntity.name
72
- })
73
-
74
- templateToAssetResourcesMap.set(template._id, assetResources)
75
- dataEntitiesToRemove.push(dataEntity._id)
76
- }
77
- }
78
- }
79
-
80
- const templateAssetResources = templateToAssetResourcesMap.get(template._id) || []
81
-
82
- if (templateAssetResources.length > 0) {
83
- const scriptProps = {
84
- content: (
85
- `
86
- // THIS SCRIPT WAS GENERATED BY MIGRATION IN V3, IT PROVIDES BACKWARD COMPATIBILITY
87
- // WITH THE DEPRECATED jsreport-resources https://jsreport.net/learn/resources
88
- // THE RECOMMENDATION NOW IS TO USE jsreport-localization https://jsreport.net/learn/localization
89
- // SO WHEN YOU DECIDE TO USE jsreport-localization TO FULLY REPLACE THE jsreport-resources
90
- // JUST REMOVE THIS SCRIPT FROM YOUR TEMPLATE AND DELETE IT
91
- const jsreport = require('jsreport-proxy')
92
-
93
- async function beforeRender (req, res) {
94
- req.options.language = req.options.language || req.template.localization?.language
95
- const defaultLanguage = ${template.resources.defaultLanguage != null ? '\'' + template.resources.defaultLanguage + '\'' : 'undefined'}
96
- const assetsResources = [${templateAssetResources.map(a => `{ name: '${a.originalName}', shortid: '${a.shortid}' }`).join(', ')}]
97
-
98
- const resources = await Promise.all(assetsResources.map(async (r) => {
99
- const asset = await jsreport.documentStore.collection('assets').findOne({ shortid: r.shortid })
100
-
101
- if (asset == null) {
102
- throw new Error(\`Asset resources with shortid \${r.shortid} was not found (resource lookup)\`)
103
- }
104
-
105
- asset.resourceName = r.name
106
- asset.content = asset.content.toString()
107
-
108
- return asset
109
- }))
110
-
111
- resources.forEach((r) => {
112
- r.dataJson = r.content
113
- r.data = JSON.parse(r.content)
114
- })
115
-
116
- req.options.resources = resources
117
- req.data.$resources = resources
118
-
119
- const resourcesByName = {}
120
-
121
- resources.forEach((r) => {
122
- resourcesByName[r.resourceName] = r.data
123
- })
124
-
125
- req.options.resource = resourcesByName
126
- req.data.$resource = resourcesByName
127
-
128
- const isLocalizedRequest = req.options.language != null || defaultLanguage != null
129
-
130
- if (isLocalizedRequest) {
131
- let languageUsed
132
- let applicableResources = []
133
-
134
- if (req.options.language) {
135
- languageUsed = req.options.language
136
- applicableResources = resources.filter((r) => r.resourceName.startsWith(\`\${languageUsed}-\`))
137
- }
138
-
139
- if (!applicableResources.length && defaultLanguage) {
140
- languageUsed = defaultLanguage
141
- applicableResources = resources.filter((r) => r.resourceName.startsWith(\`\${languageUsed}-\`))
142
- }
143
-
144
- console.log(\`Found \${applicableResources.length} resources for language "\${languageUsed}"\`)
145
-
146
- req.options.localizedResources = applicableResources
147
- req.data.$localizedResources = applicableResources
148
-
149
- const localizedResourceByName = {}
150
-
151
- applicableResources.forEach((r) => {
152
- localizedResourceByName[r.resourceName.substring(\`\${languageUsed}-\`.length)] = r.data
153
- })
154
-
155
- req.options.localizedResource = applicableResources.length === 1 ? applicableResources[0].data : localizedResourceByName
156
- req.data.$localizedResource = req.options.localizedResource
157
- }
158
- }
159
- `
160
- ),
161
- folder: template.folder || null
162
- }
163
-
164
- if (template.readPermissions != null) {
165
- scriptProps.readPermissions = template.readPermissions
166
- }
167
-
168
- if (template.editPermissions != null) {
169
- scriptProps.editPermissions = template.editPermissions
170
- }
171
-
172
- const newScript = await insertUnique(reporter, 'scripts', `${template.name}_resources`, scriptProps, req)
173
-
174
- template.scripts = template.scripts || []
175
-
176
- template.scripts.unshift({
177
- shortid: newScript.shortid
178
- })
179
- }
180
-
181
- template.resources = null
182
-
183
- await reporter.documentStore.collection('templates').update({ _id: template._id }, { $set: template }, req)
184
- }
185
-
186
- for (const dataEntityId of dataEntitiesToRemove) {
187
- await reporter.documentStore.collection('data').remove({ _id: dataEntityId }, req)
188
- }
189
-
190
- if (templateIds.length !== 0) {
191
- reporter.logger.debug('Migration "resourcesToAssets" finished')
192
- }
193
-
194
- await reporter.documentStore.commitTransaction(req)
195
-
196
- await reporter.settings.addOrSet('core-migrated-resources', true)
197
- } catch (migrationErr) {
198
- await reporter.documentStore.rollbackTransaction(req)
199
-
200
- migrationErr.message = `Migration "resourcesToAssets" failed: ${migrationErr.message}`
201
-
202
- throw migrationErr
203
- }
204
- }
205
-
206
- async function insertUnique (reporter, collectionName, baseName, entity, req) {
207
- let newEntity
208
- let tryCount = 0
209
-
210
- while (newEntity == null) {
211
- try {
212
- const entityName = '_'.repeat(tryCount) + baseName
213
-
214
- newEntity = await reporter.documentStore.collection(collectionName).insert({
215
- ...entity,
216
- name: entityName
217
- }, req)
218
-
219
- return newEntity
220
- } catch (insertError) {
221
- tryCount++
222
-
223
- if (insertError.code === 'DUPLICATED_ENTITY') {
224
- continue
225
- } else {
226
- throw insertError
227
- }
228
- }
229
- }
230
- }
1
+ const Request = require('../../shared/request')
2
+
3
+ module.exports = async (reporter) => {
4
+ if (
5
+ reporter.options.migrateResourcesToAssets === false ||
6
+ reporter.documentStore.collection('scripts') == null ||
7
+ reporter.documentStore.collection('data') == null
8
+ ) {
9
+ return
10
+ }
11
+
12
+ const migrated = await reporter.settings.findValue('core-migrated-resources')
13
+
14
+ if (migrated) {
15
+ return
16
+ }
17
+
18
+ const req = Request({})
19
+ await reporter.documentStore.beginTransaction(req)
20
+
21
+ try {
22
+ const templateIds = await reporter.documentStore.collection('templates').find({}, { _id: 1 }, req)
23
+
24
+ if (templateIds.length !== 0) {
25
+ reporter.logger.debug('Running migration "resourcesToAssets"')
26
+ }
27
+
28
+ const templateToAssetResourcesMap = new Map()
29
+ const dataToAssetMap = new Map()
30
+ const dataEntitiesToRemove = []
31
+
32
+ for (const templateId of templateIds) {
33
+ const template = await reporter.documentStore.collection('templates').findOne({ _id: templateId._id }, req)
34
+
35
+ if (template.resources == null) {
36
+ continue
37
+ }
38
+
39
+ if (Array.isArray(template.resources.items)) {
40
+ for (const dataItem of template.resources.items) {
41
+ const dataEntity = await reporter.documentStore.collection('data').findOne({ shortid: dataItem.shortid }, req)
42
+
43
+ if (dataEntity) {
44
+ let newAsset
45
+
46
+ if (dataToAssetMap.has(dataEntity._id)) {
47
+ newAsset = dataToAssetMap.get(dataEntity._id)
48
+ } else {
49
+ const assetProps = {
50
+ content: Buffer.from(dataEntity.dataJson || ''),
51
+ folder: dataEntity.folder || null
52
+ }
53
+
54
+ if (dataEntity.readPermissions != null) {
55
+ assetProps.readPermissions = dataEntity.readPermissions
56
+ }
57
+
58
+ if (dataEntity.editPermissions != null) {
59
+ assetProps.editPermissions = dataEntity.editPermissions
60
+ }
61
+
62
+ newAsset = await insertUnique(reporter, 'assets', `${dataEntity.name}.json`, assetProps, req)
63
+
64
+ dataToAssetMap.set(dataEntity._id, newAsset)
65
+ }
66
+
67
+ const assetResources = templateToAssetResourcesMap.get(template._id) || []
68
+
69
+ assetResources.push({
70
+ ...newAsset,
71
+ originalName: dataEntity.name
72
+ })
73
+
74
+ templateToAssetResourcesMap.set(template._id, assetResources)
75
+ dataEntitiesToRemove.push(dataEntity._id)
76
+ }
77
+ }
78
+ }
79
+
80
+ const templateAssetResources = templateToAssetResourcesMap.get(template._id) || []
81
+
82
+ if (templateAssetResources.length > 0) {
83
+ const scriptProps = {
84
+ content: (
85
+ `
86
+ // THIS SCRIPT WAS GENERATED BY MIGRATION IN V3, IT PROVIDES BACKWARD COMPATIBILITY
87
+ // WITH THE DEPRECATED jsreport-resources https://jsreport.net/learn/resources
88
+ // THE RECOMMENDATION NOW IS TO USE jsreport-localization https://jsreport.net/learn/localization
89
+ // SO WHEN YOU DECIDE TO USE jsreport-localization TO FULLY REPLACE THE jsreport-resources
90
+ // JUST REMOVE THIS SCRIPT FROM YOUR TEMPLATE AND DELETE IT
91
+ const jsreport = require('jsreport-proxy')
92
+
93
+ async function beforeRender (req, res) {
94
+ req.options.language = req.options.language || req.template.localization?.language
95
+ const defaultLanguage = ${template.resources.defaultLanguage != null ? '\'' + template.resources.defaultLanguage + '\'' : 'undefined'}
96
+ const assetsResources = [${templateAssetResources.map(a => `{ name: '${a.originalName}', shortid: '${a.shortid}' }`).join(', ')}]
97
+
98
+ const resources = await Promise.all(assetsResources.map(async (r) => {
99
+ const asset = await jsreport.documentStore.collection('assets').findOne({ shortid: r.shortid })
100
+
101
+ if (asset == null) {
102
+ throw new Error(\`Asset resources with shortid \${r.shortid} was not found (resource lookup)\`)
103
+ }
104
+
105
+ asset.resourceName = r.name
106
+ asset.content = asset.content.toString()
107
+
108
+ return asset
109
+ }))
110
+
111
+ resources.forEach((r) => {
112
+ r.dataJson = r.content
113
+ r.data = JSON.parse(r.content)
114
+ })
115
+
116
+ req.options.resources = resources
117
+ req.data.$resources = resources
118
+
119
+ const resourcesByName = {}
120
+
121
+ resources.forEach((r) => {
122
+ resourcesByName[r.resourceName] = r.data
123
+ })
124
+
125
+ req.options.resource = resourcesByName
126
+ req.data.$resource = resourcesByName
127
+
128
+ const isLocalizedRequest = req.options.language != null || defaultLanguage != null
129
+
130
+ if (isLocalizedRequest) {
131
+ let languageUsed
132
+ let applicableResources = []
133
+
134
+ if (req.options.language) {
135
+ languageUsed = req.options.language
136
+ applicableResources = resources.filter((r) => r.resourceName.startsWith(\`\${languageUsed}-\`))
137
+ }
138
+
139
+ if (!applicableResources.length && defaultLanguage) {
140
+ languageUsed = defaultLanguage
141
+ applicableResources = resources.filter((r) => r.resourceName.startsWith(\`\${languageUsed}-\`))
142
+ }
143
+
144
+ console.log(\`Found \${applicableResources.length} resources for language "\${languageUsed}"\`)
145
+
146
+ req.options.localizedResources = applicableResources
147
+ req.data.$localizedResources = applicableResources
148
+
149
+ const localizedResourceByName = {}
150
+
151
+ applicableResources.forEach((r) => {
152
+ localizedResourceByName[r.resourceName.substring(\`\${languageUsed}-\`.length)] = r.data
153
+ })
154
+
155
+ req.options.localizedResource = applicableResources.length === 1 ? applicableResources[0].data : localizedResourceByName
156
+ req.data.$localizedResource = req.options.localizedResource
157
+ }
158
+ }
159
+ `
160
+ ),
161
+ folder: template.folder || null
162
+ }
163
+
164
+ if (template.readPermissions != null) {
165
+ scriptProps.readPermissions = template.readPermissions
166
+ }
167
+
168
+ if (template.editPermissions != null) {
169
+ scriptProps.editPermissions = template.editPermissions
170
+ }
171
+
172
+ const newScript = await insertUnique(reporter, 'scripts', `${template.name}_resources`, scriptProps, req)
173
+
174
+ template.scripts = template.scripts || []
175
+
176
+ template.scripts.unshift({
177
+ shortid: newScript.shortid
178
+ })
179
+ }
180
+
181
+ template.resources = null
182
+
183
+ await reporter.documentStore.collection('templates').update({ _id: template._id }, { $set: template }, req)
184
+ }
185
+
186
+ for (const dataEntityId of dataEntitiesToRemove) {
187
+ await reporter.documentStore.collection('data').remove({ _id: dataEntityId }, req)
188
+ }
189
+
190
+ if (templateIds.length !== 0) {
191
+ reporter.logger.debug('Migration "resourcesToAssets" finished')
192
+ }
193
+
194
+ await reporter.documentStore.commitTransaction(req)
195
+
196
+ await reporter.settings.addOrSet('core-migrated-resources', true)
197
+ } catch (migrationErr) {
198
+ await reporter.documentStore.rollbackTransaction(req)
199
+
200
+ migrationErr.message = `Migration "resourcesToAssets" failed: ${migrationErr.message}`
201
+
202
+ throw migrationErr
203
+ }
204
+ }
205
+
206
+ async function insertUnique (reporter, collectionName, baseName, entity, req) {
207
+ let newEntity
208
+ let tryCount = 0
209
+
210
+ while (newEntity == null) {
211
+ try {
212
+ const entityName = '_'.repeat(tryCount) + baseName
213
+
214
+ newEntity = await reporter.documentStore.collection(collectionName).insert({
215
+ ...entity,
216
+ name: entityName
217
+ }, req)
218
+
219
+ return newEntity
220
+ } catch (insertError) {
221
+ tryCount++
222
+
223
+ if (insertError.code === 'DUPLICATED_ENTITY') {
224
+ continue
225
+ } else {
226
+ throw insertError
227
+ }
228
+ }
229
+ }
230
+ }