Issues with using "npm install" programmatically - javascript

It is an awesome feature that we can use "npm programmatically," but I am running into some issues. The function "npm.load" does not seems to be firing. I am not getting any console logs that are inside of my "npm.load" or "npm.commands.install" functions.
var npm = require('npm');
// There is another promise here
.then(function(path) {
// this is working the way I intend it to
cache[requestId].package = JSON.parse(path);
// This is firing
if (cache[requestId].package.name && cache[requestId].package.version && cache[requestId].package.scripts.start) {
// console logs and an array [ 'keystone', 'async', 'underscore', 'swig', 'node-sass', 'node-sass-middleware', 'dotenv' ]
console.log(Object.keys(cache[requestId].package.dependencies));
// console logs as /Users/207004/Desktop/github/mothership/server/app/routes/tractor-beam/ms-apps/my_site
console.log(localPath);
// console logs as a [Function]
console.log(npm.load);
// *** Here is the issue! This is not firing! ***
npm.load({}, function(err) {
// no console log
console.log(npm.commands.install);
// no console log
console.log(err);
npm.commands.install(localPath, Object.keys(cache[requestId].package.dependencies), function(err, done) {
// no console log
console.log('loaded');
// no console log
console.log(err, done);
// I am assuming that this is not firing, but my code does fire the console log in the next promise
return PM2.connectAsync();
});
});
} else {
console.log('else');
}
})
// Another promise chained here. A console log inside of this promise is firing.
Any help would be appreciated. Please let me know if you have any questions.
Thanks,

It took me a few days, but I figured a lot out.
While I was working on this, it seems that the documentation for using npm programmatically was removed from npmjs.com. Not sure if it means they deprecated the module, but I decided to use "child_process" after I found that the documentation was removed.
When I stated above that "npm.load" and "npm.install" was not firing, the reason was that I had my node app running with the npm "nodemon." Every time I would run "load" or "install" nodemon would consider this a change to the directory and my app would restart. I ran into the same issue with "child_process" as well. Really dumb! I know!
With my solution provided below, it takes npm install a while to run programmatically, so plan accordingly.
Here is the solution I came up with and it's with promises:
var Promise = require('bluebird');
// This will create promise functions for all the methods in the "child_process" module.
// Created "exec.execAsync" below.
var exec = Promise.promisifyAll(require('child_process'));
// Function to make package names one long string for the command line.
var getDependencies = function(dependencies) {
var deps = '';
Object.keys(dependencies).forEach(function(el){
deps = deps + ' ' + el;
});
return deps;
};
// Promise before this reads the package.json file
.then(function(packageJson){
var deps;
var pack = JSON.parse(packageJson);
if(pack && pack.dependencies) {
deps = getDependencies(pack.dependencies);
// I used the "--prefix" flag because I wanted to install the dependencies in a different directory.
// This part takes a while. Plan your promises before and after accordingly.
// The command below console logs into this "npm install --prefix /Users/Max/Desktop/github/mothership/server/app/routes/tractor-beam/ms-apps/my_site keystone async underscore swig node-sass node-sass-middleware dotenv"
return exec.execAsync('npm install --prefix ' + localPath + deps);
}
})
// Continues to next promise
Let me know if you have any questions.

Related

How to monitor STDOUT for a child_process spawn session that has a terminal animation?

Let's say I want to run npm install inside a node.js and log the STDOUT. I could think of something like this:
var process = child_process.spawn("npm", ["install", package_name]);
process.stdout.on('data', function (chunk) {
console.log(chunk.toString());
});
While this kind of execution works for some cases, in some cases it errors out. It's not giving me enough information what exactly is causing the error so I can only guess.
One thing I noticed is, nowadays a lot of npm install program executions do NOT display the log in a serial manner but instead display animation inline and stuff.
Here's an example of what I'm talking about:
My question is:
Might this kind of animation why the stdout.on('data') is erroring out in some cases?
How do I deal with this situation? I just want to get the full stream of all the data
There is stdout and stderr. Maybe try to catch errors there? Here is part of my code where I use npm installer, but in a bit different way by utilizing npm-cli.js, which gives the option to use npm without its global installation on the server:
// Require child_process module
const { fork } = require('child_process');
// Working directory for subprocess of installer
const cwd = './path-where-to-run-npm-command';
// CLI path FROM cwd path! Pay attention
// here - path should be FROM your cwd directory
// to your locally installed npm module
const cli = '../node_modules/npm/bin/npm-cli.js';
// NPM arguments to run with
// If your working directory already contains
// package.json file, then just install it!
const args = ['install']; // Or, i.e ['audit', 'fix']
// Run installer
const installer = fork(cli, args, {
silent: true,
cwd: cwd
});
// Monitor your installer STDOUT and STDERR
installer.stdout.on('data', (data) => {
console.log(data);
});
installer.stderr.on('data', (data) => {
console.log(data);
});
// Do something on installer exit
installer.on('exit', (code) => {
console.log(`Installer process finished with code ${code}`);
});

