OwnCloud Infinite Scale with Go 1.25.x

Quick and dirty manual how to build ocis with go 1.25.4

OwnCloud Infinite Scale with Go 1.25.x
git clone https://github.com/owncloud/ocis.git ocis

push ocis

go get -u github.com/gookit/goutil/sysutil
go mod tidy
go mod vendor

gmake generate
gmake -C ocis clean
gmake -C ocis build 
strip ocis/bin/ocis 

Now you have shiny new build of OCIS inside file ocis/bin/ocis .

For me it looks like following patch file I have, and the result is working site https://owncloud.ostreff.info :


diff --git a/go.mod b/go.mod
index 7ccb9a06a99..3d83a1d83f5 100644
--- a/go.mod
+++ b/go.mod
@@ -221,7 +221,7 @@ require (
 	github.com/google/go-tpm v0.9.6 // indirect
 	github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
 	github.com/google/renameio/v2 v2.0.0 // indirect
-	github.com/gookit/goutil v0.7.1 // indirect
+	github.com/gookit/goutil v0.7.2 // indirect
 	github.com/gorilla/handlers v1.5.1 // indirect
 	github.com/gorilla/schema v1.4.1 // indirect
 	github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
diff --git a/go.sum b/go.sum
index 18d7a3f4831..dbe99ef2f36 100644
--- a/go.sum
+++ b/go.sum
@@ -486,8 +486,8 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
 github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
 github.com/gookit/config/v2 v2.2.7 h1:P58/uENzkDp7r7Hp8YSZxOhZ/F5a5Y/AzyhDUkQYa9A=
 github.com/gookit/config/v2 v2.2.7/go.mod h1:QST99HmkZXXD/HkZmOm1OXpgdAnc6Rl9syGl+u62Pi8=
-github.com/gookit/goutil v0.7.1 h1:AaFJPN9mrdeYBv8HOybri26EHGCC34WJVT7jUStGJsI=
-github.com/gookit/goutil v0.7.1/go.mod h1:vJS9HXctYTCLtCsZot5L5xF+O1oR17cDYO9R0HxBmnU=
+github.com/gookit/goutil v0.7.2 h1:NSiqWWY+BT0MwIlKDeSVPfQmr9xTkkAqwDjhplobdgo=
+github.com/gookit/goutil v0.7.2/go.mod h1:vJS9HXctYTCLtCsZot5L5xF+O1oR17cDYO9R0HxBmnU=
 github.com/gookit/ini/v2 v2.3.2 h1:W6tzOGE6zOLQelH2xhcH8BIBZPtnEpJgQ+J6SsAKBSw=
 github.com/gookit/ini/v2 v2.3.2/go.mod h1:StKSqY5niArRwYBS8Z71+iWUt5ow47qt359sS9YQLYY=
 github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
diff --git a/protogen/gen/ocis/messages/settings/v0/settings.pb.go b/protogen/gen/ocis/messages/settings/v0/settings.pb.go
index cf104c870ba..563436da5a5 100644
--- a/protogen/gen/ocis/messages/settings/v0/settings.pb.go
+++ b/protogen/gen/ocis/messages/settings/v0/settings.pb.go
@@ -627,13 +627,13 @@ type Bundle struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Id          string      `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" yaml:"id"`                                                   // @gotags: yaml:"id"
-	Name        string      `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty" yaml:"name"`                                             // @gotags: yaml:"name"
-	Type        Bundle_Type `protobuf:"varint,3,opt,name=type,proto3,enum=ocis.messages.settings.v0.Bundle_Type" json:"type,omitempty" yaml:"type"` // @gotags: yaml:"type"
-	Extension   string      `protobuf:"bytes,4,opt,name=extension,proto3" json:"extension,omitempty" yaml:"extension"`                              // @gotags: yaml:"extension"
-	DisplayName string      `protobuf:"bytes,5,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty" yaml:"display_name"`    // @gotags: yaml:"display_name"
-	Settings    []*Setting  `protobuf:"bytes,6,rep,name=settings,proto3" json:"settings,omitempty" yaml:"settings"`                                 // @gotags: yaml:"settings"
-	Resource    *Resource   `protobuf:"bytes,7,opt,name=resource,proto3" json:"resource,omitempty" yaml:"resource"`                                 // @gotags: yaml:"resource"
+	Id          string      `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`                                                 // @gotags: yaml:"id"
+	Name        string      `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`                                             // @gotags: yaml:"name"
+	Type        Bundle_Type `protobuf:"varint,3,opt,name=type,proto3,enum=ocis.messages.settings.v0.Bundle_Type" json:"type,omitempty"` // @gotags: yaml:"type"
+	Extension   string      `protobuf:"bytes,4,opt,name=extension,proto3" json:"extension,omitempty"`                                   // @gotags: yaml:"extension"
+	DisplayName string      `protobuf:"bytes,5,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"`            // @gotags: yaml:"display_name"
+	Settings    []*Setting  `protobuf:"bytes,6,rep,name=settings,proto3" json:"settings,omitempty"`                                     // @gotags: yaml:"settings"
+	Resource    *Resource   `protobuf:"bytes,7,opt,name=resource,proto3" json:"resource,omitempty"`                                     // @gotags: yaml:"resource"
 }
 
 func (x *Bundle) Reset() {
@@ -722,10 +722,10 @@ type Setting struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Id          string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" yaml:"id"`                                      // @gotags: yaml:"id"
-	Name        string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty" yaml:"name"`                                  // @gotags: yaml:"name"
-	DisplayName string `protobuf:"bytes,3,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty" yaml:"display_name"` // @gotags: yaml:"display_name"
-	Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty" yaml:"description"`                    // @gotags: yaml:"description"
+	Id          string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`                                      // @gotags: yaml:"id"
+	Name        string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`                                  // @gotags: yaml:"name"
+	DisplayName string `protobuf:"bytes,3,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` // @gotags: yaml:"display_name"
+	Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"`                    // @gotags: yaml:"description"
 	// Types that are assignable to Value:
 	//
 	//	*Setting_IntValue
@@ -736,7 +736,7 @@ type Setting struct {
 	//	*Setting_PermissionValue
 	//	*Setting_MultiChoiceCollectionValue
 	Value    isSetting_Value `protobuf_oneof:"value"`
-	Resource *Resource       `protobuf:"bytes,11,opt,name=resource,proto3" json:"resource,omitempty" yaml:"resource"` // @gotags: yaml:"resource"
+	Resource *Resource       `protobuf:"bytes,11,opt,name=resource,proto3" json:"resource,omitempty"` // @gotags: yaml:"resource"
 }
 
 func (x *Setting) Reset() {
@@ -867,31 +867,31 @@ type isSetting_Value interface {
 }
 
 type Setting_IntValue struct {
-	IntValue *Int `protobuf:"bytes,5,opt,name=int_value,json=intValue,proto3,oneof" yaml:"int_value"` // @gotags: yaml:"int_value"
+	IntValue *Int `protobuf:"bytes,5,opt,name=int_value,json=intValue,proto3,oneof"` // @gotags: yaml:"int_value"
 }
 
 type Setting_StringValue struct {
-	StringValue *String `protobuf:"bytes,6,opt,name=string_value,json=stringValue,proto3,oneof" yaml:"string_value"` // @gotags: yaml:"string_value"
+	StringValue *String `protobuf:"bytes,6,opt,name=string_value,json=stringValue,proto3,oneof"` // @gotags: yaml:"string_value"
 }
 
 type Setting_BoolValue struct {
-	BoolValue *Bool `protobuf:"bytes,7,opt,name=bool_value,json=boolValue,proto3,oneof" yaml:"bool_value"` // @gotags: yaml:"bool_value"
+	BoolValue *Bool `protobuf:"bytes,7,opt,name=bool_value,json=boolValue,proto3,oneof"` // @gotags: yaml:"bool_value"
 }
 
 type Setting_SingleChoiceValue struct {
-	SingleChoiceValue *SingleChoiceList `protobuf:"bytes,8,opt,name=single_choice_value,json=singleChoiceValue,proto3,oneof" yaml:"single_choice_value"` // @gotags: yaml:"single_choice_value"
+	SingleChoiceValue *SingleChoiceList `protobuf:"bytes,8,opt,name=single_choice_value,json=singleChoiceValue,proto3,oneof"` // @gotags: yaml:"single_choice_value"
 }
 
 type Setting_MultiChoiceValue struct {
-	MultiChoiceValue *MultiChoiceList `protobuf:"bytes,9,opt,name=multi_choice_value,json=multiChoiceValue,proto3,oneof" yaml:"multi_choice_value"` // @gotags: yaml:"multi_choice_value"
+	MultiChoiceValue *MultiChoiceList `protobuf:"bytes,9,opt,name=multi_choice_value,json=multiChoiceValue,proto3,oneof"` // @gotags: yaml:"multi_choice_value"
 }
 
 type Setting_PermissionValue struct {
-	PermissionValue *Permission `protobuf:"bytes,10,opt,name=permission_value,json=permissionValue,proto3,oneof" yaml:"permission_value"` // @gotags: yaml:"permission_value"
+	PermissionValue *Permission `protobuf:"bytes,10,opt,name=permission_value,json=permissionValue,proto3,oneof"` // @gotags: yaml:"permission_value"
 }
 
 type Setting_MultiChoiceCollectionValue struct {
-	MultiChoiceCollectionValue *MultiChoiceCollection `protobuf:"bytes,12,opt,name=multi_choice_collection_value,json=multiChoiceCollectionValue,proto3,oneof" yaml:"multi_choice_collection_value"` // @gotags: yaml:"multi_choice_collection_value"
+	MultiChoiceCollectionValue *MultiChoiceCollection `protobuf:"bytes,12,opt,name=multi_choice_collection_value,json=multiChoiceCollectionValue,proto3,oneof"` // @gotags: yaml:"multi_choice_collection_value"
 }
 
 func (*Setting_IntValue) isSetting_Value() {}
@@ -913,11 +913,11 @@ type Int struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Default     int64  `protobuf:"varint,1,opt,name=default,proto3" json:"default,omitempty" yaml:"default"`        // @gotags: yaml:"default"
-	Min         int64  `protobuf:"varint,2,opt,name=min,proto3" json:"min,omitempty" yaml:"min"`                // @gotags: yaml:"min"
-	Max         int64  `protobuf:"varint,3,opt,name=max,proto3" json:"max,omitempty" yaml:"max"`                // @gotags: yaml:"max"
-	Step        int64  `protobuf:"varint,4,opt,name=step,proto3" json:"step,omitempty" yaml:"step"`              // @gotags: yaml:"step"
-	Placeholder string `protobuf:"bytes,5,opt,name=placeholder,proto3" json:"placeholder,omitempty" yaml:"placeholder"` // @gotags: yaml:"placeholder"
+	Default     int64  `protobuf:"varint,1,opt,name=default,proto3" json:"default,omitempty"`        // @gotags: yaml:"default"
+	Min         int64  `protobuf:"varint,2,opt,name=min,proto3" json:"min,omitempty"`                // @gotags: yaml:"min"
+	Max         int64  `protobuf:"varint,3,opt,name=max,proto3" json:"max,omitempty"`                // @gotags: yaml:"max"
+	Step        int64  `protobuf:"varint,4,opt,name=step,proto3" json:"step,omitempty"`              // @gotags: yaml:"step"
+	Placeholder string `protobuf:"bytes,5,opt,name=placeholder,proto3" json:"placeholder,omitempty"` // @gotags: yaml:"placeholder"
 }
 
 func (x *Int) Reset() {
@@ -992,11 +992,11 @@ type String struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Default     string `protobuf:"bytes,1,opt,name=default,proto3" json:"default,omitempty" yaml:"default"`                       // @gotags: yaml:"default"
-	Required    bool   `protobuf:"varint,2,opt,name=required,proto3" json:"required,omitempty" yaml:"required"`                    // @gotags: yaml:"required"
-	MinLength   int32  `protobuf:"varint,3,opt,name=min_length,json=minLength,proto3" json:"min_length,omitempty" yaml:"min_length"` // @gotags: yaml:"min_length"
-	MaxLength   int32  `protobuf:"varint,4,opt,name=max_length,json=maxLength,proto3" json:"max_length,omitempty" yaml:"max_length"` // @gotags: yaml:"max_length"
-	Placeholder string `protobuf:"bytes,5,opt,name=placeholder,proto3" json:"placeholder,omitempty" yaml:"placeholder"`               // @gotags: yaml:"placeholder"
+	Default     string `protobuf:"bytes,1,opt,name=default,proto3" json:"default,omitempty"`                       // @gotags: yaml:"default"
+	Required    bool   `protobuf:"varint,2,opt,name=required,proto3" json:"required,omitempty"`                    // @gotags: yaml:"required"
+	MinLength   int32  `protobuf:"varint,3,opt,name=min_length,json=minLength,proto3" json:"min_length,omitempty"` // @gotags: yaml:"min_length"
+	MaxLength   int32  `protobuf:"varint,4,opt,name=max_length,json=maxLength,proto3" json:"max_length,omitempty"` // @gotags: yaml:"max_length"
+	Placeholder string `protobuf:"bytes,5,opt,name=placeholder,proto3" json:"placeholder,omitempty"`               // @gotags: yaml:"placeholder"
 }
 
 func (x *String) Reset() {
@@ -1071,8 +1071,8 @@ type Bool struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Default bool   `protobuf:"varint,1,opt,name=default,proto3" json:"default,omitempty" yaml:"default"` // @gotags: yaml:"default"
-	Label   string `protobuf:"bytes,2,opt,name=label,proto3" json:"label,omitempty" yaml:"label"`      // @gotags: yaml:"label"
+	Default bool   `protobuf:"varint,1,opt,name=default,proto3" json:"default,omitempty"` // @gotags: yaml:"default"
+	Label   string `protobuf:"bytes,2,opt,name=label,proto3" json:"label,omitempty"`      // @gotags: yaml:"label"
 }
 
 func (x *Bool) Reset() {
@@ -1126,7 +1126,7 @@ type SingleChoiceList struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Options []*ListOption `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty" yaml:"options"` // @gotags: yaml:"options"
+	Options []*ListOption `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty"` // @gotags: yaml:"options"
 }
 
 func (x *SingleChoiceList) Reset() {
@@ -1173,7 +1173,7 @@ type MultiChoiceList struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Options []*ListOption `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty" yaml:"options"` // @gotags: yaml:"options"
+	Options []*ListOption `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty"` // @gotags: yaml:"options"
 }
 
 func (x *MultiChoiceList) Reset() {
@@ -1220,9 +1220,9 @@ type ListOption struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Value        *ListOptionValue `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty" yaml:"value"`                                   // @gotags: yaml:"value"
-	Default      bool             `protobuf:"varint,2,opt,name=default,proto3" json:"default,omitempty" yaml:"default"`                              // @gotags: yaml:"default"
-	DisplayValue string           `protobuf:"bytes,3,opt,name=display_value,json=displayValue,proto3" json:"display_value,omitempty" yaml:"display_value"` // @gotags: yaml:"display_value"
+	Value        *ListOptionValue `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`                                   // @gotags: yaml:"value"
+	Default      bool             `protobuf:"varint,2,opt,name=default,proto3" json:"default,omitempty"`                              // @gotags: yaml:"default"
+	DisplayValue string           `protobuf:"bytes,3,opt,name=display_value,json=displayValue,proto3" json:"display_value,omitempty"` // @gotags: yaml:"display_value"
 }
 
 func (x *ListOption) Reset() {
@@ -1283,7 +1283,7 @@ type MultiChoiceCollection struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Options []*MultiChoiceCollectionOption `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty" yaml:"options"` // @gotags: yaml:"options"
+	Options []*MultiChoiceCollectionOption `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty"` // @gotags: yaml:"options"
 }
 
 func (x *MultiChoiceCollection) Reset() {
@@ -1330,10 +1330,10 @@ type MultiChoiceCollectionOption struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Value        *MultiChoiceCollectionOptionValue `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty" yaml:"value"`                                   // @gotags: yaml:"value"
-	Key          string                            `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty" yaml:"key"`                                       // @gotags: yaml:"key"
-	Attribute    string                            `protobuf:"bytes,3,opt,name=attribute,proto3" json:"attribute,omitempty" yaml:"attribute"`                           // @gotags: yaml:"attribute"
-	DisplayValue string                            `protobuf:"bytes,4,opt,name=display_value,json=displayValue,proto3" json:"display_value,omitempty" yaml:"display_value"` // @gotags: yaml:"display_value"
+	Value        *MultiChoiceCollectionOptionValue `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`                                   // @gotags: yaml:"value"
+	Key          string                            `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`                                       // @gotags: yaml:"key"
+	Attribute    string                            `protobuf:"bytes,3,opt,name=attribute,proto3" json:"attribute,omitempty"`                           // @gotags: yaml:"attribute"
+	DisplayValue string                            `protobuf:"bytes,4,opt,name=display_value,json=displayValue,proto3" json:"display_value,omitempty"` // @gotags: yaml:"display_value"
 }
 
 func (x *MultiChoiceCollectionOption) Reset() {
@@ -1474,15 +1474,15 @@ type isMultiChoiceCollectionOptionValue_Option interface {
 }
 
 type MultiChoiceCollectionOptionValue_IntValue struct {
-	IntValue *Int `protobuf:"bytes,1,opt,name=int_value,json=intValue,proto3,oneof" yaml:"int_value"` // @gotags: yaml:"int_value"
+	IntValue *Int `protobuf:"bytes,1,opt,name=int_value,json=intValue,proto3,oneof"` // @gotags: yaml:"int_value"
 }
 
 type MultiChoiceCollectionOptionValue_StringValue struct {
-	StringValue *String `protobuf:"bytes,2,opt,name=string_value,json=stringValue,proto3,oneof" yaml:"string_value"` // @gotags: yaml:"string_value"
+	StringValue *String `protobuf:"bytes,2,opt,name=string_value,json=stringValue,proto3,oneof"` // @gotags: yaml:"string_value"
 }
 
 type MultiChoiceCollectionOptionValue_BoolValue struct {
-	BoolValue *Bool `protobuf:"bytes,3,opt,name=bool_value,json=boolValue,proto3,oneof" yaml:"bool_value"` // @gotags: yaml:"bool_value"
+	BoolValue *Bool `protobuf:"bytes,3,opt,name=bool_value,json=boolValue,proto3,oneof"` // @gotags: yaml:"bool_value"
 }
 
 func (*MultiChoiceCollectionOptionValue_IntValue) isMultiChoiceCollectionOptionValue_Option() {}
@@ -1496,8 +1496,8 @@ type Permission struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Operation  Permission_Operation  `protobuf:"varint,1,opt,name=operation,proto3,enum=ocis.messages.settings.v0.Permission_Operation" json:"operation,omitempty" yaml:"operation"`    // @gotags: yaml:"operation"
-	Constraint Permission_Constraint `protobuf:"varint,2,opt,name=constraint,proto3,enum=ocis.messages.settings.v0.Permission_Constraint" json:"constraint,omitempty" yaml:"constraint"` // @gotags: yaml:"constraint"
+	Operation  Permission_Operation  `protobuf:"varint,1,opt,name=operation,proto3,enum=ocis.messages.settings.v0.Permission_Operation" json:"operation,omitempty"`    // @gotags: yaml:"operation"
+	Constraint Permission_Constraint `protobuf:"varint,2,opt,name=constraint,proto3,enum=ocis.messages.settings.v0.Permission_Constraint" json:"constraint,omitempty"` // @gotags: yaml:"constraint"
 }
 
 func (x *Permission) Reset() {
@@ -1552,12 +1552,12 @@ type Value struct {
 	unknownFields protoimpl.UnknownFields
 
 	// id is the id of the Value. It is generated on saving it.
-	Id       string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" yaml:"id"`                             // @gotags: yaml:"id"
-	BundleId string `protobuf:"bytes,2,opt,name=bundle_id,json=bundleId,proto3" json:"bundle_id,omitempty" yaml:"bundle_id"` // @gotags: yaml:"bundle_id"
+	Id       string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`                             // @gotags: yaml:"id"
+	BundleId string `protobuf:"bytes,2,opt,name=bundle_id,json=bundleId,proto3" json:"bundle_id,omitempty"` // @gotags: yaml:"bundle_id"
 	// setting_id is the id of the setting from within its bundle.
-	SettingId   string    `protobuf:"bytes,3,opt,name=setting_id,json=settingId,proto3" json:"setting_id,omitempty" yaml:"setting_id"`       // @gotags: yaml:"setting_id"
-	AccountUuid string    `protobuf:"bytes,4,opt,name=account_uuid,json=accountUuid,proto3" json:"account_uuid,omitempty" yaml:"account_uuid"` // @gotags: yaml:"account_uuid"
-	Resource    *Resource `protobuf:"bytes,5,opt,name=resource,proto3" json:"resource,omitempty" yaml:"resource"`                          // @gotags: yaml:"resource"
+	SettingId   string    `protobuf:"bytes,3,opt,name=setting_id,json=settingId,proto3" json:"setting_id,omitempty"`       // @gotags: yaml:"setting_id"
+	AccountUuid string    `protobuf:"bytes,4,opt,name=account_uuid,json=accountUuid,proto3" json:"account_uuid,omitempty"` // @gotags: yaml:"account_uuid"
+	Resource    *Resource `protobuf:"bytes,5,opt,name=resource,proto3" json:"resource,omitempty"`                          // @gotags: yaml:"resource"
 	// Types that are assignable to Value:
 	//
 	//	*Value_BoolValue
@@ -1682,23 +1682,23 @@ type isValue_Value interface {
 }
 
 type Value_BoolValue struct {
-	BoolValue bool `protobuf:"varint,6,opt,name=bool_value,json=boolValue,proto3,oneof" yaml:"bool_value"` // @gotags: yaml:"bool_value"
+	BoolValue bool `protobuf:"varint,6,opt,name=bool_value,json=boolValue,proto3,oneof"` // @gotags: yaml:"bool_value"
 }
 
 type Value_IntValue struct {
-	IntValue int64 `protobuf:"varint,7,opt,name=int_value,json=intValue,proto3,oneof" yaml:"int_value"` // @gotags: yaml:"int_value"
+	IntValue int64 `protobuf:"varint,7,opt,name=int_value,json=intValue,proto3,oneof"` // @gotags: yaml:"int_value"
 }
 
 type Value_StringValue struct {
-	StringValue string `protobuf:"bytes,8,opt,name=string_value,json=stringValue,proto3,oneof" yaml:"string_value"` // @gotags: yaml:"string_value"
+	StringValue string `protobuf:"bytes,8,opt,name=string_value,json=stringValue,proto3,oneof"` // @gotags: yaml:"string_value"
 }
 
 type Value_ListValue struct {
-	ListValue *ListValue `protobuf:"bytes,9,opt,name=list_value,json=listValue,proto3,oneof" yaml:"list_value"` // @gotags: yaml:"list_value"
+	ListValue *ListValue `protobuf:"bytes,9,opt,name=list_value,json=listValue,proto3,oneof"` // @gotags: yaml:"list_value"
 }
 
 type Value_CollectionValue struct {
-	CollectionValue *CollectionValue `protobuf:"bytes,10,opt,name=collection_value,json=collectionValue,proto3,oneof" yaml:"collection_value"` // @gotags: yaml:"collection_value"
+	CollectionValue *CollectionValue `protobuf:"bytes,10,opt,name=collection_value,json=collectionValue,proto3,oneof"` // @gotags: yaml:"collection_value"
 }
 
 func (*Value_BoolValue) isValue_Value() {}
@@ -1716,7 +1716,7 @@ type ListValue struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Values []*ListOptionValue `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty" yaml:"values"` // @gotags: yaml:"values"
+	Values []*ListOptionValue `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` // @gotags: yaml:"values"
 }
 
 func (x *ListValue) Reset() {
@@ -1836,15 +1836,15 @@ type isListOptionValue_Option interface {
 }
 
 type ListOptionValue_StringValue struct {
-	StringValue string `protobuf:"bytes,1,opt,name=string_value,json=stringValue,proto3,oneof" yaml:"string_value"` // @gotags: yaml:"string_value"
+	StringValue string `protobuf:"bytes,1,opt,name=string_value,json=stringValue,proto3,oneof"` // @gotags: yaml:"string_value"
 }
 
 type ListOptionValue_IntValue struct {
-	IntValue int64 `protobuf:"varint,2,opt,name=int_value,json=intValue,proto3,oneof" yaml:"int_value"` // @gotags: yaml:"int_value"
+	IntValue int64 `protobuf:"varint,2,opt,name=int_value,json=intValue,proto3,oneof"` // @gotags: yaml:"int_value"
 }
 
 type ListOptionValue_BoolValue struct {
-	BoolValue bool `protobuf:"varint,3,opt,name=bool_value,json=boolValue,proto3,oneof" yaml:"bool_value"` // @gotags: yaml:"bool_value"
+	BoolValue bool `protobuf:"varint,3,opt,name=bool_value,json=boolValue,proto3,oneof"` // @gotags: yaml:"bool_value"
 }
 
 func (*ListOptionValue_StringValue) isListOptionValue_Option() {}
@@ -1858,7 +1858,7 @@ type CollectionValue struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Values []*CollectionOption `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty" yaml:"values"` // @gotags: yaml:"values"
+	Values []*CollectionOption `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` // @gotags: yaml:"values"
 }
 
 func (x *CollectionValue) Reset() {
@@ -1906,7 +1906,7 @@ type CollectionOption struct {
 	unknownFields protoimpl.UnknownFields
 
 	// required
-	Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty" yaml:"key"` // @gotags: yaml:"key"
+	Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` // @gotags: yaml:"key"
 	// Types that are assignable to Option:
 	//
 	//	*CollectionOption_IntValue
@@ -1987,15 +1987,15 @@ type isCollectionOption_Option interface {
 }
 
 type CollectionOption_IntValue struct {
-	IntValue int64 `protobuf:"varint,2,opt,name=int_value,json=intValue,proto3,oneof" yaml:"int_value"` // @gotags: yaml:"int_value"
+	IntValue int64 `protobuf:"varint,2,opt,name=int_value,json=intValue,proto3,oneof"` // @gotags: yaml:"int_value"
 }
 
 type CollectionOption_StringValue struct {
-	StringValue string `protobuf:"bytes,3,opt,name=string_value,json=stringValue,proto3,oneof" yaml:"string_value"` // @gotags: yaml:"string_value"
+	StringValue string `protobuf:"bytes,3,opt,name=string_value,json=stringValue,proto3,oneof"` // @gotags: yaml:"string_value"
 }
 
 type CollectionOption_BoolValue struct {
-	BoolValue bool `protobuf:"varint,4,opt,name=bool_value,json=boolValue,proto3,oneof" yaml:"bool_value"` // @gotags: yaml:"bool_value"
+	BoolValue bool `protobuf:"varint,4,opt,name=bool_value,json=boolValue,proto3,oneof"` // @gotags: yaml:"bool_value"
 }
 
 func (*CollectionOption_IntValue) isCollectionOption_Option() {}
diff --git a/vendor/github.com/gookit/goutil/.gitignore b/vendor/github.com/gookit/goutil/.gitignore
index 6eec81adfef..ec0f864bcf5 100644
--- a/vendor/github.com/gookit/goutil/.gitignore
+++ b/vendor/github.com/gookit/goutil/.gitignore
@@ -18,6 +18,7 @@
 *.out
 *.cov
 .DS_Store
+.xenv.toml
 
 *~
 testdata/
diff --git a/vendor/github.com/gookit/goutil/README.md b/vendor/github.com/gookit/goutil/README.md
index 60ae33df5a2..0d03f6e20ca 100644
--- a/vendor/github.com/gookit/goutil/README.md
+++ b/vendor/github.com/gookit/goutil/README.md
@@ -1,4 +1,4 @@
-# Go Util
+# GoUtil
 
 ![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/gookit/goutil?style=flat-square)
 [![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/gookit/goutil)](https://github.com/gookit/goutil)
@@ -7,7 +7,7 @@
 [![Coverage Status](https://coveralls.io/repos/github/gookit/goutil/badge.svg?branch=master)](https://coveralls.io/github/gookit/goutil?branch=master)
 [![Go Reference](https://pkg.go.dev/badge/github.com/gookit/goutil.svg)](https://pkg.go.dev/github.com/gookit/goutil)
 
-💪 Useful utils(**800+**) package for the Go: int, string, array/slice, map, error, time, format, CLI, ENV, filesystem, system, testing and more.
+💪 Useful utils(**900+**) package for the Go: int, string, array/slice, map, struct, reflect, error, time, format, CLI, ENV, filesystem, system, testing and more.
 
 > **[中文说明](README.zh-CN.md)**
 
@@ -52,8 +52,8 @@
 - [`encodes`](encodes): Provide some encoding/decoding, hash, crypto util functions. eg: base64, hex, etc.
 - [`finder`](x/finder) Provides a simple and convenient file/dir lookup function, supports filtering, excluding, matching, ignoring, etc.
 - [`netutil`](netutil) Network util functions. eg: Ip, IpV4, IpV6, Mac, Port, Hostname, etc.
-- [textutil](strutil/textutil) Provide some extensions text handle util functions. eg: text replace, etc.
-- [textscan](strutil/textscan) Implemented a parser that quickly scans and analyzes text content. It can be used to parse INI, Properties and other formats
+- [`textutil`](strutil/textutil) Provide some extensions text handle util functions. eg: text replace, etc.
+- [`textscan`](strutil/textscan) Implemented a parser that quickly scans and analyzes text content. It can be used to parse INI, Properties and other formats
 - [`cmdr`](sysutil/cmdr) Provide for quick build and run a cmd, batch run multi cmd tasks
 - [`clipboard`](x/clipboard) Provide a simple clipboard read and write operations.
 - [`process`](sysutil/process) Provide some process handle util functions.
@@ -63,7 +63,7 @@
 ## Go Doc
 
 Please see [Go doc](https://pkg.go.dev/github.com/gookit/goutil).
-Wiki docs on [DeepWiki - gookit/goutil](https://deepwiki.com/gookit/goutil)
+Wiki docs on [ZRead.ai - gookit/goutil](https://zread.ai/gookit/goutil)
 
 ## Install
 
@@ -109,6 +109,8 @@ dump.Print(somevar, somevar2, ...)
 
 > Package `github.com/gookit/goutil/arrutil`
 
+<details><summary>Click to see functions 👈</summary>
+
 ```go
 // source at arrutil/arrutil.go
 func GetRandomOne[T any](arr []T) T
@@ -152,6 +154,7 @@ func IntsToString[T comdef.Integer](ints []T) string
 func ToInt64s(arr any) (ret []int64, err error)
 func MustToInt64s(arr any) []int64
 func SliceToInt64s(arr []any) []int64
+func ToMap[T any, K comdef.ScalarType, V any](list []T, mapFn func(T) (K, V)) map[K]V
 func AnyToSlice(sl any) (ls []any, err error)
 func AnyToStrings(arr any) []string
 func MustToStrings(arr any) []string
@@ -171,7 +174,8 @@ func FormatIndent(arr any, indent string) string
 func Reverse[T any](ls []T)
 func Remove[T comdef.Compared](ls []T, val T) []T
 func Filter[T any](ls []T, filter ...comdef.MatchFunc[T]) []T
-func Map[T any, V any](list []T, mapFn MapFn[T, V]) []V
+func Map[T, V any](list []T, mapFn MapFn[T, V]) []V
+func Map1[T, R any](list []T, fn func(t T) R) []R
 func Column[T any, V any](list []T, mapFn func(obj T) (val V, find bool)) []V
 func Unique[T comdef.NumberOrString](list []T) []T
 func IndexOf[T comdef.NumberOrString](val T, list []T) int
@@ -189,6 +193,8 @@ func StringsFilter(ss []string, filter ...comdef.StringMatchFunc) []string
 func StringsMap(ss []string, mapFn func(s string) string) []string
 func TrimStrings(ss []string, cutSet ...string) []string

+
+

ArrUtil Usage

check value:
@@ -211,10 +217,13 @@ ss, err := arrutil.ToStrings([]int{1, 2}) // ss: []string{"1", "2"}



+
### Bytes Utils

> Package `github.com/gookit/goutil/byteutil`

+<details><summary>Click to see functions 👈</summary>
+
```go
// source at byteutil/buffer.go
func NewBuffer() *Buffer
@@ -244,18 +253,22 @@ func NewStdEncoder(encFn BytesEncodeFunc, decFn BytesDecodeFunc) *StdEncoder
// source at byteutil/pool.go
func NewChanPool(chSize int, width int, capWidth int) *ChanPool

+
+

Cflag

Package github.com/gookit/goutil/cflag

+cflag - Wraps and extends go flag.FlagSet to build simple command line applications
+
+
+

Click to see functions 👈
+

-// source at cflag/app.go
-func NewApp(fns ...func(app *App)) *App
-func NewCmd(name, desc string, runFunc ...func(c *Cmd) error) *Cmd
// source at cflag/cflag.go
-func SetDebug(open bool)
func New(fns ...func(c *CFlags)) *CFlags
+func NewWith(name, version, desc string, fns ...func(c *CFlags)) *CFlags
func NewEmpty(fns ...func(c *CFlags)) *CFlags
func WithDesc(desc string) func(c *CFlags)
func WithVersion(version string) func(c *CFlags)
@@ -269,6 +282,8 @@ func Value
// source at cflag/optarg.go
func NewArg(name, desc string, required bool) *FlagArg
// source at cflag/util.go
+func SetDebug(open bool)
+func DebugMsg(format string, args ...any)
func IsGoodName(name string) bool
func IsZeroValue(opt *flag.Flag, value string) (bool, bool)
func AddPrefix(name string) string
@@ -280,15 +295,20 @@ func IsFlagHelpErr(err error) bool
func WrapColorForCode(s string) string
func ReplaceShorts(args []string, shortsMap map[string]string) []string

+


+

cflag Usage

cflag usage please see cflag/README.md

CLI Utils

Package github.com/gookit/goutil/cliutil

+

Click to see functions 👈
+

// source at cliutil/cliutil.go
func SplitMulti(ss []string, sep string) []string
@@ -325,6 +345,8 @@ func InputIsYes(ans string) bool
func ByteIsYes(ans byte) bool
func ReadPassword(question ...string) string

+


+

CLI Util Usage

@@ -381,10 +403,13 @@ Build line: ./myapp -a val0 -m "this is message" arg0

More, please see ./cliutil/README

Var Dumper

Package github.com/gookit/goutil/dump

+

Click to see functions 👈
+

// source at dump/dump.go
func Std() *Dumper
@@ -411,7 +436,10 @@ func WithoutPosition() OptionFunc
func WithoutOutput(out io.Writer) OptionFunc
func WithoutColor() OptionFunc
func WithoutType() OptionFunc
+func WithoutLen() OptionFunc

+


+

Examples

example code:
@@ -456,10 +484,13 @@ Preview:

ENV/Environment

Package github.com/gookit/goutil/envutil

+

Click to see functions 👈
+

// source at envutil/envutil.go
func VarReplace(s string) string
@@ -503,6 +534,8 @@ func UnsetEnvs(keys ...string)
func LoadText(text string)
func LoadString(line string) bool

+


+

ENV Util Usage

helper functions:
@@ -522,13 +555,18 @@ envutil.ParseValue("${ENV_NAME | defValue}")



+
### Errorx

> Package `github.com/gookit/goutil/errorx`

-Package errorx provide a enhanced error implements, allow with call stack and wrap another error.
+`errorx` provides an enhanced error reporting implementation that contains call stack information and can wrap the previous level of error.
+
+> Additional call stack information is included when printing errors, making it easy to log and find problems.


+<details><summary>Click to see functions 👈</summary>
+
```go
// source at errorx/assert.go
func IsTrue(result bool, fmtAndArgs ...any) error
@@ -578,6 +616,8 @@ func Is(err, target error) bool
func To(err error, target any) bool
func As(err error, target any) bool

+
+

Errorx Usage

@@ -655,16 +695,23 @@ runtime.goexit()



+
### File System

> Package `github.com/gookit/goutil/fsutil`

+Package `fsutil` Filesystem util functions: quick check, create, read and write file. eg: file and dir check, operate
+
+
+<details><summary>Click to see functions 👈</summary>
+
```go
// source at fsutil/check.go
func PathExists(path string) bool
func IsDir(path string) bool
func FileExists(path string) bool
func IsFile(path string) bool
+func IsSymlink(path string) bool
func IsAbsPath(aPath string) bool
func IsEmptyDir(dirPath string) bool
func IsImageFile(path string) bool
@@ -680,6 +727,10 @@ func FirstExistsDir(paths ...string) string
func FirstExistsFile(paths ...string) string
func MatchPaths(paths []string, matcher PathMatchFunc) []string
func MatchFirst(paths []string, matcher PathMatchFunc, defaultPath string) string
+func FindAllInParentDirs(dirPath, name string, optFns ...FindParentOptFn) []string
+func FindOneInParentDirs(dirPath, name string, optFns ...FindParentOptFn) string
+func FindNameInParentDirs(dirPath, name string, collectFn func(fullPath string), optFns ...FindParentOptFn)
+func FindInParentDirs(dirPath string, matchFunc func(dir string) bool, maxLevel int)
func SearchNameUp(dirPath, name string) string
func SearchNameUpx(dirPath, name string) (string, bool)
func WalkDir(dir string, fn fs.WalkDirFunc) error
@@ -713,9 +764,12 @@ func FileExt(fPath string) string
func Extname(fPath string) string
func Suffix(fPath string) string
func Expand(pathStr string) string
+func ExpandHome(pathStr string) string
func ExpandPath(pathStr string) string
func ResolvePath(pathStr string) string
func SplitPath(pathStr string) (dir, name string)
+func UserHomeDir() string
+func HomeDir() string
// source at fsutil/info_nonwin.go
func Realpath(pathStr string) string
// source at fsutil/mime.go
@@ -723,9 +777,11 @@ func DetectMime(path string) string
func MimeType(path string) (mime string)
func ReaderMimeType(r io.Reader) (mime string)
// source at fsutil/operate.go
-func Mkdir(dirPath string, perm os.FileMode) error
-func MkDirs(perm os.FileMode, dirPaths ...string) error
-func MkSubDirs(perm os.FileMode, parentDir string, subDirs ...string) error
+func Mkdir(dirPath string, perm fs.FileMode) error
+func MkdirQuick(dirPath string) error
+func EnsureDir(path string) error
+func MkDirs(perm fs.FileMode, dirPaths ...string) error
+func MkSubDirs(perm fs.FileMode, parentDir string, subDirs ...string) error
func MkParentDir(fpath string) error
func NewOpenOption(optFns ...OpenOptionFunc) *OpenOption
func OpenOptOrNew(opt *OpenOption) *OpenOption
@@ -779,7 +835,10 @@ func WriteOSFile(f *os.File, data any) (n int, err error)
func CopyFile(srcPath, dstPath string) error
func MustCopyFile(srcPath, dstPath string)
func UpdateContents(filePath string, handleFn func(bs []byte) []byte) error
+func CreateSymlink(target, linkPath string) error

+
+

FsUtil Usage

@@ -811,6 +870,7 @@ func main() {



+
### JSON Utils

> Package `github.com/gookit/goutil/jsonutil`
@@ -841,10 +901,13 @@ func IsObject(s string) bool
func StripComments(src string) string

-### Map
+
+### Maputil

Package github.com/gookit/goutil/maputil

+

Click to see functions 👈
+

// source at maputil/check.go
func HasKey(mp, key any) (ok bool)
@@ -890,6 +953,7 @@ func Merge1level(mps ...map[string]any) map[string]any
func DeepMerge(src, dst map[string]any, deep int) map[string]any
func MergeSMap(src, dst map[string]string, ignoreCase bool) map[string]string
func MergeStrMap(src, dst map[string]string) map[string]string
+func AppendSMap(dst, src map[string]string) map[string]string
func MergeStringMap(src, dst map[string]string, ignoreCase bool) map[string]string
func MergeMultiSMap(mps ...map[string]string) map[string]string
func MergeL2StrMap(mps ...map[string]map[string]string) map[string]map[string]string
@@ -900,16 +964,23 @@ func MakeByKeys(keys []string, val any) (mp map[string]any)
func SetByPath(mp *map[string]any, path string, val any) error
func SetByKeys(mp *map[string]any, keys []string, val any) (err error)

+


+

Math/Number

Package github.com/gookit/goutil/mathutil

+Package mathutil provide math(int, number) util functions. eg: convert, math calc, random
+
+

Click to see functions 👈
+

// source at mathutil/calc.go
func Abs[T comdef.Int](val T) T
// source at mathutil/check.go
func IsNumeric(c byte) bool
+func IsInteger(val any) bool
func Compare(first, second any, op string) bool
func CompInt[T comdef.Xint](first, second T, op string) (ok bool)
func CompInt64(first, second int64, op string) bool
@@ -928,11 +999,7 @@ func SwapMaxInt(x, y int) (int, int)
func MaxI64(x, y int64) int64
func SwapMaxI64(x, y int64) (int64, int64)
func MaxFloat(x, y float64) float64
-// source at mathutil/convert.go
-func NewConvOption[T any](optFns ...ConvOptionFn[T]) *ConvOption[T]
-func WithNilAsFail[T any](opt *ConvOption[T])
-func WithHandlePtr[T any](opt *ConvOption[T])
-func WithUserConvFn[T any](fn ToTypeFunc[T]) ConvOptionFn[T]
+// source at mathutil/conv2int.go
func Int(in any) (int, error)
func SafeInt(in any) int
func QuietInt(in any) int
@@ -943,8 +1010,6 @@ func IntOr(in any, defVal int) int
func IntOrErr(in any) (int, error)
func ToInt(in any) (int, error)
func ToIntWith(in any, optFns ...ConvOptionFn[int]) (iVal int, err error)
-func StrInt(s string) int
-func StrIntOr(s string, defVal int) int
func Int64(in any) (int64, error)
func SafeInt64(in any) int64
func QuietInt64(in any) int64
@@ -972,6 +1037,19 @@ func Uint64Or(in any, defVal uint64) uint64
func Uint64OrErr(in any) (uint64, error)
func ToUint64(in any) (uint64, error)
func ToUint64With(in any, optFns ...ConvOptionFn[uint64]) (u64 uint64, err error)
+func StrInt(s string) int
+func StrIntOr(s string, defVal int) int
+func TryStrInt(s string) (int, error)
+func TryStrInt64(s string) (int64, error)
+func TryStrUint64(s string) (uint64, error)
+// source at mathutil/convert.go
+func NewConvOption[T any](optFns ...ConvOptionFn[T]) *ConvOption[T]
+func WithNilAsFail[T any](opt *ConvOption[T])
+func WithHandlePtr[T any](opt *ConvOption[T])
+func WithStrictMode[T any](opt *ConvOption[T])
+func WithUserConvFn[T any](fn ToTypeFunc[T]) ConvOptionFn[T]
+func StrictInt(val any) (int64, bool)
+func StrictUint(val any) (uint64, bool)
func QuietFloat(in any) float64
func SafeFloat(in any) float64
func FloatOrPanic(in any) float64
@@ -995,6 +1073,7 @@ func TryToString(val any, defaultAsErr bool) (string, error)
func ToStringWith(in any, optFns ...comfunc.ConvOptionFn) (string, error)
// source at mathutil/format.go
func DataSize(size uint64) string
+func FormatBytes(bytes int) string
func HowLongAgo(sec int64) string
// source at mathutil/mathutil.go
func OrElse[T comdef.Number](val, defVal T) T
@@ -1015,11 +1094,17 @@ func RandInt(min, max int) int
func RandIntWithSeed(min, max int, seed int64) int
func RandomIntWithSeed(min, max int, seed int64) int

+


+

Reflects

Package github.com/gookit/goutil/reflects

+Package reflects Provide extends reflection util functions. eg: check, convert, value set, etc.
+
+

Click to see functions 👈
+

// source at reflects/check.go
func IsTimeType(t reflect.Type) bool
@@ -1085,11 +1170,17 @@ func SetRValue(rv, val reflect.Value)
func Wrap(rv reflect.Value) Value
func ValueOf(v any) Value

+

-### Structs
+
+### Struct Utils

Package github.com/gookit/goutil/structs

+Package structs Provide some extends util functions for struct. eg: tag parse, struct init, value set/get
+
+

Click to see functions 👈
+

// source at structs/alias.go
func NewAliases(checker func(alias string)) *Aliases
@@ -1140,11 +1231,15 @@ func WithBeforeSetFn(fn BeforeSetFunc) SetOptFunc
func BindData(ptr any, data map[string]any, optFns ...SetOptFunc) error
func SetValues(ptr any, data map[string]any, optFns ...SetOptFunc) error

+

-### Strings
+
+### String Utils

Package github.com/gookit/goutil/strutil

+

Click to see functions 👈
+

// source at strutil/bytes.go
func NewBuffer(initSize ...int) *Buffer
@@ -1152,16 +1247,21 @@ func NewByteChanPool(maxSize, width, capWidth int) *ByteChanPool
// source at strutil/check.go
func IsNumChar(c byte) bool
func IsInt(s string) bool
+func IsUint(s string) bool
func IsFloat(s string) bool
func IsNumeric(s string) bool
+func IsPositiveNum(s string) bool
func IsAlphabet(char uint8) bool
func IsAlphaNum(c uint8) bool
+func IsUpper(s string) bool
+func IsLower(s string) bool
func StrPos(s, sub string) int
func BytePos(s string, bt byte) int
func IEqual(s1, s2 string) bool
func NoCaseEq(s, t string) bool
func IContains(s, sub string) bool
func ContainsByte(s string, c byte) bool
+func ContainsByteOne(s string, bs []byte) bool
func ContainsOne(s string, subs []string) bool
func HasOneSub(s string, subs []string) bool
func IContainsOne(s string, subs []string) bool
@@ -1186,6 +1286,7 @@ func HasEmpty(ss ...string) bool
func IsAllEmpty(ss ...string) bool
func IsVersion(s string) bool
func IsVarName(s string) bool
+func IsEnvName(s string) bool
func Compare(s1, s2, op string) bool
func VersionCompare(v1, v2, op string) bool
func SimpleMatch(s string, keywords []string) bool
@@ -1197,7 +1298,9 @@ func MatchNodePath(pattern, s string, sep string) bool
// source at strutil/convbase.go
func Base10Conv(src string, to int) string
func BaseConv(src string, from, to int) string
+func BaseConvInt(src uint64, to int) string
func BaseConvByTpl(src string, fromBase, toBase string) string
+func BaseConvIntByTpl(dec uint64, toBase string) string
// source at strutil/convert.go
func Quote(s string) string
func Unquote(s string) string
@@ -1257,7 +1360,6 @@ func ToArray(s string, sep ...string) []string
func Strings(s string, sep ...string) []string
func ToStrings(s string, sep ...string) []string
func ToSlice(s string, sep ...string) []string
-func ToOSArgs(s string) []string
func ToDuration(s string) (time.Duration, error)
// source at strutil/encode.go
func EscapeJS(s string) string
@@ -1299,6 +1401,10 @@ func Camel(s string, sep ...string) string
func CamelCase(s string, sep ...string) string
func Indent(s, prefix string) string
func IndentBytes(b, prefix []byte) []byte
+func Replaces(str string, pairs map[string]string) string
+func ReplaceVars(s string, vars map[string]string) string
+func NewReplacer(pairs map[string]string) *strings.Replacer
+func WrapTag(s, tag string) string
// source at strutil/gensn.go
func MicroTimeID() string
func MicroTimeHexID() string
@@ -1307,7 +1413,8 @@ func MTimeBase36() string
func MTimeBaseID(toBase int) string
func DatetimeNo(prefix string) string
func DateSN(prefix string) string
-func DateSNV2(prefix string, extBase ...int) string
+func DateSNv2(prefix string, extBase ...int) string
+func DateSNv3(prefix string, dateLen int, extBase ...int) string
// source at strutil/hash.go
func Md5(src any) string
func MD5(src any) string
@@ -1335,6 +1442,7 @@ func RepeatRune(char rune, times int) []rune
func RepeatBytes(char byte, times int) []byte
func RepeatChars[T byte | rune](char T, times int) []T
// source at strutil/parse.go
+func NumVersion(s string) string
func MustToTime(s string, layouts ...string) time.Time
func ToTime(s string, layouts ...string) (t time.Time, err error)
func ParseSizeRange(expr string, opt *ParseSizeOpt) (min, max uint64, err error)
@@ -1398,31 +1506,17 @@ func OrElse(s, orVal string) string
func OrElseNilSafe(s *string, orVal string) string
func OrHandle(s string, fn comdef.StringHandleFunc) string
func Valid(ss ...string) string
-func Replaces(str string, pairs map[string]string) string
-func NewReplacer(pairs map[string]string) *strings.Replacer
-func WrapTag(s, tag string) string
func SubstrCount(s, substr string, params ...uint64) (int, error)

+

-### Syncs

-> Package github.com/gookit/goutil/syncs

-go -// source at syncs/chan.go -func Go(f func() error) error -// source at syncs/group.go -func NewCtxErrGroup(ctx context.Context, limit ...int) (*ErrGroup, context.Context) -func NewErrGroup(limit ...int) *ErrGroup -// source at syncs/signal.go -func WaitCloseSignals(onClose func(sig os.Signal), sigCh ...chan os.Signal) -func SignalHandler(ctx context.Context, signals ...os.Signal) (execute func() error, interrupt func(error)) -

System Utils

Package github.com/gookit/goutil/sysutil

+

Click to see functions 👈
+

// source at sysutil/exec.go
func NewCmd(bin string, args ...string) *cmdr.Cmd
@@ -1473,6 +1567,13 @@ func OpenURL(URL string) error
// source at sysutil/sysutil_nonwin.go
func Kill(pid int, signal syscall.Signal) error
func ProcessExists(pid int) bool
+// source at sysutil/sysutil_unix.go
+func IsWin() bool
+func IsWindows() bool
+func IsMac() bool
+func IsDarwin() bool
+func IsLinux() bool
+func OpenURL(URL string) error
// source at sysutil/user.go
func MustFindUser(uname string) *user.User
func LoginUser() *user.User
@@ -1491,24 +1592,29 @@ func ChangeUserByName(newUname string) error
func ChangeUserUidGid(newUID int, newGid int) error
func ChangeUserUIDGid(newUID int, newGid int) (err error)

+


+

Testing Utils

Package github.com/gookit/goutil/testutil

+

Click to see functions 👈
+

// source at testutil/buffer.go
func NewBuffer() *byteutil.Buffer
+func NewSafeBuffer() *SafeBuffer
// source at testutil/envmock.go
func MockEnvValue(key, val string, fn func(nv string))
func MockEnvValues(kvMap map[string]string, fn func())
func MockOsEnvByText(envText string, fn func())
-func MockOsEnv(mp map[string]string, fn func())
func SetOsEnvs(mp map[string]string) string
func RemoveTmpEnvs(tmpKey string)
func ClearOSEnv()
func RevertOSEnv()
func RunOnCleanEnv(runFn func())
+func MockOsEnv(mp map[string]string, fn func())
func MockCleanOsEnv(mp map[string]string, fn func())
// source at testutil/httpmock.go
func NewHTTPRequest(method, path string, data *MD) *http.Request
@@ -1533,12 +1639,17 @@ func RestoreTimeLocal()
func NewTestWriter() *TestWriter
func NewDirEnt(fPath string, isDir ...bool) *fakeobj.DirEntry

+


+

Timex

Package github.com/gookit/goutil/timex

-Provides an enhanced time.Time implementation, and add more commonly used functional methods.
+Provides an enhanced time.Time implementation, and add more commonly used functional methods.
+
+

Click to see functions 👈
+

// source at timex/check.go
func IsDuration(s string) bool
@@ -1546,12 +1657,14 @@ func InRange(dst, start, end time.Time) bool
// source at timex/conv.go
func Elapsed(start, end time.Time) string
func ElapsedNow(start time.Time) string
+func FormatDuration(d time.Duration) string
func FromNow(t time.Time) string
func FromNowWith(u time.Time, tms []TimeMessage) string
func HowLongAgo(diffSec int64) string
func HowLongAgo2(diffSec int64, tms []TimeMessage) string
func ToTime(s string, layouts ...string) (time.Time, error)
func ToDur(s string) (time.Duration, error)
+func ParseDuration(s string) (time.Duration, error)
func ToDuration(s string) (time.Duration, error)
func TryToTime(s string, bt time.Time) (time.Time, error)
func ParseRange(expr string, opt *ParseRangeOpt) (start, end time.Time, err error)
@@ -1600,6 +1713,8 @@ func FormatUnix(sec int64, layout ...string) string
func FormatUnixBy(sec int64, layout string) string
func FormatUnixByTpl(sec int64, template ...string) string

+


+

Timex Usage

Create timex instance
@@ -1719,6 +1834,7 @@ date := FormatUnixByTpl(ts, "Y-m-d H:I:S") // Get: 2022-04-20 19:40:34



+
## Code Check & Testing

```bash
diff --git a/vendor/github.com/gookit/goutil/README.zh-CN.md b/vendor/github.com/gookit/goutil/README.zh-CN.md
index ee6d10db0e0..17d654cd612 100644
--- a/vendor/github.com/gookit/goutil/README.zh-CN.md
+++ b/vendor/github.com/gookit/goutil/README.zh-CN.md
@@ -1,4 +1,4 @@
-# Go Util
+# GoUtil

![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/gookit/goutil?style=flat-square)
[![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/gookit/goutil)](https://github.com/gookit/goutil)
@@ -7,7 +7,7 @@
[![Coverage Status](https://coveralls.io/repos/github/gookit/goutil/badge.svg?branch=master)](https://coveralls.io/github/gookit/goutil?branch=master)
[![Go Reference](https://pkg.go.dev/badge/github.com/gookit/goutil.svg)](https://pkg.go.dev/github.com/gookit/goutil)

-`goutil` Go 常用功能的扩展工具库(**800+**)。包含:数字,byte, 字符串,slice/数组,Map,结构体,反射,文本,文件,错误,时间日期,测试,特殊处理,格式化,常用信息获取等等。
+`goutil` Go 常用功能的扩展工具库(**900+**)。包含:数字,byte, 字符串,slice/数组,Map,结构体,反射,文本,文件,错误,时间日期,测试,特殊处理,格式化,常用信息获取等等。

> **[EN README](README.md)**

@@ -53,17 +53,17 @@
- [`cmdline`](cliutil/cmdline) 提供 cmdline 解析,args 构建到 cmdline
- [`encodes`](x/encodes): Provide some encoding/decoding, hash, crypto util functions. eg: base64, hex, etc.
- [`finder`](x/finder) 提供简单方便的file/dir查找功能,支持过滤、排除、匹配、忽略等。
-- [textscan](strutil/textscan) 实现了一个快速扫描和分析文本内容的解析器. 可用于解析 INI, Properties 等格式内容
-- [textutil](strutil/textutil) 提供一些常用的扩展文本处理功能函数。
-- [cmdr](sysutil/cmdr) 提供快速构建和运行一个cmd,批量运行多个cmd任务
-- [process](sysutil/process) 提供一些进程操作相关的实用功能。
+- [`textscan`](strutil/textscan) 实现了一个快速扫描和分析文本内容的解析器. 可用于解析 INI, Properties 等格式内容
+- [`textutil`](strutil/textutil) 提供一些常用的扩展文本处理功能函数。
+- [`cmdr`](sysutil/cmdr) 提供快速构建和运行一个cmd,批量运行多个cmd任务
+- [`process`](sysutil/process) 提供一些进程操作相关的实用功能。
- [`fmtutil`](x/fmtutil) 格式化数据工具函数 eg:数据size
- [`goinfo`](x/goinfo) 提供一些与Go info, runtime 相关的工具函数。

## GoDoc

- [Godoc for github](https://pkg.go.dev/github.com/gookit/goutil)
-- Wiki docs on [DeepWiki - gookit/goutil](https://deepwiki.com/gookit/goutil)
+- Wiki docs on [ZRead.ai - gookit/goutil](https://zread.ai/gookit/goutil)

## 获取

@@ -109,6 +109,8 @@ dump.Print(somevar, somevar2, ...)

> Package `github.com/gookit/goutil/arrutil`

+<details><summary>Click to see functions 👈</summary>
+
```go
// source at arrutil/arrutil.go
func GetRandomOne[T any](arr []T) T
@@ -152,6 +154,7 @@ func IntsToString[T comdef.Integer](ints []T) string
func ToInt64s(arr any) (ret []int64, err error)
func MustToInt64s(arr any) []int64
func SliceToInt64s(arr []any) []int64
+func ToMap[T any, K comdef.ScalarType, V any](list []T, mapFn func(T) (K, V)) map[K]V
func AnyToSlice(sl any) (ls []any, err error)
func AnyToStrings(arr any) []string
func MustToStrings(arr any) []string
@@ -171,7 +174,8 @@ func FormatIndent(arr any, indent string) string
func Reverse[T any](ls []T)
func Remove[T comdef.Compared](ls []T, val T) []T
func Filter[T any](ls []T, filter ...comdef.MatchFunc[T]) []T
-func Map[T any, V any](list []T, mapFn MapFn[T, V]) []V
+func Map[T, V any](list []T, mapFn MapFn[T, V]) []V
+func Map1[T, R any](list []T, fn func(t T) R) []R
func Column[T any, V any](list []T, mapFn func(obj T) (val V, find bool)) []V
func Unique[T comdef.NumberOrString](list []T) []T
func IndexOf[T comdef.NumberOrString](val T, list []T) int
@@ -189,6 +193,8 @@ func StringsFilter(ss []string, filter ...comdef.StringMatchFunc) []string
func StringsMap(ss []string, mapFn func(s string) string) []string
func TrimStrings(ss []string, cutSet ...string) []string

+
+

ArrUtil Usage

check value:
@@ -211,10 +217,13 @@ ss, err := arrutil.ToStrings([]int{1, 2}) // ss: []string{"1", "2"}



+
### Bytes Utils

> Package `github.com/gookit/goutil/byteutil`

+<details><summary>Click to see functions 👈</summary>
+
```go
// source at byteutil/buffer.go
func NewBuffer() *Buffer
@@ -244,18 +253,22 @@ func NewStdEncoder(encFn BytesEncodeFunc, decFn BytesDecodeFunc) *StdEncoder
// source at byteutil/pool.go
func NewChanPool(chSize int, width int, capWidth int) *ChanPool

+
+

Cflag

Package github.com/gookit/goutil/cflag

+cflag - Wraps and extends go flag.FlagSet to build simple command line applications
+
+
+

Click to see functions 👈
+

-// source at cflag/app.go
-func NewApp(fns ...func(app *App)) *App
-func NewCmd(name, desc string, runFunc ...func(c *Cmd) error) *Cmd
// source at cflag/cflag.go
-func SetDebug(open bool)
func New(fns ...func(c *CFlags)) *CFlags
+func NewWith(name, version, desc string, fns ...func(c *CFlags)) *CFlags
func NewEmpty(fns ...func(c *CFlags)) *CFlags
func WithDesc(desc string) func(c *CFlags)
func WithVersion(version string) func(c *CFlags)
@@ -269,6 +282,8 @@ func Value
// source at cflag/optarg.go
func NewArg(name, desc string, required bool) *FlagArg
// source at cflag/util.go
+func SetDebug(open bool)
+func DebugMsg(format string, args ...any)
func IsGoodName(name string) bool
func IsZeroValue(opt *flag.Flag, value string) (bool, bool)
func AddPrefix(name string) string
@@ -280,15 +295,20 @@ func IsFlagHelpErr(err error) bool
func WrapColorForCode(s string) string
func ReplaceShorts(args []string, shortsMap map[string]string) []string

+


+

cflag Usage

-cflag 使用说明请看 cflag/README.zh-CN.md
+cflag usage please see cflag/README.md
+

CLI Utils

Package github.com/gookit/goutil/cliutil

+

Click to see functions 👈
+

// source at cliutil/cliutil.go
func SplitMulti(ss []string, sep string) []string
@@ -325,6 +345,8 @@ func InputIsYes(ans string) bool
func ByteIsYes(ans byte) bool
func ReadPassword(question ...string) string

+


+

CLI Util Usage

@@ -381,10 +403,13 @@ Build line: ./myapp -a val0 -m "this is message" arg0

More, please see ./cliutil/README

Var Dumper

Package github.com/gookit/goutil/dump

+

Click to see functions 👈
+

// source at dump/dump.go
func Std() *Dumper
@@ -411,7 +436,10 @@ func WithoutPosition() OptionFunc
func WithoutOutput(out io.Writer) OptionFunc
func WithoutColor() OptionFunc
func WithoutType() OptionFunc
+func WithoutLen() OptionFunc

+


+

Examples

example code:
@@ -456,10 +484,13 @@ Preview:

ENV/Environment

Package github.com/gookit/goutil/envutil

+

Click to see functions 👈
+

// source at envutil/envutil.go
func VarReplace(s string) string
@@ -503,6 +534,8 @@ func UnsetEnvs(keys ...string)
func LoadText(text string)
func LoadString(line string) bool

+


+

ENV Util Usage

helper functions:
@@ -522,15 +555,18 @@ envutil.ParseValue("${ENV_NAME | defValue}")



+
### Errorx

> Package `github.com/gookit/goutil/errorx`

-`errorx` 提供了增强的错误报告实现,包含调用堆栈信息并且可以包装上一级错误。
+`errorx` provides an enhanced error reporting implementation that contains call stack information and can wrap the previous level of error.

-> 在打印 error 时会额外附带调用栈信息, 方便记录日志和查找问题。
+> Additional call stack information is included when printing errors, making it easy to log and find problems.


+<details><summary>Click to see functions 👈</summary>
+
```go
// source at errorx/assert.go
func IsTrue(result bool, fmtAndArgs ...any) error
@@ -580,12 +616,14 @@ func Is(err, target error) bool
func To(err error, target any) bool
func As(err error, target any) bool

+
+

-#### Errorx 使用示例
+#### Errorx Usage

-创建错误带有调用栈信息
+Create error with call stack info

-- 使用 errorx.New 替代 errors.New
+- use the errorx.New instead errors.New

func doSomething() error {
@@ -596,7 +634,7 @@ func doSomething() error {
}

-- 使用 errorx.Newf 或者 errorx.Errorf 替代 fmt.Errorf
+- use the errorx.Newf or errorx.Errorf instead fmt.Errorf

func doSomething() error {
@@ -607,9 +645,9 @@ func doSomething() error {
}

-包装上一级错误
+Wrap the previous error

-之前这样使用:
+used like this before:

    if err := SomeFunc(); err != nil {
@@ -617,7 +655,7 @@ func doSomething() error {
	}

-可以替换成:
+can be replaced with:

    if err := SomeFunc(); err != nil {
@@ -625,9 +663,9 @@ func doSomething() error {
	}

-使用效果示例
+Print the errorx.New() error

-更多关于 errorx 的使用请看 ./errorx/README
+Examples for use errorx package, more please see ./errorx/README

    err := errorx.New("the error message")
@@ -657,16 +695,23 @@ runtime.goexit()

File System

Package github.com/gookit/goutil/fsutil

+Package fsutil Filesystem util functions: quick check, create, read and write file. eg: file and dir check, operate
+
+
+

Click to see functions 👈
+

// source at fsutil/check.go
func PathExists(path string) bool
func IsDir(path string) bool
func FileExists(path string) bool
func IsFile(path string) bool
+func IsSymlink(path string) bool
func IsAbsPath(aPath string) bool
func IsEmptyDir(dirPath string) bool
func IsImageFile(path string) bool
@@ -682,6 +727,10 @@ func FirstExistsDir(paths ...string) string
func FirstExistsFile(paths ...string) string
func MatchPaths(paths []string, matcher PathMatchFunc) []string
func MatchFirst(paths []string, matcher PathMatchFunc, defaultPath string) string
+func FindAllInParentDirs(dirPath, name string, optFns ...FindParentOptFn) []string
+func FindOneInParentDirs(dirPath, name string, optFns ...FindParentOptFn) string
+func FindNameInParentDirs(dirPath, name string, collectFn func(fullPath string), optFns ...FindParentOptFn)
+func FindInParentDirs(dirPath string, matchFunc func(dir string) bool, maxLevel int)
func SearchNameUp(dirPath, name string) string
func SearchNameUpx(dirPath, name string) (string, bool)
func WalkDir(dir string, fn fs.WalkDirFunc) error
@@ -715,9 +764,12 @@ func FileExt(fPath string) string
func Extname(fPath string) string
func Suffix(fPath string) string
func Expand(pathStr string) string
+func ExpandHome(pathStr string) string
func ExpandPath(pathStr string) string
func ResolvePath(pathStr string) string
func SplitPath(pathStr string) (dir, name string)
+func UserHomeDir() string
+func HomeDir() string
// source at fsutil/info_nonwin.go
func Realpath(pathStr string) string
// source at fsutil/mime.go
@@ -725,9 +777,11 @@ func DetectMime(path string) string
func MimeType(path string) (mime string)
func ReaderMimeType(r io.Reader) (mime string)
// source at fsutil/operate.go
-func Mkdir(dirPath string, perm os.FileMode) error
-func MkDirs(perm os.FileMode, dirPaths ...string) error
-func MkSubDirs(perm os.FileMode, parentDir string, subDirs ...string) error
+func Mkdir(dirPath string, perm fs.FileMode) error
+func MkdirQuick(dirPath string) error
+func EnsureDir(path string) error
+func MkDirs(perm fs.FileMode, dirPaths ...string) error
+func MkSubDirs(perm fs.FileMode, parentDir string, subDirs ...string) error
func MkParentDir(fpath string) error
func NewOpenOption(optFns ...OpenOptionFunc) *OpenOption
func OpenOptOrNew(opt *OpenOption) *OpenOption
@@ -781,7 +835,10 @@ func WriteOSFile(f *os.File, data any) (n int, err error)
func CopyFile(srcPath, dstPath string) error
func MustCopyFile(srcPath, dstPath string)
func UpdateContents(filePath string, handleFn func(bs []byte) []byte) error
+func CreateSymlink(target, linkPath string) error

+


+

FsUtil Usage

@@ -813,6 +870,7 @@ func main() {



+
### JSON Utils

> Package `github.com/gookit/goutil/jsonutil`
@@ -843,10 +901,13 @@ func IsObject(s string) bool
func StripComments(src string) string

-### Map
+
+### Maputil

Package github.com/gookit/goutil/maputil

+

Click to see functions 👈
+

// source at maputil/check.go
func HasKey(mp, key any) (ok bool)
@@ -892,6 +953,7 @@ func Merge1level(mps ...map[string]any) map[string]any
func DeepMerge(src, dst map[string]any, deep int) map[string]any
func MergeSMap(src, dst map[string]string, ignoreCase bool) map[string]string
func MergeStrMap(src, dst map[string]string) map[string]string
+func AppendSMap(dst, src map[string]string) map[string]string
func MergeStringMap(src, dst map[string]string, ignoreCase bool) map[string]string
func MergeMultiSMap(mps ...map[string]string) map[string]string
func MergeL2StrMap(mps ...map[string]map[string]string) map[string]map[string]string
@@ -902,16 +964,23 @@ func MakeByKeys(keys []string, val any) (mp map[string]any)
func SetByPath(mp *map[string]any, path string, val any) error
func SetByKeys(mp *map[string]any, keys []string, val any) (err error)

+


+

Math/Number

Package github.com/gookit/goutil/mathutil

+Package mathutil provide math(int, number) util functions. eg: convert, math calc, random
+
+

Click to see functions 👈
+

// source at mathutil/calc.go
func Abs[T comdef.Int](val T) T
// source at mathutil/check.go
func IsNumeric(c byte) bool
+func IsInteger(val any) bool
func Compare(first, second any, op string) bool
func CompInt[T comdef.Xint](first, second T, op string) (ok bool)
func CompInt64(first, second int64, op string) bool
@@ -930,11 +999,7 @@ func SwapMaxInt(x, y int) (int, int)
func MaxI64(x, y int64) int64
func SwapMaxI64(x, y int64) (int64, int64)
func MaxFloat(x, y float64) float64
-// source at mathutil/convert.go
-func NewConvOption[T any](optFns ...ConvOptionFn[T]) *ConvOption[T]
-func WithNilAsFail[T any](opt *ConvOption[T])
-func WithHandlePtr[T any](opt *ConvOption[T])
-func WithUserConvFn[T any](fn ToTypeFunc[T]) ConvOptionFn[T]
+// source at mathutil/conv2int.go
func Int(in any) (int, error)
func SafeInt(in any) int
func QuietInt(in any) int
@@ -945,8 +1010,6 @@ func IntOr(in any, defVal int) int
func IntOrErr(in any) (int, error)
func ToInt(in any) (int, error)
func ToIntWith(in any, optFns ...ConvOptionFn[int]) (iVal int, err error)
-func StrInt(s string) int
-func StrIntOr(s string, defVal int) int
func Int64(in any) (int64, error)
func SafeInt64(in any) int64
func QuietInt64(in any) int64
@@ -974,6 +1037,19 @@ func Uint64Or(in any, defVal uint64) uint64
func Uint64OrErr(in any) (uint64, error)
func ToUint64(in any) (uint64, error)
func ToUint64With(in any, optFns ...ConvOptionFn[uint64]) (u64 uint64, err error)
+func StrInt(s string) int
+func StrIntOr(s string, defVal int) int
+func TryStrInt(s string) (int, error)
+func TryStrInt64(s string) (int64, error)
+func TryStrUint64(s string) (uint64, error)
+// source at mathutil/convert.go
+func NewConvOption[T any](optFns ...ConvOptionFn[T]) *ConvOption[T]
+func WithNilAsFail[T any](opt *ConvOption[T])
+func WithHandlePtr[T any](opt *ConvOption[T])
+func WithStrictMode[T any](opt *ConvOption[T])
+func WithUserConvFn[T any](fn ToTypeFunc[T]) ConvOptionFn[T]
+func StrictInt(val any) (int64, bool)
+func StrictUint(val any) (uint64, bool)
func QuietFloat(in any) float64
func SafeFloat(in any) float64
func FloatOrPanic(in any) float64
@@ -997,6 +1073,7 @@ func TryToString(val any, defaultAsErr bool) (string, error)
func ToStringWith(in any, optFns ...comfunc.ConvOptionFn) (string, error)
// source at mathutil/format.go
func DataSize(size uint64) string
+func FormatBytes(bytes int) string
func HowLongAgo(sec int64) string
// source at mathutil/mathutil.go
func OrElse[T comdef.Number](val, defVal T) T
@@ -1017,11 +1094,17 @@ func RandInt(min, max int) int
func RandIntWithSeed(min, max int, seed int64) int
func RandomIntWithSeed(min, max int, seed int64) int

+


+

Reflects

Package github.com/gookit/goutil/reflects

+Package reflects Provide extends reflection util functions. eg: check, convert, value set, etc.
+
+

Click to see functions 👈
+

// source at reflects/check.go
func IsTimeType(t reflect.Type) bool
@@ -1087,11 +1170,17 @@ func SetRValue(rv, val reflect.Value)
func Wrap(rv reflect.Value) Value
func ValueOf(v any) Value

+

-### Structs
+
+### Struct Utils

Package github.com/gookit/goutil/structs

+Package structs Provide some extends util functions for struct. eg: tag parse, struct init, value set/get
+
+

Click to see functions 👈
+

// source at structs/alias.go
func NewAliases(checker func(alias string)) *Aliases
@@ -1142,11 +1231,15 @@ func WithBeforeSetFn(fn BeforeSetFunc) SetOptFunc
func BindData(ptr any, data map[string]any, optFns ...SetOptFunc) error
func SetValues(ptr any, data map[string]any, optFns ...SetOptFunc) error

+

-### Strings
+
+### String Utils

Package github.com/gookit/goutil/strutil

+

Click to see functions 👈
+

// source at strutil/bytes.go
func NewBuffer(initSize ...int) *Buffer
@@ -1154,16 +1247,21 @@ func NewByteChanPool(maxSize, width, capWidth int) *ByteChanPool
// source at strutil/check.go
func IsNumChar(c byte) bool
func IsInt(s string) bool
+func IsUint(s string) bool
func IsFloat(s string) bool
func IsNumeric(s string) bool
+func IsPositiveNum(s string) bool
func IsAlphabet(char uint8) bool
func IsAlphaNum(c uint8) bool
+func IsUpper(s string) bool
+func IsLower(s string) bool
func StrPos(s, sub string) int
func BytePos(s string, bt byte) int
func IEqual(s1, s2 string) bool
func NoCaseEq(s, t string) bool
func IContains(s, sub string) bool
func ContainsByte(s string, c byte) bool
+func ContainsByteOne(s string, bs []byte) bool
func ContainsOne(s string, subs []string) bool
func HasOneSub(s string, subs []string) bool
func IContainsOne(s string, subs []string) bool
@@ -1188,6 +1286,7 @@ func HasEmpty(ss ...string) bool
func IsAllEmpty(ss ...string) bool
func IsVersion(s string) bool
func IsVarName(s string) bool
+func IsEnvName(s string) bool
func Compare(s1, s2, op string) bool
func VersionCompare(v1, v2, op string) bool
func SimpleMatch(s string, keywords []string) bool
@@ -1199,7 +1298,9 @@ func MatchNodePath(pattern, s string, sep string) bool
// source at strutil/convbase.go
func Base10Conv(src string, to int) string
func BaseConv(src string, from, to int) string
+func BaseConvInt(src uint64, to int) string
func BaseConvByTpl(src string, fromBase, toBase string) string
+func BaseConvIntByTpl(dec uint64, toBase string) string
// source at strutil/convert.go
func Quote(s string) string
func Unquote(s string) string
@@ -1259,7 +1360,6 @@ func ToArray(s string, sep ...string) []string
func Strings(s string, sep ...string) []string
func ToStrings(s string, sep ...string) []string
func ToSlice(s string, sep ...string) []string
-func ToOSArgs(s string) []string
func ToDuration(s string) (time.Duration, error)
// source at strutil/encode.go
func EscapeJS(s string) string
@@ -1301,6 +1401,10 @@ func Camel(s string, sep ...string) string
func CamelCase(s string, sep ...string) string
func Indent(s, prefix string) string
func IndentBytes(b, prefix []byte) []byte
+func Replaces(str string, pairs map[string]string) string
+func ReplaceVars(s string, vars map[string]string) string
+func NewReplacer(pairs map[string]string) *strings.Replacer
+func WrapTag(s, tag string) string
// source at strutil/gensn.go
func MicroTimeID() string
func MicroTimeHexID() string
@@ -1309,7 +1413,8 @@ func MTimeBase36() string
func MTimeBaseID(toBase int) string
func DatetimeNo(prefix string) string
func DateSN(prefix string) string
-func DateSNV2(prefix string, extBase ...int) string
+func DateSNv2(prefix string, extBase ...int) string
+func DateSNv3(prefix string, dateLen int, extBase ...int) string
// source at strutil/hash.go
func Md5(src any) string
func MD5(src any) string
@@ -1337,6 +1442,7 @@ func RepeatRune(char rune, times int) []rune
func RepeatBytes(char byte, times int) []byte
func RepeatChars[T byte | rune](char T, times int) []T
// source at strutil/parse.go
+func NumVersion(s string) string
func MustToTime(s string, layouts ...string) time.Time
func ToTime(s string, layouts ...string) (t time.Time, err error)
func ParseSizeRange(expr string, opt *ParseSizeOpt) (min, max uint64, err error)
@@ -1400,31 +1506,17 @@ func OrElse(s, orVal string) string
func OrElseNilSafe(s *string, orVal string) string
func OrHandle(s string, fn comdef.StringHandleFunc) string
func Valid(ss ...string) string
-func Replaces(str string, pairs map[string]string) string
-func NewReplacer(pairs map[string]string) *strings.Replacer
-func WrapTag(s, tag string) string
func SubstrCount(s, substr string, params ...uint64) (int, error)

+

-### Syncs

-> Package github.com/gookit/goutil/syncs

-go -// source at syncs/chan.go -func Go(f func() error) error -// source at syncs/group.go -func NewCtxErrGroup(ctx context.Context, limit ...int) (*ErrGroup, context.Context) -func NewErrGroup(limit ...int) *ErrGroup -// source at syncs/signal.go -func WaitCloseSignals(onClose func(sig os.Signal), sigCh ...chan os.Signal) -func SignalHandler(ctx context.Context, signals ...os.Signal) (execute func() error, interrupt func(error)) -

System Utils

Package github.com/gookit/goutil/sysutil

+

Click to see functions 👈
+

// source at sysutil/exec.go
func NewCmd(bin string, args ...string) *cmdr.Cmd
@@ -1475,6 +1567,13 @@ func OpenURL(URL string) error
// source at sysutil/sysutil_nonwin.go
func Kill(pid int, signal syscall.Signal) error
func ProcessExists(pid int) bool
+// source at sysutil/sysutil_unix.go
+func IsWin() bool
+func IsWindows() bool
+func IsMac() bool
+func IsDarwin() bool
+func IsLinux() bool
+func OpenURL(URL string) error
// source at sysutil/user.go
func MustFindUser(uname string) *user.User
func LoginUser() *user.User
@@ -1493,24 +1592,29 @@ func ChangeUserByName(newUname string) error
func ChangeUserUidGid(newUID int, newGid int) error
func ChangeUserUIDGid(newUID int, newGid int) (err error)

+


+

Testing Utils

Package github.com/gookit/goutil/testutil

+

Click to see functions 👈
+

// source at testutil/buffer.go
func NewBuffer() *byteutil.Buffer
+func NewSafeBuffer() *SafeBuffer
// source at testutil/envmock.go
func MockEnvValue(key, val string, fn func(nv string))
func MockEnvValues(kvMap map[string]string, fn func())
func MockOsEnvByText(envText string, fn func())
-func MockOsEnv(mp map[string]string, fn func())
func SetOsEnvs(mp map[string]string) string
func RemoveTmpEnvs(tmpKey string)
func ClearOSEnv()
func RevertOSEnv()
func RunOnCleanEnv(runFn func())
+func MockOsEnv(mp map[string]string, fn func())
func MockCleanOsEnv(mp map[string]string, fn func())
// source at testutil/httpmock.go
func NewHTTPRequest(method, path string, data *MD) *http.Request
@@ -1535,12 +1639,17 @@ func RestoreTimeLocal()
func NewTestWriter() *TestWriter
func NewDirEnt(fPath string, isDir ...bool) *fakeobj.DirEntry

+


+

Timex

Package github.com/gookit/goutil/timex

-Provides an enhanced time.Time implementation, and add more commonly used functional methods.
+Provides an enhanced time.Time implementation, and add more commonly used functional methods.
+
+

Click to see functions 👈
+

// source at timex/check.go
func IsDuration(s string) bool
@@ -1548,12 +1657,14 @@ func InRange(dst, start, end time.Time) bool
// source at timex/conv.go
func Elapsed(start, end time.Time) string
func ElapsedNow(start time.Time) string
+func FormatDuration(d time.Duration) string
func FromNow(t time.Time) string
func FromNowWith(u time.Time, tms []TimeMessage) string
func HowLongAgo(diffSec int64) string
func HowLongAgo2(diffSec int64, tms []TimeMessage) string
func ToTime(s string, layouts ...string) (time.Time, error)
func ToDur(s string) (time.Duration, error)
+func ParseDuration(s string) (time.Duration, error)
func ToDuration(s string) (time.Duration, error)
func TryToTime(s string, bt time.Time) (time.Time, error)
func ParseRange(expr string, opt *ParseRangeOpt) (start, end time.Time, err error)
@@ -1602,6 +1713,8 @@ func FormatUnix(sec int64, layout ...string) string
func FormatUnixBy(sec int64, layout string) string
func FormatUnixByTpl(sec int64, template ...string) string

+


+

Timex Usage

Create timex instance
@@ -1721,6 +1834,7 @@ date := FormatUnixByTpl(ts, "Y-m-d H:I:S") // Get: 2022-04-20 19:40:34



+
## Code Check & Testing

```bash
diff --git a/vendor/github.com/gookit/goutil/arrutil/convert.go b/vendor/github.com/gookit/goutil/arrutil/convert.go
index 9b7fe30f09b..a505e14fe19 100644
--- a/vendor/github.com/gookit/goutil/arrutil/convert.go
+++ b/vendor/github.com/gookit/goutil/arrutil/convert.go
@@ -125,6 +125,27 @@ func SliceToInt64s(arr []any) []int64 {
	return i64s
}

+// ToMap convert a list to new map.
+//
+// Example:
+//  type User struct {
+//		Name string
+//		Age  int
+//	}
+//	users := []User{{"Tom", 18}, {"Jack", 20}}
+//	mp := arrutil.ToMap(users, func(u User) (string, int) {
+//		return u.Name, u.Age
+//	})
+//  // mp = map[string]int{"Tom":18, "Jack":20}
+func ToMap[T any, K comdef.ScalarType, V any](list []T, mapFn func(T) (K, V)) map[K]V {
+	mp := make(map[K]V, len(list))
+	for _, item := range list {
+		k, v := mapFn(item)
+		mp[k] = v
+	}
+	return mp
+}
+
/*************************************************************
 * convert func for any-slice
 *************************************************************/
diff --git a/vendor/github.com/gookit/goutil/arrutil/process.go b/vendor/github.com/gookit/goutil/arrutil/process.go
index dc72c9df65e..0bbb8532fa8 100644
--- a/vendor/github.com/gookit/goutil/arrutil/process.go
+++ b/vendor/github.com/gookit/goutil/arrutil/process.go
@@ -38,6 +38,9 @@ func Filter[T any](ls []T, filter ...comdef.MatchFunc[T]) []T {
		fn = filter[0]
	} else {
		fn = func(el T) bool {
+			// if el == nil { // Filter nil value
+			// 	return false
+			// }
			return !reflect.ValueOf(el).IsZero()
		}
	}
@@ -57,7 +60,7 @@ type MapFn[T any, V any] func(input T) (target V, find bool)
// Map a list to new list
//
// eg: mapping [object0{},object1{},...] to flatten list [object0.someKey, object1.someKey, ...]
-func Map[T any, V any](list []T, mapFn MapFn[T, V]) []V {
+func Map[T, V any](list []T, mapFn MapFn[T, V]) []V {
	flatArr := make([]V, 0, len(list))

	for _, obj := range list {
@@ -68,6 +71,16 @@ func Map[T any, V any](list []T, mapFn MapFn[T, V]) []V {
	return flatArr
}

+// Map1 a list to new list, alias of Map func
+func Map1[T, R any](list []T, fn func(t T) R) []R {
+	ret := make([]R, len(list))
+
+	for i := range list {
+		ret[i] = fn(list[i])
+	}
+	return ret
+}
+
// Column alias of Map func
func Column[T any, V any](list []T, mapFn func(obj T) (val V, find bool)) []V {
	return Map(list, mapFn)
diff --git a/vendor/github.com/gookit/goutil/byteutil/buffer.go b/vendor/github.com/gookit/goutil/byteutil/buffer.go
index 6a833627cd3..f8690cede57 100644
--- a/vendor/github.com/gookit/goutil/byteutil/buffer.go
+++ b/vendor/github.com/gookit/goutil/byteutil/buffer.go
@@ -16,9 +16,7 @@ type Buffer struct {
}

// NewBuffer instance
-func NewBuffer() *Buffer {
-	return &Buffer{}
-}
+func NewBuffer() *Buffer { return &Buffer{} }

// PrintByte to buffer, ignore error. alias of WriteByte()
func (b *Buffer) PrintByte(c byte) {
@@ -26,14 +24,10 @@ func (b *Buffer) PrintByte(c byte) {
}

// WriteStr1 quiet write one string to buffer
-func (b *Buffer) WriteStr1(s string) {
-	b.writeStringNl(s, false)
-}
+func (b *Buffer) WriteStr1(s string) { b.writeStringNl(s, false) }

// WriteStr1Nl quiet write one string and end with newline
-func (b *Buffer) WriteStr1Nl(s string) {
-	b.writeStringNl(s, true)
-}
+func (b *Buffer) WriteStr1Nl(s string) { b.writeStringNl(s, true) }

// writeStringNl quiet write one string and end with newline
func (b *Buffer) writeStringNl(s string, nl bool) {
@@ -93,6 +87,9 @@ func (b *Buffer) writeAnysWithNl(vs []any, nl bool) {
	}
}

+// Writef write message to buffer, ignore error. alias of Printf()
+func (b *Buffer) Writef(tpl string, vs ...any) { _, _ = fmt.Fprintf(b, tpl, vs...) }
+
// Printf quick write message to buffer, ignore error.
func (b *Buffer) Printf(tpl string, vs ...any) { _, _ = fmt.Fprintf(b, tpl, vs...) }

@@ -112,16 +109,10 @@ func (b *Buffer) ResetAndGet() string {
}

// Close buffer
-func (b *Buffer) Close() error {
-	return b.CloseErr
-}
+func (b *Buffer) Close() error { return b.CloseErr }

// Flush buffer
-func (b *Buffer) Flush() error {
-	return b.FlushErr
-}
+func (b *Buffer) Flush() error { return b.FlushErr }

// Sync anf flush buffer
-func (b *Buffer) Sync() error {
-	return b.SyncErr
-}
+func (b *Buffer) Sync() error { return b.SyncErr }
diff --git a/vendor/github.com/gookit/goutil/byteutil/check.go b/vendor/github.com/gookit/goutil/byteutil/check.go
index f4d2e5ba607..cab9c7a8693 100644
--- a/vendor/github.com/gookit/goutil/byteutil/check.go
+++ b/vendor/github.com/gookit/goutil/byteutil/check.go
@@ -7,4 +7,3 @@ func IsNumChar(c byte) bool { return c >= '0' && c <= '9' }
func IsAlphaChar(c byte) bool {
	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
}
-
diff --git a/vendor/github.com/gookit/goutil/conv.go b/vendor/github.com/gookit/goutil/conv.go
index f9e8047a0b2..20eff91cba1 100644
--- a/vendor/github.com/gookit/goutil/conv.go
+++ b/vendor/github.com/gookit/goutil/conv.go
@@ -122,7 +122,7 @@ func ConvOrDefault(val any, kind reflect.Kind, defVal any) any {
//
// Examples:
//
-//		val, err := ToKind("123", reflect.Int) // 123
+//	val, err := ToKind("123", reflect.Int) // 123
func ToKind(val any, kind reflect.Kind, fbFunc func(val any) (any, error)) (newVal any, err error) {
	switch kind {
	case reflect.Int:
diff --git a/vendor/github.com/gookit/goutil/envutil/info.go b/vendor/github.com/gookit/goutil/envutil/info.go
index b18cb448553..9ff250b648c 100644
--- a/vendor/github.com/gookit/goutil/envutil/info.go
+++ b/vendor/github.com/gookit/goutil/envutil/info.go
@@ -36,7 +36,6 @@ func IsMSys() bool {
	return sysutil.IsMSys()
}

-
// IsTerminal isatty check
//
// Usage:
diff --git a/vendor/github.com/gookit/goutil/envutil/set.go b/vendor/github.com/gookit/goutil/envutil/set.go
index b317155f542..8c7fa6b570a 100644
--- a/vendor/github.com/gookit/goutil/envutil/set.go
+++ b/vendor/github.com/gookit/goutil/envutil/set.go
@@ -34,7 +34,8 @@ func UnsetEnvs(keys ...string) {
// LoadText parse multiline text to ENV. Can use to load .env file contents.
//
// Usage:
-// 	envutil.LoadText(fsutil.ReadFile(".env"))
+//
+//	envutil.LoadText(fsutil.ReadFile(".env"))
func LoadText(text string) {
	envMp := SplitText2map(text)
	for key, value := range envMp {
diff --git a/vendor/github.com/gookit/goutil/fsutil/check.go b/vendor/github.com/gookit/goutil/fsutil/check.go
index a015d40b02b..337a10e8085 100644
--- a/vendor/github.com/gookit/goutil/fsutil/check.go
+++ b/vendor/github.com/gookit/goutil/fsutil/check.go
@@ -61,6 +61,8 @@ func FileExists(path string) bool {
}

// IsFile reports whether the named file or directory exists.
+//
+// - NOTE: not support symlink file
func IsFile(path string) bool {
	if path == "" || len(path) > 468 {
		return false
@@ -72,6 +74,15 @@ func IsFile(path string) bool {
	return false
}

+// IsSymlink reports whether the named file is a symlink.
+func IsSymlink(path string) bool {
+	fi, err := os.Lstat(path)
+	if err != nil {
+		return false
+	}
+	return fi.Mode()&os.ModeSymlink != 0
+}
+
// IsAbsPath is abs path.
func IsAbsPath(aPath string) bool {
	if len(aPath) > 0 {
diff --git a/vendor/github.com/gookit/goutil/fsutil/find.go b/vendor/github.com/gookit/goutil/fsutil/find.go
index 4dadc430722..5eea9f78083 100644
--- a/vendor/github.com/gookit/goutil/fsutil/find.go
+++ b/vendor/github.com/gookit/goutil/fsutil/find.go
@@ -23,7 +23,7 @@ func FilePathInDirs(fPath string, dirs ...string) string {
	}

	for _, dirPath := range dirs {
-		fPath := JoinSubPaths(dirPath, fPath)
+		fPath = JoinSubPaths(dirPath, fPath)
		if FileExists(fPath) {
			return fPath
		}
@@ -67,6 +67,103 @@ func MatchFirst(paths []string, matcher PathMatchFunc, defaultPath string) strin
	return defaultPath
}

+// FindParentOption options
+type FindParentOption struct {
+	MaxLevel int // default: 10
+	// NeedDir true: find dirs; false(default): find files
+	NeedDir bool
+	OnlyOne bool // only find one, default: true
+	// Collector func
+	Collector func(fullPath string)
+	// MatchFunc custom matcher func. return false to stop find.
+	MatchFunc func(currentDir string) bool
+}
+
+// FindParentOptFn find parent option func
+type FindParentOptFn func(opt *FindParentOption)
+
+// FindAllInParentDirs looks for all match file(default)/dir in the current directory and parent directories
+func FindAllInParentDirs(dirPath, name string, optFns ...FindParentOptFn) []string {
+	var foundPaths []string
+	optFns = append(optFns, func(opt *FindParentOption) {
+		opt.OnlyOne = false
+	})
+
+	FindNameInParentDirs(dirPath, name, func(fullPath string) {
+		foundPaths = append(foundPaths, fullPath)
+	}, optFns...)
+	return foundPaths
+}
+
+// FindOneInParentDirs looks for a file(default)/dir in the current directory and parent directories
+func FindOneInParentDirs(dirPath, name string, optFns ...FindParentOptFn) string {
+	var foundPath string
+	FindNameInParentDirs(dirPath, name, func(fullPath string) {
+		foundPath = fullPath
+	}, optFns...)
+	return foundPath
+}
+
+// FindNameInParentDirs looks for file(default)/dir in the current directory and parent directories
+func FindNameInParentDirs(dirPath, name string, collectFn func(fullPath string), optFns ...FindParentOptFn) {
+	opts := &FindParentOption{
+		MaxLevel:  10,
+		OnlyOne:   true,
+		Collector: collectFn,
+	}
+	for _, fn := range optFns {
+		fn(opts)
+	}
+
+	FindInParentDirs(dirPath, func(currentDir string) bool {
+		filePath := filepath.Join(currentDir, name)
+		if fi, err := os.Stat(filePath); err == nil {
+			found := false
+			if fi.IsDir() {
+				found = opts.NeedDir
+			} else {
+				found = !opts.NeedDir
+			}
+
+			if found {
+				opts.Collector(filePath)
+				return !opts.OnlyOne
+			}
+		}
+		return true
+	}, opts.MaxLevel)
+}
+
+// FindInParentDirs looks for file/dir in the current directory and parent directories
+//  - MatchFunc custom matcher func. return false to stop find.
+func FindInParentDirs(dirPath string, matchFunc func(dir string) bool, maxLevel int) {
+	currentLv := 1
+	currentDir := ToAbsPath(dirPath)
+
+	for {
+		// Check if the file exists in the current directory
+		if !matchFunc(currentDir) {
+			return
+		}
+
+		// check find level
+		if maxLevel > 0 && currentLv > maxLevel {
+			break
+		}
+
+		// Get parent directory
+		parentDir := filepath.Dir(currentDir)
+		if parentDir == currentDir {
+			// Reached the root, file not found
+			return
+		}
+
+		// Move to parent directory
+		currentLv++
+		currentDir = parentDir
+	}
+}
+
// SearchNameUp find file/dir name in dirPath or parent dirs,
// return the name of directory path
//
@@ -158,14 +255,10 @@ type (
)

// OnlyFindDir on find
-func OnlyFindDir(_ string, ent fs.DirEntry) bool {
-	return ent.IsDir()
-}
+func OnlyFindDir(_ string, ent fs.DirEntry) bool { return ent.IsDir() }

// OnlyFindFile on find
-func OnlyFindFile(_ string, ent fs.DirEntry) bool {
-	return !ent.IsDir()
-}
+func OnlyFindFile(_ string, ent fs.DirEntry) bool { return !ent.IsDir() }

// ExcludeNames on find
func ExcludeNames(names ...string) FilterFunc {
@@ -182,9 +275,7 @@ func IncludeSuffix(ss ...string) FilterFunc {
}

// ExcludeDotFile on find
-func ExcludeDotFile(_ string, ent fs.DirEntry) bool {
-	return ent.Name()[0] != '.'
-}
+func ExcludeDotFile(_ string, ent fs.DirEntry) bool { return ent.Name()[0] != '.' }

// ExcludeSuffix on find
func ExcludeSuffix(ss ...string) FilterFunc {
@@ -205,7 +296,7 @@ func ApplyFilters(fPath string, ent fs.DirEntry, filters []FilterFunc) bool {

// FindInDir code refer the go pkg: path/filepath.glob()
//
-// - TIP: will be not found in sub-dir.
+// - TIP: default will be not found in sub-dir.
//
// filters: return false will skip the file.
func FindInDir(dir string, handleFn HandleFunc, filters ...FilterFunc) (e error) {
diff --git a/vendor/github.com/gookit/goutil/fsutil/info.go b/vendor/github.com/gookit/goutil/fsutil/info.go
index c843bc792ab..94b45cc7981 100644
--- a/vendor/github.com/gookit/goutil/fsutil/info.go
+++ b/vendor/github.com/gookit/goutil/fsutil/info.go
@@ -9,12 +9,15 @@ import (
)

// DirPath get dir path from filepath, without a last name.
+//  eg: "/foo/bar/baz.js" => "/foo/bar"
func DirPath(fPath string) string { return filepath.Dir(fPath) }

// Dir get dir path from filepath, without a last name.
+//  eg: "/foo/bar/baz.js" => "/foo/bar"
func Dir(fPath string) string { return filepath.Dir(fPath) }

-// PathName get file/dir name from a full path
+// PathName get file/dir name from a full path.
+//  eg: "/foo/bar/baz.js" => "baz.js"
func PathName(fPath string) string { return filepath.Base(fPath) }

// PathNoExt get path from full path, without ext.
@@ -30,7 +33,9 @@ func PathNoExt(fPath string) string {

// Name get file/dir name from full path.
//
-// eg: path/to/main.go => "main.go"
+// eg:
+//  "path/to/main.go" => "main.go"
+//  "/foo/bar/baz" => "baz"
func Name(fPath string) string {
	if fPath == "" {
		return ""
@@ -74,16 +79,15 @@ func Extname(fPath string) string {
func Suffix(fPath string) string { return filepath.Ext(fPath) }

// Expand will parse first `~` to user home dir path.
-func Expand(pathStr string) string {
-	return comfunc.ExpandHome(pathStr)
-}
+func Expand(pathStr string) string { return comfunc.ExpandHome(pathStr) }
+
+// ExpandHome will parse first `~` to user home dir path.
+func ExpandHome(pathStr string) string { return comfunc.ExpandHome(pathStr) }

// ExpandPath will parse `~` to user home dir path.
-func ExpandPath(pathStr string) string {
-	return comfunc.ExpandHome(pathStr)
-}
+func ExpandPath(pathStr string) string { return comfunc.ExpandHome(pathStr) }

-// ResolvePath will parse `~` and env var in path
+// ResolvePath will parse `~` and ENV var in path
func ResolvePath(pathStr string) string {
	pathStr = comfunc.ExpandHome(pathStr)
	// return comfunc.ParseEnvVar()
@@ -91,6 +95,18 @@ func ResolvePath(pathStr string) string {
}

// SplitPath splits path immediately following the final Separator, separating it into a directory and file name component
-func SplitPath(pathStr string) (dir, name string) {
-	return filepath.Split(pathStr)
+func SplitPath(pathStr string) (dir, name string) { return filepath.Split(pathStr) }
+
+// homeDir cache
+var _homeDir string
+
+// UserHomeDir is alias of os.UserHomeDir, but ignore error.(by os.UserHomeDir)
+func UserHomeDir() string {
+	if _homeDir == "" {
+		_homeDir, _ = os.UserHomeDir()
+	}
+	return _homeDir
}
+
+// HomeDir get user home dir path.
+func HomeDir() string { return UserHomeDir() }
diff --git a/vendor/github.com/gookit/goutil/fsutil/operate.go b/vendor/github.com/gookit/goutil/fsutil/operate.go
index 1d68e4c5377..59bd4d98589 100644
--- a/vendor/github.com/gookit/goutil/fsutil/operate.go
+++ b/vendor/github.com/gookit/goutil/fsutil/operate.go
@@ -13,12 +13,21 @@ import (
)

// Mkdir alias of os.MkdirAll()
-func Mkdir(dirPath string, perm os.FileMode) error {
-	return os.MkdirAll(dirPath, perm)
+func Mkdir(dirPath string, perm fs.FileMode) error { return os.MkdirAll(dirPath, perm) }
+
+// MkdirQuick with default permission 0755.
+func MkdirQuick(dirPath string) error { return EnsureDir(dirPath) }
+
+// EnsureDir creates a directory if it doesn't exist
+func EnsureDir(path string) error {
+	if !DirExist(path) {
+		return os.MkdirAll(path, 0755)
+	}
+	return nil
}

// MkDirs batch makes multi dirs at once
-func MkDirs(perm os.FileMode, dirPaths ...string) error {
+func MkDirs(perm fs.FileMode, dirPaths ...string) error {
	for _, dirPath := range dirPaths {
		if err := os.MkdirAll(dirPath, perm); err != nil {
			return err
@@ -28,7 +37,7 @@ func MkDirs(perm os.FileMode, dirPaths ...string) error {
}

// MkSubDirs batch makes multi sub-dirs at once
-func MkSubDirs(perm os.FileMode, parentDir string, subDirs ...string) error {
+func MkSubDirs(perm fs.FileMode, parentDir string, subDirs ...string) error {
	for _, dirName := range subDirs {
		dirPath := parentDir + "/" + dirName
		if err := os.MkdirAll(dirPath, perm); err != nil {
diff --git a/vendor/github.com/gookit/goutil/fsutil/opwrite.go b/vendor/github.com/gookit/goutil/fsutil/opwrite.go
index 305d8ce8b13..0431ca9718c 100644
--- a/vendor/github.com/gookit/goutil/fsutil/opwrite.go
+++ b/vendor/github.com/gookit/goutil/fsutil/opwrite.go
@@ -1,6 +1,7 @@
package fsutil

import (
+	"fmt"
	"io"
	"os"

@@ -185,3 +186,16 @@ func UpdateContents(filePath string, handleFn func(bs []byte) []byte) error {
	}
	return err
}
+
+// CreateSymlink creates a symbolic link
+func CreateSymlink(target, linkPath string) error {
+	// Check if the link already exists
+	if IsFile(linkPath) {
+		// Remove existing link/file
+		if err := os.Remove(linkPath); err != nil {
+			return fmt.Errorf("failed to remove existing symlink: %w", err)
+		}
+	}
+
+	return os.Symlink(target, linkPath)
+}
diff --git a/vendor/github.com/gookit/goutil/goutil.go b/vendor/github.com/gookit/goutil/goutil.go
index c0e92e6a574..33713b85b61 100644
--- a/vendor/github.com/gookit/goutil/goutil.go
+++ b/vendor/github.com/gookit/goutil/goutil.go
@@ -206,4 +206,3 @@ func FuncName(f any) string {
func PkgName(funcName string) string {
	return goinfo.PkgName(funcName)
}
-
diff --git a/vendor/github.com/gookit/goutil/internal/checkfn/check.go b/vendor/github.com/gookit/goutil/internal/checkfn/check.go
index e85f2315431..81eaee37ce3 100644
--- a/vendor/github.com/gookit/goutil/internal/checkfn/check.go
+++ b/vendor/github.com/gookit/goutil/internal/checkfn/check.go
@@ -118,11 +118,31 @@ func StringsContains(ss []string, s string) bool {
	return false
}

-// check is number: int or float
-var numReg = regexp.MustCompile(`^[-+]?\d*\.?\d+$`)
+var (
+	// check is number: int or float
+	numReg = regexp.MustCompile(`^[-+]?\d*\.?\d+$`)
+	// is positive number: int or float
+	pNumReg = regexp.MustCompile(`^\d*\.?\d+$`)
+)

// IsNumeric returns true if the given string is a numeric, otherwise false.
-func IsNumeric(s string) bool { return numReg.MatchString(s) }
+func IsNumeric(s string) bool {
+	if s == "" {
+		return false
+	}
+	return numReg.MatchString(s)
+}
+
+// IsPositiveNum check input string is positive number
+func IsPositiveNum(s string) bool {
+	if s == "" {
+		return false
+	}
+	if s[0] == '-' {
+		return false
+	}
+	return pNumReg.MatchString(s)
+}

// IsHttpURL check input is http/https url
func IsHttpURL(s string) bool {
diff --git a/vendor/github.com/gookit/goutil/internal/comfunc/convert.go b/vendor/github.com/gookit/goutil/internal/comfunc/convert.go
index 3d4f3b278ef..9e12be8377c 100644
--- a/vendor/github.com/gookit/goutil/internal/comfunc/convert.go
+++ b/vendor/github.com/gookit/goutil/internal/comfunc/convert.go
@@ -43,6 +43,10 @@ func StrToBool(s string) (bool, error) {
}

// FormatWithArgs format message with args
+//
+//  - only one element, format to string
+//  - first is format: fmt.Sprintf(firstElem, fmtAndArgs[1:]...)
+//  - all is args: return fmt.Sprint(fmtAndArgs...)
func FormatWithArgs(fmtAndArgs []any) string {
	ln := len(fmtAndArgs)
	if ln == 0 {
@@ -50,16 +54,15 @@ func FormatWithArgs(fmtAndArgs []any) string {
	}

	first := fmtAndArgs[0]
-
	if ln == 1 {
-		if msgAsStr, ok := first.(string); ok {
-			return msgAsStr
+		if str, ok := first.(string); ok {
+			return str
		}
		return fmt.Sprintf("%+v", first)
	}

	// is template string.
-	if tplStr, ok := first.(string); ok {
+	if tplStr, ok := first.(string); ok && strings.IndexByte(tplStr, '%') >= 0 {
		return fmt.Sprintf(tplStr, fmtAndArgs[1:]...)
	}
	return fmt.Sprint(fmtAndArgs...)
@@ -86,11 +89,6 @@ var StrBySprintFn = func(v any) (string, error) {
	return fmt.Sprint(v), nil
}

-// WithHandlePtr set ConvOption.HandlePtr option
-func WithHandlePtr(opt *ConvOption) {
-	opt.HandlePtr = true
-}
-
// WithUserConvFn set ConvOption.UserConvFn option
func WithUserConvFn(fn comdef.ToStringFunc) ConvOptionFn {
	return func(opt *ConvOption) {
@@ -116,11 +114,6 @@ func (opt *ConvOption) WithOption(optFns ...ConvOptionFn) {

// ToStringWith try to convert value to string. can with some option func, more see ConvOption.
func ToStringWith(in any, optFns ...ConvOptionFn) (str string, err error) {
-	opt := NewConvOption(optFns...)
-	if !opt.NilAsFail && in == nil {
-		return "", nil
-	}
-
	switch value := in.(type) {
	case int:
		str = strconv.Itoa(value)
@@ -161,6 +154,18 @@ func ToStringWith(in any, optFns ...ConvOptionFn) (str string, err error) {
	case error:
		str = value.Error()
	default:
+		if len(optFns) == 0 && in == nil {
+			return "", nil
+		}
+
+		opt := NewConvOption(optFns...)
+		if in == nil {
+			if opt.NilAsFail {
+				err = comdef.ErrConvType
+			}
+			return
+		}
+
		if opt.HandlePtr {
			if rv := reflect.ValueOf(in); rv.Kind() == reflect.Pointer {
				rv = rv.Elem()
diff --git a/vendor/github.com/gookit/goutil/internal/comfunc/sysfunc.go b/vendor/github.com/gookit/goutil/internal/comfunc/sysfunc.go
index 4f43d3ad132..d3f6224be25 100644
--- a/vendor/github.com/gookit/goutil/internal/comfunc/sysfunc.go
+++ b/vendor/github.com/gookit/goutil/internal/comfunc/sysfunc.go
@@ -87,19 +87,24 @@ func CurrentShell(onlyName bool, fallbackShell ...string) (binPath string) {
		// 检查父进程名称
		parentProcess := os.Getenv("GOPROCESS")
		if parentProcess != "" {
-			return parentProcess
+			binPath = parentProcess
+		} else {
+			binPath = os.Getenv("SHELL") // 适用于 Unix-like 系统
+			if len(binPath) == 0 {
+				// TODO check on Windows git bash
+				binPath, err = ShellExec("echo $SHELL")
+				if err != nil {
+					binPath = fbShell
+				}
+			}
+			binPath = strings.TrimSpace(binPath)
		}

-		binPath = os.Getenv("SHELL") // 适用于 Unix-like 系统
-		if len(binPath) == 0 {
-			// TODO check on Windows
-			binPath, err = ShellExec("echo $SHELL")
-			if err != nil {
-				return fbShell
-			}
+		// fix: 去除 .exe 后缀
+		if pos := strings.IndexByte(binPath, '.'); pos > 0 {
+			binPath = binPath[:pos]
		}

-		binPath = strings.TrimSpace(binPath)
		// cache result
		curShellCache = binPath
	} else {
diff --git a/vendor/github.com/gookit/goutil/jsonutil/encoding.go b/vendor/github.com/gookit/goutil/jsonutil/encoding.go
index b921a421523..791033f7535 100644
--- a/vendor/github.com/gookit/goutil/jsonutil/encoding.go
+++ b/vendor/github.com/gookit/goutil/jsonutil/encoding.go
@@ -72,4 +72,4 @@ func DecodeFile(file string, ptr any) error {
	}

	return json.Unmarshal(bs, ptr)
-}
\ No newline at end of file
+}
diff --git a/vendor/github.com/gookit/goutil/maputil/alias.go b/vendor/github.com/gookit/goutil/maputil/alias.go
index b8109591177..9f739d22a7e 100644
--- a/vendor/github.com/gookit/goutil/maputil/alias.go
+++ b/vendor/github.com/gookit/goutil/maputil/alias.go
@@ -1,11 +1,15 @@
package maputil

-import "fmt"
+import (
+	"fmt"
+	"sort"
+)

// Aliases implemented a simple string alias map.
+//  - key: alias, value: real name
type Aliases map[string]string

-// AddAlias to the Aliases
+// AddAlias to the Aliases map
func (as Aliases) AddAlias(alias, real string) {
	if rn, ok := as[alias]; ok {
		panic(fmt.Sprintf("The alias '%s' is already used by '%s'", alias, rn))
@@ -13,21 +17,21 @@ func (as Aliases) AddAlias(alias, real string) {
	as[alias] = real
}

-// AddAliases to the Aliases
+// AddAliases to the Aliases map
func (as Aliases) AddAliases(real string, aliases []string) {
	for _, a := range aliases {
		as.AddAlias(a, real)
	}
}

-// AddAliasMap to the Aliases
+// AddAliasMap to the Aliases map
func (as Aliases) AddAliasMap(alias2real map[string]string) {
	for a, r := range alias2real {
		as.AddAlias(a, r)
	}
}

-// HasAlias in the Aliases
+// HasAlias in the Aliases map
func (as Aliases) HasAlias(alias string) bool {
	if _, ok := as[alias]; ok {
		return true
@@ -42,3 +46,24 @@ func (as Aliases) ResolveAlias(alias string) string {
	}
	return alias
}
+
+// AliasesNames returns all sorted alias names.
+func (as Aliases) AliasesNames() []string {
+	ns := make([]string, 0, len(as))
+	for alias := range as {
+		ns = append(ns, alias)
+	}
+	sort.Strings(ns)
+	return ns
+}
+
+// GroupAliases groups aliases by real name.
+//
+// returns: {real name -> []aliases, ...}
+func (as Aliases) GroupAliases() map[string][]string {
+	gaMap := make(map[string][]string)
+	for alias, name := range as {
+		gaMap[name] = append(gaMap[name], alias)
+	}
+	return gaMap
+}
diff --git a/vendor/github.com/gookit/goutil/maputil/convert.go b/vendor/github.com/gookit/goutil/maputil/convert.go
index fd0a17d4ac5..215ba9d4b8a 100644
--- a/vendor/github.com/gookit/goutil/maputil/convert.go
+++ b/vendor/github.com/gookit/goutil/maputil/convert.go
@@ -86,7 +86,7 @@ func CombineToMap[K comdef.SortedType, V any](keys []K, values []V) map[K]V {
}

// SliceToSMap convert string k-v pairs slice to map[string]string
-//  - eg: []string{k1,v1,k2,v2} -> map[string]string{k1:v1, k2:v2}
+//   - eg: []string{k1,v1,k2,v2} -> map[string]string{k1:v1, k2:v2}
func SliceToSMap(kvPairs ...string) map[string]string {
	ln := len(kvPairs)
	// check kvPairs length must be even
diff --git a/vendor/github.com/gookit/goutil/maputil/data.go b/vendor/github.com/gookit/goutil/maputil/data.go
index 71e227ad997..5eb89cfbc78 100644
--- a/vendor/github.com/gookit/goutil/maputil/data.go
+++ b/vendor/github.com/gookit/goutil/maputil/data.go
@@ -9,12 +9,12 @@ import (
	"github.com/gookit/goutil/strutil"
)

-// Data an map data type
-type Data map[string]any
-
// Map alias of Data
type Map = Data

+// Data alias of map[string]any
+type Data map[string]any
+
// Has value on the data map
func (d Data) Has(key string) bool {
	_, ok := d.GetByPath(key)
diff --git a/vendor/github.com/gookit/goutil/maputil/maputil.go b/vendor/github.com/gookit/goutil/maputil/maputil.go
index 8acd64d409f..6aaf2584da5 100644
--- a/vendor/github.com/gookit/goutil/maputil/maputil.go
+++ b/vendor/github.com/gookit/goutil/maputil/maputil.go
@@ -63,6 +63,11 @@ func MergeStrMap(src, dst map[string]string) map[string]string {
	return MergeStringMap(src, dst, false)
}

+// AppendSMap append string map data to dst map.
+func AppendSMap(dst, src map[string]string) map[string]string {
+	return MergeStringMap(src, dst, false)
+}
+
// MergeStringMap simple merge two string map. merge src to dst map
func MergeStringMap(src, dst map[string]string, ignoreCase bool) map[string]string {
	if len(src) == 0 {
diff --git a/vendor/github.com/gookit/goutil/maputil/smap.go b/vendor/github.com/gookit/goutil/maputil/smap.go
index 6fc767a64ce..63dc2d0fea0 100644
--- a/vendor/github.com/gookit/goutil/maputil/smap.go
+++ b/vendor/github.com/gookit/goutil/maputil/smap.go
@@ -5,6 +5,8 @@ import (
	"github.com/gookit/goutil/strutil"
)

+// SM is alias of map[string]string
+type SM = StrMap
// SMap and StrMap is alias of map[string]string
type SMap = StrMap
type StrMap map[string]string
diff --git a/vendor/github.com/gookit/goutil/mathutil/check.go b/vendor/github.com/gookit/goutil/mathutil/check.go
index ed1d11957c9..2eda9ebe6dd 100644
--- a/vendor/github.com/gookit/goutil/mathutil/check.go
+++ b/vendor/github.com/gookit/goutil/mathutil/check.go
@@ -3,8 +3,16 @@ package mathutil
import "github.com/gookit/goutil/comdef"

// IsNumeric returns true if the given character is a numeric, otherwise false.
-func IsNumeric(c byte) bool {
-	return c >= '0' && c <= '9'
+func IsNumeric(c byte) bool { return c >= '0' && c <= '9' }
+
+// IsInteger strict check the given value is an integer(intX,uintX), otherwise false.
+func IsInteger(val any) bool {
+	switch val.(type) {
+	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr:
+		return true
+	default:
+		return false
+	}
}

// Compare any intX,floatX value by given op. returns `first op(=,!=,<,<=,>,>=) second`
diff --git a/vendor/github.com/gookit/goutil/mathutil/convert.go b/vendor/github.com/gookit/goutil/mathutil/convert.go
index cbedf90f6bd..edcb49fcc2e 100644
--- a/vendor/github.com/gookit/goutil/mathutil/convert.go
+++ b/vendor/github.com/gookit/goutil/mathutil/convert.go
@@ -1,8 +1,6 @@
package mathutil

import (
-	"fmt"
-	"math"
	"reflect"
	"strconv"
	"strings"
@@ -13,24 +11,6 @@ import (
	"github.com/gookit/goutil/internal/comfunc"
)

-// ToIntFunc convert value to int
-type ToIntFunc func(any) (int, error)
-
-// ToInt64Func convert value to int64
-type ToInt64Func func(any) (int64, error)
-
-// ToUintFunc convert value to uint
-type ToUintFunc func(any) (uint, error)
-
-// ToUint64Func convert value to uint
-type ToUint64Func func(any) (uint64, error)
-
-// ToFloatFunc convert value to float
-type ToFloatFunc func(any) (float64, error)
-
-// ToTypeFunc convert value to defined type
-type ToTypeFunc[T any] func(any) (T, error)
-
// ConvOption convert options
type ConvOption[T any] struct {
	// if ture: value is nil, will return convert error;
@@ -40,6 +20,11 @@ type ConvOption[T any] struct {
	// 	- if true: will use real type try convert. default is false
	//	- NOTE: current T type's ptr is default support.
	HandlePtr bool
+	// StrictMode for convert value. default is false
+	//
+	// TRUE:
+	//  - to int: string, float will return error
+	StrictMode bool
	// set custom fallback convert func for not supported type.
	UserConvFn ToTypeFunc[T]
}
@@ -68,14 +53,13 @@ type ConvOptionFn[T any] func(opt *ConvOption[T])
// Example:
//
//	ToIntWithFunc(val, mathutil.WithNilAsFail[int])
-func WithNilAsFail[T any](opt *ConvOption[T]) {
-	opt.NilAsFail = true
-}
+func WithNilAsFail[T any](opt *ConvOption[T]) { opt.NilAsFail = true }

// WithHandlePtr set ConvOption.HandlePtr option
-func WithHandlePtr[T any](opt *ConvOption[T]) {
-	opt.HandlePtr = true
-}
+func WithHandlePtr[T any](opt *ConvOption[T]) { opt.HandlePtr = true }
+
+// WithStrictMode set ConvOption.StrictMode option
+func WithStrictMode[T any](opt *ConvOption[T]) { opt.StrictMode = true }

// WithUserConvFn set ConvOption.UserConvFn option
func WithUserConvFn[T any](fn ToTypeFunc[T]) ConvOptionFn[T] {
@@ -85,488 +69,71 @@ func WithUserConvFn[T any](fn ToTypeFunc[T]) ConvOptionFn[T] {
}

/*************************************************************
- * convert value to int
+ * region Strict to int/uint
 *************************************************************/

-// Int convert value to int
-func Int(in any) (int, error) { return ToInt(in) }
-
-// SafeInt convert value to int, will ignore error
-func SafeInt(in any) int {
-	val, _ := ToInt(in)
-	return val
-}
-
-// QuietInt convert value to int, will ignore error
-func QuietInt(in any) int { return SafeInt(in) }
-
-// IntOrPanic convert value to int, will panic on error
-func IntOrPanic(in any) int {
-	val, err := ToInt(in)
-	if err != nil {
-		panic(err)
-	}
-	return val
-}
-
-// MustInt convert value to int, will panic on error
-func MustInt(in any) int { return IntOrPanic(in) }
-
-// IntOrDefault convert value to int, return defaultVal on failed
-func IntOrDefault(in any, defVal int) int { return IntOr(in, defVal) }
-
-// IntOr convert value to int, return defaultVal on failed
-func IntOr(in any, defVal int) int {
-	val, err := ToIntWith(in)
-	if err != nil {
-		return defVal
-	}
-	return val
-}
-
-// IntOrErr convert value to int, return error on failed
-func IntOrErr(in any) (int, error) { return ToIntWith(in) }
-
-// ToInt convert value to int, return error on failed
-func ToInt(in any) (int, error) { return ToIntWith(in) }
-
-// ToIntWith convert value to int, can with some option func.
-//
-// Example:
-//
-//	ToIntWithFunc(val, mathutil.WithNilAsFail, mathutil.WithUserConvFn(func(in any) (int, error) {
-//	})
-func ToIntWith(in any, optFns ...ConvOptionFn[int]) (iVal int, err error) {
-	opt := NewConvOption[int](optFns...)
-	if !opt.NilAsFail && in == nil {
-		return 0, nil
-	}
-
-	switch tVal := in.(type) {
+// StrictInt check the given value is an integer(intX,uintX), return the int64 value and true if success
+func StrictInt(val any) (int64, bool) {
+	switch tVal := val.(type) {
	case int:
-		iVal = tVal
-	case *int: // default support int ptr type
-		iVal = *tVal
+		return int64(tVal), true
	case int8:
-		iVal = int(tVal)
+		return int64(tVal), true
	case int16:
-		iVal = int(tVal)
+		return int64(tVal), true
	case int32:
-		iVal = int(tVal)
+		return int64(tVal), true
	case int64:
-		if tVal > math.MaxInt32 {
-			err = fmt.Errorf("value overflow int32. input: %v", tVal)
-		} else {
-			iVal = int(tVal)
-		}
+		return tVal, true
	case uint:
-		if tVal > math.MaxInt32 {
-			err = fmt.Errorf("value overflow int32. input: %v", tVal)
-		} else {
-			iVal = int(tVal)
-		}
+		return int64(tVal), true
	case uint8:
-		iVal = int(tVal)
+		return int64(tVal), true
	case uint16:
-		iVal = int(tVal)
+		return int64(tVal), true
	case uint32:
-		if tVal > math.MaxInt32 {
-			err = fmt.Errorf("value overflow int32. input: %v", tVal)
-		} else {
-			iVal = int(tVal)
-		}
+		return int64(tVal), true
	case uint64:
-		if tVal > math.MaxInt32 {
-			err = fmt.Errorf("value overflow int32. input: %v", tVal)
-		} else {
-			iVal = int(tVal)
-		}
-	case float32:
-		iVal = int(tVal)
-	case float64:
-		iVal = int(tVal)
-	case time.Duration:
-		if tVal > math.MaxInt32 {
-			err = fmt.Errorf("value overflow int32. input: %v", tVal)
-		} else {
-			iVal = int(tVal)
-		}
-	case string:
-		sVal := strings.TrimSpace(tVal)
-		iVal, err = strconv.Atoi(sVal)
-		// handle the case where the string might be a float
-		if err != nil && checkfn.IsNumeric(sVal) {
-			var floatVal float64
-			if floatVal, err = strconv.ParseFloat(sVal, 64); err == nil {
-				iVal = int(math.Round(floatVal))
-				err = nil
-			}
-		}
-	case comdef.Int64able: // eg: json.Number
-		var i64 int64
-		if i64, err = tVal.Int64(); err == nil {
-			if i64 > math.MaxInt32 {
-				err = fmt.Errorf("value overflow int32. input: %v", tVal)
-			} else {
-				iVal = int(i64)
-			}
-		}
+		return int64(tVal), true
+	case uintptr:
+		return int64(tVal), true
	default:
-		if opt.HandlePtr {
-			if rv := reflect.ValueOf(in); rv.Kind() == reflect.Pointer {
-				rv = rv.Elem()
-				if checkfn.IsSimpleKind(rv.Kind()) {
-					return ToIntWith(rv.Interface(), optFns...)
-				}
-			}
-		}
-
-		if opt.UserConvFn != nil {
-			return opt.UserConvFn(in)
-		}
-		err = comdef.ErrConvType
-	}
-	return
-}
-
-// StrInt convert.
-func StrInt(s string) int {
-	iVal, _ := strconv.Atoi(strings.TrimSpace(s))
-	return iVal
-}
-
-// StrIntOr convert string to int, return default val on failed
-func StrIntOr(s string, defVal int) int {
-	iVal, err := strconv.Atoi(strings.TrimSpace(s))
-	if err != nil {
-		return defVal
-	}
-	return iVal
-}
-
-/*************************************************************
- * convert value to int64
- *************************************************************/
-
-// Int64 convert value to int64, return error on failed
-func Int64(in any) (int64, error) { return ToInt64(in) }
-
-// SafeInt64 convert value to int64, will ignore error
-func SafeInt64(in any) int64 {
-	i64, _ := ToInt64With(in)
-	return i64
-}
-
-// QuietInt64 convert value to int64, will ignore error
-func QuietInt64(in any) int64 { return SafeInt64(in) }
-
-// MustInt64 convert value to int64, will panic on error
-func MustInt64(in any) int64 {
-	i64, err := ToInt64With(in)
-	if err != nil {
-		panic(err)
-	}
-	return i64
-}
-
-// Int64OrDefault convert value to int64, return default val on failed
-func Int64OrDefault(in any, defVal int64) int64 { return Int64Or(in, defVal) }
-
-// Int64Or convert value to int64, return default val on failed
-func Int64Or(in any, defVal int64) int64 {
-	i64, err := ToInt64With(in)
-	if err != nil {
-		return defVal
+		return 0, false
	}
-	return i64
}

-// ToInt64 convert value to int64, return error on failed
-func ToInt64(in any) (int64, error) { return ToInt64With(in) }
-
-// Int64OrErr convert value to int64, return error on failed
-func Int64OrErr(in any) (int64, error) { return ToInt64With(in) }
-
-// ToInt64With try to convert value to int64. can with some option func, more see ConvOption.
-func ToInt64With(in any, optFns ...ConvOptionFn[int64]) (i64 int64, err error) {
-	opt := NewConvOption(optFns...)
-	if !opt.NilAsFail && in == nil {
-		return 0, nil
-	}
-
-	switch tVal := in.(type) {
-	case string:
-		sVal := strings.TrimSpace(tVal)
-		i64, err = strconv.ParseInt(sVal, 10, 0)
-		// handle the case where the string might be a float
-		if err != nil && checkfn.IsNumeric(sVal) {
-			var floatVal float64
-			if floatVal, err = strconv.ParseFloat(sVal, 64); err == nil {
-				i64 = int64(math.Round(floatVal))
-				err = nil
-			}
-		}
+// StrictUint strict check value is integer(intX,uintX) and convert to uint64.
+func StrictUint(val any) (uint64, bool) {
+	switch tVal := val.(type) {
	case int:
-		i64 = int64(tVal)
+		return uint64(tVal), true
	case int8:
-		i64 = int64(tVal)
+		return uint64(tVal), true
	case int16:
-		i64 = int64(tVal)
+		return uint64(tVal), true
	case int32:
-		i64 = int64(tVal)
+		return uint64(tVal), true
	case int64:
-		i64 = tVal
-	case *int64: // default support int64 ptr type
-		i64 = *tVal
+		return uint64(tVal), true
	case uint:
-		i64 = int64(tVal)
+		return uint64(tVal), true
	case uint8:
-		i64 = int64(tVal)
+		return uint64(tVal), true
	case uint16:
-		i64 = int64(tVal)
+		return uint64(tVal), true
	case uint32:
-		i64 = int64(tVal)
+		return uint64(tVal), true
	case uint64:
-		i64 = int64(tVal)
-	case float32:
-		i64 = int64(tVal)
-	case float64:
-		i64 = int64(tVal)
-	case time.Duration:
-		i64 = int64(tVal)
-	case comdef.Int64able: // eg: json.Number
-		i64, err = tVal.Int64()
+		return tVal, true
+	case uintptr:
+		return uint64(tVal), true
	default:
-		if opt.HandlePtr {
-			if rv := reflect.ValueOf(in); rv.Kind() == reflect.Pointer {
-				rv = rv.Elem()
-				if checkfn.IsSimpleKind(rv.Kind()) {
-					return ToInt64With(rv.Interface(), optFns...)
-				}
-			}
-		}
-
-		if opt.UserConvFn != nil {
-			i64, err = opt.UserConvFn(in)
-		} else {
-			err = comdef.ErrConvType
-		}
+		return 0, false
	}
-	return
-}
-
-/*************************************************************
- * convert value to uint
- *************************************************************/
-
-// Uint convert any to uint, return error on failed
-func Uint(in any) (uint, error) { return ToUint(in) }
-
-// SafeUint convert any to uint, will ignore error
-func SafeUint(in any) uint {
-	val, _ := ToUint(in)
-	return val
-}
-
-// QuietUint convert any to uint, will ignore error
-func QuietUint(in any) uint { return SafeUint(in) }
-
-// MustUint convert any to uint, will panic on error
-func MustUint(in any) uint {
-	val, err := ToUintWith(in)
-	if err != nil {
-		panic(err)
-	}
-	return val
-}
-
-// UintOrDefault convert any to uint, return default val on failed
-func UintOrDefault(in any, defVal uint) uint { return UintOr(in, defVal) }
-
-// UintOr convert any to uint, return default val on failed
-func UintOr(in any, defVal uint) uint {
-	val, err := ToUintWith(in)
-	if err != nil {
-		return defVal
-	}
-	return val
-}
-
-// UintOrErr convert value to uint, return error on failed
-func UintOrErr(in any) (uint, error) { return ToUintWith(in) }
-
-// ToUint convert value to uint, return error on failed
-func ToUint(in any) (u64 uint, err error) { return ToUintWith(in) }
-
-// ToUintWith try to convert value to uint. can with some option func, more see ConvOption.
-func ToUintWith(in any, optFns ...ConvOptionFn[uint]) (uVal uint, err error) {
-	opt := NewConvOption(optFns...)
-	if !opt.NilAsFail && in == nil {
-		return 0, nil
-	}
-
-	switch tVal := in.(type) {
-	case int:
-		uVal = uint(tVal)
-	case int8:
-		uVal = uint(tVal)
-	case int16:
-		uVal = uint(tVal)
-	case int32:
-		uVal = uint(tVal)
-	case int64:
-		uVal = uint(tVal)
-	case uint:
-		uVal = tVal
-	case *uint: // default support uint ptr type
-		uVal = *tVal
-	case uint8:
-		uVal = uint(tVal)
-	case uint16:
-		uVal = uint(tVal)
-	case uint32:
-		uVal = uint(tVal)
-	case uint64:
-		uVal = uint(tVal)
-	case float32:
-		uVal = uint(tVal)
-	case float64:
-		uVal = uint(tVal)
-	case time.Duration:
-		uVal = uint(tVal)
-	case comdef.Int64able: // eg: json.Number
-		var i64 int64
-		i64, err = tVal.Int64()
-		uVal = uint(i64)
-	case string:
-		var u64 uint64
-		u64, err = strconv.ParseUint(strings.TrimSpace(tVal), 10, 0)
-		uVal = uint(u64)
-	default:
-		if opt.HandlePtr {
-			if rv := reflect.ValueOf(in); rv.Kind() == reflect.Pointer {
-				rv = rv.Elem()
-				if checkfn.IsSimpleKind(rv.Kind()) {
-					return ToUintWith(rv.Interface(), optFns...)
-				}
-			}
-		}
-
-		if opt.UserConvFn != nil {
-			uVal, err = opt.UserConvFn(in)
-		} else {
-			err = comdef.ErrConvType
-		}
-	}
-	return
-}
-
-/*************************************************************
- * convert value to uint64
- *************************************************************/
-
-// Uint64 convert any to uint64, return error on failed
-func Uint64(in any) (uint64, error) { return ToUint64(in) }
-
-// QuietUint64 convert any to uint64, will ignore error
-func QuietUint64(in any) uint64 { return SafeUint64(in) }
-
-// SafeUint64 convert any to uint64, will ignore error
-func SafeUint64(in any) uint64 {
-	val, _ := ToUint64(in)
-	return val
-}
-
-// MustUint64 convert any to uint64, will panic on error
-func MustUint64(in any) uint64 {
-	val, err := ToUint64With(in)
-	if err != nil {
-		panic(err)
-	}
-	return val
-}
-
-// Uint64OrDefault convert any to uint64, return default val on failed
-func Uint64OrDefault(in any, defVal uint64) uint64 { return Uint64Or(in, defVal) }
-
-// Uint64Or convert any to uint64, return default val on failed
-func Uint64Or(in any, defVal uint64) uint64 {
-	val, err := ToUint64With(in)
-	if err != nil {
-		return defVal
-	}
-	return val
-}
-
-// Uint64OrErr convert value to uint64, return error on failed
-func Uint64OrErr(in any) (uint64, error) { return ToUint64With(in) }
-
-// ToUint64 convert value to uint64, return error on failed
-func ToUint64(in any) (uint64, error) { return ToUint64With(in) }
-
-// ToUint64With try to convert value to uint64. can with some option func, more see ConvOption.
-func ToUint64With(in any, optFns ...ConvOptionFn[uint64]) (u64 uint64, err error) {
-	opt := NewConvOption(optFns...)
-	if !opt.NilAsFail && in == nil {
-		return 0, nil
-	}
-
-	switch tVal := in.(type) {
-	case int:
-		u64 = uint64(tVal)
-	case int8:
-		u64 = uint64(tVal)
-	case int16:
-		u64 = uint64(tVal)
-	case int32:
-		u64 = uint64(tVal)
-	case int64:
-		u64 = uint64(tVal)
-	case uint:
-		u64 = uint64(tVal)
-	case uint8:
-		u64 = uint64(tVal)
-	case uint16:
-		u64 = uint64(tVal)
-	case uint32:
-		u64 = uint64(tVal)
-	case uint64:
-		u64 = tVal
-	case *uint64: // default support uint64 ptr type
-		u64 = *tVal
-	case float32:
-		u64 = uint64(tVal)
-	case float64:
-		u64 = uint64(tVal)
-	case time.Duration:
-		u64 = uint64(tVal)
-	case comdef.Int64able: // eg: json.Number
-		var i64 int64
-		i64, err = tVal.Int64()
-		u64 = uint64(i64)
-	case string:
-		u64, err = strconv.ParseUint(strings.TrimSpace(tVal), 10, 0)
-	default:
-		if opt.HandlePtr {
-			if rv := reflect.ValueOf(in); rv.Kind() == reflect.Pointer {
-				rv = rv.Elem()
-				if checkfn.IsSimpleKind(rv.Kind()) {
-					return ToUint64With(rv.Interface(), optFns...)
-				}
-			}
-		}
-
-		if opt.UserConvFn != nil {
-			u64, err = opt.UserConvFn(in)
-		} else {
-			err = comdef.ErrConvType
-		}
-	}
-	return
}

/*************************************************************
- * convert value to float64
+ * region convert to float64
 *************************************************************/

// QuietFloat convert value to float64, will ignore error. alias of SafeFloat
@@ -671,7 +238,7 @@ func ToFloatWith(in any, optFns ...ConvOptionFn[float64]) (f64 float64, err erro
}

/*************************************************************
- * convert intX/floatX to string
+ * region intX/floatX to string
 *************************************************************/

// MustString convert intX/floatX value to string, will panic on error
diff --git a/vendor/github.com/gookit/goutil/mathutil/format.go b/vendor/github.com/gookit/goutil/mathutil/format.go
index deb29fd2a50..e310eb09116 100644
--- a/vendor/github.com/gookit/goutil/mathutil/format.go
+++ b/vendor/github.com/gookit/goutil/mathutil/format.go
@@ -22,6 +22,21 @@ func DataSize(size uint64) string {
	}
}

+// FormatBytes Format the byte size to be a readable string. eg: 1024 => 1 KB
+func FormatBytes(bytes int) string {
+	const unit = 1024
+	if bytes < unit {
+		return fmt.Sprintf("%d B", bytes)
+	}
+
+	div, exp := int64(unit), 0
+	for n := bytes / unit; n >= unit; n /= unit {
+		div *= unit
+		exp++
+	}
+	return fmt.Sprintf("%.2f %cB", float64(bytes)/float64(div), "KMGTPE"[exp])
+}
+
var timeFormats = [][]int{
	{0},
	{1},
diff --git a/vendor/github.com/gookit/goutil/structs/convert.go b/vendor/github.com/gookit/goutil/structs/convert.go
index f8029865dad..8c55e943164 100644
--- a/vendor/github.com/gookit/goutil/structs/convert.go
+++ b/vendor/github.com/gookit/goutil/structs/convert.go
@@ -66,11 +66,11 @@ func ToString(st any, optFns ...MapOptFunc) string {
const defaultFieldTag = "json"

// CustomUserFunc for map convert
-//  - fName: raw field name in struct
+//   - fName: raw field name in struct
//
// Returns:
-//  - ok: return true to collect field, otherwise excluded.
-//  - newVal: `newVal != nil` return new value to collect, otherwise collect original value.
+//   - ok: return true to collect field, otherwise excluded.
+//   - newVal: `newVal != nil` return new value to collect, otherwise collect original value.
type CustomUserFunc func(fName string, fv reflect.Value) (ok bool, newVal any)

// MapOptions for convert struct to map
diff --git a/vendor/github.com/gookit/goutil/strutil/check.go b/vendor/github.com/gookit/goutil/strutil/check.go
index 04660c307d9..a990f6f0575 100644
--- a/vendor/github.com/gookit/goutil/strutil/check.go
+++ b/vendor/github.com/gookit/goutil/strutil/check.go
@@ -3,6 +3,7 @@ package strutil
import (
	"path"
	"regexp"
+	"strconv"
	"strings"
	"unicode"
	"unicode/utf8"
@@ -17,18 +18,43 @@ var IsHttpURL = checkfn.IsHttpURL
// IsNumChar returns true if the given character is a numeric, otherwise false.
func IsNumChar(c byte) bool { return c >= '0' && c <= '9' }

-var intReg = regexp.MustCompile(`^\d+$`)
-var floatReg = regexp.MustCompile(`^[-+]?\d*\.?\d+$`)
+var (
+	uintReg = regexp.MustCompile(`^\d+$`)
+	intReg  = regexp.MustCompile(`^[-+]?\d+$`)
+
+	floatReg = regexp.MustCompile(`^[-+]?\d*\.?\d+$`)
+)

// IsInt check the string is an integer number
-func IsInt(s string) bool { return intReg.MatchString(s) }
+func IsInt(s string) bool {
+	if s == "" {
+		return false
+	}
+	return intReg.MatchString(s)
+}
+
+// IsUint check the string is an unsigned integer number
+func IsUint(s string) bool {
+	if s == "" {
+		return false
+	}
+	return uintReg.MatchString(s)
+}

// IsFloat check the string is a float number
-func IsFloat(s string) bool { return floatReg.MatchString(s) }
+func IsFloat(s string) bool {
+	if s == "" {
+		return false
+	}
+	return floatReg.MatchString(s)
+}

// IsNumeric returns true if the given string is a numeric(int/float), otherwise false.
func IsNumeric(s string) bool { return checkfn.IsNumeric(s) }

+// IsPositiveNum check the string is a positive number
+func IsPositiveNum(s string) bool { return checkfn.IsPositiveNum(s) }
+
// IsAlphabet char
func IsAlphabet(char uint8) bool {
	// A 65 -> Z 90
@@ -48,6 +74,28 @@ func IsAlphaNum(c uint8) bool {
	return c == '_' || '0' <= c && c <= '9' || 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z'
}

+// IsUpper returns true if the given string is an uppercase, otherwise false.
+func IsUpper(s string) bool {
+	for i := 0; i < len(s); i++ {
+		if s[i] >= 'A' && s[i] <= 'Z' {
+			continue
+		}
+		return false
+	}
+	return true
+}
+
+// IsLower returns true if the given string is a lowercase, otherwise false.
+func IsLower(s string) bool {
+	for i := 0; i < len(s); i++ {
+		if s[i] >= 'a' && s[i] <= 'z' {
+			continue
+		}
+		return false
+	}
+	return true
+}
+
// StrPos alias of the strings.Index
func StrPos(s, sub string) int { return strings.Index(s, sub) }

@@ -68,6 +116,16 @@ func IContains(s, sub string) bool {
// ContainsByte in given string.
func ContainsByte(s string, c byte) bool { return strings.IndexByte(s, c) >= 0 }

+// ContainsByteOne in given string.
+func ContainsByteOne(s string, bs []byte) bool {
+	for _, b := range bs {
+		if strings.IndexByte(s, b) >= 0 {
+			return true
+		}
+	}
+	return false
+}
+
// InArray alias of HasOneSub()
var InArray = HasOneSub

@@ -95,10 +153,10 @@ func IContainsOne(s string, subs []string) bool {
	return false
}

-// ContainsAll substr(s) in the given string. alias of HasAllSubs()
+// ContainsAll given string should contain all substrings. alias of HasAllSubs()
func ContainsAll(s string, subs []string) bool { return HasAllSubs(s, subs) }

-// HasAllSubs all substr in the given string.
+// HasAllSubs given string should contain all substrings
func HasAllSubs(s string, subs []string) bool {
	for _, sub := range subs {
		if !strings.Contains(s, sub) {
@@ -227,6 +285,8 @@ var (
	verRegex = regexp.MustCompile(`^[0-9][\d.]+(-\w+)?$`)
	// regex for check variable name
	varRegex = regexp.MustCompile(`^[a-zA-Z][\w-]*$`)
+	// regex for check env var name
+	envRegex = regexp.MustCompile(`^[A-Z][A-Z0-9_]*$`)
	// IsVariableName alias for IsVarName
	IsVariableName = IsVarName
)
@@ -237,25 +297,90 @@ func IsVersion(s string) bool { return verRegex.MatchString(s) }
// IsVarName is valid variable name.
func IsVarName(s string) bool { return varRegex.MatchString(s) }

-// Compare for two strings.
-func Compare(s1, s2, op string) bool { return VersionCompare(s1, s2, op) }
+// IsEnvName is valid ENV var name. eg: APP_NAME
+func IsEnvName(s string) bool { return envRegex.MatchString(s) }

-// VersionCompare for two version strings.
-func VersionCompare(v1, v2, op string) bool {
+// Compare for two strings.
+func Compare(s1, s2, op string) bool {
	switch op {
	case ">", "gt":
-		return v1 > v2
+		return s1 > s2
	case "<", "lt":
-		return v1 < v2
+		return s1 < s2
	case ">=", "gte":
-		return v1 >= v2
+		return s1 >= s2
	case "<=", "lte":
-		return v1 <= v2
+		return s1 <= s2
	case "!=", "ne", "neq":
-		return v1 != v2
+		return s1 != s2
	default: // eq
-		return v1 == v2
+		return s1 == s2
+	}
+}
+
+// VersionCompare for two version strings. eg: 1.2.0 > 1.1.0
+func VersionCompare(v1, v2, op string) bool {
+	parts1 := parseVersion(v1)
+	parts2 := parseVersion(v2)
+
+	result := compareVersions(parts1, parts2)
+	switch op {
+	case ">", "gt":
+		return result > 0
+	case "<", "lt":
+		return result < 0
+	case "=", "==", "eq":
+		return result == 0
+	case "!=", "ne", "neq":
+		return result != 0
+	case ">=", "gte":
+		return result >= 0
+	case "<=", "lte":
+		return result <= 0
+	default:
+		return false
+	}
+}
+
+// parseVersion 将版本号字符串解析为整数数组
+func parseVersion(version string) []int {
+	parts := strings.Split(version, ".")
+	result := make([]int, len(parts))
+
+	for i, part := range parts {
+		num, _ := strconv.Atoi(part)
+		result[i] = num
+	}
+	return result
+}
+
+// compareVersions 比较两个版本号数组
+// 返回: -1 表示 v1 < v2, 0 表示 v1 = v2, 1 表示 v1 > v2
+func compareVersions(v1, v2 []int) int {
+	maxLen := len(v1)
+	if len(v2) > maxLen {
+		maxLen = len(v2)
	}
+
+	for i := 0; i < maxLen; i++ {
+		num1 := 0
+		if i < len(v1) {
+			num1 = v1[i]
+		}
+
+		num2 := 0
+		if i < len(v2) {
+			num2 = v2[i]
+		}
+
+		if num1 > num2 {
+			return 1
+		} else if num1 < num2 {
+			return -1
+		}
+	}
+
+	return 0
}

// SimpleMatch all substring in the give text string.
diff --git a/vendor/github.com/gookit/goutil/strutil/convbase.go b/vendor/github.com/gookit/goutil/strutil/convbase.go
index a405778a647..c9f57edd425 100644
--- a/vendor/github.com/gookit/goutil/strutil/convbase.go
+++ b/vendor/github.com/gookit/goutil/strutil/convbase.go
@@ -16,6 +16,7 @@ const (
	Base16Chars = "0123456789abcdef"
	Base32Chars = "0123456789abcdefghjkmnpqrstvwxyz"
	Base36Chars = "0123456789abcdefghijklmnopqrstuvwxyz"
+	Base48Chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKL"
	Base62Chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
	Base64Chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/"
)
@@ -33,14 +34,26 @@ func Base10Conv(src string, to int) string { return BaseConv(src, 10, to) }
//	BaseConv("7b", 16, 10) // Output: "123"
func BaseConv(src string, from, to int) string {
	if from > 64 || from < 2 {
-		return ""
+		from = 10
	}
	if to > 64 || to < 2 {
-		return ""
+		to = 16
	}
	return BaseConvByTpl(src, Base64Chars[:from], Base64Chars[:to])
}

+// BaseConvInt convert base int to new base string.
+//
+// Usage:
+//
+//	BaseConv(123, 16) // Output: "7b"
+func BaseConvInt(src uint64, to int) string {
+	if to > 64 || to < 2 {
+		to = 16
+	}
+	return BaseConvIntByTpl(src, Base64Chars[:to])
+}
+
// BaseConvByTpl convert base string by template.
//
// Usage:
@@ -58,7 +71,7 @@ func BaseConvByTpl(src string, fromBase, toBase string) string {
		var err error
		dec, err = strconv.ParseUint(src, 10, 0)
		if err != nil {
-			basefn.Panicf("input is not a valid decimal number: %s", src)
+			basefn.Panicf("input is not a valid decimal number: %s(%v)", src, err)
		}
	} else {
		fLen := uint64(len(fromBase))
@@ -67,6 +80,12 @@ func BaseConvByTpl(src string, fromBase, toBase string) string {
		}
	}

+	// convert to new base
+	return BaseConvIntByTpl(dec, toBase)
+}
+
+// BaseConvIntByTpl convert base int to new base string.
+func BaseConvIntByTpl(dec uint64, toBase string) string {
	// convert to new base
	var res string
	toLen := uint64(len(toBase))
diff --git a/vendor/github.com/gookit/goutil/strutil/convert.go b/vendor/github.com/gookit/goutil/strutil/convert.go
index d258621f8d3..f7bbac4b0d9 100644
--- a/vendor/github.com/gookit/goutil/strutil/convert.go
+++ b/vendor/github.com/gookit/goutil/strutil/convert.go
@@ -88,7 +88,7 @@ func JoinAny(sep string, parts ...any) string {
func Implode(sep string, ss ...string) string { return strings.Join(ss, sep) }

/*************************************************************
- * convert value to string
+ * region value to string
 *************************************************************/

// String convert value to string, return error on failed
@@ -144,7 +144,7 @@ func AnyToString(val any, defaultAsErr bool) (s string, err error) {
	if !defaultAsErr {
		optFn = comfunc.WithUserConvFn(comfunc.StrBySprintFn)
	}
-	return ToStringWith(val, optFn)
+	return comfunc.ToStringWith(val, optFn)
}

// ToStringWith try to convert value to string. can with some option func, more see comfunc.ConvOption.
@@ -153,7 +153,7 @@ func ToStringWith(in any, optFns ...comfunc.ConvOptionFn) (string, error) {
}

/*************************************************************
- * convert string value to bool
+ * region string value to bool
 *************************************************************/

// ToBool convert string to bool
@@ -185,7 +185,7 @@ func Bool(s string) (bool, error) {
}

/*************************************************************
- * convert string value to int
+ * region string value to int
 *************************************************************/

// Int convert string to int, alias of ToInt()
@@ -234,7 +234,7 @@ func IntOrPanic(s string) int {
}

/*************************************************************
- * convert string value to int64
+ * region convert string to int64
 *************************************************************/

// Int64 convert string to int, will ignore error
@@ -286,7 +286,7 @@ func Int64OrPanic(s string) int64 {
}

/*************************************************************
- * convert string value to uint
+ * region string value to uint
 *************************************************************/

// Uint convert string to uint, will ignore error
@@ -335,7 +335,7 @@ func UintOr(s string, defVal uint64) uint64 {
}

/*************************************************************
- * convert string value to byte
+ * region string value to byte
 * refer from https://github.com/valyala/fastjson/blob/master/util.go
 *************************************************************/

@@ -361,7 +361,7 @@ func ToBytes(s string) (b []byte) {
}

/*************************************************************
- * convert string value to int/string slice, time.Time
+ * region string to int/string slice, time.Time
 *************************************************************/

// Ints alias of the ToIntSlice(). default sep is comma(,)
@@ -406,11 +406,6 @@ func ToSlice(s string, sep ...string) []string {
	return Split(s, ",")
}

-// ToOSArgs split string to string[](such as os.Args)
-// func ToOSArgs(s string) []string {
-// 	return cliutil.StringToOSArgs(s) // error: import cycle not allowed
-// }
-
// ToDuration parses a duration string. such as "300ms", "-1.5h" or "2h45m".
// Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
func ToDuration(s string) (time.Duration, error) {
diff --git a/vendor/github.com/gookit/goutil/strutil/format.go b/vendor/github.com/gookit/goutil/strutil/format.go
index 05150f5a4ad..c63b5d8b848 100644
--- a/vendor/github.com/gookit/goutil/strutil/format.go
+++ b/vendor/github.com/gookit/goutil/strutil/format.go
@@ -1,6 +1,7 @@
package strutil

import (
+	"fmt"
	"regexp"
	"strings"
	"unicode"
@@ -184,3 +185,46 @@ func IndentBytes(b, prefix []byte) []byte {
	}
	return res
}
+
+// Replaces replace multi strings
+//
+//	pairs: {old1: new1, old2: new2, ...}
+//
+// Can also use:
+//
+//	strings.NewReplacer("old1", "new1", "old2", "new2").Replace(str)
+func Replaces(str string, pairs map[string]string) string {
+	return NewReplacer(pairs).Replace(str)
+}
+
+// ReplaceVars replaces simple variables in a string. format: {varName}
+func ReplaceVars(s string, vars map[string]string) string {
+	if !ContainsByte(s, '{') {
+		return s
+	}
+
+	// format var name to {name}
+	pairs := make(map[string]string)
+	for k, v := range vars {
+		vName := "{" + k + "}"
+		pairs[vName] = v
+	}
+	return NewReplacer(pairs).Replace(s)
+}
+
+// NewReplacer instance
+func NewReplacer(pairs map[string]string) *strings.Replacer {
+	ss := make([]string, len(pairs)*2)
+	for old, newVal := range pairs {
+		ss = append(ss, old, newVal)
+	}
+	return strings.NewReplacer(ss...)
+}
+
+// WrapTag for given string.
+func WrapTag(s, tag string) string {
+	if s == "" {
+		return s
+	}
+	return fmt.Sprintf("<%s>%s</%s>", tag, s, tag)
+}
diff --git a/vendor/github.com/gookit/goutil/strutil/gensn.go b/vendor/github.com/gookit/goutil/strutil/gensn.go
index 31cf6cbf74d..2c2981741dc 100644
--- a/vendor/github.com/gookit/goutil/strutil/gensn.go
+++ b/vendor/github.com/gookit/goutil/strutil/gensn.go
@@ -7,7 +7,6 @@ import (
	"strconv"
	"time"

-	"github.com/gookit/goutil/mathutil"
	"github.com/gookit/goutil/x/basefn"
)

@@ -34,12 +33,12 @@ func MicroTimeID() string { return MTimeBaseID(10) }

// MicroTimeHexID micro time HEX ID generate.
//
-// return like: 5b5f0588af1761ad3(len: 16-17)
+// return like: 643d4cec7db9e(len: 13)
func MicroTimeHexID() string { return MTimeHexID() }

// MTimeHexID micro time HEX ID generate.
//
-// return like: 5b5f0588af1761ad3(len: 16-17)
+// return like: 643d4cec7db9e(len: 13)
func MTimeHexID() string { return MTimeBaseID(16) }

// MTimeBase36 micro time BASE36 id generate.
@@ -48,12 +47,19 @@ func MTimeBase36() string { return MTimeBaseID(36) }
// MTimeBaseID micro time BASE id generate. toBase: 2-36
//
// Examples:
-//   - MTimeBaseID(16): 5b5f0588af1761ad3(len: 16-17)
-//   - MTimeBaseID(36): gorntzvsa73mo(len: 13)
+//   - toBase=16: 643d4cec7db9e(len: 13)
+//   - toBase=36: hd312z9ka2(len: 10)
func MTimeBaseID(toBase int) string {
+	// eg: 1763431181849557
	ms := time.Now().UnixMicro()
-	ri := mathutil.RandomInt(DefMinInt, DefMaxInt)
-	return strconv.FormatInt(ms, toBase) + strconv.FormatInt(int64(ri), toBase)
+	// rand 1000 - 9999
+	// ri := mathutil.RandomInt(DefMinInt, DefMaxInt)
+	ri := 1000 + rand.Int63n(8999)
+
+	if toBase > 36 {
+		return BaseConvInt(uint64(ms)+uint64(ri), toBase)
+	}
+	return strconv.FormatInt(ms+ri, toBase)
}

// DatetimeNo generate. can use for order-no.
@@ -84,20 +90,20 @@ func DateSN(prefix string) string {
	bs = strconv.AppendUint(bs, uint64(c32%99), 10)

	// rand 1000 - 9999
-	rs := rand.New(rand.NewSource(nt.UnixNano()))
-	bs = strconv.AppendInt(bs, 1000+rs.Int63n(8999), 10)
+	// rs := rand.New(rand.NewSource(nt.UnixNano()))
+	bs = strconv.AppendInt(bs, 1000+rand.Int63n(8999), 10)

	return string(bs)
}

-// DateSNV2 generate date serial number.
+// DateSNv2 generate date serial number.
//   - 2 < extBase <= 36
//   - return: PREFIX + yyyyMMddHHmmss + extBase(6bit micro + 5bit random number)
//
// Example:
//   - prefix=P, extBase=16, return: P2023091414361354b4490(len=22)
//   - prefix=P, extBase=36, return: P202309141436131gw3jg(len=21)
-func DateSNV2(prefix string, extBase ...int) string {
+func DateSNv2(prefix string, extBase ...int) string {
	pl := len(prefix)
	bs := make([]byte, 0, 22+pl)
	if pl > 0 {
@@ -109,9 +115,9 @@ func DateSNV2(prefix string, extBase ...int) string {
	bs = nt.AppendFormat(bs, "20060102150405.000000")

	// rand 10000 - 99999
-	rs := rand.New(rand.NewSource(nt.UnixNano()))
+	// rs := rand.New(rand.NewSource(nt.UnixNano()))
	// 6bit micro + 5bit rand
-	ext := strconv.AppendInt(bs[16+pl:], 10000+rs.Int63n(89999), 10)
+	ext := strconv.AppendInt(bs[16+pl:], 10000+rand.Int63n(89999), 10)

	base := basefn.FirstOr(extBase, 16)
	// prefix + yyyyMMddHHmmss + ext(convert to base)
@@ -119,3 +125,43 @@ func DateSNV2(prefix string, extBase ...int) string {

	return string(bs)
}
+
+// DateSNv3 generate date serial number.
+//   - 2 < extBase <= 64
+//   - return: PREFIX + DATETIME(yyyyMMddHHmmss).dateLen + extBase(DATETIME.after+6bit micro + 5bit random number)
+//   - dateLen: 为 DATETIME(yyyyMMddHHmmss) 保留的长度,默认为 8(yyyyMMdd) 后面的给 extBase 使用
+//
+// Example:
+//   - prefix=P, dateLen=8, extBase=16, return: P202511139vs99gbifnj len: 20
+//   - prefix=P, dateLen=6, extBase=36, return: P2025119yn52qhefati len: 19
+//   - prefix=P, dateLen=6, extBase=48, return: P202511k9ksgD1fe6x len: 18
+//   - prefix=P, dateLen=4, extBase=62, return: P2025aZl8N0y58M7 len: 16
+func DateSNv3(prefix string, dateLen int, extBase ...int) string {
+	pl := len(prefix)
+	bs := make([]byte, 0, 22+pl)
+	if pl > 0 {
+		bs = append(bs, prefix...)
+	}
+
+	// micro datetime
+	nt := time.Now()
+	bs = nt.AppendFormat(bs, "20060102150405.000000")
+	// 去掉 bs 中间的 .
+	bs = append(bs[:14+pl], bs[15+pl:]...)
+
+	// rand 10000 - 99999
+	// rs := rand.New(rand.NewSource(nt.UnixNano())) // ERR: 这样使用,同时调用产生随机数相同,导致重复
+	// 6bit micro + 5bit rand
+	// ext := strconv.AppendInt(bs[dateLen+pl:], 10000+rs.Int63n(89999), 10)
+	ext := strconv.AppendInt(bs[dateLen+pl:], 10000+rand.Int63n(89999), 10)
+	extI64, _ := strconv.ParseInt(string(ext), 10, 0)
+
+	base := basefn.FirstOr(extBase, 32)
+	// PREFIX + DATETIME(yyyyMMddHHmmss).dateLen + extBase(convert to base)
+	if base > 36 {
+		bs = append(bs[:dateLen+pl], BaseConvInt(uint64(extI64), base)...)
+	} else {
+		bs = append(bs[:dateLen+pl], strconv.FormatInt(extI64, base)...)
+	}
+	return string(bs)
+}
diff --git a/vendor/github.com/gookit/goutil/strutil/parse.go b/vendor/github.com/gookit/goutil/strutil/parse.go
index c03cb125d20..580b66baae7 100644
--- a/vendor/github.com/gookit/goutil/strutil/parse.go
+++ b/vendor/github.com/gookit/goutil/strutil/parse.go
@@ -2,6 +2,7 @@ package strutil

import (
	"errors"
+	"regexp"
	"strconv"
	"strings"
	"time"
@@ -10,6 +11,13 @@ import (
	"github.com/gookit/goutil/byteutil"
)

+var regNumVersion = regexp.MustCompile(`[0-9][\d.]+([_-]\d+)?`)
+
+// NumVersion parse input string, get valid number version. eg: go-1.22.3 -> 1.22.3
+func NumVersion(s string) string {
+	return regNumVersion.FindString(s)
+}
+
// MustToTime convert date string to time.Time
func MustToTime(s string, layouts ...string) time.Time {
	t, err := ToTime(s, layouts...)
diff --git a/vendor/github.com/gookit/goutil/strutil/runes.go b/vendor/github.com/gookit/goutil/strutil/runes.go
index 6a3debba025..1bb678aad35 100644
--- a/vendor/github.com/gookit/goutil/strutil/runes.go
+++ b/vendor/github.com/gookit/goutil/strutil/runes.go
@@ -75,8 +75,8 @@ func Utf8Width(s string) int { return RunesWidth([]rune(s)) }
//	str := "hi,你好"
//
//	len(str) // 9
-//	strutil.Utf8Width(str) // 7
-//	len([]rune(str)) = utf8.RuneCountInString(s) // 5
+//	strutil.RunesWidth(str) // 7 一个中文字占两个字符
+//	len([]rune(str)) = utf8.RuneCountInString(s) // 5 按字算
func RunesWidth(rs []rune) (w int) {
	if len(rs) == 0 {
		return
diff --git a/vendor/github.com/gookit/goutil/strutil/strutil.go b/vendor/github.com/gookit/goutil/strutil/strutil.go
index 9e46773b942..2e15436f903 100644
--- a/vendor/github.com/gookit/goutil/strutil/strutil.go
+++ b/vendor/github.com/gookit/goutil/strutil/strutil.go
@@ -3,7 +3,6 @@ package strutil

import (
	"errors"
-	"fmt"
	"strings"

	"github.com/gookit/goutil/comdef"
@@ -77,34 +76,6 @@ func Valid(ss ...string) string {
	return ""
}

-// Replaces replace multi strings
-//
-//	pairs: {old1: new1, old2: new2, ...}
-//
-// Can also use:
-//
-//	strings.NewReplacer("old1", "new1", "old2", "new2").Replace(str)
-func Replaces(str string, pairs map[string]string) string {
-	return NewReplacer(pairs).Replace(str)
-}
-
-// NewReplacer instance
-func NewReplacer(pairs map[string]string) *strings.Replacer {
-	ss := make([]string, len(pairs)*2)
-	for old, newVal := range pairs {
-		ss = append(ss, old, newVal)
-	}
-	return strings.NewReplacer(ss...)
-}
-
-// WrapTag for given string.
-func WrapTag(s, tag string) string {
-	if s == "" {
-		return s
-	}
-	return fmt.Sprintf("<%s>%s</%s>", tag, s, tag)
-}
-
// SubstrCount returns the number of times the substr substring occurs in the s string.
// Actually, it comes from strings.Count().
//
diff --git a/vendor/github.com/gookit/goutil/strutil/textutil/strvar_expr.go b/vendor/github.com/gookit/goutil/strutil/textutil/strvar_expr.go
index bcfff8d2485..ea91b5b4f99 100644
--- a/vendor/github.com/gookit/goutil/strutil/textutil/strvar_expr.go
+++ b/vendor/github.com/gookit/goutil/strutil/textutil/strvar_expr.go
@@ -15,8 +15,8 @@ import (
// StrVarRenderer implements like shell vars renderer
// 简单的实现类似 php, kotlin, shell 插值变量渲染,表达式解析处理。
//
-//  - var format: $var_name, ${some_var}, ${top.sub_var}
-//  - func call: ${func($var_name, 'const string')}
+//   - var format: $var_name, ${some_var}, ${top.sub_var}
+//   - func call: ${func($var_name, 'const string')}
type StrVarRenderer struct {
	// global variables
	vars map[string]any
diff --git a/vendor/github.com/gookit/goutil/strutil/textutil/textutil.go b/vendor/github.com/gookit/goutil/strutil/textutil/textutil.go
index 7ade12c091f..931e9221daa 100644
--- a/vendor/github.com/gookit/goutil/strutil/textutil/textutil.go
+++ b/vendor/github.com/gookit/goutil/strutil/textutil/textutil.go
@@ -13,14 +13,14 @@ import (

// ReplaceVars by regex replace given tpl vars.
//
-// If a format is empty, will use {const defaultVarFormat}
+// If a format is empty, will use {const DefaultVarFormat}
func ReplaceVars(text string, vars map[string]any, format string) string {
	return NewVarReplacer(format).Replace(text, vars)
}

// RenderSMap by regex replacement given tpl vars.
//
-// If a format is empty, will use {const defaultVarFormat}
+// If a format is empty, will use {const DefaultVarFormat}
func RenderSMap(text string, vars map[string]string, format string) string {
	return NewVarReplacer(format).RenderSimple(text, vars)
}
diff --git a/vendor/github.com/gookit/goutil/strutil/textutil/var_replacer.go b/vendor/github.com/gookit/goutil/strutil/textutil/var_replacer.go
index 40044f300f6..798e0b25b6b 100644
--- a/vendor/github.com/gookit/goutil/strutil/textutil/var_replacer.go
+++ b/vendor/github.com/gookit/goutil/strutil/textutil/var_replacer.go
@@ -1,6 +1,7 @@
package textutil

import (
+	"os"
	"reflect"
	"regexp"
	"strings"
@@ -11,7 +12,8 @@ import (
	"github.com/gookit/goutil/strutil"
)

-const defaultVarFormat = "{{,}}"
+// DefaultVarFormat var template
+const DefaultVarFormat = "{{,}}"

// FallbackFn type
type FallbackFn = func(name string) (val string, ok bool)
@@ -28,7 +30,7 @@ type VarReplacer struct {
	//
	// eg: {name: {a: 1, b: 2}} => {name.a: 1, name.b: 2}
	flatSubs bool
-	// do parse env value. default: false
+	// do parse env value in var-value and tpl var-name. default: false
	parseEnv bool
	// do parse default value. default: false
	//
@@ -46,7 +48,7 @@ type VarReplacer struct {
	RenderFn func(s string, vs map[string]string) string
}

-// NewVarReplacer instance.
+// NewVarReplacer instance. default format is: DefaultVarFormat
//
// Usage:
//
@@ -104,7 +106,7 @@ func (r *VarReplacer) OnNotFound(fn FallbackFn) *VarReplacer {

// WithFormat custom var template
func (r *VarReplacer) WithFormat(format string) *VarReplacer {
-	r.Left, r.Right = strutil.QuietCut(strutil.OrElse(format, defaultVarFormat), ",")
+	r.Left, r.Right = strutil.QuietCut(strutil.OrElse(format, DefaultVarFormat), ",")
	r.Init()
	return r
}
@@ -183,7 +185,11 @@ func (r *VarReplacer) RenderSimple(s string, varMap map[string]string) string {

	if r.parseEnv {
		for name, val := range varMap {
-			varMap[name] = varexpr.SafeParse(val)
+			if strings.Contains(val, "${") {
+				varMap[name] = varexpr.SafeParse(val)
+			} else {
+				varMap[name] = val
+			}
		}
	}

@@ -223,6 +229,11 @@ func (r *VarReplacer) doReplace(s string, varMap map[string]string) string {
		if val, ok := varMap[name]; ok {
			return val
		}
+		if r.parseEnv && strutil.IsEnvName(name) {
+			if val := os.Getenv(name); val != "" {
+				return val
+			}
+		}

		// has custom not found handle func
		if r.NotFound != nil {
diff --git a/vendor/github.com/gookit/goutil/syncs/syncs.go b/vendor/github.com/gookit/goutil/syncs/syncs.go
index e8933afdc75..64f7aab3fec 100644
--- a/vendor/github.com/gookit/goutil/syncs/syncs.go
+++ b/vendor/github.com/gookit/goutil/syncs/syncs.go
@@ -1,7 +1,10 @@
// Package syncs provides synchronization primitives util functions.
package syncs

-import "sync"
+import (
+	"context"
+	"sync"
+)

// WaitGroup is a wrapper of sync.WaitGroup.
type WaitGroup struct {
@@ -16,3 +19,8 @@ func (wg *WaitGroup) Go(fn func()) {
		fn()
	}()
}
+
+// ContextValue create a new context with given value
+func ContextValue(key, value any) context.Context {
+	return context.WithValue(context.Background(), key, value)
+}
diff --git a/vendor/github.com/gookit/goutil/sysutil/os_version_windows.go b/vendor/github.com/gookit/goutil/sysutil/os_version_windows.go
index a9bb0c98347..279d6027c41 100644
--- a/vendor/github.com/gookit/goutil/sysutil/os_version_windows.go
+++ b/vendor/github.com/gookit/goutil/sysutil/os_version_windows.go
@@ -43,7 +43,7 @@ func VersionInfoBySys() *OSVersionInfo {

// OsVersionByParse Get Windows system version information by parse string
//
-//  cmdOut eg: "Microsoft Windows [Version 10.0.22631.4391]"
+//	cmdOut eg: "Microsoft Windows [Version 10.0.22631.4391]"
func OsVersionByParse(cmdOut string) (*OSVersionInfo, error) {
	return parseOsVersionString(cmdOut)
}
@@ -153,4 +153,3 @@ func parseOsVersionString(out string) (*OSVersionInfo, error) {
	}
	return &ovi, nil
}
-
diff --git a/vendor/github.com/gookit/goutil/sysutil/sysutil_darwin.go b/vendor/github.com/gookit/goutil/sysutil/sysutil_darwin.go
index f0962d8a2da..f8bb1503c70 100644
--- a/vendor/github.com/gookit/goutil/sysutil/sysutil_darwin.go
+++ b/vendor/github.com/gookit/goutil/sysutil/sysutil_darwin.go
@@ -1,4 +1,5 @@
//go:build darwin
+
package sysutil

import "os/exec"
diff --git a/vendor/github.com/gookit/goutil/x/basefn/basefn.go b/vendor/github.com/gookit/goutil/x/basefn/basefn.go
index ec9e8956e0c..3ab144eee7a 100644
--- a/vendor/github.com/gookit/goutil/x/basefn/basefn.go
+++ b/vendor/github.com/gookit/goutil/x/basefn/basefn.go
@@ -4,40 +4,18 @@ package basefn
import (
	"errors"
	"fmt"
+
+	"github.com/gookit/goutil/internal/comfunc"
)

// Panicf format panic message use fmt.Sprintf
-func Panicf(format string, v ...any) {
-	panic(fmt.Sprintf(format, v...))
-}
+func Panicf(format string, v ...any) { panic(fmt.Sprintf(format, v...)) }

// PanicIf if cond = true, panics with an error message
func PanicIf(cond bool, fmtAndArgs ...any) {
	if cond {
-		panic(errors.New(formatWithArgs(fmtAndArgs)))
-	}
-}
-
-func formatWithArgs(fmtAndArgs []any) string {
-	ln := len(fmtAndArgs)
-	if ln == 0 {
-		return ""
-	}
-
-	first := fmtAndArgs[0]
-
-	if ln == 1 {
-		if msgAsStr, ok := first.(string); ok {
-			return msgAsStr
-		}
-		return fmt.Sprintf("%+v", first)
-	}
-
-	// is template string.
-	if tplStr, ok := first.(string); ok {
-		return fmt.Sprintf(tplStr, fmtAndArgs[1:]...)
+		panic(errors.New(comfunc.FormatWithArgs(fmtAndArgs)))
	}
-	return fmt.Sprint(fmtAndArgs...)
}

// PanicErr panics if error is not empty
diff --git a/vendor/github.com/gookit/goutil/x/ccolor/color_tag.go b/vendor/github.com/gookit/goutil/x/ccolor/color_tag.go
index 69e554342fe..9162dce8447 100644
--- a/vendor/github.com/gookit/goutil/x/ccolor/color_tag.go
+++ b/vendor/github.com/gookit/goutil/x/ccolor/color_tag.go
@@ -4,8 +4,6 @@ import (
	"fmt"
	"regexp"
	"strings"
-
-	"github.com/gookit/goutil/x/termenv"
)

// output colored text like uses custom tag.
@@ -67,6 +65,7 @@ var colorTags = map[string]string{
	"normal":   "0;39", // no color
	"brown":    "0;33", // #A52A2A
	"yellow":   "0;33",
+	"ylw": "0;33",
	"ylw0":     "0;33",
	"yellowB":  "1;33", // with bold
	"ylw1":     "1;33",
@@ -178,7 +177,7 @@ func ReplaceTag(str string) string { return ParseTagByEnv(str) }
// ParseTagByEnv parse given string. will check package setting.
func ParseTagByEnv(str string) string {
	// disable OR not support color
-	if termenv.NoColor() || !termenv.IsSupportColor() {
+	if shouldCleanColor() {
		return ClearTag(str)
	}
	return ParseTag(str)
diff --git a/vendor/github.com/gookit/goutil/x/ccolor/style.go b/vendor/github.com/gookit/goutil/x/ccolor/style.go
index 5a808912024..2fd9f5791f2 100644
--- a/vendor/github.com/gookit/goutil/x/ccolor/style.go
+++ b/vendor/github.com/gookit/goutil/x/ccolor/style.go
@@ -8,8 +8,9 @@ import (

// String color style string. TODO
// eg:
-// 		s := String("red,bold")
-//		s.Println("some text message")
+//
+//	s := String("red,bold")
+//	s.Println("some text message")
type String string

// Style for color render.
diff --git a/vendor/github.com/gookit/goutil/x/ccolor/util.go b/vendor/github.com/gookit/goutil/x/ccolor/util.go
index 46ed2b4bbc4..a00110dc29e 100644
--- a/vendor/github.com/gookit/goutil/x/ccolor/util.go
+++ b/vendor/github.com/gookit/goutil/x/ccolor/util.go
@@ -22,6 +22,10 @@ func ColorsToCode(colors ...Color) string {
	return strings.Join(codes, ";")
}

+func shouldCleanColor() bool {
+	return termenv.NoColor() || !termenv.IsSupportColor()
+}
+
/*************************************************************
 * render color code
 *************************************************************/
@@ -43,7 +47,7 @@ func RenderCode(code string, args ...any) string {
	}

	// disabled OR not support color
-	if !termenv.IsSupportColor() {
+	if shouldCleanColor() {
		return ClearCode(message)
	}

@@ -62,7 +66,7 @@ func RenderString(code string, str string) string {
	}

	// disabled OR not support color
-	if !termenv.IsSupportColor() {
+	if shouldCleanColor() {
		return ClearCode(str)
	}

@@ -79,7 +83,7 @@ func RenderWithSpaces(code string, args ...any) string {
	}

	// disabled OR not support color
-	if !termenv.IsSupportColor() {
+	if shouldCleanColor() {
		return ClearCode(msg)
	}
	return StartSet + code + "m" + msg + ResetSet
@@ -128,4 +132,3 @@ func formatLikePrintln(args []any) (message string) {
	}
	return
}
-
diff --git a/vendor/github.com/gookit/goutil/x/goinfo/stack.go b/vendor/github.com/gookit/goutil/x/goinfo/stack.go
index 3912b7aa9b3..e6183569d77 100644
--- a/vendor/github.com/gookit/goutil/x/goinfo/stack.go
+++ b/vendor/github.com/gookit/goutil/x/goinfo/stack.go
@@ -124,12 +124,12 @@ type CallerFilterFunc func(file string, fc *runtime.Func) bool
//
// Usage:
//
-//		cs := sysutil.CallersInfos(3, 2)
-//		for _, ci := range cs {
-//			fc := runtime.FuncForPC(pc)
-//			// maybe need check fc = nil
-//			fnName = fc.Name()
-//		}
+//	cs := sysutil.CallersInfos(3, 2)
+//	for _, ci := range cs {
+//		fc := runtime.FuncForPC(pc)
+//		// maybe need check fc = nil
+//		fnName = fc.Name()
+//	}
func CallersInfos(skip, num int, filters ...CallerFilterFunc) []*CallerInfo {
	filterLn := len(filters)
	callers := make([]*CallerInfo, 0, num)
diff --git a/vendor/github.com/gookit/goutil/x/termenv/detect_nonwin.go b/vendor/github.com/gookit/goutil/x/termenv/detect_nonwin.go
index 39f8e367873..94ca89cda3f 100644
--- a/vendor/github.com/gookit/goutil/x/termenv/detect_nonwin.go
+++ b/vendor/github.com/gookit/goutil/x/termenv/detect_nonwin.go
@@ -43,4 +43,4 @@ func detectSpecialTermColor(termVal string) (ColorLevel, bool) {

func syscallStdinFd() int {
	return syscall.Stdin
-}
\ No newline at end of file
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 515ece4f837..12695f2da16 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -738,7 +738,7 @@ github.com/google/uuid
## explicit; go 1.19
github.com/gookit/config/v2
github.com/gookit/config/v2/yaml
-# github.com/gookit/goutil v0.7.1
+# github.com/gookit/goutil v0.7.2
## explicit; go 1.19
github.com/gookit/goutil
github.com/gookit/goutil/arrutil