Starting application using node works but not yarn or npm - node.js

There is probably an obvious answer to someone who is more familiar with NodeJS than me but:
When running an application which is using a node-gyp package, it runs without problems using
node ./src/index.js
However running it using a very simple package.json start-script:
"scripts": {
"start": "node ./src/index.js"
}
in npm:
npm start
npm info it worked if it ends with ok
npm info using npm#6.9.0
npm info using node#v11.10.1
npm info lifecycle rosbag2#0.1.0~prestart: rosbag2#0.1.0
npm info lifecycle rosbag2#0.1.0~start: rosbag2#0.1.0
> rosbag2#0.1.0 start /Users/andreasklintberg/personal/xviz/examples/converters/rosbag2
> node ./src/index.js "./src/index.js"
internal/modules/cjs/loader.js:779
return process.dlopen(module, path.toNamespacedPath(filename));
^
Error: dlopen(/Users/andreasklintberg/personal/xviz/examples/converters/rosbag2/node_modules/rosbags2_nodejs/build/Release/rosbags2_nodejs.node, 1): Library not loaded: #rpath/librosidl_typesupport_cpp.dylib
Referenced from: /Users/andreasklintberg/personal/xviz/examples/converters/rosbag2/node_modules/rosbags2_nodejs/build/Release/rosbags2_nodejs.node
Reason: image not found
And similarly in yarn
yarn start
yarn run v1.13.0
warning package.json: No license field
$ node ./src/index.js ./src/index.js -d ../../../data/rosbag2/rosbag2_2019_03_09-21_54_44 -o ../../xviz-data/rosbag2/rosbag2_2019_03_09-21_54_44/
internal/modules/cjs/loader.js:779
return process.dlopen(module, path.toNamespacedPath(filename));
^
Error: dlopen(/Users/andreasklintberg/personal/xviz/examples/converters/rosbag2/node_modules/rosbags2_nodejs/build/Release/rosbags2_nodejs.node, 1): Library not loaded: #rpath/librosidl_typesupport_cpp.dylib
Referenced from: /Users/andreasklintberg/personal/xviz/examples/converters/rosbag2/node_modules/rosbags2_nodejs/build/Release/rosbags2_nodejs.node
Reason: image not found
I know the error is because a dynamic link/#rpath is messed up, and I was thinking it was because npm/yarn messes with the env variables or something, but running yarn env it seems everything is correct.
So I guess i'm wondering if anyone know what the difference is running it in native node and using npm/yarnscript to wrap the start? And why this difference messes up the #rpath/dynamic linking ?
Edit:
My index.js file is very simple, just imports the built node-gyp package:
let RosbagDeserializer = require('../build/Release/rosbags2_nodejs.node');
const deserializer = new RosbagDeserializer.Rosbag2Wrapper();
This is the project in question, https://github.com/klintan/rosbag2_nodejs

I would love a more comprehensive answer but at least I solved it with the help of a lot of wonderful commenters:
The #rpath is not set on Mac, but with DYLD_LIBRARY_PATH it works, because that is one of the runtime search paths, it seems (https://superuser.com/questions/282450/where-do-i-set-dyld-library-path-on-mac-os-x-and-is-it-a-good-idea). However for some reason NPM removes this, I'm guessing it has to do with SIP on Mac, or maybe some other security measure that removes this env variable.
DYLD_LIBRARY_PATH is available if you run node index.js but NOT if you are running it using npm start (node index.js start script).
Both #Michal Kapracki and #Avik was hinting at this (I missed the missing env variables when comparing the first time)
What I did to solve it was similar to the dyld: Library not loaded ... Reason: Image not found question as #Avik linked, I had to add a bunch of libraries which were dependent (that was automatically resolved before) and a post_install.sh script which uses the install_name_tool to change the #rpaths to the correct path.
It's a pretty ugly solution https://github.com/klintan/rosbag2_nodejs/blob/master/post_install.sh but it works.
Only for Mac though, so needs to be generalized.
So in summary what I think is the issue:
NPM for some reason can't use or removes the env variable DYLD_LIBRARY_PATH which is used to search for dynamically linked libraries during runtime. This makes it necessary to link these manually using the mac tool install_name_tool.

Related

CodeMix/Eclipse cannot find 'react/jsx-dev-runtime'

