jack 2 tháng trước cách đây
commit
1501f69931
53 tập tin đã thay đổi với 1607 bổ sung0 xóa
  1. 1 0
      .gitattributes
  2. 19 0
      .gitignore
  3. 1 0
      Makefile
  4. 5 0
      README.MD
  5. 7 0
      app/user/Makefile
  6. 4 0
      app/user/README.MD
  7. 399 0
      app/user/api/account/v1/account.pb.go
  8. 198 0
      app/user/api/account/v1/account_grpc.pb.go
  9. 176 0
      app/user/api/pbentity/users.pb.go
  10. 10 0
      app/user/hack/config.yaml
  11. 20 0
      app/user/hack/hack-cli.mk
  12. 75 0
      app/user/hack/hack.mk
  13. 30 0
      app/user/internal/cmd/cmd.go
  14. 1 0
      app/user/internal/consts/consts.go
  15. 56 0
      app/user/internal/controller/account/account.go
  16. 0 0
      app/user/internal/dao/.gitkeep
  17. 89 0
      app/user/internal/dao/internal/users.go
  18. 22 0
      app/user/internal/dao/users.go
  19. 0 0
      app/user/internal/logic/.gitkeep
  20. 28 0
      app/user/internal/logic/account/account.go
  21. 0 0
      app/user/internal/model/.gitkeep
  22. 0 0
      app/user/internal/model/do/.gitkeep
  23. 21 0
      app/user/internal/model/do/users.go
  24. 0 0
      app/user/internal/model/entity/.gitkeep
  25. 19 0
      app/user/internal/model/entity/users.go
  26. 1 0
      app/user/internal/packed/packed.go
  27. 0 0
      app/user/internal/service/.gitkeep
  28. 24 0
      app/user/main.go
  29. 2 0
      app/user/manifest/config/etcd.yaml
  30. 21 0
      app/user/manifest/deploy/kustomize/base/deployment.yaml
  31. 8 0
      app/user/manifest/deploy/kustomize/base/kustomization.yaml
  32. 12 0
      app/user/manifest/deploy/kustomize/base/service.yaml
  33. 14 0
      app/user/manifest/deploy/kustomize/overlays/develop/configmap.yaml
  34. 10 0
      app/user/manifest/deploy/kustomize/overlays/develop/deployment.yaml
  35. 14 0
      app/user/manifest/deploy/kustomize/overlays/develop/kustomization.yaml
  36. 16 0
      app/user/manifest/docker/Dockerfile
  37. 8 0
      app/user/manifest/docker/docker.sh
  38. 0 0
      app/user/manifest/i18n/.gitkeep
  39. 0 0
      app/user/manifest/protobuf/.keep-if-necessary
  40. 40 0
      app/user/manifest/protobuf/account/v1/account.proto
  41. 20 0
      app/user/manifest/protobuf/pbentity/users.proto
  42. 0 0
      app/user/resource/public/html/.gitkeep
  43. 0 0
      app/user/resource/public/plugin/.gitkeep
  44. 0 0
      app/user/resource/public/resource/css/.gitkeep
  45. 0 0
      app/user/resource/public/resource/image/.gitkeep
  46. 0 0
      app/user/resource/public/resource/js/.gitkeep
  47. 0 0
      app/user/resource/template/.gitkeep
  48. 0 0
      app/user/utility/.gitkeep
  49. 44 0
      go.mod
  50. 98 0
      go.sum
  51. 19 0
      hack/hack-cli.mk
  52. 75 0
      hack/hack.mk
  53. 0 0
      utility/.gitkeep

+ 1 - 0
.gitattributes

@@ -0,0 +1 @@
+* linguist-language=GO

+ 19 - 0
.gitignore

@@ -0,0 +1,19 @@
+.buildpath
+.hgignore.swp
+.project
+.orig
+.swp
+.idea/
+.settings/
+.vscode/
+bin/
+**/.DS_Store
+gf
+main
+main.exe
+output/
+manifest/output/
+temp/
+temp.yaml
+bin
+**/config/config.yaml

+ 1 - 0
Makefile

@@ -0,0 +1 @@
+include hack/hack-cli.mk

+ 5 - 0
README.MD

@@ -0,0 +1,5 @@
+# GoFrame Template For MonoRepo
+
+Quick Start: 
+- https://goframe.org/pages/viewpage.action?pageId=1114399
+- https://goframe.org/pages/viewpage.action?pageId=87246764

+ 7 - 0
app/user/Makefile

@@ -0,0 +1,7 @@
+ROOT_DIR    = $(shell pwd)
+NAMESPACE   = "default"
+DEPLOY_NAME = "template-mono-app"
+DOCKER_NAME = "template-mono-app"
+
+include ./hack/hack-cli.mk
+include ./hack/hack.mk

+ 4 - 0
app/user/README.MD

@@ -0,0 +1,4 @@
+# GoFrame Template For SingleRepo
+
+Quick Start: 
+- https://goframe.org/quick

+ 399 - 0
app/user/api/account/v1/account.pb.go

