How to check if a file or directory exists without using fs.exists? - node.js

The reason I ask, is because Node.js on ubuntu doesn't seem to have the fs.exists() function. Although I can call this when I run Node.js on my Mac, when I deploy to the server, it fails with an error saying the function does not exist.
Now, I am aware that some people consider it an "anti-pattern" to check if a file exists and then try and edit / open it etc, but in my case, I never delete these files, but I still need to check if they exist before writing to them.
So how can I check if the directory (or file) exists ?
EDIT:
This is the code I run in a file called 'temp.'s' :
var fs=require('fs');
fs.exists('./temp.js',function(exists){
if(exists){
console.log('yes');
}else{
console.log("no");
}
});
On my Mac, it works fine. On ubuntu I get the error:
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^ TypeError: Object #<Object> has no method 'exists'
at Object.<anonymous> (/home/banana/temp.js:2:4)
at Module._compile (module.js:441:26)
at Object..js (module.js:459:10)
at Module.load (module.js:348:32)
at Function._load (module.js:308:12)
at Array.0 (module.js:479:10)
at EventEmitter._tickCallback (node.js:192:41)
On my Mac - version : v0.13.0-pre
On Ubuntu - version : v0.6.12

It's probably due to the fact that in NodeJs 0.6 the exists() method was located in the path module: http://web.archive.org/web/20111230180637/http://nodejs.org/api/path.html – try-catch-finally
^^ That comment answers why it isn't there. I'll answer what you can do about it (besides not using ancient versions).
From the fs.exists() documentation:
In particular, checking if a file exists before opening it is an anti-pattern that leaves you vulnerable to race conditions: another process may remove the file between the calls to fs.exists() and fs.open(). Just open the file and handle the error when it's not there.
You could do something like this:
fs.open('mypath','r',function(err,fd){
if (err && err.code=='ENOENT') { /* file doesn't exist */ }
});

The accepted answer does not take into account that the node fs module documentation recommends using fs.stat to replace fs.exists (see the documentation).
I ended up going with this:
function filePathExists(filePath) {
return new Promise((resolve, reject) => {
fs.stat(filePath, (err, stats) => {
if (err && err.code === 'ENOENT') {
return resolve(false);
} else if (err) {
return reject(err);
}
if (stats.isFile() || stats.isDirectory()) {
return resolve(true);
}
});
});
}
Note ES6 syntax + Promises - the sync version of this would be a bit simpler. Also my code also checks to see if there is a directory present in the path string and returns true if stat is happy with it - this may not be what everyone wants.

The Sync methods don't have any way of notifying about an error. Except for exceptions! As it turns out, the fs.statSync method throws an exception when the file or directory doesn't exist. Creating the sync version is as easy as that:
function checkDirectorySync(directory) {
try {
fs.statSync(directory);
} catch(e) {
try {
fs.mkdirSync(directory);
} catch(e) {
return e;
}
}
}
And that's it.
Using is as simple as before:
checkDirectorySync("./logs");
//directory created / exists, all good.
[]´z

Related

require.resolve() works. Why doesn't module.parent.require.resolve()?

