@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.
Files changed (80) hide show
  1. package/LICENSE +166 -166
  2. package/README.md +298 -284
  3. package/index.js +29 -27
  4. package/lib/main/blobStorage/blobStorage.js +52 -47
  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 -265
  11. package/lib/main/extensions/fileUtils.js +56 -55
  12. package/lib/main/extensions/findVersion.js +49 -53
  13. package/lib/main/extensions/locationCache.js +103 -97
  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 -210
  24. package/lib/main/migration/xlsxTemplatesToAssets.js +128 -118
  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/profiler.js +2 -1
  29. package/lib/main/reporter.js +575 -578
  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 -0
  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 +227 -190
  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 +158 -158
  71. package/lib/worker/render/render.js +213 -209
  72. package/lib/worker/render/resolveReferences.js +60 -60
  73. package/lib/worker/reporter.js +192 -187
  74. package/lib/worker/sandbox/runInSandbox.js +13 -4
  75. package/lib/worker/sandbox/safeSandbox.js +828 -822
  76. package/lib/worker/templates.js +78 -78
  77. package/lib/worker/workerHandler.js +54 -54
  78. package/package.json +92 -92
  79. package/test/blobStorage/common.js +21 -21
  80. package/test/store/common.js +1449 -1449
@@ -1,265 +1,264 @@
1
- /*!
2
- * Copyright(c) 2018 Jan Blaha
3
- *
4
- * ExtensionsManager responsible for loading and registering jsreport extensions.
5
- */
6
-
7
- const os = require('os')
8
- const path = require('path')
9
- const extend = require('node.extend.without.arrays')
10
- const camelCase = require('camelcase')
11
- const discover = require('./discover')
12
- const findVersion = require('./findVersion')
13
- const validateMinimalVersion = require('./validateMinimalVersion')
14
- const sorter = require('./sorter')
15
-
16
- module.exports = (reporter) => {
17
- return {
18
- availableExtensions: [],
19
- recipes: [],
20
- engines: [],
21
- usedExtensions: [],
22
- get extensions () {
23
- return this.availableExtensions.filter((e) => !e.options || e.options.enabled !== false)
24
- },
25
-
26
- async load (opts = {}) {
27
- this.availableExtensions = []
28
-
29
- if (reporter.options.discover || (reporter.options.discover !== false && this.usedExtensions.length === 0)) {
30
- const extensions = await discover({
31
- logger: reporter.logger,
32
- rootDirectory: reporter.options.rootDirectory,
33
- tempCoreDirectory: reporter.options.tempCoreDirectory,
34
- useExtensionsLocationCache: reporter.options.useExtensionsLocationCache
35
- })
36
-
37
- reporter.logger.debug(`Discovered ${extensions.length} extensions`)
38
- this.availableExtensions = this.availableExtensions.concat(extensions)
39
- }
40
-
41
- this.availableExtensions = this.availableExtensions.concat(this.usedExtensions)
42
-
43
- if (reporter.options.extensionsList) {
44
- this.availableExtensions = this.availableExtensions.filter((e) => reporter.options.extensionsList.indexOf(e.name) !== -1)
45
- }
46
-
47
- if (opts.onlyLocation !== true) {
48
- this.availableExtensions = await Promise.all(this.availableExtensions.map(async (e) => {
49
- const { version, pkgVersion, source } = await findVersion(e)
50
- return Object.assign(e, { source, version, pkgVersion })
51
- }))
52
- }
53
-
54
- this.availableExtensions.sort(sorter)
55
-
56
- // filter out duplicated extensions
57
- // this can easily happen when you install jsreport and jsreport-cli into global modules
58
- this.availableExtensions = this.extensions.filter((v, i) => {
59
- if (!v.name) {
60
- return true
61
- }
62
-
63
- const extIndex = this.availableExtensions.findIndex(e => e.name === v.name)
64
- const isUnique = extIndex === i
65
-
66
- if (!isUnique) {
67
- reporter.logger.warn(`Filtering out duplicated extension "${v.name}" from ${v.directory}, using ${this.availableExtensions[extIndex].directory}`)
68
- }
69
-
70
- return isUnique
71
- })
72
- },
73
-
74
- async init () {
75
- return this._useMany(this.availableExtensions)
76
- },
77
-
78
- use (extension) {
79
- if (typeof extension === 'function') {
80
- this.usedExtensions.push({
81
- main: extension,
82
- directory: reporter.options.parentModuleDirectory,
83
- dependencies: []
84
- })
85
- return
86
- }
87
-
88
- if (typeof extension === 'object') {
89
- this.usedExtensions.push(extension)
90
- return
91
- }
92
-
93
- throw new Error('use accepts function or object')
94
- },
95
-
96
- async _useMany (extensions) {
97
- const toValidateGroups = new Map()
98
-
99
- for (const e of extensions) {
100
- const activated = await this._useOne(e)
101
-
102
- if (!activated) {
103
- continue
104
- }
105
-
106
- const extensionRequires = Object.assign({}, e.requires)
107
- // core already validated here
108
- delete extensionRequires.core
109
-
110
- for (const baseExtName of Object.keys(extensionRequires)) {
111
- if (!toValidateGroups.has(baseExtName)) {
112
- toValidateGroups.set(baseExtName, [])
113
- }
114
-
115
- const deps = toValidateGroups.get(baseExtName)
116
- deps.push(e)
117
- }
118
- }
119
-
120
- for (const [baseExtName, deps] of toValidateGroups.entries()) {
121
- const baseExt = extensions.find((ext) => ext.name === baseExtName)
122
-
123
- if (baseExt == null || baseExt.pkgVersion == null) {
124
- continue
125
- }
126
-
127
- for (const ext of deps) {
128
- validateMinimalVersion({ name: baseExtName, version: baseExt.pkgVersion }, ext)
129
- }
130
- }
131
- },
132
-
133
- async _useOne (extension) {
134
- try {
135
- extension.options = extend(
136
- true,
137
- {},
138
- extension.options || {},
139
- extension.name != null ? reporter.options.extensions[camelCase(extension.name)] : {},
140
- extension.name != null ? reporter.options.extensions[extension.name] : {}
141
- )
142
-
143
- // we need to check for string "false" to support disabling extension by env or CLI args
144
- // since this option does not coerce by schema validation at this point but later
145
- if (extension.options.enabled === 'false' || extension.options.enabled === '0') {
146
- extension.options.enabled = false
147
- }
148
-
149
- if (extension.options.enabled === false) {
150
- if (!extension.name) {
151
- reporter.logger.debug(`Anonymous Extension${extension.directory != null ? ` at ${extension.directory}` : ''} is disabled, skipping`)
152
- } else {
153
- reporter.logger.debug(`Extension ${getExtensionDisplayName(extension)} is disabled, skipping`)
154
- }
155
-
156
- return false
157
- }
158
-
159
- validateMinimalVersion({ name: 'core', version: reporter.coreVersion }, extension)
160
-
161
- if (!extension.name) {
162
- reporter.logger.info(`Using anonymous extension${extension.directory != null ? ` at ${extension.directory}` : ''}`)
163
- } else {
164
- reporter.logger.info(`Using extension ${getExtensionDisplayName(extension)}`)
165
- }
166
-
167
- let optionsSchema
168
-
169
- if (extension.name != null) {
170
- optionsSchema = reporter.optionsValidator.getRootSchema().properties.extensions.properties[extension.name]
171
- }
172
-
173
- if (optionsSchema != null) {
174
- try {
175
- reporter.optionsValidator.addSchema(extension.name, optionsSchema)
176
- } catch (e) {
177
- throw new Error(`schema for extension options in definition does not contain a valid json schema. ${e.message}`)
178
- }
179
-
180
- const optionsValidationResult = reporter.optionsValidator.validate(extension.name, extension.options, { rootPrefix: 'options' })
181
-
182
- if (!optionsValidationResult.valid) {
183
- throw new Error(formatExtensionOptionsError(extension.name, optionsValidationResult.fullErrorMessage))
184
- }
185
-
186
- const availableExtensionIndex = this.availableExtensions.indexOf(extension)
187
- const usedExtensionIndex = this.usedExtensions.indexOf(extension)
188
-
189
- extension = new Proxy(extension, {
190
- set: (obj, prop, value, receiver) => {
191
- let newValue
192
-
193
- if (prop === 'options') {
194
- const newData = extend(true, {}, value)
195
- const result = reporter.optionsValidator.validate(extension.name, newData, { rootPrefix: 'options' })
196
-
197
- if (!result.valid) {
198
- throw new Error(formatExtensionOptionsError(extension.name, result.fullErrorMessage))
199
- }
200
-
201
- newValue = newData
202
- } else {
203
- newValue = value
204
- }
205
-
206
- return Reflect.set(obj, prop, newValue, receiver)
207
- }
208
- })
209
-
210
- // ensure extension references in availableExtensions, usedExtensions have
211
- // the proxy instance also
212
- if (availableExtensionIndex !== -1) {
213
- this.availableExtensions[availableExtensionIndex] = extension
214
- }
215
-
216
- if (usedExtensionIndex !== -1) {
217
- this.usedExtensions[usedExtensionIndex] = extension
218
- }
219
-
220
- reporter.options.extensions[extension.name] = extension.options
221
- }
222
-
223
- if (typeof extension.main === 'function') {
224
- await extension.main.call(this, reporter, extension)
225
- } else {
226
- if (extension.directory && extension.main) {
227
- await require(path.join(extension.directory, extension.main)).call(this, reporter, extension)
228
- }
229
- }
230
-
231
- if (extension.options.enabled === false) {
232
- if (!extension.name) {
233
- reporter.logger.debug(`Anonymous Extension${extension.directory != null ? ` at ${extension.directory}` : ''} was disabled`)
234
- } else {
235
- reporter.logger.debug(`Extension ${getExtensionDisplayName(extension)} was disabled`)
236
- }
237
- }
238
-
239
- return extension.options.enabled !== false
240
- } catch (e) {
241
- let errorMsg
242
-
243
- if (!extension.name) {
244
- errorMsg = `Error when loading anonymous extension${extension.directory != null ? ` at ${extension.directory}` : ''}${os.EOL}${e.stack}`
245
- } else {
246
- errorMsg = `Error when loading extension ${getExtensionDisplayName(extension)}${os.EOL}${e.stack}`
247
- }
248
-
249
- throw new Error(errorMsg)
250
- }
251
- }
252
- }
253
- }
254
-
255
- function getExtensionDisplayName (extension) {
256
- if (extension.version != null) {
257
- return `${extension.name}@${extension.version}`
258
- }
259
-
260
- return extension.name
261
- }
262
-
263
- function formatExtensionOptionsError (extName, fullErrorMessage) {
264
- return `options of extension ${extName} contain values that does not match the defined schema. ${fullErrorMessage}`
265
- }
1
+ /*!
2
+ * Copyright(c) 2018 Jan Blaha
3
+ *
4
+ * ExtensionsManager responsible for loading and registering jsreport extensions.
5
+ */
6
+
7
+ const os = require('os')
8
+ const path = require('path')
9
+ const extend = require('node.extend.without.arrays')
10
+ const camelCase = require('camelcase')
11
+ const discover = require('./discover')
12
+ const findVersion = require('./findVersion')
13
+ const validateMinimalVersion = require('./validateMinimalVersion')
14
+ const sorter = require('./sorter')
15
+
16
+ module.exports = (reporter) => {
17
+ return {
18
+ availableExtensions: [],
19
+ recipes: [],
20
+ engines: [],
21
+ usedExtensions: [],
22
+ get extensions () {
23
+ return this.availableExtensions.filter((e) => !e.options || e.options.enabled !== false)
24
+ },
25
+
26
+ async load (opts = {}) {
27
+ this.availableExtensions = []
28
+
29
+ if (reporter.options.discover || (reporter.options.discover !== false && this.usedExtensions.length === 0)) {
30
+ const extensions = await discover({
31
+ logger: reporter.logger,
32
+ rootDirectory: reporter.options.rootDirectory,
33
+ tempCoreDirectory: reporter.options.tempCoreDirectory,
34
+ useExtensionsLocationCache: reporter.options.useExtensionsLocationCache
35
+ })
36
+ reporter.logger.debug(`Discovered ${extensions.length} extensions`)
37
+ this.availableExtensions = this.availableExtensions.concat(extensions)
38
+ }
39
+
40
+ this.availableExtensions = this.availableExtensions.concat(this.usedExtensions)
41
+
42
+ if (reporter.options.extensionsList) {
43
+ this.availableExtensions = this.availableExtensions.filter((e) => reporter.options.extensionsList.indexOf(e.name) !== -1)
44
+ }
45
+
46
+ this.availableExtensions.sort(sorter)
47
+
48
+ // filter out duplicated extensions
49
+ // this can easily happen when you install jsreport and jsreport-cli into global modules
50
+ this.availableExtensions = this.extensions.filter((v, i) => {
51
+ if (!v.name) {
52
+ return true
53
+ }
54
+
55
+ const extIndex = this.availableExtensions.findIndex(e => e.name === v.name)
56
+ const isUnique = extIndex === i
57
+
58
+ if (!isUnique) {
59
+ reporter.logger.warn(`Filtering out duplicated extension "${v.name}" from ${v.directory}, using ${this.availableExtensions[extIndex].directory}`)
60
+ }
61
+
62
+ return isUnique
63
+ })
64
+
65
+ if (opts.onlyLocation !== true) {
66
+ this.availableExtensions = await Promise.all(this.availableExtensions.map(async (e) => {
67
+ const { version, pkgVersion, source } = await findVersion(e)
68
+ return Object.assign(e, { source, version, pkgVersion })
69
+ }))
70
+ }
71
+ },
72
+
73
+ async init () {
74
+ return this._useMany(this.availableExtensions)
75
+ },
76
+
77
+ use (extension) {
78
+ if (typeof extension === 'function') {
79
+ this.usedExtensions.push({
80
+ main: extension,
81
+ directory: reporter.options.parentModuleDirectory,
82
+ dependencies: []
83
+ })
84
+ return
85
+ }
86
+
87
+ if (typeof extension === 'object') {
88
+ this.usedExtensions.push(extension)
89
+ return
90
+ }
91
+
92
+ throw new Error('use accepts function or object')
93
+ },
94
+
95
+ async _useMany (extensions) {
96
+ const toValidateGroups = new Map()
97
+
98
+ for (const e of extensions) {
99
+ const activated = await this._useOne(e)
100
+
101
+ if (!activated) {
102
+ continue
103
+ }
104
+
105
+ const extensionRequires = Object.assign({}, e.requires)
106
+ // core already validated here
107
+ delete extensionRequires.core
108
+
109
+ for (const baseExtName of Object.keys(extensionRequires)) {
110
+ if (!toValidateGroups.has(baseExtName)) {
111
+ toValidateGroups.set(baseExtName, [])
112
+ }
113
+
114
+ const deps = toValidateGroups.get(baseExtName)
115
+ deps.push(e)
116
+ }
117
+ }
118
+
119
+ for (const [baseExtName, deps] of toValidateGroups.entries()) {
120
+ const baseExt = extensions.find((ext) => ext.name === baseExtName)
121
+
122
+ if (baseExt == null || baseExt.pkgVersion == null) {
123
+ continue
124
+ }
125
+
126
+ for (const ext of deps) {
127
+ validateMinimalVersion({ name: baseExtName, version: baseExt.pkgVersion }, ext)
128
+ }
129
+ }
130
+ },
131
+
132
+ async _useOne (extension) {
133
+ try {
134
+ extension.options = extend(
135
+ true,
136
+ {},
137
+ extension.options || {},
138
+ extension.name != null ? reporter.options.extensions[camelCase(extension.name)] : {},
139
+ extension.name != null ? reporter.options.extensions[extension.name] : {}
140
+ )
141
+
142
+ // we need to check for string "false" to support disabling extension by env or CLI args
143
+ // since this option does not coerce by schema validation at this point but later
144
+ if (extension.options.enabled === 'false' || extension.options.enabled === '0') {
145
+ extension.options.enabled = false
146
+ }
147
+
148
+ if (extension.options.enabled === false) {
149
+ if (!extension.name) {
150
+ reporter.logger.debug(`Anonymous Extension${extension.directory != null ? ` at ${extension.directory}` : ''} is disabled, skipping`)
151
+ } else {
152
+ reporter.logger.debug(`Extension ${getExtensionDisplayName(extension)} is disabled, skipping`)
153
+ }
154
+
155
+ return false
156
+ }
157
+
158
+ validateMinimalVersion({ name: 'core', version: reporter.coreVersion }, extension)
159
+
160
+ if (!extension.name) {
161
+ reporter.logger.info(`Using anonymous extension${extension.directory != null ? ` at ${extension.directory}` : ''}`)
162
+ } else {
163
+ reporter.logger.info(`Using extension ${getExtensionDisplayName(extension)}`)
164
+ }
165
+
166
+ let optionsSchema
167
+
168
+ if (extension.name != null) {
169
+ optionsSchema = reporter.optionsValidator.getRootSchema().properties.extensions.properties[extension.name]
170
+ }
171
+
172
+ if (optionsSchema != null) {
173
+ try {
174
+ reporter.optionsValidator.addSchema(extension.name, optionsSchema)
175
+ } catch (e) {
176
+ throw new Error(`schema for extension options in definition does not contain a valid json schema. ${e.message}`)
177
+ }
178
+
179
+ const optionsValidationResult = reporter.optionsValidator.validate(extension.name, extension.options, { rootPrefix: 'options' })
180
+
181
+ if (!optionsValidationResult.valid) {
182
+ throw new Error(formatExtensionOptionsError(extension.name, optionsValidationResult.fullErrorMessage))
183
+ }
184
+
185
+ const availableExtensionIndex = this.availableExtensions.indexOf(extension)
186
+ const usedExtensionIndex = this.usedExtensions.indexOf(extension)
187
+
188
+ extension = new Proxy(extension, {
189
+ set: (obj, prop, value, receiver) => {
190
+ let newValue
191
+
192
+ if (prop === 'options') {
193
+ const newData = extend(true, {}, value)
194
+ const result = reporter.optionsValidator.validate(extension.name, newData, { rootPrefix: 'options' })
195
+
196
+ if (!result.valid) {
197
+ throw new Error(formatExtensionOptionsError(extension.name, result.fullErrorMessage))
198
+ }
199
+
200
+ newValue = newData
201
+ } else {
202
+ newValue = value
203
+ }
204
+
205
+ return Reflect.set(obj, prop, newValue, receiver)
206
+ }
207
+ })
208
+
209
+ // ensure extension references in availableExtensions, usedExtensions have
210
+ // the proxy instance also
211
+ if (availableExtensionIndex !== -1) {
212
+ this.availableExtensions[availableExtensionIndex] = extension
213
+ }
214
+
215
+ if (usedExtensionIndex !== -1) {
216
+ this.usedExtensions[usedExtensionIndex] = extension
217
+ }
218
+
219
+ reporter.options.extensions[extension.name] = extension.options
220
+ }
221
+
222
+ if (typeof extension.main === 'function') {
223
+ await extension.main.call(this, reporter, extension)
224
+ } else {
225
+ if (extension.directory && extension.main) {
226
+ await require(path.join(extension.directory, extension.main)).call(this, reporter, extension)
227
+ }
228
+ }
229
+
230
+ if (extension.options.enabled === false) {
231
+ if (!extension.name) {
232
+ reporter.logger.debug(`Anonymous Extension${extension.directory != null ? ` at ${extension.directory}` : ''} was disabled`)
233
+ } else {
234
+ reporter.logger.debug(`Extension ${getExtensionDisplayName(extension)} was disabled`)
235
+ }
236
+ }
237
+
238
+ return extension.options.enabled !== false
239
+ } catch (e) {
240
+ let errorMsg
241
+
242
+ if (!extension.name) {
243
+ errorMsg = `Error when loading anonymous extension${extension.directory != null ? ` at ${extension.directory}` : ''}${os.EOL}${e.stack}`
244
+ } else {
245
+ errorMsg = `Error when loading extension ${getExtensionDisplayName(extension)}${os.EOL}${e.stack}`
246
+ }
247
+
248
+ throw new Error(errorMsg)
249
+ }
250
+ }
251
+ }
252
+ }
253
+
254
+ function getExtensionDisplayName (extension) {
255
+ if (extension.version != null) {
256
+ return `${extension.name}@${extension.version}`
257
+ }
258
+
259
+ return extension.name
260
+ }
261
+
262
+ function formatExtensionOptionsError (extName, fullErrorMessage) {
263
+ return `options of extension ${extName} contain values that does not match the defined schema. ${fullErrorMessage}`
264
+ }
@@ -1,55 +1,56 @@
1
- /*!
2
- * Copyright(c) 2014 Jan Blaha
3
- *
4
- */
5
- const fs = require('fs')
6
- const path = require('path')
7
-
8
- exports.walkSync = (rootPath, fileName, exclude) => {
9
- const results = []
10
- const queue = []
11
- let next = rootPath
12
-
13
- function dirname (f) {
14
- const parts = path.dirname(f).split(path.sep)
15
- return parts[parts.length - 1]
16
- }
17
-
18
- while (next) {
19
- let list
20
- try {
21
- list = fs.readdirSync(next)
22
- } catch (e) {
23
- // no permissions to read folder for example, just skip it
24
- list = []
25
- }
26
- list.forEach((i) => {
27
- const item = path.join(next, i)
28
-
29
- if (item.indexOf(exclude) > -1) {
30
- return
31
- }
32
-
33
- try {
34
- if (fs.statSync(item).isDirectory()) {
35
- queue.push(item)
36
- return
37
- }
38
- } catch (e) {
39
-
40
- }
41
-
42
- if (i === fileName) {
43
- const extensionsDirectoryName = dirname(item)
44
- const alreadyListedConfig = results.filter((f) => extensionsDirectoryName === dirname(f))
45
-
46
- if (!alreadyListedConfig.length) {
47
- results.push(item)
48
- }
49
- }
50
- })
51
- next = queue.shift()
52
- }
53
-
54
- return results
55
- }
1
+ /*!
2
+ * Copyright(c) 2014 Jan Blaha
3
+ *
4
+ */
5
+ const fs = require('fs')
6
+ const path = require('path')
7
+
8
+ exports.walkSync = (rootPath, fileName, excludePath) => {
9
+ const results = []
10
+ const queue = []
11
+ let next = rootPath
12
+
13
+ function dirname (f) {
14
+ const parts = path.dirname(f).split(path.sep)
15
+ return parts[parts.length - 1]
16
+ }
17
+
18
+ while (next) {
19
+ let list
20
+ try {
21
+ list = fs.readdirSync(next)
22
+ } catch (e) {
23
+ // no permissions to read folder for example, just skip it
24
+ list = []
25
+ }
26
+ list.forEach((i) => {
27
+ const item = path.join(next, i)
28
+
29
+ if (item.startsWith(excludePath)) {
30
+ return
31
+ }
32
+
33
+ try {
34
+ if (fs.statSync(item).isDirectory()) {
35
+ queue.push(item)
36
+ return
37
+ }
38
+ } catch (e) {
39
+
40
+ }
41
+
42
+ if (i === fileName) {
43
+ const extensionsDirectoryName = dirname(item)
44
+ const alreadyListedConfig = results.filter((f) => extensionsDirectoryName === dirname(f))
45
+
46
+ if (!alreadyListedConfig.length) {
47
+ results.push(item)
48
+ }
49
+ }
50
+ })
51
+
52
+ next = queue.shift()
53
+ }
54
+
55
+ return results
56
+ }