Skip to content

Commit 290cde5

Browse files
committed
fix: fix npm command
1 parent 97e4ceb commit 290cde5

File tree

5 files changed

+60
-29
lines changed

5 files changed

+60
-29
lines changed

docs/apis/LanguageSupport.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ Currently, LSE supports writing plugins in the following languages:
6464
- Distribute the **.llplugin** file as a plugin. When installing the plugin, just place this file directly into the
6565
plugins directory
6666
- LSE will automatically recognize the **.llplugin** file when BDS launch, extract it to the
67-
`plugins/nodejs/<PluginName>` directory, and automatically execute `npm install` in the directory to install the
67+
`plugins/nodejs/<PluginName>` directory, and automatically execute `npm install --omit=dev` in the directory to install the
6868
dependency packages. No manual intervention is needed for the whole process
6969

7070
## Python language support description

docs/apis/LanguageSupport.zh.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
- 在插件编写完成之后,请将 `package.json` 以及所有插件源码打包为一个zip压缩包,并**将文件名后缀修改为 .llplugin**
4949
- `node_modules` 目录请勿打包在压缩包之中
5050
-**.llplugin** 文件作为插件分发,安装插件时直接将此文件放置到 plugins 目录即可
51-
- 在开服时,脚本引擎会自动识别 **.llplugin** 文件,将其解压到`plugins/nodejs/插件名`目录,并在目录中自动执行 `npm install`
51+
- 在开服时,脚本引擎会自动识别 **.llplugin** 文件,将其解压到`plugins/nodejs/插件名`目录,并在目录中自动执行 `npm install --omit=dev`
5252
安装依赖包,整个过程无需人工干预
5353

5454
## Python 语言支持说明

src/legacy/main/NodeJsHelper.cpp

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
#include <filesystem>
21
#pragma warning(disable : 4251)
32

3+
#include "main/NodeJsHelper.h"
4+
45
#include "api/EventAPI.h"
56
#include "engine/EngineManager.h"
67
#include "engine/EngineOwnData.h"
@@ -15,12 +16,10 @@
1516
#include "ll/api/thread/ServerThreadExecutor.h"
1617
#include "ll/api/utils/StringUtils.h"
1718
#include "main/Global.h"
18-
#include "main/NodeJsHelper.h"
19+
#include "utils/Utils.h"
1920
#include "uv/uv.h"
2021
#include "v8/v8.h"
2122

22-
#include <functional>
23-
2423
using ll::chrono_literals::operator""_tick;
2524

2625
// pre-declare
@@ -41,24 +40,25 @@ std::vector<node::Environment*> uvLoopTask;
4140

