diff --git a/env.yml b/env.yml new file mode 100644 index 0000000..52be3b2 --- /dev/null +++ b/env.yml @@ -0,0 +1,6 @@ +test: + aaa: 111 + bbb: + - 2 + ccc: + c2: "A-8ubk1BEEeytkVuyO9F6w==" diff --git a/go.mod b/go.mod index 19b37c7..f34d93c 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/ZZMarquis/gm v1.3.2 github.com/emmansun/gmsm v0.29.3 github.com/obscuren/ecies v0.0.0-20150213224233-7c0f4a9b18d9 - github.com/ssgo/u v1.7.11 + github.com/ssgo/u v1.7.12 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/test.yml b/test.yml new file mode 100644 index 0000000..c53e7ba --- /dev/null +++ b/test.yml @@ -0,0 +1,5 @@ +aaa: 11 +bbb: + - 1 +ccc: + c1: 111 diff --git a/util.go b/util.go index 308e7c7..d235908 100644 --- a/util.go +++ b/util.go @@ -20,7 +20,9 @@ import ( "encoding/pem" "errors" "math/big" + "os" "path/filepath" + "regexp" "runtime" "strings" "text/template" @@ -44,6 +46,17 @@ var utilTS string //go:embed README.md var utilMD string +var envConfigs map[string]map[string]any +var confAes = u.NewAes([]byte("?GQ$0K0GgLdO=f+~L68PLm$uhKr4'=tV"), []byte("VFs7@sK61cj^f?HZ")) +var keysIsSet = false + +func SetSSKey(key, iv []byte) { + if !keysIsSet { + confAes = u.NewAes(key, iv) + keysIsSet = true + } +} + func init() { obj := map[string]any{ "json": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { @@ -953,15 +966,72 @@ func init() { args := gojs.MakeArgs(&argsIn, vm).Check(1) return vm.ToValue(u.Bool(args.Any(0))) }, + "searchFile": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { + args := gojs.MakeArgs(&argsIn, vm).Check(1) + filename := args.Str(0) + searchPath := args.Str(1) + findFile := "" + if searchPath != "" { + findFile = searchFile(searchPath, filename) + } else { + findFile = searchFileFromCurrent(vm, filename) + } + return vm.ToValue(findFile) + }, + "loadConfig": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { + if envConfigs == nil { + envConfigs = map[string]map[string]any{} + envFile := searchFileFromCurrent(vm, "env.yml") + if envFile == "" { + envFile = searchFileFromCurrent(vm, "env.json") + } + if envFile != "" { + u.LoadX(envFile, &envConfigs) + } + } + + args := gojs.MakeArgs(&argsIn, vm).Check(1) + confName := args.Str(0) + conf := map[string]any{} + confFile := searchFileFromCurrent(vm, confName+".yml") + if confFile == "" { + confFile = searchFileFromCurrent(vm, confName+".json") + } + if confFile != "" { + u.LoadX(confFile, &conf) + } + if envConf, ok := envConfigs[confName]; ok { + u.Convert(envConf, &conf) + } + + decTimes := 0 + confStr := encryptdMatcher.ReplaceAllStringFunc(u.Json(conf), func(str string) string { + if buf, err := base64.URLEncoding.DecodeString(str[1 : len(str)-1]); err == nil { + if buf1, err1 := confAes.DecryptBytes(buf); err1 == nil && len(buf1) > 0 { + decTimes++ + return "\"" + string(buf1) + "\"" + } + } + return str + }) + if decTimes > 0 { + u.UnJson(confStr, &conf) + } + + return vm.ToValue(conf) + }, } gojs.Register("apigo.cc/gojs/util", gojs.Module{ - Object: obj, - TsCode: utilTS, - Example: utilMD, + Object: obj, + TsCode: utilTS, + Example: utilMD, + SetSSKey: SetSSKey, }) } +var encryptdMatcher = regexp.MustCompile(`"([\w-=]+)"`) + func makeECDSAPriKey(priKey []byte) *ecdsa.PrivateKey { if len(priKey) >= 60 { return makePriKey(priKey, elliptic.P521()) @@ -1018,3 +1088,36 @@ func makeRSAPubKey(keyBytes []byte) *rsa.PublicKey { } return pubKey } + +func searchFile(searchPath, name string) string { + searched := map[string]bool{} + return _searchFile(searchPath, name, &searched) +} + +func searchFileFromCurrent(vm *goja.Runtime, name string) string { + searched := map[string]bool{} + startPath := u.String(vm.GoData["startPath"]) + filename := _searchFile(startPath, name, &searched) + if filename == "" { + currentPath, _ := os.Getwd() + filename = _searchFile(currentPath, name, &searched) + } + return filename +} + +func _searchFile(checkPath, name string, searched *map[string]bool) string { + for { + if !(*searched)[checkPath] { + (*searched)[checkPath] = true + filename := filepath.Join(checkPath, name) + if u.FileExists(filename) { + return filename + } + } + oldPath := checkPath + checkPath = filepath.Dir(oldPath) + if oldPath == checkPath { + return "" + } + } +} diff --git a/util.ts b/util.ts index 5be590a..1411f06 100644 --- a/util.ts +++ b/util.ts @@ -84,6 +84,8 @@ export default { float, bytes, bool, + searchFile, + loadConfig, } function json(data: any): string { return '' } @@ -169,3 +171,5 @@ function int(value: any): number { return 0 } function float(value: any): number { return 0 } function bytes(value: any): any { return null } function bool(value: any): boolean { return false } +function searchFile(filename: string, searchPath?: string): string { return '' } +function loadConfig(name: string): any { return null } diff --git a/util_test.go b/util_test.go index 42eb16e..bb4e84b 100644 --- a/util_test.go +++ b/util_test.go @@ -124,6 +124,24 @@ func TestRSA(t *testing.T) { fmt.Println(u.Green("ecdsa test passed")) } +func TestConfig(t *testing.T) { + r, err := gojs.Run(` + import util from 'apigo.cc/gojs/util' + let t = util.loadConfig('test') + if (t.aaa != 111) return 'failed to load config, aaa != 111' + if (t.bbb.length !== 2 || t.bbb[0] !== 1 || t.bbb[1] !== 2) return 'failed to load config, bbb != [1,2]' + if (t.ccc.c1 !== 111 || t.ccc.c2 !== "222") return 'failed to load config, ccc != [111,"222"]' + return true + `, "") + if err != nil { + t.Fatal(err) + } + if r != true { + t.Fatal(r) + } + fmt.Println(u.Green("ecdsa test passed")) +} + func testIsSame(vm *gojs.Runtime, t *testing.T, code string, checkValue any) { r, err := vm.RunCode(code) if err != nil {