Compare commits

...

2 Commits
v1.5.3 ... main

Author SHA1 Message Date
AI Engineer
1312095ce7 feat: align JS exports to PascalCase and flatten default instance (by AI) 2026-06-10 12:12:36 +08:00
AI Engineer
63cd9d392a refactor: use jsmod.Get for context configuration (by AI) 2026-06-10 09:52:55 +08:00

View File

@ -12,7 +12,69 @@ import (
func init() { func init() {
jsmod.Register("db", map[string]any{ jsmod.Register("db", map[string]any{
"get": func(ctx context.Context, name string) (*jsDB, error) { // 入口:支持别名获取,不传则默认 "default"
"Get": func(ctx context.Context, name *string) (*jsDB, error) {
target := "default"
if name != nil {
target = *name
}
return getJSDB(ctx, target)
},
// 默认快捷调用 (面向 "default" 实例)
"Query": func(ctx context.Context, query string, args ...any) (*QueryResult, error) {
jd, err := getJSDB(ctx, "default")
if err != nil {
return nil, err
}
return jd.Query(query, args...), nil
},
"Exec": func(ctx context.Context, query string, args ...any) (*ExecResult, error) {
jd, err := getJSDB(ctx, "default")
if err != nil {
return nil, err
}
return jd.Exec(query, args...), nil
},
"Insert": func(ctx context.Context, table string, data any) (*ExecResult, error) {
jd, err := getJSDB(ctx, "default")
if err != nil {
return nil, err
}
return jd.Insert(table, data), nil
},
"Update": func(ctx context.Context, table string, data any, conditions string, args ...any) (*ExecResult, error) {
jd, err := getJSDB(ctx, "default")
if err != nil {
return nil, err
}
return jd.Update(table, data, conditions, args...), nil
},
"Delete": func(ctx context.Context, table string, conditions string, args ...any) (*ExecResult, error) {
jd, err := getJSDB(ctx, "default")
if err != nil {
return nil, err
}
return jd.Delete(table, conditions, args...), nil
},
"Replace": func(ctx context.Context, table string, data any) (*ExecResult, error) {
jd, err := getJSDB(ctx, "default")
if err != nil {
return nil, err
}
return jd.Replace(table, data), nil
},
"Begin": func(ctx context.Context) (*jsTx, error) {
jd, err := getJSDB(ctx, "default")
if err != nil {
return nil, err
}
return jd.Begin()
},
})
}
func getJSDB(ctx context.Context, name string) (*jsDB, error) {
isReadOnly := false isReadOnly := false
// 安全模式下的动态判定 // 安全模式下的动态判定
@ -23,7 +85,6 @@ func init() {
if idx := strings.Index(path, "?"); idx != -1 { if idx := strings.Index(path, "?"); idx != -1 {
path = path[:idx] path = path[:idx]
} }
// 如果路径不在沙箱内VerifyPathForSafeMode 会直接返回 error阻止连接
_, err := file.VerifyPathForSafeMode(ctx, path) _, err := file.VerifyPathForSafeMode(ctx, path)
if err != nil { if err != nil {
return nil, err return nil, err
@ -32,7 +93,7 @@ func init() {
} else { } else {
// 2. 远程数据库前缀校验 // 2. 远程数据库前缀校验
var allowedDSNs []string var allowedDSNs []string
cast.Convert(&allowedDSNs, ctx.Value("AllowedDSNs")) cast.Convert(&allowedDSNs, jsmod.Get(ctx, "AllowedDSNs"))
matched := false matched := false
for _, prefix := range allowedDSNs { for _, prefix := range allowedDSNs {
if strings.HasPrefix(name, prefix) { if strings.HasPrefix(name, prefix) {
@ -41,7 +102,6 @@ func init() {
} }
} }
if !matched { if !matched {
// 未命中白名单,降级为只读模式
isReadOnly = true isReadOnly = true
} }
} }
@ -52,8 +112,6 @@ func init() {
return nil, d.Error return nil, d.Error
} }
return &jsDB{db: d, ctx: ctx, isReadOnly: isReadOnly}, nil return &jsDB{db: d, ctx: ctx, isReadOnly: isReadOnly}, nil
},
})
} }
type jsDB struct { type jsDB struct {
@ -121,6 +179,10 @@ func (jd *jsDB) Begin() (*jsTx, error) {
return &jsTx{tx: tx, ctx: jd.ctx, isReadOnly: jd.isReadOnly}, nil return &jsTx{tx: tx, ctx: jd.ctx, isReadOnly: jd.isReadOnly}, nil
} }
// Metadata
func (jd *jsDB) InKeys(numArgs int) string { return jd.db.InKeys(numArgs) }
func (jd *jsDB) Quote(text string) string { return jd.db.Quote(text) }
// jsTx wraps *Tx for JS environment // jsTx wraps *Tx for JS environment
type jsTx struct { type jsTx struct {
tx *Tx tx *Tx
@ -182,7 +244,3 @@ func (jt *jsTx) Commit() error {
} }
func (jt *jsTx) Rollback() error { return jt.tx.Rollback() } func (jt *jsTx) Rollback() error { return jt.tx.Rollback() }
// Metadata
func (jd *jsDB) InKeys(numArgs int) string { return jd.db.InKeys(numArgs) }
func (jd *jsDB) Quote(text string) string { return jd.db.Quote(text) }