@@ -0,0 +1,399 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.36.10
+// 	protoc        v3.21.11
+// source: account/v1/account.proto
+
+package v1
+
+import (
+	pbentity "proxima/app/user/api/pbentity"
+	reflect "reflect"
+	sync "sync"
+	unsafe "unsafe"
+
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+)
+
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type UserRegisterReq struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Username      string                 `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty" v:"required|min-length:2"` // v:required|min-length:2
+	Password      string                 `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty" v:"required|min-length:6"` // v:required|min-length:6
+	Email         string                 `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty" v:"required|email"`              // v:required|email
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *UserRegisterReq) Reset() {
+	*x = UserRegisterReq{}
+	mi := &file_account_v1_account_proto_msgTypes[0]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *UserRegisterReq) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UserRegisterReq) ProtoMessage() {}
+
+func (x *UserRegisterReq) ProtoReflect() protoreflect.Message {
+	mi := &file_account_v1_account_proto_msgTypes[0]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use UserRegisterReq.ProtoReflect.Descriptor instead.
+func (*UserRegisterReq) Descriptor() ([]byte, []int) {
+	return file_account_v1_account_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *UserRegisterReq) GetUsername() string {
+	if x != nil {
+		return x.Username
+	}
+	return ""
+}
+
+func (x *UserRegisterReq) GetPassword() string {
+	if x != nil {
+		return x.Password
+	}
+	return ""
+}
+
+func (x *UserRegisterReq) GetEmail() string {
+	if x != nil {
+		return x.Email
+	}
+	return ""
+}
+
+type UserRegisterRes struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Id            int32                  `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *UserRegisterRes) Reset() {
+	*x = UserRegisterRes{}
+	mi := &file_account_v1_account_proto_msgTypes[1]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *UserRegisterRes) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UserRegisterRes) ProtoMessage() {}
+
+func (x *UserRegisterRes) ProtoReflect() protoreflect.Message {
+	mi := &file_account_v1_account_proto_msgTypes[1]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use UserRegisterRes.ProtoReflect.Descriptor instead.
+func (*UserRegisterRes) Descriptor() ([]byte, []int) {
+	return file_account_v1_account_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *UserRegisterRes) GetId() int32 {
+	if x != nil {
+		return x.Id
+	}
+	return 0
+}
+
+type UserLoginReq struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Username      string                 `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty" v:"required|min-length:2"` // v:required|min-length:2
+	Password      string                 `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty" v:"required|min-length:6"` // v:required|min-length:6
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *UserLoginReq) Reset() {
+	*x = UserLoginReq{}
+	mi := &file_account_v1_account_proto_msgTypes[2]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *UserLoginReq) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UserLoginReq) ProtoMessage() {}
+
+func (x *UserLoginReq) ProtoReflect() protoreflect.Message {
+	mi := &file_account_v1_account_proto_msgTypes[2]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use UserLoginReq.ProtoReflect.Descriptor instead.
+func (*UserLoginReq) Descriptor() ([]byte, []int) {
+	return file_account_v1_account_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *UserLoginReq) GetUsername() string {
+	if x != nil {
+		return x.Username
+	}
+	return ""
+}
+
+func (x *UserLoginReq) GetPassword() string {
+	if x != nil {
+		return x.Password
+	}
+	return ""
+}
+
+type UserLoginRes struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Token         string                 `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *UserLoginRes) Reset() {
+	*x = UserLoginRes{}
+	mi := &file_account_v1_account_proto_msgTypes[3]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *UserLoginRes) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UserLoginRes) ProtoMessage() {}
+
+func (x *UserLoginRes) ProtoReflect() protoreflect.Message {
+	mi := &file_account_v1_account_proto_msgTypes[3]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use UserLoginRes.ProtoReflect.Descriptor instead.
+func (*UserLoginRes) Descriptor() ([]byte, []int) {
+	return file_account_v1_account_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *UserLoginRes) GetToken() string {
+	if x != nil {
+		return x.Token
+	}
+	return ""
+}
+
+type UserInfoReq struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Token         string                 `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty" v:"required"` // v:required
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *UserInfoReq) Reset() {
+	*x = UserInfoReq{}
+	mi := &file_account_v1_account_proto_msgTypes[4]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *UserInfoReq) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UserInfoReq) ProtoMessage() {}
+
+func (x *UserInfoReq) ProtoReflect() protoreflect.Message {
+	mi := &file_account_v1_account_proto_msgTypes[4]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use UserInfoReq.ProtoReflect.Descriptor instead.
+func (*UserInfoReq) Descriptor() ([]byte, []int) {
+	return file_account_v1_account_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *UserInfoReq) GetToken() string {
+	if x != nil {
+		return x.Token
+	}
+	return ""
+}
+
+type UserInfoRes struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	User          *pbentity.Users        `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *UserInfoRes) Reset() {
+	*x = UserInfoRes{}
+	mi := &file_account_v1_account_proto_msgTypes[5]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *UserInfoRes) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UserInfoRes) ProtoMessage() {}
+
+func (x *UserInfoRes) ProtoReflect() protoreflect.Message {
+	mi := &file_account_v1_account_proto_msgTypes[5]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use UserInfoRes.ProtoReflect.Descriptor instead.
+func (*UserInfoRes) Descriptor() ([]byte, []int) {
+	return file_account_v1_account_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *UserInfoRes) GetUser() *pbentity.Users {
+	if x != nil {
+		return x.User
+	}
+	return nil
+}
+
+var File_account_v1_account_proto protoreflect.FileDescriptor
+
+const file_account_v1_account_proto_rawDesc = "" +
+	"\n" +
+	"\x18account/v1/account.proto\x12\n" +
+	"account.v1\x1a\x14pbentity/users.proto\"_\n" +
+	"\x0fUserRegisterReq\x12\x1a\n" +
+	"\busername\x18\x01 \x01(\tR\busername\x12\x1a\n" +
+	"\bpassword\x18\x02 \x01(\tR\bpassword\x12\x14\n" +
+	"\x05email\x18\x03 \x01(\tR\x05email\"!\n" +
+	"\x0fUserRegisterRes\x12\x0e\n" +
+	"\x02id\x18\x01 \x01(\x05R\x02id\"F\n" +
+	"\fUserLoginReq\x12\x1a\n" +
+	"\busername\x18\x01 \x01(\tR\busername\x12\x1a\n" +
+	"\bpassword\x18\x02 \x01(\tR\bpassword\"$\n" +
+	"\fUserLoginRes\x12\x14\n" +
+	"\x05token\x18\x01 \x01(\tR\x05token\"#\n" +
+	"\vUserInfoReq\x12\x14\n" +
+	"\x05token\x18\x01 \x01(\tR\x05token\"2\n" +
+	"\vUserInfoRes\x12#\n" +
+	"\x04user\x18\x01 \x01(\v2\x0f.pbentity.UsersR\x04user2\xd8\x01\n" +
+	"\aAccount\x12J\n" +
+	"\fUserRegister\x12\x1b.account.v1.UserRegisterReq\x1a\x1b.account.v1.UserRegisterRes\"\x00\x12A\n" +
+	"\tUserLogin\x12\x18.account.v1.UserLoginReq\x1a\x18.account.v1.UserLoginRes\"\x00\x12>\n" +
+	"\bUserInfo\x12\x17.account.v1.UserInfoReq\x1a\x17.account.v1.UserInfoRes\"\x00B!Z\x1fproxima/app/user/api/account/v1b\x06proto3"
+
+var (
+	file_account_v1_account_proto_rawDescOnce sync.Once
+	file_account_v1_account_proto_rawDescData []byte
+)
+
+func file_account_v1_account_proto_rawDescGZIP() []byte {
+	file_account_v1_account_proto_rawDescOnce.Do(func() {
+		file_account_v1_account_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_account_v1_account_proto_rawDesc), len(file_account_v1_account_proto_rawDesc)))
+	})
+	return file_account_v1_account_proto_rawDescData
+}
+
+var file_account_v1_account_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
+var file_account_v1_account_proto_goTypes = []any{
+	(*UserRegisterReq)(nil), // 0: account.v1.UserRegisterReq
+	(*UserRegisterRes)(nil), // 1: account.v1.UserRegisterRes
+	(*UserLoginReq)(nil),    // 2: account.v1.UserLoginReq
+	(*UserLoginRes)(nil),    // 3: account.v1.UserLoginRes
+	(*UserInfoReq)(nil),     // 4: account.v1.UserInfoReq
+	(*UserInfoRes)(nil),     // 5: account.v1.UserInfoRes
+	(*pbentity.Users)(nil),  // 6: pbentity.Users
+}
+var file_account_v1_account_proto_depIdxs = []int32{
+	6, // 0: account.v1.UserInfoRes.user:type_name -> pbentity.Users
+	0, // 1: account.v1.Account.UserRegister:input_type -> account.v1.UserRegisterReq
+	2, // 2: account.v1.Account.UserLogin:input_type -> account.v1.UserLoginReq
+	4, // 3: account.v1.Account.UserInfo:input_type -> account.v1.UserInfoReq
+	1, // 4: account.v1.Account.UserRegister:output_type -> account.v1.UserRegisterRes
+	3, // 5: account.v1.Account.UserLogin:output_type -> account.v1.UserLoginRes
+	5, // 6: account.v1.Account.UserInfo:output_type -> account.v1.UserInfoRes
+	4, // [4:7] is the sub-list for method output_type
+	1, // [1:4] is the sub-list for method input_type
+	1, // [1:1] is the sub-list for extension type_name
+	1, // [1:1] is the sub-list for extension extendee
+	0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_account_v1_account_proto_init() }
+func file_account_v1_account_proto_init() {
+	if File_account_v1_account_proto != nil {
+		return
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_account_v1_account_proto_rawDesc), len(file_account_v1_account_proto_rawDesc)),
+			NumEnums:      0,
+			NumMessages:   6,
+			NumExtensions: 0,
+			NumServices:   1,
+		},
+		GoTypes:           file_account_v1_account_proto_goTypes,
+		DependencyIndexes: file_account_v1_account_proto_depIdxs,
+		MessageInfos:      file_account_v1_account_proto_msgTypes,
+	}.Build()
+	File_account_v1_account_proto = out.File
+	file_account_v1_account_proto_goTypes = nil
+	file_account_v1_account_proto_depIdxs = nil
+}

+ 198 - 0
app/user/api/account/v1/account_grpc.pb.go

@@ -0,0 +1,198 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.5.1
+// - protoc             v3.21.11
+// source: account/v1/account.proto
+
+package v1
+
+import (
+	context "context"
+
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.64.0 or later.
+const _ = grpc.SupportPackageIsVersion9
+
+const (
+	Account_UserRegister_FullMethodName = "/account.v1.Account/UserRegister"
+	Account_UserLogin_FullMethodName    = "/account.v1.Account/UserLogin"
+	Account_UserInfo_FullMethodName     = "/account.v1.Account/UserInfo"
+)
+
+// AccountClient is the client API for Account service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type AccountClient interface {
+	UserRegister(ctx context.Context, in *UserRegisterReq, opts ...grpc.CallOption) (*UserRegisterRes, error)
+	UserLogin(ctx context.Context, in *UserLoginReq, opts ...grpc.CallOption) (*UserLoginRes, error)
+	UserInfo(ctx context.Context, in *UserInfoReq, opts ...grpc.CallOption) (*UserInfoRes, error)
+}
+
+type accountClient struct {
+	cc grpc.ClientConnInterface
+}
+
+func NewAccountClient(cc grpc.ClientConnInterface) AccountClient {
+	return &accountClient{cc}
+}
+
+func (c *accountClient) UserRegister(ctx context.Context, in *UserRegisterReq, opts ...grpc.CallOption) (*UserRegisterRes, error) {
+	cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+	out := new(UserRegisterRes)
+	err := c.cc.Invoke(ctx, Account_UserRegister_FullMethodName, in, out, cOpts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *accountClient) UserLogin(ctx context.Context, in *UserLoginReq, opts ...grpc.CallOption) (*UserLoginRes, error) {
+	cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+	out := new(UserLoginRes)
+	err := c.cc.Invoke(ctx, Account_UserLogin_FullMethodName, in, out, cOpts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *accountClient) UserInfo(ctx context.Context, in *UserInfoReq, opts ...grpc.CallOption) (*UserInfoRes, error) {
+	cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+	out := new(UserInfoRes)
+	err := c.cc.Invoke(ctx, Account_UserInfo_FullMethodName, in, out, cOpts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// AccountServer is the server API for Account service.
+// All implementations must embed UnimplementedAccountServer
+// for forward compatibility.
+type AccountServer interface {
+	UserRegister(context.Context, *UserRegisterReq) (*UserRegisterRes, error)
+	UserLogin(context.Context, *UserLoginReq) (*UserLoginRes, error)
+	UserInfo(context.Context, *UserInfoReq) (*UserInfoRes, error)
+	mustEmbedUnimplementedAccountServer()
+}
+
+// UnimplementedAccountServer must be embedded to have
+// forward compatible implementations.
+//
+// NOTE: this should be embedded by value instead of pointer to avoid a nil
+// pointer dereference when methods are called.
+type UnimplementedAccountServer struct{}
+
+func (UnimplementedAccountServer) UserRegister(context.Context, *UserRegisterReq) (*UserRegisterRes, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method UserRegister not implemented")
+}
+func (UnimplementedAccountServer) UserLogin(context.Context, *UserLoginReq) (*UserLoginRes, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method UserLogin not implemented")
+}
+func (UnimplementedAccountServer) UserInfo(context.Context, *UserInfoReq) (*UserInfoRes, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method UserInfo not implemented")
+}
+func (UnimplementedAccountServer) mustEmbedUnimplementedAccountServer() {}
+func (UnimplementedAccountServer) testEmbeddedByValue()                 {}
+
+// UnsafeAccountServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to AccountServer will
+// result in compilation errors.
+type UnsafeAccountServer interface {
+	mustEmbedUnimplementedAccountServer()
+}
+
+func RegisterAccountServer(s grpc.ServiceRegistrar, srv AccountServer) {
+	// If the following call pancis, it indicates UnimplementedAccountServer was
+	// embedded by pointer and is nil.  This will cause panics if an
+	// unimplemented method is ever invoked, so we test this at initialization
+	// time to prevent it from happening at runtime later due to I/O.
+	if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
+		t.testEmbeddedByValue()
+	}
+	s.RegisterService(&Account_ServiceDesc, srv)
+}
+
+func _Account_UserRegister_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(UserRegisterReq)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(AccountServer).UserRegister(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: Account_UserRegister_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(AccountServer).UserRegister(ctx, req.(*UserRegisterReq))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Account_UserLogin_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(UserLoginReq)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(AccountServer).UserLogin(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: Account_UserLogin_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(AccountServer).UserLogin(ctx, req.(*UserLoginReq))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Account_UserInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(UserInfoReq)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(AccountServer).UserInfo(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: Account_UserInfo_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(AccountServer).UserInfo(ctx, req.(*UserInfoReq))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+// Account_ServiceDesc is the grpc.ServiceDesc for Account service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var Account_ServiceDesc = grpc.ServiceDesc{
+	ServiceName: "account.v1.Account",
+	HandlerType: (*AccountServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "UserRegister",
+			Handler:    _Account_UserRegister_Handler,
+		},
+		{
+			MethodName: "UserLogin",
+			Handler:    _Account_UserLogin_Handler,
+		},
+		{
+			MethodName: "UserInfo",
+			Handler:    _Account_UserInfo_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "account/v1/account.proto",
+}

+ 176 - 0
app/user/api/pbentity/users.pb.go

@@ -0,0 +1,176 @@
+// ==========================================================================
+// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.36.10
+// 	protoc        v3.21.11
+// source: pbentity/users.proto
+
+package pbentity
+
+import (
+	reflect "reflect"
+	sync "sync"
+	unsafe "unsafe"
+
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	timestamppb "google.golang.org/protobuf/types/known/timestamppb"
+)
+
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type Users struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Id            uint32                 `protobuf:"varint,1,opt,name=Id,proto3" json:"Id,omitempty"`              //
+	Username      string                 `protobuf:"bytes,2,opt,name=Username,proto3" json:"Username,omitempty"`   //
+	Password      string                 `protobuf:"bytes,3,opt,name=Password,proto3" json:"Password,omitempty"`   //
+	Email         string                 `protobuf:"bytes,4,opt,name=Email,proto3" json:"Email,omitempty"`         //
+	CreatedAt     *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=CreatedAt,proto3" json:"CreatedAt,omitempty"` //
+	UpdatedAt     *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=UpdatedAt,proto3" json:"UpdatedAt,omitempty"` //
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *Users) Reset() {
+	*x = Users{}
+	mi := &file_pbentity_users_proto_msgTypes[0]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *Users) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Users) ProtoMessage() {}
+
+func (x *Users) ProtoReflect() protoreflect.Message {
+	mi := &file_pbentity_users_proto_msgTypes[0]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use Users.ProtoReflect.Descriptor instead.
+func (*Users) Descriptor() ([]byte, []int) {
+	return file_pbentity_users_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Users) GetId() uint32 {
+	if x != nil {
+		return x.Id
+	}
+	return 0
+}
+
+func (x *Users) GetUsername() string {
+	if x != nil {
+		return x.Username
+	}
+	return ""
+}
+
+func (x *Users) GetPassword() string {
+	if x != nil {
+		return x.Password
+	}
+	return ""
+}
+
+func (x *Users) GetEmail() string {
+	if x != nil {
+		return x.Email
+	}
+	return ""
+}
+
+func (x *Users) GetCreatedAt() *timestamppb.Timestamp {
+	if x != nil {
+		return x.CreatedAt
+	}
+	return nil
+}
+
+func (x *Users) GetUpdatedAt() *timestamppb.Timestamp {
+	if x != nil {
+		return x.UpdatedAt
+	}
+	return nil
+}
+
+var File_pbentity_users_proto protoreflect.FileDescriptor
+
+const file_pbentity_users_proto_rawDesc = "" +
+	"\n" +
+	"\x14pbentity/users.proto\x12\bpbentity\x1a\x1fgoogle/protobuf/timestamp.proto\"\xd9\x01\n" +
+	"\x05Users\x12\x0e\n" +
+	"\x02Id\x18\x01 \x01(\rR\x02Id\x12\x1a\n" +
+	"\bUsername\x18\x02 \x01(\tR\bUsername\x12\x1a\n" +
+	"\bPassword\x18\x03 \x01(\tR\bPassword\x12\x14\n" +
+	"\x05Email\x18\x04 \x01(\tR\x05Email\x128\n" +
+	"\tCreatedAt\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\tCreatedAt\x128\n" +
+	"\tUpdatedAt\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\tUpdatedAtB\x1fZ\x1dproxima/app/user/api/pbentityb\x06proto3"
+
+var (
+	file_pbentity_users_proto_rawDescOnce sync.Once
+	file_pbentity_users_proto_rawDescData []byte
+)
+
+func file_pbentity_users_proto_rawDescGZIP() []byte {
+	file_pbentity_users_proto_rawDescOnce.Do(func() {
+		file_pbentity_users_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_pbentity_users_proto_rawDesc), len(file_pbentity_users_proto_rawDesc)))
+	})
+	return file_pbentity_users_proto_rawDescData
+}
+
+var file_pbentity_users_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_pbentity_users_proto_goTypes = []any{
+	(*Users)(nil),                 // 0: pbentity.Users
+	(*timestamppb.Timestamp)(nil), // 1: google.protobuf.Timestamp
+}
+var file_pbentity_users_proto_depIdxs = []int32{
+	1, // 0: pbentity.Users.CreatedAt:type_name -> google.protobuf.Timestamp
+	1, // 1: pbentity.Users.UpdatedAt:type_name -> google.protobuf.Timestamp
+	2, // [2:2] is the sub-list for method output_type
+	2, // [2:2] is the sub-list for method input_type
+	2, // [2:2] is the sub-list for extension type_name
+	2, // [2:2] is the sub-list for extension extendee
+	0, // [0:2] is the sub-list for field type_name
+}
+
+func init() { file_pbentity_users_proto_init() }
+func file_pbentity_users_proto_init() {
+	if File_pbentity_users_proto != nil {
+		return
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_pbentity_users_proto_rawDesc), len(file_pbentity_users_proto_rawDesc)),
+			NumEnums:      0,
+			NumMessages:   1,
+			NumExtensions: 0,
+			NumServices:   0,
+		},
+		GoTypes:           file_pbentity_users_proto_goTypes,
+		DependencyIndexes: file_pbentity_users_proto_depIdxs,
+		MessageInfos:      file_pbentity_users_proto_msgTypes,
+	}.Build()
+	File_pbentity_users_proto = out.File
+	file_pbentity_users_proto_goTypes = nil
+	file_pbentity_users_proto_depIdxs = nil
+}

