brfs icon indicating copy to clipboard operation
brfs copied to clipboard

support fs.readdir and fs.readdirSync

Open yamadapc opened this issue 10 years ago • 9 comments

I think this is feasible, and I personally think this is really useful.

In node.js it's reasonably common for me to do things like:

// controllers/index.js
'use strict';
var fs = require('fs');
var path = require('path');

var ROOT_PATH = __dirname;

module.exports = function(path) {
  var fnames = fs.readdirSync(ROOT_PATH);

  var paths = fnames.map(function(fname) {
    return path.join(ROOT_PATH, fname, '.js');
  });

  var modules = paths.map(function(path) {
    return require(path);
  });

  return modules.map(function(module) {
    // do something with the module
    // i.e. if it's this is a mongoose schema bootstrapping utility, register the model.
    //       if this is a express controller bootstrapping utility, parse its methods and register
   //        matching routes.
   //        etc.
  });
};

This allows us to abstract whole parts of the code, later on - even treat them as completely separate modules:

// app.js
var controllers = require('./controllers')

// bootstrap the controllers
controllers(/* something would come here such as an express app or a mongoose.Connection */);

If we could do this with browserify, things like bootstrapping an Ember app, could be automated. I know there are a couple of problems.

Here's an analogous example that works, though not exactly as one would hope it'd.

I know this has to do with limitations on the browserify module (which may be impossible to address) but this would be really cool.

Perhaps we could even parse things like:

['./a', './b'].map(function(name) {
  return require(name);
});

Into:

[require('./a'), require('./b')];

Or provide an utility requireMap thing that resolved into that.

I don't know if this is a relevant issue. But I though this would be a nice thing, if it was possible.

At it's core, the main point was simply to add:

var fs = require('fs');
var files = fs.readdirSync('.');

To be transformed into:

var fs = require('fs');
var files = ['a.js', 'b.js', 'main.js' /* etc. */];

What do you think?

yamadapc avatar Apr 04 '14 14:04 yamadapc

There is now a pull request to enable this; see #21.

CoolOppo avatar May 30 '14 23:05 CoolOppo

I don't really understand the use-case for this feature since browserify can only read require() calls that are statically analyzable.

ghost avatar May 30 '14 23:05 ghost

Dependencies wouldn't be parsed, but by passing the required source files manually into browserify, it should work; no?

yamadapc avatar May 30 '14 23:05 yamadapc

Here's a use-case : For example we have a Listeners\... folder looks like:

Listeners\
    KeyListener.js
    MouseListener.js
    ...

Each listener module have a bind function. So with one line I want to require all listener modules and call the bind function on each.

/**
 * Use require() or I don't know something like requireFolder()
 */
var listeners = require('./Listeners');

listeners.forEach(function(listener){
    listeners.bind();
});

So before browerify the index.js, maybe it should transform it like this :

var listeners = [
    require('./Listeners/KeyListener.js'),
    require('./Listeners/MouseListener.js'),
    ...
];

or

var listeners = {
    KeyListener: require('./Listeners/KeyListener.js'),
    MouseListener: require('./Listeners/MouseListener.js'),
    ...
};

I need something like this in my project.

krypter avatar Oct 29 '14 15:10 krypter

I'd like to have a file that require()s all files in a directory, then make a bundle with browserify. I think this would be useful, or basically supporting require-all.

trusktr avatar Jan 12 '15 10:01 trusktr

it would be cool if there was some way this could work:

var fs = require('fs');

var templates = {};

fs.readdirSync(__dirname + '/../templates').forEach(function (filename) {
  templates[filename] = fs.readFileSync(__dirname + '/../templates/' + filename, 'utf-8');
});

callumlocke avatar Apr 21 '15 13:04 callumlocke

Did someone find a solution/workaround for this issue? Tried require-all as @callumlocke suggested, but of course it has the same limitation, because it uses readdirSync..

christian-fei avatar Sep 29 '15 14:09 christian-fei

@callumlocke I don't think you can use both readdir and readFile in the same snippet since brfs it won't be able to statically evaluate it. you always need to maintain the list of files manually in the code, IMO the best you can do is maintaiining the array of files in the code:

const fs = require('fs')
const path = require('path')

const names = ['exampleList.hbs','layout.hbs']
const templates = names.map(name=>({name, content: fs.readFileSync(path.join(__dirname, 'exampleList.hbs')).toString()}))

If you really need to do serialize files automatically you can use tools like https://github.com/cancerberoSgx/fs-to-json - will serialize a glob in a json file that you can require() or import . As brfs this is a build-time tool. Perhaps would be interesting to implement a browserify transformation with which you can perform var folderJson = fsToJson({input: './src/templates/**/*.hbs'}) - I think globs are more expressive than readdir and readFile and you can do what you want with just one expression... will investigate when I have time.

cancerberoSgx avatar Jun 30 '18 00:06 cancerberoSgx

@callumlocke finally made it and working fine! https://github.com/cancerberoSgx/br-fs-to-json packing a glob of files is what I always wanted and since you will be requiring a "strange" library fs-to-json I make sure it doesn't contaminate your project with its dependencies. Much more practical than brfs IMO

cancerberoSgx avatar Jul 01 '18 06:07 cancerberoSgx