How to merge all exports from different files into one? - node.js

e.g.
./one.const.js ---------> module.exports = {};
./two.const.js ----------> module.exports = {};
./index.js---------------> module.exports = mergedExports; // mergedExports: {one: {}, two: {}};
In a folder say xyz I have two files with *.const.js filenames and there's one index.js. I want an automated code in index.js which merges all the exports from *.const.js

In a folder say xyz I have two files with *.const.js filenames and there's one index.js
The default behavior of require() is that it will look inside the xyz folder for an index.js if you don't manually specify which file to import.
index.js
exports.One = require("./one.const.js");
exports.Two = require("./two.const.js");
outside.js
const { One, Two } = require("./xyz");

Assuming you want to do this on startup:
const fs = require('fs');
const regex = new RegExp('.const.js$')
const files = fs.readdirSync('.').filter((fileName) => regex.test(fileName))
const mergedExports = {};
for (let i =0; i < files.length; i++) {
const fileName = files[i].split('.const.js')[0]
mergedExports[fileName] = require(`./${files[i]}`)
}
module.exports = mergedExports
If you want to merge the exports into a single object, update the for loop to:
for (let i =0; i < files.length; i++) {
mergedExports = { ...mergedExports,
...require(`./${files[i]}`),
}
}

Related

List of all files required by a Node script

Any thoughts on how I could get an array of file paths required (recursively) by a Node script? For example, given:
a.js
module.exports = {};
b.js
module.exports = {
a : require('./a.js');
};
c.js
const b = require('./b.js');
//etc. etc.
I'd like to run something like:
someAwesomeFunctionOrLibrary(require('./c.js')); // ["./b.js","./a.js"]
A simple solution would be to traverse module.children recursively.
var listModulePaths = (mod) => {
for (var child of mod.children) {
console.log(child.id)
listModulePaths(child)
}
}
listModulePaths(module)

Get new object from another class nodejs

Ok so I have a class that contains
Object JS
var GameServer = require("./GameServer");
var gameServer = new GameServer();
GameServer() contains
GameServer JS
function GameServer() {
// Startup
this.run = true;
this.lastNodeId = 1;
this.lastPlayerId = 1;
this.clients = [];
this.largestClient; // Required for spectators
this.nodes = [];
this.nodesVirus = []; // Virus nodes
this.nodesEjected = []; // Ejected mass nodes
this.nodesPlayer = []; // Nodes controlled by players
}
Now, what im trying to acheive is getting gameServer from ObjectClass
In my class i've tried
new JS
var ObjectClass = require("./ObjectClass");
var gameServer = ObjectClass.gameServer;
But from this way, I won't be able to grab the class GameServer() properties. I'm new to node and im sorry I have to ask this question. I'm currently stuck right now
When I try to grab clients from GameServer
var ObjectClass = require("./ObjectClass");
var gameServer = ObjectClass.gameServer;
gameServer.clients.length;
I get error, clients is undefined. Any way around this?.
I cannot modify GameServer nor Object js.. Basicly im making a script attacthed to a script for extra functionalities.
You are missing the exports of your files so when doing require(file) you're getting and empty object {}..
For gameServer you should be doing something like:
'use strict';
function GameServer() {
// Startup
this.run = true;
this.lastNodeId = 1;
this.lastPlayerId = 1;
this.clients = [];
this.largestClient; // Required for spectators
this.nodes = [];
this.nodesVirus = []; // Virus nodes
this.nodesEjected = []; // Ejected mass nodes
this.nodesPlayer = []; // Nodes controlled by players
}
module.exports = exports = GameServer;
ObjectClass
'use strict';
var GameServer = require("./GameServer");
var gameServer = new GameServer();
exports.gameServer = gameServer;
You need to understand that require cache the value returned by the file, so you would be using a singleton of gameServer.

Multiple requires of same module seem to affect scope of each successive require