I'm trying to find the file of included modules. From the main module, require.resolve('module') happily returns me the value of the main key from the module's package.json.
However, I would like to do this from a module that's been included via npm. If I simply call require.resolve('module'), it looks in the node_modules for this module, whereas I need to resolve it from the point of view of the running package.
According to the docs, require is actually module.require and module.parent returns the module that first required this one. Why then does module.parent.require.resolve('module') not work? I get ana
error:
TypeError: module.parent.require.resolve is not a function
Oddly though, console.log module.parent.require.toString() returns
function (path) {
assert(path, 'missing path');
assert(typeof path === 'string', 'path must be a string');
return Module._load(path, this, /* isMain */ false);
}
so it certainly looks like a function to me.
Anyone know what's going on? I've also tried require.main.require.resolve() and that does a very similar thing.
TypeError: module.parent.require.resolve is not a function
Oddly though, console.log module.parent.require.toString() returns ...
module.parent.require is a function, module.parent.require.resolve is not.
Why is resolve() not a function?
It appears require() and module.require() are not the same:
console.log(require === module.require); // false
For the curious:
console.log(module.require.toString())
function (path) {
assert(path, 'missing path');
assert(typeof path === 'string', 'path must be a string');
return Module._load(path, this, /* isMain */ false);
}
console.log(require.toString())
function require(path) {
try {
exports.requireDepth += 1;
return mod.require(path);
} finally {
exports.requireDepth -= 1;
}
}
So require() calls module.require(), but is not the same thing.
What about resolve()?
We know require.resolve is a function:
console.log(require.resolve.toString())
function resolve(request) {
return Module._resolveFilename(request, mod);
}
But module.require.resolve is not:
console.log(module.require.resolve)
undefined
So unfortunately resolve() is only available at require.resolve(), and not at module.require.resolve() (or module.parent.require.resolve() for that matter).
Solution?
Not a great solution, but you could try manually calling Module._resolveFilename() and passing in the parent module instead of the current module:
const Module = module.constructor;
const fileName = Module._resolveFilename('module', module.parent);
This solution isn't great because it relies on internal API functions that could possibly change in the future. It would be nice if NodeJS would provide better documentation and APIs for module loading/resolving.

EPIPE write error html-pdf only on appfog server

I'm having a very weird EPIPE write error when I'm trying to generate a PDF from HTML with this module:
https://www.npmjs.com/package/html-pdf
The exact error:
events.js:72
throw er; // Unhandled 'error' event
^
Error: write EPIPE
at errnoException (net.js:904:11)
at Object.afterWrite (net.js:720:19)
The line where I call the PDF gen:
var pdfgen = require("html-pdf");
pdfgen.create(html, options).toFile('whappbook.pdf', function(err, res) {
var errorCount = 0;
if (err) {
console.log(err);
errorCount++;
if(errorCount > 2) {
return console.log(err);
} else {
return create();
}
}
console.log(res); // { filename: '/app/businesscard.pdf' }
});
I've tried just using <h1>Testing</h1> as the HTML to see if the file was too big, but that wasn't the case.
Note: local everything works perfectly fine, but when I run this code on Appfog it doesn't work, so I suspect it has something to do with missing dependencies or file writing rights.
I'm writing directly to the home directory (in Appfog's case thats /app).
HTML-PDF is using PhantomJS and I've also directly npm'd that in my app because some people were reporting issues when it wasn't directly installed, but that didn't solve my problem either.
If there is any information that I can additionally provide please let me know!

Node.js customize require function globally

I am trying to modify require like this
require = function (path) {
try {
return module.require(path);
} catch (err) {
console.log(path)
}
}
However, scope of this modification is only in the current module. I want to modify it globally, so every module that is required by this module will also get the same copy of require function.
Basically, I want to catch SyntaxError to know which file has problem. I can't seem to find any other alternative. If I put module.require in try/catch block, I'll be able to get the file name which caused SyntaxError.
I managed to solve it by modifying prototype function require of Module class. I put this in the main script and its available to all the required modules.
var pathModule = require('path');
var assert = require('assert').ok;
module.constructor.prototype.require = function (path) {
var self = this;
assert(typeof path === 'string', 'path must be a string');
assert(path, 'missing path');
try {
return self.constructor._load(path, self);
} catch (err) {
// if module not found, we have nothing to do, simply throw it back.
if (err.code === 'MODULE_NOT_FOUND') {
throw err;
}
// resolve the path to get absolute path
path = pathModule.resolve(__dirname, path)
// Write to log or whatever
console.log('Error in file: ' + path);
}
}
Why don't you use a try-catch block inside your code and once an error occurs to check the stack trace. Check out these links
How to print a stack trace in Node.js?
http://machadogj.com/2013/4/error-handling-in-nodejs.html

Check if package is available?