+ 10 - 0
app/user/hack/config.yaml

@@ -0,0 +1,10 @@
+
+# CLI tool, only in development environment.
+# https://goframe.org/docs/cli
+gfcli:
+  gen:
+    dao:
+      - link: "mysql:root:aaaAAA111@tcp(127.0.0.1:3306)/user"
+        descriptionTag: true
+    pbentity:
+      - link: "mysql:root:aaaAAA111@tcp(127.0.0.1:3306)/user"

+ 20 - 0
app/user/hack/hack-cli.mk

@@ -0,0 +1,20 @@
+
+# Install/Update to the latest CLI tool.
+.PHONY: cli
+cli:
+	@set -e; \
+	wget -O gf \
+	https://github.com/gogf/gf/releases/latest/download/gf_$(shell go env GOOS)_$(shell go env GOARCH) && \
+	chmod +x gf && \
+	./gf install -y && \
+	rm ./gf
+
+
+# Check and install CLI tool.
+.PHONY: cli.install
+cli.install:
+	@set -e; \
+	gf -v > /dev/null 2>&1 || if [[ "$?" -ne "0" ]]; then \
+  		echo "GoFame CLI is not installed, start proceeding auto installation..."; \
+		make cli; \
+	fi;

+ 75 - 0
app/user/hack/hack.mk

