utils.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. package utils
  2. import (
  3. "bytes"
  4. "compress/gzip"
  5. "errors"
  6. "fmt"
  7. "go/format"
  8. "html/template"
  9. "net/url"
  10. "os"
  11. "path/filepath"
  12. "strings"
  13. "time"
  14. "unicode"
  15. "unsafe"
  16. )
  17. var DSNError = errors.New("dsn string error")
  18. func FirstCharacter(name string) string {
  19. return strings.ToLower(name)[:1]
  20. }
  21. func CamelizeStr(s string, upperCase bool) string {
  22. if len(s) == 0 {
  23. return s
  24. }
  25. s = replaceInvalidChars(s)
  26. var result string
  27. words := strings.Split(s, "_")
  28. for i, word := range words {
  29. //if upper := strings.ToUpper(word); commonInitialisms[upper] {
  30. // result += upper
  31. // continue
  32. //}
  33. if i > 0 || upperCase {
  34. result += camelizeWord(word)
  35. } else {
  36. result += word
  37. }
  38. }
  39. return result
  40. }
  41. func camelizeWord(word string) string {
  42. runes := []rune(word)
  43. for i, r := range runes {
  44. if i == 0 {
  45. runes[i] = unicode.ToUpper(r)
  46. } else {
  47. runes[i] = unicode.ToLower(r)
  48. }
  49. }
  50. return string(runes)
  51. }
  52. func replaceInvalidChars(str string) string {
  53. str = strings.ReplaceAll(str, "-", "_")
  54. str = strings.ReplaceAll(str, " ", "_")
  55. return strings.ReplaceAll(str, ".", "_")
  56. }
  57. // https://github.com/golang/lint/blob/206c0f020eba0f7fbcfbc467a5eb808037df2ed6/lint.go#L731
  58. var commonInitialisms = map[string]bool{
  59. "ACL": true,
  60. "API": true,
  61. "ASCII": true,
  62. "CPU": true,
  63. "CSS": true,
  64. "DNS": true,
  65. "EOF": true,
  66. "ETA": true,
  67. "GPU": true,
  68. "GUID": true,
  69. "HTML": true,
  70. "HTTP": true,
  71. "HTTPS": true,
  72. "ID": true,
  73. "IP": true,
  74. "JSON": true,
  75. "LHS": true,
  76. "OS": true,
  77. "QPS": true,
  78. "RAM": true,
  79. "RHS": true,
  80. "RPC": true,
  81. "SLA": true,
  82. "SMTP": true,
  83. "SQL": true,
  84. "SSH": true,
  85. "TCP": true,
  86. "TLS": true,
  87. "TTL": true,
  88. "UDP": true,
  89. "UI": true,
  90. "UID": true,
  91. "UUID": true,
  92. "URI": true,
  93. "URL": true,
  94. "UTF8": true,
  95. "VM": true,
  96. "XML": true,
  97. "XMPP": true,
  98. "XSRF": true,
  99. "XSS": true,
  100. "OAuth": true,
  101. }
  102. func GetDbNameFromDSN(dsn string) (string, error) {
  103. if len(strings.Split(dsn, " ")) > 1 {
  104. return getDbNameFromDsn(dsn)
  105. }
  106. index := strings.LastIndex(dsn, "/")
  107. if index <= 0 {
  108. return getDbNameFromDsn(dsn)
  109. }
  110. str := dsn[index:]
  111. urlStr, err := url.Parse(str)
  112. if err != nil {
  113. return "", err
  114. }
  115. return strings.Trim(urlStr.Path, "/"), nil
  116. }
  117. // host=127.0.0.1 dbname=test sslmode=disable Timezone=Asia/Shanghai
  118. const dbNamePrefix = "dbname="
  119. func getDbNameFromDsn(dsn string) (string, error) {
  120. strArray := strings.Split(dsn, " ")
  121. for _, item := range strArray {
  122. if strings.HasPrefix(item, dbNamePrefix) {
  123. return strings.TrimPrefix(item, dbNamePrefix), nil
  124. }
  125. }
  126. return "", DSNError
  127. }
  128. func SaveFile(dirPath, fileName string, text []byte) error {
  129. file, err := os.Create(filepath.Join(dirPath, fileName))
  130. if err != nil {
  131. return err
  132. }
  133. defer file.Close()
  134. p, err := format.Source(text)
  135. if err != nil {
  136. return err
  137. }
  138. _, err = file.Write(p)
  139. return err
  140. }
  141. func MkdirPathIfNotExist(dirPath string) error {
  142. if _, err := os.Stat(dirPath); os.IsNotExist(err) {
  143. return os.MkdirAll(dirPath, os.ModePerm)
  144. }
  145. return nil
  146. }
  147. func CleanUpGenFiles(dir string) error {
  148. exist, err := FileExists(dir)
  149. if err != nil {
  150. return err
  151. }
  152. if exist {
  153. return os.RemoveAll(dir)
  154. }
  155. return nil
  156. }
  157. // FileExists reports whether the named file or directory exists.
  158. func FileExists(name string) (bool, error) {
  159. if _, err := os.Stat(name); err != nil {
  160. if os.IsNotExist(err) {
  161. return false, err
  162. }
  163. }
  164. return true, nil
  165. }
  166. func ZipBytes(data []byte) []byte {
  167. var out bytes.Buffer
  168. w := gzip.NewWriter(&out)
  169. defer w.Close()
  170. w.Write(data)
  171. w.Flush()
  172. return out.Bytes()
  173. }
  174. func UnzipBytes(data []byte) []byte {
  175. var in bytes.Buffer
  176. in.Write(data)
  177. r, _ := gzip.NewReader(&in)
  178. var out bytes.Buffer
  179. defer r.Close()
  180. out.ReadFrom(r)
  181. return out.Bytes()
  182. }
  183. func Str2bytes(s string) []byte {
  184. x := (*[2]uintptr)(unsafe.Pointer(&s))
  185. h := [3]uintptr{x[0], x[1], x[1]}
  186. return *(*[]byte)(unsafe.Pointer(&h))
  187. }
  188. func Bytes2str(b []byte) string {
  189. return *(*string)(unsafe.Pointer(&b))
  190. }
  191. func If(condition bool, trueVal, falseVal interface{}) interface{} {
  192. if condition {
  193. return trueVal
  194. }
  195. return falseVal
  196. }
  197. func NewResult(rType string, rName string, apigen func(templateData interface{}, params map[string]interface{}) ([]byte, error), templateData interface{}, isCompress bool) *GenerateResult {
  198. gr := GenerateResult{}
  199. gr.Type = rType
  200. gr.Name = rName
  201. genBytes, err := apigen(templateData, nil)
  202. if err != nil {
  203. fmt.Println(err.Error())
  204. return nil
  205. }
  206. //fmt.Println(string(genBytes))
  207. if isCompress {
  208. gr.Content = ZipBytes(genBytes)
  209. } else {
  210. gr.Content = genBytes
  211. }
  212. return &gr
  213. }
  214. func GenTemplate(templateText string, templateData interface{}, params map[string]interface{}) ([]byte, error) {
  215. t, err := template.New("template").Funcs(template.FuncMap{
  216. "CamelizeStr": CamelizeStr,
  217. "FirstCharacter": FirstCharacter,
  218. "Replace": func(old, new, src string) string {
  219. return strings.ReplaceAll(src, old, new)
  220. },
  221. "Add": func(a, b int) int {
  222. return a + b
  223. },
  224. "Now": func() string {
  225. return time.Now().Format(time.RFC3339)
  226. },
  227. "Xorm": func(col XmlColumn) string {
  228. str := fmt.Sprintf(`xorm:"%s %s %s %s %s %s" `,
  229. "'"+col.Name+"'",
  230. col.DbType,
  231. If(col.IsPK, "pk", ""),
  232. If(col.AutoIncrement, "autoincr", ""),
  233. If(col.IsNull, "null", "notnull"),
  234. If(col.IsUnique, "unique", If(col.IsIndex, "index", "")))
  235. return str
  236. },
  237. "XormTime": func(time string) interface{} {
  238. return If(time == "local_time", "sysmodel.LocalTime", time)
  239. },
  240. "Backquote": func() string {
  241. return "`"
  242. },
  243. // 定义函数unescaped
  244. "Unescaped": func(x string) interface{} {
  245. return template.HTML(x)
  246. },
  247. "TrimPrefix": strings.TrimPrefix,
  248. "TrimSuffix": strings.TrimSuffix,
  249. "Contains": strings.Contains,
  250. "AllParams": func(params []XmlApiParam) string {
  251. str := ""
  252. for i, v := range params {
  253. if i > 0 {
  254. str += ", "
  255. }
  256. str += v.Name
  257. }
  258. return str
  259. },
  260. "SqlAllColumns": func(cols []XmlColumn, isValues bool) string {
  261. str := ""
  262. for i, v := range cols {
  263. if i > 0 {
  264. str += ", "
  265. }
  266. if isValues {
  267. str += "?" + v.Name
  268. } else {
  269. str += "`" + v.Name + "`"
  270. }
  271. }
  272. return str
  273. },
  274. "SqlNoPKUpdate": func(cols []XmlColumn) string {
  275. str := ""
  276. for _, v := range cols {
  277. if !v.IsPK {
  278. str += "`" + v.Name + "` = ?" + v.Name
  279. str += ", "
  280. }
  281. }
  282. out := strings.TrimSuffix(str, ", ")
  283. return out
  284. },
  285. "SqlPKWhere": func(cols []XmlColumn) string {
  286. str := ""
  287. for _, v := range cols {
  288. if v.IsPK {
  289. str += "`" + v.Name + "` = ?" + v.Name
  290. str += " AND "
  291. }
  292. }
  293. out := strings.TrimSuffix(str, " AND ")
  294. return out
  295. },
  296. "Param": func(name string) interface{} {
  297. if v, ok := params[name]; ok {
  298. return v
  299. }
  300. return ""
  301. },
  302. }).Parse(templateText)
  303. if err != nil {
  304. fmt.Println(err.Error())
  305. return nil, err
  306. }
  307. var buf bytes.Buffer
  308. if err := t.Execute(&buf, templateData); err != nil {
  309. fmt.Println(err.Error())
  310. return nil, err
  311. }
  312. return buf.Bytes(), nil
  313. }