Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1fa63e7e3c | ||
|
|
c0fa98a5e1 |
12
CHANGELOG.md
12
CHANGELOG.md
@ -1,5 +1,17 @@
|
|||||||
# CHANGELOG - go/js
|
# CHANGELOG - go/js
|
||||||
|
|
||||||
|
## v1.5.7 (2026-06-28)
|
||||||
|
- **低代码 TS 文档对齐**:
|
||||||
|
- `Doc()` 生成的模块入口改为顶层全局变量声明,如 `declare const api: Api_Module;`,不再使用 `declare const go: { ... }` 包裹。
|
||||||
|
- 为运行时注入的日志对象补充 `Logger` 接口,仅暴露 `Debug`、`Info`、`Warning`、`Error` 四个 JS 侧需要的方法。
|
||||||
|
- 统一非项目类型的不透明命名风格,默认声明改为 `GoContext`、`GoHTTPRequest`、`GoHTTPResponse`、`GoURL`,标准库结构体采用 `GoTime` 这类更稳定的命名。
|
||||||
|
- **测试增强**:
|
||||||
|
- `TestDocGeneration` 新增对顶层全局模块声明、`Logger` 暴露面和 `GoTime` 命名的覆盖。
|
||||||
|
|
||||||
|
## v1.5.6 (2026-06-21)
|
||||||
|
- **可变参数桥接修复**: `wrapGoFunc` 修复对 Go 可变参数(`...any`)的桥接处理。之前将 JS 剩余参数错误打包为单一切片元素,导致 `Call` 二次嵌套;现在改为逐个追加到 `goArgs` 尾部,由 `reflect.Call` 自动构建可变切片,确保 JS 调用 `redis.Do('HSET', a, b, c)` 正确展开。
|
||||||
|
- **新增测试**: `TestBridgeVariadic` 覆盖可变参数 0/1/多参数场景。
|
||||||
|
|
||||||
## v1.5.5 (2026-06-21)
|
## v1.5.5 (2026-06-21)
|
||||||
- **JS 对齐**: 重构 JS 运行时的报错堆栈提取逻辑,采用高效的字符解析替换正则表达式,并支持 `jsmod.MakeError` 错误包装在桥接层还原出真实的 Go 运行时调用堆栈。
|
- **JS 对齐**: 重构 JS 运行时的报错堆栈提取逻辑,采用高效的字符解析替换正则表达式,并支持 `jsmod.MakeError` 错误包装在桥接层还原出真实的 Go 运行时调用堆栈。
|
||||||
- **依赖更新**: 升级依赖 `jsmod` 至 `v1.5.3`,`cast` 至 `v1.5.3`,`log` 至 `v1.5.8`。
|
- **依赖更新**: 升级依赖 `jsmod` 至 `v1.5.3`,`cast` 至 `v1.5.3`,`log` 至 `v1.5.8`。
|
||||||
|
|||||||
19
README.md
19
README.md
@ -58,6 +58,25 @@ dts := js.Doc()
|
|||||||
// Feed d.ts to LLM to provide coding context
|
// Feed d.ts to LLM to provide coding context
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The generated declarations are optimized for low-code editors:
|
||||||
|
- bridged modules are exposed as top-level globals such as `api`, `cast`, `db`, `service`
|
||||||
|
- injected logger values are typed as `Logger`
|
||||||
|
- opaque runtime handles use stable names such as `GoContext`, `GoHTTPRequest`, `GoHTTPResponse`, `GoURL`
|
||||||
|
- exposed standard-library structs use stable names such as `GoTime`
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
declare const service: Service_Module
|
||||||
|
|
||||||
|
interface Logger {
|
||||||
|
Debug(message: string, ...extra: any[]): void
|
||||||
|
Info(message: string, ...extra: any[]): void
|
||||||
|
Warning(message: string, ...extra: any[]): void
|
||||||
|
Error(message: string, ...extra: any[]): void
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Internal Bridge Details
|
## Internal Bridge Details
|
||||||
|
|
||||||
The engine uses `goja`'s Host Object mechanism. When a Go struct/pointer is returned to JS, it remains a Go object. When passed back to a Go function, the original pointer is preserved, ensuring zero data loss and state consistency.
|
The engine uses `goja`'s Host Object mechanism. When a Go struct/pointer is returned to JS, it remains a Go object. When passed back to a Go function, the original pointer is preserved, ensuring zero data loss and state consistency.
|
||||||
|
|||||||
13
TEST.md
13
TEST.md
@ -1,15 +1,15 @@
|
|||||||
# Test Report - go/js
|
# Test Report - go/js
|
||||||
|
|
||||||
## Performance (Benchmark)
|
## Performance (Benchmark)
|
||||||
Date: 2026-06-21
|
Date: 2026-06-28
|
||||||
OS: darwin
|
OS: darwin
|
||||||
Arch: amd64
|
Arch: amd64
|
||||||
CPU: Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
|
CPU: Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
|
||||||
|
|
||||||
| Benchmark | Iterations | Time/op |
|
| Benchmark | Iterations | Time/op |
|
||||||
|-----------|------------|---------|
|
|-----------|------------|---------|
|
||||||
| BenchmarkCall | 661954 | 1566 ns/op |
|
| BenchmarkCall | 766462 | 1331 ns/op |
|
||||||
| BenchmarkSync | 51656 | 50748 ns/op |
|
| BenchmarkSync | 31066 | 52789 ns/op |
|
||||||
|
|
||||||
*Note: BenchmarkCall covers the hot path of executing a JS function from the pool. BenchmarkSync covers the cost of defining new code (including VM sync).*
|
*Note: BenchmarkCall covers the hot path of executing a JS function from the pool. BenchmarkSync covers the cost of defining new code (including VM sync).*
|
||||||
|
|
||||||
@ -31,6 +31,8 @@ CPU: Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
|
|||||||
--- PASS: TestBridgeMixedInjection (0.00s)
|
--- PASS: TestBridgeMixedInjection (0.00s)
|
||||||
=== RUN TestBridgeOptionalParams
|
=== RUN TestBridgeOptionalParams
|
||||||
--- PASS: TestBridgeOptionalParams (0.00s)
|
--- PASS: TestBridgeOptionalParams (0.00s)
|
||||||
|
=== RUN TestBridgeVariadic
|
||||||
|
--- PASS: TestBridgeVariadic (0.00s)
|
||||||
=== RUN TestDocGeneration
|
=== RUN TestDocGeneration
|
||||||
--- PASS: TestDocGeneration (0.00s)
|
--- PASS: TestDocGeneration (0.00s)
|
||||||
=== RUN TestPoolVersioning
|
=== RUN TestPoolVersioning
|
||||||
@ -48,7 +50,7 @@ CPU: Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
|
|||||||
=== RUN TestDefineRedefine
|
=== RUN TestDefineRedefine
|
||||||
--- PASS: TestDefineRedefine (0.00s)
|
--- PASS: TestDefineRedefine (0.00s)
|
||||||
PASS
|
PASS
|
||||||
ok apigo.cc/go/js 0.572s
|
ok apigo.cc/go/js 0.800s
|
||||||
```
|
```
|
||||||
|
|
||||||
## Features Verified
|
## Features Verified
|
||||||
@ -61,4 +63,7 @@ ok apigo.cc/go/js 0.572s
|
|||||||
- [x] Context cancellation interruption.
|
- [x] Context cancellation interruption.
|
||||||
- [x] Graceful shutdown.
|
- [x] Graceful shutdown.
|
||||||
- [x] TypeScript definition generation.
|
- [x] TypeScript definition generation.
|
||||||
|
- [x] Top-level global module declarations for low-code hints.
|
||||||
|
- [x] Opaque type naming stability (`GoContext`, `GoTime`, `GoURL`).
|
||||||
|
- [x] Runtime-injected `Logger` type hints with JS-safe methods only.
|
||||||
- [x] JS VM call stack parsing & Go dynamic call stack restoration with `jsmod.MakeError`.
|
- [x] JS VM call stack parsing & Go dynamic call stack restoration with `jsmod.MakeError`.
|
||||||
|
|||||||
31
bridge.go
31
bridge.go
@ -52,9 +52,10 @@ func wrapGoFunc(vm *goja.Runtime, fn any, isUnsafe bool) goja.Value {
|
|||||||
|
|
||||||
// 2. Prepare Arguments
|
// 2. Prepare Arguments
|
||||||
numIn := t.NumIn()
|
numIn := t.NumIn()
|
||||||
goArgs := make([]reflect.Value, numIn)
|
goArgs := make([]reflect.Value, 0, numIn+len(call.Arguments))
|
||||||
jsArgs := call.Arguments
|
jsArgs := call.Arguments
|
||||||
jsArgIdx := 0
|
jsArgIdx := 0
|
||||||
|
isVariadic := t.IsVariadic()
|
||||||
|
|
||||||
for i := 0; i < numIn; i++ {
|
for i := 0; i < numIn; i++ {
|
||||||
argType := t.In(i)
|
argType := t.In(i)
|
||||||
@ -65,7 +66,7 @@ func wrapGoFunc(vm *goja.Runtime, fn any, isUnsafe bool) goja.Value {
|
|||||||
if ctx == nil {
|
if ctx == nil {
|
||||||
ctx = context.Background()
|
ctx = context.Background()
|
||||||
}
|
}
|
||||||
goArgs[i] = reflect.ValueOf(ctx)
|
goArgs = append(goArgs, reflect.ValueOf(ctx))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,24 +81,42 @@ func wrapGoFunc(vm *goja.Runtime, fn any, isUnsafe bool) goja.Value {
|
|||||||
if logger == nil {
|
if logger == nil {
|
||||||
logger = log.DefaultLogger
|
logger = log.DefaultLogger
|
||||||
}
|
}
|
||||||
goArgs[i] = reflect.ValueOf(logger)
|
goArgs = append(goArgs, reflect.ValueOf(logger))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 可变参数:剩余 JS 参数直接追加到 goArgs,不由 Call 再包一层
|
||||||
|
if isVariadic && i == numIn-1 {
|
||||||
|
elemType := argType.Elem()
|
||||||
|
for jsArgIdx < len(jsArgs) {
|
||||||
|
exported := jsArgs[jsArgIdx].Export()
|
||||||
|
expV := reflect.ValueOf(exported)
|
||||||
|
if !expV.IsValid() || !expV.Type().AssignableTo(elemType) {
|
||||||
|
elem := reflect.New(elemType).Elem()
|
||||||
|
cast.Convert(elem.Addr().Interface(), exported)
|
||||||
|
expV = elem
|
||||||
|
}
|
||||||
|
goArgs = append(goArgs, expV)
|
||||||
|
jsArgIdx++
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normal JS Argument with go/cast
|
// Normal JS Argument with go/cast
|
||||||
goArgs[i] = reflect.New(argType).Elem()
|
goArg := reflect.New(argType).Elem()
|
||||||
if jsArgIdx < len(jsArgs) {
|
if jsArgIdx < len(jsArgs) {
|
||||||
jsVal := jsArgs[jsArgIdx]
|
jsVal := jsArgs[jsArgIdx]
|
||||||
exported := jsVal.Export()
|
exported := jsVal.Export()
|
||||||
|
|
||||||
expV := reflect.ValueOf(exported)
|
expV := reflect.ValueOf(exported)
|
||||||
if expV.IsValid() && expV.Type().AssignableTo(argType) {
|
if expV.IsValid() && expV.Type().AssignableTo(argType) {
|
||||||
goArgs[i].Set(expV)
|
goArg.Set(expV)
|
||||||
} else {
|
} else {
|
||||||
cast.Convert(goArgs[i].Addr().Interface(), exported)
|
cast.Convert(goArg.Addr().Interface(), exported)
|
||||||
}
|
}
|
||||||
jsArgIdx++
|
jsArgIdx++
|
||||||
}
|
}
|
||||||
|
goArgs = append(goArgs, goArg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Call the Go function
|
// 3. Call the Go function
|
||||||
|
|||||||
@ -106,3 +106,42 @@ func TestBridgeOptionalParams(t *testing.T) {
|
|||||||
t.Errorf("Optional param failed (val), got %v", val.Export())
|
t.Errorf("Optional param failed (val), got %v", val.Export())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBridgeVariadic(t *testing.T) {
|
||||||
|
vm := goja.New()
|
||||||
|
|
||||||
|
variadicFn := func(cmd string, args ...any) string {
|
||||||
|
t.Logf("DEBUG variadicFn received: cmd=%q len(args)=%d args=%v argsType=%T", cmd, len(args), args, args)
|
||||||
|
for i, a := range args {
|
||||||
|
t.Logf("DEBUG args[%d] = %v (type=%T)", i, a, a)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s:%d:%v", cmd, len(args), args)
|
||||||
|
}
|
||||||
|
|
||||||
|
vm.Set("vfn", wrapGoFunc(vm, variadicFn, false))
|
||||||
|
|
||||||
|
// 无额外参数
|
||||||
|
val, _ := vm.RunString(`vfn("PING")`)
|
||||||
|
t.Logf("DEBUG vfn(PING) result: %v", val.Export())
|
||||||
|
if val.Export() != "PING:0:[]" {
|
||||||
|
t.Errorf("Variadic zero args failed, got %v", val.Export())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 一个额外参数
|
||||||
|
val, _ = vm.RunString(`vfn("GET", "key1")`)
|
||||||
|
t.Logf("DEBUG vfn(GET, key1) result: %v", val.Export())
|
||||||
|
if val.Export() != "GET:1:[key1]" {
|
||||||
|
t.Errorf("Variadic one arg failed, got %v", val.Export())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 多个额外参数
|
||||||
|
val, _ = vm.RunString(`vfn("HSET", "key1", "field1", "val1")`)
|
||||||
|
result := val.Export().(string)
|
||||||
|
t.Logf("DEBUG vfn(HSET, key1, field1, val1) result: %v", result)
|
||||||
|
if !strings.Contains(result, "HSET:3:") {
|
||||||
|
t.Errorf("Variadic multi args failed, got %v", result)
|
||||||
|
}
|
||||||
|
if !strings.Contains(result, "key1") || !strings.Contains(result, "field1") || !strings.Contains(result, "val1") {
|
||||||
|
t.Errorf("Variadic args content wrong, got %v", result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
68
doc.go
68
doc.go
@ -16,17 +16,23 @@ func Doc() string {
|
|||||||
sb.WriteString("/**\n * Go/JS Low-Code Environment Type Definitions\n")
|
sb.WriteString("/**\n * Go/JS Low-Code Environment Type Definitions\n")
|
||||||
sb.WriteString(" * Generated by js.Doc(). DO NOT EDIT.\n */\n\n")
|
sb.WriteString(" * Generated by js.Doc(). DO NOT EDIT.\n */\n\n")
|
||||||
|
|
||||||
// 1. Basic Opaque types (Manual fallback for critical non-project types)
|
// 1. Basic opaque types for critical non-project types
|
||||||
sb.WriteString("/** Opaque handle to Go context.Context */\n")
|
sb.WriteString("/** Opaque handle to Go context.Context */\n")
|
||||||
sb.WriteString("interface GoContext { _isGoContext: true; }\n")
|
sb.WriteString("interface GoContext { _isGoContext: true; }\n")
|
||||||
sb.WriteString("/** Opaque handle to Go log.Logger */\n")
|
sb.WriteString("/** Logger injected by the Go runtime */\n")
|
||||||
sb.WriteString("interface GoLogger { _isGoLogger: true; }\n")
|
sb.WriteString("interface Logger {\n")
|
||||||
|
sb.WriteString(" _isLogger: true;\n")
|
||||||
|
sb.WriteString(" Debug(message: string, ...extra: any[]): void;\n")
|
||||||
|
sb.WriteString(" Info(message: string, ...extra: any[]): void;\n")
|
||||||
|
sb.WriteString(" Warning(message: string, ...extra: any[]): void;\n")
|
||||||
|
sb.WriteString(" Error(message: string, ...extra: any[]): void;\n")
|
||||||
|
sb.WriteString("}\n")
|
||||||
sb.WriteString("/** Opaque handle to Go net/http.Request */\n")
|
sb.WriteString("/** Opaque handle to Go net/http.Request */\n")
|
||||||
sb.WriteString("interface GoHttp_Request { _isGoHttpReq: true; }\n")
|
sb.WriteString("interface GoHTTPRequest { _isGoHTTPRequest: true; }\n")
|
||||||
sb.WriteString("/** Opaque handle to Go net/http.Response */\n")
|
sb.WriteString("/** Opaque handle to Go net/http.Response */\n")
|
||||||
sb.WriteString("interface GoHttp_Response { _isGoHttpRes: true; }\n")
|
sb.WriteString("interface GoHTTPResponse { _isGoHTTPResponse: true; }\n")
|
||||||
sb.WriteString("/** Opaque handle to Go net/url.URL */\n")
|
sb.WriteString("/** Opaque handle to Go net/url.URL */\n")
|
||||||
sb.WriteString("interface GoNet_URL { _isGoNetURL: true; }\n\n")
|
sb.WriteString("interface GoURL { _isGoURL: true; }\n\n")
|
||||||
|
|
||||||
modules := jsmod.GetModules()
|
modules := jsmod.GetModules()
|
||||||
modNames := make([]string, 0, len(modules))
|
modNames := make([]string, 0, len(modules))
|
||||||
@ -106,13 +112,11 @@ func Doc() string {
|
|||||||
sb.WriteString("\n\n")
|
sb.WriteString("\n\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. Global 'go' declaration
|
// 5. Global module declarations
|
||||||
sb.WriteString("/** Global entry point for Go bridged modules */\n")
|
sb.WriteString("/** Global Go bridged modules */\n")
|
||||||
sb.WriteString("declare const go: {\n")
|
|
||||||
for _, modName := range modNames {
|
for _, modName := range modNames {
|
||||||
sb.WriteString(fmt.Sprintf(" readonly %s: %s_Module;\n", modName, strings.Title(modName)))
|
sb.WriteString(fmt.Sprintf("declare const %s: %s_Module;\n", modName, strings.Title(modName)))
|
||||||
}
|
}
|
||||||
sb.WriteString("};\n")
|
|
||||||
|
|
||||||
return sb.String()
|
return sb.String()
|
||||||
}
|
}
|
||||||
@ -232,6 +236,21 @@ func goTypeToTS(t reflect.Type, ctx *docCtx) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3. Special Mappings for remaining named types (mostly Structs/Interfaces)
|
// 3. Special Mappings for remaining named types (mostly Structs/Interfaces)
|
||||||
|
if pkgPath == "context" && rawName == "Context" {
|
||||||
|
return "GoContext"
|
||||||
|
}
|
||||||
|
if pkgPath == "apigo.cc/go/log" && rawName == "Logger" {
|
||||||
|
return "Logger"
|
||||||
|
}
|
||||||
|
if pkgPath == "net/http" && rawName == "Request" {
|
||||||
|
return "GoHTTPRequest"
|
||||||
|
}
|
||||||
|
if pkgPath == "net/http" && rawName == "Response" {
|
||||||
|
return "GoHTTPResponse"
|
||||||
|
}
|
||||||
|
if pkgPath == "net/url" && rawName == "URL" {
|
||||||
|
return "GoURL"
|
||||||
|
}
|
||||||
if pkgPath == "time" && rawName == "Time" {
|
if pkgPath == "time" && rawName == "Time" {
|
||||||
return registerInterface(t, ctx)
|
return registerInterface(t, ctx)
|
||||||
}
|
}
|
||||||
@ -242,7 +261,7 @@ func goTypeToTS(t reflect.Type, ctx *docCtx) string {
|
|||||||
|
|
||||||
if pkgPath != "" && !isProject {
|
if pkgPath != "" && !isProject {
|
||||||
base := filepath.Base(pkgPath)
|
base := filepath.Base(pkgPath)
|
||||||
opaqueName := "Go" + strings.Title(base) + "_" + rawName
|
opaqueName := strings.Title(base) + "_" + rawName
|
||||||
ctx.opaqueList[opaqueName] = true
|
ctx.opaqueList[opaqueName] = true
|
||||||
return opaqueName
|
return opaqueName
|
||||||
}
|
}
|
||||||
@ -274,9 +293,7 @@ func registerInterface(t reflect.Type, ctx *docCtx) string {
|
|||||||
parts := strings.Split(pkgPath, "/")
|
parts := strings.Split(pkgPath, "/")
|
||||||
name = fmt.Sprintf("%s_%s", strings.Title(parts[len(parts)-1]), rawName)
|
name = fmt.Sprintf("%s_%s", strings.Title(parts[len(parts)-1]), rawName)
|
||||||
} else if pkgPath != "" {
|
} else if pkgPath != "" {
|
||||||
// Standard lib types like time.Time
|
name = externalTypeName(pkgPath, rawName)
|
||||||
base := filepath.Base(pkgPath)
|
|
||||||
name = fmt.Sprintf("Go%s_%s", strings.Title(base), rawName)
|
|
||||||
} else {
|
} else {
|
||||||
name = fmt.Sprintf("%s_%s", strings.Title(ctx.currentMod), rawName)
|
name = fmt.Sprintf("%s_%s", strings.Title(ctx.currentMod), rawName)
|
||||||
}
|
}
|
||||||
@ -330,6 +347,27 @@ func registerInterface(t reflect.Type, ctx *docCtx) string {
|
|||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func externalTypeName(pkgPath, rawName string) string {
|
||||||
|
base := filepath.Base(pkgPath)
|
||||||
|
baseName := externalSegmentName(base)
|
||||||
|
typeName := externalSegmentName(rawName)
|
||||||
|
if baseName == typeName {
|
||||||
|
return "Go" + typeName
|
||||||
|
}
|
||||||
|
return "Go" + baseName + typeName
|
||||||
|
}
|
||||||
|
|
||||||
|
func externalSegmentName(name string) string {
|
||||||
|
switch strings.ToLower(name) {
|
||||||
|
case "http":
|
||||||
|
return "HTTP"
|
||||||
|
case "url":
|
||||||
|
return "URL"
|
||||||
|
default:
|
||||||
|
return strings.Title(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func isMethodUnusable(t reflect.Type) bool {
|
func isMethodUnusable(t reflect.Type) bool {
|
||||||
for i := 0; i < t.NumIn(); i++ {
|
for i := 0; i < t.NumIn(); i++ {
|
||||||
if isTypeUnusable(t.In(i)) {
|
if isTypeUnusable(t.In(i)) {
|
||||||
|
|||||||
23
doc_test.go
23
doc_test.go
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"apigo.cc/go/jsmod"
|
"apigo.cc/go/jsmod"
|
||||||
)
|
)
|
||||||
@ -13,19 +14,35 @@ func TestDocGeneration(t *testing.T) {
|
|||||||
"query": func(ctx context.Context, sql string, args []any) ([]map[string]any, error) {
|
"query": func(ctx context.Context, sql string, args []any) ([]map[string]any, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
},
|
},
|
||||||
|
"now": func() time.Time { return time.Time{} },
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"__exportInternal": func() *struct{ Name string } { return nil },
|
"__exportInternal": func() *struct{ Name string } { return nil },
|
||||||
})
|
})
|
||||||
|
|
||||||
doc := Doc()
|
doc := Doc()
|
||||||
if !strings.Contains(doc, "interface GoTime") {
|
if !strings.Contains(doc, "interface GoContext {") {
|
||||||
|
t.Error("doc should contain GoContext interface")
|
||||||
|
}
|
||||||
|
if !strings.Contains(doc, "interface Logger {") {
|
||||||
|
t.Error("doc should contain Logger interface")
|
||||||
|
}
|
||||||
|
if !strings.Contains(doc, "Info(message: string, ...extra: any[]): void;") {
|
||||||
|
t.Error("doc should contain Logger methods")
|
||||||
|
}
|
||||||
|
if strings.Contains(doc, "GetTraceId(): string;") || strings.Contains(doc, "New(traceId: string): Logger;") || strings.Contains(doc, "As<T = any>(value: T, err: any): T;") {
|
||||||
|
t.Error("doc should not contain Logger internal methods")
|
||||||
|
}
|
||||||
|
if !strings.Contains(doc, "interface GoTime {") {
|
||||||
t.Error("doc should contain GoTime interface")
|
t.Error("doc should contain GoTime interface")
|
||||||
}
|
}
|
||||||
if !strings.Contains(doc, "interface Db_Module") {
|
if !strings.Contains(doc, "interface Db_Module") {
|
||||||
t.Error("doc should contain Db_Module interface")
|
t.Error("doc should contain Db_Module interface")
|
||||||
}
|
}
|
||||||
if !strings.Contains(doc, "declare const go:") {
|
if !strings.Contains(doc, "declare const db: Db_Module;") {
|
||||||
t.Error("doc should contain global go declaration")
|
t.Error("doc should contain top-level module declaration")
|
||||||
|
}
|
||||||
|
if strings.Contains(doc, "declare const go:") {
|
||||||
|
t.Error("doc should not contain legacy go namespace declaration")
|
||||||
}
|
}
|
||||||
if strings.Contains(doc, "__exportInternal") {
|
if strings.Contains(doc, "__exportInternal") {
|
||||||
t.Error("doc should NOT contain __exportInternal")
|
t.Error("doc should NOT contain __exportInternal")
|
||||||
|
|||||||
6
go.mod
6
go.mod
@ -11,12 +11,12 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
apigo.cc/go/config v1.5.3 // indirect
|
apigo.cc/go/config v1.5.3 // indirect
|
||||||
apigo.cc/go/encoding v1.5.4 // indirect
|
apigo.cc/go/encoding v1.5.5 // indirect
|
||||||
apigo.cc/go/file v1.5.5 // indirect
|
apigo.cc/go/file v1.5.5 // indirect
|
||||||
apigo.cc/go/id v1.5.4 // indirect
|
apigo.cc/go/id v1.5.6 // indirect
|
||||||
apigo.cc/go/rand v1.5.3 // indirect
|
apigo.cc/go/rand v1.5.3 // indirect
|
||||||
apigo.cc/go/safe v1.5.2 // indirect
|
apigo.cc/go/safe v1.5.2 // indirect
|
||||||
apigo.cc/go/shell v1.5.3 // indirect
|
apigo.cc/go/shell v1.5.4 // indirect
|
||||||
github.com/dlclark/regexp2 v1.11.4 // indirect
|
github.com/dlclark/regexp2 v1.11.4 // indirect
|
||||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
||||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e // indirect
|
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e // indirect
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user