init
This commit is contained in:
parent
7468eff05e
commit
3d1ebb8f8e
2
.dockerignore
Normal file
2
.dockerignore
Normal file
@ -0,0 +1,2 @@
|
||||
build
|
||||
config.yaml
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/build
|
||||
/config.yaml
|
||||
.idea
|
||||
.vscode
|
15
Dockerfile
Normal file
15
Dockerfile
Normal file
@ -0,0 +1,15 @@
|
||||
# docker build -t registry.leafdev.top/leaf/rag-new:v0.0.1-fix .
|
||||
FROM golang:latest as builder
|
||||
|
||||
COPY . /app
|
||||
|
||||
RUN go env -w GO111MODULE=on && go env -w GOPROXY=https://goproxy.cn,direct && go mod download
|
||||
RUN CGO_ENABLED=0 go build -ldflags "-w -s" -gcflags "-N -l" -o main .
|
||||
|
||||
# RUN
|
||||
FROM alpine:latest
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=builder /app/main /app/main
|
||||
ENTRYPOINT ["/app/main"]
|
8
Dockerfile2
Normal file
8
Dockerfile2
Normal file
@ -0,0 +1,8 @@
|
||||
# docker build -t registry.leafdev.top/leaf/rag-new:v0.0.1-fix . -f Dockerfile2
|
||||
# RUN
|
||||
FROM alpine:latest
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY ./main /app/main
|
||||
ENTRYPOINT ["/app/main"]
|
12
Makefile
Normal file
12
Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
.PHONY: install-deps generate
|
||||
|
||||
install-deps:
|
||||
go install github.com/google/wire/cmd/wire@latest
|
||||
go install github.com/swaggo/swag/cmd/swag@latest
|
||||
go install github.com/pressly/goose/v3/cmd/goose@latest
|
||||
|
||||
generate:
|
||||
go generate ./...
|
||||
|
||||
swag:
|
||||
swag init -g main.go --parseDependency
|
70
buf.gen.yaml
Normal file
70
buf.gen.yaml
Normal file
@ -0,0 +1,70 @@
|
||||
http:
|
||||
port: 8080
|
||||
host: 0.0.0.0
|
||||
# the production url
|
||||
url: http://127.0.0.1:8080
|
||||
|
||||
grpc:
|
||||
address: 0.0.0.0:9090
|
||||
|
||||
debug:
|
||||
enabled: false
|
||||
|
||||
database:
|
||||
host: 127.0.0.1
|
||||
port: 3306
|
||||
user: root
|
||||
password: root
|
||||
name: db_name
|
||||
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
password: ""
|
||||
db: 0
|
||||
|
||||
jwks:
|
||||
url: ""
|
||||
|
||||
metrics:
|
||||
enabled: true
|
||||
port: 8081
|
||||
host: 0.0.0.0
|
||||
|
||||
s3:
|
||||
endpoint: 127.0.0.1:9000
|
||||
external_endpoint: 127.0.0.1:9000
|
||||
access_key: minio
|
||||
secret_key: minio123
|
||||
bucket: amber
|
||||
use_ssl: false
|
||||
region:
|
||||
|
||||
milvus:
|
||||
host: 127.0.0.1
|
||||
port: 19530
|
||||
db_name: library
|
||||
# 由于 Milvus 不支持新增列, 如果更换了 Embedding Model,建议新建一个 Collection
|
||||
# 或者可以扩展张量
|
||||
document_collection: documents
|
||||
user:
|
||||
password:
|
||||
|
||||
|
||||
kafka:
|
||||
bootstrap_servers:
|
||||
- 127.0.0.1:9092
|
||||
topic: "amber"
|
||||
group_id: ""
|
||||
# Plain
|
||||
username: ""
|
||||
password: ""
|
||||
|
||||
openai:
|
||||
api_key: ""
|
||||
internal_base_url: http://192.168.81.108:9997/v1
|
||||
embedding_dim: 768
|
||||
embedding_model: jina-v2-zh
|
||||
|
||||
third_party:
|
||||
openai_api_key: ""
|
55
cmd/document.go
Normal file
55
cmd/document.go
Normal file
@ -0,0 +1,55 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/auth"
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging"
|
||||
"github.com/spf13/cobra"
|
||||
"go-template/pkg/protos/documentService"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/reflection"
|
||||
"net"
|
||||
)
|
||||
|
||||
func init() {
|
||||
RootCmd.AddCommand(documentServiceCommand)
|
||||
}
|
||||
|
||||
var documentServiceCommand = &cobra.Command{
|
||||
Use: "document",
|
||||
Short: "Start document service",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
app, err := CreateApp()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
|
||||
app.Logger.Sugar.Info("Start document service")
|
||||
|
||||
lis, err := net.Listen("tcp", app.Config.Grpc.Address)
|
||||
if err != nil {
|
||||
app.Logger.Sugar.Fatal(err)
|
||||
}
|
||||
var opts = []grpc.ServerOption{
|
||||
grpc.ChainUnaryInterceptor(
|
||||
logging.UnaryServerInterceptor(app.Handler.GRPC.Interceptor.Logger.ZapLogInterceptor()),
|
||||
|
||||
auth.UnaryServerInterceptor(app.Handler.GRPC.Interceptor.Auth.JwtAuth),
|
||||
),
|
||||
grpc.ChainStreamInterceptor(
|
||||
logging.StreamServerInterceptor(app.Handler.GRPC.Interceptor.Logger.ZapLogInterceptor()),
|
||||
auth.StreamServerInterceptor(app.Handler.GRPC.Interceptor.Auth.JwtAuth),
|
||||
),
|
||||
}
|
||||
grpcServer := grpc.NewServer(opts...)
|
||||
|
||||
documentService.RegisterDocumentServiceServer(grpcServer, app.Handler.GRPC.DocumentService)
|
||||
reflection.Register(grpcServer)
|
||||
|
||||
app.Logger.Sugar.Info("Document Service listing on " + app.Config.Grpc.Address)
|
||||
|
||||
if err := grpcServer.Serve(lis); err != nil {
|
||||
app.Logger.Sugar.Fatal(err)
|
||||
}
|
||||
},
|
||||
}
|
100
cmd/http.go
Normal file
100
cmd/http.go
Normal file
@ -0,0 +1,100 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/spf13/cobra"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
RootCmd.AddCommand(httpCmd)
|
||||
}
|
||||
|
||||
var httpCmd = &cobra.Command{
|
||||
Use: "http",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
initHttpServer()
|
||||
},
|
||||
}
|
||||
|
||||
func initHttpServer() {
|
||||
app, err := CreateApp()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
|
||||
if app.Config.Http.Host == "" {
|
||||
app.Config.Http.Host = "0.0.0.0"
|
||||
}
|
||||
|
||||
if app.Config.Http.Port == 0 {
|
||||
app.Config.Http.Port = 8000
|
||||
}
|
||||
|
||||
var bizServer *http.Server
|
||||
var metricServer *http.Server
|
||||
|
||||
bizServer = &http.Server{
|
||||
Addr: ":8080",
|
||||
}
|
||||
|
||||
bizServer.Addr = app.Config.Http.Host + ":" + strconv.Itoa(app.Config.Http.Port)
|
||||
bizServer.Handler = app.HttpServer.BizRouter()
|
||||
|
||||
// 启动 http
|
||||
go func() {
|
||||
// refresh
|
||||
app.Service.Jwks.SetupAuthRefresh()
|
||||
|
||||
app.Logger.Sugar.Info("Listening and serving HTTP on ", bizServer.Addr)
|
||||
err = bizServer.ListenAndServe()
|
||||
if err != nil && !errors.Is(http.ErrServerClosed, err) {
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
// 启动 metrics
|
||||
if app.Config.Metrics.Enabled {
|
||||
metricServer = &http.Server{
|
||||
Addr: ":8080",
|
||||
}
|
||||
metricServer.Addr = app.Config.Metrics.Host + ":" + strconv.Itoa(app.Config.Metrics.Port)
|
||||
go func() {
|
||||
app.Logger.Sugar.Info("Metrics and serving HTTP on ", metricServer.Addr)
|
||||
|
||||
metricServer.Handler = app.HttpServer.MetricRouter()
|
||||
|
||||
err = metricServer.ListenAndServe()
|
||||
if err != nil && !errors.Is(http.ErrServerClosed, err) {
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待一个 INT 或 TERM 信号
|
||||
quit := make(chan os.Signal)
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-quit
|
||||
app.Logger.Sugar.Info("Shutdown Server ...")
|
||||
// 创建超时上下文,Shutdown 可以让未处理的连接在这个时间内关闭
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// 停止HTTP服务器
|
||||
if err := bizServer.Shutdown(ctx); err != nil {
|
||||
app.Logger.Sugar.Fatal("Biz Server Shutdown Error:", err)
|
||||
}
|
||||
|
||||
if err := metricServer.Shutdown(ctx); err != nil {
|
||||
app.Logger.Sugar.Fatal("Metric Server Shutdown Error:", err)
|
||||
}
|
||||
}
|
162
cmd/migrate.go
Normal file
162
cmd/migrate.go
Normal file
@ -0,0 +1,162 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"go-template/internal/migrations"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pressly/goose/v3"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
RootCmd.AddCommand(migrateCommand, createGoMigrateCommand)
|
||||
}
|
||||
|
||||
var migrateCommand = &cobra.Command{
|
||||
Use: "goose [command]",
|
||||
Short: "goose 迁移,用法 <command>",
|
||||
Long: "适用于生产环境的数据库迁移",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) == 0 {
|
||||
_ = cmd.Help()
|
||||
return
|
||||
}
|
||||
RunMigrate(args)
|
||||
},
|
||||
}
|
||||
|
||||
var createGoMigrateCommand = &cobra.Command{
|
||||
Use: "create-migrate",
|
||||
Short: "新建 go 迁移",
|
||||
Long: "新建 goose 的 go 迁移。",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) == 0 {
|
||||
_ = cmd.Help()
|
||||
return
|
||||
}
|
||||
|
||||
name := args[0]
|
||||
|
||||
createGooseMigration(name)
|
||||
},
|
||||
}
|
||||
|
||||
// RunMigrate 为数据库函数
|
||||
func RunMigrate(args []string) {
|
||||
app, err := CreateApp()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// setup config
|
||||
migrations.Config = app.Config
|
||||
|
||||
// dic
|
||||
goose.SetBaseFS(migrations.MigrationFS)
|
||||
|
||||
// dialect tidb
|
||||
err = goose.SetDialect("tidb")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
db, err := app.GORM.DB()
|
||||
if err != nil {
|
||||
log.Fatalf("goose: %v\n", err)
|
||||
}
|
||||
|
||||
command := args[0]
|
||||
|
||||
var arguments []string
|
||||
if len(args) > 3 {
|
||||
arguments = append(arguments, args[3:]...)
|
||||
}
|
||||
|
||||
err = goose.RunContext(context.Background(), command, db, ".", arguments...)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("goose: %v\n", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := db.Close(); err != nil {
|
||||
log.Fatalf("goose: failed to close DB: %v\n", err)
|
||||
}
|
||||
}()
|
||||
|
||||
}
|
||||
|
||||
func createGooseMigration(name string) {
|
||||
// 在 internal/migrations 目录下新建一个迁移文件
|
||||
// 文件名为 yyyy-mm-dd-hh-mm-ss-<name>.go
|
||||
month := int(time.Now().Month())
|
||||
monthString := fmt.Sprintf("%d", month)
|
||||
if month < 10 {
|
||||
// 转 string
|
||||
monthString = "0" + monthString
|
||||
}
|
||||
|
||||
day := time.Now().Day()
|
||||
dayString := fmt.Sprintf("%d", day)
|
||||
if day < 10 {
|
||||
dayString = "0" + dayString
|
||||
}
|
||||
|
||||
hour := time.Now().Hour()
|
||||
hourString := fmt.Sprintf("%d", hour)
|
||||
if hour < 10 {
|
||||
hourString = "0" + hourString
|
||||
}
|
||||
|
||||
minute := time.Now().Minute()
|
||||
minuteString := fmt.Sprintf("%d", minute)
|
||||
if minute < 10 {
|
||||
minuteString = "0" + minuteString
|
||||
}
|
||||
|
||||
// 秒
|
||||
second := time.Now().Second()
|
||||
secondString := fmt.Sprintf("%d", second)
|
||||
if second < 10 {
|
||||
secondString = "0" + secondString
|
||||
}
|
||||
|
||||
funcName := fmt.Sprintf("%d%s%s%s%s%s", time.Now().Year(), monthString, dayString, hourString, minuteString, secondString)
|
||||
fileName := fmt.Sprintf("%s_%s.go", funcName, name)
|
||||
|
||||
// 模板内容
|
||||
var template = `package migrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"github.com/pressly/goose/v3"
|
||||
)
|
||||
|
||||
func init() {
|
||||
goose.AddMigrationContext(Up<FuncName>, Down<FuncName>)
|
||||
}
|
||||
|
||||
func Up<FuncName>(ctx context.Context, tx *sql.Tx) error {
|
||||
_, err := tx.ExecContext(ctx, "UPDATE users SET username='admin' WHERE username='root';")
|
||||
return err
|
||||
}
|
||||
|
||||
func Down<FuncName>(ctx context.Context, tx *sql.Tx) error {
|
||||
_, err := tx.ExecContext(ctx, "UPDATE users SET username='root' WHERE username='admin';")
|
||||
return err
|
||||
}
|
||||
`
|
||||
|
||||
template = strings.ReplaceAll(template, "<FuncName>", funcName+name)
|
||||
err := os.WriteFile("internal/migrations/"+fileName, []byte(template), 0644)
|
||||
if err != nil {
|
||||
log.Fatalf("failed creating migration file: %v", err)
|
||||
}
|
||||
|
||||
}
|
14
cmd/root.go
Normal file
14
cmd/root.go
Normal file
@ -0,0 +1,14 @@
|
||||
package cmd
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "rag",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := cmd.Help()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
},
|
||||
}
|
39
cmd/schedule.go
Normal file
39
cmd/schedule.go
Normal file
@ -0,0 +1,39 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"go-template/internal/base"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
RootCmd.AddCommand(scheduleCmd)
|
||||
}
|
||||
|
||||
var scheduleCmd = &cobra.Command{
|
||||
Use: "schedule",
|
||||
Short: "Schedule commands",
|
||||
Long: `Schedule commands`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
app, err := CreateApp()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
runSchedule(app)
|
||||
},
|
||||
}
|
||||
|
||||
func runSchedule(app *base.Application) {
|
||||
// var wg sync.WaitGroup
|
||||
|
||||
// var ctx = context.Background()
|
||||
|
||||
// wg.Add(1)
|
||||
// // 启动一个定时器
|
||||
// go func() {
|
||||
|
||||
// }()
|
||||
|
||||
// wg.Wait()
|
||||
}
|
42
cmd/wire.go
Normal file
42
cmd/wire.go
Normal file
@ -0,0 +1,42 @@
|
||||
//go:build wireinject
|
||||
// +build wireinject
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"go-template/internal/base"
|
||||
"go-template/internal/base/conf"
|
||||
"go-template/internal/base/logger"
|
||||
"go-template/internal/base/orm"
|
||||
"go-template/internal/base/redis"
|
||||
"go-template/internal/base/s3"
|
||||
"go-template/internal/base/server"
|
||||
"go-template/internal/batch"
|
||||
"go-template/internal/dao"
|
||||
"go-template/internal/handler"
|
||||
"go-template/internal/router"
|
||||
"go-template/internal/service"
|
||||
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
||||
var ProviderSet = wire.NewSet(
|
||||
conf.ProviderConfig,
|
||||
logger.NewZapLogger,
|
||||
orm.NewGORM,
|
||||
dao.NewQuery,
|
||||
redis.NewRedis,
|
||||
s3.NewS3,
|
||||
batch.NewBatch,
|
||||
service.Provider,
|
||||
handler.ProviderSet,
|
||||
router.ProviderSetRouter,
|
||||
server.NewHTTPServer,
|
||||
base.NewApplication,
|
||||
)
|
||||
|
||||
func CreateApp() (*base.Application, error) {
|
||||
wire.Build(ProviderSet)
|
||||
|
||||
return nil, nil
|
||||
}
|
63
cmd/wire_gen.go
Normal file
63
cmd/wire_gen.go
Normal file
@ -0,0 +1,63 @@
|
||||
// Code generated by Wire. DO NOT EDIT.
|
||||
|
||||
//go:generate go run -mod=mod github.com/google/wire/cmd/wire
|
||||
//go:build !wireinject
|
||||
// +build !wireinject
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/google/wire"
|
||||
"go-template/internal/base"
|
||||
"go-template/internal/base/conf"
|
||||
"go-template/internal/base/logger"
|
||||
"go-template/internal/base/orm"
|
||||
"go-template/internal/base/redis"
|
||||
"go-template/internal/base/s3"
|
||||
"go-template/internal/base/server"
|
||||
"go-template/internal/batch"
|
||||
"go-template/internal/dao"
|
||||
"go-template/internal/handler"
|
||||
"go-template/internal/handler/grpc"
|
||||
"go-template/internal/handler/grpc/documents"
|
||||
"go-template/internal/handler/http"
|
||||
"go-template/internal/handler/http/controller/v1"
|
||||
"go-template/internal/handler/http/middleware"
|
||||
"go-template/internal/router"
|
||||
"go-template/internal/service"
|
||||
"go-template/internal/service/auth"
|
||||
"go-template/internal/service/jwks"
|
||||
)
|
||||
|
||||
// Injectors from wire.go:
|
||||
|
||||
func CreateApp() (*base.Application, error) {
|
||||
loggerLogger := logger.NewZapLogger()
|
||||
config := conf.ProviderConfig(loggerLogger)
|
||||
jwksJWKS := jwks.NewJWKS(config, loggerLogger)
|
||||
authService := auth.NewAuthService(config, jwksJWKS, loggerLogger)
|
||||
userController := v1.NewUserController(authService)
|
||||
handlers := http.NewHandler(userController)
|
||||
api := router.NewApiRoute(handlers)
|
||||
swaggerRouter := router.NewSwaggerRoute()
|
||||
ginLoggerMiddleware := middleware.NewGinLoggerMiddleware(loggerLogger)
|
||||
authMiddleware := middleware.NewAuthMiddleware(authService)
|
||||
jsonResponseMiddleware := middleware.NewJSONResponseMiddleware()
|
||||
httpMiddleware := http.NewMiddleware(ginLoggerMiddleware, authMiddleware, jsonResponseMiddleware)
|
||||
httpServer := server.NewHTTPServer(config, api, swaggerRouter, httpMiddleware)
|
||||
db := orm.NewGORM(config, loggerLogger)
|
||||
query := dao.NewQuery(db)
|
||||
documentService := documents.NewDocumentService(query)
|
||||
grpcHandlers := grpc.NewHandler(documentService)
|
||||
handlerHandler := handler.NewHandler(grpcHandlers, handlers)
|
||||
serviceService := service.NewService(loggerLogger, jwksJWKS, authService)
|
||||
redisRedis := redis.NewRedis(config)
|
||||
batchBatch := batch.NewBatch(loggerLogger)
|
||||
s3S3 := s3.NewS3(config)
|
||||
application := base.NewApplication(config, httpServer, handlerHandler, loggerLogger, serviceService, httpMiddleware, redisRedis, batchBatch, s3S3, db, query)
|
||||
return application, nil
|
||||
}
|
||||
|
||||
// wire.go:
|
||||
|
||||
var ProviderSet = wire.NewSet(conf.ProviderConfig, logger.NewZapLogger, orm.NewGORM, dao.NewQuery, redis.NewRedis, s3.NewS3, batch.NewBatch, service.Provider, handler.ProviderSet, router.ProviderSetRouter, server.NewHTTPServer, base.NewApplication)
|
6
configs/config.go
Normal file
6
configs/config.go
Normal file
@ -0,0 +1,6 @@
|
||||
package configs
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed config.yaml
|
||||
var Config []byte
|
70
configs/config.yaml
Normal file
70
configs/config.yaml
Normal file
@ -0,0 +1,70 @@
|
||||
http:
|
||||
port: 8080
|
||||
host: 0.0.0.0
|
||||
# the production url
|
||||
url: http://127.0.0.1:8080
|
||||
|
||||
grpc:
|
||||
address: 0.0.0.0:9090
|
||||
|
||||
debug:
|
||||
enabled: false
|
||||
|
||||
database:
|
||||
host: 127.0.0.1
|
||||
port: 3306
|
||||
user: root
|
||||
password: root
|
||||
name: db_name
|
||||
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
password: ""
|
||||
db: 0
|
||||
|
||||
jwks:
|
||||
url: ""
|
||||
|
||||
metrics:
|
||||
enabled: true
|
||||
port: 8081
|
||||
host: 0.0.0.0
|
||||
|
||||
s3:
|
||||
endpoint: 127.0.0.1:9000
|
||||
external_endpoint: 127.0.0.1:9000
|
||||
access_key: minio
|
||||
secret_key: minio123
|
||||
bucket: amber
|
||||
use_ssl: false
|
||||
region:
|
||||
|
||||
milvus:
|
||||
host: 127.0.0.1
|
||||
port: 19530
|
||||
db_name: library
|
||||
# 由于 Milvus 不支持新增列, 如果更换了 Embedding Model,建议新建一个 Collection
|
||||
# 或者可以扩展张量
|
||||
document_collection: documents
|
||||
user:
|
||||
password:
|
||||
|
||||
|
||||
kafka:
|
||||
bootstrap_servers:
|
||||
- 127.0.0.1:9092
|
||||
topic: "amber"
|
||||
group_id: ""
|
||||
# Plain
|
||||
username: ""
|
||||
password: ""
|
||||
|
||||
openai:
|
||||
api_key: ""
|
||||
internal_base_url: http://192.168.81.108:9997/v1
|
||||
embedding_dim: 768
|
||||
embedding_model: jina-v2-zh
|
||||
|
||||
third_party:
|
||||
openai_api_key: ""
|
128
docs/docs.go
Normal file
128
docs/docs.go
Normal file
@ -0,0 +1,128 @@
|
||||
// Package docs Code generated by swaggo/swag. DO NOT EDIT
|
||||
package docs
|
||||
|
||||
import "github.com/swaggo/swag"
|
||||
|
||||
const docTemplate = `{
|
||||
"schemes": {{ marshal .Schemes }},
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"description": "{{escape .Description}}",
|
||||
"title": "{{.Title}}",
|
||||
"contact": {},
|
||||
"version": "{{.Version}}"
|
||||
},
|
||||
"host": "{{.Host}}",
|
||||
"basePath": "{{.BasePath}}",
|
||||
"paths": {
|
||||
"/api/v1/ping": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "测试接口,将会返回当前用户的信息",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"ping"
|
||||
],
|
||||
"summary": "Greet",
|
||||
"deprecated": true,
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/schema.ResponseBody"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/schema.CurrentUserResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/schema.ResponseBody"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"schema.CurrentUserResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ip": {
|
||||
"type": "string"
|
||||
},
|
||||
"userEmail": {
|
||||
"type": "string"
|
||||
},
|
||||
"userId": {
|
||||
"type": "string"
|
||||
},
|
||||
"userName": {
|
||||
"type": "string"
|
||||
},
|
||||
"valid": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema.ResponseBody": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {},
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
"ApiKeyAuth": {
|
||||
"type": "apiKey",
|
||||
"name": "Authorization",
|
||||
"in": "header"
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
// SwaggerInfo holds exported Swagger Info so clients can modify it
|
||||
var SwaggerInfo = &swag.Spec{
|
||||
Version: "1.0",
|
||||
Host: "",
|
||||
BasePath: "",
|
||||
Schemes: []string{},
|
||||
Title: "API Docs",
|
||||
Description: "",
|
||||
InfoInstanceName: "swagger",
|
||||
SwaggerTemplate: docTemplate,
|
||||
LeftDelim: "{{",
|
||||
RightDelim: "}}",
|
||||
}
|
||||
|
||||
func init() {
|
||||
swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
|
||||
}
|
101
docs/swagger.json
Normal file
101
docs/swagger.json
Normal file
@ -0,0 +1,101 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"title": "API Docs",
|
||||
"contact": {},
|
||||
"version": "1.0"
|
||||
},
|
||||
"paths": {
|
||||
"/api/v1/ping": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "测试接口,将会返回当前用户的信息",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"ping"
|
||||
],
|
||||
"summary": "Greet",
|
||||
"deprecated": true,
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/schema.ResponseBody"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/schema.CurrentUserResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/schema.ResponseBody"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"schema.CurrentUserResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ip": {
|
||||
"type": "string"
|
||||
},
|
||||
"userEmail": {
|
||||
"type": "string"
|
||||
},
|
||||
"userId": {
|
||||
"type": "string"
|
||||
},
|
||||
"userName": {
|
||||
"type": "string"
|
||||
},
|
||||
"valid": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema.ResponseBody": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {},
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
"ApiKeyAuth": {
|
||||
"type": "apiKey",
|
||||
"name": "Authorization",
|
||||
"in": "header"
|
||||
}
|
||||
}
|
||||
}
|
62
docs/swagger.yaml
Normal file
62
docs/swagger.yaml
Normal file
@ -0,0 +1,62 @@
|
||||
definitions:
|
||||
schema.CurrentUserResponse:
|
||||
properties:
|
||||
ip:
|
||||
type: string
|
||||
userEmail:
|
||||
type: string
|
||||
userId:
|
||||
type: string
|
||||
userName:
|
||||
type: string
|
||||
valid:
|
||||
type: boolean
|
||||
type: object
|
||||
schema.ResponseBody:
|
||||
properties:
|
||||
data: {}
|
||||
error:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
success:
|
||||
type: boolean
|
||||
type: object
|
||||
info:
|
||||
contact: {}
|
||||
title: API Docs
|
||||
version: "1.0"
|
||||
paths:
|
||||
/api/v1/ping:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
deprecated: true
|
||||
description: 测试接口,将会返回当前用户的信息
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/schema.ResponseBody'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/schema.CurrentUserResponse'
|
||||
type: object
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/schema.ResponseBody'
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Greet
|
||||
tags:
|
||||
- ping
|
||||
securityDefinitions:
|
||||
ApiKeyAuth:
|
||||
in: header
|
||||
name: Authorization
|
||||
type: apiKey
|
||||
swagger: "2.0"
|
111
go.mod
Normal file
111
go.mod
Normal file
@ -0,0 +1,111 @@
|
||||
module go-template
|
||||
|
||||
go 1.23.2
|
||||
|
||||
require (
|
||||
github.com/MicahParks/keyfunc/v3 v3.3.5
|
||||
github.com/bsm/redislock v0.9.4
|
||||
github.com/gin-contrib/cors v1.7.2
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||
github.com/google/wire v0.6.0
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0
|
||||
github.com/minio/minio-go/v7 v7.0.78
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/pressly/goose/v3 v3.22.1
|
||||
github.com/prometheus/client_golang v1.20.5
|
||||
github.com/redis/go-redis/v9 v9.6.2
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/spf13/viper v1.19.0
|
||||
github.com/swaggo/files v1.0.1
|
||||
github.com/swaggo/gin-swagger v1.6.0
|
||||
github.com/swaggo/swag v1.16.3
|
||||
go.uber.org/zap v1.27.0
|
||||
google.golang.org/grpc v1.64.1
|
||||
google.golang.org/protobuf v1.35.1
|
||||
gorm.io/driver/mysql v1.5.7
|
||||
gorm.io/gen v0.3.26
|
||||
gorm.io/gorm v1.25.12
|
||||
gorm.io/plugin/dbresolver v1.5.3
|
||||
moul.io/zapgorm2 v1.3.0
|
||||
)
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||
github.com/MicahParks/jwkset v0.5.20 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bytedance/sonic v1.12.3 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.6 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-ini/ini v1.67.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/spec v0.21.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.22.1 // indirect
|
||||
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||
github.com/goccy/go-json v0.10.3 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.17 // indirect
|
||||
github.com/mfridman/interpolate v0.0.2 // indirect
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.60.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||
github.com/rs/xid v1.6.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.6.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sethvargo/go-retry v0.3.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.7.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/arch v0.11.0 // indirect
|
||||
golang.org/x/crypto v0.28.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
|
||||
golang.org/x/mod v0.21.0 // indirect
|
||||
golang.org/x/net v0.30.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.26.0 // indirect
|
||||
golang.org/x/text v0.19.0 // indirect
|
||||
golang.org/x/time v0.7.0 // indirect
|
||||
golang.org/x/tools v0.26.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gorm.io/datatypes v1.2.3 // indirect
|
||||
gorm.io/hints v1.1.2 // indirect
|
||||
)
|
391
go.sum
Normal file
391
go.sum
Normal file
@ -0,0 +1,391 @@
|
||||
cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM=
|
||||
cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU=
|
||||
cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls=
|
||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
||||
github.com/MicahParks/jwkset v0.5.20 h1:gTIKx9AofTqQJ0srd8AL7ty9NeadP5WUXSPOZadTpOI=
|
||||
github.com/MicahParks/jwkset v0.5.20/go.mod h1:q8ptTGn/Z9c4MwbcfeCDssADeVQb3Pk7PnVxrvi+2QY=
|
||||
github.com/MicahParks/keyfunc/v3 v3.3.5 h1:7ceAJLUAldnoueHDNzF8Bx06oVcQ5CfJnYwNt1U3YYo=
|
||||
github.com/MicahParks/keyfunc/v3 v3.3.5/go.mod h1:SdCCyMJn/bYqWDvARspC6nCT8Sk74MjuAY22C7dCST8=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/bsm/redislock v0.9.4 h1:X/Wse1DPpiQgHbVYRE9zv6m070UcKoOGekgvpNhiSvw=
|
||||
github.com/bsm/redislock v0.9.4/go.mod h1:Epf7AJLiSFwLCiZcfi6pWFO/8eAYrYpQXFxEDPoDeAk=
|
||||
github.com/bytedance/sonic v1.12.3 h1:W2MGa7RCU1QTeYRTPE3+88mVC0yXmsRQRChiyVocVjU=
|
||||
github.com/bytedance/sonic v1.12.3/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM=
|
||||
github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc=
|
||||
github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc=
|
||||
github.com/gin-contrib/cors v1.7.2 h1:oLDHxdg8W/XDoN/8zamqk/Drgt4oVZDvaV0YmvVICQw=
|
||||
github.com/gin-contrib/cors v1.7.2/go.mod h1:SUJVARKgQ40dmrzgXEVxj2m7Ig1v1qIboQkPDTQ9t2E=
|
||||
github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
|
||||
github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
||||
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
|
||||
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
|
||||
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
|
||||
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
|
||||
github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
|
||||
github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
|
||||
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
|
||||
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
|
||||
github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE=
|
||||
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/wire v0.6.0 h1:HBkoIh4BdSxoyo9PveV8giw7ZsaBOvzWKfcg/6MrVwI=
|
||||
github.com/google/wire v0.6.0/go.mod h1:F4QhpQ9EDIdJ1Mbop/NZBRB+5yrR6qg3BnctaoUk6NA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I=
|
||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs=
|
||||
github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA=
|
||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
|
||||
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY=
|
||||
github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg=
|
||||
github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP3b/PA=
|
||||
github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA=
|
||||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||
github.com/minio/minio-go/v7 v7.0.78 h1:LqW2zy52fxnI4gg8C2oZviTaKHcBV36scS+RzJnxUFs=
|
||||
github.com/minio/minio-go/v7 v7.0.78/go.mod h1:84gmIilaX4zcvAWWzJ5Z1WI5axN+hAbM5w25xf8xvC0=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pressly/goose/v3 v3.22.1 h1:2zICEfr1O3yTP9BRZMGPj7qFxQ+ik6yeo+z1LMuioLc=
|
||||
github.com/pressly/goose/v3 v3.22.1/go.mod h1:xtMpbstWyCpyH+0cxLTMCENWBG+0CSxvTsXhW95d5eo=
|
||||
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA=
|
||||
github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/redis/go-redis/v9 v9.6.2 h1:w0uvkRbc9KpgD98zcvo5IrVUsn0lXpRMuhNgiHDJzdk=
|
||||
github.com/redis/go-redis/v9 v9.6.2/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
||||
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk=
|
||||
github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE=
|
||||
github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
|
||||
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
|
||||
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
|
||||
github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
|
||||
github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M=
|
||||
github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo=
|
||||
github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg=
|
||||
github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/arch v0.11.0 h1:KXV8WWKCXm6tRpLirl2szsO5j/oOODwZf4hATmGVNs4=
|
||||
golang.org/x/arch v0.11.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
|
||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
||||
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
||||
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA=
|
||||
google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0=
|
||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/datatypes v1.2.3 h1:95ucr9ip9dZMPhB3Tc9zbcoAi62hxYAgHicu7SLjK4g=
|
||||
gorm.io/datatypes v1.2.3/go.mod h1:f4BsLcFAX67szSv8svwLRjklArSHAvHLeE3pXAS5DZI=
|
||||
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
|
||||
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
|
||||
gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U=
|
||||
gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A=
|
||||
gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c=
|
||||
gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I=
|
||||
gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0=
|
||||
gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig=
|
||||
gorm.io/gen v0.3.26 h1:sFf1j7vNStimPRRAtH4zz5NiHM+1dr6eA9aaRdplyhY=
|
||||
gorm.io/gen v0.3.26/go.mod h1:a5lq5y3w4g5LMxBcw0wnO6tYUCdNutWODq5LrIt75LE=
|
||||
gorm.io/gorm v1.23.6/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
|
||||
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||
gorm.io/hints v1.1.2 h1:b5j0kwk5p4+3BtDtYqqfY+ATSxjj+6ptPgVveuynn9o=
|
||||
gorm.io/hints v1.1.2/go.mod h1:/ARdpUHAtyEMCh5NNi3tI7FsGh+Cj/MIUlvNxCNCFWg=
|
||||
gorm.io/plugin/dbresolver v1.5.3 h1:wFwINGZZmttuu9h7XpvbDHd8Lf9bb8GNzp/NpAMV2wU=
|
||||
gorm.io/plugin/dbresolver v1.5.3/go.mod h1:TSrVhaUg2DZAWP3PrHlDlITEJmNOkL0tFTjvTEsQ4XE=
|
||||
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI=
|
||||
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
|
||||
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
|
||||
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
|
||||
modernc.org/sqlite v1.33.0 h1:WWkA/T2G17okiLGgKAj4/RMIvgyMT19yQ038160IeYk=
|
||||
modernc.org/sqlite v1.33.0/go.mod h1:9uQ9hF/pCZoYZK73D/ud5Z7cIRIILSZI8NdIemVMTX8=
|
||||
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
|
||||
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
moul.io/zapgorm2 v1.3.0 h1:+CzUTMIcnafd0d/BvBce8T4uPn6DQnpIrz64cyixlkk=
|
||||
moul.io/zapgorm2 v1.3.0/go.mod h1:nPVy6U9goFKHR4s+zfSo1xVFaoU7Qgd5DoCdOfzoCqs=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
1
hack/gorm-gen/.gitignore
vendored
Normal file
1
hack/gorm-gen/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
dao
|
35
hack/gorm-gen/gorm.go
Normal file
35
hack/gorm-gen/gorm.go
Normal file
@ -0,0 +1,35 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"go-template/internal/entity"
|
||||
|
||||
"gorm.io/gen"
|
||||
)
|
||||
|
||||
// Dynamic SQL
|
||||
//type Querier interface {
|
||||
// // SELECT * FROM @@table WHERE name = @name{{if role !=""}} AND role = @role{{end}}
|
||||
// FilterWithNameAndRole(name, role string) ([]gen.T, error)
|
||||
//}
|
||||
|
||||
func main() {
|
||||
//app, err := cmd.CreateApp()
|
||||
//if err != nil {
|
||||
// panic(err)
|
||||
//}
|
||||
g := gen.NewGenerator(gen.Config{
|
||||
OutPath: "../../internal/dao",
|
||||
Mode: gen.WithoutContext | gen.WithDefaultQuery | gen.WithQueryInterface, // generate mode
|
||||
})
|
||||
|
||||
//g.UseDB(app.GORM)
|
||||
|
||||
g.ApplyBasic(
|
||||
entity.User{},
|
||||
)
|
||||
|
||||
// Generate Type Safe API with Dynamic SQL defined on Querier interface for `model.User` and `model.Company`
|
||||
//g.ApplyInterface(func(Querier) {}, model.User{}, model.Company{})
|
||||
|
||||
g.Execute()
|
||||
}
|
135
hack/rename/rename.go
Normal file
135
hack/rename/rename.go
Normal file
@ -0,0 +1,135 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const frameworkModuleName = "leafdev.top/ecosystem/billing"
|
||||
|
||||
func main() {
|
||||
// 输入新的 go.mod module
|
||||
var newModName string
|
||||
fmt.Printf("Enter new module name(eg: github.com/<your-username>/<your-project-name>): ")
|
||||
_, err := fmt.Scanln(&newModName)
|
||||
if err != nil {
|
||||
fmt.Printf("Unable get new module name: %v\n", err)
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("Do you want to setup the project to %s? (y/n)", newModName)
|
||||
var answer string
|
||||
_, err = fmt.Scanln(&answer)
|
||||
if err != nil {
|
||||
fmt.Printf("Error reading user input: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if answer != "y" {
|
||||
fmt.Printf("Aborting setup.\n")
|
||||
}
|
||||
|
||||
// 修改 go.mod 文件中的 module 名称
|
||||
err = replaceInFile("../../go.mod", frameworkModuleName, newModName)
|
||||
if err != nil {
|
||||
fmt.Printf("Error replacing module name in go.mod: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 读取 go.mod 中的 module 名称
|
||||
modName, err := getModuleName("../../go.mod")
|
||||
if err != nil {
|
||||
fmt.Printf("Error reading go.mod: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if modName == frameworkModuleName {
|
||||
fmt.Printf("Please update go.mod module to a different name.\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("Module name found: %s\n", modName)
|
||||
// 遍历当前文件夹(排除 vendor、setup.go 和版本控制文件夹)
|
||||
err = filepath.Walk("../../", func(path string, info fs.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 条件排除
|
||||
if info.IsDir() && (info.Name() == "vendor" || info.Name() == ".git") {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
if !info.IsDir() && info.Name() == "setup.go" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 处理文件
|
||||
if !info.IsDir() {
|
||||
err := replaceInFile(path, `"`+frameworkModuleName, fmt.Sprintf(`"%s`, modName))
|
||||
if err != nil {
|
||||
fmt.Printf("Error replacing in file %s: %v\n", path, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Printf("Error walking the path: %v\n", err)
|
||||
}
|
||||
|
||||
// run go mod tidy
|
||||
fmt.Println("Running go mod tidy...")
|
||||
var aCmd = exec.Command("go", "mod", "tidy")
|
||||
if err := aCmd.Run(); err != nil {
|
||||
fmt.Printf("Error running go mod tidy: %v\n", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 读取 go.mod 文件中的 module 名称
|
||||
func getModuleName(modFilePath string) (string, error) {
|
||||
file, err := os.Open(modFilePath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer func(file *os.File) {
|
||||
err := file.Close()
|
||||
if err != nil {
|
||||
fmt.Printf("Error closing file: %v\n", err)
|
||||
}
|
||||
}(file)
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.HasPrefix(line, "module ") {
|
||||
return strings.TrimSpace(strings.TrimPrefix(line, "module ")), nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("module name not found in go.mod")
|
||||
}
|
||||
|
||||
// 在文件中替换指定的字符串
|
||||
func replaceInFile(filePath string, old string, new string) error {
|
||||
input, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
output := strings.ReplaceAll(string(input), old, new)
|
||||
if err = os.WriteFile(filePath, []byte(output), 0666); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
57
internal/base/app.go
Normal file
57
internal/base/app.go
Normal file
@ -0,0 +1,57 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"go-template/internal/base/conf"
|
||||
"go-template/internal/base/logger"
|
||||
"go-template/internal/base/redis"
|
||||
"go-template/internal/base/s3"
|
||||
"go-template/internal/base/server"
|
||||
"go-template/internal/batch"
|
||||
"go-template/internal/dao"
|
||||
"go-template/internal/handler"
|
||||
"go-template/internal/handler/http"
|
||||
"go-template/internal/service"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Application struct {
|
||||
Config *conf.Config
|
||||
Logger *logger.Logger
|
||||
Handler *handler.Handler
|
||||
Middleware *http.Middleware
|
||||
HttpServer *server.HttpServer
|
||||
GORM *gorm.DB
|
||||
DAO *dao.Query
|
||||
Service *service.Service
|
||||
Redis *redis.Redis
|
||||
Batch *batch.Batch
|
||||
S3 *s3.S3
|
||||
}
|
||||
|
||||
func NewApplication(
|
||||
config *conf.Config,
|
||||
httpServer *server.HttpServer,
|
||||
handler *handler.Handler,
|
||||
logger *logger.Logger,
|
||||
services *service.Service,
|
||||
middleware *http.Middleware,
|
||||
redis *redis.Redis,
|
||||
batch *batch.Batch,
|
||||
S3 *s3.S3,
|
||||
GORM *gorm.DB,
|
||||
DAO *dao.Query,
|
||||
) *Application {
|
||||
return &Application{
|
||||
Config: config,
|
||||
HttpServer: httpServer,
|
||||
Handler: handler,
|
||||
Logger: logger,
|
||||
Service: services,
|
||||
Middleware: middleware,
|
||||
Redis: redis,
|
||||
Batch: batch,
|
||||
S3: S3,
|
||||
GORM: GORM,
|
||||
DAO: DAO,
|
||||
}
|
||||
}
|
107
internal/base/conf/conf.go
Normal file
107
internal/base/conf/conf.go
Normal file
@ -0,0 +1,107 @@
|
||||
package conf
|
||||
|
||||
// Config 配置文件不能有下划线或横线,否则不能解析
|
||||
type Config struct {
|
||||
Http *Http `yaml:"http"`
|
||||
|
||||
Grpc *Grpc `yaml:"grpc"`
|
||||
|
||||
Debug *Debug `yaml:"debug"`
|
||||
|
||||
Database *Database `yaml:"database"`
|
||||
|
||||
Redis *Redis `yaml:"redis"`
|
||||
|
||||
JWKS *JWKS `yaml:"jwks"`
|
||||
|
||||
Metrics *Metrics `yaml:"metrics"`
|
||||
|
||||
S3 *S3 `yaml:"s3"`
|
||||
|
||||
Kafka *Kafka `yaml:"kafka"`
|
||||
|
||||
OpenAI *OpenAI `yaml:"openai"`
|
||||
|
||||
Milvus *Milvus `yaml:"milvus"`
|
||||
|
||||
//ThirdParty *ThirdParty `yaml:"third_party" mapstructure:"third_party"`
|
||||
}
|
||||
|
||||
type ThirdParty struct {
|
||||
OpenAIApiKey string `yaml:"openai_api_key" mapstructure:"openai_api_key"`
|
||||
}
|
||||
|
||||
type Http struct {
|
||||
Host string `yaml:"host"`
|
||||
Port int `yaml:"port"`
|
||||
Url string `yaml:"url"`
|
||||
}
|
||||
|
||||
type Debug struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
|
||||
type Database struct {
|
||||
Host string `yaml:"host"`
|
||||
Port int `yaml:"port"`
|
||||
User string `yaml:"user"`
|
||||
Password string `yaml:"password"`
|
||||
Name string `yaml:"name"`
|
||||
}
|
||||
|
||||
type Redis struct {
|
||||
Host string `yaml:"host"`
|
||||
Port int `yaml:"port"`
|
||||
Password string `yaml:"password"`
|
||||
DB int `yaml:"db"`
|
||||
}
|
||||
|
||||
type JWKS struct {
|
||||
Url string `yaml:"url"`
|
||||
}
|
||||
|
||||
type Metrics struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
Port int `yaml:"port"`
|
||||
Host string `yaml:"host"`
|
||||
}
|
||||
|
||||
type S3 struct {
|
||||
Endpoint string `yaml:"endpoint" mapstructure:"endpoint"`
|
||||
ExternalEndpoint string `yaml:"external_endpoint" mapstructure:"external_endpoint"`
|
||||
AccessKey string `yaml:"access_key" mapstructure:"access_key"`
|
||||
SecretKey string `yaml:"secret_key" mapstructure:"secret_key"`
|
||||
Bucket string `yaml:"bucket" mapstructure:"bucket"`
|
||||
UseSSL bool `yaml:"use_ssl" mapstructure:"use_ssl"`
|
||||
Region string `yaml:"region" mapstructure:"region"`
|
||||
}
|
||||
|
||||
type Kafka struct {
|
||||
BootstrapServers []string `yaml:"bootstrap_servers" mapstructure:"bootstrap_servers"`
|
||||
Topic string `yaml:"topic" mapstructure:"topic"`
|
||||
GroupId string `yaml:"group_id" mapstructure:"group_id"`
|
||||
Username string `yaml:"username" mapstructure:"username"`
|
||||
Password string `yaml:"password" mapstructure:"password"`
|
||||
}
|
||||
|
||||
type Grpc struct {
|
||||
Address string `yaml:"address" mapstructure:"address"`
|
||||
}
|
||||
|
||||
type OpenAI struct {
|
||||
ApiKey string `yaml:"api_key" mapstructure:"api_key"`
|
||||
InternalBaseUrl string `yaml:"internal_base_url" mapstructure:"internal_base_url"`
|
||||
LongContextModel string `yaml:"long_context_model" mapstructure:"long_context_model"`
|
||||
EmbeddingModel string `yaml:"embedding_model" mapstructure:"embedding_model"`
|
||||
EmbeddingDim int `yaml:"embedding_dim" mapstructure:"embedding_dim"`
|
||||
EmbeddingMaxToken int `yaml:"embedding_max_token" mapstructure:"embedding_max_token"`
|
||||
}
|
||||
|
||||
type Milvus struct {
|
||||
Host string `yaml:"host" mapstructure:"host"`
|
||||
Port int `yaml:"port" mapstructure:"port"`
|
||||
DBName string `yaml:"db_name" mapstructure:"db_name"`
|
||||
DocumentCollection string `yaml:"document_collection" mapstructure:"document_collection"`
|
||||
User string `yaml:"user" mapstructure:"user"`
|
||||
Password string `yaml:"password" mapstructure:"password"`
|
||||
}
|
35
internal/base/conf/helper.go
Normal file
35
internal/base/conf/helper.go
Normal file
@ -0,0 +1,35 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"go-template/configs"
|
||||
"os"
|
||||
)
|
||||
|
||||
func createConfigIfNotExists(path string) {
|
||||
if path != "" {
|
||||
return
|
||||
}
|
||||
|
||||
// create if not exists
|
||||
var configName = "config.yaml"
|
||||
|
||||
if _, err := os.Stat(configName); os.IsNotExist(err) {
|
||||
f, err := os.Create(configName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// write default from embed
|
||||
_, err = f.Write(configs.Config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
defer func(f *os.File) {
|
||||
err := f.Close()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}(f)
|
||||
}
|
||||
}
|
71
internal/base/conf/provider.go
Normal file
71
internal/base/conf/provider.go
Normal file
@ -0,0 +1,71 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"go-template/internal/base/logger"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// depth 是配置文件的搜索深度
|
||||
var depth = 8
|
||||
|
||||
func getConfigPath() string {
|
||||
var path string
|
||||
if os.Getenv("AMBER_CONFIG") != "" {
|
||||
path = os.Getenv("AMBER_CONFIG")
|
||||
return path
|
||||
}
|
||||
var pathOptions []string
|
||||
for i := 0; i <= depth; i++ {
|
||||
pathOptions = append(pathOptions, strings.Repeat("../", i)+"config.yaml")
|
||||
}
|
||||
for _, p := range pathOptions {
|
||||
if _, err := os.Stat(p); err == nil {
|
||||
path = p
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if path != "" {
|
||||
// 假设 workDir 是当前工作目录的路径
|
||||
workDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// 将相对路径转换为绝对路径
|
||||
path, err = filepath.Abs(filepath.Join(workDir, path))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
func ProviderConfig(logger *logger.Logger) *Config {
|
||||
var path = getConfigPath()
|
||||
createConfigIfNotExists(path)
|
||||
|
||||
if path == "" {
|
||||
logger.Sugar.Fatal("config file not found, created.")
|
||||
} else {
|
||||
logger.Sugar.Infof("config file found at %s", path)
|
||||
}
|
||||
|
||||
c := &Config{}
|
||||
v := viper.New()
|
||||
v.SetConfigType("yaml")
|
||||
v.SetConfigFile(path)
|
||||
if err := v.ReadInConfig(); err != nil {
|
||||
logger.Sugar.Fatal(err)
|
||||
}
|
||||
if err := v.Unmarshal(c); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
25
internal/base/logger/provider.go
Normal file
25
internal/base/logger/provider.go
Normal file
@ -0,0 +1,25 @@
|
||||
package logger
|
||||
|
||||
import "go.uber.org/zap"
|
||||
|
||||
type Logger struct {
|
||||
Sugar *zap.SugaredLogger
|
||||
Logger *zap.Logger
|
||||
}
|
||||
|
||||
func NewZapLogger() *Logger {
|
||||
logger, err := zap.NewProduction()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
//defer func(logger *zap.Logger) {
|
||||
// err := logger.Sync()
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
//}(logger)
|
||||
|
||||
return &Logger{Sugar: logger.Sugar(), Logger: logger}
|
||||
}
|
29
internal/base/milvus/provide.go
Normal file
29
internal/base/milvus/provide.go
Normal file
@ -0,0 +1,29 @@
|
||||
package milvus
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/milvus-io/milvus-sdk-go/v2/client"
|
||||
"leafdev.top/Leaf/leaf-library/internal/base/conf"
|
||||
"leafdev.top/Leaf/leaf-library/internal/base/logger"
|
||||
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func NewMilvus(config *conf.Config, logger *logger.Logger) client.Client {
|
||||
var address = config.Milvus.Host + ":" + strconv.Itoa(config.Milvus.Port)
|
||||
|
||||
logger.Sugar.Infof("Waiting for milvus, address=%s, dbname=%s", address, config.Milvus.DBName)
|
||||
|
||||
c, err := client.NewClient(context.Background(), client.Config{
|
||||
Address: address,
|
||||
DBName: config.Milvus.DBName,
|
||||
})
|
||||
|
||||
logger.Sugar.Infof("Connected to milvus, address=%s, dbname=%s", address, config.Milvus.DBName)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
6
internal/base/orm/User.go
Normal file
6
internal/base/orm/User.go
Normal file
@ -0,0 +1,6 @@
|
||||
package orm
|
||||
|
||||
type User struct {
|
||||
Username string
|
||||
Password string
|
||||
}
|
46
internal/base/orm/provide.go
Normal file
46
internal/base/orm/provide.go
Normal file
@ -0,0 +1,46 @@
|
||||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go-template/internal/base/conf"
|
||||
"go-template/internal/base/logger"
|
||||
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
"moul.io/zapgorm2"
|
||||
)
|
||||
|
||||
//
|
||||
//func ProviderOrm() *Orm {
|
||||
// return NewOrm()
|
||||
//}
|
||||
|
||||
func NewGORM(
|
||||
config *conf.Config,
|
||||
logger *logger.Logger,
|
||||
) *gorm.DB {
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local", config.Database.User, config.Database.Password, config.Database.Host, config.Database.Port, config.Database.Name)
|
||||
|
||||
if config.Debug.Enabled {
|
||||
db, err := gorm.Open(mysql.Open(dsn))
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
zapGormLogger := zapgorm2.New(logger.Logger)
|
||||
zapGormLogger.SetAsDefault()
|
||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
|
||||
Logger: zapGormLogger,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return db
|
||||
|
||||
}
|
38
internal/base/redis/provide.go
Normal file
38
internal/base/redis/provide.go
Normal file
@ -0,0 +1,38 @@
|
||||
package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"go-template/internal/base/conf"
|
||||
|
||||
"github.com/bsm/redislock"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
type Redis struct {
|
||||
Client *redis.Client
|
||||
Locker *redislock.Client
|
||||
}
|
||||
|
||||
func NewRedis(c *conf.Config) *Redis {
|
||||
var client = redis.NewClient(&redis.Options{
|
||||
Addr: fmt.Sprintf("%s:%d", c.Redis.Host, c.Redis.Port),
|
||||
Password: c.Redis.Password,
|
||||
DB: c.Redis.DB,
|
||||
})
|
||||
|
||||
status := client.Ping(context.Background())
|
||||
if status.Err() != nil {
|
||||
panic(status.Err())
|
||||
}
|
||||
|
||||
// Create a new lock client.
|
||||
locker := redislock.New(client)
|
||||
|
||||
var r = &Redis{
|
||||
Client: client,
|
||||
Locker: locker,
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
29
internal/base/s3/provide.go
Normal file
29
internal/base/s3/provide.go
Normal file
@ -0,0 +1,29 @@
|
||||
package s3
|
||||
|
||||
import (
|
||||
"go-template/internal/base/conf"
|
||||
|
||||
"github.com/minio/minio-go/v7"
|
||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||
)
|
||||
|
||||
type S3 struct {
|
||||
Client *minio.Client
|
||||
Bucket string
|
||||
}
|
||||
|
||||
func NewS3(config *conf.Config) *S3 {
|
||||
minioClient, err := minio.New(config.S3.Endpoint, &minio.Options{
|
||||
Creds: credentials.NewStaticV4(config.S3.AccessKey, config.S3.SecretKey, ""),
|
||||
Secure: config.S3.UseSSL,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &S3{
|
||||
Client: minioClient,
|
||||
Bucket: config.S3.Bucket,
|
||||
}
|
||||
}
|
105
internal/base/server/gin.go
Normal file
105
internal/base/server/gin.go
Normal file
@ -0,0 +1,105 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"go-template/internal/base/conf"
|
||||
httpHandler "go-template/internal/handler/http"
|
||||
"go-template/internal/router"
|
||||
"go-template/internal/schema"
|
||||
"go-template/pkg/consts"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-contrib/cors"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
func promHandler(handler http.Handler) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
handler.ServeHTTP(c.Writer, c.Request)
|
||||
}
|
||||
}
|
||||
|
||||
type HttpServer struct {
|
||||
Gin *gin.Engine
|
||||
apiRouter *router.Api
|
||||
swaggerRouter *router.SwaggerRouter
|
||||
middleware *httpHandler.Middleware
|
||||
}
|
||||
|
||||
// NewHTTPServer new http server.
|
||||
func NewHTTPServer(
|
||||
config *conf.Config,
|
||||
apiRouter *router.Api,
|
||||
swaggerRouter *router.SwaggerRouter,
|
||||
middleware *httpHandler.Middleware,
|
||||
) *HttpServer {
|
||||
if config.Debug.Enabled {
|
||||
gin.SetMode(gin.DebugMode)
|
||||
} else {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
|
||||
r := gin.New()
|
||||
r.Use(gin.Recovery())
|
||||
r.Use(middleware.GinLogger.GinLogger)
|
||||
|
||||
return &HttpServer{
|
||||
Gin: r,
|
||||
apiRouter: apiRouter,
|
||||
swaggerRouter: swaggerRouter,
|
||||
middleware: middleware,
|
||||
}
|
||||
}
|
||||
|
||||
func (hs *HttpServer) AllowAllCors() {
|
||||
var config = cors.DefaultConfig()
|
||||
config.AllowAllOrigins = true
|
||||
config.AllowCredentials = true
|
||||
config.AllowMethods = []string{"GET", "POST", "PATCH", "PUT", "DELETE", "OPTIONS"}
|
||||
config.AllowHeaders = []string{"Origin", "Content-Length", "Content-Type", "Cookie", "X-Requested-With", "X-Auth-Token", "Authorization"}
|
||||
config.MaxAge = 12 * time.Hour
|
||||
|
||||
hs.Gin.Use(cors.New(config))
|
||||
}
|
||||
|
||||
func (hs *HttpServer) BizRouter() *gin.Engine {
|
||||
hs.AllowAllCors()
|
||||
|
||||
rootGroup := hs.Gin.Group("")
|
||||
|
||||
// swagger
|
||||
hs.swaggerRouter.Register(rootGroup)
|
||||
|
||||
apiV1 := rootGroup.Group("/api/v1")
|
||||
{
|
||||
//apiV1.Use(corsMiddleWare)
|
||||
apiV1.Use(hs.middleware.JSONResponse.ContentTypeJSON)
|
||||
apiV1.Use(hs.middleware.Auth.RequireJWTIDToken)
|
||||
hs.apiRouter.InitApiRouter(apiV1)
|
||||
}
|
||||
|
||||
apiV1NoAuth := rootGroup.Group("/api/v1")
|
||||
{
|
||||
//apiV1.Use(corsMiddleWare)
|
||||
hs.apiRouter.InitNoAuthApiRouter(apiV1NoAuth)
|
||||
}
|
||||
|
||||
hs.Gin.NoRoute(func(ctx *gin.Context) {
|
||||
schema.NewResponse(ctx).Status(http.StatusNotFound).Error(consts.ErrPageNotFound).Send()
|
||||
})
|
||||
|
||||
return hs.Gin
|
||||
}
|
||||
|
||||
func (hs *HttpServer) MetricRouter() *gin.Engine {
|
||||
r := gin.New()
|
||||
r.Use(gin.Recovery())
|
||||
|
||||
metricGroup := r.Group("")
|
||||
// prometheus
|
||||
metricGroup.GET("/metrics", promHandler(promhttp.Handler()))
|
||||
metricGroup.GET("/healthz", func(ctx *gin.Context) { ctx.String(200, "OK") })
|
||||
|
||||
return r
|
||||
}
|
16
internal/batch/provider.go
Normal file
16
internal/batch/provider.go
Normal file
@ -0,0 +1,16 @@
|
||||
package batch
|
||||
|
||||
import (
|
||||
"go-template/internal/base/logger"
|
||||
)
|
||||
|
||||
type Batch struct {
|
||||
logger *logger.Logger
|
||||
}
|
||||
|
||||
func NewBatch(
|
||||
logger *logger.Logger,
|
||||
) *Batch {
|
||||
//base.NewApplication()
|
||||
return &Batch{logger}
|
||||
}
|
103
internal/dao/gen.go
Normal file
103
internal/dao/gen.go
Normal file
@ -0,0 +1,103 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"gorm.io/gen"
|
||||
|
||||
"gorm.io/plugin/dbresolver"
|
||||
)
|
||||
|
||||
var (
|
||||
Q = new(Query)
|
||||
User *user
|
||||
)
|
||||
|
||||
func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
|
||||
*Q = *Use(db, opts...)
|
||||
User = &Q.User
|
||||
}
|
||||
|
||||
func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
|
||||
return &Query{
|
||||
db: db,
|
||||
User: newUser(db, opts...),
|
||||
}
|
||||
}
|
||||
|
||||
type Query struct {
|
||||
db *gorm.DB
|
||||
|
||||
User user
|
||||
}
|
||||
|
||||
func (q *Query) Available() bool { return q.db != nil }
|
||||
|
||||
func (q *Query) clone(db *gorm.DB) *Query {
|
||||
return &Query{
|
||||
db: db,
|
||||
User: q.User.clone(db),
|
||||
}
|
||||
}
|
||||
|
||||
func (q *Query) ReadDB() *Query {
|
||||
return q.ReplaceDB(q.db.Clauses(dbresolver.Read))
|
||||
}
|
||||
|
||||
func (q *Query) WriteDB() *Query {
|
||||
return q.ReplaceDB(q.db.Clauses(dbresolver.Write))
|
||||
}
|
||||
|
||||
func (q *Query) ReplaceDB(db *gorm.DB) *Query {
|
||||
return &Query{
|
||||
db: db,
|
||||
User: q.User.replaceDB(db),
|
||||
}
|
||||
}
|
||||
|
||||
type queryCtx struct {
|
||||
User IUserDo
|
||||
}
|
||||
|
||||
func (q *Query) WithContext(ctx context.Context) *queryCtx {
|
||||
return &queryCtx{
|
||||
User: q.User.WithContext(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
func (q *Query) Transaction(fc func(tx *Query) error, opts ...*sql.TxOptions) error {
|
||||
return q.db.Transaction(func(tx *gorm.DB) error { return fc(q.clone(tx)) }, opts...)
|
||||
}
|
||||
|
||||
func (q *Query) Begin(opts ...*sql.TxOptions) *QueryTx {
|
||||
tx := q.db.Begin(opts...)
|
||||
return &QueryTx{Query: q.clone(tx), Error: tx.Error}
|
||||
}
|
||||
|
||||
type QueryTx struct {
|
||||
*Query
|
||||
Error error
|
||||
}
|
||||
|
||||
func (q *QueryTx) Commit() error {
|
||||
return q.db.Commit().Error
|
||||
}
|
||||
|
||||
func (q *QueryTx) Rollback() error {
|
||||
return q.db.Rollback().Error
|
||||
}
|
||||
|
||||
func (q *QueryTx) SavePoint(name string) error {
|
||||
return q.db.SavePoint(name).Error
|
||||
}
|
||||
|
||||
func (q *QueryTx) RollbackTo(name string) error {
|
||||
return q.db.RollbackTo(name).Error
|
||||
}
|
7
internal/dao/provider.go
Normal file
7
internal/dao/provider.go
Normal file
@ -0,0 +1,7 @@
|
||||
package dao
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
func NewQuery(db *gorm.DB) *Query {
|
||||
return Use(db)
|
||||
}
|
392
internal/dao/users.gen.go
Normal file
392
internal/dao/users.gen.go
Normal file
@ -0,0 +1,392 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
"gorm.io/gorm/schema"
|
||||
|
||||
"gorm.io/gen"
|
||||
"gorm.io/gen/field"
|
||||
|
||||
"gorm.io/plugin/dbresolver"
|
||||
|
||||
"go-template/internal/entity"
|
||||
)
|
||||
|
||||
func newUser(db *gorm.DB, opts ...gen.DOOption) user {
|
||||
_user := user{}
|
||||
|
||||
_user.userDo.UseDB(db, opts...)
|
||||
_user.userDo.UseModel(&entity.User{})
|
||||
|
||||
tableName := _user.userDo.TableName()
|
||||
_user.ALL = field.NewAsterisk(tableName)
|
||||
_user.Id = field.NewUint(tableName, "id")
|
||||
_user.CreatedAt = field.NewTime(tableName, "created_at")
|
||||
_user.UpdatedAt = field.NewTime(tableName, "updated_at")
|
||||
_user.Name = field.NewString(tableName, "name")
|
||||
|
||||
_user.fillFieldMap()
|
||||
|
||||
return _user
|
||||
}
|
||||
|
||||
type user struct {
|
||||
userDo
|
||||
|
||||
ALL field.Asterisk
|
||||
Id field.Uint
|
||||
CreatedAt field.Time
|
||||
UpdatedAt field.Time
|
||||
Name field.String
|
||||
|
||||
fieldMap map[string]field.Expr
|
||||
}
|
||||
|
||||
func (u user) Table(newTableName string) *user {
|
||||
u.userDo.UseTable(newTableName)
|
||||
return u.updateTableName(newTableName)
|
||||
}
|
||||
|
||||
func (u user) As(alias string) *user {
|
||||
u.userDo.DO = *(u.userDo.As(alias).(*gen.DO))
|
||||
return u.updateTableName(alias)
|
||||
}
|
||||
|
||||
func (u *user) updateTableName(table string) *user {
|
||||
u.ALL = field.NewAsterisk(table)
|
||||
u.Id = field.NewUint(table, "id")
|
||||
u.CreatedAt = field.NewTime(table, "created_at")
|
||||
u.UpdatedAt = field.NewTime(table, "updated_at")
|
||||
u.Name = field.NewString(table, "name")
|
||||
|
||||
u.fillFieldMap()
|
||||
|
||||
return u
|
||||
}
|
||||
|
||||
func (u *user) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||
_f, ok := u.fieldMap[fieldName]
|
||||
if !ok || _f == nil {
|
||||
return nil, false
|
||||
}
|
||||
_oe, ok := _f.(field.OrderExpr)
|
||||
return _oe, ok
|
||||
}
|
||||
|
||||
func (u *user) fillFieldMap() {
|
||||
u.fieldMap = make(map[string]field.Expr, 4)
|
||||
u.fieldMap["id"] = u.Id
|
||||
u.fieldMap["created_at"] = u.CreatedAt
|
||||
u.fieldMap["updated_at"] = u.UpdatedAt
|
||||
u.fieldMap["name"] = u.Name
|
||||
}
|
||||
|
||||
func (u user) clone(db *gorm.DB) user {
|
||||
u.userDo.ReplaceConnPool(db.Statement.ConnPool)
|
||||
return u
|
||||
}
|
||||
|
||||
func (u user) replaceDB(db *gorm.DB) user {
|
||||
u.userDo.ReplaceDB(db)
|
||||
return u
|
||||
}
|
||||
|
||||
type userDo struct{ gen.DO }
|
||||
|
||||
type IUserDo interface {
|
||||
gen.SubQuery
|
||||
Debug() IUserDo
|
||||
WithContext(ctx context.Context) IUserDo
|
||||
WithResult(fc func(tx gen.Dao)) gen.ResultInfo
|
||||
ReplaceDB(db *gorm.DB)
|
||||
ReadDB() IUserDo
|
||||
WriteDB() IUserDo
|
||||
As(alias string) gen.Dao
|
||||
Session(config *gorm.Session) IUserDo
|
||||
Columns(cols ...field.Expr) gen.Columns
|
||||
Clauses(conds ...clause.Expression) IUserDo
|
||||
Not(conds ...gen.Condition) IUserDo
|
||||
Or(conds ...gen.Condition) IUserDo
|
||||
Select(conds ...field.Expr) IUserDo
|
||||
Where(conds ...gen.Condition) IUserDo
|
||||
Order(conds ...field.Expr) IUserDo
|
||||
Distinct(cols ...field.Expr) IUserDo
|
||||
Omit(cols ...field.Expr) IUserDo
|
||||
Join(table schema.Tabler, on ...field.Expr) IUserDo
|
||||
LeftJoin(table schema.Tabler, on ...field.Expr) IUserDo
|
||||
RightJoin(table schema.Tabler, on ...field.Expr) IUserDo
|
||||
Group(cols ...field.Expr) IUserDo
|
||||
Having(conds ...gen.Condition) IUserDo
|
||||
Limit(limit int) IUserDo
|
||||
Offset(offset int) IUserDo
|
||||
Count() (count int64, err error)
|
||||
Scopes(funcs ...func(gen.Dao) gen.Dao) IUserDo
|
||||
Unscoped() IUserDo
|
||||
Create(values ...*entity.User) error
|
||||
CreateInBatches(values []*entity.User, batchSize int) error
|
||||
Save(values ...*entity.User) error
|
||||
First() (*entity.User, error)
|
||||
Take() (*entity.User, error)
|
||||
Last() (*entity.User, error)
|
||||
Find() ([]*entity.User, error)
|
||||
FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*entity.User, err error)
|
||||
FindInBatches(result *[]*entity.User, batchSize int, fc func(tx gen.Dao, batch int) error) error
|
||||
Pluck(column field.Expr, dest interface{}) error
|
||||
Delete(...*entity.User) (info gen.ResultInfo, err error)
|
||||
Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
|
||||
Updates(value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
|
||||
UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateFrom(q gen.SubQuery) gen.Dao
|
||||
Attrs(attrs ...field.AssignExpr) IUserDo
|
||||
Assign(attrs ...field.AssignExpr) IUserDo
|
||||
Joins(fields ...field.RelationField) IUserDo
|
||||
Preload(fields ...field.RelationField) IUserDo
|
||||
FirstOrInit() (*entity.User, error)
|
||||
FirstOrCreate() (*entity.User, error)
|
||||
FindByPage(offset int, limit int) (result []*entity.User, count int64, err error)
|
||||
ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
|
||||
Scan(result interface{}) (err error)
|
||||
Returning(value interface{}, columns ...string) IUserDo
|
||||
UnderlyingDB() *gorm.DB
|
||||
schema.Tabler
|
||||
}
|
||||
|
||||
func (u userDo) Debug() IUserDo {
|
||||
return u.withDO(u.DO.Debug())
|
||||
}
|
||||
|
||||
func (u userDo) WithContext(ctx context.Context) IUserDo {
|
||||
return u.withDO(u.DO.WithContext(ctx))
|
||||
}
|
||||
|
||||
func (u userDo) ReadDB() IUserDo {
|
||||
return u.Clauses(dbresolver.Read)
|
||||
}
|
||||
|
||||
func (u userDo) WriteDB() IUserDo {
|
||||
return u.Clauses(dbresolver.Write)
|
||||
}
|
||||
|
||||
func (u userDo) Session(config *gorm.Session) IUserDo {
|
||||
return u.withDO(u.DO.Session(config))
|
||||
}
|
||||
|
||||
func (u userDo) Clauses(conds ...clause.Expression) IUserDo {
|
||||
return u.withDO(u.DO.Clauses(conds...))
|
||||
}
|
||||
|
||||
func (u userDo) Returning(value interface{}, columns ...string) IUserDo {
|
||||
return u.withDO(u.DO.Returning(value, columns...))
|
||||
}
|
||||
|
||||
func (u userDo) Not(conds ...gen.Condition) IUserDo {
|
||||
return u.withDO(u.DO.Not(conds...))
|
||||
}
|
||||
|
||||
func (u userDo) Or(conds ...gen.Condition) IUserDo {
|
||||
return u.withDO(u.DO.Or(conds...))
|
||||
}
|
||||
|
||||
func (u userDo) Select(conds ...field.Expr) IUserDo {
|
||||
return u.withDO(u.DO.Select(conds...))
|
||||
}
|
||||
|
||||
func (u userDo) Where(conds ...gen.Condition) IUserDo {
|
||||
return u.withDO(u.DO.Where(conds...))
|
||||
}
|
||||
|
||||
func (u userDo) Order(conds ...field.Expr) IUserDo {
|
||||
return u.withDO(u.DO.Order(conds...))
|
||||
}
|
||||
|
||||
func (u userDo) Distinct(cols ...field.Expr) IUserDo {
|
||||
return u.withDO(u.DO.Distinct(cols...))
|
||||
}
|
||||
|
||||
func (u userDo) Omit(cols ...field.Expr) IUserDo {
|
||||
return u.withDO(u.DO.Omit(cols...))
|
||||
}
|
||||
|
||||
func (u userDo) Join(table schema.Tabler, on ...field.Expr) IUserDo {
|
||||
return u.withDO(u.DO.Join(table, on...))
|
||||
}
|
||||
|
||||
func (u userDo) LeftJoin(table schema.Tabler, on ...field.Expr) IUserDo {
|
||||
return u.withDO(u.DO.LeftJoin(table, on...))
|
||||
}
|
||||
|
||||
func (u userDo) RightJoin(table schema.Tabler, on ...field.Expr) IUserDo {
|
||||
return u.withDO(u.DO.RightJoin(table, on...))
|
||||
}
|
||||
|
||||
func (u userDo) Group(cols ...field.Expr) IUserDo {
|
||||
return u.withDO(u.DO.Group(cols...))
|
||||
}
|
||||
|
||||
func (u userDo) Having(conds ...gen.Condition) IUserDo {
|
||||
return u.withDO(u.DO.Having(conds...))
|
||||
}
|
||||
|
||||
func (u userDo) Limit(limit int) IUserDo {
|
||||
return u.withDO(u.DO.Limit(limit))
|
||||
}
|
||||
|
||||
func (u userDo) Offset(offset int) IUserDo {
|
||||
return u.withDO(u.DO.Offset(offset))
|
||||
}
|
||||
|
||||
func (u userDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IUserDo {
|
||||
return u.withDO(u.DO.Scopes(funcs...))
|
||||
}
|
||||
|
||||
func (u userDo) Unscoped() IUserDo {
|
||||
return u.withDO(u.DO.Unscoped())
|
||||
}
|
||||
|
||||
func (u userDo) Create(values ...*entity.User) error {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
return u.DO.Create(values)
|
||||
}
|
||||
|
||||
func (u userDo) CreateInBatches(values []*entity.User, batchSize int) error {
|
||||
return u.DO.CreateInBatches(values, batchSize)
|
||||
}
|
||||
|
||||
// Save : !!! underlying implementation is different with GORM
|
||||
// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
|
||||
func (u userDo) Save(values ...*entity.User) error {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
return u.DO.Save(values)
|
||||
}
|
||||
|
||||
func (u userDo) First() (*entity.User, error) {
|
||||
if result, err := u.DO.First(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*entity.User), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (u userDo) Take() (*entity.User, error) {
|
||||
if result, err := u.DO.Take(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*entity.User), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (u userDo) Last() (*entity.User, error) {
|
||||
if result, err := u.DO.Last(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*entity.User), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (u userDo) Find() ([]*entity.User, error) {
|
||||
result, err := u.DO.Find()
|
||||
return result.([]*entity.User), err
|
||||
}
|
||||
|
||||
func (u userDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*entity.User, err error) {
|
||||
buf := make([]*entity.User, 0, batchSize)
|
||||
err = u.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
|
||||
defer func() { results = append(results, buf...) }()
|
||||
return fc(tx, batch)
|
||||
})
|
||||
return results, err
|
||||
}
|
||||
|
||||
func (u userDo) FindInBatches(result *[]*entity.User, batchSize int, fc func(tx gen.Dao, batch int) error) error {
|
||||
return u.DO.FindInBatches(result, batchSize, fc)
|
||||
}
|
||||
|
||||
func (u userDo) Attrs(attrs ...field.AssignExpr) IUserDo {
|
||||
return u.withDO(u.DO.Attrs(attrs...))
|
||||
}
|
||||
|
||||
func (u userDo) Assign(attrs ...field.AssignExpr) IUserDo {
|
||||
return u.withDO(u.DO.Assign(attrs...))
|
||||
}
|
||||
|
||||
func (u userDo) Joins(fields ...field.RelationField) IUserDo {
|
||||
for _, _f := range fields {
|
||||
u = *u.withDO(u.DO.Joins(_f))
|
||||
}
|
||||
return &u
|
||||
}
|
||||
|
||||
func (u userDo) Preload(fields ...field.RelationField) IUserDo {
|
||||
for _, _f := range fields {
|
||||
u = *u.withDO(u.DO.Preload(_f))
|
||||
}
|
||||
return &u
|
||||
}
|
||||
|
||||
func (u userDo) FirstOrInit() (*entity.User, error) {
|
||||
if result, err := u.DO.FirstOrInit(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*entity.User), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (u userDo) FirstOrCreate() (*entity.User, error) {
|
||||
if result, err := u.DO.FirstOrCreate(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*entity.User), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (u userDo) FindByPage(offset int, limit int) (result []*entity.User, count int64, err error) {
|
||||
result, err = u.Offset(offset).Limit(limit).Find()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if size := len(result); 0 < limit && 0 < size && size < limit {
|
||||
count = int64(size + offset)
|
||||
return
|
||||
}
|
||||
|
||||
count, err = u.Offset(-1).Limit(-1).Count()
|
||||
return
|
||||
}
|
||||
|
||||
func (u userDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
|
||||
count, err = u.Count()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = u.Offset(offset).Limit(limit).Scan(result)
|
||||
return
|
||||
}
|
||||
|
||||
func (u userDo) Scan(result interface{}) (err error) {
|
||||
return u.DO.Scan(result)
|
||||
}
|
||||
|
||||
func (u userDo) Delete(models ...*entity.User) (result gen.ResultInfo, err error) {
|
||||
return u.DO.Delete(models)
|
||||
}
|
||||
|
||||
func (u *userDo) withDO(do gen.Dao) *userDo {
|
||||
u.DO = *do.(*gen.DO)
|
||||
return u
|
||||
}
|
14
internal/entity/Model.go
Normal file
14
internal/entity/Model.go
Normal file
@ -0,0 +1,14 @@
|
||||
package entity
|
||||
|
||||
import (
|
||||
"go-template/internal/schema"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Model 是所有 entity 的基类,后期要将所有的 Base 改成这种形式
|
||||
type Model struct {
|
||||
Id schema.EntityId `gorm:"primarykey" json:"id"`
|
||||
CreatedAt time.Time `gorm:"autoUpdateTime:milli" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime:milli" json:"updated_at"`
|
||||
//DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||
}
|
10
internal/entity/User.go
Normal file
10
internal/entity/User.go
Normal file
@ -0,0 +1,10 @@
|
||||
package entity
|
||||
|
||||
type User struct {
|
||||
Model
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (u *User) TableName() string {
|
||||
return "user"
|
||||
}
|
11
internal/handler/grpc/documents/document.go
Normal file
11
internal/handler/grpc/documents/document.go
Normal file
@ -0,0 +1,11 @@
|
||||
package documents
|
||||
|
||||
import (
|
||||
"context"
|
||||
"go-template/pkg/protos/documentService"
|
||||
)
|
||||
|
||||
func (d *DocumentService) ListDocuments(ctx context.Context, req *documentService.ListDocumentsRequest) (*documentService.ListDocumentsResponse, error) {
|
||||
|
||||
return &documentService.ListDocumentsResponse{}, nil
|
||||
}
|
18
internal/handler/grpc/documents/provider.go
Normal file
18
internal/handler/grpc/documents/provider.go
Normal file
@ -0,0 +1,18 @@
|
||||
package documents
|
||||
|
||||
import (
|
||||
"go-template/internal/dao"
|
||||
"go-template/pkg/protos/documentService"
|
||||
)
|
||||
|
||||
type DocumentService struct {
|
||||
documentService.UnimplementedDocumentServiceServer
|
||||
dao *dao.Query
|
||||
}
|
||||
|
||||
func NewDocumentService(dao *dao.Query) *DocumentService {
|
||||
return &DocumentService{
|
||||
documentService.UnimplementedDocumentServiceServer{},
|
||||
dao,
|
||||
}
|
||||
}
|
40
internal/handler/grpc/interceptor/auth.go
Normal file
40
internal/handler/grpc/interceptor/auth.go
Normal file
@ -0,0 +1,40 @@
|
||||
package interceptor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/auth"
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging"
|
||||
"go-template/internal/schema"
|
||||
auth2 "go-template/internal/service/auth"
|
||||
"go-template/pkg/consts"
|
||||
)
|
||||
|
||||
type Auth struct {
|
||||
authService *auth2.Service
|
||||
}
|
||||
|
||||
func NewAuth(authService *auth2.Service) *Auth {
|
||||
return &Auth{
|
||||
authService: authService,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Auth) JwtAuth(ctx context.Context) (context.Context, error) {
|
||||
tokenString, err := auth.AuthFromMD(ctx, "bearer")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
token, err := a.authService.AuthFromToken(schema.JWTIDToken, tokenString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !token.Valid {
|
||||
return nil, consts.ErrNotValidToken
|
||||
}
|
||||
|
||||
ctx = logging.InjectFields(ctx, logging.Fields{"auth.sub", token.Token.Sub})
|
||||
|
||||
return a.authService.SetUser(ctx, token), nil
|
||||
}
|
56
internal/handler/grpc/interceptor/zap_logger.go
Normal file
56
internal/handler/grpc/interceptor/zap_logger.go
Normal file
@ -0,0 +1,56 @@
|
||||
package interceptor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging"
|
||||
"go-template/internal/base/logger"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type Logger struct {
|
||||
Logger *logger.Logger
|
||||
}
|
||||
|
||||
func NewLogger(logger *logger.Logger) *Logger {
|
||||
return &Logger{
|
||||
Logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Logger) ZapLogInterceptor() logging.Logger {
|
||||
return logging.LoggerFunc(func(ctx context.Context, lvl logging.Level, msg string, fields ...any) {
|
||||
f := make([]zap.Field, 0, len(fields)/2)
|
||||
|
||||
for i := 0; i < len(fields); i += 2 {
|
||||
key := fields[i]
|
||||
value := fields[i+1]
|
||||
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
f = append(f, zap.String(key.(string), v))
|
||||
case int:
|
||||
f = append(f, zap.Int(key.(string), v))
|
||||
case bool:
|
||||
f = append(f, zap.Bool(key.(string), v))
|
||||
default:
|
||||
f = append(f, zap.Any(key.(string), v))
|
||||
}
|
||||
}
|
||||
|
||||
logger2 := l.Logger.Logger.WithOptions(zap.AddCallerSkip(1)).With(f...)
|
||||
|
||||
switch lvl {
|
||||
case logging.LevelDebug:
|
||||
logger2.Debug(msg)
|
||||
case logging.LevelInfo:
|
||||
logger2.Info(msg)
|
||||
case logging.LevelWarn:
|
||||
logger2.Warn(msg)
|
||||
case logging.LevelError:
|
||||
logger2.Error(msg)
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown level %v", lvl))
|
||||
}
|
||||
})
|
||||
}
|
47
internal/handler/grpc/provider.go
Normal file
47
internal/handler/grpc/provider.go
Normal file
@ -0,0 +1,47 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"github.com/google/wire"
|
||||
"leafdev.top/Leaf/leaf-library/internal/handler/grpc/documents"
|
||||
"leafdev.top/Leaf/leaf-library/internal/handler/grpc/interceptor"
|
||||
)
|
||||
|
||||
var ProviderSet = wire.NewSet(
|
||||
interceptor.NewAuth,
|
||||
interceptor.NewLogger,
|
||||
documents.NewDocumentService,
|
||||
|
||||
NewInterceptor,
|
||||
NewHandler,
|
||||
)
|
||||
|
||||
func NewHandler(
|
||||
documentService *documents.DocumentService,
|
||||
interceptor2 *Interceptor,
|
||||
) *Handlers {
|
||||
return &Handlers{
|
||||
DocumentService: documentService,
|
||||
Interceptor: interceptor2,
|
||||
}
|
||||
}
|
||||
|
||||
type Handlers struct {
|
||||
DocumentService *documents.DocumentService
|
||||
Interceptor *Interceptor
|
||||
}
|
||||
|
||||
type Interceptor struct {
|
||||
Auth *interceptor.Auth
|
||||
Logger *interceptor.Logger
|
||||
}
|
||||
|
||||
func NewInterceptor(
|
||||
Auth *interceptor.Auth,
|
||||
Logger *interceptor.Logger,
|
||||
) *Interceptor {
|
||||
return &Interceptor{
|
||||
Auth: Auth,
|
||||
Logger: Logger,
|
||||
}
|
||||
|
||||
}
|
28
internal/handler/handler.go
Normal file
28
internal/handler/handler.go
Normal file
@ -0,0 +1,28 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"github.com/google/wire"
|
||||
"go-template/internal/handler/grpc"
|
||||
"go-template/internal/handler/http"
|
||||
)
|
||||
|
||||
var ProviderSet = wire.NewSet(
|
||||
grpc.ProviderSet,
|
||||
http.ProviderSet,
|
||||
NewHandler,
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
GRPC *grpc.Handlers
|
||||
HTTP *http.Handlers
|
||||
}
|
||||
|
||||
func NewHandler(
|
||||
grpcHandlers *grpc.Handlers,
|
||||
httpHandlers *http.Handlers,
|
||||
) *Handler {
|
||||
return &Handler{
|
||||
GRPC: grpcHandlers,
|
||||
HTTP: httpHandlers,
|
||||
}
|
||||
}
|
42
internal/handler/http/controller/v1/test.go
Normal file
42
internal/handler/http/controller/v1/test.go
Normal file
@ -0,0 +1,42 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"go-template/internal/schema"
|
||||
"go-template/internal/service/auth"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type UserController struct {
|
||||
authService *auth.Service
|
||||
}
|
||||
|
||||
func NewUserController(authService *auth.Service) *UserController {
|
||||
return &UserController{authService}
|
||||
}
|
||||
|
||||
// Test godoc
|
||||
// @Summary Greet
|
||||
// @Description 测试接口,将会返回当前用户的信息
|
||||
// @Tags ping
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security ApiKeyAuth
|
||||
// @deprecated true
|
||||
// @Success 200 {object} schema.ResponseBody{data=schema.CurrentUserResponse}
|
||||
// @Failure 400 {object} schema.ResponseBody
|
||||
// @Router /api/v1/ping [get]
|
||||
func (u *UserController) Test(c *gin.Context) {
|
||||
user := u.authService.GetUser(c)
|
||||
|
||||
var currentUserResponse = &schema.CurrentUserResponse{
|
||||
IP: c.ClientIP(),
|
||||
Valid: user.Valid,
|
||||
UserEmail: user.Token.Email,
|
||||
UserId: user.Token.Sub,
|
||||
UserName: user.Token.Name,
|
||||
}
|
||||
|
||||
schema.NewResponse(c).Status(http.StatusOK).Data(currentUserResponse).Send()
|
||||
}
|
45
internal/handler/http/middleware/auth.go
Normal file
45
internal/handler/http/middleware/auth.go
Normal file
@ -0,0 +1,45 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"go-template/internal/schema"
|
||||
"go-template/internal/service/auth"
|
||||
"go-template/pkg/consts"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type AuthMiddleware struct {
|
||||
authService *auth.Service
|
||||
}
|
||||
|
||||
func NewAuthMiddleware(authService *auth.Service) *AuthMiddleware {
|
||||
return &AuthMiddleware{
|
||||
authService,
|
||||
}
|
||||
}
|
||||
|
||||
func (a AuthMiddleware) RequireJWTIDToken(c *gin.Context) {
|
||||
user, err := a.authService.GinMiddlewareAuth(schema.JWTIDToken, c)
|
||||
|
||||
if err != nil {
|
||||
c.Abort()
|
||||
schema.NewResponse(c).Error(err).Status(http.StatusUnauthorized).Send()
|
||||
return
|
||||
}
|
||||
|
||||
c.Set(consts.AuthMiddlewareKey, user)
|
||||
c.Next()
|
||||
}
|
||||
|
||||
func (a AuthMiddleware) RequireJWTAccessToken(c *gin.Context) {
|
||||
user, err := a.authService.GinMiddlewareAuth(schema.JWTAccessToken, c)
|
||||
if err != nil {
|
||||
c.Abort()
|
||||
schema.NewResponse(c).Error(err).Status(http.StatusUnauthorized).Send()
|
||||
return
|
||||
}
|
||||
|
||||
c.Set(consts.AuthMiddlewareKey, user)
|
||||
c.Next()
|
||||
}
|
17
internal/handler/http/middleware/json_response.go
Normal file
17
internal/handler/http/middleware/json_response.go
Normal file
@ -0,0 +1,17 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type JSONResponseMiddleware struct {
|
||||
}
|
||||
|
||||
func (*JSONResponseMiddleware) ContentTypeJSON(c *gin.Context) {
|
||||
c.Header("Content-Type", "application/json; charset=utf-8")
|
||||
c.Next()
|
||||
}
|
||||
|
||||
func NewJSONResponseMiddleware() *JSONResponseMiddleware {
|
||||
return &JSONResponseMiddleware{}
|
||||
}
|
86
internal/handler/http/middleware/zap_logger.go
Normal file
86
internal/handler/http/middleware/zap_logger.go
Normal file
@ -0,0 +1,86 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"go-template/internal/base/logger"
|
||||
"go.uber.org/zap"
|
||||
"time"
|
||||
)
|
||||
|
||||
type GinLoggerMiddleware struct {
|
||||
logger *logger.Logger
|
||||
}
|
||||
|
||||
func NewGinLoggerMiddleware(logger *logger.Logger) *GinLoggerMiddleware {
|
||||
return &GinLoggerMiddleware{
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
// GinLogger 接收gin框架默认的日志
|
||||
func (l *GinLoggerMiddleware) GinLogger(c *gin.Context) {
|
||||
start := time.Now()
|
||||
path := c.Request.URL.Path
|
||||
query := c.Request.URL.RawQuery
|
||||
c.Next()
|
||||
|
||||
cost := time.Since(start)
|
||||
l.logger.Logger.Info(path,
|
||||
zap.Int("status", c.Writer.Status()),
|
||||
zap.String("method", c.Request.Method),
|
||||
zap.String("path", path),
|
||||
zap.String("query", query),
|
||||
zap.String("ip", c.ClientIP()),
|
||||
zap.String("user-agent", c.Request.UserAgent()),
|
||||
zap.String("errors", c.Errors.ByType(gin.ErrorTypePrivate).String()),
|
||||
zap.Duration("cost", cost),
|
||||
)
|
||||
}
|
||||
|
||||
//
|
||||
//// GinRecovery recover掉项目可能出现的panic
|
||||
//func GinRecovery(logger *zap.Logger, stack bool) gin.HandlerFunc {
|
||||
// return func(c *gin.Context) {
|
||||
// defer func() {
|
||||
// if err := recover(); err != nil {
|
||||
// // Check for a broken connection, as it is not really a
|
||||
// // condition that warrants a panic stack trace.
|
||||
// var brokenPipe bool
|
||||
// if ne, ok := err.(*net.OpError); ok {
|
||||
// if se, ok := ne.Err.(*os.SyscallError); ok {
|
||||
// if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
|
||||
// brokenPipe = true
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// httpRequest, _ := httputil.DumpRequest(c.Request, false)
|
||||
// if brokenPipe {
|
||||
// logger.Error(c.Request.URL.Path,
|
||||
// zap.Any("error", err),
|
||||
// zap.String("request", string(httpRequest)),
|
||||
// )
|
||||
// // If the connection is dead, we can't write a status to it.
|
||||
// c.Error(err.(error)) // nolint: errcheck
|
||||
// c.Abort()
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// if stack {
|
||||
// logger.Error("[Recovery from panic]",
|
||||
// zap.Any("error", err),
|
||||
// zap.String("request", string(httpRequest)),
|
||||
// zap.String("stack", string(debug.Stack())),
|
||||
// )
|
||||
// } else {
|
||||
// logger.Error("[Recovery from panic]",
|
||||
// zap.Any("error", err),
|
||||
// zap.String("request", string(httpRequest)),
|
||||
// )
|
||||
// }
|
||||
// c.AbortWithStatus(http.StatusInternalServerError)
|
||||
// }
|
||||
// }()
|
||||
// c.Next()
|
||||
// }
|
||||
//}
|
46
internal/handler/http/provider.go
Normal file
46
internal/handler/http/provider.go
Normal file
@ -0,0 +1,46 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"github.com/google/wire"
|
||||
v1 "go-template/internal/handler/http/controller/v1"
|
||||
"go-template/internal/handler/http/middleware"
|
||||
)
|
||||
|
||||
var ProviderSet = wire.NewSet(
|
||||
middleware.NewAuthMiddleware,
|
||||
middleware.NewGinLoggerMiddleware,
|
||||
middleware.NewJSONResponseMiddleware,
|
||||
NewMiddleware,
|
||||
v1.NewUserController,
|
||||
NewHandler,
|
||||
)
|
||||
|
||||
type Middleware struct {
|
||||
GinLogger *middleware.GinLoggerMiddleware
|
||||
Auth *middleware.AuthMiddleware
|
||||
JSONResponse *middleware.JSONResponseMiddleware
|
||||
}
|
||||
|
||||
func NewMiddleware(
|
||||
GinLogger *middleware.GinLoggerMiddleware,
|
||||
Auth *middleware.AuthMiddleware,
|
||||
JSONResponse *middleware.JSONResponseMiddleware,
|
||||
) *Middleware {
|
||||
return &Middleware{
|
||||
Auth: Auth,
|
||||
GinLogger: GinLogger,
|
||||
JSONResponse: JSONResponse,
|
||||
}
|
||||
}
|
||||
|
||||
type Handlers struct {
|
||||
User *v1.UserController
|
||||
}
|
||||
|
||||
func NewHandler(
|
||||
user *v1.UserController,
|
||||
) *Handlers {
|
||||
return &Handlers{
|
||||
User: user,
|
||||
}
|
||||
}
|
15
internal/migrations/1_setup.sql
Normal file
15
internal/migrations/1_setup.sql
Normal file
@ -0,0 +1,15 @@
|
||||
-- +goose Up
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `users` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`username` varchar(255) NOT NULL,
|
||||
`email` varchar(255) NOT NULL,
|
||||
`password` varchar(255) NOT NULL,
|
||||
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- +goose Down
|
||||
|
||||
DROP TABLE `users`;
|
11
internal/migrations/init.go
Normal file
11
internal/migrations/init.go
Normal file
@ -0,0 +1,11 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"go-template/internal/base/conf"
|
||||
)
|
||||
|
||||
//go:embed *.sql
|
||||
var MigrationFS embed.FS
|
||||
|
||||
var Config *conf.Config
|
38
internal/router/api.go
Normal file
38
internal/router/api.go
Normal file
@ -0,0 +1,38 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"go-template/internal/handler/http"
|
||||
)
|
||||
|
||||
// 两种方法都可以
|
||||
//type Api struct {
|
||||
// User *v1.UserController
|
||||
//}
|
||||
|
||||
type Api struct {
|
||||
HttpHandler *http.Handlers
|
||||
}
|
||||
|
||||
func NewApiRoute(
|
||||
//User *v1.UserController,
|
||||
HttpHandler *http.Handlers,
|
||||
) *Api {
|
||||
//return &Api{
|
||||
// User,
|
||||
//}
|
||||
|
||||
return &Api{
|
||||
HttpHandler,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Api) InitApiRouter(r *gin.RouterGroup) {
|
||||
//r.GET("/ping", a.User.Test)
|
||||
|
||||
r.GET("/ping", a.HttpHandler.User.Test)
|
||||
}
|
||||
|
||||
func (a *Api) InitNoAuthApiRouter(r *gin.RouterGroup) {
|
||||
|
||||
}
|
9
internal/router/provider.go
Normal file
9
internal/router/provider.go
Normal file
@ -0,0 +1,9 @@
|
||||
package router
|
||||
|
||||
import "github.com/google/wire"
|
||||
|
||||
// ProviderSetRouter is providers.
|
||||
var ProviderSetRouter = wire.NewSet(
|
||||
NewApiRoute,
|
||||
NewSwaggerRoute,
|
||||
)
|
21
internal/router/swagger.go
Normal file
21
internal/router/swagger.go
Normal file
@ -0,0 +1,21 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
_ "go-template/docs"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
swaggerFiles "github.com/swaggo/files"
|
||||
ginSwagger "github.com/swaggo/gin-swagger"
|
||||
)
|
||||
|
||||
type SwaggerRouter struct {
|
||||
//config *conf.Config
|
||||
}
|
||||
|
||||
func NewSwaggerRoute() *SwaggerRouter {
|
||||
return &SwaggerRouter{}
|
||||
}
|
||||
|
||||
func (a *SwaggerRouter) Register(r *gin.RouterGroup) {
|
||||
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||||
}
|
17
internal/schema/entity.go
Normal file
17
internal/schema/entity.go
Normal file
@ -0,0 +1,17 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type EntityId uint
|
||||
|
||||
//type EntityId int64
|
||||
|
||||
func (i EntityId) String() string {
|
||||
return strconv.FormatUint(uint64(i), 10)
|
||||
//return strconv.FormatInt(int64(i), 10)
|
||||
}
|
||||
func (i EntityId) Uint() uint {
|
||||
return uint(i)
|
||||
}
|
131
internal/schema/response.go
Normal file
131
internal/schema/response.go
Normal file
@ -0,0 +1,131 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type ResponseBody struct {
|
||||
Message string `json:"message"`
|
||||
Error string `json:"error"`
|
||||
Success bool `json:"success"`
|
||||
Data any `json:"data,omitempty"`
|
||||
Wrap bool `json:"-"`
|
||||
}
|
||||
|
||||
type HttpResponse struct {
|
||||
body *ResponseBody
|
||||
httpStatus int
|
||||
ctx *gin.Context
|
||||
}
|
||||
|
||||
func NewResponse(c *gin.Context) *HttpResponse {
|
||||
return &HttpResponse{
|
||||
body: &ResponseBody{
|
||||
Wrap: true,
|
||||
},
|
||||
httpStatus: 0,
|
||||
ctx: c,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *HttpResponse) Message(message string) *HttpResponse {
|
||||
r.body.Message = message
|
||||
|
||||
if r.httpStatus == 0 {
|
||||
r.httpStatus = http.StatusOK
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
// WithoutWrap 将不在 body 中包裹 data
|
||||
func (r *HttpResponse) WithoutWrap() *HttpResponse {
|
||||
r.body.Wrap = false
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *HttpResponse) Wrap() *HttpResponse {
|
||||
r.body.Wrap = true
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *HttpResponse) Data(data any) *HttpResponse {
|
||||
r.body.Data = data
|
||||
return r
|
||||
|
||||
}
|
||||
|
||||
func (r *HttpResponse) Error(err error) *HttpResponse {
|
||||
if err != nil {
|
||||
var errMsg = err.Error()
|
||||
|
||||
if errMsg == "EOF" {
|
||||
errMsg = "Request body is empty or missing some fields, make sure you have provided all the required fields"
|
||||
}
|
||||
|
||||
r.body.Error = errMsg
|
||||
|
||||
if r.httpStatus == 0 {
|
||||
r.httpStatus = http.StatusBadRequest
|
||||
}
|
||||
|
||||
if r.body.Message == "" {
|
||||
r.Message("Something went wrong")
|
||||
}
|
||||
r.body.Success = false
|
||||
}
|
||||
|
||||
return r
|
||||
|
||||
}
|
||||
|
||||
func (r *HttpResponse) Status(status int) *HttpResponse {
|
||||
r.httpStatus = status
|
||||
return r
|
||||
|
||||
}
|
||||
|
||||
func (r *HttpResponse) Send() {
|
||||
if r.httpStatus == 0 {
|
||||
r.httpStatus = http.StatusOK
|
||||
}
|
||||
|
||||
// if 20x or 20x, set success
|
||||
r.body.Success = r.httpStatus >= http.StatusOK && r.httpStatus < http.StatusMultipleChoices
|
||||
|
||||
if r.body.Wrap {
|
||||
r.ctx.JSON(r.httpStatus, r.body)
|
||||
return
|
||||
}
|
||||
|
||||
r.ctx.JSON(r.httpStatus, r.body.Data)
|
||||
}
|
||||
|
||||
func (r *HttpResponse) Abort() {
|
||||
r.ctx.Abort()
|
||||
}
|
||||
|
||||
//
|
||||
//func ResponseMessage(c *gin.Context, code int, message string, data interface{}) {
|
||||
// c.JSON(code, &ResponseBody{
|
||||
// Message: message,
|
||||
// Data: data,
|
||||
// })
|
||||
// c.Abort()
|
||||
//}
|
||||
//
|
||||
//func ResponseError(c *gin.Context, code int, err error) {
|
||||
// c.JSON(code, &ResponseBody{
|
||||
// Error: err.Error(),
|
||||
// })
|
||||
// c.Abort()
|
||||
//}
|
||||
//
|
||||
//func Response(c *gin.Context, code int, data interface{}) {
|
||||
// c.JSON(code, &ResponseBody{
|
||||
// Data: data,
|
||||
// })
|
||||
// c.Abort()
|
||||
//}
|
46
internal/schema/user.go
Normal file
46
internal/schema/user.go
Normal file
@ -0,0 +1,46 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type UserTokenInfo struct {
|
||||
Aud string `json:"aud"`
|
||||
Iss string `json:"iss"`
|
||||
Iat float64 `json:"iat"`
|
||||
Exp float64 `json:"exp"`
|
||||
Sub UserId `json:"sub" mapstructure:"-"`
|
||||
Scopes []string `json:"scopes"`
|
||||
Id int `json:"id"`
|
||||
Uuid string `json:"uuid"`
|
||||
Avatar string `json:"avatar"`
|
||||
Name string `json:"name"`
|
||||
EmailVerified bool `json:"email_verified"`
|
||||
RealNameVerified bool `json:"real_name_verified"`
|
||||
PhoneVerified bool `json:"phone_verified"`
|
||||
Email string `json:"email"`
|
||||
Phone string `json:"phone"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Token UserTokenInfo
|
||||
Valid bool
|
||||
}
|
||||
|
||||
type UserId string
|
||||
|
||||
func (u UserId) String() string {
|
||||
return string(u)
|
||||
}
|
||||
|
||||
type JWTTokenTypes string
|
||||
|
||||
const (
|
||||
JWTAccessToken JWTTokenTypes = "access_token"
|
||||
JWTIDToken JWTTokenTypes = "id_token"
|
||||
)
|
||||
|
||||
func (jwtTokenTypes JWTTokenTypes) String() string {
|
||||
return string(jwtTokenTypes)
|
||||
}
|
9
internal/schema/user_response.go
Normal file
9
internal/schema/user_response.go
Normal file
@ -0,0 +1,9 @@
|
||||
package schema
|
||||
|
||||
type CurrentUserResponse struct {
|
||||
IP string `json:"ip"`
|
||||
Valid bool `json:"valid"`
|
||||
UserEmail string `json:"userEmail"`
|
||||
UserId UserId `json:"userId"`
|
||||
UserName string `json:"userName"`
|
||||
}
|
136
internal/service/auth/auth.go
Normal file
136
internal/service/auth/auth.go
Normal file
@ -0,0 +1,136 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"go-template/internal/base/conf"
|
||||
"go-template/internal/base/logger"
|
||||
"go-template/internal/schema"
|
||||
"go-template/internal/service/jwks"
|
||||
"go-template/pkg/consts"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
config *conf.Config
|
||||
jwks *jwks.JWKS
|
||||
logger *logger.Logger
|
||||
}
|
||||
|
||||
func NewAuthService(config *conf.Config, jwks *jwks.JWKS, logger *logger.Logger) *Service {
|
||||
return &Service{
|
||||
config: config,
|
||||
jwks: jwks,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Service) GinMiddlewareAuth(tokenType schema.JWTTokenTypes, c *gin.Context) (*schema.User, error) {
|
||||
if a.config.Debug.Enabled {
|
||||
return a.parseUserJWT(tokenType, "")
|
||||
}
|
||||
|
||||
authorization := c.Request.Header.Get(consts.AuthHeader)
|
||||
|
||||
if authorization == "" {
|
||||
return nil, consts.ErrJWTFormatError
|
||||
}
|
||||
|
||||
authSplit := strings.Split(authorization, " ")
|
||||
if len(authSplit) != 2 {
|
||||
return nil, consts.ErrJWTFormatError
|
||||
}
|
||||
|
||||
if authSplit[0] != consts.AuthPrefix {
|
||||
return nil, consts.ErrNotBearerType
|
||||
}
|
||||
|
||||
return a.parseUserJWT(tokenType, authSplit[1])
|
||||
}
|
||||
|
||||
func (a *Service) AuthFromToken(tokenType schema.JWTTokenTypes, token string) (*schema.User, error) {
|
||||
if a.config.Debug.Enabled {
|
||||
return a.parseUserJWT(tokenType, "")
|
||||
}
|
||||
|
||||
return a.parseUserJWT(tokenType, token)
|
||||
}
|
||||
|
||||
func (a *Service) GetUserFromIdToken(idToken string) (*schema.User, error) {
|
||||
return a.parseUserJWT(schema.JWTIDToken, idToken)
|
||||
}
|
||||
|
||||
func (a *Service) GinUser(c *gin.Context) *schema.User {
|
||||
user, _ := c.Get(consts.AuthMiddlewareKey)
|
||||
return user.(*schema.User)
|
||||
}
|
||||
|
||||
func (a *Service) GetUserId(ctx context.Context) schema.UserId {
|
||||
user := a.GetUser(ctx)
|
||||
|
||||
return user.Token.Sub
|
||||
}
|
||||
|
||||
func (a *Service) GetUser(ctx context.Context) *schema.User {
|
||||
user := ctx.Value(consts.AuthMiddlewareKey)
|
||||
|
||||
return user.(*schema.User)
|
||||
}
|
||||
|
||||
func (a *Service) SetUser(ctx context.Context, user *schema.User) context.Context {
|
||||
context.WithValue(ctx, consts.AuthMiddlewareKey, user)
|
||||
return context.WithValue(ctx, consts.AuthMiddlewareKey, user)
|
||||
}
|
||||
|
||||
func (a *Service) parseUserJWT(tokenType schema.JWTTokenTypes, jwtToken string) (*schema.User, error) {
|
||||
var sub = consts.AnonymousUser
|
||||
var jwtIdToken = &schema.User{}
|
||||
|
||||
if a.config.Debug.Enabled {
|
||||
jwtIdToken.Token.Sub = sub
|
||||
jwtIdToken.Valid = true
|
||||
return jwtIdToken, nil
|
||||
} else {
|
||||
token, err := a.jwks.ParseJWT(jwtToken)
|
||||
if err != nil {
|
||||
return nil, consts.ErrNotValidToken
|
||||
}
|
||||
|
||||
subStr, err := token.Claims.GetSubject()
|
||||
if err != nil {
|
||||
return nil, consts.ErrNotValidToken
|
||||
}
|
||||
|
||||
//subInt, err := strconv.Atoi(subStr)
|
||||
//if err != nil {
|
||||
// return nil, consts.ErrNotValidToken
|
||||
//}
|
||||
|
||||
sub = schema.UserId(subStr)
|
||||
|
||||
// 如果 token.Header 中没有 typ
|
||||
if token.Header["typ"] == "" {
|
||||
return nil, consts.ErrEmptyResponse
|
||||
}
|
||||
|
||||
// 验证 token 类型
|
||||
if tokenType != "" && tokenType.String() != token.Header["typ"] {
|
||||
return nil, consts.ErrTokenError
|
||||
}
|
||||
|
||||
jwtIdToken.Valid = true
|
||||
|
||||
err = mapstructure.Decode(token.Claims, &jwtIdToken.Token)
|
||||
if err != nil {
|
||||
a.logger.Logger.Error("Failed to map token claims to JwtIDToken struct.\nError: " + err.Error())
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// 手动指定,因为 mapstructure 无法转换 UserID 类型
|
||||
jwtIdToken.Token.Sub = sub
|
||||
}
|
||||
|
||||
return jwtIdToken, nil
|
||||
}
|
14
internal/service/auth/compare.go
Normal file
14
internal/service/auth/compare.go
Normal file
@ -0,0 +1,14 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"go-template/internal/schema"
|
||||
)
|
||||
|
||||
type HasUserInterface interface {
|
||||
GetUserId() schema.UserId
|
||||
}
|
||||
|
||||
func (a *Service) Compare(ctx context.Context, entity HasUserInterface) bool {
|
||||
return entity.GetUserId() == a.GetUserId(ctx)
|
||||
}
|
108
internal/service/embedding/embedding.go
Normal file
108
internal/service/embedding/embedding.go
Normal file
@ -0,0 +1,108 @@
|
||||
package embedding
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
func (s *Service) TextEmbedding(ctx context.Context, input []string) ([][]float32, error) {
|
||||
|
||||
var r = make([][]float32, len(input)-1)
|
||||
|
||||
for _, v := range input {
|
||||
embedding2, err := s.OpenAI.CreateEmbedding(ctx, []string{v})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r = append(r, embedding2[0])
|
||||
|
||||
//embedding, err := s.getCache(ctx, v)
|
||||
//if err != nil {
|
||||
// return r, err
|
||||
//}
|
||||
//
|
||||
//if embedding != nil {
|
||||
// r = append(r, embedding)
|
||||
// continue
|
||||
//} else {
|
||||
// embedding2, err := s.OpenAI.CreateEmbedding(ctx, []string{v})
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// r = append(r, embedding2[0])
|
||||
//
|
||||
// err = s.setCache(ctx, v, embedding2[0])
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
//
|
||||
//func (s *Service) getCache(ctx context.Context, input string) ([]float32, error) {
|
||||
// md5Str, err := md5.Md5(input)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// c, err := s.dao.WithContext(ctx).Embedding.Where(s.dao.Embedding.TextMd5.Eq(md5Str)).
|
||||
// Where(s.dao.Embedding.EmbeddingModel.Eq(s.config.OpenAI.EmbeddingModel)).
|
||||
// Count()
|
||||
// if c == 0 {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// first, err := s.dao.WithContext(ctx).Embedding.Where(s.dao.Embedding.TextMd5.Eq(md5Str)).
|
||||
// Where(s.dao.Embedding.EmbeddingModel.Eq(s.config.OpenAI.EmbeddingModel)).
|
||||
// First()
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// // byte to float32
|
||||
// return first.Vector, nil
|
||||
//}
|
||||
//
|
||||
//func (s *Service) setCache(ctx context.Context, input string, embedding []float32) error {
|
||||
// md5Str, err := md5.Md5(input)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// // redis 锁
|
||||
// var key = "lock_" + md5Str
|
||||
// lock, err := s.redis.Locker.Obtain(ctx, key, 3*time.Second, nil)
|
||||
// if errors.Is(err, redislock.ErrNotObtained) {
|
||||
// s.Logger.Sugar.Warnf("redis lock %s not obtained", md5Str)
|
||||
// } else if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// defer func(lock *redislock.Lock, ctx context.Context) {
|
||||
// err := lock.Release(ctx)
|
||||
// if err != nil {
|
||||
// s.Logger.Sugar.Error(err)
|
||||
// }
|
||||
// }(lock, ctx)
|
||||
//
|
||||
// // 如果没有 cache,则设置
|
||||
// c, err := s.dao.WithContext(ctx).Embedding.Where(s.dao.Embedding.TextMd5.Eq(md5Str)).
|
||||
// Where(s.dao.Embedding.EmbeddingModel.Eq(s.config.OpenAI.EmbeddingModel)).
|
||||
// Count()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// if c == 0 {
|
||||
// return s.dao.WithContext(ctx).Embedding.Create(&entity.Embedding{
|
||||
// Text: input,
|
||||
// TextMd5: md5Str,
|
||||
// Vector: embedding,
|
||||
// EmbeddingModel: s.config.OpenAI.EmbeddingModel,
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// return nil
|
||||
//}
|
31
internal/service/embedding/provider.go
Normal file
31
internal/service/embedding/provider.go
Normal file
@ -0,0 +1,31 @@
|
||||
package embedding
|
||||
|
||||
import (
|
||||
"github.com/tmc/langchaingo/llms/openai"
|
||||
"leafdev.top/Leaf/leaf-library/internal/base/conf"
|
||||
"leafdev.top/Leaf/leaf-library/internal/base/logger"
|
||||
"leafdev.top/Leaf/leaf-library/internal/base/redis"
|
||||
"leafdev.top/Leaf/leaf-library/internal/dao"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
OpenAI *openai.LLM
|
||||
Logger *logger.Logger
|
||||
config *conf.Config
|
||||
dao *dao.Query
|
||||
redis *redis.Redis
|
||||
}
|
||||
|
||||
func NewService(config *conf.Config, logger *logger.Logger, dao *dao.Query, redis *redis.Redis) *Service {
|
||||
llm, err := openai.New(
|
||||
openai.WithToken(config.OpenAI.ApiKey),
|
||||
openai.WithBaseURL(config.OpenAI.InternalBaseUrl),
|
||||
openai.WithEmbeddingModel(config.OpenAI.EmbeddingModel),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &Service{llm, logger, config, dao, redis}
|
||||
}
|
23
internal/service/jwks/auth_refresh.go
Normal file
23
internal/service/jwks/auth_refresh.go
Normal file
@ -0,0 +1,23 @@
|
||||
package jwks
|
||||
|
||||
import "time"
|
||||
|
||||
var refreshRate = 1 * time.Hour
|
||||
|
||||
func (j *JWKS) SetupAuthRefresh() {
|
||||
// 先刷新一次
|
||||
j.RefreshJWKS()
|
||||
var firstRefreshed = true
|
||||
|
||||
// 启动一个定时器
|
||||
go func() {
|
||||
for {
|
||||
if firstRefreshed {
|
||||
firstRefreshed = false
|
||||
} else {
|
||||
j.RefreshJWKS()
|
||||
}
|
||||
time.Sleep(refreshRate)
|
||||
}
|
||||
}()
|
||||
}
|
57
internal/service/jwks/jwks.go
Normal file
57
internal/service/jwks/jwks.go
Normal file
@ -0,0 +1,57 @@
|
||||
package jwks
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"go-template/internal/base/conf"
|
||||
"go-template/internal/base/logger"
|
||||
|
||||
"github.com/MicahParks/keyfunc/v3"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
var Jwks keyfunc.Keyfunc
|
||||
|
||||
var (
|
||||
ErrJWKSNotInitialized = errors.New("JWKS is not initialized")
|
||||
)
|
||||
|
||||
type JWKS struct {
|
||||
url string
|
||||
logger *logger.Logger
|
||||
config *conf.Config
|
||||
}
|
||||
|
||||
func NewJWKS(config *conf.Config, logger *logger.Logger) *JWKS {
|
||||
return &JWKS{
|
||||
url: config.JWKS.Url,
|
||||
logger: logger,
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
|
||||
func (j *JWKS) RefreshJWKS() {
|
||||
if j.config.Debug.Enabled {
|
||||
return
|
||||
}
|
||||
|
||||
j.logger.Logger.Info("Refreshing JWKS...")
|
||||
|
||||
var err error
|
||||
|
||||
Jwks, err = keyfunc.NewDefault([]string{j.url})
|
||||
if err != nil {
|
||||
j.logger.Logger.Error("Failed to create JWK Set from resource at the given URL.\nError: " + err.Error())
|
||||
}
|
||||
|
||||
j.logger.Logger.Info("JWKS refreshed.")
|
||||
}
|
||||
|
||||
func (j *JWKS) ParseJWT(jwtB64 string) (*jwt.Token, error) {
|
||||
if Jwks.Keyfunc == nil {
|
||||
return nil, ErrJWKSNotInitialized
|
||||
}
|
||||
|
||||
token, err := jwt.Parse(jwtB64, Jwks.Keyfunc)
|
||||
|
||||
return token, err
|
||||
}
|
34
internal/service/provider.go
Normal file
34
internal/service/provider.go
Normal file
@ -0,0 +1,34 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"go-template/internal/base/logger"
|
||||
"go-template/internal/service/auth"
|
||||
"go-template/internal/service/jwks"
|
||||
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
logger *logger.Logger
|
||||
Jwks *jwks.JWKS
|
||||
Auth *auth.Service
|
||||
}
|
||||
|
||||
var Provider = wire.NewSet(
|
||||
jwks.NewJWKS,
|
||||
auth.NewAuthService,
|
||||
NewService,
|
||||
)
|
||||
|
||||
func NewService(
|
||||
logger *logger.Logger,
|
||||
jwks *jwks.JWKS,
|
||||
auth *auth.Service,
|
||||
|
||||
) *Service {
|
||||
return &Service{
|
||||
logger,
|
||||
jwks,
|
||||
auth,
|
||||
}
|
||||
}
|
18
main.go
Normal file
18
main.go
Normal file
@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"go-template/cmd"
|
||||
)
|
||||
|
||||
// @title API Docs
|
||||
// @version 1.0
|
||||
// @securityDefinitions.apikey ApiKeyAuth
|
||||
// @in header
|
||||
// @name Authorization
|
||||
func main() {
|
||||
err := cmd.RootCmd.Execute()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
}
|
29
pkg/consts/auth.go
Normal file
29
pkg/consts/auth.go
Normal file
@ -0,0 +1,29 @@
|
||||
package consts
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"go-template/internal/schema"
|
||||
)
|
||||
|
||||
const (
|
||||
AuthHeader = "Authorization"
|
||||
AuthPrefix = "Bearer"
|
||||
|
||||
//AnonymousUser schema.UserId = 1
|
||||
AnonymousUser schema.UserId = "anonymous"
|
||||
|
||||
AuthMiddlewareKey = "auth.user"
|
||||
AuthAssistantShareMiddlewareKey = "auth.assistant.share"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotValidToken = errors.New("无效的 JWT 令牌")
|
||||
ErrJWTFormatError = errors.New("JWT 格式错误")
|
||||
ErrNotBearerType = errors.New("不是 Bearer 类型")
|
||||
ErrEmptyResponse = errors.New("我们的服务器返回了空请求,可能某些环节出了问题")
|
||||
ErrTokenError = errors.New("token 类型错误")
|
||||
ErrBearerToken = errors.New("无效的 Bearer 令牌")
|
||||
|
||||
ErrNotYourResource = errors.New("你不能修改这个资源,因为它不是你创建的。")
|
||||
ErrPermissionDenied = errors.New("没有权限访问此资源")
|
||||
)
|
7
pkg/consts/model.go
Normal file
7
pkg/consts/model.go
Normal file
@ -0,0 +1,7 @@
|
||||
package consts
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrPageNotFound = errors.New("page not found")
|
||||
)
|
57
pkg/protos/document/apidocs.swagger.json
Normal file
57
pkg/protos/document/apidocs.swagger.json
Normal file
@ -0,0 +1,57 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"title": "pkg/protos/documentService/service.proto",
|
||||
"version": "version not set"
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"name": "DocumentService"
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"paths": {},
|
||||
"definitions": {
|
||||
"ListDocumentsResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Message": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"protobufAny": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"@type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": {}
|
||||
},
|
||||
"rpcStatus": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
52
pkg/protos/documentService/apidocs.swagger.json
Normal file
52
pkg/protos/documentService/apidocs.swagger.json
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"title": "pkg/protos/document/service.proto",
|
||||
"version": "version not set"
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"name": "DocumentService"
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"paths": {},
|
||||
"definitions": {
|
||||
"ListDocumentsResponse": {
|
||||
"type": "object"
|
||||
},
|
||||
"protobufAny": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"@type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": {}
|
||||
},
|
||||
"rpcStatus": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
214
pkg/protos/documentService/service.pb.go
Normal file
214
pkg/protos/documentService/service.pb.go
Normal file
@ -0,0 +1,214 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc (unknown)
|
||||
// source: pkg/protos/documentService/service.proto
|
||||
|
||||
package documentService
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type ListDocumentsRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Message string `protobuf:"bytes,1,opt,name=Message,proto3" json:"Message,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ListDocumentsRequest) Reset() {
|
||||
*x = ListDocumentsRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_pkg_protos_documentService_service_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ListDocumentsRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ListDocumentsRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ListDocumentsRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_pkg_protos_documentService_service_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ListDocumentsRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ListDocumentsRequest) Descriptor() ([]byte, []int) {
|
||||
return file_pkg_protos_documentService_service_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *ListDocumentsRequest) GetMessage() string {
|
||||
if x != nil {
|
||||
return x.Message
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ListDocumentsResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Message string `protobuf:"bytes,1,opt,name=Message,proto3" json:"Message,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ListDocumentsResponse) Reset() {
|
||||
*x = ListDocumentsResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_pkg_protos_documentService_service_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ListDocumentsResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ListDocumentsResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ListDocumentsResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_pkg_protos_documentService_service_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ListDocumentsResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ListDocumentsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_pkg_protos_documentService_service_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *ListDocumentsResponse) GetMessage() string {
|
||||
if x != nil {
|
||||
return x.Message
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_pkg_protos_documentService_service_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_pkg_protos_documentService_service_proto_rawDesc = []byte{
|
||||
0x0a, 0x28, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x64, 0x6f, 0x63,
|
||||
0x75, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x73, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x30, 0x0a, 0x14, 0x4c, 0x69,
|
||||
0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x31, 0x0a, 0x15,
|
||||
0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32,
|
||||
0x51, 0x0a, 0x0f, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69,
|
||||
0x63, 0x65, 0x12, 0x3e, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65,
|
||||
0x6e, 0x74, 0x73, 0x12, 0x15, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65,
|
||||
0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x4c, 0x69, 0x73,
|
||||
0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x42, 0x13, 0x5a, 0x11, 0x2e, 0x3b, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74,
|
||||
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_pkg_protos_documentService_service_proto_rawDescOnce sync.Once
|
||||
file_pkg_protos_documentService_service_proto_rawDescData = file_pkg_protos_documentService_service_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_pkg_protos_documentService_service_proto_rawDescGZIP() []byte {
|
||||
file_pkg_protos_documentService_service_proto_rawDescOnce.Do(func() {
|
||||
file_pkg_protos_documentService_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_protos_documentService_service_proto_rawDescData)
|
||||
})
|
||||
return file_pkg_protos_documentService_service_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_pkg_protos_documentService_service_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_pkg_protos_documentService_service_proto_goTypes = []interface{}{
|
||||
(*ListDocumentsRequest)(nil), // 0: ListDocumentsRequest
|
||||
(*ListDocumentsResponse)(nil), // 1: ListDocumentsResponse
|
||||
}
|
||||
var file_pkg_protos_documentService_service_proto_depIdxs = []int32{
|
||||
0, // 0: DocumentService.ListDocuments:input_type -> ListDocumentsRequest
|
||||
1, // 1: DocumentService.ListDocuments:output_type -> ListDocumentsResponse
|
||||
1, // [1:2] is the sub-list for method output_type
|
||||
0, // [0:1] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_pkg_protos_documentService_service_proto_init() }
|
||||
func file_pkg_protos_documentService_service_proto_init() {
|
||||
if File_pkg_protos_documentService_service_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_pkg_protos_documentService_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ListDocumentsRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_pkg_protos_documentService_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ListDocumentsResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_pkg_protos_documentService_service_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_pkg_protos_documentService_service_proto_goTypes,
|
||||
DependencyIndexes: file_pkg_protos_documentService_service_proto_depIdxs,
|
||||
MessageInfos: file_pkg_protos_documentService_service_proto_msgTypes,
|
||||
}.Build()
|
||||
File_pkg_protos_documentService_service_proto = out.File
|
||||
file_pkg_protos_documentService_service_proto_rawDesc = nil
|
||||
file_pkg_protos_documentService_service_proto_goTypes = nil
|
||||
file_pkg_protos_documentService_service_proto_depIdxs = nil
|
||||
}
|
164
pkg/protos/documentService/service.pb.gw.go
Normal file
164
pkg/protos/documentService/service.pb.gw.go
Normal file
@ -0,0 +1,164 @@
|
||||
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
|
||||
// source: pkg/protos/documentService/service.proto
|
||||
|
||||
/*
|
||||
Package documentService is a reverse proxy.
|
||||
|
||||
It translates gRPC into RESTful JSON APIs.
|
||||
*/
|
||||
package documentService
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/utilities"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// Suppress "imported and not used" errors
|
||||
var _ codes.Code
|
||||
var _ io.Reader
|
||||
var _ status.Status
|
||||
var _ = runtime.String
|
||||
var _ = utilities.NewDoubleArray
|
||||
var _ = metadata.Join
|
||||
|
||||
func request_DocumentService_ListDocuments_0(ctx context.Context, marshaler runtime.Marshaler, client DocumentServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq ListDocumentsRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.ListDocuments(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_DocumentService_ListDocuments_0(ctx context.Context, marshaler runtime.Marshaler, server DocumentServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq ListDocumentsRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.ListDocuments(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
// RegisterDocumentServiceHandlerServer registers the http handlers for service DocumentService to "mux".
|
||||
// UnaryRPC :call DocumentServiceServer directly.
|
||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||
// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterDocumentServiceHandlerFromEndpoint instead.
|
||||
// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
|
||||
func RegisterDocumentServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server DocumentServiceServer) error {
|
||||
|
||||
mux.Handle("POST", pattern_DocumentService_ListDocuments_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/.DocumentService/ListDocuments", runtime.WithHTTPPathPattern("/DocumentService/ListDocuments"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_DocumentService_ListDocuments_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_DocumentService_ListDocuments_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterDocumentServiceHandlerFromEndpoint is same as RegisterDocumentServiceHandler but
|
||||
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
|
||||
func RegisterDocumentServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
|
||||
conn, err := grpc.NewClient(endpoint, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
return RegisterDocumentServiceHandler(ctx, mux, conn)
|
||||
}
|
||||
|
||||
// RegisterDocumentServiceHandler registers the http handlers for service DocumentService to "mux".
|
||||
// The handlers forward requests to the grpc endpoint over "conn".
|
||||
func RegisterDocumentServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
|
||||
return RegisterDocumentServiceHandlerClient(ctx, mux, NewDocumentServiceClient(conn))
|
||||
}
|
||||
|
||||
// RegisterDocumentServiceHandlerClient registers the http handlers for service DocumentService
|
||||
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "DocumentServiceClient".
|
||||
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "DocumentServiceClient"
|
||||
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
|
||||
// "DocumentServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares.
|
||||
func RegisterDocumentServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client DocumentServiceClient) error {
|
||||
|
||||
mux.Handle("POST", pattern_DocumentService_ListDocuments_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/.DocumentService/ListDocuments", runtime.WithHTTPPathPattern("/DocumentService/ListDocuments"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_DocumentService_ListDocuments_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_DocumentService_ListDocuments_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
pattern_DocumentService_ListDocuments_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"DocumentService", "ListDocuments"}, ""))
|
||||
)
|
||||
|
||||
var (
|
||||
forward_DocumentService_ListDocuments_0 = runtime.ForwardResponseMessage
|
||||
)
|
15
pkg/protos/documentService/service.proto
Normal file
15
pkg/protos/documentService/service.proto
Normal file
@ -0,0 +1,15 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option go_package = ".;documentService";
|
||||
|
||||
service DocumentService {
|
||||
rpc ListDocuments(ListDocumentsRequest) returns (ListDocumentsResponse);
|
||||
}
|
||||
|
||||
message ListDocumentsRequest {
|
||||
string Message = 1;
|
||||
}
|
||||
|
||||
message ListDocumentsResponse {
|
||||
string Message = 1;
|
||||
}
|
105
pkg/protos/documentService/service_grpc.pb.go
Normal file
105
pkg/protos/documentService/service_grpc.pb.go
Normal file
@ -0,0 +1,105 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.2.0
|
||||
// - protoc (unknown)
|
||||
// source: pkg/protos/documentService/service.proto
|
||||
|
||||
package documentService
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
// DocumentServiceClient is the client API for DocumentService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type DocumentServiceClient interface {
|
||||
ListDocuments(ctx context.Context, in *ListDocumentsRequest, opts ...grpc.CallOption) (*ListDocumentsResponse, error)
|
||||
}
|
||||
|
||||
type documentServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewDocumentServiceClient(cc grpc.ClientConnInterface) DocumentServiceClient {
|
||||
return &documentServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *documentServiceClient) ListDocuments(ctx context.Context, in *ListDocumentsRequest, opts ...grpc.CallOption) (*ListDocumentsResponse, error) {
|
||||
out := new(ListDocumentsResponse)
|
||||
err := c.cc.Invoke(ctx, "/DocumentService/ListDocuments", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// DocumentServiceServer is the server API for DocumentService service.
|
||||
// All implementations must embed UnimplementedDocumentServiceServer
|
||||
// for forward compatibility
|
||||
type DocumentServiceServer interface {
|
||||
ListDocuments(context.Context, *ListDocumentsRequest) (*ListDocumentsResponse, error)
|
||||
mustEmbedUnimplementedDocumentServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedDocumentServiceServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedDocumentServiceServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedDocumentServiceServer) ListDocuments(context.Context, *ListDocumentsRequest) (*ListDocumentsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListDocuments not implemented")
|
||||
}
|
||||
func (UnimplementedDocumentServiceServer) mustEmbedUnimplementedDocumentServiceServer() {}
|
||||
|
||||
// UnsafeDocumentServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to DocumentServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeDocumentServiceServer interface {
|
||||
mustEmbedUnimplementedDocumentServiceServer()
|
||||
}
|
||||
|
||||
func RegisterDocumentServiceServer(s grpc.ServiceRegistrar, srv DocumentServiceServer) {
|
||||
s.RegisterService(&DocumentService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _DocumentService_ListDocuments_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ListDocumentsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(DocumentServiceServer).ListDocuments(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/DocumentService/ListDocuments",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(DocumentServiceServer).ListDocuments(ctx, req.(*ListDocumentsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// DocumentService_ServiceDesc is the grpc.ServiceDesc for DocumentService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var DocumentService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "DocumentService",
|
||||
HandlerType: (*DocumentServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "ListDocuments",
|
||||
Handler: _DocumentService_ListDocuments_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "pkg/protos/documentService/service.proto",
|
||||
}
|
Loading…
Reference in New Issue
Block a user