package file import ( _ "embed" "encoding/base64" "encoding/json" "os" "path/filepath" "regexp" "strings" "apigo.cc/gojs" "apigo.cc/gojs/goja" "github.com/ssgo/u" "gopkg.in/yaml.v3" ) //go:embed file.ts var fileTS string //go:embed README.md var fileMD string var envConfigs map[string]map[string]any var encryptdMatcher = regexp.MustCompile(`"([\w-=]+)"`) 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{ "exists": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(1) return vm.ToValue(u.FileExists(args.Path(0))) }, "mkdir": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(1) if err := os.MkdirAll(args.Path(0), 0755); err != nil { panic(vm.NewGoError(err)) } return nil }, "read": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(1) if r, err := u.ReadFile(args.Path(0)); err == nil { return vm.ToValue(r) } else { panic(vm.NewGoError(err)) } }, "readBytes": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(1) if r, err := u.ReadFileBytes(args.Path(0)); err == nil { return vm.ToValue(r) } else { panic(vm.NewGoError(err)) } }, "write": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(2) if err := u.WriteFileBytes(args.Path(0), args.Bytes(1)); err == nil { return nil } else { panic(vm.NewGoError(err)) } }, "dir": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(1) if r, err := u.ReadDir(args.Path(0)); err == nil { list := make([]map[string]any, len(r)) for i, info := range r { list[i] = makeFileInfo(&info) } return vm.ToValue(list) } else { panic(vm.NewGoError(err)) } }, "stat": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(1) return vm.ToValue(makeFileInfo(u.GetFileInfo(args.Path(0)))) }, "find": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(1) return vm.ToValue(args.Path(0)) }, "remove": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(1) if err := os.RemoveAll(args.Path(0)); err == nil { return nil } else { panic(vm.NewGoError(err)) } }, "rename": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(2) if err := os.Rename(args.Path(0), args.Path(1)); err == nil { return nil } else { panic(vm.NewGoError(err)) } }, "copy": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(2) if err := u.CopyFile(args.Path(0), args.Path(1)); err == nil { return nil } else { panic(vm.NewGoError(err)) } }, "cache": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(1) compress := args.Bool(1) if compress { u.LoadFileToMemoryWithCompress(args.Path(0)) } else { u.LoadFileToMemory(args.Path(0)) } return nil }, "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) }, "save": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(2) filename := args.Str(0) var data []byte var err error if strings.HasSuffix(filename, ".yml") || strings.HasSuffix(filename, ".yaml") { data, err = yaml.Marshal(args.Any(1)) } else { data, err = json.Marshal(args.Any(1)) } if err == nil { if err = u.WriteFileBytes(gojs.FindPath(vm, filename), data); err != nil { panic(vm.NewGoError(err)) } return nil } else { panic(vm.NewGoError(err)) } }, "load": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(1) filename := args.Str(0) if data, err := u.ReadFileBytes(gojs.FindPath(vm, filename)); err == nil { var r any if strings.HasSuffix(filename, ".yml") || strings.HasSuffix(filename, ".yaml") { err = yaml.Unmarshal(data, &r) } else { err = json.Unmarshal(data, &r) } if err == nil { return vm.ToValue(r) } else { panic(vm.NewGoError(err)) } } else { panic(vm.NewGoError(err)) } }, } gojs.Register("apigo.cc/gojs/file", gojs.Module{ Object: obj, Desc: "file api by https://github.com/ssgo/u", TsCode: fileTS, Example: fileMD, SetSSKey: SetSSKey, }) } func makeFileInfo(info *u.FileInfo) map[string]any { return map[string]any{ "name": info.Name, "size": info.Size, "fullName": info.FullName, "isDir": info.IsDir, "modTime": info.ModTime.UnixMilli(), } } 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 "" } } }