Ignoring Files With Chokidar In Watched Folders - node.js

I'm trying to ignore specific files within folders using Chokidar. I'm sure the syntax for the ignore path is incorrect, but I can't seem to find the problem. I've tried all combinations of strings, globs, and arrays. I'd appreciate if someone would point me in the right direction.
Here's a quick example of the problem. I'm trying to ignore ignore.js, but since the folder is being watched, console.log is executed when both writing and deleting the file.
var chokidar = require('chokidar');
var fs = require('fs');
var path = require('path');
var watcher = chokidar.watch('./test', {
ignored: path.resolve('./test/ignore.js'),
persistent: true,
ignoreInitial: true,
alwaysState: true
});
watcher.on('all',console.log);
setTimeout(function(){fs.writeFile('./test/ignore.js', 'w');}, 200);
setTimeout(function(){fs.unlink('./test/ignore.js');}, 300);
Thanks for any help!

I am inclined to agree with #loganfsmyth's comment that your path name is wrong. In my app I dynamically lookup the folder chokidar is monitoring from a function. For instance
Meteor.methods({
getWatchFolder: function () {
return watchFolder;
},
});
I set watchFolder elsewhere, it's not really important in the context of this question, but assume it is returning "/tmp". This worked great, and ignored that file:
var watcher = chokidar.watch(Meteor.call('getWatchFolder'), {
ignored: path.resolve(Meteor.call('getWatchFolder')+'/ignore.js'),
persistent: true
});
I noticed this only ignored /tmp/ignore.js, not a nested instance like /tmp/tmp2/ignore.js. If you want to ignore all nested instances this is easily remedied by adding the double asterisk wildcard to the ignore path:
var watcher = chokidar.watch(Meteor.call('getWatchFolder'), {
ignored: path.resolve(Meteor.call('getWatchFolder')+'/**/ignore.js'),
persistent: true
});
I tried setting my watch folder to . like you. It found TONS of files, I determined it was running from
/Users/esoyke/myAppName/.meteor/local/build/programs/server
This was not respecting my ignore path though. When I changed it from watching . to that absolute path instead, it naturally found the same files but the ignore worked again. I suspect there is an issue with absolute vs. relative paths going on here, see if you can refactor to use an absolute path.
P.S. Thanks for showing me that path.resolve, I hadn't used that Node module yet. I was trying to add multiple sub-directories to the ignore and was trying to do so by editing chokidar's default regex of /[/\]./. This approach is much simpler and easier to read. Sadly it doesn't seem like chokidar's library allows multiple ignore values at the moment, and path.resolve returns an array when there are more than one arg to it, so I'll probably have to go back to regex to get multiple ignore paths working.

Related

module.exports = app More than One Require

I'm creating a lambda function on AWS and I'm looking to require more than one file for "app". Apologies, I'm not great with Node yet.
In a routes.js file I have the following...
module.exports = app => {
require("./event.routes.js")(app);
require("./eventtemplate.routes.js")(app);
};
Normally there is only 1 require() between the {}. But I require both files as I've separated out the code into two different files for clarity. When I comment out the second require all is good and the runtime can find the functions in event.routes.js. But with the second require in there. It does not. Do I need to somehow name them? They do have similarly named functions. But they are contained within their "Event" and "EventTemplate" object in those different files.
Here's the event.routes.js file...
module.exports = app => {
const controller = require("../controllers/event.controller.js");
// Create a new event
app.post("/event", controller.create);
};
My eventtemplate.routes.js has similarly named functions. So I'm guessing this is the issue. My attempt to make things cleaner has broken things. Wondering if there is a better way to separate out things?
** UPDATE **
As requested, here is eventTemplate.routes.js...
module.exports = app => {
const controller = require("../controllers/eventtemplate.controller.js");
// Create a new EventTemplate
app.post("/event/template", controller.create);
);
I solved the issue. It was just that I had a misnamed function in my controller file that was being referenced from my route file. I had truncated the source listing for brevity but I would've had to post the controller code as well to see the error.
However thanks for the comments. It did steer me in the right direction to know that what I was doing was fine and correct and was just a typo. Thank you!

Getting the entire file path in route

