diff --git a/CHANGELOG.md b/CHANGELOG.md index f2cc393..239f23e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG - redis +## v1.5.6 (2026-06-21) +- **JS 对齐**: 重构 JS 导出为具名函数,并引入 `jsmod.MakeError` 动态包装错误以获取调用栈。 +- **依赖更新**: 升级依赖 `jsmod` 至 `v1.5.3`,`cast` 至 `v1.5.3`,`rand` 至 `v1.5.3`,`encoding` 至 `v1.5.4`,`shell` 至 `v1.5.3`,`safe` 至 `v1.5.2`,`id` 至 `v1.5.4`,`crypto` 至 `v1.5.3`,`file` 至 `v1.5.5`,`config` 至 `v1.5.3`,`log` 至 `v1.5.8`。 + ## v1.5.5 (2026-06-20) - **JS 导出重构**: - 移除 `js_export.go` 中冗余的独立命令快捷函数(SET, GET, DEL, EXISTS, EXPIRE, PUBLISH),统一通过 `Do` 方法调用。 diff --git a/TEST.md b/TEST.md index 9f6adbe..54d0b2d 100644 --- a/TEST.md +++ b/TEST.md @@ -16,5 +16,9 @@ - **BenchmarkGetSet**: ~80,000 ns/op (Simple GET/SET loop) - **BenchmarkIDMaker**: ~2,300 ns/op (High-performance sequence generation) -> Date: 2026-05-05 +## 🛡️ 鲁棒性防御 (Robustness) +- **安全沙箱拦截**:在 `SafeMode` 下,仅允许 GET/EXISTS/ZRANGE 等读操作命令,自动拦截所有写操作命令并返回错误。 +- **JS 错误调用栈**:JS 桥接层改用具名导出并使用 `jsmod.MakeError` 包裹错误(包括 Do 返回的 Result.Error 字段),确保 JS 抛出异常时携带准确的 Go 运行时堆栈。 + +> Date: 2026-06-21 > Environment: Darwin / Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz diff --git a/go.mod b/go.mod index 5903be5..3aeca97 100644 --- a/go.mod +++ b/go.mod @@ -3,21 +3,21 @@ module apigo.cc/go/redis go 1.25.0 require ( - apigo.cc/go/cast v1.5.2 - apigo.cc/go/config v1.5.2 - apigo.cc/go/crypto v1.5.2 - apigo.cc/go/encoding v1.5.3 - apigo.cc/go/id v1.5.3 - apigo.cc/go/jsmod v1.5.2 - apigo.cc/go/log v1.5.6 - apigo.cc/go/safe v1.5.1 + apigo.cc/go/cast v1.5.3 + apigo.cc/go/config v1.5.3 + apigo.cc/go/crypto v1.5.3 + apigo.cc/go/encoding v1.5.4 + apigo.cc/go/id v1.5.4 + apigo.cc/go/jsmod v1.5.3 + apigo.cc/go/log v1.5.8 + apigo.cc/go/safe v1.5.2 github.com/gomodule/redigo v2.0.0+incompatible ) require ( - apigo.cc/go/file v1.5.4 // indirect - apigo.cc/go/rand v1.5.2 // indirect - apigo.cc/go/shell v1.5.2 // indirect + apigo.cc/go/file v1.5.5 // indirect + apigo.cc/go/rand v1.5.3 // indirect + apigo.cc/go/shell v1.5.3 // indirect golang.org/x/crypto v0.52.0 // indirect golang.org/x/sys v0.45.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/js_export.go b/js_export.go index a6079a5..244425e 100644 --- a/js_export.go +++ b/js_export.go @@ -13,38 +13,46 @@ import ( func init() { jsmod.Register("redis", map[string]any{ // 入口:支持别名获取,不传则默认 "default" - "Get": func(ctx context.Context, name *string) (*jsRedis, error) { - target := "default" - if name != nil { - target = *name - } - rd := GetRedis(target, nil) - if rd.Error != nil { - return nil, rd.Error - } - return &jsRedis{rd: rd, ctx: ctx}, nil - }, + "Get": jsGet, // 默认快捷调用 (面向 "default" 实例) - "Do": func(ctx context.Context, cmd string, args ...any) (*Result, error) { - jr := getDefaultRedisForJS(ctx) - if jr.rd.Error != nil { - return nil, jr.rd.Error - } - res := jr.Do(cmd, args...) - return res, res.Error - }, - - "MakeID": func(ctx context.Context, size int, forDB *string) string { - jr := getDefaultRedisForJS(ctx) - if jr.rd.Error != nil { - return id.MakeID(size) - } - return jr.MakeID(size, forDB) - }, + "Do": jsDo, + "MakeID": jsMakeID, }) } +func jsGet(ctx context.Context, name *string) (*jsRedis, error) { + target := "default" + if name != nil { + target = *name + } + rd := GetRedis(target, nil) + if rd.Error != nil { + return nil, jsmod.MakeError(rd.Error) + } + return &jsRedis{rd: rd, ctx: ctx}, nil +} + +func jsDo(ctx context.Context, cmd string, args ...any) (*Result, error) { + jr := getDefaultRedisForJS(ctx) + if jr.rd.Error != nil { + return nil, jsmod.MakeError(jr.rd.Error) + } + res := jr.Do(cmd, args...) + if res != nil && res.Error != nil { + return res, jsmod.MakeError(res.Error) + } + return res, nil +} + +func jsMakeID(ctx context.Context, size int, forDB *string) string { + jr := getDefaultRedisForJS(ctx) + if jr.rd.Error != nil { + return id.MakeID(size) + } + return jr.MakeID(size, forDB) +} + type jsRedis struct { rd *Redis ctx context.Context @@ -86,9 +94,15 @@ func (jr *jsRedis) checkSafe(cmd string) error { func (jr *jsRedis) Do(cmd string, args ...any) *Result { if err := jr.checkSafe(cmd); err != nil { - return &Result{Error: err} + return &Result{Error: jsmod.MakeError(err)} } - return jr.rd.Do(cmd, args...) + res := jr.rd.Do(cmd, args...) + if res != nil && res.Error != nil { + resCopy := *res + resCopy.Error = jsmod.MakeError(res.Error) + return &resCopy + } + return res } // ID Generation