fix(esm): Vendor 支持子路径,不然 es-toolkit/compat 这种装不了

有些包把东西放在子路径下(es-toolkit 的 toString 只在 compat 里,主入口没有),
而摊平之后原包的 exports 映射就没了,import "es-toolkit/compat" 解析不到。

现在直接写子路径就行:

    esm.Install(ctx, "es-toolkit/compat", "app/node_modules")

拉的是根包,摊平的是子路径,落到 node_modules/es-toolkit/compat/。根包和子路径
可以共存——子路径目录嵌在根包目录里,而最小 package.json 不写 exports,
所以解析器认得出来。

npm.SplitPath 负责拆名字,scoped 包名自带一个斜杠所以前两段才是包名。
This commit is contained in:
2026-09-07 10:58:34 +08:00
parent 00d95c496f
commit ad722b12f9
6 changed files with 179 additions and 4 deletions
+20
View File
@@ -323,6 +323,26 @@ func SplitSpec(spec string) (name, rng string) {
return spec, ""
}
// SplitPath 把带子路径的名字拆成包名和子路径。
//
// es-toolkit → es-toolkit, ""
// es-toolkit/compat → es-toolkit, "compat"
// @scope/pkg → @scope/pkg, ""
// @scope/pkg/sub/dir → @scope/pkg, "sub/dir"
//
// scoped 包名自带一个斜杠,所以前两段是包名。
func SplitPath(name string) (pkg, subpath string) {
segs := strings.Split(name, "/")
n := 1
if strings.HasPrefix(name, "@") {
n = 2
}
if len(segs) <= n {
return name, ""
}
return strings.Join(segs[:n], "/"), strings.Join(segs[n:], "/")
}
func keysOf(m map[string]release) []string {
out := make([]string, 0, len(m))
for k := range m {