Node.js List All Modules Required in a File - javascript

I must be missing something here. I have a mocha test file that is set up like so:
require('globals');
var library1 = require('library1'),
library2 = require('library2');
it('tests stuff', function() {
...
});
Where the globals file just contains a before and afterEach block, so that they apply to all my test files.
What I'm trying to do is determine, within the before and afterEach blocks, which files that I have require'd in the test file that those blocks are currently running in. So in the example test file I gave, I would need afterEach to output a list that contains globals, library1, and library2.
I have attempted to use Node.js's module.children property, but for some reason that is only returning me globals, and excluding library1 and library2.
Edit: What am I missing that module.children wouldn't be returning library1 and library2?

Here is an example of a script that will parse requires in a file.
var fs = require('fs');
function parseRequires(absPath){
var requiredFiles = [];
var contents = fs.readFileSync(absPath, 'utf8').split('\n');
contents.forEach(function(line){
var re = /(?:require\('?"?)(.*?)(?:'?"?\))/;
var matches = re.exec(line);
if(matches){
requiredFiles.push(matches[1]);
}
});
return requiredFiles;
}
module.exports = parseRequires;
I made a test script in the same directory
var fs = require('fs');
var os = require('os');
function A(){}
var http = require("http");
var parseRequires = require("./parseRequires");
console.log( parseRequires( __dirname + '/testRequires.js') );
results in console: [ 'fs', 'os', 'http', './parseRequires' ]
This is one solution, though I'm sure there is an easier way to do it with nodejs built in functionality

Here is another solution I came up with using require.cache. It involves parsing require.cache for the files that have been required and provides the name of the file that ends up being required
var someModule = require('./someModule');
var path = require('path');
for( var p in require.cache){
console.log( trim( p ) );
}
function trim(p){
var re = /(.*?).js/;
var basename = path.basename( p );
var moduleName = re.exec( basename )[1];
return moduleName;
}
Test files:
someModule.js
var fs = require('fs');
var os = require('os');
var _ = require('lodash');
var test = require('./test');
test.js
var a = require('lodash'),
jQuery = require('jquery');
Running getRequires.js results in
getRequires
someModule
index
test
jquery
Notice that it includes itself, so there would have to be something that trims that out as well.
Also notice index, that comes from lodash
Here is a modification that shows the file paths as well
var someModule = require('./someModule');
var path = require('path');
for( var p in require.cache){
console.log( trim( p ) );
}
function trim(p){
var re = /(.*?).js/;
var basename = path.basename( p );
var moduleName = re.exec( basename )[1];
return [ moduleName, p ];
}
That gets us:
[ 'getRequires',
'/<myroot>/require/getRequires.js' ]
[ 'someModule',
'/<myroot>/require/someModule.js' ]
[ 'index',
'/<myroot>/require/node_modules/lodash/index.js' ]
[ 'test', '/<myroot>/require/test.js' ]
[ 'jquery',
'/<myroot>/require/node_modules/jquery/dist/jquery.js' ]
require is the directory I'm doing the code in.
Let me know about your thoughts on this solutions. There is more to be done but I think this can get you started.

Related

webpack function usage after bundling

I try to pack that https://www.npmjs.com/package/#jscad/dxf-deserializer library and use in browser.
Uage from node looks like
const deSerializer = require('#jscad/dxf-deserializer')
const rawData = fs.readFileSync('PATH/TO/file.dxf')
const jscadCode = deSerializer(rawData)
How should i use that now after linking bundle script?
I had tried
let objs = deserialize(fileText,'square10x10',{output: 'csg'})
and got
ReferenceError: deserialize is not defined
There is js test file works fine with node
const fs = require('fs')
const path = require('path')
const test = require('ava')
const { CSG, CAG } = require('#jscad/csg')
const { nearlyEqual } = require( '../../../test/helpers/nearlyEqual' )
const { deserialize } = require( '../index' )
const samples = path.resolve('../../node_modules/#jscad/sample-files')
//
// Test suite for DXF deserialization (import)
//
test('ASCII DXF from Bourke 3D Entities to Object Conversion', t => {
//const dxfPath = path.resolve(__dirname, '../../../../sample-files/dxf/bourke/3d-entities.dxf')
const dxfPath = path.resolve(samples, 'dxf/bourke/3d-entities.dxf')
t.deepEqual(true, fs.existsSync(dxfPath))
let dxf = fs.readFileSync(dxfPath, 'UTF8')
let objs = deserialize(dxf,'aaa',{output: 'objects'})
// expect one layer, containing 2 objects (CSG, and Line3D)
t.true(Array.isArray(objs))
t.is(objs.length,2)
})
Try Adding
node: {
fs: "empty"
}
fs module isn't defined in the browser.
Maybe that's what stopping deserialize from been created. With a try.

Where does this "_.startsWith" come from?

I am trying to understand the following code from the browserify-css repo:
var gulp = require('gulp');
var gutil = require('gulp-util');
var path = require('path');
var browserify = require('browserify');
var sourceStream = require('vinyl-source-stream');
var fse = require('fs-extra');
var bundleStream = browserify()
.add('src/index.js')
.transform(require('browserify-css'), {
rootDir: 'src',
processRelativeUrl: function(relativeUrl) {
var stripQueryStringAndHashFromPath = function(url) {
return url.split('?')[0].split('#')[0];
};
var rootDir = path.resolve(process.cwd(), 'src');
var relativePath = stripQueryStringAndHashFromPath(relativeUrl);
var queryStringAndHash = relativeUrl.substring(relativePath.length);
//
// Copying files from '../node_modules/bootstrap/' to 'dist/vendor/bootstrap/'
//
var prefix = '../node_modules/';
if (_.startsWith(relativePath, prefix)) {
var vendorPath = 'vendor/' + relativePath.substring(prefix.length);
var source = path.join(rootDir, relativePath);
var target = path.join(rootDir, vendorPath);
gutil.log('Copying file from ' + JSON.stringify(source) + ' to ' + JSON.stringify(target));
fse.copySync(source, target);
// Returns a new path string with original query string and hash fragments
return vendorPath + queryStringAndHash;
}
return relativeUrl;
}
})
.bundle();
bundleStream
.pipe(sourceStream(bundleFile))
.pipe(gulp.dest(browserifyConfig.dest));
I don't understand the part
_.startsWith(relativePath, prefix)
Where is the underscore coming from? It's supposed to be javascript executed by a task runner. I've found that in the NodeJS REPL the underscore character outputs the result of the last executed expression, but that functionality can't be used inside scripts. It's also not an underscore.js instance because it is not being declared anywhere. startsWith is a String method.
So what am I missing?
That code is using the lodash library. You can see in this section of the readme that they're importing lodash with var _ = require('lodash');

Node.js Path infinity loop

I have the following two files in a folder:
plus one file in same folder called minions_model
But when i try to call murder_model with:
var murder_model = require('./murder_model.js');
and call it to see its functions, i get:
{}
while i should see something like:
{ xxx: [Function: xxx] }
Update:
It seems like missionModel fails to get murder file because of minionModel.
I noticed if i removed minionModel reference from Murder file, it would work.
But minionModel crashes because of Mission_model. so if i remove minionModel from MissionModel it would work. But its an infinity Loop!.
What causes this and how can i fix it?
Source:
minions:
var path = require('path');
var missionsCompålicated = require('./mission_model.js');
var mongoose = require('mongoose');
function yyy() {
console.log("inside minions");
return 499;
}
module.exports = {
yyy : yyy,
};
Murder:
var path = require('path');
var MinionModel = require('./minions_model.js');
function xxx() {
console.log("inside murder model");
}
module.exports = {
/*botAttack : botAttack,*/
xxx : xxx,
};
mission:
var xau = require('./murder_model.js');
function getMission(userid) {
console.log("??:)");
console.log(xau);
console.log(xau.xxx());
}
module.exports = {
getMission : getMission,
};
Its weird, because if i call it anywhere else ( not in minion,murder or mission, for example server.js it works perfectly.
This happens because you are replacing the entire module.exports object and the two modules are requiring each other and causing a cyclic dependency. You can solve it my not replacing the module.exports object.
Try this :
module.exports.getMission = getMission;
module.exports.xxx = xxx;
module.exports.yyy = yyy;

Node Js : Unable to find error in below file filter code

I have written small code to get files filtered by extension. And my point of view logic is fine but I am unable to point out why I am not getting expected output.
Please have a look.
CODE
var fs = require('fs')
var path = require('path')
path_name = process.argv[2]
ext_name = "."+process.argv[3]
var filter_function = function ( path_name,exthide_name,callback) {
fs.readdir(dirpath,function(err,list) {
if(err) return console.error(err)
for ( var i in list) {
if(path.extname(list[i]) == ext_name)
console.log(list[i])
}
})
}
module.exports=filter_function
Output :
linuxmen#linuxmen-fresh:~/test/test1$ node ownModuleNode.js /home/linuxmen/test/test1/ js
linuxmen#linuxmen-fresh:~/test/test1$
But I have so many files with js extension in that directory.
Proof:
linuxmen#linuxmen-fresh:~/test/test1$ ls *js
check_mod1.js ex1.js ex2.js ex3.js ex4.js ex5.js ex6.js ex7.js ex8.js filter.js filter_use.js modse.js ownModuleNode.js se.js use_mod1.js using_module.js
Could please help , what I am missing.
Update - 1 : I am using above code a module file and calling it here.
File using above code
var mymodule = require('./ownModuleNode')
mymodule.filter_function(process.argv[2],process.argv[3])
Update 2 :
var fs = require('fs')
var path = require('path')
path_name = process.argv[2]
ext_name = "."+process.argv[3]
console.log("path_name :",path_name,"extname:",ext_name)
var filter_function = function ( path_name,ext_name,callback) {
fs.readdir(path_name,function(err,list) {
if (err) console.error(err)
console.log(list)
for ( var i in list) {
if(path.extname(list[i]) == ext_name)
console.log(list[i])
}
})
}
module.exports=filter_function
Output:
linuxmen#linuxmen-fresh:~/test/test1$ node ownModuleNode.js /home/linuxmen/test/test1/ js
pathanme : /home/linuxmen/test/test1/ extname: .js
Thank you.
It looks like you are exporting the function directly. When you require() it, you just getting the function. You'll need to use your module in your application. Put this in 'app.js' in the same dir as ownModuleNode.js:
var filterFunction = require('./ownModuleNode');
filterFunction(process.argv[2], process.argv[3]);
Then call it with:
node app ~/Documents/dev/project .js
Outputs:
app.js
ownModuleNode.js
Note that when you pass the extension, you need the preceding dot because path.extname() returns the dot.

How can I use these Node modules to accept HTML through a file or URL and then output JSON as validation of existing HTML elements?

Essentially what I need to do is to take a local grader.js file and then use it at the command line to input HTML, which will then output JSON data to the console to validate the existence of several HTML elements. The usage looks something like this:
./grader.js --checks checks.json --file index.html
./grader.js --checks checks.json --url http://google.com
The Node modules being used are Commander (for working at the command line), Cheerio (for HTML), and Restler (for getting HTML from URL).
The checks.json file is straightforward in that it's simply asking to check for the existence of a few simple HTML elements to find out whether or not they exist on the page:
["h1",
".navigation",
".logo",
".blank",
".about",
".heading",
".subheading",
".pitch",
".video",
".thermometer",
".order",
".social",
".section1",
".section2",
".faq",
".footer"]
The grader.js file is where things get a little more complicated. The following code actually works insofar as it takes the command line arguments and does indicate a true or false value as to whether the HTML elements exist. But it doesn't work properly after adding the URL check at the bottom. There is something wrong with my checkURL function and the way that I implement it using the Commander code at the bottom. Even though the true and false values are correct dependent upon the HTML file/URL I use, I end up spitting out both checks to the console even if I only want to check either the file or the URL, not both. I'm fairly new to this so I'm surprised that it works at all. It may have something to do with the default values, but when I try to make those changes the checkURL function seems to break down. Thanks in advance for your help I really do appreciate it.
#!/usr/bin/env node
var fs = require('fs');
var program = require('commander');
var cheerio = require('cheerio');
var rest = require('restler');
var HTMLFILE_DEFAULT = "index.html";
var CHECKSFILE_DEFAULT = "checks.json";
var URL_DEFAULT = "http://cryptic-spire-7925.herokuapp.com/index.html";
var assertFileExists = function(infile) {
var instr = infile.toString();
if(!fs.existsSync(instr)) {
console.log("%s does not exist. Exiting.", instr);
process.exit(1); // http://nodejs.org/api/process.html#process_process_exit_code
}
return instr;
};
var cheerioHtmlFile = function(htmlfile) {
return cheerio.load(fs.readFileSync(htmlfile));
};
var loadChecks = function(checksfile) {
return JSON.parse(fs.readFileSync(checksfile));
};
var checkHtmlFile = function(htmlfile, checksfile) {
$ = cheerioHtmlFile(htmlfile);
var checks = loadChecks(checksfile).sort();
var out = {};
for(var ii in checks) {
var present = $(checks[ii]).length > 0;
out[checks[ii]] = present;
}
return out;
};
var checkUrl = function(url, checksfile) {
rest.get(url).on('complete', function(data) {
$ = cheerio.load(data);
var checks = loadChecks(checksfile).sort();
var out = {};
for(var ii in checks) {
var present = $(checks[ii]).length > 0;
out[checks[ii]] = present;
}
console.log(out);
});
}
var clone = function(fn) {
// Workaround for commander.js issue.
// http://stackoverflow.com/a/6772648
return fn.bind({});
};
if(require.main == module) {
program
.option('-f, --file <html_file>', 'Path to index.html', clone(assertFileExists), HTMLFILE_DEFAULT)
.option('-u, --url <url>', 'URL to index.html', URL_DEFAULT)
.option('-c, --checks <check_file>', 'Path to checks.json', clone(assertFileExists), CHECKSFILE_DEFAULT)
.parse(process.argv);
var checkJson = checkHtmlFile(program.file, program.checks);
var outJson = JSON.stringify(checkJson, null, 4);
console.log(outJson);
var checkJson2 = checkUrl(program.url, program.checks);
var outJson2 = JSON.stringify(checkJson2, null, 4);
console.log(outJson2);
}
else {
exports.checkHtmlFile = checkHtmlFile;
}
Depending on the arguments call either one of checkHtmlFile() or checkUrl()
Something like:
if (program.url)
checkUrl(program.url, program.checks);
else checkHtmlFile(program.file, program.checks);
Read this for more references: commander.js option parsing
Also, checkJson2 is undefined as checkUrl() isn't returning anything.
Those commander .option lines look wrong to me.
Delete the clone function and revise your option lines as follows:
.option('-f, --file <html_file>', 'Path to index.html', HTMLFILE_DEFAULT)
.option('-u, --url <url>', 'URL to index.html', URL_DEFAULT)
.option('-c, --checks <check_file>', 'Path to checks.json', CHECKSFILE_DEFAULT)
This should solve your commander problem.
Here is the updated checkUrl function after the helpful hints from #David and #ankitsabharwal.
var checkUrl = function(url, checksfile) {
rest.get(url).on('complete', function(data) {
$ = cheerio.load(data);
var checks = loadChecks(checksfile).sort();
var out = {};
for(var ii in checks) {
var present = $(checks[ii]).length > 0;
out[checks[ii]] = present;
}
var outJson = JSON.stringify(out, null, 4);
console.log(outJson);
});
}
And here is the updated Commander code below:
if(require.main == module) {
program
.option('-f, --file <html_file>', 'Path to index.html')
.option('-u, --url <url>', 'URL to index.html')
.option('-c, --checks <check_file>', 'Path to checks.json')
.parse(process.argv);
if (program.url) {
checkUrl(program.url, program.checks);
} else {
checkHtmlFile (program.file, program.checks);
var checkJson = checkHtmlFile(program.file, program.checks);
var outJson = JSON.stringify(checkJson, null, 4);
console.log(outJson);
}
}

Categories