Conflicts of a global and a local installation
I am working on the npm commandline tool and package https://github.com/ecma-make/ecmake. I ran into a strange conflict between a globally and a locally installed version of the package.
I can avoid this conflict by linking the one against the library of the other. Then there is only one instance of the library and no conflict. Now I have to think of the user, who does install the package into both places, once globally to be able to run the command without the npx
prefix, once locally to have the library listed in the dev section of package.json
.
How to reproduce
# prepare test fixture
mkdir ecmakeTest
cd ecmakeTest/
npm init -y
# install globally
npm install -g @ecmake/ecmake@0.3.1
npm ls -g @ecmake/ecmake
# install locally
npm install --save-dev @ecmake/ecmake@0.3.1
npm ls @ecmake/ecmake
# init ecmakeCode.js
npx ecmake --init
# run with local lib => shows the expected behaviour
npx ecmake all
# run with global lib => NoRootTaskError
ecmake all
Origin of the conflict
The stack trace guides us to the line within the global installation: /usr/local/lib/node_modules/@ecmake/ecmake/lib/runner/reader.js:21:13
.
if (!(root instanceof Task)) {
throw new Reader.NoRootTaskError(this.makefile);
}
What did happen?
The object root
created with the local library was checked against the class definition of the global library. They have the same name but they are different.
The global ecmake
runner requires the local makefile ecmakeCode.js
. This file in turn requires the Task
definition of the local library.
const root = module.exports = require('@ecmake/ecmake').makeRoot();
root.default
.described('defaults to all')
.awaits(root.all);
[...]
How do others solve this?
Gulp and Grunt export a function, that takes the actual dependency by injection. While dependency injection is generally very smart, in this case it's not that pretty. The whole file gets wrapped. I would like to avoid this wrapping function.
See: https://gulpjs.com/docs/en/getting-started/quick-start#create-a-gulpfile
See: https://gruntjs.com/getting-started
What I already considered
The runner could first check, if there is such a conflict. In case it could delegate the arguments given on the command line to npx ecmake
by creating a child process.
Alas, this would slow down the runner. At least one subprocess is required, maybe more to check the situation.
The question
Do you have a general solution to address this situation (apart from those I already named with their disadvantages)?
from How can we safely avoid clashes between a local and a global npm package for command line tools?
No comments:
Post a Comment