@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,64 +1,64 @@
1
- const extend = require('node.extend.without.arrays')
2
- const omit = require('lodash.omit')
3
-
4
- module.exports = (obj, parent) => {
5
- if (parent && !parent.__isJsreportRequest__) {
6
- throw new Error('Invalid parent request passed')
7
- }
8
-
9
- const request = Object.create({}, {
10
- __isJsreportRequest__: {
11
- value: true,
12
- writable: false,
13
- configurable: false,
14
- enumerable: false
15
- }
16
- })
17
-
18
- request.template = extend(true, {}, obj.template)
19
-
20
- if (parent) {
21
- request.context = Object.assign({}, request.context, omit(parent.context, ['id', 'logs', 'systemHelpers']))
22
- request.context.isChildRequest = true
23
- request.options = Object.assign({}, request.options, parent.options)
24
-
25
- if (parent.data) {
26
- const dataInput = normalizeJSONData(parent.data)
27
- request.data = Object.assign(Array.isArray(dataInput) ? [] : {}, dataInput)
28
- }
29
- }
30
-
31
- request.options = extend(true, {}, request.options, obj.options)
32
- request.context = extend(true, {}, request.context, obj.context)
33
- request.context.shared = extend(true, {}, request.context.shared)
34
-
35
- if (obj.data) {
36
- const dataInput = normalizeJSONData(obj.data)
37
- request.data = Object.assign(Array.isArray(dataInput) ? [] : {}, request.data, dataInput)
38
-
39
- // don't override value if it was already set by caller
40
- if (obj.context == null || obj.context.originalInputDataIsEmpty == null) {
41
- request.context.originalInputDataIsEmpty = false
42
- }
43
- } else if (!parent) {
44
- // don't override value if it was already set by caller
45
- if (obj.context == null || obj.context.originalInputDataIsEmpty == null) {
46
- request.context.originalInputDataIsEmpty = true
47
- }
48
- }
49
-
50
- // initialize data if it is empty
51
- if (!request.data) {
52
- request.data = {}
53
- }
54
-
55
- return request
56
- }
57
-
58
- function normalizeJSONData (data) {
59
- if (typeof data === 'string') {
60
- return JSON.parse(data)
61
- }
62
-
63
- return data
64
- }
1
+ const extend = require('node.extend.without.arrays')
2
+ const omit = require('lodash.omit')
3
+
4
+ module.exports = (obj, parent) => {
5
+ if (parent && !parent.__isJsreportRequest__) {
6
+ throw new Error('Invalid parent request passed')
7
+ }
8
+
9
+ const request = Object.create({}, {
10
+ __isJsreportRequest__: {
11
+ value: true,
12
+ writable: false,
13
+ configurable: false,
14
+ enumerable: false
15
+ }
16
+ })
17
+
18
+ request.template = extend(true, {}, obj.template)
19
+
20
+ if (parent) {
21
+ request.context = Object.assign({}, request.context, omit(parent.context, ['id', 'logs']))
22
+ request.context.isChildRequest = true
23
+ request.options = Object.assign({}, request.options, parent.options)
24
+
25
+ if (parent.data) {
26
+ const dataInput = normalizeJSONData(parent.data)
27
+ request.data = Object.assign(Array.isArray(dataInput) ? [] : {}, dataInput)
28
+ }
29
+ }
30
+
31
+ request.options = extend(true, {}, request.options, obj.options)
32
+ request.context = extend(true, {}, request.context, obj.context)
33
+ request.context.shared = extend(true, {}, request.context.shared)
34
+
35
+ if (obj.data) {
36
+ const dataInput = normalizeJSONData(obj.data)
37
+ request.data = Object.assign(Array.isArray(dataInput) ? [] : {}, request.data, dataInput)
38
+
39
+ // don't override value if it was already set by caller
40
+ if (obj.context == null || obj.context.originalInputDataIsEmpty == null) {
41
+ request.context.originalInputDataIsEmpty = false
42
+ }
43
+ } else if (!parent) {
44
+ // don't override value if it was already set by caller
45
+ if (obj.context == null || obj.context.originalInputDataIsEmpty == null) {
46
+ request.context.originalInputDataIsEmpty = true
47
+ }
48
+ }
49
+
50
+ // initialize data if it is empty
51
+ if (!request.data) {
52
+ request.data = {}
53
+ }
54
+
55
+ return request
56
+ }
57
+
58
+ function normalizeJSONData (data) {
59
+ if (typeof data === 'string') {
60
+ return JSON.parse(data)
61
+ }
62
+
63
+ return data
64
+ }
@@ -1,81 +1,81 @@
1
- const path = require('path')
2
- const fs = require('fs')
3
- const fsAsync = require('fs/promises')
4
- const { v4: uuidv4 } = require('uuid')
5
-
6
- module.exports.ensureTempDirectoryExists = async function (tempDirectory) {
7
- await fsAsync.mkdir(tempDirectory, {
8
- recursive: true
9
- })
10
-
11
- return {
12
- directoryPath: tempDirectory
13
- }
14
- }
15
-
16
- module.exports.readTempFile = async function readTempFile (tempDirectory, filename, opts = {}) {
17
- const pathToFile = path.join(tempDirectory, filename)
18
-
19
- const content = await fsAsync.readFile(pathToFile, opts)
20
-
21
- return {
22
- pathToFile,
23
- filename,
24
- content
25
- }
26
- }
27
-
28
- module.exports.readTempFileStream = async function readTempFileStream (tempDirectory, filename, opts = {}) {
29
- const pathToFile = path.join(tempDirectory, filename)
30
-
31
- return new Promise((resolve) => {
32
- const stream = fs.createReadStream(pathToFile, opts)
33
-
34
- resolve({
35
- pathToFile,
36
- filename,
37
- stream
38
- })
39
- })
40
- }
41
-
42
- module.exports.writeTempFile = async function writeTempFile (tempDirectory, filenameFn, content, opts = {}) {
43
- return writeFile(tempDirectory, filenameFn, content, opts)
44
- }
45
-
46
- module.exports.writeTempFileStream = async function writeTempFileStream (tempDirectory, filenameFn, opts = {}) {
47
- return writeFile(tempDirectory, filenameFn, undefined, opts, true)
48
- }
49
-
50
- async function writeFile (tempDirectory, filenameFn, content, opts, asStream = false) {
51
- const filename = filenameFn(uuidv4())
52
-
53
- if (filename == null || filename === '') {
54
- throw new Error('No valid filename was returned from filenameFn')
55
- }
56
-
57
- const pathToFile = path.join(tempDirectory, filename)
58
-
59
- await fsAsync.mkdir(tempDirectory, {
60
- recursive: true
61
- })
62
-
63
- if (asStream === true) {
64
- return new Promise((resolve) => {
65
- const stream = fs.createWriteStream(pathToFile, opts)
66
-
67
- resolve({
68
- pathToFile,
69
- filename,
70
- stream
71
- })
72
- })
73
- } else {
74
- await fsAsync.writeFile(pathToFile, content, opts)
75
-
76
- return {
77
- pathToFile,
78
- filename
79
- }
80
- }
81
- }
1
+ const path = require('path')
2
+ const fs = require('fs')
3
+ const fsAsync = require('fs/promises')
4
+ const { v4: uuidv4 } = require('uuid')
5
+
6
+ module.exports.ensureTempDirectoryExists = async function (tempDirectory) {
7
+ await fsAsync.mkdir(tempDirectory, {
8
+ recursive: true
9
+ })
10
+
11
+ return {
12
+ directoryPath: tempDirectory
13
+ }
14
+ }
15
+
16
+ module.exports.readTempFile = async function readTempFile (tempDirectory, filename, opts = {}) {
17
+ const pathToFile = path.join(tempDirectory, filename)
18
+
19
+ const content = await fsAsync.readFile(pathToFile, opts)
20
+
21
+ return {
22
+ pathToFile,
23
+ filename,
24
+ content
25
+ }
26
+ }
27
+
28
+ module.exports.readTempFileStream = async function readTempFileStream (tempDirectory, filename, opts = {}) {
29
+ const pathToFile = path.join(tempDirectory, filename)
30
+
31
+ return new Promise((resolve) => {
32
+ const stream = fs.createReadStream(pathToFile, opts)
33
+
34
+ resolve({
35
+ pathToFile,
36
+ filename,
37
+ stream
38
+ })
39
+ })
40
+ }
41
+
42
+ module.exports.writeTempFile = async function writeTempFile (tempDirectory, filenameFn, content, opts = {}) {
43
+ return writeFile(tempDirectory, filenameFn, content, opts)
44
+ }
45
+
46
+ module.exports.writeTempFileStream = async function writeTempFileStream (tempDirectory, filenameFn, opts = {}) {
47
+ return writeFile(tempDirectory, filenameFn, undefined, opts, true)
48
+ }
49
+
50
+ async function writeFile (tempDirectory, filenameFn, content, opts, asStream = false) {
51
+ const filename = filenameFn(uuidv4())
52
+
53
+ if (filename == null || filename === '') {
54
+ throw new Error('No valid filename was returned from filenameFn')
55
+ }
56
+
57
+ const pathToFile = path.join(tempDirectory, filename)
58
+
59
+ await fsAsync.mkdir(tempDirectory, {
60
+ recursive: true
61
+ })
62
+
63
+ if (asStream === true) {
64
+ return new Promise((resolve) => {
65
+ const stream = fs.createWriteStream(pathToFile, opts)
66
+
67
+ resolve({
68
+ pathToFile,
69
+ filename,
70
+ stream
71
+ })
72
+ })
73
+ } else {
74
+ await fsAsync.writeFile(pathToFile, content, opts)
75
+
76
+ return {
77
+ pathToFile,
78
+ filename
79
+ }
80
+ }
81
+ }
@@ -1,82 +1,82 @@
1
-
2
- module.exports = (reporter) => {
3
- return {
4
- resolveTemplate: (req) => resolveTemplate(reporter, req)
5
- }
6
- }
7
-
8
- async function resolveTemplate (reporter, req) {
9
- let queryResult
10
-
11
- if (req.template._id) {
12
- queryResult = {
13
- query: { _id: req.template._id },
14
- meta: { field: '_id', value: req.template._id }
15
- }
16
- } else if (req.template.shortid) {
17
- queryResult = {
18
- query: { shortid: req.template.shortid },
19
- meta: { field: 'shortid', value: req.template.shortid }
20
- }
21
- }
22
-
23
- const meta = {}
24
- let templates = []
25
-
26
- if (queryResult) {
27
- meta.field = queryResult.meta.field
28
- meta.value = queryResult.meta.value
29
- templates = await reporter.documentStore.collection('templates').find(queryResult.query, req)
30
- } else if (req.template.name) {
31
- const nameIsPath = req.template.name.indexOf('/') !== -1
32
-
33
- meta.field = 'name'
34
- meta.value = req.template.name
35
-
36
- if (!req.template.name.startsWith('/') && nameIsPath && !req.context.currentFolderPath) {
37
- throw reporter.createError('Invalid template path, path should be absolute and start with "/"', {
38
- statusCode: 400,
39
- weak: true
40
- })
41
- }
42
-
43
- const pathParts = req.template.name.split('/').filter((p) => p)
44
-
45
- if (pathParts.length === 0) {
46
- throw reporter.createError('Invalid template path,', {
47
- statusCode: 400,
48
- weak: true
49
- })
50
- }
51
-
52
- if (!nameIsPath) {
53
- // if name is not path do global search by name (with no folder).
54
- // since template name resolution here does not support relative syntax we should not run
55
- // resolveEntityFromPath if the name is not path
56
- templates = await reporter.documentStore.collection('templates').find({
57
- name: req.template.name
58
- }, req)
59
- } else {
60
- const result = await reporter.folders.resolveEntityFromPath(req.template.name, 'templates', req)
61
-
62
- if (result) {
63
- templates = [result.entity]
64
- }
65
- }
66
- }
67
-
68
- let template
69
-
70
- if (templates.length > 1) {
71
- throw reporter.createError(`Duplicated templates found for query ${meta.field}: ${meta.value}`, {
72
- statusCode: 400,
73
- weak: true
74
- })
75
- }
76
-
77
- if (templates.length === 1) {
78
- template = templates[0]
79
- }
80
-
81
- return template
82
- }
1
+
2
+ module.exports = (reporter) => {
3
+ return {
4
+ resolveTemplate: (req) => resolveTemplate(reporter, req)
5
+ }
6
+ }
7
+
8
+ async function resolveTemplate (reporter, req) {
9
+ let queryResult
10
+
11
+ if (req.template._id) {
12
+ queryResult = {
13
+ query: { _id: req.template._id },
14
+ meta: { field: '_id', value: req.template._id }
15
+ }
16
+ } else if (req.template.shortid) {
17
+ queryResult = {
18
+ query: { shortid: req.template.shortid },
19
+ meta: { field: 'shortid', value: req.template.shortid }
20
+ }
21
+ }
22
+
23
+ const meta = {}
24
+ let templates = []
25
+
26
+ if (queryResult) {
27
+ meta.field = queryResult.meta.field
28
+ meta.value = queryResult.meta.value
29
+ templates = await reporter.documentStore.collection('templates').find(queryResult.query, req)
30
+ } else if (req.template.name) {
31
+ const nameIsPath = req.template.name.indexOf('/') !== -1
32
+
33
+ meta.field = 'name'
34
+ meta.value = req.template.name
35
+
36
+ if (!req.template.name.startsWith('/') && nameIsPath && !req.context.currentFolderPath) {
37
+ throw reporter.createError('Invalid template path, path should be absolute and start with "/"', {
38
+ statusCode: 400,
39
+ weak: true
40
+ })
41
+ }
42
+
43
+ const pathParts = req.template.name.split('/').filter((p) => p)
44
+
45
+ if (pathParts.length === 0) {
46
+ throw reporter.createError('Invalid template path,', {
47
+ statusCode: 400,
48
+ weak: true
49
+ })
50
+ }
51
+
52
+ if (!nameIsPath) {
53
+ // if name is not path do global search by name (with no folder).
54
+ // since template name resolution here does not support relative syntax we should not run
55
+ // resolveEntityFromPath if the name is not path
56
+ templates = await reporter.documentStore.collection('templates').find({
57
+ name: req.template.name
58
+ }, req)
59
+ } else {
60
+ const result = await reporter.folders.resolveEntityFromPath(req.template.name, 'templates', req)
61
+
62
+ if (result) {
63
+ templates = [result.entity]
64
+ }
65
+ }
66
+ }
67
+
68
+ let template
69
+
70
+ if (templates.length > 1) {
71
+ throw reporter.createError(`Duplicated templates found for query ${meta.field}: ${meta.value}`, {
72
+ statusCode: 400,
73
+ weak: true
74
+ })
75
+ }
76
+
77
+ if (templates.length === 1) {
78
+ template = templates[0]
79
+ }
80
+
81
+ return template
82
+ }
@@ -1,33 +1,33 @@
1
- /* eslint-disable no-unused-vars */
2
- async function module (moduleName) {
3
- const jsreport = require('jsreport-proxy')
4
- return jsreport.module(moduleName)
5
- }
6
-
7
- function toJS (data) {
8
- function jsStringEscape (string) {
9
- return ('' + string).replace(/["'\\\n\r\u2028\u2029]/g, function (character) {
10
- // Escape all characters not included in SingleStringCharacters and
11
- // DoubleStringCharacters on
12
- // http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4
13
- switch (character) {
14
- case '"':
15
- case "'":
16
- case '\\':
17
- return '\\' + character
18
- // Four possible LineTerminator characters need to be escaped:
19
- case '\n':
20
- return '\\n'
21
- case '\r':
22
- return '\\r'
23
- case '\u2028':
24
- return '\\u2028'
25
- case '\u2029':
26
- return '\\u2029'
27
- }
28
- })
29
- }
30
-
31
- const validDataStr = jsStringEscape(JSON.stringify(data))
32
- return `JSON.parse('${validDataStr}')`
33
- }
1
+ /* eslint-disable no-unused-vars */
2
+ async function module (moduleName) {
3
+ const jsreport = require('jsreport-proxy')
4
+ return jsreport.module(moduleName)
5
+ }
6
+
7
+ function toJS (data) {
8
+ function jsStringEscape (string) {
9
+ return ('' + string).replace(/["'\\\n\r\u2028\u2029]/g, function (character) {
10
+ // Escape all characters not included in SingleStringCharacters and
11
+ // DoubleStringCharacters on
12
+ // http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4
13
+ switch (character) {
14
+ case '"':
15
+ case "'":
16
+ case '\\':
17
+ return '\\' + character
18
+ // Four possible LineTerminator characters need to be escaped:
19
+ case '\n':
20
+ return '\\n'
21
+ case '\r':
22
+ return '\\r'
23
+ case '\u2028':
24
+ return '\\u2028'
25
+ case '\u2029':
26
+ return '\\u2029'
27
+ }
28
+ })
29
+ }
30
+
31
+ const validDataStr = jsStringEscape(JSON.stringify(data))
32
+ return `JSON.parse('${validDataStr}')`
33
+ }
@@ -1,34 +1,34 @@
1
- module.exports = (executeMainAction) => {
2
- return {
3
- async read (blobName, req) {
4
- const r = await executeMainAction('blobStorage.read', {
5
- blobName
6
- }, req)
7
- return Buffer.from(r, 'base64')
8
- },
9
-
10
- write (blobName, content, req) {
11
- return executeMainAction('blobStorage.write', {
12
- blobName,
13
- content: Buffer.from(content).toString('base64')
14
- }, req)
15
- },
16
-
17
- remove (blobName, req) {
18
- return executeMainAction('blobStorage.remove', {
19
- blobName
20
- }, req)
21
- },
22
-
23
- append (blobName, content, req) {
24
- return executeMainAction('blobStorage.append', {
25
- blobName,
26
- content: Buffer.from(content).toString('base64')
27
- }, req)
28
- },
29
-
30
- init () {
31
-
32
- }
33
- }
34
- }
1
+ module.exports = (executeMainAction) => {
2
+ return {
3
+ async read (blobName, req) {
4
+ const r = await executeMainAction('blobStorage.read', {
5
+ blobName
6
+ }, req)
7
+ return Buffer.from(r, 'base64')
8
+ },
9
+
10
+ write (blobName, content, req) {
11
+ return executeMainAction('blobStorage.write', {
12
+ blobName,
13
+ content: Buffer.from(content).toString('base64')
14
+ }, req)
15
+ },
16
+
17
+ remove (blobName, req) {
18
+ return executeMainAction('blobStorage.remove', {
19
+ blobName
20
+ }, req)
21
+ },
22
+
23
+ append (blobName, content, req) {
24
+ return executeMainAction('blobStorage.append', {
25
+ blobName,
26
+ content: Buffer.from(content).toString('base64')
27
+ }, req)
28
+ },
29
+
30
+ init () {
31
+
32
+ }
33
+ }
34
+ }