I created the following 3 files:
base.js
var base = {};
base.one = 1;
base.two = 2;
base.three = 3;
base.bar = function(){
console.log( this.three );
};
a.js
var base = require('./base');
base.three = 6;
module.exports = base;
b.js
var base = require('./base');
module.exports = base;
test.js
var test_modules = ['a','b'];
test_modules.forEach( function( module_name ){
require( './' + module_name ).bar();
});
And then run test.js like so:
node ./test.js
It outputs this:
6
6
Why is it that when I set the property 'three' of module 'base' in 'a.js', it then affects the object in 'b.js'?
When you require() a module, it is evaluated once and cached so that subsequent require()s for the same module do not have to get loaded from disk and thus get the same exported object. So when you mutate exported properties, all references to that module will see the updated value.
You are introducing global state for base module.
The module a mutated base and then exported it as well, which means that any further references to base will have an updated value.
It is best demonstrated by the following script inside test.js
var testModules = ['b', 'a'];
testModules.forEach(function(module) {
require('./' + module).bar();
});
Now when you run node test.js, you'll see
3
6
Why?
Because the order of inclusion of the modules changed.
How do I solve this?
Simple, get rid of global state. One option is to use prototypes like so
var Base = function() {
this.one = 1;
this.two = 2;
this.three = 3;
};
Base.prototype.bar = function() {
console.log(this.three);
};
module.exports = Base;
And then, inside a.js
var Base = require('./base');
var baseInstance = new Base();
baseInstance.three = 6;
module.exports = baseInstance;
And inside b.js
var Base = require('./base');
module.exports = new Base();
Now when you run your original test.js, the output should be
6
3

Get latest files inside a folder

i have a folder stucture like
var/
testfolder1/
myfile.rb
data.rb
testfolder2/
home.rb
sub.rb
sample.rb
rute.rb
inside var folder contains subfolders(testfolder1,testfolder2) and some files(sample.rb,rute.rb)
in the following code returing a josn object that contains folders and files inside the var folder
like
{
'0': ['sample.rb', 'rute.rb'],
testfolder1: ['myfile.rb',
'data.rb',
],
testfolder2: ['home.rb',
'sub.rb',
]
}
code
var scriptsWithGroup = {};
fs.readdir('/home/var/', function(err, subfolder) {
if(err) return context.sendJson({}, 200);
var scripts = [];
for (var j = 0; j < subfolder.length; j++) {
var scriptsInFolder = [];
if(fs.lstatSync(scriptPath + subfolder[j]).isDirectory()) {
fs.readdirSync(scriptPath + subfolder[j]).forEach(function(file) {
if (file.substr(file.length - 3) == '.rb')
scriptsInFolder.push(file);
});
scriptsWithGroup[subfolder[j]] = scriptsInFolder;
} else {
if (subfolder[j].substr(subfolder[j].length - 3) == '.rb')
scripts.push(subfolder[j]);
}
}
scriptsWithGroup["0"] = scripts;
console.log(scriptsWithGroup)
context.sendJson(scriptsWithGroup, 200);
});
What i need is i want to return the latest modified or created files.here i only use 2 files inside folders it contains lots of files.so i want to return latest created ones
I'm going to assume here that you want only the most recent two files. If you actually want them all, just sorted, just remove the slice portion of this:
scriptsInFolder = scriptsInFolder.sort(function(a, b) {
// or mtime, if you're only wanting file changes and not file attribute changes
var time1 = fs.statSync(a).ctime;
var time2 = fs.statSync(b).ctime;
if (time1 < time2) return -1;
if (time1 > time2) return 1;
return 0;
}).slice(0, 2);
I'll add, however, that it's typically considered best practice not to use to the synchronize fs methods (e.g. fs.statSync). If you're able to install async, that would be a good alternative approach.
const fs = require('fs');
const path = require('path');
const getMostRecentFile = (dir) => {
const files = orderReccentFiles(dir);
return files.length ? files[0] : undefined;
};
const orderReccentFiles = (dir) => {
return fs.readdirSync(dir)
.filter(file => fs.lstatSync(path.join(dir, file)).isFile())
.map(file => ({ file, mtime: fs.lstatSync(path.join(dir, file)).mtime }))
.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
};
const dirPath = '<PATH>';
console.log(getMostRecentFile(dirPath));

node.js require all files in a folder?

