npm package uses fs in wrong dir - node.js

I have made a very simple npm package to support my discord bot.
In my bot code, I am trying to use a function from my package. However, when I launch bot code, I receive this error:
Error: ENOENT: no such file or directory, open 'prefixes.json'
I have a prefixes.json file in the main dir of npm package. In the package this code (which returns an error) is executed:
const contents = fs.readFileSync(`prefixes.json`);
const jsonPrefixes = JSON.parse(contents);
This code is executed when I turn on my discord bot that is dependant on this package. prefix.json is in the same dir as index.js of my npm package. I tried ./prefix.json and prefix.json, none of which worked.
Is the error because the package tries to search in my bot dir, instead of his own? How do I overcome this?
Update: When I tried ./node_modules/kifo/prefixes.json it worked, but I don't want it like that - is there a way to provide a path relative to the package?

You need to use require() instead of fs.readFileSync():
const jsonPrefixes = require('./prefixes.json');
const contents = JSON.stringify(jsonPrefixes); // you don't actually need this
Why?
The reason why fs.readFileSync() must behave the way it does is because file API in all programming languages behave that way. Say for example you write a program called dump. The working directory must be the one the user is currently in otherwise if you do:
> cd /my/folder
> ls
test.txt
> dump test.txt
Error: cannot open /path/to/node_modules/dump/test.txt
Of course YOU DO NOT EXPECT THIS. Nor should you. You should not expect fs.readFileSync to use it's own module directory to open files from.
On the other hand, require() was designed to load javascript modules, some of which are form your own project. So require() will open files from the directory the code is in.
The require() function can load either javascript code or a JSON file. So in your case you can use require().
What if it's not JSON?
If you cannot use require() you can use the __dirname variable. It is a special variable that contains the path of the currently executing module:
const contents = fs.readFileSync(`${__dirname}/prefixes.json`);
const jsonPrefixes = JSON.parse(contents);
However for JSON I still prefer to use require().

Related

function used across several lambda functions in aws

I am new to nodeJS, npm, and aws lambda. Suppose I have a custom sort algorithm that I want to use in several lambda functions. This should be something very simple, but the only way I have found is to create a layer with a node module published as an npm package. I do not want any of the code be uploaded to an npm.
I tried to download the layer I am currently using, create a folder in node_modules along with other packages that are published in npm with
npm init
fill all the info for the package.json
created a function code in a index.js
'use strict'
exports.myfunc= myfunc;
function myfunc() {
console.log("This is a message from the demo package");
}
zip all the layer again and upload it in a version 2 of the layer
pick the new version in a lambda function and call it as i would do with any other node_module form a third party, like this:
const mypack= require('mypack');
mypack.myfunc();
but it tells me:
"errorMessage": "Error: Cannot find module ... \nRequire stack:\n- /var/task/index.js\n- /var/runtime/UserFunction.js\n- /var/runtime/index.js",
I think it maybe because in the layer in the nodejs folder, there is package-lock.json and my module is not there. I tried to put it there without the "resolved" and "integrity" that the packages published on npm have but did not work.
Is there a way to simply upload the code I want in a nodejs layer having nothing to do with npm?
I would like to try something such as this in the accepted answer,
var moduleName = require("path/to/example.js")
How to install a node.js module without using npm?
but I don't know where is the path of the modules of a layer, the path of lambda that shows __dirname is /var/task, but it looks like any lambda has same path. I am lost...
I was able to import js in a folder in the following manner:
download the zip of the layer uncompress it, put in node_modules any additional folder with your custom js and upload it as a new version of the layer.
In the lambda function, reference it with
moduleName = require("path/to/example.js")
You can find that path, which is the trick here, using a known library you already have in your layer and is working, in my case I used base64-js, then I returned the path of that library like this:
require.resolve('base64-js')
That returned
'/opt/nodejs/node_modules/base64-js/index.js'
So I used
moduleName = require("/opt/nodejs/node_modules/MYCUSTOMFOLDER/index.js")
and that was it...