I'm completely new to React, Node, NPM, and CodeMix in Eclipse. I'm a veteran java developer and so want to use eclipse over VSCode for familiarity. I'm following this tutorial:
https://www.genuitec.com/react-tutorial-getting-started/
I get to step 5 and run
react-scripts start
The result:
./src/index.js
Module not found: Can't resolve 'react/jsx-dev-runtime' in 'C:\temp\workspace\CCFPortal\src'
I created my project via the new project to create a React project. The wizard added all the standard code. Bringing up the terminal gave me some issues because the terminal doesn't seem to set the path to bring nodejs.exe into scope, so I did it manually in the terminal window. Adjusting the properties in window->preferences terminal+ doesn't seem to ever take effect.
I did the following in npm (in addition to the steps in the tutorial) because there were two 'warnings' in the markers view that suggested it. As near as I can tell, all commands were successful whether from the tutorial or these two (though it does flag some 'vulnerabilities' in npm that I force fixed).
npm install #types/react
npm install #types/react-dom
It is indeed true that there is no react/jsx-dev-runtime under that src folder. There's NOTHING there but the src. But I'm unclear why it wasn't there given that I ran npm install and the other things suggested in the tutorial.
Can someone help explain my pathing issue in the terminal and especially why npm is doing this when I run react-scripts start?

NodeJS unexpected strict mode reserved word "let" when installing ejs (not my code)

