HEX
Server: Apache
System: Linux webd004.cluster130.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64
User: frenchy (106757)
PHP: 7.4.33
Disabled: _dyuweyrj4,_dyuweyrj4r,dl
Upload Files
File: /home/frenchy/www/french-american.org/current/node_modules/@frctl/fractal/src/core/fs.js
'use strict';

const Promise = require('bluebird');
const Path = require('path');
const co = require('co');
const _ = require('lodash');
const fs = Promise.promisifyAll(require('fs'));
const readFile = Promise.promisify(fs.readFile);
const isBinary = Promise.promisify(require('istextorbinary').isBinary);
const utils = require('./utils');
const glob = require('globby');

const notBinary = ['.nunj', '.nunjucks', '.hbs', '.handlebars', '.jsx', '.twig']; // TODO: handle this in a scalable, extendable way

module.exports = {

    describe(dir, relDir, filter) {
        filter = filter || (filePath => !(/(^|\/)\.[^\/\.]/g).test(filePath));

        return dirscribe(dir, {
            filter: filter,
            after: files => _.orderBy(files, ['isDirectory', 'order', 'path'], ['desc', 'asc', 'asc']),
            build: build,
        });
    },

    globDescribe(dir, relDir, match) {
        return glob(match, {
            cwd: dir,
        }).then(matches => {
            const directories = [];
            matches.forEach(path => {
                const parts = Path.parse(path).dir.split('/');
                const buildPath = [];
                parts.forEach(part => {
                    buildPath.push(part);
                    directories.push(buildPath.join('/'));
                });
            });
            const included = _.uniq(directories.concat(matches)).map(p => Path.join(dir, p));
            return this.describe(dir, relDir, filePath => {
                return _.includes(included, filePath);
            });
        });
    },

    find(filePath) {
        return fs.statAsync(filePath).then((stat) => {
            return build(filePath, stat, Path.parse(filePath).dir);
        });
    }

};

function build(filePath, stat, root) {
    return co(function* () {
        const p = Path.parse(filePath);
        p.relPath = Path.relative(root, filePath);
        p.fsName = p.name;
        p.name = _.get(p.fsName.match(/^_?(\d+\-)?(.*)/), 2, p.fsName);
        p.path = filePath;
        p.dirs = _.compact(p.dir.split('/'));
        p.isHidden = !!(_.find(p.relPath.split('/'), s => s.startsWith('_')) || p.fsName.startsWith('_'));
        p.order = parseInt(_.get(p.fsName.match(/^_?(\d+)\-.*/), 1, 1000000), 10);
        p.ext = p.ext.toLowerCase();
        p.isFile = stat.isFile();
        p.isDirectory = stat.isDirectory();
        p.stat = stat;
        if (p.isFile) {
            p.lang = utils.lang(filePath);
            p.isBinary = yield checkIsBinary(p);
            p.readBuffer = function () {
                return fs.readFileSync(filePath);
            };
            p.readSync = function () {
                const contents = p.isBinary ? fs.readFileSync(filePath) : fs.readFileSync(filePath, 'utf8');
                return contents.toString();
            };
            p.read = function () {
                const read = p.isBinary ? readFile(filePath) : readFile(filePath, 'utf8');
                return read.then(function (contents) {
                    return contents.toString();
                });
            };
        }
        p.toString = function () {
            return p.path;
        };
        p.toJSON = function () {
            const self = _.clone(this);
            return self;
        };
        return p;
    });
}

function dirscribe(root, opts) {
    opts = opts || {};
    const filter = opts.filter || (i => true);
    const after = opts.after || (i => i);
    const build = opts.build || buildDefault;
    const recursive = opts.recursive === false ? false : true;
    const childrenKey = opts.childrenKey || 'children';

    function readdir(dir) {
        return fs.readdirAsync(dir)
            .filter(file => filter(Path.join(dir, file)))
            .map(filePath => objectify(Path.join(dir, filePath)))
            .then(after);
    }

    function objectify(filePath) {
        let statCache;
        return fs.statAsync(filePath).then(function (stat) {
            statCache = stat;
            return build(filePath, stat, root);
        }).then(function (desc) {
            if (recursive && statCache.isDirectory()) {
                return readdir(filePath).then(function (children) {
                    desc.children = children;
                    return desc;
                });
            }

            return desc;
        });
    }

    function buildDefault(filePath, stat) {
        const p = Path.parse(filePath);
        p.path = filePath;
        p.stat = stat;
        return p;
    }

    return objectify(root);
}

function checkIsBinary(file) {
    if (_.includes(notBinary, file.ext)) {
        return Promise.resolve(false);
    }
    return isBinary(file.path, null);
}