14 Commits

Author SHA1 Message Date
44345bb9f7 feat: 添加 HttpRoute 接口的 Path 和 Middlewares 方法 2025-12-17 23:50:27 +08:00
Rogee
744ae45c15 feat: add utility functions for environment variable handling, file operations, pointer manipulation, random generation, and string processing 2025-09-12 11:40:52 +08:00
Rogee
205c08b00d feat: update Local function to accept any type for key parameter 2025-09-12 08:59:30 +08:00
Rogee
dad2a26611 feat: update EventHandler and EventPublisher interfaces to include Channel and PublishTo methods 2025-09-11 14:10:38 +08:00
rogeecn
f9e82eba02 feat: support later funcs 2025-03-21 19:13:42 +08:00
rogeecn
661ebaf6c9 feat: add unique id to cron job 2025-03-21 16:54:26 +08:00
rogeecn
885c99ea66 feat: job cancel 2025-03-17 11:42:13 +08:00
rogeecn
24b3de2c38 feat: remove kind 2025-03-17 10:32:11 +08:00
Rogee
4bc900f387 feat: support cronjob initers 2025-03-15 21:17:12 +08:00
rogeecn
e7a1db2c16 fix: job contracts 2025-03-11 09:44:44 +08:00
Rogee
c8cf318faa feat: add event contracts 2025-02-11 15:51:29 +08:00
Rogee
c4bd0d66a9 feat: update fiber to beta4 2025-02-11 15:26:05 +08:00
Rogee
d7acdbb34b feat: update atom framework 2025-02-11 15:12:35 +08:00
Rogee
fd8f2ebe03 fix: config container 2025-01-08 15:10:54 +08:00
35 changed files with 1476 additions and 725 deletions

View File