4241
bool initNodeJs() {
4342
// Init NodeJs
44-
WCHAR buf[MAX_PATH];
45-
GetCurrentDirectory(MAX_PATH, buf);
46-
auto path = ll::string_utils::wstr2str(buf) + "\\bedrock_server_mod.exe";
43+
auto path = ll::string_utils::u8str2str(ll::sys_utils::getModulePath(nullptr).value().u8string());
4744
char* cPath = (char*)path.c_str();
4845
uv_setup_args(1, &cPath);
49-
args = {path};
50-
auto result = node::InitializeOncePerProcess(
51-
args,
46+
auto full_args = std::vector<std::string>{path};
47+
auto result = node::InitializeOncePerProcess(
48+
full_args,
5249
{node::ProcessInitializationFlags::kNoInitializeV8,
53-
node::ProcessInitializationFlags::kNoInitializeNodeV8Platform}
50+
node::ProcessInitializationFlags::kNoInitializeNodeV8Platform}
5451
);
55-
exec_args = result->exec_args();
5652
if (result->exit_code() != 0) {
5753
lse::LegacyScriptEngine::getInstance().getSelf().getLogger().error(
5854
"Failed to initialize node! NodeJs plugins won't be loaded"
5955
);
56+
for (const std::string& error : result->errors())
57+
lse::LegacyScriptEngine::getInstance().getSelf().getLogger().error(error);
6058
return false;
6159
}
60+
args = result->args();
61+
exec_args = result->exec_args();
6262

6363
// Init V8
6464
using namespace v8;
@@ -382,8 +382,8 @@ bool isESModulesSystem(const std::string& dirPath) {
382382

383383
bool processConsoleNpmCmd(const std::string& cmd) {
384384
#ifdef LEGACY_SCRIPT_ENGINE_BACKEND_NODEJS
385-
if (cmd.starts_with("npm ")) {
386-
executeNpmCommand(cmd);
385+
if (cmd.starts_with("npm ") || cmd.starts_with("npx ")) {
386+
executeNpmCommand(SplitCmdLine(cmd));
387387
return false;
388388
} else {
389389
return true;
@@ -393,21 +393,35 @@ bool processConsoleNpmCmd(const std::string& cmd) {
393393
#endif
394394
}
395395

396-
int executeNpmCommand(const std::string& cmd, std::string workingDir) {
396+
int executeNpmCommand(std::vector<std::string> npmArgs, std::string workingDir) {
397397
if (!nodeJsInited && !initNodeJs()) {
398398
return -1;
399399
}
400400
std::string engineDir =
401401
ll::string_utils::u8str2str(lse::LegacyScriptEngine::getInstance().getSelf().getModDir().u8string());
402402
if (workingDir.empty()) workingDir = engineDir;
403-
std::vector<std::string> errors;
403+
404+
auto npmPath = std::filesystem::absolute(engineDir) / "node_modules" / "npm" / "bin" / "npm-cli.js";
405+
std::vector<std::string>& env_args = npmArgs;
406+
if (!env_args.empty() && (env_args[0] == "npm" || env_args[0] == "npx")) {
407+
if (env_args[0] == "npx") {
408+
npmPath = std::filesystem::absolute(engineDir) / "node_modules" / "npm" / "bin" / "npx-cli.js";
409+
}
410+
env_args.erase(env_args.begin());
411+
}
412+
auto scriptPath = ll::string_utils::replaceAll(ll::string_utils::u8str2str(npmPath.u8string()), "\\", "/");
413+
env_args.insert(env_args.begin(), {args[0], scriptPath});
414+
415+
std::vector<std::string> errors;
416+
404417
std::unique_ptr<node::CommonEnvironmentSetup> setup = node::CommonEnvironmentSetup::Create(
405418
platform.get(),
406419
&errors,
407-
args,
420+
env_args,
408421
exec_args,
409422
node::EnvironmentFlags::kOwnsProcessState
410423
);
424+
411425
// if kOwnsInspector set, inspector_agent.cc:681
412426
// CHECK_EQ(start_io_thread_async_initialized.exchange(true), false) fail!
413427

@@ -437,26 +451,40 @@ int executeNpmCommand(const std::string& cmd, std::string workingDir) {
437451
R"(
438452
const engineDir = "{0}";
439453
const workingDir = "{1}";
440-
const command = "{2}";
441-
const oldCwd = process.cwd();
454+
const scriptPath = "{2}";
442455
const publicRequire = require("module").createRequire(
443456
require("path").resolve(engineDir) + require("path").sep
444457
);
458+
// Record states and restore at exit
459+
const oldCwd = process.cwd();
460+
const oldEnv = Object.entries(process.env).filter(([k]) => k.startsWith("npm_"));
461+
const oldTitle = process.title;
462+
process.on("exit", () => {{
463+
Object.keys(process.env)
464+
.filter((k) => k.startsWith("npm_"))
465+
.forEach((k) => delete process.env[k]);
466+
oldEnv.forEach(([k, v]) => (process.env[k] = v));
467+
process.title = oldTitle;
468+
process.chdir(oldCwd);
469+
}});
470+
445471
process.chdir(workingDir);
446-
publicRequire("npm-js-interface")(command);
447-
process.chdir(oldCwd);
472+
publicRequire(scriptPath);
448473
)",
449474
engineDir,
450475
workingDir,
451-
cmd
476+
scriptPath
452477
);
453478

454479
try {
455-
node::SetProcessExitHandler(env, [&](node::Environment* env_, int exit_code) { node::Stop(env); });
480+
node::SetProcessExitHandler(env, [&](node::Environment*, int exit_code_) {
481+
exit_code = exit_code_;
482+
node::Stop(env);
483+
});
456484
MaybeLocal<v8::Value> loadenv_ret = node::LoadEnvironment(env, executeJs);
457485
if (loadenv_ret.IsEmpty()) // There has been a JS exception.
458-
throw "error";
459-
exit_code = node::SpinEventLoop(env).FromMaybe(0);
486+
throw std::runtime_error("Failed at LoadEnvironment");
487+
exit_code = node::SpinEventLoop(env).FromMaybe(exit_code);
460488
} catch (...) {
461489
lse::LegacyScriptEngine::getInstance().getSelf().getLogger().error(
462490
"Fail to execute NPM command. Error occurs"

src/legacy/main/NodeJsHelper.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@ bool doesPluginPackHasDependency(const std::string& dirPath);
3030
bool isESModulesSystem(const std::string& dirPath);
3131

3232
bool processConsoleNpmCmd(const std::string& cmd);
33-
int executeNpmCommand(const std::string& cmd, std::string workingDir = "");
33+
int executeNpmCommand(std::vector<std::string> npmArgs = {"i", "--omit=dev", "--no-fund"}, std::string workingDir = "");
3434

3535
} // namespace NodeJsHelper

src/lse/PluginManager.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,10 @@ ll::Expected<> PluginManager::load(ll::mod::Manifest manifest) {
116116
fmt::arg("name", ll::string_utils::u8str2str(dirPath.filename().u8string()))
117117
)
118118
);
119-
if ((exitCode = NodeJsHelper::executeNpmCommand("npm install", ll::string_utils::u8str2str(dirPath.u8string())))
119+
if ((exitCode = NodeJsHelper::executeNpmCommand(
120+
{"install", "--omit=dev", "--no-fund"},
121+
ll::string_utils::u8str2str(dirPath.u8string())
122+
))
120123
!= 0) {
121124
lse::LegacyScriptEngine::getInstance().getSelf().getLogger().error(
122125
"Error occurred. Exit code: {code}"_tr(fmt::arg("code", exitCode))

0 commit comments

Comments
 (0)