I'd like to know if require(pkgName) would succeed, that is, if the package with name pkgName is available. How do I best test for that?
I know I can do
try {
require(pkgName)
} catch (err) {
available = false
}
but this swallows load errors, and I'd also like to avoid require'ing the package if possible.
The best way is to use require.resolve(), since it does not actually run any code contained in the module.
Use the internal require() machinery to look up the location of a module, but rather than loading the module, just return the resolved filename.
Just like require, resolve throws if the module is not found, so it needs to be wrapped in try/catch.
Don't think you can work around using require, but you can specifically check for MODULE_NOT_FOUND errors:
function moduleExists(mod) {
try {
require(mod);
} catch(e) {
if (e.code === 'MODULE_NOT_FOUND')
return false;
throw e;
};
return true;
}
I'm showing with the "swig" module. There might be better ways, but this works for me.
var swig;
try {
swig = require('swig');
} catch (err) {
console.log(" [FAIL]\t Cannot load swig.\n\t Have you tried installing it? npm install swig");
}
if (swig != undefined) {
console.log(" [ OK ]\t Module: swig");
}

node.js + express error: cannot read property 'url' of undefined

I'm fairly new to Node.js, installing it to try out the DrupalChat (v7dev) module. I believe this problem is with either node.js or express, as I am beyond the stage where the chat module's settings are loaded. I am faced with the following output when trying to start the chat server
Extension loaded: drupalchat_nodejs.server.extension.js
Started http server.
info - socket.io started
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
TypeError: Cannot read property 'url' of undefined
at Function.handle (/usr/local/lib/node_modules/npm/node_modules/express/node_modules/connect/lib/proto.js:105:18)
at Server.app (/usr/local/lib/node_modules/npm/node_modules/express/node_modules/connect/lib/connect.js:60:31)
at Server.serverListening (/usr/local/lib/node_modules/npm/node_modules/socket.io/node_modules/policyfile/lib/server.js:136:16)
at Server.g (events.js:154:14)
at Server.emit (events.js:64:17)
at Array.1 (net.js:710:10)
at EventEmitter._tickCallback (node.js:192:40)
I remember when express installed, it gave a warning like ".... bugs['web'] should probably be bugs['url']" (I can't remember the prefix)
So is it that the server is trying to read an (API?) variable 'url' but its currently 'web'?
I have all the modules up to date, is it that I should downgrade? Or is there some way of working around this using another module?
EDIT:
line 201 is the last very line (delete authenticatedClients[authData.authToken];)... I just added to whole function for proper context
var authenticateClientCallback = function (error, response, body) {
if (error) {
console.log("Error with authenticate client request:", error);
return;
}
if (response.statusCode == 404) {
if (settings.debug) {
console.log('Backend authentication url not found, full response info:', response);
}
else {
console.log('Backend authentication url not found.');
}
return;
}
var authData = false;
try {
authData = JSON.parse(body);
}
catch (exception) {
console.log('Failed to parse authentication message:', exception);
if (settings.debug) {
console.log('Failed message string: ' + body);
}
return;
}
if (!checkServiceKey(authData.serviceKey)) {
console.log('Invalid service key "', authData.serviceKey, '"');
return;
}
if (authData.nodejsValidAuthToken) {
if (settings.debug) {
console.log('Valid login for uid "', authData.uid, '"');
}
setupClientConnection(authData.clientId, authData, authData.contentTokens);
authenticatedClients[authData.authToken] = authData;
}
else {
console.log('Invalid login for uid "', authData.uid, '"');
delete authenticatedClients[authData.authToken];
}
}
Per #thesnufkin's post, looks like the underlying express version currently pulled is not stable. Roll back to 2.5.9 and you should be good to go:
npm uninstall express
npm install express#2.5.9
As requested,
The v7 chat module from drupal is not stable. You should not use it in production.
Check bugs : http://drupal.org/project/issues/drupalchat?status=All&categories=All
Check forums : http://drupalchat7.botskool.co.in/?q=forum
Still looking for a new maintener:
"New maintainer wanted - please ping beejeebus if you're interested!".
nodejs module has this issue, so I don't think its related to the drupalchat server specifically. Here is the issue for that: http://drupal.org/node/1537702
The option to use node.js as backend in DrupalChat is currently under development. It also depends when (date on which) you downloaded the DrupalChat since the dev code is updated everyday, if new code is committed.
Please raise an issue for the same at this link - http://drupal.org/project/issues/drupalchat?status=All&categories=All.
Thanks,
darklrd

Resources