Use modules on server without install permissions

Node.js is installed on a server that I have limited access to. I can upload files to the server and execute scripts from the command line, but I cannot run certain commands like install.
I have a Node.js script uploaded to the server that I'd like to use. The script references other files, such as a file.json, that it accesses just fine. There's even some other modules it uses, like const osPath = require( 'path' ) and const crypto = require( "crypto" ), that work just fine.
However, the script references something like const argv = require('commander'), but that gives me an error since the module is not installed.
If I download the commander files, and uploaded them to the server, am I able to modify the require statement to point to where I uploaded the file? Or is all hope lost and I would need to find a server where I can run install commands?

How to include dependencies in J2V8

How to include dependencies in J2V8? I would like to use certain dependencies in the javascript file for instance the crypto package.
var crypto = require('crypto');
function foo(){ return crypto.createHash('md5').update('Apple').digest("hex");}
However, I got the following error saying require keyword is undefined.
undefined:1: ReferenceError: require is not defined
var crypto = require('crypto');
^
ReferenceError: require is not defined at <anonymous>:1:14
com.eclipsesource.v8.V8ScriptExecutionException
at com.eclipsesource.v8.V8._executeVoidScript(Native Method)
Can anyone tell me how to import an package into J2V8?
Unless you're working with Node, require is not a feature. Usually, you want to use a bundler like webpack to pack your structured source code into one large file so that it can be understood by browsers. This way you can use require and npm packages for your frontend code, which makes development easier, and a bundler turns it with every build (or live update) into a different format, that's hard to read for humans, but is valid Javascript.
I have had success using node modules in J2v8, please check out this blog :http://eclipsesource.com/blogs/2016/07/20/running-node-js-on-the-jvm/
NodeJs nodeJS = NodeJs.createNodeJs();
After registering callbacks
nodeJs.exec(File thescripttoexecute)
Make sure you have the proper path to the node modules in the require() command.
You may have to make a nodejs package that takes dependencies and exports what you need. Then, You have to execute npm install manually.
or You can just npm install what-you-need.
Create Node JS Runtime, and use require with your your-package-dir/index.js or exact location of module that you need. like this:
V8Object module = nvm.require(file);
Now you can call the function likes:
module.executeJSFunction("test");
To deliver entire dependencies you have to bundlize module directory your self.
What if you have to support cross-platform, refer https://www.npmjs.com/package/node-pre-gyp also.

Browserify - JsSip

I have a new project where I'm using browserify to convert node modules into an sdk that can run inside the browser.
I'm requiring a number of other npm packages like:
var log4js = require('log4js');
That run fine and give me no problems in the browser, however JsSip just will not cooperate. When I do
var JsSIP = require('jssip');
I get
plivowebsdk.js:2 Uncaught Error: Cannot find module '../../package.json'
Looking through the code, it's obvious when it makes this call
var pkg = require('../../package.json');
is where it bombs out. Clearly it cannot find the package.json file, which it uses to pull out version information. I know JsSip is actually built with browersify itself (or used to be) so that it can run in either node or a browser. Is this causing a conflict?
Still sort of new to browserify, is their a configuration option or transformation I can perform to get around this?
Turned out the be browserify errors, re did the build process using the gulp recipes for browersify and works as expected.

NPM unable to read file

I have written a NPM module. which needs to read a file. While creating NPM module I have placed a file in same directory with .js file and used
var file = './sqlmap_config.json';
This files gets included well when I use the code standalone. When I create NPM module, this file is looked up in parent directory where NPM module is installed and code fails.
Do I need to hard code it to
var file = './node_modules/module/sqlmap_config.json';
Or there is any other way to accomplish this
I think you are going to want to use something like :
var file = __dirName + '/sqlmap_config.json';
https://nodejs.org/api/all.html#modules_dirname

Resources