1var fs = require ('graceful-fs') 2var dz = require ('dezalgo') 3var once = require ('once') 4var path = require ('path') 5var debug = require ('debuglog') ('rds') 6 7module . exports = readdir 8readdir.sync = readdirSync 9 10function readdir (dir, cb) { 11 fs . readdir (dir, function (er, kids) { 12 if (er) 13 return cb (er) 14 15 debug ('dir=%j, kids=%j', dir, kids) 16 readScopes (dir, kids, function (er, data) { 17 if (er) 18 return cb (er) 19 20 // Sort for bonus consistency points 21 data = data . sort (function (a, b) { 22 return a > b ? 1 : -1 23 }) 24 25 return cb (null, data) 26 }) 27 }) 28} 29 30function readdirSync (dir) { 31 var kids = fs . readdirSync (dir) 32 debug ('dir=%j, kids=%j', dir, kids) 33 var data = readScopesSync (dir, kids) 34 // Sort for bonus consistency points 35 data = data . sort (function (a, b) { 36 return a > b ? 1 : -1 37 }) 38 39 return data 40} 41 42// Turn [ 'a', '@scope' ] into 43// ['a', '@scope/foo', '@scope/bar'] 44function readScopes (root, kids, cb) { 45 var scopes = kids . filter (function (kid) { 46 return kid . charAt (0) === '@' 47 }) 48 49 kids = kids . filter (function (kid) { 50 return kid . charAt (0) !== '@' 51 }) 52 53 debug ('scopes=%j', scopes) 54 55 if (scopes . length === 0) 56 dz (cb) (null, kids) // prevent maybe-sync zalgo release 57 58 cb = once (cb) 59 var l = scopes . length 60 scopes . forEach (function (scope) { 61 var scopedir = path . resolve (root, scope) 62 debug ('root=%j scope=%j scopedir=%j', root, scope, scopedir) 63 fs . readdir (scopedir, then . bind (null, scope)) 64 }) 65 66 function then (scope, er, scopekids) { 67 if (er) 68 return cb (er) 69 70 // XXX: Not sure how old this node bug is. Maybe superstition? 71 scopekids = scopekids . filter (function (scopekid) { 72 return !(scopekid === '.' || scopekid === '..' || !scopekid) 73 }) 74 75 kids . push . apply (kids, scopekids . map (function (scopekid) { 76 return scope + '/' + scopekid 77 })) 78 79 debug ('scope=%j scopekids=%j kids=%j', scope, scopekids, kids) 80 81 if (--l === 0) 82 cb (null, kids) 83 } 84} 85 86function readScopesSync (root, kids) { 87 var scopes = kids . filter (function (kid) { 88 return kid . charAt (0) === '@' 89 }) 90 91 kids = kids . filter (function (kid) { 92 return kid . charAt (0) !== '@' 93 }) 94 95 debug ('scopes=%j', scopes) 96 97 if (scopes . length === 0) 98 return kids 99 100 var l = scopes . length 101 scopes . forEach (function (scope) { 102 var scopedir = path . resolve (root, scope) 103 debug ('root=%j scope=%j scopedir=%j', root, scope, scopedir) 104 then (scope, fs . readdirSync (scopedir)) 105 }) 106 107 function then (scope, scopekids) { 108 // XXX: Not sure how old this node bug is. Maybe superstition? 109 scopekids = scopekids . filter (function (scopekid) { 110 return !(scopekid === '.' || scopekid === '..' || !scopekid) 111 }) 112 113 kids . push . apply (kids, scopekids . map (function (scopekid) { 114 return scope + '/' + scopekid 115 })) 116 117 debug ('scope=%j scopekids=%j kids=%j', scope, scopekids, kids) 118 } 119 120 return kids 121} 122