From 78b7232e38daaf36199e1c47ab15c29f91b9668b Mon Sep 17 00:00:00 2001 From: engigu Date: Mon, 23 Mar 2026 20:53:52 +0800 Subject: [PATCH] fix: node env path loading --- docker/docker-entrypoint.sh | 3 --- internal/executor/executor.go | 12 ++++++++++++ internal/utils/mise.go | 28 ++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh index aa95278..2e739ef 100644 --- a/docker/docker-entrypoint.sh +++ b/docker/docker-entrypoint.sh @@ -78,9 +78,6 @@ log " - node: $(node --version 2>&1 | head -n 1 || echo "not found")" log "Checking npm..." log " - npm: $(npm --version 2>&1 | head -n 1 || echo "not found")" -#export NODE_PATH=$(npm root -g 2>/dev/null || echo "") -#log " - node_path: $NODE_PATH" - # ============================ # 将 baihu 注册到全局命令 # ============================ diff --git a/internal/executor/executor.go b/internal/executor/executor.go index a347f84..79768f7 100644 --- a/internal/executor/executor.go +++ b/internal/executor/executor.go @@ -113,6 +113,18 @@ func ExecuteWithHooks(ctx context.Context, req Request, stdout, stderr io.Writer execCtx, cancel := context.WithTimeout(ctx, time.Duration(timeout)*time.Minute) defer cancel() + // 隐式且静默地获取包含 node 环境的全局路径,并注入环境变量 (带极速缓存) + if req.UseMise { + for _, lang := range req.Languages { + if lang["name"] == "node" { + if nodePath := utils.GetMiseNodePath(lang["version"]); nodePath != "" { + req.Envs = append(req.Envs, "NODE_PATH="+nodePath) + } + break + } + } + } + // 如果指定使用 mise,则预先构建好带 mise 的命令,这样 PreExecute 记录的就是完整命令 if req.UseMise { req.Command = utils.BuildMiseCommand(req.Command, req.Languages) diff --git a/internal/utils/mise.go b/internal/utils/mise.go index 7de0318..6e4392f 100644 --- a/internal/utils/mise.go +++ b/internal/utils/mise.go @@ -1,9 +1,37 @@ package utils import ( + "os/exec" "strings" + "sync" ) +var nodePathCache sync.Map + +// GetMiseNodePath 获取指定版本的 node 全局包路径,使用内存缓存避免重复获取 +func GetMiseNodePath(version string) string { + if version == "" { + version = "latest" + } + + if val, ok := nodePathCache.Load(version); ok { + return val.(string) + } + + cmd := exec.Command("mise", "where", "node@"+version) + out, err := cmd.Output() + if err == nil { + nodeDir := strings.TrimSpace(string(out)) + if nodeDir != "" { + nodePath := nodeDir + "/lib/node_modules" + nodePathCache.Store(version, nodePath) + return nodePath + } + } + + return "" +} + // BuildMiseCommand 构建多语言 mise 执行命令 (字符串形式) func BuildMiseCommand(command string, languages []map[string]string) string { if len(languages) == 0 {