@jsreport/jsreport-core 3.1.2-test.2 → 3.2.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 (79) 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 +244 -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 +91 -91
  26. package/lib/main/optionsLoad.js +237 -237
  27. package/lib/main/optionsSchema.js +237 -237
  28. package/lib/main/reporter.js +574 -579
  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 -169
  53. package/lib/shared/normalizeMetaFromLogs.js +30 -30
  54. package/lib/shared/reporter.js +128 -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 +239 -207
  66. package/lib/worker/render/htmlRecipe.js +10 -10
  67. package/lib/worker/render/moduleHelper.js +45 -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 +202 -205
  71. package/lib/worker/render/resolveReferences.js +60 -60
  72. package/lib/worker/reporter.js +192 -191
  73. package/lib/worker/sandbox/runInSandbox.js +16 -9
  74. package/lib/worker/sandbox/safeSandbox.js +828 -828
  75. package/lib/worker/templates.js +80 -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,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
+ }