65 lines
2.0 KiB
JavaScript
65 lines
2.0 KiB
JavaScript
var assert = require('assert')
|
|
var path = require('path')
|
|
var Readable = require('stream').Readable
|
|
var util = require('util')
|
|
|
|
function Walker (dir, options) {
|
|
assert.strictEqual(typeof dir, 'string', '`dir` parameter should be of type string. Got type: ' + typeof dir)
|
|
var defaultStreamOptions = { objectMode: true }
|
|
var defaultOpts = {
|
|
queueMethod: 'shift',
|
|
pathSorter: undefined,
|
|
filter: undefined,
|
|
depthLimit: undefined,
|
|
preserveSymlinks: false
|
|
}
|
|
options = Object.assign(defaultOpts, options, defaultStreamOptions)
|
|
|
|
Readable.call(this, options)
|
|
this.root = path.resolve(dir)
|
|
this.paths = [this.root]
|
|
this.options = options
|
|
if (options.depthLimit > -1) this.rootDepth = this.root.split(path.sep).length + 1
|
|
this.fs = options.fs || require('graceful-fs')
|
|
}
|
|
util.inherits(Walker, Readable)
|
|
|
|
Walker.prototype._read = function () {
|
|
if (this.paths.length === 0) return this.push(null)
|
|
var self = this
|
|
var pathItem = this.paths[this.options.queueMethod]()
|
|
|
|
var statFunction = this.options.preserveSymlinks ? self.fs.lstat : self.fs.stat
|
|
|
|
statFunction(pathItem, function (err, stats) {
|
|
var item = { path: pathItem, stats: stats }
|
|
if (err) return self.emit('error', err, item)
|
|
|
|
if (!stats.isDirectory() || (self.rootDepth &&
|
|
pathItem.split(path.sep).length - self.rootDepth >= self.options.depthLimit)) {
|
|
return self.push(item)
|
|
}
|
|
|
|
self.fs.readdir(pathItem, function (err, pathItems) {
|
|
if (err) {
|
|
self.push(item)
|
|
return self.emit('error', err, item)
|
|
}
|
|
|
|
pathItems = pathItems.map(function (part) { return path.join(pathItem, part) })
|
|
if (self.options.filter) pathItems = pathItems.filter(self.options.filter)
|
|
if (self.options.pathSorter) pathItems.sort(self.options.pathSorter)
|
|
// faster way to do do incremental batch array pushes
|
|
self.paths.push.apply(self.paths, pathItems)
|
|
|
|
self.push(item)
|
|
})
|
|
})
|
|
}
|
|
|
|
function walk (root, options) {
|
|
return new Walker(root, options)
|
|
}
|
|
|
|
module.exports = walk
|