@@ -0,0 +1,75 @@
+.DEFAULT_GOAL := build
+
+# Update GoFrame and its CLI to latest stable version.
+.PHONY: up
+up: cli.install
+	@gf up -a
+
+# Build binary using configuration from hack/config.yaml.
+.PHONY: build
+build: cli.install
+	@gf build -ew
+
+# Parse api and generate controller/sdk.
+.PHONY: ctrl
+ctrl: cli.install
+	@gf gen ctrl
+
+# Generate Go files for DAO/DO/Entity.
+.PHONY: dao
+dao: cli.install
+	@gf gen dao
+
+# Parse current project go files and generate enums go file.
+.PHONY: enums
+enums: cli.install
+	@gf gen enums
+
+# Generate Go files for Service.
+.PHONY: service
+service: cli.install
+	@gf gen service
+
+
+# Build docker image.
+.PHONY: image
+image: cli.install
+	$(eval _TAG  = $(shell git rev-parse --short HEAD))
+ifneq (, $(shell git status --porcelain 2>/dev/null))
+	$(eval _TAG  = $(_TAG).dirty)
+endif
+	$(eval _TAG  = $(if ${TAG},  ${TAG}, $(_TAG)))
+	$(eval _PUSH = $(if ${PUSH}, ${PUSH}, ))
+	@gf docker ${_PUSH} -tn $(DOCKER_NAME):${_TAG};
+
+
+# Build docker image and automatically push to docker repo.
+.PHONY: image.push
+image.push: cli.install
+	@make image PUSH=-p;
+
+
+# Deploy image and yaml to current kubectl environment.
+.PHONY: deploy
+deploy: cli.install
+	$(eval _TAG = $(if ${TAG},  ${TAG}, develop))
+
+	@set -e; \
+	mkdir -p $(ROOT_DIR)/temp/kustomize;\
+	cd $(ROOT_DIR)/manifest/deploy/kustomize/overlays/${_ENV};\
+	kustomize build > $(ROOT_DIR)/temp/kustomize.yaml;\
+	kubectl   apply -f $(ROOT_DIR)/temp/kustomize.yaml; \
+	if [ $(DEPLOY_NAME) != "" ]; then \
+		kubectl patch -n $(NAMESPACE) deployment/$(DEPLOY_NAME) -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"$(shell date +%s)\"}}}}}"; \
+	fi;
+
+
+# Parsing protobuf files and generating go files.
+.PHONY: pb
+pb: cli.install
+	@gf gen pb
+
+# Generate protobuf files for database tables.
+.PHONY: pbentity
+pbentity: cli.install
+	@gf gen pbentity

