node-treeview
Asynchronous filesystem tree view for node.
Javascript (quick start)
Usage
const { TreeView } = require('node-treeview');
new TreeView(options).process(path, (error, tree) => {
if (tree) {
} else {
}
});
new TreeView(options).process(path).then(tree => {
}).catch(error => {
});
async function getTree() {
let tree;
try {
tree = await new TreeView(options).process(path);
} catch (error) {
}
}
getTree();
Example
const { TreeView } = require('node-treeview');
new TreeView({ content: true, depth: 2 })
.process('path/to/dir')
.then(tree => console.log(tree));
Here is what the json
output looks like:
[{
"name": "file1.txt",
"path": "path/to/dir",
"pathname": "path/to/dir/file1.txt",
"depth": 0,
"created": "2017-10-23T18:29:28.000Z",
"modified": "2017-10-23T18:29:28.000Z",
"type": "file",
"size": 13,
"ext": "txt",
"binary": false,
"content": "file1 content"
}, {
"name": "subdir",
"path": "path/to/dir",
"pathname": "path/to/dir/subdir",
"depth": 0,
"created": "2017-10-22T10:48:48.000Z",
"modified": "2017-10-23T18:29:29.000Z",
"type": "dir",
"nodes": [{
"name": "file2.txt",
"path": "path/to/dir/subdir",
"pathname": "path/to/dir/subdir/file2.txt",
"depth": 1,
"created": "2017-10-23T18:29:28.000Z",
"modified": "2017-10-23T18:29:29.000Z",
"type": "file",
"size": 13,
"ext": "txt",
"binary": false,
"content": "file3 content"
}, {
"name": "logo.png",
"path": "path/to/dir/subdir",
"pathname": "path/to/dir/subdir/logo.png",
"depth": 1,
"created": "2017-10-23T18:29:29.000Z",
"modified": "2017-10-23T18:29:29.000Z",
"type": "file",
"size": 325,
"ext": "png",
"binary": true,
"content": "iVBORw0KGgoAAAANSUh..."
}]
}]
The TreeView
lets you listen to item
events.
const { TreeView } = require('node-treeview');
new TreeView()
.on('item', data => console.log(`${data.type}: ${data.pathname}`))
.process('path/to/dir')
.then(() => console.log('done!'));
Here is what the txt
output looks like:
file: path/to/dir/file1.txt
dir: path/to/dir/subdir
file: path/to/dir/subdir/file2.txt
file: path/to/dir/subdir/logo.png
done!
Emitted file never have content
property,
emitted dir always have nodes
property equal to an empty array.
The TreeView
lets you process trees in parallel.
const { TreeView } = require('node-treeview');
const treeView = new TreeView({
relative: true
}).on('item', (data, ctx) => {
console.log(`${ctx.rootPath} -> ${data.pathname}`);
});
Promise.all[
treeView.process('path/to/dir1'),
treeView.process('path/to/dir2')
].then(([tree1, tree2]) => {
console.log(tree1);
console.log(tree2);
});
The TreeView
lets you watch the filesystem.
const { TreeView } = require('node-treeview');
const treeView = new TreeView();
treeview
.on('item'), (item) => {})
.on('ready'), (tree) => {})
.on('add'), (item) => {})
.on('change'), (item) => {})
.on('unlink'), (item) => {})
.on('tree'), (tree) => {})
.on('all'), (event, data) => {});
const watcher = treeview.watch('path/to/dir');
setTimeout(watcher.close, 60000);
Under the hood, the watch
feature is provided by fs.watch
on Mac and Windows, and chokidar
on other platforms.
You should NOT process trees in parallel when you watch the filesystem.
Otherwise the watch
method will not work properly.
TypeScript
Interface overview
export interface IRef {
name: string;
path: string;
pathname: string;
depth: number;
error?: any;
}
export interface IFile extends IRef {
type: 'file';
created: Date;
modified: Date;
size: number;
ext: string;
binary: boolean;
content?: string;
}
export interface IDir extends IRef {
type: 'dir';
created: Date;
modified: Date;
nodes: TreeNode[];
}
export type TreeNode = IFile | IDir | IRef;
export type Event
= 'item'
| 'ready'
| 'tree'
| 'add'
| 'change'
| 'unlink'
| 'all';
Options
export interface IOptsParam {
all?: boolean;
content?: boolean;
depth?: number;
relative?: boolean;
include?: string[];
exclude?: string[];
glob?: string[];
sort?: Sorting;
}
export enum Sorting {
Alpha,
FileFirst,
DirFirst
}
Using typing
import { TreeView } from 'node-treeview';
import * as Model from 'node-treeview/model'
const options: Model.IOptsParam = { depth: 2 };
const path = 'path/to/dir';
const promise: Promise<TreeNode[]> =
new TreeView(options).process(path);
promise.then(tree => {
tree.forEach(item => {
if ((item as Model.IRef).error) {
} else if ((item as Model.IDir).type === 'dir') {
} else if ((item as Model.IFile).type === 'file') {
}
});
});
Helper
flatten
The flatten
helper lets you get a flat version of the tree.
import { TreeView } from 'node-treeview';
import { flatten } from 'node-treeview/helper';
new TreeView().process('path/to/dir').then(tree => {
const flat = flatten(tree);
console.log(flat);
});
Or for JavaScript style using require
:
const { TreeView } = require('node-treeview');
const { flatten } = require('node-treeview/helper');
Here is what the json
output looks like:
[{
"name": "file1.txt",
"path": "path/to/dir",
"pathname": "path/to/dir/file1.txt",
"depth": 0,
"created": "2017-10-23T18:29:28.000Z",
"modified": "2017-10-23T18:29:28.000Z",
"type": "file",
"size": 13,
"ext": "txt",
"binary": false
}, {
"name": "file2.txt",
"path": "path/to/dir/subdir",
"pathname": "path/to/dir/subdir/file2.txt",
"depth": 1,
"created": "2017-10-23T18:29:28.000Z",
"modified": "2017-10-23T18:29:29.000Z",
"type": "file",
"size": 13,
"ext": "txt",
"binary": false
}, {
"name": "logo.png",
"path": "path/to/dir/subdir",
"pathname": "path/to/dir/subdir/logo.png",
"depth": 1,
"created": "2017-10-23T18:29:29.000Z",
"modified": "2017-10-23T18:29:29.000Z",
"type": "file",
"size": 325,
"ext": "png",
"binary": true
}]
clean
The clean
helper lets you clean empty directories from the tree.
import { TreeView } from 'node-treeview';
import { clean } from 'node-treeview/helper';
new TreeView().process('path/to/dir').then(tree => {
const cleaned = clean(tree);
console.log(cleaned);
});
Or for JavaScript style using require
:
const { TreeView } = require('node-treeview');
const { clean } = require('node-treeview/helper');
pretty
The pretty
helper lets you pretty-print the tree.
import { TreeView } from 'node-treeview';
import { pretty } from 'node-treeview/helper';
new TreeView().process('path/to/dir').then(tree => {
console.log(pretty(tree));
});
Here is what the txt
output looks like:
├─ fruits
│ ├─ apple.txt
│ └─ pears.txt
└─ vegetables
├─ bean.txt
├─ potato.txt
└─ endive.txt
With the pretty
helper you have full control over how to render the tree.
import { TreeView } from 'node-treeview';
import { pretty } from 'node-treeview/helper';
new TreeView().process('path/to/dir').then(tree => {
console.log(
pretty(tree, (box: string, item: Model.TreeNode) => {
if ((item as Model.IDir).type === 'dir') {
return box + `(${item.name})`;
} else if ((item as Model.IFile).type === 'file') {
return box + item.name + ` [${(item as Model.IFile).size} bytes]`;
} else {
return box + item.name;
}
})
);
});
Here is what the txt
output looks like:
├─ (fruits)
│ ├─ apple.txt [51 bytes]
│ └─ pears.txt [24 bytes]
└─ (vegetables)
├─ bean.txt [13 bytes]
├─ potato.txt [87 bytes]
└─ endive.txt [69 bytes]
And for quick rendering, use the predefined renderer
functions.
import { TreeView } from 'node-treeview';
import { pretty } from 'node-treeview/helper';
import { renderer } from 'node-treeview/helper/pretty';
new TreeView().process('path/to/dir').then(tree => {
console.log(pretty(tree, renderer.light));
console.log(pretty(tree, renderer.dark));
});
Cli
node-treeview
Usage: node-treeview <path> [options]
Options:
--version, -v Show version number [boolean]
--help, -h Show help [boolean]
--all, -a Include hidden files in output [boolean]
--content, -c Add files content to output [boolean]
--depth, -d Maximum depth of directories [number] [default: -1]
--relative, -r Use relative path [boolean]
--include, -i List of directory paths to include in output [array]
--exclude, -e List of directory paths to exclude from output [array]
--glob, -g Match files based on glob pattern [array]
--sort, -s Sort output 0 (Alpha), 1 (FileFirst), 2 (DirFirst) [number] [default: 0]
--clean, -n Clean empty directories from output [boolean]
--flatten, -f Flatten output [boolean]
--pretty, -p Pretty-print output [string]
--watch, -w Watch filesystem [boolean]
--output, -o Output file path [string]
--debug Add debugging information to output [boolean]
Contribute
git clone https://github.com/avine/node-treeview.git
cd ./node-treeview
npm install
npm run all
License
MIT @ Avine