index.js 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. var assert = require('assert')
  2. var fs
  3. try {
  4. fs = require('graceful-fs')
  5. } catch (e) {
  6. fs = require('fs')
  7. }
  8. var path = require('path')
  9. var Readable = require('stream').Readable
  10. var util = require('util')
  11. var assign = require('./assign')
  12. function Walker (dir, options) {
  13. assert.strictEqual(typeof dir, 'string', '`dir` parameter should be of type string. Got type: ' + typeof dir)
  14. var defaultStreamOptions = { objectMode: true }
  15. var defaultOpts = { queueMethod: 'shift', pathSorter: undefined, filter: undefined }
  16. options = assign(defaultOpts, options, defaultStreamOptions)
  17. Readable.call(this, options)
  18. this.root = path.resolve(dir)
  19. this.paths = [this.root]
  20. this.options = options
  21. this.fs = options.fs || fs // mock-fs
  22. }
  23. util.inherits(Walker, Readable)
  24. Walker.prototype._read = function () {
  25. if (this.paths.length === 0) return this.push(null)
  26. var self = this
  27. var pathItem = this.paths[this.options.queueMethod]()
  28. self.fs.lstat(pathItem, function (err, stats) {
  29. var item = { path: pathItem, stats: stats }
  30. if (err) return self.emit('error', err, item)
  31. if (!stats.isDirectory()) return self.push(item)
  32. self.fs.readdir(pathItem, function (err, pathItems) {
  33. if (err) {
  34. self.push(item)
  35. return self.emit('error', err, item)
  36. }
  37. pathItems = pathItems.map(function (part) { return path.join(pathItem, part) })
  38. if (self.options.filter) pathItems = pathItems.filter(self.options.filter)
  39. if (self.options.pathSorter) pathItems.sort(self.options.pathSorter)
  40. pathItems.forEach(function (pi) { self.paths.push(pi) })
  41. self.push(item)
  42. })
  43. })
  44. }
  45. function walk (root, options) {
  46. return new Walker(root, options)
  47. }
  48. module.exports = walk