@jsreport/jsreport-core 3.0.0 → 3.1.2-test.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.
- package/LICENSE +166 -166
- package/README.md +298 -284
- package/index.js +29 -27
- package/lib/main/blobStorage/blobStorage.js +52 -47
- package/lib/main/blobStorage/inMemoryProvider.js +27 -27
- package/lib/main/blobStorage/mainActions.js +24 -24
- package/lib/main/createDefaultLoggerFormat.js +17 -17
- package/lib/main/defaults.js +14 -14
- package/lib/main/extensions/discover.js +20 -20
- package/lib/main/extensions/extensionsManager.js +264 -265
- package/lib/main/extensions/fileUtils.js +56 -55
- package/lib/main/extensions/findVersion.js +49 -53
- package/lib/main/extensions/locationCache.js +103 -97
- package/lib/main/extensions/sorter.js +10 -10
- package/lib/main/extensions/validateMinimalVersion.js +50 -50
- package/lib/main/folders/cascadeFolderRemove.js +25 -25
- package/lib/main/folders/getEntitiesInFolder.js +53 -53
- package/lib/main/folders/index.js +42 -42
- package/lib/main/folders/moveBetweenFolders.js +354 -354
- package/lib/main/folders/validateDuplicatedName.js +107 -107
- package/lib/main/folders/validateReservedName.js +53 -53
- package/lib/main/logger.js +244 -244
- package/lib/main/migration/resourcesToAssets.js +230 -210
- package/lib/main/migration/xlsxTemplatesToAssets.js +128 -118
- package/lib/main/monitoring.js +91 -91
- package/lib/main/optionsLoad.js +237 -237
- package/lib/main/optionsSchema.js +237 -237
- package/lib/main/profiler.js +2 -1
- package/lib/main/reporter.js +575 -578
- package/lib/main/schemaValidator.js +252 -252
- package/lib/main/settings.js +154 -154
- package/lib/main/store/checkDuplicatedId.js +27 -27
- package/lib/main/store/collection.js +329 -329
- package/lib/main/store/documentStore.js +469 -469
- package/lib/main/store/mainActions.js +28 -28
- package/lib/main/store/memoryStoreProvider.js +99 -99
- package/lib/main/store/queue.js +48 -48
- package/lib/main/store/referenceUtils.js +251 -251
- package/lib/main/store/setupValidateId.js +43 -43
- package/lib/main/store/setupValidateShortid.js +71 -71
- package/lib/main/store/transaction.js +69 -69
- package/lib/main/store/typeUtils.js +180 -180
- package/lib/main/templates.js +34 -34
- package/lib/main/validateEntityName.js +62 -62
- package/lib/shared/createError.js +36 -36
- package/lib/shared/encryption.js +114 -114
- package/lib/shared/folders/index.js +11 -11
- package/lib/shared/folders/normalizeEntityPath.js +15 -15
- package/lib/shared/folders/resolveEntityFromPath.js +88 -88
- package/lib/shared/folders/resolveEntityPath.js +46 -46
- package/lib/shared/folders/resolveFolderFromPath.js +38 -38
- package/lib/shared/generateRequestId.js +4 -4
- package/lib/shared/listenerCollection.js +169 -0
- package/lib/shared/normalizeMetaFromLogs.js +30 -30
- package/lib/shared/reporter.js +128 -123
- package/lib/shared/request.js +64 -64
- package/lib/shared/tempFilesHandler.js +81 -81
- package/lib/shared/templates.js +82 -82
- package/lib/static/helpers.js +33 -33
- package/lib/worker/blobStorage.js +34 -34
- package/lib/worker/defaultProxyExtend.js +46 -46
- package/lib/worker/documentStore.js +49 -49
- package/lib/worker/extensionsManager.js +17 -17
- package/lib/worker/logger.js +48 -48
- package/lib/worker/render/diff.js +138 -138
- package/lib/worker/render/executeEngine.js +227 -190
- package/lib/worker/render/htmlRecipe.js +10 -10
- package/lib/worker/render/moduleHelper.js +45 -43
- package/lib/worker/render/noneEngine.js +12 -12
- package/lib/worker/render/profiler.js +158 -158
- package/lib/worker/render/render.js +213 -209
- package/lib/worker/render/resolveReferences.js +60 -60
- package/lib/worker/reporter.js +192 -187
- package/lib/worker/sandbox/runInSandbox.js +13 -4
- package/lib/worker/sandbox/safeSandbox.js +828 -822
- package/lib/worker/templates.js +78 -78
- package/lib/worker/workerHandler.js +54 -54
- package/package.json +92 -92
- package/test/blobStorage/common.js +21 -21
- package/test/store/common.js +1449 -1449
package/lib/main/optionsLoad.js
CHANGED
|
@@ -1,237 +1,237 @@
|
|
|
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
|
+
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
|