+ 30 - 0
app/user/internal/cmd/cmd.go

@@ -0,0 +1,30 @@
+package cmd
+
+import (
+	"context"
+
+	"github.com/gogf/gf/contrib/rpc/grpcx/v2"
+	"github.com/gogf/gf/v2/os/gcmd"
+	"google.golang.org/grpc"
+	"proxima/app/user/internal/controller/account"
+)
+
+var (
+	Main = gcmd.Command{
+		Name:  "main",
+		Usage: "main",
+		Brief: "user grpc service",
+		Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
+			c := grpcx.Server.NewConfig()
+			c.Options = append(c.Options, []grpc.ServerOption{
+				grpcx.Server.ChainUnary(
+					grpcx.Server.UnaryValidate,
+				)}...,
+			)
+			s := grpcx.Server.New(c)
+			account.Register(s)
+			s.Run()
+			return nil
+		},
+	}
+)

+ 1 - 0
app/user/internal/consts/consts.go

@@ -0,0 +1 @@
+package consts

+ 56 - 0
app/user/internal/controller/account/account.go

@@ -0,0 +1,56 @@
+package account
+
+import (
+	"context"
+
+	"github.com/gogf/gf/contrib/rpc/grpcx/v2"
+	"google.golang.org/protobuf/types/known/timestamppb"
+	v1 "proxima/app/user/api/account/v1"
+	"proxima/app/user/api/pbentity"
+	"proxima/app/user/internal/logic/account"
+)
+
+type Controller struct {
+	v1.UnimplementedAccountServer
+}
+
+func Register(s *grpcx.GrpcServer) {
+	v1.RegisterAccountServer(s.Server, &Controller{})
+}
+
+func (*Controller) UserRegister(ctx context.Context, req *v1.UserRegisterReq) (res *v1.UserRegisterRes, err error) {
+	id, err := account.Register(ctx)
+	if err != nil {
+		return nil, err
+	}
+	return &v1.UserRegisterRes{
+		Id: int32(id),
+	}, nil
+}
+
+func (*Controller) UserLogin(ctx context.Context, req *v1.UserLoginReq) (res *v1.UserLoginRes, err error) {
+	token, err := account.Login(ctx)
+	if err != nil {
+		return nil, err
+	}
+	return &v1.UserLoginRes{
+		Token: token,
+	}, nil
+}
+
+func (*Controller) UserInfo(ctx context.Context, req *v1.UserInfoReq) (res *v1.UserInfoRes, err error) {
+	data, err := account.Info(ctx, req.Token)
+	if err != nil {
+		return nil, err
+	}
+	return &v1.UserInfoRes{
+		User: &pbentity.Users{
+			Id:        uint32(data.Id),
+			Username:  data.Username,
+			Password:  data.Password,
+			Email:     data.Email,
+			CreatedAt: timestamppb.New(data.CreatedAt.Time),
+			UpdatedAt: timestamppb.New(data.UpdatedAt.Time),
+		},
+	}, nil
+}

