fstack

    0.2.27 • Public • Published

    fstack

    Build Status NPM version Dependency Status

    A lightweight and efficient driver stack to easily manage and maintain a filesystem. fstack is the missing filesystem wrangler for Node.js.

    fstack provides a simple and optimized interface for accessing a filesystem and deriving logical structures by utilizing the fs core library. fstack features high-level filesystem operations such as asynchronous atomic implementations of copy, move, rm -rf, and mkdir -p. fstack can also derive a filesystem tree object based on a supplied path, providing numerous solutions for filesystem dependent applications. fstack is designed to replace other npm packages such as fs-extra, file, and node-dir. fstack also extends path and os, for convenience.

    fstack's implementations of mkdir -p and rm -rf are more efficient than those found in the mkdirp and rimraf packages, respectively.

    Read more on why rimraf is a hack.

    Installing

    npm install --save fstack

    Usage

    var fstack = require('fstack');

    Benchmark (As of 0.2.18)

    i in {0..99} `mkdir -p (i)\(i * 2)`
    mkdirp 0 s, 9.906 ms
    fstack 0 s, 3.743 ms
    
    i in {0..99} `rm -rf i`
    rimraf 0 s, 23.996 ms
    fstack 0 s, 16.413 ms
    

    Documentation

    fstack.ents(path, callback, [stat])

    fstack.ents(path, callback, [stat]) will return all of the immediate child entities inside path and callback with (err, ents), where ents is an array containing entity names if stat is not specified, and will callback with (err, ents, stats) if stat is specified.

    /*
    foo/
        bar/
            baz
        qux
    */
    
    fstack.ents('./foo', function(err, ents) {
        console.log(ents);
    });
    
    // ['bar', 'qux']
    

    fstack.dirs(path, callback)

    fstack.dirs(path, callback) will return all of the immediate child directories inside path and callback with (err, dirs), where dirs is an associative array containing directory names as keys and stats as values.

    /*
    foo/
        bar/
            baz
        qux
    */
    
    fstack.dirs('./foo', function(err, dirs) {
        console.log(dirs);
    });
    
    // ['bar']
    

    fstack.files(path, callback)

    fstack.ents(path, callback) will return all of the immediate child non-directories inside path and callback with (err, files), where files is an associative array containing non-directory names as keys and stats as values.

    /*
    foo/
        bar/
            baz
        qux
    */
    
    fstack.files('./foo', function(err, files) {
        console.log(files);
    });
    
    // ['qux']
    

    fstack.fst(path, callback, [depth])

    fstack.fst(path, callback, [depth]) will callback with (err, fst), where fst is an object representing the filesystem with path as the root node. depth is the number of levels to recursively crawl the filesystem, and defaults to null, which does a complete crawl. Calling fstack#fst with a depth of 1 or 2 is a good strategy for returning an object that will represent a filesystem client-side. Directories will contain an object representing its children, while non-directories will contain their device types, which is usually 'file'.

    /*
    foo/
        bar/
            baz
        quux/
            corge/
                garply
            grault
        qux
    */
    
    fstack.fst('./foo', function(err, fst) {
        console.log(JSON.stringify(fst, null, 4));
    });
    
    /*
    {
        "qux": "file",
        "bar": {
            "baz": "file"
        },
        "quux": {
            "grault": "file",
            "corge": {
                "garply": "file"
            }
        }
    }
    */
    
    fstack.fst('./foo', function(err, fst) {
        console.log(JSON.stringify(fst, null, 4));
    }, 1);
    
    /*
    {
        "bar": {},
        "quux": {},
        "qux": "file"
    }
    */
    

    fstack.fso

    Alias of fstack#fst.

    fstack.device(path, callback)

    fstack.device(path, callback) will check the device type of path and callback with (err, mode), where mode is the determined device type of path.

    Device types are file, directory, block-device, char-device, link, fifo, socket, and unknown.

    /*
    foo/
        bar/
            baz
        qux
    */
    
    fstack.device('./foo', function(err, mode) {
        console.log(mode);
    });
    
    // 'directory'
    

    fstack.mkdir(path, callback, [force])

    fstack.mkdir(path, callback, [force]) will create the directory path if it does not already exist, and callback with (err). If force is specified, the directory will be created without checks. fstack#mkdir will callback with (err, made).

    /*
    foo/
        bar/
            baz
        qux
    */
    
    fstack.mkdir('./foo/quux', function(err) {
        
    });
    
    /*
    foo/
        bar/
            baz
        quux/
        qux
    */
    

    fstack.mkdirp(path, callback, [force])

    fstack.mkdirp(path, callback, [force]) will recursively create each directory that leads to path if any do not already exist, and callback with (err). If force is specified, directories will be created without checks. fstack#mkdirp will callback with (err).

    /*
    foo/
        bar/
            baz
        qux
    */
    
    fstack.mkdirp('./foo/quux/corge', function(err) {
        
    });
    
    /*
    foo/
        bar/
            baz
        quux/
            corge/
        qux
    */
    

    fstack.copy(source, destination, callback)

    fstack.copy(source, destination, callback) will recursively copy each directory and file from source to destination if source is a directory, and it will copy source to directory if source is a file. fstack#copy will create any missing directories in the process. Files in destination with the same name as files in source will be overwritten. fstack#copy will callback with (err).

    /*
    foo/
        bar/
            baz
        qux
    */
    
    fstack.copy('./foo', './quux', function(err) {
        
    });
    
    /*
    foo/
        bar/
            baz
        qux
    quux/
        bar/
            baz
        qux
    */
    

    fstack.move(source, destination, callback)

    fstack.move(source, destination, callback) will recursively move each directory and file from source to destination if source is a directory, using fs#rename when possible. It will move source to directory if source is a file. fstack#move will create any missing directories in the process. Files in destination with the same name as files in source will be overwritten. fstack#move will callback with (err).

    /*
    foo/
        bar/
            baz
        qux
    */
    
    fstack.move('./foo', './quux', function(err) {
        
    });
    
    /*
    quux/
        bar/
            baz
        qux
    */
    

    fstack.delete(path, callback)

    fstack.delete(path, callback) will recursively delete each directory and file in path, if path is a directory, while it will delete path if it is a non-directory. fstack#delete will callback with (err).

    /*
    foo/
        bar/
            baz
        qux
    */
    
    fstack.delete('./foo', function(err) {
        
    });
    
    /*
    
    */
    

    fstack.checkFile(path, callback)

    fstack.checkFile(path, callback) will check if path exists as a non-directory and callback with (err, stat), where stat is the stat of path.

    fstack.checkDir(path, callback)

    fstack.checkDir(path, callback) will check if path exists as a directory and callback with (err, stat), where stat is the stat of path.

    fstack.json(path, callback, [explicit])

    fstack.json(path, callback, [explicit]) will read the json from path if it is a file. explicit defaults to false, where it may append '.json' to the supplied path so that the file may be accessed without requiring the '.json' extension. fstack#json(path, callback, explicit) will callback with (err, json), where json is the parsed object for the file at path.

    /*
    test.json
        {
            "a": "b",
            "c": {
                "d": "e"
            }
        }
    */
    
    fstack.json('./test.json', function(err, json) {
        console.log(json.c);
    });
    
    // { d: 'e' }
    

    fstack.read(path, callback)

    fstack#read behaves the same way as fs#readFile, but first performs a check to see whether the supplied file exists.

    fstack.readStream(path, callback)

    fstack.readStream(path, callback) will create a Readable Stream for path and callback with (err, stream).

    fstack.write(path, callback)

    fstack#write behaves the same way as fs#writeFile, but first performs a check to see whether the supplied file exists.

    fstack.writeStream(path, callback)

    fstack.writeStream(path, callback) will create a Writable Stream for path and callback with (err, stream).

    fstack.append(path, callback)

    fstack#append behaves the same way as fs#append, but first performs a check to see whether the supplied file exists.

    rimraf

    The package rimraf, which is a popular implementation of rm -rf for Node.js, actually depends on making assumptions about files and directories during the removal of entities. rimraf must choose between assuming that there is a file and assuming that there is a directory, and makes the smarter decision favoring the existence files, but this also means that for any call to rimraf where the path given contains at least one child directory, the kernel will return an error, and a new deletion request must be made. Such system calls are expensive. Instead, fstack uses its built-in entity separator to asynchronously unlink files and rmdir directories, after the children of those directories have been unlink'd or rmdir'd.

    Install

    npm i fstack

    DownloadsWeekly Downloads

    4

    Version

    0.2.27

    License

    MIT

    Last publish

    Collaborators

    • synchronous