How do I require all files in a folder in node.js?
need something like:
files.forEach(function (v,k){
// require routes
require('./routes/'+v);
}};
When require is given the path of a folder, it'll look for an index.js file in that folder; if there is one, it uses that, and if there isn't, it fails.
It would probably make most sense (if you have control over the folder) to create an index.js file and then assign all the "modules" and then simply require that.
yourfile.js
var routes = require("./routes");
index.js
exports.something = require("./routes/something.js");
exports.others = require("./routes/others.js");
If you don't know the filenames you should write some kind of loader.
Working example of a loader:
var normalizedPath = require("path").join(__dirname, "routes");
require("fs").readdirSync(normalizedPath).forEach(function(file) {
require("./routes/" + file);
});
// Continue application logic here
I recommend using glob to accomplish that task.
var glob = require( 'glob' )
, path = require( 'path' );
glob.sync( './routes/**/*.js' ).forEach( function( file ) {
require( path.resolve( file ) );
});
Base on #tbranyen's solution, I create an index.js file that load arbitrary javascripts under current folder as part of the exports.
// Load `*.js` under current directory as properties
// i.e., `User.js` will become `exports['User']` or `exports.User`
require('fs').readdirSync(__dirname + '/').forEach(function(file) {
if (file.match(/\.js$/) !== null && file !== 'index.js') {
var name = file.replace('.js', '');
exports[name] = require('./' + file);
}
});
Then you can require this directory from any where else.
Another option is to use the package require-dir which let's you do the following. It supports recursion as well.
var requireDir = require('require-dir');
var dir = requireDir('./path/to/dir');
I have a folder /fields full of files with a single class each, ex:
fields/Text.js -> Test class
fields/Checkbox.js -> Checkbox class
Drop this in fields/index.js to export each class:
var collectExports, fs, path,
__hasProp = {}.hasOwnProperty;
fs = require('fs');
path = require('path');
collectExports = function(file) {
var func, include, _results;
if (path.extname(file) === '.js' && file !== 'index.js') {
include = require('./' + file);
_results = [];
for (func in include) {
if (!__hasProp.call(include, func)) continue;
_results.push(exports[func] = include[func]);
}
return _results;
}
};
fs.readdirSync('./fields/').forEach(collectExports);
This makes the modules act more like they would in Python:
var text = new Fields.Text()
var checkbox = new Fields.Checkbox()
One more option is require-dir-all combining features from most popular packages.
Most popular require-dir does not have options to filter the files/dirs and does not have map function (see below), but uses small trick to find module's current path.
Second by popularity require-all has regexp filtering and preprocessing, but lacks relative path, so you need to use __dirname (this has pros and contras) like:
var libs = require('require-all')(__dirname + '/lib');
Mentioned here require-index is quite minimalistic.
With map you may do some preprocessing, like create objects and pass config values (assuming modules below exports constructors):
// Store config for each module in config object properties
// with property names corresponding to module names
var config = {
module1: { value: 'config1' },
module2: { value: 'config2' }
};
// Require all files in modules subdirectory
var modules = require('require-dir-all')(
'modules', // Directory to require
{ // Options
// function to be post-processed over exported object for each require'd module
map: function(reqModule) {
// create new object with corresponding config passed to constructor
reqModule.exports = new reqModule.exports( config[reqModule.name] );
}
}
);
// Now `modules` object holds not exported constructors,
// but objects constructed using values provided in `config`.
I know this question is 5+ years old, and the given answers are good, but I wanted something a bit more powerful for express, so i created the express-map2 package for npm. I was going to name it simply express-map, however the people at yahoo already have a package with that name, so i had to rename my package.
1. basic usage:
app.js (or whatever you call it)
var app = require('express'); // 1. include express
app.set('controllers',__dirname+'/controllers/');// 2. set path to your controllers.
require('express-map2')(app); // 3. patch map() into express
app.map({
'GET /':'test',
'GET /foo':'middleware.foo,test',
'GET /bar':'middleware.bar,test'// seperate your handlers with a comma.
});
controller usage:
//single function
module.exports = function(req,res){
};
//export an object with multiple functions.
module.exports = {
foo: function(req,res){
},
bar: function(req,res){
}
};
2. advanced usage, with prefixes:
app.map('/api/v1/books',{
'GET /': 'books.list', // GET /api/v1/books
'GET /:id': 'books.loadOne', // GET /api/v1/books/5
'DELETE /:id': 'books.delete', // DELETE /api/v1/books/5
'PUT /:id': 'books.update', // PUT /api/v1/books/5
'POST /': 'books.create' // POST /api/v1/books
});
As you can see, this saves a ton of time and makes the routing of your application dead simple to write, maintain, and understand. it supports all of the http verbs that express supports, as well as the special .all() method.
npm package: https://www.npmjs.com/package/express-map2
github repo: https://github.com/r3wt/express-map
Expanding on this glob solution. Do this if you want to import all modules from a directory into index.js and then import that index.js in another part of the application. Note that template literals aren't supported by the highlighting engine used by stackoverflow so the code might look strange here.
const glob = require("glob");
let allOfThem = {};
glob.sync(`${__dirname}/*.js`).forEach((file) => {
/* see note about this in example below */
allOfThem = { ...allOfThem, ...require(file) };
});
module.exports = allOfThem;
Full Example
Directory structure
globExample/example.js
globExample/foobars/index.js
globExample/foobars/unexpected.js
globExample/foobars/barit.js
globExample/foobars/fooit.js
globExample/example.js
const { foo, bar, keepit } = require('./foobars/index');
const longStyle = require('./foobars/index');
console.log(foo()); // foo ran
console.log(bar()); // bar ran
console.log(keepit()); // keepit ran unexpected
console.log(longStyle.foo()); // foo ran
console.log(longStyle.bar()); // bar ran
console.log(longStyle.keepit()); // keepit ran unexpected
globExample/foobars/index.js
const glob = require("glob");
/*
Note the following style also works with multiple exports per file (barit.js example)
but will overwrite if you have 2 exports with the same
name (unexpected.js and barit.js have a keepit function) in the files being imported. As a result, this method is best used when
your exporting one module per file and use the filename to easily identify what is in it.
Also Note: This ignores itself (index.js) by default to prevent infinite loop.
*/
let allOfThem = {};
glob.sync(`${__dirname}/*.js`).forEach((file) => {
allOfThem = { ...allOfThem, ...require(file) };
});
module.exports = allOfThem;
globExample/foobars/unexpected.js
exports.keepit = () => 'keepit ran unexpected';
globExample/foobars/barit.js
exports.bar = () => 'bar run';
exports.keepit = () => 'keepit ran';
globExample/foobars/fooit.js
exports.foo = () => 'foo ran';
From inside project with glob installed, run node example.js
$ node example.js
foo ran
bar run
keepit ran unexpected
foo ran
bar run
keepit ran unexpected
One module that I have been using for this exact use case is require-all.
It recursively requires all files in a given directory and its sub directories as long they don't match the excludeDirs property.
It also allows specifying a file filter and how to derive the keys of the returned hash from the filenames.
Require all files from routes folder and apply as middleware. No external modules needed.
// require
const { readdirSync } = require("fs");
// apply as middleware
readdirSync("./routes").map((r) => app.use("/api", require("./routes/" + r)));
I'm using node modules copy-to module to create a single file to require all the files in our NodeJS-based system.
The code for our utility file looks like this:
/**
* Module dependencies.
*/
var copy = require('copy-to');
copy(require('./module1'))
.and(require('./module2'))
.and(require('./module3'))
.to(module.exports);
In all of the files, most functions are written as exports, like so:
exports.function1 = function () { // function contents };
exports.function2 = function () { // function contents };
exports.function3 = function () { // function contents };
So, then to use any function from a file, you just call:
var utility = require('./utility');
var response = utility.function2(); // or whatever the name of the function is
Can use : https://www.npmjs.com/package/require-file-directory
Require selected files with name only or all files.
No need of absoulute path.
Easy to understand and use.
Using this function you can require a whole dir.
const GetAllModules = ( dirname ) => {
if ( dirname ) {
let dirItems = require( "fs" ).readdirSync( dirname );
return dirItems.reduce( ( acc, value, index ) => {
if ( PATH.extname( value ) == ".js" && value.toLowerCase() != "index.js" ) {
let moduleName = value.replace( /.js/g, '' );
acc[ moduleName ] = require( `${dirname}/${moduleName}` );
}
return acc;
}, {} );
}
}
// calling this function.
let dirModules = GetAllModules(__dirname);
Create an index.js file in your folder with this code :
const fs = require('fs')
const files = fs.readdirSync('./routes')
for (const file of files) {
require('./'+file)
}
And after that you can simply load all the folder with require("./routes")
If you include all files of *.js in directory example ("app/lib/*.js"):
In directory app/lib
example.js:
module.exports = function (example) { }
example-2.js:
module.exports = function (example2) { }
In directory app create index.js
index.js:
module.exports = require('./app/lib');

Resources