I am building a route to download files from our server. The problem is that the filepath contains forward slashes and then the filePath variable only contains the first folder.
NOTE: Don't worry - the code locks the filepath down to specific folders by checking the first folder to ensure the path begins inside a download directory.
I tried using different delimiters than the normal slash, like a +. The code does actually work if I do this but that's such a terrible hack. Is there any other way to do this?
In other words, this works:
http://localhost:5000/files/C/temp+uploads+upload_c64bc04e02
But this doesn't work:
http://localhost:5000/files/C/temp/uploads/upload_c64bc04e02
I really feel like I should be finding a way to get this to work.
router.get('/files/:bucketCode/:filePath', auth.check, async (req, res) => {
let bucketCode= req.params.bucketCode;
let filePath = req.params.filePath;
I'm posting this answer because finding out how to specify and reference wildcards in route definitions was more difficult than it needs to be.
This did it for me:
...
router.get('/files/*', auth.check, async (req, res) => {
let file_path = req.originalUrl.replace(req.baseUrl, '');
let file_name = file_path.substring((file_path.lastIndexOf('/') + 1));
...
It's worth noting this is not designed to work for all cases. I have limited use cases where, for example, I know I'm never requesting a file from root and that there will always be a file and at least one folder in the path.

how can VS code support Go to definition

I have two JavaScript files: config.js, app.js. In app.js I want to use function defined in config.js so I could use require().
config.js
module.exports = {
somefunc: somefunc
}
app.js
var config = require('./config')
But I don't want to input the './' every time so I add a myRequire.js file.
myRequire.js
global.myRequire = function (p){
return require('./' + p)
}
In that case I could use myRequire('config') next time instead of myRequire('./config'), which might looks more concise.
app.js
require("./myRequire")
var config = myRequire('config')
config.somefunc()
But I met a problem, that I cannot use F12(Go to Definition) in VS Code to find the somefunc function. So could someone tell me what should I do to make it work in this case?
You are introducing a lot more problem than what you are trying to achieve. What if you are requiring a file from different file path '../../here', './over/there'.
If you really want to require something without a path. You can create your own npm module so you can require it globally without paths OR you create a folder with index.js in it and you require all the things you need.

Where should I put custom errors in sails.js?

I was wondering what's the best practice and if I should create:
a directory in which declare statically all the errors my application uses, like api/errors/custom1Error
declare them directly inside the files
or put the files directly inside the dir that needs that error, like api/controller/error/formInvalidError
other options!?
A neat way of going about this would be to simply add the errors as custom responses under api/responses. This way even the invocation becomes pretty neat. Although the doc says you should add them directly in the responses directory, I'm sure there must be a way to nest them under, say, responses/errors. I'll try that out and post an update in a bit.
Alright, off a quick search, I couldn't find any way to nest the responses, but you can use a small workaround that's not quite as neat:
Create the responses/errors directory with all the custom error response handlers. Create a custom response and name it something like custom.js. Then specify the response name while calling res.custom().
I'm adding a short snippet just for illustration:
api/responses/custom.js:
var customErrors = {
customError1: require('./errors/customError1'),
customError2: require('./errors/customError2')
};
module.exports = function custom (errorName, data) {
var req = this.req;
var res = this.res;
if (customErrors[errorName]) return customErrors[errorName](req, res, data);
else return res.negotiate();
}
From the controller:
res.custom('authError', data);
If you don't need logical processing for different errors, you can do away with the whole errors/ directory and directly invoke the respective views from custom.js:
module.exports = function custom (viewName, data) {
var req = this.req;
var res = this.res;
return res.view('errors/' + viewName, data);//assuming you have error views in views/errors
}
(You should first check if the view exists. Find out how on the linked page.)
Although I'm using something like this for certain purposes (dividing routes and so on), there definitely should be a way to include response handlers defined in different directories. (Perhaps by reconfiguring some grunt task?) I'll try to find that out and update if I find any success.
Good luck!
Update
Okay, so I found that the responses hook adds all files to res without checking if they are directories. So adding a directory under responses results in a TypeError from lodash. I may be reading this wrong but I guess it's reasonable to conclude that currently it's not possible to add a directory there, so I guess you'll have to stick to one of the above solutions.

require.main.require works but not inside Mocha test

I have written a global function for requiring certain files of my app/framework:
global.coRequireModel = function(name) {
// CRASH happens here
return require.main.require('./api/_co' + name + '/_co' + name + '.model');
}
This module is in /components/coGlobalFunctions.
It is required in my main app app.js like this:
require('./components/coGlobalFunctions');
Then in other modules using "something" from the framework I use:
var baseScheme = coRequireModel('Base');
This works but not in the Mocha tests which give me a "Error: Cannot find module" right before the require.main.require call.
It seems that the test is coming from another source folder. But I thought the require.main.require would take out the aspect of having to relatively linking to modules.
EDIT:
An example test file living in api/user:
var should = require('should');
var app = require('../../app');
var User = require('./user.model');
...
require.main points to the module that was run directly from node. So, if you run node app.js, then require.main will point to app.js. If, on the other hand, you ran it using mocha, then require.main will point to mocha. This is likely why your tests are failing.
See the node docs of more details.
Because require.main was not index.html in my node-webkit app when running mocha tests, it threw errors left and right about not being able to resolve modules. Hacky fix in my test-helper.js (required first thing in all tests) fixed it:
var path = require('path')
require.main.require = function (name) {
// navigate to main directory
var newPath = path.join(__dirname, '../', name)
return require(newPath)
}
This feels wrong, though it worked. Is there a better way to fix this? It's like combining some of the above solutions with #7 to get mocha testing working, but modifying main's require just to make everything work when testing feels really wrong.
For other avoid-the-".."-mess solutions, see here:
https://gist.github.com/branneman/8048520
This is pretty old, but here is my solution.
I needed a test harness module to be published to a private registry and required by the mocha test suite. I wanted the calling test code to pass the code under test to the harness rather than requiring it directly:
var harness = require('test-harness');
var codeUnderTest = harness('../myCode');
Inside harness (which was found in the project node_modules directory), I used the following code to make require find the correct file:
if (!path.isAbsolute(target)) {
target = path.join(path.dirname(module.parent.paths[0]), target);
}
var codeUndertest = require(target);
...
return codeUnderTest;
This relies on the require path resolution that always starts with looking for a node_modules subdirectory relative to the calling file. Couple that with module.parent and you can get access to that search path. Then just remove the trailing node_modules part and concatenate the relative filename.
For other scenarios not using relative paths, this could be accomplished with the options parameter to require:
var codeUndertest = require(target, {paths: module.parent.paths});
...
return codeUnderTest;
And the two could be combined as well. I used the first form because I was actually using proxyquire which does not offer the paths option.

Resources