Failed building JavaScript bundle. Cannot read property 'reduce' of undefined on react native module traverseDependencies.js

**Hi, I don't know what happen here, it's something release with a dependence, It's a code that I didn't write, it's a bundle and I use expo to run my code but, can't open my app because that error please help!! it's for a college project **
function resolveDependencies(parentPath, dependencies, options) {
const resolve = (parentPath, result) => {
const relativePath = result.name;
try {
return [
relativePath,
{
absolutePath: options.resolve(parentPath, relativePath),
data: result
}
];
} catch (error) {
Ignore unavailable optional dependencies. They are guarded with a try-catch block and will be handled during runtime.
if (result.data.isOptional !== true) {
throw error;
}
}
return undefined;
};
const resolved = dependencies.reduce((list, result) => {
const resolvedPath = resolve(parentPath, result);
if (resolvedPath) {
list.push(resolvedPath);
}
return list;
}, []);
return new Map(resolved);
}
Re-traverse the dependency graph in DFS order to reorder the modules and
guarantee the same order between runs. This method mutates the passed graph.
I had the same issue on the latest expo-cli 4.8.1.
For me helped following steps
downgrade from 4.8.1 -> 4.7.3 npm install -g expo-cli#~4.7.3
clear npm cache by executing npm cache clean --force
clear local user cache by deleting everything in C:\Users<user>\AppData\Local\Temp folder.
After these steps, it is working again
I had this issue when running expo start --dev-client on expo-cli version 4.12.1.
I solved it by adding the --clear flag (which clears the Metro bundler cache)
Deleting the system cache Temp folder content will work,
When I face the same issue this solution help me to solve the problem

Cypress - print both on console AND on log file - Windows

