https://github.com/avine/node-treeview
Asynchronous filesystem tree view for node
https://github.com/avine/node-treeview
asynchronous command-line filesystem glob json node terminal tree treeview typescript watch
Last synced: 4 months ago
JSON representation
Asynchronous filesystem tree view for node
- Host: GitHub
- URL: https://github.com/avine/node-treeview
- Owner: avine
- License: mit
- Created: 2017-10-22T16:58:42.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2018-07-01T23:27:28.000Z (about 8 years ago)
- Last Synced: 2025-03-24T05:13:17.626Z (over 1 year ago)
- Topics: asynchronous, command-line, filesystem, glob, json, node, terminal, tree, treeview, typescript, watch
- Language: TypeScript
- Homepage:
- Size: 580 KB
- Stars: 4
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# node-treeview
Asynchronous filesystem tree view for node.
[](https://travis-ci.org/avine/node-treeview)
## Javascript (quick start)
### Usage
```js
const { TreeView } = require('node-treeview');
// Using callback
new TreeView(options).process(path, (error, tree) => {
if (tree) {
// do some stuff...
} else {
// handle error...
}
});
// Using Promise
new TreeView(options).process(path).then(tree => {
// do some stuff...
}).catch(error => {
// handle error...
});
// Using async/await
async function getTree() {
let tree;
try {
tree = await new TreeView(options).process(path);
} catch (error) {
// handle error...
}
// do some stuff...
}
getTree();
```
### Example
```js
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:
```json
[{
"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..." //-> base64
}]
}]
```
The `TreeView` lets you listen to `item` events.
```js
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:
```txt
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.
```js
const { TreeView } = require('node-treeview');
const treeView = new TreeView({
relative: true
}).on('item', (data, ctx) => {
// Listen to each emitted data in its own context
// ('path/to/dir1' or 'path/to/dir2')
console.log(`${ctx.rootPath} -> ${data.pathname}`);
});
Promise.all[
// Use the same TreeView instance to process different
// paths in parallel with the same options
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.
```js
const { TreeView } = require('node-treeview');
const treeView = new TreeView();
treeview
.on('item'), (item) => {/* Item emitted (discovered, added, modified or removed) */})
.on('ready'), (tree) => {/* Initial tree available */})
.on('add'), (item) => {/* Item added */})
.on('change'), (item) => {/* Item modified */})
.on('unlink'), (item) => {/* Item removed */})
.on('tree'), (tree) => {/* Refreshed tree available (after 'add', 'change' or 'unlink' event) */})
.on('all'), (event, data) => {/* Listen to all events */});
// Start watching
const watcher = treeview.watch('path/to/dir');
// Stop watching after 1mn
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
```ts
// Basic interface of files and directories (used for unreadable resource)
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[];
}
// The final output is of type: `TreeNode[]`
// and the `TreeView.process` method returns a `Promise`
export type TreeNode = IFile | IDir | IRef;
// List of emitted events
export type Event
= 'item'
| 'ready'
| 'tree'
| 'add'
| 'change'
| 'unlink'
| 'all';
```
### Options
```ts
export interface IOptsParam {
// Include hidden files in output
all?: boolean;
// Add files content to output
content?: boolean;
// Maximum depth of directories
depth?: number;
// Use relative path
relative?: boolean;
// List of directory paths to include in output
include?: string[];
// List of directory paths to exclude from output
exclude?: string[];
// Match files based on glob pattern
glob?: string[];
// Sort output
sort?: Sorting;
}
// Tree sort type
export enum Sorting {
Alpha,
FileFirst,
DirFirst
}
```
### Using typing
```ts
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 =
new TreeView(options).process(path);
promise.then(tree => {
tree.forEach(item => {
if ((item as Model.IRef).error) {
// handle error...
} else if ((item as Model.IDir).type === 'dir') {
// handle directory...
} else if ((item as Model.IFile).type === 'file') {
// handle file...
}
});
});
```
## Helper
### flatten
The `flatten` helper lets you get a flat version of the tree.
```ts
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`:
```js
const { TreeView } = require('node-treeview');
const { flatten } = require('node-treeview/helper');
// ...
```
Here is what the `json` output looks like:
```json
[{
"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.
```ts
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`:
```js
const { TreeView } = require('node-treeview');
const { clean } = require('node-treeview/helper');
// ...
```
### pretty
The `pretty` helper lets you pretty-print the tree.
```ts
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:
```txt
├─ 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.
```ts
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:
```txt
├─ (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.
```ts
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
```txt
node-treeview
Usage: node-treeview [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
```bash
git clone https://github.com/avine/node-treeview.git
cd ./node-treeview
npm install
npm run all # npm run clean && npm run build && npm test
```
## License
MIT @ [Avine](https://avine.io)