+ 0 - 0
app/user/internal/dao/.gitkeep


+ 89 - 0
app/user/internal/dao/internal/users.go

@@ -0,0 +1,89 @@
+// ==========================================================================
+// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package internal
+
+import (
+	"context"
+
+	"github.com/gogf/gf/v2/database/gdb"
+	"github.com/gogf/gf/v2/frame/g"
+)
+
+// UsersDao is the data access object for the table users.
+type UsersDao struct {
+	table    string             // table is the underlying table name of the DAO.
+	group    string             // group is the database configuration group name of the current DAO.
+	columns  UsersColumns       // columns contains all the column names of Table for convenient usage.
+	handlers []gdb.ModelHandler // handlers for customized model modification.
+}
+
+// UsersColumns defines and stores column names for the table users.
+type UsersColumns struct {
+	Id        string //
+	Username  string //
+	Password  string //
+	Email     string //
+	CreatedAt string //
+	UpdatedAt string //
+}
+
+// usersColumns holds the columns for the table users.
+var usersColumns = UsersColumns{
+	Id:        "id",
+	Username:  "username",
+	Password:  "password",
+	Email:     "email",
+	CreatedAt: "created_at",
+	UpdatedAt: "updated_at",
+}
+
+// NewUsersDao creates and returns a new DAO object for table data access.
+func NewUsersDao(handlers ...gdb.ModelHandler) *UsersDao {
+	return &UsersDao{
+		group:    "default",
+		table:    "users",
+		columns:  usersColumns,
+		handlers: handlers,
+	}
+}
+
+// DB retrieves and returns the underlying raw database management object of the current DAO.
+func (dao *UsersDao) DB() gdb.DB {
+	return g.DB(dao.group)
+}
+
+// Table returns the table name of the current DAO.
+func (dao *UsersDao) Table() string {
+	return dao.table
+}
+
+// Columns returns all column names of the current DAO.
+func (dao *UsersDao) Columns() UsersColumns {
+	return dao.columns
+}
+
+// Group returns the database configuration group name of the current DAO.
+func (dao *UsersDao) Group() string {
+	return dao.group
+}
+
+// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation.
+func (dao *UsersDao) Ctx(ctx context.Context) *gdb.Model {
+	model := dao.DB().Model(dao.table)
+	for _, handler := range dao.handlers {
+		model = handler(model)
+	}
+	return model.Safe().Ctx(ctx)
+}
+
+// Transaction wraps the transaction logic using function f.
+// It rolls back the transaction and returns the error if function f returns a non-nil error.
+// It commits the transaction and returns nil if function f returns nil.
+//
+// Note: Do not commit or roll back the transaction in function f,
+// as it is automatically handled by this function.
+func (dao *UsersDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
+	return dao.Ctx(ctx).Transaction(ctx, f)
+}

+ 22 - 0
app/user/internal/dao/users.go

@@ -0,0 +1,22 @@
+// =================================================================================
+// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed.
+// =================================================================================
+
+package dao
+
+import (
+	"proxima/app/user/internal/dao/internal"
+)
+
+// usersDao is the data access object for the table users.
+// You can define custom methods on it to extend its functionality as needed.
+type usersDao struct {
+	*internal.UsersDao
+}
+
+var (
+	// Users is a globally accessible object for table users operations.
+	Users = usersDao{internal.NewUsersDao()}
+)
+
+// Add your custom methods and functionality below.

+ 0 - 0
app/user/internal/logic/.gitkeep


+ 28 - 0
app/user/internal/logic/account/account.go

@@ -0,0 +1,28 @@
+package account
+
+import (
+	"context"
+
+	"github.com/gogf/gf/v2/os/gtime"
+	"proxima/app/user/internal/model/entity"
+)
+
+func Register(ctx context.Context) (id int, err error) {
+	return 1, nil
+}
+
+func Login(ctx context.Context) (token string, err error) {
+	return "I am token", nil
+}
+
+// Info get user info
+func Info(ctx context.Context, token string) (user *entity.Users, err error) {
+	return &entity.Users{
+		Id:        1,
+		Username:  "oldme",
+		Password:  "123456",
+		Email:     "tyyn1022@gmail.com",
+		CreatedAt: gtime.New("2024-12-05 22:00:00"),
+		UpdatedAt: gtime.New("2024-12-05 22:00:00"),
+	}, nil
+}

+ 0 - 0
app/user/internal/model/.gitkeep


+ 0 - 0
app/user/internal/model/do/.gitkeep


+ 21 - 0
app/user/internal/model/do/users.go

@@ -0,0 +1,21 @@
+// =================================================================================
+// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package do
+
+import (
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/os/gtime"
+)
+
+// Users is the golang structure of table users for DAO operations like Where/Data.
+type Users struct {
+	g.Meta    `orm:"table:users, do:true"`
+	Id        any         //
+	Username  any         //
+	Password  any         //
+	Email     any         //
+	CreatedAt *gtime.Time //
+	UpdatedAt *gtime.Time //
+}

+ 0 - 0
app/user/internal/model/entity/.gitkeep


+ 19 - 0
app/user/internal/model/entity/users.go

@@ -0,0 +1,19 @@
+// =================================================================================
+// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package entity
+
+import (
+	"github.com/gogf/gf/v2/os/gtime"
+)
+
+// Users is the golang structure for table users.
+type Users struct {
+	Id        uint        `json:"id"        orm:"id"         description:""` //
+	Username  string      `json:"username"  orm:"username"   description:""` //
+	Password  string      `json:"password"  orm:"password"   description:""` //
+	Email     string      `json:"email"     orm:"email"      description:""` //
+	CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:""` //
+	UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:""` //
+}

+ 1 - 0
app/user/internal/packed/packed.go

@@ -0,0 +1 @@
+package packed

+ 0 - 0
app/user/internal/service/.gitkeep


+ 24 - 0
app/user/main.go

@@ -0,0 +1,24 @@
+package main
+
+import (
+	_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
+	"github.com/gogf/gf/contrib/rpc/grpcx/v2"
+	"github.com/gogf/gf/v2/frame/g"
+
+	"github.com/gogf/gf/v2/os/gctx"
+
+	"proxima/app/user/internal/cmd"
+)
+
+func main() {
+	var ctx = gctx.New()
+	conf, err := g.Cfg("etcd").Get(ctx, "etcd.address")
+	if err != nil {
+		panic(err)
+	}
+
+	var address = conf.String()
+	grpcx.Resolver.Register(etcd.New(address))
+
+	cmd.Main.Run(ctx)
+}

