Fir the longest time I have been having to require every file i need to use at the top of of every file that needs to use said file like so:
var moduleAPartOne = require('./module.a.one.js');
var moduleAPartTwo = require('./module.a.two.js');
var moduleAPartThree = require('./module.a.three.js');
In a large scale application this makes maintaining and making changes to the structure of the app down the road a hassle.
I am trying to put all these file requires into a single file which other files can call like so:
// a.module.js
module.exports = {
aOne: require('./a.one.js'),
aTwo: require('./a.two.js'),
aThree: require('./a.three.js')
}
// then in my other files elsewhere in the app
var aModule = require('a/a.module.js');
The object I expect to get out of this is:
aModule = {
aOne: { // some stuff... },
aTwo: { // some stuff... },
aThree: { // some stuff... }
}
instead I get:
aModule = {};
What do I need to do in order for aModule to be populated with properties and methods created in the files it required?
Related
I want to launch a js file in a js file with different permission. Just like this:
main.js (which gets started)
config = JSON.parse(require("./config.json")) // <- should be possible
console.log(config.authkey) // <- should be possible
require("./randomJSFile.js").run()
randomJSFile.js (which will be executed by main.js)
exports.run = () => {
let config = JSON.parse(require("./config.json") // <--- this should not be possible, only the main.js file should have access to the config.json file
console.log(config.authkey) // should not be possible
}
Does anyone know how to do something like that?
Based on a snippet from this question here you could possibly override the require function to check for the filename, something like this:
const Module = require('module');
const originalRequire = Module.prototype.require;
Module.prototype.require = function() {
if (!arguments.length || typeof arguments[0] !== 'string') return {};
if (arguments[0].includes('config.json')) return {};
return originalRequire.apply(this, arguments);
};
And then perform this override after you've already required the config in your main file, so you don't accidentally block yourself
In Node.JS, I'm trying to "reload" a file. I have the following code:
delete require.cache[require.resolve("./pathToFile/" + restartModule)]
with restartModule being the file name, but I'm not sure how I could add the file back using require() and define it as the variable restartModule. For example, if restartModule is myModule, how would I add myModule.js into the var called myModule? Or maybe there's an easier way to simply "reload" a file in the cache?
You could do something simple enough like this:
function reloadModule(moduleName){
delete require.cache[require.resolve(moduleName)]
console.log('reloadModule: Reloading ' + moduleName + "...");
return require(moduleName)
}
var restartModule= reloadModule('./restartModule.js');
You would have to call reloadModule every time you want to reload the source though. You could simplify by wrapping like:
var getRestartModule = function() {
return reloadModule('./restartModule.js');
}
getRestartModule().doStuff();
Or
var reloadModules = function() {
return {
restartModule = reloadModule('./restartModule.js');
};
}
var modules = reloadModules();
modules.restartModule.doStuff();
Or:
var reloadModules = function(moduleList) {
var result = {};
moduleList.forEach((module) => {
result[module.name] = reloadModule(module.path);
});
}
var modules = reloadModules([{name: 'restartModule', path: './restartModule.js'}]);
modules.restartModule.doStuff();
You could even put the module reload on a setInterval so modules would get loaded every N seconds.
Then there's always nodemon: https://nodemon.io/ this is useful in development, whenever a source file changes it will reload your server.
You just use it like node, e.g.
nodemon server.js
i built an app on 1 page, and now i want to oragenize all of its functions and objects in seperate files and directories, and import them to the app.js file. but im having some problems with global objects, the the imported functions dosent recognize them.
example:
//app.js
const req_obj = require("./objectFile.js")
const tool = {
number:4
}
req_obj.obj.addFive() // this will print "cant read number of undefined"
//objectFile.js
const req_func = require("./function.js")
exports.obj = {
addFive:req_func.addFive
}
//function.js
exports.addFive = function(){
return tool.number + 5
}
i know that it might be that im doing all wrong, and this is not how you orgenize an app and call its function. i whould be really glad if some1 will explaine my how to orgenize an app, and call its functions the right way, if what i did is wrong.
The only possibility you have to get access to variables from multiple files is to have them in a separate file and export them like this:
// objects.js
const tool = {
number:4
}
exports.tool = tool
Which then makes your app.js look like:
//app.js
const req_obj = require("./objectFile.js")
const tool = require("./objects.js").tool
// this will read 9
console.log(req_obj.obj.addFive())
And your function.js then becomes:
const tool = require("./objects.js").tool
exports.addFive = function(){
return tool.number + 5
}
Hope it helps.
I am using the below code to split up a user provided path, create all intermediate dirs in the path and attach a timestamp to the ending file name. I am splitting the path with / first and then using forEach over the resulting array. Is there any better way/direct lib function to do this in javascript / nodejs.
function test(usrPath) {
var locMatches = usrPath.split("/")
locMatches.forEach (function (item) {
location = pathUtils.join(location,item)
if (!fs.existsSync(location)) {
fs.mkdirSync(location)
}
})
return pathUtils.join (location,usrPath + (new Date).toISOString().replace(/(^\d\d\d\d)|-|:|(\..*)/g,"").replace("T","_")+".log")
}
Ok, so there are path utils that allow to make the implementation better across platform.
Also, it gives a better managed access for working with path elements like root, dir, filename and extension. pathUtils.sep allows working on the dir elements more cross platform.
var pathUtils = require('path')
function test(usrPath) {
var pathElements = pathUtils.parse(usrPath)
pathElements.dir.split(pathUtils.sep).forEach (function (item) {
location = pathUtils.join(location,item)
if (!fs.existsSync(location)) {
fs.mkdirSync(location)
}
})
return pathUtils.join (location,pathElements.name + (new Date).toISOString().replace(/(^\d\d\d\d)|-|:|(\..*)/g,"").replace("T","_")+pathElements.ext.replace(/^$/i,".log"))
}
I'm writing a nodeJs application that uses google flat buffer.
I installed flatc on my macbook pro and compiled the following schema:
namespace MyAlcoholist;
table Drink {
drink_type_name: string;
drink_company_name: string;
drink_brand_name: string;
drink_flavor_type_name : string;
liquid_color_type_name : string;
liquid_color_is_transparent : bool;
alcohol_vol : float;
calories_for_100g : uint;
global_image_id: ulong;
drink_flavor_id: ulong;
}
table Drinks { drinks:[Drink]; }
root_type Drinks;
the schema file is called drink.fbs and it generated a javascript file called drink_generated.js
I include this file in my nodejs application and add data to it using the following code.. this is my flatBufferUtil.js utility file.
var flatbuffers = require('../js/flatbuffers').flatbuffers;
var builder = new flatbuffers.Builder();
var drinks = require('../fbs/drinks_generated').MyAlcoholist; // Generated by `flatc`.
function drinkArrayToBuffer(drinkArray) {
var drinksVectArray = [];
drinkArray.forEach(function (element, index, array) {
var drinkObj = element;
var drinkBrandName = builder.createString(drinkObj.drink_brand_name);
var drinkCompanyName = builder.createString(drinkObj.drink_company_name);
var drinkflavorTypeName = builder.createString(drinkObj.drink_flavor_type_name);
var drinkTypeName = builder.createString(drinkObj.drink_type_name);
var liquidColorTypeName = builder.createString(drinkObj.liquid_color_type_name);
drinks.Drink.startDrink(builder);
drinks.Drink.addAlcoholVol(builder, drinkObj.alcohol_vol);
drinks.Drink.addCaloriesFor100g(builder,drinkObj.calories_for_100g);
drinks.Drink.addDrinkBrandName(builder,drinkBrandName);
drinks.Drink.addDrinkCompanyName(builder,drinkCompanyName);
drinks.Drink.addDrinkFlavorId(builder,drinkObj.drink_flavor_id);
drinks.Drink.addDrinkFlavorTypeName(builder, drinkflavorTypeName);
drinks.Drink.addDrinkTypeName(builder,drinkTypeName);
drinks.Drink.addGlobalImageId(builder,drinkObj.global_image_id);
drinks.Drink.addLiquidColorIsTransparent(builder,drinkObj.is_transparent);
drinks.Drink.addLiquidColorTypeName(builder,liquidColorTypeName);
var drink = drinks.Drink.endDrink(builder);
drinksVectArray.push(drink);
})
var drinksVect = drinks.createDrinksVector(builder,drinksVectArray);
builder.finish(drinksVect);
var buf = builder.dataBuffer();
return buf;
}
module.exports.drinkArrayToBuffer=drinkArrayToBuffer;
now when I execute this function it fails with the error flatbuffers is not defined.
I debugged my code and I saw that it files on the following line of code:
drinks.Drink.addDrinkFlavorId(builder,drinkObj.drink_flavor_id);
if i get inside addDrinkFlavorId function i see this code in drinks_generted.js:
MyAlcoholist.Drink.addDrinkFlavorId = function(builder, drinkFlavorId) {
builder.addFieldInt64(9, drinkFlavorId, flatbuffers.Long.ZERO);
};
as you can see it uses flatbuffers.Long.ZERO but flatbuffers is not defined in that file at all. the compilation did not provide any errors so what do I miss?
It seems to me like it is a bug... The generated file appears to be meant to exist autonomously from the flatbuffers require. However for the custom flatbuffers.Long class, the default of flatbuffers.Long.ZERO bleeds into the generated file.
While this isn't a solution per-say, one workaround is to manually add the flatbuffers require to the generated file; it's ugly, but it might be better than being blocked until a more appropriate answer (or fix) comes around.
// In `drinks_generated.js`
var flatbuffers = require('../js/flatbuffers').flatbuffers;
Note:
The drinks.Drink.addDrinkFlavorId() and drinks.Drink.addGlobalImageId() functions expect flatbuffers.Long values to be passed into them, because they were specified as ulong in the schema (fbs file). So you will need to ensure that you are not trying to pass in a simple number type.
For example:
var my_long = flatbuffers.Long(100, 0); // low = 100, high = 0
drinks.Drink.addDrinkFlavorId(builder, my_long);
As a result, another possible workaround is to change the datatype of those fields in the schema to avoid using ulong until it becomes more clear what is going on here.
P.S. I am pretty sure drinks.createDrinksVector on line 30 of that snippet should be drinks.Drinks.createDrinksVector.