package jscriptx // Extension 是一个作用域级扩展:给脚本添一个全局对象。 // // 扩展实例由调用方自己创建,跟着 ctx 走: // // st := jscriptx.NewStore() // tx := myTx(db) // ctx = jscriptx.WithScope(ctx, jscriptx.ScopeExtensions(st, tx)) // // obj, err := ctrl.New(ctx) // 脚本里能用 store 和 tx // defer obj.Close() // // st.Get("count") // Go 侧拿的就是同一份,不用再取回 // // 同一个 ctx 下 New 出来的所有实例共享同一份扩展对象——这就是多个 controller // 共享数据的方式:共享的是 Go 侧对象,不是共用 Runtime。 // // 业务写自己的扩展只要实现这三个方法: // // type tx struct{ conn *sql.Tx } // // func (t *tx) Name() string { return "tx" } // func (t *tx) Bindings() map[string]any { // return map[string]any{"commit": t.conn.Commit, "rollback": t.conn.Rollback} // } // func (t *tx) Module() (path, source string) { return "@fsdpf/tx", txTypings } type Extension interface { // Name 是它在脚本里的全局名,必须是合法的 JS 标识符。 // 跟白名单(WithGlobals)同名时以白名单为准。 Name() string // Bindings 是暴露给脚本的方法集。方法名**大写开头**,跟脚本里能碰到的 // 其它东西保持一致——传进来的 Go 对象(m.GetCode()、res.GetDBTable()) // 用的都是 Go 的方法名,扩展再用小写的话,同一行代码里两种风格混着写。 Bindings() map[string]any // Module 返回配套 TypeScript 模块的 import 路径和源码,让脚本能拿到类型: // // import store from "@jscriptx/store" // // 路径要加 scope 前缀,免得跟 node_modules 里的包撞名。用什么 scope 自己定, // 框架层那套用的是 @jscriptx/,业务自己的可以用 @fsdpf/ 之类。 // 路径返回空字符串表示不提供模块,脚本只能用全局变量的写法。 // // 模块本身只是个门面:把全局对象转发出来,附上类型声明。真正的实现在 Go 侧。 Module() (path, source string) }