I'm getting this output when trying to install a node application using npm install:
$ npm install
> ejs#2.7.4 postinstall /home/dh_8u42k7/quotegoodeair.com/node_modules/ejs
> node ./postinstall.js
/home/dh_8u42k7/quotegoodeair.com/node_modules/ejs/postinstall.js:9
let envDisable = isTrue(process.env.DISABLE_OPENCOLLECTIVE) || isTrue(process.
^^^
SyntaxError: Unexpected strict mode reserved word
I have already found this question which contains a workaround. However, this isn't my own code, so I can't just remove "let", it seems to be a problem with ejs itself.
For another thing, the file postinstall.js doesn't even exist, even the ejs folder doesn't exist, so I can't just go in and edit the file.
Is there something wrong with my node application, or with ejs, or maybe with npm or Node itself? Why does Node install components which aren't supported by Node? Why does Node tell me there's an error in a file which doesn't exist?
It may be that your version of node does not support the features in the application you are trying to install.
One solution may be to find out what the version of node the application that you are trying to install originally used.
I believe you can check the engine field in your package.json file.
If you local node version is different, and you need to change it, here is a link to a question providing that information: How can I specify the required Node.js version in package.json?
I also found this post interesting: https://github.com/tj/n/issues/472
It's for a different application but they received the same error message. The issue was conflicting npm folders. It's possible that the program that you are trying to install is conflicting with your existing npm setup if you have other nom folders in the directory you are installing the application in.
Ultimately, given the information you provided, I think your best bet it to look in the package.json file of the application you're trying to install and see if your local setup is conflicting with how the program is trying to be installed or run.

node 6.11.3 NODE_EXE not found in IntelliJ

I've updated my project to use node 6.11.3. When I now try to start a npm-script by using the Run-configurations provided from IntelliJ, I always receive the following error:
Error: Failed to replace env in config: ${NODE_EXE}
Important: This error appears only if I start npm from within my project. If I use the windows cmd, the error doesn't appear.
What could possibly have changed between node 6.11.2 and 6.11.3? Because with the prior version, everything worked fine.
A workaround for me is to add the NODE_EXE variable to my run configuration, but In my opinion, that shouldn't be needed, because it worked in 6.11.2 too.
Looks as if you have ${NODE_EXE} variable set in one of your npmrc files (see https://docs.npmjs.com/files/npmrc#files), and it can't be properly expanded for some reason when you run your script in the IDE.
is the issue specific to certain project?
how many npm versions do you have installed? Please check that npm chosen in Node.js Interpreters dialog is the same as you use in cmd shell?
please create an env.js file with console.log(process.env) and try running it via npm ("env" : "node env.js") in both cmd console and WebStorm - what is the result?

How does NPM start an Angular and Typescript application?

Would it be possible to get an explanation of how npm start works?
I have an Angular 2 application written in Typescript. I enter npm start in the console and this both compiles and launches the application using Node's built in web server.
However what is the starting point for this? Which files does the npm start command read in order to compile and start the application? Also why do I use npm start and not e.g. node start? I understood that NPM was just the package manager for node itself.
What I understand so far:
I have a tsconfig.js file which tells the TypeScript compiler what to do.
I have a packages.json file which tells node which packages to download.
Where do the following files fit into this:
main.ts
app/app.module.ts - which I understand is the starting point for my application.
How do all of these components fit together to form the application?
npm start is just an alias for npm run start, which runs whatever command is in scripts.start in your package.json.
It neither knows nor cares about TypeScript, or Angular, or anything like that - it just executes whatever script it's given on the command line.

PhantomJS from Node on Windows

I have written a Electron application using Node, Electron Boilerplate, and phantom. It works perfectly fine for me on my linux machine, I copied the source over to Windows 10, and ran with npm start, and all goes smoothly.
However, when I try to build the application with the boilerplate module using npm run release, things go a little less smoothly. I can install and open the application just fine, but when I click the button that activates the phantom module, the windows goes all white and nothing happens. I was able to logs some errors with the dev tools.
First, I have:
C:\...\dist\win-unpacked\resources\app.asar\node_modules\phantom\lib\phantom.js:361
Uncaught (in promise) Error: Error reading from stdin: Error: write EPIPE(…)
I did some research into similar issues, namely here, and it seems to me the issue is starting the child process, PhantomJS, with the npm module phantom. Originally, I was using a WPF application I wrote in C# to start the process, and that worked just fine. This leads me to believe that the phantom module is the culprit.
So I tried swapping out the npm phantom module for horseman, but got similar results:
Unhandled rejection HeadlessError: Phantom immediately exited with: 4294967295
at ChildProcess.immediateExit (C:\...\dist\win-unpacked\resources\app.asar\node_modules\node-horseman\node_modules\node-phantom-simple\node-phantom-simple.js:153:23)
at ChildProcess.g (events.js:286:16)
at emitTwo (events.js:106:13)
at ChildProcess.emit (events.js:191:7)
at Process.ChildProcess._handle.onexit (internal/child_process.js:204:12)
Here is a shot in the dark. I am not positive this will solve your issue but here it goes:
GYP and miss-matched binaries
Phantom and many other node modules use binaries built for the specific OS that it will be running on. Sometimes in your npm log files you will see references to node-gyp. Node-gyp simply helps to build native add-on's in node modules. When the binaries are built they are usually built against, among others, three main parameters, the operating system, cpu architecture and version of node that is doing the installation.
I think you need to rebuild phantomjs to the version of node Electron is using. Most of the time the node version you have installed on your machine and the node version running in Electron are not the same. Electron does its best to keep up, but there is always a little lag because of the amount of work and testing required to keep up-to-date.
When you install phantom by running npm install phantom it will assume it needs to install or build the binaries for the node version your machine is using. Then when your Electron app tries to run phantom it tries to call the binary of the Electron's node version. When it isn't there the child process immediately exits with an error.
How to fix
Luckily, there are other people out there that have figured out how to fix this issue and have created a great tool to help generate the correct binaries.
Enter electron-rebuild:
https://github.com/electron/electron-rebuild
Electron-rebuild can be run in the command line, and it will rebuild all of your native modules to the version of Electron your project is using.
To install:
npm install electron-prebuilt
To use (in Windows):
.\node_modules\.bin\electron-rebuild.cmd
This should be enough to put the correct binaries in the right place.
Other thoughts
Sometimes you can use a package that uses a dependency called node-pre-gyp. E.g. sqlite3. There is a known issue I ended up running into when trying to rebuild my packages for Electron. Basically, in order to avoid this issue (if you run into it) just append --pre-gyp-fix to the above command.
Tangent for those who run into the pre-gyp-fix issue
One more thing on the pre-gyp-fix: If one or more of your dependencies depends on one of the modules that need the pre-gyp-fix then they will be looking for the binary in the wrong place even if they are running in Electron. All of the pre-gyp binaries are stored in a folder similar to this:
.\node_modules\sqlite3\lib\binding
In my current project I have three folders here, one for Electron-v1.4, and two for node-v46 and node-v50. (hack alert) In order to have sqlite3 work with my other dependencies I copy the binary found in the Electron-v1.4 folder and put it in both node-v* folders. That way when running in Electron, all dependencies are running the correct binaries even though they are looking for them in the wrong place. (end hack alert)
Conclusion
There is no way I can be sure this has anything to do with the issue you are seeing. But it is worth a shot to see if it fixes your problem. If not then at least I hope I can help someone else experiencing the same issues I ran into.

Resources