@@ -1,42 +0,0 @@
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"
[build]
args_bin = []
bin = "./tmp/main"
cmd = "go build -o ./tmp/main ."
delay = 0
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
exclude_file = []
exclude_regex = ["_test.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = ""
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html"]
include_file = []
kill_delay = "0s"
log = "build-errors.log"
rerun = false
rerun_delay = 500
send_interrupt = false
stop_on_error = false
[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"
[log]
main_only = false
time = false
[misc]
clean_on_exit = false
[screen]
clear_on_rebuild = false
keep_scroll = true

10
.gitignore vendored
View File

@@ -1,10 +0,0 @@
vendor/
__debug_bin
.vscode
.idea
tmp/
docker-compose.yml
atom
sqlite.db
go.work
go.work.sum

View File

@@ -1,39 +0,0 @@
# version-file which will write or read current semver
version-file = "internal/version/version"
# hook scripts
[hooks]
# after version calc,
# with use the {{ .Version }} to upgrade other files.
post-version = [
"sed -i -e 's/\"version\": \"[^\"]*\"/\"version\": \"{{ .Version }}\"/g' testdata/package.json",
"sed -i -e 's/version: [^\\n]*/version: {{ .Version }}/g' testdata/pubspec.yaml"
]
# git hook pre commit
pre-commit = [
"golangci-lint run",
"husky lint-staged",
]
# git hook commit msg
commit-msg = [
"husky lint-commit",
]
# list staged files do some pre-process and git add
[lint-staged]
"*.go" = [
"goimports -l -w",
"gofmt -l -w",
]
# commit msg rule default support conventional commits
[lint-commit]
# could check if this exists
# email = "^(.+@gmail.com|.+@qq.com)$"
# optional custom types check regex
# types = "^(feat|fix|build|chore|ci|docs|perf|refactor|revert|style|test)$"
# optional header check regex
# header = "^(?P<type>\w+)(\((?P<scope>[\w/.-]+)\))?(?P<breaking>!)?:( +)?(?P<header>.+)"

View File

@@ -152,9 +152,9 @@ module/
"github.com/rogeecn/atom"
"github.com/rogeecn/atom-addons/providers/swagger"
"git.ipao.vip/rogeecn/atom/container"
"git.ipao.vip/rogeecn/atom/contracts"
"git.ipao.vip/rogeecn/atom/utils/opt"
"go.ipao.vip/atom/container"
"go.ipao.vip/atom/contracts"
"go.ipao.vip/atom/utils/opt"
)
func Providers() container.Providers {

View File

@@ -1,10 +1,10 @@
package atom
import (
"git.ipao.vip/rogeecn/atom/config"
"git.ipao.vip/rogeecn/atom/container"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"go.ipao.vip/atom/config"
"go.ipao.vip/atom/container"
"go.uber.org/dig"
)

View File

@@ -1,125 +0,0 @@
[App]
Mode = "debug" # develop, production
[Captcha]
KeyLong = 6
ImgWidth = 240 #验证码宽度
ImgHeight = 80 # 验证码高度
OpenCaptcha = 0 # 防爆破验证码开启此数0代表每次登录都需要验证码其他数字代表错误密码此数如3代表错误三次后出现验证码
OpenCaptchaTimeOut = "1h" # 防爆破验证码超时时间单位s(秒)
[Storage]
Driver = "local"
[Storage.Local]
Path = "./storage"
[Storage.AwsS3]
Bucket = "bucket"
Region = "region"
Endpoint = "endpoint"
DisableSSL = false
SecretID = ""
SecretKey = ""
BaseURL = ""
Path = ""
S3ForcePathStyle = false
[Storage.AliYunOSS]
Bucket = "bucket"
Region = "region"
Endpoint = "endpoint"
AccessKeyID = ""
AccessKeySecret = ""
BaseURL = ""
Path = ""
[Http]
Static = "./dist"
Https = false
HttpsCert = ""
HttpKey = ""
Port = 9800
[Http.Captcha]
KeyLong = 6
Width = 240
Height = 80
OpenCaptcha = 0
OpenCaptchaTimeout = 3600
[Http.JWT]
SigningKey = "f3a0ed18-3eea-4bc9-b440-d56c3bb77bd8"
ExpiresTime = "168h" # 7 days
Issuer = "AtomFramework"
[Http.Cors]
# 跨域配置
# 需要配合 server/initialize/router.go#L32 使用
# 放行模式: Allow-all, 放行全部; whitelist, 白名单模式, 来自白名单内域名的请求添加 cors 头; strict-whitelist 严格白名单模式, 白名单外的请求一律拒绝
Mode = "strict-whitelist"
[[Http.Cors.Whitelist]]
AllowOrigin = "example1.com"
AllowHeaders = "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id"
AllowMethods = "POST, GET"
ExposeHeaders = "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type"
AllowCredentials = true
[[Http.Cors.Whitelist]]
AllowOrigin = "example2.com"
AllowHeaders = "content-type"
AllowMethods = "GET, POST"
ExposeHeaders = "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type"
AllowCredentials = true
[Log]
Driver = "zap"
Level = "debug"
[Log.Zap]
Prefix = "[github.com/flipped-aurora/gin-vue-admin/server]"
Format = "console"
Director = "log"
EncodeLevel = "LowercaseColorLevelEncoder"
StacktraceKey = "stacktrace"
MaxAge = 0
ShowLine = true
LogInConsole = true
[Database]
Driver = "sqlite"
[Database.MySQL]
Host = "10.47.119.226"
Port = 3306
Database = "atom"
Username = "root"
Password = "root"
Prefix = ""
Singular = false
MaxIdleConns = 10
MaxOpenConns = 200
Engine = "InnoDB"
[Database.PostgreSQL]
Host = "10.95.31.212"
Port = 5442
Database = "cspm"
Username = "postgres"
Password = "zHTz7H6S9WJQK7Y0"
Prefix = ""
TimeZone = "Asia/Shanghai"
SslMode = "disable"
Singular = false
MaxIdleConns = 10
MaxOpenConns = 200
[Database.SQLite]
File = "data.db"
[Database.Redis]
Host = "10.47.119.226"
Port = 6379
Database = 0
Password = ""

View File

@@ -5,8 +5,8 @@ import (
"path/filepath"
"github.com/pkg/errors"
"github.com/rogeecn/atom/container"
"github.com/spf13/viper"
"go.ipao.vip/atom/container"
)
func Load(file string) (*viper.Viper, error) {

View File

@@ -7,8 +7,8 @@ import (
"os/signal"
"syscall"
"git.ipao.vip/rogeecn/atom/utils/opt"
"github.com/spf13/viper"
"go.ipao.vip/atom/opt"
"go.uber.org/dig"
)
@@ -75,3 +75,18 @@ func (p Providers) Provide(config *viper.Viper) error {
}
return nil
}
// laters for run later funcs
var later []func() error
func Later(f func() error) {
later = append(later, f)
}
func RunLaterFuncs() {
for _, f := range later {
if err := f(); err != nil {
log.Fatal(err)
}
}
}

View File

@@ -1,15 +1,23 @@
package contracts
import (
"time"
"github.com/riverqueue/river"
)
type CronJob interface {
Description() string
Periodic() time.Duration
JobArgs() []river.JobArgs
InsertOpts() *river.InsertOpts
RunOnStart() bool
Args() []CronJobArg
}
type JobArgs interface {
river.JobArgs
river.JobArgsWithInsertOpts
UniqueID() string
}
type CronJobArg struct {
RunOnStart bool
PeriodicInterval river.PeriodicSchedule
Arg JobArgs
}

View File

@@ -4,6 +4,15 @@ import "github.com/ThreeDotsLabs/watermill/message"
type EventHandler interface {
Topic() string
PublishToTopic() string
Channel() Channel
PublishTo() (Channel, string)
Handler(msg *message.Message) ([]*message.Message, error)
}
type Channel string
type EventPublisher interface {
Topic() string
Channel() Channel
Marshal() ([]byte, error)
}

View File

@@ -7,4 +7,6 @@ import (
type HttpRoute interface {
Register(fiber.Router)
Name() string
Path() string
Middlewares() []any
}

94
fen/bind.go Normal file
View File

@@ -0,0 +1,94 @@
package fen
import (
"mime/multipart"
"github.com/gofiber/fiber/v3"
"github.com/pkg/errors"
)
func File[T any](key string) func(fiber.Ctx) (*multipart.FileHeader, error) {
return func(ctx fiber.Ctx) (*multipart.FileHeader, error) {
_ = new(T)
return ctx.FormFile(key)
}
}
func Local[T any](key any) func(fiber.Ctx) (T, error) {
return func(ctx fiber.Ctx) (T, error) {
v := fiber.Locals[T](ctx, key)
return v, nil
}
}
func Path[T fiber.GenericType](key string) func(fiber.Ctx) (T, error) {
return func(ctx fiber.Ctx) (T, error) {
v := fiber.Params[T](ctx, key)
return v, nil
}
}
func PathParam[T fiber.GenericType](name string) func(fiber.Ctx) (T, error) {
return func(ctx fiber.Ctx) (T, error) {
v := fiber.Params[T](ctx, name)
return v, nil
}
}
func Body[T any](name string) func(fiber.Ctx) (*T, error) {
return func(ctx fiber.Ctx) (*T, error) {
p := new(T)
if err := ctx.Bind().Body(p); err != nil {
return nil, errors.Wrapf(err, "body: %s", name)
}
return p, nil
}
}
func QueryParam[T fiber.GenericType](key string) func(fiber.Ctx) (T, error) {
return func(ctx fiber.Ctx) (T, error) {
v := fiber.Query[T](ctx, key)
return v, nil
}
}
func Query[T any](name string) func(fiber.Ctx) (*T, error) {
return func(ctx fiber.Ctx) (*T, error) {
p := new(T)
if err := ctx.Bind().Query(p); err != nil {
return nil, errors.Wrapf(err, "query: %s", name)
}
return p, nil
}
}
func Header[T any](name string) func(fiber.Ctx) (*T, error) {
return func(ctx fiber.Ctx) (*T, error) {
p := new(T)
err := ctx.Bind().Header(p)
if err != nil {
return nil, errors.Wrapf(err, "header: %s", name)
}
return p, nil
}
}
func Cookie[T any](name string) func(fiber.Ctx) (*T, error) {
return func(ctx fiber.Ctx) (*T, error) {
p := new(T)
if err := ctx.Bind().Cookie(p); err != nil {
return nil, errors.Wrapf(err, "cookie: %s", name)
}
return p, nil
}
}
func CookieParam(name string) func(fiber.Ctx) (string, error) {
return func(ctx fiber.Ctx) (string, error) {
return ctx.Cookies(name), nil
}
}

374
fen/func.go Normal file
View File

@@ -0,0 +1,374 @@
package fen
import (
"github.com/gofiber/fiber/v3"
)
var Func0 = Func
func Func(f fiber.Handler) fiber.Handler {
return f
}
func Func1[P1 any](
f func(fiber.Ctx, P1) error,
pf1 func(fiber.Ctx) (P1, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p, err := pf1(ctx)
if err != nil {
return err
}
return f(ctx, p)
}
}
func Func2[P1, P2 any](
f func(fiber.Ctx, P1, P2) error,
pf1 func(fiber.Ctx) (P1, error),
pf2 func(fiber.Ctx) (P2, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p1, err := pf1(ctx)
if err != nil {
return err
}
p2, err := pf2(ctx)
if err != nil {
return err
}
return f(ctx, p1, p2)
}
}
func Func3[P1, P2, P3 any](
f func(fiber.Ctx, P1, P2, P3) error,
pf1 func(fiber.Ctx) (P1, error),
pf2 func(fiber.Ctx) (P2, error),
pf3 func(fiber.Ctx) (P3, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p1, err := pf1(ctx)
if err != nil {
return err
}
p2, err := pf2(ctx)
if err != nil {
return err
}
p3, err := pf3(ctx)
if err != nil {
return err
}
return f(ctx, p1, p2, p3)
}
}
func Func4[P1, P2, P3, P4 any](
f func(fiber.Ctx, P1, P2, P3, P4) error,
pf1 func(fiber.Ctx) (P1, error),
pf2 func(fiber.Ctx) (P2, error),
pf3 func(fiber.Ctx) (P3, error),
pf4 func(fiber.Ctx) (P4, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p1, err := pf1(ctx)
if err != nil {
return err
}
p2, err := pf2(ctx)
if err != nil {
return err
}
p3, err := pf3(ctx)
if err != nil {
return err
}
p4, err := pf4(ctx)
if err != nil {
return err
}
return f(ctx, p1, p2, p3, p4)
}
}
func Func5[P1, P2, P3, P4, P5 any](
f func(fiber.Ctx, P1, P2, P3, P4, P5) error,
pf1 func(fiber.Ctx) (P1, error),
pf2 func(fiber.Ctx) (P2, error),
pf3 func(fiber.Ctx) (P3, error),
pf4 func(fiber.Ctx) (P4, error),
pf5 func(fiber.Ctx) (P5, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p1, err := pf1(ctx)
if err != nil {
return err
}
p2, err := pf2(ctx)
if err != nil {
return err
}
p3, err := pf3(ctx)
if err != nil {
return err
}
p4, err := pf4(ctx)
if err != nil {
return err
}
p5, err := pf5(ctx)
if err != nil {
return err
}
return f(ctx, p1, p2, p3, p4, p5)
}
}
func Func6[P1, P2, P3, P4, P5, P6 any](
f func(fiber.Ctx, P1, P2, P3, P4, P5, P6) error,
pf1 func(fiber.Ctx) (P1, error),
pf2 func(fiber.Ctx) (P2, error),
pf3 func(fiber.Ctx) (P3, error),
pf4 func(fiber.Ctx) (P4, error),
pf5 func(fiber.Ctx) (P5, error),
pf6 func(fiber.Ctx) (P6, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p1, err := pf1(ctx)
if err != nil {
return err
}
p2, err := pf2(ctx)
if err != nil {
return err
}
p3, err := pf3(ctx)
if err != nil {
return err
}
p4, err := pf4(ctx)
if err != nil {
return err
}
p5, err := pf5(ctx)
if err != nil {
return err
}
p6, err := pf6(ctx)
if err != nil {
return err
}
return f(ctx, p1, p2, p3, p4, p5, p6)
}
}
func Func7[P1, P2, P3, P4, P5, P6, P7 any](
f func(fiber.Ctx, P1, P2, P3, P4, P5, P6, P7) error,
pf1 func(fiber.Ctx) (P1, error),
pf2 func(fiber.Ctx) (P2, error),
pf3 func(fiber.Ctx) (P3, error),
pf4 func(fiber.Ctx) (P4, error),
pf5 func(fiber.Ctx) (P5, error),
pf6 func(fiber.Ctx) (P6, error),
pf7 func(fiber.Ctx) (P7, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p1, err := pf1(ctx)
if err != nil {
return err
}
p2, err := pf2(ctx)
if err != nil {
return err
}
p3, err := pf3(ctx)
if err != nil {
return err
}
p4, err := pf4(ctx)
if err != nil {
return err
}
p5, err := pf5(ctx)
if err != nil {
return err
}
p6, err := pf6(ctx)
if err != nil {
return err
}
p7, err := pf7(ctx)
if err != nil {
return err
}
return f(ctx, p1, p2, p3, p4, p5, p6, p7)
}
}
func Func8[P1, P2, P3, P4, P5, P6, P7, P8 any](
f func(fiber.Ctx, P1, P2, P3, P4, P5, P6, P7, P8) error,
pf1 func(fiber.Ctx) (P1, error),
pf2 func(fiber.Ctx) (P2, error),
pf3 func(fiber.Ctx) (P3, error),
pf4 func(fiber.Ctx) (P4, error),
pf5 func(fiber.Ctx) (P5, error),
pf6 func(fiber.Ctx) (P6, error),
pf7 func(fiber.Ctx) (P7, error),
pf8 func(fiber.Ctx) (P8, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p1, err := pf1(ctx)
if err != nil {
return err
}
p2, err := pf2(ctx)
if err != nil {
return err
}
p3, err := pf3(ctx)
if err != nil {
return err
}
p4, err := pf4(ctx)
if err != nil {
return err
}
p5, err := pf5(ctx)
if err != nil {
return err
}
p6, err := pf6(ctx)
if err != nil {
return err
}
p7, err := pf7(ctx)
if err != nil {
return err
}
p8, err := pf8(ctx)
if err != nil {
return err
}
return f(ctx, p1, p2, p3, p4, p5, p6, p7, p8)
}
}
func Func9[P1, P2, P3, P4, P5, P6, P7, P8, P9 any](
f func(fiber.Ctx, P1, P2, P3, P4, P5, P6, P7, P8, P9) error,
pf1 func(fiber.Ctx) (P1, error),
pf2 func(fiber.Ctx) (P2, error),
pf3 func(fiber.Ctx) (P3, error),
pf4 func(fiber.Ctx) (P4, error),
pf5 func(fiber.Ctx) (P5, error),
pf6 func(fiber.Ctx) (P6, error),
pf7 func(fiber.Ctx) (P7, error),
pf8 func(fiber.Ctx) (P8, error),
pf9 func(fiber.Ctx) (P9, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p1, err := pf1(ctx)
if err != nil {
return err
}
p2, err := pf2(ctx)
if err != nil {
return err
}
p3, err := pf3(ctx)
if err != nil {
return err
}
p4, err := pf4(ctx)
if err != nil {
return err
}
p5, err := pf5(ctx)
if err != nil {
return err
}
p6, err := pf6(ctx)
if err != nil {
return err
}
p7, err := pf7(ctx)
if err != nil {
return err
}
p8, err := pf8(ctx)
if err != nil {
return err
}
p9, err := pf9(ctx)
if err != nil {
return err
}
return f(ctx, p1, p2, p3, p4, p5, p6, p7, p8, p9)
}
}
func Func10[P1, P2, P3, P4, P5, P6, P7, P8, P9, P10 any](
f func(fiber.Ctx, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) error,
pf1 func(fiber.Ctx) (P1, error),
pf2 func(fiber.Ctx) (P2, error),
pf3 func(fiber.Ctx) (P3, error),
pf4 func(fiber.Ctx) (P4, error),
pf5 func(fiber.Ctx) (P5, error),
pf6 func(fiber.Ctx) (P6, error),
pf7 func(fiber.Ctx) (P7, error),
pf8 func(fiber.Ctx) (P8, error),
pf9 func(fiber.Ctx) (P9, error),
pf10 func(fiber.Ctx) (P10, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p1, err := pf1(ctx)
if err != nil {
return err
}
p2, err := pf2(ctx)
if err != nil {
return err
}
p3, err := pf3(ctx)
if err != nil {
return err
}
p4, err := pf4(ctx)
if err != nil {
return err
}
p5, err := pf5(ctx)
if err != nil {
return err
}
p6, err := pf6(ctx)
if err != nil {
return err
}
p7, err := pf7(ctx)
if err != nil {
return err
}
p8, err := pf8(ctx)
if err != nil {
return err
}
p9, err := pf9(ctx)
if err != nil {
return err
}
p10, err := pf10(ctx)
if err != nil {
return err
}
return f(ctx, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)
}
}

413
fen/func_data.go Normal file
View File

@@ -0,0 +1,413 @@
package fen
import (
"github.com/gofiber/fiber/v3"
)
func DataFunc0[T any](
f func(fiber.Ctx) (T, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
data, err := f(ctx)
if err != nil {
return err
}
return ctx.JSON(data)
}
}
func DataFunc1[T, P1 any](
f func(fiber.Ctx, P1) (T, error),
pf1 func(fiber.Ctx) (P1, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p, err := pf1(ctx)
if err != nil {
return err
}
data, err := f(ctx, p)
if err != nil {
return err
}
return ctx.JSON(data)
}
}
func DataFunc2[T, P1, P2 any](
f func(fiber.Ctx, P1, P2) (T, error),
pf1 func(fiber.Ctx) (P1, error),
pf2 func(fiber.Ctx) (P2, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p1, err := pf1(ctx)
if err != nil {
return err
}
p2, err := pf2(ctx)
if err != nil {
return err
}
data, err := f(ctx, p1, p2)
if err != nil {
return err
}
return ctx.JSON(data)
}
}
func DataFunc3[T, P1, P2, P3 any](
f func(fiber.Ctx, P1, P2, P3) (T, error),
pf1 func(fiber.Ctx) (P1, error),
pf2 func(fiber.Ctx) (P2, error),
pf3 func(fiber.Ctx) (P3, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p1, err := pf1(ctx)
if err != nil {
return err
}
p2, err := pf2(ctx)
if err != nil {
return err
}
p3, err := pf3(ctx)
if err != nil {
return err
}
data, err := f(ctx, p1, p2, p3)
if err != nil {
return err
}
return ctx.JSON(data)
}
}
func DataFunc4[T, P1, P2, P3, P4 any](
f func(fiber.Ctx, P1, P2, P3, P4) (T, error),
pf1 func(fiber.Ctx) (P1, error),
pf2 func(fiber.Ctx) (P2, error),
pf3 func(fiber.Ctx) (P3, error),
pf4 func(fiber.Ctx) (P4, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p1, err := pf1(ctx)
if err != nil {
return err
}
p2, err := pf2(ctx)
if err != nil {
return err
}
p3, err := pf3(ctx)
if err != nil {
return err
}
p4, err := pf4(ctx)
if err != nil {
return err
}
data, err := f(ctx, p1, p2, p3, p4)
if err != nil {
return err
}
return ctx.JSON(data)
}
}
func DataFunc5[T, P1, P2, P3, P4, P5 any](
f func(fiber.Ctx, P1, P2, P3, P4, P5) (T, error),
pf1 func(fiber.Ctx) (P1, error),
pf2 func(fiber.Ctx) (P2, error),
pf3 func(fiber.Ctx) (P3, error),
pf4 func(fiber.Ctx) (P4, error),
pf5 func(fiber.Ctx) (P5, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p1, err := pf1(ctx)
if err != nil {
return err
}
p2, err := pf2(ctx)
if err != nil {
return err
}
p3, err := pf3(ctx)
if err != nil {
return err
}
p4, err := pf4(ctx)
if err != nil {
return err
}
p5, err := pf5(ctx)
if err != nil {
return err
}
data, err := f(ctx, p1, p2, p3, p4, p5)
if err != nil {
return err
}
return ctx.JSON(data)
}
}
func DataFunc6[T, P1, P2, P3, P4, P5, P6 any](
f func(fiber.Ctx, P1, P2, P3, P4, P5, P6) (T, error),
pf1 func(fiber.Ctx) (P1, error),
pf2 func(fiber.Ctx) (P2, error),
pf3 func(fiber.Ctx) (P3, error),
pf4 func(fiber.Ctx) (P4, error),
pf5 func(fiber.Ctx) (P5, error),
pf6 func(fiber.Ctx) (P6, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p1, err := pf1(ctx)
if err != nil {
return err
}
p2, err := pf2(ctx)
if err != nil {
return err
}
p3, err := pf3(ctx)
if err != nil {
return err
}
p4, err := pf4(ctx)
if err != nil {
return err
}
p5, err := pf5(ctx)
if err != nil {
return err
}
p6, err := pf6(ctx)
if err != nil {
return err
}
data, err := f(ctx, p1, p2, p3, p4, p5, p6)
if err != nil {
return err
}
return ctx.JSON(data)
}
}
func DataFunc7[T, P1, P2, P3, P4, P5, P6, P7 any](
f func(fiber.Ctx, P1, P2, P3, P4, P5, P6, P7) (T, error),
pf1 func(fiber.Ctx) (P1, error),
pf2 func(fiber.Ctx) (P2, error),
pf3 func(fiber.Ctx) (P3, error),
pf4 func(fiber.Ctx) (P4, error),
pf5 func(fiber.Ctx) (P5, error),
pf6 func(fiber.Ctx) (P6, error),
pf7 func(fiber.Ctx) (P7, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p1, err := pf1(ctx)
if err != nil {
return err
}
p2, err := pf2(ctx)
if err != nil {
return err
}
p3, err := pf3(ctx)
if err != nil {
return err
}
p4, err := pf4(ctx)
if err != nil {
return err
}
p5, err := pf5(ctx)
if err != nil {
return err
}
p6, err := pf6(ctx)
if err != nil {
return err
}
p7, err := pf7(ctx)
if err != nil {
return err
}
data, err := f(ctx, p1, p2, p3, p4, p5, p6, p7)
if err != nil {
return err
}
return ctx.JSON(data)
}
}
func DataFunc8[T, P1, P2, P3, P4, P5, P6, P7, P8 any](
f func(fiber.Ctx, P1, P2, P3, P4, P5, P6, P7, P8) (T, error),
pf1 func(fiber.Ctx) (P1, error),
pf2 func(fiber.Ctx) (P2, error),
pf3 func(fiber.Ctx) (P3, error),
pf4 func(fiber.Ctx) (P4, error),
pf5 func(fiber.Ctx) (P5, error),
pf6 func(fiber.Ctx) (P6, error),
pf7 func(fiber.Ctx) (P7, error),
pf8 func(fiber.Ctx) (P8, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p1, err := pf1(ctx)
if err != nil {
return err
}
p2, err := pf2(ctx)
if err != nil {
return err
}
p3, err := pf3(ctx)
if err != nil {
return err
}
p4, err := pf4(ctx)
if err != nil {
return err
}
p5, err := pf5(ctx)
if err != nil {
return err
}
p6, err := pf6(ctx)
if err != nil {
return err
}
p7, err := pf7(ctx)
if err != nil {
return err
}
p8, err := pf8(ctx)
if err != nil {
return err
}
data, err := f(ctx, p1, p2, p3, p4, p5, p6, p7, p8)
if err != nil {
return err
}
return ctx.JSON(data)
}
}
func DataFunc9[T, P1, P2, P3, P4, P5, P6, P7, P8, P9 any](
f func(fiber.Ctx, P1, P2, P3, P4, P5, P6, P7, P8, P9) (T, error),
pf1 func(fiber.Ctx) (P1, error),
pf2 func(fiber.Ctx) (P2, error),
pf3 func(fiber.Ctx) (P3, error),
pf4 func(fiber.Ctx) (P4, error),
pf5 func(fiber.Ctx) (P5, error),
pf6 func(fiber.Ctx) (P6, error),
pf7 func(fiber.Ctx) (P7, error),
pf8 func(fiber.Ctx) (P8, error),
pf9 func(fiber.Ctx) (P9, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p1, err := pf1(ctx)
if err != nil {
return err
}
p2, err := pf2(ctx)
if err != nil {
return err
}
p3, err := pf3(ctx)
if err != nil {
return err
}
p4, err := pf4(ctx)
if err != nil {
return err
}
p5, err := pf5(ctx)
if err != nil {
return err
}
p6, err := pf6(ctx)
if err != nil {
return err
}
p7, err := pf7(ctx)
if err != nil {
return err
}
p8, err := pf8(ctx)
if err != nil {
return err
}
p9, err := pf9(ctx)
if err != nil {
return err
}
data, err := f(ctx, p1, p2, p3, p4, p5, p6, p7, p8, p9)
if err != nil {
return err
}
return ctx.JSON(data)
}
}
func DataFunc10[T, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10 any](
f func(fiber.Ctx, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) (T, error),
pf1 func(fiber.Ctx) (P1, error),
pf2 func(fiber.Ctx) (P2, error),
pf3 func(fiber.Ctx) (P3, error),
pf4 func(fiber.Ctx) (P4, error),
pf5 func(fiber.Ctx) (P5, error),
pf6 func(fiber.Ctx) (P6, error),
pf7 func(fiber.Ctx) (P7, error),
pf8 func(fiber.Ctx) (P8, error),
pf9 func(fiber.Ctx) (P9, error),
pf10 func(fiber.Ctx) (P10, error),
) fiber.Handler {
return func(ctx fiber.Ctx) error {
p1, err := pf1(ctx)
if err != nil {
return err
}
p2, err := pf2(ctx)
if err != nil {
return err
}
p3, err := pf3(ctx)
if err != nil {
return err
}
p4, err := pf4(ctx)
if err != nil {
return err
}
p5, err := pf5(ctx)
if err != nil {
return err
}
p6, err := pf6(ctx)
if err != nil {
return err
}
p7, err := pf7(ctx)
if err != nil {
return err
}
p8, err := pf8(ctx)
if err != nil {
return err
}
p9, err := pf9(ctx)
if err != nil {
return err
}
p10, err := pf10(ctx)
if err != nil {
return err
}
data, err := f(ctx, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)
if err != nil {
return err
}
return ctx.JSON(data)
}
}

55
go.mod
View File

@@ -1,51 +1,38 @@
module git.ipao.vip/rogeecn/atom
module go.ipao.vip/atom
go 1.22
go 1.23
toolchain go1.23.2
require (
github.com/ThreeDotsLabs/watermill v1.4.1
github.com/gofiber/fiber/v3 v3.0.0-beta.3
github.com/gofiber/fiber/v3 v3.0.0-beta.4
github.com/pkg/errors v0.9.1
github.com/riverqueue/river v0.15.0
github.com/rogeecn/atom v1.0.4
github.com/rogeecn/gen v1.0.15
github.com/spf13/cobra v1.7.0
github.com/spf13/viper v1.16.0
go.uber.org/dig v1.17.0
golang.org/x/crypto v0.31.0
)
require (
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/bytedance/sonic v1.10.0-rc3 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.0 // indirect
github.com/andybalholm/brotli v1.1.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.9.1 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.14.1 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/gofiber/utils/v2 v2.0.0-beta.4 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/gofiber/schema v1.2.0 // indirect
github.com/gofiber/utils/v2 v2.0.0-beta.7 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/lithammer/shortuuid/v3 v3.0.7 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/pelletier/go-toml/v2 v2.0.9 // indirect
github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/riverqueue/river/riverdriver v0.15.0 // indirect
github.com/riverqueue/river/rivershared v0.15.0 // indirect
@@ -60,19 +47,17 @@ require (
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
github.com/tinylib/msgp v1.2.5 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.55.0 // indirect
github.com/valyala/fasthttp v1.58.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.uber.org/goleak v1.3.0 // indirect
golang.org/x/arch v0.4.0 // indirect
golang.org/x/exp v0.0.0-20230728194245-b0cb94b80691 // indirect
golang.org/x/net v0.26.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
golang.org/x/crypto v0.33.0 // indirect
golang.org/x/net v0.35.0 // indirect
golang.org/x/sync v0.11.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/text v0.22.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

119
go.sum
View File

@@ -40,19 +40,9 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/ThreeDotsLabs/watermill v1.4.1 h1:gjP6yZH+otMPjV0KsV07pl9TeMm9UQV/gqiuiuG5Drs=
github.com/ThreeDotsLabs/watermill v1.4.1/go.mod h1:lBnrLbxOjeMRgcJbv+UiZr8Ylz8RkJ4m6i/VN/Nk+to=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
github.com/bytedance/sonic v1.10.0-rc3 h1:uNSnscRapXTwUgTyOF0GVljYD08p9X/Lbr9MweSV3V0=
github.com/bytedance/sonic v1.10.0-rc3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo=
github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@@ -74,29 +64,17 @@ github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0X
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.14.1 h1:9c50NUPC30zyuKprjL3vNZ0m5oG+jU0zvx4AqHGnv4k=
github.com/go-playground/validator/v10 v10.14.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/gofiber/fiber/v3 v3.0.0-beta.3 h1:7Q2I+HsIqnIEEDB+9oe7Gadpakh6ZLhXpTYz/L20vrg=
github.com/gofiber/fiber/v3 v3.0.0-beta.3/go.mod h1:kcMur0Dxqk91R7p4vxEpJfDWZ9u5IfvrtQc8Bvv/JmY=
github.com/gofiber/utils/v2 v2.0.0-beta.4 h1:1gjbVFFwVwUb9arPcqiB6iEjHBwo7cHsyS41NeIW3co=
github.com/gofiber/utils/v2 v2.0.0-beta.4/go.mod h1:sdRsPU1FXX6YiDGGxd+q2aPJRMzpsxdzCXo9dz+xtOY=
github.com/gofiber/fiber/v3 v3.0.0-beta.4 h1:KzDSavvhG7m81NIsmnu5l3ZDbVS4feCidl4xlIfu6V0=
github.com/gofiber/fiber/v3 v3.0.0-beta.4/go.mod h1:/WFUoHRkZEsGHyy2+fYcdqi109IVOFbVwxv1n1RU+kk=
github.com/gofiber/schema v1.2.0 h1:j+ZRrNnUa/0ZuWrn/6kAtAufEr4jCJ+JuTURAMxNSZg=
github.com/gofiber/schema v1.2.0/go.mod h1:YYwj01w3hVfaNjhtJzaqetymL56VW642YS3qZPhuE6c=
github.com/gofiber/utils/v2 v2.0.0-beta.7 h1:NnHFrRHvhrufPABdWajcKZejz9HnCWmT/asoxRsiEbQ=
github.com/gofiber/utils/v2 v2.0.0-beta.7/go.mod h1:J/M03s+HMdZdvhAeyh76xT72IfVqBzuz/OJkrMa7cwU=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -135,7 +113,6 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@@ -179,17 +156,11 @@ github.com/jackc/pgx/v5 v5.7.2 h1:mLoDLV6sonKlvjIEsV56SkWNCnuNv531l94GaIzO+XI=
github.com/jackc/pgx/v5 v5.7.2/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ=
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/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
@@ -198,30 +169,24 @@ 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/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lithammer/shortuuid/v3 v3.0.7 h1:trX0KTHy4Pbwo/6ia8fscyHoGA+mf1jWbPJVuvyJQQ8=
github.com/lithammer/shortuuid/v3 v3.0.7/go.mod h1:vMk8ke37EmiewwolSO1NLW8vP4ZaKlRuDIi8tWWmAts=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
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-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
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/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0=
github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c h1:dAMKvw0MlJT1GshSTtih8C2gDs04w8dReiOGXrGLNoY=
github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
@@ -242,10 +207,6 @@ github.com/riverqueue/river/rivertype v0.15.0 h1:+TXRnvQv1ulV24uQnsuZmbb3yJdmbpi
github.com/riverqueue/river/rivertype v0.15.0/go.mod h1:4vpt5ZSdZ35mFbRAV4oXgeRdH3Mq5h1pUzQTvaGfCUA=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogeecn/atom v1.0.4 h1:GT9XL+jCCu7a4Fmu8/TsZBzSbdvF+zzsSz12E1ZBL5Q=
github.com/rogeecn/atom v1.0.4/go.mod h1:uT3tmB8pALm1NaNRcd6pVy0IR/fO8H5eZrWrFlGmPoU=
github.com/rogeecn/gen v1.0.15 h1:B2c8DegRLBJZv1FnS9sy5nJ2jPVFGDwuJQNKDsxAQ6U=
github.com/rogeecn/gen v1.0.15/go.mod h1:2bsmE6voSNriUNoCRRVye/y6tcnu79gkI/RGt0asmvU=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
@@ -266,14 +227,11 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
@@ -289,16 +247,18 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/tinylib/msgp v1.2.5 h1:WeQg1whrXRFiZusidTQqzETkRpGjFjcIhW6uqWH09po=
github.com/tinylib/msgp v1.2.5/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0=
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/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8k8=
github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM=
github.com/valyala/fasthttp v1.58.0 h1:GGB2dWxSbEprU9j0iMJHgdKYJVDyjrOwF9RE59PbRuE=
github.com/valyala/fasthttp v1.58.0/go.mod h1:SYXvHHaFp7QZHGKSHmoMipInhrI5StHrhDTYVEjK/Kw=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -313,9 +273,6 @@ go.uber.org/dig v1.17.0 h1:5Chju+tUvcC+N7N6EV08BJz41UZuO3BmHcN4A287ZLI=
go.uber.org/dig v1.17.0/go.mod h1:rTxpf7l5I0eBTlE6/9RL+lDybC7WFwY2QH55ZSjy1mU=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc=
golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -323,8 +280,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -335,8 +292,6 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20230728194245-b0cb94b80691 h1:/yRP+0AN7mf5DkD3BAI6TOFnd51gEoDEb8o35jIFtgw=
golang.org/x/exp v0.0.0-20230728194245-b0cb94b80691/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -392,8 +347,8 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -413,8 +368,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -450,12 +405,10 @@ golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/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.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -465,8 +418,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -609,8 +562,6 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
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=
@@ -629,8 +580,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

View File

@@ -7,7 +7,7 @@ import (
"os"
"os/exec"
"git.ipao.vip/rogeecn/atom/container"
"go.ipao.vip/atom/container"
"github.com/spf13/cobra"
)

View File

@@ -1,11 +0,0 @@
package db
import (
"database/sql"
"fmt"
)
func TruncateTable(db *sql.DB, table string) {
_, err := db.Exec(fmt.Sprintf("TRUNCATE TABLE %s RESTART IDENTITY", table))
_ = err
}

101
utils/envx/envx.go Normal file
View File

@@ -0,0 +1,101 @@
package envx
import (
"os"
"strconv"
"strings"
"time"
)
// Get returns the environment variable or the provided default if unset.
func Get(key, def string) string {
if v, ok := os.LookupEnv(key); ok {
return v
}
return def
}
// MustGet returns the environment variable or panics if it is not set.
func MustGet(key string) string {
if v, ok := os.LookupEnv(key); ok {
return v
}
panic("required env var not set: " + key)
}
// Bool parses a boolean-like env var with a default fallback.
// Recognized true values: 1, t, true, y, yes, on (case-insensitive)
// Recognized false values: 0, f, false, n, no, off
func Bool(key string, def bool) bool {
v, ok := os.LookupEnv(key)
if !ok {
return def
}
s := strings.TrimSpace(strings.ToLower(v))
switch s {
case "1", "t", "true", "y", "yes", "on":
return true
case "0", "f", "false", "n", "no", "off":
return false
default:
return def
}
}
// Int parses an int env var with a default fallback.
func Int(key string, def int) int {
v, ok := os.LookupEnv(key)
if !ok {
return def
}
n, err := strconv.Atoi(strings.TrimSpace(v))
if err != nil {
return def
}
return n
}
// Int64 parses an int64 env var with a default fallback.
func Int64(key string, def int64) int64 {
v, ok := os.LookupEnv(key)
if !ok {
return def
}
n, err := strconv.ParseInt(strings.TrimSpace(v), 10, 64)
if err != nil {
return def
}
return n
}
// Float64 parses a float64 env var with a default fallback.
func Float64(key string, def float64) float64 {
v, ok := os.LookupEnv(key)
if !ok {
return def
}
n, err := strconv.ParseFloat(strings.TrimSpace(v), 64)
if err != nil {
return def
}
return n
}
// Duration parses a time.Duration env var with a default fallback.
func Duration(key string, def time.Duration) time.Duration {
v, ok := os.LookupEnv(key)
if !ok {
return def
}
d, err := time.ParseDuration(strings.TrimSpace(v))
if err != nil {
return def
}
return d
}
// Expand expands ${var} or $var in the string according to the values of the current environment.
func Expand(s string) string {
return os.ExpandEnv(s)
}

View File

@@ -1,13 +0,0 @@
package err
import (
"net/http"
"github.com/rogeecn/gen"
)
var (
BindBodyFailed = gen.NewBusError(http.StatusBadRequest, http.StatusBadRequest, "Body参数错误")
BindQueryFailed = gen.NewBusError(http.StatusBadRequest, http.StatusBadRequest, "Query参数错误")
BindPathFailed = gen.NewBusError(http.StatusBadRequest, http.StatusBadRequest, "Path参数错误: %s")
)

209
utils/filex/filex.go Normal file
View File

@@ -0,0 +1,209 @@
package filex
import (
"errors"
"io/fs"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"time"
)
// Exists reports whether the given path exists (file or directory).
func Exists(path string) bool {
if path == "" {
return false
}
_, err := os.Stat(path)
return err == nil
}
// IsFile reports whether the path exists and is a regular file.
func IsFile(path string) bool {
info, err := os.Stat(path)
if err != nil {
return false
}
return info.Mode().IsRegular()
}
// IsDir reports whether the path exists and is a directory.
func IsDir(path string) bool {
info, err := os.Stat(path)
if err != nil {
return false
}
return info.IsDir()
}
// IsReadable reports whether the target can be opened for reading.
func IsReadable(path string) bool {
f, err := os.Open(path)
if err != nil {
return false
}
_ = f.Close()
return true
}
// IsWritable reports whether a file can be written to. If the file does not exist,
// it checks writability of the parent directory by attempting to create a temp file.
func IsWritable(path string) bool {
if path == "" {
return false
}
info, err := os.Stat(path)
if err == nil {
if info.IsDir() {
// Try writing a temp file in the directory
f, err := os.CreateTemp(path, ".wtmp-*")
if err != nil {
return false
}
name := f.Name()
_ = f.Close()
_ = os.Remove(name)
return true
}
// Try opening for write
f, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND, 0)
if err != nil {
return false
}
_ = f.Close()
return true
}
if !errors.Is(err, os.ErrNotExist) {
return false
}
// Not exist: check parent dir is writable by creating a temp file
dir := filepath.Dir(path)
if dir == "." || dir == "" {
dir = "."
}
f, err := os.CreateTemp(dir, ".wtmp-*")
if err != nil {
return false
}
name := f.Name()
_ = f.Close()
_ = os.Remove(name)
return true
}
// IsExecutable reports whether a file is considered executable on the current OS.
// On Unix, checks the executable bits; on Windows, checks the extension against PATHEXT.
func IsExecutable(path string) bool {
info, err := os.Stat(path)
if err != nil || info.IsDir() {
return false
}
if runtime.GOOS == "windows" {
ext := strings.ToLower(filepath.Ext(path))
if ext == ".exe" || ext == ".bat" || ext == ".cmd" || ext == ".com" || ext == ".ps1" {
return true
}
pathext := strings.ToLower(os.Getenv("PATHEXT"))
for _, e := range strings.Split(pathext, ";") {
if e != "" && ext == strings.ToLower(e) {
return true
}
}
return false
}
// Unix permissions: any execute bit set
return info.Mode()&0o111 != 0
}
// Size returns the size of the file at path.
func Size(path string) (int64, error) {
info, err := os.Stat(path)
if err != nil {
return 0, err
}
return info.Size(), nil
}
// Touch creates the file if it does not exist, or updates its modification time if it does.
func Touch(path string) error {
now := time.Now()
if Exists(path) {
return os.Chtimes(path, now, now)
}
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil {
return err
}
return f.Close()
}
// EnsureDir ensures that a directory exists with the specified permission bits.
func EnsureDir(path string, perm fs.FileMode) error {
if path == "" {
return nil
}
if Exists(path) {
if !IsDir(path) {
return errors.New("path exists and is not a directory")
}
return nil
}
return os.MkdirAll(path, perm)
}
// FindInPath searches for an executable named name in the system PATH.
func FindInPath(name string) (string, bool) {
p, err := exec.LookPath(name)
if err != nil {
return "", false
}
return p, true
}
// ReadFileString reads a whole file into a string.
func ReadFileString(path string) (string, error) {
b, err := os.ReadFile(path)
if err != nil {
return "", err
}
return string(b), nil
}
// WriteFileString writes a string to a file with the given permissions, creating or truncating it.
func WriteFileString(path, s string, perm fs.FileMode) error {
return os.WriteFile(path, []byte(s), perm)
}
// WriteFileAtomic writes data to a temporary file in the same directory and renames it into place.
func WriteFileAtomic(path string, data []byte, perm fs.FileMode) error {
dir := filepath.Dir(path)
if err := EnsureDir(dir, 0o755); err != nil {
return err
}
f, err := os.CreateTemp(dir, ".atomic-*")
if err != nil {
return err
}
tmp := f.Name()
// Best-effort cleanup on error
defer func() { _ = os.Remove(tmp) }()
if _, err := f.Write(data); err != nil {
_ = f.Close()
return err
}
if err := f.Chmod(perm); err != nil {
_ = f.Close()
return err
}
if err := f.Sync(); err != nil {
_ = f.Close()
return err
}
if err := f.Close(); err != nil {
return err
}
return os.Rename(tmp, path)
}

View File

@@ -1,37 +0,0 @@
package fs
import (
"errors"
"os"
)
func PathExists(path string) (bool, error) {
fi, err := os.Stat(path)
if err == nil {
if fi.IsDir() {
return true, nil
}
return false, errors.New("存在同名文件")
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
func CreateDir(dirs ...string) (err error) {
var exist bool
for _, v := range dirs {
exist, err = PathExists(v)
if err != nil {
return err
}
if !exist {
err = os.MkdirAll(v, os.ModePerm)
if err != nil {
return err
}
}
}
return err
}

View File

@@ -1,73 +0,0 @@
package fs
import (
"os"
"path/filepath"
"reflect"
"strings"
)
func Move(src, dst string) (err error) {
if dst == "" {
return nil
}
src, err = filepath.Abs(src)
if err != nil {
return err
}
dst, err = filepath.Abs(dst)
if err != nil {
return err
}
revoke := false
dir := filepath.Dir(dst)
Redirect:
_, err = os.Stat(dir)
if err != nil {
err = os.MkdirAll(dir, 0o755)
if err != nil {
return err
}
if !revoke {
revoke = true
goto Redirect
}
}
return os.Rename(src, dst)
}
func Delete(filePath string) error {
return os.RemoveAll(filePath)
}
func TrimSpace(target interface{}) {
t := reflect.TypeOf(target)
if t.Kind() != reflect.Ptr {
return
}
t = t.Elem()
v := reflect.ValueOf(target).Elem()
for i := 0; i < t.NumField(); i++ {
if v.Field(i).Kind() == reflect.String {
v.Field(i).SetString(strings.TrimSpace(v.Field(i).String()))
}
}
}
// FileExist 判断文件是否存在
func FileExist(path string) bool {
fi, err := os.Lstat(path)
if err == nil {
return !fi.IsDir()
}
return !os.IsNotExist(err)
}
func FilePathInfo(file string) (path, name, ext string) {
filename := filepath.Base(file)
path = filepath.Dir(file)
ext = filepath.Ext(filename)
name = strings.TrimSuffix(filename, ext)
return
}

View File

@@ -1,49 +0,0 @@
package fs
import "testing"
func TestFilePathInfo(t *testing.T) {
type args struct {
file string
}
tests := []struct {
name string
args args
wantPath string
wantName string
wantExt string
}{
{
"1.",
args{
file: "/a/bc.ext",
},
"/a",
"bc",
".ext",
},
{
"1.",
args{
file: "/a/c/c/c/bc.ext",
},
"/a/c/c/c",
"bc",
".ext",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotPath, gotName, gotExt := FilePathInfo(tt.args.file)
if gotPath != tt.wantPath {
t.Errorf("FilePathInfo() gotPath = %v, want %v", gotPath, tt.wantPath)
}
if gotName != tt.wantName {
t.Errorf("FilePathInfo() gotName = %v, want %v", gotName, tt.wantName)
}
if gotExt != tt.wantExt {
t.Errorf("FilePathInfo() gotExt = %v, want %v", gotExt, tt.wantExt)
}
})
}
}

View File

@@ -1,17 +0,0 @@
package hash
import (
"golang.org/x/crypto/bcrypt"
)
// BcryptHash 使用 bcrypt 对密码进行加密
func BcryptHash(password string) string {
bytes, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
return string(bytes)
}
// BcryptCheck 对比明文密码和数据库的哈希值
func BcryptCheck(password, hash string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
return err == nil
}

View File

@@ -1,12 +0,0 @@
package hash
import (
"crypto/md5"
"encoding/hex"
)
func MD5(str []byte, b ...byte) string {
h := md5.New()
h.Write(str)
return hex.EncodeToString(h.Sum(b))
}

View File

@@ -1,7 +0,0 @@
package utils
var (
Version = "1.0.0"
BuildAt = "2014-02-02 00:00:00"
GitHash = ""
)

28
utils/jsonx/json.go Normal file
View File

@@ -0,0 +1,28 @@
package jsonx
import "encoding/json"
func Marshal(v any) ([]byte, error) {
return json.Marshal(v)
}
func Unmarshal[T any](data []byte) (*T, error) {
var v T
err := json.Unmarshal(data, &v)
if err != nil {
return nil, err
}
return &v, nil
}
func UnmarshalTo(data []byte, a any) error {
return json.Unmarshal(data, a)
}
func MustUnmarshal[T any](data []byte) *T {
v, err := Unmarshal[T](data)
if err != nil {
panic(err)
}
return v
}

16
utils/ptr/ptr.go Normal file
View File

@@ -0,0 +1,16 @@
package ptr
// Of returns a pointer to v.
func Of[T any](v T) *T { return &v }
// Deref returns the value pointed to by p, or def if p is nil.
func Deref[T any](p *T, def T) T {
if p == nil {
return def
}
return *p
}
// Zero returns the zero value for type T.
func Zero[T any]() (z T) { return }

77
utils/randx/randx.go Normal file
View File

@@ -0,0 +1,77 @@
package randx
import (
crand "crypto/rand"
"encoding/hex"
"io"
)
// Bytes returns n cryptographically secure random bytes.
func Bytes(n int) ([]byte, error) {
if n <= 0 {
return []byte{}, nil
}
b := make([]byte, n)
_, err := io.ReadFull(crand.Reader, b)
return b, err
}
var urlSafe = []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_")
// String returns a URL-safe random string of length n using a cryptographically secure source.
func String(n int) (string, error) {
if n <= 0 {
return "", nil
}
out := make([]byte, n)
// rejection sampling to avoid modulo bias
// we want uniform selection from urlSafe (len m)
m := len(urlSafe)
threshold := 256 - (256 % m)
var buf [1]byte
for i := 0; i < n; i++ {
for {
if _, err := io.ReadFull(crand.Reader, buf[:]); err != nil {
return "", err
}
b := int(buf[0])
if b < threshold {
out[i] = urlSafe[b%m]
break
}
}
}
return string(out), nil
}
// MustString is like String but panics on error.
func MustString(n int) string {
s, err := String(n)
if err != nil {
panic(err)
}
return s
}
// UUIDv4 generates a RFC 4122 version 4 UUID string.
func UUIDv4() (string, error) {
b := make([]byte, 16)
if _, err := io.ReadFull(crand.Reader, b); err != nil {
return "", err
}
// Set version (4) and variant (10)
b[6] = (b[6] & 0x0f) | 0x40
b[8] = (b[8] & 0x3f) | 0x80
// Format 8-4-4-4-12
dst := make([]byte, 36)
hex.Encode(dst[0:8], b[0:4])
dst[8] = '-'
hex.Encode(dst[9:13], b[4:6])
dst[13] = '-'
hex.Encode(dst[14:18], b[6:8])
dst[18] = '-'
hex.Encode(dst[19:23], b[8:10])
dst[23] = '-'
hex.Encode(dst[24:36], b[10:16])
return string(dst), nil
}

60
utils/strx/strx.go Normal file
View File

@@ -0,0 +1,60 @@
package strx
import (
"strings"
)
// Coalesce returns the first non-empty string from vals, or "" if all are empty.
func Coalesce(vals ...string) string {
for _, v := range vals {
if v != "" {
return v
}
}
return ""
}
// ContainsFold reports whether substr is within s, case-insensitively.
func ContainsFold(s, substr string) bool {
if substr == "" {
return true
}
return strings.Contains(strings.ToLower(s), strings.ToLower(substr))
}
// SplitAndTrim splits s by sep, trims spaces for each part, and filters empty items.
func SplitAndTrim(s, sep string) []string {
if s == "" {
return nil
}
parts := strings.Split(s, sep)
out := make([]string, 0, len(parts))
for _, p := range parts {
p = strings.TrimSpace(p)
if p != "" {
out = append(out, p)
}
}
return out
}
// JoinNonEmpty joins parts using sep, skipping empty strings.
func JoinNonEmpty(sep string, parts ...string) string {
out := make([]string, 0, len(parts))
for _, p := range parts {
if p != "" {
out = append(out, p)
}
}
return strings.Join(out, sep)
}
// TrimAll collapses any whitespace runs to single spaces and trims both ends.
func TrimAll(s string) string {
if s == "" {
return ""
}
fields := strings.Fields(s)
return strings.Join(fields, " ")
}

View File

@@ -1,8 +0,0 @@
package tap
func T[T any](v T, ds ...func(T)) T {
for _, d := range ds {
d(v)
}
return v
}

View File

@@ -1,15 +0,0 @@
package utils
import (
"os"
"strings"
)
func IsInTesting() bool {
for _, arg := range os.Args {
if strings.HasPrefix(arg, "-test.v=") {
return true
}
}
return false
}

View File

@@ -1,131 +0,0 @@
package utils
import (
"archive/zip"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"strings"
)
// Unzip 解压
func Unzip(zipFile, destDir string) ([]string, error) {
zipReader, err := zip.OpenReader(zipFile)
paths := []string{}
if err != nil {
return []string{}, err
}
defer zipReader.Close()
for _, f := range zipReader.File {
if strings.Contains(f.Name, "..") {
return []string{}, fmt.Errorf("%s 文件名不合法", f.Name)
}
// nolint
fpath := filepath.Join(destDir, f.Name)
paths = append(paths, fpath)
if f.FileInfo().IsDir() {
err = os.MkdirAll(fpath, os.ModePerm)
if err != nil {
return nil, err
}
} else {
err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm)
if err != nil {
return []string{}, err
}
zipFunc := func(fpath string) error {
var inFile io.ReadCloser
var outFile *os.File
inFile, err = f.Open()
if err != nil {
return err
}
defer inFile.Close()
outFile, err = os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
return err
}
defer outFile.Close()
// nolint
_, err = io.Copy(outFile, inFile)
if err != nil {
return err
}
return nil
}
err = zipFunc(fpath)
if err != nil {
return []string{}, err
}
}
}
return paths, nil
}
func ZipFiles(filename string, files []string, oldForm, newForm string) error {
newZipFile, err := os.Create(filename)
if err != nil {
return err
}
defer func() {
_ = newZipFile.Close()
}()
zipWriter := zip.NewWriter(newZipFile)
defer func() {
_ = zipWriter.Close()
}()
// 把files添加到zip中
for _, file := range files {
err = func(file string) error {
var zipFile *os.File
zipFile, err = os.Open(file)
if err != nil {
return err
}
defer zipFile.Close()
// 获取file的基础信息
var info fs.FileInfo
info, err = zipFile.Stat()
if err != nil {
return err
}
var header *zip.FileHeader
header, err = zip.FileInfoHeader(info)
if err != nil {
return err
}
// 使用上面的FileInfoHeader() 就可以把文件保存的路径替换成我们自己想要的了,如下面
header.Name = strings.Replace(file, oldForm, newForm, -1)
// 优化压缩
// 更多参考see http://golang.org/pkg/archive/zip/#pkg-constants
header.Method = zip.Deflate
var writer io.Writer
writer, err = zipWriter.CreateHeader(header)
if err != nil {
return err
}
if _, err = io.Copy(writer, zipFile); err != nil {
return err
}
return nil
}(file)
if err != nil {
return err
}
}
return nil
}