# all files / file-structure/ Directory.js

100% Statements 127/127
100% Branches 40/40
100% Functions 36/36
100% Lines 42/42
22 statements, 1 function, 18 branches Ignored

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110

    1

    1
    67
    67
    67

    67
    67

    67

    67
    25
    25
    25

    42

    4

    4

    4

    9
    8

    9

    2
    2

    14
    13

    14

    2
    2

    1

    3
    3
    3

    1
    4
    2

    1
    2

    1
    2
    1
    1

    1
    1

     'use strict';

    // Constants:
    import constants from '../constants';

    // Utilities:
    import _ from 'lodash';
    import Promise from 'bluebird';
    const fs = Promise.promisifyAll(require('graceful-fs'));
    import { join, sep } from 'path';

    // Dependencies:
    import files from '../files';

    export default class Directory {
        constructor (path, directory, fileStructure) {
            this.fileStructure = fileStructure;
            this.directory = directory;
            this.path = path;

            this.directories = [];
            this.files = [];
            let [directoryName] = this.path.split(sep).reverse();
            this.name = directoryName;

            if (this.directory) {
                this.type = directory.type || this.name;
                this.extension = directory.extension || constants.EXTENSIONS[this.type];
                this.directory.addDirectory(this);
            } else {
                this.fileStructure.addDirectory(this);
            }
        }

        read () {
            return fs.readdirAsync(this.path)
            .then((itemPaths) => readItems.call(this, itemPaths));
        }

        save () {
            return Promise.map(this.directories, directory => directory.save())
            .then(() => Promise.map(this.files, file => file.save()))
            .then(() => fs.mkdirAsync(this.path))
            .then(() => this.directory.addDirectory(this));
        }

        delete () {
            return Promise.map(this.directories, directory => directory.delete())
            .then(() => Promise.map(this.files, file => file.delete()))
            .then(() => fs.rmdirAsync(this.path))
            .then(() => this.directory.removeDirectory(this));
        }

        addFile (file) {
            if (!_.contains(this.files, file)) {
                this.files.push(file);
            }
            this.fileStructure.addFile(file);
        }

        removeFile (file) {
            _.remove(this.files, file);
            this.fileStructure.removeFile(file);
        }

        addDirectory (directory) {
            if (!_.contains(this.directories, directory)) {
                this.directories.push(directory);
            }
            this.fileStructure.addDirectory(directory);
        }

        removeDirectory (directory) {
            _.remove(this.directories, directory);
            this.fileStructure.removeDirectory(directory);
        }

        getDirectory (name) {
            return _.find(this.directories, directory => directory.name === name);
        }

        toJSON () {
            let { directories, files, name, path } = this;
            directories = _.sortBy(directories, 'name');
            files = _.sortBy(files, 'name');
            return { directories, files, name, path, isDirectory: true };
        }
    }

    function readItems (itemPaths) {
        return Promise.map(itemPaths, (itemPath) => {
            return getItemInfo.call(this, join(this.path, itemPath));
        });
    }

    function getItemInfo (itemPath) {
        return fs.statAsync(itemPath)
        .then(stat => handleItem.call(this, itemPath, stat));
    }

    function handleItem (itemPath, stat) {
        if (stat.isDirectory()) {
            let directory = new Directory(itemPath, this, this.fileStructure);
            return directory.read();
        } else {
            let file = new files[this.type](itemPath, this);
            return file.read();
        }
    }