Skip to content

Instantly share code, notes, and snippets.

@ivan-demchenko
Last active October 23, 2017 01:16
Show Gist options
  • Save ivan-demchenko/4bc77bd0fa0b516dd2e203449ab0a6de to your computer and use it in GitHub Desktop.
Save ivan-demchenko/4bc77bd0fa0b516dd2e203449ab0a6de to your computer and use it in GitHub Desktop.
Async recursion
const daggy = require('daggy');
const Task = require('data.task');
const path = require('path');
const fs = require('fs');
const { sequence } = require('ramda');
// type Entity
// = File String
// | Dir String (List Entity)
const Entity = daggy.taggedSum('Entity', {
File: ['name'],
Dir: ['name', 'items'],
});
Entity.prototype.inspect = function inspect() {
return this.cata({
File: name => `File(${name})`,
Dir: (name, items) => `Dir(${name}, ${items.map(x => x.inspect())})`,
});
};
// -- isDir :: Path -> Task e Bool
const isDir = entityPath =>
new Task((rej, res) =>
fs.stat(entityPath, (err, stats) => {
return err ? rej(err) : res(stats.isDirectory());
}));
// -- readdir :: Path -> Task e [String]
const readdir = dirPath =>
new Task((rej, res) =>
fs.readdir(dirPath, (err, items) => {
return err ? rej(err) : res(items);
}));
// -- itemToEntity :: (String, Path) -> Bool -> Task e Entity
const itemToEntity = (item, newPath) => (isItDir) => {
return isItDir
? readDir2TaskListEntity(newPath).map(items => Entity.Dir(item, items))
: Task.of(Entity.File(item));
};
// -- items2Entities :: (Path, List String) -> List (Task e Entity)
const listItem2ListTaskEntity = (dirPath, items) =>
items.map((item) => {
const newPath = path.join(dirPath, item);
return isDir(newPath)
.chain(itemToEntity(item, newPath));
});
// -- readDir2TaskListEntity :: Path -> Task e (List Entity)
const readDir2TaskListEntity = dirPath =>
readdir(dirPath)
.chain(items => sequence(Task.of, listItem2ListTaskEntity(dirPath, items)));
// -- main :: String -> Path -> Entity
const main = (dirName, rootPath) =>
readDir2TaskListEntity(path.join(rootPath, dirName))
.map(items => Entity.Dir(dirName, items));
// Program
main('test', __dirname).fork(
console.log,
console.error
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment