stage 1
This commit is contained in:
41
internal/hubmodule/npm/locator.go
Normal file
41
internal/hubmodule/npm/locator.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package npm
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/any-hub/any-hub/internal/cache"
|
||||
)
|
||||
|
||||
// rewriteLocator 将 npm metadata JSON 落盘至 package.json,避免与 tarball
|
||||
// 路径的 `/-/` 子目录冲突,同时保持 tarball 使用原始路径。
|
||||
func rewriteLocator(loc cache.Locator) cache.Locator {
|
||||
path := loc.Path
|
||||
if path == "" {
|
||||
return loc
|
||||
}
|
||||
|
||||
var qsSuffix string
|
||||
core := path
|
||||
if idx := strings.Index(core, "/__qs/"); idx >= 0 {
|
||||
qsSuffix = core[idx:]
|
||||
core = core[:idx]
|
||||
}
|
||||
|
||||
if strings.Contains(core, "/-/") {
|
||||
loc.Path = core + qsSuffix
|
||||
return loc
|
||||
}
|
||||
|
||||
clean := strings.TrimSuffix(core, "/")
|
||||
if clean == "" {
|
||||
clean = "/"
|
||||
}
|
||||
|
||||
if clean == "/" {
|
||||
loc.Path = "/package.json" + qsSuffix
|
||||
return loc
|
||||
}
|
||||
|
||||
loc.Path = clean + "/package.json" + qsSuffix
|
||||
return loc
|
||||
}
|
||||
30
internal/hubmodule/npm/module.go
Normal file
30
internal/hubmodule/npm/module.go
Normal file
@@ -0,0 +1,30 @@
|
||||
// Package npm 描述 npm Registry 模块的默认策略与注册逻辑,方便新 Hub 直接启用。
|
||||
package npm
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/any-hub/any-hub/internal/hubmodule"
|
||||
)
|
||||
|
||||
const npmDefaultTTL = 30 * time.Minute
|
||||
|
||||
// npm 模块描述 NPM Registry 的默认缓存策略,并允许通过 [[Hub]] 覆盖 TTL/Validation。
|
||||
func init() {
|
||||
hubmodule.MustRegister(hubmodule.ModuleMetadata{
|
||||
Key: "npm",
|
||||
Description: "NPM proxy module with cache strategy overrides for metadata/tarballs",
|
||||
MigrationState: hubmodule.MigrationStateBeta,
|
||||
SupportedProtocols: []string{
|
||||
"npm",
|
||||
},
|
||||
CacheStrategy: hubmodule.CacheStrategyProfile{
|
||||
TTLHint: npmDefaultTTL,
|
||||
ValidationMode: hubmodule.ValidationModeLastModified,
|
||||
DiskLayout: "raw_path",
|
||||
RequiresMetadataFile: false,
|
||||
SupportsStreamingWrite: true,
|
||||
},
|
||||
LocatorRewrite: rewriteLocator,
|
||||
})
|
||||
}
|
||||
52
internal/hubmodule/npm/module_test.go
Normal file
52
internal/hubmodule/npm/module_test.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package npm
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/any-hub/any-hub/internal/hubmodule"
|
||||
)
|
||||
|
||||
func TestNPMMetadataRegistration(t *testing.T) {
|
||||
meta, ok := hubmodule.Resolve("npm")
|
||||
if !ok {
|
||||
t.Fatalf("npm module not registered")
|
||||
}
|
||||
if meta.Key != "npm" {
|
||||
t.Fatalf("unexpected module key: %s", meta.Key)
|
||||
}
|
||||
if meta.MigrationState == "" {
|
||||
t.Fatalf("migration state must be set")
|
||||
}
|
||||
if len(meta.SupportedProtocols) == 0 {
|
||||
t.Fatalf("supported protocols must not be empty")
|
||||
}
|
||||
if meta.CacheStrategy.TTLHint != npmDefaultTTL {
|
||||
t.Fatalf("expected default ttl %s, got %s", npmDefaultTTL, meta.CacheStrategy.TTLHint)
|
||||
}
|
||||
if meta.CacheStrategy.ValidationMode != hubmodule.ValidationModeLastModified {
|
||||
t.Fatalf("expected validation mode last-modified, got %s", meta.CacheStrategy.ValidationMode)
|
||||
}
|
||||
if !meta.CacheStrategy.SupportsStreamingWrite {
|
||||
t.Fatalf("npm strategy should support streaming writes")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNPMStrategyOverrides(t *testing.T) {
|
||||
meta, ok := hubmodule.Resolve("npm")
|
||||
if !ok {
|
||||
t.Fatalf("npm module not registered")
|
||||
}
|
||||
|
||||
overrideTTL := 10 * time.Minute
|
||||
strategy := hubmodule.ResolveStrategy(meta, hubmodule.StrategyOptions{
|
||||
TTLOverride: overrideTTL,
|
||||
ValidationOverride: hubmodule.ValidationModeETag,
|
||||
})
|
||||
if strategy.TTLHint != overrideTTL {
|
||||
t.Fatalf("expected ttl override %s, got %s", overrideTTL, strategy.TTLHint)
|
||||
}
|
||||
if strategy.ValidationMode != hubmodule.ValidationModeETag {
|
||||
t.Fatalf("expected validation mode override to etag, got %s", strategy.ValidationMode)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user