问题
There is a CLI that runs on Node and can be executed via command
on the command line. In its code, some functionality is deactivated for Windows users by if (process.platform === 'win32') { process.exit(1); }
. Now I want to disable this check, and allow Windows users to use the "hidden" functionality (usually the the required software is not installed on Windows, but I have a special setup where it is).
Is there some way, to lie to this CLI and simulate that it is running on e.g. Linux or macOS?
Of course I could fork the CLI, remove the check and work with my own version - but this would require repeating this process for each release. As this functionality should also be available to other users, I would have to publish the forked and modified CLI which could be a frequent source of confusion for its users (What about version numbers? Do I use the same command
?) - 99.9% of the code will stay untouched.
Could I maybe write my own CLI, that does something to "fake" the environment, then executes the installed, original CLI, and cleans up afterwards?
I created an example package that works identical to the CLI, but only does exactly that part that I am investigating:
- https://github.com/janpio/nodejs-cli-nowin
- https://www.npmjs.com/package/nodejs-cli-nowin
Install via npm i -g nodejs-cli-nowin
.
回答1:
Basically, wrapper package should be used to provide entry point instead of original package. process.platform
should be mocked with new value before original package runs.
wrapper-package/index.js
Object.defineProperty(process, 'platform', { value: 'linux' });
require('original-package/bin/entry-point.js');
This won't affect child processes if original package spawns them.
This doesn't guarantee that the package will work as intended with mocked platform, there's a good chance that it won't. Even if the package itself works correctly, this may result in unpredictable behaviour in package dependencies that rely on process.platform
.
In order to affect process.platform
only for specific module, platform
global should be shadowed with local variable. To do this, module wrapper function should be modified:
const Module = require('module')
const escapedPatchedModulePath = require.resolve('original-package/module-to-patch.js')
.replace(/\\/g, '\\\\');
Module.wrapper[0] += `
const isPatchedModule = __filename === "${escapedPatchedModulePath}";
let process = isPatchedModule
? Object.create(global.process, { platform: { value: 'linux' } })
: global.process;
`;
require('original-package/bin/entry-point.js');
来源:https://stackoverflow.com/questions/54374379/how-to-lie-to-program-about-process-platform