diff --git a/.gitignore b/.gitignore
index 66fd13c..8fb8747 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,6 @@
# Dependency directories (remove the comment below to include it)
# vendor/
+
+/**/dist/
+/**/node_modules/
diff --git a/glc/cmn/cmn.go b/glc/cmn/cmn.go
index b310db3..b41210d 100644
--- a/glc/cmn/cmn.go
+++ b/glc/cmn/cmn.go
@@ -145,3 +145,41 @@ func GeyStoreNameByDate(name string) string {
}
return name
}
+
+func EndwithsRune(str string, endstr string) bool {
+
+ if endstr == "" || str == endstr {
+ return true
+ }
+
+ strs := []rune(str)
+ ends := []rune(endstr)
+ lens := len(strs)
+ lene := len(ends)
+ if lens < lene {
+ return false
+ }
+
+ dif := lens - lene
+ for i := lene - 1; i >= 0; i-- {
+ if strs[dif+i] != ends[i] {
+ return false
+ }
+ }
+
+ return true
+}
+
+func SubStringRune(str string, start int, end int) string {
+ srune := []rune(str)
+ slen := len(srune)
+ if start >= slen || start >= end || start < 0 {
+ return ""
+ }
+
+ rs := ""
+ for i := start; i < slen && i < end; i++ {
+ rs += string(srune[i])
+ }
+ return rs
+}
diff --git a/glc/gweb/http_request.go b/glc/gweb/http_request.go
index f600406..e075b64 100644
--- a/glc/gweb/http_request.go
+++ b/glc/gweb/http_request.go
@@ -32,6 +32,10 @@ func NewHttpRequest(c *gin.Context) *HttpRequest {
}
}
+func (r *HttpRequest) SetHeader(key string, value string) {
+ r.ginCtx.Header(key, value)
+}
+
func (r *HttpRequest) GetHeader(name string) string {
ary := r.mapHead[strings.ToLower(name)]
if ary == nil {
@@ -59,3 +63,23 @@ func (r *HttpRequest) GetFormParameter(name string) string {
func (r *HttpRequest) Redirect(url string) {
r.ginCtx.Redirect(http.StatusMovedPermanently, url)
}
+
+func (r *HttpRequest) ResponseData(code int, contentType string, bytes []byte) {
+ r.ginCtx.Data(code, contentType, bytes)
+}
+
+func (r *HttpRequest) GetMethod() string {
+ return r.ginCtx.Request.Method
+}
+
+func (r *HttpRequest) AbortWithStatus(code int) {
+ r.ginCtx.AbortWithStatus(code)
+}
+
+func (r *HttpRequest) RequestURI() string {
+ return r.ginCtx.Request.RequestURI
+}
+
+func (r *HttpRequest) RequestUrlPath() string {
+ return r.ginCtx.Request.URL.Path
+}
diff --git a/glc/gweb/http_server.go b/glc/gweb/http_server.go
index 6c61c8a..bc9a4c6 100644
--- a/glc/gweb/http_server.go
+++ b/glc/gweb/http_server.go
@@ -3,6 +3,7 @@ package gweb
import (
"context"
"fmt"
+ "glc/cmn"
"glc/ldb/conf"
"glc/onexit"
"log"
@@ -19,6 +20,12 @@ func Run() {
ginEngine := gin.Default()
+ // ginEngine.GET("/assets/*filepath", func(c *gin.Context) {
+ // staticServer := http.FileServer(http.FS(assets.Static))
+ // c.Request.URL = &url.URL{Path: "web/dist" + c.Request.RequestURI}
+ // staticServer.ServeHTTP(c.Writer, c.Request)
+ // })
+
ginEngine.NoRoute(func(c *gin.Context) {
req := NewHttpRequest(c)
@@ -32,8 +39,21 @@ func Run() {
}
}
- // controller
+ // 静态文件
path := strings.ToLower(c.Request.URL.Path)
+ if cmn.EndwithsRune(path, ".html") {
+ path = "/**/*.html"
+ } else if cmn.EndwithsRune(path, ".css") {
+ path = "/**/*.css"
+ } else if cmn.EndwithsRune(path, ".js") {
+ path = "/**/*.js"
+ } else if cmn.EndwithsRune(path, ".png") {
+ path = "/**/*.png"
+ } else if cmn.EndwithsRune(path, ".ico") {
+ path = "/**/*.ico"
+ }
+
+ // controller
method := strings.ToUpper(c.Request.Method)
handle := getHttpController(method, path)
if handle == nil {
diff --git a/glc/ldb/conf/config.go b/glc/ldb/conf/config.go
index 8028e58..b52eb7a 100644
--- a/glc/ldb/conf/config.go
+++ b/glc/ldb/conf/config.go
@@ -28,15 +28,15 @@ func init() {
func UpdateConfigByEnv() {
// 读取环境变量初始化配置,各配置都有默认值
- storeRoot = Getenv("GLC_STORE_ROOT", "/glogcenter") // 存储根目录
- storeChanLength = GetenvInt("GLC_STORE_CHAN_LENGTH", 64) // 存储通道长度
- maxIdleTime = GetenvInt("GLC_MAX_IDLE_TIME", 180) // 最大闲置时间(秒),超过闲置时间将自动关闭,0时表示不关闭
- storeNameAutoAddDate = GetenvBool("GLC_STORE_NAME_AUTO_ADD_DATE", true) // 存储名是否自动添加日期(日志量大通常按日单位区分存储),默认true
- serverPort = GetenvInt("GLC_SERVER_PORT", 8080) // web服务端口
- contextPath = Getenv("GLC_CONTEXT_PATH", "/glc") // web服务contextPath
- enableSecurityKey = GetenvBool("GLC_ENABLE_SECURITY_KEY", false) // web服务是否开启API秘钥校验,默认false
- headerSecurityKey = Getenv("GLC_HEADER_SECURITY_KEY", "X-GLC-AUTH") // web服务API秘钥的header键名
- securityKey = Getenv("GLC_SECURITY_KEY", "glogcenter") // web服务API秘钥
+ storeRoot = Getenv("GLC_STORE_ROOT", "/glogcenter") // 存储根目录
+ storeChanLength = GetenvInt("GLC_STORE_CHAN_LENGTH", 64) // 存储通道长度
+ maxIdleTime = GetenvInt("GLC_MAX_IDLE_TIME", 180) // 最大闲置时间(秒),超过闲置时间将自动关闭,0时表示不关闭
+ storeNameAutoAddDate = GetenvBool("GLC_STORE_NAME_AUTO_ADD_DATE", false) // 存储名是否自动添加日期(日志量大通常按日单位区分存储),默认true
+ serverPort = GetenvInt("GLC_SERVER_PORT", 8080) // web服务端口
+ contextPath = Getenv("GLC_CONTEXT_PATH", "/glc") // web服务contextPath
+ enableSecurityKey = GetenvBool("GLC_ENABLE_SECURITY_KEY", false) // web服务是否开启API秘钥校验,默认false
+ headerSecurityKey = Getenv("GLC_HEADER_SECURITY_KEY", "X-GLC-AUTH") // web服务API秘钥的header键名
+ securityKey = Getenv("GLC_SECURITY_KEY", "glogcenter") // web服务API秘钥
}
// 取配置: web服务API秘钥的header键名,可通过环境变量“GLC_HEADER_SECURITY_KEY”设定,默认值“X-GLC-AUTH”
diff --git a/glc/ldb/engine.go b/glc/ldb/engine.go
index 288254a..55935d7 100644
--- a/glc/ldb/engine.go
+++ b/glc/ldb/engine.go
@@ -34,8 +34,8 @@ func NewDefaultEngine() *Engine {
}
// 添加日志
-func (e *Engine) AddTextLog(logText string) {
- e.logStorage.AddTextLog(logText)
+func (e *Engine) AddTextLog(date string, logText string, system string) {
+ e.logStorage.AddTextLog(date, logText, system)
}
func (e *Engine) Search(searchKey string, pageSize int, currentDocId uint64, forward bool) *search.SearchResult {
diff --git a/glc/ldb/engine_test.go b/glc/ldb/engine_test.go
index 7d66bcb..89bb05e 100644
--- a/glc/ldb/engine_test.go
+++ b/glc/ldb/engine_test.go
@@ -3,16 +3,15 @@ package ldb
import (
"log"
"testing"
- "time"
)
func Test_all(t *testing.T) {
engine := NewDefaultEngine()
- for i := 1; i <= 10000; i++ {
- engine.AddTextLog(` java.sql.SQLException: ddduse them aalav`)
- }
- time.Sleep(time.Duration(5) * time.Second)
+ // for i := 1; i <= 10000; i++ {
+ // engine.AddTextLog(` java.sql.SQLException: ddduse them aalav`)
+ // }
+ // time.Sleep(time.Duration(5) * time.Second)
// for i := 1; i <= 10000; i++ {
// engine.AddTextLog(` java.sql.SQLException: them aalav`)
@@ -24,7 +23,7 @@ func Test_all(t *testing.T) {
// }
// time.Sleep(time.Duration(5) * time.Second)
- rs := engine.Search(` them java `, 20, 0, true)
+ rs := engine.Search(` them java ddduse `, 5, 0, true)
log.Println("共查到", rs.Total, "件")
for _, v := range rs.Data {
log.Println(v.Id, v.Text)
diff --git a/glc/ldb/storage/logdata_storage.go b/glc/ldb/storage/logdata_storage.go
index 21298d5..6117db6 100644
--- a/glc/ldb/storage/logdata_storage.go
+++ b/glc/ldb/storage/logdata_storage.go
@@ -173,7 +173,7 @@ func createInvertedIndex(s *LogDataStorage) int {
idx := NewWordIndexStorage(s.StoreName(), word)
idx.Add(cmn.StringToUint64(m.Id, 36, 0)) // 日志ID加入索引
}
- log.Println("创建日志索引:", m.Id)
+ log.Println("创建日志索引:", cmn.StringToUint64(m.Id, 36, 0))
// 保存索引信息
mnt.AddKeyWords(kws) // 关键词信息
diff --git a/glc/ldb/storage/logdata_storage_handle.go b/glc/ldb/storage/logdata_storage_handle.go
index 0e405e6..5022276 100644
--- a/glc/ldb/storage/logdata_storage_handle.go
+++ b/glc/ldb/storage/logdata_storage_handle.go
@@ -41,7 +41,7 @@ func NewLogDataStorageHandle(storeName string) *LogDataStorageHandle {
}
// 添加日志(参数是普通文本日志)
-func (s *LogDataStorageHandle) AddTextLog(logText string) {
+func (s *LogDataStorageHandle) AddTextLog(date string, logText string, system string) {
txt := strings.TrimSpace(logText)
if txt == "" {
return
@@ -53,6 +53,8 @@ func (s *LogDataStorageHandle) AddTextLog(logText string) {
if len(ary) > 1 {
d.Detail = txt
}
+ d.Date = date
+ d.System = system
if s.storage.IsClose() {
s.storage = NewLogDataStorage(s.storage.storeName, "data")
diff --git a/glc/ldb/tokenizer/tokenizer.go b/glc/ldb/tokenizer/tokenizer.go
index cca8de2..6286140 100644
--- a/glc/ldb/tokenizer/tokenizer.go
+++ b/glc/ldb/tokenizer/tokenizer.go
@@ -146,5 +146,5 @@ func GetSearchKey(searchKey string) string {
// TODO
log.Println("搜索关键词", kws, "优化后搜索", rs)
- return rs[0]
+ return strings.Join(rs, " ")
}
diff --git a/glc/main.go b/glc/main.go
index 4afc70b..91d7d9f 100644
--- a/glc/main.go
+++ b/glc/main.go
@@ -1,10 +1,7 @@
package main
-import (
- "glc/gweb/http"
- "glc/web/router"
-)
+import "glc/onstart"
func main() {
- http.StartHttpServer(router.Register)
+ onstart.Run()
}
diff --git a/glc/onstart/onstart.go b/glc/onstart/onstart.go
new file mode 100644
index 0000000..0bdd503
--- /dev/null
+++ b/glc/onstart/onstart.go
@@ -0,0 +1,40 @@
+package onstart
+
+import (
+ "glc/gweb"
+ "glc/gweb/http"
+ "glc/gweb/method"
+ "glc/ldb/conf"
+ "glc/www/controller"
+ "glc/www/filter"
+ "glc/www/html"
+)
+
+func Run() {
+
+ http.StartHttpServer(func() {
+
+ contextPath := conf.GetContextPath() // ContextPath
+
+ // 过滤器
+ gweb.RegisterFilter(filter.ApiKeyFilter)
+ gweb.RegisterFilter(filter.CrossFilter)
+
+ // 控制器(跳转)
+ gweb.RegisterController(method.GET, "/", html.RedirectToHomeController)
+ gweb.RegisterController(method.GET, contextPath, html.RedirectToHomeController)
+
+ // Html静态文件
+ gweb.RegisterController(method.GET, contextPath+"/", html.HomeIndexHtmlController)
+ gweb.RegisterController(method.GET, "/**/*.html", html.StaticFileController)
+ gweb.RegisterController(method.GET, "/**/*.css", html.StaticFileController)
+ gweb.RegisterController(method.GET, "/**/*.js", html.StaticFileController)
+ gweb.RegisterController(method.GET, "/**/*.ico", html.StaticFileController)
+ gweb.RegisterController(method.GET, "/**/*.png", html.StaticFileController)
+
+ // 控制器
+ gweb.RegisterController(method.POST, contextPath+"/search", controller.LogSearchController)
+ gweb.RegisterController(method.POST, contextPath+"/add", controller.LogAddController)
+
+ })
+}
diff --git a/glc/web/filter/filter.go b/glc/web/filter/filter.go
deleted file mode 100644
index 6e2c0cf..0000000
--- a/glc/web/filter/filter.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package filter
-
-import (
- "glc/gweb"
- "glc/ldb/conf"
-)
-
-// 校验HEADER的API秘钥
-func ApiKeyFilter(req *gweb.HttpRequest) *gweb.HttpResult {
-
- // 开启API秘钥校验时才检查
- if !conf.IsEnableSecurityKey() {
- return nil
- }
-
- auth := req.GetHeader(conf.GetHeaderSecurityKey())
- if auth != conf.GetSecurityKey() {
- return gweb.Error(403, "未经授权的访问,拒绝服务")
- }
- return nil // 返回nil表示正常过滤成功
-}
diff --git a/glc/web/router/register.go b/glc/web/router/register.go
deleted file mode 100644
index 598cc59..0000000
--- a/glc/web/router/register.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package router
-
-import (
- "glc/gweb"
- "glc/gweb/method"
- "glc/ldb/conf"
- "glc/web/controller"
- "glc/web/filter"
-)
-
-func Register() {
-
- // ContextPath
- contextPath := conf.GetContextPath()
-
- // 过滤器
- gweb.RegisterFilter(filter.ApiKeyFilter)
-
- // 控制器器(跳转)
- gweb.RegisterController(method.GET, "/", controller.RedirectToSearchController)
- gweb.RegisterController(method.GET, contextPath, controller.RedirectToSearchController)
- gweb.RegisterController(method.GET, contextPath+"/", controller.RedirectToSearchController)
-
- // 控制器
- gweb.RegisterController(method.POST, contextPath+"/search", controller.LogSearchController)
- gweb.RegisterController(method.POST, contextPath+"/add", controller.LogAddController)
-
-}
diff --git a/glc/www/controller/admin_controller.go b/glc/www/controller/admin_controller.go
new file mode 100644
index 0000000..9edf6c6
--- /dev/null
+++ b/glc/www/controller/admin_controller.go
@@ -0,0 +1,12 @@
+package controller
+
+import (
+ "glc/gweb"
+ "glc/ldb/conf"
+)
+
+// 前端检索页面
+func AdminController(req *gweb.HttpRequest) *gweb.HttpResult {
+ defer req.Redirect(conf.GetContextPath() + "/search")
+ return nil
+}
diff --git a/glc/web/controller/log_add_controller.go b/glc/www/controller/log_add_controller.go
similarity index 71%
rename from glc/web/controller/log_add_controller.go
rename to glc/www/controller/log_add_controller.go
index 3d895b0..1a151e7 100644
--- a/glc/web/controller/log_add_controller.go
+++ b/glc/www/controller/log_add_controller.go
@@ -9,8 +9,10 @@ import (
func LogAddController(req *gweb.HttpRequest) *gweb.HttpResult {
storeNmae := req.GetFormParameter("name")
text := req.GetFormParameter("text")
+ date := req.GetFormParameter("date")
+ system := req.GetFormParameter("system")
engine := ldb.NewEngine(storeNmae)
- engine.AddTextLog(text)
+ engine.AddTextLog(date, text, system)
return gweb.Ok()
}
diff --git a/glc/web/controller/log_search_controller.go b/glc/www/controller/log_search_controller.go
similarity index 64%
rename from glc/web/controller/log_search_controller.go
rename to glc/www/controller/log_search_controller.go
index 4f0b68c..7bee3e2 100644
--- a/glc/web/controller/log_search_controller.go
+++ b/glc/www/controller/log_search_controller.go
@@ -4,25 +4,18 @@ import (
"glc/cmn"
"glc/gweb"
"glc/ldb"
- "glc/ldb/conf"
- "glc/ldb/tokenizer"
)
// 日志检索(表单提交方式)
func LogSearchController(req *gweb.HttpRequest) *gweb.HttpResult {
storeNmae := req.GetFormParameter("name")
- searchKey := tokenizer.GetSearchKey(req.GetFormParameter("searchKey"))
+ //searchKey := tokenizer.GetSearchKey(req.GetFormParameter("searchKey"))
+ searchKey := req.GetFormParameter("searchKey")
pageSize := cmn.StringToInt(req.GetFormParameter("pageSize"), 20)
currentId := cmn.StringToUint64(req.GetFormParameter("currentId"), 36, 0)
forward := cmn.StringToBool(req.GetFormParameter("forward"), true)
eng := ldb.NewEngine(storeNmae)
rs := eng.Search(searchKey, pageSize, currentId, forward)
- return gweb.Result(rs)
-}
-
-// 重定向
-func RedirectToSearchController(req *gweb.HttpRequest) *gweb.HttpResult {
- defer req.Redirect(conf.GetContextPath() + "/search")
- return nil
+ return gweb.Result(rs.Data)
}
diff --git a/glc/www/filter/filter.go b/glc/www/filter/filter.go
new file mode 100644
index 0000000..3407d7d
--- /dev/null
+++ b/glc/www/filter/filter.go
@@ -0,0 +1,39 @@
+package filter
+
+import (
+ "glc/gweb"
+ "glc/ldb/conf"
+ "net/http"
+)
+
+// 校验HEADER的API秘钥
+func ApiKeyFilter(req *gweb.HttpRequest) *gweb.HttpResult {
+
+ //log.Println("================================", req.RequestURI())
+ // 开启API秘钥校验时才检查
+ if !conf.IsEnableSecurityKey() {
+ return nil
+ }
+
+ auth := req.GetHeader(conf.GetHeaderSecurityKey())
+ if auth != conf.GetSecurityKey() {
+ return gweb.Error(403, "未经授权的访问,拒绝服务")
+ }
+ return nil // 返回nil表示正常过滤成功
+}
+
+// 校验HEADER的API秘钥
+func CrossFilter(req *gweb.HttpRequest) *gweb.HttpResult {
+
+ req.SetHeader("Access-Control-Allow-Origin", "*")
+ req.SetHeader("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token")
+ req.SetHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
+ req.SetHeader("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
+ req.SetHeader("Access-Control-Allow-Credentials", "true")
+
+ //放行所有OPTIONS方法
+ if req.GetMethod() == "OPTIONS" {
+ req.AbortWithStatus(http.StatusNoContent)
+ }
+ return nil
+}
diff --git a/glc/www/html/static_file_handle.go b/glc/www/html/static_file_handle.go
new file mode 100644
index 0000000..0a532fe
--- /dev/null
+++ b/glc/www/html/static_file_handle.go
@@ -0,0 +1,66 @@
+package html
+
+import (
+ "glc/cmn"
+ "glc/gweb"
+ "glc/ldb/conf"
+ "glc/www"
+ "log"
+ "os"
+)
+
+// [/]重定向到[/glc/]
+func RedirectToHomeController(req *gweb.HttpRequest) *gweb.HttpResult {
+ defer req.Redirect(conf.GetContextPath() + "/")
+ return nil
+}
+
+// 响应请求[/glc/],读取index.html返回
+func HomeIndexHtmlController(req *gweb.HttpRequest) *gweb.HttpResult {
+ file, err := www.Static.ReadFile("web/dist/index.html")
+ if err != nil && os.IsNotExist(err) {
+ req.ResponseData(404, "text/html", cmn.StringToBytes("not found"))
+ } else {
+ req.ResponseData(200, "text/html", file)
+ }
+ return nil
+}
+
+// 响应 *.html/*.css/*.js/*.png 等静态文件请求
+func StaticFileController(req *gweb.HttpRequest) *gweb.HttpResult {
+
+ urlPath := req.RequestUrlPath()
+ contentType := getContentType(urlPath)
+ file, err := www.Static.ReadFile(getStaticFilePath(urlPath))
+ if err != nil && os.IsNotExist(err) {
+ req.ResponseData(404, contentType, cmn.StringToBytes("not found"))
+ } else {
+ req.ResponseData(200, contentType, file)
+ }
+ return nil
+}
+
+// urlPath如[/glc/assets/index.f0b375ee.js]
+func getStaticFilePath(urlPath string) string {
+ path := cmn.SubStringRune(urlPath, len(conf.GetContextPath()), len(urlPath))
+ return "web/dist" + path
+}
+
+func getContentType(urlPath string) string {
+
+ if cmn.EndwithsRune(urlPath, ".html") {
+ return "text/html"
+ } else if cmn.EndwithsRune(urlPath, ".css") {
+ return "text/css"
+ } else if cmn.EndwithsRune(urlPath, ".js") {
+ return "application/x-javascript"
+ } else if cmn.EndwithsRune(urlPath, ".png") {
+ return "image/png"
+ } else if cmn.EndwithsRune(urlPath, ".ico") {
+ return "image/x-icon"
+ } else {
+ log.Println("未识别出ContentType,按text/html处理", urlPath)
+ return "text/html"
+ }
+
+}
diff --git a/glc/www/web/index.html b/glc/www/web/index.html
new file mode 100644
index 0000000..7849610
--- /dev/null
+++ b/glc/www/web/index.html
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+ 日志中心
+
+
+
+
+
+
+
+
diff --git a/glc/www/web/package.json b/glc/www/web/package.json
new file mode 100644
index 0000000..53d966d
--- /dev/null
+++ b/glc/www/web/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "web",
+ "private": true,
+ "version": "0.0.0",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@element-plus/icons-vue": "^1.1.4",
+ "@vueuse/core": "^8.4.2",
+ "axios": "^0.27.2",
+ "element-plus": "^2.1.11",
+ "sass": "^1.51.0",
+ "vue": "^3.2.25",
+ "vue-json-viewer": "3",
+ "vue-router": "^4.0.15"
+ },
+ "devDependencies": {
+ "@vitejs/plugin-vue": "^2.2.0",
+ "vite": "^2.8.0"
+ }
+}
diff --git a/glc/www/web/public/favicon.ico b/glc/www/web/public/favicon.ico
new file mode 100644
index 0000000..743ddf4
Binary files /dev/null and b/glc/www/web/public/favicon.ico differ
diff --git a/glc/www/web/public/glc.png b/glc/www/web/public/glc.png
new file mode 100644
index 0000000..bf59255
Binary files /dev/null and b/glc/www/web/public/glc.png differ
diff --git a/glc/www/web/public/title.png b/glc/www/web/public/title.png
new file mode 100644
index 0000000..5b681fb
Binary files /dev/null and b/glc/www/web/public/title.png differ
diff --git a/glc/www/web/src/App.vue b/glc/www/web/src/App.vue
new file mode 100644
index 0000000..12e5852
--- /dev/null
+++ b/glc/www/web/src/App.vue
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/glc/www/web/src/api.js b/glc/www/web/src/api.js
new file mode 100644
index 0000000..42f0941
--- /dev/null
+++ b/glc/www/web/src/api.js
@@ -0,0 +1,50 @@
+import axios from 'axios'
+
+const BASE_URL = process.env.NODE_ENV === 'production' ? location.origin : 'http://127.0.0.1:8080'
+
+function request(url, method = 'get', data) {
+ return axios({
+ baseURL: BASE_URL,
+ url: url,
+ method: method,
+ data: data,
+ })
+}
+
+function post(url, formData) {
+ return axios.post(url,formData,{
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ // 'X-GLC-AUTH': 'glogcenter',
+ }
+ })
+}
+
+export default {
+ search(params={}) {
+
+ let formData = new FormData();
+ for(let k in params){
+ formData.append(k, params[k]);
+ }
+ return post(`${BASE_URL}/glc/search`, formData)
+ },
+ // remove(db, id) {
+ // return request(`/remove?database=${db}`, 'post', { id })
+ // },
+ // gc() {
+ // return request('/gc')
+ // },
+ // getStatus() {
+ // return request('/status')
+ // },
+ // addIndex(db, index) {
+ // return request(`/index?database=${db}`, 'post', index )
+ // },
+ // drop(db){
+ // return request(`/db/drop?database=${db}`)
+ // },
+ // create(db){
+ // return request(`/db/create?database=${db}`)
+ // }
+}
diff --git a/glc/www/web/src/components/Icon.vue b/glc/www/web/src/components/Icon.vue
new file mode 100644
index 0000000..0922db9
--- /dev/null
+++ b/glc/www/web/src/components/Icon.vue
@@ -0,0 +1,24 @@
+
+
+
diff --git a/glc/www/web/src/components/Menu.vue b/glc/www/web/src/components/Menu.vue
new file mode 100644
index 0000000..0f163e8
--- /dev/null
+++ b/glc/www/web/src/components/Menu.vue
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
diff --git a/glc/www/web/src/main.js b/glc/www/web/src/main.js
new file mode 100644
index 0000000..30b4735
--- /dev/null
+++ b/glc/www/web/src/main.js
@@ -0,0 +1,20 @@
+import { createApp } from 'vue'
+import App from './App.vue'
+import 'element-plus/dist/index.css'
+import ElementPlus from 'element-plus'
+import zhCn from 'element-plus/es/locale/lang/zh-cn'
+
+import * as ElementPlusIconsVue from '@element-plus/icons-vue'
+
+import router from './router'
+let app = createApp(App)
+app.use(ElementPlus,{
+ locale: zhCn,
+})
+app.use(router)
+for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
+ app.component(key, component)
+ app.use(component)
+}
+
+app.mount('#app')
diff --git a/glc/www/web/src/menus.js b/glc/www/web/src/menus.js
new file mode 100644
index 0000000..76c173b
--- /dev/null
+++ b/glc/www/web/src/menus.js
@@ -0,0 +1,13 @@
+import { Coin, DataLine, Document, Search } from '@element-plus/icons-vue'
+
+const menus = [
+ {
+ path: '/',
+ name: 'dashboard',
+ icon: Search,
+ label: '日志检索',
+ color: '#0081dd',
+ component: () => import('./views/dashboard.vue'),
+ },
+]
+export default menus
diff --git a/glc/www/web/src/router.js b/glc/www/web/src/router.js
new file mode 100644
index 0000000..0ccabf8
--- /dev/null
+++ b/glc/www/web/src/router.js
@@ -0,0 +1,10 @@
+import { createRouter, createWebHashHistory } from 'vue-router'
+
+import menus from './menus'
+
+const router = createRouter({
+ history: createWebHashHistory(),
+ routes: menus
+})
+
+export default router
diff --git a/glc/www/web/src/views/dashboard.vue b/glc/www/web/src/views/dashboard.vue
new file mode 100644
index 0000000..a6931bb
--- /dev/null
+++ b/glc/www/web/src/views/dashboard.vue
@@ -0,0 +1,177 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/glc/www/web/vite.config.js b/glc/www/web/vite.config.js
new file mode 100644
index 0000000..0486b35
--- /dev/null
+++ b/glc/www/web/vite.config.js
@@ -0,0 +1,8 @@
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [vue()],
+ base: ''
+})
diff --git a/glc/www/web/yarn.lock b/glc/www/web/yarn.lock
new file mode 100644
index 0000000..5be4fb4
--- /dev/null
+++ b/glc/www/web/yarn.lock
@@ -0,0 +1,691 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@babel/parser@^7.16.4":
+ version "7.17.10"
+ resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.17.10.tgz"
+ integrity sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==
+
+"@ctrl/tinycolor@^3.4.1":
+ version "3.4.1"
+ resolved "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.4.1.tgz"
+ integrity sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw==
+
+"@element-plus/icons-vue@^1.1.4":
+ version "1.1.4"
+ resolved "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-1.1.4.tgz"
+ integrity sha512-Iz/nHqdp1sFPmdzRwHkEQQA3lKvoObk8azgABZ81QUOpW9s/lUyQVUSh0tNtEPZXQlKwlSh7SPgoVxzrE0uuVQ==
+
+"@floating-ui/core@^0.6.2":
+ version "0.6.2"
+ resolved "https://registry.npmmirror.com/@floating-ui/core/-/core-0.6.2.tgz"
+ integrity sha512-jktYRmZwmau63adUG3GKOAVCofBXkk55S/zQ94XOorAHhwqFIOFAy1rSp2N0Wp6/tGbe9V3u/ExlGZypyY17rg==
+
+"@floating-ui/dom@^0.4.5":
+ version "0.4.5"
+ resolved "https://registry.npmmirror.com/@floating-ui/dom/-/dom-0.4.5.tgz"
+ integrity sha512-b+prvQgJt8pieaKYMSJBXHxX/DYwdLsAWxKYqnO5dO2V4oo/TYBZJAUQCVNjTWWsrs6o4VDrNcP9+E70HAhJdw==
+ dependencies:
+ "@floating-ui/core" "^0.6.2"
+
+"@popperjs/core@npm:@sxzz/popperjs-es@^2.11.6":
+ version "2.11.7"
+ resolved "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz"
+ integrity sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==
+
+"@types/lodash-es@^4.17.6":
+ version "4.17.6"
+ resolved "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.6.tgz"
+ integrity sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==
+ dependencies:
+ "@types/lodash" "*"
+
+"@types/lodash@*", "@types/lodash@^4.14.182":
+ version "4.14.182"
+ resolved "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.182.tgz"
+ integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==
+
+"@vitejs/plugin-vue@^2.2.0":
+ version "2.3.2"
+ resolved "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.3.2.tgz"
+ integrity sha512-umyypfSHS4kQLdYAnJHhaASq7FRzNCdvcRoQ3uYGNk1/M4a+hXUd7ysN7BLhCrWH6uBokyCkFeUAaFDzSaaSrQ==
+
+"@vue/compiler-core@3.2.33":
+ version "3.2.33"
+ resolved "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.33.tgz"
+ integrity sha512-AAmr52ji3Zhk7IKIuigX2osWWsb2nQE5xsdFYjdnmtQ4gymmqXbjLvkSE174+fF3A3kstYrTgGkqgOEbsdLDpw==
+ dependencies:
+ "@babel/parser" "^7.16.4"
+ "@vue/shared" "3.2.33"
+ estree-walker "^2.0.2"
+ source-map "^0.6.1"
+
+"@vue/compiler-dom@3.2.33":
+ version "3.2.33"
+ resolved "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.33.tgz"
+ integrity sha512-GhiG1C8X98Xz9QUX/RlA6/kgPBWJkjq0Rq6//5XTAGSYrTMBgcLpP9+CnlUg1TFxnnCVughAG+KZl28XJqw8uQ==
+ dependencies:
+ "@vue/compiler-core" "3.2.33"
+ "@vue/shared" "3.2.33"
+
+"@vue/compiler-sfc@3.2.33":
+ version "3.2.33"
+ resolved "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.33.tgz"
+ integrity sha512-H8D0WqagCr295pQjUYyO8P3IejM3vEzeCO1apzByAEaAR/WimhMYczHfZVvlCE/9yBaEu/eu9RdiWr0kF8b71Q==
+ dependencies:
+ "@babel/parser" "^7.16.4"
+ "@vue/compiler-core" "3.2.33"
+ "@vue/compiler-dom" "3.2.33"
+ "@vue/compiler-ssr" "3.2.33"
+ "@vue/reactivity-transform" "3.2.33"
+ "@vue/shared" "3.2.33"
+ estree-walker "^2.0.2"
+ magic-string "^0.25.7"
+ postcss "^8.1.10"
+ source-map "^0.6.1"
+
+"@vue/compiler-ssr@3.2.33":
+ version "3.2.33"
+ resolved "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.33.tgz"
+ integrity sha512-XQh1Xdk3VquDpXsnoCd7JnMoWec9CfAzQDQsaMcSU79OrrO2PNR0ErlIjm/mGq3GmBfkQjzZACV+7GhfRB8xMQ==
+ dependencies:
+ "@vue/compiler-dom" "3.2.33"
+ "@vue/shared" "3.2.33"
+
+"@vue/devtools-api@^6.0.0":
+ version "6.1.4"
+ resolved "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.1.4.tgz"
+ integrity sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ==
+
+"@vue/reactivity-transform@3.2.33":
+ version "3.2.33"
+ resolved "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.33.tgz"
+ integrity sha512-4UL5KOIvSQb254aqenW4q34qMXbfZcmEsV/yVidLUgvwYQQ/D21bGX3DlgPUGI3c4C+iOnNmDCkIxkILoX/Pyw==
+ dependencies:
+ "@babel/parser" "^7.16.4"
+ "@vue/compiler-core" "3.2.33"
+ "@vue/shared" "3.2.33"
+ estree-walker "^2.0.2"
+ magic-string "^0.25.7"
+
+"@vue/reactivity@3.2.33":
+ version "3.2.33"
+ resolved "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.33.tgz"
+ integrity sha512-62Sq0mp9/0bLmDuxuLD5CIaMG2susFAGARLuZ/5jkU1FCf9EDbwUuF+BO8Ub3Rbodx0ziIecM/NsmyjardBxfQ==
+ dependencies:
+ "@vue/shared" "3.2.33"
+
+"@vue/runtime-core@3.2.33":
+ version "3.2.33"
+ resolved "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.33.tgz"
+ integrity sha512-N2D2vfaXsBPhzCV3JsXQa2NECjxP3eXgZlFqKh4tgakp3iX6LCGv76DLlc+IfFZq+TW10Y8QUfeihXOupJ1dGw==
+ dependencies:
+ "@vue/reactivity" "3.2.33"
+ "@vue/shared" "3.2.33"
+
+"@vue/runtime-dom@3.2.33":
+ version "3.2.33"
+ resolved "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.33.tgz"
+ integrity sha512-LSrJ6W7CZTSUygX5s8aFkraDWlO6K4geOwA3quFF2O+hC3QuAMZt/0Xb7JKE3C4JD4pFwCSO7oCrZmZ0BIJUnw==
+ dependencies:
+ "@vue/runtime-core" "3.2.33"
+ "@vue/shared" "3.2.33"
+ csstype "^2.6.8"
+
+"@vue/server-renderer@3.2.33":
+ version "3.2.33"
+ resolved "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.33.tgz"
+ integrity sha512-4jpJHRD4ORv8PlbYi+/MfP8ec1okz6rybe36MdpkDrGIdEItHEUyaHSKvz+ptNEyQpALmmVfRteHkU9F8vxOew==
+ dependencies:
+ "@vue/compiler-ssr" "3.2.33"
+ "@vue/shared" "3.2.33"
+
+"@vue/shared@3.2.33":
+ version "3.2.33"
+ resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.2.33.tgz"
+ integrity sha512-UBc1Pg1T3yZ97vsA2ueER0F6GbJebLHYlEi4ou1H5YL4KWvMOOWwpYo9/QpWq93wxKG6Wo13IY74Hcn/f7c7Bg==
+
+"@vueuse/core@^8.2.6", "@vueuse/core@^8.4.2":
+ version "8.4.2"
+ resolved "https://registry.npmmirror.com/@vueuse/core/-/core-8.4.2.tgz"
+ integrity sha512-dUVU96lii1ZdWoNJXauQNt+4QrHz1DKbuW+y6pDR2N10q7rGZJMDU7pQeMcC2XeosX7kMODfaBuqsF03NozzLg==
+ dependencies:
+ "@vueuse/metadata" "8.4.2"
+ "@vueuse/shared" "8.4.2"
+ vue-demi "*"
+
+"@vueuse/metadata@8.4.2":
+ version "8.4.2"
+ resolved "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-8.4.2.tgz"
+ integrity sha512-2BIj++7P0/I5dfMsEe8q7Kw0HqVAjVcyNOd9+G22/ILUC9TVLTeYOuJ1kwa1Gpr+0LWKHc6GqHiLWNL33+exoQ==
+
+"@vueuse/shared@8.4.2":
+ version "8.4.2"
+ resolved "https://registry.npmmirror.com/@vueuse/shared/-/shared-8.4.2.tgz"
+ integrity sha512-hILXMEjL8YQhj1LHN/HZ49UThyfk8irTjhele2nW+L3N55ElFUBGB/f4w0rg8EW+/suhqv7kJJPTZzvHCqxlIw==
+ dependencies:
+ vue-demi "*"
+
+anymatch@~3.1.2:
+ version "3.1.2"
+ resolved "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.2.tgz"
+ integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
+ dependencies:
+ normalize-path "^3.0.0"
+ picomatch "^2.0.4"
+
+async-validator@^4.0.7:
+ version "4.1.1"
+ resolved "https://registry.npmmirror.com/async-validator/-/async-validator-4.1.1.tgz"
+ integrity sha512-p4DO/JXwjs8klJyJL8Q2oM4ks5fUTze/h5k10oPPKMiLe1fj3G1QMzPHNmN1Py4ycOk7WlO2DcGXv1qiESJCZA==
+
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz"
+ integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
+
+axios@^0.27.2:
+ version "0.27.2"
+ resolved "https://registry.npmmirror.com/axios/-/axios-0.27.2.tgz"
+ integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==
+ dependencies:
+ follow-redirects "^1.14.9"
+ form-data "^4.0.0"
+
+binary-extensions@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz"
+ integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
+
+braces@~3.0.2:
+ version "3.0.2"
+ resolved "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz"
+ integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
+ dependencies:
+ fill-range "^7.0.1"
+
+"chokidar@>=3.0.0 <4.0.0":
+ version "3.5.3"
+ resolved "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz"
+ integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
+ dependencies:
+ anymatch "~3.1.2"
+ braces "~3.0.2"
+ glob-parent "~5.1.2"
+ is-binary-path "~2.1.0"
+ is-glob "~4.0.1"
+ normalize-path "~3.0.0"
+ readdirp "~3.6.0"
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+clipboard@^2.0.4:
+ version "2.0.11"
+ resolved "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz"
+ integrity sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==
+ dependencies:
+ good-listener "^1.2.2"
+ select "^1.1.2"
+ tiny-emitter "^2.0.0"
+
+combined-stream@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz"
+ integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+ dependencies:
+ delayed-stream "~1.0.0"
+
+csstype@^2.6.8:
+ version "2.6.20"
+ resolved "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz"
+ integrity sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==
+
+dayjs@^1.11.1:
+ version "1.11.2"
+ resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.2.tgz"
+ integrity sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==
+
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz"
+ integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
+
+delegate@^3.1.2:
+ version "3.2.0"
+ resolved "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz"
+ integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==
+
+element-plus@^2.1.11:
+ version "2.1.11"
+ resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.1.11.tgz"
+ integrity sha512-s4X0I8s787tv+9UdekBC1g7v42Fj4bucPAmu03EjbgrGrV7BJvkoBGuK52lNfu4yC76bl6Uyjesd5Fu8CMakSw==
+ dependencies:
+ "@ctrl/tinycolor" "^3.4.1"
+ "@element-plus/icons-vue" "^1.1.4"
+ "@floating-ui/dom" "^0.4.5"
+ "@popperjs/core" "npm:@sxzz/popperjs-es@^2.11.6"
+ "@types/lodash" "^4.14.182"
+ "@types/lodash-es" "^4.17.6"
+ "@vueuse/core" "^8.2.6"
+ async-validator "^4.0.7"
+ dayjs "^1.11.1"
+ escape-html "^1.0.3"
+ lodash "^4.17.21"
+ lodash-es "^4.17.21"
+ lodash-unified "^1.0.2"
+ memoize-one "^6.0.0"
+ normalize-wheel-es "^1.1.2"
+
+esbuild-android-64@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.38.tgz#5b94a1306df31d55055f64a62ff6b763a47b7f64"
+ integrity sha512-aRFxR3scRKkbmNuGAK+Gee3+yFxkTJO/cx83Dkyzo4CnQl/2zVSurtG6+G86EQIZ+w+VYngVyK7P3HyTBKu3nw==
+
+esbuild-android-arm64@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.38.tgz#78acc80773d16007de5219ccce544c036abd50b8"
+ integrity sha512-L2NgQRWuHFI89IIZIlpAcINy9FvBk6xFVZ7xGdOwIm8VyhX1vNCEqUJO3DPSSy945Gzdg98cxtNt8Grv1CsyhA==
+
+esbuild-darwin-64@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.38.tgz#e02b1291f629ebdc2aa46fabfacc9aa28ff6aa46"
+ integrity sha512-5JJvgXkX87Pd1Og0u/NJuO7TSqAikAcQQ74gyJ87bqWRVeouky84ICoV4sN6VV53aTW+NE87qLdGY4QA2S7KNA==
+
+esbuild-darwin-arm64@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.38.tgz"
+ integrity sha512-eqF+OejMI3mC5Dlo9Kdq/Ilbki9sQBw3QlHW3wjLmsLh+quNfHmGMp3Ly1eWm981iGBMdbtSS9+LRvR2T8B3eQ==
+
+esbuild-freebsd-64@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.38.tgz#790b8786729d4aac7be17648f9ea8e0e16475b5e"
+ integrity sha512-epnPbhZUt93xV5cgeY36ZxPXDsQeO55DppzsIgWM8vgiG/Rz+qYDLmh5ts3e+Ln1wA9dQ+nZmVHw+RjaW3I5Ig==
+
+esbuild-freebsd-arm64@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.38.tgz#b66340ab28c09c1098e6d9d8ff656db47d7211e6"
+ integrity sha512-/9icXUYJWherhk+y5fjPI5yNUdFPtXHQlwP7/K/zg8t8lQdHVj20SqU9/udQmeUo5pDFHMYzcEFfJqgOVeKNNQ==
+
+esbuild-linux-32@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.38.tgz#7927f950986fd39f0ff319e92839455912b67f70"
+ integrity sha512-QfgfeNHRFvr2XeHFzP8kOZVnal3QvST3A0cgq32ZrHjSMFTdgXhMhmWdKzRXP/PKcfv3e2OW9tT9PpcjNvaq6g==
+
+esbuild-linux-64@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.38.tgz#4893d07b229d9cfe34a2b3ce586399e73c3ac519"
+ integrity sha512-uuZHNmqcs+Bj1qiW9k/HZU3FtIHmYiuxZ/6Aa+/KHb/pFKr7R3aVqvxlAudYI9Fw3St0VCPfv7QBpUITSmBR1Q==
+
+esbuild-linux-arm64@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.38.tgz#8442402e37d0b8ae946ac616784d9c1a2041056a"
+ integrity sha512-HlMGZTEsBrXrivr64eZ/EO0NQM8H8DuSENRok9d+Jtvq8hOLzrxfsAT9U94K3KOGk2XgCmkaI2KD8hX7F97lvA==
+
+esbuild-linux-arm@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.38.tgz#d5dbf32d38b7f79be0ec6b5fb2f9251fd9066986"
+ integrity sha512-FiFvQe8J3VKTDXG01JbvoVRXQ0x6UZwyrU4IaLBZeq39Bsbatd94Fuc3F1RGqPF5RbIWW7RvkVQjn79ejzysnA==
+
+esbuild-linux-mips64le@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.38.tgz#95081e42f698bbe35d8ccee0e3a237594b337eb5"
+ integrity sha512-qd1dLf2v7QBiI5wwfil9j0HG/5YMFBAmMVmdeokbNAMbcg49p25t6IlJFXAeLzogv1AvgaXRXvgFNhScYEUXGQ==
+
+esbuild-linux-ppc64le@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.38.tgz#dceb0a1b186f5df679618882a7990bd422089b47"
+ integrity sha512-mnbEm7o69gTl60jSuK+nn+pRsRHGtDPfzhrqEUXyCl7CTOCLtWN2bhK8bgsdp6J/2NyS/wHBjs1x8aBWwP2X9Q==
+
+esbuild-linux-riscv64@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.38.tgz#61fb8edb75f475f9208c4a93ab2bfab63821afd2"
+ integrity sha512-+p6YKYbuV72uikChRk14FSyNJZ4WfYkffj6Af0/Tw63/6TJX6TnIKE+6D3xtEc7DeDth1fjUOEqm+ApKFXbbVQ==
+
+esbuild-linux-s390x@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.38.tgz#34c7126a4937406bf6a5e69100185fd702d12fe0"
+ integrity sha512-0zUsiDkGJiMHxBQ7JDU8jbaanUY975CdOW1YDrurjrM0vWHfjv9tLQsW9GSyEb/heSK1L5gaweRjzfUVBFoybQ==
+
+esbuild-netbsd-64@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.38.tgz#322ea9937d9e529183ee281c7996b93eb38a5d95"
+ integrity sha512-cljBAApVwkpnJZfnRVThpRBGzCi+a+V9Ofb1fVkKhtrPLDYlHLrSYGtmnoTVWDQdU516qYI8+wOgcGZ4XIZh0Q==
+
+esbuild-openbsd-64@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.38.tgz#1ca29bb7a2bf09592dcc26afdb45108f08a2cdbd"
+ integrity sha512-CDswYr2PWPGEPpLDUO50mL3WO/07EMjnZDNKpmaxUPsrW+kVM3LoAqr/CE8UbzugpEiflYqJsGPLirThRB18IQ==
+
+esbuild-sunos-64@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.38.tgz#c9446f7d8ebf45093e7bb0e7045506a88540019b"
+ integrity sha512-2mfIoYW58gKcC3bck0j7lD3RZkqYA7MmujFYmSn9l6TiIcAMpuEvqksO+ntBgbLep/eyjpgdplF7b+4T9VJGOA==
+
+esbuild-windows-32@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.38.tgz#f8e9b4602fd0ccbd48e5c8d117ec0ba4040f2ad1"
+ integrity sha512-L2BmEeFZATAvU+FJzJiRLFUP+d9RHN+QXpgaOrs2klshoAm1AE6Us4X6fS9k33Uy5SzScn2TpcgecbqJza1Hjw==
+
+esbuild-windows-64@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.38.tgz#280f58e69f78535f470905ce3e43db1746518107"
+ integrity sha512-Khy4wVmebnzue8aeSXLC+6clo/hRYeNIm0DyikoEqX+3w3rcvrhzpoix0S+MF9vzh6JFskkIGD7Zx47ODJNyCw==
+
+esbuild-windows-arm64@0.14.38:
+ version "0.14.38"
+ resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.38.tgz#d97e9ac0f95a4c236d9173fa9f86c983d6a53f54"
+ integrity sha512-k3FGCNmHBkqdJXuJszdWciAH77PukEyDsdIryEHn9cKLQFxzhT39dSumeTuggaQcXY57UlmLGIkklWZo2qzHpw==
+
+esbuild@^0.14.27:
+ version "0.14.38"
+ resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.14.38.tgz"
+ integrity sha512-12fzJ0fsm7gVZX1YQ1InkOE5f9Tl7cgf6JPYXRJtPIoE0zkWAbHdPHVPPaLi9tYAcEBqheGzqLn/3RdTOyBfcA==
+ optionalDependencies:
+ esbuild-android-64 "0.14.38"
+ esbuild-android-arm64 "0.14.38"
+ esbuild-darwin-64 "0.14.38"
+ esbuild-darwin-arm64 "0.14.38"
+ esbuild-freebsd-64 "0.14.38"
+ esbuild-freebsd-arm64 "0.14.38"
+ esbuild-linux-32 "0.14.38"
+ esbuild-linux-64 "0.14.38"
+ esbuild-linux-arm "0.14.38"
+ esbuild-linux-arm64 "0.14.38"
+ esbuild-linux-mips64le "0.14.38"
+ esbuild-linux-ppc64le "0.14.38"
+ esbuild-linux-riscv64 "0.14.38"
+ esbuild-linux-s390x "0.14.38"
+ esbuild-netbsd-64 "0.14.38"
+ esbuild-openbsd-64 "0.14.38"
+ esbuild-sunos-64 "0.14.38"
+ esbuild-windows-32 "0.14.38"
+ esbuild-windows-64 "0.14.38"
+ esbuild-windows-arm64 "0.14.38"
+
+escape-html@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz"
+ integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
+
+estree-walker@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz"
+ integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
+
+fill-range@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz"
+ integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+follow-redirects@^1.14.9:
+ version "1.15.0"
+ resolved "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.0.tgz"
+ integrity sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==
+
+form-data@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz"
+ integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.8"
+ mime-types "^2.1.12"
+
+fsevents@~2.3.2:
+ version "2.3.2"
+ resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz"
+ integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
+
+function-bind@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz"
+ integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+
+glob-parent@~5.1.2:
+ version "5.1.2"
+ resolved "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz"
+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+ dependencies:
+ is-glob "^4.0.1"
+
+good-listener@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz"
+ integrity sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==
+ dependencies:
+ delegate "^3.1.2"
+
+has@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz"
+ integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
+ dependencies:
+ function-bind "^1.1.1"
+
+immutable@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmmirror.com/immutable/-/immutable-4.0.0.tgz"
+ integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==
+
+is-binary-path@~2.1.0:
+ version "2.1.0"
+ resolved "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz"
+ integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
+ dependencies:
+ binary-extensions "^2.0.0"
+
+is-core-module@^2.8.1:
+ version "2.9.0"
+ resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz"
+ integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==
+ dependencies:
+ has "^1.0.3"
+
+is-extglob@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz"
+ integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+
+is-glob@^4.0.1, is-glob@~4.0.1:
+ version "4.0.3"
+ resolved "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz"
+ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+ dependencies:
+ is-extglob "^2.1.1"
+
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+lodash-es@^4.17.21:
+ version "4.17.21"
+ resolved "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz"
+ integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
+
+lodash-unified@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.2.tgz"
+ integrity sha512-OGbEy+1P+UT26CYi4opY4gebD8cWRDxAT6MAObIVQMiqYdxZr1g3QHWCToVsm31x2NkLS4K3+MC2qInaRMa39g==
+
+lodash@^4.17.21:
+ version "4.17.21"
+ resolved "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz"
+ integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
+
+magic-string@^0.25.7:
+ version "0.25.9"
+ resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz"
+ integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==
+ dependencies:
+ sourcemap-codec "^1.4.8"
+
+memoize-one@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz"
+ integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==
+
+mime-db@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz"
+ integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
+
+mime-types@^2.1.12:
+ version "2.1.35"
+ resolved "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz"
+ integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
+ dependencies:
+ mime-db "1.52.0"
+
+nanoid@^3.3.3:
+ version "3.3.4"
+ resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz"
+ integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
+
+normalize-path@^3.0.0, normalize-path@~3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz"
+ integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
+
+normalize-wheel-es@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.1.2.tgz"
+ integrity sha512-scX83plWJXYH1J4+BhAuIHadROzxX0UBF3+HuZNY2Ks8BciE7tSTQ+5JhTsvzjaO0/EJdm4JBGrfObKxFf3Png==
+
+path-parse@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz"
+ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+
+picocolors@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz"
+ integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
+
+picomatch@^2.0.4, picomatch@^2.2.1:
+ version "2.3.1"
+ resolved "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz"
+ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
+postcss@^8.1.10, postcss@^8.4.13:
+ version "8.4.13"
+ resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.13.tgz"
+ integrity sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==
+ dependencies:
+ nanoid "^3.3.3"
+ picocolors "^1.0.0"
+ source-map-js "^1.0.2"
+
+readdirp@~3.6.0:
+ version "3.6.0"
+ resolved "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz"
+ integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
+ dependencies:
+ picomatch "^2.2.1"
+
+resolve@^1.22.0:
+ version "1.22.0"
+ resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz"
+ integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==
+ dependencies:
+ is-core-module "^2.8.1"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+rollup@^2.59.0:
+ version "2.72.0"
+ resolved "https://registry.npmjs.org/rollup/-/rollup-2.72.0.tgz"
+ integrity sha512-KqtR2YcO35/KKijg4nx4STO3569aqCUeGRkKWnJ6r+AvBBrVY9L4pmf4NHVrQr4mTOq6msbohflxr2kpihhaOA==
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+sass@^1.51.0:
+ version "1.51.0"
+ resolved "https://registry.npmmirror.com/sass/-/sass-1.51.0.tgz"
+ integrity sha512-haGdpTgywJTvHC2b91GSq+clTKGbtkkZmVAb82jZQN/wTy6qs8DdFm2lhEQbEwrY0QDRgSQ3xDurqM977C3noA==
+ dependencies:
+ chokidar ">=3.0.0 <4.0.0"
+ immutable "^4.0.0"
+ source-map-js ">=0.6.2 <2.0.0"
+
+select@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.npmmirror.com/select/-/select-1.1.2.tgz"
+ integrity sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==
+
+"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz"
+ integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
+
+source-map@^0.6.1:
+ version "0.6.1"
+ resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz"
+ integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
+sourcemap-codec@^1.4.8:
+ version "1.4.8"
+ resolved "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz"
+ integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
+
+supports-preserve-symlinks-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz"
+ integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
+tiny-emitter@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz"
+ integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
+
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
+
+vite@^2.8.0:
+ version "2.9.8"
+ resolved "https://registry.npmjs.org/vite/-/vite-2.9.8.tgz"
+ integrity sha512-zsBGwn5UT3YS0NLSJ7hnR54+vUKfgzMUh/Z9CxF1YKEBVIe213+63jrFLmZphgGI5zXwQCSmqIdbPuE8NJywPw==
+ dependencies:
+ esbuild "^0.14.27"
+ postcss "^8.4.13"
+ resolve "^1.22.0"
+ rollup "^2.59.0"
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+vue-demi@*:
+ version "0.12.5"
+ resolved "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.12.5.tgz"
+ integrity sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==
+
+vue-json-viewer@3:
+ version "3.0.4"
+ resolved "https://registry.npmmirror.com/vue-json-viewer/-/vue-json-viewer-3.0.4.tgz"
+ integrity sha512-pnC080rTub6YjccthVSNQod2z9Sl5IUUq46srXtn6rxwhW8QM4rlYn+CTSLFKXWfw+N3xv77Cioxw7B4XUKIbQ==
+ dependencies:
+ clipboard "^2.0.4"
+
+vue-router@^4.0.15:
+ version "4.0.15"
+ resolved "https://registry.npmmirror.com/vue-router/-/vue-router-4.0.15.tgz"
+ integrity sha512-xa+pIN9ZqORdIW1MkN2+d9Ui2pCM1b/UMgwYUCZOiFYHAvz/slKKBDha8DLrh5aCG/RibtrpyhKjKOZ85tYyWg==
+ dependencies:
+ "@vue/devtools-api" "^6.0.0"
+
+vue@^3.2.25:
+ version "3.2.33"
+ resolved "https://registry.npmjs.org/vue/-/vue-3.2.33.tgz"
+ integrity sha512-si1ExAlDUrLSIg/V7D/GgA4twJwfsfgG+t9w10z38HhL/HA07132pUQ2KuwAo8qbCyMJ9e6OqrmWrOCr+jW7ZQ==
+ dependencies:
+ "@vue/compiler-dom" "3.2.33"
+ "@vue/compiler-sfc" "3.2.33"
+ "@vue/runtime-dom" "3.2.33"
+ "@vue/server-renderer" "3.2.33"
+ "@vue/shared" "3.2.33"
diff --git a/glc/www/web_embed.go b/glc/www/web_embed.go
new file mode 100644
index 0000000..7ebaac2
--- /dev/null
+++ b/glc/www/web_embed.go
@@ -0,0 +1,8 @@
+package www
+
+import "embed"
+
+var (
+ //go:embed web/dist/*
+ Static embed.FS
+)