@jsreport/jsreport-core 3.12.0 → 4.0.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.
@@ -21,7 +21,7 @@ module.exports = function createRunInSandbox (reporter) {
21
21
  }, req) {
22
22
  let jsreportProxy = null
23
23
 
24
- // we use dynamic name because of the potential nested vm2 execution in the jsreportProxy.assets.require
24
+ // we use dynamic name because of the potential nested vm execution in the jsreportProxy.assets.require
25
25
  // it may turn out it is a bad approach in assets so we gonna delete it here
26
26
  const executionFnName = `${nanoid()}_executionFn`
27
27
 
@@ -29,11 +29,10 @@ module.exports = function createRunInSandbox (reporter) {
29
29
  context.__appDirectory = reporter.options.appDirectory
30
30
  context.__rootDirectory = reporter.options.rootDirectory
31
31
  context.__parentModuleDirectory = reporter.options.parentModuleDirectory
32
- context.setTimeout = setTimeout
33
32
  context.__topLevelFunctions = {}
34
33
  context.__handleError = (err) => handleError(reporter, err)
35
34
 
36
- const { sourceFilesInfo, run, compileScript, restore, sandbox, sandboxRequire } = createSandbox(context, {
35
+ const { sourceFilesInfo, run, compileScript, restore, sandbox, sandboxRequire } = await createSandbox(context, {
37
36
  rootDirectory: reporter.options.rootDirectory,
38
37
  onLog: (log) => {
39
38
  // we mark any log done in sandbox as userLevel: true, this allows us to detect which logs belongs to user
@@ -159,9 +158,23 @@ module.exports = function createRunInSandbox (reporter) {
159
158
  }
160
159
 
161
160
  const functionNames = getTopLevelFunctions(functionsCache, userCode)
162
- const functionsCode = `return {${functionNames.map(h => `"${h}": ${h}`).join(',')}}`
163
- const executionCode = `;(async () => { ${userCode} \n\n;${functionsCode} })()
164
- .then((topLevelFunctions) => {
161
+
162
+ // it is better we remove our internal functions so we avoid user having the chance
163
+ // to call them, as long as we force the execution to be truly async (with the await 1)
164
+ // then it is safe to delete __handleError from context, when the execution is truly
165
+ // async then it means the __handleError was already passed to catch handler,
166
+ // therefore safe to delete
167
+ const contextNormalizeCode = [
168
+ 'await 1;',
169
+ `const ${executionFnName}_expose = ${executionFnName};`,
170
+ 'delete this.__handleError;',
171
+ `delete this['${executionFnName}'];`
172
+ ].join('')
173
+
174
+ const functionsCode = `return {topLevelFunctions: {${functionNames.map(h => `"${h}": ${h}`).join(',')}}, fnToExecute: ${executionFnName}_expose}`
175
+
176
+ const executionCode = `;(async () => { ${contextNormalizeCode}${userCode} \n\n;${functionsCode} })()
177
+ .then(({ topLevelFunctions, fnToExecute }) => {
165
178
  const mergedTopLevelFunctions = { ...topLevelFunctions, ...__topLevelFunctions }
166
179
 
167
180
  // expose top level functions to the sandbox context
@@ -170,7 +183,7 @@ module.exports = function createRunInSandbox (reporter) {
170
183
  this[topLevelFnName] = topLevelFn
171
184
  }
172
185
 
173
- return ${executionFnName}({
186
+ return fnToExecute({
174
187
  topLevelFunctions: mergedTopLevelFunctions,
175
188
  require,
176
189
  console,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsreport/jsreport-core",
3
- "version": "3.12.0",
3
+ "version": "4.0.1",
4
4
  "description": "javascript based business reporting",
5
5
  "keywords": [
6
6
  "report",
@@ -40,9 +40,11 @@
40
40
  "@babel/parser": "7.14.4",
41
41
  "@babel/traverse": "7.12.9",
42
42
  "@colors/colors": "1.5.0",
43
- "@jsreport/advanced-workers": "1.3.0",
43
+ "@jsreport/advanced-workers": "2.0.0",
44
44
  "@jsreport/mingo": "2.4.1",
45
45
  "@jsreport/reap": "0.1.0",
46
+ "@jsreport/serializator": "1.0.0",
47
+ "@jsreport/ses": "1.0.0",
46
48
  "ajv": "6.12.6",
47
49
  "app-root-path": "3.0.0",
48
50
  "bytes": "3.1.2",
@@ -59,19 +61,17 @@
59
61
  "lodash.get": "4.4.2",
60
62
  "lodash.groupby": "4.6.0",
61
63
  "lodash.omit": "4.5.0",
62
- "lodash.set": "4.3.2",
63
64
  "lru-cache": "4.1.1",
64
65
  "ms": "2.1.3",
65
66
  "nanoid": "3.2.0",
66
67
  "nconf": "0.12.0",
67
68
  "node.extend.without.arrays": "1.1.6",
68
- "semver": "7.3.5",
69
- "serializator": "1.0.2",
69
+ "semver": "7.5.4",
70
+ "set-value": "4.1.0",
70
71
  "stack-trace": "0.0.10",
71
72
  "triple-beam": "1.3.0",
72
73
  "unset-value": "2.0.1",
73
74
  "uuid": "8.3.2",
74
- "vm2": "3.9.19",
75
75
  "winston": "3.8.1",
76
76
  "winston-transport": "4.5.0",
77
77
  "yieldable-json": "2.0.1"
@@ -85,7 +85,7 @@
85
85
  "winston-loggly-bulk": "3.2.1"
86
86
  },
87
87
  "engines": {
88
- "node": ">=16.11"
88
+ "node": ">=18.15"
89
89
  },
90
90
  "standard": {
91
91
  "env": {
@@ -1,51 +1,62 @@
1
-
2
- module.exports = (reporter, definition) => {
3
- reporter.tests = reporter.tests || {}
4
- reporter.tests.beforeRenderListeners = reporter.createListenerCollection()
5
- reporter.tests.afterRenderListeners = reporter.createListenerCollection()
6
- reporter.tests.validateRenderListeners = reporter.createListenerCollection()
7
- reporter.tests.afterTemplatingEnginesExecutedListeners = reporter.createListenerCollection()
8
-
9
- reporter.registerMainAction('test-beforeRender-listeners', async (data, req) => {
10
- data.req = reporter.Request(data.req)
11
- await reporter.tests.beforeRenderListeners.fire(data.req, data.res)
12
- return { req: data.req, res: data.res }
13
- })
14
- reporter.registerMainAction('test-afterRender-listeners', async (data, req) => {
15
- data.req = reporter.Request(data.req)
16
- await reporter.tests.afterRenderListeners.fire(data.req, data.res)
17
- return { req: data.req, res: data.res }
18
- })
19
- reporter.registerMainAction('test-validateRender-listeners', async (data, req) => {
20
- data.req = reporter.Request(data.req)
21
- await reporter.tests.validateRenderListeners.fire(data.req, data.res)
22
- return { req: data.req, res: data.res }
23
- })
24
- reporter.registerMainAction('test-afterTemplatingEnginesExecuted-listeners', async (data, req) => {
25
- data.req = reporter.Request(data.req)
26
- await reporter.tests.afterTemplatingEnginesExecutedListeners.fire(data.req, data.res)
27
- return { req: data.req, res: data.res }
28
- })
29
-
30
- let beforeRenderEval
31
- reporter.tests.beforeRenderEval = (fn) => {
32
- beforeRenderEval = fn
33
- }
34
- reporter.registerMainAction('test-beforeRenderEval', async (data, req) => {
35
- if (beforeRenderEval == null) {
36
- return
37
- }
38
- return beforeRenderEval.toString()
39
- })
40
-
41
- let afterRenderEval
42
- reporter.tests.afterRenderEval = (fn) => {
43
- afterRenderEval = fn
44
- }
45
- reporter.registerMainAction('test-afterRenderEval', async (data, req) => {
46
- if (afterRenderEval == null) {
47
- return
48
- }
49
- return afterRenderEval.toString()
50
- })
51
- }
1
+
2
+ module.exports = (reporter, definition) => {
3
+ reporter.tests = reporter.tests || {}
4
+ reporter.tests.beforeRenderListeners = reporter.createListenerCollection()
5
+ reporter.tests.afterRenderListeners = reporter.createListenerCollection()
6
+ reporter.tests.validateRenderListeners = reporter.createListenerCollection()
7
+ reporter.tests.afterTemplatingEnginesExecutedListeners = reporter.createListenerCollection()
8
+
9
+ reporter.registerMainAction('test-beforeRender-listeners', async (data, req) => {
10
+ data.req = reporter.Request(data.req)
11
+ await reporter.tests.beforeRenderListeners.fire(data.req, data.res)
12
+ return { req: data.req, res: data.res }
13
+ })
14
+ reporter.registerMainAction('test-afterRender-listeners', async (data, req) => {
15
+ data.req = reporter.Request(data.req)
16
+ await reporter.tests.afterRenderListeners.fire(data.req, data.res)
17
+ return { req: data.req, res: data.res }
18
+ })
19
+ reporter.registerMainAction('test-validateRender-listeners', async (data, req) => {
20
+ data.req = reporter.Request(data.req)
21
+ await reporter.tests.validateRenderListeners.fire(data.req, data.res)
22
+ return { req: data.req, res: data.res }
23
+ })
24
+ reporter.registerMainAction('test-afterTemplatingEnginesExecuted-listeners', async (data, req) => {
25
+ data.req = reporter.Request(data.req)
26
+ await reporter.tests.afterTemplatingEnginesExecutedListeners.fire(data.req, data.res)
27
+ return { req: data.req, res: data.res }
28
+ })
29
+
30
+ let beforeRenderEval
31
+ reporter.tests.beforeRenderEval = (fn) => {
32
+ beforeRenderEval = fn
33
+ }
34
+ reporter.registerMainAction('test-beforeRenderEval', async (data, req) => {
35
+ if (beforeRenderEval == null) {
36
+ return
37
+ }
38
+ return beforeRenderEval.toString()
39
+ })
40
+
41
+ let afterRenderEval
42
+ reporter.tests.afterRenderEval = (fn) => {
43
+ afterRenderEval = fn
44
+ }
45
+ reporter.registerMainAction('test-afterRenderEval', async (data, req) => {
46
+ if (afterRenderEval == null) {
47
+ return
48
+ }
49
+ return afterRenderEval.toString()
50
+ })
51
+
52
+ let afterTemplatingEnginesExecutedEval
53
+ reporter.tests.afterTemplatingEnginesExecutedEval = (fn) => {
54
+ afterTemplatingEnginesExecutedEval = fn
55
+ }
56
+ reporter.registerMainAction('test-afterTemplatingEnginesExecutedEval', async (data, req) => {
57
+ if (afterTemplatingEnginesExecutedEval == null) {
58
+ return
59
+ }
60
+ return afterTemplatingEnginesExecutedEval.toString()
61
+ })
62
+ }
@@ -1,74 +1,81 @@
1
- const extend = require('node.extend.without.arrays')
2
- const vm = require('vm')
3
- const Module = require('module')
4
- const path = require('path')
5
- const process = require('process')
6
-
7
- module.exports = (reporter, definition) => {
8
- reporter.initializeListeners.add('test-listeners', () => {
9
- reporter.beforeRenderListeners.add('listeners', async (req, res) => {
10
- const result = await reporter.executeMainAction('test-beforeRender-listeners', { req, res }, req)
11
- extend(true, req, result.req)
12
- extend(true, res, result.res)
13
- })
14
-
15
- reporter.afterRenderListeners.add('listeners', async (req, res) => {
16
- const result = await reporter.executeMainAction('test-afterRender-listeners', { req, res }, req)
17
- extend(true, req, result.req)
18
- extend(true, res, result.res)
19
- })
20
-
21
- reporter.validateRenderListeners.add('listeners', async (req, res) => {
22
- const result = await reporter.executeMainAction('test-validateRender-listeners', { req, res }, req)
23
- extend(true, req, result.req)
24
- extend(true, res, result.res)
25
- })
26
-
27
- reporter.afterTemplatingEnginesExecutedListeners.add('listeners', async (req, res) => {
28
- const result = await reporter.executeMainAction('test-afterTemplatingEnginesExecuted-listeners', { req, res }, req)
29
- extend(true, req, result.req)
30
- extend(true, res, result.res)
31
- })
32
-
33
- const evalInWorker = (code, req, res) => {
34
- const script = new vm.Script(`
35
- ;(function () {
36
- return ${code}
37
- })()
38
- `)
39
-
40
- return script.runInThisContext({
41
- displayErrors: true
42
- })(req, res, {
43
- mainModuleFilename: require.main.filename,
44
- require: (m) => {
45
- if (Module.builtinModules.includes(m)) {
46
- return require(m)
47
- }
48
-
49
- try {
50
- return require(path.join(process.cwd(), 'node_modules', m))
51
- } catch (e) {
52
- // hack, make it working in monorepo as well as normal extension
53
- return require(path.join(process.cwd(), '../../node_modules', m))
54
- }
55
- },
56
- reporter
57
- })
58
- }
59
-
60
- reporter.afterRenderListeners.add('eval-listeners', async (req, res) => {
61
- const code = await reporter.executeMainAction('test-afterRenderEval', {}, req)
62
- if (code) {
63
- return evalInWorker(code, req, res)
64
- }
65
- })
66
-
67
- reporter.beforeRenderListeners.insert(0, 'eval-listeners', async (req, res) => {
68
- const code = await reporter.executeMainAction('test-beforeRenderEval', {}, req)
69
- if (code) {
70
- return evalInWorker(code, req, res)
71
- }
72
- })
73
- })
74
- }
1
+ const extend = require('node.extend.without.arrays')
2
+ const vm = require('vm')
3
+ const Module = require('module')
4
+ const path = require('path')
5
+ const process = require('process')
6
+
7
+ module.exports = (reporter, definition) => {
8
+ reporter.initializeListeners.add('test-listeners', () => {
9
+ reporter.beforeRenderListeners.add('listeners', async (req, res) => {
10
+ const result = await reporter.executeMainAction('test-beforeRender-listeners', { req, res }, req)
11
+ extend(true, req, result.req)
12
+ extend(true, res, result.res)
13
+ })
14
+
15
+ reporter.afterRenderListeners.add('listeners', async (req, res) => {
16
+ const result = await reporter.executeMainAction('test-afterRender-listeners', { req, res }, req)
17
+ extend(true, req, result.req)
18
+ extend(true, res, result.res)
19
+ })
20
+
21
+ reporter.validateRenderListeners.add('listeners', async (req, res) => {
22
+ const result = await reporter.executeMainAction('test-validateRender-listeners', { req, res }, req)
23
+ extend(true, req, result.req)
24
+ extend(true, res, result.res)
25
+ })
26
+
27
+ reporter.afterTemplatingEnginesExecutedListeners.add('listeners', async (req, res) => {
28
+ const result = await reporter.executeMainAction('test-afterTemplatingEnginesExecuted-listeners', { req, res }, req)
29
+ extend(true, req, result.req)
30
+ extend(true, res, result.res)
31
+ })
32
+
33
+ const evalInWorker = (code, req, res) => {
34
+ const script = new vm.Script(`
35
+ ;(function () {
36
+ return ${code}
37
+ })()
38
+ `)
39
+
40
+ return script.runInThisContext({
41
+ displayErrors: true
42
+ })(req, res, {
43
+ mainModuleFilename: require.main.filename,
44
+ require: (m) => {
45
+ if (Module.builtinModules.includes(m)) {
46
+ return require(m)
47
+ }
48
+
49
+ try {
50
+ return require(path.join(process.cwd(), 'node_modules', m))
51
+ } catch (e) {
52
+ // hack, make it working in monorepo as well as normal extension
53
+ return require(path.join(process.cwd(), '../../node_modules', m))
54
+ }
55
+ },
56
+ reporter
57
+ })
58
+ }
59
+
60
+ reporter.afterRenderListeners.add('eval-listeners', async (req, res) => {
61
+ const code = await reporter.executeMainAction('test-afterRenderEval', {}, req)
62
+ if (code) {
63
+ return evalInWorker(code, req, res)
64
+ }
65
+ })
66
+
67
+ reporter.beforeRenderListeners.insert(0, 'eval-listeners', async (req, res) => {
68
+ const code = await reporter.executeMainAction('test-beforeRenderEval', {}, req)
69
+ if (code) {
70
+ return evalInWorker(code, req, res)
71
+ }
72
+ })
73
+
74
+ reporter.afterTemplatingEnginesExecutedListeners.add('eval-listeners', async (req, res) => {
75
+ const code = await reporter.executeMainAction('test-afterTemplatingEnginesExecutedEval', {}, req)
76
+ if (code) {
77
+ return evalInWorker(code, req, res)
78
+ }
79
+ })
80
+ })
81
+ }
@@ -141,6 +141,34 @@ function collectionTests (store, isInternal, runTransactions) {
141
141
  res[0].phantom.header.should.be.eql('original')
142
142
  })
143
143
 
144
+ it('update should use clones', async () => {
145
+ const colName = !isInternal ? 'templates' : 'internalTemplates'
146
+
147
+ await store().collection('folders').insert({
148
+ name: 'f1',
149
+ shortid: 'f1'
150
+ })
151
+
152
+ await getCollection(colName).insert({
153
+ name: 'test',
154
+ engine: 'none',
155
+ recipe: 'html',
156
+ content: 'original'
157
+ })
158
+
159
+ const set = {
160
+ folder: {
161
+ shortid: 'f1'
162
+ }
163
+ }
164
+
165
+ await getCollection(colName).update({ name: 'test' }, { $set: set })
166
+ set.folder.shortid = 'changing'
167
+
168
+ const res = await getCollection(colName).findOne({})
169
+ res.folder.shortid.should.be.eql('f1')
170
+ })
171
+
144
172
  it('skip and limit', async () => {
145
173
  const colName = !isInternal ? 'templates' : 'internalTemplates'
146
174
 
@@ -443,6 +471,33 @@ function collectionTests (store, isInternal, runTransactions) {
443
471
  should(found != null).be.True()
444
472
  })
445
473
 
474
+ it('insert with transaction should use clones', async () => {
475
+ const colName = !isInternal ? 'templates' : 'internalTemplates'
476
+ const req = Request({})
477
+
478
+ await store().beginTransaction(req)
479
+
480
+ try {
481
+ const t1 = {
482
+ name: 't1',
483
+ engine: 'none',
484
+ recipe: 'html'
485
+ }
486
+
487
+ const newT1 = await getCollection(colName).insert(t1, req)
488
+
489
+ newT1.name = 'fake-t1'
490
+
491
+ await store().commitTransaction(req)
492
+ } catch (e) {
493
+ await store().rollbackTransaction(req)
494
+ throw e
495
+ }
496
+
497
+ const found = await getCollection(colName).findOne({ name: 't1' })
498
+ should(found).not.be.null()
499
+ })
500
+
446
501
  it('should be able to rollback (insert)', async () => {
447
502
  const colName = !isInternal ? 'templates' : 'internalTemplates'
448
503
  const req = Request({})
@@ -1,230 +0,0 @@
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
- }