I run Windows10, I have a project made on Cypress and I want to log the test results both on a file AND on console: I tried just printing on a file, using in my package.json this script:
"scripts": {
"open": "./node_modules/.bin/cypress open",
"runheadless": "./node_modules/.bin/cypress run --headless --browser chrome
--spec 'cypress/integration/webpages.spec.js' > cypresstest.log"
}
And this runs smoothly; my issue is that there are more than 100 tests and it takes very long time (like 20 minutes); so I can't check if something got frozen or is working fine, because nothing is printed on console.
So I tried with
"runheadless": "./node_modules/.bin/cypress run --headless --browser chrome
--spec 'cypress/integration/webpages.spec.js' | tee cypresstest.log"
But since I'm on windows, it says
tee is not recognized as internal or external program
Is there a way, or a plugin, or something I can do to simply print both on console AND on a file log?
Cypress-terminal-report has such a feature, or you can use a custom command including cy. task instead of cy.log - for example:
cypress plugin file
module.exports = (on, config) => {
on('task', {
log (message) {
console.log(message)
return null
}
})
}
custom command:
Cypress.Commands.add("logInAndOut", (message) => {
cy.log(message)
cy.task('log', message)
});
test file
cy.logInAndOut('My log')
Edit: I found another solution - Commands. overwrite(), and I`ll list an example, but I do not recommend it, since if other people try to use the code after you - won't know the change:
Cypress.Commands.overwrite('log', (originalFn, message, args...) => {
console.log(message, args...)
// originalFn is the existing `log` command that you need to call
// and it will receive whatever you pass in here.
//
// make sure to add a return here!
return originalFn(message, args...)
})

Jest Call retries were exceeded

I have error in the following below test. My node version is : v12.10.0. is there any alternative of setTimeout?
test('demo code', async () => {
const cc = await projectSetup(project);
const onNotification = jest.fn();
cc.sendNotification();
await waitForExpect(() => {
expect(onNotification).toHaveBeenCalledTimes(2);
});
});
The Error log is as
Call retries were exceeded
at ChildProcessWorker.initialize (../../../node_modules/jest-worker/build/workers/ChildProcessWorker.js:230:21)
just add jest.useFakeTimers(); after your imports
...
jest.useFakeTimers();
test('demo code', async () => {
const cc = await projectSetup(project);
const onNotification = jest.fn();
cc.sendNotification();
await waitForExpect(() => {
expect(onNotification).toHaveBeenCalledTimes(2);
});
});
it works in my code
In my case, the actual problem was with the promise handling.
I got the same issue when I was running all my test cases in one go with the jest.
Solution:
Try running one test separately then see what error is coming.
I got the below error after running one problematic test separately where earlier I was getting the Call retries were exceeded:
[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "TypeError: Cannot read property 'code' of undefined".] {
code: 'ERR_UNHANDLED_REJECTION'
}
With this, I was sure that the problem is with the catch block and when I added it in the async service API function then the test case worked perfectly fine.
Maybe you can also try the same and see if it works for you or not.
I am using the below config:
node: 15.13.0
npm: 7.8.0
jest: 26.6.3
Try running npm doctor using the latest npm version. It's a great tool and it helped me diagnose permission and ownership issues right away.
Takeaway:
Verify File/Folder Permissions & Ownership
Encountered same error when updating the vue-jest version to below listed versions
#vue/vue3-jest: ^27.0.0-alpha.4
#vue/cli-plugin-unit-jest: ~5.0.0,
node: v17.9.0 or v16.14.2
Error disappeared, once downgraded it to node version v14.x.x
Hunch is - the latest node versions are not compatible with the dependencies.
I was able to run the test's successfully doing the following;
Install npm i -D jest-canvas-mock
Update the jest.config.ts file to have:
export default {
...
testEnvironment: "jsdom",
setupFiles: ["jest-canvas-mock"],
}

Gulp [4.0.2] hangs when async function is completed even though callback is completed

I have a gulp task that's hanging after completion.
Running --verbose on my command tells me that it completed the run, but it doesnt exit the process
// ./gulpfile.js/precon/index.js
const { preconMoveFile, preconExcelToMysql } = require('../../src/lib/preCon')
module.exports = async done => {
try {
await preconMoveFile()
await preconExcelToMysql()
done()
// return <-- doesnt work either per comment
} catch (e) {
throw e
}
}
below is the command line output, pardon my debug log output
C:\Users\ALilland\Documents\macros\experiments\forecast-scraper>set NODE_ENV=development& gulp precon --verbose
[12:33:57] Using gulpfile ~\Documents\macros\experiments\forecast-scraper\gulpfile.js
[12:33:57] Starting 'precon'...
[2019-07-30T19:33:57.264Z] DEBUG - [preCon.preconMoveFile] existing ./src/tmp/precon.xlsx removed
[2019-07-30T19:33:57.333Z] DEBUG - [preCon.preconMoveFile] copied new file to ./src/tmp/precon.xlsx
[2019-07-30T19:33:58.965Z] INFO - [initialize.db.caePreconForecast] created caePreconForecast
[2019-07-30T19:33:59.012Z] DEBUG - [preCon.preconExcelToMysql] added rows to db
[12:34:00] Finished 'precon' after 3.24 s
I tried several of the options shown in the docs with no success, and also tried several of the options here with no success
I have also tried calling process.exit(0) but that produces the Did you forget to signal async completion? warning that the docs mention
Edit:
I should also note my root index.js file that requires the precon task
// ./gulpfile.js/index.js
exports.default = require('./default')
exports.precon = require('./precon')
The hang does not result from gulp, there is a background process still running preventing gulp from closing
the culprit was an open mysql pool connection
const mysql = require('mysql')
const params = require('../config/mysql')
const db = mysql.createPool(params)
db.end() // <-- running this after each task resolves the issue

Categories