+ 2 - 0
app/user/manifest/config/etcd.yaml

@@ -0,0 +1,2 @@
+etcd:
+  address: "127.0.0.1:2379"

+ 21 - 0
app/user/manifest/deploy/kustomize/base/deployment.yaml

@@ -0,0 +1,21 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: template-mono-app
+  labels:
+    app: template-mono-app
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: template-mono-app
+  template:
+    metadata:
+      labels:
+        app: template-mono-app
+    spec:
+      containers:
+        - name : main
+          image: template-mono-app
+          imagePullPolicy: Always
+

+ 8 - 0
app/user/manifest/deploy/kustomize/base/kustomization.yaml

@@ -0,0 +1,8 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+- deployment.yaml
+- service.yaml
+
+
+

+ 12 - 0
app/user/manifest/deploy/kustomize/base/service.yaml

@@ -0,0 +1,12 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: template-mono-app
+spec:
+  ports:
+  - port: 80
+    protocol: TCP
+    targetPort: 8000
+  selector:
+    app: template-mono-app
+

+ 14 - 0
app/user/manifest/deploy/kustomize/overlays/develop/configmap.yaml

@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: template-mono-app-configmap
+data:
+  config.yaml: |
+    server:
+      address:     ":8000"
+      openapiPath: "/api.json"
+      swaggerPath: "/swagger"
+
+    logger:
+      level : "all"
+      stdout: true

+ 10 - 0
app/user/manifest/deploy/kustomize/overlays/develop/deployment.yaml

@@ -0,0 +1,10 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: template-mono-app
+spec:
+  template:
+    spec:
+      containers:
+        - name : main
+          image: template-mono-app:develop

+ 14 - 0
app/user/manifest/deploy/kustomize/overlays/develop/kustomization.yaml

@@ -0,0 +1,14 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+
+resources:
+- ../../base
+- configmap.yaml
+
+patchesStrategicMerge:
+- deployment.yaml
+
+namespace: default
+
+
+

+ 16 - 0
app/user/manifest/docker/Dockerfile

@@ -0,0 +1,16 @@
+FROM loads/alpine:3.8
+
+###############################################################################
+#                                INSTALLATION
+###############################################################################
+
+ENV WORKDIR                 /app
+ADD resource                $WORKDIR/
+ADD ./temp/linux_amd64/main $WORKDIR/main
+RUN chmod +x $WORKDIR/main
+
+###############################################################################
+#                                   START
+###############################################################################
+WORKDIR $WORKDIR
+CMD ./main

+ 8 - 0
app/user/manifest/docker/docker.sh

@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# This shell is executed before docker build.
+
+
+
+
+

+ 0 - 0
app/user/manifest/i18n/.gitkeep


+ 0 - 0
app/user/manifest/protobuf/.keep-if-necessary


+ 40 - 0
app/user/manifest/protobuf/account/v1/account.proto

@@ -0,0 +1,40 @@
+syntax = "proto3";
+
+package account.v1;
+
+option go_package = "proxima/app/user/api/account/v1";
+
+import "pbentity/users.proto";
+
+service Account{
+  rpc UserRegister(UserRegisterReq) returns (UserRegisterRes) {}
+  rpc UserLogin(UserLoginReq) returns (UserLoginRes) {}
+  rpc UserInfo(UserInfoReq) returns (UserInfoRes) {}
+}
+
+message UserRegisterReq {
+  string username = 1; // v:required|min-length:2
+  string password = 2; // v:required|min-length:6
+  string email = 3; // v:required|email
+}
+
+message UserRegisterRes {
+  int32 id = 1;
+}
+
+message UserLoginReq {
+  string username = 1; // v:required|min-length:2
+  string password = 2; // v:required|min-length:6
+}
+
+message UserLoginRes {
+  string token = 1;
+}
+
+message UserInfoReq {
+  string token = 1; // v:required
+}
+
+message UserInfoRes {
+  pbentity.Users user = 1;
+}

+ 20 - 0
app/user/manifest/protobuf/pbentity/users.proto

@@ -0,0 +1,20 @@
+// ==========================================================================
+// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+syntax = "proto3";
+
+package pbentity;
+
+option go_package = "proxima/app/user/api/pbentity";
+
+import "google/protobuf/timestamp.proto";
+
+message Users {
+    uint32                    Id        = 1; //
+    string                    Username  = 2; //
+    string                    Password  = 3; //
+    string                    Email     = 4; //
+    google.protobuf.Timestamp CreatedAt = 5; //
+    google.protobuf.Timestamp UpdatedAt = 6; //
+}

+ 0 - 0
app/user/resource/public/html/.gitkeep


+ 0 - 0
app/user/resource/public/plugin/.gitkeep


+ 0 - 0
app/user/resource/public/resource/css/.gitkeep


+ 0 - 0
app/user/resource/public/resource/image/.gitkeep


+ 0 - 0
app/user/resource/public/resource/js/.gitkeep


+ 0 - 0
app/user/resource/template/.gitkeep


+ 0 - 0
app/user/utility/.gitkeep


+ 44 - 0
go.mod

