Skip to content

Commit

Permalink
add optionnable sorting capability
Browse files Browse the repository at this point in the history
  • Loading branch information
quazardous committed Jan 6, 2017
1 parent 71b8e98 commit 8e99e96
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 19 deletions.
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ with help of [filer](https://github.com/filerjs/filer "Node-like file system for
```js
const readify = require('readify');

// basic
readify('/', (error, data) => {
console.log(data);
// output
Expand All @@ -45,11 +46,13 @@ readify('/', (error, data) => {
size: '4.22kb',
date: '20.02.2016',
owner: 'coderaiser',
mode: 'rw- rw- r--'
mode: 'rw- rw- r--',
_raw: [object] // see bellow
}]
}
});

// raw output
readify('/', 'raw', (error, data) => {
console.log(data);
// output
Expand All @@ -64,6 +67,19 @@ readify('/', 'raw', (error, data) => {
}]
}
});

// sort output
// available sort option: name, size, owner, date
// available order option: asc, desc
readify('/', {sort: 'size', order: 'desc'}, (error, data) => {
console.log(data);
});

// all together
readify('/', {sort: 'size', order: 'desc', type: 'raw'}, (error, data) => {
console.log(data);
});

```

`browser` example:
Expand Down
81 changes: 65 additions & 16 deletions lib/readify.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,71 @@ const nicki = !WIN && !BROWSER && require('nicki/legacy');
const readdir = promisify(fs.readdir, fs);

/* sorting on Win and node v0.8.0 */
const sortFiles = sort((a, b) => {
return a.name > b.name ? 1 : -1;
const sortFiles = currify((attr, order, array) => {
switch (order) {
case 'desc':
// nothing
break;
case 'asc':
default:
order = 'asc';
}
var cmp;
switch (attr) {
case 'size':
cmp = (a, b) => (+a - +b);
break;
case 'date':
cmp = (a, b) => (a > b ? 1 : -1);
break;
case 'owner':
cmp = (a, b) => (a > b ? 1 : -1);
break;
case 'name':
// no break;
default:
attr = 'name';
cmp = (a, b) => a.localeCompare(b.attr);
}
return sort((a, b) => {
var res;
if (typeof a._raw !== 'undefined' && typeof b._raw !== 'undefined' ) {
res = cmp(a._raw[attr], b._raw[attr]);
} else {
res = cmp(a[attr], b[attr]);
}
if (order === 'desc') {
res = -res;
}
return res;
}, array);
});

const good = (f) => (...a) => f(null, ...a);

module.exports = readify;

function readify(path, type, fn) {
function readify(path, options, fn) {
if (!fn) {
fn = type;
type = '';
fn = options;
options = '';
}
if (typeof options !== 'object') {
options = {
type: options,
};
}
if (typeof options.sort === 'undefined') {
options.sort = '';
}
if (typeof options.type === 'undefined') {
options.type = '';
}

check(path, fn);

readdir(path)
.then(getAllStats(path, type))
.then(getAllStats(path, options))
.then(good(fn))
.catch(fn);
}
Expand All @@ -68,20 +115,20 @@ function check(path, callback) {
* @param path
* @param names
*/
function _getAllStats(path, type, names, callback) {
function _getAllStats(path, options, names, callback) {
const length = names.length;
const dir = format.addSlashToEnd(path);

if (!length)
return fillJSON(dir, [], type, callback);
return fillJSON(dir, [], options, callback);

const funcs = names.map((name) => {
return getStat(name, dir + name);
});

exec.parallel(funcs, (...args) => {
const files = args.slice(1);
fillJSON(dir, files, type, callback);
fillJSON(dir, files, options, callback);
});
}

Expand Down Expand Up @@ -111,15 +158,16 @@ function _parseAllStats(type, array) {
function parseStat(type, stat) {
const isDir = stat.isDirectory();
const size = isDir ? 'dir' : stat.size;

if (type === 'raw')
return {
const raw = {
name: stat.name,
size: size,
date: stat.mtime,
owner: stat.uid,
mode: stat.mode
};

if (type === 'raw')
return raw;

/* Переводим права доступа в 8-ричную систему */
const modeStr = Number(stat.mode).toString(8);
Expand All @@ -134,7 +182,8 @@ function parseStat(type, stat) {
size: format.size(size),
date: mtime,
owner: owner,
mode: mode && format.permissions.symbolic(mode)
mode: mode && format.permissions.symbolic(mode),
_raw: raw
};
}

Expand All @@ -143,16 +192,16 @@ function parseStat(type, stat) {
*
* @param params - { files, stats, path }
*/
function fillJSON(path, stats, type, callback) {
const processFiles = squad(changeOrder, sortFiles, parseAllStats(type));
function fillJSON(path, stats, options, callback) {
const processFiles = squad(changeOrder, sortFiles(options.sort, options.order), parseAllStats(options.type));
const json = {
path: '',
files: processFiles(stats)
};

json.path = format.addSlashToEnd(path);

if (type === 'raw')
if (options.type === 'raw')
return callback(null, json);

changeUIDToName(json, (error, files) => {
Expand Down
1 change: 1 addition & 0 deletions test/dir/1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
111
1 change: 1 addition & 0 deletions test/dir/2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2
1 change: 1 addition & 0 deletions test/dir/3.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
33
62 changes: 60 additions & 2 deletions test/readify.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ test('readify: result', (t) => {
update();

readify('.', (error, result) => {
result.files = result.files.map(function(file){
delete file._raw;
return file;
});
t.deepEqual(result, expected, 'should get raw values');

fs.readdir = readdir;
Expand Down Expand Up @@ -230,7 +234,7 @@ test('result: files should have fields name, size, date, owner, mode', (t) => {
length = files.length,
check = () =>
files.filter((file) =>
Object.keys(file).join(':') === 'name:size:date:owner:mode'
Object.keys(file).join(':') === 'name:size:date:owner:mode:_raw'
).length;

t.notOk(error, 'no error');
Expand Down Expand Up @@ -310,14 +314,68 @@ test('readify stat: error', (t) => {
const dir = path.resolve(__dirname, '..', 'dist');
readify(dir, (error, data) => {
t.notOk(error, 'no error when stat error');

data.files = data.files.map(function(file){
delete file._raw;
return file;
});
t.deepEqual(data.files, files, 'size, date, owner, mode should be empty');

fs.stat = stat;
t.end();
});
});

test('readify sort: name asc', (t) => {
const files = [
'1.txt',
'2.txt',
'3.txt'
];

readify('./test/dir', {sort: 'name'}, (error, data) => {
t.notOk(error, 'no error');
data.files = data.files.map(function(file){
return file.name;
});
t.deepEqual(data.files, files, 'correct order');
t.end();
});
});

test('readify sort: name desc', (t) => {
const files = [
'3.txt',
'2.txt',
'1.txt'
];

readify('./test/dir', {sort: 'name', order: 'desc'}, (error, data) => {
t.notOk(error, 'no error');
data.files = data.files.map(function(file){
return file.name;
});
t.deepEqual(data.files, files, 'correct order');
t.end();
});
});

test('readify sort: size asc', (t) => {
const files = [
'2.txt',
'3.txt',
'1.txt'
];

readify('./test/dir', {sort: 'size'}, (error, data) => {
t.notOk(error, 'no error');
data.files = data.files.map(function(file){
return file.name;
});
t.deepEqual(data.files, files, 'correct order');
t.end();
});
});

test('browser: filer', (t) => {
const Filer = {
FileSystem: sinon.stub()
Expand Down

0 comments on commit 8e99e96

Please sign in to comment.