init
This commit is contained in:
commit
2699d43e47
2
.dockerignore
Normal file
2
.dockerignore
Normal file
@ -0,0 +1,2 @@
|
||||
build
|
||||
config.yaml
|
97
.gitea_old/workflows/build.yaml
Normal file
97
.gitea_old/workflows/build.yaml
Normal file
@ -0,0 +1,97 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- id: commit
|
||||
uses: prompt/actions-commit-hash@v3
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '^1.22'
|
||||
- name: Get dependencies
|
||||
run: |
|
||||
go env -w GO111MODULE=on && go env -w GOPROXY=https://goproxy.cn,direct
|
||||
go mod download
|
||||
- name: Build
|
||||
run: |
|
||||
CGO_ENABLED=0 go build -ldflags "-w -s" -gcflags "-N -l" -o main .
|
||||
- name: 'Login to Container Registry'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: leafdev.top
|
||||
username: ${{ gitea.actor }}
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
- name: 'Build Inventory Image'
|
||||
run: |
|
||||
docker build . -f Dockerfile2 --tag leafdev.top/leaf/rag-new:${{ steps.commit.outputs.short }}
|
||||
docker push leafdev.top/leaf/rag-new:${{ steps.commit.outputs.short }}
|
||||
docker tag leafdev.top/leaf/rag-new:${{ steps.commit.outputs.short }} leafdev.top/leaf/rag-new:latest
|
||||
- name: 'Checkout Manifests branch'
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: manifests
|
||||
|
||||
- name: 'Patch API Manifest'
|
||||
uses: fjogeleit/yaml-update-action@main
|
||||
with:
|
||||
valueFile: 'manifests/deployment-api.yaml'
|
||||
propertyPath: 'spec.template.spec.containers[0].image'
|
||||
value: 'leafdev.top/leaf/rag-new:${{ steps.commit.outputs.short }}'
|
||||
commitChange: false
|
||||
- name: 'Patch Schedule Manifest'
|
||||
uses: fjogeleit/yaml-update-action@main
|
||||
with:
|
||||
valueFile: 'manifests/deployment-schedule.yaml'
|
||||
propertyPath: 'spec.template.spec.containers[0].image'
|
||||
value: 'leafdev.top/leaf/rag-new:${{ steps.commit.outputs.short }}'
|
||||
commitChange: false
|
||||
- name: Push
|
||||
run: |
|
||||
git config user.name ${{ gitea.actor }}
|
||||
git config user.email ${{ gitea.actor }}@users.noreply.leafdev.top
|
||||
git add manifests/deployment-api.yaml
|
||||
git add manifests/deployment-schedule.yaml
|
||||
git commit -m "Update manifests"
|
||||
git push origin manifests
|
||||
# - name: docker
|
||||
# run: |
|
||||
# - name: Build Docker Image
|
||||
# run: |
|
||||
# docker build -t ${{ env.REGISTRY }}/${{ steps.meta.outputs.tags }} -f ./docker/nginx/Dockerfile .
|
||||
# - name: Push Docker Image
|
||||
# run: |
|
||||
# docker login --username=${{ secrets.DOCKER_USERNAME }} --password ${{ secrets.DOCKER_PASSWORD }} ${{ env.REGISTRY }}
|
||||
# docker push ${{ env.REGISTRY }}/${{ steps.meta.outputs.tags }}
|
||||
# - name: Artifact
|
||||
# uses: christopherhx/gitea-upload-artifact@v4
|
||||
# with:
|
||||
# name: artifact
|
||||
# path: cmd/main
|
||||
# push:
|
||||
# runs-on: ubuntu-latest
|
||||
## needs: [build]
|
||||
# steps:
|
||||
# - uses: https://github.com/actions/checkout@v4
|
||||
# - name: Set up Docker Buildx
|
||||
# uses: https://github.com/docker/setup-buildx-action@v3
|
||||
# with:
|
||||
# config-inline: |
|
||||
# [registry."<my-private-unsecure-git-repository-ip-address>:5000"]
|
||||
# http = true
|
||||
# insecure = true
|
||||
# - name: Build and push Docker image
|
||||
# uses: https://github.com/docker/build-push-action@v5
|
||||
# with:
|
||||
# context: .
|
||||
# file: ./Dockerfile
|
||||
# push: true
|
||||
# tags: "<my-private-unsecure-git-repository-ip-address>:5000/<my-docker-image>:${{gitea.sha}},<my-private-unsecure-git-repository-ip-address>:5000/<my-docker-image>:latest"
|
25
.gitea_old/workflows/deploy.yaml
Normal file
25
.gitea_old/workflows/deploy.yaml
Normal file
@ -0,0 +1,25 @@
|
||||
name: Deploy
|
||||
|
||||
on: [release]
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Set output
|
||||
id: vars
|
||||
run: echo "tag=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT
|
||||
- name: Check output
|
||||
env:
|
||||
GITHUB_RELEASE_VERSION: ${{ steps.vars.outputs.tag }}
|
||||
run: |
|
||||
# check if GITHUB_RELEASE_VERSION is not empty
|
||||
- name: Deploy
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
tags: leafdev.top/rag-new:latest
|
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"]
|
15
Makefile
Normal file
15
Makefile
Normal file
@ -0,0 +1,15 @@
|
||||
.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
|
||||
|
||||
gorm:
|
||||
cd hack/gorm-gen && go run .
|
19
buf.gen.yaml
Normal file
19
buf.gen.yaml
Normal file
@ -0,0 +1,19 @@
|
||||
version: v1
|
||||
|
||||
plugins:
|
||||
- name: go
|
||||
out: .
|
||||
opt: paths=source_relative
|
||||
- name: go-grpc
|
||||
out: .
|
||||
opt: paths=source_relative
|
||||
- plugin: buf.build/grpc-ecosystem/gateway:v2.22.0
|
||||
out: .
|
||||
opt:
|
||||
- paths=source_relative
|
||||
- generate_unbound_methods=true
|
||||
- plugin: buf.build/grpc-ecosystem/openapiv2:v2.22.0
|
||||
out: pkg/protos/document
|
||||
opt:
|
||||
- allow_merge
|
||||
# - merge_file_name=mce-spider
|
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: "app",
|
||||
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()
|
||||
}
|
44
cmd/wire.go
Normal file
44
cmd/wire.go
Normal file
@ -0,0 +1,44 @@
|
||||
//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/milvus"
|
||||
"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,
|
||||
milvus.NewService,
|
||||
batch.NewBatch,
|
||||
service.Provider,
|
||||
handler.ProviderSet,
|
||||
router.ProviderSetRouter,
|
||||
server.NewHTTPServer,
|
||||
base.NewApplication,
|
||||
)
|
||||
|
||||
func CreateApp() (*base.Application, error) {
|
||||
wire.Build(ProviderSet)
|
||||
|
||||
return nil, nil
|
||||
}
|
67
cmd/wire_gen.go
Normal file
67
cmd/wire_gen.go
Normal file
@ -0,0 +1,67 @@
|
||||
// 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/milvus"
|
||||
"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/grpc/interceptor"
|
||||
"go-template/internal/handler/http"
|
||||
"go-template/internal/handler/http/controller/v1"
|
||||
"go-template/internal/router"
|
||||
"go-template/internal/service"
|
||||
"go-template/internal/service/auth"
|
||||
"go-template/internal/service/jwks"
|
||||
"go-template/internal/service/stream"
|
||||
)
|
||||
|
||||
// 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()
|
||||
middleware := http.NewMiddleware(config, loggerLogger, authService)
|
||||
httpServer := server.NewHTTPServer(config, api, swaggerRouter, middleware)
|
||||
db := orm.NewGORM(config, loggerLogger)
|
||||
query := dao.NewQuery(db)
|
||||
documentService := documents.NewDocumentService(query)
|
||||
interceptorAuth := interceptor.NewAuth(authService)
|
||||
interceptorLogger := interceptor.NewLogger(loggerLogger)
|
||||
grpcInterceptor := grpc.NewInterceptor(interceptorAuth, interceptorLogger)
|
||||
grpcHandlers := grpc.NewHandler(documentService, grpcInterceptor)
|
||||
handlerHandler := handler.NewHandler(grpcHandlers, handlers)
|
||||
streamService := stream.NewService(config)
|
||||
serviceService := service.NewService(loggerLogger, jwksJWKS, authService, streamService)
|
||||
redisRedis := redis.NewRedis(config)
|
||||
batchBatch := batch.NewBatch(loggerLogger)
|
||||
s3S3 := s3.NewS3(config)
|
||||
client := milvus.NewService(config, loggerLogger)
|
||||
application := base.NewApplication(config, httpServer, handlerHandler, loggerLogger, serviceService, middleware, redisRedis, batchBatch, s3S3, db, query, client)
|
||||
return application, nil
|
||||
}
|
||||
|
||||
// wire.go:
|
||||
|
||||
var ProviderSet = wire.NewSet(conf.ProviderConfig, logger.NewZapLogger, orm.NewGORM, dao.NewQuery, redis.NewRedis, s3.NewS3, milvus.NewService, 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
|
67
configs/config.yaml
Normal file
67
configs/config.yaml
Normal file
@ -0,0 +1,67 @@
|
||||
app:
|
||||
name: template
|
||||
allowed_audiences:
|
||||
- "1" # UserLand Personal Access Client
|
||||
|
||||
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:
|
||||
|
||||
|
||||
kafka:
|
||||
bootstrap_servers:
|
||||
- 127.0.0.1:9092
|
||||
topic: "amber"
|
||||
group_id: ""
|
||||
# Plain
|
||||
username: ""
|
||||
password: ""
|
||||
|
||||
milvus:
|
||||
host: 127.0.0.1
|
||||
port: 19530
|
||||
db_name: library
|
||||
document_collection: documents
|
||||
user:
|
||||
password:
|
||||
|
||||
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"
|
119
go.mod
Normal file
119
go.mod
Normal file
@ -0,0 +1,119 @@
|
||||
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/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.23.0
|
||||
github.com/labstack/echo-contrib v0.17.1
|
||||
github.com/labstack/echo/v4 v4.12.0
|
||||
github.com/milvus-io/milvus-sdk-go/v2 v2.4.2
|
||||
github.com/minio/minio-go/v7 v7.0.80
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/pressly/goose/v3 v3.22.1
|
||||
github.com/redis/go-redis/v9 v9.7.0
|
||||
github.com/segmentio/kafka-go v0.4.47
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/spf13/viper v1.19.0
|
||||
github.com/swaggo/echo-swagger v1.4.1
|
||||
github.com/swaggo/swag v1.16.4
|
||||
go.uber.org/zap v1.27.0
|
||||
google.golang.org/grpc v1.68.0
|
||||
google.golang.org/protobuf v1.35.2
|
||||
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/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cockroachdb/errors v1.11.3 // indirect
|
||||
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
|
||||
github.com/cockroachdb/redact v1.1.5 // 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.8.0 // indirect
|
||||
github.com/getsentry/sentry-go v0.29.1 // indirect
|
||||
github.com/ghodss/yaml v1.0.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-sql-driver/mysql v1.8.1 // indirect
|
||||
github.com/goccy/go-json v0.10.3 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.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/klauspost/compress v1.17.11 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/labstack/gommon v0.4.2 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // 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/milvus-io/milvus-proto/go-api/v2 v2.4.16 // indirect
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/prometheus/client_golang v1.20.5 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.60.1 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/rogpeppe/go-internal v1.13.1 // 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/swaggo/files/v2 v2.0.1 // indirect
|
||||
github.com/tidwall/gjson v1.18.0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/crypto v0.29.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
|
||||
golang.org/x/mod v0.22.0 // indirect
|
||||
golang.org/x/net v0.31.0 // indirect
|
||||
golang.org/x/sync v0.9.0 // indirect
|
||||
golang.org/x/sys v0.27.0 // indirect
|
||||
golang.org/x/text v0.20.0 // indirect
|
||||
golang.org/x/time v0.8.0 // indirect
|
||||
golang.org/x/tools v0.27.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241113202542-65e8d215514f // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gorm.io/datatypes v1.2.4 // indirect
|
||||
gorm.io/hints v1.1.2 // indirect
|
||||
)
|
499
go.sum
Normal file
499
go.sum
Normal file
@ -0,0 +1,499 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM=
|
||||
cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg=
|
||||
cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY=
|
||||
cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
|
||||
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/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
||||
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/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
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/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
|
||||
github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I=
|
||||
github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8=
|
||||
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
|
||||
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
|
||||
github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
|
||||
github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
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/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
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.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/getsentry/sentry-go v0.29.1 h1:DyZuChN8Hz3ARxGVV8ePaNXh1dQ7d76AiB117xcREwA=
|
||||
github.com/getsentry/sentry-go v0.29.1/go.mod h1:x3AtIzN01d6SiWkderzaH28Tm0lgkafpJ5Bm3li39O0=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
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-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
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-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/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
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/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
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/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
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/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 v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
|
||||
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.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0=
|
||||
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/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
|
||||
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/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
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.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
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/labstack/echo-contrib v0.17.1 h1:7I/he7ylVKsDUieaGRZ9XxxTYOjfQwVzHzUYrNykfCU=
|
||||
github.com/labstack/echo-contrib v0.17.1/go.mod h1:SnsCZtwHBAZm5uBSAtQtXQHI3wqEA73hvTn0bYMKnZA=
|
||||
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
|
||||
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
|
||||
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
||||
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
|
||||
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-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
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/milvus-io/milvus-proto/go-api/v2 v2.4.16 h1:XcdubT6Vy0PvNrWDJZ4cy6ytXWRENEYgYBCLkI+YpTE=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.4.16/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
|
||||
github.com/milvus-io/milvus-sdk-go/v2 v2.4.2 h1:Xqf+S7iicElwYoS2Zly8Nf/zKHuZsNy1xQajfdtygVY=
|
||||
github.com/milvus-io/milvus-sdk-go/v2 v2.4.2/go.mod h1:ulO1YUXKH0PGg50q27grw048GDY9ayB4FPmh7D+FFTA=
|
||||
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.80 h1:2mdUHXEykRdY/BigLt3Iuu1otL0JTogT0Nmltg0wujk=
|
||||
github.com/minio/minio-go/v7 v7.0.80/go.mod h1:84gmIilaX4zcvAWWzJ5Z1WI5axN+hAbM5w25xf8xvC0=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
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-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
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/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
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/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
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/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
||||
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.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.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
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.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc=
|
||||
github.com/prometheus/common v0.60.1/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.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E=
|
||||
github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
|
||||
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.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
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/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
|
||||
github.com/segmentio/kafka-go v0.4.47 h1:IqziR4pA3vrZq7YdRxaT3w1/5fvIH5qpCwstUanQQB0=
|
||||
github.com/segmentio/kafka-go v0.4.47/go.mod h1:HjF6XbOKh0Pjlkr5GVZxt6CsjjwnmhVOfURM5KMd8qg=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
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/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
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.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
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.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/echo-swagger v1.4.1 h1:Yf0uPaJWp1uRtDloZALyLnvdBeoEL5Kc7DtnjzO/TUk=
|
||||
github.com/swaggo/echo-swagger v1.4.1/go.mod h1:C8bSi+9yH2FLZsnhqMZLIZddpUxZdBYuNHbtaS1Hljc=
|
||||
github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw=
|
||||
github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM=
|
||||
github.com/swaggo/files/v2 v2.0.1 h1:XCVJO/i/VosCDsJu1YLpdejGsGnBE9deRMpjN4pJLHk=
|
||||
github.com/swaggo/files/v2 v2.0.1/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM=
|
||||
github.com/swaggo/swag v1.16.4 h1:clWJtd9LStiG3VeijiCfOVODP6VpHtKdQy9ELFG3s1A=
|
||||
github.com/swaggo/swag v1.16.4/go.mod h1:VBsHJRsDvfYvqoiMKnsdwhNV9LEMHgEDZcyVYX0sxPg=
|
||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
|
||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
|
||||
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
|
||||
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
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.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
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.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
||||
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/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-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
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.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
||||
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
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.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
|
||||
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
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-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
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.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
|
||||
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
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-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/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.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
||||
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
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-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/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-20211025201205-69cdffdb9359/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.0.0-20220811171246-fbc7d0a398ab/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.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||
golang.org/x/sys v0.27.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.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
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.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
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.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
||||
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
|
||||
golang.org/x/time v0.8.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-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
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.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o=
|
||||
golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q=
|
||||
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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241113202542-65e8d215514f h1:M65LEviCfuZTfrfzwwEoxVtgvfkFkBUbFnRbxCXuXhU=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241113202542-65e8d215514f/go.mod h1:Yo94eF2nj7igQt+TiJ49KxjIH8ndLYPZMIRSiRcEbg0=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f h1:C1QccEa9kUwvMgEUORqQD9S17QesQijxjZ84sO82mfo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
|
||||
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
|
||||
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
|
||||
google.golang.org/protobuf v1.35.2/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.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
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.4 h1:uZmGAcK/QZ0uyfCuVg0VQY1ZmV9h1fuG0tMwKByO1z4=
|
||||
gorm.io/datatypes v1.2.4/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=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
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=
|
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
|
||||
}
|
61
internal/base/app.go
Normal file
61
internal/base/app.go
Normal file
@ -0,0 +1,61 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"github.com/milvus-io/milvus-sdk-go/v2/client"
|
||||
"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
|
||||
Milvus client.Client
|
||||
}
|
||||
|
||||
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,
|
||||
milvus client.Client,
|
||||
) *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,
|
||||
Milvus: milvus,
|
||||
}
|
||||
}
|
104
internal/base/conf/conf.go
Normal file
104
internal/base/conf/conf.go
Normal file
@ -0,0 +1,104 @@
|
||||
package conf
|
||||
|
||||
// Config 配置文件不能有下划线或横线,否则不能解析
|
||||
type Config struct {
|
||||
App *App `yaml:"app"`
|
||||
|
||||
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"`
|
||||
|
||||
Milvus *Milvus `yaml:"milvus"`
|
||||
|
||||
ThirdParty *ThirdParty `yaml:"third_party" mapstructure:"third_party"`
|
||||
}
|
||||
|
||||
type App struct {
|
||||
Name string `yaml:"name"`
|
||||
AllowedAudiences []string `yaml:"allowed_audiences" mapstructure:"allowed_audiences"`
|
||||
}
|
||||
|
||||
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"`
|
||||
GroupId string `yaml:"group_id" mapstructure:"group_id"`
|
||||
Username string `yaml:"username" mapstructure:"username"`
|
||||
Password string `yaml:"password" mapstructure:"password"`
|
||||
MainTopic string `yaml:"main_topic" mapstructure:"main_topic"`
|
||||
WorkerTopic string `yaml:"worker_topic" mapstructure:"worker_topic"`
|
||||
}
|
||||
|
||||
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"`
|
||||
}
|
||||
|
||||
type Grpc struct {
|
||||
Address string `yaml:"address" mapstructure:"address"`
|
||||
}
|
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"
|
||||
"go-template/internal/base/conf"
|
||||
"go-template/internal/base/logger"
|
||||
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func NewService(config *conf.Config, logger *logger.Logger) client.Client {
|
||||
var address = config.Milvus.Host + ":" + strconv.Itoa(config.Milvus.Port)
|
||||
|
||||
logger.Sugar.Infof("Connecting 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("Milvus connected!")
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
43
internal/base/orm/provide.go
Normal file
43
internal/base/orm/provide.go
Normal file
@ -0,0 +1,43 @@
|
||||
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 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)
|
||||
|
||||
var d = mysql.Open(dsn)
|
||||
|
||||
if config.Debug.Enabled {
|
||||
db, err := gorm.Open(d)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
zapGormLogger := zapgorm2.New(logger.Logger)
|
||||
zapGormLogger.SetAsDefault()
|
||||
db, err := gorm.Open(d, &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,
|
||||
}
|
||||
}
|
99
internal/base/server/echo.go
Normal file
99
internal/base/server/echo.go
Normal file
@ -0,0 +1,99 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo-contrib/echoprometheus"
|
||||
"github.com/labstack/echo/v4"
|
||||
echoMiddleware "github.com/labstack/echo/v4/middleware"
|
||||
"go-template/internal/base/conf"
|
||||
httpHandlers "go-template/internal/handler/http"
|
||||
"go-template/internal/handler/http/response"
|
||||
"go-template/internal/router"
|
||||
"go-template/pkg/consts"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type HttpServer struct {
|
||||
config *conf.Config
|
||||
Echo *echo.Echo
|
||||
apiRouter *router.Api
|
||||
swaggerRouter *router.SwaggerRouter
|
||||
middleware *httpHandlers.Middleware
|
||||
}
|
||||
|
||||
// NewHTTPServer new http server.
|
||||
func NewHTTPServer(
|
||||
config *conf.Config,
|
||||
apiRouter *router.Api,
|
||||
swaggerRouter *router.SwaggerRouter,
|
||||
middleware *httpHandlers.Middleware,
|
||||
) *HttpServer {
|
||||
|
||||
e := echo.New()
|
||||
e.Use(echoMiddleware.Recover())
|
||||
e.Use(middleware.Logger.Handler())
|
||||
e.Use(middleware.JSONResponse.Handler())
|
||||
|
||||
return &HttpServer{
|
||||
config: config,
|
||||
Echo: e,
|
||||
apiRouter: apiRouter,
|
||||
swaggerRouter: swaggerRouter,
|
||||
middleware: middleware,
|
||||
}
|
||||
}
|
||||
|
||||
func (hs *HttpServer) AllowAllCors() {
|
||||
var defaultCORSConfig = echoMiddleware.CORSConfig{
|
||||
AllowOrigins: []string{"*"},
|
||||
AllowHeaders: []string{"Origin", "Content-Length", "Content-Type", "X-Requested-With", "X-Auth-Token", "Authorization"},
|
||||
AllowCredentials: true,
|
||||
AllowMethods: []string{http.MethodGet, http.MethodHead, http.MethodPut, http.MethodPatch, http.MethodPost, http.MethodDelete},
|
||||
MaxAge: 12 * 60,
|
||||
}
|
||||
|
||||
hs.Echo.Use(echoMiddleware.CORSWithConfig(defaultCORSConfig))
|
||||
}
|
||||
|
||||
func (hs *HttpServer) BizRouter() *echo.Echo {
|
||||
hs.AllowAllCors()
|
||||
|
||||
rootGroup := hs.Echo.Group("")
|
||||
|
||||
// swagger
|
||||
hs.swaggerRouter.Register(rootGroup)
|
||||
|
||||
apiV1 := rootGroup.Group("/api/v1")
|
||||
{
|
||||
//apiV1.Use(corsMiddleWare)
|
||||
apiV1.Use(hs.middleware.JSONResponse.Handler())
|
||||
apiV1.Use(hs.middleware.Auth.Handler())
|
||||
hs.apiRouter.InitApiRouter(apiV1)
|
||||
}
|
||||
|
||||
apiV1NoAuth := rootGroup.Group("/api/v1")
|
||||
{
|
||||
//apiV1.Use(corsMiddleWare)
|
||||
hs.apiRouter.InitNoAuthApiRouter(apiV1NoAuth)
|
||||
}
|
||||
|
||||
hs.Echo.RouteNotFound("/*", func(ctx echo.Context) error {
|
||||
return response.Ctx(ctx).Status(http.StatusNotFound).Error(consts.ErrPageNotFound).Send()
|
||||
})
|
||||
|
||||
return hs.Echo
|
||||
}
|
||||
|
||||
func (hs *HttpServer) MetricRouter() *echo.Echo {
|
||||
e := echo.New()
|
||||
e.Use(echoMiddleware.Recover())
|
||||
|
||||
metricGroup := e.Group("")
|
||||
// prometheus
|
||||
metricGroup.Use(echoprometheus.NewMiddleware(hs.config.App.Name))
|
||||
|
||||
metricGroup.GET("/metrics", echoprometheus.NewHandler())
|
||||
|
||||
metricGroup.GET("/healthz", func(ctx echo.Context) error { return ctx.String(200, "OK") })
|
||||
|
||||
return e
|
||||
}
|
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"
|
||||
"go-template/internal/handler/grpc/documents"
|
||||
"go-template/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,
|
||||
}
|
||||
}
|
45
internal/handler/http/controller/v1/test.go
Normal file
45
internal/handler/http/controller/v1/test.go
Normal file
@ -0,0 +1,45 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"go-template/internal/handler/http/response"
|
||||
"go-template/internal/schema"
|
||||
"go-template/internal/service/auth"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
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 echo.Context) error {
|
||||
user, ok := u.authService.GetUser(c)
|
||||
if !ok {
|
||||
return response.Ctx(c).Status(http.StatusUnauthorized).Send()
|
||||
}
|
||||
|
||||
var currentUserResponse = &schema.CurrentUserResponse{
|
||||
IP: c.Request().RemoteAddr,
|
||||
Valid: user.Valid,
|
||||
UserEmail: user.Token.Email,
|
||||
UserId: user.Token.Sub,
|
||||
UserName: user.Token.Name,
|
||||
}
|
||||
|
||||
return response.Ctx(c).Data(currentUserResponse).Send()
|
||||
}
|
87
internal/handler/http/middleware/auth.go
Normal file
87
internal/handler/http/middleware/auth.go
Normal file
@ -0,0 +1,87 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"go-template/internal/base/conf"
|
||||
"go-template/internal/handler/http/response"
|
||||
"go-template/internal/schema"
|
||||
"go-template/internal/service/auth"
|
||||
"go-template/pkg/consts"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type AuthMiddleware struct {
|
||||
config *conf.Config
|
||||
authService *auth.Service
|
||||
}
|
||||
|
||||
var audienceLength int
|
||||
|
||||
func NewAuthMiddleware(config *conf.Config, authService *auth.Service) *AuthMiddleware {
|
||||
audienceLength = len(config.App.AllowedAudiences)
|
||||
|
||||
return &AuthMiddleware{
|
||||
config,
|
||||
authService,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AuthMiddleware) Handler() echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
var r = response.Ctx(c)
|
||||
var err error
|
||||
var token *schema.User
|
||||
|
||||
if a.config.Debug.Enabled {
|
||||
token, err = a.authService.AuthFromToken(schema.JWTAccessToken, "")
|
||||
if err != nil {
|
||||
return r.Error(err).Send()
|
||||
}
|
||||
|
||||
c.Set(consts.AuthMiddlewareKey, token)
|
||||
|
||||
return next(c)
|
||||
}
|
||||
|
||||
authorization := c.Request().Header.Get(consts.AuthHeader)
|
||||
|
||||
if authorization == "" {
|
||||
return r.Error(consts.ErrJWTFormatError).Send()
|
||||
}
|
||||
|
||||
authSplit := strings.Split(authorization, " ")
|
||||
if len(authSplit) != 2 {
|
||||
return r.Error(consts.ErrJWTFormatError).Send()
|
||||
}
|
||||
|
||||
if authSplit[0] != consts.AuthPrefix {
|
||||
return r.Error(consts.ErrNotBearerType).Send()
|
||||
}
|
||||
|
||||
token, err = a.authService.AuthFromToken(schema.JWTIDToken, authSplit[1])
|
||||
|
||||
if err != nil {
|
||||
return r.Error(err).Status(http.StatusUnauthorized).Send()
|
||||
}
|
||||
|
||||
if token == nil {
|
||||
return r.Error(err).Status(http.StatusUnauthorized).Send()
|
||||
}
|
||||
|
||||
if audienceLength > 0 {
|
||||
// 检测 aud
|
||||
if !slices.Contains(a.config.App.AllowedAudiences, token.Token.Aud) {
|
||||
return r.Error(consts.ErrNotValidToken).Send()
|
||||
}
|
||||
}
|
||||
|
||||
c.Set(consts.AuthMiddlewareKey, token)
|
||||
|
||||
return next(c)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
22
internal/handler/http/middleware/json_response.go
Normal file
22
internal/handler/http/middleware/json_response.go
Normal file
@ -0,0 +1,22 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
type JSONResponseMiddleware struct {
|
||||
}
|
||||
|
||||
func (*JSONResponseMiddleware) Handler() echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
c.Response().Header().Set("Content-Type", "application/json")
|
||||
|
||||
return next(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewJSONResponseMiddleware() *JSONResponseMiddleware {
|
||||
return &JSONResponseMiddleware{}
|
||||
}
|
32
internal/handler/http/middleware/zap_logger.go
Normal file
32
internal/handler/http/middleware/zap_logger.go
Normal file
@ -0,0 +1,32 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
echoMiddleware "github.com/labstack/echo/v4/middleware"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type LoggerMiddleware struct {
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
func NewLoggerMiddleware(logger *zap.Logger) *LoggerMiddleware {
|
||||
return &LoggerMiddleware{
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *LoggerMiddleware) Handler() echo.MiddlewareFunc {
|
||||
return echoMiddleware.RequestLoggerWithConfig(echoMiddleware.RequestLoggerConfig{
|
||||
LogURI: true,
|
||||
LogStatus: true,
|
||||
LogValuesFunc: func(c echo.Context, v echoMiddleware.RequestLoggerValues) error {
|
||||
l.logger.Info("request",
|
||||
zap.String("URI", v.URI),
|
||||
zap.Int("status", v.Status),
|
||||
)
|
||||
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
50
internal/handler/http/provider.go
Normal file
50
internal/handler/http/provider.go
Normal file
@ -0,0 +1,50 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"github.com/google/wire"
|
||||
"github.com/labstack/echo/v4"
|
||||
"go-template/internal/base/conf"
|
||||
"go-template/internal/base/logger"
|
||||
v1 "go-template/internal/handler/http/controller/v1"
|
||||
"go-template/internal/handler/http/middleware"
|
||||
"go-template/internal/service/auth"
|
||||
)
|
||||
|
||||
type IMiddleware interface {
|
||||
Handler() echo.MiddlewareFunc
|
||||
}
|
||||
|
||||
type Middleware struct {
|
||||
Logger IMiddleware
|
||||
Auth IMiddleware
|
||||
JSONResponse IMiddleware
|
||||
}
|
||||
|
||||
type Handlers struct {
|
||||
User *v1.UserController
|
||||
}
|
||||
|
||||
func NewHandler(
|
||||
user *v1.UserController,
|
||||
) *Handlers {
|
||||
return &Handlers{
|
||||
User: user,
|
||||
}
|
||||
}
|
||||
|
||||
func NewMiddleware(config *conf.Config, logger *logger.Logger, authService *auth.Service) *Middleware {
|
||||
return &Middleware{
|
||||
Logger: middleware.NewLoggerMiddleware(logger.Logger),
|
||||
Auth: middleware.NewAuthMiddleware(config, authService),
|
||||
JSONResponse: middleware.NewJSONResponseMiddleware(),
|
||||
}
|
||||
}
|
||||
|
||||
var ProviderSet = wire.NewSet(
|
||||
middleware.NewAuthMiddleware,
|
||||
middleware.NewLoggerMiddleware,
|
||||
middleware.NewJSONResponseMiddleware,
|
||||
NewMiddleware,
|
||||
v1.NewUserController,
|
||||
NewHandler,
|
||||
)
|
126
internal/handler/http/response/http.go
Normal file
126
internal/handler/http/response/http.go
Normal file
@ -0,0 +1,126 @@
|
||||
package response
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Body 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 *Body
|
||||
httpStatus int
|
||||
ctx echo.Context
|
||||
}
|
||||
|
||||
func Ctx(c echo.Context) *HttpResponse {
|
||||
return &HttpResponse{
|
||||
body: &Body{
|
||||
Wrap: true,
|
||||
},
|
||||
ctx: c,
|
||||
httpStatus: 0,
|
||||
}
|
||||
}
|
||||
|
||||
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() error {
|
||||
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 {
|
||||
return r.ctx.JSON(r.httpStatus, r.body)
|
||||
}
|
||||
|
||||
return r.ctx.JSON(r.httpStatus, r.body.Data)
|
||||
}
|
||||
|
||||
//
|
||||
//func ResponseMessage(c *gin.Context, code int, message string, data interface{}) {
|
||||
// c.JSON(code, &Body{
|
||||
// Message: message,
|
||||
// Data: data,
|
||||
// })
|
||||
// c.Abort()
|
||||
//}
|
||||
//
|
||||
//func ResponseError(c *gin.Context, code int, err error) {
|
||||
// c.JSON(code, &Body{
|
||||
// Error: err.Error(),
|
||||
// })
|
||||
// c.Abort()
|
||||
//}
|
||||
//
|
||||
//func Response(c *gin.Context, code int, data interface{}) {
|
||||
// c.JSON(code, &Body{
|
||||
// Data: data,
|
||||
// })
|
||||
// c.Abort()
|
||||
//}
|
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/labstack/echo/v4"
|
||||
"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 *echo.Group) {
|
||||
//r.GET("/ping", a.User.Test)
|
||||
|
||||
r.GET("/ping", a.HttpHandler.User.Test)
|
||||
}
|
||||
|
||||
func (a *Api) InitNoAuthApiRouter(r *echo.Group) {
|
||||
|
||||
}
|
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,
|
||||
)
|
20
internal/router/swagger.go
Normal file
20
internal/router/swagger.go
Normal file
@ -0,0 +1,20 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
_ "go-template/docs"
|
||||
|
||||
echoSwagger "github.com/swaggo/echo-swagger"
|
||||
)
|
||||
|
||||
type SwaggerRouter struct {
|
||||
//config *conf.Config
|
||||
}
|
||||
|
||||
func NewSwaggerRoute() *SwaggerRouter {
|
||||
return &SwaggerRouter{}
|
||||
}
|
||||
|
||||
func (a *SwaggerRouter) Register(e *echo.Group) {
|
||||
e.GET("/swagger/*", echoSwagger.WrapHandler)
|
||||
}
|
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)
|
||||
}
|
12
internal/schema/jwt.go
Normal file
12
internal/schema/jwt.go
Normal file
@ -0,0 +1,12 @@
|
||||
package schema
|
||||
|
||||
type JWTTokenTypes string
|
||||
|
||||
const (
|
||||
JWTAccessToken JWTTokenTypes = "access_token"
|
||||
JWTIDToken JWTTokenTypes = "id_token"
|
||||
)
|
||||
|
||||
func (jwtTokenTypes JWTTokenTypes) String() string {
|
||||
return string(jwtTokenTypes)
|
||||
}
|
22
internal/schema/stream.go
Normal file
22
internal/schema/stream.go
Normal file
@ -0,0 +1,22 @@
|
||||
package schema
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type EventMessage interface {
|
||||
JSON() ([]byte, error)
|
||||
}
|
||||
|
||||
type ProcessPostRequest struct {
|
||||
EventMessage
|
||||
PostId string `json:"post_id"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
func (p *ProcessPostRequest) JSON() ([]byte, error) {
|
||||
return json.Marshal(p)
|
||||
}
|
||||
|
||||
type ProcessPostResult struct {
|
||||
PostId string `json:"post_id"`
|
||||
Keywords []string `json:"keywords"`
|
||||
}
|
86
internal/schema/user.go
Normal file
86
internal/schema/user.go
Normal file
@ -0,0 +1,86 @@
|
||||
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"`
|
||||
Roles *UserRoles `json:"roles"`
|
||||
Permissions *UserPermissions `json:"permissions"`
|
||||
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 UserRole string
|
||||
type UserPermission struct{}
|
||||
|
||||
type UserRoles []UserRole
|
||||
type UserPermissions []UserPermission
|
||||
|
||||
type UserId string
|
||||
|
||||
func (u *User) GetId() UserId {
|
||||
return u.Token.Sub
|
||||
}
|
||||
|
||||
func (u *User) GetName() string {
|
||||
return u.Token.Name
|
||||
}
|
||||
|
||||
func (u *User) GetEmail() string {
|
||||
return u.Token.Email
|
||||
}
|
||||
|
||||
func (u *User) GetPhone() string {
|
||||
return u.Token.Phone
|
||||
}
|
||||
|
||||
func (u *User) GetRoles() *UserRoles {
|
||||
return u.Token.Roles
|
||||
}
|
||||
|
||||
func (u *User) GetPermissions() *UserPermissions {
|
||||
return u.Token.Permissions
|
||||
}
|
||||
|
||||
func (u UserId) String() string {
|
||||
return string(u)
|
||||
}
|
||||
|
||||
func (ur *UserRoles) Has(role UserRole) bool {
|
||||
for _, r := range *ur {
|
||||
if r == role {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (up *UserPermissions) Has(permission UserPermission) bool {
|
||||
for _, p := range *up {
|
||||
if p == permission {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
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"`
|
||||
}
|
111
internal/service/auth/auth.go
Normal file
111
internal/service/auth/auth.go
Normal file
@ -0,0 +1,111 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"go-template/internal/base/conf"
|
||||
"go-template/internal/base/logger"
|
||||
"go-template/internal/schema"
|
||||
"go-template/internal/service/jwks"
|
||||
"go-template/pkg/consts"
|
||||
)
|
||||
|
||||
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) 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) GetUserId(ctx echo.Context) (schema.UserId, error) {
|
||||
user, ok := a.GetUser(ctx)
|
||||
|
||||
if !ok {
|
||||
return "", consts.ErrUnauthorized
|
||||
}
|
||||
|
||||
return user.Token.Sub, nil
|
||||
}
|
||||
|
||||
func (a *Service) GetUser(ctx echo.Context) (*schema.User, bool) {
|
||||
user := ctx.Get(consts.AuthMiddlewareKey)
|
||||
|
||||
u, ok := user.(*schema.User)
|
||||
return u, ok
|
||||
}
|
||||
|
||||
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
|
||||
}
|
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
|
||||
}
|
38
internal/service/provider.go
Normal file
38
internal/service/provider.go
Normal file
@ -0,0 +1,38 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"go-template/internal/base/logger"
|
||||
"go-template/internal/service/auth"
|
||||
"go-template/internal/service/jwks"
|
||||
"go-template/internal/service/stream"
|
||||
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
logger *logger.Logger
|
||||
Jwks *jwks.JWKS
|
||||
Auth *auth.Service
|
||||
Stream *stream.Service
|
||||
}
|
||||
|
||||
var Provider = wire.NewSet(
|
||||
jwks.NewJWKS,
|
||||
auth.NewAuthService,
|
||||
stream.NewService,
|
||||
NewService,
|
||||
)
|
||||
|
||||
func NewService(
|
||||
logger *logger.Logger,
|
||||
jwks *jwks.JWKS,
|
||||
auth *auth.Service,
|
||||
stream *stream.Service,
|
||||
) *Service {
|
||||
return &Service{
|
||||
logger,
|
||||
jwks,
|
||||
auth,
|
||||
stream,
|
||||
}
|
||||
}
|
68
internal/service/stream/consumer.go
Normal file
68
internal/service/stream/consumer.go
Normal file
@ -0,0 +1,68 @@
|
||||
package stream
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/segmentio/kafka-go"
|
||||
"time"
|
||||
)
|
||||
|
||||
//func (s *Service) Listen(topic string, handler HandlerFunc) error {
|
||||
// conn, err := s.dial(topic)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// batch := conn.ReadBatch(10e3, 1e6) // fetch 10KB min, 1MB max
|
||||
//
|
||||
// b := make([]byte, 10e3) // 10KB max per message
|
||||
// for {
|
||||
// n, err := batch.Read(b)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// handler(b[:n])
|
||||
// }
|
||||
//}
|
||||
|
||||
func (s *Service) Consumer(topic string, groupId string) *kafka.Reader {
|
||||
var r = kafka.ReaderConfig{
|
||||
Brokers: s.config.Kafka.BootstrapServers,
|
||||
GroupID: groupId,
|
||||
GroupTopics: nil,
|
||||
Topic: topic,
|
||||
CommitInterval: time.Second,
|
||||
//StartOffset: kafka., // 仅对新创建的消费者组生效,从头开始消费,工作中可能更常用从最新的开始消费kafka.LastOffset
|
||||
Logger: nil,
|
||||
ErrorLogger: nil,
|
||||
IsolationLevel: 0,
|
||||
MaxAttempts: 0,
|
||||
OffsetOutOfRangeError: false,
|
||||
MaxBytes: 10e6, // 10MB
|
||||
}
|
||||
|
||||
if s.config.Kafka.Username != "" && s.config.Kafka.Password != "" {
|
||||
r.Dialer = &kafka.Dialer{
|
||||
Timeout: 10 * time.Second,
|
||||
DualStack: true,
|
||||
SASLMechanism: s.auth(),
|
||||
}
|
||||
}
|
||||
|
||||
return kafka.NewReader(r)
|
||||
|
||||
}
|
||||
|
||||
type HandlerFunc func([]byte)
|
||||
|
||||
// ReadMessage 消费消息
|
||||
func (s *Service) ReadMessage(ctx context.Context, topic string, groupId string) {
|
||||
for {
|
||||
if msg, err := s.Consumer(topic, groupId).ReadMessage(ctx); err != nil {
|
||||
fmt.Println(fmt.Sprintf("读kafka失败,err:%v", err))
|
||||
continue
|
||||
} else {
|
||||
fmt.Println(fmt.Sprintf("topic=%s,partition=%d,offset=%d,key=%s,value=%s", msg.Topic, msg.Partition, msg.Offset, msg.Key, msg.Value))
|
||||
}
|
||||
}
|
||||
}
|
13
internal/service/stream/kafka.go
Normal file
13
internal/service/stream/kafka.go
Normal file
@ -0,0 +1,13 @@
|
||||
package stream
|
||||
|
||||
import (
|
||||
"github.com/segmentio/kafka-go/sasl/plain"
|
||||
)
|
||||
|
||||
func (s *Service) auth() plain.Mechanism {
|
||||
mechanism := plain.Mechanism{
|
||||
Username: s.config.Kafka.Username,
|
||||
Password: s.config.Kafka.Password,
|
||||
}
|
||||
return mechanism
|
||||
}
|
119
internal/service/stream/producer.go
Normal file
119
internal/service/stream/producer.go
Normal file
@ -0,0 +1,119 @@
|
||||
package stream
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/segmentio/kafka-go"
|
||||
"go-template/internal/schema"
|
||||
"time"
|
||||
)
|
||||
|
||||
//var connections = map[string]*kafka.Conn{}
|
||||
|
||||
//func (s *Service) dial(topic string) (*kafka.Conn, error) {
|
||||
//
|
||||
// // 如果topic 存在于 connections 则直接返回
|
||||
// if conn, ok := connections[topic]; ok {
|
||||
// return conn, nil
|
||||
// }
|
||||
//
|
||||
// ctx := context.Background()
|
||||
//
|
||||
// conn, err := kafka.DialLeader(ctx, "tcp", s.config.Kafka.BootstrapServers[0], s.topic(topic), 0)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// //err = conn.SetWriteDeadline(time.Now().Add(10 * time.Second))
|
||||
// //if err != nil {
|
||||
// // return conn, err
|
||||
// //}
|
||||
// //
|
||||
// //// set read deadline
|
||||
// //err = conn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||
// //if err != nil {
|
||||
// // return conn, err
|
||||
// //}
|
||||
//
|
||||
// connections[topic] = conn
|
||||
//
|
||||
// return conn, nil
|
||||
//}
|
||||
//
|
||||
//func (s *Service) Publish(topic string, message ...[]byte) error {
|
||||
// conn, err := s.dial(topic)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// msg := make([]kafka.Message, len(message))
|
||||
// for i, v := range message {
|
||||
// msg[i] = kafka.Message{Value: v}
|
||||
// }
|
||||
//
|
||||
// _, err = conn.WriteMessages(msg...)
|
||||
//
|
||||
// return err
|
||||
//}
|
||||
|
||||
func (s *Service) Producer(topic string) *kafka.Writer {
|
||||
var w = &kafka.Writer{
|
||||
Addr: kafka.TCP(s.config.Kafka.BootstrapServers...),
|
||||
Topic: topic,
|
||||
Balancer: &kafka.Hash{}, // 用于对key进行hash,决定消息发送到哪个分区
|
||||
MaxAttempts: 0,
|
||||
WriteBackoffMin: 0,
|
||||
WriteBackoffMax: 0,
|
||||
BatchSize: 0,
|
||||
BatchBytes: 0,
|
||||
BatchTimeout: 0,
|
||||
ReadTimeout: 0,
|
||||
//WriteTimeout: time.Second, // kafka有时候可能负载很高,写不进去,那么超时后可以放弃写入,用于可以丢消息的场景
|
||||
RequiredAcks: kafka.RequireAll, // 不需要任何节点确认就返回
|
||||
Async: true,
|
||||
Completion: nil,
|
||||
Compression: 0,
|
||||
Logger: nil,
|
||||
ErrorLogger: nil,
|
||||
Transport: nil,
|
||||
AllowAutoTopicCreation: false, // 第一次发消息的时候,如果topic不存在,就自动创建topic,工作中禁止使用
|
||||
}
|
||||
|
||||
if s.config.Kafka.Username != "" && s.config.Kafka.Password != "" {
|
||||
w.Transport = &kafka.Transport{
|
||||
SASL: s.auth(),
|
||||
}
|
||||
}
|
||||
|
||||
return w
|
||||
}
|
||||
|
||||
func (s *Service) SendMessage(ctx context.Context, topic string, data []byte) error {
|
||||
msg := kafka.Message{
|
||||
Partition: 0,
|
||||
Offset: 0,
|
||||
HighWaterMark: 0,
|
||||
//Key: key,
|
||||
Value: data,
|
||||
Time: time.Time{},
|
||||
}
|
||||
|
||||
err := s.Producer(topic).WriteMessages(ctx, msg)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Service) SendEvent(ctx context.Context, topic string, data schema.EventMessage) error {
|
||||
j, err := data.JSON()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
msg := kafka.Message{
|
||||
Partition: 0,
|
||||
Offset: 0,
|
||||
HighWaterMark: 0,
|
||||
Value: j,
|
||||
Time: time.Time{},
|
||||
}
|
||||
|
||||
err = s.Producer(topic).WriteMessages(ctx, msg)
|
||||
return err
|
||||
}
|
15
internal/service/stream/provider.go
Normal file
15
internal/service/stream/provider.go
Normal file
@ -0,0 +1,15 @@
|
||||
package stream
|
||||
|
||||
import (
|
||||
"go-template/internal/base/conf"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
config *conf.Config
|
||||
}
|
||||
|
||||
func NewService(config *conf.Config) *Service {
|
||||
return &Service{
|
||||
config,
|
||||
}
|
||||
}
|
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
|
||||
}
|
||||
}
|
31
pkg/consts/auth.go
Normal file
31
pkg/consts/auth.go
Normal file
@ -0,0 +1,31 @@
|
||||
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 not valid")
|
||||
ErrJWTFormatError = errors.New("JWT format error")
|
||||
ErrNotBearerType = errors.New("not bearer token")
|
||||
ErrEmptyResponse = errors.New("empty response")
|
||||
ErrTokenError = errors.New("token type error")
|
||||
ErrUnauthorized = errors.New("unauthorized")
|
||||
ErrAudienceNotAllowed = errors.New("audience not allowed")
|
||||
ErrBearerToken = errors.New("无效的 Bearer 令牌")
|
||||
|
||||
ErrNotYourResource = errors.New("this resource not yours")
|
||||
ErrPermissionDenied = errors.New("permission denied")
|
||||
)
|
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")
|
||||
)
|
7
pkg/consts/rbac.go
Normal file
7
pkg/consts/rbac.go
Normal file
@ -0,0 +1,7 @@
|
||||
package consts
|
||||
|
||||
import "go-template/internal/schema"
|
||||
|
||||
const (
|
||||
RoleSuperAdmin schema.UserRole = "super-admin"
|
||||
)
|
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