@@ -0,0 +1,44 @@
+module proxima
+
+go 1.24.0
+
+require (
+	github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.4
+	github.com/gogf/gf/contrib/rpc/grpcx/v2 v2.9.4
+	github.com/gogf/gf/v2 v2.9.4
+	google.golang.org/grpc v1.76.0
+	google.golang.org/protobuf v1.36.10
+)
+
+require (
+	github.com/BurntSushi/toml v1.5.0 // indirect
+	github.com/clbanning/mxj/v2 v2.7.0 // indirect
+	github.com/emirpasic/gods v1.18.1 // indirect
+	github.com/fatih/color v1.18.0 // indirect
+	github.com/fsnotify/fsnotify v1.9.0 // indirect
+	github.com/go-logr/logr v1.4.3 // indirect
+	github.com/go-logr/stdr v1.2.2 // indirect
+	github.com/go-sql-driver/mysql v1.7.1 // indirect
+	github.com/gogf/gf/contrib/registry/file/v2 v2.9.4 // indirect
+	github.com/google/uuid v1.6.0 // indirect
+	github.com/gorilla/websocket v1.5.3 // indirect
+	github.com/grokify/html-strip-tags-go v0.1.0 // indirect
+	github.com/magiconair/properties v1.8.10 // indirect
+	github.com/mattn/go-colorable v0.1.14 // indirect
+	github.com/mattn/go-isatty v0.0.20 // indirect
+	github.com/mattn/go-runewidth v0.0.16 // indirect
+	github.com/olekukonko/errors v1.1.0 // indirect
+	github.com/olekukonko/ll v0.0.9 // indirect
+	github.com/olekukonko/tablewriter v1.1.0 // indirect
+	github.com/rivo/uniseg v0.4.7 // indirect
+	go.opentelemetry.io/auto/sdk v1.1.0 // indirect
+	go.opentelemetry.io/otel v1.38.0 // indirect
+	go.opentelemetry.io/otel/metric v1.38.0 // indirect
+	go.opentelemetry.io/otel/sdk v1.38.0 // indirect
+	go.opentelemetry.io/otel/trace v1.38.0 // indirect
+	golang.org/x/net v0.43.0 // indirect
+	golang.org/x/sys v0.35.0 // indirect
+	golang.org/x/text v0.28.0 // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+)

+ 98 - 0
go.sum

@@ -0,0 +1,98 @@
+github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
+github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
+github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
+github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
+github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
+github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
+github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
+github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
+github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
+github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
+github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.4 h1:ntAPahCjQwQ79CC6tI67QDgj17NTWp+lMd1SaL2jJhs=
+github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.4/go.mod h1:/350+9clTW5ktUvF+hePMN9yDknB2ipslqcx3Y2rLDQ=
+github.com/gogf/gf/contrib/registry/file/v2 v2.9.4 h1:Y6L1j2xibCF3GE0JBFqbkTf1pF1Lg+t/jCuPdciw7L4=
+github.com/gogf/gf/contrib/registry/file/v2 v2.9.4/go.mod h1:SS7jhiJ50/2l4Y47KA7qjEEddjbQEhOEW67SAfRLdJ8=
+github.com/gogf/gf/contrib/rpc/grpcx/v2 v2.9.4 h1:8+I5vzrPRXZVtq3s/Y6cgsPRh3IKSJsxEp8s+DyCa2I=
+github.com/gogf/gf/contrib/rpc/grpcx/v2 v2.9.4/go.mod h1:RMuVphL+vBvhZXmbgVTOgtn3n5dWPDWYwE6vHhil4DA=
+github.com/gogf/gf/v2 v2.9.4 h1:6vleEWypot9WBPncP2GjbpgAUeG6Mzb1YESb9nPMkjY=
+github.com/gogf/gf/v2 v2.9.4/go.mod h1:Ukl+5HUH9S7puBmNLR4L1zUqeRwi0nrW4OigOknEztU=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
+github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4=
+github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
+github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
+github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
+github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
+github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM=
+github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
+github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI=
+github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g=
+github.com/olekukonko/tablewriter v1.1.0 h1:N0LHrshF4T39KvI96fn6GT8HEjXRXYNDrDjKFDB7RIY=
+github.com/olekukonko/tablewriter v1.1.0/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
+github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
+github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
+github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
+github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
+github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
+go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
+go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
+go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
+go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
+go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
+go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
+go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
+go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
+go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
+go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
+go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
+go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
+golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
+golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
+golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
+gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
+gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b h1:zPKJod4w6F1+nRGDI9ubnXYhU9NSWoFAijkHkUXeTK8=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
+google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
+google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
+google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
+google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

+ 19 - 0
hack/hack-cli.mk

@@ -0,0 +1,19 @@
+
+# Install/Update to the latest CLI tool.
+.PHONY: cli
+cli:
+	@set -e; \
+	wget -O gf https://github.com/gogf/gf/releases/latest/download/gf_$(shell go env GOOS)_$(shell go env GOARCH) && \
+	chmod +x gf && \
+	./gf install -y && \
+	rm ./gf
+
+
+# Check and install CLI tool.
+.PHONY: cli.install
+cli.install:
+	@set -e; \
+	gf -v > /dev/null 2>&1 || if [[ "$?" -ne "0" ]]; then \
+  		echo "GoFame CLI is not installed, start proceeding auto installation..."; \
+		make cli; \
+	fi;

+ 75 - 0
hack/hack.mk

@@ -0,0 +1,75 @@
+include ../../hack/hack-cli.mk
+
+# Update GoFrame and its CLI to latest stable version.
+.PHONY: up
+up: cli.install
+	@gf up -a
+
+# Build binary using configuration from hack/config.yaml.
+.PHONY: build
+build: cli.install
+	@gf build -ew
+
+# Parse api and generate controller/sdk.
+.PHONY: ctrl
+ctrl: cli.install
+	@gf gen ctrl
+
+# Generate Go files for DAO/DO/Entity.
+.PHONY: dao
+dao: cli.install
+	@gf gen dao
+
+# Parse current project go files and generate enums go file.
+.PHONY: enums
+enums: cli.install
+	@gf gen enums
+
+# Generate Go files for Service.
+.PHONY: service
+service: cli.install
+	@gf gen service
+
+
+# Build docker image.
+.PHONY: image
+image: cli.install
+	$(eval _TAG  = $(shell git describe --dirty --always --tags --abbrev=8 --match 'v*' | sed 's/-/./2' | sed 's/-/./2'))
+ifneq (, $(shell git status --porcelain 2>/dev/null))
+	$(eval _TAG  = $(_TAG).dirty)
+endif
+	$(eval _TAG  = $(if ${TAG},  ${TAG}, $(_TAG)))
+	$(eval _PUSH = $(if ${PUSH}, ${PUSH}, ))
+	@gf docker ${_PUSH} -tn $(DOCKER_NAME):${_TAG};
+
+
+# Build docker image and automatically push to docker repo.
+.PHONY: image.push
+image.push:
+	@make image PUSH=-p;
+
+
+# Deploy image and yaml to current kubectl environment.
+.PHONY: deploy
+deploy:
+	$(eval _TAG = $(if ${TAG},  ${TAG}, develop))
+
+	@set -e; \
+	mkdir -p $(ROOT_DIR)/temp/kustomize;\
+	cd $(ROOT_DIR)/manifest/deploy/kustomize/overlays/${_ENV};\
+	kustomize build > $(ROOT_DIR)/temp/kustomize.yaml;\
+	kubectl   apply -f $(ROOT_DIR)/temp/kustomize.yaml; \
+	if [ $(DEPLOY_NAME) != "" ]; then \
+		kubectl   patch -n $(NAMESPACE) deployment/$(DEPLOY_NAME) -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"$(shell date +%s)\"}}}}}"; \
+	fi;
+
+
+# Parsing protobuf files and generating go files.
+.PHONY: pb
+pb: cli.install
+	@gf gen pb
+
+# Generate protobuf files for database tables.
+.PHONY: pbentity
+pbentity: cli.install
+	@gf gen pbentity

+ 0 - 0
utility/.gitkeep